All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH qemu] ui/sdl2: add grab-on-tablet option for absolute input devices
@ 2026-06-05  9:53 ~rongyichang
  2026-06-05 16:47 ` BALATON Zoltan
  0 siblings, 1 reply; 4+ messages in thread
From: ~rongyichang @ 2026-06-05  9:53 UTC (permalink / raw)
  To: qemu-devel; +Cc: marcandre.lureau, armbru, eblake

From: rongyichang <rongyichang@xiaomi.com>

When using absolute coordinate input devices (e.g. virtio-tablet-device),
the SDL display backend implements a "soft grab" where the mouse is
automatically grabbed when it enters the window interior and ungrabbed
when it hits the window edge. This edge-ungrab behavior causes problems
in embedded emulation scenarios:

1. Mouse escapes the SDL window at edges
2. SDL does not deliver BUTTONUP events for the escaped mouse
3. The guest gets stuck in a pressed/touch-down state
4. First click back into the window is silently dropped

This issue is confirmed as a known SDL limitation (SDL issue #5301).

Add a new -display sdl,grab-on-tablet=on option that makes absolute
coordinate devices use the same grab behavior as relative (mouse)
devices: user must click to grab, Ctrl+Alt+G to release, and no
automatic grab on window enter or edge-based ungrab/regrab.

Signed-off-by: Yichang Rong <rongyichang@xiaomi.com>
---
 qapi/ui.json    |  8 +++++++-
 qemu-options.hx |  9 +++++++--
 ui/sdl2.c       | 16 +++++++++++++---
 3 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/qapi/ui.json b/qapi/ui.json
index b2c42a7f57..454d9041bf 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -1477,10 +1477,16 @@
 # @grab-mod: Modifier keys that should be pressed together with the
 #     "G" key to release the mouse grab.
 #
+# @grab-on-tablet: When enabled, the mouse grab is required even for
+#     tablet (absolute) input devices.  This is useful when the guest
+#     OS uses a tablet device but you still want click-to-grab
+#     semantics (e.g. NuttX touchscreen emulation).
+#
 # Since: 7.1
 ##
 { 'struct'  : 'DisplaySDL',
-  'data'    : { '*grab-mod'   : 'HotKeyMod' } }
+  'data'    : { '*grab-mod'   : 'HotKeyMod',
+                '*grab-on-tablet' : 'bool' } }
 
 ##
 # @DisplayType:
diff --git a/qemu-options.hx b/qemu-options.hx
index 96ae41f787..1e1836312c 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2205,8 +2205,8 @@ DEF("display", HAS_ARG, QEMU_OPTION_display,
     "-display spice-app[,gl=on|off]\n"
 #endif
 #if defined(CONFIG_SDL)
-    "-display sdl[,gl=on|core|es|off][,grab-mod=<mod>][,show-cursor=on|off]\n"
-    "            [,window-close=on|off]\n"
+    "-display sdl[,gl=on|core|es|off][,grab-mod=<mod>][,grab-on-tablet=on|off]\n"
+    "            [,show-cursor=on|off][,window-close=on|off]\n"
 #endif
 #if defined(CONFIG_GTK)
     "-display gtk[,clipboard=on|off][,full-screen=on|off][,gl=on|off]\n"
@@ -2284,6 +2284,11 @@ SRST
         the mouse grabbing in conjunction with the "g" key. ``<mods>`` can be
         either ``lshift-lctrl-lalt`` or ``rctrl``.
 
+        ``grab-on-tablet=on|off`` : When enabled, the mouse grab is required
+        even for tablet (absolute) input devices.  This is useful when the
+        guest OS uses a tablet device but you still want click-to-grab
+        semantics.
+
         ``gl=on|off|core|es`` : Use OpenGL for displaying
 
         ``show-cursor=on|off`` :  Force showing the mouse cursor
diff --git a/ui/sdl2.c b/ui/sdl2.c
index 4fcdbd79d3..af94ae8500 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -46,6 +46,7 @@ static SDL_Surface *guest_sprite_surface;
 static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
 static bool alt_grab;
 static bool ctrl_grab;
+static bool grab_on_tablet;
 
 static int gui_saved_grab;
 static int gui_fullscreen;
@@ -504,7 +505,8 @@ static void handle_mousemotion(SDL_Event *ev)
     }
 
     SDL_GetWindowSize(scon->real_window, &scr_w, &scr_h);
-    if (qemu_input_is_absolute(scon->dcl.con) || absolute_enabled) {
+    if ((qemu_input_is_absolute(scon->dcl.con) || absolute_enabled) &&
+        !grab_on_tablet) {
         max_x = scr_w - 1;
         max_y = scr_h - 1;
         if (gui_grab && !gui_fullscreen
@@ -545,7 +547,8 @@ static void handle_mousebutton(SDL_Event *ev)
     x = (int64_t)bev->x * surface_width(scon->surface) / scr_w;
     y = (int64_t)bev->y * surface_height(scon->surface) / scr_h;
 
-    if (!gui_grab && !qemu_input_is_absolute(scon->dcl.con)) {
+    if (!gui_grab &&
+        (!qemu_input_is_absolute(scon->dcl.con) || grab_on_tablet)) {
         if (ev->type == SDL_MOUSEBUTTONUP && bev->button == SDL_BUTTON_LEFT) {
             /* start grabbing all events */
             sdl_grab_start(scon);
@@ -614,7 +617,10 @@ static void handle_windowevent(SDL_Event *ev)
     case SDL_WINDOWEVENT_FOCUS_GAINED:
         /* fall through */
     case SDL_WINDOWEVENT_ENTER:
-        if (!gui_grab && (qemu_input_is_absolute(scon->dcl.con) || absolute_enabled)) {
+        if (!gui_grab &&
+            (qemu_input_is_absolute(scon->dcl.con) ||
+             absolute_enabled) &&
+            !grab_on_tablet) {
             absolute_mouse_grab(scon);
         }
         /* If a new console window opened using a hotkey receives the
@@ -921,6 +927,10 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o)
         }
     }
 
+    if (o->u.sdl.has_grab_on_tablet) {
+        grab_on_tablet = o->u.sdl.grab_on_tablet;
+    }
+
     for (i = 0;; i++) {
         QemuConsole *con = qemu_console_lookup_by_index(i);
         if (!con) {
-- 
2.49.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-06-18 12:56 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-05  9:53 [PATCH qemu] ui/sdl2: add grab-on-tablet option for absolute input devices ~rongyichang
2026-06-05 16:47 ` BALATON Zoltan
2026-06-06  3:01   ` 答复: [External Mail]Re: " 荣义昌 via qemu development
2026-06-18 12:56     ` BALATON Zoltan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.