Dear Maintainer,
when running qemu in the default graphical mode, it does not correctly
handle what happens when the window loses keyboard focus.
For example:
* The window manager is configured to switch focus when Super+Tab is
pressed.
* A qemu window is focused.
* I press Super; a KeyPress event is sent to qemu, and the
corresponding keycode is sent to the guest OS.
* I press Tab, which is grabbed by the window manager; the WM
switches focus to another window.
* I release both keys; the KeyRelease events are now delivered to
that other window, and not to qemu.
* The guest OS still believes the Super key is pressed, and will
continue to believe so until I re-focus the qemu window, and press
and release Super while the window is focused.
The result can be quite frustrating because qemu doesn't give any
visual indication of what keys it believes are currently pressed, and
in most cases neither does the guest OS. Fixing the problem requires
the user to realize what has happened (which isn't obvious) and then
to press keys one at a time until they become un-wedged.
It appears that qemu will actually keep track of which "modifier" keys
are pressed, and automatically release *those* particular keys when
the window loses focus. However:
- It is limited to left and right Shift, Control, and Alt.
- It is based on qemu's idea of what physical keycodes correspond to
modifiers, which may have nothing to do with what keys are actually
mapped as X modifiers.
- There's no particular reason that the underlying problem is limited
to modifiers in the first place (there are plenty of other ways
that the window can lose focus while one or more keys are pressed.)
Below is a patch to fix this behavior for the SDL interface used in
stretch.
It looks like the latest version of the package, in unstable, has
removed the SDL interface in favor of GTK+. I haven't tested it, but
from a quick skim of the source, it appears that the GTK+ interface
will have the same problem (see gd_key_event() and
gtk_release_modifiers() in ui/gtk.c.)
--- qemu-2.8+dfsg.orig/ui/sdl.c
+++ qemu-2.8+dfsg/ui/sdl.c
@@ -328,17 +328,6 @@ static void sdl_process_key(SDL_Keyboard
/* sent when leaving window: reset the modifiers state */
reset_keys();
return;
- case 0x2a: /* Left Shift */
- case 0x36: /* Right Shift */
- case 0x1d: /* Left CTRL */
- case 0x9d: /* Right CTRL */
- case 0x38: /* Left ALT */
- case 0xb8: /* Right ALT */
- if (ev->type == SDL_KEYUP)
- modifiers_state[keycode] = 0;
- else
- modifiers_state[keycode] = 1;
- break;
#define QEMU_SDL_VERSION ((SDL_MAJOR_VERSION << 8) + SDL_MINOR_VERSION)
#if QEMU_SDL_VERSION < 0x102 || QEMU_SDL_VERSION == 0x102 && SDL_PATCHLEVEL < 14
/* SDL versions before 1.2.14 don't support key up for caps/num lock. */
@@ -351,6 +340,12 @@ static void sdl_process_key(SDL_Keyboard
#endif
}
+ assert(keycode >= 0 && keycode < ARRAY_SIZE(modifiers_state));
+ if (ev->type == SDL_KEYUP)
+ modifiers_state[keycode] = 0;
+ else
+ modifiers_state[keycode] = 1;
+
/* now send the key code */
qemu_input_event_send_key_number(dcl->con, keycode,
ev->type == SDL_KEYDOWN);