Refactor input backend-system
This is a rewrite of the input system. The backends itself are not modified. However, it is now possible to have multiple backends and change them on runtime. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
This commit is contained in:
parent
a0217124e5
commit
741b8d33df
10
Makefile.am
10
Makefile.am
@ -152,6 +152,9 @@ libuterm_la_SOURCES = \
|
|||||||
src/uterm_video.c \
|
src/uterm_video.c \
|
||||||
src/uterm_monitor.c \
|
src/uterm_monitor.c \
|
||||||
src/uterm_input.c \
|
src/uterm_input.c \
|
||||||
|
src/uterm_input_plain.c \
|
||||||
|
external/imKStoUCS.h \
|
||||||
|
external/imKStoUCS.c \
|
||||||
src/uterm_vt.c \
|
src/uterm_vt.c \
|
||||||
src/vt.h \
|
src/vt.h \
|
||||||
src/vt.c
|
src/vt.c
|
||||||
@ -195,12 +198,7 @@ endif
|
|||||||
|
|
||||||
if UTERM_HAVE_XKBCOMMON
|
if UTERM_HAVE_XKBCOMMON
|
||||||
libuterm_la_SOURCES += \
|
libuterm_la_SOURCES += \
|
||||||
src/uterm_input_xkb.c
|
src/uterm_input_uxkb.c
|
||||||
else
|
|
||||||
libuterm_la_SOURCES += \
|
|
||||||
src/uterm_input_dumb.c \
|
|
||||||
external/imKStoUCS.h \
|
|
||||||
external/imKStoUCS.c
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
include_HEADERS += \
|
include_HEADERS += \
|
||||||
|
@ -336,7 +336,8 @@ if test ! x$enable_xkbcommon = xno ; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if test x$xkbcommon_enabled = xyes ; then
|
if test x$xkbcommon_enabled = xyes ; then
|
||||||
test # dummy
|
AC_DEFINE([UTERM_HAVE_XKBCOMMON], [1],
|
||||||
|
[Use xkbcommon as input keyboard handling backend])
|
||||||
else
|
else
|
||||||
XKBCOMMON_CFLAGS=""
|
XKBCOMMON_CFLAGS=""
|
||||||
XKBCOMMON_LIBS=""
|
XKBCOMMON_LIBS=""
|
||||||
|
@ -182,8 +182,10 @@ static void seat_add_video(struct kmscon_seat *seat,
|
|||||||
|
|
||||||
ret = kmscon_ui_new(&seat->ui, seat->app->eloop, seat->video,
|
ret = kmscon_ui_new(&seat->ui, seat->app->eloop, seat->video,
|
||||||
seat->input);
|
seat->input);
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
log_error("cannot create UI object");
|
||||||
goto err_video;
|
goto err_video;
|
||||||
|
}
|
||||||
|
|
||||||
seat->vdev = dev;
|
seat->vdev = dev;
|
||||||
log_debug("new graphics device on seat %s", seat->sname);
|
log_debug("new graphics device on seat %s", seat->sname);
|
||||||
|
@ -88,7 +88,7 @@ static void notify_key(struct uterm_input_dev *dev,
|
|||||||
if (type != EV_KEY)
|
if (type != EV_KEY)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ret = kbd_dev_process_key(dev->kbd, value, code, &ev);
|
ret = kbd_dev_process(dev->kbd, value, code, &ev);
|
||||||
if (ret)
|
if (ret)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -200,7 +200,7 @@ static void input_new_dev(struct uterm_input *input,
|
|||||||
if (!dev->node)
|
if (!dev->node)
|
||||||
goto err_free;
|
goto err_free;
|
||||||
|
|
||||||
ret = kbd_dev_new(&dev->kbd, input->desc);
|
ret = kbd_desc_alloc(input->desc, &dev->kbd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_node;
|
goto err_node;
|
||||||
|
|
||||||
@ -254,11 +254,22 @@ int uterm_input_new(struct uterm_input **out,
|
|||||||
goto err_free;
|
goto err_free;
|
||||||
|
|
||||||
ret = kbd_desc_new(&input->desc,
|
ret = kbd_desc_new(&input->desc,
|
||||||
conf_global.xkb_layout,
|
conf_global.xkb_layout,
|
||||||
conf_global.xkb_variant,
|
conf_global.xkb_variant,
|
||||||
conf_global.xkb_options);
|
conf_global.xkb_options,
|
||||||
if (ret)
|
KBD_UXKB);
|
||||||
|
if (ret == -EOPNOTSUPP) {
|
||||||
|
log_info("XKB keyboard backend not available, trying plain backend");
|
||||||
|
ret = kbd_desc_new(&input->desc,
|
||||||
|
conf_global.xkb_layout,
|
||||||
|
conf_global.xkb_variant,
|
||||||
|
conf_global.xkb_options,
|
||||||
|
KBD_PLAIN);
|
||||||
|
if (ret)
|
||||||
|
goto err_hook;
|
||||||
|
} else if (ret) {
|
||||||
goto err_hook;
|
goto err_hook;
|
||||||
|
}
|
||||||
|
|
||||||
log_debug("new object %p", input);
|
log_debug("new object %p", input);
|
||||||
ev_eloop_ref(input->eloop);
|
ev_eloop_ref(input->eloop);
|
||||||
|
@ -47,12 +47,7 @@
|
|||||||
#include "uterm.h"
|
#include "uterm.h"
|
||||||
#include "uterm_internal.h"
|
#include "uterm_internal.h"
|
||||||
|
|
||||||
#define LOG_SUBSYSTEM "input_dumb"
|
#define LOG_SUBSYSTEM "input_plain"
|
||||||
|
|
||||||
struct kbd_dev {
|
|
||||||
unsigned long ref;
|
|
||||||
unsigned int mods;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These tables do not contain all possible keys from linux/input.h.
|
* These tables do not contain all possible keys from linux/input.h.
|
||||||
@ -284,21 +279,7 @@ static const struct {
|
|||||||
[KEY_RIGHTMETA] = { UTERM_MOD4_MASK, MOD_NORMAL },
|
[KEY_RIGHTMETA] = { UTERM_MOD4_MASK, MOD_NORMAL },
|
||||||
};
|
};
|
||||||
|
|
||||||
int kbd_dev_new(struct kbd_dev **out, struct kbd_desc *desc)
|
static void plain_dev_ref(struct kbd_dev *kbd)
|
||||||
{
|
|
||||||
struct kbd_dev *kbd;
|
|
||||||
|
|
||||||
kbd = malloc(sizeof(*kbd));
|
|
||||||
if (!kbd)
|
|
||||||
return -ENOMEM;
|
|
||||||
memset(kbd, 0, sizeof(*kbd));
|
|
||||||
kbd->ref = 1;
|
|
||||||
|
|
||||||
*out = kbd;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void kbd_dev_ref(struct kbd_dev *kbd)
|
|
||||||
{
|
{
|
||||||
if (!kbd || !kbd->ref)
|
if (!kbd || !kbd->ref)
|
||||||
return;
|
return;
|
||||||
@ -306,7 +287,7 @@ void kbd_dev_ref(struct kbd_dev *kbd)
|
|||||||
++kbd->ref;
|
++kbd->ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
void kbd_dev_unref(struct kbd_dev *kbd)
|
static void plain_dev_unref(struct kbd_dev *kbd)
|
||||||
{
|
{
|
||||||
if (!kbd || !kbd->ref || --kbd->ref)
|
if (!kbd || !kbd->ref || --kbd->ref)
|
||||||
return;
|
return;
|
||||||
@ -314,23 +295,23 @@ void kbd_dev_unref(struct kbd_dev *kbd)
|
|||||||
free(kbd);
|
free(kbd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kbd_dev_reset(struct kbd_dev *kbd, const unsigned long *ledbits)
|
static void plain_dev_reset(struct kbd_dev *kbd, const unsigned long *ledbits)
|
||||||
{
|
{
|
||||||
if (!kbd)
|
if (!kbd)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
kbd->mods = 0;
|
kbd->plain.mods = 0;
|
||||||
|
|
||||||
if (input_bit_is_set(ledbits, LED_NUML))
|
if (input_bit_is_set(ledbits, LED_NUML))
|
||||||
kbd->mods |= UTERM_MOD2_MASK;
|
kbd->plain.mods |= UTERM_MOD2_MASK;
|
||||||
if (input_bit_is_set(ledbits, LED_CAPSL))
|
if (input_bit_is_set(ledbits, LED_CAPSL))
|
||||||
kbd->mods |= UTERM_LOCK_MASK;
|
kbd->plain.mods |= UTERM_LOCK_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kbd_dev_process_key(struct kbd_dev *kbd,
|
static int plain_dev_process(struct kbd_dev *kbd,
|
||||||
uint16_t key_state,
|
uint16_t key_state,
|
||||||
uint16_t code,
|
uint16_t code,
|
||||||
struct uterm_input_event *out)
|
struct uterm_input_event *out)
|
||||||
{
|
{
|
||||||
uint32_t keysym;
|
uint32_t keysym;
|
||||||
unsigned int mod;
|
unsigned int mod;
|
||||||
@ -353,12 +334,12 @@ int kbd_dev_process_key(struct kbd_dev *kbd,
|
|||||||
*/
|
*/
|
||||||
if (key_state == 1) {
|
if (key_state == 1) {
|
||||||
if (mod_type == MOD_NORMAL)
|
if (mod_type == MOD_NORMAL)
|
||||||
kbd->mods |= mod;
|
kbd->plain.mods |= mod;
|
||||||
else if (mod_type == MOD_LOCK)
|
else if (mod_type == MOD_LOCK)
|
||||||
kbd->mods ^= mod;
|
kbd->plain.mods ^= mod;
|
||||||
} else if (key_state == 0) {
|
} else if (key_state == 0) {
|
||||||
if (mod_type == MOD_NORMAL)
|
if (mod_type == MOD_NORMAL)
|
||||||
kbd->mods &= ~mod;
|
kbd->plain.mods &= ~mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't deliver events purely for modifiers. */
|
/* Don't deliver events purely for modifiers. */
|
||||||
@ -370,11 +351,11 @@ int kbd_dev_process_key(struct kbd_dev *kbd,
|
|||||||
|
|
||||||
keysym = 0;
|
keysym = 0;
|
||||||
|
|
||||||
if (!keysym && kbd->mods & UTERM_MOD2_MASK)
|
if (!keysym && kbd->plain.mods & UTERM_MOD2_MASK)
|
||||||
keysym = keytab_numlock[code];
|
keysym = keytab_numlock[code];
|
||||||
if (!keysym && kbd->mods & UTERM_SHIFT_MASK)
|
if (!keysym && kbd->plain.mods & UTERM_SHIFT_MASK)
|
||||||
keysym = keytab_shift[code];
|
keysym = keytab_shift[code];
|
||||||
if (!keysym && kbd->mods & UTERM_LOCK_MASK)
|
if (!keysym && kbd->plain.mods & UTERM_LOCK_MASK)
|
||||||
keysym = keytab_capslock[code];
|
keysym = keytab_capslock[code];
|
||||||
if (!keysym)
|
if (!keysym)
|
||||||
keysym = keytab_normal[code];
|
keysym = keytab_normal[code];
|
||||||
@ -385,34 +366,81 @@ int kbd_dev_process_key(struct kbd_dev *kbd,
|
|||||||
out->keycode = code;
|
out->keycode = code;
|
||||||
out->keysym = keysym;
|
out->keysym = keysym;
|
||||||
out->unicode = KeysymToUcs4(keysym) ?: UTERM_INPUT_INVALID;
|
out->unicode = KeysymToUcs4(keysym) ?: UTERM_INPUT_INVALID;
|
||||||
out->mods = kbd->mods;
|
out->mods = kbd->plain.mods;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kbd_desc_new(struct kbd_desc **out,
|
static int plain_desc_init(struct kbd_desc **out,
|
||||||
const char *layout,
|
const char *layout,
|
||||||
const char *variant,
|
const char *variant,
|
||||||
const char *options)
|
const char *options)
|
||||||
{
|
{
|
||||||
|
struct kbd_desc *desc;
|
||||||
|
|
||||||
if (!out)
|
if (!out)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
desc = malloc(sizeof(*desc));
|
||||||
|
if (!desc)
|
||||||
|
return -ENOMEM;
|
||||||
|
memset(desc, 0, sizeof(*desc));
|
||||||
|
desc->ops = &plain_desc_ops;
|
||||||
|
|
||||||
log_debug("new keyboard description (%s, %s, %s)",
|
log_debug("new keyboard description (%s, %s, %s)",
|
||||||
layout, variant, options);
|
layout, variant, options);
|
||||||
*out = NULL;
|
*out = desc;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void kbd_desc_ref(struct kbd_desc *desc)
|
static void plain_desc_ref(struct kbd_desc *desc)
|
||||||
{
|
{
|
||||||
|
if (!desc || !desc->ref)
|
||||||
|
return;
|
||||||
|
|
||||||
|
++desc->ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
void kbd_desc_unref(struct kbd_desc *desc)
|
static void plain_desc_unref(struct kbd_desc *desc)
|
||||||
{
|
{
|
||||||
|
if (!desc || !desc->ref || --desc->ref)
|
||||||
|
return;
|
||||||
|
|
||||||
|
log_debug("destroying keyboard description");
|
||||||
|
free(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kbd_keysym_to_string(uint32_t keysym, char *str, size_t size)
|
static int plain_desc_alloc(struct kbd_desc *desc, struct kbd_dev **out)
|
||||||
|
{
|
||||||
|
struct kbd_dev *kbd;
|
||||||
|
|
||||||
|
kbd = malloc(sizeof(*kbd));
|
||||||
|
if (!kbd)
|
||||||
|
return -ENOMEM;
|
||||||
|
memset(kbd, 0, sizeof(*kbd));
|
||||||
|
kbd->ref = 1;
|
||||||
|
kbd->ops = &plain_dev_ops;
|
||||||
|
|
||||||
|
*out = kbd;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void plain_keysym_to_string(uint32_t keysym, char *str, size_t size)
|
||||||
{
|
{
|
||||||
snprintf(str, size, "%#x", keysym);
|
snprintf(str, size, "%#x", keysym);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const struct kbd_desc_ops plain_desc_ops = {
|
||||||
|
.init = plain_desc_init,
|
||||||
|
.ref = plain_desc_ref,
|
||||||
|
.unref = plain_desc_unref,
|
||||||
|
.alloc = plain_desc_alloc,
|
||||||
|
.keysym_to_string = plain_keysym_to_string,
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct kbd_dev_ops plain_dev_ops = {
|
||||||
|
.ref = plain_dev_ref,
|
||||||
|
.unref = plain_dev_unref,
|
||||||
|
.reset = plain_dev_reset,
|
||||||
|
.process = plain_dev_process,
|
||||||
|
};
|
@ -35,44 +35,9 @@
|
|||||||
#include "uterm.h"
|
#include "uterm.h"
|
||||||
#include "uterm_internal.h"
|
#include "uterm_internal.h"
|
||||||
|
|
||||||
#define LOG_SUBSYSTEM "input_xkb"
|
#define LOG_SUBSYSTEM "input_uxkb"
|
||||||
|
|
||||||
struct kbd_desc {
|
static void uxkb_dev_ref(struct kbd_dev *kbd)
|
||||||
unsigned long ref;
|
|
||||||
struct xkb_context *ctx;
|
|
||||||
struct xkb_keymap *keymap;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct kbd_dev {
|
|
||||||
unsigned long ref;
|
|
||||||
struct kbd_desc *desc;
|
|
||||||
struct xkb_state *state;
|
|
||||||
};
|
|
||||||
|
|
||||||
int kbd_dev_new(struct kbd_dev **out, struct kbd_desc *desc)
|
|
||||||
{
|
|
||||||
struct kbd_dev *kbd;
|
|
||||||
|
|
||||||
kbd = malloc(sizeof(*kbd));
|
|
||||||
if (!kbd)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
memset(kbd, 0, sizeof(*kbd));
|
|
||||||
kbd->ref = 1;
|
|
||||||
kbd->desc = desc;
|
|
||||||
|
|
||||||
kbd->state = xkb_state_new(desc->keymap);
|
|
||||||
if (!kbd->state) {
|
|
||||||
free(kbd);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
kbd_desc_ref(desc);
|
|
||||||
*out = kbd;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void kbd_dev_ref(struct kbd_dev *kbd)
|
|
||||||
{
|
{
|
||||||
if (!kbd || !kbd->ref)
|
if (!kbd || !kbd->ref)
|
||||||
return;
|
return;
|
||||||
@ -80,12 +45,12 @@ void kbd_dev_ref(struct kbd_dev *kbd)
|
|||||||
++kbd->ref;
|
++kbd->ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
void kbd_dev_unref(struct kbd_dev *kbd)
|
static void uxkb_dev_unref(struct kbd_dev *kbd)
|
||||||
{
|
{
|
||||||
if (!kbd || !kbd->ref || --kbd->ref)
|
if (!kbd || !kbd->ref || --kbd->ref)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
xkb_state_unref(kbd->state);
|
xkb_state_unref(kbd->uxkb.state);
|
||||||
kbd_desc_unref(kbd->desc);
|
kbd_desc_unref(kbd->desc);
|
||||||
free(kbd);
|
free(kbd);
|
||||||
}
|
}
|
||||||
@ -120,10 +85,10 @@ static unsigned int get_effective_modmask(struct xkb_state *state)
|
|||||||
return mods;
|
return mods;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kbd_dev_process_key(struct kbd_dev *kbd,
|
static int uxkb_dev_process(struct kbd_dev *kbd,
|
||||||
uint16_t key_state,
|
uint16_t key_state,
|
||||||
uint16_t code,
|
uint16_t code,
|
||||||
struct uterm_input_event *out)
|
struct uterm_input_event *out)
|
||||||
{
|
{
|
||||||
struct xkb_state *state;
|
struct xkb_state *state;
|
||||||
struct xkb_keymap *keymap;
|
struct xkb_keymap *keymap;
|
||||||
@ -134,7 +99,7 @@ int kbd_dev_process_key(struct kbd_dev *kbd,
|
|||||||
if (!kbd)
|
if (!kbd)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
state = kbd->state;
|
state = kbd->uxkb.state;
|
||||||
keymap = xkb_state_get_map(state);
|
keymap = xkb_state_get_map(state);
|
||||||
keycode = code + EVDEV_KEYCODE_OFFSET;
|
keycode = code + EVDEV_KEYCODE_OFFSET;
|
||||||
|
|
||||||
@ -161,8 +126,8 @@ int kbd_dev_process_key(struct kbd_dev *kbd,
|
|||||||
*/
|
*/
|
||||||
out->keycode = code;
|
out->keycode = code;
|
||||||
out->keysym = keysyms[0];
|
out->keysym = keysyms[0];
|
||||||
out->mods = get_effective_modmask(state);;
|
out->mods = get_effective_modmask(state);
|
||||||
out->unicode = xkb_keysym_to_utf32(out->keysym) ?: UTERM_INPUT_INVALID;
|
out->unicode = xkb_keysym_to_utf32(out->keysym) ? : UTERM_INPUT_INVALID;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -172,7 +137,7 @@ int kbd_dev_process_key(struct kbd_dev *kbd,
|
|||||||
* We don't reset the locked group, this should survive a VT switch, etc. The
|
* We don't reset the locked group, this should survive a VT switch, etc. The
|
||||||
* locked modifiers are reset according to the keyboard LEDs.
|
* locked modifiers are reset according to the keyboard LEDs.
|
||||||
*/
|
*/
|
||||||
void kbd_dev_reset(struct kbd_dev *kbd, const unsigned long *ledbits)
|
static void uxkb_dev_reset(struct kbd_dev *kbd, const unsigned long *ledbits)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
struct xkb_state *state;
|
struct xkb_state *state;
|
||||||
@ -188,7 +153,7 @@ void kbd_dev_reset(struct kbd_dev *kbd, const unsigned long *ledbits)
|
|||||||
if (!kbd)
|
if (!kbd)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
state = kbd->state;
|
state = kbd->uxkb.state;
|
||||||
|
|
||||||
for (i = 0; i < sizeof(led_names) / sizeof(*led_names); i++) {
|
for (i = 0; i < sizeof(led_names) / sizeof(*led_names); i++) {
|
||||||
if (!input_bit_is_set(ledbits, led_names[i].led))
|
if (!input_bit_is_set(ledbits, led_names[i].led))
|
||||||
@ -205,10 +170,10 @@ void kbd_dev_reset(struct kbd_dev *kbd, const unsigned long *ledbits)
|
|||||||
(void)state;
|
(void)state;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kbd_desc_new(struct kbd_desc **out,
|
static int uxkb_desc_init(struct kbd_desc **out,
|
||||||
const char *layout,
|
const char *layout,
|
||||||
const char *variant,
|
const char *variant,
|
||||||
const char *options)
|
const char *options)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct kbd_desc *desc;
|
struct kbd_desc *desc;
|
||||||
@ -229,15 +194,16 @@ int kbd_desc_new(struct kbd_desc **out,
|
|||||||
|
|
||||||
memset(desc, 0, sizeof(*desc));
|
memset(desc, 0, sizeof(*desc));
|
||||||
desc->ref = 1;
|
desc->ref = 1;
|
||||||
|
desc->ops = &uxkb_desc_ops;
|
||||||
|
|
||||||
desc->ctx = xkb_context_new(0);
|
desc->uxkb.ctx = xkb_context_new(0);
|
||||||
if (!desc->ctx) {
|
if (!desc->uxkb.ctx) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto err_desc;
|
goto err_desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
desc->keymap = xkb_map_new_from_names(desc->ctx, &rmlvo, 0);
|
desc->uxkb.keymap = xkb_map_new_from_names(desc->uxkb.ctx, &rmlvo, 0);
|
||||||
if (!desc->keymap) {
|
if (!desc->uxkb.keymap) {
|
||||||
log_warn("failed to create keymap (%s, %s, %s), "
|
log_warn("failed to create keymap (%s, %s, %s), "
|
||||||
"reverting to default US keymap",
|
"reverting to default US keymap",
|
||||||
layout, variant, options);
|
layout, variant, options);
|
||||||
@ -246,8 +212,9 @@ int kbd_desc_new(struct kbd_desc **out,
|
|||||||
rmlvo.variant = "";
|
rmlvo.variant = "";
|
||||||
rmlvo.options = "";
|
rmlvo.options = "";
|
||||||
|
|
||||||
desc->keymap = xkb_map_new_from_names(desc->ctx, &rmlvo, 0);
|
desc->uxkb.keymap = xkb_map_new_from_names(desc->uxkb.ctx,
|
||||||
if (!desc->keymap) {
|
&rmlvo, 0);
|
||||||
|
if (!desc->uxkb.keymap) {
|
||||||
log_warn("failed to create keymap");
|
log_warn("failed to create keymap");
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto err_ctx;
|
goto err_ctx;
|
||||||
@ -260,13 +227,13 @@ int kbd_desc_new(struct kbd_desc **out,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_ctx:
|
err_ctx:
|
||||||
xkb_context_unref(desc->ctx);
|
xkb_context_unref(desc->uxkb.ctx);
|
||||||
err_desc:
|
err_desc:
|
||||||
free(desc);
|
free(desc);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void kbd_desc_ref(struct kbd_desc *desc)
|
static void uxkb_desc_ref(struct kbd_desc *desc)
|
||||||
{
|
{
|
||||||
if (!desc || !desc->ref)
|
if (!desc || !desc->ref)
|
||||||
return;
|
return;
|
||||||
@ -274,18 +241,57 @@ void kbd_desc_ref(struct kbd_desc *desc)
|
|||||||
++desc->ref;
|
++desc->ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
void kbd_desc_unref(struct kbd_desc *desc)
|
static void uxkb_desc_unref(struct kbd_desc *desc)
|
||||||
{
|
{
|
||||||
if (!desc || !desc->ref || --desc->ref)
|
if (!desc || !desc->ref || --desc->ref)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
log_debug("destroying keyboard description");
|
log_debug("destroying keyboard description");
|
||||||
xkb_map_unref(desc->keymap);
|
xkb_map_unref(desc->uxkb.keymap);
|
||||||
xkb_context_unref(desc->ctx);
|
xkb_context_unref(desc->uxkb.ctx);
|
||||||
free(desc);
|
free(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kbd_keysym_to_string(uint32_t keysym, char *str, size_t size)
|
static int uxkb_desc_alloc(struct kbd_desc *desc, struct kbd_dev **out)
|
||||||
|
{
|
||||||
|
struct kbd_dev *kbd;
|
||||||
|
|
||||||
|
kbd = malloc(sizeof(*kbd));
|
||||||
|
if (!kbd)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
memset(kbd, 0, sizeof(*kbd));
|
||||||
|
kbd->ref = 1;
|
||||||
|
kbd->desc = desc;
|
||||||
|
kbd->ops = &uxkb_dev_ops;
|
||||||
|
|
||||||
|
kbd->uxkb.state = xkb_state_new(desc->uxkb.keymap);
|
||||||
|
if (!kbd->uxkb.state) {
|
||||||
|
free(kbd);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
kbd_desc_ref(desc);
|
||||||
|
*out = kbd;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uxkb_keysym_to_string(uint32_t keysym, char *str, size_t size)
|
||||||
{
|
{
|
||||||
xkb_keysym_get_name(keysym, str, size);
|
xkb_keysym_get_name(keysym, str, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const struct kbd_desc_ops uxkb_desc_ops = {
|
||||||
|
.init = uxkb_desc_init,
|
||||||
|
.ref = uxkb_desc_ref,
|
||||||
|
.unref = uxkb_desc_unref,
|
||||||
|
.alloc = uxkb_desc_alloc,
|
||||||
|
.keysym_to_string = uxkb_keysym_to_string,
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct kbd_dev_ops uxkb_dev_ops = {
|
||||||
|
.ref = uxkb_dev_ref,
|
||||||
|
.unref = uxkb_dev_unref,
|
||||||
|
.reset = uxkb_dev_reset,
|
||||||
|
.process = uxkb_dev_process,
|
||||||
|
};
|
@ -372,37 +372,189 @@ static inline bool input_bit_is_set(const unsigned long *array, int bit)
|
|||||||
struct kbd_desc;
|
struct kbd_desc;
|
||||||
struct kbd_dev;
|
struct kbd_dev;
|
||||||
|
|
||||||
int kbd_desc_new(struct kbd_desc **out,
|
struct kbd_desc_ops {
|
||||||
const char *layout,
|
int (*init) (struct kbd_desc **out, const char *layout,
|
||||||
const char *variant,
|
const char *variant, const char *options);
|
||||||
const char *options);
|
void (*ref) (struct kbd_desc *desc);
|
||||||
void kbd_desc_ref(struct kbd_desc *desc);
|
void (*unref) (struct kbd_desc *desc);
|
||||||
void kbd_desc_unref(struct kbd_desc *desc);
|
int (*alloc) (struct kbd_desc *desc, struct kbd_dev **out);
|
||||||
|
void (*keysym_to_string) (uint32_t keysym, char *str, size_t size);
|
||||||
|
};
|
||||||
|
|
||||||
int kbd_dev_new(struct kbd_dev **out, struct kbd_desc *desc);
|
struct kbd_dev_ops {
|
||||||
void kbd_dev_ref(struct kbd_dev *state);
|
void (*ref) (struct kbd_dev *dev);
|
||||||
void kbd_dev_unref(struct kbd_dev *state);
|
void (*unref) (struct kbd_dev *dev);
|
||||||
|
void (*reset) (struct kbd_dev *dev, const unsigned long *ledbits);
|
||||||
/*
|
int (*process) (struct kbd_dev *dev, uint16_t state, uint16_t code,
|
||||||
* This resets the keyboard state in case it got out of sync. It's mainly used
|
|
||||||
* to sync our notion of the keyboard state with what the keyboard LEDs show.
|
|
||||||
*/
|
|
||||||
void kbd_dev_reset(struct kbd_dev *kbd, const unsigned long *ledbits);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is the entry point to the keyboard processing.
|
|
||||||
* We get an evdev scancode and the keyboard state, and should put out a
|
|
||||||
* proper input event.
|
|
||||||
* Some evdev input events shouldn't result in us sending an input event
|
|
||||||
* (e.g. a key release):
|
|
||||||
* - If the event was filled out, 0 is returned.
|
|
||||||
* - Otherwise, if there was no error, -ENOKEY is returned.
|
|
||||||
*/
|
|
||||||
int kbd_dev_process_key(struct kbd_dev *kbd,
|
|
||||||
uint16_t key_state,
|
|
||||||
uint16_t code,
|
|
||||||
struct uterm_input_event *out);
|
struct uterm_input_event *out);
|
||||||
|
};
|
||||||
|
|
||||||
void kbd_dev_keysym_to_string(uint32_t keysym, char *str, size_t size);
|
struct plain_desc {
|
||||||
|
int unused;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct plain_dev {
|
||||||
|
unsigned int mods;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const bool plain_available = true;
|
||||||
|
extern const struct kbd_desc_ops plain_desc_ops;
|
||||||
|
extern const struct kbd_dev_ops plain_dev_ops;
|
||||||
|
|
||||||
|
#ifdef UTERM_HAVE_XKBCOMMON
|
||||||
|
|
||||||
|
struct uxkb_desc {
|
||||||
|
struct xkb_context *ctx;
|
||||||
|
struct xkb_keymap *keymap;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct uxkb_dev {
|
||||||
|
struct xkb_state *state;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const bool uxkb_available = true;
|
||||||
|
extern const struct kbd_desc_ops uxkb_desc_ops;
|
||||||
|
extern const struct kbd_dev_ops uxkb_dev_ops;
|
||||||
|
|
||||||
|
#else /* !UTERM_HAVE_XKBCOMMON */
|
||||||
|
|
||||||
|
struct uxkb_desc {
|
||||||
|
int unused;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct uxkb_dev {
|
||||||
|
int unused;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const bool xkb_available = false;
|
||||||
|
static const struct kbd_desc_ops uxkb_desc_ops;
|
||||||
|
static const struct kbd_dev_ops uxkb_dev_ops;
|
||||||
|
|
||||||
|
#endif /* UTERM_HAVE_XKBCOMMON */
|
||||||
|
|
||||||
|
struct kbd_desc {
|
||||||
|
unsigned long ref;
|
||||||
|
const struct kbd_desc_ops *ops;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct plain_desc plain;
|
||||||
|
struct uxkb_desc uxkb;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct kbd_dev {
|
||||||
|
unsigned long ref;
|
||||||
|
struct kbd_desc *desc;
|
||||||
|
const struct kbd_dev_ops *ops;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct plain_dev plain;
|
||||||
|
struct uxkb_dev uxkb;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
enum kbd_mode {
|
||||||
|
KBD_PLAIN,
|
||||||
|
KBD_UXKB,
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline int kbd_desc_new(struct kbd_desc **out, const char *layout,
|
||||||
|
const char *variant, const char *options,
|
||||||
|
unsigned int mode)
|
||||||
|
{
|
||||||
|
const struct kbd_desc_ops *ops;
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case KBD_UXKB:
|
||||||
|
if (!uxkb_available) {
|
||||||
|
log_error("XKB KBD backend not available");
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
ops = &uxkb_desc_ops;
|
||||||
|
break;
|
||||||
|
case KBD_PLAIN:
|
||||||
|
if (!plain_available) {
|
||||||
|
log_error("plain KBD backend not available");
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
ops = &plain_desc_ops;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
log_error("unknown KBD backend %u", mode);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ops->init(out, layout, variant, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void kbd_desc_ref(struct kbd_desc *desc)
|
||||||
|
{
|
||||||
|
if (!desc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
return desc->ops->ref(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void kbd_desc_unref(struct kbd_desc *desc)
|
||||||
|
{
|
||||||
|
if (!desc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
return desc->ops->unref(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int kbd_desc_alloc(struct kbd_desc *desc, struct kbd_dev **out)
|
||||||
|
{
|
||||||
|
if (!desc)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return desc->ops->alloc(desc, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void kbd_desc_keysym_to_string(struct kbd_desc *desc,
|
||||||
|
uint32_t keysym,
|
||||||
|
char *str, size_t size)
|
||||||
|
{
|
||||||
|
if (!desc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
return desc->ops->keysym_to_string(keysym, str, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void kbd_dev_ref(struct kbd_dev *dev)
|
||||||
|
{
|
||||||
|
if (!dev)
|
||||||
|
return;
|
||||||
|
|
||||||
|
return dev->ops->ref(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void kbd_dev_unref(struct kbd_dev *dev)
|
||||||
|
{
|
||||||
|
if (!dev)
|
||||||
|
return;
|
||||||
|
|
||||||
|
return dev->ops->unref(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void kbd_dev_reset(struct kbd_dev *dev,
|
||||||
|
const unsigned long *ledbits)
|
||||||
|
{
|
||||||
|
if (!dev)
|
||||||
|
return;
|
||||||
|
|
||||||
|
return dev->ops->reset(dev, ledbits);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int kbd_dev_process(struct kbd_dev *dev,
|
||||||
|
uint16_t key_state,
|
||||||
|
uint16_t code,
|
||||||
|
struct uterm_input_event *out)
|
||||||
|
{
|
||||||
|
if (!dev)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return dev->ops->process(dev, key_state, code, out);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* UTERM_INTERNAL_H */
|
#endif /* UTERM_INTERNAL_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user