diff --git a/client/SDL/SDL2/man/CMakeLists.txt b/client/SDL/SDL2/man/CMakeLists.txt index 2dfb6516f..9483e2b38 100644 --- a/client/SDL/SDL2/man/CMakeLists.txt +++ b/client/SDL/SDL2/man/CMakeLists.txt @@ -10,5 +10,6 @@ set(DEPS include(GetSysconfDir) get_sysconf_dir("" SYSCONF_DIR) -set(VAR_NAMES "VENDOR" "PRODUCT" "VENDOR_PRODUCT" "SYSCONF_DIR") +set(SDL_WIKI_BASE_URL "https://wiki.libsdl.org/SDL2") +set(VAR_NAMES "VENDOR" "PRODUCT" "VENDOR_PRODUCT" "SYSCONF_DIR" "SDL_WIKI_BASE_URL") generate_and_install_freerdp_man_from_xml(${MODULE_NAME} "1" "${DEPS}" "${VAR_NAMES}") diff --git a/client/SDL/SDL2/sdl_kbd.cpp b/client/SDL/SDL2/sdl_kbd.cpp index 1a3db8cae..25159e812 100644 --- a/client/SDL/SDL2/sdl_kbd.cpp +++ b/client/SDL/SDL2/sdl_kbd.cpp @@ -386,29 +386,65 @@ BOOL sdlInput::keyboard_set_ime_status(rdpContext* context, UINT16 imeId, UINT32 return TRUE; } -uint32_t sdlInput::prefToMask() +static const std::map& getSdlMap() { - const std::map mapping = { - { "KMOD_LSHIFT", KMOD_LSHIFT }, { "KMOD_RSHIFT", KMOD_RSHIFT }, - { "KMOD_LCTRL", KMOD_LCTRL }, { "KMOD_RCTRL", KMOD_RCTRL }, - { "KMOD_LALT", KMOD_LALT }, { "KMOD_RALT", KMOD_RALT }, - { "KMOD_LGUI", KMOD_LGUI }, { "KMOD_RGUI", KMOD_RGUI }, - { "KMOD_NUM", KMOD_NUM }, { "KMOD_CAPS", KMOD_CAPS }, + static std::map s_map = { + { "KMOD_LSHIFT", KMOD_LSHIFT }, { "KMOD_RSHIFT", KMOD_RSHIFT }, + { "KMOD_LCTRL", KMOD_LCTRL }, { "KMOD_RCTRL", KMOD_RCTRL }, + { "KMOD_LALT", KMOD_LALT }, { "KMOD_RALT", KMOD_RALT }, + { "KMOD_LGUI", KMOD_LGUI }, { "KMOD_RGUI", KMOD_RGUI }, + { "KMOD_NUM", KMOD_NUM }, { "KMOD_CAPS", KMOD_CAPS }, { "KMOD_MODE", KMOD_MODE }, #if SDL_VERSION_ATLEAST(2, 0, 18) { "KMOD_SCROLL", KMOD_SCROLL }, #endif - { "KMOD_CTRL", KMOD_CTRL }, { "KMOD_SHIFT", KMOD_SHIFT }, - { "KMOD_ALT", KMOD_ALT }, { "KMOD_GUI", KMOD_GUI } + { "KMOD_CTRL", KMOD_CTRL }, { "KMOD_SHIFT", KMOD_SHIFT }, + { "KMOD_ALT", KMOD_ALT }, { "KMOD_GUI", KMOD_GUI }, + { "KMOD_NONE", KMOD_NONE }, { "SDL_KMOD_LSHIFT", KMOD_LSHIFT }, + { "SDL_KMOD_RSHIFT", KMOD_RSHIFT }, { "SDL_KMOD_LCTRL", KMOD_LCTRL }, + { "SDL_KMOD_RCTRL", KMOD_RCTRL }, { "SDL_KMOD_LALT", KMOD_LALT }, + { "SDL_KMOD_RALT", KMOD_RALT }, { "SDL_KMOD_LGUI", KMOD_LGUI }, + { "SDL_KMOD_RGUI", KMOD_RGUI }, { "SDL_KMOD_NUM", KMOD_NUM }, + { "SDL_KMOD_CAPS", KMOD_CAPS }, { "SDL_KMOD_MODE", KMOD_MODE }, + { "SDL_KMOD_SCROLL", KMOD_SCROLL }, { "SDL_KMOD_CTRL", KMOD_CTRL }, + { "SDL_KMOD_SHIFT", KMOD_SHIFT }, { "SDL_KMOD_ALT", KMOD_ALT }, + { "SDL_KMOD_GUI", KMOD_GUI }, { "SDL_KMOD_NONE", KMOD_NONE } }; + + return s_map; +} + +bool sdlInput::prefToEnabled() +{ + bool enable = true; + const auto& m = getSdlMap(); + for (const auto& val : SdlPref::instance()->get_array("SDL_KeyModMask", { "KMOD_RSHIFT" })) + { + auto it = m.find(val); + if (it != m.end()) + { + if (it->second == KMOD_NONE) + enable = false; + } + else + { + WLog_WARN(TAG, "Invalid config::SDL_KeyModMask entry value '%s', disabling hotkeys", + val.c_str()); + enable = false; + } + } + return enable; +} + +uint32_t sdlInput::prefToMask() +{ + const auto& mapping = getSdlMap(); uint32_t mod = KMOD_NONE; for (const auto& val : SdlPref::instance()->get_array("SDL_KeyModMask", { "KMOD_RSHIFT" })) { auto it = mapping.find(val); if (it != mapping.end()) - { mod |= it->second; - } } return mod; } @@ -483,7 +519,7 @@ BOOL sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) const UINT32 rdp_scancode = sdl_scancode_to_rdp(ev->keysym.scancode); const SDL_Keymod mods = SDL_GetModState(); - if ((mods & _hotkeyModmask) == _hotkeyModmask) + if (_hotkeysEnabled && (mods & _hotkeyModmask) == _hotkeyModmask) { if (ev->type == SDL_KEYDOWN) { @@ -556,7 +592,8 @@ BOOL sdlInput::mouse_grab(Uint32 windowID, SDL_bool enable) } sdlInput::sdlInput(SdlContext* sdl) - : _sdl(sdl), _lastWindowID(UINT32_MAX), _hotkeyModmask(prefToMask()) + : _sdl(sdl), _lastWindowID(UINT32_MAX), _hotkeysEnabled(prefToEnabled()), + _hotkeyModmask(prefToMask()) { auto list = freerdp_settings_get_string(_sdl->context()->settings, FreeRDP_KeyboardRemappingList); diff --git a/client/SDL/SDL2/sdl_kbd.hpp b/client/SDL/SDL2/sdl_kbd.hpp index 802e077af..e65e8ccac 100644 --- a/client/SDL/SDL2/sdl_kbd.hpp +++ b/client/SDL/SDL2/sdl_kbd.hpp @@ -55,6 +55,7 @@ class sdlInput static BOOL keyboard_set_ime_status(rdpContext* context, UINT16 imeId, UINT32 imeState, UINT32 imeConvMode); + static bool prefToEnabled(); static uint32_t prefToMask(); static uint32_t prefKeyValue(const std::string& key, uint32_t fallback = SDL_SCANCODE_UNKNOWN); @@ -67,6 +68,7 @@ class sdlInput Uint32 _lastWindowID; // hotkey handling + bool _hotkeysEnabled; uint32_t _hotkeyModmask; // modifier keys mask uint32_t _hotkeyFullscreen; uint32_t _hotkeyResizable; diff --git a/client/SDL/SDL3/man/CMakeLists.txt b/client/SDL/SDL3/man/CMakeLists.txt index 2dfb6516f..22756aa1e 100644 --- a/client/SDL/SDL3/man/CMakeLists.txt +++ b/client/SDL/SDL3/man/CMakeLists.txt @@ -10,5 +10,6 @@ set(DEPS include(GetSysconfDir) get_sysconf_dir("" SYSCONF_DIR) -set(VAR_NAMES "VENDOR" "PRODUCT" "VENDOR_PRODUCT" "SYSCONF_DIR") +set(SDL_WIKI_BASE_URL "https://wiki.libsdl.org/SDL3") +set(VAR_NAMES "VENDOR" "PRODUCT" "VENDOR_PRODUCT" "SYSCONF_DIR" "SDL_WIKI_BASE_URL") generate_and_install_freerdp_man_from_xml(${MODULE_NAME} "1" "${DEPS}" "${VAR_NAMES}") diff --git a/client/SDL/SDL3/sdl_kbd.cpp b/client/SDL/SDL3/sdl_kbd.cpp index e5143a96a..4330b53aa 100644 --- a/client/SDL/SDL3/sdl_kbd.cpp +++ b/client/SDL/SDL3/sdl_kbd.cpp @@ -376,14 +376,23 @@ BOOL sdlInput::keyboard_set_ime_status(rdpContext* context, UINT16 imeId, UINT32 static const std::map& getSdlMap() { static std::map s_map = { - { "KMOD_LSHIFT", SDL_KMOD_LSHIFT }, { "KMOD_RSHIFT", SDL_KMOD_RSHIFT }, - { "KMOD_LCTRL", SDL_KMOD_LCTRL }, { "KMOD_RCTRL", SDL_KMOD_RCTRL }, - { "KMOD_LALT", SDL_KMOD_LALT }, { "KMOD_RALT", SDL_KMOD_RALT }, - { "KMOD_LGUI", SDL_KMOD_LGUI }, { "KMOD_RGUI", SDL_KMOD_RGUI }, - { "KMOD_NUM", SDL_KMOD_NUM }, { "KMOD_CAPS", SDL_KMOD_CAPS }, - { "KMOD_MODE", SDL_KMOD_MODE }, { "KMOD_SCROLL", SDL_KMOD_SCROLL }, - { "KMOD_CTRL", SDL_KMOD_CTRL }, { "KMOD_SHIFT", SDL_KMOD_SHIFT }, - { "KMOD_ALT", SDL_KMOD_ALT }, { "KMOD_GUI", SDL_KMOD_GUI } + { "KMOD_LSHIFT", SDL_KMOD_LSHIFT }, { "KMOD_RSHIFT", SDL_KMOD_RSHIFT }, + { "KMOD_LCTRL", SDL_KMOD_LCTRL }, { "KMOD_RCTRL", SDL_KMOD_RCTRL }, + { "KMOD_LALT", SDL_KMOD_LALT }, { "KMOD_RALT", SDL_KMOD_RALT }, + { "KMOD_LGUI", SDL_KMOD_LGUI }, { "KMOD_RGUI", SDL_KMOD_RGUI }, + { "KMOD_NUM", SDL_KMOD_NUM }, { "KMOD_CAPS", SDL_KMOD_CAPS }, + { "KMOD_MODE", SDL_KMOD_MODE }, { "KMOD_SCROLL", SDL_KMOD_SCROLL }, + { "KMOD_CTRL", SDL_KMOD_CTRL }, { "KMOD_SHIFT", SDL_KMOD_SHIFT }, + { "KMOD_ALT", SDL_KMOD_ALT }, { "KMOD_GUI", SDL_KMOD_GUI }, + { "KMOD_NONE", SDL_KMOD_NONE }, { "SDL_KMOD_LSHIFT", SDL_KMOD_LSHIFT }, + { "SDL_KMOD_RSHIFT", SDL_KMOD_RSHIFT }, { "SDL_KMOD_LCTRL", SDL_KMOD_LCTRL }, + { "SDL_KMOD_RCTRL", SDL_KMOD_RCTRL }, { "SDL_KMOD_LALT", SDL_KMOD_LALT }, + { "SDL_KMOD_RALT", SDL_KMOD_RALT }, { "SDL_KMOD_LGUI", SDL_KMOD_LGUI }, + { "SDL_KMOD_RGUI", SDL_KMOD_RGUI }, { "SDL_KMOD_NUM", SDL_KMOD_NUM }, + { "SDL_KMOD_CAPS", SDL_KMOD_CAPS }, { "SDL_KMOD_MODE", SDL_KMOD_MODE }, + { "SDL_KMOD_SCROLL", SDL_KMOD_SCROLL }, { "SDL_KMOD_CTRL", SDL_KMOD_CTRL }, + { "SDL_KMOD_SHIFT", SDL_KMOD_SHIFT }, { "SDL_KMOD_ALT", SDL_KMOD_ALT }, + { "SDL_KMOD_GUI", SDL_KMOD_GUI }, { "SDL_KMOD_NONE", SDL_KMOD_NONE } }; return s_map; @@ -424,17 +433,38 @@ static std::string masktostr(uint32_t mask) return str; } -uint32_t sdlInput::prefToMask() +bool sdlInput::prefToEnabled() { - auto m = getSdlMap(); - uint32_t mod = SDL_KMOD_NONE; + bool enabled = true; + const auto& m = getSdlMap(); for (const auto& val : SdlPref::instance()->get_array("SDL_KeyModMask", { "KMOD_RSHIFT" })) { auto it = m.find(val); if (it != m.end()) { - mod |= it->second; + if (it->second == SDL_KMOD_NONE) + enabled = false; } + else + { + WLog_Print(_sdl->log, WLOG_WARN, + "Invalid config::SDL_KeyModMask entry value '%s', disabling hotkeys", + val.c_str()); + enabled = false; + } + } + return enabled; +} + +uint32_t sdlInput::prefToMask() +{ + const auto& m = getSdlMap(); + uint32_t mod = SDL_KMOD_NONE; + for (const auto& val : SdlPref::instance()->get_array("SDL_KeyModMask", { "KMOD_RSHIFT" })) + { + auto it = m.find(val); + if (it != m.end()) + mod |= it->second; } return mod; } @@ -544,7 +574,7 @@ BOOL sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) const UINT32 rdp_scancode = scancode_to_rdp(ev->scancode); const SDL_Keymod mods = SDL_GetModState(); - if ((mods & _hotkeyModmask) == _hotkeyModmask) + if (_hotkeysEnabled && (mods & _hotkeyModmask) == _hotkeyModmask) { if (ev->type == SDL_EVENT_KEY_DOWN) { @@ -651,7 +681,8 @@ BOOL sdlInput::mouse_grab(Uint32 windowID, bool enable) } sdlInput::sdlInput(SdlContext* sdl) - : _sdl(sdl), _lastWindowID(UINT32_MAX), _hotkeyModmask(prefToMask()) + : _sdl(sdl), _lastWindowID(UINT32_MAX), _hotkeysEnabled(prefToEnabled()), + _hotkeyModmask(prefToMask()) { _hotkeyFullscreen = prefKeyValue("SDL_Fullscreen", SDL_SCANCODE_RETURN); _hotkeyResizable = prefKeyValue("SDL_Resizeable", SDL_SCANCODE_R); diff --git a/client/SDL/SDL3/sdl_kbd.hpp b/client/SDL/SDL3/sdl_kbd.hpp index d767462b8..901f79a0f 100644 --- a/client/SDL/SDL3/sdl_kbd.hpp +++ b/client/SDL/SDL3/sdl_kbd.hpp @@ -57,7 +57,8 @@ class sdlInput static BOOL keyboard_set_ime_status(rdpContext* context, UINT16 imeId, UINT32 imeState, UINT32 imeConvMode); - static uint32_t prefToMask(); + bool prefToEnabled(); + uint32_t prefToMask(); static uint32_t prefKeyValue(const std::string& key, uint32_t fallback = SDL_SCANCODE_UNKNOWN); private: @@ -71,6 +72,7 @@ class sdlInput Uint32 _lastWindowID; // hotkey handling + bool _hotkeysEnabled; uint32_t _hotkeyModmask; // modifier keys mask uint32_t _hotkeyFullscreen; uint32_t _hotkeyResizable; diff --git a/client/SDL/common/man/sdl-freerdp-config.1.in b/client/SDL/common/man/sdl-freerdp-config.1.in index 1a07fe959..ca982b9eb 100644 --- a/client/SDL/common/man/sdl-freerdp-config.1.in +++ b/client/SDL/common/man/sdl-freerdp-config.1.in @@ -39,6 +39,8 @@ An array of \fISDL_Keymod\fR strings as defined at \fI@SDL_WIKI_BASE_URL@/SDL_Keymod\fR +.br +use \fRKEYMOD_NONE\fR to disable hotkeys .RE .RE .PP @@ -54,7 +56,7 @@ Default .br A string as defined at -\fI@SDL_WIKI_BASE_URL@/SDLScancodeLookup\fR +\fI@SDL_WIKI_BASE_URL@/SDL_Scancode\fR .RE .RE .PP @@ -70,7 +72,7 @@ Default .br A string as defined at -\fI@SDL_WIKI_BASE_URL@/SDLScancodeLookup\fR +\fI@SDL_WIKI_BASE_URL@/SDL_Scancode\fR .RE .RE .PP @@ -86,7 +88,7 @@ Default .br A string as defined at -\fI@SDL_WIKI_BASE_URL@/SDLScancodeLookup\fR +\fI@SDL_WIKI_BASE_URL@/SDL_Scancode\fR .RE .RE .PP @@ -106,7 +108,7 @@ Default .br A string as defined at -\fI@SDL_WIKI_BASE_URL@/SDLScancodeLookup\fR +\fI@SDL_WIKI_BASE_URL@/SDL_Scancode\fR .RE .RE .PP @@ -122,7 +124,7 @@ Default .br A string as defined at -\fI@SDL_WIKI_BASE_URL@/SDLScancodeLookup\fR +\fI@SDL_WIKI_BASE_URL@/SDL_Scancode\fR .RE .RE .RE diff --git a/client/X11/man/CMakeLists.txt b/client/X11/man/CMakeLists.txt index eeb5a3fb5..452d1478a 100644 --- a/client/X11/man/CMakeLists.txt +++ b/client/X11/man/CMakeLists.txt @@ -10,6 +10,5 @@ set(DEPS include(GetSysconfDir) get_sysconf_dir("" SYSCONF_DIR) -set(SDL_WIKI_BASE_URL "https://wiki.libsdl.org/SDL2") -set(VAR_NAMES "VENDOR" "PRODUCT" "VENDOR_PRODUCT" "SYSCONF_DIR" "SDL_WIKI_BASE_URL") +set(VAR_NAMES "VENDOR" "PRODUCT" "VENDOR_PRODUCT" "SYSCONF_DIR") generate_and_install_freerdp_man_from_xml(${MODULE_NAME} "1" "${DEPS}" "${VAR_NAMES}")