From nobody Wed Dec 17 06:08:54 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.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 208.118.235.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 [208.118.235.17]) by mx.zohomail.com with SMTPS id 151923325104448.1029191360783; Wed, 21 Feb 2018 09:14:11 -0800 (PST) Received: from localhost ([::1]:33859 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eoXy6-00059v-0h for importer@patchew.org; Wed, 21 Feb 2018 12:14:10 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39781) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eoXsY-0000Th-Gt for qemu-devel@nongnu.org; Wed, 21 Feb 2018 12:08:28 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eoXsW-0005dC-CY for qemu-devel@nongnu.org; Wed, 21 Feb 2018 12:08:26 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:40734 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eoXsW-0005cQ-6p for qemu-devel@nongnu.org; Wed, 21 Feb 2018 12:08:24 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id DA9AEEAEAB; Wed, 21 Feb 2018 17:08:23 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-147.ams2.redhat.com [10.36.116.147]) by smtp.corp.redhat.com (Postfix) with ESMTP id 916FF10A971A; Wed, 21 Feb 2018 17:08:21 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id CB74917514; Wed, 21 Feb 2018 18:08:20 +0100 (CET) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Wed, 21 Feb 2018 18:08:16 +0100 Message-Id: <20180221170820.15365-2-kraxel@redhat.com> In-Reply-To: <20180221170820.15365-1-kraxel@redhat.com> References: <20180221170820.15365-1-kraxel@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Wed, 21 Feb 2018 17:08:23 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Wed, 21 Feb 2018 17:08:23 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kraxel@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [RFC PATCH 1/5] 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: programmingkidx@gmail.com, Gerd Hoffmann , peter.maydell@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 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 | 22 +++++++++ ui/kbd-state.c | 119 +++++++++++++++++++++++++++++++++++++++++++++= ++++ ui/Makefile.objs | 2 +- 3 files changed, 142 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..c961da45b2 --- /dev/null +++ b/include/ui/kbd-state.h @@ -0,0 +1,22 @@ +typedef enum KbdModifier KbdModifier; + +enum KbdModifier { + KBD_MOD_NONE =3D 0, + + KBD_MOD_SHIFT, + KBD_MOD_CTRL, + KBD_MOD_ALT, + + KBD_MOD_NUMLOCK, + KBD_MOD_CAPSLOCK, + + KBD_MOD__MAX +}; + +typedef struct KbdState KbdState; + +bool kbd_state_modifier_get(KbdState *kbd, KbdModifier mod); +bool kbd_state_key_get(KbdState *kbd, QKeyCode qcode); +void kbd_state_key_event(KbdState *kbd, QKeyCode qcode, bool down); +void kbd_state_lift_all_keys(KbdState *kbd); +KbdState *kbd_state_init(QemuConsole *con); diff --git a/ui/kbd-state.c b/ui/kbd-state.c new file mode 100644 index 0000000000..7a9fe268c2 --- /dev/null +++ b/ui/kbd-state.c @@ -0,0 +1,119 @@ +#include "qemu/osdep.h" +#include "qemu/bitmap.h" +#include "qemu/queue.h" +#include "qapi-types.h" +#include "ui/console.h" +#include "ui/input.h" +#include "ui/kbd-state.h" + +typedef struct KbdHotkey KbdHotkey; + +struct KbdHotkey { + uint32_t id; + QKeyCode qcode; + DECLARE_BITMAP(mods, KBD_MOD__MAX); + QTAILQ_ENTRY(KbdHotkey) next; +}; + +struct KbdState { + QemuConsole *con; + DECLARE_BITMAP(keys, Q_KEY_CODE__MAX); + DECLARE_BITMAP(mods, KBD_MOD__MAX); + QTAILQ_HEAD(,KbdHotkey) hotkeys; +}; + +static void kbd_state_modifier_update(KbdState *kbd, + QKeyCode qcode1, QKeyCode qcode2, + KbdModifier mod) +{ + if (test_bit(qcode1, kbd->keys) || test_bit(qcode2, kbd->keys)) { + set_bit(mod, kbd->mods); + } else { + clear_bit(mod, kbd->mods); + } +} + +bool kbd_state_modifier_get(KbdState *kbd, KbdModifier mod) +{ + return test_bit(mod, kbd->mods); +} + +bool kbd_state_key_get(KbdState *kbd, QKeyCode qcode) +{ + return test_bit(qcode, kbd->keys); +} + +void kbd_state_key_event(KbdState *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: + kbd_state_modifier_update(kbd, Q_KEY_CODE_SHIFT, Q_KEY_CODE_SHIFT_= R, + KBD_MOD_SHIFT); + break; + case Q_KEY_CODE_CTRL: + case Q_KEY_CODE_CTRL_R: + kbd_state_modifier_update(kbd, Q_KEY_CODE_CTRL, Q_KEY_CODE_CTRL_R, + KBD_MOD_CTRL); + break; + case Q_KEY_CODE_ALT: + kbd_state_modifier_update(kbd, Q_KEY_CODE_ALT, Q_KEY_CODE_ALT, + KBD_MOD_ALT); + break; + case Q_KEY_CODE_CAPS_LOCK: + if (down) { + change_bit(KBD_MOD_CAPSLOCK, kbd->mods); + } + break; + case Q_KEY_CODE_NUM_LOCK: + if (down) { + change_bit(KBD_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); + } +} + +void kbd_state_lift_all_keys(KbdState *kbd) +{ + int qcode; + + for (qcode =3D 0; qcode < Q_KEY_CODE__MAX; qcode++) { + if (test_bit(qcode, kbd->keys)) { + kbd_state_key_event(kbd, qcode, false); + } + } +} + +KbdState *kbd_state_init(QemuConsole *con) +{ + KbdState *kbd =3D g_new0(KbdState, 1); + + kbd->con =3D con; + QTAILQ_INIT(&kbd->hotkeys); + + return kbd; +} diff --git a/ui/Makefile.objs b/ui/Makefile.objs index ced7d91a63..aa81ce4c47 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_SDL) +=3D sdl.mo --=20 2.9.3