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)