diff options
Diffstat (limited to 'indra/llwindow')
| -rw-r--r-- | indra/llwindow/CMakeLists.txt | 17 | ||||
| -rw-r--r-- | indra/llwindow/llkeyboard.cpp | 12 | ||||
| -rw-r--r-- | indra/llwindow/llkeyboard.h | 20 | ||||
| -rw-r--r-- | indra/llwindow/llkeyboardheadless.cpp | 4 | ||||
| -rw-r--r-- | indra/llwindow/llkeyboardheadless.h | 9 | ||||
| -rw-r--r-- | indra/llwindow/llkeyboardsdl.cpp | 459 | ||||
| -rw-r--r-- | indra/llwindow/llkeyboardsdl.h | 27 | ||||
| -rw-r--r-- | indra/llwindow/llwindow.cpp | 12 | ||||
| -rw-r--r-- | indra/llwindow/llwindowcallbacks.cpp | 4 | ||||
| -rw-r--r-- | indra/llwindow/llwindowcallbacks.h | 1 | ||||
| -rw-r--r-- | indra/llwindow/llwindowmacosx.cpp | 1 | ||||
| -rw-r--r-- | indra/llwindow/llwindowsdl.cpp | 1940 | ||||
| -rw-r--r-- | indra/llwindow/llwindowsdl.h | 344 | ||||
| -rw-r--r-- | indra/llwindow/llwindowwin32.cpp | 13 | 
14 files changed, 1781 insertions, 1082 deletions
| diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt index 2996f58fe0..ce9134e7f1 100644 --- a/indra/llwindow/CMakeLists.txt +++ b/indra/llwindow/CMakeLists.txt @@ -52,7 +52,6 @@ set(llwindow_LINK_LIBRARIES          llcommon          llimage          llmath -        llrender          llfilesystem          llxml          ll::glm @@ -60,11 +59,14 @@ set(llwindow_LINK_LIBRARIES          ll::uilibraries          ll::SDL          ) + +include_directories(${CMAKE_SOURCE_DIR}/llrender) +  # Libraries on which this library depends, needed for Linux builds  # Sort by high-level to low-level -if (LINUX) -  list(APPEND viewer_SOURCE_FILES  -       llkeyboardsdl.cpp  +if (USESYSTEMLIBS AND NOT DARWIN) +  list(APPEND viewer_SOURCE_FILES +       llkeyboardsdl.cpp         llwindowsdl.cpp         )    list(APPEND viewer_HEADER_FILES @@ -84,8 +86,7 @@ if (LINUX)          fontconfig          # For FCInit and other FC* functions.          )    endif (BUILD_HEADLESS) - -endif (LINUX) +endif (USESYSTEMLIBS AND NOT DARWIN)  if (DARWIN)    list(APPEND llwindow_SOURCE_FILES @@ -180,9 +181,11 @@ 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)    target_link_libraries(llwindow ${CARBON_LIBRARY})  endif (DARWIN) + +include(LibraryInstall) diff --git a/indra/llwindow/llkeyboard.cpp b/indra/llwindow/llkeyboard.cpp index 33eebdadd1..a16c0a318a 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,12 +194,11 @@ void LLKeyboard::resetKeys()  } -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;      // 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; @@ -214,11 +212,9 @@ bool LLKeyboard::translateKey(const U16 os_key, KEY *out_key)      }  } - -U16 LLKeyboard::inverseTranslateKey(const KEY translated_key) +LLKeyboard::NATIVE_KEY_TYPE LLKeyboard::inverseTranslateKey(const KEY translated_key)  { -    std::map<KEY, U16>::iterator iter; -    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 713eb7aec2..a527227672 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,16 +72,15 @@ public:      bool            getKeyDown(const KEY key) { return mKeyLevel[key]; }      bool            getKeyRepeated(const KEY key) { return mKeyRepeated[key]; } -    bool            translateKey(const U16 os_key, KEY *translated_key); -    U16             inverseTranslateKey(const KEY translated_key); +    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 +    virtual bool    handleKeyUp(const NATIVE_KEY_TYPE key, MASK mask) = 0; +    virtual bool    handleKeyDown(const NATIVE_KEY_TYPE key, MASK mask) = 0; -    virtual bool    handleKeyUp(const U16 key, MASK mask) = 0; -    virtual bool    handleKeyDown(const U16 key, MASK mask) = 0; - -#ifdef LL_DARWIN +#if defined(LL_DARWIN) && !defined(LL_SDL)      // We only actually use this for macOS.      virtual void    handleModifier(MASK mask) = 0;  #endif // LL_DARWIN @@ -111,8 +115,8 @@ protected:      void            addKeyName(KEY key, const std::string& name);  protected: -    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 +    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 8669a5b41a..6f8c829dd5 100644 --- a/indra/llwindow/llkeyboardheadless.cpp +++ b/indra/llwindow/llkeyboardheadless.cpp @@ -35,12 +35,8 @@ void LLKeyboardHeadless::resetMaskKeys()  { } -bool LLKeyboardHeadless::handleKeyDown(const U16 key, const U32 mask) -{ return false; } -bool LLKeyboardHeadless::handleKeyUp(const U16 key, const U32 mask) -{ 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 2528f0e3f1..439abaf25b 100644 --- a/indra/llwindow/llkeyboardheadless.h +++ b/indra/llwindow/llkeyboardheadless.h @@ -35,8 +35,13 @@ public:      LLKeyboardHeadless();      /*virtual*/ ~LLKeyboardHeadless() {}; -    /*virtual*/ bool    handleKeyUp(const U16 key, MASK mask); -    /*virtual*/ bool    handleKeyDown(const U16 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 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);      /*virtual*/ void    scanKeyboard(); diff --git a/indra/llwindow/llkeyboardsdl.cpp b/indra/llwindow/llkeyboardsdl.cpp index 97198f0cc0..72b4577276 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 "SDL/SDL.h" +#include "SDL2/SDL.h" +#include "SDL2/SDL_keycode.h"  LLKeyboardSDL::LLKeyboardSDL()  { @@ -40,6 +38,10 @@ LLKeyboardSDL::LLKeyboardSDL()      // Virtual key mappings from SDL_keysym.h ...      // SDL maps the letter keys to the ASCII you'd expect, but it's lowercase... + +    // <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++)      { @@ -68,13 +70,12 @@ LLKeyboardSDL::LLKeyboardSDL()      //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,40 +112,39 @@ 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<U16, 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;      }      // numpad map -    mTranslateNumpadMap[SDLK_KP0] = KEY_PAD_INS; -    mTranslateNumpadMap[SDLK_KP1] = KEY_PAD_END; -    mTranslateNumpadMap[SDLK_KP2] = KEY_PAD_DOWN; -    mTranslateNumpadMap[SDLK_KP3] = KEY_PAD_PGDN; -    mTranslateNumpadMap[SDLK_KP4] = KEY_PAD_LEFT; -    mTranslateNumpadMap[SDLK_KP5] = KEY_PAD_CENTER; -    mTranslateNumpadMap[SDLK_KP6] = KEY_PAD_RIGHT; -    mTranslateNumpadMap[SDLK_KP7] = KEY_PAD_HOME; -    mTranslateNumpadMap[SDLK_KP8] = KEY_PAD_UP; -    mTranslateNumpadMap[SDLK_KP9] = KEY_PAD_PGUP; +    mTranslateNumpadMap[SDLK_KP_0] = KEY_PAD_INS; +    mTranslateNumpadMap[SDLK_KP_1] = KEY_PAD_END; +    mTranslateNumpadMap[SDLK_KP_2] = KEY_PAD_DOWN; +    mTranslateNumpadMap[SDLK_KP_3] = KEY_PAD_PGDN; +    mTranslateNumpadMap[SDLK_KP_4] = KEY_PAD_LEFT; +    mTranslateNumpadMap[SDLK_KP_5] = KEY_PAD_CENTER; +    mTranslateNumpadMap[SDLK_KP_6] = KEY_PAD_RIGHT; +    mTranslateNumpadMap[SDLK_KP_7] = KEY_PAD_HOME; +    mTranslateNumpadMap[SDLK_KP_8] = KEY_PAD_UP; +    mTranslateNumpadMap[SDLK_KP_9] = KEY_PAD_PGUP;      mTranslateNumpadMap[SDLK_KP_PERIOD] = KEY_PAD_DEL;      // build inverse numpad map -    for (iter = mTranslateNumpadMap.begin(); +    for (auto iter = mTranslateNumpadMap.begin();           iter != mTranslateNumpadMap.end();           iter++)      { @@ -154,7 +154,7 @@ LLKeyboardSDL::LLKeyboardSDL()  void LLKeyboardSDL::resetMaskKeys()  { -    SDLMod mask = SDL_GetModState(); +    SDL_Keymod mask = SDL_GetModState();      // MBW -- XXX -- This mirrors the operation of the Windows version of resetMaskKeys().      //    It looks a bit suspicious, as it won't correct for keys that have been released. @@ -165,7 +165,11 @@ void LLKeyboardSDL::resetMaskKeys()          mKeyLevel[KEY_SHIFT] = true;      } -    if(mask & KMOD_CTRL) +    if(mask & (KMOD_CTRL +#ifdef LL_DARWIN +        | KMOD_GUI +#endif +        ))      {          mKeyLevel[KEY_CONTROL] = true;      } @@ -187,7 +191,11 @@ MASK LLKeyboardSDL::updateModifiers(const U32 mask)          out_mask |= MASK_SHIFT;      } -    if(mask & KMOD_CTRL) +    if(mask & (KMOD_CTRL +#ifdef LL_DARWIN +        | KMOD_GUI +#endif +        ))      {          out_mask |= MASK_CONTROL;      } @@ -201,34 +209,34 @@ MASK LLKeyboardSDL::updateModifiers(const U32 mask)  } -static U16 adjustNativekeyFromUnhandledMask(const U16 key, const U32 mask) +static U32 adjustNativekeyFromUnhandledMask(const U32 key, const U32 mask)  {      // SDL doesn't automatically adjust the keysym according to      // whether NUMLOCK is engaged, so we massage the keysym manually. -    U16 rtn = key; +    U32 rtn = key;      if (!(mask & KMOD_NUM))      {          switch (key)          { -        case SDLK_KP_PERIOD: rtn = SDLK_DELETE; break; -        case SDLK_KP0: rtn = SDLK_INSERT; break; -        case SDLK_KP1: rtn = SDLK_END; break; -        case SDLK_KP2: rtn = SDLK_DOWN; break; -        case SDLK_KP3: rtn = SDLK_PAGEDOWN; break; -        case SDLK_KP4: rtn = SDLK_LEFT; break; -        case SDLK_KP6: rtn = SDLK_RIGHT; break; -        case SDLK_KP7: rtn = SDLK_HOME; break; -        case SDLK_KP8: rtn = SDLK_UP; break; -        case SDLK_KP9: 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;  } -bool LLKeyboardSDL::handleKeyDown(const U16 key, const U32 mask) +bool LLKeyboardSDL::handleKeyDown(const U32 key, const U32 mask)  { -    U16     adjusted_nativekey; +    U32 adjusted_nativekey;      KEY translated_key = 0;      U32 translated_mask = MASK_NONE;      bool    handled = false; @@ -246,9 +254,9 @@ bool LLKeyboardSDL::handleKeyDown(const U16 key, const U32 mask)  } -bool LLKeyboardSDL::handleKeyUp(const U16 key, const U32 mask) +bool LLKeyboardSDL::handleKeyUp(const U32 key, const U32 mask)  { -    U16     adjusted_nativekey; +    U32 adjusted_nativekey;      KEY translated_key = 0;      U32 translated_mask = MASK_NONE;      bool    handled = false; @@ -268,16 +276,20 @@ bool LLKeyboardSDL::handleKeyUp(const U16 key, const U32 mask)  MASK LLKeyboardSDL::currentMask(bool for_mouse_event)  {      MASK result = MASK_NONE; -    SDLMod mask = SDL_GetModState(); +    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_META) result |= MASK_CONTROL; +        if (mask & KMOD_GUI) +            result |= MASK_CONTROL;      }      return result; @@ -310,7 +322,7 @@ void LLKeyboardSDL::scanKeyboard()  } -bool LLKeyboardSDL::translateNumpadKey( const U16 os_key, KEY *translated_key) +bool LLKeyboardSDL::translateNumpadKey( const U32 os_key, KEY *translated_key)  {      return translateKey(os_key, translated_key);  } @@ -320,5 +332,338 @@ 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 fd348b28f2..3af098c4d1 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,11 +23,14 @@   * $/LicenseInfo$   */ -#ifndef LL_LLKEYBOARDSDL_H -#define LL_LLKEYBOARDSDL_H +#ifndef LL_LLKEYBOARDSDL2_H +#define LL_LLKEYBOARDSDL2_H  #include "llkeyboard.h" -#include "SDL/SDL.h" +#if !defined(__i386__) && !defined(__x86_64__) +#define SDL_DISABLE_IMMINTRIN_H +#endif +#include "SDL2/SDL.h"  class LLKeyboardSDL : public LLKeyboard  { @@ -36,8 +38,8 @@ public:      LLKeyboardSDL();      /*virtual*/ ~LLKeyboardSDL() {}; -    /*virtual*/ bool    handleKeyUp(const U16 key, MASK mask); -    /*virtual*/ bool    handleKeyDown(const U16 key, MASK mask); +    /*virtual*/ bool    handleKeyUp(const U32 key, MASK mask); +    /*virtual*/ bool    handleKeyDown(const U32 key, MASK mask);      /*virtual*/ void    resetMaskKeys();      /*virtual*/ MASK    currentMask(bool for_mouse_event);      /*virtual*/ void    scanKeyboard(); @@ -45,11 +47,14 @@ public:  protected:      MASK    updateModifiers(const U32 mask);      void    setModifierKeyLevel( KEY key, bool new_state ); -    bool    translateNumpadKey( const U16 os_key, KEY *translated_key ); +    bool    translateNumpadKey( const U32 os_key, KEY *translated_key );      U16 inverseTranslateNumpadKey(const KEY translated_key);  private: -    std::map<U16, KEY> mTranslateNumpadMap;  // special map for translating OS keys to numpad keys -    std::map<KEY, U16> mInvTranslateNumpadMap; // inverse of the above +    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/llwindow.cpp b/indra/llwindow/llwindow.cpp index 378e633cd2..302d038a79 100644 --- a/indra/llwindow/llwindow.cpp +++ b/indra/llwindow/llwindow.cpp @@ -76,7 +76,7 @@ S32 OSMessageBox(const std::string& text, const std::string& caption, U32 type)      return OSBTN_OK;  #elif LL_WINDOWS      result = OSMessageBoxWin32(text, caption, type); -#elif LL_DARWIN +#elif LL_DARWIN && !LL_SDL      result = OSMessageBoxMacOSX(text, caption, type);  #elif LL_SDL      result = OSMessageBoxSDL(text, caption, type); @@ -261,7 +261,7 @@ std::vector<std::string> LLWindow::getDynamicFallbackFontList()  {  #if LL_WINDOWS      return LLWindowWin32::getDynamicFallbackFontList(); -#elif LL_DARWIN +#elif LL_DARWIN && !LL_SDL      return LLWindowMacOSX::getDynamicFallbackFontList();  #elif LL_SDL      return LLWindowSDL::getDynamicFallbackFontList(); @@ -275,7 +275,7 @@ std::vector<std::string> LLWindow::getDisplaysResolutionList()  {  #if LL_WINDOWS      return LLWindowWin32::getDisplaysResolutionList(); -#elif LL_DARWIN +#elif LL_DARWIN && !LL_SDL      return LLWindowMacOSX::getDisplaysResolutionList();  #else      return std::vector<std::string>(); @@ -346,7 +346,7 @@ LLSplashScreen *LLSplashScreen::create()      return 0;  #elif LL_WINDOWS      return new LLSplashScreenWin32; -#elif LL_DARWIN +#elif LL_DARWIN && !LL_SDL      return new LLSplashScreenMacOSX;  #else  #error("LLSplashScreen not implemented on this platform!") @@ -361,7 +361,7 @@ void LLSplashScreen::show()      {  #if LL_WINDOWS && !LL_MESA_HEADLESS          gSplashScreenp = new LLSplashScreenWin32; -#elif LL_DARWIN +#elif LL_DARWIN && !LL_SDL          gSplashScreenp = new LLSplashScreenMacOSX;  #endif          if (gSplashScreenp) @@ -411,7 +411,7 @@ LLWindow* LLWindowManager::createWindow(      U32 max_cores,      F32 max_gl_version)  { -    LLWindow* new_window; +    LLWindow* new_window = nullptr;      if (use_gl)      { diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp index c160382c17..624ecd5030 100644 --- a/indra/llwindow/llwindowcallbacks.cpp +++ b/indra/llwindow/llwindowcallbacks.cpp @@ -52,6 +52,10 @@ bool LLWindowCallbacks::handleUnicodeChar(llwchar uni_char, MASK mask)      return false;  } +bool LLWindowCallbacks::handleUnicodeString(char *uni_str, bool editing) +{ +	return FALSE; +}  bool LLWindowCallbacks::handleMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask)  { diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h index 63b585231f..74660e1705 100644 --- a/indra/llwindow/llwindowcallbacks.h +++ b/indra/llwindow/llwindowcallbacks.h @@ -37,6 +37,7 @@ public:      virtual bool handleTranslatedKeyUp(KEY key,  MASK mask);      virtual void handleScanKey(KEY key, bool key_down, bool key_up, bool key_level);      virtual bool handleUnicodeChar(llwchar uni_char, MASK mask); +    virtual bool handleUnicodeString(char *uni_str, bool editing);      virtual bool handleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask);      virtual bool handleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask); diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 80001b14ee..3cfc9d7c84 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -38,6 +38,7 @@  #include "lldir.h"  #include "indra_constants.h" +  #include <OpenGL/OpenGL.h>  #include <Carbon/Carbon.h>  #include <CoreServices/CoreServices.h> diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 7433ad6bd2..8c90f917b8 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" @@ -40,23 +38,23 @@  #include "lldir.h"  #include "llfindlocale.h" -#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"  } -#if LL_LINUX +#if LL_LINUX || __FreeBSD__  // not necessarily available on random SDL platforms, so #if LL_LINUX  // for execv(), waitpid(), fork()  # include <unistd.h>  # include <sys/types.h>  # include <sys/wait.h> +# define GLX_GLXEXT_PROTOTYPES 1 +# include <GL/glx.h> +# include <stdio.h>  #endif // LL_LINUX  extern bool gDebugWindowProc; @@ -66,6 +64,43 @@ const S32 MAX_NUM_RESOLUTIONS = 200;  // static variable for ATI mouse cursor crash work-around:  static bool ATIbug = false; +#if LL_DARWIN + +#include <OpenGL/OpenGL.h> +#include <CoreGraphics/CGDirectDisplay.h> +#include <CoreServices/CoreServices.h> + +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; +} +// +// LLWindowMacOSX +// + +bool LLWindowSDL::sUseMultGL = false; + +#endif + +bool hasHIDPI = 0; +  //  // LLWindowSDL  // @@ -97,108 +132,291 @@ 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; -    if (!done_setlocale) +    Atom XA_CLIPBOARD; +    Atom XA_TARGETS; +    Atom PVT_PASTE_BUFFER; +    long const MAX_PASTE_BUFFER_SIZE = 16383; + +    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; -        if (!g_thread_supported ()) g_thread_init (NULL); -        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); + +            // 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; + +    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(); +} + +bool LLWindowSDL::getSelectionText( Atom aSelection, Atom aType, LLWString &text ) +{ +    if( !mSDL_Display ) +        return false; + +    if( !grab_property(mSDL_Display, mSDL_XWindowID, aSelection,aType ) ) +        return false; -        done_gtk_diag = true; +    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);      } -    return gtk_is_good; +    maybe_unlock_display(); +    return res == Success;  } -#endif // LL_GTK +bool LLWindowSDL::getSelectionText(Atom selection, LLWString& text) +{ +    if (!mSDL_Display) +        return false; -#if LL_X11 -// static -Window LLWindowSDL::get_SDL_XWindowID(void) +    maybe_lock_display(); + +    Window owner = XGetSelectionOwner(mSDL_Display, selection); +    if (owner == None) +    { +        if (selection == XA_PRIMARY) +        { +            owner = DefaultRootWindow(mSDL_Display); +            selection = XA_CUT_BUFFER0; +        } +        else +        { +            maybe_unlock_display(); +            return false; +        } +    } + +    maybe_unlock_display(); + +    for( Atom atom : gSupportedAtoms ) +    { +        if(getSelectionText(selection, atom, text ) ) +            return true; +    } + +    return false; +} + +bool LLWindowSDL::setSelectionText(Atom selection, const LLWString& text)  { -    if (gWindowImplementation) { -        return gWindowImplementation->mSDL_XWindowID; +    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 None; +    else +        mSecondaryClipboard = text; + +    XSetSelectionOwner(mSDL_Display, selection, mSDL_XWindowID, CurrentTime); + +    auto owner = XGetSelectionOwner(mSDL_Display, selection); + +    maybe_unlock_display(); + +    return owner == mSDL_XWindowID;  } -//static -Display* LLWindowSDL::get_SDL_Display(void) +Display* LLWindowSDL::getSDLDisplay()  { -    if (gWindowImplementation) { +    if (gWindowImplementation)          return gWindowImplementation->mSDL_Display; -    } -    return NULL; +    return nullptr;  } -#endif // LL_X11 + +#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();      gKeyboard->setCallbacks(callbacks);      // Note that we can't set up key-repeat until after SDL has init'd video +#if LL_DARWIN +    hasHIDPI = gHiDPISupport; +#endif +      // Ignore use_gl for now, only used for drones on PC      mWindow = NULL; +    mContext = {};      mNeedsResize = false;      mOverrideAspectRatio = 0.f;      mGrabbyKeyFlags = 0; @@ -212,13 +430,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; @@ -244,9 +455,9 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,  #if LL_X11      mFlashing = false; +    initialiseX11Clipboard();  #endif // LL_X11 -    mKeyScanCode = 0;      mKeyVirtualKey = 0;      mKeyModifiers = KMOD_NONE;  } @@ -258,10 +469,10 @@ 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); @@ -348,7 +559,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) @@ -373,7 +584,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."; @@ -383,7 +594,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) @@ -399,95 +610,170 @@ 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; -    const SDL_version *r_sdl_version; -    r_sdl_version = SDL_Linked_Version(); +               << 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; -    const SDL_VideoInfo *video_info = SDL_GetVideoInfo( ); -    if (!video_info) -    { -        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; -    if (video_info->current_h > 0) -    { -        mOriginalAspectRatio = (float)video_info->current_w / (float)video_info->current_h; -        LL_INFOS() << "Original aspect ratio was " << video_info->current_w << ":" << video_info->current_h << "=" << mOriginalAspectRatio << LL_ENDL; -    } +    mFullscreen = fullscreen; -    SDL_EnableUNICODE(1); -    SDL_WM_SetCaption(mWindowTitle.c_str(), mWindowTitle.c_str()); +    int sdlflags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; -    // Set the application icon. -    SDL_Surface *bmpsurface; -    bmpsurface = Load_BMP_Resource("ll_icon.BMP"); -    if (bmpsurface) +    if( mFullscreen )      { -        // This attempts to give a black-keyed mask to the icon. -        SDL_SetColorKey(bmpsurface, -                SDL_SRCCOLORKEY, -                SDL_MapRGB(bmpsurface->format, 0,0,0) ); -        SDL_WM_SetIcon(bmpsurface, NULL); -        // The SDL examples cheerfully avoid freeing the icon -        // surface, but I'm betting that's leaky. -        SDL_FreeSurface(bmpsurface); -        bmpsurface = NULL; +        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}; + +    GLint depthBits{(bits <= 16) ? 16 : 24}, stencilBits{8}; + +    if (getenv("LL_GL_NO_STENCIL")) +        stencilBits = 0; -    int sdlflags = SDL_OPENGL | SDL_RESIZABLE | SDL_ANYFORMAT; +    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 +    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); +#else +    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6); +#endif +    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);      SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); @@ -497,80 +783,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; -            } +            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); +    } -        if((width == 0) || (height == 0)) -        { -            // Mode search failed for some reason.  Use the old-school default. -            width = 1024; -            height = 768; -        } - -        mWindow = SDL_SetVideoMode(width, height, bits, sdlflags | SDL_FULLSCREEN); -        if (!mWindow && bits > 16) -        { -            SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); -            mWindow = SDL_SetVideoMode(width, height, bits, sdlflags | SDL_FULLSCREEN); -        } +    if( mFullscreen ) +    {          if (mWindow)          {              mFullscreen = true; -            mFullscreenWidth   = mWindow->w; -            mFullscreenHeight  = mWindow->h; -            mFullscreenBits    = mWindow->format->BitsPerPixel; +            /* +            mFullscreenWidth = mSurface->w; +            mFullscreenHeight = mSurface->h; +            mFullscreenBits    = mSurface->format->BitsPerPixel; +            */ +            SDL_GetWindowSize(mWindow, &mFullscreenWidth, &mFullscreenHeight);              mFullscreenRefresh = -1;              LL_INFOS() << "Running at " << mFullscreenWidth -                << "x"   << mFullscreenHeight -                << "x"   << mFullscreenBits -                << " @ " << mFullscreenRefresh -                << LL_ENDL; +                       << "x"   << mFullscreenHeight +                       << "x"   << mFullscreenBits +                       << " @ " << mFullscreenRefresh +                       << LL_ENDL;          }          else          { @@ -584,33 +831,27 @@ 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_SetVideoMode(width, height, bits, sdlflags); -        if (!mWindow && bits > 16) -        { -            SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); -            mWindow = SDL_SetVideoMode(width, height, bits, sdlflags); -        } -          if (!mWindow)          {              LL_WARNS() << "createContext: window creation failure. SDL: " << SDL_GetError() << LL_ENDL;              setupFailure("Window creation error", "Error", OSMB_OK);              return false;          } -    } else if (!mFullscreen && (mWindow != NULL)) +    } + +    // Set the application icon. +    SDL_Surface *bmpsurface; +    bmpsurface = Load_BMP_Resource("ll_icon.BMP"); +    if (bmpsurface)      { -        LL_INFOS() << "createContext: SKIPPING - !fullscreen, but +mWindow " << width << "x" << height << "x" << bits << LL_ENDL; +        SDL_SetWindowIcon(mWindow, bmpsurface); +        SDL_FreeSurface(bmpsurface); +        bmpsurface = NULL;      }      // Detect video memory size. @@ -620,39 +861,67 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b      {          LL_INFOS() << "X11 log-parser detected " << gGLManager.mVRAM << "MB VRAM." << LL_ENDL;      } else +    { +        PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC queryInteger; +        queryInteger = (PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC) +            glXGetProcAddressARB((const GLubyte *)"glXQueryCurrentRendererIntegerMESA"); +        unsigned int vram_megabytes = 0; +        queryInteger(GLX_RENDERER_VIDEO_MEMORY_MESA, &vram_megabytes); +        if (!vram_megabytes) { +            glGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, (int *)&vram_megabytes); +            vram_megabytes /= 1024; +        } +        if (!vram_megabytes) { +            glGetIntegerv(GL_VBO_FREE_MEMORY_ATI, (int *)&vram_megabytes); +            vram_megabytes /= 1024; +        } +        gGLManager.mVRAM = vram_megabytes; +    } +#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 = video_info->video_mem / 1024; +        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 @@ -660,70 +929,51 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b      // relaxed about if we have to.      if (colorBits < 32)      { +#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); -        return false; -    } - -#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); +                "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 LL_X11      /* Grab the window manager specific information */      SDL_SysWMinfo info;      SDL_VERSION(&info.version); -    if ( SDL_GetWMInfo(&info) ) +    if ( SDL_GetWindowWMInfo(mWindow, &info) )      {          /* Save the information for later use */          if ( info.subsystem == SDL_SYSWM_X11 )          {              mSDL_Display = info.info.x11.display; -            mSDL_XWindowID = info.info.x11.wmwindow; -            Lock_Display = info.info.x11.lock_func; -            Unlock_Display = info.info.x11.unlock_func; +            mSDL_XWindowID = info.info.x11.window;          }          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); - -    // 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; +#endif      // Don't need to get the current gamma, since there's a call that restores it to the system defaults.      return true; @@ -761,6 +1011,7 @@ void LLWindowSDL::destroyContext()  {      LL_INFOS() << "destroyContext begins" << LL_ENDL; +    SDL_StopTextInput();  #if LL_X11      mSDL_Display = NULL;      mSDL_XWindowID = None; @@ -794,23 +1045,39 @@ LLWindowSDL::~LLWindowSDL()  void LLWindowSDL::show()  {      // *FIX: What to do with SDL? +    if (mWindow) +    { +        SDL_ShowWindow(mWindow); +    }  }  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); +    }  }  //virtual  void LLWindowSDL::restore()  {      // *FIX: What to do with SDL? +    if (mWindow) +    { +        SDL_RestoreWindow(mWindow); +    }  } @@ -844,7 +1111,7 @@ bool LLWindowSDL::getVisible()      // Then what is?      if (mWindow)      { -        result = true; +        if( SDL_GetWindowFlags(mWindow) & SDL_WINDOW_SHOWN ) result = true;      }      return(result); @@ -854,10 +1121,12 @@ bool LLWindowSDL::getMinimized()  {      bool result = false; -    if (mWindow && (1 == mIsMinimized)) +    if (mWindow/*&& (1 == mIsMinimized)*/)      { -        result = true; +        if( SDL_GetWindowFlags(mWindow) & SDL_WINDOW_MINIMIZED ) result = true;      } + +    mIsMinimized = result;      return(result);  } @@ -868,6 +1137,8 @@ bool LLWindowSDL::getMaximized()      if (mWindow)      {          // TODO +        if( SDL_GetWindowFlags(mWindow) & SDL_WINDOW_MAXIMIZED ) result = true; +        else result = false;      }      return(result); @@ -876,7 +1147,15 @@ bool LLWindowSDL::getMaximized()  bool LLWindowSDL::maximize()  {      // TODO -    return false; +    bool result = false; + +    if (mWindow) +    { +        SDL_MaximizeWindow(mWindow); +        result = true; +    } + +    return result;  }  bool LLWindowSDL::getFullscreen() @@ -896,9 +1175,13 @@ bool LLWindowSDL::getSize(LLCoordScreen *size)  {      if (mWindow)      { -        size->mX = mWindow->w; -        size->mY = mWindow->h; -    return (true); +        /* +        if(hasHIDPI) +            SDL_GL_GetDrawableSize(mWindow, &size->mX, &size->mY); +        else +        */ +        SDL_GetWindowSize(mWindow, &size->mX, &size->mY); +        return (true);      }      return (false); @@ -908,9 +1191,11 @@ bool LLWindowSDL::getSize(LLCoordWindow *size)  {      if (mWindow)      { -        size->mX = mWindow->w; -        size->mY = mWindow->h; -    return (true); +        if(hasHIDPI) +            SDL_GL_GetDrawableSize(mWindow, &size->mX, &size->mY); +        else +            SDL_GetWindowSize(mWindow, &size->mX, &size->mY); +        return (true);      }      return (false); @@ -918,49 +1203,50 @@ bool LLWindowSDL::getSize(LLCoordWindow *size)  bool LLWindowSDL::setPosition(const LLCoordScreen position)  { +    bool result = false; +      if(mWindow)      {          // *FIX: (?)          //MacMoveWindow(mWindow, position.mX, position.mY, false); +        SDL_SetWindowPosition(mWindow, position.mX, position.mY); +        result = true;      } -    return true; +    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_VIDEORESIZE; -        event.resize.w = size.mX; -        event.resize.h = 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_VIDEORESIZE; -        event.resize.w = size.mX; -        event.resize.h = 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 );  } @@ -968,7 +1254,7 @@ void LLWindowSDL::swapBuffers()  {      if (mWindow)      { -        SDL_GL_SwapBuffers(); +        SDL_GL_SwapWindow( mWindow );      }  } @@ -990,7 +1276,10 @@ F32 LLWindowSDL::getGamma()  bool LLWindowSDL::restoreGamma()  {      //CGDisplayRestoreColorSyncSettings(); -    SDL_SetGamma(1.0f, 1.0f, 1.0f); +    // SDL_SetGamma(1.0f, 1.0f, 1.0f); +    Uint16 ramp; +    SDL_CalculateGammaRamp(1.0f, &ramp); +    SDL_SetWindowGammaRamp(mWindow, &ramp, &ramp, &ramp);      return true;  } @@ -999,7 +1288,10 @@ bool LLWindowSDL::setGamma(const F32 gamma)      mGamma = gamma;      if (mGamma == 0) mGamma = 0.1f;      mGamma = 1/mGamma; -    SDL_SetGamma(mGamma, mGamma, mGamma); +    // SDL_SetGamma(mGamma, mGamma, mGamma); +    Uint16 ramp; +    SDL_CalculateGammaRamp(mGamma, &ramp); +    SDL_SetWindowGammaRamp(mWindow, &ramp, &ramp, &ramp);      return true;  } @@ -1048,7 +1340,14 @@ bool LLWindowSDL::setCursorPosition(const LLCoordWindow position)      //LL_INFOS() << "setCursorPosition(" << screen_pos.mX << ", " << screen_pos.mY << ")" << LL_ENDL;      // do the actual forced cursor move. -    SDL_WarpMouse(screen_pos.mX, screen_pos.mY); + +    if (mFullscreen) +    { +        SDL_WarpMouseGlobal(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; @@ -1070,21 +1369,14 @@ bool LLWindowSDL::getCursorPosition(LLCoordWindow *position)      return convertCoords(screen_pos, position);  } +F32 LLWindowSDL::getSystemUISize() +{ +    if(hasHIDPI) return 2.0f; +    else return 1.f; +}  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. @@ -1146,7 +1438,7 @@ void LLWindowSDL::beforeDialog()              // it only works in X11              if (running_x11 && mWindow)              { -                SDL_WM_ToggleFullScreen(mWindow); +                SDL_SetWindowFullscreen( mWindow, 0 );              }          }      } @@ -1162,12 +1454,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();  } @@ -1188,7 +1474,7 @@ void LLWindowSDL::afterDialog()          // in X11          if (running_x11 && mWindow)          { -            SDL_WM_ToggleFullScreen(mWindow); +            SDL_SetWindowFullscreen( mWindow, 0 );          }      }  } @@ -1224,143 +1510,87 @@ 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) +bool LLWindowSDL::isClipboardTextAvailable()  { -    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 +#if LL_X11 +    return mSDL_Display && XGetSelectionOwner(mSDL_Display, XA_CLIPBOARD) != None; +#else +    return SDL_HasClipboardText(); +#endif  } -bool LLWindowSDL::copyTextToPrimary(const LLWString &text) +bool LLWindowSDL::pasteTextFromClipboard(LLWString &dst)  { -    if (ll_try_gtk_init()) +#if LL_X11 +    return getSelectionText(XA_CLIPBOARD, dst); +#else +    auto data = SDL_GetClipboardText(); +    if (data)      { -        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()); +        dst = LLWString(utf8str_to_wstring(data)); +        SDL_free(data);          return true;      } -    return false; // failure -} - -#else - -bool LLWindowSDL::isClipboardTextAvailable() -{ -    return false; // unsupported -} - -bool LLWindowSDL::pasteTextFromClipboard(LLWString &dst) -{ -    return false; // unsupported +    return false; +#endif  }  bool LLWindowSDL::copyTextToClipboard(const LLWString &s)  { -    return false;  // unsupported +#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) @@ -1368,33 +1598,30 @@ 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; -                int w = r->w; -                int h = r->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++;                  }              }          } @@ -1410,7 +1637,9 @@ bool LLWindowSDL::convertCoords(LLCoordGL from, LLCoordWindow *to)          return false;      to->mX = from.mX; -    to->mY = mWindow->h - from.mY - 1; +    int h; +    SDL_GetWindowSize(mWindow, nullptr, &h); +    to->mY = h - from.mY - 1;      return true;  } @@ -1421,7 +1650,9 @@ bool LLWindowSDL::convertCoords(LLCoordWindow from, LLCoordGL* to)          return false;      to->mX = from.mX; -    to->mY = mWindow->h - from.mY - 1; +    int h; +    SDL_GetWindowSize(mWindow, nullptr, &h); +    to->mY = h - from.mY - 1;      return true;  } @@ -1482,13 +1713,13 @@ bool LLWindowSDL::SDLReallyCaptureInput(bool capture)      else          mReallyCapturedCount = 0; -    SDL_GrabMode wantmode, newmode; +    bool wantGrab;      if (mReallyCapturedCount <= 0) // uncapture      { -        wantmode = SDL_GRAB_OFF; +        wantGrab = false;      } else // capture      { -        wantmode = SDL_GRAB_ON; +        wantGrab = true;      }      if (mReallyCapturedCount < 0) // yuck, imbalance. @@ -1497,9 +1728,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 @@ -1512,49 +1745,37 @@ bool LLWindowSDL::SDLReallyCaptureInput(bool capture)                 *keyboard* input from the window manager, which was                 frustrating users. */              int result; -            if (wantmode == SDL_GRAB_ON) +            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_GRAB_ON; +                    newGrab = true;                  else -                    newmode = SDL_GRAB_OFF; -            } else if (wantmode == SDL_GRAB_OFF) +                    newGrab = false; +            } +            else              { -                //LL_INFOS() << "X11 POINTER UNGRABBY" << LL_ENDL; -                newmode = SDL_GRAB_OFF; -                //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_GRAB_ON==newmode) || -        (!capture && SDL_GRAB_OFF==newmode); +    return capture == newGrab;  } -U32 LLWindowSDL::SDLCheckGrabbyKeys(SDLKey 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 @@ -1572,16 +1793,16 @@ U32 LLWindowSDL::SDLCheckGrabbyKeys(SDLKey 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) @@ -1679,7 +1900,7 @@ void check_vm_bloat()          last_rss_size = this_rss_size;          last_vm_size = this_vm_size; -finally: +        finally:          if (NULL != ptr)          {              free(ptr); @@ -1694,33 +1915,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")) @@ -1743,43 +1948,89 @@ void LLWindowSDL::gatherInput()      {          switch (event.type)          { +            case SDL_MOUSEWHEEL: +                if( event.wheel.y != 0 ) +                    mCallbacks->handleScrollWheel(this, -event.wheel.y); +                break; +              case SDL_MOUSEMOTION:              {                  LLCoordWindow winCoord(event.button.x, event.button.y);                  LLCoordGL openGlCoord;                  convertCoords(winCoord, &openGlCoord); + +                openGlCoord.mX = openGlCoord.mX * getSystemUISize(); +                openGlCoord.mY = openGlCoord.mY * getSystemUISize(); + +                //LL_INFOS() << "SDL_MOUSEMOTION " << event.button.x << " " << event.button.y << " gl " << openGlCoord.mX << " " << openGlCoord.mY << LL_ENDL; +                  MASK mask = gKeyboard->currentMask(true);                  mCallbacks->handleMouseMove(this, openGlCoord, mask);                  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: -            mKeyScanCode = event.key.keysym.scancode; -            mKeyVirtualKey = event.key.keysym.unicode; -            mKeyModifiers = event.key.keysym.mod; +                mKeyVirtualKey = event.key.keysym.sym; +                mKeyModifiers = event.key.keysym.mod; +                mInputType = "keydown"; -            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); +                // 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); -            if (event.key.keysym.unicode) -            { -                handleUnicodeUTF16(event.key.keysym.unicode, -                           gKeyboard->currentMask(false)); -            }                  break;              case SDL_KEYUP: -            mKeyScanCode = event.key.keysym.scancode; -            mKeyVirtualKey = event.key.keysym.unicode; -            mKeyModifiers = event.key.keysym.mod; +                mKeyVirtualKey = event.key.keysym.sym; +                mKeyModifiers = event.key.keysym.mod; +                mInputType = "keyup"; -            if (SDLCheckGrabbyKeys(event.key.keysym.sym, false) == 0) -                SDLReallyCaptureInput(false); // part of the fix for SL-13243 +                // treat all possible Enter/Return keys the same +                if (mKeyVirtualKey == SDLK_RETURN2 || mKeyVirtualKey == SDLK_KP_ENTER) +                { +                    mKeyVirtualKey = SDLK_RETURN; +                } -            gKeyboard->handleKeyUp(event.key.keysym.sym, event.key.keysym.mod); -            break; +                if (SDLCheckGrabbyKeys(mKeyVirtualKey, false) == 0) +                    SDLReallyCaptureInput(false); // part of the fix for SL-13243 + +                gKeyboard->handleKeyUp(mKeyVirtualKey,mKeyModifiers); +                break;              case SDL_MOUSEBUTTONDOWN:              { @@ -1787,7 +2038,11 @@ void LLWindowSDL::gatherInput()                  LLCoordWindow winCoord(event.button.x, event.button.y);                  LLCoordGL openGlCoord;                  convertCoords(winCoord, &openGlCoord); -        MASK mask = gKeyboard->currentMask(true); + +                openGlCoord.mX *= getSystemUISize(); +                openGlCoord.mY *= getSystemUISize(); + +                MASK mask = gKeyboard->currentMask(true);                  if (event.button.button == SDL_BUTTON_LEFT)   // SDL doesn't manage double clicking...                  { @@ -1799,7 +2054,7 @@ void LLWindowSDL::gatherInput()                          if (++leftClick >= 2)                          {                              leftClick = 0; -                isDoubleClick = true; +                            isDoubleClick = true;                          }                      }                      lastLeftDown = now; @@ -1830,7 +2085,7 @@ void LLWindowSDL::gatherInput()                  else if (event.button.button == SDL_BUTTON_RIGHT)  // right                  { -            mCallbacks->handleRightMouseDown(this, openGlCoord, mask); +                    mCallbacks->handleRightMouseDown(this, openGlCoord, mask);                  }                  else if (event.button.button == SDL_BUTTON_MIDDLE)  // middle @@ -1850,86 +2105,108 @@ void LLWindowSDL::gatherInput()                  LLCoordWindow winCoord(event.button.x, event.button.y);                  LLCoordGL openGlCoord;                  convertCoords(winCoord, &openGlCoord); -        MASK mask = gKeyboard->currentMask(true); + +                openGlCoord.mX *= getSystemUISize(); +                openGlCoord.mY *= getSystemUISize(); + +                MASK mask = gKeyboard->currentMask(true);                  if (event.button.button == SDL_BUTTON_LEFT)  // left -            mCallbacks->handleMouseUp(this, openGlCoord, mask); +                    mCallbacks->handleMouseUp(this, openGlCoord, mask);                  else if (event.button.button == SDL_BUTTON_RIGHT)  // right -            mCallbacks->handleRightMouseUp(this, openGlCoord, mask); +                    mCallbacks->handleRightMouseUp(this, openGlCoord, mask);                  else if (event.button.button == SDL_BUTTON_MIDDLE)  // middle -            mCallbacks->handleMiddleMouseUp(this, openGlCoord, mask); +                    mCallbacks->handleMiddleMouseUp(this, openGlCoord, mask);                  // don't handle mousewheel here...                  break;              } -            case SDL_VIDEOEXPOSE:  // VIDEOEXPOSE doesn't specify the damage, but hey, it's OpenGL...repaint the whole thing! -                mCallbacks->handlePaint(this, 0, 0, mWindow->w, mWindow->h); -                break; - -            case SDL_VIDEORESIZE:  // *FIX: handle this? +            case SDL_WINDOWEVENT:  // *FIX: handle this?              { -        LL_INFOS() << "Handling a resize event: " << event.resize.w << -            "x" << event.resize.h << LL_ENDL; +                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; -        S32 width = llmax(event.resize.w, (S32)mMinWindowWidth); -        S32 height = llmax(event.resize.h, (S32)mMinWindowHeight); +                    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)) +                    // *FIX: I'm not sure this is necessary! +                    // <FS:ND> I think is is not +                    // SDL_SetWindowSize(mWindow, width, height); +                    // + +                    mCallbacks->handleResize(this, width * getSystemUISize(), height * getSystemUISize()); +                } +                else if(event.window.event == SDL_WINDOWEVENT_ENTER)                  { -                    // Get the app to initiate cleanup. -                    mCallbacks->handleQuit(this); -                    // The app is responsible for calling destroyWindow when done with GL +                    LL_INFOS() << "SDL_WINDOWEVENT_ENTER" << LL_ENDL; +                    if(!mHaveInputFocus) mCallbacks->handleFocus(this); +                    mHaveInputFocus = true;                  } -                break; -        } - -        mCallbacks->handleResize(this, width, height); -                break; -            } -            case SDL_ACTIVEEVENT: -                if (event.active.state & SDL_APPINPUTFOCUS) +                else if(event.window.event == SDL_WINDOWEVENT_LEAVE)                  { -            // Note that for SDL (particularly on X11), keyboard -            // and mouse focus are independent things.  Here we are -            // tracking keyboard focus state changes. - -            // 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]. -            if (event.active.gain != mHaveInputFocus) -            { -                mHaveInputFocus = !!event.active.gain; +                    LL_INFOS() << "SDL_WINDOWEVENT_LEAVE" << LL_ENDL; +                    if(mHaveInputFocus) mCallbacks->handleFocusLost(this); +                    mHaveInputFocus = false; +                } +                else if( event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED ) // <FS:ND> What about SDL_WINDOWEVENT_ENTER (mouse focus) +                { +                    // 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; -                if (mHaveInputFocus)                      mCallbacks->handleFocus(this); -                else +                } +                else if( event.window.event == SDL_WINDOWEVENT_FOCUS_LOST ) // <FS:ND> What about SDL_WINDOWEVENT_LEAVE (mouse focus) +                { +                    // 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); -            }                  } -                if (event.active.state & SDL_APPACTIVE) +                /* + +                Bug : the app remains inactive when maximized .. + +                else if(event.window.event == SDL_WINDOWEVENT_MINIMIZED)                  { -            // Change in iconification/minimization state. -            if ((!event.active.gain) != mIsMinimized) -            { -                mIsMinimized = (!event.active.gain); +                    LL_INFOS() << "SDL_WINDOWEVENT_MINIMIZED" << LL_ENDL; +                    if(!mIsMinimized) mCallbacks->handleActivate(this,false); +                    mIsMinimized = true; +                } +                else if(event.window.event == SDL_WINDOWEVENT_MAXIMIZED) +                { +                    LL_INFOS() << "SDL_WINDOWEVENT_MAXIMIZED" << LL_ENDL; +                    if(mIsMinimized) mCallbacks->handleActivate(this,true); +                    mIsMinimized = false; +                } +                */ +                else if (event.window.event == SDL_WINDOWEVENT_EXPOSED) +                { +                    int w, h; +                    SDL_GL_GetDrawableSize(mWindow, &w, &h); -                mCallbacks->handleActivate(this, !mIsMinimized); -                LL_INFOS() << "SDL deiconification state switched to " << bool(event.active.gain) << LL_ENDL; -            } -            else -            { -                LL_INFOS() << "Ignored bogus redundant SDL deiconification state switch to " << bool(event.active.gain) << LL_ENDL; -            } +                    mCallbacks->handlePaint(this, 0, 0, w, h);                  } -                break; +                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))                  { @@ -1938,9 +2215,9 @@ 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; +            default: +                //LL_INFOS() << "Unhandled SDL event type " << event.type << LL_ENDL; +                break;          }      } @@ -1968,21 +2245,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; @@ -1997,26 +2274,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 { @@ -2207,8 +2484,6 @@ void LLWindowSDL::hideCursorUntilMouseMove()      }  } - -  //  // LLSplashScreenSDL - I don't think we'll bother to implement this; it's  // fairly obsolete at this point. @@ -2233,133 +2508,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; - -    if(gWindowImplementation != NULL) -        gWindowImplementation->beforeDialog(); +    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 (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! @@ -2377,99 +2590,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["virtual_key"] = (S32)mKeyVirtualKey; +    result["virtual_key_win"] = (S32)LLKeyboardSDL::mapSDL2toWin( 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); +    result["input_type"] = mInputType; +    return result;  } -#endif // LL_GTK +#endif // LL_DARWIN -#if LL_LINUX +#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) @@ -2481,9 +2610,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. @@ -2525,7 +2677,7 @@ void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async)      LL_INFOS() << "spawn_web_browser: " << escaped_url << LL_ENDL; -#if LL_LINUX +#if LL_LINUX || __FreeBSD__  # if LL_X11      if (mSDL_Display)      { @@ -2537,43 +2689,65 @@ void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async)  # endif // LL_X11      std::string cmd, arg; +#ifdef LL_USESYSTEMLIBS +    cmd  = gDirUtilp->getExecutableDir(); +#else      cmd  = gDirUtilp->getAppRODataDir();      cmd += gDirUtilp->getDirDelimiter();      cmd += "etc"; +#endif      cmd += gDirUtilp->getDirDelimiter();      cmd += "launch_url.sh";      arg = escaped_url;      exec_cmd(cmd, arg); -#endif // LL_LINUX -    LL_INFOS() << "spawn_web_browser returning." << LL_ENDL; -} +#elif LL_DARWIN +    S32 result = 0; +    CFURLRef urlRef = NULL; -void *LLWindowSDL::getPlatformWindow() -{ -#if LL_GTK && LL_LLMOZLIB_ENABLED -    if (LLWindowSDL::ll_try_gtk_init()) +    LL_INFOS() << "Opening URL " << escaped_url << LL_ENDL; + +    CFStringRef    stringRef = CFStringCreateWithCString(NULL, escaped_url.c_str(), kCFStringEncodingUTF8); +    if (stringRef)      { -        maybe_lock_display(); +        // 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); -        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); +        // Don't use CRURLCreateWithFileSystemPath -- only want valid URLs -        maybe_unlock_display(); +        CFRelease(stringRef); +    } -        return rtnw; +    if (urlRef) +    { +        result = LSOpenCFURLRef(urlRef, NULL); + +        if (result != noErr) +        { +            LL_INFOS() << "Error " << result << " on open." << LL_ENDL; +        } + +        CFRelease(urlRef);      } -#endif // LL_GTK && LL_LLMOZLIB_ENABLED -    // Unixoid mozilla really needs GTK. +    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() +{      return NULL;  } @@ -2634,10 +2808,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); @@ -2655,7 +2829,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);      } @@ -2669,8 +2843,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)); @@ -2694,4 +2868,64 @@ 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); +    } +} + +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 196ad2986d..3ed2811572 100644 --- a/indra/llwindow/llwindowsdl.h +++ b/indra/llwindow/llwindowsdl.h @@ -24,20 +24,24 @@   * $/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  #include "llwindow.h"  #include "lltimer.h" -#include "SDL/SDL.h" -#include "SDL/SDL_endian.h" +#if !defined(__i386__) && !defined(__x86_64__) +#define SDL_DISABLE_IMMINTRIN_H +#endif +#include "SDL2/SDL.h" +#include "SDL2/SDL_video.h" +#include "SDL2/SDL_endian.h"  #if LL_X11  // get X11-specific headers for use in low-level stuff like copy-and-paste support -#include "SDL/SDL_syswm.h" +#include "SDL2/SDL_syswm.h"  #endif  // AssertMacros.h does bad things. @@ -46,83 +50,141 @@  #undef require -class LLWindowSDL : public LLWindow -{ +class LLWindowSDL : public LLWindow {  public: -    /*virtual*/ void show(); -    /*virtual*/ void hide(); -    /*virtual*/ void close(); -    /*virtual*/ bool getVisible(); -    /*virtual*/ bool getMinimized(); -    /*virtual*/ bool getMaximized(); -    /*virtual*/ bool maximize(); -    /*virtual*/ void minimize(); -    /*virtual*/ void restore(); -    /*virtual*/ bool getFullscreen(); -    /*virtual*/ bool getPosition(LLCoordScreen *position); -    /*virtual*/ bool getSize(LLCoordScreen *size); -    /*virtual*/ bool getSize(LLCoordWindow *size); -    /*virtual*/ bool setPosition(LLCoordScreen position); -    /*virtual*/ bool setSizeImpl(LLCoordScreen size); -    /*virtual*/ bool setSizeImpl(LLCoordWindow size); -    /*virtual*/ bool switchContext(bool fullscreen, const LLCoordScreen &size, bool disable_vsync, const LLCoordScreen * const posp = NULL); -    /*virtual*/ bool setCursorPosition(LLCoordWindow position); -    /*virtual*/ bool getCursorPosition(LLCoordWindow *position); -    /*virtual*/ void showCursor(); -    /*virtual*/ void hideCursor(); -    /*virtual*/ void showCursorFromMouseMove(); -    /*virtual*/ void hideCursorUntilMouseMove(); -    /*virtual*/ bool isCursorHidden(); -    /*virtual*/ void updateCursor(); -    /*virtual*/ void captureMouse(); -    /*virtual*/ void releaseMouse(); -    /*virtual*/ void setMouseClipping( bool b ); -    /*virtual*/ void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true); - -    /*virtual*/ bool isClipboardTextAvailable(); -    /*virtual*/ bool pasteTextFromClipboard(LLWString &dst); -    /*virtual*/ bool copyTextToClipboard(const LLWString & src); - -    /*virtual*/ bool isPrimaryTextAvailable(); -    /*virtual*/ bool pasteTextFromPrimary(LLWString &dst); -    /*virtual*/ bool copyTextToPrimary(const LLWString & src); - -    /*virtual*/ void flashIcon(F32 seconds); -    /*virtual*/ F32 getGamma(); -    /*virtual*/ bool setGamma(const F32 gamma); // Set the gamma -    /*virtual*/ U32 getFSAASamples(); -    /*virtual*/ void setFSAASamples(const U32 samples); -    /*virtual*/ bool restoreGamma();            // Restore original gamma table (before updating gamma) -    /*virtual*/ ESwapMethod getSwapMethod() { return mSwapMethod; } -    /*virtual*/ void processMiscNativeEvents(); -    /*virtual*/ void gatherInput(); -    /*virtual*/ void swapBuffers(); -    /*virtual*/ void restoreGLContext() {}; - -    /*virtual*/ void delayInputProcessing() { }; +    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; + +    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; + +    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; + +    bool isClipboardTextAvailable() override; + +    bool pasteTextFromClipboard(LLWString &dst) override; + +    bool copyTextToClipboard(const LLWString &src) override; + +    bool isPrimaryTextAvailable() override; + +    bool pasteTextFromPrimary(LLWString &dst) 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; } + +    void processMiscNativeEvents() override; + +    void gatherInput() override; + +    void swapBuffers() override; + +    void restoreGLContext() {}; + +    void delayInputProcessing()  override {};      // handy coordinate space conversion routines -    /*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordWindow *to); -    /*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordScreen *to); -    /*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordGL *to); -    /*virtual*/ bool convertCoords(LLCoordGL from, LLCoordWindow *to); -    /*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordGL *to); -    /*virtual*/ bool convertCoords(LLCoordGL from, LLCoordScreen *to); +    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; -    /*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions); -    /*virtual*/ F32 getNativeAspectRatio(); -    /*virtual*/ F32 getPixelAspectRatio(); -    /*virtual*/ void setNativeAspectRatio(F32 ratio) { mOverrideAspectRatio = ratio; } +    LLWindowResolution *getSupportedResolutions(S32 &num_resolutions) override; -    /*virtual*/ void beforeDialog(); -    /*virtual*/ void afterDialog(); +    F32 getNativeAspectRatio() override; -    /*virtual*/ bool dialogColorPicker(F32 *r, F32 *g, F32 *b); +    F32 getPixelAspectRatio() override; -    /*virtual*/ void *getPlatformWindow(); -    /*virtual*/ void bringToFront(); +    void setNativeAspectRatio(F32 ratio)  override { mOverrideAspectRatio = ratio; } -    /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async); +    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; + +    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(); @@ -132,40 +194,56 @@ 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; +#endif + +    void *createSharedContext() override; + +    void makeContextCurrent(void *context) override; + +    void destroySharedContext(void *context) override; + +    void toggleVSync(bool enable_vsync) 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(); -    /*virtual*/ bool    isValid(); -    /*virtual*/ LLSD    getNativeKeyData(); +    bool isValid() override; + +    LLSD getNativeKeyData() override; -    void    initCursors(); -    void    quitCursors(); -    void    moveWindow(const LLCoordScreen& position,const LLCoordScreen& size); +    void initCursors(); + +    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:      // @@ -174,46 +252,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(SDLKey keysym, bool gain); + +    U32 SDLCheckGrabbyKeys(U32 keysym, bool gain); +      bool SDLReallyCaptureInput(bool capture);      //      // Platform specific variables      // -    U32             mGrabbyKeyFlags; -    int         mReallyCapturedCount; -    SDL_Surface *   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 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; -    SDLMod mKeyModifiers; -}; +    U32 mKeyVirtualKey; +    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  { @@ -221,9 +337,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 91437b98d1..a48bd35765 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 | 
