Bug 104070

Summary: Keyboard Modifiers handled after Keycode if in same USB report
Product: Wayland Reporter: sf <onlyTMP0303>
Component: libinputAssignee: Wayland bug list <wayland-bugs>
Status: RESOLVED DUPLICATE QA Contact:
Severity: normal    
Priority: medium    
Version: unspecified   
Hardware: x86-64 (AMD64)   
OS: Linux (All)   
Whiteboard:
i915 platform: i915 features:

Description sf 2017-12-04 14:51:07 UTC
A recent update of libinput to 1.9.3 changed the behaviour when modifier and keycode appear at the exact same time in USB report.

Background: I use a custom keyboard with my own firmware and have some virtual keys like '/' defined on my base layer that emit the required modifier key automatically in addition to the regular keycode (shift-7 here) at exactly the same time. The USB report thus contains a modifier and a regular keycode.

Before commit db3b6fe5f the modified key was handled correctly, eg pressing '/' lead to '/'.

After that change the unmodified key is detected first, and the modifier only after that so that only repeats are modified, not the first keypress:
Press '/' -> '7'
Hold '/' -> '7////'

I traced it down to the change db3b6fe5f in fallback_handle_state() where buttons and keys are handled in a for-loop that goes through all codes in sequence. In the case of '/', KEY_LEFTSHIFT(42) is detected only after KEY_7(8).
If I add code to check for modifiers prior to the loop, the behaviour is as expected. 

Thus far I have worked around this by changing my keyboard firmware to first emit only the modifier, and then in the next report modifier plus keycode.
Since I don't know if pressing modifiers at the exact time as another key is a defined usecase or if there is some spec saying they should appear prior to any modified key feel free to ignore this report. But my gut feeling is that any modifier currently visible to the system should be applied to any key detected at the same time.


Besides (but without looking any further into it) the following change in fallback_return_to_neutral_state() does not make much sense to me - should last_hw_key_mask be reset here?

  memset(dispatch->hw_key_mask, 0, sizeof(dispatch->hw_key_mask));
+ memset(dispatch->hw_key_mask, 0, sizeof(dispatch->last_hw_key_mask));
Comment 1 sf 2017-12-04 15:05:49 UTC
Just found 104030 which is describing the issue already for other use cases.

*** This bug has been marked as a duplicate of bug 104030 ***

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.