All of lore.kernel.org
 help / color / mirror / Atom feed
* [GIT PULL 00/27] UI patches for 2026-06-17
@ 2026-06-17 15:22 Marc-André Lureau
  2026-06-17 15:22 ` [GIT PULL 01/27] hmp-commands.hx: fix button_state doc Marc-André Lureau
                   ` (27 more replies)
  0 siblings, 28 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

The following changes since commit b0df6e2f2c6c45df8d4d286933799c623e124d98:

  Merge tag 'pull-riscv-to-apply-20260616' of https://github.com/alistair23/qemu into staging (2026-06-16 10:41:47 -0400)

are available in the Git repository at:

  https://gitlab.com/marcandre.lureau/qemu.git tags/ui-input-pr-v1

for you to fetch changes up to 490a3e1867f025c68fa13db766b5c8da16c6eca4:

  ui/sdl2: Set GL ES profile before creating initial GL context (2026-06-17 19:22:50 +0400)

----------------------------------------------------------------
UI patches for 2026-06-17

- retire input-legacy.c
- sdl2 fixes

To: qemu-devel@nongnu.org
Cc: Stefan Hajnoczi <stefanha@redhat.com>

----------------------------------------------------------------
Akihiko Odaki (1):
      ui/sdl2: Explicitly specify EGL platform

Marc-André Lureau (23):
      hmp-commands.hx: fix button_state doc
      ui/hmp: move index_from_key() where it is used
      hw/i386/vmmouse: convert to QemuInputHandler API
      hw/usb/dev-wacom: convert to modern QemuInputHandler API
      ui: move LED and key utilities to input.c, delete input-legacy.c
      hw/input: replace fprint with LOG_GUEST_ERROR
      ui/input: remove double-notification on qemu_mouse_set()
      ui/input: remove dead declaration
      ui/input: add LED state tracking to QemuInputHandlerState
      hw/input/ps2: keep QemuInputHandlerState in PS2State
      hw/arm: keep QemuInputHandlerState in musicpal
      hw/input: keep QemuInputHandlerState in adb-kbd
      hw/input: keep QemuInputHandlerState in stellaris
      hw/m68k: keep QemuInputHandlerState in next-kbd
      ui/input: qemu_input_handler_register to warn for unused result
      hw/input/ps2: use qemu_input_handler_set_leds_mask() for LED state
      hw/input/hid: use qemu_input_handler_set_leds_mask() for LED state
      hw/input/virtio-input-hid: use qemu_input_handler_set_leds_mask() for LED state
      ui/vnc: switch LED handling to Notifier-based input API
      ui/spice: switch LED handling to Notifier-based input API
      ui/dbus: switch LED handling to Notifier-based input API
      ui/input: remove old LED handler broadcast queue
      ui/pixman: fix zero rowstride in qemu_pixman_image_new_shareable()

Philippe Mathieu-Daudé (2):
      tools/qemu-vnc: Have console_get_mouse/keyboard take const QemuConsole
      ui/input: Have qemu_input_is_absolute() take a const QemuConsole

Ryan Zhang (1):
      ui/sdl2: Set GL ES profile before creating initial GL context

 include/hw/input/ps2.h               |   2 +
 include/hw/input/stellaris_gamepad.h |   2 +
 include/ui/console.h                 |  30 -----
 include/ui/egl-helpers.h             |   5 +
 include/ui/input.h                   |  15 ++-
 include/ui/pixman-minimal.h          |  25 +---
 include/ui/qemu-pixman-helpers.h     |  49 ++++++++
 include/ui/qemu-pixman.h             |   1 +
 tools/qemu-vnc/qemu-vnc.h            |   4 +-
 ui/vnc.h                             |   2 +-
 hw/arm/musicpal.c                    |  13 +-
 hw/i386/vmmouse.c                    | 115 ++++++++++++-----
 hw/input/adb-kbd.c                   |  17 ++-
 hw/input/hid.c                       |   3 +-
 hw/input/ps2.c                       |  28 ++++-
 hw/input/stellaris_gamepad.c         |  12 +-
 hw/input/virtio-input-hid.c          |  15 ++-
 hw/m68k/next-kbd.c                   |  11 +-
 hw/usb/dev-wacom.c                   | 155 ++++++++++++++---------
 tools/qemu-vnc/display.c             |   4 +-
 tools/qemu-vnc/input.c               |  51 +++-----
 ui/dbus-console.c                    |  14 ++-
 ui/egl-helpers.c                     |   4 +-
 ui/input-legacy.c                    | 236 -----------------------------------
 ui/input.c                           |  80 ++++++++++--
 ui/qemu-pixman.c                     |   8 +-
 ui/sdl2.c                            |   5 +-
 ui/spice-input.c                     |  16 ++-
 ui/ui-hmp-cmds.c                     |  22 +++-
 ui/vnc.c                             |  11 +-
 hmp-commands.hx                      |   4 +-
 hw/i386/trace-events                 |   2 +-
 ui/meson.build                       |   1 -
 33 files changed, 495 insertions(+), 467 deletions(-)
 create mode 100644 include/ui/qemu-pixman-helpers.h
 delete mode 100644 ui/input-legacy.c



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

* [GIT PULL 01/27] hmp-commands.hx: fix button_state doc
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
@ 2026-06-17 15:22 ` Marc-André Lureau
  2026-06-17 15:22 ` [GIT PULL 02/27] ui/hmp: move index_from_key() where it is used Marc-André Lureau
                   ` (26 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

Right & middle buttons are inverted (see hmp_mouse_button)

Acked-by: Dr. David Alan Gilbert <dave@treblig.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hmp-commands.hx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 0d780e6da30..7ae2468a3d9 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -752,13 +752,13 @@ ERST
         .name       = "mouse_button",
         .args_type  = "button_state:i",
         .params     = "state",
-        .help       = "change mouse button state (1=L, 2=M, 4=R)",
+        .help       = "change mouse button state (1=L, 2=R, 4=M)",
         .cmd        = hmp_mouse_button,
     },
 
 SRST
 ``mouse_button`` *val*
-  Change the active mouse button state *val* (1=L, 2=M, 4=R).
+  Change the active mouse button state *val* (1=L, 2=R, 4=M).
 ERST
 
     {

-- 
2.54.0



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

* [GIT PULL 02/27] ui/hmp: move index_from_key() where it is used
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
  2026-06-17 15:22 ` [GIT PULL 01/27] hmp-commands.hx: fix button_state doc Marc-André Lureau
@ 2026-06-17 15:22 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 03/27] hw/i386/vmmouse: convert to QemuInputHandler API Marc-André Lureau
                   ` (25 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/ui/console.h |  3 ---
 ui/input-legacy.c    | 15 ---------------
 ui/ui-hmp-cmds.c     | 15 +++++++++++++++
 3 files changed, 15 insertions(+), 18 deletions(-)

diff --git a/include/ui/console.h b/include/ui/console.h
index a31c5a4995c..3cb78989cd2 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -450,9 +450,6 @@ bool vnc_display_reload_certs(const char *id,  Error **errp);
 bool vnc_display_update(DisplayUpdateOptionsVNC *arg, Error **errp);
 void vnc_cleanup(void);
 
-/* input.c */
-int index_from_key(const char *key, size_t key_length);
-
 #ifdef CONFIG_LINUX
 /* udmabuf.c */
 int udmabuf_fd(void);
diff --git a/ui/input-legacy.c b/ui/input-legacy.c
index 193c9ae2ef9..71b17a3cfc7 100644
--- a/ui/input-legacy.c
+++ b/ui/input-legacy.c
@@ -56,21 +56,6 @@ struct QEMUPutLEDEntry {
 static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers =
     QTAILQ_HEAD_INITIALIZER(led_handlers);
 
-int index_from_key(const char *key, size_t key_length)
-{
-    int i;
-
-    for (i = 0; i < Q_KEY_CODE__MAX; i++) {
-        if (!strncmp(key, QKeyCode_str(i), key_length) &&
-            !QKeyCode_str(i)[key_length]) {
-            break;
-        }
-    }
-
-    /* Return Q_KEY_CODE__MAX if the key is invalid */
-    return i;
-}
-
 void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time,
                   Error **errp)
 {
diff --git a/ui/ui-hmp-cmds.c b/ui/ui-hmp-cmds.c
index 1e9bc77bd80..76f5181de43 100644
--- a/ui/ui-hmp-cmds.c
+++ b/ui/ui-hmp-cmds.c
@@ -350,6 +350,21 @@ void hmp_change_vnc(Monitor *mon, const char *device, const char *target,
 }
 #endif
 
+static int index_from_key(const char *key, size_t key_length)
+{
+    int i;
+
+    for (i = 0; i < Q_KEY_CODE__MAX; i++) {
+        if (!strncmp(key, QKeyCode_str(i), key_length) &&
+            !QKeyCode_str(i)[key_length]) {
+            break;
+        }
+    }
+
+    /* Return Q_KEY_CODE__MAX if the key is invalid */
+    return i;
+}
+
 void hmp_sendkey(Monitor *mon, const QDict *qdict)
 {
     const char *keys = qdict_get_str(qdict, "keys");

-- 
2.54.0



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

* [GIT PULL 03/27] hw/i386/vmmouse: convert to QemuInputHandler API
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
  2026-06-17 15:22 ` [GIT PULL 01/27] hmp-commands.hx: fix button_state doc Marc-André Lureau
  2026-06-17 15:22 ` [GIT PULL 02/27] ui/hmp: move index_from_key() where it is used Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 04/27] hw/usb/dev-wacom: convert to modern " Marc-André Lureau
                   ` (24 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

Replace the legacy QEMUPutMouseEvent callback with a proper
QemuInputHandler registration. This eliminates one of the two
remaining users of the legacy input adapter in ui/input-legacy.c.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/i386/vmmouse.c    | 115 +++++++++++++++++++++++++++++++++++++--------------
 hw/i386/trace-events |   2 +-
 2 files changed, 85 insertions(+), 32 deletions(-)

diff --git a/hw/i386/vmmouse.c b/hw/i386/vmmouse.c
index d54adb34a88..e289bce8e2e 100644
--- a/hw/i386/vmmouse.c
+++ b/hw/i386/vmmouse.c
@@ -68,7 +68,10 @@ struct VMMouseState {
     uint16_t nb_queue;
     uint16_t status;
     uint8_t absolute;
-    QEMUPutMouseEntry *entry;
+    QemuInputHandlerState *hs;
+    int axis[INPUT_AXIS__MAX];
+    int dz;
+    bool btns[INPUT_BUTTON__MAX];
     ISAKBDState *i8042;
 };
 
@@ -99,39 +102,78 @@ static uint32_t vmmouse_get_status(VMMouseState *s)
     return (s->status << 16) | s->nb_queue;
 }
 
-static void vmmouse_mouse_event(void *opaque, int x, int y, int dz, int buttons_state)
+static void vmmouse_input_event(DeviceState *dev, QemuConsole *src,
+                                QemuInputEvent *evt)
 {
-    VMMouseState *s = opaque;
+    VMMouseState *s = VMMOUSE(dev);
+
+    switch (evt->type) {
+    case INPUT_EVENT_KIND_BTN:
+        if (evt->btn.down) {
+            if (evt->btn.button == INPUT_BUTTON_WHEEL_UP) {
+                s->dz--;
+            } else if (evt->btn.button == INPUT_BUTTON_WHEEL_DOWN) {
+                s->dz++;
+            }
+        }
+        s->btns[evt->btn.button] = evt->btn.down;
+        break;
+    case INPUT_EVENT_KIND_ABS:
+        if (evt->abs.axis == INPUT_AXIS_X) {
+            s->axis[INPUT_AXIS_X] =
+                qemu_input_scale_axis(evt->abs.value,
+                                      INPUT_EVENT_ABS_MIN, INPUT_EVENT_ABS_MAX,
+                                      VMMOUSE_MIN_X, VMMOUSE_MAX_X);
+        } else if (evt->abs.axis == INPUT_AXIS_Y) {
+            s->axis[INPUT_AXIS_Y] =
+                qemu_input_scale_axis(evt->abs.value,
+                                      INPUT_EVENT_ABS_MIN, INPUT_EVENT_ABS_MAX,
+                                      VMMOUSE_MIN_Y, VMMOUSE_MAX_Y);
+        }
+        break;
+    case INPUT_EVENT_KIND_REL:
+        s->axis[evt->rel.axis] += evt->rel.value;
+        break;
+    default:
+        break;
+    }
+}
+
+static void vmmouse_input_sync(DeviceState *dev)
+{
+    VMMouseState *s = VMMOUSE(dev);
     int buttons = 0;
 
-    if (s->nb_queue > (VMMOUSE_QUEUE_SIZE - 4))
+    if (s->nb_queue > (VMMOUSE_QUEUE_SIZE - 4)) {
         return;
+    }
 
-    trace_vmmouse_mouse_event(x, y, dz, buttons_state);
-
-    if ((buttons_state & MOUSE_EVENT_LBUTTON))
+    if (s->btns[INPUT_BUTTON_LEFT]) {
         buttons |= VMMOUSE_LEFT_BUTTON;
-    if ((buttons_state & MOUSE_EVENT_RBUTTON))
+    }
+    if (s->btns[INPUT_BUTTON_RIGHT]) {
         buttons |= VMMOUSE_RIGHT_BUTTON;
-    if ((buttons_state & MOUSE_EVENT_MBUTTON))
+    }
+    if (s->btns[INPUT_BUTTON_MIDDLE]) {
         buttons |= VMMOUSE_MIDDLE_BUTTON;
-
-    if (s->absolute) {
-        x = qemu_input_scale_axis(x,
-                                  INPUT_EVENT_ABS_MIN, INPUT_EVENT_ABS_MAX,
-                                  VMMOUSE_MIN_X, VMMOUSE_MAX_X);
-        y = qemu_input_scale_axis(y,
-                                  INPUT_EVENT_ABS_MIN, INPUT_EVENT_ABS_MAX,
-                                  VMMOUSE_MIN_Y, VMMOUSE_MAX_Y);
-    } else{
-        /* add for guest vmmouse driver to judge this is a relative packet. */
+    }
+    if (!s->absolute) {
         buttons |= VMMOUSE_RELATIVE_PACKET;
     }
 
+    trace_vmmouse_queue_event(s->axis[INPUT_AXIS_X], s->axis[INPUT_AXIS_Y],
+                              s->dz, buttons);
+
     s->queue[s->nb_queue++] = buttons;
-    s->queue[s->nb_queue++] = x;
-    s->queue[s->nb_queue++] = y;
-    s->queue[s->nb_queue++] = dz;
+    s->queue[s->nb_queue++] = s->axis[INPUT_AXIS_X];
+    s->queue[s->nb_queue++] = s->axis[INPUT_AXIS_Y];
+    s->queue[s->nb_queue++] = s->dz;
+    s->dz = 0;
+
+    if (!s->absolute) {
+        s->axis[INPUT_AXIS_X] = 0;
+        s->axis[INPUT_AXIS_Y] = 0;
+    }
 
     /* need to still generate PS2 events to notify driver to
        read from queue */
@@ -140,14 +182,25 @@ static void vmmouse_mouse_event(void *opaque, int x, int y, int dz, int buttons_
 
 static void vmmouse_remove_handler(VMMouseState *s)
 {
-    if (s->entry) {
-        qemu_remove_mouse_event_handler(s->entry);
-        s->entry = NULL;
-    }
+    g_clear_pointer(&s->hs, qemu_input_handler_unregister);
 }
 
 static void vmmouse_update_handler(VMMouseState *s, int absolute)
 {
+    static const QemuInputHandler vmmouse_abs_handler = {
+        .name  = "vmmouse",
+        .mask  = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_ABS,
+        .event = vmmouse_input_event,
+        .sync  = vmmouse_input_sync,
+    };
+
+    static const QemuInputHandler vmmouse_rel_handler = {
+        .name  = "vmmouse",
+        .mask  = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
+        .event = vmmouse_input_event,
+        .sync  = vmmouse_input_sync,
+    };
+
     if (s->status != 0) {
         return;
     }
@@ -155,11 +208,11 @@ static void vmmouse_update_handler(VMMouseState *s, int absolute)
         s->absolute = absolute;
         vmmouse_remove_handler(s);
     }
-    if (s->entry == NULL) {
-        s->entry = qemu_add_mouse_event_handler(vmmouse_mouse_event,
-                                                s, s->absolute,
-                                                "vmmouse");
-        qemu_activate_mouse_event_handler(s->entry);
+    if (s->hs == NULL) {
+        const QemuInputHandler *h = s->absolute ?
+            &vmmouse_abs_handler : &vmmouse_rel_handler;
+        s->hs = qemu_input_handler_register(DEVICE(s), h);
+        qemu_input_handler_activate(s->hs);
     }
 }
 
diff --git a/hw/i386/trace-events b/hw/i386/trace-events
index a1dfade20f1..a1a50d09109 100644
--- a/hw/i386/trace-events
+++ b/hw/i386/trace-events
@@ -134,7 +134,7 @@ port92_write(uint8_t val) "port92: write 0x%02x"
 
 # vmmouse.c
 vmmouse_get_status(void) ""
-vmmouse_mouse_event(int x, int y, int dz, int buttons_state) "event: x=%d y=%d dz=%d state=%d"
+vmmouse_queue_event(int x, int y, int dz, int buttons_state) "event: x=%d y=%d dz=%d state=%d"
 vmmouse_init(void) ""
 vmmouse_read_id(void) ""
 vmmouse_request_relative(void) ""

-- 
2.54.0



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

* [GIT PULL 04/27] hw/usb/dev-wacom: convert to modern QemuInputHandler API
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (2 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 03/27] hw/i386/vmmouse: convert to QemuInputHandler API Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 05/27] ui: move LED and key utilities to input.c, delete input-legacy.c Marc-André Lureau
                   ` (23 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

Replace the legacy QEMUPutMouseEvent callbacks with a proper
QemuInputHandler registration. The device now receives typed
input events (BTN/ABS/REL) directly.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/dev-wacom.c | 155 ++++++++++++++++++++++++++++++++---------------------
 1 file changed, 94 insertions(+), 61 deletions(-)

diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c
index 14d07e81281..c69e247f7b7 100644
--- a/hw/usb/dev-wacom.c
+++ b/hw/usb/dev-wacom.c
@@ -42,10 +42,10 @@
 struct USBWacomState {
     USBDevice dev;
     USBEndpoint *intr;
-    QEMUPutMouseEntry *eh_entry;
-    int dx, dy, dz, buttons_state;
-    int x, y;
-    int mouse_grabbed;
+    QemuInputHandlerState *hs;
+    int axis[INPUT_AXIS__MAX];
+    int dz;
+    bool btns[INPUT_BUTTON__MAX];
     enum {
         WACOM_MODE_HID = 1,
         WACOM_MODE_WACOM = 2,
@@ -188,29 +188,37 @@ static const USBDesc desc_wacom = {
     .str  = desc_strings,
 };
 
-static void usb_mouse_event(void *opaque,
-                            int dx1, int dy1, int dz1, int buttons_state)
+static void usb_wacom_input_event(DeviceState *dev, QemuConsole *src,
+                                  QemuInputEvent *evt)
 {
-    USBWacomState *s = opaque;
+    USBWacomState *s = USB_WACOM(dev);
 
-    s->dx += dx1;
-    s->dy += dy1;
-    s->dz += dz1;
-    s->buttons_state = buttons_state;
-    s->changed = 1;
-    usb_wakeup(s->intr, 0);
+    switch (evt->type) {
+    case INPUT_EVENT_KIND_BTN:
+        if (evt->btn.down) {
+            if (evt->btn.button == INPUT_BUTTON_WHEEL_UP) {
+                s->dz--;
+            } else if (evt->btn.button == INPUT_BUTTON_WHEEL_DOWN) {
+                s->dz++;
+            }
+        }
+        s->btns[evt->btn.button] = evt->btn.down;
+        break;
+    case INPUT_EVENT_KIND_ABS:
+        s->axis[evt->abs.axis] = evt->abs.value;
+        break;
+    case INPUT_EVENT_KIND_REL:
+        s->axis[evt->rel.axis] += evt->rel.value;
+        break;
+    default:
+        break;
+    }
 }
 
-static void usb_wacom_event(void *opaque,
-                            int x, int y, int dz, int buttons_state)
+static void usb_wacom_input_sync(DeviceState *dev)
 {
-    USBWacomState *s = opaque;
+    USBWacomState *s = USB_WACOM(dev);
 
-    /* scale to Penpartner resolution */
-    s->x = (x * 5040 / 0x7FFF);
-    s->y = (y * 3780 / 0x7FFF);
-    s->dz += dz;
-    s->buttons_state = buttons_state;
     s->changed = 1;
     usb_wakeup(s->intr, 0);
 }
@@ -225,32 +233,57 @@ static inline int int_clamp(int val, int vmin, int vmax)
         return val;
 }
 
+static void usb_wacom_register_input_handler(USBWacomState *s, bool absolute)
+{
+    static const QemuInputHandler usb_wacom_abs_handler = {
+        .name  = "QEMU PenPartner tablet",
+        .mask  = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_ABS,
+        .event = usb_wacom_input_event,
+        .sync  = usb_wacom_input_sync,
+    };
+
+    static const QemuInputHandler usb_wacom_rel_handler = {
+        .name  = "QEMU PenPartner tablet",
+        .mask  = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
+        .event = usb_wacom_input_event,
+        .sync  = usb_wacom_input_sync,
+    };
+
+    const QemuInputHandler *h = absolute ?
+        &usb_wacom_abs_handler : &usb_wacom_rel_handler;
+
+    g_clear_pointer(&s->hs, qemu_input_handler_unregister);
+
+    s->hs = qemu_input_handler_register(DEVICE(s), h);
+    qemu_input_handler_activate(s->hs);
+}
+
 static int usb_mouse_poll(USBWacomState *s, uint8_t *buf, int len)
 {
     int dx, dy, dz, b, l;
 
-    if (!s->mouse_grabbed) {
-        s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, s, 0,
-                        "QEMU PenPartner tablet");
-        qemu_activate_mouse_event_handler(s->eh_entry);
-        s->mouse_grabbed = 1;
+    if (!s->hs) {
+        usb_wacom_register_input_handler(s, false);
     }
 
-    dx = int_clamp(s->dx, -128, 127);
-    dy = int_clamp(s->dy, -128, 127);
+    dx = int_clamp(s->axis[INPUT_AXIS_X], -128, 127);
+    dy = int_clamp(s->axis[INPUT_AXIS_Y], -128, 127);
     dz = int_clamp(s->dz, -128, 127);
 
-    s->dx -= dx;
-    s->dy -= dy;
+    s->axis[INPUT_AXIS_X] -= dx;
+    s->axis[INPUT_AXIS_Y] -= dy;
     s->dz -= dz;
 
     b = 0;
-    if (s->buttons_state & MOUSE_EVENT_LBUTTON)
+    if (s->btns[INPUT_BUTTON_LEFT]) {
         b |= 0x01;
-    if (s->buttons_state & MOUSE_EVENT_RBUTTON)
+    }
+    if (s->btns[INPUT_BUTTON_RIGHT]) {
         b |= 0x02;
-    if (s->buttons_state & MOUSE_EVENT_MBUTTON)
+    }
+    if (s->btns[INPUT_BUTTON_MIDDLE]) {
         b |= 0x04;
+    }
 
     buf[0] = b;
     buf[1] = dx;
@@ -265,32 +298,40 @@ static int usb_mouse_poll(USBWacomState *s, uint8_t *buf, int len)
 
 static int usb_wacom_poll(USBWacomState *s, uint8_t *buf, int len)
 {
-    int b;
+    int b, x, y;
 
-    if (!s->mouse_grabbed) {
-        s->eh_entry = qemu_add_mouse_event_handler(usb_wacom_event, s, 1,
-                        "QEMU PenPartner tablet");
-        qemu_activate_mouse_event_handler(s->eh_entry);
-        s->mouse_grabbed = 1;
+    if (!s->hs) {
+        usb_wacom_register_input_handler(s, true);
     }
 
     b = 0;
-    if (s->buttons_state & MOUSE_EVENT_LBUTTON)
+    if (s->btns[INPUT_BUTTON_LEFT]) {
         b |= 0x01;
-    if (s->buttons_state & MOUSE_EVENT_RBUTTON)
+    }
+    if (s->btns[INPUT_BUTTON_RIGHT]) {
         b |= 0x40;
-    if (s->buttons_state & MOUSE_EVENT_MBUTTON)
+    }
+    if (s->btns[INPUT_BUTTON_MIDDLE]) {
         b |= 0x20; /* eraser */
+    }
 
-    if (len < 7)
+    if (len < 7) {
         return 0;
+    }
+
+    x = qemu_input_scale_axis(s->axis[INPUT_AXIS_X],
+                              INPUT_EVENT_ABS_MIN, INPUT_EVENT_ABS_MAX,
+                              0, 5040);
+    y = qemu_input_scale_axis(s->axis[INPUT_AXIS_Y],
+                              INPUT_EVENT_ABS_MIN, INPUT_EVENT_ABS_MAX,
+                              0, 3780);
 
     buf[0] = s->mode;
     buf[5] = 0x00 | (b & 0xf0);
-    buf[1] = s->x & 0xff;
-    buf[2] = s->x >> 8;
-    buf[3] = s->y & 0xff;
-    buf[4] = s->y >> 8;
+    buf[1] = x & 0xff;
+    buf[2] = x >> 8;
+    buf[3] = y & 0xff;
+    buf[4] = y >> 8;
     if (b & 0x3f) {
         buf[6] = 0;
     } else {
@@ -302,15 +343,13 @@ static int usb_wacom_poll(USBWacomState *s, uint8_t *buf, int len)
 
 static void usb_wacom_handle_reset(USBDevice *dev)
 {
-    USBWacomState *s = (USBWacomState *) dev;
+    USBWacomState *s = USB_WACOM(dev);
 
-    s->dx = 0;
-    s->dy = 0;
+    memset(s->axis, 0, sizeof(s->axis));
+    memset(s->btns, 0, sizeof(s->btns));
     s->dz = 0;
-    s->x = 0;
-    s->y = 0;
-    s->buttons_state = 0;
     s->mode = WACOM_MODE_HID;
+    g_clear_pointer(&s->hs, qemu_input_handler_unregister);
 }
 
 static void usb_wacom_handle_control(USBDevice *dev, USBPacket *p,
@@ -337,10 +376,7 @@ static void usb_wacom_handle_control(USBDevice *dev, USBPacket *p,
         }
         break;
     case WACOM_SET_REPORT:
-        if (s->mouse_grabbed) {
-            qemu_remove_mouse_event_handler(s->eh_entry);
-            s->mouse_grabbed = 0;
-        }
+        g_clear_pointer(&s->hs, qemu_input_handler_unregister);
         s->mode = data[0];
         break;
     case WACOM_GET_REPORT:
@@ -400,10 +436,7 @@ static void usb_wacom_unrealize(USBDevice *dev)
 {
     USBWacomState *s = (USBWacomState *) dev;
 
-    if (s->mouse_grabbed) {
-        qemu_remove_mouse_event_handler(s->eh_entry);
-        s->mouse_grabbed = 0;
-    }
+    g_clear_pointer(&s->hs, qemu_input_handler_unregister);
 }
 
 static void usb_wacom_realize(USBDevice *dev, Error **errp)

-- 
2.54.0



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

* [GIT PULL 05/27] ui: move LED and key utilities to input.c, delete input-legacy.c
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (3 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 04/27] hw/usb/dev-wacom: convert to modern " Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 06/27] hw/input: replace fprint with LOG_GUEST_ERROR Marc-André Lureau
                   ` (22 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

With both legacy mouse API consumers converted, the remaining
code in input-legacy.c (LED broadcast, index_from_key, qmp_send_key)
is not legacy-specific. Move it to ui/input.c and delete the file.

Clean up include/ui/console.h by removing the now-unused legacy
mouse API declarations (QEMUPutMouseEvent, QEMUPutMouseEntry,
QEMUPutKBDEvent, QEMUPutKbdEntry) and MOUSE_EVENT_* constants.

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/ui/console.h |  18 -----
 ui/input-legacy.c    | 221 ---------------------------------------------------
 ui/input.c           |  66 +++++++++++++++
 ui/ui-hmp-cmds.c     |   7 +-
 ui/meson.build       |   1 -
 5 files changed, 70 insertions(+), 243 deletions(-)

diff --git a/include/ui/console.h b/include/ui/console.h
index 3cb78989cd2..0299ed4b566 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -30,14 +30,6 @@ OBJECT_DECLARE_SIMPLE_TYPE(QemuFixedTextConsole, QEMU_FIXED_TEXT_CONSOLE)
 #define QEMU_IS_FIXED_TEXT_CONSOLE(c) \
     object_dynamic_cast(OBJECT(c), TYPE_QEMU_FIXED_TEXT_CONSOLE)
 
-/* keyboard/mouse support */
-
-#define MOUSE_EVENT_LBUTTON 0x01
-#define MOUSE_EVENT_RBUTTON 0x02
-#define MOUSE_EVENT_MBUTTON 0x04
-#define MOUSE_EVENT_WHEELUP 0x08
-#define MOUSE_EVENT_WHEELDN 0x10
-
 /* identical to the ps/2 keyboard bits */
 #define QEMU_SCROLL_LOCK_LED (1 << 0)
 #define QEMU_NUM_LOCK_LED    (1 << 1)
@@ -62,20 +54,10 @@ enum qemu_color_names {
 #define ATTR2CHTYPE(c, fg, bg, bold) \
     ((bold) << 21 | (bg) << 11 | (fg) << 8 | (c))
 
-typedef void QEMUPutKBDEvent(void *opaque, int keycode);
 typedef void QEMUPutLEDEvent(void *opaque, int ledstate);
-typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int buttons_state);
 
-typedef struct QEMUPutMouseEntry QEMUPutMouseEntry;
-typedef struct QEMUPutKbdEntry QEMUPutKbdEntry;
 typedef struct QEMUPutLEDEntry QEMUPutLEDEntry;
 
-QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
-                                                void *opaque, int absolute,
-                                                const char *name);
-void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry);
-void qemu_activate_mouse_event_handler(QEMUPutMouseEntry *entry);
-
 QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func, void *opaque);
 void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry);
 
diff --git a/ui/input-legacy.c b/ui/input-legacy.c
deleted file mode 100644
index 71b17a3cfc7..00000000000
--- a/ui/input-legacy.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * QEMU System Emulator
- *
- * Copyright (c) 2003-2008 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu/osdep.h"
-#include "qemu/log.h"
-#include "qapi/qapi-commands-ui.h"
-#include "ui/console.h"
-#include "keymaps.h"
-#include "ui/input.h"
-
-struct QEMUPutMouseEntry {
-    QEMUPutMouseEvent *qemu_put_mouse_event;
-    void *qemu_put_mouse_event_opaque;
-    int qemu_put_mouse_event_absolute;
-
-    /* new input core */
-    QemuInputHandler h;
-    QemuInputHandlerState *s;
-    int axis[INPUT_AXIS__MAX];
-    int buttons;
-};
-
-struct QEMUPutKbdEntry {
-    QEMUPutKBDEvent *put_kbd;
-    void *opaque;
-    QemuInputHandlerState *s;
-};
-
-struct QEMUPutLEDEntry {
-    QEMUPutLEDEvent *put_led;
-    void *opaque;
-    QTAILQ_ENTRY(QEMUPutLEDEntry) next;
-};
-
-static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers =
-    QTAILQ_HEAD_INITIALIZER(led_handlers);
-
-void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time,
-                  Error **errp)
-{
-    KeyValueList *p;
-    unsigned int *up = NULL;
-    int count = 0;
-
-    if (!has_hold_time) {
-        hold_time = 0; /* use default */
-    }
-
-    for (p = keys; p != NULL; p = p->next) {
-        up = g_realloc(up, sizeof(*up) * (count+1));
-        up[count] = qemu_input_key_value_to_linux(p->value);
-        qemu_input_event_send_key_linux(NULL, up[count], true);
-        qemu_input_event_send_key_delay(hold_time);
-        count++;
-    }
-    while (count) {
-        count--;
-        qemu_input_event_send_key_linux(NULL, up[count], false);
-        qemu_input_event_send_key_delay(hold_time);
-    }
-    g_free(up);
-}
-
-static void legacy_mouse_event(DeviceState *dev, QemuConsole *src,
-                               QemuInputEvent *evt)
-{
-    static const int bmap[INPUT_BUTTON__MAX] = {
-        [INPUT_BUTTON_LEFT]   = MOUSE_EVENT_LBUTTON,
-        [INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON,
-        [INPUT_BUTTON_RIGHT]  = MOUSE_EVENT_RBUTTON,
-    };
-    QEMUPutMouseEntry *s = (QEMUPutMouseEntry *)dev;
-
-    switch (evt->type) {
-    case INPUT_EVENT_KIND_BTN:
-        if (evt->btn.down) {
-            s->buttons |= bmap[evt->btn.button];
-        } else {
-            s->buttons &= ~bmap[evt->btn.button];
-        }
-        if (evt->btn.down && evt->btn.button == INPUT_BUTTON_WHEEL_UP) {
-            s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
-                                    s->axis[INPUT_AXIS_X],
-                                    s->axis[INPUT_AXIS_Y],
-                                    -1,
-                                    s->buttons);
-        }
-        if (evt->btn.down && evt->btn.button == INPUT_BUTTON_WHEEL_DOWN) {
-            s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
-                                    s->axis[INPUT_AXIS_X],
-                                    s->axis[INPUT_AXIS_Y],
-                                    1,
-                                    s->buttons);
-        }
-        if (evt->btn.down && evt->btn.button == INPUT_BUTTON_WHEEL_RIGHT) {
-            s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
-                                    s->axis[INPUT_AXIS_X],
-                                    s->axis[INPUT_AXIS_Y],
-                                    -2,
-                                    s->buttons);
-        }
-        if (evt->btn.down && evt->btn.button == INPUT_BUTTON_WHEEL_LEFT) {
-            s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
-                                    s->axis[INPUT_AXIS_X],
-                                    s->axis[INPUT_AXIS_Y],
-                                    2,
-                                    s->buttons);
-        }
-        break;
-    case INPUT_EVENT_KIND_ABS:
-        s->axis[evt->abs.axis] = evt->abs.value;
-        break;
-    case INPUT_EVENT_KIND_REL:
-        s->axis[evt->rel.axis] += evt->rel.value;
-        break;
-    default:
-        break;
-    }
-}
-
-static void legacy_mouse_sync(DeviceState *dev)
-{
-    QEMUPutMouseEntry *s = (QEMUPutMouseEntry *)dev;
-
-    s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
-                            s->axis[INPUT_AXIS_X],
-                            s->axis[INPUT_AXIS_Y],
-                            0,
-                            s->buttons);
-
-    if (!s->qemu_put_mouse_event_absolute) {
-        s->axis[INPUT_AXIS_X] = 0;
-        s->axis[INPUT_AXIS_Y] = 0;
-    }
-}
-
-QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
-                                                void *opaque, int absolute,
-                                                const char *name)
-{
-    QEMUPutMouseEntry *s;
-
-    s = g_new0(QEMUPutMouseEntry, 1);
-
-    s->qemu_put_mouse_event = func;
-    s->qemu_put_mouse_event_opaque = opaque;
-    s->qemu_put_mouse_event_absolute = absolute;
-
-    s->h.name = name;
-    s->h.mask = INPUT_EVENT_MASK_BTN |
-        (absolute ? INPUT_EVENT_MASK_ABS : INPUT_EVENT_MASK_REL);
-    s->h.event = legacy_mouse_event;
-    s->h.sync = legacy_mouse_sync;
-    s->s = qemu_input_handler_register((DeviceState *)s,
-                                       &s->h);
-
-    return s;
-}
-
-void qemu_activate_mouse_event_handler(QEMUPutMouseEntry *entry)
-{
-    qemu_input_handler_activate(entry->s);
-}
-
-void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry)
-{
-    qemu_input_handler_unregister(entry->s);
-
-    g_free(entry);
-}
-
-QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func,
-                                            void *opaque)
-{
-    QEMUPutLEDEntry *s;
-
-    s = g_new0(QEMUPutLEDEntry, 1);
-
-    s->put_led = func;
-    s->opaque = opaque;
-    QTAILQ_INSERT_TAIL(&led_handlers, s, next);
-    return s;
-}
-
-void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
-{
-    if (entry == NULL)
-        return;
-    QTAILQ_REMOVE(&led_handlers, entry, next);
-    g_free(entry);
-}
-
-void kbd_put_ledstate(int ledstate)
-{
-    QEMUPutLEDEntry *cursor;
-
-    QTAILQ_FOREACH(cursor, &led_handlers, next) {
-        cursor->put_led(cursor->opaque, ledstate);
-    }
-}
diff --git a/ui/input.c b/ui/input.c
index c013cd9f7e0..55769c66fcc 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -648,3 +648,69 @@ void qemu_input_touch_event(QemuConsole *con,
         qemu_input_event_sync();
     }
 }
+
+struct QEMUPutLEDEntry {
+    QEMUPutLEDEvent *put_led;
+    void *opaque;
+    QTAILQ_ENTRY(QEMUPutLEDEntry) next;
+};
+
+static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers =
+    QTAILQ_HEAD_INITIALIZER(led_handlers);
+
+QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func,
+                                            void *opaque)
+{
+    QEMUPutLEDEntry *s;
+
+    s = g_new0(QEMUPutLEDEntry, 1);
+
+    s->put_led = func;
+    s->opaque = opaque;
+    QTAILQ_INSERT_TAIL(&led_handlers, s, next);
+    return s;
+}
+
+void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
+{
+    if (entry == NULL) {
+        return;
+    }
+    QTAILQ_REMOVE(&led_handlers, entry, next);
+    g_free(entry);
+}
+
+void kbd_put_ledstate(int ledstate)
+{
+    QEMUPutLEDEntry *cursor;
+
+    QTAILQ_FOREACH(cursor, &led_handlers, next) {
+        cursor->put_led(cursor->opaque, ledstate);
+    }
+}
+
+void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time,
+                  Error **errp)
+{
+    KeyValueList *p;
+    unsigned int *up = NULL;
+    int count = 0;
+
+    if (!has_hold_time) {
+        hold_time = 0; /* use default */
+    }
+
+    for (p = keys; p != NULL; p = p->next) {
+        up = g_realloc_n(up, count + 1, sizeof(*up));
+        up[count] = qemu_input_key_value_to_linux(p->value);
+        qemu_input_event_send_key_linux(NULL, up[count], true);
+        qemu_input_event_send_key_delay(hold_time);
+        count++;
+    }
+    while (count) {
+        count--;
+        qemu_input_event_send_key_linux(NULL, up[count], false);
+        qemu_input_event_send_key_delay(hold_time);
+    }
+    g_free(up);
+}
diff --git a/ui/ui-hmp-cmds.c b/ui/ui-hmp-cmds.c
index 76f5181de43..ee3e731d07e 100644
--- a/ui/ui-hmp-cmds.c
+++ b/ui/ui-hmp-cmds.c
@@ -55,10 +55,11 @@ void hmp_mouse_move(Monitor *mon, const QDict *qdict)
 
 void hmp_mouse_button(Monitor *mon, const QDict *qdict)
 {
+    /* HMP mouse_button bitmask: 1=L, 2=R, 4=M */
     static uint32_t bmap[INPUT_BUTTON__MAX] = {
-        [INPUT_BUTTON_LEFT]       = MOUSE_EVENT_LBUTTON,
-        [INPUT_BUTTON_MIDDLE]     = MOUSE_EVENT_MBUTTON,
-        [INPUT_BUTTON_RIGHT]      = MOUSE_EVENT_RBUTTON,
+        [INPUT_BUTTON_LEFT]       = 0x01,
+        [INPUT_BUTTON_MIDDLE]     = 0x04,
+        [INPUT_BUTTON_RIGHT]      = 0x02,
     };
     int button_state = qdict_get_int(qdict, "button_state");
 
diff --git a/ui/meson.build b/ui/meson.build
index bb01f0728e2..0c6a432948c 100644
--- a/ui/meson.build
+++ b/ui/meson.build
@@ -53,7 +53,6 @@ libui = static_library('qemuui', libui_sources + genh,
 ui = declare_dependency(objects: libui.extract_all_objects(recursive: false), dependencies: [pixman])
 system_ss.add(png)
 system_ss.add(files(
-  'input-legacy.c',
   'input-barrier.c',
   'input.c',
   'ui-hmp-cmds.c',

-- 
2.54.0



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

* [GIT PULL 06/27] hw/input: replace fprint with LOG_GUEST_ERROR
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (4 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 05/27] ui: move LED and key utilities to input.c, delete input-legacy.c Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 07/27] ui/input: remove double-notification on qemu_mouse_set() Marc-André Lureau
                   ` (21 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hw/input/virtio-input-hid.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/hw/input/virtio-input-hid.c b/hw/input/virtio-input-hid.c
index 75fe45d89a2..73423ac0c73 100644
--- a/hw/input/virtio-input-hid.c
+++ b/hw/input/virtio-input-hid.c
@@ -6,6 +6,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu/iov.h"
+#include "qemu/log.h"
 #include "qemu/module.h"
 
 #include "hw/virtio/virtio.h"
@@ -107,9 +108,9 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
             virtio_input_send(vinput, &event);
         } else {
             if (evt->btn.down) {
-                fprintf(stderr, "%s: unmapped button: %d [%s]\n", __func__,
-                        evt->btn.button,
-                        InputButton_str(evt->btn.button));
+                qemu_log_mask(LOG_GUEST_ERROR,
+                    "%s: unmapped button: %d [%s]\n", __func__,
+                    evt->btn.button, InputButton_str(evt->btn.button));
             }
         }
         break;
@@ -210,8 +211,9 @@ static void virtio_input_hid_handle_status(VirtIOInput *vinput,
         kbd_put_ledstate(vhid->ledstate);
         break;
     default:
-        fprintf(stderr, "%s: unknown type %d\n", __func__,
-                le16_to_cpu(event->type));
+        qemu_log_mask(LOG_GUEST_ERROR,
+            "%s: unknown type %d\n", __func__,
+            le16_to_cpu(event->type));
         break;
     }
 }

-- 
2.54.0



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

* [GIT PULL 07/27] ui/input: remove double-notification on qemu_mouse_set()
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (5 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 06/27] hw/input: replace fprint with LOG_GUEST_ERROR Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 08/27] ui/input: remove dead declaration Marc-André Lureau
                   ` (20 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

qemu_input_handler_activate() already notifies.

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 ui/input.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/ui/input.c b/ui/input.c
index 55769c66fcc..15affeabf44 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -580,7 +580,6 @@ bool qemu_mouse_set(int index, Error **errp)
     }
 
     qemu_input_handler_activate(s);
-    notifier_list_notify(&mouse_mode_notifiers, NULL);
     return true;
 }
 

-- 
2.54.0



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

* [GIT PULL 08/27] ui/input: remove dead declaration
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (6 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 07/27] ui/input: remove double-notification on qemu_mouse_set() Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 09/27] ui/input: add LED state tracking to QemuInputHandlerState Marc-André Lureau
                   ` (19 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

Fixes: 0337e4123e6 ("input: Allow to choose console with  qemu_input_is_absolute")
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/ui/input.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/include/ui/input.h b/include/ui/input.h
index ea2d944a7ed..6df8ae3a8a3 100644
--- a/include/ui/input.h
+++ b/include/ui/input.h
@@ -100,7 +100,6 @@ void qemu_input_touch_event(QemuConsole *con,
                             InputMultiTouchType type,
                             Error **errp);
 
-void qemu_input_check_mode_change(void);
 void qemu_add_mouse_mode_change_notifier(Notifier *notify);
 void qemu_remove_mouse_mode_change_notifier(Notifier *notify);
 

-- 
2.54.0



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

* [GIT PULL 09/27] ui/input: add LED state tracking to QemuInputHandlerState
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (7 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 08/27] ui/input: remove dead declaration Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 10/27] hw/input/ps2: keep QemuInputHandlerState in PS2State Marc-André Lureau
                   ` (18 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

Add per-handler LED state and a NotifierList for UI backends to
subscribe to LED changes.

Devices call qemu_input_handler_set_led() to store their LED state and
notify backends. Notify also on focus change, or list update.

Note: I considered conflating mouse-mode & led-state changes, but those
are quite different events (from different source kinds etc) and we may
want to improve the internal implementation.

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/ui/input.h | 11 +++++++++++
 ui/input.c         | 51 ++++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 57 insertions(+), 5 deletions(-)

diff --git a/include/ui/input.h b/include/ui/input.h
index 6df8ae3a8a3..11146c92bd4 100644
--- a/include/ui/input.h
+++ b/include/ui/input.h
@@ -151,4 +151,15 @@ extern const guint16 qemu_input_map_xorgxwin_to_linux[];
 extern const guint qemu_input_map_osx_to_linux_len;
 extern const guint16 qemu_input_map_osx_to_linux[];
 
+/**
+ * qemu_input_get_leds_mask() - get the LED mask for the given console
+ * @con: a QemuConsole or NULL
+ *
+ * If @con is NULL, returns the LED state mask for the default console.
+ */
+uint32_t qemu_input_get_leds_mask(const QemuConsole *con);
+void qemu_input_handler_set_leds_mask(QemuInputHandlerState *s, uint32_t leds_mask);
+void qemu_input_led_notifier_add(Notifier *n);
+void qemu_input_led_notifier_remove(Notifier *n);
+
 #endif /* INPUT_H */
diff --git a/ui/input.c b/ui/input.c
index 15affeabf44..3e362c05787 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -14,6 +14,7 @@ struct QemuInputHandlerState {
     int               id;
     int               events;
     QemuConsole       *con;
+    uint32_t          leds_mask;
     QTAILQ_ENTRY(QemuInputHandlerState) node;
 };
 
@@ -38,6 +39,8 @@ static QTAILQ_HEAD(, QemuInputHandlerState) handlers =
     QTAILQ_HEAD_INITIALIZER(handlers);
 static NotifierList mouse_mode_notifiers =
     NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers);
+static NotifierList leds_notifiers =
+    NOTIFIER_LIST_INITIALIZER(leds_notifiers);
 
 static QemuInputEventQueueHead kbd_queue = QTAILQ_HEAD_INITIALIZER(kbd_queue);
 static QEMUTimer *kbd_timer;
@@ -45,6 +48,14 @@ static uint32_t kbd_default_delay_ms = 10;
 static uint32_t queue_count;
 static uint32_t queue_limit = 1024;
 
+static void notify_input_changed(uint32_t mask)
+{
+    notifier_list_notify(&mouse_mode_notifiers, NULL);
+    if (mask & INPUT_EVENT_MASK_KEY) {
+        notifier_list_notify(&leds_notifiers, NULL);
+    }
+}
+
 QemuInputHandlerState *qemu_input_handler_register(DeviceState *dev,
                                             const QemuInputHandler *handler)
 {
@@ -55,8 +66,8 @@ QemuInputHandlerState *qemu_input_handler_register(DeviceState *dev,
     s->handler = handler;
     s->id = id++;
     QTAILQ_INSERT_TAIL(&handlers, s, node);
+    notify_input_changed(handler->mask);
 
-    notifier_list_notify(&mouse_mode_notifiers, NULL);
     return s;
 }
 
@@ -64,21 +75,23 @@ void qemu_input_handler_activate(QemuInputHandlerState *s)
 {
     QTAILQ_REMOVE(&handlers, s, node);
     QTAILQ_INSERT_HEAD(&handlers, s, node);
-    notifier_list_notify(&mouse_mode_notifiers, NULL);
+    notify_input_changed(s->handler->mask);
 }
 
 void qemu_input_handler_deactivate(QemuInputHandlerState *s)
 {
     QTAILQ_REMOVE(&handlers, s, node);
     QTAILQ_INSERT_TAIL(&handlers, s, node);
-    notifier_list_notify(&mouse_mode_notifiers, NULL);
+    notify_input_changed(s->handler->mask);
 }
 
 void qemu_input_handler_unregister(QemuInputHandlerState *s)
 {
+    uint32_t mask = s->handler->mask;
+
     QTAILQ_REMOVE(&handlers, s, node);
     g_free(s);
-    notifier_list_notify(&mouse_mode_notifiers, NULL);
+    notify_input_changed(mask);
 }
 
 void qemu_input_handler_bind(QemuInputHandlerState *s,
@@ -98,7 +111,7 @@ void qemu_input_handler_bind(QemuInputHandlerState *s,
 }
 
 static QemuInputHandlerState*
-qemu_input_find_handler(uint32_t mask, QemuConsole *con)
+qemu_input_find_handler(uint32_t mask, const QemuConsole *con)
 {
     QemuInputHandlerState *s;
 
@@ -122,6 +135,23 @@ qemu_input_find_handler(uint32_t mask, QemuConsole *con)
     return NULL;
 }
 
+void qemu_input_handler_set_leds_mask(QemuInputHandlerState *s, uint32_t leds_mask)
+{
+    assert(s->handler->mask & INPUT_EVENT_MASK_KEY);
+    s->leds_mask = leds_mask;
+    notifier_list_notify(&leds_notifiers, NULL);
+}
+
+void qemu_input_led_notifier_add(Notifier *n)
+{
+    notifier_list_add(&leds_notifiers, n);
+}
+
+void qemu_input_led_notifier_remove(Notifier *n)
+{
+    notifier_remove(n);
+}
+
 void qmp_input_send_event(const char *device,
                           bool has_head, int64_t head,
                           InputEventList *events, Error **errp)
@@ -445,6 +475,17 @@ bool qemu_input_is_absolute(QemuConsole *con)
     return (s != NULL) && (s->handler->mask & INPUT_EVENT_MASK_ABS);
 }
 
+uint32_t qemu_input_get_leds_mask(const QemuConsole *con)
+{
+    QemuInputHandlerState *s;
+
+    s = qemu_input_find_handler(INPUT_EVENT_MASK_KEY, con);
+    if (s) {
+        return s->leds_mask;
+    }
+    return 0;
+}
+
 int qemu_input_scale_axis(int value,
                           int min_in, int max_in,
                           int min_out, int max_out)

-- 
2.54.0



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

* [GIT PULL 10/27] hw/input/ps2: keep QemuInputHandlerState in PS2State
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (8 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 09/27] ui/input: add LED state tracking to QemuInputHandlerState Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 11/27] hw/arm: keep QemuInputHandlerState in musicpal Marc-André Lureau
                   ` (17 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

Track the input handled state, and dispose it on unrealize.

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/hw/input/ps2.h |  2 ++
 hw/input/ps2.c         | 24 ++++++++++++++++++++++--
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/include/hw/input/ps2.h b/include/hw/input/ps2.h
index 058db3e0890..d0c532a38f2 100644
--- a/include/hw/input/ps2.h
+++ b/include/hw/input/ps2.h
@@ -26,6 +26,7 @@
 #define HW_PS2_H
 
 #include "hw/core/sysbus.h"
+#include "ui/input.h"
 
 #define PS2_MOUSE_BUTTON_LEFT   0x01
 #define PS2_MOUSE_BUTTON_RIGHT  0x02
@@ -59,6 +60,7 @@ struct PS2State {
     PS2Queue queue;
     int32_t write_cmd;
     qemu_irq irq;
+    QemuInputHandlerState *hs;
 };
 
 #define TYPE_PS2_DEVICE "ps2-device"
diff --git a/hw/input/ps2.c b/hw/input/ps2.c
index f2523ff4bc7..97df7a9a43e 100644
--- a/hw/input/ps2.c
+++ b/hw/input/ps2.c
@@ -1233,7 +1233,16 @@ static const QemuInputHandler ps2_keyboard_handler = {
 
 static void ps2_kbd_realize(DeviceState *dev, Error **errp)
 {
-    qemu_input_handler_register(dev, &ps2_keyboard_handler);
+    PS2State *s = PS2_DEVICE(dev);
+
+    s->hs = qemu_input_handler_register(dev, &ps2_keyboard_handler);
+}
+
+static void ps2_kbd_unrealize(DeviceState *dev)
+{
+    PS2State *s = PS2_DEVICE(dev);
+
+    g_clear_pointer(&s->hs, qemu_input_handler_unregister);
 }
 
 static const QemuInputHandler ps2_mouse_handler = {
@@ -1245,7 +1254,16 @@ static const QemuInputHandler ps2_mouse_handler = {
 
 static void ps2_mouse_realize(DeviceState *dev, Error **errp)
 {
-    qemu_input_handler_register(dev, &ps2_mouse_handler);
+    PS2State *s = PS2_DEVICE(dev);
+
+    s->hs = qemu_input_handler_register(dev, &ps2_mouse_handler);
+}
+
+static void ps2_mouse_unrealize(DeviceState *dev)
+{
+    PS2State *s = PS2_DEVICE(dev);
+
+    g_clear_pointer(&s->hs, qemu_input_handler_unregister);
 }
 
 static void ps2_kbd_class_init(ObjectClass *klass, const void *data)
@@ -1255,6 +1273,7 @@ static void ps2_kbd_class_init(ObjectClass *klass, const void *data)
     PS2DeviceClass *ps2dc = PS2_DEVICE_CLASS(klass);
 
     dc->realize = ps2_kbd_realize;
+    dc->unrealize = ps2_kbd_unrealize;
     resettable_class_set_parent_phases(rc, NULL, ps2_kbd_reset_hold, NULL,
                                        &ps2dc->parent_phases);
     dc->vmsd = &vmstate_ps2_keyboard;
@@ -1274,6 +1293,7 @@ static void ps2_mouse_class_init(ObjectClass *klass, const void *data)
     PS2DeviceClass *ps2dc = PS2_DEVICE_CLASS(klass);
 
     dc->realize = ps2_mouse_realize;
+    dc->unrealize = ps2_mouse_unrealize;
     resettable_class_set_parent_phases(rc, NULL, ps2_mouse_reset_hold, NULL,
                                        &ps2dc->parent_phases);
     dc->vmsd = &vmstate_ps2_mouse;

-- 
2.54.0



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

* [GIT PULL 11/27] hw/arm: keep QemuInputHandlerState in musicpal
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (9 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 10/27] hw/input/ps2: keep QemuInputHandlerState in PS2State Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 12/27] hw/input: keep QemuInputHandlerState in adb-kbd Marc-André Lureau
                   ` (16 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

Track the input handled state, and dispose it on unrealize.

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hw/arm/musicpal.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index e2630243eb7..69e83bdd973 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -1062,6 +1062,7 @@ struct musicpal_key_state {
     SysBusDevice parent_obj;
     /*< public >*/
 
+    QemuInputHandlerState *hs;
     uint32_t pressed_keys;
     qemu_irq out[8];
 };
@@ -1158,7 +1159,16 @@ static const QemuInputHandler musicpal_key_handler = {
 
 static void musicpal_key_realize(DeviceState *dev, Error **errp)
 {
-    qemu_input_handler_register(dev, &musicpal_key_handler);
+    musicpal_key_state *s = MUSICPAL_KEY(dev);
+
+    s->hs = qemu_input_handler_register(dev, &musicpal_key_handler);
+}
+
+static void musicpal_key_unrealize(DeviceState *dev)
+{
+    musicpal_key_state *s = MUSICPAL_KEY(dev);
+
+    g_clear_pointer(&s->hs, qemu_input_handler_unregister);
 }
 
 static const VMStateDescription musicpal_key_vmsd = {
@@ -1177,6 +1187,7 @@ static void musicpal_key_class_init(ObjectClass *klass, const void *data)
 
     dc->vmsd = &musicpal_key_vmsd;
     dc->realize = musicpal_key_realize;
+    dc->unrealize = musicpal_key_unrealize;
 }
 
 static const TypeInfo musicpal_key_info = {

-- 
2.54.0



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

* [GIT PULL 12/27] hw/input: keep QemuInputHandlerState in adb-kbd
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (10 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 11/27] hw/arm: keep QemuInputHandlerState in musicpal Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 13/27] hw/input: keep QemuInputHandlerState in stellaris Marc-André Lureau
                   ` (15 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

Track the input handled state, and dispose it on unrealize.

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hw/input/adb-kbd.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/hw/input/adb-kbd.c b/hw/input/adb-kbd.c
index c4ef9ebb90c..ece51d5df72 100644
--- a/hw/input/adb-kbd.c
+++ b/hw/input/adb-kbd.c
@@ -40,6 +40,7 @@ struct KBDState {
     ADBDevice parent_obj;
     /*< public >*/
 
+    QemuInputHandlerState *hs;
     uint8_t data[128];
     int rptr, wptr, count;
 };
@@ -51,6 +52,7 @@ struct ADBKeyboardClass {
     /*< public >*/
 
     DeviceRealize parent_realize;
+    DeviceUnrealize parent_unrealize;
 };
 
 /* The adb keyboard doesn't have every key imaginable */
@@ -361,9 +363,20 @@ static const QemuInputHandler adb_keyboard_handler = {
 
 static void adb_kbd_realizefn(DeviceState *dev, Error **errp)
 {
+    KBDState *s = ADB_KEYBOARD(dev);
     ADBKeyboardClass *akc = ADB_KEYBOARD_GET_CLASS(dev);
+
     akc->parent_realize(dev, errp);
-    qemu_input_handler_register(dev, &adb_keyboard_handler);
+    s->hs = qemu_input_handler_register(dev, &adb_keyboard_handler);
+}
+
+static void adb_kbd_unrealizefn(DeviceState *dev)
+{
+    KBDState *s = ADB_KEYBOARD(dev);
+    ADBKeyboardClass *akc = ADB_KEYBOARD_GET_CLASS(dev);
+
+    g_clear_pointer(&s->hs, qemu_input_handler_unregister);
+    akc->parent_unrealize(dev);
 }
 
 static void adb_kbd_initfn(Object *obj)
@@ -381,6 +394,8 @@ static void adb_kbd_class_init(ObjectClass *oc, const void *data)
 
     device_class_set_parent_realize(dc, adb_kbd_realizefn,
                                     &akc->parent_realize);
+    device_class_set_parent_unrealize(dc, adb_kbd_unrealizefn,
+                                    &akc->parent_unrealize);
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 
     adc->devreq = adb_kbd_request;

-- 
2.54.0



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

* [GIT PULL 13/27] hw/input: keep QemuInputHandlerState in stellaris
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (11 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 12/27] hw/input: keep QemuInputHandlerState in adb-kbd Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 14/27] hw/m68k: keep QemuInputHandlerState in next-kbd Marc-André Lureau
                   ` (14 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

Track the input handled state, and dispose it on unrealize.

Also free some allocated fields during unrealize.

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/hw/input/stellaris_gamepad.h |  2 ++
 hw/input/stellaris_gamepad.c         | 12 +++++++++++-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/include/hw/input/stellaris_gamepad.h b/include/hw/input/stellaris_gamepad.h
index e011482646f..c1069735010 100644
--- a/include/hw/input/stellaris_gamepad.h
+++ b/include/hw/input/stellaris_gamepad.h
@@ -13,6 +13,7 @@
 
 #include "hw/core/sysbus.h"
 #include "qom/object.h"
+#include "ui/input.h"
 
 /*
  * QEMU interface:
@@ -28,6 +29,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(StellarisGamepad, STELLARIS_GAMEPAD)
 struct StellarisGamepad {
     SysBusDevice parent_obj;
 
+    QemuInputHandlerState *hs;
     uint32_t num_buttons;
     qemu_irq *irqs;
     uint32_t *keycodes;
diff --git a/hw/input/stellaris_gamepad.c b/hw/input/stellaris_gamepad.c
index 25769fc2616..376d91abad7 100644
--- a/hw/input/stellaris_gamepad.c
+++ b/hw/input/stellaris_gamepad.c
@@ -59,7 +59,16 @@ static void stellaris_gamepad_realize(DeviceState *dev, Error **errp)
     s->irqs = g_new0(qemu_irq, s->num_buttons);
     s->pressed = g_new0(uint8_t, s->num_buttons);
     qdev_init_gpio_out(dev, s->irqs, s->num_buttons);
-    qemu_input_handler_register(dev, &stellaris_gamepad_handler);
+    s->hs = qemu_input_handler_register(dev, &stellaris_gamepad_handler);
+}
+
+static void stellaris_gamepad_unrealize(DeviceState *dev)
+{
+    StellarisGamepad *s = STELLARIS_GAMEPAD(dev);
+
+    g_clear_pointer(&s->irqs, g_free);
+    g_clear_pointer(&s->pressed, g_free);
+    g_clear_pointer(&s->hs, qemu_input_handler_unregister);
 }
 
 static void stellaris_gamepad_reset_enter(Object *obj, ResetType type)
@@ -81,6 +90,7 @@ static void stellaris_gamepad_class_init(ObjectClass *klass, const void *data)
 
     rc->phases.enter = stellaris_gamepad_reset_enter;
     dc->realize = stellaris_gamepad_realize;
+    dc->unrealize = stellaris_gamepad_unrealize;
     dc->vmsd = &vmstate_stellaris_gamepad;
     device_class_set_props(dc, stellaris_gamepad_properties);
 }

-- 
2.54.0



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

* [GIT PULL 14/27] hw/m68k: keep QemuInputHandlerState in next-kbd
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (12 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 13/27] hw/input: keep QemuInputHandlerState in stellaris Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 15/27] ui/input: qemu_input_handler_register to warn for unused result Marc-André Lureau
                   ` (13 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

Track the input handled state, and dispose it on unrealize.

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hw/m68k/next-kbd.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/hw/m68k/next-kbd.c b/hw/m68k/next-kbd.c
index 7be5ab2fb79..84a610edab2 100644
--- a/hw/m68k/next-kbd.c
+++ b/hw/m68k/next-kbd.c
@@ -65,6 +65,7 @@ typedef struct {
 struct NextKBDState {
     SysBusDevice sbd;
     MemoryRegion mr;
+    QemuInputHandlerState *hs;
     KBDQueue queue;
     uint16_t shift;
 };
@@ -304,7 +305,14 @@ static void nextkbd_realize(DeviceState *dev, Error **errp)
     memory_region_init_io(&s->mr, OBJECT(dev), &kbd_ops, s, "next.kbd", 0x1000);
     sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mr);
 
-    qemu_input_handler_register(dev, &nextkbd_handler);
+    s->hs = qemu_input_handler_register(dev, &nextkbd_handler);
+}
+
+static void nextkbd_unrealize(DeviceState *dev)
+{
+    NextKBDState *s = NEXTKBD(dev);
+
+    g_clear_pointer(&s->hs, qemu_input_handler_unregister);
 }
 
 static const VMStateDescription nextkbd_vmstate = {
@@ -319,6 +327,7 @@ static void nextkbd_class_init(ObjectClass *oc, const void *data)
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
     dc->vmsd = &nextkbd_vmstate;
     dc->realize = nextkbd_realize;
+    dc->unrealize = nextkbd_unrealize;
     device_class_set_legacy_reset(dc, nextkbd_reset);
 }
 

-- 
2.54.0



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

* [GIT PULL 15/27] ui/input: qemu_input_handler_register to warn for unused result
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (13 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 14/27] hw/m68k: keep QemuInputHandlerState in next-kbd Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 16/27] hw/input/ps2: use qemu_input_handler_set_leds_mask() for LED state Marc-André Lureau
                   ` (12 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

Suggested-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/ui/input.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/ui/input.h b/include/ui/input.h
index 11146c92bd4..18088babe2a 100644
--- a/include/ui/input.h
+++ b/include/ui/input.h
@@ -45,6 +45,7 @@ struct QemuInputHandler {
     QemuInputHandlerSync   sync;
 };
 
+G_GNUC_WARN_UNUSED_RESULT
 QemuInputHandlerState *qemu_input_handler_register(DeviceState *dev,
                                             const QemuInputHandler *handler);
 void qemu_input_handler_activate(QemuInputHandlerState *s);

-- 
2.54.0



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

* [GIT PULL 16/27] hw/input/ps2: use qemu_input_handler_set_leds_mask() for LED state
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (14 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 15/27] ui/input: qemu_input_handler_register to warn for unused result Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 17/27] hw/input/hid: " Marc-André Lureau
                   ` (11 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hw/input/ps2.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/input/ps2.c b/hw/input/ps2.c
index 97df7a9a43e..5516eb262d7 100644
--- a/hw/input/ps2.c
+++ b/hw/input/ps2.c
@@ -577,7 +577,7 @@ static void ps2_set_ledstate(PS2KbdState *s, int ledstate)
 {
     trace_ps2_set_ledstate(s, ledstate);
     s->ledstate = ledstate;
-    kbd_put_ledstate(ledstate);
+    qemu_input_handler_set_leds_mask(PS2_DEVICE(s)->hs, ledstate);
 }
 
 static void ps2_reset_keyboard(PS2KbdState *s)
@@ -1108,7 +1108,7 @@ static int ps2_kbd_ledstate_post_load(void *opaque, int version_id)
 {
     PS2KbdState *s = opaque;
 
-    kbd_put_ledstate(s->ledstate);
+    qemu_input_handler_set_leds_mask(PS2_DEVICE(s)->hs, s->ledstate);
     return 0;
 }
 

-- 
2.54.0



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

* [GIT PULL 17/27] hw/input/hid: use qemu_input_handler_set_leds_mask() for LED state
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (15 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 16/27] hw/input/ps2: use qemu_input_handler_set_leds_mask() for LED state Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 18/27] hw/input/virtio-input-hid: " Marc-André Lureau
                   ` (10 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hw/input/hid.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/input/hid.c b/hw/input/hid.c
index 467ba8f14f3..0f28827554e 100644
--- a/hw/input/hid.c
+++ b/hw/input/hid.c
@@ -25,6 +25,7 @@
 
 #include "qemu/osdep.h"
 #include "ui/console.h"
+#include "ui/input.h"
 #include "qemu/timer.h"
 #include "hw/input/hid.h"
 #include "migration/vmstate.h"
@@ -470,7 +471,7 @@ int hid_keyboard_write(HIDState *hs, uint8_t *buf, int len)
         if (hs->kbd.leds & 0x02) {
             ledstate |= QEMU_CAPS_LOCK_LED;
         }
-        kbd_put_ledstate(ledstate);
+        qemu_input_handler_set_leds_mask(hs->s, ledstate);
         return 1;
     }
     return 0;

-- 
2.54.0



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

* [GIT PULL 18/27] hw/input/virtio-input-hid: use qemu_input_handler_set_leds_mask() for LED state
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (16 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 17/27] hw/input/hid: " Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 19/27] ui/vnc: switch LED handling to Notifier-based input API Marc-André Lureau
                   ` (9 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hw/input/virtio-input-hid.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/input/virtio-input-hid.c b/hw/input/virtio-input-hid.c
index 73423ac0c73..1019d6b2e53 100644
--- a/hw/input/virtio-input-hid.c
+++ b/hw/input/virtio-input-hid.c
@@ -12,6 +12,7 @@
 #include "hw/virtio/virtio.h"
 #include "hw/core/qdev-properties.h"
 #include "hw/virtio/virtio-input.h"
+#include "ui/input.h"
 
 #include "ui/console.h"
 
@@ -208,7 +209,7 @@ static void virtio_input_hid_handle_status(VirtIOInput *vinput,
         } else {
             vhid->ledstate &= ~ledbit;
         }
-        kbd_put_ledstate(vhid->ledstate);
+        qemu_input_handler_set_leds_mask(vhid->hs, vhid->ledstate);
         break;
     default:
         qemu_log_mask(LOG_GUEST_ERROR,

-- 
2.54.0



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

* [GIT PULL 19/27] ui/vnc: switch LED handling to Notifier-based input API
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (17 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 18/27] hw/input/virtio-input-hid: " Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 20/27] ui/spice: " Marc-André Lureau
                   ` (8 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

Replace QEMUPutLEDEntry with an embedded Notifier in VncDisplay.
Use qemu_input_led_notifier_add/remove instead of the old
qemu_add/remove_led_event_handler.

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 ui/vnc.h               |  2 +-
 tools/qemu-vnc/input.c | 49 +++++++++++++++++--------------------------------
 ui/vnc.c               | 11 ++++++-----
 3 files changed, 24 insertions(+), 38 deletions(-)

diff --git a/ui/vnc.h b/ui/vnc.h
index c8d87cd5301..88293ef4971 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -147,7 +147,7 @@ struct VncDisplay
     DisplayChangeListener dcl;
     kbd_layout_t *kbd_layout;
     int lock_key_sync;
-    QEMUPutLEDEntry *led;
+    Notifier led_notifier;
     int ledstate;
     QKbdState *kbd;
     QemuMutex mutex;
diff --git a/tools/qemu-vnc/input.c b/tools/qemu-vnc/input.c
index 6fb73b31248..dd6a55ce9e5 100644
--- a/tools/qemu-vnc/input.c
+++ b/tools/qemu-vnc/input.c
@@ -13,58 +13,43 @@
 #include "trace.h"
 #include "qemu-vnc.h"
 
-struct QEMUPutLEDEntry {
-    QEMUPutLEDEvent *put_led;
-    void *opaque;
-    QTAILQ_ENTRY(QEMUPutLEDEntry) next;
-};
-
 static NotifierList mouse_mode_notifiers =
     NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers);
-static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers =
-    QTAILQ_HEAD_INITIALIZER(led_handlers);
+static NotifierList led_notifiers =
+    NOTIFIER_LIST_INITIALIZER(led_notifiers);
 
 /* Track the target console for pending mouse events (used by sync) */
 static QemuConsole *mouse_target;
 
-QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func,
-                                            void *opaque)
+/*
+ * The D-Bus Keyboard.Modifiers property uses the same
+ * bit layout as QEMU's LED constants.
+ */
+static guint modifiers;
+
+void qemu_input_led_notifier_add(Notifier *n)
 {
-    QEMUPutLEDEntry *s;
+    notifier_list_add(&led_notifiers, n);
+}
 
-    s = g_new0(QEMUPutLEDEntry, 1);
-    s->put_led = func;
-    s->opaque = opaque;
-    QTAILQ_INSERT_TAIL(&led_handlers, s, next);
-    return s;
+void qemu_input_led_notifier_remove(Notifier *n)
+{
+    notifier_remove(n);
 }
 
-void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
+uint32_t qemu_input_get_leds_mask(const QemuConsole *con)
 {
-    if (!entry) {
-        return;
-    }
-    QTAILQ_REMOVE(&led_handlers, entry, next);
-    g_free(entry);
+    return modifiers;
 }
 
 static void
 on_keyboard_modifiers_changed(GObject *gobject, GParamSpec *pspec,
                               gpointer user_data)
 {
-    guint modifiers;
-    QEMUPutLEDEntry *cursor;
-
     modifiers = qemu_dbus_display1_keyboard_get_modifiers(
         QEMU_DBUS_DISPLAY1_KEYBOARD(gobject));
 
-    /*
-     * The D-Bus Keyboard.Modifiers property uses the same
-     * bit layout as QEMU's LED constants.
-     */
-    QTAILQ_FOREACH(cursor, &led_handlers, next) {
-        cursor->put_led(cursor->opaque, modifiers);
-    }
+    notifier_list_notify(&led_notifiers, NULL);
 }
 
 void qemu_add_mouse_mode_change_notifier(Notifier *notify)
diff --git a/ui/vnc.c b/ui/vnc.c
index 253b1a9f634..b2b69923b75 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1820,9 +1820,10 @@ static void vnc_led_state_change(VncState *vs)
     vnc_flush(vs);
 }
 
-static void kbd_leds(void *opaque, int ledstate)
+static void kbd_leds(Notifier *notifier, void *data)
 {
-    VncDisplay *vd = opaque;
+    VncDisplay *vd = container_of(notifier, VncDisplay, led_notifier);
+    int ledstate = qemu_input_get_leds_mask(vd->dcl.con);
     VncState *client;
 
     trace_vnc_key_guest_leds((ledstate & QEMU_CAPS_LOCK_LED),
@@ -3489,8 +3490,7 @@ static void vnc_display_close(VncDisplay *vd)
     g_free(vd->tlsauthzid);
     vd->tlsauthzid = NULL;
     if (vd->lock_key_sync) {
-        qemu_remove_led_event_handler(vd->led);
-        vd->led = NULL;
+        qemu_input_led_notifier_remove(&vd->led_notifier);
     }
 #ifdef CONFIG_VNC_SASL
     if (vd->sasl.authz) {
@@ -4221,7 +4221,8 @@ static bool vnc_display_open(VncDisplay *vd, Error **errp)
 #endif
     vd->lock_key_sync = lock_key_sync;
     if (lock_key_sync) {
-        vd->led = qemu_add_led_event_handler(kbd_leds, vd);
+        vd->led_notifier.notify = kbd_leds;
+        qemu_input_led_notifier_add(&vd->led_notifier);
     }
     vd->ledstate = 0;
 

-- 
2.54.0



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

* [GIT PULL 20/27] ui/spice: switch LED handling to Notifier-based input API
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (18 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 19/27] ui/vnc: switch LED handling to Notifier-based input API Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 21/27] ui/dbus: " Marc-André Lureau
                   ` (7 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 ui/spice-input.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/ui/spice-input.c b/ui/spice-input.c
index f0bb915fd77..845abc7387f 100644
--- a/ui/spice-input.c
+++ b/ui/spice-input.c
@@ -33,6 +33,7 @@ typedef struct QemuSpiceKbd {
     int ledstate;
     bool emul0;
     size_t pauseseq;
+    Notifier led_notifier;
 } QemuSpiceKbd;
 
 static void kbd_push_key(SpiceKbdInstance *sin, uint8_t frag);
@@ -86,18 +87,20 @@ static uint8_t kbd_get_leds(SpiceKbdInstance *sin)
     return kbd->ledstate;
 }
 
-static void kbd_leds(void *opaque, int ledstate)
+static void kbd_leds(Notifier *notifier, void *data)
 {
-    QemuSpiceKbd *kbd = opaque;
+    QemuSpiceKbd *kbd = container_of(notifier, QemuSpiceKbd, led_notifier);
+    /* spice has no associated console support */
+    uint32_t leds_mask = qemu_input_get_leds_mask(NULL);
 
     kbd->ledstate = 0;
-    if (ledstate & QEMU_SCROLL_LOCK_LED) {
+    if (leds_mask & QEMU_SCROLL_LOCK_LED) {
         kbd->ledstate |= SPICE_KEYBOARD_MODIFIER_FLAGS_SCROLL_LOCK;
     }
-    if (ledstate & QEMU_NUM_LOCK_LED) {
+    if (leds_mask & QEMU_NUM_LOCK_LED) {
         kbd->ledstate |= SPICE_KEYBOARD_MODIFIER_FLAGS_NUM_LOCK;
     }
-    if (ledstate & QEMU_CAPS_LOCK_LED) {
+    if (leds_mask & QEMU_CAPS_LOCK_LED) {
         kbd->ledstate |= SPICE_KEYBOARD_MODIFIER_FLAGS_CAPS_LOCK;
     }
     spice_server_kbd_leds(&kbd->sin, kbd->ledstate);
@@ -247,7 +250,8 @@ void qemu_spice_input_init(void)
     kbd = g_malloc0(sizeof(*kbd));
     kbd->sin.base.sif = &kbd_interface.base;
     qemu_spice.add_interface(&kbd->sin.base);
-    qemu_add_led_event_handler(kbd_leds, kbd);
+    kbd->led_notifier.notify = kbd_leds;
+    qemu_input_led_notifier_add(&kbd->led_notifier);
 
     pointer = g_malloc0(sizeof(*pointer));
     pointer->mouse.base.sif  = &mouse_interface.base;

-- 
2.54.0



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

* [GIT PULL 21/27] ui/dbus: switch LED handling to Notifier-based input API
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (19 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 20/27] ui/spice: " Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 22/27] ui/input: remove old LED handler broadcast queue Marc-André Lureau
                   ` (6 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 ui/dbus-console.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/ui/dbus-console.c b/ui/dbus-console.c
index 21eceb24362..9e154da1eca 100644
--- a/ui/dbus-console.c
+++ b/ui/dbus-console.c
@@ -27,6 +27,7 @@
 #include "ui/input.h"
 #include "ui/kbd-state.h"
 #include "trace.h"
+#include <stdint.h>
 
 #ifdef G_OS_UNIX
 #include <gio/gunixfdlist.h>
@@ -46,6 +47,7 @@ struct _DBusDisplayConsole {
 
     QemuDBusDisplay1Keyboard *iface_kbd;
     QKbdState *kbd;
+    Notifier led_notifier;
 
     QemuDBusDisplay1Mouse *iface_mouse;
     QemuDBusDisplay1MultiTouch *iface_touch;
@@ -150,6 +152,7 @@ dbus_display_console_dispose(GObject *object)
 {
     DBusDisplayConsole *ddc = DBUS_DISPLAY_CONSOLE(object);
 
+    qemu_input_led_notifier_remove(&ddc->led_notifier);
     qemu_console_unregister_listener(&ddc->dcl);
     g_clear_object(&ddc->iface_touch);
     g_clear_object(&ddc->iface_mouse);
@@ -367,11 +370,13 @@ dbus_kbd_release(DBusDisplayConsole *ddc,
 }
 
 static void
-dbus_kbd_qemu_leds_updated(void *data, int ledstate)
+dbus_kbd_qemu_leds_updated(Notifier *notifier, void *data)
 {
-    DBusDisplayConsole *ddc = DBUS_DISPLAY_CONSOLE(data);
+    DBusDisplayConsole *ddc = container_of(notifier, DBusDisplayConsole,
+                                           led_notifier);
+    uint32_t leds_mask = qemu_input_get_leds_mask(ddc->dcl.con);
 
-    qemu_dbus_display1_keyboard_set_modifiers(ddc->iface_kbd, ledstate);
+    qemu_dbus_display1_keyboard_set_modifiers(ddc->iface_kbd, leds_mask);
 }
 
 static gboolean
@@ -577,7 +582,8 @@ dbus_display_console_new(DBusDisplay *display, QemuConsole *con)
 
     ddc->kbd = qkbd_state_init(con);
     ddc->iface_kbd = qemu_dbus_display1_keyboard_skeleton_new();
-    qemu_add_led_event_handler(dbus_kbd_qemu_leds_updated, ddc);
+    ddc->led_notifier.notify = dbus_kbd_qemu_leds_updated;
+    qemu_input_led_notifier_add(&ddc->led_notifier);
     g_object_connect(ddc->iface_kbd,
         "swapped-signal::handle-press", dbus_kbd_press, ddc,
         "swapped-signal::handle-release", dbus_kbd_release, ddc,

-- 
2.54.0



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

* [GIT PULL 22/27] ui/input: remove old LED handler broadcast queue
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (20 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 21/27] ui/dbus: " Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 23/27] tools/qemu-vnc: Have console_get_mouse/keyboard take const QemuConsole Marc-André Lureau
                   ` (5 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/ui/console.h |  9 ---------
 ui/input.c           | 40 ----------------------------------------
 2 files changed, 49 deletions(-)

diff --git a/include/ui/console.h b/include/ui/console.h
index 0299ed4b566..b7bfecb6ee9 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -54,15 +54,6 @@ enum qemu_color_names {
 #define ATTR2CHTYPE(c, fg, bg, bold) \
     ((bold) << 21 | (bg) << 11 | (fg) << 8 | (c))
 
-typedef void QEMUPutLEDEvent(void *opaque, int ledstate);
-
-typedef struct QEMUPutLEDEntry QEMUPutLEDEntry;
-
-QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func, void *opaque);
-void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry);
-
-void kbd_put_ledstate(int ledstate);
-
 bool qemu_mouse_set(int index, Error **errp);
 
 /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx
diff --git a/ui/input.c b/ui/input.c
index 3e362c05787..40a0d507de5 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -689,46 +689,6 @@ void qemu_input_touch_event(QemuConsole *con,
     }
 }
 
-struct QEMUPutLEDEntry {
-    QEMUPutLEDEvent *put_led;
-    void *opaque;
-    QTAILQ_ENTRY(QEMUPutLEDEntry) next;
-};
-
-static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers =
-    QTAILQ_HEAD_INITIALIZER(led_handlers);
-
-QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func,
-                                            void *opaque)
-{
-    QEMUPutLEDEntry *s;
-
-    s = g_new0(QEMUPutLEDEntry, 1);
-
-    s->put_led = func;
-    s->opaque = opaque;
-    QTAILQ_INSERT_TAIL(&led_handlers, s, next);
-    return s;
-}
-
-void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
-{
-    if (entry == NULL) {
-        return;
-    }
-    QTAILQ_REMOVE(&led_handlers, entry, next);
-    g_free(entry);
-}
-
-void kbd_put_ledstate(int ledstate)
-{
-    QEMUPutLEDEntry *cursor;
-
-    QTAILQ_FOREACH(cursor, &led_handlers, next) {
-        cursor->put_led(cursor->opaque, ledstate);
-    }
-}
-
 void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time,
                   Error **errp)
 {

-- 
2.54.0



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

* [GIT PULL 23/27] tools/qemu-vnc: Have console_get_mouse/keyboard take const QemuConsole
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (21 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 22/27] ui/input: remove old LED handler broadcast queue Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 24/27] ui/input: Have qemu_input_is_absolute() take a " Marc-André Lureau
                   ` (4 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

From: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>

Both console_get_mouse() and console_get_keyboard() only
access @con in read-only mode. Make that argument const.

Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260611114212.27472-2-philmd@oss.qualcomm.com>
---
 tools/qemu-vnc/qemu-vnc.h | 4 ++--
 tools/qemu-vnc/display.c  | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/tools/qemu-vnc/qemu-vnc.h b/tools/qemu-vnc/qemu-vnc.h
index 6e483e4b475..15e4ead80b7 100644
--- a/tools/qemu-vnc/qemu-vnc.h
+++ b/tools/qemu-vnc/qemu-vnc.h
@@ -26,8 +26,8 @@ void input_setup(QemuDBusDisplay1Keyboard *kbd,
                  QemuDBusDisplay1Mouse *mouse);
 bool console_setup(GDBusConnection *bus, const char *bus_name,
                    const char *console_path);
-QemuDBusDisplay1Keyboard *console_get_keyboard(QemuConsole *con);
-QemuDBusDisplay1Mouse *console_get_mouse(QemuConsole *con);
+QemuDBusDisplay1Keyboard *console_get_keyboard(const QemuConsole *con);
+QemuDBusDisplay1Mouse *console_get_mouse(const QemuConsole *con);
 
 void audio_setup(GDBusObjectManager *manager);
 void clipboard_setup(GDBusObjectManager *manager, GDBusConnection *bus);
diff --git a/tools/qemu-vnc/display.c b/tools/qemu-vnc/display.c
index 8fe9b6fc898..b485cbe3100 100644
--- a/tools/qemu-vnc/display.c
+++ b/tools/qemu-vnc/display.c
@@ -433,7 +433,7 @@ bool console_setup(GDBusConnection *bus, const char *bus_name,
     return true;
 }
 
-QemuDBusDisplay1Keyboard *console_get_keyboard(QemuConsole *con)
+QemuDBusDisplay1Keyboard *console_get_keyboard(const QemuConsole *con)
 {
     ConsoleData *cd;
 
@@ -444,7 +444,7 @@ QemuDBusDisplay1Keyboard *console_get_keyboard(QemuConsole *con)
     return cd ? cd->keyboard_proxy : NULL;
 }
 
-QemuDBusDisplay1Mouse *console_get_mouse(QemuConsole *con)
+QemuDBusDisplay1Mouse *console_get_mouse(const QemuConsole *con)
 {
     ConsoleData *cd;
 

-- 
2.54.0



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

* [GIT PULL 24/27] ui/input: Have qemu_input_is_absolute() take a const QemuConsole
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (22 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 23/27] tools/qemu-vnc: Have console_get_mouse/keyboard take const QemuConsole Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 25/27] ui/pixman: fix zero rowstride in qemu_pixman_image_new_shareable() Marc-André Lureau
                   ` (3 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

From: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>

qemu_input_is_absolute() does not update the content of the
QemuConsole structure. Make the argument const.

Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260611114212.27472-3-philmd@oss.qualcomm.com>
---
 include/ui/input.h     | 2 +-
 tools/qemu-vnc/input.c | 2 +-
 ui/input.c             | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/include/ui/input.h b/include/ui/input.h
index 18088babe2a..a1560cac0f8 100644
--- a/include/ui/input.h
+++ b/include/ui/input.h
@@ -73,7 +73,7 @@ void qemu_input_queue_btn(QemuConsole *src, InputButton btn, bool down);
 void qemu_input_update_buttons(QemuConsole *src, uint32_t *button_map,
                                uint32_t button_old, uint32_t button_new);
 
-bool qemu_input_is_absolute(QemuConsole *con);
+bool qemu_input_is_absolute(const QemuConsole *con);
 int qemu_input_scale_axis(int value,
                           int min_in, int max_in,
                           int min_out, int max_out);
diff --git a/tools/qemu-vnc/input.c b/tools/qemu-vnc/input.c
index dd6a55ce9e5..a1e9ff00864 100644
--- a/tools/qemu-vnc/input.c
+++ b/tools/qemu-vnc/input.c
@@ -160,7 +160,7 @@ void qemu_input_event_sync(void)
     }
 }
 
-bool qemu_input_is_absolute(QemuConsole *con)
+bool qemu_input_is_absolute(const QemuConsole *con)
 {
     QemuDBusDisplay1Mouse *mouse;
 
diff --git a/ui/input.c b/ui/input.c
index 40a0d507de5..b82622c8645 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -466,7 +466,7 @@ void qemu_input_update_buttons(QemuConsole *src, uint32_t *button_map,
     }
 }
 
-bool qemu_input_is_absolute(QemuConsole *con)
+bool qemu_input_is_absolute(const QemuConsole *con)
 {
     QemuInputHandlerState *s;
 

-- 
2.54.0



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

* [GIT PULL 25/27] ui/pixman: fix zero rowstride in qemu_pixman_image_new_shareable()
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (23 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 24/27] ui/input: Have qemu_input_is_absolute() take a " Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 26/27] ui/sdl2: Explicitly specify EGL platform Marc-André Lureau
                   ` (2 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

qemu_create_displaysurface_from() callers such as xlnx_dp.c pass
linesize=0 with data=NULL, relying on pixman to compute the stride.
Since 1ff788db978 ("ui: use a shareable type"), the data=NULL path
goes through qemu_pixman_image_new_shareable() which computes
size = height * rowstride_bytes, resulting in a zero-size allocation
and an abort in qemu_memfd_alloc().

Introduce qemu-pixman-helpers.h with overflow-safe stride and buffer
size computation (matching pixman's create_bits() formula), and use it
from both qemu_pixman_image_new_shareable() and pixman-minimal's
create_bits().

Reported-by: Peter Maydell <peter.maydell@linaro.org>
Fixes: 1ff788db9781 ("ui: use a shareable type")
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260611113614.1935094-1-marcandre.lureau@redhat.com>
---
 include/ui/pixman-minimal.h      | 25 ++++----------------
 include/ui/qemu-pixman-helpers.h | 49 ++++++++++++++++++++++++++++++++++++++++
 include/ui/qemu-pixman.h         |  1 +
 ui/qemu-pixman.c                 |  8 ++++++-
 4 files changed, 61 insertions(+), 22 deletions(-)

diff --git a/include/ui/pixman-minimal.h b/include/ui/pixman-minimal.h
index 6dd7de1c7e7..680cc809ace 100644
--- a/include/ui/pixman-minimal.h
+++ b/include/ui/pixman-minimal.h
@@ -113,6 +113,8 @@ typedef struct pixman_color {
     uint16_t    alpha;
 } pixman_color_t;
 
+#include "qemu-pixman-helpers.h"
+
 static inline uint32_t *create_bits(pixman_format_code_t format,
                                     int width,
                                     int height,
@@ -120,28 +122,9 @@ static inline uint32_t *create_bits(pixman_format_code_t format,
 {
     int stride = 0;
     size_t buf_size = 0;
-    int bpp = PIXMAN_FORMAT_BPP(format);
-
-    /*
-     * Calculate the following while checking for overflow truncation:
-     * stride = ((width * bpp + 0x1f) >> 5) * sizeof(uint32_t);
-     */
-
-    if (unlikely(__builtin_mul_overflow(width, bpp, &stride))) {
-        return NULL;
-    }
-
-    if (unlikely(__builtin_add_overflow(stride, 0x1f, &stride))) {
-        return NULL;
-    }
-
-    stride >>= 5;
-
-    stride *= sizeof(uint32_t);
 
-    if (unlikely(__builtin_mul_overflow((size_t) height,
-                                        (size_t) stride,
-                                        &buf_size))) {
+    if (!qemu_pixman_image_calc_size(format, width, height,
+                                     &stride, &buf_size)) {
         return NULL;
     }
 
diff --git a/include/ui/qemu-pixman-helpers.h b/include/ui/qemu-pixman-helpers.h
new file mode 100644
index 00000000000..3e247a37946
--- /dev/null
+++ b/include/ui/qemu-pixman-helpers.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Pixman stride and buffer size helpers.
+ * Expects PIXMAN_FORMAT_BPP() and pixman_format_code_t to be
+ * already defined (by either <pixman.h> or "pixman-minimal.h").
+ */
+
+#ifndef QEMU_PIXMAN_HELPERS_H
+#define QEMU_PIXMAN_HELPERS_H
+
+/*
+ * Compute the row stride for a pixman image, aligned to sizeof(uint32_t),
+ * as pixman does. Returns -1 on integer overflow.
+ */
+static inline int qemu_pixman_stride(pixman_format_code_t format, int width)
+{
+    int stride;
+
+    if (unlikely(__builtin_mul_overflow(width, PIXMAN_FORMAT_BPP(format),
+                                        &stride)) ||
+        unlikely(__builtin_add_overflow(stride, 31, &stride))) {
+        return -1;
+    }
+    return (stride / 32) * sizeof(uint32_t);
+}
+
+/*
+ * Compute stride and buffer size for a pixman image.
+ * If *rowstride_bytes is 0, compute it from format and width
+ * (aligned to sizeof(uint32_t), as pixman does).
+ * Returns false on integer overflow.
+ */
+static inline bool qemu_pixman_image_calc_size(pixman_format_code_t format,
+                                               int width, int height,
+                                               int *rowstride_bytes,
+                                               size_t *buf_size)
+{
+    if (!*rowstride_bytes) {
+        *rowstride_bytes = qemu_pixman_stride(format, width);
+        if (*rowstride_bytes < 0) {
+            return false;
+        }
+    }
+
+    return likely(!__builtin_mul_overflow((size_t)height,
+                                          (size_t)*rowstride_bytes, buf_size));
+}
+
+#endif /* QEMU_PIXMAN_HELPERS_H */
diff --git a/include/ui/qemu-pixman.h b/include/ui/qemu-pixman.h
index 4bc7a59698e..1d042c7f634 100644
--- a/include/ui/qemu-pixman.h
+++ b/include/ui/qemu-pixman.h
@@ -8,6 +8,7 @@
 
 #ifdef CONFIG_PIXMAN
 #include <pixman.h>
+#include "qemu-pixman-helpers.h"
 #else
 #include "pixman-minimal.h"
 #endif
diff --git a/ui/qemu-pixman.c b/ui/qemu-pixman.c
index aea09755b94..9dc606f692a 100644
--- a/ui/qemu-pixman.c
+++ b/ui/qemu-pixman.c
@@ -320,12 +320,18 @@ qemu_pixman_image_new_shareable(pixman_image_t **image,
                                 Error **errp)
 {
     ERRP_GUARD();
-    size_t size = height * rowstride_bytes;
+    size_t size;
     void *bits = NULL;
 
     g_return_val_if_fail(image != NULL, false);
     g_return_val_if_fail(handle != NULL, false);
 
+    if (!qemu_pixman_image_calc_size(format, width, height,
+                                     &rowstride_bytes, &size)) {
+        error_setg(errp, "Image dimensions overflow");
+        return false;
+    }
+
     bits = qemu_pixman_shareable_alloc(name, size, handle, errp);
     if (!bits) {
         return false;

-- 
2.54.0



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

* [GIT PULL 26/27] ui/sdl2: Explicitly specify EGL platform
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (24 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 25/27] ui/pixman: fix zero rowstride in qemu_pixman_image_new_shareable() Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-17 15:23 ` [GIT PULL 27/27] ui/sdl2: Set GL ES profile before creating initial GL context Marc-André Lureau
  2026-06-18 17:53 ` [GIT PULL 00/27] UI patches for 2026-06-17 Stefan Hajnoczi
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

From: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>

Mesa's eglGetDisplay() chooses the native EGL platform from
EGL_PLATFORM, limited autodetection, or the build-time default. If that
selects Wayland while SDL is using the X11 video backend, Mesa can treat
the X11 Display pointer as a wl_display and crash during eglInitialize().

Probe EGL with the X11 platform explicitly before enabling
SDL_HINT_VIDEO_X11_FORCE_EGL.

Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3540
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260611-sdl-v1-1-93d4a51684bb@rsg.ci.i.u-tokyo.ac.jp>
---
 include/ui/egl-helpers.h | 5 +++++
 ui/egl-helpers.c         | 4 ++--
 ui/sdl2.c                | 3 ++-
 3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h
index acf993fcf52..c97a0d5c248 100644
--- a/include/ui/egl-helpers.h
+++ b/include/ui/egl-helpers.h
@@ -61,6 +61,11 @@ void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf);
 
 EGLSurface qemu_egl_init_surface_x11(EGLContext ectx, EGLNativeWindowType win);
 
+#if defined(CONFIG_X11) || defined(CONFIG_GBM) || defined(WIN32)
+EGLDisplay qemu_egl_get_display(EGLNativeDisplayType native,
+                                EGLenum platform);
+#endif
+
 #if defined(CONFIG_X11) || defined(CONFIG_GBM)
 
 int qemu_egl_init_dpy_x11(EGLNativeDisplayType dpy, DisplayGLMode mode);
diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
index e3f2872cc14..069a5249554 100644
--- a/ui/egl-helpers.c
+++ b/ui/egl-helpers.c
@@ -520,8 +520,8 @@ EGLSurface qemu_egl_init_surface_x11(EGLContext ectx, EGLNativeWindowType win)
  * platform extensions (EGL_KHR_platform_gbm and friends) yet it doesn't seem
  * like mesa will be able to advertise these (even though it can do EGL 1.5).
  */
-static EGLDisplay qemu_egl_get_display(EGLNativeDisplayType native,
-                                       EGLenum platform)
+EGLDisplay qemu_egl_get_display(EGLNativeDisplayType native,
+                                EGLenum platform)
 {
     EGLDisplay dpy = EGL_NO_DISPLAY;
 
diff --git a/ui/sdl2.c b/ui/sdl2.c
index 4fcdbd79d3c..ce14bd1f4e1 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -862,7 +862,8 @@ static void sdl2_set_hint_x11_force_egl(void)
     }
 
     /* Prefer EGL over GLX to get dma-buf support. */
-    egl_display = eglGetDisplay((EGLNativeDisplayType)x_disp);
+    egl_display = qemu_egl_get_display((EGLNativeDisplayType)x_disp,
+                                       EGL_PLATFORM_X11_KHR);
 
     if (egl_display != EGL_NO_DISPLAY) {
         /*

-- 
2.54.0



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

* [GIT PULL 27/27] ui/sdl2: Set GL ES profile before creating initial GL context
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (25 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 26/27] ui/sdl2: Explicitly specify EGL platform Marc-André Lureau
@ 2026-06-17 15:23 ` Marc-André Lureau
  2026-06-18 17:53 ` [GIT PULL 00/27] UI patches for 2026-06-17 Stefan Hajnoczi
  27 siblings, 0 replies; 29+ messages in thread
From: Marc-André Lureau @ 2026-06-17 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi

From: Ryan Zhang <mailto>

When the user selects GLES via '-display sdl,gl=es', we need to set
SDL_GL_CONTEXT_PROFILE_MASK to SDL_GL_CONTEXT_PROFILE_ES before
calling SDL_GL_CreateContext(). This ensures SDL_GL_LoadLibrary()
loads the correct GLES driver instead of the desktop OpenGL driver.

Fix the below issue: qemu-system-aarch64: /usr/src/debug/libepoxy
/1.5.10/src/dispatch_common.c:872: epoxy_get_proc_address: Assertion
`0 && "Couldn't find current GLX or EGL context.\n"' failed.

sdl2_gl_create_context() already sets the profile mask correctly for
ES mode, but the initial context created in sdl2_window_create() is
missing the same treatment.

Fixes:da3f7a3ab9ea0091955b58f8909dfcee01f4043e ("ui/sdl: try to instantiate the matching opengl renderer")

Signed-off-by: ryan.zhang@nxp.com
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <DU2PR04MB9018BB3650BA218438C01F2A83042@DU2PR04MB9018.eurprd04.prod.outlook.com>
---
 ui/sdl2.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/ui/sdl2.c b/ui/sdl2.c
index ce14bd1f4e1..c75f750e00e 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -113,6 +113,8 @@ void sdl2_window_create(struct sdl2_console *scon)
 
         if (scon->opts->gl == DISPLAY_GL_MODE_ES) {
             driver = "opengles2";
+            SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
+                                SDL_GL_CONTEXT_PROFILE_ES);
         }
 
         SDL_SetHint(SDL_HINT_RENDER_DRIVER, driver);

-- 
2.54.0



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

* Re: [GIT PULL 00/27] UI patches for 2026-06-17
  2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
                   ` (26 preceding siblings ...)
  2026-06-17 15:23 ` [GIT PULL 27/27] ui/sdl2: Set GL ES profile before creating initial GL context Marc-André Lureau
@ 2026-06-18 17:53 ` Stefan Hajnoczi
  27 siblings, 0 replies; 29+ messages in thread
From: Stefan Hajnoczi @ 2026-06-18 17:53 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Stefan Hajnoczi

[-- Attachment #1: Type: text/plain, Size: 116 bytes --]

Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/11.1 for any user-visible changes.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

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

Thread overview: 29+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-17 15:22 [GIT PULL 00/27] UI patches for 2026-06-17 Marc-André Lureau
2026-06-17 15:22 ` [GIT PULL 01/27] hmp-commands.hx: fix button_state doc Marc-André Lureau
2026-06-17 15:22 ` [GIT PULL 02/27] ui/hmp: move index_from_key() where it is used Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 03/27] hw/i386/vmmouse: convert to QemuInputHandler API Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 04/27] hw/usb/dev-wacom: convert to modern " Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 05/27] ui: move LED and key utilities to input.c, delete input-legacy.c Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 06/27] hw/input: replace fprint with LOG_GUEST_ERROR Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 07/27] ui/input: remove double-notification on qemu_mouse_set() Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 08/27] ui/input: remove dead declaration Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 09/27] ui/input: add LED state tracking to QemuInputHandlerState Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 10/27] hw/input/ps2: keep QemuInputHandlerState in PS2State Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 11/27] hw/arm: keep QemuInputHandlerState in musicpal Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 12/27] hw/input: keep QemuInputHandlerState in adb-kbd Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 13/27] hw/input: keep QemuInputHandlerState in stellaris Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 14/27] hw/m68k: keep QemuInputHandlerState in next-kbd Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 15/27] ui/input: qemu_input_handler_register to warn for unused result Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 16/27] hw/input/ps2: use qemu_input_handler_set_leds_mask() for LED state Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 17/27] hw/input/hid: " Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 18/27] hw/input/virtio-input-hid: " Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 19/27] ui/vnc: switch LED handling to Notifier-based input API Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 20/27] ui/spice: " Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 21/27] ui/dbus: " Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 22/27] ui/input: remove old LED handler broadcast queue Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 23/27] tools/qemu-vnc: Have console_get_mouse/keyboard take const QemuConsole Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 24/27] ui/input: Have qemu_input_is_absolute() take a " Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 25/27] ui/pixman: fix zero rowstride in qemu_pixman_image_new_shareable() Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 26/27] ui/sdl2: Explicitly specify EGL platform Marc-André Lureau
2026-06-17 15:23 ` [GIT PULL 27/27] ui/sdl2: Set GL ES profile before creating initial GL context Marc-André Lureau
2026-06-18 17:53 ` [GIT PULL 00/27] UI patches for 2026-06-17 Stefan Hajnoczi

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.