From: Diego Augusto Date: Sat, 15 Oct 2022 17:53:34 +0000 (-0400) Subject: drm: Add support for new /dev/input feature X-Git-Tag: 23.51.283~49 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3dacf642dd5b2ec33b7a8e483c83b11a3d1c86d1;p=thirdparty%2Fplymouth.git drm: Add support for new /dev/input feature Now that the core plymouth code supports /dev/input, the renderer plugins need to support it as well. As a first step, this commit adds such support to the drm renderer plugin. Some contributions by n3rdopolis and Ray Strode. --- diff --git a/src/plugins/renderers/drm/plugin.c b/src/plugins/renderers/drm/plugin.c index fb0c7e8a..56c9f898 100644 --- a/src/plugins/renderers/drm/plugin.c +++ b/src/plugins/renderers/drm/plugin.c @@ -51,6 +51,7 @@ #include "ply-array.h" #include "ply-buffer.h" #include "ply-event-loop.h" +#include "ply-input-device.h" #include "ply-list.h" #include "ply-logger.h" #include "ply-hashtable.h" @@ -94,6 +95,7 @@ struct _ply_renderer_input_source { ply_renderer_backend_t *backend; ply_fd_watch_t *terminal_input_watch; + ply_list_t *input_devices; ply_buffer_t *key_buffer; @@ -158,6 +160,7 @@ struct _ply_renderer_backend uint32_t is_active : 1; uint32_t requires_explicit_flushing : 1; + uint32_t input_source_is_open : 1; int panel_width; int panel_height; @@ -166,6 +169,8 @@ struct _ply_renderer_backend }; ply_renderer_plugin_interface_t *ply_renderer_backend_get_interface (void); + +static bool using_input_device (ply_renderer_input_source_t *backend); static bool open_input_source (ply_renderer_backend_t *backend, ply_renderer_input_source_t *input_source); static void flush_head (ply_renderer_backend_t *backend, @@ -884,6 +889,7 @@ create_backend (const char *device_name, backend->loop = ply_event_loop_get_default (); backend->heads = ply_list_new (); backend->input_source.key_buffer = ply_buffer_new (); + backend->input_source.input_devices = ply_list_new (); backend->terminal = terminal; backend->requires_explicit_flushing = true; backend->output_buffers = ply_hashtable_new (ply_hashtable_direct_hash, @@ -908,6 +914,7 @@ destroy_backend (ply_renderer_backend_t *backend) free (backend->device_name); ply_hashtable_free (backend->output_buffers); ply_hashtable_free (backend->heads_by_controller_id); + ply_list_free (backend->input_source.input_devices); free (backend->outputs); free (backend); @@ -1236,14 +1243,12 @@ find_controller_for_output (ply_renderer_backend_t *backend, if (!(possible_controllers & (1 << i))) continue; /* controller not usable for this connector */ - for (j = 0; j < outputs_len; j++) { if (outputs[j].controller_id == controller_id) break; } if (j < outputs_len) continue; /* controller already in use */ - return controller_id; } @@ -1744,9 +1749,18 @@ get_input_source (ply_renderer_backend_t *backend) } static void -on_key_event (ply_renderer_input_source_t *input_source, - int terminal_fd) +on_terminal_key_event (ply_renderer_input_source_t *input_source) { + ply_renderer_backend_t *backend = input_source->backend; + int terminal_fd; + + if (using_input_device (input_source)) { + ply_terminal_flush_input (backend->terminal); + return; + } + + terminal_fd = ply_terminal_get_fd (backend->terminal); + ply_buffer_append_from_fd (input_source->key_buffer, terminal_fd); @@ -1754,6 +1768,34 @@ on_key_event (ply_renderer_input_source_t *input_source, input_source->handler (input_source->user_data, input_source->key_buffer, input_source); } +static void +on_input_device_key (ply_renderer_input_source_t *input_source, + ply_input_device_t *input_device, + const char *text) +{ + int len = strlen (text); + if (len > 0) + ply_buffer_append_bytes (input_source->key_buffer, text, len); + + if (input_source->handler != NULL) + input_source->handler (input_source->user_data, input_source->key_buffer, input_source); +} + +static void +on_input_leds_changed (ply_renderer_input_source_t *input_source, + ply_input_device_t *input_device) +{ + ply_xkb_keyboard_state_t *state; + ply_list_node_t *node; + + state = ply_input_device_get_state (input_device); + + ply_list_foreach (input_source->input_devices, node) { + ply_input_device_t *set_input_device = ply_list_node_get_data (node); + ply_input_device_set_state (set_input_device, state); + } +} + static void on_input_source_disconnected (ply_renderer_input_source_t *input_source) { @@ -1762,6 +1804,37 @@ on_input_source_disconnected (ply_renderer_input_source_t *input_source) open_input_source (input_source->backend, input_source); } +static bool +using_input_device (ply_renderer_input_source_t *input_source) +{ + return ply_list_get_length (input_source->input_devices) > 0; +} + +static void +watch_input_device (ply_renderer_backend_t *backend, + ply_input_device_t *input_device) +{ + ply_trace ("Listening for keys from device '%s'", ply_input_device_get_name (input_device)); + + ply_input_device_watch_for_input (input_device, + (ply_input_device_input_handler_t) on_input_device_key, + (ply_input_device_leds_changed_handler_t) on_input_leds_changed, + &backend->input_source); +} + +static void +watch_input_devices (ply_renderer_backend_t *backend) +{ + ply_list_node_t *node; + ply_renderer_input_source_t *input_source = &backend->input_source; + + ply_list_foreach (input_source->input_devices, node) { + ply_input_device_t *input_device = ply_list_node_get_data (node); + + watch_input_device (backend, input_device); + } +} + static bool open_input_source (ply_renderer_backend_t *backend, ply_renderer_input_source_t *input_source) @@ -1771,16 +1844,24 @@ open_input_source (ply_renderer_backend_t *backend, assert (backend != NULL); assert (has_input_source (backend, input_source)); + if (!backend->input_source_is_open) + watch_input_devices (backend); + if (backend->terminal == NULL) return false; - terminal_fd = ply_terminal_get_fd (backend->terminal); + if (backend->terminal != NULL) { + terminal_fd = ply_terminal_get_fd (backend->terminal); + + input_source->terminal_input_watch = ply_event_loop_watch_fd (backend->loop, terminal_fd, PLY_EVENT_LOOP_FD_STATUS_HAS_DATA, + (ply_event_handler_t) on_terminal_key_event, + (ply_event_handler_t) + on_input_source_disconnected, input_source); + } input_source->backend = backend; - input_source->terminal_input_watch = ply_event_loop_watch_fd (backend->loop, terminal_fd, PLY_EVENT_LOOP_FD_STATUS_HAS_DATA, - (ply_event_handler_t) on_key_event, - (ply_event_handler_t) - on_input_source_disconnected, input_source); + backend->input_source_is_open = true; + return true; } @@ -1804,12 +1885,28 @@ close_input_source (ply_renderer_backend_t *backend, assert (backend != NULL); assert (has_input_source (backend, input_source)); - if (backend->terminal == NULL) + if (!backend->input_source_is_open) return; - ply_event_loop_stop_watching_fd (backend->loop, input_source->terminal_input_watch); - input_source->terminal_input_watch = NULL; + if (using_input_device (input_source)) { + ply_list_node_t *node; + ply_list_foreach (input_source->input_devices, node) { + ply_input_device_t *input_device = ply_list_node_get_data (node); + ply_input_device_stop_watching_for_input (input_device, + (ply_input_device_input_handler_t) on_input_device_key, + (ply_input_device_leds_changed_handler_t) on_input_leds_changed, + &backend->input_source); + } + } + + if (input_source->terminal_input_watch != NULL) { + ply_event_loop_stop_watching_fd (backend->loop, input_source->terminal_input_watch); + input_source->terminal_input_watch = NULL; + } + input_source->backend = NULL; + + backend->input_source_is_open = false; } static bool @@ -1829,9 +1926,30 @@ get_panel_properties (ply_renderer_backend_t *backend, return true; } +static ply_input_device_t * +get_any_input_device_with_leds (ply_renderer_backend_t *backend) +{ + ply_list_node_t *node; + + ply_list_foreach (backend->input_source.input_devices, node) { + ply_input_device_t *input_device; + + input_device = ply_list_node_get_data (node); + + if (ply_input_device_is_keyboard_with_leds (input_device)) + return input_device; + } + + return NULL; +} + static bool get_capslock_state (ply_renderer_backend_t *backend) { + if (using_input_device (&backend->input_source)) { + ply_input_device_t *dev = get_any_input_device_with_leds (backend); + return ply_input_device_get_capslock_state (dev); + } if (!backend->terminal) return false; @@ -1841,12 +1959,64 @@ get_capslock_state (ply_renderer_backend_t *backend) static const char * get_keymap (ply_renderer_backend_t *backend) { + if (using_input_device (&backend->input_source)) { + ply_input_device_t *dev = get_any_input_device_with_leds (backend); + const char *keymap = ply_input_device_get_keymap (dev); + if (keymap != NULL) { + return keymap; + } + } if (!backend->terminal) return NULL; return ply_terminal_get_keymap (backend->terminal); } +static void +sync_input_devices (ply_renderer_backend_t *backend) +{ + ply_list_node_t *node; + ply_xkb_keyboard_state_t *xkb_state; + ply_input_device_t *source_input_device; + + source_input_device = get_any_input_device_with_leds (backend); + + if (source_input_device == NULL) + return; + + xkb_state = ply_input_device_get_state (source_input_device); + + ply_list_foreach (backend->input_source.input_devices, node) { + ply_input_device_t *target_input_device = ply_list_node_get_data (node); + + if (source_input_device == target_input_device) + continue; + + ply_input_device_set_state (target_input_device, xkb_state); + } +} + +static void +add_input_device (ply_renderer_backend_t *backend, + ply_input_device_t *input_device) +{ + ply_list_append_data (backend->input_source.input_devices, input_device); + + if (backend->input_source_is_open) + watch_input_device (backend, input_device); + + sync_input_devices (backend); +} + +static void +remove_input_device (ply_renderer_backend_t *backend, + ply_input_device_t *input_device) +{ + ply_list_remove_data (backend->input_source.input_devices, input_device); + + sync_input_devices (backend); +} + ply_renderer_plugin_interface_t * ply_renderer_backend_get_interface (void) { @@ -1873,8 +2043,9 @@ ply_renderer_backend_get_interface (void) .get_panel_properties = get_panel_properties, .get_capslock_state = get_capslock_state, .get_keymap = get_keymap, + .add_input_device = add_input_device, + .remove_input_device = remove_input_device, }; return &plugin_interface; } -