diff --git a/src/conf.c b/src/conf.c index c69026a..87cac59 100644 --- a/src/conf.c +++ b/src/conf.c @@ -36,8 +36,10 @@ #include #include #include +#include #include "conf.h" #include "log.h" +#include "shl_misc.h" #define LOG_SUBSYSTEM "config" @@ -147,6 +149,84 @@ void conf_default_string_list(struct conf_option *opt) *(void**)opt->mem = opt->def; } +int conf_parse_grab(struct conf_option *opt, bool on, const char *arg) +{ + char *buf, *tmp, *start; + struct conf_grab grab, *gnew; + + memset(&grab, 0, sizeof(grab)); + + buf = strdup(arg); + if (!buf) + return -ENOMEM; + tmp = buf; + +next_mod: + if (*tmp == '<') { + start = tmp; + while (*tmp && *tmp != '>') + ++tmp; + + if (*tmp != '>') { + log_error("missing '>' in grab '%s' near '%s'", + arg, start); + goto err_free; + } + + *tmp++ = 0; + ++start; + if (!strcasecmp(start, "shift")) { + grab.mods |= SHL_SHIFT_MASK; + } else if (!strcasecmp(start, "lock")) { + grab.mods |= SHL_LOCK_MASK; + } else if (!strcasecmp(start, "control") || + !strcasecmp(start, "ctrl")) { + grab.mods |= SHL_CONTROL_MASK; + } else if (!strcasecmp(start, "alt")) { + grab.mods |= SHL_ALT_MASK; + } else if (!strcasecmp(start, "logo")) { + grab.mods |= SHL_LOGO_MASK; + } else { + log_error("invalid modifier '%s' in grab '%s'", + start, arg); + goto err_free; + } + + goto next_mod; + } + + if (!*tmp) { + log_error("missing key in grab '%s'", arg); + goto err_free; + } + + grab.keysym = xkb_keysym_from_name(tmp); + if (!grab.keysym) { + log_error("invalid key '%s' in grab '%s'", tmp, arg); + goto err_free; + } + + gnew = malloc(sizeof(*gnew)); + if (!gnew) + goto err_free; + memcpy(gnew, &grab, sizeof(*gnew)); + + opt->type->free(opt); + *(void**)opt->mem = gnew; + free(buf); + + return 0; + +err_free: + free(buf); + return -EFAULT; +} + +void conf_default_grab(struct conf_option *opt) +{ + *(void**)opt->mem = opt->def; +} + const struct conf_type conf_bool = { .flags = 0, .parse = conf_parse_bool, @@ -182,6 +262,13 @@ const struct conf_type conf_string_list = { .set_default = conf_default_string_list, }; +const struct conf_type conf_grab = { + .flags = CONF_HAS_ARG, + .parse = conf_parse_grab, + .free = conf_free_value, + .set_default = conf_default_grab, +}; + /* free all memory that we allocated and reset to initial state */ void conf_free(struct conf_option *opts, size_t len) { diff --git a/src/conf.h b/src/conf.h index 8643d36..3499ddf 100644 --- a/src/conf.h +++ b/src/conf.h @@ -36,6 +36,13 @@ #include #include +/* parsed types */ + +struct conf_grab { + unsigned int mods; + uint32_t keysym; +}; + /* configuration parser */ struct conf_type; @@ -108,6 +115,14 @@ struct conf_option { _aftercheck, \ _mem, \ _def) +#define CONF_OPTION_GRAB(_short, _long, _aftercheck, _mem, _def) \ + CONF_OPTION(0, \ + _short, \ + _long, \ + &conf_grab, \ + _aftercheck, \ + _mem, \ + _def) void conf_free_value(struct conf_option *opt); int conf_parse_bool(struct conf_option *opt, bool on, const char *arg); @@ -120,12 +135,15 @@ int conf_parse_string(struct conf_option *opt, bool on, const char *arg); void conf_default_string(struct conf_option *opt); int conf_parse_string_list(struct conf_option *opt, bool on, const char *arg); void conf_default_string_list(struct conf_option *opt); +int conf_parse_grab(struct conf_option *opt, bool on, const char *arg); +void conf_default_grab(struct conf_option *opt); extern const struct conf_type conf_bool; extern const struct conf_type conf_int; extern const struct conf_type conf_uint; extern const struct conf_type conf_string; extern const struct conf_type conf_string_list; +extern const struct conf_type conf_grab; void conf_free(struct conf_option *opts, size_t len); int conf_parse_argv(struct conf_option *opts, size_t len, diff --git a/src/main.c b/src/main.c index 7e1d1b4..c7736e3 100644 --- a/src/main.c +++ b/src/main.c @@ -31,7 +31,6 @@ #include #include #include -#include #include "conf.h" #include "eloop.h" #include "log.h" @@ -489,107 +488,6 @@ static void print_help() */ } -int conf_parse_grab(struct conf_option *opt, bool on, const char *arg) -{ - char *buf, *tmp, *start; - int ret; - struct uterm_input_grab grab, *gnew; - - memset(&grab, 0, sizeof(grab)); - - buf = strdup(arg); - if (!buf) - return -ENOMEM; - tmp = buf; - -next_mod: - if (*tmp == '<') { - start = tmp; - while (*tmp && *tmp != '>') - ++tmp; - - if (*tmp != '>') { - log_error("missing '>' in grab '%s' near '%s'", - arg, start); - goto err_free; - } - - *tmp++ = 0; - ++start; - if (!strcasecmp(start, "shift")) { - grab.mods |= UTERM_SHIFT_MASK; - } else if (!strcasecmp(start, "lock")) { - grab.mods |= UTERM_LOCK_MASK; - } else if (!strcasecmp(start, "control") || - !strcasecmp(start, "ctrl")) { - grab.mods |= UTERM_CONTROL_MASK; - } else if (!strcasecmp(start, "mod1")) { - grab.mods |= UTERM_MOD1_MASK; - } else if (!strcasecmp(start, "mod2")) { - grab.mods |= UTERM_MOD2_MASK; - } else if (!strcasecmp(start, "mod3")) { - grab.mods |= UTERM_MOD3_MASK; - } else if (!strcasecmp(start, "mod4")) { - grab.mods |= UTERM_MOD4_MASK; - } else if (!strcasecmp(start, "mod5")) { - grab.mods |= UTERM_MOD5_MASK; - } else { - log_error("invalid modifier '%s' in grab '%s'", - start, arg); - goto err_free; - } - - goto next_mod; - } - - if (!*tmp) { - log_error("missing key in grab '%s'", arg); - goto err_free; - } - - ret = uterm_input_string_to_keysym(NULL, tmp, &grab.keysym); - if (ret || !grab.keysym) { - log_error("invalid key '%s' in grab '%s'", tmp, arg); - goto err_free; - } - - gnew = malloc(sizeof(*gnew)); - if (!gnew) - goto err_free; - memcpy(gnew, &grab, sizeof(*gnew)); - - opt->type->free(opt); - *(void**)opt->mem = gnew; - free(buf); - - return 0; - -err_free: - free(buf); - return -EFAULT; -} - -void conf_default_grab(struct conf_option *opt) -{ - *(void**)opt->mem = opt->def; -} - -const struct conf_type conf_grab = { - .flags = CONF_HAS_ARG, - .parse = conf_parse_grab, - .free = conf_free_value, - .set_default = conf_default_grab, -}; - -#define CONF_OPTION_GRAB(_short, _long, _aftercheck, _mem, _def) \ - CONF_OPTION(0, \ - _short, \ - _long, \ - &conf_grab, \ - _aftercheck, \ - _mem, \ - _def) - int conf_parse_vt(struct conf_option *opt, bool on, const char *arg) { static const char prefix[] = "/dev/"; @@ -692,23 +590,23 @@ static int aftercheck_seats(struct conf_option *opt, int argc, char **argv, static char *def_seats[] = { "seat0", NULL }; -static struct uterm_input_grab def_grab_scroll_up = { - .mods = UTERM_SHIFT_MASK, +static struct conf_grab def_grab_scroll_up = { + .mods = SHL_SHIFT_MASK, .keysym = XKB_KEY_Up, }; -static struct uterm_input_grab def_grab_scroll_down = { - .mods = UTERM_SHIFT_MASK, +static struct conf_grab def_grab_scroll_down = { + .mods = SHL_SHIFT_MASK, .keysym = XKB_KEY_Down, }; -static struct uterm_input_grab def_grab_page_up = { - .mods = UTERM_SHIFT_MASK, +static struct conf_grab def_grab_page_up = { + .mods = SHL_SHIFT_MASK, .keysym = XKB_KEY_Prior, }; -static struct uterm_input_grab def_grab_page_down = { - .mods = UTERM_SHIFT_MASK, +static struct conf_grab def_grab_page_down = { + .mods = SHL_SHIFT_MASK, .keysym = XKB_KEY_Next, }; diff --git a/src/main.h b/src/main.h index 03cc549..ebb796d 100644 --- a/src/main.h +++ b/src/main.h @@ -33,7 +33,7 @@ #include #include -#include "uterm.h" +#include "conf.h" struct kmscon_conf_t { /* show help/usage information */ @@ -71,13 +71,13 @@ struct kmscon_conf_t { /* terminal scroll-back buffer size */ unsigned int sb_size; /* scroll-up grab */ - struct uterm_input_grab *grab_scroll_up; + struct conf_grab *grab_scroll_up; /* scroll-down grab */ - struct uterm_input_grab *grab_scroll_down; + struct conf_grab *grab_scroll_down; /* page-up grab */ - struct uterm_input_grab *grab_page_up; + struct conf_grab *grab_page_up; /* page-down grab */ - struct uterm_input_grab *grab_page_down; + struct conf_grab *grab_page_down; /* seats */ char **seats; diff --git a/src/shl_misc.h b/src/shl_misc.h index 2d8909b..724a7c0 100644 --- a/src/shl_misc.h +++ b/src/shl_misc.h @@ -36,8 +36,10 @@ #include #include #include +#include -int shl_strtou(const char *input, unsigned int *output) { +static inline int shl_strtou(const char *input, unsigned int *output) +{ unsigned long val; unsigned int res; char *tmp = NULL; @@ -57,4 +59,38 @@ int shl_strtou(const char *input, unsigned int *output) { return 0; } +/* TODO: xkbcommon should provide these flags! + * We currently copy them into each library API we use so we need to keep + * them in sync. Currently, they're used in uterm-input and tsm-vte. */ +enum shl_xkb_mods { + SHL_SHIFT_MASK = (1 << 0), + SHL_LOCK_MASK = (1 << 1), + SHL_CONTROL_MASK = (1 << 2), + SHL_ALT_MASK = (1 << 3), + SHL_LOGO_MASK = (1 << 4), +}; + +static inline unsigned int shl_get_xkb_mods(struct xkb_state *state) +{ + unsigned int mods = 0; + + if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_SHIFT, + XKB_STATE_EFFECTIVE)) + mods |= SHL_SHIFT_MASK; + if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS, + XKB_STATE_EFFECTIVE)) + mods |= SHL_LOCK_MASK; + if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL, + XKB_STATE_EFFECTIVE)) + mods |= SHL_CONTROL_MASK; + if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_ALT, + XKB_STATE_EFFECTIVE)) + mods |= SHL_ALT_MASK; + if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_LOGO, + XKB_STATE_EFFECTIVE)) + mods |= SHL_LOGO_MASK; + + return mods; +} + #endif /* SHL_MISC_H */ diff --git a/src/tsm_vte.c b/src/tsm_vte.c index 358d610..72a214f 100644 --- a/src/tsm_vte.c +++ b/src/tsm_vte.c @@ -2164,7 +2164,7 @@ bool tsm_vte_handle_keyboard(struct tsm_vte *vte, uint32_t keysym, * Also check whether altSendsEscape should be the default (xterm * disables this by default, why?) and whether we should implement the * fallback shifting that xterm does. */ - if (mods & TSM_MOD1_MASK) + if (mods & TSM_ALT_MASK) vte->flags |= FLAG_PREPEND_ESCAPE; if (mods & TSM_CONTROL_MASK) { diff --git a/src/tsm_vte.h b/src/tsm_vte.h index 8124aa1..7c72471 100644 --- a/src/tsm_vte.h +++ b/src/tsm_vte.h @@ -50,18 +50,16 @@ extern tsm_vte_charset tsm_vte_dec_special_graphics; struct tsm_vte; -/* keep in sync with uterm_input_modifier */ +/* keep in sync with shl_xkb_mods */ enum tsm_vte_modifier { TSM_SHIFT_MASK = (1 << 0), TSM_LOCK_MASK = (1 << 1), TSM_CONTROL_MASK = (1 << 2), - TSM_MOD1_MASK = (1 << 3), - TSM_MOD2_MASK = (1 << 4), - TSM_MOD3_MASK = (1 << 5), - TSM_MOD4_MASK = (1 << 6), - TSM_MOD5_MASK = (1 << 7), + TSM_ALT_MASK = (1 << 3), + TSM_LOGO_MASK = (1 << 4), }; +/* keep in sync with TSM_INPUT_INVALID */ #define TSM_VTE_INVALID 0xffffffff typedef void (*tsm_vte_write_cb) (struct tsm_vte *vte, diff --git a/src/uterm.h b/src/uterm.h index 98232ad..8912df1 100644 --- a/src/uterm.h +++ b/src/uterm.h @@ -256,18 +256,16 @@ void uterm_video_poll(struct uterm_video *video); struct uterm_input; -/* keep in sync with tsm_vte_modified */ +/* keep in sync with shl_xkb_mods */ enum uterm_input_modifier { UTERM_SHIFT_MASK = (1 << 0), UTERM_LOCK_MASK = (1 << 1), UTERM_CONTROL_MASK = (1 << 2), - UTERM_MOD1_MASK = (1 << 3), - UTERM_MOD2_MASK = (1 << 4), - UTERM_MOD3_MASK = (1 << 5), - UTERM_MOD4_MASK = (1 << 6), - UTERM_MOD5_MASK = (1 << 7), + UTERM_ALT_MASK = (1 << 3), + UTERM_LOGO_MASK = (1 << 4), }; +/* keep in sync with TSM_VTE_INVALID */ #define UTERM_INPUT_INVALID 0xffffffff struct uterm_input_event { @@ -279,11 +277,6 @@ struct uterm_input_event { #define UTERM_INPUT_HAS_MODS(_ev, _mods) (((_ev)->mods & (_mods)) == (_mods)) -struct uterm_input_grab { - unsigned int mods; - uint32_t keysym; -}; - typedef void (*uterm_input_cb) (struct uterm_input *input, struct uterm_input_event *ev, void *data); diff --git a/src/uterm_input_plain.c b/src/uterm_input_plain.c index 44de350..91926ee 100644 --- a/src/uterm_input_plain.c +++ b/src/uterm_input_plain.c @@ -271,13 +271,12 @@ static const struct { [KEY_LEFTCTRL] = { UTERM_CONTROL_MASK, MOD_NORMAL }, [KEY_LEFTSHIFT] = { UTERM_SHIFT_MASK, MOD_NORMAL }, [KEY_RIGHTSHIFT] = { UTERM_SHIFT_MASK, MOD_NORMAL }, - [KEY_LEFTALT] = { UTERM_MOD1_MASK, MOD_NORMAL }, + [KEY_LEFTALT] = { UTERM_ALT_MASK, MOD_NORMAL }, [KEY_CAPSLOCK] = { UTERM_LOCK_MASK, MOD_LOCK }, - [KEY_NUMLOCK] = { UTERM_MOD2_MASK, MOD_LOCK }, [KEY_RIGHTCTRL] = { UTERM_CONTROL_MASK, MOD_NORMAL }, - [KEY_RIGHTALT] = { UTERM_MOD1_MASK, MOD_NORMAL }, - [KEY_LEFTMETA] = { UTERM_MOD4_MASK, MOD_NORMAL }, - [KEY_RIGHTMETA] = { UTERM_MOD4_MASK, MOD_NORMAL }, + [KEY_RIGHTALT] = { UTERM_ALT_MASK, MOD_NORMAL }, + [KEY_LEFTMETA] = { UTERM_LOGO_MASK, MOD_NORMAL }, + [KEY_RIGHTMETA] = { UTERM_LOGO_MASK, MOD_NORMAL }, }; static void plain_dev_ref(struct kbd_dev *kbd) @@ -303,8 +302,6 @@ static void plain_dev_reset(struct kbd_dev *kbd, const unsigned long *ledbits) kbd->plain.mods = 0; - if (input_bit_is_set(ledbits, LED_NUML)) - kbd->plain.mods |= UTERM_MOD2_MASK; if (input_bit_is_set(ledbits, LED_CAPSL)) kbd->plain.mods |= UTERM_LOCK_MASK; } @@ -352,8 +349,6 @@ static int plain_dev_process(struct kbd_dev *kbd, keysym = 0; - if (!keysym && kbd->plain.mods & UTERM_MOD2_MASK) - keysym = keytab_numlock[code]; if (!keysym && kbd->plain.mods & UTERM_SHIFT_MASK) keysym = keytab_shift[code]; if (!keysym && kbd->plain.mods & UTERM_LOCK_MASK) diff --git a/src/uterm_input_uxkb.c b/src/uterm_input_uxkb.c index 59a5b85..ddc9b67 100644 --- a/src/uterm_input_uxkb.c +++ b/src/uterm_input_uxkb.c @@ -32,6 +32,7 @@ #include #include #include "log.h" +#include "shl_misc.h" #include "uterm.h" #include "uterm_input.h" @@ -62,29 +63,6 @@ enum { KEY_REPEATED = 2, }; -static unsigned int get_effective_modmask(struct xkb_state *state) -{ - unsigned int mods = 0; - - if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_SHIFT, - XKB_STATE_EFFECTIVE)) - mods |= UTERM_SHIFT_MASK; - if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS, - XKB_STATE_EFFECTIVE)) - mods |= UTERM_LOCK_MASK; - if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL, - XKB_STATE_EFFECTIVE)) - mods |= UTERM_CONTROL_MASK; - if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_ALT, - XKB_STATE_EFFECTIVE)) - mods |= UTERM_MOD1_MASK; - if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_LOGO, - XKB_STATE_EFFECTIVE)) - mods |= UTERM_MOD4_MASK; - - return mods; -} - static int uxkb_dev_process(struct kbd_dev *kbd, uint16_t key_state, uint16_t code, @@ -126,7 +104,7 @@ static int uxkb_dev_process(struct kbd_dev *kbd, */ out->keycode = code; out->keysym = keysyms[0]; - out->mods = get_effective_modmask(state); + out->mods = shl_get_xkb_mods(state); out->unicode = xkb_keysym_to_utf32(out->keysym) ? : UTERM_INPUT_INVALID; return 0; diff --git a/src/uterm_vt.c b/src/uterm_vt.c index 8f713af..a427ad4 100644 --- a/src/uterm_vt.c +++ b/src/uterm_vt.c @@ -419,7 +419,7 @@ static void vt_input(struct uterm_input *input, { struct uterm_vt *vt = data; - if (UTERM_INPUT_HAS_MODS(ev, UTERM_MOD4_MASK | UTERM_CONTROL_MASK)) { + if (UTERM_INPUT_HAS_MODS(ev, UTERM_LOGO_MASK | UTERM_CONTROL_MASK)) { if (ev->keysym == XKB_KEY_F12) { if (vt->active) { log_debug("deactivating fake VT due to user input"); diff --git a/src/wlt_toolkit.c b/src/wlt_toolkit.c index 37b07b0..0b11cf5 100644 --- a/src/wlt_toolkit.c +++ b/src/wlt_toolkit.c @@ -40,6 +40,7 @@ #include "log.h" #include "shl_dlist.h" #include "shl_hook.h" +#include "shl_misc.h" #include "tsm_vte.h" #include "wlt_toolkit.h" @@ -617,29 +618,6 @@ static void keyboard_leave(void *data, struct wl_keyboard *keyboard, ev_timer_update(disp->repeat_timer, NULL); } -static unsigned int get_effective_modmask(struct xkb_state *state) -{ - unsigned int mods = 0; - - if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_SHIFT, - XKB_STATE_EFFECTIVE)) - mods |= TSM_SHIFT_MASK; - if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS, - XKB_STATE_EFFECTIVE)) - mods |= TSM_LOCK_MASK; - if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL, - XKB_STATE_EFFECTIVE)) - mods |= TSM_CONTROL_MASK; - if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_ALT, - XKB_STATE_EFFECTIVE)) - mods |= TSM_MOD1_MASK; - if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_LOGO, - XKB_STATE_EFFECTIVE)) - mods |= TSM_MOD4_MASK; - - return mods; -} - static void keyboard_key(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state_w) @@ -663,7 +641,7 @@ static void keyboard_key(void *data, struct wl_keyboard *keyboard, if (!wnd) return; - mask = get_effective_modmask(disp->xkb_state); + mask = shl_get_xkb_mods(disp->xkb_state); num_syms = xkb_key_get_syms(disp->xkb_state, code, &syms); sym = XKB_KEY_NoSymbol; if (num_syms == 1) @@ -700,7 +678,7 @@ static void repeat_event(struct ev_timer *timer, uint64_t num, void *data) if (!wnd) return; - mask = get_effective_modmask(disp->xkb_state); + mask = shl_get_xkb_mods(disp->xkb_state); shl_dlist_for_each(iter, &wnd->widget_list) { widget = shl_dlist_entry(iter, struct wlt_widget, list); if (widget->keyboard_cb)