mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
terminal: add xkb-based keyboard devices to idev
The idev-keyboard object provides keyboard devices to the idev interface. It uses libxkbcommon to provide proper keymap support. So far, the keyboard implementation is pretty straightforward with one keyboard device per matching evdev element. We feed everything into the system keymap and provide proper high-level keyboard events to the application. Compose-features and IM need to be added later.
This commit is contained in:
@@ -2976,6 +2976,7 @@ libsystemd_terminal_la_SOURCES = \
|
||||
src/libsystemd-terminal/idev-internal.h \
|
||||
src/libsystemd-terminal/idev.c \
|
||||
src/libsystemd-terminal/idev-evdev.c \
|
||||
src/libsystemd-terminal/idev-keyboard.c \
|
||||
src/libsystemd-terminal/sysview.h \
|
||||
src/libsystemd-terminal/sysview-internal.h \
|
||||
src/libsystemd-terminal/sysview.c \
|
||||
|
||||
@@ -1066,7 +1066,7 @@ AM_CONDITIONAL(ENABLE_MULTI_SEAT_X, [test "$have_multi_seat_x" = "yes"])
|
||||
have_terminal=no
|
||||
AC_ARG_ENABLE(terminal, AS_HELP_STRING([--enable-terminal], [enable terminal support]))
|
||||
if test "x$enable_terminal" = "xyes"; then
|
||||
PKG_CHECK_MODULES([TERMINAL], [ libevdev >= 1.2 ], [have_terminal=yes])
|
||||
PKG_CHECK_MODULES([TERMINAL], [ libevdev >= 1.2 xkbcommon >= 0.4 ], [have_terminal=yes])
|
||||
AS_IF([test "x$have_terminal" != xyes -a "x$enable_terminal" = xyes],
|
||||
[AC_MSG_ERROR([*** terminal support requested but required dependencies not available])],
|
||||
[test "x$have_terminal" = xyes],
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <systemd/sd-bus.h>
|
||||
#include <systemd/sd-event.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include "hashmap.h"
|
||||
#include "idev.h"
|
||||
#include "list.h"
|
||||
@@ -46,6 +47,14 @@ bool idev_is_evdev(idev_element *e);
|
||||
idev_element *idev_find_evdev(idev_session *s, dev_t devnum);
|
||||
int idev_evdev_new(idev_element **out, idev_session *s, struct udev_device *ud);
|
||||
|
||||
/*
|
||||
* Keyboard Devices
|
||||
*/
|
||||
|
||||
bool idev_is_keyboard(idev_device *d);
|
||||
idev_device *idev_find_keyboard(idev_session *s, const char *name);
|
||||
int idev_keyboard_new(idev_device **out, idev_session *s, const char *name);
|
||||
|
||||
/*
|
||||
* Element Links
|
||||
*/
|
||||
|
||||
846
src/libsystemd-terminal/idev-keyboard.c
Normal file
846
src/libsystemd-terminal/idev-keyboard.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -27,6 +27,7 @@
|
||||
#include <systemd/sd-bus.h>
|
||||
#include <systemd/sd-event.h>
|
||||
#include <systemd/sd-login.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include "hashmap.h"
|
||||
#include "idev.h"
|
||||
#include "idev-internal.h"
|
||||
@@ -525,10 +526,40 @@ void idev_session_disable(idev_session *s) {
|
||||
}
|
||||
}
|
||||
|
||||
static int add_link(idev_element *e, idev_device *d) {
|
||||
idev_link *l;
|
||||
|
||||
assert(e);
|
||||
assert(d);
|
||||
|
||||
l = new0(idev_link, 1);
|
||||
if (!l)
|
||||
return -ENOMEM;
|
||||
|
||||
l->element = e;
|
||||
l->device = d;
|
||||
LIST_PREPEND(links_by_element, e->links, l);
|
||||
LIST_PREPEND(links_by_device, d->links, l);
|
||||
device_attach(d, l);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int guess_type(struct udev_device *d) {
|
||||
const char *id_key;
|
||||
|
||||
id_key = udev_device_get_property_value(d, "ID_INPUT_KEY");
|
||||
if (streq_ptr(id_key, "1"))
|
||||
return IDEV_DEVICE_KEYBOARD;
|
||||
|
||||
return IDEV_DEVICE_CNT;
|
||||
}
|
||||
|
||||
int idev_session_add_evdev(idev_session *s, struct udev_device *ud) {
|
||||
idev_element *e;
|
||||
idev_device *d;
|
||||
dev_t devnum;
|
||||
int r;
|
||||
int r, type;
|
||||
|
||||
assert_return(s, -EINVAL);
|
||||
assert_return(ud, -EINVAL);
|
||||
@@ -549,7 +580,34 @@ int idev_session_add_evdev(idev_session *s, struct udev_device *ud) {
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
type = guess_type(ud);
|
||||
if (type < 0)
|
||||
return type;
|
||||
|
||||
switch (type) {
|
||||
case IDEV_DEVICE_KEYBOARD:
|
||||
d = idev_find_keyboard(s, e->name);
|
||||
if (d) {
|
||||
log_debug("idev: %s: keyboard for new evdev element '%s' already available",
|
||||
s->name, e->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = idev_keyboard_new(&d, s, e->name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = add_link(e, d);
|
||||
if (r < 0) {
|
||||
idev_device_free(d);
|
||||
return r;
|
||||
}
|
||||
|
||||
return session_add_device(s, d);
|
||||
default:
|
||||
/* unknown elements are silently ignored */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int idev_session_remove_evdev(idev_session *s, struct udev_device *ud) {
|
||||
|
||||
@@ -32,10 +32,12 @@
|
||||
#include <stdlib.h>
|
||||
#include <systemd/sd-bus.h>
|
||||
#include <systemd/sd-event.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include "util.h"
|
||||
|
||||
typedef struct idev_data idev_data;
|
||||
typedef struct idev_data_evdev idev_data_evdev;
|
||||
typedef struct idev_data_keyboard idev_data_keyboard;
|
||||
|
||||
typedef struct idev_event idev_event;
|
||||
typedef struct idev_device idev_device;
|
||||
@@ -52,6 +54,7 @@ enum {
|
||||
};
|
||||
|
||||
enum {
|
||||
IDEV_DEVICE_KEYBOARD,
|
||||
IDEV_DEVICE_CNT
|
||||
};
|
||||
|
||||
@@ -63,6 +66,50 @@ struct idev_data_evdev {
|
||||
struct input_event event;
|
||||
};
|
||||
|
||||
/*
|
||||
* Keyboard Devices
|
||||
*/
|
||||
|
||||
struct xkb_state;
|
||||
|
||||
enum {
|
||||
IDEV_KBDMOD_IDX_SHIFT,
|
||||
IDEV_KBDMOD_IDX_CTRL,
|
||||
IDEV_KBDMOD_IDX_ALT,
|
||||
IDEV_KBDMOD_IDX_LINUX,
|
||||
IDEV_KBDMOD_IDX_CAPS,
|
||||
IDEV_KBDMOD_CNT,
|
||||
|
||||
IDEV_KBDMOD_SHIFT = 1 << IDEV_KBDMOD_IDX_SHIFT,
|
||||
IDEV_KBDMOD_CTRL = 1 << IDEV_KBDMOD_IDX_CTRL,
|
||||
IDEV_KBDMOD_ALT = 1 << IDEV_KBDMOD_IDX_ALT,
|
||||
IDEV_KBDMOD_LINUX = 1 << IDEV_KBDMOD_IDX_LINUX,
|
||||
IDEV_KBDMOD_CAPS = 1 << IDEV_KBDMOD_IDX_CAPS,
|
||||
};
|
||||
|
||||
enum {
|
||||
IDEV_KBDLED_IDX_NUM,
|
||||
IDEV_KBDLED_IDX_CAPS,
|
||||
IDEV_KBDLED_IDX_SCROLL,
|
||||
IDEV_KBDLED_CNT,
|
||||
|
||||
IDEV_KBDLED_NUM = 1 << IDEV_KBDLED_IDX_NUM,
|
||||
IDEV_KBDLED_CAPS = 1 << IDEV_KBDLED_IDX_CAPS,
|
||||
IDEV_KBDLED_SCROLL = 1 << IDEV_KBDLED_IDX_SCROLL,
|
||||
};
|
||||
|
||||
struct idev_data_keyboard {
|
||||
struct xkb_state *xkb_state;
|
||||
int8_t ascii;
|
||||
uint8_t value;
|
||||
uint16_t keycode;
|
||||
uint32_t mods;
|
||||
uint32_t consumed_mods;
|
||||
uint32_t n_syms;
|
||||
uint32_t *keysyms;
|
||||
uint32_t *codepoints;
|
||||
};
|
||||
|
||||
/*
|
||||
* Data Packets
|
||||
*/
|
||||
@@ -70,6 +117,7 @@ struct idev_data_evdev {
|
||||
enum {
|
||||
IDEV_DATA_RESYNC,
|
||||
IDEV_DATA_EVDEV,
|
||||
IDEV_DATA_KEYBOARD,
|
||||
IDEV_DATA_CNT
|
||||
};
|
||||
|
||||
@@ -79,6 +127,7 @@ struct idev_data {
|
||||
|
||||
union {
|
||||
idev_data_evdev evdev;
|
||||
idev_data_keyboard keyboard;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user