diff --git a/.gitignore b/.gitignore index 4b9a7a4cd6..b47f28773e 100755 --- a/.gitignore +++ b/.gitignore @@ -111,3 +111,5 @@ compile_commands.json # ignore tracy for now indra/tracy firestorm.code-workspace + +.cache/clangd/index/ diff --git a/autobuild.xml b/autobuild.xml index 3ec2dd5271..7579bf3d3e 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3,6 +3,62 @@ installables + glib + + copyright + Copyright (C) glib project + license + LGPL + license_file + LICENSES/glib.txt + name + glib + platforms + + linux64 + + archive + + hash + 9c93ba8b8af97fc8379f77de77e1540a + url + http://3p.firestormviewer.org/glib-2.48.0.202301938-linux64-202301938.tar.bz2 + + name + linux + + + version + 2.48.0 + + fltk + + copyright + Copyright (C) fltk project + license + LGPL/fltk + license_file + LICENSES/fltk.txt + name + fltk + platforms + + linux64 + + archive + + hash + 81fe1e927e4fe3c5e5f15ce6219ca883 + url + http://3p.firestormviewer.org/fltk-1.3.5.202282121-linux64-202282121.tar.bz2 + + name + linux + + + version + 1.3.5 + jemalloc copyright @@ -787,48 +843,6 @@ version 5.1.25 - dbus_glib - - copyright - Copyright (C) Red Hat Inc. - description - D-Bus bindings for glib - license - Academic Free License v. 2.1 - license_file - LICENSES/dbus-glib.txt - name - dbus_glib - platforms - - linux - - archive - - hash - 9591dcb7efce2a770d77e907705e1492 - url - http://3p.firestormviewer.org/dbus_glib-0.76-linux-180871236.tar.bz2 - - name - linux - - linux64 - - archive - - hash - 5a685a65a7066937ef580dcd5a90f9dc - url - http://3p.firestormviewer.org/dbus_glib-0.76-linux64-180841549.tar.bz2 - - name - linux64 - - - version - 0.76 - dictionaries copyright @@ -1058,11 +1072,11 @@ archive hash - bde9eb3e53001584edb1af44e3b265a2 + 2db00aa4126d4ee8152fc49b03bb3fe1 hash_algorithm md5 url - file:///opt/firestorm/fmodstudio-2.02.04-darwin-213491614.tar.bz2 + file:///opt/firestorm/fmodstudio-2.02.05-darwin-220160006.tar.bz2 name darwin @@ -1577,46 +1591,6 @@ version 0.10.6.314267 - gtk-atk-pango-glib - - copyright - Copyright (various, see sources) - license - lgpl - license_file - LICENSES/gtk-atk-pango-glib.txt - name - gtk-atk-pango-glib - platforms - - linux - - archive - - hash - fb047d496c32cc3b9f99793ee6ebb1e3 - url - http://3p.firestormviewer.org/gtk_atk_pango_glib-2.1-linux-180871647.tar.bz2 - - name - linux - - linux64 - - archive - - hash - d918d894430c1d1d869b9f2e06570c65 - url - http://3p.firestormviewer.org/gtk_atk_pango_glib-2.1-linux64-180841902.tar.bz2 - - name - linux64 - - - version - 2.1 - havok-source copyright diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 74d32defea..2d4031d101 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -20,7 +20,7 @@ set(cmake_SOURCE_FILES ConfigurePkgConfig.cmake CURL.cmake Copy3rdPartyLibs.cmake - DBusGlib.cmake + GLIB.cmake DeploySharedLibs.cmake Discord.cmake # Discord rich presence DragDrop.cmake diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index c262d7f209..519f68b53e 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -245,16 +245,9 @@ elseif(LINUX) # have to deal with if (NOT USESYSTEMLIBS) set(release_files - #libapr-1.so.0 - #libaprutil-1.so.0 - libatk-1.0.so #libdb-5.1.so ${EXPAT_COPY} - #libfreetype.so.6.6.2 - #libfreetype.so.6 #libGLOD.so - libgmodule-2.0.so - libgobject-2.0.so libhunspell-1.3.so.0.0.0 libopenal.so #libopenjpeg.so diff --git a/indra/cmake/DBusGlib.cmake b/indra/cmake/DBusGlib.cmake deleted file mode 100644 index 5e46b6711a..0000000000 --- a/indra/cmake/DBusGlib.cmake +++ /dev/null @@ -1,29 +0,0 @@ -# -*- cmake -*- -include(Prebuilt) - -if (USESYSTEMLIBS) - include(FindPkgConfig) - - pkg_check_modules(DBUSGLIB REQUIRED dbus-glib-1) - -elseif (LINUX) - use_prebuilt_binary(dbus_glib) - set(DBUSGLIB_FOUND ON FORCE BOOL) - set(DBUSGLIB_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/include/dbus - ) - # We don't need to explicitly link against dbus-glib itself, because - # the viewer probes for the system's copy at runtime. - set(DBUSGLIB_LIBRARIES - gobject-2.0 - glib-2.0 - ) -endif (USESYSTEMLIBS) - -if (DBUSGLIB_FOUND) - set(DBUSGLIB ON CACHE BOOL "Build with dbus-glib message bus support.") -endif (DBUSGLIB_FOUND) - -if (DBUSGLIB) - add_definitions(-DLL_DBUS_ENABLED=1) -endif (DBUSGLIB) diff --git a/indra/cmake/FreeType.cmake b/indra/cmake/FreeType.cmake index df267985c4..79159843e1 100644 --- a/indra/cmake/FreeType.cmake +++ b/indra/cmake/FreeType.cmake @@ -9,7 +9,11 @@ else (USESYSTEMLIBS) use_prebuilt_binary(freetype) set(FREETYPE_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) set(FREETYPE_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/freetype2) # Also add freetype2 to search dir, or some includes will fail. - set(FREETYPE_LIBRARIES freetype) + # Linux links this via UI.cmake + if( NOT LINUX ) + set(FREETYPE_LIBRARIES freetype) + endif() + # endif (USESYSTEMLIBS) link_directories(${FREETYPE_LIBRARY_DIRS}) diff --git a/indra/cmake/GLIB.cmake b/indra/cmake/GLIB.cmake new file mode 100644 index 0000000000..ce0ac3e76f --- /dev/null +++ b/indra/cmake/GLIB.cmake @@ -0,0 +1,11 @@ + +include(Prebuilt) + +if( LINUX ) + use_prebuilt_binary(glib) + set(GLIB_FOUND ON CACHE BOOL "Build against glib 2") + set(GLIB_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/glib-2.0 ${LIBS_PREBUILT_DIR}/lib/release/glib-2.0/include ) + set(GLIB_LIBRARIES libgobject-2.0.a libglib-2.0.a libffi.a libpcre.a) + set(GIO_LIBRARIES libgio-2.0.a libgmodule-2.0.a -lresolv) + add_definitions(-DLL_GLIB=1) +endif() diff --git a/indra/cmake/Hunspell.cmake b/indra/cmake/Hunspell.cmake index 06227b3fe2..34e0fb3c35 100644 --- a/indra/cmake/Hunspell.cmake +++ b/indra/cmake/Hunspell.cmake @@ -13,7 +13,7 @@ else (USESYSTEMLIBS) elseif(DARWIN) set(HUNSPELL_LIBRARY hunspell-1.3) elseif(LINUX) - set(HUNSPELL_LIBRARY hunspell-1.3) + set(HUNSPELL_LIBRARY libhunspell-1.3.a) else() message(FATAL_ERROR "Invalid platform") endif() diff --git a/indra/cmake/MediaPluginBase.cmake b/indra/cmake/MediaPluginBase.cmake index 2be035b641..cde56fb5e4 100644 --- a/indra/cmake/MediaPluginBase.cmake +++ b/indra/cmake/MediaPluginBase.cmake @@ -1,5 +1,32 @@ # -*- cmake -*- +# Try to find pulse header, if we got them we can use the linux volume catcher +if (LINUX) + include(GLIB) + + include_directories( ${GLIB_INCLUDE_DIRS} ) + + set( PULSE_AUDIO True ) + foreach( PULSE_FILE pulse/introspect.h pulse/context.h pulse/subscribe.h pulse/glib-mainloop.h ) + find_path( PULSE_FILE_FOUND ${PULSE_FILE} NO_CACHE) + if( NOT PULSE_FILE_FOUND ) + message( "Looking for ${PULSE_FILE} ... not found") + set( PULSE_AUDIO False ) + else() + message( "Looking for ${PULSE_FILE} ... found") + endif() + endforeach() + + if( NOT PULSE_AUDIO ) + message( "Building without linux volume catcher" ) + set(LINUX_VOLUME_CATCHER dummy_volume_catcher.cpp) + else() + message( "Building with linux volume catcher" ) + set(LINUX_VOLUME_CATCHER linux_volume_catcher.cpp) + endif() + +endif() + set(MEDIA_PLUGIN_BASE_INCLUDE_DIRS ${LIBS_OPEN_DIR}/media_plugins/base/ diff --git a/indra/cmake/UI.cmake b/indra/cmake/UI.cmake index f1a8b68900..de567bdba0 100644 --- a/indra/cmake/UI.cmake +++ b/indra/cmake/UI.cmake @@ -1,27 +1,34 @@ # -*- cmake -*- include(Prebuilt) include(FreeType) +include(GLIB) if (USESYSTEMLIBS) include(FindPkgConfig) + if( NOT GTK_VERSION ) + set( GTK_VERSION 2.0 ) + endif() if (LINUX) set(PKGCONFIG_PACKAGES atk cairo - gdk-2.0 + gdk-${GTK_VERSION} gdk-pixbuf-2.0 glib-2.0 gmodule-2.0 - gtk+-2.0 + gtk+-${GTK_VERSION} gthread-2.0 libpng pango pangoft2 - pangox - pangoxft - sdl + sdl2 ) + if( GTK_VERSION LESS "3.0" ) + LIST( APPEND PKGCONFIG_PACKAGES pangoxft ) + else() + add_definitions( -DGTK_DISABLE_DEPRECATED) + endif() endif (LINUX) foreach(pkg ${PKGCONFIG_PACKAGES}) @@ -31,29 +38,16 @@ if (USESYSTEMLIBS) list(APPEND UI_LIBRARIES ${${pkg}_LIBRARIES}) add_definitions(${${pkg}_CFLAGS_OTHERS}) endforeach(pkg) + list(APPEND UI_LIBRARIES X11) else (USESYSTEMLIBS) if (LINUX) - use_prebuilt_binary(gtk-atk-pango-glib) + use_prebuilt_binary(fltk) endif (LINUX) if (LINUX) set(UI_LIB_NAMES - freetype - atk-1.0 - gdk-x11-2.0 - gdk_pixbuf-2.0 - glib-2.0 - gmodule-2.0 - gobject-2.0 - gthread-2.0 - gtk-x11-2.0 - pango-1.0 - pangoft2-1.0 - pangox-1.0 - #pangoxft-1.0 - gio-2.0 - pangocairo-1.0 - ffi + libfltk.a + libfreetype.a ) foreach(libname ${UI_LIB_NAMES}) @@ -68,6 +62,7 @@ else (USESYSTEMLIBS) endforeach(libname) set(UI_LIBRARIES ${UI_LIBRARIES} Xinerama) + include_directories ( ${GLIB_INCLUDE_DIRS} ) endif (LINUX) include_directories ( @@ -80,5 +75,5 @@ else (USESYSTEMLIBS) endif (USESYSTEMLIBS) if (LINUX) - add_definitions(-DLL_GTK=1 -DLL_X11=1) + add_definitions(-DLL_X11=1 -DLL_FLTK=1) endif (LINUX) diff --git a/indra/linux_crash_logger/llcrashloggerlinux.cpp b/indra/linux_crash_logger/llcrashloggerlinux.cpp index f6fd71e849..0395935d04 100644 --- a/indra/linux_crash_logger/llcrashloggerlinux.cpp +++ b/indra/linux_crash_logger/llcrashloggerlinux.cpp @@ -40,6 +40,7 @@ #if LL_GTK # include "gtk/gtk.h" +#error "Direct use of GTK is deprecated" #endif // LL_GTK #define MAX_LOADSTRING 100 diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt index bb003a77e3..53e4df3825 100644 --- a/indra/llwindow/CMakeLists.txt +++ b/indra/llwindow/CMakeLists.txt @@ -77,7 +77,8 @@ if (LINUX) ${LLXML_LIBRARIES} ${UI_LIBRARIES} # for GTK ${SDL_LIBRARY} - fontconfig # For FCInit and other FC* functions. + libfontconfig.a # For FCInit and other FC* functions. + libfreetype.a ) list(APPEND viewer_SOURCE_FILES diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index db39b08485..e0cd0bfb46 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -43,10 +43,15 @@ #if LL_GTK extern "C" { # include "gtk/gtk.h" +#error "Direct use of GTK is deprecated" } #include #endif // LL_GTK +#ifdef LL_GLIB +#include +#endif + extern "C" { # include "fontconfig/fontconfig.h" } @@ -186,6 +191,248 @@ Display* LLWindowSDL::get_SDL_Display(void) } #endif // LL_X11 +#if LL_X11 + +// Clipboard handing via native X11, base on the implementation in Cool VL by Henri Beauchamp + +namespace +{ + std::array gSupportedAtoms; + + Atom XA_CLIPBOARD; + Atom XA_TARGETS; + Atom PVT_PASTE_BUFFER; + long const MAX_PASTE_BUFFER_SIZE = 16383; + + void filterSelectionRequest( XEvent aEvent ) + { + auto *display = LLWindowSDL::getSDLDisplay(); + auto &request = aEvent.xselectionrequest; + + XSelectionEvent reply { SelectionNotify, aEvent.xany.serial, aEvent.xany.send_event, display, + request.requestor, request.selection, request.target, + request.property,request.time }; + + if (request.target == XA_TARGETS) + { + XChangeProperty(display, request.requestor, request.property, + XA_ATOM, 32, PropModeReplace, + (unsigned char *) &gSupportedAtoms.front(), gSupportedAtoms.size()); + } + else if (std::find(gSupportedAtoms.begin(), gSupportedAtoms.end(), request.target) != + gSupportedAtoms.end()) + { + std::string utf8; + if (request.selection == XA_PRIMARY) + utf8 = wstring_to_utf8str(gWindowImplementation->getPrimaryText()); + else + utf8 = wstring_to_utf8str(gWindowImplementation->getSecondaryText()); + + XChangeProperty(display, request.requestor, request.property, + request.target, 8, PropModeReplace, + (unsigned char *) utf8.c_str(), utf8.length()); + } + else if (request.selection == XA_CLIPBOARD) + { + // Did not have what they wanted, so no property set + reply.property = None; + } + else + return; + + XSendEvent(request.display, request.requestor, False, NoEventMask, (XEvent *) &reply); + XSync(display, False); + } + + void filterSelectionClearRequest( XEvent aEvent ) + { + auto &request = aEvent.xselectionrequest; + if (request.selection == XA_PRIMARY) + gWindowImplementation->clearPrimaryText(); + else if (request.selection == XA_CLIPBOARD) + gWindowImplementation->clearSecondaryText(); + } + + int x11_clipboard_filter(const SDL_Event *evt) + { + Display *display = LLWindowSDL::getSDLDisplay(); + if (!display) + return 1; + + if (evt->type != SDL_SYSWMEVENT) + return 1; + + auto xevent = evt->syswm.msg->event.xevent; + + if (xevent.type == SelectionRequest) + filterSelectionRequest( xevent ); + else if (xevent.type == SelectionClear) + filterSelectionClearRequest( xevent ); + return 1; + } + + bool grab_property(Display* display, Window window, Atom selection, Atom target) + { + if( !display ) + return false; + + maybe_lock_display(); + + XDeleteProperty(display, window, PVT_PASTE_BUFFER); + XFlush(display); + + XConvertSelection(display, selection, target, PVT_PASTE_BUFFER, window, CurrentTime); + + // Unlock the connection so that the SDL event loop may function + maybe_unlock_display(); + + const auto start{ SDL_GetTicks() }; + const auto end{ start + 1000 }; + + XEvent xevent {}; + bool response = false; + + do + { + SDL_Event event {}; + + // Wait for an event + SDL_WaitEvent(&event); + + // If the event is a window manager event + if (event.type == SDL_SYSWMEVENT) + { + xevent = event.syswm.msg->event.xevent; + + if (xevent.type == SelectionNotify && xevent.xselection.requestor == window) + response = true; + } + } while (!response && SDL_GetTicks() < end ); + + return response && xevent.xselection.property != None; + } +} + +void LLWindowSDL::initialiseX11Clipboard() +{ + if (!mSDL_Display) + return; + + SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); + SDL_SetEventFilter(x11_clipboard_filter); + + maybe_lock_display(); + + XA_CLIPBOARD = XInternAtom(mSDL_Display, "CLIPBOARD", False); + + gSupportedAtoms[0] = XA_STRING; + + gSupportedAtoms[1] = XInternAtom(mSDL_Display, "COMPOUND_TEXT", False); + gSupportedAtoms[2] = XInternAtom(mSDL_Display, "UTF8_STRING", False); + + // TARGETS atom + XA_TARGETS = XInternAtom(mSDL_Display, "TARGETS", False); + + // SL_PASTE_BUFFER atom + PVT_PASTE_BUFFER = XInternAtom(mSDL_Display, "FS_PASTE_BUFFER", False); + + maybe_unlock_display(); +} + +bool LLWindowSDL::getSelectionText( Atom aSelection, Atom aType, LLWString &text ) +{ + if( !mSDL_Display ) + return false; + + if( !grab_property(mSDL_Display, mSDL_XWindowID, aSelection,aType ) ) + return false; + + maybe_lock_display(); + + Atom type; + int format{}; + unsigned long len{},remaining {}; + unsigned char* data = nullptr; + int res = XGetWindowProperty(mSDL_Display, mSDL_XWindowID, + PVT_PASTE_BUFFER, 0, MAX_PASTE_BUFFER_SIZE, False, + AnyPropertyType, &type, &format, &len, + &remaining, &data); + if (data && len) + { + text = LLWString( + utf8str_to_wstring(reinterpret_cast< char const *>( data ) ) + ); + XFree(data); + } + + maybe_unlock_display(); + return res == Success; +} + +bool LLWindowSDL::getSelectionText(Atom selection, LLWString& text) +{ + if (!mSDL_Display) + return false; + + maybe_lock_display(); + + Window owner = XGetSelectionOwner(mSDL_Display, selection); + if (owner == None) + { + if (selection == XA_PRIMARY) + { + owner = DefaultRootWindow(mSDL_Display); + selection = XA_CUT_BUFFER0; + } + else + { + maybe_unlock_display(); + return false; + } + } + + maybe_unlock_display(); + + for( Atom atom : gSupportedAtoms ) + { + if(getSelectionText(selection, atom, text ) ) + return true; + } + + return false; +} + +bool LLWindowSDL::setSelectionText(Atom selection, const LLWString& text) +{ + maybe_lock_display(); + + if (selection == XA_PRIMARY) + { + std::string utf8 = wstring_to_utf8str(text); + XStoreBytes(mSDL_Display, utf8.c_str(), utf8.length() + 1); + mPrimaryClipboard = text; + } + else + mSecondaryClipboard = text; + + XSetSelectionOwner(mSDL_Display, selection, mSDL_XWindowID, CurrentTime); + + auto owner = XGetSelectionOwner(mSDL_Display, selection); + + maybe_unlock_display(); + + return owner == mSDL_XWindowID; +} + +Display* LLWindowSDL::getSDLDisplay() +{ + if (gWindowImplementation) + return gWindowImplementation->mSDL_Display; + return nullptr; +} + +#endif + LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks, const std::string& title, S32 x, S32 y, S32 width, @@ -253,6 +500,7 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks, #if LL_X11 mFlashing = FALSE; + initialiseX11Clipboard(); #endif // LL_X11 mKeyScanCode = 0; @@ -1356,33 +1604,34 @@ BOOL LLWindowSDL::copyTextToPrimary(const LLWString &text) #else BOOL LLWindowSDL::isClipboardTextAvailable() -{ - return FALSE; // unsupported +{ + return mSDL_Display && XGetSelectionOwner(mSDL_Display, XA_CLIPBOARD) != None; } BOOL LLWindowSDL::pasteTextFromClipboard(LLWString &dst) { - return FALSE; // unsupported + return getSelectionText(XA_CLIPBOARD, dst); } BOOL LLWindowSDL::copyTextToClipboard(const LLWString &s) { - return FALSE; // unsupported + return setSelectionText(XA_CLIPBOARD, s); } BOOL LLWindowSDL::isPrimaryTextAvailable() { - return FALSE; // unsupported + LLWString text; + return getSelectionText(XA_PRIMARY, text) && !text.empty(); } BOOL LLWindowSDL::pasteTextFromPrimary(LLWString &dst) { - return FALSE; // unsupported + return getSelectionText(XA_PRIMARY, dst); } BOOL LLWindowSDL::copyTextToPrimary(const LLWString &s) { - return FALSE; // unsupported + return setSelectionText(XA_PRIMARY, s); } #endif // LL_GTK @@ -1747,7 +1996,18 @@ void LLWindowSDL::processMiscNativeEvents() setlocale(LC_ALL, saved_locale.c_str() ); } #endif // LL_GTK - +#if LL_GLIB + // Pump until we've nothing left to do or passed 1/15th of a + // second pumping for this frame. + static LLTimer pump_timer; + pump_timer.reset(); + pump_timer.setTimerExpirySec(1.0f / 15.0f); + do + { + g_main_context_iteration(g_main_context_default(), FALSE); + } while( g_main_context_pending(g_main_context_default()) && !pump_timer.hasExpired()); +#endif + // hack - doesn't belong here - but this is just for debugging if (getenv("LL_DEBUG_BLOAT")) { @@ -2398,39 +2658,6 @@ static void color_changed_callback(GtkWidget *widget, gtk_color_selection_get_current_color(colorsel, colorp); } - -/* - Make the raw keyboard data available - used to poke through to LLQtWebKit so - that Qt/Webkit has access to the virtual keycodes etc. that it needs -*/ -LLSD LLWindowSDL::getNativeKeyData() -{ - LLSD result = LLSD::emptyMap(); - - U32 modifiers = 0; // pretend-native modifiers... oh what a tangled web we weave! - - // we go through so many levels of device abstraction that I can't really guess - // what a plugin under GDK under Qt under SL under SDL under X11 considers - // a 'native' modifier mask. this has been sort of reverse-engineered... they *appear* - // to match GDK consts, but that may be co-incidence. - modifiers |= (mKeyModifiers & KMOD_LSHIFT) ? 0x0001 : 0; - modifiers |= (mKeyModifiers & KMOD_RSHIFT) ? 0x0001 : 0;// munge these into the same shift - modifiers |= (mKeyModifiers & KMOD_CAPS) ? 0x0002 : 0; - modifiers |= (mKeyModifiers & KMOD_LCTRL) ? 0x0004 : 0; - modifiers |= (mKeyModifiers & KMOD_RCTRL) ? 0x0004 : 0;// munge these into the same ctrl - modifiers |= (mKeyModifiers & KMOD_LALT) ? 0x0008 : 0;// untested - modifiers |= (mKeyModifiers & KMOD_RALT) ? 0x0008 : 0;// untested - // *todo: test ALTs - I don't have a case for testing these. Do you? - // *todo: NUM? - I don't care enough right now (and it's not a GDK modifier). - - result["scan_code"] = (S32)mKeyScanCode; - result["virtual_key"] = (S32)mKeyVirtualKey; - result["modifiers"] = (S32)modifiers; - result[ "sdl_sym" ] = (S32)mSDLSym; // Store the SDL Keysym too. - return result; -} - - BOOL LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b) { BOOL rtn = FALSE; @@ -2515,6 +2742,37 @@ BOOL LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b) } #endif // LL_GTK +/* + Make the raw keyboard data available - used to poke through to LLQtWebKit so + that Qt/Webkit has access to the virtual keycodes etc. that it needs +*/ +LLSD LLWindowSDL::getNativeKeyData() +{ + LLSD result = LLSD::emptyMap(); + + U32 modifiers = 0; // pretend-native modifiers... oh what a tangled web we weave! + + // we go through so many levels of device abstraction that I can't really guess + // what a plugin under GDK under Qt under SL under SDL under X11 considers + // a 'native' modifier mask. this has been sort of reverse-engineered... they *appear* + // to match GDK consts, but that may be co-incidence. + modifiers |= (mKeyModifiers & KMOD_LSHIFT) ? 0x0001 : 0; + modifiers |= (mKeyModifiers & KMOD_RSHIFT) ? 0x0001 : 0;// munge these into the same shift + modifiers |= (mKeyModifiers & KMOD_CAPS) ? 0x0002 : 0; + modifiers |= (mKeyModifiers & KMOD_LCTRL) ? 0x0004 : 0; + modifiers |= (mKeyModifiers & KMOD_RCTRL) ? 0x0004 : 0;// munge these into the same ctrl + modifiers |= (mKeyModifiers & KMOD_LALT) ? 0x0008 : 0;// untested + modifiers |= (mKeyModifiers & KMOD_RALT) ? 0x0008 : 0;// untested + // *todo: test ALTs - I don't have a case for testing these. Do you? + // *todo: NUM? - I don't care enough right now (and it's not a GDK modifier). + + result["scan_code"] = (S32)mKeyScanCode; + result["virtual_key"] = (S32)mKeyVirtualKey; + result["modifiers"] = (S32)modifiers; + result[ "sdl_sym" ] = (S32)mSDLSym; // Store the SDL Keysym too. + return result; +} + #if LL_LINUX // extracted from spawnWebBrowser for clarity and to eliminate // compiler confusion regarding close(int fd) vs. LLWindow::close() diff --git a/indra/llwindow/llwindowsdl.h b/indra/llwindow/llwindowsdl.h index de0ee173ec..a0ca9839a5 100644 --- a/indra/llwindow/llwindowsdl.h +++ b/indra/llwindow/llwindowsdl.h @@ -220,6 +220,24 @@ private: U32 mSDLSym; // Store the SDL Keysym too. BOOL mUseLegacyCursors; // Legacy cursor setting from main program + +public: +#if LL_X11 + static Display* getSDLDisplay(); + LLWString const& getPrimaryText() const { return mPrimaryClipboard; } + LLWString const& getSecondaryText() const { return mSecondaryClipboard; } + void clearPrimaryText() { mPrimaryClipboard.clear(); } + void clearSecondaryText() { mSecondaryClipboard.clear(); } +private: + void initialiseX11Clipboard(); + + bool getSelectionText(Atom selection, LLWString& text); + bool getSelectionText( Atom selection, Atom type, LLWString &text ); + + bool setSelectionText(Atom selection, const LLWString& text); +#endif + LLWString mPrimaryClipboard; + LLWString mSecondaryClipboard; }; diff --git a/indra/media_plugins/base/CMakeLists.txt b/indra/media_plugins/base/CMakeLists.txt index 7f2b82ffdd..197c41bc20 100644 --- a/indra/media_plugins/base/CMakeLists.txt +++ b/indra/media_plugins/base/CMakeLists.txt @@ -49,4 +49,3 @@ set(media_plugin_base_HEADER_FILES add_library(media_plugin_base ${media_plugin_base_SOURCE_FILES} ) - diff --git a/indra/media_plugins/cef/CMakeLists.txt b/indra/media_plugins/cef/CMakeLists.txt index a846c04626..3f85cfc6a4 100644 --- a/indra/media_plugins/cef/CMakeLists.txt +++ b/indra/media_plugins/cef/CMakeLists.txt @@ -58,7 +58,8 @@ set (media_plugin_cef_LINK_LIBRARIES if (LINUX) # message(FATAL_ERROR "CEF plugin has been enabled for a Linux compile.\n" # " Please create a volume_catcher implementation for this platform.") - list(APPEND media_plugin_cef_SOURCE_FILES dummy_volume_catcher.cpp) + + list(APPEND media_plugin_cef_SOURCE_FILES ${LINUX_VOLUME_CATCHER}) set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--build-id -Wl,-rpath,'$ORIGIN:$ORIGIN/../../lib'") elseif (DARWIN) list(APPEND media_plugin_cef_SOURCE_FILES mac_volume_catcher_null.cpp) diff --git a/indra/media_plugins/cef/linux_volume_catcher.cpp b/indra/media_plugins/cef/linux_volume_catcher.cpp index 91be3a89e9..fdea6fb15f 100755 --- a/indra/media_plugins/cef/linux_volume_catcher.cpp +++ b/indra/media_plugins/cef/linux_volume_catcher.cpp @@ -53,6 +53,7 @@ extern "C" { #include "apr_dso.h" } + //////////////////////////////////////////////////// #define DEBUGMSG(...) do {} while(0) @@ -81,7 +82,7 @@ bool grab_pa_syms(std::string pulse_dso_name) apr_status_t rv; apr_dso_handle_t *sSymPADSOHandle = NULL; -#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##PASYM, sSymPADSOHandle, #PASYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #PASYM); if (REQUIRED) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #PASYM, (void*)ll##PASYM);}while(0) +#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##PASYM, sSymPADSOHandle, #PASYM); if (rv != APR_SUCCESS) { if (REQUIRED) sym_error = true;} } while(0); //attempt to load the shared library apr_pool_create(&sSymPADSOMemoryPool, NULL); @@ -216,17 +217,16 @@ void VolumeCatcherImpl::init() mGotSyms = loadsyms("libpulse-mainloop-glib.so.0"); if (!mGotSyms) return; - // better make double-sure glib itself is initialized properly. - if (!g_thread_supported ()) g_thread_init (NULL); - g_type_init(); - mMainloop = llpa_glib_mainloop_new(g_main_context_default()); + if (mMainloop) { pa_mainloop_api *api = llpa_glib_mainloop_get_api(mMainloop); + if (api) { pa_proplist *proplist = llpa_proplist_new(); + if (proplist) { llpa_proplist_sets(proplist, PA_PROP_APPLICATION_ICON_NAME, "multimedia-player"); @@ -236,6 +236,7 @@ void VolumeCatcherImpl::init() // plain old pa_context_new() is broken! mPAContext = llpa_context_new_with_proplist(api, NULL, proplist); + llpa_proplist_free(proplist); } } @@ -350,6 +351,51 @@ void VolumeCatcherImpl::update_index_volume(U32 index, F32 volume) } } +pid_t getParentPid( pid_t aPid ) +{ + std::stringstream strm; + strm << "/proc/" << aPid << "/status"; + std::ifstream in{ strm.str() }; + + if( !in.is_open() ) + return 0; + + pid_t res {0}; + while( !in.eof() && res == 0 ) + { + std::string line; + line.resize( 1024, 0 ); + in.getline( &line[0], line.length() ); + + auto i = line.find( "PPid:" ); + + if( i == std::string::npos ) + continue; + + char const *pIn = line.c_str() + 5; // Skip over pid; + while( *pIn != 0 && isspace( *pIn ) ) + ++pIn; + + if( *pIn ) + res = atoll( pIn ); + } + return res; +} + + +bool isPluginPid( pid_t aPid ) +{ + auto myPid = getpid(); + + do + { + if( aPid == myPid ) + return true; + aPid = getParentPid( aPid ); + } while( aPid > 1 ); + + return false; +} void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info *sii, int eol, void *userdata) { @@ -360,11 +406,10 @@ void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info { pa_proplist *proplist = sii->proplist; pid_t sinkpid = atoll(llpa_proplist_gets(proplist, PA_PROP_APPLICATION_PROCESS_ID)); - - if (sinkpid == getpid()) // does the discovered sinkinput belong to this process? + + if (isPluginPid( sinkpid )) // does the discovered sinkinput belong to this process? { - bool is_new = (impl->mSinkInputIndices.find(sii->index) == - impl->mSinkInputIndices.end()); + bool is_new = (impl->mSinkInputIndices.find(sii->index) == impl->mSinkInputIndices.end()); impl->mSinkInputIndices.insert(sii->index); impl->mSinkInputNumChannels[sii->index] = sii->channel_map.channels; @@ -387,32 +432,31 @@ void callback_subscription_alert(pa_context *context, pa_subscription_event_type VolumeCatcherImpl *impl = dynamic_cast((VolumeCatcherImpl*)userdata); llassert(impl); - switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { + switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) + { case PA_SUBSCRIPTION_EVENT_SINK_INPUT: - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == - PA_SUBSCRIPTION_EVENT_REMOVE) - { - // forget this sinkinput, if we were caring about it - impl->mSinkInputIndices.erase(index); - impl->mSinkInputNumChannels.erase(index); - } - else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == - PA_SUBSCRIPTION_EVENT_NEW) - { - // ask for more info about this new sinkinput - pa_operation *op; - if ((op = llpa_context_get_sink_input_info(impl->mPAContext, index, callback_discovered_sinkinput, impl))) + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - llpa_operation_unref(op); + // forget this sinkinput, if we were caring about it + impl->mSinkInputIndices.erase(index); + impl->mSinkInputNumChannels.erase(index); } - } - else - { - // property change on this sinkinput - we don't care. - } - break; + else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) + { + // ask for more info about this new sinkinput + pa_operation *op; + if ((op = llpa_context_get_sink_input_info(impl->mPAContext, index, callback_discovered_sinkinput, impl))) + { + llpa_operation_unref(op); + } + } + else + { + // property change on this sinkinput - we don't care. + } + break; - default:; + default:; } } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 2151ece287..762a5fa55f 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -13,7 +13,7 @@ include(BuildPackagesInfo) include(BuildVersion) include(CMakeCopyIfDifferent) include(CubemapToEquirectangularJS) -include(DBusGlib) +include(GLIB) include(DragDrop) include(EXPAT) include(FMODSTUDIO) @@ -1797,7 +1797,6 @@ if (LINUX) # fsversionstrings.h with the right numbers in it. # COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" ) - LIST(APPEND viewer_SOURCE_FILES llappviewerlinux_api_dbus.cpp) # [FS] Growl support LIST(APPEND viewer_HEADER_FILES desktopnotifierlinux.h growlmanager.h) LIST(APPEND viewer_SOURCE_FILES desktopnotifierlinux.cpp growlmanager.cpp) @@ -2518,7 +2517,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${BOOST_WAVE_LIBRARY} #FS specific ${BOOST_THREAD_LIBRARY} #FS specific ${BOOST_CONTEXT_LIBRARY} - ${DBUSGLIB_LIBRARIES} + ${GLIB_LIBRARIES} ${OPENGL_LIBRARIES} ${FMODWRAPPER_LIBRARY} # must come after LLAudio ${OPENAL_LIBRARIES} @@ -2538,6 +2537,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLPHYSICSEXTENSIONS_LIBRARIES} ${LLAPPEARANCE_LIBRARIES} ${GROWL_LIBRARY} + ${GIO_LIBRARIES} ) target_link_libraries(${VIEWER_BINARY_NAME} ${DISCORD_LIBRARY} ) diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 5e3ec53ea6..54358db763 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -6.5.2 +6.5.4 diff --git a/indra/newview/fsfloaterperformance.cpp b/indra/newview/fsfloaterperformance.cpp index c8f5d64d76..43401fe0b4 100644 --- a/indra/newview/fsfloaterperformance.cpp +++ b/indra/newview/fsfloaterperformance.cpp @@ -139,7 +139,7 @@ BOOL FSFloaterPerformance::postBuild() mObjectList->setHoverIconName("StopReload_Off"); mObjectList->setIconClickedCallback(boost::bind(&FSFloaterPerformance::detachItem, this, _1)); - mSettingsPanel->getChild("graphics_quality")->setCommitCallback(boost::bind(&FSFloaterPerformance::onChangeQuality, this, _2)); + mSettingsPanel->getChild("quality_vs_perf_selection")->setCommitCallback(boost::bind(&FSFloaterPerformance::onChangeQuality, this, _2)); mNearbyPanel->getChild("exceptions_btn")->setCommitCallback(boost::bind(&FSFloaterPerformance::onClickExceptions, this)); mNearbyPanel->getChild("hide_avatars")->setCommitCallback(boost::bind(&FSFloaterPerformance::onClickHideAvatars, this)); @@ -240,104 +240,106 @@ void FSFloaterPerformance::draw() // tot_frame_time_ns -= tot_limit_time_ns; // tot_frame_time_ns -= tot_sleep_time_ns; - if(tot_frame_time_ns == 0) + if(tot_frame_time_ns != 0) { - LL_WARNS("performance") << "things went wrong, quit while we can." << LL_ENDL; - return; - } - auto pct_avatar_time = (tot_avatar_time_ns * 100)/tot_frame_time_ns; - auto pct_huds_time = (tot_huds_time_ns * 100)/tot_frame_time_ns; - auto pct_ui_time = (tot_ui_time_ns * 100)/tot_frame_time_ns; - auto pct_idle_time = (tot_idle_time_ns * 100)/tot_frame_time_ns; - auto pct_swap_time = (tot_swap_time_ns * 100)/tot_frame_time_ns; - auto pct_scene_render_time = (tot_scene_time_ns * 100)/tot_frame_time_ns; - pct_avatar_time = llclamp(pct_avatar_time,0.,100.); - pct_huds_time = llclamp(pct_huds_time,0.,100.); - pct_ui_time = llclamp(pct_ui_time,0.,100.); - pct_idle_time = llclamp(pct_idle_time,0.,100.); - pct_swap_time = llclamp(pct_swap_time,0.,100.); - pct_scene_render_time = llclamp(pct_scene_render_time,0.,100.); + auto pct_avatar_time = (tot_avatar_time_ns * 100)/tot_frame_time_ns; + auto pct_huds_time = (tot_huds_time_ns * 100)/tot_frame_time_ns; + auto pct_ui_time = (tot_ui_time_ns * 100)/tot_frame_time_ns; + auto pct_idle_time = (tot_idle_time_ns * 100)/tot_frame_time_ns; + auto pct_swap_time = (tot_swap_time_ns * 100)/tot_frame_time_ns; + auto pct_scene_render_time = (tot_scene_time_ns * 100)/tot_frame_time_ns; + pct_avatar_time = llclamp(pct_avatar_time,0.,100.); + pct_huds_time = llclamp(pct_huds_time,0.,100.); + pct_ui_time = llclamp(pct_ui_time,0.,100.); + pct_idle_time = llclamp(pct_idle_time,0.,100.); + pct_swap_time = llclamp(pct_swap_time,0.,100.); + pct_scene_render_time = llclamp(pct_scene_render_time,0.,100.); - args["AV_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_avatar_time)); - args["HUDS_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_huds_time)); - args["UI_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_ui_time)); - args["IDLE_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_idle_time)); - args["SWAP_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_swap_time)); - args["SCENERY_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_scene_render_time)); - args["TOT_FRAME_TIME"] = llformat("%02u", (U32)llround(tot_frame_time_ns/1000000)); - args["FPSCAP"] = llformat("%02u", (U32)fpsCap); - args["FPSTARGET"] = llformat("%02u", (U32)targetFPS); + args["AV_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_avatar_time)); + args["HUDS_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_huds_time)); + args["UI_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_ui_time)); + args["IDLE_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_idle_time)); + args["SWAP_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_swap_time)); + args["SCENERY_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_scene_render_time)); + args["TOT_FRAME_TIME"] = llformat("%02u", (U32)llround(tot_frame_time_ns/1000000)); + args["FPSCAP"] = llformat("%02u", (U32)fpsCap); + args["FPSTARGET"] = llformat("%02u", (U32)targetFPS); - getChild("av_frame_stats")->setText(getString("av_frame_pct", args)); - getChild("huds_frame_stats")->setText(getString("huds_frame_pct", args)); - getChild("frame_breakdown")->setText(getString("frame_stats", args)); - - auto textbox = getChild("fps_warning"); - if (tot_sleep_time_raw > 0) // We are sleeping because view is not focussed - { - textbox->setVisible(true); - textbox->setText(getString("focus_fps")); - textbox->setColor(LLUIColorTable::instance().getColor("DrYellow")); - unreliable = true; - } - else if (tot_limit_time_raw > 0) - { - textbox->setVisible(true); - textbox->setText(getString("limit_fps", args)); - textbox->setColor(LLUIColorTable::instance().getColor("DrYellow")); - unreliable = true; - } - else if (FSPerfStats::autoTune) - { - textbox->setVisible(true); - textbox->setText(getString("tuning_fps", args)); - textbox->setColor(LLUIColorTable::instance().getColor("green")); + getChild("av_frame_stats")->setText(getString("av_frame_pct", args)); + getChild("huds_frame_stats")->setText(getString("huds_frame_pct", args)); + getChild("frame_breakdown")->setText(getString("frame_stats", args)); + + auto textbox = getChild("fps_warning"); + if (tot_sleep_time_raw > 0) // We are sleeping because view is not focussed + { + textbox->setVisible(true); + textbox->setText(getString("focus_fps")); + textbox->setColor(LLUIColorTable::instance().getColor("DrYellow")); + unreliable = true; + } + else if (tot_limit_time_raw > 0) + { + textbox->setVisible(true); + textbox->setText(getString("limit_fps", args)); + textbox->setColor(LLUIColorTable::instance().getColor("DrYellow")); + unreliable = true; + } + else if (FSPerfStats::autoTune) + { + textbox->setVisible(true); + textbox->setText(getString("tuning_fps", args)); + textbox->setColor(LLUIColorTable::instance().getColor("green")); + } + else + { + textbox->setVisible(false); + } + + if (FSPerfStats::autoTune && !unreliable ) + { + // the tuning itself is managed from another thread but we can report progress here + + // Is our target frame time lower than current? If so we need to take action to reduce draw overheads. + if (target_frame_time_ns <= tot_frame_time_ns) + { + U32 non_avatar_time_ns = tot_frame_time_ns - tot_avatar_time_ns; + // If the target frame time < non avatar frame time then we can pototentially reach it. + if (non_avatar_time_ns < target_frame_time_ns) + { + textbox->setColor(LLUIColorTable::instance().getColor("orange")); + } + else + { + // TODO(Beq): Set advisory text for further actions + textbox->setColor(LLUIColorTable::instance().getColor("red")); + } + } + else if (target_frame_time_ns > (tot_frame_time_ns + FSPerfStats::renderAvatarMaxART_ns)) + { + // if we have more time to spare. Display this (the service will update things) + textbox->setColor(LLUIColorTable::instance().getColor("green")); + } + } + + if (mHUDsPanel->getVisible()) + { + populateHUDList(); + } + else if (mNearbyPanel->getVisible()) + { + populateNearbyList(); + mNearbyPanel->getChild("hide_avatars")->set(!LLPipeline::hasRenderTypeControl(LLPipeline::RENDER_TYPE_AVATAR)); + } + else if (mComplexityPanel->getVisible()) + { + populateObjectList(); + } } else { - textbox->setVisible(false); + LL_WARNS("performance") << "Scene time 0. Skipping til we have data." << LL_ENDL; } - - if (FSPerfStats::autoTune && !unreliable ) - { - // the tuning itself is managed from another thread but we can report progress here - - // Is our target frame time lower than current? If so we need to take action to reduce draw overheads. - if (target_frame_time_ns <= tot_frame_time_ns) - { - U32 non_avatar_time_ns = tot_frame_time_ns - tot_avatar_time_ns; - // If the target frame time < non avatar frame time then we can pototentially reach it. - if (non_avatar_time_ns < target_frame_time_ns) - { - textbox->setColor(LLUIColorTable::instance().getColor("orange")); - } - else - { - // TODO(Beq): Set advisory text for further actions - textbox->setColor(LLUIColorTable::instance().getColor("red")); - } - } - else if (target_frame_time_ns > (tot_frame_time_ns + FSPerfStats::renderAvatarMaxART_ns)) - { - // if we have more time to spare. Display this (the service will update things) - textbox->setColor(LLUIColorTable::instance().getColor("green")); - } - } - - if (mHUDsPanel->getVisible()) - { - populateHUDList(); - } - else if (mNearbyPanel->getVisible()) - { - populateNearbyList(); - mNearbyPanel->getChild("hide_avatars")->set(!LLPipeline::hasRenderTypeControl(LLPipeline::RENDER_TYPE_AVATAR)); - } - else if (mComplexityPanel->getVisible()) - { - populateObjectList(); - } - + mUpdateTimer->setTimerExpirySec(REFRESH_INTERVAL); } LLFloater::draw(); @@ -732,11 +734,9 @@ void FSFloaterPerformance::detachItem(const LLUUID& item_id) void FSFloaterPerformance::onChangeQuality(const LLSD& data) { - LLFloaterPreference* instance = LLFloaterReg::getTypedInstance("preferences"); - if (instance) - { - instance->onChangeQuality(data); - } + U32 level = (U32)(data.asReal()); + LLFeatureManager::getInstance()->setGraphicsLevel(level, true); + refresh(); } void FSFloaterPerformance::onClickHideAvatars() diff --git a/indra/newview/fsperfstats.cpp b/indra/newview/fsperfstats.cpp index 1febba5f35..aeb8880927 100644 --- a/indra/newview/fsperfstats.cpp +++ b/indra/newview/fsperfstats.cpp @@ -49,11 +49,12 @@ namespace FSPerfStats std::atomic tunedAvatars{0}; U32 targetFPS; // desired FPS U64 renderAvatarMaxART_ns{(U64)(ART_UNLIMITED_NANOS)}; // highest render time we'll allow without culling features - U32 fpsTuningStrategy{0}; // linked to FSTuningFPSStrategy U32 lastGlobalPrefChange{0}; std::mutex bufferToggleLock{}; bool autoTune{false}; + Tunables tunables; + std::atomic StatsRecorder::writeBuffer{0}; bool StatsRecorder::collectionEnabled{true}; LLUUID StatsRecorder::focusAv{LLUUID::null}; @@ -61,6 +62,14 @@ namespace FSPerfStats std::array StatsRecorder::max{ {} }; std::array StatsRecorder::sum{ {} }; + void Tunables::applyUpdates() + { + assert_main_thread(); + if( tuningFlag & NonImposters ){ gSavedSettings.setU32("IndirectMaxNonImpostors", nonImposters); }; + if( tuningFlag & ReflectionDetail ){ gSavedSettings.setS32("RenderReflectionDetail", reflectionDetail); }; + if( tuningFlag & FarClip ){ gSavedSettings.setF32("RenderFarClip", farClip); }; + resetChanges(); + } StatsRecorder::StatsRecorder():q(1024*16),t(&StatsRecorder::run) { @@ -109,6 +118,7 @@ namespace FSPerfStats unreliable = true; lastStats[static_cast(StatType_t::RENDER_FPSLIMIT)] = sceneStats[static_cast(StatType_t::RENDER_FPSLIMIT)]; lastStats[static_cast(StatType_t::RENDER_SLEEP)] = sceneStats[static_cast(StatType_t::RENDER_SLEEP)]; + lastStats[static_cast(StatType_t::RENDER_FRAME)] = sceneStats[static_cast(StatType_t::RENDER_FRAME)]; // bring over the total frame render time to deal with region crossing overlap issues } if(!unreliable) @@ -174,7 +184,7 @@ namespace FSPerfStats sum[writeBuffer][i].fill(0); } - // and now adjust the visuals. + // and now adjust the proxy vars so that the main thread can adjust the visuals. if(autoTune) { updateAvatarParams(); @@ -279,6 +289,7 @@ namespace FSPerfStats static LLCachedControl impostorDistance(gSavedSettings, "FSAutoTuneImpostorFarAwayDistance"); static LLCachedControl impostorDistanceTuning(gSavedSettings, "FSAutoTuneImpostorByDistEnabled"); static LLCachedControl maxNonImpostors (gSavedSettings, "IndirectMaxNonImpostors"); + static LLCachedControl fpsTuningStrategy (gSavedSettings, "FSTuningFPSStrategy"); if(impostorDistanceTuning) { @@ -287,7 +298,7 @@ namespace FSPerfStats auto count = countNearbyAvatars(std::min(drawDistance, impostorDistance)); if( count != maxNonImpostors ) { - gSavedSettings.setU32("IndirectMaxNonImpostors", (count < LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER)?count : LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER); + tunables.updateNonImposters( (count < LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER)?count : LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER ); LL_DEBUGS("AutoTune") << "There are " << count << "avatars within " << std::min(drawDistance, impostorDistance) << "m of the camera" << LL_ENDL; } } @@ -338,13 +349,13 @@ namespace FSPerfStats // we cannnot do this by avatar adjustment alone. if((gFrameCount - FSPerfStats::lastGlobalPrefChange) > 10) // give changes a short time to take effect. { - if(FSPerfStats::fpsTuningStrategy == 1) + if(fpsTuningStrategy == 1) { // 1 - hack the water to opaque. all non opaque have a significant hit, this is a big boost for (arguably) a minor visual hit. // the other reflection options make comparatively little change and iof this overshoots we'll be stepping back up later if(LLPipeline::RenderReflectionDetail != -2) { - gSavedSettings.setS32("RenderReflectionDetail", -2); + FSPerfStats::tunables.updateReflectionDetail(-2); FSPerfStats::lastGlobalPrefChange = gFrameCount; return; } @@ -354,7 +365,7 @@ namespace FSPerfStats auto new_dd = (drawDistance-10>userMinDrawDistance)?(drawDistance - 10) : userMinDrawDistance; if(new_dd != drawDistance) { - gSavedSettings.setF32("RenderFarClip", new_dd); + FSPerfStats::tunables.updateFarClip( new_dd ); FSPerfStats::lastGlobalPrefChange = gFrameCount; return; } @@ -403,15 +414,14 @@ namespace FSPerfStats } if( drawDistance < userTargetDrawDistance ) { - gSavedSettings.setF32("RenderFarClip", drawDistance + 10.); + FSPerfStats::tunables.updateFarClip( drawDistance + 10. ); } if( (target_frame_time_raw * 1.5) > tot_frame_time_raw && FSPerfStats::tunedAvatars == 0 && drawDistance >= userTargetDrawDistance) { // if everything else is "max" and we have 50% headroom let's knock the water quality up a notch at a time. - auto water = gSavedSettings.getS32("RenderReflectionDetail"); - gSavedSettings.setS32("RenderReflectionDetail", water+1); + FSPerfStats::tunables.updateReflectionDetail( gSavedSettings.getS32("RenderReflectionDetail") + 1 ); } } updateSettingsFromRenderCostLimit(); diff --git a/indra/newview/fsperfstats.h b/indra/newview/fsperfstats.h index 49a7e8e6d1..7ada042a6a 100644 --- a/indra/newview/fsperfstats.h +++ b/indra/newview/fsperfstats.h @@ -74,7 +74,6 @@ namespace FSPerfStats extern std::atomic tunedAvatars; extern U32 targetFPS; // desired FPS extern U64 renderAvatarMaxART_ns; - extern U32 fpsTuningStrategy; extern U32 lastGlobalPrefChange; extern std::mutex bufferToggleLock; extern bool autoTune; @@ -116,6 +115,28 @@ namespace FSPerfStats bool isHUD; }; + struct Tunables + { + static constexpr U32 Nothing{0}; + static constexpr U32 NonImposters{1}; + static constexpr U32 ReflectionDetail{2}; + static constexpr U32 FarClip{4}; + + U32 tuningFlag{0}; + U32 nonImposters; + S32 reflectionDetail; + F32 farClip; + + void updateFarClip(F32 nv){farClip=nv; tuningFlag |= FarClip;}; + void updateNonImposters(U32 nv){nonImposters=nv; tuningFlag |= NonImposters;}; + void updateReflectionDetail(S32 nv){reflectionDetail=nv; tuningFlag |= ReflectionDetail;}; + + void applyUpdates(); + void resetChanges(){tuningFlag=Nothing;}; + }; + + extern Tunables tunables; + class StatsRecorder{ using Queue = moodycamel::BlockingConcurrentQueue; public: diff --git a/indra/newview/installers/darwin/apple-notarize.sh b/indra/newview/installers/darwin/apple-notarize.sh index 466898ecda..e019437924 100755 --- a/indra/newview/installers/darwin/apple-notarize.sh +++ b/indra/newview/installers/darwin/apple-notarize.sh @@ -16,8 +16,9 @@ if [ -f "$CONFIG_FILE" ]; then --password $PASSWORD \ --asc-provider $ASC_PROVIDER \ --file "$zip_file" 2>&1) + echo $res + requestUUID=$(echo $res | awk '/RequestUUID/ { print $NF; }') - echo "Apple Notarization RequestUUID: $requestUUID" if [[ -n $requestUUID ]]; then diff --git a/indra/newview/installers/linux/appimage.sh b/indra/newview/installers/linux/appimage.sh new file mode 100755 index 0000000000..85dfda6284 --- /dev/null +++ b/indra/newview/installers/linux/appimage.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +SCRIPT_PATH=`readlink -f $0` +SCRIPT_PATH=`dirname $SCRIPT_PATH` + +# All hope is lost if there is no lsb_release command +command -v lsb_release >/dev/null 2>/dev/null || exit 0 + +if [ `lsb_release -is` != "Ubuntu" ] +then + echo "Distribution is not Ubuntu, skipping AppImage creation" + exit 0 +fi + +set -e + +cd $1 +pushd packaged + +wget -q https://github.com/AppImage/AppImages/raw/master/functions.sh -O ./functions.sh +. ./functions.sh +rm functions.sh + +cp firestorm AppRun +cp ${SCRIPT_PATH}/firestorm.desktop firestorm.desktop + +copy_deps +copy_deps +copy_deps +delete_blacklisted + +# Now copy everything to ./lib. The viewer binaries got build with a rpath pointing to ./lib so all so will be magically found there. +#find ./usr/lib/ -type f -print0 | xargs -0 -Ifile cp file ./lib/ +#find ./lib/x86_64-linux-gnu/ -type f -print0 | xargs -0 -Ifile cp file ./lib/ + +#rm -rf ./usr/lib/ +#rm -rf ./lib/x86_64-linux-gnu/ + +find . -empty -type d -delete + +popd + +wget "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage" +chmod a+x appimagetool-x86_64.AppImage +./appimagetool-x86_64.AppImage --appimage-extract +rm appimagetool-x86_64.AppImage +ARCH=x86_64 squashfs-root/AppRun packaged diff --git a/indra/newview/installers/linux/firestorm.desktop b/indra/newview/installers/linux/firestorm.desktop new file mode 100644 index 0000000000..8604a208bc --- /dev/null +++ b/indra/newview/installers/linux/firestorm.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Type=Application +Name=Firestorm +Exec=firestorm +Comment=Client for virtual worlds +Icon=firestorm_icon +Categories=Development; +Terminal=true diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 3aede75ec4..ad3c72e89f 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1645,6 +1645,12 @@ bool LLAppViewer::doFrame() { // Perfstats collection Frame boundary { + // and now adjust the visuals from previous frame. + if(FSPerfStats::autoTune && FSPerfStats::tunables.tuningFlag != FSPerfStats::Tunables::Nothing) + { + FSPerfStats::tunables.applyUpdates(); + } + FSPerfStats::RecordSceneTime T (FSPerfStats::StatType_t::RENDER_FRAME); LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop")); @@ -1702,7 +1708,7 @@ bool LLAppViewer::doFrame() } // Check if we need to temporarily enable rendering. //F32 periodic_rendering = gSavedSettings.getF32("ForcePeriodicRenderingTime"); - static LLCachedControl periodic_rendering(gSavedSettings, "ForcePeriodicRenderingTime"); + static LLCachedControl periodic_rendering(gSavedSettings, "ForcePeriodicRenderingTime", -1.f); if (periodic_rendering > F_APPROXIMATELY_ZERO && periodicRenderingTimer.getElapsedTimeF64() > periodic_rendering) { periodicRenderingTimer.reset(); diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index e961871908..af00bd64e7 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -42,16 +42,27 @@ #include "json/reader.h" // To parse manifest.json from pepperflash -#if LL_DBUS_ENABLED -# include "llappviewerlinux_api_dbus.h" -// regrettable hacks to give us better runtime compatibility with older systems inside llappviewerlinux_api.h: -#define llg_return_if_fail(COND) do{if (!(COND)) return;}while(0) -#undef g_return_if_fail -#define g_return_if_fail(COND) llg_return_if_fail(COND) -// The generated API -# include "llappviewerlinux_api.h" -#endif +#include + +#define VIEWERAPI_SERVICE "com.secondlife.ViewerAppAPIService" +#define VIEWERAPI_PATH "/com/secondlife/ViewerAppAPI" +#define VIEWERAPI_INTERFACE "com.secondlife.ViewerAppAPI" + +static const char * DBUS_SERVER = "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + ""; + +typedef struct +{ + GObject parent; +} ViewerAppAPI; namespace { @@ -127,10 +138,6 @@ bool LLAppViewerLinux::init() // libraries likes to use glib functions; in short, do this here // really early in app startup! -#if ( !defined(GLIB_MAJOR_VERSION) && !defined(GLIB_MINOR_VERSION) ) || ( GLIB_MAJOR_VERSION < 2 ) || ( GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 32 ) - if (!g_thread_supported ()) g_thread_init (NULL); -#endif - bool success = LLAppViewer::init(); #if LL_SEND_CRASH_REPORTS @@ -152,40 +159,17 @@ bool LLAppViewerLinux::restoreErrorTrap() } ///////////////////////////////////////// -#if LL_DBUS_ENABLED +#if LL_GLIB typedef struct { GObjectClass parent_class; } ViewerAppAPIClass; -static void viewerappapi_init(ViewerAppAPI *server); -static void viewerappapi_class_init(ViewerAppAPIClass *klass); - /// -// regrettable hacks to give us better runtime compatibility with older systems in general -static GType llg_type_register_static_simple_ONCE(GType parent_type, - const gchar *type_name, - guint class_size, - GClassInitFunc class_init, - guint instance_size, - GInstanceInitFunc instance_init, - GTypeFlags flags) -{ - static GTypeInfo type_info; - memset(&type_info, 0, sizeof(type_info)); - - type_info.class_size = class_size; - type_info.class_init = class_init; - type_info.instance_size = instance_size; - type_info.instance_init = instance_init; - - return g_type_register_static(parent_type, type_name, &type_info, flags); -} -#define llg_intern_static_string(S) (S) -#define g_intern_static_string(S) llg_intern_static_string(S) -#define g_type_register_static_simple(parent_type, type_name, class_size, class_init, instance_size, instance_init, flags) llg_type_register_static_simple_ONCE(parent_type, type_name, class_size, class_init, instance_size, instance_init, flags) +static void viewerappapi_init(ViewerAppAPI *server); +static void viewerappapi_class_init(ViewerAppAPIClass *klass); G_DEFINE_TYPE(ViewerAppAPI, viewerappapi, G_TYPE_OBJECT); @@ -193,79 +177,71 @@ void viewerappapi_class_init(ViewerAppAPIClass *klass) { } -static bool dbus_server_init = false; - -void viewerappapi_init(ViewerAppAPI *server) +static void dispatchSLURL(gchar const *slurl) { - // Connect to the default DBUS, register our service/API. + LL_INFOS() << "Was asked to go to slurl: " << slurl << LL_ENDL; - if (!dbus_server_init) - { - GError *error = NULL; - - server->connection = lldbus_g_bus_get(DBUS_BUS_SESSION, &error); - if (server->connection) - { - lldbus_g_object_type_install_info(viewerappapi_get_type(), &dbus_glib_viewerapp_object_info); - - lldbus_g_connection_register_g_object(server->connection, VIEWERAPI_PATH, G_OBJECT(server)); - - DBusGProxy *serverproxy = lldbus_g_proxy_new_for_name(server->connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); - - guint request_name_ret_unused; - // akin to org_freedesktop_DBus_request_name - if (lldbus_g_proxy_call(serverproxy, "RequestName", &error, G_TYPE_STRING, VIEWERAPI_SERVICE, G_TYPE_UINT, 0, G_TYPE_INVALID, G_TYPE_UINT, &request_name_ret_unused, G_TYPE_INVALID)) - { - // total success. - dbus_server_init = true; - } - else - { - LL_WARNS() << "Unable to register service name: " << error->message << LL_ENDL; - } - - g_object_unref(serverproxy); - } - else - { - g_warning("Unable to connect to dbus: %s", error->message); - } - - if (error) - g_error_free(error); - } + std::string url = slurl; + LLMediaCtrl* web = NULL; + const bool trusted_browser = false; + LLURLDispatcher::dispatch(url, "", web, trusted_browser); } -// FIRE-5417; The xml manifest for dbus claims success_rtn is a boolean, not a boolean array -//gboolean viewer_app_api_GoSLURL(ViewerAppAPI *obj, gchar *slurl, gboolean **success_rtn, GError **error) -gboolean viewer_app_api_GoSLURL(ViewerAppAPI *obj, gchar *slurl, gboolean *success_rtn, GError **error) -// +static void DoMethodeCall (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) { - bool success = false; + LL_INFOS() << "DBUS message " << method_name << " from: " << sender << " interface: " << interface_name << LL_ENDL; + const gchar *slurl; - LL_INFOS() << "Was asked to go to slurl: " << slurl << LL_ENDL; + g_variant_get (parameters, "(&s)", &slurl); + dispatchSLURL(slurl); +} - std::string url = slurl; - LLMediaCtrl* web = NULL; - const bool trusted_browser = false; - if (LLURLDispatcher::dispatch(url, "", web, trusted_browser)) - { - // bring window to foreground, as it has just been "launched" from a URL - // todo: hmm, how to get there from here? - //xxx->mWindow->bringToFront(); - success = true; - } +GDBusNodeInfo *gBusNodeInfo = nullptr; +static const GDBusInterfaceVTable interface_vtable = + { + DoMethodeCall + }; +static void busAcquired(GDBusConnection *connection, const gchar *name, gpointer user_data) +{ + auto id = g_dbus_connection_register_object(connection, + VIEWERAPI_PATH, + gBusNodeInfo->interfaces[0], + &interface_vtable, + NULL, /* user_data */ + NULL, /* user_data_free_func */ + NULL); /* GError** */ + g_assert (id > 0); +} - // FIRE-5417; The xml manifest for dbus claims success_rtn is a boolean, not a boolean array +static void nameAcquired(GDBusConnection *connection, const gchar *name, gpointer user_data) +{ +} - // *success_rtn = g_new (gboolean, 1); - // (*success_rtn)[0] = (gboolean)success; +static void nameLost(GDBusConnection *connection, const gchar *name, gpointer user_data) +{ - *success_rtn = (gboolean)success; +} +void viewerappapi_init(ViewerAppAPI *server) +{ + gBusNodeInfo = g_dbus_node_info_new_for_xml (DBUS_SERVER, NULL); + g_assert (gBusNodeInfo != NULL); - // + auto owner_id = g_bus_own_name(G_BUS_TYPE_SESSION, + VIEWERAPI_SERVICE, + G_BUS_NAME_OWNER_FLAGS_NONE, + busAcquired, + nameAcquired, + nameLost, + NULL, + NULL); - return TRUE; // the invokation succeeded, even if the actual dispatch didn't. } /// @@ -273,15 +249,6 @@ gboolean viewer_app_api_GoSLURL(ViewerAppAPI *obj, gchar *slurl, gboolean *succe //virtual bool LLAppViewerLinux::initSLURLHandler() { - if (!grab_dbus_syms(DBUSGLIB_DYLIB_DEFAULT_NAME)) - { - return false; // failed - } - -#if ( !defined(GLIB_MAJOR_VERSION) && !defined(GLIB_MINOR_VERSION) ) || ( GLIB_MAJOR_VERSION < 2 ) || ( GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 35 ) - g_type_init(); -#endif - //ViewerAppAPI *api_server = (ViewerAppAPI*) g_object_new(viewerappapi_get_type(), NULL); @@ -291,51 +258,51 @@ bool LLAppViewerLinux::initSLURLHandler() //virtual bool LLAppViewerLinux::sendURLToOtherInstance(const std::string& url) { - if (!grab_dbus_syms(DBUSGLIB_DYLIB_DEFAULT_NAME)) - { - return false; // failed - } + bool success = false; - bool success = false; - DBusGConnection *bus; - GError *error = NULL; + auto *pBus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, nullptr); -#if ( !defined(GLIB_MAJOR_VERSION) && !defined(GLIB_MINOR_VERSION) ) || ( GLIB_MAJOR_VERSION < 2 ) || ( GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 35 ) - g_type_init(); -#endif - - bus = lldbus_g_bus_get (DBUS_BUS_SESSION, &error); - if (bus) - { - gboolean rtn = FALSE; - DBusGProxy *remote_object = - lldbus_g_proxy_new_for_name(bus, VIEWERAPI_SERVICE, VIEWERAPI_PATH, VIEWERAPI_INTERFACE); + if( !pBus ) + { + LL_WARNS() << "Getting dbus failed." << LL_ENDL; + return false; + } - if (lldbus_g_proxy_call(remote_object, "GoSLURL", &error, - G_TYPE_STRING, url.c_str(), G_TYPE_INVALID, - G_TYPE_BOOLEAN, &rtn, G_TYPE_INVALID)) - { - success = rtn; - } - else - { - LL_INFOS() << "Call-out to other instance failed (perhaps not running): " << error->message << LL_ENDL; - } + auto pProxy = g_dbus_proxy_new_sync(pBus, G_DBUS_PROXY_FLAGS_NONE, nullptr, + VIEWERAPI_SERVICE, VIEWERAPI_PATH, + VIEWERAPI_INTERFACE, nullptr, nullptr); - g_object_unref(G_OBJECT(remote_object)); - } - else - { - LL_WARNS() << "Couldn't connect to session bus: " << error->message << LL_ENDL; - } + if( !pProxy ) + { + LL_WARNS() << "Cannot create new dbus proxy." << LL_ENDL; + g_object_unref( pBus ); + return false; + } - if (error) - g_error_free(error); - - return success; + auto *pArgs = g_variant_new( "(s)", url.c_str() ); + if( !pArgs ) + { + LL_WARNS() << "Cannot create new variant." << LL_ENDL; + g_object_unref( pBus ); + return false; + } + + auto pRes = g_dbus_proxy_call_sync(pProxy, + "GoSLURL", + pArgs, + G_DBUS_CALL_FLAGS_NONE, + -1, nullptr, nullptr); + + + + if( pRes ) + g_variant_unref( pRes ); + g_object_unref( pProxy ); + g_object_unref( pBus ); + return true; } -#else // LL_DBUS_ENABLED +#else // LL_GLIB bool LLAppViewerLinux::initSLURLHandler() { return false; // not implemented without dbus @@ -344,7 +311,7 @@ bool LLAppViewerLinux::sendURLToOtherInstance(const std::string& url) { return false; // not implemented without dbus } -#endif // LL_DBUS_ENABLED +#endif // LL_GLIB void LLAppViewerLinux::initCrashReporting(bool reportFreeze) { diff --git a/indra/newview/llappviewerlinux.h b/indra/newview/llappviewerlinux.h index ed71ff36fd..abe62c9289 100644 --- a/indra/newview/llappviewerlinux.h +++ b/indra/newview/llappviewerlinux.h @@ -27,17 +27,6 @@ #ifndef LL_LLAPPVIEWERLINUX_H #define LL_LLAPPVIEWERLINUX_H -extern "C" { -# include -} - -#if LL_DBUS_ENABLED -extern "C" { -# include -# include -} -#endif - #ifndef LL_LLAPPVIEWER_H #include "llappviewer.h" #endif @@ -70,26 +59,4 @@ protected: virtual bool sendURLToOtherInstance(const std::string& url); }; -#if LL_DBUS_ENABLED -typedef struct -{ - GObject parent; - DBusGConnection *connection; -} ViewerAppAPI; - -extern "C" { - // FIRE-5417; The xml manifest for dbus claims success_rtn is a boolean, not a boolean array - - // gboolean viewer_app_api_GoSLURL(ViewerAppAPI *obj, gchar *slurl, gboolean **success_rtn, GError **error); - gboolean viewer_app_api_GoSLURL(ViewerAppAPI *obj, gchar *slurl, gboolean *success_rtn, GError **error); - - // -} - -#define VIEWERAPI_SERVICE "com.secondlife.ViewerAppAPIService" -#define VIEWERAPI_PATH "/com/secondlife/ViewerAppAPI" -#define VIEWERAPI_INTERFACE "com.secondlife.ViewerAppAPI" - -#endif // LL_DBUS_ENABLED - #endif // LL_LLAPPVIEWERLINUX_H diff --git a/indra/newview/llappviewerlinux_api.h b/indra/newview/llappviewerlinux_api.h deleted file mode 100644 index 5d5fcaa3d6..0000000000 --- a/indra/newview/llappviewerlinux_api.h +++ /dev/null @@ -1,143 +0,0 @@ -/* Generated by dbus-binding-tool; do not edit! */ -/** - * $LicenseInfo:firstyear=2008&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef __dbus_glib_marshal_viewerapp_MARSHAL_H__ -#define __dbus_glib_marshal_viewerapp_MARSHAL_H__ - -#include - -G_BEGIN_DECLS - -#ifdef G_ENABLE_DEBUG -#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) -#define g_marshal_value_peek_char(v) g_value_get_char (v) -#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) -#define g_marshal_value_peek_int(v) g_value_get_int (v) -#define g_marshal_value_peek_uint(v) g_value_get_uint (v) -#define g_marshal_value_peek_long(v) g_value_get_long (v) -#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) -#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) -#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) -#define g_marshal_value_peek_enum(v) g_value_get_enum (v) -#define g_marshal_value_peek_flags(v) g_value_get_flags (v) -#define g_marshal_value_peek_float(v) g_value_get_float (v) -#define g_marshal_value_peek_double(v) g_value_get_double (v) -#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) -#define g_marshal_value_peek_param(v) g_value_get_param (v) -#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) -#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) -#define g_marshal_value_peek_object(v) g_value_get_object (v) -#else /* !G_ENABLE_DEBUG */ -/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. - * Do not access GValues directly in your code. Instead, use the - * g_value_get_*() functions - */ -#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int -#define g_marshal_value_peek_char(v) (v)->data[0].v_int -#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint -#define g_marshal_value_peek_int(v) (v)->data[0].v_int -#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint -#define g_marshal_value_peek_long(v) (v)->data[0].v_long -#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong -#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 -#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 -#define g_marshal_value_peek_enum(v) (v)->data[0].v_long -#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong -#define g_marshal_value_peek_float(v) (v)->data[0].v_float -#define g_marshal_value_peek_double(v) (v)->data[0].v_double -#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer -#endif /* !G_ENABLE_DEBUG */ - - -/* BOOLEAN:STRING,POINTER,POINTER (/tmp/dbus-binding-tool-c-marshallers.5XXD8T:1) */ -extern void dbus_glib_marshal_viewerapp_BOOLEAN__STRING_POINTER_POINTER (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); -void -dbus_glib_marshal_viewerapp_BOOLEAN__STRING_POINTER_POINTER (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - typedef gboolean (*GMarshalFunc_BOOLEAN__STRING_POINTER_POINTER) (gpointer data1, - gpointer arg_1, - gpointer arg_2, - gpointer arg_3, - gpointer data2); - register GMarshalFunc_BOOLEAN__STRING_POINTER_POINTER callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - gboolean v_return; - - g_return_if_fail (return_value != NULL); - g_return_if_fail (n_param_values == 4); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_BOOLEAN__STRING_POINTER_POINTER) (marshal_data ? marshal_data : cc->callback); - - v_return = callback (data1, - g_marshal_value_peek_string (param_values + 1), - g_marshal_value_peek_pointer (param_values + 2), - g_marshal_value_peek_pointer (param_values + 3), - data2); - - g_value_set_boolean (return_value, v_return); -} - -G_END_DECLS - -#endif /* __dbus_glib_marshal_viewerapp_MARSHAL_H__ */ - -#include -static const DBusGMethodInfo dbus_glib_viewerapp_methods[] = { - { (GCallback) viewer_app_api_GoSLURL, dbus_glib_marshal_viewerapp_BOOLEAN__STRING_POINTER_POINTER, 0 }, -}; - -const DBusGObjectInfo dbus_glib_viewerapp_object_info = { - 0, - dbus_glib_viewerapp_methods, - 1, -"com.secondlife.ViewerAppAPI\0GoSLURL\0S\0slurl\0I\0s\0success_ret\0O\0F\0N\0b\0\0\0", -"\0", -"\0" -}; - diff --git a/indra/newview/llappviewerlinux_api.xml b/indra/newview/llappviewerlinux_api.xml deleted file mode 100644 index fac35b7adc..0000000000 --- a/indra/newview/llappviewerlinux_api.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/indra/newview/llappviewerlinux_api_dbus.cpp b/indra/newview/llappviewerlinux_api_dbus.cpp deleted file mode 100644 index 6ac30bd9b8..0000000000 --- a/indra/newview/llappviewerlinux_api_dbus.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/** - * @file llappviewerlinux_api_dbus.cpp - * @brief dynamic DBus symbol-grabbing code - * - * $LicenseInfo:firstyear=2008&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#if LL_DBUS_ENABLED - -#include "linden_common.h" - -extern "C" { -#include - -#include "apr_pools.h" -#include "apr_dso.h" -} - -#define DEBUGMSG(...) do { LL_DEBUGS() << llformat(__VA_ARGS__) << LL_ENDL; } while(0) -#define INFOMSG(...) do { LL_INFOS() << llformat(__VA_ARGS__) << LL_ENDL; } while(0) -#define WARNMSG(...) do { LL_WARNS() << llformat(__VA_ARGS__) << LL_ENDL; } while(0) - -#define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) RTN (*ll##DBUSSYM)(__VA_ARGS__) = NULL -#include "llappviewerlinux_api_dbus_syms_raw.inc" -#undef LL_DBUS_SYM - -static bool sSymsGrabbed = false; -static apr_pool_t *sSymDBUSDSOMemoryPool = NULL; -static apr_dso_handle_t *sSymDBUSDSOHandleG = NULL; - -bool grab_dbus_syms(std::string dbus_dso_name) -{ - if (sSymsGrabbed) - { - // already have grabbed good syms - return TRUE; - } - - bool sym_error = false; - bool rtn = false; - apr_status_t rv; - apr_dso_handle_t *sSymDBUSDSOHandle = NULL; - -#define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##DBUSSYM, sSymDBUSDSOHandle, #DBUSSYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #DBUSSYM); if (REQUIRED) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #DBUSSYM, (void*)ll##DBUSSYM);}while(0) - - //attempt to load the shared library - apr_pool_create(&sSymDBUSDSOMemoryPool, NULL); - - if ( APR_SUCCESS == (rv = apr_dso_load(&sSymDBUSDSOHandle, - dbus_dso_name.c_str(), - sSymDBUSDSOMemoryPool) )) - { - INFOMSG("Found DSO: %s", dbus_dso_name.c_str()); - -#include "llappviewerlinux_api_dbus_syms_raw.inc" - - if ( sSymDBUSDSOHandle ) - { - sSymDBUSDSOHandleG = sSymDBUSDSOHandle; - sSymDBUSDSOHandle = NULL; - } - - rtn = !sym_error; - } - else - { - INFOMSG("Couldn't load DSO: %s", dbus_dso_name.c_str()); - rtn = false; // failure - } - - if (sym_error) - { - WARNMSG("Failed to find necessary symbols in DBUS-GLIB libraries."); - } -#undef LL_DBUS_SYM - - sSymsGrabbed = rtn; - return rtn; -} - - -void ungrab_dbus_syms() -{ - // should be safe to call regardless of whether we've - // actually grabbed syms. - - if ( sSymDBUSDSOHandleG ) - { - apr_dso_unload(sSymDBUSDSOHandleG); - sSymDBUSDSOHandleG = NULL; - } - - if ( sSymDBUSDSOMemoryPool ) - { - apr_pool_destroy(sSymDBUSDSOMemoryPool); - sSymDBUSDSOMemoryPool = NULL; - } - - // NULL-out all of the symbols we'd grabbed -#define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) do{ll##DBUSSYM = NULL;}while(0) -#include "llappviewerlinux_api_dbus_syms_raw.inc" -#undef LL_DBUS_SYM - - sSymsGrabbed = false; -} - -#endif // LL_DBUS_ENABLED diff --git a/indra/newview/llappviewerlinux_api_dbus.h b/indra/newview/llappviewerlinux_api_dbus.h deleted file mode 100644 index 3eee25b53d..0000000000 --- a/indra/newview/llappviewerlinux_api_dbus.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @file llappviewerlinux_api_dbus.h - * @brief DBus-glib symbol handling - * - * $LicenseInfo:firstyear=2008&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#if LL_DBUS_ENABLED - -extern "C" { -#include -} - -#define DBUSGLIB_DYLIB_DEFAULT_NAME "libdbus-glib-1.so.2" - -bool grab_dbus_syms(std::string dbus_dso_name); -void ungrab_dbus_syms(); - -#define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) extern RTN (*ll##DBUSSYM)(__VA_ARGS__) -#include "llappviewerlinux_api_dbus_syms_raw.inc" -#undef LL_DBUS_SYM - -#endif // LL_DBUS_ENABLED diff --git a/indra/newview/llappviewerlinux_api_dbus_syms_raw.inc b/indra/newview/llappviewerlinux_api_dbus_syms_raw.inc deleted file mode 100644 index c0548e2fba..0000000000 --- a/indra/newview/llappviewerlinux_api_dbus_syms_raw.inc +++ /dev/null @@ -1,9 +0,0 @@ - -// required symbols to grab -LL_DBUS_SYM(true, dbus_g_bus_get, DBusGConnection*, DBusBusType, GError**); -LL_DBUS_SYM(true, dbus_g_proxy_new_for_name, DBusGProxy*, DBusGConnection*, const char *, const char*, const char*); -LL_DBUS_SYM(true, dbus_g_proxy_call, gboolean, DBusGProxy*, const char*, GError**, GType, ...); -LL_DBUS_SYM(true, dbus_g_object_type_install_info, void, GType, const DBusGObjectInfo*); -LL_DBUS_SYM(true, dbus_g_connection_register_g_object, void, DBusGConnection*, const char*, GObject*); - -// optional symbols to grab diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 753a78fefd..e55931cfa9 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -885,6 +885,7 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id, } else { + args["ONLINE_STATUS"] = true; LLNotificationsUI::LLNotificationManager::instance().onChat(chat, args); } diff --git a/indra/newview/lldirpicker.cpp b/indra/newview/lldirpicker.cpp index 01790ad19e..12dbc53f60 100644 --- a/indra/newview/lldirpicker.cpp +++ b/indra/newview/lldirpicker.cpp @@ -41,6 +41,11 @@ # include "llfilepicker.h" #endif +#ifdef LL_FLTK + #include "FL/Fl.H" + #include "FL/Fl_Native_File_Chooser.H" +#endif + // // Globals // @@ -193,32 +198,41 @@ LLDirPicker::LLDirPicker() : mFileName(NULL), mLocked(false) { +#ifndef LL_FLTK mFilePicker = new LLFilePicker(); +#endif + reset(); } LLDirPicker::~LLDirPicker() { +#ifndef LL_FLTK delete mFilePicker; +#endif } void LLDirPicker::reset() { +#ifndef LL_FLTK if (mFilePicker) - mFilePicker->reset(); + mFilePicker->reset(); +#else + mDir = ""; +#endif } BOOL LLDirPicker::getDir(std::string* filename, bool blocking) { reset(); - // if local file browsing is turned off, return without opening dialog if ( check_local_file_access_enabled() == false ) { return FALSE; } +#ifndef LL_FLTK #if !LL_MESA_HEADLESS if (mFilePicker) @@ -237,15 +251,42 @@ BOOL LLDirPicker::getDir(std::string* filename, bool blocking) #endif // !LL_MESA_HEADLESS return FALSE; +#else + gViewerWindow->getWindow()->beforeDialog(); + Fl_Native_File_Chooser flDlg; + flDlg.title(LLTrans::getString("choose_the_directory").c_str()); + flDlg.type(Fl_Native_File_Chooser::BROWSE_DIRECTORY ); + + int res = flDlg.show(); + + gViewerWindow->getWindow()->afterDialog(); + + if( res == 0 ) + { + char const *pDir = flDlg.filename(0); + if( pDir ) + mDir = pDir; + } + else if( res == -1 ) + { + LL_WARNS() << "FLTK failed: " << flDlg.errmsg() << LL_ENDL; + } + + return !mDir.empty(); +#endif } std::string LLDirPicker::getDirName() { +#ifndef LL_FLTK if (mFilePicker) { return mFilePicker->getFirstFile(); } return ""; +#else + return mDir; +#endif } #else // not implemented diff --git a/indra/newview/lldirpicker.h b/indra/newview/lldirpicker.h index 52febe4523..3406488494 100644 --- a/indra/newview/lldirpicker.h +++ b/indra/newview/lldirpicker.h @@ -79,9 +79,12 @@ private: bool check_local_file_access_enabled(); #if LL_LINUX || LL_DARWIN - // On Linux we just implement LLDirPicker on top of LLFilePicker + // On Linux we just implement LLDirPicker on top of LLFilePicker + // Seems like on OSX too ... Unless FLTK is used, then nope +#ifndef LL_FLTK LLFilePicker *mFilePicker; #endif +#endif std::string* mFileName; diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index be62f7b3a9..48ca376a7a 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -36,10 +36,16 @@ #include "llviewercontrol.h" #include "llwindow.h" // beforeDialog() +#undef LL_GTK #if LL_SDL #include "llwindowsdl.h" // for some X/GTK utils to help with filepickers #endif // LL_SDL +#ifdef LL_FLTK + #include "FL/Fl.H" + #include "FL/Fl_Native_File_Chooser.H" +#endif + #if LL_LINUX #include "llhttpconstants.h" // file picker uses some of thes constants on Linux #endif @@ -1566,12 +1572,243 @@ BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter, bool blocking) return rtn; } +#elif LL_FLTK +BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename, bool blocking ) +{ + return openFileDialog( filter, blocking, eSaveFile ); +} + +BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking ) +{ + return openFileDialog( filter, blocking, eOpenFile ); +} + +BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter, bool blocking) +{ + return openFileDialog( filter, blocking, eOpenMultiple ); +} + +bool LLFilePicker::openFileDialog( int32_t filter, bool blocking, EType aType ) +{ + if ( check_local_file_access_enabled() == false ) + return false; + + gViewerWindow->getWindow()->beforeDialog(); + reset(); + Fl_Native_File_Chooser::Type flType = Fl_Native_File_Chooser::BROWSE_FILE; + + if( aType == eOpenMultiple ) + flType = Fl_Native_File_Chooser::BROWSE_MULTI_FILE; + else if( aType == eSaveFile ) + flType = Fl_Native_File_Chooser::BROWSE_SAVE_FILE; + + Fl_Native_File_Chooser flDlg; + + std::string file_dialog_title; + std::string file_dialog_filter; + + if (aType == EType::eSaveFile) + { + std::string file_type("all_files"); + + switch ((ESaveFilter) filter) + { + case FFSAVE_ALL: + break; + case FFSAVE_TGA: + file_type = "targa_image_files"; + file_dialog_filter = "*.tga"; + break; + case FFSAVE_BMP: + file_type = "bitmap_image_files"; + file_dialog_filter = "*.bmp"; + break; + case FFSAVE_AVI: + file_type = "avi_movie_file"; + file_dialog_filter = "*.avi"; + break; + case FFSAVE_ANIM: + file_type = "xaf_animation_file"; + file_dialog_filter = "*.xaf"; + break; + case FFSAVE_XML: + file_type = "xml_file"; + file_dialog_filter = "*.xml"; + break; + case FFSAVE_COLLADA: + file_type = "collada_files"; + file_dialog_filter = "*.dae"; + break; + case FFSAVE_RAW: + file_type = "raw_file"; + file_dialog_filter = "*.raw"; + break; + case FFSAVE_J2C: + file_type = "compressed_image_files"; + file_dialog_filter = "*.j2c"; + break; + case FFSAVE_PNG: + file_type = "png_image_files"; + file_dialog_filter = "*.png"; + break; + case FFSAVE_JPEG: + file_type = "jpeg_image_files"; + file_dialog_filter = "*.{jpg,jpeg}"; + break; + case FFSAVE_SCRIPT: + file_type = "script_files"; + file_dialog_filter = "*.lsl"; + break; + case FFSAVE_TGAPNG: + file_type = "save_texture_image_files"; + file_dialog_filter = "*.{tga,png}"; + break; + case FFSAVE_WAV: + file_type = "sound_files"; + file_dialog_filter = "*.wav"; + break; + + // Firestorm additions + case FFSAVE_BEAM: + file_type = "xml_file"; + file_dialog_filter = "*.xml"; + break; + case FFSAVE_EXPORT: + file_type = "backup_files"; + file_dialog_filter = "*.oxp"; + break; + case FFSAVE_CSV: + file_type = "csv_files"; + file_dialog_filter = "*.csv"; + break; + +#ifdef _CORY_TESTING + case FFSAVE_GEOMETRY: + // no file type translation for this, so using the default "all_files" for now + file_dialog_filter = "*.slg"; + break; +#endif + } + + // can't say I like this combining of verb+type, it might not work too well in all languages -Zi + file_dialog_title = LLTrans::getString("save_file_verb") + " " + LLTrans::getString(file_type); + file_dialog_filter = LLTrans::getString(file_type) + " \t" + file_dialog_filter; + } + else + { + std::string file_type("all_files"); + + switch ((ELoadFilter) filter) + { + case FFLOAD_ALL: + break; + case FFLOAD_WAV: + file_type = "sound_files"; + file_dialog_filter = "*.wav"; + break; + case FFLOAD_IMAGE: + file_type = "image_files"; + file_dialog_filter = "*.{tga,bmp,jpg,jpeg,png}"; + break; + case FFLOAD_ANIM: + file_type = "animation_files"; + file_dialog_filter = "*.{bvh,anim}"; + break; + case FFLOAD_XML: + file_type = "xml_file"; + file_dialog_filter = "*.xml"; + break; + case FFLOAD_SLOBJECT: + file_type = "xml_file"; + file_dialog_filter = "*.slobject"; + break; + case FFLOAD_RAW: + file_type = "raw_file"; + file_dialog_filter = "*.raw"; + break; + case FFLOAD_MODEL: + case FFLOAD_COLLADA: + file_type = "collada_files"; + file_dialog_filter = "*.dae"; + break; + case FFLOAD_SCRIPT: + file_type = "script_files"; + file_dialog_filter = "*.lsl"; + break; + case FFLOAD_DICTIONARY: + file_type = "dictionary_files"; + file_dialog_filter = "*.{dic,xcu}"; + break; + case FFLOAD_DIRECTORY: + file_type = "choose_the_directory"; + break; + case FFLOAD_EXE: + file_type = "executable_files"; + break; + + // Firestorm additions + case FFLOAD_IMPORT: + file_type = "backup_files"; + file_dialog_filter = "*.oxp"; + break; + +#ifdef _CORY_TESTING + case FFLOAD_GEOMETRY: + // no file type translation for this, so using the default "all_files" for now + file_dialog_filter = "*.slg"; + break; +#endif + } + + if (aType == EType::eOpenMultiple) + { + file_dialog_title = LLTrans::getString("load_files"); + } + else + { + // can't say I like this combining of verb+type, it might not work too well in all languages -Zi + file_dialog_title = LLTrans::getString("load_file_verb") + " " + LLTrans::getString(file_type); + file_dialog_filter = LLTrans::getString(file_type) + " \t" + file_dialog_filter; + } + } + + flDlg.title(file_dialog_title.c_str()); + flDlg.type(flType); + + if (!file_dialog_filter.empty()) + { + flDlg.filter(file_dialog_filter.c_str()); + } + + int res = flDlg.show(); + gViewerWindow->getWindow()->afterDialog(); + + if( res == 0 ) + { + int32_t count = flDlg.count(); + if( count < 0 ) + count = 0; + for( int32_t i = 0; i < count; ++i ) + { + char const *pFile = flDlg.filename(i); + if( pFile && strlen(pFile) > 0 ) + mFiles.push_back( pFile ); + } + } + else if( res == -1 ) + { + LL_WARNS() << "FLTK failed: " << flDlg.errmsg() << LL_ENDL; + } + + return mFiles.empty()?FALSE:TRUE; +} + # else // LL_GTK // Hacky stubs designed to facilitate fake getSaveFile and getOpenFile with // static results, when we don't have a real filepicker. -BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename ) +BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename, bool blocking ) { // if local file browsing is turned off, return without opening dialog // (Even though this is a stub, I think we still should not return anything at all) @@ -1634,7 +1871,7 @@ BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter, bool blocking) #else // not implemented -BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename ) +BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename, bool blockin ) { reset(); return FALSE; diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index 53ea7fd316..1aa5802d02 100644 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -33,6 +33,12 @@ #ifndef LL_LLFILEPICKER_H #define LL_LLFILEPICKER_H +#if LL_FLTK + #if LL_GTK + #undef LL_GTK + #endif +#endif + #include "stdtypes.h" #if LL_DARWIN @@ -58,12 +64,13 @@ extern "C" { // mostly for Linux, possible on others #if LL_GTK # include "gtk/gtk.h" +#error "Direct use of GTK is deprecated" #endif // LL_GTK } class LLFilePicker { -#ifdef LL_GTK +#if LL_GTK friend class LLDirPicker; friend void chooser_responder(GtkWidget *, gint, gpointer); #endif // LL_GTK @@ -187,7 +194,14 @@ private: // we also remember the extension of the last added file. std::string mCurrentExtension; #endif - +#if LL_FLTK + enum EType + { + eSaveFile, eOpenFile, eOpenMultiple + }; + bool openFileDialog( int32_t filter, bool blocking, EType aType ); +#endif + std::vector mFiles; S32 mCurrentFile; bool mLocked; diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp index 3136f96fe4..2031fc6a4e 100644 --- a/indra/newview/llfloaterimnearbychathandler.cpp +++ b/indra/newview/llfloaterimnearbychathandler.cpp @@ -569,7 +569,7 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg, RlvUtil::filterLocation(tmp_chat.mText); tmp_chat.mRlvLocFiltered = TRUE; } - if ( (!RlvActions::canShowName(RlvActions::SNC_DEFAULT)) && (!tmp_chat.mRlvNamesFiltered) && (CHAT_SOURCE_AGENT != tmp_chat.mSourceType) ) + if ( (!RlvActions::canShowName(RlvActions::SNC_DEFAULT)) && (!tmp_chat.mRlvNamesFiltered) && (CHAT_SOURCE_AGENT != tmp_chat.mSourceType) && (!args.has("ONLINE_STATUS") || !args["ONLINE_STATUS"].asBoolean()) ) { RlvUtil::filterNames(tmp_chat.mText); tmp_chat.mRlvNamesFiltered = TRUE; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 603de526b4..2987593788 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -3139,6 +3139,16 @@ void LLFloaterPreference::updateUISoundsControls() getChild("PlayModeUISndNewIncomingGroupIMSession")->setValue((int)gSavedSettings.getU32("PlayModeUISndNewIncomingGroupIMSession")); // 0, 1, 2, 3. Shared with Chat > Notifications > "When receiving Group Instant Messages" getChild("PlayModeUISndNewIncomingConfIMSession")->setValue((int)gSavedSettings.getU32("PlayModeUISndNewIncomingConfIMSession")); // 0, 1, 2, 3. Shared with Chat > Notifications > "When receiving AdHoc Instant Messages" #ifdef OPENSIM + // OpenSim has option to not attenuate nearby local voice by distance + auto earPosGroup = findChild("ear_location"); + if (earPosGroup) + { + // It seems there is no better way to do this than with magic numbers short of importing the enums in vivoxvoice (which aren't necessarily the same thing). + // Index 2 here is the opensim only option to hear nearby chat without attenuation. + constexpr int hearNearbyVoiceFullVolume{2}; + earPosGroup->setIndexEnabled(hearNearbyVoiceFullVolume, LLGridManager::instance().isInOpenSim()); + } + // getChild("textFSRestartOpenSim")->setVisible(TRUE); getChild("UISndRestartOpenSim")->setVisible(TRUE); getChild("Prev_UISndRestartOpenSim")->setVisible(TRUE); diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index c60ab8ca2a..500ec37738 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -334,15 +334,15 @@ BOOL LLFloaterTools::postBuild() sShowObjectCost = gSavedSettings.getBOOL("ShowObjectRenderingCost"); // Added back more/less button - LLButton* btnExpand = getChild("btnExpand"); + LLButton* btnExpand = findChild("btnExpand"); if (btnExpand && mTab) { mExpandedHeight = getRect().getHeight(); mCollapsedHeight = mExpandedHeight - mTab->getRect().getHeight() + btnExpand->getRect().getHeight(); - if(!gSavedSettings.getBOOL("FSToolboxExpanded")) + if (!gSavedSettings.getBOOL("FSToolboxExpanded")) { mTab->setVisible(FALSE); - reshape( getRect().getWidth(), mCollapsedHeight); + reshape(getRect().getWidth(), mCollapsedHeight); btnExpand->setImageOverlay("Arrow_Down", btnExpand->getImageOverlayHAlign()); } } diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index a7227c7f58..3b1f3179d3 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -1112,11 +1112,7 @@ void handleRenderAvatarMaxARTChanged(const LLSD& newValue) { FSPerfStats::StatsRecorder::updateRenderCostLimitFromSettings(); } -void handleFPSTuningStrategyChanged(const LLSD& newValue) -{ - const auto newval = gSavedSettings.getU32("FSTuningFPSStrategy"); - FSPerfStats::fpsTuningStrategy = newval; -} + void handlePerformanceStatsEnabledChanged(const LLSD& newValue) { const auto newval = gSavedSettings.getBOOL("FSPerfStatsCaptureEnabled"); @@ -1383,7 +1379,6 @@ void settings_setup_listeners() gSavedSettings.getControl("FSTargetFPS")->getSignal()->connect(boost::bind(&handleTargetFPSChanged, _2)); gSavedSettings.getControl("FSAutoTuneFPS")->getSignal()->connect(boost::bind(&handleAutoTuneFPSChanged, _2)); gSavedSettings.getControl("FSRenderAvatarMaxART")->getSignal()->connect(boost::bind(&handleRenderAvatarMaxARTChanged, _2)); - gSavedSettings.getControl("FSTuningFPSStrategy")->getSignal()->connect(boost::bind(&handleFPSTuningStrategyChanged, _2)); gSavedSettings.getControl("FSPerfStatsCaptureEnabled")->getSignal()->connect(boost::bind(&handlePerformanceStatsEnabledChanged, _2)); // } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index c1e66229da..e4eea0a510 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -6839,7 +6839,7 @@ void mean_name_callback(const LLUUID &id, const LLAvatarName& av_name) LLMeanCollisionData *mcd = *iter; if (mcd->mPerp == id) { - mcd->mFullName = av_name.getUserName(); + mcd->mFullName = gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) ? RlvStrings::getAnonym(av_name) : av_name.getUserName(); } } // Instant bump list floater update @@ -6886,7 +6886,14 @@ void process_mean_collision_alert_message(LLMessageSystem *msgsystem, void **use { std::string action; LLStringUtil::format_map_t args; - args["NAME"] = llformat("secondlife:///app/agent/%s/inspect", perp.asString().c_str()); + if (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) + { + args["NAME"] = llformat("secondlife:///app/agent/%s/inspect", perp.asString().c_str()); + } + else + { + args["NAME"] = llformat("secondlife:///app/agent/%s/rlvanonym", perp.asString().c_str()); + } switch (type) { @@ -6920,10 +6927,10 @@ void process_mean_collision_alert_message(LLMessageSystem *msgsystem, void **use LLMessageSystem* msgs = gMessageSystem; msgs->newMessage(_PREHASH_ScriptDialogReply); msgs->nextBlock(_PREHASH_AgentData); - msgs->addUUID(_PREHASH_AgentID, gAgent.getID()); - msgs->addUUID(_PREHASH_SessionID, gAgent.getSessionID()); + msgs->addUUID(_PREHASH_AgentID, gAgentID); + msgs->addUUID(_PREHASH_SessionID, gAgentSessionID); msgs->nextBlock(_PREHASH_Data); - msgs->addUUID(_PREHASH_ObjectID, gAgent.getID()); + msgs->addUUID(_PREHASH_ObjectID, gAgentID); msgs->addS32(_PREHASH_ChatChannel, gSavedSettings.getS32("FSReportCollisionMessagesChannel")); msgs->addS32(_PREHASH_ButtonIndex, 1); msgs->addString(_PREHASH_ButtonLabel, collision_data.c_str()); diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 733fb3c7df..0f15443b8b 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -614,7 +614,8 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, if(update_cache) { - objectp = regionp->updateCacheEntry(local_id, objectp, update_type); + //update object cache if the object receives a full-update or terse update + objectp = regionp->updateCacheEntry(local_id, objectp); } // This looks like it will break if the local_id of the object doesn't change diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 48ca6e0b28..a0ae4a9f9b 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1862,13 +1862,8 @@ LLViewerObject* LLViewerRegion::addNewObject(LLVOCacheEntry* entry) //update object cache if the object receives a full-update or terse update //update_type == EObjectUpdateType::OUT_TERSE_IMPROVED or EObjectUpdateType::OUT_FULL -LLViewerObject* LLViewerRegion::updateCacheEntry(U32 local_id, LLViewerObject* objectp, U32 update_type) +LLViewerObject* LLViewerRegion::updateCacheEntry(U32 local_id, LLViewerObject* objectp) { - if(objectp && update_type != (U32)OUT_TERSE_IMPROVED) - { - return objectp; //no need to access cache - } - LLVOCacheEntry* entry = getCacheEntry(local_id); if (!entry) { @@ -1880,11 +1875,8 @@ LLViewerObject* LLViewerRegion::updateCacheEntry(U32 local_id, LLViewerObject* o objectp = addNewObject(entry); } - //remove from cache if terse update - if(update_type == (U32)OUT_TERSE_IMPROVED) - { - killCacheEntry(entry, true); - } + //remove from cache. + killCacheEntry(entry, true); return objectp; } diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index 2aa8258a75..77acc5a98b 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -380,7 +380,7 @@ public: void requestCacheMisses(); void addCacheMissFull(const U32 local_id); //update object cache if the object receives a full-update or terse update - LLViewerObject* updateCacheEntry(U32 local_id, LLViewerObject* objectp, U32 update_type); + LLViewerObject* updateCacheEntry(U32 local_id, LLViewerObject* objectp); void findOrphans(U32 parent_id); void clearCachedVisibleObjects(); void dumpCache(); diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index fce26c1d10..4b0a3c8259 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -3397,17 +3397,31 @@ void LLVivoxVoiceClient::sendPositionAndVolumeUpdate(void) earVelocity = mAvatarVelocity; earRot = mCameraRot; break; +// reimplement hear voice equally + case earLocSpeaker: + // we leave EarPos/Vel/Rot as empty + LL_DEBUGS("Voice") << "EarLoc Speaker in use" << LL_ENDL; + break; +// } +// reimplement hear voice equally + if(mEarLocation != earLocSpeaker) + { + // for all spatial sources we need to do the transform +// l = earRot.getLeftRow(); u = earRot.getUpRow(); a = earRot.getFwdRow(); pos = earPosition; vel = earVelocity; - + oldSDKTransform(l, u, a, pos, vel); +// reimplement hear voice equally + } +// if (mHidden) { diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h index d19e6ca718..23a04b723c 100644 --- a/indra/newview/llvoicevivox.h +++ b/indra/newview/llvoicevivox.h @@ -803,6 +803,7 @@ private: { earLocCamera = 0, // ear at camera earLocAvatar, // ear at avatar + earLocSpeaker, // re-add equal voice based loosely on original patch from Tigh MacFanatic earLocMixed // ear at avatar location/camera direction }; diff --git a/indra/newview/skins/default/xui/de/floater_performance.xml b/indra/newview/skins/default/xui/de/floater_performance.xml index 28a98d3e55..4985f92000 100644 --- a/indra/newview/skins/default/xui/de/floater_performance.xml +++ b/indra/newview/skins/default/xui/de/floater_performance.xml @@ -48,7 +48,7 @@ - + diff --git a/indra/newview/skins/default/xui/de/panel_preferences_UI.xml b/indra/newview/skins/default/xui/de/panel_preferences_UI.xml index ce4be02ba0..d28f52b3fc 100644 --- a/indra/newview/skins/default/xui/de/panel_preferences_UI.xml +++ b/indra/newview/skins/default/xui/de/panel_preferences_UI.xml @@ -233,6 +233,7 @@ + diff --git a/indra/newview/skins/default/xui/de/panel_preferences_sound.xml b/indra/newview/skins/default/xui/de/panel_preferences_sound.xml index 8cdf0fa6dd..06df86e757 100644 --- a/indra/newview/skins/default/xui/de/panel_preferences_sound.xml +++ b/indra/newview/skins/default/xui/de/panel_preferences_sound.xml @@ -10,8 +10,8 @@ Maustaste 5 - - + + @@ -57,7 +57,7 @@ - + @@ -72,23 +72,23 @@