diff --git a/autobuild.xml b/autobuild.xml index 31d81cd87..f5f17ea95 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -389,6 +389,54 @@ version 2.3 + crashpad + + canonical_repo + https://git.alchemyviewer.org/alchemy/thirdparty/3p-crashpad + copyright + Copyright 2014 The Crashpad Authors. All rights reserved. + description + Crashpad is a crash-reporting system. + license + Apache 2.0 + license_file + LICENSES/crashpad.txt + name + crashpad + platforms + + windows + + archive + + hash + 849f515d4d77162c15614ebff8599c13 + hash_algorithm + md5 + url + https://pkg.alchemyviewer.org/repository/autobuild-external/crashpad/windows/crashpad-365c520b.6-windows-6.tar.bz2 + + name + windows + + windows64 + + archive + + hash + 7ea820b6a2cfa172f47d673c07dfa62c + hash_algorithm + md5 + url + https://pkg.alchemyviewer.org/repository/autobuild-external/crashpad/windows64/crashpad-365c520b.6-windows64-6.tar.bz2 + + name + windows64 + + + version + 365c520b.6 + curl copyright @@ -865,51 +913,7 @@ version - 1.10.10.190360453 - - fontconfig - - copyright - Copyright (C) 2000,2001,2002,2003,2004,2006,2007 Keith Packard, 2005 Patrick Lam, 2009 Roozbeh Pournader, 2008,2009 Red Hat, Inc., 2008 Danilo Šegan, 2012 Google, Inc. - description - Fontconfig is a library for configuring and customizing font access. - license - bsd - license_file - LICENSES/fontconfig.txt - name - fontconfig - platforms - - linux - - archive - - hash - 2843c48e6c84a51e3d6aa05dace4c8c0 - url - http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3pl_3p-fontconfig-update/rev/290569/arch/Linux/installer/fontconfig-2.11.0-linux-20140602.tar.bz2 - - name - linux - - linux64 - - archive - - hash - 25726244f5bcd05f412514b030098c3c - hash_algorithm - md5 - url - http://depot.alchemyviewer.org/pub/linux64/lib-trusty/fontconfig-2.11.0-linux64-201603241804.tar.bz2 - - name - linux64 - - - version - 2.11.0 + 2.00.03.192211300 fonts @@ -1017,32 +1021,6 @@ name darwin - linux - - archive - - hash - 52f87a65cc61ec4b05721c079d015b19 - url - http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3pl_3p-freetype-update/rev/290557/arch/Linux/installer/freetype-2.4.4-linux-20140602.tar.bz2 - - name - linux - - linux64 - - archive - - hash - b10ba0775b9f1033daf580a2cb55789d - hash_algorithm - md5 - url - http://depot.alchemyviewer.org/pub/linux64/lib-trusty/freetype-2.6.3-linux64-201603241755.tar.bz2 - - name - linux64 - windows archive @@ -1237,104 +1215,6 @@ version 1.0pre3.190390340 - google_breakpad - - copyright - Copyright (c) 2006, Google Inc. - description - Breakpad is a crossplatform library for capturing crash callstacks and runtime data. - license - bsd - license_file - LICENSES/google_breakpad.txt - name - google_breakpad - platforms - - darwin - - archive - - hash - 9f963eb1728e6d5077d4feba805d4896 - hash_algorithm - md5 - url - https://bitbucket.org/alchemyviewer/publiclibs-darwin/downloads/google_breakpad-9e60a27-darwin-201511222009.tar.bz2 - - name - darwin - - darwin64 - - archive - - hash - 2d43c6a149cd9c89ba19e884579b1e25 - url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1836/4096/google_breakpad-1413.501824-darwin64-501824.tar.bz2 - - name - darwin64 - - linux - - archive - - hash - 52257e5eb166a0b69c9c0c38f6e1920e - url - http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-breakpad/rev/273079/arch/Linux/installer/google_breakpad-0.0.0-rev1099-linux-20130329.tar.bz2 - - name - linux - - linux64 - - archive - - hash - 3709a51d4d5dff5ec0c4656623eaa05d - hash_algorithm - md5 - url - http://depot.alchemyviewer.org/pub/linux64/lib-trusty/google_breakpad-9e60a27-linux64-201603240004.tar.bz2 - - name - linux64 - - windows - - archive - - hash - fa7f683ba4ddd7db777c78c8213d2e46 - hash_algorithm - md5 - url - https://depot.alchemyviewer.org/pub/windows/lib-vc141/google_breakpad-7398ce15b79da-windows-201703090621.tar.bz2 - - name - windows - - windows64 - - archive - - hash - 71ffc5cae4da7e2e7aac856da44cb8c4 - hash_algorithm - md5 - url - https://depot.alchemyviewer.org/pub/windows64/lib-vc141/google_breakpad-7398ce15b79da-windows64-201703081616.tar.bz2 - - name - windows64 - - - version - 9e60a27 - gperftools copyright @@ -2995,10 +2875,10 @@ build command - make + ninja options - -j 7 + -v configure @@ -3006,7 +2886,7 @@ options -G - Unix Makefiles + Ninja default @@ -3019,10 +2899,10 @@ build command - make + ninja options - -j 7 + -v configure @@ -3030,7 +2910,7 @@ options -G - Unix Makefiles + Ninja name @@ -3051,10 +2931,10 @@ build command - make + ninja options - -j 7 + -v configure @@ -3062,7 +2942,7 @@ options -G - Unix Makefiles + Ninja -DWORD_SIZE:STRING=64 @@ -3076,10 +2956,10 @@ build command - make + ninja options - -j 7 + -v configure @@ -3087,7 +2967,7 @@ options -G - Unix Makefiles + Ninja -DWORD_SIZE:STRING=64 diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 32be5e4b4..6dddeed57 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -5,6 +5,7 @@ if(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) set(${CMAKE_CURRENT_LIST_FILE}_INCLUDED "YES") +include(CheckCCompilerFlag) include(Variables) # Portable compilation flags. @@ -17,19 +18,6 @@ set(CMAKE_C_FLAGS_RELEASE set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-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") - -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) @@ -55,6 +43,14 @@ if (WINDOWS) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LARGEADDRESSAWARE") endif (WORD_SIZE EQUAL 32) + if (FULL_DEBUG_SYMS OR USE_CRASHPAD) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DEBUG:FULL") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG:FULL") + else () + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DEBUG:FASTLINK") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG:FASTLINK") + endif () + if (USE_LTO) if(INCREMENTAL_LINK) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LTCG:INCREMENTAL") @@ -199,10 +195,13 @@ if (LINUX) # End of hacks. - if (NOT STANDALONE) - # this stops us requiring a really recent glibc at runtime - add_definitions(-fno-stack-protector) - endif (NOT STANDALONE) + CHECK_C_COMPILER_FLAG(-fstack-protector-strong HAS_STRONG_STACK_PROTECTOR) + if (${CMAKE_BUILD_TYPE} STREQUAL "Release") + if(HAS_STRONG_STACK_PROTECTOR) + add_compile_options(-fstack-protector-strong) + endif(HAS_STRONG_STACK_PROTECTOR) + endif (${CMAKE_BUILD_TYPE} STREQUAL "Release") + if (${ARCH} STREQUAL "x86_64") add_definitions(-pipe) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ffast-math") @@ -306,6 +305,13 @@ endif (LINUX OR DARWIN) if (STANDALONE) add_definitions(-DLL_STANDALONE=1) else (STANDALONE) + #Enforce compile-time correctness for fmt strings + add_definitions(-DFMT_STRING_ALIAS=1) + + if(USE_CRASHPAD) + add_definitions(-DUSE_CRASHPAD=1 -DCRASHPAD_URL="${CRASHPAD_URL}") + endif() + set(${ARCH}_linux_INCLUDES atk-1.0 cairo diff --git a/indra/cmake/BuildPackagesInfo.cmake b/indra/cmake/BuildPackagesInfo.cmake index 64a353ba2..26088fcaf 100644 --- a/indra/cmake/BuildPackagesInfo.cmake +++ b/indra/cmake/BuildPackagesInfo.cmake @@ -9,7 +9,7 @@ include(Variables) # building in an IDE, it probably isn't. Set it explicitly using # run_build_test.py. add_custom_command(OUTPUT packages-info.txt - COMMENT Generating packages-info.txt for the about box + COMMENT "Generating packages-info.txt for the about box" MAIN_DEPENDENCY ${CMAKE_SOURCE_DIR}/../autobuild.xml DEPENDS ${CMAKE_SOURCE_DIR}/../scripts/packages-formatter.py ${CMAKE_SOURCE_DIR}/../autobuild.xml diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 0431ff6bb..8202868a1 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -22,6 +22,7 @@ set(cmake_SOURCE_FILES ConfigurePkgConfig.cmake CURL.cmake Copy3rdPartyLibs.cmake + CrashPad.cmake Cwdebug.cmake DBusGlib.cmake DeploySharedLibs.cmake @@ -32,7 +33,6 @@ set(cmake_SOURCE_FILES FindCARes.cmake FindColladadom.cmake FindGLOD.cmake - FindGoogleBreakpad.cmake FindGooglePerfTools.cmake FindHunSpell.cmake FindNDOF.cmake @@ -47,7 +47,6 @@ set(cmake_SOURCE_FILES GStreamer010Plugin.cmake Glui.cmake Glut.cmake - GoogleBreakpad.cmake GooglePerfTools.cmake Hunspell.cmake JPEG.cmake diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index b9d12919b..abe2a6f2a 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -86,6 +86,11 @@ if(WINDOWS) set(release_files ${release_files} libtcmalloc_minimal.dll) endif(NOT DISABLE_TCMALLOC) + if(OPENAL) + set(debug_files ${debug_files} alut.dll OpenAL32.dll) + set(release_files ${release_files} alut.dll OpenAL32.dll) + endif(OPENAL) + if (FMODSTUDIO) set(debug_files ${debug_files} fmodL.dll) set(release_files ${release_files} fmod.dll) @@ -179,16 +184,10 @@ elseif(LINUX) libatk-1.0.so libexpat.so libexpat.so.1 - libfreetype.so.6.12.3 - libfreetype.so.6 - libfreetype.so libGLOD.so libgmodule-2.0.so libgobject-2.0.so libopenal.so - libfontconfig.so.1.8.0 - libfontconfig.so.1 - libfontconfig.so ) if (USE_TCMALLOC) diff --git a/indra/cmake/CrashPad.cmake b/indra/cmake/CrashPad.cmake new file mode 100644 index 000000000..d3f4ed6b7 --- /dev/null +++ b/indra/cmake/CrashPad.cmake @@ -0,0 +1,22 @@ +# -*- cmake -*- +include(Prebuilt) +include(Variables) + +if(USE_CRASHPAD) + +if (USESYSTEMLIBS) +else (USESYSTEMLIBS) + use_prebuilt_binary(crashpad) + if (WINDOWS) + set(CRASHPAD_LIBRARIES + debug client.lib util.lib base.lib + optimized client.lib util.lib base.lib) + elseif (LINUX) + + else (DARWIN) + + endif () + set(CRASHPAD_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/crashpad) +endif (USESYSTEMLIBS) + +endif() diff --git a/indra/cmake/FMODSTUDIO.cmake b/indra/cmake/FMODSTUDIO.cmake index 84de5689e..2f8691c27 100644 --- a/indra/cmake/FMODSTUDIO.cmake +++ b/indra/cmake/FMODSTUDIO.cmake @@ -30,22 +30,21 @@ if (FMODSTUDIO) optimized ${FMOD_LINK_LIBRARY_RELEASE} ) - set(FMOD_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/fmodstudio) + set(FMODSTUDIO_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/fmodstudio) endif(FMODSTUDIO) -if(FMOD_LIBRARY_RELEASE AND FMOD_INCLUDE_DIR) +if(FMOD_LIBRARY_RELEASE AND FMODSTUDIO_INCLUDE_DIR) set(FMOD ON) if (NOT FMOD_LIBRARY_DEBUG) #Use release library in debug configuration if debug library is absent. set(FMOD_LIBRARY_DEBUG ${FMOD_LIBRARY_RELEASE}) endif (NOT FMOD_LIBRARY_DEBUG) -else (FMOD_LIBRARY_RELEASE AND FMOD_INCLUDE_DIR) +else (FMOD_LIBRARY_RELEASE AND FMODSTUDIO_INCLUDE_DIR) message(STATUS "No support for FMOD Studio audio (need to set FMODSTUDIO_SDK_DIR?)") set(FMOD OFF) set(FMODSTUDIO OFF) -endif (FMOD_LIBRARY_RELEASE AND FMOD_INCLUDE_DIR) +endif (FMOD_LIBRARY_RELEASE AND FMODSTUDIO_INCLUDE_DIR) if (FMOD) message(STATUS "Building with FMOD Studio audio support") - set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMODSTUDIO=1") endif (FMOD) diff --git a/indra/cmake/FindGoogleBreakpad.cmake b/indra/cmake/FindGoogleBreakpad.cmake deleted file mode 100644 index 18e0b56ed..000000000 --- a/indra/cmake/FindGoogleBreakpad.cmake +++ /dev/null @@ -1,40 +0,0 @@ -# -*- cmake -*- - -# - Find Google BreakPad -# Find the Google BreakPad includes and library -# This module defines -# BREAKPAD_INCLUDE_DIRECTORIES, where to find the Goole BreakPad includes. -# BREAKPAD_EXCEPTION_HANDLER_LIBRARIES, the libraries needed to use Google BreakPad. -# BREAKPAD_EXCEPTION_HANDLER_FOUND, If false, do not try to use Google BreakPad. -# also defined, but not for general use are -# BREAKPAD_EXCEPTION_HANDLER_LIBRARY, where to find the Google BreakPad library. - -FIND_PATH(BREAKPAD_INCLUDE_DIRECTORIES common/using_std_string.h PATH_SUFFIXES google_breakpad) - -SET(BREAKPAD_EXCEPTION_HANDLER_NAMES ${BREAKPAD_EXCEPTION_HANDLER_NAMES} breakpad_client) -FIND_LIBRARY(BREAKPAD_EXCEPTION_HANDLER_LIBRARY - NAMES ${BREAKPAD_EXCEPTION_HANDLER_NAMES} - ) - -IF (BREAKPAD_EXCEPTION_HANDLER_LIBRARY AND BREAKPAD_INCLUDE_DIRECTORIES) - SET(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES ${BREAKPAD_EXCEPTION_HANDLER_LIBRARY}) - SET(BREAKPAD_EXCEPTION_HANDLER_FOUND "YES") -ELSE (BREAKPAD_EXCEPTION_HANDLER_LIBRARY AND BREAKPAD_INCLUDE_DIRECTORIES) - SET(BREAKPAD_EXCEPTION_HANDLER_FOUND "NO") -ENDIF (BREAKPAD_EXCEPTION_HANDLER_LIBRARY AND BREAKPAD_INCLUDE_DIRECTORIES) - - -IF (BREAKPAD_EXCEPTION_HANDLER_FOUND) - IF (NOT BREAKPAD_EXCEPTION_HANDLER_FIND_QUIETLY) - MESSAGE(STATUS "Found Google BreakPad: ${BREAKPAD_EXCEPTION_HANDLER_LIBRARIES}") - ENDIF (NOT BREAKPAD_EXCEPTION_HANDLER_FIND_QUIETLY) -ELSE (BREAKPAD_EXCEPTION_HANDLER_FOUND) - IF (BREAKPAD_EXCEPTION_HANDLER_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find Google BreakPad library") - ENDIF (BREAKPAD_EXCEPTION_HANDLER_FIND_REQUIRED) -ENDIF (BREAKPAD_EXCEPTION_HANDLER_FOUND) - -MARK_AS_ADVANCED( - BREAKPAD_EXCEPTION_HANDLER_LIBRARY - BREAKPAD_INCLUDE_DIRECTORIES - ) diff --git a/indra/cmake/FreeType.cmake b/indra/cmake/FreeType.cmake index 2d6025f3a..da122419d 100644 --- a/indra/cmake/FreeType.cmake +++ b/indra/cmake/FreeType.cmake @@ -1,14 +1,14 @@ # -*- cmake -*- include(Prebuilt) -if (STANDALONE) +if (LINUX) include(FindPkgConfig) pkg_check_modules(FREETYPE REQUIRED freetype2) -else (STANDALONE) +else (LINUX) use_prebuilt_binary(freetype) set(FREETYPE_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/freetype2) set(FREETYPE_LIBRARIES freetype) -endif (STANDALONE) +endif (LINUX) link_directories(${FREETYPE_LIBRARY_DIRS}) diff --git a/indra/cmake/GeneratePrecompiledHeader.cmake b/indra/cmake/GeneratePrecompiledHeader.cmake index 9ff2062ed..67929d3a3 100644 --- a/indra/cmake/GeneratePrecompiledHeader.cmake +++ b/indra/cmake/GeneratePrecompiledHeader.cmake @@ -94,7 +94,7 @@ macro(target_precompiled_header TARGET_NAME PRECOMPILED_HEADER PRECOMPILED_SOURC # Add a custom target for building the precompiled header. add_custom_command( OUTPUT ${OUTPUT_NAME} - COMMAND ${CMAKE_CXX_COMPILER} @${PCH_FLAGS_FILE} ${COMPILER_FLAGS} -x c++-header -std=${CXX_STD} -o ${OUTPUT_NAME} ${PRECOMPILED_HEADER} + COMMAND ${CMAKE_CXX_COMPILER} @${PCH_FLAGS_FILE} ${COMPILER_FLAGS} -x c++-header -o ${OUTPUT_NAME} ${PRECOMPILED_HEADER} DEPENDS ${PRECOMPILED_HEADER}) add_custom_target(${TARGET_NAME}_gch DEPENDS ${OUTPUT_NAME}) add_dependencies(${TARGET_NAME} ${TARGET_NAME}_gch) diff --git a/indra/cmake/GoogleBreakpad.cmake b/indra/cmake/GoogleBreakpad.cmake deleted file mode 100644 index de899a462..000000000 --- a/indra/cmake/GoogleBreakpad.cmake +++ /dev/null @@ -1,26 +0,0 @@ -# -*- cmake -*- -include(Prebuilt) - -if (STANDALONE) - set(BREAKPAD_EXCEPTION_HANDLER_FIND_REQUIRED ON) - include(FindGoogleBreakpad) -else (STANDALONE) - use_prebuilt_binary(google_breakpad) - if (DARWIN) - set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler) - endif (DARWIN) - if (LINUX) - set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES breakpad_client) - endif (LINUX) - if (WINDOWS) - set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler crash_generation_client crash_generation_server common) - endif (WINDOWS) - # yes, this does look dumb, no, it's not incorrect - # I think it's incorrect: the second one should go --Aleric - set(BREAKPAD_INCLUDE_DIRECTORIES - ${LIBS_PREBUILT_DIR}/include/google_breakpad - ${LIBS_PREBUILT_LEGACY_DIR}/include/google_breakpad - ${LIBS_PREBUILT_DIR}/include/google_breakpad/google_breakpad - ${LIBS_PREBUILT_LEGACY_DIR}/include/google_breakpad/google_breakpad - ) -endif (STANDALONE) diff --git a/indra/cmake/Linking.cmake b/indra/cmake/Linking.cmake index 2a8bf40dd..38ae03a61 100644 --- a/indra/cmake/Linking.cmake +++ b/indra/cmake/Linking.cmake @@ -48,10 +48,14 @@ link_directories(${AUTOBUILD_LIBS_INSTALL_DIRS}) if (LINUX) set(DL_LIBRARY dl) + set(RT_LIBRARY rt) set(PTHREAD_LIBRARY pthread) + set(FMT_LIBRARY "") else (LINUX) set(DL_LIBRARY "") + set(RT_LIBRARY "") set(PTHREAD_LIBRARY "") + set(FMT_LIBRARY fmt::fmt) endif (LINUX) if (WINDOWS) @@ -73,6 +77,6 @@ else (WINDOWS) set(WINDOWS_LIBRARIES "") endif (WINDOWS) -mark_as_advanced(DL_LIBRARY PTHREAD_LIBRARY WINDOWS_LIBRARIES) +mark_as_advanced(DL_LIBRARY RT_LIBRARY PTHREAD_LIBRARY FMT_LIBRARY WINDOWS_LIBRARIES) endif(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) diff --git a/indra/cmake/OPENAL.cmake b/indra/cmake/OPENAL.cmake index 7f98cbbc4..c25eb929e 100644 --- a/indra/cmake/OPENAL.cmake +++ b/indra/cmake/OPENAL.cmake @@ -2,7 +2,6 @@ include(Linking) include(Prebuilt) -if(NOT FMOD) if (LINUX) set(OPENAL ON CACHE BOOL "Enable OpenAL") else (LINUX) @@ -10,6 +9,7 @@ else (LINUX) endif (LINUX) if (OPENAL) + set(OPENAL_LIB_INCLUDE_DIRS "${LIBS_PREBUILT_DIR}/include/AL") if (STANDALONE) include(FindPkgConfig) include(FindOpenAL) @@ -18,15 +18,16 @@ if (OPENAL) else (STANDALONE) use_prebuilt_binary(openal) endif (STANDALONE) + if(WINDOWS) set(OPENAL_LIBRARIES - openal + OpenAL32 alut ) - set(OPENAL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) -endif (OPENAL) - -if (OPENAL) + else() + set(OPENAL_LIBRARIES + openal + alut + ) + endif() message(STATUS "Building with OpenAL audio support") - set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_OPENAL") endif (OPENAL) -endif(NOT FMOD) diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index 189efe536..51e10a09a 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -36,6 +36,11 @@ option(USE_PRECOMPILED_HEADERS "Enable use of precompiled header directives wher option(USE_LTO "Enable Whole Program Optimization and related folding and binary reduction routines" OFF) option(UNATTENDED "Disable use of uneeded tooling for automated builds" OFF) +# Configure crash reporting +option(USE_CRASHPAD "Build support for crashpad reporting engine" OFF) +set(CRASHPAD_URL "" CACHE STRING "Crashpad endpoint url") +set(VIEWER_SYMBOL_FILE "" CACHE STRING "Name of tarball into which to place symbol files") + # Media Plugins option(ENABLE_MEDIA_PLUGINS "Turn off building media plugins if they are imported by third-party library mechanism" ON) option(LIBVLCPLUGIN "Turn off building support for libvlc plugin" ON) diff --git a/indra/cmake/ViewerMiscLibs.cmake b/indra/cmake/ViewerMiscLibs.cmake index 2984f5261..36ee514e9 100644 --- a/indra/cmake/ViewerMiscLibs.cmake +++ b/indra/cmake/ViewerMiscLibs.cmake @@ -3,9 +3,6 @@ include(Prebuilt) if (NOT STANDALONE) use_prebuilt_binary(slvoice) - if(LINUX) - use_prebuilt_binary(fontconfig) - endif(LINUX) else (NOT STANDALONE) # Download there even when using standalone. set(STANDALONE OFF) @@ -16,4 +13,9 @@ else (NOT STANDALONE) set(STANDALONE ON) endif(NOT STANDALONE) +if(LINUX) + include(FindPkgConfig) + pkg_check_modules(FONTCONFIG REQUIRED fontconfig) +endif(LINUX) + use_prebuilt_binary(fonts) diff --git a/indra/deps/CMakeLists.txt b/indra/deps/CMakeLists.txt index 3525203d6..47b676d2c 100644 --- a/indra/deps/CMakeLists.txt +++ b/indra/deps/CMakeLists.txt @@ -39,6 +39,8 @@ if (BUILD_TESTING) endif() #Download the rest of the libraries -#FetchContent_MakeAvailable(fmt) +if(WINDOWS) +FetchContent_MakeAvailable(fmt) +endif() set(CMAKE_FOLDER "") diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp index 5761c3535..31edbc67d 100644 --- a/indra/llappearance/llwearable.cpp +++ b/indra/llappearance/llwearable.cpp @@ -184,7 +184,7 @@ void LLWearable::createLayers(S32 te, LLAvatarAppearance *avatarp) { LLTexLayerSet *layer_set = NULL; const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)te); - if (texture_dict->mIsUsedByBakedTexture) + if (texture_dict && texture_dict->mIsUsedByBakedTexture) { const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; @@ -197,7 +197,7 @@ void LLWearable::createLayers(S32 te, LLAvatarAppearance *avatarp) } else { - LL_ERRS() << "could not find layerset for LTO in wearable!" << LL_ENDL; + LL_WARNS() << "could not find layerset for LTO in wearable!" << LL_ENDL; } } diff --git a/indra/llaudio/CMakeLists.txt b/indra/llaudio/CMakeLists.txt index a200a456e..20456f5dc 100644 --- a/indra/llaudio/CMakeLists.txt +++ b/indra/llaudio/CMakeLists.txt @@ -3,8 +3,6 @@ project(llaudio) include(00-Common) -include(Audio) -include(LLAudio) include(FMODSTUDIO) include(OPENAL) include(LLCommon) @@ -12,10 +10,6 @@ include(LLMath) include(LLMessage) include(LLVFS) -if (FMOD) - include_directories(${FMOD_INCLUDE_DIR}) -endif(FMOD) - include_directories( ${LLAUDIO_INCLUDE_DIRS} ${LLCOMMON_INCLUDE_DIRS} @@ -26,7 +20,7 @@ include_directories( ${VORBISENC_INCLUDE_DIRS} ${VORBISFILE_INCLUDE_DIRS} ${VORBIS_INCLUDE_DIRS} - ${OPENAL_INCLUDE_DIRS} + ${OPENAL_LIB_INCLUDE_DIRS} ${FREEAULT_LIB_INCLUDE_DIRS} ) @@ -50,6 +44,9 @@ set(llaudio_HEADER_FILES ) if (FMODSTUDIO) + include_directories( + ${FMODSTUDIO_INCLUDE_DIR} + ) list(APPEND llaudio_SOURCE_FILES llaudioengine_fmodstudio.cpp lllistener_fmodstudio.cpp diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 6479c7bca..cae62271d 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -13,7 +13,6 @@ include(Boost) include(OpenSSL) include(LLSharedLibs) include(Json) -include(GoogleBreakpad) include(Copy3rdPartyLibs) include(ZLIB) include(URIPARSER) @@ -291,7 +290,6 @@ target_link_libraries( llcommon PUBLIC absl::hash - ${BREAKPAD_EXCEPTION_HANDLER_LIBRARIES} ${APRUTIL_LIBRARIES} ${APR_LIBRARIES} ${EXPAT_LIBRARIES} diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h index 142f47e2a..8fa21bd7e 100644 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h @@ -368,13 +368,6 @@ const U32 MAP_ITEM_CLASSIFIED = 0x08; const U32 MAP_ITEM_ADULT_EVENT = 0x09; const U32 MAP_ITEM_LAND_FOR_SALE_ADULT = 0x0a; -// Crash reporter behavior -const char* const CRASH_SETTINGS_FILE = "settings_crash_behavior.xml"; -const char* const CRASH_BEHAVIOR_SETTING = "CrashSubmitBehavior"; -const S32 CRASH_BEHAVIOR_ASK = 0; -const S32 CRASH_BEHAVIOR_ALWAYS_SEND = 1; -const S32 CRASH_BEHAVIOR_NEVER_SEND = 2; - // Export/Import return values const S32 EXPORT_SUCCESS = 0; const S32 EXPORT_ERROR_PERMISSIONS = -1; diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index b6498ffbf..36c6b0f61 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -25,9 +25,8 @@ */ #include "linden_common.h" -#include "llapp.h" -#include +#include "llapp.h" #ifdef LL_DARWIN #include @@ -45,7 +44,6 @@ #include "llstl.h" // for DeletePointer() #include "llstring.h" #include "lleventtimer.h" -#include "exception_handler.h" // // Signal handling @@ -57,12 +55,6 @@ LONG WINAPI default_windows_exception_handler(struct _EXCEPTION_POINTERS *exception_infop); BOOL ConsoleCtrlHandler(DWORD fdwCtrlType); -bool windows_post_minidump_callback(const wchar_t* dump_path, - const wchar_t* minidump_id, - void* context, - EXCEPTION_POINTERS* exinfo, - MDRawAssertionInfo* assertion, - bool succeeded); #else # include # include // for fork() @@ -70,18 +62,6 @@ bool windows_post_minidump_callback(const wchar_t* dump_path, void setup_signals(); void default_unix_signal_handler(int signum, siginfo_t *info, void *); -#if LL_LINUX -#include "client/linux/handler/minidump_descriptor.h" -static bool unix_minidump_callback(const google_breakpad::MinidumpDescriptor& minidump_desc, - void* context, - bool succeeded); -#else -// Called by breakpad exception handler after the minidump has been generated. -bool unix_post_minidump_callback(const char *dump_dir, - const char *minidump_id, - void *context, bool succeeded); -#endif - # if LL_DARWIN /* OSX doesn't support SIGRT* */ S32 LL_SMACKDOWN_SIGNAL = SIGUSR1; @@ -98,7 +78,7 @@ S32 LL_HEARTBEAT_SIGNAL = (SIGRTMAX >= 0) ? (SIGRTMAX-0) : SIGUSR2; #endif // LL_WINDOWS // the static application instance -LLApp* LLApp::sApplication = NULL; +LLApp* LLApp::sApplication = nullptr; // Allows the generation of core files for post mortem under gdb // and disables crashlogger @@ -110,7 +90,7 @@ BOOL LLApp::sLogInSignal = FALSE; // static LLApp::EAppStatus LLApp::sStatus = LLApp::APP_STATUS_STOPPED; // Keeps track of application status -LLAppErrorHandler LLApp::sErrorHandler = NULL; +LLAppErrorHandler LLApp::sErrorHandler = nullptr; BOOL LLApp::sErrorThreadRunning = FALSE; #if !LL_WINDOWS LLApp::child_map LLApp::sChildMap; @@ -119,13 +99,12 @@ LLAppChildCallback LLApp::sDefaultChildCallback = NULL; #endif -LLApp::LLApp() : mThreadErrorp(NULL) +LLApp::LLApp() + : mThreadErrorp(nullptr) { commonCtor(); } -static void* sCrashLoggerReserve = NULL; - void LLApp::commonCtor() { // Set our status to running @@ -150,34 +129,11 @@ void LLApp::commonCtor() // Set the application to this instance. sApplication = this; - mExceptionHandler = 0; - -#if LL_WINDOWS - sCrashLoggerReserve = VirtualAlloc(NULL, 512*1024, MEM_COMMIT|MEM_RESERVE, PAGE_NOACCESS); -#else - sCrashLoggerReserve = malloc(512*1024); -#endif - // initialize the buffer to write the minidump filename to // (this is used to avoid allocating memory in the crash handler) - memset(mMinidumpPath, 0, MAX_MINDUMP_PATH_LENGTH); mCrashReportPipeStr = L"\\\\.\\pipe\\LLCrashReporterPipe"; } -#if LL_WINDOWS -static bool clear_CrashLoggerReserve_callback(void* context, EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion) -{ - VirtualFree(sCrashLoggerReserve, 0, MEM_RELEASE); - return true; -} -#else -static bool clear_CrashLoggerReserve_callback(void* context) -{ - free(sCrashLoggerReserve); - return true; -} -#endif - LLApp::LLApp(LLErrorThread *error_thread) : mThreadErrorp(error_thread) { @@ -198,11 +154,9 @@ LLApp::~LLApp() if (mThreadErrorp) { delete mThreadErrorp; - mThreadErrorp = NULL; + mThreadErrorp = nullptr; } - if(mExceptionHandler != 0) delete mExceptionHandler; - LLCommon::cleanupClass(); } @@ -216,8 +170,8 @@ LLApp* LLApp::instance() LLSD LLApp::getOption(const std::string& name) const { LLSD rv; - LLSD::array_const_iterator iter = mOptions.beginArray(); - LLSD::array_const_iterator end = mOptions.endArray(); + auto iter = mOptions.beginArray(); + auto end = mOptions.endArray(); for(; iter != end; ++iter) { rv = (*iter)[name]; @@ -264,9 +218,9 @@ bool LLApp::parseCommandOptions(int argc, char** argv) #if LL_WINDOWS //Windows changed command line parsing. Deal with it. - S32 slen = value.length() - 1; - S32 start = 0; - S32 end = slen; + size_t slen = value.length() - 1; + size_t start = 0; + size_t end = slen; if (argv[ii][start]=='"')start++; if (argv[ii][end]=='"')end--; if (start!=0 || end!=slen) @@ -343,92 +297,17 @@ void LLApp::setupErrorHandling() // Error handling is done by starting up an error handling thread, which just sleeps and // occasionally checks to see if the app is in an error state, and sees if it needs to be run. -#if LL_WINDOWS - -#if LL_SEND_CRASH_REPORTS - EnableCrashingOnCrashes(); - - // This sets a callback to handle w32 signals to the console window. - // The viewer shouldn't be affected, sicne its a windowed app. - SetConsoleCtrlHandler( (PHANDLER_ROUTINE) ConsoleCtrlHandler, TRUE); - - // Install the Google Breakpad crash handler for Windows - if(mExceptionHandler == 0) - { - mExceptionHandler = new google_breakpad::ExceptionHandler( - std::wstring(mDumpPath.begin(),mDumpPath.end()), //Dump path - clear_CrashLoggerReserve_callback, - windows_post_minidump_callback, - 0, - google_breakpad::ExceptionHandler::HANDLER_ALL); - if (mExceptionHandler) - { - mExceptionHandler->set_handle_debug_exceptions(true); - } - } -#endif -#else +#if !LL_WINDOWS // // Start up signal handling. // // There are two different classes of signals. Synchronous signals are delivered to a specific // thread, asynchronous signals can be delivered to any thread (in theory) // - setup_signals(); - - // Add google breakpad exception handler configured for Darwin/Linux. - bool installHandler = true; -#if LL_DARWIN - // For the special case of Darwin, we do not want to install the handler if - // the process is being debugged as the app will exit with value ABRT (6) if - // we do. Unfortunately, the code below which performs that test relies on - // the structure kinfo_proc which has been tagged by apple as an unstable - // API. We disable this test for shipping versions to avoid conflicts with - // future releases of Darwin. This test is really only needed for developers - // starting the app from a debugger anyway. - #ifndef LL_RELEASE_FOR_DOWNLOAD - int mib[4]; - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = getpid(); - - struct kinfo_proc info; - memset(&info, 0, sizeof(info)); - - size_t size = sizeof(info); - int result = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0); - if((result == 0) || (errno == ENOMEM)) - { - // P_TRACED flag is set, so this process is being debugged; do not install - // the handler - if(info.kp_proc.p_flag & P_TRACED) installHandler = false; - } - else - { - // Failed to discover if the process is being debugged; default to - // installing the handler. - installHandler = true; - } - - if(installHandler && (mExceptionHandler == 0)) - { - mExceptionHandler = new google_breakpad::ExceptionHandler(mDumpPath, clear_CrashLoggerReserve_callback, &unix_post_minidump_callback, 0, true, 0); - } - #endif -#elif LL_LINUX - if(installHandler && (mExceptionHandler == 0)) - { - if (mDumpPath.empty()) - { - mDumpPath = "/tmp"; - } - google_breakpad::MinidumpDescriptor desc(mDumpPath); - mExceptionHandler = new google_breakpad::ExceptionHandler(desc, clear_CrashLoggerReserve_callback, unix_minidump_callback, NULL, true, -1); - } -#endif - +#endif // ! LL_WINDOWS +#if !defined(USE_CRASHPAD) + startErrorThread(); #endif } @@ -466,7 +345,6 @@ void LLApp::setErrorHandler(LLAppErrorHandler handler) LLApp::sErrorHandler = handler; } - // static void LLApp::runErrorHandler() { @@ -479,7 +357,6 @@ void LLApp::runErrorHandler() LLApp::setStopped(); } - // static void LLApp::setStatus(EAppStatus status) { @@ -494,43 +371,12 @@ void LLApp::setError() setStatus(APP_STATUS_ERROR); } -void LLApp::setMiniDumpDir(const std::string &path) -{ - if (path.empty()) - { - mDumpPath = "/tmp"; - } - else - { - mDumpPath = path; - } - - if(mExceptionHandler == 0) return; -#ifdef LL_WINDOWS - wchar_t buffer[MAX_MINDUMP_PATH_LENGTH]; - mbstowcs(buffer, mDumpPath.c_str(), MAX_MINDUMP_PATH_LENGTH); - mExceptionHandler->set_dump_path(std::wstring(buffer)); -#elif LL_LINUX - //google_breakpad::MinidumpDescriptor desc("/tmp"); //path works in debug fails in production inside breakpad lib so linux gets a little less stack reporting until it is patched. - google_breakpad::MinidumpDescriptor desc(mDumpPath); //path works in debug fails in production inside breakpad lib so linux gets a little less stack reporting until it is patched. - mExceptionHandler->set_minidump_descriptor(desc); -#else - mExceptionHandler->set_dump_path(mDumpPath); -#endif -} - void LLApp::setDebugFileNames(const std::string &path) { mStaticDebugFileName = path + "static_debug_info.log"; mDynamicDebugFileName = path + "dynamic_debug_info.log"; } -void LLApp::writeMiniDump() -{ - if(mExceptionHandler == 0) return; - mExceptionHandler->WriteMinidump(); -} - // static void LLApp::setQuitting() { @@ -585,13 +431,6 @@ bool LLApp::isExiting() void LLApp::disableCrashlogger() { - // Disable Breakpad exception handler. - if (mExceptionHandler != 0) - { - delete mExceptionHandler; - mExceptionHandler = 0; - } - sDisableCrashlogger = TRUE; } @@ -660,12 +499,6 @@ LONG WINAPI default_windows_exception_handler(struct _EXCEPTION_POINTERS *except ms_sleep(10); } - // - // Generate a minidump if we can. - // - // TODO: This needs to be ported over form the viewer-specific - // LLWinDebug class - // // At this point, we always want to exit the app. There's no graceful // recovery for an unhandled exception. @@ -965,150 +798,4 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) } } } - -#if LL_LINUX -bool unix_minidump_callback(const google_breakpad::MinidumpDescriptor& minidump_desc, void* context, bool succeeded) -{ - // Copy minidump file path into fixed buffer in the app instance to avoid - // heap allocations in a crash handler. - - // path format: /.dmp - - //HACK: *path points to the buffer in getMiniDumpFilename which has already allocated space - //to avoid doing allocation during crash. - char * path = LLApp::instance()->getMiniDumpFilename(); - int dir_path_len = strlen(path); - - // The path must not be truncated. - S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH - dir_path_len; - - llassert( (remaining - strlen(minidump_desc.path())) > 5); - - path += dir_path_len; - - if (dir_path_len > 0 && path[-1] != '/') - { - *path++ = '/'; - --remaining; - } - - strncpy(path, minidump_desc.path(), remaining); - - LL_INFOS() << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << LL_ENDL; - LLApp::runErrorHandler(); - -#ifndef LL_RELEASE_FOR_DOWNLOAD - clear_signals(); - return false; -#else - return true; -#endif - -} -#endif - - -bool unix_post_minidump_callback(const char *dump_dir, - const char *minidump_id, - void *context, bool succeeded) -{ - // Copy minidump file path into fixed buffer in the app instance to avoid - // heap allocations in a crash handler. - - // path format: /.dmp - int dirPathLength = strlen(dump_dir); - int idLength = strlen(minidump_id); - - // The path must not be truncated. - llassert((dirPathLength + idLength + 5) <= LLApp::MAX_MINDUMP_PATH_LENGTH); - - char * path = LLApp::instance()->getMiniDumpFilename(); - S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH; - strncpy(path, dump_dir, remaining); - remaining -= dirPathLength; - path += dirPathLength; - if (remaining > 0 && dirPathLength > 0 && path[-1] != '/') - { - *path++ = '/'; - --remaining; - } - if (remaining > 0) - { - strncpy(path, minidump_id, remaining); - remaining -= idLength; - path += idLength; - strncpy(path, ".dmp", remaining); - } - - LL_INFOS() << "generated minidump: " << path << LL_ENDL; - LLApp::runErrorHandler(); - -#ifndef LL_RELEASE_FOR_DOWNLOAD - clear_signals(); - return false; -#else - return true; -#endif -} #endif // !WINDOWS - -#ifdef LL_WINDOWS -bool windows_post_minidump_callback(const wchar_t* dump_path, - const wchar_t* minidump_id, - void* context, - EXCEPTION_POINTERS* exinfo, - MDRawAssertionInfo* assertion, - bool succeeded) -{ - char * path = LLApp::instance()->getMiniDumpFilename(); - S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH; - size_t bytesUsed; - - bytesUsed = wcstombs(path, dump_path, static_cast(remaining)); - remaining -= bytesUsed; - path += bytesUsed; - if(remaining > 0 && bytesUsed > 0 && path[-1] != '\\') - { - *path++ = '\\'; - --remaining; - } - if(remaining > 0) - { - bytesUsed = wcstombs(path, minidump_id, static_cast(remaining)); - remaining -= bytesUsed; - path += bytesUsed; - } - if(remaining > 0) - { - strncpy(path, ".dmp", remaining); - } - - LL_INFOS() << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << LL_ENDL; - // *NOTE:Mani - this code is stolen from LLApp, where its never actually used. - //OSMessageBox("Attach Debugger Now", "Error", OSMB_OK); - // *TODO: Translate the signals/exceptions into cross-platform stuff - // Windows implementation - LL_INFOS() << "Entering Windows Exception Handler..." << LL_ENDL; - - if (LLApp::isError()) - { - LL_WARNS() << "Got another fatal signal while in the error handler, die now!" << LL_ENDL; - } - - // Flag status to error, so thread_error starts its work - LLApp::setError(); - - // Block in the exception handler until the app has stopped - // This is pretty sketchy, but appears to work just fine - while (!LLApp::isStopped()) - { - ms_sleep(10); - } - -#ifndef LL_RELEASE_FOR_DOWNLOAD - return false; -#else - return true; -#endif -} -#endif diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index aab871799..2a8fddfa2 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -60,10 +60,6 @@ public: }; #endif -namespace google_breakpad { - class ExceptionHandler; // See exception_handler.h -} - class LL_COMMON_API LLApp : public LLOptionInterface { friend class LLErrorThread; @@ -233,22 +229,11 @@ public: static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred. //@} - // the maximum length of the minidump filename returned by getMiniDumpFilename() - static const U32 MAX_MINDUMP_PATH_LENGTH = 256; - - // change the directory where Breakpad minidump files are written to - void setMiniDumpDir(const std::string &path); void setDebugFileNames(const std::string &path); - // Return the Google Breakpad minidump filename after a crash. - char *getMiniDumpFilename() { return mMinidumpPath; } std::string* getStaticDebugFile() { return &mStaticDebugFileName; } std::string* getDynamicDebugFile() { return &mDynamicDebugFileName; } - // Write out a Google Breakpad minidump file. - void writeMiniDump(); - - #if !LL_WINDOWS // // Child process handling (Unix only for now) @@ -281,8 +266,6 @@ protected: static BOOL sDisableCrashlogger; // Let the OS handle crashes for us. std::wstring mCrashReportPipeStr; //Name of pipe to use for crash reporting. - std::string mDumpPath; //output path for google breakpad. Dependency workaround. - #if !LL_WINDOWS static LLAtomicU32* sSigChildCount; // Number of SIGCHLDs received. typedef std::map child_map; // Map key is a PID @@ -290,16 +273,13 @@ protected: static LLAppChildCallback sDefaultChildCallback; #endif - void startErrorThread(); - /** * @brief This method is called at the end, just prior to deinitializing curl. */ void stopErrorThread(); private: - // Contains the filename of the minidump file after a crash. - char mMinidumpPath[MAX_MINDUMP_PATH_LENGTH]; + void startErrorThread(); std::string mStaticDebugFileName; std::string mDynamicDebugFileName; @@ -323,11 +303,8 @@ private: std::vector mLiveFiles; //@} -private: // the static application instance if it was created. static LLApp* sApplication; - google_breakpad::ExceptionHandler * mExceptionHandler; - #if !LL_WINDOWS friend void default_unix_signal_handler(int signum, siginfo_t *info, void *); diff --git a/indra/llmessage/aihttptimeoutpolicy.cpp b/indra/llmessage/aihttptimeoutpolicy.cpp index 705b4770d..70e71c1d7 100644 --- a/indra/llmessage/aihttptimeoutpolicy.cpp +++ b/indra/llmessage/aihttptimeoutpolicy.cpp @@ -960,5 +960,4 @@ P(webProfileResponders); P(wholeModelFeeResponder); P(wholeModelUploadResponder); P2(XMLRPCResponder, connect_40s); -P2(crashLoggerResponder, transfer_300s); P(getUpdateInfoResponder); \ No newline at end of file diff --git a/indra/llprimitive/llmaterialid.cpp b/indra/llprimitive/llmaterialid.cpp index fc72961ea..81b457542 100644 --- a/indra/llprimitive/llmaterialid.cpp +++ b/indra/llprimitive/llmaterialid.cpp @@ -42,8 +42,11 @@ LLMaterialID::LLMaterialID() LLMaterialID::LLMaterialID(const LLSD& pMaterialID) { - llassert(pMaterialID.isBinary()); - parseFromBinary(pMaterialID.asBinary()); + llassert(pMaterialID.isBinary() || pMaterialID.isUUID()); + if (pMaterialID.isUUID()) + set(pMaterialID.asUUID().mData); + else + parseFromBinary(pMaterialID.asBinary()); } LLMaterialID::LLMaterialID(const LLSD::Binary& pMaterialID) diff --git a/indra/llprimitive/llmaterialid.h b/indra/llprimitive/llmaterialid.h index 275939032..1a086e23b 100644 --- a/indra/llprimitive/llmaterialid.h +++ b/indra/llprimitive/llmaterialid.h @@ -36,6 +36,7 @@ class LLMaterialID { public: LLMaterialID(); + LLMaterialID(const LLUUID& id) { set(id.mData); } LLMaterialID(const LLSD& pMaterialID); LLMaterialID(const LLSD::Binary& pMaterialID); LLMaterialID(const void* pMemory); diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 7a5141da2..dd39a5ab0 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -200,9 +200,14 @@ LLView* LLComboBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory * // if we haven't already gotten a value from our control_name and // if providing user text entry or descriptive label // don't select an item under the hood - if (combo_box->getControlName().empty() && !combo_box->acceptsTextInput() && combo_box->mLabel.empty()) + if (combo_box->getControlName().empty()) { - combo_box->selectFirstItem(); + const auto text = combo_box->acceptsTextInput(); + std::string label; + if (node->getAttributeString("label", label)) + text ? combo_box->setLabel(label) : (void)combo_box->mList->selectItemByLabel(label, FALSE); + else if (!text && combo_box->mLabel.empty()) + combo_box->selectFirstItem(); } return combo_box; diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 9916c9465..1f851e2dd 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -43,18 +43,18 @@ #include "lltimer.h" #include "llcalc.h" -//#include "llclipboard.h" +#include "llclipboard.h" #include "llcontrol.h" #include "llbutton.h" #include "llfocusmgr.h" #include "llkeyboard.h" +#include "llmenugl.h" #include "llrect.h" #include "llresmgr.h" #include "llstring.h" #include "llwindow.h" #include "llui.h" #include "lluictrlfactory.h" -#include "llclipboard.h" #include "../newview/lgghunspell_wrapper.h" // @@ -443,28 +443,9 @@ void LLLineEditor::deselect() } -void LLLineEditor::spell_correct(void* data) +void LLLineEditor::spell_show(void* show) { - SpellMenuBind* tempBind = (SpellMenuBind*)data; - LLLineEditor* line = tempBind->origin; - if(tempBind && line) - { - LL_INFOS() << ((LLMenuItemCallGL *)(tempBind->menuItem))->getName() << " : " << tempBind->origin->getName() << " : " << tempBind->word << LL_ENDL; - if(line)line->spellReplace(tempBind); - } -} - - -void LLLineEditor::spell_show(void * data) -{ - SpellMenuBind* tempBind = (SpellMenuBind*)data; - LLLineEditor* line = tempBind->origin; - - if (tempBind && line) - { - BOOL show = (tempBind->word == "Show Misspellings"); - glggHunSpell->setSpellCheckHighlight(show); - } + glggHunSpell->setSpellCheckHighlight(!!show); } std::vector LLLineEditor::getMisspelledWordsPositions() @@ -516,11 +497,12 @@ std::vector LLLineEditor::getMisspelledWordsPositions() void LLLineEditor::spell_add(void* data) { - SpellMenuBind* tempBind = (SpellMenuBind*)data; - if(tempBind) + auto self = static_cast(data); + S32 wordStart = 0, wordLen = 0; + if (self->getWordBoundriesAt(self->calculateCursorFromMouse(self->mLastContextMenuX), &wordStart, &wordLen)) { - glggHunSpell->addWordToCustomDictionary(tempBind->word); - tempBind->origin->mPrevSpelledText="";//make it update + glggHunSpell->addWordToCustomDictionary(wstring_to_utf8str(self->getWText().substr(wordStart, wordLen))); + self->mPrevSpelledText.clear(); //make it update } } @@ -1149,12 +1131,19 @@ void LLLineEditor::copy() } -void LLLineEditor::spellReplace(SpellMenuBind* spellData) +void LLLineEditor::spell_correct(void* data) { - mText.erase(spellData->wordPositionStart, - spellData->wordPositionEnd - spellData->wordPositionStart); - insert(spellData->word,spellData->wordPositionStart); - mCursorPos+=spellData->word.length() - (spellData->wordPositionEnd-spellData->wordPositionStart); + auto self = static_cast(data); + S32 wordStart = 0, wordLen = 0; + if (self->getWordBoundriesAt(self->calculateCursorFromMouse(self->mLastContextMenuX), &wordStart, &wordLen)) + { + auto word = utf8str_to_wstring(LLMenuGL::sMenuContainer->getActivatedItem()->getLabel()); + LLWStringUtil::replaceTabsWithSpaces(word, 4); + + self->mText.erase(wordStart, wordLen); + self->mText.insert(wordStart, word); + self->mCursorPos += word.length() - wordLen; + } } @@ -3017,15 +3006,6 @@ void LLLineEditor::showContextMenu(S32 x, S32 y) { gEditMenuHandler = this; - /*S32 screen_x, screen_y; - localPointToScreen(x, y, &screen_x, &screen_y); - menu->show(screen_x, screen_y);*/ - - - //setCursorAtLocalPos( x); - S32 wordStart = 0; - S32 wordLen = 0; - S32 pos = calculateCursorFromMouse(x); LLMenuGL* menu = (LLMenuGL*)mContextMenuHandle.get(); if (menu) @@ -3034,77 +3014,39 @@ void LLLineEditor::showContextMenu(S32 x, S32 y) { menu->setVisible(FALSE); } - for (int i = 0;i<(int)suggestionMenuItems.size();i++) - { - SpellMenuBind * tempBind = suggestionMenuItems[i]; - if(tempBind) - { - menu->removeChild((LLMenuItemCallGL *)tempBind->menuItem); - ((LLMenuItemCallGL *)tempBind->menuItem)->die(); - //delete tempBind->menuItem; - //tempBind->menuItem = NULL; - delete tempBind; - } - } - suggestionMenuItems.clear(); // spell_check="true" in xui - menu->setItemVisible("Spelsep", !mReadOnly && mSpellCheckable); if (!mReadOnly && mSpellCheckable) { // search for word matches - bool is_word_part = getWordBoundriesAt(pos, &wordStart, &wordLen); - if (is_word_part) + S32 wordStart = 0; + S32 wordLen = 0; + S32 pos = calculateCursorFromMouse(x); + if (getWordBoundriesAt(pos, &wordStart, &wordLen)) { - const LLWString& text = mText.getWString(); - std::string selectedWord(std::string(text.begin(), text.end()).substr(wordStart,wordLen)); - - if (!glggHunSpell->isSpelledRight(selectedWord)) - { - //misspelled word here, and you have just right clicked on it! - std::vector suggs = glggHunSpell->getSuggestionList(selectedWord); + const auto selectedWord = wstring_to_utf8str(getWText().substr(wordStart, wordLen)); - for (int i = 0; i<(int)suggs.size() ;i++) + if (!glggHunSpell->isSpelledRight(selectedWord)) + { + //misspelled word here, and you have just right clicked on it! + + for (const auto& word : glggHunSpell->getSuggestionList(selectedWord)) { - SpellMenuBind * tempStruct = new SpellMenuBind; - tempStruct->origin = this; - tempStruct->word = suggs[i]; - tempStruct->wordPositionEnd = wordStart + wordLen; - tempStruct->wordPositionStart=wordStart; - LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL( - tempStruct->word, spell_correct, NULL, tempStruct); - tempStruct->menuItem = suggMenuItem; - suggestionMenuItems.push_back(tempStruct); - menu->addChild(suggMenuItem); + menu->addChild(new LLMenuItemCallGL(word, spell_correct, nullptr, this)); } - SpellMenuBind * tempStruct = new SpellMenuBind; - tempStruct->origin = this; - tempStruct->word = selectedWord; - tempStruct->wordPositionEnd = wordStart + wordLen; - tempStruct->wordPositionStart=wordStart; - LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL( - "Add Word", spell_add, NULL, tempStruct); - tempStruct->menuItem = suggMenuItem; - suggestionMenuItems.push_back(tempStruct); - menu->addChild(suggMenuItem); + menu->addChild(new LLMenuItemCallGL("Add Word", spell_add, nullptr, this)); } } - SpellMenuBind * tempStruct = new SpellMenuBind; - tempStruct->origin = this; - if (glggHunSpell->getSpellCheckHighlight()) + const std::string showstr("Show Misspellings"), hidestr("Hide Misspellings"); + bool show = !glggHunSpell->getSpellCheckHighlight(); + auto word = show ? showstr : hidestr; + if (!menu->hasChild(word)) { - tempStruct->word = "Hide Misspellings"; + menu->addChild(new LLMenuItemCallGL(word, spell_show, nullptr, show ? &show : nullptr)); + if (auto child = menu->getChild(show ? hidestr : showstr, false, false)) + menu->removeChild(child); } - else - { - tempStruct->word = "Show Misspellings"; - } - LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL( - tempStruct->word, spell_show, NULL, tempStruct); - tempStruct->menuItem = suggMenuItem; - suggestionMenuItems.push_back(tempStruct); - menu->addChild(suggMenuItem); } mLastContextMenuX = x; diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index c6712b7cf..440407cd8 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -101,16 +101,6 @@ public: /*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char); /*virtual*/ void onMouseCaptureLost(); - struct SpellMenuBind - { - LLLineEditor* origin; - void * menuItem; - std::string word; - S32 wordPositionStart; - S32 wordPositionEnd; - }; - - virtual void spellReplace(SpellMenuBind* spellData); virtual void insert(std::string what,S32 wher); // LLEditMenuHandler overrides @@ -304,7 +294,6 @@ protected: S32 mEndSpellHere; // the location of the last char on the screen BOOL mSpellCheckable; // set in xui as "spell_check". Default value for a field LLFrameTimer mSpellTimer; - std::vector suggestionMenuItems; S32 mLastContextMenuX; // line history support: diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 5ae3d36b2..7b9bbe372 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -73,7 +73,6 @@ using namespace LLOldEvents; LLMenuHolderGL *LLMenuGL::sMenuContainer = nullptr; S32 MENU_BAR_HEIGHT = 0; -S32 MENU_BAR_WIDTH = 0; ///============================================================================ /// Local function declarations, constants, enums, and typedefs diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 153479852..45e21e18e 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -47,7 +47,6 @@ extern S32 MENU_BAR_HEIGHT; -extern S32 MENU_BAR_WIDTH; // These callbacks are used by the LLMenuItemCallGL and LLMenuItemCheckGL // classes during their work. @@ -897,6 +896,7 @@ public: LLView*const getVisibleMenu() const; virtual BOOL hasVisibleMenu() const {return getVisibleMenu() != NULL;} + static LLMenuItemGL* getActivatedItem() { return static_cast(sItemLastSelectedHandle.get()); } static void setActivatedItem(LLMenuItemGL* item); // Need to detect if mouse-up after context menu spawn has moved. diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index c4cdbbdf8..25400455b 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -508,26 +508,23 @@ public: void LLTextEditor::spell_correct(void* data) { - SpellMenuBind* tempBind = (SpellMenuBind*)data; - LLTextEditor* line = tempBind->origin; - if(tempBind && line) + auto self = static_cast(data); + S32 wordStart = 0, wordLen = 0; + if (self->getWordBoundriesAt(self->getCursorPosFromLocalCoord(self->mLastContextMenuX, self->mLastContextMenuY, TRUE), &wordStart, &wordLen)) { - LL_INFOS() << tempBind->menuItem->getName() << " : " << tempBind->origin->getName() << " : " << tempBind->word << LL_ENDL; - if(line)line->spellReplace(tempBind); + const auto& word = utf8str_to_wstring(LLMenuGL::sMenuContainer->getActivatedItem()->getLabel()); + + self->remove(wordStart, wordLen, TRUE); + self->insert(wordStart, word, FALSE); + self->mCursorPos += word.length() - wordLen; + self->needsReflow(); } } -void LLTextEditor::spell_show(void * data) +void LLTextEditor::spell_show(void* show) { - SpellMenuBind* tempBind = (SpellMenuBind*)data; - LLTextEditor* line = tempBind->origin; - - if(tempBind && line) - { - BOOL show = (tempBind->word == "Show Misspellings"); - glggHunSpell->setSpellCheckHighlight(show); - } + glggHunSpell->setSpellCheckHighlight(!!show); } @@ -574,11 +571,12 @@ std::vector LLTextEditor::getMisspelledWordsPositions() void LLTextEditor::spell_add(void* data) { - SpellMenuBind* tempBind = (SpellMenuBind*)data; - if(tempBind) + auto self = static_cast(data); + S32 wordStart = 0, wordLen = 0; + if (self->getWordBoundriesAt(self->getCursorPosFromLocalCoord(self->mLastContextMenuX, self->mLastContextMenuY, TRUE), &wordStart, &wordLen)) { - glggHunSpell->addWordToCustomDictionary(tempBind->word); - tempBind->origin->mPrevSpelledText.erase();//make it update + glggHunSpell->addWordToCustomDictionary(wstring_to_utf8str(self->getWText().substr(wordStart, wordLen))); + self->mPrevSpelledText.erase(); //make it update } } @@ -768,7 +766,7 @@ LLMenuGL* LLTextEditor::createUrlContextMenu(S32 x, S32 y, const std::string &in // create and return the context menu from the XUI file llassert(LLMenuGL::sMenuContainer != NULL); - auto menu = LLUICtrlFactory::getInstance()->buildMenu(xui_file, LLMenuGL::sMenuContainer); + auto menu = LLUICtrlFactory::instance().buildMenu(xui_file, LLMenuGL::sMenuContainer); if (menu) { if (mIsFriendSignal) @@ -1531,35 +1529,13 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask) } BOOL LLTextEditor::handleRightMouseDown( S32 x, S32 y, MASK mask ) { - setFocus(TRUE); - //setCursorAtLocalPos( x, y, TRUE ); - S32 wordStart = 0; - S32 wordLen = 0; - S32 pos = getCursorPosFromLocalCoord(x,y,TRUE); - - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if (menu) - { - for (auto tempBind : suggestionMenuItems) - { - if (tempBind) - { - menu->removeChild(tempBind->menuItem); - tempBind->menuItem->die(); - delete tempBind; - } - } - suggestionMenuItems.clear(); - menu->die(); - } - auto segment = getSegmentAtLocalPos(x, y); const LLStyleSP style = segment ? segment->getStyle() : nullptr; auto submenu = (style && style->isLink()) ? createUrlContextMenu(x, y, style->getLinkHREF()) : nullptr; // Add url menu to base menu if we have a selection, otherwise make it the menu. - menu = (submenu && !hasSelection()) ? submenu : LLUICtrlFactory::getInstance()->buildMenu("menu_texteditor.xml", LLMenuGL::sMenuContainer); + auto menu = (submenu && !hasSelection()) ? submenu : LLUICtrlFactory::instance().buildMenu("menu_texteditor.xml", LLMenuGL::sMenuContainer); mPopupMenuHandle = menu->getHandle(); if (menu) { @@ -1572,62 +1548,29 @@ BOOL LLTextEditor::handleRightMouseDown( S32 x, S32 y, MASK mask ) // spell_check="true" in xui if (!mReadOnly && mSpellCheckable) { - bool is_word_part = getWordBoundriesAt(pos, &wordStart, &wordLen); - if (is_word_part) + S32 wordStart = 0; + S32 wordLen = 0; + S32 pos = getCursorPosFromLocalCoord(x, y, TRUE); + if (getWordBoundriesAt(pos, &wordStart, &wordLen)) { - const LLWString &text = mWText; - std::string selectedWord(std::string(text.begin(), text.end()).substr(wordStart, wordLen)); + const auto selectedWord = wstring_to_utf8str(getWText().substr(wordStart, wordLen)); if (!glggHunSpell->isSpelledRight(selectedWord)) { //misspelled word here, and you have just right clicked on it! - std::vector suggs = glggHunSpell->getSuggestionList(selectedWord); menu->addSeparator(); - for (auto word : suggs) + for (const auto& word : glggHunSpell->getSuggestionList(selectedWord)) { - SpellMenuBind * tempStruct = new SpellMenuBind; - tempStruct->origin = this; - tempStruct->word = word; - tempStruct->wordPositionEnd = wordStart + wordLen; - tempStruct->wordPositionStart = wordStart; - tempStruct->wordY = y; - LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL( - tempStruct->word, spell_correct, NULL, tempStruct); - tempStruct->menuItem = suggMenuItem; - suggestionMenuItems.push_back(tempStruct); - menu->addChild(suggMenuItem); + menu->addChild(new LLMenuItemCallGL(word, spell_correct, nullptr, this)); } - SpellMenuBind * tempStruct = new SpellMenuBind; - tempStruct->origin = this; - tempStruct->word = selectedWord; - tempStruct->wordPositionEnd = wordStart + wordLen; - tempStruct->wordPositionStart = wordStart; - tempStruct->wordY = y; - LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL( - "Add Word", spell_add, NULL, tempStruct); - tempStruct->menuItem = suggMenuItem; - suggestionMenuItems.push_back(tempStruct); - menu->addChild(suggMenuItem); + menu->addChild(new LLMenuItemCallGL("Add Word", spell_add, nullptr, this)); } } - SpellMenuBind * tempStruct = new SpellMenuBind; - tempStruct->origin = this; - if (glggHunSpell->getSpellCheckHighlight()) - { - tempStruct->word = "Hide Misspellings"; - } - else - { - tempStruct->word = "Show Misspellings"; - } - - LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL( - tempStruct->word, spell_show, NULL, tempStruct); - tempStruct->menuItem = suggMenuItem; - suggestionMenuItems.push_back(tempStruct); - menu->addChild(suggMenuItem); + bool show = !glggHunSpell->getSpellCheckHighlight(); + auto word = show ? "Show Misspellings" : "Hide Misspellings"; + menu->addChild(new LLMenuItemCallGL(word, spell_show, nullptr, show ? &show : nullptr)); } mLastContextMenuX = x; @@ -2423,17 +2366,6 @@ BOOL LLTextEditor::canPaste() const } -void LLTextEditor::spellReplace(SpellMenuBind* spellData) -{ - remove( spellData->wordPositionStart, - spellData->wordPositionEnd - spellData->wordPositionStart, TRUE ); - LLWString clean_string = utf8str_to_wstring(spellData->word); - insert(spellData->wordPositionStart, clean_string, FALSE); - mCursorPos+=clean_string.length() - (spellData->wordPositionEnd-spellData->wordPositionStart); - needsReflow(); -} - - // paste from clipboard void LLTextEditor::paste() { diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index b5d3eb699..a18907749 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -43,14 +43,11 @@ #include "lleditmenuhandler.h" #include "llpreeditor.h" -#include "llmenugl.h" class LLFontGL; -class LLScrollbar; -class LLViewBorder; class LLKeywordToken; +class LLMenuGL; class LLTextCmd; -class LLUICtrlFactory; class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor { @@ -126,16 +123,6 @@ public: virtual BOOL isDirty() const { return( mLastCmd != NULL || (mPristineCmd && (mPristineCmd != mLastCmd)) ); } BOOL isSpellDirty() const { return mWText != mPrevSpelledText; } // Returns TRUE if user changed value at all void resetSpellDirty() { mPrevSpelledText = mWText; } // Clear dirty state - - struct SpellMenuBind - { - LLTextEditor* origin; - LLMenuItemCallGL * menuItem; - std::string word; - S32 wordPositionStart; - S32 wordPositionEnd; - S32 wordY; - }; // LLEditMenuHandler interface virtual void undo(); @@ -151,8 +138,6 @@ public: virtual void paste(); virtual BOOL canPaste() const; - virtual void spellReplace(SpellMenuBind* spellData); - virtual void updatePrimary(); virtual void copyPrimary(); virtual void pastePrimary(); @@ -580,7 +565,6 @@ private: typedef std::vector line_list_t; //to keep track of what we have to remove before showing menu - std::vector suggestionMenuItems; S32 mLastContextMenuX; S32 mLastContextMenuY; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index fbd06b54e..57ad1b0b2 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -12,6 +12,7 @@ include(BuildPackagesInfo) include(BuildVersion) include(BuildBranding) include(CMakeCopyIfDifferent) +include(CrashPad) include(DBusGlib) include(FMODSTUDIO) include(GeneratePrecompiledHeader) @@ -49,6 +50,15 @@ include(WinManifest) include(ZLIB) include(URIPARSER) + +if(FMODSTUDIO) + include_directories(${FMODSTUDIO_INCLUDE_DIR}) +endif(FMODSTUDIO) + +if(USE_CRASHPAD) + include_directories(${CRASHPAD_INCLUDE_DIRS}) +endif(USE_CRASHPAD) + include_directories( ${STATEMACHINE_INCLUDE_DIRS} ${DBUSGLIB_INCLUDE_DIRS} @@ -71,6 +81,7 @@ include_directories( ${LLWINDOW_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} ${HUNSPELL_INCLUDE_DIR} + ${OPENAL_LIB_INCLUDE_DIRS} ${LLAPPEARANCE_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR} ) @@ -143,7 +154,6 @@ set(viewer_SOURCE_FILES llconfirmationmanager.cpp llconsole.cpp llcontrolavatar.cpp - llcrashlogger.cpp llcurrencyuimanager.cpp llcylinder.cpp lldaycyclemanager.cpp @@ -681,7 +691,6 @@ set(viewer_HEADER_FILES llconfirmationmanager.h llconsole.h llcontrolavatar.h - llcrashlogger.h llcurrencyuimanager.h llcylinder.h lldaycyclemanager.h @@ -1303,16 +1312,16 @@ if (WINDOWS) set_source_files_properties(${viewer_RESOURCE_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) - set(viewer_RESOURCE_FILES + + list(APPEND viewer_RESOURCE_FILES ${CMAKE_CURRENT_BINARY_DIR}/viewerRes.rc - ${viewer_RESOURCE_FILES} ) set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/viewerRes.rc PROPERTIES COMPILE_FLAGS "-I${CMAKE_CURRENT_SOURCE_DIR}/res" ) - SOURCE_GROUP("Resource Files" FILES ${viewer_RESOURCE_FILES}) + source_group("Resource Files" FILES ${viewer_RESOURCE_FILES}) list(APPEND viewer_SOURCE_FILES ${viewer_RESOURCE_FILES}) @@ -1375,7 +1384,6 @@ set(viewer_APPSETTINGS_FILES app_settings/settings.xml app_settings/settings_ascent.xml app_settings/settings_ascent_coa.xml - app_settings/settings_crash_behavior.xml app_settings/settings_files.xml app_settings/settings_per_account.xml app_settings/settings_sh.xml @@ -1422,7 +1430,15 @@ if (WINDOWS) list(APPEND viewer_SOURCE_FILES ${viewer_INSTALLER_FILES}) endif (WINDOWS) -set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}") +if (OPENAL) + list(APPEND LLSTARTUP_COMPILE_DEFINITIONS "LL_OPENAL=1") +endif (OPENAL) + +if (FMODSTUDIO) + list(APPEND LLSTARTUP_COMPILE_DEFINITIONS "LL_FMODSTUDIO=1") +endif (FMODSTUDIO) + +set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_DEFINITIONS "${LLSTARTUP_COMPILE_DEFINITIONS}") if (LIBVLCPLUGIN) set_source_files_properties(llfloaterabout.cpp PROPERTIES COMPILE_DEFINITIONS "VLCPLUGIN=1") @@ -1624,6 +1640,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${PNG_PRELOAD_ARCHIVES} ${ZLIB_PRELOAD_ARCHIVES} ${GOOGLE_PERFTOOLS_LIBRARIES} + ${CRASHPAD_LIBRARIES} ${LLAUDIO_LIBRARIES} ${LLAUDIO_VORBIS_LIBRARIES} ${LLCHARACTER_LIBRARIES} @@ -1671,6 +1688,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLAPPEARANCE_LIBRARIES} absl::flat_hash_map absl::node_hash_map + ${FMT_LIBRARY} ) if (LINUX) @@ -1822,8 +1840,10 @@ if (INSTALL) include(${CMAKE_CURRENT_SOURCE_DIR}/ViewerInstall.cmake) endif (INSTALL) -if (PACKAGE) +if (PACKAGE AND USE_CRASHPAD) + # Breakpad symbol-file generation set(SYMBOL_NAME ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${VIEWER_CHANNEL_NOSPACE}-${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}-symbols) + set(SYMBOL_SEARCH_DIRS "") if (WINDOWS) list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") @@ -1853,7 +1873,6 @@ if (PACKAGE) set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest) endif (LINUX) - if(RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) if(GEN_IS_MULTI_CONFIG) set(LLBUILD_CONFIG ${CMAKE_BUILD_TYPE}) else() @@ -1874,14 +1893,14 @@ if (PACKAGE) DEPENDS generate_breakpad_symbols.py VERBATIM) - add_custom_target(generate_breakpad_symbols DEPENDS "${VIEWER_SYMBOL_FILE}") - add_dependencies(generate_breakpad_symbols ${VIEWER_BINARY_NAME}) -if(VIEWER_COPY_MANIFEST) - add_dependencies(generate_breakpad_symbols ${VIEWER_COPY_MANIFEST}) -endif(VIEWER_COPY_MANIFEST) - add_dependencies(llpackage generate_breakpad_symbols) - endif(RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) -endif (PACKAGE) + add_custom_target(generate_symbols DEPENDS "${VIEWER_SYMBOL_FILE}" ${VIEWER_BINARY_NAME} "${VIEWER_COPY_MANIFEST}") + add_dependencies(generate_symbols ${VIEWER_BINARY_NAME}) + if (WINDOWS OR LINUX) + add_dependencies(generate_symbols "${VIEWER_COPY_MANIFEST}") + endif (WINDOWS OR LINUX) + + add_dependencies(llpackage generate_symbols) +endif () # Add tests if (LL_TESTS) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 2b7e54597..e1ba77b93 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -2538,17 +2538,6 @@ This should be as low as possible, but too low may break functionality 1 - CrashHostUrl - - Comment - A URL pointing to a crash report handler; overrides cluster negotiation to locate crash handler. - Persist - 1 - Type - String - Value - http://crash.singularityviewer.org/report.php> - AFKTimeout Comment @@ -10750,17 +10739,6 @@ This should be as low as possible, but too low may break functionality Value 18 - MenuBarWidth - - Comment - - Persist - 0 - Type - S32 - Value - 410 - MeshEnabled Comment @@ -18982,24 +18960,13 @@ This should be as low as possible, but too low may break functionality CrashSubmitBehavior Comment - Controls behavior when viewer crashes (0 = ask before sending crash report, 1 = always send crash report, 2 = never send crash report) + Controls behavior when viewer crashes (0 = never send crash report, 1 = always send crash report) Persist 1 Type S32 Value - 0 - - CrashReportID - - Comment - ID of the last crash report sent. Zero indicates that no crash report has been sent. Non-zero value can be useful infermation for developers to track a specific issue - Persist - 1 - Type - S32 - Value - 0 + -1 EveryoneCopy diff --git a/indra/newview/app_settings/settings_crash_behavior.xml b/indra/newview/app_settings/settings_crash_behavior.xml deleted file mode 100644 index 74704f8ad..000000000 --- a/indra/newview/app_settings/settings_crash_behavior.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - CrashSubmitBehavior - - Comment - Controls behavior when viewer crashes (0 = ask before sending crash report, 1 = always send crash report, 2 = never send crash report) - Persist - 2 - Type - S32 - Value - 1 - - - diff --git a/indra/newview/app_settings/settings_files.xml b/indra/newview/app_settings/settings_files.xml index ac304f759..cfb4504f2 100644 --- a/indra/newview/app_settings/settings_files.xml +++ b/indra/newview/app_settings/settings_files.xml @@ -43,13 +43,6 @@ Requirement 1 - CrashSettings - - Name - settings_crash_behavior.xml - Requirement - 1 - User @@ -65,11 +58,6 @@ NameFromSetting ClientSettingsFile - CrashSettings - - Name - settings_crash_behavior.xml - Account diff --git a/indra/newview/chatbar_as_cmdline.cpp b/indra/newview/chatbar_as_cmdline.cpp index 145f3c9fe..c70eec31b 100644 --- a/indra/newview/chatbar_as_cmdline.cpp +++ b/indra/newview/chatbar_as_cmdline.cpp @@ -705,7 +705,7 @@ void fake_local_chat(std::string msg) chat.mSourceType = CHAT_SOURCE_SYSTEM; if (rlv_handler_t::isEnabled()) chat.mRlvLocFiltered = chat.mRlvNamesFiltered = true; chat.mPosAgent = gAgent.getPositionAgent(); - chat.mURL = "secondlife:///app/agent/" + gAgentID.asString() + "/about"; + chat.mURL = LLAvatarActions::getSLURL(gAgentID); if (action) chat.mChatStyle = CHAT_STYLE_IRC; if (!LLAvatarNameCache::getNSName(gAgentID, chat.mFromName)) { diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index c91eccafd..56c2c6550 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -87,7 +87,6 @@ #include "llappearancemgr.h" // [/SL:KB] #include "llfloaterteleporthistory.h" -#include "llcrashlogger.h" #include "llweb.h" #include "llsecondlifeurls.h" #include "llavatarrenderinfoaccountant.h" @@ -211,6 +210,20 @@ #include +#ifdef USE_CRASHPAD +#pragma warning(disable:4265) + +#include +#include +#include +#include + +#include + +#include "llnotificationsutil.h" +#include "llversioninfo.h" +#endif + ////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor // @@ -237,6 +250,8 @@ F32 gSimFrames; BOOL gShowObjectUpdates = FALSE; +S32 gLastExecDuration = -1; // (<0 indicates unknown) + BOOL gAcceptTOS = FALSE; BOOL gAcceptCriticalMessage = FALSE; @@ -297,8 +312,9 @@ BOOL gLogoutInProgress = FALSE; //////////////////////////////////////////////////////////// // Internal globals... that should be removed. static std::string gArgs; - +const int MAX_MARKER_LENGTH = 1024; const std::string MARKER_FILE_NAME("Singularity.exec_marker"); +const std::string START_MARKER_FILE_NAME("Singularity.start_marker");; const std::string ERROR_MARKER_FILE_NAME("Singularity.error_marker"); const std::string LLERROR_MARKER_FILE_NAME("Singularity.llerror_marker"); const std::string LOGOUT_MARKER_FILE_NAME("Singularity.logout_marker"); @@ -367,7 +383,6 @@ void init_default_trans_args() const char *VFS_DATA_FILE_BASE = "data.db2.x."; const char *VFS_INDEX_FILE_BASE = "index.db2.x."; -static std::string gSecondLife; std::string gWindowTitle; std::string gLoginPage; @@ -434,24 +449,6 @@ void request_initial_instant_messages() } } -// A settings system callback for CrashSubmitBehavior -bool handleCrashSubmitBehaviorChanged(const LLSD& newvalue) -{ - S32 cb = newvalue.asInteger(); - const S32 NEVER_SUBMIT_REPORT = 2; - if(cb == NEVER_SUBMIT_REPORT) - { -// LLWatchdog::getInstance()->cleanup(); // SJB: cleaning up a running watchdog thread is unsafe - LLAppViewer::instance()->destroyMainloopTimeout(); - } - else if(gSavedSettings.getBOOL("WatchdogEnabled") == TRUE) - { - // Don't re-enable the watchdog when we change the setting; this may get called before it's started -// LLWatchdog::getInstance()->init(); - } - return true; -} - // Use these strictly for things that are constructed at startup, // or for things that are performance critical. JC static void settings_to_globals() @@ -461,8 +458,8 @@ static void settings_to_globals() BTN_HEIGHT_SMALL = gSavedSettings.getS32("ButtonHeightSmall"); BTN_HEIGHT = gSavedSettings.getS32("ButtonHeight"); + extern S32 MENU_BAR_HEIGHT; MENU_BAR_HEIGHT = gSavedSettings.getS32("MenuBarHeight"); - MENU_BAR_WIDTH = gSavedSettings.getS32("MenuBarWidth"); extern S32 STATUS_BAR_HEIGHT; STATUS_BAR_HEIGHT = gSavedSettings.getS32("StatusBarHeight"); @@ -536,7 +533,6 @@ LLAppViewer* LLAppViewer::sInstance = NULL; const std::string LLAppViewer::sGlobalSettingsName = "Global"; const std::string LLAppViewer::sPerAccountSettingsName = "PerAccount"; -const std::string LLAppViewer::sCrashSettingsName = "CrashSettings"; LLTextureCache* LLAppViewer::sTextureCache = NULL; LLImageDecodeThread* LLAppViewer::sImageDecodeThread = NULL; @@ -544,7 +540,7 @@ LLTextureFetch* LLAppViewer::sTextureFetch = NULL; LLAppViewer::LLAppViewer() : mMarkerFile(), - mLogoutMarkerFile(NULL), + mLogoutMarkerFile(), mReportedCrash(false), mNumSessions(0), mPurgeCache(false), @@ -556,13 +552,11 @@ LLAppViewer::LLAppViewer() : mMainloopTimeout(NULL), mAgentRegionLastAlive(false) { - if(NULL != sInstance) + if(nullptr != sInstance) { LL_ERRS() << "Oh no! An instance of LLAppViewer already exists! LLAppViewer is sort of like a singleton." << LL_ENDL; } - mDumpPath.clear(); - // Need to do this initialization before we do anything else, since anything // that touches files should really go through the lldir API { @@ -580,7 +574,26 @@ LLAppViewer::LLAppViewer() : gDirUtilp->initAppDirs("SecondLife", newview_path); } + // + // IMPORTANT! Do NOT put anything that will write + // into the log files during normal startup until AFTER + // we run the "program crashed last time" error handler below. + // sInstance = this; + + + initLoggingAndGetLastDuration(); + + processMarkerFiles(); + // + // OK to write stuff to logs now, we've now crash reported if necessary + // +#if !defined(USE_CRASHPAD) + // write dump files to a per-run dump directory to avoid multiple viewer issues. + std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, ""); + + setDebugFileNames(logdir); +#endif } @@ -589,13 +602,13 @@ LLAppViewer::~LLAppViewer() destroyMainloopTimeout(); // If we got to this destructor somehow, the app didn't hang. - removeMarkerFile(); + removeMarkerFiles(); } class LLUITranslationBridge : public LLTranslationBridge { public: - virtual std::string getString(const std::string &xml_desc) + std::string getString(const std::string &xml_desc) override { return LLTrans::getString(xml_desc); } @@ -634,17 +647,151 @@ void fast_exit(int rc) } */ +#ifdef USE_CRASHPAD +base::FilePath databasePath() +{ + // Cache directory that will store crashpad information and minidumps + std::string crashpad_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "crashpad"); + return base::FilePath(ll_convert_string_to_wide(crashpad_path)); +} + +static void handleCrashSubmitBehaviorChanged(LLControlVariable*, const LLSD& val) +{ + if (auto db = crashpad::CrashReportDatabase::Initialize(databasePath())) + { + if (auto settings = db->GetSettings()) + { + settings->SetUploadsEnabled(val.asBoolean()); + } + } +} + +static void configureCrashUploads() +{ + auto database = databasePath(); + auto db = crashpad::CrashReportDatabase::InitializeWithoutCreating(database); + if (!db) return; + auto settings = db->GetSettings(); + if (!settings) return; + auto control = gSavedSettings.getControl("CrashSubmitBehavior"); + control->getSignal()->connect(handleCrashSubmitBehaviorChanged); + if (control->get().asInteger() == -1) + { + LLNotificationsUtil::add("SubmitCrashReports", LLSD(), LLSD(), [control](const LLSD& p, const LLSD& f) { + control->set(!LLNotificationsUtil::getSelectedOption(p, f)); + }); + } + + if (!settings->SetUploadsEnabled(control->get().asInteger() == 1)) + { + LL_WARNS() << "Failed to set enable upload of crash database." << LL_ENDL; + } +} +#endif + +void LLAppViewer::initCrashReporting() +{ +#ifdef USE_CRASHPAD + // Path to the out-of-process handler executable + std::string handler_path = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "crashpad_handler.exe"); + if (!gDirUtilp->fileExists(handler_path)) + { + LL_ERRS() << "Failed to initialize crashpad due to missing handler executable." << LL_ENDL; + return; + } + base::FilePath handler(ll_convert_string_to_wide(handler_path)); + + auto database = databasePath(); + + // URL used to submit minidumps to + std::string url(CRASHPAD_URL); + + // Optional annotations passed via --annotations to the handler + std::map annotations; + +#if 0 + unsigned char node_id[6]; + if (LLUUID::getNodeID(node_id) > 0) + { + char md5str[MD5HEX_STR_SIZE] = { 0 }; + LLMD5 hashed_unique_id; + hashed_unique_id.update(node_id, 6); + hashed_unique_id.finalize(); + hashed_unique_id.hex_digest((char*)md5str); + annotations.emplace("sentry[contexts][app][device_app_hash]", std::string(md5str)); + } +#endif + + annotations.emplace("sentry[contexts][app][app_name]", LLVersionInfo::getChannel()); + annotations.emplace("sentry[contexts][app][app_version]", LLVersionInfo::getVersion()); + annotations.emplace("sentry[contexts][app][app_build]", LLVersionInfo::getChannelAndVersion()); + + annotations.emplace("sentry[tags][second_instance]", fmt::to_string(isSecondInstance())); + //annotations.emplace("sentry[tags][bitness]", fmt::to_string(ADDRESS_SIZE)); + annotations.emplace("sentry[tags][bitness]", +#if defined(_WIN64) || defined(__x86_64__) + "64" +#else + "32" +#endif + ); + + // Optional arguments to pass to the handler + std::vector arguments; + arguments.push_back("--no-upload-gzip"); + arguments.push_back("--no-rate-limit"); + arguments.push_back("--monitor-self"); + + if (isSecondInstance()) + { + arguments.push_back("--no-periodic-tasks"); + } + else + { + auto db = crashpad::CrashReportDatabase::Initialize(database); + if (db == nullptr) + { + LL_WARNS() << "Failed to initialize crashpad database at path: " << wstring_to_utf8str(database.value()) << LL_ENDL; + return; + } + + auto prune_condition = crashpad::PruneCondition::GetDefault(); + if (prune_condition != nullptr) + { + auto ret = crashpad::PruneCrashReportDatabase(db.get(), prune_condition.get()); + LL_INFOS() << "Pruned " << ret << " reports from the crashpad database." << LL_ENDL; + } + } + + crashpad::CrashpadClient client; + bool success = client.StartHandler( + handler, + database, + database, + url, + annotations, + arguments, + /* restartable */ true, + /* asynchronous_start */ false + ); + if (success) + LL_INFOS() << "Crashpad init success" << LL_ENDL; + else + LL_WARNS() << "FAILED TO INITIALIZE CRASHPAD" << LL_ENDL; +#endif +} + bool LLAppViewer::init() -{ +{ +#ifdef USE_CRASHPAD + initCrashReporting(); +#endif + setupErrorHandling(); // // Start of the application // - // IMPORTANT! Do NOT put anything that will write - // into the log files during normal startup until AFTER - // we run the "program crashed last time" error handler below. - // LLFastTimer::reset(); // initialize LLWearableType translation bridge. @@ -667,15 +814,12 @@ bool LLAppViewer::init() // this allows simple skinned file lookups to work gDirUtilp->setSkinFolder("default", "en-us"); - initLogging(); +// initLoggingAndGetLastDuration(); // // Curl must be initialized before any thread is running. AICurlInterface::initCurl(); - // Logging is initialized. Now it's safe to start the error thread. - startErrorThread(); - // // OK to write stuff to logs now, we've now crash reported if necessary // @@ -686,7 +830,6 @@ bool LLAppViewer::init() LL_INFOS("InitInfo") << "Configuration initialized." << LL_ENDL ; - // initialize skinning util LLSkinningUtil::initClass(); @@ -711,25 +854,9 @@ bool LLAppViewer::init() AIHTTPTimeoutPolicy::setDefaultCurlTimeout(policy_tmp); } - // Check if we have a crash report to send - LLCrashLogger crashLogger; - crashLogger.checkCrashDump(); - - // write Google Breakpad minidump files to a per-run dump directory to avoid multiple viewer issues. - std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, ""); - mDumpPath = logdir; - setMiniDumpDir(logdir); - logdir += gDirUtilp->getDirDelimiter(); - setDebugFileNames(logdir); - mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling")); - { - // Viewer metrics initialization - //static LLCachedControl metrics_submode(gSavedSettings, - // "QAModeMetrics", - // false, - // "Enables QA features (logging, faster cycling) for metrics collector"); + { if (gSavedSettings.getBOOL("QAModeMetrics")) { app_metrics_qa_mode = true; @@ -782,6 +909,11 @@ bool LLAppViewer::init() LLNotifications::instance().createDefaultChannels(); LL_INFOS("InitInfo") << "Notifications initialized." << LL_ENDL ; +#ifdef USE_CRASHPAD + // Now that we have Settings and Notifications, we can configure crash uploads + configureCrashUploads(); +#endif + writeSystemInfo(); ////////////////////////////////////////////////////////////////////////////// @@ -797,10 +929,6 @@ bool LLAppViewer::init() LL_INFOS("InitInfo") << "J2C Engine is: " << LLImageJ2C::getEngineInfo() << LL_ENDL; LL_INFOS("InitInfo") << "libcurl version is: " << LLCurl::getVersionString() << LL_ENDL; - // Get the single value from the crash settings file, if it exists - std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE); - gCrashSettings.loadFromFile(crash_settings_filename); - ///////////////////////////////////////////////// // OS-specific login dialogs ///////////////////////////////////////////////// @@ -898,6 +1026,7 @@ bool LLAppViewer::init() if (!initCache()) { + LL_WARNS("InitInfo") << "Failed to init cache" << LL_ENDL; std::ostringstream msg; msg << LLTrans::getString("MBUnableToAccessFile"); OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK); @@ -1051,9 +1180,8 @@ void LLAppViewer::initMaxHeapSize() //currently SL is built under 32-bit setting, we set its max heap size no more than 1.6 GB. //F32 max_heap_size_gb = llmin(1.6f, (F32)gSavedSettings.getF32("MaxHeapSize")) ; - F32Gigabytes max_heap_size_gb = (F32Gigabytes)gSavedSettings.getF32("MaxHeapSize") ; - + //This is all a bunch of CRAP. We run LAA on windows. 64bit windows supports LAA out of the box. 32bit does not, unless PAE is on. #if LL_WINDOWS //http://msdn.microsoft.com/en-us/library/windows/desktop/ms684139%28v=vs.85%29.aspx @@ -1081,7 +1209,7 @@ void LLAppViewer::initMaxHeapSize() } #endif - BOOL enable_mem_failure_prevention = (BOOL)gSavedSettings.getBOOL("MemoryFailurePreventionEnabled") ; + BOOL enable_mem_failure_prevention = gSavedSettings.getBOOL("MemoryFailurePreventionEnabled") ; LLMemory::initMaxHeapSizeGB(max_heap_size_gb, enable_mem_failure_prevention) ; } @@ -1263,7 +1391,6 @@ bool LLAppViewer::mainLoop() gKeyboard->scanKeyboard(); if (gAgent.isCrouching()) gAgent.moveUp(-1); - } // Update state based on messages, user input, object idle. @@ -1311,11 +1438,11 @@ bool LLAppViewer::mainLoop() pingMainloopTimeout("Main:Display"); gGLActive = TRUE; display(); + pingMainloopTimeout("Main:Snapshot"); LLFloaterSnapshot::update(); // take snapshots gGLActive = FALSE; } - } pingMainloopTimeout("Main:Sleep"); @@ -1459,7 +1586,7 @@ bool LLAppViewer::mainLoop() void LLAppViewer::flushVFSIO() { - while (1) + while (true) { S32 pending = LLVFSThread::updateClass(0); pending += LLLFSThread::updateClass(0); @@ -1477,7 +1604,8 @@ extern void cleanup_pose_stand(void); bool LLAppViewer::cleanup() { //ditch LLVOAvatarSelf instance - gAgentAvatarp = NULL; + gAgentAvatarp = nullptr; + // remove any old breakpad minidump files from the log directory if (! isError()) @@ -1502,7 +1630,7 @@ bool LLAppViewer::cleanup() release_start_screen(); // just in case - LLError::logToFixedBuffer(NULL); + LLError::logToFixedBuffer(nullptr); // stop the fixed buffer recorder LL_INFOS() << "Cleaning Up" << LL_ENDL; @@ -1533,7 +1661,7 @@ bool LLAppViewer::cleanup() } delete gAssetStorage; - gAssetStorage = NULL; + gAssetStorage = nullptr; LLPolyMesh::freeAllMeshes(); @@ -1541,7 +1669,10 @@ bool LLAppViewer::cleanup() // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be deleted. - LLWorldMap::getInstance()->reset(); // release any images + if (LLWorldMap::instanceExists()) + { + LLWorldMap::getInstance()->reset(); // release any images + } LLCalc::cleanUp(); @@ -1610,7 +1741,7 @@ bool LLAppViewer::cleanup() // This may generate window reshape and activation events. // Therefore must do this before destroying the message system. delete gViewerWindow; - gViewerWindow = NULL; + gViewerWindow = nullptr; LL_INFOS() << "ViewerWindow deleted" << LL_ENDL; } @@ -1618,7 +1749,7 @@ bool LLAppViewer::cleanup() // viewer UI relies on keyboard so keep it aound until viewer UI isa gone delete gKeyboard; - gKeyboard = NULL; + gKeyboard = nullptr; LL_INFOS() << "Cleaning up Objects" << LL_ENDL; @@ -1695,10 +1826,6 @@ bool LLAppViewer::cleanup() LL_INFOS() << "Saved settings" << LL_ENDL; } - std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE); - // save all settings, even if equals defaults - gCrashSettings.saveToFile(crash_settings_filename, FALSE); - // Save URL history file LLURLHistory::saveFile("url_history.xml"); @@ -1712,15 +1839,15 @@ bool LLAppViewer::cleanup() // save mute list. gMuteList used to also be deleted here too. LLMuteList::getInstance()->cache(gAgent.getID()); + if (mPurgeOnExit) { LL_INFOS() << "Purging all cache files on exit" << LL_ENDL; gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),"*.*"); } - removeMarkerFile(); // Any crashes from here on we'll just have to ignore // moved this stuff from above to make it conditional here... - if(!anotherInstanceRunning()) + if(!mSecondInstance) { removeCacheFiles("*.wav"); removeCacheFiles("*.tmp"); @@ -1736,8 +1863,7 @@ bool LLAppViewer::cleanup() LL_INFOS() << "Not removing cache files. Other viewer instance detected." << LL_ENDL; } // - - removeDumpDir(); + writeDebugInfo(); // Stop the plugin read thread if it's running. @@ -1751,7 +1877,7 @@ bool LLAppViewer::cleanup() LLTimer idleTimer; idleTimer.reset(); const F64 max_idle_time = 5.f; // 5 seconds - while(1) + while(true) { S32 pending = 0; pending += LLAppViewer::getTextureCache()->update(1); // unpauses the worker thread @@ -1761,7 +1887,7 @@ bool LLAppViewer::cleanup() pending += LLLFSThread::updateClass(0); if (!pending) { - break; + break ; //done } else if (idleTimer.getElapsedTimeF64() >= max_idle_time) { @@ -1775,14 +1901,16 @@ bool LLAppViewer::cleanup() sTextureFetch->shutdown(); sTextureCache->shutdown(); sImageDecodeThread->shutdown(); + sTextureFetch->shutDownTextureCacheThread(); sTextureFetch->shutDownImageDecodeThread(); delete sTextureCache; - sTextureCache = NULL; + sTextureCache = nullptr; delete sTextureFetch; - sTextureFetch = NULL; + sTextureFetch = nullptr; delete sImageDecodeThread; - sImageDecodeThread = NULL; + sImageDecodeThread = nullptr; + LL_INFOS() << "Cleaning up Media and Textures" << LL_ENDL; @@ -1815,9 +1943,9 @@ bool LLAppViewer::cleanup() // For safety, the LLVFS has to be deleted *after* LLVFSThread. This should be cleaned up. // (LLVFS doesn't know about LLVFSThread so can't kill pending requests) -Steve delete gStaticVFS; - gStaticVFS = NULL; + gStaticVFS = nullptr; delete gVFS; - gVFS = NULL; + gVFS = nullptr; LLWatchdog::getInstance()->cleanup(); @@ -1832,7 +1960,6 @@ bool LLAppViewer::cleanup() // Cleanup settings last in case other classes reference them. gSavedSettings.cleanup(); gColors.cleanup(); - gCrashSettings.cleanup(); LLViewerAssetStatsFF::cleanup(); // If we're exiting to launch an URL, do that here so the screen @@ -1842,7 +1969,7 @@ bool LLAppViewer::cleanup() LL_INFOS() << "Launch file on quit." << LL_ENDL; #if LL_WINDOWS // Indicate an application is starting. - SetCursor(LoadCursor(NULL, IDC_WAIT)); + SetCursor(LoadCursor(nullptr, IDC_WAIT)); #endif // HACK: Attempt to wait until the screen res. switch is complete. @@ -1863,6 +1990,8 @@ bool LLAppViewer::cleanup() LLError::LLCallStacks::cleanup(); + removeMarkerFiles(); + MEM_TRACK_RELEASE LL_INFOS() << "Goodbye!" << LL_ENDL; @@ -1871,13 +2000,13 @@ bool LLAppViewer::cleanup() return true; } -// A callback for llerrs to call during the watchdog error. +// A callback for LL_ERRS() to call during the watchdog error. void watchdog_llerrs_callback(const std::string &error_string) { gLLErrorActivated = true; #ifdef LL_WINDOWS - RaiseException(0,0,0,0); + RaiseException(0,0,0,nullptr); #else raise(SIGQUIT); #endif @@ -1898,9 +2027,8 @@ bool LLAppViewer::initThreads() static const bool enable_threads = true; #endif - const S32 NEVER_SUBMIT_REPORT = 2; bool use_watchdog = gSavedSettings.getBOOL("WatchdogEnabled"); - bool send_reports = gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING) != NEVER_SUBMIT_REPORT; + bool send_reports = gSavedSettings.getS32("CrashSubmitBehavior") == 1; if(use_watchdog && send_reports) { LLWatchdog::getInstance()->init(watchdog_killer_callback); @@ -1937,8 +2065,8 @@ void errorCallback(const std::string &error_string) static std::string last_message; if(last_message != error_string) { - U32 response = OSMessageBox(error_string, "Crash Loop?", OSMB_YESNO); - if(response) + U32 response = OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_YESNO); + if (response == OSBTN_NO) { last_message = error_string; return; @@ -1947,38 +2075,91 @@ void errorCallback(const std::string &error_string) //Set the ErrorActivated global so we know to create a marker file gLLErrorActivated = true; + gDebugInfo["FatalMessage"] = error_string; + // We're not already crashing -- we simply *intend* to crash. Since we + // haven't actually trashed anything yet, we can afford to write the whole + // static info file. + LLAppViewer::instance()->writeDebugInfo(); + LLError::crashAndLoop(error_string); } } -bool init_logging(); -bool LLAppViewer::initLogging() +void LLAppViewer::initLoggingAndGetLastDuration() { // // Set up logging defaults for the viewer // LLError::initForApplication( - gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); + gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "") + ); LLError::setFatalFunction(errorCallback); + //LLError::setTimeFunction(getRuntime); - return init_logging(); + initLoggingInternal(); } -bool init_logging() +void LLAppViewer::initLoggingInternal() { // Remove the last ".old" log file. - std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, OLD_LOG_FILE); + std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, + OLD_LOG_FILE); LLFile::remove(old_log_file); + // Get name of the log file + std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, + LOG_FILE); + /* + * Before touching any log files, compute the duration of the last run + * by comparing the ctime of the previous start marker file with the ctime + * of the last log file. + */ + std::string start_marker_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, START_MARKER_FILE_NAME); + llstat start_marker_stat; + llstat log_file_stat; + std::ostringstream duration_log_stream; // can't log yet, so save any message for when we can below + int start_stat_result = LLFile::stat(start_marker_file_name, &start_marker_stat); + int log_stat_result = LLFile::stat(log_file, &log_file_stat); + if ( 0 == start_stat_result && 0 == log_stat_result ) + { + int elapsed_seconds = log_file_stat.st_ctime - start_marker_stat.st_ctime; + // only report a last run time if the last viewer was the same version + // because this stat will be counted against this version + if ( markerIsSameVersion(start_marker_file_name) ) + { + gLastExecDuration = elapsed_seconds; + } + else + { + duration_log_stream << "start marker from some other version; duration is not reported"; + gLastExecDuration = -1; + } + } + else + { + // at least one of the LLFile::stat calls failed, so we can't compute the run time + duration_log_stream << "duration stat failure; start: "<< start_stat_result << " log: " << log_stat_result; + gLastExecDuration = -1; // unknown + } + std::string duration_log_msg(duration_log_stream.str()); + + // Create a new start marker file for comparison with log file time for the next run + LLAPRFile start_marker_file ; + start_marker_file.open(start_marker_file_name, LL_APR_WB); + if (start_marker_file.getFileHandle()) + { + recordMarkerVersion(start_marker_file); + start_marker_file.close(); + } + // Rename current log file to ".old" - std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LOG_FILE); LLFile::rename(log_file, old_log_file); - // Set the log file to Singularity.log - + // Set the log file to SecondLife.log LLError::logToFile(log_file); - - // *FIX:Mani no error handling here! - return true; + if (!duration_log_msg.empty()) + { + LL_WARNS("MarkerFile") << duration_log_msg << LL_ENDL; + } } bool LLAppViewer::loadSettingsFromDirectory(AIReadAccess const& settings_r, @@ -2098,7 +2279,6 @@ bool LLAppViewer::initConfiguration() //Set up internal pointers settings[sGlobalSettingsName] = &gSavedSettings; settings[sPerAccountSettingsName] = &gSavedPerAccountSettings; - settings[sCrashSettingsName] = &gCrashSettings; //Load settings files list std::string settings_file_list = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_files.xml"); @@ -2125,9 +2305,9 @@ bool LLAppViewer::initConfiguration() bool set_defaults = true; if(!loadSettingsFromDirectory(settings_w, "Default", set_defaults)) { - std::ostringstream msg; - msg << "Unable to load default settings file. The installation may be corrupted."; - OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK); + OSMessageBox( + "Unable to load default settings file. The installation may be corrupted.", + LLStringUtil::null,OSMB_OK); return false; } @@ -2139,6 +2319,7 @@ bool LLAppViewer::initConfiguration() gSavedSettings.connectCOAVars(gSavedPerAccountSettings); // - set procedural settings + // Note: can't use LL_PATH_PER_SL_ACCOUNT for any of these since we haven't logged in yet gSavedSettings.setString("ClientSettingsFile", gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Global"))); @@ -2171,8 +2352,6 @@ bool LLAppViewer::initConfiguration() gSavedSettings.setBOOL("WatchdogEnabled", FALSE); #endif - gCrashSettings.getControl(CRASH_BEHAVIOR_SETTING)->getSignal()->connect(boost::bind(&handleCrashSubmitBehaviorChanged, _2)); - // These are warnings that appear on the first experience of that condition. // They are already set in the settings_default.xml file, but still need to be added to LLFirstUse // for disable/reset ability @@ -2231,7 +2410,7 @@ bool LLAppViewer::initConfiguration() const std::string log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LOG_FILE); LL_INFOS() << "Attempting to use portable settings and cache!" << LL_ENDL; gDirUtilp->makePortable(); - init_logging(); // Switch to portable log file + initLoggingInternal(); // Switch to portable log file LL_INFOS() << "Portable viewer configuration initialized!" << LL_ENDL; LLFile::remove(log); LL_INFOS() << "Cleaned up local log file to keep this computer untouched." << LL_ENDL; @@ -2246,7 +2425,7 @@ bool LLAppViewer::initConfiguration() gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, clp.getOption("settings")[0]); gSavedSettings.setString("ClientSettingsFile", user_settings_filename); - LL_INFOS() << "Using command line specified settings filename: " + LL_INFOS("Settings") << "Using command line specified settings filename: " << user_settings_filename << LL_ENDL; } else @@ -2289,7 +2468,7 @@ bool LLAppViewer::initConfiguration() if(clp.hasOption("disablecrashlogger")) { LL_WARNS() << "Crashes will be handled by system, stack trace logs and crash logger are both disabled" <disableCrashlogger(); + disableCrashlogger(); } // Handle initialization from settings. @@ -2306,7 +2485,7 @@ bool LLAppViewer::initConfiguration() LL_INFOS() << msg.str() << LL_ENDL; OSMessageBox( - msg.str().c_str(), + msg.str(), LLStringUtil::null, OSMB_OK); @@ -2406,22 +2585,6 @@ bool LLAppViewer::initConfiguration() gSavedSettings.getString("Language")); } - // XUI:translate - gSecondLife = LLTrans::getString("APP_NAME"); - - // Read skin/branding settings if specified. - //if (! gDirUtilp->getSkinDir().empty() ) - //{ - // std::string skin_def_file = gDirUtilp->findSkinnedFilename("skin.xml"); - // LLXmlTree skin_def_tree; - - // if (!skin_def_tree.parseFile(skin_def_file)) - // { - // LL_ERRS() << "Failed to parse skin definition." << LL_ENDL; - // } - - //} - #if LL_DARWIN // Initialize apple menubar and various callbacks init_apple_menu(LLTrans::getString("APP_NAME").c_str()); @@ -2469,46 +2632,29 @@ bool LLAppViewer::initConfiguration() } } - if (!gSavedSettings.getBOOL("AllowMultipleViewers")) + + // + // Check for another instance of the app running + // + if (mSecondInstance && !gSavedSettings.getBOOL("AllowMultipleViewers")) { - // - // Check for another instance of the app running - // - - mSecondInstance = anotherInstanceRunning(); - - if (mSecondInstance) - { - std::ostringstream msg; - msg << LLTrans::getString("MBAlreadyRunning"); - OSMessageBox( - msg.str(), - LLStringUtil::null, - OSMB_OK); - return false; - } - - initMarkerFile(); - + OSMessageBox( + LLTrans::getString("MBAlreadyRunning"), + LLStringUtil::null, + OSMB_OK); + return false; } - else - { - mSecondInstance = anotherInstanceRunning(); - - if (mSecondInstance) - { - // This is the second instance of SL. Turn off voice support, - // but make sure the setting is *not* persisted. - LLControlVariable* disable_voice = gSavedSettings.getControl("CmdLineDisableVoice"); - if(disable_voice && !gSavedSettings.getBOOL("VoiceMultiInstance")) - { - const BOOL DO_NOT_PERSIST = FALSE; - disable_voice->setValue(LLSD(TRUE), DO_NOT_PERSIST); - } - } - initMarkerFile(); - + if (mSecondInstance) + { + // This is the second instance of SL. Turn off voice support, + // but make sure the setting is *not* persisted. + LLControlVariable* disable_voice = gSavedSettings.getControl("CmdLineDisableVoice"); + if(disable_voice && !gSavedSettings.getBOOL("VoiceMultiInstance")) + { + const BOOL DO_NOT_PERSIST = FALSE; + disable_voice->setValue(LLSD(TRUE), DO_NOT_PERSIST); + } } // need to do this here - need to have initialized global settings first @@ -2592,25 +2738,25 @@ bool LLAppViewer::initWindow() //gViewerWindow->getWindow()->show(); LL_INFOS("AppInit") << "Window initialization done." << LL_ENDL; + return true; } void LLAppViewer::writeDebugInfo(bool isStatic) { +#if !defined(USE_CRASHPAD) //Try to do the minimum when writing data during a crash. std::string* debug_filename; debug_filename = ( isStatic ? getStaticDebugFile() : getDynamicDebugFile() ); - LL_INFOS() << "Opening debug file " << *debug_filename << LL_ENDL; - llofstream out_file(*debug_filename); + LL_INFOS() << "Writing debug file " << *debug_filename << LL_ENDL; + llofstream out_file(debug_filename->c_str()); isStatic ? LLSDSerialize::toPrettyXML(gDebugInfo, out_file) : LLSDSerialize::toPrettyXML(gDebugInfo["Dynamic"], out_file); - - - out_file.close(); +#endif } void LLAppViewer::cleanupSavedSettings() @@ -2673,12 +2819,13 @@ void LLAppViewer::writeSystemInfo() gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor(); gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::getPatch(); gDebugInfo["ClientInfo"]["BuildVersion"] = LLVersionInfo::getBuild(); - + gDebugInfo["ClientInfo"]["AddressSize"] = #if defined(_WIN64) || defined(__x86_64__) - gDebugInfo["ClientInfo"]["Architecture"] = "x86_64"; + "64"; #else - gDebugInfo["ClientInfo"]["Architecture"] = "i386"; + "32"; #endif + gDebugInfo["CAFilename"] = gDirUtilp->getCAFile(); gDebugInfo["CPUInfo"]["CPUString"] = gSysCPU.getCPUString(); @@ -2742,9 +2889,9 @@ void LLAppViewer::writeSystemInfo() void LLAppViewer::handleViewerCrash() { - LL_INFOS() << "Handle viewer crash entry." << LL_ENDL; + LL_INFOS("CRASHREPORT") << "Handle viewer crash entry." << LL_ENDL; - LL_INFOS() << "Last render pool type: " << LLPipeline::sCurRenderPoolType << LL_ENDL ; + LL_INFOS("CRASHREPORT") << "Last render pool type: " << LLPipeline::sCurRenderPoolType << LL_ENDL ; LLMemory::logMemoryInfo(true) ; @@ -2787,8 +2934,7 @@ void LLAppViewer::handleViewerCrash() { gDebugInfo["Dynamic"]["ParcelMediaURL"] = parcel->getMediaURL(); } - - + gDebugInfo["SettingsFilename"] = gSavedSettings.getString("ClientSettingsFile"); gDebugInfo["CAFilename"] = gDirUtilp->getCAFile(); gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName(); @@ -2805,7 +2951,7 @@ void LLAppViewer::handleViewerCrash() } else { - gDebugInfo["LastExecEvent"] = gLLErrorActivated ? LAST_EXEC_LLERROR_CRASH : LAST_EXEC_OTHER_CRASH; + gDebugInfo["Dynamic"]["LastExecEvent"] = gLLErrorActivated ? LAST_EXEC_LLERROR_CRASH : LAST_EXEC_OTHER_CRASH; } if(gAgent.getRegion()) @@ -2833,26 +2979,27 @@ void LLAppViewer::handleViewerCrash() //we're already in a crash situation if (gDirUtilp) { - std::string crash_file_name; - if(gLLErrorActivated) crash_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LLERROR_MARKER_FILE_NAME); - else crash_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,ERROR_MARKER_FILE_NAME); - LL_INFOS() << "Creating crash marker file " << crash_file_name << LL_ENDL; - - LLAPRFile crash_file(crash_file_name, LL_APR_W); - if (crash_file.getFileHandle()) + std::string crash_marker_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, + gLLErrorActivated + ? LLERROR_MARKER_FILE_NAME + : ERROR_MARKER_FILE_NAME); + LLAPRFile crash_marker_file ; + crash_marker_file.open(crash_marker_file_name, LL_APR_WB); + if (crash_marker_file.getFileHandle()) { - LL_INFOS("MarkerFile") << "Created crash marker file " << crash_file_name << LL_ENDL; + LL_INFOS("MarkerFile") << "Created crash marker file " << crash_marker_file_name << LL_ENDL; + recordMarkerVersion(crash_marker_file); } else { - LL_WARNS("MarkerFile") << "Cannot create error marker file " << crash_file_name << LL_ENDL; + LL_WARNS("MarkerFile") << "Cannot create error marker file " << crash_marker_file_name << LL_ENDL; } } - char *minidump_file = pApp->getMiniDumpFilename(); - if(minidump_file && minidump_file[0] != 0) + else { - gDebugInfo["Dynamic"]["MinidumpPath"] = minidump_file; + LL_WARNS("MarkerFile") << "No gDirUtilp with which to create error marker file name" << LL_ENDL; } + LL_WARNS("CRASHREPORT") << "no minidump file? ah yeah, boi!" << LL_ENDL; gDebugInfo["Dynamic"]["CrashType"]="crash"; @@ -2860,13 +3007,17 @@ void LLAppViewer::handleViewerCrash() { std::string filename; filename = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "stats.log"); - llofstream file(filename, llofstream::binary); + LL_DEBUGS("CRASHREPORT") << "recording stats " << filename << LL_ENDL; + llofstream file(filename.c_str(), std::ios_base::binary); if(file.good()) { - LL_INFOS() << "Handle viewer crash generating stats log." << LL_ENDL; gMessageSystem->summarizeLogs(file); file.close(); } + else + { + LL_WARNS("CRASHREPORT") << "problem recording stats" << LL_ENDL; + } } if (gMessageSystem) @@ -2879,158 +3030,241 @@ void LLAppViewer::handleViewerCrash() // Close the debug file pApp->writeDebugInfo(false); //false answers the isStatic question with the least overhead. - - LLError::logToFile(""); - - // Remove the marker file, since otherwise we'll spawn a process that'll keep it locked - if(gDebugInfo["Dynamic"]["LastExecEvent"].asInteger() == LAST_EXEC_LOGOUT_CRASH) - { - pApp->removeMarkerFile(true); - } - else - { - pApp->removeMarkerFile(false); - } - - return; } -bool LLAppViewer::anotherInstanceRunning() +// static +void LLAppViewer::recordMarkerVersion(LLAPRFile& marker_file) { - // We create a marker file when the program starts and remove the file when it finishes. - // If the file is currently locked, that means another process is already running. - - std::string marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, MARKER_FILE_NAME); - LL_DEBUGS("MarkerFile") << "Checking marker file for lock..." << LL_ENDL; - - //Freeze case checks - if (LLAPRFile::isExist(marker_file, LL_APR_RB)) + std::string marker_version(LLVersionInfo::getChannelAndVersion()); + if ( marker_version.length() > MAX_MARKER_LENGTH ) { - // File exists, try opening with write permissions - LLAPRFile outfile(marker_file, LL_APR_WB); - apr_file_t* fMarker = outfile.getFileHandle() ; - if (!fMarker) - { - // Another instance is running. Skip the rest of these operations. - LL_INFOS("MarkerFile") << "Marker file is locked." << LL_ENDL; - return true; - } - if (apr_file_lock(fMarker, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS) //flock(fileno(fMarker), LOCK_EX | LOCK_NB) == -1) - { - LL_INFOS("MarkerFile") << "Marker file is locked." << LL_ENDL; - return true; - } - // No other instances; we'll lock this file now & delete on quit. + LL_WARNS_ONCE("MarkerFile") << "Version length ("<< marker_version.length()<< ")" + << " greater than maximum (" << MAX_MARKER_LENGTH << ")" + << ": marker matching may be incorrect" + << LL_ENDL; } - LL_DEBUGS("MarkerFile") << "Marker file isn't locked." << LL_ENDL; - return false; + + // record the viewer version in the marker file + marker_file.write(marker_version.data(), marker_version.length()); } -void LLAppViewer::initMarkerFile() +bool LLAppViewer::markerIsSameVersion(const std::string& marker_name) const { - //First, check for the existence of other files. - //There are marker files for two different types of crashes - - mMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,MARKER_FILE_NAME); - LL_DEBUGS("MarkerFile") << "Checking marker file for lock..." << LL_ENDL; + bool sameVersion = false; + std::string my_version(LLVersionInfo::getChannelAndVersion()); + char marker_version[MAX_MARKER_LENGTH]; + + LLAPRFile marker_file; + marker_file.open(marker_name, LL_APR_RB); + if (marker_file.getFileHandle()) + { + S32 marker_version_length = marker_file.read(marker_version, sizeof(marker_version)); + std::string marker_string(marker_version, marker_version_length); + if ( 0 == my_version.compare( 0, my_version.length(), marker_version, 0, marker_version_length ) ) + { + sameVersion = true; + } + LL_DEBUGS("MarkerFile") << "Compare markers for '" << marker_name << "': " + << "\n mine '" << my_version << "'" + << "\n marker '" << marker_string << "'" + << "\n " << ( sameVersion ? "same" : "different" ) << " version" + << LL_ENDL; + marker_file.close(); + } + return sameVersion; +} + +void LLAppViewer::processMarkerFiles() +{ //We've got 4 things to test for here - // - Other Process Running (Singularity.exec_marker present, locked) - // - Freeze (Singularity.exec_marker present, not locked) - // - LLError Crash (Singularity.llerror_marker present) - // - Other Crash (Singularity.error_marker present) + // - Other Process Running (SecondLife.exec_marker present, locked) + // - Freeze (SecondLife.exec_marker present, not locked) + // - LLError Crash (SecondLife.llerror_marker present) + // - Other Crash (SecondLife.error_marker present) // These checks should also remove these files for the last 2 cases if they currently exist - //LLError/Error checks. Only one of these should ever happen at a time. - std::string logout_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LOGOUT_MARKER_FILE_NAME); - std::string llerror_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LLERROR_MARKER_FILE_NAME); - std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME); + bool marker_is_same_version = true; + // first, look for the marker created at startup and deleted on a clean exit + mMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,MARKER_FILE_NAME); + if (LLAPRFile::isExist(mMarkerFileName, LL_APR_RB)) + { + // File exists... + // first, read it to see if it was created by the same version (we need this later) + marker_is_same_version = markerIsSameVersion(mMarkerFileName); - if (LLAPRFile::isExist(mMarkerFileName, LL_APR_RB) && !anotherInstanceRunning()) - { - gLastExecEvent = LAST_EXEC_FROZE; - LL_INFOS("MarkerFile") << "Exec marker found: program froze on previous execution" << LL_ENDL; - } - if(LLAPRFile::isExist(logout_marker_file, LL_APR_RB)) - { - gLastExecEvent = LAST_EXEC_LOGOUT_FROZE; - LL_INFOS("MarkerFile") << "Last exec LLError crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL; - LLAPRFile::remove(logout_marker_file); - } - if(LLAPRFile::isExist(llerror_marker_file, LL_APR_RB)) - { - LL_INFOS() << "Last exec LLError crashed, setting LastExecEvent to " << LAST_EXEC_LLERROR_CRASH << LL_ENDL; - if(gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) gLastExecEvent = LAST_EXEC_LOGOUT_CRASH; - else gLastExecEvent = LAST_EXEC_LLERROR_CRASH; - LL_INFOS("MarkerFile") << "Last exec LLError crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL; - LLAPRFile::remove(llerror_marker_file); - } - if(LLAPRFile::isExist(error_marker_file, LL_APR_RB)) - { - LL_INFOS("MarkerFile") << "Last exec crashed, setting LastExecEvent to " << LAST_EXEC_OTHER_CRASH << LL_ENDL; - if(gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) gLastExecEvent = LAST_EXEC_LOGOUT_CRASH; - else gLastExecEvent = LAST_EXEC_OTHER_CRASH; - LL_INFOS("MarkerFile") << "Last exec crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL; - LLAPRFile::remove(error_marker_file); - } - - // No new markers if another instance is running. - if(anotherInstanceRunning()) - { - return; - } - - // Create the marker file for this execution & lock it - apr_status_t s; - s = mMarkerFile.open(mMarkerFileName, LL_APR_W, LLAPRFile::long_lived); - - if (s == APR_SUCCESS && mMarkerFile.getFileHandle()) - { - LL_DEBUGS("MarkerFile") << "Marker file created." << LL_ENDL; - } - else - { - LL_INFOS("MarkerFile") << "Failed to create marker file." << LL_ENDL; - return; - } - if (apr_file_lock(mMarkerFile.getFileHandle(), APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS) - { - mMarkerFile.close() ; - LL_INFOS("MarkerFile") << "Marker file cannot be locked." << LL_ENDL; - return; - } - - LL_DEBUGS("MarkerFile") << "Marker file locked." << LL_ENDL; -} - -void LLAppViewer::removeMarkerFile(bool leave_logout_marker) -{ - LL_DEBUGS("MarkerFile") << "removeMarkerFile()" << LL_ENDL; - if (mMarkerFile.getFileHandle()) - { - mMarkerFile.close() ; - LLAPRFile::remove( mMarkerFileName ); - } - if (mLogoutMarkerFile != NULL) - { - if(!leave_logout_marker) + // now test to see if this file is locked by a running process (try to open for write) + LL_DEBUGS("MarkerFile") << "Checking exec marker file for lock..." << LL_ENDL; + mMarkerFile.open(mMarkerFileName, LL_APR_WB); + apr_file_t* fMarker = mMarkerFile.getFileHandle() ; + if (!fMarker) { - LLAPRFile::remove( mLogoutMarkerFileName ); - mLogoutMarkerFile = NULL; + LL_INFOS("MarkerFile") << "Exec marker file open failed - assume it is locked." << LL_ENDL; + mSecondInstance = true; // lock means that instance is running. } else { - LL_WARNS("MarkerFile") << "leaving markers because this is a second instance" << LL_ENDL; + // We were able to open it, now try to lock it ourselves... + if (apr_file_lock(fMarker, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS) + { + LL_WARNS_ONCE("MarkerFile") << "Locking exec marker failed." << LL_ENDL; + mSecondInstance = true; // lost a race? be conservative + } + else + { + // No other instances; we've locked this file now, so record our version; delete on quit. + recordMarkerVersion(mMarkerFile); + LL_DEBUGS("MarkerFile") << "Exec marker file existed but was not locked; rewritten." << LL_ENDL; + } } + + if (mSecondInstance) + { + LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' owned by another instance" << LL_ENDL; + } + else if (marker_is_same_version) + { + // the file existed, is ours, and matched our version, so we can report on what it says + LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found; last exec FROZE" << LL_ENDL; + gLastExecEvent = LAST_EXEC_FROZE; + + } + else + { + LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found, but versions did not match" << LL_ENDL; + } + } + else // marker did not exist... last exec (if any) did not freeze + { + // Create the marker file for this execution & lock it; it will be deleted on a clean exit + apr_status_t s; + s = mMarkerFile.open(mMarkerFileName, LL_APR_WB, TRUE); + + if (s == APR_SUCCESS && mMarkerFile.getFileHandle()) + { + LL_DEBUGS("MarkerFile") << "Exec marker file '"<< mMarkerFileName << "' created." << LL_ENDL; + if (APR_SUCCESS == apr_file_lock(mMarkerFile.getFileHandle(), APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE)) + { + recordMarkerVersion(mMarkerFile); + LL_DEBUGS("MarkerFile") << "Exec marker file locked." << LL_ENDL; + } + else + { + LL_WARNS("MarkerFile") << "Exec marker file cannot be locked." << LL_ENDL; + } + } + else + { + LL_WARNS("MarkerFile") << "Failed to create exec marker file '"<< mMarkerFileName << "'." << LL_ENDL; + } + } + + // now check for cases in which the exec marker may have been cleaned up by crash handlers + + // check for any last exec event report based on whether or not it happened during logout + // (the logout marker is created when logout begins) + std::string logout_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LOGOUT_MARKER_FILE_NAME); + if(LLAPRFile::isExist(logout_marker_file, LL_APR_RB)) + { + if (markerIsSameVersion(logout_marker_file)) + { + gLastExecEvent = LAST_EXEC_LOGOUT_FROZE; + LL_INFOS("MarkerFile") << "Logout crash marker '"<< logout_marker_file << "', changing LastExecEvent to LOGOUT_FROZE" << LL_ENDL; + } + else + { + LL_INFOS("MarkerFile") << "Logout crash marker '"<< logout_marker_file << "' found, but versions did not match" << LL_ENDL; + } + LLAPRFile::remove(logout_marker_file); + } + // further refine based on whether or not a marker created during an llerr crash is found + std::string llerror_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LLERROR_MARKER_FILE_NAME); + if(LLAPRFile::isExist(llerror_marker_file, LL_APR_RB)) + { + if (markerIsSameVersion(llerror_marker_file)) + { + if ( gLastExecEvent == LAST_EXEC_LOGOUT_FROZE ) + { + gLastExecEvent = LAST_EXEC_LOGOUT_CRASH; + LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' crashed, setting LastExecEvent to LOGOUT_CRASH" << LL_ENDL; + } + else + { + gLastExecEvent = LAST_EXEC_LLERROR_CRASH; + LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' crashed, setting LastExecEvent to LLERROR_CRASH" << LL_ENDL; + } + } + else + { + LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' found, but versions did not match" << LL_ENDL; + } + LLAPRFile::remove(llerror_marker_file); + } + // and last refine based on whether or not a marker created during a non-llerr crash is found + std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME); + if(LLAPRFile::isExist(error_marker_file, LL_APR_RB)) + { + if (markerIsSameVersion(error_marker_file)) + { + if (gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) + { + gLastExecEvent = LAST_EXEC_LOGOUT_CRASH; + LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to LOGOUT_CRASH" << LL_ENDL; + } + else + { + gLastExecEvent = LAST_EXEC_OTHER_CRASH; + LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL; + } + } + else + { + LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' marker found, but versions did not match" << LL_ENDL; + } + LLAPRFile::remove(error_marker_file); + } +} + +void LLAppViewer::removeMarkerFiles() +{ + if (!mSecondInstance) + { + if (mMarkerFile.getFileHandle()) + { + mMarkerFile.close() ; + LLAPRFile::remove( mMarkerFileName ); + LL_DEBUGS("MarkerFile") << "removed exec marker '"<getExpandedFilename(LL_PATH_DUMP, ""); gDirUtilp->deleteDirAndContents(dump_dir); +#endif } void LLAppViewer::forceQuit() @@ -3050,7 +3284,7 @@ void LLAppViewer::fastQuit(S32 error_code) // figure out the error code S32 final_error_code = error_code ? error_code : (S32)isError(); // this isn't a crash - removeMarkerFile(); + removeMarkerFiles(); // get outta here _exit(final_error_code); } @@ -3171,8 +3405,7 @@ void LLAppViewer::migrateCacheDirectory() { gSavedSettings.setBOOL("MigrateCacheDirectory", FALSE); - std::string delimiter = gDirUtilp->getDirDelimiter(); - std::string old_cache_dir = gDirUtilp->getOSUserAppDir() + delimiter + "cache"; + std::string old_cache_dir = gDirUtilp->add(gDirUtilp->getOSUserAppDir(), "cache"); std::string new_cache_dir = gDirUtilp->getCacheDir(true); if (gDirUtilp->fileExists(old_cache_dir)) @@ -3188,8 +3421,8 @@ void LLAppViewer::migrateCacheDirectory() while (iter.next(file_name)) { if (file_name == "." || file_name == "..") continue; - std::string source_path = old_cache_dir + delimiter + file_name; - std::string dest_path = new_cache_dir + delimiter + file_name; + std::string source_path = gDirUtilp->add(old_cache_dir, file_name); + std::string dest_path = gDirUtilp->add(new_cache_dir, file_name); if (!LLFile::rename(source_path, dest_path)) { file_count++; @@ -3239,6 +3472,7 @@ void dumpVFSCaches() gStaticVFS->dumpFiles(); SetCurrentDirectory(w_str); #endif + LL_INFOS() << "========= Dynamic VFS ====" << LL_ENDL; gVFS->listFiles(); #if LL_WINDOWS @@ -3299,6 +3533,7 @@ bool LLAppViewer::initCache() if (gSavedSettings.getBOOL("PurgeCacheOnStartup") || gSavedSettings.getBOOL("PurgeCacheOnNextStartup")) { + LL_INFOS("AppCache") << "Startup cache purge requested: " << (gSavedSettings.getBOOL("PurgeCacheOnStartup") ? "ALWAYS" : "ONCE") << LL_ENDL; gSavedSettings.setBOOL("PurgeCacheOnNextStartup", false); mPurgeCache = true; // STORM-1141 force purgeAllTextures to get called to prevent a crash here. -brad @@ -3314,6 +3549,7 @@ bool LLAppViewer::initCache() std::string new_cache_location = gSavedSettings.getString("NewCacheLocation"); if (new_cache_location != cache_location) { + LL_INFOS("AppCache") << "Cache location changed, cache needs purging" << LL_ENDL; gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation")); purgeCache(); // purge old cache gSavedSettings.setString("CacheLocation", new_cache_location); @@ -3341,6 +3577,7 @@ bool LLAppViewer::initCache() std::random_device rnddev; std::mt19937 rng(rnddev()); std::uniform_int_distribution<> dist(0, 4); + LLSplashScreen::update(LLTrans::getString( llformat("StartupInitializingTextureCache%d", dist(rng)))); } @@ -3385,7 +3622,7 @@ bool LLAppViewer::initCache() // This has to happen BEFORE starting the vfs // time_t ltime; - srand(time(NULL)); // Flawfinder: ignore + srand(time(nullptr)); // Flawfinder: ignore U32 old_salt = gSavedSettings.getU32("VFSSalt"); U32 new_salt; std::string old_vfs_data_file; @@ -3427,10 +3664,10 @@ bool LLAppViewer::initCache() LLDirIterator iter(dir, mask); if (iter.next(found_file)) { - old_vfs_data_file = dir + gDirUtilp->getDirDelimiter() + found_file; + old_vfs_data_file = gDirUtilp->add(dir, found_file); - S32 start_pos = found_file.find_last_of('.'); - if (start_pos > 0) + size_t start_pos = found_file.find_last_of('.'); + if (start_pos != std::string::npos && start_pos != 0) { sscanf(found_file.substr(start_pos+1).c_str(), "%d", &old_salt); } @@ -3537,9 +3774,9 @@ void LLAppViewer::purgeCache() gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), mask); } -const std::string& LLAppViewer::getSecondLifeTitle() const +std::string LLAppViewer::getSecondLifeTitle() const { - return gSecondLife; + return LLTrans::getString("APP_NAME"); } const std::string& LLAppViewer::getWindowTitle() const @@ -3576,9 +3813,9 @@ void LLAppViewer::forceDisconnect(const std::string& mesg) return; } - // Translate the message if possible + // *TODO: Translate the message if possible std::string big_reason = LLAgent::sTeleportErrorMessages[mesg]; - if ( big_reason.size() == 0 ) + if (big_reason.empty()) { big_reason = mesg; } @@ -3609,26 +3846,25 @@ void LLAppViewer::badNetworkHandler() mPurgeOnExit = TRUE; - std::string grid_support_msg = ""; - if (!gHippoGridManager->getCurrentGrid()->getSupportUrl().empty()) - { - grid_support_msg = "\n\nOr visit the grid support page at: \n " - + gHippoGridManager->getCurrentGrid()->getSupportUrl(); - } std::ostringstream message; message << "The viewer has detected mangled network data indicative\n" "of a bad upstream network connection or an incomplete\n" - "local installation of " << gSecondLife << ". \n" + "local installation of " << LLAppViewer::instance()->getSecondLifeTitle() << ". \n" " \n" "Try uninstalling and reinstalling to see if this resolves \n" "the issue. \n" " \n" "If the problem continues, please report the issue at: \n" - "http://www.singularityviewer.org" << grid_support_msg; + "http://www.singularityviewer.org"; + + if (!gHippoGridManager->getCurrentGrid()->getSupportUrl().empty()) + { + message << "\n\nOr visit the grid support page at: \n" + << gHippoGridManager->getCurrentGrid()->getSupportUrl(); + } + forceDisconnect(message.str()); - - LLApp::instance()->writeMiniDump(); } // This routine may get called more than once during the shutdown process. @@ -3659,11 +3895,11 @@ void LLAppViewer::saveFinalSnapshot() void LLAppViewer::loadNameCache() { - // Phoenix: Wolfspirit: Loads the Display Name Cache. And set if we are using Display Names. + // display names cache std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml"); LL_INFOS("AvNameCache") << filename << LL_ENDL; - llifstream name_cache_stream(filename); + llifstream name_cache_stream(filename.c_str()); if(name_cache_stream.is_open()) { LLAvatarNameCache::importFile(name_cache_stream); @@ -3673,7 +3909,7 @@ void LLAppViewer::loadNameCache() std::string name_cache; name_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "name.cache"); - llifstream cache_file(name_cache); + llifstream cache_file(name_cache.c_str()); if(cache_file.is_open()) { if(gCacheName->importFile(cache_file)) return; @@ -3682,26 +3918,29 @@ void LLAppViewer::loadNameCache() void LLAppViewer::saveNameCache() { - // Phoenix: Wolfspirit: Saves the Display Name Cache. + // display names cache std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml"); - llofstream name_cache_stream(filename); + llofstream name_cache_stream(filename.c_str()); if(name_cache_stream.is_open()) { LLAvatarNameCache::exportFile(name_cache_stream); } - if (!gCacheName) return; - - std::string name_cache; - name_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "name.cache"); - llofstream cache_file(name_cache); - if(cache_file.is_open()) - { - gCacheName->exportFile(cache_file); + // real names cache + if (gCacheName) + { + std::string name_cache; + name_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "name.cache"); + llofstream cache_file(name_cache.c_str()); + if(cache_file.is_open()) + { + gCacheName->exportFile(cache_file); + } } } + /*! @brief This class is an LLFrameTimer that can be created with an elapsed time that starts counting up from the given value rather than 0.0. @@ -3781,11 +4020,12 @@ void LLAppViewer::idle() // Smoothly weight toward current frame gFPSClamped = (frame_rate_clamped + (4.f * gFPSClamped)) / 5.f; - F32 qas = gSavedSettings.getF32("QuitAfterSeconds"); + static LLCachedControl qas(gSavedSettings, "QuitAfterSeconds"); if (qas > 0.f) { if (gRenderStartTime.getElapsedTimeF32() > qas) { + LL_INFOS() << "Quitting after " << qas << " seconds. See setting \"QuitAfterSeconds\"." << LL_ENDL; LLAppViewer::instance()->forceQuit(); } } @@ -3842,7 +4082,8 @@ void LLAppViewer::idle() // Update simulator agent state // - if (gSavedSettings.getBOOL("RotateRight")) + static LLCachedControl rotateRight(gSavedSettings, "RotateRight"); + if (rotateRight) { gAgent.moveYaw(-1.f); } @@ -3859,7 +4100,8 @@ void LLAppViewer::idle() // When appropriate, update agent location to the simulator. F32 agent_update_time = agent_update_timer.getElapsedTimeF32(); - BOOL flags_changed = gAgent.controlFlagsDirty() || (last_control_flags != gAgent.getControlFlags()); + BOOL flags_changed = gAgent.controlFlagsDirty() + || (last_control_flags != gAgent.getControlFlags()); if (flags_changed || (agent_update_time > (1.0f / (F32)AGENT_UPDATES_PER_SECOND))) { @@ -3885,7 +4127,7 @@ void LLAppViewer::idle() reset_statistics(); // Update session stats every large chunk of time - // *FIX: (???) SAMANTHA + // *FIX: (?) SAMANTHA if (viewer_stats_timer.getElapsedTimeF32() >= SEND_STATS_PERIOD && !gDisconnected) { LL_INFOS() << "Transmitting sessions stats" << LL_ENDL; @@ -4304,13 +4546,11 @@ void LLAppViewer::sendLogoutRequest() //Set internal status variables and marker files gLogoutInProgress = TRUE; mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LOGOUT_MARKER_FILE_NAME); - - LLAPRFile outfile(mLogoutMarkerFileName, LL_APR_W); - mLogoutMarkerFile = outfile.getFileHandle() ; - if (mLogoutMarkerFile) + + if (mLogoutMarkerFile.open(mLogoutMarkerFileName, LL_APR_W) == APR_SUCCESS) { LL_INFOS() << "Created logout marker file " << mLogoutMarkerFileName << LL_ENDL; - apr_file_close(mLogoutMarkerFile); + mLogoutMarkerFile.close(); } else { @@ -4632,26 +4872,31 @@ void LLAppViewer::disconnectViewer() void LLAppViewer::forceErrorLLError() { - LL_ERRS() << "This is an llerror" << LL_ENDL; + LL_ERRS() << "This is a deliberate llerror" << LL_ENDL; } void LLAppViewer::forceErrorBreakpoint() { + LL_WARNS() << "Forcing a deliberate breakpoint" << LL_ENDL; #ifdef LL_WINDOWS DebugBreak(); +#else + asm ("int $3"); #endif return; } void LLAppViewer::forceErrorBadMemoryAccess() { - S32* crash = NULL; + LL_WARNS() << "Forcing a deliberate bad memory access" << LL_ENDL; + S32* crash = nullptr; *crash = 0xDEADBEEF; return; } void LLAppViewer::forceErrorInfiniteLoop() { + LL_WARNS() << "Forcing a deliberate infinite loop" << LL_ENDL; while(true) { ; @@ -4661,13 +4906,15 @@ void LLAppViewer::forceErrorInfiniteLoop() void LLAppViewer::forceErrorSoftwareException() { + LL_WARNS() << "Forcing a deliberate exception" << LL_ENDL; // *FIX: Any way to insure it won't be handled? throw; } void LLAppViewer::forceErrorDriverCrash() { - glDeleteTextures(1, NULL); + LL_WARNS() << "Forcing a deliberate driver crash" << LL_ENDL; + glDeleteTextures(1, nullptr); } void LLAppViewer::initMainloopTimeout(const std::string& state, F32 secs) @@ -4684,7 +4931,7 @@ void LLAppViewer::destroyMainloopTimeout() if(mMainloopTimeout) { delete mMainloopTimeout; - mMainloopTimeout = NULL; + mMainloopTimeout = nullptr; } } diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index e646aa2b5..9644fbe08 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -76,6 +76,7 @@ public: bool quitRequested() { return mQuitRequested; } bool logoutRequestSent() { return mLogoutRequestSent; } + bool isSecondInstance() { return mSecondInstance; } void writeDebugInfo(bool isStatic=true); @@ -86,7 +87,7 @@ public: virtual bool restoreErrorTrap() = 0; // Require platform specific override to reset error handling mechanism. // return false if the error trap needed restoration. - virtual void initCrashReporting(bool reportFreeze = false) = 0; // What to do with crash report? + void initCrashReporting(); // What to do with crash report? static void handleViewerCrash(); // Hey! The viewer crashed. Do this, soon. // Thread accessors @@ -101,7 +102,7 @@ public: bool getPurgeCache() const { return mPurgeCache; } - const std::string& getSecondLifeTitle() const; // The Second Life title. + std::string getSecondLifeTitle() const; // The Second Life title. const std::string& getWindowTitle() const; // The window display name. void forceDisconnect(const std::string& msg); // Force disconnection, with a message to the user. @@ -113,7 +114,7 @@ public: void loadNameCache(); void saveNameCache(); - void removeMarkerFile(bool leave_logout_marker = false); + void removeMarkerFiles(); void removeDumpDir(); // LLAppViewer testing helpers. @@ -125,14 +126,13 @@ public: virtual void forceErrorSoftwareException(); virtual void forceErrorDriverCrash(); - // *NOTE: There are currently 3 settings files: - // "Global", "PerAccount" and "CrashSettings" + // *NOTE: There are currently 2 settings files: + // "Global", and "PerAccount" // The list is found in app_settings/settings_files.xml // but since they are used explicitly in code, // the follow consts should also do the trick. static const std::string sGlobalSettingsName; static const std::string sPerAccountSettingsName; - static const std::string sCrashSettingsName; // Load settings from the location specified by loction_key. // Key availale and rules for loading, are specified in @@ -158,6 +158,7 @@ public: void handleLoginComplete(); LLAllocator & getAllocator() { return mAlloc; } + // On LoginCompleted callback typedef boost::signals2::signal login_completed_signal_t; login_completed_signal_t mOnLoginCompleted; @@ -172,7 +173,8 @@ public: static void metricsSend(bool enable_reporting); protected: virtual bool initWindow(); // Initialize the viewer's window. - virtual bool initLogging(); // Initialize log files, logging system, return false on failure. + virtual void initLoggingAndGetLastDuration(); // Initialize log files, logging system + void initLoggingInternal(); virtual void initConsole() {}; // Initialize OS level debugging console. virtual bool initHardwareTest() { return true; } // A false result indicates the app should quit. virtual bool initSLURLHandler(); @@ -189,7 +191,6 @@ private: void initMaxHeapSize(); bool initThreads(); // Initialize viewer threads, return false on failure. bool initConfiguration(); // Initialize settings from the command line/config file. - bool initCache(); // Initialize local client cache. void checkMemory() ; @@ -202,8 +203,9 @@ private: void writeSystemInfo(); // Write system info to "debug_info.log" - bool anotherInstanceRunning(); - void initMarkerFile(); + void processMarkerFiles(); + static void recordMarkerVersion(LLAPRFile& marker_file); + bool markerIsSameVersion(const std::string& marker_name) const; void idle(); void idleShutdown(); @@ -226,8 +228,7 @@ private: LLAPRFile mMarkerFile; // A file created to indicate the app is running. std::string mLogoutMarkerFileName; - apr_file_t* mLogoutMarkerFile; // A file created to indicate the app is running. - + LLAPRFile mLogoutMarkerFile; // A file created to indicate the app is running. LLOSInfo mSysOSInfo; bool mReportedCrash; diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index 764d36e4d..0f2957bc9 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -119,7 +119,6 @@ int main( int argc, char **argv ) } delete viewer_app_ptr; viewer_app_ptr = NULL; - return 0; } @@ -143,20 +142,12 @@ bool LLAppViewerLinux::init() bool success = LLAppViewer::init(); -#if LL_SEND_CRASH_REPORTS - if (success) - { - LLAppViewer* pApp = LLAppViewer::instance(); - pApp->initCrashReporting(); - } -#endif - return success; } bool LLAppViewerLinux::restoreErrorTrap() { - // *NOTE:Mani there is a case for implementing this or the mac. + // *NOTE:Mani there is a case for implementing this on the mac. // Linux doesn't need it to my knowledge. return true; } @@ -347,12 +338,6 @@ bool LLAppViewerLinux::sendURLToOtherInstance(const std::string& url) } #endif // LL_DBUS_ENABLED -void LLAppViewerLinux::initCrashReporting(bool reportFreeze) -{ - // Singu Note: this is where original code forks crash logger process. - // Singularity doesn't need it -} - bool LLAppViewerLinux::beingDebugged() { static enum {unknown, no, yes} debugged = unknown; @@ -397,7 +382,7 @@ bool LLAppViewerLinux::beingDebugged() #endif } -bool LLAppViewerLinux::initLogging() +void LLAppViewerLinux::initLoggingAndGetLastDuration() { // Remove the last stack trace, if any // This file is no longer created, since the move to Google Breakpad @@ -406,7 +391,7 @@ bool LLAppViewerLinux::initLogging() gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log"); LLFile::remove(old_stack_file); - return LLAppViewer::initLogging(); + LLAppViewer::initLoggingAndGetLastDuration(); } bool LLAppViewerLinux::initParseCommandLine(LLCommandLineParser& clp) diff --git a/indra/newview/llappviewerlinux.h b/indra/newview/llappviewerlinux.h index 6de13b81c..6c4020c4c 100644 --- a/indra/newview/llappviewerlinux.h +++ b/indra/newview/llappviewerlinux.h @@ -64,9 +64,8 @@ protected: virtual bool beingDebugged(); virtual bool restoreErrorTrap(); - virtual void initCrashReporting(bool reportFreeze); - virtual bool initLogging(); + virtual void initLoggingAndGetLastDuration(); virtual bool initParseCommandLine(LLCommandLineParser& clp); virtual bool initSLURLHandler(); diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 300480634..d4eef2b2b 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -260,12 +260,6 @@ bool LLAppViewerMacOSX::restoreErrorTrap() return reset_count == 0; } -void LLAppViewerMacOSX::initCrashReporting(bool reportFreeze) -{ - // Singu Note: this is where original code forks crash logger process. - // Singularity doesn't need it -} - std::string LLAppViewerMacOSX::generateSerialNumber() { char serial_md5[MD5HEX_STR_SIZE]; // Flawfinder: ignore diff --git a/indra/newview/llappviewermacosx.h b/indra/newview/llappviewermacosx.h index e94b297be..69d069d01 100644 --- a/indra/newview/llappviewermacosx.h +++ b/indra/newview/llappviewermacosx.h @@ -51,7 +51,6 @@ public: protected: virtual bool restoreErrorTrap(); - virtual void initCrashReporting(bool reportFreeze); std::string generateSerialNumber(); virtual bool initParseCommandLine(LLCommandLineParser& clp); diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 9ca2feeb6..3dc530a57 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -32,12 +32,6 @@ #include "llviewerprecompiledheaders.h" -#if defined(_DEBUG) -# if _MSC_VER >= 1400 // Visual C++ 2005 or later -# define WINDOWS_CRT_MEM_CHECKS 1 -# endif -#endif - #include "llwindowwin32.h" // *FIX: for setting gIconResource. #include "llappviewerwin32.h" @@ -73,19 +67,6 @@ #include "llcommandlineparser.h" #include "lltrans.h" -// *FIX:Mani - This hack is to fix a linker issue with libndofdev.lib -// The lib was compiled under VS2005 - in VS2003 we need to remap assert -#ifdef LL_DEBUG -#ifdef LL_MSVC7 -extern "C" { - void _wassert(const wchar_t * _Message, const wchar_t *_File, unsigned _Line) - { - LL_ERRS() << _Message << LL_ENDL; - } -} -#endif -#endif - const std::string LLAppViewerWin32::sWindowClass = "Second Life"; // Create app mutex creates a unique global windows object. @@ -101,7 +82,7 @@ bool create_app_mutex() bool result = true; LPCWSTR unique_mutex_name = L"SecondLifeAppMutex"; HANDLE hMutex; - hMutex = CreateMutex(NULL, TRUE, unique_mutex_name); + hMutex = CreateMutex(nullptr, TRUE, unique_mutex_name); if(GetLastError() == ERROR_ALREADY_EXISTS) { result = false; @@ -240,7 +221,9 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, LLAppViewerWin32* viewer_app_ptr = new LLAppViewerWin32(lpCmdLine); +#if !defined(USE_CRASHPAD) viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash); +#endif // Set a debug info flag to indicate if multiple instances are running. bool found_other_instance = !create_app_mutex(); @@ -332,7 +315,7 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, } delete viewer_app_ptr; - viewer_app_ptr = NULL; + viewer_app_ptr = nullptr; //start updater if(LLAppViewer::sUpdaterInfo) @@ -392,13 +375,13 @@ void LLAppViewerWin32::disableWinErrorReporting() const S32 MAX_CONSOLE_LINES = 500; -void create_console() +static bool create_console() { CONSOLE_SCREEN_BUFFER_INFO coninfo; // allocate a console for this app - AllocConsole(); + const bool isConsoleAllocated = AllocConsole(); // set the screen buffer to be big enough to let us scroll text GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo); @@ -410,16 +393,16 @@ void create_console() freopen("CONOUT$", "w", stdout); freopen("CONOUT$", "w", stderr); - setvbuf( stdin, NULL, _IONBF, 0 ); - setvbuf( stdout, NULL, _IONBF, 0 ); - setvbuf( stderr, NULL, _IONBF, 0 ); - + setvbuf( stdin, nullptr, _IONBF, 0 ); + setvbuf( stdout, nullptr, _IONBF, 0 ); + setvbuf( stderr, nullptr, _IONBF, 0 ); + return isConsoleAllocated; } - LLAppViewerWin32::LLAppViewerWin32(const char* cmd_line) : - mCmdLine(cmd_line) + mCmdLine(cmd_line), + mIsConsoleAllocated(false) { } @@ -442,15 +425,6 @@ bool LLAppViewerWin32::init() LLWinDebug::instance().init(); #endif -#if LL_WINDOWS -#if LL_SEND_CRASH_REPORTS - - LLAppViewer* pApp = LLAppViewer::instance(); - pApp->initCrashReporting(); - -#endif -#endif - bool success = LLAppViewer::init(); return success; @@ -462,18 +436,24 @@ bool LLAppViewerWin32::cleanup() gDXHardware.cleanup(); + if (mIsConsoleAllocated) + { + FreeConsole(); + mIsConsoleAllocated = false; + } + return result; } -bool LLAppViewerWin32::initLogging() +void LLAppViewerWin32::initLoggingAndGetLastDuration() { - return LLAppViewer::initLogging(); + LLAppViewer::initLoggingAndGetLastDuration(); } void LLAppViewerWin32::initConsole() { // pop up debug console - create_console(); + mIsConsoleAllocated = create_console(); return LLAppViewer::initConsole(); } @@ -571,7 +551,7 @@ bool LLAppViewerWin32::initParseCommandLine(LLCommandLineParser& clp) } // Find the system language. - FL_Locale *locale = NULL; + FL_Locale *locale = nullptr; FL_Success success = FL_FindLocale(&locale, FL_MESSAGES); if (success != 0) { @@ -595,12 +575,6 @@ bool LLAppViewerWin32::initParseCommandLine(LLCommandLineParser& clp) bool LLAppViewerWin32::restoreErrorTrap() { return true; - //return LLWinDebug::checkExceptionHandler(); -} - -void LLAppViewerWin32::initCrashReporting(bool reportFreeze) -{ - // Singu Note: we don't fork the crash logger on start } //virtual @@ -610,9 +584,9 @@ bool LLAppViewerWin32::sendURLToOtherInstance(const std::string& url) mbstowcs(window_class, sWindowClass.c_str(), 255); window_class[255] = 0; // Use the class instead of the window name. - HWND other_window = FindWindow(window_class, NULL); + HWND other_window = FindWindow(window_class, nullptr); - if (other_window != NULL) + if (other_window != nullptr) { LL_DEBUGS() << "Found other window with the name '" << getWindowTitle() << "'" << LL_ENDL; COPYDATASTRUCT cds; @@ -638,13 +612,13 @@ std::string LLAppViewerWin32::generateSerialNumber() DWORD serial = 0; DWORD flags = 0; BOOL success = GetVolumeInformation( - L"C:\\", - NULL, // volume name buffer + TEXT("C:\\"), + nullptr, // volume name buffer 0, // volume name buffer size &serial, // volume serial - NULL, // max component length + nullptr, // max component length &flags, // file system flags - NULL, // file system name buffer + nullptr, // file system name buffer 0); // file system name buffer size if (success) { diff --git a/indra/newview/llappviewerwin32.h b/indra/newview/llappviewerwin32.h index 757f6ea0c..96f834798 100644 --- a/indra/newview/llappviewerwin32.h +++ b/indra/newview/llappviewerwin32.h @@ -46,22 +46,20 @@ public: // // Main application logic // - virtual bool init(); // Override to do application initialization - virtual bool cleanup(); + bool init() override; // Override to do application initialization + bool cleanup() override; protected: - virtual bool initLogging(); // Override to clean stack_trace info. - virtual void initConsole(); // Initialize OS level debugging console. - virtual bool initHardwareTest(); // Win32 uses DX9 to test hardware. - virtual bool initParseCommandLine(LLCommandLineParser& clp); + void initLoggingAndGetLastDuration() override; // Override to clean stack_trace info. + void initConsole() override; // Initialize OS level debugging console. + bool initHardwareTest() override; // Win32 uses DX9 to test hardware. + bool initParseCommandLine(LLCommandLineParser& clp) override; - virtual bool restoreErrorTrap(); - virtual void initCrashReporting(bool reportFreeze); + bool restoreErrorTrap() override; - virtual bool sendURLToOtherInstance(const std::string& url); - - std::string generateSerialNumber(); + bool sendURLToOtherInstance(const std::string& url) override; + std::string generateSerialNumber() override; static const std::string sWindowClass; @@ -69,6 +67,7 @@ private: void disableWinErrorReporting(); std::string mCmdLine; + bool mIsConsoleAllocated; }; #endif // LL_LLAPPVIEWERWIN32_H diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index cb914859f..cfe688689 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -745,6 +745,7 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id, // Use display name only because this user is your friend LLSD args; args["NAME"] = av_name.getNSName(friend_name_system()); + args["ID"] = agent_id; args["STATUS"] = online ? LLTrans::getString("OnlineStatus") : LLTrans::getString("OfflineStatus"); // Popup a notify box with online status of this agent diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index ee5170721..fce835651 100644 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -470,7 +470,7 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id, std::string text = LLTrans::getString("CompileQueueProblemUploading"); LLChat chat(text); LLFloaterChat::addChat(chat); - buffer = text + LLTrans::getString(":") + " " + data->mScriptName; + buffer = text + LLTrans::getString(":") + ' ' + data->mScriptName; LL_WARNS() << "Problem uploading script asset." << LL_ENDL; if(queue) queue->removeItemByItemID(data->mItemId); } @@ -485,18 +485,18 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id, LLChat chat(LLTrans::getString("CompileQueueScriptNotFound")); LLFloaterChat::addChat(chat); - buffer = LLTrans::getString("CompileQueueProblemDownloading") + LLTrans::getString(":") + " " + data->mScriptName; + buffer = LLTrans::getString("CompileQueueProblemDownloading") + LLTrans::getString(":") + ' ' + data->mScriptName; } else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) { LLChat chat(LLTrans::getString("CompileQueueInsufficientPermDownload")); LLFloaterChat::addChat(chat); - buffer = LLTrans::getString("CompileQueueInsufficientPermFor") + LLTrans::getString(":") + " " + data->mScriptName; + buffer = LLTrans::getString("CompileQueueInsufficientPermFor") + LLTrans::getString(":") + ' ' + data->mScriptName; } else { - buffer = LLTrans::getString("CompileQueueUnknownFailure") + (" ") + data->mScriptName; + buffer = LLTrans::getString("CompileQueueUnknownFailure") + ' ' + data->mScriptName; } LL_WARNS() << "Problem downloading script asset." << LL_ENDL; @@ -590,7 +590,7 @@ void LLFloaterResetQueue::handleInventory(LLViewerObject* viewer_obj, { LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it)); std::string buffer; - buffer = getString("Resetting") + LLTrans::getString(":") + " " + item->getName(); + buffer = getString("Resetting") + LLTrans::getString(":") + ' ' + item->getName(); getChild("queue output")->addSimpleElement(buffer, ADD_BOTTOM); LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_ScriptReset); @@ -650,7 +650,7 @@ void LLFloaterRunQueue::handleInventory(LLViewerObject* viewer_obj, LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it)); LLScrollListCtrl* list = getChild("queue output"); std::string buffer; - buffer = getString("Running") + LLTrans::getString(":") + " " + item->getName(); + buffer = getString("Running") + LLTrans::getString(":") + ' ' + item->getName(); list->addSimpleElement(buffer, ADD_BOTTOM); LLMessageSystem* msg = gMessageSystem; @@ -750,7 +750,7 @@ void LLFloaterNotRunQueue::handleInventory(LLViewerObject* viewer_obj, LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it)); LLScrollListCtrl* list = getChild("queue output"); std::string buffer; - buffer = getString("NotRunning") + LLTrans::getString(":") + " " + item->getName(); + buffer = getString("NotRunning") + LLTrans::getString(":") + ' ' + item->getName(); list->addSimpleElement(buffer, ADD_BOTTOM); LLMessageSystem* msg = gMessageSystem; diff --git a/indra/newview/llcrashlogger.cpp b/indra/newview/llcrashlogger.cpp deleted file mode 100644 index 6a6dfa861..000000000 --- a/indra/newview/llcrashlogger.cpp +++ /dev/null @@ -1,418 +0,0 @@ - /** -* @file llcrashlogger.cpp -* @brief Crash logger implementation -* -* $LicenseInfo:firstyear=2003&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 "llcrashlogger.h" -#include "linden_common.h" -#include "llstring.h" -#include "indra_constants.h" // CRASH_BEHAVIOR_... -#include "llerror.h" -#include "llerrorcontrol.h" -#include "lltimer.h" -#include "lldir.h" -#include "llfile.h" -#include "llsdserialize.h" -#include "lliopipe.h" -#include "llpumpio.h" -#include "llhttpclient.h" -#include "llsdserialize.h" -#include "llproxy.h" -#include "llwindow.h" -#include "lltrans.h" -#include "aistatemachine.h" -#include "boost/filesystem.hpp" - -class AIHTTPTimeoutPolicy; -extern AIHTTPTimeoutPolicy crashLoggerResponder_timeout; -extern const std::string OLD_LOG_FILE; - -class LLCrashLoggerResponder : public LLHTTPClient::ResponderWithResult -{ -public: - LLCrashLoggerResponder() - { - } - - virtual void httpFailure(void) - { - LL_WARNS() << "Crash report sending failed: " << mReason << LL_ENDL; - } - - virtual void httpSuccess(void) - { - std::string msg = "Crash report successfully sent"; - if (mContent.has("message")) - { - msg += ": " + mContent["message"].asString(); - } - LL_INFOS() << msg << LL_ENDL; - - if (mContent.has("report_id")) - { - gSavedSettings.setS32("CrashReportID", mContent["report_id"].asInteger()); - } - - } - - virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const - { - return crashLoggerResponder_timeout; - } - - virtual char const* getName(void) const - { - return "LLCrashLoggerResponder"; - } -}; - -LLCrashLogger::LLCrashLogger() : - mCrashBehavior(CRASH_BEHAVIOR_ALWAYS_SEND), - mCrashInPreviousExec(false), - mCrashHost("") -{ -} - -LLCrashLogger::~LLCrashLogger() -{ - -} - -// TRIM_SIZE must remain larger than LINE_SEARCH_SIZE. -const int TRIM_SIZE = 128000; -const int LINE_SEARCH_DIST = 500; -const std::string SKIP_TEXT = "\n ...Skipping... \n"; -void trimSLLog(std::string& sllog) -{ - if(sllog.length() > TRIM_SIZE * 2) - { - std::string::iterator head = sllog.begin() + TRIM_SIZE; - std::string::iterator tail = sllog.begin() + sllog.length() - TRIM_SIZE; - std::string::iterator new_head = std::find(head, head - LINE_SEARCH_DIST, '\n'); - if(new_head != head - LINE_SEARCH_DIST) - { - head = new_head; - } - - std::string::iterator new_tail = std::find(tail, tail + LINE_SEARCH_DIST, '\n'); - if(new_tail != tail + LINE_SEARCH_DIST) - { - tail = new_tail; - } - - sllog.erase(head, tail); - sllog.insert(head, SKIP_TEXT.begin(), SKIP_TEXT.end()); - } -} - -std::string getStartupStateFromLog(std::string& sllog) -{ - std::string startup_state = "STATE_FIRST"; - std::string startup_token = "Startup state changing from "; - - int index = sllog.rfind(startup_token); - if (index < 0 || index + startup_token.length() > sllog.length()) { - return startup_state; - } - - // find new line - char cur_char = sllog[index + startup_token.length()]; - std::string::size_type newline_loc = index + startup_token.length(); - while(cur_char != '\n' && newline_loc < sllog.length()) - { - newline_loc++; - cur_char = sllog[newline_loc]; - } - - // get substring and find location of " to " - std::string state_line = sllog.substr(index, newline_loc - index); - std::string::size_type state_index = state_line.find(" to "); - startup_state = state_line.substr(state_index + 4, state_line.length() - state_index - 4); - - return startup_state; -} - -bool miniDumpExists(const std::string& dumpDir) -{ - bool found = false; - - try - { - if (!boost::filesystem::exists(dumpDir)) - { - return false; - } - - boost::filesystem::directory_iterator end_itr; - for (boost::filesystem::directory_iterator i(dumpDir); i != end_itr; ++i) - { - if (!boost::filesystem::is_regular_file(i->status())) continue; - if (".dmp" == i->path().extension()) - { - found = true; - break; - } - } - } - catch (const boost::filesystem::filesystem_error& e) - { - LL_WARNS() << "Failed to determine existance of the minidump file: '" + e.code().message() +"'" << LL_ENDL; - } - - return found; -} - -bool LLCrashLogger::readDebugFromXML(LLSD& dest, const std::string& filename ) -{ - std::string db_file_name = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,filename); - std::ifstream debug_log_file(db_file_name.c_str()); - - // Look for it in the debug_info.log file - if (debug_log_file.is_open()) - { - LLSDSerialize::fromXML(dest, debug_log_file); - debug_log_file.close(); - return true; - } - return false; -} - -void LLCrashLogger::mergeLogs( LLSD src_sd ) -{ - LLSD::map_iterator iter = src_sd.beginMap(); - LLSD::map_iterator end = src_sd.endMap(); - for( ; iter != end; ++iter) - { - mDebugLog[iter->first] = iter->second; - } -} - -bool LLCrashLogger::readMinidump(std::string minidump_path) -{ - size_t length=0; - - std::ifstream minidump_stream(minidump_path.c_str(), std::ios_base::in | std::ios_base::binary); - if(minidump_stream.is_open()) - { - minidump_stream.seekg(0, std::ios::end); - length = (size_t)minidump_stream.tellg(); - minidump_stream.seekg(0, std::ios::beg); - - LLSD::Binary data; - data.resize(length); - - minidump_stream.read(reinterpret_cast(&(data[0])),length); - minidump_stream.close(); - - mCrashInfo["Minidump"] = data; - } - return (length>0?true:false); -} - -void LLCrashLogger::gatherFiles() -{ - LL_INFOS() << "Gathering logs..." << LL_ENDL; - - LLSD static_sd; - LLSD dynamic_sd; - - bool has_logs = readDebugFromXML( static_sd, "static_debug_info.log" ); - has_logs |= readDebugFromXML( dynamic_sd, "dynamic_debug_info.log" ); - - if ( has_logs ) - { - mDebugLog = static_sd; - mergeLogs(dynamic_sd); - mCrashInPreviousExec = mDebugLog["CrashNotHandled"].asBoolean(); - - mFileMap["SecondLifeLog"] = mDebugLog["SLLog"].asString(); - mFileMap["SettingsXml"] = mDebugLog["SettingsFilename"].asString(); - if(mDebugLog.has("CAFilename")) - { - LLCurl::setCAFile(mDebugLog["CAFilename"].asString()); - } - else - { - LLCurl::setCAFile(gDirUtilp->getCAFile()); - } - - LL_INFOS() << "Using log file from debug log " << mFileMap["SecondLifeLog"] << LL_ENDL; - LL_INFOS() << "Using settings file from debug log " << mFileMap["SettingsXml"] << LL_ENDL; - } - else - { - // Figure out the filename of the second life log - LLCurl::setCAFile(gDirUtilp->getCAFile()); - mFileMap["SecondLifeLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"SecondLife.log"); - mFileMap["SettingsXml"] = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"settings.xml"); - } - - if(mCrashInPreviousExec) - { - // Restarting after freeze. - // Replace the log file ext with .old, since the - // instance that launched this process has overwritten - // SecondLife.log - std::string log_filename = mFileMap["SecondLifeLog"]; - log_filename.replace(log_filename.size() - 4, 4, ".old"); - mFileMap["SecondLifeLog"] = log_filename; - } - - gatherPlatformSpecificFiles(); - - mCrashInfo["DebugLog"] = mDebugLog; - mFileMap["StatsLog"] = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,"stats.log"); - // Singu Note: we have just started again, log has been renamed - mFileMap["SecondLifeLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, OLD_LOG_FILE); - - LL_INFOS() << "Encoding files..." << LL_ENDL; - - for(std::map::iterator itr = mFileMap.begin(); itr != mFileMap.end(); ++itr) - { - std::ifstream f((*itr).second.c_str()); - if(!f.is_open()) - { - LL_INFOS() << "Can't find file " << (*itr).second << LL_ENDL; - continue; - } - std::stringstream s; - s << f.rdbuf(); - - std::string crash_info = s.str(); - if(itr->first == "SecondLifeLog") - { - if(!mCrashInfo["DebugLog"].has("StartupState")) - { - mCrashInfo["DebugLog"]["StartupState"] = getStartupStateFromLog(crash_info); - } - trimSLLog(crash_info); - } - - mCrashInfo[(*itr).first] = LLStringFn::strip_invalid_xml(rawstr_to_utf8(crash_info)); - } - - std::string minidump_path; - - // Add minidump as binary. - bool has_minidump = mDebugLog.has("MinidumpPath"); - - if (has_minidump) - minidump_path = mDebugLog["MinidumpPath"].asString(); - - - if (has_minidump) - { - has_minidump = readMinidump(minidump_path); - } - - if (!has_minidump) //Viewer was probably so hosed it couldn't write remaining data. Try brute force. - { - //Look for a filename at least 30 characters long in the dump dir which contains the characters MDMP as the first 4 characters in the file. - typedef std::vector vec; - - std::string pathname = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,""); - vec file_vec = gDirUtilp->getFilesInDir(pathname); - for(vec::const_iterator iter=file_vec.begin(); iter!=file_vec.end(); ++iter) - { - if ( ( iter->length() > 30 ) && (iter->rfind(".log") != (iter->length()-4) ) ) - { - std::string fullname = pathname + *iter; - std::ifstream fdat( fullname.c_str(), std::ifstream::binary); - if (fdat) - { - char buf[5]; - fdat.read(buf,4); - fdat.close(); - if (!strncmp(buf,"MDMP",4)) - { - minidump_path = *iter; - has_minidump = readMinidump(fullname); - mDebugLog["MinidumpPath"] = fullname; - } - } - } - } - } -} - -LLSD LLCrashLogger::constructPostData() -{ - return mCrashInfo; -} - - -bool LLCrashLogger::sendCrashLog(std::string dump_dir) -{ - gDirUtilp->setDumpDir( dump_dir ); - - std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, - "SingularityCrashReport"); - std::string report_file = dump_path + ".log"; - - gatherFiles(); - - LLSD post_data; - post_data = constructPostData(); - - LL_INFOS() << "Sending reports..." << LL_ENDL; - - std::ofstream out_file(report_file.c_str()); - LLSDSerialize::toPrettyXML(post_data, out_file); - out_file.close(); - - LLHTTPClient::post(mCrashHost, post_data, new LLCrashLoggerResponder()); - - return true; -} - - -void LLCrashLogger::checkCrashDump() -{ -#if LL_SEND_CRASH_REPORTS - // 0 - ask, 1 - always send, 2 - never send - S32 pref = gSavedSettings.getS32("CrashSubmitBehavior"); - if (pref == 2) return; //never send - - mCrashHost = gSavedSettings.getString("CrashHostUrl"); - std::string dumpDir = gDirUtilp->getDumpDir(); - - // Do we have something to send, and somewhere to send it - if (!mCrashHost.empty() && miniDumpExists(dumpDir)) - { - if (pref == 1) // always send - { - sendCrashLog(dumpDir); - } - else // ask - { - U32 response = OSMessageBox(LLTrans::getString("MBFrozenCrashed"), LLTrans::getString("MBAlert"), OSMB_YESNO); - if (response == OSBTN_YES) - { - sendCrashLog(dumpDir); - } - } - } -#endif -} diff --git a/indra/newview/llcrashlogger.h b/indra/newview/llcrashlogger.h deleted file mode 100644 index c510acb98..000000000 --- a/indra/newview/llcrashlogger.h +++ /dev/null @@ -1,67 +0,0 @@ -/** -* @file llcrashlogger.h -* @brief Crash Logger Definition -* -* $LicenseInfo:firstyear=2003&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 LLCRASHLOGGER_H -#define LLCRASHLOGGER_H - -#include - -#include "linden_common.h" - -#include "llapp.h" -#include "llsd.h" -#include "llcontrol.h" - -class LLCrashLogger -{ -public: - LLCrashLogger(); - virtual ~LLCrashLogger(); - S32 loadCrashBehaviorSetting(); - bool readDebugFromXML(LLSD& dest, const std::string& filename ); - void gatherFiles(); - void mergeLogs( LLSD src_sd ); - - virtual void gatherPlatformSpecificFiles() {} - bool saveCrashBehaviorSetting(S32 crash_behavior); - bool sendCrashLog(std::string dump_dir); - LLSD constructPostData(); - void setUserText(const std::string& text) { mCrashInfo["UserNotes"] = text; } - S32 getCrashBehavior() { return mCrashBehavior; } - bool readMinidump(std::string minidump_path); - void checkCrashDump(); - -protected: - S32 mCrashBehavior; - BOOL mCrashInPreviousExec; - std::map mFileMap; - std::string mGridName; - std::string mProductName; - LLSD mCrashInfo; - std::string mCrashHost; - LLSD mDebugLog; -}; - -#endif //LLCRASHLOGGER_H diff --git a/indra/newview/llfloateravatarlist.cpp b/indra/newview/llfloateravatarlist.cpp index 9d6264f3c..0f90007f0 100644 --- a/indra/newview/llfloateravatarlist.cpp +++ b/indra/newview/llfloateravatarlist.cpp @@ -114,7 +114,7 @@ namespace chat.mFromName = name; chat.mFromID = key; if (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) // RLVa:LF - No way! - chat.mURL = llformat("secondlife:///app/agent/%s/about", key.asString().c_str()); + chat.mURL = LLAvatarActions::getSLURL(key); chat.mSourceType = CHAT_SOURCE_SYSTEM; LLFloaterChat::addChat(chat); } diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp index c1bf51012..e36a41975 100644 --- a/indra/newview/llfloaterchat.cpp +++ b/indra/newview/llfloaterchat.cpp @@ -51,6 +51,7 @@ // project include #include "ascentkeyword.h" #include "llagent.h" +#include "llavataractions.h" #include "llchatbar.h" #include "llconsole.h" #include "llfloaterchatterbox.h" @@ -195,7 +196,7 @@ void add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4& (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ) // [/RLVa:KB] { - chat.mURL = llformat("secondlife:///app/agent/%s/about",chat.mFromID.asString().c_str()); + chat.mURL = LLAvatarActions::getSLURL(chat.mFromID); } if (chat.mSourceType == CHAT_SOURCE_OBJECT) @@ -227,6 +228,12 @@ void add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4& edit->appendText(line, false, prepend_newline, style, false); } +void LLFloaterChat::addChatHistory(const std::string& str, bool log_to_file) +{ + LLChat chat(str); + addChatHistory(chat, log_to_file); +} + void log_chat_text(const LLChat& chat) { std::string histstr; @@ -238,7 +245,7 @@ void log_chat_text(const LLChat& chat) LLLogChat::saveHistory(std::string("chat"), histstr); } // static -void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file) +void LLFloaterChat::addChatHistory(LLChat& chat, bool log_to_file) { // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) if (rlv_handler_t::isEnabled()) @@ -246,20 +253,18 @@ void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file) // TODO-RLVa: we might cast too broad a net by filtering here, needs testing if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) && (!chat.mRlvLocFiltered) && (CHAT_SOURCE_AGENT != chat.mSourceType) ) { - LLChat& rlvChat = const_cast(chat); - RlvUtil::filterLocation(rlvChat.mText); - rlvChat.mRlvLocFiltered = TRUE; + RlvUtil::filterLocation(chat.mText); + chat.mRlvLocFiltered = TRUE; } if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (!chat.mRlvNamesFiltered) ) { // NOTE: this will also filter inventory accepted/declined text in the chat history - LLChat& rlvChat = const_cast(chat); if (CHAT_SOURCE_AGENT != chat.mSourceType) { // Filter object and system chat (names are filtered elsewhere to save ourselves an gObjectList lookup) - RlvUtil::filterNames(rlvChat.mText); + RlvUtil::filterNames(chat.mText); } - rlvChat.mRlvNamesFiltered = TRUE; + chat.mRlvNamesFiltered = TRUE; } } // [/RLVa:KB] @@ -275,10 +280,7 @@ void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file) if (chat.mChatType == CHAT_TYPE_DEBUG_MSG) { - LLFloaterScriptDebug::addScriptLine(chat.mText, - chat.mFromName, - color, - chat.mFromID); + LLFloaterScriptDebug::addScriptLine(chat, color); if (!gSavedSettings.getBOOL("ScriptErrorsAsChat")) { return; @@ -339,8 +341,14 @@ void LLFloaterChat::onClickToggleShowMute(bool show_mute, LLTextEditor* history_ (show_mute ? history_editor_with_mute : history_editor)->setCursorAndScrollToEnd(); } +void LLFloaterChat::addChat(const std::string& str, BOOL from_im, BOOL local_agent) +{ + LLChat chat(str); + addChat(chat, from_im, local_agent); +} + // Put a line of chat in all the right places -void LLFloaterChat::addChat(const LLChat& chat, +void LLFloaterChat::addChat(LLChat& chat, BOOL from_instant_message, BOOL local_agent) { @@ -356,20 +364,18 @@ void LLFloaterChat::addChat(const LLChat& chat, // TODO-RLVa: we might cast too broad a net by filtering here, needs testing if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) && (!chat.mRlvLocFiltered) && (CHAT_SOURCE_AGENT != chat.mSourceType) ) { - LLChat& rlvChat = const_cast(chat); if (!from_instant_message) - RlvUtil::filterLocation(rlvChat.mText); - rlvChat.mRlvLocFiltered = TRUE; + RlvUtil::filterLocation(chat.mText); + chat.mRlvLocFiltered = TRUE; } if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (!chat.mRlvNamesFiltered) ) { - LLChat& rlvChat = const_cast(chat); if ( (!from_instant_message) && (CHAT_SOURCE_AGENT != chat.mSourceType) ) { // Filter object and system chat (names are filtered elsewhere to save ourselves an gObjectList lookup) - RlvUtil::filterNames(rlvChat.mText); + RlvUtil::filterNames(chat.mText); } - rlvChat.mRlvNamesFiltered = TRUE; + chat.mRlvNamesFiltered = TRUE; } } // [/RLVa:KB] diff --git a/indra/newview/llfloaterchat.h b/indra/newview/llfloaterchat.h index e1c55e779..f6c6addc7 100644 --- a/indra/newview/llfloaterchat.h +++ b/indra/newview/llfloaterchat.h @@ -60,13 +60,15 @@ public: void updateConsoleVisibility(); static void setHistoryCursorAndScrollToEnd(); - + // Add chat to console and history list. // Color based on source, type, distance. - static void addChat(const LLChat& chat, BOOL from_im = FALSE, BOOL local_agent = FALSE); + static void addChat(const std::string& str, BOOL from_im = FALSE, BOOL local_agent = FALSE); + static void addChat(LLChat& chat, BOOL from_im = FALSE, BOOL local_agent = FALSE); // Add chat to history alone. - static void addChatHistory(const LLChat& chat, bool log_to_file = true); + static void addChatHistory(const std::string& str, bool log_to_file = true); + static void addChatHistory(LLChat& chat, bool log_to_file = true); static void triggerAlerts(const std::string& text); diff --git a/indra/newview/llfloatermarketplacelistings.cpp b/indra/newview/llfloatermarketplacelistings.cpp index e51cbd6c7..b91e719e8 100644 --- a/indra/newview/llfloatermarketplacelistings.cpp +++ b/indra/newview/llfloatermarketplacelistings.cpp @@ -37,6 +37,7 @@ #include "llinventoryobserver.h" #include "llinventoryfunctions.h" #include "llmarketplacefunctions.h" +#include "llmenugl.h" //#include "llnotificationhandler.h" //#include "llnotificationmanager.h" #include "llnotificationsutil.h" diff --git a/indra/newview/llfloatermarketplacelistings.h b/indra/newview/llfloatermarketplacelistings.h index 22896a34e..496117a7f 100644 --- a/indra/newview/llfloatermarketplacelistings.h +++ b/indra/newview/llfloatermarketplacelistings.h @@ -217,6 +217,8 @@ private: LLTextEditor* mEditor; }; + +#if 0 //----------------------------------------------------------------------------- // LLFloaterItemProperties //----------------------------------------------------------------------------- @@ -232,5 +234,6 @@ public: private: }; +#endif #endif // LL_LLFLOATERMARKETPLACELISTINGS_H diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 9f08b1295..792f28cb2 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -4115,6 +4115,30 @@ void LLPanelEstateAccess::requestEstateGetAccessCoro(std::string url) } */ +const std::string& getNAString() +{ + static const auto na = LLTrans::getString("na"); + return na; +} + +void handlePseudoISO8601(const std::string& date_str, LLSD& column, const std::string& fmt) +{ + if (date_str.front() == '0') // server returns the "0000-00-00 00:00:00" date in case it doesn't know it + { + column["value"] = getNAString(); + } + else + { + std::tm time = {}; + if (std::istringstream(date_str) >> std::get_time(&time, "%Y-%m-%d %T")) + { + column["value"] = LLDate(mktime(&time)); + column["type"] = "date"; + column["format"] = fmt; + } + else column["value"] = date_str; + } +} void LLPanelEstateAccess::onEstateAccessReceived(const LLSD& result) { LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); @@ -4149,10 +4173,10 @@ void LLPanelEstateAccess::onEstateAccessReceived(const LLSD& result) std::string msg = LLTrans::getString("RegionInfoBannedResidents", args); panel->getChild("ban_resident_label")->setValue(LLSD(msg)); + const auto format = gSavedSettings.getString("ShortDateFormat"); const auto order = banned_agent_name_list->getSortOrder(); banned_agent_name_list->clearSortOrder(); banned_agent_name_list->deleteAllItems(); - static const auto na = LLTrans::getString("na"); for (LLSD::array_const_iterator it = result["BannedAgents"].beginArray(); it != result["BannedAgents"].endArray(); ++it) { LLSD item; @@ -4161,19 +4185,19 @@ void LLPanelEstateAccess::onEstateAccessReceived(const LLSD& result) columns[0]["column"] = "name"; // to be populated later - columns[1]["column"] = "last_login_date"; - columns[1]["value"] = (*it)["last_login_date"].asString().substr(0, 16); // cut the seconds + auto& col = columns[1]; + col["column"] = "last_login_date"; + handlePseudoISO8601((*it)["last_login_date"].asString(), col, format); - std::string ban_date = (*it)["ban_date"].asString(); columns[2]["column"] = "ban_date"; - columns[2]["value"] = ban_date[0] != '0' ? ban_date.substr(0, 16) : na; // server returns the "0000-00-00 00:00:00" date in case it doesn't know it + handlePseudoISO8601((*it)["ban_date"].asString(), columns[2], format); columns[3]["column"] = "bannedby"; LLUUID banning_id = (*it)["banning_id"].asUUID(); LLAvatarName av_name; if (banning_id.isNull()) { - columns[3]["value"] = na; + columns[3]["value"] = getNAString(); } else if (LLAvatarNameCache::get(banning_id, &av_name)) { diff --git a/indra/newview/llfloaterscriptdebug.cpp b/indra/newview/llfloaterscriptdebug.cpp index ce70602a5..e1209ccdf 100644 --- a/indra/newview/llfloaterscriptdebug.cpp +++ b/indra/newview/llfloaterscriptdebug.cpp @@ -32,21 +32,16 @@ #include "llviewerprecompiledheaders.h" -#include "lluictrlfactory.h" #include "llfloaterscriptdebug.h" -#include "llfontgl.h" -#include "llrect.h" -#include "llerror.h" -#include "llstring.h" -#include "llvoavatarself.h" -#include "message.h" +#include "lluictrlfactory.h" // project include -#include "llviewertexteditor.h" -#include "llviewercontrol.h" +#include "llslurl.h" #include "llviewerobjectlist.h" -#include "llviewertexturelist.h" +#include "llviewerregion.h" +#include "llviewertexteditor.h" +#include "llvoavatarself.h" // // Statics @@ -123,8 +118,12 @@ LLFloater* LLFloaterScriptDebug::addOutputWindow(const LLUUID &object_id) return floaterp; } -void LLFloaterScriptDebug::addScriptLine(const std::string &utf8mesg, const std::string &user_name, const LLColor4& color, const LLUUID& source_id) +void LLFloaterScriptDebug::addScriptLine(LLChat& chat, const LLColor4& color) { + const auto& utf8mesg = chat.mText; + const auto& user_name = chat.mFromName; + const auto& source_id = chat.mFromID; + LLViewerObject* objectp = gObjectList.findObject(source_id); std::string floater_label; @@ -132,6 +131,7 @@ void LLFloaterScriptDebug::addScriptLine(const std::string &utf8mesg, const std: std::string prefix = utf8mesg.substr(0, 4); std::string message = (prefix == "/me " || prefix == "/me'") ? user_name + utf8mesg.substr(3) : utf8mesg; + LLSD sdQuery = LLSD().with("name", user_name); if (objectp) { if(objectp->isHUDAttachment()) @@ -145,32 +145,39 @@ void LLFloaterScriptDebug::addScriptLine(const std::string &utf8mesg, const std: { objectp->setIcon(LLViewerTextureManager::getFetchedTextureFromFile("script_error.j2c", FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_UI)); } + + const auto& pos = objectp->getPositionRegion(); + sdQuery.with("owner", objectp->mOwnerID) + .with("groupowned", objectp->flagObjectGroupOwned()) + .with("slurl", LLSLURL(objectp->getRegion()->getName(), pos).getLocationString()); + floater_label = llformat("%s(%.0f, %.0f, %.0f)", user_name.c_str(), - objectp->getPositionRegion().mV[VX], - objectp->getPositionRegion().mV[VY], - objectp->getPositionRegion().mV[VZ]); + pos.mV[VX], + pos.mV[VY], + pos.mV[VZ]); } else { floater_label = user_name; } + chat.mURL = LLSLURL("objectim", source_id, LLURI::mapToQueryString(sdQuery)).getSLURLString(); + addOutputWindow(LLUUID::null); addOutputWindow(source_id); // add to "All" floater - LLFloaterScriptDebugOutput* floaterp = LLFloaterScriptDebugOutput::getFloaterByID(LLUUID::null); - if (floaterp) + if (auto floaterp = LLFloaterScriptDebugOutput::getFloaterByID(LLUUID::null)) { - floaterp->addLine(message, user_name, color); + floaterp->addLine(chat, message, color); } // add to specific script instance floater - floaterp = LLFloaterScriptDebugOutput::getFloaterByID(source_id); - if (floaterp) + if (auto floaterp = LLFloaterScriptDebugOutput::getFloaterByID(source_id)) { - floaterp->addLine(message, floater_label, color); + floaterp->setTitle(floater_label); // Update title + floaterp->addLine(chat, message, color); } } @@ -205,6 +212,7 @@ LLFloaterScriptDebugOutput::LLFloaterScriptDebugOutput(const LLUUID& object_id) mHistoryEditor->setFollowsAll(); mHistoryEditor->setEnabled( FALSE ); mHistoryEditor->setTabStop( TRUE ); // We want to be able to cut or copy from the history. + mHistoryEditor->setParseHTML(true); addChild(mHistoryEditor); } @@ -228,6 +236,7 @@ void LLFloaterScriptDebugOutput::initFloater(const std::string& title, BOOL resi mHistoryEditor->setFollowsAll(); mHistoryEditor->setEnabled( FALSE ); mHistoryEditor->setTabStop( TRUE ); // We want to be able to cut or copy from the history. + mHistoryEditor->setParseHTML(true); addChild(mHistoryEditor); } @@ -236,20 +245,15 @@ LLFloaterScriptDebugOutput::~LLFloaterScriptDebugOutput() sInstanceMap.erase(mObjectID); } -void LLFloaterScriptDebugOutput::addLine(const std::string &utf8mesg, const std::string &user_name, const LLColor4& color) +void LLFloaterScriptDebugOutput::addLine(const LLChat& chat, std::string message, const LLColor4& color) { - if (mObjectID.isNull()) + if (!chat.mURL.empty()) { - //setTitle("[All scripts]"); - setCanTearOff(FALSE); - setCanClose(FALSE); + message.erase(0, chat.mFromName.size()); + mHistoryEditor->appendText(chat.mURL, false, true); } - else - { - setTitle(user_name); - } - - mHistoryEditor->appendColoredText(utf8mesg, false, true, color); + LLStyleSP style(new LLStyle(true, color, LLStringUtil::null)); + mHistoryEditor->appendText(message, false, false, style, false); } //static @@ -262,6 +266,13 @@ LLFloaterScriptDebugOutput* LLFloaterScriptDebugOutput::show(const LLUUID& objec floaterp = new LLFloaterScriptDebugOutput(object_id); sInstanceMap[object_id] = floaterp; floaterp->open(); /* Flawfinder: ignore*/ + + if (object_id.isNull()) + { + //floaterp->setTitle("[All scripts]"); + floaterp->setCanTearOff(FALSE); + floaterp->setCanClose(FALSE); + } } else { diff --git a/indra/newview/llfloaterscriptdebug.h b/indra/newview/llfloaterscriptdebug.h index 0d5bc7411..8e28ea33d 100644 --- a/indra/newview/llfloaterscriptdebug.h +++ b/indra/newview/llfloaterscriptdebug.h @@ -35,6 +35,7 @@ #include "llmultifloater.h" +class LLChat; class LLTextEditor; class LLUUID; @@ -45,7 +46,7 @@ public: virtual void onClose(bool app_quitting) { setVisible(FALSE); } virtual BOOL postBuild(); static void show(const LLUUID& object_id); - static void addScriptLine(const std::string &utf8mesg, const std::string &user_name, const LLColor4& color, const LLUUID& source_id); + static void addScriptLine(LLChat& chat, const LLColor4& color); protected: LLFloaterScriptDebug(); @@ -67,7 +68,7 @@ public: S32 min_width, S32 min_height, BOOL drag_on_left, BOOL minimizable, BOOL close_btn); - void addLine(const std::string &utf8mesg, const std::string &user_name, const LLColor4& color); + void addLine(const LLChat& chat, std::string message, const LLColor4& color); static LLFloaterScriptDebugOutput* show(const LLUUID& object_id); static LLFloaterScriptDebugOutput* getFloaterByID(const LLUUID& id); diff --git a/indra/newview/llfloatersettingsdebug.cpp b/indra/newview/llfloatersettingsdebug.cpp index aac8e2223..9031d2422 100644 --- a/indra/newview/llfloatersettingsdebug.cpp +++ b/indra/newview/llfloatersettingsdebug.cpp @@ -35,7 +35,6 @@ #include "llfloatersettingsdebug.h" #include "llcolorswatch.h" -//#include "llfirstuse.h" #include "llfloater.h" #include "llscrolllistctrl.h" #include "llscrolllistitem.h" @@ -46,17 +45,21 @@ #include "llviewercontrol.h" #include "llwindow.h" -// [RLVa:KB] - Checked: 2010-03-18 (RLVa-1.2.0a) -#include "rlvhandler.h" -#include "rlvextensions.h" -// [/RLVa:KB] - LLFloaterSettingsDebug::LLFloaterSettingsDebug() : LLFloater(std::string("Configuration Editor")) -, mCurrentControlVariable(NULL) -, mOldControlVariable(NULL) -, mOldSearchTerm(std::string("---")) +, mOldSearchTerm("---") +, mCurrentControlVariable(nullptr) +, mSettingsScrollList(nullptr) +, mValSpinner1(nullptr) +, mValSpinner2(nullptr) +, mValSpinner3(nullptr) +, mValSpinner4(nullptr) +, mValColor(nullptr) +, mValBool(nullptr) +, mValText(nullptr) , mComment(nullptr) +, mBtnCopy(nullptr) +, mBtnDefault(nullptr) { mCommitCallbackRegistrar.add("SettingSelect", boost::bind(&LLFloaterSettingsDebug::onSettingSelect, this)); mCommitCallbackRegistrar.add("CommitSettings", boost::bind(&LLFloaterSettingsDebug::onCommitSettings, this)); @@ -69,19 +72,20 @@ LLFloaterSettingsDebug::LLFloaterSettingsDebug() LLFloaterSettingsDebug::~LLFloaterSettingsDebug() { - if (mOldControlVariable) - mOldControlVariable->getCommitSignal()->disconnect(boost::bind(&LLFloaterSettingsDebug::onSettingSelect, this)); + if (mCurrentControlVariable) + mCurrentControlVariable->getCommitSignal()->disconnect(boost::bind(&LLFloaterSettingsDebug::updateControl, this)); } BOOL LLFloaterSettingsDebug::postBuild() { mSettingsScrollList = getChild("settings_scroll_list"); - struct f : public LLControlGroup::ApplyFunctor + struct f final : public LLControlGroup::ApplyFunctor { settings_map_t* map; f(settings_map_t* m) : map(m) {} - virtual void apply(const std::string& name, LLControlVariable* control) + + void apply(const std::string& name, LLControlVariable* control) override final { if (!control->isHiddenFromSettingsEditor()) { @@ -95,26 +99,30 @@ BOOL LLFloaterSettingsDebug::postBuild() gColors.applyToAll(&func); // Populate the list - { - for(settings_map_t::iterator it = mSettingsMap.begin(); it != mSettingsMap.end(); it++) - { - LLSD item; - item["columns"][0]["value"] = it->second->getName(); - mSettingsScrollList->addElement(item, ADD_BOTTOM, it->second); - } - } + for(const auto& pair : mSettingsMap) + addRow(pair.second); + mSettingsScrollList->sortByColumnIndex(0, true); + mComment = getChild("comment_text"); + mValSpinner1 = getChild("val_spinner_1"); + mValSpinner2 = getChild("val_spinner_2"); + mValSpinner3 = getChild("val_spinner_3"); + mValSpinner4 = getChild("val_spinner_4"); + mValColor = getChild("val_color_swatch"); + mValBool = getChild("boolean_combo"); + mValText = getChild("val_text"); + mBtnCopy = getChildView("copy_btn"); + mBtnDefault = getChildView("default_btn"); LL_INFOS() << mSettingsScrollList->getItemCount() << " total debug settings displayed." << LL_ENDL; - mComment = getChild("comment_text"); return TRUE; } void LLFloaterSettingsDebug::draw() { // check for changes in control visibility, like RLVa does - if(mCurrentControlVariable && mCurrentControlVariable->isHiddenFromSettingsEditor() != mOldVisibility) + if (mCurrentControlVariable && mCurrentControlVariable->isHiddenFromSettingsEditor() != mOldVisibility) updateControl(); LLFloater::draw(); @@ -123,36 +131,66 @@ void LLFloaterSettingsDebug::draw() LLControlVariable* LLFloaterSettingsDebug::getControlVariable() { LLScrollListItem* item = mSettingsScrollList->getFirstSelected(); - if (!item) return NULL; + if (!item) return nullptr; LLControlVariable* controlp = static_cast(item->getUserdata()); - return controlp ? controlp->getCOAActive() : NULL; + return controlp ? controlp->getCOAActive() : nullptr; +} + +void LLFloaterSettingsDebug::addRow(LLControlVariable* control, const std::string& searchTerm) +{ + const auto& name = control->getName(); + const auto& comment = control->getComment(); + + if (!searchTerm.empty()) + { + std::string itemValue = control->getName(); + LLStringUtil::toLower(itemValue); + if (itemValue.find(searchTerm, 0) == std::string::npos) + { + std::string itemComment = control->getComment(); + LLStringUtil::toLower(itemComment); + if (itemComment.find(searchTerm, 0) == std::string::npos) + return; + } + } + + auto params = LLScrollListItem::Params(); + params.userdata(control) + .columns.add(LLScrollListCell::Params() + .value(name) + .tool_tip(comment)); + mSettingsScrollList->addRow(params); } void LLFloaterSettingsDebug::onSettingSelect() { - mCurrentControlVariable = getControlVariable(); + auto new_control = getControlVariable(); - if (mOldControlVariable == mCurrentControlVariable) return; + if (new_control == mCurrentControlVariable) return; // unbind change control signal from previously selected control - if(mOldControlVariable) - mOldControlVariable->getCommitSignal()->disconnect(boost::bind(&LLFloaterSettingsDebug::onSettingSelect, this)); + if (mCurrentControlVariable) + mCurrentControlVariable->getCommitSignal()->disconnect(boost::bind(&LLFloaterSettingsDebug::updateControl, this)); + + mCurrentControlVariable = new_control; // bind change control signal, so we can see updates to the current control in realtime - if(mCurrentControlVariable) - mCurrentControlVariable->getCommitSignal()->connect(boost::bind(&LLFloaterSettingsDebug::onSettingSelect, this)); - - mOldControlVariable = mCurrentControlVariable; + if (mCurrentControlVariable) + mCurrentControlVariable->getCommitSignal()->connect(boost::bind(&LLFloaterSettingsDebug::updateControl, this)); updateControl(); } void LLFloaterSettingsDebug::onCommitSettings() { - if (!mCurrentControlVariable) + LLControlVariable* controlp = mCurrentControlVariable; + + if (!controlp) + { return; + } LLVector3 vector; LLVector3d vectord; @@ -162,63 +200,63 @@ void LLFloaterSettingsDebug::onCommitSettings() LLColor4U col4U; LLColor4 color_with_alpha; - switch(mCurrentControlVariable->type()) + switch(controlp->type()) { case TYPE_U32: - mCurrentControlVariable->set(getChild("val_spinner_1")->getValue()); + controlp->set(mValSpinner1->getValue()); break; case TYPE_S32: - mCurrentControlVariable->set(getChild("val_spinner_1")->getValue()); + controlp->set(mValSpinner1->getValue()); break; case TYPE_F32: - mCurrentControlVariable->set(LLSD(getChild("val_spinner_1")->getValue().asReal())); + controlp->set(LLSD(mValSpinner1->getValue().asReal())); break; case TYPE_BOOLEAN: - mCurrentControlVariable->set(getChild("boolean_combo")->getValue()); + controlp->set(mValBool->getValue()); break; case TYPE_STRING: - mCurrentControlVariable->set(LLSD(getChild("val_text")->getValue().asString())); + controlp->set(mValText->getValue()); break; case TYPE_VEC3: - vector.mV[VX] = (F32)getChild("val_spinner_1")->getValue().asReal(); - vector.mV[VY] = (F32)getChild("val_spinner_2")->getValue().asReal(); - vector.mV[VZ] = (F32)getChild("val_spinner_3")->getValue().asReal(); - mCurrentControlVariable->set(vector.getValue()); + vector.mV[VX] = (F32)mValSpinner1->getValue().asReal(); + vector.mV[VY] = (F32)mValSpinner2->getValue().asReal(); + vector.mV[VZ] = (F32)mValSpinner3->getValue().asReal(); + controlp->set(vector.getValue()); break; case TYPE_VEC3D: - vectord.mdV[VX] = getChild("val_spinner_1")->getValue().asReal(); - vectord.mdV[VY] = getChild("val_spinner_2")->getValue().asReal(); - vectord.mdV[VZ] = getChild("val_spinner_3")->getValue().asReal(); - mCurrentControlVariable->set(vectord.getValue()); + vectord.mdV[VX] = mValSpinner1->getValue().asReal(); + vectord.mdV[VY] = mValSpinner2->getValue().asReal(); + vectord.mdV[VZ] = mValSpinner3->getValue().asReal(); + controlp->set(vectord.getValue()); break; case TYPE_RECT: - rect.mLeft = getChild("val_spinner_1")->getValue().asInteger(); - rect.mRight = getChild("val_spinner_2")->getValue().asInteger(); - rect.mBottom = getChild("val_spinner_3")->getValue().asInteger(); - rect.mTop = getChild("val_spinner_4")->getValue().asInteger(); - mCurrentControlVariable->set(rect.getValue()); + rect.mLeft = mValSpinner1->getValue().asInteger(); + rect.mRight = mValSpinner2->getValue().asInteger(); + rect.mBottom = mValSpinner3->getValue().asInteger(); + rect.mTop = mValSpinner4->getValue().asInteger(); + controlp->set(rect.getValue()); break; case TYPE_COL4: - col3.setValue(getChild("val_color_swatch")->getValue()); - col4 = LLColor4(col3, (F32)getChild("val_spinner_4")->getValue().asReal()); - mCurrentControlVariable->set(col4.getValue()); + col3.setValue(mValColor->getValue()); + col4 = LLColor4(col3, (F32)mValSpinner4->getValue().asReal()); + controlp->set(col4.getValue()); break; case TYPE_COL3: - mCurrentControlVariable->set(getChild("val_color_swatch")->getValue()); - //col3.mV[VRED] = (F32)getChild("val_spinner_1")->getValue().asC(); - //col3.mV[VGREEN] = (F32)getChild("val_spinner_2")->getValue().asReal(); - //col3.mV[VBLUE] = (F32)getChild("val_spinner_3")->getValue().asReal(); + controlp->set(mValColor->getValue()); + //col3.mV[VRED] = (F32)mValSpinner1->getValue().asReal(); + //col3.mV[VGREEN] = (F32)mValSpinner2->getValue().asReal(); + //col3.mV[VBLUE] = (F32)mValSpinner3->getValue().asReal(); //mCurrentControlVariable->set(col3.getValue()); break; case TYPE_COL4U: - col3.setValue(getChild("val_color_swatch")->getValue()); + col3.setValue(mValColor->getValue()); col4U.setVecScaleClamp(col3); - col4U.mV[VALPHA] = getChild("val_spinner_4")->getValue().asInteger(); + col4U.mV[VALPHA] = mValSpinner4->getValue().asInteger(); mCurrentControlVariable->set(col4U.getValue()); break; case TYPE_LLSD: { - auto val = getChild("val_text")->getValue().asString(); + const auto& val = mValText->getValue().asString(); LLSD sd; if (!val.empty()) { @@ -246,164 +284,156 @@ void LLFloaterSettingsDebug::onClickDefault() void LLFloaterSettingsDebug::onCopyToClipboard() { if (mCurrentControlVariable) + { getWindow()->copyTextToClipboard(utf8str_to_wstring(mCurrentControlVariable->getName())); + } } -// we've switched controls, so update spinners, etc. +// we've switched controls, or doing per-frame update, so update spinners, etc. void LLFloaterSettingsDebug::updateControl() { - LLSpinCtrl* spinner1 = getChild("val_spinner_1"); - LLSpinCtrl* spinner2 = getChild("val_spinner_2"); - LLSpinCtrl* spinner3 = getChild("val_spinner_3"); - LLSpinCtrl* spinner4 = getChild("val_spinner_4"); - LLColorSwatchCtrl* color_swatch = getChild("val_color_swatch"); - LLUICtrl* bool_ctrl = getChild("boolean_combo"); - - if (!spinner1 || !spinner2 || !spinner3 || !spinner4 || !color_swatch) + if (!mValSpinner1 || !mValSpinner2 || !mValSpinner3 || !mValSpinner4 || !mValColor) { LL_WARNS() << "Could not find all desired controls by name" << LL_ENDL; return; } - spinner1->setVisible(FALSE); - spinner2->setVisible(FALSE); - spinner3->setVisible(FALSE); - spinner4->setVisible(FALSE); - color_swatch->setVisible(FALSE); - getChildView("val_text")->setVisible( FALSE); - mComment->setText(LLStringUtil::null); - childSetEnabled("copy_btn", false); - childSetEnabled("default_btn", false); - bool_ctrl->setVisible(false); + mValSpinner1->setVisible(FALSE); + mValSpinner2->setVisible(FALSE); + mValSpinner3->setVisible(FALSE); + mValSpinner4->setVisible(FALSE); + mValColor->setVisible(FALSE); + mValText->setVisible(FALSE); + if (!mComment->hasFocus()) // + { + mComment->setText(LLStringUtil::null); + } + mValBool->setVisible(false); + mBtnCopy->setEnabled(false); + mBtnDefault->setEnabled(false); if (mCurrentControlVariable) { // [RLVa:KB] - Checked: 2011-05-28 (RLVa-1.4.0a) | Modified: RLVa-1.4.0a // If "HideFromEditor" was toggled while the floater is open then we need to manually disable access to the control mOldVisibility = mCurrentControlVariable->isHiddenFromSettingsEditor(); - spinner1->setEnabled(!mOldVisibility); - spinner2->setEnabled(!mOldVisibility); - spinner3->setEnabled(!mOldVisibility); - spinner4->setEnabled(!mOldVisibility); - color_swatch->setEnabled(!mOldVisibility); - childSetEnabled("val_text", !mOldVisibility); - bool_ctrl->setEnabled(!mOldVisibility); - childSetEnabled("default_btn", !mOldVisibility); + mValSpinner1->setEnabled(!mOldVisibility); + mValSpinner2->setEnabled(!mOldVisibility); + mValSpinner3->setEnabled(!mOldVisibility); + mValSpinner4->setEnabled(!mOldVisibility); + mValColor->setEnabled(!mOldVisibility); + mValText->setEnabled(!mOldVisibility); + mValBool->setEnabled(!mOldVisibility); + mBtnDefault->setEnabled(!mOldVisibility); // [/RLVa:KB] - childSetEnabled("copy_btn", true); + mBtnCopy->setEnabled(true); eControlType type = mCurrentControlVariable->type(); - - mComment->setText(mCurrentControlVariable->getName() + std::string(": ") + mCurrentControlVariable->getComment()); - - spinner1->setMaxValue(F32_MAX); - spinner2->setMaxValue(F32_MAX); - spinner3->setMaxValue(F32_MAX); - spinner4->setMaxValue(F32_MAX); - spinner1->setMinValue(-F32_MAX); - spinner2->setMinValue(-F32_MAX); - spinner3->setMinValue(-F32_MAX); - spinner4->setMinValue(-F32_MAX); - if (!spinner1->hasFocus()) + if (!mComment->hasFocus()) // { - spinner1->setIncrement(0.1f); + mComment->setText(mCurrentControlVariable->getName() + std::string(": ") + mCurrentControlVariable->getComment()); } - if (!spinner2->hasFocus()) + mValSpinner1->setMaxValue(F32_MAX); + mValSpinner2->setMaxValue(F32_MAX); + mValSpinner3->setMaxValue(F32_MAX); + mValSpinner4->setMaxValue(F32_MAX); + mValSpinner1->setMinValue(F32_MIN); + mValSpinner2->setMinValue(F32_MIN); + mValSpinner3->setMinValue(F32_MIN); + mValSpinner4->setMinValue(F32_MIN); + if (!mValSpinner1->hasFocus()) { - spinner2->setIncrement(0.1f); + mValSpinner1->setIncrement(0.1f); } - if (!spinner3->hasFocus()) + if (!mValSpinner2->hasFocus()) { - spinner3->setIncrement(0.1f); + mValSpinner2->setIncrement(0.1f); } - if (!spinner4->hasFocus()) + if (!mValSpinner3->hasFocus()) { - spinner4->setIncrement(0.1f); + mValSpinner3->setIncrement(0.1f); + } + if (!mValSpinner4->hasFocus()) + { + mValSpinner4->setIncrement(0.1f); } LLSD sd = mCurrentControlVariable->get(); switch(type) { case TYPE_U32: - spinner1->setVisible(TRUE); - spinner1->setLabel(std::string("value")); // Debug, don't translate - if (!spinner1->hasFocus()) + mValSpinner1->setVisible(TRUE); + mValSpinner1->setLabel(LLStringExplicit("value")); // Debug, don't translate + if (!mValSpinner1->hasFocus()) { - spinner1->setValue(sd); - spinner1->setMinValue((F32)U32_MIN); - spinner1->setMaxValue((F32)U32_MAX); - spinner1->setIncrement(1.f); - spinner1->setPrecision(0); + mValSpinner1->setValue(sd); + mValSpinner1->setMinValue((F32)U32_MIN); + mValSpinner1->setMaxValue((F32)U32_MAX); + mValSpinner1->setIncrement(1.f); + mValSpinner1->setPrecision(0); } break; case TYPE_S32: - spinner1->setVisible(TRUE); - spinner1->setLabel(std::string("value")); // Debug, don't translate - if (!spinner1->hasFocus()) + mValSpinner1->setVisible(TRUE); + mValSpinner1->setLabel(LLStringExplicit("value")); // Debug, don't translate + if (!mValSpinner1->hasFocus()) { - spinner1->setValue(sd); - spinner1->setMinValue((F32)S32_MIN); - spinner1->setMaxValue((F32)S32_MAX); - spinner1->setIncrement(1.f); - spinner1->setPrecision(0); + mValSpinner1->setValue(sd); + mValSpinner1->setMinValue((F32)S32_MIN); + mValSpinner1->setMaxValue((F32)S32_MAX); + mValSpinner1->setIncrement(1.f); + mValSpinner1->setPrecision(0); } break; case TYPE_F32: - spinner1->setVisible(TRUE); - spinner1->setLabel(std::string("value")); // Debug, don't translate - if (!spinner1->hasFocus()) + mValSpinner1->setVisible(TRUE); + mValSpinner1->setLabel(LLStringExplicit("value")); // Debug, don't translate + if (!mValSpinner1->hasFocus()) { - spinner1->setPrecision(3); - spinner1->setValue(sd); + mValSpinner1->setPrecision(3); + mValSpinner1->setValue(sd); } break; case TYPE_BOOLEAN: - bool_ctrl->setVisible(true); - if (!bool_ctrl->hasFocus()) + mValBool->setVisible(true); + if (!mValBool->hasFocus()) { - if (sd.asBoolean()) - { - bool_ctrl->setValue(LLSD("TRUE")); - } - else - { - bool_ctrl->setValue(LLSD("FALSE")); - } + mValBool->setValue(LLSD(sd.asBoolean() ? "TRUE" : "FALSE")); } break; case TYPE_STRING: - getChildView("val_text")->setVisible( TRUE); - if (!getChild("val_text")->hasFocus()) + mValText->setVisible(TRUE); + if (!mValText->hasFocus()) { - getChild("val_text")->setValue(sd); + mValText->setValue(sd); } break; case TYPE_VEC3: { LLVector3 v; v.setValue(sd); - spinner1->setVisible(TRUE); - spinner1->setLabel(std::string("X")); - spinner2->setVisible(TRUE); - spinner2->setLabel(std::string("Y")); - spinner3->setVisible(TRUE); - spinner3->setLabel(std::string("Z")); - if (!spinner1->hasFocus()) + mValSpinner1->setVisible(TRUE); + mValSpinner1->setLabel(LLStringExplicit("X")); + mValSpinner2->setVisible(TRUE); + mValSpinner2->setLabel(LLStringExplicit("Y")); + mValSpinner3->setVisible(TRUE); + mValSpinner3->setLabel(LLStringExplicit("Z")); + if (!mValSpinner1->hasFocus()) { - spinner1->setPrecision(3); - spinner1->setValue(v[VX]); + mValSpinner1->setPrecision(3); + mValSpinner1->setValue(v[VX]); } - if (!spinner2->hasFocus()) + if (!mValSpinner2->hasFocus()) { - spinner2->setPrecision(3); - spinner2->setValue(v[VY]); + mValSpinner2->setPrecision(3); + mValSpinner2->setValue(v[VY]); } - if (!spinner3->hasFocus()) + if (!mValSpinner3->hasFocus()) { - spinner3->setPrecision(3); - spinner3->setValue(v[VZ]); + mValSpinner3->setPrecision(3); + mValSpinner3->setValue(v[VZ]); } break; } @@ -411,26 +441,26 @@ void LLFloaterSettingsDebug::updateControl() { LLVector3d v; v.setValue(sd); - spinner1->setVisible(TRUE); - spinner1->setLabel(std::string("X")); - spinner2->setVisible(TRUE); - spinner2->setLabel(std::string("Y")); - spinner3->setVisible(TRUE); - spinner3->setLabel(std::string("Z")); - if (!spinner1->hasFocus()) + mValSpinner1->setVisible(TRUE); + mValSpinner1->setLabel(LLStringExplicit("X")); + mValSpinner2->setVisible(TRUE); + mValSpinner2->setLabel(LLStringExplicit("Y")); + mValSpinner3->setVisible(TRUE); + mValSpinner3->setLabel(LLStringExplicit("Z")); + if (!mValSpinner1->hasFocus()) { - spinner1->setPrecision(3); - spinner1->setValue(v[VX]); + mValSpinner1->setPrecision(3); + mValSpinner1->setValue(v[VX]); } - if (!spinner2->hasFocus()) + if (!mValSpinner2->hasFocus()) { - spinner2->setPrecision(3); - spinner2->setValue(v[VY]); + mValSpinner2->setPrecision(3); + mValSpinner2->setValue(v[VY]); } - if (!spinner3->hasFocus()) + if (!mValSpinner3->hasFocus()) { - spinner3->setPrecision(3); - spinner3->setValue(v[VZ]); + mValSpinner3->setPrecision(3); + mValSpinner3->setValue(v[VZ]); } break; } @@ -438,70 +468,70 @@ void LLFloaterSettingsDebug::updateControl() { LLRect r; r.setValue(sd); - spinner1->setVisible(TRUE); - spinner1->setLabel(std::string("Left")); - spinner2->setVisible(TRUE); - spinner2->setLabel(std::string("Right")); - spinner3->setVisible(TRUE); - spinner3->setLabel(std::string("Bottom")); - spinner4->setVisible(TRUE); - spinner4->setLabel(std::string("Top")); - if (!spinner1->hasFocus()) + mValSpinner1->setVisible(TRUE); + mValSpinner1->setLabel(LLStringExplicit("Left")); + mValSpinner2->setVisible(TRUE); + mValSpinner2->setLabel(LLStringExplicit("Right")); + mValSpinner3->setVisible(TRUE); + mValSpinner3->setLabel(LLStringExplicit("Bottom")); + mValSpinner4->setVisible(TRUE); + mValSpinner4->setLabel(LLStringExplicit("Top")); + if (!mValSpinner1->hasFocus()) { - spinner1->setPrecision(0); - spinner1->setValue(r.mLeft); + mValSpinner1->setPrecision(0); + mValSpinner1->setValue(r.mLeft); } - if (!spinner2->hasFocus()) + if (!mValSpinner2->hasFocus()) { - spinner2->setPrecision(0); - spinner2->setValue(r.mRight); + mValSpinner2->setPrecision(0); + mValSpinner2->setValue(r.mRight); } - if (!spinner3->hasFocus()) + if (!mValSpinner3->hasFocus()) { - spinner3->setPrecision(0); - spinner3->setValue(r.mBottom); + mValSpinner3->setPrecision(0); + mValSpinner3->setValue(r.mBottom); } - if (!spinner4->hasFocus()) + if (!mValSpinner4->hasFocus()) { - spinner4->setPrecision(0); - spinner4->setValue(r.mTop); + mValSpinner4->setPrecision(0); + mValSpinner4->setValue(r.mTop); } - spinner1->setMinValue((F32)S32_MIN); - spinner1->setMaxValue((F32)S32_MAX); - spinner1->setIncrement(1.f); + mValSpinner1->setMinValue((F32)S32_MIN); + mValSpinner1->setMaxValue((F32)S32_MAX); + mValSpinner1->setIncrement(1.f); - spinner2->setMinValue((F32)S32_MIN); - spinner2->setMaxValue((F32)S32_MAX); - spinner2->setIncrement(1.f); + mValSpinner2->setMinValue((F32)S32_MIN); + mValSpinner2->setMaxValue((F32)S32_MAX); + mValSpinner2->setIncrement(1.f); - spinner3->setMinValue((F32)S32_MIN); - spinner3->setMaxValue((F32)S32_MAX); - spinner3->setIncrement(1.f); + mValSpinner3->setMinValue((F32)S32_MIN); + mValSpinner3->setMaxValue((F32)S32_MAX); + mValSpinner3->setIncrement(1.f); - spinner4->setMinValue((F32)S32_MIN); - spinner4->setMaxValue((F32)S32_MAX); - spinner4->setIncrement(1.f); + mValSpinner4->setMinValue((F32)S32_MIN); + mValSpinner4->setMaxValue((F32)S32_MAX); + mValSpinner4->setIncrement(1.f); break; } case TYPE_COL4: { LLColor4 clr; clr.setValue(sd); - color_swatch->setVisible(TRUE); + mValColor->setVisible(TRUE); // only set if changed so color picker doesn't update - if(clr != LLColor4(color_swatch->getValue())) + if(clr != LLColor4(mValColor->getValue())) { - color_swatch->set(LLColor4(sd), TRUE, FALSE); + mValColor->set(LLColor4(sd), TRUE, FALSE); } - spinner4->setVisible(TRUE); - spinner4->setLabel(std::string("Alpha")); - if (!spinner4->hasFocus()) + mValSpinner4->setVisible(TRUE); + mValSpinner4->setLabel(LLStringExplicit("Alpha")); + if (!mValSpinner4->hasFocus()) { - spinner4->setPrecision(3); - spinner4->setMinValue(0.0); - spinner4->setMaxValue(1.f); - spinner4->setValue(clr.mV[VALPHA]); + mValSpinner4->setPrecision(3); + mValSpinner4->setMinValue(0.0); + mValSpinner4->setMaxValue(1.f); + mValSpinner4->setValue(clr.mV[VALPHA]); } break; } @@ -509,43 +539,42 @@ void LLFloaterSettingsDebug::updateControl() { LLColor3 clr; clr.setValue(sd); - color_swatch->setVisible(TRUE); - color_swatch->setValue(sd); + mValColor->setVisible(TRUE); + mValColor->setValue(sd); break; } case TYPE_COL4U: { - LLColor4U clr; - clr.setValue(sd); - color_swatch->setVisible(TRUE); - if(LLColor4(clr) != LLColor4(color_swatch->getValue())) + LLColor4U clr(sd); + mValColor->setVisible(TRUE); + if (LLColor4(clr) != LLColor4(mValColor->getValue())) { - color_swatch->set(LLColor4(clr), TRUE, FALSE); + mValColor->set(LLColor4(clr), TRUE, FALSE); } - spinner4->setVisible(TRUE); - spinner4->setLabel(std::string("Alpha")); - if(!spinner4->hasFocus()) + mValSpinner4->setVisible(TRUE); + mValSpinner4->setLabel(std::string("Alpha")); + if(!mValSpinner4->hasFocus()) { - spinner4->setPrecision(0); - spinner4->setValue(clr.mV[VALPHA]); + mValSpinner4->setPrecision(0); + mValSpinner4->setValue(clr.mV[VALPHA]); } - spinner4->setMinValue(0); - spinner4->setMaxValue(255); - spinner4->setIncrement(1.f); + mValSpinner4->setMinValue(0); + mValSpinner4->setMaxValue(255); + mValSpinner4->setIncrement(1.f); break; } case TYPE_LLSD: - getChildView("val_text")->setVisible(true); + mValText->setVisible(true); { std::ostringstream str; LLSDSerialize::toPrettyXML(sd, str); - getChild("val_text")->setValue(str.str()); + mValText->setValue(str.str()); } break; default: - mComment->setText(std::string("unknown")); + mComment->setText(LLStringExplicit("unknown")); break; } } @@ -559,49 +588,23 @@ void LLFloaterSettingsDebug::onUpdateFilter(const LLSD& value) void LLFloaterSettingsDebug::updateFilter(std::string searchTerm) { + LLStringUtil::toLower(searchTerm); + // make sure not to reselect the first item in the list on focus restore if (searchTerm == mOldSearchTerm) return; mOldSearchTerm = searchTerm; - LLStringUtil::toLower(searchTerm); - mSettingsScrollList->deleteAllItems(); - for(settings_map_t::iterator it = mSettingsMap.begin(); it != mSettingsMap.end(); it++) - { - bool addItem = searchTerm.empty(); - if (!addItem) - { - std::string itemValue = it->second->getName(); + for(const auto& pair : mSettingsMap) + addRow(pair.second, searchTerm); - LLStringUtil::toLower(itemValue); - - if (itemValue.find(searchTerm, 0) != std::string::npos) - { - addItem = true; - } - else // performance: broken out to save toLower calls on comments - { - std::string itemComment = it->second->getComment(); - LLStringUtil::toLower(itemComment); - if (itemComment.find(searchTerm, 0) != std::string::npos) - addItem = true; - } - } - - if (addItem) - { - LLSD item; - item["columns"][0]["value"] = it->second->getName(); - mSettingsScrollList->addElement(item, ADD_BOTTOM, it->second); - } - } mSettingsScrollList->sortByColumnIndex(0, true); // if at least one match was found, highlight and select the topmost entry in the list // but only if actually a search term was given - if (mSettingsScrollList->getItemCount() && !searchTerm.empty()) + if (!searchTerm.empty() && mSettingsScrollList->getItemCount()) mSettingsScrollList->selectFirstItem(); onSettingSelect(); diff --git a/indra/newview/llfloatersettingsdebug.h b/indra/newview/llfloatersettingsdebug.h index 5c94d6bd0..d9fd50e91 100644 --- a/indra/newview/llfloatersettingsdebug.h +++ b/indra/newview/llfloatersettingsdebug.h @@ -36,10 +36,14 @@ #include "llcontrol.h" #include "llfloater.h" +class LLControlVariable; +class LLColorSwatchCtrl; class LLScrollListCtrl; +class LLSpinCtrl; class LLTextEditor; +class LLUICtrl; -class LLFloaterSettingsDebug +class LLFloaterSettingsDebug final : public LLFloater , public LLSingleton { @@ -47,8 +51,8 @@ public: LLFloaterSettingsDebug(); virtual ~LLFloaterSettingsDebug(); - virtual BOOL postBuild(); - virtual void draw(); + BOOL postBuild() override; + void draw() override; void updateControl(); @@ -64,6 +68,7 @@ public: private: // returns a pointer to the currently selected control variable, or NULL LLControlVariable* getControlVariable(); + void addRow(LLControlVariable* control, const std::string& searchTerm = LLStringUtil::null); protected: typedef std::map settings_map_t; @@ -72,11 +77,19 @@ protected: std::string mOldSearchTerm; LLControlVariable* mCurrentControlVariable; - LLControlVariable* mOldControlVariable; bool mOldVisibility; LLScrollListCtrl* mSettingsScrollList; + LLSpinCtrl* mValSpinner1; + LLSpinCtrl* mValSpinner2; + LLSpinCtrl* mValSpinner3; + LLSpinCtrl* mValSpinner4; + LLColorSwatchCtrl* mValColor; + LLUICtrl* mValBool; + LLUICtrl* mValText; LLTextEditor* mComment; + LLView* mBtnCopy; + LLView* mBtnDefault; }; #endif //LLFLOATERDEBUGSETTINGS_H diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 5087b89e8..b7147404b 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -538,36 +538,74 @@ void LLFloaterTools::refresh() else #endif { - F32 link_cost = LLSelectMgr::getInstance()->getSelection()->getSelectedLinksetCost(); - S32 link_count = LLSelectMgr::getInstance()->getSelection()->getRootObjectCount(); - - // Added in Link Num value -HgB - S32 prim_count = LLSelectMgr::getInstance()->getEditSelection()->getObjectCount(); - std::string value_string; - bool edit_linked(gSavedSettings.getBOOL("EditLinkedParts")); - if (edit_linked && prim_count == 1) //Selecting a single prim in "Edit Linked" mode, show link number + auto selection = LLSelectMgr::getInstance()->getSelection(); + F32 link_cost = selection->getSelectedLinksetCost(); + S32 link_count = selection->getRootObjectCount(); + S32 prim_count = selection->getObjectCount(); + auto child = getChild("link_num_obj_count"); + auto selected_face = -1; + if (auto node = prim_count == 1 ? *selection->begin() : nullptr) + //for (const auto& node : selection) // All selected objects { - link_cost = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectCost(); - childSetTextArg("link_num_obj_count", "[DESC]", std::string("Link number:")); - - LLViewerObject* selected = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); - if (selected && selected->getRootEdit()) + // TODO: Count selected faces? What use is there for this? + if (node->getTESelectMask() == 0xFFFFFFFF) // All faces selected { - LLViewerObject::child_list_t children = selected->getRootEdit()->getChildren(); - if (children.empty()) + selected_face = -2; // Multiple + } + if (const auto& obj = node->getObject()) // This node's object + { + //if (!obj->isSelected()) continue; + const auto& numTEs = obj->getNumTEs(); + for (S32 te = 0; selected_face != -2 && te < numTEs; ++te) // Faces { - value_string = "0"; // An unlinked prim is "link 0". - } - else - { - children.push_front(selected->getRootEdit()); // need root in the list too - S32 index = 1; - for (LLViewerObject::child_list_t::iterator iter = children.begin(); iter != children.end(); ++iter, ++index) + if (!node->isTESelected(te)) continue; + if (selected_face != -1) { - if ((*iter)->isSelected()) + selected_face = -2; // Multiple + } + else selected_face = te; + } + } + //if (selected_face == -2) break; + } + // Added in Link Num value -HgB + std::string value_string; + bool edit_linked(mCheckSelectIndividual->getValue()); + if (mRadioSelectFace->getValue() || selected_face > 0) // In select faces mode, show either multiple or the face number, otherwise only show if single face selected + { + child->setTextArg("[DESC]", getString("Selected Face:")); + if (selected_face < 0) + { + value_string = LLTrans::getString(selected_face == -1 && !prim_count ? "None" : "multiple_textures"); + } + else LLResMgr::getInstance()->getIntegerString(value_string, selected_face); + } + else if (edit_linked && prim_count == 1) //Selecting a single prim in "Edit Linked" mode, show link number + { + link_cost = selection->getSelectedObjectCost(); + child->setTextArg("[DESC]", getString("Link number:")); + + if (LLViewerObject* selected = selection->getFirstObject()) + { + if (auto root = selected->getRootEdit()) + { + LLViewerObject::child_list_t children = root->getChildren(); + if (children.empty()) + { + value_string = "0"; // An unlinked prim is "link 0". + } + else + { + children.push_front(selected->getRootEdit()); // need root in the list too + S32 index = 1; + for (const auto& child : children) { - LLResMgr::getInstance()->getIntegerString(value_string, index); - break; + ++index; + if (child->isSelected()) + { + LLResMgr::getInstance()->getIntegerString(value_string, index); + break; + } } } } @@ -575,16 +613,16 @@ void LLFloaterTools::refresh() } else if (edit_linked) { - childSetTextArg("link_num_obj_count", "[DESC]", std::string("Selected prims:")); + child->setTextArg("[DESC]", getString("Selected prims:")); LLResMgr::getInstance()->getIntegerString(value_string, prim_count); - link_cost = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectCost(); + link_cost = selection->getSelectedObjectCost(); } else { - childSetTextArg("link_num_obj_count", "[DESC]", std::string("Selected objects:")); + child->setTextArg("[DESC]", getString("Selected objects:")); LLResMgr::getInstance()->getIntegerString(value_string, link_count); } - childSetTextArg("link_num_obj_count", "[NUM]", value_string); + child->setTextArg("[NUM]", value_string); /* Singu Note: We're not using this yet because we have no place to put it LLCrossParcelFunctor func; @@ -610,18 +648,17 @@ void LLFloaterTools::refresh() } } - LLStringUtil::format_map_t selection_args; - selection_args["OBJ_COUNT"] = llformat("%.1d", prim_count); - selection_args["LAND_IMPACT"] = llformat(edit_linked ? "%.2f" : "%.0f", link_cost); + auto sel_count = getChild("selection_count"); + bool have_selection = !selection->isEmpty(); + if (have_selection) + { + LLStringUtil::format_map_t selection_args; + selection_args["OBJ_COUNT"] = llformat("%.1d", prim_count); + selection_args["LAND_IMPACT"] = llformat(edit_linked ? "%.2f" : "%.0f", link_cost); - std::ostringstream selection_info; - - selection_info << getString("status_selectcount", selection_args); - - getChild("selection_count")->setText(selection_info.str()); - - bool have_selection = !LLSelectMgr::getInstance()->getSelection()->isEmpty(); - childSetVisible("selection_count", have_selection); + sel_count->setText(getString("status_selectcount", selection_args)); + } + sel_count->setVisible(have_selection); //childSetVisible("remaining_capacity", have_selection); childSetVisible("selection_empty", !have_selection); } diff --git a/indra/newview/llgiveinventory.cpp b/indra/newview/llgiveinventory.cpp index 59d7e0083..73bc6cd83 100644 --- a/indra/newview/llgiveinventory.cpp +++ b/indra/newview/llgiveinventory.cpp @@ -36,6 +36,7 @@ #include "llagentdata.h" #include "llagentui.h" #include "llagentwearables.h" +#include "llavataractions.h" #include "llfloaterchat.h" //for addChatHistory #include "llfloatertools.h" // for gFloaterTool #include "llhudeffecttrail.h" @@ -348,13 +349,9 @@ void LLGiveInventory::logInventoryOffer(const LLUUID& to_agent, const LLUUID &im // If this item was given by drag-and-drop on avatar while IM panel wasn't open, log this action to IM history. else { - std::string full_name; - if (gCacheName->getFullName(to_agent, full_name)) - { - LLChat chat(LLTrans::getString("inventory_item_offered_to") + " " + full_name); - chat.mSourceType = CHAT_SOURCE_SYSTEM; - LLFloaterChat::addChatHistory(chat); - } + LLChat chat(LLTrans::getString("inventory_item_offered_to") + ' ' + LLAvatarActions::getSLURL(to_agent)); + chat.mSourceType = CHAT_SOURCE_SYSTEM; + LLFloaterChat::addChatHistory(chat); } } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index bbd5224d2..756466117 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1738,7 +1738,7 @@ void LLItemBridge::restoreToWorld() //Similar functionality to the drag and drop rez logic bool no_copy = !itemp->getPermissions().allowCopyBy(gAgentID); if (no_copy && gHippoGridManager->getCurrentGrid()->isSecondLife()) - LLNotificationsUtil::add("RestoreToWorldConfirm", LLSD(), LLSD(), boost::bind(restore_to_world, itemp, true, !boost::bind(LLNotification::getSelectedOption, _1, _2))); + LLNotificationsUtil::add("RezRestoreToWorld", LLSD(), LLSD(), boost::bind(restore_to_world, itemp, true, !boost::bind(LLNotification::getSelectedOption, _1, _2))); else restore_to_world(itemp, no_copy); } diff --git a/indra/newview/llmediaremotectrl.cpp b/indra/newview/llmediaremotectrl.cpp index e4055c567..e6d0aece1 100644 --- a/indra/newview/llmediaremotectrl.cpp +++ b/indra/newview/llmediaremotectrl.cpp @@ -289,7 +289,7 @@ void LLMediaRemoteCtrl::enableMediaButtons() { sLastTooltip = info_text; LLChat chat; - chat.mText = getString("Now_playing") + " " + info_text; + chat.mText = getString("Now_playing") + ' ' + info_text; chat.mSourceType = CHAT_SOURCE_SYSTEM; // Lie to RLVa so it won't filter this chat.mRlvLocFiltered = true; diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index f6ebe00bf..efe7230c8 100644 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -58,6 +58,7 @@ #include "llxfermanager.h" #include "llagent.h" +#include "llavataractions.h" #include "llviewergenericmessage.h" // for gGenericDispatcher #include "llworld.h" //for particle system banning #include "llfloaterchat.h" @@ -458,7 +459,7 @@ void LLMuteList::updateRemove(const LLMute& mute) gAgent.sendReliableMessage(); } -void notify_automute_callback(const LLUUID& agent_id, const std::string& full_name, bool is_group, LLMuteList::EAutoReason reason) +static void notify_automute_callback(const LLUUID& agent_id, const LLMuteList::EAutoReason& reason) { std::string notif_name; switch (reason) @@ -475,11 +476,7 @@ void notify_automute_callback(const LLUUID& agent_id, const std::string& full_na break; } - LLSD args; - args["NAME"] = full_name; - - LLNotificationPtr notif_ptr = LLNotifications::instance().add(notif_name, args, LLSD()); - if (notif_ptr) + if (auto notif_ptr = LLNotifications::instance().add(notif_name, LLSD().with("NAME", LLAvatarActions::getSLURL(agent_id)), LLSD())) { std::string message = notif_ptr->getMessage(); @@ -506,18 +503,7 @@ BOOL LLMuteList::autoRemove(const LLUUID& agent_id, const EAutoReason reason) removed = TRUE; remove(automute); - std::string full_name; - if (gCacheName->getFullName(agent_id, full_name)) - { - // name in cache, call callback directly - notify_automute_callback(agent_id, full_name, false, reason); - } - else - { - // not in cache, lookup name from cache - gCacheName->get(agent_id, false, - boost::bind(¬ify_automute_callback, _1, _2, _3, reason)); - } + notify_automute_callback(agent_id, reason); } return removed; diff --git a/indra/newview/llnamebox.cpp b/indra/newview/llnamebox.cpp index f09bf0e63..28a465a57 100644 --- a/indra/newview/llnamebox.cpp +++ b/indra/newview/llnamebox.cpp @@ -33,6 +33,7 @@ #include "llviewerprecompiledheaders.h" #include "llnamebox.h" +#include "llwindow.h" static LLRegisterWidget r("name_box"); @@ -66,6 +67,18 @@ BOOL LLNameBox::handleRightMouseDown(S32 x, S32 y, MASK mask) return handled; } +// virtual +BOOL LLNameBox::handleHover(S32 x, S32 y, MASK mask) +{ + auto handled = LLTextBox::handleHover(x, y, mask); + if (mAllowInteract) + { + getWindow()->setCursor(UI_CURSOR_HAND); + handled = true; + } + return handled; +} + // virtual void LLNameBox::initFromXML(LLXMLNodePtr node, LLView* parent) { diff --git a/indra/newview/llnamebox.h b/indra/newview/llnamebox.h index 8d0005c75..52992d0eb 100644 --- a/indra/newview/llnamebox.h +++ b/indra/newview/llnamebox.h @@ -50,6 +50,7 @@ public: LLSD getValue() const override final { return LLNameUI::getValue(); } BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override final; + BOOL handleHover(S32 x, S32 y, MASK mask) override final; protected: LLNameBox(const std::string& name); diff --git a/indra/newview/llnameeditor.cpp b/indra/newview/llnameeditor.cpp index a88cd5f05..e69161cbe 100644 --- a/indra/newview/llnameeditor.cpp +++ b/indra/newview/llnameeditor.cpp @@ -36,6 +36,7 @@ #include "llmenugl.h" #include "lluictrlfactory.h" +#include "llwindow.h" static LLRegisterWidget r("name_editor"); @@ -90,6 +91,18 @@ BOOL LLNameEditor::handleRightMouseDown(S32 x, S32 y, MASK mask) return LLLineEditor::handleRightMouseDown(x, y, mask); } +// virtual +BOOL LLNameEditor::handleHover(S32 x, S32 y, MASK mask) +{ + auto handled = LLLineEditor::handleHover(x, y, mask); + if (mAllowInteract && mClickForProfile && !mIsSelecting) + { + getWindow()->setCursor(UI_CURSOR_HAND); + handled = true; + } + return handled; +} + void LLNameEditor::displayAsLink(bool link) { static const LLUICachedControl color("HTMLAgentColor"); @@ -108,6 +121,9 @@ LLXMLNodePtr LLNameEditor::getXML(bool save_children) const LLXMLNodePtr node = LLLineEditor::getXML(); node->setName(LL_NAME_EDITOR_TAG); + node->createChild("label", TRUE)->setStringValue(mInitialValue); + node->createChild("rlv_sensitive", TRUE)->setBoolValue(mRLVSensitive); + node->createChild("click_for_profile", TRUE)->setBoolValue(mClickForProfile); return node; } diff --git a/indra/newview/llnameeditor.h b/indra/newview/llnameeditor.h index abb8bdfda..3453906c2 100644 --- a/indra/newview/llnameeditor.h +++ b/indra/newview/llnameeditor.h @@ -53,6 +53,7 @@ public: BOOL handleMouseDown(S32 x, S32 y, MASK mask) override final; BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override final; + BOOL handleHover(S32 x, S32 y, MASK mask) override final; LLXMLNodePtr getXML(bool save_children = true) const override final; static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index df6b342d3..9fe61950d 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -198,7 +198,9 @@ void LLPanelAvatarSecondLife::processProperties(void* data, EAvatarProcessorType { date birthday(year, month, day), today(day_clock::local_day()); std::ostringstream born_on; - born_on << pAvatarData->born_on << " (" << today - birthday << ')'; + const std::locale fmt(std::locale::classic(), new date_facet(gSavedSettings.getString("ShortDateFormat").data())); + born_on.imbue(fmt); + born_on << birthday << " (" << today - birthday << ')'; childSetValue("born", born_on.str()); } else childSetValue("born", born); diff --git a/indra/newview/llpanelgeneral.cpp b/indra/newview/llpanelgeneral.cpp index d794e43da..30a0e6430 100644 --- a/indra/newview/llpanelgeneral.cpp +++ b/indra/newview/llpanelgeneral.cpp @@ -87,7 +87,7 @@ BOOL LLPanelGeneral::postBuild() childSetValue("ui_auto_scale", gSavedSettings.getBOOL("UIAutoScale")); LLComboBox* crash_behavior_combobox = getChild("crash_behavior_combobox"); - crash_behavior_combobox->setCurrentByIndex(gSavedSettings.getS32(CRASH_BEHAVIOR_SETTING)); + crash_behavior_combobox->setValue(gSavedSettings.getS32("CrashSubmitBehavior")); childSetValue("language_combobox", gSavedSettings.getString("Language")); @@ -163,7 +163,7 @@ void LLPanelGeneral::apply() gSavedSettings.setString("Language", childGetValue("language_combobox")); LLComboBox* crash_behavior_combobox = getChild("crash_behavior_combobox"); - gSavedSettings.setS32(CRASH_BEHAVIOR_SETTING, crash_behavior_combobox->getCurrentIndex()); + gSavedSettings.setS32("CrashSubmitBehavior", crash_behavior_combobox->getValue()); } void LLPanelGeneral::cancel() diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index 0b9ace614..86b6054e4 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -83,7 +83,6 @@ LLPanelGroupGeneral::LLPanelGroupGeneral(const std::string& name, mGroupNameEditor(NULL), mFounderName(NULL), mInsignia(NULL), - mGroupName(NULL), mEditCharter(NULL), mBtnJoinGroup(NULL), mListVisibleMembers(NULL), @@ -121,7 +120,6 @@ BOOL LLPanelGroupGeneral::postBuild() // General info mGroupNameEditor = getChild("group_name_editor", recurse); - mGroupName = getChild("group_name", recurse); mInsignia = getChild("insignia", recurse); if (mInsignia) @@ -263,7 +261,7 @@ BOOL LLPanelGroupGeneral::postBuild() mBtnJoinGroup->setVisible(FALSE); mBtnInfo->setVisible(FALSE); - mGroupName->setVisible(FALSE); + getChildView("group_name")->setVisible(FALSE); } std::string member_count(LLTrans::getString("LoadingData")); @@ -732,7 +730,7 @@ void LLPanelGroupGeneral::update(LLGroupChange gc) if (mInsignia) mInsignia->setEnabled(can_change_ident); if (mEditCharter) mEditCharter->setEnabled(can_change_ident); - if (mGroupName) mGroupName->setValue(mGroupID); + getChildView("group_name")->setValue(mGroupID); if (mGroupNameEditor) mGroupNameEditor->setVisible(FALSE); if (mFounderName) mFounderName->setValue(gdatap->mFounderID); @@ -907,7 +905,6 @@ void LLPanelGroupGeneral::updateChanged() LLUICtrl *check_list[] = { mGroupNameEditor, - mGroupName, mFounderName, mInsignia, mEditCharter, diff --git a/indra/newview/llpanelgroupgeneral.h b/indra/newview/llpanelgroupgeneral.h index 00b9c7fc9..aa54e83b7 100644 --- a/indra/newview/llpanelgroupgeneral.h +++ b/indra/newview/llpanelgroupgeneral.h @@ -91,7 +91,6 @@ private: // Group information (include any updates in updateChanged) LLLineEditor *mGroupNameEditor; - LLNameBox *mGroupName; LLNameBox *mFounderName; LLTextureCtrl *mInsignia; LLTextEditor *mEditCharter; diff --git a/indra/newview/llpanelnetwork.cpp b/indra/newview/llpanelnetwork.cpp index 3d7a03593..ebf19eb5f 100644 --- a/indra/newview/llpanelnetwork.cpp +++ b/indra/newview/llpanelnetwork.cpp @@ -74,17 +74,32 @@ BOOL LLPanelNetwork::postBuild() } childSetValue("max_bandwidth", gSavedSettings.getF32("ThrottleBandwidthKBPS")); childSetValue("tex_bandwidth", gSavedSettings.getF32("HTTPThrottleBandwidth")); - childSetValue("http_textures", gSavedSettings.getBOOL("ImagePipelineUseHTTP")); - childSetValue("http_inventory", gSavedSettings.getBOOL("UseHTTPInventory")); childSetValue("connection_port_enabled", gSavedSettings.getBOOL("ConnectionPortEnabled")); childSetValue("connection_port", (F32)gSavedSettings.getU32("ConnectionPort")); - // If in Avination, hide the texture bandwidth slider, Avination throttles server-side - if (gHippoGridManager->getConnectedGrid()->isAvination()) + const auto& grid = gHippoGridManager->getConnectedGrid(); + if (!grid->isSecondLife()) { - childSetVisible("text_box4", FALSE); - childSetVisible("tex_bandwidth", FALSE); - childSetVisible("text_box3", FALSE); + if (auto view = getChildView("use_http_for")) + view->setVisible(true); + if (auto view = getChildView("http_textures")) + { + view->setVisible(true); + view->setValue(gSavedSettings.getBOOL("ImagePipelineUseHTTP")); + } + if (auto view = getChildView("http_inventory")) + { + view->setVisible(true); + view->setValue(gSavedSettings.getBOOL("UseHTTPInventory")); + } + + // If in Avination, hide the texture bandwidth slider, Avination throttles server-side + if (grid->isAvination()) + { + childSetVisible("text_box4", FALSE); + childSetVisible("tex_bandwidth", FALSE); + childSetVisible("text_box3", FALSE); + } } // Socks 5 proxy settings, commit callbacks @@ -124,9 +139,15 @@ void LLPanelNetwork::apply() { gSavedSettings.setU32("CacheSize", childGetValue("cache_size").asInteger()); gSavedSettings.setF32("ThrottleBandwidthKBPS", childGetValue("max_bandwidth").asReal()); - gSavedSettings.setF32("HTTPThrottleBandwidth", childGetValue("tex_bandwidth").asReal()); - gSavedSettings.setBOOL("ImagePipelineUseHTTP", childGetValue("http_textures")); - gSavedSettings.setBOOL("UseHTTPInventory", childGetValue("http_inventory")); + if (const auto& view = getChildView("tex_bandwidth")) + if (view->getVisible()) + gSavedSettings.setF32("HTTPThrottleBandwidth", view->getValue().asReal()); + if (const auto& view = getChildView("http_textures")) + if (view->getVisible()) + gSavedSettings.setBOOL("ImagePipelineUseHTTP", view->getValue()); + if (const auto& view = getChildView("http_inventory")) + if (view->getVisible()) + gSavedSettings.setBOOL("UseHTTPInventory", view->getValue()); gSavedSettings.setBOOL("ConnectionPortEnabled", childGetValue("connection_port_enabled")); gSavedSettings.setU32("ConnectionPort", childGetValue("connection_port").asInteger()); diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 2f6ba27e4..d4693dee8 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -120,25 +120,6 @@ LLParticipantList::~LLParticipantList() mAvatarListRefreshConnection.disconnect(); mAvatarListReturnConnection.disconnect(); mAvatarListToggleIconsConnection.disconnect(); - - // It is possible Participant List will be re-created from LLCallFloater::onCurrentChannelChanged() - // See ticket EXT-3427 - // hide menu before deleting it to stop enable and check handlers from triggering. - if(mParticipantListMenu && !LLApp::isExiting()) - { - mParticipantListMenu->hide(); - } - - if (mParticipantListMenu) - { - delete mParticipantListMenu; - mParticipantListMenu = NULL; - } - - mAvatarList->setContextMenu(NULL); - mAvatarList->setComparator(NULL); - - delete mAvalineUpdater; */ } diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 2f7415bdd..75afa197f 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -45,6 +45,7 @@ #include "llfloatersearchreplace.h" #include "llinventorymodel.h" #include "lllineeditor.h" +#include "llmenugl.h" #include "llnotificationsutil.h" #include "llresmgr.h" #include "roles_constants.h" diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index a60f31f9a..7cb3be329 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -5451,13 +5451,6 @@ void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data dialog_refresh_all(); - // silly hack to allow 'save into inventory' - if(gPopupMenuView->getVisible()) - { - gPopupMenuView->setItemEnabled(SAVE_INTO_INVENTORY, - enable_save_into_inventory(NULL)); - } - // hack for left-click buy object LLToolPie::selectionPropertiesReceived(); } diff --git a/indra/newview/llstylemap.cpp b/indra/newview/llstylemap.cpp index ff6159e4e..fb6dad7a2 100644 --- a/indra/newview/llstylemap.cpp +++ b/indra/newview/llstylemap.cpp @@ -33,6 +33,7 @@ #include "llviewerprecompiledheaders.h" #include "llstylemap.h" +#include "llavataractions.h" LLStyleMap::LLStyleMap() { @@ -59,8 +60,7 @@ const LLStyleSP &LLStyleMap::lookupAgent(const LLUUID &source) if (source.notNull()) { style->setColor(gSavedSettings.getColor4("HTMLAgentColor")); - std::string link = llformat("secondlife:///app/agent/%s/about",source.asString().c_str()); - style->setLinkHREF(link); + style->setLinkHREF(LLAvatarActions::getSLURL(source)); } (*this)[source] = style; } diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 3d62acf8c..192f2bc9f 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -75,7 +75,6 @@ // // tag: vaa emerald local_asset_browser [begin] -//#include #include "floaterlocalassetbrowse.h" #include "llscrolllistctrl.h" #define LOCALLIST_COL_ID 1 @@ -298,10 +297,9 @@ void LLFloaterTexturePicker::setImageID(const LLUUID& image_id) } /* TODO: Figure out how to select local asset if in use? // tag: vaa emerald local_asset_browser [begin] - else if (boost::algorithm::any_of_equal(mLocalScrollCtrl->getAllIDs(), mImageAssetID)) + else if (mLocalScrollCtrl->selectByID(mImageAssetID)) { tab = "local_tab"; - mLocalScrollCtrl->selectByID(mImageAssetID); } // tag: vaa emerald local_asset_browser [end] */ @@ -966,7 +964,7 @@ void LLFloaterTexturePicker::onBtnBrowser(void *userdata) // reacts to user clicking a valid field in the local scroll list. void LLFloaterTexturePicker::onLocalScrollCommit() { - LLUUID id(mLocalScrollCtrl->getSelectedItemLabel(LOCALLIST_COL_ID)); + LLUUID id(mLocalScrollCtrl->getStringUUIDSelectedItem()); mOwner->setImageAssetID(id); if (childGetValue("apply_immediate_check").asBoolean()) @@ -1473,9 +1471,10 @@ BOOL LLTextureCtrl::handleMouseDown(S32 x, S32 y, MASK mask) // if(!mEnable) return FALSE; - BOOL handled = LLUICtrl::handleMouseDown( x, y , mask ); + const auto clicked_picture = mBorder->parentPointInView(x, y); + BOOL handled = (mCaption->getText().empty() || clicked_picture) && LLUICtrl::handleMouseDown( x, y , mask ); - if (!handled && mBorder->parentPointInView(x, y)) + if (!handled && clicked_picture) { showPicker(FALSE); //grab textures first... diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp index 912a3a341..b628851bb 100644 --- a/indra/newview/lltoolcomp.cpp +++ b/indra/newview/lltoolcomp.cpp @@ -758,7 +758,7 @@ BOOL LLToolCompGun::handleHover(S32 x, S32 y, MASK mask) { // *NOTE: This hack is here to make mouselook kick in again after // item selected from context menu. - if ( mCur == mNull && !gPopupMenuView->getVisible() ) + if (mCur == mNull) { LLSelectMgr::getInstance()->deselectAll(); setCurrentTool( (LLTool*) mGrab ); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index f7f8d22cb..1e4e210f2 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -94,7 +94,6 @@ AIThreadSafeDC gSettings; LLControlGroup gSavedSettings("Global"); // saved at end of session LLControlGroup gSavedPerAccountSettings("PerAccount"); // saved at end of session LLControlGroup gColors("Colors"); // saved at end of session -LLControlGroup gCrashSettings("CrashSettings"); // saved at end of session std::string gLastRunVersion; diff --git a/indra/newview/llviewercontrol.h b/indra/newview/llviewercontrol.h index 0fd6b9cd4..203c5cfb3 100644 --- a/indra/newview/llviewercontrol.h +++ b/indra/newview/llviewercontrol.h @@ -62,9 +62,6 @@ void create_graphics_group(LLControlGroup& group); // Read-only extern LLControlGroup gColors; -// Saved at end of session -extern LLControlGroup gCrashSettings; - // Set after settings loaded extern std::string gLastRunVersion; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index d182ed75e..171abfce2 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -206,7 +206,6 @@ extern AIHTTPView* gHttpView; LLMenuBarGL *gMenuBarView = NULL; LLViewerMenuHolderGL *gMenuHolder = NULL; -LLMenuGL *gPopupMenuView = NULL; LLMenuBarGL *gLoginMenuBarView = NULL; // Pie menus @@ -220,7 +219,6 @@ LLContextMenu *gPieLand = NULL; const std::string CLIENT_MENU_NAME("Advanced"); const std::string SERVER_MENU_NAME("Admin"); -const std::string SAVE_INTO_INVENTORY("Save Object Back to My Inventory"); const std::string SAVE_INTO_TASK_INVENTORY("Save Object Back to Object Contents"); LLMenuGL* gAttachSubMenu = NULL; @@ -453,7 +451,6 @@ BOOL enable_land_selected( void* ); BOOL enable_more_than_one_selected(void* ); BOOL enable_selection_you_own_all(void*); BOOL enable_selection_you_own_one(void*); -BOOL enable_save_into_inventory(void*); BOOL enable_save_into_task_inventory(void*); BOOL enable_detach(const LLSD& = LLSD()); @@ -637,16 +634,6 @@ void init_menus() // Initialize actions initialize_menus(); - /// - /// Popup menu - /// - /// The popup menu is now populated by the show_context_menu() - /// method. - - gPopupMenuView = new LLMenuGL( "Popup" ); - gPopupMenuView->setVisible( FALSE ); - gMenuHolder->addChild( gPopupMenuView ); - /// /// Pie menus /// @@ -659,9 +646,6 @@ void init_menus() /// LLColor4 color; - color = gColors.getColor( "MenuPopupBgColor" ); - gPopupMenuView->setBackgroundColor( color ); - // If we are not in production, use a different color to make it apparent. if (LLViewerLogin::getInstance()->isInProductionGrid()) { @@ -1769,9 +1753,6 @@ void cleanup_menus() delete gMenuBarView; gMenuBarView = NULL; - delete gPopupMenuView; - gPopupMenuView = NULL; - delete gMenuHolder; gMenuHolder = NULL; @@ -5131,7 +5112,8 @@ class LLToolsSaveToInventory : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - if(enable_save_into_inventory(NULL)) + bool enable_save_into_inventory(); + if(enable_save_into_inventory()) { derez_objects(DRD_SAVE_INTO_AGENT_INVENTORY, LLUUID::null); } @@ -7664,7 +7646,7 @@ bool LLHasAsset::operator()(LLInventoryCategory* cat, return FALSE; } -BOOL enable_save_into_inventory(void*) +bool enable_save_into_inventory() { // *TODO: clean this up // find the last root diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index 29d46def8..a52f8682f 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -48,7 +48,6 @@ void cleanup_menus(); void show_debug_menus(); // checks for if menus should be shown first. void show_context_menu( S32 x, S32 y, MASK mask ); void show_build_mode_context_menu(S32 x, S32 y, MASK mask); -BOOL enable_save_into_inventory(void*); void handle_reset_view(); void handle_cut(void*); void handle_copy(void*); @@ -159,11 +158,8 @@ protected: LLSafeHandle mObjectSelection; }; -extern const std::string SAVE_INTO_INVENTORY; - extern LLMenuBarGL* gMenuBarView; //extern LLView* gMenuBarHolder; -extern LLMenuGL* gPopupMenuView; extern LLViewerMenuHolderGL* gMenuHolder; extern LLMenuBarGL* gLoginMenuBarView; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index f2d83efa2..c23ffa186 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2219,12 +2219,10 @@ std::string replace_wildcards(std::string input, const LLUUID& id, const std::st void autoresponder_finish(bool show_autoresponded, const LLUUID& session_id, const LLUUID& from_id, const std::string& name, const LLUUID& itemid, bool is_muted) { - LLAvatarName av_name; - const std::string ns_name(LLAvatarNameCache::get(from_id, &av_name) ? av_name.getNSName() : name); void cmdline_printchat(const std::string& message); if (show_autoresponded) { - const std::string notice(LLTrans::getString("IM_autoresponded_to") + ' ' + ns_name); + const std::string notice(LLTrans::getString("IM_autoresponded_to") + ' ' + LLAvatarActions::getSLURL(from_id)); is_muted ? cmdline_printchat(notice) : gIMMgr->addMessage(session_id, from_id, name, notice); } if (LLViewerInventoryItem* item = gInventory.getItem(itemid)) @@ -2232,7 +2230,7 @@ void autoresponder_finish(bool show_autoresponded, const LLUUID& session_id, con LLGiveInventory::doGiveInventoryItem(from_id, item, session_id); if (show_autoresponded) { - const std::string notice(llformat("%s %s \"%s\"", ns_name.c_str(), LLTrans::getString("IM_autoresponse_sent_item").c_str(), item->getName().c_str())); + const std::string notice(llformat("%s %s \"%s\"", LLAvatarActions::getSLURL(from_id).data(), LLTrans::getString("IM_autoresponse_sent_item").c_str(), item->getName().c_str())); is_muted ? cmdline_printchat(notice) : gIMMgr->addMessage(session_id, from_id, name, notice); } } @@ -2803,12 +2801,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) info->mTransactionID = session_id; info->mType = (LLAssetType::EType) asset_type; info->mFolderID = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(info->mType)); - std::string from_name; - - from_name += LLTrans::getString("AGroupMemberNamed") + " "; - from_name += name; - - info->mFromName = from_name; + info->mFromName = LLTrans::getString("AGroupMemberNamed", LLSD().with("GROUP_ID", group_id).with("FROM_ID", from_id)); info->mDesc = item_name; info->mHost = msg->getSender(); } @@ -3368,7 +3361,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // if (IM_LURE_USER == dialog) - gAgent.showLureDestination(name, region_handle, pos.mV[VX], pos.mV[VY], pos.mV[VZ]); + gAgent.showLureDestination(LLAvatarActions::getSLURL(from_id), region_handle, pos.mV[VX], pos.mV[VY], pos.mV[VZ]); script_msg_api(from_id.asString().append(IM_LURE_USER == dialog ? ", 2" : ", 3")); // } @@ -3733,7 +3726,7 @@ private: }; #endif -void add_floater_chat(const LLChat &chat, const BOOL history) +void add_floater_chat(LLChat &chat, const BOOL history) { if (history) { @@ -7174,7 +7167,7 @@ void chat_mean_collision(const LLUUID& id, const LLAvatarName& avname, const EMe args["MAG"] = llformat("%f", mag); LLChat chat(LLTrans::getString("BumpedYou", args)); chat.mFromName = name; - chat.mURL = llformat("secondlife:///app/agent/%s/about", id.asString().c_str()); + chat.mURL = LLAvatarActions::getSLURL(id); chat.mSourceType = CHAT_SOURCE_SYSTEM; LLFloaterChat::addChat(chat); } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index e59ef3eb3..f9b36e00d 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -45,6 +45,7 @@ #include "llagentcamera.h" #include "llagentwearables.h" #include "llanimationstates.h" +#include "llavataractions.h" #include "llavatarnamecache.h" #include "llavatarpropertiesprocessor.h" #include "llcontrolavatar.h" @@ -6427,8 +6428,8 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL LLAvatarNameCache::getNSName(mID, name); LLChat chat; chat.mFromName = name; - chat.mText = name + " " + LLTrans::getString("took_a_snapshot") + "."; - chat.mURL = llformat("secondlife:///app/agent/%s/about",mID.asString().c_str()); + chat.mText = name + ' ' + LLTrans::getString("took_a_snapshot") + '.'; + chat.mURL = LLAvatarActions::getSLURL(mID); chat.mSourceType = CHAT_SOURCE_SYSTEM; LLFloaterChat::addChat(chat); } diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 7d9dcdb20..292524dd8 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -2892,6 +2892,8 @@ void LLVOAvatarSelf::requestLayerSetUpdate(ETextureIndex index ) if( mUpperBodyLayerSet ) mUpperBodyLayerSet->requestUpdate(); */ const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture(index); + if (!texture_dict) + return; if (!texture_dict->mIsLocalTexture || !texture_dict->mIsUsedByBakedTexture) return; const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; @@ -2908,7 +2910,7 @@ LLViewerTexLayerSet* LLVOAvatarSelf::getLayerSet(ETextureIndex index) const case TEX_HEAD_BODYPAINT: return mHeadLayerSet; */ const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture(index); - if (texture_dict->mIsUsedByBakedTexture) + if (texture_dict && texture_dict->mIsUsedByBakedTexture) { const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; return getLayerSet(baked_index); diff --git a/indra/newview/res/viewerRes.rc.in b/indra/newview/res/viewerRes.rc.in index 97859af50..44c8104aa 100644 --- a/indra/newview/res/viewerRes.rc.in +++ b/indra/newview/res/viewerRes.rc.in @@ -2,12 +2,6 @@ // #include "resource.h" -#ifdef IDC_STATIC -#undef IDC_STATIC -#endif -#define IDC_STATIC (-1) -#include "winresrc.h" - #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml index 495e6d8ef..9c95ef0bd 100644 --- a/indra/newview/skins/default/xui/de/strings.xml +++ b/indra/newview/skins/default/xui/de/strings.xml @@ -352,7 +352,6 @@ Steuerung neu zuweisen Avatar animieren An Avatar anhängen - A group member named Eigentum aufgeben und öffentlich machen Mit Objekten verknüpfen und davon trennen Verbindungen zu anderen Objekten hinzufügen und entfernen diff --git a/indra/newview/skins/default/xui/en-us/floater_new_outfit_dialog.xml b/indra/newview/skins/default/xui/en-us/floater_new_outfit_dialog.xml index a07137430..639919f06 100644 --- a/indra/newview/skins/default/xui/en-us/floater_new_outfit_dialog.xml +++ b/indra/newview/skins/default/xui/en-us/floater_new_outfit_dialog.xml @@ -7,223 +7,224 @@ label="Save" label_selected="Save" left="171" mouse_opaque="true" name="Save" scale_image="true" width="82" />