From: Maximilian Senftleben <[email protected]> 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/[email protected]/ Link: https://lists.gnu.org/archive/html/qemu-devel/2024-03/msg04004.html Signed-off-by: Maximilian Senftleben <[email protected]> --- This revives Justinien Bouron's earlier input-linux grab-on-startup patch: https://patchew.org/QEMU/[email protected]/ 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 v5: - Fixed patch email line breaks 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 d96cc5aa21..2e15af8259 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
