From nobody Wed Nov 5 12:59:48 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; dkim=fail; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 153505727719525.297460135817005; Thu, 23 Aug 2018 13:47:57 -0700 (PDT) Received: from localhost ([::1]:38716 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fswWJ-0006am-HN for importer@patchew.org; Thu, 23 Aug 2018 16:47:55 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33471) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fswVA-00066P-Gh for qemu-devel@nongnu.org; Thu, 23 Aug 2018 16:46:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fswV1-00011s-Gp for qemu-devel@nongnu.org; Thu, 23 Aug 2018 16:46:40 -0400 Received: from mail-40136.protonmail.ch ([185.70.40.136]:43442) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fswV0-0000zm-UL for qemu-devel@nongnu.org; Thu, 23 Aug 2018 16:46:35 -0400 Date: Thu, 23 Aug 2018 20:46:22 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=default; t=1535057189; bh=/b9OJzoDCQM+RpsCpwhpSyT6mck5T6l/9RbSN2pmxWI=; h=Date:To:From:Reply-To:Subject:Feedback-ID:From; b=wridi65VslNv9OvBFQVsc3LTcDowLhQ13ukW2OnjTi6XjpWSjlbzTzy5aDBlN8b9z yf2lfU7QjYQWpOjEA+RJM67Mck8JNKIaQY4FrezZEyaWQ/vL25hWCeijDEFneuy8P8 2uYajyhSeevbeGPx4n/1HvVFm/aW07yoU6+tBFZA= To: "qemu-devel@nongnu.org" , "kraxel@redhat.com" Message-ID: <8f7eYzw9BgwUeH_z45Rgcwu8DVy8fSamlQ-f-VsR2pj9TgnAJBMrCoZjxzT6XN5XojiHMMEbOOgy-gHU0KuLiSD7YerZJPI8TZYaBdhCCIs=@protonmail.com> Feedback-ID: bQ1YSMeFIHAUAn-uQLnVQcD6sUw_KdWbXPbLTy5DSY-qJoKk-ALPWbW_iVWAtXYm4PkoUPhIOhNDcF8xb3qjMA==:Ext:ProtonMail MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 185.70.40.136 Content-Transfer-Encoding: quoted-printable X-Content-Filtered-By: Mailman/MimeDel 2.1.21 Subject: [Qemu-devel] [PATCH] input-linux: customizable toggle keys 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: , From: Ryan El Kochta via Qemu-devel Reply-To: Ryan El Kochta Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" This patch introduces a new string option to the input-linux commandline: toggle_keys=3D[num]:[num]:[num] ... Separated by colons, toggle_keys allows the user to specify the key IDs of all the keys desired for switching between the guest and host. These key IDs can be found in: include/standard-headers/linux/input-event-codes.h and are prefixed with KEY_. If the option is malformed or not specified, it will use the current default of KEY_LEFTCTRL + KEY_RIGHTCTRL. --- ui/input-linux.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 134 insertions(+), 2 deletions(-) diff --git a/ui/input-linux.c b/ui/input-linux.c index 9720333b2c..38878f0836 100644 --- a/ui/input-linux.c +++ b/ui/input-linux.c @@ -12,6 +12,7 @@ #include "sysemu/sysemu.h" #include "ui/input.h" #include "qom/object_interfaces.h" +#include "include/qemu/cutils.h" #include #include "standard-headers/linux/input.h" @@ -63,6 +64,10 @@ struct InputLinux { struct input_event event; int read_offset; + char *toggle_keys; + int toggle_keys_len; + int *toggle_keys_list; + QTAILQ_ENTRY(InputLinux) next; }; @@ -98,6 +103,16 @@ static void input_linux_toggle_grab(InputLinux *il) } } +static bool input_linux_check_toggle_keys(InputLinux *il) +{ + for (unsigned i =3D 0; i < il->toggle_keys_len; i++) { + if (!il->keydown[il->toggle_keys_list[i]]) { + return false; + } + } + return true; +} + static void input_linux_handle_keyboard(InputLinux *il, struct input_event *event) { @@ -134,8 +149,7 @@ static void input_linux_handle_keyboard(InputLinux *il, } /* hotkey -> record switch request ... */ - if (il->keydown[KEY_LEFTCTRL] && - il->keydown[KEY_RIGHTCTRL]) { + if (input_linux_check_toggle_keys(il)) { il->grab_request =3D true; } @@ -274,6 +288,18 @@ static void input_linux_complete(UserCreatable *uc, Er= ror **errp) return; } + /* + * If the toggle_keys char was not provided, set + * the default of KEY_LEFTCTRL and KEY_RIGHTCTRL + */ + if (!il->toggle_keys || !il->toggle_keys_list || !il->toggle_keys_len)= { + il->toggle_keys =3D NULL; + il->toggle_keys_len =3D 2; + il->toggle_keys_list =3D g_new(int, 2); + il->toggle_keys_list[0] =3D KEY_LEFTCTRL; + il->toggle_keys_list[1] =3D KEY_RIGHTCTRL; + } + il->fd =3D open(il->evdev, O_RDWR); if (il->fd < 0) { error_setg_file_open(errp, errno, il->evdev); @@ -359,6 +385,11 @@ static void input_linux_instance_finalize(Object *obj) close(il->fd); } g_free(il->evdev); + + if (il->toggle_keys) { + g_free(il->toggle_keys); + } + g_free(il->toggle_keys_list); } static char *input_linux_get_evdev(Object *obj, Error **errp) @@ -410,11 +441,112 @@ static void input_linux_set_repeat(Object *obj, bool= value, il->repeat =3D value; } +static void input_linux_populate_toggle_keys(InputLinux *il) +{ + /* + * If no toggle_keys was provided, return zero keys. + * This will be cleaned up in the input_linux_complete() + * function and reset to both Ctrl keys. + */ + if (!il->toggle_keys) { + il->toggle_keys_len =3D 0; + il->toggle_keys_list =3D NULL; + return; + } + + /* + * Iterate through each token in the toggle_keys string, + * separated by colons, and add it to the il->toggle_keys_list + * array. + * + * Unfortunately this must be done twice in order to + * determine how much memory will be allocated later on. + */ + + /* First scan */ + il->toggle_keys_len =3D 0; + + char *orig, *token, *saveptr; + + orig =3D g_strdup(il->toggle_keys); + saveptr =3D orig; + + while (strtok_r(saveptr, ":", &saveptr)) { + il->toggle_keys_len++; + } + + /* + * If the count found zero tokens, return an empty list. + * Again, this will be cleaned up in input_linux_complete(). + */ + if (!il->toggle_keys_len) { + il->toggle_keys_list =3D NULL; + g_free(orig); + return; + } + + /* Second scan */ + il->toggle_keys_list =3D g_new(int, il->toggle_keys_len); + + strcpy(orig, il->toggle_keys); + saveptr =3D orig; + unsigned cntr =3D 0; + + /* Add each token's int representation to the list */ + while ((token =3D strtok_r(saveptr, ":", &saveptr))) { + long val =3D 0; + int strtol_ret =3D qemu_strtol(token, NULL, 10, &val); + + /* + * Check to ensure (a) qemu_strtol() did not fail + * and (b) the integer it returned is within the + * range of possible keys + */ + if (strtol_ret > 0 || !(val > 0 && val < KEY_CNT)) { + g_free(il->toggle_keys_list); + g_free(orig); + il->toggle_keys_len =3D 0; + il->toggle_keys_list =3D NULL; + return; + } + + il->toggle_keys_list[cntr] =3D val; + cntr++; + } + + g_free(orig); +} + +static void input_linux_set_toggle_keys(Object *obj, const char *value, + Error **errp) +{ + InputLinux *il =3D INPUT_LINUX(obj); + + if (il->toggle_keys) { + error_setg(errp, "toggle_keys property already set"); + return; + } + + il->toggle_keys =3D g_strdup(value); + + input_linux_populate_toggle_keys(il); +} + +static char *input_linux_get_toggle_keys(Object *obj, Error **errp) +{ + InputLinux *il =3D INPUT_LINUX(obj); + + return g_strdup(il->toggle_keys); +} + static void input_linux_instance_init(Object *obj) { object_property_add_str(obj, "evdev", input_linux_get_evdev, input_linux_set_evdev, NULL); + object_property_add_str(obj, "toggle_keys", + input_linux_get_toggle_keys, + input_linux_set_toggle_keys, NULL); object_property_add_bool(obj, "grab_all", input_linux_get_grab_all, input_linux_set_grab_all, NULL); -- 2.18.0