summaryrefslogtreecommitdiff
path: root/indra/llwindow
diff options
context:
space:
mode:
authorAndrey Lihatskiy <alihatskiy@productengine.com>2024-10-17 16:56:21 +0300
committerGitHub <noreply@github.com>2024-10-17 16:56:21 +0300
commit0ef7a9b39cf72da1211039ab22bdf8f9f6a2c984 (patch)
tree6f51ef179497265b5bff2a355471ae5dc9643ad2 /indra/llwindow
parent9e24b300d02e5627ea0d304d412cb683ec2de3a4 (diff)
parentd3d349ae0f17a72481f30b9354b9367b1cd3b639 (diff)
Merge pull request #2856 from secondlife/marchcat/c-develop
Develop → Maint C sync
Diffstat (limited to 'indra/llwindow')
-rw-r--r--indra/llwindow/CMakeLists.txt25
-rw-r--r--indra/llwindow/lldragdropwin32.cpp10
-rw-r--r--indra/llwindow/lldragdropwin32.h4
-rw-r--r--indra/llwindow/lldxhardware.cpp36
-rw-r--r--indra/llwindow/lldxhardware.h12
-rw-r--r--indra/llwindow/llgamecontrol.cpp2122
-rw-r--r--indra/llwindow/llgamecontrol.h347
-rw-r--r--indra/llwindow/llgamecontroltranslator.cpp275
-rw-r--r--indra/llwindow/llgamecontroltranslator.h93
-rw-r--r--indra/llwindow/llkeyboard.cpp125
-rw-r--r--indra/llwindow/llkeyboard.h50
-rw-r--r--indra/llwindow/llkeyboardheadless.cpp25
-rw-r--r--indra/llwindow/llkeyboardheadless.h14
-rw-r--r--indra/llwindow/llkeyboardmacosx.cpp31
-rw-r--r--indra/llwindow/llkeyboardmacosx.h20
-rw-r--r--indra/llwindow/llkeyboardsdl.cpp471
-rw-r--r--indra/llwindow/llkeyboardsdl.h38
-rw-r--r--indra/llwindow/llkeyboardwin32.cpp38
-rw-r--r--indra/llwindow/llkeyboardwin32.h21
-rw-r--r--indra/llwindow/llmousehandler.cpp4
-rw-r--r--indra/llwindow/llmousehandler.h26
-rw-r--r--indra/llwindow/llpreeditor.h8
-rw-r--r--indra/llwindow/llsdl.cpp102
-rw-r--r--indra/llwindow/llsdl.h30
-rw-r--r--indra/llwindow/llwindow.cpp118
-rw-r--r--indra/llwindow/llwindow.h145
-rw-r--r--indra/llwindow/llwindowcallbacks.cpp82
-rw-r--r--indra/llwindow/llwindowcallbacks.h44
-rw-r--r--indra/llwindow/llwindowheadless.cpp4
-rw-r--r--indra/llwindow/llwindowheadless.h121
-rw-r--r--indra/llwindow/llwindowmacosx-objc.h5
-rw-r--r--indra/llwindow/llwindowmacosx-objc.mm7
-rw-r--r--indra/llwindow/llwindowmacosx.cpp253
-rw-r--r--indra/llwindow/llwindowmacosx.h109
-rw-r--r--indra/llwindow/llwindowmesaheadless.cpp4
-rw-r--r--indra/llwindow/llwindowmesaheadless.h118
-rw-r--r--indra/llwindow/llwindowsdl.cpp2394
-rw-r--r--indra/llwindow/llwindowsdl.h322
-rw-r--r--indra/llwindow/llwindowwin32.cpp861
-rw-r--r--indra/llwindow/llwindowwin32.h186
40 files changed, 5652 insertions, 3048 deletions
diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt
index 7b1430c67c..e86ef2d578 100644
--- a/indra/llwindow/CMakeLists.txt
+++ b/indra/llwindow/CMakeLists.txt
@@ -17,11 +17,16 @@ include(LLImage)
include(LLWindow)
include(UI)
include(ViewerMiscLibs)
+include(GLM)
+include(SDL2)
set(llwindow_SOURCE_FILES
llcursortypes.cpp
+ llgamecontrol.cpp
+ llgamecontroltranslator.cpp
llkeyboard.cpp
llkeyboardheadless.cpp
+ llsdl.cpp
llwindowheadless.cpp
llwindowcallbacks.cpp
llwindow.cpp
@@ -31,8 +36,11 @@ set(llwindow_HEADER_FILES
CMakeLists.txt
llcursortypes.h
+ llgamecontrol.h
+ llgamecontroltranslator.h
llkeyboard.h
llkeyboardheadless.h
+ llsdl.h
llwindowheadless.h
llwindowcallbacks.h
)
@@ -54,16 +62,18 @@ set(llwindow_LINK_LIBRARIES
llrender
llfilesystem
llxml
- ll::glh_linear
+ ll::glm
ll::glext
ll::uilibraries
- ll::SDL
+ ll::SDL2
+ ll::zlib-ng
)
+
# Libraries on which this library depends, needed for Linux builds
# Sort by high-level to low-level
if (LINUX)
- list(APPEND viewer_SOURCE_FILES
- llkeyboardsdl.cpp
+ list(APPEND viewer_SOURCE_FILES
+ llkeyboardsdl.cpp
llwindowsdl.cpp
)
list(APPEND viewer_HEADER_FILES
@@ -83,7 +93,6 @@ if (LINUX)
fontconfig # For FCInit and other FC* functions.
)
endif (BUILD_HEADLESS)
-
endif (LINUX)
if (DARWIN)
@@ -171,15 +180,15 @@ endif (llwindow_HEADER_FILES)
${viewer_SOURCE_FILES}
)
-if (SDL_FOUND)
+if (SDL2_FOUND)
set_property(TARGET llwindow
PROPERTY COMPILE_DEFINITIONS LL_SDL=1
)
-endif (SDL_FOUND)
+endif (SDL2_FOUND)
target_link_libraries (llwindow ${llwindow_LINK_LIBRARIES})
target_include_directories(llwindow INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
-
+
if (DARWIN)
include(CMakeFindFrameworks)
find_library(CARBON_LIBRARY Carbon)
diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp
index b164eb9579..15490ef953 100644
--- a/indra/llwindow/lldragdropwin32.cpp
+++ b/indra/llwindow/lldragdropwin32.cpp
@@ -124,7 +124,7 @@ class LLDragDropWin32Target:
ScreenToClient( mAppWindowHandle, &pt2 );
LLCoordWindow cursor_coord_window( pt2.x, pt2.y );
- MASK mask = gKeyboard->currentMask(TRUE);
+ MASK mask = gKeyboard->currentMask(true);
LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( cursor_coord_window.convert(), mask,
LLWindowCallbacks::DNDA_START_TRACKING, mDropUrl );
@@ -179,7 +179,7 @@ class LLDragDropWin32Target:
ScreenToClient( mAppWindowHandle, &pt2 );
LLCoordWindow cursor_coord_window( pt2.x, pt2.y );
- MASK mask = gKeyboard->currentMask(TRUE);
+ MASK mask = gKeyboard->currentMask(true);
LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( cursor_coord_window.convert(), mask,
LLWindowCallbacks::DNDA_TRACK, mDropUrl );
@@ -219,7 +219,7 @@ class LLDragDropWin32Target:
if (NULL != window_imp)
{
LLCoordGL gl_coord( 0, 0 );
- MASK mask = gKeyboard->currentMask(TRUE);
+ MASK mask = gKeyboard->currentMask(true);
window_imp->completeDragNDropRequest( gl_coord, mask, LLWindowCallbacks::DNDA_STOP_TRACKING, mDropUrl );
};
return S_OK;
@@ -249,7 +249,7 @@ class LLDragDropWin32Target:
LL_INFOS() << LL_ENDL;
// no keyboard modifier option yet but we could one day
- MASK mask = gKeyboard->currentMask( TRUE );
+ MASK mask = gKeyboard->currentMask( true );
// actually do the drop
LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask,
@@ -312,7 +312,7 @@ LLDragDropWin32::~LLDragDropWin32()
bool LLDragDropWin32::init( HWND hWnd )
{
if ( NOERROR != OleInitialize( NULL ) )
- return FALSE;
+ return false;
mDropTarget = new LLDragDropWin32Target( hWnd );
if ( mDropTarget )
diff --git a/indra/llwindow/lldragdropwin32.h b/indra/llwindow/lldragdropwin32.h
index 1b30dced27..16d016677b 100644
--- a/indra/llwindow/lldragdropwin32.h
+++ b/indra/llwindow/lldragdropwin32.h
@@ -31,7 +31,7 @@
#ifndef LL_LLDRAGDROP32_H
#define LL_LLDRAGDROP32_H
-#include "llwin32headerslean.h"
+#include "llwin32headers.h"
#include <ole2.h>
class LLDragDropWin32
@@ -54,7 +54,7 @@ class LLDragDropWin32
#ifndef LL_LLDRAGDROP32_H
#define LL_LLDRAGDROP32_H
-#include "llwin32headerslean.h"
+#include "llwin32headers.h"
#include <ole2.h>
// impostor class that does nothing
diff --git a/indra/llwindow/lldxhardware.cpp b/indra/llwindow/lldxhardware.cpp
index f972e8f628..4bc069c5a4 100644
--- a/indra/llwindow/lldxhardware.cpp
+++ b/indra/llwindow/lldxhardware.cpp
@@ -216,7 +216,7 @@ HRESULT GetVideoMemoryViaWMI(WCHAR* strInputDeviceID, DWORD* pdwAdapterRam)
}
//static
-S32 LLDXHardware::getMBVideoMemoryViaWMI()
+U32 LLDXHardware::getMBVideoMemoryViaWMI()
{
DWORD vram = 0;
if (SUCCEEDED(GetVideoMemoryViaWMI(NULL, &vram)))
@@ -343,7 +343,7 @@ std::string LLDXHardware::getDriverVersionWMI(EGPUVendor vendor)
//convert BSTR to std::string
std::wstring ws(caption, SysStringLen(caption));
- std::string caption_str(ws.begin(), ws.end());
+ std::string caption_str = ll_convert_wide_to_string(ws);
LLStringUtil::toLower(caption_str);
bool found = false;
@@ -395,7 +395,7 @@ std::string LLDXHardware::getDriverVersionWMI(EGPUVendor vendor)
//convert BSTR to std::string
std::wstring ws(driverVersion, SysStringLen(driverVersion));
- std::string str(ws.begin(), ws.end());
+ std::string str = ll_convert_wide_to_string(ws);
LL_INFOS("AppInit") << " DriverVersion : " << str << LL_ENDL;
if (mDriverVersion.empty())
@@ -441,7 +441,7 @@ std::string LLDXHardware::getDriverVersionWMI(EGPUVendor vendor)
return mDriverVersion;
}
-void get_wstring(IDxDiagContainer* containerp, WCHAR* wszPropName, WCHAR* wszPropValue, int outputSize)
+void get_wstring(IDxDiagContainer* containerp, const WCHAR* wszPropName, WCHAR* wszPropValue, int outputSize)
{
HRESULT hr;
VARIANT var;
@@ -454,10 +454,10 @@ void get_wstring(IDxDiagContainer* containerp, WCHAR* wszPropName, WCHAR* wszPro
switch( var.vt )
{
case VT_UI4:
- swprintf( wszPropValue, L"%d", var.ulVal ); /* Flawfinder: ignore */
+ swprintf( wszPropValue, outputSize, L"%d", var.ulVal ); /* Flawfinder: ignore */
break;
case VT_I4:
- swprintf( wszPropValue, L"%d", var.lVal ); /* Flawfinder: ignore */
+ swprintf( wszPropValue, outputSize, L"%d", var.lVal ); /* Flawfinder: ignore */
break;
case VT_BOOL:
wcscpy( wszPropValue, (var.boolVal) ? L"true" : L"false" ); /* Flawfinder: ignore */
@@ -472,7 +472,7 @@ void get_wstring(IDxDiagContainer* containerp, WCHAR* wszPropName, WCHAR* wszPro
VariantClear( &var );
}
-std::string get_string(IDxDiagContainer *containerp, WCHAR *wszPropName)
+std::string get_string(IDxDiagContainer *containerp, const WCHAR *wszPropName)
{
WCHAR wszPropValue[256];
get_wstring(containerp, wszPropName, wszPropValue, 256);
@@ -483,7 +483,7 @@ std::string get_string(IDxDiagContainer *containerp, WCHAR *wszPropName)
LLVersion::LLVersion()
{
- mValid = FALSE;
+ mValid = false;
S32 i;
for (i = 0; i < 4; i++)
{
@@ -491,7 +491,7 @@ LLVersion::LLVersion()
}
}
-BOOL LLVersion::set(const std::string &version_string)
+bool LLVersion::set(const std::string &version_string)
{
S32 i;
for (i = 0; i < 4; i++)
@@ -518,11 +518,11 @@ BOOL LLVersion::set(const std::string &version_string)
{
mFields[i] = 0;
}
- mValid = FALSE;
+ mValid = false;
}
else
{
- mValid = TRUE;
+ mValid = true;
}
return mValid;
}
@@ -678,10 +678,10 @@ LLDXDevice *LLDXHardware::findDevice(const std::string &vendor, const std::strin
}
*/
-BOOL LLDXHardware::getInfo(BOOL vram_only)
+bool LLDXHardware::getInfo(bool vram_only)
{
LLTimer hw_timer;
- BOOL ok = FALSE;
+ bool ok = false;
HRESULT hr;
// CLSID_DxDiagProvider does not work with Multithreaded?
@@ -809,7 +809,7 @@ BOOL LLDXHardware::getInfo(BOOL vram_only)
if (vram_only)
{
- ok = TRUE;
+ ok = true;
goto LCleanup;
}
@@ -869,7 +869,7 @@ BOOL LLDXHardware::getInfo(BOOL vram_only)
tokenizer::iterator iter = tokens.begin();
S32 count = 0;
- BOOL valid = TRUE;
+ bool valid = true;
for (;(iter != tokens.end()) && (count < 3);++iter)
{
switch (count)
@@ -877,7 +877,7 @@ BOOL LLDXHardware::getInfo(BOOL vram_only)
case 0:
if (strcmp(iter->c_str(), "PCI"))
{
- valid = FALSE;
+ valid = false;
}
break;
case 1:
@@ -948,7 +948,7 @@ BOOL LLDXHardware::getInfo(BOOL vram_only)
}
// dumpDevices();
- ok = TRUE;
+ ok = true;
LCleanup:
if (!ok)
@@ -1059,7 +1059,7 @@ LLSD LLDXHardware::getDisplayInfo()
// Dump the string as an int into the structure
char *stopstring;
- ret["VRAM"] = strtol(ram_str.c_str(), &stopstring, 10);
+ ret["VRAM"] = LLSD::Integer(strtol(ram_str.c_str(), &stopstring, 10));
std::string device_name = get_string(device_containerp, L"szDescription");
ret["DeviceName"] = device_name;
std::string device_driver= get_string(device_containerp, L"szDriverVersion");
diff --git a/indra/llwindow/lldxhardware.h b/indra/llwindow/lldxhardware.h
index 12273e97bc..2b879e021c 100644
--- a/indra/llwindow/lldxhardware.h
+++ b/indra/llwindow/lldxhardware.h
@@ -37,12 +37,12 @@ class LLVersion
{
public:
LLVersion();
- BOOL set(const std::string &version_string);
+ bool set(const std::string &version_string);
S32 getField(const S32 field_num);
protected:
std::string mVersionString;
S32 mFields[4];
- BOOL mValid;
+ bool mValid;
};
class LLDXDriverFile
@@ -84,9 +84,9 @@ public:
void setWriteDebugFunc(void (*func)(const char*));
void cleanup();
- // Returns TRUE on success.
- // vram_only TRUE does a "light" probe.
- BOOL getInfo(BOOL vram_only);
+ // Returns true on success.
+ // vram_only true does a "light" probe.
+ bool getInfo(bool vram_only);
// WMI can return multiple GPU drivers
// specify which one to output
@@ -104,7 +104,7 @@ public:
// Will get memory of best GPU in MB, return memory on sucsess, 0 on failure
// Note: WMI is not accurate in some cases
- static S32 getMBVideoMemoryViaWMI();
+ static U32 getMBVideoMemoryViaWMI();
// Find a particular device that matches the following specs.
// Empty strings indicate that you don't care.
diff --git a/indra/llwindow/llgamecontrol.cpp b/indra/llwindow/llgamecontrol.cpp
new file mode 100644
index 0000000000..9d3c854ca2
--- /dev/null
+++ b/indra/llwindow/llgamecontrol.cpp
@@ -0,0 +1,2122 @@
+/**
+ * @file llgamecontrol.h
+ * @brief GameController detection and management
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2023, 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 "llgamecontrol.h"
+
+#include <algorithm>
+#include <chrono>
+#include <unordered_map>
+
+#include "SDL2/SDL.h"
+#include "SDL2/SDL_gamecontroller.h"
+#include "SDL2/SDL_joystick.h"
+
+#include "indra_constants.h"
+#include "llfile.h"
+#include "llgamecontroltranslator.h"
+#include "llsd.h"
+
+namespace std
+{
+ string to_string(const SDL_JoystickGUID& guid)
+ {
+ char buffer[33] = { 0 };
+ SDL_JoystickGetGUIDString(guid, buffer, sizeof(guid));
+ return buffer;
+ }
+
+ string to_string(SDL_JoystickType type)
+ {
+ switch (type)
+ {
+ case SDL_JOYSTICK_TYPE_GAMECONTROLLER:
+ return "GAMECONTROLLER";
+ case SDL_JOYSTICK_TYPE_WHEEL:
+ return "WHEEL";
+ case SDL_JOYSTICK_TYPE_ARCADE_STICK:
+ return "ARCADE_STICK";
+ case SDL_JOYSTICK_TYPE_FLIGHT_STICK:
+ return "FLIGHT_STICK";
+ case SDL_JOYSTICK_TYPE_DANCE_PAD:
+ return "DANCE_PAD";
+ case SDL_JOYSTICK_TYPE_GUITAR:
+ return "GUITAR";
+ case SDL_JOYSTICK_TYPE_DRUM_KIT:
+ return "DRUM_KIT";
+ case SDL_JOYSTICK_TYPE_ARCADE_PAD:
+ return "ARCADE_PAD";
+ case SDL_JOYSTICK_TYPE_THROTTLE:
+ return "THROTTLE";
+ default:;
+ }
+ return "UNKNOWN";
+ }
+
+ string to_string(SDL_GameControllerType type)
+ {
+ switch (type)
+ {
+ case SDL_CONTROLLER_TYPE_XBOX360:
+ return "XBOX360";
+ case SDL_CONTROLLER_TYPE_XBOXONE:
+ return "XBOXONE";
+ case SDL_CONTROLLER_TYPE_PS3:
+ return "PS3";
+ case SDL_CONTROLLER_TYPE_PS4:
+ return "PS4";
+ case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO:
+ return "NINTENDO_SWITCH_PRO";
+ case SDL_CONTROLLER_TYPE_VIRTUAL:
+ return "VIRTUAL";
+ case SDL_CONTROLLER_TYPE_PS5:
+ return "PS5";
+ case SDL_CONTROLLER_TYPE_AMAZON_LUNA:
+ return "AMAZON_LUNA";
+ case SDL_CONTROLLER_TYPE_GOOGLE_STADIA:
+ return "GOOGLE_STADIA";
+ case SDL_CONTROLLER_TYPE_NVIDIA_SHIELD:
+ return "NVIDIA_SHIELD";
+ case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT:
+ return "NINTENDO_SWITCH_JOYCON_LEFT";
+ case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT:
+ return "NINTENDO_SWITCH_JOYCON_RIGHT";
+ case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR:
+ return "NINTENDO_SWITCH_JOYCON_PAIR";
+ default:;
+ }
+ return "UNKNOWN";
+ }
+}
+
+// Util for dumping SDL_JoystickGUID info
+std::ostream& operator<<(std::ostream& out, SDL_JoystickGUID& guid)
+{
+ return out << std::to_string(guid);
+}
+
+// Util for dumping SDL_JoystickType type name
+std::ostream& operator<<(std::ostream& out, SDL_JoystickType type)
+{
+ return out << std::to_string(type);
+}
+
+// Util for dumping SDL_GameControllerType type name
+std::ostream& operator<<(std::ostream& out, SDL_GameControllerType type)
+{
+ return out << std::to_string(type);
+}
+
+namespace std
+{
+ string to_string(SDL_Joystick* joystick)
+ {
+ if (!joystick)
+ {
+ return "nullptr";
+ }
+
+ std::stringstream ss;
+
+ ss << "{id:" << SDL_JoystickInstanceID(joystick);
+ SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
+ ss << ",guid:'" << guid << "'";
+ ss << ",type:'" << SDL_JoystickGetType(joystick) << "'";
+ ss << ",name:'" << ll_safe_string(SDL_JoystickName(joystick)) << "'";
+ ss << ",vendor:" << SDL_JoystickGetVendor(joystick);
+ ss << ",product:" << SDL_JoystickGetProduct(joystick);
+ if (U16 version = SDL_JoystickGetProductVersion(joystick))
+ {
+ ss << ",version:" << version;
+ }
+ if (const char* serial = SDL_JoystickGetSerial(joystick))
+ {
+ ss << ",serial:'" << serial << "'";
+ }
+ ss << ",num_axes:" << SDL_JoystickNumAxes(joystick);
+ ss << ",num_balls:" << SDL_JoystickNumBalls(joystick);
+ ss << ",num_hats:" << SDL_JoystickNumHats(joystick);
+ ss << ",num_buttons:" << SDL_JoystickNumHats(joystick);
+ ss << "}";
+
+ return ss.str();
+ }
+
+ string to_string(SDL_GameController* controller)
+ {
+ if (!controller)
+ {
+ return "nullptr";
+ }
+
+ stringstream ss;
+
+ ss << "{type:'" << SDL_GameControllerGetType(controller) << "'";
+ ss << ",name:'" << ll_safe_string(SDL_GameControllerName(controller)) << "'";
+ ss << ",vendor:" << SDL_GameControllerGetVendor(controller);
+ ss << ",product:" << SDL_GameControllerGetProduct(controller);
+ if (U16 version = SDL_GameControllerGetProductVersion(controller))
+ {
+ ss << ",version:" << version;
+ }
+ if (const char* serial = SDL_GameControllerGetSerial(controller))
+ {
+ ss << ",serial:'" << serial << "'";
+ }
+ ss << "}";
+
+ return ss.str();
+ }
+}
+
+// Util for dumping SDL_Joystick info
+std::ostream& operator<<(std::ostream& out, SDL_Joystick* joystick)
+{
+ return out << std::to_string(joystick);
+}
+
+// Util for dumping SDL_GameController info
+std::ostream& operator<<(std::ostream& out, SDL_GameController* controller)
+{
+ return out << std::to_string(controller);
+}
+
+std::string LLGameControl::InputChannel::getLocalName() const
+{
+ // HACK: we hard-code English channel names, but
+ // they should be loaded from localized XML config files.
+
+ if ((mType == LLGameControl::InputChannel::TYPE_AXIS) && (mIndex < NUM_AXES))
+ {
+ return "AXIS_" + std::to_string((U32)mIndex) +
+ (mSign < 0 ? "-" : mSign > 0 ? "+" : "");
+ }
+
+ if ((mType == LLGameControl::InputChannel::TYPE_BUTTON) && (mIndex < NUM_BUTTONS))
+ {
+ return "BUTTON_" + std::to_string((U32)mIndex);
+ }
+
+ return "NONE";
+}
+
+std::string LLGameControl::InputChannel::getRemoteName() const
+{
+ // HACK: we hard-code English channel names, but
+ // they should be loaded from localized XML config files.
+ std::string name = " ";
+ // GAME_CONTROL_AXIS_LEFTX, GAME_CONTROL_BUTTON_A, etc
+ if (mType == LLGameControl::InputChannel::TYPE_AXIS)
+ {
+ switch (mIndex)
+ {
+ case 0:
+ name = "GAME_CONTROL_AXIS_LEFTX";
+ break;
+ case 1:
+ name = "GAME_CONTROL_AXIS_LEFTY";
+ break;
+ case 2:
+ name = "GAME_CONTROL_AXIS_RIGHTX";
+ break;
+ case 3:
+ name = "GAME_CONTROL_AXIS_RIGHTY";
+ break;
+ case 4:
+ name = "GAME_CONTROL_AXIS_PADDLELEFT";
+ break;
+ case 5:
+ name = "GAME_CONTROL_AXIS_PADDLERIGHT";
+ break;
+ default:
+ break;
+ }
+ }
+ else if (mType == LLGameControl::InputChannel::TYPE_BUTTON)
+ {
+ switch(mIndex)
+ {
+ case 0:
+ name = "GAME_CONTROL_BUTTON_A";
+ break;
+ case 1:
+ name = "GAME_CONTROL_BUTTON_B";
+ break;
+ case 2:
+ name = "GAME_CONTROL_BUTTON_X";
+ break;
+ case 3:
+ name = "GAME_CONTROL_BUTTON_Y";
+ break;
+ case 4:
+ name = "GAME_CONTROL_BUTTON_BACK";
+ break;
+ case 5:
+ name = "GAME_CONTROL_BUTTON_GUIDE";
+ break;
+ case 6:
+ name = "GAME_CONTROL_BUTTON_START";
+ break;
+ case 7:
+ name = "GAME_CONTROL_BUTTON_LEFTSTICK";
+ break;
+ case 8:
+ name = "GAME_CONTROL_BUTTON_RIGHTSTICK";
+ break;
+ case 9:
+ name = "GAME_CONTROL_BUTTON_LEFTSHOULDER";
+ break;
+ case 10:
+ name = "GAME_CONTROL_BUTTON_RIGHTSHOULDER";
+ break;
+ case 11:
+ name = "GAME_CONTROL_BUTTON_DPAD_UP";
+ break;
+ case 12:
+ name = "GAME_CONTROL_BUTTON_DPAD_DOWN";
+ break;
+ case 13:
+ name = "GAME_CONTROL_BUTTON_DPAD_LEFT";
+ break;
+ case 14:
+ name = "GAME_CONTROL_BUTTON_DPAD_RIGHT";
+ break;
+ case 15:
+ name = "GAME_CONTROL_BUTTON_MISC1";
+ break;
+ case 16:
+ name = "GAME_CONTROL_BUTTON_PADDLE1";
+ break;
+ case 17:
+ name = "GAME_CONTROL_BUTTON_PADDLE2";
+ break;
+ case 18:
+ name = "GAME_CONTROL_BUTTON_PADDLE3";
+ break;
+ case 19:
+ name = "GAME_CONTROL_BUTTON_PADDLE4";
+ break;
+ case 20:
+ name = "GAME_CONTROL_BUTTON_TOUCHPAD";
+ break;
+ default:
+ break;
+ }
+ }
+ return name;
+}
+
+
+// internal class for managing list of controllers and per-controller state
+class LLGameControllerManager
+{
+public:
+ using ActionToChannelMap = std::map< std::string, LLGameControl::InputChannel >;
+ LLGameControllerManager();
+
+ static void getDefaultMappings(std::vector<std::pair<std::string, LLGameControl::InputChannel>>& agent_channels,
+ std::vector<LLGameControl::InputChannel>& flycam_channels);
+ void getDefaultMappings(std::vector<std::pair<std::string, LLGameControl::InputChannel>>& mappings);
+ void initializeMappingsByDefault();
+ void resetDeviceOptionsToDefaults();
+ void loadDeviceOptionsFromSettings();
+ void saveDeviceOptionsToSettings() const;
+ void setDeviceOptions(const std::string& guid, const LLGameControl::Options& options);
+
+ void addController(SDL_JoystickID id, const std::string& guid, const std::string& name);
+ void removeController(SDL_JoystickID id);
+
+ void onAxis(SDL_JoystickID id, U8 axis, S16 value);
+ void onButton(SDL_JoystickID id, U8 button, bool pressed);
+
+ void clearAllStates();
+
+ void accumulateInternalState();
+ void computeFinalState();
+
+ LLGameControl::ActionNameType getActionNameType(const std::string& action) const;
+ LLGameControl::InputChannel getChannelByAction(const std::string& action) const;
+ LLGameControl::InputChannel getFlycamChannelByAction(const std::string& action) const;
+
+ bool updateActionMap(const std::string& name, LLGameControl::InputChannel channel);
+ U32 computeInternalActionFlags();
+ void getFlycamInputs(std::vector<F32>& inputs_out);
+ void setExternalInput(U32 action_flags, U32 buttons);
+
+ U32 getMappedFlags() const { return mActionTranslator.getMappedFlags(); }
+
+ void clear();
+
+ std::string getAnalogMappings() const;
+ std::string getBinaryMappings() const;
+ std::string getFlycamMappings() const;
+
+ void setAnalogMappings(const std::string& mappings);
+ void setBinaryMappings(const std::string& mappings);
+ void setFlycamMappings(const std::string& mappings);
+
+private:
+ void updateFlycamMap(const std::string& action, LLGameControl::InputChannel channel);
+
+ std::list<LLGameControl::Device> mDevices; // all connected devices
+ using device_it = std::list<LLGameControl::Device>::iterator;
+ device_it findDevice(SDL_JoystickID id)
+ {
+ return std::find_if(mDevices.begin(), mDevices.end(),
+ [id](LLGameControl::Device& device)
+ {
+ return device.getJoystickID() == id;
+ });
+ }
+
+ LLGameControl::State mExternalState;
+ LLGameControlTranslator mActionTranslator;
+ std::map<std::string, LLGameControl::ActionNameType> mActions;
+ std::vector <std::string> mAnalogActions;
+ std::vector <std::string> mBinaryActions;
+ std::vector <std::string> mFlycamActions;
+ std::vector<LLGameControl::InputChannel> mFlycamChannels;
+ std::vector<S32> mAxesAccumulator;
+ U32 mButtonAccumulator { 0 };
+ U32 mLastActiveFlags { 0 };
+ U32 mLastFlycamActionFlags { 0 };
+
+ friend class LLGameControl;
+};
+
+// local globals
+namespace
+{
+ LLGameControl* g_gameControl = nullptr;
+ LLGameControllerManager g_manager;
+
+ // The GameControlInput message is sent via UDP which is lossy.
+ // Since we send the only the list of pressed buttons the receiving
+ // side can compute the difference between subsequent states to
+ // find button-down/button-up events.
+ //
+ // To reduce the likelihood of buttons being stuck "pressed" forever
+ // on the receiving side (for lost final packet) we resend the last
+ // data state. However, to keep the ambient resend bandwidth low we
+ // expand the resend period at a geometric rate.
+ //
+ constexpr U64 MSEC_PER_NSEC = 1000000;
+ constexpr U64 FIRST_RESEND_PERIOD = 100 * MSEC_PER_NSEC;
+ constexpr U64 RESEND_EXPANSION_RATE = 10;
+ LLGameControl::State g_outerState; // from controller devices
+ LLGameControl::State g_innerState; // state from gAgent
+ LLGameControl::State g_finalState; // sum of inner and outer
+ U64 g_lastSend = 0;
+ U64 g_nextResendPeriod = FIRST_RESEND_PERIOD;
+
+ bool g_enabled = false;
+ bool g_sendToServer = false;
+ bool g_controlAgent = false;
+ bool g_translateAgentActions = false;
+ LLGameControl::AgentControlMode g_agentControlMode = LLGameControl::CONTROL_MODE_AVATAR;
+
+ std::map<std::string, std::string> g_deviceOptions;
+
+ std::function<bool(const std::string&)> s_loadBoolean;
+ std::function<void(const std::string&, bool)> s_saveBoolean;
+ std::function<std::string(const std::string&)> s_loadString;
+ std::function<void(const std::string&, const std::string&)> s_saveString;
+ std::function<LLSD(const std::string&)> s_loadObject;
+ std::function<void(const std::string&, LLSD&)> s_saveObject;
+ std::function<void()> s_updateUI;
+
+ std::string SETTING_ENABLE("EnableGameControl");
+ std::string SETTING_SENDTOSERVER("GameControlToServer");
+ std::string SETTING_CONTROLAGENT("GameControlToAgent");
+ std::string SETTING_TRANSLATEACTIONS("AgentToGameControl");
+ std::string SETTING_AGENTCONTROLMODE("AgentControlMode");
+ std::string SETTING_ANALOGMAPPINGS("AnalogChannelMappings");
+ std::string SETTING_BINARYMAPPINGS("BinaryChannelMappings");
+ std::string SETTING_FLYCAMMAPPINGS("FlycamChannelMappings");
+ std::string SETTING_KNOWNCONTROLLERS("KnownGameControllers");
+
+ std::string ENUM_AGENTCONTROLMODE_FLYCAM("flycam");
+ std::string ENUM_AGENTCONTROLMODE_NONE("none");
+
+ LLGameControl::AgentControlMode convertStringToAgentControlMode(const std::string& mode)
+ {
+ if (mode == ENUM_AGENTCONTROLMODE_NONE)
+ return LLGameControl::CONTROL_MODE_NONE;
+ if (mode == ENUM_AGENTCONTROLMODE_FLYCAM)
+ return LLGameControl::CONTROL_MODE_FLYCAM;
+ // All values except NONE and FLYCAM are treated as default (AVATAR)
+ return LLGameControl::CONTROL_MODE_AVATAR;
+ }
+
+ const std::string& convertAgentControlModeToString(LLGameControl::AgentControlMode mode)
+ {
+ if (mode == LLGameControl::CONTROL_MODE_NONE)
+ return ENUM_AGENTCONTROLMODE_NONE;
+ if (mode == LLGameControl::CONTROL_MODE_FLYCAM)
+ return ENUM_AGENTCONTROLMODE_FLYCAM;
+ // All values except NONE and FLYCAM are treated as default (AVATAR)
+ return LLStringUtil::null;
+ }
+
+ const std::string& getDeviceOptionsString(const std::string& guid)
+ {
+ const auto& it = g_deviceOptions.find(guid);
+ return it == g_deviceOptions.end() ? LLStringUtil::null : it->second;
+ }
+}
+
+LLGameControl::~LLGameControl()
+{
+ terminate();
+}
+
+LLGameControl::State::State()
+: mButtons(0)
+{
+ mAxes.resize(NUM_AXES, 0);
+ mPrevAxes.resize(NUM_AXES, 0);
+}
+
+void LLGameControl::State::clear()
+{
+ std::fill(mAxes.begin(), mAxes.end(), 0);
+
+ // DO NOT clear mPrevAxes because those are managed by external logic.
+ //std::fill(mPrevAxes.begin(), mPrevAxes.end(), 0);
+
+ mButtons = 0;
+}
+
+bool LLGameControl::State::onButton(U8 button, bool pressed)
+{
+ U32 old_buttons = mButtons;
+ if (button < NUM_BUTTONS)
+ {
+ if (pressed)
+ {
+ mButtons |= (0x01 << button);
+ }
+ else
+ {
+ mButtons &= ~(0x01 << button);
+ }
+ }
+ return mButtons != old_buttons;
+}
+
+LLGameControl::Device::Device(int joystickID, const std::string& guid, const std::string& name)
+: mJoystickID(joystickID)
+, mGUID(guid)
+, mName(name)
+{
+}
+
+LLGameControl::Options::Options()
+{
+ mAxisOptions.resize(NUM_AXES);
+ mAxisMap.resize(NUM_AXES);
+ mButtonMap.resize(NUM_BUTTONS);
+ resetToDefaults();
+}
+
+void LLGameControl::Options::resetToDefaults()
+{
+ for (size_t i = 0; i < NUM_AXES; ++i)
+ {
+ mAxisOptions[i].resetToDefaults();
+ mAxisMap[i] = (U8)i;
+ }
+ for (size_t i = 0; i < NUM_BUTTONS; ++i)
+ {
+ mButtonMap[i] = (U8)i;
+ }
+}
+
+U8 LLGameControl::Options::mapAxis(U8 axis) const
+{
+ if (axis >= NUM_AXES)
+ {
+ LL_WARNS("SDL2") << "Invalid input axis: " << axis << LL_ENDL;
+ return axis;
+ }
+ return mAxisMap[axis];
+}
+
+U8 LLGameControl::Options::mapButton(U8 button) const
+{
+ if (button >= NUM_BUTTONS)
+ {
+ LL_WARNS("SDL2") << "Invalid input button: " << button << LL_ENDL;
+ return button;
+ }
+ return mButtonMap[button];
+}
+
+S16 LLGameControl::Options::fixAxisValue(U8 axis, S16 value) const
+{
+ if (axis >= NUM_AXES)
+ {
+ LL_WARNS("SDL2") << "Invalid input axis: " << axis << LL_ENDL;
+ }
+ else
+ {
+ value = mAxisOptions[axis].computeModifiedValue(value);
+ }
+ return value;
+}
+
+std::string LLGameControl::Options::AxisOptions::saveToString() const
+{
+ std::list<std::string> options;
+
+ if (mMultiplier == -1)
+ {
+ options.push_back("invert:1");
+ }
+ if (mDeadZone)
+ {
+ options.push_back(llformat("dead_zone:%u", mDeadZone));
+ }
+ if (mOffset)
+ {
+ options.push_back(llformat("offset:%d", mOffset));
+ }
+
+ std::string result = LLStringUtil::join(options);
+
+ return result.empty() ? result : "{" + result + "}";
+}
+
+// Parse string "{key:value,key:{key:value,key:value}}" and fill the map
+static bool parse(std::map<std::string, std::string>& result, std::string source)
+{
+ result.clear();
+
+ LLStringUtil::trim(source);
+ if (source.empty())
+ return true;
+
+ if (source.front() != '{' || source.back() != '}')
+ return false;
+
+ source = source.substr(1, source.size() - 2);
+
+ LLStringUtil::trim(source);
+ if (source.empty())
+ return true;
+
+ // Split the string "key:value" and add the pair to the map
+ auto split = [&](const std::string& pair) -> bool
+ {
+ size_t pos = pair.find(':');
+ if (!pos || pos == std::string::npos)
+ return false;
+ std::string key = pair.substr(0, pos);
+ std::string value = pair.substr(pos + 1);
+ LLStringUtil::trim(key);
+ LLStringUtil::trim(value);
+ if (key.empty() || value.empty())
+ return false;
+ result[key] = value;
+ return true;
+ };
+
+ U32 depth = 0;
+ size_t offset = 0;
+ while (true)
+ {
+ size_t pos = source.find_first_of(depth ? "{}" : ",{}", offset);
+ if (pos == std::string::npos)
+ {
+ return !depth && split(source);
+ }
+ if (source[pos] == ',')
+ {
+ if (!split(source.substr(0, pos)))
+ return false;
+ source = source.substr(pos + 1);
+ offset = 0;
+ }
+ else if (source[pos] == '{')
+ {
+ depth++;
+ offset = pos + 1;
+ }
+ else if (depth) // Assume '}' here
+ {
+ depth--;
+ offset = pos + 1;
+ }
+ else
+ {
+ return false; // Extra '}' found
+ }
+ }
+
+ return true;
+}
+
+void LLGameControl::Options::AxisOptions::loadFromString(std::string options)
+{
+ resetToDefaults();
+
+ if (options.empty())
+ return;
+
+ std::map<std::string, std::string> pairs;
+ if (!parse(pairs, options))
+ {
+ LL_WARNS("SDL2") << "Invalid axis options: '" << options << "'" << LL_ENDL;
+ }
+
+ mMultiplier = 1;
+ std::string invert = pairs["invert"];
+ if (!invert.empty())
+ {
+ if (invert == "1")
+ {
+ mMultiplier = -1;
+ }
+ else
+ {
+ LL_WARNS("SDL2") << "Invalid invert value: '" << invert << "'" << LL_ENDL;
+ }
+ }
+
+ std::string dead_zone = pairs["dead_zone"];
+ if (!dead_zone.empty())
+ {
+ size_t number = std::stoull(dead_zone);
+ if (number <= MAX_AXIS_DEAD_ZONE && std::to_string(number) == dead_zone)
+ {
+ mDeadZone = (U16)number;
+ }
+ else
+ {
+ LL_WARNS("SDL2") << "Invalid dead_zone value: '" << dead_zone << "'" << LL_ENDL;
+ }
+ }
+
+ std::string offset = pairs["offset"];
+ if (!offset.empty())
+ {
+ S32 number = std::stoi(offset);
+ if (abs(number) > MAX_AXIS_OFFSET || std::to_string(number) != offset)
+ {
+ LL_WARNS("SDL2") << "Invalid offset value: '" << offset << "'" << LL_ENDL;
+ }
+ else
+ {
+ mOffset = (S16)number;
+ }
+ }
+}
+
+std::string LLGameControl::Options::saveToString(const std::string& name, bool force_empty) const
+{
+ return stringifyDeviceOptions(name, mAxisOptions, mAxisMap, mButtonMap, force_empty);
+}
+
+bool LLGameControl::Options::loadFromString(std::string& name, std::string options)
+{
+ resetToDefaults();
+ return LLGameControl::parseDeviceOptions(options, name, mAxisOptions, mAxisMap, mButtonMap);
+}
+
+bool LLGameControl::Options::loadFromString(std::string options)
+{
+ resetToDefaults();
+ std::string dummy_name;
+ return LLGameControl::parseDeviceOptions(options, dummy_name, mAxisOptions, mAxisMap, mButtonMap);
+}
+
+LLGameControllerManager::LLGameControllerManager()
+{
+ mAxesAccumulator.resize(LLGameControl::NUM_AXES, 0);
+
+ mAnalogActions = { "push", "slide", "jump", "turn", "look" };
+ mBinaryActions = { "toggle_run", "toggle_fly", "toggle_flycam", "stop" };
+ mFlycamActions = { "advance", "pan", "rise", "pitch", "yaw", "zoom" };
+
+ // Collect all known action names with their types in one container
+ for (const std::string& name : mAnalogActions)
+ {
+ mActions[name] = LLGameControl::ACTION_NAME_ANALOG;
+ mActions[name + "+"] = LLGameControl::ACTION_NAME_ANALOG_POS;
+ mActions[name + "-"] = LLGameControl::ACTION_NAME_ANALOG_NEG;
+ }
+ for (const std::string& name : mBinaryActions)
+ {
+ mActions[name] = LLGameControl::ACTION_NAME_BINARY;
+ }
+ for (const std::string& name : mFlycamActions)
+ {
+ mActions[name] = LLGameControl::ACTION_NAME_FLYCAM;
+ }
+
+ // Here we build an invariant map between the named agent actions
+ // and control bit sent to the server. This map will be used,
+ // in combination with the action->InputChannel map below,
+ // to maintain an inverse map from control bit masks to GameControl data.
+ LLGameControlTranslator::ActionToMaskMap actionMasks =
+ {
+ // Analog actions (pairs)
+ { "push+", AGENT_CONTROL_AT_POS | AGENT_CONTROL_FAST_AT },
+ { "push-", AGENT_CONTROL_AT_NEG | AGENT_CONTROL_FAST_AT },
+ { "slide+", AGENT_CONTROL_LEFT_POS | AGENT_CONTROL_FAST_LEFT },
+ { "slide-", AGENT_CONTROL_LEFT_NEG | AGENT_CONTROL_FAST_LEFT },
+ { "jump+", AGENT_CONTROL_UP_POS | AGENT_CONTROL_FAST_UP },
+ { "jump-", AGENT_CONTROL_UP_NEG | AGENT_CONTROL_FAST_UP },
+ { "turn+", AGENT_CONTROL_YAW_POS },
+ { "turn-", AGENT_CONTROL_YAW_NEG },
+ { "look+", AGENT_CONTROL_PITCH_POS },
+ { "look-", AGENT_CONTROL_PITCH_NEG },
+ // Button actions
+ { "stop", AGENT_CONTROL_STOP },
+ // These are HACKs. We borrow some AGENT_CONTROL bits for "unrelated" features.
+ // Not a problem because these bits are only used internally.
+ { "toggle_run", AGENT_CONTROL_NUDGE_AT_POS }, // HACK
+ { "toggle_fly", AGENT_CONTROL_FLY }, // HACK
+ { "toggle_flycam", AGENT_CONTROL_NUDGE_AT_NEG }, // HACK
+ };
+ mActionTranslator.setAvailableActionMasks(actionMasks);
+
+ initializeMappingsByDefault();
+}
+
+// static
+void LLGameControllerManager::getDefaultMappings(
+ std::vector<std::pair<std::string, LLGameControl::InputChannel>>& agent_channels,
+ std::vector<LLGameControl::InputChannel>& flycam_channels)
+{
+ // Here we build a list of pairs between named agent actions and
+ // GameControl channels. Note: we only supply the non-signed names
+ // (e.g. "push" instead of "push+" and "push-") because mActionTranslator
+ // automatially expands action names as necessary.
+ using type = LLGameControl::InputChannel::Type;
+ agent_channels =
+ {
+ // Analog actions (associated by common name - without '+' or '-')
+ { "push", { type::TYPE_AXIS, LLGameControl::AXIS_LEFTY, 1 } },
+ { "slide", { type::TYPE_AXIS, LLGameControl::AXIS_LEFTX, 1 } },
+ { "jump", { type::TYPE_AXIS, LLGameControl::AXIS_TRIGGERLEFT, 1 } },
+ { "turn", { type::TYPE_AXIS, LLGameControl::AXIS_RIGHTX, 1 } },
+ { "look", { type::TYPE_AXIS, LLGameControl::AXIS_RIGHTY, 1 } },
+ // Button actions (associated by name)
+ { "toggle_run", { type::TYPE_BUTTON, LLGameControl::BUTTON_LEFTSHOULDER } },
+ { "toggle_fly", { type::TYPE_BUTTON, LLGameControl::BUTTON_DPAD_UP } },
+ { "toggle_flycam", { type::TYPE_BUTTON, LLGameControl::BUTTON_RIGHTSHOULDER } },
+ { "stop", { type::TYPE_BUTTON, LLGameControl::BUTTON_LEFTSTICK } }
+ };
+
+ // Flycam actions don't need bitwise translation, so we maintain the map
+ // of channels here directly rather than using an LLGameControlTranslator.
+ flycam_channels =
+ {
+ // Flycam actions (associated just by an order index)
+ { type::TYPE_AXIS, LLGameControl::AXIS_LEFTY, 1 }, // advance
+ { type::TYPE_AXIS, LLGameControl::AXIS_LEFTX, 1 }, // pan
+ { type::TYPE_AXIS, LLGameControl::AXIS_TRIGGERRIGHT, 1 }, // rise
+ { type::TYPE_AXIS, LLGameControl::AXIS_RIGHTY, -1 }, // pitch
+ { type::TYPE_AXIS, LLGameControl::AXIS_RIGHTX, 1 }, // yaw
+ { type::TYPE_NONE, 0 } // zoom
+ };
+}
+
+void LLGameControllerManager::getDefaultMappings(std::vector<std::pair<std::string, LLGameControl::InputChannel>>& mappings)
+{
+ // Join two different data structures into the one
+ std::vector<LLGameControl::InputChannel> flycam_channels;
+ getDefaultMappings(mappings, flycam_channels);
+ for (size_t i = 0; i < flycam_channels.size(); ++i)
+ {
+ mappings.emplace_back(mFlycamActions[i], flycam_channels[i]);
+ }
+}
+
+void LLGameControllerManager::initializeMappingsByDefault()
+{
+ std::vector<std::pair<std::string, LLGameControl::InputChannel>> agent_channels;
+ getDefaultMappings(agent_channels, mFlycamChannels);
+ mActionTranslator.setMappings(agent_channels);
+}
+
+void LLGameControllerManager::resetDeviceOptionsToDefaults()
+{
+ for (LLGameControl::Device& device : mDevices)
+ {
+ device.resetOptionsToDefaults();
+ }
+}
+
+void LLGameControllerManager::loadDeviceOptionsFromSettings()
+{
+ for (LLGameControl::Device& device : mDevices)
+ {
+ device.loadOptionsFromString(getDeviceOptionsString(device.getGUID()));
+ }
+}
+
+void LLGameControllerManager::saveDeviceOptionsToSettings() const
+{
+ for (const LLGameControl::Device& device : mDevices)
+ {
+ std::string options = device.saveOptionsToString();
+ if (options.empty())
+ {
+ g_deviceOptions.erase(device.getGUID());
+ }
+ else
+ {
+ g_deviceOptions[device.getGUID()] = options;
+ }
+ }
+}
+
+void LLGameControllerManager::setDeviceOptions(const std::string& guid, const LLGameControl::Options& options)
+{
+ // find Device by name
+ for (LLGameControl::Device& device : mDevices)
+ {
+ if (device.getGUID() == guid)
+ {
+ device.mOptions = options;
+ return;
+ }
+ }
+}
+
+void LLGameControllerManager::addController(SDL_JoystickID id, const std::string& guid, const std::string& name)
+{
+ llassert(id >= 0);
+
+ for (const LLGameControl::Device& device : mDevices)
+ {
+ if (device.getJoystickID() == id)
+ {
+ LL_WARNS("SDL2") << "device with id=" << id << " was already added"
+ << ", guid: '" << device.getGUID() << "'"
+ << ", name: '" << device.getName() << "'"
+ << LL_ENDL;
+ return;
+ }
+ }
+
+ mDevices.emplace_back(id, guid, name).loadOptionsFromString(getDeviceOptionsString(guid));
+}
+
+void LLGameControllerManager::removeController(SDL_JoystickID id)
+{
+ LL_INFOS("SDL2") << "joystick id: " << id << LL_ENDL;
+
+ mDevices.remove_if([id](LLGameControl::Device& device)
+ {
+ return device.getJoystickID() == id;
+ });
+}
+
+void LLGameControllerManager::onAxis(SDL_JoystickID id, U8 axis, S16 value)
+{
+ device_it it = findDevice(id);
+ if (it == mDevices.end())
+ {
+ LL_WARNS("SDL2") << "Unknown device: joystick=0x" << std::hex << id << std::dec
+ << " axis=" << (S32)axis
+ << " value=" << (S32)value << LL_ENDL;
+ return;
+ }
+
+ // Map axis using device-specific settings
+ // or leave the value unchanged
+ U8 mapped_axis = it->mOptions.mapAxis(axis);
+ if (mapped_axis != axis)
+ {
+ LL_DEBUGS("SDL2") << "Axis mapped: joystick=0x" << std::hex << id << std::dec
+ << " input axis i=" << (S32)axis
+ << " mapped axis i=" << (S32)mapped_axis << LL_ENDL;
+ axis = mapped_axis;
+ }
+
+ if (axis >= LLGameControl::NUM_AXES)
+ {
+ LL_WARNS("SDL2") << "Unknown axis: joystick=0x" << std::hex << id << std::dec
+ << " axis=" << (S32)(axis)
+ << " value=" << (S32)(value) << LL_ENDL;
+ return;
+ }
+
+ // Fix value using device-specific settings
+ // or leave the value unchanged
+ S16 fixed_value = it->mOptions.fixAxisValue(axis, value);
+ if (fixed_value != value)
+ {
+ LL_DEBUGS("SDL2") << "Value fixed: joystick=0x" << std::hex << id << std::dec
+ << " axis i=" << (S32)axis
+ << " input value=" << (S32)value
+ << " fixed value=" << (S32)fixed_value << LL_ENDL;
+ value = fixed_value;
+ }
+
+ // Note: the RAW analog joysticks provide NEGATIVE X,Y values for LEFT,FORWARD
+ // whereas those directions are actually POSITIVE in SL's local right-handed
+ // reference frame. Therefore we implicitly negate those axes here where
+ // they are extracted from SDL, before being used anywhere.
+ if (axis < SDL_CONTROLLER_AXIS_TRIGGERLEFT)
+ {
+ // Note: S16 value is in range [-32768, 32767] which means
+ // the negative range has an extra possible value. We need
+ // to add (or subtract) one during negation.
+ if (value < 0)
+ {
+ value = - (value + 1);
+ }
+ else if (value > 0)
+ {
+ value = (-value) - 1;
+ }
+ }
+
+ LL_DEBUGS("SDL2") << "joystick=0x" << std::hex << id << std::dec
+ << " axis=" << (S32)(axis)
+ << " value=" << (S32)(value) << LL_ENDL;
+ it->mState.mAxes[axis] = value;
+}
+
+void LLGameControllerManager::onButton(SDL_JoystickID id, U8 button, bool pressed)
+{
+ device_it it = findDevice(id);
+ if (it == mDevices.end())
+ {
+ LL_WARNS("SDL2") << "Unknown device: joystick=0x" << std::hex << id << std::dec
+ << " button i=" << (S32)button << LL_ENDL;
+ return;
+ }
+
+ // Map button using device-specific settings
+ // or leave the value unchanged
+ U8 mapped_button = it->mOptions.mapButton(button);
+ if (mapped_button != button)
+ {
+ LL_DEBUGS("SDL2") << "Button mapped: joystick=0x" << std::hex << id << std::dec
+ << " input button i=" << (S32)button
+ << " mapped button i=" << (S32)mapped_button << LL_ENDL;
+ button = mapped_button;
+ }
+
+ if (button >= LLGameControl::NUM_BUTTONS)
+ {
+ LL_WARNS("SDL2") << "Unknown button: joystick=0x" << std::hex << id << std::dec
+ << " button i=" << (S32)button << LL_ENDL;
+ return;
+ }
+
+ if (it->mState.onButton(button, pressed))
+ {
+ LL_DEBUGS("SDL2") << "joystick=0x" << std::hex << id << std::dec
+ << " button i=" << (S32)button
+ << " pressed=" << pressed << LL_ENDL;
+ }
+}
+
+void LLGameControllerManager::clearAllStates()
+{
+ for (auto& device : mDevices)
+ {
+ device.mState.clear();
+ }
+ mExternalState.clear();
+ mLastActiveFlags = 0;
+ mLastFlycamActionFlags = 0;
+}
+
+void LLGameControllerManager::accumulateInternalState()
+{
+ // clear the old state
+ std::fill(mAxesAccumulator.begin(), mAxesAccumulator.end(), 0);
+ mButtonAccumulator = 0;
+
+ // accumulate the controllers
+ for (const auto& device : mDevices)
+ {
+ mButtonAccumulator |= device.mState.mButtons;
+ for (size_t i = 0; i < LLGameControl::NUM_AXES; ++i)
+ {
+ // Note: we don't bother to clamp the axes yet
+ // because at this stage we haven't yet accumulated the "inner" state.
+ mAxesAccumulator[i] += (S32)device.mState.mAxes[i];
+ }
+ }
+}
+
+void LLGameControllerManager::computeFinalState()
+{
+ // We assume accumulateInternalState() has already been called and we will
+ // finish by accumulating "external" state (if enabled)
+ U32 old_buttons = g_finalState.mButtons;
+ g_finalState.mButtons = mButtonAccumulator;
+ if (g_translateAgentActions)
+ {
+ // accumulate from mExternalState
+ g_finalState.mButtons |= mExternalState.mButtons;
+ }
+ if (old_buttons != g_finalState.mButtons)
+ {
+ g_nextResendPeriod = 0; // packet needs to go out ASAP
+ }
+
+ // clamp the accumulated axes
+ for (size_t i = 0; i < LLGameControl::NUM_AXES; ++i)
+ {
+ S32 axis = mAxesAccumulator[i];
+ if (g_translateAgentActions)
+ {
+ // Note: we accumulate mExternalState onto local 'axis' variable
+ // rather than onto mAxisAccumulator[i] because the internal
+ // accumulated value is also used to drive the Flycam, and
+ // we don't want any external state leaking into that value.
+ axis += (S32)mExternalState.mAxes[i];
+ }
+ axis = (S16)std::min(std::max(axis, -32768), 32767);
+ // check for change
+ if (g_finalState.mAxes[i] != axis)
+ {
+ // When axis changes we explicitly update the corresponding prevAxis
+ // prior to storing axis. The only other place where prevAxis
+ // is updated in updateResendPeriod() which is explicitly called after
+ // a packet is sent. The result is: unchanged axes are included in
+ // first resend but not later ones.
+ g_finalState.mPrevAxes[i] = g_finalState.mAxes[i];
+ g_finalState.mAxes[i] = axis;
+ g_nextResendPeriod = 0; // packet needs to go out ASAP
+ }
+ }
+}
+
+LLGameControl::ActionNameType LLGameControllerManager::getActionNameType(const std::string& action) const
+{
+ auto it = mActions.find(action);
+ return it == mActions.end() ? LLGameControl::ACTION_NAME_UNKNOWN : it->second;
+}
+
+LLGameControl::InputChannel LLGameControllerManager::getChannelByAction(const std::string& action) const
+{
+ LLGameControl::InputChannel channel;
+ auto action_it = mActions.find(action);
+ if (action_it != mActions.end())
+ {
+ if (action_it->second == LLGameControl::ACTION_NAME_FLYCAM)
+ {
+ channel = getFlycamChannelByAction(action);
+ }
+ else
+ {
+ channel = mActionTranslator.getChannelByAction(action);
+ }
+ }
+ return channel;
+}
+
+LLGameControl::InputChannel LLGameControllerManager::getFlycamChannelByAction(const std::string& action) const
+{
+ auto flycam_it = std::find(mFlycamActions.begin(), mFlycamActions.end(), action);
+ llassert(flycam_it != mFlycamActions.end());
+ std::ptrdiff_t index = std::distance(mFlycamActions.begin(), flycam_it);
+ return mFlycamChannels[(std::size_t)index];
+}
+
+// Common implementation of getAnalogMappings(), getBinaryMappings() and getFlycamMappings()
+static std::string getMappings(const std::vector<std::string>& actions, LLGameControl::InputChannel::Type type,
+ std::function<LLGameControl::InputChannel(const std::string& action)> getChannel)
+{
+ std::list<std::string> mappings;
+
+ std::vector<std::pair<std::string, LLGameControl::InputChannel>> default_mappings;
+ LLGameControl::getDefaultMappings(default_mappings);
+
+ // Walk through the all known actions of the chosen type
+ for (const std::string& action : actions)
+ {
+ LLGameControl::InputChannel channel = getChannel(action);
+ // Only channels of the expected type should be stored
+ if (channel.mType == type)
+ {
+ bool mapping_differs = false;
+ for (const auto& pair : default_mappings)
+ {
+ if (pair.first == action)
+ {
+ mapping_differs = !channel.isEqual(pair.second);
+ break;
+ }
+ }
+ // Only mappings different from the default should be stored
+ if (mapping_differs)
+ {
+ mappings.push_back(action + ":" + channel.getLocalName());
+ }
+ }
+ }
+
+ std::string result = LLStringUtil::join(mappings);
+
+ return result;
+}
+
+std::string LLGameControllerManager::getAnalogMappings() const
+{
+ return getMappings(mAnalogActions, LLGameControl::InputChannel::TYPE_AXIS,
+ [&](const std::string& action) -> LLGameControl::InputChannel
+ {
+ return mActionTranslator.getChannelByAction(action + "+");
+ });
+}
+
+std::string LLGameControllerManager::getBinaryMappings() const
+{
+ return getMappings(mBinaryActions, LLGameControl::InputChannel::TYPE_BUTTON,
+ [&](const std::string& action) -> LLGameControl::InputChannel
+ {
+ return mActionTranslator.getChannelByAction(action);
+ });
+}
+
+std::string LLGameControllerManager::getFlycamMappings() const
+{
+ return getMappings(mFlycamActions, LLGameControl::InputChannel::TYPE_AXIS,
+ [&](const std::string& action) -> LLGameControl::InputChannel
+ {
+ return getFlycamChannelByAction(action);
+ });
+}
+
+// Common implementation of setAnalogMappings(), setBinaryMappings() and setFlycamMappings()
+static void setMappings(const std::string& mappings,
+ const std::vector<std::string>& actions, LLGameControl::InputChannel::Type type,
+ std::function<void(const std::string& action, LLGameControl::InputChannel channel)> updateMap)
+{
+ if (mappings.empty())
+ return;
+
+ std::map<std::string, std::string> pairs;
+ LLStringOps::splitString(mappings, ',', [&](const std::string& mapping)
+ {
+ std::size_t pos = mapping.find(':');
+ if (pos > 0 && pos != std::string::npos)
+ {
+ pairs[mapping.substr(0, pos)] = mapping.substr(pos + 1);
+ }
+ });
+
+ static const LLGameControl::InputChannel channelNone;
+
+ for (const std::string& action : actions)
+ {
+ auto it = pairs.find(action);
+ if (it != pairs.end())
+ {
+ LLGameControl::InputChannel channel = LLGameControl::getChannelByName(it->second);
+ if (channel.isNone() || channel.mType == type)
+ {
+ updateMap(action, channel);
+ continue;
+ }
+ }
+ updateMap(action, channelNone);
+ }
+}
+
+void LLGameControllerManager::setAnalogMappings(const std::string& mappings)
+{
+ setMappings(mappings, mAnalogActions, LLGameControl::InputChannel::TYPE_AXIS,
+ [&](const std::string& action, LLGameControl::InputChannel channel)
+ {
+ mActionTranslator.updateMap(action, channel);
+ });
+}
+
+void LLGameControllerManager::setBinaryMappings(const std::string& mappings)
+{
+ setMappings(mappings, mBinaryActions, LLGameControl::InputChannel::TYPE_BUTTON,
+ [&](const std::string& action, LLGameControl::InputChannel channel)
+ {
+ mActionTranslator.updateMap(action, channel);
+ });
+}
+
+void LLGameControllerManager::setFlycamMappings(const std::string& mappings)
+{
+ setMappings(mappings, mFlycamActions, LLGameControl::InputChannel::TYPE_AXIS,
+ [&](const std::string& action, LLGameControl::InputChannel channel)
+ {
+ updateFlycamMap(action, channel);
+ });
+}
+
+bool LLGameControllerManager::updateActionMap(const std::string& action, LLGameControl::InputChannel channel)
+{
+ auto action_it = mActions.find(action);
+ if (action_it == mActions.end())
+ {
+ LL_WARNS("SDL2") << "unmappable action='" << action << "'" << LL_ENDL;
+ return false;
+ }
+
+ if (action_it->second == LLGameControl::ACTION_NAME_FLYCAM)
+ {
+ updateFlycamMap(action, channel);
+ }
+ else
+ {
+ mActionTranslator.updateMap(action, channel);
+ }
+ return true;
+}
+
+void LLGameControllerManager::updateFlycamMap(const std::string& action, LLGameControl::InputChannel channel)
+{
+ auto flycam_it = std::find(mFlycamActions.begin(), mFlycamActions.end(), action);
+ llassert(flycam_it != mFlycamActions.end());
+ std::ptrdiff_t index = std::distance(mFlycamActions.begin(), flycam_it);
+ llassert(index >= 0 && (std::size_t)index < mFlycamChannels.size());
+ mFlycamChannels[(std::size_t)index] = channel;
+}
+
+U32 LLGameControllerManager::computeInternalActionFlags()
+{
+ // add up device inputs
+ accumulateInternalState();
+ if (g_controlAgent)
+ {
+ return mActionTranslator.computeFlagsFromState(mAxesAccumulator, mButtonAccumulator);
+ }
+ return 0;
+}
+
+void LLGameControllerManager::getFlycamInputs(std::vector<F32>& inputs)
+{
+ // The inputs are packed in the same order as they exist in mFlycamChannels:
+ //
+ // advance
+ // pan
+ // rise
+ // pitch
+ // yaw
+ // zoom
+ //
+ for (const auto& channel: mFlycamChannels)
+ {
+ S16 axis;
+ if (channel.mIndex == LLGameControl::AXIS_TRIGGERLEFT ||
+ channel.mIndex == LLGameControl::AXIS_TRIGGERRIGHT)
+ {
+ // TIED TRIGGER HACK: we assume the two triggers are paired together
+ S32 total_axis = mAxesAccumulator[LLGameControl::AXIS_TRIGGERLEFT]
+ - mAxesAccumulator[LLGameControl::AXIS_TRIGGERRIGHT];
+ if (channel.mIndex == LLGameControl::AXIS_TRIGGERRIGHT)
+ {
+ // negate previous math when TRIGGERRIGHT is positive channel
+ total_axis *= -1;
+ }
+ axis = S16(std::min(std::max(total_axis, -32768), 32767));
+ }
+ else
+ {
+ axis = S16(std::min(std::max(mAxesAccumulator[channel.mIndex], -32768), 32767));
+ }
+ // value arrives as S16 in range [-32768, 32767]
+ // so we scale positive and negative values by slightly different factors
+ // to try to map it to [-1, 1]
+ F32 input = F32(axis) / ((axis > 0.0f) ? 32767 : 32768) * channel.mSign;
+ inputs.push_back(input);
+ }
+}
+
+void LLGameControllerManager::setExternalInput(U32 action_flags, U32 buttons)
+{
+ if (g_translateAgentActions)
+ {
+ // HACK: these are the bits we can safely translate from control flags to GameControl
+ // Extracting LLGameControl::InputChannels that are mapped to other bits is a WIP.
+ // TODO: translate other bits to GameControl, which might require measure of gAgent
+ // state changes (e.g. sitting <--> standing, flying <--> not-flying, etc)
+ const U32 BITS_OF_INTEREST =
+ AGENT_CONTROL_AT_POS | AGENT_CONTROL_AT_NEG
+ | AGENT_CONTROL_LEFT_POS | AGENT_CONTROL_LEFT_NEG
+ | AGENT_CONTROL_UP_POS | AGENT_CONTROL_UP_NEG
+ | AGENT_CONTROL_YAW_POS | AGENT_CONTROL_YAW_NEG
+ | AGENT_CONTROL_PITCH_POS | AGENT_CONTROL_PITCH_NEG
+ | AGENT_CONTROL_STOP
+ | AGENT_CONTROL_FAST_AT
+ | AGENT_CONTROL_FAST_LEFT
+ | AGENT_CONTROL_FAST_UP;
+ action_flags &= BITS_OF_INTEREST;
+
+ U32 active_flags = action_flags & mActionTranslator.getMappedFlags();
+ if (active_flags != mLastActiveFlags)
+ {
+ mLastActiveFlags = active_flags;
+ mExternalState = mActionTranslator.computeStateFromFlags(action_flags);
+ mExternalState.mButtons |= buttons;
+ }
+ else
+ {
+ mExternalState.mButtons = buttons;
+ }
+ }
+ else
+ {
+ mExternalState.mButtons = buttons;
+ }
+}
+
+void LLGameControllerManager::clear()
+{
+ mDevices.clear();
+}
+
+U64 get_now_nsec()
+{
+ std::chrono::time_point<std::chrono::steady_clock> t0;
+ return (std::chrono::steady_clock::now() - t0).count();
+}
+
+void onJoystickDeviceAdded(const SDL_Event& event)
+{
+ SDL_JoystickGUID guid(SDL_JoystickGetDeviceGUID(event.cdevice.which));
+ SDL_JoystickType type(SDL_JoystickGetDeviceType(event.cdevice.which));
+ std::string name(ll_safe_string(SDL_JoystickNameForIndex(event.cdevice.which)));
+
+ LL_INFOS("SDL2") << "joystick {id:" << event.cdevice.which
+ << ",guid:'" << guid << "'"
+ << ",type:'" << type << "'"
+ << ",name:'" << name << "'"
+ << "}" << LL_ENDL;
+
+ if (SDL_Joystick* joystick = SDL_JoystickOpen(event.cdevice.which))
+ {
+ LL_INFOS("SDL2") << "joystick " << joystick << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("SDL2") << "Can't open joystick: " << SDL_GetError() << LL_ENDL;
+ }
+}
+
+void onJoystickDeviceRemoved(const SDL_Event& event)
+{
+ LL_INFOS("SDL2") << "joystick id: " << event.cdevice.which << LL_ENDL;
+}
+
+void onControllerDeviceAdded(const SDL_Event& event)
+{
+ std::string guid(std::to_string(SDL_JoystickGetDeviceGUID(event.cdevice.which)));
+ SDL_GameControllerType type(SDL_GameControllerTypeForIndex(event.cdevice.which));
+ std::string name(ll_safe_string(SDL_GameControllerNameForIndex(event.cdevice.which)));
+
+ LL_INFOS("SDL2") << "controller {id:" << event.cdevice.which
+ << ",guid:'" << guid << "'"
+ << ",type:'" << type << "'"
+ << ",name:'" << name << "'"
+ << "}" << LL_ENDL;
+
+ SDL_JoystickID id = SDL_JoystickGetDeviceInstanceID(event.cdevice.which);
+ if (id < 0)
+ {
+ LL_WARNS("SDL2") << "Can't get device instance ID: " << SDL_GetError() << LL_ENDL;
+ return;
+ }
+
+ SDL_GameController* controller = SDL_GameControllerOpen(event.cdevice.which);
+ if (!controller)
+ {
+ LL_WARNS("SDL2") << "Can't open game controller: " << SDL_GetError() << LL_ENDL;
+ return;
+ }
+
+ g_manager.addController(id, guid, name);
+
+ // this event could happen while the preferences UI is open
+ // in which case we need to force it to update
+ s_updateUI();
+}
+
+void onControllerDeviceRemoved(const SDL_Event& event)
+{
+ LL_INFOS("SDL2") << "joystick id=" << event.cdevice.which << LL_ENDL;
+
+ SDL_JoystickID id = event.cdevice.which;
+ g_manager.removeController(id);
+
+ // this event could happen while the preferences UI is open
+ // in which case we need to force it to update
+ s_updateUI();
+}
+
+void onControllerButton(const SDL_Event& event)
+{
+ g_manager.onButton(event.cbutton.which, event.cbutton.button, event.cbutton.state == SDL_PRESSED);
+}
+
+void onControllerAxis(const SDL_Event& event)
+{
+ LL_DEBUGS("SDL2") << "joystick=0x" << std::hex << event.caxis.which << std::dec
+ << " axis=" << (S32)(event.caxis.axis)
+ << " value=" << (S32)(event.caxis.value) << LL_ENDL;
+ g_manager.onAxis(event.caxis.which, event.caxis.axis, event.caxis.value);
+}
+
+// static
+bool LLGameControl::isEnabled()
+{
+ return g_enabled;
+}
+
+void LLGameControl::setEnabled(bool enable)
+{
+ if (enable != g_enabled)
+ {
+ g_enabled = enable;
+ s_saveBoolean(SETTING_ENABLE, g_enabled);
+ }
+}
+
+// static
+bool LLGameControl::isInitialized()
+{
+ return g_gameControl != nullptr;
+}
+
+// static
+// TODO: find a cleaner way to provide callbacks to LLGameControl
+void LLGameControl::init(const std::string& gamecontrollerdb_path,
+ std::function<bool(const std::string&)> loadBoolean,
+ std::function<void(const std::string&, bool)> saveBoolean,
+ std::function<std::string(const std::string&)> loadString,
+ std::function<void(const std::string&, const std::string&)> saveString,
+ std::function<LLSD(const std::string&)> loadObject,
+ std::function<void(const std::string&, const LLSD&)> saveObject,
+ std::function<void()> updateUI)
+{
+ if (g_gameControl)
+ return;
+
+ llassert(loadBoolean);
+ llassert(saveBoolean);
+ llassert(loadString);
+ llassert(saveString);
+ llassert(loadObject);
+ llassert(saveObject);
+ llassert(updateUI);
+
+ int result = SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER | SDL_INIT_SENSOR);
+ if (result < 0)
+ {
+ // This error is critical, we stop working with SDL and return
+ LL_WARNS("SDL2") << "Error initializing GameController subsystems : " << SDL_GetError() << LL_ENDL;
+ return;
+ }
+
+ // The inability to read this file is not critical, we can continue working
+ if (!LLFile::isfile(gamecontrollerdb_path.c_str()))
+ {
+ LL_WARNS("SDL2") << "Device mapping db file not found: " << gamecontrollerdb_path << LL_ENDL;
+ }
+ else
+ {
+ int count = SDL_GameControllerAddMappingsFromFile(gamecontrollerdb_path.c_str());
+ if (count < 0)
+ {
+ LL_WARNS("SDL2") << "Error adding mappings from " << gamecontrollerdb_path << " : " << SDL_GetError() << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS("SDL2") << "Total " << count << " mappings added from " << gamecontrollerdb_path << LL_ENDL;
+ }
+ }
+
+ g_gameControl = LLGameControl::getInstance();
+
+ s_loadBoolean = loadBoolean;
+ s_saveBoolean = saveBoolean;
+ s_loadString = loadString;
+ s_saveString = saveString;
+ s_loadObject = loadObject;
+ s_saveObject = saveObject;
+ s_updateUI = updateUI;
+
+ loadFromSettings();
+}
+
+// static
+void LLGameControl::terminate()
+{
+ g_manager.clear();
+}
+
+// static
+const std::list<LLGameControl::Device>& LLGameControl::getDevices()
+{
+ return g_manager.mDevices;
+}
+
+//static
+const std::map<std::string, std::string>& LLGameControl::getDeviceOptions()
+{
+ return g_deviceOptions;
+}
+
+//static
+// returns 'true' if GameControlInput message needs to go out,
+// which will be the case for new data or resend. Call this right
+// before deciding to put a GameControlInput packet on the wire
+// or not.
+bool LLGameControl::computeFinalStateAndCheckForChanges()
+{
+ // Note: LLGameControllerManager::computeFinalState() modifies g_nextResendPeriod as a side-effect
+ g_manager.computeFinalState();
+
+ // should send input when:
+ // sending is enabled and
+ // g_lastSend has "expired"
+ // either because g_nextResendPeriod has been zeroed
+ // or the last send really has expired.
+ return g_enabled && g_sendToServer && (g_lastSend + g_nextResendPeriod < get_now_nsec());
+}
+
+// static
+void LLGameControl::clearAllStates()
+{
+ g_manager.clearAllStates();
+}
+
+// static
+void LLGameControl::processEvents(bool app_has_focus)
+{
+ // This method used by non-linux platforms which only use SDL for GameController input
+ SDL_Event event;
+ if (!app_has_focus)
+ {
+ // when SL window lacks focus: pump SDL events but ignore them
+ while (g_gameControl && SDL_PollEvent(&event))
+ {
+ // do nothing: SDL_PollEvent() is the operator
+ }
+ g_manager.clearAllStates();
+ return;
+ }
+
+ while (g_gameControl && SDL_PollEvent(&event))
+ {
+ handleEvent(event, app_has_focus);
+ }
+}
+
+void LLGameControl::handleEvent(const SDL_Event& event, bool app_has_focus)
+{
+ switch (event.type)
+ {
+ case SDL_JOYDEVICEADDED:
+ onJoystickDeviceAdded(event);
+ break;
+ case SDL_JOYDEVICEREMOVED:
+ onJoystickDeviceRemoved(event);
+ break;
+ case SDL_CONTROLLERDEVICEADDED:
+ onControllerDeviceAdded(event);
+ break;
+ case SDL_CONTROLLERDEVICEREMOVED:
+ onControllerDeviceRemoved(event);
+ break;
+ case SDL_CONTROLLERBUTTONDOWN:
+ /* FALLTHROUGH */
+ case SDL_CONTROLLERBUTTONUP:
+ if (app_has_focus)
+ {
+ onControllerButton(event);
+ }
+ break;
+ case SDL_CONTROLLERAXISMOTION:
+ if (app_has_focus)
+ {
+ onControllerAxis(event);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+// static
+const LLGameControl::State& LLGameControl::getState()
+{
+ return g_finalState;
+}
+
+// static
+LLGameControl::InputChannel LLGameControl::getActiveInputChannel()
+{
+ InputChannel input;
+
+ State state = g_finalState;
+ if (state.mButtons > 0)
+ {
+ // check buttons
+ input.mType = LLGameControl::InputChannel::TYPE_BUTTON;
+ for (U8 i = 0; i < 32; ++i)
+ {
+ if ((0x1 << i) & state.mButtons)
+ {
+ input.mIndex = i;
+ break;
+ }
+ }
+ }
+ else
+ {
+ // scan axes
+ constexpr S16 threshold = std::numeric_limits<S16>::max() / 2;
+ for (U8 i = 0; i < 6; ++i)
+ {
+ if (abs(state.mAxes[i]) > threshold)
+ {
+ input.mType = LLGameControl::InputChannel::TYPE_AXIS;
+ // input.mIndex ultimately translates to a LLGameControl::KeyboardAxis
+ // which distinguishes between negative and positive directions
+ // so we must translate to axis index "i" according to the sign
+ // of the axis value.
+ input.mIndex = i;
+ input.mSign = state.mAxes[i] > 0 ? 1 : -1;
+ break;
+ }
+ }
+ }
+
+ return input;
+}
+
+// static
+void LLGameControl::getFlycamInputs(std::vector<F32>& inputs_out)
+{
+ return g_manager.getFlycamInputs(inputs_out);
+}
+
+// static
+void LLGameControl::setSendToServer(bool enable)
+{
+ g_sendToServer = enable;
+ s_saveBoolean(SETTING_SENDTOSERVER, g_sendToServer);
+}
+
+// static
+void LLGameControl::setControlAgent(bool enable)
+{
+ g_controlAgent = enable;
+ s_saveBoolean(SETTING_CONTROLAGENT, g_controlAgent);
+}
+
+// static
+void LLGameControl::setTranslateAgentActions(bool enable)
+{
+ g_translateAgentActions = enable;
+ s_saveBoolean(SETTING_TRANSLATEACTIONS, g_translateAgentActions);
+}
+
+// static
+void LLGameControl::setAgentControlMode(LLGameControl::AgentControlMode mode)
+{
+ g_agentControlMode = mode;
+ s_saveString(SETTING_AGENTCONTROLMODE, convertAgentControlModeToString(mode));
+}
+
+// static
+bool LLGameControl::getSendToServer()
+{
+ return g_sendToServer;
+}
+
+// static
+bool LLGameControl::getControlAgent()
+{
+ return g_controlAgent;
+}
+
+// static
+bool LLGameControl::getTranslateAgentActions()
+{
+ return g_translateAgentActions;
+}
+
+// static
+LLGameControl::AgentControlMode LLGameControl::getAgentControlMode()
+{
+ return g_agentControlMode;
+}
+
+// static
+LLGameControl::ActionNameType LLGameControl::getActionNameType(const std::string& action)
+{
+ return g_manager.getActionNameType(action);
+}
+
+// static
+bool LLGameControl::willControlAvatar()
+{
+ return g_enabled && g_controlAgent && g_agentControlMode == CONTROL_MODE_AVATAR;
+}
+
+// static
+//
+// Given a name like "AXIS_1-" or "BUTTON_5" returns the corresponding InputChannel
+// If the axis name lacks the +/- postfix it assumes '+' postfix.
+LLGameControl::InputChannel LLGameControl::getChannelByName(const std::string& name)
+{
+ LLGameControl::InputChannel channel;
+
+ // 'name' has two acceptable formats: AXIS_<index>[sign] or BUTTON_<index>
+ if (LLStringUtil::startsWith(name, "AXIS_"))
+ {
+ channel.mType = LLGameControl::InputChannel::Type::TYPE_AXIS;
+ // Decimal postfix is only one character
+ channel.mIndex = atoi(name.substr(5, 1).c_str());
+ // AXIS_n can have an optional +/- at index 6
+ // Assume positive axis when sign not provided
+ channel.mSign = name.back() == '-' ? -1 : 1;
+ }
+ else if (LLStringUtil::startsWith(name, "BUTTON_"))
+ {
+ channel.mType = LLGameControl::InputChannel::Type::TYPE_BUTTON;
+ // Decimal postfix is only one or two characters
+ channel.mIndex = atoi(name.substr(7).c_str());
+ }
+
+ return channel;
+}
+
+// static
+// Given an action_name like "push+", or "strafe-", returns the InputChannel
+// mapped to it if found, else channel.isNone() will be true.
+LLGameControl::InputChannel LLGameControl::getChannelByAction(const std::string& action)
+{
+ return g_manager.getChannelByAction(action);
+}
+
+// static
+bool LLGameControl::updateActionMap(const std::string& action, LLGameControl::InputChannel channel)
+{
+ return g_manager.updateActionMap(action, channel);
+}
+
+// static
+U32 LLGameControl::computeInternalActionFlags()
+{
+ return g_manager.computeInternalActionFlags();
+}
+
+// static
+void LLGameControl::setExternalInput(U32 action_flags, U32 buttons)
+{
+ g_manager.setExternalInput(action_flags, buttons);
+}
+
+//static
+void LLGameControl::updateResendPeriod()
+{
+ // we expect this method to be called right after data is sent
+ g_lastSend = get_now_nsec();
+ if (g_nextResendPeriod == 0)
+ {
+ g_nextResendPeriod = FIRST_RESEND_PERIOD;
+ }
+ else
+ {
+ // Reset mPrevAxes only on second resend or higher
+ // because when the joysticks are being used we expect a steady stream
+ // of recorrection data rather than sparse changes.
+ //
+ // (The above assumption is not necessarily true for "Actions" input
+ // (e.g. keyboard events). TODO: figure out what to do about this.)
+ //
+ // In other words: we want to include changed axes in the first resend
+ // so we only overwrite g_finalState.mPrevAxes on higher resends.
+ g_finalState.mPrevAxes = g_finalState.mAxes;
+ g_nextResendPeriod *= RESEND_EXPANSION_RATE;
+ }
+}
+
+// static
+std::string LLGameControl::stringifyAnalogMappings(getChannel_t getChannel)
+{
+ return getMappings(g_manager.mAnalogActions, InputChannel::TYPE_AXIS, getChannel);
+}
+
+// static
+std::string LLGameControl::stringifyBinaryMappings(getChannel_t getChannel)
+{
+ return getMappings(g_manager.mBinaryActions, InputChannel::TYPE_BUTTON, getChannel);
+}
+
+// static
+std::string LLGameControl::stringifyFlycamMappings(getChannel_t getChannel)
+{
+ return getMappings(g_manager.mFlycamActions, InputChannel::TYPE_AXIS, getChannel);
+}
+
+// static
+void LLGameControl::getDefaultMappings(std::vector<std::pair<std::string, LLGameControl::InputChannel>>& mappings)
+{
+ g_manager.getDefaultMappings(mappings);
+}
+
+// static
+bool LLGameControl::parseDeviceOptions(const std::string& options, std::string& name,
+ std::vector<LLGameControl::Options::AxisOptions>& axis_options,
+ std::vector<U8>& axis_map, std::vector<U8>& button_map)
+{
+ if (options.empty())
+ return false;
+
+ name.clear();
+ axis_options.resize(NUM_AXES);
+ axis_map.resize(NUM_AXES);
+ button_map.resize(NUM_BUTTONS);
+
+ for (size_t i = 0; i < NUM_AXES; ++i)
+ {
+ axis_options[i].resetToDefaults();
+ axis_map[i] = (U8)i;
+ }
+
+ for (size_t i = 0; i < NUM_BUTTONS; ++i)
+ {
+ button_map[i] = (U8)i;
+ }
+
+ std::map<std::string, std::string> pairs;
+ if (!parse(pairs, options))
+ {
+ LL_WARNS("SDL2") << "Invalid options: '" << options << "'" << LL_ENDL;
+ return false;
+ }
+
+ std::map<std::string, std::string> axis_string_options;
+ if (!parse(axis_string_options, pairs["axis_options"]))
+ {
+ LL_WARNS("SDL2") << "Invalid axis_options: '" << pairs["axis_options"] << "'" << LL_ENDL;
+ return false;
+ }
+
+ std::map<std::string, std::string> axis_string_map;
+ if (!parse(axis_string_map, pairs["axis_map"]))
+ {
+ LL_WARNS("SDL2") << "Invalid axis_map: '" << pairs["axis_map"] << "'" << LL_ENDL;
+ return false;
+ }
+
+ std::map<std::string, std::string> button_string_map;
+ if (!parse(button_string_map, pairs["button_map"]))
+ {
+ LL_WARNS("SDL2") << "Invalid button_map: '" << pairs["button_map"] << "'" << LL_ENDL;
+ return false;
+ }
+
+ name = pairs["name"];
+
+ for (size_t i = 0; i < NUM_AXES; ++i)
+ {
+ std::string key = std::to_string(i);
+
+ std::string one_axis_options = axis_string_options[key];
+ if (!one_axis_options.empty())
+ {
+ axis_options[i].loadFromString(one_axis_options);
+ }
+
+ std::string value = axis_string_map[key];
+ if (!value.empty())
+ {
+ size_t number = std::stoull(value);
+ if (number >= NUM_AXES || std::to_string(number) != value)
+ {
+ LL_WARNS("SDL2") << "Invalid axis mapping: " << i << "->" << value << LL_ENDL;
+ }
+ else
+ {
+ axis_map[i] = (U8)number;
+ }
+ }
+ }
+
+ for (size_t i = 0; i < NUM_BUTTONS; ++i)
+ {
+ std::string value = button_string_map[std::to_string(i)];
+ if (!value.empty())
+ {
+ size_t number = std::stoull(value);
+ if (number >= NUM_BUTTONS || std::to_string(number) != value)
+ {
+ LL_WARNS("SDL2") << "Invalid button mapping: " << i << "->" << value << LL_ENDL;
+ }
+ else
+ {
+ button_map[i] = (U8)number;
+ }
+ }
+ }
+
+ return true;
+}
+
+// static
+std::string LLGameControl::stringifyDeviceOptions(const std::string& name,
+ const std::vector<LLGameControl::Options::AxisOptions>& axis_options,
+ const std::vector<U8>& axis_map, const std::vector<U8>& button_map,
+ bool force_empty)
+{
+ std::list<std::string> options;
+
+ auto opts2str = [](size_t i, const Options::AxisOptions& options) -> std::string
+ {
+ std::string string = options.saveToString();
+ return string.empty() ? string : llformat("%u:%s", i, string.c_str());
+ };
+
+ std::string axis_options_string = LLStringUtil::join<std::vector<Options::AxisOptions>, Options::AxisOptions>(axis_options, opts2str);
+ if (!axis_options_string.empty())
+ {
+ options.push_back("axis_options:{" + axis_options_string + "}");
+ }
+
+ auto map2str = [](size_t index, const U8& value) -> std::string
+ {
+ return value == index ? LLStringUtil::null : llformat("%u:%u", index, value);
+ };
+
+ std::string axis_map_string = LLStringUtil::join<std::vector<U8>, U8>(axis_map, map2str);
+ if (!axis_map_string.empty())
+ {
+ options.push_back("axis_map:{" + axis_map_string + "}");
+ }
+
+ std::string button_map_string = LLStringUtil::join<std::vector<U8>, U8>(button_map, map2str);
+ if (!button_map_string.empty())
+ {
+ options.push_back("button_map:{" + button_map_string + "}");
+ }
+
+ if (!force_empty && options.empty())
+ return LLStringUtil::null;
+
+ // Remove control characters [',', '{', '}'] from name
+ std::string safe_name;
+ safe_name.reserve(name.size());
+ for (char c : name)
+ {
+ if (c != ',' && c != '{' && c != '}')
+ {
+ safe_name.push_back(c);
+ }
+ }
+ options.push_front(llformat("name:%s", safe_name.c_str()));
+
+ std::string result = LLStringUtil::join(options);
+
+ return "{" + result + "}";
+}
+
+// static
+void LLGameControl::initByDefault()
+{
+ g_sendToServer = false;
+ g_controlAgent = false;
+ g_translateAgentActions = false;
+ g_agentControlMode = CONTROL_MODE_AVATAR;
+ g_manager.initializeMappingsByDefault();
+ g_manager.resetDeviceOptionsToDefaults();
+ g_deviceOptions.clear();
+}
+
+// static
+void LLGameControl::loadFromSettings()
+{
+ // In case of absence of the required setting the default value is assigned
+ g_enabled = s_loadBoolean(SETTING_ENABLE);
+ g_sendToServer = s_loadBoolean(SETTING_SENDTOSERVER);
+ g_controlAgent = s_loadBoolean(SETTING_CONTROLAGENT);
+ g_translateAgentActions = s_loadBoolean(SETTING_TRANSLATEACTIONS);
+ g_agentControlMode = convertStringToAgentControlMode(s_loadString(SETTING_AGENTCONTROLMODE));
+
+ g_manager.initializeMappingsByDefault();
+
+ // Load action-to-channel mappings
+ std::string analogMappings = s_loadString(SETTING_ANALOGMAPPINGS);
+ std::string binaryMappings = s_loadString(SETTING_BINARYMAPPINGS);
+ std::string flycamMappings = s_loadString(SETTING_FLYCAMMAPPINGS);
+ g_manager.setAnalogMappings(analogMappings);
+ g_manager.setBinaryMappings(binaryMappings);
+ g_manager.setFlycamMappings(flycamMappings);
+
+ // Load device-specific settings
+ g_deviceOptions.clear();
+ LLSD options = s_loadObject(SETTING_KNOWNCONTROLLERS);
+ for (auto it = options.beginMap(); it != options.endMap(); ++it)
+ {
+ g_deviceOptions.emplace(it->first, it->second);
+ }
+ g_manager.loadDeviceOptionsFromSettings();
+}
+
+// static
+void LLGameControl::saveToSettings()
+{
+ s_saveBoolean(SETTING_ENABLE, g_enabled);
+ s_saveBoolean(SETTING_SENDTOSERVER, g_sendToServer);
+ s_saveBoolean(SETTING_CONTROLAGENT, g_controlAgent);
+ s_saveBoolean(SETTING_TRANSLATEACTIONS, g_translateAgentActions);
+ s_saveString(SETTING_AGENTCONTROLMODE, convertAgentControlModeToString(g_agentControlMode));
+ s_saveString(SETTING_ANALOGMAPPINGS, g_manager.getAnalogMappings());
+ s_saveString(SETTING_BINARYMAPPINGS, g_manager.getBinaryMappings());
+ s_saveString(SETTING_FLYCAMMAPPINGS, g_manager.getFlycamMappings());
+
+ g_manager.saveDeviceOptionsToSettings();
+
+ // construct LLSD version of g_deviceOptions but only include non-empty values
+ LLSD deviceOptions = LLSD::emptyMap();
+ for (const auto& data_pair : g_deviceOptions)
+ {
+ if (!data_pair.second.empty())
+ {
+ LLSD value(data_pair.second);
+ deviceOptions.insert(data_pair.first, value);
+ }
+ }
+
+ s_saveObject(SETTING_KNOWNCONTROLLERS, deviceOptions);
+}
+
+// static
+void LLGameControl::setDeviceOptions(const std::string& guid, const Options& options)
+{
+ g_manager.setDeviceOptions(guid, options);
+}
diff --git a/indra/llwindow/llgamecontrol.h b/indra/llwindow/llgamecontrol.h
new file mode 100644
index 0000000000..a4b47cc47f
--- /dev/null
+++ b/indra/llwindow/llgamecontrol.h
@@ -0,0 +1,347 @@
+/**
+ * @file llgamecontrol.h
+ * @brief GameController detection and management
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2023, 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 <vector>
+
+
+#include "llerror.h"
+#include "llsingleton.h"
+#include "stdtypes.h"
+#include "SDL2/SDL_events.h"
+
+// For reference, here are the RAW indices of the various input channels
+// of a standard XBox controller. Button (N) is numbered in parentheses,
+// whereas axisN has N+ and N- labels.
+//
+// leftpaddle rightpaddle
+// _______ _______
+// / 4+ '-. .-' 5+ \.
+// leftshoulder _(9)_________'-.____ ____.-'_________(10) rightshoulder
+// / _________ \_________/ \.
+// / / 1- \ (3) \.
+// | | | (4) (5) (6) Y |
+// | |0- (7) 0+| _________ (2)X B(1) |
+// | | | / 3- \ A |
+// | | 1+ | | | (0) |
+// | \_________/ |2- (8) 2+| |
+// | leftstick (11) | | |
+// | (13) (14) | 3+ | |
+// | (12) \_________/ |
+// | d-pad rightstick |
+// | ____________________ |
+// | / \ |
+// | / \ |
+// | / \ |
+// \__________/ \__________/
+//
+// Note: the analog joysticks provide NEGATIVE X,Y values for LEFT,FORWARD
+// whereas those directions are actually POSITIVE in SL's local right-handed
+// reference frame. This is why we implicitly negate those axes the moment
+// they are extracted from SDL, before being used anywhere. See the
+// implementation in LLGameControllerManager::onAxis().
+
+// LLGameControl is a singleton with pure static public interface
+class LLGameControl : public LLSingleton<LLGameControl>
+{
+ LLSINGLETON_EMPTY_CTOR(LLGameControl);
+ virtual ~LLGameControl();
+ LOG_CLASS(LLGameControl);
+
+public:
+ enum AgentControlMode
+ {
+ CONTROL_MODE_AVATAR,
+ CONTROL_MODE_FLYCAM,
+ CONTROL_MODE_NONE
+ };
+
+ enum ActionNameType
+ {
+ ACTION_NAME_UNKNOWN,
+ ACTION_NAME_ANALOG, // E.g., "push"
+ ACTION_NAME_ANALOG_POS, // E.g., "push+"
+ ACTION_NAME_ANALOG_NEG, // E.g., "push-"
+ ACTION_NAME_BINARY, // E.g., "stop"
+ ACTION_NAME_FLYCAM // E.g., "zoom"
+ };
+
+ enum KeyboardAxis : U8
+ {
+ AXIS_LEFTX,
+ AXIS_LEFTY,
+ AXIS_RIGHTX,
+ AXIS_RIGHTY,
+ AXIS_TRIGGERLEFT,
+ AXIS_TRIGGERRIGHT,
+ NUM_AXES
+ };
+
+ enum Button
+ {
+ BUTTON_A,
+ BUTTON_B,
+ BUTTON_X,
+ BUTTON_Y,
+ BUTTON_BACK,
+ BUTTON_GUIDE,
+ BUTTON_START,
+ BUTTON_LEFTSTICK,
+ BUTTON_RIGHTSTICK,
+ BUTTON_LEFTSHOULDER,
+ BUTTON_RIGHTSHOULDER, // 10
+ BUTTON_DPAD_UP,
+ BUTTON_DPAD_DOWN,
+ BUTTON_DPAD_LEFT,
+ BUTTON_DPAD_RIGHT,
+ BUTTON_MISC1,
+ BUTTON_PADDLE1,
+ BUTTON_PADDLE2,
+ BUTTON_PADDLE3,
+ BUTTON_PADDLE4,
+ BUTTON_TOUCHPAD, // 20
+ BUTTON_21,
+ BUTTON_22,
+ BUTTON_23,
+ BUTTON_24,
+ BUTTON_25,
+ BUTTON_26,
+ BUTTON_27,
+ BUTTON_28,
+ BUTTON_29,
+ BUTTON_30,
+ BUTTON_31,
+ NUM_BUTTONS
+ };
+
+ static const U16 MAX_AXIS_DEAD_ZONE = 16384;
+ static const U16 MAX_AXIS_OFFSET = 16384;
+
+ class InputChannel
+ {
+ public:
+ enum Type
+ {
+ TYPE_NONE,
+ TYPE_AXIS,
+ TYPE_BUTTON
+ };
+
+ InputChannel() {}
+ InputChannel(Type type, U8 index) : mType(type), mIndex(index) {}
+ InputChannel(Type type, U8 index, S32 sign) : mType(type), mSign(sign), mIndex(index) {}
+
+ // these methods for readability
+ bool isNone() const { return mType == TYPE_NONE; }
+ bool isAxis() const { return mType == TYPE_AXIS; }
+ bool isButton() const { return mType == TYPE_BUTTON; }
+
+ bool isEqual(const InputChannel& other)
+ {
+ return mType == other.mType && mSign == other.mSign && mIndex == other.mIndex;
+ }
+
+ std::string getLocalName() const; // AXIS_0-, AXIS_0+, BUTTON_0, NONE etc.
+ std::string getRemoteName() const; // GAME_CONTROL_AXIS_LEFTX, GAME_CONTROL_BUTTON_A, etc
+
+ Type mType { TYPE_NONE };
+ S32 mSign { 0 };
+ U8 mIndex { 255 };
+ };
+
+ // Options is a data structure for storing device-specific settings
+ class Options
+ {
+ public:
+ struct AxisOptions
+ {
+ S32 mMultiplier = 1;
+ U16 mDeadZone { 0 };
+ S16 mOffset { 0 };
+
+ void resetToDefaults()
+ {
+ mMultiplier = 1;
+ mDeadZone = 0;
+ mOffset = 0;
+ }
+
+ S16 computeModifiedValue(S16 raw_value) const
+ {
+ S32 new_value = ((S32)raw_value + S32(mOffset)) * mMultiplier;
+ return (S16)(std::clamp(new_value, -32768, 32767));
+ }
+
+ std::string saveToString() const;
+ void loadFromString(std::string options);
+ };
+
+ Options();
+
+ void resetToDefaults();
+
+ U8 mapAxis(U8 axis) const;
+ U8 mapButton(U8 button) const;
+
+ S16 fixAxisValue(U8 axis, S16 value) const;
+
+ std::string saveToString(const std::string& name, bool force_empty = false) const;
+ bool loadFromString(std::string& name, std::string options);
+ bool loadFromString(std::string options);
+
+ const std::vector<AxisOptions>& getAxisOptions() const { return mAxisOptions; }
+ std::vector<AxisOptions>& getAxisOptions() { return mAxisOptions; }
+ const std::vector<U8>& getAxisMap() const { return mAxisMap; }
+ std::vector<U8>& getAxisMap() { return mAxisMap; }
+ const std::vector<U8>& getButtonMap() const { return mButtonMap; }
+ std::vector<U8>& getButtonMap() { return mButtonMap; }
+
+ private:
+ std::vector<AxisOptions> mAxisOptions;
+ std::vector<U8> mAxisMap;
+ std::vector<U8> mButtonMap;
+ };
+
+ // State is a minimal class for storing axes and buttons values
+ class State
+ {
+ public:
+ State();
+ void clear();
+ bool onButton(U8 button, bool pressed);
+ std::vector<S16> mAxes; // [ -32768, 32767 ]
+ std::vector<S16> mPrevAxes; // value in last outgoing packet
+ U32 mButtons;
+ };
+
+ // Device is a data structure for describing any detected controller
+ class Device
+ {
+ const int mJoystickID { -1 };
+ const std::string mGUID;
+ const std::string mName;
+ Options mOptions;
+ State mState;
+
+ public:
+ Device(int joystickID, const std::string& guid, const std::string& name);
+ int getJoystickID() const { return mJoystickID; }
+ std::string getGUID() const { return mGUID; }
+ std::string getName() const { return mName; }
+ const Options& getOptions() const { return mOptions; }
+ const State& getState() const { return mState; }
+
+ void resetOptionsToDefaults() { mOptions.resetToDefaults(); }
+ std::string saveOptionsToString(bool force_empty = false) const { return mOptions.saveToString(mName, force_empty); }
+ void loadOptionsFromString(const std::string& options) { mOptions.loadFromString(options); }
+
+ friend class LLGameControllerManager;
+ };
+
+ static bool isEnabled();
+ static void setEnabled(bool enabled);
+
+ static bool isInitialized();
+ static void init(const std::string& gamecontrollerdb_path,
+ std::function<bool(const std::string&)> loadBoolean,
+ std::function<void(const std::string&, bool)> saveBoolean,
+ std::function<std::string(const std::string&)> loadString,
+ std::function<void(const std::string&, const std::string&)> saveString,
+ std::function<LLSD(const std::string&)> loadObject,
+ std::function<void(const std::string&, const LLSD&)> saveObject,
+ std::function<void()> updateUI);
+ static void terminate();
+
+ static const std::list<LLGameControl::Device>& getDevices();
+ static const std::map<std::string, std::string>& getDeviceOptions();
+
+ // returns 'true' if GameControlInput message needs to go out,
+ // which will be the case for new data or resend. Call this right
+ // before deciding to put a GameControlInput packet on the wire
+ // or not.
+ static bool computeFinalStateAndCheckForChanges();
+
+ static void clearAllStates();
+
+ static void processEvents(bool app_has_focus = true);
+ static void handleEvent(const SDL_Event& event, bool app_has_focus);
+ static const State& getState();
+ static InputChannel getActiveInputChannel();
+ static void getFlycamInputs(std::vector<F32>& inputs_out);
+
+ // these methods for accepting input from keyboard
+ static void setSendToServer(bool enable);
+ static void setControlAgent(bool enable);
+ static void setTranslateAgentActions(bool enable);
+ static void setAgentControlMode(AgentControlMode mode);
+
+ static bool getSendToServer();
+ static bool getControlAgent();
+ static bool getTranslateAgentActions();
+ static AgentControlMode getAgentControlMode();
+ static ActionNameType getActionNameType(const std::string& action);
+
+ static bool willControlAvatar();
+
+ // Given a name like "AXIS_1-" or "BUTTON_5" returns the corresponding InputChannel
+ // If the axis name lacks the +/- postfix it assumes '+' postfix.
+ static LLGameControl::InputChannel getChannelByName(const std::string& name);
+
+ // action_name = push+, strafe-, etc
+ static LLGameControl::InputChannel getChannelByAction(const std::string& action);
+
+ static bool updateActionMap(const std::string& action_name, LLGameControl::InputChannel channel);
+
+ // Keyboard presses produce action_flags which can be translated into State
+ // and game_control devices produce State which can be translated into action_flags.
+ // These methods help exchange such translations.
+ static U32 computeInternalActionFlags();
+ static void setExternalInput(U32 action_flags, U32 buttons_from_keys);
+
+ // call this after putting a GameControlInput packet on the wire
+ static void updateResendPeriod();
+
+ using getChannel_t = std::function<LLGameControl::InputChannel(const std::string& action)>;
+ static std::string stringifyAnalogMappings(getChannel_t getChannel);
+ static std::string stringifyBinaryMappings(getChannel_t getChannel);
+ static std::string stringifyFlycamMappings(getChannel_t getChannel);
+ static void getDefaultMappings(std::vector<std::pair<std::string, LLGameControl::InputChannel>>& mappings);
+
+ static bool parseDeviceOptions(const std::string& options, std::string& name,
+ std::vector<LLGameControl::Options::AxisOptions>& axis_options,
+ std::vector<U8>& axis_map, std::vector<U8>& button_map);
+ static std::string stringifyDeviceOptions(const std::string& name,
+ const std::vector<LLGameControl::Options::AxisOptions>& axis_options,
+ const std::vector<U8>& axis_map, const std::vector<U8>& button_map,
+ bool force_empty = false);
+
+ static void initByDefault();
+ static void loadFromSettings();
+ static void saveToSettings();
+ static void setDeviceOptions(const std::string& guid, const Options& options);
+};
+
diff --git a/indra/llwindow/llgamecontroltranslator.cpp b/indra/llwindow/llgamecontroltranslator.cpp
new file mode 100644
index 0000000000..84468ab657
--- /dev/null
+++ b/indra/llwindow/llgamecontroltranslator.cpp
@@ -0,0 +1,275 @@
+/**
+ * @file llgamecontroltranslator.cpp
+ * @brief LLGameControlTranslator class implementation
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2023, 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$
+ */
+
+/*
+ * App-wide preferences. Note that these are not per-user,
+ * because we need to load many preferences before we have
+ * a login name.
+ */
+
+#include "llgamecontroltranslator.h"
+#include "llsd.h"
+
+
+using ActionToMaskMap = LLGameControlTranslator::ActionToMaskMap;
+
+LLGameControlTranslator::LLGameControlTranslator()
+{
+}
+
+void LLGameControlTranslator::setAvailableActionMasks(ActionToMaskMap& action_to_mask)
+{
+ mActionToMask = std::move(action_to_mask);
+}
+
+LLGameControl::InputChannel LLGameControlTranslator::getChannelByAction(const std::string& action) const
+{
+ LLGameControl::InputChannel channel;
+ auto mask_itr = mActionToMask.find(action);
+ if (mask_itr != mActionToMask.end())
+ {
+ U32 mask = mask_itr->second;
+ auto channel_itr = mMaskToChannel.find(mask);
+ if (channel_itr != mMaskToChannel.end())
+ {
+ channel = channel_itr->second;
+ }
+ }
+ else
+ {
+ // It is expected that sometimes 'action' lacks the postfix '+' or '-'.
+ // When it is missing we append '+' and try again.
+ std::string action_plus = action;
+ action_plus.append("+");
+ mask_itr = mActionToMask.find(action_plus);
+ if (mask_itr != mActionToMask.end())
+ {
+ U32 mask = mask_itr->second;
+ auto channel_itr = mMaskToChannel.find(mask);
+ if (channel_itr != mMaskToChannel.end())
+ {
+ channel = channel_itr->second;
+ }
+ }
+ }
+ return channel;
+}
+
+void LLGameControlTranslator::setMappings(LLGameControlTranslator::NamedChannels& named_channels)
+{
+ mMaskToChannel.clear();
+ mMappedFlags = 0;
+ mPrevActiveFlags = 0;
+ mCachedState.clear();
+
+ for (const auto& named_channel : named_channels)
+ {
+ updateMap(named_channel.first, named_channel.second);
+ }
+}
+
+void LLGameControlTranslator::updateMap(const std::string& action, const LLGameControl::InputChannel& channel)
+{
+ // First, get the action name type
+ LLGameControl::ActionNameType actionNameType = LLGameControl::getActionNameType(action);
+ if (actionNameType == LLGameControl::ACTION_NAME_UNKNOWN ||
+ actionNameType == LLGameControl::ACTION_NAME_FLYCAM)
+ {
+ LL_WARNS("SDL2") << "unmappable action='" << action << "' (type=" << actionNameType << ")" << LL_ENDL;
+ return;
+ }
+
+ // Second, get the expected associated channel type (except of TYPE_NONE)
+ LLGameControl::InputChannel::Type expectedChannelType =
+ actionNameType == LLGameControl::ACTION_NAME_BINARY ?
+ LLGameControl::InputChannel::TYPE_BUTTON :
+ LLGameControl::InputChannel::TYPE_AXIS;
+ if (!channel.isNone() && (channel.mType != expectedChannelType))
+ {
+ LL_WARNS("SDL2") << "unmappable channel (type=" << channel.mType << ")"
+ << " for action='" << action << "' (type=" << actionNameType << ")" << LL_ENDL;
+ return;
+ }
+
+ if (actionNameType == LLGameControl::ACTION_NAME_ANALOG) // E.g., "push"
+ {
+ // Special (double) processing for analog action names
+ // sequentially adding '+' and '-' to the given action
+ updateMapInternal(action + "+", channel);
+
+ // For the channel type TYPE_NONE we can map the same channel
+ // In fact, the mapping will be removed from the mapping list
+ if (channel.isNone())
+ {
+ updateMapInternal(action + "-", channel);
+ }
+ else
+ {
+ // For the channel type except of TYPE_NONE we construct the other channel
+ // with the same type and index but with the opposite sign
+ LLGameControl::InputChannel other_channel(channel.mType, channel.mIndex, -channel.mSign);
+
+ // TIED TRIGGER HACK: this works for XBox and similar controllers,
+ // and those are pretty much the only supported devices right now
+ // however TODO: figure out how to do this better.
+ //
+ // AXIS_TRIGGERLEFT and AXIS_TRIGGERRIGHT are separate axes and most devices
+ // only allow them to read positive, not negative. When used for motion control
+ // they are typically paired together. We assume as much here when computing
+ // the other_channel.
+ if (channel.mIndex == LLGameControl::AXIS_TRIGGERLEFT)
+ {
+ other_channel.mIndex = LLGameControl::AXIS_TRIGGERRIGHT;
+ other_channel.mSign = 1;
+ }
+ else if (channel.mIndex == LLGameControl::AXIS_TRIGGERRIGHT)
+ {
+ other_channel.mIndex = LLGameControl::AXIS_TRIGGERLEFT;
+ other_channel.mSign = 1;
+ }
+ updateMapInternal(action + "-", other_channel);
+ }
+ }
+ else
+ {
+ // Simple (single) processing for other action name types
+ updateMapInternal(action, channel);
+ }
+
+ // recompute mMappedFlags
+ mMappedFlags = 0;
+ for (auto& pair : mMaskToChannel)
+ {
+ mMappedFlags |= pair.first;
+ }
+ mPrevActiveFlags = 0;
+ mCachedState.clear();
+}
+
+// Given external action_flags (i.e. raw avatar input)
+// compute the corresponding LLGameControl::State that would have produced those flags.
+// Note: "action flags" are similar to, but not quite the same as, "control flags".
+// "Action flags" are the raw input of avatar movement intent, whereas "control flags"
+// are the consequential set of instructions that are sent to the server for moving
+// the avatar character.
+const LLGameControl::State& LLGameControlTranslator::computeStateFromFlags(U32 action_flags)
+{
+ // translate action_flag bits to equivalent game controller state
+ // according to data in mMaskToChannel
+
+ // only bother to update mCachedState if active_flags have changed
+ U32 active_flags = action_flags & mMappedFlags;
+ if (active_flags != mPrevActiveFlags)
+ {
+ mCachedState.clear();
+ for (const auto& pair : mMaskToChannel)
+ {
+ U32 mask = pair.first;
+ if (mask == (mask & action_flags))
+ {
+ LLGameControl::InputChannel channel = pair.second;
+ if (channel.isAxis())
+ {
+ if (channel.mSign < 0)
+ {
+ mCachedState.mAxes[channel.mIndex] = std::numeric_limits<S16>::min();
+ }
+ else
+ {
+ mCachedState.mAxes[channel.mIndex] = std::numeric_limits<S16>::max();
+ }
+ }
+ else if (channel.isButton())
+ {
+ mCachedState.mButtons |= 0x01U << channel.mIndex;
+ }
+ }
+ }
+ mPrevActiveFlags = active_flags;
+ }
+ return mCachedState;
+}
+
+// Given LLGameControl::State (i.e. from a real controller)
+// compute corresponding action flags (e.g. for moving the avatar around)
+U32 LLGameControlTranslator::computeFlagsFromState(const std::vector<S32>& axes, U32 buttons)
+{
+ // HACK: supply hard-coded threshold for ON/OFF zones
+ constexpr S32 AXIS_THRESHOLD = 32768 / 8;
+ U32 action_flags = 0;
+ for (const auto& pair : mMaskToChannel)
+ {
+ // pair = { mask, channel }
+ const LLGameControl::InputChannel& channel = pair.second;
+ if (channel.isAxis())
+ {
+ if (channel.mSign < 0)
+ {
+ if (axes[channel.mIndex] < -AXIS_THRESHOLD)
+ {
+ action_flags |= pair.first;
+ }
+ }
+ else if (axes[channel.mIndex] > AXIS_THRESHOLD)
+ {
+ action_flags |= pair.first;
+ }
+ }
+ else if (channel.isButton())
+ {
+ U32 bit_set = buttons & (0x01U << channel.mIndex);
+ if (bit_set)
+ {
+ action_flags |= pair.first;
+ }
+ }
+ }
+ return action_flags;
+}
+
+void LLGameControlTranslator::updateMapInternal(const std::string& name, const LLGameControl::InputChannel& channel)
+{
+ auto action_it = mActionToMask.find(name);
+ llassert(action_it != mActionToMask.end());
+ U32 mask = action_it->second;
+ auto channel_it = mMaskToChannel.find(mask);
+ if (channel_it == mMaskToChannel.end())
+ {
+ // create new mapping
+ mMaskToChannel[mask] = channel;
+ }
+ else if (channel.isNone())
+ {
+ // remove old mapping
+ mMaskToChannel.erase(channel_it);
+ }
+ else
+ {
+ // update old mapping
+ channel_it->second = channel;
+ }
+}
+
diff --git a/indra/llwindow/llgamecontroltranslator.h b/indra/llwindow/llgamecontroltranslator.h
new file mode 100644
index 0000000000..533408014c
--- /dev/null
+++ b/indra/llwindow/llgamecontroltranslator.h
@@ -0,0 +1,93 @@
+/**
+ * @file llgamecontroltranslator.h
+ * @brief LLGameControlTranslator class definition
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2023, 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 <map>
+
+#include "stdtypes.h"
+#include "llgamecontrol.h"
+
+
+// GameControl data is sent to the server to expose game controller input to LSL scripts,
+// however not everyone will have a game controller device. To allow keyboard users to provide
+// GameControl data we allow the User to configure equivalences between avatar actions
+// (i.e. "push forward", "strafe left", etc) and keyboard buttons to GameControl axes
+// and buttons.
+//
+// The LLGameControlTranslator stores the equivalences and translates avatar action_flags
+// and keyboard state into GameContrl data, and in some cases the other direction: from
+// LLGameControl::State into avatar action_flags.
+//
+
+class LLGameControlTranslator
+{
+public:
+
+ using ActionToMaskMap = std::map< std::string, U32 >; // < action : mask >
+ using MaskToChannelMap = std::map< U32, LLGameControl::InputChannel >; // < mask : channel >
+ using NamedChannel = std::pair < std::string , LLGameControl::InputChannel >;
+ using NamedChannels = std::vector< NamedChannel >;
+
+
+ LLGameControlTranslator();
+ void setAvailableActionMasks(ActionToMaskMap& action_to_mask);
+ LLGameControl::InputChannel getChannelByAction(const std::string& action) const;
+ void setMappings(NamedChannels& named_channels);
+ void updateMap(const std::string& action, const LLGameControl::InputChannel& channel);
+ // Note: to remove a mapping you can call updateMap() with a TYPE_NONE channel
+
+ // Given external action_flags (i.e. raw avatar input)
+ // compute the corresponding LLGameControl::State that would have produced those flags.
+ // Note: "action_flags" are similar to, but not quite the same as, "control_flags".
+ const LLGameControl::State& computeStateFromFlags(U32 action_flags);
+
+ // Given LLGameControl::State (i.e. from a real controller)
+ // compute corresponding action flags (e.g. for moving the avatar around)
+ U32 computeFlagsFromState(const std::vector<S32>& axes, U32 buttons);
+
+ U32 getMappedFlags() const { return mMappedFlags; }
+
+private:
+ void updateMapInternal(const std::string& name, const LLGameControl::InputChannel& channel);
+
+private:
+ // mActionToMask is an invarient map between the possible actions
+ // and the action bit masks. Only actions therein can have their
+ // bit masks mapped to channels.
+ ActionToMaskMap mActionToMask; // invariant map after init
+
+ // mMaskToChannel is a dynamic map between action bit masks
+ // and GameControl channels.
+ MaskToChannelMap mMaskToChannel; // dynamic map, per preference changes
+
+ // mCachedState is an optimization:
+ // it is only recomputed when external action_flags change
+ LLGameControl::State mCachedState;
+
+ U32 mMappedFlags { 0 };
+ U32 mPrevActiveFlags { 0 };
+};
diff --git a/indra/llwindow/llkeyboard.cpp b/indra/llwindow/llkeyboard.cpp
index b3dcac6222..cb0c312a1d 100644
--- a/indra/llwindow/llkeyboard.cpp
+++ b/indra/llwindow/llkeyboard.cpp
@@ -41,7 +41,6 @@ std::map<KEY,std::string> LLKeyboard::sKeysToNames;
std::map<std::string,KEY> LLKeyboard::sNamesToKeys;
LLKeyStringTranslatorFunc* LLKeyboard::mStringTranslator = NULL; // Used for l10n + PC/Mac/Linux accelerator labeling
-
//
// Class Implementation
//
@@ -55,10 +54,10 @@ LLKeyboard::LLKeyboard() : mCallbacks(NULL)
for (i = 0; i < KEY_COUNT; i++)
{
mKeyLevelFrameCount[i] = 0;
- mKeyLevel[i] = FALSE;
- mKeyUp[i] = FALSE;
- mKeyDown[i] = FALSE;
- mKeyRepeated[i] = FALSE;
+ mKeyLevel[i] = false;
+ mKeyUp[i] = false;
+ mKeyDown[i] = false;
+ mKeyRepeated[i] = false;
}
mInsertMode = LL_KIM_INSERT;
@@ -150,18 +149,19 @@ void LLKeyboard::addKeyName(KEY key, const std::string& name)
void LLKeyboard::resetKeyDownAndHandle()
{
- MASK mask = currentMask(FALSE);
+ MASK mask = currentMask(false);
for (S32 i = 0; i < KEY_COUNT; i++)
{
if (mKeyLevel[i])
{
- mKeyDown[i] = FALSE;
- mKeyLevel[i] = FALSE;
- mKeyUp[i] = TRUE;
+ mKeyDown[i] = false;
+ mKeyLevel[i] = false;
+ mKeyUp[i] = true;
mCurTranslatedKey = (KEY)i;
mCallbacks->handleTranslatedKeyUp(i, mask);
}
}
+ mCurTranslatedKey = KEY_NONE;
}
// BUG this has to be called when an OS dialog is shown, otherwise modifier key state
@@ -174,51 +174,48 @@ void LLKeyboard::resetKeys()
{
if( mKeyLevel[i] )
{
- mKeyLevel[i] = FALSE;
+ mKeyLevel[i] = false;
}
}
for (i = 0; i < KEY_COUNT; i++)
{
- mKeyUp[i] = FALSE;
+ mKeyUp[i] = false;
}
for (i = 0; i < KEY_COUNT; i++)
{
- mKeyDown[i] = FALSE;
+ mKeyDown[i] = false;
}
for (i = 0; i < KEY_COUNT; i++)
{
- mKeyRepeated[i] = FALSE;
+ mKeyRepeated[i] = false;
}
}
-BOOL LLKeyboard::translateKey(const U16 os_key, KEY *out_key)
+bool LLKeyboard::translateKey(const NATIVE_KEY_TYPE os_key, KEY *out_key)
{
- std::map<U16, KEY>::iterator iter;
// Only translate keys in the map, ignore all other keys for now
- iter = mTranslateKeyMap.find(os_key);
+ auto iter = mTranslateKeyMap.find(os_key);
if (iter == mTranslateKeyMap.end())
{
//LL_WARNS() << "Unknown virtual key " << os_key << LL_ENDL;
*out_key = 0;
- return FALSE;
+ return false;
}
else
{
*out_key = iter->second;
- return TRUE;
+ return true;
}
}
-
-U16 LLKeyboard::inverseTranslateKey(const KEY translated_key)
+LLKeyboard::NATIVE_KEY_TYPE LLKeyboard::inverseTranslateKey(const KEY translated_key)
{
- std::map<KEY, U16>::iterator iter;
- iter = mInvTranslateKeyMap.find(translated_key);
+ auto iter = mInvTranslateKeyMap.find(translated_key);
if (iter == mInvTranslateKeyMap.end())
{
return 0;
@@ -230,47 +227,47 @@ U16 LLKeyboard::inverseTranslateKey(const KEY translated_key)
}
-BOOL LLKeyboard::handleTranslatedKeyDown(KEY translated_key, U32 translated_mask)
+bool LLKeyboard::handleTranslatedKeyDown(KEY translated_key, MASK translated_mask)
{
- BOOL handled = FALSE;
- BOOL repeated = FALSE;
+ bool handled = false;
+ bool repeated = false;
// is this the first time the key went down?
// if so, generate "character" message
if( !mKeyLevel[translated_key] )
{
- mKeyLevel[translated_key] = TRUE;
+ mKeyLevel[translated_key] = true;
mKeyLevelTimer[translated_key].reset();
mKeyLevelFrameCount[translated_key] = 0;
- mKeyRepeated[translated_key] = FALSE;
+ mKeyRepeated[translated_key] = false;
}
else
{
// Level is already down, assume it's repeated.
- repeated = TRUE;
- mKeyRepeated[translated_key] = TRUE;
+ repeated = true;
+ mKeyRepeated[translated_key] = true;
}
- mKeyDown[translated_key] = TRUE;
+ mKeyDown[translated_key] = true;
mCurTranslatedKey = (KEY)translated_key;
handled = mCallbacks->handleTranslatedKeyDown(translated_key, translated_mask, repeated);
return handled;
}
-BOOL LLKeyboard::handleTranslatedKeyUp(KEY translated_key, U32 translated_mask)
+bool LLKeyboard::handleTranslatedKeyUp(KEY translated_key, MASK translated_mask)
{
- BOOL handled = FALSE;
+ bool handled = false;
if( mKeyLevel[translated_key] )
{
- mKeyLevel[translated_key] = FALSE;
+ mKeyLevel[translated_key] = false;
// Only generate key up events if the key is thought to
// be down. This allows you to call resetKeys() in the
// middle of a frame and ignore subsequent KEY_UP
// messages in the same frame. This was causing the
// sequence W<return> in chat to move agents forward. JC
- mKeyUp[translated_key] = TRUE;
+ mKeyUp[translated_key] = true;
handled = mCallbacks->handleTranslatedKeyUp(translated_key, translated_mask);
}
@@ -280,6 +277,32 @@ BOOL LLKeyboard::handleTranslatedKeyUp(KEY translated_key, U32 translated_mask)
}
+bool LLKeyboard::handleKeyDown(const NATIVE_KEY_TYPE key, const MASK mask)
+{
+ MASK translated_mask = updateModifiers(mask);
+ KEY translated_key = 0;
+ bool handled = false;
+ if(translateKey(key, &translated_key))
+ {
+ handled = handleTranslatedKeyDown(translated_key, translated_mask);
+ }
+ return handled;
+}
+
+
+bool LLKeyboard::handleKeyUp(const NATIVE_KEY_TYPE key, const MASK mask)
+{
+ MASK translated_mask = updateModifiers(mask);
+ KEY translated_key = 0;
+ bool handled = false;
+ if(translateKey(key, &translated_key))
+ {
+ handled = handleTranslatedKeyUp(translated_key, translated_mask);
+ }
+ return handled;
+}
+
+
void LLKeyboard::toggleInsertMode()
{
if (LL_KIM_INSERT == mInsertMode)
@@ -306,14 +329,14 @@ S32 LLKeyboard::getKeyElapsedFrameCount(KEY key)
}
// static
-BOOL LLKeyboard::keyFromString(const std::string& str, KEY *key)
+bool LLKeyboard::keyFromString(const std::string& str, KEY *key)
{
std::string instring(str);
size_t length = instring.size();
if (length < 1)
{
- return FALSE;
+ return false;
}
if (length == 1)
{
@@ -326,7 +349,7 @@ BOOL LLKeyboard::keyFromString(const std::string& str, KEY *key)
('{' <= ch && ch <= '~')) // {|}~
{
*key = ch;
- return TRUE;
+ return true;
}
}
@@ -335,10 +358,10 @@ BOOL LLKeyboard::keyFromString(const std::string& str, KEY *key)
if (res != 0)
{
*key = res;
- return TRUE;
+ return true;
}
LL_WARNS() << "keyFromString failed: " << str << LL_ENDL;
- return FALSE;
+ return false;
}
@@ -359,7 +382,7 @@ std::string LLKeyboard::stringFromKey(KEY key, bool translate)
LLKeyStringTranslatorFunc *trans = gKeyboard->mStringTranslator;
if (trans != NULL)
{
- res = trans(res.c_str());
+ res = trans(res);
}
}
@@ -399,7 +422,7 @@ std::string LLKeyboard::stringFromMouse(EMouseClickType click, bool translate)
LLKeyStringTranslatorFunc* trans = gKeyboard->mStringTranslator;
if (trans != NULL)
{
- res = trans(res.c_str());
+ res = trans(res);
}
}
return res;
@@ -486,52 +509,52 @@ std::string LLKeyboard::stringFromAccelerator(MASK accel_mask, EMouseClickType c
}
//static
-BOOL LLKeyboard::maskFromString(const std::string& str, MASK *mask)
+bool LLKeyboard::maskFromString(const std::string& str, MASK *mask)
{
std::string instring(str);
if (instring == "NONE")
{
*mask = MASK_NONE;
- return TRUE;
+ return true;
}
else if (instring == "SHIFT")
{
*mask = MASK_SHIFT;
- return TRUE;
+ return true;
}
else if (instring == "CTL")
{
*mask = MASK_CONTROL;
- return TRUE;
+ return true;
}
else if (instring == "ALT")
{
*mask = MASK_ALT;
- return TRUE;
+ return true;
}
else if (instring == "CTL_SHIFT")
{
*mask = MASK_CONTROL | MASK_SHIFT;
- return TRUE;
+ return true;
}
else if (instring == "ALT_SHIFT")
{
*mask = MASK_ALT | MASK_SHIFT;
- return TRUE;
+ return true;
}
else if (instring == "CTL_ALT")
{
*mask = MASK_CONTROL | MASK_ALT;
- return TRUE;
+ return true;
}
else if (instring == "CTL_ALT_SHIFT")
{
*mask = MASK_CONTROL | MASK_ALT | MASK_SHIFT;
- return TRUE;
+ return true;
}
else
{
- return FALSE;
+ return false;
}
}
diff --git a/indra/llwindow/llkeyboard.h b/indra/llwindow/llkeyboard.h
index 2618f9f022..c092f55685 100644
--- a/indra/llwindow/llkeyboard.h
+++ b/indra/llwindow/llkeyboard.h
@@ -42,7 +42,7 @@ enum EKeystate
};
typedef boost::function<bool(EKeystate keystate)> LLKeyFunc;
-typedef std::string (LLKeyStringTranslatorFunc)(const char *label);
+typedef std::string (LLKeyStringTranslatorFunc)(std::string_view);
enum EKeyboardInsertMode
{
@@ -55,6 +55,13 @@ class LLWindowCallbacks;
class LLKeyboard
{
public:
+#ifdef LL_USE_SDL_KEYBOARD
+ // linux relies on SDL2 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();
@@ -64,22 +71,18 @@ public:
F32 getCurKeyElapsedTime() { return getKeyDown(mCurScanKey) ? getKeyElapsedTime( mCurScanKey ) : 0.f; }
F32 getCurKeyElapsedFrameCount() { return getKeyDown(mCurScanKey) ? (F32)getKeyElapsedFrameCount( mCurScanKey ) : 0.f; }
- BOOL getKeyDown(const KEY key) { return mKeyLevel[key]; }
- BOOL getKeyRepeated(const KEY key) { return mKeyRepeated[key]; }
-
- BOOL translateKey(const U16 os_key, KEY *translated_key);
- U16 inverseTranslateKey(const KEY translated_key);
- BOOL handleTranslatedKeyUp(KEY translated_key, U32 translated_mask); // Translated into "Linden" keycodes
- BOOL handleTranslatedKeyDown(KEY translated_key, U32 translated_mask); // Translated into "Linden" keycodes
+ bool getKeyDown(const KEY key) { return mKeyLevel[key]; }
+ 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, MASK translated_mask); // Translated into "Linden" keycodes
+ bool handleTranslatedKeyDown(KEY translated_key, MASK translated_mask); // Translated into "Linden" keycodes
- virtual BOOL handleKeyUp(const U16 key, MASK mask) = 0;
- virtual BOOL handleKeyDown(const U16 key, MASK mask) = 0;
+ virtual bool handleKeyUp(const NATIVE_KEY_TYPE key, MASK mask) = 0;
+ virtual bool handleKeyDown(const NATIVE_KEY_TYPE key, MASK mask) = 0;
-#ifdef LL_DARWIN
- // We only actually use this for OS X.
- virtual void handleModifier(MASK mask) = 0;
-#endif // LL_DARWIN
+ virtual void handleModifier(MASK mask) { }
// Asynchronously poll the control, alt, and shift keys and set the
// appropriate internal key masks.
@@ -87,14 +90,14 @@ public:
virtual void scanKeyboard() = 0; // scans keyboard, calls functions as necessary
// Mac must differentiate between Command = Control for keyboard events
// and Command != Control for mouse events.
- virtual MASK currentMask(BOOL for_mouse_event) = 0;
+ virtual MASK currentMask(bool for_mouse_event) = 0;
virtual KEY currentKey() { return mCurTranslatedKey; }
EKeyboardInsertMode getInsertMode() { return mInsertMode; }
void toggleInsertMode();
- static BOOL maskFromString(const std::string& str, MASK *mask); // False on failure
- static BOOL keyFromString(const std::string& str, KEY *key); // False on failure
+ static bool maskFromString(const std::string& str, MASK *mask); // False on failure
+ static bool keyFromString(const std::string& str, KEY *key); // False on failure
static std::string stringFromKey(KEY key, bool translate = true);
static std::string stringFromMouse(EMouseClickType click, bool translate = true);
static std::string stringFromAccelerator( MASK accel_mask ); // separated for convinience, returns with "+": "Shift+" or "Shift+Alt+"...
@@ -109,18 +112,19 @@ public:
protected:
void addKeyName(KEY key, const std::string& name);
+ virtual MASK updateModifiers(const MASK mask) { return mask; }
protected:
- std::map<U16, KEY> mTranslateKeyMap; // Map of translations from OS keys to Linden KEYs
- std::map<KEY, U16> mInvTranslateKeyMap; // Map of translations from Linden KEYs to OS keys
+ std::map<NATIVE_KEY_TYPE, KEY> mTranslateKeyMap; // Map of translations from OS keys to Linden KEYs
+ std::map<KEY, NATIVE_KEY_TYPE> mInvTranslateKeyMap; // Map of translations from Linden KEYs to OS keys
LLWindowCallbacks *mCallbacks;
LLTimer mKeyLevelTimer[KEY_COUNT]; // Time since level was set
S32 mKeyLevelFrameCount[KEY_COUNT]; // Frames since level was set
- BOOL mKeyLevel[KEY_COUNT]; // Levels
- BOOL mKeyRepeated[KEY_COUNT]; // Key was repeated
- BOOL mKeyUp[KEY_COUNT]; // Up edge
- BOOL mKeyDown[KEY_COUNT]; // Down edge
+ bool mKeyLevel[KEY_COUNT]; // Levels
+ bool mKeyRepeated[KEY_COUNT]; // Key was repeated
+ bool mKeyUp[KEY_COUNT]; // Up edge
+ bool mKeyDown[KEY_COUNT]; // Down edge
KEY mCurTranslatedKey;
KEY mCurScanKey; // Used during the scanKeyboard()
diff --git a/indra/llwindow/llkeyboardheadless.cpp b/indra/llwindow/llkeyboardheadless.cpp
index 01ac26261b..0ca8c09f42 100644
--- a/indra/llwindow/llkeyboardheadless.cpp
+++ b/indra/llwindow/llkeyboardheadless.cpp
@@ -31,18 +31,20 @@
LLKeyboardHeadless::LLKeyboardHeadless()
{ }
-void LLKeyboardHeadless::resetMaskKeys()
-{ }
-
-
-BOOL LLKeyboardHeadless::handleKeyDown(const U16 key, const U32 mask)
-{ return FALSE; }
+bool LLKeyboardHeadless::handleKeyUp(const LLKeyboard::NATIVE_KEY_TYPE key, MASK mask)
+{
+ return false;
+}
+bool LLKeyboardHeadless::handleKeyDown(const LLKeyboard::NATIVE_KEY_TYPE key, MASK mask)
+{
+ return false;
+}
-BOOL LLKeyboardHeadless::handleKeyUp(const U16 key, const U32 mask)
-{ return FALSE; }
+void LLKeyboardHeadless::resetMaskKeys()
+{ }
-MASK LLKeyboardHeadless::currentMask(BOOL for_mouse_event)
+MASK LLKeyboardHeadless::currentMask(bool for_mouse_event)
{ return MASK_NONE; }
#ifdef LL_DARWIN
@@ -65,12 +67,13 @@ 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++)
{
- mKeyUp[key] = FALSE;
- mKeyDown[key] = FALSE;
+ mKeyUp[key] = false;
+ mKeyDown[key] = false;
if (mKeyLevel[key])
{
mKeyLevelFrameCount[key]++;
diff --git a/indra/llwindow/llkeyboardheadless.h b/indra/llwindow/llkeyboardheadless.h
index 8e067e6108..60c4d61e1c 100644
--- a/indra/llwindow/llkeyboardheadless.h
+++ b/indra/llwindow/llkeyboardheadless.h
@@ -33,15 +33,15 @@ class LLKeyboardHeadless : public LLKeyboard
{
public:
LLKeyboardHeadless();
- /*virtual*/ ~LLKeyboardHeadless() {};
+ ~LLKeyboardHeadless() {};
- /*virtual*/ BOOL handleKeyUp(const U16 key, MASK mask);
- /*virtual*/ BOOL handleKeyDown(const U16 key, MASK mask);
- /*virtual*/ void resetMaskKeys();
- /*virtual*/ MASK currentMask(BOOL for_mouse_event);
- /*virtual*/ void scanKeyboard();
+ bool handleKeyUp(const LLKeyboard::NATIVE_KEY_TYPE key, MASK mask) override;
+ bool handleKeyDown(const LLKeyboard::NATIVE_KEY_TYPE key, MASK mask) override;
+ void resetMaskKeys() override;
+ MASK currentMask(bool for_mouse_event) override;
+ void scanKeyboard() override;
#ifdef LL_DARWIN
- /*virtual*/ void handleModifier(MASK mask);
+ void handleModifier(MASK mask) override;
#endif
};
diff --git a/indra/llwindow/llkeyboardmacosx.cpp b/indra/llwindow/llkeyboardmacosx.cpp
index a1aeb2e5e4..1a403e5d94 100644
--- a/indra/llwindow/llkeyboardmacosx.cpp
+++ b/indra/llwindow/llkeyboardmacosx.cpp
@@ -162,7 +162,7 @@ LLKeyboardMacOSX::LLKeyboardMacOSX()
void LLKeyboardMacOSX::resetMaskKeys()
{
- U32 mask = getModifiers();
+ MASK mask = getModifiers();
// MBW -- XXX -- This mirrors the operation of the Windows version of resetMaskKeys().
// It looks a bit suspicious, as it won't correct for keys that have been released.
@@ -172,22 +172,22 @@ void LLKeyboardMacOSX::resetMaskKeys()
if(mask & MAC_SHIFT_KEY)
{
- mKeyLevel[KEY_SHIFT] = TRUE;
+ mKeyLevel[KEY_SHIFT] = true;
}
if(mask & MAC_CTRL_KEY)
{
- mKeyLevel[KEY_CONTROL] = TRUE;
+ mKeyLevel[KEY_CONTROL] = true;
}
if(mask & MAC_ALT_KEY)
{
- mKeyLevel[KEY_ALT] = TRUE;
+ mKeyLevel[KEY_ALT] = true;
}
}
/*
-static BOOL translateKeyMac(const U16 key, const U32 mask, KEY &outKey, U32 &outMask)
+static bool translateKeyMac(const U16 key, const MASK mask, KEY &outKey, U32 &outMask)
{
// Translate the virtual keycode into the keycodes the keyboard system expects.
U16 virtualKey = (mask >> 24) & 0x0000007F;
@@ -203,7 +203,7 @@ void LLKeyboardMacOSX::handleModifier(MASK mask)
updateModifiers(mask);
}
-MASK LLKeyboardMacOSX::updateModifiers(const U32 mask)
+MASK LLKeyboardMacOSX::updateModifiers(const MASK mask)
{
// translate the mask
MASK out_mask = 0;
@@ -226,11 +226,11 @@ 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;
- BOOL handled = FALSE;
+ bool handled = false;
translated_mask = updateModifiers(mask);
@@ -243,11 +243,11 @@ 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;
- BOOL handled = FALSE;
+ bool handled = false;
translated_mask = updateModifiers(mask);
@@ -259,10 +259,10 @@ BOOL LLKeyboardMacOSX::handleKeyUp(const U16 key, const U32 mask)
return handled;
}
-MASK LLKeyboardMacOSX::currentMask(BOOL for_mouse_event)
+MASK LLKeyboardMacOSX::currentMask(bool for_mouse_event)
{
MASK result = MASK_NONE;
- U32 mask = getModifiers();
+ MASK mask = getModifiers();
if (mask & MAC_SHIFT_KEY) result |= MASK_SHIFT;
if (mask & MAC_CTRL_KEY) result |= MASK_CONTROL;
@@ -291,12 +291,13 @@ 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++)
{
- mKeyUp[key] = FALSE;
- mKeyDown[key] = FALSE;
+ mKeyUp[key] = false;
+ mKeyDown[key] = false;
if (mKeyLevel[key])
{
mKeyLevelFrameCount[key]++;
@@ -304,7 +305,7 @@ void LLKeyboardMacOSX::scanKeyboard()
}
}
-BOOL LLKeyboardMacOSX::translateNumpadKey( const U16 os_key, KEY *translated_key )
+bool LLKeyboardMacOSX::translateNumpadKey( const U16 os_key, KEY *translated_key )
{
return translateKey(os_key, translated_key);
}
diff --git a/indra/llwindow/llkeyboardmacosx.h b/indra/llwindow/llkeyboardmacosx.h
index d6895f684d..a5f59f3fba 100644
--- a/indra/llwindow/llkeyboardmacosx.h
+++ b/indra/llwindow/llkeyboardmacosx.h
@@ -42,19 +42,19 @@ class LLKeyboardMacOSX : public LLKeyboard
{
public:
LLKeyboardMacOSX();
- /*virtual*/ ~LLKeyboardMacOSX() {};
+ ~LLKeyboardMacOSX() {};
- /*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 U16 key, MASK mask) override;
+ bool handleKeyDown(const U16 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);
- void setModifierKeyLevel( KEY key, BOOL new_state );
- BOOL translateNumpadKey( const U16 os_key, KEY *translated_key );
+ MASK updateModifiers(const MASK mask) override;
+ void setModifierKeyLevel( KEY key, bool new_state );
+ bool translateNumpadKey( const U16 os_key, KEY *translated_key );
U16 inverseTranslateNumpadKey(const KEY translated_key);
private:
std::map<U16, KEY> mTranslateNumpadMap; // special map for translating OS keys to numpad keys
diff --git a/indra/llwindow/llkeyboardsdl.cpp b/indra/llwindow/llkeyboardsdl.cpp
index 3ee10f70cd..b6666195a6 100644
--- a/indra/llwindow/llkeyboardsdl.cpp
+++ b/indra/llwindow/llkeyboardsdl.cpp
@@ -1,6 +1,5 @@
/**
- * @file llkeyboardsdl.cpp
- * @brief Handler for assignable key bindings
+ * @author This module has many fathers, and it shows.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
@@ -24,12 +23,11 @@
* $/LicenseInfo$
*/
-#if LL_SDL
-
#include "linden_common.h"
#include "llkeyboardsdl.h"
#include "llwindowcallbacks.h"
-#include "SDL/SDL.h"
+
+#include "SDL2/SDL_keycode.h"
LLKeyboardSDL::LLKeyboardSDL()
{
@@ -40,7 +38,11 @@ LLKeyboardSDL::LLKeyboardSDL()
// Virtual key mappings from SDL_keysym.h ...
// SDL maps the letter keys to the ASCII you'd expect, but it's lowercase...
- U16 cur_char;
+
+ // <FS:ND> Looks like we need to map those despite of SDL_TEXTINPUT handling most of this, but without
+ // the translation lower->upper here accelerators will not work.
+
+ LLKeyboard::NATIVE_KEY_TYPE cur_char;
for (cur_char = 'A'; cur_char <= 'Z'; cur_char++)
{
mTranslateKeyMap[cur_char] = cur_char;
@@ -68,13 +70,12 @@ LLKeyboardSDL::LLKeyboardSDL()
//mTranslateKeyMap[SDLK_KP3] = KEY_PAGE_DOWN;
//mTranslateKeyMap[SDLK_KP0] = KEY_INSERT;
- mTranslateKeyMap[SDLK_SPACE] = ' ';
+ mTranslateKeyMap[SDLK_SPACE] = ' '; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
mTranslateKeyMap[SDLK_RETURN] = KEY_RETURN;
mTranslateKeyMap[SDLK_LEFT] = KEY_LEFT;
mTranslateKeyMap[SDLK_RIGHT] = KEY_RIGHT;
mTranslateKeyMap[SDLK_UP] = KEY_UP;
mTranslateKeyMap[SDLK_DOWN] = KEY_DOWN;
- mTranslateKeyMap[SDLK_ESCAPE] = KEY_ESCAPE;
mTranslateKeyMap[SDLK_KP_ENTER] = KEY_RETURN;
mTranslateKeyMap[SDLK_ESCAPE] = KEY_ESCAPE;
mTranslateKeyMap[SDLK_BACKSPACE] = KEY_BACKSPACE;
@@ -111,40 +112,39 @@ LLKeyboardSDL::LLKeyboardSDL()
mTranslateKeyMap[SDLK_F10] = KEY_F10;
mTranslateKeyMap[SDLK_F11] = KEY_F11;
mTranslateKeyMap[SDLK_F12] = KEY_F12;
- mTranslateKeyMap[SDLK_PLUS] = '=';
- mTranslateKeyMap[SDLK_COMMA] = ',';
- mTranslateKeyMap[SDLK_MINUS] = '-';
- mTranslateKeyMap[SDLK_PERIOD] = '.';
- mTranslateKeyMap[SDLK_BACKQUOTE] = '`';
- mTranslateKeyMap[SDLK_SLASH] = KEY_DIVIDE;
- mTranslateKeyMap[SDLK_SEMICOLON] = ';';
- mTranslateKeyMap[SDLK_LEFTBRACKET] = '[';
- mTranslateKeyMap[SDLK_BACKSLASH] = '\\';
- mTranslateKeyMap[SDLK_RIGHTBRACKET] = ']';
- mTranslateKeyMap[SDLK_QUOTE] = '\'';
+ mTranslateKeyMap[SDLK_PLUS] = '='; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
+ mTranslateKeyMap[SDLK_COMMA] = ','; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
+ mTranslateKeyMap[SDLK_MINUS] = '-'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
+ mTranslateKeyMap[SDLK_PERIOD] = '.'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
+ mTranslateKeyMap[SDLK_BACKQUOTE] = '`'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
+ mTranslateKeyMap[SDLK_SLASH] = KEY_DIVIDE; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
+ mTranslateKeyMap[SDLK_SEMICOLON] = ';'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
+ mTranslateKeyMap[SDLK_LEFTBRACKET] = '['; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
+ mTranslateKeyMap[SDLK_BACKSLASH] = '\\'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
+ mTranslateKeyMap[SDLK_RIGHTBRACKET] = ']'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
+ mTranslateKeyMap[SDLK_QUOTE] = '\''; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
// Build inverse map
- std::map<U16, KEY>::iterator iter;
- for (iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end(); iter++)
+ for (auto iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end(); iter++)
{
mInvTranslateKeyMap[iter->second] = iter->first;
}
// numpad map
- mTranslateNumpadMap[SDLK_KP0] = KEY_PAD_INS;
- mTranslateNumpadMap[SDLK_KP1] = KEY_PAD_END;
- mTranslateNumpadMap[SDLK_KP2] = KEY_PAD_DOWN;
- mTranslateNumpadMap[SDLK_KP3] = KEY_PAD_PGDN;
- mTranslateNumpadMap[SDLK_KP4] = KEY_PAD_LEFT;
- mTranslateNumpadMap[SDLK_KP5] = KEY_PAD_CENTER;
- mTranslateNumpadMap[SDLK_KP6] = KEY_PAD_RIGHT;
- mTranslateNumpadMap[SDLK_KP7] = KEY_PAD_HOME;
- mTranslateNumpadMap[SDLK_KP8] = KEY_PAD_UP;
- mTranslateNumpadMap[SDLK_KP9] = KEY_PAD_PGUP;
+ mTranslateNumpadMap[SDLK_KP_0] = KEY_PAD_INS;
+ mTranslateNumpadMap[SDLK_KP_1] = KEY_PAD_END;
+ mTranslateNumpadMap[SDLK_KP_2] = KEY_PAD_DOWN;
+ mTranslateNumpadMap[SDLK_KP_3] = KEY_PAD_PGDN;
+ mTranslateNumpadMap[SDLK_KP_4] = KEY_PAD_LEFT;
+ mTranslateNumpadMap[SDLK_KP_5] = KEY_PAD_CENTER;
+ mTranslateNumpadMap[SDLK_KP_6] = KEY_PAD_RIGHT;
+ mTranslateNumpadMap[SDLK_KP_7] = KEY_PAD_HOME;
+ mTranslateNumpadMap[SDLK_KP_8] = KEY_PAD_UP;
+ mTranslateNumpadMap[SDLK_KP_9] = KEY_PAD_PGUP;
mTranslateNumpadMap[SDLK_KP_PERIOD] = KEY_PAD_DEL;
// build inverse numpad map
- for (iter = mTranslateNumpadMap.begin();
+ for (auto iter = mTranslateNumpadMap.begin();
iter != mTranslateNumpadMap.end();
iter++)
{
@@ -154,7 +154,7 @@ LLKeyboardSDL::LLKeyboardSDL()
void LLKeyboardSDL::resetMaskKeys()
{
- SDLMod mask = SDL_GetModState();
+ SDL_Keymod mask = SDL_GetModState();
// MBW -- XXX -- This mirrors the operation of the Windows version of resetMaskKeys().
// It looks a bit suspicious, as it won't correct for keys that have been released.
@@ -162,22 +162,22 @@ void LLKeyboardSDL::resetMaskKeys()
if(mask & KMOD_SHIFT)
{
- mKeyLevel[KEY_SHIFT] = TRUE;
+ mKeyLevel[KEY_SHIFT] = true;
}
if(mask & KMOD_CTRL)
{
- mKeyLevel[KEY_CONTROL] = TRUE;
+ mKeyLevel[KEY_CONTROL] = true;
}
if(mask & KMOD_ALT)
{
- mKeyLevel[KEY_ALT] = TRUE;
+ mKeyLevel[KEY_ALT] = true;
}
}
-MASK LLKeyboardSDL::updateModifiers(const U32 mask)
+MASK LLKeyboardSDL::updateModifiers(const MASK mask)
{
// translate the mask
MASK out_mask = MASK_NONE;
@@ -201,37 +201,37 @@ MASK LLKeyboardSDL::updateModifiers(const U32 mask)
}
-static U16 adjustNativekeyFromUnhandledMask(const U16 key, const U32 mask)
+U32 adjustNativekeyFromUnhandledMask(const LLKeyboard::NATIVE_KEY_TYPE key, const MASK mask)
{
// SDL doesn't automatically adjust the keysym according to
// whether NUMLOCK is engaged, so we massage the keysym manually.
- U16 rtn = key;
+ U32 rtn = key;
if (!(mask & KMOD_NUM))
{
switch (key)
{
- case SDLK_KP_PERIOD: rtn = SDLK_DELETE; break;
- case SDLK_KP0: rtn = SDLK_INSERT; break;
- case SDLK_KP1: rtn = SDLK_END; break;
- case SDLK_KP2: rtn = SDLK_DOWN; break;
- case SDLK_KP3: rtn = SDLK_PAGEDOWN; break;
- case SDLK_KP4: rtn = SDLK_LEFT; break;
- case SDLK_KP6: rtn = SDLK_RIGHT; break;
- case SDLK_KP7: rtn = SDLK_HOME; break;
- case SDLK_KP8: rtn = SDLK_UP; break;
- case SDLK_KP9: rtn = SDLK_PAGEUP; break;
+ case SDLK_KP_PERIOD: rtn = SDLK_DELETE; break;
+ case SDLK_KP_0: rtn = SDLK_INSERT; break;
+ case SDLK_KP_1: rtn = SDLK_END; break;
+ case SDLK_KP_2: rtn = SDLK_DOWN; break;
+ case SDLK_KP_3: rtn = SDLK_PAGEDOWN; break;
+ case SDLK_KP_4: rtn = SDLK_LEFT; break;
+ case SDLK_KP_6: rtn = SDLK_RIGHT; break;
+ case SDLK_KP_7: rtn = SDLK_HOME; break;
+ case SDLK_KP_8: rtn = SDLK_UP; break;
+ case SDLK_KP_9: rtn = SDLK_PAGEUP; break;
}
}
return rtn;
}
-BOOL LLKeyboardSDL::handleKeyDown(const U16 key, const U32 mask)
+bool LLKeyboardSDL::handleKeyDown(const LLKeyboard::NATIVE_KEY_TYPE key, const MASK mask)
{
- U16 adjusted_nativekey;
+ U32 adjusted_nativekey;
KEY translated_key = 0;
- U32 translated_mask = MASK_NONE;
- BOOL handled = FALSE;
+ MASK translated_mask = MASK_NONE;
+ bool handled = false;
adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask);
@@ -246,12 +246,12 @@ BOOL LLKeyboardSDL::handleKeyDown(const U16 key, const U32 mask)
}
-BOOL LLKeyboardSDL::handleKeyUp(const U16 key, const U32 mask)
+bool LLKeyboardSDL::handleKeyUp(const LLKeyboard::NATIVE_KEY_TYPE key, const MASK mask)
{
- U16 adjusted_nativekey;
+ U32 adjusted_nativekey;
KEY translated_key = 0;
U32 translated_mask = MASK_NONE;
- BOOL handled = FALSE;
+ bool handled = false;
adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask);
@@ -265,19 +265,23 @@ BOOL LLKeyboardSDL::handleKeyUp(const U16 key, const U32 mask)
return handled;
}
-MASK LLKeyboardSDL::currentMask(BOOL for_mouse_event)
+MASK LLKeyboardSDL::currentMask(bool for_mouse_event)
{
MASK result = MASK_NONE;
- SDLMod mask = SDL_GetModState();
+ SDL_Keymod mask = SDL_GetModState();
- if (mask & KMOD_SHIFT) result |= MASK_SHIFT;
- if (mask & KMOD_CTRL) result |= MASK_CONTROL;
- if (mask & KMOD_ALT) result |= MASK_ALT;
+ if (mask & KMOD_SHIFT)
+ result |= MASK_SHIFT;
+ if (mask & KMOD_CTRL)
+ result |= MASK_CONTROL;
+ if (mask & KMOD_ALT)
+ result |= MASK_ALT;
// For keyboard events, consider Meta keys equivalent to Control
if (!for_mouse_event)
{
- if (mask & KMOD_META) result |= MASK_CONTROL;
+ if (mask & KMOD_GUI)
+ result |= MASK_CONTROL;
}
return result;
@@ -296,12 +300,13 @@ 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++)
{
- mKeyUp[key] = FALSE;
- mKeyDown[key] = FALSE;
+ mKeyUp[key] = false;
+ mKeyDown[key] = false;
if (mKeyLevel[key])
{
mKeyLevelFrameCount[key]++;
@@ -310,15 +315,347 @@ void LLKeyboardSDL::scanKeyboard()
}
-BOOL LLKeyboardSDL::translateNumpadKey( const U16 os_key, KEY *translated_key)
+bool LLKeyboardSDL::translateNumpadKey( const LLKeyboard::NATIVE_KEY_TYPE os_key, KEY *translated_key)
{
return translateKey(os_key, translated_key);
}
-U16 LLKeyboardSDL::inverseTranslateNumpadKey(const KEY translated_key)
+LLKeyboard::NATIVE_KEY_TYPE LLKeyboardSDL::inverseTranslateNumpadKey(const KEY translated_key)
{
return inverseTranslateKey(translated_key);
}
-#endif
+enum class WindowsVK : U32
+{
+ VK_UNKNOWN = 0,
+ VK_CANCEL = 0x03,
+ VK_BACK = 0x08,
+ VK_TAB = 0x09,
+ VK_CLEAR = 0x0C,
+ VK_RETURN = 0x0D,
+ VK_SHIFT = 0x10,
+ VK_CONTROL = 0x11,
+ VK_MENU = 0x12,
+ VK_PAUSE = 0x13,
+ VK_CAPITAL = 0x14,
+ VK_KANA = 0x15,
+ VK_HANGUL = 0x15,
+ VK_JUNJA = 0x17,
+ VK_FINAL = 0x18,
+ VK_HANJA = 0x19,
+ VK_KANJI = 0x19,
+ VK_ESCAPE = 0x1B,
+ VK_CONVERT = 0x1C,
+ VK_NONCONVERT = 0x1D,
+ VK_ACCEPT = 0x1E,
+ VK_MODECHANGE = 0x1F,
+ VK_SPACE = 0x20,
+ VK_PRIOR = 0x21,
+ VK_NEXT = 0x22,
+ VK_END = 0x23,
+ VK_HOME = 0x24,
+ VK_LEFT = 0x25,
+ VK_UP = 0x26,
+ VK_RIGHT = 0x27,
+ VK_DOWN = 0x28,
+ VK_SELECT = 0x29,
+ VK_PRINT = 0x2A,
+ VK_EXECUTE = 0x2B,
+ VK_SNAPSHOT = 0x2C,
+ VK_INSERT = 0x2D,
+ VK_DELETE = 0x2E,
+ VK_HELP = 0x2F,
+ VK_0 = 0x30,
+ VK_1 = 0x31,
+ VK_2 = 0x32,
+ VK_3 = 0x33,
+ VK_4 = 0x34,
+ VK_5 = 0x35,
+ VK_6 = 0x36,
+ VK_7 = 0x37,
+ VK_8 = 0x38,
+ VK_9 = 0x39,
+ VK_A = 0x41,
+ VK_B = 0x42,
+ VK_C = 0x43,
+ VK_D = 0x44,
+ VK_E = 0x45,
+ VK_F = 0x46,
+ VK_G = 0x47,
+ VK_H = 0x48,
+ VK_I = 0x49,
+ VK_J = 0x4A,
+ VK_K = 0x4B,
+ VK_L = 0x4C,
+ VK_M = 0x4D,
+ VK_N = 0x4E,
+ VK_O = 0x4F,
+ VK_P = 0x50,
+ VK_Q = 0x51,
+ VK_R = 0x52,
+ VK_S = 0x53,
+ VK_T = 0x54,
+ VK_U = 0x55,
+ VK_V = 0x56,
+ VK_W = 0x57,
+ VK_X = 0x58,
+ VK_Y = 0x59,
+ VK_Z = 0x5A,
+ VK_LWIN = 0x5B,
+ VK_RWIN = 0x5C,
+ VK_APPS = 0x5D,
+ VK_SLEEP = 0x5F,
+ VK_NUMPAD0 = 0x60,
+ VK_NUMPAD1 = 0x61,
+ VK_NUMPAD2 = 0x62,
+ VK_NUMPAD3 = 0x63,
+ VK_NUMPAD4 = 0x64,
+ VK_NUMPAD5 = 0x65,
+ VK_NUMPAD6 = 0x66,
+ VK_NUMPAD7 = 0x67,
+ VK_NUMPAD8 = 0x68,
+ VK_NUMPAD9 = 0x69,
+ VK_MULTIPLY = 0x6A,
+ VK_ADD = 0x6B,
+ VK_SEPARATOR = 0x6C,
+ VK_SUBTRACT = 0x6D,
+ VK_DECIMAL = 0x6E,
+ VK_DIVIDE = 0x6F,
+ VK_F1 = 0x70,
+ VK_F2 = 0x71,
+ VK_F3 = 0x72,
+ VK_F4 = 0x73,
+ VK_F5 = 0x74,
+ VK_F6 = 0x75,
+ VK_F7 = 0x76,
+ VK_F8 = 0x77,
+ VK_F9 = 0x78,
+ VK_F10 = 0x79,
+ VK_F11 = 0x7A,
+ VK_F12 = 0x7B,
+ VK_F13 = 0x7C,
+ VK_F14 = 0x7D,
+ VK_F15 = 0x7E,
+ VK_F16 = 0x7F,
+ VK_F17 = 0x80,
+ VK_F18 = 0x81,
+ VK_F19 = 0x82,
+ VK_F20 = 0x83,
+ VK_F21 = 0x84,
+ VK_F22 = 0x85,
+ VK_F23 = 0x86,
+ VK_F24 = 0x87,
+ VK_NUMLOCK = 0x90,
+ VK_SCROLL = 0x91,
+ VK_LSHIFT = 0xA0,
+ VK_RSHIFT = 0xA1,
+ VK_LCONTROL = 0xA2,
+ VK_RCONTROL = 0xA3,
+ VK_LMENU = 0xA4,
+ VK_RMENU = 0xA5,
+ VK_BROWSER_BACK = 0xA6,
+ VK_BROWSER_FORWARD = 0xA7,
+ VK_BROWSER_REFRESH = 0xA8,
+ VK_BROWSER_STOP = 0xA9,
+ VK_BROWSER_SEARCH = 0xAA,
+ VK_BROWSER_FAVORITES = 0xAB,
+ VK_BROWSER_HOME = 0xAC,
+ VK_VOLUME_MUTE = 0xAD,
+ VK_VOLUME_DOWN = 0xAE,
+ VK_VOLUME_UP = 0xAF,
+ VK_MEDIA_NEXT_TRACK = 0xB0,
+ VK_MEDIA_PREV_TRACK = 0xB1,
+ VK_MEDIA_STOP = 0xB2,
+ VK_MEDIA_PLAY_PAUSE = 0xB3,
+ VK_MEDIA_LAUNCH_MAIL = 0xB4,
+ VK_MEDIA_LAUNCH_MEDIA_SELECT = 0xB5,
+ VK_MEDIA_LAUNCH_APP1 = 0xB6,
+ VK_MEDIA_LAUNCH_APP2 = 0xB7,
+ VK_OEM_1 = 0xBA,
+ VK_OEM_PLUS = 0xBB,
+ VK_OEM_COMMA = 0xBC,
+ VK_OEM_MINUS = 0xBD,
+ VK_OEM_PERIOD = 0xBE,
+ VK_OEM_2 = 0xBF,
+ VK_OEM_3 = 0xC0,
+ VK_OEM_4 = 0xDB,
+ VK_OEM_5 = 0xDC,
+ VK_OEM_6 = 0xDD,
+ VK_OEM_7 = 0xDE,
+ VK_OEM_8 = 0xDF,
+ VK_OEM_102 = 0xE2,
+ VK_PROCESSKEY = 0xE5,
+ VK_PACKET = 0xE7,
+ VK_ATTN = 0xF6,
+ VK_CRSEL = 0xF7,
+ VK_EXSEL = 0xF8,
+ VK_EREOF = 0xF9,
+ VK_PLAY = 0xFA,
+ VK_ZOOM = 0xFB,
+ VK_NONAME = 0xFC,
+ VK_PA1 = 0xFD,
+ VK_OEM_CLEAR = 0xFE,
+};
+
+std::map< U32, U32 > mSDL2_to_Win;
+
+U32 LLKeyboardSDL::mapSDL2toWin( U32 aSymbol )
+{
+ // <FS:ND> Map SDLK_ virtual keys to Windows VK_ virtual keys.
+ // Text is handled via unicode input (SDL_TEXTINPUT event) and does not need to be translated into VK_ values as those match already.
+ if( mSDL2_to_Win.empty() )
+ {
+
+ mSDL2_to_Win[ SDLK_BACKSPACE ] = (U32)WindowsVK::VK_BACK;
+ mSDL2_to_Win[ SDLK_TAB ] = (U32)WindowsVK::VK_TAB;
+ mSDL2_to_Win[ 12 ] = (U32)WindowsVK::VK_CLEAR;
+ mSDL2_to_Win[ SDLK_RETURN ] = (U32)WindowsVK::VK_RETURN;
+ mSDL2_to_Win[ 19 ] = (U32)WindowsVK::VK_PAUSE;
+ mSDL2_to_Win[ SDLK_ESCAPE ] = (U32)WindowsVK::VK_ESCAPE;
+ mSDL2_to_Win[ SDLK_SPACE ] = (U32)WindowsVK::VK_SPACE;
+ mSDL2_to_Win[ SDLK_QUOTE ] = (U32)WindowsVK::VK_OEM_7;
+ mSDL2_to_Win[ SDLK_COMMA ] = (U32)WindowsVK::VK_OEM_COMMA;
+ mSDL2_to_Win[ SDLK_MINUS ] = (U32)WindowsVK::VK_OEM_MINUS;
+ mSDL2_to_Win[ SDLK_PERIOD ] = (U32)WindowsVK::VK_OEM_PERIOD;
+ mSDL2_to_Win[ SDLK_SLASH ] = (U32)WindowsVK::VK_OEM_2;
+
+ mSDL2_to_Win[ SDLK_0 ] = (U32)WindowsVK::VK_0;
+ mSDL2_to_Win[ SDLK_1 ] = (U32)WindowsVK::VK_1;
+ mSDL2_to_Win[ SDLK_2 ] = (U32)WindowsVK::VK_2;
+ mSDL2_to_Win[ SDLK_3 ] = (U32)WindowsVK::VK_3;
+ mSDL2_to_Win[ SDLK_4 ] = (U32)WindowsVK::VK_4;
+ mSDL2_to_Win[ SDLK_5 ] = (U32)WindowsVK::VK_5;
+ mSDL2_to_Win[ SDLK_6 ] = (U32)WindowsVK::VK_6;
+ mSDL2_to_Win[ SDLK_7 ] = (U32)WindowsVK::VK_7;
+ mSDL2_to_Win[ SDLK_8 ] = (U32)WindowsVK::VK_8;
+ mSDL2_to_Win[ SDLK_9 ] = (U32)WindowsVK::VK_9;
+
+ mSDL2_to_Win[ SDLK_SEMICOLON ] = (U32)WindowsVK::VK_OEM_1;
+ mSDL2_to_Win[ SDLK_LESS ] = (U32)WindowsVK::VK_OEM_102;
+ mSDL2_to_Win[ SDLK_EQUALS ] = (U32)WindowsVK::VK_OEM_PLUS;
+ mSDL2_to_Win[ SDLK_KP_EQUALS ] = (U32)WindowsVK::VK_OEM_PLUS;
+
+ mSDL2_to_Win[ SDLK_LEFTBRACKET ] = (U32)WindowsVK::VK_OEM_4;
+ mSDL2_to_Win[ SDLK_BACKSLASH ] = (U32)WindowsVK::VK_OEM_5;
+ mSDL2_to_Win[ SDLK_RIGHTBRACKET ] = (U32)WindowsVK::VK_OEM_6;
+ mSDL2_to_Win[ SDLK_BACKQUOTE ] = (U32)WindowsVK::VK_OEM_8;
+
+ mSDL2_to_Win[ SDLK_a ] = (U32)WindowsVK::VK_A;
+ mSDL2_to_Win[ SDLK_b ] = (U32)WindowsVK::VK_B;
+ mSDL2_to_Win[ SDLK_c ] = (U32)WindowsVK::VK_C;
+ mSDL2_to_Win[ SDLK_d ] = (U32)WindowsVK::VK_D;
+ mSDL2_to_Win[ SDLK_e ] = (U32)WindowsVK::VK_E;
+ mSDL2_to_Win[ SDLK_f ] = (U32)WindowsVK::VK_F;
+ mSDL2_to_Win[ SDLK_g ] = (U32)WindowsVK::VK_G;
+ mSDL2_to_Win[ SDLK_h ] = (U32)WindowsVK::VK_H;
+ mSDL2_to_Win[ SDLK_i ] = (U32)WindowsVK::VK_I;
+ mSDL2_to_Win[ SDLK_j ] = (U32)WindowsVK::VK_J;
+ mSDL2_to_Win[ SDLK_k ] = (U32)WindowsVK::VK_K;
+ mSDL2_to_Win[ SDLK_l ] = (U32)WindowsVK::VK_L;
+ mSDL2_to_Win[ SDLK_m ] = (U32)WindowsVK::VK_M;
+ mSDL2_to_Win[ SDLK_n ] = (U32)WindowsVK::VK_N;
+ mSDL2_to_Win[ SDLK_o ] = (U32)WindowsVK::VK_O;
+ mSDL2_to_Win[ SDLK_p ] = (U32)WindowsVK::VK_P;
+ mSDL2_to_Win[ SDLK_q ] = (U32)WindowsVK::VK_Q;
+ mSDL2_to_Win[ SDLK_r ] = (U32)WindowsVK::VK_R;
+ mSDL2_to_Win[ SDLK_s ] = (U32)WindowsVK::VK_S;
+ mSDL2_to_Win[ SDLK_t ] = (U32)WindowsVK::VK_T;
+ mSDL2_to_Win[ SDLK_u ] = (U32)WindowsVK::VK_U;
+ mSDL2_to_Win[ SDLK_v ] = (U32)WindowsVK::VK_V;
+ mSDL2_to_Win[ SDLK_w ] = (U32)WindowsVK::VK_W;
+ mSDL2_to_Win[ SDLK_x ] = (U32)WindowsVK::VK_X;
+ mSDL2_to_Win[ SDLK_y ] = (U32)WindowsVK::VK_Y;
+ mSDL2_to_Win[ SDLK_z ] = (U32)WindowsVK::VK_Z;
+
+ mSDL2_to_Win[ SDLK_DELETE ] = (U32)WindowsVK::VK_DELETE;
+
+
+ mSDL2_to_Win[ SDLK_NUMLOCKCLEAR ] = (U32)WindowsVK::VK_NUMLOCK;
+ mSDL2_to_Win[ SDLK_SCROLLLOCK ] = (U32)WindowsVK::VK_SCROLL;
+
+ mSDL2_to_Win[ SDLK_HELP ] = (U32)WindowsVK::VK_HELP;
+ mSDL2_to_Win[ SDLK_PRINTSCREEN ] = (U32)WindowsVK::VK_SNAPSHOT;
+ mSDL2_to_Win[ SDLK_CANCEL ] = (U32)WindowsVK::VK_CANCEL;
+ mSDL2_to_Win[ SDLK_APPLICATION ] = (U32)WindowsVK::VK_APPS;
+
+ mSDL2_to_Win[ SDLK_UNKNOWN ] = (U32)WindowsVK::VK_UNKNOWN;
+ mSDL2_to_Win[ SDLK_BACKSPACE ] = (U32)WindowsVK::VK_BACK;
+ mSDL2_to_Win[ SDLK_TAB ] = (U32)WindowsVK::VK_TAB;
+ mSDL2_to_Win[ SDLK_CLEAR ] = (U32)WindowsVK::VK_CLEAR;
+ mSDL2_to_Win[ SDLK_RETURN ] = (U32)WindowsVK::VK_RETURN;
+ mSDL2_to_Win[ SDLK_PAUSE ] = (U32)WindowsVK::VK_PAUSE;
+ mSDL2_to_Win[ SDLK_ESCAPE ] = (U32)WindowsVK::VK_ESCAPE;
+ mSDL2_to_Win[ SDLK_DELETE ] = (U32)WindowsVK::VK_DELETE;
+
+ mSDL2_to_Win[ SDLK_KP_PERIOD ] = (U32)WindowsVK::VK_OEM_PERIOD; // VK_DECIMAL?
+ mSDL2_to_Win[ SDLK_KP_DIVIDE ] = (U32)WindowsVK::VK_DIVIDE;
+ mSDL2_to_Win[ SDLK_KP_MULTIPLY] = (U32)WindowsVK::VK_MULTIPLY;
+ mSDL2_to_Win[ SDLK_KP_MINUS ] = (U32)WindowsVK::VK_OEM_MINUS; // VK_SUBSTRACT?
+ mSDL2_to_Win[ SDLK_KP_PLUS ] = (U32)WindowsVK::VK_OEM_PLUS; // VK_ADD?
+ mSDL2_to_Win[ SDLK_KP_ENTER ] = (U32)WindowsVK::VK_RETURN;
+ mSDL2_to_Win[ SDLK_KP_0 ] = (U32)WindowsVK::VK_NUMPAD0;
+ mSDL2_to_Win[ SDLK_KP_1 ] = (U32)WindowsVK::VK_NUMPAD1;
+ mSDL2_to_Win[ SDLK_KP_2 ] = (U32)WindowsVK::VK_NUMPAD2;
+ mSDL2_to_Win[ SDLK_KP_3 ] = (U32)WindowsVK::VK_NUMPAD3;
+ mSDL2_to_Win[ SDLK_KP_4 ] = (U32)WindowsVK::VK_NUMPAD4;
+ mSDL2_to_Win[ SDLK_KP_5 ] = (U32)WindowsVK::VK_NUMPAD5;
+ mSDL2_to_Win[ SDLK_KP_6 ] = (U32)WindowsVK::VK_NUMPAD6;
+ mSDL2_to_Win[ SDLK_KP_7 ] = (U32)WindowsVK::VK_NUMPAD7;
+ mSDL2_to_Win[ SDLK_KP_8 ] = (U32)WindowsVK::VK_NUMPAD8;
+ mSDL2_to_Win[ SDLK_KP_9 ] = (U32)WindowsVK::VK_NUMPAD9;
+
+ // ?
+
+ mSDL2_to_Win[ SDLK_UP ] = (U32)WindowsVK::VK_UP;
+ mSDL2_to_Win[ SDLK_DOWN ] = (U32)WindowsVK::VK_DOWN;
+ mSDL2_to_Win[ SDLK_RIGHT ] = (U32)WindowsVK::VK_RIGHT;
+ mSDL2_to_Win[ SDLK_LEFT ] = (U32)WindowsVK::VK_LEFT;
+ mSDL2_to_Win[ SDLK_INSERT ] = (U32)WindowsVK::VK_INSERT;
+ mSDL2_to_Win[ SDLK_HOME ] = (U32)WindowsVK::VK_HOME;
+ mSDL2_to_Win[ SDLK_END ] = (U32)WindowsVK::VK_END;
+ mSDL2_to_Win[ SDLK_PAGEUP ] = (U32)WindowsVK::VK_PRIOR;
+ mSDL2_to_Win[ SDLK_PAGEDOWN ] = (U32)WindowsVK::VK_NEXT;
+ mSDL2_to_Win[ SDLK_F1 ] = (U32)WindowsVK::VK_F1;
+ mSDL2_to_Win[ SDLK_F2 ] = (U32)WindowsVK::VK_F2;
+ mSDL2_to_Win[ SDLK_F3 ] = (U32)WindowsVK::VK_F3;
+ mSDL2_to_Win[ SDLK_F4 ] = (U32)WindowsVK::VK_F4;
+ mSDL2_to_Win[ SDLK_F5 ] = (U32)WindowsVK::VK_F5;
+ mSDL2_to_Win[ SDLK_F6 ] = (U32)WindowsVK::VK_F6;
+ mSDL2_to_Win[ SDLK_F7 ] = (U32)WindowsVK::VK_F7;
+ mSDL2_to_Win[ SDLK_F8 ] = (U32)WindowsVK::VK_F8;
+ mSDL2_to_Win[ SDLK_F9 ] = (U32)WindowsVK::VK_F9;
+ mSDL2_to_Win[ SDLK_F10 ] = (U32)WindowsVK::VK_F10;
+ mSDL2_to_Win[ SDLK_F11 ] = (U32)WindowsVK::VK_F11;
+ mSDL2_to_Win[ SDLK_F12 ] = (U32)WindowsVK::VK_F12;
+ mSDL2_to_Win[ SDLK_F13 ] = (U32)WindowsVK::VK_F13;
+ mSDL2_to_Win[ SDLK_F14 ] = (U32)WindowsVK::VK_F14;
+ mSDL2_to_Win[ SDLK_F15 ] = (U32)WindowsVK::VK_F15;
+ mSDL2_to_Win[ SDLK_CAPSLOCK ] = (U32)WindowsVK::VK_CAPITAL;
+ mSDL2_to_Win[ SDLK_RSHIFT ] = (U32)WindowsVK::VK_SHIFT;
+ mSDL2_to_Win[ SDLK_LSHIFT ] = (U32)WindowsVK::VK_SHIFT;
+ mSDL2_to_Win[ SDLK_RCTRL ] = (U32)WindowsVK::VK_CONTROL;
+ mSDL2_to_Win[ SDLK_LCTRL ] = (U32)WindowsVK::VK_CONTROL;
+ mSDL2_to_Win[ SDLK_RALT ] = (U32)WindowsVK::VK_MENU;
+ mSDL2_to_Win[ SDLK_LALT ] = (U32)WindowsVK::VK_MENU;
+
+ mSDL2_to_Win[ SDLK_MENU ] = (U32)WindowsVK::VK_MENU;
+
+ // VK_MODECHANGE ?
+ // mSDL2_to_Win[ SDLK_MODE ] = (U32)WindowsVK::VK_MODE;
+
+ // ?
+ // mSDL2_to_Win[ SDLK_SYSREQ ] = (U32)WindowsVK::VK_SYSREQ;
+ // mSDL2_to_Win[ SDLK_POWER ] = (U32)WindowsVK::VK_POWER;
+ // mSDL2_to_Win[ SDLK_UNDO ] = (U32)WindowsVK::VK_UNDO;
+ // mSDL2_to_Win[ SDLK_KP_EQUALS ] = (U32)WindowsVK::VK_EQUALS;
+ // mSDL2_to_Win[ 311 ] = (U32)WindowsVK::VK_LWIN;
+ // mSDL2_to_Win[ 312 ] = (U32)WindowsVK::VK_RWIN;
+ // mSDL2_to_Win[ SDLK_COLON ] = ?
+ }
+
+ auto itr = mSDL2_to_Win.find( aSymbol );
+ if( itr != mSDL2_to_Win.end() )
+ return itr->second;
+ return aSymbol;
+}
diff --git a/indra/llwindow/llkeyboardsdl.h b/indra/llwindow/llkeyboardsdl.h
index 620f83e9b4..7671e4c859 100644
--- a/indra/llwindow/llkeyboardsdl.h
+++ b/indra/llwindow/llkeyboardsdl.h
@@ -1,8 +1,7 @@
/**
- * @file llkeyboardsdl.h
- * @brief Handler for assignable key bindings
+ * @author This module has many fathers, and it shows.
*
- * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
@@ -24,32 +23,35 @@
* $/LicenseInfo$
*/
-#ifndef LL_LLKEYBOARDSDL_H
-#define LL_LLKEYBOARDSDL_H
+#ifndef LL_LLKEYBOARDSDL2_H
+#define LL_LLKEYBOARDSDL2_H
#include "llkeyboard.h"
-#include "SDL/SDL.h"
+#include "SDL2/SDL.h"
class LLKeyboardSDL : public LLKeyboard
{
public:
LLKeyboardSDL();
- /*virtual*/ ~LLKeyboardSDL() {};
+ ~LLKeyboardSDL() {};
- /*virtual*/ BOOL handleKeyUp(const U16 key, MASK mask);
- /*virtual*/ BOOL handleKeyDown(const U16 key, MASK mask);
- /*virtual*/ void resetMaskKeys();
- /*virtual*/ MASK currentMask(BOOL for_mouse_event);
- /*virtual*/ void scanKeyboard();
+ bool handleKeyUp(const LLKeyboard::NATIVE_KEY_TYPE key, MASK mask) override;
+ bool handleKeyDown(const LLKeyboard::NATIVE_KEY_TYPE key, MASK mask) override;
+ void resetMaskKeys() override;
+ MASK currentMask(bool for_mouse_event) override;
+ void scanKeyboard() override;
protected:
- MASK updateModifiers(const U32 mask);
- void setModifierKeyLevel( KEY key, BOOL new_state );
- BOOL translateNumpadKey( const U16 os_key, KEY *translated_key );
- U16 inverseTranslateNumpadKey(const KEY translated_key);
+ MASK updateModifiers(const MASK mask) override;
+ void setModifierKeyLevel( KEY key, bool new_state );
+ bool translateNumpadKey( const LLKeyboard::NATIVE_KEY_TYPE os_key, KEY *translated_key );
+ LLKeyboard::NATIVE_KEY_TYPE inverseTranslateNumpadKey(const KEY translated_key);
private:
- std::map<U16, KEY> mTranslateNumpadMap; // special map for translating OS keys to numpad keys
- std::map<KEY, U16> mInvTranslateNumpadMap; // inverse of the above
+ std::map<LLKeyboard::NATIVE_KEY_TYPE, KEY> mTranslateNumpadMap; // special map for translating OS keys to numpad keys
+ std::map<KEY, LLKeyboard::NATIVE_KEY_TYPE> mInvTranslateNumpadMap; // inverse of the above
+
+public:
+ static U32 mapSDL2toWin( U32 );
};
#endif
diff --git a/indra/llwindow/llkeyboardwin32.cpp b/indra/llwindow/llkeyboardwin32.cpp
index 4934e21d55..c31ef5c9a3 100644
--- a/indra/llwindow/llkeyboardwin32.cpp
+++ b/indra/llwindow/llkeyboardwin32.cpp
@@ -28,7 +28,7 @@
#include "linden_common.h"
-#include "llwin32headerslean.h"
+#include "llwin32headers.h"
#include "llkeyboardwin32.h"
#include "llwindowcallbacks.h"
@@ -152,22 +152,22 @@ void LLKeyboardWin32::resetMaskKeys()
// bit to indicate that the key is down.
if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
{
- mKeyLevel[KEY_SHIFT] = TRUE;
+ mKeyLevel[KEY_SHIFT] = true;
}
if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
{
- mKeyLevel[KEY_CONTROL] = TRUE;
+ mKeyLevel[KEY_CONTROL] = true;
}
if (GetAsyncKeyState(VK_MENU) & 0x8000)
{
- mKeyLevel[KEY_ALT] = TRUE;
+ mKeyLevel[KEY_ALT] = true;
}
}
-//void LLKeyboardWin32::setModifierKeyLevel( KEY key, BOOL new_state )
+//void LLKeyboardWin32::setModifierKeyLevel( KEY key, bool new_state )
//{
// if( mKeyLevel[key] != new_state )
// {
@@ -182,7 +182,7 @@ void LLKeyboardWin32::resetMaskKeys()
//}
-MASK LLKeyboardWin32::updateModifiers()
+MASK LLKeyboardWin32::updateModifiers(const U32 mask)
{
//RN: this seems redundant, as we should have already received the appropriate
// messages for the modifier keys
@@ -191,19 +191,18 @@ MASK LLKeyboardWin32::updateModifiers()
// (keydown encoded in high order bit of short)
mKeyLevel[KEY_CAPSLOCK] = (GetKeyState(VK_CAPITAL) & 0x0001) != 0; // Low order bit carries the toggle state.
// Get mask for keyboard events
- MASK mask = currentMask(FALSE);
- return mask;
+ return currentMask(false);
}
// 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 U16 key, MASK mask)
{
KEY translated_key;
U32 translated_mask;
- BOOL handled = FALSE;
+ bool handled = false;
- translated_mask = updateModifiers();
+ translated_mask = updateModifiers(mask);
if (translateExtendedKey(key, mask, &translated_key))
{
@@ -214,13 +213,13 @@ 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 U16 key, MASK mask)
{
KEY translated_key;
U32 translated_mask;
- BOOL handled = FALSE;
+ bool handled = false;
- translated_mask = updateModifiers();
+ translated_mask = updateModifiers(mask);
if (translateExtendedKey(key, mask, &translated_key))
{
@@ -231,7 +230,7 @@ BOOL LLKeyboardWin32::handleKeyUp(const U16 key, MASK mask)
}
-MASK LLKeyboardWin32::currentMask(BOOL)
+MASK LLKeyboardWin32::currentMask(bool)
{
MASK mask = MASK_NONE;
@@ -259,12 +258,13 @@ void LLKeyboardWin32::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++)
{
- mKeyUp[key] = FALSE;
- mKeyDown[key] = FALSE;
+ mKeyUp[key] = false;
+ mKeyDown[key] = false;
if (mKeyLevel[key])
{
mKeyLevelFrameCount[key]++;
@@ -272,7 +272,7 @@ void LLKeyboardWin32::scanKeyboard()
}
}
-BOOL LLKeyboardWin32::translateExtendedKey(const U16 os_key, const MASK mask, KEY *translated_key)
+bool LLKeyboardWin32::translateExtendedKey(const U16 os_key, const MASK mask, KEY *translated_key)
{
return translateKey(os_key, translated_key);
}
@@ -321,4 +321,4 @@ U16 LLKeyboardWin32::inverseTranslateExtendedKey(const KEY translated_key)
return inverseTranslateKey(converted_key);
}
-#endif
+#endif // LL_WINDOWS
diff --git a/indra/llwindow/llkeyboardwin32.h b/indra/llwindow/llkeyboardwin32.h
index 838566d69c..ea7bb4d866 100644
--- a/indra/llwindow/llkeyboardwin32.h
+++ b/indra/llwindow/llkeyboardwin32.h
@@ -37,19 +37,20 @@ class LLKeyboardWin32 : public LLKeyboard
{
public:
LLKeyboardWin32();
- /*virtual*/ ~LLKeyboardWin32() {};
+ ~LLKeyboardWin32() {};
- /*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 U16 key, MASK mask) override;
+ bool handleKeyDown(const U16 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();
- //void setModifierKeyLevel( KEY key, BOOL new_state );
+ MASK updateModifiers(const MASK mask) override;
+ //void setModifierKeyLevel( KEY key, bool new_state );
private:
std::map<U16, KEY> mTranslateNumpadMap;
std::map<KEY, U16> mInvTranslateNumpadMap;
diff --git a/indra/llwindow/llmousehandler.cpp b/indra/llwindow/llmousehandler.cpp
index 62ad406967..eeceab502a 100644
--- a/indra/llwindow/llmousehandler.cpp
+++ b/indra/llwindow/llmousehandler.cpp
@@ -27,9 +27,9 @@
#include "llmousehandler.h"
//virtual
-BOOL LLMouseHandler::handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down)
+bool LLMouseHandler::handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, bool down)
{
- BOOL handled = FALSE;
+ bool handled = false;
if (down)
{
switch (clicktype)
diff --git a/indra/llwindow/llmousehandler.h b/indra/llwindow/llmousehandler.h
index dea28a0fc3..565d7bed70 100644
--- a/indra/llwindow/llmousehandler.h
+++ b/indra/llwindow/llmousehandler.h
@@ -47,19 +47,19 @@ public:
SHOW_ALWAYS,
} EShowToolTip;
- virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down);
- virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) = 0;
- virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) = 0;
- virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask) = 0;
- virtual BOOL handleMiddleMouseUp(S32 x, S32 y, MASK mask) = 0;
- virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) = 0;
- virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask) = 0;
- virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask) = 0;
+ virtual bool handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, bool down);
+ virtual bool handleMouseDown(S32 x, S32 y, MASK mask) = 0;
+ virtual bool handleMouseUp(S32 x, S32 y, MASK mask) = 0;
+ virtual bool handleMiddleMouseDown(S32 x, S32 y, MASK mask) = 0;
+ virtual bool handleMiddleMouseUp(S32 x, S32 y, MASK mask) = 0;
+ virtual bool handleRightMouseDown(S32 x, S32 y, MASK mask) = 0;
+ virtual bool handleRightMouseUp(S32 x, S32 y, MASK mask) = 0;
+ virtual bool handleDoubleClick(S32 x, S32 y, MASK mask) = 0;
- virtual BOOL handleHover(S32 x, S32 y, MASK mask) = 0;
- virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) = 0;
- virtual BOOL handleScrollHWheel(S32 x, S32 y, S32 clicks) = 0;
- virtual BOOL handleToolTip(S32 x, S32 y, MASK mask) = 0;
+ virtual bool handleHover(S32 x, S32 y, MASK mask) = 0;
+ virtual bool handleScrollWheel(S32 x, S32 y, S32 clicks) = 0;
+ virtual bool handleScrollHWheel(S32 x, S32 y, S32 clicks) = 0;
+ virtual bool handleToolTip(S32 x, S32 y, MASK mask) = 0;
virtual const std::string& getName() const = 0;
virtual void onMouseCaptureLost() = 0;
@@ -67,7 +67,7 @@ public:
virtual void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const = 0;
virtual void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const = 0;
- virtual BOOL hasMouseCapture() = 0;
+ virtual bool hasMouseCapture() = 0;
};
#endif
diff --git a/indra/llwindow/llpreeditor.h b/indra/llwindow/llpreeditor.h
index 943d70c3dd..492a3e9e88 100644
--- a/indra/llwindow/llpreeditor.h
+++ b/indra/llwindow/llpreeditor.h
@@ -34,7 +34,7 @@ class LLPreeditor
public:
typedef std::vector<S32> segment_lengths_t;
- typedef std::vector<BOOL> standouts_t;
+ typedef std::deque<bool> standouts_t;
// We don't delete against LLPreeditor, but compilers complain without this...
@@ -79,7 +79,7 @@ public:
// Locations are relative to the app window and measured in GL coordinate space (before scaling.)
// query_position is IN argument, and other three are OUT.
- virtual BOOL getPreeditLocation(S32 query_position, LLCoordGL *coord, LLRect *bounds, LLRect *control) const = 0;
+ virtual bool getPreeditLocation(S32 query_position, LLCoordGL *coord, LLRect *bounds, LLRect *control) const = 0;
// Get the size (height) of the current font used in this preeditor.
@@ -93,9 +93,9 @@ public:
// Handle a UTF-32 char on this preeditor, i.e., add the character
// to the contents.
// This is a back door of the method of same name of LLWindowCallback.
- // called_from_parent should be set to FALSE if calling through LLPreeditor.
+ // called_from_parent should be set to false if calling through LLPreeditor.
- virtual BOOL handleUnicodeCharHere(llwchar uni_char) = 0;
+ virtual bool handleUnicodeCharHere(llwchar uni_char) = 0;
};
#endif
diff --git a/indra/llwindow/llsdl.cpp b/indra/llwindow/llsdl.cpp
new file mode 100644
index 0000000000..6161bd2972
--- /dev/null
+++ b/indra/llwindow/llsdl.cpp
@@ -0,0 +1,102 @@
+/**
+ * @file llsdl.cpp
+ * @brief SDL2 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 "SDL2/SDL.h"
+
+#include "llerror.h"
+#include "llwindow.h"
+
+void sdl_logger(void *userdata, int category, SDL_LogPriority priority, const char *message)
+{
+ LL_DEBUGS("SDL2") << "log='" << message << "'" << LL_ENDL;
+}
+
+void init_sdl()
+{
+ 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 with SDL "
+ << int(r_sdl_version.major) << "."
+ << int(r_sdl_version.minor) << "."
+ << int(r_sdl_version.patch) << LL_ENDL;
+#ifdef LL_LINUX
+ // 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_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},
+ };
+#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)) < 0)
+ {
+ 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;
+ }
+ }
+ }
+
+ SDL_LogSetOutputFunction(&sdl_logger, nullptr);
+}
+
+void quit_sdl()
+{
+ SDL_Quit();
+}
diff --git a/indra/llwindow/llsdl.h b/indra/llwindow/llsdl.h
new file mode 100644
index 0000000000..9fc8de129c
--- /dev/null
+++ b/indra/llwindow/llsdl.h
@@ -0,0 +1,30 @@
+/**
+ * @file llsdl.h
+ * @brief SDL2 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
+
+void init_sdl();
+void quit_sdl();
diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp
index 9cc11091b6..93ac58ca6f 100644
--- a/indra/llwindow/llwindow.cpp
+++ b/indra/llwindow/llwindow.cpp
@@ -27,18 +27,19 @@
#include "linden_common.h"
#include "llwindowheadless.h"
-#if LL_MESA_HEADLESS
-#include "llwindowmesaheadless.h"
-#elif LL_SDL
-#include "llwindowsdl.h"
-#elif LL_WINDOWS
+#if LL_WINDOWS
#include "llwindowwin32.h"
#elif LL_DARWIN
#include "llwindowmacosx.h"
+#elif LL_MESA_HEADLESS
+#include "llwindowmesaheadless.h"
+#elif LL_LINUX
+#include "llwindowsdl.h"
#endif
#include "llerror.h"
#include "llkeyboard.h"
+#include "llsdl.h"
#include "llwindowcallbacks.h"
@@ -46,8 +47,8 @@
// Globals
//
LLSplashScreen *gSplashScreenp = NULL;
-BOOL gDebugClicks = FALSE;
-BOOL gDebugWindowProc = FALSE;
+bool gDebugClicks = false;
+bool gDebugWindowProc = false;
const S32 gURLProtocolWhitelistCount = 5;
const std::string gURLProtocolWhitelist[] = { "secondlife:", "http:", "https:", "data:", "mailto:" };
@@ -63,22 +64,22 @@ const std::string gURLProtocolWhitelist[] = { "secondlife:", "http:", "https:",
S32 OSMessageBox(const std::string& text, const std::string& caption, U32 type)
{
// Properly hide the splash screen when displaying the message box
- BOOL was_visible = FALSE;
+ bool was_visible = false;
if (LLSplashScreen::isVisible())
{
- was_visible = TRUE;
+ was_visible = true;
LLSplashScreen::hide();
}
S32 result = 0;
-#if LL_MESA_HEADLESS // !!! *FIX: (?)
LL_WARNS() << "OSMessageBox: " << text << LL_ENDL;
- return OSBTN_OK;
-#elif LL_WINDOWS
+#if LL_WINDOWS
result = OSMessageBoxWin32(text, caption, type);
#elif LL_DARWIN
result = OSMessageBoxMacOSX(text, caption, type);
-#elif LL_SDL
+#elif LL_MESA_HEADLESS // !!! *FIX: (?)
+ return OSBTN_OK;
+#elif LL_LINUX
result = OSMessageBoxSDL(text, caption, type);
#else
#error("OSMessageBox not implemented for this platform!")
@@ -97,9 +98,9 @@ S32 OSMessageBox(const std::string& text, const std::string& caption, U32 type)
// LLWindow
//
-LLWindow::LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags)
+LLWindow::LLWindow(LLWindowCallbacks* callbacks, bool fullscreen, U32 flags)
: mCallbacks(callbacks),
- mPostQuit(TRUE),
+ mPostQuit(true),
mFullscreen(fullscreen),
mFullscreenWidth(0),
mFullscreenHeight(0),
@@ -109,13 +110,13 @@ LLWindow::LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags)
mNumSupportedResolutions(0),
mCurrentCursor(UI_CURSOR_ARROW),
mNextCursor(UI_CURSOR_ARROW),
- mCursorHidden(FALSE),
+ mCursorHidden(false),
mBusyCount(0),
- mIsMouseClipping(FALSE),
+ mIsMouseClipping(false),
mMinWindowWidth(0),
mMinWindowHeight(0),
mSwapMethod(SWAP_METHOD_UNDEFINED),
- mHideCursorPermanent(FALSE),
+ mHideCursorPermanent(false),
mFlags(flags),
mHighSurrogate(0),
mRefreshRate(0)
@@ -127,15 +128,15 @@ LLWindow::~LLWindow()
}
//virtual
-BOOL LLWindow::isValid()
+bool LLWindow::isValid()
{
- return TRUE;
+ return true;
}
//virtual
-BOOL LLWindow::canDelete()
+bool LLWindow::canDelete()
{
- return TRUE;
+ return true;
}
//virtual
@@ -178,9 +179,9 @@ ECursorType LLWindow::getCursor() const
}
//virtual
-BOOL LLWindow::dialogColorPicker(F32 *r, F32 *g, F32 *b)
+bool LLWindow::dialogColorPicker(F32 *r, F32 *g, F32 *b)
{
- return FALSE;
+ return false;
}
void *LLWindow::getMediaWindow()
@@ -189,7 +190,7 @@ void *LLWindow::getMediaWindow()
return getPlatformWindow();
}
-BOOL LLWindow::setSize(LLCoordScreen size)
+bool LLWindow::setSize(LLCoordScreen size)
{
if (!getMaximized())
{
@@ -199,7 +200,7 @@ BOOL LLWindow::setSize(LLCoordScreen size)
return setSizeImpl(size);
}
-BOOL LLWindow::setSize(LLCoordWindow size)
+bool LLWindow::setSize(LLCoordWindow size)
{
//HACK: we are inconsistently using minimum window dimensions
// in this case, we are constraining the inner "client" rect and other times
@@ -241,19 +242,19 @@ void LLWindow::processMiscNativeEvents()
}
//virtual
-BOOL LLWindow::isPrimaryTextAvailable()
+bool LLWindow::isPrimaryTextAvailable()
{
- return FALSE; // no
+ return false; // no
}
//virtual
-BOOL LLWindow::pasteTextFromPrimary(LLWString &dst)
+bool LLWindow::pasteTextFromPrimary(LLWString &dst)
{
- return FALSE; // fail
+ return false; // fail
}
// virtual
-BOOL LLWindow::copyTextToPrimary(const LLWString &src)
+bool LLWindow::copyTextToPrimary(const LLWString &src)
{
- return FALSE; // fail
+ return false; // fail
}
// static
@@ -263,7 +264,7 @@ std::vector<std::string> LLWindow::getDynamicFallbackFontList()
return LLWindowWin32::getDynamicFallbackFontList();
#elif LL_DARWIN
return LLWindowMacOSX::getDynamicFallbackFontList();
-#elif LL_SDL
+#elif LL_LINUX
return LLWindowSDL::getDynamicFallbackFontList();
#else
return std::vector<std::string>();
@@ -336,18 +337,18 @@ void LLWindow::handleUnicodeUTF16(U16 utf16, MASK mask)
// static
bool LLSplashScreen::isVisible()
{
- return gSplashScreenp ? true: false;
+ return gSplashScreenp;
}
// static
LLSplashScreen *LLSplashScreen::create()
{
-#if LL_MESA_HEADLESS || LL_SDL // !!! *FIX: (?)
- return 0;
-#elif LL_WINDOWS
+#if LL_WINDOWS
return new LLSplashScreenWin32;
#elif LL_DARWIN
return new LLSplashScreenMacOSX;
+#elif LL_MESA_HEADLESS || LL_LINUX // !!! *FIX: (?)
+ return 0;
#else
#error("LLSplashScreen not implemented on this platform!")
#endif
@@ -402,36 +403,36 @@ static std::set<LLWindow*> sWindowList;
LLWindow* LLWindowManager::createWindow(
LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags,
- BOOL fullscreen,
- BOOL clearBg,
- BOOL enable_vsync,
- BOOL use_gl,
- BOOL ignore_pixel_depth,
+ bool fullscreen,
+ bool clearBg,
+ bool enable_vsync,
+ bool use_gl,
+ bool ignore_pixel_depth,
U32 fsaa_samples,
U32 max_cores,
- U32 max_vram,
F32 max_gl_version)
{
LLWindow* new_window;
if (use_gl)
{
-#if LL_MESA_HEADLESS
- new_window = new LLWindowMesaHeadless(callbacks,
- title, name, x, y, width, height, flags,
- fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth);
-#elif LL_SDL
- new_window = new LLWindowSDL(callbacks,
- title, x, y, width, height, flags,
- fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
-#elif LL_WINDOWS
+ init_sdl();
+#if LL_WINDOWS
new_window = new LLWindowWin32(callbacks,
title, name, x, y, width, height, flags,
- fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples, max_cores, max_vram, max_gl_version);
+ fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples, max_cores, max_gl_version);
#elif LL_DARWIN
new_window = new LLWindowMacOSX(callbacks,
title, name, x, y, width, height, flags,
fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
+#elif LL_MESA_HEADLESS
+ new_window = new LLWindowMesaHeadless(callbacks,
+ title, name, x, y, width, height, flags,
+ fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth);
+#elif LL_LINUX
+ new_window = new LLWindowSDL(callbacks,
+ title, name, x, y, width, height, flags,
+ fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
#endif
}
else
@@ -441,7 +442,7 @@ LLWindow* LLWindowManager::createWindow(
fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth);
}
- if (FALSE == new_window->isValid())
+ if (false == new_window->isValid())
{
delete new_window;
LL_WARNS() << "LLWindowManager::create() : Error creating window." << LL_ENDL;
@@ -451,25 +452,26 @@ LLWindow* LLWindowManager::createWindow(
return new_window;
}
-BOOL LLWindowManager::destroyWindow(LLWindow* window)
+bool LLWindowManager::destroyWindow(LLWindow* window)
{
if (sWindowList.find(window) == sWindowList.end())
{
LL_ERRS() << "LLWindowManager::destroyWindow() : Window pointer not valid, this window doesn't exist!"
<< LL_ENDL;
- return FALSE;
+ return false;
}
window->close();
sWindowList.erase(window);
+ quit_sdl();
delete window;
- return TRUE;
+ return true;
}
-BOOL LLWindowManager::isWindowValid(LLWindow *window)
+bool LLWindowManager::isWindowValid(LLWindow *window)
{
return sWindowList.find(window) != sWindowList.end();
}
diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h
index aff9334cb6..e74142c7df 100644
--- a/indra/llwindow/llwindow.h
+++ b/indra/llwindow/llwindow.h
@@ -24,8 +24,7 @@
* $/LicenseInfo$
*/
-#ifndef LL_LLWINDOW_H
-#define LL_LLWINDOW_H
+#pragma once
#include "llrect.h"
#include "llcoord.h"
@@ -33,6 +32,7 @@
#include "llcursortypes.h"
#include "llinstancetracker.h"
#include "llsd.h"
+#include "llsdl.h"
class LLSplashScreen;
class LLPreeditor;
@@ -63,21 +63,21 @@ public:
virtual void show() = 0;
virtual void hide() = 0;
virtual void close() = 0;
- virtual BOOL getVisible() = 0;
- virtual BOOL getMinimized() = 0;
- virtual BOOL getMaximized() = 0;
- virtual BOOL maximize() = 0;
+ virtual bool getVisible() const = 0;
+ virtual bool getMinimized() const = 0;
+ virtual bool getMaximized() const = 0;
+ virtual bool maximize() = 0;
virtual void minimize() = 0;
virtual void restore() = 0;
- BOOL getFullscreen() { return mFullscreen; };
- virtual BOOL getPosition(LLCoordScreen *position) = 0;
- virtual BOOL getSize(LLCoordScreen *size) = 0;
- virtual BOOL getSize(LLCoordWindow *size) = 0;
- virtual BOOL setPosition(LLCoordScreen position) = 0;
- BOOL setSize(LLCoordScreen size);
- BOOL setSize(LLCoordWindow size);
+ virtual bool getFullscreen() const { return mFullscreen; };
+ virtual bool getPosition(LLCoordScreen *position) const = 0;
+ virtual bool getSize(LLCoordScreen *size) const = 0;
+ virtual bool getSize(LLCoordWindow *size) const = 0;
+ virtual bool setPosition(LLCoordScreen position) = 0;
+ bool setSize(LLCoordScreen size);
+ bool setSize(LLCoordWindow size);
virtual void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true);
- virtual BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL) = 0;
+ virtual bool switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp = NULL) = 0;
//create a new GL context that shares a namespace with this Window's main GL context and make it current on the current thread
// returns a pointer to be handed back to destroySharedConext/makeContextCurrent
@@ -90,14 +90,14 @@ public:
virtual void toggleVSync(bool enable_vsync) = 0;
- virtual BOOL setCursorPosition(LLCoordWindow position) = 0;
- virtual BOOL getCursorPosition(LLCoordWindow *position) = 0;
+ virtual bool setCursorPosition(LLCoordWindow position) = 0;
+ virtual bool getCursorPosition(LLCoordWindow *position) = 0;
#if LL_WINDOWS
- virtual BOOL getCursorDelta(LLCoordCommon* delta) = 0;
+ virtual bool getCursorDelta(LLCoordCommon* delta) const = 0;
#endif
virtual void showCursor() = 0;
virtual void hideCursor() = 0;
- virtual BOOL isCursorHidden() = 0;
+ virtual bool isCursorHidden() = 0;
virtual void showCursorFromMouseMove() = 0;
virtual void hideCursorUntilMouseMove() = 0;
@@ -124,25 +124,25 @@ public:
virtual void captureMouse() = 0;
virtual void releaseMouse() = 0;
- virtual void setMouseClipping( BOOL b ) = 0;
+ virtual void setMouseClipping( bool b ) = 0;
- virtual BOOL isClipboardTextAvailable() = 0;
- virtual BOOL pasteTextFromClipboard(LLWString &dst) = 0;
- virtual BOOL copyTextToClipboard(const LLWString &src) = 0;
+ virtual bool isClipboardTextAvailable() = 0;
+ virtual bool pasteTextFromClipboard(LLWString &dst) = 0;
+ virtual bool copyTextToClipboard(const LLWString &src) = 0;
- virtual BOOL isPrimaryTextAvailable();
- virtual BOOL pasteTextFromPrimary(LLWString &dst);
- virtual BOOL copyTextToPrimary(const LLWString &src);
+ virtual bool isPrimaryTextAvailable();
+ virtual bool pasteTextFromPrimary(LLWString &dst);
+ virtual bool copyTextToPrimary(const LLWString &src);
virtual void flashIcon(F32 seconds) = 0;
- virtual F32 getGamma() = 0;
- virtual BOOL setGamma(const F32 gamma) = 0; // Set the gamma
+ virtual F32 getGamma() const = 0;
+ virtual bool setGamma(const F32 gamma) = 0; // Set the gamma
virtual void setFSAASamples(const U32 fsaa_samples) = 0; //set number of FSAA samples
- virtual U32 getFSAASamples() = 0;
- virtual BOOL restoreGamma() = 0; // Restore original gamma table (before updating gamma)
- virtual ESwapMethod getSwapMethod() { return mSwapMethod; }
+ virtual U32 getFSAASamples() const = 0;
+ virtual bool restoreGamma() = 0; // Restore original gamma table (before updating gamma)
+ ESwapMethod getSwapMethod() { return mSwapMethod; }
virtual void processMiscNativeEvents();
- virtual void gatherInput() = 0;
+ virtual void gatherInput(bool app_has_focus) = 0;
virtual void delayInputProcessing() = 0;
virtual void swapBuffers() = 0;
virtual void bringToFront() = 0;
@@ -151,12 +151,12 @@ public:
// handy coordinate space conversion routines
// NB: screen to window and vice verse won't work on width/height coordinate pairs,
// as the conversion must take into account left AND right border widths, etc.
- virtual BOOL convertCoords( LLCoordScreen from, LLCoordWindow *to) = 0;
- virtual BOOL convertCoords( LLCoordWindow from, LLCoordScreen *to) = 0;
- virtual BOOL convertCoords( LLCoordWindow from, LLCoordGL *to) = 0;
- virtual BOOL convertCoords( LLCoordGL from, LLCoordWindow *to) = 0;
- virtual BOOL convertCoords( LLCoordScreen from, LLCoordGL *to) = 0;
- virtual BOOL convertCoords( LLCoordGL from, LLCoordScreen *to) = 0;
+ virtual bool convertCoords( LLCoordScreen from, LLCoordWindow *to) const = 0;
+ virtual bool convertCoords( LLCoordWindow from, LLCoordScreen *to) const = 0;
+ virtual bool convertCoords( LLCoordWindow from, LLCoordGL *to) const = 0;
+ virtual bool convertCoords( LLCoordGL from, LLCoordWindow *to) const = 0;
+ virtual bool convertCoords( LLCoordScreen from, LLCoordGL *to) const = 0;
+ virtual bool convertCoords( LLCoordGL from, LLCoordScreen *to) const = 0;
// query supported resolutions
virtual LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) = 0;
@@ -164,15 +164,12 @@ public:
virtual F32 getPixelAspectRatio() = 0;
virtual void setNativeAspectRatio(F32 aspect) = 0;
- // query VRAM usage
- virtual U32 getAvailableVRAMMegabytes() = 0;
-
virtual void beforeDialog() {}; // prepare to put up an OS dialog (if special measures are required, such as in fullscreen mode)
virtual void afterDialog() {}; // undo whatever was done in beforeDialog()
// opens system default color picker, modally
- // Returns TRUE if valid color selected
- virtual BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b);
+ // Returns true if valid color selected
+ virtual bool dialogColorPicker(F32 *r, F32 *g, F32 *b);
// return a platform-specific window reference (HWND on Windows, WindowRef on the Mac, Gtk window on Linux)
virtual void *getPlatformWindow() = 0;
@@ -181,16 +178,18 @@ public:
virtual void *getMediaWindow();
// control platform's Language Text Input mechanisms.
- virtual void allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) {}
+ virtual void allowLanguageTextInput(LLPreeditor *preeditor, bool b) {}
virtual void setLanguageTextInput( const LLCoordGL & pos ) {};
virtual void updateLanguageTextInputArea() {}
virtual void interruptLanguageTextInput() {}
virtual void spawnWebBrowser(const std::string& escaped_url, bool async) {};
+ virtual void openFolder(const std::string &path) {};
+
static std::vector<std::string> getDynamicFallbackFontList();
// Provide native key event data
- virtual LLSD getNativeKeyData() { return LLSD::emptyMap(); }
+ virtual LLSD getNativeKeyData() const { return LLSD::emptyMap(); }
// Get system UI size based on DPI (for 96 DPI UI size should be 1.0)
virtual F32 getSystemUISize() { return 1.0; }
@@ -207,23 +206,23 @@ public:
return false;
};
- virtual S32 getRefreshRate() { return mRefreshRate; }
+ virtual S32 getRefreshRate() const { return mRefreshRate; }
protected:
- LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags);
+ LLWindow(LLWindowCallbacks* callbacks, bool fullscreen, U32 flags);
virtual ~LLWindow();
// Defaults to true
- virtual BOOL isValid();
+ virtual bool isValid();
// Defaults to true
- virtual BOOL canDelete();
+ virtual bool canDelete();
- virtual BOOL setSizeImpl(LLCoordScreen size) = 0;
- virtual BOOL setSizeImpl(LLCoordWindow size) = 0;
+ virtual bool setSizeImpl(LLCoordScreen size) = 0;
+ virtual bool setSizeImpl(LLCoordWindow size) = 0;
protected:
LLWindowCallbacks* mCallbacks;
- BOOL mPostQuit; // should this window post a quit message when destroyed?
- BOOL mFullscreen;
+ bool mPostQuit; // should this window post a quit message when destroyed?
+ bool mFullscreen;
S32 mFullscreenWidth;
S32 mFullscreenHeight;
S32 mFullscreenBits;
@@ -232,11 +231,11 @@ protected:
S32 mNumSupportedResolutions;
ECursorType mCurrentCursor;
ECursorType mNextCursor;
- BOOL mCursorHidden;
+ bool mCursorHidden;
S32 mBusyCount; // how deep is the "cursor busy" stack?
- BOOL mIsMouseClipping; // Is this window currently clipping the mouse
+ bool mIsMouseClipping; // Is this window currently clipping the mouse
ESwapMethod mSwapMethod;
- BOOL mHideCursorPermanent;
+ bool mHideCursorPermanent;
U32 mFlags;
U16 mHighSurrogate;
S32 mMinWindowWidth;
@@ -281,20 +280,20 @@ protected:
virtual void updateImpl(const std::string& string) = 0;
virtual void hideImpl() = 0;
- static BOOL sVisible;
+ static bool sVisible;
};
// Platform-neutral for accessing the platform specific message box
S32 OSMessageBox(const std::string& text, const std::string& caption, U32 type);
-const U32 OSMB_OK = 0;
-const U32 OSMB_OKCANCEL = 1;
-const U32 OSMB_YESNO = 2;
+constexpr U32 OSMB_OK = 0;
+constexpr U32 OSMB_OKCANCEL = 1;
+constexpr U32 OSMB_YESNO = 2;
-const S32 OSBTN_YES = 0;
-const S32 OSBTN_NO = 1;
-const S32 OSBTN_OK = 2;
-const S32 OSBTN_CANCEL = 3;
+constexpr S32 OSBTN_YES = 0;
+constexpr S32 OSBTN_NO = 1;
+constexpr S32 OSBTN_OK = 2;
+constexpr S32 OSBTN_CANCEL = 3;
//
// LLWindowManager
@@ -307,29 +306,25 @@ public:
LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
U32 flags = 0,
- BOOL fullscreen = FALSE,
- BOOL clearBg = FALSE,
- BOOL enable_vsync = FALSE,
- BOOL use_gl = TRUE,
- BOOL ignore_pixel_depth = FALSE,
+ bool fullscreen = false,
+ bool clearBg = false,
+ bool enable_vsync = false,
+ bool use_gl = true,
+ bool ignore_pixel_depth = false,
U32 fsaa_samples = 0,
U32 max_cores = 0,
- U32 max_vram = 0,
F32 max_gl_version = 4.6f);
- static BOOL destroyWindow(LLWindow* window);
- static BOOL isWindowValid(LLWindow *window);
+ static bool destroyWindow(LLWindow* window);
+ static bool isWindowValid(LLWindow *window);
};
//
// helper funcs
//
-extern BOOL gDebugWindowProc;
+extern bool gDebugWindowProc;
// Protocols, like "http" and "https" we support in URLs
extern const S32 gURLProtocolWhitelistCount;
extern const std::string gURLProtocolWhitelist[];
//extern const std::string gURLProtocolWhitelistHandler[];
-void simpleEscapeString ( std::string& stringIn );
-
-#endif // _LL_window_h_
diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp
index a43d281d4c..c160382c17 100644
--- a/indra/llwindow/llwindowcallbacks.cpp
+++ b/indra/llwindow/llwindowcallbacks.cpp
@@ -32,35 +32,35 @@
// LLWindowCallbacks
//
-BOOL LLWindowCallbacks::handleTranslatedKeyDown(const KEY key, const MASK mask, BOOL repeated)
+bool LLWindowCallbacks::handleTranslatedKeyDown(const KEY key, const MASK mask, bool repeated)
{
- return FALSE;
+ return false;
}
-BOOL LLWindowCallbacks::handleTranslatedKeyUp(const KEY key, const MASK mask)
+bool LLWindowCallbacks::handleTranslatedKeyUp(const KEY key, const MASK mask)
{
- return FALSE;
+ return false;
}
-void LLWindowCallbacks::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
+void LLWindowCallbacks::handleScanKey(KEY key, bool key_down, bool key_up, bool key_level)
{
}
-BOOL LLWindowCallbacks::handleUnicodeChar(llwchar uni_char, MASK mask)
+bool LLWindowCallbacks::handleUnicodeChar(llwchar uni_char, MASK mask)
{
- return FALSE;
+ return false;
}
-BOOL LLWindowCallbacks::handleMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask)
+bool LLWindowCallbacks::handleMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask)
{
- return FALSE;
+ return false;
}
-BOOL LLWindowCallbacks::handleMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask)
+bool LLWindowCallbacks::handleMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask)
{
- return FALSE;
+ return false;
}
void LLWindowCallbacks::handleMouseLeave(LLWindow *window)
@@ -68,54 +68,54 @@ void LLWindowCallbacks::handleMouseLeave(LLWindow *window)
return;
}
-BOOL LLWindowCallbacks::handleCloseRequest(LLWindow *window)
+bool LLWindowCallbacks::handleCloseRequest(LLWindow *window)
{
//allow the window to close
- return TRUE;
+ return true;
}
void LLWindowCallbacks::handleQuit(LLWindow *window)
{
}
-BOOL LLWindowCallbacks::handleRightMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask)
+bool LLWindowCallbacks::handleRightMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask)
{
- return FALSE;
+ return false;
}
-BOOL LLWindowCallbacks::handleRightMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask)
+bool LLWindowCallbacks::handleRightMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask)
{
- return FALSE;
+ return false;
}
-BOOL LLWindowCallbacks::handleMiddleMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask)
+bool LLWindowCallbacks::handleMiddleMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask)
{
- return FALSE;
+ return false;
}
-BOOL LLWindowCallbacks::handleMiddleMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask)
+bool LLWindowCallbacks::handleMiddleMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask)
{
- return FALSE;
+ return false;
}
-BOOL LLWindowCallbacks::handleOtherMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask, S32 button)
+bool LLWindowCallbacks::handleOtherMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask, S32 button)
{
- return FALSE;
+ return false;
}
-BOOL LLWindowCallbacks::handleOtherMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask, S32 button)
+bool LLWindowCallbacks::handleOtherMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask, S32 button)
{
- return FALSE;
+ return false;
}
-BOOL LLWindowCallbacks::handleActivate(LLWindow *window, BOOL activated)
+bool LLWindowCallbacks::handleActivate(LLWindow *window, bool activated)
{
- return FALSE;
+ return false;
}
-BOOL LLWindowCallbacks::handleActivateApp(LLWindow *window, BOOL activating)
+bool LLWindowCallbacks::handleActivateApp(LLWindow *window, bool activating)
{
- return FALSE;
+ return false;
}
void LLWindowCallbacks::handleMouseMove(LLWindow *window, const LLCoordGL pos, MASK mask)
@@ -151,15 +151,15 @@ void LLWindowCallbacks::handleMenuSelect(LLWindow *window, const S32 menu_item)
{
}
-BOOL LLWindowCallbacks::handlePaint(LLWindow *window, const S32 x, const S32 y,
+bool LLWindowCallbacks::handlePaint(LLWindow *window, const S32 x, const S32 y,
const S32 width, const S32 height)
{
- return FALSE;
+ return false;
}
-BOOL LLWindowCallbacks::handleDoubleClick(LLWindow *window, const LLCoordGL pos, MASK mask)
+bool LLWindowCallbacks::handleDoubleClick(LLWindow *window, const LLCoordGL pos, MASK mask)
{
- return FALSE;
+ return false;
}
void LLWindowCallbacks::handleWindowBlock(LLWindow *window)
@@ -179,24 +179,24 @@ LLWindowCallbacks::DragNDropResult LLWindowCallbacks::handleDragNDrop(LLWindow *
return LLWindowCallbacks::DND_NONE;
}
-BOOL LLWindowCallbacks::handleTimerEvent(LLWindow *window)
+bool LLWindowCallbacks::handleTimerEvent(LLWindow *window)
{
- return FALSE;
+ return false;
}
-BOOL LLWindowCallbacks::handleDeviceChange(LLWindow *window)
+bool LLWindowCallbacks::handleDeviceChange(LLWindow *window)
{
- return FALSE;
+ return false;
}
-BOOL LLWindowCallbacks::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height)
+bool LLWindowCallbacks::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height)
{
- return FALSE;
+ return false;
}
-BOOL LLWindowCallbacks::handleWindowDidChangeScreen(LLWindow *window)
+bool LLWindowCallbacks::handleWindowDidChangeScreen(LLWindow *window)
{
- return FALSE;
+ return false;
}
void LLWindowCallbacks::handlePingWatchdog(LLWindow *window, const char * msg)
diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h
index d5681400a1..63b585231f 100644
--- a/indra/llwindow/llwindowcallbacks.h
+++ b/indra/llwindow/llwindowcallbacks.h
@@ -33,26 +33,26 @@ class LLWindowCallbacks
{
public:
virtual ~LLWindowCallbacks() {}
- virtual BOOL handleTranslatedKeyDown(KEY key, MASK mask, BOOL repeated);
- virtual BOOL handleTranslatedKeyUp(KEY key, MASK mask);
- virtual void handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level);
- virtual BOOL handleUnicodeChar(llwchar uni_char, MASK mask);
+ virtual bool handleTranslatedKeyDown(KEY key, MASK mask, bool repeated);
+ virtual bool handleTranslatedKeyUp(KEY key, MASK mask);
+ virtual void handleScanKey(KEY key, bool key_down, bool key_up, bool key_level);
+ virtual bool handleUnicodeChar(llwchar uni_char, MASK mask);
- virtual BOOL handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
- virtual BOOL handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
+ virtual bool handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
+ virtual bool handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
virtual void handleMouseLeave(LLWindow *window);
- // return TRUE to allow window to close, which will then cause handleQuit to be called
- virtual BOOL handleCloseRequest(LLWindow *window);
+ // return true to allow window to close, which will then cause handleQuit to be called
+ virtual bool handleCloseRequest(LLWindow *window);
// window is about to be destroyed, clean up your business
virtual void handleQuit(LLWindow *window);
- virtual BOOL handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
- virtual BOOL handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
- virtual BOOL handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
- virtual BOOL handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
- virtual BOOL handleOtherMouseDown(LLWindow *window, LLCoordGL pos, MASK mask, S32 button);
- virtual BOOL handleOtherMouseUp(LLWindow *window, LLCoordGL pos, MASK mask, S32 button);
- virtual BOOL handleActivate(LLWindow *window, BOOL activated);
- virtual BOOL handleActivateApp(LLWindow *window, BOOL activating);
+ virtual bool handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
+ virtual bool handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
+ virtual bool handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
+ virtual bool handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
+ virtual bool handleOtherMouseDown(LLWindow *window, LLCoordGL pos, MASK mask, S32 button);
+ virtual bool handleOtherMouseUp(LLWindow *window, LLCoordGL pos, MASK mask, S32 button);
+ virtual bool handleActivate(LLWindow *window, bool activated);
+ virtual bool handleActivateApp(LLWindow *window, bool activating);
virtual void handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask);
virtual void handleMouseDragged(LLWindow *window, LLCoordGL pos, MASK mask);
virtual void handleScrollWheel(LLWindow *window, S32 clicks);
@@ -61,15 +61,15 @@ public:
virtual void handleFocus(LLWindow *window);
virtual void handleFocusLost(LLWindow *window);
virtual void handleMenuSelect(LLWindow *window, S32 menu_item);
- virtual BOOL handlePaint(LLWindow *window, S32 x, S32 y, S32 width, S32 height);
- virtual BOOL handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK mask); // double-click of left mouse button
+ virtual bool handlePaint(LLWindow *window, S32 x, S32 y, S32 width, S32 height);
+ virtual bool handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK mask); // double-click of left mouse button
virtual void handleWindowBlock(LLWindow *window); // window is taking over CPU for a while
virtual void handleWindowUnblock(LLWindow *window); // window coming back after taking over CPU for a while
virtual void handleDataCopy(LLWindow *window, S32 data_type, void *data);
- virtual BOOL handleTimerEvent(LLWindow *window);
- virtual BOOL handleDeviceChange(LLWindow *window);
- virtual BOOL handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height);
- virtual BOOL handleWindowDidChangeScreen(LLWindow *window);
+ virtual bool handleTimerEvent(LLWindow *window);
+ virtual bool handleDeviceChange(LLWindow *window);
+ virtual bool handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height);
+ virtual bool handleWindowDidChangeScreen(LLWindow *window);
enum DragNDropAction {
DNDA_START_TRACKING = 0,// Start tracking an incoming drag
diff --git a/indra/llwindow/llwindowheadless.cpp b/indra/llwindow/llwindowheadless.cpp
index bbeb710445..55e5cfd51e 100644
--- a/indra/llwindow/llwindowheadless.cpp
+++ b/indra/llwindow/llwindowheadless.cpp
@@ -34,8 +34,8 @@
// LLWindowHeadless
//
LLWindowHeadless::LLWindowHeadless(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
- U32 flags, BOOL fullscreen, BOOL clear_background,
- BOOL enable_vsync, BOOL use_gl, BOOL ignore_pixel_depth)
+ U32 flags, bool fullscreen, bool clear_background,
+ bool enable_vsync, bool use_gl, bool ignore_pixel_depth)
: LLWindow(callbacks, fullscreen, flags)
{
// Initialize a headless keyboard.
diff --git a/indra/llwindow/llwindowheadless.h b/indra/llwindow/llwindowheadless.h
index af2cdb63fa..96654b8838 100644
--- a/indra/llwindow/llwindowheadless.h
+++ b/indra/llwindow/llwindowheadless.h
@@ -32,86 +32,77 @@
class LLWindowHeadless : public LLWindow
{
public:
- /*virtual*/ void show() override {}
- /*virtual*/ void hide() override {}
- /*virtual*/ void close() override {}
- /*virtual*/ BOOL getVisible() override {return FALSE;}
- /*virtual*/ BOOL getMinimized() override {return FALSE;}
- /*virtual*/ BOOL getMaximized() override {return FALSE;}
- /*virtual*/ BOOL maximize() override {return FALSE;}
- /*virtual*/ void minimize() override {}
- /*virtual*/ void restore() override {}
- // TODO: LLWindow::getFullscreen() is (intentionally?) NOT virtual.
- // Apparently the coder of LLWindowHeadless didn't realize that. Is it a
- // mistake to shadow the base-class method with an LLWindowHeadless
- // override when called on the subclass, yet call the base-class method
- // when indirecting through a polymorphic pointer or reference?
- BOOL getFullscreen() {return FALSE;}
- /*virtual*/ BOOL getPosition(LLCoordScreen *position) override {return FALSE;}
- /*virtual*/ BOOL getSize(LLCoordScreen *size) override {return FALSE;}
- /*virtual*/ BOOL getSize(LLCoordWindow *size) override {return FALSE;}
- /*virtual*/ BOOL setPosition(LLCoordScreen position) override {return FALSE;}
- /*virtual*/ BOOL setSizeImpl(LLCoordScreen size) override {return FALSE;}
- /*virtual*/ BOOL setSizeImpl(LLCoordWindow size) override {return FALSE;}
- /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL) override {return FALSE;}
+ void show() override {}
+ void hide() override {}
+ void close() override {}
+ bool getVisible() const override {return false;}
+ bool getMinimized() const override {return false;}
+ bool getMaximized() const override {return false;}
+ bool maximize() override {return false;}
+ void minimize() override {}
+ void restore() override {}
+ bool getFullscreen() const override {return false;};
+ bool getPosition(LLCoordScreen *position) const override {return false;}
+ bool getSize(LLCoordScreen *size) const override {return false;}
+ bool getSize(LLCoordWindow *size) const override {return false;}
+ bool setPosition(LLCoordScreen position) override {return false;}
+ bool setSizeImpl(LLCoordScreen size) override {return false;}
+ bool setSizeImpl(LLCoordWindow size) override {return false;}
+ bool switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp = NULL) override {return false;}
void* createSharedContext() override { return nullptr; }
void makeContextCurrent(void*) override {}
void destroySharedContext(void*) override {}
- /*virtual*/ void toggleVSync(bool enable_vsync) override { }
- /*virtual*/ BOOL setCursorPosition(LLCoordWindow position) override {return FALSE;}
- /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position) override {return FALSE;}
+ void toggleVSync(bool enable_vsync) override { }
+ bool setCursorPosition(LLCoordWindow position) override {return false;}
+ bool getCursorPosition(LLCoordWindow *position) override {return false;}
#if LL_WINDOWS
- /*virtual*/ BOOL getCursorDelta(LLCoordCommon* delta) override { return FALSE; }
+ bool getCursorDelta(LLCoordCommon* delta) const override { return false; }
#endif
- /*virtual*/ void showCursor() override {}
- /*virtual*/ void hideCursor() override {}
- /*virtual*/ void showCursorFromMouseMove() override {}
- /*virtual*/ void hideCursorUntilMouseMove() override {}
- /*virtual*/ BOOL isCursorHidden() override {return FALSE;}
- /*virtual*/ void updateCursor() override {}
- //virtual ECursorType getCursor() override { return mCurrentCursor; }
- /*virtual*/ void captureMouse() override {}
- /*virtual*/ void releaseMouse() override {}
- /*virtual*/ void setMouseClipping( BOOL b ) override {}
- /*virtual*/ BOOL isClipboardTextAvailable() override {return FALSE; }
- /*virtual*/ BOOL pasteTextFromClipboard(LLWString &dst) override {return FALSE; }
- /*virtual*/ BOOL copyTextToClipboard(const LLWString &src) override {return FALSE; }
- /*virtual*/ void flashIcon(F32 seconds) override {}
- /*virtual*/ F32 getGamma() override {return 1.0f; }
- /*virtual*/ BOOL setGamma(const F32 gamma) override {return FALSE; } // Set the gamma
- /*virtual*/ void setFSAASamples(const U32 fsaa_samples) override { }
- /*virtual*/ U32 getFSAASamples() override { return 0; }
- /*virtual*/ BOOL restoreGamma() override {return FALSE; } // Restore original gamma table (before updating gamma)
- //virtual ESwapMethod getSwapMethod() override { return mSwapMethod; }
- /*virtual*/ void gatherInput() override {}
- /*virtual*/ void delayInputProcessing() override {}
- /*virtual*/ void swapBuffers() override;
+ void showCursor() override {}
+ void hideCursor() override {}
+ void showCursorFromMouseMove() override {}
+ void hideCursorUntilMouseMove() override {}
+ bool isCursorHidden() override {return false;}
+ void updateCursor() override {}
+ 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() const override {return 1.0f; }
+ bool setGamma(const F32 gamma) override {return false; } // Set the gamma
+ void setFSAASamples(const U32 fsaa_samples) override { }
+ U32 getFSAASamples() const override { return 0; }
+ bool restoreGamma() override {return false; } // Restore original gamma table (before updating gamma)
+ void gatherInput(bool app_has_focus) override {}
+ void delayInputProcessing() override {}
+ void swapBuffers() override;
// handy coordinate space conversion routines
- /*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to) override { return FALSE; }
- /*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordScreen *to) override { return FALSE; }
- /*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordGL *to) override { return FALSE; }
- /*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordWindow *to) override { return FALSE; }
- /*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordGL *to) override { return FALSE; }
- /*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordScreen *to) override { return FALSE; }
+ bool convertCoords(LLCoordScreen from, LLCoordWindow *to) const override { return false; }
+ bool convertCoords(LLCoordWindow from, LLCoordScreen *to) const override { return false; }
+ bool convertCoords(LLCoordWindow from, LLCoordGL *to) const override { return false; }
+ bool convertCoords(LLCoordGL from, LLCoordWindow *to) const override { return false; }
+ bool convertCoords(LLCoordScreen from, LLCoordGL *to) const override { return false; }
+ bool convertCoords(LLCoordGL from, LLCoordScreen *to) const override { return false; }
- /*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) override { return NULL; }
- /*virtual*/ F32 getNativeAspectRatio() override { return 1.0f; }
- /*virtual*/ F32 getPixelAspectRatio() override { return 1.0f; }
- /*virtual*/ void setNativeAspectRatio(F32 ratio) override {}
+ 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 {}
- U32 getAvailableVRAMMegabytes() override { return 4096; }
-
- /*virtual*/ void *getPlatformWindow() override { return 0; }
- /*virtual*/ void bringToFront() override {}
+ void *getPlatformWindow() override { return 0; }
+ void bringToFront() override {}
LLWindowHeadless(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name,
S32 x, S32 y,
S32 width, S32 height,
- U32 flags, BOOL fullscreen, BOOL clear_background,
- BOOL enable_vsync, BOOL use_gl, BOOL ignore_pixel_depth);
+ U32 flags, bool fullscreen, bool clear_background,
+ bool enable_vsync, bool use_gl, bool ignore_pixel_depth);
virtual ~LLWindowHeadless();
private:
diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h
index 31dc83493e..620bbc8876 100644
--- a/indra/llwindow/llwindowmacosx-objc.h
+++ b/indra/llwindow/llwindowmacosx-objc.h
@@ -30,6 +30,7 @@
#include <map>
#include <vector>
+#include <deque>
//fir CGSize
#include <CoreGraphics/CGGeometry.h>
@@ -37,7 +38,7 @@
typedef std::vector<std::pair<int, bool> > segment_t;
typedef std::vector<int> segment_lengths;
-typedef std::vector<int> segment_standouts;
+typedef std::deque<bool> segment_standouts;
struct attributedStringInfo {
segment_lengths seg_lengths;
@@ -177,6 +178,8 @@ void setMarkedText(unsigned short *text, unsigned int *selectedRange, unsigned i
void getPreeditLocation(float *location, unsigned int length);
void allowDirectMarkedTextInput(bool allow, GLViewRef glView);
+void openFolderWithFinder(const char *folder_path);
+
NSWindowRef getMainAppWindow();
GLViewRef getGLView();
diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm
index 2e75d309ea..01feac7885 100644
--- a/indra/llwindow/llwindowmacosx-objc.mm
+++ b/indra/llwindow/llwindowmacosx-objc.mm
@@ -463,6 +463,13 @@ long showAlert(std::string text, std::string title, int type)
return ret;
}
+void openFolderWithFinder(const char *folder_path)
+{
+ @autoreleasepool {
+ NSString *folderPathString = [NSString stringWithUTF8String:folder_path];
+ [[NSWorkspace sharedWorkspace] openFile:folderPathString withApplication:@"Finder"];
+ }
+}
/*
GLViewRef getGLView()
{
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index 453905b19b..1883c6c9c1 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -28,6 +28,7 @@
#include "llwindowmacosx.h"
+#include "llgamecontrol.h"
#include "llkeyboardmacosx.h"
#include "llwindowcallbacks.h"
#include "llpreeditor.h"
@@ -50,8 +51,8 @@
#include <IOKit/hid/IOHIDLib.h>
#include <IOKit/usb/IOUSBLib.h>
-extern BOOL gDebugWindowProc;
-BOOL gHiDPISupport = TRUE;
+extern bool gDebugWindowProc;
+bool gHiDPISupport = true;
const S32 BITS_PER_PIXEL = 32;
const S32 MAX_NUM_RESOLUTIONS = 32;
@@ -66,11 +67,11 @@ namespace
// LLWindowMacOSX
//
-BOOL LLWindowMacOSX::sUseMultGL = FALSE;
+bool LLWindowMacOSX::sUseMultGL = false;
// Cross-platform bits:
-BOOL check_for_card(const char* RENDERER, const char* bad_card)
+bool check_for_card(const char* RENDERER, const char* bad_card)
{
if (!strnicmp(RENDERER, bad_card, strlen(bad_card)))
{
@@ -91,15 +92,15 @@ BOOL check_for_card(const char* RENDERER, const char* bad_card)
S32 button = OSMessageBox(buffer.c_str(), "Unsupported video card", OSMB_YESNO);
if (OSBTN_YES == button)
{
- return FALSE;
+ return false;
}
else
{
- return TRUE;
+ return true;
}
}
- return FALSE;
+ return false;
}
// Switch to determine whether we capture all displays, or just the main one.
@@ -119,9 +120,9 @@ static LLWindowMacOSX *gWindowImplementation = NULL;
LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, S32 x, S32 y, S32 width,
S32 height, U32 flags,
- BOOL fullscreen, BOOL clearBg,
- BOOL enable_vsync, BOOL use_gl,
- BOOL ignore_pixel_depth,
+ bool fullscreen, bool clearBg,
+ bool enable_vsync, bool use_gl,
+ bool ignore_pixel_depth,
U32 fsaa_samples)
: LLWindow(NULL, fullscreen, flags)
{
@@ -143,21 +144,21 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
mContext = NULL;
mPixelFormat = NULL;
mDisplay = CGMainDisplayID();
- mSimulatedRightClick = FALSE;
+ mSimulatedRightClick = false;
mLastModifiers = 0;
- mHandsOffEvents = FALSE;
- mCursorDecoupled = FALSE;
+ mHandsOffEvents = false;
+ mCursorDecoupled = false;
mCursorLastEventDeltaX = 0;
mCursorLastEventDeltaY = 0;
- mCursorIgnoreNextDelta = FALSE;
- mNeedsResize = FALSE;
+ mCursorIgnoreNextDelta = false;
+ mNeedsResize = false;
mOverrideAspectRatio = 0.f;
- mMaximized = FALSE;
- mMinimized = FALSE;
- mLanguageTextInputAllowed = FALSE;
+ mMaximized = false;
+ mMinimized = false;
+ mLanguageTextInputAllowed = false;
mPreeditor = NULL;
mFSAASamples = fsaa_samples;
- mForceRebuild = FALSE;
+ mForceRebuild = false;
// Get the original aspect ratio of the main device.
mOriginalAspectRatio = (double)CGDisplayPixelsWide(mDisplay) / (double)CGDisplayPixelsHigh(mDisplay);
@@ -197,7 +198,7 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
initCursors();
setCursor( UI_CURSOR_ARROW );
- allowLanguageTextInput(NULL, FALSE);
+ allowLanguageTextInput(NULL, false);
}
mCallbacks = callbacks;
@@ -221,14 +222,14 @@ bool callKeyDown(NSKeyEventRef event, unsigned short key, unsigned int mask, wch
{
//if (mask!=MASK_NONE)
{
- if((key == gKeyboard->inverseTranslateKey('Z')) && (character == 'y'))
- {
- key = gKeyboard->inverseTranslateKey('Y');
- }
- else if ((key == gKeyboard->inverseTranslateKey('Y')) && (character == 'z'))
- {
- key = gKeyboard->inverseTranslateKey('Z');
- }
+ if((key == gKeyboard->inverseTranslateKey('Z')) && (character == 'y'))
+ {
+ key = gKeyboard->inverseTranslateKey('Y');
+ }
+ else if ((key == gKeyboard->inverseTranslateKey('Y')) && (character == 'z'))
+ {
+ key = gKeyboard->inverseTranslateKey('Z');
+ }
}
mRawKeyEvent = event;
@@ -289,7 +290,7 @@ void callRightMouseDown(float *pos, MASK mask)
LLCoordGL outCoords;
outCoords.mX = ll_round(pos[0]);
outCoords.mY = ll_round(pos[1]);
- gWindowImplementation->getCallbacks()->handleRightMouseDown(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
+ gWindowImplementation->getCallbacks()->handleRightMouseDown(gWindowImplementation, outCoords, gKeyboard->currentMask(true));
}
void callRightMouseUp(float *pos, MASK mask)
@@ -302,7 +303,7 @@ void callRightMouseUp(float *pos, MASK mask)
LLCoordGL outCoords;
outCoords.mX = ll_round(pos[0]);
outCoords.mY = ll_round(pos[1]);
- gWindowImplementation->getCallbacks()->handleRightMouseUp(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
+ gWindowImplementation->getCallbacks()->handleRightMouseUp(gWindowImplementation, outCoords, gKeyboard->currentMask(true));
}
void callLeftMouseDown(float *pos, MASK mask)
@@ -315,7 +316,7 @@ void callLeftMouseDown(float *pos, MASK mask)
LLCoordGL outCoords;
outCoords.mX = ll_round(pos[0]);
outCoords.mY = ll_round(pos[1]);
- gWindowImplementation->getCallbacks()->handleMouseDown(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
+ gWindowImplementation->getCallbacks()->handleMouseDown(gWindowImplementation, outCoords, gKeyboard->currentMask(true));
}
void callLeftMouseUp(float *pos, MASK mask)
@@ -328,7 +329,7 @@ void callLeftMouseUp(float *pos, MASK mask)
LLCoordGL outCoords;
outCoords.mX = ll_round(pos[0]);
outCoords.mY = ll_round(pos[1]);
- gWindowImplementation->getCallbacks()->handleMouseUp(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
+ gWindowImplementation->getCallbacks()->handleMouseUp(gWindowImplementation, outCoords, gKeyboard->currentMask(true));
}
@@ -342,7 +343,7 @@ void callDoubleClick(float *pos, MASK mask)
LLCoordGL outCoords;
outCoords.mX = ll_round(pos[0]);
outCoords.mY = ll_round(pos[1]);
- gWindowImplementation->getCallbacks()->handleDoubleClick(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
+ gWindowImplementation->getCallbacks()->handleDoubleClick(gWindowImplementation, outCoords, gKeyboard->currentMask(true));
}
void callResize(unsigned int width, unsigned int height)
@@ -362,7 +363,7 @@ void callMouseMoved(float *pos, MASK mask)
gWindowImplementation->getMouseDeltas(deltas);
outCoords.mX += deltas[0];
outCoords.mY += deltas[1];
- gWindowImplementation->getCallbacks()->handleMouseMove(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
+ gWindowImplementation->getCallbacks()->handleMouseMove(gWindowImplementation, outCoords, gKeyboard->currentMask(true));
//gWindowImplementation->getCallbacks()->handleScrollWheel(gWindowImplementation, 0);
}
@@ -375,7 +376,7 @@ void callMouseDragged(float *pos, MASK mask)
gWindowImplementation->getMouseDeltas(deltas);
outCoords.mX += deltas[0];
outCoords.mY += deltas[1];
- gWindowImplementation->getCallbacks()->handleMouseDragged(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
+ gWindowImplementation->getCallbacks()->handleMouseDragged(gWindowImplementation, outCoords, gKeyboard->currentMask(true));
}
void callScrollMoved(float deltaX, float deltaY)
@@ -617,7 +618,7 @@ void LLWindowMacOSX::updateMouseDeltas(float* deltas)
{
mCursorLastEventDeltaX = 0;
mCursorLastEventDeltaY = 0;
- mCursorIgnoreNextDelta = FALSE;
+ mCursorIgnoreNextDelta = false;
}
} else {
mCursorLastEventDeltaX = 0;
@@ -625,13 +626,13 @@ void LLWindowMacOSX::updateMouseDeltas(float* deltas)
}
}
-void LLWindowMacOSX::getMouseDeltas(float* delta)
+void LLWindowMacOSX::getMouseDeltas(float* delta) const
{
delta[0] = mCursorLastEventDeltaX;
delta[1] = mCursorLastEventDeltaY;
}
-BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL enable_vsync)
+bool LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits, bool fullscreen, bool enable_vsync)
{
mFullscreen = fullscreen;
@@ -690,7 +691,7 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
if (err != kCGLNoError)
{
setupFailure("Can't activate GL rendering context", "Error", OSMB_OK);
- return FALSE;
+ return false;
}
}
@@ -723,15 +724,15 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
}
makeFirstResponder(mWindow, mGLView);
- return TRUE;
+ return true;
}
// We only support OS X 10.7's fullscreen app mode which is literally a full screen window that fills a virtual desktop.
// This makes this method obsolete.
-BOOL LLWindowMacOSX::switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp)
+bool LLWindowMacOSX::switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp)
{
- return FALSE;
+ return false;
}
void LLWindowMacOSX::destroyContext()
@@ -801,13 +802,13 @@ void LLWindowMacOSX::show()
void LLWindowMacOSX::hide()
{
- setMouseClipping(FALSE);
+ setMouseClipping(false);
}
//virtual
void LLWindowMacOSX::minimize()
{
- setMouseClipping(FALSE);
+ setMouseClipping(false);
showCursor();
}
@@ -829,48 +830,48 @@ void LLWindowMacOSX::close()
// }
// Make sure cursor is visible and we haven't mangled the clipping state.
- setMouseClipping(FALSE);
+ setMouseClipping(false);
showCursor();
destroyContext();
}
-BOOL LLWindowMacOSX::isValid()
+bool LLWindowMacOSX::isValid()
{
if(mFullscreen)
{
- return(TRUE);
+ return(true);
}
return (mWindow != NULL);
}
-BOOL LLWindowMacOSX::getVisible()
+bool LLWindowMacOSX::getVisible() const
{
- BOOL result = FALSE;
+ bool result = false;
if(mFullscreen)
{
- result = TRUE;
+ result = true;
}if (mWindow)
{
- result = TRUE;
+ result = true;
}
return(result);
}
-BOOL LLWindowMacOSX::getMinimized()
+bool LLWindowMacOSX::getMinimized() const
{
return mMinimized;
}
-BOOL LLWindowMacOSX::getMaximized()
+bool LLWindowMacOSX::getMaximized() const
{
return mMaximized;
}
-BOOL LLWindowMacOSX::maximize()
+bool LLWindowMacOSX::maximize()
{
if (mWindow && !mMaximized)
{
@@ -879,17 +880,13 @@ BOOL LLWindowMacOSX::maximize()
return mMaximized;
}
-BOOL LLWindowMacOSX::getFullscreen()
-{
- return mFullscreen;
-}
-
-void LLWindowMacOSX::gatherInput()
+void LLWindowMacOSX::gatherInput(bool app_has_focus)
{
updateCursor();
+ LLGameControl::processEvents(app_has_focus);
}
-BOOL LLWindowMacOSX::getPosition(LLCoordScreen *position)
+bool LLWindowMacOSX::getPosition(LLCoordScreen *position) const
{
S32 err = -1;
@@ -916,7 +913,7 @@ BOOL LLWindowMacOSX::getPosition(LLCoordScreen *position)
return (err == noErr);
}
-BOOL LLWindowMacOSX::getSize(LLCoordScreen *size)
+bool LLWindowMacOSX::getSize(LLCoordScreen *size) const
{
S32 err = -1;
@@ -942,7 +939,7 @@ BOOL LLWindowMacOSX::getSize(LLCoordScreen *size)
return (err == noErr);
}
-BOOL LLWindowMacOSX::getSize(LLCoordWindow *size)
+bool LLWindowMacOSX::getSize(LLCoordWindow *size) const
{
S32 err = -1;
@@ -970,7 +967,7 @@ BOOL LLWindowMacOSX::getSize(LLCoordWindow *size)
return (err == noErr);
}
-BOOL LLWindowMacOSX::setPosition(const LLCoordScreen position)
+bool LLWindowMacOSX::setPosition(const LLCoordScreen position)
{
if(mWindow)
{
@@ -978,32 +975,32 @@ BOOL LLWindowMacOSX::setPosition(const LLCoordScreen position)
setWindowPos(mWindow, pos);
}
- return TRUE;
+ return true;
}
-BOOL LLWindowMacOSX::setSizeImpl(const LLCoordScreen size)
+bool LLWindowMacOSX::setSizeImpl(const LLCoordScreen size)
{
if(mWindow)
{
LLCoordWindow to;
convertCoords(size, &to);
setWindowSize(mWindow, to.mX, to.mY);
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
-BOOL LLWindowMacOSX::setSizeImpl(const LLCoordWindow size)
+bool LLWindowMacOSX::setSizeImpl(const LLCoordWindow size)
{
if (mWindow)
{
const int titlePadding = 22;
setWindowSize(mWindow, size.mX, size.mY + titlePadding);
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
void LLWindowMacOSX::swapBuffers()
@@ -1016,7 +1013,7 @@ void LLWindowMacOSX::restoreGLContext()
CGLSetCurrentContext(mContext);
}
-F32 LLWindowMacOSX::getGamma()
+F32 LLWindowMacOSX::getGamma() const
{
F32 result = 2.2; // Default to something sane
@@ -1050,7 +1047,7 @@ F32 LLWindowMacOSX::getGamma()
return result;
}
-U32 LLWindowMacOSX::getFSAASamples()
+U32 LLWindowMacOSX::getFSAASamples() const
{
return mFSAASamples;
}
@@ -1058,16 +1055,16 @@ U32 LLWindowMacOSX::getFSAASamples()
void LLWindowMacOSX::setFSAASamples(const U32 samples)
{
mFSAASamples = samples;
- mForceRebuild = TRUE;
+ mForceRebuild = true;
}
-BOOL LLWindowMacOSX::restoreGamma()
+bool LLWindowMacOSX::restoreGamma()
{
CGDisplayRestoreColorSyncSettings();
return true;
}
-BOOL LLWindowMacOSX::setGamma(const F32 gamma)
+bool LLWindowMacOSX::setGamma(const F32 gamma)
{
CGGammaValue redMin;
CGGammaValue redMax;
@@ -1115,7 +1112,7 @@ BOOL LLWindowMacOSX::setGamma(const F32 gamma)
return true;
}
-BOOL LLWindowMacOSX::isCursorHidden()
+bool LLWindowMacOSX::isCursorHidden()
{
return mCursorHidden;
}
@@ -1123,31 +1120,31 @@ BOOL LLWindowMacOSX::isCursorHidden()
// Constrains the mouse to the window.
-void LLWindowMacOSX::setMouseClipping( BOOL b )
+void LLWindowMacOSX::setMouseClipping( bool b )
{
// Just stash the requested state. We'll simulate this when the cursor is hidden by decoupling.
mIsMouseClipping = b;
if(b)
{
- // LL_INFOS() << "setMouseClipping(TRUE)" << LL_ENDL;
+ // LL_INFOS() << "setMouseClipping(true)" << LL_ENDL;
}
else
{
- // LL_INFOS() << "setMouseClipping(FALSE)" << LL_ENDL;
+ // LL_INFOS() << "setMouseClipping(false)" << LL_ENDL;
}
adjustCursorDecouple();
}
-BOOL LLWindowMacOSX::setCursorPosition(const LLCoordWindow position)
+bool LLWindowMacOSX::setCursorPosition(const LLCoordWindow position)
{
- BOOL result = FALSE;
+ bool result = false;
LLCoordScreen screen_pos;
if (!convertCoords(position, &screen_pos))
{
- return FALSE;
+ return false;
}
CGPoint newPosition;
@@ -1160,7 +1157,7 @@ BOOL LLWindowMacOSX::setCursorPosition(const LLCoordWindow position)
CGSetLocalEventsSuppressionInterval(0.0);
if(CGWarpMouseCursorPosition(newPosition) == noErr)
{
- result = TRUE;
+ result = true;
}
// Under certain circumstances, this will trigger us to decouple the cursor.
@@ -1177,13 +1174,13 @@ BOOL LLWindowMacOSX::setCursorPosition(const LLCoordWindow position)
return result;
}
-BOOL LLWindowMacOSX::getCursorPosition(LLCoordWindow *position)
+bool LLWindowMacOSX::getCursorPosition(LLCoordWindow *position)
{
float cursor_point[2];
LLCoordScreen screen_pos;
if(mWindow == NULL)
- return FALSE;
+ return false;
getCursorPos(mWindow, cursor_point);
@@ -1206,7 +1203,7 @@ BOOL LLWindowMacOSX::getCursorPosition(LLCoordWindow *position)
position->mX = cursor_point[0] * scale;
position->mY = cursor_point[1] * scale;
- return TRUE;
+ return true;
}
void LLWindowMacOSX::adjustCursorDecouple(bool warpingMouse)
@@ -1221,7 +1218,7 @@ void LLWindowMacOSX::adjustCursorDecouple(bool warpingMouse)
// LL_INFOS() << "adjustCursorDecouple: decoupling cursor" << LL_ENDL;
CGAssociateMouseAndMouseCursorPosition(false);
mCursorDecoupled = true;
- mCursorIgnoreNextDelta = TRUE;
+ mCursorIgnoreNextDelta = true;
}
}
}
@@ -1259,20 +1256,10 @@ F32 LLWindowMacOSX::getNativeAspectRatio()
F32 LLWindowMacOSX::getPixelAspectRatio()
{
- //OS X always enforces a 1:1 pixel aspect ratio, regardless of video mode
+ //macOS always enforces a 1:1 pixel aspect ratio, regardless of video mode
return 1.f;
}
-U32 LLWindowMacOSX::getAvailableVRAMMegabytes() {
- // MTL (and MoltenVK) has some additional gpu data, such as recommendedMaxWorkingSetSize and currentAllocatedSize.
- // But these are not available for OpenGL and/or our current mimimum OS version.
- // So we will estimate.
- static const U32 mb = 1024*1024;
- // We're asked for total available gpu memory, but we only have allocation info on texture usage. So estimate by doubling that.
- static const U32 total_factor = 2; // estimated total/textures
- return gGLManager.mVRAM - (LLImageGL::getTextureBytesAllocated() * total_factor/mb);
-}
-
//static SInt32 oldWindowLevel;
// MBW -- XXX -- There's got to be a better way than this. Find it, please...
@@ -1291,17 +1278,17 @@ void LLWindowMacOSX::afterDialog()
void LLWindowMacOSX::flashIcon(F32 seconds)
{
- // For consistency with OS X conventions, the number of seconds given is ignored and
+ // For consistency with macOS conventions, the number of seconds given is ignored and
// left up to the OS (which will actually bounce it for one second).
requestUserAttention();
}
-BOOL LLWindowMacOSX::isClipboardTextAvailable()
+bool LLWindowMacOSX::isClipboardTextAvailable()
{
return pasteBoardAvailable();
}
-BOOL LLWindowMacOSX::pasteTextFromClipboard(LLWString &dst)
+bool LLWindowMacOSX::pasteTextFromClipboard(LLWString &dst)
{
unsigned short* pboard_data = copyFromPBoard(); // must free returned data
llutf16string str(pboard_data);
@@ -1316,9 +1303,9 @@ BOOL LLWindowMacOSX::pasteTextFromClipboard(LLWString &dst)
}
}
-BOOL LLWindowMacOSX::copyTextToClipboard(const LLWString &s)
+bool LLWindowMacOSX::copyTextToClipboard(const LLWString &s)
{
- BOOL result = false;
+ bool result = false;
llutf16string utf16str = wstring_to_utf16str(s);
result = copyToPBoard(utf16str.data(), utf16str.length());
@@ -1328,7 +1315,7 @@ BOOL LLWindowMacOSX::copyTextToClipboard(const LLWString &s)
// protected
-BOOL LLWindowMacOSX::resetDisplayResolution()
+bool LLWindowMacOSX::resetDisplayResolution()
{
// This is only called from elsewhere in this class, and it's not used by the Mac implementation.
return true;
@@ -1361,13 +1348,13 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r
if(bits == BITS_PER_PIXEL && width >= 800 && height >= 600)
{
- BOOL resolution_exists = FALSE;
+ bool resolution_exists = false;
for(S32 i = 0; i < mNumSupportedResolutions; i++)
{
if (mSupportedResolutions[i].mWidth == width &&
mSupportedResolutions[i].mHeight == height)
{
- resolution_exists = TRUE;
+ resolution_exists = true;
}
}
if (!resolution_exists)
@@ -1386,21 +1373,21 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r
return mSupportedResolutions;
}
-BOOL LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordWindow *to)
+bool LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordWindow *to) const
{
to->mX = from.mX;
to->mY = from.mY;
- return TRUE;
+ return true;
}
-BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordGL* to)
+bool LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordGL* to) const
{
to->mX = from.mX;
to->mY = from.mY;
- return TRUE;
+ return true;
}
-BOOL LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordWindow* to)
+bool LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordWindow* to) const
{
if(mWindow)
{
@@ -1414,12 +1401,12 @@ BOOL LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordWindow* to)
to->mX = mouse_point[0];
to->mY = mouse_point[1];
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
-BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordScreen *to)
+bool LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordScreen *to) const
{
if(mWindow)
{
@@ -1433,19 +1420,19 @@ BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordScreen *to)
to->mX = mouse_point[0];
to->mY = mouse_point[1];
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
-BOOL LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordGL *to)
+bool LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordGL *to) const
{
LLCoordWindow window_coord;
return(convertCoords(from, &window_coord) && convertCoords(window_coord, to));
}
-BOOL LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordScreen *to)
+bool LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordScreen *to) const
{
LLCoordWindow window_coord;
@@ -1707,8 +1694,8 @@ void LLWindowMacOSX::hideCursor()
if(!mCursorHidden)
{
// LL_INFOS() << "hideCursor: hiding" << LL_ENDL;
- mCursorHidden = TRUE;
- mHideCursorPermanent = TRUE;
+ mCursorHidden = true;
+ mHideCursorPermanent = true;
hideNSCursor();
}
else
@@ -1724,8 +1711,8 @@ void LLWindowMacOSX::showCursor()
if(mCursorHidden || !isCGCursorVisible())
{
// LL_INFOS() << "showCursor: showing" << LL_ENDL;
- mCursorHidden = FALSE;
- mHideCursorPermanent = FALSE;
+ mCursorHidden = false;
+ mHideCursorPermanent = false;
showNSCursor();
}
else
@@ -1749,7 +1736,7 @@ void LLWindowMacOSX::hideCursorUntilMouseMove()
if (!mHideCursorPermanent)
{
hideCursor();
- mHideCursorPermanent = FALSE;
+ mHideCursorPermanent = false;
}
}
@@ -2331,7 +2318,7 @@ bool LLWindowMacOSX::getInputDevices(U32 device_type_filter,
return return_value;
}
-LLSD LLWindowMacOSX::getNativeKeyData()
+LLSD LLWindowMacOSX::getNativeKeyData() const
{
LLSD result = LLSD::emptyMap();
@@ -2350,9 +2337,9 @@ LLSD LLWindowMacOSX::getNativeKeyData()
return result;
}
-BOOL LLWindowMacOSX::dialogColorPicker( F32 *r, F32 *g, F32 *b)
+bool LLWindowMacOSX::dialogColorPicker( F32 *r, F32 *g, F32 *b)
{
- BOOL retval = FALSE;
+ bool retval = false;
OSErr error = noErr;
NColorPickerInfo info;
@@ -2409,12 +2396,12 @@ static long getDictLong (CFDictionaryRef refDict, CFStringRef key)
return int_value; // otherwise return the long value
}
-void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b)
+void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, bool b)
{
if (preeditor != mPreeditor && !b)
{
// This condition may occur by a call to
- // setEnabled(BOOL) against LLTextEditor or LLLineEditor
+ // setEnabled(bool) against LLTextEditor or LLLineEditor
// when the control is not focused.
// We need to silently ignore the case so that
// the language input status of the focused control
@@ -2515,6 +2502,7 @@ void LLWindowMacOSX::interruptLanguageTextInput()
commitCurrentPreedit(mGLView);
}
+// static
std::vector<std::string> LLWindowMacOSX::getDisplaysResolutionList()
{
std::vector<std::string> resolution_list;
@@ -2544,7 +2532,7 @@ std::vector<std::string> LLWindowMacOSX::getDisplaysResolutionList()
return resolution_list;
}
-//static
+// static
std::vector<std::string> LLWindowMacOSX::getDynamicFallbackFontList()
{
// Fonts previously in getFontListSans() have moved to fonts.xml.
@@ -2566,6 +2554,11 @@ F32 LLWindowMacOSX::getSystemUISize()
return gHiDPISupport ? ::getDeviceUnitSize(mGLView) : LLWindow::getSystemUISize();
}
+void LLWindowMacOSX::openFolder(const std::string &path)
+{
+ openFolderWithFinder(path.c_str());
+}
+
#if LL_OS_DRAGDROP_ENABLED
/*
S16 LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow,
diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h
index 5e09e58a99..14a56a038e 100644
--- a/indra/llwindow/llwindowmacosx.h
+++ b/indra/llwindow/llwindowmacosx.h
@@ -47,75 +47,72 @@ public:
void show() override;
void hide() override;
void close() override;
- BOOL getVisible() override;
- BOOL getMinimized() override;
- BOOL getMaximized() override;
- BOOL maximize() override;
+ bool getVisible() const override;
+ bool getMinimized() const override;
+ bool getMaximized() const override;
+ bool maximize() override;
void minimize() override;
void restore() override;
- BOOL getFullscreen();
- BOOL getPosition(LLCoordScreen *position) override;
- BOOL getSize(LLCoordScreen *size) override;
- BOOL getSize(LLCoordWindow *size) override;
- BOOL setPosition(LLCoordScreen position) override;
- BOOL setSizeImpl(LLCoordScreen size) override;
- BOOL setSizeImpl(LLCoordWindow size) override;
- BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL) override;
- BOOL setCursorPosition(LLCoordWindow position) override;
- BOOL getCursorPosition(LLCoordWindow *position) override;
+ bool getPosition(LLCoordScreen *position) const override;
+ bool getSize(LLCoordScreen *size) const override;
+ bool getSize(LLCoordWindow *size) const override;
+ bool setPosition(LLCoordScreen position) override;
+ bool setSizeImpl(LLCoordScreen size) override;
+ bool setSizeImpl(LLCoordWindow size) override;
+ bool switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp = NULL) override;
+ bool setCursorPosition(LLCoordWindow position) override;
+ bool getCursorPosition(LLCoordWindow *position) override;
void showCursor() override;
void hideCursor() override;
void showCursorFromMouseMove() override;
void hideCursorUntilMouseMove() override;
- BOOL isCursorHidden() override;
+ bool isCursorHidden() override;
void updateCursor() override;
ECursorType getCursor() const override;
void captureMouse() override;
void releaseMouse() override;
- void setMouseClipping( BOOL b ) override;
- BOOL isClipboardTextAvailable() override;
- BOOL pasteTextFromClipboard(LLWString &dst) override;
- BOOL copyTextToClipboard(const LLWString & src) override;
+ void setMouseClipping( bool b ) override;
+ bool isClipboardTextAvailable() override;
+ bool pasteTextFromClipboard(LLWString &dst) override;
+ bool copyTextToClipboard(const LLWString & src) override;
void flashIcon(F32 seconds) override;
- F32 getGamma() override;
- BOOL setGamma(const F32 gamma) override; // Set the gamma
- U32 getFSAASamples() override;
+ F32 getGamma() const override;
+ bool setGamma(const F32 gamma) override; // Set the gamma
+ U32 getFSAASamples() const override;
void setFSAASamples(const U32 fsaa_samples) override;
- BOOL restoreGamma() override; // Restore original gamma table (before updating gamma)
- ESwapMethod getSwapMethod() override { return mSwapMethod; }
- void gatherInput() override;
+ bool restoreGamma() override; // Restore original gamma table (before updating gamma)
+ void gatherInput(bool app_has_focus) override;
void delayInputProcessing() override {};
void swapBuffers() 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;
+ bool convertCoords(LLCoordScreen from, LLCoordWindow *to) const override;
+ bool convertCoords(LLCoordWindow from, LLCoordScreen *to) const override;
+ bool convertCoords(LLCoordWindow from, LLCoordGL *to) const override;
+ bool convertCoords(LLCoordGL from, LLCoordWindow *to) const override;
+ bool convertCoords(LLCoordScreen from, LLCoordGL *to) const override;
+ bool convertCoords(LLCoordGL from, LLCoordScreen *to) const override;
LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) override;
F32 getNativeAspectRatio() override;
F32 getPixelAspectRatio() override;
void setNativeAspectRatio(F32 ratio) override { mOverrideAspectRatio = ratio; }
- // query VRAM usage
- /*virtual*/ U32 getAvailableVRAMMegabytes() override;
-
void beforeDialog() override;
void afterDialog() override;
- BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b) override;
+ bool dialogColorPicker(F32 *r, F32 *g, F32 *b) override;
void *getPlatformWindow() override;
void bringToFront() override {};
- void allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) override;
+ void allowLanguageTextInput(LLPreeditor *preeditor, bool b) override;
void interruptLanguageTextInput() override;
void spawnWebBrowser(const std::string& escaped_url, bool async) override;
F32 getSystemUISize() override;
+ void openFolder(const std::string &path) override;
+
bool getInputDevices(U32 device_type_filter,
std::function<bool(std::string&, LLSD&, void*)> osx_callback,
void* win_callback,
@@ -126,14 +123,14 @@ public:
static std::vector<std::string> getDynamicFallbackFontList();
// Provide native key event data
- LLSD getNativeKeyData() override;
+ LLSD getNativeKeyData() const override;
void* getWindow() { return mWindow; }
LLWindowCallbacks* getCallbacks() { return mCallbacks; }
LLPreeditor* getPreeditor() { return mPreeditor; }
void updateMouseDeltas(float* deltas);
- void getMouseDeltas(float* delta);
+ void getMouseDeltas(float* delta) const;
void handleDragNDrop(std::string url, LLWindowCallbacks::DragNDropAction action);
@@ -153,26 +150,26 @@ public:
protected:
LLWindowMacOSX(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,
- BOOL fullscreen, BOOL clearBg, BOOL enable_vsync, BOOL use_gl,
- BOOL ignore_pixel_depth,
+ bool fullscreen, bool clearBg, bool enable_vsync, bool use_gl,
+ bool ignore_pixel_depth,
U32 fsaa_samples);
~LLWindowMacOSX();
void initCursors();
- BOOL isValid() override;
+ bool isValid() override;
void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size);
// Changes display resolution. Returns true if successful
- BOOL setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
+ bool setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
// Go back to last fullscreen display resolution.
- BOOL setFullscreenResolution();
+ bool setFullscreenResolution();
// Restore the display resolution to its value before we ran the app.
- BOOL resetDisplayResolution();
+ bool resetDisplayResolution();
- BOOL shouldPostQuit() { return mPostQuit; }
+ bool shouldPostQuit() { return mPostQuit; }
//Satisfy MAINT-3135 and MAINT-3288 with a flag.
/*virtual */ void setOldResize(bool oldresize) override {setResizeMode(oldresize, mGLView); }
@@ -186,7 +183,7 @@ 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);
+ bool createContext(int x, int y, int width, int height, int bits, bool fullscreen, bool enable_vsync);
void destroyContext();
void setupFailure(const std::string& text, const std::string& caption, U32 type);
void adjustCursorDecouple(bool warpingMouse = false);
@@ -214,30 +211,30 @@ protected:
LLRect mOldMouseClip; // Screen rect to which the mouse cursor was globally constrained before we changed it in clipMouse()
std::string mWindowTitle;
double mOriginalAspectRatio;
- BOOL mSimulatedRightClick;
+ bool mSimulatedRightClick;
U32 mLastModifiers;
- BOOL mHandsOffEvents; // When true, temporarially disable CarbonEvent processing.
+ bool mHandsOffEvents; // When true, temporarially disable CarbonEvent processing.
// Used to allow event processing when putting up dialogs in fullscreen mode.
- BOOL mCursorDecoupled;
+ bool mCursorDecoupled;
S32 mCursorLastEventDeltaX;
S32 mCursorLastEventDeltaY;
- BOOL mCursorIgnoreNextDelta;
- BOOL mNeedsResize; // Constructor figured out the window is too big, it needs a resize.
+ bool mCursorIgnoreNextDelta;
+ bool mNeedsResize; // Constructor figured out the window is too big, it needs a resize.
LLCoordScreen mNeedsResizeSize;
F32 mOverrideAspectRatio;
- BOOL mMaximized;
- BOOL mMinimized;
+ bool mMaximized;
+ bool mMinimized;
U32 mFSAASamples;
- BOOL mForceRebuild;
+ bool mForceRebuild;
S32 mDragOverrideCursor;
// Input method management through Text Service Manager.
- BOOL mLanguageTextInputAllowed;
+ bool mLanguageTextInputAllowed;
LLPreeditor* mPreeditor;
public:
- static BOOL sUseMultGL;
+ static bool sUseMultGL;
friend class LLWindowManager;
diff --git a/indra/llwindow/llwindowmesaheadless.cpp b/indra/llwindow/llwindowmesaheadless.cpp
index 58f8f80d2d..6cbd737ed2 100644
--- a/indra/llwindow/llwindowmesaheadless.cpp
+++ b/indra/llwindow/llwindowmesaheadless.cpp
@@ -40,8 +40,8 @@ U16 *gMesaBuffer = NULL;
//
LLWindowMesaHeadless::LLWindowMesaHeadless(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
- U32 flags, BOOL fullscreen, BOOL clearBg,
- BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth)
+ U32 flags, bool fullscreen, bool clearBg,
+ bool disable_vsync, bool use_gl, bool ignore_pixel_depth)
: LLWindow(callbacks, fullscreen, flags)
{
if (use_gl)
diff --git a/indra/llwindow/llwindowmesaheadless.h b/indra/llwindow/llwindowmesaheadless.h
index 9aa376a6db..0a29ddfa5b 100644
--- a/indra/llwindow/llwindowmesaheadless.h
+++ b/indra/llwindow/llwindowmesaheadless.h
@@ -36,69 +36,69 @@
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() override {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;};
+ void showCursor() override {};
+ void hideCursor() override {};
+ void showCursorFromMouseMove() override {};
+ void hideCursorUntilMouseMove() override {};
+ bool isCursorHidden() override {return false;};
+ void updateCursor() override {};
+ //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; }
+ //ESwapMethod getSwapMethod() override { return mSwapMethod; }
+ void gatherInput(bool app_has_focus) override {};
+ void delayInputProcessing() override {};
+ void swapBuffers() override;
+ void restoreGLContext() override {};
// 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,
- U32 flags, BOOL fullscreen, BOOL clearBg,
- BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth);
+ U32 flags, bool fullscreen, bool clearBg,
+ bool disable_vsync, bool use_gl, bool ignore_pixel_depth);
~LLWindowMesaHeadless();
private:
@@ -112,9 +112,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 df8b2ba5ab..f87a00c34b 100644
--- a/indra/llwindow/llwindowsdl.cpp
+++ b/indra/llwindow/llwindowsdl.cpp
@@ -25,8 +25,6 @@
* $/LicenseInfo$
*/
-#if LL_SDL
-
#include "linden_common.h"
#include "llwindowsdl.h"
@@ -39,13 +37,11 @@
#include "llstring.h"
#include "lldir.h"
#include "llfindlocale.h"
+#include "llgamecontrol.h"
-#if LL_GTK
-extern "C" {
-# include "gtk/gtk.h"
-}
-#include <locale.h>
-#endif // LL_GTK
+#ifdef LL_GLIB
+#include <glib.h>
+#endif
extern "C" {
# include "fontconfig/fontconfig.h"
@@ -54,181 +50,209 @@ extern "C" {
#if LL_LINUX
// not necessarily available on random SDL platforms, so #if LL_LINUX
// for execv(), waitpid(), fork()
-# include <unistd.h>
-# include <sys/types.h>
-# include <sys/wait.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdio.h>
#endif // LL_LINUX
-extern BOOL gDebugWindowProc;
+extern bool gDebugWindowProc;
const S32 MAX_NUM_RESOLUTIONS = 200;
-// static variable for ATI mouse cursor crash work-around:
-static bool ATIbug = false;
-
//
// LLWindowSDL
//
-#if LL_X11
-# include <X11/Xutil.h>
-#endif //LL_X11
+#include <X11/Xutil.h>
// TOFU HACK -- (*exactly* the same hack as LLWindowMacOSX for a similar
// set of reasons): Stash a pointer to the LLWindowSDL object here and
// maintain in the constructor and destructor. This assumes that there will
// be only one object of this class at any time. Currently this is true.
-static LLWindowSDL *gWindowImplementation = NULL;
-
+static LLWindowSDL *gWindowImplementation = nullptr;
void maybe_lock_display(void)
{
- if (gWindowImplementation && gWindowImplementation->Lock_Display) {
+ if (gWindowImplementation && gWindowImplementation->Lock_Display)
gWindowImplementation->Lock_Display();
- }
}
-
void maybe_unlock_display(void)
{
- if (gWindowImplementation && gWindowImplementation->Unlock_Display) {
+ if (gWindowImplementation && gWindowImplementation->Unlock_Display)
gWindowImplementation->Unlock_Display();
- }
}
-#if LL_GTK
-// Lazily initialize and check the runtime GTK version for goodness.
-// static
-bool LLWindowSDL::ll_try_gtk_init(void)
+Window LLWindowSDL::get_SDL_XWindowID(void)
{
- static BOOL done_gtk_diag = FALSE;
- static BOOL gtk_is_good = FALSE;
- static BOOL done_setlocale = FALSE;
- static BOOL tried_gtk_init = FALSE;
+ if (gWindowImplementation)
+ return gWindowImplementation->mX11Data.mXWindowID;
+ return None;
+}
- if (!done_setlocale)
- {
- LL_INFOS() << "Starting GTK Initialization." << LL_ENDL;
- maybe_lock_display();
- gtk_disable_setlocale();
- maybe_unlock_display();
- done_setlocale = TRUE;
- }
+Display* LLWindowSDL::get_SDL_Display(void)
+{
+ if (gWindowImplementation)
+ return gWindowImplementation->mX11Data.mDisplay;
+ return nullptr;
+}
- if (!tried_gtk_init)
- {
- tried_gtk_init = TRUE;
- if (!g_thread_supported ()) g_thread_init (NULL);
- maybe_lock_display();
- gtk_is_good = gtk_init_check(NULL, NULL);
- maybe_unlock_display();
- if (!gtk_is_good)
- LL_WARNS() << "GTK Initialization failed." << LL_ENDL;
- }
+/*
+ * In wayland a window does not have a state of "minimized" or gets messages that it got minimized [1]
+ * There's two ways to approach this challenge:
+ * 1) Ignore it, this would mean even if minimized/not visible the viewer will always fun at full fps
+ * 2) Try to detect something like "minimized", the best way I found so far is to as for frame_done events. Those will
+ * only happen if parts of the viewer are visible. As such it is not the same a "minimized" but rather "this window
+ * is not fully hidden behind another window or minimized". That's (I guess) still better than nothing and running
+ * full tilt even if hidden.
+ *
+ * [1] As of 2024-09, maybe in the future we get nice things
+*/
+#ifdef LL_WAYLAND
+#include <wayland-client-protocol.h>
+#include <dlfcn.h>
- if (gtk_is_good && !done_gtk_diag)
- {
- LL_INFOS() << "GTK Initialized." << LL_ENDL;
- LL_INFOS() << "- Compiled against GTK version "
- << GTK_MAJOR_VERSION << "."
- << GTK_MINOR_VERSION << "."
- << GTK_MICRO_VERSION << LL_ENDL;
- LL_INFOS() << "- Running against GTK version "
- << gtk_major_version << "."
- << gtk_minor_version << "."
- << gtk_micro_version << LL_ENDL;
- maybe_lock_display();
- const gchar* gtk_warning = gtk_check_version(
- GTK_MAJOR_VERSION,
- GTK_MINOR_VERSION,
- GTK_MICRO_VERSION);
- maybe_unlock_display();
- if (gtk_warning)
- {
- LL_WARNS() << "- GTK COMPATIBILITY WARNING: " <<
- gtk_warning << LL_ENDL;
- gtk_is_good = FALSE;
- } else {
- LL_INFOS() << "- GTK version is good." << LL_ENDL;
- }
+bool LLWindowSDL::isWaylandWindowNotDrawing() const
+{
+ if( Wayland != mServerProtocol || mWaylandData.mLastFrameEvent == 0 )
+ return false;
- done_gtk_diag = TRUE;
- }
+ auto currentTime = LLTimer::getTotalTime();
+ if( (currentTime - mWaylandData.mLastFrameEvent) > 250000 )
+ return true;
- return gtk_is_good;
+ return false;
}
-#endif // LL_GTK
+uint32_t (*ll_wl_proxy_get_version)(struct wl_proxy *proxy);
+void (*ll_wl_proxy_destroy)(struct wl_proxy *proxy);
+int (*ll_wl_proxy_add_listener)(struct wl_proxy *proxy, void (**implementation)(void), void *data);
-#if LL_X11
-// static
-Window LLWindowSDL::get_SDL_XWindowID(void)
+wl_interface *ll_wl_callback_interface;
+
+int ll_wl_callback_add_listener(struct wl_callback *wl_callback,
+ const struct wl_callback_listener *listener, void *data)
{
- if (gWindowImplementation) {
- return gWindowImplementation->mSDL_XWindowID;
- }
- return None;
+ return ll_wl_proxy_add_listener((struct wl_proxy *) wl_callback,
+ (void (**)(void)) listener, data);
}
-//static
-Display* LLWindowSDL::get_SDL_Display(void)
+struct wl_proxy* (*ll_wl_proxy_marshal_flags)(struct wl_proxy *proxy, uint32_t opcode,
+ const struct wl_interface *interface,
+ uint32_t version,
+ uint32_t flags, ...);
+
+
+bool loadWaylandClient()
+{
+ auto *pSO = dlopen( "libwayland-client.so", RTLD_NOW);
+ if( !pSO )
+ return false;
+
+
+ ll_wl_callback_interface = (wl_interface*)dlsym(pSO, "wl_callback_interface");
+ *(void**)&ll_wl_proxy_marshal_flags = dlsym(pSO, "wl_proxy_marshal_flags");
+ *(void**)&ll_wl_proxy_get_version = dlsym(pSO, "wl_proxy_get_version");
+ *(void**)&ll_wl_proxy_destroy = dlsym(pSO, "wl_proxy_destroy");
+ *(void**)&ll_wl_proxy_add_listener = dlsym(pSO, "wl_proxy_add_listener");
+
+ return ll_wl_callback_interface != nullptr && ll_wl_proxy_marshal_flags != nullptr &&
+ ll_wl_proxy_get_version != nullptr && ll_wl_proxy_destroy != nullptr &&
+ ll_wl_proxy_add_listener != nullptr;
+}
+
+struct wl_callback* ll_wl_surface_frame(struct wl_surface *wl_surface)
+{
+ auto version = ll_wl_proxy_get_version((struct wl_proxy *) wl_surface);
+
+ auto callback = ll_wl_proxy_marshal_flags((struct wl_proxy *) wl_surface,
+ WL_SURFACE_FRAME, ll_wl_callback_interface, version,
+ 0, nullptr);
+
+ return (struct wl_callback *) callback;
+}
+
+void ll_wl_callback_destroy(struct wl_callback *wl_callback)
+{
+ ll_wl_proxy_destroy((struct wl_proxy *) wl_callback);
+}
+
+void LLWindowSDL::waylandFrameDoneCB(void *data, struct wl_callback *cb, uint32_t time)
{
- if (gWindowImplementation) {
- return gWindowImplementation->mSDL_Display;
+ static uint32_t frame_count {0};
+ static F64SecondsImplicit lastInfo{0};
+
+ ++frame_count;
+
+ ll_wl_callback_destroy(cb);
+ auto pThis = reinterpret_cast<LLWindowSDL*>(data);
+ pThis->mWaylandData.mLastFrameEvent = LLTimer::getTotalTime();
+
+ auto now = LLTimer::getElapsedSeconds();
+ if( lastInfo > 0)
+ {
+ auto diff = now.value() - lastInfo.value();
+ constexpr double FPS_INFO_INTERVAL = 60.f * 5.f;
+ if( diff >= FPS_INFO_INTERVAL)
+ {
+ double fFPS = frame_count;
+ fFPS /= diff;
+ LL_INFOS() << "Wayland: FPS " << fFPS << " fps, " << frame_count << " #frames time " << (diff) << LL_ENDL;
+ frame_count = 0;
+ lastInfo = now;
+ }
}
- return NULL;
+ else
+ lastInfo = now;
+
+ pThis->setupWaylandFrameCallback(); // ask for a new frame
}
-#endif // LL_X11
+void LLWindowSDL::setupWaylandFrameCallback()
+{
+ static wl_callback_listener frame_listener { nullptr };
+ frame_listener.done = &LLWindowSDL::waylandFrameDoneCB;
+
+ auto cb = ll_wl_surface_frame(mWaylandData.mSurface);
+ ll_wl_callback_add_listener(cb, &frame_listener, this);
+}
+#else
+bool LLWindowSDL::isWaylandWindowNotDrawing()
+{
+ return false;
+}
+void LLWindowSDL::setupWaylandFrameCallback()
+{
+ LL_WARNS() << "Viewer is running under Wayland, but was not compiled with full wayland support!" << LL_ENDL;
+}
+#endif
LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
- const std::string& title, S32 x, S32 y, S32 width,
- S32 height, U32 flags,
- BOOL fullscreen, BOOL clearBg,
- BOOL disable_vsync, BOOL use_gl,
- BOOL ignore_pixel_depth, U32 fsaa_samples)
- : LLWindow(callbacks, fullscreen, flags),
- Lock_Display(NULL),
- Unlock_Display(NULL), mGamma(1.0f)
+ const std::string& title, const std::string& name, S32 x, S32 y, S32 width,
+ S32 height, U32 flags,
+ bool fullscreen, bool clearBg,
+ bool enable_vsync, bool use_gl,
+ bool ignore_pixel_depth, U32 fsaa_samples)
+ : LLWindow(callbacks, fullscreen, flags),
+ Lock_Display(nullptr),
+ Unlock_Display(nullptr), mGamma(1.0f)
{
// Initialize the keyboard
gKeyboard = new LLKeyboardSDL();
gKeyboard->setCallbacks(callbacks);
- // Note that we can't set up key-repeat until after SDL has init'd video
-
- // Ignore use_gl for now, only used for drones on PC
- mWindow = NULL;
- mNeedsResize = FALSE;
- mOverrideAspectRatio = 0.f;
- mGrabbyKeyFlags = 0;
- mReallyCapturedCount = 0;
- mHaveInputFocus = -1;
- mIsMinimized = -1;
- mFSAASamples = fsaa_samples;
-
-#if LL_X11
- mSDL_XWindowID = None;
- mSDL_Display = NULL;
-#endif // LL_X11
-
-#if LL_GTK
- // We MUST be the first to initialize GTK so that GTK doesn't get badly
- // initialized with a non-C locale and cause lots of serious random
- // weirdness.
- ll_try_gtk_init();
-#endif // LL_GTK
// Assume 4:3 aspect ratio until we know better
mOriginalAspectRatio = 1024.0 / 768.0;
if (title.empty())
- mWindowTitle = "SDL Window"; // *FIX: (?)
+ mWindowTitle = "Second Life";
else
mWindowTitle = title;
// Create the GL context and set it up for windowed or fullscreen, as appropriate.
- if(createContext(x, y, width, height, 32, fullscreen, disable_vsync))
+ if(createContext(x, y, width, height, 32, fullscreen, enable_vsync))
{
gGLManager.initGL();
@@ -242,13 +266,8 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
// Stash an object pointer for OSMessageBox()
gWindowImplementation = this;
-#if LL_X11
- mFlashing = FALSE;
-#endif // LL_X11
+ mFlashing = false;
- mKeyScanCode = 0;
- mKeyVirtualKey = 0;
- mKeyModifiers = KMOD_NONE;
}
static SDL_Surface *Load_BMP_Resource(const char *basename)
@@ -258,401 +277,195 @@ static SDL_Surface *Load_BMP_Resource(const char *basename)
// Figure out where our BMP is living on the disk
snprintf(path_buffer, PATH_BUFFER_SIZE-1, "%s%sres-sdl%s%s",
- gDirUtilp->getAppRODataDir().c_str(),
- gDirUtilp->getDirDelimiter().c_str(),
- gDirUtilp->getDirDelimiter().c_str(),
- basename);
+ gDirUtilp->getAppRODataDir().c_str(),
+ gDirUtilp->getDirDelimiter().c_str(),
+ gDirUtilp->getDirDelimiter().c_str(),
+ basename);
path_buffer[PATH_BUFFER_SIZE-1] = '\0';
return SDL_LoadBMP(path_buffer);
}
-#if LL_X11
-// This is an XFree86/XOrg-specific hack for detecting the amount of Video RAM
-// on this machine. It works by searching /var/log/var/log/Xorg.?.log or
-// /var/log/XFree86.?.log for a ': (VideoRAM ?|Memory): (%d+) kB' regex, where
-// '?' is the X11 display number derived from $DISPLAY
-static int x11_detect_VRAM_kb_fp(FILE *fp, const char *prefix_str)
-{
- const int line_buf_size = 1000;
- char line_buf[line_buf_size];
- while (fgets(line_buf, line_buf_size, fp))
- {
- //LL_DEBUGS() << "XLOG: " << line_buf << LL_ENDL;
-
- // Why the ad-hoc parser instead of using a regex? Our
- // favourite regex implementation - libboost_regex - is
- // quite a heavy and troublesome dependency for the client, so
- // it seems a shame to introduce it for such a simple task.
- // *FIXME: libboost_regex is a dependency now anyway, so we may
- // as well use it instead of this hand-rolled nonsense.
- const char *part1_template = prefix_str;
- const char part2_template[] = " kB";
- char *part1 = strstr(line_buf, part1_template);
- if (part1) // found start of matching line
- {
- part1 = &part1[strlen(part1_template)]; // -> after
- char *part2 = strstr(part1, part2_template);
- if (part2) // found end of matching line
- {
- // now everything between part1 and part2 is
- // supposed to be numeric, describing the
- // number of kB of Video RAM supported
- int rtn = 0;
- for (; part1 < part2; ++part1)
- {
- if (*part1 < '0' || *part1 > '9')
- {
- // unexpected char, abort parse
- rtn = 0;
- break;
- }
- rtn *= 10;
- rtn += (*part1) - '0';
- }
- if (rtn > 0)
- {
- // got the kB number. return it now.
- return rtn;
- }
- }
- }
- }
- return 0; // 'could not detect'
+void LLWindowSDL::setTitle(const std::string title)
+{
+ SDL_SetWindowTitle( mWindow, title.c_str() );
}
-static int x11_detect_VRAM_kb()
+void LLWindowSDL::tryFindFullscreenSize( int &width, int &height )
{
- std::string x_log_location("/var/log/");
- std::string fname;
- int rtn = 0; // 'could not detect'
- int display_num = 0;
- FILE *fp;
- char *display_env = getenv("DISPLAY"); // e.g. :0 or :0.0 or :1.0 etc
- // parse DISPLAY number so we can go grab the right log file
- if (display_env[0] == ':' &&
- display_env[1] >= '0' && display_env[1] <= '9')
- {
- display_num = display_env[1] - '0';
- }
+ LL_INFOS() << "createContext: setting up fullscreen " << width << "x" << height << LL_ENDL;
- // *TODO: we could be smarter and see which of Xorg/XFree86 has the
- // freshest time-stamp.
-
- // Try Xorg log first
- fname = x_log_location;
- fname += "Xorg.";
- fname += ('0' + display_num);
- fname += ".log";
- fp = fopen(fname.c_str(), "r");
- if (fp)
+ // If the requested width or height is 0, find the best default for the monitor.
+ if(width == 0 || height == 0)
{
- LL_INFOS() << "Looking in " << fname
- << " for VRAM info..." << LL_ENDL;
- rtn = x11_detect_VRAM_kb_fp(fp, ": VideoRAM: ");
- fclose(fp);
- if (0 == rtn)
+ // Scan through the list of modes, looking for one which has:
+ // height between 700 and 800
+ // aspect ratio closest to the user's original mode
+ S32 resolutionCount = 0;
+ LLWindowResolution *resolutionList = getSupportedResolutions(resolutionCount);
+
+ if(resolutionList != nullptr)
{
- fp = fopen(fname.c_str(), "r");
- if (fp)
+ F32 closestAspect = 0;
+ U32 closestHeight = 0;
+ U32 closestWidth = 0;
+
+ LL_INFOS() << "createContext: searching for a display mode, original aspect is " << mOriginalAspectRatio << LL_ENDL;
+
+ for(S32 i=0; i < resolutionCount; i++)
{
- rtn = x11_detect_VRAM_kb_fp(fp, ": Video RAM: ");
- fclose(fp);
- if (0 == rtn)
+ F32 aspect = (F32)resolutionList[i].mWidth / (F32)resolutionList[i].mHeight;
+
+ LL_INFOS() << "createContext: width " << resolutionList[i].mWidth << " height " << resolutionList[i].mHeight << " aspect " << aspect << LL_ENDL;
+
+ if( (resolutionList[i].mHeight >= 700) && (resolutionList[i].mHeight <= 800) &&
+ (fabs(aspect - mOriginalAspectRatio) < fabs(closestAspect - mOriginalAspectRatio)))
{
- fp = fopen(fname.c_str(), "r");
- if (fp)
- {
- rtn = x11_detect_VRAM_kb_fp(fp, ": Memory: ");
- fclose(fp);
- }
+ LL_INFOS() << " (new closest mode) " << LL_ENDL;
+
+ // This is the closest mode we've seen yet.
+ closestWidth = resolutionList[i].mWidth;
+ closestHeight = resolutionList[i].mHeight;
+ closestAspect = aspect;
}
}
+
+ width = closestWidth;
+ height = closestHeight;
}
}
- else
+
+ if(width == 0 || height == 0)
{
- LL_INFOS() << "Could not open " << fname
- << " - skipped." << LL_ENDL;
- // Try old XFree86 log otherwise
- fname = x_log_location;
- fname += "XFree86.";
- fname += ('0' + display_num);
- fname += ".log";
- fp = fopen(fname.c_str(), "r");
- if (fp)
- {
- LL_INFOS() << "Looking in " << fname
- << " for VRAM info..." << LL_ENDL;
- rtn = x11_detect_VRAM_kb_fp(fp, ": VideoRAM: ");
- fclose(fp);
- if (0 == rtn)
- {
- fp = fopen(fname.c_str(), "r");
- if (fp)
- {
- rtn = x11_detect_VRAM_kb_fp(fp, ": Memory: ");
- fclose(fp);
- }
- }
- }
- else
- {
- LL_INFOS() << "Could not open " << fname
- << " - skipped." << LL_ENDL;
- }
+ // Mode search failed for some reason. Use the old-school default.
+ width = 1024;
+ height = 768;
}
- return rtn;
}
-#endif // LL_X11
-BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync)
+bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, bool fullscreen, bool enable_vsync)
{
- //bool glneedsinit = false;
-
- LL_INFOS() << "createContext, fullscreen=" << fullscreen <<
- " size=" << width << "x" << height << LL_ENDL;
+ LL_INFOS() << "createContext, fullscreen=" << fullscreen << " size=" << width << "x" << height << LL_ENDL;
// captures don't survive contexts
mGrabbyKeyFlags = 0;
- mReallyCapturedCount = 0;
- if (SDL_Init(SDL_INIT_VIDEO) < 0)
+ if (width == 0)
+ width = 1024;
+ if (height == 0)
+ width = 768;
+ if (x == 0)
+ x = SDL_WINDOWPOS_UNDEFINED;
+ if (y == 0)
+ y = SDL_WINDOWPOS_UNDEFINED;
+
+ mFullscreen = fullscreen;
+
+
+ // Setup default backing colors
+ GLint redBits{8}, greenBits{8}, blueBits{8}, alphaBits{8};
+ GLint depthBits{24}, stencilBits{8};
+
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, redBits);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, greenBits);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, blueBits);
+ SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, alphaBits);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, depthBits);
+ SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, stencilBits);
+
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+ U32 context_flags = 0;
+ if (gDebugGL)
{
- LL_INFOS() << "sdl_init() failed! " << SDL_GetError() << LL_ENDL;
- setupFailure("sdl_init() failure, window creation error", "error", OSMB_OK);
- return false;
+ 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);
- SDL_version c_sdl_version;
- SDL_VERSION(&c_sdl_version);
- LL_INFOS() << "Compiled against SDL "
- << int(c_sdl_version.major) << "."
- << int(c_sdl_version.minor) << "."
- << int(c_sdl_version.patch) << LL_ENDL;
- const SDL_version *r_sdl_version;
- r_sdl_version = SDL_Linked_Version();
- LL_INFOS() << " Running against SDL "
- << int(r_sdl_version->major) << "."
- << int(r_sdl_version->minor) << "."
- << int(r_sdl_version->patch) << LL_ENDL;
+ int sdlflags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
- const SDL_VideoInfo *video_info = SDL_GetVideoInfo( );
- if (!video_info)
+ if( mFullscreen )
{
- LL_INFOS() << "SDL_GetVideoInfo() failed! " << SDL_GetError() << LL_ENDL;
- setupFailure("SDL_GetVideoInfo() failed, Window creation error", "Error", OSMB_OK);
- return FALSE;
+ sdlflags |= SDL_WINDOW_FULLSCREEN;
+ tryFindFullscreenSize( width, height );
}
- if (video_info->current_h > 0)
+ mWindow = SDL_CreateWindow( mWindowTitle.c_str(), x, y, width, height, sdlflags );
+ if (mWindow == nullptr)
{
- mOriginalAspectRatio = (float)video_info->current_w / (float)video_info->current_h;
- LL_INFOS() << "Original aspect ratio was " << video_info->current_w << ":" << video_info->current_h << "=" << mOriginalAspectRatio << LL_ENDL;
+ LL_WARNS() << "Window creation failure. SDL: " << SDL_GetError() << LL_ENDL;
+ setupFailure("Window creation error", "Error", OSMB_OK);
}
- SDL_EnableUNICODE(1);
- SDL_WM_SetCaption(mWindowTitle.c_str(), mWindowTitle.c_str());
-
- // Set the application icon.
- SDL_Surface *bmpsurface;
- bmpsurface = Load_BMP_Resource("ll_icon.BMP");
- if (bmpsurface)
+ // Create the context
+ mContext = SDL_GL_CreateContext(mWindow);
+ if(!mContext)
{
- // This attempts to give a black-keyed mask to the icon.
- SDL_SetColorKey(bmpsurface,
- SDL_SRCCOLORKEY,
- SDL_MapRGB(bmpsurface->format, 0,0,0) );
- SDL_WM_SetIcon(bmpsurface, NULL);
- // The SDL examples cheerfully avoid freeing the icon
- // surface, but I'm betting that's leaky.
- SDL_FreeSurface(bmpsurface);
- bmpsurface = NULL;
+ LL_WARNS() << "Cannot create GL context " << SDL_GetError() << LL_ENDL;
+ setupFailure("GL Context creation error", "Error", OSMB_OK);
}
- // note: these SetAttributes make Tom's 9600-on-AMD64 fail to
- // get a visual, but it's broken anyway when it does, and without
- // these SetAttributes we might easily get an avoidable substandard
- // visual to work with on most other machines.
- SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8);
- SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, (bits <= 16) ? 16 : 24);
- // We need stencil support for a few (minor) things.
- if (!getenv("LL_GL_NO_STENCIL"))
- SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, (bits <= 16) ? 1 : 8);
-
- // *FIX: try to toggle vsync here?
-
- mFullscreen = fullscreen;
-
- int sdlflags = SDL_OPENGL | SDL_RESIZABLE | SDL_ANYFORMAT;
-
- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
-
- if (mFSAASamples > 0)
+ if (SDL_GL_MakeCurrent(mWindow, mContext) != 0)
{
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, mFSAASamples);
+ LL_WARNS() << "Failed to make context current. SDL: " << SDL_GetError() << LL_ENDL;
+ setupFailure("GL Context failed to set current failure", "Error", OSMB_OK);
}
- mSDLFlags = sdlflags;
-
- if (mFullscreen)
+ mSurface = SDL_GetWindowSurface(mWindow);
+ if(mFullscreen)
{
- LL_INFOS() << "createContext: setting up fullscreen " << width << "x" << height << LL_ENDL;
-
- // If the requested width or height is 0, find the best default for the monitor.
- if((width == 0) || (height == 0))
- {
- // Scan through the list of modes, looking for one which has:
- // height between 700 and 800
- // aspect ratio closest to the user's original mode
- S32 resolutionCount = 0;
- LLWindowResolution *resolutionList = getSupportedResolutions(resolutionCount);
-
- if(resolutionList != NULL)
- {
- F32 closestAspect = 0;
- U32 closestHeight = 0;
- U32 closestWidth = 0;
- int i;
-
- LL_INFOS() << "createContext: searching for a display mode, original aspect is " << mOriginalAspectRatio << LL_ENDL;
-
- for(i=0; i < resolutionCount; i++)
- {
- F32 aspect = (F32)resolutionList[i].mWidth / (F32)resolutionList[i].mHeight;
-
- LL_INFOS() << "createContext: width " << resolutionList[i].mWidth << " height " << resolutionList[i].mHeight << " aspect " << aspect << LL_ENDL;
-
- if( (resolutionList[i].mHeight >= 700) && (resolutionList[i].mHeight <= 800) &&
- (fabs(aspect - mOriginalAspectRatio) < fabs(closestAspect - mOriginalAspectRatio)))
- {
- LL_INFOS() << " (new closest mode) " << LL_ENDL;
-
- // This is the closest mode we've seen yet.
- closestWidth = resolutionList[i].mWidth;
- closestHeight = resolutionList[i].mHeight;
- closestAspect = aspect;
- }
- }
-
- width = closestWidth;
- height = closestHeight;
- }
- }
-
- if((width == 0) || (height == 0))
- {
- // Mode search failed for some reason. Use the old-school default.
- width = 1024;
- height = 768;
- }
-
- mWindow = SDL_SetVideoMode(width, height, bits, sdlflags | SDL_FULLSCREEN);
- if (!mWindow && bits > 16)
+ if (mSurface)
{
- SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
- mWindow = SDL_SetVideoMode(width, height, bits, sdlflags | SDL_FULLSCREEN);
- }
-
- if (mWindow)
- {
- mFullscreen = TRUE;
- mFullscreenWidth = mWindow->w;
- mFullscreenHeight = mWindow->h;
- mFullscreenBits = mWindow->format->BitsPerPixel;
+ mFullscreen = true;
+ mFullscreenWidth = mSurface->w;
+ mFullscreenHeight = mSurface->h;
+ mFullscreenBits = mSurface->format->BitsPerPixel;
mFullscreenRefresh = -1;
LL_INFOS() << "Running at " << mFullscreenWidth
- << "x" << mFullscreenHeight
- << "x" << mFullscreenBits
- << " @ " << mFullscreenRefresh
- << LL_ENDL;
+ << "x" << mFullscreenHeight
+ << "x" << mFullscreenBits
+ << " @ " << mFullscreenRefresh
+ << LL_ENDL;
}
else
{
LL_WARNS() << "createContext: fullscreen creation failure. SDL: " << SDL_GetError() << LL_ENDL;
- // No fullscreen support
- mFullscreen = FALSE;
+
+ mFullscreen = false;
mFullscreenWidth = -1;
mFullscreenHeight = -1;
mFullscreenBits = -1;
mFullscreenRefresh = -1;
std::string error = llformat("Unable to run fullscreen at %d x %d.\nRunning in window.", width, height);
- OSMessageBox(error, "Error", OSMB_OK);
+ setupFailure( error, "Error", OSMB_OK );
}
}
-
- if(!mFullscreen && (mWindow == NULL))
+ else
{
- if (width == 0)
- width = 1024;
- if (height == 0)
- width = 768;
-
- LL_INFOS() << "createContext: creating window " << width << "x" << height << "x" << bits << LL_ENDL;
- mWindow = SDL_SetVideoMode(width, height, bits, sdlflags);
- if (!mWindow && bits > 16)
- {
- SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
- mWindow = SDL_SetVideoMode(width, height, bits, sdlflags);
- }
-
if (!mWindow)
{
LL_WARNS() << "createContext: window creation failure. SDL: " << SDL_GetError() << LL_ENDL;
setupFailure("Window creation error", "Error", OSMB_OK);
- return FALSE;
}
- } else if (!mFullscreen && (mWindow != NULL))
- {
- LL_INFOS() << "createContext: SKIPPING - !fullscreen, but +mWindow " << width << "x" << height << "x" << bits << LL_ENDL;
}
- // Detect video memory size.
-# if LL_X11
- gGLManager.mVRAM = x11_detect_VRAM_kb() / 1024;
- if (gGLManager.mVRAM != 0)
- {
- LL_INFOS() << "X11 log-parser detected " << gGLManager.mVRAM << "MB VRAM." << LL_ENDL;
- } else
-# endif // LL_X11
- {
- // fallback to letting SDL detect VRAM.
- // note: I've not seen SDL's detection ever actually find
- // VRAM != 0, but if SDL *does* detect it then that's a bonus.
- gGLManager.mVRAM = video_info->video_mem / 1024;
- if (gGLManager.mVRAM != 0)
- {
- LL_INFOS() << "SDL detected " << gGLManager.mVRAM << "MB VRAM." << LL_ENDL;
- }
- }
- // If VRAM is not detected, that is handled later
-
- // *TODO: Now would be an appropriate time to check for some
- // explicitly unsupported cards.
- //const char* RENDERER = (const char*) glGetString(GL_RENDERER);
-
- GLint depthBits, stencilBits, redBits, greenBits, blueBits, alphaBits;
-
- glGetIntegerv(GL_RED_BITS, &redBits);
- glGetIntegerv(GL_GREEN_BITS, &greenBits);
- glGetIntegerv(GL_BLUE_BITS, &blueBits);
- glGetIntegerv(GL_ALPHA_BITS, &alphaBits);
- glGetIntegerv(GL_DEPTH_BITS, &depthBits);
- glGetIntegerv(GL_STENCIL_BITS, &stencilBits);
+ SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &redBits);
+ SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &greenBits);
+ SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &blueBits);
+ SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &alphaBits);
+ SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &depthBits);
+ SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &stencilBits);
LL_INFOS() << "GL buffer:" << LL_ENDL;
- LL_INFOS() << " Red Bits " << S32(redBits) << LL_ENDL;
- LL_INFOS() << " Green Bits " << S32(greenBits) << LL_ENDL;
- LL_INFOS() << " Blue Bits " << S32(blueBits) << LL_ENDL;
- LL_INFOS() << " Alpha Bits " << S32(alphaBits) << LL_ENDL;
- LL_INFOS() << " Depth Bits " << S32(depthBits) << LL_ENDL;
- LL_INFOS() << " Stencil Bits " << S32(stencilBits) << LL_ENDL;
+ LL_INFOS() << " Red Bits " << S32(redBits) << LL_ENDL;
+ LL_INFOS() << " Green Bits " << S32(greenBits) << LL_ENDL;
+ LL_INFOS() << " Blue Bits " << S32(blueBits) << LL_ENDL;
+ LL_INFOS() << " Alpha Bits " << S32(alphaBits) << LL_ENDL;
+ LL_INFOS() << " Depth Bits " << S32(depthBits) << LL_ENDL;
+ LL_INFOS() << " Stencil Bits " << S32(stencilBits) << LL_ENDL;
GLint colorBits = redBits + greenBits + blueBits + alphaBits;
// fixme: actually, it's REALLY important for picking that we get at
@@ -662,86 +475,131 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
{
close();
setupFailure(
- "Second Life requires True Color (32-bit) to run in a window.\n"
- "Please go to Control Panels -> Display -> Settings and\n"
- "set the screen to 32-bit color.\n"
- "Alternately, if you choose to run fullscreen, Second Life\n"
- "will automatically adjust the screen each time it runs.",
- "Error",
- OSMB_OK);
- return FALSE;
+ "Second Life requires True Color (32-bit) to run in a window.\n"
+ "Please go to Control Panels -> Display -> Settings and\n"
+ "set the screen to 32-bit color.\n"
+ "Alternately, if you choose to run fullscreen, Second Life\n"
+ "will automatically adjust the screen each time it runs.",
+ "Error",
+ OSMB_OK);
}
-#if 0 // *FIX: we're going to brave it for now...
- if (alphaBits < 8)
+ LL_PROFILER_GPU_CONTEXT;
+
+ // Enable vertical sync
+ toggleVSync(enable_vsync);
+
+ // Set the application icon.
+ SDL_Surface* bmpsurface = Load_BMP_Resource("ll_icon.BMP");
+ if (bmpsurface)
{
- close();
- setupFailure(
- "Second Life is unable to run because it can't get an 8 bit alpha\n"
- "channel. Usually this is due to video card driver issues.\n"
- "Please make sure you have the latest video card drivers installed.\n"
- "Also be sure your monitor is set to True Color (32-bit) in\n"
- "Control Panels -> Display -> Settings.\n"
- "If you continue to receive this message, contact customer service.",
- "Error",
- OSMB_OK);
- return FALSE;
+ SDL_SetWindowIcon(mWindow, bmpsurface);
+ SDL_FreeSurface(bmpsurface);
+ bmpsurface = nullptr;
}
-#endif
-#if LL_X11
/* Grab the window manager specific information */
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
- if ( SDL_GetWMInfo(&info) )
+ if ( SDL_GetWindowWMInfo(mWindow, &info) )
{
/* Save the information for later use */
if ( info.subsystem == SDL_SYSWM_X11 )
{
- mSDL_Display = info.info.x11.display;
- mSDL_XWindowID = info.info.x11.wmwindow;
- Lock_Display = info.info.x11.lock_func;
- Unlock_Display = info.info.x11.unlock_func;
+ mX11Data.mDisplay = info.info.x11.display;
+ mX11Data.mXWindowID = info.info.x11.window;
+ mServerProtocol = X11;
+ LL_INFOS() << "Running under X11" << LL_ENDL;
+ }
+ else if ( info.subsystem == SDL_SYSWM_WAYLAND )
+ {
+#ifdef LL_WAYLAND
+ if( !loadWaylandClient() )
+ LL_ERRS() << "Failed to load wayland-client.so or grab required functions" << LL_ENDL;
+
+ mWaylandData.mSurface = info.info.wl.surface;
+ mServerProtocol = Wayland;
+ setupWaylandFrameCallback();
+
+ // If set (XWayland) remove DISPLAY, this will prompt dullahan to also use Wayland
+ if( getenv("DISPLAY") )
+ unsetenv("DISPLAY");
+
+ LL_INFOS() << "Running under Wayland" << LL_ENDL;
+ LL_WARNS() << "Be aware that with at least SDL2 the window will not receive minimizing events, thus minimized state can only be estimated."
+ "also setting the application icon via SDL_SetWindowIcon does not work." << LL_ENDL;
+#else
+ setupFailure("Viewer is running under Wayland, but was not compiled with full wayland support!\nYou can compile the viewer with wayland prelimiary support using COMPILE_WAYLAND_SUPPORT", "Error", OSMB_OK);
+#endif
}
else
{
- LL_WARNS() << "We're not running under X11? Wild."
- << LL_ENDL;
+ LL_WARNS() << "We're not running under X11 or Wayland? Wild." << LL_ENDL;
}
}
else
{
- LL_WARNS() << "We're not running under any known WM. Wild."
- << LL_ENDL;
+ LL_WARNS() << "We're not running under any known WM. Wild." << LL_ENDL;
}
-#endif // LL_X11
-
+ SDL_StartTextInput();
//make sure multisampling is disabled by default
glDisable(GL_MULTISAMPLE_ARB);
- // We need to do this here, once video is init'd
- if (-1 == SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,
- SDL_DEFAULT_REPEAT_INTERVAL))
- LL_WARNS() << "Couldn't enable key-repeat: " << SDL_GetError() <<LL_ENDL;
-
// Don't need to get the current gamma, since there's a call that restores it to the system defaults.
- return TRUE;
+ 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;
+ }
+
+ LL_WARNS() << "Creating shared OpenGL context failed!" << LL_ENDL;
+ return nullptr;
}
+void LLWindowSDL::makeContextCurrent(void* contextPtr)
+{
+ SDL_GL_MakeCurrent(mWindow, contextPtr);
+ LL_PROFILER_GPU_CONTEXT;
+}
+
+void LLWindowSDL::destroySharedContext(void* contextPtr)
+{
+ SDL_GL_DeleteContext(contextPtr);
+}
+
+void LLWindowSDL::toggleVSync(bool enable_vsync)
+{
+ if (!enable_vsync)
+ {
+ LL_INFOS("Window") << "Disabling vertical sync" << LL_ENDL;
+ SDL_GL_SetSwapInterval(0);
+ }
+ else
+ {
+ LL_INFOS("Window") << "Enabling vertical sync" << LL_ENDL;
+ SDL_GL_SetSwapInterval(1);
+ }
+}
// changing fullscreen resolution, or switching between windowed and fullscreen mode.
-BOOL LLWindowSDL::switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp)
+bool LLWindowSDL::switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp)
{
- const BOOL needsRebuild = TRUE; // Just nuke the context and start over.
- BOOL result = true;
+ const bool needsRebuild = true; // Just nuke the context and start over.
+ bool result = true;
LL_INFOS() << "switchContext, fullscreen=" << fullscreen << LL_ENDL;
stop_glerror();
if(needsRebuild)
{
destroyContext();
- result = createContext(0, 0, size.mX, size.mY, 0, fullscreen, disable_vsync);
+ result = createContext(0, 0, size.mX, size.mY, 32, fullscreen, enable_vsync);
if (result)
{
gGLManager.initGL();
@@ -761,206 +619,238 @@ void LLWindowSDL::destroyContext()
{
LL_INFOS() << "destroyContext begins" << LL_ENDL;
-#if LL_X11
- mSDL_Display = NULL;
- mSDL_XWindowID = None;
- Lock_Display = NULL;
- Unlock_Display = NULL;
-#endif // LL_X11
+ // Stop unicode input
+ SDL_StopTextInput();
// Clean up remaining GL state before blowing away window
LL_INFOS() << "shutdownGL begins" << LL_ENDL;
gGLManager.shutdownGL();
+
+ mX11Data.mDisplay = nullptr;
+ mX11Data.mXWindowID = None;
+ Lock_Display = nullptr;
+ Unlock_Display = nullptr;
+ mServerProtocol = Unknown;
+
+ LL_INFOS() << "Destroying SDL cursors" << LL_ENDL;
+ quitCursors();
+
+ if (mContext)
+ {
+ LL_INFOS() << "Destroying SDL GL Context" << LL_ENDL;
+ SDL_GL_DeleteContext(mContext);
+ mContext = nullptr;
+ }
+ else
+ {
+ LL_INFOS() << "SDL GL Context already destroyed" << LL_ENDL;
+ }
+
+ if (mWindow)
+ {
+ LL_INFOS() << "Destroying SDL Window" << LL_ENDL;
+ SDL_DestroyWindow(mWindow);
+ mWindow = nullptr;
+ }
+ else
+ {
+ LL_INFOS() << "SDL Window already destroyed" << LL_ENDL;
+ }
+ LL_INFOS() << "destroyContext end" << LL_ENDL;
+
LL_INFOS() << "SDL_QuitSS/VID begins" << LL_ENDL;
SDL_QuitSubSystem(SDL_INIT_VIDEO); // *FIX: this might be risky...
-
- mWindow = NULL;
}
LLWindowSDL::~LLWindowSDL()
{
- quitCursors();
destroyContext();
- if(mSupportedResolutions != NULL)
- {
- delete []mSupportedResolutions;
- }
+ delete []mSupportedResolutions;
- gWindowImplementation = NULL;
+ gWindowImplementation = nullptr;
}
void LLWindowSDL::show()
{
- // *FIX: What to do with SDL?
+ if (mWindow)
+ {
+ SDL_ShowWindow(mWindow);
+ }
}
void LLWindowSDL::hide()
{
- // *FIX: What to do with SDL?
+ if (mWindow)
+ {
+ SDL_HideWindow(mWindow);
+ }
}
-//virtual
void LLWindowSDL::minimize()
{
- // *FIX: What to do with SDL?
+ if (mWindow)
+ {
+ SDL_MinimizeWindow(mWindow);
+ }
}
-//virtual
void LLWindowSDL::restore()
{
- // *FIX: What to do with SDL?
+ if (mWindow)
+ {
+ SDL_RestoreWindow(mWindow);
+ }
}
-
// close() destroys all OS-specific code associated with a window.
// Usually called from LLWindowManager::destroyWindow()
void LLWindowSDL::close()
{
- // Is window is already closed?
- // if (!mWindow)
- // {
- // return;
- // }
-
// Make sure cursor is visible and we haven't mangled the clipping state.
- setMouseClipping(FALSE);
+ setMouseClipping(false);
showCursor();
destroyContext();
}
-BOOL LLWindowSDL::isValid()
+bool LLWindowSDL::isValid()
{
- return (mWindow != NULL);
+ return mWindow != nullptr;
}
-BOOL LLWindowSDL::getVisible()
+bool LLWindowSDL::getVisible() const
{
- BOOL result = FALSE;
-
- // *FIX: This isn't really right...
- // Then what is?
+ bool result = false;
if (mWindow)
{
- result = TRUE;
+ Uint32 flags = SDL_GetWindowFlags(mWindow);
+ if (flags & SDL_WINDOW_SHOWN)
+ {
+ result = true;
+ }
}
-
- return(result);
+ return result;
}
-BOOL LLWindowSDL::getMinimized()
+bool LLWindowSDL::getMinimized() const
{
- BOOL result = FALSE;
+ if( isWaylandWindowNotDrawing() )
+ return true;
- if (mWindow && (1 == mIsMinimized))
+ bool result = false;
+ if (mWindow)
{
- result = TRUE;
+ Uint32 flags = SDL_GetWindowFlags(mWindow);
+ if (flags & SDL_WINDOW_MINIMIZED)
+ {
+ result = true;
+ }
}
- return(result);
+ return result;
}
-BOOL LLWindowSDL::getMaximized()
+bool LLWindowSDL::getMaximized() const
{
- BOOL result = FALSE;
-
+ bool result = false;
if (mWindow)
{
- // TODO
+ Uint32 flags = SDL_GetWindowFlags(mWindow);
+ if (flags & SDL_WINDOW_MAXIMIZED)
+ {
+ result = true;
+ }
}
- return(result);
-}
-
-BOOL LLWindowSDL::maximize()
-{
- // TODO
- return FALSE;
+ return result;
}
-BOOL LLWindowSDL::getFullscreen()
+bool LLWindowSDL::maximize()
{
- return mFullscreen;
+ if (mWindow)
+ {
+ SDL_MaximizeWindow(mWindow);
+ return true;
+ }
+ return false;
}
-BOOL LLWindowSDL::getPosition(LLCoordScreen *position)
+bool LLWindowSDL::getPosition(LLCoordScreen *position) const
{
- // *FIX: can anything be done with this?
- position->mX = 0;
- position->mY = 0;
- return TRUE;
+ if (mWindow)
+ {
+ SDL_GetWindowPosition(mWindow, &position->mX, &position->mY);
+ return true;
+ }
+ return false;
}
-BOOL LLWindowSDL::getSize(LLCoordScreen *size)
+bool LLWindowSDL::getSize(LLCoordScreen *size) const
{
- if (mWindow)
+ if (mSurface)
{
- size->mX = mWindow->w;
- size->mY = mWindow->h;
- return (TRUE);
+ size->mX = mSurface->w;
+ size->mY = mSurface->h;
+ return true;
}
- return (FALSE);
+ return false;
}
-BOOL LLWindowSDL::getSize(LLCoordWindow *size)
+bool LLWindowSDL::getSize(LLCoordWindow *size) const
{
- if (mWindow)
+ if (mSurface)
{
- size->mX = mWindow->w;
- size->mY = mWindow->h;
- return (TRUE);
+ size->mX = mSurface->w;
+ size->mY = mSurface->h;
+ return true;
}
- return (FALSE);
+ return false;
}
-BOOL LLWindowSDL::setPosition(const LLCoordScreen position)
+bool LLWindowSDL::setPosition(const LLCoordScreen position)
{
- if(mWindow)
+ if (mWindow)
{
- // *FIX: (?)
- //MacMoveWindow(mWindow, position.mX, position.mY, false);
+ SDL_SetWindowPosition(mWindow, position.mX, position.mY);
+ return true;
}
- return TRUE;
+ return false;
}
-BOOL LLWindowSDL::setSizeImpl(const LLCoordScreen size)
+template< typename T > bool setSizeImpl( const T& newSize, SDL_Window *pWin )
{
- if(mWindow)
- {
- // Push a resize event onto SDL's queue - we'll handle it
- // when it comes out again.
- SDL_Event event;
- event.type = SDL_VIDEORESIZE;
- event.resize.w = size.mX;
- event.resize.h = size.mY;
- SDL_PushEvent(&event); // copied into queue
+ if( !pWin )
+ return false;
- return TRUE;
- }
+ auto nFlags = SDL_GetWindowFlags( pWin );
+
+ if( nFlags & SDL_WINDOW_MAXIMIZED )
+ SDL_RestoreWindow( pWin );
- return FALSE;
+ SDL_SetWindowSize( pWin, newSize.mX, newSize.mY );
+ SDL_Event event;
+ event.type = SDL_WINDOWEVENT;
+ event.window.event = SDL_WINDOWEVENT_RESIZED;
+ event.window.windowID = SDL_GetWindowID( pWin );
+ event.window.data1 = newSize.mX;
+ event.window.data2 = newSize.mY;
+ SDL_PushEvent( &event );
+
+ return true;
}
-BOOL LLWindowSDL::setSizeImpl(const LLCoordWindow size)
+bool LLWindowSDL::setSizeImpl(const LLCoordScreen size)
{
- if(mWindow)
- {
- // Push a resize event onto SDL's queue - we'll handle it
- // when it comes out again.
- SDL_Event event;
- event.type = SDL_VIDEORESIZE;
- event.resize.w = size.mX;
- event.resize.h = size.mY;
- SDL_PushEvent(&event); // copied into queue
-
- return TRUE;
- }
+ return ::setSizeImpl( size, mWindow );
+}
- return FALSE;
+bool LLWindowSDL::setSizeImpl(const LLCoordWindow size)
+{
+ return ::setSizeImpl( size, mWindow );
}
@@ -968,11 +858,12 @@ void LLWindowSDL::swapBuffers()
{
if (mWindow)
{
- SDL_GL_SwapBuffers();
+ SDL_GL_SwapWindow(mWindow);
}
+ LL_PROFILER_GPU_COLLECT;
}
-U32 LLWindowSDL::getFSAASamples()
+U32 LLWindowSDL::getFSAASamples() const
{
return mFSAASamples;
}
@@ -982,38 +873,49 @@ void LLWindowSDL::setFSAASamples(const U32 samples)
mFSAASamples = samples;
}
-F32 LLWindowSDL::getGamma()
+F32 LLWindowSDL::getGamma() const
{
- return 1/mGamma;
+ return 1.f / mGamma;
}
-BOOL LLWindowSDL::restoreGamma()
+bool LLWindowSDL::restoreGamma()
{
- //CGDisplayRestoreColorSyncSettings();
- SDL_SetGamma(1.0f, 1.0f, 1.0f);
+ if (mWindow)
+ {
+ Uint16 ramp[256];
+ SDL_CalculateGammaRamp(1.f, ramp);
+ SDL_SetWindowGammaRamp(mWindow, ramp, ramp, ramp);
+ }
return true;
}
-BOOL LLWindowSDL::setGamma(const F32 gamma)
+bool LLWindowSDL::setGamma(const F32 gamma)
{
- mGamma = gamma;
- if (mGamma == 0) mGamma = 0.1f;
- mGamma = 1/mGamma;
- SDL_SetGamma(mGamma, mGamma, mGamma);
+ if (mWindow)
+ {
+ Uint16 ramp[256];
+
+ mGamma = gamma;
+ if (mGamma == 0)
+ mGamma = 0.1f;
+ mGamma = 1.f / mGamma;
+
+ SDL_CalculateGammaRamp(mGamma, ramp);
+ SDL_SetWindowGammaRamp(mWindow, ramp, ramp, ramp);
+ }
return true;
}
-BOOL LLWindowSDL::isCursorHidden()
+bool LLWindowSDL::isCursorHidden()
{
return mCursorHidden;
}
-
-
// Constrains the mouse to the window.
-void LLWindowSDL::setMouseClipping( BOOL b )
+void LLWindowSDL::setMouseClipping(bool b)
{
- //SDL_WM_GrabInput(b ? SDL_GRAB_ON : SDL_GRAB_OFF);
+ if( mWindow )
+ SDL_SetWindowGrab( mWindow, b?SDL_TRUE:SDL_FALSE );
}
// virtual
@@ -1021,46 +923,31 @@ void LLWindowSDL::setMinSize(U32 min_width, U32 min_height, bool enforce_immedia
{
LLWindow::setMinSize(min_width, min_height, enforce_immediately);
-#if LL_X11
- // Set the minimum size limits for X11 window
- // so the window manager doesn't allow resizing below those limits.
- XSizeHints* hints = XAllocSizeHints();
- hints->flags |= PMinSize;
- hints->min_width = mMinWindowWidth;
- hints->min_height = mMinWindowHeight;
-
- XSetWMNormalHints(mSDL_Display, mSDL_XWindowID, hints);
-
- XFree(hints);
-#endif
+ if (mWindow && min_width > 0 && min_height > 0)
+ {
+ SDL_SetWindowMinimumSize(mWindow, mMinWindowWidth, mMinWindowHeight);
+ }
}
-BOOL LLWindowSDL::setCursorPosition(const LLCoordWindow position)
+bool LLWindowSDL::setCursorPosition(const LLCoordWindow position)
{
- BOOL result = TRUE;
+ bool result = true;
LLCoordScreen screen_pos;
if (!convertCoords(position, &screen_pos))
- {
- return FALSE;
- }
-
- //LL_INFOS() << "setCursorPosition(" << screen_pos.mX << ", " << screen_pos.mY << ")" << LL_ENDL;
+ return false;
// do the actual forced cursor move.
- SDL_WarpMouse(screen_pos.mX, screen_pos.mY);
-
- //LL_INFOS() << llformat("llcw %d,%d -> scr %d,%d", position.mX, position.mY, screen_pos.mX, screen_pos.mY) << LL_ENDL;
+ SDL_WarpMouseInWindow(mWindow, screen_pos.mX, screen_pos.mY);
return result;
}
-BOOL LLWindowSDL::getCursorPosition(LLCoordWindow *position)
+bool LLWindowSDL::getCursorPosition(LLCoordWindow *position)
{
//Point cursor_point;
LLCoordScreen screen_pos;
- //GetMouse(&cursor_point);
int x, y;
SDL_GetMouseState(&x, &y);
@@ -1070,21 +957,8 @@ BOOL LLWindowSDL::getCursorPosition(LLCoordWindow *position)
return convertCoords(screen_pos, position);
}
-
F32 LLWindowSDL::getNativeAspectRatio()
{
-#if 0
- // RN: this hack presumes that the largest supported resolution is monitor-limited
- // and that pixels in that mode are square, therefore defining the native aspect ratio
- // of the monitor...this seems to work to a close approximation for most CRTs/LCDs
- S32 num_resolutions;
- LLWindowResolution* resolutions = getSupportedResolutions(num_resolutions);
-
-
- return ((F32)resolutions[num_resolutions - 1].mWidth / (F32)resolutions[num_resolutions - 1].mHeight);
- //rn: AC
-#endif
-
// MBW -- there are a couple of bad assumptions here. One is that the display list won't include
// ridiculous resolutions nobody would ever use. The other is that the list is in order.
@@ -1103,9 +977,7 @@ F32 LLWindowSDL::getNativeAspectRatio()
// switching, and stashes it in mOriginalAspectRatio. Here, we just return it.
if (mOverrideAspectRatio > 0.f)
- {
return mOverrideAspectRatio;
- }
return mOriginalAspectRatio;
}
@@ -1117,9 +989,7 @@ F32 LLWindowSDL::getPixelAspectRatio()
{
LLCoordScreen screen_size;
if (getSize(&screen_size))
- {
pixel_aspect = getNativeAspectRatio() * (F32)screen_size.mY / (F32)screen_size.mX;
- }
}
return pixel_aspect;
@@ -1130,104 +1000,39 @@ 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 (SDLReallyCaptureInput(false)) // must ungrab input so popup works!
{
- if (mFullscreen)
- {
- // need to temporarily go non-fullscreen; bless SDL
- // for providing a SDL_WM_ToggleFullScreen() - though
- // it only works in X11
- if (running_x11 && mWindow)
- {
- SDL_WM_ToggleFullScreen(mWindow);
- }
- }
+ if (mFullscreen && mWindow )
+ SDL_SetWindowFullscreen( mWindow, 0 );
}
-#if LL_X11
- if (mSDL_Display)
+ if (mServerProtocol == X11 && mX11Data.mDisplay)
{
// Everything that we/SDL asked for should happen before we
// potentially hand control over to GTK.
maybe_lock_display();
- XSync(mSDL_Display, False);
+ XSync(mX11Data.mDisplay, False);
maybe_unlock_display();
}
-#endif // LL_X11
-
-#if LL_GTK
- // this is a good time to grab some GTK version information for
- // diagnostics, if not already done.
- ll_try_gtk_init();
-#endif // LL_GTK
maybe_lock_display();
}
void LLWindowSDL::afterDialog()
{
- bool running_x11 = false;
-#if LL_X11
- running_x11 = (mSDL_XWindowID != None);
-#endif //LL_X11
-
LL_INFOS() << "LLWindowSDL::afterDialog()" << LL_ENDL;
maybe_unlock_display();
- if (mFullscreen)
- {
- // need to restore fullscreen mode after dialog - only works
- // in X11
- if (running_x11 && mWindow)
- {
- SDL_WM_ToggleFullScreen(mWindow);
- }
- }
+ if (mFullscreen && mWindow )
+ SDL_SetWindowFullscreen( mWindow, 0 );
}
-
-#if LL_X11
-// set/reset the XWMHints flag for 'urgency' that usually makes the icon flash
-void LLWindowSDL::x11_set_urgent(BOOL urgent)
-{
- if (mSDL_Display && !mFullscreen)
- {
- XWMHints *wm_hints;
-
- LL_INFOS() << "X11 hint for urgency, " << urgent << LL_ENDL;
-
- maybe_lock_display();
- wm_hints = XGetWMHints(mSDL_Display, mSDL_XWindowID);
- if (!wm_hints)
- wm_hints = XAllocWMHints();
-
- if (urgent)
- wm_hints->flags |= XUrgencyHint;
- else
- wm_hints->flags &= ~XUrgencyHint;
-
- XSetWMHints(mSDL_Display, mSDL_XWindowID, wm_hints);
- XFree(wm_hints);
- XSync(mSDL_Display, False);
- maybe_unlock_display();
- }
-}
-#endif // LL_X11
-
void LLWindowSDL::flashIcon(F32 seconds)
{
-#if !LL_X11
- LL_INFOS() << "Stub LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL;
-#else
- LL_INFOS() << "X11 LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL;
+ LL_INFOS() << "LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL;
F32 remaining_time = mFlashTimer.getRemainingTimeF32();
if (remaining_time < seconds)
@@ -1235,132 +1040,71 @@ void LLWindowSDL::flashIcon(F32 seconds)
mFlashTimer.reset();
mFlashTimer.setTimerExpirySec(remaining_time);
- x11_set_urgent(TRUE);
- mFlashing = TRUE;
-#endif // LL_X11
+ SDL_FlashWindow(mWindow, SDL_FLASH_UNTIL_FOCUSED);
+ mFlashing = true;
}
-
-#if LL_GTK
-BOOL LLWindowSDL::isClipboardTextAvailable()
+void LLWindowSDL::maybeStopFlashIcon()
{
- if (ll_try_gtk_init())
+ if (mFlashing && mFlashTimer.hasExpired())
{
- GtkClipboard * const clipboard =
- gtk_clipboard_get(GDK_NONE);
- return gtk_clipboard_wait_is_text_available(clipboard) ?
- TRUE : FALSE;
+ mFlashing = false;
+ SDL_FlashWindow( mWindow, SDL_FLASH_CANCEL );
}
- return FALSE; // failure
}
-BOOL LLWindowSDL::pasteTextFromClipboard(LLWString &text)
+bool LLWindowSDL::isClipboardTextAvailable()
+{
+ return SDL_HasClipboardText() == SDL_TRUE;
+}
+
+bool LLWindowSDL::pasteTextFromClipboard(LLWString &dst)
{
- if (ll_try_gtk_init())
+ if (isClipboardTextAvailable())
{
- GtkClipboard * const clipboard =
- gtk_clipboard_get(GDK_NONE);
- gchar * const data = gtk_clipboard_wait_for_text(clipboard);
+ char* data = SDL_GetClipboardText();
if (data)
{
- text = LLWString(utf8str_to_wstring(data));
- g_free(data);
- return TRUE;
+ dst = LLWString(utf8str_to_wstring(data));
+ SDL_free(data);
+ return true;
}
}
- return FALSE; // failure
+ return false;
}
-BOOL LLWindowSDL::copyTextToClipboard(const LLWString &text)
+bool LLWindowSDL::copyTextToClipboard(const LLWString& text)
{
- if (ll_try_gtk_init())
- {
- const std::string utf8 = wstring_to_utf8str(text);
- GtkClipboard * const clipboard =
- gtk_clipboard_get(GDK_NONE);
- gtk_clipboard_set_text(clipboard, utf8.c_str(), utf8.length());
- return TRUE;
- }
- return FALSE; // failure
+ const std::string utf8 = wstring_to_utf8str(text);
+ return SDL_SetClipboardText(utf8.c_str()) == 0; // success == 0
}
-
-BOOL LLWindowSDL::isPrimaryTextAvailable()
+bool LLWindowSDL::isPrimaryTextAvailable()
{
- if (ll_try_gtk_init())
- {
- GtkClipboard * const clipboard =
- gtk_clipboard_get(GDK_SELECTION_PRIMARY);
- return gtk_clipboard_wait_is_text_available(clipboard) ?
- TRUE : FALSE;
- }
- return FALSE; // failure
+ return SDL_HasPrimarySelectionText() == SDL_TRUE;
}
-BOOL LLWindowSDL::pasteTextFromPrimary(LLWString &text)
+bool LLWindowSDL::pasteTextFromPrimary(LLWString &dst)
{
- if (ll_try_gtk_init())
+ if (isPrimaryTextAvailable())
{
- GtkClipboard * const clipboard =
- gtk_clipboard_get(GDK_SELECTION_PRIMARY);
- gchar * const data = gtk_clipboard_wait_for_text(clipboard);
+ char* data = SDL_GetPrimarySelectionText();
if (data)
{
- text = LLWString(utf8str_to_wstring(data));
- g_free(data);
- return TRUE;
+ dst = LLWString(utf8str_to_wstring(data));
+ SDL_free(data);
+ return true;
}
}
- return FALSE; // failure
-}
-
-BOOL LLWindowSDL::copyTextToPrimary(const LLWString &text)
-{
- if (ll_try_gtk_init())
- {
- const std::string utf8 = wstring_to_utf8str(text);
- GtkClipboard * const clipboard =
- gtk_clipboard_get(GDK_SELECTION_PRIMARY);
- gtk_clipboard_set_text(clipboard, utf8.c_str(), utf8.length());
- return TRUE;
- }
- return FALSE; // failure
-}
-
-#else
-
-BOOL LLWindowSDL::isClipboardTextAvailable()
-{
- return FALSE; // unsupported
-}
-
-BOOL LLWindowSDL::pasteTextFromClipboard(LLWString &dst)
-{
- return FALSE; // unsupported
-}
-
-BOOL LLWindowSDL::copyTextToClipboard(const LLWString &s)
-{
- return FALSE; // unsupported
-}
-
-BOOL LLWindowSDL::isPrimaryTextAvailable()
-{
- return FALSE; // unsupported
+ return false;
}
-BOOL LLWindowSDL::pasteTextFromPrimary(LLWString &dst)
+bool LLWindowSDL::copyTextToPrimary(const LLWString& text)
{
- return FALSE; // unsupported
+ const std::string utf8 = wstring_to_utf8str(text);
+ return SDL_SetPrimarySelectionText(utf8.c_str()) == 0; // success == 0
}
-BOOL LLWindowSDL::copyTextToPrimary(const LLWString &s)
-{
- return FALSE; // unsupported
-}
-
-#endif // LL_GTK
-
LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_resolutions)
{
if (!mSupportedResolutions)
@@ -1368,33 +1112,28 @@ LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_reso
mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS];
mNumSupportedResolutions = 0;
- SDL_Rect **modes = SDL_ListModes(NULL, SDL_OPENGL | SDL_FULLSCREEN);
- if ( (modes != NULL) && (modes != ((SDL_Rect **) -1)) )
+ // <FS:ND> Use display no from mWindow/mSurface here?
+ int max = SDL_GetNumDisplayModes(0);
+ max = llclamp( max, 0, MAX_NUM_RESOLUTIONS );
+
+ for( int i =0; i < max; ++i )
{
- int count = 0;
- while (*modes && count<MAX_NUM_RESOLUTIONS) // they're sorted biggest to smallest, so find end...
- {
- modes++;
- count++;
- }
+ SDL_DisplayMode mode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 };
+ if (SDL_GetDisplayMode( 0 , i, &mode) != 0)
+ continue;
- while (count--)
+ int w = mode.w;
+ int h = mode.h;
+ if ((w >= 800) && (h >= 600))
{
- modes--;
- SDL_Rect *r = *modes;
- int w = r->w;
- int h = r->h;
- if ((w >= 800) && (h >= 600))
+ // make sure we don't add the same resolution multiple times!
+ if ( (mNumSupportedResolutions == 0) ||
+ ((mSupportedResolutions[mNumSupportedResolutions-1].mWidth != w) &&
+ (mSupportedResolutions[mNumSupportedResolutions-1].mHeight != h)) )
{
- // make sure we don't add the same resolution multiple times!
- if ( (mNumSupportedResolutions == 0) ||
- ((mSupportedResolutions[mNumSupportedResolutions-1].mWidth != w) &&
- (mSupportedResolutions[mNumSupportedResolutions-1].mHeight != h)) )
- {
- mSupportedResolutions[mNumSupportedResolutions].mWidth = w;
- mSupportedResolutions[mNumSupportedResolutions].mHeight = h;
- mNumSupportedResolutions++;
- }
+ mSupportedResolutions[mNumSupportedResolutions].mWidth = w;
+ mSupportedResolutions[mNumSupportedResolutions].mHeight = h;
+ mNumSupportedResolutions++;
}
}
}
@@ -1404,157 +1143,83 @@ LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_reso
return mSupportedResolutions;
}
-BOOL LLWindowSDL::convertCoords(LLCoordGL from, LLCoordWindow *to)
+bool LLWindowSDL::convertCoords(LLCoordGL from, LLCoordWindow *to) const
{
if (!to)
- return FALSE;
+ return false;
to->mX = from.mX;
- to->mY = mWindow->h - from.mY - 1;
+ to->mY = mSurface->h - from.mY - 1;
- return TRUE;
+ return true;
}
-BOOL LLWindowSDL::convertCoords(LLCoordWindow from, LLCoordGL* to)
+bool LLWindowSDL::convertCoords(LLCoordWindow from, LLCoordGL* to) const
{
if (!to)
- return FALSE;
+ return false;
to->mX = from.mX;
- to->mY = mWindow->h - from.mY - 1;
+ to->mY = mSurface->h - from.mY - 1;
- return TRUE;
+ return true;
}
-BOOL LLWindowSDL::convertCoords(LLCoordScreen from, LLCoordWindow* to)
+bool LLWindowSDL::convertCoords(LLCoordScreen from, LLCoordWindow* to) const
{
if (!to)
- return FALSE;
+ return false;
// 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)
+bool LLWindowSDL::convertCoords(LLCoordWindow from, LLCoordScreen *to) const
{
if (!to)
- return FALSE;
+ return false;
// 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)
+bool LLWindowSDL::convertCoords(LLCoordScreen from, LLCoordGL *to) const
{
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)
+bool LLWindowSDL::convertCoords(LLCoordGL from, LLCoordScreen *to) const
{
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();
OSMessageBox(text, caption, type);
+
+ // This is so catastrophic > bail as fast as possible. Otherwise the viewer can be stuck in a perpetual state of startup pain
+ std::terminate();
}
-BOOL LLWindowSDL::SDLReallyCaptureInput(BOOL capture)
+bool LLWindowSDL::SDLReallyCaptureInput(bool capture)
{
- // note: this used to be safe to call nestedly, but in the
- // end that's not really a wise usage pattern, so don't.
-
- if (capture)
- mReallyCapturedCount = 1;
- else
- mReallyCapturedCount = 0;
-
- SDL_GrabMode wantmode, newmode;
- if (mReallyCapturedCount <= 0) // uncapture
- {
- wantmode = SDL_GRAB_OFF;
- } else // capture
- {
- wantmode = SDL_GRAB_ON;
- }
-
- if (mReallyCapturedCount < 0) // yuck, imbalance.
- {
- mReallyCapturedCount = 0;
- LL_WARNS() << "ReallyCapture count was < 0" << LL_ENDL;
- }
-
- if (!mFullscreen) /* only bother if we're windowed anyway */
- {
-#if LL_X11
- if (mSDL_Display)
- {
- /* we dirtily mix raw X11 with SDL so that our pointer
- isn't (as often) constrained to the limits of the
- window while grabbed, which feels nicer and
- hopefully eliminates some reported 'sticky pointer'
- problems. We use raw X11 instead of
- SDL_WM_GrabInput() because the latter constrains
- the pointer to the window and also steals all
- *keyboard* input from the window manager, which was
- frustrating users. */
- int result;
- if (wantmode == SDL_GRAB_ON)
- {
- //LL_INFOS() << "X11 POINTER GRABBY" << LL_ENDL;
- //newmode = SDL_WM_GrabInput(wantmode);
- maybe_lock_display();
- result = XGrabPointer(mSDL_Display, mSDL_XWindowID,
- True, 0, GrabModeAsync,
- GrabModeAsync,
- None, None, CurrentTime);
- maybe_unlock_display();
- if (GrabSuccess == result)
- newmode = SDL_GRAB_ON;
- else
- newmode = SDL_GRAB_OFF;
- } else if (wantmode == SDL_GRAB_OFF)
- {
- //LL_INFOS() << "X11 POINTER UNGRABBY" << LL_ENDL;
- newmode = SDL_GRAB_OFF;
- //newmode = SDL_WM_GrabInput(SDL_GRAB_OFF);
-
- maybe_lock_display();
- XUngrabPointer(mSDL_Display, CurrentTime);
- // Make sure the ungrab happens RIGHT NOW.
- XSync(mSDL_Display, False);
- maybe_unlock_display();
- } else
- {
- newmode = SDL_GRAB_QUERY; // neutral
- }
- } else // not actually running on X11, for some reason
- newmode = wantmode;
-#endif // LL_X11
- } else {
- // pretend we got what we wanted, when really we don't care.
- newmode = wantmode;
- }
+ if (!mFullscreen && mWindow ) /* only bother if we're windowed anyway */
+ SDL_SetWindowGrab( mWindow, capture?SDL_TRUE:SDL_FALSE);
- // return boolean success for whether we ended up in the desired state
- return (capture && SDL_GRAB_ON==newmode) ||
- (!capture && SDL_GRAB_OFF==newmode);
+ return capture;
}
-U32 LLWindowSDL::SDLCheckGrabbyKeys(SDLKey keysym, BOOL gain)
+U32 LLWindowSDL::SDLCheckGrabbyKeys(U32 keysym, bool gain)
{
/* part of the fix for SL-13243: Some popular window managers like
to totally eat alt-drag for the purposes of moving windows. We
@@ -1572,16 +1237,16 @@ U32 LLWindowSDL::SDLCheckGrabbyKeys(SDLKey keysym, BOOL gain)
U32 mask = 0;
switch (keysym)
{
- case SDLK_LALT:
- mask = 1U << 0; break;
- case SDLK_RALT:
- mask = 1U << 1; break;
- case SDLK_LCTRL:
- mask = 1U << 2; break;
- case SDLK_RCTRL:
- mask = 1U << 3; break;
- default:
- break;
+ case SDLK_LALT:
+ mask = 1U << 0; break;
+ case SDLK_RALT:
+ mask = 1U << 1; break;
+ case SDLK_LCTRL:
+ mask = 1U << 2; break;
+ case SDLK_RCTRL:
+ mask = 1U << 3; break;
+ default:
+ break;
}
if (gain)
@@ -1598,7 +1263,6 @@ U32 LLWindowSDL::SDLCheckGrabbyKeys(SDLKey keysym, BOOL gain)
void check_vm_bloat()
{
-#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");
@@ -1613,7 +1277,7 @@ void check_vm_bloat()
ssize_t res;
size_t dummy;
- char *ptr = NULL;
+ char *ptr = nullptr;
for (int i=0; i<22; ++i) // parse past the values we don't want
{
res = getdelim(&ptr, &dummy, ' ', fp);
@@ -1623,7 +1287,7 @@ void check_vm_bloat()
goto finally;
}
free(ptr);
- ptr = NULL;
+ ptr = nullptr;
}
// 23rd space-delimited entry is vsize
res = getdelim(&ptr, &dummy, ' ', fp);
@@ -1635,7 +1299,7 @@ void check_vm_bloat()
}
this_vm_size = atoll(ptr);
free(ptr);
- ptr = NULL;
+ ptr = nullptr;
// 24th space-delimited entry is RSS
res = getdelim(&ptr, &dummy, ' ', fp);
llassert(ptr);
@@ -1646,12 +1310,11 @@ void check_vm_bloat()
}
this_rss_size = getpagesize() * atoll(ptr);
free(ptr);
- ptr = NULL;
+ ptr = nullptr;
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)
+ if (llabs(last_vm_size - this_vm_size) > significant_vm_difference)
{
if (this_vm_size > last_vm_size)
{
@@ -1663,8 +1326,7 @@ void check_vm_bloat()
}
}
- if (llabs(last_rss_size - this_rss_size) >
- significant_rss_difference)
+ if (llabs(last_rss_size - this_rss_size) > significant_rss_difference)
{
if (this_rss_size > last_rss_size)
{
@@ -1680,167 +1342,146 @@ void check_vm_bloat()
last_vm_size = this_vm_size;
finally:
- if (NULL != ptr)
- {
+ if (ptr)
free(ptr);
- ptr = NULL;
- }
fclose(fp);
}
-#endif // LL_LINUX
}
// virtual
void LLWindowSDL::processMiscNativeEvents()
{
-#if LL_GTK
- // Pump GTK events to avoid starvation for:
- // * DBUS servicing
- // * Anything else which quietly hooks into the default glib/GTK loop
- if (ll_try_gtk_init())
- {
- // Yuck, Mozilla's GTK callbacks play with the locale - push/pop
- // the locale to protect it, as exotic/non-C locales
- // causes our code lots of general critical weirdness
- // and crashness. (SL-35450)
- static std::string saved_locale;
- saved_locale = ll_safe_string(setlocale(LC_ALL, NULL));
-
- // Pump until we've nothing left to do or passed 1/15th of a
- // second pumping for this frame.
- static LLTimer pump_timer;
- pump_timer.reset();
- pump_timer.setTimerExpirySec(1.0f / 15.0f);
- do {
- // Always do at least one non-blocking pump
- gtk_main_iteration_do(FALSE);
- } while (gtk_events_pending() &&
- !pump_timer.hasExpired());
-
- setlocale(LC_ALL, saved_locale.c_str() );
- }
-#endif // LL_GTK
+ // 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());
// hack - doesn't belong here - but this is just for debugging
if (getenv("LL_DEBUG_BLOAT"))
- {
check_vm_bloat();
- }
}
-void LLWindowSDL::gatherInput()
+void LLWindowSDL::gatherInput(bool app_has_focus)
{
- const Uint32 CLICK_THRESHOLD = 300; // milliseconds
- static int leftClick = 0;
- static int rightClick = 0;
- static Uint32 lastLeftDown = 0;
- static Uint32 lastRightDown = 0;
- SDL_Event event;
+ SDL_Event event;
// Handle all outstanding SDL events
while (SDL_PollEvent(&event))
{
switch (event.type)
{
+ case SDL_MOUSEWHEEL:
+ {
+ if( event.wheel.y != 0 )
+ {
+ mCallbacks->handleScrollWheel(this, -event.wheel.y);
+ }
+ if (event.wheel.x != 0)
+ {
+ mCallbacks->handleScrollHWheel(this, -event.wheel.x);
+ }
+ break;
+ }
+
case SDL_MOUSEMOTION:
{
- LLCoordWindow winCoord(event.button.x, event.button.y);
+ LLCoordWindow winCoord(event.motion.x, event.motion.y);
LLCoordGL openGlCoord;
convertCoords(winCoord, &openGlCoord);
- MASK mask = gKeyboard->currentMask(TRUE);
+ MASK mask = gKeyboard->currentMask(true);
mCallbacks->handleMouseMove(this, openGlCoord, mask);
break;
}
- case SDL_KEYDOWN:
- mKeyScanCode = event.key.keysym.scancode;
- mKeyVirtualKey = event.key.keysym.unicode;
- mKeyModifiers = event.key.keysym.mod;
+ case SDL_TEXTINPUT:
+ {
+ auto string = utf8str_to_utf16str( event.text.text );
+ mKeyModifiers = gKeyboard->currentMask( false );
- gKeyboard->handleKeyDown(event.key.keysym.sym, event.key.keysym.mod);
- // part of the fix for SL-13243
- if (SDLCheckGrabbyKeys(event.key.keysym.sym, TRUE) != 0)
- SDLReallyCaptureInput(TRUE);
+ for( auto key: string )
+ {
+ mKeyVirtualKey = key;
- if (event.key.keysym.unicode)
- {
- handleUnicodeUTF16(event.key.keysym.unicode,
- gKeyboard->currentMask(FALSE));
+ if( (MASK_CONTROL|MASK_ALT)&mKeyModifiers )
+ gKeyboard->handleKeyDown(mKeyVirtualKey, mKeyModifiers );
+ else
+ handleUnicodeUTF16( key, mKeyModifiers );
+ }
+ break;
}
+
+ case SDL_KEYDOWN:
+ mKeyVirtualKey = event.key.keysym.sym;
+ mKeyModifiers = event.key.keysym.mod;
+
+ // 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:
- mKeyScanCode = event.key.keysym.scancode;
- mKeyVirtualKey = event.key.keysym.unicode;
- mKeyModifiers = event.key.keysym.mod;
+ mKeyVirtualKey = event.key.keysym.sym;
+ mKeyModifiers = event.key.keysym.mod;
- if (SDLCheckGrabbyKeys(event.key.keysym.sym, FALSE) == 0)
- SDLReallyCaptureInput(FALSE); // part of the fix for SL-13243
+ // treat all possible Enter/Return keys the same
+ if (mKeyVirtualKey == SDLK_RETURN2 || mKeyVirtualKey == SDLK_KP_ENTER)
+ mKeyVirtualKey = SDLK_RETURN;
- gKeyboard->handleKeyUp(event.key.keysym.sym, event.key.keysym.mod);
- break;
+ if (SDLCheckGrabbyKeys(mKeyVirtualKey, false) == 0)
+ SDLReallyCaptureInput(false); // part of the fix for SL-13243
+
+ gKeyboard->handleKeyUp(mKeyVirtualKey,mKeyModifiers);
+ break;
case SDL_MOUSEBUTTONDOWN:
{
- bool isDoubleClick = false;
LLCoordWindow winCoord(event.button.x, event.button.y);
LLCoordGL openGlCoord;
convertCoords(winCoord, &openGlCoord);
- MASK mask = gKeyboard->currentMask(TRUE);
-
- if (event.button.button == SDL_BUTTON_LEFT) // SDL doesn't manage double clicking...
- {
- Uint32 now = SDL_GetTicks();
- if ((now - lastLeftDown) > CLICK_THRESHOLD)
- leftClick = 1;
- else
- {
- if (++leftClick >= 2)
- {
- leftClick = 0;
- isDoubleClick = true;
- }
- }
- lastLeftDown = now;
- }
- else if (event.button.button == SDL_BUTTON_RIGHT)
- {
- Uint32 now = SDL_GetTicks();
- if ((now - lastRightDown) > CLICK_THRESHOLD)
- rightClick = 1;
- else
- {
- if (++rightClick >= 2)
- {
- rightClick = 0;
- isDoubleClick = true;
- }
- }
- lastRightDown = now;
- }
+ MASK mask = gKeyboard->currentMask(true);
if (event.button.button == SDL_BUTTON_LEFT) // left
{
- if (isDoubleClick)
+ 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
+ else if (event.button.button == SDL_BUTTON_RIGHT)
{
- mCallbacks->handleRightMouseDown(this, openGlCoord, mask);
+ mCallbacks->handleRightMouseDown(this, openGlCoord, mask);
}
-
else if (event.button.button == SDL_BUTTON_MIDDLE) // middle
{
mCallbacks->handleMiddleMouseDown(this, openGlCoord, mask);
}
- else if (event.button.button == 4) // mousewheel up...thanks to X11 for making SDL consider these "buttons".
- mCallbacks->handleScrollWheel(this, -1);
- else if (event.button.button == 5) // mousewheel down...thanks to X11 for making SDL consider these "buttons".
- mCallbacks->handleScrollWheel(this, 1);
+ else
+ {
+ mCallbacks->handleOtherMouseDown(this, openGlCoord, mask, event.button.button);
+ }
break;
}
@@ -1850,86 +1491,70 @@ void LLWindowSDL::gatherInput()
LLCoordWindow winCoord(event.button.x, event.button.y);
LLCoordGL openGlCoord;
convertCoords(winCoord, &openGlCoord);
- MASK mask = gKeyboard->currentMask(TRUE);
+ MASK mask = gKeyboard->currentMask(true);
if (event.button.button == SDL_BUTTON_LEFT) // left
- mCallbacks->handleMouseUp(this, openGlCoord, mask);
+ {
+ mCallbacks->handleMouseUp(this, openGlCoord, mask);
+ }
else if (event.button.button == SDL_BUTTON_RIGHT) // right
- mCallbacks->handleRightMouseUp(this, openGlCoord, mask);
+ {
+ mCallbacks->handleRightMouseUp(this, openGlCoord, mask);
+ }
else if (event.button.button == SDL_BUTTON_MIDDLE) // middle
- mCallbacks->handleMiddleMouseUp(this, openGlCoord, mask);
- // don't handle mousewheel here...
-
- break;
- }
-
- case SDL_VIDEOEXPOSE: // VIDEOEXPOSE doesn't specify the damage, but hey, it's OpenGL...repaint the whole thing!
- mCallbacks->handlePaint(this, 0, 0, mWindow->w, mWindow->h);
- break;
-
- case SDL_VIDEORESIZE: // *FIX: handle this?
- {
- LL_INFOS() << "Handling a resize event: " << event.resize.w <<
- "x" << event.resize.h << LL_ENDL;
-
- S32 width = llmax(event.resize.w, (S32)mMinWindowWidth);
- S32 height = llmax(event.resize.h, (S32)mMinWindowHeight);
-
- // *FIX: I'm not sure this is necessary!
- mWindow = SDL_SetVideoMode(width, height, 32, mSDLFlags);
- if (!mWindow)
- {
- // *FIX: More informative dialog?
- LL_INFOS() << "Could not recreate context after resize! Quitting..." << LL_ENDL;
- if(mCallbacks->handleCloseRequest(this))
{
- // Get the app to initiate cleanup.
- mCallbacks->handleQuit(this);
- // The app is responsible for calling destroyWindow when done with GL
+ mCallbacks->handleMiddleMouseUp(this, openGlCoord, mask);
+ }
+ else
+ {
+ mCallbacks->handleOtherMouseUp(this, openGlCoord, mask, event.button.button);
}
- break;
- }
- mCallbacks->handleResize(this, width, height);
break;
}
- case SDL_ACTIVEEVENT:
- if (event.active.state & SDL_APPINPUTFOCUS)
- {
- // Note that for SDL (particularly on X11), keyboard
- // and mouse focus are independent things. Here we are
- // tracking keyboard focus state changes.
-
- // We have to do our own state massaging because SDL
- // can send us two unfocus events in a row for example,
- // which confuses the focus code [SL-24071].
- if (event.active.gain != mHaveInputFocus)
- {
- mHaveInputFocus = !!event.active.gain;
- if (mHaveInputFocus)
- mCallbacks->handleFocus(this);
- else
- mCallbacks->handleFocusLost(this);
- }
- }
- if (event.active.state & SDL_APPACTIVE)
- {
- // Change in iconification/minimization state.
- if ((!event.active.gain) != mIsMinimized)
+ case SDL_WINDOWEVENT:
{
- mIsMinimized = (!event.active.gain);
+ 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->handleActivate(this, !mIsMinimized);
- LL_INFOS() << "SDL deiconification state switched to " << BOOL(event.active.gain) << LL_ENDL;
- }
- else
- {
- LL_INFOS() << "Ignored bogus redundant SDL deiconification state switch to " << BOOL(event.active.gain) << LL_ENDL;
- }
+ mSurface = SDL_GetWindowSurface(mWindow);
+ mCallbacks->handleResize(this, width, height);
+ 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;
-
+ }
case SDL_QUIT:
if(mCallbacks->handleCloseRequest(this))
{
@@ -1938,28 +1563,26 @@ void LLWindowSDL::gatherInput()
// The app is responsible for calling destroyWindow when done with GL
}
break;
- default:
- //LL_INFOS() << "Unhandled SDL event type " << event.type << LL_ENDL;
- break;
+ default:
+ LLGameControl::handleEvent(event, app_has_focus);
+ break;
}
}
updateCursor();
-#if LL_X11
// This is a good time to stop flashing the icon if our mFlashTimer has
// expired.
if (mFlashing && mFlashTimer.hasExpired())
{
- x11_set_urgent(FALSE);
- mFlashing = FALSE;
+ SDL_FlashWindow(mWindow, SDL_FLASH_CANCEL);
+ mFlashing = false;
}
-#endif // LL_X11
}
static SDL_Cursor *makeSDLCursorFromBMP(const char *filename, int hotx, int hoty)
{
- SDL_Cursor *sdlcursor = NULL;
+ SDL_Cursor *sdlcursor = nullptr;
SDL_Surface *bmpsurface;
// Load cursor pixel data from BMP file
@@ -1968,21 +1591,21 @@ static SDL_Cursor *makeSDLCursorFromBMP(const char *filename, int hotx, int hoty
{
SDL_Surface *cursurface;
LL_DEBUGS() << "Loaded cursor file " << filename << " "
- << bmpsurface->w << "x" << bmpsurface->h << LL_ENDL;
+ << bmpsurface->w << "x" << bmpsurface->h << LL_ENDL;
cursurface = SDL_CreateRGBSurface (SDL_SWSURFACE,
- bmpsurface->w,
- bmpsurface->h,
- 32,
- SDL_SwapLE32(0xFFU),
- SDL_SwapLE32(0xFF00U),
- SDL_SwapLE32(0xFF0000U),
- SDL_SwapLE32(0xFF000000U));
- SDL_FillRect(cursurface, NULL, SDL_SwapLE32(0x00000000U));
+ bmpsurface->w,
+ bmpsurface->h,
+ 32,
+ SDL_SwapLE32(0xFFU),
+ SDL_SwapLE32(0xFF00U),
+ SDL_SwapLE32(0xFF0000U),
+ SDL_SwapLE32(0xFF000000U));
+ SDL_FillRect(cursurface, nullptr, SDL_SwapLE32(0x00000000U));
// Blit the cursor pixel data onto a 32-bit RGBA surface so we
// only have to cope with processing one type of pixel format.
- if (0 == SDL_BlitSurface(bmpsurface, NULL,
- cursurface, NULL))
+ if (0 == SDL_BlitSurface(bmpsurface, nullptr,
+ cursurface, nullptr))
{
// n.b. we already checked that width is a multiple of 8.
const int bitmap_bytes = (cursurface->w * cursurface->h) / 8;
@@ -1997,26 +1620,26 @@ static SDL_Cursor *makeSDLCursorFromBMP(const char *filename, int hotx, int hoty
for (i=0; i<cursurface->h; ++i) {
for (j=0; j<cursurface->w; ++j) {
U8 *pixelp =
- ((U8*)cursurface->pixels)
- + cursurface->pitch * i
- + j*cursurface->format->BytesPerPixel;
+ ((U8*)cursurface->pixels)
+ + cursurface->pitch * i
+ + j*cursurface->format->BytesPerPixel;
U8 srcred = pixelp[0];
U8 srcgreen = pixelp[1];
U8 srcblue = pixelp[2];
- BOOL mask_bit = (srcred != 200)
- || (srcgreen != 200)
- || (srcblue != 200);
- BOOL data_bit = mask_bit && (srcgreen <= 80);//not 0x80
+ bool mask_bit = (srcred != 200)
+ || (srcgreen != 200)
+ || (srcblue != 200);
+ bool data_bit = mask_bit && (srcgreen <= 80);//not 0x80
unsigned char bit_offset = (cursurface->w/8) * i
- + j/8;
+ + j/8;
cursor_data[bit_offset] |= (data_bit) << (7 - (j&7));
cursor_mask[bit_offset] |= (mask_bit) << (7 - (j&7));
}
}
sdlcursor = SDL_CreateCursor((Uint8*)cursor_data,
- (Uint8*)cursor_mask,
- cursurface->w, cursurface->h,
- hotx, hoty);
+ (Uint8*)cursor_mask,
+ cursurface->w, cursurface->h,
+ hotx, hoty);
delete[] cursor_data;
delete[] cursor_mask;
} else {
@@ -2033,12 +1656,6 @@ static SDL_Cursor *makeSDLCursorFromBMP(const char *filename, int hotx, int hoty
void LLWindowSDL::updateCursor()
{
- if (ATIbug) {
- // cursor-updating is very flaky when this bug is
- // present; do nothing.
- return;
- }
-
if (mCurrentCursor != mNextCursor)
{
if (mNextCursor < UI_CURSOR_COUNT)
@@ -2050,37 +1667,38 @@ void LLWindowSDL::updateCursor()
sdlcursor = mSDLCursors[UI_CURSOR_ARROW];
if (sdlcursor)
SDL_SetCursor(sdlcursor);
- } else {
+
+ mCurrentCursor = mNextCursor;
+ }
+ else
+ {
LL_WARNS() << "Tried to set invalid cursor number " << mNextCursor << LL_ENDL;
}
- mCurrentCursor = mNextCursor;
}
}
void LLWindowSDL::initCursors()
{
- int i;
// Blank the cursor pointer array for those we may miss.
- for (i=0; i<UI_CURSOR_COUNT; ++i)
- {
- mSDLCursors[i] = NULL;
- }
+ 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] = makeSDLCursorFromBMP("llarrow.BMP",0,0);
- mSDLCursors[UI_CURSOR_WAIT] = makeSDLCursorFromBMP("wait.BMP",12,15);
- mSDLCursors[UI_CURSOR_HAND] = makeSDLCursorFromBMP("hand.BMP",7,10);
- mSDLCursors[UI_CURSOR_IBEAM] = makeSDLCursorFromBMP("ibeam.BMP",15,16);
- mSDLCursors[UI_CURSOR_CROSS] = makeSDLCursorFromBMP("cross.BMP",16,14);
- mSDLCursors[UI_CURSOR_SIZENWSE] = makeSDLCursorFromBMP("sizenwse.BMP",14,17);
- mSDLCursors[UI_CURSOR_SIZENESW] = makeSDLCursorFromBMP("sizenesw.BMP",17,17);
- mSDLCursors[UI_CURSOR_SIZEWE] = makeSDLCursorFromBMP("sizewe.BMP",16,14);
- mSDLCursors[UI_CURSOR_SIZENS] = makeSDLCursorFromBMP("sizens.BMP",17,16);
- mSDLCursors[UI_CURSOR_SIZEALL] = makeSDLCursorFromBMP("sizeall.BMP", 17, 17);
- mSDLCursors[UI_CURSOR_NO] = makeSDLCursorFromBMP("llno.BMP",8,8);
- mSDLCursors[UI_CURSOR_WORKING] = makeSDLCursorFromBMP("working.BMP",12,15);
+ mSDLCursors[UI_CURSOR_ARROW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
+ 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_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_TOOLGRAB] = makeSDLCursorFromBMP("lltoolgrab.BMP",2,13);
mSDLCursors[UI_CURSOR_TOOLLAND] = makeSDLCursorFromBMP("lltoolland.BMP",1,6);
mSDLCursors[UI_CURSOR_TOOLFOCUS] = makeSDLCursorFromBMP("lltoolfocus.BMP",8,5);
@@ -2113,32 +1731,28 @@ void LLWindowSDL::initCursors()
mSDLCursors[UI_CURSOR_TOOLPATHFINDING_PATH_END] = makeSDLCursorFromBMP("lltoolpathfindingpathend.BMP", 16, 16);
mSDLCursors[UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD] = makeSDLCursorFromBMP("lltoolpathfindingpathendadd.BMP", 16, 16);
mSDLCursors[UI_CURSOR_TOOLNO] = makeSDLCursorFromBMP("llno.BMP",8,8);
-
- if (getenv("LL_ATI_MOUSE_CURSOR_BUG") != NULL) {
- LL_INFOS() << "Disabling cursor updating due to LL_ATI_MOUSE_CURSOR_BUG" << LL_ENDL;
- ATIbug = true;
- }
}
void LLWindowSDL::quitCursors()
{
- int i;
if (mWindow)
{
- for (i=0; i<UI_CURSOR_COUNT; ++i)
+ for (int i=0; i<UI_CURSOR_COUNT; ++i)
{
if (mSDLCursors[i])
{
SDL_FreeCursor(mSDLCursors[i]);
- mSDLCursors[i] = NULL;
+ 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;
}
}
@@ -2165,9 +1779,9 @@ void LLWindowSDL::hideCursor()
if(!mCursorHidden)
{
// LL_INFOS() << "hideCursor: hiding" << LL_ENDL;
- mCursorHidden = TRUE;
- mHideCursorPermanent = TRUE;
- SDL_ShowCursor(0);
+ mCursorHidden = true;
+ mHideCursorPermanent = true;
+ SDL_ShowCursor(SDL_DISABLE);
}
else
{
@@ -2180,9 +1794,9 @@ void LLWindowSDL::showCursor()
if(mCursorHidden)
{
// LL_INFOS() << "showCursor: showing" << LL_ENDL;
- mCursorHidden = FALSE;
- mHideCursorPermanent = FALSE;
- SDL_ShowCursor(1);
+ mCursorHidden = false;
+ mHideCursorPermanent = false;
+ SDL_ShowCursor(SDL_ENABLE);
}
else
{
@@ -2203,12 +1817,10 @@ void LLWindowSDL::hideCursorUntilMouseMove()
if (!mHideCursorPermanent)
{
hideCursor();
- mHideCursorPermanent = FALSE;
+ mHideCursorPermanent = false;
}
}
-
-
//
// LLSplashScreenSDL - I don't think we'll bother to implement this; it's
// fairly obsolete at this point.
@@ -2233,133 +1845,51 @@ void LLSplashScreenSDL::hideImpl()
{
}
-
-
-#if LL_GTK
-static void response_callback (GtkDialog *dialog,
- gint arg1,
- gpointer user_data)
-{
- gint *response = (gint*)user_data;
- *response = arg1;
- gtk_widget_destroy(GTK_WIDGET(dialog));
- gtk_main_quit();
-}
-
S32 OSMessageBoxSDL(const std::string& text, const std::string& caption, U32 type)
{
- S32 rtn = OSBTN_CANCEL;
-
- if(gWindowImplementation != NULL)
- gWindowImplementation->beforeDialog();
+ SDL_MessageBoxData oData = { SDL_MESSAGEBOX_INFORMATION, nullptr, caption.c_str(), text.c_str(), 0, nullptr, nullptr };
+ SDL_MessageBoxButtonData btnOk[] = {{SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, OSBTN_OK, "OK" }};
+ SDL_MessageBoxButtonData btnOkCancel [] = {{SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, OSBTN_OK, "OK" }, {SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, OSBTN_CANCEL, "Cancel"} };
+ SDL_MessageBoxButtonData btnYesNo[] = { {SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, OSBTN_YES, "Yes" }, {SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, OSBTN_NO, "No"} };
- if (LLWindowSDL::ll_try_gtk_init())
+ switch (type)
{
- GtkWidget *win = NULL;
-
- LL_INFOS() << "Creating a dialog because we're in windowed mode and GTK is happy." << LL_ENDL;
-
- GtkDialogFlags flags = GTK_DIALOG_MODAL;
- GtkMessageType messagetype;
- GtkButtonsType buttons;
- switch (type)
- {
default:
case OSMB_OK:
- messagetype = GTK_MESSAGE_WARNING;
- buttons = GTK_BUTTONS_OK;
+ oData.flags = SDL_MESSAGEBOX_WARNING;
+ oData.buttons = btnOk;
+ oData.numbuttons = 1;
break;
case OSMB_OKCANCEL:
- messagetype = GTK_MESSAGE_QUESTION;
- buttons = GTK_BUTTONS_OK_CANCEL;
+ oData.flags = SDL_MESSAGEBOX_INFORMATION;
+ oData.buttons = btnOkCancel;
+ oData.numbuttons = 2;
break;
case OSMB_YESNO:
- messagetype = GTK_MESSAGE_QUESTION;
- buttons = GTK_BUTTONS_YES_NO;
+ oData.flags = SDL_MESSAGEBOX_INFORMATION;
+ oData.buttons = btnYesNo;
+ oData.numbuttons = 2;
break;
- }
- win = gtk_message_dialog_new(NULL, flags, messagetype, buttons, "%s",
- text.c_str());
-
-# if LL_X11
- // Make GTK tell the window manager to associate this
- // dialog with our non-GTK SDL window, which should try
- // to keep it on top etc.
- if (gWindowImplementation &&
- gWindowImplementation->mSDL_XWindowID != None)
- {
- gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin
- GdkWindow *gdkwin = gdk_window_foreign_new(gWindowImplementation->mSDL_XWindowID);
- gdk_window_set_transient_for(GTK_WIDGET(win)->window,
- gdkwin);
- }
-# endif //LL_X11
-
- gtk_window_set_position(GTK_WINDOW(win),
- GTK_WIN_POS_CENTER_ON_PARENT);
-
- gtk_window_set_type_hint(GTK_WINDOW(win),
- GDK_WINDOW_TYPE_HINT_DIALOG);
-
- if (!caption.empty())
- gtk_window_set_title(GTK_WINDOW(win), caption.c_str());
-
- gint response = GTK_RESPONSE_NONE;
- g_signal_connect (win,
- "response",
- G_CALLBACK (response_callback),
- &response);
-
- // we should be able to use a gtk_dialog_run(), but it's
- // apparently not written to exist in a world without a higher
- // gtk_main(), so we manage its signal/destruction outselves.
- gtk_widget_show_all (win);
- gtk_main();
-
- //LL_INFOS() << "response: " << response << LL_ENDL;
- switch (response)
- {
- case GTK_RESPONSE_OK: rtn = OSBTN_OK; break;
- case GTK_RESPONSE_YES: rtn = OSBTN_YES; break;
- case GTK_RESPONSE_NO: rtn = OSBTN_NO; break;
- case GTK_RESPONSE_APPLY: rtn = OSBTN_OK; break;
- case GTK_RESPONSE_NONE:
- case GTK_RESPONSE_CANCEL:
- case GTK_RESPONSE_CLOSE:
- case GTK_RESPONSE_DELETE_EVENT:
- default: rtn = OSBTN_CANCEL;
- }
- }
- else
- {
- LL_INFOS() << "MSGBOX: " << caption << ": " << text << LL_ENDL;
- LL_INFOS() << "Skipping dialog because we're in fullscreen mode or GTK is not happy." << LL_ENDL;
- rtn = OSBTN_OK;
}
- if(gWindowImplementation != NULL)
- gWindowImplementation->afterDialog();
-
- return rtn;
+ int btn{0};
+ if( 0 == SDL_ShowMessageBox( &oData, &btn ) )
+ return btn;
+ return OSBTN_CANCEL;
}
-static void color_changed_callback(GtkWidget *widget,
- gpointer user_data)
+bool LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b)
{
- GtkColorSelection *colorsel = GTK_COLOR_SELECTION(widget);
- GdkColor *colorp = (GdkColor*)user_data;
-
- gtk_color_selection_get_current_color(colorsel, colorp);
+ return false;
}
-
/*
Make the raw keyboard data available - used to poke through to LLQtWebKit so
that Qt/Webkit has access to the virtual keycodes etc. that it needs
*/
-LLSD LLWindowSDL::getNativeKeyData()
+LLSD LLWindowSDL::getNativeKeyData() const
{
- LLSD result = LLSD::emptyMap();
+ LLSD result = LLSD::emptyMap();
U32 modifiers = 0; // pretend-native modifiers... oh what a tangled web we weave!
@@ -2377,130 +1907,11 @@ LLSD LLWindowSDL::getNativeKeyData()
// *todo: test ALTs - I don't have a case for testing these. Do you?
// *todo: NUM? - I don't care enough right now (and it's not a GDK modifier).
- result["scan_code"] = (S32)mKeyScanCode;
- result["virtual_key"] = (S32)mKeyVirtualKey;
+ result["virtual_key"] = (S32)mKeyVirtualKey;
+ result["virtual_key_win"] = (S32)LLKeyboardSDL::mapSDL2toWin( mKeyVirtualKey );
result["modifiers"] = (S32)modifiers;
-
- return result;
-}
-
-
-BOOL LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b)
-{
- BOOL rtn = FALSE;
-
- beforeDialog();
-
- if (ll_try_gtk_init())
- {
- GtkWidget *win = NULL;
-
- win = gtk_color_selection_dialog_new(NULL);
-
-# if LL_X11
- // Get GTK to tell the window manager to associate this
- // dialog with our non-GTK SDL window, which should try
- // to keep it on top etc.
- if (mSDL_XWindowID != None)
- {
- gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin
- GdkWindow *gdkwin = gdk_window_foreign_new(mSDL_XWindowID);
- gdk_window_set_transient_for(GTK_WIDGET(win)->window,
- gdkwin);
- }
-# endif //LL_X11
-
- GtkColorSelection *colorsel = GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG(win)->colorsel);
-
- GdkColor color, orig_color;
- orig_color.pixel = 0;
- orig_color.red = guint16(65535 * *r);
- orig_color.green= guint16(65535 * *g);
- orig_color.blue = guint16(65535 * *b);
- color = orig_color;
-
- gtk_color_selection_set_previous_color (colorsel, &color);
- gtk_color_selection_set_current_color (colorsel, &color);
- gtk_color_selection_set_has_palette (colorsel, TRUE);
- gtk_color_selection_set_has_opacity_control(colorsel, FALSE);
-
- gint response = GTK_RESPONSE_NONE;
- g_signal_connect (win,
- "response",
- G_CALLBACK (response_callback),
- &response);
-
- g_signal_connect (G_OBJECT (colorsel), "color_changed",
- G_CALLBACK (color_changed_callback),
- &color);
-
- gtk_window_set_modal(GTK_WINDOW(win), TRUE);
- gtk_widget_show_all(win);
- // hide the help button - we don't service it.
- gtk_widget_hide(GTK_COLOR_SELECTION_DIALOG(win)->help_button);
- gtk_main();
-
- if (response == GTK_RESPONSE_OK &&
- (orig_color.red != color.red
- || orig_color.green != color.green
- || orig_color.blue != color.blue) )
- {
- *r = color.red / 65535.0f;
- *g = color.green / 65535.0f;
- *b = color.blue / 65535.0f;
- rtn = TRUE;
- }
- }
-
- afterDialog();
-
- return rtn;
-}
-#else
-S32 OSMessageBoxSDL(const std::string& text, const std::string& caption, U32 type)
-{
- LL_INFOS() << "MSGBOX: " << caption << ": " << text << LL_ENDL;
- return 0;
-}
-
-BOOL LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b)
-{
- return (FALSE);
-}
-#endif // LL_GTK
-
-#if LL_LINUX
-// extracted from spawnWebBrowser for clarity and to eliminate
-// compiler confusion regarding close(int fd) vs. LLWindow::close()
-void exec_cmd(const std::string& cmd, const std::string& arg)
-{
- char* const argv[] = {(char*)cmd.c_str(), (char*)arg.c_str(), NULL};
- fflush(NULL);
- pid_t pid = fork();
- if (pid == 0)
- { // child
- // disconnect from stdin/stdout/stderr, or child will
- // keep our output pipe undesirably alive if it outlives us.
- close(0);
- close(1);
- close(2);
- // end ourself by running the command
- execv(cmd.c_str(), argv); /* Flawfinder: ignore */
- // if execv returns at all, there was a problem.
- LL_WARNS() << "execv failure when trying to start " << cmd << LL_ENDL;
- _exit(1); // _exit because we don't want atexit() clean-up!
- } else {
- if (pid > 0)
- {
- // parent - wait for child to die
- int childExitStatus;
- waitpid(pid, &childExitStatus, 0);
- } else {
- LL_WARNS() << "fork failure." << LL_ENDL;
- }
- }
+ return result;
}
-#endif
// Open a URL with the user's default web browser.
// Must begin with protocol identifier.
@@ -2525,56 +1936,17 @@ void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async)
LL_INFOS() << "spawn_web_browser: " << escaped_url << LL_ENDL;
-#if LL_LINUX
-# if LL_X11
- if (mSDL_Display)
+ if (SDL_OpenURL(escaped_url.c_str()) != 0)
{
- maybe_lock_display();
- // Just in case - before forking.
- XSync(mSDL_Display, False);
- maybe_unlock_display();
+ LL_WARNS() << "spawn_web_browser failed with error: " << SDL_GetError() << LL_ENDL;
}
-# endif // LL_X11
-
- std::string cmd, arg;
- cmd = gDirUtilp->getAppRODataDir();
- cmd += gDirUtilp->getDirDelimiter();
- cmd += "etc";
- cmd += gDirUtilp->getDirDelimiter();
- cmd += "launch_url.sh";
- arg = escaped_url;
- exec_cmd(cmd, arg);
-#endif // LL_LINUX
LL_INFOS() << "spawn_web_browser returning." << LL_ENDL;
}
-
void *LLWindowSDL::getPlatformWindow()
{
-#if LL_GTK && LL_LLMOZLIB_ENABLED
- if (LLWindowSDL::ll_try_gtk_init())
- {
- maybe_lock_display();
-
- GtkWidget *owin = gtk_window_new(GTK_WINDOW_POPUP);
- // Why a layout widget? A MozContainer would be ideal, but
- // it involves exposing Mozilla headers to mozlib-using apps.
- // A layout widget with a GtkWindow parent has the desired
- // properties of being plain GTK, having a window, and being
- // derived from a GtkContainer.
- GtkWidget *rtnw = gtk_layout_new(NULL, NULL);
- gtk_container_add(GTK_CONTAINER(owin), rtnw);
- gtk_widget_realize(rtnw);
- GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(rtnw), GTK_NO_WINDOW);
-
- maybe_unlock_display();
-
- return rtnw;
- }
-#endif // LL_GTK && LL_LLMOZLIB_ENABLED
- // Unixoid mozilla really needs GTK.
- return NULL;
+ return nullptr;
}
void LLWindowSDL::bringToFront()
@@ -2582,15 +1954,10 @@ void LLWindowSDL::bringToFront()
// This is currently used when we are 'launched' to a specific
// map position externally.
LL_INFOS() << "bringToFront" << LL_ENDL;
-#if LL_X11
- if (mSDL_Display && !mFullscreen)
+ if (mWindow && !mFullscreen)
{
- maybe_lock_display();
- XRaiseWindow(mSDL_Display, mSDL_XWindowID);
- XSync(mSDL_Display, False);
- maybe_unlock_display();
+ SDL_RaiseWindow(mWindow);
}
-#endif // LL_X11
}
//static
@@ -2613,8 +1980,8 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList()
// to use some of the fonts we want it to.
const bool elide_unicode_coverage = true;
std::vector<std::string> rtns;
- FcFontSet *fs = NULL;
- FcPattern *sortpat = NULL;
+ FcFontSet *fs = nullptr;
+ FcPattern *sortpat = nullptr;
LL_INFOS() << "Getting system font list from FontConfig..." << LL_ENDL;
@@ -2623,7 +1990,7 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList()
// of languages that can be displayed, but ensures that their
// preferred language is rendered from a single consistent font where
// possible.
- FL_Locale *locale = NULL;
+ FL_Locale *locale = nullptr;
FL_Success success = FL_FindLocale(&locale, FL_MESSAGES);
if (success != 0)
{
@@ -2634,10 +2001,10 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList()
LL_INFOS("AppInit") << "Variant " << locale->variant << LL_ENDL;
LL_INFOS() << "Preferring fonts of language: "
- << locale->lang
- << LL_ENDL;
+ << locale->lang
+ << LL_ENDL;
sort_order = "lang=" + std::string(locale->lang) + ":"
- + sort_order;
+ + sort_order;
}
}
FL_FreeLocale(&locale);
@@ -2654,8 +2021,7 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList()
{
// Sort the list of system fonts from most-to-least-desirable.
FcResult result;
- fs = FcFontSort(NULL, sortpat, elide_unicode_coverage,
- NULL, &result);
+ fs = FcFontSort(nullptr, sortpat, elide_unicode_coverage, nullptr, &result);
FcPatternDestroy(sortpat);
}
@@ -2668,10 +2034,7 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList()
for (int i=0; i<fs->nfont; ++i)
{
FcChar8 *filename;
- if (FcResultMatch == FcPatternGetString(fs->fonts[i],
- FC_FILE, 0,
- &filename)
- && filename)
+ if (FcResultMatch == FcPatternGetString(fs->fonts[i], FC_FILE, 0, &filename) && filename)
{
rtns.push_back(std::string((const char*)filename));
if (rtns.size() >= max_font_count_cutoff)
@@ -2682,16 +2045,27 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList()
}
LL_DEBUGS() << "Using font list: " << LL_ENDL;
- for (std::vector<std::string>::iterator it = rtns.begin();
- it != rtns.end();
- ++it)
+ for (auto it = rtns.begin(); it != rtns.end(); ++it)
{
LL_DEBUGS() << " file: " << *it << LL_ENDL;
}
+
LL_INFOS() << "Using " << rtns.size() << "/" << found_font_count << " system fonts." << LL_ENDL;
rtns.push_back(final_fallback);
return rtns;
}
-#endif // LL_SDL
+void LLWindowSDL::setLanguageTextInput(const LLCoordGL& position)
+{
+ LLCoordWindow win_pos;
+ convertCoords( position, &win_pos );
+
+ SDL_Rect r;
+ r.x = win_pos.mX;
+ r.y = win_pos.mY;
+ r.w = 500;
+ r.h = 16;
+
+ SDL_SetTextInputRect(&r);
+}
diff --git a/indra/llwindow/llwindowsdl.h b/indra/llwindow/llwindowsdl.h
index e96fce92f5..974ba69b61 100644
--- a/indra/llwindow/llwindowsdl.h
+++ b/indra/llwindow/llwindowsdl.h
@@ -11,7 +11,6 @@
* 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.
@@ -24,21 +23,20 @@
* $/LicenseInfo$
*/
-#ifndef LL_LLWINDOWSDL_H
-#define LL_LLWINDOWSDL_H
+#ifndef LL_LLWINDOWSDL2_H
+#define LL_LLWINDOWSDL2_H
// Simple Directmedia Layer (http://libsdl.org/) implementation of LLWindow class
+#if LL_LINUX
#include "llwindow.h"
#include "lltimer.h"
-#include "SDL/SDL.h"
-#include "SDL/SDL_endian.h"
+#include "SDL2/SDL.h"
+#include "SDL2/SDL_endian.h"
-#if LL_X11
// get X11-specific headers for use in low-level stuff like copy-and-paste support
-#include "SDL/SDL_syswm.h"
-#endif
+#include "SDL2/SDL_syswm.h"
// AssertMacros.h does bad things.
#include "fix_macros.h"
@@ -46,126 +44,158 @@
#undef require
-class LLWindowSDL : public LLWindow
-{
+class LLWindowSDL : public LLWindow {
public:
- /*virtual*/ void show();
- /*virtual*/ void hide();
- /*virtual*/ void close();
- /*virtual*/ BOOL getVisible();
- /*virtual*/ BOOL getMinimized();
- /*virtual*/ BOOL getMaximized();
- /*virtual*/ BOOL maximize();
- /*virtual*/ void minimize();
- /*virtual*/ void restore();
- /*virtual*/ BOOL getFullscreen();
- /*virtual*/ BOOL getPosition(LLCoordScreen *position);
- /*virtual*/ BOOL getSize(LLCoordScreen *size);
- /*virtual*/ BOOL getSize(LLCoordWindow *size);
- /*virtual*/ BOOL setPosition(LLCoordScreen position);
- /*virtual*/ BOOL setSizeImpl(LLCoordScreen size);
- /*virtual*/ BOOL setSizeImpl(LLCoordWindow size);
- /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL);
- /*virtual*/ BOOL setCursorPosition(LLCoordWindow position);
- /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position);
- /*virtual*/ void showCursor();
- /*virtual*/ void hideCursor();
- /*virtual*/ void showCursorFromMouseMove();
- /*virtual*/ void hideCursorUntilMouseMove();
- /*virtual*/ BOOL isCursorHidden();
- /*virtual*/ void updateCursor();
- /*virtual*/ void captureMouse();
- /*virtual*/ void releaseMouse();
- /*virtual*/ void setMouseClipping( BOOL b );
- /*virtual*/ void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true);
-
- /*virtual*/ BOOL isClipboardTextAvailable();
- /*virtual*/ BOOL pasteTextFromClipboard(LLWString &dst);
- /*virtual*/ BOOL copyTextToClipboard(const LLWString & src);
-
- /*virtual*/ BOOL isPrimaryTextAvailable();
- /*virtual*/ BOOL pasteTextFromPrimary(LLWString &dst);
- /*virtual*/ BOOL copyTextToPrimary(const LLWString & src);
-
- /*virtual*/ void flashIcon(F32 seconds);
- /*virtual*/ F32 getGamma();
- /*virtual*/ BOOL setGamma(const F32 gamma); // Set the gamma
- /*virtual*/ U32 getFSAASamples();
- /*virtual*/ void setFSAASamples(const U32 samples);
- /*virtual*/ BOOL restoreGamma(); // Restore original gamma table (before updating gamma)
- /*virtual*/ ESwapMethod getSwapMethod() { return mSwapMethod; }
- /*virtual*/ void processMiscNativeEvents();
- /*virtual*/ void gatherInput();
- /*virtual*/ void swapBuffers();
- /*virtual*/ void restoreGLContext() {};
-
- /*virtual*/ void delayInputProcessing() { };
+ void show() override;
+ void hide() override;
+ void restore() override;
+
+ void close() override;
+
+ bool getVisible() const override;
+
+ bool getMinimized() const override;
+
+ bool getMaximized() const override;
+
+ bool maximize() override;
+ void minimize() override;
+
+ bool getPosition(LLCoordScreen *position) const override;
+
+ bool getSize(LLCoordScreen *size) const override;
+
+ bool getSize(LLCoordWindow *size) const override;
+
+ bool setPosition(LLCoordScreen position) override;
+
+ bool setSizeImpl(LLCoordScreen size) override;
+
+ bool setSizeImpl(LLCoordWindow size) override;
+
+ bool switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync,
+ const LLCoordScreen *const posp = NULL) override;
+
+ bool setCursorPosition(LLCoordWindow position) override;
+
+ bool getCursorPosition(LLCoordWindow *position) override;
+
+ void showCursor() override;
+ void hideCursor() override;
+ bool isCursorHidden() override;
+
+ void showCursorFromMouseMove() override;
+ void hideCursorUntilMouseMove() override;
+
+ void updateCursor() override;
+
+ void captureMouse() override;
+ void releaseMouse() override;
+
+ void setMouseClipping(bool b) override;
+
+ void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true) override;
+
+ bool isClipboardTextAvailable() override;
+ bool pasteTextFromClipboard(LLWString &dst) override;
+ bool copyTextToClipboard(const LLWString &src) override;
+ bool isPrimaryTextAvailable() override;
+ bool pasteTextFromPrimary(LLWString &dst) override;
+ bool copyTextToPrimary(const LLWString &src) override;
+
+ void flashIcon(F32 seconds) override;
+ void maybeStopFlashIcon();
+
+ F32 getGamma() const override;
+ bool setGamma(const F32 gamma) override; // Set the gamma
+ bool restoreGamma() override; // Restore original gamma table (before updating gamma)
+
+ U32 getFSAASamples() const override;
+ void setFSAASamples(const U32 samples) override;
+
+ void processMiscNativeEvents() override;
+
+ void gatherInput(bool app_has_focus) override;
+
+ void swapBuffers() override;
+
+ void restoreGLContext() {};
+
+ void delayInputProcessing() override {};
// handy coordinate space conversion routines
- /*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to);
- /*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordScreen *to);
- /*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordGL *to);
- /*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordWindow *to);
- /*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordGL *to);
- /*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordScreen *to);
+ bool convertCoords(LLCoordScreen from, LLCoordWindow *to) const override;
- /*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions);
- /*virtual*/ F32 getNativeAspectRatio();
- /*virtual*/ F32 getPixelAspectRatio();
- /*virtual*/ void setNativeAspectRatio(F32 ratio) { mOverrideAspectRatio = ratio; }
+ bool convertCoords(LLCoordWindow from, LLCoordScreen *to) const override;
- /*virtual*/ void beforeDialog();
- /*virtual*/ void afterDialog();
+ bool convertCoords(LLCoordWindow from, LLCoordGL *to) const override;
- /*virtual*/ BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b);
+ bool convertCoords(LLCoordGL from, LLCoordWindow *to) const override;
- /*virtual*/ void *getPlatformWindow();
- /*virtual*/ void bringToFront();
+ bool convertCoords(LLCoordScreen from, LLCoordGL *to) const override;
- /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async);
+ bool convertCoords(LLCoordGL from, LLCoordScreen *to) const override;
+
+ LLWindowResolution *getSupportedResolutions(S32 &num_resolutions) override;
+
+ F32 getNativeAspectRatio() override;
+
+ F32 getPixelAspectRatio() override;
+
+ void setNativeAspectRatio(F32 ratio) override { mOverrideAspectRatio = ratio; }
+
+ void beforeDialog() override;
+ void afterDialog() override;
+
+ bool dialogColorPicker(F32 *r, F32 *g, F32 *b) override;
+
+ void *getPlatformWindow() override;
+
+ void bringToFront() override;
+
+ void setLanguageTextInput(const LLCoordGL& pos) override;
+
+ void spawnWebBrowser(const std::string &escaped_url, bool async) override;
+
+ void setTitle(const std::string title) override;
static std::vector<std::string> getDynamicFallbackFontList();
- // Not great that these are public, but they have to be accessible
- // by non-class code and it's better than making them global.
-#if LL_X11
- Window mSDL_XWindowID;
- Display *mSDL_Display;
-#endif
- void (*Lock_Display)(void);
- void (*Unlock_Display)(void);
-
-#if LL_GTK
- // Lazily initialize and check the runtime GTK version for goodness.
- static bool ll_try_gtk_init(void);
-#endif // LL_GTK
-
-#if LL_X11
+ void (*Lock_Display)(void) = nullptr;
+ void (*Unlock_Display)(void) = nullptr;
+
static Window get_SDL_XWindowID(void);
- static Display* get_SDL_Display(void);
-#endif // LL_X11
+ static Display *get_SDL_Display(void);
+
+ void *createSharedContext() override;
+ void makeContextCurrent(void *context) override;
+ void destroySharedContext(void *context) override;
+ void toggleVSync(bool enable_vsync) override;
protected:
- LLWindowSDL(LLWindowCallbacks* callbacks,
- const std::string& title, int x, int y, int width, int height, U32 flags,
- BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl,
- BOOL ignore_pixel_depth, U32 fsaa_samples);
+ LLWindowSDL(LLWindowCallbacks *callbacks,
+ const std::string &title, const std::string& name, int x, int y, int width, int height, U32 flags,
+ bool fullscreen, bool clearBg, bool enable_vsync, bool use_gl,
+ bool ignore_pixel_depth, U32 fsaa_samples);
+
~LLWindowSDL();
- /*virtual*/ BOOL isValid();
- /*virtual*/ LLSD getNativeKeyData();
+ bool isValid() override;
+
+ LLSD getNativeKeyData() const override;
- void initCursors();
- void quitCursors();
- void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size);
+ void initCursors();
+ void quitCursors();
+
+ void moveWindow(const LLCoordScreen &position, const LLCoordScreen &size);
// Changes display resolution. Returns true if successful
- BOOL setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
+ bool setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
// Go back to last fullscreen display resolution.
- BOOL setFullscreenResolution();
+ bool setFullscreenResolution();
- BOOL shouldPostQuit() { return mPostQuit; }
+ bool shouldPostQuit() { return mPostQuit; }
protected:
//
@@ -173,47 +203,66 @@ protected:
//
// create or re-create the GL context/window. Called from the constructor and switchContext().
- BOOL createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync);
+ bool createContext(int x, int y, int width, int height, int bits, bool fullscreen, bool enable_vsync);
void destroyContext();
- void setupFailure(const std::string& text, const std::string& caption, U32 type);
- void fixWindowSize(void);
- U32 SDLCheckGrabbyKeys(SDLKey keysym, BOOL gain);
- BOOL SDLReallyCaptureInput(BOOL capture);
+
+ void setupFailure(const std::string &text, const std::string &caption, U32 type);
+
+ U32 SDLCheckGrabbyKeys(U32 keysym, bool gain);
+
+ bool SDLReallyCaptureInput(bool capture);
//
// Platform specific variables
//
- U32 mGrabbyKeyFlags;
- int mReallyCapturedCount;
- SDL_Surface * mWindow;
- std::string mWindowTitle;
- double mOriginalAspectRatio;
- BOOL mNeedsResize; // Constructor figured out the window is too big, it needs a resize.
- LLCoordScreen mNeedsResizeSize;
- F32 mOverrideAspectRatio;
- F32 mGamma;
- U32 mFSAASamples;
+ U32 mGrabbyKeyFlags = 0;
+
+ SDL_Window *mWindow = nullptr;
+ SDL_Surface *mSurface;
+ SDL_GLContext mContext;
+ SDL_Cursor *mSDLCursors[UI_CURSOR_COUNT];
- int mSDLFlags;
+ std::string mWindowTitle;
+ double mOriginalAspectRatio = 1.0f;
+ bool mNeedsResize = false; // Constructor figured out the window is too big, it needs a resize.
+ LLCoordScreen mNeedsResizeSize;
+ F32 mOverrideAspectRatio = 0.0f;
+ F32 mGamma = 0.0f;
+ U32 mFSAASamples = 0;
- SDL_Cursor* mSDLCursors[UI_CURSOR_COUNT];
- int mHaveInputFocus; /* 0=no, 1=yes, else unknown */
- int mIsMinimized; /* 0=no, 1=yes, else unknown */
+ int mHaveInputFocus = -1; /* 0=no, 1=yes, else unknown */
friend class LLWindowManager;
private:
-#if LL_X11
- void x11_set_urgent(BOOL urgent);
- BOOL mFlashing;
+ bool mFlashing = false;
LLTimer mFlashTimer;
-#endif //LL_X11
+ U32 mKeyVirtualKey = 0;
+ U32 mKeyModifiers = KMOD_NONE;
- U32 mKeyScanCode;
- U32 mKeyVirtualKey;
- SDLMod mKeyModifiers;
-};
+ enum EServerProtocol{ X11, Wayland, Unknown };
+ EServerProtocol mServerProtocol = Unknown;
+ struct {
+ Window mXWindowID = None;
+ Display *mDisplay = nullptr;
+ } mX11Data;
+
+ // Wayland
+ struct {
+ wl_surface *mSurface = nullptr;
+ uint64_t mLastFrameEvent = 0;
+ } mWaylandData;
+
+ bool isWaylandWindowNotDrawing() const;
+
+ void setupWaylandFrameCallback();
+ static void waylandFrameDoneCB(void *data, struct wl_callback *cb, uint32_t time);
+ //
+
+private:
+ void tryFindFullscreenSize(int &aWidth, int &aHeight);
+};
class LLSplashScreenSDL : public LLSplashScreen
{
@@ -221,11 +270,12 @@ public:
LLSplashScreenSDL();
virtual ~LLSplashScreenSDL();
- /*virtual*/ void showImpl();
- /*virtual*/ void updateImpl(const std::string& mesg);
- /*virtual*/ void hideImpl();
+ void showImpl();
+ void updateImpl(const std::string& mesg);
+ void hideImpl();
};
S32 OSMessageBoxSDL(const std::string& text, const std::string& caption, U32 type);
+#endif //LL_LINUX
#endif //LL_LLWINDOWSDL_H
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index abf86e363c..bacf5325fe 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -31,6 +31,7 @@
#include "llwindowwin32.h"
// LLWindow library includes
+#include "llgamecontrol.h"
#include "llkeyboardwin32.h"
#include "lldragdropwin32.h"
#include "llpreeditor.h"
@@ -92,7 +93,7 @@ const F32 ICON_FLASH_TIME = 0.5f;
const UINT WM_DUMMY_(WM_USER + 0x0017);
const UINT WM_POST_FUNCTION_(WM_USER + 0x0018);
-extern BOOL gDebugWindowProc;
+extern bool gDebugWindowProc;
static std::thread::id sWindowThreadId;
static std::thread::id sMainThreadId;
@@ -163,30 +164,21 @@ HGLRC SafeCreateContext(HDC &hdc)
GLuint SafeChoosePixelFormat(HDC &hdc, const PIXELFORMATDESCRIPTOR *ppfd)
{
- __try
- {
- return ChoosePixelFormat(hdc, ppfd);
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- // convert to C++ styled exception
- // C exception don't allow classes, so it's a regular char array
- char integer_string[32];
- sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode());
- throw std::exception(integer_string);
- }
+ return LL::seh::catcher([hdc, ppfd]{ return ChoosePixelFormat(hdc, ppfd); });
}
//static
-BOOL LLWindowWin32::sIsClassRegistered = FALSE;
+bool LLWindowWin32::sIsClassRegistered = false;
-BOOL LLWindowWin32::sLanguageTextInputAllowed = TRUE;
-BOOL LLWindowWin32::sWinIMEOpened = FALSE;
+bool LLWindowWin32::sLanguageTextInputAllowed = true;
+bool LLWindowWin32::sWinIMEOpened = false;
HKL LLWindowWin32::sWinInputLocale = 0;
DWORD LLWindowWin32::sWinIMEConversionMode = IME_CMODE_NATIVE;
DWORD LLWindowWin32::sWinIMESentenceMode = IME_SMODE_AUTOMATIC;
LLCoordWindow LLWindowWin32::sWinIMEWindowPosition(-1,-1);
+static HWND sWindowHandleForMessageBox = NULL;
+
// The following class LLWinImm delegates Windows IMM APIs.
// It was originally introduced to support US Windows XP, on which we needed
// to dynamically load IMM32.DLL and use GetProcAddress to resolve its entry
@@ -200,24 +192,24 @@ public:
public:
// Wrappers for IMM API.
- static BOOL isIME(HKL hkl);
+ static bool isIME(HKL hkl);
static HIMC getContext(HWND hwnd);
- static BOOL releaseContext(HWND hwnd, HIMC himc);
- static BOOL getOpenStatus(HIMC himc);
- static BOOL setOpenStatus(HIMC himc, BOOL status);
- static BOOL getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence);
- static BOOL setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence);
- static BOOL getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form);
- static BOOL setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form);
+ static bool releaseContext(HWND hwnd, HIMC himc);
+ static bool getOpenStatus(HIMC himc);
+ static bool setOpenStatus(HIMC himc, bool status);
+ static bool getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence);
+ static bool setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence);
+ static bool getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form);
+ static bool setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form);
static LONG getCompositionString(HIMC himc, DWORD index, LPVOID data, DWORD length);
- static BOOL setCompositionString(HIMC himc, DWORD index, LPVOID pComp, DWORD compLength, LPVOID pRead, DWORD readLength);
- static BOOL setCompositionFont(HIMC himc, LPLOGFONTW logfont);
- static BOOL setCandidateWindow(HIMC himc, LPCANDIDATEFORM candidate_form);
- static BOOL notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value);
+ static bool setCompositionString(HIMC himc, DWORD index, LPVOID pComp, DWORD compLength, LPVOID pRead, DWORD readLength);
+ static bool setCompositionFont(HIMC himc, LPLOGFONTW logfont);
+ static bool setCandidateWindow(HIMC himc, LPCANDIDATEFORM candidate_form);
+ static bool notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value);
};
// static
-BOOL LLWinImm::isIME(HKL hkl)
+bool LLWinImm::isIME(HKL hkl)
{
return ImmIsIME(hkl);
}
@@ -229,43 +221,43 @@ HIMC LLWinImm::getContext(HWND hwnd)
}
//static
-BOOL LLWinImm::releaseContext(HWND hwnd, HIMC himc)
+bool LLWinImm::releaseContext(HWND hwnd, HIMC himc)
{
return ImmReleaseContext(hwnd, himc);
}
// static
-BOOL LLWinImm::getOpenStatus(HIMC himc)
+bool LLWinImm::getOpenStatus(HIMC himc)
{
return ImmGetOpenStatus(himc);
}
// static
-BOOL LLWinImm::setOpenStatus(HIMC himc, BOOL status)
+bool LLWinImm::setOpenStatus(HIMC himc, bool status)
{
return ImmSetOpenStatus(himc, status);
}
// static
-BOOL LLWinImm::getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence)
+bool LLWinImm::getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence)
{
return ImmGetConversionStatus(himc, conversion, sentence);
}
// static
-BOOL LLWinImm::setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence)
+bool LLWinImm::setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence)
{
return ImmSetConversionStatus(himc, conversion, sentence);
}
// static
-BOOL LLWinImm::getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form)
+bool LLWinImm::getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form)
{
return ImmGetCompositionWindow(himc, form);
}
// static
-BOOL LLWinImm::setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form)
+bool LLWinImm::setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form)
{
return ImmSetCompositionWindow(himc, form);
}
@@ -279,25 +271,25 @@ LONG LLWinImm::getCompositionString(HIMC himc, DWORD index, LPVOID data,
// static
-BOOL LLWinImm::setCompositionString(HIMC himc, DWORD index, LPVOID pComp, DWORD compLength, LPVOID pRead, DWORD readLength)
+bool LLWinImm::setCompositionString(HIMC himc, DWORD index, LPVOID pComp, DWORD compLength, LPVOID pRead, DWORD readLength)
{
return ImmSetCompositionString(himc, index, pComp, compLength, pRead, readLength);
}
// static
-BOOL LLWinImm::setCompositionFont(HIMC himc, LPLOGFONTW pFont)
+bool LLWinImm::setCompositionFont(HIMC himc, LPLOGFONTW pFont)
{
return ImmSetCompositionFont(himc, pFont);
}
// static
-BOOL LLWinImm::setCandidateWindow(HIMC himc, LPCANDIDATEFORM form)
+bool LLWinImm::setCandidateWindow(HIMC himc, LPCANDIDATEFORM form)
{
return ImmSetCandidateWindow(himc, form);
}
// static
-BOOL LLWinImm::notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value)
+bool LLWinImm::notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value)
{
return ImmNotifyIME(himc, action, index, value);
}
@@ -365,22 +357,8 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
mGLReady = true;
}
- // initialzie DXGI adapter (for querying available VRAM)
- void initDX();
-
- // initialize D3D (if DXGI cannot be used)
- void initD3D();
-
- //clean up DXGI/D3D resources
- void cleanupDX();
-
- // call periodically to update available VRAM
- void updateVRAMUsage();
-
- U32 getAvailableVRAMMegabytes()
- {
- return mAvailableVRAM;
- }
+ // Use DXGI to check memory (because WMI doesn't report more than 4Gb)
+ void checkDXMem();
/// called by main thread to post work to this window thread
template <typename CALLABLE>
@@ -422,34 +400,25 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
using FuncType = std::function<void()>;
// call GetMessage() and pull enqueue messages for later processing
- void gatherInput();
HWND mWindowHandleThrd = NULL;
HDC mhDCThrd = 0;
// *HACK: Attempt to prevent startup crashes by deferring memory accounting
// until after some graphics setup. See SL-20177. -Cosmic,2023-09-18
bool mGLReady = false;
+ bool mGotGLBuffer = false;
LLAtomicBool mDeleteOnExit = false;
- // best guess at available video memory in MB
- std::atomic<U32> mAvailableVRAM;
-
- U32 mMaxVRAM = 0; // maximum amount of vram to allow in the "budget", or 0 for no maximum (see updateVRAMUsage)
-
- IDXGIAdapter3* mDXGIAdapter = nullptr;
- LPDIRECT3D9 mD3D = nullptr;
- LPDIRECT3DDEVICE9 mD3DDevice = nullptr;
};
LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, S32 x, S32 y, S32 width,
S32 height, U32 flags,
- BOOL fullscreen, BOOL clearBg,
- BOOL enable_vsync, BOOL use_gl,
- BOOL ignore_pixel_depth,
+ bool fullscreen, bool clearBg,
+ bool enable_vsync, bool use_gl,
+ bool ignore_pixel_depth,
U32 fsaa_samples,
U32 max_cores,
- U32 max_vram,
F32 max_gl_version)
:
LLWindow(callbacks, fullscreen, flags),
@@ -458,7 +427,6 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
{
sMainThreadId = LLThread::currentID();
mWindowThread = new LLWindowWin32Thread();
- mWindowThread->mMaxVRAM = max_vram;
//MAINT-516 -- force a load of opengl32.dll just in case windows went sideways
LoadLibrary(L"opengl32.dll");
@@ -470,7 +438,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
mMaxCores = llmin(mMaxCores, (U32) 64);
DWORD_PTR mask = 0;
- for (int i = 0; i < mMaxCores; ++i)
+ for (U32 i = 0; i < mMaxCores; ++i)
{
mask |= ((DWORD_PTR) 1) << i;
}
@@ -539,7 +507,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
mIconResource = gIconResource;
mOverrideAspectRatio = 0.f;
mNativeAspectRatio = 0.f;
- mInputProcessingPaused = FALSE;
+ mInputProcessingPaused = false;
mPreeditor = NULL;
mKeyCharCode = 0;
mKeyScanCode = 0;
@@ -548,7 +516,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
mhRC = NULL;
memset(mCurrentGammaRamp, 0, sizeof(mCurrentGammaRamp));
memset(mPrevGammaRamp, 0, sizeof(mPrevGammaRamp));
- mCustomGammaSet = FALSE;
+ mCustomGammaSet = false;
mWindowHandle = NULL;
mRect = {0, 0, 0, 0};
@@ -556,7 +524,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
if (!SystemParametersInfo(SPI_GETMOUSEVANISH, 0, &mMouseVanish, 0))
{
- mMouseVanish = TRUE;
+ mMouseVanish = true;
}
// Initialize the keyboard
@@ -568,7 +536,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
// Initialize (boot strap) the Language text input management,
// based on the system's (user's) default settings.
- allowLanguageTextInput(mPreeditor, FALSE);
+ allowLanguageTextInput(mPreeditor, false);
WNDCLASS wc;
RECT window_rect;
@@ -686,7 +654,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
mCallbacks->translateString("MBError"), OSMB_OK);
return;
}
- sIsClassRegistered = TRUE;
+ sIsClassRegistered = true;
}
//-----------------------------------------------------------------------
@@ -714,7 +682,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
//-----------------------------------------------------------------------
if (mFullscreen)
{
- BOOL success = FALSE;
+ bool success = false;
DWORD closest_refresh = 0;
for (S32 mode_num = 0;; mode_num++)
@@ -728,7 +696,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
dev_mode.dmPelsHeight == height &&
dev_mode.dmBitsPerPel == BITS_PER_PIXEL)
{
- success = TRUE;
+ success = true;
if ((dev_mode.dmDisplayFrequency - current_refresh)
< (closest_refresh - current_refresh))
{
@@ -740,11 +708,11 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
if (closest_refresh == 0)
{
LL_WARNS("Window") << "Couldn't find display mode " << width << " by " << height << " at " << BITS_PER_PIXEL << " bits per pixel" << LL_ENDL;
- //success = FALSE;
+ //success = false;
if (!EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode))
{
- success = FALSE;
+ success = false;
}
else
{
@@ -753,12 +721,12 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
LL_WARNS("Window") << "Current BBP is OK falling back to that" << LL_ENDL;
window_rect.right=width=dev_mode.dmPelsWidth;
window_rect.bottom=height=dev_mode.dmPelsHeight;
- success = TRUE;
+ success = true;
}
else
{
LL_WARNS("Window") << "Current BBP is BAD" << LL_ENDL;
- success = FALSE;
+ success = false;
}
}
}
@@ -776,7 +744,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
// If it failed, we don't want to run fullscreen
if (success)
{
- mFullscreen = TRUE;
+ mFullscreen = true;
mFullscreenWidth = dev_mode.dmPelsWidth;
mFullscreenHeight = dev_mode.dmPelsHeight;
mFullscreenBits = dev_mode.dmBitsPerPel;
@@ -790,7 +758,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
}
else
{
- mFullscreen = FALSE;
+ mFullscreen = false;
mFullscreenWidth = -1;
mFullscreenHeight = -1;
mFullscreenBits = -1;
@@ -832,8 +800,8 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
size_t name_len = strlen(display_device.DeviceName );
size_t desc_len = strlen(display_device.DeviceString);
- CHAR *name = name_len ? display_device.DeviceName : "???";
- CHAR *desc = desc_len ? display_device.DeviceString : "???";
+ const CHAR *name = name_len ? display_device.DeviceName : "???";
+ const CHAR *desc = desc_len ? display_device.DeviceString : "???";
sprintf(text, "Display Device %d: %s, %s", display_index, name, desc);
LL_INFOS("Window") << text << LL_ENDL;
@@ -871,12 +839,17 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
// Initialize (boot strap) the Language text input management,
// based on the system's (or user's) default settings.
- allowLanguageTextInput(NULL, FALSE);
+ allowLanguageTextInput(NULL, false);
}
LLWindowWin32::~LLWindowWin32()
{
+ if (sWindowHandleForMessageBox == mWindowHandle)
+ {
+ sWindowHandleForMessageBox = NULL;
+ }
+
delete mDragDrop;
mDragDrop = NULL;
@@ -903,14 +876,14 @@ void LLWindowWin32::show()
void LLWindowWin32::hide()
{
- setMouseClipping(FALSE);
+ setMouseClipping(false);
ShowWindow(mWindowHandle, SW_HIDE);
}
//virtual
void LLWindowWin32::minimize()
{
- setMouseClipping(FALSE);
+ setMouseClipping(false);
showCursor();
ShowWindow(mWindowHandle, SW_MINIMIZE);
}
@@ -967,7 +940,7 @@ void LLWindowWin32::close()
// Make sure cursor is visible and we haven't mangled the clipping state.
showCursor();
- setMouseClipping(FALSE);
+ setMouseClipping(false);
if (gKeyboard)
{
gKeyboard->resetKeys();
@@ -1001,6 +974,11 @@ void LLWindowWin32::close()
LL_DEBUGS("Window") << "Destroying Window" << LL_ENDL;
+ if (sWindowHandleForMessageBox == mWindowHandle)
+ {
+ sWindowHandleForMessageBox = NULL;
+ }
+
mhDC = NULL;
mWindowHandle = NULL;
@@ -1011,29 +989,29 @@ void LLWindowWin32::close()
}
}
-BOOL LLWindowWin32::isValid()
+bool LLWindowWin32::isValid()
{
return (mWindowHandle != NULL);
}
-BOOL LLWindowWin32::getVisible()
+bool LLWindowWin32::getVisible() const
{
return (mWindowHandle && IsWindowVisible(mWindowHandle));
}
-BOOL LLWindowWin32::getMinimized()
+bool LLWindowWin32::getMinimized() const
{
return (mWindowHandle && IsIconic(mWindowHandle));
}
-BOOL LLWindowWin32::getMaximized()
+bool LLWindowWin32::getMaximized() const
{
return (mWindowHandle && IsZoomed(mWindowHandle));
}
-BOOL LLWindowWin32::maximize()
+bool LLWindowWin32::maximize()
{
- BOOL success = FALSE;
+ bool success = false;
if (!mWindowHandle) return success;
mWindowThread->post([=]
@@ -1048,56 +1026,51 @@ BOOL LLWindowWin32::maximize()
}
});
- return TRUE;
-}
-
-BOOL LLWindowWin32::getFullscreen()
-{
- return mFullscreen;
+ return true;
}
-BOOL LLWindowWin32::getPosition(LLCoordScreen *position)
+bool LLWindowWin32::getPosition(LLCoordScreen *position) const
{
position->mX = mRect.left;
position->mY = mRect.top;
- return TRUE;
+ return true;
}
-BOOL LLWindowWin32::getSize(LLCoordScreen *size)
+bool LLWindowWin32::getSize(LLCoordScreen *size) const
{
size->mX = mRect.right - mRect.left;
size->mY = mRect.bottom - mRect.top;
- return TRUE;
+ return true;
}
-BOOL LLWindowWin32::getSize(LLCoordWindow *size)
+bool LLWindowWin32::getSize(LLCoordWindow *size) const
{
size->mX = mClientRect.right - mClientRect.left;
size->mY = mClientRect.bottom - mClientRect.top;
- return TRUE;
+ return true;
}
-BOOL LLWindowWin32::setPosition(const LLCoordScreen position)
+bool LLWindowWin32::setPosition(const LLCoordScreen position)
{
LLCoordScreen size;
if (!mWindowHandle)
{
- return FALSE;
+ return false;
}
getSize(&size);
moveWindow(position, size);
- return TRUE;
+ return true;
}
-BOOL LLWindowWin32::setSizeImpl(const LLCoordScreen size)
+bool LLWindowWin32::setSizeImpl(const LLCoordScreen size)
{
LLCoordScreen position;
getPosition(&position);
if (!mWindowHandle)
{
- return FALSE;
+ return false;
}
mWindowThread->post([=]()
@@ -1113,10 +1086,10 @@ BOOL LLWindowWin32::setSizeImpl(const LLCoordScreen size)
});
moveWindow(position, size);
- return TRUE;
+ return true;
}
-BOOL LLWindowWin32::setSizeImpl(const LLCoordWindow size)
+bool LLWindowWin32::setSizeImpl(const LLCoordWindow size)
{
RECT window_rect = {0, 0, size.mX, size.mY };
DWORD dw_ex_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
@@ -1128,7 +1101,7 @@ BOOL LLWindowWin32::setSizeImpl(const LLCoordWindow size)
}
// changing fullscreen resolution
-BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BOOL enable_vsync, const LLCoordScreen* const posp)
+bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bool enable_vsync, const LLCoordScreen* const posp)
{
//called from main thread
GLuint pixel_format;
@@ -1141,11 +1114,11 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
RECT window_rect = { 0, 0, 0, 0 };
S32 width = size.mX;
S32 height = size.mY;
- BOOL auto_show = FALSE;
+ bool auto_show = false;
if (mhRC)
{
- auto_show = TRUE;
+ auto_show = true;
resetDisplayResolution();
}
@@ -1178,8 +1151,8 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
if (fullscreen)
{
- mFullscreen = TRUE;
- BOOL success = FALSE;
+ mFullscreen = true;
+ bool success = false;
DWORD closest_refresh = 0;
for (S32 mode_num = 0;; mode_num++)
@@ -1193,7 +1166,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
dev_mode.dmPelsHeight == height &&
dev_mode.dmBitsPerPel == BITS_PER_PIXEL)
{
- success = TRUE;
+ success = true;
if ((dev_mode.dmDisplayFrequency - current_refresh)
< (closest_refresh - current_refresh))
{
@@ -1205,7 +1178,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
if (closest_refresh == 0)
{
LL_WARNS("Window") << "Couldn't find display mode " << width << " by " << height << " at " << BITS_PER_PIXEL << " bits per pixel" << LL_ENDL;
- return FALSE;
+ return false;
}
// If we found a good resolution, use it.
@@ -1220,7 +1193,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
if (success)
{
- mFullscreen = TRUE;
+ mFullscreen = true;
mFullscreenWidth = dev_mode.dmPelsWidth;
mFullscreenHeight = dev_mode.dmPelsHeight;
mFullscreenBits = dev_mode.dmBitsPerPel;
@@ -1246,19 +1219,19 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
// If it failed, we don't want to run fullscreen
else
{
- mFullscreen = FALSE;
+ mFullscreen = false;
mFullscreenWidth = -1;
mFullscreenHeight = -1;
mFullscreenBits = -1;
mFullscreenRefresh = -1;
LL_INFOS("Window") << "Unable to run fullscreen at " << width << "x" << height << LL_ENDL;
- return FALSE;
+ return false;
}
}
else
{
- mFullscreen = FALSE;
+ mFullscreen = false;
window_rect.left = (long)(posp ? posp->mX : 0);
window_rect.right = (long)width + window_rect.left; // Windows GDI rects don't include rightmost pixel
window_rect.top = (long)(posp ? posp->mY : 0);
@@ -1270,7 +1243,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
// don't post quit messages when destroying old windows
- mPostQuit = FALSE;
+ mPostQuit = false;
// create window
@@ -1320,7 +1293,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
close();
OSMessageBox(mCallbacks->translateString("MBDevContextErr"),
mCallbacks->translateString("MBError"), OSMB_OK);
- return FALSE;
+ return false;
}
LL_INFOS("Window") << "Device context retrieved." << LL_ENDL ;
@@ -1334,7 +1307,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
OSMessageBox(mCallbacks->translateString("MBPixelFmtErr"),
mCallbacks->translateString("MBError"), OSMB_OK);
close();
- return FALSE;
+ return false;
}
}
catch (...)
@@ -1343,7 +1316,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
OSMessageBox(mCallbacks->translateString("MBPixelFmtErr"),
mCallbacks->translateString("MBError"), OSMB_OK);
close();
- return FALSE;
+ return false;
}
LL_INFOS("Window") << "Pixel format chosen." << LL_ENDL ;
@@ -1355,7 +1328,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"),
mCallbacks->translateString("MBError"), OSMB_OK);
close();
- return FALSE;
+ return false;
}
// (EXP-1765) dump pixel data to see if there is a pattern that leads to unreproducible crash
@@ -1394,7 +1367,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"),
mCallbacks->translateString("MBError"), OSMB_OK);
close();
- return FALSE;
+ return false;
}
@@ -1403,7 +1376,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
OSMessageBox(mCallbacks->translateString("MBGLContextErr"),
mCallbacks->translateString("MBError"), OSMB_OK);
close();
- return FALSE;
+ return false;
}
if (!wglMakeCurrent(mhDC, mhRC))
@@ -1411,14 +1384,14 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
OSMessageBox(mCallbacks->translateString("MBGLContextActErr"),
mCallbacks->translateString("MBError"), OSMB_OK);
close();
- return FALSE;
+ return false;
}
LL_INFOS("Window") << "Drawing context is created." << LL_ENDL ;
gGLManager.initWGL();
- if (wglChoosePixelFormatARB)
+ if (wglChoosePixelFormatARB && wglGetPixelFormatAttribivARB)
{
// OK, at this point, use the ARB wglChoosePixelFormatsARB function to see if we
// can get exactly what we want.
@@ -1503,7 +1476,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
close();
show_window_creation_error("Error after wglChoosePixelFormatARB 32-bit");
- return FALSE;
+ return false;
}
if (!num_formats)
@@ -1518,7 +1491,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
{
close();
show_window_creation_error("Error after wglChoosePixelFormatARB 32-bit no AA");
- return FALSE;
+ return false;
}
}
@@ -1532,7 +1505,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
{
close();
show_window_creation_error("Error after wglChoosePixelFormatARB 24-bit");
- return FALSE;
+ return false;
}
if (!num_formats)
@@ -1544,7 +1517,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
{
close();
show_window_creation_error("Error after wglChoosePixelFormatARB 16-bit");
- return FALSE;
+ return false;
}
}
}
@@ -1617,7 +1590,7 @@ const S32 max_format = (S32)num_formats - 1;
{
OSMessageBox(mCallbacks->translateString("MBDevContextErr"), mCallbacks->translateString("MBError"), OSMB_OK);
close();
- return FALSE;
+ return false;
}
if (!SetPixelFormat(mhDC, pixel_format, &pfd))
@@ -1625,7 +1598,7 @@ const S32 max_format = (S32)num_formats - 1;
OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"),
mCallbacks->translateString("MBError"), OSMB_OK);
close();
- return FALSE;
+ return false;
}
if (wglGetPixelFormatAttribivARB(mhDC, pixel_format, 0, 1, &swap_query, &swap_method))
@@ -1653,9 +1626,11 @@ const S32 max_format = (S32)num_formats - 1;
}
else
{
- LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBVideoDrvErr"));
- // mWindowHandle is 0, going to crash either way
- LL_ERRS("Window") << "No wgl_ARB_pixel_format extension!" << LL_ENDL;
+ LL_WARNS("Window") << "No wgl_ARB_pixel_format extension!" << LL_ENDL;
+ // cannot proceed without wgl_ARB_pixel_format extension, shutdown same as any other gGLManager.initGL() failure
+ OSMessageBox(mCallbacks->translateString("MBVideoDrvErr"), mCallbacks->translateString("MBError"), OSMB_OK);
+ close();
+ return false;
}
// Verify what pixel format we actually received.
@@ -1664,7 +1639,7 @@ const S32 max_format = (S32)num_formats - 1;
{
OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"), mCallbacks->translateString("MBError"), OSMB_OK);
close();
- return FALSE;
+ return false;
}
LL_INFOS("Window") << "GL buffer: Color Bits " << S32(pfd.cColorBits)
@@ -1678,7 +1653,7 @@ const S32 max_format = (S32)num_formats - 1;
mhRC = (HGLRC) createSharedContext();
if (!mhRC)
{
- return FALSE;
+ return false;
}
}
@@ -1686,14 +1661,14 @@ const S32 max_format = (S32)num_formats - 1;
{
OSMessageBox(mCallbacks->translateString("MBGLContextActErr"), mCallbacks->translateString("MBError"), OSMB_OK);
close();
- return FALSE;
+ return false;
}
if (!gGLManager.initGL())
{
OSMessageBox(mCallbacks->translateString("MBVideoDrvErr"), mCallbacks->translateString("MBError"), OSMB_OK);
close();
- return FALSE;
+ return false;
}
// Disable vertical sync for swap
@@ -1710,7 +1685,7 @@ const S32 max_format = (S32)num_formats - 1;
SetTimer( mWindowHandle, 0, 1000 / 30, NULL ); // 30 fps timer
// ok to post quit messages now
- mPostQuit = TRUE;
+ mPostQuit = true;
// *HACK: Attempt to prevent startup crashes by deferring memory accounting
// until after some graphics setup. See SL-20177. -Cosmic,2023-09-18
@@ -1729,7 +1704,7 @@ const S32 max_format = (S32)num_formats - 1;
LL_PROFILER_GPU_CONTEXT;
- return TRUE;
+ return true;
}
void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw_style)
@@ -1737,10 +1712,15 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw
auto oldWindowHandle = mWindowHandle;
auto oldDCHandle = mhDC;
+ if (sWindowHandleForMessageBox == mWindowHandle)
+ {
+ sWindowHandleForMessageBox = NULL;
+ }
+
// zero out mWindowHandle and mhDC before destroying window so window
// thread falls back to peekmessage
- mWindowHandle = 0;
- mhDC = 0;
+ mWindowHandle = NULL;
+ mhDC = NULL;
std::promise<std::pair<HWND, HDC>> promise;
// What follows must be done on the window thread.
@@ -1837,6 +1817,8 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw
auto pair = future.get();
mWindowHandle = pair.first;
mhDC = pair.second;
+
+ sWindowHandleForMessageBox = mWindowHandle;
}
void* LLWindowWin32::createSharedContext()
@@ -1844,7 +1826,7 @@ void* LLWindowWin32::createSharedContext()
mMaxGLVersion = llclamp(mMaxGLVersion, 3.f, 4.6f);
S32 version_major = llfloor(mMaxGLVersion);
- S32 version_minor = llround((mMaxGLVersion-version_major)*10);
+ S32 version_minor = (S32)llround((mMaxGLVersion-version_major)*10);
S32 attribs[] =
{
@@ -1958,13 +1940,13 @@ void LLWindowWin32::setTitle(const std::string title)
});
}
-BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position)
+bool LLWindowWin32::setCursorPosition(const LLCoordWindow position)
{
ASSERT_MAIN_THREAD();
if (!mWindowHandle)
{
- return FALSE;
+ return false;
}
LLCoordScreen screen_pos(position.convert());
@@ -1984,31 +1966,31 @@ BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position)
SetCursorPos(screen_pos.mX, screen_pos.mY);
});
- return TRUE;
+ return true;
}
-BOOL LLWindowWin32::getCursorPosition(LLCoordWindow *position)
+bool LLWindowWin32::getCursorPosition(LLCoordWindow *position)
{
ASSERT_MAIN_THREAD();
if (!position)
{
- return FALSE;
+ return false;
}
*position = mCursorPosition;
- return TRUE;
+ return true;
}
-BOOL LLWindowWin32::getCursorDelta(LLCoordCommon* delta)
+bool LLWindowWin32::getCursorDelta(LLCoordCommon* delta) const
{
if (delta == nullptr)
{
- return FALSE;
+ return false;
}
*delta = mMouseFrameDelta;
- return TRUE;
+ return true;
}
void LLWindowWin32::hideCursor()
@@ -2023,8 +2005,8 @@ void LLWindowWin32::hideCursor()
}
});
- mCursorHidden = TRUE;
- mHideCursorPermanent = TRUE;
+ mCursorHidden = true;
+ mHideCursorPermanent = true;
}
void LLWindowWin32::showCursor()
@@ -2042,8 +2024,8 @@ void LLWindowWin32::showCursor()
}
});
- mCursorHidden = FALSE;
- mHideCursorPermanent = FALSE;
+ mCursorHidden = false;
+ mHideCursorPermanent = false;
}
void LLWindowWin32::showCursorFromMouseMove()
@@ -2059,11 +2041,11 @@ void LLWindowWin32::hideCursorUntilMouseMove()
if (!mHideCursorPermanent && mMouseVanish)
{
hideCursor();
- mHideCursorPermanent = FALSE;
+ mHideCursorPermanent = false;
}
}
-BOOL LLWindowWin32::isCursorHidden()
+bool LLWindowWin32::isCursorHidden()
{
return mCursorHidden;
}
@@ -2146,7 +2128,7 @@ void LLWindowWin32::initCursors()
void LLWindowWin32::updateCursor()
{
ASSERT_MAIN_THREAD();
- LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32;
if (mNextCursor == UI_CURSOR_ARROW
&& mBusyCount > 0)
{
@@ -2183,14 +2165,14 @@ void LLWindowWin32::releaseMouse()
void LLWindowWin32::delayInputProcessing()
{
- mInputProcessingPaused = TRUE;
+ mInputProcessingPaused = true;
}
-void LLWindowWin32::gatherInput()
+void LLWindowWin32::gatherInput(bool app_has_focus)
{
ASSERT_MAIN_THREAD();
- LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32;
MSG msg;
{
@@ -2264,9 +2246,11 @@ void LLWindowWin32::gatherInput()
}
}
- mInputProcessingPaused = FALSE;
+ mInputProcessingPaused = false;
updateCursor();
+
+ LLGameControl::processEvents(app_has_focus);
}
static LLTrace::BlockTimerStatHandle FTM_KEYHANDLER("Handle Keyboard");
@@ -2309,7 +2293,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// pass along extended flag in mask
MASK mask = (l_param >> 16 & KF_EXTENDED) ? MASK_EXTENDED : 0x0;
- BOOL eat_keystroke = TRUE;
+ bool eat_keystroke = true;
switch (u_msg)
{
@@ -2331,7 +2315,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
{
WINDOW_IMP_POST(window_imp->mCallbacks->handleDeviceChange(window_imp));
- return TRUE;
+ return 1;
}
break;
}
@@ -2488,8 +2472,9 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_SYSKEYDOWN");
// allow system keys, such as ALT-F4 to be processed by Windows
- eat_keystroke = FALSE;
+ eat_keystroke = false;
// intentional fall-through here
+ [[fallthrough]];
}
case WM_KEYDOWN:
{
@@ -2498,33 +2483,34 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
{
window_imp->mKeyCharCode = 0; // don't know until wm_char comes in next
window_imp->mKeyScanCode = (l_param >> 16) & 0xff;
- window_imp->mKeyVirtualKey = w_param;
+ window_imp->mKeyVirtualKey = (U32)w_param;
window_imp->mRawMsg = u_msg;
- window_imp->mRawWParam = w_param;
- window_imp->mRawLParam = l_param;
+ window_imp->mRawWParam = (U32)w_param;
+ window_imp->mRawLParam = (U32)l_param;
- gKeyboard->handleKeyDown(w_param, mask);
+ gKeyboard->handleKeyDown((U16)w_param, mask);
});
if (eat_keystroke) return 0; // skip DefWindowProc() handling if we're consuming the keypress
break;
}
case WM_SYSKEYUP:
- eat_keystroke = FALSE;
+ eat_keystroke = false;
// intentional fall-through here
+ [[fallthrough]];
case WM_KEYUP:
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_KEYUP");
window_imp->post([=]()
{
window_imp->mKeyScanCode = (l_param >> 16) & 0xff;
- window_imp->mKeyVirtualKey = w_param;
+ window_imp->mKeyVirtualKey = (U32)w_param;
window_imp->mRawMsg = u_msg;
- window_imp->mRawWParam = w_param;
- window_imp->mRawLParam = l_param;
+ window_imp->mRawWParam = (U32)w_param;
+ window_imp->mRawLParam = (U32)l_param;
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_KEYUP");
- gKeyboard->handleKeyUp(w_param, mask);
+ gKeyboard->handleKeyUp((U16)w_param, mask);
}
});
if (eat_keystroke) return 0; // skip DefWindowProc() handling if we're consuming the keypress
@@ -2564,7 +2550,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_IME_COMPOSITION");
if (LLWinImm::isAvailable() && window_imp->mPreeditor)
{
- WINDOW_IMP_POST(window_imp->handleCompositionMessage(l_param));
+ WINDOW_IMP_POST(window_imp->handleCompositionMessage((U32)l_param));
return 0;
}
break;
@@ -2585,10 +2571,10 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_CHAR");
window_imp->post([=]()
{
- window_imp->mKeyCharCode = w_param;
+ window_imp->mKeyCharCode = (U32)w_param;
window_imp->mRawMsg = u_msg;
- window_imp->mRawWParam = w_param;
- window_imp->mRawLParam = l_param;
+ window_imp->mRawWParam = (U32)w_param;
+ window_imp->mRawLParam = (U32)l_param;
// Should really use WM_UNICHAR eventually, but it requires a specific Windows version and I need
// to figure out how that works. - Doug
@@ -2601,9 +2587,9 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// characters. We just need to take care of surrogate pairs sent as two WM_CHAR's
// by ourselves. It is not that tough. -- Alissa Sabre @ SL
- // Even if LLWindowCallbacks::handleUnicodeChar(llwchar, BOOL) returned FALSE,
+ // Even if LLWindowCallbacks::handleUnicodeChar(llwchar, bool) returned false,
// we *did* processed the event, so I believe we should not pass it to DefWindowProc...
- window_imp->handleUnicodeUTF16((U16)w_param, gKeyboard->currentMask(FALSE));
+ window_imp->handleUnicodeUTF16((U16)w_param, gKeyboard->currentMask(false));
});
return 0;
}
@@ -2634,7 +2620,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
window_imp->interruptLanguageTextInput();
}
- MASK mask = gKeyboard->currentMask(TRUE);
+ MASK mask = gKeyboard->currentMask(true);
auto gl_coord = window_imp->mCursorPosition.convert();
window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
window_imp->mCallbacks->handleMouseDown(window_imp, gl_coord, mask);
@@ -2657,7 +2643,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
sHandleDoubleClick = true;
return;
}
- MASK mask = gKeyboard->currentMask(TRUE);
+ MASK mask = gKeyboard->currentMask(true);
// generate move event to update mouse coordinates
window_imp->mCursorPosition = window_coord;
@@ -2681,7 +2667,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
sHandleDoubleClick = true;
- MASK mask = gKeyboard->currentMask(TRUE);
+ MASK mask = gKeyboard->currentMask(true);
// generate move event to update mouse coordinates
window_imp->mCursorPosition = window_coord;
window_imp->mCallbacks->handleMouseUp(window_imp, window_imp->mCursorPosition.convert(), mask);
@@ -2702,7 +2688,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
WINDOW_IMP_POST(window_imp->interruptLanguageTextInput());
}
- MASK mask = gKeyboard->currentMask(TRUE);
+ MASK mask = gKeyboard->currentMask(true);
// generate move event to update mouse coordinates
auto gl_coord = window_imp->mCursorPosition.convert();
window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
@@ -2720,7 +2706,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER);
window_imp->postMouseButtonEvent([=]()
{
- MASK mask = gKeyboard->currentMask(TRUE);
+ MASK mask = gKeyboard->currentMask(true);
window_imp->mCallbacks->handleRightMouseUp(window_imp, window_imp->mCursorPosition.convert(), mask);
});
}
@@ -2740,7 +2726,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
window_imp->interruptLanguageTextInput();
}
- MASK mask = gKeyboard->currentMask(TRUE);
+ MASK mask = gKeyboard->currentMask(true);
window_imp->mCallbacks->handleMiddleMouseDown(window_imp, window_imp->mCursorPosition.convert(), mask);
});
}
@@ -2754,7 +2740,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER);
window_imp->postMouseButtonEvent([=]()
{
- MASK mask = gKeyboard->currentMask(TRUE);
+ MASK mask = gKeyboard->currentMask(true);
window_imp->mCallbacks->handleMiddleMouseUp(window_imp, window_imp->mCursorPosition.convert(), mask);
});
}
@@ -2772,7 +2758,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
window_imp->interruptLanguageTextInput();
}
- MASK mask = gKeyboard->currentMask(TRUE);
+ MASK mask = gKeyboard->currentMask(true);
// Windows uses numbers 1 and 2 for buttons, remap to 4, 5
window_imp->mCallbacks->handleOtherMouseDown(window_imp, window_imp->mCursorPosition.convert(), mask, button + 3);
});
@@ -2789,7 +2775,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER);
S32 button = GET_XBUTTON_WPARAM(w_param);
- MASK mask = gKeyboard->currentMask(TRUE);
+ MASK mask = gKeyboard->currentMask(true);
// Windows uses numbers 1 and 2 for buttons, remap to 4, 5
window_imp->mCallbacks->handleOtherMouseUp(window_imp, window_imp->mCursorPosition.convert(), mask, button + 3);
});
@@ -2899,7 +2885,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_MOUSEMOVE lambda");
- MASK mask = gKeyboard->currentMask(TRUE);
+ MASK mask = gKeyboard->currentMask(true);
window_imp->mMouseMask = mask;
window_imp->mCursorPosition = window_coord;
});
@@ -2936,19 +2922,19 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// means that the window was un-minimized.
if (w_param == SIZE_RESTORED && window_imp->mLastSizeWParam != SIZE_RESTORED)
{
- WINDOW_IMP_POST(window_imp->mCallbacks->handleActivate(window_imp, TRUE));
+ WINDOW_IMP_POST(window_imp->mCallbacks->handleActivate(window_imp, true));
}
// handle case of window being maximized from fully minimized state
if (w_param == SIZE_MAXIMIZED && window_imp->mLastSizeWParam != SIZE_MAXIMIZED)
{
- WINDOW_IMP_POST(window_imp->mCallbacks->handleActivate(window_imp, TRUE));
+ WINDOW_IMP_POST(window_imp->mCallbacks->handleActivate(window_imp, true));
}
// Also handle the minimization case
if (w_param == SIZE_MINIMIZED && window_imp->mLastSizeWParam != SIZE_MINIMIZED)
{
- WINDOW_IMP_POST(window_imp->mCallbacks->handleActivate(window_imp, FALSE));
+ WINDOW_IMP_POST(window_imp->mCallbacks->handleActivate(window_imp, false));
}
// Actually resize all of our views
@@ -3012,13 +2998,11 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
window_imp->post([=]()
{
- window_imp->mCallbacks->handleDataCopy(window_imp, myType, data);
+ window_imp->mCallbacks->handleDataCopy(window_imp, (S32)myType, data);
delete[] data;
});
};
return 0;
-
- break;
}
case WM_SETTINGCHANGE:
{
@@ -3027,7 +3011,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
{
if (!SystemParametersInfo(SPI_GETMOUSEVANISH, 0, &window_imp->mMouseVanish, 0))
{
- WINDOW_IMP_POST(window_imp->mMouseVanish = TRUE);
+ WINDOW_IMP_POST(window_imp->mMouseVanish = true);
}
}
}
@@ -3074,8 +3058,8 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
S32 width = GetSystemMetrics(v_desktop ? SM_CXVIRTUALSCREEN : SM_CXSCREEN);
S32 height = GetSystemMetrics(v_desktop ? SM_CYVIRTUALSCREEN : SM_CYSCREEN);
- absolute_x = (raw->data.mouse.lLastX / 65535.0f) * width;
- absolute_y = (raw->data.mouse.lLastY / 65535.0f) * height;
+ absolute_x = (S32)((raw->data.mouse.lLastX / 65535.0f) * width);
+ absolute_y = (S32)((raw->data.mouse.lLastY / 65535.0f) * height);
}
window_imp->mRawMouseDelta.mX += absolute_x - prev_absolute_x;
@@ -3096,13 +3080,14 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
}
else
{
- window_imp->mRawMouseDelta.mX += round((F32)raw->data.mouse.lLastX * (F32)speed / DEFAULT_SPEED);
- window_imp->mRawMouseDelta.mY -= round((F32)raw->data.mouse.lLastY * (F32)speed / DEFAULT_SPEED);
+ window_imp->mRawMouseDelta.mX += (S32)round((F32)raw->data.mouse.lLastX * (F32)speed / DEFAULT_SPEED);
+ window_imp->mRawMouseDelta.mY -= (S32)round((F32)raw->data.mouse.lLastY * (F32)speed / DEFAULT_SPEED);
}
}
}
}
}
+ break;
//list of messages we get often that we don't care to log about
case WM_NCHITTEST:
@@ -3143,7 +3128,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
return ret;
}
-BOOL LLWindowWin32::convertCoords(LLCoordGL from, LLCoordWindow *to)
+bool LLWindowWin32::convertCoords(LLCoordGL from, LLCoordWindow *to) const
{
S32 client_height;
RECT client_rect;
@@ -3153,17 +3138,17 @@ BOOL LLWindowWin32::convertCoords(LLCoordGL from, LLCoordWindow *to)
!GetClientRect(mWindowHandle, &client_rect) ||
NULL == to)
{
- return FALSE;
+ return false;
}
to->mX = from.mX;
client_height = client_rect.bottom - client_rect.top;
to->mY = client_height - from.mY - 1;
- return TRUE;
+ return true;
}
-BOOL LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordGL* to)
+bool LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordGL* to) const
{
S32 client_height;
RECT client_rect;
@@ -3172,23 +3157,23 @@ BOOL LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordGL* to)
!GetClientRect(mWindowHandle, &client_rect) ||
NULL == to)
{
- return FALSE;
+ return false;
}
to->mX = from.mX;
client_height = client_rect.bottom - client_rect.top;
to->mY = client_height - from.mY - 1;
- return TRUE;
+ return true;
}
-BOOL LLWindowWin32::convertCoords(LLCoordScreen from, LLCoordWindow* to)
+bool LLWindowWin32::convertCoords(LLCoordScreen from, LLCoordWindow* to) const
{
POINT mouse_point;
mouse_point.x = from.mX;
mouse_point.y = from.mY;
- BOOL result = ScreenToClient(mWindowHandle, &mouse_point);
+ bool result = ScreenToClient(mWindowHandle, &mouse_point);
if (result)
{
@@ -3199,13 +3184,13 @@ BOOL LLWindowWin32::convertCoords(LLCoordScreen from, LLCoordWindow* to)
return result;
}
-BOOL LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordScreen *to)
+bool LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordScreen *to) const
{
POINT mouse_point;
mouse_point.x = from.mX;
mouse_point.y = from.mY;
- BOOL result = ClientToScreen(mWindowHandle, &mouse_point);
+ bool result = ClientToScreen(mWindowHandle, &mouse_point);
if (result)
{
@@ -3216,44 +3201,44 @@ BOOL LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordScreen *to)
return result;
}
-BOOL LLWindowWin32::convertCoords(LLCoordScreen from, LLCoordGL *to)
+bool LLWindowWin32::convertCoords(LLCoordScreen from, LLCoordGL *to) const
{
LLCoordWindow window_coord;
if (!mWindowHandle || (NULL == to))
{
- return FALSE;
+ return false;
}
convertCoords(from, &window_coord);
convertCoords(window_coord, to);
- return TRUE;
+ return true;
}
-BOOL LLWindowWin32::convertCoords(LLCoordGL from, LLCoordScreen *to)
+bool LLWindowWin32::convertCoords(LLCoordGL from, LLCoordScreen *to) const
{
LLCoordWindow window_coord;
if (!mWindowHandle || (NULL == to))
{
- return FALSE;
+ return false;
}
convertCoords(from, &window_coord);
convertCoords(window_coord, to);
- return TRUE;
+ return true;
}
-BOOL LLWindowWin32::isClipboardTextAvailable()
+bool LLWindowWin32::isClipboardTextAvailable()
{
return IsClipboardFormatAvailable(CF_UNICODETEXT);
}
-BOOL LLWindowWin32::pasteTextFromClipboard(LLWString &dst)
+bool LLWindowWin32::pasteTextFromClipboard(LLWString &dst)
{
- BOOL success = FALSE;
+ bool success = false;
if (IsClipboardFormatAvailable(CF_UNICODETEXT))
{
@@ -3268,7 +3253,7 @@ BOOL LLWindowWin32::pasteTextFromClipboard(LLWString &dst)
dst = utf16str_to_wstring(utf16str);
LLWStringUtil::removeWindowsCR(dst);
GlobalUnlock(h_data);
- success = TRUE;
+ success = true;
}
}
CloseClipboard();
@@ -3279,9 +3264,9 @@ BOOL LLWindowWin32::pasteTextFromClipboard(LLWString &dst)
}
-BOOL LLWindowWin32::copyTextToClipboard(const LLWString& wstr)
+bool LLWindowWin32::copyTextToClipboard(const LLWString& wstr)
{
- BOOL success = FALSE;
+ bool success = false;
if (OpenClipboard(mWindowHandle))
{
@@ -3305,7 +3290,7 @@ BOOL LLWindowWin32::copyTextToClipboard(const LLWString& wstr)
if (SetClipboardData(CF_UNICODETEXT, hglobal_copy_utf16))
{
- success = TRUE;
+ success = true;
}
}
}
@@ -3317,13 +3302,13 @@ BOOL LLWindowWin32::copyTextToClipboard(const LLWString& wstr)
}
// Constrains the mouse to the window.
-void LLWindowWin32::setMouseClipping( BOOL b )
+void LLWindowWin32::setMouseClipping( bool b )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32;
ASSERT_MAIN_THREAD();
if( b != mIsMouseClipping )
{
- BOOL success = FALSE;
+ bool success = false;
if( b )
{
@@ -3349,9 +3334,9 @@ void LLWindowWin32::setMouseClipping( BOOL b )
}
}
-BOOL LLWindowWin32::getClientRectInScreenSpace( RECT* rectp )
+bool LLWindowWin32::getClientRectInScreenSpace( RECT* rectp ) const
{
- BOOL success = FALSE;
+ bool success = false;
RECT client_rect;
if (mWindowHandle && GetClientRect(mWindowHandle, &client_rect))
@@ -3372,7 +3357,7 @@ BOOL LLWindowWin32::getClientRectInScreenSpace( RECT* rectp )
bottom_right.x,
bottom_right.y);
- success = TRUE;
+ success = true;
}
return success;
@@ -3393,41 +3378,41 @@ void LLWindowWin32::flashIcon(F32 seconds)
});
}
-F32 LLWindowWin32::getGamma()
+F32 LLWindowWin32::getGamma() const
{
return mCurrentGamma;
}
-BOOL LLWindowWin32::restoreGamma()
+bool LLWindowWin32::restoreGamma()
{
ASSERT_MAIN_THREAD();
- if (mCustomGammaSet != FALSE)
+ if (mCustomGammaSet)
{
LL_DEBUGS("Window") << "Restoring gamma" << LL_ENDL;
- mCustomGammaSet = FALSE;
+ mCustomGammaSet = false;
return SetDeviceGammaRamp(mhDC, mPrevGammaRamp);
}
- return TRUE;
+ return true;
}
-BOOL LLWindowWin32::setGamma(const F32 gamma)
+bool LLWindowWin32::setGamma(const F32 gamma)
{
ASSERT_MAIN_THREAD();
mCurrentGamma = gamma;
//Get the previous gamma ramp to restore later.
- if (mCustomGammaSet == FALSE)
+ if (!mCustomGammaSet)
{
if (!gGLManager.mIsIntel) // skip for Intel GPUs (see SL-11341)
{
LL_DEBUGS("Window") << "Getting the previous gamma ramp to restore later" << LL_ENDL;
- if(GetDeviceGammaRamp(mhDC, mPrevGammaRamp) == FALSE)
+ if (!GetDeviceGammaRamp(mhDC, mPrevGammaRamp))
{
LL_WARNS("Window") << "Failed to get the previous gamma ramp" << LL_ENDL;
- return FALSE;
+ return false;
}
}
- mCustomGammaSet = TRUE;
+ mCustomGammaSet = true;
}
LL_DEBUGS("Window") << "Setting gamma to " << gamma << LL_ENDL;
@@ -3455,7 +3440,7 @@ void LLWindowWin32::setFSAASamples(const U32 fsaa_samples)
mFSAASamples = fsaa_samples;
}
-U32 LLWindowWin32::getFSAASamples()
+U32 LLWindowWin32::getFSAASamples() const
{
return mFSAASamples;
}
@@ -3482,13 +3467,13 @@ LLWindow::LLWindowResolution* LLWindowWin32::getSupportedResolutions(S32 &num_re
dev_mode.dmPelsWidth >= 800 &&
dev_mode.dmPelsHeight >= 600)
{
- BOOL resolution_exists = FALSE;
+ bool resolution_exists = false;
for(S32 i = 0; i < mNumSupportedResolutions; i++)
{
if (mSupportedResolutions[i].mWidth == dev_mode.dmPelsWidth &&
mSupportedResolutions[i].mHeight == dev_mode.dmPelsHeight)
{
- resolution_exists = TRUE;
+ resolution_exists = true;
}
}
if (!resolution_exists)
@@ -3541,12 +3526,12 @@ F32 LLWindowWin32::getPixelAspectRatio()
// Change display resolution. Returns true if successful.
// protected
-BOOL LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh)
+bool LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh)
{
DEVMODE dev_mode;
::ZeroMemory(&dev_mode, sizeof(DEVMODE));
dev_mode.dmSize = sizeof(DEVMODE);
- BOOL success = FALSE;
+ bool success = false;
// Don't change anything if we don't have to
if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode))
@@ -3557,7 +3542,7 @@ BOOL LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 re
dev_mode.dmDisplayFrequency == refresh )
{
// ...display mode identical, do nothing
- return TRUE;
+ return true;
}
}
@@ -3584,7 +3569,7 @@ BOOL LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 re
}
// protected
-BOOL LLWindowWin32::setFullscreenResolution()
+bool LLWindowWin32::setFullscreenResolution()
{
if (mFullscreen)
{
@@ -3592,18 +3577,18 @@ BOOL LLWindowWin32::setFullscreenResolution()
}
else
{
- return FALSE;
+ return false;
}
}
// protected
-BOOL LLWindowWin32::resetDisplayResolution()
+bool LLWindowWin32::resetDisplayResolution()
{
LL_DEBUGS("Window") << "resetDisplayResolution START" << LL_ENDL;
LONG cds_result = ChangeDisplaySettings(NULL, 0);
- BOOL success = (DISP_CHANGE_SUCCESSFUL == cds_result);
+ bool success = (DISP_CHANGE_SUCCESSFUL == cds_result);
if (!success)
{
@@ -3661,13 +3646,13 @@ void LLSplashScreenWin32::updateImpl(const std::string& mesg)
{
if (!mWindow) return;
- int output_str_len = MultiByteToWideChar(CP_UTF8, 0, mesg.c_str(), mesg.length(), NULL, 0);
+ int output_str_len = MultiByteToWideChar(CP_UTF8, 0, mesg.c_str(), static_cast<int>(mesg.length()), NULL, 0);
if( output_str_len>1024 )
return;
WCHAR w_mesg[1025];//big enought to keep null terminatos
- MultiByteToWideChar (CP_UTF8, 0, mesg.c_str(), mesg.length(), w_mesg, output_str_len);
+ MultiByteToWideChar (CP_UTF8, 0, mesg.c_str(), static_cast<int>(mesg.length()), w_mesg, output_str_len);
//looks like MultiByteToWideChar didn't add null terminator to converted string, see EXT-4858
w_mesg[output_str_len] = 0;
@@ -3725,7 +3710,18 @@ S32 OSMessageBoxWin32(const std::string& text, const std::string& caption, U32 t
break;
}
- int retval_win = MessageBoxW(NULL, // HWND
+ // AG: Of course, the using of the static global variable sWindowHandleForMessageBox
+ // instead of using the field mWindowHandle of the class LLWindowWin32 looks strange.
+ // But in fact, the function OSMessageBoxWin32() doesn't have access to gViewerWindow
+ // because the former is implemented in the library llwindow which is abstract enough.
+ //
+ // "This is why I'm doing it this way, instead of what you would think would be more obvious..."
+ // (C) Nat Goodspeed
+ if (!IsWindow(sWindowHandleForMessageBox))
+ {
+ sWindowHandleForMessageBox = NULL;
+ }
+ int retval_win = MessageBoxW(sWindowHandleForMessageBox, // HWND
ll_convert_string_to_wide(text).c_str(),
ll_convert_string_to_wide(caption).c_str(),
uType);
@@ -3753,6 +3749,23 @@ S32 OSMessageBoxWin32(const std::string& text, const std::string& caption, U32 t
return retval;
}
+void shell_open(const std::string &file, bool async)
+{
+ std::wstring url_utf16 = ll_convert(file);
+
+ // let the OS decide what to use to open the URL
+ SHELLEXECUTEINFO sei = {sizeof(sei)};
+ // NOTE: this assumes that SL will stick around long enough to complete the DDE message exchange
+ // necessary for ShellExecuteEx to complete
+ if (async)
+ {
+ sei.fMask = SEE_MASK_ASYNCOK;
+ }
+ sei.nShow = SW_SHOWNORMAL;
+ sei.lpVerb = L"open";
+ sei.lpFile = url_utf16.c_str();
+ ShellExecuteEx(&sei);
+}
void LLWindowWin32::spawnWebBrowser(const std::string& escaped_url, bool async)
{
@@ -3778,29 +3791,19 @@ void LLWindowWin32::spawnWebBrowser(const std::string& escaped_url, bool async)
// replaced ShellExecute code with ShellExecuteEx since ShellExecute doesn't work
// reliablly on Vista.
- // this is madness.. no, this is..
- LLWString url_wstring = utf8str_to_wstring( escaped_url );
- llutf16string url_utf16 = wstring_to_utf16str( url_wstring );
+ shell_open(escaped_url, async);
+}
- // let the OS decide what to use to open the URL
- SHELLEXECUTEINFO sei = { sizeof( sei ) };
- // NOTE: this assumes that SL will stick around long enough to complete the DDE message exchange
- // necessary for ShellExecuteEx to complete
- if (async)
- {
- sei.fMask = SEE_MASK_ASYNCOK;
- }
- sei.nShow = SW_SHOWNORMAL;
- sei.lpVerb = L"open";
- sei.lpFile = url_utf16.c_str();
- ShellExecuteEx( &sei );
+void LLWindowWin32::openFolder(const std::string &path)
+{
+ shell_open(path, false);
}
/*
Make the raw keyboard data available - used to poke through to LLQtWebKit so
that Qt/Webkit has access to the virtual keycodes etc. that it needs
*/
-LLSD LLWindowWin32::getNativeKeyData()
+LLSD LLWindowWin32::getNativeKeyData() const
{
LLSD result = LLSD::emptyMap();
@@ -3813,9 +3816,9 @@ LLSD LLWindowWin32::getNativeKeyData()
return result;
}
-BOOL LLWindowWin32::dialogColorPicker( F32 *r, F32 *g, F32 *b )
+bool LLWindowWin32::dialogColorPicker( F32 *r, F32 *g, F32 *b )
{
- BOOL retval = FALSE;
+ bool retval = false;
static CHOOSECOLOR cc;
static COLORREF crCustColors[16];
@@ -3868,7 +3871,7 @@ void LLWindowWin32::focusClient()
});
}
-void LLWindowWin32::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b)
+void LLWindowWin32::allowLanguageTextInput(LLPreeditor *preeditor, bool b)
{
if (b == sLanguageTextInputAllowed || !LLWinImm::isAvailable())
{
@@ -3878,7 +3881,7 @@ void LLWindowWin32::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b)
if (preeditor != mPreeditor && !b)
{
// This condition may occur with a call to
- // setEnabled(BOOL) from LLTextEditor or LLLineEditor
+ // setEnabled(bool) from LLTextEditor or LLLineEditor
// when the control is not focused.
// We need to silently ignore the case so that
// the language input status of the focused control
@@ -3908,7 +3911,7 @@ void LLWindowWin32::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b)
if (sWinIMEOpened && GetKeyboardLayout(0) == sWinInputLocale)
{
HIMC himc = LLWinImm::getContext(mWindowHandle);
- LLWinImm::setOpenStatus(himc, TRUE);
+ LLWinImm::setOpenStatus(himc, true);
LLWinImm::setConversionStatus(himc, sWinIMEConversionMode, sWinIMESentenceMode);
LLWinImm::releaseContext(mWindowHandle, himc);
}
@@ -3934,7 +3937,7 @@ void LLWindowWin32::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b)
// We need both ImmSetConversionStatus and ImmSetOpenStatus here to surely disable IME's
// keyboard hooking, because Some IME reacts only on the former and some other on the latter...
LLWinImm::setConversionStatus(himc, IME_CMODE_NOCONVERSION, sWinIMESentenceMode);
- LLWinImm::setOpenStatus(himc, FALSE);
+ LLWinImm::setOpenStatus(himc, false);
}
LLWinImm::releaseContext(mWindowHandle, himc);
}
@@ -4061,14 +4064,14 @@ U32 LLWindowWin32::fillReconvertString(const LLWString &text,
S32 focus, S32 focus_length, RECONVERTSTRING *reconvert_string)
{
const llutf16string text_utf16 = wstring_to_utf16str(text);
- const DWORD required_size = sizeof(RECONVERTSTRING) + (text_utf16.length() + 1) * sizeof(WCHAR);
+ const DWORD required_size = sizeof(RECONVERTSTRING) + (static_cast<DWORD>(text_utf16.length()) + 1) * sizeof(WCHAR);
if (reconvert_string && reconvert_string->dwSize >= required_size)
{
const DWORD focus_utf16_at = wstring_utf16_length(text, 0, focus);
const DWORD focus_utf16_length = wstring_utf16_length(text, focus, focus_length);
reconvert_string->dwVersion = 0;
- reconvert_string->dwStrLen = text_utf16.length();
+ reconvert_string->dwStrLen = static_cast<DWORD>(text_utf16.length());
reconvert_string->dwStrOffset = sizeof(RECONVERTSTRING);
reconvert_string->dwCompStrLen = focus_utf16_length;
reconvert_string->dwCompStrOffset = focus_utf16_at * sizeof(WCHAR);
@@ -4140,7 +4143,7 @@ void LLWindowWin32::handleCompositionMessage(const U32 indexes)
{
return;
}
- BOOL needs_update = FALSE;
+ bool needs_update = false;
LLWString result_string;
LLWString preedit_string;
S32 preedit_string_utf16_length = 0;
@@ -4163,7 +4166,7 @@ void LLWindowWin32::handleCompositionMessage(const U32 indexes)
result_string = utf16str_to_wstring(llutf16string(data, size / sizeof(WCHAR)));
}
delete[] data;
- needs_update = TRUE;
+ needs_update = true;
}
}
@@ -4180,7 +4183,7 @@ void LLWindowWin32::handleCompositionMessage(const U32 indexes)
preedit_string = utf16str_to_wstring(llutf16string(data, size / sizeof(WCHAR)));
}
delete[] data;
- needs_update = TRUE;
+ needs_update = true;
}
}
@@ -4216,13 +4219,13 @@ void LLWindowWin32::handleCompositionMessage(const U32 indexes)
size = LLWinImm::getCompositionString(himc, GCS_COMPATTR, data, size);
if (size == preedit_string_utf16_length)
{
- preedit_standouts.assign(preedit_segment_lengths.size(), FALSE);
+ preedit_standouts.assign(preedit_segment_lengths.size(), false);
S32 offset = 0;
for (U32 i = 0; i < preedit_segment_lengths.size(); i++)
{
if (ATTR_TARGET_CONVERTED == data[offset] || ATTR_TARGET_NOTCONVERTED == data[offset])
{
- preedit_standouts[i] = TRUE;
+ preedit_standouts[i] = true;
}
offset += wstring_utf16_length(preedit_string, offset, preedit_segment_lengths[i]);
}
@@ -4231,7 +4234,7 @@ void LLWindowWin32::handleCompositionMessage(const U32 indexes)
}
}
- S32 caret_position = preedit_string.length();
+ S32 caret_position = static_cast<S32>(preedit_string.length());
if (indexes & GCS_CURSORPOS)
{
const S32 caret_position_utf16 = LLWinImm::getCompositionString(himc, GCS_CURSORPOS, NULL, 0);
@@ -4246,7 +4249,7 @@ void LLWindowWin32::handleCompositionMessage(const U32 indexes)
// I'm not sure this condition really happens, but
// Windows SDK document says it is an indication
// of "reset everything."
- needs_update = TRUE;
+ needs_update = true;
}
LLWinImm::releaseContext(mWindowHandle, himc);
@@ -4277,11 +4280,11 @@ void LLWindowWin32::handleCompositionMessage(const U32 indexes)
{
if (preedit_segment_lengths.size() == 0)
{
- preedit_segment_lengths.assign(1, preedit_string.length());
+ preedit_segment_lengths.assign(1, static_cast<S32>(preedit_string.length()));
}
if (preedit_standouts.size() == 0)
{
- preedit_standouts.assign(preedit_segment_lengths.size(), FALSE);
+ preedit_standouts.assign(preedit_segment_lengths.size(), false);
}
}
mPreeditor->updatePreedit(preedit_string, preedit_segment_lengths, preedit_standouts, caret_position);
@@ -4328,11 +4331,11 @@ LLWindowCallbacks::DragNDropResult LLWindowWin32::completeDragNDropRequest( cons
}
// Handle WM_IME_REQUEST message.
-// If it handled the message, returns TRUE. Otherwise, FALSE.
+// If it handled the message, returns true. Otherwise, false.
// When it handled the message, the value to be returned from
// the Window Procedure is set to *result.
-BOOL LLWindowWin32::handleImeRequests(WPARAM request, LPARAM param, LRESULT *result)
+bool LLWindowWin32::handleImeRequests(WPARAM request, LPARAM param, LRESULT *result)
{
if ( mPreeditor )
{
@@ -4350,7 +4353,7 @@ BOOL LLWindowWin32::handleImeRequests(WPARAM request, LPARAM param, LRESULT *res
form->dwIndex = dwIndex;
*result = 1;
- return TRUE;
+ return true;
}
case IMR_QUERYCHARPOSITION:
{
@@ -4370,20 +4373,20 @@ BOOL LLWindowWin32::handleImeRequests(WPARAM request, LPARAM param, LRESULT *res
if (!mPreeditor->getPreeditLocation(position, &caret_coord, &preedit_bounds, &text_control))
{
LL_WARNS("Window") << "*** IMR_QUERYCHARPOSITON called but getPreeditLocation failed." << LL_ENDL;
- return FALSE;
+ return false;
}
fillCharPosition(caret_coord, preedit_bounds, text_control, char_position);
*result = 1;
- return TRUE;
+ return true;
}
case IMR_COMPOSITIONFONT:
{
fillCompositionLogfont((LOGFONT *)param);
*result = 1;
- return TRUE;
+ return true;
}
case IMR_RECONVERTSTRING:
{
@@ -4404,7 +4407,7 @@ BOOL LLWindowWin32::handleImeRequests(WPARAM request, LPARAM param, LRESULT *res
// Let the IME to decide the reconversion range, and
// adjust the reconvert_string structure accordingly.
HIMC himc = LLWinImm::getContext(mWindowHandle);
- const BOOL adjusted = LLWinImm::setCompositionString(himc,
+ const bool adjusted = LLWinImm::setCompositionString(himc,
SCS_QUERYRECONVERTSTRING, reconvert_string, size, NULL, 0);
LLWinImm::releaseContext(mWindowHandle, himc);
if (adjusted)
@@ -4421,12 +4424,12 @@ BOOL LLWindowWin32::handleImeRequests(WPARAM request, LPARAM param, LRESULT *res
}
*result = size;
- return TRUE;
+ return true;
}
case IMR_CONFIRMRECONVERTSTRING:
{
- *result = FALSE;
- return TRUE;
+ *result = 0;
+ return true;
}
case IMR_DOCUMENTFEED:
{
@@ -4448,14 +4451,14 @@ BOOL LLWindowWin32::handleImeRequests(WPARAM request, LPARAM param, LRESULT *res
RECONVERTSTRING *reconvert_string = (RECONVERTSTRING *)param;
*result = fillReconvertString(context, preedit, 0, reconvert_string);
- return TRUE;
+ return true;
}
default:
- return FALSE;
+ return false;
}
}
- return FALSE;
+ return false;
}
//static
@@ -4581,12 +4584,6 @@ std::vector<std::string> LLWindowWin32::getDynamicFallbackFontList()
// Fonts previously in getFontListSans() have moved to fonts.xml.
return std::vector<std::string>();
}
-
-U32 LLWindowWin32::getAvailableVRAMMegabytes()
-{
- return mWindowThread ? mWindowThread->getAvailableVRAMMegabytes() : 0;
-}
-
#endif // LL_WINDOWS
inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread()
@@ -4641,41 +4638,63 @@ private:
std::string mPrev;
};
-// Print hardware debug info about available graphics adapters in ordinal order
-void debugEnumerateGraphicsAdapters()
+void LLWindowWin32::LLWindowWin32Thread::checkDXMem()
{
- LL_INFOS("Window") << "Enumerating graphics adapters..." << LL_ENDL;
+ if (!mGLReady || mGotGLBuffer) { return; }
+
+ if ((gGLManager.mHasAMDAssociations || gGLManager.mHasNVXGpuMemoryInfo) && gGLManager.mVRAM != 0)
+ { // OpenGL already told us the memory budget, don't ask DX
+ mGotGLBuffer = true;
+ return;
+ }
+
+ IDXGIFactory4* p_factory = nullptr;
+
+ HRESULT res = CreateDXGIFactory1(__uuidof(IDXGIFactory4), (void**)&p_factory);
- IDXGIFactory1* factory;
- HRESULT res = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&factory);
- if (FAILED(res) || !factory)
+ if (FAILED(res))
{
LL_WARNS() << "CreateDXGIFactory1 failed: 0x" << std::hex << res << LL_ENDL;
}
else
{
+ IDXGIAdapter3* p_dxgi_adapter = nullptr;
UINT graphics_adapter_index = 0;
- IDXGIAdapter3* dxgi_adapter;
while (true)
{
- res = factory->EnumAdapters(graphics_adapter_index, reinterpret_cast<IDXGIAdapter**>(&dxgi_adapter));
+ res = p_factory->EnumAdapters(graphics_adapter_index, reinterpret_cast<IDXGIAdapter**>(&p_dxgi_adapter));
if (FAILED(res))
{
if (graphics_adapter_index == 0)
{
LL_WARNS() << "EnumAdapters failed: 0x" << std::hex << res << LL_ENDL;
}
- else
- {
- LL_INFOS("Window") << "Done enumerating graphics adapters" << LL_ENDL;
- }
}
else
{
+ if (graphics_adapter_index == 0) // Should it check largest one isntead of first?
+ {
+ DXGI_QUERY_VIDEO_MEMORY_INFO info;
+ p_dxgi_adapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &info);
+
+ // Alternatively use GetDesc from below to get adapter's memory
+ UINT64 budget_mb = info.Budget / (1024 * 1024);
+ if (gGLManager.mVRAM < (S32)budget_mb)
+ {
+ gGLManager.mVRAM = (S32)budget_mb;
+ LL_INFOS("RenderInit") << "New VRAM Budget (DX9): " << gGLManager.mVRAM << " MB" << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS("RenderInit") << "VRAM Budget (DX9): " << budget_mb
+ << " MB, current (WMI): " << gGLManager.mVRAM << " MB" << LL_ENDL;
+ }
+ }
+
DXGI_ADAPTER_DESC desc;
- dxgi_adapter->GetDesc(&desc);
+ p_dxgi_adapter->GetDesc(&desc);
std::wstring description_w((wchar_t*)desc.Description);
- std::string description(description_w.begin(), description_w.end());
+ std::string description = ll_convert_wide_to_string(description_w);
LL_INFOS("Window") << "Graphics adapter index: " << graphics_adapter_index << ", "
<< "Description: " << description << ", "
<< "DeviceId: " << desc.DeviceId << ", "
@@ -4686,10 +4705,10 @@ void debugEnumerateGraphicsAdapters()
<< "SharedSystemMemory: " << desc.SharedSystemMemory / 1024 / 1024 << LL_ENDL;
}
- if (dxgi_adapter)
+ if (p_dxgi_adapter)
{
- dxgi_adapter->Release();
- dxgi_adapter = NULL;
+ p_dxgi_adapter->Release();
+ p_dxgi_adapter = NULL;
}
else
{
@@ -4700,168 +4719,12 @@ void debugEnumerateGraphicsAdapters()
}
}
- if (factory)
- {
- factory->Release();
- }
-}
-
-void LLWindowWin32::LLWindowWin32Thread::initDX()
-{
- if (!mGLReady) { return; }
-
- if (mDXGIAdapter == NULL)
- {
- debugEnumerateGraphicsAdapters();
-
- IDXGIFactory4* pFactory = nullptr;
-
- HRESULT res = CreateDXGIFactory1(__uuidof(IDXGIFactory4), (void**)&pFactory);
-
- if (FAILED(res))
- {
- LL_WARNS() << "CreateDXGIFactory1 failed: 0x" << std::hex << res << LL_ENDL;
- }
- else
- {
- res = pFactory->EnumAdapters(0, reinterpret_cast<IDXGIAdapter**>(&mDXGIAdapter));
- if (FAILED(res))
- {
- LL_WARNS() << "EnumAdapters failed: 0x" << std::hex << res << LL_ENDL;
- }
- else
- {
- LL_INFOS() << "EnumAdapters success" << LL_ENDL;
- }
- }
-
- if (pFactory)
- {
- pFactory->Release();
- }
- }
-}
-
-void LLWindowWin32::LLWindowWin32Thread::initD3D()
-{
- if (!mGLReady) { return; }
-
- if (mDXGIAdapter == NULL && mD3DDevice == NULL && mWindowHandleThrd != 0)
- {
- mD3D = Direct3DCreate9(D3D_SDK_VERSION);
-
- D3DPRESENT_PARAMETERS d3dpp;
-
- ZeroMemory(&d3dpp, sizeof(d3dpp));
- d3dpp.Windowed = TRUE;
- d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
-
- HRESULT res = mD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, mWindowHandleThrd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &mD3DDevice);
-
- if (FAILED(res))
- {
- LL_WARNS() << "(fallback) CreateDevice failed: 0x" << std::hex << res << LL_ENDL;
- }
- else
- {
- LL_INFOS() << "(fallback) CreateDevice success" << LL_ENDL;
- }
- }
-}
-
-void LLWindowWin32::LLWindowWin32Thread::cleanupDX()
-{
- //clean up DXGI/D3D resources
- if (mDXGIAdapter)
+ if (p_factory)
{
- mDXGIAdapter->Release();
- mDXGIAdapter = nullptr;
+ p_factory->Release();
}
- if (mD3DDevice)
- {
- mD3DDevice->Release();
- mD3DDevice = nullptr;
- }
-
- if (mD3D)
- {
- mD3D->Release();
- mD3D = nullptr;
- }
-}
-
-void LLWindowWin32::LLWindowWin32Thread::updateVRAMUsage()
-{
- LL_PROFILE_ZONE_SCOPED;
- if (!mGLReady) { return; }
-
- if (mDXGIAdapter != nullptr)
- {
- // NOTE: what lies below is hand wavy math based on compatibility testing and observation against a variety of hardware
- // It doesn't make sense, but please don't refactor it to make sense. -- davep
-
- DXGI_QUERY_VIDEO_MEMORY_INFO info;
- mDXGIAdapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &info);
-#if 0 // debug 0 budget and 0 CU
- info.Budget = 0;
- info.CurrentUsage = 0;
-#endif
-
- U32 budget_mb = info.Budget / 1024 / 1024;
- gGLManager.mVRAM = llmax(gGLManager.mVRAM, (S32) budget_mb);
-
- U32 afr_mb = info.AvailableForReservation / 1024 / 1024;
- // correct for systems that misreport budget
- if (budget_mb == 0)
- {
- // fall back to available for reservation clamped between 512MB and 2GB
- budget_mb = llclamp(afr_mb, (U32) 512, (U32) 2048);
- }
-
- if ( mMaxVRAM != 0)
- {
- budget_mb = llmin(budget_mb, mMaxVRAM);
- }
-
- U32 cu_mb = info.CurrentUsage / 1024 / 1024;
-
- // get an estimated usage based on texture bytes allocated
- U32 eu_mb = LLImageGL::getTextureBytesAllocated() * 2 / 1024 / 1024;
-
- if (cu_mb == 0)
- { // current usage is sometimes unreliable on Intel GPUs, fall back to estimated usage
- cu_mb = llmax((U32)1, eu_mb);
- }
- U32 target_mb = budget_mb;
-
- if (target_mb > 4096) // if 4GB are installed, try to leave 2GB free
- {
- target_mb -= 2048;
- }
- else // if less than 4GB are installed, try not to use more than half of it
- {
- target_mb /= 2;
- }
-
- mAvailableVRAM = cu_mb < target_mb ? target_mb - cu_mb : 0;
-
-#if 0
-
- F32 eu_error = (F32)((S32)eu_mb - (S32)cu_mb) / (F32)cu_mb;
- LL_INFOS("Window") << "\nLocal\nAFR: " << info.AvailableForReservation / 1024 / 1024
- << "\nBudget: " << info.Budget / 1024 / 1024
- << "\nCR: " << info.CurrentReservation / 1024 / 1024
- << "\nCU: " << info.CurrentUsage / 1024 / 1024
- << "\nEU: " << eu_mb << llformat(" (%.2f)", eu_error)
- << "\nTU: " << target_mb
- << "\nAM: " << mAvailableVRAM << LL_ENDL;
-#endif
- }
- else if (mD3DDevice != NULL)
- { // fallback to D3D9
- mAvailableVRAM = mD3DDevice->GetAvailableTextureMem() / 1024 / 1024;
- }
+ mGotGLBuffer = true;
}
void LLWindowWin32::LLWindowWin32Thread::run()
@@ -4881,15 +4744,11 @@ void LLWindowWin32::LLWindowWin32Thread::run()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32;
- // lazily call initD3D inside this loop to catch when mGLReady has been set to true
- initDX();
+ // Check memory budget using DirectX if OpenGL doesn't have the means to tell us
+ checkDXMem();
if (mWindowHandleThrd != 0)
{
- // lazily call initD3D inside this loop to catch when mWindowHandle has been set, and mGLReady has been set to true
- // *TODO: Shutdown if this fails when mWindowHandle exists
- initD3D();
-
MSG msg;
BOOL status;
if (mhDCThrd == 0)
@@ -4922,13 +4781,6 @@ void LLWindowWin32::LLWindowWin32Thread::run()
getQueue().runPending();
}
- // update available vram once every 3 seconds
- static LLFrameTimer vramTimer;
- if (vramTimer.getElapsedTimeF32() > 3.f)
- {
- updateVRAMUsage();
- vramTimer.reset();
- }
#if 0
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("w32t - Sleep");
@@ -4939,7 +4791,6 @@ void LLWindowWin32::LLWindowWin32Thread::run()
}
destroyWindow();
- cleanupDX();
if (mDeleteOnExit)
{
diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h
index 33fa67ba50..f4964d064e 100644
--- a/indra/llwindow/llwindowwin32.h
+++ b/indra/llwindow/llwindowwin32.h
@@ -28,7 +28,7 @@
#define LL_LLWINDOWWIN32_H
// Limit Windows API to small and manageable set.
-#include "llwin32headerslean.h"
+#include "llwin32headers.h"
#include "llwindow.h"
#include "llwindowcallbacks.h"
@@ -45,84 +45,82 @@ typedef void (*LLW32MsgCallback)(const MSG &msg);
class LLWindowWin32 : public LLWindow
{
public:
- /*virtual*/ void show();
- /*virtual*/ void hide();
- /*virtual*/ void close();
- /*virtual*/ BOOL getVisible();
- /*virtual*/ BOOL getMinimized();
- /*virtual*/ BOOL getMaximized();
- /*virtual*/ BOOL maximize();
- /*virtual*/ void minimize();
- /*virtual*/ void restore();
- /*virtual*/ BOOL getFullscreen();
- /*virtual*/ BOOL getPosition(LLCoordScreen *position);
- /*virtual*/ BOOL getSize(LLCoordScreen *size);
- /*virtual*/ BOOL getSize(LLCoordWindow *size);
- /*virtual*/ BOOL setPosition(LLCoordScreen position);
- /*virtual*/ BOOL setSizeImpl(LLCoordScreen size);
- /*virtual*/ BOOL setSizeImpl(LLCoordWindow size);
- /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL);
- /*virtual*/ void setTitle(const std::string title);
+ void show() override;
+ void hide() override;
+ void close() override;
+ bool getVisible() const override;
+ bool getMinimized() const override;
+ bool getMaximized() const override;
+ bool maximize() override;
+ void minimize() override;
+ void restore() override;
+ bool getPosition(LLCoordScreen *position) const override;
+ bool getSize(LLCoordScreen *size) const override;
+ bool getSize(LLCoordWindow *size) const override;
+ bool setPosition(LLCoordScreen position) override;
+ bool setSizeImpl(LLCoordScreen size) override;
+ bool setSizeImpl(LLCoordWindow size) override;
+ bool switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp = NULL) override;
+ void setTitle(const std::string title) override;
void* createSharedContext() override;
void makeContextCurrent(void* context) override;
void destroySharedContext(void* context) override;
- /*virtual*/ void toggleVSync(bool enable_vsync);
- /*virtual*/ BOOL setCursorPosition(LLCoordWindow position);
- /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position);
- /*virtual*/ BOOL getCursorDelta(LLCoordCommon* delta);
- /*virtual*/ void showCursor();
- /*virtual*/ void hideCursor();
- /*virtual*/ void showCursorFromMouseMove();
- /*virtual*/ void hideCursorUntilMouseMove();
- /*virtual*/ BOOL isCursorHidden();
- /*virtual*/ void updateCursor();
- /*virtual*/ ECursorType getCursor() const;
- /*virtual*/ void captureMouse();
- /*virtual*/ void releaseMouse();
- /*virtual*/ void setMouseClipping( BOOL b );
- /*virtual*/ BOOL isClipboardTextAvailable();
- /*virtual*/ BOOL pasteTextFromClipboard(LLWString &dst);
- /*virtual*/ BOOL copyTextToClipboard(const LLWString &src);
- /*virtual*/ void flashIcon(F32 seconds);
- /*virtual*/ F32 getGamma();
- /*virtual*/ BOOL setGamma(const F32 gamma); // Set the gamma
- /*virtual*/ void setFSAASamples(const U32 fsaa_samples);
- /*virtual*/ U32 getFSAASamples();
- /*virtual*/ BOOL restoreGamma(); // Restore original gamma table (before updating gamma)
- /*virtual*/ ESwapMethod getSwapMethod() { return mSwapMethod; }
- /*virtual*/ void gatherInput();
- /*virtual*/ void delayInputProcessing();
- /*virtual*/ void swapBuffers();
- /*virtual*/ void restoreGLContext() {};
+ void toggleVSync(bool enable_vsync) override;
+ bool setCursorPosition(LLCoordWindow position) override;
+ bool getCursorPosition(LLCoordWindow *position) override;
+ bool getCursorDelta(LLCoordCommon* delta) const override;
+ void showCursor() override;
+ void hideCursor() override;
+ void showCursorFromMouseMove() override;
+ void hideCursorUntilMouseMove() override;
+ bool isCursorHidden() override;
+ void updateCursor() override;
+ ECursorType getCursor() const override;
+ void captureMouse() override;
+ void releaseMouse() override;
+ void setMouseClipping( bool b ) override;
+ bool isClipboardTextAvailable() override;
+ bool pasteTextFromClipboard(LLWString &dst) override;
+ bool copyTextToClipboard(const LLWString &src) override;
+ void flashIcon(F32 seconds) override;
+ F32 getGamma() const override;
+ bool setGamma(const F32 gamma) override; // Set the gamma
+ void setFSAASamples(const U32 fsaa_samples) override;
+ U32 getFSAASamples() const override;
+ bool restoreGamma() override; // Restore original gamma table (before updating gamma)
+ void gatherInput(bool app_has_focus) override;
+ void delayInputProcessing() override;
+ void swapBuffers() override;
+ void restoreGLContext() {};
// handy coordinate space conversion routines
- /*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to);
- /*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordScreen *to);
- /*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordGL *to);
- /*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordWindow *to);
- /*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordGL *to);
- /*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordScreen *to);
+ bool convertCoords(LLCoordScreen from, LLCoordWindow *to) const override;
+ bool convertCoords(LLCoordWindow from, LLCoordScreen *to) const override;
+ bool convertCoords(LLCoordWindow from, LLCoordGL *to) const override;
+ bool convertCoords(LLCoordGL from, LLCoordWindow *to) const override;
+ bool convertCoords(LLCoordScreen from, LLCoordGL *to) const override;
+ bool convertCoords(LLCoordGL from, LLCoordScreen *to) const override;
- /*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions);
- /*virtual*/ F32 getNativeAspectRatio();
- /*virtual*/ F32 getPixelAspectRatio();
- /*virtual*/ void setNativeAspectRatio(F32 ratio) { mOverrideAspectRatio = ratio; }
+ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) override;
+ F32 getNativeAspectRatio() override;
+ F32 getPixelAspectRatio() override;
+ void setNativeAspectRatio(F32 ratio) override { mOverrideAspectRatio = ratio; }
- U32 getAvailableVRAMMegabytes() override;
+ bool dialogColorPicker(F32 *r, F32 *g, F32 *b ) override;
- /*virtual*/ BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b );
+ void *getPlatformWindow() override;
+ void bringToFront() override;
+ void focusClient() override;
- /*virtual*/ void *getPlatformWindow();
- /*virtual*/ void bringToFront();
- /*virtual*/ void focusClient();
+ void allowLanguageTextInput(LLPreeditor *preeditor, bool b) override;
+ void setLanguageTextInput( const LLCoordGL & pos ) override;
+ void updateLanguageTextInputArea() override;
+ void interruptLanguageTextInput() override;
+ void spawnWebBrowser(const std::string& escaped_url, bool async) override;
- /*virtual*/ void allowLanguageTextInput(LLPreeditor *preeditor, BOOL b);
- /*virtual*/ void setLanguageTextInput( const LLCoordGL & pos );
- /*virtual*/ void updateLanguageTextInputArea();
- /*virtual*/ void interruptLanguageTextInput();
- /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async);
+ void openFolder(const std::string &path) override;
- /*virtual*/ F32 getSystemUISize();
+ F32 getSystemUISize() override;
LLWindowCallbacks::DragNDropResult completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url );
@@ -130,58 +128,54 @@ public:
static std::vector<std::string> getDynamicFallbackFontList();
static void setDPIAwareness();
- /*virtual*/ void* getDirectInput8();
- /*virtual*/ bool getInputDevices(U32 device_type_filter,
+ void* getDirectInput8() override;
+ bool getInputDevices(U32 device_type_filter,
std::function<bool(std::string&, LLSD&, void*)> osx_callback,
void* win_callback,
- void* userdata);
+ void* userdata) override;
- U32 getRawWParam() { return mRawWParam; }
+ U32 getRawWParam() const { return mRawWParam; }
protected:
LLWindowWin32(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,
- BOOL fullscreen, BOOL clearBg, BOOL enable_vsync, BOOL use_gl,
- BOOL ignore_pixel_depth, U32 fsaa_samples, U32 max_cores, U32 max_vram, F32 max_gl_version);
+ bool fullscreen, bool clearBg, bool enable_vsync, bool use_gl,
+ bool ignore_pixel_depth, U32 fsaa_samples, U32 max_cores, F32 max_gl_version);
~LLWindowWin32();
void initCursors();
- void initInputDevices();
HCURSOR loadColorCursor(LPCTSTR name);
- BOOL isValid();
+ bool isValid();
void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size);
- virtual LLSD getNativeKeyData();
+ LLSD getNativeKeyData() const override;
// Changes display resolution. Returns true if successful
- BOOL setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
+ bool setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
// Go back to last fullscreen display resolution.
- BOOL setFullscreenResolution();
+ bool setFullscreenResolution();
// Restore the display resolution to its value before we ran the app.
- BOOL resetDisplayResolution();
+ bool resetDisplayResolution();
- BOOL shouldPostQuit() { return mPostQuit; }
+ bool shouldPostQuit() { return mPostQuit; }
- void fillCompositionForm(const LLRect& bounds, COMPOSITIONFORM *form);
void fillCandidateForm(const LLCoordGL& caret, const LLRect& bounds, CANDIDATEFORM *form);
void fillCharPosition(const LLCoordGL& caret, const LLRect& bounds, const LLRect& control, IMECHARPOSITION *char_position);
void fillCompositionLogfont(LOGFONT *logfont);
U32 fillReconvertString(const LLWString &text, S32 focus, S32 focus_length, RECONVERTSTRING *reconvert_string);
void handleStartCompositionMessage();
void handleCompositionMessage(U32 indexes);
- BOOL handleImeRequests(WPARAM request, LPARAM param, LRESULT *result);
+ bool handleImeRequests(WPARAM request, LPARAM param, LRESULT *result);
protected:
//
// Platform specific methods
//
- BOOL getClientRectInScreenSpace(RECT* rectp);
- void updateJoystick( );
+ bool getClientRectInScreenSpace(RECT* rectp) const;
static LRESULT CALLBACK mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_param, LPARAM l_param);
- static BOOL CALLBACK enumChildWindows(HWND h_wnd, LPARAM l_param);
//
@@ -209,7 +203,7 @@ protected:
MASK mMouseMask;
- static BOOL sIsClassRegistered; // has the window class been registered?
+ static bool sIsClassRegistered; // has the window class been registered?
F32 mCurrentGamma;
U32 mFSAASamples;
@@ -217,16 +211,16 @@ protected:
F32 mMaxGLVersion; // maximum OpenGL version to attempt to use (clamps to 3.2 - 4.6)
WORD mPrevGammaRamp[3][256];
WORD mCurrentGammaRamp[3][256];
- BOOL mCustomGammaSet;
+ bool mCustomGammaSet;
LPWSTR mIconResource;
- BOOL mInputProcessingPaused;
+ bool mInputProcessingPaused;
// The following variables are for Language Text Input control.
// They are all static, since one context is shared by all LLWindowWin32
// instances.
- static BOOL sLanguageTextInputAllowed;
- static BOOL sWinIMEOpened;
+ static bool sLanguageTextInputAllowed;
+ static bool sWinIMEOpened;
static HKL sWinInputLocale;
static DWORD sWinIMEConversionMode;
static DWORD sWinIMESentenceMode;
@@ -245,7 +239,7 @@ protected:
U32 mRawWParam;
U32 mRawLParam;
- BOOL mMouseVanish;
+ bool mMouseVanish;
// Cached values of GetWindowRect and GetClientRect to be used by app thread
void updateWindowRect();
@@ -270,9 +264,9 @@ public:
LLSplashScreenWin32();
virtual ~LLSplashScreenWin32();
- /*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;
#if LL_WINDOWS
static LRESULT CALLBACK windowProc(HWND h_wnd, UINT u_msg,
@@ -288,8 +282,6 @@ private:
extern LLW32MsgCallback gAsyncMsgCallback;
extern LPWSTR gIconResource;
-static void handleMessage( const MSG& msg );
-
S32 OSMessageBoxWin32(const std::string& text, const std::string& caption, U32 type);
#endif //LL_LLWINDOWWIN32_H