Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Batch updating the keyboard state / regrabbing keys #4367

Draft
wants to merge 4 commits into
base: next
Choose a base branch
from

Conversation

psychon
Copy link
Contributor

@psychon psychon commented Mar 7, 2021

This adds a test case that tests that i3 does something quickly. With current next, the test needs 13 seconds on my computer and fails. That's not quick. The following commits fix this by batching "the keyboard changed"-stuff: Instead of executing this code once per event we receive, this is now only done once per main loop iteration.

This might or might not fix #3924 (no idea - I only tested with my new test case), hence CC @sammko

Also, I have no clue how to write test cases. I do not really know perl and I did not figure out the numbering scheme (thus went with 600). Perhaps this even has to handle the case "xmodmap is not installed" somehow? Dunno.

The test uses a time limit of two seconds because time() only provides second granularity. Limiting this to one second could cause failures where the current time is x.99999 when the test starts and (x+1).000001 when the test finishes. This would already look like a one second time difference. Allowing two seconds thus seemed the safest option to me.

Finally: IMO I am using way too many static variables for this, but let's see what you guys say about this.

This testcases causes 5000 keyboard events to be generated, meaning that
i3 (needlessly) updates the keymap 5000 times. This currently takes
about 13 seconds on my computer.

This may or may not be a testcase for
i3#3924. I am not sure.

Signed-off-by: Uli Schlachter <psychon@znc.in>
No behavioural changes intended.

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit moves two more cases to the regrab_keys() helper function.

This is not just a straight forward refactoring since the order of
things is different for RG_LOAD_KEYMAP_AND_TRANSLATE before and after
this commit. While I do not think this makes much of a difference, I
still did this in its extra commit for bisectability.

Signed-off-by: Uli Schlachter <psychon@znc.in>
Instead of updating the keyboard state and regrabbing all the keys
immediately when requested, this simply starts an ev idle watcher. This
has the effect of batching updates: When multiple updates are requested
during a main loop iteration, only one update is actually done.

This fixes the new test case that I just added.

This might or might not fix i3#3924.

Signed-off-by: Uli Schlachter <psychon@znc.in>
@psychon
Copy link
Contributor Author

psychon commented Mar 7, 2021

Hrm. The test definitely needs some more work. It just failed locally for me and I have no idea why:

#   Failed test 'Test finishes quickly'
#   at /home/psychon/projects/i3/testcases/t/600-slow-keyboard-update.t line 30.

Someone who knows perl & the test suite is invited to look at this and improve it somehow (a good first step would be to improve the error message to include the value of $delay). AFAIK you can just push new commits to the branch behind this PR.

Also, another test failed on Travis, but I cannot reproduce this locally.

#   Failed test 'Received precisely one event'
#   at /usr/src/i3/distbuild/meson-private/dist-unpack/i3-4.19.2/testcases/t/290-keypress-numlock.t line 86.
#          got: '0'
#     expected: '1'
#   Failed test 'change is "run"'
#   at /usr/src/i3/distbuild/meson-private/dist-unpack/i3-4.19.2/testcases/t/290-keypress-numlock.t line 86.
#          got: undef
#     expected: 'run'
#   Failed test 'triggered the "a" keybinding'
#   at /usr/src/i3/distbuild/meson-private/dist-unpack/i3-4.19.2/testcases/t/290-keypress-numlock.t line 86.
#          got: undef
#     expected: 'a'

A random guess would be: The test uses xtest_sync_with_i3 which seems to work by sending an I3_SYNC message to the root window. My use of an ev idle watcher seems to be breaking the synchronisation here (since an I3_SYNC message could be handled before the idle watcher fires).

Urgh. Another synchronisation issue that I stepped into. :-(

Edit: Actually, its worse than that. The test (de)activates num lock, which means that keys are regrabbed. What prevents the following sequence of events?

  • the test suite activates num lock
  • i3 does ungrab_all_keys()
  • the test suite presses a, expecting a binding to trigger
  • i3 re-grabs the keys it is interested in

The above is quite unlikely in the current tests since all the xtest requests should be sent with a single write() syscall, but this still seems potentially racy.

Perhaps this needs a xtest_sync_with_i3 after activating num lock and hoping that this gives enough time to the idle watcher to fire? Hrm...

@orestisfl orestisfl marked this pull request as draft September 21, 2022 22:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ibus with input method not shared among windows causes massive re-grabbing churn when switching windows
1 participant