diff --git a/src/gui/render.cpp b/src/gui/render.cpp index 27c5de1..519035f 100644 --- a/src/gui/render.cpp +++ b/src/gui/render.cpp @@ -2455,6 +2455,7 @@ void Render::ProcessSdlEvent(const SDL_Event& event) { case SDL_EVENT_WINDOW_FOCUS_LOST: if (stream_window_ && SDL_GetWindowID(stream_window_) == event.window.windowID) { + ForceReleasePressedModifiers(); focus_on_stream_window_ = false; } else if (main_window_ && SDL_GetWindowID(main_window_) == event.window.windowID) { diff --git a/src/gui/render.h b/src/gui/render.h index f0790b5..fee335b 100644 --- a/src/gui/render.h +++ b/src/gui/render.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "IconsFontAwesome6.h" @@ -322,6 +323,9 @@ class Render { private: int SendKeyCommand(int key_code, bool is_down); + static bool IsModifierVkKey(int key_code); + void UpdatePressedModifierState(int key_code, bool is_down); + void ForceReleasePressedModifiers(); int ProcessMouseEvent(const SDL_Event& event); static void SdlCaptureAudioIn(void* userdata, Uint8* stream, int len); @@ -506,6 +510,8 @@ class Render { std::string controlled_remote_id_ = ""; std::string focused_remote_id_ = ""; std::string remote_client_id_ = ""; + std::unordered_set pressed_modifier_keys_; + std::mutex pressed_modifier_keys_mutex_; SDL_Event last_mouse_event; SDL_AudioStream* output_stream_; uint32_t STREAM_REFRESH_EVENT = 0; diff --git a/src/gui/render_callback.cpp b/src/gui/render_callback.cpp index 6d1b9c8..9e1364a 100644 --- a/src/gui/render_callback.cpp +++ b/src/gui/render_callback.cpp @@ -81,6 +81,55 @@ void Render::OnSignalMessageCb(const char* message, size_t size, } } +bool Render::IsModifierVkKey(int key_code) { + switch (key_code) { + case 0x10: // VK_SHIFT + case 0x11: // VK_CONTROL + case 0x12: // VK_MENU(ALT) + case 0x5B: // VK_LWIN + case 0x5C: // VK_RWIN + case 0xA0: // VK_LSHIFT + case 0xA1: // VK_RSHIFT + case 0xA2: // VK_LCONTROL + case 0xA3: // VK_RCONTROL + case 0xA4: // VK_LMENU + case 0xA5: // VK_RMENU + return true; + default: + return false; + } +} + +void Render::UpdatePressedModifierState(int key_code, bool is_down) { + if (!IsModifierVkKey(key_code)) { + return; + } + + std::lock_guard lock(pressed_modifier_keys_mutex_); + if (is_down) { + pressed_modifier_keys_.insert(key_code); + } else { + pressed_modifier_keys_.erase(key_code); + } +} + +void Render::ForceReleasePressedModifiers() { + std::vector pressed_keys; + { + std::lock_guard lock(pressed_modifier_keys_mutex_); + if (pressed_modifier_keys_.empty()) { + return; + } + pressed_keys.assign(pressed_modifier_keys_.begin(), + pressed_modifier_keys_.end()); + pressed_modifier_keys_.clear(); + } + + for (int key_code : pressed_keys) { + SendKeyCommand(key_code, false); + } +} + int Render::SendKeyCommand(int key_code, bool is_down) { RemoteAction remote_action; remote_action.type = ControlType::keyboard; @@ -109,6 +158,8 @@ int Render::SendKeyCommand(int key_code, bool is_down) { } } + UpdatePressedModifierState(key_code, is_down); + return 0; }