ui/gtk: use native keyboard scancodes on Windows

Since GTK 3.22 the function gdk_event_get_scancode() is
available. On Windows this function returns keyboard scancodes
and some extended flags. These raw keyboard scancodes are much
better suited for this use case than the half-cooked win32
virtual-key codes because scancodes report the key position on
the keyboard and the positions are independent of national
language settings.

Signed-off-by: Volker Rümelin <vr_qemu@t-online.de>
Message-id: 20200516072014.7766-10-vr_qemu@t-online.de
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
master
Volker Rümelin 2020-05-16 09:20:13 +02:00 committed by Gerd Hoffmann
parent d3953bf797
commit 1454192746
1 changed files with 29 additions and 4 deletions

View File

@ -1026,8 +1026,13 @@ static const guint16 *gd_get_keymap(size_t *maplen)
#ifdef GDK_WINDOWING_WIN32 #ifdef GDK_WINDOWING_WIN32
if (GDK_IS_WIN32_DISPLAY(dpy)) { if (GDK_IS_WIN32_DISPLAY(dpy)) {
trace_gd_keymap_windowing("win32"); trace_gd_keymap_windowing("win32");
#if GTK_CHECK_VERSION(3, 22, 0)
*maplen = qemu_input_map_atset1_to_qcode_len;
return qemu_input_map_atset1_to_qcode;
#else
*maplen = qemu_input_map_win32_to_qcode_len; *maplen = qemu_input_map_win32_to_qcode_len;
return qemu_input_map_win32_to_qcode; return qemu_input_map_win32_to_qcode;
#endif
} }
#endif #endif
@ -1073,6 +1078,25 @@ static int gd_map_keycode(int scancode)
return keycode_map[scancode]; return keycode_map[scancode];
} }
static int gd_get_keycode(GdkEventKey *key)
{
#if defined G_OS_WIN32 && GTK_CHECK_VERSION(3, 22, 0)
int scancode = gdk_event_get_scancode((GdkEvent *)key);
/* translate Windows native scancodes to atset1 keycodes */
switch (scancode & (KF_EXTENDED | 0xff)) {
case 0x145: /* NUMLOCK */
return scancode & 0xff;
}
return scancode & KF_EXTENDED ?
0xe000 | (scancode & 0xff) : scancode & 0xff;
#else
return key->hardware_keycode;
#endif
}
static gboolean gd_text_key_down(GtkWidget *widget, static gboolean gd_text_key_down(GtkWidget *widget,
GdkEventKey *key, void *opaque) GdkEventKey *key, void *opaque)
{ {
@ -1084,7 +1108,7 @@ static gboolean gd_text_key_down(GtkWidget *widget,
} else if (key->length) { } else if (key->length) {
kbd_put_string_console(con, key->string, key->length); kbd_put_string_console(con, key->string, key->length);
} else { } else {
int qcode = gd_map_keycode(key->hardware_keycode); int qcode = gd_map_keycode(gd_get_keycode(key));
kbd_put_qcode_console(con, qcode, false); kbd_put_qcode_console(con, qcode, false);
} }
return TRUE; return TRUE;
@ -1093,7 +1117,7 @@ static gboolean gd_text_key_down(GtkWidget *widget,
static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque) static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque)
{ {
VirtualConsole *vc = opaque; VirtualConsole *vc = opaque;
int qcode; int keycode, qcode;
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
/* on windows, we ought to ignore the reserved key event? */ /* on windows, we ought to ignore the reserved key event? */
@ -1121,9 +1145,10 @@ static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque)
return TRUE; return TRUE;
} }
qcode = gd_map_keycode(key->hardware_keycode); keycode = gd_get_keycode(key);
qcode = gd_map_keycode(keycode);
trace_gd_key_event(vc->label, key->hardware_keycode, qcode, trace_gd_key_event(vc->label, keycode, qcode,
(key->type == GDK_KEY_PRESS) ? "down" : "up"); (key->type == GDK_KEY_PRESS) ? "down" : "up");
qkbd_state_key_event(vc->gfx.kbd, qcode, qkbd_state_key_event(vc->gfx.kbd, qcode,