summaryrefslogtreecommitdiff
path: root/indra/llwindow
diff options
context:
space:
mode:
authorJonathan "Geenz" Goodman <geenz@geenzo.com>2026-08-11 21:39:19 -0400
committerJonathan "Geenz" Goodman <geenz@geenzo.com>2026-08-11 21:39:19 -0400
commit8cabc33e960ca93fdc1a32c77cf611269d95d51b (patch)
tree931fcecac10bf73214efa07cc3d704ba2bd01272 /indra/llwindow
parent9b7ab49575b54523128952af6686d17eb6696725 (diff)
parentd045f9aa32789a35628aced166145c182751acbf (diff)
Merge remote-tracking branch 'origin/develop-linux' into geenz/linux-to-develop
Diffstat (limited to 'indra/llwindow')
-rw-r--r--indra/llwindow/CMakeLists.txt112
-rw-r--r--indra/llwindow/llkeyboard.cpp18
-rw-r--r--indra/llwindow/llkeyboard.h26
-rw-r--r--indra/llwindow/llkeyboardheadless.cpp21
-rw-r--r--indra/llwindow/llkeyboardheadless.h16
-rw-r--r--indra/llwindow/llkeyboardmacosx.cpp13
-rw-r--r--indra/llwindow/llkeyboardmacosx.h16
-rw-r--r--indra/llwindow/llkeyboardsdl.cpp446
-rw-r--r--indra/llwindow/llkeyboardsdl.h27
-rw-r--r--indra/llwindow/llkeyboardwin32.cpp4
-rw-r--r--indra/llwindow/llkeyboardwin32.h17
-rw-r--r--indra/llwindow/llmousehandler.cpp2
-rw-r--r--indra/llwindow/llsdl.cpp149
-rw-r--r--indra/llwindow/llsdl.h34
-rw-r--r--indra/llwindow/llwindow.cpp52
-rw-r--r--indra/llwindow/llwindow.h5
-rw-r--r--indra/llwindow/llwindowheadless.h2
-rw-r--r--indra/llwindow/llwindowmacosx.h5
-rw-r--r--indra/llwindow/llwindowmesaheadless.h121
-rw-r--r--indra/llwindow/llwindowsdl.cpp2636
-rw-r--r--indra/llwindow/llwindowsdl.h313
-rw-r--r--indra/llwindow/llwindowwin32.cpp17
-rw-r--r--indra/llwindow/llwindowwin32.h3
23 files changed, 2021 insertions, 2034 deletions
diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt
index 3dae2d1067..5f8a9a64eb 100644
--- a/indra/llwindow/CMakeLists.txt
+++ b/indra/llwindow/CMakeLists.txt
@@ -12,12 +12,14 @@ project(llwindow)
include(00-Common)
include(DragDrop)
+include(Linking)
include(LLCommon)
include(LLImage)
include(LLWindow)
include(UI)
include(ViewerMiscLibs)
include(GLM)
+include(SDL3)
set(llwindow_SOURCE_FILES
llcursortypes.cpp
@@ -66,11 +68,13 @@ set(macosx_HEADER_FILES
)
set(linux_SOURCE_FILES
+ llsdl.cpp
llkeyboardsdl.cpp
llwindowsdl.cpp
)
set(linux_HEADER_FILES
+ llsdl.h
llkeyboardsdl.h
llwindowsdl.h
)
@@ -99,28 +103,16 @@ set(llwindow_LINK_LIBRARIES
ll::glm
ll::glext
ll::uilibraries
- ll::SDL
)
-# Libraries on which this library depends, needed for Linux builds
-# Sort by high-level to low-level
-if (LINUX)
+
+if (USE_SDL_WINDOW)
list(APPEND viewer_SOURCE_FILES ${linux_SOURCE_FILES})
list(APPEND viewer_HEADER_FILES ${linux_HEADER_FILES})
- if (BUILD_HEADLESS)
- set(llwindowheadless_LINK_LIBRARIES
- ${LLCOMMON_LIBRARIES}
- ${LLIMAGE_LIBRARIES}
- ${LLMATH_LIBRARIES}
- ${LLRENDER_HEADLESS_LIBRARIES}
- ${LLFILESYSTEM_LIBRARIES}
- ${LLWINDOW_HEADLESS_LIBRARIES}
- ${LLXML_LIBRARIES}
- fontconfig # For FCInit and other FC* functions.
- )
- endif (BUILD_HEADLESS)
-
-endif (LINUX)
+ list(APPEND llwindow_LINK_LIBRARIES
+ ll::SDL3
+ )
+endif ()
if (DARWIN)
list(APPEND llwindow_SOURCE_FILES ${macosx_SOURCE_FILES})
@@ -133,6 +125,13 @@ if (DARWIN)
PROPERTIES
COMPILE_FLAGS "-fpascal-strings"
)
+
+ set_source_files_properties(
+ llwindowmacosx-objc.mm
+ llopenglview-objc.mm
+ PROPERTIES
+ SKIP_PRECOMPILE_HEADERS TRUE
+ )
endif (DARWIN)
@@ -147,32 +146,55 @@ if (WINDOWS)
)
endif (WINDOWS)
-if (SOLARIS)
- list(APPEND llwindow_SOURCE_FILES
- llwindowsolaris.cpp
- )
- list(APPEND llwindow_HEADER_FILES
- llwindowsolaris.h
- )
-endif (SOLARIS)
if (BUILD_HEADLESS)
set(llwindowheadless_SOURCE_FILES
- llwindowmesaheadless.cpp
- llmousehandler.cpp
- )
+ llcursortypes.cpp
+ llkeyboard.cpp
+ llkeyboardheadless.cpp
+ llwindowheadless.cpp
+ llwindowcallbacks.cpp
+ llwindow.cpp
+ llwindowmesaheadless.cpp
+ llmousehandler.cpp
+ )
+
set(llwindowheadless_HEADER_FILES
- llwindowmesaheadless.h
- llmousehandler.h
- )
+ llcursortypes.h
+ llkeyboard.h
+ llkeyboardheadless.h
+ llwindowheadless.h
+ llwindowcallbacks.h
+ llwindowmesaheadless.h
+ llmousehandler.h
+ )
+
add_library (llwindowheadless
- ${llwindow_SOURCE_FILES}
${llwindowheadless_SOURCE_FILES}
+ ${llwindowheadless_HEADER_FILES}
)
- set_property(TARGET llwindowheadless
- PROPERTY COMPILE_DEFINITIONS LL_MESA=1 LL_MESA_HEADLESS=1
- )
- target_link_libraries (llwindowheadless ${llwindowheadless_LINK_LIBRARIES} dl)
+
+ target_compile_definitions( llwindowheadless PUBLIC LL_MESA_HEADLESS=1 )
+
+ target_link_libraries (llwindowheadless
+ llcommon
+ llimage
+ llmath
+ llrenderheadless
+ llfilesystem
+ llxml
+ ll::glm
+ ll::glext
+ ll::zlib-ng
+ PkgConfig::OSMESA
+ fontconfig
+ dl
+ )
+ target_include_directories(llwindowheadless INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
+
+ if (USE_PRECOMPILED_HEADERS)
+ target_precompile_headers(llwindowheadless REUSE_FROM llprecompiled)
+ endif ()
endif (BUILD_HEADLESS)
if (llwindow_HEADER_FILES)
@@ -224,14 +246,16 @@ elseif (LINUX)
)
endif()
-if (SDL_FOUND)
- set_property(TARGET llwindow
- PROPERTY COMPILE_DEFINITIONS LL_SDL=1
- )
-endif (SDL_FOUND)
+target_link_libraries (llwindow ${llwindow_LINK_LIBRARIES})
+target_include_directories(llwindow INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
+
+if (USE_SDL_WINDOW)
+ target_compile_definitions( llwindow PUBLIC LL_SDL_WINDOW=1 )
+endif()
- target_link_libraries (llwindow ${llwindow_LINK_LIBRARIES})
- target_include_directories(llwindow INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
+if (USE_PRECOMPILED_HEADERS)
+ target_precompile_headers(llwindow REUSE_FROM llprecompiled)
+endif ()
if (DARWIN)
target_link_libraries(llwindow ${CARBON_LIBRARY})
diff --git a/indra/llwindow/llkeyboard.cpp b/indra/llwindow/llkeyboard.cpp
index b642736d8e..df69b1390c 100644
--- a/indra/llwindow/llkeyboard.cpp
+++ b/indra/llwindow/llkeyboard.cpp
@@ -43,7 +43,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
//
@@ -164,6 +163,7 @@ void LLKeyboard::resetKeyDownAndHandle()
mCallbacks->handleTranslatedKeyUp(i, mask);
}
}
+ mCurTranslatedKey = KEY_NONE;
}
// BUG this has to be called when an OS dialog is shown, otherwise modifier key state
@@ -197,12 +197,10 @@ 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;
@@ -216,11 +214,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;
@@ -232,7 +228,7 @@ U16 LLKeyboard::inverseTranslateKey(const KEY translated_key)
}
-bool LLKeyboard::handleTranslatedKeyDown(KEY translated_key, U32 translated_mask)
+bool LLKeyboard::handleTranslatedKeyDown(KEY translated_key, MASK translated_mask)
{
bool handled = false;
bool repeated = false;
@@ -260,7 +256,7 @@ bool LLKeyboard::handleTranslatedKeyDown(KEY translated_key, U32 translated_mask
}
-bool LLKeyboard::handleTranslatedKeyUp(KEY translated_key, U32 translated_mask)
+bool LLKeyboard::handleTranslatedKeyUp(KEY translated_key, MASK translated_mask)
{
bool handled = false;
if( mKeyLevel[translated_key] )
diff --git a/indra/llwindow/llkeyboard.h b/indra/llwindow/llkeyboard.h
index 067445d24c..a092787cef 100644
--- a/indra/llwindow/llkeyboard.h
+++ b/indra/llwindow/llkeyboard.h
@@ -54,6 +54,13 @@ class LLWindowCallbacks;
class LLKeyboard
{
public:
+#ifdef LL_SDL_WINDOW
+ // linux relies on SDL which uses U32 for its native key type
+ typedef U32 NATIVE_KEY_TYPE;
+#else
+ // on non-linux platforms we can get by with a smaller native key type
+ typedef U16 NATIVE_KEY_TYPE;
+#endif
LLKeyboard();
virtual ~LLKeyboard();
@@ -66,16 +73,15 @@ public:
bool getKeyDown(const KEY key) { return mKeyLevel[key]; }
bool getKeyRepeated(const KEY key) { return mKeyRepeated[key]; }
- bool translateKey(const U16 os_key, KEY *translated_key);
- U16 inverseTranslateKey(const KEY translated_key);
- bool handleTranslatedKeyUp(KEY translated_key, U32 translated_mask); // Translated into "Linden" keycodes
- bool handleTranslatedKeyDown(KEY translated_key, U32 translated_mask); // Translated into "Linden" keycodes
-
+ bool translateKey(const NATIVE_KEY_TYPE os_key, KEY *translated_key);
+ NATIVE_KEY_TYPE inverseTranslateKey(const KEY translated_key);
+ bool handleTranslatedKeyUp(KEY translated_key, MASK translated_mask); // Translated into "Linden" keycodes
+ bool handleTranslatedKeyDown(KEY translated_key, MASK 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
+#if LL_DARWIN && !LL_SDL_WINDOW
// We only actually use this for macOS.
virtual void handleModifier(MASK mask) = 0;
#endif // LL_DARWIN
@@ -110,8 +116,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..50d03aaf20 100644
--- a/indra/llwindow/llkeyboardheadless.cpp
+++ b/indra/llwindow/llkeyboardheadless.cpp
@@ -31,21 +31,23 @@
LLKeyboardHeadless::LLKeyboardHeadless()
{ }
-void LLKeyboardHeadless::resetMaskKeys()
-{ }
-
-
-bool LLKeyboardHeadless::handleKeyDown(const U16 key, const U32 mask)
-{ return false; }
+bool LLKeyboardHeadless::handleKeyUp(const LLKeyboard::NATIVE_KEY_TYPE key, MASK mask)
+{
+ return false;
+}
+bool LLKeyboardHeadless::handleKeyDown(const LLKeyboard::NATIVE_KEY_TYPE key, MASK mask)
+{
+ return false;
+}
-bool LLKeyboardHeadless::handleKeyUp(const U16 key, const U32 mask)
-{ return false; }
+void LLKeyboardHeadless::resetMaskKeys()
+{ }
MASK LLKeyboardHeadless::currentMask(bool for_mouse_event)
{ return MASK_NONE; }
-#ifdef LL_DARWIN
+#if LL_DARWIN && !LL_SDL_WINDOW
void LLKeyboardHeadless::handleModifier(MASK mask)
{
@@ -65,6 +67,7 @@ void LLKeyboardHeadless::scanKeyboard()
mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key], mKeyLevel[key]);
}
}
+ mCurScanKey = KEY_NONE;
// Reset edges for next frame
for (S32 key = 0; key < KEY_COUNT; key++)
diff --git a/indra/llwindow/llkeyboardheadless.h b/indra/llwindow/llkeyboardheadless.h
index 2528f0e3f1..364fb03fe7 100644
--- a/indra/llwindow/llkeyboardheadless.h
+++ b/indra/llwindow/llkeyboardheadless.h
@@ -33,15 +33,15 @@ class LLKeyboardHeadless : public LLKeyboard
{
public:
LLKeyboardHeadless();
- /*virtual*/ ~LLKeyboardHeadless() {};
+ ~LLKeyboardHeadless() = default;
- /*virtual*/ bool handleKeyUp(const U16 key, MASK mask);
- /*virtual*/ bool handleKeyDown(const U16 key, MASK mask);
- /*virtual*/ void resetMaskKeys();
- /*virtual*/ MASK currentMask(bool for_mouse_event);
- /*virtual*/ void scanKeyboard();
-#ifdef LL_DARWIN
- /*virtual*/ void handleModifier(MASK mask);
+ bool handleKeyUp(const LLKeyboard::NATIVE_KEY_TYPE key, MASK mask) override;
+ bool handleKeyDown(const LLKeyboard::NATIVE_KEY_TYPE key, MASK mask) override;
+ void resetMaskKeys() override;
+ MASK currentMask(bool for_mouse_event) override;
+ void scanKeyboard() override;
+#if LL_DARWIN && !LL_SDL_WINDOW
+ void handleModifier(MASK mask) override;
#endif
};
diff --git a/indra/llwindow/llkeyboardmacosx.cpp b/indra/llwindow/llkeyboardmacosx.cpp
index 89ff7c6d3f..1a403e5d94 100644
--- a/indra/llwindow/llkeyboardmacosx.cpp
+++ b/indra/llwindow/llkeyboardmacosx.cpp
@@ -162,7 +162,7 @@ LLKeyboardMacOSX::LLKeyboardMacOSX()
void LLKeyboardMacOSX::resetMaskKeys()
{
- U32 mask = getModifiers();
+ MASK mask = getModifiers();
// 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.
@@ -187,7 +187,7 @@ void LLKeyboardMacOSX::resetMaskKeys()
}
/*
-static bool translateKeyMac(const U16 key, const U32 mask, KEY &outKey, U32 &outMask)
+static bool translateKeyMac(const U16 key, const MASK mask, KEY &outKey, U32 &outMask)
{
// Translate the virtual keycode into the keycodes the keyboard system expects.
U16 virtualKey = (mask >> 24) & 0x0000007F;
@@ -203,7 +203,7 @@ void LLKeyboardMacOSX::handleModifier(MASK mask)
updateModifiers(mask);
}
-MASK LLKeyboardMacOSX::updateModifiers(const U32 mask)
+MASK LLKeyboardMacOSX::updateModifiers(const MASK mask)
{
// translate the mask
MASK out_mask = 0;
@@ -226,7 +226,7 @@ MASK LLKeyboardMacOSX::updateModifiers(const U32 mask)
return out_mask;
}
-bool LLKeyboardMacOSX::handleKeyDown(const U16 key, const U32 mask)
+bool LLKeyboardMacOSX::handleKeyDown(const U16 key, MASK mask)
{
KEY translated_key = 0;
U32 translated_mask = 0;
@@ -243,7 +243,7 @@ bool LLKeyboardMacOSX::handleKeyDown(const U16 key, const U32 mask)
}
-bool LLKeyboardMacOSX::handleKeyUp(const U16 key, const U32 mask)
+bool LLKeyboardMacOSX::handleKeyUp(const U16 key, MASK mask)
{
KEY translated_key = 0;
U32 translated_mask = 0;
@@ -262,7 +262,7 @@ bool LLKeyboardMacOSX::handleKeyUp(const U16 key, const U32 mask)
MASK LLKeyboardMacOSX::currentMask(bool for_mouse_event)
{
MASK result = MASK_NONE;
- U32 mask = getModifiers();
+ MASK mask = getModifiers();
if (mask & MAC_SHIFT_KEY) result |= MASK_SHIFT;
if (mask & MAC_CTRL_KEY) result |= MASK_CONTROL;
@@ -291,6 +291,7 @@ void LLKeyboardMacOSX::scanKeyboard()
mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key], mKeyLevel[key]);
}
}
+ mCurScanKey = KEY_NONE;
// Reset edges for next frame
for (key = 0; key < KEY_COUNT; key++)
diff --git a/indra/llwindow/llkeyboardmacosx.h b/indra/llwindow/llkeyboardmacosx.h
index 92ab5c9a85..c824e7b713 100644
--- a/indra/llwindow/llkeyboardmacosx.h
+++ b/indra/llwindow/llkeyboardmacosx.h
@@ -42,17 +42,17 @@ class LLKeyboardMacOSX : public LLKeyboard
{
public:
LLKeyboardMacOSX();
- /*virtual*/ ~LLKeyboardMacOSX() {};
+ ~LLKeyboardMacOSX() = default;
- /*virtual*/ bool handleKeyUp(const U16 key, MASK mask);
- /*virtual*/ bool handleKeyDown(const U16 key, MASK mask);
- /*virtual*/ void resetMaskKeys();
- /*virtual*/ MASK currentMask(bool for_mouse_event);
- /*virtual*/ void scanKeyboard();
- /*virtual*/ void handleModifier(MASK mask);
+ bool handleKeyUp(const NATIVE_KEY_TYPE key, MASK mask) override;
+ bool handleKeyDown(const NATIVE_KEY_TYPE key, MASK mask) override;
+ void resetMaskKeys() override;
+ MASK currentMask(bool for_mouse_event) override;
+ void scanKeyboard() override;
+ void handleModifier(MASK mask) override;
protected:
- MASK updateModifiers(const U32 mask);
+ MASK updateModifiers(const MASK mask);
void setModifierKeyLevel( KEY key, bool new_state );
bool translateNumpadKey( const U16 os_key, KEY *translated_key );
U16 inverseTranslateNumpadKey(const KEY translated_key);
diff --git a/indra/llwindow/llkeyboardsdl.cpp b/indra/llwindow/llkeyboardsdl.cpp
index 97198f0cc0..e4d096e2e9 100644
--- a/indra/llwindow/llkeyboardsdl.cpp
+++ b/indra/llwindow/llkeyboardsdl.cpp
@@ -24,12 +24,11 @@
* $/LicenseInfo$
*/
-#if LL_SDL
-
#include "linden_common.h"
#include "llkeyboardsdl.h"
#include "llwindowcallbacks.h"
-#include "SDL/SDL.h"
+
+#include "SDL3/SDL_keycode.h"
LLKeyboardSDL::LLKeyboardSDL()
{
@@ -40,7 +39,7 @@ LLKeyboardSDL::LLKeyboardSDL()
// Virtual key mappings from SDL_keysym.h ...
// SDL maps the letter keys to the ASCII you'd expect, but it's lowercase...
- U16 cur_char;
+ LLKeyboard::NATIVE_KEY_TYPE cur_char;
for (cur_char = 'A'; cur_char <= 'Z'; cur_char++)
{
mTranslateKeyMap[cur_char] = cur_char;
@@ -74,7 +73,6 @@ LLKeyboardSDL::LLKeyboardSDL()
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;
@@ -115,36 +113,35 @@ LLKeyboardSDL::LLKeyboardSDL()
mTranslateKeyMap[SDLK_COMMA] = ',';
mTranslateKeyMap[SDLK_MINUS] = '-';
mTranslateKeyMap[SDLK_PERIOD] = '.';
- mTranslateKeyMap[SDLK_BACKQUOTE] = '`';
+ mTranslateKeyMap[SDLK_GRAVE] = '`';
mTranslateKeyMap[SDLK_SLASH] = KEY_DIVIDE;
mTranslateKeyMap[SDLK_SEMICOLON] = ';';
mTranslateKeyMap[SDLK_LEFTBRACKET] = '[';
mTranslateKeyMap[SDLK_BACKSLASH] = '\\';
mTranslateKeyMap[SDLK_RIGHTBRACKET] = ']';
- mTranslateKeyMap[SDLK_QUOTE] = '\'';
+ mTranslateKeyMap[SDLK_APOSTROPHE] = '\'';
// 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,45 +151,45 @@ 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.
// Is this the way it's supposed to work?
- if(mask & KMOD_SHIFT)
+ if(mask & SDL_KMOD_SHIFT)
{
mKeyLevel[KEY_SHIFT] = true;
}
- if(mask & KMOD_CTRL)
+ if(mask & SDL_KMOD_CTRL)
{
mKeyLevel[KEY_CONTROL] = true;
}
- if(mask & KMOD_ALT)
+ if(mask & SDL_KMOD_ALT)
{
mKeyLevel[KEY_ALT] = true;
}
}
-MASK LLKeyboardSDL::updateModifiers(const U32 mask)
+MASK LLKeyboardSDL::updateModifiers(const MASK mask)
{
// translate the mask
MASK out_mask = MASK_NONE;
- if(mask & KMOD_SHIFT)
+ if(mask & SDL_KMOD_SHIFT)
{
out_mask |= MASK_SHIFT;
}
- if(mask & KMOD_CTRL)
+ if(mask & SDL_KMOD_CTRL)
{
out_mask |= MASK_CONTROL;
}
- if(mask & KMOD_ALT)
+ if(mask & SDL_KMOD_ALT)
{
out_mask |= MASK_ALT;
}
@@ -201,37 +198,37 @@ MASK LLKeyboardSDL::updateModifiers(const U32 mask)
}
-static U16 adjustNativekeyFromUnhandledMask(const U16 key, const U32 mask)
+LLKeyboard::NATIVE_KEY_TYPE adjustNativekeyFromUnhandledMask(const LLKeyboard::NATIVE_KEY_TYPE key, const MASK mask)
{
// SDL doesn't automatically adjust the keysym according to
// whether NUMLOCK is engaged, so we massage the keysym manually.
- U16 rtn = key;
- if (!(mask & KMOD_NUM))
+ LLKeyboard::NATIVE_KEY_TYPE rtn = key;
+ if (!(mask & SDL_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 LLKeyboard::NATIVE_KEY_TYPE key, const MASK mask)
{
- U16 adjusted_nativekey;
+ LLKeyboard::NATIVE_KEY_TYPE adjusted_nativekey;
KEY translated_key = 0;
- U32 translated_mask = MASK_NONE;
- bool handled = false;
+ MASK translated_mask = MASK_NONE;
+ bool handled = false;
adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask);
@@ -246,12 +243,12 @@ bool LLKeyboardSDL::handleKeyDown(const U16 key, const U32 mask)
}
-bool LLKeyboardSDL::handleKeyUp(const U16 key, const U32 mask)
+bool LLKeyboardSDL::handleKeyUp(const LLKeyboard::NATIVE_KEY_TYPE key, const MASK mask)
{
- U16 adjusted_nativekey;
+ LLKeyboard::NATIVE_KEY_TYPE adjusted_nativekey;
KEY translated_key = 0;
U32 translated_mask = MASK_NONE;
- bool handled = false;
+ bool handled = false;
adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask);
@@ -268,16 +265,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 & SDL_KMOD_SHIFT)
+ result |= MASK_SHIFT;
+ if (mask & SDL_KMOD_CTRL)
+ result |= MASK_CONTROL;
+ if (mask & SDL_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 & SDL_KMOD_GUI)
+ result |= MASK_CONTROL;
}
return result;
@@ -296,6 +297,7 @@ void LLKeyboardSDL::scanKeyboard()
mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key], mKeyLevel[key]);
}
}
+ mCurScanKey = KEY_NONE;
// Reset edges for next frame
for (S32 key = 0; key < KEY_COUNT; key++)
@@ -310,15 +312,347 @@ void LLKeyboardSDL::scanKeyboard()
}
-bool LLKeyboardSDL::translateNumpadKey( const U16 os_key, KEY *translated_key)
+bool LLKeyboardSDL::translateNumpadKey( const LLKeyboard::NATIVE_KEY_TYPE os_key, KEY *translated_key)
{
return translateKey(os_key, translated_key);
}
-U16 LLKeyboardSDL::inverseTranslateNumpadKey(const KEY translated_key)
+LLKeyboard::NATIVE_KEY_TYPE LLKeyboardSDL::inverseTranslateNumpadKey(const KEY translated_key)
{
return inverseTranslateKey(translated_key);
}
-#endif
+enum class WindowsVK : U32
+{
+ LL_VK_UNKNOWN = 0,
+ LL_VK_CANCEL = 0x03,
+ LL_VK_BACK = 0x08,
+ LL_VK_TAB = 0x09,
+ LL_VK_CLEAR = 0x0C,
+ LL_VK_RETURN = 0x0D,
+ LL_VK_SHIFT = 0x10,
+ LL_VK_CONTROL = 0x11,
+ LL_VK_MENU = 0x12,
+ LL_VK_PAUSE = 0x13,
+ LL_VK_CAPITAL = 0x14,
+ LL_VK_KANA = 0x15,
+ LL_VK_HANGUL = 0x15,
+ LL_VK_JUNJA = 0x17,
+ LL_VK_FINAL = 0x18,
+ LL_VK_HANJA = 0x19,
+ LL_VK_KANJI = 0x19,
+ LL_VK_ESCAPE = 0x1B,
+ LL_VK_CONVERT = 0x1C,
+ LL_VK_NONCONVERT = 0x1D,
+ LL_VK_ACCEPT = 0x1E,
+ LL_VK_MODECHANGE = 0x1F,
+ LL_VK_SPACE = 0x20,
+ LL_VK_PRIOR = 0x21,
+ LL_VK_NEXT = 0x22,
+ LL_VK_END = 0x23,
+ LL_VK_HOME = 0x24,
+ LL_VK_LEFT = 0x25,
+ LL_VK_UP = 0x26,
+ LL_VK_RIGHT = 0x27,
+ LL_VK_DOWN = 0x28,
+ LL_VK_SELECT = 0x29,
+ LL_VK_PRINT = 0x2A,
+ LL_VK_EXECUTE = 0x2B,
+ LL_VK_SNAPSHOT = 0x2C,
+ LL_VK_INSERT = 0x2D,
+ LL_VK_DELETE = 0x2E,
+ LL_VK_HELP = 0x2F,
+ LL_VK_0 = 0x30,
+ LL_VK_1 = 0x31,
+ LL_VK_2 = 0x32,
+ LL_VK_3 = 0x33,
+ LL_VK_4 = 0x34,
+ LL_VK_5 = 0x35,
+ LL_VK_6 = 0x36,
+ LL_VK_7 = 0x37,
+ LL_VK_8 = 0x38,
+ LL_VK_9 = 0x39,
+ LL_VK_A = 0x41,
+ LL_VK_B = 0x42,
+ LL_VK_C = 0x43,
+ LL_VK_D = 0x44,
+ LL_VK_E = 0x45,
+ LL_VK_F = 0x46,
+ LL_VK_G = 0x47,
+ LL_VK_H = 0x48,
+ LL_VK_I = 0x49,
+ LL_VK_J = 0x4A,
+ LL_VK_K = 0x4B,
+ LL_VK_L = 0x4C,
+ LL_VK_M = 0x4D,
+ LL_VK_N = 0x4E,
+ LL_VK_O = 0x4F,
+ LL_VK_P = 0x50,
+ LL_VK_Q = 0x51,
+ LL_VK_R = 0x52,
+ LL_VK_S = 0x53,
+ LL_VK_T = 0x54,
+ LL_VK_U = 0x55,
+ LL_VK_V = 0x56,
+ LL_VK_W = 0x57,
+ LL_VK_X = 0x58,
+ LL_VK_Y = 0x59,
+ LL_VK_Z = 0x5A,
+ LL_VK_LWIN = 0x5B,
+ LL_VK_RWIN = 0x5C,
+ LL_VK_APPS = 0x5D,
+ LL_VK_SLEEP = 0x5F,
+ LL_VK_NUMPAD0 = 0x60,
+ LL_VK_NUMPAD1 = 0x61,
+ LL_VK_NUMPAD2 = 0x62,
+ LL_VK_NUMPAD3 = 0x63,
+ LL_VK_NUMPAD4 = 0x64,
+ LL_VK_NUMPAD5 = 0x65,
+ LL_VK_NUMPAD6 = 0x66,
+ LL_VK_NUMPAD7 = 0x67,
+ LL_VK_NUMPAD8 = 0x68,
+ LL_VK_NUMPAD9 = 0x69,
+ LL_VK_MULTIPLY = 0x6A,
+ LL_VK_ADD = 0x6B,
+ LL_VK_SEPARATOR = 0x6C,
+ LL_VK_SUBTRACT = 0x6D,
+ LL_VK_DECIMAL = 0x6E,
+ LL_VK_DIVIDE = 0x6F,
+ LL_VK_F1 = 0x70,
+ LL_VK_F2 = 0x71,
+ LL_VK_F3 = 0x72,
+ LL_VK_F4 = 0x73,
+ LL_VK_F5 = 0x74,
+ LL_VK_F6 = 0x75,
+ LL_VK_F7 = 0x76,
+ LL_VK_F8 = 0x77,
+ LL_VK_F9 = 0x78,
+ LL_VK_F10 = 0x79,
+ LL_VK_F11 = 0x7A,
+ LL_VK_F12 = 0x7B,
+ LL_VK_F13 = 0x7C,
+ LL_VK_F14 = 0x7D,
+ LL_VK_F15 = 0x7E,
+ LL_VK_F16 = 0x7F,
+ LL_VK_F17 = 0x80,
+ LL_VK_F18 = 0x81,
+ LL_VK_F19 = 0x82,
+ LL_VK_F20 = 0x83,
+ LL_VK_F21 = 0x84,
+ LL_VK_F22 = 0x85,
+ LL_VK_F23 = 0x86,
+ LL_VK_F24 = 0x87,
+ LL_VK_NUMLOCK = 0x90,
+ LL_VK_SCROLL = 0x91,
+ LL_VK_LSHIFT = 0xA0,
+ LL_VK_RSHIFT = 0xA1,
+ LL_VK_LCONTROL = 0xA2,
+ LL_VK_RCONTROL = 0xA3,
+ LL_VK_LMENU = 0xA4,
+ LL_VK_RMENU = 0xA5,
+ LL_VK_BROWSER_BACK = 0xA6,
+ LL_VK_BROWSER_FORWARD = 0xA7,
+ LL_VK_BROWSER_REFRESH = 0xA8,
+ LL_VK_BROWSER_STOP = 0xA9,
+ LL_VK_BROWSER_SEARCH = 0xAA,
+ LL_VK_BROWSER_FAVORITES = 0xAB,
+ LL_VK_BROWSER_HOME = 0xAC,
+ LL_VK_VOLUME_MUTE = 0xAD,
+ LL_VK_VOLUME_DOWN = 0xAE,
+ LL_VK_VOLUME_UP = 0xAF,
+ LL_VK_MEDIA_NEXT_TRACK = 0xB0,
+ LL_VK_MEDIA_PREV_TRACK = 0xB1,
+ LL_VK_MEDIA_STOP = 0xB2,
+ LL_VK_MEDIA_PLAY_PAUSE = 0xB3,
+ LL_VK_MEDIA_LAUNCH_MAIL = 0xB4,
+ LL_VK_MEDIA_LAUNCH_MEDIA_SELECT = 0xB5,
+ LL_VK_MEDIA_LAUNCH_APP1 = 0xB6,
+ LL_VK_MEDIA_LAUNCH_APP2 = 0xB7,
+ LL_VK_OEM_1 = 0xBA,
+ LL_VK_OEM_PLUS = 0xBB,
+ LL_VK_OEM_COMMA = 0xBC,
+ LL_VK_OEM_MINUS = 0xBD,
+ LL_VK_OEM_PERIOD = 0xBE,
+ LL_VK_OEM_2 = 0xBF,
+ LL_VK_OEM_3 = 0xC0,
+ LL_VK_OEM_4 = 0xDB,
+ LL_VK_OEM_5 = 0xDC,
+ LL_VK_OEM_6 = 0xDD,
+ LL_VK_OEM_7 = 0xDE,
+ LL_VK_OEM_8 = 0xDF,
+ LL_VK_OEM_102 = 0xE2,
+ LL_VK_PROCESSKEY = 0xE5,
+ LL_VK_PACKET = 0xE7,
+ LL_VK_ATTN = 0xF6,
+ LL_VK_CRSEL = 0xF7,
+ LL_VK_EXSEL = 0xF8,
+ LL_VK_EREOF = 0xF9,
+ LL_VK_PLAY = 0xFA,
+ LL_VK_ZOOM = 0xFB,
+ LL_VK_NONAME = 0xFC,
+ LL_VK_PA1 = 0xFD,
+ LL_VK_OEM_CLEAR = 0xFE,
+};
+
+std::map< U32, U32 > mSDL_to_Win;
+
+U32 LLKeyboardSDL::mapSDLtoWin( U32 aSymbol )
+{
+ // <FS:ND> Map SDLK_ virtual keys to Windows LL_VK_ virtual keys.
+ // Text is handled via unicode input (SDL_TEXTINPUT event) and does not need to be translated into LL_VK_ values as those match already.
+ if( mSDL_to_Win.empty() )
+ {
+
+ mSDL_to_Win[ SDLK_BACKSPACE ] = (U32)WindowsVK::LL_VK_BACK;
+ mSDL_to_Win[ SDLK_TAB ] = (U32)WindowsVK::LL_VK_TAB;
+ mSDL_to_Win[ 12 ] = (U32)WindowsVK::LL_VK_CLEAR;
+ mSDL_to_Win[ SDLK_RETURN ] = (U32)WindowsVK::LL_VK_RETURN;
+ mSDL_to_Win[ 19 ] = (U32)WindowsVK::LL_VK_PAUSE;
+ mSDL_to_Win[ SDLK_ESCAPE ] = (U32)WindowsVK::LL_VK_ESCAPE;
+ mSDL_to_Win[ SDLK_SPACE ] = (U32)WindowsVK::LL_VK_SPACE;
+ mSDL_to_Win[ SDLK_APOSTROPHE ] = (U32)WindowsVK::LL_VK_OEM_7;
+ mSDL_to_Win[ SDLK_COMMA ] = (U32)WindowsVK::LL_VK_OEM_COMMA;
+ mSDL_to_Win[ SDLK_MINUS ] = (U32)WindowsVK::LL_VK_OEM_MINUS;
+ mSDL_to_Win[ SDLK_PERIOD ] = (U32)WindowsVK::LL_VK_OEM_PERIOD;
+ mSDL_to_Win[ SDLK_SLASH ] = (U32)WindowsVK::LL_VK_OEM_2;
+
+ mSDL_to_Win[ SDLK_0 ] = (U32)WindowsVK::LL_VK_0;
+ mSDL_to_Win[ SDLK_1 ] = (U32)WindowsVK::LL_VK_1;
+ mSDL_to_Win[ SDLK_2 ] = (U32)WindowsVK::LL_VK_2;
+ mSDL_to_Win[ SDLK_3 ] = (U32)WindowsVK::LL_VK_3;
+ mSDL_to_Win[ SDLK_4 ] = (U32)WindowsVK::LL_VK_4;
+ mSDL_to_Win[ SDLK_5 ] = (U32)WindowsVK::LL_VK_5;
+ mSDL_to_Win[ SDLK_6 ] = (U32)WindowsVK::LL_VK_6;
+ mSDL_to_Win[ SDLK_7 ] = (U32)WindowsVK::LL_VK_7;
+ mSDL_to_Win[ SDLK_8 ] = (U32)WindowsVK::LL_VK_8;
+ mSDL_to_Win[ SDLK_9 ] = (U32)WindowsVK::LL_VK_9;
+
+ mSDL_to_Win[ SDLK_SEMICOLON ] = (U32)WindowsVK::LL_VK_OEM_1;
+ mSDL_to_Win[ SDLK_LESS ] = (U32)WindowsVK::LL_VK_OEM_102;
+ mSDL_to_Win[ SDLK_EQUALS ] = (U32)WindowsVK::LL_VK_OEM_PLUS;
+ mSDL_to_Win[ SDLK_KP_EQUALS ] = (U32)WindowsVK::LL_VK_OEM_PLUS;
+
+ mSDL_to_Win[ SDLK_LEFTBRACKET ] = (U32)WindowsVK::LL_VK_OEM_4;
+ mSDL_to_Win[ SDLK_BACKSLASH ] = (U32)WindowsVK::LL_VK_OEM_5;
+ mSDL_to_Win[ SDLK_RIGHTBRACKET ] = (U32)WindowsVK::LL_VK_OEM_6;
+ mSDL_to_Win[ SDLK_GRAVE ] = (U32)WindowsVK::LL_VK_OEM_8;
+
+ mSDL_to_Win[ SDLK_A ] = (U32)WindowsVK::LL_VK_A;
+ mSDL_to_Win[ SDLK_B ] = (U32)WindowsVK::LL_VK_B;
+ mSDL_to_Win[ SDLK_C ] = (U32)WindowsVK::LL_VK_C;
+ mSDL_to_Win[ SDLK_D ] = (U32)WindowsVK::LL_VK_D;
+ mSDL_to_Win[ SDLK_E ] = (U32)WindowsVK::LL_VK_E;
+ mSDL_to_Win[ SDLK_F ] = (U32)WindowsVK::LL_VK_F;
+ mSDL_to_Win[ SDLK_G ] = (U32)WindowsVK::LL_VK_G;
+ mSDL_to_Win[ SDLK_H ] = (U32)WindowsVK::LL_VK_H;
+ mSDL_to_Win[ SDLK_I ] = (U32)WindowsVK::LL_VK_I;
+ mSDL_to_Win[ SDLK_J ] = (U32)WindowsVK::LL_VK_J;
+ mSDL_to_Win[ SDLK_K ] = (U32)WindowsVK::LL_VK_K;
+ mSDL_to_Win[ SDLK_L ] = (U32)WindowsVK::LL_VK_L;
+ mSDL_to_Win[ SDLK_M ] = (U32)WindowsVK::LL_VK_M;
+ mSDL_to_Win[ SDLK_N ] = (U32)WindowsVK::LL_VK_N;
+ mSDL_to_Win[ SDLK_O ] = (U32)WindowsVK::LL_VK_O;
+ mSDL_to_Win[ SDLK_P ] = (U32)WindowsVK::LL_VK_P;
+ mSDL_to_Win[ SDLK_Q ] = (U32)WindowsVK::LL_VK_Q;
+ mSDL_to_Win[ SDLK_R ] = (U32)WindowsVK::LL_VK_R;
+ mSDL_to_Win[ SDLK_S ] = (U32)WindowsVK::LL_VK_S;
+ mSDL_to_Win[ SDLK_T ] = (U32)WindowsVK::LL_VK_T;
+ mSDL_to_Win[ SDLK_Y ] = (U32)WindowsVK::LL_VK_U;
+ mSDL_to_Win[ SDLK_V ] = (U32)WindowsVK::LL_VK_V;
+ mSDL_to_Win[ SDLK_W ] = (U32)WindowsVK::LL_VK_W;
+ mSDL_to_Win[ SDLK_X ] = (U32)WindowsVK::LL_VK_X;
+ mSDL_to_Win[ SDLK_Y ] = (U32)WindowsVK::LL_VK_Y;
+ mSDL_to_Win[ SDLK_Z ] = (U32)WindowsVK::LL_VK_Z;
+ mSDL_to_Win[ SDLK_DELETE ] = (U32)WindowsVK::LL_VK_DELETE;
+
+
+ mSDL_to_Win[ SDLK_NUMLOCKCLEAR ] = (U32)WindowsVK::LL_VK_NUMLOCK;
+ mSDL_to_Win[ SDLK_SCROLLLOCK ] = (U32)WindowsVK::LL_VK_SCROLL;
+
+ mSDL_to_Win[ SDLK_HELP ] = (U32)WindowsVK::LL_VK_HELP;
+ mSDL_to_Win[ SDLK_PRINTSCREEN ] = (U32)WindowsVK::LL_VK_SNAPSHOT;
+ mSDL_to_Win[ SDLK_CANCEL ] = (U32)WindowsVK::LL_VK_CANCEL;
+ mSDL_to_Win[ SDLK_APPLICATION ] = (U32)WindowsVK::LL_VK_APPS;
+
+ mSDL_to_Win[ SDLK_UNKNOWN ] = (U32)WindowsVK::LL_VK_UNKNOWN;
+ mSDL_to_Win[ SDLK_BACKSPACE ] = (U32)WindowsVK::LL_VK_BACK;
+ mSDL_to_Win[ SDLK_TAB ] = (U32)WindowsVK::LL_VK_TAB;
+ mSDL_to_Win[ SDLK_CLEAR ] = (U32)WindowsVK::LL_VK_CLEAR;
+ mSDL_to_Win[ SDLK_RETURN ] = (U32)WindowsVK::LL_VK_RETURN;
+ mSDL_to_Win[ SDLK_PAUSE ] = (U32)WindowsVK::LL_VK_PAUSE;
+ mSDL_to_Win[ SDLK_ESCAPE ] = (U32)WindowsVK::LL_VK_ESCAPE;
+ mSDL_to_Win[ SDLK_DELETE ] = (U32)WindowsVK::LL_VK_DELETE;
+
+ mSDL_to_Win[ SDLK_KP_PERIOD ] = (U32)WindowsVK::LL_VK_DELETE; // LL_VK_DECIMAL?
+ mSDL_to_Win[ SDLK_KP_DIVIDE ] = (U32)WindowsVK::LL_VK_DIVIDE;
+ mSDL_to_Win[ SDLK_KP_MULTIPLY] = (U32)WindowsVK::LL_VK_MULTIPLY;
+ mSDL_to_Win[ SDLK_KP_MINUS ] = (U32)WindowsVK::LL_VK_OEM_MINUS; // LL_VK_SUBSTRACT?
+ mSDL_to_Win[ SDLK_KP_PLUS ] = (U32)WindowsVK::LL_VK_OEM_PLUS; // LL_VK_ADD?
+ mSDL_to_Win[ SDLK_KP_ENTER ] = (U32)WindowsVK::LL_VK_RETURN;
+ mSDL_to_Win[ SDLK_KP_0 ] = (U32)WindowsVK::LL_VK_INSERT;
+ mSDL_to_Win[ SDLK_KP_1 ] = (U32)WindowsVK::LL_VK_END;
+ mSDL_to_Win[ SDLK_KP_2 ] = (U32)WindowsVK::LL_VK_DOWN;
+ mSDL_to_Win[ SDLK_KP_3 ] = (U32)WindowsVK::LL_VK_NEXT;
+ mSDL_to_Win[ SDLK_KP_4 ] = (U32)WindowsVK::LL_VK_LEFT;
+ mSDL_to_Win[ SDLK_KP_5 ] = (U32)WindowsVK::LL_VK_NUMPAD5;
+ mSDL_to_Win[ SDLK_KP_6 ] = (U32)WindowsVK::LL_VK_RIGHT;
+ mSDL_to_Win[ SDLK_KP_7 ] = (U32)WindowsVK::LL_VK_HOME;
+ mSDL_to_Win[ SDLK_KP_8 ] = (U32)WindowsVK::LL_VK_UP;
+ mSDL_to_Win[ SDLK_KP_9 ] = (U32)WindowsVK::LL_VK_PRIOR;
+
+ // ?
+
+ mSDL_to_Win[ SDLK_UP ] = (U32)WindowsVK::LL_VK_UP;
+ mSDL_to_Win[ SDLK_DOWN ] = (U32)WindowsVK::LL_VK_DOWN;
+ mSDL_to_Win[ SDLK_RIGHT ] = (U32)WindowsVK::LL_VK_RIGHT;
+ mSDL_to_Win[ SDLK_LEFT ] = (U32)WindowsVK::LL_VK_LEFT;
+ mSDL_to_Win[ SDLK_INSERT ] = (U32)WindowsVK::LL_VK_INSERT;
+ mSDL_to_Win[ SDLK_HOME ] = (U32)WindowsVK::LL_VK_HOME;
+ mSDL_to_Win[ SDLK_END ] = (U32)WindowsVK::LL_VK_END;
+ mSDL_to_Win[ SDLK_PAGEUP ] = (U32)WindowsVK::LL_VK_PRIOR;
+ mSDL_to_Win[ SDLK_PAGEDOWN ] = (U32)WindowsVK::LL_VK_NEXT;
+ mSDL_to_Win[ SDLK_F1 ] = (U32)WindowsVK::LL_VK_F1;
+ mSDL_to_Win[ SDLK_F2 ] = (U32)WindowsVK::LL_VK_F2;
+ mSDL_to_Win[ SDLK_F3 ] = (U32)WindowsVK::LL_VK_F3;
+ mSDL_to_Win[ SDLK_F4 ] = (U32)WindowsVK::LL_VK_F4;
+ mSDL_to_Win[ SDLK_F5 ] = (U32)WindowsVK::LL_VK_F5;
+ mSDL_to_Win[ SDLK_F6 ] = (U32)WindowsVK::LL_VK_F6;
+ mSDL_to_Win[ SDLK_F7 ] = (U32)WindowsVK::LL_VK_F7;
+ mSDL_to_Win[ SDLK_F8 ] = (U32)WindowsVK::LL_VK_F8;
+ mSDL_to_Win[ SDLK_F9 ] = (U32)WindowsVK::LL_VK_F9;
+ mSDL_to_Win[ SDLK_F10 ] = (U32)WindowsVK::LL_VK_F10;
+ mSDL_to_Win[ SDLK_F11 ] = (U32)WindowsVK::LL_VK_F11;
+ mSDL_to_Win[ SDLK_F12 ] = (U32)WindowsVK::LL_VK_F12;
+ mSDL_to_Win[ SDLK_F13 ] = (U32)WindowsVK::LL_VK_F13;
+ mSDL_to_Win[ SDLK_F14 ] = (U32)WindowsVK::LL_VK_F14;
+ mSDL_to_Win[ SDLK_F15 ] = (U32)WindowsVK::LL_VK_F15;
+ mSDL_to_Win[ SDLK_CAPSLOCK ] = (U32)WindowsVK::LL_VK_CAPITAL;
+ mSDL_to_Win[ SDLK_RSHIFT ] = (U32)WindowsVK::LL_VK_SHIFT;
+ mSDL_to_Win[ SDLK_LSHIFT ] = (U32)WindowsVK::LL_VK_SHIFT;
+ mSDL_to_Win[ SDLK_RCTRL ] = (U32)WindowsVK::LL_VK_CONTROL;
+ mSDL_to_Win[ SDLK_LCTRL ] = (U32)WindowsVK::LL_VK_CONTROL;
+ mSDL_to_Win[ SDLK_RALT ] = (U32)WindowsVK::LL_VK_MENU;
+ mSDL_to_Win[ SDLK_LALT ] = (U32)WindowsVK::LL_VK_MENU;
+
+ mSDL_to_Win[ SDLK_MENU ] = (U32)WindowsVK::LL_VK_MENU;
+
+ // LL_VK_MODECHANGE ?
+ // mSDL_to_Win[ SDLK_MODE ] = (U32)WindowsVK::LL_VK_MODE;
+
+ // ?
+ // mSDL_to_Win[ SDLK_SYSREQ ] = (U32)WindowsVK::LL_VK_SYSREQ;
+ // mSDL_to_Win[ SDLK_POWER ] = (U32)WindowsVK::LL_VK_POWER;
+ // mSDL_to_Win[ SDLK_UNDO ] = (U32)WindowsVK::LL_VK_UNDO;
+ // mSDL_to_Win[ SDLK_KP_EQUALS ] = (U32)WindowsVK::LL_VK_EQUALS;
+ // mSDL_to_Win[ 311 ] = (U32)WindowsVK::LL_VK_LWIN;
+ // mSDL_to_Win[ 312 ] = (U32)WindowsVK::LL_VK_RWIN;
+ // mSDL_to_Win[ SDLK_COLON ] = ?
+ }
+
+ auto itr = mSDL_to_Win.find( aSymbol );
+ if( itr != mSDL_to_Win.end() )
+ return itr->second;
+
+ return aSymbol;
+}
diff --git a/indra/llwindow/llkeyboardsdl.h b/indra/llwindow/llkeyboardsdl.h
index fd348b28f2..2ebe647561 100644
--- a/indra/llwindow/llkeyboardsdl.h
+++ b/indra/llwindow/llkeyboardsdl.h
@@ -28,28 +28,31 @@
#define LL_LLKEYBOARDSDL_H
#include "llkeyboard.h"
-#include "SDL/SDL.h"
+#include "SDL3/SDL.h"
class LLKeyboardSDL : public LLKeyboard
{
public:
LLKeyboardSDL();
- /*virtual*/ ~LLKeyboardSDL() {};
+ ~LLKeyboardSDL() = default;
- /*virtual*/ bool handleKeyUp(const U16 key, MASK mask);
- /*virtual*/ bool handleKeyDown(const U16 key, MASK mask);
- /*virtual*/ void resetMaskKeys();
- /*virtual*/ MASK currentMask(bool for_mouse_event);
- /*virtual*/ void scanKeyboard();
+ bool handleKeyUp(const LLKeyboard::NATIVE_KEY_TYPE key, MASK mask) override;
+ bool handleKeyDown(const LLKeyboard::NATIVE_KEY_TYPE key, MASK mask) override;
+ void resetMaskKeys() override;
+ MASK currentMask(bool for_mouse_event) override;
+ void scanKeyboard() override;
protected:
- MASK updateModifiers(const U32 mask);
+ MASK updateModifiers(const MASK mask);
void setModifierKeyLevel( KEY key, bool new_state );
- bool translateNumpadKey( const U16 os_key, KEY *translated_key );
- U16 inverseTranslateNumpadKey(const KEY translated_key);
+ bool translateNumpadKey( const LLKeyboard::NATIVE_KEY_TYPE os_key, KEY *translated_key );
+ LLKeyboard::NATIVE_KEY_TYPE 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<LLKeyboard::NATIVE_KEY_TYPE, KEY> mTranslateNumpadMap; // special map for translating OS keys to numpad keys
+ std::map<KEY, LLKeyboard::NATIVE_KEY_TYPE> mInvTranslateNumpadMap; // inverse of the above
+
+public:
+ static U32 mapSDLtoWin( U32 );
};
#endif
diff --git a/indra/llwindow/llkeyboardwin32.cpp b/indra/llwindow/llkeyboardwin32.cpp
index 8d6b8d9b93..4ef0b493a5 100644
--- a/indra/llwindow/llkeyboardwin32.cpp
+++ b/indra/llwindow/llkeyboardwin32.cpp
@@ -197,7 +197,7 @@ MASK LLKeyboardWin32::updateModifiers()
// mask is ignored, except for extended flag -- we poll the modifier keys for the other flags
-bool LLKeyboardWin32::handleKeyDown(const U16 key, MASK mask)
+bool LLKeyboardWin32::handleKeyDown(const LLKeyboard::NATIVE_KEY_TYPE key, MASK mask)
{
KEY translated_key;
U32 translated_mask;
@@ -214,7 +214,7 @@ bool LLKeyboardWin32::handleKeyDown(const U16 key, MASK mask)
}
// mask is ignored, except for extended flag -- we poll the modifier keys for the other flags
-bool LLKeyboardWin32::handleKeyUp(const U16 key, MASK mask)
+bool LLKeyboardWin32::handleKeyUp(const LLKeyboard::NATIVE_KEY_TYPE key, MASK mask)
{
KEY translated_key;
U32 translated_mask;
diff --git a/indra/llwindow/llkeyboardwin32.h b/indra/llwindow/llkeyboardwin32.h
index d0dfc5cfdd..fa223a2904 100644
--- a/indra/llwindow/llkeyboardwin32.h
+++ b/indra/llwindow/llkeyboardwin32.h
@@ -37,15 +37,16 @@ class LLKeyboardWin32 : public LLKeyboard
{
public:
LLKeyboardWin32();
- /*virtual*/ ~LLKeyboardWin32() {};
+ ~LLKeyboardWin32() = default;
- /*virtual*/ bool handleKeyUp(const U16 key, MASK mask);
- /*virtual*/ bool handleKeyDown(const U16 key, MASK mask);
- /*virtual*/ void resetMaskKeys();
- /*virtual*/ MASK currentMask(bool for_mouse_event);
- /*virtual*/ void scanKeyboard();
- bool translateExtendedKey(const U16 os_key, const MASK mask, KEY *translated_key);
- U16 inverseTranslateExtendedKey(const KEY translated_key);
+ bool handleKeyUp(const LLKeyboard::NATIVE_KEY_TYPE key, MASK mask) override;
+ bool handleKeyDown(const LLKeyboard::NATIVE_KEY_TYPE key, MASK mask) override;
+ void resetMaskKeys() override;
+ MASK currentMask(bool for_mouse_event) override;
+ void scanKeyboard() override;
+
+ bool translateExtendedKey(const U16 os_key, const MASK mask, KEY *translated_key);
+ U16 inverseTranslateExtendedKey(const KEY translated_key);
protected:
MASK updateModifiers();
diff --git a/indra/llwindow/llmousehandler.cpp b/indra/llwindow/llmousehandler.cpp
index eeceab502a..959dde70b4 100644
--- a/indra/llwindow/llmousehandler.cpp
+++ b/indra/llwindow/llmousehandler.cpp
@@ -24,6 +24,8 @@
* $/LicenseInfo$
*/
+#include "linden_common.h"
+
#include "llmousehandler.h"
//virtual
diff --git a/indra/llwindow/llsdl.cpp b/indra/llwindow/llsdl.cpp
new file mode 100644
index 0000000000..bc38120386
--- /dev/null
+++ b/indra/llwindow/llsdl.cpp
@@ -0,0 +1,149 @@
+/**
+ * @file llsdl.cpp
+ * @brief SDL initialization
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include <initializer_list>
+#include <list>
+
+#include "SDL3/SDL.h"
+
+#ifndef LL_SDL_APP
+#define SDL_MAIN_HANDLED 1
+#include "SDL3/SDL_main.h"
+#endif
+
+#include "llerror.h"
+#include "llwindow.h"
+
+bool gSDLMainHandled = false;
+
+void sdl_logger(void *userdata, int category, SDL_LogPriority priority, const char *message)
+{
+ switch (priority)
+ {
+ case SDL_LOG_PRIORITY_TRACE:
+ case SDL_LOG_PRIORITY_VERBOSE:
+ case SDL_LOG_PRIORITY_DEBUG:
+ LL_DEBUGS("SDL") << "log='" << message << "'" << LL_ENDL;
+ break;
+ case SDL_LOG_PRIORITY_INFO:
+ LL_INFOS("SDL") << "log='" << message << "'" << LL_ENDL;
+ break;
+ case SDL_LOG_PRIORITY_WARN:
+ case SDL_LOG_PRIORITY_ERROR:
+ case SDL_LOG_PRIORITY_CRITICAL:
+ LL_WARNS("SDL") << "log='" << message << "'" << LL_ENDL;
+ break;
+ case SDL_LOG_PRIORITY_INVALID:
+ default:
+ break;
+ }
+}
+
+void init_sdl(const std::string& app_name)
+{
+#ifndef LL_SDL_APP
+ if (!gSDLMainHandled)
+ {
+ SDL_SetMainReady();
+ }
+#endif
+
+ SDL_SetLogOutputFunction(&sdl_logger, nullptr);
+
+ const int c_sdl_version = SDL_VERSION;
+ LL_INFOS() << "Compiled against SDL "
+ << SDL_VERSIONNUM_MAJOR(c_sdl_version) << "."
+ << SDL_VERSIONNUM_MINOR(c_sdl_version) << "."
+ << SDL_VERSIONNUM_MICRO(c_sdl_version) << LL_ENDL;
+ const int r_sdl_version = SDL_GetVersion();
+ LL_INFOS() << "Running with SDL "
+ << SDL_VERSIONNUM_MAJOR(r_sdl_version) << "."
+ << SDL_VERSIONNUM_MINOR(r_sdl_version) << "."
+ << SDL_VERSIONNUM_MICRO(r_sdl_version) << LL_ENDL;
+
+#if LL_WINDOWS && defined(LL_SDL_WINDOW)
+ Uint32 style = 0;
+#if defined(CS_BYTEALIGNCLIENT) && defined(CS_OWNDC)
+ style = (CS_BYTEALIGNCLIENT | CS_OWNDC);
+#endif
+ SDL_RegisterApp(app_name.c_str(), style, nullptr);
+#endif
+
+#if LL_SDL_WINDOW
+ // For linux we SDL_INIT_VIDEO and _AUDIO
+ 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_MOUSE_EMULATE_WARP_WITH_RELATIVE,"0"},
+ {SDL_HINT_MOUSE_RELATIVE_WARP_MOTION,"1"},
+ {SDL_HINT_KEYCODE_OPTIONS,"french_numbers,latin_letters"}
+ };
+
+ for (auto hint: hintList)
+ {
+ 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_JOYSTICK,"SDL_INIT_JOYSTICK", true},
+ {SDL_INIT_GAMEPAD,"SDL_INIT_GAMEPAD", true},
+ };
+#else
+ // For non-linux platforms we still SDL_INIT_VIDEO because it is a pre-requisite
+ // for SDL_INIT_GAMECONTROLLER.
+ std::initializer_list<std::tuple<uint32_t, char const*, bool>> initList=
+ {
+ {SDL_INIT_VIDEO,"SDL_INIT_VIDEO", false},
+ };
+#endif // LL_LINUX
+ // We SDL_INIT_GAMECONTROLLER later in the startup process to make it
+ // more likely we'll catch initial SDL_CONTROLLERDEVICEADDED events.
+
+ for (auto subSystem : initList)
+ {
+ if (!SDL_InitSubSystem(std::get<0>(subSystem)))
+ {
+ LL_WARNS() << "SDL_InitSubSystem for " << std::get<1>(subSystem) << " failed " << SDL_GetError() << LL_ENDL;
+
+ if (std::get<2>(subSystem))
+ {
+ OSMessageBox("SDL_Init() failure", "error", OSMB_OK);
+ return;
+ }
+ }
+ }
+}
+
+void quit_sdl()
+{
+#if LL_WINDOWS && defined(LL_SDL_WINDOW)
+ SDL_UnregisterApp();
+#endif
+ SDL_Quit();
+}
diff --git a/indra/llwindow/llsdl.h b/indra/llwindow/llsdl.h
new file mode 100644
index 0000000000..6c9c9eb07c
--- /dev/null
+++ b/indra/llwindow/llsdl.h
@@ -0,0 +1,34 @@
+/**
+ * @file llsdl.h
+ * @brief SDL initialization
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#pragma once
+
+#include "llpreprocessor.h"
+
+extern bool gSDLMainHandled;
+
+void init_sdl(const std::string& app_name);
+void quit_sdl();
diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp
index eb11a28360..2313aeda50 100644
--- a/indra/llwindow/llwindow.cpp
+++ b/indra/llwindow/llwindow.cpp
@@ -29,7 +29,7 @@
#if LL_MESA_HEADLESS
#include "llwindowmesaheadless.h"
-#elif LL_SDL
+#elif LL_SDL_WINDOW
#include "llwindowsdl.h"
#elif LL_WINDOWS
#include "llwindowwin32.h"
@@ -39,6 +39,9 @@
#include "llerror.h"
#include "llkeyboard.h"
+#if LL_SDL_WINDOW && !defined(LL_MESA_HEADLESS)
+#include "llsdl.h"
+#endif
#include "llwindowcallbacks.h"
@@ -74,14 +77,15 @@ S32 OSMessageBox(const std::string& text, const std::string& caption, U32 type)
LL_WARNS() << "OSMessageBox: " << text << LL_ENDL;
#if LL_MESA_HEADLESS // !!! *FIX: (?)
return OSBTN_OK;
+#elif LL_SDL_WINDOW
+ result = OSMessageBoxSDL(text, caption, type);
#elif LL_WINDOWS
result = OSMessageBoxWin32(text, caption, type);
#elif LL_DARWIN
result = OSMessageBoxMacOSX(text, caption, type);
-#elif LL_SDL
- result = OSMessageBoxSDL(text, caption, type);
#else
-#error("OSMessageBox not implemented for this platform!")
+ LL_WARNS() << "OSMessageBox not implemented for this platform!" << LL_ENDL;
+ return OSBTN_OK;
#endif
if (was_visible)
@@ -182,12 +186,6 @@ bool LLWindow::dialogColorPicker(F32 *r, F32 *g, F32 *b)
return false;
}
-void *LLWindow::getMediaWindow()
-{
- // Default to returning the platform window.
- return getPlatformWindow();
-}
-
bool LLWindow::setSize(LLCoordScreen size)
{
if (!getMaximized())
@@ -258,12 +256,12 @@ bool LLWindow::copyTextToPrimary(const LLWString &src)
// static
std::vector<std::string> LLWindow::getDynamicFallbackFontList()
{
-#if LL_WINDOWS
+#if LL_SDL_WINDOW && !LL_MESA_HEADLESS
+ return LLWindowSDL::getDynamicFallbackFontList();
+#elif LL_WINDOWS
return LLWindowWin32::getDynamicFallbackFontList();
#elif LL_DARWIN
return LLWindowMacOSX::getDynamicFallbackFontList();
-#elif LL_SDL
- return LLWindowSDL::getDynamicFallbackFontList();
#else
return std::vector<std::string>();
#endif
@@ -272,7 +270,9 @@ std::vector<std::string> LLWindow::getDynamicFallbackFontList()
// static
std::vector<std::string> LLWindow::getDisplaysResolutionList()
{
-#if LL_WINDOWS
+#if LL_SDL_WINDOW && !LL_MESA_HEADLESS
+ return LLWindowSDL::getDisplaysResolutionList();
+#elif LL_WINDOWS
return LLWindowWin32::getDisplaysResolutionList();
#elif LL_DARWIN
return LLWindowMacOSX::getDisplaysResolutionList();
@@ -341,14 +341,17 @@ bool LLSplashScreen::isVisible()
// static
LLSplashScreen *LLSplashScreen::create()
{
-#if LL_MESA_HEADLESS || LL_SDL // !!! *FIX: (?)
- return 0;
+#if LL_MESA_HEADLESS
+ return nullptr;
+#elif LL_SDL_WINDOW
+ return new LLSplashScreenSDL;
#elif LL_WINDOWS
return new LLSplashScreenWin32;
#elif LL_DARWIN
return new LLSplashScreenMacOSX;
#else
-#error("LLSplashScreen not implemented on this platform!")
+ LL_WARNS() << ("LLSplashScreen not implemented on this platform!") << LL_ENDL;
+ return nullptr;
#endif
}
@@ -358,7 +361,9 @@ void LLSplashScreen::show()
{
if (!gSplashScreenp)
{
-#if LL_WINDOWS && !LL_MESA_HEADLESS
+#if LL_SDL_WINDOW && !LL_MESA_HEADLESS
+ gSplashScreenp = new LLSplashScreenSDL;
+#elif LL_WINDOWS && !LL_MESA_HEADLESS
gSplashScreenp = new LLSplashScreenWin32;
#elif LL_DARWIN
gSplashScreenp = new LLSplashScreenMacOSX;
@@ -412,15 +417,19 @@ LLWindow* LLWindowManager::createWindow(
{
LLWindow* new_window;
+#if LL_SDL_WINDOW && !defined(LL_MESA_HEADLESS)
+ init_sdl(name);
+#endif
+
if (use_gl)
{
#if LL_MESA_HEADLESS
new_window = new LLWindowMesaHeadless(callbacks,
title, name, x, y, width, height, flags,
fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth);
-#elif LL_SDL
+#elif LL_SDL_WINDOW
new_window = new LLWindowSDL(callbacks,
- title, x, y, width, height, flags,
+ title, name, x, y, width, height, flags,
fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
#elif LL_WINDOWS
new_window = new LLWindowWin32(callbacks,
@@ -461,6 +470,9 @@ bool LLWindowManager::destroyWindow(LLWindow* window)
window->close();
sWindowList.erase(window);
+#if LL_SDL_WINDOW && !defined(LL_MESA_HEADLESS)
+ quit_sdl();
+#endif
delete window;
diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h
index 185940e32d..e9dfa3aba4 100644
--- a/indra/llwindow/llwindow.h
+++ b/indra/llwindow/llwindow.h
@@ -92,7 +92,7 @@ public:
virtual bool setCursorPosition(LLCoordWindow position) = 0;
virtual bool getCursorPosition(LLCoordWindow *position) = 0;
-#if LL_WINDOWS
+#if LL_WINDOWS && !LL_SDL_WINDOW
virtual bool getCursorDelta(LLCoordCommon* delta) = 0;
#endif
virtual bool isWrapMouse() const = 0;
@@ -174,9 +174,6 @@ public:
// return a platform-specific window reference (HWND on Windows, WindowRef on the Mac, Gtk window on Linux)
virtual void *getPlatformWindow() = 0;
-// return the platform-specific window reference we use to initialize llmozlib (HWND on Windows, WindowRef on the Mac, Gtk window on Linux)
- virtual void *getMediaWindow();
-
// control platform's Language Text Input mechanisms.
virtual void allowLanguageTextInput(LLPreeditor *preeditor, bool b) {}
virtual void setLanguageTextInput( const LLCoordGL & pos ) {};
diff --git a/indra/llwindow/llwindowheadless.h b/indra/llwindow/llwindowheadless.h
index dc7b833013..8b7b0ef55c 100644
--- a/indra/llwindow/llwindowheadless.h
+++ b/indra/llwindow/llwindowheadless.h
@@ -60,7 +60,7 @@ public:
/*virtual*/ void toggleVSync(bool enable_vsync) override { }
/*virtual*/ bool setCursorPosition(LLCoordWindow position) override {return false;}
/*virtual*/ bool getCursorPosition(LLCoordWindow *position) override {return false;}
-#if LL_WINDOWS
+#if LL_WINDOWS && !LL_SDL_WINDOW
/*virtual*/ bool getCursorDelta(LLCoordCommon* delta) override { return false; }
#endif
/*virtual*/ bool isWrapMouse() const override { return true; }
diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h
index d703a84d02..dc8b7504c9 100644
--- a/indra/llwindow/llwindowmacosx.h
+++ b/indra/llwindow/llwindowmacosx.h
@@ -36,11 +36,6 @@
#include <ApplicationServices/ApplicationServices.h>
#include <OpenGL/OpenGL.h>
-// AssertMacros.h does bad things.
-#include "fix_macros.h"
-#undef verify
-#undef require
-
class LLWindowMacOSX : public LLWindow
{
public:
diff --git a/indra/llwindow/llwindowmesaheadless.h b/indra/llwindow/llwindowmesaheadless.h
index 0bf8c46a30..47cd6320b1 100644
--- a/indra/llwindow/llwindowmesaheadless.h
+++ b/indra/llwindow/llwindowmesaheadless.h
@@ -30,70 +30,75 @@
#if LL_MESA_HEADLESS
#include "llwindow.h"
-#include "GL/glu.h"
#include "GL/osmesa.h"
class LLWindowMesaHeadless : public LLWindow
{
public:
- /*virtual*/ void show() {};
- /*virtual*/ void hide() {};
- /*virtual*/ void close() {};
- /*virtual*/ bool getVisible() {return false;};
- /*virtual*/ bool getMinimized() {return false;};
- /*virtual*/ bool getMaximized() {return false;};
- /*virtual*/ bool maximize() {return false;};
- /*virtual*/ void minimize() {};
- /*virtual*/ void restore() {};
- /*virtual*/ bool getFullscreen() {return false;};
- /*virtual*/ bool getPosition(LLCoordScreen *position) {return false;};
- /*virtual*/ bool getSize(LLCoordScreen *size) {return false;};
- /*virtual*/ bool getSize(LLCoordWindow *size) {return false;};
- /*virtual*/ bool setPosition(LLCoordScreen position) {return false;};
- /*virtual*/ bool setSizeImpl(LLCoordScreen size) {return false;};
- /*virtual*/ bool switchContext(bool fullscreen, const LLCoordScreen &size, bool disable_vsync, const LLCoordScreen * const posp = NULL) {return false;};
- /*virtual*/ bool setCursorPosition(LLCoordWindow position) {return false;};
- /*virtual*/ bool getCursorPosition(LLCoordWindow *position) {return false;};
- /*virtual*/ void showCursor() {};
- /*virtual*/ void hideCursor() {};
- /*virtual*/ void showCursorFromMouseMove() {};
- /*virtual*/ void hideCursorUntilMouseMove() {};
- /*virtual*/ bool isCursorHidden() {return false;};
- /*virtual*/ void updateCursor() {};
- //virtual ECursorType getCursor() { return mCurrentCursor; };
- /*virtual*/ void captureMouse() {};
- /*virtual*/ void releaseMouse() {};
- /*virtual*/ void setMouseClipping( bool b ) {};
- /*virtual*/ bool isClipboardTextAvailable() {return false; };
- /*virtual*/ bool pasteTextFromClipboard(LLWString &dst) {return false; };
- /*virtual*/ bool copyTextToClipboard(const LLWString &src) {return false; };
- /*virtual*/ void flashIcon(F32 seconds) {};
- /*virtual*/ F32 getGamma() {return 1.0f; };
- /*virtual*/ bool setGamma(const F32 gamma) {return false; }; // Set the gamma
- /*virtual*/ bool restoreGamma() {return false; }; // Restore original gamma table (before updating gamma)
- /*virtual*/ void setFSAASamples(const U32 fsaa_samples) { /* FSAA not supported yet on Mesa headless.*/ }
- /*virtual*/ U32 getFSAASamples() { return 0; }
- //virtual ESwapMethod getSwapMethod() { return mSwapMethod; }
- /*virtual*/ void gatherInput() {};
- /*virtual*/ void delayInputProcessing() {};
- /*virtual*/ void swapBuffers();
- /*virtual*/ void restoreGLContext() {};
+ void show() override {};
+ void hide() override {};
+ void close() override {};
+ bool getVisible() override {return false;};
+ bool getMinimized() override {return false;};
+ bool getMaximized() override {return false;};
+ bool maximize() override {return false;};
+ void minimize() override {};
+ void restore() override {};
+ bool getFullscreen() {return false;};
+ bool getPosition(LLCoordScreen *position) override {return false;};
+ bool getSize(LLCoordScreen *size) override {return false;};
+ bool getSize(LLCoordWindow *size) override {return false;};
+ bool setPosition(LLCoordScreen position) override {return false;};
+ bool setSizeImpl(LLCoordScreen size) override {return false;};
+ bool switchContext(bool fullscreen, const LLCoordScreen &size, bool disable_vsync, const LLCoordScreen * const posp = NULL) override {return false;};
+ bool setCursorPosition(LLCoordWindow position) override {return false;};
+ bool getCursorPosition(LLCoordWindow *position) override {return false;};
+ bool isWrapMouse() const override { return true; }
+ void showCursor() override {};
+ void hideCursor() override {};
+ void showCursorFromMouseMove() override {};
+ void hideCursorUntilMouseMove() override {};
+ bool isCursorHidden() override {return false;};
+ void updateCursor() override {};
+ //virtual ECursorType getCursor() override { return mCurrentCursor; };
+ void captureMouse() override {};
+ void releaseMouse() override {};
+ void setMouseClipping( bool b ) override {};
+ bool isClipboardTextAvailable() override {return false; };
+ bool pasteTextFromClipboard(LLWString &dst) override {return false; };
+ bool copyTextToClipboard(const LLWString &src) override {return false; };
+ void flashIcon(F32 seconds) override {};
+ F32 getGamma() override {return 1.0f; };
+ bool setGamma(const F32 gamma) override {return false; }; // Set the gamma
+ bool restoreGamma() override {return false; }; // Restore original gamma table (before updating gamma)
+ void setFSAASamples(const U32 fsaa_samples) override { /* FSAA not supported yet on Mesa headless.*/ }
+ U32 getFSAASamples() override { return 0; }
+ //virtual ESwapMethod getSwapMethod() override { return mSwapMethod; }
+ void gatherInput() override {};
+ void delayInputProcessing() override {};
+ void swapBuffers() override;
+
+ void* createSharedContext()override{return nullptr;};
+ void makeContextCurrent(void* context)override{};
+ void destroySharedContext(void* context)override{};
+ void toggleVSync(bool enable_vsync) override {};
+ bool setSizeImpl(LLCoordWindow size) override { return false; };
// handy coordinate space conversion routines
- /*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordWindow *to) { return false; };
- /*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordScreen *to) { return false; };
- /*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordGL *to) { return false; };
- /*virtual*/ bool convertCoords(LLCoordGL from, LLCoordWindow *to) { return false; };
- /*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordGL *to) { return false; };
- /*virtual*/ bool convertCoords(LLCoordGL from, LLCoordScreen *to) { return false; };
+ bool convertCoords(LLCoordScreen from, LLCoordWindow *to) override { return false; };
+ bool convertCoords(LLCoordWindow from, LLCoordScreen *to) override { return false; };
+ bool convertCoords(LLCoordWindow from, LLCoordGL *to) override { return false; };
+ bool convertCoords(LLCoordGL from, LLCoordWindow *to) override { return false; };
+ bool convertCoords(LLCoordScreen from, LLCoordGL *to) override { return false; };
+ bool convertCoords(LLCoordGL from, LLCoordScreen *to) override { return false; };
- /*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) { return NULL; };
- /*virtual*/ F32 getNativeAspectRatio() { return 1.0f; };
- /*virtual*/ F32 getPixelAspectRatio() { return 1.0f; };
- /*virtual*/ void setNativeAspectRatio(F32 ratio) {}
+ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) override { return NULL; };
+ F32 getNativeAspectRatio() override { return 1.0f; };
+ F32 getPixelAspectRatio() override { return 1.0f; };
+ void setNativeAspectRatio(F32 ratio) override {}
- /*virtual*/ void *getPlatformWindow() { return 0; };
- /*virtual*/ void bringToFront() {};
+ void *getPlatformWindow() override { return 0; };
+ void bringToFront() override {};
LLWindowMesaHeadless(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
@@ -112,9 +117,9 @@ public:
LLSplashScreenMesaHeadless() {};
virtual ~LLSplashScreenMesaHeadless() {};
- /*virtual*/ void showImpl() {};
- /*virtual*/ void updateImpl(const std::string& mesg) {};
- /*virtual*/ void hideImpl() {};
+ void showImpl() override {};
+ void updateImpl(const std::string& mesg) override {};
+ void hideImpl() override {};
};
diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp
index 05be319c0b..2d8a74c782 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"
@@ -39,197 +37,84 @@
#include "llstring.h"
#include "lldir.h"
#include "llfindlocale.h"
+#include "llpreeditor.h"
+#include "llsdl.h"
-#if LL_GTK
-extern "C" {
-# include "gtk/gtk.h"
-}
-#include <locale.h>
-#endif // LL_GTK
+#if LL_LINUX
+#ifdef LL_GLIB
+#include <glib.h>
+#endif
extern "C" {
# include "fontconfig/fontconfig.h"
}
-#if LL_LINUX
// not necessarily available on random SDL platforms, so #if LL_LINUX
// for execv(), waitpid(), fork()
-# include <unistd.h>
-# include <sys/types.h>
-# include <sys/wait.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdio.h>
+
+#if LL_X11
+LLWindowSDL::X11_DATA LLWindowSDL::sX11Data = {};
+#endif
+#if LL_WAYLAND
+LLWindowSDL::WAYLAND_DATA LLWindowSDL::sWaylandData = {};
+#endif
#endif // LL_LINUX
-extern bool gDebugWindowProc;
+#if LL_DARWIN
+#include <OpenGL/OpenGL.h>
+#include <Carbon/Carbon.h>
+#include <CoreServices/CoreServices.h>
+#include <CoreGraphics/CGDisplayConfiguration.h>
-const S32 MAX_NUM_RESOLUTIONS = 200;
+bool LLWindowSDL::sUseMultGL = false;
+#endif
+
+bool gHiDPISupport = true;
-// static variable for ATI mouse cursor crash work-around:
-static bool ATIbug = false;
+const S32 MAX_NUM_RESOLUTIONS = 200;
+const S32 DEFAULT_REFRESH_RATE = 60;
//
// LLWindowSDL
//
-#if LL_X11
-# include <X11/Xutil.h>
-#endif //LL_X11
-
// TOFU HACK -- (*exactly* the same hack as LLWindowMacOSX for a similar
// set of reasons): Stash a pointer to the LLWindowSDL object here and
// maintain in the constructor and destructor. This assumes that there will
// be only one object of this class at any time. Currently this is true.
-static LLWindowSDL *gWindowImplementation = NULL;
-
-
-void maybe_lock_display(void)
-{
- if (gWindowImplementation && gWindowImplementation->Lock_Display) {
- gWindowImplementation->Lock_Display();
- }
-}
-
-
-void maybe_unlock_display(void)
-{
- if (gWindowImplementation && gWindowImplementation->Unlock_Display) {
- gWindowImplementation->Unlock_Display();
- }
-}
-
-
-#if LL_GTK
-// Lazily initialize and check the runtime GTK version for goodness.
-// static
-bool LLWindowSDL::ll_try_gtk_init(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 (!done_setlocale)
- {
- LL_INFOS() << "Starting GTK Initialization." << LL_ENDL;
- maybe_lock_display();
- gtk_disable_setlocale();
- maybe_unlock_display();
- done_setlocale = true;
- }
-
- if (!tried_gtk_init)
- {
- 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;
- }
-
- if (gtk_is_good && !done_gtk_diag)
- {
- 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;
- maybe_lock_display();
- const gchar* gtk_warning = gtk_check_version(
- GTK_MAJOR_VERSION,
- GTK_MINOR_VERSION,
- GTK_MICRO_VERSION);
- maybe_unlock_display();
- if (gtk_warning)
- {
- LL_WARNS() << "- GTK COMPATIBILITY WARNING: " <<
- gtk_warning << LL_ENDL;
- gtk_is_good = false;
- } else {
- LL_INFOS() << "- GTK version is good." << LL_ENDL;
- }
-
- done_gtk_diag = true;
- }
-
- return gtk_is_good;
-}
-#endif // LL_GTK
-
-
-#if LL_X11
-// static
-Window LLWindowSDL::get_SDL_XWindowID(void)
-{
- if (gWindowImplementation) {
- return gWindowImplementation->mSDL_XWindowID;
- }
- return None;
-}
-
-//static
-Display* LLWindowSDL::get_SDL_Display(void)
-{
- if (gWindowImplementation) {
- return gWindowImplementation->mSDL_Display;
- }
- return NULL;
-}
-#endif // LL_X11
-
+static LLWindowSDL *gWindowImplementation = nullptr;
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, const std::string& name, 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),
+ mGamma(1.0f), mFlashing(false)
{
+ SDL_GL_LoadLibrary(nullptr);
+
// Initialize the keyboard
gKeyboard = new LLKeyboardSDL();
gKeyboard->setCallbacks(callbacks);
- // Note that we can't set up key-repeat until after SDL has init'd video
-
- // Ignore use_gl for now, only used for drones on PC
- mWindow = NULL;
- mNeedsResize = false;
- mOverrideAspectRatio = 0.f;
- mGrabbyKeyFlags = 0;
- mReallyCapturedCount = 0;
- mHaveInputFocus = -1;
- mIsMinimized = -1;
- mFSAASamples = fsaa_samples;
-
-#if LL_X11
- mSDL_XWindowID = None;
- mSDL_Display = NULL;
-#endif // LL_X11
-
-#if LL_GTK
- // We MUST be the first to initialize GTK so that GTK doesn't get badly
- // initialized with a non-C locale and cause lots of serious random
- // weirdness.
- ll_try_gtk_init();
-#endif // LL_GTK
// Assume 4:3 aspect ratio until we know better
- mOriginalAspectRatio = 1024.0 / 768.0;
+ mNativeAspectRatio = 1024.f / 768.f;
if (title.empty())
- mWindowTitle = "SDL Window"; // *FIX: (?)
+ mWindowTitle = "Second Life";
else
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.initWGL();
gGLManager.initGL();
//start with arrow cursor
@@ -241,14 +126,6 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
// Stash an object pointer for OSMessageBox()
gWindowImplementation = this;
-
-#if LL_X11
- mFlashing = false;
-#endif // LL_X11
-
- mKeyScanCode = 0;
- mKeyVirtualKey = 0;
- mKeyModifiers = KMOD_NONE;
}
static SDL_Surface *Load_BMP_Resource(const char *basename)
@@ -258,480 +135,377 @@ static SDL_Surface *Load_BMP_Resource(const char *basename)
// Figure out where our BMP is living on the disk
snprintf(path_buffer, PATH_BUFFER_SIZE-1, "%s%sres-sdl%s%s",
- gDirUtilp->getAppRODataDir().c_str(),
- gDirUtilp->getDirDelimiter().c_str(),
- gDirUtilp->getDirDelimiter().c_str(),
- basename);
+ gDirUtilp->getAppRODataDir().c_str(),
+ gDirUtilp->getDirDelimiter().c_str(),
+ gDirUtilp->getDirDelimiter().c_str(),
+ basename);
path_buffer[PATH_BUFFER_SIZE-1] = '\0';
return SDL_LoadBMP(path_buffer);
}
-#if LL_X11
-// This is an XFree86/XOrg-specific hack for detecting the amount of Video RAM
-// on this machine. It works by searching /var/log/var/log/Xorg.?.log or
-// /var/log/XFree86.?.log for a ': (VideoRAM ?|Memory): (%d+) kB' regex, where
-// '?' is the X11 display number derived from $DISPLAY
-static int x11_detect_VRAM_kb_fp(FILE *fp, const char *prefix_str)
+void LLWindowSDL::setTitle(const std::string title)
{
- const int line_buf_size = 1000;
- char line_buf[line_buf_size];
- while (fgets(line_buf, line_buf_size, fp))
- {
- //LL_DEBUGS() << "XLOG: " << line_buf << LL_ENDL;
-
- // Why the ad-hoc parser instead of using a regex? Our
- // favourite regex implementation - libboost_regex - is
- // quite a heavy and troublesome dependency for the client, so
- // it seems a shame to introduce it for such a simple task.
- // *FIXME: libboost_regex is a dependency now anyway, so we may
- // as well use it instead of this hand-rolled nonsense.
- const char *part1_template = prefix_str;
- const char part2_template[] = " kB";
- char *part1 = strstr(line_buf, part1_template);
- if (part1) // found start of matching line
- {
- part1 = &part1[strlen(part1_template)]; // -> after
- char *part2 = strstr(part1, part2_template);
- if (part2) // found end of matching line
- {
- // now everything between part1 and part2 is
- // supposed to be numeric, describing the
- // number of kB of Video RAM supported
- int rtn = 0;
- for (; part1 < part2; ++part1)
- {
- if (*part1 < '0' || *part1 > '9')
- {
- // unexpected char, abort parse
- rtn = 0;
- break;
- }
- rtn *= 10;
- rtn += (*part1) - '0';
- }
- if (rtn > 0)
- {
- // got the kB number. return it now.
- return rtn;
- }
- }
- }
- }
- return 0; // 'could not detect'
+ SDL_SetWindowTitle( mWindow, title.c_str() );
}
-static int x11_detect_VRAM_kb()
+void LLWindowSDL::tryFindFullscreenSize( int &width, int &height )
{
- std::string x_log_location("/var/log/");
- std::string fname;
- int rtn = 0; // 'could not detect'
- int display_num = 0;
- FILE *fp;
- char *display_env = getenv("DISPLAY"); // e.g. :0 or :0.0 or :1.0 etc
- // parse DISPLAY number so we can go grab the right log file
- if (display_env[0] == ':' &&
- display_env[1] >= '0' && display_env[1] <= '9')
- {
- display_num = display_env[1] - '0';
- }
+ LL_INFOS() << "createContext: setting up fullscreen " << width << "x" << height << LL_ENDL;
- // *TODO: we could be smarter and see which of Xorg/XFree86 has the
- // freshest time-stamp.
-
- // Try Xorg log first
- fname = x_log_location;
- fname += "Xorg.";
- fname += ('0' + display_num);
- fname += ".log";
- fp = fopen(fname.c_str(), "r");
- if (fp)
+ // If the requested width or height is 0, find the best default for the monitor.
+ if(width == 0 || height == 0)
{
- LL_INFOS() << "Looking in " << fname
- << " for VRAM info..." << LL_ENDL;
- rtn = x11_detect_VRAM_kb_fp(fp, ": VideoRAM: ");
- fclose(fp);
- if (0 == rtn)
+ // 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 != nullptr)
{
- fp = fopen(fname.c_str(), "r");
- if (fp)
+ F32 closestAspect = 0;
+ U32 closestHeight = 0;
+ U32 closestWidth = 0;
+
+ LL_INFOS() << "createContext: searching for a display mode, original aspect is " << mNativeAspectRatio << LL_ENDL;
+
+ for(S32 i=0; i < resolutionCount; i++)
{
- rtn = x11_detect_VRAM_kb_fp(fp, ": Video RAM: ");
- fclose(fp);
- if (0 == rtn)
+ 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 - mNativeAspectRatio) < fabs(closestAspect - mNativeAspectRatio)))
{
- fp = fopen(fname.c_str(), "r");
- if (fp)
- {
- rtn = x11_detect_VRAM_kb_fp(fp, ": Memory: ");
- fclose(fp);
- }
+ 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;
}
}
- else
+
+ if(width == 0 || height == 0)
{
- LL_INFOS() << "Could not open " << fname
- << " - skipped." << LL_ENDL;
- // Try old XFree86 log otherwise
- fname = x_log_location;
- fname += "XFree86.";
- fname += ('0' + display_num);
- fname += ".log";
- fp = fopen(fname.c_str(), "r");
- if (fp)
- {
- LL_INFOS() << "Looking in " << fname
- << " for VRAM info..." << LL_ENDL;
- rtn = x11_detect_VRAM_kb_fp(fp, ": VideoRAM: ");
- fclose(fp);
- if (0 == rtn)
- {
- fp = fopen(fname.c_str(), "r");
- if (fp)
- {
- rtn = x11_detect_VRAM_kb_fp(fp, ": Memory: ");
- fclose(fp);
- }
- }
- }
- else
- {
- LL_INFOS() << "Could not open " << fname
- << " - skipped." << LL_ENDL;
- }
+ // Mode search failed for some reason. Use the old-school default.
+ width = 1024;
+ height = 768;
}
- return rtn;
}
-#endif // LL_X11
-bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, bool fullscreen, bool disable_vsync)
+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;
+ LL_INFOS() << "createContext, fullscreen=" << fullscreen << " size=" << width << "x" << height << LL_ENDL;
// captures don't survive contexts
mGrabbyKeyFlags = 0;
- mReallyCapturedCount = 0;
- if (SDL_Init(SDL_INIT_VIDEO) < 0)
- {
- LL_INFOS() << "sdl_init() failed! " << SDL_GetError() << LL_ENDL;
- setupFailure("sdl_init() failure, window creation error", "error", OSMB_OK);
- return false;
- }
+ if (width == 0)
+ width = 1024;
+ if (height == 0)
+ width = 768;
+ if (x == 0)
+ x = SDL_WINDOWPOS_UNDEFINED;
+ if (y == 0)
+ y = SDL_WINDOWPOS_UNDEFINED;
- 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();
- LL_INFOS() << " Running against SDL "
- << int(r_sdl_version->major) << "."
- << int(r_sdl_version->minor) << "."
- << int(r_sdl_version->patch) << LL_ENDL;
+ mFullscreen = fullscreen;
+
+ // Setup default backing colors
+ GLint redBits{8}, greenBits{8}, blueBits{8}, alphaBits{8};
+ GLint depthBits{24}, stencilBits{8};
+
+ 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_ALPHA_SIZE, alphaBits);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, depthBits);
+ SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, stencilBits);
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
- const SDL_VideoInfo *video_info = SDL_GetVideoInfo( );
- if (!video_info)
+ SDL_GLContextFlag context_flags{};
+ if(LLRender::sGLCoreProfile)
{
- LL_INFOS() << "SDL_GetVideoInfo() failed! " << SDL_GetError() << LL_ENDL;
- setupFailure("SDL_GetVideoInfo() failed, Window creation error", "Error", OSMB_OK);
- return false;
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
+#if LL_DARWIN
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
+ context_flags |= SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG;
+#endif
}
- if (video_info->current_h > 0)
+ if (gDebugGL)
{
- 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;
+ context_flags |= SDL_GL_CONTEXT_DEBUG_FLAG;
}
- SDL_EnableUNICODE(1);
- SDL_WM_SetCaption(mWindowTitle.c_str(), mWindowTitle.c_str());
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, context_flags);
+ SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
- // 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;
+ 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);
-
- // *FIX: try to toggle vsync here?
-
- mFullscreen = fullscreen;
-
- int sdlflags = SDL_OPENGL | SDL_RESIZABLE | SDL_ANYFORMAT;
-
- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+ SDL_PropertiesID props = SDL_CreateProperties();
+ SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, mWindowTitle.c_str());
+ SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, x);
+ SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, y);
+ SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, width);
+ SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, height);
+ SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_RESIZABLE_BOOLEAN, true);
+ SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_OPENGL_BOOLEAN, true);
+ SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FULLSCREEN_BOOLEAN, mFullscreen);
+ SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIDDEN_BOOLEAN, true);
+ SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN, gHiDPISupport);
- if (mFSAASamples > 0)
+ mWindow = SDL_CreateWindowWithProperties(props);
+ if (mWindow == nullptr)
{
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, mFSAASamples);
+ LL_WARNS() << "Window creation failure. SDL: " << SDL_GetError() << LL_ENDL;
+ setupFailure("Window creation error", "Error", OSMB_OK);
+ SDL_DestroyProperties(props);
+ return false;
}
+ SDL_DestroyProperties(props); // Free properties once window is created
- mSDLFlags = sdlflags;
+ // Create the context
+ mContext = SDL_GL_CreateContext(mWindow);
+ if(!mContext)
+ {
+ LL_WARNS() << "Cannot create GL context " << SDL_GetError() << LL_ENDL;
+ setupFailure("GL Context creation error", "Error", OSMB_OK);
+ return false;
+ }
- if (mFullscreen)
+ if (!SDL_GL_MakeCurrent(mWindow, mContext))
{
- LL_INFOS() << "createContext: setting up fullscreen " << width << "x" << height << LL_ENDL;
+ LL_WARNS() << "Failed to make context current. SDL: " << SDL_GetError() << LL_ENDL;
+ setupFailure("GL Context failed to set current failure", "Error", OSMB_OK);
+ return false;
+ }
- // If the requested width or height is 0, find the best default for the monitor.
- if((width == 0) || (height == 0))
+ const SDL_DisplayMode* displayMode = SDL_GetCurrentDisplayMode(SDL_GetDisplayForWindow(mWindow));
+ if(displayMode)
+ {
+ mRefreshRate = ll_round(displayMode->refresh_rate);
+ mNativeAspectRatio = ((F32)displayMode->w) / ((F32)displayMode->h);
+ if(mFullscreen)
{
- // 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;
+ mFullscreenWidth = displayMode->w;
+ mFullscreenHeight = displayMode->h;
+ mFullscreenRefresh = ll_round(displayMode->refresh_rate);
- for(i=0; i < resolutionCount; i++)
- {
- F32 aspect = (F32)resolutionList[i].mWidth / (F32)resolutionList[i].mHeight;
-
- LL_INFOS() << "createContext: width " << resolutionList[i].mWidth << " height " << resolutionList[i].mHeight << " aspect " << aspect << LL_ENDL;
-
- if( (resolutionList[i].mHeight >= 700) && (resolutionList[i].mHeight <= 800) &&
- (fabs(aspect - mOriginalAspectRatio) < fabs(closestAspect - mOriginalAspectRatio)))
- {
- LL_INFOS() << " (new closest mode) " << LL_ENDL;
-
- // This is the closest mode we've seen yet.
- closestWidth = resolutionList[i].mWidth;
- closestHeight = resolutionList[i].mHeight;
- closestAspect = aspect;
- }
- }
-
- width = closestWidth;
- height = closestHeight;
- }
+ LL_INFOS() << "Running at " << mFullscreenWidth
+ << "x" << mFullscreenHeight
+ << " @ " << mFullscreenRefresh
+ << LL_ENDL;
}
-
- if((width == 0) || (height == 0))
+ }
+ else
+ {
+ LL_WARNS() << "Failed to get current display mode and refresh rate" << LL_ENDL;
+ mRefreshRate = 0;
+ mNativeAspectRatio = 1024.f / 768.f;
+ if(mFullscreen) // Fallback to window size
{
- // Mode search failed for some reason. Use the old-school default.
- width = 1024;
- height = 768;
+ SDL_GetWindowSize(mWindow, &mFullscreenWidth, &mFullscreenHeight);
+ mFullscreenRefresh = -1;
}
+ }
- 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(mRefreshRate == 0) // We failed to get a valid refresh rate above
+ {
+ mRefreshRate = DEFAULT_REFRESH_RATE;
+ }
- if (mWindow)
- {
- mFullscreen = true;
- mFullscreenWidth = mWindow->w;
- mFullscreenHeight = mWindow->h;
- mFullscreenBits = mWindow->format->BitsPerPixel;
- mFullscreenRefresh = -1;
+ /* Grab the window manager specific information */
+#if LL_LINUX
+ if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0)
+ {
+ LL_INFOS() << "Running under X11" << LL_ENDL;
+ mServerProtocol = X11;
- LL_INFOS() << "Running at " << mFullscreenWidth
- << "x" << mFullscreenHeight
- << "x" << mFullscreenBits
- << " @ " << mFullscreenRefresh
- << LL_ENDL;
- }
- else
+ gGLManager.mIsX11 = true;
+
+#if LL_X11
+ sX11Data.xdisplay = (Display *)SDL_GetPointerProperty(SDL_GetWindowProperties(mWindow), SDL_PROP_WINDOW_X11_DISPLAY_POINTER, nullptr);
+ sX11Data.xwindow = (Window)SDL_GetNumberProperty(SDL_GetWindowProperties(mWindow), SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0);
+ sX11Data.xscreen = (int)SDL_GetNumberProperty(SDL_GetWindowProperties(mWindow), SDL_PROP_WINDOW_X11_SCREEN_NUMBER, -1);
+ if (sX11Data.xdisplay && sX11Data.xwindow)
{
- LL_WARNS() << "createContext: fullscreen creation failure. SDL: " << SDL_GetError() << LL_ENDL;
- // No fullscreen support
- mFullscreen = false;
- mFullscreenWidth = -1;
- mFullscreenHeight = -1;
- mFullscreenBits = -1;
- mFullscreenRefresh = -1;
- std::string error = llformat("Unable to run fullscreen at %d x %d.\nRunning in window.", width, height);
- OSMessageBox(error, "Error", OSMB_OK);
}
- }
+#endif
- if(!mFullscreen && (mWindow == NULL))
+ gGLManager.initGLX();
+ }
+ else if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0)
{
- if (width == 0)
- width = 1024;
- if (height == 0)
- width = 768;
+ LL_INFOS() << "Running under Wayland" << LL_ENDL;
+ mServerProtocol = Wayland;
- 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);
- }
+ gGLManager.mIsWayland = true;
- if (!mWindow)
+#if LL_WAYLAND
+ sWaylandData.display = (struct wl_display *)SDL_GetPointerProperty(SDL_GetWindowProperties(mWindow), SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER, nullptr);
+ sWaylandData.surface = (struct wl_surface *)SDL_GetPointerProperty(SDL_GetWindowProperties(mWindow), SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, nullptr);
+ if (sWaylandData.display && sWaylandData.surface)
{
- 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))
- {
- LL_INFOS() << "createContext: SKIPPING - !fullscreen, but +mWindow " << width << "x" << height << "x" << bits << LL_ENDL;
- }
+#endif
- // Detect video memory size.
-# if LL_X11
- gGLManager.mVRAM = x11_detect_VRAM_kb() / 1024;
- if (gGLManager.mVRAM != 0)
- {
- LL_INFOS() << "X11 log-parser detected " << gGLManager.mVRAM << "MB VRAM." << LL_ENDL;
- } else
-# endif // LL_X11
- {
- // fallback to letting SDL detect VRAM.
- // note: I've not seen SDL's detection ever actually find
- // VRAM != 0, but if SDL *does* detect it then that's a bonus.
- gGLManager.mVRAM = video_info->video_mem / 1024;
- if (gGLManager.mVRAM != 0)
+ gGLManager.initEGL();
+
+ // If set (XWayland) remove DISPLAY, this will prompt dullahan to also use Wayland
+ if(getenv("DISPLAY"))
{
- LL_INFOS() << "SDL detected " << gGLManager.mVRAM << "MB VRAM." << LL_ENDL;
+ unsetenv("DISPLAY");
}
}
- // If VRAM is not detected, that is handled later
-
- // *TODO: Now would be an appropriate time to check for some
- // explicitly unsupported cards.
- //const char* RENDERER = (const char*) glGetString(GL_RENDERER);
-
- GLint depthBits, stencilBits, redBits, greenBits, blueBits, alphaBits;
+#endif
- 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
- // least 8 bits each of red,green,blue. Alpha we can be a bit more
- // relaxed about if we have to.
if (colorBits < 32)
{
- close();
setupFailure(
- "Second Life requires True Color (32-bit) to run in a window.\n"
- "Please go to Control Panels -> Display -> Settings and\n"
- "set the screen to 32-bit color.\n"
- "Alternately, if you choose to run fullscreen, Second Life\n"
- "will automatically adjust the screen each time it runs.",
- "Error",
- OSMB_OK);
+ "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)
+ LL_PROFILER_GPU_CONTEXT;
+
+ // Enable vertical sync
+ toggleVSync(enable_vsync);
+
+#if LL_DARWIN
+ setUseMultGL(sUseMultGL);
+
+ // Get vram via CGL on macos
+ gGLManager.mVRAM = getVramSize();
+#endif
+
+ // Set the application icon.
+ SDL_Surface* bmpsurface = Load_BMP_Resource("ll_icon.BMP");
+ if (bmpsurface)
{
- close();
- setupFailure(
- "Second Life is unable to run because it can't get an 8 bit alpha\n"
- "channel. Usually this is due to video card driver issues.\n"
- "Please make sure you have the latest video card drivers installed.\n"
- "Also be sure your monitor is set to True Color (32-bit) in\n"
- "Control Panels -> Display -> Settings.\n"
- "If you continue to receive this message, contact customer service.",
- "Error",
- OSMB_OK);
- return false;
+ SDL_SetWindowIcon(mWindow, bmpsurface);
+ SDL_DestroySurface(bmpsurface);
+ bmpsurface = nullptr;
}
-#endif
-#if LL_X11
- /* Grab the window manager specific information */
- SDL_SysWMinfo info;
- SDL_VERSION(&info.version);
- if ( SDL_GetWMInfo(&info) )
+ SDL_StartTextInput(mWindow);
+ return true;
+}
+
+void* LLWindowSDL::createSharedContext()
+{
+ SDL_PropertiesID props = SDL_CreateProperties();
+ SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, "Second Life OSR Utility");
+ SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, 1);
+ SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, 1);
+ SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_RESIZABLE_BOOLEAN, false);
+ SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_OPENGL_BOOLEAN, true);
+ SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIDDEN_BOOLEAN, true);
+ SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN, false);
+ SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_UTILITY_BOOLEAN, true);
+ SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN, gHiDPISupport);
+
+ auto osr_window = SDL_CreateWindowWithProperties(props);
+ if (osr_window == nullptr)
{
- /* 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;
- }
- else
- {
- LL_WARNS() << "We're not running under X11? Wild."
- << LL_ENDL;
- }
+ SDL_DestroyProperties(props);
+ return nullptr;
}
- else
+ SDL_DestroyProperties(props); // Free properties once window is created
+ SDL_GLContext pContext = SDL_GL_CreateContext(osr_window);
+
+ // Hack to ensure main window context is bound
+ SDL_GL_MakeCurrent(mWindow, mContext);
+
+ if (!pContext)
{
- LL_WARNS() << "We're not running under any known WM. Wild."
- << LL_ENDL;
+ LL_WARNS() << "Creating shared OpenGL context failed!" << LL_ENDL;
+ SDL_DestroyWindow(osr_window);
+ return nullptr;
}
-#endif // LL_X11
+ {
+ LLMutexLock osr_lock(&mOSRMutex);
+ mOSRContexts.emplace(pContext, osr_window);
+ }
- //make sure multisampling is disabled by default
- glDisable(GL_MULTISAMPLE_ARB);
+ LL_DEBUGS() << "Creating shared OpenGL context successful!" << LL_ENDL;
+ return (void*)pContext;
+}
- // 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;
+void LLWindowSDL::makeContextCurrent(void* contextPtr)
+{
+ LLMutexLock osr_lock(&mOSRMutex);
+ auto it = mOSRContexts.find((SDL_GLContext)contextPtr);
+ if(it != mOSRContexts.end())
+ {
+ SDL_GL_MakeCurrent((SDL_Window*)it->second, (SDL_GLContext)it->first);
+ }
+ LL_PROFILER_GPU_CONTEXT;
+}
- // Don't need to get the current gamma, since there's a call that restores it to the system defaults.
- return true;
+void LLWindowSDL::destroySharedContext(void* contextPtr)
+{
+ LLMutexLock osr_lock(&mOSRMutex);
+ auto it = mOSRContexts.find((SDL_GLContext)contextPtr);
+ if(it != mOSRContexts.end())
+ {
+ SDL_GL_DestroyContext((SDL_GLContext)it->first);
+ mDeadOSRWindows.push_back((SDL_Window*)it->second);
+ }
}
+void LLWindowSDL::toggleVSync(bool enable_vsync)
+{
+ if (!enable_vsync)
+ {
+ LL_INFOS("Window") << "Disabling vertical sync" << LL_ENDL;
+ SDL_GL_SetSwapInterval(0);
+ }
+ else
+ {
+ LL_INFOS("Window") << "Enabling vertical sync" << LL_ENDL;
+ SDL_GL_SetSwapInterval(1);
+ }
+}
// 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,9 +515,10 @@ 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, 32, fullscreen, enable_vsync);
if (result)
{
+ gGLManager.initWGL();
gGLManager.initGL();
//start with arrow cursor
@@ -761,69 +536,96 @@ void LLWindowSDL::destroyContext()
{
LL_INFOS() << "destroyContext begins" << LL_ENDL;
-#if LL_X11
- mSDL_Display = NULL;
- mSDL_XWindowID = None;
- Lock_Display = NULL;
- Unlock_Display = NULL;
-#endif // LL_X11
+ {
+ LLMutexLock osr_lock(&mOSRMutex);
+ for(SDL_Window* pWindow : mDeadOSRWindows)
+ {
+ SDL_DestroyWindow(pWindow);
+ }
+ mDeadOSRWindows.clear();
+ }
+
+ // Stop unicode input
+ SDL_StopTextInput(mWindow);
// Clean up remaining GL state before blowing away window
LL_INFOS() << "shutdownGL begins" << LL_ENDL;
gGLManager.shutdownGL();
- LL_INFOS() << "SDL_QuitSS/VID begins" << LL_ENDL;
- SDL_QuitSubSystem(SDL_INIT_VIDEO); // *FIX: this might be risky...
- mWindow = NULL;
+ LL_INFOS() << "Destroying SDL cursors" << LL_ENDL;
+ quitCursors();
+
+ if (mContext)
+ {
+ LL_INFOS() << "Destroying SDL GL Context" << LL_ENDL;
+ SDL_GL_DestroyContext(mContext);
+ mContext = nullptr;
+ }
+ else
+ {
+ LL_INFOS() << "SDL GL Context already destroyed" << LL_ENDL;
+ }
+
+ if (mWindow)
+ {
+ LL_INFOS() << "Destroying SDL Window" << LL_ENDL;
+ SDL_DestroyWindow(mWindow);
+ mWindow = nullptr;
+ }
+ else
+ {
+ LL_INFOS() << "SDL Window already destroyed" << LL_ENDL;
+ }
+ LL_INFOS() << "destroyContext end" << LL_ENDL;
}
LLWindowSDL::~LLWindowSDL()
{
- quitCursors();
destroyContext();
- if(mSupportedResolutions != NULL)
- {
- delete []mSupportedResolutions;
- }
+ delete[] mSupportedResolutions;
- gWindowImplementation = NULL;
+ gWindowImplementation = nullptr;
}
void LLWindowSDL::show()
{
- // *FIX: What to do with SDL?
+ if (mWindow)
+ {
+ SDL_ShowWindow(mWindow);
+ SDL_RaiseWindow(mWindow);
+ }
}
void LLWindowSDL::hide()
{
- // *FIX: What to do with SDL?
+ if (mWindow)
+ {
+ SDL_HideWindow(mWindow);
+ }
}
-//virtual
void LLWindowSDL::minimize()
{
- // *FIX: What to do with SDL?
+ if (mWindow)
+ {
+ SDL_MinimizeWindow(mWindow);
+ }
}
-//virtual
void LLWindowSDL::restore()
{
- // *FIX: What to do with SDL?
+ if (mWindow)
+ {
+ SDL_RestoreWindow(mWindow);
+ }
}
-
// close() destroys all OS-specific code associated with a window.
// Usually called from LLWindowManager::destroyWindow()
void LLWindowSDL::close()
{
- // Is window is already closed?
- // if (!mWindow)
- // {
- // return;
- // }
-
// Make sure cursor is visible and we haven't mangled the clipping state.
setMouseClipping(false);
showCursor();
@@ -833,134 +635,127 @@ void LLWindowSDL::close()
bool LLWindowSDL::isValid()
{
- return (mWindow != NULL);
+ return mWindow != nullptr;
}
bool LLWindowSDL::getVisible()
{
- bool result = false;
-
- // *FIX: This isn't really right...
- // Then what is?
+ bool result = true;
if (mWindow)
{
- result = true;
+ SDL_WindowFlags flags = SDL_GetWindowFlags(mWindow);
+ if (flags & SDL_WINDOW_HIDDEN)
+ {
+ result = false;
+ }
}
-
- return(result);
+ return result;
}
bool LLWindowSDL::getMinimized()
{
bool result = false;
-
- if (mWindow && (1 == mIsMinimized))
+ if (mWindow)
{
- result = true;
+ SDL_WindowFlags flags = SDL_GetWindowFlags(mWindow);
+ if (flags & SDL_WINDOW_MINIMIZED)
+ {
+ result = true;
+ }
}
- return(result);
+ return result;
}
bool LLWindowSDL::getMaximized()
{
bool result = false;
-
if (mWindow)
{
- // TODO
+ SDL_WindowFlags flags = SDL_GetWindowFlags(mWindow);
+ if (flags & SDL_WINDOW_MAXIMIZED)
+ {
+ result = true;
+ }
}
- return(result);
+ return result;
}
bool LLWindowSDL::maximize()
{
- // TODO
+ if (mWindow)
+ {
+ SDL_MaximizeWindow(mWindow);
+ return true;
+ }
return false;
}
-bool LLWindowSDL::getFullscreen()
-{
- return mFullscreen;
-}
-
bool LLWindowSDL::getPosition(LLCoordScreen *position)
{
- // *FIX: can anything be done with this?
- position->mX = 0;
- position->mY = 0;
- return true;
+ if (mWindow)
+ {
+ SDL_GetWindowPosition(mWindow, &position->mX, &position->mY);
+ return true;
+ }
+ return false;
}
bool LLWindowSDL::getSize(LLCoordScreen *size)
{
if (mWindow)
{
- size->mX = mWindow->w;
- size->mY = mWindow->h;
- return (true);
+ SDL_GetWindowSize(mWindow, &size->mX, &size->mY);
+ return true;
}
- return (false);
+ return false;
}
bool LLWindowSDL::getSize(LLCoordWindow *size)
{
if (mWindow)
{
- size->mX = mWindow->w;
- size->mY = mWindow->h;
- return (true);
+ SDL_GetWindowSizeInPixels(mWindow, &size->mX, &size->mY);
+ return true;
}
- return (false);
+ return false;
}
bool LLWindowSDL::setPosition(const LLCoordScreen position)
{
- if(mWindow)
+ if (mWindow)
{
- // *FIX: (?)
- //MacMoveWindow(mWindow, position.mX, position.mY, false);
+ SDL_SetWindowPosition(mWindow, position.mX, position.mY);
+ return true;
}
- return true;
+ return false;
}
-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;
- }
+ SDL_WindowFlags winFlags = SDL_GetWindowFlags(pWin);
- return false;
+ if( winFlags & SDL_WINDOW_MAXIMIZED)
+ SDL_RestoreWindow(pWin);
+
+ SDL_SetWindowSize(pWin, newSize.mX, newSize.mY);
+ 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,8 +763,9 @@ void LLWindowSDL::swapBuffers()
{
if (mWindow)
{
- SDL_GL_SwapBuffers();
+ SDL_GL_SwapWindow(mWindow);
}
+ LL_PROFILER_GPU_COLLECT;
}
U32 LLWindowSDL::getFSAASamples()
@@ -984,22 +780,23 @@ void LLWindowSDL::setFSAASamples(const U32 samples)
F32 LLWindowSDL::getGamma()
{
- return 1/mGamma;
+ return 1.f / mGamma;
}
bool LLWindowSDL::restoreGamma()
{
- //CGDisplayRestoreColorSyncSettings();
- SDL_SetGamma(1.0f, 1.0f, 1.0f);
return true;
}
bool LLWindowSDL::setGamma(const F32 gamma)
{
- mGamma = gamma;
- if (mGamma == 0) mGamma = 0.1f;
- mGamma = 1/mGamma;
- SDL_SetGamma(mGamma, mGamma, mGamma);
+ if (mWindow)
+ {
+ mGamma = gamma;
+ if (mGamma == 0)
+ mGamma = 0.1f;
+ mGamma = 1.f / mGamma;
+ }
return true;
}
@@ -1008,12 +805,13 @@ bool LLWindowSDL::isCursorHidden()
return mCursorHidden;
}
-
-
// Constrains the mouse to the window.
-void LLWindowSDL::setMouseClipping( bool b )
+void LLWindowSDL::setMouseClipping(bool b)
{
- //SDL_WM_GrabInput(b ? SDL_GRAB_ON : SDL_GRAB_OFF);
+ if (mWindow)
+ {
+ SDL_SetWindowMouseGrab(mWindow, b);
+ }
}
// virtual
@@ -1021,38 +819,16 @@ void LLWindowSDL::setMinSize(U32 min_width, U32 min_height, bool enforce_immedia
{
LLWindow::setMinSize(min_width, min_height, enforce_immediately);
-#if LL_X11
- // Set the minimum size limits for X11 window
- // so the window manager doesn't allow resizing below those limits.
- XSizeHints* hints = XAllocSizeHints();
- hints->flags |= PMinSize;
- hints->min_width = mMinWindowWidth;
- hints->min_height = mMinWindowHeight;
-
- XSetWMNormalHints(mSDL_Display, mSDL_XWindowID, hints);
-
- XFree(hints);
-#endif
+ if (mWindow && min_width > 0 && min_height > 0)
+ {
+ SDL_SetWindowMinimumSize(mWindow, mMinWindowWidth, mMinWindowHeight);
+ }
}
bool LLWindowSDL::setCursorPosition(const LLCoordWindow position)
{
- bool result = true;
- LLCoordScreen screen_pos;
-
- if (!convertCoords(position, &screen_pos))
- {
- return false;
- }
-
- //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);
-
- //LL_INFOS() << llformat("llcw %d,%d -> scr %d,%d", position.mX, position.mY, screen_pos.mX, screen_pos.mY) << LL_ENDL;
-
- return result;
+ SDL_WarpMouseInWindow(mWindow, (F32)position.mX, (F32)position.mY);
+ return true;
}
bool LLWindowSDL::getCursorPosition(LLCoordWindow *position)
@@ -1060,54 +836,34 @@ bool LLWindowSDL::getCursorPosition(LLCoordWindow *position)
//Point cursor_point;
LLCoordScreen screen_pos;
- //GetMouse(&cursor_point);
- int x, y;
+ float x, y;
SDL_GetMouseState(&x, &y);
- screen_pos.mX = x;
- screen_pos.mY = y;
+ screen_pos.mX = (S32)x;
+ screen_pos.mY = (S32)y;
return convertCoords(screen_pos, position);
}
-
F32 LLWindowSDL::getNativeAspectRatio()
{
-#if 0
+ if (mOverrideAspectRatio > 0.f)
+ {
+ return mOverrideAspectRatio;
+ }
+ else if (mNativeAspectRatio > 0.f)
+ {
+ // we grabbed this value at startup, based on the user's desktop settings
+ return mNativeAspectRatio;
+ }
+
// 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.
-
- // New assumptions:
- // - pixels are square (the only reasonable choice, really)
- // - The user runs their display at a native resolution, so the resolution of the display
- // when the app is launched has an aspect ratio that matches the monitor.
-
- //RN: actually, the assumption that there are no ridiculous resolutions (above the display's native capabilities) has
- // been born out in my experience.
- // Pixels are often not square (just ask the people who run their LCDs at 1024x768 or 800x600 when running fullscreen, like me)
- // The ordering of display list is a blind assumption though, so we should check for max values
- // Things might be different on the Mac though, so I'll defer to MBW
-
- // The constructor for this class grabs the aspect ratio of the monitor before doing any resolution
- // switching, and stashes it in mOriginalAspectRatio. Here, we just return it.
-
- if (mOverrideAspectRatio > 0.f)
- {
- return mOverrideAspectRatio;
- }
-
- return mOriginalAspectRatio;
}
F32 LLWindowSDL::getPixelAspectRatio()
@@ -1130,104 +886,26 @@ F32 LLWindowSDL::getPixelAspectRatio()
// dialogs are still usable in fullscreen.
void LLWindowSDL::beforeDialog()
{
- bool running_x11 = false;
-#if LL_X11
- running_x11 = (mSDL_XWindowID != None);
-#endif //LL_X11
-
LL_INFOS() << "LLWindowSDL::beforeDialog()" << LL_ENDL;
if (SDLReallyCaptureInput(false)) // must ungrab input so popup works!
{
- if (mFullscreen)
- {
- // need to temporarily go non-fullscreen; bless SDL
- // for providing a SDL_WM_ToggleFullScreen() - though
- // it only works in X11
- if (running_x11 && mWindow)
- {
- SDL_WM_ToggleFullScreen(mWindow);
- }
- }
- }
-
-#if LL_X11
- if (mSDL_Display)
- {
- // Everything that we/SDL asked for should happen before we
- // potentially hand control over to GTK.
- maybe_lock_display();
- XSync(mSDL_Display, False);
- maybe_unlock_display();
+ if (mFullscreen && mWindow )
+ SDL_SetWindowFullscreen( mWindow, 0 );
}
-#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();
}
void LLWindowSDL::afterDialog()
{
- bool running_x11 = false;
-#if LL_X11
- running_x11 = (mSDL_XWindowID != None);
-#endif //LL_X11
-
LL_INFOS() << "LLWindowSDL::afterDialog()" << LL_ENDL;
- maybe_unlock_display();
-
- if (mFullscreen)
- {
- // need to restore fullscreen mode after dialog - only works
- // in X11
- if (running_x11 && mWindow)
- {
- SDL_WM_ToggleFullScreen(mWindow);
- }
- }
+ if (mFullscreen && mWindow )
+ SDL_SetWindowFullscreen( mWindow, 0 );
}
-
-#if LL_X11
-// set/reset the XWMHints flag for 'urgency' that usually makes the icon flash
-void LLWindowSDL::x11_set_urgent(bool urgent)
-{
- if (mSDL_Display && !mFullscreen)
- {
- XWMHints *wm_hints;
-
- LL_INFOS() << "X11 hint for urgency, " << urgent << LL_ENDL;
-
- maybe_lock_display();
- wm_hints = XGetWMHints(mSDL_Display, mSDL_XWindowID);
- if (!wm_hints)
- wm_hints = XAllocWMHints();
-
- if (urgent)
- wm_hints->flags |= XUrgencyHint;
- else
- wm_hints->flags &= ~XUrgencyHint;
-
- XSetWMHints(mSDL_Display, mSDL_XWindowID, wm_hints);
- XFree(wm_hints);
- XSync(mSDL_Display, False);
- maybe_unlock_display();
- }
-}
-#endif // LL_X11
-
void LLWindowSDL::flashIcon(F32 seconds)
{
-#if !LL_X11
- LL_INFOS() << "Stub LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL;
-#else
- LL_INFOS() << "X11 LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL;
+ LL_INFOS() << "LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL;
F32 remaining_time = mFlashTimer.getRemainingTimeF32();
if (remaining_time < seconds)
@@ -1235,132 +913,71 @@ void LLWindowSDL::flashIcon(F32 seconds)
mFlashTimer.reset();
mFlashTimer.setTimerExpirySec(remaining_time);
- x11_set_urgent(true);
+ SDL_FlashWindow(mWindow, SDL_FLASH_UNTIL_FOCUSED);
mFlashing = true;
-#endif // LL_X11
}
-
-#if LL_GTK
-bool LLWindowSDL::isClipboardTextAvailable()
+void LLWindowSDL::maybeStopFlashIcon()
{
- if (ll_try_gtk_init())
+ if (mFlashing && mFlashTimer.hasExpired())
{
- GtkClipboard * const clipboard =
- gtk_clipboard_get(GDK_NONE);
- return gtk_clipboard_wait_is_text_available(clipboard) ?
- true : false;
+ mFlashing = false;
+ SDL_FlashWindow( mWindow, SDL_FLASH_CANCEL );
}
- return false; // failure
}
-bool LLWindowSDL::pasteTextFromClipboard(LLWString &text)
+bool LLWindowSDL::isClipboardTextAvailable()
{
- if (ll_try_gtk_init())
+ return SDL_HasClipboardText();
+}
+
+bool LLWindowSDL::pasteTextFromClipboard(LLWString &dst)
+{
+ if (isClipboardTextAvailable())
{
- GtkClipboard * const clipboard =
- gtk_clipboard_get(GDK_NONE);
- gchar * const data = gtk_clipboard_wait_for_text(clipboard);
+ char* data = SDL_GetClipboardText();
if (data)
{
- text = LLWString(utf8str_to_wstring(data));
- g_free(data);
+ dst = LLWString(utf8str_to_wstring(data));
+ SDL_free(data);
return true;
}
}
- return false; // failure
+ return false;
}
-bool LLWindowSDL::copyTextToClipboard(const LLWString &text)
+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
+ const std::string utf8 = wstring_to_utf8str(text);
+ return SDL_SetClipboardText(utf8.c_str());
}
-
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
+ return SDL_HasPrimarySelectionText();
}
-bool LLWindowSDL::pasteTextFromPrimary(LLWString &text)
+bool LLWindowSDL::pasteTextFromPrimary(LLWString &dst)
{
- if (ll_try_gtk_init())
+ if (isPrimaryTextAvailable())
{
- GtkClipboard * const clipboard =
- gtk_clipboard_get(GDK_SELECTION_PRIMARY);
- gchar * const data = gtk_clipboard_wait_for_text(clipboard);
+ char* data = SDL_GetPrimarySelectionText();
if (data)
{
- text = LLWString(utf8str_to_wstring(data));
- g_free(data);
+ dst = LLWString(utf8str_to_wstring(data));
+ SDL_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
-}
-
-bool LLWindowSDL::pasteTextFromClipboard(LLWString &dst)
-{
- return false; // unsupported
-}
-
-bool LLWindowSDL::copyTextToClipboard(const LLWString &s)
-{
- return false; // unsupported
-}
-
-bool LLWindowSDL::isPrimaryTextAvailable()
-{
- return false; // unsupported
-}
-
-bool LLWindowSDL::pasteTextFromPrimary(LLWString &dst)
-{
- return false; // unsupported
+ return false;
}
-bool LLWindowSDL::copyTextToPrimary(const LLWString &s)
+bool LLWindowSDL::copyTextToPrimary(const LLWString& text)
{
- return false; // unsupported
+ const std::string utf8 = wstring_to_utf8str(text);
+ return SDL_SetPrimarySelectionText(utf8.c_str());
}
-#endif // LL_GTK
-
LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_resolutions)
{
if (!mSupportedResolutions)
@@ -1368,28 +985,21 @@ 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)) )
- {
- int count = 0;
- while (*modes && count<MAX_NUM_RESOLUTIONS) // they're sorted biggest to smallest, so find end...
- {
- modes++;
- count++;
- }
-
- while (count--)
- {
- modes--;
- SDL_Rect *r = *modes;
- int w = r->w;
- int h = r->h;
+ SDL_DisplayID display = SDL_GetPrimaryDisplay();
+ int num_modes = 0;
+ SDL_DisplayMode **modes = SDL_GetFullscreenDisplayModes(display, &num_modes);
+ num_modes = llclamp(num_modes, 0, MAX_NUM_RESOLUTIONS);
+ if (modes) {
+ for (int i = 0; i < num_modes; ++i) {
+ SDL_DisplayMode *mode = modes[i];
+ int w = mode->w;
+ int h = mode->h;
if ((w >= 800) && (h >= 600))
{
// make sure we don't add the same resolution multiple times!
if ( (mNumSupportedResolutions == 0) ||
- ((mSupportedResolutions[mNumSupportedResolutions-1].mWidth != w) &&
- (mSupportedResolutions[mNumSupportedResolutions-1].mHeight != h)) )
+ ((mSupportedResolutions[mNumSupportedResolutions-1].mWidth != w) &&
+ (mSupportedResolutions[mNumSupportedResolutions-1].mHeight != h)) )
{
mSupportedResolutions[mNumSupportedResolutions].mWidth = w;
mSupportedResolutions[mNumSupportedResolutions].mHeight = h;
@@ -1397,6 +1007,7 @@ LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_reso
}
}
}
+ SDL_free(modes);
}
}
@@ -1404,13 +1015,42 @@ LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_reso
return mSupportedResolutions;
}
+//static
+std::vector<std::string> LLWindowSDL::getDisplaysResolutionList()
+{
+ std::vector<std::string> ret;
+ if (gWindowImplementation)
+ {
+ S32 resolutionCount = 0;
+ LLWindowResolution* resolutionList = gWindowImplementation->getSupportedResolutions(resolutionCount);
+ if (resolutionList != nullptr)
+ {
+ for (S32 i = 0; i < resolutionCount; i++)
+ {
+ const LLWindowResolution& resolution = resolutionList[i];
+ ret.push_back(std::to_string(resolution.mWidth) + "x" + std::to_string(resolution.mHeight));
+ }
+ }
+ }
+ return ret;
+}
+
+
bool LLWindowSDL::convertCoords(LLCoordGL from, LLCoordWindow *to)
{
if (!to)
return false;
- to->mX = from.mX;
- to->mY = mWindow->h - from.mY - 1;
+ if (!mWindow)
+ return false;
+
+ S32 height;
+ SDL_GetWindowSizeInPixels(mWindow, nullptr, &height);
+
+ float pixel_scale = SDL_GetWindowPixelDensity(mWindow);
+
+ to->mX = from.mX / pixel_scale;
+ to->mY = (height - from.mY - 1) / pixel_scale;
return true;
}
@@ -1420,8 +1060,15 @@ bool LLWindowSDL::convertCoords(LLCoordWindow from, LLCoordGL* to)
if (!to)
return false;
- to->mX = from.mX;
- to->mY = mWindow->h - from.mY - 1;
+ if (!mWindow)
+ return false;
+ S32 height;
+ SDL_GetWindowSize(mWindow, nullptr, &height);
+
+ float pixel_scale = SDL_GetWindowPixelDensity(mWindow);
+
+ to->mX = from.mX * pixel_scale;
+ to->mY = (height - from.mY - 1) * pixel_scale;
return true;
}
@@ -1434,7 +1081,7 @@ bool LLWindowSDL::convertCoords(LLCoordScreen from, LLCoordWindow* to)
// In the fullscreen case, window and screen coordinates are the same.
to->mX = from.mX;
to->mY = from.mY;
- return (true);
+ return true;
}
bool LLWindowSDL::convertCoords(LLCoordWindow from, LLCoordScreen *to)
@@ -1445,29 +1092,26 @@ bool LLWindowSDL::convertCoords(LLCoordWindow from, LLCoordScreen *to)
// In the fullscreen case, window and screen coordinates are the same.
to->mX = from.mX;
to->mY = from.mY;
- return (true);
+ return true;
}
bool LLWindowSDL::convertCoords(LLCoordScreen from, LLCoordGL *to)
{
LLCoordWindow window_coord;
- return(convertCoords(from, &window_coord) && convertCoords(window_coord, to));
+ return convertCoords(from, &window_coord) && convertCoords(window_coord, to);
}
bool LLWindowSDL::convertCoords(LLCoordGL from, LLCoordScreen *to)
{
LLCoordWindow window_coord;
- return(convertCoords(from, &window_coord) && convertCoords(window_coord, to));
+ return convertCoords(from, &window_coord) && convertCoords(window_coord, to);
}
-
-
-
void LLWindowSDL::setupFailure(const std::string& text, const std::string& caption, U32 type)
{
- destroyContext();
+ close();
OSMessageBox(text, caption, type);
}
@@ -1482,13 +1126,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,64 +1141,32 @@ bool LLWindowSDL::SDLReallyCaptureInput(bool capture)
LL_WARNS() << "ReallyCapture count was < 0" << LL_ENDL;
}
+ bool newGrab = wantGrab;
if (!mFullscreen) /* only bother if we're windowed anyway */
{
-#if LL_X11
- if (mSDL_Display)
+ int result;
+ if (wantGrab)
{
- /* we dirtily mix raw X11 with SDL so that our pointer
- isn't (as often) constrained to the limits of the
- window while grabbed, which feels nicer and
- hopefully eliminates some reported 'sticky pointer'
- problems. We use raw X11 instead of
- SDL_WM_GrabInput() because the latter constrains
- the pointer to the window and also steals all
- *keyboard* input from the window manager, which was
- frustrating users. */
- int result;
- if (wantmode == SDL_GRAB_ON)
- {
- //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);
- maybe_unlock_display();
- if (GrabSuccess == result)
- newmode = SDL_GRAB_ON;
- else
- newmode = SDL_GRAB_OFF;
- } else if (wantmode == SDL_GRAB_OFF)
- {
- //LL_INFOS() << "X11 POINTER UNGRABBY" << LL_ENDL;
- newmode = SDL_GRAB_OFF;
- //newmode = SDL_WM_GrabInput(SDL_GRAB_OFF);
-
- 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;
+ // LL_INFOS() << "X11 POINTER GRABBY" << LL_ENDL;
+ result = SDL_SetWindowMouseGrab(mWindow, true);
+ if (0 == result)
+ newGrab = true;
+ else
+ newGrab = false;
+ }
+ else
+ {
+ newGrab = false;
+ result = SDL_SetWindowMouseGrab(mWindow, false);
+ }
}
+ // pretend we got what we wanted, when really we don't care.
// 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 +1184,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)
@@ -1595,371 +1207,265 @@ U32 LLWindowSDL::SDLCheckGrabbyKeys(SDLKey keysym, bool gain)
return mGrabbyKeyFlags;
}
-
-void check_vm_bloat()
+// virtual
+void LLWindowSDL::processMiscNativeEvents()
{
-#if LL_LINUX
- // watch our own VM and RSS sizes, warn if we bloated rapidly
- static const std::string STATS_FILE = "/proc/self/stat";
- FILE *fp = fopen(STATS_FILE.c_str(), "r");
- if (fp)
{
- static long long last_vm_size = 0;
- static long long last_rss_size = 0;
- const long long significant_vm_difference = 250 * 1024*1024;
- const long long significant_rss_difference = 50 * 1024*1024;
- long long this_vm_size = 0;
- long long this_rss_size = 0;
-
- ssize_t res;
- size_t dummy;
- char *ptr = NULL;
- for (int i=0; i<22; ++i) // parse past the values we don't want
+ LLMutexLock osr_lock(&mOSRMutex);
+ for(SDL_Window* pWindow : mDeadOSRWindows)
{
- res = getdelim(&ptr, &dummy, ' ', fp);
- if (-1 == res)
- {
- LL_WARNS() << "Unable to parse " << STATS_FILE << LL_ENDL;
- goto finally;
- }
- free(ptr);
- ptr = NULL;
+ SDL_DestroyWindow(pWindow);
}
- // 23rd space-delimited entry is vsize
- res = getdelim(&ptr, &dummy, ' ', fp);
- llassert(ptr);
- if (-1 == res)
+ mDeadOSRWindows.clear();
+ }
+}
+
+void LLWindowSDL::gatherInput()
+{
+ // This is for the case where SDL is not driving the main event loop
+ if(!gSDLMainHandled)
+ {
+ SDL_Event event;
+
+ // Handle all outstanding SDL events
+ while (SDL_PollEvent(&event))
{
- LL_WARNS() << "Unable to parse " << STATS_FILE << LL_ENDL;
- goto finally;
+ handleEvent(event);
}
- this_vm_size = atoll(ptr);
- free(ptr);
- ptr = NULL;
- // 24th space-delimited entry is RSS
- res = getdelim(&ptr, &dummy, ' ', fp);
- llassert(ptr);
- if (-1 == res)
+ }
+
+ updateCursor();
+
+ // This is a good time to stop flashing the icon if our mFlashTimer has
+ // expired.
+ if (mFlashing && mFlashTimer.hasExpired())
+ {
+ SDL_FlashWindow(mWindow, SDL_FLASH_CANCEL);
+ mFlashing = false;
+ }
+}
+
+SDL_AppResult LLWindowSDL::handleEvent(const SDL_Event& event)
+{
+ switch(event.type)
+ {
+ case SDL_EVENT_MOUSE_MOTION:
{
- LL_WARNS() << "Unable to parse " << STATS_FILE << LL_ENDL;
- goto finally;
+ LLCoordWindow winCoord(llfloor(event.motion.x), llfloor(event.motion.y));
+ LLCoordGL openGlCoord;
+ convertCoords(winCoord, &openGlCoord);
+ mCallbacks->handleMouseMove(this, openGlCoord, gKeyboard->currentMask(true));
+ break;
}
- this_rss_size = getpagesize() * atoll(ptr);
- free(ptr);
- ptr = NULL;
-
- LL_INFOS() << "VM SIZE IS NOW " << (this_vm_size/(1024*1024)) << " MB, RSS SIZE IS NOW " << (this_rss_size/(1024*1024)) << " MB" << LL_ENDL;
- if (llabs(last_vm_size - this_vm_size) >
- significant_vm_difference)
+ case SDL_EVENT_MOUSE_WHEEL:
{
- if (this_vm_size > last_vm_size)
+ if(event.wheel.integer_y != 0)
{
- LL_WARNS() << "VM size grew by " << (this_vm_size - last_vm_size)/(1024*1024) << " MB in last frame" << LL_ENDL;
+ mCallbacks->handleScrollWheel(this, -event.wheel.integer_y);
}
- else
+ if (event.wheel.integer_x != 0)
{
- LL_INFOS() << "VM size shrank by " << (last_vm_size - this_vm_size)/(1024*1024) << " MB in last frame" << LL_ENDL;
+ mCallbacks->handleScrollHWheel(this, -event.wheel.integer_x);
}
+ break;
}
- if (llabs(last_rss_size - this_rss_size) >
- significant_rss_difference)
+ case SDL_EVENT_MOUSE_BUTTON_DOWN:
{
- if (this_rss_size > last_rss_size)
+ LLCoordWindow winCoord(llfloor(event.button.x), llfloor(event.button.y));
+ LLCoordGL openGlCoord;
+ convertCoords(winCoord, &openGlCoord);
+ MASK mask = gKeyboard->currentMask(true);
+
+ if (event.button.button == SDL_BUTTON_LEFT) // left
+ {
+ if (event.button.clicks == 2)
+ mCallbacks->handleDoubleClick(this, openGlCoord, mask);
+ else
+ mCallbacks->handleMouseDown(this, openGlCoord, mask);
+ }
+ else if (event.button.button == SDL_BUTTON_RIGHT)
{
- LL_WARNS() << "RSS size grew by " << (this_rss_size - last_rss_size)/(1024*1024) << " MB in last frame" << LL_ENDL;
+ mCallbacks->handleRightMouseDown(this, openGlCoord, mask);
+ }
+ else if (event.button.button == SDL_BUTTON_MIDDLE) // middle
+ {
+ mCallbacks->handleMiddleMouseDown(this, openGlCoord, mask);
}
else
{
- LL_INFOS() << "RSS size shrank by " << (last_rss_size - this_rss_size)/(1024*1024) << " MB in last frame" << LL_ENDL;
+ mCallbacks->handleOtherMouseDown(this, openGlCoord, mask, event.button.button);
}
- }
-
- last_rss_size = this_rss_size;
- last_vm_size = this_vm_size;
-finally:
- if (NULL != ptr)
- {
- free(ptr);
- ptr = NULL;
+ break;
}
- fclose(fp);
- }
-#endif // LL_LINUX
-}
+ case SDL_EVENT_MOUSE_BUTTON_UP:
+ {
+ LLCoordWindow winCoord(llfloor(event.button.x), llfloor(event.button.y));
+ LLCoordGL openGlCoord;
+ convertCoords(winCoord, &openGlCoord);
+ MASK mask = gKeyboard->currentMask(true);
-// 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));
+ if (event.button.button == SDL_BUTTON_LEFT) // left
+ {
+ mCallbacks->handleMouseUp(this, openGlCoord, mask);
+ }
+ else if (event.button.button == SDL_BUTTON_RIGHT) // right
+ {
+ mCallbacks->handleRightMouseUp(this, openGlCoord, mask);
+ }
+ else if (event.button.button == SDL_BUTTON_MIDDLE) // middle
+ {
+ mCallbacks->handleMiddleMouseUp(this, openGlCoord, mask);
+ }
+ else
+ {
+ mCallbacks->handleOtherMouseUp(this, openGlCoord, mask, event.button.button);
+ }
- // 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());
+ break;
+ }
- setlocale(LC_ALL, saved_locale.c_str() );
- }
-#endif // LL_GTK
+ case SDL_EVENT_KEY_DOWN:
+ {
+ mKeyVirtualKey = event.key.key;
+ mKeyModifiers = event.key.mod;
- // hack - doesn't belong here - but this is just for debugging
- if (getenv("LL_DEBUG_BLOAT"))
- {
- check_vm_bloat();
- }
-}
+ if (mKeyVirtualKey == SDLK_RETURN2 || mKeyVirtualKey == SDLK_KP_ENTER)
+ {
+ mKeyVirtualKey = SDLK_RETURN;
+ }
-void LLWindowSDL::gatherInput()
-{
- const Uint32 CLICK_THRESHOLD = 300; // milliseconds
- static int leftClick = 0;
- static int rightClick = 0;
- static Uint32 lastLeftDown = 0;
- static Uint32 lastRightDown = 0;
- SDL_Event event;
+ gKeyboard->handleKeyDown(mKeyVirtualKey, mKeyModifiers);
- // Handle all outstanding SDL events
- while (SDL_PollEvent(&event))
- {
- switch (event.type)
- {
- case SDL_MOUSEMOTION:
+ if (mKeyVirtualKey == SDLK_RETURN)
{
- LLCoordWindow winCoord(event.button.x, event.button.y);
- LLCoordGL openGlCoord;
- convertCoords(winCoord, &openGlCoord);
- MASK mask = gKeyboard->currentMask(true);
- mCallbacks->handleMouseMove(this, openGlCoord, mask);
- break;
+ // fix return key not working when capslock, scrolllock or numlock are enabled
+ mKeyModifiers &= (~(SDL_KMOD_NUM | SDL_KMOD_CAPS | SDL_KMOD_MODE | SDL_KMOD_SCROLL));
+ mCallbacks->handleUnicodeChar(mKeyVirtualKey, gKeyboard->currentMask(false));
}
- case SDL_KEYDOWN:
- mKeyScanCode = event.key.keysym.scancode;
- mKeyVirtualKey = event.key.keysym.unicode;
- mKeyModifiers = event.key.keysym.mod;
-
- gKeyboard->handleKeyDown(event.key.keysym.sym, event.key.keysym.mod);
// part of the fix for SL-13243
- if (SDLCheckGrabbyKeys(event.key.keysym.sym, true) != 0)
+ if (SDLCheckGrabbyKeys(mKeyVirtualKey, true) != 0)
SDLReallyCaptureInput(true);
+ break;
+ }
+
+ case SDL_EVENT_KEY_UP:
+ {
+ mKeyVirtualKey = event.key.key;
+ mKeyModifiers = event.key.mod;
- if (event.key.keysym.unicode)
+ if (mKeyVirtualKey == SDLK_RETURN2 || mKeyVirtualKey == SDLK_KP_ENTER)
{
- handleUnicodeUTF16(event.key.keysym.unicode,
- gKeyboard->currentMask(false));
+ mKeyVirtualKey = SDLK_RETURN;
}
- break;
- case SDL_KEYUP:
- mKeyScanCode = event.key.keysym.scancode;
- mKeyVirtualKey = event.key.keysym.unicode;
- mKeyModifiers = event.key.keysym.mod;
-
- if (SDLCheckGrabbyKeys(event.key.keysym.sym, false) == 0)
+ gKeyboard->handleKeyUp(mKeyVirtualKey, mKeyModifiers);
+ if (SDLCheckGrabbyKeys(mKeyVirtualKey, false) == 0)
SDLReallyCaptureInput(false); // part of the fix for SL-13243
-
- gKeyboard->handleKeyUp(event.key.keysym.sym, event.key.keysym.mod);
break;
+ }
- case SDL_MOUSEBUTTONDOWN:
- {
- bool isDoubleClick = false;
- LLCoordWindow winCoord(event.button.x, event.button.y);
- LLCoordGL openGlCoord;
- convertCoords(winCoord, &openGlCoord);
- MASK mask = gKeyboard->currentMask(true);
-
- if (event.button.button == SDL_BUTTON_LEFT) // SDL doesn't manage double clicking...
- {
- Uint32 now = SDL_GetTicks();
- if ((now - lastLeftDown) > CLICK_THRESHOLD)
- leftClick = 1;
- else
- {
- if (++leftClick >= 2)
- {
- leftClick = 0;
- isDoubleClick = true;
- }
- }
- lastLeftDown = now;
- }
- else if (event.button.button == SDL_BUTTON_RIGHT)
- {
- Uint32 now = SDL_GetTicks();
- if ((now - lastRightDown) > CLICK_THRESHOLD)
- rightClick = 1;
- else
- {
- if (++rightClick >= 2)
- {
- rightClick = 0;
- isDoubleClick = true;
- }
- }
- lastRightDown = now;
- }
-
- if (event.button.button == SDL_BUTTON_LEFT) // left
- {
- if (isDoubleClick)
- mCallbacks->handleDoubleClick(this, openGlCoord, mask);
- else
- mCallbacks->handleMouseDown(this, openGlCoord, mask);
- }
-
- else if (event.button.button == SDL_BUTTON_RIGHT) // right
- {
- mCallbacks->handleRightMouseDown(this, openGlCoord, mask);
- }
-
- else if (event.button.button == SDL_BUTTON_MIDDLE) // middle
- {
- mCallbacks->handleMiddleMouseDown(this, openGlCoord, mask);
- }
- else if (event.button.button == 4) // mousewheel up...thanks to X11 for making SDL consider these "buttons".
- mCallbacks->handleScrollWheel(this, -1);
- else if (event.button.button == 5) // mousewheel down...thanks to X11 for making SDL consider these "buttons".
- mCallbacks->handleScrollWheel(this, 1);
-
- break;
- }
-
- case SDL_MOUSEBUTTONUP:
+ case SDL_EVENT_TEXT_INPUT:
+ {
+ auto string = utf8str_to_wstring(event.text.text);
+ MASK current_mask = gKeyboard->currentMask(false);
+ for (auto key : string)
{
- LLCoordWindow winCoord(event.button.x, event.button.y);
- LLCoordGL openGlCoord;
- convertCoords(winCoord, &openGlCoord);
- MASK mask = gKeyboard->currentMask(true);
-
- if (event.button.button == SDL_BUTTON_LEFT) // left
- mCallbacks->handleMouseUp(this, openGlCoord, mask);
- else if (event.button.button == SDL_BUTTON_RIGHT) // right
- mCallbacks->handleRightMouseUp(this, openGlCoord, mask);
- else if (event.button.button == SDL_BUTTON_MIDDLE) // middle
- mCallbacks->handleMiddleMouseUp(this, openGlCoord, mask);
- // don't handle mousewheel here...
-
- break;
+ mKeyVirtualKey = key;
+ mCallbacks->handleUnicodeChar(key, current_mask);
}
+ 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?
- {
- LL_INFOS() << "Handling a resize event: " << event.resize.w <<
- "x" << event.resize.h << LL_ENDL;
-
- S32 width = llmax(event.resize.w, (S32)mMinWindowWidth);
- S32 height = llmax(event.resize.h, (S32)mMinWindowHeight);
-
- // *FIX: I'm not sure this is necessary!
- mWindow = SDL_SetVideoMode(width, height, 32, mSDLFlags);
- if (!mWindow)
+ case SDL_EVENT_WINDOW_EXPOSED:
{
- // *FIX: More informative dialog?
- LL_INFOS() << "Could not recreate context after resize! Quitting..." << LL_ENDL;
- if(mCallbacks->handleCloseRequest(this, false))
- {
- // Get the app to initiate cleanup.
- mCallbacks->handleQuit(this);
- // The app is responsible for calling destroyWindow when done with GL
- }
- break;
+ mCallbacks->handlePaint(this, 0, 0, 0, 0);
+ break;
}
- mCallbacks->handleResize(this, width, height);
- break;
- }
- case SDL_ACTIVEEVENT:
- if (event.active.state & SDL_APPINPUTFOCUS)
- {
- // 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;
+ case SDL_EVENT_WINDOW_RESIZED:
+ {
+ LL_INFOS() << "Handling a resize event: " << event.window.data1 << "x" << event.window.data2 << LL_ENDL;
+ F32 pixel_density = SDL_GetWindowPixelDensity(mWindow);
+ S32 width = llmax(event.window.data1, (S32)mMinWindowWidth) * pixel_density;
+ S32 height = llmax(event.window.data2, (S32)mMinWindowHeight) * pixel_density;
- if (mHaveInputFocus)
- mCallbacks->handleFocus(this);
- else
- mCallbacks->handleFocusLost(this);
- }
- }
- if (event.active.state & SDL_APPACTIVE)
- {
- // Change in iconification/minimization state.
- if ((!event.active.gain) != mIsMinimized)
+ mCallbacks->handleResize(this, width, height);
+ break;
+ }
+ case SDL_EVENT_WINDOW_MOUSE_ENTER:
+ break;
+ case SDL_EVENT_WINDOW_MOUSE_LEAVE:
+ mCallbacks->handleMouseLeave(this);
+ break;
+ case SDL_EVENT_WINDOW_FOCUS_GAINED:
+ //SDL_SetWindowKeyboardGrab(mWindow, true);
+ mCallbacks->handleFocus(this);
+ break;
+ case SDL_EVENT_WINDOW_FOCUS_LOST:
+ mCallbacks->handleFocusLost(this);
+ //SDL_SetWindowKeyboardGrab(mWindow, false);
+ break;
+ case SDL_EVENT_WINDOW_RESTORED:
+ mCallbacks->handleActivate(this, true);
+ break;
+ case SDL_EVENT_WINDOW_MAXIMIZED:
+ mCallbacks->handleActivate(this, true);
+ break;
+ case SDL_EVENT_WINDOW_MINIMIZED:
+ mCallbacks->handleActivate(this, false);
+ break;
+ case SDL_EVENT_WINDOW_DISPLAY_CHANGED:
+ {
+ // Update refresh rate when changing monitors
+ const SDL_DisplayMode* displayMode = SDL_GetCurrentDisplayMode(event.window.data1);
+ if(displayMode)
{
- mIsMinimized = (!event.active.gain);
-
- mCallbacks->handleActivate(this, !mIsMinimized);
- LL_INFOS() << "SDL deiconification state switched to " << bool(event.active.gain) << LL_ENDL;
+ mRefreshRate = ll_round(displayMode->refresh_rate);
+ mNativeAspectRatio = ((F32)displayMode->w) / ((F32)displayMode->h);
}
- else
+ mCallbacks->handleDisplayChanged();
+ break;
+ }
+ case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED:
+ {
+ S32 w, h = 0;
+ SDL_GetWindowSizeInPixels(mWindow, &w, &h);
+ mCallbacks->handleDPIChanged(this, getSystemUISize(), w, h);
+ break;
+ }
+ case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
+ {
+ if(mCallbacks->handleCloseRequest(this, true))
{
- LL_INFOS() << "Ignored bogus redundant SDL deiconification state switch to " << bool(event.active.gain) << LL_ENDL;
+ // Get the app to initiate cleanup.
+ mCallbacks->handleQuit(this);
+ // The app is responsible for calling destroyWindow when done with GL
}
- }
- break;
-
- case SDL_QUIT:
- if(mCallbacks->handleCloseRequest(this, true))
- {
- // Get the app to initiate cleanup.
- mCallbacks->handleQuit(this);
- // The app is responsible for calling destroyWindow when done with GL
- }
- break;
- default:
- //LL_INFOS() << "Unhandled SDL event type " << event.type << LL_ENDL;
- break;
+ break;
}
+ default:
+ break;
}
- updateCursor();
+ return SDL_APP_CONTINUE;
+}
-#if LL_X11
- // This is a good time to stop flashing the icon if our mFlashTimer has
- // expired.
- if (mFlashing && mFlashTimer.hasExpired())
- {
- x11_set_urgent(false);
- mFlashing = false;
- }
-#endif // LL_X11
+// static
+SDL_AppResult LLWindowSDL::handleEvents(const SDL_Event& event)
+{
+ if(!gWindowImplementation) return SDL_APP_CONTINUE;
+
+ return gWindowImplementation->handleEvent(event);
}
static SDL_Cursor *makeSDLCursorFromBMP(const char *filename, int hotx, int hoty)
{
- SDL_Cursor *sdlcursor = NULL;
+ SDL_Cursor *sdlcursor = nullptr;
SDL_Surface *bmpsurface;
// Load cursor pixel data from BMP file
@@ -1968,21 +1474,32 @@ 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;
- cursurface = SDL_CreateRGBSurface (SDL_SWSURFACE,
- bmpsurface->w,
- bmpsurface->h,
- 32,
- SDL_SwapLE32(0xFFU),
- SDL_SwapLE32(0xFF00U),
- SDL_SwapLE32(0xFF0000U),
- SDL_SwapLE32(0xFF000000U));
- SDL_FillRect(cursurface, NULL, SDL_SwapLE32(0x00000000U));
+ << bmpsurface->w << "x" << bmpsurface->h << LL_ENDL;
+ SDL_PixelFormat pix_format = SDL_GetPixelFormatForMasks(32,
+ SDL_Swap32LE(0xFFU),
+ SDL_Swap32LE(0xFF00U),
+ SDL_Swap32LE(0xFF0000U),
+ SDL_Swap32LE(0xFF000000U));
+ if (pix_format == SDL_PIXELFORMAT_UNKNOWN)
+ {
+ return nullptr;
+ }
+
+ const SDL_PixelFormatDetails* pix_format_details = SDL_GetPixelFormatDetails(pix_format);
+ if(!pix_format_details)
+ {
+ return nullptr;
+ }
+
+ cursurface = SDL_CreateSurface(bmpsurface->w,
+ bmpsurface->h,
+ pix_format);
+ SDL_FillSurfaceRect(cursurface, nullptr, SDL_Swap32LE(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))
+ if (SDL_BlitSurface(bmpsurface, nullptr,
+ cursurface, nullptr))
{
// n.b. we already checked that width is a multiple of 8.
const int bitmap_bytes = (cursurface->w * cursurface->h) / 8;
@@ -1997,33 +1514,33 @@ 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*pix_format_details->bytes_per_pixel;
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 {
LL_WARNS() << "CURSOR BLIT FAILURE, cursurface: " << cursurface << LL_ENDL;
}
- SDL_FreeSurface(cursurface);
- SDL_FreeSurface(bmpsurface);
+ SDL_DestroySurface(cursurface);
+ SDL_DestroySurface(bmpsurface);
} else {
LL_WARNS() << "CURSOR LOAD FAILURE " << filename << LL_ENDL;
}
@@ -2033,12 +1550,6 @@ static SDL_Cursor *makeSDLCursorFromBMP(const char *filename, int hotx, int hoty
void LLWindowSDL::updateCursor()
{
- if (ATIbug) {
- // cursor-updating is very flaky when this bug is
- // present; do nothing.
- return;
- }
-
if (mCurrentCursor != mNextCursor)
{
if (mNextCursor < UI_CURSOR_COUNT)
@@ -2050,37 +1561,40 @@ void LLWindowSDL::updateCursor()
sdlcursor = mSDLCursors[UI_CURSOR_ARROW];
if (sdlcursor)
SDL_SetCursor(sdlcursor);
- } else {
+
+ mCurrentCursor = mNextCursor;
+ }
+ else
+ {
LL_WARNS() << "Tried to set invalid cursor number " << mNextCursor << LL_ENDL;
}
- mCurrentCursor = mNextCursor;
}
}
void LLWindowSDL::initCursors()
{
- int i;
// Blank the cursor pointer array for those we may miss.
- for (i=0; i<UI_CURSOR_COUNT; ++i)
+ for (int i=0; i<UI_CURSOR_COUNT; ++i)
{
- mSDLCursors[i] = NULL;
+ mSDLCursors[i] = nullptr;
}
+
// Pre-make an SDL cursor for each of the known cursor types.
// We hardcode the hotspots - to avoid that we'd have to write
// a .cur file loader.
// NOTE: SDL doesn't load RLE-compressed BMP files.
- mSDLCursors[UI_CURSOR_ARROW] = makeSDLCursorFromBMP("llarrow.BMP",0,0);
- mSDLCursors[UI_CURSOR_WAIT] = makeSDLCursorFromBMP("wait.BMP",12,15);
- mSDLCursors[UI_CURSOR_HAND] = makeSDLCursorFromBMP("hand.BMP",7,10);
- mSDLCursors[UI_CURSOR_IBEAM] = makeSDLCursorFromBMP("ibeam.BMP",15,16);
- mSDLCursors[UI_CURSOR_CROSS] = makeSDLCursorFromBMP("cross.BMP",16,14);
- mSDLCursors[UI_CURSOR_SIZENWSE] = makeSDLCursorFromBMP("sizenwse.BMP",14,17);
- mSDLCursors[UI_CURSOR_SIZENESW] = makeSDLCursorFromBMP("sizenesw.BMP",17,17);
- mSDLCursors[UI_CURSOR_SIZEWE] = makeSDLCursorFromBMP("sizewe.BMP",16,14);
- mSDLCursors[UI_CURSOR_SIZENS] = makeSDLCursorFromBMP("sizens.BMP",17,16);
- mSDLCursors[UI_CURSOR_SIZEALL] = makeSDLCursorFromBMP("sizeall.BMP", 17, 17);
- mSDLCursors[UI_CURSOR_NO] = makeSDLCursorFromBMP("llno.BMP",8,8);
- mSDLCursors[UI_CURSOR_WORKING] = makeSDLCursorFromBMP("working.BMP",12,15);
+ mSDLCursors[UI_CURSOR_ARROW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_DEFAULT);
+ mSDLCursors[UI_CURSOR_WAIT] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAIT);
+ mSDLCursors[UI_CURSOR_HAND] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_POINTER);
+ mSDLCursors[UI_CURSOR_IBEAM] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_TEXT);
+ mSDLCursors[UI_CURSOR_CROSS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_CROSSHAIR);
+ mSDLCursors[UI_CURSOR_SIZENWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NWSE_RESIZE);
+ mSDLCursors[UI_CURSOR_SIZENESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NESW_RESIZE);
+ mSDLCursors[UI_CURSOR_SIZEWE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_EW_RESIZE);
+ mSDLCursors[UI_CURSOR_SIZENS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NS_RESIZE);
+ mSDLCursors[UI_CURSOR_SIZEALL] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_MOVE);
+ mSDLCursors[UI_CURSOR_NO] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NOT_ALLOWED);
+ mSDLCursors[UI_CURSOR_WORKING] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_PROGRESS);
mSDLCursors[UI_CURSOR_TOOLGRAB] = makeSDLCursorFromBMP("lltoolgrab.BMP",2,13);
mSDLCursors[UI_CURSOR_TOOLLAND] = makeSDLCursorFromBMP("lltoolland.BMP",1,6);
mSDLCursors[UI_CURSOR_TOOLFOCUS] = makeSDLCursorFromBMP("lltoolfocus.BMP",8,5);
@@ -2113,32 +1627,28 @@ void LLWindowSDL::initCursors()
mSDLCursors[UI_CURSOR_TOOLPATHFINDING_PATH_END] = makeSDLCursorFromBMP("lltoolpathfindingpathend.BMP", 16, 16);
mSDLCursors[UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD] = makeSDLCursorFromBMP("lltoolpathfindingpathendadd.BMP", 16, 16);
mSDLCursors[UI_CURSOR_TOOLNO] = makeSDLCursorFromBMP("llno.BMP",8,8);
-
- if (getenv("LL_ATI_MOUSE_CURSOR_BUG") != NULL) {
- LL_INFOS() << "Disabling cursor updating due to LL_ATI_MOUSE_CURSOR_BUG" << LL_ENDL;
- ATIbug = true;
- }
}
void LLWindowSDL::quitCursors()
{
- int i;
if (mWindow)
{
- for (i=0; i<UI_CURSOR_COUNT; ++i)
+ for (int i=0; i<UI_CURSOR_COUNT; ++i)
{
if (mSDLCursors[i])
{
- SDL_FreeCursor(mSDLCursors[i]);
- mSDLCursors[i] = NULL;
+ SDL_DestroyCursor(mSDLCursors[i]);
+ mSDLCursors[i] = nullptr;
}
}
- } else {
+ }
+ else
+ {
// SDL doesn't refcount cursors, so if the window has
// already been destroyed then the cursors have gone with it.
LL_INFOS() << "Skipping quitCursors: mWindow already gone." << LL_ENDL;
- for (i=0; i<UI_CURSOR_COUNT; ++i)
- mSDLCursors[i] = NULL;
+ for (int i=0; i<UI_CURSOR_COUNT; ++i)
+ mSDLCursors[i] = nullptr;
}
}
@@ -2167,7 +1677,7 @@ void LLWindowSDL::hideCursor()
// LL_INFOS() << "hideCursor: hiding" << LL_ENDL;
mCursorHidden = true;
mHideCursorPermanent = true;
- SDL_ShowCursor(0);
+ SDL_HideCursor();
}
else
{
@@ -2182,7 +1692,7 @@ void LLWindowSDL::showCursor()
// LL_INFOS() << "showCursor: showing" << LL_ENDL;
mCursorHidden = false;
mHideCursorPermanent = false;
- SDL_ShowCursor(1);
+ SDL_ShowCursor();
}
else
{
@@ -2207,8 +1717,6 @@ void LLWindowSDL::hideCursorUntilMouseMove()
}
}
-
-
//
// LLSplashScreenSDL - I don't think we'll bother to implement this; it's
// fairly obsolete at this point.
@@ -2233,133 +1741,62 @@ 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();
+ if(gWindowImplementation != nullptr)
+ gWindowImplementation->beforeDialog();
- //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
+ int btn{0};
+ if(SDL_ShowMessageBox( &oData, &btn ))
{
- 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 != nullptr)
+ gWindowImplementation->afterDialog();
+ return btn;
}
- if(gWindowImplementation != NULL)
+ if(gWindowImplementation != nullptr)
gWindowImplementation->afterDialog();
- return rtn;
+ 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!
@@ -2367,140 +1804,21 @@ LLSD LLWindowSDL::getNativeKeyData()
// what a plugin under GDK under Qt under SL under SDL under X11 considers
// a 'native' modifier mask. this has been sort of reverse-engineered... they *appear*
// to match GDK consts, but that may be co-incidence.
- modifiers |= (mKeyModifiers & KMOD_LSHIFT) ? 0x0001 : 0;
- modifiers |= (mKeyModifiers & KMOD_RSHIFT) ? 0x0001 : 0;// munge these into the same shift
- modifiers |= (mKeyModifiers & KMOD_CAPS) ? 0x0002 : 0;
- modifiers |= (mKeyModifiers & KMOD_LCTRL) ? 0x0004 : 0;
- modifiers |= (mKeyModifiers & KMOD_RCTRL) ? 0x0004 : 0;// munge these into the same ctrl
- modifiers |= (mKeyModifiers & KMOD_LALT) ? 0x0008 : 0;// untested
- modifiers |= (mKeyModifiers & KMOD_RALT) ? 0x0008 : 0;// untested
+ modifiers |= (mKeyModifiers & SDL_KMOD_LSHIFT) ? 0x0001 : 0;
+ modifiers |= (mKeyModifiers & SDL_KMOD_RSHIFT) ? 0x0001 : 0;// munge these into the same shift
+ modifiers |= (mKeyModifiers & SDL_KMOD_CAPS) ? 0x0002 : 0;
+ modifiers |= (mKeyModifiers & SDL_KMOD_LCTRL) ? 0x0004 : 0;
+ modifiers |= (mKeyModifiers & SDL_KMOD_RCTRL) ? 0x0004 : 0;// munge these into the same ctrl
+ modifiers |= (mKeyModifiers & SDL_KMOD_LALT) ? 0x0008 : 0;// untested
+ modifiers |= (mKeyModifiers & SDL_KMOD_RALT) ? 0x0008 : 0;// untested
// *todo: test ALTs - I don't have a case for testing these. Do you?
// *todo: NUM? - I don't care enough right now (and it's not a GDK modifier).
- result["scan_code"] = (S32)mKeyScanCode;
- result["virtual_key"] = (S32)mKeyVirtualKey;
+ result["virtual_key"] = (S32)mKeyVirtualKey;
+ result["virtual_key_win"] = (S32)LLKeyboardSDL::mapSDLtoWin( 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);
-}
-#endif // LL_GTK
-
-#if LL_LINUX
-// 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)
-{
- char* const argv[] = {(char*)cmd.c_str(), (char*)arg.c_str(), NULL};
- fflush(NULL);
- pid_t pid = fork();
- if (pid == 0)
- { // 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);
- // end ourself by running the command
- execv(cmd.c_str(), argv); /* Flawfinder: ignore */
- // if execv returns at all, there was a problem.
- LL_WARNS() << "execv failure when trying to start " << cmd << LL_ENDL;
- _exit(1); // _exit because we don't want atexit() clean-up!
- } else {
- if (pid > 0)
- {
- // parent - wait for child to die
- int childExitStatus;
- waitpid(pid, &childExitStatus, 0);
- } else {
- LL_WARNS() << "fork failure." << LL_ENDL;
- }
- }
+ return result;
}
-#endif
// Open a URL with the user's default web browser.
// Must begin with protocol identifier.
@@ -2525,56 +1843,26 @@ void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async)
LL_INFOS() << "spawn_web_browser: " << escaped_url << LL_ENDL;
-#if LL_LINUX
-# if LL_X11
- if (mSDL_Display)
+ if (!SDL_OpenURL(escaped_url.c_str()))
{
- maybe_lock_display();
- // Just in case - before forking.
- XSync(mSDL_Display, False);
- maybe_unlock_display();
+ LL_WARNS() << "spawn_web_browser failed with error: " << SDL_GetError() << LL_ENDL;
}
-# endif // LL_X11
-
- std::string cmd, arg;
- cmd = gDirUtilp->getAppRODataDir();
- cmd += gDirUtilp->getDirDelimiter();
- cmd += "etc";
- cmd += gDirUtilp->getDirDelimiter();
- cmd += "launch_url.sh";
- arg = escaped_url;
- exec_cmd(cmd, arg);
-#endif // LL_LINUX
LL_INFOS() << "spawn_web_browser returning." << LL_ENDL;
}
-
-void *LLWindowSDL::getPlatformWindow()
+void* LLWindowSDL::getPlatformWindow()
{
-#if LL_GTK && LL_LLMOZLIB_ENABLED
- if (LLWindowSDL::ll_try_gtk_init())
+ void* ret = nullptr;
+ if (mWindow)
{
- 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;
+#if LL_WINDOWS
+ ret = SDL_GetPointerProperty(SDL_GetWindowProperties(mWindow), SDL_PROP_WINDOW_WIN32_HWND_POINTER, nullptr);
+#elif LL_DARWIN
+ ret = SDL_GetPointerProperty(SDL_GetWindowProperties(mWindow), SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, nullptr);
+#endif
}
-#endif // LL_GTK && LL_LLMOZLIB_ENABLED
- // Unixoid mozilla really needs GTK.
- return NULL;
+ return ret;
}
void LLWindowSDL::bringToFront()
@@ -2582,20 +1870,17 @@ void LLWindowSDL::bringToFront()
// This is currently used when we are 'launched' to a specific
// map position externally.
LL_INFOS() << "bringToFront" << LL_ENDL;
-#if LL_X11
- if (mSDL_Display && !mFullscreen)
+ if (mWindow && !mFullscreen)
{
- maybe_lock_display();
- XRaiseWindow(mSDL_Display, mSDL_XWindowID);
- XSync(mSDL_Display, False);
- maybe_unlock_display();
+ SDL_RaiseWindow(mWindow);
}
-#endif // LL_X11
}
//static
std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList()
{
+ std::vector<std::string> rtns;
+#if LL_LINUX
// Use libfontconfig to find us a nice ordered list of fallback fonts
// specific to this system.
std::string final_fallback("/usr/share/fonts/truetype/kochi/kochi-gothic.ttf");
@@ -2612,9 +1897,9 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList()
// renderable range if for some reason our FreeType actually fails
// to use some of the fonts we want it to.
const bool elide_unicode_coverage = true;
- std::vector<std::string> rtns;
- FcFontSet *fs = NULL;
- FcPattern *sortpat = NULL;
+
+ FcFontSet *fs = nullptr;
+ FcPattern *sortpat = nullptr;
LL_INFOS() << "Getting system font list from FontConfig..." << LL_ENDL;
@@ -2623,7 +1908,7 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList()
// of languages that can be displayed, but ensures that their
// preferred language is rendered from a single consistent font where
// possible.
- FL_Locale *locale = NULL;
+ FL_Locale *locale = nullptr;
FL_Success success = FL_FindLocale(&locale, FL_MESSAGES);
if (success != 0)
{
@@ -2634,10 +1919,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);
@@ -2654,8 +1939,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);
+ fs = FcFontSort(nullptr, sortpat, elide_unicode_coverage, nullptr, &result);
FcPatternDestroy(sortpat);
}
@@ -2668,10 +1952,7 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList()
for (int i=0; i<fs->nfont; ++i)
{
FcChar8 *filename;
- if (FcResultMatch == FcPatternGetString(fs->fonts[i],
- FC_FILE, 0,
- &filename)
- && filename)
+ if (FcResultMatch == FcPatternGetString(fs->fonts[i], FC_FILE, 0, &filename) && filename)
{
rtns.push_back(std::string((const char*)filename));
if (rtns.size() >= max_font_count_cutoff)
@@ -2682,16 +1963,101 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList()
}
LL_DEBUGS() << "Using font list: " << LL_ENDL;
- for (std::vector<std::string>::iterator it = rtns.begin();
- it != rtns.end();
- ++it)
+ for (auto it = rtns.begin(); it != rtns.end(); ++it)
{
LL_DEBUGS() << " file: " << *it << LL_ENDL;
}
+
LL_INFOS() << "Using " << rtns.size() << "/" << found_font_count << " system fonts." << LL_ENDL;
rtns.push_back(final_fallback);
+#endif
return rtns;
}
-#endif // LL_SDL
+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_SetTextInputArea(mWindow, &r, 0);
+}
+
+F32 LLWindowSDL::getSystemUISize()
+{
+ if(mWindow)
+ {
+ F32 scale = SDL_GetWindowDisplayScale(mWindow);
+ if (scale > 0.0f)
+ {
+ return scale;
+ }
+ }
+ return 1.f;
+}
+
+#if LL_DARWIN
+// static
+U64 LLWindowSDL::getVramSize()
+{
+ CGLRendererInfoObj info = 0;
+ GLint vram_megabytes = 0;
+ int num_renderers = 0;
+ CGLError the_err = CGLQueryRendererInfo (CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay), &info, &num_renderers);
+ if(0 == the_err)
+ {
+ // The name, uses, and other platform definitions of gGLManager.mVRAM suggest that this is supposed to be total vram in MB,
+ // rather than, say, just the texture memory. The two exceptions are:
+ // 1. LLAppViewer::getViewerInfo() puts the value in a field labeled "TEXTURE_MEMORY"
+ // 2. For years, this present function used kCGLRPTextureMemoryMegabytes
+ // Now we use kCGLRPVideoMemoryMegabytes to bring it in line with everything else (except thatone label).
+ CGLDescribeRenderer (info, 0, kCGLRPVideoMemoryMegabytes, &vram_megabytes);
+ CGLDestroyRendererInfo (info);
+ }
+ else
+ {
+ vram_megabytes = 256;
+ }
+
+ return (U64)vram_megabytes; // return value is in megabytes.
+}
+
+//static
+void LLWindowSDL::setUseMultGL(bool use_mult_gl)
+{
+ bool was_enabled = sUseMultGL;
+
+ sUseMultGL = use_mult_gl;
+
+ if (gGLManager.mInited)
+ {
+ CGLContextObj ctx = CGLGetCurrentContext();
+ //enable multi-threaded OpenGL (whether or not sUseMultGL actually changed)
+ if (sUseMultGL)
+ {
+ CGLError cgl_err = CGLEnable( ctx, kCGLCEMPEngine);
+ if (cgl_err != kCGLNoError )
+ {
+ LL_INFOS("GLInit") << "Multi-threaded OpenGL not available." << LL_ENDL;
+ sUseMultGL = false;
+ }
+ else
+ {
+ LL_INFOS("GLInit") << "Multi-threaded OpenGL enabled." << LL_ENDL;
+ }
+ }
+ else if (was_enabled)
+ {
+ CGLDisable( ctx, kCGLCEMPEngine);
+ LL_INFOS("GLInit") << "Multi-threaded OpenGL disabled." << LL_ENDL;
+ }
+ }
+}
+#endif
+
diff --git a/indra/llwindow/llwindowsdl.h b/indra/llwindow/llwindowsdl.h
index 521d52df30..4d4a7a5f65 100644
--- a/indra/llwindow/llwindowsdl.h
+++ b/indra/llwindow/llwindowsdl.h
@@ -31,142 +31,163 @@
#include "llwindow.h"
#include "lltimer.h"
+#include "llmutex.h"
-#include "SDL/SDL.h"
-#include "SDL/SDL_endian.h"
+#include "SDL3/SDL.h"
+#include "SDL3/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"
+#ifdef LL_WAYLAND
+#include <wayland-client-protocol.h>
#endif
-// AssertMacros.h does bad things.
-#include "fix_macros.h"
-#undef verify
-#undef require
+#if LL_X11
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#endif
+class LLPreeditor;
-class LLWindowSDL : public LLWindow
+class LLWindowSDL final : 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*/ bool isWrapMouse() const override { return true; }
- /*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);
+ void show() override;
+ void hide() override;
+ void restore() override;
+
+ void close() override;
+
+ bool getVisible() override;
+
+ bool getMinimized() override;
+
+ bool getMaximized() override;
+
+ bool maximize() override;
+ void minimize() override;
+
+ 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;
- /*virtual*/ bool isClipboardTextAvailable();
- /*virtual*/ bool pasteTextFromClipboard(LLWString &dst);
- /*virtual*/ bool copyTextToClipboard(const LLWString & src);
+ bool getCursorPosition(LLCoordWindow *position) override;
+ bool isWrapMouse() const override { return true; }
+ void showCursor() override;
+ void hideCursor() override;
+ bool isCursorHidden() override;
- /*virtual*/ bool isPrimaryTextAvailable();
- /*virtual*/ bool pasteTextFromPrimary(LLWString &dst);
- /*virtual*/ bool copyTextToPrimary(const LLWString & src);
+ void showCursorFromMouseMove() override;
+ void hideCursorUntilMouseMove() override;
- /*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() {};
+ void updateCursor() override;
- /*virtual*/ void delayInputProcessing() { };
+ 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;
+ void maybeStopFlashIcon();
+
+ F32 getGamma() override;
+ bool setGamma(const F32 gamma) override; // Set the gamma
+ bool restoreGamma() override; // Restore original gamma table (before updating gamma)
+
+ U32 getFSAASamples() override;
+ void setFSAASamples(const U32 samples) override;
+
+ void processMiscNativeEvents() override;
+
+ void gatherInput() override;
+
+ SDL_AppResult handleEvent(const SDL_Event& event);
+ static SDL_AppResult handleEvents(const SDL_Event& event);
+
+ void swapBuffers() override;
+
+ void delayInputProcessing() override {};
// handy coordinate space conversion routines
- /*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordWindow *to);
- /*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordScreen *to);
- /*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordGL *to);
- /*virtual*/ bool convertCoords(LLCoordGL from, LLCoordWindow *to);
- /*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordGL *to);
- /*virtual*/ bool convertCoords(LLCoordGL from, LLCoordScreen *to);
+ bool convertCoords(LLCoordScreen from, LLCoordWindow *to) override;
+ bool convertCoords(LLCoordWindow from, LLCoordScreen *to) override;
+ bool convertCoords(LLCoordWindow from, LLCoordGL *to) override;
+ bool convertCoords(LLCoordGL from, LLCoordWindow *to) override;
+ bool convertCoords(LLCoordScreen from, LLCoordGL *to) override;
+ bool convertCoords(LLCoordGL from, LLCoordScreen *to) override;
+
+ LLWindowResolution *getSupportedResolutions(S32 &num_resolutions) override;
- /*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions);
- /*virtual*/ F32 getNativeAspectRatio();
- /*virtual*/ F32 getPixelAspectRatio();
- /*virtual*/ void setNativeAspectRatio(F32 ratio) { mOverrideAspectRatio = ratio; }
+ F32 getNativeAspectRatio() override;
+ F32 getPixelAspectRatio() override;
+ void setNativeAspectRatio(F32 ratio) override { mOverrideAspectRatio = ratio; }
- /*virtual*/ void beforeDialog();
- /*virtual*/ void afterDialog();
+ void beforeDialog() override;
+ void afterDialog() override;
- /*virtual*/ bool dialogColorPicker(F32 *r, F32 *g, F32 *b);
+ bool dialogColorPicker(F32 *r, F32 *g, F32 *b) override;
- /*virtual*/ void *getPlatformWindow();
- /*virtual*/ void bringToFront();
+ void *getPlatformWindow() override;
- /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async);
+ void bringToFront() override;
+
+ void setLanguageTextInput(const LLCoordGL& pos) override;
+
+ void spawnWebBrowser(const std::string &escaped_url, bool async) override;
+
+ void setTitle(const std::string title) override;
static std::vector<std::string> getDynamicFallbackFontList();
- // Not great that these are public, but they have to be accessible
- // by non-class code and it's better than making them global.
-#if LL_X11
- Window mSDL_XWindowID;
- Display *mSDL_Display;
-#endif
- void (*Lock_Display)(void);
- void (*Unlock_Display)(void);
+ void *createSharedContext() override;
+ void makeContextCurrent(void *context) override;
+ void destroySharedContext(void *context) override;
+ void toggleVSync(bool enable_vsync) override;
-#if LL_GTK
- // Lazily initialize and check the runtime GTK version for goodness.
- static bool ll_try_gtk_init(void);
-#endif // LL_GTK
+ F32 getSystemUISize() override;
-#if LL_X11
- static Window get_SDL_XWindowID(void);
- static Display* get_SDL_Display(void);
-#endif // LL_X11
+ static std::vector<std::string> getDisplaysResolutionList();
-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();
+#if LL_DARWIN
+ static U64 getVramSize();
+ static void setUseMultGL(bool use_mult_gl);
+
+ static bool sUseMultGL;
+#endif
- /*virtual*/ bool isValid();
- /*virtual*/ LLSD getNativeKeyData();
+protected:
+ LLWindowSDL(LLWindowCallbacks *callbacks,
+ const std::string &title, const std::string& name, 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);
- void initCursors();
- void quitCursors();
- void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size);
+ ~LLWindowSDL();
- // Changes display resolution. Returns true if successful
- bool setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
+ bool isValid() override;
- // Go back to last fullscreen display resolution.
- bool setFullscreenResolution();
+ LLSD getNativeKeyData() override;
- bool shouldPostQuit() { return mPostQuit; }
+ void initCursors();
+ void quitCursors();
protected:
//
@@ -174,47 +195,67 @@ 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 fixWindowSize(void);
- U32 SDLCheckGrabbyKeys(SDLKey keysym, bool gain);
+
+ void setupFailure(const std::string &text, const std::string &caption, U32 type);
+
bool SDLReallyCaptureInput(bool capture);
+ U32 SDLCheckGrabbyKeys(U32 keysym, bool gain);
//
// Platform specific variables
//
- U32 mGrabbyKeyFlags;
- int mReallyCapturedCount;
- SDL_Surface * mWindow;
- 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;
+ U32 mGrabbyKeyFlags = 0;
+ S32 mReallyCapturedCount = 0;
+ SDL_Window *mWindow = nullptr;
+ SDL_GLContext mContext;
+ SDL_Cursor *mSDLCursors[UI_CURSOR_COUNT];
- int mSDLFlags;
-
- SDL_Cursor* mSDLCursors[UI_CURSOR_COUNT];
- int mHaveInputFocus; /* 0=no, 1=yes, else unknown */
- int mIsMinimized; /* 0=no, 1=yes, else unknown */
+ std::string mWindowTitle;
+ F32 mNativeAspectRatio = 0.0f;
+ F32 mOverrideAspectRatio = 0.0f;
+ F32 mGamma = 0.0f;
+ U32 mFSAASamples = 0;
friend class LLWindowManager;
private:
-#if LL_X11
- void x11_set_urgent(bool urgent);
- bool mFlashing;
+ bool mFlashing = false;
LLTimer mFlashTimer;
-#endif //LL_X11
+ U32 mKeyVirtualKey = 0;
+ U32 mKeyModifiers = SDL_KMOD_NONE;
- U32 mKeyScanCode;
- U32 mKeyVirtualKey;
- SDLMod mKeyModifiers;
-};
+ LLMutex mOSRMutex;
+ std::unordered_map<SDL_GLContext, SDL_Window*> mOSRContexts;
+ std::list<SDL_Window*> mDeadOSRWindows;
+
+ void tryFindFullscreenSize(int &aWidth, int &aHeight);
+ enum EServerProtocol{ X11, Wayland, Unknown };
+ EServerProtocol mServerProtocol = Unknown;
+public:
+#if LL_X11
+ // X11
+ struct X11_DATA
+ {
+ Display* xdisplay = nullptr;
+ Window xwindow = 0;
+ int xscreen = -1;
+ };
+ static X11_DATA sX11Data;
+#endif
+
+#if LL_WAYLAND
+ // Wayland
+ struct WAYLAND_DATA
+ {
+ struct wl_display* display = nullptr;
+ struct wl_surface* surface = nullptr;
+ };
+ static WAYLAND_DATA sWaylandData;
+#endif
+};
class LLSplashScreenSDL : public LLSplashScreen
{
@@ -222,9 +263,9 @@ public:
LLSplashScreenSDL();
virtual ~LLSplashScreenSDL();
- /*virtual*/ void showImpl();
- /*virtual*/ void updateImpl(const std::string& mesg);
- /*virtual*/ void hideImpl();
+ void showImpl() override;
+ void updateImpl(const std::string& mesg) override;
+ void hideImpl() override;
};
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 3c7b83bde4..e947948c57 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -227,6 +227,7 @@ HKL LLWindowWin32::sWinInputLocale = 0;
DWORD LLWindowWin32::sWinIMEConversionMode = IME_CMODE_NATIVE;
DWORD LLWindowWin32::sWinIMESentenceMode = IME_SMODE_AUTOMATIC;
LLCoordWindow LLWindowWin32::sWinIMEWindowPosition(-1,-1);
+HMODULE LLWindowWin32::sGLDLLHandle = nullptr;
static HWND sWindowHandleForMessageBox = NULL;
@@ -529,7 +530,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
mWindowThread = new LLWindowWin32Thread();
//MAINT-516 -- force a load of opengl32.dll just in case windows went sideways
- LoadLibrary(L"opengl32.dll");
+ sGLDLLHandle = LoadLibrary(L"opengl32.dll");
// Request high-performance GPU before creating OpenGL context
// This increases probability of discrete GPU being used when
@@ -1779,6 +1780,8 @@ const S32 max_format = (S32)num_formats - 1;
return false;
}
+ gGLManager.initWGL(); // Reinit WGL functions once we have our full context
+
if (!gGLManager.initGL())
{
LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBVideoDrvErr"), LLError::LLUserWarningMsg::ERROR_INIT_FAILED);
@@ -5260,6 +5263,18 @@ F32 LLWindowWin32::getSystemUISize()
}
//static
+PROC WINAPI LLWindowWin32::getProcAddress(const char* func)
+{
+ PROC ret_func = wglGetProcAddress(func);
+ if (!ret_func && sGLDLLHandle)
+ {
+ // Try to fallback to OpenGL32.dll
+ ret_func = GetProcAddress(sGLDLLHandle, func);
+ }
+ return ret_func;
+}
+
+//static
std::vector<std::string> LLWindowWin32::getDisplaysResolutionList()
{
return sMonitorInfo.getResolutionsList();
diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h
index defa90d1a3..956dd510dd 100644
--- a/indra/llwindow/llwindowwin32.h
+++ b/indra/llwindow/llwindowwin32.h
@@ -130,6 +130,7 @@ public:
LLWindowCallbacks::DragNDropResult completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url );
+ static PROC WINAPI getProcAddress(const char* func);
static std::vector<std::string> getDisplaysResolutionList();
static std::vector<std::string> getDynamicFallbackFontList();
static void setDPIAwareness();
@@ -265,6 +266,8 @@ protected:
bool mMouseVanish;
+ static HMODULE sGLDLLHandle;
+
// Cached values of GetWindowRect and GetClientRect to be used by app thread
void updateWindowRect();
RECT mRect;