From nobody Sun Feb 8 20:13:32 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1548152774169267.37316343393434; Tue, 22 Jan 2019 02:26:14 -0800 (PST) Received: from localhost ([127.0.0.1]:42371 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gltFw-0003LE-5Q for importer@patchew.org; Tue, 22 Jan 2019 05:26:08 -0500 Received: from eggs.gnu.org ([209.51.188.92]:58945) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1glsVw-00068S-K5 for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:38:37 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1glsM5-0003U0-4W for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:28:27 -0500 Received: from mx1.redhat.com ([209.132.183.28]:49908) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1glsM4-0003TU-SG for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:28:25 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1DF40ED258 for ; Tue, 22 Jan 2019 09:28:24 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-38.ams2.redhat.com [10.36.116.38]) by smtp.corp.redhat.com (Postfix) with ESMTP id D34885C20D; Tue, 22 Jan 2019 09:28:15 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 0D5E342280; Tue, 22 Jan 2019 10:28:15 +0100 (CET) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Tue, 22 Jan 2019 10:28:07 +0100 Message-Id: <20190122092814.14919-2-kraxel@redhat.com> In-Reply-To: <20190122092814.14919-1-kraxel@redhat.com> References: <20190122092814.14919-1-kraxel@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Tue, 22 Jan 2019 09:28:24 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC PATCH v3 1/8] kbd-state: add keyboard state tracker X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Now that most user interfaces are using QKeyCodes it is easier to have common keyboard code useable by all user interfaces. This patch adds helper code to track the state of all keyboard keys, using a bitmap indexed by QKeyCode. Modifier state is tracked too, as separate bitmap. That makes checking modifier state easier. Likewise we can easily apply special handling for capslock & numlock (toggles on keypress) and ctrl + shift (we have two keys for that). Signed-off-by: Gerd Hoffmann --- include/ui/kbd-state.h | 96 +++++++++++++++++++++++++++++++++++++ ui/kbd-state.c | 125 +++++++++++++++++++++++++++++++++++++++++++++= ++++ ui/Makefile.objs | 2 +- 3 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 include/ui/kbd-state.h create mode 100644 ui/kbd-state.c diff --git a/include/ui/kbd-state.h b/include/ui/kbd-state.h new file mode 100644 index 0000000000..277198f169 --- /dev/null +++ b/include/ui/kbd-state.h @@ -0,0 +1,96 @@ +#ifndef QEMU_UI_KBD_STATE_H +#define QEMU_UI_KBD_STATE_H 1 + +#include "qapi/qapi-types-ui.h" + +typedef enum QKbdModifier QKbdModifier; + +enum QKbdModifier { + QKBD_MOD_NONE =3D 0, + + QKBD_MOD_SHIFT, + QKBD_MOD_CTRL, + QKBD_MOD_ALT, + QKBD_MOD_ALTGR, + + QKBD_MOD_NUMLOCK, + QKBD_MOD_CAPSLOCK, + + QKBD_MOD__MAX +}; + +typedef struct QKbdState QKbdState; + +/** + * qkbd_state_init: init keyboard state tracker. + * + * Allocates and initializes keyboard state struct. + * + * @con: QemuConsole for this state tracker. Gets passed down to + * qemu_input_*() functions when sending key events to the guest. + */ +QKbdState *qkbd_state_init(QemuConsole *con); + +/** + * qkbd_state_free: free keyboard tracker state. + * + * @kbd: state tracker state. + */ +void qkbd_state_free(QKbdState *kbd); + +/** + * qkbd_state_key_event: process key event. + * + * Update keyboard state, send event to the guest. + * + * This function takes care to not send suspious events (keyup event + * for a key not pressed for example). + * + * @kbd: state tracker state. + * @qcode: the key pressed or released. + * @down: true for key down events, false otherwise. + */ +void qkbd_state_key_event(QKbdState *kbd, QKeyCode qcode, bool down); + +/** + * qkbd_state_set_delay: set key press delay. + * + * When set the specified delay will be added after each key event, + * using qemu_input_event_send_key_delay(). + * + * @kbd: state tracker state. + * @delay_ms: the delay in miliseconds. + */ +void qkbd_state_set_delay(QKbdState *kbd, int delay_ms); + +/** + * qkbd_state_key_get: get key state. + * + * Returns true when the key is down. + * + * @kbd: state tracker state. + * @qcode: the key to query. + */ +bool qkbd_state_key_get(QKbdState *kbd, QKeyCode qcode); + +/** + * qkbd_state_modifier_get: get modifier state. + * + * Returns true when the modifier is active. + * + * @kbd: state tracker state. + * @mod: the modifier to query. + */ +bool qkbd_state_modifier_get(QKbdState *kbd, QKbdModifier mod); + +/** + * qkbd_state_lift_all_keys: lift all pressed keys. + * + * This sends key up events to the guest for all keys which are in + * down state. + * + * @kbd: state tracker state. + */ +void qkbd_state_lift_all_keys(QKbdState *kbd); + +#endif /* QEMU_UI_KBD_STATE_H */ diff --git a/ui/kbd-state.c b/ui/kbd-state.c new file mode 100644 index 0000000000..c8397ebed4 --- /dev/null +++ b/ui/kbd-state.c @@ -0,0 +1,125 @@ +#include "qemu/osdep.h" +#include "qemu/bitmap.h" +#include "qemu/queue.h" +#include "ui/console.h" +#include "ui/input.h" +#include "ui/kbd-state.h" + +struct QKbdState { + QemuConsole *con; + int key_delay_ms; + DECLARE_BITMAP(keys, Q_KEY_CODE__MAX); + DECLARE_BITMAP(mods, QKBD_MOD__MAX); +}; + +static void qkbd_state_modifier_update(QKbdState *kbd, + QKeyCode qcode1, QKeyCode qcode2, + QKbdModifier mod) +{ + if (test_bit(qcode1, kbd->keys) || test_bit(qcode2, kbd->keys)) { + set_bit(mod, kbd->mods); + } else { + clear_bit(mod, kbd->mods); + } +} + +bool qkbd_state_modifier_get(QKbdState *kbd, QKbdModifier mod) +{ + return test_bit(mod, kbd->mods); +} + +bool qkbd_state_key_get(QKbdState *kbd, QKeyCode qcode) +{ + return test_bit(qcode, kbd->keys); +} + +void qkbd_state_key_event(QKbdState *kbd, QKeyCode qcode, bool down) +{ + bool state =3D test_bit(qcode, kbd->keys); + + if (state =3D=3D down) { + /* + * Filter out events which don't change the keyboard state. + * + * Most notably this allows to simply send along all key-up + * events, and this function will filter out everything where + * the corresponding key-down event wasn't send to the guest, + * for example due to being a host hotkey. + */ + return; + } + + /* update key and modifier state */ + change_bit(qcode, kbd->keys); + switch (qcode) { + case Q_KEY_CODE_SHIFT: + case Q_KEY_CODE_SHIFT_R: + qkbd_state_modifier_update(kbd, Q_KEY_CODE_SHIFT, Q_KEY_CODE_SHIFT= _R, + QKBD_MOD_SHIFT); + break; + case Q_KEY_CODE_CTRL: + case Q_KEY_CODE_CTRL_R: + qkbd_state_modifier_update(kbd, Q_KEY_CODE_CTRL, Q_KEY_CODE_CTRL_R, + QKBD_MOD_CTRL); + break; + case Q_KEY_CODE_ALT: + qkbd_state_modifier_update(kbd, Q_KEY_CODE_ALT, Q_KEY_CODE_ALT, + QKBD_MOD_ALT); + break; + case Q_KEY_CODE_ALT_R: + qkbd_state_modifier_update(kbd, Q_KEY_CODE_ALT_R, Q_KEY_CODE_ALT_R, + QKBD_MOD_ALTGR); + break; + case Q_KEY_CODE_CAPS_LOCK: + if (down) { + change_bit(QKBD_MOD_CAPSLOCK, kbd->mods); + } + break; + case Q_KEY_CODE_NUM_LOCK: + if (down) { + change_bit(QKBD_MOD_NUMLOCK, kbd->mods); + } + break; + default: + /* keep gcc happy */ + break; + } + + /* send to guest */ + if (qemu_console_is_graphic(kbd->con)) { + qemu_input_event_send_key_qcode(kbd->con, qcode, down); + if (kbd->key_delay_ms) { + qemu_input_event_send_key_delay(kbd->key_delay_ms); + } + } +} + +void qkbd_state_lift_all_keys(QKbdState *kbd) +{ + int qcode; + + for (qcode =3D 0; qcode < Q_KEY_CODE__MAX; qcode++) { + if (test_bit(qcode, kbd->keys)) { + qkbd_state_key_event(kbd, qcode, false); + } + } +} + +void qkbd_state_set_delay(QKbdState *kbd, int delay_ms) +{ + kbd->key_delay_ms =3D delay_ms; +} + +void qkbd_state_free(QKbdState *kbd) +{ + g_free(kbd); +} + +QKbdState *qkbd_state_init(QemuConsole *con) +{ + QKbdState *kbd =3D g_new0(QKbdState, 1); + + kbd->con =3D con; + + return kbd; +} diff --git a/ui/Makefile.objs b/ui/Makefile.objs index 00f6976c30..3c04bdda94 100644 --- a/ui/Makefile.objs +++ b/ui/Makefile.objs @@ -8,7 +8,7 @@ vnc-obj-y +=3D vnc-ws.o vnc-obj-y +=3D vnc-jobs.o =20 common-obj-y +=3D keymaps.o console.o cursor.o qemu-pixman.o -common-obj-y +=3D input.o input-keymap.o input-legacy.o +common-obj-y +=3D input.o input-keymap.o input-legacy.o kbd-state.o common-obj-$(CONFIG_LINUX) +=3D input-linux.o common-obj-$(CONFIG_SPICE) +=3D spice-core.o spice-input.o spice-display.o common-obj-$(CONFIG_COCOA) +=3D cocoa.o --=20 2.9.3 From nobody Sun Feb 8 20:13:32 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 154815243764574.63804804342521; Tue, 22 Jan 2019 02:20:37 -0800 (PST) Received: from localhost ([127.0.0.1]:42231 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gltAW-0006sB-Kq for importer@patchew.org; Tue, 22 Jan 2019 05:20:32 -0500 Received: from eggs.gnu.org ([209.51.188.92]:59106) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1glsVw-0006AI-M1 for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:38:37 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1glsM0-0003OS-Rb for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:28:21 -0500 Received: from mx1.redhat.com ([209.132.183.28]:57636) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1glsM0-0003MP-Lz for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:28:20 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 66A9C50452 for ; Tue, 22 Jan 2019 09:28:19 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-38.ams2.redhat.com [10.36.116.38]) by smtp.corp.redhat.com (Postfix) with ESMTP id D153060920; Tue, 22 Jan 2019 09:28:15 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 169034229C; Tue, 22 Jan 2019 10:28:15 +0100 (CET) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Tue, 22 Jan 2019 10:28:08 +0100 Message-Id: <20190122092814.14919-3-kraxel@redhat.com> In-Reply-To: <20190122092814.14919-1-kraxel@redhat.com> References: <20190122092814.14919-1-kraxel@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Tue, 22 Jan 2019 09:28:19 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC PATCH v3 2/8] sdl2: remove sdl2_reset_keys() function X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" No users left, dead code. Signed-off-by: Gerd Hoffmann --- include/ui/sdl2.h | 1 - ui/sdl2-input.c | 16 ---------------- 2 files changed, 17 deletions(-) diff --git a/include/ui/sdl2.h b/include/ui/sdl2.h index f43eecdbd6..fffbbfaee4 100644 --- a/include/ui/sdl2.h +++ b/include/ui/sdl2.h @@ -41,7 +41,6 @@ void sdl2_window_destroy(struct sdl2_console *scon); void sdl2_window_resize(struct sdl2_console *scon); void sdl2_poll_events(struct sdl2_console *scon); =20 -void sdl2_reset_keys(struct sdl2_console *scon); void sdl2_process_key(struct sdl2_console *scon, SDL_KeyboardEvent *ev); =20 diff --git a/ui/sdl2-input.c b/ui/sdl2-input.c index 1378b63dd9..208266c6a5 100644 --- a/ui/sdl2-input.c +++ b/ui/sdl2-input.c @@ -32,22 +32,6 @@ =20 static uint8_t modifiers_state[SDL_NUM_SCANCODES]; =20 -void sdl2_reset_keys(struct sdl2_console *scon) -{ - QemuConsole *con =3D scon ? scon->dcl.con : NULL; - int i; - - for (i =3D 0 ; - i < SDL_NUM_SCANCODES && i < qemu_input_map_usb_to_qcode_len ; - i++) { - if (modifiers_state[i]) { - int qcode =3D qemu_input_map_usb_to_qcode[i]; - qemu_input_event_send_key_qcode(con, qcode, false); - modifiers_state[i] =3D 0; - } - } -} - void sdl2_process_key(struct sdl2_console *scon, SDL_KeyboardEvent *ev) { --=20 2.9.3 From nobody Sun Feb 8 20:13:32 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1548151966106196.99129593753844; Tue, 22 Jan 2019 02:12:46 -0800 (PST) Received: from localhost ([127.0.0.1]:42116 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1glt2z-0000ed-2c for importer@patchew.org; Tue, 22 Jan 2019 05:12:45 -0500 Received: from eggs.gnu.org ([209.51.188.92]:59571) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1glsVw-0006XP-LE for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:38:37 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1glsM0-0003OD-PH for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:28:21 -0500 Received: from mx1.redhat.com ([209.132.183.28]:49882) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1glsM0-0003MR-GG for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:28:20 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 70AD8D2EE5 for ; Tue, 22 Jan 2019 09:28:19 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-38.ams2.redhat.com [10.36.116.38]) by smtp.corp.redhat.com (Postfix) with ESMTP id D27CF5D739; Tue, 22 Jan 2019 09:28:15 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 21062422A1; Tue, 22 Jan 2019 10:28:15 +0100 (CET) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Tue, 22 Jan 2019 10:28:09 +0100 Message-Id: <20190122092814.14919-4-kraxel@redhat.com> In-Reply-To: <20190122092814.14919-1-kraxel@redhat.com> References: <20190122092814.14919-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Tue, 22 Jan 2019 09:28:19 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC PATCH v3 3/8] kbd-state: use state tracker for sdl2 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Use the new keyboard state tracked for sdl2. We can drop the modifier state tracking from sdl2. Also keyup code is simpler, the state tracker will take care to not send suspious keyup events to the guest. Signed-off-by: Gerd Hoffmann Reviewed-by: Daniel P. Berrang=C3=A9 --- include/ui/sdl2.h | 2 ++ ui/sdl2-input.c | 27 ++------------------------- ui/sdl2.c | 12 +++--------- 3 files changed, 7 insertions(+), 34 deletions(-) diff --git a/include/ui/sdl2.h b/include/ui/sdl2.h index fffbbfaee4..6627fe05b0 100644 --- a/include/ui/sdl2.h +++ b/include/ui/sdl2.h @@ -7,6 +7,7 @@ #include #include =20 +#include "ui/kbd-state.h" #ifdef CONFIG_OPENGL # include "ui/egl-helpers.h" #endif @@ -27,6 +28,7 @@ struct sdl2_console { int idle_counter; int ignore_hotkeys; SDL_GLContext winctx; + QKbdState *kbd; #ifdef CONFIG_OPENGL QemuGLShader *gls; egl_fb guest_fb; diff --git a/ui/sdl2-input.c b/ui/sdl2-input.c index 208266c6a5..22e3336aab 100644 --- a/ui/sdl2-input.c +++ b/ui/sdl2-input.c @@ -30,8 +30,6 @@ #include "ui/sdl2.h" #include "sysemu/sysemu.h" =20 -static uint8_t modifiers_state[SDL_NUM_SCANCODES]; - void sdl2_process_key(struct sdl2_console *scon, SDL_KeyboardEvent *ev) { @@ -43,31 +41,10 @@ void sdl2_process_key(struct sdl2_console *scon, } =20 qcode =3D qemu_input_map_usb_to_qcode[ev->keysym.scancode]; - - /* modifier state tracking */ - switch (ev->keysym.scancode) { - case SDL_SCANCODE_LCTRL: - case SDL_SCANCODE_LSHIFT: - case SDL_SCANCODE_LALT: - case SDL_SCANCODE_LGUI: - case SDL_SCANCODE_RCTRL: - case SDL_SCANCODE_RSHIFT: - case SDL_SCANCODE_RALT: - case SDL_SCANCODE_RGUI: - if (ev->type =3D=3D SDL_KEYUP) { - modifiers_state[ev->keysym.scancode] =3D 0; - } else { - modifiers_state[ev->keysym.scancode] =3D 1; - } - break; - default: - /* nothing */ - break; - } + qkbd_state_key_event(scon->kbd, qcode, ev->type =3D=3D SDL_KEYDOWN); =20 if (!qemu_console_is_graphic(con)) { - bool ctrl =3D (modifiers_state[SDL_SCANCODE_LCTRL] || - modifiers_state[SDL_SCANCODE_RCTRL]); + bool ctrl =3D qkbd_state_modifier_get(scon->kbd, QKBD_MOD_CTRL); if (ev->type =3D=3D SDL_KEYDOWN) { switch (ev->keysym.scancode) { case SDL_SCANCODE_RETURN: diff --git a/ui/sdl2.c b/ui/sdl2.c index a10b6e3a08..13ad4a76eb 100644 --- a/ui/sdl2.c +++ b/ui/sdl2.c @@ -38,7 +38,6 @@ static int gui_grab; /* if true, all keyboard/mouse event= s are grabbed */ =20 static int gui_saved_grab; static int gui_fullscreen; -static int gui_keysym; static int gui_grab_code =3D KMOD_LALT | KMOD_LCTRL; static SDL_Cursor *sdl_cursor_normal; static SDL_Cursor *sdl_cursor_hidden; @@ -330,6 +329,7 @@ static void handle_keydown(SDL_Event *ev) int win; struct sdl2_console *scon =3D get_scon_from_window(ev->key.windowID); int gui_key_modifier_pressed =3D get_mod_state(); + int gui_keysym =3D 0; =20 if (!scon->ignore_hotkeys && gui_key_modifier_pressed && !ev->key.repe= at) { switch (ev->key.keysym.scancode) { @@ -410,16 +410,9 @@ static void handle_keydown(SDL_Event *ev) static void handle_keyup(SDL_Event *ev) { struct sdl2_console *scon =3D get_scon_from_window(ev->key.windowID); - int gui_key_modifier_pressed =3D get_mod_state(); =20 scon->ignore_hotkeys =3D false; - - if (!gui_key_modifier_pressed) { - gui_keysym =3D 0; - } - if (!gui_keysym) { - sdl2_process_key(scon, &ev->key); - } + sdl2_process_key(scon, &ev->key); } =20 static void handle_textinput(SDL_Event *ev) @@ -823,6 +816,7 @@ static void sdl2_display_init(DisplayState *ds, Display= Options *o) sdl2_console[i].dcl.ops =3D &dcl_2d_ops; #endif sdl2_console[i].dcl.con =3D con; + sdl2_console[i].kbd =3D qkbd_state_init(con); register_displaychangelistener(&sdl2_console[i].dcl); =20 #if defined(SDL_VIDEO_DRIVER_WINDOWS) || defined(SDL_VIDEO_DRIVER_X11) --=20 2.9.3 From nobody Sun Feb 8 20:13:32 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1548151214870439.93228109055474; Tue, 22 Jan 2019 02:00:14 -0800 (PST) Received: from localhost ([127.0.0.1]:41890 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1glsqp-0007Fp-SV for importer@patchew.org; Tue, 22 Jan 2019 05:00:11 -0500 Received: from eggs.gnu.org ([209.51.188.92]:59386) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1glsVy-0006Mz-GS for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:38:39 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1glsM0-0003O7-OW for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:28:21 -0500 Received: from mx1.redhat.com ([209.132.183.28]:39706) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1glsM0-0003MH-IR for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:28:20 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4761D753F9 for ; Tue, 22 Jan 2019 09:28:19 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-38.ams2.redhat.com [10.36.116.38]) by smtp.corp.redhat.com (Postfix) with ESMTP id D1E415D738; Tue, 22 Jan 2019 09:28:15 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 28D7342303; Tue, 22 Jan 2019 10:28:15 +0100 (CET) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Tue, 22 Jan 2019 10:28:10 +0100 Message-Id: <20190122092814.14919-5-kraxel@redhat.com> In-Reply-To: <20190122092814.14919-1-kraxel@redhat.com> References: <20190122092814.14919-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Tue, 22 Jan 2019 09:28:19 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC PATCH v3 4/8] sdl2: use only QKeyCode in sdl2_process_key() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Also: sdl2_process_key is never called with scon =3D=3D NULL. Signed-off-by: Gerd Hoffmann Reviewed-by: Daniel P. Berrang=C3=A9 --- ui/sdl2-input.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ui/sdl2-input.c b/ui/sdl2-input.c index 22e3336aab..664364a5e5 100644 --- a/ui/sdl2-input.c +++ b/ui/sdl2-input.c @@ -34,20 +34,19 @@ void sdl2_process_key(struct sdl2_console *scon, SDL_KeyboardEvent *ev) { int qcode; - QemuConsole *con =3D scon ? scon->dcl.con : NULL; + QemuConsole *con =3D scon->dcl.con; =20 if (ev->keysym.scancode >=3D qemu_input_map_usb_to_qcode_len) { return; } - qcode =3D qemu_input_map_usb_to_qcode[ev->keysym.scancode]; qkbd_state_key_event(scon->kbd, qcode, ev->type =3D=3D SDL_KEYDOWN); =20 if (!qemu_console_is_graphic(con)) { bool ctrl =3D qkbd_state_modifier_get(scon->kbd, QKBD_MOD_CTRL); if (ev->type =3D=3D SDL_KEYDOWN) { - switch (ev->keysym.scancode) { - case SDL_SCANCODE_RETURN: + switch (qcode) { + case Q_KEY_CODE_RET: kbd_put_keysym_console(con, '\n'); break; default: --=20 2.9.3 From nobody Sun Feb 8 20:13:32 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 15481510450841020.5509451947161; Tue, 22 Jan 2019 01:57:25 -0800 (PST) Received: from localhost ([127.0.0.1]:41863 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1glso4-0004uB-GJ for importer@patchew.org; Tue, 22 Jan 2019 04:57:20 -0500 Received: from eggs.gnu.org ([209.51.188.92]:59723) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1glsVw-0006nx-Jt for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:38:37 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1glsM4-0003TZ-Dj for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:28:30 -0500 Received: from mx1.redhat.com ([209.132.183.28]:42284) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1glsM3-0003Qf-WC for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:28:24 -0500 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4085C8667B for ; Tue, 22 Jan 2019 09:28:23 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-38.ams2.redhat.com [10.36.116.38]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0969F6013B; Tue, 22 Jan 2019 09:28:20 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 329CF423A4; Tue, 22 Jan 2019 10:28:15 +0100 (CET) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Tue, 22 Jan 2019 10:28:11 +0100 Message-Id: <20190122092814.14919-6-kraxel@redhat.com> In-Reply-To: <20190122092814.14919-1-kraxel@redhat.com> References: <20190122092814.14919-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Tue, 22 Jan 2019 09:28:23 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC PATCH v3 5/8] kbd-state: use state tracker for gtk X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Use the new keyboard state tracked for gtk. Allows to drop the gtk-specific modifier state tracking code. Signed-off-by: Gerd Hoffmann Reviewed-by: Daniel P. Berrang=C3=A9 --- include/ui/gtk.h | 2 ++ ui/gtk.c | 38 ++++++-------------------------------- 2 files changed, 8 insertions(+), 32 deletions(-) diff --git a/include/ui/gtk.h b/include/ui/gtk.h index 99edd3c085..d9eedad976 100644 --- a/include/ui/gtk.h +++ b/include/ui/gtk.h @@ -22,6 +22,7 @@ #include #endif =20 +#include "ui/kbd-state.h" #if defined(CONFIG_OPENGL) #include "ui/egl-helpers.h" #include "ui/egl-context.h" @@ -32,6 +33,7 @@ typedef struct GtkDisplayState GtkDisplayState; typedef struct VirtualGfxConsole { GtkWidget *drawing_area; DisplayChangeListener dcl; + QKbdState *kbd; DisplaySurface *ds; pixman_image_t *convert; cairo_surface_t *surface; diff --git a/ui/gtk.c b/ui/gtk.c index 579990b865..1be65025f2 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -122,17 +122,6 @@ =20 #define HOTKEY_MODIFIERS (GDK_CONTROL_MASK | GDK_MOD1_MASK) =20 -static const int modifier_keycode[] =3D { - Q_KEY_CODE_SHIFT, - Q_KEY_CODE_SHIFT_R, - Q_KEY_CODE_CTRL, - Q_KEY_CODE_CTRL_R, - Q_KEY_CODE_ALT, - Q_KEY_CODE_ALT_R, - Q_KEY_CODE_META_L, - Q_KEY_CODE_META_R, -}; - static const guint16 *keycode_map; static size_t keycode_maplen; =20 @@ -187,7 +176,6 @@ struct GtkDisplayState { =20 bool external_pause_update; =20 - bool modifier_pressed[ARRAY_SIZE(modifier_keycode)]; bool ignore_keys; =20 DisplayOptions *opts; @@ -426,20 +414,12 @@ static void gd_update_full_redraw(VirtualConsole *vc) static void gtk_release_modifiers(GtkDisplayState *s) { VirtualConsole *vc =3D gd_vc_find_current(s); - int i, qcode; =20 if (vc->type !=3D GD_VC_GFX || !qemu_console_is_graphic(vc->gfx.dcl.con)) { return; } - for (i =3D 0; i < ARRAY_SIZE(modifier_keycode); i++) { - qcode =3D modifier_keycode[i]; - if (!s->modifier_pressed[i]) { - continue; - } - qemu_input_event_send_key_qcode(vc->gfx.dcl.con, qcode, false); - s->modifier_pressed[i] =3D false; - } + qkbd_state_lift_all_keys(vc->gfx.kbd); } =20 static void gd_widget_reparent(GtkWidget *from, GtkWidget *to, @@ -1113,7 +1093,6 @@ static gboolean gd_key_event(GtkWidget *widget, GdkEv= entKey *key, void *opaque) VirtualConsole *vc =3D opaque; GtkDisplayState *s =3D vc->s; int qcode; - int i; =20 if (s->ignore_keys) { s->ignore_keys =3D (key->type =3D=3D GDK_KEY_PRESS); @@ -1134,8 +1113,8 @@ static gboolean gd_key_event(GtkWidget *widget, GdkEv= entKey *key, void *opaque) || key->hardware_keycode =3D=3D VK_PAUSE #endif ) { - qemu_input_event_send_key_qcode(vc->gfx.dcl.con, Q_KEY_CODE_PAUSE, - key->type =3D=3D GDK_KEY_PRESS); + qkbd_state_key_event(vc->gfx.kbd, Q_KEY_CODE_PAUSE, + key->type =3D=3D GDK_KEY_PRESS); return TRUE; } =20 @@ -1144,14 +1123,8 @@ static gboolean gd_key_event(GtkWidget *widget, GdkE= ventKey *key, void *opaque) trace_gd_key_event(vc->label, key->hardware_keycode, qcode, (key->type =3D=3D GDK_KEY_PRESS) ? "down" : "up"); =20 - for (i =3D 0; i < ARRAY_SIZE(modifier_keycode); i++) { - if (qcode =3D=3D modifier_keycode[i]) { - s->modifier_pressed[i] =3D (key->type =3D=3D GDK_KEY_PRESS); - } - } - - qemu_input_event_send_key_qcode(vc->gfx.dcl.con, qcode, - key->type =3D=3D GDK_KEY_PRESS); + qkbd_state_key_event(vc->gfx.kbd, qcode, + key->type =3D=3D GDK_KEY_PRESS); =20 return TRUE; } @@ -2052,6 +2025,7 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, Vir= tualConsole *vc, gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook), vc->tab_item, gtk_label_new(vc->label)); =20 + vc->gfx.kbd =3D qkbd_state_init(con); vc->gfx.dcl.con =3D con; register_displaychangelistener(&vc->gfx.dcl); =20 --=20 2.9.3 From nobody Sun Feb 8 20:13:32 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1548152516843505.1476686846162; Tue, 22 Jan 2019 02:21:56 -0800 (PST) Received: from localhost ([127.0.0.1]:42266 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gltBm-000823-Ko for importer@patchew.org; Tue, 22 Jan 2019 05:21:50 -0500 Received: from eggs.gnu.org ([209.51.188.92]:59267) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1glsVw-0006Ht-KB for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:38:38 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1glsM3-0003Qo-MF for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:28:24 -0500 Received: from mx1.redhat.com ([209.132.183.28]:49026) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1glsM3-0003QZ-EG for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:28:23 -0500 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B07CE81F0D for ; Tue, 22 Jan 2019 09:28:22 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-38.ams2.redhat.com [10.36.116.38]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0EC101001F5B; Tue, 22 Jan 2019 09:28:20 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 3C22B423E7; Tue, 22 Jan 2019 10:28:15 +0100 (CET) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Tue, 22 Jan 2019 10:28:12 +0100 Message-Id: <20190122092814.14919-7-kraxel@redhat.com> In-Reply-To: <20190122092814.14919-1-kraxel@redhat.com> References: <20190122092814.14919-1-kraxel@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Tue, 22 Jan 2019 09:28:22 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC PATCH v3 6/8] kbd-state: use state tracker for vnc X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Use the new keyboard state tracked for vnc. Allows to drop the vnc-specific modifier state tracking code. Signed-off-by: Gerd Hoffmann Reviewed-by: Daniel P. Berrang=C3=A9 --- ui/vnc.h | 5 ++- ui/vnc.c | 120 ++++++++++++++++++-----------------------------------------= ---- 2 files changed, 35 insertions(+), 90 deletions(-) diff --git a/ui/vnc.h b/ui/vnc.h index a86e0610e8..81daa7a0eb 100644 --- a/ui/vnc.h +++ b/ui/vnc.h @@ -44,6 +44,7 @@ #include "keymaps.h" #include "vnc-palette.h" #include "vnc-enc-zrle.h" +#include "ui/kbd-state.h" =20 // #define _VNC_DEBUG 1 =20 @@ -155,7 +156,7 @@ struct VncDisplay int lock_key_sync; QEMUPutLEDEntry *led; int ledstate; - int key_delay_ms; + QKbdState *kbd; QemuMutex mutex; =20 QEMUCursor *cursor; @@ -326,8 +327,6 @@ struct VncState =20 VncReadEvent *read_handler; size_t read_handler_expect; - /* input */ - uint8_t modifiers_state[256]; =20 bool abort; QemuMutex output_mutex; diff --git a/ui/vnc.c b/ui/vnc.c index 9e4b2beb71..a9fe166ee8 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -59,7 +59,6 @@ static QTAILQ_HEAD(, VncDisplay) vnc_displays =3D QTAILQ_HEAD_INITIALIZER(vnc_displays); =20 static int vnc_cursor_define(VncState *vs); -static void vnc_release_modifiers(VncState *vs); static void vnc_update_throttle_offset(VncState *vs); =20 static void vnc_set_share_mode(VncState *vs, VncShareMode mode) @@ -1248,7 +1247,7 @@ void vnc_disconnect_finish(VncState *vs) vnc_sasl_client_cleanup(vs); #endif /* CONFIG_VNC_SASL */ audio_del(vs); - vnc_release_modifiers(vs); + qkbd_state_lift_all_keys(vs->vd->kbd); =20 if (vs->mouse_mode_notifier.notify !=3D NULL) { qemu_remove_mouse_mode_change_notifier(&vs->mouse_mode_notifier); @@ -1737,26 +1736,10 @@ static void pointer_event(VncState *vs, int button_= mask, int x, int y) qemu_input_event_sync(); } =20 -static void reset_keys(VncState *vs) +static void press_key(VncState *vs, QKeyCode qcode) { - int i; - for(i =3D 0; i < 256; i++) { - if (vs->modifiers_state[i]) { - qemu_input_event_send_key_number(vs->vd->dcl.con, i, false); - qemu_input_event_send_key_delay(vs->vd->key_delay_ms); - vs->modifiers_state[i] =3D 0; - } - } -} - -static void press_key(VncState *vs, int keysym) -{ - int keycode =3D keysym2scancode(vs->vd->kbd_layout, keysym, - false, false, false) & SCANCODE_KEYMASK; - qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, true); - qemu_input_event_send_key_delay(vs->vd->key_delay_ms); - qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, false); - qemu_input_event_send_key_delay(vs->vd->key_delay_ms); + qkbd_state_key_event(vs->vd->kbd, qcode, true); + qkbd_state_key_event(vs->vd->kbd, qcode, false); } =20 static void vnc_led_state_change(VncState *vs) @@ -1797,32 +1780,20 @@ static void kbd_leds(void *opaque, int ledstate) =20 static void do_key_event(VncState *vs, int down, int keycode, int sym) { + QKeyCode qcode =3D qemu_input_key_number_to_qcode(keycode); + /* QEMU console switch */ - switch(keycode) { - 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 (down) - vs->modifiers_state[keycode] =3D 1; - else - vs->modifiers_state[keycode] =3D 0; - break; - case 0x02 ... 0x0a: /* '1' to '9' keys */ - if (vs->vd->dcl.con =3D=3D NULL && - down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]= ) { + switch (qcode) { + case Q_KEY_CODE_1 ... Q_KEY_CODE_9: /* '1' to '9' keys */ + if (vs->vd->dcl.con =3D=3D NULL && down && + qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_CTRL) && + qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_ALT)) { /* Reset the modifiers sent to the current console */ - reset_keys(vs); - console_select(keycode - 0x02); + qkbd_state_lift_all_keys(vs->vd->kbd); + console_select(qcode - Q_KEY_CODE_1); return; } - break; - case 0x3a: /* CapsLock */ - case 0x45: /* NumLock */ - if (down) - vs->modifiers_state[keycode] ^=3D 1; + default: break; } =20 @@ -1837,16 +1808,14 @@ static void do_key_event(VncState *vs, int down, in= t keycode, int sym) toggles numlock away from the VNC window. */ if (keysym_is_numlock(vs->vd->kbd_layout, sym & 0xFFFF)) { - if (!vs->modifiers_state[0x45]) { + if (!qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_NUMLOCK)) { trace_vnc_key_sync_numlock(true); - vs->modifiers_state[0x45] =3D 1; - press_key(vs, 0xff7f); + press_key(vs, Q_KEY_CODE_NUM_LOCK); } } else { - if (vs->modifiers_state[0x45]) { + if (qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_NUMLOCK)) { trace_vnc_key_sync_numlock(false); - vs->modifiers_state[0x45] =3D 0; - press_key(vs, 0xff7f); + press_key(vs, Q_KEY_CODE_NUM_LOCK); } } } @@ -1859,30 +1828,25 @@ static void do_key_event(VncState *vs, int down, in= t keycode, int sym) toggles capslock away from the VNC window. */ int uppercase =3D !!(sym >=3D 'A' && sym <=3D 'Z'); - int shift =3D !!(vs->modifiers_state[0x2a] | vs->modifiers_state[0= x36]); - int capslock =3D !!(vs->modifiers_state[0x3a]); + bool shift =3D qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_SHIFT= ); + bool capslock =3D qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_CA= PSLOCK); if (capslock) { if (uppercase =3D=3D shift) { trace_vnc_key_sync_capslock(false); - vs->modifiers_state[0x3a] =3D 0; - press_key(vs, 0xffe5); + press_key(vs, Q_KEY_CODE_CAPS_LOCK); } } else { if (uppercase !=3D shift) { trace_vnc_key_sync_capslock(true); - vs->modifiers_state[0x3a] =3D 1; - press_key(vs, 0xffe5); + press_key(vs, Q_KEY_CODE_CAPS_LOCK); } } } =20 - if (qemu_console_is_graphic(NULL)) { - qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, down); - qemu_input_event_send_key_delay(vs->vd->key_delay_ms); - } else { - bool numlock =3D vs->modifiers_state[0x45]; - bool control =3D (vs->modifiers_state[0x1d] || - vs->modifiers_state[0x9d]); + qkbd_state_key_event(vs->vd->kbd, qcode, down); + if (!qemu_console_is_graphic(NULL)) { + bool numlock =3D qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_NUM= LOCK); + bool control =3D qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_CTR= L); /* QEMU console emulation */ if (down) { switch (keycode) { @@ -1983,27 +1947,6 @@ static void do_key_event(VncState *vs, int down, int= keycode, int sym) } } =20 -static void vnc_release_modifiers(VncState *vs) -{ - static const int keycodes[] =3D { - /* shift, control, alt keys, both left & right */ - 0x2a, 0x36, 0x1d, 0x9d, 0x38, 0xb8, - }; - int i, keycode; - - if (!qemu_console_is_graphic(NULL)) { - return; - } - for (i =3D 0; i < ARRAY_SIZE(keycodes); i++) { - keycode =3D keycodes[i]; - if (!vs->modifiers_state[keycode]) { - continue; - } - qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, false); - qemu_input_event_send_key_delay(vs->vd->key_delay_ms); - } -} - static const char *code2name(int keycode) { return QKeyCode_str(qemu_input_key_number_to_qcode(keycode)); @@ -2011,9 +1954,9 @@ static const char *code2name(int keycode) =20 static void key_event(VncState *vs, int down, uint32_t sym) { - bool shift =3D vs->modifiers_state[0x2a] || vs->modifiers_state[0x36]; - bool altgr =3D vs->modifiers_state[0xb8]; - bool ctrl =3D vs->modifiers_state[0x1d] || vs->modifiers_state[0x9d]; + bool shift =3D qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_SHIFT); + bool altgr =3D qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_ALTGR); + bool ctrl =3D qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_CTRL); int keycode; int lsym =3D sym; =20 @@ -3240,6 +3183,7 @@ void vnc_display_init(const char *id, Error **errp) =20 vd->dcl.ops =3D &dcl_ops; register_displaychangelistener(&vd->dcl); + vd->kbd =3D qkbd_state_init(vd->dcl.con); } =20 =20 @@ -3976,7 +3920,6 @@ void vnc_display_open(const char *id, Error **errp) vd->led =3D qemu_add_led_event_handler(kbd_leds, vd); } vd->ledstate =3D 0; - vd->key_delay_ms =3D key_delay_ms; =20 device_id =3D qemu_opt_get(opts, "display"); if (device_id) { @@ -3993,10 +3936,13 @@ void vnc_display_open(const char *id, Error **errp) } =20 if (con !=3D vd->dcl.con) { + qkbd_state_free(vd->kbd); unregister_displaychangelistener(&vd->dcl); vd->dcl.con =3D con; register_displaychangelistener(&vd->dcl); + vd->kbd =3D qkbd_state_init(vd->dcl.con); } + qkbd_state_set_delay(vd->kbd, key_delay_ms); =20 if (saddr =3D=3D NULL) { goto cleanup; --=20 2.9.3 From nobody Sun Feb 8 20:13:32 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1548152140440914.8710515972493; Tue, 22 Jan 2019 02:15:40 -0800 (PST) Received: from localhost ([127.0.0.1]:42149 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1glt5n-0002xj-8r for importer@patchew.org; Tue, 22 Jan 2019 05:15:39 -0500 Received: from eggs.gnu.org ([209.51.188.92]:58893) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1glsVw-00065q-Ll for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:38:37 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1glsM1-0003QD-Ue for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:28:22 -0500 Received: from mx1.redhat.com ([209.132.183.28]:46526) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1glsM1-0003PJ-M4 for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:28:21 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E31237F3F7 for ; Tue, 22 Jan 2019 09:28:20 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-38.ams2.redhat.com [10.36.116.38]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1E2675C22C; Tue, 22 Jan 2019 09:28:20 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 480B24241D; Tue, 22 Jan 2019 10:28:15 +0100 (CET) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Tue, 22 Jan 2019 10:28:13 +0100 Message-Id: <20190122092814.14919-8-kraxel@redhat.com> In-Reply-To: <20190122092814.14919-1-kraxel@redhat.com> References: <20190122092814.14919-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Tue, 22 Jan 2019 09:28:20 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC PATCH v3 7/8] keymap: pass full keyboard state to keysym2scancode X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Pass the keyboard state tracker handle down to keysym2scancode(), so the code can fully inspect the keyboard state as needed. No functional change. Signed-off-by: Gerd Hoffmann Reviewed-by: Daniel P. Berrang=C3=A9 --- ui/keymaps.h | 3 ++- ui/curses.c | 2 +- ui/keymaps.c | 8 ++++---- ui/vnc.c | 5 +---- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/ui/keymaps.h b/ui/keymaps.h index 4e9c87fb8f..d8652b8a5a 100644 --- a/ui/keymaps.h +++ b/ui/keymaps.h @@ -26,6 +26,7 @@ #define QEMU_KEYMAPS_H =20 #include "qemu-common.h" +#include "ui/kbd-state.h" =20 typedef struct { const char* name; @@ -55,7 +56,7 @@ typedef struct kbd_layout_t kbd_layout_t; kbd_layout_t *init_keyboard_layout(const name2keysym_t *table, const char *language, Error **errp); int keysym2scancode(kbd_layout_t *k, int keysym, - bool shift, bool altgr, bool ctrl); + QKbdState *kbd); int keycode_is_keypad(kbd_layout_t *k, int keycode); int keysym_is_numlock(kbd_layout_t *k, int keysym); =20 diff --git a/ui/curses.c b/ui/curses.c index f4e7a12f74..54687589d4 100644 --- a/ui/curses.c +++ b/ui/curses.c @@ -273,7 +273,7 @@ static void curses_refresh(DisplayChangeListener *dcl) } =20 keycode =3D keysym2scancode(kbd_layout, keysym & KEYSYM_MASK, - false, false, false); + NULL); if (keycode =3D=3D 0) continue; =20 diff --git a/ui/keymaps.c b/ui/keymaps.c index 6e44f738ed..c8b2135340 100644 --- a/ui/keymaps.c +++ b/ui/keymaps.c @@ -188,7 +188,7 @@ kbd_layout_t *init_keyboard_layout(const name2keysym_t = *table, =20 =20 int keysym2scancode(kbd_layout_t *k, int keysym, - bool shift, bool altgr, bool ctrl) + QKbdState *kbd) { static const uint32_t mask =3D SCANCODE_SHIFT | SCANCODE_ALTGR | SCANCODE_CTRL; @@ -220,13 +220,13 @@ int keysym2scancode(kbd_layout_t *k, int keysym, * If so, prefer that one. */ mods =3D 0; - if (shift) { + if (kbd && qkbd_state_modifier_get(kbd, QKBD_MOD_SHIFT)) { mods |=3D SCANCODE_SHIFT; } - if (altgr) { + if (kbd && qkbd_state_modifier_get(kbd, QKBD_MOD_ALTGR)) { mods |=3D SCANCODE_ALTGR; } - if (ctrl) { + if (kbd && qkbd_state_modifier_get(kbd, QKBD_MOD_CTRL)) { mods |=3D SCANCODE_CTRL; } =20 diff --git a/ui/vnc.c b/ui/vnc.c index a9fe166ee8..fc41f9b318 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -1954,9 +1954,6 @@ static const char *code2name(int keycode) =20 static void key_event(VncState *vs, int down, uint32_t sym) { - bool shift =3D qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_SHIFT); - bool altgr =3D qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_ALTGR); - bool ctrl =3D qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_CTRL); int keycode; int lsym =3D sym; =20 @@ -1965,7 +1962,7 @@ static void key_event(VncState *vs, int down, uint32_= t sym) } =20 keycode =3D keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF, - shift, altgr, ctrl) & SCANCODE_KEYMASK; + vs->vd->kbd) & SCANCODE_KEYMASK; trace_vnc_key_event_map(down, sym, keycode, code2name(keycode)); do_key_event(vs, down, keycode, sym); } --=20 2.9.3 From nobody Sun Feb 8 20:13:32 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1548152608268756.3421098974698; Tue, 22 Jan 2019 02:23:28 -0800 (PST) Received: from localhost ([127.0.0.1]:42299 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gltDL-0000vK-3C for importer@patchew.org; Tue, 22 Jan 2019 05:23:27 -0500 Received: from eggs.gnu.org ([209.51.188.92]:59398) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1glsVw-0006NI-Jg for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:38:37 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1glsM7-0003Xa-T7 for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:28:32 -0500 Received: from mx1.redhat.com ([209.132.183.28]:38186) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1glsM7-0003UX-HZ for qemu-devel@nongnu.org; Tue, 22 Jan 2019 04:28:27 -0500 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B96DAC079C4B for ; Tue, 22 Jan 2019 09:28:25 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-38.ams2.redhat.com [10.36.116.38]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1AAAF6013C; Tue, 22 Jan 2019 09:28:20 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 5C96B51B80; Tue, 22 Jan 2019 10:28:15 +0100 (CET) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Tue, 22 Jan 2019 10:28:14 +0100 Message-Id: <20190122092814.14919-9-kraxel@redhat.com> In-Reply-To: <20190122092814.14919-1-kraxel@redhat.com> References: <20190122092814.14919-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Tue, 22 Jan 2019 09:28:25 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC PATCH v3 8/8] keymap: fix keyup mappings X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" It is possible that the modifier state on keyup is different from the modifier state on keydown. In that case the keycode lookup can end up with different keys in case multiple keysym -> keycode mappings exist, because it picks the mapping depending on modifier state. To fix that change the lookup logic for keyup events. Instead of looking at the modifier state check the key state and prefer a keycodes where the key is in "down" state right now. Fixes: abb4f2c965 keymap: consider modifier state when picking a mapping Buglink: https://bugs.launchpad.net/bugs/1738283 Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=3D1658676 Signed-off-by: Gerd Hoffmann Reviewed-by: Daniel P. Berrang=C3=A9 --- ui/keymaps.h | 2 +- ui/curses.c | 2 +- ui/keymaps.c | 55 ++++++++++++++++++++++++++++++++++--------------------- ui/vnc.c | 2 +- 4 files changed, 37 insertions(+), 24 deletions(-) diff --git a/ui/keymaps.h b/ui/keymaps.h index d8652b8a5a..b6d48aac40 100644 --- a/ui/keymaps.h +++ b/ui/keymaps.h @@ -56,7 +56,7 @@ typedef struct kbd_layout_t kbd_layout_t; kbd_layout_t *init_keyboard_layout(const name2keysym_t *table, const char *language, Error **errp); int keysym2scancode(kbd_layout_t *k, int keysym, - QKbdState *kbd); + QKbdState *kbd, bool down); int keycode_is_keypad(kbd_layout_t *k, int keycode); int keysym_is_numlock(kbd_layout_t *k, int keysym); =20 diff --git a/ui/curses.c b/ui/curses.c index 54687589d4..6e0091c3b2 100644 --- a/ui/curses.c +++ b/ui/curses.c @@ -273,7 +273,7 @@ static void curses_refresh(DisplayChangeListener *dcl) } =20 keycode =3D keysym2scancode(kbd_layout, keysym & KEYSYM_MASK, - NULL); + NULL, false); if (keycode =3D=3D 0) continue; =20 diff --git a/ui/keymaps.c b/ui/keymaps.c index c8b2135340..544b55c27b 100644 --- a/ui/keymaps.c +++ b/ui/keymaps.c @@ -28,6 +28,7 @@ #include "trace.h" #include "qemu/error-report.h" #include "qapi/error.h" +#include "ui/input.h" =20 struct keysym2code { uint32_t count; @@ -188,7 +189,7 @@ kbd_layout_t *init_keyboard_layout(const name2keysym_t = *table, =20 =20 int keysym2scancode(kbd_layout_t *k, int keysym, - QKbdState *kbd) + QKbdState *kbd, bool down) { static const uint32_t mask =3D SCANCODE_SHIFT | SCANCODE_ALTGR | SCANCODE_CTRL; @@ -212,27 +213,39 @@ int keysym2scancode(kbd_layout_t *k, int keysym, return keysym2code->keycodes[0]; } =20 - /* - * We have multiple keysym -> keycode mappings. - * - * Check whenever we find one mapping where the modifier state of - * the mapping matches the current user interface modifier state. - * If so, prefer that one. - */ - mods =3D 0; - if (kbd && qkbd_state_modifier_get(kbd, QKBD_MOD_SHIFT)) { - mods |=3D SCANCODE_SHIFT; - } - if (kbd && qkbd_state_modifier_get(kbd, QKBD_MOD_ALTGR)) { - mods |=3D SCANCODE_ALTGR; - } - if (kbd && qkbd_state_modifier_get(kbd, QKBD_MOD_CTRL)) { - mods |=3D SCANCODE_CTRL; - } + /* We have multiple keysym -> keycode mappings. */ + if (down) { + /* + * On keydown: Check whenever we find one mapping where the + * modifier state of the mapping matches the current user + * interface modifier state. If so, prefer that one. + */ + mods =3D 0; + if (kbd && qkbd_state_modifier_get(kbd, QKBD_MOD_SHIFT)) { + mods |=3D SCANCODE_SHIFT; + } + if (kbd && qkbd_state_modifier_get(kbd, QKBD_MOD_ALTGR)) { + mods |=3D SCANCODE_ALTGR; + } + if (kbd && qkbd_state_modifier_get(kbd, QKBD_MOD_CTRL)) { + mods |=3D SCANCODE_CTRL; + } =20 - for (i =3D 0; i < keysym2code->count; i++) { - if ((keysym2code->keycodes[i] & mask) =3D=3D mods) { - return keysym2code->keycodes[i]; + for (i =3D 0; i < keysym2code->count; i++) { + if ((keysym2code->keycodes[i] & mask) =3D=3D mods) { + return keysym2code->keycodes[i]; + } + } + } else { + /* + * On keyup: Try find a key which is actually down. + */ + for (i =3D 0; i < keysym2code->count; i++) { + QKeyCode qcode =3D qemu_input_key_number_to_qcode + (keysym2code->keycodes[i]); + if (kbd && qkbd_state_key_get(kbd, qcode)) { + return keysym2code->keycodes[i]; + } } } return keysym2code->keycodes[0]; diff --git a/ui/vnc.c b/ui/vnc.c index fc41f9b318..bc730496ae 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -1962,7 +1962,7 @@ static void key_event(VncState *vs, int down, uint32_= t sym) } =20 keycode =3D keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF, - vs->vd->kbd) & SCANCODE_KEYMASK; + vs->vd->kbd, down) & SCANCODE_KEYMASK; trace_vnc_key_event_map(down, sym, keycode, code2name(keycode)); do_key_event(vs, down, keycode, sym); } --=20 2.9.3