summaryrefslogtreecommitdiff
path: root/src/managers/input/InputManager.cpp
diff options
context:
space:
mode:
authorJS Deck <jsdeckerido@gmail.com>2025-10-26 15:54:48 -0300
committerGitHub <noreply@github.com>2025-10-26 18:54:48 +0000
commit88e34d7dd2b3d45da8b7f4c85e18810a472fa172 (patch)
treec8f22cd4a5dd4352362ad54c609f9173e01970c0 /src/managers/input/InputManager.cpp
parent05aa4e1c54da31d95663f9b4bc757e2a6ca65538 (diff)
IME: do not share keys/mods states from grabbed keyboards with ime keys/mods (#11917)
Diffstat (limited to 'src/managers/input/InputManager.cpp')
-rw-r--r--src/managers/input/InputManager.cpp47
1 files changed, 36 insertions, 11 deletions
diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp
index ae355b4b..80a5fabd 100644
--- a/src/managers/input/InputManager.cpp
+++ b/src/managers/input/InputManager.cpp
@@ -1451,16 +1451,34 @@ void CInputManager::onKeyboardKey(const IKeyboard::SKeyEvent& event, SP<IKeyboar
passEvent = g_pKeybindManager->onKeyEvent(event, pKeyboard);
if (passEvent) {
+ auto state = event.state;
+ auto pressed = state == WL_KEYBOARD_KEY_STATE_PRESSED;
+
+ // use merged keys states when sending to ime or when sending to seat with no ime
+ // if passing from ime, send keys directly without merging
+ if (USEIME || !HASIME) {
+ const auto ANYPRESSED = shareKeyFromAllKBs(event.keycode, pressed);
+
+ // do not turn released event into pressed event (when one keyboard has a key released but some
+ // other keyboard still has the key pressed)
+ // maybe we should keep track of pressed keys for inputs like m_pressed for seat outputs below,
+ // to avoid duplicate pressed events, but this should work well enough
+ if (!pressed && ANYPRESSED)
+ return;
+
+ pressed = ANYPRESSED;
+ state = pressed ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED;
+ }
+
if (USEIME) {
IME->setKeyboard(pKeyboard);
- IME->sendKey(event.timeMs, event.keycode, event.state);
+ IME->sendKey(event.timeMs, event.keycode, state);
} else {
- const auto PRESSED = shareKeyFromAllKBs(event.keycode, event.state == WL_KEYBOARD_KEY_STATE_PRESSED);
const auto CONTAINS = std::ranges::contains(m_pressed, event.keycode);
- if (CONTAINS && PRESSED)
+ if (CONTAINS && pressed)
return;
- if (!CONTAINS && !PRESSED)
+ if (!CONTAINS && !pressed)
return;
if (CONTAINS)
@@ -1469,7 +1487,7 @@ void CInputManager::onKeyboardKey(const IKeyboard::SKeyEvent& event, SP<IKeyboar
m_pressed.emplace_back(event.keycode);
g_pSeatManager->setKeyboard(pKeyboard);
- g_pSeatManager->sendKeyboardKey(event.timeMs, event.keycode, event.state);
+ g_pSeatManager->sendKeyboardKey(event.timeMs, event.keycode, state);
}
updateKeyboardsLeds(pKeyboard);
@@ -1482,14 +1500,21 @@ void CInputManager::onKeyboardMod(SP<IKeyboard> pKeyboard) {
const bool DISALLOWACTION = pKeyboard->isVirtual() && shouldIgnoreVirtualKeyboard(pKeyboard);
- auto MODS = pKeyboard->m_modifiersState;
- const auto ALLMODS = shareModsFromAllKBs(MODS.depressed);
- MODS.depressed = ALLMODS;
- m_lastMods = MODS.depressed;
+ const auto IME = m_relay.m_inputMethod.lock();
+ const bool HASIME = IME && IME->hasGrab();
+ const bool USEIME = HASIME && !DISALLOWACTION;
- const auto IME = m_relay.m_inputMethod.lock();
+ auto MODS = pKeyboard->m_modifiersState;
+
+ // use merged mods states when sending to ime or when sending to seat with no ime
+ // if passing from ime, send mods directly without merging
+ if (USEIME || !HASIME) {
+ const auto ALLMODS = shareModsFromAllKBs(MODS.depressed);
+ MODS.depressed = ALLMODS;
+ m_lastMods = MODS.depressed; // for hyprland keybinds use; not for sending to seat
+ }
- if (IME && IME->hasGrab() && !DISALLOWACTION) {
+ if (USEIME) {
IME->setKeyboard(pKeyboard);
IME->sendMods(MODS.depressed, MODS.latched, MODS.locked, MODS.group);
} else {