2020
2121#include < xkbcommon/xkbcommon-keysyms.h>
2222
23- #include < ranges >
23+ #include < algorithm >
2424
2525namespace mf = mir::frontend;
2626
@@ -40,7 +40,7 @@ bool mf::KeyboardStateTracker::process(MirEvent const& event)
4040 auto const action = key_event->action ();
4141 auto const modifiers = key_event->modifiers ();
4242
43- auto & [pressed_keysyms, pressed_scancodes , shift_state] = device_states[input_event->device_id ()];
43+ auto & [scancode_to_keysym , shift_state] = device_states[input_event->device_id ()];
4444
4545 auto const prev_shift_state = shift_state;
4646 shift_state = modifiers & (mir_input_event_modifier_shift | mir_input_event_modifier_shift_left |
@@ -49,47 +49,46 @@ bool mf::KeyboardStateTracker::process(MirEvent const& event)
4949 auto processed = false ;
5050 if (action == mir_keyboard_action_down)
5151 {
52- pressed_keysyms.insert (keysym);
53- pressed_scancodes.insert (scancode);
52+ scancode_to_keysym[scancode] = keysym;
5453 processed = true ;
5554 }
5655 else if (action == mir_keyboard_action_up)
5756 {
58- pressed_keysyms.erase (keysym);
59- pressed_scancodes.erase (scancode);
57+ // Remove by scancode so that a mismatched key-up keysym (caused by a
58+ // modifier change while the key was held) does not leave stale entries.
59+ scancode_to_keysym.erase (scancode);
6060 processed = true ;
6161 }
6262
6363 // Transitioned from no shift to at least one shift
6464 if (prev_shift_state == 0 && shift_state != 0 )
6565 {
66- auto const uppercase =
67- std::ranges::views::transform (pressed_keysyms, [](auto key) { return xkb_keysym_to_upper (key); });
68- pressed_keysyms = std::unordered_set<xkb_keysym_t >(uppercase.begin (), uppercase.end ());
66+ for (auto & [sc, ks] : scancode_to_keysym)
67+ ks = xkb_keysym_to_upper (ks);
6968 }
7069 else if (prev_shift_state != 0 && shift_state == 0 )
7170 {
7271 // Transitioned from at least one shift to no shift
73- auto const lowercase =
74- std::ranges::views::transform (pressed_keysyms, [](auto key) { return xkb_keysym_to_lower (key); });
75- pressed_keysyms = std::unordered_set<xkb_keysym_t >(lowercase.begin (), lowercase.end ());
72+ for (auto & [sc, ks] : scancode_to_keysym)
73+ ks = xkb_keysym_to_lower (ks);
7674 }
7775
7876 return processed;
7977}
8078
8179auto mf::KeyboardStateTracker::keysym_is_pressed (MirInputDeviceId device, xkb_keysym_t keysym) const -> bool
8280{
83- if (!device_states.contains (device)) return false ;
81+ if (!device_states.contains (device))
82+ return false ;
8483
85- auto const & [pressed_keysyms, _, __] = device_states. at (device);
86- return pressed_keysyms. contains ( keysym);
84+ return std::ranges::any_of (
85+ device_states. at (device). scancode_to_keysym , [ keysym]( auto const & pair) { return pair. second == keysym; } );
8786}
8887
8988auto mf::KeyboardStateTracker::scancode_is_pressed (MirInputDeviceId device, int32_t scancode) const -> bool
9089{
91- if (!device_states.contains (device)) return false ;
90+ if (!device_states.contains (device))
91+ return false ;
9292
93- auto const & [_, pressed_scancodes, __] = device_states.at (device);
94- return pressed_scancodes.contains (scancode);
93+ return device_states.at (device).scancode_to_keysym .contains (scancode);
9594}
0 commit comments