From 45228f920da1a93917df07ab8fa74260618e62ff Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Tue, 19 Mar 2019 02:41:31 -0400 Subject: [PATCH 001/110] Cleanup excess code and gURLProtocolWhitelist, add isWhitelistedProtocol() # Conflicts: # indra/llwindow/llwindowmacosx.cpp # indra/llwindow/llwindowsdl2.cpp --- indra/llwindow/llwindow.cpp | 9 +- indra/llwindow/llwindow.h | 6 +- indra/llwindow/llwindowmacosx.cpp | 3114 +++++++---------------------- indra/llwindow/llwindowsdl.cpp | 13 +- indra/llwindow/llwindowwin32.cpp | 13 +- 5 files changed, 705 insertions(+), 2450 deletions(-) diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp index f64b48667..5efcdbd18 100644 --- a/indra/llwindow/llwindow.cpp +++ b/indra/llwindow/llwindow.cpp @@ -49,15 +49,18 @@ LLSplashScreen *gSplashScreenp = NULL; BOOL gDebugClicks = FALSE; BOOL gDebugWindowProc = FALSE; -const S32 gURLProtocolWhitelistCount = 5; -const std::string gURLProtocolWhitelist[] = { "secondlife:", "http:", "https:", "data:", "mailto:" }; - +bool isWhitelistedProtocol(const std::string& escaped_url) { // CP: added a handler list - this is what's used to open the protocol and is based on registry entry // only meaningful difference currently is that file: protocols are opened using http: // since no protocol handler exists in registry for file: // Important - these lists should match - protocol to handler // Maestro: This list isn't referenced anywhere that I could find //const std::string gURLProtocolWhitelistHandler[] = { "http", "http", "https" }; + for (const auto& protocol : { "secondlife:", "http:", "https:", "data:", "mailto:" }) + if (escaped_url.find(protocol) != std::string::npos) + return true; + return false; +} S32 OSMessageBox(const std::string& text, const std::string& caption, U32 type) diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index cf92c3a51..85d5c0fb1 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -290,11 +290,7 @@ public: // extern BOOL gDebugWindowProc; -// Protocols, like "http" and "https" we support in URLs -extern const S32 gURLProtocolWhitelistCount; -extern const std::string gURLProtocolWhitelist[]; -//extern const std::string gURLProtocolWhitelistHandler[]; - +bool isWhitelistedProtocol(const std::string& escaped_url); void simpleEscapeString ( std::string& stringIn ); #endif // _LL_window_h_ diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 8c11a05d3..9becdcaff 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com /** * @file llwindowmacosx.cpp * @brief Platform-dependent implementation of llwindow @@ -30,7 +32,6 @@ #include "llkeyboardmacosx.h" #include "llwindowcallbacks.h" -#include "llwindowmacosx-objc.h" #include "llpreeditor.h" #include "llerror.h" @@ -39,27 +40,28 @@ #include "lldir.h" #include "indra_constants.h" -#include #include +#include +#include extern BOOL gDebugWindowProc; +extern BOOL gUseMultGL; // culled from winuser.h //const S32 WHEEL_DELTA = 120; /* Value for rolling one detent */ // On the Mac, the scroll wheel reports a delta of 1 for each detent. // There's also acceleration for faster scrolling, based on a slider in the system preferences. -const S32 WHEEL_DELTA = 1; /* Value for rolling one detent */ const S32 BITS_PER_PIXEL = 32; const S32 MAX_NUM_RESOLUTIONS = 32; - +namespace +{ + NSKeyEventRef mRawKeyEvent = NULL; +} // // LLWindowMacOSX // -BOOL LLWindowMacOSX::sUseMultGL = FALSE; -WindowRef LLWindowMacOSX::sMediaWindow = NULL; - // Cross-platform bits: BOOL check_for_card(const char* RENDERER, const char* bad_card) @@ -67,20 +69,20 @@ BOOL check_for_card(const char* RENDERER, const char* bad_card) if (!strnicmp(RENDERER, bad_card, strlen(bad_card))) { std::string buffer = llformat( - "Your video card appears to be a %s, which Second Life does not support.\n" + "Your video card appears to be a %s, which Singularity does not support.\n" "\n" - "Second Life requires a video card with 32 Mb of memory or more, as well as\n" + "Singularity requires a video card with 32 Mb of memory or more, as well as\n" "multitexture support. We explicitly support nVidia GeForce 2 or better, \n" - "and ATI Radeon 8500 or better.\n" + "and ATI Radeon 8500 or better... A LOT better. lol\n" "\n" "If you own a supported card and continue to receive this message, try \n" "updating to the latest video card drivers. Otherwise look in the\n" "secondlife.com support section or e-mail technical support\n" "\n" - "You can try to run Second Life, but it will probably crash or run\n" + "You can try to run Singularity, but it will probably crash or run\n" "very slowly. Try anyway?", bad_card); - S32 button = OSMessageBox(buffer, "Unsupported video card", OSMB_YESNO); + S32 button = OSMessageBox(buffer.c_str(), "Unsupported video card", OSMB_YESNO); if (OSBTN_YES == button) { return FALSE; @@ -98,105 +100,9 @@ BOOL check_for_card(const char* RENDERER, const char* bad_card) // We may want to base this on the setting of _DEBUG... #define CAPTURE_ALL_DISPLAYS 0 -static double getDictDouble (CFDictionaryRef refDict, CFStringRef key); +//static double getDictDouble (CFDictionaryRef refDict, CFStringRef key); static long getDictLong (CFDictionaryRef refDict, CFStringRef key); - - - -// CarbonEvents we're interested in. -static EventTypeSpec WindowHandlerEventList[] = -{ - // Window-related events - { kEventClassWindow, kEventWindowActivated }, - { kEventClassWindow, kEventWindowDeactivated }, - { kEventClassWindow, kEventWindowShown }, - { kEventClassWindow, kEventWindowHidden }, - { kEventClassWindow, kEventWindowCollapsed }, - { kEventClassWindow, kEventWindowExpanded }, - { kEventClassWindow, kEventWindowGetClickActivation }, - { kEventClassWindow, kEventWindowClose }, - { kEventClassWindow, kEventWindowBoundsChanging }, - { kEventClassWindow, kEventWindowBoundsChanged }, - { kEventClassWindow, kEventWindowGetIdealSize }, - - // Mouse events - { kEventClassMouse, kEventMouseDown }, - { kEventClassMouse, kEventMouseUp }, - { kEventClassMouse, kEventMouseDragged }, - { kEventClassMouse, kEventMouseWheelMoved }, - { kEventClassMouse, kEventMouseMoved }, - - // Keyboard events - // No longer handle raw key down events directly. - // When text input events come in, extract the raw key events from them and process at that point. - // This allows input methods to eat keystrokes the way they're supposed to. -// { kEventClassKeyboard, kEventRawKeyDown }, -// { kEventClassKeyboard, kEventRawKeyRepeat }, - { kEventClassKeyboard, kEventRawKeyUp }, - { kEventClassKeyboard, kEventRawKeyModifiersChanged }, - - // Text input events - { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent }, - { kEventClassTextInput, kEventTextInputUpdateActiveInputArea }, - { kEventClassTextInput, kEventTextInputOffsetToPos }, - { kEventClassTextInput, kEventTextInputPosToOffset }, - { kEventClassTextInput, kEventTextInputShowHideBottomWindow }, - { kEventClassTextInput, kEventTextInputGetSelectedText }, - { kEventClassTextInput, kEventTextInputFilterText }, - - // TSM Document Access events (advanced input method support) - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetLength }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetSelectedRange }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetCharacters }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetFont }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetGlyphInfo }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessLockDocument }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessUnlockDocument } -}; - -static EventTypeSpec GlobalHandlerEventList[] = -{ - // Mouse events - { kEventClassMouse, kEventMouseDown }, - { kEventClassMouse, kEventMouseUp }, - { kEventClassMouse, kEventMouseDragged }, - { kEventClassMouse, kEventMouseWheelMoved }, - { kEventClassMouse, kEventMouseMoved }, - - // Keyboard events - // No longer handle raw key down events directly. - // When text input events come in, extract the raw key events from them and process at that point. - // This allows input methods to eat keystrokes the way they're supposed to. -// { kEventClassKeyboard, kEventRawKeyDown }, -// { kEventClassKeyboard, kEventRawKeyRepeat }, - { kEventClassKeyboard, kEventRawKeyUp }, - { kEventClassKeyboard, kEventRawKeyModifiersChanged }, - - // Text input events - { kEventClassTextInput, kEventTextInputUpdateActiveInputArea }, - { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent }, - { kEventClassTextInput, kEventTextInputOffsetToPos }, - { kEventClassTextInput, kEventTextInputPosToOffset }, - { kEventClassTextInput, kEventTextInputShowHideBottomWindow }, - { kEventClassTextInput, kEventTextInputGetSelectedText }, - { kEventClassTextInput, kEventTextInputFilterText }, - - // TSM Document Access events (advanced input method support) - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetLength }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetSelectedRange }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetCharacters }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetFont }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetGlyphInfo }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessLockDocument }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessUnlockDocument } -}; - -static EventTypeSpec CommandHandlerEventList[] = -{ - { kEventClassCommand, kEventCommandProcess } -}; - // MBW -- HACK ALERT // On the Mac, to put up an OS dialog in full screen mode, we must first switch OUT of full screen mode. // The proper way to do this is to bracket the dialog with calls to beforeDialog() and afterDialog(), but these @@ -204,13 +110,11 @@ static EventTypeSpec CommandHandlerEventList[] = // This assumes that there will be only one object of this class at any time. Hopefully this is true. static LLWindowMacOSX *gWindowImplementation = NULL; - - LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags, BOOL fullscreen, BOOL clearBg, - const S32 vsync_mode, + S32 vsync_setting, BOOL ignore_pixel_depth, U32 fsaa_samples) : LLWindow(NULL, fullscreen, flags) @@ -233,8 +137,6 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, mContext = NULL; mPixelFormat = NULL; mDisplay = CGMainDisplayID(); - mOldDisplayMode = NULL; - mTimer = NULL; mSimulatedRightClick = FALSE; mLastModifiers = 0; mHandsOffEvents = FALSE; @@ -246,70 +148,40 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, mOverrideAspectRatio = 0.f; mMaximized = FALSE; mMinimized = FALSE; - mTSMDocument = NULL; // Just in case. mLanguageTextInputAllowed = FALSE; - mTSMScriptCode = 0; - mTSMLangCode = 0; mPreeditor = NULL; - mRawKeyEvent = NULL; mFSAASamples = fsaa_samples; - mVsyncMode = vsync_mode; mForceRebuild = FALSE; - // For reasons that aren't clear to me, LLTimers seem to be created in the "started" state. - // Since the started state of this one is used to track whether the NMRec has been installed, it wants to start out in the "stopped" state. - mBounceTimer.stop(); - // Get the original aspect ratio of the main device. mOriginalAspectRatio = (double)CGDisplayPixelsWide(mDisplay) / (double)CGDisplayPixelsHigh(mDisplay); // Stash the window title - strcpy((char*)mWindowTitle + 1, title.c_str()); /* Flawfinder: ignore */ - mWindowTitle[0] = title.length(); - - mEventHandlerUPP = NewEventHandlerUPP(staticEventHandler); - mMoveEventCampartorUPP = NewEventComparatorUPP(staticMoveEventComparator); - mGlobalHandlerRef = NULL; - mWindowHandlerRef = NULL; + mWindowTitle = title; + //mWindowTitle[0] = title.length(); mDragOverrideCursor = -1; - // We're not clipping yet - SetRect( &mOldMouseClip, 0, 0, 0, 0 ); - // Set up global event handlers (the fullscreen case needs this) - InstallStandardEventHandler(GetApplicationEventTarget()); + //InstallStandardEventHandler(GetApplicationEventTarget()); // Stash an object pointer for OSMessageBox() gWindowImplementation = this; - // Create the GL context and set it up for windowed or fullscreen, as appropriate. - if(createContext(x, y, width, height, 32, fullscreen, vsync_mode)) + if(createContext(x, y, width, height, 32, fullscreen, vsync_setting)) { if(mWindow != NULL) { - // MBW -- XXX -- I think we can now do this here? - // Constrain the window to the screen it's mostly on, resizing if necessary. - ConstrainWindowToScreen( - mWindow, - kWindowStructureRgn, - kWindowConstrainMayResize | - // kWindowConstrainStandardOptions | - 0, - NULL, - NULL); - - MacShowWindow(mWindow); - BringToFront(mWindow); + makeWindowOrderFront(mWindow); } if (!gGLManager.initGL()) { setupFailure( - "Second Life is unable to run because your video card drivers\n" + "Singularity is unable to run because your video card drivers\n" "are out of date or unsupported. Please make sure you have\n" "the latest video card drivers installed.\n" - "If you continue to receive this message, contact customer service.", + "If you continue to receive this message, contact support.", "Error", OSMB_OK); return; @@ -318,483 +190,452 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, //start with arrow cursor initCursors(); setCursor( UI_CURSOR_ARROW ); + + allowLanguageTextInput(NULL, FALSE); } mCallbacks = callbacks; stop_glerror(); + + } -BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, const S32 vsync_mode) +// These functions are used as wrappers for our internal event handling callbacks. +// It's a good idea to wrap these to avoid reworking more code than we need to within LLWindow. + +bool callKeyUp(NSKeyEventRef event, unsigned short key, unsigned int mask) { - OSStatus err; - BOOL glNeedsInit = FALSE; + mRawKeyEvent = event; + bool retVal = gKeyboard->handleKeyUp(key, mask); + mRawKeyEvent = NULL; + return retVal; +} - if(mGlobalHandlerRef == NULL) +bool callKeyDown(NSKeyEventRef event, unsigned short key, unsigned int mask) +{ + mRawKeyEvent = event; + bool retVal = gKeyboard->handleKeyDown(key, mask); + mRawKeyEvent = NULL; + return retVal; +} + +void callResetKeys() +{ + gKeyboard->resetKeys(); +} + +bool callUnicodeCallback(wchar_t character, unsigned int mask) +{ + NativeKeyEventData eventData; + + memset(&eventData, 0, sizeof(NativeKeyEventData)); + + eventData.mKeyEvent = NativeKeyEventData::KEYCHAR; + eventData.mEventType = 0; + eventData.mEventModifiers = mask; + eventData.mEventKeyCode = 0; + eventData.mEventChars = character; + eventData.mEventUnmodChars = character; + eventData.mEventRepeat = false; + + mRawKeyEvent = &eventData; + + bool result = gWindowImplementation->getCallbacks()->handleUnicodeChar(character, mask); + mRawKeyEvent = NULL; + return result; +} + +void callFocus() +{ + if (gWindowImplementation) { - InstallApplicationEventHandler(mEventHandlerUPP, GetEventTypeCount (CommandHandlerEventList), CommandHandlerEventList, (void*)this, &mGlobalHandlerRef); + gWindowImplementation->getCallbacks()->handleFocus(gWindowImplementation); + } +} + +void callFocusLost() +{ + if (gWindowImplementation) + { + gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation); + } +} + +void callRightMouseDown(float *pos, MASK mask) +{ + if (gWindowImplementation->allowsLanguageInput()) + { + gWindowImplementation->interruptLanguageTextInput(); + } + + LLCoordGL outCoords; + outCoords.mX = ll_round(pos[0]); + outCoords.mY = ll_round(pos[1]); + gWindowImplementation->getCallbacks()->handleRightMouseDown(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); +} + +void callRightMouseUp(float *pos, MASK mask) +{ + if (gWindowImplementation->allowsLanguageInput()) + { + gWindowImplementation->interruptLanguageTextInput(); + } + + LLCoordGL outCoords; + outCoords.mX = ll_round(pos[0]); + outCoords.mY = ll_round(pos[1]); + gWindowImplementation->getCallbacks()->handleRightMouseUp(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); +} + +void callLeftMouseDown(float *pos, MASK mask) +{ + if (gWindowImplementation->allowsLanguageInput()) + { + gWindowImplementation->interruptLanguageTextInput(); + } + + LLCoordGL outCoords; + outCoords.mX = ll_round(pos[0]); + outCoords.mY = ll_round(pos[1]); + gWindowImplementation->getCallbacks()->handleMouseDown(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); +} + +void callLeftMouseUp(float *pos, MASK mask) +{ + if (gWindowImplementation->allowsLanguageInput()) + { + gWindowImplementation->interruptLanguageTextInput(); + } + + LLCoordGL outCoords; + outCoords.mX = ll_round(pos[0]); + outCoords.mY = ll_round(pos[1]); + gWindowImplementation->getCallbacks()->handleMouseUp(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); + +} + +void callDoubleClick(float *pos, MASK mask) +{ + if (gWindowImplementation->allowsLanguageInput()) + { + gWindowImplementation->interruptLanguageTextInput(); + } + + LLCoordGL outCoords; + outCoords.mX = ll_round(pos[0]); + outCoords.mY = ll_round(pos[1]); + gWindowImplementation->getCallbacks()->handleDoubleClick(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); +} + +void callResize(unsigned int width, unsigned int height) +{ + if (gWindowImplementation != NULL) + { + gWindowImplementation->getCallbacks()->handleResize(gWindowImplementation, width, height); + } +} + +void callMouseMoved(float *pos, MASK mask) +{ + LLCoordGL outCoords; + outCoords.mX = ll_round(pos[0]); + outCoords.mY = ll_round(pos[1]); + S32 deltas[2]; + gWindowImplementation->getMouseDeltas(deltas); + outCoords.mX += deltas[0]; + outCoords.mY += deltas[1]; + gWindowImplementation->getCallbacks()->handleMouseMove(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); +} + +void callScrollMoved(float delta) +{ + gWindowImplementation->getCallbacks()->handleScrollWheel(gWindowImplementation, delta); +} + +void callMouseExit() +{ + gWindowImplementation->getCallbacks()->handleMouseLeave(gWindowImplementation); +} + +void callWindowFocus() +{ + if ( gWindowImplementation && gWindowImplementation->getCallbacks() ) + { + gWindowImplementation->getCallbacks()->handleFocus(gWindowImplementation); + // Reset badge count + updateBadge(0); + } + else + { + LL_WARNS("COCOA") << "Window Implementation or callbacks not yet initialized." << LL_ENDL; } + +} + +void callWindowUnfocus() +{ + gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation); +} + +void callWindowHide() +{ + if ( gWindowImplementation && gWindowImplementation->getCallbacks() ) + { + gWindowImplementation->getCallbacks()->handleActivate(gWindowImplementation, false); + } +} + +void callWindowUnhide() +{ + if ( gWindowImplementation && gWindowImplementation->getCallbacks() ) + { + gWindowImplementation->getCallbacks()->handleActivate(gWindowImplementation, true); + } +} + +void callDeltaUpdate(double *delta, MASK mask) +{ + gWindowImplementation->updateMouseDeltas(delta); +} + +void callMiddleMouseDown(float *pos, MASK mask) +{ + LLCoordGL outCoords; + outCoords.mX = ll_round(pos[0]); + outCoords.mY = ll_round(pos[1]); + S32 deltas[2]; + gWindowImplementation->getMouseDeltas(deltas); + outCoords.mX += deltas[0]; + outCoords.mY += deltas[1]; + gWindowImplementation->getCallbacks()->handleMiddleMouseDown(gWindowImplementation, outCoords, mask); +} + +void callMiddleMouseUp(float *pos, MASK mask) +{ + LLCoordGL outCoords; + outCoords.mX = ll_round(pos[0]); + outCoords.mY = ll_round(pos[1]); + S32 deltas[2]; + gWindowImplementation->getMouseDeltas(deltas); + outCoords.mX += deltas[0]; + outCoords.mY += deltas[1]; + gWindowImplementation->getCallbacks()->handleMiddleMouseUp(gWindowImplementation, outCoords, mask); +} + +void callModifier(MASK mask) +{ + gKeyboard->handleModifier(mask); +} + +void callHandleDragEntered(std::string url) +{ + gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_START_TRACKING); +} + +void callHandleDragExited(std::string url) +{ + gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_STOP_TRACKING); +} + +void callHandleDragUpdated(std::string url) +{ + gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_TRACK); +} + +void callHandleDragDropped(std::string url) +{ + gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_DROPPED); +} + +void callQuitHandler() +{ + if (gWindowImplementation) + { + if(gWindowImplementation->getCallbacks()->handleCloseRequest(gWindowImplementation)) + { + gWindowImplementation->getCallbacks()->handleQuit(gWindowImplementation); + } + } +} + +void getPreeditSelectionRange(int *position, int *length) +{ + if (gWindowImplementation->getPreeditor()) + { + gWindowImplementation->getPreeditor()->getSelectionRange(position, length); + } +} + +void getPreeditMarkedRange(int *position, int *length) +{ + if (gWindowImplementation->getPreeditor()) + { + gWindowImplementation->getPreeditor()->getPreeditRange(position, length); + } +} + +void setPreeditMarkedRange(int position, int length) +{ + if (gWindowImplementation->getPreeditor()) + { + gWindowImplementation->getPreeditor()->markAsPreedit(position, length); + } +} + +bool handleUnicodeCharacter(wchar_t c) +{ + bool success = false; + if (gWindowImplementation->getPreeditor()) + { + success = gWindowImplementation->getPreeditor()->handleUnicodeCharHere(c); + } + + return success; +} + +void resetPreedit() +{ + if (gWindowImplementation->getPreeditor()) + { + gWindowImplementation->getPreeditor()->resetPreedit(); + } +} + +// For reasons of convenience, handle IME updates here. +// This largely mirrors the old implementation, only sans the carbon parameters. +void setMarkedText(unsigned short *unitext, unsigned int *replacementRange, long text_len, attributedStringInfo segments) +{ + if (gWindowImplementation->getPreeditor()) + { + LLPreeditor *preeditor = gWindowImplementation->getPreeditor(); + preeditor->resetPreedit(); + // This should be a viable replacement for the kEventParamTextInputSendReplaceRange parameter. + if (replacementRange[0] < replacementRange[1]) + { + const LLWString& text = preeditor->getPreeditString(); + const S32 location = wstring_wstring_length_from_utf16_length(text, 0, replacementRange[0]); + const S32 length = wstring_wstring_length_from_utf16_length(text, location, replacementRange[1]); + preeditor->markAsPreedit(location, length); + } + + LLWString fix_str = utf16str_to_wstring(llutf16string(unitext, text_len)); + + S32 caret_position = fix_str.length(); + + preeditor->updatePreedit(fix_str, segments.seg_lengths, segments.seg_standouts, caret_position); + } +} + +void getPreeditLocation(float *location, unsigned int length) +{ + if (gWindowImplementation->getPreeditor()) + { + LLPreeditor *preeditor = gWindowImplementation->getPreeditor(); + LLCoordGL coord; + LLCoordScreen screen; + LLRect rect; + + preeditor->getPreeditLocation(length, &coord, &rect, NULL); + + float c[4] = {static_cast(coord.mX), + static_cast(coord.mY), 0, 0}; + + convertRectToScreen(gWindowImplementation->getWindow(), c); + + location[0] = c[0]; + location[1] = c[1]; + } +} + +void LLWindowMacOSX::updateMouseDeltas(double* deltas) +{ + if (mCursorDecoupled) + { + mCursorLastEventDeltaX = ll_round(deltas[0]); + mCursorLastEventDeltaY = ll_round(-deltas[1]); + + if (mCursorIgnoreNextDelta) + { + mCursorLastEventDeltaX = 0; + mCursorLastEventDeltaY = 0; + mCursorIgnoreNextDelta = FALSE; + } + } else { + mCursorLastEventDeltaX = 0; + mCursorLastEventDeltaY = 0; + } +} + +void LLWindowMacOSX::getMouseDeltas(S32* delta) +{ + delta[0] = mCursorLastEventDeltaX; + delta[1] = mCursorLastEventDeltaY; +} + +BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, S32 vsync_setting) +{ mFullscreen = fullscreen; - - if (mFullscreen && (mOldDisplayMode == NULL)) + + if (mWindow == NULL) { - LL_INFOS("Window") << "createContext: setting up fullscreen " << width << "x" << height << LL_ENDL; - - // NOTE: The refresh rate will be REPORTED AS 0 for many DVI and notebook displays. Plan accordingly. - double refresh = getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate); - - // If the requested width or height is 0, find the best default for the monitor. - if((width == 0) || (height == 0)) - { - // Scan through the list of modes, looking for one which has: - // height between 700 and 800 - // aspect ratio closest to the user's original mode - S32 resolutionCount = 0; - LLWindowResolution *resolutionList = getSupportedResolutions(resolutionCount); - - if(resolutionList != NULL) - { - F32 closestAspect = 0; - U32 closestHeight = 0; - U32 closestWidth = 0; - int i; - - LL_DEBUGS("Window") << "createContext: searching for a display mode, original aspect is " << mOriginalAspectRatio << LL_ENDL; - - for(i=0; i < resolutionCount; i++) - { - F32 aspect = (F32)resolutionList[i].mWidth / (F32)resolutionList[i].mHeight; - - LL_DEBUGS("Window") << "createContext: width " << resolutionList[i].mWidth << " height " << resolutionList[i].mHeight << " aspect " << aspect << LL_ENDL; - - if( (resolutionList[i].mHeight >= 700) && (resolutionList[i].mHeight <= 800) && - (fabs(aspect - mOriginalAspectRatio) < fabs(closestAspect - mOriginalAspectRatio))) - { - LL_DEBUGS("Window") << " (new closest mode) " << LL_ENDL; - - // This is the closest mode we've seen yet. - closestWidth = resolutionList[i].mWidth; - closestHeight = resolutionList[i].mHeight; - closestAspect = aspect; - } - } - - width = closestWidth; - height = closestHeight; - } - } - - if((width == 0) || (height == 0)) - { - // Mode search failed for some reason. Use the old-school default. - width = 1024; - height = 768; - } - - if (true) - { - // Fullscreen support - CFDictionaryRef refDisplayMode = 0; - boolean_t exactMatch = false; - -#if CAPTURE_ALL_DISPLAYS - // Capture all displays (may want to do this for final build) - CGCaptureAllDisplays (); -#else - // Capture only the main display (useful for debugging) - CGDisplayCapture (mDisplay); -#endif - - // Switch the display to the desired resolution and refresh - refDisplayMode = CGDisplayBestModeForParametersAndRefreshRate( - mDisplay, - BITS_PER_PIXEL, - width, - height, - refresh, - &exactMatch); - - if (refDisplayMode) - { - LL_DEBUGS("Window") << "createContext: switching display resolution" << LL_ENDL; - mOldDisplayMode = CGDisplayCurrentMode (mDisplay); - CGDisplaySwitchToMode (mDisplay, refDisplayMode); - // CFRelease(refDisplayMode); - - AddEventTypesToHandler(mGlobalHandlerRef, GetEventTypeCount (GlobalHandlerEventList), GlobalHandlerEventList); - } - - - mFullscreen = TRUE; - mFullscreenWidth = CGDisplayPixelsWide(mDisplay); - mFullscreenHeight = CGDisplayPixelsHigh(mDisplay); - mFullscreenBits = CGDisplayBitsPerPixel(mDisplay); - mFullscreenRefresh = llround(getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate)); - - LL_INFOS("Window") << "Running at " << mFullscreenWidth - << "x" << mFullscreenHeight - << "x" << mFullscreenBits - << " @ " << mFullscreenRefresh - << LL_ENDL; - } - else - { - // No fullscreen support - mFullscreen = FALSE; - mFullscreenWidth = -1; - mFullscreenHeight = -1; - mFullscreenBits = -1; - mFullscreenRefresh = -1; - - std::string error= llformat("Unable to run fullscreen at %d x %d.\nRunning in window.", width, height); - OSMessageBox(error, "Error", OSMB_OK); - } + mWindow = getMainAppWindow(); } - if(!mFullscreen && (mWindow == NULL)) + // Disable vertical sync for swap + bool vsync_enabled; + GLint frames_per_swap; + switch (vsync_setting) { - //int displayWidth = CGDisplayPixelsWide(mDisplay); - //int displayHeight = CGDisplayPixelsHigh(mDisplay); - //const int menuBarPlusTitleBar = 44; // Ugly magic number. - - LL_DEBUGS("Window") << "createContext: creating window" << LL_ENDL; - - mPreviousWindowRect.left = (long) x; - mPreviousWindowRect.right = (long) x + width; - mPreviousWindowRect.top = (long) y; - mPreviousWindowRect.bottom = (long) y + height; - - //----------------------------------------------------------------------- - // Create the window - //----------------------------------------------------------------------- - mWindow = NewCWindow( - NULL, - &mPreviousWindowRect, - mWindowTitle, - false, // Create the window invisible. Whoever calls createContext() should show it after any moving/resizing. - // noGrowDocProc, // Window with no grow box and no zoom box - zoomDocProc, // Window with a grow box and a zoom box - // zoomNoGrow, // Window with a zoom box but no grow box - kFirstWindowOfClass, - true, - (long)this); - - if (!mWindow) - { - setupFailure("Window creation error", "Error", OSMB_OK); - return FALSE; - } - - // Turn on live resize. - // For this to work correctly, we need to be able to call LLViewerWindow::draw from - // the event handler for kEventWindowBoundsChanged. It's not clear that we have access from here. - // err = ChangeWindowAttributes(mWindow, kWindowLiveResizeAttribute, 0); - - // Set up window event handlers (some window-related events ONLY go to window handlers.) - InstallStandardEventHandler(GetWindowEventTarget(mWindow)); - InstallWindowEventHandler(mWindow, mEventHandlerUPP, GetEventTypeCount (WindowHandlerEventList), WindowHandlerEventList, (void*)this, &mWindowHandlerRef); // add event handler -#if LL_OS_DRAGDROP_ENABLED - InstallTrackingHandler( dragTrackingHandler, mWindow, (void*)this ); - InstallReceiveHandler( dragReceiveHandler, mWindow, (void*)this ); -#endif // LL_OS_DRAGDROP_ENABLED + //default: + case 0: //E_VSYNC_DISABLED: + { + LL_INFOS("Window") << "Disabling vertical sync" << LL_ENDL; + vsync_enabled = false; + frames_per_swap = 0; + break; } - + case -1: //E_VSYNC_ADAPTIVE: + default: //case E_VSYNC_NORMAL: { - // Create and initialize our TSM document for language text input. - // If an error occured, we can do nothing better than simply ignore it. - // mTSMDocument will be kept NULL in case. - if (mTSMDocument) - { - DeactivateTSMDocument(mTSMDocument); - DeleteTSMDocument(mTSMDocument); - mTSMDocument = NULL; - } - static InterfaceTypeList types = { kUnicodeDocument }; - err = NewTSMDocument(1, types, &mTSMDocument, 0); - if (err != noErr) - { - LL_WARNS("Window") << "createContext: couldn't create a TSMDocument (" << err << ")" << LL_ENDL; - } - if (mTSMDocument) - { - ActivateTSMDocument(mTSMDocument); - allowLanguageTextInput(NULL, FALSE); - } + LL_INFOS("Window") << "Enabling vertical sync" << LL_ENDL; + vsync_enabled = true; + frames_per_swap = 1; + break; + } } if(mContext == NULL) { - AGLRendererInfo rendererInfo = NULL; - - //----------------------------------------------------------------------- - // Create GL drawing context - //----------------------------------------------------------------------- - - if(mPixelFormat == NULL) - { - if(mFullscreen) - { - GLint fullscreenAttrib[] = - { - AGL_RGBA, - AGL_FULLSCREEN, - AGL_NO_RECOVERY, - AGL_SAMPLE_BUFFERS_ARB, mFSAASamples > 0 ? 1 : 0, - AGL_SAMPLES_ARB, mFSAASamples, - AGL_DOUBLEBUFFER, - AGL_CLOSEST_POLICY, - AGL_ACCELERATED, - AGL_RED_SIZE, 8, - AGL_GREEN_SIZE, 8, - AGL_BLUE_SIZE, 8, - AGL_ALPHA_SIZE, 8, - AGL_DEPTH_SIZE, 24, - AGL_STENCIL_SIZE, 8, - AGL_NONE - }; - - LL_DEBUGS("Window") << "createContext: creating fullscreen pixelformat" << LL_ENDL; - - GDHandle gdhDisplay = NULL; - err = DMGetGDeviceByDisplayID ((DisplayIDType)mDisplay, &gdhDisplay, false); - - mPixelFormat = aglChoosePixelFormat(&gdhDisplay, 1, fullscreenAttrib); - rendererInfo = aglQueryRendererInfo(&gdhDisplay, 1); - } - else - { - // NOTE from Leslie: - // - // AGL_NO_RECOVERY, when combined with AGL_ACCELERATED prevents software rendering - // fallback which means we won't hvae shaders that compile and link but then don't - // work. The drawback is that our shader compilation will be a bit more finicky though. - - GLint windowedAttrib[] = - { - AGL_RGBA, - AGL_NO_RECOVERY, - AGL_DOUBLEBUFFER, - AGL_CLOSEST_POLICY, - AGL_ACCELERATED, - AGL_SAMPLE_BUFFERS_ARB, mFSAASamples > 0 ? 1 : 0, - AGL_SAMPLES_ARB, mFSAASamples, - AGL_RED_SIZE, 8, - AGL_GREEN_SIZE, 8, - AGL_BLUE_SIZE, 8, - AGL_ALPHA_SIZE, 8, - AGL_DEPTH_SIZE, 24, - AGL_STENCIL_SIZE, 8, - AGL_NONE - }; - - LL_DEBUGS("Window") << "createContext: creating windowed pixelformat" << LL_ENDL; - - mPixelFormat = aglChoosePixelFormat(NULL, 0, windowedAttrib); - - GDHandle gdhDisplay = GetMainDevice(); - rendererInfo = aglQueryRendererInfo(&gdhDisplay, 1); - } - - // May want to get the real error text like this: - // (char *) aglErrorString(aglGetError()); - - if(aglGetError() != AGL_NO_ERROR) - { - setupFailure("Can't find suitable pixel format", "Error", OSMB_OK); - return FALSE; - } - } - - if(mPixelFormat) - { - LL_DEBUGS("Window") << "createContext: creating GL context" << LL_ENDL; - mContext = aglCreateContext(mPixelFormat, NULL); - } - - if(mContext == NULL) - { - setupFailure("Can't make GL context", "Error", OSMB_OK); - return FALSE; - } - - gGLManager.mVRAM = 0; - - if(rendererInfo != NULL) - { - GLint result; - - if(aglDescribeRenderer(rendererInfo, AGL_VIDEO_MEMORY, &result)) - { - // LL_INFOS() << "createContext: aglDescribeRenderer(AGL_VIDEO_MEMORY) returned " << result << LL_ENDL; - gGLManager.mVRAM = result / (1024 * 1024); - } - else - { - // LL_INFOS() << "createContext: aglDescribeRenderer(AGL_VIDEO_MEMORY) failed." << LL_ENDL; - } - - // This could be useful at some point, if it takes into account the memory already used by screen buffers, etc... - if(aglDescribeRenderer(rendererInfo, AGL_TEXTURE_MEMORY, &result)) - { - // LL_INFOS() << "createContext: aglDescribeRenderer(AGL_TEXTURE_MEMORY) returned " << result << LL_ENDL; - } - else - { - // LL_INFOS() << "createContext: aglDescribeRenderer(AGL_TEXTURE_MEMORY) failed." << LL_ENDL; - } - - aglDestroyRendererInfo(rendererInfo); - } - - // Since we just created the context, it needs to be set up. - glNeedsInit = TRUE; + // Our OpenGL view is already defined within SecondLife.xib. + // Get the view instead. + mGLView = createOpenGLView(mWindow, mFSAASamples, vsync_enabled); + mContext = getCGLContextObj(mGLView); + + gGLManager.mVRAM = getVramSize(mGLView); } - + + // This sets up our view to recieve text from our non-inline text input window. + setupInputWindow(mWindow, mGLView); + // Hook up the context to a drawable - if (mFullscreen && (mOldDisplayMode != NULL)) - { - // We successfully captured the display. Use a fullscreen drawable - - LL_DEBUGS("Window") << "createContext: attaching fullscreen drawable" << LL_ENDL; - -#if CAPTURE_ALL_DISPLAYS - // Capture all displays (may want to do this for final build) - aglDisable (mContext, AGL_FS_CAPTURE_SINGLE); -#else - // Capture only the main display (useful for debugging) - aglEnable (mContext, AGL_FS_CAPTURE_SINGLE); -#endif - - if (!aglSetFullScreen (mContext, 0, 0, 0, 0)) - { - setupFailure("Can't set GL fullscreen", "Error", OSMB_OK); - return FALSE; - } - } - else if(!mFullscreen && (mWindow != NULL)) - { - LL_DEBUGS("Window") << "createContext: attaching windowed drawable" << LL_ENDL; - - // We created a window. Use it as the drawable. - if(!aglSetDrawable(mContext, GetWindowPort (mWindow))) - { - setupFailure("Can't set GL drawable", "Error", OSMB_OK); - return FALSE; - } - } - else - { - setupFailure("Can't get fullscreen or windowed drawable.", "Error", OSMB_OK); - return FALSE; - } if(mContext != NULL) { - LL_DEBUGS("Window") << "createContext: setting current context" << LL_ENDL; - - if (!aglSetCurrentContext(mContext)) + + + CGLError err = CGLSetCurrentContext(mContext); + if (err != kCGLNoError) { setupFailure("Can't activate GL rendering context", "Error", OSMB_OK); return FALSE; } } - if(glNeedsInit) - { - // Check for some explicitly unsupported cards. - const char* RENDERER = (const char*) glGetString(GL_RENDERER); - - const char* CARD_LIST[] = - { "RAGE 128", - "RIVA TNT2", - "Intel 810", - "3Dfx/Voodoo3", - "Radeon 7000", - "Radeon 7200", - "Radeon 7500", - "Radeon DDR", - "Radeon VE", - "GDI Generic" }; - const S32 CARD_COUNT = LL_ARRAY_SIZE(CARD_LIST); - - // Future candidates: - // ProSavage/Twister - // SuperSavage - - S32 i; - for (i = 0; i < CARD_COUNT; i++) - { - if (check_for_card(RENDERER, CARD_LIST[i])) - { - close(); - return FALSE; - } - } - } - - GLint colorBits, alphaBits, depthBits, stencilBits; - - if( !aglDescribePixelFormat(mPixelFormat, AGL_BUFFER_SIZE, &colorBits) || - !aglDescribePixelFormat(mPixelFormat, AGL_ALPHA_SIZE, &alphaBits) || - !aglDescribePixelFormat(mPixelFormat, AGL_DEPTH_SIZE, &depthBits) || - !aglDescribePixelFormat(mPixelFormat, AGL_STENCIL_SIZE, &stencilBits)) - { - close(); - setupFailure("Can't get pixel format description", "Error", OSMB_OK); - return FALSE; - } - - LL_INFOS("GLInit") << "GL buffer: Color Bits " << S32(colorBits) - << " Alpha Bits " << S32(alphaBits) - << " Depth Bits " << S32(depthBits) - << " Stencil Bits" << S32(stencilBits) - << LL_ENDL; - - if (colorBits < 32) - { - close(); - setupFailure( - "Second Life requires True Color (32-bit) to run in a window.\n" - "Please go to Control Panels -> Display -> Settings and\n" - "set the screen to 32-bit color.\n" - "Alternately, if you choose to run fullscreen, Second Life\n" - "will automatically adjust the screen each time it runs.", - "Error", - OSMB_OK); - return FALSE; - } - - if (alphaBits < 8) - { - close(); - setupFailure( - "Second Life is unable to run because it can't get an 8 bit alpha\n" - "channel. Usually this is due to video card driver issues.\n" - "Please make sure you have the latest video card drivers installed.\n" - "Also be sure your monitor is set to True Color (32-bit) in\n" - "Control Panels -> Display -> Settings.\n" - "If you continue to receive this message, contact customer service.", - "Error", - OSMB_OK); - return FALSE; - } - - // Disable vertical sync for swap - GLint frames_per_swap = 0; - if (vsync_mode != 1) - { - LL_DEBUGS("GLInit") << "Disabling vertical sync" << LL_ENDL; - frames_per_swap = 0; - } - else - { - LL_DEBUGS("GLinit") << "Keeping vertical sync" << LL_ENDL; - frames_per_swap = 1; - } - aglSetInteger(mContext, AGL_SWAP_INTERVAL, &frames_per_swap); + CGLSetParameter(mContext, kCGLCPSwapInterval, &frames_per_swap); //enable multi-threaded OpenGL - if (sUseMultGL) + if (gUseMultGL) { CGLError cgl_err; CGLContextObj ctx = CGLGetCurrentContext(); @@ -810,109 +651,17 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits LL_DEBUGS("GLInit") << "Multi-threaded OpenGL enabled." << LL_ENDL; } } - - // Don't need to get the current gamma, since there's a call that restores it to the system defaults. + makeFirstResponder(mWindow, mGLView); + return TRUE; } -// changing fullscreen resolution, or switching between windowed and fullscreen mode. +// We only support OS X 10.7's fullscreen app mode which is literally a full screen window that fills a virtual desktop. +// This makes this method obsolete. BOOL LLWindowMacOSX::switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, const LLCoordScreen * const posp) { - BOOL needsRebuild = FALSE; - BOOL result = true; - - if(fullscreen) - { - if(mFullscreen) - { - // Switching resolutions in fullscreen mode. Don't need to rebuild for this. - // Fullscreen support - CFDictionaryRef refDisplayMode = 0; - boolean_t exactMatch = false; - - // Switch the display to the desired resolution and refresh - refDisplayMode = CGDisplayBestModeForParametersAndRefreshRate( - mDisplay, - BITS_PER_PIXEL, - size.mX, - size.mY, - getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate), - &exactMatch); - - if (refDisplayMode) - { - CGDisplaySwitchToMode (mDisplay, refDisplayMode); - // CFRelease(refDisplayMode); - } - - mFullscreenWidth = CGDisplayPixelsWide(mDisplay); - mFullscreenHeight = CGDisplayPixelsHigh(mDisplay); - mFullscreenBits = CGDisplayBitsPerPixel(mDisplay); - mFullscreenRefresh = llround(getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate)); - - LL_INFOS("Window") << "Switched resolution to " << mFullscreenWidth - << "x" << mFullscreenHeight - << "x" << mFullscreenBits - << " @ " << mFullscreenRefresh - << LL_ENDL; - - // Update the GL context to the new screen size - if (!aglUpdateContext(mContext)) - { - setupFailure("Can't set GL fullscreen", "Error", OSMB_OK); - result = FALSE; - } - } - else - { - // Switching from windowed to fullscreen - needsRebuild = TRUE; - } - } - else - { - if(mFullscreen) - { - // Switching from fullscreen to windowed - needsRebuild = TRUE; - } - else - { - // Windowed to windowed -- not sure why we would be called like this. Just change the window size. - // The bounds changed event handler will do the rest. - if(mWindow != NULL) - { - ::SizeWindow(mWindow, size.mX, size.mY, true); - } - } - } - - stop_glerror(); - if(needsRebuild || mForceRebuild) - { - mForceRebuild = FALSE; - destroyContext(); - result = createContext(0, 0, size.mX, size.mY, 0, fullscreen, vsync_mode); - if (result) - { - if(mWindow != NULL) - { - MacShowWindow(mWindow); - BringToFront(mWindow); - } - - llverify(gGLManager.initGL()); - - //start with arrow cursor - initCursors(); - setCursor( UI_CURSOR_ARROW ); - } - } - - stop_glerror(); - - return result; + return FALSE; } void LLWindowMacOSX::destroyContext() @@ -926,32 +675,7 @@ void LLWindowMacOSX::destroyContext() if(mContext != NULL) { LL_DEBUGS("Window") << "destroyContext: unhooking drawable " << LL_ENDL; - - aglSetCurrentContext (NULL); - aglSetDrawable(mContext, NULL); - } - - // Make sure the display resolution gets restored - if(mOldDisplayMode != NULL) - { - LL_DEBUGS("Window") << "destroyContext: restoring display resolution " << LL_ENDL; - - CGDisplaySwitchToMode (mDisplay, mOldDisplayMode); - -#if CAPTURE_ALL_DISPLAYS - // Uncapture all displays (may want to do this for final build) - CGReleaseAllDisplays (); -#else - // Uncapture only the main display (useful for debugging) - CGDisplayRelease (mDisplay); -#endif - - // CFRelease(mOldDisplayMode); - - mOldDisplayMode = NULL; - - // Remove the global event handlers the fullscreen case needed - RemoveEventTypesFromHandler(mGlobalHandlerRef, GetEventTypeCount (GlobalHandlerEventList), GlobalHandlerEventList); + CGLSetCurrentContext(NULL); } // Clean up remaining GL state before blowing away window @@ -960,49 +684,29 @@ void LLWindowMacOSX::destroyContext() // Clean up the pixel format if(mPixelFormat != NULL) { - LL_DEBUGS("Window") << "destroyContext: destroying pixel format " << LL_ENDL; - aglDestroyPixelFormat(mPixelFormat); + CGLDestroyPixelFormat(mPixelFormat); mPixelFormat = NULL; } - // Remove any Carbon Event handlers we installed - if(mGlobalHandlerRef != NULL) + // Destroy our LLOpenGLView + if(mGLView != NULL) { - LL_DEBUGS("Window") << "destroyContext: removing global event handler" << LL_ENDL; - RemoveEventHandler(mGlobalHandlerRef); - mGlobalHandlerRef = NULL; + removeGLView(mGLView); + mGLView = NULL; } - - if(mWindowHandlerRef != NULL) - { - LL_DEBUGS("Window") << "destroyContext: removing window event handler" << LL_ENDL; - RemoveEventHandler(mWindowHandlerRef); - mWindowHandlerRef = NULL; - } - - // Cleanup any TSM document we created. - if(mTSMDocument != NULL) - { - LL_DEBUGS("Window") << "destroyContext: deleting TSM document" << LL_ENDL; - DeactivateTSMDocument(mTSMDocument); - DeleteTSMDocument(mTSMDocument); - mTSMDocument = NULL; - } - - // Close the window - if(mWindow != NULL) - { - LL_DEBUGS("Window") << "destroyContext: disposing window" << LL_ENDL; - DisposeWindow(mWindow); - mWindow = NULL; - } - + // Clean up the GL context if(mContext != NULL) { - LL_DEBUGS("Window") << "destroyContext: destroying GL context" << LL_ENDL; - aglDestroyContext(mContext); - mContext = NULL; + CGLDestroyContext(mContext); + } + + // Close the window + if(mWindow != NULL) + { + NSWindowRef dead_window = mWindow; + mWindow = NULL; + closeWindow(dead_window); } } @@ -1021,19 +725,13 @@ LLWindowMacOSX::~LLWindowMacOSX() } -void LLWindowMacOSX::show() +void LLWindowMacOSX::show(bool) { - if(IsWindowCollapsed(mWindow)) - CollapseWindow(mWindow, false); - - MacShowWindow(mWindow); - BringToFront(mWindow); } void LLWindowMacOSX::hide() { setMouseClipping(FALSE); - HideWindow(mWindow); } //virtual @@ -1041,7 +739,6 @@ void LLWindowMacOSX::minimize() { setMouseClipping(FALSE); showCursor(); - CollapseWindow(mWindow, true); } //virtual @@ -1070,7 +767,7 @@ void LLWindowMacOSX::close() BOOL LLWindowMacOSX::isValid() { - if(mFullscreen) + if (mFullscreen) { return(TRUE); } @@ -1082,12 +779,12 @@ BOOL LLWindowMacOSX::getVisible() { BOOL result = FALSE; - if(mFullscreen) + if (mFullscreen) { result = TRUE; - }if (mWindow) + } + if (mWindow) { - if(MacIsWindowVisible(mWindow)) result = TRUE; } @@ -1108,7 +805,6 @@ BOOL LLWindowMacOSX::maximize() { if (mWindow && !mMaximized) { - ZoomWindow(mWindow, inContent, true); } return mMaximized; @@ -1121,60 +817,15 @@ BOOL LLWindowMacOSX::getFullscreen() void LLWindowMacOSX::gatherInput() { - // stop bouncing icon after fixed period of time - if (mBounceTimer.getStarted() && mBounceTimer.getElapsedTimeF32() > mBounceTime) - { - stopDockTileBounce(); - } - - // Use the old-school version so we get AppleEvent handler dispatch and menuselect handling. - // Anything that has an event handler will get processed inside WaitNextEvent, so we only need to handle - // the odd stuff here. - EventRecord evt; - while(WaitNextEvent(everyEvent, &evt, 0, NULL)) - { - // printf("WaitNextEvent returned true, event is %d.\n", evt.what); - switch(evt.what) - { - case mouseDown: - { - short part; - WindowRef window; - long selectResult; - part = FindWindow(evt.where, &window); - switch ( part ) - { - case inMenuBar: - selectResult = MenuSelect(evt.where); - - HiliteMenu(0); - break; - } - } - break; - - case kHighLevelEvent: - AEProcessAppleEvent (&evt); - break; - - case updateEvt: - // We shouldn't be getting these regularly (since our window will be buffered), but we need to handle them correctly... - BeginUpdate((WindowRef)evt.message); - EndUpdate((WindowRef)evt.message); - break; - - } - } - updateCursor(); } BOOL LLWindowMacOSX::getPosition(LLCoordScreen *position) { - Rect window_rect; - OSStatus err = -1; + float rect[4]; + S32 err = -1; - if(mFullscreen) + if (mFullscreen) { position->mX = 0; position->mY = 0; @@ -1182,10 +833,10 @@ BOOL LLWindowMacOSX::getPosition(LLCoordScreen *position) } else if(mWindow) { - err = GetWindowBounds(mWindow, kWindowContentRgn, &window_rect); + getContentViewBounds(mWindow, rect); - position->mX = window_rect.left; - position->mY = window_rect.top; + position->mX = rect[0]; + position->mY = rect[1]; } else { @@ -1197,10 +848,10 @@ BOOL LLWindowMacOSX::getPosition(LLCoordScreen *position) BOOL LLWindowMacOSX::getSize(LLCoordScreen *size) { - Rect window_rect; - OSStatus err = -1; + float rect[4]; + S32 err = -1; - if(mFullscreen) + if (mFullscreen) { size->mX = mFullscreenWidth; size->mY = mFullscreenHeight; @@ -1208,10 +859,10 @@ BOOL LLWindowMacOSX::getSize(LLCoordScreen *size) } else if(mWindow) { - err = GetWindowBounds(mWindow, kWindowContentRgn, &window_rect); + getScaledContentViewBounds(mWindow, mGLView, rect); - size->mX = window_rect.right - window_rect.left; - size->mY = window_rect.bottom - window_rect.top; + size->mX = rect[2]; + size->mY = rect[3]; } else { @@ -1223,10 +874,10 @@ BOOL LLWindowMacOSX::getSize(LLCoordScreen *size) BOOL LLWindowMacOSX::getSize(LLCoordWindow *size) { - Rect window_rect; - OSStatus err = -1; - - if(mFullscreen) + float rect[4]; + S32 err = -1; + + if (mFullscreen) { size->mX = mFullscreenWidth; size->mY = mFullscreenHeight; @@ -1234,72 +885,69 @@ BOOL LLWindowMacOSX::getSize(LLCoordWindow *size) } else if(mWindow) { - err = GetWindowBounds(mWindow, kWindowContentRgn, &window_rect); - - size->mX = window_rect.right - window_rect.left; - size->mY = window_rect.bottom - window_rect.top; + getScaledContentViewBounds(mWindow, mGLView, rect); + + size->mX = rect[2]; + size->mY = rect[3]; } else { LL_ERRS() << "LLWindowMacOSX::getPosition(): no window and not fullscreen!" << LL_ENDL; } - + return (err == noErr); } -BOOL LLWindowMacOSX::setPosition(const LLCoordScreen position) +BOOL LLWindowMacOSX::setPosition(LLCoordScreen position) { if(mWindow) { - MacMoveWindow(mWindow, position.mX, position.mY, false); + float pos[2] = {static_cast(position.mX), + static_cast(position.mY)}; + setWindowPos(mWindow, pos); } return TRUE; } -BOOL LLWindowMacOSX::setSizeImpl(const LLCoordScreen size) +BOOL LLWindowMacOSX::setSizeImpl(LLCoordScreen size) { if(mWindow) { - SizeWindow(mWindow, size.mX, size.mY, true); + LLCoordWindow to; + convertCoords(size, &to); + setWindowSize(mWindow, to.mX, to.mY); + return TRUE; } - return TRUE; + return FALSE; } -BOOL LLWindowMacOSX::setSizeImpl(const LLCoordWindow size) +BOOL LLWindowMacOSX::setSizeImpl(LLCoordWindow size) { - Rect client_rect; if (mWindow) { - OSStatus err = GetWindowBounds(mWindow, kWindowContentRgn, &client_rect); - if (err == noErr) - { - client_rect.right = client_rect.left + size.mX; - client_rect.bottom = client_rect.top + size.mY; - err = SetWindowBounds(mWindow, kWindowContentRgn, &client_rect); - } - if (err == noErr) - { - return TRUE; - } - else - { - LL_INFOS() << "Error setting size" << err << LL_ENDL; - return FALSE; - } + const int titlePadding = 22; + setWindowSize(mWindow, size.mX, size.mY + titlePadding); + return TRUE; } + return FALSE; } void LLWindowMacOSX::swapBuffers() { - aglSwapBuffers(mContext); + CGLFlushDrawable(mContext); +} + +void LLWindowMacOSX::restoreGLContext() +{ + CGLSetCurrentContext(mContext); } F32 LLWindowMacOSX::getGamma() { - F32 result = 1.8; // Default to something sane + F32 result = 2.2; // Default to something sane CGGammaValue redMin; CGGammaValue redMax; @@ -1342,16 +990,6 @@ void LLWindowMacOSX::setFSAASamples(const U32 samples) mForceRebuild = TRUE; } -S32 LLWindowMacOSX::getVsyncMode() -{ - return mVsyncMode; -} -void LLWindowMacOSX::setVsyncMode(const S32 vsync_mode) -{ - mVsyncMode = vsync_mode; - mForceRebuild = TRUE; -} - BOOL LLWindowMacOSX::restoreGamma() { CGDisplayRestoreColorSyncSettings(); @@ -1431,7 +1069,7 @@ void LLWindowMacOSX::setMouseClipping( BOOL b ) adjustCursorDecouple(); } -BOOL LLWindowMacOSX::setCursorPosition(const LLCoordWindow position) +BOOL LLWindowMacOSX::setCursorPosition(LLCoordWindow position) { BOOL result = FALSE; LLCoordScreen screen_pos; @@ -1448,11 +1086,13 @@ BOOL LLWindowMacOSX::setCursorPosition(const LLCoordWindow position) newPosition.x = screen_pos.mX; newPosition.y = screen_pos.mY; - CGSetLocalEventsSuppressionInterval(0.0); + CGEventSourceRef src = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); + CGEventSourceSetLocalEventsSuppressionInterval(src, 0.0); if(CGWarpMouseCursorPosition(newPosition) == noErr) { result = TRUE; } + CFRelease(src); // Under certain circumstances, this will trigger us to decouple the cursor. adjustCursorDecouple(true); @@ -1465,39 +1105,15 @@ BOOL LLWindowMacOSX::setCursorPosition(const LLCoordWindow position) return result; } -static void fixOrigin(void) -{ - GrafPtr port; - Rect portrect; - - ::GetPort(&port); - ::GetPortBounds(port, &portrect); - if((portrect.left != 0) || (portrect.top != 0)) - { - // Mozilla sometimes changes our port origin. - ::SetOrigin(0,0); - } -} - BOOL LLWindowMacOSX::getCursorPosition(LLCoordWindow *position) { - Point cursor_point; + float cursor_point[2]; LLCoordScreen screen_pos; - GrafPtr save; if(mWindow == NULL) return FALSE; - - ::GetPort(&save); - ::SetPort(GetWindowPort(mWindow)); - fixOrigin(); - - // gets the mouse location in local coordinates - ::GetMouse(&cursor_point); - -// LL_DEBUGS() << "getCursorPosition(): cursor is at " << cursor_point.h << ", " << cursor_point.v << " port origin: " << portrect.left << ", " << portrect.top << LL_ENDL; - - ::SetPort(save); + + getCursorPos(mWindow, cursor_point); if(mCursorDecoupled) { @@ -1510,12 +1126,12 @@ BOOL LLWindowMacOSX::getCursorPosition(LLCoordWindow *position) // CGGetLastMouseDelta may behave strangely when the cursor's first captured. // Stash in the event handler instead. - cursor_point.h += mCursorLastEventDeltaX; - cursor_point.v += mCursorLastEventDeltaY; + cursor_point[0] += mCursorLastEventDeltaX; + cursor_point[1] += mCursorLastEventDeltaY; } - - position->mX = cursor_point.h; - position->mY = cursor_point.v; + float scale = getScaleFactor(); + position->mX = cursor_point[0] * scale; + position->mY = cursor_point[1] * scale; return TRUE; } @@ -1532,7 +1148,6 @@ void LLWindowMacOSX::adjustCursorDecouple(bool warpingMouse) // LL_INFOS() << "adjustCursorDecouple: decoupling cursor" << LL_ENDL; CGAssociateMouseAndMouseCursorPosition(false); mCursorDecoupled = true; - FlushSpecificEventsFromQueue(GetCurrentEventQueue(), mMoveEventCampartorUPP, NULL); mCursorIgnoreNextDelta = TRUE; } } @@ -1579,183 +1194,56 @@ F32 LLWindowMacOSX::getPixelAspectRatio() // MBW -- XXX -- There's got to be a better way than this. Find it, please... +// Since we're no longer supporting the "typical" fullscreen mode with CGL or NSOpenGL anymore, these are unnecessary. -Geenz void LLWindowMacOSX::beforeDialog() { - if(mFullscreen) - { - -#if CAPTURE_ALL_DISPLAYS - // Uncapture all displays (may want to do this for final build) - CGReleaseAllDisplays (); -#else - // Uncapture only the main display (useful for debugging) - CGDisplayRelease (mDisplay); -#endif - // kDocumentWindowClass - // kMovableModalWindowClass - // kAllWindowClasses - - // GLint order = 0; - // aglSetInteger(mContext, AGL_ORDER_CONTEXT_TO_FRONT, &order); - aglSetDrawable(mContext, NULL); - // GetWindowGroupLevel(GetWindowGroupOfClass(kAllWindowClasses), &oldWindowLevel); - // SetWindowGroupLevel(GetWindowGroupOfClass(kAllWindowClasses), CGShieldingWindowLevel()); - - mHandsOffEvents = TRUE; - - } } void LLWindowMacOSX::afterDialog() { - if(mFullscreen) - { - mHandsOffEvents = FALSE; - - // SetWindowGroupLevel(GetWindowGroupOfClass(kAllWindowClasses), oldWindowLevel); - aglSetFullScreen(mContext, 0, 0, 0, 0); - // GLint order = 1; - // aglSetInteger(mContext, AGL_ORDER_CONTEXT_TO_FRONT, &order); - -#if CAPTURE_ALL_DISPLAYS - // Capture all displays (may want to do this for final build) - CGCaptureAllDisplays (); -#else - // Capture only the main display (useful for debugging) - CGDisplayCapture (mDisplay); -#endif - } + //For fix problem with Core Flow view on OSX + restoreGLContext(); } void LLWindowMacOSX::flashIcon(F32 seconds) { - // Don't do this if we're already started, since this would try to install the NMRec twice. - if(!mBounceTimer.getStarted()) - { - OSErr err; - - mBounceTime = seconds; - memset(&mBounceRec, 0, sizeof(mBounceRec)); - mBounceRec.qType = nmType; - mBounceRec.nmMark = 1; - err = NMInstall(&mBounceRec); - if(err == noErr) - { - mBounceTimer.start(); - } - else - { - // This is very not-fatal (only problem is the icon will not bounce), but we'd like to find out about it somehow... - LL_INFOS() << "NMInstall failed with error code " << err << LL_ENDL; - } - } + // For consistency with OS X conventions, the number of seconds given is ignored and + // left up to the OS (which will actually bounce it for one second). + requestUserAttention(); } BOOL LLWindowMacOSX::isClipboardTextAvailable() { - OSStatus err; - ScrapRef scrap; - ScrapFlavorFlags flags; - BOOL result = false; - - err = GetCurrentScrap(&scrap); - - if(err == noErr) - { - err = GetScrapFlavorFlags(scrap, kScrapFlavorTypeUnicode, &flags); - } - - if(err == noErr) - result = true; - - return result; + return pasteBoardAvailable(); } BOOL LLWindowMacOSX::pasteTextFromClipboard(LLWString &dst) -{ - OSStatus err; - ScrapRef scrap; - Size len; - BOOL result = false; - - err = GetCurrentScrap(&scrap); - - if(err == noErr) +{ + llutf16string str(copyFromPBoard()); + dst = utf16str_to_wstring(str); + if (dst != L"") { - err = GetScrapFlavorSize(scrap, kScrapFlavorTypeUnicode, &len); + return true; + } else { + return false; } - - if((err == noErr) && (len > 0)) - { - int u16len = len / sizeof(U16); - U16 *temp = new U16[u16len + 1]; - if (temp) - { - memset(temp, 0, (u16len + 1) * sizeof(temp[0])); - err = GetScrapFlavorData(scrap, kScrapFlavorTypeUnicode, &len, temp); - if (err == noErr) - { - // convert \r\n to \n and \r to \n in the incoming text. - U16 *s, *d; - for(s = d = temp; s[0] != '\0'; s++, d++) - { - if(s[0] == '\r') - { - if(s[1] == '\n') - { - // CRLF, a.k.a. DOS newline. Collapse to a single '\n'. - s++; - } - - d[0] = '\n'; - } - else - { - d[0] = s[0]; - } - } - - d[0] = '\0'; - - dst = utf16str_to_wstring(temp); - - result = true; - } - delete[] temp; - } - } - - return result; } BOOL LLWindowMacOSX::copyTextToClipboard(const LLWString &s) { - OSStatus err; - ScrapRef scrap; - //Size len; - //char *temp; BOOL result = false; - - if (!s.empty()) - { - err = GetCurrentScrap(&scrap); - if (err == noErr) - err = ClearScrap(&scrap); - - if (err == noErr) - { - llutf16string utf16str = wstring_to_utf16str(s); - size_t u16len = utf16str.length() * sizeof(U16); - err = PutScrapFlavor(scrap, kScrapFlavorTypeUnicode, kScrapFlavorMaskNone, u16len, utf16str.data()); - if (err == noErr) - result = true; - } - } + llutf16string utf16str = wstring_to_utf16str(s); + + result = copyToPBoard(utf16str.data(), utf16str.length()); return result; } +void LLWindowMacOSX::setWindowTitle(const std::string& title) +{ + setTitle(title); +} // protected BOOL LLWindowMacOSX::resetDisplayResolution() @@ -1769,7 +1257,7 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r { if (!mSupportedResolutions) { - CFArrayRef modes = CGDisplayAvailableModes(mDisplay); + CFArrayRef modes = CGDisplayCopyAllDisplayModes(mDisplay, NULL); if(modes != NULL) { @@ -1808,6 +1296,7 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r } } } + CFRelease(modes); } } @@ -1817,122 +1306,52 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r BOOL LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordWindow *to) { - S32 client_height; - Rect client_rect; - - if(mFullscreen) - { - // In the fullscreen case, the "window" is the entire screen. - client_rect.left = 0; - client_rect.top = 0; - client_rect.right = mFullscreenWidth; - client_rect.bottom = mFullscreenHeight; - } - else if (!mWindow || - (GetWindowBounds(mWindow, kWindowContentRgn, &client_rect) != noErr) || - NULL == to) - { - return FALSE; - } - to->mX = from.mX; - client_height = client_rect.bottom - client_rect.top; - to->mY = client_height - from.mY - 1; - + to->mY = from.mY; return TRUE; } BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordGL* to) { - S32 client_height; - Rect client_rect; - - if(mFullscreen) - { - // In the fullscreen case, the "window" is the entire screen. - client_rect.left = 0; - client_rect.top = 0; - client_rect.right = mFullscreenWidth; - client_rect.bottom = mFullscreenHeight; - } - else if (!mWindow || - (GetWindowBounds(mWindow, kWindowContentRgn, &client_rect) != noErr) || - NULL == to) - { - return FALSE; - } - to->mX = from.mX; - client_height = client_rect.bottom - client_rect.top; - to->mY = client_height - from.mY - 1; - + to->mY = from.mY; return TRUE; } BOOL LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordWindow* to) { - if(mFullscreen) + if(mWindow) { - // In the fullscreen case, window and screen coordinates are the same. - to->mX = from.mX; - to->mY = from.mY; - return TRUE; - } - else if(mWindow) - { - GrafPtr save; - Point mouse_point; + float mouse_point[2]; + float scale_factor = getScaleFactor(); + mouse_point[0] = from.mX; + mouse_point[1] = from.mY; + + convertScreenToWindow(mWindow, mouse_point); - mouse_point.h = from.mX; - mouse_point.v = from.mY; - - ::GetPort(&save); - ::SetPort(GetWindowPort(mWindow)); - fixOrigin(); - - ::GlobalToLocal(&mouse_point); - - to->mX = mouse_point.h; - to->mY = mouse_point.v; - - ::SetPort(save); + to->mX = mouse_point[0] * scale_factor; + to->mY = mouse_point[1] * scale_factor; return TRUE; } - return FALSE; } BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordScreen *to) { - if(mFullscreen) + if(mWindow) { - // In the fullscreen case, window and screen coordinates are the same. - to->mX = from.mX; - to->mY = from.mY; - return TRUE; - } - else if(mWindow) - { - GrafPtr save; - Point mouse_point; + float mouse_point[2]; + float scale_factor = getScaleFactor(); + mouse_point[0] = from.mX / scale_factor; + mouse_point[1] = from.mY / scale_factor; + convertWindowToScreen(mWindow, mouse_point); - mouse_point.h = from.mX; - mouse_point.v = from.mY; - ::GetPort(&save); - ::SetPort(GetWindowPort(mWindow)); - fixOrigin(); - - LocalToGlobal(&mouse_point); - - to->mX = mouse_point.h; - to->mY = mouse_point.v; - - ::SetPort(save); + to->mX = mouse_point[0]; + to->mY = mouse_point[1]; return TRUE; } - return FALSE; } @@ -1960,862 +1379,8 @@ void LLWindowMacOSX::setupFailure(const std::string& text, const std::string& ca OSMessageBox(text, caption, type); } -pascal Boolean LLWindowMacOSX::staticMoveEventComparator( EventRef event, void* data) -{ - UInt32 evtClass = GetEventClass (event); - UInt32 evtKind = GetEventKind (event); - - if ((evtClass == kEventClassMouse) && ((evtKind == kEventMouseDragged) || (evtKind == kEventMouseMoved))) - { - return true; - } - - else - { - return false; - } -} - - -pascal OSStatus LLWindowMacOSX::staticEventHandler(EventHandlerCallRef myHandler, EventRef event, void* userData) -{ - LLWindowMacOSX *self = (LLWindowMacOSX*)userData; - - return(self->eventHandler(myHandler, event)); -} - -OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef event) -{ - OSStatus result = eventNotHandledErr; - UInt32 evtClass = GetEventClass (event); - UInt32 evtKind = GetEventKind (event); - - // Always handle command events, even in hands-off mode. - if((evtClass == kEventClassCommand) && (evtKind == kEventCommandProcess)) - { - HICommand command; - GetEventParameter (event, kEventParamDirectObject, typeHICommand, NULL, sizeof(command), NULL, &command); - - switch(command.commandID) - { - case kHICommandQuit: - if(mCallbacks->handleCloseRequest(this)) - { - // Get the app to initiate cleanup. - mCallbacks->handleQuit(this); - // The app is responsible for calling destroyWindow when done with GL - } - result = noErr; - break; - - default: - // MBW -- XXX -- Should we handle other events here? - break; - } - } - - if(mHandsOffEvents) - { - return(result); - } - - switch (evtClass) - { - case kEventClassTextInput: - { - switch (evtKind) - { - case kEventTextInputUpdateActiveInputArea: - { - EventParamType param_type; - - long fix_len; - UInt32 text_len; - if (mPreeditor - && (result = GetEventParameter(event, kEventParamTextInputSendFixLen, - typeLongInteger, ¶m_type, sizeof(fix_len), NULL, &fix_len)) == noErr - && typeLongInteger == param_type - && (result = GetEventParameter(event, kEventParamTextInputSendText, - typeUnicodeText, ¶m_type, 0, &text_len, NULL)) == noErr - && typeUnicodeText == param_type) - { - // Handle an optional (but essential to facilitate TSMDA) ReplaceRange param. - CFRange range; - if (GetEventParameter(event, kEventParamTextInputSendReplaceRange, - typeCFRange, ¶m_type, sizeof(range), NULL, &range) == noErr - && typeCFRange == param_type) - { - // Although the spec. is unclear, replace range should - // not present when there is an active preedit. We just - // ignore the case. markAsPreedit will detect the case and warn it. - const LLWString & text = mPreeditor->getPreeditString(); - const S32 location = wstring_wstring_length_from_utf16_length(text, 0, range.location); - const S32 length = wstring_wstring_length_from_utf16_length(text, location, range.length); - mPreeditor->markAsPreedit(location, length); - } - mPreeditor->resetPreedit(); - - // Receive the text from input method. - U16 *const text = new U16[text_len / sizeof(U16)]; - GetEventParameter(event, kEventParamTextInputSendText, typeUnicodeText, NULL, text_len, NULL, text); - if (fix_len < 0) - { - // Do we still need this? Seems obsolete... - fix_len = text_len; - } - const LLWString fix_string - = utf16str_to_wstring(llutf16string(text, fix_len / sizeof(U16))); - const LLWString preedit_string - = utf16str_to_wstring(llutf16string(text + fix_len / sizeof(U16), (text_len - fix_len) / sizeof(U16))); - delete[] text; - - // Handle fixed (comitted) string. - if (fix_string.length() > 0) - { - for (LLWString::const_iterator i = fix_string.begin(); i != fix_string.end(); i++) - { - mPreeditor->handleUnicodeCharHere(*i); - } - } - - // Receive the segment info and caret position. - LLPreeditor::segment_lengths_t preedit_segment_lengths; - LLPreeditor::standouts_t preedit_standouts; - S32 caret_position = preedit_string.length(); - UInt32 text_range_array_size; - if (GetEventParameter(event, kEventParamTextInputSendHiliteRng, typeTextRangeArray, - ¶m_type, 0, &text_range_array_size, NULL) == noErr - && typeTextRangeArray == param_type - && text_range_array_size > sizeof(TextRangeArray)) - { - // TextRangeArray is a variable-length struct. - TextRangeArray * const text_range_array = (TextRangeArray *) new char[text_range_array_size]; - GetEventParameter(event, kEventParamTextInputSendHiliteRng, typeTextRangeArray, - NULL, text_range_array_size, NULL, text_range_array); - - // WARNING: We assume ranges are in ascending order, - // although the condition is undocumented. It seems - // OK to assume this. I also assumed - // the ranges are contiguous in previous versions, but I - // have heard a rumore that older versions os ATOK may - // return ranges with some _gap_. I don't know whether - // it is true, but I'm preparing my code for the case. - - const S32 ranges = text_range_array->fNumOfRanges; - preedit_segment_lengths.reserve(ranges); - preedit_standouts.reserve(ranges); - - S32 last_bytes = 0; - S32 last_utf32 = 0; - for (S32 i = 0; i < ranges; i++) - { - const TextRange &range = text_range_array->fRange[i]; - if (range.fStart > last_bytes) - { - const S32 length_utf16 = (range.fStart - last_bytes) / sizeof(U16); - const S32 length_utf32 = wstring_wstring_length_from_utf16_length(preedit_string, last_utf32, length_utf16); - preedit_segment_lengths.push_back(length_utf32); - preedit_standouts.push_back(FALSE); - last_utf32 += length_utf32; - } - if (range.fEnd > range.fStart) - { - const S32 length_utf16 = (range.fEnd - range.fStart) / sizeof(U16); - const S32 length_utf32 = wstring_wstring_length_from_utf16_length(preedit_string, last_utf32, length_utf16); - preedit_segment_lengths.push_back(length_utf32); - preedit_standouts.push_back( - kTSMHiliteSelectedRawText == range.fHiliteStyle - || kTSMHiliteSelectedConvertedText == range.fHiliteStyle - || kTSMHiliteSelectedText == range.fHiliteStyle); - last_utf32 += length_utf32; - } - if (kTSMHiliteCaretPosition == range.fHiliteStyle) - { - caret_position = last_utf32; - } - last_bytes = range.fEnd; - } - if (preedit_string.length() > last_utf32) - { - preedit_segment_lengths.push_back(preedit_string.length() - last_utf32); - preedit_standouts.push_back(FALSE); - } - - delete[] (char *) text_range_array; - } - - // Handle preedit string. - if (preedit_string.length() == 0) - { - preedit_segment_lengths.clear(); - preedit_standouts.clear(); - } - else if (preedit_segment_lengths.size() == 0) - { - preedit_segment_lengths.push_back(preedit_string.length()); - preedit_standouts.push_back(FALSE); - } - mPreeditor->updatePreedit(preedit_string, preedit_segment_lengths, preedit_standouts, caret_position); - - result = noErr; - } - } - break; - - case kEventTextInputUnicodeForKeyEvent: - { - UInt32 modifiers = 0; - - - // First, process the raw event. - { - EventRef rawEvent = NULL; - - // Get the original event and extract the modifier keys, so we can ignore command-key events. - if (GetEventParameter(event, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(rawEvent), NULL, &rawEvent) == noErr) - { - // Grab the modifiers for later use in this function... - GetEventParameter (rawEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); - - // and call this function recursively to handle the raw key event. - eventHandler (myHandler, rawEvent); - - // save the raw event until we're done processing the unicode input as well. - mRawKeyEvent = rawEvent; - } - } - - OSStatus err = noErr; - EventParamType actualType = typeUnicodeText; - UInt32 actualSize = 0; - size_t actualCount = 0; - U16 *buffer = NULL; - - // Get the size of the unicode data - err = GetEventParameter (event, kEventParamTextInputSendText, typeUnicodeText, &actualType, 0, &actualSize, NULL); - if(err == noErr) - { - // allocate a buffer and get the actual data. - actualCount = actualSize / sizeof(U16); - buffer = new U16[actualCount]; - err = GetEventParameter (event, kEventParamTextInputSendText, typeUnicodeText, &actualType, actualSize, &actualSize, buffer); - } - - if(err == noErr) - { - if(modifiers & (cmdKey | controlKey)) - { - // This was a menu key equivalent. Ignore it. - } - else - { - MASK mask = LLWindowMacOSX::modifiersToMask(modifiers); - - llassert( actualType == typeUnicodeText ); - - // The result is a UTF16 buffer. Pass the characters in turn to handleUnicodeChar. - - // Convert to UTF32 and go character-by-character. - llutf16string utf16(buffer, actualCount); - LLWString utf32 = utf16str_to_wstring(utf16); - LLWString::iterator iter; - - for(iter = utf32.begin(); iter != utf32.end(); iter++) - { - mCallbacks->handleUnicodeChar(*iter, mask); - } - } - } - - if(buffer != NULL) - { - delete[] buffer; - } - - mRawKeyEvent = NULL; - result = err; - } - break; - - case kEventTextInputOffsetToPos: - { - EventParamType param_type; - long offset; - if (mPreeditor - && GetEventParameter(event, kEventParamTextInputSendTextOffset, typeLongInteger, - ¶m_type, sizeof(offset), NULL, &offset) == noErr - && typeLongInteger == param_type) - { - S32 preedit, preedit_length; - mPreeditor->getPreeditRange(&preedit, &preedit_length); - const LLWString & text = mPreeditor->getPreeditString(); - - LLCoordGL caret_coord; - LLRect preedit_bounds; - if (0 <= offset - && mPreeditor->getPreeditLocation(wstring_wstring_length_from_utf16_length(text, preedit, offset / sizeof(U16)), - &caret_coord, &preedit_bounds, NULL)) - { - LLCoordGL caret_base_coord(caret_coord.mX, preedit_bounds.mBottom); - LLCoordScreen caret_base_coord_screen; - convertCoords(caret_base_coord, &caret_base_coord_screen); - Point qd_point; - qd_point.h = caret_base_coord_screen.mX; - qd_point.v = caret_base_coord_screen.mY; - SetEventParameter(event, kEventParamTextInputReplyPoint, typeQDPoint, sizeof(qd_point), &qd_point); - - short line_height = (short) preedit_bounds.getHeight(); - SetEventParameter(event, kEventParamTextInputReplyLineHeight, typeShortInteger, sizeof(line_height), &line_height); - - result = noErr; - } - else - { - result = errOffsetInvalid; - } - } - } - break; - - case kEventTextInputGetSelectedText: - { - if (mPreeditor) - { - S32 selection, selection_length; - mPreeditor->getSelectionRange(&selection, &selection_length); - if (selection_length) - { - const LLWString text = mPreeditor->getPreeditString().substr(selection, selection_length); - const llutf16string text_utf16 = wstring_to_utf16str(text); - result = SetEventParameter(event, kEventParamTextInputReplyText, typeUnicodeText, - text_utf16.length() * sizeof(U16), text_utf16.c_str()); - } - } - } - break; - } - } - break; - - case kEventClassKeyboard: - { - UInt32 keyCode = 0; - char charCode = 0; - UInt32 modifiers = 0; - - // Some of these may fail for some event types. That's fine. - GetEventParameter (event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode); - GetEventParameter (event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); - - // save the raw event so getNativeKeyData can use it. - mRawKeyEvent = event; - - // printf("key event, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n", keyCode, charCode, (char)charCode, modifiers); - // fflush(stdout); - - switch (evtKind) - { - case kEventRawKeyDown: - case kEventRawKeyRepeat: - if (gDebugWindowProc) - { - printf("key down, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n", - (unsigned int)keyCode, charCode, (char)charCode, (unsigned int)modifiers); - fflush(stdout); - } - gKeyboard->handleKeyDown(keyCode, modifiers); - result = eventNotHandledErr; - break; - - case kEventRawKeyUp: - if (gDebugWindowProc) - { - printf("key up, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n", - (unsigned int)keyCode, charCode, (char)charCode, (unsigned int)modifiers); - fflush(stdout); - } - gKeyboard->handleKeyUp(keyCode, modifiers); - result = eventNotHandledErr; - break; - - case kEventRawKeyModifiersChanged: - // The keyboard input system wants key up/down events for modifier keys. - // Mac OS doesn't supply these directly, but can supply events when the collective modifier state changes. - // Use these events to generate up/down events for the modifiers. - - if((modifiers & shiftKey) && !(mLastModifiers & shiftKey)) - { - if (gDebugWindowProc) printf("Shift key down event\n"); - gKeyboard->handleKeyDown(0x38, (modifiers & 0x00FFFFFF) | ((0x38 << 24) & 0xFF000000)); - } - else if(!(modifiers & shiftKey) && (mLastModifiers & shiftKey)) - { - if (gDebugWindowProc) printf("Shift key up event\n"); - gKeyboard->handleKeyUp(0x38, (modifiers & 0x00FFFFFF) | ((0x38 << 24) & 0xFF000000)); - } - - if((modifiers & alphaLock) && !(mLastModifiers & alphaLock)) - { - if (gDebugWindowProc) printf("Caps lock down event\n"); - gKeyboard->handleKeyDown(0x39, (modifiers & 0x00FFFFFF) | ((0x39 << 24) & 0xFF000000)); - } - else if(!(modifiers & alphaLock) && (mLastModifiers & alphaLock)) - { - if (gDebugWindowProc) printf("Caps lock up event\n"); - gKeyboard->handleKeyUp(0x39, (modifiers & 0x00FFFFFF) | ((0x39 << 24) & 0xFF000000)); - } - - if((modifiers & controlKey) && !(mLastModifiers & controlKey)) - { - if (gDebugWindowProc) printf("Control key down event\n"); - gKeyboard->handleKeyDown(0x3b, (modifiers & 0x00FFFFFF) | ((0x3b << 24) & 0xFF000000)); - } - else if(!(modifiers & controlKey) && (mLastModifiers & controlKey)) - { - if (gDebugWindowProc) printf("Control key up event\n"); - gKeyboard->handleKeyUp(0x3b, (modifiers & 0x00FFFFFF) | ((0x3b << 24) & 0xFF000000)); - } - - if((modifiers & optionKey) && !(mLastModifiers & optionKey)) - { - if (gDebugWindowProc) printf("Option key down event\n"); - gKeyboard->handleKeyDown(0x3a, (modifiers & 0x00FFFFFF) | ((0x3a << 24) & 0xFF000000)); - } - else if(!(modifiers & optionKey) && (mLastModifiers & optionKey)) - { - if (gDebugWindowProc) printf("Option key up event\n"); - gKeyboard->handleKeyUp(0x3a, (modifiers & 0x00FFFFFF) | ((0x3a << 24) & 0xFF000000)); - } - - // When the state of the 'Fn' key (the one that changes some of the mappings on a powerbook/macbook keyboard - // to an embedded keypad) changes, it may subsequently cause a key up event to be lost, which may lead to - // a movement key getting "stuck" down. This is bad. - // This is an OS bug -- even the GetKeys() API doesn't tell you the key has been released. - // This workaround causes all held-down keys to be reset whenever the state of the Fn key changes. This isn't - // exactly what we want, but it does avoid the case where you get stuck running forward. - if((modifiers & kEventKeyModifierFnMask) != (mLastModifiers & kEventKeyModifierFnMask)) - { - if (gDebugWindowProc) printf("Fn key state change event\n"); - gKeyboard->resetKeys(); - } - - if (gDebugWindowProc) fflush(stdout); - - mLastModifiers = modifiers; - result = eventNotHandledErr; - break; - } - - mRawKeyEvent = NULL; - } - break; - - case kEventClassMouse: - { - result = CallNextEventHandler(myHandler, event); - if (eventNotHandledErr == result) - { // only handle events not already handled (prevents wierd resize interaction) - EventMouseButton button = kEventMouseButtonPrimary; - HIPoint location = {0.0f, 0.0f}; - UInt32 modifiers = 0; - UInt32 clickCount = 1; - long wheelDelta = 0; - LLCoordScreen inCoords; - LLCoordGL outCoords; - MASK mask = 0; - - GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button); - GetEventParameter(event, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(location), NULL, &location); - GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(modifiers), NULL, &modifiers); - GetEventParameter(event, kEventParamMouseWheelDelta, typeLongInteger, NULL, sizeof(wheelDelta), NULL, &wheelDelta); - GetEventParameter(event, kEventParamClickCount, typeUInt32, NULL, sizeof(clickCount), NULL, &clickCount); - - inCoords.mX = llround(location.x); - inCoords.mY = llround(location.y); - - if(modifiers & shiftKey) { mask |= MASK_SHIFT; } - if(modifiers & controlKey) { mask |= MASK_CONTROL; } - if(modifiers & optionKey) { mask |= MASK_ALT; } - - if(mCursorDecoupled) - { - CGMouseDelta x, y; - - // If the cursor's decoupled, we need to read the latest movement delta as well. - CGGetLastMouseDelta( &x, &y ); - mCursorLastEventDeltaX = x; - mCursorLastEventDeltaY = y; - - if(mCursorIgnoreNextDelta) - { - mCursorLastEventDeltaX = 0; - mCursorLastEventDeltaY = 0; - mCursorIgnoreNextDelta = FALSE; - } - } - else - { - mCursorLastEventDeltaX = 0; - mCursorLastEventDeltaY = 0; - } - - inCoords.mX += mCursorLastEventDeltaX; - inCoords.mY += mCursorLastEventDeltaY; - - convertCoords(inCoords, &outCoords); - - // printf("coords in: %d, %d; coords out: %d, %d\n", inCoords.mX, inCoords.mY, outCoords.mX, outCoords.mY); - // fflush(stdout); - - - switch (evtKind) - { - case kEventMouseDown: - if (mLanguageTextInputAllowed) - { - // We need to interrupt before handling mouse events, - // so that the fixed string from IM are delivered to - // the currently focused UI component. - interruptLanguageTextInput(); - } - switch(button) - { - case kEventMouseButtonPrimary: - if(modifiers & cmdKey) - { - // Simulate a right click - mSimulatedRightClick = true; - mCallbacks->handleRightMouseDown(this, outCoords, mask); - } - else if(clickCount == 2) - { - // Windows double-click events replace the second mousedown event in a double-click. - mCallbacks->handleDoubleClick(this, outCoords, mask); - } - else - { - mCallbacks->handleMouseDown(this, outCoords, mask); - } - break; - case kEventMouseButtonSecondary: - mCallbacks->handleRightMouseDown(this, outCoords, mask); - break; - - case kEventMouseButtonTertiary: - mCallbacks->handleMiddleMouseDown(this, outCoords, mask); - break; - } - result = noErr; - break; - case kEventMouseUp: - - switch(button) - { - case kEventMouseButtonPrimary: - if(mSimulatedRightClick) - { - // End of simulated right click - mSimulatedRightClick = false; - mCallbacks->handleRightMouseUp(this, outCoords, mask); - } - else - { - mCallbacks->handleMouseUp(this, outCoords, mask); - } - break; - case kEventMouseButtonSecondary: - mCallbacks->handleRightMouseUp(this, outCoords, mask); - break; - - case kEventMouseButtonTertiary: - mCallbacks->handleMiddleMouseUp(this, outCoords, mask); - break; - } - result = noErr; - break; - - case kEventMouseWheelMoved: - { - static S32 z_delta = 0; - - z_delta += wheelDelta; - - if (z_delta <= -WHEEL_DELTA || WHEEL_DELTA <= z_delta) - { - mCallbacks->handleScrollWheel(this, -z_delta / WHEEL_DELTA); - z_delta = 0; - } - } - result = noErr; - break; - - case kEventMouseDragged: - case kEventMouseMoved: - mCallbacks->handleMouseMove(this, outCoords, mask); - result = noErr; - break; - - } - } - } - break; - - case kEventClassWindow: - switch(evtKind) - { - case kEventWindowActivated: - if (mTSMDocument) - { - ActivateTSMDocument(mTSMDocument); - } - mCallbacks->handleFocus(this); - break; - case kEventWindowDeactivated: - if (mTSMDocument) - { - DeactivateTSMDocument(mTSMDocument); - } - mCallbacks->handleFocusLost(this); - break; - - case kEventWindowBoundsChanging: - { - // This is where we would constrain move/resize to a particular screen - - const S32 MIN_WIDTH = mMinWindowWidth; - const S32 MIN_HEIGHT = mMinWindowHeight; - - Rect currentBounds; - Rect previousBounds; - - GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, ¤tBounds); - GetEventParameter(event, kEventParamPreviousBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &previousBounds); - - // Put an offset into window un-maximize operation since the kEventWindowGetIdealSize - // event only allows the specification of size and not position. - if (mMaximized) - { - short leftOffset = mPreviousWindowRect.left - currentBounds.left; - currentBounds.left += leftOffset; - currentBounds.right += leftOffset; - - short topOffset = mPreviousWindowRect.top - currentBounds.top; - currentBounds.top += topOffset; - currentBounds.bottom += topOffset; - } - else - { - // Store off the size for future un-maximize operations - mPreviousWindowRect = previousBounds; - } - - if ((currentBounds.right - currentBounds.left) < MIN_WIDTH) - { - currentBounds.right = currentBounds.left + MIN_WIDTH; - } - - if ((currentBounds.bottom - currentBounds.top) < MIN_HEIGHT) - { - currentBounds.bottom = currentBounds.top + MIN_HEIGHT; - } - - SetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, sizeof(Rect), ¤tBounds); - result = noErr; - } - break; - - case kEventWindowBoundsChanged: - { - // Get new window bounds - Rect newBounds; - GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &newBounds); - - // Get previous window bounds - Rect oldBounds; - GetEventParameter(event, kEventParamPreviousBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &oldBounds); - - // Determine if the new size is larger than the old - bool newBoundsLarger = ((newBounds.right - newBounds.left) >= (oldBounds.right - oldBounds.left)); - newBoundsLarger &= ((newBounds.bottom - newBounds.top) >= (oldBounds.bottom - oldBounds.top)); - - // Check to see if this is a zoom event (+ button on window pane) - unsigned int eventParams; - GetEventParameter(event, kEventParamAttributes, typeUInt32, NULL, sizeof(int), NULL, &eventParams); - bool isZoomEvent = ((eventParams & kWindowBoundsChangeZoom) != 0); - - // Maximized flag is if zoom event and increasing window size - mMaximized = (isZoomEvent && newBoundsLarger); - - aglUpdateContext(mContext); - - mCallbacks->handleResize(this, newBounds.right - newBounds.left, newBounds.bottom - newBounds.top); - } - break; - - case kEventWindowGetIdealSize: - // Only recommend a new ideal size when un-maximizing - if (mMaximized == TRUE) - { - Point nonMaximizedSize; - - nonMaximizedSize.v = mPreviousWindowRect.bottom - mPreviousWindowRect.top; - nonMaximizedSize.h = mPreviousWindowRect.right - mPreviousWindowRect.left; - - SetEventParameter(event, kEventParamDimensions, typeQDPoint, sizeof(Point), &nonMaximizedSize); - result = noErr; - } - break; - - case kEventWindowClose: - if(mCallbacks->handleCloseRequest(this)) - { - // Get the app to initiate cleanup. - mCallbacks->handleQuit(this); - // The app is responsible for calling destroyWindow when done with GL - } - result = noErr; - break; - - case kEventWindowHidden: - // LL_INFOS() << "LLWindowMacOSX: Deactivating on hide" << LL_ENDL; - mMinimized = TRUE; - mCallbacks->handleActivate(this, false); - // result = noErr; - break; - - case kEventWindowShown: - // LL_INFOS() << "LLWindowMacOSX: Activating on show" << LL_ENDL; - mMinimized = FALSE; - mCallbacks->handleActivate(this, true); - // result = noErr; - break; - - case kEventWindowCollapsed: - // LL_INFOS() << "LLWindowMacOSX: Deactivating on collapse" << LL_ENDL; - mMinimized = TRUE; - mCallbacks->handleActivate(this, false); - // result = noErr; - break; - - case kEventWindowExpanded: - // LL_INFOS() << "LLWindowMacOSX: Activating on expand" << LL_ENDL; - mMinimized = FALSE; - mCallbacks->handleActivate(this, true); - // result = noErr; - break; - - case kEventWindowGetClickActivation: - // BringToFront(mWindow); - // result = noErr; - break; - } - break; - - case kEventClassTSMDocumentAccess: - if (mPreeditor) - { - switch(evtKind) - { - - case kEventTSMDocumentAccessGetLength: - { - // Return the number of UTF-16 units in the text, excluding those for preedit. - - S32 preedit, preedit_length; - mPreeditor->getPreeditRange(&preedit, &preedit_length); - const LLWString & text = mPreeditor->getPreeditString(); - const CFIndex length = wstring_utf16_length(text, 0, preedit) - + wstring_utf16_length(text, preedit + preedit_length, text.length()); - result = SetEventParameter(event, kEventParamTSMDocAccessCharacterCount, typeCFIndex, sizeof(length), &length); - } - break; - - case kEventTSMDocumentAccessGetSelectedRange: - { - // Return the selected range, excluding preedit. - // In our preeditor, preedit and selection are exclusive, so, - // when it has a preedit, there is no selection and the - // insertion point is on the preedit that corrupses into the - // beginning of the preedit when the preedit was removed. - - S32 preedit, preedit_length; - mPreeditor->getPreeditRange(&preedit, &preedit_length); - const LLWString & text = mPreeditor->getPreeditString(); - - CFRange range; - if (preedit_length) - { - range.location = wstring_utf16_length(text, 0, preedit); - range.length = 0; - } - else - { - S32 selection, selection_length; - mPreeditor->getSelectionRange(&selection, &selection_length); - range.location = wstring_utf16_length(text, 0, selection); - range.length = wstring_utf16_length(text, selection, selection_length); - } - - result = SetEventParameter(event, kEventParamTSMDocAccessReplyCharacterRange, typeCFRange, sizeof(range), &range); - } - break; - - case kEventTSMDocumentAccessGetCharacters: - { - UniChar *target_pointer; - CFRange range; - EventParamType param_type; - if ((result = GetEventParameter(event, kEventParamTSMDocAccessSendCharacterRange, - typeCFRange, ¶m_type, sizeof(range), NULL, &range)) == noErr - && typeCFRange == param_type - && (result = GetEventParameter(event, kEventParamTSMDocAccessSendCharactersPtr, - typePtr, ¶m_type, sizeof(target_pointer), NULL, &target_pointer)) == noErr - && typePtr == param_type) - { - S32 preedit, preedit_length; - mPreeditor->getPreeditRange(&preedit, &preedit_length); - const LLWString & text = mPreeditor->getPreeditString(); - - // The GetCharacters event of TSMDA has a fundamental flaw; - // An input method need to decide the starting offset and length - // *before* it actually see the contents, so it is impossible - // to guarantee the character-aligned access. The event reply - // has no way to indicate a condition something like "Request - // was not fulfilled due to unaligned access. Please retry." - // Any error sent back to the input method stops use of TSMDA - // entirely during the session... - // We need to simulate very strictly the behaviour as if the - // underlying *text engine* holds the contents in UTF-16. - // I guess this is the reason why Apple repeats saying "all - // text handling application should use UTF-16." They are - // trying to _fix_ the flaw by changing the appliations... - // ... or, domination of UTF-16 in the industry may be a part - // of the company vision, and Apple is trying to force third - // party developers to obey their vision. Remember that use - // of 16 bits per _a_character_ was one of the very fundamental - // Unicode design policy on its early days (during late 80s) - // and the original Unicode design was by two Apple employees... - - const llutf16string text_utf16 - = wstring_to_utf16str(text, preedit) - + wstring_to_utf16str(text.substr(preedit + preedit_length)); - - llassert_always(sizeof(U16) == sizeof(UniChar)); - llassert(0 <= range.location && 0 <= range.length && range.location + range.length <= text_utf16.length()); - memcpy(target_pointer, text_utf16.c_str() + range.location, range.length * sizeof(UniChar)); - - // Note that result has already been set above. - } - } - break; - - } - } - break; - } - return result; -} - + // Note on event recording - QUIT is a known special case and we are choosing NOT to record it for the record and playback feature + // it is handled at a very low-level const char* cursorIDToName(int id) { switch (id) @@ -2855,8 +1420,14 @@ const char* cursorIDToName(int id) case UI_CURSOR_PIPETTE: return "UI_CURSOR_PIPETTE"; case UI_CURSOR_TOOLSIT: return "UI_CURSOR_TOOLSIT"; case UI_CURSOR_TOOLBUY: return "UI_CURSOR_TOOLBUY"; - case UI_CURSOR_TOOLOPEN: return "UI_CURSOR_TOOLOPEN"; case UI_CURSOR_TOOLPAY: return "UI_CURSOR_TOOLPAY"; + case UI_CURSOR_TOOLOPEN: return "UI_CURSOR_TOOLOPEN"; + /*case UI_CURSOR_TOOLPATHFINDING: return "UI_CURSOR_PATHFINDING"; + case UI_CURSOR_TOOLPATHFINDING_PATH_START: return "UI_CURSOR_PATHFINDING_START"; + case UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD: return "UI_CURSOR_PATHFINDING_START_ADD"; + case UI_CURSOR_TOOLPATHFINDING_PATH_END: return "UI_CURSOR_PATHFINDING_END"; + case UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD: return "UI_CURSOR_PATHFINDING_END_ADD"; + case UI_CURSOR_TOOLNO: return "UI_CURSOR_NO";*/ } LL_ERRS() << "cursorIDToName: unknown cursor id" << id << LL_ENDL; @@ -2882,7 +1453,7 @@ static void initPixmapCursor(int cursorid, int hotspotX, int hotspotY) void LLWindowMacOSX::updateCursor() { - OSStatus result = noErr; + S32 result = 0; if (mDragOverrideCursor != -1) { @@ -2898,8 +1469,10 @@ void LLWindowMacOSX::updateCursor() mNextCursor = UI_CURSOR_WORKING; } - if(mCurrentCursor == mNextCursor) - return; + if(mCurrentCursor == mNextCursor) + { + return; + } // RN: replace multi-drag cursors with single versions if (mNextCursor == UI_CURSOR_ARROWDRAGMULTI) @@ -2915,11 +1488,11 @@ void LLWindowMacOSX::updateCursor() { default: case UI_CURSOR_ARROW: - InitCursor(); + setArrowCursor(); if(mCursorHidden) { // Since InitCursor resets the hide level, correct for it here. - ::HideCursor(); + hideNSCursor(); } break; @@ -2927,12 +1500,12 @@ void LLWindowMacOSX::updateCursor() // Find out what they look like and replicate them. // These are essentially correct - case UI_CURSOR_WAIT: SetThemeCursor(kThemeWatchCursor); break; - case UI_CURSOR_IBEAM: SetThemeCursor(kThemeIBeamCursor); break; - case UI_CURSOR_CROSS: SetThemeCursor(kThemeCrossCursor); break; - case UI_CURSOR_HAND: SetThemeCursor(kThemePointingHandCursor); break; + case UI_CURSOR_WAIT: /* Apple purposely doesn't allow us to set the beachball cursor manually. Let NSApp figure out when to do this. */ break; + case UI_CURSOR_IBEAM: setIBeamCursor(); break; + case UI_CURSOR_CROSS: setCrossCursor(); break; + case UI_CURSOR_HAND: setPointingHandCursor(); break; // case UI_CURSOR_NO: SetThemeCursor(kThemeNotAllowedCursor); break; - case UI_CURSOR_ARROWCOPY: SetThemeCursor(kThemeCopyArrowCursor); break; + case UI_CURSOR_ARROWCOPY: setCopyCursor(); break; // Double-check these case UI_CURSOR_NO: @@ -2949,6 +1522,7 @@ void LLWindowMacOSX::updateCursor() case UI_CURSOR_NOLOCKED: case UI_CURSOR_ARROWLOCKED: case UI_CURSOR_GRABLOCKED: + case UI_CURSOR_PIPETTE: case UI_CURSOR_TOOLTRANSLATE: case UI_CURSOR_TOOLROTATE: case UI_CURSOR_TOOLSCALE: @@ -2961,8 +1535,14 @@ void LLWindowMacOSX::updateCursor() case UI_CURSOR_TOOLMEDIAOPEN: case UI_CURSOR_TOOLSIT: case UI_CURSOR_TOOLBUY: - case UI_CURSOR_TOOLOPEN: case UI_CURSOR_TOOLPAY: + case UI_CURSOR_TOOLOPEN: + /*case UI_CURSOR_TOOLPATHFINDING: + case UI_CURSOR_TOOLPATHFINDING_PATH_START: + case UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD: + case UI_CURSOR_TOOLPATHFINDING_PATH_END: + case UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD: + case UI_CURSOR_TOOLNO:*/ result = setImageCursor(gCursors[mNextCursor]); break; @@ -2970,7 +1550,7 @@ void LLWindowMacOSX::updateCursor() if(result != noErr) { - InitCursor(); + setArrowCursor(); } mCurrentCursor = mNextCursor; @@ -2994,6 +1574,7 @@ void LLWindowMacOSX::initCursors() initPixmapCursor(UI_CURSOR_NOLOCKED, 8, 8); initPixmapCursor(UI_CURSOR_ARROWLOCKED, 1, 1); initPixmapCursor(UI_CURSOR_GRABLOCKED, 2, 14); + initPixmapCursor(UI_CURSOR_PIPETTE, 3, 29); initPixmapCursor(UI_CURSOR_TOOLTRANSLATE, 1, 1); initPixmapCursor(UI_CURSOR_TOOLROTATE, 1, 1); initPixmapCursor(UI_CURSOR_TOOLSCALE, 1, 1); @@ -3006,8 +1587,14 @@ void LLWindowMacOSX::initCursors() initPixmapCursor(UI_CURSOR_TOOLMEDIAOPEN, 1, 1); initPixmapCursor(UI_CURSOR_TOOLSIT, 20, 15); initPixmapCursor(UI_CURSOR_TOOLBUY, 20, 15); + initPixmapCursor(UI_CURSOR_TOOLPAY, 20, 15); initPixmapCursor(UI_CURSOR_TOOLOPEN, 20, 15); - initPixmapCursor(UI_CURSOR_TOOLPAY, 1, 1); + /*initPixmapCursor(UI_CURSOR_TOOLPATHFINDING, 16, 16); + initPixmapCursor(UI_CURSOR_TOOLPATHFINDING_PATH_START, 16, 16); + initPixmapCursor(UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD, 16, 16); + initPixmapCursor(UI_CURSOR_TOOLPATHFINDING_PATH_END, 16, 16); + initPixmapCursor(UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD, 16, 16); + initPixmapCursor(UI_CURSOR_TOOLNO, 8, 8);*/ initPixmapCursor(UI_CURSOR_SIZENWSE, 10, 10); initPixmapCursor(UI_CURSOR_SIZENESW, 10, 10); @@ -3035,7 +1622,7 @@ void LLWindowMacOSX::hideCursor() // LL_INFOS() << "hideCursor: hiding" << LL_ENDL; mCursorHidden = TRUE; mHideCursorPermanent = TRUE; - ::HideCursor(); + hideNSCursor(); } else { @@ -3052,7 +1639,7 @@ void LLWindowMacOSX::showCursor() // LL_INFOS() << "showCursor: showing" << LL_ENDL; mCursorHidden = FALSE; mHideCursorPermanent = FALSE; - ::ShowCursor(); + showNSCursor(); } else { @@ -3096,53 +1683,18 @@ LLSplashScreenMacOSX::~LLSplashScreenMacOSX() void LLSplashScreenMacOSX::showImpl() { // This code _could_ be used to display a spash screen... -#if 0 - IBNibRef nib = NULL; - OSStatus err; - - err = CreateNibReference(CFSTR("SecondLife"), &nib); - - if(err == noErr) - { - CreateWindowFromNib(nib, CFSTR("Splash Screen"), &mWindow); - - DisposeNibReference(nib); - } - - if(mWindow != NULL) - { - ShowWindow(mWindow); - } -#endif } void LLSplashScreenMacOSX::updateImpl(const std::string& mesg) { +#if 0 if(mWindow != NULL) { CFStringRef string = NULL; string = CFStringCreateWithCString(NULL, mesg.c_str(), kCFStringEncodingUTF8); - - if(string != NULL) - { - ControlRef progressText = NULL; - ControlID id; - OSStatus err; - - id.signature = 'what'; - id.id = 0; - - err = GetControlByID(mWindow, &id, &progressText); - if(err == noErr) - { - err = SetControlData(progressText, kControlEntireControl, kControlStaticTextCFStringTag, sizeof(CFStringRef), (Ptr)&string); - Draw1Control(progressText); - } - - CFRelease(string); - } } +#endif } @@ -3150,134 +1702,32 @@ void LLSplashScreenMacOSX::hideImpl() { if(mWindow != NULL) { - DisposeWindow(mWindow); mWindow = NULL; } } - - S32 OSMessageBoxMacOSX(const std::string& text, const std::string& caption, U32 type) { - S32 result = OSBTN_CANCEL; - SInt16 retval_mac = 1; - AlertStdCFStringAlertParamRec params; - CFStringRef errorString = NULL; - CFStringRef explanationString = NULL; - DialogRef alert = NULL; - AlertType alertType = kAlertCautionAlert; - OSStatus err; - - explanationString = CFStringCreateWithCString(NULL, text.c_str(), kCFStringEncodingUTF8); - errorString = CFStringCreateWithCString(NULL, caption.c_str(), kCFStringEncodingUTF8); - - params.version = kStdCFStringAlertVersionOne; - params.movable = false; - params.helpButton = false; - params.defaultText = (CFStringRef)kAlertDefaultOKText; - params.cancelText = 0; - params.otherText = 0; - params.defaultButton = 1; - params.cancelButton = 0; - params.position = kWindowDefaultPosition; - params.flags = 0; - - switch(type) - { - case OSMB_OK: - default: - break; - case OSMB_OKCANCEL: - params.cancelText = (CFStringRef)kAlertDefaultCancelText; - params.cancelButton = 2; - break; - case OSMB_YESNO: - alertType = kAlertNoteAlert; - params.defaultText = CFSTR("Yes"); - params.cancelText = CFSTR("No"); - params.cancelButton = 2; - break; - } - - if(gWindowImplementation != NULL) - gWindowImplementation->beforeDialog(); - - err = CreateStandardAlert( - alertType, - errorString, - explanationString, - ¶ms, - &alert); - - if(err == noErr) - { - err = RunStandardAlert( - alert, - NULL, - &retval_mac); - } - - if(gWindowImplementation != NULL) - gWindowImplementation->afterDialog(); - - switch(type) - { - case OSMB_OK: - case OSMB_OKCANCEL: - default: - if(retval_mac == 1) - result = OSBTN_OK; - else - result = OSBTN_CANCEL; - break; - case OSMB_YESNO: - if(retval_mac == 1) - result = OSBTN_YES; - else - result = OSBTN_NO; - break; - } - - if(errorString != NULL) - { - CFRelease(errorString); - } - - if(explanationString != NULL) - { - CFRelease(explanationString); - } - - return result; + return showAlert(text, caption, type); } // Open a URL with the user's default web browser. // Must begin with protocol identifier. void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async) { - bool found = false; - S32 i; - for (i = 0; i < gURLProtocolWhitelistCount; i++) - { - if (escaped_url.find(gURLProtocolWhitelist[i]) != std::string::npos) - { - found = true; - break; - } - } - - if (!found) + // I'm fairly certain that this is all legitimate under Apple's currently supported APIs. + if (!isWhitelistedProtocol(escaped_url)) { LL_WARNS() << "spawn_web_browser called for url with protocol not on whitelist: " << escaped_url << LL_ENDL; return; } - OSStatus result = noErr; + S32 result = 0; CFURLRef urlRef = NULL; LL_INFOS() << "Opening URL " << escaped_url << LL_ENDL; - CFStringRef stringRef = CFStringCreateWithBytes(NULL, (UInt8 *)escaped_url.c_str(), strlen(escaped_url.c_str()), kCFStringEncodingUTF8, false); + CFStringRef stringRef = CFStringCreateWithCString(NULL, escaped_url.c_str(), kCFStringEncodingUTF8); if (stringRef) { // This will succeed if the string is a full URL, including the http:// @@ -3306,28 +1756,11 @@ void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async) } } -void LLWindowMacOSX::setTitle(const std::string &title) -{ - /*strncpy((char*)mWindowTitle + 1, title.c_str(), 253); - mWindowTitle[0] = title.length();*/ - - CFStringRef title_str = CFStringCreateWithCString(NULL, title.c_str(), kCFStringEncodingUTF8); - SetWindowTitleWithCFString(mWindow, title_str); -} - -// virtual +// Open a URL with the user's default web browser. +// Must begin with protocol identifier. void LLWindowMacOSX::ShellEx(const std::string& command) { - char * path = NULL; - asprintf(&path, "%s %s", (char*)"file://", command.c_str()); - CFURLRef url = CFURLCreateAbsoluteURLWithBytes(NULL, (UInt8 *)path, strlen(path), - kCFURLPOSIXPathStyle, NULL, true); - if (url != NULL) - { - LSOpenCFURLRef(url, NULL); - CFRelease(url); - } - free(path); + std::system(("open " + command).data()); } LLSD LLWindowMacOSX::getNativeKeyData() @@ -3336,75 +1769,33 @@ LLSD LLWindowMacOSX::getNativeKeyData() if(mRawKeyEvent) { - char char_code = 0; - UInt32 key_code = 0; - UInt32 modifiers = 0; - UInt32 keyboard_type = 0; - - GetEventParameter (mRawKeyEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &char_code); - GetEventParameter (mRawKeyEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &key_code); - GetEventParameter (mRawKeyEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); - GetEventParameter (mRawKeyEvent, kEventParamKeyboardType, typeUInt32, NULL, sizeof(UInt32), NULL, &keyboard_type); - - result["char_code"] = (S32)char_code; - result["key_code"] = (S32)key_code; - result["modifiers"] = (S32)modifiers; - result["keyboard_type"] = (S32)keyboard_type; - -#if 0 - // This causes trouble for control characters -- apparently character codes less than 32 (escape, control-A, etc) - // cause llsd serialization to create XML that the llsd deserializer won't parse! - std::string unicode; - OSStatus err = noErr; - EventParamType actualType = typeUTF8Text; - UInt32 actualSize = 0; - char *buffer = NULL; - - err = GetEventParameter (mRawKeyEvent, kEventParamKeyUnicodes, typeUTF8Text, &actualType, 0, &actualSize, NULL); - if(err == noErr) - { - // allocate a buffer and get the actual data. - buffer = new char[actualSize]; - err = GetEventParameter (mRawKeyEvent, kEventParamKeyUnicodes, typeUTF8Text, &actualType, actualSize, &actualSize, buffer); - if(err == noErr) - { - unicode.assign(buffer, actualSize); - } - delete[] buffer; - } - - result["unicode"] = unicode; -#endif - + result["event_type"] = LLSD::Integer(mRawKeyEvent->mEventType); + result["event_modifiers"] = LLSD::Integer(mRawKeyEvent->mEventModifiers); + result["event_keycode"] = LLSD::Integer(mRawKeyEvent->mEventKeyCode); + result["event_chars"] = (mRawKeyEvent->mEventChars) ? LLSD(LLSD::Integer(mRawKeyEvent->mEventChars)) : LLSD(); + result["event_umodchars"] = (mRawKeyEvent->mEventUnmodChars) ? LLSD(LLSD::Integer(mRawKeyEvent->mEventUnmodChars)) : LLSD(); + result["event_isrepeat"] = LLSD::Boolean(mRawKeyEvent->mEventRepeat); } - LL_DEBUGS() << "native key data is: " << result << LL_ENDL; return result; } - BOOL LLWindowMacOSX::dialogColorPicker( F32 *r, F32 *g, F32 *b) { BOOL retval = FALSE; OSErr error = noErr; NColorPickerInfo info; - + memset(&info, 0, sizeof(info)); info.theColor.color.rgb.red = (UInt16)(*r * 65535.f); info.theColor.color.rgb.green = (UInt16)(*g * 65535.f); info.theColor.color.rgb.blue = (UInt16)(*b * 65535.f); info.placeWhere = kCenterOnMainScreen; - if(gWindowImplementation != NULL) - gWindowImplementation->beforeDialog(); - error = NPickColor(&info); - - if(gWindowImplementation != NULL) - gWindowImplementation->afterDialog(); - + if (error == noErr) { retval = info.newColorChosen; @@ -3415,54 +1806,18 @@ BOOL LLWindowMacOSX::dialogColorPicker( F32 *r, F32 *g, F32 *b) *b = ((float) info.theColor.color.rgb.blue) / 65535.0; } } + return (retval); } - void *LLWindowMacOSX::getPlatformWindow() { // NOTE: this will be NULL in fullscreen mode. Plan accordingly. return (void*)mWindow; } -void *LLWindowMacOSX::getMediaWindow() -{ - /* - Mozilla needs to be initialized with a WindowRef to function properly. - (There's no good reason for this, since it shouldn't be interacting with our window in any way, but that's another issue.) - If we're in windowed mode, we _could_ hand it our actual window pointer, but a subsequent switch to fullscreen will destroy that window, - which trips up Mozilla. - Instead of using our actual window, we create an invisible window which will persist for the lifetime of the application and pass that to Mozilla. - This satisfies its deep-seated need to latch onto a WindowRef and solves the issue with switching between fullscreen and windowed modes. - - Note that we will never destroy this window (by design!), but since only one will ever be created per run of the application, that's okay. - */ - - if(sMediaWindow == NULL) - { - Rect window_rect = {100, 100, 200, 200}; - - sMediaWindow = NewCWindow( - NULL, - &window_rect, - (ConstStr255Param) "\p", - false, // Create the window invisible. - zoomDocProc, // Window with a grow box and a zoom box - kLastWindowOfClass, // create it behind other windows - false, // no close box - 0); - } - - return (void*)sMediaWindow; -} - -void LLWindowMacOSX::stopDockTileBounce() -{ - NMRemove(&mBounceRec); - mBounceTimer.stop(); -} - // get a double value from a dictionary +/* static double getDictDouble (CFDictionaryRef refDict, CFStringRef key) { double double_value; @@ -3472,7 +1827,7 @@ static double getDictDouble (CFDictionaryRef refDict, CFStringRef key) if (!CFNumberGetValue(number_value, kCFNumberDoubleType, &double_value)) // or if cant convert it return -1; // fail return double_value; // otherwise return the long value -} +}*/ // get a long value from a dictionary static long getDictLong (CFDictionaryRef refDict, CFStringRef key) @@ -3488,8 +1843,6 @@ static long getDictLong (CFDictionaryRef refDict, CFStringRef key) void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) { - ScriptLanguageRecord script_language; - if (preeditor != mPreeditor && !b) { // This condition may occur by a call to @@ -3500,9 +1853,7 @@ void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) // is not disturbed. return; } - - UseInputWindow(mTSMDocument, !b); - + // Take care of old and new preeditors. if (preeditor != mPreeditor || !b) { @@ -3515,44 +1866,18 @@ void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) } mPreeditor = (b ? preeditor : NULL); } - + if (b == mLanguageTextInputAllowed) { return; } mLanguageTextInputAllowed = b; - - if (b) - { - if (mTSMScriptCode != smRoman) - { - script_language.fScript = mTSMScriptCode; - script_language.fLanguage = mTSMLangCode; - SetTextServiceLanguage(&script_language); - } - } - else - { - GetTextServiceLanguage(&script_language); - mTSMScriptCode = script_language.fScript; - mTSMLangCode = script_language.fLanguage; - if (mTSMScriptCode != smRoman) - { - script_language.fScript = smRoman; - script_language.fLanguage = langEnglish; - SetTextServiceLanguage(&script_language); - } - } + allowDirectMarkedTextInput(b, mGLView); // mLanguageTextInputAllowed and mMarkedTextAllowed should be updated at once (by Pell Smit } void LLWindowMacOSX::interruptLanguageTextInput() { - if (mTSMDocument) - { - FixTSMDocument(mTSMDocument); - } - // Don't we need to call resetPreedit here? - // Well, if Apple's TSM document is correct, we don't. + commitCurrentPreedit(mGLView); } //static @@ -3563,21 +1888,32 @@ std::vector LLWindowMacOSX::getDynamicFallbackFontList() } // static -MASK LLWindowMacOSX::modifiersToMask(SInt16 modifiers) +MASK LLWindowMacOSX::modifiersToMask(S16 modifiers) { MASK mask = 0; - if(modifiers & shiftKey) { mask |= MASK_SHIFT; } - if(modifiers & (cmdKey | controlKey)) { mask |= MASK_CONTROL; } - if(modifiers & optionKey) { mask |= MASK_ALT; } + if(modifiers & MAC_SHIFT_KEY) { mask |= MASK_SHIFT; } + if(modifiers & (MAC_CMD_KEY | MAC_CTRL_KEY)) { mask |= MASK_CONTROL; } + if(modifiers & MAC_ALT_KEY) { mask |= MASK_ALT; } return mask; } -#if LL_OS_DRAGDROP_ENABLED +//[CR:Retina] +F32 LLWindowMacOSX::getScaleFactor() +{ + return ::getScaleFactor(mGLView); +} -OSErr LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, +void LLWindowMacOSX::updateUnreadCount(S32 num_conversations) +{ + updateBadge(num_conversations); +} + +#if LL_OS_DRAGDROP_ENABLED +/* +S16 LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, void * handlerRefCon, DragRef drag) { - OSErr result = noErr; + S16 result = 0; LLWindowMacOSX *self = (LLWindowMacOSX*)handlerRefCon; LL_DEBUGS() << "drag tracking handler, message = " << message << LL_ENDL; @@ -3602,7 +1938,6 @@ OSErr LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef return result; } - OSErr LLWindowMacOSX::dragReceiveHandler(WindowRef theWindow, void * handlerRefCon, DragRef drag) { @@ -3610,126 +1945,69 @@ OSErr LLWindowMacOSX::dragReceiveHandler(WindowRef theWindow, void * handlerRefC return self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_DROPPED); } - -OSErr LLWindowMacOSX::handleDragNDrop(DragRef drag, LLWindowCallbacks::DragNDropAction action) +*/ +void LLWindowMacOSX::handleDragNDrop(std::string url, LLWindowCallbacks::DragNDropAction action) { - OSErr result = dragNotAcceptedErr; // overall function result - OSErr err = noErr; // for local error handling + MASK mask = LLWindowMacOSX::modifiersToMask(getModifiers()); - // Get the mouse position and modifiers of this drag. - SInt16 modifiers, mouseDownModifiers, mouseUpModifiers; - ::GetDragModifiers(drag, &modifiers, &mouseDownModifiers, &mouseUpModifiers); - MASK mask = LLWindowMacOSX::modifiersToMask(modifiers); - - Point mouse_point; - // This will return the mouse point in global screen coords - ::GetDragMouse(drag, &mouse_point, NULL); - LLCoordScreen screen_coords(mouse_point.h, mouse_point.v); + float mouse_point[2]; + // This will return the mouse point in window coords + getCursorPos(mWindow, mouse_point); + LLCoordWindow window_coords(mouse_point[0], mouse_point[1]); LLCoordGL gl_pos; - convertCoords(screen_coords, &gl_pos); - - // Look at the pasteboard and try to extract an URL from it - PasteboardRef pasteboard; - if(GetDragPasteboard(drag, &pasteboard) == noErr) + convertCoords(window_coords, &gl_pos); + + if(!url.empty()) { - ItemCount num_items = 0; - // Treat an error here as an item count of 0 - (void)PasteboardGetItemCount(pasteboard, &num_items); - - // Only deal with single-item drags. - if(num_items == 1) + LLWindowCallbacks::DragNDropResult res = + mCallbacks->handleDragNDrop(this, gl_pos, mask, action, url); + + switch (res) { + case LLWindowCallbacks::DND_NONE: // No drop allowed + if (action == LLWindowCallbacks::DNDA_TRACK) + { + mDragOverrideCursor = 0; + } + else { + mDragOverrideCursor = -1; + } + break; + case LLWindowCallbacks::DND_MOVE: // Drop accepted would result in a "move" operation + mDragOverrideCursor = UI_CURSOR_NO; + break; + case LLWindowCallbacks::DND_COPY: // Drop accepted would result in a "copy" operation + mDragOverrideCursor = UI_CURSOR_ARROWCOPY; + break; + default: + mDragOverrideCursor = -1; + break; + } + // This overrides the cursor being set by setCursor. + // This is a bit of a hack workaround because lots of areas + // within the viewer just blindly set the cursor. + if (mDragOverrideCursor == -1) { - PasteboardItemID item_id = NULL; - CFArrayRef flavors = NULL; - CFDataRef data = NULL; - - err = PasteboardGetItemIdentifier(pasteboard, 1, &item_id); // Yes, this really is 1-based. - - // Try to extract an URL from the pasteboard - if(err == noErr) - { - err = PasteboardCopyItemFlavors( pasteboard, item_id, &flavors); - } - - if(err == noErr) - { - if(CFArrayContainsValue(flavors, CFRangeMake(0, CFArrayGetCount(flavors)), kUTTypeURL)) - { - // This is an URL. - err = PasteboardCopyItemFlavorData(pasteboard, item_id, kUTTypeURL, &data); - } - else if(CFArrayContainsValue(flavors, CFRangeMake(0, CFArrayGetCount(flavors)), kUTTypeUTF8PlainText)) - { - // This is a string that might be an URL. - err = PasteboardCopyItemFlavorData(pasteboard, item_id, kUTTypeUTF8PlainText, &data); - } - - } - - if(flavors != NULL) - { - CFRelease(flavors); - } - - if(data != NULL) - { - std::string url; - url.assign((char*)CFDataGetBytePtr(data), CFDataGetLength(data)); - CFRelease(data); - - if(!url.empty()) - { - LLWindowCallbacks::DragNDropResult res = - mCallbacks->handleDragNDrop(this, gl_pos, mask, action, url); - - switch (res) { - case LLWindowCallbacks::DND_NONE: // No drop allowed - if (action == LLWindowCallbacks::DNDA_TRACK) - { - mDragOverrideCursor = kThemeNotAllowedCursor; - } - else { - mDragOverrideCursor = -1; - } - break; - case LLWindowCallbacks::DND_MOVE: // Drop accepted would result in a "move" operation - mDragOverrideCursor = kThemePointingHandCursor; - result = noErr; - break; - case LLWindowCallbacks::DND_COPY: // Drop accepted would result in a "copy" operation - mDragOverrideCursor = kThemeCopyArrowCursor; - result = noErr; - break; - case LLWindowCallbacks::DND_LINK: // Drop accepted would result in a "link" operation: - mDragOverrideCursor = kThemeAliasArrowCursor; - result = noErr; - break; - default: - mDragOverrideCursor = -1; - break; - } - // This overrides the cursor being set by setCursor. - // This is a bit of a hack workaround because lots of areas - // within the viewer just blindly set the cursor. - if (mDragOverrideCursor == -1) - { - // Restore the cursor - ECursorType temp_cursor = mCurrentCursor; - // get around the "setting the same cursor" code in setCursor() - mCurrentCursor = UI_CURSOR_COUNT; - setCursor(temp_cursor); - } - else { - // Override the cursor - SetThemeCursor(mDragOverrideCursor); - } - - } - } + // Restore the cursor + ECursorType temp_cursor = mCurrentCursor; + // get around the "setting the same cursor" code in setCursor() + mCurrentCursor = UI_CURSOR_COUNT; + setCursor(temp_cursor); + } + else { + // Override the cursor + switch (mDragOverrideCursor) { + case 0: + setArrowCursor(); + break; + case UI_CURSOR_NO: + setNotAllowedCursor(); + case UI_CURSOR_ARROWCOPY: + setCopyCursor(); + default: + break; + }; } } - - return result; } #endif // LL_OS_DRAGDROP_ENABLED diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 3d6919393..2c02cd143 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -2476,18 +2476,7 @@ void exec_cmd(const std::string& cmd, const std::string& arg) // Must begin with protocol identifier. void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async) { - bool found = false; - S32 i; - for (i = 0; i < gURLProtocolWhitelistCount; i++) - { - if (escaped_url.find(gURLProtocolWhitelist[i]) != std::string::npos) - { - found = true; - break; - } - } - - if (!found) + if (!isWhitelistedProtocol(escaped_url)) { LL_WARNS() << "spawn_web_browser called for url with protocol not on whitelist: " << escaped_url << LL_ENDL; return; diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index e4ce7e837..c9a779cc2 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -3377,18 +3377,7 @@ void LLWindowWin32::ShellEx(const std::string& command) void LLWindowWin32::spawnWebBrowser(const std::string& escaped_url, bool async) { - bool found = false; - S32 i; - for (i = 0; i < gURLProtocolWhitelistCount; i++) - { - if (escaped_url.find(gURLProtocolWhitelist[i]) == 0) - { - found = true; - break; - } - } - - if (!found) + if (!isWhitelistedProtocol(escaped_url)) { LL_WARNS("Window") << "spawn_web_browser() called for url with protocol not on whitelist: " << escaped_url << LL_ENDL; return; From cfc71a47db79c1aee0c161ea4e29f2fc90ecdc06 Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Tue, 19 Feb 2019 04:11:41 -0500 Subject: [PATCH 002/110] Fix up ShellEx It's now crossplatform wrapper for std::system opening of a file/path/url. It returns an int just like std::system, 0 means it worked. It's static so you don't need to gViewerWindow->getWindow() anymore, honestly it should've been static in the first place. Clean up other code to use this function because duplicate code sucks. # Conflicts: # indra/llwindow/llwindowmacosx.h # indra/llwindow/llwindowsdl2.cpp --- indra/llwindow/llwindow.cpp | 13 ++++ indra/llwindow/llwindow.h | 2 +- indra/llwindow/llwindowmacosx.cpp | 7 -- indra/llwindow/llwindowmacosx.h | 93 +++++++++++++-------------- indra/llwindow/llwindowwin32.cpp | 14 ---- indra/llwindow/llwindowwin32.h | 1 - indra/newview/lgghunspell_wrapper.cpp | 2 +- indra/newview/llimpanel.cpp | 9 +-- 8 files changed, 60 insertions(+), 81 deletions(-) diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp index 5efcdbd18..1acd62169 100644 --- a/indra/llwindow/llwindow.cpp +++ b/indra/llwindow/llwindow.cpp @@ -252,6 +252,19 @@ BOOL LLWindow::copyTextToPrimary(const LLWString &src) return FALSE; // fail } +int LLWindow::ShellEx(const std::string& command) +{ + constexpr auto&& open = +#if LL_WINDOWS + "start \"\" \""; // Quoted first argument is the title of the command prompt +#elif LL_DARWIN + "open \""; +#else // LL_LINUX or other modern unix, pray it has xdg-open + "xdg-open \"" +#endif + return std::system((open + command + '"').c_str()); +} + // static std::vector LLWindow::getDynamicFallbackFontList() { diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index 85d5c0fb1..d05b00b95 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -168,7 +168,7 @@ public: virtual void updateLanguageTextInputArea() {} virtual void interruptLanguageTextInput() {} virtual void spawnWebBrowser(const std::string& escaped_url, bool async) {}; - virtual void ShellEx(const std::string& command) {}; + static int ShellEx(const std::string& command); static std::vector getDynamicFallbackFontList(); diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 9becdcaff..dcde667e3 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -1756,13 +1756,6 @@ void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async) } } -// Open a URL with the user's default web browser. -// Must begin with protocol identifier. -void LLWindowMacOSX::ShellEx(const std::string& command) -{ - std::system(("open " + command).data()); -} - LLSD LLWindowMacOSX::getNativeKeyData() { LLSD result = LLSD::emptyMap(); diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index d8d46edb9..292af641a 100644 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -29,22 +29,23 @@ #include "llwindow.h" #include "llwindowcallbacks.h" +#include "llwindowmacosx-objc.h" #include "lltimer.h" -#include -#include +#include +#include // AssertMacros.h does bad things. +#include "fix_macros.h" #undef verify -#undef check #undef require class LLWindowMacOSX : public LLWindow { public: - /*virtual*/ void show(); + /*virtual*/ void show(bool focus = true); /*virtual*/ void hide(); /*virtual*/ void close(); /*virtual*/ BOOL getVisible(); @@ -60,7 +61,7 @@ public: /*virtual*/ BOOL setPosition(LLCoordScreen position); /*virtual*/ BOOL setSizeImpl(LLCoordScreen size); /*virtual*/ BOOL setSizeImpl(LLCoordWindow size); - /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, const LLCoordScreen * const posp = NULL); + /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, const LLCoordScreen * const posp = nullptr); /*virtual*/ BOOL setCursorPosition(LLCoordWindow position); /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position); /*virtual*/ void showCursor(); @@ -76,19 +77,18 @@ public: /*virtual*/ BOOL isClipboardTextAvailable(); /*virtual*/ BOOL pasteTextFromClipboard(LLWString &dst); /*virtual*/ BOOL copyTextToClipboard(const LLWString & src); + /*virtual*/ void setWindowTitle(const std::string& title); /*virtual*/ void flashIcon(F32 seconds); /*virtual*/ F32 getGamma(); /*virtual*/ BOOL setGamma(const F32 gamma); // Set the gamma /*virtual*/ U32 getFSAASamples(); /*virtual*/ void setFSAASamples(const U32 fsaa_samples); - /*virtual*/ void setVsyncMode(const S32 vsync_mode); - /*virtual*/ S32 getVsyncMode(); /*virtual*/ BOOL restoreGamma(); // Restore original gamma table (before updating gamma) /*virtual*/ ESwapMethod getSwapMethod() { return mSwapMethod; } /*virtual*/ void gatherInput(); /*virtual*/ void delayInputProcessing() {}; /*virtual*/ void swapBuffers(); - + // handy coordinate space conversion routines /*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to); /*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordScreen *to); @@ -108,26 +108,34 @@ public: /*virtual*/ BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b); /*virtual*/ void *getPlatformWindow(); - /*virtual*/ void *getMediaWindow(); /*virtual*/ void bringToFront() {}; /*virtual*/ void allowLanguageTextInput(LLPreeditor *preeditor, BOOL b); /*virtual*/ void interruptLanguageTextInput(); /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async); - - /*virtual*/ void setTitle(const std::string &title); - /*virtual*/ void ShellEx(const std::string& command); + /*virtual*/ F32 getScaleFactor(); + /*virtual*/ void updateUnreadCount(S32 num_conversations); static std::vector getDynamicFallbackFontList(); // Provide native key event data /*virtual*/ LLSD getNativeKeyData(); - + + void* getWindow() { return mWindow; } + LLWindowCallbacks* getCallbacks() { return mCallbacks; } + LLPreeditor* getPreeditor() { return mPreeditor; } + + void updateMouseDeltas(double* deltas); + void getMouseDeltas(S32* delta); + + void handleDragNDrop(std::string url, LLWindowCallbacks::DragNDropAction action); + + bool allowsLanguageInput() { return mLanguageTextInputAllowed; } protected: LLWindowMacOSX(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags, - BOOL fullscreen, BOOL clearBg, const S32 vsync_mode, + BOOL fullscreen, BOOL clearBg, S32 vsync_setting, BOOL ignore_pixel_depth, U32 fsaa_samples); ~LLWindowMacOSX(); @@ -148,6 +156,8 @@ protected: BOOL shouldPostQuit() { return mPostQuit; } +private: + void restoreGLContext(); protected: // @@ -155,43 +165,36 @@ protected: // // create or re-create the GL context/window. Called from the constructor and switchContext(). - BOOL createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, const S32 vsync_mode); + BOOL createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, S32 vsync_setting); void destroyContext(); void setupFailure(const std::string& text, const std::string& caption, U32 type); - static pascal OSStatus staticEventHandler (EventHandlerCallRef myHandler, EventRef event, void* userData); - static pascal Boolean staticMoveEventComparator( EventRef event, void* data); - OSStatus eventHandler (EventHandlerCallRef myHandler, EventRef event); void adjustCursorDecouple(bool warpingMouse = false); - void stopDockTileBounce(); - static MASK modifiersToMask(SInt16 modifiers); + static MASK modifiersToMask(S16 modifiers); #if LL_OS_DRAGDROP_ENABLED - static OSErr dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, - void * handlerRefCon, DragRef theDrag); - static OSErr dragReceiveHandler(WindowRef theWindow, void * handlerRefCon, DragRef theDrag); - OSErr handleDragNDrop(DragRef theDrag, LLWindowCallbacks::DragNDropAction action); + + //static OSErr dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, void * handlerRefCon, DragRef theDrag); + //static OSErr dragReceiveHandler(WindowRef theWindow, void * handlerRefCon, DragRef theDrag); + + #endif // LL_OS_DRAGDROP_ENABLED // // Platform specific variables // - WindowRef mWindow; - AGLContext mContext; - AGLPixelFormat mPixelFormat; - CGDirectDisplayID mDisplay; - CFDictionaryRef mOldDisplayMode; - EventLoopTimerRef mTimer; - EventHandlerUPP mEventHandlerUPP; - EventHandlerRef mGlobalHandlerRef; - EventHandlerRef mWindowHandlerRef; - EventComparatorUPP mMoveEventCampartorUPP; - Rect mOldMouseClip; // Screen rect to which the mouse cursor was globally constrained before we changed it in clipMouse() - Rect mPreviousWindowRect; // Save previous window for un-maximize event - Str255 mWindowTitle; + // Use generic pointers here. This lets us do some funky Obj-C interop using Obj-C objects without having to worry about any compilation problems that may arise. + NSWindowRef mWindow; + GLViewRef mGLView; + CGLContextObj mContext; + CGLPixelFormatObj mPixelFormat; + CGDirectDisplayID mDisplay; + + LLRect mOldMouseClip; // Screen rect to which the mouse cursor was globally constrained before we changed it in clipMouse() + std::string mWindowTitle; double mOriginalAspectRatio; BOOL mSimulatedRightClick; - UInt32 mLastModifiers; + U32 mLastModifiers; BOOL mHandsOffEvents; // When true, temporarially disable CarbonEvent processing. // Used to allow event processing when putting up dialogs in fullscreen mode. BOOL mCursorDecoupled; @@ -204,28 +207,18 @@ protected: BOOL mMaximized; BOOL mMinimized; U32 mFSAASamples; - S32 mVsyncMode; BOOL mForceRebuild; - S32 mDragOverrideCursor; - - F32 mBounceTime; - NMRec mBounceRec; - LLTimer mBounceTimer; + S32 mDragOverrideCursor; // Input method management through Text Service Manager. - TSMDocumentID mTSMDocument; BOOL mLanguageTextInputAllowed; - ScriptCode mTSMScriptCode; - LangCode mTSMLangCode; LLPreeditor* mPreeditor; static BOOL sUseMultGL; friend class LLWindowManager; - static WindowRef sMediaWindow; - EventRef mRawKeyEvent; - + }; diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index c9a779cc2..a4cbdc757 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -3361,20 +3361,6 @@ S32 OSMessageBoxWin32(const std::string& text, const std::string& caption, U32 t return retval; } -void LLWindowWin32::ShellEx(const std::string& command) -{ - LLWString url_wstring = utf8str_to_wstring( "\"" + command + "\"" ); - llutf16string url_utf16 = wstring_to_utf16str( url_wstring ); - - SHELLEXECUTEINFO sei = { sizeof( sei ) }; - sei.fMask = SEE_MASK_FLAG_DDEWAIT; - sei.nShow = SW_SHOWNORMAL; - sei.lpVerb = L"open"; - sei.lpFile = url_utf16.c_str(); - ShellExecuteEx( &sei ); -} - - void LLWindowWin32::spawnWebBrowser(const std::string& escaped_url, bool async) { if (!isWhitelistedProtocol(escaped_url)) diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index ca82f7512..02466adde 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -109,7 +109,6 @@ public: /*virtual*/ void setLanguageTextInput( const LLCoordGL & pos ); /*virtual*/ void updateLanguageTextInputArea(); /*virtual*/ void interruptLanguageTextInput(); - void ShellEx(const std::string& command); /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async); /*virtual*/ void setTitle(const std::string &title); diff --git a/indra/newview/lgghunspell_wrapper.cpp b/indra/newview/lgghunspell_wrapper.cpp index c28f83a0c..d19e91485 100644 --- a/indra/newview/lgghunspell_wrapper.cpp +++ b/indra/newview/lgghunspell_wrapper.cpp @@ -948,7 +948,7 @@ void lggHunSpell_Wrapper::editCustomButton() //glggHunSpell->addWordToCustomDictionary("temp"); } - gViewerWindow->getWindow()->ShellEx(dicdicpath); + LLWindow::ShellEx(dicdicpath); } void lggHunSpell_Wrapper::setSpellCheckHighlight(BOOL highlight) diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index b80225d3e..5425fc965 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -1154,13 +1154,8 @@ void show_log_browser(const std::string& name, const std::string& id) const std::string file(LLLogChat::makeLogFileName(name)); if (gSavedSettings.getBOOL("LiruLegacyLogLaunch")) { -#if LL_WINDOWS || LL_DARWIN - gViewerWindow->getWindow()->ShellEx(file); -#elif LL_LINUX - // xdg-open might not actually be installed on all distros, but it's our best bet. - if (!std::system(("/usr/bin/xdg-open \"" + file +'"').c_str())) // 0 = success, otherwise fallback on internal browser. -#endif - return; + if (!LLWindow::ShellEx(file)) // 0 = success, otherwise fallback on internal browser. + return; } LLFloaterWebContent::Params p; p.url("file:///" + file); From 83270e13f8d4bb3a9ce334d78f0575872ebd3e8b Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Tue, 19 Feb 2019 05:03:01 -0500 Subject: [PATCH 003/110] Woops, where'd that semicolon go when we most needed it? --- indra/llwindow/llwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp index 1acd62169..ef0b75b6e 100644 --- a/indra/llwindow/llwindow.cpp +++ b/indra/llwindow/llwindow.cpp @@ -260,7 +260,7 @@ int LLWindow::ShellEx(const std::string& command) #elif LL_DARWIN "open \""; #else // LL_LINUX or other modern unix, pray it has xdg-open - "xdg-open \"" + "xdg-open \""; #endif return std::system((open + command + '"').c_str()); } From 3f9f79c1552279108b077576aeec7b197cf87b8b Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Tue, 19 Mar 2019 21:09:26 -0400 Subject: [PATCH 004/110] Fix an oopsie woopsie, thanks Shyotl --- indra/newview/llvlmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llvlmanager.cpp b/indra/newview/llvlmanager.cpp index b4ec788f7..f3dd91ab5 100644 --- a/indra/newview/llvlmanager.cpp +++ b/indra/newview/llvlmanager.cpp @@ -70,7 +70,7 @@ void LLVLManager::addLayerData(LLVLData *vl_datap, const S32 mesg_size) { mLandBits += mesg_size * 8; } - else if (WATER_LAYER_CODE == vl_datap->mType || WHITECORE_CLOUD_LAYER_CODE == vl_datap->mType) + else if (WATER_LAYER_CODE == vl_datap->mType || WHITECORE_WATER_LAYER_CODE == vl_datap->mType) { mWaterBits += mesg_size * 8; } From 273c9b3479b3cefa60259fb7dd2d085faa405315 Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Tue, 19 Mar 2019 21:28:39 -0400 Subject: [PATCH 005/110] Call ShellEx for launching urls in browser on Windows --- indra/llwindow/llwindowwin32.cpp | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index a4cbdc757..b533f2e36 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -3375,25 +3375,8 @@ void LLWindowWin32::spawnWebBrowser(const std::string& escaped_url, bool async) // reliablly on Vista. // this is madness.. no, this is.. - LLWString url_wstring = utf8str_to_wstring( escaped_url ); - llutf16string url_utf16 = wstring_to_utf16str( url_wstring ); - // let the OS decide what to use to open the URL - SHELLEXECUTEINFO sei = { sizeof( sei ) }; - // NOTE: this assumes that SL will stick around long enough to complete the DDE message exchange - // necessary for ShellExecuteEx to complete - if (async) - { - sei.fMask = SEE_MASK_ASYNCOK; - } - else - { - sei.fMask = SEE_MASK_FLAG_DDEWAIT; - } - sei.nShow = SW_SHOWNORMAL; - sei.lpVerb = L"open"; - sei.lpFile = url_utf16.c_str(); - ShellExecuteEx( &sei ); + ShellEx(escaped_url); } void LLWindowWin32::setTitle(const std::string &title) From f5cbae3958ce2243402506a7e067f5d70972abf8 Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Wed, 20 Mar 2019 00:27:06 -0400 Subject: [PATCH 006/110] Support Halcyon as though it were opensim, for now. --- indra/newview/hippogridmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/hippogridmanager.cpp b/indra/newview/hippogridmanager.cpp index 315b7cf8b..bf82c7fde 100644 --- a/indra/newview/hippogridmanager.cpp +++ b/indra/newview/hippogridmanager.cpp @@ -109,7 +109,7 @@ void HippoGridInfo::setPlatform(const std::string& platform) { setPlatform(PLATFORM_WHITECORE); } - else if (tmp == "opensim") + else if (tmp == "opensim" || tmp == "halcyon") { setPlatform(PLATFORM_OPENSIM); } From 95ff7acd6df9c3459a2ac795a012f067b850bee3 Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Thu, 21 Mar 2019 01:09:47 -0400 Subject: [PATCH 007/110] [Joystick] Do the code better --- indra/newview/llfloaterjoystick.cpp | 19 +++++++++-------- indra/newview/llviewerjoystick.cpp | 32 +++++++++++++++-------------- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/indra/newview/llfloaterjoystick.cpp b/indra/newview/llfloaterjoystick.cpp index b2d1d63fa..e4f594fa0 100644 --- a/indra/newview/llfloaterjoystick.cpp +++ b/indra/newview/llfloaterjoystick.cpp @@ -59,26 +59,29 @@ LLFloaterJoystick::LLFloaterJoystick(const LLSD& data) void LLFloaterJoystick::draw() { + // Singu TODO: Cache these children, or consider not doing this in the draw call bool joystick_inited = LLViewerJoystick::getInstance()->isJoystickInitialized(); childSetEnabled("enable_joystick", joystick_inited); - childSetEnabled("joystick_type", joystick_inited); + auto type(getChild("joystick_type")); + type->setEnabled(joystick_inited); std::string desc = LLViewerJoystick::getInstance()->getDescription(); if (desc.empty()) desc = getString("NoDevice"); - childSetText("joystick_type", desc); + type->setValue(desc); LLViewerJoystick* joystick(LLViewerJoystick::getInstance()); - for (U32 i = 0; i < 6; i++) + for (U32 i = 0; i < 6; ++i) { F32 value = joystick->getJoystickAxis(i); mAxisStats[i]->addValue(value * gFrameIntervalSeconds); - - if (mAxisStatsBar[i]->mMinBar > value) + auto& bar = mAxisStatsBar[i]; + + if (bar->mMinBar > value) { - mAxisStatsBar[i]->mMinBar = value; + bar->mMinBar = value; } - if (mAxisStatsBar[i]->mMaxBar < value) + if (bar->mMaxBar < value) { - mAxisStatsBar[i]->mMaxBar = value; + bar->mMaxBar = value; } } diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp index aa2099066..8d0456495 100644 --- a/indra/newview/llviewerjoystick.cpp +++ b/indra/newview/llviewerjoystick.cpp @@ -47,15 +47,15 @@ // ---------------------------------------------------------------------------- // Constants -#define X_I 1 -#define Y_I 2 -#define Z_I 0 -#define RX_I 4 -#define RY_I 5 -#define RZ_I 3 +constexpr auto X_I = 1; +constexpr auto Y_I = 2; +constexpr auto Z_I = 0; +constexpr auto RX_I = 4; +constexpr auto RY_I = 5; +constexpr auto RZ_I = 3; // minimum time after setting away state before coming back -const F32 MIN_AFK_TIME = 2.f; +constexpr F32 MIN_AFK_TIME = 2.f; F32 LLViewerJoystick::sLastDelta[] = {0,0,0,0,0,0,0}; F32 LLViewerJoystick::sDelta[] = {0,0,0,0,0,0,0}; @@ -113,11 +113,13 @@ enum DS3Keys S32 get_joystick_type() { - if (sType == SPACE_NAV) return 0; - if (sType == XBOX) return isOUYA(LLViewerJoystick::getInstance()->getDescription()) ? 1 : 2; - if (sType == DS3) return 3; - - return -1; // sType == NONE || sType == UNKNOWN + switch (sType) + { + case SPACE_NAV: return 0; + case XBOX: return isOUYA(LLViewerJoystick::getInstance()->getDescription()) ? 1 : 2; + case DS3: return 3; + default: return -1; // sType == NONE || sType == UNKNOWN + } } // @@ -126,8 +128,8 @@ S32 get_joystick_type() // should be. It has to be equal to 3000 because the SpaceNavigator on Windows // refuses to respond to the DirectInput SetProperty call; it always returns // values in the [-3000, 3000] range. -#define MAX_SPACENAVIGATOR_INPUT 3000.0f -#define MAX_JOYSTICK_INPUT_VALUE MAX_SPACENAVIGATOR_INPUT +constexpr auto MAX_SPACENAVIGATOR_INPUT = 3000.0f; +constexpr auto MAX_JOYSTICK_INPUT_VALUE = MAX_SPACENAVIGATOR_INPUT; // ----------------------------------------------------------------------------- void LLViewerJoystick::updateEnabled(bool autoenable) @@ -1390,7 +1392,7 @@ void LLViewerJoystick::setSNDefaults(S32 type) const float platformScaleAvXZ = 2.f; const bool is_3d_cursor = true; #endif - + //gViewerWindow->alertXml("CacheWillClear"); const bool ouya = type == 1; const bool xbox = ouya || type == 2; From c9226f6b63ecb622ac67e8af1181c658a19701ce Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Thu, 21 Mar 2019 01:26:23 -0400 Subject: [PATCH 008/110] [Joystick] Use the button layout for the chosen controller type Using the drop down now FORCES your controller to be detected as your selection for the duration of the session until you choose another --- indra/newview/llviewerjoystick.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp index 8d0456495..d558988c9 100644 --- a/indra/newview/llviewerjoystick.cpp +++ b/indra/newview/llviewerjoystick.cpp @@ -111,6 +111,17 @@ enum DS3Keys DS3_LOGO_KEY }; +void set_joystick_type(const S32& type) +{ + switch (type) + { + case 0: sType = SPACE_NAV; break; + case 1: case 2: sType = XBOX; break; + case 3: sType = DS3; break; + default: sType = UNKNOWN; break; + } +} + S32 get_joystick_type() { switch (sType) @@ -1393,6 +1404,7 @@ void LLViewerJoystick::setSNDefaults(S32 type) const bool is_3d_cursor = true; #endif + set_joystick_type(type); // Breaks resetting to default but allows declaring a new identity and button config for the controller //gViewerWindow->alertXml("CacheWillClear"); const bool ouya = type == 1; const bool xbox = ouya || type == 2; From c2f15ff47c6b203be88a9ddab24fd8a5db3ceba5 Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Thu, 21 Mar 2019 01:27:57 -0400 Subject: [PATCH 009/110] [Joystick] Detect xBOx cOntrOLLers in ANY cAsE --- indra/newview/llviewerjoystick.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp index d558988c9..1dec47062 100644 --- a/indra/newview/llviewerjoystick.cpp +++ b/indra/newview/llviewerjoystick.cpp @@ -42,6 +42,7 @@ #include "llfocusmgr.h" #include "rlvhandler.h" +#include #include // ---------------------------------------------------------------------------- @@ -85,8 +86,7 @@ bool isOUYA(const std::string& desc) { return desc.find("OUYA") != std::string:: bool isXboxLike(const std::string& desc) { - return desc.find("Xbox") != std::string::npos - || isOUYA(desc); + return boost::algorithm::icontains(desc, "xbox") || isOUYA(desc); } bool isDS3Like(const std::string& desc) From 879cd79fdc2962422c8e13906abb817d4f6f9afd Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Thu, 21 Mar 2019 03:13:13 -0400 Subject: [PATCH 010/110] Gesture UI optimization, first pass --- indra/newview/llpreview.h | 2 + indra/newview/llpreviewgesture.cpp | 264 ++++++++++++----------------- indra/newview/llpreviewgesture.h | 2 +- 3 files changed, 111 insertions(+), 157 deletions(-) diff --git a/indra/newview/llpreview.h b/indra/newview/llpreview.h index 02184af85..5203ce31f 100644 --- a/indra/newview/llpreview.h +++ b/indra/newview/llpreview.h @@ -137,6 +137,8 @@ protected: // for LLInventoryObserver virtual void changed(U32 mask); BOOL mDirty; + +public: virtual const char *getTitleName() const { return "Preview"; } protected: diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp index c0ab5ef97..0ac8f3298 100644 --- a/indra/newview/llpreviewgesture.cpp +++ b/indra/newview/llpreviewgesture.cpp @@ -86,10 +86,9 @@ protected: void LLInventoryGestureAvailable::done() { - for(uuid_vec_t::iterator it = mComplete.begin(); it != mComplete.end(); ++it) + for(auto id : mComplete) { - LLPreview* preview = LLPreview::find((*it)); - if(preview) + if (auto preview = LLPreview::find(id)) { preview->refresh(); } @@ -98,15 +97,6 @@ void LLInventoryGestureAvailable::done() delete this; } -// Used for sorting -struct SortItemPtrsByName -{ - bool operator()(const LLInventoryItem* i1, const LLInventoryItem* i2) - { - return (LLStringUtil::compareDict(i1->getName(), i2->getName()) < 0); - } -}; - // static LLPreviewGesture* LLPreviewGesture::show(const std::string& title, const LLUUID& item_id, const LLUUID& object_id, BOOL take_focus) { @@ -128,7 +118,7 @@ LLPreviewGesture* LLPreviewGesture::show(const std::string& title, const LLUUID& // Move window to top-left of screen LLMultiFloater* hostp = preview->getHost(); - if (hostp == NULL) + if (hostp == nullptr) { LLRect r = preview->getRect(); LLRect screen = gFloaterView->getRect(); @@ -226,7 +216,7 @@ BOOL LLPreviewGesture::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, } else if (drop) { - LLScrollListItem* line = NULL; + LLScrollListItem* line = nullptr; if (cargo_type == DAD_ANIMATION) { line = addStep( STEP_ANIMATION ); @@ -342,23 +332,23 @@ bool LLPreviewGesture::handleSaveChangesDialog(const LLSD& notification, const L LLPreviewGesture::LLPreviewGesture() : LLPreview("Gesture Preview"), - mTriggerEditor(NULL), - mModifierCombo(NULL), - mKeyCombo(NULL), - mLibraryList(NULL), - mAddBtn(NULL), - mUpBtn(NULL), - mDownBtn(NULL), - mDeleteBtn(NULL), - mStepList(NULL), - mOptionsText(NULL), - mAnimationRadio(NULL), - mAnimationCombo(NULL), - mSoundCombo(NULL), - mChatEditor(NULL), - mSaveBtn(NULL), - mPreviewBtn(NULL), - mPreviewGesture(NULL), + mTriggerEditor(nullptr), + mModifierCombo(nullptr), + mKeyCombo(nullptr), + mLibraryList(nullptr), + mAddBtn(nullptr), + mUpBtn(nullptr), + mDownBtn(nullptr), + mDeleteBtn(nullptr), + mStepList(nullptr), + mOptionsText(nullptr), + mAnimationRadio(nullptr), + mAnimationCombo(nullptr), + mSoundCombo(nullptr), + mChatEditor(nullptr), + mSaveBtn(nullptr), + mPreviewBtn(nullptr), + mPreviewGesture(nullptr), mDirty(FALSE) { } @@ -367,14 +357,11 @@ LLPreviewGesture::LLPreviewGesture() LLPreviewGesture::~LLPreviewGesture() { // Userdata for all steps is a LLGestureStep we need to clean up - std::vector data_list = mStepList->getAllData(); - std::vector::iterator data_itor; - for (data_itor = data_list.begin(); data_itor != data_list.end(); ++data_itor) + for (auto& item : mStepList->getAllData()) { - LLScrollListItem* item = *data_itor; LLGestureStep* step = (LLGestureStep*)item->getUserdata(); delete step; - step = NULL; + step = nullptr; } } @@ -517,9 +504,10 @@ BOOL LLPreviewGesture::postBuild() if (item) { - childSetCommitCallback("desc", LLPreview::onText, this); - childSetText("desc", item->getDescription()); - getChild("desc")->setPrevalidate(&LLLineEditor::prevalidatePrintableNotPipe); + auto desc = getChild("desc"); + desc->setCommitCallback(LLPreview::onText, this); + desc->setValue(item->getDescription()); + desc->setPrevalidate(&LLLineEditor::prevalidatePrintableNotPipe); } return TRUE; @@ -541,7 +529,20 @@ static const std::string valid_key_to_string(KEY key) { std::string skey(1,(char)key); std::string strkey = LLKeyboard::stringFromKey(key); - return ((skey == strkey && key >= ' ' && key <= '~') || (skey != strkey) ) ? strkey : ""; + return ((skey == strkey && key >= ' ' && key <= '~') || (skey != strkey) ) ? strkey : LLStringUtil::null; +} + +void load_and_sort(LLComboBox* combo, const LLViewerInventoryItem::item_array_t& items) +{ + combo->removeall(); + + // Load up the combobox + for (const auto& item : items) + { + combo->add(item->getName(), item->getAssetUUID()); + } + // Sort + combo->sortByName(); } void LLPreviewGesture::addKeys() @@ -549,10 +550,10 @@ void LLPreviewGesture::addKeys() LLComboBox* combo = mKeyCombo; combo->add( NONE_LABEL ); - for (KEY key = ' '; key < KEY_NONE; key++) + for (KEY key = ' '; key < KEY_NONE; ++key) { std::string keystr = valid_key_to_string(key); - if(keystr != "")combo->add( keystr, ADD_BOTTOM ); + if (!keystr.empty()) combo->add( keystr, ADD_BOTTOM ); } combo->setCurrentByIndex(0); } @@ -562,22 +563,7 @@ void LLPreviewGesture::addKeys() void LLPreviewGesture::addAnimations() { LLComboBox* combo = mAnimationCombo; - combo->removeall(); - - std::string none_text = getString("none_text"); - - combo->add(none_text, LLUUID::null); - - // Add all the default (legacy) animations - S32 i; - for (i = 0; i < gUserAnimStatesCount; ++i) - { - // Use the user-readable name - std::string label = LLAnimStateLabels::getStateLabel( gUserAnimStates[i].mName ); - const LLUUID& id = gUserAnimStates[i].mID; - combo->add(label, id); - } // Get all inventory items that are animations LLViewerInventoryCategory::cat_array_t cats; @@ -592,38 +578,21 @@ void LLPreviewGesture::addAnimations() LLInventoryModel::EXCLUDE_TRASH, is_copyable_animation); - // Copy into something we can sort - std::vector animations; + load_and_sort(combo, items); - S32 count = items.size(); - for(i = 0; i < count; ++i) + // Add all the default (legacy) animations + for (S32 i = gUserAnimStatesCount - 1; i >= 0; --i) { - animations.push_back( items.at(i) ); - } - - // Do the sort - std::sort(animations.begin(), animations.end(), SortItemPtrsByName()); - - // And load up the combobox - std::vector::iterator it; - for (it = animations.begin(); it != animations.end(); ++it) - { - LLInventoryItem* item = *it; - - combo->add(item->getName(), item->getAssetUUID(), ADD_BOTTOM); + // Use the user-readable name + const auto& state = gUserAnimStates[i]; + combo->add(LLAnimStateLabels::getStateLabel(state.mName), state.mID, ADD_TOP); } + combo->add(getString("none_text"), LLUUID::null, ADD_TOP); } void LLPreviewGesture::addSounds() { - LLComboBox* combo = mSoundCombo; - combo->removeall(); - - std::string none_text = getString("none_text"); - - combo->add(none_text, LLUUID::null); - // Get all inventory items that are sounds LLViewerInventoryCategory::cat_array_t cats; LLViewerInventoryItem::item_array_t items; @@ -637,27 +606,9 @@ void LLPreviewGesture::addSounds() LLInventoryModel::EXCLUDE_TRASH, is_copyable_sound); - // Copy sounds into something we can sort - std::vector sounds; - - S32 i; - S32 count = items.size(); - for(i = 0; i < count; ++i) - { - sounds.push_back( items.at(i) ); - } - - // Do the sort - std::sort(sounds.begin(), sounds.end(), SortItemPtrsByName()); - - // And load up the combobox - std::vector::iterator it; - for (it = sounds.begin(); it != sounds.end(); ++it) - { - LLInventoryItem* item = *it; - - combo->add(item->getName(), item->getAssetUUID(), ADD_BOTTOM); - } + LLComboBox* combo = mSoundCombo; + load_and_sort(combo, items); + combo->add(getString("none_text"), LLUUID::null, ADD_TOP); } @@ -732,12 +683,12 @@ void LLPreviewGesture::refresh() BOOL have_replace = !replace.empty(); LLScrollListItem* library_item = mLibraryList->getFirstSelected(); - BOOL have_library = (library_item != NULL); + BOOL have_library = (library_item != nullptr); LLScrollListItem* step_item = mStepList->getFirstSelected(); S32 step_index = mStepList->getFirstSelectedIndex(); S32 step_count = mStepList->getItemCount(); - BOOL have_step = (step_item != NULL); + BOOL have_step = (step_item != nullptr); mReplaceText->setEnabled(have_trigger || have_replace); mReplaceEditor->setEnabled(have_trigger || have_replace); @@ -937,7 +888,7 @@ void LLPreviewGesture::onLoadComplete(LLVFS *vfs, } delete gesture; - gesture = NULL; + gesture = nullptr; self->mAssetStatus = PREVIEW_ASSET_LOADED; } @@ -960,7 +911,7 @@ void LLPreviewGesture::onLoadComplete(LLVFS *vfs, } } delete item_idp; - item_idp = NULL; + item_idp = nullptr; } @@ -1007,7 +958,7 @@ void LLPreviewGesture::loadUIFromGesture(LLMultiGesture* gesture) { LLGestureStep* step = gesture->mSteps[i]; - LLGestureStep* new_step = NULL; + LLGestureStep* new_step = nullptr; switch(step->getType()) { @@ -1109,13 +1060,13 @@ void LLPreviewGesture::saveIfNeeded() LLNotificationsUtil::add("GestureSaveFailedTooManySteps"); delete gesture; - gesture = NULL; + gesture = nullptr; } else if (!ok) { LLNotificationsUtil::add("GestureSaveFailedTryAgain"); delete gesture; - gesture = NULL; + gesture = nullptr; } else { @@ -1187,7 +1138,7 @@ void LLPreviewGesture::saveIfNeeded() { // we're done with this gesture delete gesture; - gesture = NULL; + gesture = nullptr; } mDirty = FALSE; @@ -1200,7 +1151,7 @@ void LLPreviewGesture::saveIfNeeded() } delete [] buffer; - buffer = NULL; + buffer = nullptr; } @@ -1237,7 +1188,7 @@ void LLPreviewGesture::onSaveComplete(const LLUUID& asset_uuid, void* user_data, { // Saving into in-world object inventory LLViewerObject* object = gObjectList.findObject(info->mObjectUUID); - LLViewerInventoryItem* item = NULL; + LLViewerInventoryItem* item = nullptr; if(object) { item = (LLViewerInventoryItem*)object->getInventoryObject(info->mItemUUID); @@ -1271,7 +1222,7 @@ void LLPreviewGesture::onSaveComplete(const LLUUID& asset_uuid, void* user_data, LLNotificationsUtil::add("GestureSaveFailedReason", args); } delete info; - info = NULL; + info = nullptr; } @@ -1306,11 +1257,8 @@ LLMultiGesture* LLPreviewGesture::createGesture() LLKeyboard::keyFromString(key_string, &(gesture->mKey)); } - std::vector data_list = mStepList->getAllData(); - std::vector::iterator data_itor; - for (data_itor = data_list.begin(); data_itor != data_list.end(); ++data_itor) + for (auto& item : mStepList->getAllData()) { - LLScrollListItem* item = *data_itor; LLGestureStep* step = (LLGestureStep*)item->getUserdata(); switch(step->getType()) @@ -1366,11 +1314,7 @@ LLMultiGesture* LLPreviewGesture::createGesture() void LLPreviewGesture::updateLabel(LLScrollListItem* item) { LLGestureStep* step = (LLGestureStep*)item->getUserdata(); - - LLScrollListCell* cell = item->getColumn(0); - LLScrollListText* text_cell = (LLScrollListText*)cell; - std::string label = getLabel( step->getLabel()); - text_cell->setText(label); + static_cast(item->getColumn(0))->setText(getLabel(step->getLabel())); } void LLPreviewGesture::onCommitSetDirty() @@ -1518,9 +1462,7 @@ void LLPreviewGesture::onCommitWait() LLLocale locale(LLLocale::USER_LOCALE); F32 wait_seconds = (F32)atof(mWaitTimeEditor->getText().c_str()); - if (wait_seconds < 0.f) wait_seconds = 0.f; - if (wait_seconds > 3600.f) wait_seconds = 3600.f; - wait_step->mWaitSeconds = wait_seconds; + wait_step->mWaitSeconds = llclamp(wait_seconds, 0.f, 3600.f); } // Enable the input area if necessary @@ -1579,7 +1521,7 @@ LLScrollListItem* LLPreviewGesture::addStep( const EStepType step_type ) { // Order of enum EStepType MUST match the library_list element in floater_preview_gesture.xml - LLGestureStep* step = NULL; + LLGestureStep* step = nullptr; switch( step_type) { case STEP_ANIMATION: @@ -1596,13 +1538,14 @@ LLScrollListItem* LLPreviewGesture::addStep( const EStepType step_type ) break; default: LL_ERRS() << "Unknown step type: " << (S32)step_type << LL_ENDL; - return NULL; + return nullptr; } // Create an enabled item with this step LLSD row; - row["columns"][0]["value"] = getLabel(step->getLabel()); - row["columns"][0]["font"] = "SANSSERIF_SMALL"; + auto& element = row["columns"][0]; + element["value"] = getLabel(step->getLabel()); + element["font"] = "SANSSERIF_SMALL"; LLScrollListItem* step_item = mStepList->addElement(row); step_item->setUserdata(step); @@ -1616,57 +1559,65 @@ LLScrollListItem* LLPreviewGesture::addStep( const EStepType step_type ) } // static -std::string LLPreviewGesture::getLabel(std::vector labels) +std::string LLPreviewGesture::getLabel(const std::vector& v_labels) { - std::vector v_labels = labels ; - std::string result(""); - if( v_labels.size() != 2) { - return result; + return LLStringUtil::null; } - - if(v_labels[0]=="Chat") + + auto result(v_labels[0]); + if (result == "Chat") { - result=LLTrans::getString("Chat Message"); + static const auto chat = LLTrans::getString("Chat Message"); + result = chat; } - else if(v_labels[0]=="Sound") + else if (result == "Sound") { - result=LLTrans::getString("Sound"); + static const auto sound = LLTrans::getString("Sound"); + result = sound; } - else if(v_labels[0]=="Wait") + else if (result == "Wait") { - result=LLTrans::getString("Wait"); + static const auto wait = LLTrans::getString("Wait"); + result = wait; } - else if(v_labels[0]=="AnimFlagStop") + else if (result == "AnimFlagStop") { - result=LLTrans::getString("AnimFlagStop"); + static const auto stop = LLTrans::getString("AnimFlagStop"); + result = stop; } - else if(v_labels[0]=="AnimFlagStart") + else if (result == "AnimFlagStart") { - result=LLTrans::getString("AnimFlagStart"); + static const auto start = LLTrans::getString("AnimFlagStart"); + result = start; } // lets localize action value std::string action = v_labels[1]; if ("None" == action) { - action = LLTrans::getString("GestureActionNone"); + static const auto none = LLTrans::getString("GestureActionNone"); + action = none; } else if ("until animations are done" == action) { //action = LLFloaterReg::getInstance("preview_gesture")->getChild("wait_anim_check")->getLabel(); //Worst. Thing. Ever. We are in a static function. Find any existing gesture preview and grab the label from its 'wait_anim_check' element. - for(preview_map_t::iterator it = LLPreview::sInstances.begin(); it != LLPreview::sInstances.end();++it) + static auto wait_anim = LLStringUtil::null; + if (wait_anim.empty()) { - LLPreviewGesture* pPreview = dynamic_cast(it->second); - if(pPreview) + for(const auto& pair : LLPreview::sInstances) { - pPreview->getChild("wait_anim_check")->getLabel(); - break; + const auto& pPreview(pair.second); + if (pPreview && pPreview->getTitleName() == "Gesture") + { + wait_anim = pPreview->getChild("wait_anim_check")->getLabel(); + break; + } } } - + action = wait_anim; } result.append(action); return result; @@ -1716,13 +1667,14 @@ void LLPreviewGesture::onClickDelete() void LLPreviewGesture::onCommitActive() { - if (!LLGestureMgr::instance().isGestureActive(mItemUUID)) + auto& inst(LLGestureMgr::instance()); + if (!inst.isGestureActive(mItemUUID)) { - LLGestureMgr::instance().activateGesture(mItemUUID); + inst.activateGesture(mItemUUID); } else { - LLGestureMgr::instance().deactivateGesture(mItemUUID); + inst.deactivateGesture(mItemUUID); } // Make sure the (active) label in the inventory gets updated. @@ -1773,7 +1725,7 @@ void LLPreviewGesture::onDonePreview(LLMultiGesture* gesture) mPreviewBtn->setLabel(getString("preview_txt")); delete mPreviewGesture; - mPreviewGesture = NULL; + mPreviewGesture = nullptr; refresh(); } diff --git a/indra/newview/llpreviewgesture.h b/indra/newview/llpreviewgesture.h index 7bb27063f..757d84308 100644 --- a/indra/newview/llpreviewgesture.h +++ b/indra/newview/llpreviewgesture.h @@ -113,7 +113,7 @@ protected: // "Sound", "Chat", or "Wait" LLScrollListItem* addStep(const enum EStepType step_type); - static std::string getLabel(std::vector labels); + static std::string getLabel(const std::vector& labels); static void updateLabel(LLScrollListItem* item); void onCommitSetDirty(); From f5492144ad07359bf57252081dadb5227aa90f5b Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Thu, 21 Mar 2019 22:01:13 -0400 Subject: [PATCH 011/110] Gesture Optimization Pass 2 --- indra/llcharacter/llmultigesture.cpp | 190 +++------- indra/llcharacter/llmultigesture.h | 80 ++-- indra/newview/llgesturemgr.cpp | 539 +++++++++++---------------- indra/newview/llgesturemgr.h | 39 +- 4 files changed, 338 insertions(+), 510 deletions(-) diff --git a/indra/llcharacter/llmultigesture.cpp b/indra/llcharacter/llmultigesture.cpp index 7fbb5c137..64de502b6 100644 --- a/indra/llcharacter/llmultigesture.cpp +++ b/indra/llcharacter/llmultigesture.cpp @@ -36,7 +36,7 @@ #include "lldatapacker.h" #include "llstl.h" -const S32 GESTURE_VERSION = 2; +constexpr S32 GESTURE_VERSION = 2; //--------------------------------------------------------------------------- // LLMultiGesture @@ -48,10 +48,10 @@ LLMultiGesture::LLMultiGesture() mTrigger(), mReplaceText(), mSteps(), - mPlaying(FALSE), + mPlaying(false), mLocal(false), mCurrentStep(0), - mDoneCallback(NULL) + mDoneCallback(nullptr) { reset(); } @@ -63,13 +63,13 @@ LLMultiGesture::~LLMultiGesture() void LLMultiGesture::reset() { - mPlaying = FALSE; + mPlaying = false; mLocal = false; mCurrentStep = 0; mWaitTimer.reset(); - mWaitingTimer = FALSE; - mWaitingAnimations = FALSE; - mWaitingAtEnd = FALSE; + mWaitingTimer = false; + mWaitingAnimations = false; + mWaitingAtEnd = false; mRequestedAnimIDs.clear(); mPlayingAnimIDs.clear(); } @@ -88,10 +88,8 @@ S32 LLMultiGesture::getMaxSerialSize() const max_size += 64; // step count S32 - std::vector::const_iterator it; - for (it = mSteps.begin(); it != mSteps.end(); ++it) + for (const auto& step : mSteps) { - LLGestureStep* step = *it; max_size += 64; // type S32 max_size += step->getMaxSerialSize(); } @@ -104,10 +102,8 @@ S32 LLMultiGesture::getMaxSerialSize() const max_size += sizeof(S32); // step count - std::vector::const_iterator it; - for (it = mSteps.begin(); it != mSteps.end(); ++it) + for (const auto& step : mSteps) { - LLGestureStep* step = *it; max_size += sizeof(S32); // type max_size += step->getMaxSerialSize(); } @@ -116,7 +112,7 @@ S32 LLMultiGesture::getMaxSerialSize() const return max_size; } -BOOL LLMultiGesture::serialize(LLDataPacker& dp) const +bool LLMultiGesture::serialize(LLDataPacker& dp) const { dp.packS32(GESTURE_VERSION, "version"); dp.packU8(mKey, "key"); @@ -126,22 +122,18 @@ BOOL LLMultiGesture::serialize(LLDataPacker& dp) const S32 count = (S32)mSteps.size(); dp.packS32(count, "step_count"); - S32 i; - for (i = 0; i < count; ++i) + for (const auto& step : mSteps) { - LLGestureStep* step = mSteps[i]; - dp.packS32(step->getType(), "step_type"); - BOOL ok = step->serialize(dp); - if (!ok) + if (!step->serialize(dp)) { - return FALSE; + return false; } } - return TRUE; + return true; } -BOOL LLMultiGesture::deserialize(LLDataPacker& dp) +bool LLMultiGesture::deserialize(LLDataPacker& dp) { S32 version; dp.unpackS32(version, "version"); @@ -150,15 +142,12 @@ BOOL LLMultiGesture::deserialize(LLDataPacker& dp) LL_WARNS() << "Bad LLMultiGesture version " << version << " should be " << GESTURE_VERSION << LL_ENDL; - return FALSE; + return false; } dp.unpackU8(mKey, "key"); dp.unpackU32(mMask, "mask"); - - dp.unpackString(mTrigger, "trigger"); - dp.unpackString(mReplaceText, "replace"); S32 count; @@ -166,58 +155,31 @@ BOOL LLMultiGesture::deserialize(LLDataPacker& dp) if (count < 0) { LL_WARNS() << "Bad LLMultiGesture step count " << count << LL_ENDL; - return FALSE; + return false; } - S32 i; - for (i = 0; i < count; ++i) + std::unique_ptr step; + for (S32 i = 0; i < count; ++i) { S32 type; dp.unpackS32(type, "step_type"); - EStepType step_type = (EStepType)type; - switch(step_type) + switch((EStepType)type) { - case STEP_ANIMATION: - { - std::unique_ptr step(new LLGestureStepAnimation()); - BOOL ok = step->deserialize(dp); - if (!ok) return FALSE; - mSteps.push_back(step.release()); - break; - } - case STEP_SOUND: - { - std::unique_ptr step(new LLGestureStepSound()); - BOOL ok = step->deserialize(dp); - if (!ok) return FALSE; - mSteps.push_back(step.release()); - break; - } - case STEP_CHAT: - { - std::unique_ptr step(new LLGestureStepChat()); - BOOL ok = step->deserialize(dp); - if (!ok) return FALSE; - mSteps.push_back(step.release()); - break; - } - case STEP_WAIT: - { - std::unique_ptr step(new LLGestureStepWait()); - BOOL ok = step->deserialize(dp); - if (!ok) return FALSE; - mSteps.push_back(step.release()); - break; - } + case STEP_ANIMATION: step.reset(new LLGestureStepAnimation); break; + case STEP_SOUND: step.reset(new LLGestureStepSound); break; + case STEP_CHAT: step.reset(new LLGestureStepChat); break; + case STEP_WAIT: step.reset(new LLGestureStepWait); break; default: { LL_WARNS() << "Bad LLMultiGesture step type " << type << LL_ENDL; - return FALSE; + return false; } } + if (!step->deserialize(dp)) return false; + mSteps.push_back(step.release()); } - return TRUE; + return true; } void LLMultiGesture::dump() @@ -226,10 +188,8 @@ void LLMultiGesture::dump() << " trigger " << mTrigger << " replace " << mReplaceText << LL_ENDL; - U32 i; - for (i = 0; i < mSteps.size(); ++i) + for (const auto& step : mSteps) { - LLGestureStep* step = mSteps[i]; step->dump(); } } @@ -264,21 +224,21 @@ S32 LLGestureStepAnimation::getMaxSerialSize() const return max_size; } -BOOL LLGestureStepAnimation::serialize(LLDataPacker& dp) const +bool LLGestureStepAnimation::serialize(LLDataPacker& dp) const { dp.packString(mAnimName, "anim_name"); dp.packUUID(mAnimAssetID, "asset_id"); dp.packU32(mFlags, "flags"); - return TRUE; + return true; } -BOOL LLGestureStepAnimation::deserialize(LLDataPacker& dp) +bool LLGestureStepAnimation::deserialize(LLDataPacker& dp) { dp.unpackString(mAnimName, "anim_name"); // Apparently an earlier version of the gesture code added \r to the end // of the animation names. Get rid of it. JC - if (!mAnimName.empty() && mAnimName[mAnimName.length() - 1] == '\r') + if (!mAnimName.empty() && mAnimName.back() == '\r') { // chop the last character mAnimName.resize(mAnimName.length() - 1); @@ -286,29 +246,18 @@ BOOL LLGestureStepAnimation::deserialize(LLDataPacker& dp) dp.unpackUUID(mAnimAssetID, "asset_id"); dp.unpackU32(mFlags, "flags"); - return TRUE; + return true; } // *NOTE: result is translated in LLPreviewGesture::getLabel() std::vector LLGestureStepAnimation::getLabel() const { - std::vector strings; - -// std::string label; +/* std::string label; if (mFlags & ANIM_FLAG_STOP) - { - strings.push_back( "AnimFlagStop"); - -// label = "Stop Animation: "; - } + label = "Stop Animation: "; else - { - strings.push_back( "AnimFlagStart"); - -// label = "Start Animation: "; - } - strings.push_back( mAnimName); -// label += mAnimName; - return strings; + label = "Start Animation: "; + label += mAnimName;*/ + return {mFlags & ANIM_FLAG_STOP ? "AnimFlagStop" : "AnimFlagStart", mAnimName}; } void LLGestureStepAnimation::dump() @@ -346,31 +295,28 @@ S32 LLGestureStepSound::getMaxSerialSize() const return max_size; } -BOOL LLGestureStepSound::serialize(LLDataPacker& dp) const +bool LLGestureStepSound::serialize(LLDataPacker& dp) const { dp.packString(mSoundName, "sound_name"); dp.packUUID(mSoundAssetID, "asset_id"); dp.packU32(mFlags, "flags"); - return TRUE; + return true; } -BOOL LLGestureStepSound::deserialize(LLDataPacker& dp) +bool LLGestureStepSound::deserialize(LLDataPacker& dp) { dp.unpackString(mSoundName, "sound_name"); dp.unpackUUID(mSoundAssetID, "asset_id"); dp.unpackU32(mFlags, "flags"); - return TRUE; + return true; } // *NOTE: result is translated in LLPreviewGesture::getLabel() std::vector LLGestureStepSound::getLabel() const { - std::vector strings; - strings.push_back( "Sound"); - strings.push_back( mSoundName); // std::string label("Sound: "); // label += mSoundName; - return strings; + return {"Sound", mSoundName}; } void LLGestureStepSound::dump() @@ -406,27 +352,23 @@ S32 LLGestureStepChat::getMaxSerialSize() const return max_size; } -BOOL LLGestureStepChat::serialize(LLDataPacker& dp) const +bool LLGestureStepChat::serialize(LLDataPacker& dp) const { dp.packString(mChatText, "chat_text"); dp.packU32(mFlags, "flags"); - return TRUE; + return true; } -BOOL LLGestureStepChat::deserialize(LLDataPacker& dp) +bool LLGestureStepChat::deserialize(LLDataPacker& dp) { dp.unpackString(mChatText, "chat_text"); - dp.unpackU32(mFlags, "flags"); - return TRUE; + return true; } // *NOTE: result is translated in LLPreviewGesture::getLabel() std::vector LLGestureStepChat::getLabel() const { - std::vector strings; - strings.push_back("Chat"); - strings.push_back(mChatText); - return strings; + return {"Chat", mChatText}; } void LLGestureStepChat::dump() @@ -461,44 +403,26 @@ S32 LLGestureStepWait::getMaxSerialSize() const return max_size; } -BOOL LLGestureStepWait::serialize(LLDataPacker& dp) const +bool LLGestureStepWait::serialize(LLDataPacker& dp) const { dp.packF32(mWaitSeconds, "wait_seconds"); dp.packU32(mFlags, "flags"); - return TRUE; + return true; } -BOOL LLGestureStepWait::deserialize(LLDataPacker& dp) +bool LLGestureStepWait::deserialize(LLDataPacker& dp) { dp.unpackF32(mWaitSeconds, "wait_seconds"); dp.unpackU32(mFlags, "flags"); - return TRUE; + return true; } // *NOTE: result is translated in LLPreviewGesture::getLabel() std::vector LLGestureStepWait::getLabel() const { - std::vector strings; - strings.push_back( "Wait" ); - -// std::string label("--- Wait: "); - if (mFlags & WAIT_FLAG_TIME) - { - char buffer[64]; /* Flawfinder: ignore */ - snprintf(buffer, sizeof(buffer), "%.1f seconds", (double)mWaitSeconds); /* Flawfinder: ignore */ - strings.push_back(buffer); -// label += buffer; - } - else if (mFlags & WAIT_FLAG_ALL_ANIM) - { - strings.push_back("until animations are done"); - // label += "until animations are done"; - } - else - { - strings.push_back(""); - } - - return strings; + return {"Wait", + mFlags & WAIT_FLAG_TIME ? llformat("%.1f seconds", mWaitSeconds) + : mFlags & WAIT_FLAG_ALL_ANIM ? "until animations are done" + : LLStringUtil::null}; } diff --git a/indra/llcharacter/llmultigesture.h b/indra/llcharacter/llmultigesture.h index 8e4821357..e7a5fda15 100644 --- a/indra/llcharacter/llmultigesture.h +++ b/indra/llcharacter/llmultigesture.h @@ -27,7 +27,7 @@ #ifndef LL_LLMULTIGESTURE_H #define LL_LLMULTIGESTURE_H -#include +#include #include #include @@ -46,8 +46,8 @@ public: // Maximum number of bytes this could hold once serialized. S32 getMaxSerialSize() const; - BOOL serialize(LLDataPacker& dp) const; - BOOL deserialize(LLDataPacker& dp); + bool serialize(LLDataPacker& dp) const; + bool deserialize(LLDataPacker& dp); void dump(); @@ -77,7 +77,7 @@ public: std::vector mSteps; // Is the gesture currently playing? - BOOL mPlaying; + bool mPlaying; // Is the gesture to be played locally? bool mLocal; @@ -86,25 +86,25 @@ public: S32 mCurrentStep; // We're waiting for triggered animations to stop playing - BOOL mWaitingAnimations; + bool mWaitingAnimations; // We're waiting a fixed amount of time - BOOL mWaitingTimer; + bool mWaitingTimer; // Waiting after the last step played for all animations to complete - BOOL mWaitingAtEnd; + bool mWaitingAtEnd; // Timer for waiting LLFrameTimer mWaitTimer; - boost::function mDoneCallback; + std::function mDoneCallback; // Animations that we requested to start - std::set mRequestedAnimIDs; + std::unordered_set mRequestedAnimIDs; // Once the animation starts playing (sim says to start playing) // the ID is moved from mRequestedAnimIDs to here. - std::set mPlayingAnimIDs; + std::unordered_set mPlayingAnimIDs; }; @@ -127,14 +127,14 @@ public: LLGestureStep() {} virtual ~LLGestureStep() {} - virtual EStepType getType() = 0; + virtual EStepType getType() const = 0; // Return a user-readable label for this step virtual std::vector getLabel() const = 0; virtual S32 getMaxSerialSize() const = 0; - virtual BOOL serialize(LLDataPacker& dp) const = 0; - virtual BOOL deserialize(LLDataPacker& dp) = 0; + virtual bool serialize(LLDataPacker& dp) const = 0; + virtual bool deserialize(LLDataPacker& dp) = 0; virtual void dump() = 0; }; @@ -142,7 +142,7 @@ public: // By default, animation steps start animations. // If the least significant bit is 1, it will stop animations. -const U32 ANIM_FLAG_STOP = 0x01; +constexpr U32 ANIM_FLAG_STOP = 0x01; class LLGestureStepAnimation : public LLGestureStep { @@ -150,15 +150,15 @@ public: LLGestureStepAnimation(); virtual ~LLGestureStepAnimation(); - virtual EStepType getType() { return STEP_ANIMATION; } + EStepType getType() const override { return STEP_ANIMATION; } - virtual std::vector getLabel() const; + std::vector getLabel() const override; - virtual S32 getMaxSerialSize() const; - virtual BOOL serialize(LLDataPacker& dp) const; - virtual BOOL deserialize(LLDataPacker& dp); + S32 getMaxSerialSize() const override; + bool serialize(LLDataPacker& dp) const override; + bool deserialize(LLDataPacker& dp) override; - virtual void dump(); + void dump() override; public: std::string mAnimName; @@ -173,15 +173,15 @@ public: LLGestureStepSound(); virtual ~LLGestureStepSound(); - virtual EStepType getType() { return STEP_SOUND; } + EStepType getType() const override { return STEP_SOUND; } - virtual std::vector getLabel() const; + std::vector getLabel() const override; - virtual S32 getMaxSerialSize() const; - virtual BOOL serialize(LLDataPacker& dp) const; - virtual BOOL deserialize(LLDataPacker& dp); + S32 getMaxSerialSize() const override; + bool serialize(LLDataPacker& dp) const override; + bool deserialize(LLDataPacker& dp) override; - virtual void dump(); + void dump() override; public: std::string mSoundName; @@ -196,15 +196,15 @@ public: LLGestureStepChat(); virtual ~LLGestureStepChat(); - virtual EStepType getType() { return STEP_CHAT; } + EStepType getType() const override { return STEP_CHAT; } - virtual std::vector getLabel() const; + std::vector getLabel() const override; - virtual S32 getMaxSerialSize() const; - virtual BOOL serialize(LLDataPacker& dp) const; - virtual BOOL deserialize(LLDataPacker& dp); + S32 getMaxSerialSize() const override; + bool serialize(LLDataPacker& dp) const override; + bool deserialize(LLDataPacker& dp) override; - virtual void dump(); + void dump() override; public: std::string mChatText; @@ -212,8 +212,8 @@ public: }; -const U32 WAIT_FLAG_TIME = 0x01; -const U32 WAIT_FLAG_ALL_ANIM = 0x02; +constexpr U32 WAIT_FLAG_TIME = 0x01; +constexpr U32 WAIT_FLAG_ALL_ANIM = 0x02; class LLGestureStepWait : public LLGestureStep { @@ -221,15 +221,15 @@ public: LLGestureStepWait(); virtual ~LLGestureStepWait(); - virtual EStepType getType() { return STEP_WAIT; } + EStepType getType() const override { return STEP_WAIT; } - virtual std::vector getLabel() const; + std::vector getLabel() const override; - virtual S32 getMaxSerialSize() const; - virtual BOOL serialize(LLDataPacker& dp) const; - virtual BOOL deserialize(LLDataPacker& dp); + S32 getMaxSerialSize() const override; + bool serialize(LLDataPacker& dp) const override; + bool deserialize(LLDataPacker& dp) override; - virtual void dump(); + void dump() override; public: F32 mWaitSeconds; diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 1d821e3f8..22eaccd1a 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -69,7 +69,7 @@ const F32 MAX_WAIT_ANIM_SECS = 30.f; // Lightweight constructor. // init() does the heavy lifting. LLGestureMgr::LLGestureMgr() -: mValid(FALSE), +: mValid(false), mPlaying(), mActive(), mLoadingCount(0) @@ -87,7 +87,7 @@ LLGestureMgr::~LLGestureMgr() LLMultiGesture* gesture = (*it).second; delete gesture; - gesture = NULL; + gesture = nullptr; } gInventory.removeObserver(this); } @@ -148,86 +148,64 @@ void LLGestureMgr::activateGesture(const LLUUID& item_id) mLoadingCount = 1; mDeactivateSimilarNames.clear(); - const BOOL inform_server = TRUE; - const BOOL deactivate_similar = FALSE; + const bool inform_server = true; + const bool deactivate_similar = false; activateGestureWithAsset(item_id, asset_id, inform_server, deactivate_similar); } void LLGestureMgr::activateGestures(LLViewerInventoryItem::item_array_t& items) { - // Load up the assets - S32 count = 0; - LLViewerInventoryItem::item_array_t::const_iterator it; - for (it = items.begin(); it != items.end(); ++it) - { - LLViewerInventoryItem* item = *it; - - if (isGestureActive(item->getUUID())) - { - continue; - } - else - { // Make gesture active and persistent through login sessions. -Aura 07-12-06 - activateGesture(item->getUUID()); - } - - count++; - } - - mLoadingCount = count; mDeactivateSimilarNames.clear(); - for (it = items.begin(); it != items.end(); ++it) - { - LLViewerInventoryItem* item = *it; - - if (isGestureActive(item->getUUID())) - { - continue; - } - - // Don't inform server, we'll do that in bulk - const BOOL no_inform_server = FALSE; - const BOOL deactivate_similar = TRUE; - activateGestureWithAsset(item->getUUID(), item->getAssetUUID(), - no_inform_server, - deactivate_similar); - } + // Load up the assets + mLoadingCount = 0; // Inform the database of this change LLMessageSystem* msg = gMessageSystem; + bool start_message = true; - BOOL start_message = TRUE; - - for (it = items.begin(); it != items.end(); ++it) + for (const auto& item : items) { - LLViewerInventoryItem* item = *it; - - if (isGestureActive(item->getUUID())) + const auto& id = item->getUUID(); + if (isGestureActive(id)) { continue; } + // Make gesture active and persistent through login sessions. -Aura 07-12-06 + activateGesture(id); + + ++mLoadingCount; + + const auto& asset_id = item->getAssetUUID(); + + // Don't inform server, we'll do that in bulk + const bool no_inform_server = false; + const bool deactivate_similar = true; + activateGestureWithAsset(id, asset_id, + no_inform_server, + deactivate_similar); + if (start_message) { msg->newMessage("ActivateGestures"); msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); + msg->addUUID("AgentID", gAgentID); msg->addUUID("SessionID", gAgent.getSessionID()); msg->addU32("Flags", 0x0); - start_message = FALSE; + start_message = false; } msg->nextBlock("Data"); - msg->addUUID("ItemID", item->getUUID()); - msg->addUUID("AssetID", item->getAssetUUID()); + msg->addUUID("ItemID", id); + msg->addUUID("AssetID", asset_id); msg->addU32("GestureFlags", 0x0); if (msg->getCurrentSendTotal() > MTUBYTES) { gAgent.sendReliableMessage(); - start_message = TRUE; + start_message = true; } } @@ -241,8 +219,8 @@ void LLGestureMgr::activateGestures(LLViewerInventoryItem::item_array_t& items) struct LLLoadInfo { LLUUID mItemID; - BOOL mInformServer; - BOOL mDeactivateSimilar; + bool mInformServer; + bool mDeactivateSimilar; }; // If inform_server is true, will send a message upstream to update @@ -252,8 +230,8 @@ struct LLLoadInfo */ void LLGestureMgr::activateGestureWithAsset(const LLUUID& item_id, const LLUUID& asset_id, - BOOL inform_server, - BOOL deactivate_similar) + bool inform_server, + bool deactivate_similar) { const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); @@ -275,9 +253,9 @@ void LLGestureMgr::activateGestureWithAsset(const LLUUID& item_id, // return; // } - // For now, put NULL into the item map. We'll build a gesture + // For now, put nullptr into the item map. We'll build a gesture // class object when the asset data arrives. - mActive[base_item_id] = NULL; + mActive[base_item_id] = nullptr; // Copy the UUID if (asset_id.notNull()) @@ -287,7 +265,7 @@ void LLGestureMgr::activateGestureWithAsset(const LLUUID& item_id, info->mInformServer = inform_server; info->mDeactivateSimilar = deactivate_similar; - const BOOL high_priority = TRUE; + const bool high_priority = true; gAssetStorage->getAssetData(asset_id, LLAssetType::AT_GESTURE, onLoadComplete, @@ -304,7 +282,7 @@ void LLGestureMgr::activateGestureWithAsset(const LLUUID& item_id, void LLGestureMgr::deactivateGesture(const LLUUID& item_id) { const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); - item_map_t::iterator it = mActive.find(base_item_id); + const auto& it = mActive.find(base_item_id); if (it == mActive.end()) { LL_WARNS() << "deactivateGesture for inactive gesture " << base_item_id << LL_ENDL; @@ -314,13 +292,13 @@ void LLGestureMgr::deactivateGesture(const LLUUID& item_id) // mActive owns this gesture pointer, so clean up memory. LLMultiGesture* gesture = (*it).second; - // Can be NULL gestures in the map + // Can be nullptr gestures in the map if (gesture) { stopGesture(gesture); delete gesture; - gesture = NULL; + gesture = nullptr; } mActive.erase(it); @@ -330,7 +308,7 @@ void LLGestureMgr::deactivateGesture(const LLUUID& item_id) LLMessageSystem* msg = gMessageSystem; msg->newMessage("DeactivateGestures"); msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); + msg->addUUID("AgentID", gAgentID); msg->addUUID("SessionID", gAgent.getSessionID()); msg->addU32("Flags", 0x0); @@ -346,14 +324,16 @@ void LLGestureMgr::deactivateGesture(const LLUUID& item_id) } -void LLGestureMgr::deactivateSimilarGestures(LLMultiGesture* in, const LLUUID& in_item_id) +void LLGestureMgr::deactivateSimilarGestures(const LLMultiGesture* in, const LLUUID& in_item_id) { const LLUUID& base_in_item_id = gInventory.getLinkedItemID(in_item_id); - uuid_vec_t gest_item_ids; + + // Inform database of the change + LLMessageSystem* msg = gMessageSystem; + bool start_message = true; // Deactivate all gestures that match - item_map_t::iterator it; - for (it = mActive.begin(); it != mActive.end(); ) + for (auto& it = mActive.begin(); it != mActive.end(); ) { const LLUUID& item_id = (*it).first; LLMultiGesture* gest = (*it).second; @@ -368,16 +348,37 @@ void LLGestureMgr::deactivateSimilarGestures(LLMultiGesture* in, const LLUUID& i else if ((!gest->mTrigger.empty() && gest->mTrigger == in->mTrigger) || (gest->mKey != KEY_NONE && gest->mKey == in->mKey && gest->mMask == in->mMask)) { - gest_item_ids.push_back(item_id); - stopGesture(gest); delete gest; - gest = NULL; + gest = nullptr; - mActive.erase(it++); + it = mActive.erase(it); gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); + if (start_message) + { + msg->newMessage("DeactivateGestures"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgentID); + msg->addUUID("SessionID", gAgent.getSessionID()); + msg->addU32("Flags", 0x0); + start_message = false; + } + + msg->nextBlock("Data"); + msg->addUUID("ItemID", item_id); + msg->addU32("GestureFlags", 0x0); + + if (msg->getCurrentSendTotal() > MTUBYTES) + { + gAgent.sendReliableMessage(); + start_message = true; + } + + // Add to the list of names for the user. + if (const auto& item = gInventory.getItem(item_id)) + mDeactivateSimilarNames += item->getName() + '\n'; } else { @@ -385,88 +386,45 @@ void LLGestureMgr::deactivateSimilarGestures(LLMultiGesture* in, const LLUUID& i } } - // Inform database of the change - LLMessageSystem* msg = gMessageSystem; - BOOL start_message = TRUE; - uuid_vec_t::const_iterator vit = gest_item_ids.begin(); - while (vit != gest_item_ids.end()) - { - if (start_message) - { - msg->newMessage("DeactivateGestures"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); - msg->addUUID("SessionID", gAgent.getSessionID()); - msg->addU32("Flags", 0x0); - start_message = FALSE; - } - - msg->nextBlock("Data"); - msg->addUUID("ItemID", *vit); - msg->addU32("GestureFlags", 0x0); - - if (msg->getCurrentSendTotal() > MTUBYTES) - { - gAgent.sendReliableMessage(); - start_message = TRUE; - } - - ++vit; - } - if (!start_message) { gAgent.sendReliableMessage(); } - // Add to the list of names for the user. - for (vit = gest_item_ids.begin(); vit != gest_item_ids.end(); ++vit) - { - LLViewerInventoryItem* item = gInventory.getItem(*vit); - if (!item) continue; - - mDeactivateSimilarNames.append(item->getName()); - mDeactivateSimilarNames.append("\n"); - } - + // *TODO: We call notify observers in stopGesture above, should we pass a flag to only do that here? notifyObservers(); } -BOOL LLGestureMgr::isGestureActive(const LLUUID& item_id) +bool LLGestureMgr::isGestureActive(const LLUUID& item_id) const { const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); - item_map_t::iterator it = mActive.find(base_item_id); + const auto& it = mActive.find(base_item_id); return (it != mActive.end()); } -BOOL LLGestureMgr::isGesturePlaying(const LLUUID& item_id) +bool LLGestureMgr::isGesturePlaying(const LLUUID& item_id) const { const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); - item_map_t::iterator it = mActive.find(base_item_id); - if (it == mActive.end()) return FALSE; + const auto& it = mActive.find(base_item_id); + if (it == mActive.end()) return false; - LLMultiGesture* gesture = (*it).second; - if (!gesture) return FALSE; + const LLMultiGesture* gesture = (*it).second; + if (!gesture) return false; return gesture->mPlaying; } -BOOL LLGestureMgr::isGesturePlaying(LLMultiGesture* gesture) +bool LLGestureMgr::isGesturePlaying(const LLMultiGesture* gesture) const { - if(!gesture) - { - return FALSE; - } - - return gesture->mPlaying; + return gesture && gesture->mPlaying; } void LLGestureMgr::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_gesture, const LLUUID& asset_id) { const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); - item_map_t::iterator it = mActive.find(base_item_id); + const auto& it = mActive.find(base_item_id); if (it == mActive.end()) { LL_WARNS() << "replaceGesture for inactive gesture " << base_item_id << LL_ENDL; @@ -481,7 +439,7 @@ void LLGestureMgr::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_ges mActive[base_item_id] = new_gesture; delete old_gesture; - old_gesture = NULL; + old_gesture = nullptr; if (asset_id.notNull()) { @@ -490,10 +448,10 @@ void LLGestureMgr::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_ges LLLoadInfo* info = new LLLoadInfo; info->mItemID = base_item_id; - info->mInformServer = TRUE; - info->mDeactivateSimilar = FALSE; + info->mInformServer = true; + info->mDeactivateSimilar = false; - const BOOL high_priority = TRUE; + const bool high_priority = true; gAssetStorage->getAssetData(asset_id, LLAssetType::AT_GESTURE, onLoadComplete, @@ -508,7 +466,7 @@ void LLGestureMgr::replaceGesture(const LLUUID& item_id, const LLUUID& new_asset { const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); - item_map_t::iterator it = LLGestureMgr::instance().mActive.find(base_item_id); + auto it = LLGestureMgr::instance().mActive.find(base_item_id); if (it == mActive.end()) { LL_WARNS() << "replaceGesture for inactive gesture " << base_item_id << LL_ENDL; @@ -528,7 +486,7 @@ void LLGestureMgr::playGesture(LLMultiGesture* gesture, bool local) gesture->mCurrentStep = 0; // Add to list of playing - gesture->mPlaying = TRUE; + gesture->mPlaying = true; gesture->mLocal = local; mPlaying.push_back(gesture); @@ -565,7 +523,7 @@ void LLGestureMgr::playGesture(LLMultiGesture* gesture, bool local) LLAssetType::AT_ANIMATION, onAssetLoadComplete, (void *)id, - TRUE); + true); } break; } @@ -581,8 +539,8 @@ void LLGestureMgr::playGesture(LLMultiGesture* gesture, bool local) gAssetStorage->getAssetData(sound_id, LLAssetType::AT_SOUND, onAssetLoadComplete, - NULL, - TRUE); + nullptr, + true); } break; } @@ -624,12 +582,12 @@ void LLGestureMgr::playGesture(const LLUUID& item_id, bool local) // Iterates through space delimited tokens in string, triggering any gestures found. // Generates a revised string that has the found tokens replaced by their replacement strings // and (as a minor side effect) has multiple spaces in a row replaced by single spaces. -BOOL LLGestureMgr::triggerAndReviseString(const std::string &utf8str, std::string* revised_string) +bool LLGestureMgr::triggerAndReviseString(const std::string &utf8str, std::string* revised_string) { std::string tokenized = utf8str; - BOOL found_gestures = FALSE; - BOOL first_token = TRUE; + bool found_gestures = false; + bool first_token = true; typedef boost::tokenizer > tokenizer; boost::char_separator sep(" "); @@ -639,17 +597,16 @@ BOOL LLGestureMgr::triggerAndReviseString(const std::string &utf8str, std::strin for( token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter) { const char* cur_token = token_iter->c_str(); - LLMultiGesture* gesture = NULL; + LLMultiGesture* gesture = nullptr; // Only pay attention to the first gesture in the string. if( !found_gestures ) { // collect gestures that match std::vector matching; - item_map_t::iterator it; - for (it = mActive.begin(); it != mActive.end(); ++it) + for (const auto& pair : mActive) { - gesture = (*it).second; + gesture = pair.second; // Gesture asset data might not have arrived yet if (!gesture) continue; @@ -659,7 +616,7 @@ BOOL LLGestureMgr::triggerAndReviseString(const std::string &utf8str, std::strin matching.push_back(gesture); } - gesture = NULL; + gesture = nullptr; } @@ -673,59 +630,43 @@ BOOL LLGestureMgr::triggerAndReviseString(const std::string &utf8str, std::strin playGesture(gesture); - if (!gesture->mReplaceText.empty()) + if (revised_string && !gesture->mReplaceText.empty()) { - if( !first_token ) - { - if (revised_string) - revised_string->append( " " ); - } + if (!first_token) revised_string->push_back(' '); // Don't muck with the user's capitalization if we don't have to. - if( LLStringUtil::compareInsensitive(cur_token, gesture->mReplaceText) == 0) - { - if (revised_string) - revised_string->append( cur_token ); - } - else - { - if (revised_string) - revised_string->append( gesture->mReplaceText ); - } + revised_string->append(LLStringUtil::compareInsensitive(cur_token, gesture->mReplaceText) == 0 ? + cur_token : gesture->mReplaceText); } - found_gestures = TRUE; + found_gestures = true; } } } - if(!gesture) + if (!gesture && revised_string) { // This token doesn't match a gesture. Pass it through to the output. - if( !first_token ) - { - if (revised_string) - revised_string->append( " " ); - } - if (revised_string) - revised_string->append( cur_token ); + if (!first_token) revised_string->push_back(' '); + revised_string->append(cur_token); } - first_token = FALSE; - gesture = NULL; + first_token = false; + gesture = nullptr; } return found_gestures; } -BOOL LLGestureMgr::triggerGesture(KEY key, MASK mask) +bool LLGestureMgr::triggerGesture(KEY key, MASK mask) { - std::vector matching; - item_map_t::iterator it; + if (mActive.empty()) return false; + + std::vector matching; // collect matching gestures - for (it = mActive.begin(); it != mActive.end(); ++it) + for (const auto& pair : mActive) { - LLMultiGesture* gesture = (*it).second; + LLMultiGesture* gesture = pair.second; // asset data might not have arrived yet if (!gesture) continue; @@ -738,16 +679,13 @@ BOOL LLGestureMgr::triggerGesture(KEY key, MASK mask) } // choose one and play it - if (matching.size() > 0) + const auto& count = matching.size(); + if (count > 0) { - U32 random = ll_rand(matching.size()); - - LLMultiGesture* gesture = matching[random]; - - playGesture(gesture); - return TRUE; + playGesture(matching[ll_rand(count)]); + return true; } - return FALSE; + return false; } @@ -761,49 +699,38 @@ struct IsGesturePlaying : public std::unary_function { bool operator()(const LLMultiGesture* gesture) const { - return gesture->mPlaying ? true : false; + return gesture->mPlaying; } }; void LLGestureMgr::update() { - S32 i; - for (i = 0; i < (S32)mPlaying.size(); ++i) + bool notify = false; + for (auto& it = mPlaying.begin(); it != mPlaying.end();) { - stepGesture(mPlaying[i]); - } - - // Clear out gestures that are done, by moving all the - // ones that are still playing to the front. - std::vector::iterator new_end; - new_end = std::partition(mPlaying.begin(), - mPlaying.end(), - IsGesturePlaying()); - - // Something finished playing - if (new_end != mPlaying.end()) - { - // Delete the completed gestures that want deletion - std::vector::iterator it; - for (it = new_end; it != mPlaying.end(); ++it) + auto& gesture = *it; + stepGesture(gesture); + if (!gesture->mPlaying) { - LLMultiGesture* gesture = *it; - + // Delete the completed gestures that want deletion if (gesture->mDoneCallback) { gesture->mDoneCallback(gesture); // callback might have deleted gesture, can't // rely on this pointer any more - gesture = NULL; + gesture = nullptr; } + + // And take done gesture out of the playing list + it = mPlaying.erase(it); + notify = true; } - - // And take done gestures out of the playing list - mPlaying.erase(new_end, mPlaying.end()); - - notifyObservers(); + else ++it; } + + // Something finished playing + if (notify) notifyObservers(); } @@ -818,22 +745,21 @@ void LLGestureMgr::stepGesture(LLMultiGesture* gesture) // Of the ones that started playing, have any stopped? - std::set::iterator gest_it; - for (gest_it = gesture->mPlayingAnimIDs.begin(); - gest_it != gesture->mPlayingAnimIDs.end(); - ) + const auto& signaled(gAgentAvatarp->mSignaledAnimations); + const auto& signaled_end(signaled.end()); + for (auto gest_it = gesture->mPlayingAnimIDs.begin(), end = gesture->mPlayingAnimIDs.end(); gest_it != end;) { if (gesture->mLocal) { // Local, erase if no longer playing (or gone) LLMotion* motion = gAgentAvatarp->findMotion(*gest_it); if (!motion || motion->isStopped()) - gesture->mPlayingAnimIDs.erase(gest_it); - ++gest_it; + gest_it = gesture->mPlayingAnimIDs.erase(gest_it); + else ++gest_it; } // look in signaled animations (simulator's view of what is // currently playing. - else if (gAgentAvatarp->mSignaledAnimations.find(*gest_it) != gAgentAvatarp->mSignaledAnimations.end()) + else if (signaled.find(*gest_it) != signaled_end) { ++gest_it; } @@ -841,23 +767,20 @@ void LLGestureMgr::stepGesture(LLMultiGesture* gesture) { // not found, so not currently playing or scheduled to play // delete from the triggered set - gesture->mPlayingAnimIDs.erase(gest_it++); + gest_it = gesture->mPlayingAnimIDs.erase(gest_it); } } // Of all the animations that we asked the sim to start for us, // pick up the ones that have actually started. - for (gest_it = gesture->mRequestedAnimIDs.begin(); - gest_it != gesture->mRequestedAnimIDs.end(); - ) + for (auto gest_it = gesture->mRequestedAnimIDs.begin(), end = gesture->mRequestedAnimIDs.end(); gest_it != end;) { - LLVOAvatar::AnimIterator play_it = gAgentAvatarp->mSignaledAnimations.find(*gest_it); - if (play_it != gAgentAvatarp->mSignaledAnimations.end()) + if (signaled.find(*gest_it) != signaled_end) { // Hooray, this animation has started playing! // Copy into playing. gesture->mPlayingAnimIDs.insert(*gest_it); - gesture->mRequestedAnimIDs.erase(gest_it++); + gest_it = gesture->mRequestedAnimIDs.erase(gest_it); } else { @@ -867,21 +790,21 @@ void LLGestureMgr::stepGesture(LLMultiGesture* gesture) } // Run the current steps - BOOL waiting = FALSE; + bool waiting = false; while (!waiting && gesture->mPlaying) { // Get the current step, if there is one. // Otherwise enter the waiting at end state. - LLGestureStep* step = NULL; + LLGestureStep* step = nullptr; if (gesture->mCurrentStep < (S32)gesture->mSteps.size()) { step = gesture->mSteps[gesture->mCurrentStep]; - llassert(step != NULL); + llassert(step != nullptr); } else { // step stays null, we're off the end - gesture->mWaitingAtEnd = TRUE; + gesture->mWaitingAtEnd = true; } @@ -896,12 +819,12 @@ void LLGestureMgr::stepGesture(LLMultiGesture* gesture) && gesture->mPlayingAnimIDs.empty())) { // all animations are done playing - gesture->mWaitingAtEnd = FALSE; - gesture->mPlaying = FALSE; + gesture->mWaitingAtEnd = false; + gesture->mPlaying = false; } else { - waiting = TRUE; + waiting = true; } continue; } @@ -916,20 +839,20 @@ void LLGestureMgr::stepGesture(LLMultiGesture* gesture) && gesture->mPlayingAnimIDs.empty())) { // all animations are done playing - gesture->mWaitingAnimations = FALSE; - gesture->mCurrentStep++; + gesture->mWaitingAnimations = false; + ++gesture->mCurrentStep; } else if (gesture->mWaitTimer.getElapsedTimeF32() > MAX_WAIT_ANIM_SECS) { // we've waited too long for an animation LL_INFOS() << "Waited too long for animations to stop, continuing gesture." << LL_ENDL; - gesture->mWaitingAnimations = FALSE; - gesture->mCurrentStep++; + gesture->mWaitingAnimations = false; + ++gesture->mCurrentStep; } else { - waiting = TRUE; + waiting = true; } continue; } @@ -945,13 +868,13 @@ void LLGestureMgr::stepGesture(LLMultiGesture* gesture) if (elapsed > wait_step->mWaitSeconds) { // wait is done, continue execution - gesture->mWaitingTimer = FALSE; - gesture->mCurrentStep++; + gesture->mWaitingTimer = false; + ++gesture->mCurrentStep; } else { // we're waiting, so execution is done for now - waiting = TRUE; + waiting = true; } continue; } @@ -971,7 +894,7 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step) LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step; if (anim_step->mAnimAssetID.isNull()) { - gesture->mCurrentStep++; + ++gesture->mCurrentStep; } if (anim_step->mFlags & ANIM_FLAG_STOP) @@ -984,7 +907,7 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step) { gAgent.sendAnimationRequest(anim_step->mAnimAssetID, ANIM_REQUEST_STOP); // remove it from our request set in case we just requested it - std::set::iterator set_it = gesture->mRequestedAnimIDs.find(anim_step->mAnimAssetID); + auto& set_it = gesture->mRequestedAnimIDs.find(anim_step->mAnimAssetID); if (set_it != gesture->mRequestedAnimIDs.end()) { gesture->mRequestedAnimIDs.erase(set_it); @@ -1008,38 +931,37 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step) gesture->mRequestedAnimIDs.insert(anim_step->mAnimAssetID); } } - gesture->mCurrentStep++; + ++gesture->mCurrentStep; break; } case STEP_SOUND: { LLGestureStepSound* sound_step = (LLGestureStepSound*)step; const LLUUID& sound_id = sound_step->mSoundAssetID; - const F32 volume = 1.f; + constexpr F32 volume = 1.f; if (gesture->mLocal) gAudiop->triggerSound(sound_id, gAgentID, volume, LLAudioEngine::AUDIO_TYPE_UI, gAgent.getPositionGlobal()); else send_sound_trigger(sound_id, volume); - gesture->mCurrentStep++; + ++gesture->mCurrentStep; break; } case STEP_CHAT: { LLGestureStepChat* chat_step = (LLGestureStepChat*)step; - std::string chat_text = chat_step->mChatText; + const std::string& chat_text = chat_step->mChatText; // Don't animate the nodding, as this might not blend with // other playing animations. - const BOOL animate = FALSE; - - if ( cmd_line_chat(chat_text, CHAT_TYPE_NORMAL)) + constexpr bool animate = false; + if (cmd_line_chat(chat_text, CHAT_TYPE_NORMAL)) { #if SHY_MOD //Command handler if(!SHCommandHandler::handleCommand(true, chat_text, gAgentID, gAgentAvatarp))//returns true if handled #endif //shy_mod gesture->mLocal ? fake_local_chat(chat_text) : gChatBar->sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate); } - gesture->mCurrentStep++; + ++gesture->mCurrentStep; break; } case STEP_WAIT: @@ -1047,19 +969,19 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step) LLGestureStepWait* wait_step = (LLGestureStepWait*)step; if (wait_step->mFlags & WAIT_FLAG_TIME) { - gesture->mWaitingTimer = TRUE; + gesture->mWaitingTimer = true; gesture->mWaitTimer.reset(); } else if (wait_step->mFlags & WAIT_FLAG_ALL_ANIM) { - gesture->mWaitingAnimations = TRUE; + gesture->mWaitingAnimations = true; // Use the wait timer as a deadlock breaker for animation // waits. gesture->mWaitTimer.reset(); } else { - gesture->mCurrentStep++; + ++gesture->mCurrentStep; } // Don't increment instruction pointer until wait is complete. break; @@ -1080,32 +1002,29 @@ void LLGestureMgr::onLoadComplete(LLVFS *vfs, { LLLoadInfo* info = (LLLoadInfo*)user_data; - LLUUID item_id = info->mItemID; - BOOL inform_server = info->mInformServer; - BOOL deactivate_similar = info->mDeactivateSimilar; + const LLUUID& item_id = info->mItemID; + const bool& inform_server = info->mInformServer; + const bool& deactivate_similar = info->mDeactivateSimilar; delete info; - info = NULL; + info = nullptr; LLGestureMgr& self = LLGestureMgr::instance(); - self.mLoadingCount--; + --self.mLoadingCount; if (0 == status) { LLVFile file(vfs, asset_uuid, type, LLVFile::READ); S32 size = file.getSize(); - std::vector buffer(size+1); - + // ensure there's a trailing nullptr so strlen will work. + std::vector buffer(size+1, '\0'); file.read((U8*)&buffer[0], size); - // ensure there's a trailing NULL so strlen will work. - buffer[size] = '\0'; LLMultiGesture* gesture = new LLMultiGesture(); LLDataPackerAsciiBuffer dp(&buffer[0], size+1); - BOOL ok = gesture->deserialize(dp); - if (ok) + if (gesture->deserialize(dp)) { if (deactivate_similar) { @@ -1155,7 +1074,7 @@ void LLGestureMgr::onLoadComplete(LLVFS *vfs, gAgent.sendReliableMessage(); } - callback_map_t::iterator i_cb = self.mCallbackMap.find(item_id); + auto& i_cb = self.mCallbackMap.find(item_id); if(i_cb != self.mCallbackMap.end()) { @@ -1172,7 +1091,7 @@ void LLGestureMgr::onLoadComplete(LLVFS *vfs, self.mActive.erase(item_id); delete gesture; - gesture = NULL; + gesture = nullptr; } } else @@ -1240,11 +1159,8 @@ bool LLGestureMgr::hasLoadingAssets(LLMultiGesture* gesture) { LLGestureMgr& self = LLGestureMgr::instance(); - for (std::vector::iterator steps_it = gesture->mSteps.begin(); - steps_it != gesture->mSteps.end(); - ++steps_it) + for (auto& step : gesture->mSteps) { - LLGestureStep* step = *steps_it; switch(step->getType()) { case STEP_ANIMATION: @@ -1293,28 +1209,21 @@ void LLGestureMgr::stopGesture(LLMultiGesture* gesture) if (!gesture) return; // Stop any animations that this gesture is currently playing - std::set::const_iterator set_it; - for (set_it = gesture->mRequestedAnimIDs.begin(); set_it != gesture->mRequestedAnimIDs.end(); ++set_it) + for (const auto& anim_id : gesture->mRequestedAnimIDs) { - const LLUUID& anim_id = *set_it; gAgent.sendAnimationRequest(anim_id, ANIM_REQUEST_STOP); } - for (set_it = gesture->mPlayingAnimIDs.begin(); set_it != gesture->mPlayingAnimIDs.end(); ++set_it) + for (const auto& anim_id : gesture->mPlayingAnimIDs) { - const LLUUID& anim_id = *set_it; if (gesture->mLocal) - gAgentAvatarp->stopMotion(anim_id, TRUE); + gAgentAvatarp->stopMotion(anim_id, true); else gAgent.sendAnimationRequest(anim_id, ANIM_REQUEST_STOP); } - std::vector::iterator it; - it = std::find(mPlaying.begin(), mPlaying.end(), gesture); - while (it != mPlaying.end()) - { - mPlaying.erase(it); - it = std::find(mPlaying.begin(), mPlaying.end(), gesture); - } + for (auto& it = std::find(mPlaying.begin(), mPlaying.end(), gesture); + it != mPlaying.end(); + it = std::find(mPlaying.erase(it), mPlaying.end(), gesture)); gesture->reset(); @@ -1324,7 +1233,7 @@ void LLGestureMgr::stopGesture(LLMultiGesture* gesture) // callback might have deleted gesture, can't // rely on this pointer any more - gesture = NULL; + gesture = nullptr; } notifyObservers(); @@ -1334,7 +1243,7 @@ void LLGestureMgr::stopGesture(LLMultiGesture* gesture) void LLGestureMgr::stopGesture(const LLUUID& item_id) { const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); - item_map_t::iterator it = mActive.find(base_item_id); + auto& it = mActive.find(base_item_id); if (it == mActive.end()) return; LLMultiGesture* gesture = (*it).second; @@ -1351,9 +1260,9 @@ void LLGestureMgr::addObserver(LLGestureManagerObserver* observer) void LLGestureMgr::removeObserver(LLGestureManagerObserver* observer) { - std::vector::iterator it; - it = std::find(mObservers.begin(), mObservers.end(), observer); - if (it != mObservers.end()) + const auto& end = mObservers.end(); + auto& it = std::find(mObservers.begin(), end, observer); + if (it != end) { mObservers.erase(it); } @@ -1366,27 +1275,23 @@ void LLGestureMgr::notifyObservers() { LL_DEBUGS() << "LLGestureMgr::notifyObservers" << LL_ENDL; - for(std::vector::iterator iter = mObservers.begin(); - iter != mObservers.end(); - ++iter) + for(auto& observer : mObservers) { - LLGestureManagerObserver* observer = (*iter); observer->changed(); } } -BOOL LLGestureMgr::matchPrefix(const std::string& in_str, std::string* out_str) +bool LLGestureMgr::matchPrefix(const std::string& in_str, std::string* out_str) const { S32 in_len = in_str.length(); #ifdef MATCH_COMMON_CHARS - std::string rest_of_match = ""; - std::string buf = ""; + std::string rest_of_match; + std::string buf; #endif - item_map_t::iterator it; - for (it = mActive.begin(); it != mActive.end(); ++it) + for (const auto& pair : mActive) { - LLMultiGesture* gesture = (*it).second; + const LLMultiGesture* gesture = pair.second; if (gesture) { const std::string& trigger = gesture->getTrigger(); @@ -1395,7 +1300,7 @@ BOOL LLGestureMgr::matchPrefix(const std::string& in_str, std::string* out_str) if (!LLStringUtil::compareInsensitive(in_str, trigger)) { *out_str = trigger; - return TRUE; + return true; } #else if (in_len > (S32)trigger.length()) continue; // too short, bail out @@ -1408,37 +1313,36 @@ BOOL LLGestureMgr::matchPrefix(const std::string& in_str, std::string* out_str) { #ifndef MATCH_COMMON_CHARS *out_str = trigger; - return TRUE; + return true; #else - if (rest_of_match.compare("") == 0) + if (rest_of_match.empty()) { rest_of_match = trigger.substr(in_str.size()); } std::string cur_rest_of_match = trigger.substr(in_str.size()); - buf = ""; - U32 i=0; + buf.clear(); - while (ipush_back(it->first); + ids->push_back(pair.first); } } void LLGestureMgr::done() { bool notify = false; - for(item_map_t::iterator it = mActive.begin(); it != mActive.end(); ++it) + for(const auto& pair : mActive) { - if(it->second && it->second->mName.empty()) + if (pair.second && pair.second->mName.empty()) { - LLViewerInventoryItem* item = gInventory.getItem(it->first); + LLViewerInventoryItem* item = gInventory.getItem(pair.first); if(item) { - it->second->mName = item->getName(); + pair.second->mName = item->getName(); notify = true; } } diff --git a/indra/newview/llgesturemgr.h b/indra/newview/llgesturemgr.h index 419ae77e7..4eef5275f 100644 --- a/indra/newview/llgesturemgr.h +++ b/indra/newview/llgesturemgr.h @@ -27,8 +27,9 @@ #ifndef LL_LLGESTUREMGR_H #define LL_LLGESTUREMGR_H -#include #include +#include +#include #include #include "llassetstorage.h" // LLAssetType @@ -53,10 +54,10 @@ class LLGestureMgr : public LLSingleton, public LLInventoryFetchIt { public: - typedef boost::function gesture_loaded_callback_t; + typedef std::function gesture_loaded_callback_t; // Maps inventory item_id to gesture - typedef std::map item_map_t; - typedef std::map callback_map_t; + typedef std::unordered_map item_map_t; + typedef std::unordered_map callback_map_t; LLGestureMgr(); ~LLGestureMgr(); @@ -81,24 +82,24 @@ public: // Load gesture into in-memory active form. // Can be called even if the inventory item isn't loaded yet. - // inform_server TRUE will send message upstream to update database + // inform_server true will send message upstream to update database // user_gesture_active table, which isn't necessary on login. // deactivate_similar will cause other gestures with the same trigger phrase // or keybinding to be deactivated. - void activateGestureWithAsset(const LLUUID& item_id, const LLUUID& asset_id, BOOL inform_server, BOOL deactivate_similar); + void activateGestureWithAsset(const LLUUID& item_id, const LLUUID& asset_id, bool inform_server, bool deactivate_similar); // Takes gesture out of active list and deletes it. void deactivateGesture(const LLUUID& item_id); // Deactivates all gestures that match either this trigger phrase, // or this hot key. - void deactivateSimilarGestures(LLMultiGesture* gesture, const LLUUID& in_item_id); + void deactivateSimilarGestures(const LLMultiGesture* gesture, const LLUUID& in_item_id); - BOOL isGestureActive(const LLUUID& item_id); + bool isGestureActive(const LLUUID& item_id) const; - BOOL isGesturePlaying(const LLUUID& item_id); + bool isGesturePlaying(const LLUUID& item_id) const; - BOOL isGesturePlaying(LLMultiGesture* gesture); + bool isGesturePlaying(const LLMultiGesture* gesture) const; const item_map_t& getActiveGestures() const { return mActive; } // Force a gesture to be played, for example, if it is being @@ -115,19 +116,19 @@ public: * Note: * Manager will call cb after gesture will be loaded and will remove cb automatically. */ - void setGestureLoadedCallback(LLUUID inv_item_id, gesture_loaded_callback_t cb) + void setGestureLoadedCallback(const LLUUID& inv_item_id, gesture_loaded_callback_t cb) { mCallbackMap[inv_item_id] = cb; } // Trigger the first gesture that matches this key. // Returns TRUE if it finds a gesture bound to that key. - BOOL triggerGesture(KEY key, MASK mask); + bool triggerGesture(KEY key, MASK mask); // Trigger all gestures referenced as substrings in this string - BOOL triggerAndReviseString(const std::string &str, std::string *revised_string = NULL); + bool triggerAndReviseString(const std::string &str, std::string *revised_string = NULL); // Does some gesture have this key bound? - BOOL isKeyBound(KEY key, MASK mask); + //bool isKeyBound(KEY key, MASK mask) const; S32 getPlayingCount() const; @@ -138,10 +139,10 @@ public: // Overriding so we can update active gesture names and notify observers void changed(U32 mask); - BOOL matchPrefix(const std::string& in_str, std::string* out_str); + bool matchPrefix(const std::string& in_str, std::string* out_str) const; // Copy item ids into the vector - void getItemIDs(uuid_vec_t* ids); + void getItemIDs(uuid_vec_t* ids) const; protected: // Handle the processing of a single gesture @@ -172,7 +173,7 @@ protected: private: // Active gestures. - // NOTE: The gesture pointer CAN BE NULL. This means that + // NOTE: The gesture pointer CAN BE a nullptr. This means that // there is a gesture with that item_id, but the asset data // is still on its way down from the server. item_map_t mActive; @@ -183,9 +184,9 @@ private: std::vector mObservers; callback_map_t mCallbackMap; std::vector mPlaying; - BOOL mValid; + bool mValid; - std::set mLoadingAssets; + std::unordered_set mLoadingAssets; }; #endif From 3a17bf519f396a38f8069cc0a0504be3e64019ec Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Fri, 22 Mar 2019 00:56:09 -0400 Subject: [PATCH 012/110] Gesture Opts Pass 3, mainly fixes Fix a linux warning, thanks Router! Fix Linux compile errors, Thanks Router and Bitten! Thanks to Gooz for confirming speed boosts. Also cache end iters maybe minor boost. --- indra/newview/llgesturemgr.cpp | 30 ++++++++++++------------------ indra/newview/llpreviewgesture.cpp | 17 ++++++++++++++++- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 22eaccd1a..294c683fa 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -333,7 +333,7 @@ void LLGestureMgr::deactivateSimilarGestures(const LLMultiGesture* in, const LLU bool start_message = true; // Deactivate all gestures that match - for (auto& it = mActive.begin(); it != mActive.end(); ) + for (auto it = mActive.begin(), end = mActive.end(); it != end; ) { const LLUUID& item_id = (*it).first; LLMultiGesture* gest = (*it).second; @@ -354,6 +354,7 @@ void LLGestureMgr::deactivateSimilarGestures(const LLMultiGesture* in, const LLU gest = nullptr; it = mActive.erase(it); + end = mActive.end(); gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); if (start_message) @@ -695,18 +696,10 @@ S32 LLGestureMgr::getPlayingCount() const } -struct IsGesturePlaying : public std::unary_function -{ - bool operator()(const LLMultiGesture* gesture) const - { - return gesture->mPlaying; - } -}; - void LLGestureMgr::update() { bool notify = false; - for (auto& it = mPlaying.begin(); it != mPlaying.end();) + for (auto it = mPlaying.begin(), end = mPlaying.end(); it != end;) { auto& gesture = *it; stepGesture(gesture); @@ -724,6 +717,7 @@ void LLGestureMgr::update() // And take done gesture out of the playing list it = mPlaying.erase(it); + end = mPlaying.end(); notify = true; } else ++it; @@ -907,7 +901,7 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step) { gAgent.sendAnimationRequest(anim_step->mAnimAssetID, ANIM_REQUEST_STOP); // remove it from our request set in case we just requested it - auto& set_it = gesture->mRequestedAnimIDs.find(anim_step->mAnimAssetID); + auto set_it = gesture->mRequestedAnimIDs.find(anim_step->mAnimAssetID); if (set_it != gesture->mRequestedAnimIDs.end()) { gesture->mRequestedAnimIDs.erase(set_it); @@ -1074,8 +1068,8 @@ void LLGestureMgr::onLoadComplete(LLVFS *vfs, gAgent.sendReliableMessage(); } - auto& i_cb = self.mCallbackMap.find(item_id); - + + auto i_cb = self.mCallbackMap.find(item_id); if(i_cb != self.mCallbackMap.end()) { i_cb->second(gesture); @@ -1221,9 +1215,9 @@ void LLGestureMgr::stopGesture(LLMultiGesture* gesture) gAgent.sendAnimationRequest(anim_id, ANIM_REQUEST_STOP); } - for (auto& it = std::find(mPlaying.begin(), mPlaying.end(), gesture); - it != mPlaying.end(); - it = std::find(mPlaying.erase(it), mPlaying.end(), gesture)); + for (auto end = mPlaying.end(), it = std::find(mPlaying.begin(), end, gesture); + it != end; + it = std::find(mPlaying.erase(it), end = mPlaying.end(), gesture)); gesture->reset(); @@ -1243,7 +1237,7 @@ void LLGestureMgr::stopGesture(LLMultiGesture* gesture) void LLGestureMgr::stopGesture(const LLUUID& item_id) { const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); - auto& it = mActive.find(base_item_id); + auto it = mActive.find(base_item_id); if (it == mActive.end()) return; LLMultiGesture* gesture = (*it).second; @@ -1261,7 +1255,7 @@ void LLGestureMgr::addObserver(LLGestureManagerObserver* observer) void LLGestureMgr::removeObserver(LLGestureManagerObserver* observer) { const auto& end = mObservers.end(); - auto& it = std::find(mObservers.begin(), end, observer); + auto it = std::find(mObservers.begin(), end, observer); if (it != end) { mObservers.erase(it); diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp index 0ac8f3298..eb0bece56 100644 --- a/indra/newview/llpreviewgesture.cpp +++ b/indra/newview/llpreviewgesture.cpp @@ -1610,7 +1610,22 @@ std::string LLPreviewGesture::getLabel(const std::vector& v_labels) for(const auto& pair : LLPreview::sInstances) { const auto& pPreview(pair.second); - if (pPreview && pPreview->getTitleName() == "Gesture") +#ifndef LL_WINDOWS +#if __cplusplus >= 201606 + constexpr std::string_view gesture("Gesture"); + if (pPreview && pPreview->getTitleName().compare(gesture) == 0) + LL_COMPILE_TIME_MESSAGE("String view support detected, remove this macro check, this line and the old check below"); +#endif +#endif + if (pPreview && pPreview->getTitleName() == +#ifndef LL_WINDOWS + static_cast( +#endif + "Gesture" +#ifndef LL_WINDOWS + ) +#endif + ) { wait_anim = pPreview->getChild("wait_anim_check")->getLabel(); break; From 8d1c345580eee7ff29cf6887dfc12127762271a9 Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Fri, 22 Mar 2019 02:08:12 -0400 Subject: [PATCH 013/110] [InvOpts] Inventory Panel unordered opt pass --- indra/newview/llinventorypanel.cpp | 2 +- indra/newview/llinventorypanel.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 82fc9d391..11789100f 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -1118,7 +1118,7 @@ void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_foc setSelectionByID(obj_id, take_keyboard_focus); } -void LLInventoryPanel::setSelectCallback(const boost::function& items, BOOL user_action)>& cb) +void LLInventoryPanel::setSelectCallback(const std::function& items, BOOL user_action)>& cb) { if (mFolderRoot.get()) { diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index a29b0ea99..3912bf5bc 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -129,7 +129,7 @@ public: void closeAllFolders(); void openDefaultFolderForType(LLAssetType::EType); void setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus); - void setSelectCallback(const boost::function& items, BOOL user_action)>& cb); + void setSelectCallback(const std::function& items, BOOL user_action)>& cb); void clearSelection(); bool isSelectionRemovable(); LLInventoryFilter& getFilter(); @@ -211,7 +211,7 @@ protected: LLScrollContainer* mScroller; LLPointer mGroupedItemBridge; - std::map mItemMap; + std::unordered_map mItemMap; /** * Pointer to LLInventoryFolderViewModelBuilder. * From 5f1047c57420bdbf300a936c103ff064ba71d5c2 Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Fri, 22 Mar 2019 02:09:44 -0400 Subject: [PATCH 014/110] [InvOpts] Inventory Observer unordered opt pass --- indra/newview/llinventoryobserver.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h index baa245788..c465d2f57 100644 --- a/indra/newview/llinventoryobserver.h +++ b/indra/newview/llinventoryobserver.h @@ -30,6 +30,7 @@ #include "lluuid.h" #include "llmd5.h" #include +#include #include class LLViewerInventoryCategory; @@ -256,7 +257,7 @@ protected: class LLInventoryCategoriesObserver : public LLInventoryObserver { public: - typedef boost::function callback_t; + typedef std::function callback_t; LLInventoryCategoriesObserver() {}; virtual void changed(U32 mask); @@ -284,7 +285,7 @@ protected: LLUUID mCatID; }; - typedef std::map category_map_t; + typedef std::unordered_map category_map_t; typedef category_map_t::value_type category_map_value_t; category_map_t mCategoryMap; From 9f23dcb0c404721cd23819cfd615bc7f977e99bd Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Fri, 22 Mar 2019 02:10:43 -0400 Subject: [PATCH 015/110] [InvOpts] Folder View unordered opt pass --- indra/newview/llfolderview.cpp | 13 ++++------- indra/newview/llfolderview.h | 4 ++-- indra/newview/llfolderviewitem.cpp | 5 ++-- indra/newview/llfolderviewitem.h | 5 +++- indra/newview/llinventoryactions.cpp | 29 ++++++++---------------- indra/newview/llinventorypanel.cpp | 8 +++---- indra/newview/llpanelobjectinventory.cpp | 7 +++--- indra/newview/llviewermessage.cpp | 2 +- 8 files changed, 30 insertions(+), 43 deletions(-) diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 3fd05a12c..789da8b82 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -865,14 +865,12 @@ void LLFolderView::clearSelection() mSelectThisID.setNull(); } -std::set LLFolderView::getSelectionList() const +std::unordered_set LLFolderView::getSelectionList() const { - std::set selection; - for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); - item_it != mSelectedItems.end(); - ++item_it) + std::unordered_set selection; + for (const auto& item : mSelectedItems) { - selection.insert((*item_it)->getListener()->getUUID()); + selection.insert(item->getListener()->getUUID()); } return selection; } @@ -2118,8 +2116,7 @@ LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id) return this; } - std::map::iterator map_it; - map_it = mItemMap.find(id); + auto map_it = mItemMap.find(id); if (map_it != mItemMap.end()) { return map_it->second; diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 7433e87bb..407c23d4f 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -158,7 +158,7 @@ public: // children, and keeps track of selected objects. virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); - virtual std::set getSelectionList() const; + virtual std::unordered_set getSelectionList() const; // Make sure if ancestor is selected, descendants are not void sanitizeSelection(); @@ -330,7 +330,7 @@ protected: S32 mSignalSelectCallback; S32 mMinWidth; S32 mRunningHeight; - std::map mItemMap; + std::unordered_map mItemMap; LLUUID mSelectThisID; // if non null, select this item LLHandle mParentPanel; diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 1f87716f2..799545f4d 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -378,10 +378,9 @@ void LLFolderViewItem::setSelectionFromRoot(LLFolderViewItem* selection, getRoot()->setSelection(selection, openitem, take_keyboard_focus); } -std::set LLFolderViewItem::getSelectionList() const +std::unordered_set LLFolderViewItem::getSelectionList() const { - std::set selection; - return selection; + return std::unordered_set(); } EInventorySortGroup LLFolderViewItem::getSortGroup() const diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index c33eb575b..0eac95f3d 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -30,6 +30,9 @@ #include "lluiimage.h" #include "lluictrl.h" +#include +#include + class LLFontGL; class LLFolderView; class LLFolderViewEventListener; @@ -218,7 +221,7 @@ public: virtual void selectItem(); // gets multiple-element selection - virtual std::set getSelectionList() const; + virtual std::unordered_set getSelectionList() const; // Returns true is this object and all of its children can be removed (deleted by user) virtual BOOL isRemovable(); diff --git a/indra/newview/llinventoryactions.cpp b/indra/newview/llinventoryactions.cpp index 16e0b9c6c..07313d1c5 100644 --- a/indra/newview/llinventoryactions.cpp +++ b/indra/newview/llinventoryactions.cpp @@ -107,11 +107,8 @@ bool get_selection_object_uuids(LLFolderView *root, uuid_vec_t& ids) { uuid_vec_t results; //S32 no_object = 0; - std::set selectedItems = root->getSelectionList(); - for(std::set::iterator it = selectedItems.begin(); it != selectedItems.end(); ++it) + for(const auto& id : root->getSelectionList()) { - const LLUUID& id(*it); - if(id.notNull()) { results.push_back(id); @@ -134,12 +131,12 @@ bool LLInventoryAction::doToSelected(LLFolderView* root, std::string action, BOO if (!root) return true; - std::set selected_items = root->getSelectionList(); + auto selected_items = root->getSelectionList(); // Prompt the user and check for authorization for some marketplace active listing edits if (user_confirm && (("delete" == action) || ("cut" == action) || ("rename" == action) || ("properties" == action) || ("task_properties" == action) || ("open" == action))) { - std::set::iterator set_iter = std::find_if(selected_items.begin(), selected_items.end(), boost::bind(&depth_nesting_in_marketplace, _1) >= 0); + auto set_iter = std::find_if(selected_items.begin(), selected_items.end(), boost::bind(&depth_nesting_in_marketplace, _1) >= 0); if (set_iter != selected_items.end()) { if ("open" == action) @@ -177,7 +174,7 @@ bool LLInventoryAction::doToSelected(LLFolderView* root, std::string action, BOO // Copying to the marketplace needs confirmation if nocopy items are involved if (("copy_to_marketplace_listings" == action)) { - std::set::iterator set_iter = selected_items.begin(); + auto set_iter = selected_items.begin(); if (contains_nocopy_items(*set_iter)) { LLNotificationsUtil::add("ConfirmCopyToMarketplace", LLSD(), LLSD(), boost::bind(&LLInventoryAction::callback_copySelected, _1, _2, root, action)); @@ -233,8 +230,6 @@ bool LLInventoryAction::doToSelected(LLFolderView* root, std::string action, BOO LLFloater::setFloaterHost(multi_floaterp); } - std::set::iterator set_iter; - // This rather warty piece of code is to allow items to be removed // from the avatar in a batch, eliminating redundant @@ -250,9 +245,9 @@ bool LLInventoryAction::doToSelected(LLFolderView* root, std::string action, BOO } else { - for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) + for (const auto& id : selected_items) { - LLFolderViewItem* folder_item = root->getItemByID(*set_iter); + LLFolderViewItem* folder_item = root->getItemByID(id); if(!folder_item) continue; LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener(); if(!bridge) continue; @@ -286,10 +281,9 @@ void LLInventoryAction::buildMarketplaceFolders(LLFolderView* root) return; } - std::set selected_items = root->getSelectionList(); - for (std::set::const_iterator set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) + for (const auto& item : root->getSelectionList()) { - const LLInventoryObject* obj(gInventory.getObject(*set_iter)); + const LLInventoryObject* obj(gInventory.getObject(item)); if (!obj) continue; if (gInventory.isObjectDescendentOf(obj->getParentUUID(), marketplacelistings_id)) { @@ -522,7 +516,6 @@ struct LLBeginIMSession : public inventory_panel_listener_t LLInventoryPanel *panel = mPtr; LLInventoryModel* model = panel->getModel(); if(!model) return true; - std::set selected_items = panel->getRootFolder()->getSelectionList(); std::string name; static int session_num = 1; @@ -534,10 +527,8 @@ struct LLBeginIMSession : public inventory_panel_listener_t bool fRlvCanStartIM = true; // [/RLVa:KB] - for (std::set::const_iterator iter = selected_items.begin(); iter != selected_items.end(); iter++) + for (const auto& item : panel->getRootFolder()->getSelectionList()) { - - LLUUID item = *iter; LLFolderViewItem* folder_item = panel->getRootFolder()->getItemByID(item); if(folder_item) @@ -644,7 +635,7 @@ struct LLAttachObject : public inventory_panel_listener_t LLFolderView* folder = panel->getRootFolder(); if(!folder) return true; - std::set selected_items = folder->getSelectionList(); + auto selected_items = folder->getSelectionList(); LLUUID id = *selected_items.begin(); std::string joint_name = userdata.asString(); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 11789100f..a8a155436 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -1365,15 +1365,13 @@ bool LLInventoryPanel::isSelectionRemovable() bool can_delete = false; if (mFolderRoot.get()) { - std::set selection_set = mFolderRoot.get()->getSelectionList(); + auto selection_set = mFolderRoot.get()->getSelectionList(); if (!selection_set.empty()) { can_delete = true; - for (std::set::iterator iter = selection_set.begin(); - iter != selection_set.end(); - ++iter) + for (const auto& id : selection_set) { - LLFolderViewItem *item = getItemByID(*iter); + LLFolderViewItem *item = getItemByID(id); const LLFolderViewEventListener* listener =item->getListener(); if (!listener) { diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index cf28f992c..c47c8a2b3 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1710,7 +1710,7 @@ void LLPanelObjectInventory::updateInventory() // << " panel UUID: " << panel->mTaskUUID << "\n" // << " task UUID: " << object->mID << LL_ENDL; // We're still interested in this task's inventory. - std::set selected_items; + std::unordered_set selected_items; BOOL inventory_has_focus = FALSE; if (mHaveInventory) { @@ -1748,11 +1748,10 @@ void LLPanelObjectInventory::updateInventory() } // restore previous selection - std::set::iterator selection_it; bool first_item = true; - for (selection_it = selected_items.begin(); selection_it != selected_items.end(); ++selection_it) + for (const auto id : selected_items) { - LLFolderViewItem* selected_item = mFolders->getItemByID(*selection_it); + LLFolderViewItem* selected_item = mFolders->getItemByID(id); if (selected_item) { diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 65da02e4c..19a0fb4ab 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -881,7 +881,7 @@ private: } LLHandle mActivePanel; - typedef std::set selected_items_t; + typedef std::unordered_set selected_items_t; selected_items_t mSelectedItems; /** From 8d06ea5a15814783f15e4b4b0b2f15b3bb288ea9 Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Fri, 22 Mar 2019 02:58:51 -0400 Subject: [PATCH 016/110] [InvOpts] Folder View unordered opt pass 2: Linux Boogaloo --- indra/newview/llavataractions.cpp | 75 ++++++++++++------------------- indra/newview/llavataractions.h | 4 +- 2 files changed, 31 insertions(+), 48 deletions(-) diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 269c24956..d1ddf598d 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -616,25 +616,21 @@ namespace action_give_inventory static bool is_give_inventory_acceptable() { // check selection in the panel - const std::set inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs(); + const auto inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs(); if (inventory_selected_uuids.empty()) return false; // nothing selected bool acceptable = false; - std::set::const_iterator it = inventory_selected_uuids.begin(); - const std::set::const_iterator it_end = inventory_selected_uuids.end(); - for (; it != it_end; ++it) + for (const auto& id : inventory_selected_uuids) { - LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it); // any category can be offered. - if (inv_cat) + if (gInventory.getCategory(id)) { acceptable = true; continue; } - LLViewerInventoryItem* inv_item = gInventory.getItem(*it); // check if inventory item can be given - if (LLGiveInventory::isInventoryGiveAcceptable(inv_item)) + if (LLGiveInventory::isInventoryGiveAcceptable(gInventory.getItem(id))) { acceptable = true; continue; @@ -647,29 +643,23 @@ namespace action_give_inventory return acceptable; } - static void build_items_string(const std::set& inventory_selected_uuids , std::string& items_string) + static void build_items_string(const std::unordered_set& inventory_selected_uuids, std::string& items_string) { llassert(inventory_selected_uuids.size() > 0); const std::string& separator = LLTrans::getString("words_separator"); - for (std::set::const_iterator it = inventory_selected_uuids.begin(); ; ) + for (const auto& id : inventory_selected_uuids) { - LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it); - if (NULL != inv_cat) + if (!items_string.empty()) items_string.append(separator); + if (LLViewerInventoryCategory* inv_cat = gInventory.getCategory(id)) { items_string = inv_cat->getName(); break; } - LLViewerInventoryItem* inv_item = gInventory.getItem(*it); - if (NULL != inv_item) + else if (LLViewerInventoryItem* inv_item = gInventory.getItem(id)) { items_string.append(inv_item->getName()); } - if(++it == inventory_selected_uuids.end()) - { - break; - } - items_string.append(separator); } } @@ -688,14 +678,14 @@ namespace action_give_inventory return; } - const std::set inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs(); + const auto inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs(); if (inventory_selected_uuids.empty()) { return; } S32 count = LLShareInfo::instance().mAvatarNames.size(); - bool shared = count && !inventory_selected_uuids.empty(); + bool shared = count; // iterate through avatars for(S32 i = 0; i < count; ++i) @@ -705,17 +695,13 @@ namespace action_give_inventory // We souldn't open IM session, just calculate session ID for logging purpose. See EXT-6710 const LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL, avatar_uuid); - std::set::const_iterator it = inventory_selected_uuids.begin(); - const std::set::const_iterator it_end = inventory_selected_uuids.end(); - const std::string& separator = LLTrans::getString("words_separator"); std::string noncopy_item_names; LLSD noncopy_items = LLSD::emptyArray(); // iterate through selected inventory objects - for (; it != it_end; ++it) + for (const auto& id : inventory_selected_uuids) { - LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it); - if (inv_cat) + if (LLViewerInventoryCategory* inv_cat = gInventory.getCategory(id)) { if (!LLGiveInventory::doGiveInventoryCategory(avatar_uuid, inv_cat, session_id, "ItemsShared")) { @@ -723,7 +709,7 @@ namespace action_give_inventory } break; } - LLViewerInventoryItem* inv_item = gInventory.getItem(*it); + LLViewerInventoryItem* inv_item = gInventory.getItem(id); if (!inv_item->getPermissions().allowCopyBy(gAgentID)) { if (!noncopy_item_names.empty()) @@ -731,7 +717,7 @@ namespace action_give_inventory noncopy_item_names.append(separator); } noncopy_item_names.append(inv_item->getName()); - noncopy_items.append(*it); + noncopy_items.append(id); } else { @@ -775,7 +761,7 @@ namespace action_give_inventory { llassert(avatar_names.size() == avatar_uuids.size()); - const std::set inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs(); + const auto inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs(); if (inventory_selected_uuids.empty()) { return; @@ -787,23 +773,21 @@ namespace action_give_inventory std::string items; build_items_string(inventory_selected_uuids, items); - int folders_count = 0; - std::set::const_iterator it = inventory_selected_uuids.begin(); - + bool folders_count = false; // Singu Note: Was a count, but break right after == 1, so bool. //traverse through selected inventory items and count folders among them - for ( ; it != inventory_selected_uuids.end() && folders_count <=1 ; ++it) + for (const auto& id : inventory_selected_uuids) { - LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it); - if (NULL != inv_cat) + if (gInventory.getCategory(id)) { - folders_count++; + folders_count = true; + break; } } // EXP-1599 // In case of sharing multiple folders, make the confirmation // dialog contain a warning that only one folder can be shared at a time. - std::string notification = (folders_count > 1) ? "ShareFolderConfirmation" : "ShareItemsConfirmation"; + std::string notification = folders_count ? "ShareFolderConfirmation" : "ShareItemsConfirmation"; LLSD substitutions; substitutions["RESIDENTS"] = residents; substitutions["ITEMS"] = items; @@ -854,10 +838,10 @@ void LLAvatarActions::buildResidentsString(const uuid_vec_t& avatar_uuids, std:: } //static -std::set LLAvatarActions::getInventorySelectedUUIDs() +std::unordered_set LLAvatarActions::getInventorySelectedUUIDs() { LLInventoryPanel* active_panel = action_give_inventory::get_active_inventory_panel(); - return active_panel ? active_panel->getRootFolder()->getSelectionList() : std::set(); + return active_panel ? active_panel->getRootFolder()->getSelectionList() : std::unordered_set(); /*std::set inventory_selected; LLInventoryPanel* active_panel = action_give_inventory::get_active_inventory_panel(); @@ -875,8 +859,8 @@ std::set LLAvatarActions::getInventorySelectedUUIDs() } } - std::set inventory_selected_uuids; - for (std::set::iterator it = inventory_selected.begin(), end_it = inventory_selected.end(); + std::unordered_set inventory_selected_uuids; + for (auto it = inventory_selected.begin(), end_it = inventory_selected.end(); it != end_it; ++it) { @@ -927,16 +911,13 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL { return false; } - const std::set inventory_selected = root_folder->getSelectionList(); + const auto inventory_selected = root_folder->getSelectionList(); if (inventory_selected.empty()) return false; // nothing selected bool can_share = true; const LLUUID& trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); // - std::set::const_iterator it = inventory_selected.begin(); - const std::set::const_iterator it_end = inventory_selected.end(); - for (; it != it_end; ++it) + for (const auto& id : inventory_selected) { - const LLUUID id(*it); LLViewerInventoryCategory* inv_cat = gInventory.getCategory(id); // any category can be offered. if (inv_cat && !gInventory.isObjectDescendentOf(inv_cat->getUUID(), trash_id)) // diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 57e1ddd17..e4b313266 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -27,6 +27,8 @@ #ifndef LL_LLAVATARACTIONS_H #define LL_LLAVATARACTIONS_H +#include + class LLAvatarName; class LLInventoryPanel; class LLFloater; @@ -232,7 +234,7 @@ public: */ static void buildResidentsString(const uuid_vec_t& avatar_uuids, std::string& residents_string); - static std::set getInventorySelectedUUIDs(); + static std::unordered_set getInventorySelectedUUIDs(); /** * Copy the selected avatar's UUID to clipboard From 42f4c816b735bc41f16ceea8861677d1b4f0e51c Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Fri, 22 Mar 2019 03:57:58 -0400 Subject: [PATCH 017/110] [Animesh] Restore Quick Settings Hover Slider responsiveness --- indra/newview/wlfPanel_AdvSettings.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/indra/newview/wlfPanel_AdvSettings.cpp b/indra/newview/wlfPanel_AdvSettings.cpp index 0952c00da..166355d8d 100644 --- a/indra/newview/wlfPanel_AdvSettings.cpp +++ b/indra/newview/wlfPanel_AdvSettings.cpp @@ -421,10 +421,7 @@ void wlfPanel_AdvSettings::updateTimeSlider() { F32 val = LLWLParamManager::getInstance()->mAnimator.getDayTime() - 0.25f; - if(val < 0.0) - { - val++; - } + if (val < 0.0) ++val; mTimeSlider->setValue(val); } @@ -437,8 +434,8 @@ void syncFromPreferenceSetting(LLSliderCtrl* sldrCtrl) if (isAgentAvatarValid()) { - LLVector3 offset(0.0, 0.0, llclamp(value,MIN_HOVER_Z,MAX_HOVER_Z)); - LL_INFOS("Avatar") << "setting hover from preference setting " << offset[2] << LL_ENDL; + const auto hover = llclamp(value,MIN_HOVER_Z,MAX_HOVER_Z); + LL_INFOS("Avatar") << "setting hover from preference setting " << hover << LL_ENDL; gAgentAvatarp->setHoverIfRegionEnabled(); } } @@ -446,9 +443,9 @@ void syncFromPreferenceSetting(LLSliderCtrl* sldrCtrl) void onHoverSliderMoved(const LLSD& val) { F32 value = val.asFloat(); - LLVector3 offset(0.0, 0.0, llclamp(value,MIN_HOVER_Z,MAX_HOVER_Z)); - LL_INFOS("Avatar") << "setting hover from slider moved" << offset[2] << LL_ENDL; - gAgentAvatarp->setHoverIfRegionEnabled(); + const auto hover = llclamp(value,MIN_HOVER_Z,MAX_HOVER_Z); + LL_DEBUGS("Avatar") << "setting hover from slider moved" << hover << LL_ENDL; + gAgentAvatarp->setHoverOffset(LLVector3(0.0, 0.0, hover), false); } bool sInwlfPanelUpdate = false; @@ -461,8 +458,8 @@ void onHoverSliderFinalCommit(const LLSD& val) F32 value = val.asFloat(); gSavedPerAccountSettings.setF32("AvatarHoverOffsetZ", value); - LLVector3 offset(0.0, 0.0, llclamp(value,MIN_HOVER_Z,MAX_HOVER_Z)); - LL_INFOS("Avatar") << "setting hover from slider final commit " << offset[2] << LL_ENDL; + const auto hover = llclamp(value,MIN_HOVER_Z,MAX_HOVER_Z); + LL_INFOS("Avatar") << "setting hover from slider final commit " << hover << LL_ENDL; gAgentAvatarp->setHoverIfRegionEnabled(); // will send update this time. sInwlfPanelUpdate = false; } From aaeb90436c1a09ffd5b5bb5bfecb171566172240 Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Fri, 22 Mar 2019 17:13:37 -0400 Subject: [PATCH 018/110] Actually, function operator comma order is impl defined, use erase remove --- indra/newview/llgesturemgr.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 294c683fa..ae5bded83 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -1215,9 +1215,7 @@ void LLGestureMgr::stopGesture(LLMultiGesture* gesture) gAgent.sendAnimationRequest(anim_id, ANIM_REQUEST_STOP); } - for (auto end = mPlaying.end(), it = std::find(mPlaying.begin(), end, gesture); - it != end; - it = std::find(mPlaying.erase(it), end = mPlaying.end(), gesture)); + mPlaying.erase(std::remove(mPlaying.begin(), mPlaying.end(), gesture), mPlaying.end()); gesture->reset(); From 3d8e05fa2a0d078785ff2144bfbbdd447af1aad0 Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Fri, 22 Mar 2019 18:02:33 -0400 Subject: [PATCH 019/110] Remove ze gestures --- indra/newview/llinventorybridge.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 49693f6c2..14278f881 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -128,7 +128,7 @@ bool isAddAction(const std::string& action) bool isRemoveAction(const std::string& action) { - return ("take_off" == action || "detach" == action || "deactivate" == action); + return ("take_off" == action || "detach" == action); } // Used by LLFolderBridge as callback for directory fetching recursion @@ -5654,7 +5654,7 @@ void LLGestureBridge::performAction(LLInventoryModel* model, std::string action) // we need to inform server about gesture activating to be consistent with LLPreviewGesture and LLGestureComboList. BOOL inform_server = TRUE; BOOL deactivate_similar = FALSE; - LLGestureMgr::instance().setGestureLoadedCallback(mUUID, boost::bind(&LLGestureBridge::playGesture, mUUID)); + LLGestureMgr::instance().setGestureLoadedCallback(mUUID, std::bind(&LLGestureBridge::playGesture, mUUID)); LLViewerInventoryItem* item = gInventory.getItem(mUUID); llassert(item); if (item) From 3d26f79b8babd909867254f469c5343180d57a60 Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Sat, 23 Mar 2019 00:49:53 -0400 Subject: [PATCH 020/110] Dumb --- indra/llwindow/llwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp index ef0b75b6e..aed30dda6 100644 --- a/indra/llwindow/llwindow.cpp +++ b/indra/llwindow/llwindow.cpp @@ -76,7 +76,7 @@ S32 OSMessageBox(const std::string& text, const std::string& caption, U32 type) S32 result = 0; #if LL_MESA_HEADLESS // !!! *FIX: (???) LL_WARNS() << "OSMessageBox: " << text << LL_ENDL; - return OSBTN_OK; + result = OSBTN_OK; #elif LL_WINDOWS result = OSMessageBoxWin32(text, caption, type); #elif LL_DARWIN From b3f918970b517b7b2d37c4902ddefcab94250009 Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Sat, 23 Mar 2019 00:57:06 -0400 Subject: [PATCH 021/110] Let's print out nonzero return codes --- indra/llwindow/llwindow.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp index aed30dda6..3970d5ea0 100644 --- a/indra/llwindow/llwindow.cpp +++ b/indra/llwindow/llwindow.cpp @@ -262,7 +262,10 @@ int LLWindow::ShellEx(const std::string& command) #else // LL_LINUX or other modern unix, pray it has xdg-open "xdg-open \""; #endif - return std::system((open + command + '"').c_str()); + + const auto& code = std::system((open + command + '"').c_str()); + if (code) LL_WARNS() << "Failed to open \"" << command << "\" return code: " << code << LL_ENDL; + return code; } // static From cc88b1edcd74cbd7a2df9db1d811ee3251e20d9c Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Sat, 23 Mar 2019 01:00:12 -0400 Subject: [PATCH 022/110] Do this instead --- indra/newview/llimpanel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 5425fc965..fdbb80c59 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -1406,7 +1406,7 @@ void LLFloaterIMPanel::onSendMsg() // Look for actions here. if (action) { - utf8_text.replace(0,3,""); + utf8_text.erase(0,3); } else { From c4f868cd89fd5fb2d4a9eb2efc3f8d19ef12ff24 Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Sat, 23 Mar 2019 02:03:23 -0400 Subject: [PATCH 023/110] Fix Deltek's briefly missing icon for adult results in search --- indra/newview/skins/default/textures/textures.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index e79da44cc..f224a0d1f 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -295,6 +295,7 @@ with the same filename but different name + From 8946aa9ee52397f7e15294970e9a651bb7f3a539 Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Sat, 23 Mar 2019 02:07:02 -0400 Subject: [PATCH 024/110] If a group starts with "Singularity ", mark it as a support session This is probably not the best way to go about this, but since we're not in control of support groups on other grids, and we have support groups in other languages we don't run on Second Life, this is better than maintaining a list of IDs somewhere. --- indra/newview/llimpanel.cpp | 8 +++++++- indra/newview/llimpanel.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index fdbb80c59..26a870690 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -65,6 +65,7 @@ #include "llviewerwindow.h" #include "llvoicechannel.h" +#include #include // [RLVa:KB] - Checked: 2013-05-10 (RLVa-1.4.9) @@ -331,7 +332,9 @@ LLFloaterIMPanel::LLFloaterIMPanel( { static LLCachedControl concise("UseConciseGroupChatButtons"); xml_filename = concise ? "floater_instant_message_group_concisebuttons.xml" : "floater_instant_message_group.xml"; - mSessionType = GROUP_SESSION; + bool support = boost::starts_with(mLogLabel, LLTrans::getString("SHORT_APP_NAME") + ' '); + // Singu Note: We could make a button feature for dumping Help->About contents for support, too. + mSessionType = support ? SUPPORT_SESSION : GROUP_SESSION; } else { @@ -1108,6 +1111,7 @@ void LLFloaterIMPanel::onFlyoutCommit(LLComboBox* flyout, const LLSD& value) { switch (mSessionType) { + case SUPPORT_SESSION: case GROUP_SESSION: LLGroupActions::show(mOtherParticipantUUID); return; case P2P_SESSION: LLAvatarActions::showProfile(mOtherParticipantUUID); return; default: onClickHistory(); return; // If there's no profile for this type, we should be the history button. @@ -1313,6 +1317,8 @@ void LLFloaterIMPanel::onSendMsg() case GROUP_SESSION: // Group chat fRlvFilter = !RlvActions::canSendIM(mSessionUUID); break; + case SUPPORT_SESSION: // Support Group, never filter, they may need help!! + break; case ADHOC_SESSION: // Conference chat: allow if all participants can be sent an IM { if (!mSpeakers) diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h index 6a2e54dbe..6a4dffc81 100644 --- a/indra/newview/llimpanel.h +++ b/indra/newview/llimpanel.h @@ -114,6 +114,7 @@ public: { P2P_SESSION, GROUP_SESSION, + SUPPORT_SESSION, ADHOC_SESSION }; const SType& getSessionType() const { return mSessionType; } From c16fa02558947bb2db422091d38f845cc4188cd6 Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Sat, 23 Mar 2019 03:40:20 -0400 Subject: [PATCH 025/110] Support chats have build in every message, cool. This is optional. --- indra/newview/llimpanel.cpp | 20 +++++++++++++++++-- .../en-us/floater_instant_message_group.xml | 1 + ...r_instant_message_group_concisebuttons.xml | 1 + 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 26a870690..10cfd7a26 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -59,6 +59,7 @@ #include "llstylemap.h" #include "lltrans.h" #include "lluictrlfactory.h" +#include "llversioninfo.h" #include "llviewerobjectlist.h" #include "llviewertexteditor.h" #include "llviewerstats.h" @@ -333,7 +334,6 @@ LLFloaterIMPanel::LLFloaterIMPanel( static LLCachedControl concise("UseConciseGroupChatButtons"); xml_filename = concise ? "floater_instant_message_group_concisebuttons.xml" : "floater_instant_message_group.xml"; bool support = boost::starts_with(mLogLabel, LLTrans::getString("SHORT_APP_NAME") + ' '); - // Singu Note: We could make a button feature for dumping Help->About contents for support, too. mSessionType = support ? SUPPORT_SESSION : GROUP_SESSION; } else @@ -564,11 +564,21 @@ BOOL LLFloaterIMPanel::postBuild() mSpeakerPanel->refreshSpeakers(); } - if (mSessionType == P2P_SESSION) + switch (mSessionType) + { + case P2P_SESSION: { getChild("mute_btn")->setCommitCallback(boost::bind(&LLFloaterIMPanel::onClickMuteVoice, this)); getChild("speaker_volume")->setCommitCallback(boost::bind(&LLVoiceClient::setUserVolume, LLVoiceClient::getInstance(), mOtherParticipantUUID, _2)); } + break; + case SUPPORT_SESSION: + getChildView("Support Check")->setVisible(true); + // Singu Note: We could make a button feature for dumping Help->About contents for support, too. + break; + default: + break; + } setDefaultBtn("send_btn"); @@ -1353,6 +1363,12 @@ void LLFloaterIMPanel::onSendMsg() } // [/RLVa:KB] + if (mSessionType == SUPPORT_SESSION && getChildView("Support Check")->getValue()) + { + static const auto version = llformat(" (%d) ", LLVersionInfo::getBuild()); + utf8_text.insert(action ? 3 : 0, action ? version.substr(0, version.size()-1) : version.substr(1)); + } + if ( mSessionInitialized ) { // Split messages that are too long, same code like in llimpanel.cpp diff --git a/indra/newview/skins/default/xui/en-us/floater_instant_message_group.xml b/indra/newview/skins/default/xui/en-us/floater_instant_message_group.xml index 2f3a4a11b..a9cfeeb46 100644 --- a/indra/newview/skins/default/xui/en-us/floater_instant_message_group.xml +++ b/indra/newview/skins/default/xui/en-us/floater_instant_message_group.xml @@ -17,6 +17,7 @@ + + diff --git a/indra/newview/skins/default/xui/en-us/fonts.xml b/indra/newview/skins/default/xui/en-us/fonts.xml index 9ed679b43..a3899f239 100644 --- a/indra/newview/skins/default/xui/en-us/fonts.xml +++ b/indra/newview/skins/default/xui/en-us/fonts.xml @@ -3,8 +3,15 @@ DejaVuSansCondensed.ttf + NotoSansDisplay-Regular.ttf + SourceHanSansJP-Regular.otf + SourceHanSansKR-Regular.otf + SourceHanSansCN-Regular.otf + SourceHanSansHK-Regular.otf + SourceHanSansTW-Regular.otf YuGothR.ttc + meiryo.TTC MSGOTHIC.TTC gulim.ttc simhei.ttf @@ -22,14 +29,48 @@ - - DroidSans.ttf - - DroidSans-Bold.ttf + DejaVuSansCondensed-Bold.ttf + NotoSansDisplay-Bold.ttf + SourceHanSansJP-Bold.otf + SourceHanSansKR-Bold.otf + SourceHanSansCN-Bold.otf + SourceHanSansHK-Bold.otf + SourceHanSansTW-Bold.otf + + + + DroidSans.ttf + + + + DroidSans-Bold.ttf + DejaVuSansCondensed-Bold.ttf + NotoSansDisplay-Bold.ttf + SourceHanSansJP-Bold.otf + SourceHanSansKR-Bold.otf + SourceHanSansCN-Bold.otf + SourceHanSansHK-Bold.otf + SourceHanSansTW-Bold.otf + + + + DejaVuSansCondensed-Oblique.ttf + NotoSansDisplay-Italic.ttf + + + + DejaVuSansCondensed-BoldOblique.ttf + NotoSansDisplay-BoldItalic.ttf - DejaVuSans.ttf + DejaVuSansCondensed.ttf - DejaVuSansBold.ttf + DejaVuSansCondensed-Bold.ttf - DejaVuSansOblique.ttf + DejaVuSansCondensed-Oblique.ttf - DejaVuSansBoldOblique.ttf + DejaVuSansCondensed-BoldOblique.ttf - diff --git a/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_system.xml b/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_system.xml index abdee1a6c..4d3b11bb4 100644 --- a/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_system.xml +++ b/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_system.xml @@ -117,7 +117,7 @@ Drop a landmark below to autoteleport there in the last 20 seconds before region restarts - Drop a backup landmark to autoteleport to below, should you already be at the above + Drop a backup landmark to autoteleport to below, should you already be at above diff --git a/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_vanity.xml b/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_vanity.xml index 72d9b4c51..6dd9e25ae 100644 --- a/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_vanity.xml +++ b/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_vanity.xml @@ -17,7 +17,7 @@ Sound played when regions will restart: - + diff --git a/indra/newview/skins/default/xui/en-us/panel_preferences_general.xml b/indra/newview/skins/default/xui/en-us/panel_preferences_general.xml index 52cb051d1..74e915cf9 100644 --- a/indra/newview/skins/default/xui/en-us/panel_preferences_general.xml +++ b/indra/newview/skins/default/xui/en-us/panel_preferences_general.xml @@ -1,6 +1,6 @@ - + My Home My Last Location @@ -28,7 +28,7 @@ - + Rating: I want to access content rated: diff --git a/indra/newview/skins/default/xui/en-us/panel_preferences_grids.xml b/indra/newview/skins/default/xui/en-us/panel_preferences_grids.xml index d556bafed..ab5ef0ff5 100644 --- a/indra/newview/skins/default/xui/en-us/panel_preferences_grids.xml +++ b/indra/newview/skins/default/xui/en-us/panel_preferences_grids.xml @@ -66,7 +66,7 @@ follows="left|top|right" border_visible="false" mouse_opaque="false" drop_shadow_visible="true" border_drop_shadow_visible="false" />