From patchwork Thu Aug 23 20:49:05 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Denis V. Lunev\" via" X-Patchwork-Id: 10574545 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8853B1390 for ; Thu, 23 Aug 2018 20:50:07 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7B8412C7A9 for ; Thu, 23 Aug 2018 20:50:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6F3712C7AE; Thu, 23 Aug 2018 20:50:07 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id D80CC2C7C1 for ; Thu, 23 Aug 2018 20:50:06 +0000 (UTC) Received: from localhost ([::1]:38725 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fswYQ-0007ej-97 for patchwork-qemu-devel@patchwork.kernel.org; Thu, 23 Aug 2018 16:50:06 -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 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: , X-Patchwork-Original-From: Ryan El Kochta via Qemu-devel From: "Denis V. Lunev\" via" Reply-To: Ryan El Kochta Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP This patch introduces a new string option to the input-linux commandline: toggle_keys=[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(-) -- 2.18.0 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 = 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 = true; } @@ -274,6 +288,18 @@ static void input_linux_complete(UserCreatable *uc, Error **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 = NULL; + il->toggle_keys_len = 2; + il->toggle_keys_list = g_new(int, 2); + il->toggle_keys_list[0] = KEY_LEFTCTRL; + il->toggle_keys_list[1] = KEY_RIGHTCTRL; + } + il->fd = 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 = 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 = 0; + il->toggle_keys_list = 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 = 0; + + char *orig, *token, *saveptr; + + orig = g_strdup(il->toggle_keys); + saveptr = 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 = NULL; + g_free(orig); + return; + } + + /* Second scan */ + il->toggle_keys_list = g_new(int, il->toggle_keys_len); + + strcpy(orig, il->toggle_keys); + saveptr = orig; + unsigned cntr = 0; + + /* Add each token's int representation to the list */ + while ((token = strtok_r(saveptr, ":", &saveptr))) { + long val = 0; + int strtol_ret = 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 = 0; + il->toggle_keys_list = NULL; + return; + } + + il->toggle_keys_list[cntr] = val; + cntr++; + } + + g_free(orig); +} + +static void input_linux_set_toggle_keys(Object *obj, const char *value, + Error **errp) +{ + InputLinux *il = INPUT_LINUX(obj); + + if (il->toggle_keys) { + error_setg(errp, "toggle_keys property already set"); + return; + } + + il->toggle_keys = g_strdup(value); + + input_linux_populate_toggle_keys(il); +} + +static char *input_linux_get_toggle_keys(Object *obj, Error **errp) +{ + InputLinux *il = 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);