summaryrefslogtreecommitdiff
path: root/indra/llwindow
diff options
context:
space:
mode:
authorErik Kundiman <erik@megapahit.org>2026-09-01 18:35:23 +0800
committerErik Kundiman <erik@megapahit.org>2026-09-04 21:58:53 +0800
commit00bb3bb6f07660bd914d29a1389342bb3060d254 (patch)
tree431f574922494d2201718f13085f17bc6bd7fb42 /indra/llwindow
parenta8636720129952c10cf49ab80da21bf8b340b96c (diff)
parent4ef9f8f14b35ed388c294d53767a0dca0e890924 (diff)
Merge remote-tracking branch 'secondlife/release/26.4' into 26.4
Diffstat (limited to 'indra/llwindow')
-rw-r--r--indra/llwindow/CMakeLists.txt224
-rw-r--r--indra/llwindow/llkeyboard.cpp6
-rw-r--r--indra/llwindow/llkeyboard.h16
-rw-r--r--indra/llwindow/llkeyboardheadless.cpp17
-rw-r--r--indra/llwindow/llkeyboardheadless.h21
-rw-r--r--indra/llwindow/llkeyboardmacosx.cpp13
-rw-r--r--indra/llwindow/llkeyboardmacosx.h16
-rw-r--r--indra/llwindow/llkeyboardsdl.cpp691
-rw-r--r--indra/llwindow/llkeyboardsdl.h38
-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.cpp64
-rw-r--r--indra/llwindow/llwindow.h15
-rw-r--r--indra/llwindow/llwindowcallbacks.cpp12
-rw-r--r--indra/llwindow/llwindowcallbacks.h4
-rw-r--r--indra/llwindow/llwindowheadless.h2
-rw-r--r--indra/llwindow/llwindowmacosx.cpp10
-rw-r--r--indra/llwindow/llwindowmacosx.h6
-rw-r--r--indra/llwindow/llwindowmacosx_iokit.h35
-rw-r--r--indra/llwindow/llwindowmesaheadless.h121
-rw-r--r--indra/llwindow/llwindowsdl.cpp1679
-rw-r--r--indra/llwindow/llwindowsdl.h186
-rw-r--r--indra/llwindow/llwindowwin32.cpp341
-rw-r--r--indra/llwindow/llwindowwin32.h11
27 files changed, 2059 insertions, 1675 deletions
diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt
index 69f11991ea..e35fcff06e 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
@@ -48,6 +50,49 @@ set(viewer_HEADER_FILES
llmousehandler.h
)
+# Platform-specific files for IDE visibility (excluded from build on other platforms)
+set(macosx_SOURCE_FILES
+ llkeyboardmacosx.cpp
+ llwindowmacosx.cpp
+ llwindowmacosx-objc.mm
+ llopenglview-objc.mm
+ )
+
+set(macosx_HEADER_FILES
+ llkeyboardmacosx.h
+ llwindowmacosx.h
+ llwindowmacosx-objc.h
+ llwindowmacosx_iokit.h
+ llopenglview-objc.h
+ llappdelegate-objc.h
+ )
+
+set(linux_SOURCE_FILES
+ llsdl.cpp
+ llkeyboardsdl.cpp
+ llwindowsdl.cpp
+ )
+
+set(linux_HEADER_FILES
+ llsdl.h
+ llkeyboardsdl.h
+ llwindowsdl.h
+ )
+
+set(windows_SOURCE_FILES
+ llwindowwin32.cpp
+ lldxhardware.cpp
+ llkeyboardwin32.cpp
+ lldragdropwin32.cpp
+ )
+
+set(windows_HEADER_FILES
+ llwindowwin32.h
+ lldxhardware.h
+ llkeyboardwin32.h
+ lldragdropwin32.h
+ )
+
set(llwindow_LINK_LIBRARIES
llcommon
llimage
@@ -57,51 +102,22 @@ set(llwindow_LINK_LIBRARIES
ll::glm
ll::glext
ll::uilibraries
- ll::SDL
)
include_directories(${CMAKE_SOURCE_DIR}/llrender)
-# Libraries on which this library depends, needed for Linux builds
-# Sort by high-level to low-level
-if (NOT (DARWIN OR WINDOWS))
- list(APPEND viewer_SOURCE_FILES
- llkeyboardsdl.cpp
- llwindowsdl.cpp
- )
- list(APPEND viewer_HEADER_FILES
- llkeyboardsdl.h
- llwindowsdl.h
- )
+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)
+ list(APPEND llwindow_LINK_LIBRARIES
+ ll::SDL3
+ )
endif ()
if (DARWIN)
- list(APPEND llwindow_SOURCE_FILES
- llkeyboardmacosx.cpp
- llwindowmacosx.cpp
- llwindowmacosx-objc.mm
- llopenglview-objc.mm
- )
- list(APPEND llwindow_HEADER_FILES
- llkeyboardmacosx.h
- llwindowmacosx.h
- llwindowmacosx-objc.h
- llopenglview-objc.h
- llappdelegate-objc.h
- )
+ list(APPEND llwindow_SOURCE_FILES ${macosx_SOURCE_FILES})
+ list(APPEND llwindow_HEADER_FILES ${macosx_HEADER_FILES})
# We use a bunch of deprecated system APIs.
set_source_files_properties(
@@ -110,22 +126,19 @@ if (DARWIN)
PROPERTIES
COMPILE_FLAGS "-fpascal-strings"
)
+
+ set_source_files_properties(
+ llwindowmacosx-objc.mm
+ llopenglview-objc.mm
+ PROPERTIES
+ SKIP_PRECOMPILE_HEADERS TRUE
+ )
endif (DARWIN)
if (WINDOWS)
- list(APPEND llwindow_SOURCE_FILES
- llwindowwin32.cpp
- lldxhardware.cpp
- llkeyboardwin32.cpp
- lldragdropwin32.cpp
- )
- list(APPEND llwindow_HEADER_FILES
- llwindowwin32.h
- lldxhardware.h
- llkeyboardwin32.h
- lldragdropwin32.h
- )
+ list(APPEND llwindow_SOURCE_FILES ${windows_SOURCE_FILES})
+ list(APPEND llwindow_HEADER_FILES ${windows_HEADER_FILES})
list(APPEND llwindow_LINK_LIBRARIES
comdlg32 # Common Dialogs for ChooseColor
ole32
@@ -134,32 +147,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)
@@ -168,19 +204,59 @@ endif (llwindow_HEADER_FILES)
list(APPEND viewer_SOURCE_FILES ${viewer_HEADER_FILES})
+ # Collect all platform files for IDE visibility, excluding already-added current platform
+ set(ide_visibility_files "")
+ if (NOT DARWIN)
+ list(APPEND ide_visibility_files ${macosx_SOURCE_FILES} ${macosx_HEADER_FILES})
+ endif()
+ if (NOT (LINUX OR CMAKE_SYSTEM_NAME MATCHES FreeBSD))
+ list(APPEND ide_visibility_files ${linux_SOURCE_FILES} ${linux_HEADER_FILES})
+ endif()
+ if (NOT WINDOWS)
+ list(APPEND ide_visibility_files ${windows_SOURCE_FILES} ${windows_HEADER_FILES})
+ endif()
+
add_library (llwindow
${llwindow_SOURCE_FILES}
${viewer_SOURCE_FILES}
+ # Add non-platform files for IDE visibility only
+ ${ide_visibility_files}
)
-if (SDL_FOUND)
- set_property(TARGET llwindow
- PROPERTY COMPILE_DEFINITIONS LL_SDL=1
+# Mark non-platform files as excluded from build
+if (WINDOWS)
+ set_source_files_properties(
+ ${macosx_SOURCE_FILES}
+ ${linux_SOURCE_FILES}
+ PROPERTIES
+ HEADER_FILE_ONLY TRUE
+ )
+elseif (DARWIN)
+ set_source_files_properties(
+ ${windows_SOURCE_FILES}
+ ${linux_SOURCE_FILES}
+ PROPERTIES
+ HEADER_FILE_ONLY TRUE
+ )
+elseif (LINUX OR CMAKE_SYSTEM_NAME MATCHES FreeBSD)
+ set_source_files_properties(
+ ${macosx_SOURCE_FILES}
+ ${windows_SOURCE_FILES}
+ PROPERTIES
+ HEADER_FILE_ONLY TRUE
)
-endif (SDL_FOUND)
+endif()
+
+target_link_libraries (llwindow ${llwindow_LINK_LIBRARIES})
+target_include_directories(llwindow INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
- 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()
+
+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 d9c1a9cf7d..df69b1390c 100644
--- a/indra/llwindow/llkeyboard.cpp
+++ b/indra/llwindow/llkeyboard.cpp
@@ -163,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
@@ -198,7 +199,6 @@ void LLKeyboard::resetKeys()
bool LLKeyboard::translateKey(const NATIVE_KEY_TYPE os_key, KEY *out_key)
{
-
// Only translate keys in the map, ignore all other keys for now
auto iter = mTranslateKeyMap.find(os_key);
if (iter == mTranslateKeyMap.end())
@@ -228,7 +228,7 @@ LLKeyboard::NATIVE_KEY_TYPE LLKeyboard::inverseTranslateKey(const KEY translated
}
-bool LLKeyboard::handleTranslatedKeyDown(KEY translated_key, U32 translated_mask)
+bool LLKeyboard::handleTranslatedKeyDown(KEY translated_key, MASK translated_mask)
{
bool handled = false;
bool repeated = false;
@@ -256,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 808be7b245..a092787cef 100644
--- a/indra/llwindow/llkeyboard.h
+++ b/indra/llwindow/llkeyboard.h
@@ -54,10 +54,12 @@ class LLWindowCallbacks;
class LLKeyboard
{
public:
-#ifndef LL_SDL
- typedef U16 NATIVE_KEY_TYPE;
-#else
+#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();
@@ -72,14 +74,14 @@ public:
bool getKeyRepeated(const KEY key) { return mKeyRepeated[key]; }
bool translateKey(const NATIVE_KEY_TYPE os_key, KEY *translated_key);
- NATIVE_KEY_TYPE inverseTranslateKey(const KEY translated_key);
- bool handleTranslatedKeyUp(KEY translated_key, U32 translated_mask); // Translated into "Linden" keycodes
- bool handleTranslatedKeyDown(KEY translated_key, U32 translated_mask); // Translated into "Linden" keycodes
+ 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 NATIVE_KEY_TYPE key, MASK mask) = 0;
virtual bool handleKeyDown(const NATIVE_KEY_TYPE key, MASK mask) = 0;
-#if defined(LL_DARWIN) && !defined(LL_SDL)
+#if LL_DARWIN && !LL_SDL_WINDOW
// We only actually use this for macOS.
virtual void handleModifier(MASK mask) = 0;
#endif // LL_DARWIN
diff --git a/indra/llwindow/llkeyboardheadless.cpp b/indra/llwindow/llkeyboardheadless.cpp
index 6f8c829dd5..50d03aaf20 100644
--- a/indra/llwindow/llkeyboardheadless.cpp
+++ b/indra/llwindow/llkeyboardheadless.cpp
@@ -31,17 +31,23 @@
LLKeyboardHeadless::LLKeyboardHeadless()
{ }
-void LLKeyboardHeadless::resetMaskKeys()
-{ }
-
-
+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;
+}
+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)
{
@@ -61,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 439abaf25b..364fb03fe7 100644
--- a/indra/llwindow/llkeyboardheadless.h
+++ b/indra/llwindow/llkeyboardheadless.h
@@ -33,20 +33,15 @@ class LLKeyboardHeadless : public LLKeyboard
{
public:
LLKeyboardHeadless();
- /*virtual*/ ~LLKeyboardHeadless() {};
+ ~LLKeyboardHeadless() = default;
-#ifndef LL_SDL
- /*virtual*/ bool handleKeyUp(const U16 key, MASK mask) { return false; }
- /*virtual*/ bool handleKeyDown(const U16 key, MASK mask) { return false; }
-#else
- /*virtual*/ bool handleKeyUp(const U32 key, MASK mask) { return false; }
- /*virtual*/ bool handleKeyDown(const U32 key, MASK mask) { return false; }
-#endif
- /*virtual*/ void resetMaskKeys();
- /*virtual*/ MASK currentMask(bool for_mouse_event);
- /*virtual*/ void scanKeyboard();
-#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 101e035135..7d270a4392 100644
--- a/indra/llwindow/llkeyboardmacosx.cpp
+++ b/indra/llwindow/llkeyboardmacosx.cpp
@@ -196,7 +196,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.
@@ -221,7 +221,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;
@@ -237,7 +237,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;
@@ -260,7 +260,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;
@@ -277,7 +277,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;
@@ -296,7 +296,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;
@@ -325,6 +325,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 c8805300cb..d951ce331e 100644
--- a/indra/llwindow/llkeyboardsdl.cpp
+++ b/indra/llwindow/llkeyboardsdl.cpp
@@ -1,5 +1,6 @@
/**
- * @author This module has many fathers, and it shows.
+ * @file llkeyboardsdl.cpp
+ * @brief Handler for assignable key bindings
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
@@ -27,8 +28,8 @@
#include "linden_common.h"
#include "llkeyboardsdl.h"
#include "llwindowcallbacks.h"
-#include "SDL2/SDL.h"
-#include "SDL2/SDL_keycode.h"
+
+#include "SDL3/SDL_keycode.h"
LLKeyboardSDL::LLKeyboardSDL()
{
@@ -39,11 +40,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...
-
- // <FS:ND> Looks like we need to map those despite of SDL_TEXTINPUT handling most of this, but without
- // the translation lower->upper here accelerators will not work.
-
- U16 cur_char;
+ LLKeyboard::NATIVE_KEY_TYPE cur_char;
for (cur_char = 'A'; cur_char <= 'Z'; cur_char++)
{
mTranslateKeyMap[cur_char] = cur_char;
@@ -71,7 +68,7 @@ LLKeyboardSDL::LLKeyboardSDL()
//mTranslateKeyMap[SDLK_KP3] = KEY_PAGE_DOWN;
//mTranslateKeyMap[SDLK_KP0] = KEY_INSERT;
- mTranslateKeyMap[SDLK_SPACE] = ' '; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
+ mTranslateKeyMap[SDLK_SPACE] = ' ';
mTranslateKeyMap[SDLK_RETURN] = KEY_RETURN;
mTranslateKeyMap[SDLK_LEFT] = KEY_LEFT;
mTranslateKeyMap[SDLK_RIGHT] = KEY_RIGHT;
@@ -113,17 +110,17 @@ LLKeyboardSDL::LLKeyboardSDL()
mTranslateKeyMap[SDLK_F10] = KEY_F10;
mTranslateKeyMap[SDLK_F11] = KEY_F11;
mTranslateKeyMap[SDLK_F12] = KEY_F12;
- mTranslateKeyMap[SDLK_PLUS] = '='; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
- mTranslateKeyMap[SDLK_COMMA] = ','; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
- mTranslateKeyMap[SDLK_MINUS] = '-'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
- mTranslateKeyMap[SDLK_PERIOD] = '.'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
- mTranslateKeyMap[SDLK_BACKQUOTE] = '`'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
- mTranslateKeyMap[SDLK_SLASH] = KEY_DIVIDE; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
- mTranslateKeyMap[SDLK_SEMICOLON] = ';'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
- mTranslateKeyMap[SDLK_LEFTBRACKET] = '['; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
- mTranslateKeyMap[SDLK_BACKSLASH] = '\\'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
- mTranslateKeyMap[SDLK_RIGHTBRACKET] = ']'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
- mTranslateKeyMap[SDLK_QUOTE] = '\''; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
+ mTranslateKeyMap[SDLK_PLUS] = '=';
+ mTranslateKeyMap[SDLK_COMMA] = ',';
+ mTranslateKeyMap[SDLK_MINUS] = '-';
+ mTranslateKeyMap[SDLK_PERIOD] = '.';
+ mTranslateKeyMap[SDLK_GRAVE] = '`';
+ mTranslateKeyMap[SDLK_SLASH] = KEY_DIVIDE;
+ mTranslateKeyMap[SDLK_SEMICOLON] = ';';
+ mTranslateKeyMap[SDLK_LEFTBRACKET] = '[';
+ mTranslateKeyMap[SDLK_BACKSLASH] = '\\';
+ mTranslateKeyMap[SDLK_RIGHTBRACKET] = ']';
+ mTranslateKeyMap[SDLK_APOSTROPHE] = '\'';
// Build inverse map
for (auto iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end(); iter++)
@@ -161,12 +158,12 @@ void LLKeyboardSDL::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
#ifdef LL_DARWIN
| KMOD_GUI
#endif
@@ -175,24 +172,24 @@ void LLKeyboardSDL::resetMaskKeys()
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
#ifdef LL_DARWIN
| KMOD_GUI
#endif
@@ -201,7 +198,7 @@ MASK LLKeyboardSDL::updateModifiers(const U32 mask)
out_mask |= MASK_CONTROL;
}
- if(mask & KMOD_ALT)
+ if(mask & SDL_KMOD_ALT)
{
out_mask |= MASK_ALT;
}
@@ -210,12 +207,12 @@ MASK LLKeyboardSDL::updateModifiers(const U32 mask)
}
-static U32 adjustNativekeyFromUnhandledMask(const U32 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.
- U32 rtn = key;
- if (!(mask & KMOD_NUM))
+ LLKeyboard::NATIVE_KEY_TYPE rtn = key;
+ if (!(mask & SDL_KMOD_NUM))
{
switch (key)
{
@@ -235,12 +232,12 @@ static U32 adjustNativekeyFromUnhandledMask(const U32 key, const U32 mask)
}
-bool LLKeyboardSDL::handleKeyDown(const U32 key, const U32 mask)
+bool LLKeyboardSDL::handleKeyDown(const LLKeyboard::NATIVE_KEY_TYPE key, const MASK mask)
{
- U32 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);
@@ -255,12 +252,12 @@ bool LLKeyboardSDL::handleKeyDown(const U32 key, const U32 mask)
}
-bool LLKeyboardSDL::handleKeyUp(const U32 key, const U32 mask)
+bool LLKeyboardSDL::handleKeyUp(const LLKeyboard::NATIVE_KEY_TYPE key, const MASK mask)
{
- U32 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);
@@ -279,17 +276,17 @@ MASK LLKeyboardSDL::currentMask(bool for_mouse_event)
MASK result = MASK_NONE;
SDL_Keymod mask = SDL_GetModState();
- if (mask & KMOD_SHIFT)
+ if (mask & SDL_KMOD_SHIFT)
result |= MASK_SHIFT;
- if (mask & KMOD_CTRL)
+ if (mask & SDL_KMOD_CTRL)
result |= MASK_CONTROL;
- if (mask & KMOD_ALT)
+ if (mask & SDL_KMOD_ALT)
result |= MASK_ALT;
// For keyboard events, consider Meta keys equivalent to Control
if (!for_mouse_event)
{
- if (mask & KMOD_GUI)
+ if (mask & SDL_KMOD_GUI)
result |= MASK_CONTROL;
}
@@ -309,6 +306,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++)
@@ -323,347 +321,346 @@ void LLKeyboardSDL::scanKeyboard()
}
-bool LLKeyboardSDL::translateNumpadKey( const U32 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);
}
enum class WindowsVK : U32
{
- VK_UNKNOWN = 0,
- VK_CANCEL = 0x03,
- VK_BACK = 0x08,
- VK_TAB = 0x09,
- VK_CLEAR = 0x0C,
- VK_RETURN = 0x0D,
- VK_SHIFT = 0x10,
- VK_CONTROL = 0x11,
- VK_MENU = 0x12,
- VK_PAUSE = 0x13,
- VK_CAPITAL = 0x14,
- VK_KANA = 0x15,
- VK_HANGUL = 0x15,
- VK_JUNJA = 0x17,
- VK_FINAL = 0x18,
- VK_HANJA = 0x19,
- VK_KANJI = 0x19,
- VK_ESCAPE = 0x1B,
- VK_CONVERT = 0x1C,
- VK_NONCONVERT = 0x1D,
- VK_ACCEPT = 0x1E,
- VK_MODECHANGE = 0x1F,
- VK_SPACE = 0x20,
- VK_PRIOR = 0x21,
- VK_NEXT = 0x22,
- VK_END = 0x23,
- VK_HOME = 0x24,
- VK_LEFT = 0x25,
- VK_UP = 0x26,
- VK_RIGHT = 0x27,
- VK_DOWN = 0x28,
- VK_SELECT = 0x29,
- VK_PRINT = 0x2A,
- VK_EXECUTE = 0x2B,
- VK_SNAPSHOT = 0x2C,
- VK_INSERT = 0x2D,
- VK_DELETE = 0x2E,
- VK_HELP = 0x2F,
- VK_0 = 0x30,
- VK_1 = 0x31,
- VK_2 = 0x32,
- VK_3 = 0x33,
- VK_4 = 0x34,
- VK_5 = 0x35,
- VK_6 = 0x36,
- VK_7 = 0x37,
- VK_8 = 0x38,
- VK_9 = 0x39,
- VK_A = 0x41,
- VK_B = 0x42,
- VK_C = 0x43,
- VK_D = 0x44,
- VK_E = 0x45,
- VK_F = 0x46,
- VK_G = 0x47,
- VK_H = 0x48,
- VK_I = 0x49,
- VK_J = 0x4A,
- VK_K = 0x4B,
- VK_L = 0x4C,
- VK_M = 0x4D,
- VK_N = 0x4E,
- VK_O = 0x4F,
- VK_P = 0x50,
- VK_Q = 0x51,
- VK_R = 0x52,
- VK_S = 0x53,
- VK_T = 0x54,
- VK_U = 0x55,
- VK_V = 0x56,
- VK_W = 0x57,
- VK_X = 0x58,
- VK_Y = 0x59,
- VK_Z = 0x5A,
- VK_LWIN = 0x5B,
- VK_RWIN = 0x5C,
- VK_APPS = 0x5D,
- VK_SLEEP = 0x5F,
- VK_NUMPAD0 = 0x60,
- VK_NUMPAD1 = 0x61,
- VK_NUMPAD2 = 0x62,
- VK_NUMPAD3 = 0x63,
- VK_NUMPAD4 = 0x64,
- VK_NUMPAD5 = 0x65,
- VK_NUMPAD6 = 0x66,
- VK_NUMPAD7 = 0x67,
- VK_NUMPAD8 = 0x68,
- VK_NUMPAD9 = 0x69,
- VK_MULTIPLY = 0x6A,
- VK_ADD = 0x6B,
- VK_SEPARATOR = 0x6C,
- VK_SUBTRACT = 0x6D,
- VK_DECIMAL = 0x6E,
- VK_DIVIDE = 0x6F,
- VK_F1 = 0x70,
- VK_F2 = 0x71,
- VK_F3 = 0x72,
- VK_F4 = 0x73,
- VK_F5 = 0x74,
- VK_F6 = 0x75,
- VK_F7 = 0x76,
- VK_F8 = 0x77,
- VK_F9 = 0x78,
- VK_F10 = 0x79,
- VK_F11 = 0x7A,
- VK_F12 = 0x7B,
- VK_F13 = 0x7C,
- VK_F14 = 0x7D,
- VK_F15 = 0x7E,
- VK_F16 = 0x7F,
- VK_F17 = 0x80,
- VK_F18 = 0x81,
- VK_F19 = 0x82,
- VK_F20 = 0x83,
- VK_F21 = 0x84,
- VK_F22 = 0x85,
- VK_F23 = 0x86,
- VK_F24 = 0x87,
- VK_NUMLOCK = 0x90,
- VK_SCROLL = 0x91,
- VK_LSHIFT = 0xA0,
- VK_RSHIFT = 0xA1,
- VK_LCONTROL = 0xA2,
- VK_RCONTROL = 0xA3,
- VK_LMENU = 0xA4,
- VK_RMENU = 0xA5,
- VK_BROWSER_BACK = 0xA6,
- VK_BROWSER_FORWARD = 0xA7,
- VK_BROWSER_REFRESH = 0xA8,
- VK_BROWSER_STOP = 0xA9,
- VK_BROWSER_SEARCH = 0xAA,
- VK_BROWSER_FAVORITES = 0xAB,
- VK_BROWSER_HOME = 0xAC,
- VK_VOLUME_MUTE = 0xAD,
- VK_VOLUME_DOWN = 0xAE,
- VK_VOLUME_UP = 0xAF,
- VK_MEDIA_NEXT_TRACK = 0xB0,
- VK_MEDIA_PREV_TRACK = 0xB1,
- VK_MEDIA_STOP = 0xB2,
- VK_MEDIA_PLAY_PAUSE = 0xB3,
- VK_MEDIA_LAUNCH_MAIL = 0xB4,
- VK_MEDIA_LAUNCH_MEDIA_SELECT = 0xB5,
- VK_MEDIA_LAUNCH_APP1 = 0xB6,
- VK_MEDIA_LAUNCH_APP2 = 0xB7,
- VK_OEM_1 = 0xBA,
- VK_OEM_PLUS = 0xBB,
- VK_OEM_COMMA = 0xBC,
- VK_OEM_MINUS = 0xBD,
- VK_OEM_PERIOD = 0xBE,
- VK_OEM_2 = 0xBF,
- VK_OEM_3 = 0xC0,
- VK_OEM_4 = 0xDB,
- VK_OEM_5 = 0xDC,
- VK_OEM_6 = 0xDD,
- VK_OEM_7 = 0xDE,
- VK_OEM_8 = 0xDF,
- VK_OEM_102 = 0xE2,
- VK_PROCESSKEY = 0xE5,
- VK_PACKET = 0xE7,
- VK_ATTN = 0xF6,
- VK_CRSEL = 0xF7,
- VK_EXSEL = 0xF8,
- VK_EREOF = 0xF9,
- VK_PLAY = 0xFA,
- VK_ZOOM = 0xFB,
- VK_NONAME = 0xFC,
- VK_PA1 = 0xFD,
- VK_OEM_CLEAR = 0xFE,
+ 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 > mSDL2_to_Win;
-std::set< U32 > mIgnoreSDL2Keys;
+std::map< U32, U32 > mSDL_to_Win;
-U32 LLKeyboardSDL::mapSDL2toWin( U32 aSymbol )
+U32 LLKeyboardSDL::mapSDLtoWin( U32 aSymbol )
{
- // <FS:ND> Map SDLK_ virtual keys to Windows VK_ virtual keys.
- // Text is handled via unicode input (SDL_TEXTINPUT event) and does not need to be translated into VK_ values as those match already.
- if( mSDL2_to_Win.empty() )
+ // <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() )
{
- mSDL2_to_Win[ SDLK_BACKSPACE ] = (U32)WindowsVK::VK_BACK;
- mSDL2_to_Win[ SDLK_TAB ] = (U32)WindowsVK::VK_TAB;
- mSDL2_to_Win[ 12 ] = (U32)WindowsVK::VK_CLEAR;
- mSDL2_to_Win[ SDLK_RETURN ] = (U32)WindowsVK::VK_RETURN;
- mSDL2_to_Win[ 19 ] = (U32)WindowsVK::VK_PAUSE;
- mSDL2_to_Win[ SDLK_ESCAPE ] = (U32)WindowsVK::VK_ESCAPE;
- mSDL2_to_Win[ SDLK_SPACE ] = (U32)WindowsVK::VK_SPACE;
- mSDL2_to_Win[ SDLK_QUOTE ] = (U32)WindowsVK::VK_OEM_7;
- mSDL2_to_Win[ SDLK_COMMA ] = (U32)WindowsVK::VK_OEM_COMMA;
- mSDL2_to_Win[ SDLK_MINUS ] = (U32)WindowsVK::VK_OEM_MINUS;
- mSDL2_to_Win[ SDLK_PERIOD ] = (U32)WindowsVK::VK_OEM_PERIOD;
- mSDL2_to_Win[ SDLK_SLASH ] = (U32)WindowsVK::VK_OEM_2;
+ 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;
- mSDL2_to_Win[ SDLK_0 ] = (U32)WindowsVK::VK_0;
- mSDL2_to_Win[ SDLK_1 ] = (U32)WindowsVK::VK_1;
- mSDL2_to_Win[ SDLK_2 ] = (U32)WindowsVK::VK_2;
- mSDL2_to_Win[ SDLK_3 ] = (U32)WindowsVK::VK_3;
- mSDL2_to_Win[ SDLK_4 ] = (U32)WindowsVK::VK_4;
- mSDL2_to_Win[ SDLK_5 ] = (U32)WindowsVK::VK_5;
- mSDL2_to_Win[ SDLK_6 ] = (U32)WindowsVK::VK_6;
- mSDL2_to_Win[ SDLK_7 ] = (U32)WindowsVK::VK_7;
- mSDL2_to_Win[ SDLK_8 ] = (U32)WindowsVK::VK_8;
- mSDL2_to_Win[ SDLK_9 ] = (U32)WindowsVK::VK_9;
+ 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;
- mSDL2_to_Win[ SDLK_SEMICOLON ] = (U32)WindowsVK::VK_OEM_1;
- mSDL2_to_Win[ SDLK_LESS ] = (U32)WindowsVK::VK_OEM_102;
- mSDL2_to_Win[ SDLK_EQUALS ] = (U32)WindowsVK::VK_OEM_PLUS;
- mSDL2_to_Win[ SDLK_KP_EQUALS ] = (U32)WindowsVK::VK_OEM_PLUS;
+ 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;
- mSDL2_to_Win[ SDLK_LEFTBRACKET ] = (U32)WindowsVK::VK_OEM_4;
- mSDL2_to_Win[ SDLK_BACKSLASH ] = (U32)WindowsVK::VK_OEM_5;
- mSDL2_to_Win[ SDLK_RIGHTBRACKET ] = (U32)WindowsVK::VK_OEM_6;
- mSDL2_to_Win[ SDLK_BACKQUOTE ] = (U32)WindowsVK::VK_OEM_8;
+ 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;
- mSDL2_to_Win[ SDLK_a ] = (U32)WindowsVK::VK_A;
- mSDL2_to_Win[ SDLK_b ] = (U32)WindowsVK::VK_B;
- mSDL2_to_Win[ SDLK_c ] = (U32)WindowsVK::VK_C;
- mSDL2_to_Win[ SDLK_d ] = (U32)WindowsVK::VK_D;
- mSDL2_to_Win[ SDLK_e ] = (U32)WindowsVK::VK_E;
- mSDL2_to_Win[ SDLK_f ] = (U32)WindowsVK::VK_F;
- mSDL2_to_Win[ SDLK_g ] = (U32)WindowsVK::VK_G;
- mSDL2_to_Win[ SDLK_h ] = (U32)WindowsVK::VK_H;
- mSDL2_to_Win[ SDLK_i ] = (U32)WindowsVK::VK_I;
- mSDL2_to_Win[ SDLK_j ] = (U32)WindowsVK::VK_J;
- mSDL2_to_Win[ SDLK_k ] = (U32)WindowsVK::VK_K;
- mSDL2_to_Win[ SDLK_l ] = (U32)WindowsVK::VK_L;
- mSDL2_to_Win[ SDLK_m ] = (U32)WindowsVK::VK_M;
- mSDL2_to_Win[ SDLK_n ] = (U32)WindowsVK::VK_N;
- mSDL2_to_Win[ SDLK_o ] = (U32)WindowsVK::VK_O;
- mSDL2_to_Win[ SDLK_p ] = (U32)WindowsVK::VK_P;
- mSDL2_to_Win[ SDLK_q ] = (U32)WindowsVK::VK_Q;
- mSDL2_to_Win[ SDLK_r ] = (U32)WindowsVK::VK_R;
- mSDL2_to_Win[ SDLK_s ] = (U32)WindowsVK::VK_S;
- mSDL2_to_Win[ SDLK_t ] = (U32)WindowsVK::VK_T;
- mSDL2_to_Win[ SDLK_u ] = (U32)WindowsVK::VK_U;
- mSDL2_to_Win[ SDLK_v ] = (U32)WindowsVK::VK_V;
- mSDL2_to_Win[ SDLK_w ] = (U32)WindowsVK::VK_W;
- mSDL2_to_Win[ SDLK_x ] = (U32)WindowsVK::VK_X;
- mSDL2_to_Win[ SDLK_y ] = (U32)WindowsVK::VK_Y;
- mSDL2_to_Win[ SDLK_z ] = (U32)WindowsVK::VK_Z;
+ 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;
- mSDL2_to_Win[ SDLK_DELETE ] = (U32)WindowsVK::VK_DELETE;
+ mSDL_to_Win[ SDLK_DELETE ] = (U32)WindowsVK::LL_VK_DELETE;
- mSDL2_to_Win[ SDLK_NUMLOCKCLEAR ] = (U32)WindowsVK::VK_NUMLOCK;
- mSDL2_to_Win[ SDLK_SCROLLLOCK ] = (U32)WindowsVK::VK_SCROLL;
+ mSDL_to_Win[ SDLK_NUMLOCKCLEAR ] = (U32)WindowsVK::LL_VK_NUMLOCK;
+ mSDL_to_Win[ SDLK_SCROLLLOCK ] = (U32)WindowsVK::LL_VK_SCROLL;
- mSDL2_to_Win[ SDLK_HELP ] = (U32)WindowsVK::VK_HELP;
- mSDL2_to_Win[ SDLK_PRINTSCREEN ] = (U32)WindowsVK::VK_SNAPSHOT;
- mSDL2_to_Win[ SDLK_CANCEL ] = (U32)WindowsVK::VK_CANCEL;
- mSDL2_to_Win[ SDLK_APPLICATION ] = (U32)WindowsVK::VK_APPS;
+ 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;
- mSDL2_to_Win[ SDLK_UNKNOWN ] = (U32)WindowsVK::VK_UNKNOWN;
- mSDL2_to_Win[ SDLK_BACKSPACE ] = (U32)WindowsVK::VK_BACK;
- mSDL2_to_Win[ SDLK_TAB ] = (U32)WindowsVK::VK_TAB;
- mSDL2_to_Win[ SDLK_CLEAR ] = (U32)WindowsVK::VK_CLEAR;
- mSDL2_to_Win[ SDLK_RETURN ] = (U32)WindowsVK::VK_RETURN;
- mSDL2_to_Win[ SDLK_PAUSE ] = (U32)WindowsVK::VK_PAUSE;
- mSDL2_to_Win[ SDLK_ESCAPE ] = (U32)WindowsVK::VK_ESCAPE;
- mSDL2_to_Win[ SDLK_DELETE ] = (U32)WindowsVK::VK_DELETE;
+ 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;
- mSDL2_to_Win[ SDLK_KP_PERIOD ] = (U32)WindowsVK::VK_OEM_PERIOD; // VK_DECIMAL?
- mSDL2_to_Win[ SDLK_KP_DIVIDE ] = (U32)WindowsVK::VK_DIVIDE;
- mSDL2_to_Win[ SDLK_KP_MULTIPLY] = (U32)WindowsVK::VK_MULTIPLY;
- mSDL2_to_Win[ SDLK_KP_MINUS ] = (U32)WindowsVK::VK_OEM_MINUS; // VK_SUBSTRACT?
- mSDL2_to_Win[ SDLK_KP_PLUS ] = (U32)WindowsVK::VK_OEM_PLUS; // VK_ADD?
- mSDL2_to_Win[ SDLK_KP_ENTER ] = (U32)WindowsVK::VK_RETURN;
- mSDL2_to_Win[ SDLK_KP_0 ] = (U32)WindowsVK::VK_NUMPAD0;
- mSDL2_to_Win[ SDLK_KP_1 ] = (U32)WindowsVK::VK_NUMPAD1;
- mSDL2_to_Win[ SDLK_KP_2 ] = (U32)WindowsVK::VK_NUMPAD2;
- mSDL2_to_Win[ SDLK_KP_3 ] = (U32)WindowsVK::VK_NUMPAD3;
- mSDL2_to_Win[ SDLK_KP_4 ] = (U32)WindowsVK::VK_NUMPAD4;
- mSDL2_to_Win[ SDLK_KP_5 ] = (U32)WindowsVK::VK_NUMPAD5;
- mSDL2_to_Win[ SDLK_KP_6 ] = (U32)WindowsVK::VK_NUMPAD6;
- mSDL2_to_Win[ SDLK_KP_7 ] = (U32)WindowsVK::VK_NUMPAD7;
- mSDL2_to_Win[ SDLK_KP_8 ] = (U32)WindowsVK::VK_NUMPAD8;
- mSDL2_to_Win[ SDLK_KP_9 ] = (U32)WindowsVK::VK_NUMPAD9;
+ 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;
// ?
- mSDL2_to_Win[ SDLK_UP ] = (U32)WindowsVK::VK_UP;
- mSDL2_to_Win[ SDLK_DOWN ] = (U32)WindowsVK::VK_DOWN;
- mSDL2_to_Win[ SDLK_RIGHT ] = (U32)WindowsVK::VK_RIGHT;
- mSDL2_to_Win[ SDLK_LEFT ] = (U32)WindowsVK::VK_LEFT;
- mSDL2_to_Win[ SDLK_INSERT ] = (U32)WindowsVK::VK_INSERT;
- mSDL2_to_Win[ SDLK_HOME ] = (U32)WindowsVK::VK_HOME;
- mSDL2_to_Win[ SDLK_END ] = (U32)WindowsVK::VK_END;
- mSDL2_to_Win[ SDLK_PAGEUP ] = (U32)WindowsVK::VK_PRIOR;
- mSDL2_to_Win[ SDLK_PAGEDOWN ] = (U32)WindowsVK::VK_NEXT;
- mSDL2_to_Win[ SDLK_F1 ] = (U32)WindowsVK::VK_F1;
- mSDL2_to_Win[ SDLK_F2 ] = (U32)WindowsVK::VK_F2;
- mSDL2_to_Win[ SDLK_F3 ] = (U32)WindowsVK::VK_F3;
- mSDL2_to_Win[ SDLK_F4 ] = (U32)WindowsVK::VK_F4;
- mSDL2_to_Win[ SDLK_F5 ] = (U32)WindowsVK::VK_F5;
- mSDL2_to_Win[ SDLK_F6 ] = (U32)WindowsVK::VK_F6;
- mSDL2_to_Win[ SDLK_F7 ] = (U32)WindowsVK::VK_F7;
- mSDL2_to_Win[ SDLK_F8 ] = (U32)WindowsVK::VK_F8;
- mSDL2_to_Win[ SDLK_F9 ] = (U32)WindowsVK::VK_F9;
- mSDL2_to_Win[ SDLK_F10 ] = (U32)WindowsVK::VK_F10;
- mSDL2_to_Win[ SDLK_F11 ] = (U32)WindowsVK::VK_F11;
- mSDL2_to_Win[ SDLK_F12 ] = (U32)WindowsVK::VK_F12;
- mSDL2_to_Win[ SDLK_F13 ] = (U32)WindowsVK::VK_F13;
- mSDL2_to_Win[ SDLK_F14 ] = (U32)WindowsVK::VK_F14;
- mSDL2_to_Win[ SDLK_F15 ] = (U32)WindowsVK::VK_F15;
- mSDL2_to_Win[ SDLK_CAPSLOCK ] = (U32)WindowsVK::VK_CAPITAL;
- mSDL2_to_Win[ SDLK_RSHIFT ] = (U32)WindowsVK::VK_SHIFT;
- mSDL2_to_Win[ SDLK_LSHIFT ] = (U32)WindowsVK::VK_SHIFT;
- mSDL2_to_Win[ SDLK_RCTRL ] = (U32)WindowsVK::VK_CONTROL;
- mSDL2_to_Win[ SDLK_LCTRL ] = (U32)WindowsVK::VK_CONTROL;
- mSDL2_to_Win[ SDLK_RALT ] = (U32)WindowsVK::VK_MENU;
- mSDL2_to_Win[ SDLK_LALT ] = (U32)WindowsVK::VK_MENU;
+ 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;
- mSDL2_to_Win[ SDLK_MENU ] = (U32)WindowsVK::VK_MENU;
+ mSDL_to_Win[ SDLK_MENU ] = (U32)WindowsVK::LL_VK_MENU;
- // VK_MODECHANGE ?
- // mSDL2_to_Win[ SDLK_MODE ] = (U32)WindowsVK::VK_MODE;
+ // LL_VK_MODECHANGE ?
+ // mSDL_to_Win[ SDLK_MODE ] = (U32)WindowsVK::LL_VK_MODE;
// ?
- // mSDL2_to_Win[ SDLK_SYSREQ ] = (U32)WindowsVK::VK_SYSREQ;
- // mSDL2_to_Win[ SDLK_POWER ] = (U32)WindowsVK::VK_POWER;
- // mSDL2_to_Win[ SDLK_UNDO ] = (U32)WindowsVK::VK_UNDO;
- // mSDL2_to_Win[ SDLK_KP_EQUALS ] = (U32)WindowsVK::VK_EQUALS;
- // mSDL2_to_Win[ 311 ] = (U32)WindowsVK::VK_LWIN;
- // mSDL2_to_Win[ 312 ] = (U32)WindowsVK::VK_RWIN;
- // mSDL2_to_Win[ SDLK_COLON ] = ?
+ // 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 = mSDL2_to_Win.find( aSymbol );
- if( itr != mSDL2_to_Win.end() )
+ 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 3af098c4d1..2ebe647561 100644
--- a/indra/llwindow/llkeyboardsdl.h
+++ b/indra/llwindow/llkeyboardsdl.h
@@ -1,7 +1,8 @@
/**
- * @author This module has many fathers, and it shows.
+ * @file llkeyboardsdl.h
+ * @brief Handler for assignable key bindings
*
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
@@ -23,38 +24,35 @@
* $/LicenseInfo$
*/
-#ifndef LL_LLKEYBOARDSDL2_H
-#define LL_LLKEYBOARDSDL2_H
+#ifndef LL_LLKEYBOARDSDL_H
+#define LL_LLKEYBOARDSDL_H
#include "llkeyboard.h"
-#if !defined(__i386__) && !defined(__x86_64__)
-#define SDL_DISABLE_IMMINTRIN_H
-#endif
-#include "SDL2/SDL.h"
+#include "SDL3/SDL.h"
class LLKeyboardSDL : public LLKeyboard
{
public:
LLKeyboardSDL();
- /*virtual*/ ~LLKeyboardSDL() {};
+ ~LLKeyboardSDL() = default;
- /*virtual*/ bool handleKeyUp(const U32 key, MASK mask);
- /*virtual*/ bool handleKeyDown(const U32 key, MASK mask);
- /*virtual*/ void resetMaskKeys();
- /*virtual*/ MASK currentMask(bool for_mouse_event);
- /*virtual*/ void scanKeyboard();
+ 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 U32 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<U32, KEY> mTranslateNumpadMap; // special map for translating OS keys to numpad keys
- std::map<KEY, U32> 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 mapSDL2toWin( U32 );
+ 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 935050485f..b6177abfc7 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
+#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);
#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,7 +256,7 @@ bool LLWindow::copyTextToPrimary(const LLWString &src)
// static
std::vector<std::string> LLWindow::getDynamicFallbackFontList()
{
-#if LL_SDL
+#if LL_SDL_WINDOW && !LL_MESA_HEADLESS
return LLWindowSDL::getDynamicFallbackFontList();
#elif LL_WINDOWS
return LLWindowWin32::getDynamicFallbackFontList();
@@ -270,14 +268,30 @@ std::vector<std::string> LLWindow::getDynamicFallbackFontList()
}
// static
+LLFontFallbackMatch LLWindow::findFallbackFontForChar(llwchar wch)
+{
+#if LL_SDL_WINDOW && !LL_MESA_HEADLESS
+ return LLWindowSDL::findFallbackFontForChar(wch);
+#elif LL_WINDOWS
+ return LLWindowWin32::findFallbackFontForChar(wch);
+#elif LL_DARWIN
+ return LLWindowMacOSX::findFallbackFontForChar(wch);
+#else
+ return LLFontFallbackMatch();
+#endif
+}
+
+// static
std::vector<std::string> LLWindow::getDisplaysResolutionList()
{
-#if LL_SDL
- return std::vector<std::string>();
+#if LL_SDL_WINDOW && !LL_MESA_HEADLESS
+ return LLWindowSDL::getDisplaysResolutionList();
#elif LL_WINDOWS
return LLWindowWin32::getDisplaysResolutionList();
#elif LL_DARWIN
return LLWindowMacOSX::getDisplaysResolutionList();
+#else
+ return std::vector<std::string>();
#endif
}
@@ -341,14 +355,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,9 +375,11 @@ void LLSplashScreen::show()
{
if (!gSplashScreenp)
{
-#if LL_WINDOWS && !LL_MESA_HEADLESS && !LL_SDL
+#if LL_SDL_WINDOW && !LL_MESA_HEADLESS
+ gSplashScreenp = new LLSplashScreenSDL;
+#elif LL_WINDOWS && !LL_MESA_HEADLESS
gSplashScreenp = new LLSplashScreenWin32;
-#elif LL_DARWIN && !LL_SDL
+#elif LL_DARWIN
gSplashScreenp = new LLSplashScreenMacOSX;
#endif
if (gSplashScreenp)
@@ -410,7 +429,11 @@ LLWindow* LLWindowManager::createWindow(
U32 max_cores,
F32 max_gl_version)
{
- LLWindow* new_window = nullptr;
+ LLWindow* new_window;
+
+#if LL_SDL_WINDOW && !defined(LL_MESA_HEADLESS)
+ init_sdl(name);
+#endif
if (use_gl)
{
@@ -418,7 +441,7 @@ LLWindow* LLWindowManager::createWindow(
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, name, x, y, width, height, flags,
fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
@@ -461,6 +484,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 80bfd60cd1..327323b018 100644
--- a/indra/llwindow/llwindow.h
+++ b/indra/llwindow/llwindow.h
@@ -38,6 +38,13 @@ class LLSplashScreen;
class LLPreeditor;
class LLWindowCallbacks;
+// Result of an OS font-fallback query; empty mPath means no font was found.
+struct LLFontFallbackMatch
+{
+ std::string mPath;
+ S32 mFaceIndex = 0;
+};
+
// Refer to llwindow_test in test/common/llwindow for usage example
class LLWindow : public LLInstanceTracker<LLWindow>
@@ -92,7 +99,7 @@ public:
virtual bool setCursorPosition(LLCoordWindow position) = 0;
virtual bool getCursorPosition(LLCoordWindow *position) = 0;
-#if LL_WINDOWS && !LL_SDL
+#if LL_WINDOWS && !LL_SDL_WINDOW
virtual bool getCursorDelta(LLCoordCommon* delta) = 0;
#endif
virtual bool isWrapMouse() const = 0;
@@ -174,9 +181,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 ) {};
@@ -186,6 +190,9 @@ public:
static std::vector<std::string> getDynamicFallbackFontList();
+ // Ask the OS for a font file covering the given codepoint (lazy fallback).
+ static LLFontFallbackMatch findFallbackFontForChar(llwchar wch);
+
// Provide native key event data
virtual LLSD getNativeKeyData() { return LLSD::emptyMap(); }
diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp
index 4b804c82cc..f997aebb9d 100644
--- a/indra/llwindow/llwindowcallbacks.cpp
+++ b/indra/llwindow/llwindowcallbacks.cpp
@@ -68,6 +68,18 @@ void LLWindowCallbacks::handleMouseLeave(LLWindow *window)
return;
}
+void LLWindowCallbacks::handlePreCloseRequest()
+{
+}
+
+void LLWindowCallbacks::handleCloseRequestCanceled()
+{
+}
+
+void LLWindowCallbacks::handleSuspendRequest()
+{
+}
+
bool LLWindowCallbacks::handleCloseRequest(LLWindow *window, bool from_user)
{
//allow the window to close
diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h
index 6d1990e92b..cd54ccd7c9 100644
--- a/indra/llwindow/llwindowcallbacks.h
+++ b/indra/llwindow/llwindowcallbacks.h
@@ -41,6 +41,10 @@ public:
virtual bool handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
virtual bool handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
virtual void handleMouseLeave(LLWindow *window);
+ // Called before close request is processed (ex: to create marker file in case OS is about to kill app).
+ virtual void handlePreCloseRequest();
+ virtual void handleCloseRequestCanceled();
+ virtual void handleSuspendRequest();
// return true to allow window to close, which will then cause handleQuit to be called
virtual bool handleCloseRequest(LLWindow *window, bool from_user);
virtual bool handleSessionExit(LLWindow* window);
diff --git a/indra/llwindow/llwindowheadless.h b/indra/llwindow/llwindowheadless.h
index 0a1ecb05e0..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 && !LL_SDL
+#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.cpp b/indra/llwindow/llwindowmacosx.cpp
index 5a85887143..ce2f3cf9e2 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -44,7 +44,7 @@
#include <CoreGraphics/CGDisplayConfiguration.h>
#include <IOKit/IOCFPlugIn.h>
-#include <IOKit/IOKitLib.h>
+#include "llwindowmacosx_iokit.h"
#include <IOKit/IOMessage.h>
#include <IOKit/hid/IOHIDUsageTables.h>
#include <IOKit/hid/IOHIDLib.h>
@@ -2383,7 +2383,7 @@ bool LLWindowMacOSX::getInputDevices(U32 device_type_filter,
io_iterator_t io_iter = 0;
// create an IO object iterator
- result = IOServiceGetMatchingServices( kIOMasterPortDefault, device_dict_ref, &io_iter );
+ result = IOServiceGetMatchingServices( kLLIOMainPort, device_dict_ref, &io_iter );
if ( kIOReturnSuccess != result )
{
LL_WARNS("Joystick") << "IOServiceGetMatchingServices failed" << LL_ENDL;
@@ -2637,6 +2637,12 @@ std::vector<std::string> LLWindowMacOSX::getDynamicFallbackFontList()
return std::vector<std::string>();
}
+LLFontFallbackMatch LLWindowMacOSX::findFallbackFontForChar(llwchar wch)
+{
+ // Not implemented on macOS; would use CoreText (CTFontCreateForString).
+ return LLFontFallbackMatch();
+}
+
// static
MASK LLWindowMacOSX::modifiersToMask(S16 modifiers)
{
diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h
index d703a84d02..9534eadf8e 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:
@@ -122,6 +117,7 @@ public:
static std::vector<std::string> getDisplaysResolutionList();
static std::vector<std::string> getDynamicFallbackFontList();
+ static LLFontFallbackMatch findFallbackFontForChar(llwchar wch);
// Provide native key event data
LLSD getNativeKeyData() override;
diff --git a/indra/llwindow/llwindowmacosx_iokit.h b/indra/llwindow/llwindowmacosx_iokit.h
new file mode 100644
index 0000000000..a6be2c86ef
--- /dev/null
+++ b/indra/llwindow/llwindowmacosx_iokit.h
@@ -0,0 +1,35 @@
+/**
+ * @file llwindowmacosx_iokit.h
+ * @brief IOKit compatibility for macOS deployment target differences
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, 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 <IOKit/IOKitLib.h>
+
+// kIOMainPortDefault is the macOS 12+ rename of kIOMasterPortDefault.
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 120000
+static const mach_port_t kLLIOMainPort = kIOMainPortDefault;
+#else
+static const mach_port_t kLLIOMainPort = kIOMasterPortDefault;
+#endif
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 ad40dea0c3..c98913e8b5 100644
--- a/indra/llwindow/llwindowsdl.cpp
+++ b/indra/llwindow/llwindowsdl.cpp
@@ -37,7 +37,10 @@
#include "llstring.h"
#include "lldir.h"
#include "llfindlocale.h"
+#include "llpreeditor.h"
+#include "llsdl.h"
+#if LL_LINUX || __FreeBSD__
#ifdef LL_GLIB
#include <glib.h>
#endif
@@ -46,66 +49,39 @@ extern "C" {
# include "fontconfig/fontconfig.h"
}
-#if LL_LINUX || __FreeBSD__
// not necessarily available on random SDL platforms, so #if LL_LINUX
// for execv(), waitpid(), fork()
-# include <unistd.h>
-# include <sys/types.h>
-# include <sys/wait.h>
-# define GLX_GLXEXT_PROTOTYPES 1
-# include <GL/glx.h>
-# include <stdio.h>
-#endif // LL_LINUX
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdio.h>
-extern bool gDebugWindowProc;
-
-const S32 MAX_NUM_RESOLUTIONS = 200;
+#if LL_X11
+LLWindowSDL::X11_DATA LLWindowSDL::sX11Data = {};
+#endif
+#if LL_WAYLAND
+LLWindowSDL::WAYLAND_DATA LLWindowSDL::sWaylandData = {};
+#endif
+#endif // LL_LINUX
#if LL_DARWIN
-
#include <OpenGL/OpenGL.h>
-#include <CoreGraphics/CGDirectDisplay.h>
+#include <Carbon/Carbon.h>
#include <CoreServices/CoreServices.h>
-
-bool gHiDPISupport = true;
-
-namespace
-{
- struct NativeKeyEventData {
- enum EventType {
- KEYUNKNOWN,
- KEYUP,
- KEYDOWN,
- KEYCHAR
- };
-
- EventType mKeyEvent = KEYUNKNOWN;
- uint32_t mEventType = 0;
- uint32_t mEventModifiers = 0;
- uint32_t mEventKeyCode = 0;
- uint32_t mEventChars = 0;
- uint32_t mEventUnmodChars = 0;
- bool mEventRepeat = false;
- } *mRawKeyEvent = NULL;
-}
-//
-// LLWindowMacOSX
-//
+#include <CoreGraphics/CGDisplayConfiguration.h>
bool LLWindowSDL::sUseMultGL = false;
-
#endif
-bool hasHIDPI = 0;
+bool gHiDPISupport = true;
+
+const S32 MAX_NUM_RESOLUTIONS = 200;
+const S32 DEFAULT_REFRESH_RATE = 60;
//
// LLWindowSDL
//
-#if LL_X11
-# include <X11/Xutil.h>
-#endif //LL_X11
-
#if LL_WINDOWS && !LL_MESA_HEADLESS
#pragma comment(lib, "dinput8")
#endif
@@ -114,44 +90,7 @@ bool hasHIDPI = 0;
// 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_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, const std::string& name, S32 x, S32 y, S32 width,
@@ -160,36 +99,16 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
bool enable_vsync, bool use_gl,
bool ignore_pixel_depth, U32 fsaa_samples)
: LLWindow(callbacks, fullscreen, flags),
- Lock_Display(NULL),
- Unlock_Display(NULL), mGamma(1.0f)
+ 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
-
-#if LL_DARWIN
- hasHIDPI = gHiDPISupport;
-#endif
-
- // Ignore use_gl for now, only used for drones on PC
- mWindow = NULL;
- mContext = {};
- mNeedsResize = false;
- mOverrideAspectRatio = 0.f;
- mGrabbyKeyFlags = 0;
- mReallyCapturedCount = 0;
- mHaveInputFocus = -1;
- mIsMinimized = -1;
- mFSAASamples = fsaa_samples;
-
-#if LL_X11
- mSDL_XWindowID = None;
- mSDL_Display = nullptr;
-#endif // LL_X11
// Assume 4:3 aspect ratio until we know better
- mOriginalAspectRatio = 1024.0 / 768.0;
+ mNativeAspectRatio = 1024.f / 768.f;
if (title.empty())
mWindowTitle = "Second Life";
@@ -199,6 +118,7 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
// Create the GL context and set it up for windowed or fullscreen, as appropriate.
if(createContext(x, y, width, height, 32, fullscreen, enable_vsync))
{
+ gGLManager.initWGL();
gGLManager.initGL();
//start with arrow cursor
@@ -210,11 +130,6 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
// Stash an object pointer for OSMessageBox()
gWindowImplementation = this;
-
- mFlashing = false;
-
- mKeyVirtualKey = 0;
- mKeyModifiers = KMOD_NONE;
}
static SDL_Surface *Load_BMP_Resource(const char *basename)
@@ -243,7 +158,7 @@ void LLWindowSDL::tryFindFullscreenSize( int &width, int &height )
LL_INFOS() << "createContext: setting up fullscreen " << width << "x" << height << LL_ENDL;
// If the requested width or height is 0, find the best default for the monitor.
- if((width == 0) || (height == 0))
+ if(width == 0 || height == 0)
{
// Scan through the list of modes, looking for one which has:
// height between 700 and 800
@@ -251,23 +166,22 @@ void LLWindowSDL::tryFindFullscreenSize( int &width, int &height )
S32 resolutionCount = 0;
LLWindowResolution *resolutionList = getSupportedResolutions(resolutionCount);
- if(resolutionList != NULL)
+ if(resolutionList != nullptr)
{
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;
+ LL_INFOS() << "createContext: searching for a display mode, original aspect is " << mNativeAspectRatio << LL_ENDL;
- for(i=0; i < resolutionCount; i++)
+ for(S32 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)))
+ (fabs(aspect - mNativeAspectRatio) < fabs(closestAspect - mNativeAspectRatio)))
{
LL_INFOS() << " (new closest mode) " << LL_ENDL;
@@ -283,7 +197,7 @@ void LLWindowSDL::tryFindFullscreenSize( int &width, int &height )
}
}
- if((width == 0) || (height == 0))
+ if(width == 0 || height == 0)
{
// Mode search failed for some reason. Use the old-school default.
width = 1024;
@@ -293,58 +207,10 @@ void LLWindowSDL::tryFindFullscreenSize( int &width, int &height )
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;
-
- std::initializer_list<std::tuple< char const*, char const * > > hintList =
- {
- {SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR,"0"},
- {SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH,"1"},
- {SDL_HINT_IME_INTERNAL_EDITING,"1"}
- };
-
- for( auto hint: hintList )
- {
- SDL_SetHint( std::get<0>(hint), std::get<1>(hint));
- }
-
- std::initializer_list<std::tuple<uint32_t, char const*, bool>> initList=
- { {SDL_INIT_VIDEO,"SDL_INIT_VIDEO", true},
- {SDL_INIT_AUDIO,"SDL_INIT_AUDIO", false},
- {SDL_INIT_GAMECONTROLLER,"SDL_INIT_GAMECONTROLLER", false},
- {SDL_INIT_SENSOR,"SDL_INIT_SENSOR", false}
- };
-
- for( auto subSystem : initList)
- {
- if( SDL_InitSubSystem( std::get<0>(subSystem) ) < 0 )
- {
- LL_WARNS() << "SDL_InitSubSystem for " << std::get<1>(subSystem) << " failed " << SDL_GetError() << LL_ENDL;
-
- if( std::get<2>(subSystem))
- setupFailure("SDL_Init() failure", "error", OSMB_OK);
-
- }
- }
-
- SDL_version c_sdl_version;
- SDL_VERSION(&c_sdl_version);
- LL_INFOS() << "Compiled against SDL "
- << int(c_sdl_version.major) << "."
- << int(c_sdl_version.minor) << "."
- << int(c_sdl_version.patch) << LL_ENDL;
- SDL_version r_sdl_version;
- SDL_GetVersion(&r_sdl_version);
- LL_INFOS() << " Running against SDL "
- << int(r_sdl_version.major) << "."
- << int(r_sdl_version.minor) << "."
- << int(r_sdl_version.patch) << LL_ENDL;
if (width == 0)
width = 1024;
@@ -357,18 +223,6 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b
mFullscreen = fullscreen;
- int sdlflags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
-
- if( mFullscreen )
- {
- sdlflags |= SDL_WINDOW_FULLSCREEN;
- tryFindFullscreenSize( width, height );
- }
-
- if(hasHIDPI) sdlflags = sdlflags | SDL_WINDOW_ALLOW_HIGHDPI;
-
- mSDLFlags = sdlflags;
-
// Setup default backing colors
GLint redBits{8}, greenBits{8}, blueBits{8}, alphaBits{8};
GLint depthBits{24}, stencilBits{8};
@@ -379,33 +233,55 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b
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);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
+ SDL_GLContextFlag context_flags{};
+ if(LLRender::sGLCoreProfile)
+ {
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
#if LL_DARWIN
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
+ context_flags |= SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG;
#else
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
#endif
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
-
- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+ }
- U32 context_flags = 0;
if (gDebugGL)
{
context_flags |= SDL_GL_CONTEXT_DEBUG_FLAG;
}
+
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, context_flags);
SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
- // Create the window
- mWindow = SDL_CreateWindow(mWindowTitle.c_str(), x, y, width, height, mSDLFlags);
+ if(mFullscreen)
+ {
+ tryFindFullscreenSize(width, height);
+ }
+
+ 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);
+
+ mWindow = SDL_CreateWindowWithProperties(props);
if (mWindow == nullptr)
{
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
// Create the context
mContext = SDL_GL_CreateContext(mWindow);
@@ -416,53 +292,92 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b
return false;
}
- if (SDL_GL_MakeCurrent(mWindow, mContext) != 0)
+ if (!SDL_GL_MakeCurrent(mWindow, mContext))
{
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(mFullscreen)
+ const SDL_DisplayMode* displayMode = SDL_GetCurrentDisplayMode(SDL_GetDisplayForWindow(mWindow));
+ if(displayMode)
{
- if (mWindow)
+ mRefreshRate = ll_round(displayMode->refresh_rate);
+ mNativeAspectRatio = ((F32)displayMode->w) / ((F32)displayMode->h);
+ if(mFullscreen)
{
- mFullscreen = true;
- /*
- mFullscreenWidth = mSurface->w;
- mFullscreenHeight = mSurface->h;
- */
- SDL_GetWindowSize(mWindow, &mFullscreenWidth, &mFullscreenHeight);
- mFullscreenRefresh = -1;
+ mFullscreenWidth = displayMode->w;
+ mFullscreenHeight = displayMode->h;
+ mFullscreenRefresh = ll_round(displayMode->refresh_rate);
LL_INFOS() << "Running at " << mFullscreenWidth
- << "x" << mFullscreenHeight
- << " @ " << mFullscreenRefresh
- << LL_ENDL;
+ << "x" << mFullscreenHeight
+ << " @ " << mFullscreenRefresh
+ << LL_ENDL;
}
- else
+ }
+ 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
{
- LL_WARNS() << "createContext: fullscreen creation failure. SDL: " << SDL_GetError() << LL_ENDL;
- // No fullscreen support
- mFullscreen = false;
- mFullscreenWidth = -1;
- mFullscreenHeight = -1;
+ SDL_GetWindowSize(mWindow, &mFullscreenWidth, &mFullscreenHeight);
mFullscreenRefresh = -1;
+ }
+ }
+
+ if(mRefreshRate == 0) // We failed to get a valid refresh rate above
+ {
+ mRefreshRate = DEFAULT_REFRESH_RATE;
+ }
+
+ /* Grab the window manager specific information */
+#if LL_LINUX || __FreeBSD__
+ if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0)
+ {
+ LL_INFOS() << "Running under X11" << LL_ENDL;
+ mServerProtocol = X11;
+
+ 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)
+ {
- std::string error = llformat("Unable to run fullscreen at %d x %d.\nRunning in window.", width, height);
- OSMessageBox(error, "Error", OSMB_OK);
- return false;
}
+#endif
+
+ gGLManager.initGLX();
}
- else
+ else if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0)
{
- if (!mWindow)
+ LL_INFOS() << "Running under Wayland" << LL_ENDL;
+ mServerProtocol = Wayland;
+
+ gGLManager.mIsWayland = true;
+
+#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;
+ }
+#endif
+
+ gGLManager.initEGL();
+
+ // If set (XWayland) remove DISPLAY, this will prompt dullahan to also use Wayland
+ if(getenv("DISPLAY"))
+ {
+ unsetenv("DISPLAY");
}
}
+#endif
SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &redBits);
SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &greenBits);
@@ -480,13 +395,8 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b
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)
{
-#if 0
- close();
setupFailure(
"Second Life requires True Color (32-bit) to run in a window.\n"
"Please go to Control Panels -> Display -> Settings and\n"
@@ -496,7 +406,6 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b
"Error",
OSMB_OK);
return false;
-#endif
}
LL_PROFILER_GPU_CONTEXT;
@@ -504,104 +413,87 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b
// 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)
{
SDL_SetWindowIcon(mWindow, bmpsurface);
- SDL_FreeSurface(bmpsurface);
- bmpsurface = NULL;
+ SDL_DestroySurface(bmpsurface);
+ bmpsurface = nullptr;
}
-#if LL_X11
- /* Grab the window manager specific information */
- SDL_SysWMinfo info;
- SDL_VERSION(&info.version);
- if ( SDL_GetWindowWMInfo(mWindow, &info) )
- {
- /* Save the information for later use */
- if ( info.subsystem == SDL_SYSWM_X11 )
- {
- mSDL_Display = info.info.x11.display;
- mSDL_XWindowID = info.info.x11.window;
- }
- else
- {
- LL_WARNS() << "We're not running under X11? Wild."
- << LL_ENDL;
- }
- }
- else
- {
- LL_WARNS() << "We're not running under any known WM. Wild."
- << LL_ENDL;
- }
-#endif // LL_X11
+ SDL_StartTextInput(mWindow);
+ return true;
+}
-# if LL_X11
- PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC queryInteger;
- queryInteger = (PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC)glXGetProcAddressARB((const GLubyte *)"glXQueryCurrentRendererIntegerMESA");
- unsigned int vram_megabytes = 0;
- queryInteger(GLX_RENDERER_VIDEO_MEMORY_MESA, &vram_megabytes);
- if (!vram_megabytes)
- {
- glGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, (int *)&vram_megabytes);
- vram_megabytes /= 1024;
- }
- if (!vram_megabytes)
- {
- glGetIntegerv(GL_VBO_FREE_MEMORY_ATI, (int *)&vram_megabytes);
- vram_megabytes /= 1024;
- }
- gGLManager.mVRAM = vram_megabytes;
-#elif LL_DARWIN
- CGLRendererInfoObj info = 0;
- GLint vram_megabytes = 0;
- int num_renderers = 0;
- auto err = CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay), &info, &num_renderers);
- if (!err)
+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)
{
- CGLDescribeRenderer(info, 0, kCGLRPVideoMemoryMegabytes, &vram_megabytes);
- CGLDestroyRendererInfo(info);
+ 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)
{
- vram_megabytes = 256;
+ LL_WARNS() << "Creating shared OpenGL context failed!" << LL_ENDL;
+ SDL_DestroyWindow(osr_window);
+ return nullptr;
}
- gGLManager.mVRAM = vram_megabytes;
-# endif
- SDL_StartTextInput();
- //make sure multisampling is disabled by default
-#if GL_VERSION_1_3
- glDisable(GL_MULTISAMPLE_ARB);
-#endif
- // Don't need to get the current gamma, since there's a call that restores it to the system defaults.
- return true;
-}
-
-void* LLWindowSDL::createSharedContext()
-{
- SDL_GLContext pContext = SDL_GL_CreateContext(mWindow);
- if (pContext)
{
- LL_DEBUGS() << "Creating shared OpenGL context successful!" << LL_ENDL;
- return (void*)pContext;
+ LLMutexLock osr_lock(&mOSRMutex);
+ mOSRContexts.emplace(pContext, osr_window);
}
- LL_WARNS() << "Creating shared OpenGL context failed!" << LL_ENDL;
- return nullptr;
+ LL_DEBUGS() << "Creating shared OpenGL context successful!" << LL_ENDL;
+ return (void*)pContext;
}
void LLWindowSDL::makeContextCurrent(void* contextPtr)
{
- SDL_GL_MakeCurrent(mWindow, 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;
}
void LLWindowSDL::destroySharedContext(void* contextPtr)
{
- SDL_GL_DeleteContext(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)
@@ -610,13 +502,11 @@ void LLWindowSDL::toggleVSync(bool enable_vsync)
{
LL_INFOS("Window") << "Disabling vertical sync" << LL_ENDL;
SDL_GL_SetSwapInterval(0);
- SDL_SetHintWithPriority(SDL_HINT_RENDER_VSYNC,"0",SDL_HINT_OVERRIDE);
}
else
{
LL_INFOS("Window") << "Enabling vertical sync" << LL_ENDL;
SDL_GL_SetSwapInterval(1);
- SDL_SetHintWithPriority(SDL_HINT_RENDER_VSYNC,"1",SDL_HINT_OVERRIDE);
}
}
@@ -634,6 +524,7 @@ bool LLWindowSDL::switchContext(bool fullscreen, const LLCoordScreen &size, bool
result = createContext(0, 0, size.mX, size.mY, 32, fullscreen, enable_vsync);
if (result)
{
+ gGLManager.initWGL();
gGLManager.initGL();
//start with arrow cursor
@@ -651,27 +542,29 @@ void LLWindowSDL::destroyContext()
{
LL_INFOS() << "destroyContext begins" << LL_ENDL;
+ {
+ LLMutexLock osr_lock(&mOSRMutex);
+ for(SDL_Window* pWindow : mDeadOSRWindows)
+ {
+ SDL_DestroyWindow(pWindow);
+ }
+ mDeadOSRWindows.clear();
+ }
+
// Stop unicode input
- SDL_StopTextInput();
+ SDL_StopTextInput(mWindow);
// Clean up remaining GL state before blowing away window
LL_INFOS() << "shutdownGL begins" << LL_ENDL;
gGLManager.shutdownGL();
-#if LL_X11
- mSDL_Display = NULL;
- mSDL_XWindowID = None;
- Lock_Display = NULL;
- Unlock_Display = NULL;
-#endif // LL_X11
-
LL_INFOS() << "Destroying SDL cursors" << LL_ENDL;
quitCursors();
if (mContext)
{
LL_INFOS() << "Destroying SDL GL Context" << LL_ENDL;
- SDL_GL_DeleteContext(mContext);
+ SDL_GL_DestroyContext(mContext);
mContext = nullptr;
}
else
@@ -690,21 +583,15 @@ void LLWindowSDL::destroyContext()
LL_INFOS() << "SDL Window already destroyed" << LL_ENDL;
}
LL_INFOS() << "destroyContext end" << LL_ENDL;
-
- LL_INFOS() << "SDL_QuitSS/VID begins" << LL_ENDL;
- SDL_QuitSubSystem(SDL_INIT_VIDEO); // *FIX: this might be risky...
}
LLWindowSDL::~LLWindowSDL()
{
destroyContext();
- if(mSupportedResolutions != NULL)
- {
- delete []mSupportedResolutions;
- }
+ delete[] mSupportedResolutions;
- gWindowImplementation = NULL;
+ gWindowImplementation = nullptr;
}
@@ -713,6 +600,7 @@ void LLWindowSDL::show()
if (mWindow)
{
SDL_ShowWindow(mWindow);
+ SDL_RaiseWindow(mWindow);
}
}
@@ -724,7 +612,6 @@ void LLWindowSDL::hide()
}
}
-//virtual
void LLWindowSDL::minimize()
{
if (mWindow)
@@ -733,7 +620,6 @@ void LLWindowSDL::minimize()
}
}
-//virtual
void LLWindowSDL::restore()
{
if (mWindow)
@@ -746,12 +632,6 @@ void LLWindowSDL::restore()
// 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();
@@ -761,18 +641,18 @@ void LLWindowSDL::close()
bool LLWindowSDL::isValid()
{
- return (mWindow != NULL);
+ return mWindow != nullptr;
}
bool LLWindowSDL::getVisible()
{
- bool result = false;
+ bool result = true;
if (mWindow)
{
- Uint32 flags = SDL_GetWindowFlags(mWindow);
- if (flags & SDL_WINDOW_SHOWN)
+ SDL_WindowFlags flags = SDL_GetWindowFlags(mWindow);
+ if (flags & SDL_WINDOW_HIDDEN)
{
- result = true;
+ result = false;
}
}
return result;
@@ -783,7 +663,7 @@ bool LLWindowSDL::getMinimized()
bool result = false;
if (mWindow)
{
- Uint32 flags = SDL_GetWindowFlags(mWindow);
+ SDL_WindowFlags flags = SDL_GetWindowFlags(mWindow);
if (flags & SDL_WINDOW_MINIMIZED)
{
result = true;
@@ -797,7 +677,7 @@ bool LLWindowSDL::getMaximized()
bool result = false;
if (mWindow)
{
- Uint32 flags = SDL_GetWindowFlags(mWindow);
+ SDL_WindowFlags flags = SDL_GetWindowFlags(mWindow);
if (flags & SDL_WINDOW_MAXIMIZED)
{
result = true;
@@ -817,11 +697,6 @@ bool LLWindowSDL::maximize()
return false;
}
-bool LLWindowSDL::getFullscreen()
-{
- return mFullscreen;
-}
-
bool LLWindowSDL::getPosition(LLCoordScreen *position)
{
if (mWindow)
@@ -836,30 +711,22 @@ bool LLWindowSDL::getSize(LLCoordScreen *size)
{
if (mWindow)
{
- /*
- if(hasHIDPI)
- SDL_GL_GetDrawableSize(mWindow, &size->mX, &size->mY);
- else
- */
SDL_GetWindowSize(mWindow, &size->mX, &size->mY);
- return (true);
+ return true;
}
- return (false);
+ return false;
}
bool LLWindowSDL::getSize(LLCoordWindow *size)
{
if (mWindow)
{
- if(hasHIDPI)
- SDL_GL_GetDrawableSize(mWindow, &size->mX, &size->mY);
- else
- SDL_GetWindowSize(mWindow, &size->mX, &size->mY);
- return (true);
+ SDL_GetWindowSizeInPixels(mWindow, &size->mX, &size->mY);
+ return true;
}
- return (false);
+ return false;
}
bool LLWindowSDL::setPosition(const LLCoordScreen position)
@@ -878,21 +745,12 @@ template< typename T > bool setSizeImpl( const T& newSize, SDL_Window *pWin )
if( !pWin )
return false;
- auto nFlags = SDL_GetWindowFlags( pWin );
-
- if( nFlags & SDL_WINDOW_MAXIMIZED )
- SDL_RestoreWindow( pWin );
+ SDL_WindowFlags winFlags = SDL_GetWindowFlags(pWin);
+ if( winFlags & SDL_WINDOW_MAXIMIZED)
+ SDL_RestoreWindow(pWin);
- SDL_SetWindowSize( pWin, newSize.mX, newSize.mY );
- SDL_Event event;
- event.type = SDL_WINDOWEVENT;
- event.window.event = SDL_WINDOWEVENT_RESIZED;
- event.window.windowID = SDL_GetWindowID( pWin );
- event.window.data1 = newSize.mX;
- event.window.data2 = newSize.mY;
- SDL_PushEvent( &event );
-
+ SDL_SetWindowSize(pWin, newSize.mX, newSize.mY);
return true;
}
@@ -933,12 +791,6 @@ F32 LLWindowSDL::getGamma()
bool LLWindowSDL::restoreGamma()
{
- if (mWindow)
- {
- Uint16 ramp[256];
- SDL_CalculateGammaRamp(1.f, ramp);
- SDL_SetWindowGammaRamp(mWindow, ramp, ramp, ramp);
- }
return true;
}
@@ -946,14 +798,10 @@ bool LLWindowSDL::setGamma(const F32 gamma)
{
if (mWindow)
{
- Uint16 ramp[256];
-
mGamma = gamma;
- if (mGamma == 0) mGamma = 0.1f;
+ if (mGamma == 0)
+ mGamma = 0.1f;
mGamma = 1.f / mGamma;
-
- SDL_CalculateGammaRamp(mGamma, ramp);
- SDL_SetWindowGammaRamp(mWindow, ramp, ramp, ramp);
}
return true;
}
@@ -966,7 +814,10 @@ bool LLWindowSDL::isCursorHidden()
// Constrains the mouse to the window.
void LLWindowSDL::setMouseClipping(bool b)
{
- //SDL_WM_GrabInput(b ? SDL_GRAB_ON : SDL_GRAB_OFF);
+ if (mWindow)
+ {
+ SDL_SetWindowMouseGrab(mWindow, b);
+ }
}
// virtual
@@ -982,29 +833,15 @@ void LLWindowSDL::setMinSize(U32 min_width, U32 min_height, bool enforce_immedia
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.
-
+ /*
if (mFullscreen)
{
- SDL_WarpMouseGlobal(screen_pos.mX, screen_pos.mY);
- return result;
+ SDL_WarpMouseGlobal((F32)position.mX, (F32)position.mY);
+ return true;
}
-
- SDL_WarpMouseInWindow(mWindow, screen_pos.mX, screen_pos.mY);
-
- //LL_INFOS() << llformat("llcw %d,%d -> scr %d,%d", position.mX, position.mY, screen_pos.mX, screen_pos.mY) << LL_ENDL;
-
- return result;
+ */
+ SDL_WarpMouseInWindow(mWindow, (F32)position.mX, (F32)position.mY);
+ return true;
}
bool LLWindowSDL::getCursorPosition(LLCoordWindow *position)
@@ -1012,46 +849,34 @@ bool LLWindowSDL::getCursorPosition(LLCoordWindow *position)
//Point cursor_point;
LLCoordScreen screen_pos;
- 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::getSystemUISize()
-{
- if(hasHIDPI) return 2.0f;
- else return 1.f;
-}
-
F32 LLWindowSDL::getNativeAspectRatio()
{
- // 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;
}
+ else if (mNativeAspectRatio > 0.f)
+ {
+ // we grabbed this value at startup, based on the user's desktop settings
+ return mNativeAspectRatio;
+ }
- return mOriginalAspectRatio;
+ // 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);
}
F32 LLWindowSDL::getPixelAspectRatio()
@@ -1074,61 +899,21 @@ 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_SetWindowFullscreen( mWindow, 0 );
- }
- }
- }
-
-#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
-
- 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_SetWindowFullscreen( mWindow, 0 );
- }
- }
+ if (mFullscreen && mWindow )
+ SDL_SetWindowFullscreen( mWindow, 0 );
}
void LLWindowSDL::flashIcon(F32 seconds)
@@ -1145,9 +930,18 @@ void LLWindowSDL::flashIcon(F32 seconds)
mFlashing = true;
}
+void LLWindowSDL::maybeStopFlashIcon()
+{
+ if (mFlashing && mFlashTimer.hasExpired())
+ {
+ mFlashing = false;
+ SDL_FlashWindow( mWindow, SDL_FLASH_CANCEL );
+ }
+}
+
bool LLWindowSDL::isClipboardTextAvailable()
{
- return SDL_HasClipboardText() == SDL_TRUE;
+ return SDL_HasClipboardText();
}
bool LLWindowSDL::pasteTextFromClipboard(LLWString &dst)
@@ -1168,12 +962,12 @@ bool LLWindowSDL::pasteTextFromClipboard(LLWString &dst)
bool LLWindowSDL::copyTextToClipboard(const LLWString& text)
{
const std::string utf8 = wstring_to_utf8str(text);
- return SDL_SetClipboardText(utf8.c_str()) == 0; // success == 0
+ return SDL_SetClipboardText(utf8.c_str());
}
bool LLWindowSDL::isPrimaryTextAvailable()
{
- return SDL_HasPrimarySelectionText() == SDL_TRUE;
+ return SDL_HasPrimarySelectionText();
}
bool LLWindowSDL::pasteTextFromPrimary(LLWString &dst)
@@ -1194,7 +988,7 @@ bool LLWindowSDL::pasteTextFromPrimary(LLWString &dst)
bool LLWindowSDL::copyTextToPrimary(const LLWString& text)
{
const std::string utf8 = wstring_to_utf8str(text);
- return SDL_SetPrimarySelectionText(utf8.c_str()) == 0; // success == 0
+ return SDL_SetPrimarySelectionText(utf8.c_str());
}
LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_resolutions)
@@ -1204,32 +998,29 @@ LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_reso
mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS];
mNumSupportedResolutions = 0;
- // <FS:ND> Use display no from mWindow/mSurface here?
- int max = SDL_GetNumDisplayModes(0);
- max = llclamp( max, 0, MAX_NUM_RESOLUTIONS );
-
- for( int i =0; i < max; ++i )
- {
- SDL_DisplayMode mode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 };
- if (SDL_GetDisplayMode( 0 , i, &mode) != 0)
- {
- continue;
- }
-
- 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)) )
+ 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))
{
- mSupportedResolutions[mNumSupportedResolutions].mWidth = w;
- mSupportedResolutions[mNumSupportedResolutions].mHeight = h;
- mNumSupportedResolutions++;
+ // make sure we don't add the same resolution multiple times!
+ if ( (mNumSupportedResolutions == 0) ||
+ ((mSupportedResolutions[mNumSupportedResolutions-1].mWidth != w) &&
+ (mSupportedResolutions[mNumSupportedResolutions-1].mHeight != h)) )
+ {
+ mSupportedResolutions[mNumSupportedResolutions].mWidth = w;
+ mSupportedResolutions[mNumSupportedResolutions].mHeight = h;
+ mNumSupportedResolutions++;
+ }
}
}
+ SDL_free(modes);
}
}
@@ -1237,15 +1028,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;
- int h;
- SDL_GetWindowSize(mWindow, nullptr, &h);
- to->mY = 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;
}
@@ -1255,10 +1073,15 @@ bool LLWindowSDL::convertCoords(LLCoordWindow from, LLCoordGL* to)
if (!to)
return false;
- to->mX = from.mX;
- int h;
- SDL_GetWindowSize(mWindow, nullptr, &h);
- to->mY = 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;
}
@@ -1271,7 +1094,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)
@@ -1282,26 +1105,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);
}
@@ -1332,13 +1155,13 @@ bool LLWindowSDL::SDLReallyCaptureInput(bool capture)
}
bool newGrab = wantGrab;
-
if (!mFullscreen) /* only bother if we're windowed anyway */
{
int result;
- if (wantGrab == true)
+ if (wantGrab)
{
- result = SDL_CaptureMouse(SDL_TRUE);
+ // LL_INFOS() << "X11 POINTER GRABBY" << LL_ENDL;
+ result = SDL_SetWindowMouseGrab(mWindow, true);
if (0 == result)
newGrab = true;
else
@@ -1347,9 +1170,10 @@ bool LLWindowSDL::SDLReallyCaptureInput(bool capture)
else
{
newGrab = false;
- result = SDL_CaptureMouse(SDL_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 == newGrab;
@@ -1396,354 +1220,260 @@ U32 LLWindowSDL::SDLCheckGrabbyKeys(U32 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
{
- LL_WARNS() << "RSS size grew by " << (this_rss_size - last_rss_size)/(1024*1024) << " MB in last frame" << LL_ENDL;
+ if (event.button.clicks == 2)
+ mCallbacks->handleDoubleClick(this, openGlCoord, mask);
+ else
+ mCallbacks->handleMouseDown(this, openGlCoord, mask);
+ }
+ else if (event.button.button == SDL_BUTTON_RIGHT)
+ {
+ 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
-}
-
-
-// virtual
-void LLWindowSDL::processMiscNativeEvents()
-{
-#if LL_GLIB
- // Pump until we've nothing left to do or passed 1/15th of a
- // second pumping for this frame.
- static LLTimer pump_timer;
- pump_timer.reset();
- pump_timer.setTimerExpirySec(1.0f / 15.0f);
- do
- {
- g_main_context_iteration(g_main_context_default(), false);
- } while( g_main_context_pending(g_main_context_default()) && !pump_timer.hasExpired());
-#endif
- // hack - doesn't belong here - but this is just for debugging
- if (getenv("LL_DEBUG_BLOAT"))
- {
- check_vm_bloat();
- }
-}
-
-void LLWindowSDL::gatherInput()
-{
- SDL_Event event;
-
- // Handle all outstanding SDL events
- while (SDL_PollEvent(&event))
- {
- switch (event.type)
+ case SDL_EVENT_MOUSE_BUTTON_UP:
{
- case SDL_MOUSEWHEEL:
+ 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.wheel.y != 0 )
- {
- mCallbacks->handleScrollWheel(this, -event.wheel.y);
- }
- if (event.wheel.x != 0)
- {
- mCallbacks->handleScrollHWheel(this, -event.wheel.x);
- }
- break;
+ mCallbacks->handleMouseUp(this, openGlCoord, mask);
}
-
- case SDL_MOUSEMOTION:
+ else if (event.button.button == SDL_BUTTON_RIGHT) // right
{
- LLCoordWindow winCoord(event.motion.x, event.motion.y);
- LLCoordGL openGlCoord;
- convertCoords(winCoord, &openGlCoord);
-
- openGlCoord.mX = openGlCoord.mX * getSystemUISize();
- openGlCoord.mY = openGlCoord.mY * getSystemUISize();
-
- //LL_INFOS() << "SDL_MOUSEMOTION " << event.button.x << " " << event.button.y << " gl " << openGlCoord.mX << " " << openGlCoord.mY << LL_ENDL;
-
- MASK mask = gKeyboard->currentMask(true);
- mCallbacks->handleMouseMove(this, openGlCoord, mask);
- break;
+ mCallbacks->handleRightMouseUp(this, openGlCoord, mask);
}
-
- case SDL_TEXTINPUT:
+ else if (event.button.button == SDL_BUTTON_MIDDLE) // middle
{
- auto string = utf8str_to_utf16str( event.text.text );
- mKeyModifiers = gKeyboard->currentMask( false );
- mInputType = "textinput";
- for( auto key: string )
- {
- mKeyVirtualKey = key;
-
- if( (MASK_CONTROL|MASK_ALT)&mKeyModifiers )
- gKeyboard->handleKeyDown(mKeyVirtualKey, mKeyModifiers );
- else
- handleUnicodeUTF16( key, mKeyModifiers );
- }
- break;
+ mCallbacks->handleMiddleMouseUp(this, openGlCoord, mask);
+ }
+ else
+ {
+ mCallbacks->handleOtherMouseUp(this, openGlCoord, mask, event.button.button);
}
- case SDL_KEYDOWN:
- mKeyVirtualKey = event.key.keysym.sym;
- mKeyModifiers = event.key.keysym.mod;
- mInputType = "keydown";
-
- // treat all possible Enter/Return keys the same
- if (mKeyVirtualKey == SDLK_RETURN2 || mKeyVirtualKey == SDLK_KP_ENTER)
- {
- mKeyVirtualKey = SDLK_RETURN;
- }
-
- gKeyboard->handleKeyDown(mKeyVirtualKey, mKeyModifiers );
-
- // <FS:ND> Slightly hacky :| To make the viewer honor enter (eg to accept form input) we've to not only send handleKeyDown but also send a
- // invoke handleUnicodeUTF16 in case the user hits return.
- // Note that we cannot blindly use handleUnicodeUTF16 for each SDL_KEYDOWN. Doing so will create bogus keyboard input (like % for cursor left).
- if( mKeyVirtualKey == SDLK_RETURN )
- {
- // fix return key not working when capslock, scrolllock or numlock are enabled
- mKeyModifiers &= (~(KMOD_NUM | KMOD_CAPS | KMOD_MODE | KMOD_SCROLL));
- handleUnicodeUTF16( mKeyVirtualKey, mKeyModifiers );
- }
-
- // part of the fix for SL-13243
- if (SDLCheckGrabbyKeys(event.key.keysym.sym, true) != 0)
- SDLReallyCaptureInput(true);
-
- break;
-
- case SDL_KEYUP:
- mKeyVirtualKey = event.key.keysym.sym;
- mKeyModifiers = event.key.keysym.mod;
- mInputType = "keyup";
+ break;
+ }
- // treat all possible Enter/Return keys the same
- if (mKeyVirtualKey == SDLK_RETURN2 || mKeyVirtualKey == SDLK_KP_ENTER)
- {
- mKeyVirtualKey = SDLK_RETURN;
- }
+ case SDL_EVENT_KEY_DOWN:
+ {
+ mKeyVirtualKey = event.key.key;
+ mKeyModifiers = event.key.mod;
- if (SDLCheckGrabbyKeys(mKeyVirtualKey, false) == 0)
- SDLReallyCaptureInput(false); // part of the fix for SL-13243
+ if (mKeyVirtualKey == SDLK_RETURN2 || mKeyVirtualKey == SDLK_KP_ENTER)
+ {
+ mKeyVirtualKey = SDLK_RETURN;
+ }
- gKeyboard->handleKeyUp(mKeyVirtualKey,mKeyModifiers);
- break;
+ gKeyboard->handleKeyDown(mKeyVirtualKey, mKeyModifiers);
- case SDL_MOUSEBUTTONDOWN:
+ if (mKeyVirtualKey == SDLK_RETURN)
{
- LLCoordWindow winCoord(event.button.x, event.button.y);
- LLCoordGL openGlCoord;
- convertCoords(winCoord, &openGlCoord);
-
- openGlCoord.mX *= getSystemUISize();
- openGlCoord.mY *= getSystemUISize();
+ // 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));
+ }
- MASK mask = gKeyboard->currentMask(true);
+ // part of the fix for SL-13243
+ if (SDLCheckGrabbyKeys(mKeyVirtualKey, true) != 0)
+ SDLReallyCaptureInput(true);
+ break;
+ }
- 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) // right
- {
- mCallbacks->handleRightMouseDown(this, openGlCoord, mask);
- }
- else if (event.button.button == SDL_BUTTON_MIDDLE) // middle
- {
- mCallbacks->handleMiddleMouseDown(this, openGlCoord, mask);
- }
- else
- {
- mCallbacks->handleOtherMouseDown(this, openGlCoord, mask, event.button.button);
- }
+ case SDL_EVENT_KEY_UP:
+ {
+ mKeyVirtualKey = event.key.key;
+ mKeyModifiers = event.key.mod;
- break;
+ if (mKeyVirtualKey == SDLK_RETURN2 || mKeyVirtualKey == SDLK_KP_ENTER)
+ {
+ mKeyVirtualKey = SDLK_RETURN;
}
- case SDL_MOUSEBUTTONUP:
- {
- LLCoordWindow winCoord(event.button.x, event.button.y);
- LLCoordGL openGlCoord;
- convertCoords(winCoord, &openGlCoord);
+ gKeyboard->handleKeyUp(mKeyVirtualKey, mKeyModifiers);
+ if (SDLCheckGrabbyKeys(mKeyVirtualKey, false) == 0)
+ SDLReallyCaptureInput(false); // part of the fix for SL-13243
+ break;
+ }
- openGlCoord.mX *= getSystemUISize();
- openGlCoord.mY *= getSystemUISize();
+ case SDL_EVENT_TEXT_INPUT:
+ {
+ auto string = utf8str_to_wstring(event.text.text);
+ MASK current_mask = gKeyboard->currentMask(false);
+ for (auto key : string)
+ {
+ mKeyVirtualKey = key;
+ mCallbacks->handleUnicodeChar(key, current_mask);
+ }
+ break;
+ }
- MASK mask = gKeyboard->currentMask(true);
+ case SDL_EVENT_WINDOW_EXPOSED:
+ {
+ mCallbacks->handlePaint(this, 0, 0, 0, 0);
+ break;
+ }
- 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);
- }
+ 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;
- break;
+ 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)
+ {
+ mRefreshRate = ll_round(displayMode->refresh_rate);
+ mNativeAspectRatio = ((F32)displayMode->w) / ((F32)displayMode->h);
}
-
- case SDL_WINDOWEVENT:
+ 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))
{
- switch(event.window.event)
- {
- //case SDL_WINDOWEVENT_SIZE_CHANGED: <FS:ND> SDL_WINDOWEVENT_SIZE_CHANGED is followed by SDL_WINDOWEVENT_RESIZED, so handling one shall be enough
- case SDL_WINDOWEVENT_RESIZED:
- {
- LL_INFOS() << "Handling a resize event: " << event.window.data1 << "x" << event.window.data2 << LL_ENDL;
- S32 width = llmax(event.window.data1, (S32)mMinWindowWidth);
- S32 height = llmax(event.window.data2, (S32)mMinWindowHeight);
-
- mCallbacks->handleResize(this, width * getSystemUISize(), height * getSystemUISize());
- break;
- }
- case SDL_WINDOWEVENT_LEAVE:
- mCallbacks->handleMouseLeave(this);
- break;
- case SDL_WINDOWEVENT_FOCUS_GAINED:
- mCallbacks->handleFocus(this);
- break;
- case SDL_WINDOWEVENT_FOCUS_LOST:
- mCallbacks->handleFocusLost(this);
- break;
- case SDL_WINDOWEVENT_EXPOSED:
- case SDL_WINDOWEVENT_SHOWN:
- case SDL_WINDOWEVENT_HIDDEN:
- case SDL_WINDOWEVENT_MINIMIZED:
- case SDL_WINDOWEVENT_MAXIMIZED:
- case SDL_WINDOWEVENT_RESTORED:
- {
- Uint32 flags = SDL_GetWindowFlags(mWindow);
- bool minimized = (flags & SDL_WINDOW_MINIMIZED);
- bool hidden = (flags & SDL_WINDOW_HIDDEN);
-
- mCallbacks->handleActivate(this, !minimized || !hidden);
- LL_INFOS() << "SDL deiconification state switched to " << minimized << LL_ENDL;
- break;
- }
- }
- break;
+ // Get the app to initiate cleanup.
+ mCallbacks->handleQuit(this);
+ // The app is responsible for calling destroyWindow when done with GL
}
- 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;
+}
- // 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;
- }
+// 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)
@@ -1758,20 +1488,31 @@ 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,
+ 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,
- 32,
- SDL_SwapLE32(0xFFU),
- SDL_SwapLE32(0xFF00U),
- SDL_SwapLE32(0xFF0000U),
- SDL_SwapLE32(0xFF000000U));
- SDL_FillRect(cursurface, NULL, SDL_SwapLE32(0x00000000U));
+ 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;
@@ -1788,7 +1529,7 @@ static SDL_Cursor *makeSDLCursorFromBMP(const char *filename, int hotx, int hoty
U8 *pixelp =
((U8*)cursurface->pixels)
+ cursurface->pitch * i
- + j*cursurface->format->BytesPerPixel;
+ + j*pix_format_details->bytes_per_pixel;
U8 srcred = pixelp[0];
U8 srcgreen = pixelp[1];
U8 srcblue = pixelp[2];
@@ -1811,8 +1552,8 @@ static SDL_Cursor *makeSDLCursorFromBMP(const char *filename, int hotx, int hoty
} 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;
}
@@ -1845,28 +1586,28 @@ void LLWindowSDL::updateCursor()
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] = 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] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
+ 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_HAND);
- mSDLCursors[UI_CURSOR_IBEAM] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
+ 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_SIZENWSE);
- mSDLCursors[UI_CURSOR_SIZENESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW);
- mSDLCursors[UI_CURSOR_SIZEWE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
- mSDLCursors[UI_CURSOR_SIZENS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
- mSDLCursors[UI_CURSOR_SIZEALL] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
- mSDLCursors[UI_CURSOR_NO] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO);
- mSDLCursors[UI_CURSOR_WORKING] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAITARROW);
+ 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);
@@ -1903,23 +1644,24 @@ void LLWindowSDL::initCursors()
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;
}
}
@@ -1948,7 +1690,7 @@ void LLWindowSDL::hideCursor()
// LL_INFOS() << "hideCursor: hiding" << LL_ENDL;
mCursorHidden = true;
mHideCursorPermanent = true;
- SDL_ShowCursor(SDL_DISABLE);
+ SDL_HideCursor();
}
else
{
@@ -1963,7 +1705,7 @@ void LLWindowSDL::showCursor()
// LL_INFOS() << "showCursor: showing" << LL_ENDL;
mCursorHidden = false;
mHideCursorPermanent = false;
- SDL_ShowCursor(SDL_ENABLE);
+ SDL_ShowCursor();
}
else
{
@@ -2039,37 +1781,28 @@ S32 OSMessageBoxSDL(const std::string& text, const std::string& caption, U32 typ
break;
}
+ if(gWindowImplementation != nullptr)
+ gWindowImplementation->beforeDialog();
+
int btn{0};
- if( 0 == SDL_ShowMessageBox( &oData, &btn ) )
+ if(SDL_ShowMessageBox( &oData, &btn ))
+ {
+ if(gWindowImplementation != nullptr)
+ gWindowImplementation->afterDialog();
return btn;
+ }
+
+ if(gWindowImplementation != nullptr)
+ gWindowImplementation->afterDialog();
+
return OSBTN_CANCEL;
}
bool LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b)
{
- return (false);
+ return false;
}
-#if LL_DARWIN
-LLSD LLWindowSDL::getNativeKeyData()
-{
- LLSD result = LLSD::emptyMap();
-
- if(mRawKeyEvent)
- {
- result["event_type"] = LLSD::Integer(mRawKeyEvent->mEventType);
- result["event_modifiers"] = LLSD::Integer(mRawKeyEvent->mEventModifiers);
- result["event_keycode"] = LLSD::Integer(mRawKeyEvent->mEventKeyCode);
- result["event_chars"] = (mRawKeyEvent->mEventChars) ? LLSD(LLSD::Integer(mRawKeyEvent->mEventChars)) : LLSD();
- result["event_umodchars"] = (mRawKeyEvent->mEventUnmodChars) ? LLSD(LLSD::Integer(mRawKeyEvent->mEventUnmodChars)) : LLSD();
- result["event_isrepeat"] = LLSD::Boolean(mRawKeyEvent->mEventRepeat);
- }
-
- LL_DEBUGS() << "native key data is: " << result << LL_ENDL;
-
- return result;
-}
-#else
/*
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
@@ -2084,23 +1817,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["virtual_key"] = (S32)mKeyVirtualKey;
- result["virtual_key_win"] = (S32)LLKeyboardSDL::mapSDL2toWin( mKeyVirtualKey );
+ result["virtual_key_win"] = (S32)LLKeyboardSDL::mapSDLtoWin( mKeyVirtualKey );
result["modifiers"] = (S32)modifiers;
- result["input_type"] = mInputType;
return result;
}
-#endif // LL_DARWIN
// Open a URL with the user's default web browser.
// Must begin with protocol identifier.
@@ -2125,7 +1856,7 @@ void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async)
LL_INFOS() << "spawn_web_browser: " << escaped_url << LL_ENDL;
- if (SDL_OpenURL(escaped_url.c_str()) != 0)
+ if (!SDL_OpenURL(escaped_url.c_str()))
{
LL_WARNS() << "spawn_web_browser failed with error: " << SDL_GetError() << LL_ENDL;
}
@@ -2133,9 +1864,18 @@ void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async)
LL_INFOS() << "spawn_web_browser returning." << LL_ENDL;
}
-void *LLWindowSDL::getPlatformWindow()
+void* LLWindowSDL::getPlatformWindow()
{
- return NULL;
+ void* ret = nullptr;
+ if (mWindow)
+ {
+#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
+ }
+ return ret;
}
void LLWindowSDL::bringToFront()
@@ -2152,102 +1892,64 @@ void LLWindowSDL::bringToFront()
//static
std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList()
{
- // 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");
- const int max_font_count_cutoff = 40; // fonts are expensive in the current system, don't enumerate an arbitrary number of them
- // Our 'ideal' font properties which define the sorting results.
- // slant=0 means Roman, index=0 means the first face in a font file
- // (the one we actually use), weight=80 means medium weight,
- // spacing=0 means proportional spacing.
- std::string sort_order("slant=0:index=0:weight=80:spacing=0");
- // elide_unicode_coverage removes fonts from the list whose unicode
- // range is covered by fonts earlier in the list. This usually
- // removes ~90% of the fonts as redundant (which is great because
- // the font list can be huge), but might unnecessarily reduce the
- // 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;
-
- LL_INFOS() << "Getting system font list from FontConfig..." << LL_ENDL;
+ // Lazy-loaded fonts, seeded with fonts.xml
+ return std::vector<std::string>();
+}
- // If the user has a system-wide language preference, then favor
- // fonts from that language group. This doesn't affect the types
- // 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_Success success = FL_FindLocale(&locale, FL_MESSAGES);
- if (success != 0)
+LLFontFallbackMatch LLWindowSDL::findFallbackFontForChar(llwchar wch)
+{
+ LLFontFallbackMatch result;
+#if LL_LINUX || __FreeBSD__
+ // FcInit() is idempotent, but this runs per missing codepoint, so only
+ // attempt initialization once.
+ static bool fc_ready = FcInit();
+ if (!fc_ready)
{
- if (success >= 2 && locale->lang) // confident!
- {
- LL_INFOS("AppInit") << "Language " << locale->lang << LL_ENDL;
- LL_INFOS("AppInit") << "Location " << locale->country << LL_ENDL;
- LL_INFOS("AppInit") << "Variant " << locale->variant << LL_ENDL;
-
- LL_INFOS() << "Preferring fonts of language: "
- << locale->lang
- << LL_ENDL;
- sort_order = "lang=" + std::string(locale->lang) + ":"
- + sort_order;
- }
+ LL_WARNS_ONCE() << "FontConfig failed to initialize." << LL_ENDL;
+ return result;
}
- FL_FreeLocale(&locale);
- if (!FcInit())
+ // Ask FontConfig for the best font covering this codepoint.
+ FcCharSet* charset = FcCharSetCreate();
+ FcPattern* pat = FcPatternCreate();
+ if (!charset || !pat)
{
- LL_WARNS() << "FontConfig failed to initialize." << LL_ENDL;
- rtns.push_back(final_fallback);
- return rtns;
+ if (charset) FcCharSetDestroy(charset);
+ if (pat) FcPatternDestroy(pat);
+ return result;
}
- sortpat = FcNameParse((FcChar8*) sort_order.c_str());
- if (sortpat)
- {
- // Sort the list of system fonts from most-to-least-desirable.
- FcResult result;
- fs = FcFontSort(NULL, sortpat, elide_unicode_coverage,
- NULL, &result);
- FcPatternDestroy(sortpat);
- }
+ FcCharSetAddChar(charset, (FcChar32)wch);
+
+ FcPatternAddCharSet(pat, FC_CHARSET, charset);
+ FcPatternAddBool(pat, FC_SCALABLE, FcTrue);
+
+ FcConfigSubstitute(nullptr, pat, FcMatchPattern);
+ FcDefaultSubstitute(pat);
- int found_font_count = 0;
- if (fs)
+ FcResult fc_result;
+ FcPattern* match = FcFontMatch(nullptr, pat, &fc_result);
+ if (match)
{
- // Get the full pathnames to the fonts, where available,
- // which is what we really want.
- found_font_count = fs->nfont;
- for (int i=0; i<fs->nfont; ++i)
+ FcChar8* filename = nullptr;
+ if (FcResultMatch == FcPatternGetString(match, FC_FILE, 0, &filename) && filename)
{
- FcChar8 *filename;
- if (FcResultMatch == FcPatternGetString(fs->fonts[i],
- FC_FILE, 0,
- &filename)
- && filename)
+ result.mPath = (const char*)filename;
+
+ // .ttc/.otc collections carry several faces; get the right one.
+ int index = 0;
+ if (FcResultMatch == FcPatternGetInteger(match, FC_INDEX, 0, &index))
{
- rtns.push_back(std::string((const char*)filename));
- if (rtns.size() >= max_font_count_cutoff)
- break; // hit limit
+ result.mFaceIndex = index;
}
}
- FcFontSetDestroy (fs);
+ FcPatternDestroy(match);
}
- LL_DEBUGS() << "Using font list: " << LL_ENDL;
- for (std::vector<std::string>::iterator 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);
- return rtns;
+ FcPatternDestroy(pat);
+ FcCharSetDestroy(charset);
+#endif
+ return result;
}
void LLWindowSDL::setLanguageTextInput(const LLCoordGL& position)
@@ -2261,5 +1963,78 @@ void LLWindowSDL::setLanguageTextInput(const LLCoordGL& position)
r.w = 500;
r.h = 16;
- SDL_SetTextInputRect(&r);
+ 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 d9b6be5fdc..7156ad66b7 100644
--- a/indra/llwindow/llwindowsdl.h
+++ b/indra/llwindow/llwindowsdl.h
@@ -24,37 +24,35 @@
* $/LicenseInfo$
*/
-#ifndef LL_LLWINDOWSDL2_H
-#define LL_LLWINDOWSDL2_H
+#ifndef LL_LLWINDOWSDL_H
+#define LL_LLWINDOWSDL_H
// Simple Directmedia Layer (http://libsdl.org/) implementation of LLWindow class
#include "llwindow.h"
#include "lltimer.h"
+#include "llmutex.h"
-#if !defined(__i386__) && !defined(__x86_64__) && !_M_X64
-#define SDL_DISABLE_IMMINTRIN_H
+#include "SDL3/SDL.h"
+#include "SDL3/SDL_endian.h"
+
+#ifdef LL_WAYLAND
+#include <wayland-client-protocol.h>
#endif
-#include "SDL2/SDL.h"
-#include "SDL2/SDL_video.h"
-#include "SDL2/SDL_endian.h"
#if LL_X11
-// get X11-specific headers for use in low-level stuff like copy-and-paste support
-#include "SDL2/SDL_syswm.h"
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
#endif
-// AssertMacros.h does bad things.
-#include "fix_macros.h"
-#undef verify
-#undef require
-
+class LLPreeditor;
-class LLWindowSDL : public LLWindow {
+class LLWindowSDL final : public LLWindow
+{
public:
void show() override;
-
void hide() override;
+ void restore() override;
void close() override;
@@ -65,23 +63,16 @@ public:
bool getMaximized() override;
bool maximize() override;
-
void minimize() override;
- void restore() override;
-
- bool getFullscreen();
-
bool getPosition(LLCoordScreen *position) override;
bool getSize(LLCoordScreen *size) override;
-
bool getSize(LLCoordWindow *size) override;
bool setPosition(LLCoordScreen position) override;
bool setSizeImpl(LLCoordScreen size) override;
-
bool setSizeImpl(LLCoordWindow size) override;
bool switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync,
@@ -90,88 +81,67 @@ public:
bool setCursorPosition(LLCoordWindow position) override;
bool getCursorPosition(LLCoordWindow *position) override;
-
bool isWrapMouse() const override { return true; }
-
void showCursor() override;
-
void hideCursor() override;
+ bool isCursorHidden() override;
void showCursorFromMouseMove() override;
-
void hideCursorUntilMouseMove() override;
- bool isCursorHidden() override;
-
void updateCursor() override;
void captureMouse() override;
-
void releaseMouse() override;
void setMouseClipping(bool b) override;
- void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true) override;
+ void 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
- U32 getFSAASamples() override;
+ bool restoreGamma() override; // Restore original gamma table (before updating gamma)
+ U32 getFSAASamples() override;
void setFSAASamples(const U32 samples) override;
- bool restoreGamma() override; // Restore original gamma table (before updating gamma)
- ESwapMethod getSwapMethod() override { return mSwapMethod; }
-
void processMiscNativeEvents() override;
void gatherInput() override;
- void swapBuffers() override;
+ SDL_AppResult handleEvent(const SDL_Event& event);
+ static SDL_AppResult handleEvents(const SDL_Event& event);
- void restoreGLContext() {};
+ void swapBuffers() override;
void delayInputProcessing() override {};
// handy coordinate space conversion routines
bool convertCoords(LLCoordScreen from, LLCoordWindow *to) override;
-
bool convertCoords(LLCoordWindow from, LLCoordScreen *to) override;
-
bool convertCoords(LLCoordWindow from, LLCoordGL *to) override;
-
bool convertCoords(LLCoordGL from, LLCoordWindow *to) override;
-
bool convertCoords(LLCoordScreen from, LLCoordGL *to) override;
-
bool convertCoords(LLCoordGL from, LLCoordScreen *to) override;
LLWindowResolution *getSupportedResolutions(S32 &num_resolutions) override;
F32 getNativeAspectRatio() override;
-
F32 getPixelAspectRatio() override;
-
void setNativeAspectRatio(F32 ratio) override { mOverrideAspectRatio = ratio; }
- F32 getSystemUISize() override;
-
void beforeDialog() override;
-
void afterDialog() override;
bool dialogColorPicker(F32 *r, F32 *g, F32 *b) override;
@@ -187,38 +157,24 @@ public:
void setTitle(const std::string title) override;
static std::vector<std::string> getDynamicFallbackFontList();
+ static LLFontFallbackMatch findFallbackFontForChar(llwchar wch);
- // 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);
-
-#if LL_X11
-
- static Window get_SDL_XWindowID(void);
+ void *createSharedContext() override;
+ void makeContextCurrent(void *context) override;
+ void destroySharedContext(void *context) override;
+ void toggleVSync(bool enable_vsync) override;
- static Display *get_SDL_Display(void);
+ F32 getSystemUISize() override;
-#endif // LL_X11
+ static std::vector<std::string> getDisplaysResolutionList();
#if LL_DARWIN
+ static U64 getVramSize();
+ static void setUseMultGL(bool use_mult_gl);
+
static bool sUseMultGL;
#endif
- void *createSharedContext() override;
-
- void makeContextCurrent(void *context) override;
-
- void destroySharedContext(void *context) override;
-
- void toggleVSync(bool enable_vsync) override;
-
protected:
LLWindowSDL(LLWindowCallbacks *callbacks,
const std::string &title, const std::string& name, int x, int y, int width, int height, U32 flags,
@@ -232,19 +188,8 @@ protected:
LLSD getNativeKeyData() override;
void initCursors();
-
void quitCursors();
- void moveWindow(const LLCoordScreen &position, const LLCoordScreen &size);
-
- // Changes display resolution. Returns true if successful
- bool setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
-
- // Go back to last fullscreen display resolution.
- bool setFullscreenResolution();
-
- bool shouldPostQuit() { return mPostQuit; }
-
protected:
//
// Platform specific methods
@@ -252,50 +197,65 @@ 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 enable_vsync);
-
void destroyContext();
void setupFailure(const std::string &text, const std::string &caption, U32 type);
- U32 SDLCheckGrabbyKeys(U32 keysym, bool gain);
-
bool SDLReallyCaptureInput(bool capture);
+ U32 SDLCheckGrabbyKeys(U32 keysym, bool gain);
//
// Platform specific variables
//
- U32 mGrabbyKeyFlags;
- int mReallyCapturedCount;
-
- SDL_Window *mWindow;
+ U32 mGrabbyKeyFlags = 0;
+ S32 mReallyCapturedCount = 0;
+ SDL_Window *mWindow = nullptr;
SDL_GLContext mContext;
SDL_Cursor *mSDLCursors[UI_CURSOR_COUNT];
std::string mWindowTitle;
- double mOriginalAspectRatio;
- bool mNeedsResize; // Constructor figured out the window is too big, it needs a resize.
- LLCoordScreen mNeedsResizeSize;
- F32 mOverrideAspectRatio;
- F32 mGamma;
- U32 mFSAASamples;
-
- int mSDLFlags;
-
- int mHaveInputFocus; /* 0=no, 1=yes, else unknown */
- int mIsMinimized; /* 0=no, 1=yes, else unknown */
+ F32 mNativeAspectRatio = 0.0f;
+ F32 mOverrideAspectRatio = 0.0f;
+ F32 mGamma = 0.0f;
+ U32 mFSAASamples = 0;
friend class LLWindowManager;
private:
- bool mFlashing;
+ bool mFlashing = false;
LLTimer mFlashTimer;
- U32 mKeyVirtualKey;
- U32 mKeyModifiers;
- std::string mInputType;
+ U32 mKeyVirtualKey = 0;
+ U32 mKeyModifiers = SDL_KMOD_NONE;
+ LLMutex mOSRMutex;
+ std::unordered_map<SDL_GLContext, SDL_Window*> mOSRContexts;
+ std::list<SDL_Window*> mDeadOSRWindows;
-private:
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
@@ -304,9 +264,9 @@ public:
LLSplashScreenSDL();
virtual ~LLSplashScreenSDL();
- void showImpl();
- void updateImpl(const std::string& mesg);
- 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 5793254ded..7f371ff0cf 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -177,6 +177,19 @@ void show_window_creation_error(const std::string& title)
LL_WARNS("Window") << title << LL_ENDL;
}
+static bool is_thread_from_current_process(DWORD thread_id)
+{
+ HANDLE thread_handle = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, thread_id);
+ if (!thread_handle)
+ {
+ return false;
+ }
+
+ const DWORD process_id = GetProcessIdOfThread(thread_handle);
+ CloseHandle(thread_handle);
+ return process_id == GetCurrentProcessId();
+}
+
HGLRC SafeCreateContext(HDC &hdc)
{
__try
@@ -214,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;
@@ -518,6 +532,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
:
LLWindow(callbacks, fullscreen, flags),
mAbsoluteCursorPosition(false),
+ mReceivedSCClose(false),
mMaxGLVersion(max_gl_version),
mMaxCores(max_cores)
{
@@ -525,7 +540,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
@@ -1432,7 +1447,7 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo
catch (...)
{
LOG_UNHANDLED_EXCEPTION("ChoosePixelFormat");
- LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBPixelFmtErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
+ LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBPixelFmtErr"), LLError::LLUserWarningMsg::ERROR_INIT_FAILED);
close();
return false;
}
@@ -1443,7 +1458,7 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo
if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),
&pfd))
{
- LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBPixelFmtDescErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
+ LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBPixelFmtDescErr"), LLError::LLUserWarningMsg::ERROR_INIT_FAILED);
close();
return false;
}
@@ -1481,7 +1496,7 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo
if (!SetPixelFormat(mhDC, pixel_format, &pfd))
{
- LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBPixelFmtSetErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
+ LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBPixelFmtSetErr"), LLError::LLUserWarningMsg::ERROR_INIT_FAILED);
close();
return false;
}
@@ -1489,14 +1504,14 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo
if (!(mhRC = SafeCreateContext(mhDC)))
{
- LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBGLContextErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
+ LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBGLContextErr"), LLError::LLUserWarningMsg::ERROR_INIT_FAILED);
close();
return false;
}
if (!wglMakeCurrent(mhDC, mhRC))
{
- LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBGLContextActErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
+ LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBGLContextActErr"), LLError::LLUserWarningMsg::ERROR_INIT_FAILED);
close();
return false;
}
@@ -1702,14 +1717,14 @@ const S32 max_format = (S32)num_formats - 1;
if (!mhDC)
{
- LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBDevContextErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
+ LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBDevContextErr"), LLError::LLUserWarningMsg::ERROR_INIT_FAILED);
close();
return false;
}
if (!SetPixelFormat(mhDC, pixel_format, &pfd))
{
- LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBPixelFmtSetErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
+ LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBPixelFmtSetErr"), LLError::LLUserWarningMsg::ERROR_INIT_FAILED);
close();
return false;
}
@@ -1741,7 +1756,7 @@ const S32 max_format = (S32)num_formats - 1;
{
LL_WARNS("Window") << "No wgl_ARB_pixel_format extension!" << LL_ENDL;
// cannot proceed without wgl_ARB_pixel_format extension, shutdown same as any other gGLManager.initGL() failure
- LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBVideoDrvErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
+ LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBVideoDrvErr"), LLError::LLUserWarningMsg::ERROR_INIT_FAILED);
close();
return false;
}
@@ -1750,7 +1765,7 @@ const S32 max_format = (S32)num_formats - 1;
if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),
&pfd))
{
- LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBPixelFmtDescErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
+ LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBPixelFmtDescErr"), LLError::LLUserWarningMsg::ERROR_INIT_FAILED);
close();
return false;
}
@@ -1772,14 +1787,16 @@ const S32 max_format = (S32)num_formats - 1;
if (!wglMakeCurrent(mhDC, mhRC))
{
- LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBGLContextActErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
+ LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBGLContextActErr"), LLError::LLUserWarningMsg::ERROR_INIT_FAILED);
close();
return false;
}
+ gGLManager.initWGL(); // Reinit WGL functions once we have our full context
+
if (!gGLManager.initGL())
{
- LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBVideoDrvErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
+ LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBVideoDrvErr"), LLError::LLUserWarningMsg::ERROR_INIT_FAILED);
close();
return false;
}
@@ -1987,7 +2004,7 @@ void* LLWindowWin32::createSharedContext()
if (!rc && !(rc = wglCreateContext(mhDC)))
{
close();
- LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBGLContextErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
+ LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBGLContextErr"), LLError::LLUserWarningMsg::ERROR_INIT_FAILED);
}
return rc;
@@ -2472,6 +2489,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
update_width, update_height));
break;
}
+ case WM_ERASEBKGND:
+ {
+ RECT client_rect;
+ if (GetClientRect(h_wnd, &client_rect))
+ {
+ FillRect((HDC)w_param, &client_rect, (HBRUSH)GetStockObject(BLACK_BRUSH));
+ }
+ return 1;
+ }
case WM_PARENTNOTIFY:
{
break;
@@ -2506,23 +2532,27 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
break;
}
- case WM_POWERBROADCAST:
- {
- // Might need to register for power broadcast interface
- // Todo: log monitor suspending and resuming.
- LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_POWERBROADCAST");
- LL_INFOS("Window") << "Received WM_POWERBROADCAST with wParam: 0x" << std::hex << (uintptr_t)w_param << " lParam: 0x" << (uintptr_t)l_param << std::dec << LL_ENDL;
- break;
- }
-
case WM_ACTIVATEAPP:
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_ACTIVATEAPP");
+ // Resolve ownership before deferring the work because thread IDs can
+ // be reused after a thread exits.
+ const bool activating_same_process_thread =
+ !w_param && is_thread_from_current_process(static_cast<DWORD>(l_param));
window_imp->post([=]()
{
// This message should be sent whenever the app gains or loses focus.
BOOL activating = (BOOL)w_param;
+ // Native dialogs run on a worker thread. Moving focus between
+ // the viewer and one of those dialogs must not be treated as
+ // switching to another application: in fullscreen that would
+ // minimize the viewer and hide its owned dialog.
+ if (!activating && activating_same_process_thread)
+ {
+ activating = TRUE;
+ }
+
if (window_imp->mFullscreen)
{
// When we run fullscreen, restoring or minimizing the app needs
@@ -2572,8 +2602,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_SYSCOMMAND:
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_SYSCOMMAND");
- switch (w_param)
+ switch (w_param & 0xFFF0)
{
+ case SC_CLOSE:
+ // User clicked close from system menu/taskbar or 'end process' from task manager
+ // Do nothing, will cause WM_CLOSE.
+ // If we don't get this message before WM_CLOSE, we are likely getting
+ // a kill from some external program. Win11 task manager Does cause SC_CLOSE.
+ window_imp->mReceivedSCClose = true;
+ break;
case SC_KEYMENU:
// Disallow the ALT key from triggering the default system menu.
return 0;
@@ -2589,9 +2626,30 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_CLOSE");
window_imp->mWindowThread->pingWindowTimeout("WM_CLOSE");
- // todo: WM_CLOSE can be caused by user and by task manager,
- // distinguish these cases.
- // For now assume it is always user.
+
+ window_imp->mCallbacks->handlePreCloseRequest(); // mark app as potentially closing
+ if (!window_imp->mReceivedSCClose)
+ {
+ // Some external program is trying to close the app.
+ // Assume that it's going to destroy process if it fails
+ // and try to fast-quit without confirmation or cleanup.
+ window_imp->post([=]()
+ {
+ // Check if app needs cleanup or can be closed immediately.
+ if (window_imp->mCallbacks->handleSessionExit(window_imp))
+ {
+ // Get the app to initiate cleanup.
+ window_imp->mCallbacks->handleQuit(window_imp);
+ }
+ });
+ return 0;
+ }
+ window_imp->mReceivedSCClose = false;
+
+ // There is no way to tell the difference between a user issued
+ // WM_CLOSE or task manager's WM_CLOSE.
+ // Assume it is a user and ask for confirmation, but create a marker file.
+ // If App keeps doing something after a second, or gets 'destroy' message clear the marker.
window_imp->post([=]()
{
// Will the app allow the window to close?
@@ -2613,6 +2671,16 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
}
return 0;
}
+ case WM_NCDESTROY:
+ LL_INFOS("Window") << "Received WM_NCDESTROY" << LL_ENDL;
+ break;
+ case WM_WTSSESSION_CHANGE:
+ {
+ // Detects Remote Desktop disconnects, fast user switching, session logoff
+ // w_param: WTS_CONSOLE_CONNECT, WTS_CONSOLE_DISCONNECT, WTS_SESSION_LOGOFF, etc.
+ LL_INFOS("Window") << "Received WM_WTSSESSION_CHANGE with wParam: " << (U32)w_param << LL_ENDL;
+ break;
+ }
case WM_QUERYENDSESSION:
{
// Generally means that OS is going to shut down or user is going to log off.
@@ -2635,8 +2703,10 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
|| (end_session_flags & ENDSESSION_CRITICAL) // will shutdown regardless of app state
|| (end_session_flags & ENDSESSION_LOGOFF)) // logoff, can delay shutdown
{
+ window_imp->mCallbacks->handlePreCloseRequest(); // mark app as closing
window_imp->post([=]()
{
+ LL_INFOS("Window") << "Shutting down due to session terminating" << LL_ENDL;
// Check if app needs cleanup or can be closed immediately.
if (window_imp->mCallbacks->handleSessionExit(window_imp))
{
@@ -2655,6 +2725,193 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// if session is ending OS is going to take care of it.
return 0;
}
+ case WM_POWERBROADCAST:
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_POWERBROADCAST");
+ switch (w_param)
+ {
+ case PBT_APMSUSPEND:
+ LL_INFOS("Window") << "System is suspending (sleep/hibernate)" << LL_ENDL;
+ // System is about to enter sleep or hibernation
+ // Viewer can't function in hibernation, try to shut down.
+ // The system allows approximately two seconds for an
+ // application to handle this notification.
+
+ // Mark app as potentially closing, to minimize issues if OS does not recover.
+ window_imp->mCallbacks->handlePreCloseRequest();
+ window_imp->post([=]()
+ {
+ window_imp->mCallbacks->handleSuspendRequest();
+ });
+ // Window thread normally doesn't block main thread, but OS can suspend
+ // immediately if we don't wait.
+ // Keep OS from suspending to give a chance to send stats.
+ ms_sleep(1000);
+ return TRUE;
+
+ case PBT_APMRESUMESUSPEND:
+ LL_INFOS("Window") << "System is resuming from suspend" << LL_ENDL;
+ window_imp->mCallbacks->handleCloseRequestCanceled();
+ return TRUE;
+
+ case PBT_APMPOWERSTATUSCHANGE:
+ LL_INFOS("Window") << "Power status has changed" << LL_ENDL;
+ // Power status change (AC/battery)
+ // Viewer requires high performance, not much we can do.
+ // about it, but log for diagnostic purposes (example:
+ // OS trying to throw viewer at an iGPU after this message)
+ return TRUE;
+
+ default:
+ LL_INFOS("Window") << "Received WM_POWERBROADCAST with wParam: 0x" << std::hex << (uintptr_t)w_param << " lParam: 0x" << (uintptr_t)l_param << std::dec << LL_ENDL;
+ break;
+ }
+ break;
+ }
+ case WM_POST_UNINSTALL_:
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_POST_UNINSTALL_");
+ // Other instance, likely velopack, requested we quit.
+ // Don't trust PID alone (can be spoofed), verify the
+ // path for security purposes before processing.
+ // Verifying path isn't a strong varranty, if this turns
+ // up to be a risk, we will want something more secure.
+ // See sendShutdownToOtherInstances for the sender.
+
+ // LPARAM contains message type.
+ DWORD message_type = static_cast<DWORD>(l_param);
+ if (message_type == WM_POST_UNINSTALL_MSG_SHUTDOWN || message_type == WM_POST_UNINSTALL_MSG_UPDATE)
+ {
+ DWORD sender_process_id = static_cast<DWORD>(w_param);
+
+ // Make sure something didn't just send us our own process
+ DWORD our_process_id = GetCurrentProcessId();
+ if (our_process_id == sender_process_id)
+ {
+ LL_WARNS("Window") << "Received WM_POST_UNINSTALL_ from our own process, ignoring" << LL_ENDL;
+ break;
+ }
+
+ if (sender_process_id == 0)
+ {
+ LL_WARNS("Window") << "Received WM_POST_UNINSTALL_ but couldn't get sender process ID" << LL_ENDL;
+ break;
+ }
+
+ // Open the existing sender process to verify its executable path
+ HANDLE hSenderProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, sender_process_id);
+ if (!hSenderProcess)
+ {
+ LL_WARNS("Window") << "Received WM_POST_UNINSTALL_ but couldn't open sender process" << LL_ENDL;
+ break;
+ }
+
+ // Get the actual executable path of the sender
+ wchar_t sender_exe_path[MAX_PATH];
+ DWORD size = MAX_PATH;
+ bool got_sender_path = QueryFullProcessImageNameW(hSenderProcess, 0, sender_exe_path, &size) != 0;
+ CloseHandle(hSenderProcess);
+
+ if (!got_sender_path)
+ {
+ LL_WARNS("Window") << "Received WM_POST_UNINSTALL_ but couldn't query sender executable path" << LL_ENDL;
+ break;
+ }
+
+ // Extract directory from sender's executable path
+ wchar_t sender_dir[MAX_PATH];
+ wchar_t* file_part = nullptr;
+ DWORD result = GetFullPathNameW(sender_exe_path, MAX_PATH, sender_dir, &file_part);
+
+ if (result == 0 || result >= MAX_PATH)
+ {
+ LL_WARNS("Window") << "Failed to normalize sender executable path" << LL_ENDL;
+ break;
+ }
+
+ // Remove the filename to get just directory
+ if (file_part)
+ {
+ *file_part = L'\0';
+ }
+
+ // Remove trailing backslash
+ size_t sender_dir_len = wcslen(sender_dir);
+ if (sender_dir_len > 0 && sender_dir[sender_dir_len - 1] == L'\\')
+ {
+ sender_dir[sender_dir_len - 1] = L'\0';
+ sender_dir_len--;
+ }
+
+ // Remove "\current" suffix from sender's path if present
+ const std::wstring current_suffix = L"\\current";
+ std::wstring sender_normalized_str(sender_dir);
+ if (sender_normalized_str.length() >= current_suffix.length() &&
+ _wcsicmp(sender_normalized_str.c_str() + sender_normalized_str.length() - current_suffix.length(),
+ current_suffix.c_str()) == 0)
+ {
+ sender_normalized_str.resize(sender_normalized_str.length() - current_suffix.length());
+ }
+
+ // Get our executable directory for comparison
+ std::wstring our_wide = ll_convert<std::wstring>(gDirUtilp->getExecutableDir());
+
+ // Normalize our path
+ wchar_t our_normalized[MAX_PATH];
+ file_part = nullptr;
+
+ DWORD result2 = GetFullPathNameW(our_wide.c_str(), MAX_PATH, our_normalized, &file_part);
+
+ if (result2 == 0 || result2 >= MAX_PATH)
+ {
+ LL_WARNS("Window") << "Failed to normalize our executable path" << LL_ENDL;
+ break;
+ }
+
+ // Remove trailing backslash
+ size_t our_len = wcslen(our_normalized);
+ if (our_len > 0 && our_normalized[our_len - 1] == L'\\')
+ {
+ our_normalized[our_len - 1] = L'\0';
+ our_len--;
+ }
+
+ // Remove "\current" suffix from our path if present
+ std::wstring our_normalized_str(our_normalized);
+ if (our_normalized_str.length() >= current_suffix.length() &&
+ _wcsicmp(our_normalized_str.c_str() + our_normalized_str.length() - current_suffix.length(),
+ current_suffix.c_str()) == 0)
+ {
+ our_normalized_str.resize(our_normalized_str.length() - current_suffix.length());
+ }
+
+ // Compare the normalized base installation paths (case-insensitive)
+ if (_wcsicmp(sender_normalized_str.c_str(), our_normalized_str.c_str()) == 0)
+ {
+ window_imp->post([=]()
+ {
+ LL_INFOS("Window") << "Received valid shutdown request from verified same installation directory" << LL_ENDL;
+ // Check if app needs cleanup or can be closed immediately.
+ if (window_imp->mCallbacks->handleCloseRequest(window_imp, false))
+ {
+ // Get the app to initiate cleanup.
+ window_imp->mCallbacks->handleQuit(window_imp);
+ }
+ });
+ }
+ else
+ {
+ LL_WARNS("Window") << "Rejected shutdown request - sender not from our installation directory. "
+ << "Sender: " << ll_convert_wide_to_string(sender_normalized_str)
+ << " Our: " << ll_convert_wide_to_string(our_normalized_str) << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_WARNS("Window") << "Received invalid WM_POST_UNINSTALL_ message" << LL_ENDL;
+ }
+ break;
+ }
case WM_COMMAND:
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_COMMAND");
@@ -3183,9 +3440,19 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_DISPLAYCHANGE:
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_DISPLAYCHANGE");
window_imp->mWindowThread->pingWindowTimeout("WM_DISPLAYCHANGE");
- WINDOW_IMP_POST(window_imp->mCallbacks->handleDisplayChanged());
- break;
+ window_imp->post([=]() {
+ window_imp->mCallbacks->handleDisplayChanged();
+ // Note: WM_DISPLAYCHANGE was passing to WM_SETFOCUS
+ // which might have been unintended and was messing with zones.
+ // handleFocus was copied over and return 0 added, but
+ // handleFocus might be not needed here.
+ // handleFocus resets mouse, closes popups and keys, which
+ // we probablt should do on 'display change'.
+ window_imp->mCallbacks->handleFocus(window_imp);
+ });
+ return 0;
}
case WM_SETFOCUS:
@@ -5053,6 +5320,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();
@@ -5064,6 +5343,12 @@ std::vector<std::string> LLWindowWin32::getDynamicFallbackFontList()
// Fonts previously in getFontListSans() have moved to fonts.xml.
return std::vector<std::string>();
}
+
+LLFontFallbackMatch LLWindowWin32::findFallbackFontForChar(llwchar wch)
+{
+ // Not implemented on Windows; would use DirectWrite (IDWriteFontFallback::MapCharacters).
+ return LLFontFallbackMatch();
+}
#endif // LL_WINDOWS
inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread()
diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h
index aab2635a34..0b104c6da8 100644
--- a/indra/llwindow/llwindowwin32.h
+++ b/indra/llwindow/llwindowwin32.h
@@ -40,6 +40,12 @@
// Hack for async host by name
#define LL_WM_HOST_RESOLVED (WM_APP + 1)
+// For requesting shutdown on uninstall,
+// make sure it does not conflict with messages like WM_DUMMY_
+inline constexpr UINT WM_POST_UNINSTALL_ = WM_USER + 0x0019;
+inline constexpr DWORD WM_POST_UNINSTALL_MSG_SHUTDOWN = 1;
+inline constexpr DWORD WM_POST_UNINSTALL_MSG_UPDATE = 2;
+
typedef void (*LLW32MsgCallback)(const MSG &msg);
class LLWindowWin32 : public LLWindow
@@ -124,8 +130,10 @@ 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 LLFontFallbackMatch findFallbackFontForChar(llwchar wch);
static void setDPIAwareness();
void* getDirectInput8() override;
@@ -232,6 +240,7 @@ protected:
LPWSTR mIconResource;
LPWSTR mIconSmallResource;
bool mInputProcessingPaused;
+ bool mReceivedSCClose; // received SC_CLOSE and expecting WM_CLOSE
// The following variables are for Language Text Input control.
// They are all static, since one context is shared by all LLWindowWin32
@@ -258,6 +267,8 @@ protected:
bool mMouseVanish;
+ static HMODULE sGLDLLHandle;
+
// Cached values of GetWindowRect and GetClientRect to be used by app thread
void updateWindowRect();
RECT mRect;