From 7c4fb8b08404d4153211d5d38bb08dbc4c3ad8bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 16 Apr 2026 13:15:22 -0600 Subject: [PATCH] Add basic modifier key tracking to UIScreen --- Common/Input/InputState.h | 6 ++++++ Common/UI/UIScreen.cpp | 32 ++++++++++++++++++++++++++++++++ Common/UI/UIScreen.h | 17 +++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/Common/Input/InputState.h b/Common/Input/InputState.h index bdbec037d7..c48737cb84 100644 --- a/Common/Input/InputState.h +++ b/Common/Input/InputState.h @@ -171,7 +171,13 @@ enum class KeyInputFlags { HAS_WHEEL_DELTA = 1 << 2, IS_REPEAT = 1 << 3, CHAR = 1 << 4, // Unicode character input. Cannot detect keyups of these so KeyInputFlags::DOWN and KeyInputFlags::UP are zero when this is set. + + // NOTE: These are only available in sync input. + MOD_CTRL = 1 << 5, + MOD_SHIFT = 1 << 6, + MOD_ALT = 1 << 7, }; + ENUM_CLASS_BITOPS(KeyInputFlags); struct KeyInput { diff --git a/Common/UI/UIScreen.cpp b/Common/UI/UIScreen.cpp index 8566822af6..f223c02185 100644 --- a/Common/UI/UIScreen.cpp +++ b/Common/UI/UIScreen.cpp @@ -130,9 +130,41 @@ bool UIScreen::UnsyncKey(const KeyInput &key) { } } + // Track modifier keys. + if (key.flags & KeyInputFlags::DOWN) { + switch (key.keyCode) { + case NKCODE_CTRL_LEFT: modifiersPressed_ |= Modifier::LCTRL; break; + case NKCODE_CTRL_RIGHT: modifiersPressed_ |= Modifier::RCTRL; break; + case NKCODE_SHIFT_LEFT: modifiersPressed_ |= Modifier::LSHIFT; break; + case NKCODE_SHIFT_RIGHT: modifiersPressed_ |= Modifier::RSHIFT; break; + case NKCODE_ALT_LEFT: modifiersPressed_ |= Modifier::LALT; break; + case NKCODE_ALT_RIGHT: modifiersPressed_ |= Modifier::RALT; break; + } + } + if (key.flags & KeyInputFlags::UP) { + switch (key.keyCode) { + case NKCODE_CTRL_LEFT: modifiersPressed_ &= ~Modifier::LCTRL; break; + case NKCODE_CTRL_RIGHT: modifiersPressed_ &= ~Modifier::RCTRL; break; + case NKCODE_SHIFT_LEFT: modifiersPressed_ &= ~Modifier::LSHIFT; break; + case NKCODE_SHIFT_RIGHT: modifiersPressed_ &= ~Modifier::RSHIFT; break; + case NKCODE_ALT_LEFT: modifiersPressed_ &= ~Modifier::LALT; break; + case NKCODE_ALT_RIGHT: modifiersPressed_ &= ~Modifier::RALT; break; + } + } + QueuedEvent ev{}; ev.type = QueuedEventType::KEY; ev.key = key; + + if (modifiersPressed_ & (Modifier::LCTRL | Modifier::RCTRL)) { + ev.key.flags |= KeyInputFlags::MOD_CTRL; + } + if (modifiersPressed_ & (Modifier::LSHIFT | Modifier::RSHIFT)) { + ev.key.flags |= KeyInputFlags::MOD_SHIFT; + } + if (modifiersPressed_ & (Modifier::LALT | Modifier::RALT)) { + ev.key.flags |= KeyInputFlags::MOD_ALT; + } std::lock_guard guard(eventQueueLock_); eventQueue_.push_back(ev); return retval; diff --git a/Common/UI/UIScreen.h b/Common/UI/UIScreen.h index e319b097d2..8732752067 100644 --- a/Common/UI/UIScreen.h +++ b/Common/UI/UIScreen.h @@ -32,6 +32,17 @@ struct QueuedEvent { }; }; +enum class Modifier { + NONE = 0, + LCTRL = 1, + RCTRL = 2, + LSHIFT = 4, + RSHIFT = 8, + LALT = 16, + RALT = 32, +}; +ENUM_CLASS_BITOPS(Modifier); + class UIScreen : public Screen { public: UIScreen(); @@ -61,6 +72,10 @@ public: virtual UI::Margins RootMargins() const { return UI::Margins(0); } + virtual void focusChanged(ScreenFocusChange focusChange) { + modifiersPressed_ = Modifier::NONE; + } + protected: virtual void CreateViews() = 0; @@ -90,6 +105,8 @@ protected: private: std::mutex eventQueueLock_; std::deque eventQueue_; + + Modifier modifiersPressed_{}; }; class UIDialogScreen : public UIScreen {