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é <[email protected]>
Signed-off-by: Marc-André Lureau <[email protected]>
---
 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


Reply via email to