uterm: input: add support for multiple keysyms

xkbcommon supports reporting multiple keysyms per key-event. There is no
keymap which uses this, yet. However, this feature is not meant to enhance
performance by reducing the number of calls into xkb, but instead multiple
keysyms are to be handled as one big keysym.
But there are no examples, yet, so we cannot actually perform any
conversions on them. But we can add the infrastructure for it.

Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
This commit is contained in:
David Herrmann 2012-10-09 11:19:30 +02:00
parent fba4b9104b
commit 0a03785ffc
6 changed files with 78 additions and 35 deletions

View File

@ -359,36 +359,42 @@ static void input_event(struct uterm_input *input,
return;
if (UTERM_INPUT_HAS_MODS(ev, kmscon_conf.grab_scroll_up->mods) &&
ev->keysym == kmscon_conf.grab_scroll_up->keysym) {
ev->keysyms[0] == kmscon_conf.grab_scroll_up->keysym) {
tsm_screen_sb_up(term->console, 1);
schedule_redraw(term);
ev->handled = true;
return;
}
if (UTERM_INPUT_HAS_MODS(ev, kmscon_conf.grab_scroll_down->mods) &&
ev->keysym == kmscon_conf.grab_scroll_down->keysym) {
ev->keysyms[0] == kmscon_conf.grab_scroll_down->keysym) {
tsm_screen_sb_down(term->console, 1);
schedule_redraw(term);
ev->handled = true;
return;
}
if (UTERM_INPUT_HAS_MODS(ev, kmscon_conf.grab_page_up->mods) &&
ev->keysym == kmscon_conf.grab_page_up->keysym) {
ev->keysyms[0] == kmscon_conf.grab_page_up->keysym) {
tsm_screen_sb_page_up(term->console, 1);
schedule_redraw(term);
ev->handled = true;
return;
}
if (UTERM_INPUT_HAS_MODS(ev, kmscon_conf.grab_page_down->mods) &&
ev->keysym == kmscon_conf.grab_page_down->keysym) {
ev->keysyms[0] == kmscon_conf.grab_page_down->keysym) {
tsm_screen_sb_page_down(term->console, 1);
schedule_redraw(term);
ev->handled = true;
return;
}
if (tsm_vte_handle_keyboard(term->vte, ev->keysym, ev->mods,
ev->unicode)) {
/* TODO: xkbcommon supports multiple keysyms, but it is currently
* unclear how this feature will be used. There is no keymap, which
* uses this, yet. */
if (ev->num_syms > 1)
return;
if (tsm_vte_handle_keyboard(term->vte, ev->keysyms[0], ev->mods,
ev->codepoints[0])) {
tsm_screen_sb_reset(term->console);
schedule_redraw(term);
ev->handled = true;

View File

@ -269,11 +269,13 @@ enum uterm_input_modifier {
#define UTERM_INPUT_INVALID 0xffffffff
struct uterm_input_event {
bool handled;
bool handled; /* user-controlled, default is false */
uint16_t keycode; /* linux keycode - KEY_* - linux/input.h */
uint32_t keysym; /* X keysym - XKB_KEY_* - X11/keysym.h */
unsigned int mods; /* active modifiers - uterm_modifier mask */
uint32_t unicode; /* ucs4 unicode value or UTERM_INPUT_INVALID */
unsigned int num_syms; /* number of keysyms */
uint32_t *keysyms; /* XKB-common keysym-array - XKB_KEY_* */
uint32_t *codepoints; /* ucs4 unicode value or UTERM_INPUT_INVALID */
};
#define UTERM_INPUT_HAS_MODS(_ev, _mods) (((_ev)->mods & (_mods)) == (_mods))

View File

@ -61,17 +61,15 @@ static void notify_key(struct uterm_input_dev *dev,
int32_t value)
{
int ret;
struct uterm_input_event ev;
if (type != EV_KEY)
return;
memset(&ev, 0, sizeof(ev));
ret = uxkb_dev_process(dev, value, code, &ev);
ret = uxkb_dev_process(dev, value, code);
if (ret)
return;
shl_hook_call(dev->input->hook, dev->input, &ev);
shl_hook_call(dev->input->hook, dev->input, &dev->event);
}
static void input_data_dev(struct ev_fd *fd, int mask, void *data)
@ -179,9 +177,17 @@ static void input_new_dev(struct uterm_input *input,
if (!dev->node)
goto err_free;
dev->num_syms = 1;
dev->event.keysyms = malloc(sizeof(uint32_t) * dev->num_syms);
if (!dev->event.keysyms)
goto err_node;
dev->event.codepoints = malloc(sizeof(uint32_t) * dev->num_syms);
if (!dev->event.codepoints)
goto err_syms;
ret = uxkb_dev_init(dev);
if (ret)
goto err_node;
goto err_codepoints;
if (input->awake > 0) {
ret = input_wake_up_dev(dev);
@ -195,6 +201,10 @@ static void input_new_dev(struct uterm_input *input,
err_kbd:
uxkb_dev_destroy(dev);
err_codepoints:
free(dev->event.codepoints);
err_syms:
free(dev->event.keysyms);
err_node:
free(dev->node);
err_free:
@ -207,6 +217,8 @@ static void input_free_dev(struct uterm_input_dev *dev)
input_sleep_dev(dev);
shl_dlist_unlink(&dev->list);
uxkb_dev_destroy(dev);
free(dev->event.codepoints);
free(dev->event.keysyms);
free(dev->node);
free(dev);
}

View File

@ -46,6 +46,9 @@ struct uterm_input_dev {
char *node;
struct ev_fd *fd;
struct xkb_state *state;
struct uterm_input_event event;
unsigned int num_syms;
};
struct uterm_input {
@ -75,8 +78,7 @@ int uxkb_dev_init(struct uterm_input_dev *dev);
void uxkb_dev_destroy(struct uterm_input_dev *dev);
int uxkb_dev_process(struct uterm_input_dev *dev,
uint16_t key_state,
uint16_t code,
struct uterm_input_event *out);
uint16_t code);
void uxkb_dev_reset(struct uterm_input_dev *dev, const unsigned long *ledbits);
#endif /* UTERM_INPUT_H */

View File

@ -113,15 +113,14 @@ enum {
};
int uxkb_dev_process(struct uterm_input_dev *dev,
uint16_t key_state,
uint16_t code,
struct uterm_input_event *out)
uint16_t key_state, uint16_t code)
{
struct xkb_state *state;
struct xkb_keymap *keymap;
xkb_keycode_t keycode;
const xkb_keysym_t *keysyms;
int num_keysyms;
int num_keysyms, i;
uint32_t *tmp;
state = dev->state;
keymap = xkb_state_get_map(state);
@ -143,15 +142,37 @@ int uxkb_dev_process(struct uterm_input_dev *dev,
if (num_keysyms <= 0)
return -ENOKEY;
/*
* TODO: xkbcommon actually supports multiple keysyms
* per key press. Here we're just using the first one,
* but we might want to support this feature.
*/
out->keycode = code;
out->keysym = keysyms[0];
out->mods = shl_get_xkb_mods(state);
out->unicode = xkb_keysym_to_utf32(out->keysym) ? : UTERM_INPUT_INVALID;
if (dev->num_syms < num_keysyms) {
tmp = realloc(dev->event.keysyms,
sizeof(uint32_t) * num_keysyms);
if (!tmp) {
log_warning("cannot reallocate keysym buffer");
return -ENOKEY;
}
dev->event.keysyms = tmp;
tmp = realloc(dev->event.codepoints,
sizeof(uint32_t) * num_keysyms);
if (!tmp) {
log_warning("cannot reallocate codepoints buffer");
return -ENOKEY;
}
dev->event.codepoints = tmp;
dev->num_syms = num_keysyms;
}
dev->event.handled = false;
dev->event.keycode = code;
dev->event.mods = shl_get_xkb_mods(state);
dev->event.num_syms = num_keysyms;
memcpy(dev->event.keysyms, keysyms, sizeof(uint32_t) * num_keysyms);
for (i = 0; i < num_keysyms; ++i) {
dev->event.codepoints[i] = xkb_keysym_to_utf32(keysyms[i]);
if (!dev->event.codepoints[i])
dev->event.codepoints[i] = UTERM_INPUT_INVALID;
}
return 0;
}

View File

@ -503,15 +503,15 @@ static void real_input(struct uterm_vt *vt, struct uterm_input_event *ev)
id = 0;
if (SHL_HAS_BITS(ev->mods, SHL_CONTROL_MASK | SHL_ALT_MASK) &&
ev->keysym >= XKB_KEY_F1 && ev->keysym <= XKB_KEY_F12) {
ev->keysyms[0] >= XKB_KEY_F1 && ev->keysyms[0] <= XKB_KEY_F12) {
ev->handled = true;
id = ev->keysym - XKB_KEY_F1 + 1;
id = ev->keysyms[0] - XKB_KEY_F1 + 1;
if (id == vt->real_num)
return;
} else if (ev->keysym >= XKB_KEY_XF86Switch_VT_1 &&
ev->keysym <= XKB_KEY_XF86Switch_VT_12) {
} else if (ev->keysyms[0] >= XKB_KEY_XF86Switch_VT_1 &&
ev->keysyms[0] <= XKB_KEY_XF86Switch_VT_12) {
ev->handled = true;
id = ev->keysym - XKB_KEY_XF86Switch_VT_1 + 1;
id = ev->keysyms[0] - XKB_KEY_XF86Switch_VT_1 + 1;
if (id == vt->real_num)
return;
}
@ -577,7 +577,7 @@ static void fake_input(struct uterm_vt *vt, struct uterm_input_event *ev)
return;
if (SHL_HAS_BITS(ev->mods, SHL_CONTROL_MASK | SHL_LOGO_MASK) &&
ev->keysym == XKB_KEY_F12) {
ev->keysyms[0] == XKB_KEY_F12) {
ev->handled = true;
if (vt->active) {
log_debug("deactivating fake VT due to user input");