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 1535057426197523.0932249318828; Thu, 23 Aug 2018 13:50:26 -0700 (PDT) Received: from localhost ([::1]:38725 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fswYf-0007ej-9k for importer@patchew.org; Thu, 23 Aug 2018 16:50:21 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35096) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fswXn-00072T-Dn for qemu-devel@nongnu.org; Thu, 23 Aug 2018 16:49:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fswXh-0002ab-Pg for qemu-devel@nongnu.org; Thu, 23 Aug 2018 16:49:27 -0400 Received: from mail-40136.protonmail.ch ([185.70.40.136]:52049) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fswXh-0002Ym-6L for qemu-devel@nongnu.org; Thu, 23 Aug 2018 16:49:21 -0400 Date: Thu, 23 Aug 2018 20:49:05 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=default; t=1535057352; bh=NN1fSz/Gn+s/wPioEM1fsNhuv0wQ68ieAsYj95ZMh4k=; h=Date:To:From:Reply-To:Subject:Feedback-ID:From; b=S7x0mwyv/Ph+qlX8dFa2iAfsVv87rjc2m4RCFCijWqmjffKmK7NZ0QzDhkO5tSGxW fQaCp87uBBpl45Dttor6gZszID6eO7ujJOva4tILEDOCXvLn7vo2/fBkN7FM0e7Kv3 HdEhX0VXXPHZ4OTErB17O4uu+9zUhuu++9pFgqWA= To: "qemu-devel@nongnu.org" , "kraxel@redhat.com" Message-ID: 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 v2 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 commas, 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. Sending once again as v2 as I forgot to sign off the last one. Signed-off-by: Ryan El Kochta --- 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