Eliminate libinput_multi*

Fixes: #3
This commit is contained in:
Johannes Marbach
2021-09-24 09:07:37 +02:00
parent 51b1945744
commit 50463b27c2
10 changed files with 250 additions and 607 deletions

View File

@@ -51,7 +51,7 @@ Below is a summary of contributions upstreamed thus far.
- [Add support for keypads to libinput driver] (✅ merged) - [Add support for keypads to libinput driver] (✅ merged)
- [Add full keyboard support to libinput/evdev driver] (✅ merged) - [Add full keyboard support to libinput/evdev driver] (✅ merged)
- [Automatic device discovery via libinput] (✅ 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 # Usage

189
indev.c Normal file
View File

@@ -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 <https://www.gnu.org/licenses/>.
*/
#include "indev.h"
#include "cursor.h"
#include "log.h"
#include "lv_drivers/indev/libinput_drv.h"
#include <limits.h>
/**
* 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);
}
}

52
indev.h Normal file
View File

@@ -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 <https://www.gnu.org/licenses/>.
*/
#ifndef UL_INDEV_H
#define UL_INDEV_H
#include "lvgl/lvgl.h"
#include <stdbool.h>
/**
* 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 */

View File

@@ -1,249 +0,0 @@
/**
* @file libinput_multi.c
*
*/
/*********************
* INCLUDES
*********************/
#include "libinput_multi.h"
#if USE_LIBINPUT || USE_BSD_LIBINPUT
#include <stdio.h>
#include <unistd.h>
#include <linux/limits.h>
#include <fcntl.h>
#include <errno.h>
#include <stdbool.h>
#include <poll.h>
#include <libinput.h>
#if USE_BSD_LIBINPUT
#include <dev/evdev/input.h>
#else
#include <linux/input.h>
#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 */

View File

@@ -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 */

View File

@@ -1,146 +0,0 @@
/**
* @file libinput_xkb.c
*
*/
/*********************
* INCLUDES
*********************/
#include "libinput_xkb.h"
#if USE_LIBINPUT || USE_BSD_LIBINPUT
#include <stdio.h>
#include <stdlib.h>
#include <xkbcommon/xkbcommon.h>
/*********************
* 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 */

View File

@@ -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 */

75
main.c
View File

@@ -19,20 +19,16 @@
#include "command_line.h" #include "command_line.h"
#include "cursor.h" #include "indev.h"
#include "libinput_multi.h"
#include "libinput_xkb.h"
#include "log.h" #include "log.h"
#include "unl0kr.h" #include "unl0kr.h"
#include "lv_drivers/display/fbdev.h" #include "lv_drivers/display/fbdev.h"
#include "lv_drivers/indev/libinput_drv.h"
#include "lvgl/lvgl.h" #include "lvgl/lvgl.h"
#include "squeek2lvgl/sq2lv.h" #include "squeek2lvgl/sq2lv.h"
#include <limits.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
@@ -378,70 +374,15 @@ int main(int argc, char *argv[]) {
disp_drv.ver_res = ver_res; disp_drv.ver_res = ver_res;
lv_disp_drv_register(&disp_drv); lv_disp_drv_register(&disp_drv);
/* Connect keyboards */ /* Connect input devices */
libinput_xkb_init(); ul_indev_auto_connect();
#define MAX_KEYBOARDS 3 ul_indev_set_up_mouse_cursor();
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]);
}
/* Hide the on-screen keyboard by default if a physical keyboard is connected */ /* 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; 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 */ /* Initialise theme and styles */
set_theme(is_dark_theme); set_theme(is_dark_theme);
lv_style_init(&style_text_normal); 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); lv_obj_add_style(textarea, &style_text_normal, 0);
/* Route physical keyboard input into textarea */ /* Route physical keyboard input into textarea */
lv_group_t *group = lv_group_create(); ul_indev_set_up_textarea_for_keyboard_input(textarea);
lv_group_add_obj(group, textarea);
for (int i = 0; i < num_keyboards; ++i) {
lv_indev_set_group(keyboard_indevs[i], group);
}
/* Show / hide password button */ /* Show / hide password button */
lv_obj_t *toggle_pw_btn = lv_btn_create(lv_scr_act()); lv_obj_t *toggle_pw_btn = lv_btn_create(lv_scr_act());

View File

@@ -29,9 +29,8 @@ add_project_arguments('-DUL_VERSION="@0@"'.format(meson.project_version()), lang
unl0kr_sources = [ unl0kr_sources = [
'command_line.c', 'command_line.c',
'cursor.c', 'cursor.c',
'indev.c',
'log.c', 'log.c',
'libinput_multi.c',
'libinput_xkb.c',
'main.c', 'main.c',
'montserrat_extended_32.c', 'montserrat_extended_32.c',
'sq2lv_layouts.c', 'sq2lv_layouts.c',