Open h1771t opened 2 years ago
What does the ICCCM say about this?
I cannot see anything specific. I looked in https://www.x.org/releases/X11R7.6/doc/xorg-docs/specs/ICCCM/icccm.html#the_keyboard_mapping
However smithay uses https://docs.rs/xkbcommon/0.4.0/xkbcommon/xkb/struct.State.html#method.update_key which has this description which looks related:
A series of calls to this function should be consistent; that is, a call with xkb::KEY_DOWN for a key should be matched by an xkb::KEY_UP; if a key is pressed twice, it should be released twice; etc. Otherwise (e.g. due to missed input events), situations like "stuck modifiers" may occur
I suspect smithay x11 backend gets alt-pressed event upon alt+tab to move away. It does not get the alt-depressed due to main shell moving to another app. Then upon another alt+tab back to smithay x11, the main shell doesn't send a alt-depressed perhaps? So from then on, xkb State has alt pressed, any further pressing only increments to 2 and depressing decrements back to 1, so it never sees 0 again.
I am going to attempt to using https://docs.rs/xkbcommon/0.4.0/xkbcommon/xkb/struct.State.html#method.update_mask to reset the mask upon window leave event, and see if it fixes the issue for me. I will post the results I find
Indeed if I add a function in src/wayland/seat/keyboard.rs
+ fn reset_modifiers(&mut self) {
+ self.state.update_mask(0, 0, 0, 0, 0, 0);
+ }
And have it called from compositor when a window enter-event occurs, then the issues seems to resolve for me. Super key shortcuts work for me in x11 backend window when it isn't main shell, even after alt+tab switching to another app and then back to x11 backend window again.
This does work, with one major issue. When the x11 backend is not the main x11 shell but rather just another x11 window being run, and the user moves the mouse off the window and presses
ALT+TAB
, the window/seat sees thealt:true
keyboardModifiersState
up until theTAB
key is hit. At that point the x11 main shell switches app to another window. The window/seat does not end up getting thealt:false
. If the user then hitsALT+TAB
again to move back to the smithay x11 window, theModifiersState
stays stuck atalt:true
even though theALT
key is not pressed. At this point pressingALT
and releasing makes no difference, theModifiersState
seems permanently stuck atalt:true
In which desktop environment does this happen? On Wayland (with XWayland) or inside an X11 session?
Also does the connection.grab_keyboard
request return a XCB_GRAB_STATUS_SUCCESS
(or whatever the equivalent is in x11rb), could you log that?
Because this seems like a bug in the DEs application switcher, normally if the window has successfully obtained a grab, it should receive all keyboard events (including the alt+tab release event).
We need to figure out, who is not behaving correctly here.
@i509VCB The ICCCM indeed has no conventions for this edge case, that would help us here. At least I was not able to find some. What is your opinion on this? Resetting the modifiers map seems reasonable to me, but I am not sure, if we mess up the state, if a modifier is already pressen when re-entering the window. Does Xorg send the modifiers again on focus?
In which desktop environment does this happen? On Wayland (with XWayland) or inside an X11 session?
Inside X11. Here are the steps I'm using to reproduce:
INFO Connecting to the X server, smithay_module: backend_x11
so I know it is using smithay x11 backendgrab_keyboard
and ungrab_keyboard
bits from https://github.com/pop-os/smithay/compare/main...h1771t:smithay-1:main#) in order to produce issue 2 which this github issue was opened for.If I apply the full patch from https://github.com/pop-os/smithay/compare/main...h1771t:smithay-1:main# for smithay and also this one for cosmic-comp https://github.com/pop-os/cosmic-comp/pull/20/files which is resetting the keyboard modifiers upon mouse-enter, then issue 2 is resolved for me, ie. super key actions of cosmic-comp work for me even if I have ALT+TAB away from cosmic-comp window and then back again
I am not sure thought that resetting modifiers on mouse-enter is the right way to fix this.
Also does the
connection.grab_keyboard
request return aXCB_GRAB_STATUS_SUCCESS
(or whatever the equivalent is in x11rb), could you log that?
This is the exact keyboard grab function being used, but it is unrelated to issue 2 because the grab and ungrab does work fine: https://docs.rs/x11rb/0.9.0/x11rb/protocol/xproto/trait.ConnectionExt.html#method.grab_keyboard
Because this seems like a bug in the DEs application switcher, normally if the window has successfully obtained a grab, it should receive all keyboard events (including the alt+tab release event).
Sorry I was not being clear around this. With the mouse inside cosmic-comp window (grabbed), all keyboard is indeed handled by cosmic-comp, including ALT+TAB This behaves correctly. Only when I move the mouse out of cosmic-comp window (ungrabbed) and ALT+TAB, do I cause issue 2.
Seems even with the mouse outside cosmic-comp window (ungrabbed), cosmic-comp still has focus so when doing ALT+TAB, cosmic-comp/smithay detects a ALT-pressed, but as soon as TAB is hit, the main Pop_OS! shell switches apps and ALT-pressed stays stuck in cosmic-comp/smithay
We need to figure out, who is not behaving correctly here.
I suspect the main shell/DE app switcher in Pop_OS! is behaving fine, and most x11 apps won't track modifierState the way cosmic-comp/smithay needs to, so they won't experience the issue? I'm not totally sure.
Also does the
connection.grab_keyboard
request return aXCB_GRAB_STATUS_SUCCESS
(or whatever the equivalent is in x11rb), could you log that?This is the exact keyboard grab function being used, but it is unrelated to issue 2 because the grab and ungrab does work fine: https://docs.rs/x11rb/0.9.0/x11rb/protocol/xproto/trait.ConnectionExt.html#method.grab_keyboard
Yes, and that function returns a Cookie
with a GrabKeyboardReply, it would be interesting to log, if it succeeds, although this is not the issue at hand, because...
Because this seems like a bug in the DEs application switcher, normally if the window has successfully obtained a grab, it should receive all keyboard events (including the alt+tab release event).
Sorry I was not being clear around this. With the mouse inside cosmic-comp window (grabbed), all keyboard is indeed handled by cosmic-comp, including ALT+TAB This behaves correctly. Only when I move the mouse out of cosmic-comp window (ungrabbed) and ALT+TAB, do I cause issue 2.
Seems even with the mouse outside cosmic-comp window (ungrabbed), cosmic-comp still has focus so when doing ALT+TAB, cosmic-comp/smithay detects a ALT-pressed, but as soon as TAB is hit, the main Pop_OS! shell switches apps and ALT-pressed stays stuck in cosmic-comp/smithay
This indicates, that grabbing is not related to this issue at all. Just moving the mouse outside the window and loosing focus while a modifier is pressed, would cause said modifier to get stuck.
It seems winit has applied a similar fix to a very similar problem: https://github.com/rust-windowing/winit/pull/1279
The correct solution here is not resetting the modifiers (which might report modifiers as unset, when they are not), but to query the modifiers from X11 after gaining focus again.
The functions they use to get that state seems little annoying, but should map to similar calls from x11rb: https://github.com/murarth/winit/blob/master/src/platform_impl/linux/x11/util/modifiers.rs#L50-L95
Great thanks, makes sense. I will attempt to make a PR for the correct fix then.
X has a XKeymapEvent
that's produced when the window gains keyboard focus, which it should be possible to use to determine what keys (including modifiers) are held when the window is focused. But interestingly GTK doesn't seem to use and, and I guess the winit code linked above doesn't either.
In experimenting with making smithay x11 backend grab keyboard to allow super key shortcuts to work (when the smithay x11 backend window is not the main x11 shell), I have these edits in src/backend/x11/window_inner.rs
This does work, with one major issue. When the x11 backend is not the main x11 shell but rather just another x11 window being run, and the user moves the mouse off the window and presses
ALT+TAB
, the window/seat sees thealt:true
keyboardModifiersState
up until theTAB
key is hit. At that point the x11 main shell switches app to another window. The window/seat does not end up getting thealt:false
. If the user then hitsALT+TAB
again to move back to the smithay x11 window, theModifiersState
stays stuck atalt:true
even though theALT
key is not pressed. At this point pressingALT
and releasing makes no difference, theModifiersState
seems permanently stuck atalt:true
Issue also described at https://github.com/pop-os/cosmic-comp/issues/9#issuecomment-1163218515
As per this suggestion https://github.com/pop-os/cosmic-comp/issues/9#issuecomment-1163258734 I have opened a ticket here to get feedback. The suggestion made was to possibly have the
ModifiersState
reset when the x11 window comes back into focus.