Source: qemu
Version: 1:2.8+dfsg-6+deb9u3
Severity: normal
Tags: patch

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);

-- System Information:
Debian Release: 9.4
  APT prefers stable
  APT policy: (990, 'stable'), (500, 'stable-updates'), (500, 'stable-debug')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.9.0-6-amd64 (SMP w/40 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), 
LANGUAGE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

Reply via email to