#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"
{
ply_renderer_backend_t *backend;
ply_fd_watch_t *terminal_input_watch;
+ ply_list_t *input_devices;
ply_buffer_t *key_buffer;
uint32_t is_active : 1;
uint32_t requires_explicit_flushing : 1;
+ uint32_t input_source_is_open : 1;
int panel_width;
int panel_height;
};
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,
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,
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);
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;
}
}
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);
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)
{
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)
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;
}
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
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;
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)
{
.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;
}
-