summaryrefslogtreecommitdiff
path: root/indra/llwindow
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llwindow')
-rw-r--r--indra/llwindow/CMakeLists.txt9
-rw-r--r--indra/llwindow/llkeyboard.cpp12
-rw-r--r--indra/llwindow/llkeyboard.h18
-rw-r--r--indra/llwindow/llkeyboardheadless.cpp8
-rw-r--r--indra/llwindow/llkeyboardheadless.h9
-rw-r--r--indra/llwindow/llkeyboardsdl.cpp451
-rw-r--r--indra/llwindow/llkeyboardsdl.h24
-rw-r--r--indra/llwindow/llwindow.h2
-rw-r--r--indra/llwindow/llwindowmacosx-objc.h2
-rw-r--r--indra/llwindow/llwindowmacosx-objc.mm7
-rw-r--r--indra/llwindow/llwindowmacosx.cpp21
-rw-r--r--indra/llwindow/llwindowmacosx.h2
-rw-r--r--indra/llwindow/llwindowsdl.cpp1653
-rw-r--r--indra/llwindow/llwindowsdl.h336
-rw-r--r--indra/llwindow/llwindowwin32.cpp58
-rw-r--r--indra/llwindow/llwindowwin32.h2
16 files changed, 1504 insertions, 1110 deletions
diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt
index 2996f58fe0..075e17235a 100644
--- a/indra/llwindow/CMakeLists.txt
+++ b/indra/llwindow/CMakeLists.txt
@@ -59,12 +59,14 @@ set(llwindow_LINK_LIBRARIES
ll::glext
ll::uilibraries
ll::SDL
+ ll::zlib-ng
)
+
# 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
+ list(APPEND viewer_SOURCE_FILES
+ llkeyboardsdl.cpp
llwindowsdl.cpp
)
list(APPEND viewer_HEADER_FILES
@@ -84,7 +86,6 @@ if (LINUX)
fontconfig # For FCInit and other FC* functions.
)
endif (BUILD_HEADLESS)
-
endif (LINUX)
if (DARWIN)
@@ -180,7 +181,7 @@ endif (SDL_FOUND)
target_link_libraries (llwindow ${llwindow_LINK_LIBRARIES})
target_include_directories(llwindow INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
-
+
if (DARWIN)
include(CMakeFindFrameworks)
find_library(CARBON_LIBRARY Carbon)
diff --git a/indra/llwindow/llkeyboard.cpp b/indra/llwindow/llkeyboard.cpp
index 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..d3c35b1ed4 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,14 +72,13 @@ 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 U16 key, MASK mask) = 0;
- virtual bool handleKeyDown(const U16 key, MASK mask) = 0;
+ virtual bool handleKeyUp(const NATIVE_KEY_TYPE key, MASK mask) = 0;
+ virtual bool handleKeyDown(const NATIVE_KEY_TYPE key, MASK mask) = 0;
#ifdef LL_DARWIN
// We only actually use this for macOS.
@@ -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..ad8e42a412 100644
--- a/indra/llwindow/llkeyboardheadless.cpp
+++ b/indra/llwindow/llkeyboardheadless.cpp
@@ -34,14 +34,6 @@ LLKeyboardHeadless::LLKeyboardHeadless()
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..543882fc8f 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.
@@ -201,37 +201,37 @@ 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;
+ bool handled = false;
adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask);
@@ -246,12 +246,12 @@ 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;
+ bool handled = false;
adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask);
@@ -268,16 +268,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 +314,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 +324,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..9ebff66865 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,11 @@
* $/LicenseInfo$
*/
-#ifndef LL_LLKEYBOARDSDL_H
-#define LL_LLKEYBOARDSDL_H
+#ifndef LL_LLKEYBOARDSDL2_H
+#define LL_LLKEYBOARDSDL2_H
#include "llkeyboard.h"
-#include "SDL/SDL.h"
+#include "SDL2/SDL.h"
class LLKeyboardSDL : public LLKeyboard
{
@@ -36,8 +35,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 +44,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.h b/indra/llwindow/llwindow.h
index 5e06e665f3..fcc4fd863a 100644
--- a/indra/llwindow/llwindow.h
+++ b/indra/llwindow/llwindow.h
@@ -184,6 +184,8 @@ public:
virtual void interruptLanguageTextInput() {}
virtual void spawnWebBrowser(const std::string& escaped_url, bool async) {};
+ virtual void openFolder(const std::string &path) {};
+
static std::vector<std::string> getDynamicFallbackFontList();
// Provide native key event data
diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h
index d9d8bfce1f..620bbc8876 100644
--- a/indra/llwindow/llwindowmacosx-objc.h
+++ b/indra/llwindow/llwindowmacosx-objc.h
@@ -178,6 +178,8 @@ void setMarkedText(unsigned short *text, unsigned int *selectedRange, unsigned i
void getPreeditLocation(float *location, unsigned int length);
void allowDirectMarkedTextInput(bool allow, GLViewRef glView);
+void openFolderWithFinder(const char *folder_path);
+
NSWindowRef getMainAppWindow();
GLViewRef getGLView();
diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm
index 2e75d309ea..01feac7885 100644
--- a/indra/llwindow/llwindowmacosx-objc.mm
+++ b/indra/llwindow/llwindowmacosx-objc.mm
@@ -463,6 +463,13 @@ long showAlert(std::string text, std::string title, int type)
return ret;
}
+void openFolderWithFinder(const char *folder_path)
+{
+ @autoreleasepool {
+ NSString *folderPathString = [NSString stringWithUTF8String:folder_path];
+ [[NSWorkspace sharedWorkspace] openFile:folderPathString withApplication:@"Finder"];
+ }
+}
/*
GLViewRef getGLView()
{
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index 80001b14ee..e95ad4d970 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -221,14 +221,14 @@ bool callKeyDown(NSKeyEventRef event, unsigned short key, unsigned int mask, wch
{
//if (mask!=MASK_NONE)
{
- if((key == gKeyboard->inverseTranslateKey('Z')) && (character == 'y'))
- {
- key = gKeyboard->inverseTranslateKey('Y');
- }
- else if ((key == gKeyboard->inverseTranslateKey('Y')) && (character == 'z'))
- {
- key = gKeyboard->inverseTranslateKey('Z');
- }
+ if((key == gKeyboard->inverseTranslateKey('Z')) && (character == 'y'))
+ {
+ key = gKeyboard->inverseTranslateKey('Y');
+ }
+ else if ((key == gKeyboard->inverseTranslateKey('Y')) && (character == 'z'))
+ {
+ key = gKeyboard->inverseTranslateKey('Z');
+ }
}
mRawKeyEvent = event;
@@ -2556,6 +2556,11 @@ F32 LLWindowMacOSX::getSystemUISize()
return gHiDPISupport ? ::getDeviceUnitSize(mGLView) : LLWindow::getSystemUISize();
}
+void LLWindowMacOSX::openFolder(const std::string &path)
+{
+ openFolderWithFinder(path.c_str());
+}
+
#if LL_OS_DRAGDROP_ENABLED
/*
S16 LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow,
diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h
index f5b6441746..211ae872c6 100644
--- a/indra/llwindow/llwindowmacosx.h
+++ b/indra/llwindow/llwindowmacosx.h
@@ -113,6 +113,8 @@ public:
void spawnWebBrowser(const std::string& escaped_url, bool async) override;
F32 getSystemUISize() override;
+ void openFolder(const std::string &path) override;
+
bool getInputDevices(U32 device_type_filter,
std::function<bool(std::string&, LLSD&, void*)> osx_callback,
void* win_callback,
diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp
index 7433ad6bd2..89f0d152c6 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,12 +38,9 @@
#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"
@@ -57,6 +52,7 @@ extern "C" {
# include <unistd.h>
# include <sys/types.h>
# include <sys/wait.h>
+# include <stdio.h>
#endif // LL_LINUX
extern bool gDebugWindowProc;
@@ -97,100 +93,277 @@ 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)
{
- static bool done_gtk_diag = false;
- static bool gtk_is_good = false;
- static bool done_setlocale = false;
- static bool tried_gtk_init = false;
+ if (gWindowImplementation) {
+ return gWindowImplementation->mSDL_XWindowID;
+ }
+ return None;
+}
- if (!done_setlocale)
+//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
+{
+ std::array<Atom, 3> gSupportedAtoms;
+
+ 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();
+ }
+
+ int x11_clipboard_filter(void*, SDL_Event *evt)
+ {
+ 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;
}
- if (gtk_is_good && !done_gtk_diag)
+ bool grab_property(Display* display, Window window, Atom selection, Atom target)
{
- 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;
+ 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 );
- done_gtk_diag = true;
+ 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);
- return gtk_is_good;
+ maybe_lock_display();
+
+ XA_CLIPBOARD = XInternAtom(mSDL_Display, "CLIPBOARD", False);
+
+ gSupportedAtoms[0] = XInternAtom(mSDL_Display, "UTF8_STRING", False);
+ gSupportedAtoms[1] = XInternAtom(mSDL_Display, "COMPOUND_TEXT", False);
+ gSupportedAtoms[2] = XA_STRING;
+
+ // TARGETS atom
+ XA_TARGETS = XInternAtom(mSDL_Display, "TARGETS", False);
+
+ // SL_PASTE_BUFFER atom
+ PVT_PASTE_BUFFER = XInternAtom(mSDL_Display, "FS_PASTE_BUFFER", False);
+
+ maybe_unlock_display();
}
-#endif // LL_GTK
+bool LLWindowSDL::getSelectionText( Atom aSelection, Atom aType, LLWString &text )
+{
+ if( !mSDL_Display )
+ return false;
-#if LL_X11
-// static
-Window LLWindowSDL::get_SDL_XWindowID(void)
+ if( !grab_property(mSDL_Display, mSDL_XWindowID, aSelection,aType ) )
+ return false;
+
+ maybe_lock_display();
+
+ Atom type;
+ int format{};
+ unsigned long len{},remaining {};
+ unsigned char* data = nullptr;
+ int res = XGetWindowProperty(mSDL_Display, mSDL_XWindowID,
+ PVT_PASTE_BUFFER, 0, MAX_PASTE_BUFFER_SIZE, False,
+ AnyPropertyType, &type, &format, &len,
+ &remaining, &data);
+ if (data && len)
+ {
+ text = LLWString(
+ utf8str_to_wstring(reinterpret_cast< char const *>( data ) )
+ );
+ XFree(data);
+ }
+
+ maybe_unlock_display();
+ return res == Success;
+}
+
+bool LLWindowSDL::getSelectionText(Atom selection, LLWString& text)
{
- if (gWindowImplementation) {
- return gWindowImplementation->mSDL_XWindowID;
+ if (!mSDL_Display)
+ return false;
+
+ maybe_lock_display();
+
+ Window owner = XGetSelectionOwner(mSDL_Display, selection);
+ if (owner == None)
+ {
+ if (selection == XA_PRIMARY)
+ {
+ owner = DefaultRootWindow(mSDL_Display);
+ selection = XA_CUT_BUFFER0;
+ }
+ else
+ {
+ maybe_unlock_display();
+ return false;
+ }
}
- return None;
+
+ maybe_unlock_display();
+
+ for( Atom atom : gSupportedAtoms )
+ {
+ if(getSelectionText(selection, atom, text ) )
+ return true;
+ }
+
+ return false;
}
-//static
-Display* LLWindowSDL::get_SDL_Display(void)
+bool LLWindowSDL::setSelectionText(Atom selection, const LLWString& text)
{
- if (gWindowImplementation) {
- return gWindowImplementation->mSDL_Display;
+ maybe_lock_display();
+
+ if (selection == XA_PRIMARY)
+ {
+ std::string utf8 = wstring_to_utf8str(text);
+ XStoreBytes(mSDL_Display, utf8.c_str(), utf8.length() + 1);
+ mPrimaryClipboard = text;
}
- return NULL;
+ else
+ mSecondaryClipboard = text;
+
+ XSetSelectionOwner(mSDL_Display, selection, mSDL_XWindowID, CurrentTime);
+
+ auto owner = XGetSelectionOwner(mSDL_Display, selection);
+
+ maybe_unlock_display();
+
+ return owner == mSDL_XWindowID;
}
-#endif // LL_X11
+
+Display* LLWindowSDL::getSDLDisplay()
+{
+ if (gWindowImplementation)
+ return gWindowImplementation->mSDL_Display;
+ return nullptr;
+}
+
+#endif
LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
- const std::string& title, S32 x, S32 y, S32 width,
- S32 height, U32 flags,
- bool fullscreen, bool clearBg,
- bool disable_vsync, bool use_gl,
- bool ignore_pixel_depth, U32 fsaa_samples)
- : LLWindow(callbacks, fullscreen, flags),
- Lock_Display(NULL),
- Unlock_Display(NULL), mGamma(1.0f)
+ const std::string& title, S32 x, S32 y, S32 width,
+ S32 height, U32 flags,
+ bool fullscreen, bool clearBg,
+ bool enable_vsync, bool use_gl,
+ bool ignore_pixel_depth, U32 fsaa_samples)
+ : LLWindow(callbacks, fullscreen, flags),
+ Lock_Display(NULL),
+ Unlock_Display(NULL), mGamma(1.0f)
{
// Initialize the keyboard
gKeyboard = new LLKeyboardSDL();
@@ -199,6 +372,7 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
// Ignore use_gl for now, only used for drones on PC
mWindow = NULL;
+ mContext = {};
mNeedsResize = false;
mOverrideAspectRatio = 0.f;
mGrabbyKeyFlags = 0;
@@ -209,16 +383,9 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
#if LL_X11
mSDL_XWindowID = None;
- mSDL_Display = NULL;
+ mSDL_Display = nullptr;
#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;
@@ -228,7 +395,7 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
mWindowTitle = title;
// Create the GL context and set it up for windowed or fullscreen, as appropriate.
- if(createContext(x, y, width, height, 32, fullscreen, disable_vsync))
+ if(createContext(x, y, width, height, 32, fullscreen, enable_vsync))
{
gGLManager.initGL();
@@ -244,9 +411,9 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
#if LL_X11
mFlashing = false;
+ initialiseX11Clipboard();
#endif // LL_X11
- mKeyScanCode = 0;
mKeyVirtualKey = 0;
mKeyModifiers = KMOD_NONE;
}
@@ -258,10 +425,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 +515,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 +540,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 +550,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 +566,160 @@ static int x11_detect_VRAM_kb()
else
{
LL_INFOS() << "Could not open " << fname
- << " - skipped." << LL_ENDL;
+ << " - skipped." << LL_ENDL;
}
}
return rtn;
}
#endif // LL_X11
-bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, bool fullscreen, bool disable_vsync)
+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 enable_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);
+ mSDLFlags = sdlflags;
- // *FIX: try to toggle vsync here?
+ GLint redBits{8}, greenBits{8}, blueBits{8}, alphaBits{8};
- mFullscreen = fullscreen;
+ 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_DOUBLEBUFFER, 1);
@@ -497,80 +729,39 @@ 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;
-
- // 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;
+ mContext = SDL_GL_CreateContext( mWindow );
- 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))
+ if( mContext == 0 )
{
- // Mode search failed for some reason. Use the old-school default.
- width = 1024;
- height = 768;
+ LL_WARNS() << "Cannot create GL context " << SDL_GetError() << LL_ENDL;
+ setupFailure("GL Context creation error creation error", "Error", OSMB_OK);
+ return false;
}
+ // SDL_GL_SetSwapInterval(1);
+ mSurface = SDL_GetWindowSurface( mWindow );
+ }
- 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 (mWindow)
+ if( mFullscreen )
+ {
+ if (mSurface)
{
mFullscreen = true;
- mFullscreenWidth = mWindow->w;
- mFullscreenHeight = mWindow->h;
- mFullscreenBits = mWindow->format->BitsPerPixel;
+ mFullscreenWidth = mSurface->w;
+ mFullscreenHeight = mSurface->h;
+ mFullscreenBits = mSurface->format->BitsPerPixel;
mFullscreenRefresh = -1;
LL_INFOS() << "Running at " << mFullscreenWidth
- << "x" << mFullscreenHeight
- << "x" << mFullscreenBits
- << " @ " << mFullscreenRefresh
- << LL_ENDL;
+ << "x" << mFullscreenHeight
+ << "x" << mFullscreenBits
+ << " @ " << mFullscreenRefresh
+ << LL_ENDL;
}
else
{
@@ -584,33 +775,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.
@@ -625,7 +810,7 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b
// 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;
@@ -637,22 +822,20 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b
// 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
@@ -662,76 +845,53 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b
{
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
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;
-
// Don't need to get the current gamma, since there's a call that restores it to the system defaults.
return true;
}
// changing fullscreen resolution, or switching between windowed and fullscreen mode.
-bool LLWindowSDL::switchContext(bool fullscreen, const LLCoordScreen &size, bool disable_vsync, const LLCoordScreen * const posp)
+bool LLWindowSDL::switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp)
{
const bool needsRebuild = true; // Just nuke the context and start over.
bool result = true;
@@ -741,7 +901,7 @@ bool LLWindowSDL::switchContext(bool fullscreen, const LLCoordScreen &size, bool
if(needsRebuild)
{
destroyContext();
- result = createContext(0, 0, size.mX, size.mY, 0, fullscreen, disable_vsync);
+ result = createContext(0, 0, size.mX, size.mY, 0, fullscreen, enable_vsync);
if (result)
{
gGLManager.initGL();
@@ -761,6 +921,7 @@ void LLWindowSDL::destroyContext()
{
LL_INFOS() << "destroyContext begins" << LL_ENDL;
+ SDL_StopTextInput();
#if LL_X11
mSDL_Display = NULL;
mSDL_XWindowID = None;
@@ -894,11 +1055,11 @@ bool LLWindowSDL::getPosition(LLCoordScreen *position)
bool LLWindowSDL::getSize(LLCoordScreen *size)
{
- if (mWindow)
+ if (mSurface)
{
- size->mX = mWindow->w;
- size->mY = mWindow->h;
- return (true);
+ size->mX = mSurface->w;
+ size->mY = mSurface->h;
+ return (true);
}
return (false);
@@ -906,11 +1067,11 @@ bool LLWindowSDL::getSize(LLCoordScreen *size)
bool LLWindowSDL::getSize(LLCoordWindow *size)
{
- if (mWindow)
+ if (mSurface)
{
- size->mX = mWindow->w;
- size->mY = mWindow->h;
- return (true);
+ size->mX = mSurface->w;
+ size->mY = mSurface->h;
+ return (true);
}
return (false);
@@ -927,40 +1088,37 @@ bool LLWindowSDL::setPosition(const LLCoordScreen position)
return true;
}
-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 +1126,7 @@ void LLWindowSDL::swapBuffers()
{
if (mWindow)
{
- SDL_GL_SwapBuffers();
+ SDL_GL_SwapWindow( mWindow );
}
}
@@ -990,7 +1148,7 @@ F32 LLWindowSDL::getGamma()
bool LLWindowSDL::restoreGamma()
{
//CGDisplayRestoreColorSyncSettings();
- SDL_SetGamma(1.0f, 1.0f, 1.0f);
+ // SDL_SetGamma(1.0f, 1.0f, 1.0f);
return true;
}
@@ -999,7 +1157,7 @@ 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);
return true;
}
@@ -1048,7 +1206,7 @@ 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);
+ 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;
@@ -1073,18 +1231,6 @@ bool LLWindowSDL::getCursorPosition(LLCoordWindow *position)
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 +1292,7 @@ void LLWindowSDL::beforeDialog()
// it only works in X11
if (running_x11 && mWindow)
{
- SDL_WM_ToggleFullScreen(mWindow);
+ SDL_SetWindowFullscreen( mWindow, 0 );
}
}
}
@@ -1162,12 +1308,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 +1328,7 @@ void LLWindowSDL::afterDialog()
// in X11
if (running_x11 && mWindow)
{
- SDL_WM_ToggleFullScreen(mWindow);
+ SDL_SetWindowFullscreen( mWindow, 0 );
}
}
}
@@ -1224,143 +1364,56 @@ void LLWindowSDL::x11_set_urgent(bool urgent)
void LLWindowSDL::flashIcon(F32 seconds)
{
+ if (getMinimized())
+ {
#if !LL_X11
- LL_INFOS() << "Stub LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL;
+ LL_INFOS() << "Stub LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL;
#else
- LL_INFOS() << "X11 LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL;
+ LL_INFOS() << "X11 LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL;
- F32 remaining_time = mFlashTimer.getRemainingTimeF32();
- if (remaining_time < seconds)
- remaining_time = seconds;
- mFlashTimer.reset();
- mFlashTimer.setTimerExpirySec(remaining_time);
+ F32 remaining_time = mFlashTimer.getRemainingTimeF32();
+ if (remaining_time < seconds)
+ remaining_time = seconds;
+ mFlashTimer.reset();
+ mFlashTimer.setTimerExpirySec(remaining_time);
- x11_set_urgent(true);
- mFlashing = true;
+ x11_set_urgent(true);
+ mFlashing = true;
#endif // LL_X11
-}
-
-
-#if LL_GTK
-bool LLWindowSDL::isClipboardTextAvailable()
-{
- if (ll_try_gtk_init())
- {
- GtkClipboard * const clipboard =
- gtk_clipboard_get(GDK_NONE);
- return gtk_clipboard_wait_is_text_available(clipboard) ?
- true : false;
- }
- return false; // failure
-}
-
-bool LLWindowSDL::pasteTextFromClipboard(LLWString &text)
-{
- if (ll_try_gtk_init())
- {
- GtkClipboard * const clipboard =
- gtk_clipboard_get(GDK_NONE);
- gchar * const data = gtk_clipboard_wait_for_text(clipboard);
- if (data)
- {
- text = LLWString(utf8str_to_wstring(data));
- g_free(data);
- return true;
- }
- }
- return false; // failure
-}
-
-bool LLWindowSDL::copyTextToClipboard(const LLWString &text)
-{
- if (ll_try_gtk_init())
- {
- const std::string utf8 = wstring_to_utf8str(text);
- GtkClipboard * const clipboard =
- gtk_clipboard_get(GDK_NONE);
- gtk_clipboard_set_text(clipboard, utf8.c_str(), utf8.length());
- return true;
- }
- return false; // failure
-}
-
-
-bool LLWindowSDL::isPrimaryTextAvailable()
-{
- if (ll_try_gtk_init())
- {
- GtkClipboard * const clipboard =
- gtk_clipboard_get(GDK_SELECTION_PRIMARY);
- return gtk_clipboard_wait_is_text_available(clipboard) ?
- true : false;
- }
- return false; // failure
-}
-
-bool LLWindowSDL::pasteTextFromPrimary(LLWString &text)
-{
- if (ll_try_gtk_init())
- {
- GtkClipboard * const clipboard =
- gtk_clipboard_get(GDK_SELECTION_PRIMARY);
- gchar * const data = gtk_clipboard_wait_for_text(clipboard);
- if (data)
- {
- text = LLWString(utf8str_to_wstring(data));
- g_free(data);
- return true;
- }
- }
- return false; // failure
-}
-
-bool LLWindowSDL::copyTextToPrimary(const LLWString &text)
-{
- if (ll_try_gtk_init())
- {
- const std::string utf8 = wstring_to_utf8str(text);
- GtkClipboard * const clipboard =
- gtk_clipboard_get(GDK_SELECTION_PRIMARY);
- gtk_clipboard_set_text(clipboard, utf8.c_str(), utf8.length());
- return true;
}
- return false; // failure
}
-#else
-
bool LLWindowSDL::isClipboardTextAvailable()
{
- return false; // unsupported
+ return mSDL_Display && XGetSelectionOwner(mSDL_Display, XA_CLIPBOARD) != None;
}
bool LLWindowSDL::pasteTextFromClipboard(LLWString &dst)
{
- return false; // unsupported
+ return getSelectionText(XA_CLIPBOARD, dst);
}
bool LLWindowSDL::copyTextToClipboard(const LLWString &s)
{
- return false; // unsupported
+ return setSelectionText(XA_CLIPBOARD, s);
}
bool LLWindowSDL::isPrimaryTextAvailable()
{
- return false; // unsupported
+ LLWString text;
+ return getSelectionText(XA_PRIMARY, text) && !text.empty();
}
bool LLWindowSDL::pasteTextFromPrimary(LLWString &dst)
{
- return false; // unsupported
+ return getSelectionText(XA_PRIMARY, dst);
}
bool LLWindowSDL::copyTextToPrimary(const LLWString &s)
{
- return false; // unsupported
+ return setSelectionText(XA_PRIMARY, s);
}
-#endif // LL_GTK
-
LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_resolutions)
{
if (!mSupportedResolutions)
@@ -1368,33 +1421,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 +1460,7 @@ bool LLWindowSDL::convertCoords(LLCoordGL from, LLCoordWindow *to)
return false;
to->mX = from.mX;
- to->mY = mWindow->h - from.mY - 1;
+ to->mY = mSurface->h - from.mY - 1;
return true;
}
@@ -1421,7 +1471,7 @@ bool LLWindowSDL::convertCoords(LLCoordWindow from, LLCoordGL* to)
return false;
to->mX = from.mX;
- to->mY = mWindow->h - from.mY - 1;
+ to->mY = mSurface->h - from.mY - 1;
return true;
}
@@ -1482,13 +1532,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 +1547,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 +1564,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 +1612,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 +1719,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 +1734,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,6 +1767,11 @@ 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);
@@ -1753,33 +1782,68 @@ void LLWindowSDL::gatherInput()
break;
}
+ case SDL_TEXTINPUT:
+ {
+ auto string = utf8str_to_utf16str( event.text.text );
+ mKeyModifiers = gKeyboard->currentMask( false );
+ mInputType = "textinput";
+ for( auto key: string )
+ {
+ mKeyVirtualKey = key;
+
+ if( (MASK_CONTROL|MASK_ALT)&mKeyModifiers )
+ gKeyboard->handleKeyDown(mKeyVirtualKey, mKeyModifiers );
+ else
+ handleUnicodeUTF16( key, mKeyModifiers );
+ }
+ break;
+ }
+
case SDL_KEYDOWN:
- 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 +1851,7 @@ void LLWindowSDL::gatherInput()
LLCoordWindow winCoord(event.button.x, event.button.y);
LLCoordGL openGlCoord;
convertCoords(winCoord, &openGlCoord);
- MASK mask = gKeyboard->currentMask(true);
+ MASK mask = gKeyboard->currentMask(true);
if (event.button.button == SDL_BUTTON_LEFT) // SDL doesn't manage double clicking...
{
@@ -1799,7 +1863,7 @@ void LLWindowSDL::gatherInput()
if (++leftClick >= 2)
{
leftClick = 0;
- isDoubleClick = true;
+ isDoubleClick = true;
}
}
lastLeftDown = now;
@@ -1830,7 +1894,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 +1914,69 @@ void LLWindowSDL::gatherInput()
LLCoordWindow winCoord(event.button.x, event.button.y);
LLCoordGL openGlCoord;
convertCoords(winCoord, &openGlCoord);
- MASK mask = gKeyboard->currentMask(true);
+ 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);
+ mSurface = SDL_GetWindowSurface( mWindow );
- // *FIX: I'm not sure this is necessary!
- mWindow = SDL_SetVideoMode(width, height, 32, mSDLFlags);
- if (!mWindow)
- {
- // *FIX: More informative dialog?
- LL_INFOS() << "Could not recreate context after resize! Quitting..." << LL_ENDL;
- if(mCallbacks->handleCloseRequest(this))
- {
- // Get the app to initiate cleanup.
- mCallbacks->handleQuit(this);
- // The app is responsible for calling destroyWindow when done with GL
- }
- break;
- }
+ // *FIX: I'm not sure this is necessary!
+ // <FS:ND> I think is is not
+ // SDL_SetWindowSize(mWindow, width, height);
+ //
- mCallbacks->handleResize(this, width, height);
- break;
- }
- case SDL_ACTIVEEVENT:
- if (event.active.state & SDL_APPINPUTFOCUS)
+ mCallbacks->handleResize(this, width, height);
+ }
+ else if( event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED ) // <FS:ND> What about SDL_WINDOWEVENT_ENTER (mouse focus)
{
- // 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;
+ // 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)
+ 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 )
{
- // Change in iconification/minimization state.
- if ((!event.active.gain) != mIsMinimized)
- {
- mIsMinimized = (!event.active.gain);
+ mIsMinimized = (event.window.event == SDL_WINDOWEVENT_MINIMIZED);
- 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->handleActivate(this, !mIsMinimized);
+ LL_INFOS() << "SDL deiconification state switched to " << mIsMinimized << LL_ENDL;
}
- break;
+ break;
+ }
case SDL_QUIT:
if(mCallbacks->handleCloseRequest(this))
{
@@ -1938,9 +1985,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 +2015,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 +2044,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 +2254,6 @@ void LLWindowSDL::hideCursorUntilMouseMove()
}
}
-
-
//
// LLSplashScreenSDL - I don't think we'll bother to implement this; it's
// fairly obsolete at this point.
@@ -2233,133 +2278,51 @@ 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();
- return rtn;
+ int btn{0};
+ if( 0 == SDL_ShowMessageBox( &oData, &btn ) )
+ return btn;
+ return OSBTN_CANCEL;
}
-static void color_changed_callback(GtkWidget *widget,
- gpointer user_data)
+bool LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b)
{
- GtkColorSelection *colorsel = GTK_COLOR_SELECTION(widget);
- GdkColor *colorp = (GdkColor*)user_data;
-
- gtk_color_selection_get_current_color(colorsel, colorp);
+ return (false);
}
-
/*
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 +2340,14 @@ 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
-#if LL_LINUX
+#if LL_LINUX || LL_SOLARIS
// 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 +2359,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.
@@ -2549,31 +2450,13 @@ void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async)
LL_INFOS() << "spawn_web_browser returning." << LL_ENDL;
}
+void LLWindowSDL::openFile(const std::string& file_name)
+{
+ spawnWebBrowser("file://"+file_name,true);
+}
void *LLWindowSDL::getPlatformWindow()
{
-#if LL_GTK && LL_LLMOZLIB_ENABLED
- if (LLWindowSDL::ll_try_gtk_init())
- {
- maybe_lock_display();
-
- GtkWidget *owin = gtk_window_new(GTK_WINDOW_POPUP);
- // Why a layout widget? A MozContainer would be ideal, but
- // it involves exposing Mozilla headers to mozlib-using apps.
- // A layout widget with a GtkWindow parent has the desired
- // properties of being plain GTK, having a window, and being
- // derived from a GtkContainer.
- GtkWidget *rtnw = gtk_layout_new(NULL, NULL);
- gtk_container_add(GTK_CONTAINER(owin), rtnw);
- gtk_widget_realize(rtnw);
- GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(rtnw), GTK_NO_WINDOW);
-
- maybe_unlock_display();
-
- return rtnw;
- }
-#endif // LL_GTK && LL_LLMOZLIB_ENABLED
- // Unixoid mozilla really needs GTK.
return NULL;
}
@@ -2634,10 +2517,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 +2538,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 +2552,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 +2577,54 @@ 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)
+{
+}
+
+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..10769bb3ba 100644
--- a/indra/llwindow/llwindowsdl.h
+++ b/indra/llwindow/llwindowsdl.h
@@ -24,20 +24,20 @@
* $/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"
+#include "SDL2/SDL.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 +46,139 @@
#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 enable_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;
- /*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions);
- /*virtual*/ F32 getNativeAspectRatio();
- /*virtual*/ F32 getPixelAspectRatio();
- /*virtual*/ void setNativeAspectRatio(F32 ratio) { mOverrideAspectRatio = ratio; }
+ bool convertCoords(LLCoordGL from, LLCoordScreen *to) override;
- /*virtual*/ void beforeDialog();
- /*virtual*/ void afterDialog();
+ LLWindowResolution *getSupportedResolutions(S32 &num_resolutions) override;
- /*virtual*/ bool dialogColorPicker(F32 *r, F32 *g, F32 *b);
+ F32 getNativeAspectRatio() override;
- /*virtual*/ void *getPlatformWindow();
- /*virtual*/ void bringToFront();
+ F32 getPixelAspectRatio() override;
- /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async);
+ void setNativeAspectRatio(F32 ratio) override { mOverrideAspectRatio = ratio; }
+
+ 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 +188,52 @@ 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
+ 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 enable_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 initCursors();
- void quitCursors();
- void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size);
+ void quitCursors();
+
+ void moveWindow(const LLCoordScreen &position, const LLCoordScreen &size);
// Changes display resolution. Returns true if successful
- bool setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
+ bool setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
// Go back to last fullscreen display resolution.
- bool setFullscreenResolution();
+ bool setFullscreenResolution();
- bool shouldPostQuit() { return mPostQuit; }
+ bool shouldPostQuit() { return mPostQuit; }
protected:
//
@@ -173,47 +241,85 @@ 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);
+ bool createContext(int x, int y, int width, int height, int bits, bool fullscreen, bool enable_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_Surface *mSurface;
+ 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 */
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 tryFindFullscreenSize(int &aWidth, int &aHeight);
+
+ void initialiseX11Clipboard();
+
+ bool getSelectionText(Atom selection, LLWString &text);
+
+ bool getSelectionText(Atom selection, Atom type, LLWString &text);
+
+ bool setSelectionText(Atom selection, const LLWString &text);
+
+#endif
+ LLWString mPrimaryClipboard;
+ LLWString mSecondaryClipboard;
+};
class LLSplashScreenSDL : public LLSplashScreen
{
@@ -221,9 +327,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 0b6ee541c0..b19fa13b41 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
@@ -1630,9 +1619,11 @@ const S32 max_format = (S32)num_formats - 1;
}
else
{
- LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBVideoDrvErr"));
- // mWindowHandle is 0, going to crash either way
- LL_ERRS("Window") << "No wgl_ARB_pixel_format extension!" << LL_ENDL;
+ LL_WARNS("Window") << "No wgl_ARB_pixel_format extension!" << LL_ENDL;
+ // cannot proceed without wgl_ARB_pixel_format extension, shutdown same as any other gGLManager.initGL() failure
+ OSMessageBox(mCallbacks->translateString("MBVideoDrvErr"), mCallbacks->translateString("MBError"), OSMB_OK);
+ close();
+ return false;
}
// Verify what pixel format we actually received.
@@ -3742,6 +3733,23 @@ S32 OSMessageBoxWin32(const std::string& text, const std::string& caption, U32 t
return retval;
}
+void shell_open(const std::string &file, bool async)
+{
+ std::wstring url_utf16 = ll_convert(file);
+
+ // let the OS decide what to use to open the URL
+ SHELLEXECUTEINFO sei = {sizeof(sei)};
+ // NOTE: this assumes that SL will stick around long enough to complete the DDE message exchange
+ // necessary for ShellExecuteEx to complete
+ if (async)
+ {
+ sei.fMask = SEE_MASK_ASYNCOK;
+ }
+ sei.nShow = SW_SHOWNORMAL;
+ sei.lpVerb = L"open";
+ sei.lpFile = url_utf16.c_str();
+ ShellExecuteEx(&sei);
+}
void LLWindowWin32::spawnWebBrowser(const std::string& escaped_url, bool async)
{
@@ -3767,22 +3775,12 @@ void LLWindowWin32::spawnWebBrowser(const std::string& escaped_url, bool async)
// replaced ShellExecute code with ShellExecuteEx since ShellExecute doesn't work
// reliablly on Vista.
- // this is madness.. no, this is..
- LLWString url_wstring = utf8str_to_wstring( escaped_url );
- llutf16string url_utf16 = wstring_to_utf16str( url_wstring );
+ shell_open(escaped_url, async);
+}
- // let the OS decide what to use to open the URL
- SHELLEXECUTEINFO sei = { sizeof( sei ) };
- // NOTE: this assumes that SL will stick around long enough to complete the DDE message exchange
- // necessary for ShellExecuteEx to complete
- if (async)
- {
- sei.fMask = SEE_MASK_ASYNCOK;
- }
- sei.nShow = SW_SHOWNORMAL;
- sei.lpVerb = L"open";
- sei.lpFile = url_utf16.c_str();
- ShellExecuteEx( &sei );
+void LLWindowWin32::openFolder(const std::string &path)
+{
+ shell_open(path, false);
}
/*
diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h
index 36e89e4586..e38cfe7ebc 100644
--- a/indra/llwindow/llwindowwin32.h
+++ b/indra/llwindow/llwindowwin32.h
@@ -120,6 +120,8 @@ public:
/*virtual*/ void interruptLanguageTextInput();
/*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async);
+ void openFolder(const std::string &path) override;
+
/*virtual*/ F32 getSystemUISize();
LLWindowCallbacks::DragNDropResult completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url );