diff options
Diffstat (limited to 'indra/llwindow')
-rw-r--r-- | indra/llwindow/CMakeLists.txt | 8 | ||||
-rw-r--r-- | indra/llwindow/llkeyboard.cpp | 24 | ||||
-rw-r--r-- | indra/llwindow/llkeyboard.h | 33 | ||||
-rw-r--r-- | indra/llwindow/llkeyboardheadless.cpp | 12 | ||||
-rw-r--r-- | indra/llwindow/llkeyboardheadless.h | 10 | ||||
-rw-r--r-- | indra/llwindow/llkeyboardsdl.cpp | 437 | ||||
-rw-r--r-- | indra/llwindow/llkeyboardsdl.h | 14 | ||||
-rw-r--r-- | indra/llwindow/llwindowsdl.cpp | 1952 | ||||
-rw-r--r-- | indra/llwindow/llwindowsdl.h | 227 | ||||
-rw-r--r-- | indra/llwindow/llwindowwin32.cpp | 13 |
10 files changed, 1524 insertions, 1206 deletions
diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt index 4d5c6053fb..6b70d66d7a 100644 --- a/indra/llwindow/CMakeLists.txt +++ b/indra/llwindow/CMakeLists.txt @@ -51,7 +51,6 @@ set(llwindow_LINK_LIBRARIES llcommon llimage llmath - #llrender llfilesystem llxml ll::glh_linear @@ -65,8 +64,8 @@ include_directories(${CMAKE_SOURCE_DIR}/llrender) # Libraries on which this library depends, needed for Linux builds # Sort by high-level to low-level if (USESYSTEMLIBS AND NOT DARWIN) - list(APPEND viewer_SOURCE_FILES - llkeyboardsdl.cpp + list(APPEND viewer_SOURCE_FILES + llkeyboardsdl.cpp llwindowsdl.cpp ) list(APPEND viewer_HEADER_FILES @@ -86,7 +85,6 @@ if (USESYSTEMLIBS AND NOT DARWIN) fontconfig # For FCInit and other FC* functions. ) endif (BUILD_HEADLESS) - endif (USESYSTEMLIBS AND NOT DARWIN) if (DARWIN) @@ -182,7 +180,7 @@ endif (SDL_FOUND) target_link_libraries (llwindow ${llwindow_LINK_LIBRARIES}) target_include_directories(llwindow INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) - + if (DARWIN) include(CMakeFindFrameworks) find_library(CARBON_LIBRARY Carbon) diff --git a/indra/llwindow/llkeyboard.cpp b/indra/llwindow/llkeyboard.cpp index e93ad28fdf..d4b0743f32 100644 --- a/indra/llwindow/llkeyboard.cpp +++ b/indra/llwindow/llkeyboard.cpp @@ -41,7 +41,6 @@ std::map<KEY,std::string> LLKeyboard::sKeysToNames; std::map<std::string,KEY> LLKeyboard::sNamesToKeys; LLKeyStringTranslatorFunc* LLKeyboard::mStringTranslator = NULL; // Used for l10n + PC/Mac/Linux accelerator labeling - // // Class Implementation // @@ -195,18 +194,11 @@ void LLKeyboard::resetKeys() } -#if LL_SDL -BOOL LLKeyboard::translateKey(const U32 os_key, KEY *out_key) -{ - std::map<U32, KEY>::iterator iter; -#else -BOOL LLKeyboard::translateKey(const U16 os_key, KEY *out_key) +BOOL LLKeyboard::translateKey(const NATIVE_KEY_TYPE os_key, KEY *out_key) { - std::map<U16, KEY>::iterator iter; -#endif // Only translate keys in the map, ignore all other keys for now - iter = mTranslateKeyMap.find(os_key); + auto iter = mTranslateKeyMap.find(os_key); if (iter == mTranslateKeyMap.end()) { //LL_WARNS() << "Unknown virtual key " << os_key << LL_ENDL; @@ -220,17 +212,9 @@ BOOL LLKeyboard::translateKey(const U16 os_key, KEY *out_key) } } - -#if LL_SDL -U32 LLKeyboard::inverseTranslateKey(const KEY translated_key) -{ - std::map<KEY, U32>::iterator iter; -#else -U16 LLKeyboard::inverseTranslateKey(const KEY translated_key) +LLKeyboard::NATIVE_KEY_TYPE LLKeyboard::inverseTranslateKey(const KEY translated_key) { - std::map<KEY, U16>::iterator iter; -#endif - iter = mInvTranslateKeyMap.find(translated_key); + auto iter = mInvTranslateKeyMap.find(translated_key); if (iter == mInvTranslateKeyMap.end()) { return 0; diff --git a/indra/llwindow/llkeyboard.h b/indra/llwindow/llkeyboard.h index 89fa840e42..2800b9fb60 100644 --- a/indra/llwindow/llkeyboard.h +++ b/indra/llwindow/llkeyboard.h @@ -55,6 +55,11 @@ class LLWindowCallbacks; class LLKeyboard { public: +#ifndef LL_SDL + typedef U16 NATIVE_KEY_TYPE; +#else + typedef U32 NATIVE_KEY_TYPE; +#endif LLKeyboard(); virtual ~LLKeyboard(); @@ -67,24 +72,13 @@ public: BOOL getKeyDown(const KEY key) { return mKeyLevel[key]; } BOOL getKeyRepeated(const KEY key) { return mKeyRepeated[key]; } -#if LL_SDL - BOOL translateKey(const U32 os_key, KEY *translated_key); - U32 inverseTranslateKey(const KEY translated_key); -#else - BOOL translateKey(const U16 os_key, KEY *translated_key); - U16 inverseTranslateKey(const KEY translated_key); -#endif + BOOL translateKey(const NATIVE_KEY_TYPE os_key, KEY *translated_key); + NATIVE_KEY_TYPE inverseTranslateKey(const KEY translated_key); BOOL handleTranslatedKeyUp(KEY translated_key, U32 translated_mask); // Translated into "Linden" keycodes BOOL handleTranslatedKeyDown(KEY translated_key, U32 translated_mask); // Translated into "Linden" keycodes - -#if LL_SDL - virtual BOOL handleKeyUp(const U32 key, MASK mask) = 0; - virtual BOOL handleKeyDown(const U32 key, MASK mask) = 0; -#else - virtual BOOL handleKeyUp(const U16 key, MASK mask) = 0; - virtual BOOL handleKeyDown(const U16 key, MASK mask) = 0; -#endif + virtual BOOL handleKeyUp(const NATIVE_KEY_TYPE key, MASK mask) = 0; + virtual BOOL handleKeyDown(const NATIVE_KEY_TYPE key, MASK mask) = 0; #if defined(LL_DARWIN) && !defined(LL_SDL) // We only actually use this for OS X. @@ -121,13 +115,8 @@ protected: void addKeyName(KEY key, const std::string& name); protected: -#if LL_SDL - std::map<U32, KEY> mTranslateKeyMap; // Map of translations from OS keys to Linden KEYs - std::map<KEY, U32> mInvTranslateKeyMap; // Map of translations from Linden KEYs to OS keys -#else - std::map<U16, KEY> mTranslateKeyMap; // Map of translations from OS keys to Linden KEYs - std::map<KEY, U16> mInvTranslateKeyMap; // Map of translations from Linden KEYs to OS keys -#endif + std::map<NATIVE_KEY_TYPE, KEY> mTranslateKeyMap; // Map of translations from OS keys to Linden KEYs + std::map<KEY, NATIVE_KEY_TYPE> mInvTranslateKeyMap; // Map of translations from Linden KEYs to OS keys LLWindowCallbacks *mCallbacks; LLTimer mKeyLevelTimer[KEY_COUNT]; // Time since level was set diff --git a/indra/llwindow/llkeyboardheadless.cpp b/indra/llwindow/llkeyboardheadless.cpp index a3c86fde2b..265d7e6c76 100644 --- a/indra/llwindow/llkeyboardheadless.cpp +++ b/indra/llwindow/llkeyboardheadless.cpp @@ -35,20 +35,8 @@ void LLKeyboardHeadless::resetMaskKeys() { } -#if LL_SDL -BOOL LLKeyboardHeadless::handleKeyDown(const U32 key, const U32 mask) -#else -BOOL LLKeyboardHeadless::handleKeyDown(const U16 key, const U32 mask) -#endif -{ return FALSE; } -#if LL_SDL -BOOL LLKeyboardHeadless::handleKeyUp(const U32 key, const U32 mask) -#else -BOOL LLKeyboardHeadless::handleKeyUp(const U16 key, const U32 mask) -#endif -{ return FALSE; } MASK LLKeyboardHeadless::currentMask(BOOL for_mouse_event) { return MASK_NONE; } diff --git a/indra/llwindow/llkeyboardheadless.h b/indra/llwindow/llkeyboardheadless.h index 2bb670a53d..595f824872 100644 --- a/indra/llwindow/llkeyboardheadless.h +++ b/indra/llwindow/llkeyboardheadless.h @@ -35,12 +35,12 @@ public: LLKeyboardHeadless(); /*virtual*/ ~LLKeyboardHeadless() {}; -#if LL_SDL - /*virtual*/ BOOL handleKeyUp(const U32 key, MASK mask); - /*virtual*/ BOOL handleKeyDown(const U32 key, MASK mask); +#ifndef LL_SDL + /*virtual*/ BOOL handleKeyUp(const U16 key, MASK mask) { return FALSE; } + /*virtual*/ BOOL handleKeyDown(const U16 key, MASK mask) { return FALSE; } #else - /*virtual*/ BOOL handleKeyUp(const U16 key, MASK mask); - /*virtual*/ BOOL handleKeyDown(const U16 key, MASK mask); + /*virtual*/ BOOL handleKeyUp(const U32 key, MASK mask) { return FALSE; } + /*virtual*/ BOOL handleKeyDown(const U32 key, MASK mask) { return FALSE; } #endif /*virtual*/ void resetMaskKeys(); /*virtual*/ MASK currentMask(BOOL for_mouse_event); diff --git a/indra/llwindow/llkeyboardsdl.cpp b/indra/llwindow/llkeyboardsdl.cpp index d1e5cd6c5a..cb6df9401d 100644 --- a/indra/llwindow/llkeyboardsdl.cpp +++ b/indra/llwindow/llkeyboardsdl.cpp @@ -1,6 +1,5 @@ /** - * @file llkeyboardsdl.cpp - * @brief Handler for assignable key bindings + * @author This module has many fathers, and it shows. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code @@ -24,12 +23,11 @@ * $/LicenseInfo$ */ -#if LL_SDL - #include "linden_common.h" #include "llkeyboardsdl.h" #include "llwindowcallbacks.h" #include "SDL2/SDL.h" +#include "SDL2/SDL_keycode.h" LLKeyboardSDL::LLKeyboardSDL() { @@ -40,7 +38,11 @@ LLKeyboardSDL::LLKeyboardSDL() // Virtual key mappings from SDL_keysym.h ... // SDL maps the letter keys to the ASCII you'd expect, but it's lowercase... - U32 cur_char; + + // <FS:ND> Looks like we need to map those despite of SDL_TEXTINPUT handling most of this, but without + // the translation lower->upper here accelerators will not work. + + U16 cur_char; for (cur_char = 'A'; cur_char <= 'Z'; cur_char++) { mTranslateKeyMap[cur_char] = cur_char; @@ -57,24 +59,23 @@ LLKeyboardSDL::LLKeyboardSDL() // These ones are translated manually upon keydown/keyup because // SDL doesn't handle their numlock transition. - //mTranslateKeyMap[SDLK_KP_4] = KEY_PAD_LEFT; - //mTranslateKeyMap[SDLK_KP_6] = KEY_PAD_RIGHT; - //mTranslateKeyMap[SDLK_KP_8] = KEY_PAD_UP; - //mTranslateKeyMap[SDLK_KP_2] = KEY_PAD_DOWN; + //mTranslateKeyMap[SDLK_KP4] = KEY_PAD_LEFT; + //mTranslateKeyMap[SDLK_KP6] = KEY_PAD_RIGHT; + //mTranslateKeyMap[SDLK_KP8] = KEY_PAD_UP; + //mTranslateKeyMap[SDLK_KP2] = KEY_PAD_DOWN; //mTranslateKeyMap[SDLK_KP_PERIOD] = KEY_DELETE; - //mTranslateKeyMap[SDLK_KP_7] = KEY_HOME; - //mTranslateKeyMap[SDLK_KP_1] = KEY_END; - //mTranslateKeyMap[SDLK_KP_9] = KEY_PAGE_UP; - //mTranslateKeyMap[SDLK_KP_3] = KEY_PAGE_DOWN; - //mTranslateKeyMap[SDLK_KP_0] = KEY_INSERT; + //mTranslateKeyMap[SDLK_KP7] = KEY_HOME; + //mTranslateKeyMap[SDLK_KP1] = KEY_END; + //mTranslateKeyMap[SDLK_KP9] = KEY_PAGE_UP; + //mTranslateKeyMap[SDLK_KP3] = KEY_PAGE_DOWN; + //mTranslateKeyMap[SDLK_KP0] = KEY_INSERT; - mTranslateKeyMap[SDLK_SPACE] = ' '; + mTranslateKeyMap[SDLK_SPACE] = ' '; // <FS:ND/> Those are handled by SDL2 via text input, do not map them mTranslateKeyMap[SDLK_RETURN] = KEY_RETURN; mTranslateKeyMap[SDLK_LEFT] = KEY_LEFT; mTranslateKeyMap[SDLK_RIGHT] = KEY_RIGHT; mTranslateKeyMap[SDLK_UP] = KEY_UP; mTranslateKeyMap[SDLK_DOWN] = KEY_DOWN; - mTranslateKeyMap[SDLK_ESCAPE] = KEY_ESCAPE; mTranslateKeyMap[SDLK_KP_ENTER] = KEY_RETURN; mTranslateKeyMap[SDLK_ESCAPE] = KEY_ESCAPE; mTranslateKeyMap[SDLK_BACKSPACE] = KEY_BACKSPACE; @@ -111,21 +112,20 @@ LLKeyboardSDL::LLKeyboardSDL() mTranslateKeyMap[SDLK_F10] = KEY_F10; mTranslateKeyMap[SDLK_F11] = KEY_F11; mTranslateKeyMap[SDLK_F12] = KEY_F12; - mTranslateKeyMap[SDLK_PLUS] = '='; - mTranslateKeyMap[SDLK_COMMA] = ','; - mTranslateKeyMap[SDLK_MINUS] = '-'; - mTranslateKeyMap[SDLK_PERIOD] = '.'; - mTranslateKeyMap[SDLK_BACKQUOTE] = '`'; - mTranslateKeyMap[SDLK_SLASH] = KEY_DIVIDE; - mTranslateKeyMap[SDLK_SEMICOLON] = ';'; - mTranslateKeyMap[SDLK_LEFTBRACKET] = '['; - mTranslateKeyMap[SDLK_BACKSLASH] = '\\'; - mTranslateKeyMap[SDLK_RIGHTBRACKET] = ']'; - mTranslateKeyMap[SDLK_QUOTE] = '\''; + mTranslateKeyMap[SDLK_PLUS] = '='; // <FS:ND/> Those are handled by SDL2 via text input, do not map them + mTranslateKeyMap[SDLK_COMMA] = ','; // <FS:ND/> Those are handled by SDL2 via text input, do not map them + mTranslateKeyMap[SDLK_MINUS] = '-'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them + mTranslateKeyMap[SDLK_PERIOD] = '.'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them + mTranslateKeyMap[SDLK_BACKQUOTE] = '`'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them + mTranslateKeyMap[SDLK_SLASH] = KEY_DIVIDE; // <FS:ND/> Those are handled by SDL2 via text input, do not map them + mTranslateKeyMap[SDLK_SEMICOLON] = ';'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them + mTranslateKeyMap[SDLK_LEFTBRACKET] = '['; // <FS:ND/> Those are handled by SDL2 via text input, do not map them + mTranslateKeyMap[SDLK_BACKSLASH] = '\\'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them + mTranslateKeyMap[SDLK_RIGHTBRACKET] = ']'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them + mTranslateKeyMap[SDLK_QUOTE] = '\''; // <FS:ND/> Those are handled by SDL2 via text input, do not map them // Build inverse map - std::map<U32, KEY>::iterator iter; - for (iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end(); iter++) + for (auto iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end(); iter++) { mInvTranslateKeyMap[iter->second] = iter->first; } @@ -144,7 +144,7 @@ LLKeyboardSDL::LLKeyboardSDL() mTranslateNumpadMap[SDLK_KP_PERIOD] = KEY_PAD_DEL; // build inverse numpad map - for (iter = mTranslateNumpadMap.begin(); + for (auto iter = mTranslateNumpadMap.begin(); iter != mTranslateNumpadMap.end(); iter++) { @@ -218,16 +218,16 @@ static U32 adjustNativekeyFromUnhandledMask(const U32 key, const U32 mask) { switch (key) { - case SDLK_KP_PERIOD: rtn = SDLK_DELETE; break; - case SDLK_KP_0: rtn = SDLK_INSERT; break; - case SDLK_KP_1: rtn = SDLK_END; break; - case SDLK_KP_2: rtn = SDLK_DOWN; break; - case SDLK_KP_3: rtn = SDLK_PAGEDOWN; break; - case SDLK_KP_4: rtn = SDLK_LEFT; break; - case SDLK_KP_6: rtn = SDLK_RIGHT; break; - case SDLK_KP_7: rtn = SDLK_HOME; break; - case SDLK_KP_8: rtn = SDLK_UP; break; - case SDLK_KP_9: rtn = SDLK_PAGEUP; break; + case SDLK_KP_PERIOD: rtn = SDLK_DELETE; break; + case SDLK_KP_0: rtn = SDLK_INSERT; break; + case SDLK_KP_1: rtn = SDLK_END; break; + case SDLK_KP_2: rtn = SDLK_DOWN; break; + case SDLK_KP_3: rtn = SDLK_PAGEDOWN; break; + case SDLK_KP_4: rtn = SDLK_LEFT; break; + case SDLK_KP_6: rtn = SDLK_RIGHT; break; + case SDLK_KP_7: rtn = SDLK_HOME; break; + case SDLK_KP_8: rtn = SDLK_UP; break; + case SDLK_KP_9: rtn = SDLK_PAGEUP; break; } } return rtn; @@ -236,10 +236,10 @@ static U32 adjustNativekeyFromUnhandledMask(const U32 key, const U32 mask) BOOL LLKeyboardSDL::handleKeyDown(const U32 key, const U32 mask) { - U32 adjusted_nativekey; + U32 adjusted_nativekey; KEY translated_key = 0; U32 translated_mask = MASK_NONE; - BOOL handled = FALSE; + BOOL handled = FALSE; adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask); @@ -256,10 +256,10 @@ BOOL LLKeyboardSDL::handleKeyDown(const U32 key, const U32 mask) BOOL LLKeyboardSDL::handleKeyUp(const U32 key, const U32 mask) { - U32 adjusted_nativekey; + U32 adjusted_nativekey; KEY translated_key = 0; U32 translated_mask = MASK_NONE; - BOOL handled = FALSE; + BOOL handled = FALSE; adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask); @@ -278,14 +278,18 @@ MASK LLKeyboardSDL::currentMask(BOOL for_mouse_event) MASK result = MASK_NONE; SDL_Keymod mask = SDL_GetModState(); - if (mask & KMOD_SHIFT) result |= MASK_SHIFT; - if (mask & KMOD_CTRL) result |= MASK_CONTROL; - if (mask & KMOD_ALT) result |= MASK_ALT; + if (mask & KMOD_SHIFT) + result |= MASK_SHIFT; + if (mask & KMOD_CTRL) + result |= MASK_CONTROL; + if (mask & KMOD_ALT) + result |= MASK_ALT; // For keyboard events, consider Meta keys equivalent to Control if (!for_mouse_event) { - if (mask & KMOD_GUI) result |= MASK_CONTROL; + if (mask & KMOD_GUI) + result |= MASK_CONTROL; } return result; @@ -323,10 +327,343 @@ BOOL LLKeyboardSDL::translateNumpadKey( const U32 os_key, KEY *translated_key) return translateKey(os_key, translated_key); } -U32 LLKeyboardSDL::inverseTranslateNumpadKey(const KEY translated_key) +U16 LLKeyboardSDL::inverseTranslateNumpadKey(const KEY translated_key) { return inverseTranslateKey(translated_key); } -#endif +enum class WindowsVK : U32 +{ + VK_UNKNOWN = 0, + VK_CANCEL = 0x03, + VK_BACK = 0x08, + VK_TAB = 0x09, + VK_CLEAR = 0x0C, + VK_RETURN = 0x0D, + VK_SHIFT = 0x10, + VK_CONTROL = 0x11, + VK_MENU = 0x12, + VK_PAUSE = 0x13, + VK_CAPITAL = 0x14, + VK_KANA = 0x15, + VK_HANGUL = 0x15, + VK_JUNJA = 0x17, + VK_FINAL = 0x18, + VK_HANJA = 0x19, + VK_KANJI = 0x19, + VK_ESCAPE = 0x1B, + VK_CONVERT = 0x1C, + VK_NONCONVERT = 0x1D, + VK_ACCEPT = 0x1E, + VK_MODECHANGE = 0x1F, + VK_SPACE = 0x20, + VK_PRIOR = 0x21, + VK_NEXT = 0x22, + VK_END = 0x23, + VK_HOME = 0x24, + VK_LEFT = 0x25, + VK_UP = 0x26, + VK_RIGHT = 0x27, + VK_DOWN = 0x28, + VK_SELECT = 0x29, + VK_PRINT = 0x2A, + VK_EXECUTE = 0x2B, + VK_SNAPSHOT = 0x2C, + VK_INSERT = 0x2D, + VK_DELETE = 0x2E, + VK_HELP = 0x2F, + VK_0 = 0x30, + VK_1 = 0x31, + VK_2 = 0x32, + VK_3 = 0x33, + VK_4 = 0x34, + VK_5 = 0x35, + VK_6 = 0x36, + VK_7 = 0x37, + VK_8 = 0x38, + VK_9 = 0x39, + VK_A = 0x41, + VK_B = 0x42, + VK_C = 0x43, + VK_D = 0x44, + VK_E = 0x45, + VK_F = 0x46, + VK_G = 0x47, + VK_H = 0x48, + VK_I = 0x49, + VK_J = 0x4A, + VK_K = 0x4B, + VK_L = 0x4C, + VK_M = 0x4D, + VK_N = 0x4E, + VK_O = 0x4F, + VK_P = 0x50, + VK_Q = 0x51, + VK_R = 0x52, + VK_S = 0x53, + VK_T = 0x54, + VK_U = 0x55, + VK_V = 0x56, + VK_W = 0x57, + VK_X = 0x58, + VK_Y = 0x59, + VK_Z = 0x5A, + VK_LWIN = 0x5B, + VK_RWIN = 0x5C, + VK_APPS = 0x5D, + VK_SLEEP = 0x5F, + VK_NUMPAD0 = 0x60, + VK_NUMPAD1 = 0x61, + VK_NUMPAD2 = 0x62, + VK_NUMPAD3 = 0x63, + VK_NUMPAD4 = 0x64, + VK_NUMPAD5 = 0x65, + VK_NUMPAD6 = 0x66, + VK_NUMPAD7 = 0x67, + VK_NUMPAD8 = 0x68, + VK_NUMPAD9 = 0x69, + VK_MULTIPLY = 0x6A, + VK_ADD = 0x6B, + VK_SEPARATOR = 0x6C, + VK_SUBTRACT = 0x6D, + VK_DECIMAL = 0x6E, + VK_DIVIDE = 0x6F, + VK_F1 = 0x70, + VK_F2 = 0x71, + VK_F3 = 0x72, + VK_F4 = 0x73, + VK_F5 = 0x74, + VK_F6 = 0x75, + VK_F7 = 0x76, + VK_F8 = 0x77, + VK_F9 = 0x78, + VK_F10 = 0x79, + VK_F11 = 0x7A, + VK_F12 = 0x7B, + VK_F13 = 0x7C, + VK_F14 = 0x7D, + VK_F15 = 0x7E, + VK_F16 = 0x7F, + VK_F17 = 0x80, + VK_F18 = 0x81, + VK_F19 = 0x82, + VK_F20 = 0x83, + VK_F21 = 0x84, + VK_F22 = 0x85, + VK_F23 = 0x86, + VK_F24 = 0x87, + VK_NUMLOCK = 0x90, + VK_SCROLL = 0x91, + VK_LSHIFT = 0xA0, + VK_RSHIFT = 0xA1, + VK_LCONTROL = 0xA2, + VK_RCONTROL = 0xA3, + VK_LMENU = 0xA4, + VK_RMENU = 0xA5, + VK_BROWSER_BACK = 0xA6, + VK_BROWSER_FORWARD = 0xA7, + VK_BROWSER_REFRESH = 0xA8, + VK_BROWSER_STOP = 0xA9, + VK_BROWSER_SEARCH = 0xAA, + VK_BROWSER_FAVORITES = 0xAB, + VK_BROWSER_HOME = 0xAC, + VK_VOLUME_MUTE = 0xAD, + VK_VOLUME_DOWN = 0xAE, + VK_VOLUME_UP = 0xAF, + VK_MEDIA_NEXT_TRACK = 0xB0, + VK_MEDIA_PREV_TRACK = 0xB1, + VK_MEDIA_STOP = 0xB2, + VK_MEDIA_PLAY_PAUSE = 0xB3, + VK_MEDIA_LAUNCH_MAIL = 0xB4, + VK_MEDIA_LAUNCH_MEDIA_SELECT = 0xB5, + VK_MEDIA_LAUNCH_APP1 = 0xB6, + VK_MEDIA_LAUNCH_APP2 = 0xB7, + VK_OEM_1 = 0xBA, + VK_OEM_PLUS = 0xBB, + VK_OEM_COMMA = 0xBC, + VK_OEM_MINUS = 0xBD, + VK_OEM_PERIOD = 0xBE, + VK_OEM_2 = 0xBF, + VK_OEM_3 = 0xC0, + VK_OEM_4 = 0xDB, + VK_OEM_5 = 0xDC, + VK_OEM_6 = 0xDD, + VK_OEM_7 = 0xDE, + VK_OEM_8 = 0xDF, + VK_OEM_102 = 0xE2, + VK_PROCESSKEY = 0xE5, + VK_PACKET = 0xE7, + VK_ATTN = 0xF6, + VK_CRSEL = 0xF7, + VK_EXSEL = 0xF8, + VK_EREOF = 0xF9, + VK_PLAY = 0xFA, + VK_ZOOM = 0xFB, + VK_NONAME = 0xFC, + VK_PA1 = 0xFD, + VK_OEM_CLEAR = 0xFE, +}; + +std::map< U32, U32 > mSDL2_to_Win; +std::set< U32 > mIgnoreSDL2Keys; + +U32 LLKeyboardSDL::mapSDL2toWin( U32 aSymbol ) +{ + // <FS:ND> Map SDLK_ virtual keys to Windows VK_ virtual keys. + // Text is handled via unicode input (SDL_TEXTINPUT event) and does not need to be translated into VK_ values as those match already. + if( mSDL2_to_Win.empty() ) + { + + mSDL2_to_Win[ SDLK_BACKSPACE ] = (U32)WindowsVK::VK_BACK; + mSDL2_to_Win[ SDLK_TAB ] = (U32)WindowsVK::VK_TAB; + mSDL2_to_Win[ 12 ] = (U32)WindowsVK::VK_CLEAR; + mSDL2_to_Win[ SDLK_RETURN ] = (U32)WindowsVK::VK_RETURN; + mSDL2_to_Win[ 19 ] = (U32)WindowsVK::VK_PAUSE; + mSDL2_to_Win[ SDLK_ESCAPE ] = (U32)WindowsVK::VK_ESCAPE; + mSDL2_to_Win[ SDLK_SPACE ] = (U32)WindowsVK::VK_SPACE; + mSDL2_to_Win[ SDLK_QUOTE ] = (U32)WindowsVK::VK_OEM_7; + mSDL2_to_Win[ SDLK_COMMA ] = (U32)WindowsVK::VK_OEM_COMMA; + mSDL2_to_Win[ SDLK_MINUS ] = (U32)WindowsVK::VK_OEM_MINUS; + mSDL2_to_Win[ SDLK_PERIOD ] = (U32)WindowsVK::VK_OEM_PERIOD; + mSDL2_to_Win[ SDLK_SLASH ] = (U32)WindowsVK::VK_OEM_2; + + mSDL2_to_Win[ SDLK_0 ] = (U32)WindowsVK::VK_0; + mSDL2_to_Win[ SDLK_1 ] = (U32)WindowsVK::VK_1; + mSDL2_to_Win[ SDLK_2 ] = (U32)WindowsVK::VK_2; + mSDL2_to_Win[ SDLK_3 ] = (U32)WindowsVK::VK_3; + mSDL2_to_Win[ SDLK_4 ] = (U32)WindowsVK::VK_4; + mSDL2_to_Win[ SDLK_5 ] = (U32)WindowsVK::VK_5; + mSDL2_to_Win[ SDLK_6 ] = (U32)WindowsVK::VK_6; + mSDL2_to_Win[ SDLK_7 ] = (U32)WindowsVK::VK_7; + mSDL2_to_Win[ SDLK_8 ] = (U32)WindowsVK::VK_8; + mSDL2_to_Win[ SDLK_9 ] = (U32)WindowsVK::VK_9; + + mSDL2_to_Win[ SDLK_SEMICOLON ] = (U32)WindowsVK::VK_OEM_1; + mSDL2_to_Win[ SDLK_LESS ] = (U32)WindowsVK::VK_OEM_102; + mSDL2_to_Win[ SDLK_EQUALS ] = (U32)WindowsVK::VK_OEM_PLUS; + mSDL2_to_Win[ SDLK_KP_EQUALS ] = (U32)WindowsVK::VK_OEM_PLUS; + + mSDL2_to_Win[ SDLK_LEFTBRACKET ] = (U32)WindowsVK::VK_OEM_4; + mSDL2_to_Win[ SDLK_BACKSLASH ] = (U32)WindowsVK::VK_OEM_5; + mSDL2_to_Win[ SDLK_RIGHTBRACKET ] = (U32)WindowsVK::VK_OEM_6; + mSDL2_to_Win[ SDLK_BACKQUOTE ] = (U32)WindowsVK::VK_OEM_8; + + mSDL2_to_Win[ SDLK_a ] = (U32)WindowsVK::VK_A; + mSDL2_to_Win[ SDLK_b ] = (U32)WindowsVK::VK_B; + mSDL2_to_Win[ SDLK_c ] = (U32)WindowsVK::VK_C; + mSDL2_to_Win[ SDLK_d ] = (U32)WindowsVK::VK_D; + mSDL2_to_Win[ SDLK_e ] = (U32)WindowsVK::VK_E; + mSDL2_to_Win[ SDLK_f ] = (U32)WindowsVK::VK_F; + mSDL2_to_Win[ SDLK_g ] = (U32)WindowsVK::VK_G; + mSDL2_to_Win[ SDLK_h ] = (U32)WindowsVK::VK_H; + mSDL2_to_Win[ SDLK_i ] = (U32)WindowsVK::VK_I; + mSDL2_to_Win[ SDLK_j ] = (U32)WindowsVK::VK_J; + mSDL2_to_Win[ SDLK_k ] = (U32)WindowsVK::VK_K; + mSDL2_to_Win[ SDLK_l ] = (U32)WindowsVK::VK_L; + mSDL2_to_Win[ SDLK_m ] = (U32)WindowsVK::VK_M; + mSDL2_to_Win[ SDLK_n ] = (U32)WindowsVK::VK_N; + mSDL2_to_Win[ SDLK_o ] = (U32)WindowsVK::VK_O; + mSDL2_to_Win[ SDLK_p ] = (U32)WindowsVK::VK_P; + mSDL2_to_Win[ SDLK_q ] = (U32)WindowsVK::VK_Q; + mSDL2_to_Win[ SDLK_r ] = (U32)WindowsVK::VK_R; + mSDL2_to_Win[ SDLK_s ] = (U32)WindowsVK::VK_S; + mSDL2_to_Win[ SDLK_t ] = (U32)WindowsVK::VK_T; + mSDL2_to_Win[ SDLK_u ] = (U32)WindowsVK::VK_U; + mSDL2_to_Win[ SDLK_v ] = (U32)WindowsVK::VK_V; + mSDL2_to_Win[ SDLK_w ] = (U32)WindowsVK::VK_W; + mSDL2_to_Win[ SDLK_x ] = (U32)WindowsVK::VK_X; + mSDL2_to_Win[ SDLK_y ] = (U32)WindowsVK::VK_Y; + mSDL2_to_Win[ SDLK_z ] = (U32)WindowsVK::VK_Z; + + mSDL2_to_Win[ SDLK_DELETE ] = (U32)WindowsVK::VK_DELETE; + + + mSDL2_to_Win[ SDLK_NUMLOCKCLEAR ] = (U32)WindowsVK::VK_NUMLOCK; + mSDL2_to_Win[ SDLK_SCROLLLOCK ] = (U32)WindowsVK::VK_SCROLL; + + mSDL2_to_Win[ SDLK_HELP ] = (U32)WindowsVK::VK_HELP; + mSDL2_to_Win[ SDLK_PRINTSCREEN ] = (U32)WindowsVK::VK_SNAPSHOT; + mSDL2_to_Win[ SDLK_CANCEL ] = (U32)WindowsVK::VK_CANCEL; + mSDL2_to_Win[ SDLK_APPLICATION ] = (U32)WindowsVK::VK_APPS; + + mSDL2_to_Win[ SDLK_UNKNOWN ] = (U32)WindowsVK::VK_UNKNOWN; + mSDL2_to_Win[ SDLK_BACKSPACE ] = (U32)WindowsVK::VK_BACK; + mSDL2_to_Win[ SDLK_TAB ] = (U32)WindowsVK::VK_TAB; + mSDL2_to_Win[ SDLK_CLEAR ] = (U32)WindowsVK::VK_CLEAR; + mSDL2_to_Win[ SDLK_RETURN ] = (U32)WindowsVK::VK_RETURN; + mSDL2_to_Win[ SDLK_PAUSE ] = (U32)WindowsVK::VK_PAUSE; + mSDL2_to_Win[ SDLK_ESCAPE ] = (U32)WindowsVK::VK_ESCAPE; + mSDL2_to_Win[ SDLK_DELETE ] = (U32)WindowsVK::VK_DELETE; + + mSDL2_to_Win[ SDLK_KP_PERIOD ] = (U32)WindowsVK::VK_OEM_PERIOD; // VK_DECIMAL? + mSDL2_to_Win[ SDLK_KP_DIVIDE ] = (U32)WindowsVK::VK_DIVIDE; + mSDL2_to_Win[ SDLK_KP_MULTIPLY] = (U32)WindowsVK::VK_MULTIPLY; + mSDL2_to_Win[ SDLK_KP_MINUS ] = (U32)WindowsVK::VK_OEM_MINUS; // VK_SUBSTRACT? + mSDL2_to_Win[ SDLK_KP_PLUS ] = (U32)WindowsVK::VK_OEM_PLUS; // VK_ADD? + mSDL2_to_Win[ SDLK_KP_ENTER ] = (U32)WindowsVK::VK_RETURN; + mSDL2_to_Win[ SDLK_KP_0 ] = (U32)WindowsVK::VK_NUMPAD0; + mSDL2_to_Win[ SDLK_KP_1 ] = (U32)WindowsVK::VK_NUMPAD1; + mSDL2_to_Win[ SDLK_KP_2 ] = (U32)WindowsVK::VK_NUMPAD2; + mSDL2_to_Win[ SDLK_KP_3 ] = (U32)WindowsVK::VK_NUMPAD3; + mSDL2_to_Win[ SDLK_KP_4 ] = (U32)WindowsVK::VK_NUMPAD4; + mSDL2_to_Win[ SDLK_KP_5 ] = (U32)WindowsVK::VK_NUMPAD5; + mSDL2_to_Win[ SDLK_KP_6 ] = (U32)WindowsVK::VK_NUMPAD6; + mSDL2_to_Win[ SDLK_KP_7 ] = (U32)WindowsVK::VK_NUMPAD7; + mSDL2_to_Win[ SDLK_KP_8 ] = (U32)WindowsVK::VK_NUMPAD8; + mSDL2_to_Win[ SDLK_KP_9 ] = (U32)WindowsVK::VK_NUMPAD9; + + // ? + + mSDL2_to_Win[ SDLK_UP ] = (U32)WindowsVK::VK_UP; + mSDL2_to_Win[ SDLK_DOWN ] = (U32)WindowsVK::VK_DOWN; + mSDL2_to_Win[ SDLK_RIGHT ] = (U32)WindowsVK::VK_RIGHT; + mSDL2_to_Win[ SDLK_LEFT ] = (U32)WindowsVK::VK_LEFT; + mSDL2_to_Win[ SDLK_INSERT ] = (U32)WindowsVK::VK_INSERT; + mSDL2_to_Win[ SDLK_HOME ] = (U32)WindowsVK::VK_HOME; + mSDL2_to_Win[ SDLK_END ] = (U32)WindowsVK::VK_END; + mSDL2_to_Win[ SDLK_PAGEUP ] = (U32)WindowsVK::VK_PRIOR; + mSDL2_to_Win[ SDLK_PAGEDOWN ] = (U32)WindowsVK::VK_NEXT; + mSDL2_to_Win[ SDLK_F1 ] = (U32)WindowsVK::VK_F1; + mSDL2_to_Win[ SDLK_F2 ] = (U32)WindowsVK::VK_F2; + mSDL2_to_Win[ SDLK_F3 ] = (U32)WindowsVK::VK_F3; + mSDL2_to_Win[ SDLK_F4 ] = (U32)WindowsVK::VK_F4; + mSDL2_to_Win[ SDLK_F5 ] = (U32)WindowsVK::VK_F5; + mSDL2_to_Win[ SDLK_F6 ] = (U32)WindowsVK::VK_F6; + mSDL2_to_Win[ SDLK_F7 ] = (U32)WindowsVK::VK_F7; + mSDL2_to_Win[ SDLK_F8 ] = (U32)WindowsVK::VK_F8; + mSDL2_to_Win[ SDLK_F9 ] = (U32)WindowsVK::VK_F9; + mSDL2_to_Win[ SDLK_F10 ] = (U32)WindowsVK::VK_F10; + mSDL2_to_Win[ SDLK_F11 ] = (U32)WindowsVK::VK_F11; + mSDL2_to_Win[ SDLK_F12 ] = (U32)WindowsVK::VK_F12; + mSDL2_to_Win[ SDLK_F13 ] = (U32)WindowsVK::VK_F13; + mSDL2_to_Win[ SDLK_F14 ] = (U32)WindowsVK::VK_F14; + mSDL2_to_Win[ SDLK_F15 ] = (U32)WindowsVK::VK_F15; + mSDL2_to_Win[ SDLK_CAPSLOCK ] = (U32)WindowsVK::VK_CAPITAL; + mSDL2_to_Win[ SDLK_RSHIFT ] = (U32)WindowsVK::VK_SHIFT; + mSDL2_to_Win[ SDLK_LSHIFT ] = (U32)WindowsVK::VK_SHIFT; + mSDL2_to_Win[ SDLK_RCTRL ] = (U32)WindowsVK::VK_CONTROL; + mSDL2_to_Win[ SDLK_LCTRL ] = (U32)WindowsVK::VK_CONTROL; + mSDL2_to_Win[ SDLK_RALT ] = (U32)WindowsVK::VK_MENU; + mSDL2_to_Win[ SDLK_LALT ] = (U32)WindowsVK::VK_MENU; + + mSDL2_to_Win[ SDLK_MENU ] = (U32)WindowsVK::VK_MENU; + + // VK_MODECHANGE ? + // mSDL2_to_Win[ SDLK_MODE ] = (U32)WindowsVK::VK_MODE; + + // ? + // mSDL2_to_Win[ SDLK_SYSREQ ] = (U32)WindowsVK::VK_SYSREQ; + // mSDL2_to_Win[ SDLK_POWER ] = (U32)WindowsVK::VK_POWER; + // mSDL2_to_Win[ SDLK_UNDO ] = (U32)WindowsVK::VK_UNDO; + // mSDL2_to_Win[ SDLK_KP_EQUALS ] = (U32)WindowsVK::VK_EQUALS; + // mSDL2_to_Win[ 311 ] = (U32)WindowsVK::VK_LWIN; + // mSDL2_to_Win[ 312 ] = (U32)WindowsVK::VK_RWIN; + // mSDL2_to_Win[ SDLK_COLON ] = ? + } + + auto itr = mSDL2_to_Win.find( aSymbol ); + if( itr != mSDL2_to_Win.end() ) + return itr->second; + return aSymbol; +} diff --git a/indra/llwindow/llkeyboardsdl.h b/indra/llwindow/llkeyboardsdl.h index ac6e9f2cef..962ff5884b 100644 --- a/indra/llwindow/llkeyboardsdl.h +++ b/indra/llwindow/llkeyboardsdl.h @@ -1,8 +1,7 @@ /** - * @file llkeyboardsdl.h - * @brief Handler for assignable key bindings + * @author This module has many fathers, and it shows. * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * @@ -24,8 +23,8 @@ * $/LicenseInfo$ */ -#ifndef LL_LLKEYBOARDSDL_H -#define LL_LLKEYBOARDSDL_H +#ifndef LL_LLKEYBOARDSDL2_H +#define LL_LLKEYBOARDSDL2_H #include "llkeyboard.h" #if !defined(__i386__) && !defined(__x86_64__) @@ -49,10 +48,13 @@ protected: MASK updateModifiers(const U32 mask); void setModifierKeyLevel( KEY key, BOOL new_state ); BOOL translateNumpadKey( const U32 os_key, KEY *translated_key ); - U32 inverseTranslateNumpadKey(const KEY translated_key); + U16 inverseTranslateNumpadKey(const KEY translated_key); private: std::map<U32, KEY> mTranslateNumpadMap; // special map for translating OS keys to numpad keys std::map<KEY, U32> mInvTranslateNumpadMap; // inverse of the above + +public: + static U32 mapSDL2toWin( U32 ); }; #endif diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 531c70e8d9..83f5e16977 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -25,8 +25,6 @@ * $/LicenseInfo$ */ -#if LL_SDL - #include "linden_common.h" #include "llwindowsdl.h" @@ -44,12 +42,9 @@ extern LLControlGroup gSavedSettings; -#if LL_GTK -extern "C" { -# include "gtk/gtk.h" -} -#include <locale.h> -#endif // LL_GTK +#ifdef LL_GLIB +#include <glib.h> +#endif extern "C" { # include "fontconfig/fontconfig.h" @@ -63,6 +58,7 @@ extern "C" { # include <sys/wait.h> # define GLX_GLXEXT_PROTOTYPES 1 # include <GL/glx.h> +# include <stdio.h> #endif // LL_LINUX extern BOOL gDebugWindowProc; @@ -82,22 +78,22 @@ BOOL gHiDPISupport = TRUE; namespace { - struct NativeKeyEventData { - enum EventType { - KEYUNKNOWN, - KEYUP, - KEYDOWN, - KEYCHAR - }; - - EventType mKeyEvent = KEYUNKNOWN; - uint32_t mEventType = 0; - uint32_t mEventModifiers = 0; - uint32_t mEventKeyCode = 0; - uint32_t mEventChars = 0; - uint32_t mEventUnmodChars = 0; - bool mEventRepeat = false; - } *mRawKeyEvent = NULL; + struct NativeKeyEventData { + enum EventType { + KEYUNKNOWN, + KEYUP, + KEYDOWN, + KEYCHAR + }; + + EventType mKeyEvent = KEYUNKNOWN; + uint32_t mEventType = 0; + uint32_t mEventModifiers = 0; + uint32_t mEventKeyCode = 0; + uint32_t mEventChars = 0; + uint32_t mEventUnmodChars = 0; + bool mEventRepeat = false; + } *mRawKeyEvent = NULL; } // // LLWindowMacOSX @@ -140,102 +136,278 @@ void maybe_unlock_display(void) } -#if LL_GTK -// Lazily initialize and check the runtime GTK version for goodness. +#if LL_X11 // static -bool LLWindowSDL::ll_try_gtk_init(void) +Window LLWindowSDL::get_SDL_XWindowID(void) +{ + if (gWindowImplementation) { + return gWindowImplementation->mSDL_XWindowID; + } + return None; +} + +//static +Display* LLWindowSDL::get_SDL_Display(void) +{ + if (gWindowImplementation) { + return gWindowImplementation->mSDL_Display; + } + return NULL; +} +#endif // LL_X11 + +#if LL_X11 + +// Clipboard handing via native X11, base on the implementation in Cool VL by Henri Beauchamp + +namespace { - static BOOL done_gtk_diag = FALSE; - static BOOL gtk_is_good = FALSE; - static BOOL done_setlocale = FALSE; - static BOOL tried_gtk_init = FALSE; + std::array<Atom, 3> gSupportedAtoms; + + Atom XA_CLIPBOARD; + Atom XA_TARGETS; + Atom PVT_PASTE_BUFFER; + long const MAX_PASTE_BUFFER_SIZE = 16383; - if (!done_setlocale) + void filterSelectionRequest( XEvent aEvent ) { - LL_INFOS() << "Starting GTK Initialization." << LL_ENDL; - maybe_lock_display(); - gtk_disable_setlocale(); - maybe_unlock_display(); - done_setlocale = TRUE; + auto *display = LLWindowSDL::getSDLDisplay(); + auto &request = aEvent.xselectionrequest; + + XSelectionEvent reply { SelectionNotify, aEvent.xany.serial, aEvent.xany.send_event, display, + request.requestor, request.selection, request.target, + request.property,request.time }; + + if (request.target == XA_TARGETS) + { + XChangeProperty(display, request.requestor, request.property, + XA_ATOM, 32, PropModeReplace, + (unsigned char *) &gSupportedAtoms.front(), gSupportedAtoms.size()); + } + else if (std::find(gSupportedAtoms.begin(), gSupportedAtoms.end(), request.target) != + gSupportedAtoms.end()) + { + std::string utf8; + if (request.selection == XA_PRIMARY) + utf8 = wstring_to_utf8str(gWindowImplementation->getPrimaryText()); + else + utf8 = wstring_to_utf8str(gWindowImplementation->getSecondaryText()); + + XChangeProperty(display, request.requestor, request.property, + request.target, 8, PropModeReplace, + (unsigned char *) utf8.c_str(), utf8.length()); + } + else if (request.selection == XA_CLIPBOARD) + { + // Did not have what they wanted, so no property set + reply.property = None; + } + else + return; + + XSendEvent(request.display, request.requestor, False, NoEventMask, (XEvent *) &reply); + XSync(display, False); } - if (!tried_gtk_init) + void filterSelectionClearRequest( XEvent aEvent ) { - tried_gtk_init = TRUE; -#ifndef LL_USESYSTEMLIBS - if (!g_thread_supported ()) g_thread_init (NULL); -#endif - maybe_lock_display(); - gtk_is_good = gtk_init_check(NULL, NULL); - maybe_unlock_display(); - if (!gtk_is_good) - LL_WARNS() << "GTK Initialization failed." << LL_ENDL; + auto &request = aEvent.xselectionrequest; + if (request.selection == XA_PRIMARY) + gWindowImplementation->clearPrimaryText(); + else if (request.selection == XA_CLIPBOARD) + gWindowImplementation->clearSecondaryText(); } - if (gtk_is_good && !done_gtk_diag) + int x11_clipboard_filter(void*, SDL_Event *evt) { - LL_INFOS() << "GTK Initialized." << LL_ENDL; - LL_INFOS() << "- Compiled against GTK version " - << GTK_MAJOR_VERSION << "." - << GTK_MINOR_VERSION << "." - << GTK_MICRO_VERSION << LL_ENDL; - LL_INFOS() << "- Running against GTK version " - << gtk_major_version << "." - << gtk_minor_version << "." - << gtk_micro_version << LL_ENDL; + Display *display = LLWindowSDL::getSDLDisplay(); + if (!display) + return 1; + + if (evt->type != SDL_SYSWMEVENT) + return 1; + + auto xevent = evt->syswm.msg->msg.x11.event; + + if (xevent.type == SelectionRequest) + filterSelectionRequest( xevent ); + else if (xevent.type == SelectionClear) + filterSelectionClearRequest( xevent ); + return 1; + } + + bool grab_property(Display* display, Window window, Atom selection, Atom target) + { + if( !display ) + return false; + maybe_lock_display(); - const gchar* gtk_warning = gtk_check_version( - GTK_MAJOR_VERSION, - GTK_MINOR_VERSION, - GTK_MICRO_VERSION); + + XDeleteProperty(display, window, PVT_PASTE_BUFFER); + XFlush(display); + + XConvertSelection(display, selection, target, PVT_PASTE_BUFFER, window, CurrentTime); + + // Unlock the connection so that the SDL event loop may function maybe_unlock_display(); - if (gtk_warning) + + const auto start{ SDL_GetTicks() }; + const auto end{ start + 1000 }; + + XEvent xevent {}; + bool response = false; + + do { - LL_WARNS() << "- GTK COMPATIBILITY WARNING: " << - gtk_warning << LL_ENDL; - gtk_is_good = FALSE; - } else { - LL_INFOS() << "- GTK version is good." << LL_ENDL; - } + SDL_Event event {}; + + // Wait for an event + SDL_WaitEvent(&event); - done_gtk_diag = TRUE; + // If the event is a window manager event + if (event.type == SDL_SYSWMEVENT) + { + xevent = event.syswm.msg->msg.x11.event; + + if (xevent.type == SelectionNotify && xevent.xselection.requestor == window) + response = true; + } + } while (!response && SDL_GetTicks() < end ); + + return response && xevent.xselection.property != None; } +} + +void LLWindowSDL::initialiseX11Clipboard() +{ + if (!mSDL_Display) + return; - return gtk_is_good; + SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); + SDL_SetEventFilter(x11_clipboard_filter, nullptr); + + maybe_lock_display(); + + XA_CLIPBOARD = XInternAtom(mSDL_Display, "CLIPBOARD", False); + + gSupportedAtoms[0] = XInternAtom(mSDL_Display, "UTF8_STRING", False); + gSupportedAtoms[1] = XInternAtom(mSDL_Display, "COMPOUND_TEXT", False); + gSupportedAtoms[2] = XA_STRING; + + // TARGETS atom + XA_TARGETS = XInternAtom(mSDL_Display, "TARGETS", False); + + // SL_PASTE_BUFFER atom + PVT_PASTE_BUFFER = XInternAtom(mSDL_Display, "FS_PASTE_BUFFER", False); + + maybe_unlock_display(); } -#endif // LL_GTK +bool LLWindowSDL::getSelectionText( Atom aSelection, Atom aType, LLWString &text ) +{ + if( !mSDL_Display ) + return false; -#if LL_X11 -// static -Window LLWindowSDL::get_SDL_XWindowID(void) + if( !grab_property(mSDL_Display, mSDL_XWindowID, aSelection,aType ) ) + return false; + + maybe_lock_display(); + + Atom type; + int format{}; + unsigned long len{},remaining {}; + unsigned char* data = nullptr; + int res = XGetWindowProperty(mSDL_Display, mSDL_XWindowID, + PVT_PASTE_BUFFER, 0, MAX_PASTE_BUFFER_SIZE, False, + AnyPropertyType, &type, &format, &len, + &remaining, &data); + if (data && len) + { + text = LLWString( + utf8str_to_wstring(reinterpret_cast< char const *>( data ) ) + ); + XFree(data); + } + + maybe_unlock_display(); + return res == Success; +} + +bool LLWindowSDL::getSelectionText(Atom selection, LLWString& text) { - if (gWindowImplementation) { - return gWindowImplementation->mSDL_XWindowID; + if (!mSDL_Display) + return false; + + maybe_lock_display(); + + Window owner = XGetSelectionOwner(mSDL_Display, selection); + if (owner == None) + { + if (selection == XA_PRIMARY) + { + owner = DefaultRootWindow(mSDL_Display); + selection = XA_CUT_BUFFER0; + } + else + { + maybe_unlock_display(); + return false; + } } - return None; + + maybe_unlock_display(); + + for( Atom atom : gSupportedAtoms ) + { + if(getSelectionText(selection, atom, text ) ) + return true; + } + + return false; } -//static -Display* LLWindowSDL::get_SDL_Display(void) +bool LLWindowSDL::setSelectionText(Atom selection, const LLWString& text) { - if (gWindowImplementation) { - return gWindowImplementation->mSDL_Display; + maybe_lock_display(); + + if (selection == XA_PRIMARY) + { + std::string utf8 = wstring_to_utf8str(text); + XStoreBytes(mSDL_Display, utf8.c_str(), utf8.length() + 1); + mPrimaryClipboard = text; } - return NULL; + else + mSecondaryClipboard = text; + + XSetSelectionOwner(mSDL_Display, selection, mSDL_XWindowID, CurrentTime); + + auto owner = XGetSelectionOwner(mSDL_Display, selection); + + maybe_unlock_display(); + + return owner == mSDL_XWindowID; } -#endif // LL_X11 + +Display* LLWindowSDL::getSDLDisplay() +{ + if (gWindowImplementation) + return gWindowImplementation->mSDL_Display; + return nullptr; +} + +#endif LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks, - const std::string& title, S32 x, S32 y, S32 width, - S32 height, U32 flags, - BOOL fullscreen, BOOL clearBg, - BOOL disable_vsync, BOOL use_gl, - BOOL ignore_pixel_depth, U32 fsaa_samples) - : LLWindow(callbacks, fullscreen, flags), - Lock_Display(NULL), - Unlock_Display(NULL), mGamma(1.0f) + const std::string& title, S32 x, S32 y, S32 width, + S32 height, U32 flags, + BOOL fullscreen, BOOL clearBg, + BOOL disable_vsync, BOOL use_gl, + BOOL ignore_pixel_depth, U32 fsaa_samples) + : LLWindow(callbacks, fullscreen, flags), + Lock_Display(NULL), + //Unlock_Display(NULL), mGamma(1.0f) + Unlock_Display(NULL), mGamma(1.0f) { // Initialize the keyboard gKeyboard = new LLKeyboardSDL(); @@ -248,6 +420,7 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks, // Ignore use_gl for now, only used for drones on PC mWindow = NULL; + mContext = {}; mNeedsResize = FALSE; mOverrideAspectRatio = 0.f; mGrabbyKeyFlags = 0; @@ -261,13 +434,6 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks, mSDL_Display = NULL; #endif // LL_X11 -#if LL_GTK - // We MUST be the first to initialize GTK so that GTK doesn't get badly - // initialized with a non-C locale and cause lots of serious random - // weirdness. - ll_try_gtk_init(); -#endif // LL_GTK - // Assume 4:3 aspect ratio until we know better mOriginalAspectRatio = 1024.0 / 768.0; @@ -293,9 +459,9 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks, #if LL_X11 mFlashing = FALSE; + initialiseX11Clipboard(); #endif // LL_X11 - mKeyScanCode = 0; mKeyVirtualKey = 0; mKeyModifiers = KMOD_NONE; } @@ -307,16 +473,16 @@ static SDL_Surface *Load_BMP_Resource(const char *basename) // Figure out where our BMP is living on the disk snprintf(path_buffer, PATH_BUFFER_SIZE-1, "%s%sres-sdl%s%s", - gDirUtilp->getAppRODataDir().c_str(), - gDirUtilp->getDirDelimiter().c_str(), - gDirUtilp->getDirDelimiter().c_str(), - basename); + gDirUtilp->getAppRODataDir().c_str(), + gDirUtilp->getDirDelimiter().c_str(), + gDirUtilp->getDirDelimiter().c_str(), + basename); path_buffer[PATH_BUFFER_SIZE-1] = '\0'; return SDL_LoadBMP(path_buffer); } -#if 0 +#if LL_X11 // This is an XFree86/XOrg-specific hack for detecting the amount of Video RAM // on this machine. It works by searching /var/log/var/log/Xorg.?.log or // /var/log/XFree86.?.log for a ': (VideoRAM ?|Memory): (%d+) kB' regex, where @@ -397,7 +563,7 @@ static int x11_detect_VRAM_kb() if (fp) { LL_INFOS() << "Looking in " << fname - << " for VRAM info..." << LL_ENDL; + << " for VRAM info..." << LL_ENDL; rtn = x11_detect_VRAM_kb_fp(fp, ": VideoRAM: "); fclose(fp); if (0 == rtn) @@ -422,7 +588,7 @@ static int x11_detect_VRAM_kb() else { LL_INFOS() << "Could not open " << fname - << " - skipped." << LL_ENDL; + << " - skipped." << LL_ENDL; // Try old XFree86 log otherwise fname = x_log_location; fname += "XFree86."; @@ -432,7 +598,7 @@ static int x11_detect_VRAM_kb() if (fp) { LL_INFOS() << "Looking in " << fname - << " for VRAM info..." << LL_ENDL; + << " for VRAM info..." << LL_ENDL; rtn = x11_detect_VRAM_kb_fp(fp, ": VideoRAM: "); fclose(fp); if (0 == rtn) @@ -448,78 +614,162 @@ static int x11_detect_VRAM_kb() else { LL_INFOS() << "Could not open " << fname - << " - skipped." << LL_ENDL; + << " - skipped." << LL_ENDL; } } return rtn; } #endif // LL_X11 +void LLWindowSDL::setTitle(const std::string title) +{ + SDL_SetWindowTitle( mWindow, title.c_str() ); +} + +void LLWindowSDL::tryFindFullscreenSize( int &width, int &height ) +{ + LL_INFOS() << "createContext: setting up fullscreen " << width << "x" << height << LL_ENDL; + + // 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_INFOS() << "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_INFOS() << "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_INFOS() << " (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; + } +} + BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync) { //bool glneedsinit = false; LL_INFOS() << "createContext, fullscreen=" << fullscreen << - " size=" << width << "x" << height << LL_ENDL; + " size=" << width << "x" << height << LL_ENDL; // captures don't survive contexts mGrabbyKeyFlags = 0; mReallyCapturedCount = 0; - if (SDL_Init(SDL_INIT_VIDEO) < 0) + std::initializer_list<std::tuple< char const*, char const * > > hintList = + { + {SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR,"0"}, + {SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH,"1"}, + {SDL_HINT_IME_INTERNAL_EDITING,"1"} + }; + + for( auto hint: hintList ) { - LL_INFOS() << "sdl_init() failed! " << SDL_GetError() << LL_ENDL; - setupFailure("sdl_init() failure, window creation error", "error", OSMB_OK); - return false; + SDL_SetHint( std::get<0>(hint), std::get<1>(hint)); + } + + std::initializer_list<std::tuple<uint32_t, char const*, bool>> initList= + { {SDL_INIT_VIDEO,"SDL_INIT_VIDEO", true}, + {SDL_INIT_AUDIO,"SDL_INIT_AUDIO", false}, + {SDL_INIT_GAMECONTROLLER,"SDL_INIT_GAMECONTROLLER", false}, + {SDL_INIT_SENSOR,"SDL_INIT_SENSOR", false} + }; + + for( auto subSystem : initList) + { + if( SDL_InitSubSystem( std::get<0>(subSystem) ) < 0 ) + { + LL_WARNS() << "SDL_InitSubSystem for " << std::get<1>(subSystem) << " failed " << SDL_GetError() << LL_ENDL; + + if( std::get<2>(subSystem)) + setupFailure("SDL_Init() failure", "error", OSMB_OK); + + } } SDL_version c_sdl_version; SDL_VERSION(&c_sdl_version); LL_INFOS() << "Compiled against SDL " - << int(c_sdl_version.major) << "." - << int(c_sdl_version.minor) << "." - << int(c_sdl_version.patch) << LL_ENDL; + << int(c_sdl_version.major) << "." + << int(c_sdl_version.minor) << "." + << int(c_sdl_version.patch) << LL_ENDL; SDL_version r_sdl_version; SDL_GetVersion(&r_sdl_version); LL_INFOS() << " Running against SDL " - << int(r_sdl_version.major) << "." - << int(r_sdl_version.minor) << "." - << int(r_sdl_version.patch) << LL_ENDL; + << int(r_sdl_version.major) << "." + << int(r_sdl_version.minor) << "." + << int(r_sdl_version.patch) << LL_ENDL; - SDL_DisplayMode display_mode; - if (SDL_GetDesktopDisplayMode(0, &display_mode) < 0) - { - LL_INFOS() << "SDL_GetVideoInfo() failed! " << SDL_GetError() << LL_ENDL; - setupFailure("SDL_GetVideoInfo() failed, Window creation error", "Error", OSMB_OK); - return FALSE; - } + if (width == 0) + width = 1024; + if (height == 0) + width = 768; + + mFullscreen = fullscreen; - if (display_mode.h > 0) + int sdlflags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; + + if( mFullscreen ) { - mOriginalAspectRatio = (float)display_mode.w / (float)display_mode.h; - LL_INFOS() << "Original aspect ratio was " << display_mode.w << ":" << display_mode.h << "=" << mOriginalAspectRatio << LL_ENDL; + sdlflags |= SDL_WINDOW_FULLSCREEN; + tryFindFullscreenSize( width, height ); } - // note: these SetAttributes make Tom's 9600-on-AMD64 fail to - // get a visual, but it's broken anyway when it does, and without - // these SetAttributes we might easily get an avoidable substandard - // visual to work with on most other machines. - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, (bits <= 16) ? 16 : 24); - // We need stencil support for a few (minor) things. - if (!getenv("LL_GL_NO_STENCIL")) - SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, (bits <= 16) ? 1 : 8); + if(hasHIDPI) sdlflags = sdlflags | SDL_WINDOW_ALLOW_HIGHDPI; - // *FIX: try to toggle vsync here? + mSDLFlags = sdlflags; - mFullscreen = fullscreen; + GLint redBits{8}, greenBits{8}, blueBits{8}, alphaBits{8}; - int sdlflags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;// | SDL_ANYFORMAT; + GLint depthBits{(bits <= 16) ? 16 : 24}, stencilBits{8}; - if(hasHIDPI) sdlflags = sdlflags | SDL_WINDOW_ALLOW_HIGHDPI; + if (getenv("LL_GL_NO_STENCIL")) + stencilBits = 0; + + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, alphaBits); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, redBits); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, greenBits); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, blueBits); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, depthBits ); + + // We need stencil support for a few (minor) things. + if (stencilBits) + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, stencilBits); + // *FIX: try to toggle vsync here? SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); #if LL_DARWIN @@ -537,85 +787,41 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, mFSAASamples); } - mSDLFlags = sdlflags; + SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1); + mWindow = SDL_CreateWindow( mWindowTitle.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, mSDLFlags ); - if (mFullscreen) + if( mWindow ) { - LL_INFOS() << "createContext: setting up fullscreen " << width << "x" << height << LL_ENDL; + mContext = SDL_GL_CreateContext( mWindow ); - // If the requested width or height is 0, find the best default for the monitor. - if((width == 0) || (height == 0)) + if( mContext == 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_INFOS() << "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_INFOS() << "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_INFOS() << " (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; + LL_WARNS() << "Cannot create GL context " << SDL_GetError() << LL_ENDL; + setupFailure("GL Context creation error creation error", "Error", OSMB_OK); + return FALSE; } + // SDL_GL_SetSwapInterval(1); + } - mWindow = SDL_CreateWindow(mWindowTitle.c_str(), - SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - width, height, sdlflags | SDL_WINDOW_FULLSCREEN); - - if (!mWindow && bits > 16) - { - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); - mWindow = SDL_CreateWindow(mWindowTitle.c_str(), - SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - width, height, sdlflags | SDL_WINDOW_FULLSCREEN); - } + if( mFullscreen ) + { if (mWindow) { - SDL_GL_CreateContext(mWindow); mFullscreen = TRUE; + /* + mFullscreenWidth = mSurface->w; + mFullscreenHeight = mSurface->h; + mFullscreenBits = mSurface->format->BitsPerPixel; + */ SDL_GetWindowSize(mWindow, &mFullscreenWidth, &mFullscreenHeight); - //mFullscreenBits = mWindow->format->BitsPerPixel; mFullscreenRefresh = -1; LL_INFOS() << "Running at " << mFullscreenWidth - << "x" << mFullscreenHeight - << "x" << mFullscreenBits - << " @ " << mFullscreenRefresh - << LL_ENDL; + << "x" << mFullscreenHeight + << "x" << mFullscreenBits + << " @ " << mFullscreenRefresh + << LL_ENDL; } else { @@ -629,73 +835,37 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B std::string error = llformat("Unable to run fullscreen at %d x %d.\nRunning in window.", width, height); OSMessageBox(error, "Error", OSMB_OK); + return FALSE; } } - - if(!mFullscreen && (mWindow == NULL)) + else { - if (width == 0) - width = 1024; - if (height == 0) - width = 768; - - LL_INFOS() << "createContext: creating window " << width << "x" << height << "x" << bits << LL_ENDL; - mWindow = SDL_CreateWindow(mWindowTitle.c_str(), - SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - width, height, sdlflags); - if (!mWindow && bits > 16) - { - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); - mWindow = SDL_CreateWindow(mWindowTitle.c_str(), - SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - width, height, sdlflags); - } - if (!mWindow) { LL_WARNS() << "createContext: window creation failure. SDL: " << SDL_GetError() << LL_ENDL; setupFailure("Window creation error", "Error", OSMB_OK); return FALSE; } - SDL_GL_CreateContext(mWindow); - } else if (!mFullscreen && (mWindow != NULL)) - { - LL_INFOS() << "createContext: SKIPPING - !fullscreen, but +mWindow " << width << "x" << height << "x" << bits << LL_ENDL; } - //SDL_EnableUNICODE(1); - SDL_SetWindowTitle(mWindow, mWindowTitle.c_str()); - // Set the application icon. SDL_Surface *bmpsurface; bmpsurface = Load_BMP_Resource("ll_icon.BMP"); if (bmpsurface) { - // This attempts to give a black-keyed mask to the icon. - SDL_SetColorKey(bmpsurface, - SDL_TRUE, - SDL_MapRGB(bmpsurface->format, 0,0,0) ); - SDL_SetWindowIcon(mWindow, bmpsurface); - // The SDL examples cheerfully avoid freeing the icon - // surface, but I'm betting that's leaky. + SDL_SetWindowIcon(mWindow, bmpsurface); SDL_FreeSurface(bmpsurface); bmpsurface = NULL; } // Detect video memory size. -#if LL_DARWIN - CGLRendererInfoObj info = 0; - GLint vram_megabytes = 0; - int num_renderers = 0; - auto err = CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay), - &info, &num_renderers); - if (!err) { - CGLDescribeRenderer(info, 0, kCGLRPVideoMemoryMegabytes, &vram_megabytes); - CGLDestroyRendererInfo(info); +# if LL_X11 + gGLManager.mVRAM = x11_detect_VRAM_kb() / 1024; + if (gGLManager.mVRAM != 0) + { + LL_INFOS() << "X11 log-parser detected " << gGLManager.mVRAM << "MB VRAM." << LL_ENDL; } else - vram_megabytes = 256; - gGLManager.mVRAM = vram_megabytes; -#else + { PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC queryInteger; queryInteger = (PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC) glXGetProcAddressARB((const GLubyte *)"glXQueryCurrentRendererIntegerMESA"); @@ -709,33 +879,53 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B glGetIntegerv(GL_VBO_FREE_MEMORY_ATI, (int *)&vram_megabytes); vram_megabytes /= 1024; } - gGLManager.mVRAM = vram_megabytes; -# endif // LL_DARWIN - if (gGLManager.mVRAM) - LL_INFOS() << "Detected " << gGLManager.mVRAM << "MB VRAM." << LL_ENDL; + } +#elif LL_DARWIN + CGLRendererInfoObj info = 0; + GLint vram_megabytes = 0; + int num_renderers = 0; + auto err = CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay), + &info, &num_renderers); + if (!err) { + CGLDescribeRenderer(info, 0, kCGLRPVideoMemoryMegabytes, &vram_megabytes); + CGLDestroyRendererInfo(info); + } else + vram_megabytes = 256; + gGLManager.mVRAM = vram_megabytes; +# endif // LL_X11 +/* + { + // fallback to letting SDL detect VRAM. + // note: I've not seen SDL's detection ever actually find + // VRAM != 0, but if SDL *does* detect it then that's a bonus. + gGLManager.mVRAM = 0; + if (gGLManager.mVRAM != 0) + { + LL_INFOS() << "SDL detected " << gGLManager.mVRAM << "MB VRAM." << LL_ENDL; + } + } +*/ // If VRAM is not detected, that is handled later // *TODO: Now would be an appropriate time to check for some // explicitly unsupported cards. //const char* RENDERER = (const char*) glGetString(GL_RENDERER); - GLint depthBits, stencilBits, redBits, greenBits, blueBits, alphaBits; - - glGetIntegerv(GL_RED_BITS, &redBits); - glGetIntegerv(GL_GREEN_BITS, &greenBits); - glGetIntegerv(GL_BLUE_BITS, &blueBits); - glGetIntegerv(GL_ALPHA_BITS, &alphaBits); - glGetIntegerv(GL_DEPTH_BITS, &depthBits); - glGetIntegerv(GL_STENCIL_BITS, &stencilBits); + SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &redBits); + SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &greenBits); + SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &blueBits); + SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &alphaBits); + SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &depthBits); + SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &stencilBits); LL_INFOS() << "GL buffer:" << LL_ENDL; - LL_INFOS() << " Red Bits " << S32(redBits) << LL_ENDL; - LL_INFOS() << " Green Bits " << S32(greenBits) << LL_ENDL; - LL_INFOS() << " Blue Bits " << S32(blueBits) << LL_ENDL; - LL_INFOS() << " Alpha Bits " << S32(alphaBits) << LL_ENDL; - LL_INFOS() << " Depth Bits " << S32(depthBits) << LL_ENDL; - LL_INFOS() << " Stencil Bits " << S32(stencilBits) << LL_ENDL; + LL_INFOS() << " Red Bits " << S32(redBits) << LL_ENDL; + LL_INFOS() << " Green Bits " << S32(greenBits) << LL_ENDL; + LL_INFOS() << " Blue Bits " << S32(blueBits) << LL_ENDL; + LL_INFOS() << " Alpha Bits " << S32(alphaBits) << LL_ENDL; + LL_INFOS() << " Depth Bits " << S32(depthBits) << LL_ENDL; + LL_INFOS() << " Stencil Bits " << S32(stencilBits) << LL_ENDL; GLint colorBits = redBits + greenBits + blueBits + alphaBits; // fixme: actually, it's REALLY important for picking that we get at @@ -746,34 +936,17 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B #if 0 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); + "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; #endif } -#if 0 // *FIX: we're going to brave it for now... - 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; - } -#endif - #if LL_X11 /* Grab the window manager specific information */ SDL_SysWMinfo info; @@ -785,40 +958,28 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B { mSDL_Display = info.info.x11.display; mSDL_XWindowID = info.info.x11.window; - /* - Lock_Display = info.info.x11.lock_func; - Unlock_Display = info.info.x11.unlock_func; - */ } else { LL_WARNS() << "We're not running under X11? Wild." - << LL_ENDL; + << LL_ENDL; } } else { LL_WARNS() << "We're not running under any known WM. Wild." - << LL_ENDL; + << LL_ENDL; } #endif // LL_X11 + SDL_StartTextInput(); //make sure multisampling is disabled by default #if GL_VERSION_1_3 glDisable(GL_MULTISAMPLE_ARB); #endif - // We need to do this here, once video is init'd - /* - if (-1 == SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, - SDL_DEFAULT_REPEAT_INTERVAL)) - LL_WARNS() << "Couldn't enable key-repeat: " << SDL_GetError() <<LL_ENDL; - */ - // Don't need to get the current gamma, since there's a call that restores it to the system defaults. - - return TRUE; } @@ -854,6 +1015,7 @@ void LLWindowSDL::destroyContext() { LL_INFOS() << "destroyContext begins" << LL_ENDL; + SDL_StopTextInput(); #if LL_X11 mSDL_Display = NULL; mSDL_XWindowID = None; @@ -886,6 +1048,7 @@ LLWindowSDL::~LLWindowSDL() void LLWindowSDL::show() { + // *FIX: What to do with SDL? if (mWindow) { SDL_ShowWindow(mWindow); @@ -894,35 +1057,27 @@ void LLWindowSDL::show() void LLWindowSDL::hide() { + // *FIX: What to do with SDL? if (mWindow) { SDL_HideWindow(mWindow); } } +//virtual void LLWindowSDL::minimize() { + // *FIX: What to do with SDL? if (mWindow) { SDL_MinimizeWindow(mWindow); } } -BOOL LLWindowSDL::maximize() -{ - BOOL result = FALSE; - - if (mWindow) - { - SDL_MaximizeWindow(mWindow); - result = TRUE; - } - - return result; -} - +//virtual void LLWindowSDL::restore() { + // *FIX: What to do with SDL? if (mWindow) { SDL_RestoreWindow(mWindow); @@ -956,6 +1111,8 @@ BOOL LLWindowSDL::getVisible() { BOOL result = FALSE; + // *FIX: This isn't really right... + // Then what is? if (mWindow) { if( SDL_GetWindowFlags(mWindow) & SDL_WINDOW_SHOWN ) result = TRUE; @@ -968,7 +1125,7 @@ BOOL LLWindowSDL::getMinimized() { BOOL result = FALSE; - if (mWindow) + if (mWindow/*&& (1 == mIsMinimized)*/) { if( SDL_GetWindowFlags(mWindow) & SDL_WINDOW_MINIMIZED ) result = TRUE; } @@ -983,6 +1140,7 @@ BOOL LLWindowSDL::getMaximized() if (mWindow) { + // TODO if( SDL_GetWindowFlags(mWindow) & SDL_WINDOW_MAXIMIZED ) result = TRUE; else result = FALSE; } @@ -990,6 +1148,20 @@ BOOL LLWindowSDL::getMaximized() return(result); } +BOOL LLWindowSDL::maximize() +{ + // TODO + BOOL result = FALSE; + + if (mWindow) + { + SDL_MaximizeWindow(mWindow); + result = TRUE; + } + + return result; +} + BOOL LLWindowSDL::getFullscreen() { return mFullscreen; @@ -1009,17 +1181,10 @@ BOOL LLWindowSDL::getSize(LLCoordScreen *size) { /* if(hasHIDPI) - { SDL_GL_GetDrawableSize(mWindow, &size->mX, &size->mY); - } else - { - SDL_GetWindowSize(mWindow, &size->mX, &size->mY); - } */ - SDL_GetWindowSize(mWindow, &size->mX, &size->mY); - return (TRUE); } @@ -1031,14 +1196,9 @@ BOOL LLWindowSDL::getSize(LLCoordWindow *size) if (mWindow) { if(hasHIDPI) - { SDL_GL_GetDrawableSize(mWindow, &size->mX, &size->mY); - } else - { SDL_GetWindowSize(mWindow, &size->mX, &size->mY); - } - return (TRUE); } @@ -1051,6 +1211,8 @@ BOOL LLWindowSDL::setPosition(const LLCoordScreen position) if(mWindow) { + // *FIX: (?) + //MacMoveWindow(mWindow, position.mX, position.mY, false); SDL_SetWindowPosition(mWindow, position.mX, position.mY); result = TRUE; } @@ -1058,42 +1220,37 @@ BOOL LLWindowSDL::setPosition(const LLCoordScreen position) return result; } -BOOL LLWindowSDL::setSizeImpl(const LLCoordScreen size) +template< typename T > bool setSizeImpl( const T& newSize, SDL_Window *pWin ) { - if(mWindow) - { - // Push a resize event onto SDL's queue - we'll handle it - // when it comes out again. - SDL_Event event; - event.type = SDL_WINDOWEVENT; - event.window.event = SDL_WINDOWEVENT_RESIZED; - event.window.data1 = size.mX; - event.window.data2 = size.mY; - SDL_PushEvent(&event); // copied into queue + if( !pWin ) + return false; - return TRUE; - } + auto nFlags = SDL_GetWindowFlags( pWin ); - return FALSE; + if( nFlags & SDL_WINDOW_MAXIMIZED ) + SDL_RestoreWindow( pWin ); + + + SDL_SetWindowSize( pWin, newSize.mX, newSize.mY ); + SDL_Event event; + event.type = SDL_WINDOWEVENT; + event.window.event = SDL_WINDOWEVENT_RESIZED; + event.window.windowID = SDL_GetWindowID( pWin ); + event.window.data1 = newSize.mX; + event.window.data2 = newSize.mY; + SDL_PushEvent( &event ); + + return true; } -BOOL LLWindowSDL::setSizeImpl(const LLCoordWindow size) +BOOL LLWindowSDL::setSizeImpl(const LLCoordScreen size) { - if(mWindow) - { - // Push a resize event onto SDL's queue - we'll handle it - // when it comes out again. - SDL_Event event; - event.type = SDL_WINDOWEVENT; - event.window.event = SDL_WINDOWEVENT_RESIZED; - event.window.data1 = size.mX; - event.window.data2 = size.mY; - SDL_PushEvent(&event); // copied into queue - - return TRUE; - } + return ::setSizeImpl( size, mWindow ); +} - return FALSE; +BOOL LLWindowSDL::setSizeImpl(const LLCoordWindow size) +{ + return ::setSizeImpl( size, mWindow ); } @@ -1101,7 +1258,7 @@ void LLWindowSDL::swapBuffers() { if (mWindow) { - SDL_GL_SwapWindow(mWindow); + SDL_GL_SwapWindow( mWindow ); U32 mode = gSavedSettings.getU32("MPVBufferOptiMode"); if (mode == 0) { @@ -1135,6 +1292,7 @@ F32 LLWindowSDL::getGamma() BOOL LLWindowSDL::restoreGamma() { //CGDisplayRestoreColorSyncSettings(); + // SDL_SetGamma(1.0f, 1.0f, 1.0f); Uint16 ramp; SDL_CalculateGammaRamp(1.0f, &ramp); SDL_SetWindowGammaRamp(mWindow, &ramp, &ramp, &ramp); @@ -1146,6 +1304,7 @@ BOOL LLWindowSDL::setGamma(const F32 gamma) mGamma = gamma; if (mGamma == 0) mGamma = 0.1f; mGamma = 1/mGamma; + // SDL_SetGamma(mGamma, mGamma, mGamma); Uint16 ramp; SDL_CalculateGammaRamp(mGamma, &ramp); SDL_SetWindowGammaRamp(mWindow, &ramp, &ramp, &ramp); @@ -1184,36 +1343,6 @@ void LLWindowSDL::setMinSize(U32 min_width, U32 min_height, bool enforce_immedia #endif } -void *LLWindowSDL::createSharedContext() -{ - // *FIX: What to do with SDL? - return nullptr; -} - -void LLWindowSDL::makeContextCurrent(void* context) -{ - // *FIX: What to do with SDL? -} - -void LLWindowSDL::destroySharedContext(void* context) -{ - // *FIX: What to do with SDL? -} - -void LLWindowSDL::toggleVSync(bool enable_vsync) -{ - if( !enable_vsync) - { - SDL_GL_SetSwapInterval(0); - SDL_SetHintWithPriority(SDL_HINT_RENDER_VSYNC,"0",SDL_HINT_OVERRIDE); - } - else - { - SDL_GL_SetSwapInterval(1); - SDL_SetHintWithPriority(SDL_HINT_RENDER_VSYNC,"1",SDL_HINT_OVERRIDE); - } -} - BOOL LLWindowSDL::setCursorPosition(const LLCoordWindow position) { BOOL result = TRUE; @@ -1224,13 +1353,19 @@ BOOL LLWindowSDL::setCursorPosition(const LLCoordWindow position) return FALSE; } + //LL_INFOS() << "setCursorPosition(" << screen_pos.mX << ", " << screen_pos.mY << ")" << LL_ENDL; + // do the actual forced cursor move. if (mFullscreen) + { SDL_WarpMouseGlobal(screen_pos.mX, screen_pos.mY); - else - SDL_WarpMouseInWindow(mWindow, screen_pos.mX, screen_pos.mY); + return result; + } + + SDL_WarpMouseInWindow(mWindow, screen_pos.mX, screen_pos.mY); + //LL_INFOS() << llformat("llcw %d,%d -> scr %d,%d", position.mX, position.mY, screen_pos.mX, screen_pos.mY) << LL_ENDL; return result; } @@ -1258,18 +1393,6 @@ F32 LLWindowSDL::getSystemUISize() F32 LLWindowSDL::getNativeAspectRatio() { -#if 0 - // RN: this hack presumes that the largest supported resolution is monitor-limited - // and that pixels in that mode are square, therefore defining the native aspect ratio - // of the monitor...this seems to work to a close approximation for most CRTs/LCDs - S32 num_resolutions; - LLWindowResolution* resolutions = getSupportedResolutions(num_resolutions); - - - return ((F32)resolutions[num_resolutions - 1].mWidth / (F32)resolutions[num_resolutions - 1].mHeight); - //rn: AC -#endif - // MBW -- there are a couple of bad assumptions here. One is that the display list won't include // ridiculous resolutions nobody would ever use. The other is that the list is in order. @@ -1310,12 +1433,6 @@ F32 LLWindowSDL::getPixelAspectRatio() return pixel_aspect; } -U32 LLWindowSDL::getAvailableVRAMMegabytes() -{ - static const U32 mb = 1024*1024; - static const U32 total_factor = 2; - return gGLManager.mVRAM - (LLImageGL::getTextureBytesAllocated() * total_factor/mb); -} // This is to support 'temporarily windowed' mode so that // dialogs are still usable in fullscreen. @@ -1337,7 +1454,7 @@ void LLWindowSDL::beforeDialog() // it only works in X11 if (running_x11 && mWindow) { - SDL_SetWindowFullscreen(mWindow, SDL_WINDOW_FULLSCREEN); + SDL_SetWindowFullscreen( mWindow, 0 ); } } } @@ -1353,12 +1470,6 @@ void LLWindowSDL::beforeDialog() } #endif // LL_X11 -#if LL_GTK - // this is a good time to grab some GTK version information for - // diagnostics, if not already done. - ll_try_gtk_init(); -#endif // LL_GTK - maybe_lock_display(); } @@ -1379,7 +1490,7 @@ void LLWindowSDL::afterDialog() // in X11 if (running_x11 && mWindow) { - SDL_SetWindowFullscreen(mWindow, SDL_WINDOW_FULLSCREEN); + SDL_SetWindowFullscreen( mWindow, 0 ); } } } @@ -1415,118 +1526,39 @@ void LLWindowSDL::x11_set_urgent(BOOL urgent) void LLWindowSDL::flashIcon(F32 seconds) { + if (getMinimized()) + { #if !LL_X11 - LL_INFOS() << "Stub LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL; + LL_INFOS() << "Stub LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL; #else - LL_INFOS() << "X11 LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL; + LL_INFOS() << "X11 LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL; - F32 remaining_time = mFlashTimer.getRemainingTimeF32(); - if (remaining_time < seconds) - remaining_time = seconds; - mFlashTimer.reset(); - mFlashTimer.setTimerExpirySec(remaining_time); + F32 remaining_time = mFlashTimer.getRemainingTimeF32(); + if (remaining_time < seconds) + remaining_time = seconds; + mFlashTimer.reset(); + mFlashTimer.setTimerExpirySec(remaining_time); - x11_set_urgent(TRUE); - mFlashing = TRUE; + x11_set_urgent(TRUE); + mFlashing = TRUE; #endif // LL_X11 -} - - -#if LL_GTK -BOOL LLWindowSDL::isClipboardTextAvailable() -{ - if (ll_try_gtk_init()) - { - GtkClipboard * const clipboard = - gtk_clipboard_get(GDK_NONE); - return gtk_clipboard_wait_is_text_available(clipboard) ? - TRUE : FALSE; - } - return FALSE; // failure -} - -BOOL LLWindowSDL::pasteTextFromClipboard(LLWString &text) -{ - if (ll_try_gtk_init()) - { - GtkClipboard * const clipboard = - gtk_clipboard_get(GDK_NONE); - gchar * const data = gtk_clipboard_wait_for_text(clipboard); - if (data) - { - text = LLWString(utf8str_to_wstring(data)); - g_free(data); - return TRUE; - } - } - return FALSE; // failure -} - -BOOL LLWindowSDL::copyTextToClipboard(const LLWString &text) -{ - if (ll_try_gtk_init()) - { - const std::string utf8 = wstring_to_utf8str(text); - GtkClipboard * const clipboard = - gtk_clipboard_get(GDK_NONE); - gtk_clipboard_set_text(clipboard, utf8.c_str(), utf8.length()); - return TRUE; } - return FALSE; // failure } - -BOOL LLWindowSDL::isPrimaryTextAvailable() -{ - if (ll_try_gtk_init()) - { - GtkClipboard * const clipboard = - gtk_clipboard_get(GDK_SELECTION_PRIMARY); - return gtk_clipboard_wait_is_text_available(clipboard) ? - TRUE : FALSE; - } - return FALSE; // failure -} - -BOOL LLWindowSDL::pasteTextFromPrimary(LLWString &text) -{ - if (ll_try_gtk_init()) - { - GtkClipboard * const clipboard = - gtk_clipboard_get(GDK_SELECTION_PRIMARY); - gchar * const data = gtk_clipboard_wait_for_text(clipboard); - if (data) - { - text = LLWString(utf8str_to_wstring(data)); - g_free(data); - return TRUE; - } - } - return FALSE; // failure -} - -BOOL LLWindowSDL::copyTextToPrimary(const LLWString &text) -{ - if (ll_try_gtk_init()) - { - const std::string utf8 = wstring_to_utf8str(text); - GtkClipboard * const clipboard = - gtk_clipboard_get(GDK_SELECTION_PRIMARY); - gtk_clipboard_set_text(clipboard, utf8.c_str(), utf8.length()); - return TRUE; - } - return FALSE; // failure -} - -#else - BOOL LLWindowSDL::isClipboardTextAvailable() { +#if LL_X11 + return mSDL_Display && XGetSelectionOwner(mSDL_Display, XA_CLIPBOARD) != None; +#else return SDL_HasClipboardText(); +#endif } BOOL LLWindowSDL::pasteTextFromClipboard(LLWString &dst) { +#if LL_X11 + return getSelectionText(XA_CLIPBOARD, dst); +#else auto data = SDL_GetClipboardText(); if (data) { @@ -1535,30 +1567,46 @@ BOOL LLWindowSDL::pasteTextFromClipboard(LLWString &dst) return TRUE; } return FALSE; +#endif } BOOL LLWindowSDL::copyTextToClipboard(const LLWString &s) { +#if LL_X11 + return setSelectionText(XA_CLIPBOARD, s); +#else return !SDL_SetClipboardText(wstring_to_utf8str(s).c_str()); +#endif } BOOL LLWindowSDL::isPrimaryTextAvailable() { +#if LL_X11 + LLWString text; + return getSelectionText(XA_PRIMARY, text) && !text.empty(); +#else return FALSE; // unsupported +#endif } BOOL LLWindowSDL::pasteTextFromPrimary(LLWString &dst) { +#if LL_X11 + return getSelectionText(XA_PRIMARY, dst); +#else return FALSE; // unsupported +#endif } BOOL LLWindowSDL::copyTextToPrimary(const LLWString &s) { - return FALSE; // unsupported +#if LL_X11 + return setSelectionText(XA_PRIMARY, s); +#else + return FALSE; // unsupported +#endif } -#endif // LL_GTK - LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_resolutions) { if (!mSupportedResolutions) @@ -1566,43 +1614,33 @@ LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_reso mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS]; mNumSupportedResolutions = 0; - /* - SDL_Rect **modes = SDL_ListModes(NULL, SDL_OPENGL | SDL_FULLSCREEN); - if ( (modes != NULL) && (modes != ((SDL_Rect **) -1)) ) + // <FS:ND> Use display no from mWindow/mSurface here? + int max = SDL_GetNumDisplayModes(0); + max = llclamp( max, 0, MAX_NUM_RESOLUTIONS ); + + for( int i =0; i < max; ++i ) { - int count = 0; - while (*modes && count<MAX_NUM_RESOLUTIONS) // they're sorted biggest to smallest, so find end... + SDL_DisplayMode mode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 }; + if (SDL_GetDisplayMode( 0 , i, &mode) != 0) { - modes++; - count++; + continue; } - while (count--) + int w = mode.w; + int h = mode.h; + if ((w >= 800) && (h >= 600)) { - modes--; - SDL_Rect *r = *modes; - */ - static int display_in_use = 0; // Only using first display - auto display_mode_count = SDL_GetNumDisplayModes(display_in_use); - SDL_DisplayMode mode; - for (int i = 0; i < display_mode_count; ++i) { - SDL_GetDisplayMode(display_in_use, i, &mode); - int w = mode.w; - int h = mode.h; - if ((w >= 800) && (h >= 600)) + // make sure we don't add the same resolution multiple times! + if ( (mNumSupportedResolutions == 0) || + ((mSupportedResolutions[mNumSupportedResolutions-1].mWidth != w) && + (mSupportedResolutions[mNumSupportedResolutions-1].mHeight != h)) ) { - // make sure we don't add the same resolution multiple times! - if ( (mNumSupportedResolutions == 0) || - ((mSupportedResolutions[mNumSupportedResolutions-1].mWidth != w) && - (mSupportedResolutions[mNumSupportedResolutions-1].mHeight != h)) ) - { - mSupportedResolutions[mNumSupportedResolutions].mWidth = w; - mSupportedResolutions[mNumSupportedResolutions].mHeight = h; - mNumSupportedResolutions++; - } + mSupportedResolutions[mNumSupportedResolutions].mWidth = w; + mSupportedResolutions[mNumSupportedResolutions].mHeight = h; + mNumSupportedResolutions++; } } - //} + } } num_resolutions = mNumSupportedResolutions; @@ -1691,13 +1729,13 @@ BOOL LLWindowSDL::SDLReallyCaptureInput(BOOL capture) else mReallyCapturedCount = 0; - SDL_bool wantmode, newmode; + bool wantGrab; if (mReallyCapturedCount <= 0) // uncapture { - wantmode = SDL_FALSE; + wantGrab = false; } else // capture { - wantmode = SDL_TRUE; + wantGrab = true; } if (mReallyCapturedCount < 0) // yuck, imbalance. @@ -1706,9 +1744,11 @@ BOOL LLWindowSDL::SDLReallyCaptureInput(BOOL capture) LL_WARNS() << "ReallyCapture count was < 0" << LL_ENDL; } + bool newGrab = wantGrab; + +#if LL_X11 if (!mFullscreen) /* only bother if we're windowed anyway */ { -#if LL_X11 if (mSDL_Display) { /* we dirtily mix raw X11 with SDL so that our pointer @@ -1721,49 +1761,37 @@ BOOL LLWindowSDL::SDLReallyCaptureInput(BOOL capture) *keyboard* input from the window manager, which was frustrating users. */ int result; - if (wantmode == SDL_TRUE) + if (wantGrab == true) { - //LL_INFOS() << "X11 POINTER GRABBY" << LL_ENDL; - //newmode = SDL_WM_GrabInput(wantmode); maybe_lock_display(); result = XGrabPointer(mSDL_Display, mSDL_XWindowID, - True, 0, GrabModeAsync, - GrabModeAsync, - None, None, CurrentTime); + True, 0, GrabModeAsync, + GrabModeAsync, + None, None, CurrentTime); maybe_unlock_display(); if (GrabSuccess == result) - newmode = SDL_TRUE; + newGrab = true; else - newmode = SDL_FALSE; - } else if (wantmode == SDL_FALSE) + newGrab = false; + } + else { - //LL_INFOS() << "X11 POINTER UNGRABBY" << LL_ENDL; - newmode = SDL_FALSE; - //newmode = SDL_WM_GrabInput(SDL_GRAB_OFF); + newGrab = false; maybe_lock_display(); XUngrabPointer(mSDL_Display, CurrentTime); // Make sure the ungrab happens RIGHT NOW. XSync(mSDL_Display, False); maybe_unlock_display(); - } else - { - //newmode = SDL_GRAB_QUERY; // neutral } - } else // not actually running on X11, for some reason - newmode = wantmode; -#endif // LL_X11 - } else { - // pretend we got what we wanted, when really we don't care. - newmode = wantmode; + } } - +#endif // LL_X11 // return boolean success for whether we ended up in the desired state - return (capture && SDL_TRUE==newmode) || - (!capture && SDL_FALSE==newmode); + return capture == newGrab; } -U32 LLWindowSDL::SDLCheckGrabbyKeys(SDL_Keycode keysym, BOOL gain) +U32 LLWindowSDL::SDLCheckGrabbyKeys(U32 keysym, BOOL gain) { /* part of the fix for SL-13243: Some popular window managers like to totally eat alt-drag for the purposes of moving windows. We @@ -1781,16 +1809,16 @@ U32 LLWindowSDL::SDLCheckGrabbyKeys(SDL_Keycode keysym, BOOL gain) U32 mask = 0; switch (keysym) { - case SDLK_LALT: - mask = 1U << 0; break; - case SDLK_RALT: - mask = 1U << 1; break; - case SDLK_LCTRL: - mask = 1U << 2; break; - case SDLK_RCTRL: - mask = 1U << 3; break; - default: - break; + case SDLK_LALT: + mask = 1U << 0; break; + case SDLK_RALT: + mask = 1U << 1; break; + case SDLK_LCTRL: + mask = 1U << 2; break; + case SDLK_RCTRL: + mask = 1U << 3; break; + default: + break; } if (gain) @@ -1888,7 +1916,7 @@ void check_vm_bloat() last_rss_size = this_rss_size; last_vm_size = this_vm_size; -finally: + finally: if (NULL != ptr) { free(ptr); @@ -1903,33 +1931,17 @@ finally: // virtual void LLWindowSDL::processMiscNativeEvents() { -#if LL_GTK - // Pump GTK events to avoid starvation for: - // * DBUS servicing - // * Anything else which quietly hooks into the default glib/GTK loop - if (ll_try_gtk_init()) - { - // Yuck, Mozilla's GTK callbacks play with the locale - push/pop - // the locale to protect it, as exotic/non-C locales - // causes our code lots of general critical weirdness - // and crashness. (SL-35450) - static std::string saved_locale; - saved_locale = ll_safe_string(setlocale(LC_ALL, NULL)); - - // Pump until we've nothing left to do or passed 1/15th of a - // second pumping for this frame. - static LLTimer pump_timer; - pump_timer.reset(); - pump_timer.setTimerExpirySec(1.0f / 15.0f); - do { - // Always do at least one non-blocking pump - gtk_main_iteration_do(FALSE); - } while (gtk_events_pending() && - !pump_timer.hasExpired()); - - setlocale(LC_ALL, saved_locale.c_str() ); - } -#endif // LL_GTK +#if LL_GLIB + // Pump until we've nothing left to do or passed 1/15th of a + // second pumping for this frame. + static LLTimer pump_timer; + pump_timer.reset(); + pump_timer.setTimerExpirySec(1.0f / 15.0f); + do + { + g_main_context_iteration(g_main_context_default(), FALSE); + } while( g_main_context_pending(g_main_context_default()) && !pump_timer.hasExpired()); +#endif // hack - doesn't belong here - but this is just for debugging if (getenv("LL_DEBUG_BLOAT")) @@ -1952,40 +1964,11 @@ void LLWindowSDL::gatherInput() { switch (event.type) { - case SDL_KEYDOWN: - mKeyScanCode = event.key.keysym.scancode; - mKeyModifiers = event.key.keysym.mod; - - gKeyboard->handleKeyDown(event.key.keysym.sym, event.key.keysym.mod); - // part of the fix for SL-13243 - if (SDLCheckGrabbyKeys(event.key.keysym.sym, TRUE) != 0) - SDLReallyCaptureInput(TRUE); - - if (event.key.keysym.sym < SDLK_SPACE) - { - handleUnicodeUTF16(event.key.keysym.sym, - gKeyboard->currentMask(FALSE)); - } - break; - - case SDL_TEXTINPUT: - mCallbacks->handleUnicodeString(event.text.text, false); + case SDL_MOUSEWHEEL: + if( event.wheel.y != 0 ) + mCallbacks->handleScrollWheel(this, -event.wheel.y); break; - case SDL_TEXTEDITING: - mCallbacks->handleUnicodeString(event.edit.text, true); - break; - - case SDL_KEYUP: - mKeyScanCode = event.key.keysym.scancode; - mKeyModifiers = event.key.keysym.mod; - - if (SDLCheckGrabbyKeys(event.key.keysym.sym, FALSE) == 0) - SDLReallyCaptureInput(FALSE); // part of the fix for SL-13243 - - gKeyboard->handleKeyUp(event.key.keysym.sym, event.key.keysym.mod); - break; - case SDL_MOUSEMOTION: { LLCoordWindow winCoord(event.button.x, event.button.y); @@ -2002,6 +1985,69 @@ void LLWindowSDL::gatherInput() break; } + case SDL_TEXTINPUT: + { + auto string = utf8str_to_utf16str( event.text.text ); + mKeyModifiers = gKeyboard->currentMask( FALSE ); + mInputType = "textinput"; + for( auto key: string ) + { + mKeyVirtualKey = key; + + if( (MASK_CONTROL|MASK_ALT)&mKeyModifiers ) + gKeyboard->handleKeyDown(mKeyVirtualKey, mKeyModifiers ); + else + handleUnicodeUTF16( key, mKeyModifiers ); + } + break; + } + + case SDL_KEYDOWN: + mKeyVirtualKey = event.key.keysym.sym; + mKeyModifiers = event.key.keysym.mod; + mInputType = "keydown"; + + // treat all possible Enter/Return keys the same + if (mKeyVirtualKey == SDLK_RETURN2 || mKeyVirtualKey == SDLK_KP_ENTER) + { + mKeyVirtualKey = SDLK_RETURN; + } + + gKeyboard->handleKeyDown(mKeyVirtualKey, mKeyModifiers ); + + // <FS:ND> Slightly hacky :| To make the viewer honor enter (eg to accept form input) we've to not only send handleKeyDown but also send a + // invoke handleUnicodeUTF16 in case the user hits return. + // Note that we cannot blindly use handleUnicodeUTF16 for each SDL_KEYDOWN. Doing so will create bogus keyboard input (like % for cursor left). + if( mKeyVirtualKey == SDLK_RETURN ) + { + // fix return key not working when capslock, scrolllock or numlock are enabled + mKeyModifiers &= (~(KMOD_NUM | KMOD_CAPS | KMOD_MODE | KMOD_SCROLL)); + handleUnicodeUTF16( mKeyVirtualKey, mKeyModifiers ); + } + + // part of the fix for SL-13243 + if (SDLCheckGrabbyKeys(event.key.keysym.sym, TRUE) != 0) + SDLReallyCaptureInput(TRUE); + + break; + + case SDL_KEYUP: + mKeyVirtualKey = event.key.keysym.sym; + mKeyModifiers = event.key.keysym.mod; + mInputType = "keyup"; + + // treat all possible Enter/Return keys the same + if (mKeyVirtualKey == SDLK_RETURN2 || mKeyVirtualKey == SDLK_KP_ENTER) + { + mKeyVirtualKey = SDLK_RETURN; + } + + if (SDLCheckGrabbyKeys(mKeyVirtualKey, FALSE) == 0) + SDLReallyCaptureInput(FALSE); // part of the fix for SL-13243 + + gKeyboard->handleKeyUp(mKeyVirtualKey,mKeyModifiers); + break; + case SDL_MOUSEBUTTONDOWN: { bool isDoubleClick = false; @@ -2052,25 +2098,24 @@ void LLWindowSDL::gatherInput() else mCallbacks->handleMouseDown(this, openGlCoord, mask); } + else if (event.button.button == SDL_BUTTON_RIGHT) // right { mCallbacks->handleRightMouseDown(this, openGlCoord, mask); } + else if (event.button.button == SDL_BUTTON_MIDDLE) // middle { mCallbacks->handleMiddleMouseDown(this, openGlCoord, mask); } + else if (event.button.button == 4) // mousewheel up...thanks to X11 for making SDL consider these "buttons". + mCallbacks->handleScrollWheel(this, -1); + else if (event.button.button == 5) // mousewheel down...thanks to X11 for making SDL consider these "buttons". + mCallbacks->handleScrollWheel(this, 1); break; } - case SDL_MOUSEWHEEL: - if (event.wheel.y > 0) // mousewheel up - mCallbacks->handleScrollWheel(this, -1); - else if (event.wheel.y < 0) // mousewheel down - mCallbacks->handleScrollWheel(this, 1); - break; - case SDL_MOUSEBUTTONUP: { LLCoordWindow winCoord(event.button.x, event.button.y); @@ -2093,40 +2138,20 @@ void LLWindowSDL::gatherInput() break; } - case SDL_WINDOWEVENT: + case SDL_WINDOWEVENT: // *FIX: handle this? { - if (event.window.event == SDL_WINDOWEVENT_EXPOSED) - { // VIDEOEXPOSE doesn't specify the damage, but hey, it's OpenGL...repaint the whole thing! - int w, h; - //SDL_GetWindowSize(mWindow, &w, &h); - SDL_GL_GetDrawableSize(mWindow, &w, &h); - - mCallbacks->handlePaint(this, 0, 0, w, h); - } - else if (event.window.event == SDL_WINDOWEVENT_RESIZED) + if( event.window.event == SDL_WINDOWEVENT_RESIZED + /* || event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED*/ ) // <FS:ND> SDL_WINDOWEVENT_SIZE_CHANGED is followed by SDL_WINDOWEVENT_RESIZED, so handling one shall be enough { - LL_INFOS() << "Handling a resize event: " << event.window.data1 << - "x" << event.window.data2 << LL_ENDL; + LL_INFOS() << "Handling a resize event: " << event.window.data1 << "x" << event.window.data2 << LL_ENDL; S32 width = llmax(event.window.data1, (S32)mMinWindowWidth); S32 height = llmax(event.window.data2, (S32)mMinWindowHeight); // *FIX: I'm not sure this is necessary! - /* - mWindow = SDL_SetVideoMode(width, height, 32, mSDLFlags); - if (!mWindow) - { - // *FIX: More informative dialog? - LL_INFOS() << "Could not recreate context after resize! Quitting..." << LL_ENDL; - if(mCallbacks->handleCloseRequest(this)) - { - // Get the app to initiate cleanup. - mCallbacks->handleQuit(this); - // The app is responsible for calling destroyWindow when done with GL - } - break; - } - */ + // <FS:ND> I think is is not + // SDL_SetWindowSize(mWindow, width, height); + // mCallbacks->handleResize(this, width * getSystemUISize(), height * getSystemUISize()); } @@ -2142,17 +2167,23 @@ void LLWindowSDL::gatherInput() if(mHaveInputFocus) mCallbacks->handleFocusLost(this); mHaveInputFocus = FALSE; } - else if (event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED) + else if( event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED ) // <FS:ND> What about SDL_WINDOWEVENT_ENTER (mouse focus) { - LL_INFOS() << "SDL_WINDOWEVENT_FOCUS_GAINED" << LL_ENDL; - if(!mHaveInputFocus) mCallbacks->handleFocus(this); - mHaveInputFocus = TRUE; + // We have to do our own state massaging because SDL + // can send us two unfocus events in a row for example, + // which confuses the focus code [SL-24071]. + mHaveInputFocus = true; + + mCallbacks->handleFocus(this); } - else if (event.window.event == SDL_WINDOWEVENT_FOCUS_LOST) + else if( event.window.event == SDL_WINDOWEVENT_FOCUS_LOST ) // <FS:ND> What about SDL_WINDOWEVENT_LEAVE (mouse focus) { - LL_INFOS() << "SDL_WINDOWEVENT_FOCUS_LOST" << LL_ENDL; - if(mHaveInputFocus) mCallbacks->handleFocusLost(this); - mHaveInputFocus = FALSE; + // We have to do our own state massaging because SDL + // can send us two unfocus events in a row for example, + // which confuses the focus code [SL-24071]. + mHaveInputFocus = false; + + mCallbacks->handleFocusLost(this); } /* @@ -2171,9 +2202,27 @@ void LLWindowSDL::gatherInput() mIsMinimized = FALSE; } */ - } - break; + else if (event.window.event == SDL_WINDOWEVENT_EXPOSED) + { + int w, h; + SDL_GL_GetDrawableSize(mWindow, &w, &h); + mCallbacks->handlePaint(this, 0, 0, w, h); + } + else if( event.window.event == SDL_WINDOWEVENT_MINIMIZED || + event.window.event == SDL_WINDOWEVENT_MAXIMIZED || + event.window.event == SDL_WINDOWEVENT_RESTORED || + event.window.event == SDL_WINDOWEVENT_EXPOSED || + event.window.event == SDL_WINDOWEVENT_SHOWN ) + { + mIsMinimized = (event.window.event == SDL_WINDOWEVENT_MINIMIZED); + + mCallbacks->handleActivate(this, !mIsMinimized); + LL_INFOS() << "SDL deiconification state switched to " << mIsMinimized << LL_ENDL; + } + + break; + } case SDL_QUIT: if(mCallbacks->handleCloseRequest(this)) { @@ -2182,7 +2231,6 @@ void LLWindowSDL::gatherInput() // The app is responsible for calling destroyWindow when done with GL } break; - default: //LL_INFOS() << "Unhandled SDL event type " << event.type << LL_ENDL; break; @@ -2213,21 +2261,21 @@ static SDL_Cursor *makeSDLCursorFromBMP(const char *filename, int hotx, int hoty { SDL_Surface *cursurface; LL_DEBUGS() << "Loaded cursor file " << filename << " " - << bmpsurface->w << "x" << bmpsurface->h << LL_ENDL; + << bmpsurface->w << "x" << bmpsurface->h << LL_ENDL; cursurface = SDL_CreateRGBSurface (SDL_SWSURFACE, - bmpsurface->w, - bmpsurface->h, - 32, - SDL_SwapLE32(0xFFU), - SDL_SwapLE32(0xFF00U), - SDL_SwapLE32(0xFF0000U), - SDL_SwapLE32(0xFF000000U)); + bmpsurface->w, + bmpsurface->h, + 32, + SDL_SwapLE32(0xFFU), + SDL_SwapLE32(0xFF00U), + SDL_SwapLE32(0xFF0000U), + SDL_SwapLE32(0xFF000000U)); SDL_FillRect(cursurface, NULL, SDL_SwapLE32(0x00000000U)); // Blit the cursor pixel data onto a 32-bit RGBA surface so we // only have to cope with processing one type of pixel format. if (0 == SDL_BlitSurface(bmpsurface, NULL, - cursurface, NULL)) + cursurface, NULL)) { // n.b. we already checked that width is a multiple of 8. const int bitmap_bytes = (cursurface->w * cursurface->h) / 8; @@ -2242,26 +2290,26 @@ static SDL_Cursor *makeSDLCursorFromBMP(const char *filename, int hotx, int hoty for (i=0; i<cursurface->h; ++i) { for (j=0; j<cursurface->w; ++j) { U8 *pixelp = - ((U8*)cursurface->pixels) - + cursurface->pitch * i - + j*cursurface->format->BytesPerPixel; + ((U8*)cursurface->pixels) + + cursurface->pitch * i + + j*cursurface->format->BytesPerPixel; U8 srcred = pixelp[0]; U8 srcgreen = pixelp[1]; U8 srcblue = pixelp[2]; BOOL mask_bit = (srcred != 200) - || (srcgreen != 200) - || (srcblue != 200); + || (srcgreen != 200) + || (srcblue != 200); BOOL data_bit = mask_bit && (srcgreen <= 80);//not 0x80 unsigned char bit_offset = (cursurface->w/8) * i - + j/8; + + j/8; cursor_data[bit_offset] |= (data_bit) << (7 - (j&7)); cursor_mask[bit_offset] |= (mask_bit) << (7 - (j&7)); } } sdlcursor = SDL_CreateCursor((Uint8*)cursor_data, - (Uint8*)cursor_mask, - cursurface->w, cursurface->h, - hotx, hoty); + (Uint8*)cursor_mask, + cursurface->w, cursurface->h, + hotx, hoty); delete[] cursor_data; delete[] cursor_mask; } else { @@ -2452,8 +2500,6 @@ void LLWindowSDL::hideCursorUntilMouseMove() } } - - // // LLSplashScreenSDL - I don't think we'll bother to implement this; it's // fairly obsolete at this point. @@ -2478,133 +2524,71 @@ void LLSplashScreenSDL::hideImpl() { } - - -#if LL_GTK -static void response_callback (GtkDialog *dialog, - gint arg1, - gpointer user_data) -{ - gint *response = (gint*)user_data; - *response = arg1; - gtk_widget_destroy(GTK_WIDGET(dialog)); - gtk_main_quit(); -} - S32 OSMessageBoxSDL(const std::string& text, const std::string& caption, U32 type) { - S32 rtn = OSBTN_CANCEL; + SDL_MessageBoxData oData = { SDL_MESSAGEBOX_INFORMATION, nullptr, caption.c_str(), text.c_str(), 0, nullptr, nullptr }; + SDL_MessageBoxButtonData btnOk[] = {{SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, OSBTN_OK, "OK" }}; + SDL_MessageBoxButtonData btnOkCancel [] = {{SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, OSBTN_OK, "OK" }, {SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, OSBTN_CANCEL, "Cancel"} }; + SDL_MessageBoxButtonData btnYesNo[] = { {SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, OSBTN_YES, "Yes" }, {SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, OSBTN_NO, "No"} }; - if(gWindowImplementation != NULL) - gWindowImplementation->beforeDialog(); - - if (LLWindowSDL::ll_try_gtk_init()) + switch (type) { - GtkWidget *win = NULL; - - LL_INFOS() << "Creating a dialog because we're in windowed mode and GTK is happy." << LL_ENDL; - - GtkDialogFlags flags = GTK_DIALOG_MODAL; - GtkMessageType messagetype; - GtkButtonsType buttons; - switch (type) - { default: case OSMB_OK: - messagetype = GTK_MESSAGE_WARNING; - buttons = GTK_BUTTONS_OK; + oData.flags = SDL_MESSAGEBOX_WARNING; + oData.buttons = btnOk; + oData.numbuttons = 1; break; case OSMB_OKCANCEL: - messagetype = GTK_MESSAGE_QUESTION; - buttons = GTK_BUTTONS_OK_CANCEL; + oData.flags = SDL_MESSAGEBOX_INFORMATION; + oData.buttons = btnOkCancel; + oData.numbuttons = 2; break; case OSMB_YESNO: - messagetype = GTK_MESSAGE_QUESTION; - buttons = GTK_BUTTONS_YES_NO; + oData.flags = SDL_MESSAGEBOX_INFORMATION; + oData.buttons = btnYesNo; + oData.numbuttons = 2; break; - } - win = gtk_message_dialog_new(NULL, flags, messagetype, buttons, "%s", - text.c_str()); - -# if LL_X11 - // Make GTK tell the window manager to associate this - // dialog with our non-GTK SDL window, which should try - // to keep it on top etc. - if (gWindowImplementation && - gWindowImplementation->mSDL_XWindowID != None) - { - gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin - GdkWindow *gdkwin = gdk_window_foreign_new(gWindowImplementation->mSDL_XWindowID); - gdk_window_set_transient_for(GTK_WIDGET(win)->window, - gdkwin); - } -# endif //LL_X11 - - gtk_window_set_position(GTK_WINDOW(win), - GTK_WIN_POS_CENTER_ON_PARENT); - - gtk_window_set_type_hint(GTK_WINDOW(win), - GDK_WINDOW_TYPE_HINT_DIALOG); - - if (!caption.empty()) - gtk_window_set_title(GTK_WINDOW(win), caption.c_str()); - - gint response = GTK_RESPONSE_NONE; - g_signal_connect (win, - "response", - G_CALLBACK (response_callback), - &response); - - // we should be able to use a gtk_dialog_run(), but it's - // apparently not written to exist in a world without a higher - // gtk_main(), so we manage its signal/destruction outselves. - gtk_widget_show_all (win); - gtk_main(); - - //LL_INFOS() << "response: " << response << LL_ENDL; - switch (response) - { - case GTK_RESPONSE_OK: rtn = OSBTN_OK; break; - case GTK_RESPONSE_YES: rtn = OSBTN_YES; break; - case GTK_RESPONSE_NO: rtn = OSBTN_NO; break; - case GTK_RESPONSE_APPLY: rtn = OSBTN_OK; break; - case GTK_RESPONSE_NONE: - case GTK_RESPONSE_CANCEL: - case GTK_RESPONSE_CLOSE: - case GTK_RESPONSE_DELETE_EVENT: - default: rtn = OSBTN_CANCEL; - } - } - else - { - LL_INFOS() << "MSGBOX: " << caption << ": " << text << LL_ENDL; - LL_INFOS() << "Skipping dialog because we're in fullscreen mode or GTK is not happy." << LL_ENDL; - rtn = OSBTN_OK; } - if(gWindowImplementation != NULL) - gWindowImplementation->afterDialog(); + int btn{0}; + if( 0 == SDL_ShowMessageBox( &oData, &btn ) ) + return btn; + return OSBTN_CANCEL; +} - return rtn; +BOOL LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b) +{ + return (FALSE); } -static void color_changed_callback(GtkWidget *widget, - gpointer user_data) +#if LL_DARWIN +LLSD LLWindowSDL::getNativeKeyData() { - GtkColorSelection *colorsel = GTK_COLOR_SELECTION(widget); - GdkColor *colorp = (GdkColor*)user_data; + LLSD result = LLSD::emptyMap(); - gtk_color_selection_get_current_color(colorsel, colorp); -} + if(mRawKeyEvent) + { + 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; +} +#else /* Make the raw keyboard data available - used to poke through to LLQtWebKit so that Qt/Webkit has access to the virtual keycodes etc. that it needs */ LLSD LLWindowSDL::getNativeKeyData() { - LLSD result = LLSD::emptyMap(); + LLSD result = LLSD::emptyMap(); U32 modifiers = 0; // pretend-native modifiers... oh what a tangled web we weave! @@ -2622,145 +2606,15 @@ LLSD LLWindowSDL::getNativeKeyData() // *todo: test ALTs - I don't have a case for testing these. Do you? // *todo: NUM? - I don't care enough right now (and it's not a GDK modifier). - result["scan_code"] = (S32)mKeyScanCode; - result["virtual_key"] = (S32)mKeyVirtualKey; - result["modifiers"] = (S32)modifiers; - - return result; -} - - -BOOL LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b) -{ - BOOL rtn = FALSE; - - beforeDialog(); - - if (ll_try_gtk_init()) - { - GtkWidget *win = NULL; - - win = gtk_color_selection_dialog_new(NULL); - -# if LL_X11 - // Get GTK to tell the window manager to associate this - // dialog with our non-GTK SDL window, which should try - // to keep it on top etc. - if (mSDL_XWindowID != None) - { - gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin - GdkWindow *gdkwin = gdk_window_foreign_new(mSDL_XWindowID); - gdk_window_set_transient_for(GTK_WIDGET(win)->window, - gdkwin); - } -# endif //LL_X11 - - GtkColorSelection *colorsel = GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG(win)->colorsel); - - GdkColor color, orig_color; - orig_color.pixel = 0; - orig_color.red = guint16(65535 * *r); - orig_color.green= guint16(65535 * *g); - orig_color.blue = guint16(65535 * *b); - color = orig_color; - - gtk_color_selection_set_previous_color (colorsel, &color); - gtk_color_selection_set_current_color (colorsel, &color); - gtk_color_selection_set_has_palette (colorsel, TRUE); - gtk_color_selection_set_has_opacity_control(colorsel, FALSE); - - gint response = GTK_RESPONSE_NONE; - g_signal_connect (win, - "response", - G_CALLBACK (response_callback), - &response); - - g_signal_connect (G_OBJECT (colorsel), "color_changed", - G_CALLBACK (color_changed_callback), - &color); - - gtk_window_set_modal(GTK_WINDOW(win), TRUE); - gtk_widget_show_all(win); - // hide the help button - we don't service it. - gtk_widget_hide(GTK_COLOR_SELECTION_DIALOG(win)->help_button); - gtk_main(); - - if (response == GTK_RESPONSE_OK && - (orig_color.red != color.red - || orig_color.green != color.green - || orig_color.blue != color.blue) ) - { - *r = color.red / 65535.0f; - *g = color.green / 65535.0f; - *b = color.blue / 65535.0f; - rtn = TRUE; - } - } - - afterDialog(); - - return rtn; -} -#else -S32 OSMessageBoxSDL(const std::string& text, const std::string& caption, U32 type) -{ - LL_INFOS() << "MSGBOX: " << caption << ": " << text << LL_ENDL; - return 0; -} - -BOOL LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b) -{ - return (FALSE); -} - -#if LL_DARWIN - -LLSD LLWindowSDL::getNativeKeyData() -{ - LLSD result = LLSD::emptyMap(); - - if(mRawKeyEvent) - { - 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; -} - -#else - -LLSD LLWindowSDL::getNativeKeyData() -{ - LLSD result = LLSD::emptyMap(); - - U32 modifiers = 0; - modifiers |= (mKeyModifiers & KMOD_LSHIFT) ? 0x0001 : 0; - modifiers |= (mKeyModifiers & KMOD_RSHIFT) ? 0x0001 : 0; - modifiers |= (mKeyModifiers & KMOD_CAPS) ? 0x0002 : 0; - modifiers |= (mKeyModifiers & KMOD_LCTRL) ? 0x0004 : 0; - modifiers |= (mKeyModifiers & KMOD_RCTRL) ? 0x0004 : 0; - modifiers |= (mKeyModifiers & KMOD_LALT) ? 0x0008 : 0; - modifiers |= (mKeyModifiers & KMOD_RALT) ? 0x0008 : 0; - - result["scan_code"] = (S32)mKeyScanCode; result["virtual_key"] = (S32)mKeyVirtualKey; - result["modifiers"] = (S32)modifiers; - + result["virtual_key_win"] = (S32)LLKeyboardSDL::mapSDL2toWin( mKeyVirtualKey ); + result["modifiers"] = (S32)modifiers; + result["input_type"] = mInputType; return result; } - #endif // LL_DARWIN -#endif // LL_GTK - -#if LL_LINUX || __FreeBSD__ +#if LL_LINUX || LL_SOLARIS || __FreeBSD__ // extracted from spawnWebBrowser for clarity and to eliminate // compiler confusion regarding close(int fd) vs. LLWindow::close() void exec_cmd(const std::string& cmd, const std::string& arg) @@ -2772,9 +2626,32 @@ void exec_cmd(const std::string& cmd, const std::string& arg) { // child // disconnect from stdin/stdout/stderr, or child will // keep our output pipe undesirably alive if it outlives us. - close(0); - close(1); - close(2); + // close(0); + // close(1); + // close(2); + // <FS:TS> Reopen stdin, stdout, and stderr to /dev/null. + // It's good practice to always have those file + // descriptors open to something, lest the exec'd + // program actually try to use them. + FILE *result; + result = freopen("/dev/null","r",stdin); + if (result == NULL) + { + LL_WARNS() << "Error reopening stdin for web browser: " + << strerror(errno) << LL_ENDL; + } + result = freopen("/dev/null","w",stdout); + if (result == NULL) + { + LL_WARNS() << "Error reopening stdout for web browser: " + << strerror(errno) << LL_ENDL; + } + result = freopen("/dev/null","w",stderr); + if (result == NULL) + { + LL_WARNS() << "Error reopening stderr for web browser: " + << strerror(errno) << LL_ENDL; + } // end ourself by running the command execv(cmd.c_str(), argv); /* Flawfinder: ignore */ // if execv returns at all, there was a problem. @@ -2842,69 +2719,51 @@ void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async) #elif LL_DARWIN - S32 result = 0; - CFURLRef urlRef = NULL; + S32 result = 0; + CFURLRef urlRef = NULL; - LL_INFOS() << "Opening URL " << escaped_url << LL_ENDL; + LL_INFOS() << "Opening URL " << escaped_url << LL_ENDL; - CFStringRef stringRef = CFStringCreateWithCString(NULL, escaped_url.c_str(), kCFStringEncodingUTF8); - if (stringRef) - { - // This will succeed if the string is a full URL, including the http:// - // Note that URLs specified this way need to be properly percent-escaped. - urlRef = CFURLCreateWithString(NULL, stringRef, NULL); + CFStringRef stringRef = CFStringCreateWithCString(NULL, escaped_url.c_str(), kCFStringEncodingUTF8); + if (stringRef) + { + // This will succeed if the string is a full URL, including the http:// + // Note that URLs specified this way need to be properly percent-escaped. + urlRef = CFURLCreateWithString(NULL, stringRef, NULL); - // Don't use CRURLCreateWithFileSystemPath -- only want valid URLs + // Don't use CRURLCreateWithFileSystemPath -- only want valid URLs - CFRelease(stringRef); - } + CFRelease(stringRef); + } - if (urlRef) - { - result = LSOpenCFURLRef(urlRef, NULL); + if (urlRef) + { + result = LSOpenCFURLRef(urlRef, NULL); - if (result != noErr) - { - LL_INFOS() << "Error " << result << " on open." << LL_ENDL; - } + if (result != noErr) + { + LL_INFOS() << "Error " << result << " on open." << LL_ENDL; + } - CFRelease(urlRef); - } - else - { - LL_INFOS() << "Error: couldn't create URL." << LL_ENDL; - } + CFRelease(urlRef); + } + else + { + LL_INFOS() << "Error: couldn't create URL." << LL_ENDL; + } #endif // LL_LINUX LL_INFOS() << "spawn_web_browser returning." << LL_ENDL; } +void LLWindowSDL::openFile(const std::string& file_name) +{ + spawnWebBrowser("file://"+file_name,TRUE); +} void *LLWindowSDL::getPlatformWindow() { -#if LL_GTK && LL_LLMOZLIB_ENABLED - if (LLWindowSDL::ll_try_gtk_init()) - { - maybe_lock_display(); - - GtkWidget *owin = gtk_window_new(GTK_WINDOW_POPUP); - // Why a layout widget? A MozContainer would be ideal, but - // it involves exposing Mozilla headers to mozlib-using apps. - // A layout widget with a GtkWindow parent has the desired - // properties of being plain GTK, having a window, and being - // derived from a GtkContainer. - GtkWidget *rtnw = gtk_layout_new(NULL, NULL); - gtk_container_add(GTK_CONTAINER(owin), rtnw); - gtk_widget_realize(rtnw); - GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(rtnw), GTK_NO_WINDOW); - - maybe_unlock_display(); - - return rtnw; - } -#endif // LL_GTK && LL_LLMOZLIB_ENABLED - // Unixoid mozilla really needs GTK. return NULL; } @@ -2965,10 +2824,10 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList() LL_INFOS("AppInit") << "Variant " << locale->variant << LL_ENDL; LL_INFOS() << "Preferring fonts of language: " - << locale->lang - << LL_ENDL; + << locale->lang + << LL_ENDL; sort_order = "lang=" + std::string(locale->lang) + ":" - + sort_order; + + sort_order; } } FL_FreeLocale(&locale); @@ -2986,7 +2845,7 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList() // Sort the list of system fonts from most-to-least-desirable. FcResult result; fs = FcFontSort(NULL, sortpat, elide_unicode_coverage, - NULL, &result); + NULL, &result); FcPatternDestroy(sortpat); } @@ -3000,8 +2859,8 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList() { FcChar8 *filename; if (FcResultMatch == FcPatternGetString(fs->fonts[i], - FC_FILE, 0, - &filename) + FC_FILE, 0, + &filename) && filename) { rtns.push_back(std::string((const char*)filename)); @@ -3025,4 +2884,75 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList() return rtns; } -#endif // LL_SDL + +void* LLWindowSDL::createSharedContext() +{ + auto *pContext = SDL_GL_CreateContext(mWindow); + if ( pContext) + { + SDL_GL_SetSwapInterval(0); + SDL_GL_MakeCurrent(mWindow, mContext); + + LLCoordScreen size; + if (getSize(&size)) + setSize(size); + + LL_DEBUGS() << "Creating shared OpenGL context successful!" << LL_ENDL; + + return (void*)pContext; + } + + LL_WARNS() << "Creating shared OpenGL context failed!" << LL_ENDL; + + return nullptr; +} + +void LLWindowSDL::makeContextCurrent(void* contextPtr) +{ + LL_PROFILER_GPU_CONTEXT; + SDL_GL_MakeCurrent( mWindow, contextPtr ); +} + +void LLWindowSDL::destroySharedContext(void* contextPtr) +{ + SDL_GL_DeleteContext( contextPtr ); +} + +void LLWindowSDL::toggleVSync(bool enable_vsync) +{ + if( !enable_vsync) + { + SDL_GL_SetSwapInterval(0); + SDL_SetHintWithPriority(SDL_HINT_RENDER_VSYNC,"0",SDL_HINT_OVERRIDE); + } + else + { + SDL_GL_SetSwapInterval(1); + SDL_SetHintWithPriority(SDL_HINT_RENDER_VSYNC,"1",SDL_HINT_OVERRIDE); + } +} + +U32 LLWindowSDL::getAvailableVRAMMegabytes() +{ +#if LL_DARWIN + static const U32 mb = 1024*1024; + static const U32 total_factor = 2; + return gGLManager.mVRAM - (LLImageGL::getTextureBytesAllocated() * total_factor/mb); +#else + return 4096; +#endif +} + +void LLWindowSDL::setLanguageTextInput(const LLCoordGL& position) +{ + LLCoordWindow win_pos; + convertCoords( position, &win_pos ); + + SDL_Rect r; + r.x = win_pos.mX; + r.y = win_pos.mY; + r.w = 500; + r.h = 16; + + SDL_SetTextInputRect(&r); +} diff --git a/indra/llwindow/llwindowsdl.h b/indra/llwindow/llwindowsdl.h index 9b5a1f2c61..87a3e15731 100644 --- a/indra/llwindow/llwindowsdl.h +++ b/indra/llwindow/llwindowsdl.h @@ -24,8 +24,8 @@ * $/LicenseInfo$ */ -#ifndef LL_LLWINDOWSDL_H -#define LL_LLWINDOWSDL_H +#ifndef LL_LLWINDOWSDL2_H +#define LL_LLWINDOWSDL2_H // Simple Directmedia Layer (http://libsdl.org/) implementation of LLWindow class @@ -50,91 +50,141 @@ #undef require -class LLWindowSDL : public LLWindow -{ +class LLWindowSDL : public LLWindow { public: void show() override; + void hide() override; + void close() override; + BOOL getVisible() override; + BOOL getMinimized() override; + BOOL getMaximized() override; + BOOL maximize() override; + void minimize() override; + void restore() override; - /*virtual*/ BOOL getFullscreen(); + + BOOL getFullscreen(); + BOOL getPosition(LLCoordScreen *position) override; + BOOL getSize(LLCoordScreen *size) override; + BOOL getSize(LLCoordWindow *size) override; + BOOL setPosition(LLCoordScreen position) override; + BOOL setSizeImpl(LLCoordScreen size) override; + BOOL setSizeImpl(LLCoordWindow size) override; - BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL) override; - void* createSharedContext() override; - void makeContextCurrent(void* context) override; - void destroySharedContext(void* context) override; - void toggleVSync(bool enable_vsync) override; + + BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, + const LLCoordScreen *const posp = NULL) override; + BOOL setCursorPosition(LLCoordWindow position) override; + BOOL getCursorPosition(LLCoordWindow *position) override; + void showCursor() override; + void hideCursor() override; + void showCursorFromMouseMove() override; + void hideCursorUntilMouseMove() override; + BOOL isCursorHidden() override; + void updateCursor() override; + void captureMouse() override; + void releaseMouse() override; - void setMouseClipping( BOOL b ) override; - void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true) override; + + void setMouseClipping(BOOL b) override; + + void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true) override; BOOL isClipboardTextAvailable() override; + BOOL pasteTextFromClipboard(LLWString &dst) override; - BOOL copyTextToClipboard(const LLWString & src) override; + + BOOL copyTextToClipboard(const LLWString &src) override; BOOL isPrimaryTextAvailable() override; + BOOL pasteTextFromPrimary(LLWString &dst) override; - BOOL copyTextToPrimary(const LLWString & src) override; + + BOOL copyTextToPrimary(const LLWString &src) override; void flashIcon(F32 seconds) override; + F32 getGamma() override; + BOOL setGamma(const F32 gamma) override; // Set the gamma U32 getFSAASamples() override; + void setFSAASamples(const U32 samples) override; + BOOL restoreGamma() override; // Restore original gamma table (before updating gamma) - ESwapMethod getSwapMethod() override { return mSwapMethod; } + ESwapMethod getSwapMethod() override { return mSwapMethod; } + void processMiscNativeEvents() override; + void gatherInput() override; + void swapBuffers() override; - /*virtual*/ void restoreGLContext() {}; - void delayInputProcessing() override { }; + void restoreGLContext() {}; + + void delayInputProcessing() override {}; // handy coordinate space conversion routines BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to) override; + BOOL convertCoords(LLCoordWindow from, LLCoordScreen *to) override; + BOOL convertCoords(LLCoordWindow from, LLCoordGL *to) override; + BOOL convertCoords(LLCoordGL from, LLCoordWindow *to) override; + BOOL convertCoords(LLCoordScreen from, LLCoordGL *to) override; + BOOL convertCoords(LLCoordGL from, LLCoordScreen *to) override; - LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) override; + LLWindowResolution *getSupportedResolutions(S32 &num_resolutions) override; + F32 getNativeAspectRatio() override; + F32 getPixelAspectRatio() override; - void setNativeAspectRatio(F32 ratio) override { mOverrideAspectRatio = ratio; } - F32 getSystemUISize() override; + void setNativeAspectRatio(F32 ratio) override { mOverrideAspectRatio = ratio; } - U32 getAvailableVRAMMegabytes() override; + F32 getSystemUISize() override; void beforeDialog() override; + void afterDialog() override; BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b) override; void *getPlatformWindow() override; + void bringToFront() override; + + void setLanguageTextInput(const LLCoordGL& pos) override; - /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async) override; + void spawnWebBrowser(const std::string &escaped_url, bool async) override; + + void openFile(const std::string &file_name); + + void setTitle(const std::string title) override; static std::vector<std::string> getDynamicFallbackFontList(); @@ -144,44 +194,58 @@ public: Window mSDL_XWindowID; Display *mSDL_Display; #endif + void (*Lock_Display)(void); - void (*Unlock_Display)(void); -#if LL_GTK - // Lazily initialize and check the runtime GTK version for goodness. - static bool ll_try_gtk_init(void); -#endif // LL_GTK + void (*Unlock_Display)(void); #if LL_X11 + static Window get_SDL_XWindowID(void); - static Display* get_SDL_Display(void); + + static Display *get_SDL_Display(void); + #endif // LL_X11 #if LL_DARWIN - static BOOL sUseMultGL; + static BOOL sUseMultGL; #endif + void *createSharedContext() override; + + void makeContextCurrent(void *context) override; + + void destroySharedContext(void *context) override; + + void toggleVSync(bool enable_vsync) override; + + U32 getAvailableVRAMMegabytes() override; + protected: - LLWindowSDL(LLWindowCallbacks* callbacks, - const std::string& title, int x, int y, int width, int height, U32 flags, - BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl, - BOOL ignore_pixel_depth, U32 fsaa_samples); + LLWindowSDL(LLWindowCallbacks *callbacks, + const std::string &title, int x, int y, int width, int height, U32 flags, + BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl, + BOOL ignore_pixel_depth, U32 fsaa_samples); + ~LLWindowSDL(); - BOOL isValid() override; - LLSD getNativeKeyData() override; + BOOL isValid() override; + + LLSD getNativeKeyData() override; + + void initCursors(); - void initCursors(); - void quitCursors(); - void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size); + void quitCursors(); + + void moveWindow(const LLCoordScreen &position, const LLCoordScreen &size); // Changes display resolution. Returns true if successful - BOOL setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh); + BOOL setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh); // Go back to last fullscreen display resolution. - BOOL setFullscreenResolution(); + BOOL setFullscreenResolution(); - BOOL shouldPostQuit() { return mPostQuit; } + BOOL shouldPostQuit() { return mPostQuit; } protected: // @@ -190,47 +254,84 @@ 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, BOOL disable_vsync); + void destroyContext(); - void setupFailure(const std::string& text, const std::string& caption, U32 type); + + void setupFailure(const std::string &text, const std::string &caption, U32 type); + void fixWindowSize(void); - U32 SDLCheckGrabbyKeys(SDL_Keycode keysym, BOOL gain); + + U32 SDLCheckGrabbyKeys(U32 keysym, BOOL gain); + BOOL SDLReallyCaptureInput(BOOL capture); // // Platform specific variables // - U32 mGrabbyKeyFlags; - int mReallyCapturedCount; - SDL_Window * mWindow; + U32 mGrabbyKeyFlags; + int mReallyCapturedCount; + + SDL_Window *mWindow; + SDL_GLContext mContext; + SDL_Cursor *mSDLCursors[UI_CURSOR_COUNT]; + std::string mWindowTitle; - double mOriginalAspectRatio; - BOOL mNeedsResize; // Constructor figured out the window is too big, it needs a resize. - LLCoordScreen mNeedsResizeSize; - F32 mOverrideAspectRatio; - F32 mGamma; - U32 mFSAASamples; + double mOriginalAspectRatio; + BOOL mNeedsResize; // Constructor figured out the window is too big, it needs a resize. + LLCoordScreen mNeedsResizeSize; + F32 mOverrideAspectRatio; + F32 mGamma; + U32 mFSAASamples; - int mSDLFlags; + int mSDLFlags; - SDL_Cursor* mSDLCursors[UI_CURSOR_COUNT]; - int mHaveInputFocus; /* 0=no, 1=yes, else unknown */ - int mIsMinimized; /* 0=no, 1=yes, else unknown */ - int mIsActive; /* 0=no, 1=yes, else unknown */ + int mHaveInputFocus; /* 0=no, 1=yes, else unknown */ + int mIsMinimized; /* 0=no, 1=yes, else unknown */ + int mIsActive; /* 0=no, 1=yes, else unknown */ friend class LLWindowManager; private: #if LL_X11 + void x11_set_urgent(BOOL urgent); + BOOL mFlashing; LLTimer mFlashTimer; #endif //LL_X11 - U32 mKeyScanCode; U32 mKeyVirtualKey; - Uint16 mKeyModifiers; -}; + U32 mKeyModifiers; + std::string mInputType; + +public: +#if LL_X11 + + static Display *getSDLDisplay(); + LLWString const &getPrimaryText() const { return mPrimaryClipboard; } + + LLWString const &getSecondaryText() const { return mSecondaryClipboard; } + + void clearPrimaryText() { mPrimaryClipboard.clear(); } + + void clearSecondaryText() { mSecondaryClipboard.clear(); } + +private: + void initialiseX11Clipboard(); + + bool getSelectionText(Atom selection, LLWString &text); + + bool getSelectionText(Atom selection, Atom type, LLWString &text); + + bool setSelectionText(Atom selection, const LLWString &text); +#endif + + void tryFindFullscreenSize(int &aWidth, int &aHeight); + + LLWString mPrimaryClipboard; + LLWString mSecondaryClipboard; +}; class LLSplashScreenSDL : public LLSplashScreen { @@ -238,9 +339,9 @@ public: LLSplashScreenSDL(); virtual ~LLSplashScreenSDL(); - /*virtual*/ void showImpl(); - /*virtual*/ void updateImpl(const std::string& mesg); - /*virtual*/ void hideImpl(); + void showImpl(); + void updateImpl(const std::string& mesg); + void hideImpl(); }; S32 OSMessageBoxSDL(const std::string& text, const std::string& caption, U32 type); diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index d6b93b93d9..12cd5320b8 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -163,18 +163,7 @@ HGLRC SafeCreateContext(HDC &hdc) GLuint SafeChoosePixelFormat(HDC &hdc, const PIXELFORMATDESCRIPTOR *ppfd) { - __try - { - return ChoosePixelFormat(hdc, ppfd); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - // convert to C++ styled exception - // C exception don't allow classes, so it's a regular char array - char integer_string[32]; - sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode()); - throw std::exception(integer_string); - } + return LL::seh::catcher([hdc, ppfd]{ return ChoosePixelFormat(hdc, ppfd); }); } //static |