@samitouri / QOSamiQemu / commits / 63cdb870aa

ui/input: add LED state tracking to QemuInputHandlerState

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>

Marc-André Lureau committed Jun 9, 2026 at 01:05 UTC 63cdb870aa182515be3e9d91cabe01e1592d9dc9
2 files changed +57 -5
include/ui/input.h
+11
@@ -151,4 +151,15 @@ extern const guint16 qemu_input_map_xorgxwin_to_linux[];
151 extern const guint qemu_input_map_osx_to_linux_len;
152 extern const guint16 qemu_input_map_osx_to_linux[];
153
154 +/**
155 + * qemu_input_get_leds_mask() - get the LED mask for the given console
156 + * @con: a QemuConsole or NULL
157 + *
158 + * If @con is NULL, returns the LED state mask for the default console.
159 + */
160 +uint32_t qemu_input_get_leds_mask(const QemuConsole *con);
161 +void qemu_input_handler_set_leds_mask(QemuInputHandlerState *s, uint32_t leds_mask);
162 +void qemu_input_led_notifier_add(Notifier *n);
163 +void qemu_input_led_notifier_remove(Notifier *n);
164 +
165 #endif /* INPUT_H */
ui/input.c
+46 -5
@@ -14,6 +14,7 @@ struct QemuInputHandlerState {
14 int id;
15 int events;
16 QemuConsole *con;
17 + uint32_t leds_mask;
18 QTAILQ_ENTRY(QemuInputHandlerState) node;
19 };
20
@@ -38,6 +39,8 @@ static QTAILQ_HEAD(, QemuInputHandlerState) handlers =
39 QTAILQ_HEAD_INITIALIZER(handlers);
40 static NotifierList mouse_mode_notifiers =
41 NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers);
42 +static NotifierList leds_notifiers =
43 + NOTIFIER_LIST_INITIALIZER(leds_notifiers);
44
45 static QemuInputEventQueueHead kbd_queue = QTAILQ_HEAD_INITIALIZER(kbd_queue);
46 static QEMUTimer *kbd_timer;
@@ -45,6 +48,14 @@ static uint32_t kbd_default_delay_ms = 10;
48 static uint32_t queue_count;
49 static uint32_t queue_limit = 1024;
50
51 +static void notify_input_changed(uint32_t mask)
52 +{
53 + notifier_list_notify(&mouse_mode_notifiers, NULL);
54 + if (mask & INPUT_EVENT_MASK_KEY) {
55 + notifier_list_notify(&leds_notifiers, NULL);
56 + }
57 +}
58 +
59 QemuInputHandlerState *qemu_input_handler_register(DeviceState *dev,
60 const QemuInputHandler *handler)
61 {
@@ -55,8 +66,8 @@ QemuInputHandlerState *qemu_input_handler_register(DeviceState *dev,
66 s->handler = handler;
67 s->id = id++;
68 QTAILQ_INSERT_TAIL(&handlers, s, node);
69 + notify_input_changed(handler->mask);
70
59 - notifier_list_notify(&mouse_mode_notifiers, NULL);
71 return s;
72 }
73
@@ -64,21 +75,23 @@ void qemu_input_handler_activate(QemuInputHandlerState *s)
75 {
76 QTAILQ_REMOVE(&handlers, s, node);
77 QTAILQ_INSERT_HEAD(&handlers, s, node);
67 - notifier_list_notify(&mouse_mode_notifiers, NULL);
78 + notify_input_changed(s->handler->mask);
79 }
80
81 void qemu_input_handler_deactivate(QemuInputHandlerState *s)
82 {
83 QTAILQ_REMOVE(&handlers, s, node);
84 QTAILQ_INSERT_TAIL(&handlers, s, node);
74 - notifier_list_notify(&mouse_mode_notifiers, NULL);
85 + notify_input_changed(s->handler->mask);
86 }
87
88 void qemu_input_handler_unregister(QemuInputHandlerState *s)
89 {
90 + uint32_t mask = s->handler->mask;
91 +
92 QTAILQ_REMOVE(&handlers, s, node);
93 g_free(s);
81 - notifier_list_notify(&mouse_mode_notifiers, NULL);
94 + notify_input_changed(mask);
95 }
96
97 void qemu_input_handler_bind(QemuInputHandlerState *s,
@@ -98,7 +111,7 @@ void qemu_input_handler_bind(QemuInputHandlerState *s,
111 }
112
113 static QemuInputHandlerState*
101 -qemu_input_find_handler(uint32_t mask, QemuConsole *con)
114 +qemu_input_find_handler(uint32_t mask, const QemuConsole *con)
115 {
116 QemuInputHandlerState *s;
117
@@ -122,6 +135,23 @@ qemu_input_find_handler(uint32_t mask, QemuConsole *con)
135 return NULL;
136 }
137
138 +void qemu_input_handler_set_leds_mask(QemuInputHandlerState *s, uint32_t leds_mask)
139 +{
140 + assert(s->handler->mask & INPUT_EVENT_MASK_KEY);
141 + s->leds_mask = leds_mask;
142 + notifier_list_notify(&leds_notifiers, NULL);
143 +}
144 +
145 +void qemu_input_led_notifier_add(Notifier *n)
146 +{
147 + notifier_list_add(&leds_notifiers, n);
148 +}
149 +
150 +void qemu_input_led_notifier_remove(Notifier *n)
151 +{
152 + notifier_remove(n);
153 +}
154 +
155 void qmp_input_send_event(const char *device,
156 bool has_head, int64_t head,
157 InputEventList *events, Error **errp)
@@ -445,6 +475,17 @@ bool qemu_input_is_absolute(QemuConsole *con)
475 return (s != NULL) && (s->handler->mask & INPUT_EVENT_MASK_ABS);
476 }
477
478 +uint32_t qemu_input_get_leds_mask(const QemuConsole *con)
479 +{
480 + QemuInputHandlerState *s;
481 +
482 + s = qemu_input_find_handler(INPUT_EVENT_MASK_KEY, con);
483 + if (s) {
484 + return s->leds_mask;
485 + }
486 + return 0;
487 +}
488 +
489 int qemu_input_scale_axis(int value,
490 int min_in, int max_in,
491 int min_out, int max_out)