diff --git a/README.md b/README.md
index 26dc996..64c2500 100644
--- a/README.md
+++ b/README.md
@@ -51,7 +51,7 @@ Below is a summary of contributions upstreamed thus far.
- [Add support for keypads to libinput driver] (✅ merged)
- [Add full keyboard support to libinput/evdev driver] (✅ merged)
- [Automatic device discovery via libinput] (✅ merged)
-- [Make it possible to use multiple devices with the libinput and XKB drivers] (⏳ in review)
+- [Make it possible to use multiple devices with the libinput and XKB drivers] (✅ merged)
# Usage
diff --git a/indev.c b/indev.c
new file mode 100644
index 0000000..b1cb4a6
--- /dev/null
+++ b/indev.c
@@ -0,0 +1,189 @@
+/**
+ * Copyright 2021 Johannes Marbach
+ *
+ * This file is part of unl0kr, hereafter referred to as the program.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+
+#include "indev.h"
+
+#include "cursor.h"
+#include "log.h"
+
+#include "lv_drivers/indev/libinput_drv.h"
+
+#include
+
+
+/**
+ * Defines
+ */
+
+#define MAX_KEYBOARD_DEVS 4
+#define MAX_POINTER_DEVS 4
+#define MAX_TOUCHSCREEN_DEVS 1
+
+
+/**
+ * Static variables
+ */
+
+static int num_keyboard_devs = 0;
+static char *keyboard_devs[MAX_KEYBOARD_DEVS];
+static lv_indev_t *keyboard_indevs[MAX_KEYBOARD_DEVS];
+static lv_indev_drv_t keyboard_indev_drvs[MAX_KEYBOARD_DEVS];
+static libinput_drv_state_t keyboard_drv_states[MAX_KEYBOARD_DEVS];
+
+static int num_pointer_devs = 0;
+static char *pointer_devs[MAX_POINTER_DEVS];
+static lv_indev_t *pointer_indevs[MAX_POINTER_DEVS];
+static lv_indev_drv_t pointer_indev_drvs[MAX_POINTER_DEVS];
+static libinput_drv_state_t pointer_drv_states[MAX_POINTER_DEVS];
+
+static int num_touchscreen_devs = 0;
+static char *touchscreen_devs[MAX_TOUCHSCREEN_DEVS];
+static lv_indev_t *touchscreen_indevs[MAX_TOUCHSCREEN_DEVS];
+static lv_indev_drv_t touchscreen_indev_drvs[MAX_TOUCHSCREEN_DEVS];
+static libinput_drv_state_t touchscreen_drv_states[MAX_TOUCHSCREEN_DEVS];
+
+
+/**
+ * Static prototypes
+ */
+
+/**
+ * Auto-connect available input devices having a specific capability.
+ *
+ * @param capability capability to filter devices by
+ * @param max_num_devs maximum number of devices to connect
+ * @param num_devs pointer for writing the actual number of connected devices into
+ * @param devs array for storing device paths
+ * @param indevs array for storing LVGL indevs
+ * @param indev_drvs array for storing LVGL indev drivers
+ * @param drv_states array for storing LVGL libinput driver states
+ */
+static void auto_connect(libinput_capability capability, int max_num_devs, int *num_devs, char *devs[], lv_indev_t *indevs[],
+ lv_indev_drv_t indev_drvs[], libinput_drv_state_t drv_states[]);
+
+/**
+ * Log a message announcing the connection of an input device.
+ *
+ * @param capability the device's capability
+ * @param dev the device path
+ */
+static void log_connection(libinput_capability capability, char *dev);
+
+/**
+ * Perform an input read on a device using the libinput driver.
+ *
+ * @param indev_drv input device driver
+ * @param data input device data to write into
+ */
+static void libinput_read_cb(lv_indev_drv_t *indev_drv, lv_indev_data_t *data);
+
+
+/**
+ * Static functions
+ */
+
+static void auto_connect(libinput_capability capability, int max_num_devs, int *num_devs, char *devs[], lv_indev_t *indevs[],
+ lv_indev_drv_t indev_drvs[], libinput_drv_state_t drv_states[]) {
+
+ memset(devs, 0, max_num_devs * sizeof(char *));
+ memset(indevs, 0, max_num_devs * sizeof(lv_indev_t));
+ memset(indev_drvs, 0, max_num_devs * sizeof(lv_indev_drv_t));
+ memset(drv_states, 0, max_num_devs * sizeof(libinput_drv_state_t));
+
+ *num_devs = libinput_find_devs(capability, devs, max_num_devs, false);
+
+ for (int i = 0; i < *num_devs; ++i) {
+ log_connection(capability, devs[i]);
+
+ libinput_init_state(&(drv_states[i]), devs[i]);
+ lv_indev_drv_init(&(indev_drvs[i]));
+
+ indev_drvs[i].read_cb = libinput_read_cb;
+ indev_drvs[i].user_data = &(drv_states[i]);
+
+ if (capability == LIBINPUT_CAPABILITY_KEYBOARD) {
+ indev_drvs[i].type = LV_INDEV_TYPE_KEYPAD;
+ } else {
+ indev_drvs[i].type = LV_INDEV_TYPE_POINTER;
+ indev_drvs[i].long_press_repeat_time = USHRT_MAX;
+ }
+
+ indevs[i] = lv_indev_drv_register(&(indev_drvs[i]));
+ }
+}
+
+static void log_connection(libinput_capability capability, char *dev) {
+ switch (capability) {
+ case LIBINPUT_CAPABILITY_KEYBOARD:
+ ul_log(UL_LOG_LEVEL_VERBOSE, "Connecting keyboard device %s\n", dev);
+ break;
+ case LIBINPUT_CAPABILITY_POINTER:
+ ul_log(UL_LOG_LEVEL_VERBOSE, "Connecting pointer device %s\n", dev);
+ break;
+ case LIBINPUT_CAPABILITY_TOUCH:
+ ul_log(UL_LOG_LEVEL_VERBOSE, "Connecting touchscreen device %s\n", dev);
+ break;
+ case LIBINPUT_CAPABILITY_NONE:
+ break;
+ }
+}
+
+static void libinput_read_cb(lv_indev_drv_t *indev_drv, lv_indev_data_t *data) {
+ libinput_read_state(indev_drv->user_data, indev_drv, data);
+}
+
+
+/**
+ * Public functions
+ */
+
+void ul_indev_auto_connect() {
+ auto_connect(LIBINPUT_CAPABILITY_KEYBOARD, MAX_KEYBOARD_DEVS, &num_keyboard_devs, keyboard_devs, keyboard_indevs,
+ keyboard_indev_drvs, keyboard_drv_states);
+ auto_connect(LIBINPUT_CAPABILITY_POINTER, MAX_POINTER_DEVS, &num_pointer_devs, pointer_devs, pointer_indevs,
+ pointer_indev_drvs, pointer_drv_states);
+ auto_connect(LIBINPUT_CAPABILITY_TOUCH, MAX_TOUCHSCREEN_DEVS, &num_touchscreen_devs, touchscreen_devs, touchscreen_indevs,
+ touchscreen_indev_drvs, touchscreen_drv_states);
+}
+
+bool ul_indev_is_keyboard_connected() {
+ return num_keyboard_devs > 0;
+}
+
+void ul_indev_set_up_textarea_for_keyboard_input(lv_obj_t *textarea) {
+ if (!ul_indev_is_keyboard_connected()) {
+ return;
+ }
+
+ lv_group_t *group = lv_group_create();
+ lv_group_add_obj(group, textarea);
+
+ for (int i = 0; i < num_keyboard_devs; ++i) {
+ lv_indev_set_group(keyboard_indevs[i], group);
+ }
+}
+
+void ul_indev_set_up_mouse_cursor() {
+ lv_obj_t *cursor_obj = lv_img_create(lv_scr_act());
+ lv_img_set_src(cursor_obj, &ul_cursor_img_dsc);
+ for (int i = 0; i < num_pointer_devs; ++i) {
+ lv_indev_set_cursor(pointer_indevs[i], cursor_obj);
+ }
+}
diff --git a/indev.h b/indev.h
new file mode 100644
index 0000000..e56afcc
--- /dev/null
+++ b/indev.h
@@ -0,0 +1,52 @@
+/**
+ * Copyright 2021 Johannes Marbach
+ *
+ * This file is part of unl0kr, hereafter referred to as the program.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+
+#ifndef UL_INDEV_H
+#define UL_INDEV_H
+
+#include "lvgl/lvgl.h"
+
+#include
+
+/**
+ * Auto-connect currently available keyboard, pointer and touchscreen input devices.
+ */
+void ul_indev_auto_connect();
+
+/**
+ * Check if any keyboard devices are connected.
+ *
+ * @return true if at least one keyboard device is connected, false otherwise
+ */
+bool ul_indev_is_keyboard_connected();
+
+/**
+ * Set up an LVGL text area to receive input from currently connected keyboard devices.
+ *
+ * @param textarea textarea widget
+ */
+void ul_indev_set_up_textarea_for_keyboard_input(lv_obj_t *textarea);
+
+/**
+ * Set up the mouse cursor image for currently connected pointer devices.
+ */
+void ul_indev_set_up_mouse_cursor();
+
+#endif /* UL_INDEV_H */
diff --git a/libinput_multi.c b/libinput_multi.c
deleted file mode 100644
index d259a16..0000000
--- a/libinput_multi.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/**
- * @file libinput_multi.c
- *
- */
-
-/*********************
- * INCLUDES
- *********************/
-#include "libinput_multi.h"
-#if USE_LIBINPUT || USE_BSD_LIBINPUT
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#if USE_BSD_LIBINPUT
-#include
-#else
-#include
-#endif
-
-#include "libinput_xkb.h"
-
-/*********************
- * DEFINES
- *********************/
-
-/**********************
- * TYPEDEFS
- **********************/
-
-/**********************
- * STATIC PROTOTYPES
- **********************/
-static int open_restricted(const char *path, int flags, void *user_data);
-static void close_restricted(int fd, void *user_data);
-
-typedef struct {
- int button;
- int libinput_key_val;
- struct libinput_device *device;
- void *keyboard_state;
-
- int libinput_fd;
- struct libinput *libinput_context;
- struct pollfd fds[1];
-} libinput_multi_state;
-
-/**********************
- * STATIC VARIABLES
- **********************/
-static const int timeout = 0; // do not block
-static const nfds_t nfds = 1;
-static lv_point_t most_recent_touch_point = { .x = 0, .y = 0};
-
-static const struct libinput_interface interface = {
- .open_restricted = open_restricted,
- .close_restricted = close_restricted,
-};
-
-/**********************
- * MACROS
- **********************/
-
-/**********************
- * GLOBAL FUNCTIONS
- **********************/
-
-/**
- * reconfigure the device file for libinput
- * @param indev_drv driver object (must be initialised)
- * @param dev_name set the libinput device filename
- * @return true: the device file set complete
- * false: the device file doesn't exist current system
- */
-bool libinput_multi_set_file(lv_indev_drv_t * indev_drv, char* dev_name)
-{
- libinput_multi_state *state = (libinput_multi_state *)indev_drv->user_data;
- if (!state) {
- perror("unable to read state from driver:");
- return false;
- }
-
- // This check *should* not be necessary, yet applications crashes even on NULL handles.
- // citing libinput.h:libinput_path_remove_device:
- // > If no matching device exists, this function does nothing.
- if (state->device) {
- state->device = libinput_device_unref(state->device);
- libinput_path_remove_device(state->device);
- }
-
- state->device = libinput_path_add_device(state->libinput_context, dev_name);
- if(!state->device) {
- perror("unable to add device to libinput context:");
- return false;
- }
- state->device = libinput_device_ref(state->device);
- if(!state->device) {
- perror("unable to reference device within libinput context:");
- return false;
- }
-
- state->button = LV_INDEV_STATE_REL;
- state->libinput_key_val = 0;
-
- return true;
-}
-
-/**
- * initialise a driver with fresh state data
- * @param indev_drv driver object
- */
-void libinput_multi_init_driver(lv_indev_drv_t * indev_drv) {
- libinput_multi_state *state = (libinput_multi_state *)malloc(sizeof(libinput_multi_state));
- state->device = NULL;
-
- state->libinput_context = libinput_path_create_context(&interface, NULL);
- state->libinput_fd = libinput_get_fd(state->libinput_context);
-
- /* prepare poll */
- state->fds[0].fd = state->libinput_fd;
- state->fds[0].events = POLLIN;
- state->fds[0].revents = 0;
-
- state->keyboard_state = libinput_xkb_create_state();
-
- indev_drv->user_data = (void *)state;
-}
-
-/**
- * destroy any existing state data on a driver
- * @param indev_drv driver object
- */
-void libinput_multi_deinit_driver(lv_indev_drv_t * indev_drv) {
- if (indev_drv->user_data) {
- libinput_multi_state *state = (libinput_multi_state *)indev_drv->user_data;
-
- struct libinput_device *device = libinput_device_unref(state->device);
- libinput_path_remove_device(device);
-
- libinput_unref(state->libinput_context);
-
- // TODO: dealloc keyboard state
-
- free(indev_drv->user_data);
- indev_drv->user_data = NULL;
- }
-}
-
-/**
- * Get the current position and state of the libinput
- * @param indev_drv driver object itself
- * @param data store the libinput data here
- * @return false: because the points are not buffered, so no more data to be read
- */
-void libinput_multi_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
-{
- libinput_multi_state *state = (libinput_multi_state *)indev_drv->user_data;
- if (!state) {
- perror("unable to read state from driver:");
- return;
- }
-
- struct libinput_event *event;
- struct libinput_event_touch *touch_event = NULL;
- struct libinput_event_pointer *pointer_event = NULL;
- struct libinput_event_keyboard *keyboard_event = NULL;
- int rc = 0;
-
- rc = poll(state->fds, nfds, timeout);
- switch (rc){
- case -1:
- perror(NULL);
- case 0:
- goto report_most_recent_state;
- default:
- break;
- }
- libinput_dispatch(state->libinput_context);
- while((event = libinput_get_event(state->libinput_context)) != NULL) {
- enum libinput_event_type type = libinput_event_get_type(event);
- switch (type) {
- case LIBINPUT_EVENT_TOUCH_MOTION:
- case LIBINPUT_EVENT_TOUCH_DOWN:
- touch_event = libinput_event_get_touch_event(event);
- most_recent_touch_point.x = libinput_event_touch_get_x_transformed(touch_event, LV_HOR_RES);
- most_recent_touch_point.y = libinput_event_touch_get_y_transformed(touch_event, LV_VER_RES);
- state->button = LV_INDEV_STATE_PR;
- break;
- case LIBINPUT_EVENT_TOUCH_UP:
- state->button = LV_INDEV_STATE_REL;
- break;
- case LIBINPUT_EVENT_POINTER_MOTION:
- pointer_event = libinput_event_get_pointer_event(event);
- most_recent_touch_point.x += libinput_event_pointer_get_dx(pointer_event);
- most_recent_touch_point.y += libinput_event_pointer_get_dy(pointer_event);
- most_recent_touch_point.x = most_recent_touch_point.x < 0 ? 0 : most_recent_touch_point.x;
- most_recent_touch_point.x = most_recent_touch_point.x > LV_HOR_RES - 1 ? LV_HOR_RES - 1 : most_recent_touch_point.x;
- most_recent_touch_point.y = most_recent_touch_point.y < 0 ? 0 : most_recent_touch_point.y;
- most_recent_touch_point.y = most_recent_touch_point.y > LV_VER_RES - 1 ? LV_VER_RES - 1 : most_recent_touch_point.y;
- break;
- case LIBINPUT_EVENT_POINTER_BUTTON:
- pointer_event = libinput_event_get_pointer_event(event);
- enum libinput_button_state button_state = libinput_event_pointer_get_button_state(pointer_event);
- state->button = button_state == LIBINPUT_BUTTON_STATE_RELEASED ? LV_INDEV_STATE_REL : LV_INDEV_STATE_PR;
- break;
- case LIBINPUT_EVENT_KEYBOARD_KEY:
- keyboard_event = libinput_event_get_keyboard_event(event);
- enum libinput_key_state key_state = libinput_event_keyboard_get_key_state(keyboard_event);
- uint32_t code = libinput_event_keyboard_get_key(keyboard_event);
- state->libinput_key_val = libinput_xkb_process_key(code, key_state == LIBINPUT_KEY_STATE_PRESSED, state->keyboard_state);
- if (state->libinput_key_val != 0) {
- state->button = (key_state == LIBINPUT_KEY_STATE_RELEASED) ? LV_INDEV_STATE_REL : LV_INDEV_STATE_PR; //
- }
- break;
- default:
- break;
- }
- libinput_event_destroy(event);
- }
-report_most_recent_state:
- data->point.x = most_recent_touch_point.x;
- data->point.y = most_recent_touch_point.y;
- data->state = state->button;
- data->key = state->libinput_key_val;
-}
-
-
-/**********************
- * STATIC FUNCTIONS
- **********************/
-
-static int open_restricted(const char *path, int flags, void *user_data)
-{
- int fd = open(path, flags);
- return fd < 0 ? -errno : fd;
-}
-
-static void close_restricted(int fd, void *user_data)
-{
- close(fd);
-}
-
-#endif /* USE_LIBINPUT || USE_BSD_LIBINPUT */
diff --git a/libinput_multi.h b/libinput_multi.h
deleted file mode 100644
index 56aa9b7..0000000
--- a/libinput_multi.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * @file libinput_multi.h
- *
- */
-
-#ifndef LVGL_LIBINPUT_MULTI_H
-#define LVGL_LIBINPUT_MULTI_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*********************
- * INCLUDES
- *********************/
-// #ifndef LV_DRV_NO_CONF
-// #ifdef LV_CONF_INCLUDE_SIMPLE
-#include "lv_drv_conf.h"
-// #else
-// #include "../../lv_drv_conf.h"
-// #endif
-// #endif
-
-#if USE_LIBINPUT || USE_BSD_LIBINPUT
-
-#ifdef LV_LVGL_H_INCLUDE_SIMPLE
-#include "lvgl.h"
-#else
-#include "lvgl/lvgl.h"
-#endif
-
-/*********************
- * DEFINES
- *********************/
-
-/**********************
- * TYPEDEFS
- **********************/
-
-/**********************
- * GLOBAL PROTOTYPES
- **********************/
-
-/**
- * initialise a driver with fresh state data
- * @param indev_drv driver object
- */
-void libinput_multi_init_driver(lv_indev_drv_t * indev_drv);
-/**
- * destroy any existing state data on a driver
- * @param indev_drv driver object
- */
-void libinput_multi_deinit_driver(lv_indev_drv_t * indev_drv);
-/**
- * reconfigure the device file for libinput
- * @param indev_drv driver object (must be initialised)
- * @param dev_name set the libinput device filename
- * @return true: the device file set complete
- * false: the device file doesn't exist current system
- */
-bool libinput_multi_set_file(lv_indev_drv_t * indev_drv, char* dev_name);
-/**
- * Get the current position and state of the libinput
- * @param indev_drv driver object itself
- * @param data store the libinput data here
- * @return false: because the points are not buffered, so no more data to be read
- */
-void libinput_multi_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
-
-
-/**********************
- * MACROS
- **********************/
-
-#endif /* USE_LIBINPUT || USE_BSD_LIBINPUT */
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* LVGL_LIBINPUT_MULTI_H */
diff --git a/libinput_xkb.c b/libinput_xkb.c
deleted file mode 100644
index a085ecf..0000000
--- a/libinput_xkb.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/**
- * @file libinput_xkb.c
- *
- */
-
-/*********************
- * INCLUDES
- *********************/
-#include "libinput_xkb.h"
-#if USE_LIBINPUT || USE_BSD_LIBINPUT
-
-#include
-#include
-#include
-
-/*********************
- * DEFINES
- *********************/
-
-/**********************
- * TYPEDEFS
- **********************/
-
-/**********************
- * STATIC PROTOTYPES
- **********************/
-
-/**********************
- * STATIC VARIABLES
- **********************/
-static struct xkb_context *ctx = NULL;
-static struct xkb_keymap *keymap = NULL;
-
-/**********************
- * MACROS
- **********************/
-
-/**********************
- * GLOBAL FUNCTIONS
- **********************/
-
-bool libinput_xkb_init(void) {
- if (ctx) {
- perror("context is already initialised");
- return true;
- }
-
- ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
- if (!ctx) {
- perror("could not create new XKB context");
- return false;
- }
-
- struct xkb_rule_names names = {
- .rules = NULL,
- .model = "pc105",
- .layout = "de",
- .variant = "nodeadkeys",
- .options = NULL
- };
-
- keymap = xkb_keymap_new_from_names(ctx, &names, XKB_KEYMAP_COMPILE_NO_FLAGS);
- if (!keymap) {
- perror("could not create XKB keymap");
- return false;
- }
-
- keymap = xkb_keymap_ref(keymap);
- if (!keymap) {
- perror("could not reference XKB keymap");
- return false;
- }
-
- return true;
-}
-
-void *libinput_xkb_create_state(void) {
- struct xkb_state *state = xkb_state_new(keymap);
- if (!state) {
- perror("could not create XKB state");
- return false;
- }
-
- state = xkb_state_ref(state);
- if (!state) {
- perror("could not reference XKB state");
- return false;
- }
-
- return state;
-}
-
-uint32_t libinput_xkb_process_key(uint32_t scancode, bool down, void *state) {
- /* Offset the evdev scancode by 8, see https://xkbcommon.org/doc/current/xkbcommon_8h.html#ac29aee92124c08d1953910ab28ee1997 */
- xkb_keycode_t keycode = scancode + 8;
-
- uint32_t result = 0;
-
- switch (xkb_state_key_get_one_sym(state, keycode)) {
- case XKB_KEY_BackSpace:
- result = LV_KEY_BACKSPACE;
- break;
- case XKB_KEY_Return:
- result = LV_KEY_ENTER;
- break;
- case XKB_KEY_Prior:
- result = LV_KEY_PREV;
- break;
- case XKB_KEY_Next:
- result = LV_KEY_NEXT;
- break;
- case XKB_KEY_Up:
- result = LV_KEY_UP;
- break;
- case XKB_KEY_Left:
- result = LV_KEY_LEFT;
- break;
- case XKB_KEY_Right:
- result = LV_KEY_RIGHT;
- break;
- case XKB_KEY_Down:
- result = LV_KEY_DOWN;
- break;
- default:
- break;
- }
-
- if (result == 0) {
- char buffer[4] = { 0, 0, 0, 0 };
- int size = xkb_state_key_get_utf8((struct xkb_state *)state, keycode, NULL, 0) + 1;
- if (size > 1) {
- xkb_state_key_get_utf8((struct xkb_state *)state, keycode, buffer, size);
- memcpy(&result, buffer, 4);
- }
- }
-
- xkb_state_update_key((struct xkb_state *)state, keycode, down ? XKB_KEY_DOWN : XKB_KEY_UP);
-
- return result;
-}
-
-/**********************
- * STATIC FUNCTIONS
- **********************/
-
-#endif /* USE_LIBINPUT || USE_BSD_LIBINPUT */
diff --git a/libinput_xkb.h b/libinput_xkb.h
deleted file mode 100644
index a8f4f21..0000000
--- a/libinput_xkb.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * @file libinput_xkb.h
- *
- */
-
-#ifndef LVGL_LIBINPUT_XKB_H
-#define LVGL_LIBINPUT_XKB_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*********************
- * INCLUDES
- *********************/
-// #ifndef LV_DRV_NO_CONF
-// #ifdef LV_CONF_INCLUDE_SIMPLE
-#include "lv_drv_conf.h"
-// #else
-// #include "../../lv_drv_conf.h"
-// #endif
-// #endif
-
-#if USE_LIBINPUT || USE_BSD_LIBINPUT
-
-#ifdef LV_LVGL_H_INCLUDE_SIMPLE
-#include "lvgl.h"
-#else
-#include "lvgl/lvgl.h"
-#endif
-
-/*********************
- * DEFINES
- *********************/
-
-/**********************
- * TYPEDEFS
- **********************/
-
-/**********************
- * GLOBAL PROTOTYPES
- **********************/
-
-bool libinput_xkb_init(void);
-void *libinput_xkb_create_state(void);
-uint32_t libinput_xkb_process_key(uint32_t code, bool down, void *state);
-
-/**********************
- * MACROS
- **********************/
-
-#endif /* USE_LIBINPUT || USE_BSD_LIBINPUT */
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* LVGL_LIBINPUT_XKB_H */
diff --git a/lv_drivers b/lv_drivers
index 8960d0f..7a0f788 160000
--- a/lv_drivers
+++ b/lv_drivers
@@ -1 +1 @@
-Subproject commit 8960d0fcd0ae4b947169b4282ee7ff94ce5d1cef
+Subproject commit 7a0f788733d53399c87d9572b4f5326e0fe16b16
diff --git a/main.c b/main.c
index 830ddcf..b4def86 100644
--- a/main.c
+++ b/main.c
@@ -19,20 +19,16 @@
#include "command_line.h"
-#include "cursor.h"
-#include "libinput_multi.h"
-#include "libinput_xkb.h"
+#include "indev.h"
#include "log.h"
#include "unl0kr.h"
#include "lv_drivers/display/fbdev.h"
-#include "lv_drivers/indev/libinput_drv.h"
#include "lvgl/lvgl.h"
#include "squeek2lvgl/sq2lv.h"
-#include
#include
#include
#include
@@ -378,70 +374,15 @@ int main(int argc, char *argv[]) {
disp_drv.ver_res = ver_res;
lv_disp_drv_register(&disp_drv);
- /* Connect keyboards */
- libinput_xkb_init();
- #define MAX_KEYBOARDS 3
- char *keyboard_devices[MAX_KEYBOARDS] = { NULL, NULL, NULL };
- lv_indev_drv_t keyboard_indev_drvs[MAX_KEYBOARDS];
- lv_indev_t *keyboard_indevs[MAX_KEYBOARDS] = { NULL, NULL, NULL };
- size_t num_keyboards = libinput_find_devs(LIBINPUT_CAPABILITY_KEYBOARD, keyboard_devices, MAX_KEYBOARDS, false);
- for (int i = 0; i < num_keyboards; ++i) {
- ul_log(UL_LOG_LEVEL_VERBOSE, "Connecting keyboard device %s\n", keyboard_devices[i]);
- lv_indev_drv_init(&keyboard_indev_drvs[i]);
- keyboard_indev_drvs[i].type = LV_INDEV_TYPE_KEYPAD;
- keyboard_indev_drvs[i].read_cb = libinput_multi_read;
- libinput_multi_init_driver(&keyboard_indev_drvs[i]);
- libinput_multi_set_file(&keyboard_indev_drvs[i], keyboard_devices[i]);
- keyboard_indevs[i] = lv_indev_drv_register(&keyboard_indev_drvs[i]);
- }
+ /* Connect input devices */
+ ul_indev_auto_connect();
+ ul_indev_set_up_mouse_cursor();
/* Hide the on-screen keyboard by default if a physical keyboard is connected */
- if (num_keyboards > 0) {
+ if (ul_indev_is_keyboard_connected()) {
is_keyboard_hidden = true;
}
- /* Connect mice and trackpads */
- #define MAX_POINTER_DEVICES 4
- char *pointer_devices[MAX_POINTER_DEVICES] = { NULL, NULL, NULL, NULL };
- lv_indev_drv_t pointer_indev_drvs[MAX_POINTER_DEVICES];
- lv_indev_t *pointer_indevs[MAX_POINTER_DEVICES] = { NULL, NULL, NULL, NULL };
- size_t num_pointer_devices = libinput_find_devs(LIBINPUT_CAPABILITY_POINTER, pointer_devices, MAX_POINTER_DEVICES, false);
- for (int i = 0; i < num_pointer_devices; ++i) {
- ul_log(UL_LOG_LEVEL_VERBOSE, "Connecting pointer device %s\n", pointer_devices[i]);
- lv_indev_drv_init(&pointer_indev_drvs[i]);
- pointer_indev_drvs[i].type = LV_INDEV_TYPE_POINTER;
- pointer_indev_drvs[i].read_cb = libinput_multi_read;
- pointer_indev_drvs[i].long_press_repeat_time = USHRT_MAX;
- libinput_multi_init_driver(&pointer_indev_drvs[i]);
- libinput_multi_set_file(&pointer_indev_drvs[i], pointer_devices[i]);
- pointer_indevs[i] = lv_indev_drv_register(&pointer_indev_drvs[i]);
- }
-
- /* Set mouse cursor */
- if (num_pointer_devices > 0) {
- lv_obj_t *cursor_obj = lv_img_create(lv_scr_act());
- lv_img_set_src(cursor_obj, &ul_cursor_img_dsc);
- for (int i = 0; i < num_pointer_devices; ++i) {
- lv_indev_set_cursor(pointer_indevs[i], cursor_obj);
- }
- }
-
- /* Connect touchscreens */
- #define MAX_TOUCHSCREENS 1
- char *touchscreens[MAX_TOUCHSCREENS] = { NULL };
- lv_indev_drv_t touchscreen_indev_drvs[MAX_TOUCHSCREENS];
- size_t num_touchscreens = libinput_find_devs(LIBINPUT_CAPABILITY_TOUCH, touchscreens, MAX_TOUCHSCREENS, false);
- for (int i = 0; i < num_touchscreens; ++i) {
- ul_log(UL_LOG_LEVEL_VERBOSE, "Connecting touchscreen device %s\n", touchscreens[i]);
- lv_indev_drv_init(&touchscreen_indev_drvs[i]);
- touchscreen_indev_drvs[i].type = LV_INDEV_TYPE_POINTER;
- touchscreen_indev_drvs[i].read_cb = libinput_multi_read;
- touchscreen_indev_drvs[i].long_press_repeat_time = USHRT_MAX;
- libinput_multi_init_driver(&touchscreen_indev_drvs[i]);
- libinput_multi_set_file(&touchscreen_indev_drvs[i], touchscreens[i]);
- lv_indev_drv_register(&touchscreen_indev_drvs[i]);
- }
-
/* Initialise theme and styles */
set_theme(is_dark_theme);
lv_style_init(&style_text_normal);
@@ -510,11 +451,7 @@ int main(int argc, char *argv[]) {
lv_obj_add_style(textarea, &style_text_normal, 0);
/* Route physical keyboard input into textarea */
- lv_group_t *group = lv_group_create();
- lv_group_add_obj(group, textarea);
- for (int i = 0; i < num_keyboards; ++i) {
- lv_indev_set_group(keyboard_indevs[i], group);
- }
+ ul_indev_set_up_textarea_for_keyboard_input(textarea);
/* Show / hide password button */
lv_obj_t *toggle_pw_btn = lv_btn_create(lv_scr_act());
diff --git a/meson.build b/meson.build
index 42328a9..f389253 100644
--- a/meson.build
+++ b/meson.build
@@ -29,9 +29,8 @@ add_project_arguments('-DUL_VERSION="@0@"'.format(meson.project_version()), lang
unl0kr_sources = [
'command_line.c',
'cursor.c',
+ 'indev.c',
'log.c',
- 'libinput_multi.c',
- 'libinput_xkb.c',
'main.c',
'montserrat_extended_32.c',
'sq2lv_layouts.c',