diff options
| author | JS Deck <jsdeckerido@gmail.com> | 2025-10-26 15:54:48 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-10-26 18:54:48 +0000 |
| commit | 88e34d7dd2b3d45da8b7f4c85e18810a472fa172 (patch) | |
| tree | c8f22cd4a5dd4352362ad54c609f9173e01970c0 /src/managers/input/InputManager.cpp | |
| parent | 05aa4e1c54da31d95663f9b4bc757e2a6ca65538 (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.cpp | 47 |
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 { |
