qapi/qom.json | 14 +++++++++++++- ui/input-linux.c | 27 +++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-)
Some workflows start a guest in the background and do not want evdev
devices to be grabbed immediately. In that case, the current behavior
is annoying because the host loses control of the keyboard or mouse
before the user actually wants to interact with the guest.
Add a new boolean input-linux property, grab-on-startup. When true,
the device is grabbed during initialization, which keeps the existing
behavior. When false, the device remains ungrabbed until the toggle
key combination is entered.
Also make sure startup grabbing is skipped entirely when
grab-on-startup is false, even if keys are already pressed during
device initialization. Without this, QEMU could still perform a delayed
grab once those keys are released.
This revives an earlier patch originally posted by Justinien Bouron and
incorporates the follow-up review feedback.
Link:https://patchew.org/QEMU/20240403055002.890760-1-justinien.bouron@gmail.com/
Link:https://lists.gnu.org/archive/html/qemu-devel/2024-03/msg04004.html
Signed-off-by: Maximilian Senftleben YOUR NAME <YOUR EMAIL>
---
This revives Justinien Bouron's earlier input-linux grab-on-startup
patch:
https://patchew.org/QEMU/20240403055002.890760-1-justinien.bouron@gmail.com/
Last known review state:
- Marc-Andre Lureau asked for a resend with an updated commit message:
https://lists.gnu.org/archive/html/qemu-devel/2024-03/msg04003.html
- Markus Armbruster reviewed the QAPI schema and pointed out that the
delayed-grab path still needed to be skipped when keys are already
pressed at startup and grab-on-startup is false:
https://lists.gnu.org/archive/html/qemu-devel/2024-03/msg04004.html
- Daniel P. Berrange asked for a clearer motivation for the feature:
https://lists.gnu.org/archive/html/qemu-devel/2024-03/msg01969.html
Changes since v3:
- Skip startup grabbing entirely when grab-on-startup is false, even if
keys are already pressed during initialization
- Refresh the commit message to clarify the motivation for the option
- Keep the QAPI documentation formatting requested in prior review and
update the since tag for the current development cycle
qapi/qom.json | 14 +++++++++++++-
ui/input-linux.c | 27 +++++++++++++++++++++++++++
2 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/qapi/qom.json b/qapi/qom.json
index dd45ac1087..e3eda5c1ec 100644
--- a/qapi/qom.json
+++ b/qapi/qom.json
@@ -558,13 +558,25 @@
# @grab-toggle: the key or key combination that toggles device grab
# (default: ctrl-ctrl)
#
+# @grab-on-startup: if true, grab the device immediately upon starting
+# the guest. Otherwise, don't grab the device until the
+# combination is entered. This does not influence other devices
+# even if grab_all is true, i.e. in the unlikely scenario where
+# device1 has grab_all=true + grab-on-startup=true and device2 has
+# grab-on-startup=false, only device1 is grabbed on startup, then,
+# once the grab combination is entered, grabbing is toggled off
+# for both devices (because device1 enforces the grab_all
+# property) until the combination is entered again at which point
+# both devices will be grabbed. (default: true) (since 11.1).
+#
# Since: 2.6
##
{ 'struct': 'InputLinuxProperties',
'data': { 'evdev': 'str',
'*grab_all': 'bool',
'*repeat': 'bool',
- '*grab-toggle': 'GrabToggleKeys' },
+ '*grab-toggle': 'GrabToggleKeys',
+ '*grab-on-startup': 'bool' },
'if': 'CONFIG_LINUX' }
##
diff --git a/ui/input-linux.c b/ui/input-linux.c
index f4eee1ffd7..767374e99a 100644
--- a/ui/input-linux.c
+++ b/ui/input-linux.c
@@ -43,6 +43,7 @@ struct InputLinux {
bool grab_request;
bool grab_active;
bool grab_all;
+ bool grab_on_startup;
bool keydown[KEY_CNT];
int keycount;
int wheel;
@@ -394,12 +395,17 @@ static void input_linux_complete(UserCreatable *uc, Error **errp)
}
qemu_set_fd_handler(il->fd, input_linux_event, NULL, il);
+ if (!il->grab_on_startup) {
+ goto skip_grab;
+ }
if (il->keycount) {
/* delay grab until all keys are released */
il->grab_request = true;
} else {
input_linux_toggle_grab(il);
}
+
+skip_grab:
QTAILQ_INSERT_TAIL(&inputs, il, next);
il->initialized = true;
return;
@@ -487,6 +493,21 @@ static void input_linux_set_grab_toggle(Object *obj, int value,
il->grab_toggle = value;
}
+static bool input_linux_get_grab_on_startup(Object *obj, Error **errp)
+{
+ InputLinux *il = INPUT_LINUX(obj);
+
+ return il->grab_on_startup;
+}
+
+static void input_linux_set_grab_on_startup(Object *obj, bool value,
+ Error **errp)
+{
+ InputLinux *il = INPUT_LINUX(obj);
+
+ il->grab_on_startup = value;
+}
+
static void input_linux_instance_init(Object *obj)
{
}
@@ -494,6 +515,7 @@ static void input_linux_instance_init(Object *obj)
static void input_linux_class_init(ObjectClass *oc, const void *data)
{
UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
+ ObjectProperty *grab_on_startup_prop;
ucc->complete = input_linux_complete;
@@ -510,6 +532,11 @@ static void input_linux_class_init(ObjectClass *oc, const void *data)
&GrabToggleKeys_lookup,
input_linux_get_grab_toggle,
input_linux_set_grab_toggle);
+ grab_on_startup_prop = object_class_property_add_bool(
+ oc, "grab-on-startup",
+ input_linux_get_grab_on_startup,
+ input_linux_set_grab_on_startup);
+ object_property_set_default_bool(grab_on_startup_prop, true);
}
static const TypeInfo input_linux_info = {
-- 2.53.0
© 2016 - 2026 Red Hat, Inc.