GNOME Bugzilla – Bug 666101
pressing super key multiple times breaks keyboard shortcuts
Last modified: 2014-03-06 13:55:30 UTC
It seems to happen randomly so sometimes it's hard to trigger: 1. press super key few times in a row 2. all keyboard shortcuts stop working (gnome related, not like ctrl+alt+f2) 3. go to overview using mouse: all keyboard shortcuts work here 4. leave overview 5a. press super - keyboard shortcuts remain broken 5b. use any other keyboard shortcut - everything is working again, including super The worst thing is if this happens with fullscreen app open, then you can't go to overview with mouse and you can't do anything Distro: Arch/Fedora 16 Graphics card: Sandybridge
Are there any errors messages in your ~/.xsession-errors after this happens?
No messages in ~/.xsession-errors.
Is this a dupe of 607797 ? Have you changed the default mouse button modifier from alt to super ?
Didn't change that, it's set to <Alt>.
One more thing I noticed now: to fix this you don't actually have to go to overview, you can click on some element from top panel and then use any keyboard shortcut other that super.
do you have any extensions installed?
No extensions.
This is similar to bug 660922, but no GtkMenu interaction is involved here. Just like in the first comment of that bug.
One more thing: I can't reproduce it on empty workspace. There has to be at least one window open on the active workspace.
(In reply to comment #1) > Are there any errors messages in your ~/.xsession-errors after this happens? I didn't notice it before but after closing any app I get: Window manager warning: CurrentTime used to choose focus window; focus window may not be correct. Window manager warning: Got a request to focus 0x1a00972 (mariusz@g5) with a timestamp of 0. This shouldn't happen! Window manager warning: CurrentTime used to choose focus window; focus window may not be correct. Window manager warning: Got a request to focus the no_focus_window with a timestamp of 0. This shouldn't happen! Also when I log in I get: Window manager warning: Log level 16: get_all_cb: couldn't retrieve system settings properties: (25) Launch helper exited with unknown return code 1. Window manager warning: CurrentTime used to choose focus window; focus window may not be correct. Window manager warning: Got a request to focus the no_focus_window with a timestamp of 0. This shouldn't happen! Window manager warning: Log level 16: fetch_connections_done: error fetching connections: (25) Launch helper exited with unknown return code 1. Window manager warning: Log level 16: nm_client_get_devices: error getting devices: Launch helper exited with unknown return code 1 I don't know if it has any connection since I get that messages whether I trigger the bug or not.
Still happening in 3.7.92. Hitting super too many times causes it to stop working util the mouse is used to go into the overview.
How many times are we talking here ? My attempts to reproduce this failed.
I haven't be able to reproduce with less than 7-8 (very!) quick consecutive presses.
https://bugzilla.gnome.org/show_bug.cgi?id=660922 is similar.
Got the same problem described in report after upgrading to GNOME 3.8. After pressing multiple times <Super> key all shortcuts stop working until mouse click on overview or some app window. Distro: Archlinux. GNOME 3.8.2 Graphics: Intel SandyBridge.
I can easily reproduce this with 3.8.3 on Debian. It seems to be a focus problem. If I reproduce it with an app that shows a cursor (e.g. a terminal or this chromium window while writing this comment), when the bug happens the window gets unfocused (the cursor no longer blinks, the comment box in chromium is white instead of yellow). Clicking on the terminal/chromium window brings focus back and makes <super> work again. There are no messages on session.log when the problem happens.
I can also reproduce it with just 1 window opened (gnome-terminal). It often works fine for about 10 <super> key press. And just before it stops working, Mutter displays the message: Doing grab op 1 on window 0x2400006 (Terminal) button 1 pointer already grabbed: 1 pointer pos 704,574 I am not clicking or grabbing the window, I am just pressing the <super> key quickly.
With GDB on Xorg, and reading grabs from all inputInfo.devices (for dev = inputInfo.devices; dev; dev = dev->next), I see that during the bug, the grab is on the root window, which confirms the grab comes from gnome-shell/Mutter: (gdb) p inputInfo.devices->next->deviceGrab->activeGrab->window->parent $21 = (WindowPtr) 0x0 When the bug is triggered, Mutter's event_callback() and meta_display_process_key_event() are not longer called. But when the user workaround the bug by clicking on the window, event_callback() and meta_display_process_key_event() are called a lot of times for all the <super> key press which were inhibited during the bug.
Can you investigate why we're trying to start a grab op on the window? Put a breakpoint on meta_display_begin_grab_op. Are we getting an XI_ButtonPress? Are we getting a _NET_WM_MOVERESIZE?
The breakpoint on meta_display_begin_grab_op is not triggered when then bug happens... this function is called but only *after* the bug when I decide to click on the window to workaround the bug. I also set a breakpoint on XIGrabDevice with the following GDB script (I cannot just add a breakpoint manually because I need to press the <super> key quickly to trigger the bug): set width 0 set height 0 set verbose off break XIGrabDevice commands 1 backtrace continue end continue And attach GDB with: "gdb --batch --command=script.gdb -p 9119 /usr/bin/gnome-shell" and I see XIGrabDevice is called from mutter/src/compositor/compositor.c:meta_begin_modal_for_plugin() each time the <super> key is pressed to enter in the overview but it is a grab on a normal window, not on the root window. After pressing <super> repetitively for a while, the bug happens but I don't see any other XIGrabDevice at that time than the normal case in meta_begin_modal_for_plugin(). So I still don't know who is setting up the grab on the root window. Since I don't see it with my test in GDB, it could be done from another function than XIGrabDevice (I don't know if there is any function I should look in the X11 protocol), or from another process than gnome-shell?
(In reply to comment #20) > The breakpoint on meta_display_begin_grab_op is not triggered when then bug > happens... this function is called but only *after* the bug when I decide to > click on the window to workaround the bug. So you're saying that the "Doing grab op 1 on window 0x2400006 (Terminal) button 1 pointer already grabbed: 1 pointer pos 704,574" message *does not* appear when the bug happens, but only after when you click on the window?
Yes, exact. When the bug is triggered, GDB on Xorg says it is a passive grab: (gdb) p inputInfo.devices->next->deviceGrab->fromPassiveGrab $8 = 1 So not a grab from XIGrabDevice but from a previously registered grab with XIGrabKeycode: src/core/keybindings.c:meta_change_keygrab()
Created attachment 250890 [details] [review] [PATCH] keybindings: always acknowledge events to the X server With the attached patch, I don't have the bug anymore :) I get the log "Got event {type=2 detail=133}. Ignore it." from the patch, which is KeyPress for Super_L. I don't know why we get in this condition: I thought that since overlay_key_only_pressed is TRUE, we should not get a second KeyPress event for Super_L. But when process_overlay_key() returns TRUE, we ought to make some XIAllowEvents() call to avoid freezing. I didn't notice any side effect with the patch.
Could it be key repeat somehow? Try installing evtest to snoop on the event stream you get, or use Meta.add_verbose_topic(Meta.DebugTopic.EVENTS); to look at the event stream.
I looked at the event stream with the META_DEBUG_EVENTS logs. In the vast majority of case, it is just a sequence of: - XI_KeyPress Key 'Super_L' - XI_KeyRelease Key 'Super_L' without missing XI_KeyRelease. But occasionally, there is a missing XI_KeyRelease. Some logs I added in gnome-shell shows that XI_KeyRelease will be missed whenever js/ui/overview.js:_syncInputMode() is called while Super_L is pressed. _syncInputMode() is called when the overview animation finishes. 1. js/ui/overview.js:_syncInputMode() 2. js/ui/main.js:popModal() 3. global.set_stage_input_mode(Shell.StageInputMode.NORMAL); shell_global_set_stage_input_mode() 4.1 meta_set_stage_input_region() then XFixesSetWindowShapeRegion(), XFixesDestroyRegion(), XFixesCopyRegion() 4.2 shell_global_focus_stage() then XSetInputFocus() (and maybe other X calls I missed which could mess up with the 'Super_L' events)
This sounds like an X server bug to me. We set up a key grab on the root window, so no matter what has focus, we should receive the KeyRelease.
I was wrong in my previous comment: it is not about XSetInputFocus but about XIUngrabDevice being called: While Super_L is down, the animation from overview to windows finishes: 0. js/ui/overview.js:_hideDone() 1. js/ui/overview.js:_syncInputMode() 2. js/ui/main.js:popModal() 3. js/ui/main.js:global.end_modal(timestamp); 4. src/shell-global.c:shell_global_end_modal() 5. src/compositor/meta-plugin.c:meta_plugin_end_modal() 6. src/compositor/compositor.c:meta_end_modal_for_plugin() 7. XIUngrabDevice Passive key grabs are only activated (turned into an active grab) on KeyPress. It's not possible to add a passive grab which gets activated on KeyRelease. The mask XI_KeyPress + XI_KeyRelease used in XIGrabKeycode (src/core/keybindings.c:meta_change_keygrab) says which events will be received while the grab is active but not when the grab will become active. So if there is a queued KeyRelease when XIUngrabDevice is received by the X server, the passive grab will not be reactivated immediately by the KeyRelease so the KeyRelease will be delivered to the window with the focus instead of the root window. If we really want to get all the events, we could change meta_end_modal_for_plugin() to delay XIUngrabDevice until we receive the KeyRelease. Or generate a fake KeyRelease to keep MetaKeyBinding's state machine sane. But it seems overly complicated and I would argue that patching process_overlay_key() in a similar way to Comment #23 is good enough.
Jasper: only button press/releases are paired like you suggest, with unbreakable implicit grabs. If what Alban describes in comment #27 is indeed happening (and that's my best guess, having stepped through it with him), then that's a flat-out client bug. Admittedly, there's no way to ever fully solve this race when using GrabAsync, because you have no idea what's in the server's event queue, or the client's, or in socket buffers somewhere. The only way to do it 100% reliably is to use Sync instead. But that's a design/protocol flaw, not a bug.
Ah, I thought that it was like button press/releases, where even if we dropped our grab with XIUngrabDevice the button release would still be delivered to us. I suppose it's also bad because we take an async grab in the overview, a sync grab when the key is pressed, and then the overview code tries to drop the async grab, and drops the sync grab as well. Ugh. The patch looks fine, but I'd like a better comment and to drop the log.
Created attachment 251071 [details] [review] [PATCH] keybindings: always acknowledge events to the X server Patch updated: - log dropped - better comment
(In reply to comment #29) > Ah, I thought that it was like button press/releases, where even if we dropped > our grab with XIUngrabDevice the button release would still be delivered to us. Alas no. > I suppose it's also bad because we take an async grab in the overview, a sync > grab when the key is pressed, and then the overview code tries to drop the > async grab, and drops the sync grab as well. Ugh. There are no separate grabs: they're the same thing. Calling AllowEvents for a pointer grab can either change the mode of the grab (in case of switching between Sync and Async), allow one more event through (when it remains Sync), or drop the grab and pass the event through (Replay). So all you're doing is switching the mode of the grab, and ungrabbing it, well, ungrabs it. The problem is with ever switching to Async. You just don't know what state the keyboard's going to be in, and you can't find out without doing XIQueryDevice afterwards. Ungrabbing from a timeout is obviously an additional source of race condition comedy. I understand totally why you switch the grab from Sync to Async on KeyRelease - avoids the twice-per-key roundtrips when you're typing in overlay mode - but either it has to be Sync with AllowEvents, or you need to query the device state after you've released the grab and manually resync with your view of the world (i.e. did you miss a KeyRelease?). Hooray for X.
Right. We could rewrite parts of mutter so that we always know what grab state we'll be in, so when the compositor drops its modal, we'll go from the sync keybinding grab to the async grab, but that's a bunch of code to write and just making the keybindings code accept a somewhat pathological input sounds fine to me.
Review of attachment 251071 [details] [review]: ::: src/core/keybindings.c @@ +1976,3 @@ + * - passive grabs are only activated on KeyPress and not KeyRelease. + * + * In this case, display->overlay_key_only_pressed, might be wrong. extraneous comma before "might be wrong".
Created attachment 251087 [details] [review] [PATCH] keybindings: always acknowledge events to the X server Patch updated: - remove a comma
Review of attachment 251087 [details] [review]: OK.
Comment on attachment 251087 [details] [review] [PATCH] keybindings: always acknowledge events to the X server Committed on git master as 8c17b670fb61d2fbfaaf8f47448d0e48bfa7f29e
*** Bug 719778 has been marked as a duplicate of this bug. ***