summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOz Linden <oz@lindenlab.com>2011-01-05 17:54:12 -0500
committerOz Linden <oz@lindenlab.com>2011-01-05 17:54:12 -0500
commit1034db639462d95e54e9bf9e4d63500b745bb0a2 (patch)
tree68b010fb3f9f2c4b67e59187d125090b1c69d72f
parent0eb491417e8479516b07cc9237242b60d36d10f5 (diff)
parenteb0b8ab3ea19617a52881191bab21bfedcc5696d (diff)
merge changes for storm-806
-rwxr-xr-xbuild.sh3
-rw-r--r--doc/contributions.txt21
-rw-r--r--indra/cmake/00-Common.cmake27
-rw-r--r--indra/cmake/BerkeleyDB.cmake7
-rw-r--r--indra/cmake/CMakeLists.txt1
-rw-r--r--indra/cmake/FindJsonCpp.cmake5
-rw-r--r--indra/cmake/FindLLQtWebkit.cmake62
-rw-r--r--indra/cmake/FindNDOF.cmake39
-rw-r--r--indra/cmake/FindTut.cmake7
-rw-r--r--indra/cmake/FindZLIB.cmake46
-rw-r--r--indra/cmake/LLAddBuildTest.cmake3
-rw-r--r--indra/cmake/LLCommon.cmake9
-rw-r--r--indra/cmake/LLPlugin.cmake8
-rw-r--r--indra/cmake/NDOF.cmake34
-rw-r--r--indra/cmake/Tut.cmake1
-rw-r--r--indra/cmake/WebKitLibPlugin.cmake25
-rw-r--r--indra/lib/python/indra/util/test_win32_manifest.py24
-rw-r--r--indra/llcommon/llapr.cpp22
-rw-r--r--indra/llcommon/llapr.h5
-rw-r--r--indra/llcommon/llevents.cpp4
-rw-r--r--indra/llimage/CMakeLists.txt13
-rw-r--r--indra/llimage/tests/llimageworker_test.cpp18
-rw-r--r--indra/llimagej2coj/llimagej2coj.cpp6
-rw-r--r--indra/llimagej2coj/llimagej2coj.h6
-rw-r--r--indra/llkdu/CMakeLists.txt10
-rw-r--r--indra/llkdu/llimagej2ckdu.cpp13
-rw-r--r--indra/llkdu/llimagej2ckdu.h5
-rw-r--r--indra/llkdu/tests/llimagej2ckdu_test.cpp248
-rw-r--r--indra/llmath/tests/m3math_test.cpp1
-rw-r--r--indra/llplugin/CMakeLists.txt1
-rw-r--r--indra/llplugin/llpluginclassmedia.cpp57
-rw-r--r--indra/llplugin/llpluginclassmedia.h18
-rw-r--r--indra/llplugin/llpluginclassmediaowner.h6
-rw-r--r--indra/llui/CMakeLists.txt2
-rw-r--r--indra/llui/llfloater.cpp4
-rw-r--r--indra/llui/lllayoutstack.cpp54
-rw-r--r--indra/llui/lllayoutstack.h23
-rw-r--r--indra/llui/lllineeditor.cpp3
-rw-r--r--indra/llui/lllineeditor.h3
-rw-r--r--indra/llui/llnotifications.cpp11
-rw-r--r--indra/llui/llnotifications.h1
-rw-r--r--indra/llui/llnotificationtemplate.h14
-rw-r--r--indra/llui/lluictrl.cpp2
-rw-r--r--indra/llui/llview.h9
-rw-r--r--indra/llui/llwindowshade.cpp328
-rw-r--r--indra/llui/llwindowshade.h69
-rw-r--r--indra/llwindow/CMakeLists.txt5
-rw-r--r--indra/media_plugins/example/media_plugin_example.cpp733
-rw-r--r--indra/media_plugins/webkit/CMakeLists.txt1
-rw-r--r--indra/media_plugins/webkit/media_plugin_webkit.cpp75
-rw-r--r--indra/newview/CMakeLists.txt46
-rw-r--r--indra/newview/app_settings/lindenlab.pem27
-rw-r--r--indra/newview/app_settings/settings.xml87
-rw-r--r--indra/newview/app_settings/shaders/shader_hierarchy.txt (renamed from indra/newview/app_settings/shaders/shader_heirarchy.txt)0
-rw-r--r--indra/newview/featuretable.txt2
-rw-r--r--indra/newview/featuretable_linux.txt2
-rw-r--r--indra/newview/featuretable_mac.txt2
-rw-r--r--indra/newview/featuretable_xp.txt2
-rw-r--r--indra/newview/llagentcamera.cpp7
-rw-r--r--indra/newview/llappviewer.cpp150
-rw-r--r--indra/newview/llbrowsernotification.cpp14
-rw-r--r--indra/newview/llchathistory.cpp2
-rw-r--r--indra/newview/llfloaterabout.cpp2
-rw-r--r--indra/newview/llfloaterhelpbrowser.cpp7
-rw-r--r--indra/newview/llfloatermap.cpp13
-rw-r--r--indra/newview/llfloatermediabrowser.cpp28
-rw-r--r--indra/newview/llfloatersearch.cpp2
-rw-r--r--indra/newview/llfloaterwebcontent.cpp402
-rw-r--r--indra/newview/llfloaterwebcontent.h82
-rw-r--r--indra/newview/llimfloater.cpp11
-rw-r--r--indra/newview/llimfloater.h2
-rw-r--r--indra/newview/llinventorybridge.cpp5
-rw-r--r--indra/newview/lllogininstance.cpp415
-rw-r--r--indra/newview/lllogininstance.h6
-rw-r--r--indra/newview/llmediactrl.cpp313
-rw-r--r--indra/newview/llmediactrl.h7
-rw-r--r--indra/newview/llnearbychathandler.cpp3
-rw-r--r--indra/newview/llnetmap.cpp2
-rw-r--r--indra/newview/llpanellogin.cpp107
-rw-r--r--indra/newview/llpanelmaininventory.cpp8
-rw-r--r--indra/newview/llpanelplaces.cpp5
-rw-r--r--indra/newview/llpanelprimmediacontrols.cpp60
-rw-r--r--indra/newview/llpanelprimmediacontrols.h8
-rw-r--r--indra/newview/llprogressview.cpp4
-rw-r--r--indra/newview/llscreenchannel.cpp20
-rw-r--r--indra/newview/llscreenchannel.h2
-rw-r--r--indra/newview/llsidetray.cpp29
-rw-r--r--indra/newview/llsidetray.h15
-rw-r--r--indra/newview/llstartup.cpp11
-rw-r--r--indra/newview/llviewercontrol.cpp7
-rw-r--r--indra/newview/llviewerfloaterreg.cpp2
-rw-r--r--indra/newview/llviewermedia.cpp130
-rw-r--r--indra/newview/llviewermedia.h16
-rw-r--r--indra/newview/llviewermenu.cpp9
-rw-r--r--indra/newview/llviewermessage.cpp57
-rw-r--r--indra/newview/llviewerparcelmedia.cpp12
-rw-r--r--indra/newview/llviewerwindow.h5
-rw-r--r--indra/newview/llweb.cpp25
-rw-r--r--indra/newview/llweb.h5
-rw-r--r--indra/newview/llworldmipmap.cpp3
-rw-r--r--indra/newview/skins/default/textures/textures.xml4
-rw-r--r--indra/newview/skins/default/xui/en/floater_help_browser.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_web_content.xml190
-rw-r--r--indra/newview/skins/default/xui/en/inspect_object.xml27
-rw-r--r--indra/newview/skins/default/xui/en/menu_login.xml10
-rw-r--r--indra/newview/skins/default/xui/en/menu_mini_map.xml11
-rw-r--r--indra/newview/skins/default/xui/en/menu_place.xml22
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml12
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml123
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_invite.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_land_money.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_login.xml7
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_setup.xml55
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_sound.xml1
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml4
-rw-r--r--indra/newview/tests/lllogininstance_test.cpp47
-rw-r--r--indra/newview/tests/llworldmap_test.cpp42
-rw-r--r--indra/newview/tests/llworldmipmap_test.cpp27
-rw-r--r--indra/test/CMakeLists.txt1
-rw-r--r--indra/test_apps/llplugintest/llmediaplugintest.cpp15
-rw-r--r--indra/viewer_components/updater/llupdatedownloader.cpp103
-rw-r--r--indra/viewer_components/updater/llupdatedownloader.h9
-rw-r--r--indra/viewer_components/updater/llupdateinstaller.cpp12
-rw-r--r--indra/viewer_components/updater/llupdateinstaller.h7
-rw-r--r--indra/viewer_components/updater/llupdaterservice.cpp111
-rw-r--r--indra/viewer_components/updater/llupdaterservice.h26
-rw-r--r--indra/viewer_components/updater/scripts/darwin/update_install2
-rw-r--r--indra/viewer_components/updater/scripts/linux/update_install2
-rw-r--r--indra/viewer_components/updater/scripts/windows/update_install.bat2
-rw-r--r--indra/viewer_components/updater/tests/llupdaterservice_test.cpp5
-rw-r--r--install.xml8
-rwxr-xr-xscripts/install.py2
132 files changed, 4054 insertions, 1113 deletions
diff --git a/build.sh b/build.sh
index f9c6beefed..c5f74c23ee 100755
--- a/build.sh
+++ b/build.sh
@@ -59,10 +59,11 @@ pre_build()
-t $variant \
-G "$cmake_generator" \
configure \
- -DGRID:STRING="$viewer_grid" \
+ -DGRID:STRING="$viewer_grid" \
-DVIEWER_CHANNEL:STRING="$viewer_channel" \
-DVIEWER_LOGIN_CHANNEL:STRING="$login_channel" \
-DINSTALL_PROPRIETARY:BOOL=ON \
+ -DRELEASE_CRASH_REPORTING:BOOL=ON \
-DLOCALIZESETUP:BOOL=ON \
-DPACKAGE:BOOL=ON \
-DCMAKE_VERBOSE_MAKEFILE:BOOL=TRUE
diff --git a/doc/contributions.txt b/doc/contributions.txt
index 740c2f470c..d7a5f73ac0 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -61,19 +61,27 @@ Aimee Trescothick
Alejandro Rosenthal
VWR-1184
Aleric Inglewood
+ SNOW-240
SNOW-522
SNOW-626
SNOW-756
SNOW-764
VWR-10001
+ VWR-10579
VWR-10759
VWR-10837
VWR-12691
VWR-12984
VWR-13996
VWR-14426
+ VWR-24247
+ VWR-24251
+ VWR-24252
+ VWR-24254
+ VWR-24261
SNOW-84
SNOW-477
+ SNOW-744
SNOW-766
STORM-163
Ales Beaumont
@@ -211,6 +219,8 @@ Catherine Pfeffer
Celierra Darling
VWR-1274
VWR-6975
+Cron Stardust
+ VWR-10579
Cypren Christenson
STORM-417
Dale Glass
@@ -354,11 +364,14 @@ JB Kraft
Joghert LeSabre
VWR-64
Jonathan Yap
- VWR-17801
+ STORM-596
+ STORM-523
STORM-616
STORM-679
- STORM-596
+ STORM-737
STORM-726
+ VWR-17801
+ STORM-785
Kage Pixel
VWR-11
Ken March
@@ -587,6 +600,7 @@ Robin Cornelius
STORM-422
VWR-2488
VWR-9557
+ VWR-10579
VWR-11128
VWR-12533
VWR-12587
@@ -735,6 +749,8 @@ Tue Torok
CT-74
Twisted Laws
SNOW-352
+ STORM-466
+ STORM-467
Vadim Bigbear
VWR-2681
Vector Hastings
@@ -783,6 +799,7 @@ WolfPup Lowenhar
STORM-654
STORM-674
STORM-776
+ STORM-825
VWR-20741
VWR-20933
Zai Lynch
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index db2cdb5ff8..dbe0cf5cd0 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -4,27 +4,28 @@
include(Variables)
-
# Portable compilation flags.
-
-if (EXISTS ${CMAKE_SOURCE_DIR}/llphysics)
- # The release build should only offer to send crash reports if we're
- # building from a Linden internal source tree.
- set(release_crash_reports 1)
-else (EXISTS ${CMAKE_SOURCE_DIR}/llphysics)
- set(release_crash_reports 0)
-endif (EXISTS ${CMAKE_SOURCE_DIR}/llphysics)
-
set(CMAKE_CXX_FLAGS_DEBUG "-D_DEBUG -DLL_DEBUG=1")
set(CMAKE_CXX_FLAGS_RELEASE
- "-DLL_RELEASE=1 -DLL_RELEASE_FOR_DOWNLOAD=1 -D_SECURE_SCL=0 -DLL_SEND_CRASH_REPORTS=${release_crash_reports} -DNDEBUG")
+ "-DLL_RELEASE=1 -DLL_RELEASE_FOR_DOWNLOAD=1 -D_SECURE_SCL=0 -DNDEBUG")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO
- "-DLL_RELEASE=1 -D_SECURE_SCL=0 -DLL_SEND_CRASH_REPORTS=0 -DNDEBUG -DLL_RELEASE_WITH_DEBUG_INFO=1")
+ "-DLL_RELEASE=1 -D_SECURE_SCL=0 -DNDEBUG -DLL_RELEASE_WITH_DEBUG_INFO=1")
+# Configure crash reporting
+set(RELEASE_CRASH_REPORTING OFF CACHE BOOL "Enable use of crash reporting in release builds")
+set(NON_RELEASE_CRASH_REPORTING OFF CACHE BOOL "Enable use of crash reporting in developer builds")
-# Don't bother with a MinSizeRel build.
+if(RELEASE_CRASH_REPORTING)
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DLL_SEND_CRASH_REPORTS=1")
+endif()
+
+if(NON_RELEASE_CRASH_REPORTING)
+ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DLL_SEND_CRASH_REPORTS=1")
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DLL_SEND_CRASH_REPORTS=1")
+endif()
+# Don't bother with a MinSizeRel build.
set(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo;Release;Debug" CACHE STRING
"Supported build types." FORCE)
diff --git a/indra/cmake/BerkeleyDB.cmake b/indra/cmake/BerkeleyDB.cmake
index d98e79179d..e3ca0fd77d 100644
--- a/indra/cmake/BerkeleyDB.cmake
+++ b/indra/cmake/BerkeleyDB.cmake
@@ -6,6 +6,11 @@ set(DB_FIND_REQUIRED ON)
if (STANDALONE)
include(FindBerkeleyDB)
else (STANDALONE)
- set(DB_LIBRARIES db-4.2)
+ if (LINUX)
+ # Need to add dependency pthread explicitely to support ld.gold.
+ set(DB_LIBRARIES db-4.2 pthread)
+ else (LINUX)
+ set(DB_LIBRARIES db-4.2)
+ endif (LINUX)
set(DB_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)
endif (STANDALONE)
diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index 6470836286..3f421b270b 100644
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -33,6 +33,7 @@ set(cmake_SOURCE_FILES
FindMySQL.cmake
FindOpenJPEG.cmake
FindXmlRpcEpi.cmake
+ FindZLIB.cmake
FMOD.cmake
FreeType.cmake
GStreamer010Plugin.cmake
diff --git a/indra/cmake/FindJsonCpp.cmake b/indra/cmake/FindJsonCpp.cmake
index 9d16f2aaab..cf84b309c1 100644
--- a/indra/cmake/FindJsonCpp.cmake
+++ b/indra/cmake/FindJsonCpp.cmake
@@ -21,7 +21,12 @@ EXEC_PROGRAM(${CMAKE_CXX_COMPILER}
OUTPUT_STRIP_TRAILING_WHITESPACE
)
+# Try to find a library that was compiled with the same compiler version as we currently use.
SET(JSONCPP_NAMES ${JSONCPP_NAMES} libjson_linux-gcc-${_gcc_COMPILER_VERSION}_libmt.so)
+IF (STANDALONE)
+ # On standalone, assume that the system installed library was compiled with the used compiler.
+ SET(JSONCPP_NAMES ${JSONCPP_NAMES} libjson.so)
+ENDIF (STANDALONE)
FIND_LIBRARY(JSONCPP_LIBRARY
NAMES ${JSONCPP_NAMES}
PATHS /usr/lib /usr/local/lib
diff --git a/indra/cmake/FindLLQtWebkit.cmake b/indra/cmake/FindLLQtWebkit.cmake
new file mode 100644
index 0000000000..c747ec32a2
--- /dev/null
+++ b/indra/cmake/FindLLQtWebkit.cmake
@@ -0,0 +1,62 @@
+# -*- cmake -*-
+
+# - Find llqtwebkit
+# Find the llqtwebkit includes and library
+# This module defines
+# LLQTWEBKIT_INCLUDE_DIR, where to find llqtwebkit.h, etc.
+# LLQTWEBKIT_LIBRARY, the llqtwebkit library with full path.
+# LLQTWEBKIT_FOUND, If false, do not try to use llqtwebkit.
+# also defined, but not for general use are
+# LLQTWEBKIT_LIBRARIES, the libraries needed to use llqtwebkit.
+# LLQTWEBKIT_LIBRARY_DIRS, where to find the llqtwebkit library.
+# LLQTWEBKIT_DEFINITIONS - You should add_definitions(${LLQTWEBKIT_DEFINITIONS})
+# before compiling code that includes llqtwebkit library files.
+
+# Try to use pkg-config first.
+# This allows to have two different libllqtwebkit packages installed:
+# one for viewer 2.x and one for viewer 1.x.
+include(FindPkgConfig)
+if (PKG_CONFIG_FOUND)
+ if (LLQtWebkit_FIND_REQUIRED AND LLQtWebkit_FIND_VERSION)
+ set(_PACKAGE_ARGS libllqtwebkit>=${LLQtWebkit_FIND_VERSION} REQUIRED)
+ else (LLQtWebkit_FIND_REQUIRED AND LLQtWebkit_FIND_VERSION)
+ set(_PACKAGE_ARGS libllqtwebkit)
+ endif (LLQtWebkit_FIND_REQUIRED AND LLQtWebkit_FIND_VERSION)
+ if (NOT "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_LESS "2.8")
+ # As virtually nobody will have a pkg-config file for this, do this check always quiet.
+ # Unfortunately cmake 2.8 or higher is required for pkg_check_modules to have a 'QUIET'.
+ set(_PACKAGE_ARGS ${_PACKAGE_ARGS} QUIET)
+ endif ()
+ pkg_check_modules(LLQTWEBKIT ${_PACKAGE_ARGS})
+endif (PKG_CONFIG_FOUND)
+set(LLQTWEBKIT_DEFINITIONS ${LLQTWEBKIT_CFLAGS_OTHER})
+
+find_path(LLQTWEBKIT_INCLUDE_DIR llqtwebkit.h NO_SYSTEM_ENVIRONMENT_PATH HINTS ${LLQTWEBKIT_INCLUDE_DIRS})
+
+find_library(LLQTWEBKIT_LIBRARY NAMES llqtwebkit NO_SYSTEM_ENVIRONMENT_PATH HINTS ${LLQTWEBKIT_LIBRARY_DIRS})
+
+if (NOT PKG_CONFIG_FOUND OR NOT LLQTWEBKIT_FOUND) # If pkg-config couldn't find it, pretend we don't have pkg-config.
+ set(LLQTWEBKIT_LIBRARIES llqtwebkit)
+ get_filename_component(LLQTWEBKIT_LIBRARY_DIRS ${LLQTWEBKIT_LIBRARY} PATH)
+endif (NOT PKG_CONFIG_FOUND OR NOT LLQTWEBKIT_FOUND)
+
+# Handle the QUIETLY and REQUIRED arguments and set LLQTWEBKIT_FOUND
+# to TRUE if all listed variables are TRUE.
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(
+ LLQTWEBKIT
+ DEFAULT_MSG
+ LLQTWEBKIT_LIBRARY
+ LLQTWEBKIT_INCLUDE_DIR
+ LLQTWEBKIT_LIBRARIES
+ LLQTWEBKIT_LIBRARY_DIRS
+ )
+
+mark_as_advanced(
+ LLQTWEBKIT_LIBRARY
+ LLQTWEBKIT_INCLUDE_DIR
+ LLQTWEBKIT_LIBRARIES
+ LLQTWEBKIT_LIBRARY_DIRS
+ LLQTWEBKIT_DEFINITIONS
+ )
+
diff --git a/indra/cmake/FindNDOF.cmake b/indra/cmake/FindNDOF.cmake
new file mode 100644
index 0000000000..6dcf590a53
--- /dev/null
+++ b/indra/cmake/FindNDOF.cmake
@@ -0,0 +1,39 @@
+# -*- cmake -*-
+
+# - Find NDOF
+# Find the NDOF includes and library
+# This module defines
+# NDOF_INCLUDE_DIR, where to find ndofdev_external.h, etc.
+# NDOF_LIBRARY, the library needed to use NDOF.
+# NDOF_FOUND, If false, do not try to use NDOF.
+
+find_path(NDOF_INCLUDE_DIR ndofdev_external.h
+ PATH_SUFFIXES ndofdev
+ )
+
+set(NDOF_NAMES ${NDOF_NAMES} ndofdev libndofdev)
+find_library(NDOF_LIBRARY
+ NAMES ${NDOF_NAMES}
+ )
+
+if (NDOF_LIBRARY AND NDOF_INCLUDE_DIR)
+ set(NDOF_FOUND "YES")
+else (NDOF_LIBRARY AND NDOF_INCLUDE_DIR)
+ set(NDOF_FOUND "NO")
+endif (NDOF_LIBRARY AND NDOF_INCLUDE_DIR)
+
+
+if (NDOF_FOUND)
+ if (NOT NDOF_FIND_QUIETLY)
+ message(STATUS "Found NDOF: Library in '${NDOF_LIBRARY}' and header in '${NDOF_INCLUDE_DIR}' ")
+ endif (NOT NDOF_FIND_QUIETLY)
+else (NDOF_FOUND)
+ if (NDOF_FIND_REQUIRED)
+ message(FATAL_ERROR " * * *\nCould not find NDOF library!\nIf you don't need Space Navigator Joystick support you can skip this test by configuring with -DNDOF:BOOL=OFF\n * * *")
+ endif (NDOF_FIND_REQUIRED)
+endif (NDOF_FOUND)
+
+mark_as_advanced(
+ NDOF_LIBRARY
+ NDOF_INCLUDE_DIR
+ )
diff --git a/indra/cmake/FindTut.cmake b/indra/cmake/FindTut.cmake
index b5d58f6396..c2a9f43053 100644
--- a/indra/cmake/FindTut.cmake
+++ b/indra/cmake/FindTut.cmake
@@ -3,12 +3,11 @@
# - Find Tut
# Find the Tut unit test framework includes and library
# This module defines
-# TUT_INCLUDE_DIR, where to find tut.h, etc.
+# TUT_INCLUDE_DIR, where to find tut/tut.hpp.
# TUT_FOUND, If false, do not try to use Tut.
-find_path(TUT_INCLUDE_DIR tut.h
- /usr/local/include/
- /usr/include
+find_path(TUT_INCLUDE_DIR tut/tut.hpp
+ NO_SYSTEM_ENVIRONMENT_PATH
)
if (TUT_INCLUDE_DIR)
diff --git a/indra/cmake/FindZLIB.cmake b/indra/cmake/FindZLIB.cmake
new file mode 100644
index 0000000000..6d630f1ba9
--- /dev/null
+++ b/indra/cmake/FindZLIB.cmake
@@ -0,0 +1,46 @@
+# -*- cmake -*-
+
+# - Find zlib
+# Find the ZLIB includes and library
+# This module defines
+# ZLIB_INCLUDE_DIRS, where to find zlib.h, etc.
+# ZLIB_LIBRARIES, the libraries needed to use zlib.
+# ZLIB_FOUND, If false, do not try to use zlib.
+#
+# This FindZLIB is about 43 times as fast the one provided with cmake (2.8.x),
+# because it doesn't look up the version of zlib, resulting in a dramatic
+# speed up for configure (from 4 minutes 22 seconds to 6 seconds).
+#
+# Note: Since this file is only used for standalone, the windows
+# specific parts were left out.
+
+FIND_PATH(ZLIB_INCLUDE_DIR zlib.h
+ NO_SYSTEM_ENVIRONMENT_PATH
+ )
+
+FIND_LIBRARY(ZLIB_LIBRARY z)
+
+if (ZLIB_LIBRARY AND ZLIB_INCLUDE_DIR)
+ SET(ZLIB_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR})
+ SET(ZLIB_LIBRARIES ${ZLIB_LIBRARY})
+ SET(ZLIB_FOUND "YES")
+else (ZLIB_LIBRARY AND ZLIB_INCLUDE_DIR)
+ SET(ZLIB_FOUND "NO")
+endif (ZLIB_LIBRARY AND ZLIB_INCLUDE_DIR)
+
+if (ZLIB_FOUND)
+ if (NOT ZLIB_FIND_QUIETLY)
+ message(STATUS "Found ZLIB: ${ZLIB_LIBRARIES}")
+ SET(ZLIB_FIND_QUIETLY TRUE)
+ endif (NOT ZLIB_FIND_QUIETLY)
+else (ZLIB_FOUND)
+ if (ZLIB_FIND_REQUIRED)
+ message(FATAL_ERROR "Could not find ZLIB library")
+ endif (ZLIB_FIND_REQUIRED)
+endif (ZLIB_FOUND)
+
+mark_as_advanced(
+ ZLIB_LIBRARY
+ ZLIB_INCLUDE_DIR
+ )
+
diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake
index 29e2492551..62b764bb30 100644
--- a/indra/cmake/LLAddBuildTest.cmake
+++ b/indra/cmake/LLAddBuildTest.cmake
@@ -205,6 +205,9 @@ FUNCTION(LL_ADD_INTEGRATION_TEST
endif(TEST_DEBUG)
ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})
SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}")
+ if(STANDALONE)
+ SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES COMPILE_FLAGS -I"${TUT_INCLUDE_DIR}")
+ endif(STANDALONE)
# Add link deps to the executable
if(TEST_DEBUG)
diff --git a/indra/cmake/LLCommon.cmake b/indra/cmake/LLCommon.cmake
index d1ab264a41..17e211cb99 100644
--- a/indra/cmake/LLCommon.cmake
+++ b/indra/cmake/LLCommon.cmake
@@ -13,7 +13,14 @@ set(LLCOMMON_INCLUDE_DIRS
${Boost_INCLUDE_DIRS}
)
-set(LLCOMMON_LIBRARIES llcommon)
+if (LINUX)
+ # In order to support using ld.gold on linux, we need to explicitely
+ # specify all libraries that llcommon uses.
+ # llcommon uses `clock_gettime' which is provided by librt on linux.
+ set(LLCOMMON_LIBRARIES llcommon rt)
+else (LINUX)
+ set(LLCOMMON_LIBRARIES llcommon)
+endif (LINUX)
add_definitions(${TCMALLOC_FLAG})
diff --git a/indra/cmake/LLPlugin.cmake b/indra/cmake/LLPlugin.cmake
index 9722f16c3c..7ee404b9bd 100644
--- a/indra/cmake/LLPlugin.cmake
+++ b/indra/cmake/LLPlugin.cmake
@@ -5,4 +5,10 @@ set(LLPLUGIN_INCLUDE_DIRS
${LIBS_OPEN_DIR}/llplugin
)
-set(LLPLUGIN_LIBRARIES llplugin)
+if (LINUX)
+ # In order to support using ld.gold on linux, we need to explicitely
+ # specify all libraries that llplugin uses.
+ set(LLPLUGIN_LIBRARIES llplugin pthread)
+else (LINUX)
+ set(LLPLUGIN_LIBRARIES llplugin)
+endif (LINUX)
diff --git a/indra/cmake/NDOF.cmake b/indra/cmake/NDOF.cmake
index dad74e99b1..7a463d1190 100644
--- a/indra/cmake/NDOF.cmake
+++ b/indra/cmake/NDOF.cmake
@@ -1,14 +1,32 @@
# -*- cmake -*-
include(Prebuilt)
-use_prebuilt_binary(ndofdev)
+set(NDOF ON CACHE BOOL "Use NDOF space navigator joystick library.")
-if (WINDOWS OR DARWIN OR LINUX)
+if (NDOF)
+ if (STANDALONE)
+ set(NDOF_FIND_REQUIRED ON)
+ include(FindNDOF)
+ else (STANDALONE)
+ use_prebuilt_binary(ndofdev)
+
+ if (WINDOWS)
+ set(NDOF_LIBRARY libndofdev)
+ elseif (DARWIN OR LINUX)
+ set(NDOF_LIBRARY ndofdev)
+ endif (WINDOWS)
+
+ set(NDOF_INCLUDE_DIR ${ARCH_PREBUILT_DIRS}/include/ndofdev)
+ set(NDOF_FOUND 1)
+ endif (STANDALONE)
+endif (NDOF)
+
+if (NDOF_FOUND)
add_definitions(-DLIB_NDOF=1)
-endif (WINDOWS OR DARWIN OR LINUX)
+ include_directories(${NDOF_INCLUDE_DIR})
+else (NDOF_FOUND)
+ message(STATUS "Building without N-DoF joystick support")
+ set(NDOF_INCLUDE_DIR "")
+ set(NDOF_LIBRARY "")
+endif (NDOF_FOUND)
-if (WINDOWS)
- set(NDOF_LIBRARY libndofdev)
-elseif (DARWIN OR LINUX)
- set(NDOF_LIBRARY ndofdev)
-endif (WINDOWS)
diff --git a/indra/cmake/Tut.cmake b/indra/cmake/Tut.cmake
index 784560471d..738c08c42f 100644
--- a/indra/cmake/Tut.cmake
+++ b/indra/cmake/Tut.cmake
@@ -6,7 +6,6 @@ set(TUT_FIND_QUIETLY TRUE)
if (STANDALONE)
include(FindTut)
- include_directories(${TUT_INCLUDE_DIR})
else (STANDALONE)
use_prebuilt_binary(tut)
endif (STANDALONE)
diff --git a/indra/cmake/WebKitLibPlugin.cmake b/indra/cmake/WebKitLibPlugin.cmake
index 12ba1b1b35..1f5b0f5d84 100644
--- a/indra/cmake/WebKitLibPlugin.cmake
+++ b/indra/cmake/WebKitLibPlugin.cmake
@@ -3,6 +3,29 @@ include(Linking)
include(Prebuilt)
if (STANDALONE)
+ # The minimal version, 4.4.3, is rather arbitrary: it's the version in Debian/Lenny.
+ find_package(Qt4 4.4.3 COMPONENTS QtCore QtGui QtNetwork QtOpenGL QtWebKit REQUIRED)
+ include(${QT_USE_FILE})
+ set(QTDIR $ENV{QTDIR})
+ if (QTDIR AND NOT "${QT_BINARY_DIR}" STREQUAL "${QTDIR}/bin")
+ message(FATAL_ERROR "\"${QT_BINARY_DIR}\" is unequal \"${QTDIR}/bin\"; "
+ "Qt is found by looking for qmake in your PATH. "
+ "Please set your PATH such that 'qmake' is found in \$QTDIR/bin, "
+ "or unset QTDIR if the found Qt is correct.")
+ endif (QTDIR AND NOT "${QT_BINARY_DIR}" STREQUAL "${QTDIR}/bin")
+ find_package(LLQtWebkit REQUIRED QUIET)
+ # Add the plugins.
+ set(QT_PLUGIN_LIBRARIES)
+ foreach(qlibname qgif qjpeg)
+ find_library(QT_PLUGIN_${qlibname} ${qlibname} PATHS ${QT_PLUGINS_DIR}/imageformats NO_DEFAULT_PATH)
+ if (QT_PLUGIN_${qlibname})
+ list(APPEND QT_PLUGIN_LIBRARIES ${QT_PLUGIN_${qlibname}})
+ else (QT_PLUGIN_${qtlibname})
+ message(FATAL_ERROR "Could not find the Qt plugin ${qlibname} in \"${QT_PLUGINS_DIR}/imageformats\"!")
+ endif (QT_PLUGIN_${qlibname})
+ endforeach(qlibname)
+ # qjpeg depends on libjpeg
+ list(APPEND QT_PLUGIN_LIBRARIES jpeg)
set(WEBKITLIBPLUGIN OFF CACHE BOOL
"WEBKITLIBPLUGIN support for the llplugin/llmedia test apps.")
else (STANDALONE)
@@ -35,7 +58,7 @@ elseif (DARWIN)
)
elseif (LINUX)
if (STANDALONE)
- set(WEBKIT_PLUGIN_LIBRARIES llqtwebkit)
+ set(WEBKIT_PLUGIN_LIBRARIES ${LLQTWEBKIT_LIBRARY} ${QT_LIBRARIES} ${QT_PLUGIN_LIBRARIES})
else (STANDALONE)
set(WEBKIT_PLUGIN_LIBRARIES
llqtwebkit
diff --git a/indra/lib/python/indra/util/test_win32_manifest.py b/indra/lib/python/indra/util/test_win32_manifest.py
index 786521c068..da8ee6c545 100644
--- a/indra/lib/python/indra/util/test_win32_manifest.py
+++ b/indra/lib/python/indra/util/test_win32_manifest.py
@@ -52,20 +52,22 @@ def get_HKLM_registry_value(key_str, value_str):
def find_vc_dir():
supported_versions = (r'8.0', r'9.0')
+ supported_products = (r'VisualStudio', r'VCExpress')
value_str = (r'ProductDir')
- for version in supported_versions:
- key_str = (r'SOFTWARE\Microsoft\VisualStudio\%s\Setup\VC' %
- version)
- try:
- return get_HKLM_registry_value(key_str, value_str)
- except WindowsError, err:
- x64_key_str = (r'SOFTWARE\Wow6432Node\Microsoft\VisualStudio\%s\Setup\VS' %
- version)
+ for product in supported_products:
+ for version in supported_versions:
+ key_str = (r'SOFTWARE\Microsoft\%s\%s\Setup\VC' %
+ (product, version))
try:
- return get_HKLM_registry_value(x64_key_str, value_str)
- except:
- print >> sys.stderr, "Didn't find MS VC version %s " % version
+ return get_HKLM_registry_value(key_str, value_str)
+ except WindowsError, err:
+ x64_key_str = (r'SOFTWARE\Wow6432Node\Microsoft\VisualStudio\%s\Setup\VS' %
+ version)
+ try:
+ return get_HKLM_registry_value(x64_key_str, value_str)
+ except:
+ print >> sys.stderr, "Didn't find MS %s version %s " % (product,version)
raise
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index 66ec5bad2c..d1c44c9403 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -28,6 +28,7 @@
#include "linden_common.h"
#include "llapr.h"
+#include "apr_dso.h"
apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool
LLVolatileAPRPool *LLAPRFile::sAPRFilePoolp = NULL ; //global volatile APR memory pool.
@@ -279,14 +280,31 @@ bool ll_apr_warn_status(apr_status_t status)
{
if(APR_SUCCESS == status) return false;
char buf[MAX_STRING]; /* Flawfinder: ignore */
- apr_strerror(status, buf, MAX_STRING);
+ apr_strerror(status, buf, sizeof(buf));
LL_WARNS("APR") << "APR: " << buf << LL_ENDL;
return true;
}
+bool ll_apr_warn_status(apr_status_t status, apr_dso_handle_t *handle)
+{
+ bool result = ll_apr_warn_status(status);
+ // Despite observed truncation of actual Mac dylib load errors, increasing
+ // this buffer to more than MAX_STRING doesn't help: it appears that APR
+ // stores the output in a fixed 255-character internal buffer. (*sigh*)
+ char buf[MAX_STRING]; /* Flawfinder: ignore */
+ apr_dso_error(handle, buf, sizeof(buf));
+ LL_WARNS("APR") << "APR: " << buf << LL_ENDL;
+ return result;
+}
+
void ll_apr_assert_status(apr_status_t status)
{
- llassert(ll_apr_warn_status(status) == false);
+ llassert(! ll_apr_warn_status(status));
+}
+
+void ll_apr_assert_status(apr_status_t status, apr_dso_handle_t *handle)
+{
+ llassert(! ll_apr_warn_status(status, handle));
}
//---------------------------------------------------------------------
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index 4930270af8..af33ce666f 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -53,6 +53,8 @@
extern LL_COMMON_API apr_thread_mutex_t* gLogMutexp;
extern apr_thread_mutex_t* gCallStacksLogMutexp;
+struct apr_dso_handle_t;
+
/**
* @brief initialize the common apr constructs -- apr itself, the
* global pool, and a mutex.
@@ -259,8 +261,11 @@ public:
* @return Returns <code>true</code> if status is an error condition.
*/
bool LL_COMMON_API ll_apr_warn_status(apr_status_t status);
+/// There's a whole other APR error-message function if you pass a DSO handle.
+bool LL_COMMON_API ll_apr_warn_status(apr_status_t status, apr_dso_handle_t* handle);
void LL_COMMON_API ll_apr_assert_status(apr_status_t status);
+void LL_COMMON_API ll_apr_assert_status(apr_status_t status, apr_dso_handle_t* handle);
extern "C" LL_COMMON_API apr_pool_t* gAPRPoolp; // Global APR memory pool
diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp
index 84a6620a77..97e2bdeb57 100644
--- a/indra/llcommon/llevents.cpp
+++ b/indra/llcommon/llevents.cpp
@@ -475,7 +475,7 @@ void LLEventPump::stopListening(const std::string& name)
*****************************************************************************/
bool LLEventStream::post(const LLSD& event)
{
- if (! mEnabled)
+ if (! mEnabled || !mSignal)
{
return false;
}
@@ -515,6 +515,8 @@ bool LLEventQueue::post(const LLSD& event)
void LLEventQueue::flush()
{
+ if(!mSignal) return;
+
// Consider the case when a given listener on this LLEventQueue posts yet
// another event on the same queue. If we loop over mEventQueue directly,
// we'll end up processing all those events during the same flush() call
diff --git a/indra/llimage/CMakeLists.txt b/indra/llimage/CMakeLists.txt
index 6834267d4b..ea8c1a1107 100644
--- a/indra/llimage/CMakeLists.txt
+++ b/indra/llimage/CMakeLists.txt
@@ -3,12 +3,13 @@
project(llimage)
include(00-Common)
-include(LLAddBuildTest)
include(LLCommon)
include(LLImage)
include(LLMath)
include(LLVFS)
include(ZLIB)
+include(LLAddBuildTest)
+include(Tut)
include_directories(
${LLCOMMON_INCLUDE_DIRS}
@@ -63,4 +64,12 @@ target_link_libraries(llimage
)
# Add tests
-#ADD_BUILD_TEST(llimageworker llimage)
+if (LL_TESTS)
+ SET(llimage_TEST_SOURCE_FILES
+ llimageworker.cpp
+ )
+ LL_ADD_PROJECT_UNIT_TESTS(llimage "${llimage_TEST_SOURCE_FILES}")
+endif (LL_TESTS)
+
+
+
diff --git a/indra/llimage/tests/llimageworker_test.cpp b/indra/llimage/tests/llimageworker_test.cpp
index a109276709..08476fb72c 100644
--- a/indra/llimage/tests/llimageworker_test.cpp
+++ b/indra/llimage/tests/llimageworker_test.cpp
@@ -26,10 +26,8 @@
*/
// Precompiled header: almost always required for newview cpp files
-#include <list>
-#include <map>
-#include <algorithm>
-// Class to test
+#include "linden_common.h"
+// Class to test
#include "../llimageworker.h"
// For timer class
#include "../llcommon/lltimer.h"
@@ -44,7 +42,17 @@
// * Do not make any assumption as to how those classes or methods work (i.e. don't copy/paste code)
// * A simulator for a class can be implemented here. Please comment and document thoroughly.
-LLImageBase::LLImageBase() {}
+LLImageBase::LLImageBase()
+: mData(NULL),
+mDataSize(0),
+mWidth(0),
+mHeight(0),
+mComponents(0),
+mBadBufferAllocation(false),
+mAllowOverSize(false),
+mMemType(LLMemType::MTYPE_IMAGEBASE)
+{
+}
LLImageBase::~LLImageBase() {}
void LLImageBase::dump() { }
void LLImageBase::sanityCheck() { }
diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp
index 95e0997d5b..13b12c0928 100644
--- a/indra/llimagej2coj/llimagej2coj.cpp
+++ b/indra/llimagej2coj/llimagej2coj.cpp
@@ -90,6 +90,12 @@ void info_callback(const char* msg, void*)
lldebugs << "LLImageJ2COJ: " << chomp(msg) << llendl;
}
+// Divide a by 2 to the power of b and round upwards
+int ceildivpow2(int a, int b)
+{
+ return (a + (1 << b) - 1) >> b;
+}
+
LLImageJ2COJ::LLImageJ2COJ()
: LLImageJ2CImpl()
diff --git a/indra/llimagej2coj/llimagej2coj.h b/indra/llimagej2coj/llimagej2coj.h
index 7edacbe97c..9476665ccb 100644
--- a/indra/llimagej2coj/llimagej2coj.h
+++ b/indra/llimagej2coj/llimagej2coj.h
@@ -34,17 +34,11 @@ class LLImageJ2COJ : public LLImageJ2CImpl
public:
LLImageJ2COJ();
virtual ~LLImageJ2COJ();
-
protected:
/*virtual*/ BOOL getMetadata(LLImageJ2C &base);
/*virtual*/ BOOL decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count);
/*virtual*/ BOOL encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0,
BOOL reversible = FALSE);
- int ceildivpow2(int a, int b)
- {
- // Divide a by b to the power of 2 and round upwards.
- return (a + (1 << b) - 1) >> b;
- }
};
#endif
diff --git a/indra/llkdu/CMakeLists.txt b/indra/llkdu/CMakeLists.txt
index b8b44b44fc..7ed1c6c694 100644
--- a/indra/llkdu/CMakeLists.txt
+++ b/indra/llkdu/CMakeLists.txt
@@ -42,4 +42,14 @@ list(APPEND llkdu_SOURCE_FILES ${llkdu_HEADER_FILES})
if (USE_KDU)
add_library (${LLKDU_LIBRARIES} ${llkdu_SOURCE_FILES})
+ # Add tests
+ if (LL_TESTS)
+ include(LLAddBuildTest)
+ include(Tut)
+ SET(llkdu_TEST_SOURCE_FILES
+ llimagej2ckdu.cpp
+ )
+ LL_ADD_PROJECT_UNIT_TESTS(llkdu "${llkdu_TEST_SOURCE_FILES}")
+ endif (LL_TESTS)
+
endif (USE_KDU)
diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp
index 1a286d1406..10ea5685e8 100644
--- a/indra/llkdu/llimagej2ckdu.cpp
+++ b/indra/llkdu/llimagej2ckdu.cpp
@@ -229,16 +229,17 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECod
mCodeStreamp = NULL;
}
- if (!mInputp)
+ if (!mInputp && base.getData())
{
- llassert(base.getData());
// The compressed data has been loaded
- // Setup the source for the codestrea
+ // Setup the source for the codestream
mInputp = new LLKDUMemSource(base.getData(), data_size);
}
- llassert(mInputp);
- mInputp->reset();
+ if (mInputp)
+ {
+ mInputp->reset();
+ }
mCodeStreamp = new kdu_codestream;
mCodeStreamp->create(mInputp);
@@ -1017,7 +1018,7 @@ kdc_flow_control::kdc_flow_control (kdu_image_in_base *img_in, kdu_codestream co
comp->ratio_counter = 0;
comp->remaining_lines = comp->initial_lines = dims.size.y;
}
- assert(num_components > 0);
+ assert(num_components >= 0);
tile.set_components_of_interest(num_components);
max_buffer_memory = engine.create(codestream,tile,false,NULL,false,1,NULL,NULL,false);
diff --git a/indra/llkdu/llimagej2ckdu.h b/indra/llkdu/llimagej2ckdu.h
index 03f289f8b1..5628f69eeb 100644
--- a/indra/llkdu/llimagej2ckdu.h
+++ b/indra/llkdu/llimagej2ckdu.h
@@ -50,17 +50,16 @@ public:
MODE_RESILIENT = 1,
MODE_FUSSY = 2
};
-
-public:
LLImageJ2CKDU();
virtual ~LLImageJ2CKDU();
-
+
protected:
/*virtual*/ BOOL getMetadata(LLImageJ2C &base);
/*virtual*/ BOOL decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count);
/*virtual*/ BOOL encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0,
BOOL reversible=FALSE);
+private:
void setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECodeStreamMode mode);
void cleanupCodeStream();
BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count );
diff --git a/indra/llkdu/tests/llimagej2ckdu_test.cpp b/indra/llkdu/tests/llimagej2ckdu_test.cpp
new file mode 100644
index 0000000000..1ccee4bb64
--- /dev/null
+++ b/indra/llkdu/tests/llimagej2ckdu_test.cpp
@@ -0,0 +1,248 @@
+/**
+ * @file llimagej2ckdu_test.cpp
+ * @author Merov Linden
+ * @date 2010-12-17
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+// Class to test
+#include "../llimagej2ckdu.h"
+#include "../llkdumem.h"
+// Tut header
+#include "../test/lltut.h"
+
+// -------------------------------------------------------------------------------------------
+// Stubbing: Declarations required to link and run the class being tested
+// Notes:
+// * Add here stubbed implementation of the few classes and methods used in the class to be tested
+// * Add as little as possible (let the link errors guide you)
+// * Do not make any assumption as to how those classes or methods work (i.e. don't copy/paste code)
+// * A simulator for a class can be implemented here. Please comment and document thoroughly.
+
+// End Stubbing
+// -------------------------------------------------------------------------------------------
+// Stubb the LL Image Classes
+LLImageRaw::LLImageRaw() { }
+LLImageRaw::~LLImageRaw() { }
+U8* LLImageRaw::allocateData(S32 ) { return NULL; }
+void LLImageRaw::deleteData() { }
+U8* LLImageRaw::reallocateData(S32 ) { return NULL; }
+BOOL LLImageRaw::resize(U16, U16, S8) { return TRUE; } // this method always returns TRUE...
+
+LLImageBase::LLImageBase()
+: mData(NULL),
+mDataSize(0),
+mWidth(0),
+mHeight(0),
+mComponents(0),
+mBadBufferAllocation(false),
+mAllowOverSize(false),
+mMemType(LLMemType::MTYPE_IMAGEBASE)
+{ }
+LLImageBase::~LLImageBase() { }
+U8* LLImageBase::allocateData(S32 ) { return NULL; }
+void LLImageBase::deleteData() { }
+void LLImageBase::dump() { }
+const U8* LLImageBase::getData() const { return NULL; }
+U8* LLImageBase::getData() { return NULL; }
+U8* LLImageBase::reallocateData(S32 ) { return NULL; }
+void LLImageBase::sanityCheck() { }
+void LLImageBase::setSize(S32 , S32 , S32 ) { }
+
+LLImageJ2CImpl::~LLImageJ2CImpl() { }
+
+LLImageFormatted::LLImageFormatted(S8 ) { }
+LLImageFormatted::~LLImageFormatted() { }
+U8* LLImageFormatted::allocateData(S32 ) { return NULL; }
+S32 LLImageFormatted::calcDataSize(S32 ) { return 0; }
+S32 LLImageFormatted::calcDiscardLevelBytes(S32 ) { return 0; }
+BOOL LLImageFormatted::decodeChannels(LLImageRaw*, F32, S32, S32) { return FALSE; }
+BOOL LLImageFormatted::copyData(U8 *, S32) { return TRUE; } // this method always returns TRUE...
+void LLImageFormatted::deleteData() { }
+void LLImageFormatted::dump() { }
+U8* LLImageFormatted::reallocateData(S32 ) { return NULL; }
+void LLImageFormatted::resetLastError() { }
+void LLImageFormatted::sanityCheck() { }
+void LLImageFormatted::setLastError(const std::string& , const std::string& ) { }
+
+LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C) { }
+LLImageJ2C::~LLImageJ2C() { }
+S32 LLImageJ2C::calcDataSize(S32 ) { return 0; }
+S32 LLImageJ2C::calcDiscardLevelBytes(S32 ) { return 0; }
+S32 LLImageJ2C::calcHeaderSize() { return 0; }
+BOOL LLImageJ2C::decode(LLImageRaw*, F32) { return FALSE; }
+BOOL LLImageJ2C::decodeChannels(LLImageRaw*, F32, S32, S32 ) { return FALSE; }
+void LLImageJ2C::decodeFailed() { }
+BOOL LLImageJ2C::encode(const LLImageRaw*, F32) { return FALSE; }
+S8 LLImageJ2C::getRawDiscardLevel() { return 0; }
+void LLImageJ2C::resetLastError() { }
+void LLImageJ2C::setLastError(const std::string&, const std::string&) { }
+BOOL LLImageJ2C::updateData() { return FALSE; }
+void LLImageJ2C::updateRawDiscardLevel() { }
+
+LLKDUMemIn::LLKDUMemIn(const U8*, const U32, const U16, const U16, const U8, siz_params*) { }
+LLKDUMemIn::~LLKDUMemIn() { }
+bool LLKDUMemIn::get(int, kdu_line_buf&, int) { return false; }
+
+// Stub Kakadu Library calls
+kdu_tile_comp kdu_tile::access_component(int ) { kdu_tile_comp a; return a; }
+void kdu_tile::close(kdu_thread_env* ) { }
+int kdu_tile::get_num_components() { return 0; }
+bool kdu_tile::get_ycc() { return false; }
+void kdu_tile::set_components_of_interest(int , const int* ) { }
+kdu_resolution kdu_tile_comp::access_resolution() { kdu_resolution a; return a; }
+int kdu_tile_comp::get_bit_depth(bool ) { return 8; }
+bool kdu_tile_comp::get_reversible() { return false; }
+kdu_subband kdu_resolution::access_subband(int ) { kdu_subband a; return a; }
+void kdu_resolution::get_dims(kdu_dims& ) { }
+int kdu_resolution::which() { return 0; }
+kdu_decoder::kdu_decoder(kdu_subband , kdu_sample_allocator*, bool , float, int, kdu_thread_env*, kdu_thread_queue*) { }
+kdu_synthesis::kdu_synthesis(kdu_resolution, kdu_sample_allocator*, bool, float, kdu_thread_env*, kdu_thread_queue*) { }
+kdu_params::kdu_params(const char*, bool, bool, bool, bool, bool) { }
+kdu_params::~kdu_params() { }
+void kdu_params::set(const char* , int , int , bool ) { }
+void kdu_params::set(const char* , int , int , int ) { }
+void kdu_params::finalize_all(bool ) { }
+void kdu_params::copy_from(kdu_params*, int, int, int, int, int, bool, bool, bool) { }
+bool kdu_params::parse_string(const char*) { return false; }
+bool kdu_params::get(const char*, int, int, bool&, bool, bool, bool) { return false; }
+bool kdu_params::get(const char*, int, int, float&, bool, bool, bool) { return false; }
+bool kdu_params::get(const char*, int, int, int&, bool, bool, bool) { return false; }
+kdu_params* kdu_params::access_relation(int, int, int, bool) { return NULL; }
+kdu_params* kdu_params::access_cluster(const char*) { return NULL; }
+void kdu_codestream::set_fast() { }
+void kdu_codestream::set_fussy() { }
+void kdu_codestream::get_dims(int, kdu_dims&, bool ) { }
+void kdu_codestream::change_appearance(bool, bool, bool) { }
+void kdu_codestream::get_tile_dims(kdu_coords, int, kdu_dims&, bool ) { }
+void kdu_codestream::destroy() { }
+void kdu_codestream::collect_timing_stats(int ) { }
+void kdu_codestream::set_max_bytes(kdu_long, bool, bool ) { }
+void kdu_codestream::get_valid_tiles(kdu_dims& ) { }
+void kdu_codestream::create(siz_params*, kdu_compressed_target*, kdu_dims*, int, kdu_long ) { }
+void kdu_codestream::create(kdu_compressed_source*, kdu_thread_env*) { }
+void kdu_codestream::apply_input_restrictions( int, int, int, int, kdu_dims*, kdu_component_access_mode ) { }
+void kdu_codestream::get_subsampling(int , kdu_coords&, bool ) { }
+void kdu_codestream::flush(kdu_long *, int , kdu_uint16 *, bool, bool, double, kdu_thread_env*) { }
+void kdu_codestream::set_resilient(bool ) { }
+int kdu_codestream::get_num_components(bool ) { return 0; }
+siz_params* kdu_codestream::access_siz() { return NULL; }
+kdu_tile kdu_codestream::open_tile(kdu_coords , kdu_thread_env* ) { kdu_tile a; return a; }
+kdu_codestream_comment kdu_codestream::add_comment() { kdu_codestream_comment a; return a; }
+bool kdu_codestream_comment::put_text(const char*) { return false; }
+void kdu_customize_warnings(kdu_message*) { }
+void kdu_customize_errors(kdu_message*) { }
+void kdu_convert_ycc_to_rgb(kdu_line_buf&, kdu_line_buf&, kdu_line_buf&, int) { }
+kdu_long kdu_multi_analysis::create(kdu_codestream, kdu_tile, bool, kdu_roi_image*, bool, int, kdu_thread_env*, kdu_thread_queue*, bool ) { kdu_long a = 0; return a; }
+siz_params::siz_params() : kdu_params(NULL, false, false, false, false, false) { }
+void siz_params::finalize(bool ) { }
+void siz_params::copy_with_xforms(kdu_params*, int, int, bool, bool, bool) { }
+int siz_params::write_marker_segment(kdu_output*, kdu_params*, int) { return 0; }
+bool siz_params::check_marker_segment(kdu_uint16, int, kdu_byte a[], int&) { return false; }
+bool siz_params::read_marker_segment(kdu_uint16, int, kdu_byte a[], int) { return false; }
+
+// -------------------------------------------------------------------------------------------
+// TUT
+// -------------------------------------------------------------------------------------------
+
+namespace tut
+{
+ // Test wrapper declarations
+ struct llimagej2ckdu_test
+ {
+ // Derived test class
+ class LLTestImageJ2CKDU : public LLImageJ2CKDU
+ {
+ public:
+ // Provides public access to some protected methods for testing
+ BOOL callGetMetadata(LLImageJ2C &base) { return getMetadata(base); }
+ BOOL callDecodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)
+ {
+ return decodeImpl(base, raw_image, decode_time, first_channel, max_channel_count);
+ }
+ BOOL callEncodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text)
+ {
+ return encodeImpl(base, raw_image, comment_text);
+ }
+ };
+ // Instance to be tested
+ LLTestImageJ2CKDU* mImage;
+
+ // Constructor and destructor of the test wrapper
+ llimagej2ckdu_test()
+ {
+ mImage = new LLTestImageJ2CKDU;
+ }
+ ~llimagej2ckdu_test()
+ {
+ delete mImage;
+ }
+ };
+
+ // Tut templating thingamagic: test group, object and test instance
+ typedef test_group<llimagej2ckdu_test> llimagej2ckdu_t;
+ typedef llimagej2ckdu_t::object llimagej2ckdu_object_t;
+ tut::llimagej2ckdu_t tut_llimagej2ckdu("LLImageJ2CKDU");
+
+ // ---------------------------------------------------------------------------------------
+ // Test functions
+ // Notes:
+ // * Test as many as you possibly can without requiring a full blown simulation of everything
+ // * The tests are executed in sequence so the test instance state may change between calls
+ // * Remember that you cannot test private methods with tut
+ // ---------------------------------------------------------------------------------------
+
+ // Test 1 : test getMetadata()
+ template<> template<>
+ void llimagej2ckdu_object_t::test<1>()
+ {
+ LLImageJ2C* image = new LLImageJ2C();
+ BOOL res = mImage->callGetMetadata(*image);
+ // Trying to set up a data stream with all NIL values and stubbed KDU will "work" and return TRUE
+ // Note that is linking with KDU, that call will throw an exception and fail, returning FALSE
+ ensure("getMetadata() test failed", res == TRUE);
+ }
+
+ // Test 2 : test decodeImpl()
+ template<> template<>
+ void llimagej2ckdu_object_t::test<2>()
+ {
+ LLImageJ2C* image = new LLImageJ2C();
+ LLImageRaw* raw = new LLImageRaw();
+ BOOL res = mImage->callDecodeImpl(*image, *raw, 0.0, 0, 0);
+ // Decoding returns TRUE whenever there's nothing else to do, including if decoding failed, so we'll get TRUE here
+ ensure("decodeImpl() test failed", res == TRUE);
+ }
+
+ // Test 3 : test encodeImpl()
+ template<> template<>
+ void llimagej2ckdu_object_t::test<3>()
+ {
+ LLImageJ2C* image = new LLImageJ2C();
+ LLImageRaw* raw = new LLImageRaw();
+ BOOL res = mImage->callEncodeImpl(*image, *raw, NULL);
+ // Encoding returns TRUE unless an exception was raised, so we'll get TRUE here though nothing really was done
+ ensure("encodeImpl() test failed", res == TRUE);
+ }
+}
diff --git a/indra/llmath/tests/m3math_test.cpp b/indra/llmath/tests/m3math_test.cpp
index 8abf61b740..e4d31996a3 100644
--- a/indra/llmath/tests/m3math_test.cpp
+++ b/indra/llmath/tests/m3math_test.cpp
@@ -280,7 +280,6 @@ namespace tut
llmat_obj.setRows(llvec1, llvec2, llvec3);
llmat_obj.orthogonalize();
- skip("Grr, LLMatrix3::orthogonalize test is failing. Has it ever worked?");
ensure("LLMatrix3::orthogonalize failed ",
is_approx_equal(0.19611613f, llmat_obj.mMatrix[0][0]) &&
is_approx_equal(0.78446454f, llmat_obj.mMatrix[0][1]) &&
diff --git a/indra/llplugin/CMakeLists.txt b/indra/llplugin/CMakeLists.txt
index d3a73058c4..1dc05e0b20 100644
--- a/indra/llplugin/CMakeLists.txt
+++ b/indra/llplugin/CMakeLists.txt
@@ -20,6 +20,7 @@ include_directories(
${LLRENDER_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS}
${LLWINDOW_INCLUDE_DIRS}
+ ${LLQTWEBKIT_INCLUDE_DIR}
)
set(llplugin_SOURCE_FILES
diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index 69ed0fb09c..595c470a19 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -160,7 +160,7 @@ void LLPluginClassMedia::idle(void)
mPlugin->idle();
}
- if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()))
+ if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()) || (mOwner == NULL))
{
// Can't process a size change at this time
}
@@ -522,7 +522,15 @@ bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifie
}
break;
}
-
+
+#if LL_DARWIN
+ if(modifiers & MASK_ALT)
+ {
+ // Option-key modified characters should be handled by the unicode input path instead of this one.
+ result = false;
+ }
+#endif
+
if(result)
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "key_event");
@@ -674,7 +682,21 @@ void LLPluginClassMedia::sendPickFileResponse(const std::string &file)
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file_response");
message.setValue("file", file);
- if(mPlugin->isBlocked())
+ if(mPlugin && mPlugin->isBlocked())
+ {
+ // If the plugin sent a blocking pick-file request, the response should unblock it.
+ message.setValueBoolean("blocking_response", true);
+ }
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::sendAuthResponse(bool ok, const std::string &username, const std::string &password)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_response");
+ message.setValueBoolean("ok", ok);
+ message.setValue("username", username);
+ message.setValue("password", password);
+ if(mPlugin && mPlugin->isBlocked())
{
// If the plugin sent a blocking pick-file request, the response should unblock it.
message.setValueBoolean("blocking_response", true);
@@ -947,6 +969,12 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
{
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PICK_FILE_REQUEST);
}
+ else if(message_name == "auth_request")
+ {
+ mAuthURL = message.getValue("url");
+ mAuthRealm = message.getValue("realm");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_AUTH_REQUEST);
+ }
else
{
LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
@@ -1019,6 +1047,15 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_GEOMETRY_CHANGE);
}
+ else if(message_name == "link_hovered")
+ {
+ // text is not currently used -- the tooltip hover text is taken from the "title".
+ mHoverLink = message.getValue("link");
+ mHoverText = message.getValue("title");
+ // message.getValue("text");
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LINK_HOVERED);
+ }
else
{
LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
@@ -1192,6 +1229,20 @@ void LLPluginClassMedia::proxyWindowClosed(const std::string &uuid)
sendMessage(message);
}
+void LLPluginClassMedia::ignore_ssl_cert_errors(bool ignore)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "ignore_ssl_cert_errors");
+ message.setValueBoolean("ignore", ignore);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::addCertificateFilePath(const std::string& path)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "add_certificate_file_path");
+ message.setValue("path", path);
+ sendMessage(message);
+}
+
void LLPluginClassMedia::crashPlugin()
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash");
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index 9cb67fe909..c826e13c40 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -85,6 +85,8 @@ public:
void setBackgroundColor(LLColor4 color) { mBackgroundColor = color; };
+ void setOwner(LLPluginClassMediaOwner *owner) { mOwner = owner; };
+
// Returns true if all of the texture parameters (depth, format, size, and texture size) are set up and consistent.
// This will initially be false, and will also be false for some time after setSize while the resize is processed.
// Note that if this returns true, it is safe to use all the get() functions above without checking for invalid return values
@@ -159,6 +161,8 @@ public:
void sendPickFileResponse(const std::string &file);
+ void sendAuthResponse(bool ok, const std::string &username, const std::string &password);
+
// Valid after a MEDIA_EVENT_CURSOR_CHANGED event
std::string getCursorName() const { return mCursorName; };
@@ -198,6 +202,8 @@ public:
void setBrowserUserAgent(const std::string& user_agent);
void proxyWindowOpened(const std::string &target, const std::string &uuid);
void proxyWindowClosed(const std::string &uuid);
+ void ignore_ssl_cert_errors(bool ignore);
+ void addCertificateFilePath(const std::string& path);
// This is valid after MEDIA_EVENT_NAVIGATE_BEGIN or MEDIA_EVENT_NAVIGATE_COMPLETE
std::string getNavigateURI() const { return mNavigateURI; };
@@ -231,7 +237,15 @@ public:
S32 getGeometryY() const { return mGeometryY; };
S32 getGeometryWidth() const { return mGeometryWidth; };
S32 getGeometryHeight() const { return mGeometryHeight; };
+
+ // These are valid during MEDIA_EVENT_AUTH_REQUEST
+ std::string getAuthURL() const { return mAuthURL; };
+ std::string getAuthRealm() const { return mAuthRealm; };
+ // These are valid during MEDIA_EVENT_LINK_HOVERED
+ std::string getHoverText() const { return mHoverText; };
+ std::string getHoverLink() const { return mHoverLink; };
+
std::string getMediaName() const { return mMediaName; };
std::string getMediaDescription() const { return mMediaDescription; };
@@ -369,6 +383,10 @@ protected:
S32 mGeometryY;
S32 mGeometryWidth;
S32 mGeometryHeight;
+ std::string mAuthURL;
+ std::string mAuthRealm;
+ std::string mHoverText;
+ std::string mHoverLink;
/////////////////////////////////////////
// media_time class
diff --git a/indra/llplugin/llpluginclassmediaowner.h b/indra/llplugin/llpluginclassmediaowner.h
index c9efff216c..42e93cc6d7 100644
--- a/indra/llplugin/llpluginclassmediaowner.h
+++ b/indra/llplugin/llpluginclassmediaowner.h
@@ -59,7 +59,11 @@ public:
MEDIA_EVENT_GEOMETRY_CHANGE, // The plugin requested its window geometry be changed (per the javascript window interface)
MEDIA_EVENT_PLUGIN_FAILED_LAUNCH, // The plugin failed to launch
- MEDIA_EVENT_PLUGIN_FAILED // The plugin died unexpectedly
+ MEDIA_EVENT_PLUGIN_FAILED, // The plugin died unexpectedly
+
+ MEDIA_EVENT_AUTH_REQUEST, // The plugin wants to display an auth dialog
+
+ MEDIA_EVENT_LINK_HOVERED // Got a "link hovered" event from the plugin
} EMediaEvent;
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index 864f3f699e..33ab2e93b5 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -111,6 +111,7 @@ set(llui_SOURCE_FILES
llviewmodel.cpp
llview.cpp
llviewquery.cpp
+ llwindowshade.cpp
)
set(llui_HEADER_FILES
@@ -210,6 +211,7 @@ set(llui_HEADER_FILES
llviewmodel.h
llview.h
llviewquery.h
+ llwindowshade.h
)
set_source_files_properties(${llui_HEADER_FILES}
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 1265733bf5..d30697e178 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -2910,7 +2910,9 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::str
params.from_xui = true;
applyXUILayout(params, parent);
initFromParams(params);
-
+ // chrome floaters don't take focus at all
+ setFocusRoot(!getIsChrome());
+
initFloater(params);
LLMultiFloater* last_host = LLFloater::getFloaterHost();
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index ac30fce392..19ac4c58a8 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -38,6 +38,12 @@
static LLDefaultChildRegistry::Register<LLLayoutStack> register_layout_stack("layout_stack");
static LLLayoutStack::LayoutStackRegistry::Register<LLLayoutPanel> register_layout_panel("layout_panel");
+void LLLayoutStack::OrientationNames::declareValues()
+{
+ declare("horizontal", HORIZONTAL);
+ declare("vertical", VERTICAL);
+}
+
//
// LLLayoutPanel
//
@@ -47,47 +53,47 @@ LLLayoutPanel::LLLayoutPanel(const Params& p)
mMaxDim(p.max_dim),
mAutoResize(p.auto_resize),
mUserResize(p.user_resize),
- mCollapsed(FALSE),
- mCollapseAmt(0.f),
- mVisibleAmt(1.f), // default to fully visible
- mResizeBar(NULL)
- {
+ mCollapsed(FALSE),
+ mCollapseAmt(0.f),
+ mVisibleAmt(1.f), // default to fully visible
+ mResizeBar(NULL)
+{
// panels initialized as hidden should not start out partially visible
if (!getVisible())
- {
+ {
mVisibleAmt = 0.f;
- }
- }
+ }
+}
void LLLayoutPanel::initFromParams(const Params& p)
- {
+{
LLPanel::initFromParams(p);
setFollowsNone();
- }
+}
LLLayoutPanel::~LLLayoutPanel()
- {
- // probably not necessary, but...
- delete mResizeBar;
- mResizeBar = NULL;
- }
+{
+ // probably not necessary, but...
+ delete mResizeBar;
+ mResizeBar = NULL;
+}
F32 LLLayoutPanel::getCollapseFactor(LLLayoutStack::ELayoutOrientation orientation)
- {
+{
if (orientation == LLLayoutStack::HORIZONTAL)
- {
- F32 collapse_amt =
- clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)mMinDim / (F32)llmax(1, getRect().getWidth()));
- return mVisibleAmt * collapse_amt;
- }
- else
+ {
+ F32 collapse_amt =
+ clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)mMinDim / (F32)llmax(1, getRect().getWidth()));
+ return mVisibleAmt * collapse_amt;
+ }
+ else
{
F32 collapse_amt =
clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, llmin(1.f, (F32)mMinDim / (F32)llmax(1, getRect().getHeight())));
return mVisibleAmt * collapse_amt;
- }
}
+}
//
// LLLayoutStack
@@ -109,7 +115,7 @@ LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p)
mMinWidth(0),
mMinHeight(0),
mPanelSpacing(p.border_size),
- mOrientation((p.orientation() == "vertical") ? VERTICAL : HORIZONTAL),
+ mOrientation(p.orientation),
mAnimate(p.animate),
mAnimatedThisFrame(false),
mClip(p.clip),
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index 2fc6164d7a..4ac8ef0ee9 100644
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -37,12 +37,24 @@ class LLLayoutPanel;
class LLLayoutStack : public LLView, public LLInstanceTracker<LLLayoutStack>
{
public:
+ typedef enum e_layout_orientation
+ {
+ HORIZONTAL,
+ VERTICAL
+ } ELayoutOrientation;
+
+ struct OrientationNames
+ : public LLInitParam::TypeValuesHelper<ELayoutOrientation, OrientationNames>
+ {
+ static void declareValues();
+ };
+
struct LayoutStackRegistry : public LLChildRegistry<LayoutStackRegistry>
{};
struct Params : public LLInitParam::Block<Params, LLView::Params>
{
- Mandatory<std::string> orientation;
+ Mandatory<ELayoutOrientation, OrientationNames> orientation;
Optional<S32> border_size;
Optional<bool> animate,
clip;
@@ -54,12 +66,6 @@ public:
typedef LayoutStackRegistry child_registry_t;
- typedef enum e_layout_orientation
- {
- HORIZONTAL,
- VERTICAL
- } ELayoutOrientation;
-
virtual ~LLLayoutStack();
/*virtual*/ void draw();
@@ -171,6 +177,9 @@ public:
~LLLayoutPanel();
void initFromParams(const Params& p);
+ void setMinDim(S32 value) { mMinDim = value; }
+ void setMaxDim(S32 value) { mMaxDim = value; }
+
protected:
LLLayoutPanel(const Params& p) ;
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index aed391c780..7e348656a9 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -88,6 +88,7 @@ LLLineEditor::Params::Params()
revert_on_esc("revert_on_esc", true),
commit_on_focus_lost("commit_on_focus_lost", true),
ignore_tab("ignore_tab", true),
+ is_password("is_password", false),
cursor_color("cursor_color"),
text_color("text_color"),
text_readonly_color("text_readonly_color"),
@@ -129,7 +130,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
mBorderThickness( 0 ),
mIgnoreArrowKeys( FALSE ),
mIgnoreTab( p.ignore_tab ),
- mDrawAsterixes( FALSE ),
+ mDrawAsterixes( p.is_password ),
mSelectAllonFocusReceived( p.select_on_focus ),
mPassDelete(FALSE),
mReadOnly(FALSE),
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index ce2dfdeeb8..723423a5b9 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -85,7 +85,8 @@ public:
Optional<bool> select_on_focus,
revert_on_esc,
commit_on_focus_lost,
- ignore_tab;
+ ignore_tab,
+ is_password;
// colors
Optional<LLUIColor> cursor_color,
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index c347e15792..cd0f0e36b0 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -82,6 +82,7 @@ LLNotificationForm::FormButton::FormButton()
LLNotificationForm::FormInput::FormInput()
: type("type"),
+ text("text"),
max_length_chars("max_length_chars"),
width("width", 0),
value("value")
@@ -421,7 +422,7 @@ LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Par
it != end_it;
++it)
{
- mUniqueContext.push_back(it->key);
+ mUniqueContext.push_back(it->value);
}
lldebugs << "notification \"" << mName << "\": tag count is " << p.tags.size() << llendl;
@@ -792,13 +793,19 @@ bool LLNotification::isEquivalentTo(LLNotificationPtr that) const
{
const LLSD& these_substitutions = this->getSubstitutions();
const LLSD& those_substitutions = that->getSubstitutions();
+ const LLSD& this_payload = this->getPayload();
+ const LLSD& that_payload = that->getPayload();
// highlander bit sez there can only be one of these
for (std::vector<std::string>::const_iterator it = mTemplatep->mUniqueContext.begin(), end_it = mTemplatep->mUniqueContext.end();
it != end_it;
++it)
{
- if (these_substitutions.get(*it).asString() != those_substitutions.get(*it).asString())
+ // if templates differ in either substitution strings or payload with the given field name
+ // then they are considered inequivalent
+ // use of get() avoids converting the LLSD value to a map as the [] operator would
+ if (these_substitutions.get(*it).asString() != those_substitutions.get(*it).asString()
+ || this_payload.get(*it).asString() != that_payload.get(*it).asString())
{
return false;
}
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index f8f4469958..34d3537781 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -195,6 +195,7 @@ public:
Mandatory<std::string> type;
Optional<S32> width;
Optional<S32> max_length_chars;
+ Optional<std::string> text;
Optional<std::string> value;
FormInput();
diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h
index 5a6ab40a2e..eff572b553 100644
--- a/indra/llui/llnotificationtemplate.h
+++ b/indra/llui/llnotificationtemplate.h
@@ -74,11 +74,13 @@ struct LLNotificationTemplate
struct UniquenessContext : public LLInitParam::Block<UniquenessContext>
{
- Mandatory<std::string> key;
+ Mandatory<std::string> value;
UniquenessContext()
- : key("key")
- {}
+ : value("value")
+ {
+ addSynonym(value, "key");
+ }
};
@@ -88,7 +90,7 @@ struct LLNotificationTemplate
// this idiom allows
// <notification unique="true">
// as well as
- // <notification> <unique> <context key=""/> </unique>...
+ // <notification> <unique> <context></context> </unique>...
Optional<bool> dummy_val;
public:
Multiple<UniquenessContext> contexts;
@@ -243,8 +245,8 @@ struct LLNotificationTemplate
// (used for things like progress indications, or repeating warnings
// like "the grid is going down in N minutes")
bool mUnique;
- // if we want to be unique only if a certain part of the payload is constant
- // specify the field names for the payload. The notification will only be
+ // if we want to be unique only if a certain part of the payload or substitutions args
+ // are constant specify the field names for the payload. The notification will only be
// combined if all of the fields named in the context are identical in the
// new and the old notification; otherwise, the notification will be
// duplicated. This is to support suppressing duplicate offers from the same
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index afd60cbb3e..0a06b5e74f 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -827,7 +827,7 @@ LLUICtrl* LLUICtrl::findRootMostFocusRoot()
{
LLUICtrl* focus_root = NULL;
LLUICtrl* next_view = this;
- while(next_view)
+ while(next_view && next_view->hasTabStop())
{
if (next_view->isFocusRoot())
{
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index a5d8e31640..d2bbd663b8 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -413,14 +413,9 @@ public:
LLControlVariable *findControl(const std::string& name);
- // Moved setValue(), getValue(), setControlValue(), setControlName(),
- // controlListener() to LLUICtrl because an LLView is NOT assumed to
- // contain a value. If that's what you want, use LLUICtrl instead.
-// virtual bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata);
-
const child_list_t* getChildList() const { return &mChildList; }
- const child_list_const_iter_t beginChild() { return mChildList.begin(); }
- const child_list_const_iter_t endChild() { return mChildList.end(); }
+ child_list_const_iter_t beginChild() const { return mChildList.begin(); }
+ child_list_const_iter_t endChild() const { return mChildList.end(); }
// LLMouseHandler functions
// Default behavior is to pass events to children
diff --git a/indra/llui/llwindowshade.cpp b/indra/llui/llwindowshade.cpp
new file mode 100644
index 0000000000..77e94385d4
--- /dev/null
+++ b/indra/llui/llwindowshade.cpp
@@ -0,0 +1,328 @@
+/**
+ * @file LLWindowShade.cpp
+ * @brief Notification dialog that slides down and optionally disabled a piece of UI
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llwindowshade.h"
+
+#include "lllayoutstack.h"
+#include "lltextbox.h"
+#include "lliconctrl.h"
+#include "llbutton.h"
+#include "llcheckboxctrl.h"
+#include "lllineeditor.h"
+
+const S32 MIN_NOTIFICATION_AREA_HEIGHT = 30;
+const S32 MAX_NOTIFICATION_AREA_HEIGHT = 100;
+
+LLWindowShade::Params::Params()
+: bg_image("bg_image"),
+ modal("modal", false),
+ text_color("text_color"),
+ can_close("can_close", true)
+{
+ mouse_opaque = false;
+}
+
+LLWindowShade::LLWindowShade(const LLWindowShade::Params& params)
+: LLUICtrl(params),
+ mNotification(params.notification),
+ mModal(params.modal),
+ mFormHeight(0),
+ mTextColor(params.text_color)
+{
+ setFocusRoot(true);
+}
+
+void LLWindowShade::initFromParams(const LLWindowShade::Params& params)
+{
+ LLUICtrl::initFromParams(params);
+
+ LLLayoutStack::Params layout_p;
+ layout_p.name = "notification_stack";
+ layout_p.rect = params.rect;
+ layout_p.follows.flags = FOLLOWS_ALL;
+ layout_p.mouse_opaque = false;
+ layout_p.orientation = LLLayoutStack::VERTICAL;
+ layout_p.border_size = 0;
+
+ LLLayoutStack* stackp = LLUICtrlFactory::create<LLLayoutStack>(layout_p);
+ addChild(stackp);
+
+ LLLayoutPanel::Params panel_p;
+ panel_p.rect = LLRect(0, 30, 800, 0);
+ panel_p.name = "notification_area";
+ panel_p.visible = false;
+ panel_p.user_resize = false;
+ panel_p.background_visible = true;
+ panel_p.bg_alpha_image = params.bg_image;
+ panel_p.auto_resize = false;
+ LLLayoutPanel* notification_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p);
+ stackp->addChild(notification_panel);
+
+ panel_p = LLUICtrlFactory::getDefaultParams<LLLayoutPanel>();
+ panel_p.auto_resize = true;
+ panel_p.user_resize = false;
+ panel_p.rect = params.rect;
+ panel_p.name = "background_area";
+ panel_p.mouse_opaque = false;
+ panel_p.background_visible = false;
+ panel_p.bg_alpha_color = LLColor4(0.f, 0.f, 0.f, 0.2f);
+ LLLayoutPanel* dummy_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p);
+ stackp->addChild(dummy_panel);
+
+ layout_p = LLUICtrlFactory::getDefaultParams<LLLayoutStack>();
+ layout_p.rect = LLRect(0, 30, 800, 0);
+ layout_p.follows.flags = FOLLOWS_ALL;
+ layout_p.orientation = LLLayoutStack::HORIZONTAL;
+ stackp = LLUICtrlFactory::create<LLLayoutStack>(layout_p);
+ notification_panel->addChild(stackp);
+
+ panel_p = LLUICtrlFactory::getDefaultParams<LLLayoutPanel>();
+ panel_p.rect.height = 30;
+ LLLayoutPanel* panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p);
+ stackp->addChild(panel);
+
+ LLIconCtrl::Params icon_p;
+ icon_p.name = "notification_icon";
+ icon_p.rect = LLRect(5, 23, 21, 8);
+ panel->addChild(LLUICtrlFactory::create<LLIconCtrl>(icon_p));
+
+ LLTextBox::Params text_p;
+ text_p.rect = LLRect(31, 20, panel->getRect().getWidth() - 5, 0);
+ text_p.follows.flags = FOLLOWS_ALL;
+ text_p.text_color = mTextColor;
+ text_p.font = LLFontGL::getFontSansSerifSmall();
+ text_p.font.style = "BOLD";
+ text_p.name = "notification_text";
+ text_p.use_ellipses = true;
+ text_p.wrap = true;
+ panel->addChild(LLUICtrlFactory::create<LLTextBox>(text_p));
+
+ panel_p = LLUICtrlFactory::getDefaultParams<LLLayoutPanel>();
+ panel_p.auto_resize = false;
+ panel_p.user_resize = false;
+ panel_p.name="form_elements";
+ panel_p.rect = LLRect(0, 30, 130, 0);
+ LLLayoutPanel* form_elements_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p);
+ stackp->addChild(form_elements_panel);
+
+ if (params.can_close)
+ {
+ panel_p = LLUICtrlFactory::getDefaultParams<LLLayoutPanel>();
+ panel_p.auto_resize = false;
+ panel_p.user_resize = false;
+ panel_p.rect = LLRect(0, 30, 25, 0);
+ LLLayoutPanel* close_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p);
+ stackp->addChild(close_panel);
+
+ LLButton::Params button_p;
+ button_p.name = "close_notification";
+ button_p.rect = LLRect(5, 23, 21, 7);
+ button_p.image_color.control="DkGray_66";
+ button_p.image_unselected.name="Icon_Close_Foreground";
+ button_p.image_selected.name="Icon_Close_Press";
+ button_p.click_callback.function = boost::bind(&LLWindowShade::onCloseNotification, this);
+
+ close_panel->addChild(LLUICtrlFactory::create<LLButton>(button_p));
+ }
+
+ LLSD payload = mNotification->getPayload();
+
+ LLNotificationFormPtr formp = mNotification->getForm();
+ LLLayoutPanel& notification_area = getChildRef<LLLayoutPanel>("notification_area");
+ notification_area.getChild<LLUICtrl>("notification_icon")->setValue(mNotification->getIcon());
+ notification_area.getChild<LLUICtrl>("notification_text")->setValue(mNotification->getMessage());
+ notification_area.getChild<LLUICtrl>("notification_text")->setToolTip(mNotification->getMessage());
+
+ LLNotificationForm::EIgnoreType ignore_type = formp->getIgnoreType();
+ LLLayoutPanel& form_elements = notification_area.getChildRef<LLLayoutPanel>("form_elements");
+ form_elements.deleteAllChildren();
+
+ const S32 FORM_PADDING_HORIZONTAL = 10;
+ const S32 FORM_PADDING_VERTICAL = 3;
+ const S32 WIDGET_HEIGHT = 24;
+ const S32 LINE_EDITOR_WIDTH = 120;
+ S32 cur_x = FORM_PADDING_HORIZONTAL;
+ S32 cur_y = FORM_PADDING_VERTICAL + WIDGET_HEIGHT;
+ S32 form_width = cur_x;
+
+ if (ignore_type != LLNotificationForm::IGNORE_NO)
+ {
+ LLCheckBoxCtrl::Params checkbox_p;
+ checkbox_p.name = "ignore_check";
+ checkbox_p.rect = LLRect(cur_x, cur_y, cur_x, cur_y - WIDGET_HEIGHT);
+ checkbox_p.label = formp->getIgnoreMessage();
+ checkbox_p.label_text.text_color = LLColor4::black;
+ checkbox_p.commit_callback.function = boost::bind(&LLWindowShade::onClickIgnore, this, _1);
+ checkbox_p.initial_value = formp->getIgnored();
+
+ LLCheckBoxCtrl* check = LLUICtrlFactory::create<LLCheckBoxCtrl>(checkbox_p);
+ check->setRect(check->getBoundingRect());
+ form_elements.addChild(check);
+ cur_x = check->getRect().mRight + FORM_PADDING_HORIZONTAL;
+ form_width = llmax(form_width, cur_x);
+ }
+
+ for (S32 i = 0; i < formp->getNumElements(); i++)
+ {
+ LLSD form_element = formp->getElement(i);
+ std::string type = form_element["type"].asString();
+ if (type == "button")
+ {
+ LLButton::Params button_p;
+ button_p.name = form_element["name"];
+ button_p.label = form_element["text"];
+ button_p.rect = LLRect(cur_x, cur_y, cur_x, cur_y - WIDGET_HEIGHT);
+ button_p.click_callback.function = boost::bind(&LLWindowShade::onClickNotificationButton, this, form_element["name"].asString());
+ button_p.auto_resize = true;
+
+ LLButton* button = LLUICtrlFactory::create<LLButton>(button_p);
+ button->autoResize();
+ form_elements.addChild(button);
+
+ if (form_element["default"].asBoolean())
+ {
+ form_elements.setDefaultBtn(button);
+ }
+
+ cur_x = button->getRect().mRight + FORM_PADDING_HORIZONTAL;
+ form_width = llmax(form_width, cur_x);
+ }
+ else if (type == "text" || type == "password")
+ {
+ // if not at beginning of line...
+ if (cur_x != FORM_PADDING_HORIZONTAL)
+ {
+ // start new line
+ cur_x = FORM_PADDING_HORIZONTAL;
+ cur_y -= WIDGET_HEIGHT + FORM_PADDING_VERTICAL;
+ }
+ LLTextBox::Params label_p;
+ label_p.name = form_element["name"].asString() + "_label";
+ label_p.rect = LLRect(cur_x, cur_y, cur_x + LINE_EDITOR_WIDTH, cur_y - WIDGET_HEIGHT);
+ label_p.initial_value = form_element["text"];
+ label_p.text_color = mTextColor;
+ label_p.font_valign = LLFontGL::VCENTER;
+ label_p.v_pad = 5;
+ LLTextBox* textbox = LLUICtrlFactory::create<LLTextBox>(label_p);
+ textbox->reshapeToFitText();
+ textbox->reshape(textbox->getRect().getWidth(), form_elements.getRect().getHeight() - 2 * FORM_PADDING_VERTICAL);
+ form_elements.addChild(textbox);
+ cur_x = textbox->getRect().mRight + FORM_PADDING_HORIZONTAL;
+
+ LLLineEditor::Params line_p;
+ line_p.name = form_element["name"];
+ line_p.keystroke_callback = boost::bind(&LLWindowShade::onEnterNotificationText, this, _1, form_element["name"].asString());
+ line_p.is_password = type == "password";
+ line_p.rect = LLRect(cur_x, cur_y, cur_x + LINE_EDITOR_WIDTH, cur_y - WIDGET_HEIGHT);
+
+ LLLineEditor* line_editor = LLUICtrlFactory::create<LLLineEditor>(line_p);
+ form_elements.addChild(line_editor);
+ form_width = llmax(form_width, cur_x + LINE_EDITOR_WIDTH + FORM_PADDING_HORIZONTAL);
+
+ // reset to start of next line
+ cur_x = FORM_PADDING_HORIZONTAL;
+ cur_y -= WIDGET_HEIGHT + FORM_PADDING_VERTICAL;
+ }
+ }
+
+ mFormHeight = form_elements.getRect().getHeight() - (cur_y - FORM_PADDING_VERTICAL) + WIDGET_HEIGHT;
+ form_elements.reshape(form_width, mFormHeight);
+ form_elements.setMinDim(form_width);
+
+ // move all form elements back onto form surface
+ S32 delta_y = WIDGET_HEIGHT + FORM_PADDING_VERTICAL - cur_y;
+ for (child_list_const_iter_t it = form_elements.getChildList()->begin(), end_it = form_elements.getChildList()->end();
+ it != end_it;
+ ++it)
+ {
+ (*it)->translate(0, delta_y);
+ }
+}
+
+void LLWindowShade::show()
+{
+ getChildRef<LLLayoutPanel>("notification_area").setVisible(true);
+ getChildRef<LLLayoutPanel>("background_area").setBackgroundVisible(mModal);
+
+ setMouseOpaque(mModal);
+}
+
+void LLWindowShade::draw()
+{
+ LLRect message_rect = getChild<LLTextBox>("notification_text")->getTextBoundingRect();
+
+ LLLayoutPanel* notification_area = getChild<LLLayoutPanel>("notification_area");
+
+ notification_area->reshape(notification_area->getRect().getWidth(),
+ llclamp(message_rect.getHeight() + 10,
+ llmin(mFormHeight, MAX_NOTIFICATION_AREA_HEIGHT),
+ MAX_NOTIFICATION_AREA_HEIGHT));
+
+ LLUICtrl::draw();
+ if (mNotification && !mNotification->isActive())
+ {
+ hide();
+ }
+}
+
+void LLWindowShade::hide()
+{
+ getChildRef<LLLayoutPanel>("notification_area").setVisible(false);
+ getChildRef<LLLayoutPanel>("background_area").setBackgroundVisible(false);
+
+ setMouseOpaque(false);
+}
+
+void LLWindowShade::onCloseNotification()
+{
+ LLNotifications::instance().cancel(mNotification);
+}
+
+void LLWindowShade::onClickIgnore(LLUICtrl* ctrl)
+{
+ bool check = ctrl->getValue().asBoolean();
+ if (mNotification && mNotification->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN)
+ {
+ // question was "show again" so invert value to get "ignore"
+ check = !check;
+ }
+ mNotification->setIgnored(check);
+}
+
+void LLWindowShade::onClickNotificationButton(const std::string& name)
+{
+ if (!mNotification) return;
+
+ mNotificationResponse[name] = true;
+
+ mNotification->respond(mNotificationResponse);
+}
+
+void LLWindowShade::onEnterNotificationText(LLUICtrl* ctrl, const std::string& name)
+{
+ mNotificationResponse[name] = ctrl->getValue().asString();
+}
diff --git a/indra/llui/llwindowshade.h b/indra/llui/llwindowshade.h
new file mode 100644
index 0000000000..0047195929
--- /dev/null
+++ b/indra/llui/llwindowshade.h
@@ -0,0 +1,69 @@
+/**
+ * @file llwindowshade.h
+ * @brief Notification dialog that slides down and optionally disabled a piece of UI
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLWINDOWSHADE_H
+#define LL_LLWINDOWSHADE_H
+
+#include "lluictrl.h"
+#include "llnotifications.h"
+
+class LLWindowShade : public LLUICtrl
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Mandatory<LLNotificationPtr> notification;
+ Optional<LLUIImage*> bg_image;
+ Optional<LLUIColor> text_color;
+ Optional<bool> modal,
+ can_close;
+
+ Params();
+ };
+
+ void show();
+ /*virtual*/ void draw();
+ void hide();
+
+private:
+ friend class LLUICtrlFactory;
+
+ LLWindowShade(const Params& p);
+ void initFromParams(const Params& params);
+
+ void onCloseNotification();
+ void onClickNotificationButton(const std::string& name);
+ void onEnterNotificationText(LLUICtrl* ctrl, const std::string& name);
+ void onClickIgnore(LLUICtrl* ctrl);
+
+ LLNotificationPtr mNotification;
+ LLSD mNotificationResponse;
+ bool mModal;
+ S32 mFormHeight;
+ LLUIColor mTextColor;
+};
+
+#endif // LL_LLWINDOWSHADE_H
diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt
index bf3233f386..4d2677fd91 100644
--- a/indra/llwindow/CMakeLists.txt
+++ b/indra/llwindow/CMakeLists.txt
@@ -59,12 +59,13 @@ set(viewer_HEADER_FILES
# Libraries on which this library depends, needed for Linux builds
# Sort by high-level to low-level
-if (NOT LINUX OR VIEWER)
+if (LINUX AND VIEWER)
set(llwindow_LINK_LIBRARIES
${UI_LIBRARIES} # for GTK
${SDL_LIBRARY}
+ fontconfig # For FCInit and other FC* functions.
)
-endif (NOT LINUX OR VIEWER)
+endif (LINUX AND VIEWER)
if (DARWIN)
list(APPEND llwindow_SOURCE_FILES
diff --git a/indra/media_plugins/example/media_plugin_example.cpp b/indra/media_plugins/example/media_plugin_example.cpp
index f8a871930e..da7de01799 100644
--- a/indra/media_plugins/example/media_plugin_example.cpp
+++ b/indra/media_plugins/example/media_plugin_example.cpp
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
@@ -39,48 +39,48 @@
////////////////////////////////////////////////////////////////////////////////
//
class MediaPluginExample :
- public MediaPluginBase
+ public MediaPluginBase
{
- public:
- MediaPluginExample( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data );
- ~MediaPluginExample();
-
- /*virtual*/ void receiveMessage( const char* message_string );
-
- private:
- bool init();
- void update( F64 milliseconds );
- void write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b );
- bool mFirstTime;
-
- time_t mLastUpdateTime;
- enum Constants { ENumObjects = 10 };
- unsigned char* mBackgroundPixels;
- int mColorR[ ENumObjects ];
- int mColorG[ ENumObjects ];
- int mColorB[ ENumObjects ];
- int mXpos[ ENumObjects ];
- int mYpos[ ENumObjects ];
- int mXInc[ ENumObjects ];
- int mYInc[ ENumObjects ];
- int mBlockSize[ ENumObjects ];
- bool mMouseButtonDown;
- bool mStopAction;
+ public:
+ MediaPluginExample( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data );
+ ~MediaPluginExample();
+
+ /*virtual*/ void receiveMessage( const char* message_string );
+
+ private:
+ bool init();
+ void update( F64 milliseconds );
+ void write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b );
+ bool mFirstTime;
+
+ time_t mLastUpdateTime;
+ enum Constants { ENumObjects = 10 };
+ unsigned char* mBackgroundPixels;
+ int mColorR[ ENumObjects ];
+ int mColorG[ ENumObjects ];
+ int mColorB[ ENumObjects ];
+ int mXpos[ ENumObjects ];
+ int mYpos[ ENumObjects ];
+ int mXInc[ ENumObjects ];
+ int mYInc[ ENumObjects ];
+ int mBlockSize[ ENumObjects ];
+ bool mMouseButtonDown;
+ bool mStopAction;
};
////////////////////////////////////////////////////////////////////////////////
//
MediaPluginExample::MediaPluginExample( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ) :
- MediaPluginBase( host_send_func, host_user_data )
+ MediaPluginBase( host_send_func, host_user_data )
{
- mFirstTime = true;
- mWidth = 0;
- mHeight = 0;
- mDepth = 4;
- mPixels = 0;
- mMouseButtonDown = false;
- mStopAction = false;
- mLastUpdateTime = 0;
+ mFirstTime = true;
+ mWidth = 0;
+ mHeight = 0;
+ mDepth = 4;
+ mPixels = 0;
+ mMouseButtonDown = false;
+ mStopAction = false;
+ mLastUpdateTime = 0;
}
////////////////////////////////////////////////////////////////////////////////
@@ -93,395 +93,320 @@ MediaPluginExample::~MediaPluginExample()
//
void MediaPluginExample::receiveMessage( const char* message_string )
{
- LLPluginMessage message_in;
-
- if ( message_in.parse( message_string ) >= 0 )
- {
- std::string message_class = message_in.getClass();
- std::string message_name = message_in.getName();
-
- if ( message_class == LLPLUGIN_MESSAGE_CLASS_BASE )
- {
- if ( message_name == "init" )
- {
- LLPluginMessage message( "base", "init_response" );
- LLSD versions = LLSD::emptyMap();
- versions[ LLPLUGIN_MESSAGE_CLASS_BASE ] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
- versions[ LLPLUGIN_MESSAGE_CLASS_MEDIA ] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
- versions[ LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER ] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION;
- message.setValueLLSD( "versions", versions );
-
- std::string plugin_version = "Example media plugin, Example Version 1.0.0.0";
- message.setValue( "plugin_version", plugin_version );
- sendMessage( message );
- }
- else
- if ( message_name == "idle" )
- {
- // no response is necessary here.
- F64 time = message_in.getValueReal( "time" );
-
- // Convert time to milliseconds for update()
- update( time );
- }
- else
- if ( message_name == "cleanup" )
- {
- // clean up here
- }
- else
- if ( message_name == "shm_added" )
- {
- SharedSegmentInfo info;
- info.mAddress = message_in.getValuePointer( "address" );
- info.mSize = ( size_t )message_in.getValueS32( "size" );
- std::string name = message_in.getValue( "name" );
-
- mSharedSegments.insert( SharedSegmentMap::value_type( name, info ) );
-
- }
- else
- if ( message_name == "shm_remove" )
- {
- std::string name = message_in.getValue( "name" );
-
- SharedSegmentMap::iterator iter = mSharedSegments.find( name );
- if( iter != mSharedSegments.end() )
- {
- if ( mPixels == iter->second.mAddress )
- {
- // This is the currently active pixel buffer.
- // Make sure we stop drawing to it.
- mPixels = NULL;
- mTextureSegmentName.clear();
- };
- mSharedSegments.erase( iter );
- }
- else
- {
- //std::cerr << "MediaPluginExample::receiveMessage: unknown shared memory region!" << std::endl;
- };
-
- // Send the response so it can be cleaned up.
- LLPluginMessage message( "base", "shm_remove_response" );
- message.setValue( "name", name );
- sendMessage( message );
- }
- else
- {
- //std::cerr << "MediaPluginExample::receiveMessage: unknown base message: " << message_name << std::endl;
- };
- }
- else
- if ( message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA )
- {
- if ( message_name == "init" )
- {
- // Plugin gets to decide the texture parameters to use.
- LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params" );
- message.setValueS32( "default_width", mWidth );
- message.setValueS32( "default_height", mHeight );
- message.setValueS32( "depth", mDepth );
- message.setValueU32( "internalformat", GL_RGBA );
- message.setValueU32( "format", GL_RGBA );
- message.setValueU32( "type", GL_UNSIGNED_BYTE );
- message.setValueBoolean( "coords_opengl", false );
- sendMessage( message );
- }
- else if ( message_name == "size_change" )
- {
- std::string name = message_in.getValue( "name" );
- S32 width = message_in.getValueS32( "width" );
- S32 height = message_in.getValueS32( "height" );
- S32 texture_width = message_in.getValueS32( "texture_width" );
- S32 texture_height = message_in.getValueS32( "texture_height" );
-
- if ( ! name.empty() )
- {
- // Find the shared memory region with this name
- SharedSegmentMap::iterator iter = mSharedSegments.find( name );
- if ( iter != mSharedSegments.end() )
- {
- mPixels = ( unsigned char* )iter->second.mAddress;
- mWidth = width;
- mHeight = height;
-
- mTextureWidth = texture_width;
- mTextureHeight = texture_height;
-
- init();
- };
- };
-
- LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response" );
- message.setValue( "name", name );
- message.setValueS32( "width", width );
- message.setValueS32( "height", height );
- message.setValueS32( "texture_width", texture_width );
- message.setValueS32( "texture_height", texture_height );
- sendMessage( message );
- }
- else
- if ( message_name == "load_uri" )
- {
- std::string uri = message_in.getValue( "uri" );
- if ( ! uri.empty() )
- {
- };
- }
- else
- if ( message_name == "mouse_event" )
- {
- std::string event = message_in.getValue( "event" );
- S32 button = message_in.getValueS32( "button" );
-
- // left mouse button
- if ( button == 0 )
- {
- int mouse_x = message_in.getValueS32( "x" );
- int mouse_y = message_in.getValueS32( "y" );
- std::string modifiers = message_in.getValue( "modifiers" );
-
- if ( event == "move" )
- {
- if ( mMouseButtonDown )
- write_pixel( mouse_x, mouse_y, rand() % 0x80 + 0x80, rand() % 0x80 + 0x80, rand() % 0x80 + 0x80 );
- }
- else
- if ( event == "down" )
- {
- mMouseButtonDown = true;
- }
- else
- if ( event == "up" )
- {
- mMouseButtonDown = false;
- }
- else
- if ( event == "double_click" )
- {
- };
- };
- }
- else
- if ( message_name == "key_event" )
- {
- std::string event = message_in.getValue( "event" );
- S32 key = message_in.getValueS32( "key" );
- std::string modifiers = message_in.getValue( "modifiers" );
-
- if ( event == "down" )
- {
- if ( key == ' ')
- {
- mLastUpdateTime = 0;
- update( 0.0f );
- };
- };
- }
- else
- {
- //std::cerr << "MediaPluginExample::receiveMessage: unknown media message: " << message_string << std::endl;
- };
- }
- else
- if ( message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER )
- {
- if ( message_name == "browse_reload" )
- {
- mLastUpdateTime = 0;
- mFirstTime = true;
- mStopAction = false;
- update( 0.0f );
- }
- else
- if ( message_name == "browse_stop" )
- {
- for( int n = 0; n < ENumObjects; ++n )
- mXInc[ n ] = mYInc[ n ] = 0;
-
- mStopAction = true;
- update( 0.0f );
- }
- else
- {
- //std::cerr << "MediaPluginExample::receiveMessage: unknown media_browser message: " << message_string << std::endl;
- };
- }
- else
- {
- //std::cerr << "MediaPluginExample::receiveMessage: unknown message class: " << message_class << std::endl;
- };
- };
+// std::cerr << "MediaPluginWebKit::receiveMessage: received message: \"" << message_string << "\"" << std::endl;
+ LLPluginMessage message_in;
+
+ if(message_in.parse(message_string) >= 0)
+ {
+ std::string message_class = message_in.getClass();
+ std::string message_name = message_in.getName();
+ if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE)
+ {
+ if(message_name == "init")
+ {
+ LLPluginMessage message("base", "init_response");
+ LLSD versions = LLSD::emptyMap();
+ versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
+ versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
+ versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION;
+ message.setValueLLSD("versions", versions);
+
+ std::string plugin_version = "Example plugin 1.0..0";
+ message.setValue("plugin_version", plugin_version);
+ sendMessage(message);
+ }
+ else if(message_name == "idle")
+ {
+ // no response is necessary here.
+ F64 time = message_in.getValueReal("time");
+
+ // Convert time to milliseconds for update()
+ update((int)(time * 1000.0f));
+ }
+ else if(message_name == "cleanup")
+ {
+ }
+ else if(message_name == "shm_added")
+ {
+ SharedSegmentInfo info;
+ info.mAddress = message_in.getValuePointer("address");
+ info.mSize = (size_t)message_in.getValueS32("size");
+ std::string name = message_in.getValue("name");
+
+ mSharedSegments.insert(SharedSegmentMap::value_type(name, info));
+
+ }
+ else if(message_name == "shm_remove")
+ {
+ std::string name = message_in.getValue("name");
+
+ SharedSegmentMap::iterator iter = mSharedSegments.find(name);
+ if(iter != mSharedSegments.end())
+ {
+ if(mPixels == iter->second.mAddress)
+ {
+ // This is the currently active pixel buffer. Make sure we stop drawing to it.
+ mPixels = NULL;
+ mTextureSegmentName.clear();
+ }
+ mSharedSegments.erase(iter);
+ }
+ else
+ {
+// std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl;
+ }
+
+ // Send the response so it can be cleaned up.
+ LLPluginMessage message("base", "shm_remove_response");
+ message.setValue("name", name);
+ sendMessage(message);
+ }
+ else
+ {
+// std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl;
+ }
+ }
+ else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
+ {
+ if(message_name == "init")
+ {
+ // Plugin gets to decide the texture parameters to use.
+ mDepth = 4;
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
+ message.setValueS32("default_width", 1024);
+ message.setValueS32("default_height", 1024);
+ message.setValueS32("depth", mDepth);
+ message.setValueU32("internalformat", GL_RGBA);
+ message.setValueU32("format", GL_RGBA);
+ message.setValueU32("type", GL_UNSIGNED_BYTE);
+ message.setValueBoolean("coords_opengl", true);
+ sendMessage(message);
+ }
+ else if(message_name == "size_change")
+ {
+ std::string name = message_in.getValue("name");
+ S32 width = message_in.getValueS32("width");
+ S32 height = message_in.getValueS32("height");
+ S32 texture_width = message_in.getValueS32("texture_width");
+ S32 texture_height = message_in.getValueS32("texture_height");
+
+ if(!name.empty())
+ {
+ // Find the shared memory region with this name
+ SharedSegmentMap::iterator iter = mSharedSegments.find(name);
+ if(iter != mSharedSegments.end())
+ {
+ mPixels = (unsigned char*)iter->second.mAddress;
+ mWidth = width;
+ mHeight = height;
+
+ mTextureWidth = texture_width;
+ mTextureHeight = texture_height;
+ };
+ };
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response");
+ message.setValue("name", name);
+ message.setValueS32("width", width);
+ message.setValueS32("height", height);
+ message.setValueS32("texture_width", texture_width);
+ message.setValueS32("texture_height", texture_height);
+ sendMessage(message);
+
+ }
+ else if(message_name == "load_uri")
+ {
+ }
+ else if(message_name == "mouse_event")
+ {
+ std::string event = message_in.getValue("event");
+ if(event == "down")
+ {
+
+ }
+ else if(event == "up")
+ {
+ }
+ else if(event == "double_click")
+ {
+ }
+ }
+ }
+ else
+ {
+// std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl;
+ };
+ }
}
////////////////////////////////////////////////////////////////////////////////
//
void MediaPluginExample::write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b )
{
- // make sure we don't write outside the buffer
- if ( ( x < 0 ) || ( x >= mWidth ) || ( y < 0 ) || ( y >= mHeight ) )
- return;
-
- if ( mBackgroundPixels != NULL )
- {
- unsigned char *pixel = mBackgroundPixels;
- pixel += y * mWidth * mDepth;
- pixel += ( x * mDepth );
- pixel[ 0 ] = b;
- pixel[ 1 ] = g;
- pixel[ 2 ] = r;
-
- setDirty( x, y, x + 1, y + 1 );
- };
+ // make sure we don't write outside the buffer
+ if ( ( x < 0 ) || ( x >= mWidth ) || ( y < 0 ) || ( y >= mHeight ) )
+ return;
+
+ if ( mBackgroundPixels != NULL )
+ {
+ unsigned char *pixel = mBackgroundPixels;
+ pixel += y * mWidth * mDepth;
+ pixel += ( x * mDepth );
+ pixel[ 0 ] = b;
+ pixel[ 1 ] = g;
+ pixel[ 2 ] = r;
+
+ setDirty( x, y, x + 1, y + 1 );
+ };
}
////////////////////////////////////////////////////////////////////////////////
//
void MediaPluginExample::update( F64 milliseconds )
{
- if ( mWidth < 1 || mWidth > 2048 || mHeight < 1 || mHeight > 2048 )
- return;
-
- if ( mPixels == 0 )
- return;
-
- if ( mFirstTime )
- {
- for( int n = 0; n < ENumObjects; ++n )
- {
- mXpos[ n ] = ( mWidth / 2 ) + rand() % ( mWidth / 16 ) - ( mWidth / 32 );
- mYpos[ n ] = ( mHeight / 2 ) + rand() % ( mHeight / 16 ) - ( mHeight / 32 );
-
- mColorR[ n ] = rand() % 0x60 + 0x60;
- mColorG[ n ] = rand() % 0x60 + 0x60;
- mColorB[ n ] = rand() % 0x60 + 0x60;
-
- mXInc[ n ] = 0;
- while ( mXInc[ n ] == 0 )
- mXInc[ n ] = rand() % 7 - 3;
-
- mYInc[ n ] = 0;
- while ( mYInc[ n ] == 0 )
- mYInc[ n ] = rand() % 9 - 4;
-
- mBlockSize[ n ] = rand() % 0x30 + 0x10;
- };
-
- delete [] mBackgroundPixels;
-
- mBackgroundPixels = new unsigned char[ mWidth * mHeight * mDepth ];
-
- mFirstTime = false;
- };
-
- if ( mStopAction )
- return;
-
- if ( time( NULL ) > mLastUpdateTime + 3 )
- {
- const int num_squares = rand() % 20 + 4;
- int sqr1_r = rand() % 0x80 + 0x20;
- int sqr1_g = rand() % 0x80 + 0x20;
- int sqr1_b = rand() % 0x80 + 0x20;
- int sqr2_r = rand() % 0x80 + 0x20;
- int sqr2_g = rand() % 0x80 + 0x20;
- int sqr2_b = rand() % 0x80 + 0x20;
-
- for ( int y1 = 0; y1 < num_squares; ++y1 )
- {
- for ( int x1 = 0; x1 < num_squares; ++x1 )
- {
- int px_start = mWidth * x1 / num_squares;
- int px_end = ( mWidth * ( x1 + 1 ) ) / num_squares;
- int py_start = mHeight * y1 / num_squares;
- int py_end = ( mHeight * ( y1 + 1 ) ) / num_squares;
-
- for( int y2 = py_start; y2 < py_end; ++y2 )
- {
- for( int x2 = px_start; x2 < px_end; ++x2 )
- {
- int rowspan = mWidth * mDepth;
-
- if ( ( y1 % 2 ) ^ ( x1 % 2 ) )
- {
- mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr1_r;
- mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr1_g;
- mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr1_b;
- }
- else
- {
- mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr2_r;
- mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr2_g;
- mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr2_b;
- };
- };
- };
- };
- };
-
- time( &mLastUpdateTime );
- };
-
- memcpy( mPixels, mBackgroundPixels, mWidth * mHeight * mDepth );
-
- for( int n = 0; n < ENumObjects; ++n )
- {
- if ( rand() % 50 == 0 )
- {
- mXInc[ n ] = 0;
- while ( mXInc[ n ] == 0 )
- mXInc[ n ] = rand() % 7 - 3;
-
- mYInc[ n ] = 0;
- while ( mYInc[ n ] == 0 )
- mYInc[ n ] = rand() % 9 - 4;
- };
-
- if ( mXpos[ n ] + mXInc[ n ] < 0 || mXpos[ n ] + mXInc[ n ] >= mWidth - mBlockSize[ n ] )
- mXInc[ n ] =- mXInc[ n ];
-
- if ( mYpos[ n ] + mYInc[ n ] < 0 || mYpos[ n ] + mYInc[ n ] >= mHeight - mBlockSize[ n ] )
- mYInc[ n ] =- mYInc[ n ];
-
- mXpos[ n ] += mXInc[ n ];
- mYpos[ n ] += mYInc[ n ];
-
- for( int y = 0; y < mBlockSize[ n ]; ++y )
- {
- for( int x = 0; x < mBlockSize[ n ]; ++x )
- {
- mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 0 ] = mColorR[ n ];
- mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 1 ] = mColorG[ n ];
- mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 2 ] = mColorB[ n ];
- };
- };
- };
-
- setDirty( 0, 0, mWidth, mHeight );
+ if ( mWidth < 1 || mWidth > 2048 || mHeight < 1 || mHeight > 2048 )
+ return;
+
+ if ( mPixels == 0 )
+ return;
+
+ if ( mFirstTime )
+ {
+ for( int n = 0; n < ENumObjects; ++n )
+ {
+ mXpos[ n ] = ( mWidth / 2 ) + rand() % ( mWidth / 16 ) - ( mWidth / 32 );
+ mYpos[ n ] = ( mHeight / 2 ) + rand() % ( mHeight / 16 ) - ( mHeight / 32 );
+
+ mColorR[ n ] = rand() % 0x60 + 0x60;
+ mColorG[ n ] = rand() % 0x60 + 0x60;
+ mColorB[ n ] = rand() % 0x60 + 0x60;
+
+ mXInc[ n ] = 0;
+ while ( mXInc[ n ] == 0 )
+ mXInc[ n ] = rand() % 7 - 3;
+
+ mYInc[ n ] = 0;
+ while ( mYInc[ n ] == 0 )
+ mYInc[ n ] = rand() % 9 - 4;
+
+ mBlockSize[ n ] = rand() % 0x30 + 0x10;
+ };
+
+ delete [] mBackgroundPixels;
+
+ mBackgroundPixels = new unsigned char[ mWidth * mHeight * mDepth ];
+
+ mFirstTime = false;
+ };
+
+ if ( mStopAction )
+ return;
+
+ if ( time( NULL ) > mLastUpdateTime + 3 )
+ {
+ const int num_squares = rand() % 20 + 4;
+ int sqr1_r = rand() % 0x80 + 0x20;
+ int sqr1_g = rand() % 0x80 + 0x20;
+ int sqr1_b = rand() % 0x80 + 0x20;
+ int sqr2_r = rand() % 0x80 + 0x20;
+ int sqr2_g = rand() % 0x80 + 0x20;
+ int sqr2_b = rand() % 0x80 + 0x20;
+
+ for ( int y1 = 0; y1 < num_squares; ++y1 )
+ {
+ for ( int x1 = 0; x1 < num_squares; ++x1 )
+ {
+ int px_start = mWidth * x1 / num_squares;
+ int px_end = ( mWidth * ( x1 + 1 ) ) / num_squares;
+ int py_start = mHeight * y1 / num_squares;
+ int py_end = ( mHeight * ( y1 + 1 ) ) / num_squares;
+
+ for( int y2 = py_start; y2 < py_end; ++y2 )
+ {
+ for( int x2 = px_start; x2 < px_end; ++x2 )
+ {
+ int rowspan = mWidth * mDepth;
+
+ if ( ( y1 % 2 ) ^ ( x1 % 2 ) )
+ {
+ mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr1_r;
+ mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr1_g;
+ mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr1_b;
+ }
+ else
+ {
+ mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr2_r;
+ mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr2_g;
+ mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr2_b;
+ };
+ };
+ };
+ };
+ };
+
+ time( &mLastUpdateTime );
+ };
+
+ memcpy( mPixels, mBackgroundPixels, mWidth * mHeight * mDepth );
+
+ for( int n = 0; n < ENumObjects; ++n )
+ {
+ if ( rand() % 50 == 0 )
+ {
+ mXInc[ n ] = 0;
+ while ( mXInc[ n ] == 0 )
+ mXInc[ n ] = rand() % 7 - 3;
+
+ mYInc[ n ] = 0;
+ while ( mYInc[ n ] == 0 )
+ mYInc[ n ] = rand() % 9 - 4;
+ };
+
+ if ( mXpos[ n ] + mXInc[ n ] < 0 || mXpos[ n ] + mXInc[ n ] >= mWidth - mBlockSize[ n ] )
+ mXInc[ n ] =- mXInc[ n ];
+
+ if ( mYpos[ n ] + mYInc[ n ] < 0 || mYpos[ n ] + mYInc[ n ] >= mHeight - mBlockSize[ n ] )
+ mYInc[ n ] =- mYInc[ n ];
+
+ mXpos[ n ] += mXInc[ n ];
+ mYpos[ n ] += mYInc[ n ];
+
+ for( int y = 0; y < mBlockSize[ n ]; ++y )
+ {
+ for( int x = 0; x < mBlockSize[ n ]; ++x )
+ {
+ mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 0 ] = mColorR[ n ];
+ mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 1 ] = mColorG[ n ];
+ mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 2 ] = mColorB[ n ];
+ };
+ };
+ };
+
+ setDirty( 0, 0, mWidth, mHeight );
};
////////////////////////////////////////////////////////////////////////////////
//
bool MediaPluginExample::init()
{
- LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text" );
- message.setValue( "name", "Example Plugin" );
- sendMessage( message );
+ LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text" );
+ message.setValue( "name", "Example Plugin" );
+ sendMessage( message );
- return true;
+ return true;
};
////////////////////////////////////////////////////////////////////////////////
//
int init_media_plugin( LLPluginInstance::sendMessageFunction host_send_func,
- void* host_user_data,
- LLPluginInstance::sendMessageFunction *plugin_send_func,
- void **plugin_user_data )
+ void* host_user_data,
+ LLPluginInstance::sendMessageFunction *plugin_send_func,
+ void **plugin_user_data )
{
- MediaPluginExample* self = new MediaPluginExample( host_send_func, host_user_data );
- *plugin_send_func = MediaPluginExample::staticReceiveMessage;
- *plugin_user_data = ( void* )self;
+ MediaPluginExample* self = new MediaPluginExample( host_send_func, host_user_data );
+ *plugin_send_func = MediaPluginExample::staticReceiveMessage;
+ *plugin_user_data = ( void* )self;
- return 0;
+ return 0;
}
+
diff --git a/indra/media_plugins/webkit/CMakeLists.txt b/indra/media_plugins/webkit/CMakeLists.txt
index 05f1236606..3b1f679540 100644
--- a/indra/media_plugins/webkit/CMakeLists.txt
+++ b/indra/media_plugins/webkit/CMakeLists.txt
@@ -27,6 +27,7 @@ include_directories(
${LLIMAGE_INCLUDE_DIRS}
${LLRENDER_INCLUDE_DIRS}
${LLWINDOW_INCLUDE_DIRS}
+ ${LLQTWEBKIT_INCLUDE_DIR}
)
diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp
index bd1a44a930..d6f8ae3e16 100644
--- a/indra/media_plugins/webkit/media_plugin_webkit.cpp
+++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp
@@ -341,7 +341,7 @@ private:
url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundB * 255.0f);
url << "%22%3E%3C/body%3E%3C/html%3E";
- lldebugs << "data url is: " << url.str() << llendl;
+ //lldebugs << "data url is: " << url.str() << llendl;
LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, url.str() );
// LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" );
@@ -407,6 +407,8 @@ private:
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin");
message.setValue("uri", event.getEventUri());
+ message.setValueBoolean("history_back_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK));
+ message.setValueBoolean("history_forward_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD));
sendMessage(message);
setStatus(STATUS_LOADING);
@@ -569,6 +571,57 @@ private:
return blockingPickFile();
}
+ std::string mAuthUsername;
+ std::string mAuthPassword;
+ bool mAuthOK;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ bool onAuthRequest(const std::string &in_url, const std::string &in_realm, std::string &out_username, std::string &out_password)
+ {
+ mAuthOK = false;
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_request");
+ message.setValue("url", in_url);
+ message.setValue("realm", in_realm);
+ message.setValueBoolean("blocking_request", true);
+
+ // The "blocking_request" key in the message means this sendMessage call will block until a response is received.
+ sendMessage(message);
+
+ if(mAuthOK)
+ {
+ out_username = mAuthUsername;
+ out_password = mAuthPassword;
+ }
+
+ return mAuthOK;
+ }
+
+ void authResponse(LLPluginMessage &message)
+ {
+ mAuthOK = message.getValueBoolean("ok");
+ if(mAuthOK)
+ {
+ mAuthUsername = message.getValue("username");
+ mAuthPassword = message.getValue("password");
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onLinkHovered(const EventType& event)
+ {
+ if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "link_hovered");
+ message.setValue("link", event.getEventUri());
+ message.setValue("title", event.getStringValue());
+ message.setValue("text", event.getStringValue2());
+ sendMessage(message);
+ }
+ }
+
LLQtWebKit::EKeyboardModifier decodeModifiers(std::string &modifiers)
{
int result = 0;
@@ -1096,6 +1149,10 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
{
onPickFileResponse(message_in.getValue("file"));
}
+ if(message_name == "auth_response")
+ {
+ authResponse(message_in);
+ }
else
{
// std::cerr << "MediaPluginWebKit::receiveMessage: unknown media message: " << message_string << std::endl;
@@ -1182,6 +1239,22 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
mUserAgent = message_in.getValue("user_agent");
LLQtWebKit::getInstance()->setBrowserAgentId( mUserAgent );
}
+ else if(message_name == "ignore_ssl_cert_errors")
+ {
+#if LLQTWEBKIT_API_VERSION >= 3
+ LLQtWebKit::getInstance()->setIgnoreSSLCertErrors( message_in.getValueBoolean("ignore") );
+#else
+ llwarns << "Ignoring ignore_ssl_cert_errors message (llqtwebkit version is too old)." << llendl;
+#endif
+ }
+ else if(message_name == "add_certificate_file_path")
+ {
+#if LLQTWEBKIT_API_VERSION >= 6
+ LLQtWebKit::getInstance()->addCAFile( message_in.getValue("path") );
+#else
+ llwarns << "Ignoring add_certificate_file_path message (llqtwebkit version is too old)." << llendl;
+#endif
+ }
else if(message_name == "init_history")
{
// Initialize browser history
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 4869aa72a0..ce22a52460 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -223,6 +223,7 @@ set(viewer_SOURCE_FILES
llfloaterurlentry.cpp
llfloatervoiceeffect.cpp
llfloaterwater.cpp
+ llfloaterwebcontent.cpp
llfloaterwhitelistentry.cpp
llfloaterwindlight.cpp
llfloaterwindowsize.cpp
@@ -759,6 +760,7 @@ set(viewer_HEADER_FILES
llfloaterurlentry.h
llfloatervoiceeffect.h
llfloaterwater.h
+ llfloaterwebcontent.h
llfloaterwhitelistentry.h
llfloaterwindlight.h
llfloaterwindowsize.h
@@ -1850,29 +1852,31 @@ if (PACKAGE)
set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest)
endif (LINUX)
- if(CMAKE_CFG_INTDIR STREQUAL ".")
+ if(RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING)
+ if(CMAKE_CFG_INTDIR STREQUAL ".")
set(LLBUILD_CONFIG ${CMAKE_BUILD_TYPE})
- else(CMAKE_CFG_INTDIR STREQUAL ".")
+ else(CMAKE_CFG_INTDIR STREQUAL ".")
# set LLBUILD_CONFIG to be a shell variable evaluated at build time
# reflecting the configuration we are currently building.
set(LLBUILD_CONFIG ${CMAKE_CFG_INTDIR})
- endif(CMAKE_CFG_INTDIR STREQUAL ".")
- add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}"
- COMMAND "${PYTHON_EXECUTABLE}"
- ARGS
- "${CMAKE_CURRENT_SOURCE_DIR}/generate_breakpad_symbols.py"
- "${LLBUILD_CONFIG}"
- "${VIEWER_DIST_DIR}"
- "${VIEWER_EXE_GLOBS}"
- "${VIEWER_LIB_GLOB}"
- "${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/bin/dump_syms"
- "${VIEWER_SYMBOL_FILE}"
- DEPENDS generate_breakpad_symbols.py
- VERBATIM
- )
- add_custom_target(generate_breakpad_symbols DEPENDS "${VIEWER_SYMBOL_FILE}")
- add_dependencies(generate_breakpad_symbols "${VIEWER_BINARY_NAME}" "${VIEWER_COPY_MANIFEST}")
- add_dependencies(package generate_breakpad_symbols)
+ endif(CMAKE_CFG_INTDIR STREQUAL ".")
+ add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}"
+ COMMAND "${PYTHON_EXECUTABLE}"
+ ARGS
+ "${CMAKE_CURRENT_SOURCE_DIR}/generate_breakpad_symbols.py"
+ "${LLBUILD_CONFIG}"
+ "${VIEWER_DIST_DIR}"
+ "${VIEWER_EXE_GLOBS}"
+ "${VIEWER_LIB_GLOB}"
+ "${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/bin/dump_syms"
+ "${VIEWER_SYMBOL_FILE}"
+ DEPENDS generate_breakpad_symbols.py
+ VERBATIM)
+
+ add_custom_target(generate_breakpad_symbols DEPENDS "${VIEWER_SYMBOL_FILE}")
+ add_dependencies(generate_breakpad_symbols "${VIEWER_BINARY_NAME}" "${VIEWER_COPY_MANIFEST}")
+ add_dependencies(package generate_breakpad_symbols)
+ endif(RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING)
endif (PACKAGE)
if (LL_TESTS)
@@ -1887,6 +1891,8 @@ if (LL_TESTS)
llremoteparcelrequest.cpp
llviewerhelputil.cpp
llversioninfo.cpp
+ llworldmap.cpp
+ llworldmipmap.cpp
)
##################################################
@@ -1974,8 +1980,6 @@ if (LL_TESTS)
#ADD_VIEWER_BUILD_TEST(llmemoryview viewer)
#ADD_VIEWER_BUILD_TEST(llagentaccess viewer)
- #ADD_VIEWER_BUILD_TEST(llworldmap viewer)
- #ADD_VIEWER_BUILD_TEST(llworldmipmap viewer)
#ADD_VIEWER_BUILD_TEST(lltextureinfo viewer)
#ADD_VIEWER_BUILD_TEST(lltextureinfodetails viewer)
#ADD_VIEWER_BUILD_TEST(lltexturestatsuploader viewer)
diff --git a/indra/newview/app_settings/lindenlab.pem b/indra/newview/app_settings/lindenlab.pem
new file mode 100644
index 0000000000..cf88d0e047
--- /dev/null
+++ b/indra/newview/app_settings/lindenlab.pem
@@ -0,0 +1,27 @@
+-----BEGIN CERTIFICATE-----
+MIIEUDCCA7mgAwIBAgIJAN4ppNGwj6yIMA0GCSqGSIb3DQEBBAUAMIHMMQswCQYD
+VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5j
+aXNjbzEZMBcGA1UEChMQTGluZGVuIExhYiwgSW5jLjEpMCcGA1UECxMgTGluZGVu
+IExhYiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxKTAnBgNVBAMTIExpbmRlbiBMYWIg
+Q2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYJKoZIhvcNAQkBFhBjYUBsaW5kZW5s
+YWIuY29tMB4XDTA1MDQyMTAyNDAzMVoXDTI1MDQxNjAyNDAzMVowgcwxCzAJBgNV
+BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp
+c2NvMRkwFwYDVQQKExBMaW5kZW4gTGFiLCBJbmMuMSkwJwYDVQQLEyBMaW5kZW4g
+TGFiIENlcnRpZmljYXRlIEF1dGhvcml0eTEpMCcGA1UEAxMgTGluZGVuIExhYiBD
+ZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgkqhkiG9w0BCQEWEGNhQGxpbmRlbmxh
+Yi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKXh1MThucdTbMg9bYBO
+rAm8yWns32YojB0PRfbq8rUjepEhTm3/13s0u399Uc202v4ejcGhkIDWJZd2NZMF
+oKrhmRfxGHSKPCuFaXC3jh0lRECj7k8FoPkcmaPjSyodrDFDUUuv+C06oYJoI+rk
+8REyal9NwgHvqCzOrZtiTXAdAgMBAAGjggE2MIIBMjAdBgNVHQ4EFgQUO1zK2e1f
+1wO1fHAjq6DTJobKDrcwggEBBgNVHSMEgfkwgfaAFDtcytntX9cDtXxwI6ug0yaG
+yg63oYHSpIHPMIHMMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEW
+MBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQTGluZGVuIExhYiwgSW5j
+LjEpMCcGA1UECxMgTGluZGVuIExhYiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxKTAn
+BgNVBAMTIExpbmRlbiBMYWIgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYJKoZI
+hvcNAQkBFhBjYUBsaW5kZW5sYWIuY29tggkA3imk0bCPrIgwDAYDVR0TBAUwAwEB
+/zANBgkqhkiG9w0BAQQFAAOBgQA/ZkgfvwHYqk1UIAKZS3kMCxz0HvYuEQtviwnu
+xA39CIJ65Zozs28Eg1aV9/Y+Of7TnWhW+U3J3/wD/GghaAGiKK6vMn9gJBIdBX/9
+e6ef37VGyiOEFFjnUIbuk0RWty0orN76q/lI/xjCi15XSA/VSq2j4vmnwfZcPTDu
+glmQ1A==
+-----END CERTIFICATE-----
+
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 06992d2b52..ea7ac6beda 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -686,6 +686,39 @@
<key>Value</key>
<string>http://www.secondlife.com</string>
</map>
+ <key>BrowserIgnoreSSLCertErrors</key>
+ <map>
+ <key>Comment</key>
+ <string>FOR TESTING ONLY: Tell the built-in web browser to ignore SSL cert errors.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>BrowserUseDefaultCAFile</key>
+ <map>
+ <key>Comment</key>
+ <string>Tell the built-in web browser to use the CA.pem file shipped with the client.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>BrowserCAFilePath</key>
+ <map>
+ <key>Comment</key>
+ <string>Tell the built-in web browser the path to an alternative CA.pem file (only used if BrowserUseDefaultCAFile is false).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string></string>
+ </map>
<key>BlockAvatarAppearanceMessages</key>
<map>
<key>Comment</key>
@@ -4747,6 +4780,17 @@
<key>Value</key>
<string>http://map.secondlife.com.s3.amazonaws.com/</string>
</map>
+ <key>CurrentMapServerURL</key>
+ <map>
+ <key>Comment</key>
+ <string>Current Session World map URL</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string></string>
+ </map>
<key>MapShowEvents</key>
<map>
<key>Comment</key>
@@ -6572,7 +6616,18 @@
<key>MediaBrowserWindowLimit</key>
<map>
<key>Comment</key>
- <string>Maximum number of media brower windows that can be open at once (0 for no limit)</string>
+ <string>Maximum number of media brower windows that can be open at once in the media browser floater (0 for no limit)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>5</integer>
+ </map>
+ <key>WebContentWindowLimit</key>
+ <map>
+ <key>Comment</key>
+ <string>Maximum number of web brower windows that can be open at once in the Web content floater (0 for no limit)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -9980,6 +10035,17 @@
<key>Value</key>
<real>500.0</real>
</map>
+ <key>UpdaterMaximumBandwidth</key>
+ <map>
+ <key>Comment</key>
+ <string>Maximum allowable downstream bandwidth for updater service (kilo bits per second)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>500.0</real>
+ </map>
<key>ToolTipDelay</key>
<map>
<key>Comment</key>
@@ -11080,16 +11146,16 @@
<key>Value</key>
<integer>15</integer>
</map>
- <key>UpdaterServiceActive</key>
+ <key>UpdaterServiceSetting</key>
<map>
<key>Comment</key>
- <string>Enable or disable the updater service.</string>
+ <string>Configure updater service.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Boolean</string>
+ <string>U32</string>
<key>Value</key>
- <integer>1</integer>
+ <integer>3</integer>
</map>
<key>UpdaterServiceCheckPeriod</key>
<map>
@@ -12368,5 +12434,16 @@
<key>Value</key>
<string>name</string>
</map>
+ <key>ReleaseNotesURL</key>
+ <map>
+ <key>Comment</key>
+ <string>Release notes URL template</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>http://secondlife.com/app/releasenotes/?channel=[CHANNEL]&amp;version=[VERSION]</string>
+ </map>
</map>
</llsd>
diff --git a/indra/newview/app_settings/shaders/shader_heirarchy.txt b/indra/newview/app_settings/shaders/shader_hierarchy.txt
index d8bbf69b38..d8bbf69b38 100644
--- a/indra/newview/app_settings/shaders/shader_heirarchy.txt
+++ b/indra/newview/app_settings/shaders/shader_hierarchy.txt
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index a95abd7dd1..a82c3da4c5 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -135,7 +135,7 @@ RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
RenderObjectBump 1 1
-RenderReflectionDetail 1 2
+RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt
index a52b32355d..a2cd4b834c 100644
--- a/indra/newview/featuretable_linux.txt
+++ b/indra/newview/featuretable_linux.txt
@@ -134,7 +134,7 @@ RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
RenderObjectBump 1 1
-RenderReflectionDetail 1 2
+RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index 6dabef53a8..3ad7f4e892 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -133,7 +133,7 @@ RenderGlowResolutionPow 1 9
RenderLightingDetail 1 1
RenderMaxPartCount 1 4096
RenderObjectBump 1 1
-RenderReflectionDetail 1 2
+RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
diff --git a/indra/newview/featuretable_xp.txt b/indra/newview/featuretable_xp.txt
index a09ba17c62..38e6bb1e5e 100644
--- a/indra/newview/featuretable_xp.txt
+++ b/indra/newview/featuretable_xp.txt
@@ -135,7 +135,7 @@ RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
RenderObjectBump 1 1
-RenderReflectionDetail 1 2
+RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp
index 15f8e7bf4d..f01d5ff1f5 100644
--- a/indra/newview/llagentcamera.cpp
+++ b/indra/newview/llagentcamera.cpp
@@ -2695,6 +2695,9 @@ void LLAgentCamera::lookAtLastChat()
new_camera_pos -= delta_pos * 0.4f;
new_camera_pos += left * 0.3f;
new_camera_pos += up * 0.2f;
+
+ setFocusOnAvatar(FALSE, FALSE);
+
if (chatter_av->mHeadp)
{
setFocusGlobal(gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()), gAgent.getLastChatter());
@@ -2705,7 +2708,6 @@ void LLAgentCamera::lookAtLastChat()
setFocusGlobal(chatter->getPositionGlobal(), gAgent.getLastChatter());
mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal();
}
- setFocusOnAvatar(FALSE, TRUE);
}
else
{
@@ -2725,9 +2727,10 @@ void LLAgentCamera::lookAtLastChat()
new_camera_pos += left * 0.3f;
new_camera_pos += up * 0.2f;
+ setFocusOnAvatar(FALSE, FALSE);
+
setFocusGlobal(chatter->getPositionGlobal(), gAgent.getLastChatter());
mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal();
- setFocusOnAvatar(FALSE, TRUE);
}
}
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 5c0c5adabe..3a98c23e05 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -80,6 +80,8 @@
#include "llfeaturemanager.h"
#include "llurlmatch.h"
#include "lltextutil.h"
+#include "lllogininstance.h"
+#include "llprogressview.h"
#include "llweb.h"
#include "llsecondlifeurls.h"
@@ -602,10 +604,14 @@ LLAppViewer::LLAppViewer() :
setupErrorHandling();
sInstance = this;
gLoggedInTime.stop();
+
+ LLLoginInstance::instance().setUpdaterService(mUpdater.get());
}
LLAppViewer::~LLAppViewer()
{
+ LLLoginInstance::instance().setUpdaterService(0);
+
destroyMainloopTimeout();
// If we got to this destructor somehow, the app didn't hang.
@@ -2432,26 +2438,120 @@ bool LLAppViewer::initConfiguration()
}
namespace {
- // *TODO - decide if there's a better place for this function.
+ // *TODO - decide if there's a better place for these functions.
// do we need a file llupdaterui.cpp or something? -brad
+
+ void apply_update_callback(LLSD const & notification, LLSD const & response)
+ {
+ lldebugs << "LLUpdate user response: " << response << llendl;
+ if(response["OK_okcancelbuttons"].asBoolean())
+ {
+ llinfos << "LLUpdate restarting viewer" << llendl;
+ static const bool install_if_ready = true;
+ // *HACK - this lets us launch the installer immediately for now
+ LLUpdaterService().startChecking(install_if_ready);
+ }
+ }
+
+ void apply_update_ok_callback(LLSD const & notification, LLSD const & response)
+ {
+ llinfos << "LLUpdate restarting viewer" << llendl;
+ static const bool install_if_ready = true;
+ // *HACK - this lets us launch the installer immediately for now
+ LLUpdaterService().startChecking(install_if_ready);
+ }
+
+ void on_update_downloaded(LLSD const & data)
+ {
+ std::string notification_name;
+ void (*apply_callback)(LLSD const &, LLSD const &) = NULL;
+
+ if(data["required"].asBoolean())
+ {
+ apply_callback = &apply_update_ok_callback;
+ if(LLStartUp::getStartupState() <= STATE_LOGIN_WAIT)
+ {
+ // The user never saw the progress bar.
+ notification_name = "RequiredUpdateDownloadedVerboseDialog";
+ }
+ else
+ {
+ notification_name = "RequiredUpdateDownloadedDialog";
+ }
+ }
+ else
+ {
+ apply_callback = &apply_update_callback;
+ if(LLStartUp::getStartupState() < STATE_STARTED)
+ {
+ // CHOP-262 we need to use a different notification
+ // method prior to login.
+ notification_name = "DownloadBackgroundDialog";
+ }
+ else
+ {
+ notification_name = "DownloadBackgroundTip";
+ }
+ }
+
+ LLSD substitutions;
+ substitutions["VERSION"] = data["version"];
+
+ // truncate version at the rightmost '.'
+ std::string version_short(data["version"]);
+ size_t short_length = version_short.rfind('.');
+ if (short_length != std::string::npos)
+ {
+ version_short.resize(short_length);
+ }
+
+ LLUIString relnotes_url("[RELEASE_NOTES_BASE_URL][CHANNEL_URL]/[VERSION_SHORT]");
+ relnotes_url.setArg("[VERSION_SHORT]", version_short);
+
+ // *TODO thread the update service's response through to this point
+ std::string const & channel = LLVersionInfo::getChannel();
+ boost::shared_ptr<char> channel_escaped(curl_escape(channel.c_str(), channel.size()), &curl_free);
+
+ relnotes_url.setArg("[CHANNEL_URL]", channel_escaped.get());
+ relnotes_url.setArg("[RELEASE_NOTES_BASE_URL]", LLTrans::getString("RELEASE_NOTES_BASE_URL"));
+ substitutions["RELEASE_NOTES_FULL_URL"] = relnotes_url.getString();
+
+ LLNotificationsUtil::add(notification_name, substitutions, LLSD(), apply_callback);
+ }
+
+ void install_error_callback(LLSD const & notification, LLSD const & response)
+ {
+ LLAppViewer::instance()->forceQuit();
+ }
+
bool notify_update(LLSD const & evt)
{
+ std::string notification_name;
switch (evt["type"].asInteger())
{
case LLUpdaterService::DOWNLOAD_COMPLETE:
- LLNotificationsUtil::add("DownloadBackground");
+ on_update_downloaded(evt);
break;
case LLUpdaterService::INSTALL_ERROR:
- LLNotificationsUtil::add("FailedUpdateInstall");
+ if(evt["required"].asBoolean()) {
+ LLNotificationsUtil::add("FailedRequiredUpdateInstall", LLSD(), LLSD(), &install_error_callback);
+ } else {
+ LLNotificationsUtil::add("FailedUpdateInstall");
+ }
break;
default:
- llinfos << "unhandled update event " << evt << llendl;
break;
}
// let others also handle this event by default
return false;
}
+
+ bool on_bandwidth_throttle(LLUpdaterService * updater, LLSD const & evt)
+ {
+ updater->setBandwidthLimit(evt.asInteger() * (1024/8));
+ return false; // Let others receive this event.
+ };
};
void LLAppViewer::initUpdater()
@@ -2474,7 +2574,10 @@ void LLAppViewer::initUpdater()
channel,
version);
mUpdater->setCheckPeriod(check_period);
- if(gSavedSettings.getBOOL("UpdaterServiceActive"))
+ mUpdater->setBandwidthLimit((int)gSavedSettings.getF32("UpdaterMaximumBandwidth") * (1024/8));
+ gSavedSettings.getControl("UpdaterMaximumBandwidth")->getSignal()->
+ connect(boost::bind(&on_bandwidth_throttle, mUpdater.get(), _2));
+ if(gSavedSettings.getU32("UpdaterServiceSetting"))
{
bool install_if_ready = true;
mUpdater->startChecking(install_if_ready);
@@ -2901,8 +3004,10 @@ void LLAppViewer::handleViewerCrash()
pApp->removeMarkerFile(false);
}
+#if LL_SEND_CRASH_REPORTS
// Call to pure virtual, handled by platform specific llappviewer instance.
pApp->handleCrashReporting();
+#endif
return;
}
@@ -3113,7 +3218,7 @@ static LLNotificationFunctorRegistration finish_quit_reg("ConfirmQuit", finish_q
void LLAppViewer::userQuit()
{
- if (gDisconnected)
+ if (gDisconnected || gViewerWindow->getProgressView()->getVisible())
{
requestQuit();
}
@@ -4629,6 +4734,35 @@ void LLAppViewer::loadEventHostModule(S32 listen_port)
return;
}
+ LL_INFOS("eventhost") << "Found lleventhost at '" << dso_path << "'" << LL_ENDL;
+#if ! defined(LL_WINDOWS)
+ {
+ std::string outfile("/tmp/lleventhost.file.out");
+ std::string command("file '" + dso_path + "' > '" + outfile + "' 2>&1");
+ int rc = system(command.c_str());
+ if (rc != 0)
+ {
+ LL_WARNS("eventhost") << command << " ==> " << rc << ':' << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS("eventhost") << command << ':' << LL_ENDL;
+ }
+ {
+ std::ifstream reader(outfile.c_str());
+ std::string line;
+ while (std::getline(reader, line))
+ {
+ size_t len = line.length();
+ if (len && line[len-1] == '\n')
+ line.erase(len-1);
+ LL_INFOS("eventhost") << line << LL_ENDL;
+ }
+ }
+ remove(outfile.c_str());
+ }
+#endif // LL_WINDOWS
+
apr_dso_handle_t * eventhost_dso_handle = NULL;
apr_pool_t * eventhost_dso_memory_pool = NULL;
@@ -4637,13 +4771,13 @@ void LLAppViewer::loadEventHostModule(S32 listen_port)
apr_status_t rv = apr_dso_load(&eventhost_dso_handle,
dso_path.c_str(),
eventhost_dso_memory_pool);
- ll_apr_assert_status(rv);
+ llassert_always(! ll_apr_warn_status(rv, eventhost_dso_handle));
llassert_always(eventhost_dso_handle != NULL);
int (*ll_plugin_start_func)(LLSD const &) = NULL;
rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_start_func, eventhost_dso_handle, "ll_plugin_start");
- ll_apr_assert_status(rv);
+ llassert_always(! ll_apr_warn_status(rv, eventhost_dso_handle));
llassert_always(ll_plugin_start_func != NULL);
LLSD args;
diff --git a/indra/newview/llbrowsernotification.cpp b/indra/newview/llbrowsernotification.cpp
index d6a813d608..6e77d1e336 100644
--- a/indra/newview/llbrowsernotification.cpp
+++ b/indra/newview/llbrowsernotification.cpp
@@ -29,8 +29,9 @@
#include "llnotificationhandler.h"
#include "llnotifications.h"
-#include "llfloaterreg.h"
#include "llmediactrl.h"
+#include "llviewermedia.h"
+#include "llviewermediafocus.h"
using namespace LLNotificationsUI;
@@ -39,10 +40,19 @@ bool LLBrowserNotification::processNotification(const LLSD& notify)
LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
if (!notification) return false;
- LLMediaCtrl* media_instance = LLMediaCtrl::getInstance(notification->getPayload()["media_id"].asUUID());
+ LLUUID media_id = notification->getPayload()["media_id"].asUUID();
+ LLMediaCtrl* media_instance = LLMediaCtrl::getInstance(media_id);
if (media_instance)
{
media_instance->showNotification(notification);
}
+ else if (LLViewerMediaFocus::instance().getControlsMediaID() == media_id)
+ {
+ LLViewerMediaImpl* impl = LLViewerMedia::getMediaImplFromTextureID(media_id);
+ if (impl)
+ {
+ impl->showNotification(notification);
+ }
+ }
return false;
}
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 6e778de2d8..c98bcbda45 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -586,7 +586,7 @@ void LLChatHistory::initFromParams(const LLChatHistory::Params& p)
LLLayoutStack::Params layout_p;
layout_p.rect = stack_rect;
layout_p.follows.flags = FOLLOWS_ALL;
- layout_p.orientation = "vertical";
+ layout_p.orientation = LLLayoutStack::VERTICAL;
layout_p.mouse_opaque = false;
LLLayoutStack* stackp = LLUICtrlFactory::create<LLLayoutStack>(layout_p, this);
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index 8ae3ccbae3..2873bc0059 100644
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -272,7 +272,7 @@ LLSD LLFloaterAbout::getInfo()
}
// TODO: Implement media plugin version query
- info["QT_WEBKIT_VERSION"] = "4.6 (version number hard-coded)";
+ info["QT_WEBKIT_VERSION"] = "4.7.1 (version number hard-coded)";
if (gPacketsIn > 0)
{
diff --git a/indra/newview/llfloaterhelpbrowser.cpp b/indra/newview/llfloaterhelpbrowser.cpp
index cec98e9992..a650886d89 100644
--- a/indra/newview/llfloaterhelpbrowser.cpp
+++ b/indra/newview/llfloaterhelpbrowser.cpp
@@ -132,9 +132,10 @@ void LLFloaterHelpBrowser::onClickOpenWebBrowser(void* user_data)
void LLFloaterHelpBrowser::openMedia(const std::string& media_url)
{
- mBrowser->setHomePageUrl(media_url);
- //mBrowser->navigateTo("data:text/html;charset=utf-8,I'd really love to be going to:<br><b>" + media_url + "</b>"); // tofu HACK for debugging =:)
- mBrowser->navigateTo(media_url);
+ // explicitly make the media mime type for this floater since it will
+ // only ever display one type of content (Web).
+ mBrowser->setHomePageUrl(media_url, "text/html");
+ mBrowser->navigateTo(media_url, "text/html");
setCurrentURL(media_url);
}
diff --git a/indra/newview/llfloatermap.cpp b/indra/newview/llfloatermap.cpp
index 351b9ac5da..1b94d8cbcd 100644
--- a/indra/newview/llfloatermap.cpp
+++ b/indra/newview/llfloatermap.cpp
@@ -83,7 +83,6 @@ LLFloaterMap::~LLFloaterMap()
BOOL LLFloaterMap::postBuild()
{
mMap = getChild<LLNetMap>("Net Map");
- mMap->setScale(gSavedSettings.getF32("MiniMapScale"));
mMap->setToolTipMsg(getString("ToolTipMsg"));
sendChildToBack(mMap);
@@ -288,7 +287,16 @@ void LLFloaterMap::handleZoom(const LLSD& userdata)
std::string level = userdata.asString();
F32 scale = 0.0f;
- if (level == std::string("close"))
+ if (level == std::string("default"))
+ {
+ LLControlVariable *pvar = gSavedSettings.getControl("MiniMapScale");
+ if(pvar)
+ {
+ pvar->resetToDefault();
+ scale = gSavedSettings.getF32("MiniMapScale");
+ }
+ }
+ else if (level == std::string("close"))
scale = LLNetMap::MAP_SCALE_MAX;
else if (level == std::string("medium"))
scale = LLNetMap::MAP_SCALE_MID;
@@ -296,7 +304,6 @@ void LLFloaterMap::handleZoom(const LLSD& userdata)
scale = LLNetMap::MAP_SCALE_MIN;
if (scale != 0.0f)
{
- gSavedSettings.setF32("MiniMapScale", scale );
mMap->setScale(scale);
}
}
diff --git a/indra/newview/llfloatermediabrowser.cpp b/indra/newview/llfloatermediabrowser.cpp
index d20092e344..7a670dd90c 100644
--- a/indra/newview/llfloatermediabrowser.cpp
+++ b/indra/newview/llfloatermediabrowser.cpp
@@ -306,17 +306,14 @@ void LLFloaterMediaBrowser::setCurrentURL(const std::string& url)
{
mCurrentURL = url;
- // redirects will navigate momentarily to about:blank, don't add to history
- if (mCurrentURL != "about:blank")
- {
- mAddressCombo->remove(mCurrentURL);
- mAddressCombo->add(mCurrentURL);
- mAddressCombo->selectByValue(mCurrentURL);
+ mAddressCombo->remove(mCurrentURL);
+ mAddressCombo->add(mCurrentURL);
+ mAddressCombo->selectByValue(mCurrentURL);
+
+ // Serialize url history
+ LLURLHistory::removeURL("browser", mCurrentURL);
+ LLURLHistory::addURL("browser", mCurrentURL);
- // Serialize url history
- LLURLHistory::removeURL("browser", mCurrentURL);
- LLURLHistory::addURL("browser", mCurrentURL);
- }
getChildView("back")->setEnabled(mBrowser->canNavigateBack());
getChildView("forward")->setEnabled(mBrowser->canNavigateForward());
getChildView("reload")->setEnabled(TRUE);
@@ -334,8 +331,15 @@ void LLFloaterMediaBrowser::onClickRefresh(void* user_data)
{
LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data;
- self->mAddressCombo->remove(0);
- self->mBrowser->navigateTo(self->mCurrentURL);
+ if( self->mBrowser->getMediaPlugin() && self->mBrowser->getMediaPlugin()->pluginSupportsMediaBrowser())
+ {
+ bool ignore_cache = true;
+ self->mBrowser->getMediaPlugin()->browse_reload( ignore_cache );
+ }
+ else
+ {
+ self->mBrowser->navigateTo(self->mCurrentURL);
+ }
}
//static
diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp
index 3ed4aec89a..2041fac8d8 100644
--- a/indra/newview/llfloatersearch.cpp
+++ b/indra/newview/llfloatersearch.cpp
@@ -200,5 +200,5 @@ void LLFloaterSearch::search(const LLSD &key)
url = LLWeb::expandURLSubstitutions(url, subs);
// and load the URL in the web view
- mBrowser->navigateTo(url);
+ mBrowser->navigateTo(url, "text/html");
}
diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp
new file mode 100644
index 0000000000..51726112a0
--- /dev/null
+++ b/indra/newview/llfloaterwebcontent.cpp
@@ -0,0 +1,402 @@
+/**
+ * @file llfloaterwebcontent.cpp
+ * @brief floater for displaying web content - e.g. profiles and search (eventually)
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llcombobox.h"
+#include "lliconctrl.h"
+#include "llfloaterreg.h"
+#include "lllayoutstack.h"
+#include "llpluginclassmedia.h"
+#include "llprogressbar.h"
+#include "lltextbox.h"
+#include "llurlhistory.h"
+#include "llviewercontrol.h"
+#include "llweb.h"
+#include "llwindow.h"
+
+#include "llfloaterwebcontent.h"
+
+LLFloaterWebContent::LLFloaterWebContent( const LLSD& key )
+ : LLFloater( key )
+{
+ mCommitCallbackRegistrar.add( "WebContent.Back", boost::bind( &LLFloaterWebContent::onClickBack, this ));
+ mCommitCallbackRegistrar.add( "WebContent.Forward", boost::bind( &LLFloaterWebContent::onClickForward, this ));
+ mCommitCallbackRegistrar.add( "WebContent.Reload", boost::bind( &LLFloaterWebContent::onClickReload, this ));
+ mCommitCallbackRegistrar.add( "WebContent.Stop", boost::bind( &LLFloaterWebContent::onClickStop, this ));
+ mCommitCallbackRegistrar.add( "WebContent.EnterAddress", boost::bind( &LLFloaterWebContent::onEnterAddress, this ));
+ mCommitCallbackRegistrar.add( "WebContent.PopExternal", boost::bind( &LLFloaterWebContent::onPopExternal, this ));
+}
+
+BOOL LLFloaterWebContent::postBuild()
+{
+ // these are used in a bunch of places so cache them
+ mWebBrowser = getChild< LLMediaCtrl >( "webbrowser" );
+ mAddressCombo = getChild< LLComboBox >( "address" );
+ mStatusBarText = getChild< LLTextBox >( "statusbartext" );
+ mStatusBarProgress = getChild<LLProgressBar>("statusbarprogress" );
+
+ // observe browser events
+ mWebBrowser->addObserver( this );
+
+ // these buttons are always enabled
+ getChildView("reload")->setEnabled( true );
+ getChildView("popexternal")->setEnabled( true );
+
+ // cache image for secure browsing
+ mSecureLockIcon = getChild< LLIconCtrl >("media_secure_lock_flag");
+
+ // initialize the URL history using the system URL History manager
+ initializeURLHistory();
+
+ return TRUE;
+}
+
+void LLFloaterWebContent::initializeURLHistory()
+{
+ // start with an empty list
+ LLCtrlListInterface* url_list = childGetListInterface("address");
+ if (url_list)
+ {
+ url_list->operateOnAll(LLCtrlListInterface::OP_DELETE);
+ }
+
+ // Get all of the entries in the "browser" collection
+ LLSD browser_history = LLURLHistory::getURLHistory("browser");
+ LLSD::array_iterator iter_history =
+ browser_history.beginArray();
+ LLSD::array_iterator end_history =
+ browser_history.endArray();
+ for(; iter_history != end_history; ++iter_history)
+ {
+ std::string url = (*iter_history).asString();
+ if(! url.empty())
+ url_list->addSimpleElement(url);
+ }
+}
+
+//static
+void LLFloaterWebContent::create( const std::string &url, const std::string& target, const std::string& uuid )
+{
+ lldebugs << "url = " << url << ", target = " << target << ", uuid = " << uuid << llendl;
+
+ std::string tag = target;
+
+ if(target.empty() || target == "_blank")
+ {
+ if(!uuid.empty())
+ {
+ tag = uuid;
+ }
+ else
+ {
+ // create a unique tag for this instance
+ LLUUID id;
+ id.generate();
+ tag = id.asString();
+ }
+ }
+
+ S32 browser_window_limit = gSavedSettings.getS32("WebContentWindowLimit");
+
+ if(LLFloaterReg::findInstance("web_content", tag) != NULL)
+ {
+ // There's already a web browser for this tag, so we won't be opening a new window.
+ }
+ else if(browser_window_limit != 0)
+ {
+ // showInstance will open a new window. Figure out how many web browsers are already open,
+ // and close the least recently opened one if this will put us over the limit.
+
+ LLFloaterReg::const_instance_list_t &instances = LLFloaterReg::getFloaterList("web_content");
+ lldebugs << "total instance count is " << instances.size() << llendl;
+
+ for(LLFloaterReg::const_instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); iter++)
+ {
+ lldebugs << " " << (*iter)->getKey() << llendl;
+ }
+
+ if(instances.size() >= (size_t)browser_window_limit)
+ {
+ // Destroy the least recently opened instance
+ (*instances.begin())->closeFloater();
+ }
+ }
+
+ LLFloaterWebContent *browser = dynamic_cast<LLFloaterWebContent*> (LLFloaterReg::showInstance("web_content", tag));
+ llassert(browser);
+ if(browser)
+ {
+ browser->mUUID = uuid;
+
+ // tell the browser instance to load the specified URL
+ browser->open_media(url, target);
+ LLViewerMedia::proxyWindowOpened(target, uuid);
+ }
+}
+
+//static
+void LLFloaterWebContent::closeRequest(const std::string &uuid)
+{
+ LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("web_content");
+ lldebugs << "instance list size is " << inst_list.size() << ", incoming uuid is " << uuid << llendl;
+ for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter)
+ {
+ LLFloaterWebContent* i = dynamic_cast<LLFloaterWebContent*>(*iter);
+ lldebugs << " " << i->mUUID << llendl;
+ if (i && i->mUUID == uuid)
+ {
+ i->closeFloater(false);
+ return;
+ }
+ }
+}
+
+//static
+void LLFloaterWebContent::geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height)
+{
+ LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("web_content");
+ lldebugs << "instance list size is " << inst_list.size() << ", incoming uuid is " << uuid << llendl;
+ for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter)
+ {
+ LLFloaterWebContent* i = dynamic_cast<LLFloaterWebContent*>(*iter);
+ lldebugs << " " << i->mUUID << llendl;
+ if (i && i->mUUID == uuid)
+ {
+ i->geometryChanged(x, y, width, height);
+ return;
+ }
+ }
+}
+
+void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height)
+{
+ // Make sure the layout of the browser control is updated, so this calculation is correct.
+ LLLayoutStack::updateClass();
+
+ // TODO: need to adjust size and constrain position to make sure floaters aren't moved outside the window view, etc.
+ LLCoordWindow window_size;
+ getWindow()->getSize(&window_size);
+
+ // Adjust width and height for the size of the chrome on the web Browser window.
+ width += getRect().getWidth() - mWebBrowser->getRect().getWidth();
+ height += getRect().getHeight() - mWebBrowser->getRect().getHeight();
+
+ LLRect geom;
+ geom.setOriginAndSize(x, window_size.mY - (y + height), width, height);
+
+ lldebugs << "geometry change: " << geom << llendl;
+
+ handleReshape(geom,false);
+}
+
+void LLFloaterWebContent::open_media(const std::string& web_url, const std::string& target)
+{
+ // Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin.
+ mWebBrowser->setHomePageUrl(web_url, "text/html");
+ mWebBrowser->setTarget(target);
+ mWebBrowser->navigateTo(web_url, "text/html");
+ set_current_url(web_url);
+}
+
+//virtual
+void LLFloaterWebContent::onClose(bool app_quitting)
+{
+ LLViewerMedia::proxyWindowClosed(mUUID);
+ destroy();
+}
+
+// virtual
+void LLFloaterWebContent::draw()
+{
+ // this is asychronous so we need to keep checking
+ getChildView( "back" )->setEnabled( mWebBrowser->canNavigateBack() );
+ getChildView( "forward" )->setEnabled( mWebBrowser->canNavigateForward() );
+
+ LLFloater::draw();
+}
+
+// virtual
+void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
+{
+ if(event == MEDIA_EVENT_LOCATION_CHANGED)
+ {
+ const std::string url = self->getLocation();
+
+ if ( url.length() )
+ mStatusBarText->setText( url );
+
+ set_current_url( url );
+ }
+ else if(event == MEDIA_EVENT_NAVIGATE_BEGIN)
+ {
+ // flags are sent with this event
+ getChildView("back")->setEnabled( self->getHistoryBackAvailable() );
+ getChildView("forward")->setEnabled( self->getHistoryForwardAvailable() );
+
+ // toggle visibility of these buttons based on browser state
+ getChildView("reload")->setVisible( false );
+ getChildView("stop")->setVisible( true );
+
+ // turn "on" progress bar now we're about to start loading
+ mStatusBarProgress->setVisible( true );
+ }
+ else if(event == MEDIA_EVENT_NAVIGATE_COMPLETE)
+ {
+ // flags are sent with this event
+ getChildView("back")->setEnabled( self->getHistoryBackAvailable() );
+ getChildView("forward")->setEnabled( self->getHistoryForwardAvailable() );
+
+ // toggle visibility of these buttons based on browser state
+ getChildView("reload")->setVisible( true );
+ getChildView("stop")->setVisible( false );
+
+ // turn "off" progress bar now we're loaded
+ mStatusBarProgress->setVisible( false );
+
+ // we populate the status bar with URLs as they change so clear it now we're done
+ const std::string end_str = "";
+ mStatusBarText->setText( end_str );
+
+ // decide if secure browsing icon should be displayed
+ std::string prefix = std::string("https://");
+ std::string test_prefix = mCurrentURL.substr(0, prefix.length());
+ LLStringUtil::toLower(test_prefix);
+ if(test_prefix == prefix)
+ {
+ mSecureLockIcon->setVisible(true);
+ }
+ else
+ {
+ mSecureLockIcon->setVisible(false);
+ }
+ }
+ else if(event == MEDIA_EVENT_CLOSE_REQUEST)
+ {
+ // The browser instance wants its window closed.
+ closeFloater();
+ }
+ else if(event == MEDIA_EVENT_GEOMETRY_CHANGE)
+ {
+ geometryChanged(self->getGeometryX(), self->getGeometryY(), self->getGeometryWidth(), self->getGeometryHeight());
+ }
+ else if(event == MEDIA_EVENT_STATUS_TEXT_CHANGED )
+ {
+ const std::string text = self->getStatusText();
+ if ( text.length() )
+ mStatusBarText->setText( text );
+ }
+ else if(event == MEDIA_EVENT_PROGRESS_UPDATED )
+ {
+ int percent = (int)self->getProgressPercent();
+ mStatusBarProgress->setValue( percent );
+ }
+ else if(event == MEDIA_EVENT_NAME_CHANGED )
+ {
+ std::string page_title = self->getMediaName();
+ // simulate browser behavior - title is empty, use the current URL
+ if ( page_title.length() > 0 )
+ setTitle( page_title );
+ else
+ setTitle( mCurrentURL );
+ }
+ else if(event == MEDIA_EVENT_LINK_HOVERED )
+ {
+ const std::string link = self->getHoverLink();
+ mStatusBarText->setText( link );
+ }
+}
+
+void LLFloaterWebContent::set_current_url(const std::string& url)
+{
+ mCurrentURL = url;
+
+ // serialize url history into the system URL History manager
+ LLURLHistory::removeURL("browser", mCurrentURL);
+ LLURLHistory::addURL("browser", mCurrentURL);
+
+ mAddressCombo->remove( mCurrentURL );
+ mAddressCombo->add( mCurrentURL );
+ mAddressCombo->selectByValue( mCurrentURL );
+}
+
+void LLFloaterWebContent::onClickForward()
+{
+ mWebBrowser->navigateForward();
+}
+
+void LLFloaterWebContent::onClickBack()
+{
+ mWebBrowser->navigateBack();
+}
+
+void LLFloaterWebContent::onClickReload()
+{
+
+ if( mWebBrowser->getMediaPlugin() )
+ {
+ bool ignore_cache = true;
+ mWebBrowser->getMediaPlugin()->browse_reload( ignore_cache );
+ }
+ else
+ {
+ mWebBrowser->navigateTo(mCurrentURL);
+ }
+}
+
+void LLFloaterWebContent::onClickStop()
+{
+ if( mWebBrowser->getMediaPlugin() )
+ mWebBrowser->getMediaPlugin()->browse_stop();
+
+ // still should happen when we catch the navigate complete event
+ // but sometimes (don't know why) that event isn't sent from Qt
+ // and we getto a point where the stop button stays active.
+ getChildView("reload")->setVisible( true );
+ getChildView("stop")->setVisible( false );
+}
+
+void LLFloaterWebContent::onEnterAddress()
+{
+ // make sure there is at least something there.
+ // (perhaps this test should be for minimum length of a URL)
+ std::string url = mAddressCombo->getValue().asString();
+ if ( url.length() > 0 )
+ {
+ mWebBrowser->navigateTo( url, "text/html");
+ };
+}
+
+void LLFloaterWebContent::onPopExternal()
+{
+ // make sure there is at least something there.
+ // (perhaps this test should be for minimum length of a URL)
+ std::string url = mAddressCombo->getValue().asString();
+ if ( url.length() > 0 )
+ {
+ LLWeb::loadURLExternal( url );
+ };
+}
diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h
new file mode 100644
index 0000000000..001d822ada
--- /dev/null
+++ b/indra/newview/llfloaterwebcontent.h
@@ -0,0 +1,82 @@
+/**
+ * @file llfloaterwebcontent.h
+ * @brief floater for displaying web content - e.g. profiles and search (eventually)
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLOATERWEBCONTENT_H
+#define LL_LLFLOATERWEBCONTENT_H
+
+#include "llfloater.h"
+#include "llmediactrl.h"
+
+class LLMediaCtrl;
+class LLComboBox;
+class LLTextBox;
+class LLProgressBar;
+class LLIconCtrl;
+
+class LLFloaterWebContent :
+ public LLFloater,
+ public LLViewerMediaObserver
+{
+public:
+ LOG_CLASS(LLFloaterWebContent);
+ LLFloaterWebContent(const LLSD& key);
+
+ void initializeURLHistory();
+
+ static void create(const std::string &url, const std::string& target, const std::string& uuid = LLStringUtil::null);
+
+ static void closeRequest(const std::string &uuid);
+ static void geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height);
+ void geometryChanged(S32 x, S32 y, S32 width, S32 height);
+
+ /* virtual */ BOOL postBuild();
+ /* virtual */ void onClose(bool app_quitting);
+ /* virtual */ void draw();
+
+ // inherited from LLViewerMediaObserver
+ /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
+
+ void onClickBack();
+ void onClickForward();
+ void onClickReload();
+ void onClickStop();
+ void onEnterAddress();
+ void onPopExternal();
+
+private:
+ void open_media(const std::string& media_url, const std::string& target);
+ void set_current_url(const std::string& url);
+
+ LLMediaCtrl* mWebBrowser;
+ LLComboBox* mAddressCombo;
+ LLIconCtrl *mSecureLockIcon;
+ LLTextBox* mStatusBarText;
+ LLProgressBar* mStatusBarProgress;
+ std::string mCurrentURL;
+ std::string mUUID;
+};
+
+#endif // LL_LLFLOATERWEBCONTENT_H
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index bdc0dfa7e2..f74ae92a7b 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -470,7 +470,7 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id)
}
//static
-bool LLIMFloater::resetAllowedRectPadding(const LLSD& newvalue)
+bool LLIMFloater::resetAllowedRectPadding()
{
//reset allowed rect right padding if "SidebarCameraMovement" option
//or sidebar state changed
@@ -482,10 +482,10 @@ void LLIMFloater::getAllowedRect(LLRect& rect)
{
if (sAllowedRectRightPadding == RECT_PADDING_NOT_INIT) //wasn't initialized
{
- gSavedSettings.getControl("SidebarCameraMovement")->getSignal()->connect(boost::bind(&LLIMFloater::resetAllowedRectPadding, _2));
+ gSavedSettings.getControl("SidebarCameraMovement")->getSignal()->connect(boost::bind(&LLIMFloater::resetAllowedRectPadding));
LLSideTray* side_bar = LLSideTray::getInstance();
- side_bar->getCollapseSignal().connect(boost::bind(&LLIMFloater::resetAllowedRectPadding, _2));
+ side_bar->setVisibleWidthChangeCallback(boost::bind(&LLIMFloater::resetAllowedRectPadding));
sAllowedRectRightPadding = RECT_PADDING_NEED_RECALC;
}
@@ -500,10 +500,7 @@ void LLIMFloater::getAllowedRect(LLRect& rect)
if (gSavedSettings.getBOOL("SidebarCameraMovement") == FALSE)
{
- LLSideTray* side_bar = LLSideTray::getInstance();
-
- if (side_bar->getVisible() && !side_bar->getCollapsed())
- sAllowedRectRightPadding += side_bar->getRect().getWidth();
+ sAllowedRectRightPadding += LLSideTray::getInstance()->getVisibleWidth();
}
}
rect.mRight -= sAllowedRectRightPadding;
diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h
index e80e45e64a..5158f6c1f7 100644
--- a/indra/newview/llimfloater.h
+++ b/indra/newview/llimfloater.h
@@ -156,7 +156,7 @@ private:
static void closeHiddenIMToasts();
- static bool resetAllowedRectPadding(const LLSD& newvalue);
+ static bool resetAllowedRectPadding();
//need to keep this static for performance issues
static S32 sAllowedRectRightPadding;
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index ab0acbae50..5108f68592 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -5344,11 +5344,6 @@ void LLRecentItemsFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
menuentry_vec_t disabled_items, items = getMenuItems();
- items.erase(std::remove(items.begin(), items.end(), std::string("New Body Parts")), items.end());
- items.erase(std::remove(items.begin(), items.end(), std::string("New Clothes")), items.end());
- items.erase(std::remove(items.begin(), items.end(), std::string("New Note")), items.end());
- items.erase(std::remove(items.begin(), items.end(), std::string("New Gesture")), items.end());
- items.erase(std::remove(items.begin(), items.end(), std::string("New Script")), items.end());
items.erase(std::remove(items.begin(), items.end(), std::string("New Folder")), items.end());
hide_context_entries(menu, items, disabled_items);
diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp
index 0546803784..d866db1829 100644
--- a/indra/newview/lllogininstance.cpp
+++ b/indra/newview/lllogininstance.cpp
@@ -49,18 +49,421 @@
#include "llnotifications.h"
#include "llwindow.h"
#include "llviewerwindow.h"
+#include "llprogressview.h"
#if LL_LINUX || LL_SOLARIS
#include "lltrans.h"
#endif
#include "llsecapi.h"
#include "llstartup.h"
#include "llmachineid.h"
+#include "llupdaterservice.h"
+#include "llevents.h"
+#include "llnotificationsutil.h"
+#include "llappviewer.h"
+
+#include <boost/scoped_ptr.hpp>
+#include <sstream>
+
+class LLLoginInstance::Disposable {
+public:
+ virtual ~Disposable() {}
+};
+
+namespace {
+ class MandatoryUpdateMachine:
+ public LLLoginInstance::Disposable
+ {
+ public:
+ MandatoryUpdateMachine(LLLoginInstance & loginInstance, LLUpdaterService & updaterService);
+
+ void start(void);
+
+ private:
+ class State;
+ class CheckingForUpdate;
+ class Error;
+ class ReadyToInstall;
+ class StartingUpdaterService;
+ class WaitingForDownload;
+
+ LLLoginInstance & mLoginInstance;
+ boost::scoped_ptr<State> mState;
+ LLUpdaterService & mUpdaterService;
+
+ void setCurrentState(State * newState);
+ };
+
+
+ class MandatoryUpdateMachine::State {
+ public:
+ virtual ~State() {}
+ virtual void enter(void) {}
+ virtual void exit(void) {}
+ };
+
+
+ class MandatoryUpdateMachine::CheckingForUpdate:
+ public MandatoryUpdateMachine::State
+ {
+ public:
+ CheckingForUpdate(MandatoryUpdateMachine & machine);
+
+ virtual void enter(void);
+ virtual void exit(void);
+
+ private:
+ LLTempBoundListener mConnection;
+ MandatoryUpdateMachine & mMachine;
+ LLProgressView * mProgressView;
+
+ bool onEvent(LLSD const & event);
+ };
+
+
+ class MandatoryUpdateMachine::Error:
+ public MandatoryUpdateMachine::State
+ {
+ public:
+ Error(MandatoryUpdateMachine & machine);
+
+ virtual void enter(void);
+ virtual void exit(void);
+ void onButtonClicked(const LLSD &, const LLSD &);
+
+ private:
+ MandatoryUpdateMachine & mMachine;
+ };
+
+
+ class MandatoryUpdateMachine::ReadyToInstall:
+ public MandatoryUpdateMachine::State
+ {
+ public:
+ ReadyToInstall(MandatoryUpdateMachine & machine);
+
+ virtual void enter(void);
+ virtual void exit(void);
+
+ private:
+ MandatoryUpdateMachine & mMachine;
+ };
+
+
+ class MandatoryUpdateMachine::StartingUpdaterService:
+ public MandatoryUpdateMachine::State
+ {
+ public:
+ StartingUpdaterService(MandatoryUpdateMachine & machine);
+
+ virtual void enter(void);
+ virtual void exit(void);
+ void onButtonClicked(const LLSD & uiform, const LLSD & result);
+ private:
+ MandatoryUpdateMachine & mMachine;
+ };
+
+
+ class MandatoryUpdateMachine::WaitingForDownload:
+ public MandatoryUpdateMachine::State
+ {
+ public:
+ WaitingForDownload(MandatoryUpdateMachine & machine);
+
+ virtual void enter(void);
+ virtual void exit(void);
+
+ private:
+ LLTempBoundListener mConnection;
+ MandatoryUpdateMachine & mMachine;
+ LLProgressView * mProgressView;
+
+ bool onEvent(LLSD const & event);
+ };
+}
static const char * const TOS_REPLY_PUMP = "lllogininstance_tos_callback";
static const char * const TOS_LISTENER_NAME = "lllogininstance_tos";
std::string construct_start_string();
+
+
+// MandatoryUpdateMachine
+//-----------------------------------------------------------------------------
+
+
+MandatoryUpdateMachine::MandatoryUpdateMachine(LLLoginInstance & loginInstance, LLUpdaterService & updaterService):
+ mLoginInstance(loginInstance),
+ mUpdaterService(updaterService)
+{
+ ; // No op.
+}
+
+
+void MandatoryUpdateMachine::start(void)
+{
+ llinfos << "starting manditory update machine" << llendl;
+
+ if(mUpdaterService.isChecking()) {
+ switch(mUpdaterService.getState()) {
+ case LLUpdaterService::UP_TO_DATE:
+ mUpdaterService.stopChecking();
+ mUpdaterService.startChecking();
+ // Fall through.
+ case LLUpdaterService::INITIAL:
+ case LLUpdaterService::CHECKING_FOR_UPDATE:
+ setCurrentState(new CheckingForUpdate(*this));
+ break;
+ case LLUpdaterService::DOWNLOADING:
+ setCurrentState(new WaitingForDownload(*this));
+ break;
+ case LLUpdaterService::TERMINAL:
+ if(LLUpdaterService::updateReadyToInstall()) {
+ setCurrentState(new ReadyToInstall(*this));
+ } else {
+ setCurrentState(new Error(*this));
+ }
+ break;
+ case LLUpdaterService::FAILURE:
+ setCurrentState(new Error(*this));
+ break;
+ default:
+ llassert(!"unpossible case");
+ break;
+ }
+ } else {
+ setCurrentState(new StartingUpdaterService(*this));
+ }
+}
+
+
+void MandatoryUpdateMachine::setCurrentState(State * newStatePointer)
+{
+ {
+ boost::scoped_ptr<State> newState(newStatePointer);
+ if(mState != 0) mState->exit();
+ mState.swap(newState);
+
+ // Old state will be deleted on exit from this block before the new state
+ // is entered.
+ }
+ if(mState != 0) mState->enter();
+}
+
+
+
+// MandatoryUpdateMachine::CheckingForUpdate
+//-----------------------------------------------------------------------------
+
+
+MandatoryUpdateMachine::CheckingForUpdate::CheckingForUpdate(MandatoryUpdateMachine & machine):
+ mMachine(machine)
+{
+ ; // No op.
+}
+
+
+void MandatoryUpdateMachine::CheckingForUpdate::enter(void)
+{
+ llinfos << "entering checking for update" << llendl;
+
+ mProgressView = gViewerWindow->getProgressView();
+ mProgressView->setMessage("Looking for update...");
+ mProgressView->setText("There is a required update for your Second Life installation.");
+ mProgressView->setPercent(0);
+ mProgressView->setVisible(true);
+ mConnection = LLEventPumps::instance().obtain(LLUpdaterService::pumpName()).
+ listen("MandatoryUpdateMachine::CheckingForUpdate", boost::bind(&MandatoryUpdateMachine::CheckingForUpdate::onEvent, this, _1));
+}
+
+
+void MandatoryUpdateMachine::CheckingForUpdate::exit(void)
+{
+}
+
+
+bool MandatoryUpdateMachine::CheckingForUpdate::onEvent(LLSD const & event)
+{
+ if(event["type"].asInteger() == LLUpdaterService::STATE_CHANGE) {
+ switch(event["state"].asInteger()) {
+ case LLUpdaterService::DOWNLOADING:
+ mMachine.setCurrentState(new WaitingForDownload(mMachine));
+ break;
+ case LLUpdaterService::UP_TO_DATE:
+ case LLUpdaterService::TERMINAL:
+ case LLUpdaterService::FAILURE:
+ mProgressView->setVisible(false);
+ mMachine.setCurrentState(new Error(mMachine));
+ break;
+ case LLUpdaterService::INSTALLING:
+ llassert(!"can't possibly be installing");
+ break;
+ default:
+ break;
+ }
+ } else {
+ ; // Ignore.
+ }
+
+ return false;
+}
+
+
+
+// MandatoryUpdateMachine::Error
+//-----------------------------------------------------------------------------
+
+
+MandatoryUpdateMachine::Error::Error(MandatoryUpdateMachine & machine):
+ mMachine(machine)
+{
+ ; // No op.
+}
+
+
+void MandatoryUpdateMachine::Error::enter(void)
+{
+ llinfos << "entering error" << llendl;
+ LLNotificationsUtil::add("FailedUpdateInstall", LLSD(), LLSD(), boost::bind(&MandatoryUpdateMachine::Error::onButtonClicked, this, _1, _2));
+}
+
+
+void MandatoryUpdateMachine::Error::exit(void)
+{
+ LLAppViewer::instance()->forceQuit();
+}
+
+
+void MandatoryUpdateMachine::Error::onButtonClicked(const LLSD &, const LLSD &)
+{
+ mMachine.setCurrentState(0);
+}
+
+
+
+// MandatoryUpdateMachine::ReadyToInstall
+//-----------------------------------------------------------------------------
+
+
+MandatoryUpdateMachine::ReadyToInstall::ReadyToInstall(MandatoryUpdateMachine & machine):
+ mMachine(machine)
+{
+ ; // No op.
+}
+
+
+void MandatoryUpdateMachine::ReadyToInstall::enter(void)
+{
+ llinfos << "entering ready to install" << llendl;
+ // Open update ready dialog.
+}
+
+
+void MandatoryUpdateMachine::ReadyToInstall::exit(void)
+{
+ // Restart viewer.
+}
+
+
+
+// MandatoryUpdateMachine::StartingUpdaterService
+//-----------------------------------------------------------------------------
+
+
+MandatoryUpdateMachine::StartingUpdaterService::StartingUpdaterService(MandatoryUpdateMachine & machine):
+ mMachine(machine)
+{
+ ; // No op.
+}
+
+
+void MandatoryUpdateMachine::StartingUpdaterService::enter(void)
+{
+ llinfos << "entering start update service" << llendl;
+ LLNotificationsUtil::add("UpdaterServiceNotRunning", LLSD(), LLSD(), boost::bind(&MandatoryUpdateMachine::StartingUpdaterService::onButtonClicked, this, _1, _2));
+}
+
+
+void MandatoryUpdateMachine::StartingUpdaterService::exit(void)
+{
+ ; // No op.
+}
+
+
+void MandatoryUpdateMachine::StartingUpdaterService::onButtonClicked(const LLSD & uiform, const LLSD & result)
+{
+ if(result["OK_okcancelbuttons"].asBoolean()) {
+ mMachine.mUpdaterService.startChecking(false);
+ mMachine.setCurrentState(new CheckingForUpdate(mMachine));
+ } else {
+ LLAppViewer::instance()->forceQuit();
+ }
+}
+
+
+
+// MandatoryUpdateMachine::WaitingForDownload
+//-----------------------------------------------------------------------------
+
+
+MandatoryUpdateMachine::WaitingForDownload::WaitingForDownload(MandatoryUpdateMachine & machine):
+ mMachine(machine),
+ mProgressView(0)
+{
+ ; // No op.
+}
+
+
+void MandatoryUpdateMachine::WaitingForDownload::enter(void)
+{
+ llinfos << "entering waiting for download" << llendl;
+ mProgressView = gViewerWindow->getProgressView();
+ mProgressView->setMessage("Downloading update...");
+ std::ostringstream stream;
+ stream << "There is a required update for your Second Life installation." << std::endl <<
+ "Version " << mMachine.mUpdaterService.updatedVersion();
+ mProgressView->setText(stream.str());
+ mProgressView->setPercent(0);
+ mProgressView->setVisible(true);
+ mConnection = LLEventPumps::instance().obtain(LLUpdaterService::pumpName()).
+ listen("MandatoryUpdateMachine::CheckingForUpdate", boost::bind(&MandatoryUpdateMachine::WaitingForDownload::onEvent, this, _1));
+}
+
+
+void MandatoryUpdateMachine::WaitingForDownload::exit(void)
+{
+ mProgressView->setVisible(false);
+}
+
+
+bool MandatoryUpdateMachine::WaitingForDownload::onEvent(LLSD const & event)
+{
+ switch(event["type"].asInteger()) {
+ case LLUpdaterService::DOWNLOAD_COMPLETE:
+ mMachine.setCurrentState(new ReadyToInstall(mMachine));
+ break;
+ case LLUpdaterService::DOWNLOAD_ERROR:
+ mMachine.setCurrentState(new Error(mMachine));
+ break;
+ case LLUpdaterService::PROGRESS: {
+ double downloadSize = event["download_size"].asReal();
+ double bytesDownloaded = event["bytes_downloaded"].asReal();
+ mProgressView->setPercent(100. * bytesDownloaded / downloadSize);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return false;
+}
+
+
+
+// LLLoginInstance
+//-----------------------------------------------------------------------------
+
+
LLLoginInstance::LLLoginInstance() :
mLoginModule(new LLLogin()),
mNotifications(NULL),
@@ -69,7 +472,8 @@ LLLoginInstance::LLLoginInstance() :
mSkipOptionalUpdate(false),
mAttemptComplete(false),
mTransferRate(0.0f),
- mDispatcher("LLLoginInstance", "change")
+ mDispatcher("LLLoginInstance", "change"),
+ mUpdaterService(0)
{
mLoginModule->getEventPump().listen("lllogininstance",
boost::bind(&LLLoginInstance::handleLoginEvent, this, _1));
@@ -354,6 +758,15 @@ bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key)
void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg)
{
+ if(mandatory)
+ {
+ gViewerWindow->setShowProgress(false);
+ MandatoryUpdateMachine * machine = new MandatoryUpdateMachine(*this, *mUpdaterService);
+ mUpdateStateMachine.reset(machine);
+ machine->start();
+ return;
+ }
+
// store off config state, as we might quit soon
gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE);
LLUIColorTable::instance().saveUserSettings();
diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h
index 159e05046c..b872d7d1b1 100644
--- a/indra/newview/lllogininstance.h
+++ b/indra/newview/lllogininstance.h
@@ -34,12 +34,15 @@
class LLLogin;
class LLEventStream;
class LLNotificationsInterface;
+class LLUpdaterService;
// This class hosts the login module and is used to
// negotiate user authentication attempts.
class LLLoginInstance : public LLSingleton<LLLoginInstance>
{
public:
+ class Disposable;
+
LLLoginInstance();
~LLLoginInstance();
@@ -75,6 +78,7 @@ public:
typedef boost::function<void()> UpdaterLauncherCallback;
void setUpdaterLauncher(const UpdaterLauncherCallback& ulc) { mUpdaterLauncher = ulc; }
+ void setUpdaterService(LLUpdaterService * updaterService) { mUpdaterService = updaterService; }
private:
void constructAuthParams(LLPointer<LLCredential> user_credentials);
void updateApp(bool mandatory, const std::string& message);
@@ -104,6 +108,8 @@ private:
int mLastExecEvent;
UpdaterLauncherCallback mUpdaterLauncher;
LLEventDispatcher mDispatcher;
+ LLUpdaterService * mUpdaterService;
+ boost::scoped_ptr<Disposable> mUpdateStateMachine;
};
#endif
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 0f66713ab0..9493fddf50 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -25,7 +25,7 @@
*/
#include "llviewerprecompiledheaders.h"
-
+#include "lltooltip.h"
#include "llmediactrl.h"
@@ -54,6 +54,10 @@
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llnotifications.h"
+#include "lllineeditor.h"
+#include "llfloatermediabrowser.h"
+#include "llfloaterwebcontent.h"
+#include "llwindowshade.h"
extern BOOL gRestoreGL;
@@ -98,7 +102,9 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :
mTextureHeight ( 1024 ),
mClearCache(false),
mHomePageMimeType(p.initial_mime_type),
- mTrusted(p.trusted_content)
+ mTrusted(p.trusted_content),
+ mWindowShade(NULL),
+ mHoverTextChanged(false)
{
{
LLColor4 color = p.caret_color().get();
@@ -127,7 +133,7 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :
setTextureSize(screen_width, screen_height);
}
- mMediaTextureID.generate();
+ mMediaTextureID = getKey();
// We don't need to create the media source up front anymore unless we have a non-empty home URL to navigate to.
if(!mHomePageUrl.empty())
@@ -141,8 +147,6 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :
// addChild( mBorder );
}
-////////////////////////////////////////////////////////////////////////////////
-// note: this is now a singleton and destruction happens via initClass() now
LLMediaCtrl::~LLMediaCtrl()
{
@@ -182,6 +186,13 @@ BOOL LLMediaCtrl::handleHover( S32 x, S32 y, MASK mask )
mMediaSource->mouseMove(x, y, mask);
gViewerWindow->setCursor(mMediaSource->getLastSetCursor());
}
+
+ // TODO: Is this the right way to handle hover text changes driven by the plugin?
+ if(mHoverTextChanged)
+ {
+ mHoverTextChanged = false;
+ handleToolTip(x, y, mask);
+ }
return TRUE;
}
@@ -198,6 +209,35 @@ BOOL LLMediaCtrl::handleScrollWheel( S32 x, S32 y, S32 clicks )
}
////////////////////////////////////////////////////////////////////////////////
+// virtual
+BOOL LLMediaCtrl::handleToolTip(S32 x, S32 y, MASK mask)
+{
+ std::string hover_text;
+
+ if (mMediaSource && mMediaSource->hasMedia())
+ hover_text = mMediaSource->getMediaPlugin()->getHoverText();
+
+ if(hover_text.empty())
+ {
+ return FALSE;
+ }
+ else
+ {
+ S32 screen_x, screen_y;
+
+ localPointToScreen(x, y, &screen_x, &screen_y);
+ LLRect sticky_rect_screen;
+ sticky_rect_screen.setCenterAndSize(screen_x, screen_y, 20, 20);
+
+ LLToolTipMgr::instance().show(LLToolTip::Params()
+ .message(hover_text)
+ .sticky_rect(sticky_rect_screen));
+ }
+
+ return TRUE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
//
BOOL LLMediaCtrl::handleMouseUp( S32 x, S32 y, MASK mask )
{
@@ -338,85 +378,6 @@ void LLMediaCtrl::onFocusLost()
//
BOOL LLMediaCtrl::postBuild ()
{
- LLLayoutStack::Params layout_p;
- layout_p.name = "notification_stack";
- layout_p.rect = LLRect(0,getLocalRect().mTop,getLocalRect().mRight, 30);
- layout_p.follows.flags = FOLLOWS_ALL;
- layout_p.mouse_opaque = false;
- layout_p.orientation = "vertical";
-
- LLLayoutStack* stackp = LLUICtrlFactory::create<LLLayoutStack>(layout_p);
- addChild(stackp);
-
- LLLayoutPanel::Params panel_p;
- panel_p.rect = LLRect(0, 30, 800, 0);
- panel_p.min_height = 30;
- panel_p.name = "notification_area";
- panel_p.visible = false;
- panel_p.user_resize = false;
- panel_p.background_visible = true;
- panel_p.bg_alpha_image.name = "Yellow_Gradient";
- panel_p.auto_resize = false;
- LLLayoutPanel* notification_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p);
- stackp->addChild(notification_panel);
-
- panel_p = LLUICtrlFactory::getDefaultParams<LLLayoutPanel>();
- panel_p.auto_resize = true;
- panel_p.mouse_opaque = false;
- LLLayoutPanel* dummy_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p);
- stackp->addChild(dummy_panel);
-
- layout_p = LLUICtrlFactory::getDefaultParams<LLLayoutStack>();
- layout_p.rect = LLRect(0, 30, 800, 0);
- layout_p.follows.flags = FOLLOWS_ALL;
- layout_p.orientation = "horizontal";
- stackp = LLUICtrlFactory::create<LLLayoutStack>(layout_p);
- notification_panel->addChild(stackp);
-
- panel_p = LLUICtrlFactory::getDefaultParams<LLLayoutPanel>();
- panel_p.rect.height = 30;
- LLLayoutPanel* panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p);
- stackp->addChild(panel);
-
- LLIconCtrl::Params icon_p;
- icon_p.name = "notification_icon";
- icon_p.rect = LLRect(5, 23, 21, 8);
- panel->addChild(LLUICtrlFactory::create<LLIconCtrl>(icon_p));
-
- LLTextBox::Params text_p;
- text_p.rect = LLRect(31, 20, 430, 0);
- text_p.text_color = LLColor4::black;
- text_p.font = LLFontGL::getFontSansSerif();
- text_p.font.style = "BOLD";
- text_p.name = "notification_text";
- text_p.use_ellipses = true;
- panel->addChild(LLUICtrlFactory::create<LLTextBox>(text_p));
-
- panel_p = LLUICtrlFactory::getDefaultParams<LLLayoutPanel>();
- panel_p.auto_resize = false;
- panel_p.user_resize = false;
- panel_p.name="form_elements";
- panel_p.rect = LLRect(0, 30, 130, 0);
- LLLayoutPanel* form_elements_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p);
- stackp->addChild(form_elements_panel);
-
- panel_p = LLUICtrlFactory::getDefaultParams<LLLayoutPanel>();
- panel_p.auto_resize = false;
- panel_p.user_resize = false;
- panel_p.rect = LLRect(0, 30, 25, 0);
- LLLayoutPanel* close_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p);
- stackp->addChild(close_panel);
-
- LLButton::Params button_p;
- button_p.name = "close_notification";
- button_p.rect = LLRect(5, 23, 21, 7);
- button_p.image_color=LLUIColorTable::instance().getColor("DkGray_66");
- button_p.image_unselected.name="Icon_Close_Foreground";
- button_p.image_selected.name="Icon_Close_Press";
- button_p.click_callback.function = boost::bind(&LLMediaCtrl::onCloseNotification, this);
-
- close_panel->addChild(LLUICtrlFactory::create<LLButton>(button_p));
-
setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChange, this, _2));
return TRUE;
}
@@ -425,13 +386,15 @@ BOOL LLMediaCtrl::postBuild ()
//
BOOL LLMediaCtrl::handleKeyHere( KEY key, MASK mask )
{
- if (LLPanel::handleKeyHere(key, mask)) return TRUE;
BOOL result = FALSE;
if (mMediaSource)
{
result = mMediaSource->handleKeyHere(key, mask);
}
+
+ if ( ! result )
+ result = LLPanel::handleKeyHere(key, mask);
return result;
}
@@ -451,7 +414,6 @@ void LLMediaCtrl::handleVisibilityChange ( BOOL new_visibility )
//
BOOL LLMediaCtrl::handleUnicodeCharHere(llwchar uni_char)
{
- if (LLPanel::handleUnicodeCharHere(uni_char)) return TRUE;
BOOL result = FALSE;
if (mMediaSource)
@@ -459,6 +421,9 @@ BOOL LLMediaCtrl::handleUnicodeCharHere(llwchar uni_char)
result = mMediaSource->handleUnicodeCharHere(uni_char);
}
+ if ( ! result )
+ result = LLPanel::handleUnicodeCharHere(uni_char);
+
return result;
}
@@ -914,11 +879,6 @@ void LLMediaCtrl::draw()
if ( mBorder && mBorder->getVisible() )
mBorder->setKeyboardFocusHighlight( gFocusMgr.childHasKeyboardFocus( this ) );
- if (mCurNotification && !mCurNotification->isActive())
- {
- hideNotification();
- }
-
LLPanel::draw();
// Restore the previous values
@@ -1026,7 +986,7 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
LLNotification::Params notify_params;
notify_params.name = "PopupAttempt";
- notify_params.payload = LLSD().with("target", target).with("url", url).with("uuid", uuid).with("media_id", getKey());
+ notify_params.payload = LLSD().with("target", target).with("url", url).with("uuid", uuid).with("media_id", mMediaTextureID);
notify_params.functor.function = boost::bind(&LLMediaCtrl::onPopup, this, _1, _2);
if (mTrusted)
@@ -1081,6 +1041,31 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_GEOMETRY_CHANGE, uuid is " << self->getClickUUID() << LL_ENDL;
}
break;
+
+ case MEDIA_EVENT_AUTH_REQUEST:
+ {
+ LLNotification::Params auth_request_params;
+ auth_request_params.name = "AuthRequest";
+
+ // pass in host name and realm for site (may be zero length but will always exist)
+ LLSD args;
+ LLURL raw_url( self->getAuthURL().c_str() );
+ args["HOST_NAME"] = raw_url.getAuthority();
+ args["REALM"] = self->getAuthRealm();
+ auth_request_params.substitutions = args;
+
+ auth_request_params.payload = LLSD().with("media_id", mMediaTextureID);
+ auth_request_params.functor.function = boost::bind(&LLViewerMedia::onAuthSubmit, _1, _2);
+ LLNotifications::instance().add(auth_request_params);
+ };
+ break;
+
+ case MEDIA_EVENT_LINK_HOVERED:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_LINK_HOVERED, hover text is: " << self->getHoverText() << LL_ENDL;
+ mHoverTextChanged = true;
+ };
+ break;
};
// chain all events to any potential observers of this object.
@@ -1098,109 +1083,85 @@ void LLMediaCtrl::onPopup(const LLSD& notification, const LLSD& response)
{
if (response["open"])
{
- LLWeb::loadURL(notification["payload"]["url"], notification["payload"]["target"], notification["payload"]["uuid"]);
+ // name of default floater to open
+ std::string floater_name = "media_browser";
+
+ // look for parent floater name
+ if ( gFloaterView )
+ {
+ if ( gFloaterView->getParentFloater(this) )
+ {
+ floater_name = gFloaterView->getParentFloater(this)->getInstanceName();
+ }
+ else
+ {
+ lldebugs << "No gFloaterView->getParentFloater(this) for onPopuup()" << llendl;
+ };
+ }
+ else
+ {
+ lldebugs << "No gFloaterView for onPopuup()" << llendl;
+ };
+
+ // (for now) open web content floater if that's our parent, otherwise, open the current media floater
+ // (this will change soon)
+ if ( floater_name == "web_content" )
+ {
+ LLWeb::loadWebURL(notification["payload"]["url"], notification["payload"]["target"], notification["payload"]["uuid"]);
+ }
+ else
+ {
+ LLWeb::loadURL(notification["payload"]["url"], notification["payload"]["target"], notification["payload"]["uuid"]);
+ }
}
else
{
// Make sure the opening instance knows its window open request was denied, so it can clean things up.
LLViewerMedia::proxyWindowClosed(notification["payload"]["uuid"]);
}
-
}
-void LLMediaCtrl::onCloseNotification()
-{
- LLNotifications::instance().cancel(mCurNotification);
-}
-
-void LLMediaCtrl::onClickIgnore(LLUICtrl* ctrl)
+void LLMediaCtrl::showNotification(LLNotificationPtr notify)
{
- bool check = ctrl->getValue().asBoolean();
- if (mCurNotification && mCurNotification->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN)
+ delete mWindowShade;
+
+ LLWindowShade::Params params;
+ params.name = "notification_shade";
+ params.rect = getLocalRect();
+ params.follows.flags = FOLLOWS_ALL;
+ params.notification = notify;
+ params.modal = true;
+ //HACK: don't hardcode this
+ if (notify->getIcon() == "Popup_Caution")
{
- // question was "show again" so invert value to get "ignore"
- check = !check;
+ params.bg_image.name = "Yellow_Gradient";
+ params.text_color = LLColor4::black;
}
- mCurNotification->setIgnored(check);
-}
-
-void LLMediaCtrl::onClickNotificationButton(const std::string& name)
-{
- if (!mCurNotification) return;
-
- LLSD response = mCurNotification->getResponseTemplate();
- response[name] = true;
-
- mCurNotification->respond(response);
-}
-
-void LLMediaCtrl::showNotification(LLNotificationPtr notify)
-{
- mCurNotification = notify;
-
- // add popup here
- LLSD payload = notify->getPayload();
-
- LLNotificationFormPtr formp = notify->getForm();
- LLLayoutPanel& panel = getChildRef<LLLayoutPanel>("notification_area");
- panel.setVisible(true);
- panel.getChild<LLUICtrl>("notification_icon")->setValue(notify->getIcon());
- panel.getChild<LLUICtrl>("notification_text")->setValue(notify->getMessage());
- panel.getChild<LLUICtrl>("notification_text")->setToolTip(notify->getMessage());
- LLNotificationForm::EIgnoreType ignore_type = formp->getIgnoreType();
- LLLayoutPanel& form_elements = panel.getChildRef<LLLayoutPanel>("form_elements");
- form_elements.deleteAllChildren();
-
- const S32 FORM_PADDING_HORIZONTAL = 10;
- const S32 FORM_PADDING_VERTICAL = 3;
- S32 cur_x = FORM_PADDING_HORIZONTAL;
-
- if (ignore_type != LLNotificationForm::IGNORE_NO)
+ else
+ //HACK: another one since XUI doesn't support what we need right now
+ if (notify->getName() == "AuthRequest")
{
- LLCheckBoxCtrl::Params checkbox_p;
- checkbox_p.name = "ignore_check";
- checkbox_p.rect = LLRect(cur_x, form_elements.getRect().getHeight() - FORM_PADDING_VERTICAL, cur_x, FORM_PADDING_VERTICAL);
- checkbox_p.label = formp->getIgnoreMessage();
- checkbox_p.label_text.text_color = LLColor4::black;
- checkbox_p.commit_callback.function = boost::bind(&LLMediaCtrl::onClickIgnore, this, _1);
- checkbox_p.initial_value = formp->getIgnored();
-
- LLCheckBoxCtrl* check = LLUICtrlFactory::create<LLCheckBoxCtrl>(checkbox_p);
- check->setRect(check->getBoundingRect());
- form_elements.addChild(check);
- cur_x = check->getRect().mRight + FORM_PADDING_HORIZONTAL;
+ params.bg_image.name = "Yellow_Gradient";
+ params.text_color = LLColor4::black;
+ params.can_close = false;
}
-
- for (S32 i = 0; i < formp->getNumElements(); i++)
+ else
{
- LLSD form_element = formp->getElement(i);
- if (form_element["type"].asString() == "button")
- {
- LLButton::Params button_p;
- button_p.name = form_element["name"];
- button_p.label = form_element["text"];
- button_p.rect = LLRect(cur_x, form_elements.getRect().getHeight() - FORM_PADDING_VERTICAL, cur_x, FORM_PADDING_VERTICAL);
- button_p.click_callback.function = boost::bind(&LLMediaCtrl::onClickNotificationButton, this, form_element["name"].asString());
- button_p.auto_resize = true;
-
- LLButton* button = LLUICtrlFactory::create<LLButton>(button_p);
- button->autoResize();
- form_elements.addChild(button);
-
- cur_x = button->getRect().mRight + FORM_PADDING_HORIZONTAL;
- }
+ //HACK: make this a property of the notification itself, "cancellable"
+ params.can_close = false;
+ params.text_color.control = "LabelTextColor";
}
+ mWindowShade = LLUICtrlFactory::create<LLWindowShade>(params);
- form_elements.reshape(cur_x, form_elements.getRect().getHeight());
-
- //LLWeb::loadURL(payload["url"], payload["target"]);
+ addChild(mWindowShade);
+ mWindowShade->show();
}
void LLMediaCtrl::hideNotification()
{
- LLLayoutPanel& panel = getChildRef<LLLayoutPanel>("notification_area");
- panel.setVisible(FALSE);
-
- mCurNotification.reset();
+ if (mWindowShade)
+ {
+ mWindowShade->hide();
+ }
}
diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h
index 96bb0c1df5..38a74f90d3 100644
--- a/indra/newview/llmediactrl.h
+++ b/indra/newview/llmediactrl.h
@@ -90,6 +90,7 @@ public:
virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask );
virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
+ virtual BOOL handleToolTip(S32 x, S32 y, MASK mask);
// navigation
void navigateTo( std::string url_in, std::string mime_type = "");
@@ -168,9 +169,6 @@ public:
private:
void onVisibilityChange ( const LLSD& new_visibility );
void onPopup(const LLSD& notification, const LLSD& response);
- void onCloseNotification();
- void onClickNotificationButton(const std::string& name);
- void onClickIgnore(LLUICtrl* ctrl);
const S32 mTextureDepthBytes;
LLUUID mMediaTextureID;
@@ -194,7 +192,8 @@ public:
S32 mTextureWidth;
S32 mTextureHeight;
bool mClearCache;
- boost::shared_ptr<class LLNotification> mCurNotification;
+ class LLWindowShade* mWindowShade;
+ bool mHoverTextChanged;
};
#endif // LL_LLMediaCtrl_H
diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp
index cebfac86e7..de5439e4e0 100644
--- a/indra/newview/llnearbychathandler.cpp
+++ b/indra/newview/llnearbychathandler.cpp
@@ -527,7 +527,8 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, const LLSD &args)
if( nearby_chat->getVisible()
|| ( chat_msg.mSourceType == CHAT_SOURCE_AGENT
- && gSavedSettings.getBOOL("UseChatBubbles") ) )
+ && gSavedSettings.getBOOL("UseChatBubbles") )
+ || !mChannel->getShowToasts() ) // to prevent toasts in Busy mode
return;//no need in toast if chat is visible or if bubble chat is enabled
// Handle irc styled messages for toast panel
diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp
index f084002385..1a8ec4991d 100644
--- a/indra/newview/llnetmap.cpp
+++ b/indra/newview/llnetmap.cpp
@@ -94,10 +94,12 @@ LLNetMap::LLNetMap (const Params & p)
mToolTipMsg()
{
mDotRadius = llmax(DOT_SCALE * mPixelsPerMeter, MIN_DOT_RADIUS);
+ setScale(gSavedSettings.getF32("MiniMapScale"));
}
LLNetMap::~LLNetMap()
{
+ gSavedSettings.setF32("MiniMapScale", mScale);
}
void LLNetMap::setScale( F32 scale )
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index 2e4be78be1..5f89097c17 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -73,7 +73,6 @@
#endif // LL_WINDOWS
#include "llsdserialize.h"
-#define USE_VIEWER_AUTH 0
const S32 BLACK_BORDER_HEIGHT = 160;
const S32 MAX_PASSWORD = 16;
@@ -190,10 +189,6 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
buildFromFile( "panel_login.xml");
-#if USE_VIEWER_AUTH
- //leave room for the login menu bar
- setRect(LLRect(0, rect.getHeight()-18, rect.getWidth(), 0));
-#endif
// Legacy login web page is hidden under the menu bar.
// Adjust reg-in-client web browser widget to not be hidden.
if (gSavedSettings.getBOOL("RegInClient"))
@@ -205,16 +200,12 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
reshape(rect.getWidth(), rect.getHeight());
}
-#if !USE_VIEWER_AUTH
getChild<LLLineEditor>("password_edit")->setKeystrokeCallback(onPassKey, this);
// change z sort of clickable text to be behind buttons
//sendChildToBack(getChildView("channel_text"));
sendChildToBack(getChildView("forgot_password_text"));
- LLLineEditor* edit = getChild<LLLineEditor>("password_edit");
- if (edit) edit->setDrawAsterixes(TRUE);
-
if(LLStartUp::getStartSLURL().getType() != LLSLURL::LOCATION)
{
LLSLURL slurl(gSavedSettings.getString("LoginLocation"));
@@ -248,7 +239,6 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
LLTextBox* need_help_text = getChild<LLTextBox>("login_help");
need_help_text->setClickedCallback(onClickHelp, NULL);
-#endif
// get the web browser control
LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html");
@@ -275,15 +265,9 @@ void LLPanelLogin::reshapeBrowser()
LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html");
LLRect rect = gViewerWindow->getWindowRectScaled();
LLRect html_rect;
-#if USE_VIEWER_AUTH
- html_rect.setCenterAndSize(
- rect.getCenterX() - 2, rect.getCenterY(),
- rect.getWidth() + 6, rect.getHeight());
-#else
html_rect.setCenterAndSize(
rect.getCenterX() - 2, rect.getCenterY() + 40,
rect.getWidth() + 6, rect.getHeight() - 78 );
-#endif
web_browser->setRect( html_rect );
web_browser->reshape( html_rect.getWidth(), html_rect.getHeight(), TRUE );
reshape( rect.getWidth(), rect.getHeight(), 1 );
@@ -306,7 +290,6 @@ void LLPanelLogin::setSiteIsAlive( bool alive )
else
// the site is not available (missing page, server down, other badness)
{
-#if !USE_VIEWER_AUTH
if ( web_browser )
{
// hide browser control (revealing default one)
@@ -315,16 +298,6 @@ void LLPanelLogin::setSiteIsAlive( bool alive )
// mark as unavailable
mHtmlAvailable = FALSE;
}
-#else
-
- if ( web_browser )
- {
- web_browser->navigateToLocalPage( "loading-error" , "index.html" );
-
- // mark as available
- mHtmlAvailable = TRUE;
- }
-#endif
}
}
@@ -364,7 +337,6 @@ void LLPanelLogin::draw()
if ( mHtmlAvailable )
{
-#if !USE_VIEWER_AUTH
if (getChild<LLView>("login_widgets")->getVisible())
{
// draw a background box in black
@@ -373,7 +345,6 @@ void LLPanelLogin::draw()
// just the blue background to the native client UI
mLogoImage->draw(0, -264, width + 8, mLogoImage->getHeight());
}
-#endif
}
else
{
@@ -419,12 +390,6 @@ void LLPanelLogin::setFocus(BOOL b)
// static
void LLPanelLogin::giveFocus()
{
-#if USE_VIEWER_AUTH
- if (sInstance)
- {
- sInstance->setFocus(TRUE);
- }
-#else
if( sInstance )
{
// Grab focus and move cursor to first blank input field
@@ -453,17 +418,18 @@ void LLPanelLogin::giveFocus()
edit->selectAll();
}
}
-#endif
}
// static
void LLPanelLogin::showLoginWidgets()
{
+ // *NOTE: Mani - This may or may not be obselete code.
+ // It seems to be part of the defunct? reg-in-client project.
sInstance->getChildView("login_widgets")->setVisible( true);
LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
sInstance->reshapeBrowser();
// *TODO: Append all the usual login parameters, like first_login=Y etc.
- std::string splash_screen_url = sInstance->getString("real_url");
+ std::string splash_screen_url = LLGridManager::getInstance()->getLoginPage();
web_browser->navigateTo( splash_screen_url, "text/html" );
LLUICtrl* username_edit = sInstance->getChild<LLUICtrl>("username_edit");
username_edit->setFocus(TRUE);
@@ -833,73 +799,6 @@ void LLPanelLogin::loadLoginPage()
curl_free(curl_grid);
gViewerWindow->setMenuBackgroundColor(false, !LLGridManager::getInstance()->isInProductionGrid());
gLoginMenuBarView->setBackgroundColor(gMenuBarView->getBackgroundColor());
-
-
-#if USE_VIEWER_AUTH
- LLURLSimString::sInstance.parse();
-
- std::string location;
- std::string region;
- std::string password;
-
- if (LLURLSimString::parse())
- {
- std::ostringstream oRegionStr;
- location = "specify";
- oRegionStr << LLURLSimString::sInstance.mSimName << "/" << LLURLSimString::sInstance.mX << "/"
- << LLURLSimString::sInstance.mY << "/"
- << LLURLSimString::sInstance.mZ;
- region = oRegionStr.str();
- }
- else
- {
- location = gSavedSettings.getString("LoginLocation");
- }
-
- std::string username;
-
- if(gSavedSettings.getLLSD("UserLoginInfo").size() == 3)
- {
- LLSD cmd_line_login = gSavedSettings.getLLSD("UserLoginInfo");
- username = cmd_line_login[0].asString() + " " + cmd_line_login[1];
- password = cmd_line_login[2].asString();
- }
-
-
- char* curl_region = curl_escape(region.c_str(), 0);
-
- oStr <<"username=" << username <<
- "&location=" << location << "&region=" << curl_region;
-
- curl_free(curl_region);
-
- if (!password.empty())
- {
- oStr << "&password=" << password;
- }
- else if (!(password = load_password_from_disk()).empty())
- {
- oStr << "&password=$1$" << password;
- }
- if (gAutoLogin)
- {
- oStr << "&auto_login=TRUE";
- }
- if (gSavedSettings.getBOOL("ShowStartLocation"))
- {
- oStr << "&show_start_location=TRUE";
- }
- if (gSavedSettings.getBOOL("RememberPassword"))
- {
- oStr << "&remember_password=TRUE";
- }
-#ifndef LL_RELEASE_FOR_DOWNLOAD
- oStr << "&show_grid=TRUE";
-#else
- if (gSavedSettings.getBOOL("ForceShowGrid"))
- oStr << "&show_grid=TRUE";
-#endif
-#endif
LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 17433a557b..c83176d980 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -506,9 +506,6 @@ void LLPanelMainInventory::onFilterSelected()
return;
}
- BOOL recent_active = ("Recent Items" == mActivePanel->getName());
- getChildView("add_btn_panel")->setVisible( !recent_active);
-
setFilterSubString(mFilterSubString);
LLInventoryFilter* filter = mActivePanel->getFilter();
LLFloaterInventoryFinder *finder = getFinder();
@@ -944,6 +941,11 @@ void LLPanelMainInventory::updateListCommands()
void LLPanelMainInventory::onAddButtonClick()
{
+// Gray out the "New Folder" option when the Recent tab is active as new folders will not be displayed
+// unless "Always show folders" is checked in the filter options.
+ bool recent_active = ("Recent Items" == mActivePanel->getName());
+ mMenuAdd->getChild<LLMenuItemGL>("New Folder")->setEnabled(!recent_active);
+
setUploadCostIfNeeded();
showActionMenu(mMenuAdd,"add_btn");
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 1869e92c8c..00ac34efa5 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -753,6 +753,11 @@ void LLPanelPlaces::onOverflowButtonClicked()
// there is no landmark already pointing to that parcel in agent's inventory.
menu->getChild<LLMenuItemCallGL>("landmark")->setEnabled(is_agent_place_info_visible &&
!LLLandmarkActions::landmarkAlreadyExists());
+ // STORM-411
+ // Creating landmarks for remote locations is impossible.
+ // So hide menu item "Make a Landmark" in "Teleport History Profile" panel.
+ menu->setItemVisible("landmark", mPlaceInfoType != TELEPORT_HISTORY_INFO_TYPE);
+ menu->arrangeAndClear();
}
else if (mPlaceInfoType == LANDMARK_INFO_TYPE && mLandmarkMenu != NULL)
{
diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp
index 614700fb0a..8ae3553857 100644
--- a/indra/newview/llpanelprimmediacontrols.cpp
+++ b/indra/newview/llpanelprimmediacontrols.cpp
@@ -59,6 +59,7 @@
#include "llvovolume.h"
#include "llweb.h"
#include "llwindow.h"
+#include "llwindowshade.h"
#include "llfloatertools.h" // to enable hide if build tools are up
// Functions pulled from pipeline.cpp
@@ -90,7 +91,8 @@ LLPanelPrimMediaControls::LLPanelPrimMediaControls() :
mTargetObjectNormal(LLVector3::zero),
mZoomObjectID(LLUUID::null),
mZoomObjectFace(0),
- mVolumeSliderVisible(0)
+ mVolumeSliderVisible(0),
+ mWindowShade(NULL)
{
mCommitCallbackRegistrar.add("MediaCtrl.Close", boost::bind(&LLPanelPrimMediaControls::onClickClose, this));
mCommitCallbackRegistrar.add("MediaCtrl.Back", boost::bind(&LLPanelPrimMediaControls::onClickBack, this));
@@ -205,6 +207,9 @@ BOOL LLPanelPrimMediaControls::postBuild()
mMediaAddress->setFocusReceivedCallback(boost::bind(&LLPanelPrimMediaControls::onInputURL, _1, this ));
+ LLWindowShade::Params window_shade_params;
+ window_shade_params.name = "window_shade";
+
mCurrentZoom = ZOOM_NONE;
// clicks on buttons do not remove keyboard focus from media
setIsChrome(TRUE);
@@ -698,6 +703,24 @@ void LLPanelPrimMediaControls::updateShape()
/*virtual*/
void LLPanelPrimMediaControls::draw()
{
+ LLViewerMediaImpl* impl = getTargetMediaImpl();
+ if (impl)
+ {
+ LLNotificationPtr notification = impl->getCurrentNotification();
+ if (notification != mActiveNotification)
+ {
+ mActiveNotification = notification;
+ if (notification)
+ {
+ showNotification(notification);
+ }
+ else
+ {
+ hideNotification();
+ }
+ }
+ }
+
F32 alpha = getDrawContext().mAlpha;
if(mFadeTimer.getStarted())
{
@@ -1295,3 +1318,38 @@ bool LLPanelPrimMediaControls::shouldVolumeSliderBeVisible()
{
return mVolumeSliderVisible > 0;
}
+
+void LLPanelPrimMediaControls::showNotification(LLNotificationPtr notify)
+{
+ delete mWindowShade;
+ LLWindowShade::Params params;
+ params.rect = mMediaRegion->getLocalRect();
+ params.follows.flags = FOLLOWS_ALL;
+ params.notification = notify;
+
+ //HACK: don't hardcode this
+ if (notify->getIcon() == "Popup_Caution")
+ {
+ params.bg_image.name = "Yellow_Gradient";
+ params.text_color = LLColor4::black;
+ }
+ else
+ {
+ //HACK: make this a property of the notification itself, "cancellable"
+ params.can_close = false;
+ params.text_color.control = "LabelTextColor";
+ }
+
+ mWindowShade = LLUICtrlFactory::create<LLWindowShade>(params);
+
+ mMediaRegion->addChild(mWindowShade);
+ mWindowShade->show();
+}
+
+void LLPanelPrimMediaControls::hideNotification()
+{
+ if (mWindowShade)
+ {
+ mWindowShade->hide();
+ }
+}
diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h
index 3ec24f0e24..0b9664359c 100644
--- a/indra/newview/llpanelprimmediacontrols.h
+++ b/indra/newview/llpanelprimmediacontrols.h
@@ -29,6 +29,7 @@
#include "llpanel.h"
#include "llviewermedia.h"
+#include "llnotificationptr.h"
class LLButton;
class LLCoordWindow;
@@ -37,6 +38,7 @@ class LLLayoutStack;
class LLProgressBar;
class LLSliderCtrl;
class LLViewerMediaImpl;
+class LLWindowShade;
class LLPanelPrimMediaControls : public LLPanel
{
@@ -54,6 +56,9 @@ public:
void updateShape();
bool isMouseOver();
+ void showNotification(LLNotificationPtr notify);
+ void hideNotification();
+
enum EZoomLevel
{
ZOOM_NONE = 0,
@@ -162,6 +167,7 @@ private:
LLUICtrl *mRightBookend;
LLUIImage* mBackgroundImage;
LLUIImage* mVolumeSliderBackgroundImage;
+ LLWindowShade* mWindowShade;
F32 mSkipStep;
S32 mMinWidth;
S32 mMinHeight;
@@ -204,6 +210,8 @@ private:
S32 mZoomObjectFace;
S32 mVolumeSliderVisible;
+
+ LLNotificationPtr mActiveNotification;
};
#endif // LL_PANELPRIMMEDIACONTROLS_H
diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp
index db02d76139..31fde5d58a 100644
--- a/indra/newview/llprogressview.cpp
+++ b/indra/newview/llprogressview.cpp
@@ -133,13 +133,13 @@ void LLProgressView::setVisible(BOOL visible)
mFadeTimer.start();
}
// showing progress view
- else if (!getVisible() && visible)
+ else if (visible && (!getVisible() || mFadeTimer.getStarted()))
{
setFocus(TRUE);
mFadeTimer.stop();
mProgressTimer.start();
LLPanel::setVisible(TRUE);
- }
+ }
}
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index 0eeb89792b..e3bc67a414 100644
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -83,11 +83,10 @@ bool LLScreenChannelBase::isHovering()
return mHoveredToast->isHovered();
}
-bool LLScreenChannelBase::resetPositionAndSize(const LLSD& newvalue)
+void LLScreenChannelBase::resetPositionAndSize()
{
LLRect rc = gViewerWindow->getWorldViewRectScaled();
updatePositionAndSize(rc, rc);
- return true;
}
void LLScreenChannelBase::updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect)
@@ -99,10 +98,7 @@ void LLScreenChannelBase::updatePositionAndSize(LLRect old_world_rect, LLRect ne
if (gSavedSettings.getBOOL("SidebarCameraMovement") == FALSE
&& LLSideTray::instanceCreated ())
{
- LLSideTray* side_bar = LLSideTray::getInstance();
-
- if (side_bar->getVisible() && !side_bar->getCollapsed())
- world_rect_padding += side_bar->getRect().getWidth();
+ world_rect_padding += LLSideTray::getInstance()->getVisibleWidth();
}
@@ -133,7 +129,7 @@ void LLScreenChannelBase::init(S32 channel_left, S32 channel_right)
if(LLSideTray::instanceCreated())
{
LLSideTray* side_bar = LLSideTray::getInstance();
- side_bar->getCollapseSignal().connect(boost::bind(&LLScreenChannelBase::resetPositionAndSize, this, _2));
+ side_bar->setVisibleWidthChangeCallback(boost::bind(&LLScreenChannelBase::resetPositionAndSize, this));
}
// top and bottom set by updateBottom()
@@ -214,10 +210,7 @@ void LLScreenChannel::updatePositionAndSize(LLRect old_world_rect, LLRect new_wo
if (gSavedSettings.getBOOL("SidebarCameraMovement") == FALSE
&& LLSideTray::instanceCreated ())
{
- LLSideTray* side_bar = LLSideTray::getInstance();
-
- if (side_bar->getVisible() && !side_bar->getCollapsed())
- world_rect_padding += side_bar->getRect().getWidth();
+ world_rect_padding += LLSideTray::getInstance()->getVisibleWidth();
}
@@ -495,7 +488,7 @@ void LLScreenChannel::modifyToastByNotificationID(LLUUID id, LLPanel* panel)
//--------------------------------------------------------------------------
void LLScreenChannel::redrawToasts()
{
- if(mToastList.size() == 0 || isHovering())
+ if(mToastList.size() == 0)
return;
switch(mToastAlignment)
@@ -841,8 +834,7 @@ void LLScreenChannel::onToastHover(LLToast* toast, bool mouse_enter)
}
}
- if(!isHovering())
- redrawToasts();
+ redrawToasts();
}
//--------------------------------------------------------------------------
diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h
index c536a21779..d207d13981 100644
--- a/indra/newview/llscreenchannel.h
+++ b/indra/newview/llscreenchannel.h
@@ -59,8 +59,8 @@ public:
// Channel's outfit-functions
// update channel's size and position in the World View
virtual void updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect);
+ void resetPositionAndSize();
- bool resetPositionAndSize(const LLSD& newvalue);
// initialization of channel's shape and position
virtual void init(S32 channel_left, S32 channel_right);
diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp
index 3bc3959e0b..aef665a35c 100644
--- a/indra/newview/llsidetray.cpp
+++ b/indra/newview/llsidetray.cpp
@@ -561,7 +561,7 @@ BOOL LLSideTray::postBuild()
{
if ((*it).channel)
{
- getCollapseSignal().connect(boost::bind(&LLScreenChannelBase::resetPositionAndSize, (*it).channel, _2));
+ setVisibleWidthChangeCallback(boost::bind(&LLScreenChannelBase::resetPositionAndSize, (*it).channel));
}
}
@@ -980,9 +980,6 @@ void LLSideTray::reflectCollapseChange()
}
gFloaterView->refresh();
-
- LLSD new_value = mCollapsed;
- mCollapseSignal(this,new_value);
}
void LLSideTray::arrange()
@@ -1262,9 +1259,29 @@ bool LLSideTray::isPanelActive(const std::string& panel_name)
void LLSideTray::updateSidetrayVisibility()
{
// set visibility of parent container based on collapsed state
- if (getParent())
+ LLView* parent = getParent();
+ if (parent)
{
- getParent()->setVisible(!mCollapsed && !gAgentCamera.cameraMouselook());
+ bool old_visibility = parent->getVisible();
+ bool new_visibility = !mCollapsed && !gAgentCamera.cameraMouselook();
+
+ if (old_visibility != new_visibility)
+ {
+ parent->setVisible(new_visibility);
+
+ // Signal change of visible width.
+ llinfos << "Visible: " << new_visibility << llendl;
+ mVisibleWidthChangeSignal(this, new_visibility);
+ }
}
}
+S32 LLSideTray::getVisibleWidth()
+{
+ return (isInVisibleChain() && !mCollapsed) ? getRect().getWidth() : 0;
+}
+
+void LLSideTray::setVisibleWidthChangeCallback(const commit_signal_t::slot_type& cb)
+{
+ mVisibleWidthChangeSignal.connect(cb);
+}
diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h
index 3c572dde95..184d78845f 100644
--- a/indra/newview/llsidetray.h
+++ b/indra/newview/llsidetray.h
@@ -165,9 +165,18 @@ public:
void reshape (S32 width, S32 height, BOOL called_from_parent = TRUE);
- void updateSidetrayVisibility();
+ /**
+ * @return side tray width if it's visible and expanded, 0 otherwise.
+ *
+ * Not that width of the tab buttons is not included.
+ *
+ * @see setVisibleWidthChangeCallback()
+ */
+ S32 getVisibleWidth();
+
+ void setVisibleWidthChangeCallback(const commit_signal_t::slot_type& cb);
- commit_signal_t& getCollapseSignal() { return mCollapseSignal; }
+ void updateSidetrayVisibility();
void handleLoginComplete();
@@ -216,7 +225,7 @@ private:
tab_order_vector_t mOriginalTabOrder;
LLSideTrayTab* mActiveTab;
- commit_signal_t mCollapseSignal;
+ commit_signal_t mVisibleWidthChangeSignal;
LLButton* mCollapseButton;
bool mCollapsed;
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index d945af0776..611f9de2e6 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -3095,7 +3095,16 @@ bool process_login_success_response()
std::string map_server_url = response["map-server-url"];
if(!map_server_url.empty())
{
- gSavedSettings.setString("MapServerURL", map_server_url);
+ // We got an answer from the grid -> use that for map for the current session
+ gSavedSettings.setString("CurrentMapServerURL", map_server_url);
+ LL_INFOS("LLStartup") << "map-server-url : we got an answer from the grid : " << map_server_url << LL_ENDL;
+ }
+ else
+ {
+ // No answer from the grid -> use the default setting for current session
+ map_server_url = gSavedSettings.getString("MapServerURL");
+ gSavedSettings.setString("CurrentMapServerURL", map_server_url);
+ LL_INFOS("LLStartup") << "map-server-url : no map-server-url answer, we use the default setting for the map : " << map_server_url << LL_ENDL;
}
// Default male and female avatars allowing the user to choose their avatar on first login.
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index 622d09c600..8c5a52c187 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -504,9 +504,10 @@ bool toggle_show_object_render_cost(const LLSD& newvalue)
void toggle_updater_service_active(LLControlVariable* control, const LLSD& new_value)
{
- if(new_value.asBoolean())
+ if(new_value.asInteger())
{
- LLUpdaterService().startChecking();
+ LLUpdaterService update_service;
+ if(!update_service.isChecking()) update_service.startChecking();
}
else
{
@@ -661,7 +662,7 @@ void settings_setup_listeners()
gSavedSettings.getControl("ShowNavbarFavoritesPanel")->getSignal()->connect(boost::bind(&toggle_show_favorites_panel, _2));
gSavedSettings.getControl("ShowMiniLocationPanel")->getSignal()->connect(boost::bind(&toggle_show_mini_location_panel, _2));
gSavedSettings.getControl("ShowObjectRenderingCost")->getSignal()->connect(boost::bind(&toggle_show_object_render_cost, _2));
- gSavedSettings.getControl("UpdaterServiceActive")->getSignal()->connect(&toggle_updater_service_active);
+ gSavedSettings.getControl("UpdaterServiceSetting")->getSignal()->connect(&toggle_updater_service_active);
gSavedSettings.getControl("ForceShowGrid")->getSignal()->connect(boost::bind(&handleForceShowGrid, _2));
gSavedSettings.getControl("RenderTransparentWater")->getSignal()->connect(boost::bind(&handleRenderTransparentWaterChanged, _2));
}
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index f573f25efe..dca1e33e60 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -60,6 +60,7 @@
#include "llfloaterhardwaresettings.h"
#include "llfloaterhelpbrowser.h"
#include "llfloatermediabrowser.h"
+#include "llfloaterwebcontent.h"
#include "llfloatermediasettings.h"
#include "llfloaterhud.h"
#include "llfloaterimagepreview.h"
@@ -252,6 +253,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("voice_controls", "floater_voice_controls.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLCallFloater>);
LLFloaterReg::add("voice_effect", "floater_voice_effect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterVoiceEffect>);
+ LLFloaterReg::add("web_content", "floater_web_content.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWebContent>);
LLFloaterReg::add("whitelist_entry", "floater_whitelist_entry.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWhiteListEntry>);
LLFloaterWindowSizeUtil::registerFloater();
LLFloaterReg::add("world_map", "floater_world_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWorldMap>);
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index fae4eb3c05..d3b6dcd86f 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -52,6 +52,7 @@
#include "llviewerregion.h"
#include "llwebsharing.h" // For LLWebSharing::setOpenIDCookie(), *TODO: find a better way to do this!
#include "llfilepicker.h"
+#include "llnotifications.h"
#include "llevent.h" // LLSimpleListener
#include "llnotificationsutil.h"
@@ -62,6 +63,7 @@
#include "llwindow.h"
#include "llfloatermediabrowser.h" // for handling window close requests and geometry change requests in media browser windows.
+#include "llfloaterwebcontent.h" // for handling window close requests and geometry change requests in media browser windows.
#include <boost/bind.hpp> // for SkinFolder listener
#include <boost/signals2.hpp>
@@ -293,6 +295,7 @@ public:
LLPluginCookieStore *LLViewerMedia::sCookieStore = NULL;
LLURL LLViewerMedia::sOpenIDURL;
std::string LLViewerMedia::sOpenIDCookie;
+LLPluginClassMedia* LLViewerMedia::sSpareBrowserMediaSource = NULL;
static LLViewerMedia::impl_list sViewerMediaImplList;
static LLViewerMedia::impl_id_map sViewerMediaTextureIDMap;
static LLTimer sMediaCreateTimer;
@@ -742,6 +745,9 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
// Enable/disable the plugin read thread
LLPluginProcessParent::setUseReadThread(gSavedSettings.getBOOL("PluginUseReadThread"));
+ // HACK: we always try to keep a spare running webkit plugin around to improve launch times.
+ createSpareBrowserMediaSource();
+
sAnyMediaShowing = false;
sUpdatedCookies = getCookieStore()->getChangedCookies();
if(!sUpdatedCookies.empty())
@@ -759,6 +765,12 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
pimpl->update();
pimpl->calculateInterest();
}
+
+ // Let the spare media source actually launch
+ if(sSpareBrowserMediaSource)
+ {
+ sSpareBrowserMediaSource->idle();
+ }
// Sort the static instance list using our interest criteria
sViewerMediaImplList.sort(priorityComparitor);
@@ -1034,6 +1046,26 @@ bool LLViewerMedia::isParcelAudioPlaying()
return (LLViewerMedia::hasParcelAudio() && gAudiop && LLAudioEngine::AUDIO_PLAYING == gAudiop->isInternetStreamPlaying());
}
+void LLViewerMedia::onAuthSubmit(const LLSD& notification, const LLSD& response)
+{
+ LLViewerMediaImpl *impl = LLViewerMedia::getMediaImplFromTextureID(notification["payload"]["media_id"]);
+ if(impl)
+ {
+ LLPluginClassMedia* media = impl->getMediaPlugin();
+ if(media)
+ {
+ if (response["ok"])
+ {
+ media->sendAuthResponse(true, response["username"], response["password"]);
+ }
+ else
+ {
+ media->sendAuthResponse(false, "", "");
+ }
+ }
+ }
+}
+
/////////////////////////////////////////////////////////////////////////////////////////
// static
void LLViewerMedia::clearAllCookies()
@@ -1400,6 +1432,29 @@ void LLViewerMedia::proxyWindowClosed(const std::string &uuid)
}
}
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::createSpareBrowserMediaSource()
+{
+ if(!sSpareBrowserMediaSource)
+ {
+ // If we don't have a spare browser media source, create one.
+ // The null owner will keep the browser plugin from fully initializing
+ // (specifically, it keeps LLPluginClassMedia from negotiating a size change,
+ // which keeps MediaPluginWebkit::initBrowserWindow from doing anything until we have some necessary data, like the background color)
+ sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType("text/html", NULL, 0, 0);
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+LLPluginClassMedia* LLViewerMedia::getSpareBrowserMediaSource()
+{
+ LLPluginClassMedia* result = sSpareBrowserMediaSource;
+ sSpareBrowserMediaSource = NULL;
+ return result;
+};
+
bool LLViewerMedia::hasInWorldMedia()
{
if (sInWorldMediaDisabled) return false;
@@ -1636,6 +1691,21 @@ void LLViewerMediaImpl::setMediaType(const std::string& media_type)
LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target)
{
std::string plugin_basename = LLMIMETypes::implType(media_type);
+ LLPluginClassMedia* media_source = NULL;
+
+ // HACK: we always try to keep a spare running webkit plugin around to improve launch times.
+ if(plugin_basename == "media_plugin_webkit")
+ {
+ media_source = LLViewerMedia::getSpareBrowserMediaSource();
+ if(media_source)
+ {
+ media_source->setOwner(owner);
+ media_source->setTarget(target);
+ media_source->setSize(default_width, default_height);
+
+ return media_source;
+ }
+ }
if(plugin_basename.empty())
{
@@ -1673,7 +1743,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
}
else
{
- LLPluginClassMedia* media_source = new LLPluginClassMedia(owner);
+ media_source = new LLPluginClassMedia(owner);
media_source->setSize(default_width, default_height);
media_source->setUserDataPath(user_data_path);
media_source->setLanguageCode(LLUI::getLanguage());
@@ -1753,6 +1823,22 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
media_source->focus(mHasFocus);
media_source->setBackgroundColor(mBackgroundColor);
+ if(gSavedSettings.getBOOL("BrowserIgnoreSSLCertErrors"))
+ {
+ media_source->ignore_ssl_cert_errors(true);
+ }
+
+ // start by assuming the default CA file will be used
+ std::string ca_path = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "lindenlab.pem" );
+
+ // default turned off so pick up the user specified path
+ if( ! gSavedSettings.getBOOL("BrowserUseDefaultCAFile"))
+ {
+ ca_path = gSavedSettings.getString("BrowserCAFilePath");
+ }
+ // set the path to the CA.pem file
+ media_source->addCertificateFilePath( ca_path );
+
media_source->proxy_setup(gSavedSettings.getBOOL("BrowserProxyEnabled"), gSavedSettings.getString("BrowserProxyAddress"), gSavedSettings.getS32("BrowserProxyPort"));
if(mClearCache)
@@ -1849,6 +1935,18 @@ void LLViewerMediaImpl::setSize(int width, int height)
}
//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::showNotification(LLNotificationPtr notify)
+{
+ mNotification = notify;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::hideNotification()
+{
+ mNotification.reset();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::play()
{
// If the media source isn't there, try to initialize it and load an URL.
@@ -2850,7 +2948,6 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
LL_DEBUGS("Media") << "MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is: " << plugin->getClickURL() << LL_ENDL;
std::string url = plugin->getClickURL();
LLURLDispatcher::dispatch(url, NULL, mTrustedBrowser);
-
}
break;
case MEDIA_EVENT_CLICK_LINK_HREF:
@@ -2913,6 +3010,7 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_BEGIN:
{
LL_DEBUGS("Media") << "MEDIA_EVENT_NAVIGATE_BEGIN, uri is: " << plugin->getNavigateURI() << LL_ENDL;
+ hideNotification();
if(getNavState() == MEDIANAVSTATE_SERVER_SENT)
{
@@ -3003,7 +3101,26 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
plugin->sendPickFileResponse(response);
}
break;
-
+
+
+ case LLViewerMediaObserver::MEDIA_EVENT_AUTH_REQUEST:
+ {
+ LLNotification::Params auth_request_params;
+ auth_request_params.name = "AuthRequest";
+
+ // pass in host name and realm for site (may be zero length but will always exist)
+ LLSD args;
+ LLURL raw_url( plugin->getAuthURL().c_str() );
+ args["HOST_NAME"] = raw_url.getAuthority();
+ args["REALM"] = plugin->getAuthRealm();
+ auth_request_params.substitutions = args;
+
+ auth_request_params.payload = LLSD().with("media_id", mTextureId);
+ auth_request_params.functor.function = boost::bind(&LLViewerMedia::onAuthSubmit, _1, _2);
+ LLNotifications::instance().add(auth_request_params);
+ };
+ break;
+
case LLViewerMediaObserver::MEDIA_EVENT_CLOSE_REQUEST:
{
std::string uuid = plugin->getClickUUID();
@@ -3019,6 +3136,7 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
// This close request is directed at another instance
pass_through = false;
LLFloaterMediaBrowser::closeRequest(uuid);
+ LLFloaterWebContent::closeRequest(uuid);
}
}
break;
@@ -3038,6 +3156,7 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
// This request is directed at another instance
pass_through = false;
LLFloaterMediaBrowser::geometryChanged(uuid, plugin->getGeometryX(), plugin->getGeometryY(), plugin->getGeometryWidth(), plugin->getGeometryHeight());
+ LLFloaterWebContent::geometryChanged(uuid, plugin->getGeometryX(), plugin->getGeometryY(), plugin->getGeometryWidth(), plugin->getGeometryHeight());
}
}
break;
@@ -3521,6 +3640,11 @@ bool LLViewerMediaImpl::isInAgentParcel() const
return result;
}
+LLNotificationPtr LLViewerMediaImpl::getCurrentNotification() const
+{
+ return mNotification;
+}
+
//////////////////////////////////////////////////////////////////////////////////////////
//
// static
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index 4025a4484f..e2e342cc45 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -37,6 +37,7 @@
#include "llpluginclassmedia.h"
#include "v4color.h"
+#include "llnotificationptr.h"
#include "llurl.h"
@@ -130,6 +131,8 @@ public:
static bool isParcelMediaPlaying();
static bool isParcelAudioPlaying();
+ static void onAuthSubmit(const LLSD& notification, const LLSD& response);
+
// Clear all cookies for all plugins
static void clearAllCookies();
@@ -155,6 +158,9 @@ public:
static void proxyWindowOpened(const std::string &target, const std::string &uuid);
static void proxyWindowClosed(const std::string &uuid);
+ static void createSpareBrowserMediaSource();
+ static LLPluginClassMedia* getSpareBrowserMediaSource();
+
private:
static void setOpenIDCookie();
static void onTeleportFinished();
@@ -162,6 +168,7 @@ private:
static LLPluginCookieStore *sCookieStore;
static LLURL sOpenIDURL;
static std::string sOpenIDCookie;
+ static LLPluginClassMedia* sSpareBrowserMediaSource;
};
// Implementation functions not exported into header file
@@ -195,6 +202,9 @@ public:
LLPluginClassMedia* getMediaPlugin() { return mMediaSource; }
void setSize(int width, int height);
+ void showNotification(LLNotificationPtr notify);
+ void hideNotification();
+
void play();
void stop();
void pause();
@@ -387,6 +397,9 @@ public:
// Is this media in the agent's parcel?
bool isInAgentParcel() const;
+ // get currently active notification associated with this media instance
+ LLNotificationPtr getCurrentNotification() const;
+
private:
bool isAutoPlayable() const;
bool shouldShowBasedOnClass() const;
@@ -444,7 +457,8 @@ private:
bool mNavigateSuspendedDeferred;
bool mTrustedBrowser;
std::string mTarget;
-
+ LLNotificationPtr mNotification;
+
private:
BOOL mIsUpdated ;
std::list< LLVOVolume* > mObjectList ;
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index e18b4ec414..9e16bf2fbb 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -7223,6 +7223,12 @@ void handle_web_browser_test(const LLSD& param)
LLWeb::loadURLInternal(url);
}
+void handle_web_content_test(const LLSD& param)
+{
+ std::string url = param.asString();
+ LLWeb::loadWebURLInternal(url);
+}
+
void handle_buy_currency_test(void*)
{
std::string url =
@@ -7973,7 +7979,8 @@ void initialize_menus()
view_listener_t::addMenu(new LLAdvancedDumpRegionObjectCache(), "Advanced.DumpRegionObjectCache");
// Advanced > UI
- commit.add("Advanced.WebBrowserTest", boost::bind(&handle_web_browser_test, _2));
+ commit.add("Advanced.WebBrowserTest", boost::bind(&handle_web_browser_test, _2)); // sigh! this one opens the MEDIA browser
+ commit.add("Advanced.WebContentTest", boost::bind(&handle_web_content_test, _2)); // this one opens the Web Content floater
view_listener_t::addMenu(new LLAdvancedBuyCurrencyTest(), "Advanced.BuyCurrencyTest");
view_listener_t::addMenu(new LLAdvancedDumpSelectMgr(), "Advanced.DumpSelectMgr");
view_listener_t::addMenu(new LLAdvancedDumpInventory(), "Advanced.DumpInventory");
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 7313463f1b..7dc5d96689 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -171,6 +171,31 @@ const BOOL SCRIPT_QUESTION_IS_CAUTION[SCRIPT_PERMISSION_EOF] =
FALSE // ControlYourCamera
};
+// Extract channel and version from a string like "SL Web Viewer Beta 10.11.29.215604".
+// (channel: "SL Web Viewer Beta", version: "10.11.29.215604")
+static bool parse_version_info(const std::string& version_info, std::string& channel, std::string& ver)
+{
+ size_t last_space = version_info.rfind(" ");
+ channel = version_info;
+
+ if (last_space != std::string::npos)
+ {
+ try
+ {
+ ver = version_info.substr(last_space + 1);
+ channel.replace(last_space, ver.length() + 1, ""); // strip version
+ }
+ catch (std::out_of_range)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
bool friendship_offer_callback(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
@@ -3825,28 +3850,22 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**)
if (!gLastVersionChannel.empty())
{
- // work out the URL for this server's Release Notes
- std::string url ="http://wiki.secondlife.com/wiki/Release_Notes/";
- std::string server_version = version_channel;
- std::vector<std::string> s_vect;
- boost::algorithm::split(s_vect, server_version, isspace);
- for(U32 i = 0; i < s_vect.size(); i++)
+ std::string url = regionp->getCapability("ServerReleaseNotes");
+ if (url.empty())
{
- if (i != (s_vect.size() - 1))
- {
- if(i != (s_vect.size() - 2))
- {
- url += s_vect[i] + "_";
- }
- else
- {
- url += s_vect[i] + "/";
- }
- }
- else
+ // The capability hasn't arrived yet or is not supported,
+ // fall back to parsing server version channel.
+ std::string channel, ver;
+ if (!parse_version_info(version_channel, channel, ver))
{
- url += s_vect[i].substr(0,4);
+ llwarns << "Failed to parse server version channel (" << version_channel << ")" << llendl;
}
+
+ url = gSavedSettings.getString("ReleaseNotesURL");
+ LLSD args;
+ args["CHANNEL"] = LLWeb::escapeURL(channel);
+ args["VERSION"] = LLWeb::escapeURL(ver);
+ LLStringUtil::format(url, args);
}
LLSD args;
diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp
index 99e869dafc..40f0b43313 100644
--- a/indra/newview/llviewerparcelmedia.cpp
+++ b/indra/newview/llviewerparcelmedia.cpp
@@ -586,6 +586,18 @@ void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_GEOMETRY_CHANGE, uuid is " << self->getClickUUID() << LL_ENDL;
}
break;
+
+ case MEDIA_EVENT_AUTH_REQUEST:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_AUTH_REQUEST, url " << self->getAuthURL() << ", realm " << self->getAuthRealm() << LL_ENDL;
+ }
+ break;
+
+ case MEDIA_EVENT_LINK_HOVERED:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_LINK_HOVERED, hover text is: " << self->getHoverText() << LL_ENDL;
+ };
+ break;
};
}
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index b8fd944321..5eeb02b080 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -186,11 +186,6 @@ public:
/*virtual*/ std::string translateString(const char* tag,
const std::map<std::string, std::string>& args);
- // signal on bottom tray width changed
- typedef boost::function<void (void)> bottom_tray_callback_t;
- typedef boost::signals2::signal<void (void)> bottom_tray_signal_t;
- bottom_tray_signal_t mOnBottomTrayWidthChanged;
- boost::signals2::connection setOnBottomTrayWidthChanged(bottom_tray_callback_t cb) { return mOnBottomTrayWidthChanged.connect(cb); }
// signal on update of WorldView rect
typedef boost::function<void (LLRect old_world_rect, LLRect new_world_rect)> world_rect_callback_t;
typedef boost::signals2::signal<void (LLRect old_world_rect, LLRect new_world_rect)> world_rect_signal_t;
diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp
index 6028a8fbea..b73017a51a 100644
--- a/indra/newview/llweb.cpp
+++ b/indra/newview/llweb.cpp
@@ -35,6 +35,7 @@
#include "llagent.h"
#include "llappviewer.h"
#include "llfloatermediabrowser.h"
+#include "llfloaterwebcontent.h"
#include "llfloaterreg.h"
#include "lllogininstance.h"
#include "llparcel.h"
@@ -95,6 +96,23 @@ void LLWeb::loadURL(const std::string& url, const std::string& target, const std
}
}
+// static
+void LLWeb::loadWebURL(const std::string& url, const std::string& target, const std::string& uuid)
+{
+ if(target == "_internal")
+ {
+ // Force load in the internal browser, as if with a blank target.
+ loadWebURLInternal(url, "", uuid);
+ }
+ else if (gSavedSettings.getBOOL("UseExternalBrowser") || (target == "_external"))
+ {
+ loadURLExternal(url);
+ }
+ else
+ {
+ loadWebURLInternal(url, target, uuid);
+ }
+}
// static
void LLWeb::loadURLInternal(const std::string &url, const std::string& target, const std::string& uuid)
@@ -102,6 +120,13 @@ void LLWeb::loadURLInternal(const std::string &url, const std::string& target, c
LLFloaterMediaBrowser::create(url, target, uuid);
}
+// static
+// Explicitly open a Web URL using the Web content floater
+void LLWeb::loadWebURLInternal(const std::string &url, const std::string& target, const std::string& uuid)
+{
+ LLFloaterWebContent::create(url, target, uuid);
+}
+
// static
void LLWeb::loadURLExternal(const std::string& url, const std::string& uuid)
diff --git a/indra/newview/llweb.h b/indra/newview/llweb.h
index 2915376583..dc5958e57f 100644
--- a/indra/newview/llweb.h
+++ b/indra/newview/llweb.h
@@ -57,6 +57,11 @@ public:
static void loadURLExternal(const std::string& url, const std::string& uuid);
static void loadURLExternal(const std::string& url, bool async, const std::string& uuid = LLStringUtil::null);
+ // Explicitly open a Web URL using the Web content floater vs. the more general media browser
+ static void loadWebURL(const std::string& url, const std::string& target, const std::string& uuid);
+ static void loadWebURLInternal(const std::string &url, const std::string& target, const std::string& uuid);
+ static void loadWebURLInternal(const std::string &url) { loadWebURLInternal(url, LLStringUtil::null, LLStringUtil::null); }
+
/// Returns escaped url (eg, " " to "%20") - used by all loadURL methods
static std::string escapeURL(const std::string& url);
/// Expands various strings like [LANG], [VERSION], etc. in a URL
diff --git a/indra/newview/llworldmipmap.cpp b/indra/newview/llworldmipmap.cpp
index be8298daab..74ed844376 100644
--- a/indra/newview/llworldmipmap.cpp
+++ b/indra/newview/llworldmipmap.cpp
@@ -181,8 +181,7 @@ LLPointer<LLViewerFetchedTexture> LLWorldMipmap::getObjectsTile(U32 grid_x, U32
LLPointer<LLViewerFetchedTexture> LLWorldMipmap::loadObjectsTile(U32 grid_x, U32 grid_y, S32 level)
{
// Get the grid coordinates
- std::string imageurl = gSavedSettings.getString("MapServerURL") + llformat("map-%d-%d-%d-objects.jpg", level, grid_x, grid_y);
-
+ std::string imageurl = gSavedSettings.getString("CurrentMapServerURL") + llformat("map-%d-%d-%d-objects.jpg", level, grid_x, grid_y);
// DO NOT COMMIT!! DEBUG ONLY!!!
// Use a local jpeg for every tile to test map speed without S3 access
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index a51a096482..89611d8899 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -392,7 +392,7 @@ with the same filename but different name
<texture name="RadioButton_On_Disabled" file_name="widgets/RadioButton_On_Disabled.png" preload="true" />
- <texture name="Refresh_Off" file_name="icons/Refresh_Off.png" preload="false" />
+ <texture name="Refresh_Off" file_name="icons/Refresh_Off.png" preload="true" />
<texture name="Resize_Corner" file_name="windows/Resize_Corner.png" preload="true" />
@@ -468,7 +468,7 @@ with the same filename but different name
<texture name="Stepper_Up_Off" file_name="widgets/Stepper_Up_Off.png" preload="false" />
<texture name="Stepper_Up_Press" file_name="widgets/Stepper_Up_Press.png" preload="false" />
- <texture name="Stop_Off" file_name="icons/Stop_Off.png" preload="false" />
+ <texture name="Stop_Off" file_name="icons/Stop_Off.png" preload="true" />
<texture name="StopReload_Off" file_name="icons/StopReload_Off.png" preload="false" />
<texture name="StopReload_Over" file_name="icons/StopReload_Over.png" preload="false" />
diff --git a/indra/newview/skins/default/xui/en/floater_help_browser.xml b/indra/newview/skins/default/xui/en/floater_help_browser.xml
index 837923bcf6..02e50ee584 100644
--- a/indra/newview/skins/default/xui/en/floater_help_browser.xml
+++ b/indra/newview/skins/default/xui/en/floater_help_browser.xml
@@ -36,7 +36,8 @@
user_resize="false"
width="620">
<web_browser
- trusted_content="true"
+ trusted_content="true"
+ initial_mime_type="text/html"
bottom="-25"
follows="left|right|top|bottom"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_web_content.xml b/indra/newview/skins/default/xui/en/floater_web_content.xml
new file mode 100644
index 0000000000..2ad46824c2
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_web_content.xml
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="440"
+ layout="topleft"
+ min_height="140"
+ min_width="467"
+ name="floater_web_content"
+ help_topic="floater_web_content"
+ save_rect="true"
+ auto_tile="true"
+ title=""
+ initial_mime_type="text/html"
+ width="820">
+ <layout_stack
+ bottom="440"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ left="5"
+ name="stack1"
+ orientation="vertical"
+ top="20"
+ width="810">
+ <layout_panel
+ auto_resize="false"
+ default_tab_group="1"
+ height="22"
+ layout="topleft"
+ left="0"
+ min_height="20"
+ name="nav_controls"
+ top="400"
+ user_resize="false"
+ width="800">
+ <button
+ image_overlay="Arrow_Left_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ tool_tip="Navigate back"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="1"
+ name="back"
+ top="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.Back" />
+ </button>
+ <button
+ image_overlay="Arrow_Right_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ tool_tip="Navigate forward"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="27"
+ name="forward"
+ top_delta="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.Forward" />
+ </button>
+ <button
+ image_overlay="Stop_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ tool_tip="Stop navigation"
+ enabled="true"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="51"
+ name="stop"
+ top_delta="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.Stop" />
+ </button>
+ <button
+ image_overlay="Refresh_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ tool_tip="Reload page"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="51"
+ name="reload"
+ top_delta="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.Reload" />
+ </button>
+ <combo_box
+ allow_text_entry="true"
+ follows="left|top|right"
+ tab_group="1"
+ height="22"
+ layout="topleft"
+ left_pad="4"
+ max_chars="1024"
+ name="address"
+ combo_editor.select_on_focus="true"
+ tool_tip="Enter URL here"
+ top_delta="0"
+ width="702">
+ <combo_box.commit_callback
+ function="WebContent.EnterAddress" />
+ </combo_box>
+ <icon
+ name="media_secure_lock_flag"
+ height="16"
+ follows="top|right"
+ image_name="Lock2"
+ layout="topleft"
+ left_delta="656"
+ top_delta="2"
+ visible="false"
+ tool_tip="Secured Browsing"
+ width="16" />
+ <button
+ image_overlay="ExternalBrowser_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ tool_tip="Open current URL in your desktop browser"
+ follows="right|top"
+ enabled="true"
+ height="22"
+ layout="topleft"
+ name="popexternal"
+ right="800"
+ top_delta="-2"
+ width="22">
+ <button.commit_callback
+ function="WebContent.PopExternal" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ height="40"
+ layout="topleft"
+ left_delta="0"
+ name="external_controls"
+ top_delta="0"
+ user_resize="false"
+ width="540">
+ <web_browser
+ bottom="-22"
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="webbrowser"
+ top="0"/>
+ <text
+ type="string"
+ length="100"
+ follows="bottom|left"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="statusbartext"
+ parse_urls="false"
+ text_color="0.4 0.4 0.4 1"
+ top_pad="5"
+ width="452"/>
+ <progress_bar
+ color_bar="0.3 1.0 0.3 1"
+ follows="bottom|right"
+ height="16"
+ top_delta="-1"
+ left_pad="24"
+ layout="topleft"
+ name="statusbarprogress"
+ width="64"/>
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/inspect_object.xml b/indra/newview/skins/default/xui/en/inspect_object.xml
index eb2e7ea788..8d14c974b4 100644
--- a/indra/newview/skins/default/xui/en/inspect_object.xml
+++ b/indra/newview/skins/default/xui/en/inspect_object.xml
@@ -76,13 +76,24 @@ L$30,000
</text>
<!-- Overlapping buttons for all default actions. Show "Buy" if
for sale, "Sit" if can sit, etc. -->
+ <icon
+ name="secure_browsing"
+ image_name="Lock"
+ left="0"
+ visible="false"
+ width="18"
+ height="18"
+ top="103"
+ tool_tip="Secure Browsing"
+ follows="left|top" />
<text
follows="all"
font="SansSerifSmall"
height="13"
name="object_media_url"
- width="220"
- top_pad="0"
+ width="207"
+ left_pad="2"
+ top_delta="0"
max_length = "50"
use_ellipses="true">
http://www.superdupertest.com
@@ -135,16 +146,6 @@ L$30,000
name="open_btn"
top_delta="0"
width="80" />
- <icon
- name="secure_browsing"
- image_name="Lock"
- left_delta="80"
- visible="false"
- width="18"
- height="18"
- top_delta="0"
- tool_tip="Secure Browsing"
- follows="left|top" />
<!-- non-overlapping buttons here -->
<button
@@ -153,7 +154,7 @@ L$30,000
label="More"
layout="topleft"
name="more_info_btn"
- left_delta="10"
+ left_pad="10"
top_delta="0"
tab_stop="false"
width="80" />
diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml
index 4f982cc8e9..0d4a095e14 100644
--- a/indra/newview/skins/default/xui/en/menu_login.xml
+++ b/indra/newview/skins/default/xui/en/menu_login.xml
@@ -176,13 +176,19 @@
parameter="message_critical" />
</menu_item_call>
<menu_item_call
- label="Web Browser Test"
+ label="Media Browser Test"
name="Web Browser Test">
<menu_item_call.on_click
function="Advanced.WebBrowserTest"
parameter="http://join.secondlife.com/"/>
</menu_item_call>
- <menu_item_separator/>
+ <menu_item_call
+ label="Web Content Floater Test"
+ name="Web Content Floater Test">
+ <menu_item_call.on_click
+ function="Advanced.WebContentTest"
+ parameter="http://www.google.com"/>
+ </menu_item_call>
<menu_item_check
label="Show Grid Picker"
name="Show Grid Picker"
diff --git a/indra/newview/skins/default/xui/en/menu_mini_map.xml b/indra/newview/skins/default/xui/en/menu_mini_map.xml
index 8fe89d3934..ea263d05ce 100644
--- a/indra/newview/skins/default/xui/en/menu_mini_map.xml
+++ b/indra/newview/skins/default/xui/en/menu_mini_map.xml
@@ -8,7 +8,7 @@
top="724"
visible="false"
width="128">
- <menu_item_call
+ <menu_item_call
label="Zoom Close"
name="Zoom Close">
<menu_item_call.on_click
@@ -29,7 +29,14 @@
function="Minimap.Zoom"
parameter="far" />
</menu_item_call>
- <menu_item_separator />
+ <menu_item_call
+ label="Zoom Default"
+ name="Zoom Default">
+ <menu_item_call.on_click
+ function="Minimap.Zoom"
+ parameter="default" />
+ </menu_item_call>
+ <menu_item_separator />
<menu_item_check
label="Rotate Map"
name="Rotate Map">
diff --git a/indra/newview/skins/default/xui/en/menu_place.xml b/indra/newview/skins/default/xui/en/menu_place.xml
index 1b96eb51f0..288811d2f6 100644
--- a/indra/newview/skins/default/xui/en/menu_place.xml
+++ b/indra/newview/skins/default/xui/en/menu_place.xml
@@ -24,26 +24,4 @@
function="Places.OverflowMenu.Enable"
parameter="can_create_pick" />
</menu_item_call>
- <menu_item_separator
- layout="topleft"/>
- <menu_item_call
- enabled="false"
- label="Buy Pass"
- layout="topleft"
- name="pass">
- <menu_item_call.on_click
- function="Places.OverflowMenu.Action"
- parameter="pass" />
- </menu_item_call>
- <menu_item_separator
- layout="topleft"/>
- <menu_item_call
- enabled="false"
- label="Edit"
- layout="topleft"
- name="edit">
- <menu_item_call.on_click
- function="Places.OverflowMenu.Action"
- parameter="edit" />
- </menu_item_call>
</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 3b1ebc64ab..d997a262a8 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -2646,13 +2646,21 @@
parameter="BottomPanelNew" />
</menu_item_check>-->
<menu_item_call
- label="Web Browser Test"
+ label="Media Browser Test"
name="Web Browser Test">
<menu_item_call.on_click
function="Advanced.WebBrowserTest"
parameter="http://secondlife.com/app/search/slurls.html"/>
</menu_item_call>
- <menu_item_call
+ <menu_item_call
+ label="Web Content Browser"
+ name="Web Content Browser"
+ shortcut="control|alt|W">
+ <menu_item_call.on_click
+ function="Advanced.WebContentTest"
+ parameter="http://google.com"/>
+ </menu_item_call>
+ <menu_item_call
label="Dump SelectMgr"
name="Dump SelectMgr">
<menu_item_call.on_click
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index b1fd579c6f..63c030b068 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -2901,12 +2901,80 @@ http://secondlife.com/download.
name="okbutton"
yestext="OK"/>
</notification>
+
<notification
- icon="notifytip.tga"
- name="DownloadBackground"
- type="notifytip">
-An updated version of [APP_NAME] has been downloaded.
-It will be applied the next time you restart [APP_NAME]
+ icon="alertmodal.tga"
+ name="FailedRequiredUpdateInstall"
+ type="alertmodal">
+We were unable to install a required update.
+You will be unable to log in until [APP_NAME] has been updated.
+
+Please download and install the latest viewer from
+http://secondlife.com/download.
+ <usetemplate
+ name="okbutton"
+ yestext="Quit"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="UpdaterServiceNotRunning"
+ type="alertmodal">
+There is a required update for your Second Life Installation.
+
+You may download this update from http://www.secondlife.com/downloads
+or you can install it now.
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Quit Second Life"
+ yestext="Download and install now"/>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="DownloadBackgroundTip"
+ type="notify">
+We have downloaded an update to your [APP_NAME] installation.
+Version [VERSION] [[RELEASE_NOTES_FULL_URL] Information about this update]
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Later..."
+ yestext="Install now and restart [APP_NAME]"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="DownloadBackgroundDialog"
+ type="alertmodal">
+We have downloaded an update to your [APP_NAME] installation.
+Version [VERSION] [[RELEASE_NOTES_FULL_URL] Information about this update]
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Later..."
+ yestext="Install now and restart [APP_NAME]"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="RequiredUpdateDownloadedVerboseDialog"
+ type="alertmodal">
+We have downloaded a required software update.
+Version [VERSION]
+
+We must restart [APP_NAME] to install the update.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="RequiredUpdateDownloadedDialog"
+ type="alertmodal">
+We must restart [APP_NAME] to install the update.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
</notification>
<notification
@@ -5014,7 +5082,7 @@ If you want to view streaming media on parcels that support it you should go to
type="notify">
No Media Plugin was found to handle the "[MIME_TYPE]" mime type. Media of this type will be unavailable.
<unique>
- <context key="[MIME_TYPE]"/>
+ <context>MIME_TYPE</context>
</unique>
</notification>
@@ -5943,7 +6011,7 @@ You may only select up to [MAX_SELECT] items from this list.
[NAME] is inviting you to a Voice Chat call.
Click Accept to join the call or Decline to decline the invitation. Click Block to block this caller.
<unique>
- <context key="NAME"/>
+ <context>NAME</context>
</unique>
<form name="form">
<button
@@ -5992,8 +6060,8 @@ Click Accept to join the call or Decline to decline the invitation. Click Block
[NAME] has joined a Voice Chat call with the group [GROUP].
Click Accept to join the call or Decline to decline the invitation. Click Block to block this caller.
<unique>
- <context key="NAME"/>
- <context key="GROUP"/>
+ <context>NAME</context>
+ <context>GROUP</context>
</unique>
<form name="form">
<button
@@ -6018,7 +6086,7 @@ Click Accept to join the call or Decline to decline the invitation. Click Block
[NAME] has joined a voice chat call with a conference chat.
Click Accept to join the call or Decline to decline the invitation. Click Block to block this caller.
<unique>
- <context key="NAME"/>
+ <context>NAME</context>
</unique>
<form name="form">
<button
@@ -6043,7 +6111,7 @@ Click Accept to join the call or Decline to decline the invitation. Click Block
[NAME] is inviting you to a conference chat.
Click Accept to join the chat or Decline to decline the invitation. Click Block to block this caller.
<unique>
- <context key="NAME"/>
+ <context>NAME</context>
</unique>
<form name="form">
<button
@@ -6067,7 +6135,7 @@ Click Accept to join the chat or Decline to decline the invitation. Click Block
type="notifytip">
The voice call you are trying to join, [VOICE_CHANNEL_NAME], has reached maximum capacity. Please try again later.
<unique>
- <context key="VOICE_CHANNEL_NAME"/>
+ <context>VOICE_CHANNEL_NAME</context>
</unique>
</notification>
@@ -6085,7 +6153,7 @@ We&apos;re sorry. This area has reached maximum capacity for voice conversation
type="notifytip">
You have been disconnected from [VOICE_CHANNEL_NAME]. You will now be reconnected to Nearby Voice Chat.
<unique>
- <context key="VOICE_CHANNEL_NAME"/>
+ <context>VOICE_CHANNEL_NAME</context>
</unique>
</notification>
@@ -6095,7 +6163,7 @@ You have been disconnected from [VOICE_CHANNEL_NAME]. You will now be reconnect
type="notifytip">
[VOICE_CHANNEL_NAME] has ended the call. You will now be reconnected to Nearby Voice Chat.
<unique>
- <context key="VOICE_CHANNEL_NAME"/>
+ <context>VOICE_CHANNEL_NAME</context>
</unique>
</notification>
@@ -6105,7 +6173,7 @@ You have been disconnected from [VOICE_CHANNEL_NAME]. You will now be reconnect
type="notifytip">
[VOICE_CHANNEL_NAME] has declined your call. You will now be reconnected to Nearby Voice Chat.
<unique>
- <context key="VOICE_CHANNEL_NAME"/>
+ <context>VOICE_CHANNEL_NAME</context>
</unique>
</notification>
@@ -6115,7 +6183,7 @@ You have been disconnected from [VOICE_CHANNEL_NAME]. You will now be reconnect
type="notifytip">
[VOICE_CHANNEL_NAME] is not available to take your call. You will now be reconnected to Nearby Voice Chat.
<unique>
- <context key="VOICE_CHANNEL_NAME"/>
+ <context>VOICE_CHANNEL_NAME</context>
</unique>
</notification>
@@ -6125,7 +6193,7 @@ You have been disconnected from [VOICE_CHANNEL_NAME]. You will now be reconnect
type="notifytip">
Failed to connect to [VOICE_CHANNEL_NAME], please try again later. You will now be reconnected to Nearby Voice Chat.
<unique>
- <context key="VOICE_CHANNEL_NAME"/>
+ <context>VOICE_CHANNEL_NAME</context>
</unique>
</notification>
@@ -6211,7 +6279,7 @@ Cannot enter parcel, you are not on the access list.
type="notifytip">
You do not have permission to connect to voice chat for [VOICE_CHANNEL_NAME].
<unique>
- <context key="VOICE_CHANNEL_NAME"/>
+ <context>VOICE_CHANNEL_NAME</context>
</unique>
</notification>
@@ -6221,7 +6289,7 @@ You do not have permission to connect to voice chat for [VOICE_CHANNEL_NAME].
type="notifytip">
An error has occurred while trying to connect to voice chat for [VOICE_CHANNEL_NAME]. Please try again later.
<unique>
- <context key="VOICE_CHANNEL_NAME"/>
+ <context>VOICE_CHANNEL_NAME</context>
</unique>
</notification>
@@ -6628,6 +6696,23 @@ Mute everyone?
</form>
</notification>
+ <notification
+ name="AuthRequest"
+ type="browser">
+The site at &apos;&lt;nolink&gt;[HOST_NAME]&lt;/nolink&gt;&apos; in realm &apos;[REALM]&apos; requires a user name and password.
+ <form name="form">
+ <input name="username" type="text" text="User Name"/>
+ <input name="password" type="password" text="Password "/>
+ <button default="true"
+ index="0"
+ name="ok"
+ text="Submit"/>
+ <button index="1"
+ name="cancel"
+ text="Cancel"/>
+ </form>
+ </notification>
+
<global name="UnsupportedCPU">
- Your CPU speed does not meet the minimum requirements.
diff --git a/indra/newview/skins/default/xui/en/panel_group_invite.xml b/indra/newview/skins/default/xui/en/panel_group_invite.xml
index 15a3191bdf..cd834b61ce 100644
--- a/indra/newview/skins/default/xui/en/panel_group_invite.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_invite.xml
@@ -94,7 +94,7 @@
left_pad="2"
name="cancel_button"
top_delta="0"
- width="70" />
+ width="65" />
<string
name="GroupInvitation">
Group Invitation
diff --git a/indra/newview/skins/default/xui/en/panel_group_land_money.xml b/indra/newview/skins/default/xui/en/panel_group_land_money.xml
index 1270a21710..61d6cbb2d0 100644
--- a/indra/newview/skins/default/xui/en/panel_group_land_money.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_land_money.xml
@@ -117,7 +117,7 @@
name="map_button"
top_delta="-4"
left_pad="0"
- width="60"
+ width="57"
enabled="false" />
<text
type="string"
diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml
index e3cd61c5aa..257ed799da 100644
--- a/indra/newview/skins/default/xui/en/panel_login.xml
+++ b/indra/newview/skins/default/xui/en/panel_login.xml
@@ -12,11 +12,7 @@ top="600"
name="create_account_url">
http://join.secondlife.com/
</panel.string>
-<panel.string
- name="real_url" translate="false">
- http://secondlife.com/app/login/
-</panel.string>
- <string name="reg_in_client_url" translate="false">
+<string name="reg_in_client_url" translate="false">
http://secondlife.eniac15.lindenlab.com/reg-in-client/
</string>
<panel.string
@@ -92,6 +88,7 @@ follows="left|bottom"
height="22"
max_length_bytes="16"
name="password_edit"
+is_password="true"
select_on_focus="true"
top_pad="0"
width="135" />
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
index 584bd1ea9d..901a1257e0 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
@@ -142,7 +142,7 @@
layout="topleft"
left="80"
name="Cache location"
- top_delta="40"
+ top_delta="20"
width="300">
Cache location:
</text>
@@ -341,20 +341,41 @@
name="web_proxy_port"
top_delta="0"
width="145" />
-
- <check_box
- top_delta="2"
- enabled="true"
- follows="left|top"
- height="18"
- initial_value="true"
- control_name="UpdaterServiceActive"
- label="Automatically download and install [APP_NAME] updates"
- left="30"
- mouse_opaque="true"
- name="updater_service_active"
- radio_style="false"
- width="400"
- top_pad="10"/>
-
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="30"
+ name="Software updates:"
+ mouse_opaque="false"
+ top_pad="5"
+ width="300">
+ Software updates:
+ </text>
+ <combo_box
+ control_name="UpdaterServiceSetting"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left_delta="50"
+ top_pad="5"
+ name="updater_service_combobox"
+ width="300">
+ <combo_box.item
+ label="Install automatically"
+ name="Install_automatically"
+ value="3" />
+ <!--
+ <combo_box.item
+ label="Ask before installing"
+ name="Install_ask"
+ value="1" />
+ -->
+ <combo_box.item
+ label="Download and install updates manually"
+ name="Install_manual"
+ value="0" />
+ </combo_box>
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
index da366f30ae..f0ce8b849a 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
@@ -296,6 +296,7 @@
<check_box
name="media_auto_play_btn"
control_name="ParcelMediaAutoPlayEnable"
+ enabled_control="AudioStreamingMedia"
value="true"
follows="left|bottom|right"
height="15"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 51fba470cb..752bb6ed3a 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -1716,8 +1716,8 @@ integer llGetRegionAgentCount()
Returns the number of avatars in the region
</string>
<string name="LSLTipText_llTextBox" translate="false">
-llTextBox(key avatar, string message, integer chat_channel
-Shows a dialog box on the avatar&apos;s screen with the message.
+llTextBox(key avatar, string message, integer chat_channel)
+Shows a window on the avatar&apos;s screen with the message.
It contains a text box for input, and if entered that text is chatted on chat_channel.
</string>
<string name="LSLTipText_llGetAgentLanguage" translate="false">
diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp
index 309e9e9ee3..9e321db889 100644
--- a/indra/newview/tests/lllogininstance_test.cpp
+++ b/indra/newview/tests/lllogininstance_test.cpp
@@ -40,6 +40,7 @@
#if defined(LL_WINDOWS)
#pragma warning(disable: 4355) // using 'this' in base-class ctor initializer expr
+#pragma warning(disable: 4702) // disable 'unreachable code' so we can safely use skip().
#endif
// Constants
@@ -68,6 +69,7 @@ static bool gDisconnectCalled = false;
#include "../llviewerwindow.h"
void LLViewerWindow::setShowProgress(BOOL show) {}
+LLProgressView * LLViewerWindow::getProgressView(void) const { return 0; }
LLViewerWindow* gViewerWindow;
@@ -185,6 +187,41 @@ const std::string &LLVersionInfo::getChannelAndVersion() { return VIEWERLOGIN_VE
const std::string &LLVersionInfo::getChannel() { return VIEWERLOGIN_CHANNEL; }
//-----------------------------------------------------------------------------
+#include "../llappviewer.h"
+void LLAppViewer::forceQuit(void) {}
+LLAppViewer * LLAppViewer::sInstance = 0;
+
+//-----------------------------------------------------------------------------
+#include "llnotificationsutil.h"
+LLNotificationPtr LLNotificationsUtil::add(const std::string& name,
+ const LLSD& substitutions,
+ const LLSD& payload,
+ boost::function<void (const LLSD&, const LLSD&)> functor) { return LLNotificationPtr((LLNotification*)0); }
+
+
+//-----------------------------------------------------------------------------
+#include "llupdaterservice.h"
+
+std::string const & LLUpdaterService::pumpName(void)
+{
+ static std::string wakka = "wakka wakka wakka";
+ return wakka;
+}
+bool LLUpdaterService::updateReadyToInstall(void) { return false; }
+void LLUpdaterService::initialize(const std::string& protocol_version,
+ const std::string& url,
+ const std::string& path,
+ const std::string& channel,
+ const std::string& version) {}
+
+void LLUpdaterService::setCheckPeriod(unsigned int seconds) {}
+void LLUpdaterService::startChecking(bool install_if_ready) {}
+void LLUpdaterService::stopChecking() {}
+bool LLUpdaterService::isChecking() { return false; }
+LLUpdaterService::eUpdaterState LLUpdaterService::getState() { return INITIAL; }
+std::string LLUpdaterService::updatedVersion() { return ""; }
+
+//-----------------------------------------------------------------------------
#include "llnotifications.h"
#include "llfloaterreg.h"
static std::string gTOSType;
@@ -198,6 +235,12 @@ LLFloater* LLFloaterReg::showInstance(const std::string& name, const LLSD& key,
return NULL;
}
+//----------------------------------------------------------------------------
+#include "../llprogressview.h"
+void LLProgressView::setText(std::string const &){}
+void LLProgressView::setPercent(float){}
+void LLProgressView::setMessage(std::string const &){}
+
//-----------------------------------------------------------------------------
// LLNotifications
class MockNotifications : public LLNotificationsInterface
@@ -435,6 +478,8 @@ namespace tut
template<> template<>
void lllogininstance_object::test<3>()
{
+ skip();
+
set_test_name("Test Mandatory Update User Accepts");
// Part 1 - Mandatory Update, with User accepts response.
@@ -462,6 +507,8 @@ namespace tut
template<> template<>
void lllogininstance_object::test<4>()
{
+ skip();
+
set_test_name("Test Mandatory Update User Decline");
// Test connect with update needed.
diff --git a/indra/newview/tests/llworldmap_test.cpp b/indra/newview/tests/llworldmap_test.cpp
index b976ac5ea9..acc6e814bc 100644
--- a/indra/newview/tests/llworldmap_test.cpp
+++ b/indra/newview/tests/llworldmap_test.cpp
@@ -25,13 +25,16 @@
* $/LicenseInfo$
*/
-// Precompiled header: almost always required for newview cpp files
-#include "../llviewerprecompiledheaders.h"
-// Class to test
-#include "../llworldmap.h"
// Dependencies
-#include "../llviewerimagelist.h"
+#include "linden_common.h"
+#include "llapr.h"
+#include "llsingleton.h"
+#include "lltrans.h"
+#include "lluistring.h"
+#include "../llviewertexture.h"
#include "../llworldmapmessage.h"
+// Class to test
+#include "../llworldmap.h"
// Tut header
#include "../test/lltut.h"
@@ -44,34 +47,29 @@
// * A simulator for a class can be implemented here. Please comment and document thoroughly.
// Stub image calls
-LLViewerImageList::LLViewerImageList() { }
-LLViewerImageList::~LLViewerImageList() { }
-LLViewerImageList gImageList;
-LLViewerImage* LLViewerImageList::getImage(const LLUUID &image_id,
- BOOL usemipmaps,
- BOOL level_immediate,
- LLGLint internal_format,
- LLGLenum primary_format,
- LLHost request_from_host)
-{ return NULL; }
-void LLViewerImage::setBoostLevel(S32 level) { }
-void LLImageGL::setAddressMode(LLTexUnit::eTextureAddressMode mode) { }
+void LLViewerTexture::setBoostLevel(S32 ) { }
+void LLViewerTexture::setAddressMode(LLTexUnit::eTextureAddressMode ) { }
+LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture(const LLUUID&, BOOL, LLViewerTexture::EBoostLevel, S8,
+ LLGLint, LLGLenum, LLHost ) { return NULL; }
// Stub related map calls
LLWorldMapMessage::LLWorldMapMessage() { }
LLWorldMapMessage::~LLWorldMapMessage() { }
void LLWorldMapMessage::sendItemRequest(U32 type, U64 handle) { }
void LLWorldMapMessage::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent) { }
+
LLWorldMipmap::LLWorldMipmap() { }
LLWorldMipmap::~LLWorldMipmap() { }
void LLWorldMipmap::reset() { }
void LLWorldMipmap::dropBoostLevels() { }
void LLWorldMipmap::equalizeBoostLevels() { }
-LLPointer<LLViewerImage> LLWorldMipmap::getObjectsTile(U32 grid_x, U32 grid_y, S32 level, bool load)
-{ return NULL; }
+LLPointer<LLViewerFetchedTexture> LLWorldMipmap::getObjectsTile(U32 grid_x, U32 grid_y, S32 level, bool load) { return NULL; }
// Stub other stuff
-BOOL gPacificDaylightTime;
+std::string LLTrans::getString(const std::string &, const LLStringUtil::format_map_t& ) { return std::string("test_trans"); }
+void LLUIString::updateResult() const { }
+void LLUIString::setArg(const std::string& , const std::string& ) { }
+void LLUIString::assign(const std::string& ) { }
// End Stubbing
// -------------------------------------------------------------------------------------------
@@ -237,7 +235,7 @@ namespace tut
// Test 9 : setLandForSaleImage() / getLandForSaleImage()
LLUUID id;
mSim->setLandForSaleImage(id);
- LLPointer<LLViewerImage> image = mSim->getLandForSaleImage();
+ LLPointer<LLViewerFetchedTexture> image = mSim->getLandForSaleImage();
ensure("LLSimInfo::getLandForSaleImage() test failed", image.isNull());
// Test 10 : isPG()
mSim->setAccess(SIM_ACCESS_PG);
@@ -370,7 +368,7 @@ namespace tut
}
// Test 7 : getObjectsTile()
try {
- LLPointer<LLViewerImage> image = mWorld->getObjectsTile((U32)(X_WORLD_TEST/REGION_WIDTH_METERS), (U32)(Y_WORLD_TEST/REGION_WIDTH_METERS), 1);
+ LLPointer<LLViewerFetchedTexture> image = mWorld->getObjectsTile((U32)(X_WORLD_TEST/REGION_WIDTH_METERS), (U32)(Y_WORLD_TEST/REGION_WIDTH_METERS), 1);
ensure("LLWorldMap::getObjectsTile() failed", image.isNull());
} catch (...) {
fail("LLWorldMap::getObjectsTile() test failed with exception");
diff --git a/indra/newview/tests/llworldmipmap_test.cpp b/indra/newview/tests/llworldmipmap_test.cpp
index 54887ae219..4c0959d1a9 100644
--- a/indra/newview/tests/llworldmipmap_test.cpp
+++ b/indra/newview/tests/llworldmipmap_test.cpp
@@ -25,12 +25,12 @@
* $/LicenseInfo$
*/
-// Precompiled header: almost always required for newview cpp files
-#include "../llviewerprecompiledheaders.h"
+// Dependencies
+#include "linden_common.h"
+#include "../llviewertexture.h"
+#include "../llviewercontrol.h"
// Class to test
#include "../llworldmipmap.h"
-// Dependencies
-#include "../llviewerimagelist.h"
// Tut header
#include "../test/lltut.h"
@@ -42,19 +42,14 @@
// * Do not make any assumption as to how those classes or methods work (i.e. don't copy/paste code)
// * A simulator for a class can be implemented here. Please comment and document thoroughly.
-LLViewerImageList::LLViewerImageList() { }
-LLViewerImageList::~LLViewerImageList() { }
-
-LLViewerImageList gImageList;
+void LLViewerTexture::setBoostLevel(S32 ) { }
+LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const std::string&, BOOL, LLViewerTexture::EBoostLevel, S8,
+ LLGLint, LLGLenum, const LLUUID& ) { return NULL; }
-LLViewerImage* LLViewerImageList::getImageFromUrl(const std::string& url,
- BOOL usemipmaps,
- BOOL level_immediate,
- LLGLint internal_format,
- LLGLenum primary_format,
- const LLUUID& force_id)
-{ return NULL; }
-void LLViewerImage::setBoostLevel(S32 level) { }
+LLControlGroup::LLControlGroup(const std::string& name) : LLInstanceTracker<LLControlGroup, std::string>(name) { }
+LLControlGroup::~LLControlGroup() { }
+std::string LLControlGroup::getString(const std::string& ) { return std::string("test_url"); }
+LLControlGroup gSavedSettings("test_settings");
// End Stubbing
// -------------------------------------------------------------------------------------------
diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt
index 66c78a86c4..e9eb3c1884 100644
--- a/indra/test/CMakeLists.txt
+++ b/indra/test/CMakeLists.txt
@@ -27,6 +27,7 @@ include_directories(
${LLXML_INCLUDE_DIRS}
${LSCRIPT_INCLUDE_DIRS}
${GOOGLEMOCK_INCLUDE_DIRS}
+ ${TUT_INCLUDE_DIR}
)
set(test_SOURCE_FILES
diff --git a/indra/test_apps/llplugintest/llmediaplugintest.cpp b/indra/test_apps/llplugintest/llmediaplugintest.cpp
index 873fa23db8..4a2272032b 100644
--- a/indra/test_apps/llplugintest/llmediaplugintest.cpp
+++ b/indra/test_apps/llplugintest/llmediaplugintest.cpp
@@ -2220,6 +2220,21 @@ void LLMediaPluginTest::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent e
<< ", height = " << self->getGeometryHeight()
<< std::endl;
break;
+
+ case MEDIA_EVENT_AUTH_REQUEST:
+ {
+ //std::cerr << "Media event: MEDIA_EVENT_AUTH_REQUEST, url " << self->getAuthURL() ", realm " << self->getAuthRealm() << std::endl;
+
+ // TODO: display an auth dialog
+ self->sendAuthResponse(false, "", "");
+ }
+ break;
+
+ case MEDIA_EVENT_LINK_HOVERED:
+ {
+ std::cerr << "Media event: MEDIA_EVENT_LINK_HOVERED, hover text is: " << self->getHoverText() << std::endl;
+ };
+ break;
}
}
diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp
index c17a50e242..e88d1bf811 100644
--- a/indra/viewer_components/updater/llupdatedownloader.cpp
+++ b/indra/viewer_components/updater/llupdatedownloader.cpp
@@ -24,17 +24,20 @@
*/
#include "linden_common.h"
+
+#include "llupdatedownloader.h"
+
#include <stdexcept>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <curl/curl.h>
#include "lldir.h"
+#include "llevents.h"
#include "llfile.h"
#include "llmd5.h"
#include "llsd.h"
#include "llsdserialize.h"
#include "llthread.h"
-#include "llupdatedownloader.h"
#include "llupdaterservice.h"
@@ -45,18 +48,25 @@ public:
Implementation(LLUpdateDownloader::Client & client);
~Implementation();
void cancel(void);
- void download(LLURI const & uri, std::string const & hash);
+ void download(LLURI const & uri,
+ std::string const & hash,
+ std::string const & updateVersion,
+ bool required);
bool isDownloading(void);
size_t onHeader(void * header, size_t size);
size_t onBody(void * header, size_t size);
+ int onProgress(double downloadSize, double bytesDownloaded);
void resume(void);
+ void setBandwidthLimit(U64 bytesPerSecond);
private:
+ curl_off_t mBandwidthLimit;
bool mCancelled;
LLUpdateDownloader::Client & mClient;
CURL * mCurl;
LLSD mDownloadData;
llofstream mDownloadStream;
+ unsigned char mDownloadPercent;
std::string mDownloadRecordPath;
curl_slist * mHeaderList;
@@ -113,9 +123,12 @@ void LLUpdateDownloader::cancel(void)
}
-void LLUpdateDownloader::download(LLURI const & uri, std::string const & hash)
+void LLUpdateDownloader::download(LLURI const & uri,
+ std::string const & hash,
+ std::string const & updateVersion,
+ bool required)
{
- mImplementation->download(uri, hash);
+ mImplementation->download(uri, hash, updateVersion, required);
}
@@ -131,6 +144,12 @@ void LLUpdateDownloader::resume(void)
}
+void LLUpdateDownloader::setBandwidthLimit(U64 bytesPerSecond)
+{
+ mImplementation->setBandwidthLimit(bytesPerSecond);
+}
+
+
// LLUpdateDownloader::Implementation
//-----------------------------------------------------------------------------
@@ -149,14 +168,27 @@ namespace {
size_t bytes = blockSize * blocks;
return reinterpret_cast<LLUpdateDownloader::Implementation *>(downloader)->onHeader(data, bytes);
}
+
+
+ int progress_callback(void * downloader,
+ double dowloadTotal,
+ double downloadNow,
+ double uploadTotal,
+ double uploadNow)
+ {
+ return reinterpret_cast<LLUpdateDownloader::Implementation *>(downloader)->
+ onProgress(dowloadTotal, downloadNow);
+ }
}
LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & client):
LLThread("LLUpdateDownloader"),
+ mBandwidthLimit(0),
mCancelled(false),
mClient(client),
mCurl(0),
+ mDownloadPercent(0),
mHeaderList(0)
{
CURLcode code = curl_global_init(CURL_GLOBAL_ALL); // Just in case.
@@ -182,12 +214,17 @@ void LLUpdateDownloader::Implementation::cancel(void)
}
-void LLUpdateDownloader::Implementation::download(LLURI const & uri, std::string const & hash)
+void LLUpdateDownloader::Implementation::download(LLURI const & uri,
+ std::string const & hash,
+ std::string const & updateVersion,
+ bool required)
{
if(isDownloading()) mClient.downloadError("download in progress");
mDownloadRecordPath = downloadMarkerPath();
mDownloadData = LLSD();
+ mDownloadData["required"] = required;
+ mDownloadData["update_version"] = updateVersion;
try {
startDownloading(uri, hash);
} catch(DownloadError const & e) {
@@ -233,12 +270,18 @@ void LLUpdateDownloader::Implementation::resume(void)
resumeDownloading(fileStatus.st_size);
} else if(!validateDownload()) {
LLFile::remove(filePath);
- download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString());
+ download(LLURI(mDownloadData["url"].asString()),
+ mDownloadData["hash"].asString(),
+ mDownloadData["update_version"].asString(),
+ mDownloadData["required"].asBoolean());
} else {
mClient.downloadComplete(mDownloadData);
}
} else {
- download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString());
+ download(LLURI(mDownloadData["url"].asString()),
+ mDownloadData["hash"].asString(),
+ mDownloadData["update_version"].asString(),
+ mDownloadData["required"].asBoolean());
}
} catch(DownloadError & e) {
mClient.downloadError(e.what());
@@ -246,6 +289,20 @@ void LLUpdateDownloader::Implementation::resume(void)
}
+void LLUpdateDownloader::Implementation::setBandwidthLimit(U64 bytesPerSecond)
+{
+ if((mBandwidthLimit != bytesPerSecond) && isDownloading() && !mDownloadData["required"].asBoolean()) {
+ llassert(mCurl != 0);
+ mBandwidthLimit = bytesPerSecond;
+ CURLcode code = curl_easy_setopt(mCurl, CURLOPT_MAX_RECV_SPEED_LARGE, &mBandwidthLimit);
+ if(code != CURLE_OK) LL_WARNS("UpdateDownload") <<
+ "unable to change dowload bandwidth" << LL_ENDL;
+ } else {
+ mBandwidthLimit = bytesPerSecond;
+ }
+}
+
+
size_t LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size)
{
char const * headerPtr = reinterpret_cast<const char *> (buffer);
@@ -290,6 +347,30 @@ size_t LLUpdateDownloader::Implementation::onBody(void * buffer, size_t size)
}
+int LLUpdateDownloader::Implementation::onProgress(double downloadSize, double bytesDownloaded)
+{
+ int downloadPercent = static_cast<int>(100. * (bytesDownloaded / downloadSize));
+ if(downloadPercent > mDownloadPercent) {
+ mDownloadPercent = downloadPercent;
+
+ LLSD event;
+ event["pump"] = LLUpdaterService::pumpName();
+ LLSD payload;
+ payload["type"] = LLSD(LLUpdaterService::PROGRESS);
+ payload["download_size"] = downloadSize;
+ payload["bytes_downloaded"] = bytesDownloaded;
+ event["payload"] = payload;
+ LLEventPumps::instance().obtain("mainlooprepeater").post(event);
+
+ LL_INFOS("UpdateDownload") << "progress event " << payload << LL_ENDL;
+ } else {
+ ; // Keep events to a reasonalbe number.
+ }
+
+ return 0;
+}
+
+
void LLUpdateDownloader::Implementation::run(void)
{
CURLcode code = curl_easy_perform(mCurl);
@@ -343,6 +424,14 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u
}
throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HTTPGET, true));
throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_URL, url.c_str()));
+ throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_PROGRESSFUNCTION, &progress_callback));
+ throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_PROGRESSDATA, this));
+ throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_NOPROGRESS, false));
+ // if it's a required update set the bandwidth limit to 0 (unlimited)
+ curl_off_t limit = mDownloadData["required"].asBoolean() ? 0 : mBandwidthLimit;
+ throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_MAX_RECV_SPEED_LARGE, limit));
+
+ mDownloadPercent = 0;
}
diff --git a/indra/viewer_components/updater/llupdatedownloader.h b/indra/viewer_components/updater/llupdatedownloader.h
index 1b3d7480fd..0d635640cf 100644
--- a/indra/viewer_components/updater/llupdatedownloader.h
+++ b/indra/viewer_components/updater/llupdatedownloader.h
@@ -52,7 +52,10 @@ public:
void cancel(void);
// Start a new download.
- void download(LLURI const & uri, std::string const & hash);
+ void download(LLURI const & uri,
+ std::string const & hash,
+ std::string const & updateVersion,
+ bool required=false);
// Returns true if a download is in progress.
bool isDownloading(void);
@@ -60,6 +63,9 @@ public:
// Resume a partial download.
void resume(void);
+ // Set a limit on the dowload rate.
+ void setBandwidthLimit(U64 bytesPerSecond);
+
private:
boost::shared_ptr<Implementation> mImplementation;
};
@@ -76,6 +82,7 @@ public:
// url - source (remote) location
// hash - the md5 sum that should match the installer file.
// path - destination (local) location
+ // required - boolean indicating if this is a required update.
// size - the size of the installer in bytes
virtual void downloadComplete(LLSD const & data) = 0;
diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp
index 6e69bcf28b..d450c068ad 100644
--- a/indra/viewer_components/updater/llupdateinstaller.cpp
+++ b/indra/viewer_components/updater/llupdateinstaller.cpp
@@ -31,6 +31,12 @@
#include "lldir.h"
+#if defined(LL_WINDOWS)
+#pragma warning(disable: 4702) // disable 'unreachable code' so we can use lexical_cast (really!).
+#endif
+#include <boost/lexical_cast.hpp>
+
+
namespace {
class RelocateError {};
@@ -47,7 +53,10 @@ namespace {
}
-int ll_install_update(std::string const & script, std::string const & updatePath, LLInstallScriptMode mode)
+int ll_install_update(std::string const & script,
+ std::string const & updatePath,
+ bool required,
+ LLInstallScriptMode mode)
{
std::string actualScriptPath;
switch(mode) {
@@ -73,6 +82,7 @@ int ll_install_update(std::string const & script, std::string const & updatePath
launcher.setExecutable(actualScriptPath);
launcher.addArgument(updatePath);
launcher.addArgument(ll_install_failed_marker_path().c_str());
+ launcher.addArgument(boost::lexical_cast<std::string>(required));
int result = launcher.launch();
launcher.orphan();
diff --git a/indra/viewer_components/updater/llupdateinstaller.h b/indra/viewer_components/updater/llupdateinstaller.h
index 6ce08ce6fa..fe5b1d19b5 100644
--- a/indra/viewer_components/updater/llupdateinstaller.h
+++ b/indra/viewer_components/updater/llupdateinstaller.h
@@ -42,9 +42,10 @@ enum LLInstallScriptMode {
// that the current application terminate once this function is called.
//
int ll_install_update(
- std::string const & script, // Script to execute.
- std::string const & updatePath, // Path to update file.
- LLInstallScriptMode mode=LL_COPY_INSTALL_SCRIPT_TO_TEMP); // Run in place or copy to temp?
+ std::string const & script, // Script to execute.
+ std::string const & updatePath, // Path to update file.
+ bool required, // Is the update required.
+ LLInstallScriptMode mode=LL_COPY_INSTALL_SCRIPT_TO_TEMP); // Run in place or copy to temp?
//
diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp
index cc60eaead2..aa4983a3b6 100644
--- a/indra/viewer_components/updater/llupdaterservice.cpp
+++ b/indra/viewer_components/updater/llupdaterservice.cpp
@@ -25,10 +25,11 @@
#include "linden_common.h"
+#include "llupdaterservice.h"
+
#include "llupdatedownloader.h"
#include "llevents.h"
#include "lltimer.h"
-#include "llupdaterservice.h"
#include "llupdatechecker.h"
#include "llupdateinstaller.h"
#include "llversionviewer.h"
@@ -98,6 +99,8 @@ class LLUpdaterServiceImpl :
LLUpdaterService::app_exit_callback_t mAppExitCallback;
+ LLUpdaterService::eUpdaterState mState;
+
LOG_CLASS(LLUpdaterServiceImpl);
public:
@@ -111,12 +114,15 @@ public:
const std::string& version);
void setCheckPeriod(unsigned int seconds);
+ void setBandwidthLimit(U64 bytesPerSecond);
void startChecking(bool install_if_ready);
void stopChecking();
bool isChecking();
+ LLUpdaterService::eUpdaterState getState();
void setAppExitCallback(LLUpdaterService::app_exit_callback_t aecb) { mAppExitCallback = aecb;}
+ std::string updatedVersion(void);
bool checkForInstall(bool launchInstaller); // Test if a local install is ready.
bool checkForResume(); // Test for resumeable d/l.
@@ -138,7 +144,10 @@ public:
bool onMainLoop(LLSD const & event);
private:
+ std::string mNewVersion;
+
void restartTimer(unsigned int seconds);
+ void setState(LLUpdaterService::eUpdaterState state);
void stopTimer();
};
@@ -149,7 +158,8 @@ LLUpdaterServiceImpl::LLUpdaterServiceImpl() :
mIsDownloading(false),
mCheckPeriod(0),
mUpdateChecker(*this),
- mUpdateDownloader(*this)
+ mUpdateDownloader(*this),
+ mState(LLUpdaterService::INITIAL)
{
}
@@ -183,6 +193,11 @@ void LLUpdaterServiceImpl::setCheckPeriod(unsigned int seconds)
mCheckPeriod = seconds;
}
+void LLUpdaterServiceImpl::setBandwidthLimit(U64 bytesPerSecond)
+{
+ mUpdateDownloader.setBandwidthLimit(bytesPerSecond);
+}
+
void LLUpdaterServiceImpl::startChecking(bool install_if_ready)
{
if(mUrl.empty() || mChannel.empty() || mVersion.empty())
@@ -201,10 +216,16 @@ void LLUpdaterServiceImpl::startChecking(bool install_if_ready)
if(!mIsDownloading)
{
+ setState(LLUpdaterService::CHECKING_FOR_UPDATE);
+
// Checking can only occur during the mainloop.
// reset the timer to 0 so that the next mainloop event
// triggers a check;
restartTimer(0);
+ }
+ else
+ {
+ setState(LLUpdaterService::DOWNLOADING);
}
}
}
@@ -222,6 +243,8 @@ void LLUpdaterServiceImpl::stopChecking()
mUpdateDownloader.cancel();
mIsDownloading = false;
}
+
+ setState(LLUpdaterService::TERMINAL);
}
bool LLUpdaterServiceImpl::isChecking()
@@ -229,6 +252,16 @@ bool LLUpdaterServiceImpl::isChecking()
return mIsChecking;
}
+LLUpdaterService::eUpdaterState LLUpdaterServiceImpl::getState()
+{
+ return mState;
+}
+
+std::string LLUpdaterServiceImpl::updatedVersion(void)
+{
+ return mNewVersion;
+}
+
bool LLUpdaterServiceImpl::checkForInstall(bool launchInstaller)
{
bool foundInstall = false; // return true if install is found.
@@ -266,10 +299,13 @@ bool LLUpdaterServiceImpl::checkForInstall(bool launchInstaller)
{
if(launchInstaller)
{
+ setState(LLUpdaterService::INSTALLING);
+
LLFile::remove(update_marker_path());
int result = ll_install_update(install_script_path(),
update_info["path"].asString(),
+ update_info["required"].asBoolean(),
install_script_mode());
if((result == 0) && mAppExitCallback)
@@ -304,6 +340,7 @@ bool LLUpdaterServiceImpl::checkForResume()
if(download_info["current_version"].asString() == ll_get_version())
{
mIsDownloading = true;
+ mNewVersion = download_info["update_version"].asString();
mUpdateDownloader.resume();
result = true;
}
@@ -333,8 +370,11 @@ void LLUpdaterServiceImpl::optionalUpdate(std::string const & newVersion,
std::string const & hash)
{
stopTimer();
+ mNewVersion = newVersion;
mIsDownloading = true;
- mUpdateDownloader.download(uri, hash);
+ mUpdateDownloader.download(uri, hash, newVersion, false);
+
+ setState(LLUpdaterService::DOWNLOADING);
}
void LLUpdaterServiceImpl::requiredUpdate(std::string const & newVersion,
@@ -342,8 +382,11 @@ void LLUpdaterServiceImpl::requiredUpdate(std::string const & newVersion,
std::string const & hash)
{
stopTimer();
+ mNewVersion = newVersion;
mIsDownloading = true;
- mUpdateDownloader.download(uri, hash);
+ mUpdateDownloader.download(uri, hash, newVersion, true);
+
+ setState(LLUpdaterService::DOWNLOADING);
}
void LLUpdaterServiceImpl::upToDate(void)
@@ -352,6 +395,8 @@ void LLUpdaterServiceImpl::upToDate(void)
{
restartTimer(mCheckPeriod);
}
+
+ setState(LLUpdaterService::UP_TO_DATE);
}
void LLUpdaterServiceImpl::downloadComplete(LLSD const & data)
@@ -367,8 +412,12 @@ void LLUpdaterServiceImpl::downloadComplete(LLSD const & data)
event["pump"] = LLUpdaterService::pumpName();
LLSD payload;
payload["type"] = LLSD(LLUpdaterService::DOWNLOAD_COMPLETE);
+ payload["required"] = data["required"];
+ payload["version"] = mNewVersion;
event["payload"] = payload;
LLEventPumps::instance().obtain("mainlooprepeater").post(event);
+
+ setState(LLUpdaterService::TERMINAL);
}
void LLUpdaterServiceImpl::downloadError(std::string const & message)
@@ -390,6 +439,8 @@ void LLUpdaterServiceImpl::downloadError(std::string const & message)
payload["message"] = message;
event["payload"] = payload;
LLEventPumps::instance().obtain("mainlooprepeater").post(event);
+
+ setState(LLUpdaterService::FAILURE);
}
void LLUpdaterServiceImpl::restartTimer(unsigned int seconds)
@@ -402,6 +453,28 @@ void LLUpdaterServiceImpl::restartTimer(unsigned int seconds)
sListenerName, boost::bind(&LLUpdaterServiceImpl::onMainLoop, this, _1));
}
+void LLUpdaterServiceImpl::setState(LLUpdaterService::eUpdaterState state)
+{
+ if(state != mState)
+ {
+ mState = state;
+
+ LLSD event;
+ event["pump"] = LLUpdaterService::pumpName();
+ LLSD payload;
+ payload["type"] = LLSD(LLUpdaterService::STATE_CHANGE);
+ payload["state"] = state;
+ event["payload"] = payload;
+ LLEventPumps::instance().obtain("mainlooprepeater").post(event);
+
+ LL_INFOS("UpdaterService") << "setting state to " << state << LL_ENDL;
+ }
+ else
+ {
+ ; // State unchanged; noop.
+ }
+}
+
void LLUpdaterServiceImpl::stopTimer()
{
mTimer.stop();
@@ -417,6 +490,12 @@ bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event)
// Check for failed install.
if(LLFile::isfile(ll_install_failed_marker_path()))
{
+ int requiredValue = 0;
+ {
+ llifstream stream(ll_install_failed_marker_path());
+ stream >> requiredValue;
+ if(stream.fail()) requiredValue = 0;
+ }
// TODO: notify the user.
llinfos << "found marker " << ll_install_failed_marker_path() << llendl;
llinfos << "last install attempt failed" << llendl;
@@ -424,11 +503,15 @@ bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event)
LLSD event;
event["type"] = LLSD(LLUpdaterService::INSTALL_ERROR);
+ event["required"] = LLSD(requiredValue);
LLEventPumps::instance().obtain(LLUpdaterService::pumpName()).post(event);
+
+ setState(LLUpdaterService::TERMINAL);
}
else
{
mUpdateChecker.check(mProtocolVersion, mUrl, mPath, mChannel, mVersion);
+ setState(LLUpdaterService::CHECKING_FOR_UPDATE);
}
}
else
@@ -449,6 +532,11 @@ std::string const & LLUpdaterService::pumpName(void)
return name;
}
+bool LLUpdaterService::updateReadyToInstall(void)
+{
+ return LLFile::isfile(update_marker_path());
+}
+
LLUpdaterService::LLUpdaterService()
{
if(gUpdater.expired())
@@ -480,6 +568,11 @@ void LLUpdaterService::setCheckPeriod(unsigned int seconds)
{
mImpl->setCheckPeriod(seconds);
}
+
+void LLUpdaterService::setBandwidthLimit(U64 bytesPerSecond)
+{
+ mImpl->setBandwidthLimit(bytesPerSecond);
+}
void LLUpdaterService::startChecking(bool install_if_ready)
{
@@ -496,11 +589,21 @@ bool LLUpdaterService::isChecking()
return mImpl->isChecking();
}
+LLUpdaterService::eUpdaterState LLUpdaterService::getState()
+{
+ return mImpl->getState();
+}
+
void LLUpdaterService::setImplAppExitCallback(LLUpdaterService::app_exit_callback_t aecb)
{
return mImpl->setAppExitCallback(aecb);
}
+std::string LLUpdaterService::updatedVersion(void)
+{
+ return mImpl->updatedVersion();
+}
+
std::string const & ll_get_version(void) {
static std::string version("");
diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h
index 752a6f834b..421481bc43 100644
--- a/indra/viewer_components/updater/llupdaterservice.h
+++ b/indra/viewer_components/updater/llupdaterservice.h
@@ -43,12 +43,27 @@ public:
// Name of the event pump through which update events will be delivered.
static std::string const & pumpName(void);
+ // Returns true if an update has been completely downloaded and is now ready to install.
+ static bool updateReadyToInstall(void);
+
// Type codes for events posted by this service. Stored the event's 'type' element.
- enum eUpdateEvent {
+ enum eUpdaterEvent {
INVALID,
DOWNLOAD_COMPLETE,
DOWNLOAD_ERROR,
- INSTALL_ERROR
+ INSTALL_ERROR,
+ PROGRESS,
+ STATE_CHANGE
+ };
+
+ enum eUpdaterState {
+ INITIAL,
+ CHECKING_FOR_UPDATE,
+ DOWNLOADING,
+ INSTALLING,
+ UP_TO_DATE,
+ TERMINAL,
+ FAILURE
};
LLUpdaterService();
@@ -61,10 +76,12 @@ public:
const std::string& version);
void setCheckPeriod(unsigned int seconds);
+ void setBandwidthLimit(U64 bytesPerSecond);
void startChecking(bool install_if_ready = false);
void stopChecking();
bool isChecking();
+ eUpdaterState getState();
typedef boost::function<void (void)> app_exit_callback_t;
template <typename F>
@@ -73,6 +90,11 @@ public:
app_exit_callback_t aecb = callable;
setImplAppExitCallback(aecb);
}
+
+ // If an update is or has been downloaded, this method will return the
+ // version string for that update. An empty string will be returned
+ // otherwise.
+ std::string updatedVersion(void);
private:
boost::shared_ptr<LLUpdaterServiceImpl> mImpl;
diff --git a/indra/viewer_components/updater/scripts/darwin/update_install b/indra/viewer_components/updater/scripts/darwin/update_install
index 9df382f119..6a95f96d86 100644
--- a/indra/viewer_components/updater/scripts/darwin/update_install
+++ b/indra/viewer_components/updater/scripts/darwin/update_install
@@ -6,5 +6,5 @@
#
cd "$(dirname "$0")"
-../Resources/mac-updater.app/Contents/MacOS/mac-updater -dmg "$1" -name "Second Life Viewer 2" -marker "$2" &
+(../Resources/mac-updater.app/Contents/MacOS/mac-updater -dmg "$1" -name "Second Life Viewer 2"; if [ $? -ne 0 ]; then echo $3 >> "$2"; fi;) &
exit 0
diff --git a/indra/viewer_components/updater/scripts/linux/update_install b/indra/viewer_components/updater/scripts/linux/update_install
index a271926e25..88451340ec 100644
--- a/indra/viewer_components/updater/scripts/linux/update_install
+++ b/indra/viewer_components/updater/scripts/linux/update_install
@@ -4,7 +4,7 @@ export LD_LIBRARY_PATH="$INSTALL_DIR/lib"
bin/linux-updater.bin --file "$1" --dest "$INSTALL_DIR" --name "Second Life Viewer 2" --stringsdir "$INSTALL_DIR/skins/default/xui/en" --stringsfile "strings.xml"
if [ $? -ne 0 ]
- then touch "$2"
+ then echo $3 >> "$2"
fi
rm -f "$1"
diff --git a/indra/viewer_components/updater/scripts/windows/update_install.bat b/indra/viewer_components/updater/scripts/windows/update_install.bat
index 42e148a707..96687226a8 100644
--- a/indra/viewer_components/updater/scripts/windows/update_install.bat
+++ b/indra/viewer_components/updater/scripts/windows/update_install.bat
@@ -1,3 +1,3 @@
start /WAIT %1 /SKIP_DIALOGS
-IF ERRORLEVEL 1 ECHO %ERRORLEVEL% > %2
+IF ERRORLEVEL 1 ECHO %3 > %2
DEL %1
diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
index 04ed4e6364..5f8cd28f29 100644
--- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
+++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
@@ -48,7 +48,7 @@ void LLUpdateChecker::check(std::string const & protocolVersion, std::string con
std::string const & servicePath, std::string channel, std::string version)
{}
LLUpdateDownloader::LLUpdateDownloader(Client & ) {}
-void LLUpdateDownloader::download(LLURI const & , std::string const &){}
+void LLUpdateDownloader::download(LLURI const & , std::string const &, std::string const &, bool){}
class LLDir_Mock : public LLDir
{
@@ -101,8 +101,9 @@ std::string LLUpdateDownloader::downloadMarkerPath(void)
void LLUpdateDownloader::resume(void) {}
void LLUpdateDownloader::cancel(void) {}
+void LLUpdateDownloader::setBandwidthLimit(U64 bytesPerSecond) {}
-int ll_install_update(std::string const &, std::string const &, LLInstallScriptMode)
+int ll_install_update(std::string const &, std::string const &, bool, LLInstallScriptMode)
{
return 0;
}
diff --git a/install.xml b/install.xml
index 36e7824e1c..13abaac1c1 100644
--- a/install.xml
+++ b/install.xml
@@ -981,9 +981,9 @@ anguage Infrstructure (CLI) international standard</string>
<key>darwin</key>
<map>
<key>md5sum</key>
- <string>34d9e4c93678a422cf80521bf0cd7628</string>
+ <string>66c46841825ab4969ec875b5c8f9b24c</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-4.6-darwin-20100914.tar.bz2</uri>
+ <uri>http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-darwin-qt4.7.1-20101221.tar.bz2</uri>
</map>
<key>linux</key>
<map>
@@ -995,9 +995,9 @@ anguage Infrstructure (CLI) international standard</string>
<key>windows</key>
<map>
<key>md5sum</key>
- <string>4b8412833c00f8cdaba26808f0ddb404</string>
+ <string>b678c4d18ea8e4fab42b20f8d0b2629a</string>
<key>url</key>
- <uri>http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.6-20100916.tar.bz2</uri>
+ <uri>http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.7.1-20101221.tar.bz2</uri>
</map>
</map>
</map>
diff --git a/scripts/install.py b/scripts/install.py
index c2adf4d0a2..d3bdf52283 100755
--- a/scripts/install.py
+++ b/scripts/install.py
@@ -486,7 +486,7 @@ windows/i686/vs/2003 -- specify a windows visual studio 2003 package"""
for filename in remove_file_list:
print "rm",filename
if not self._dryrun:
- if os.path.exists(filename):
+ if os.path.lexists(filename):
remove_dir_set.add(os.path.dirname(filename))
try:
os.remove(filename)