diff --git a/docs/man/kmscon.xml b/docs/man/kmscon.xml index 7777ede..9fe0ba1 100644 --- a/docs/man/kmscon.xml +++ b/docs/man/kmscon.xml @@ -299,6 +299,15 @@ + + + + Path to a single predefined keymap file. This takes precedence + over the above options. An empty path "" is interpreted as not + using a keymap. (default: not used) + + + diff --git a/src/kmscon_conf.c b/src/kmscon_conf.c index d960c42..27df14a 100644 --- a/src/kmscon_conf.c +++ b/src/kmscon_conf.c @@ -105,6 +105,8 @@ static void print_help() "\t --xkb-layout [-] Set XkbLayout for input devices\n" "\t --xkb-variant [-] Set XkbVariant for input devices\n" "\t --xkb-options [-] Set XkbOptions for input devices\n" + "\t --xkb-keymap [-] Use a predefined keymap for\n" + "\t input devices\n" "\t --xkb-repeat-delay [250]\n" "\t Initial delay for key-repeat in ms\n" "\t --xkb-repeat-rate [50]\n" @@ -581,6 +583,7 @@ int kmscon_conf_new(struct conf_ctx **out) CONF_OPTION_STRING(0, "xkb-layout", &conf->xkb_layout, ""), CONF_OPTION_STRING(0, "xkb-variant", &conf->xkb_variant, ""), CONF_OPTION_STRING(0, "xkb-options", &conf->xkb_options, ""), + CONF_OPTION_STRING(0, "xkb-keymap", &conf->xkb_keymap, ""), CONF_OPTION_UINT(0, "xkb-repeat-delay", &conf->xkb_repeat_delay, 250), CONF_OPTION_UINT(0, "xkb-repeat-rate", &conf->xkb_repeat_rate, 50), diff --git a/src/kmscon_conf.h b/src/kmscon_conf.h index 4cb4789..113ea1a 100644 --- a/src/kmscon_conf.h +++ b/src/kmscon_conf.h @@ -104,6 +104,8 @@ struct kmscon_conf_t { char *xkb_variant; /* input KBD options */ char *xkb_options; + /* input predefined KBD keymap */ + char *xkb_keymap; /* keyboard key-repeat delay */ unsigned int xkb_repeat_delay; /* keyboard key-repeat rate */ diff --git a/src/kmscon_seat.c b/src/kmscon_seat.c index be8a5ab..8a259b9 100644 --- a/src/kmscon_seat.c +++ b/src/kmscon_seat.c @@ -639,6 +639,7 @@ int kmscon_seat_new(struct kmscon_seat **out, { struct kmscon_seat *seat; int ret; + char *keymap; if (!out || !eloop || !vtm || !seatname) return -EINVAL; @@ -675,13 +676,27 @@ int kmscon_seat_new(struct kmscon_seat **out, goto err_conf; } + /* TODO: The XKB-API currently requires zero-terminated strings as + * keymap input. Hence, we have to read it in instead of using mmap(). + * We should fix this upstream! */ + keymap = NULL; + if (seat->conf->xkb_keymap && *seat->conf->xkb_keymap) { + ret = shl_read_file(seat->conf->xkb_keymap, &keymap, NULL); + if (ret) + log_error("cannot read keymap file %s: %d", + seat->conf->xkb_keymap, ret); + } + ret = uterm_input_new(&seat->input, seat->eloop, seat->conf->xkb_model, seat->conf->xkb_layout, seat->conf->xkb_variant, seat->conf->xkb_options, + keymap, seat->conf->xkb_repeat_delay, seat->conf->xkb_repeat_rate); + free(keymap); + if (ret) goto err_conf; diff --git a/src/uterm_input.c b/src/uterm_input.c index 1ba8812..c248ee8 100644 --- a/src/uterm_input.c +++ b/src/uterm_input.c @@ -223,6 +223,7 @@ int uterm_input_new(struct uterm_input **out, const char *layout, const char *variant, const char *options, + const char *keymap, unsigned int repeat_delay, unsigned int repeat_rate) { @@ -255,7 +256,7 @@ int uterm_input_new(struct uterm_input **out, if (ret) goto err_free; - ret = uxkb_desc_init(input, model, layout, variant, options); + ret = uxkb_desc_init(input, model, layout, variant, options, keymap); if (ret) goto err_hook; diff --git a/src/uterm_input.h b/src/uterm_input.h index 36f5de2..43faccc 100644 --- a/src/uterm_input.h +++ b/src/uterm_input.h @@ -71,8 +71,8 @@ typedef void (*uterm_input_cb) (struct uterm_input *input, int uterm_input_new(struct uterm_input **out, struct ev_eloop *eloop, const char *model, const char *layout, const char *variant, - const char *options, unsigned int repeat_delay, - unsigned int repeat_rate); + const char *options, const char *keymap, + unsigned int repeat_delay, unsigned int repeat_rate); void uterm_input_ref(struct uterm_input *input); void uterm_input_unref(struct uterm_input *input); diff --git a/src/uterm_input_internal.h b/src/uterm_input_internal.h index 727af97..6491d33 100644 --- a/src/uterm_input_internal.h +++ b/src/uterm_input_internal.h @@ -86,7 +86,8 @@ int uxkb_desc_init(struct uterm_input *input, const char *model, const char *layout, const char *variant, - const char *options); + const char *options, + const char *keymap); void uxkb_desc_destroy(struct uterm_input *input); int uxkb_dev_init(struct uterm_input_dev *dev); diff --git a/src/uterm_input_uxkb.c b/src/uterm_input_uxkb.c index 3053dfc..8ba4abc 100644 --- a/src/uterm_input_uxkb.c +++ b/src/uterm_input_uxkb.c @@ -44,7 +44,8 @@ int uxkb_desc_init(struct uterm_input *input, const char *model, const char *layout, const char *variant, - const char *options) + const char *options, + const char *keymap) { int ret; struct xkb_rule_names rmlvo = { @@ -61,6 +62,18 @@ int uxkb_desc_init(struct uterm_input *input, return -ENOMEM; } + /* If a complete keymap file was given, first try that. */ + if (keymap && *keymap) { + input->keymap = xkb_keymap_new_from_string(input->ctx, + keymap, XKB_KEYMAP_FORMAT_TEXT_V1, 0); + if (input->keymap) { + log_debug("new keyboard description from memory"); + return 0; + } + + log_warn("cannot parse keymap, reverting to rmlvo"); + } + input->keymap = xkb_keymap_new_from_names(input->ctx, &rmlvo, 0); if (!input->keymap) { log_warn("failed to create keymap (%s, %s, %s, %s), " diff --git a/tests/test_input.c b/tests/test_input.c index 832c3b2..7dc06c7 100644 --- a/tests/test_input.c +++ b/tests/test_input.c @@ -52,6 +52,7 @@ struct { char *xkb_layout; char *xkb_variant; char *xkb_options; + char *xkb_keymap; } input_conf; /* Pressing Ctrl-\ should toggle the capturing. */ @@ -109,16 +110,27 @@ static void monitor_event(struct uterm_monitor *mon, void *data) { int ret; + char *keymap; if (ev->type == UTERM_MONITOR_NEW_SEAT) { if (strcmp(ev->seat_name, "seat0")) return; + keymap = NULL; + if (input_conf.xkb_keymap && *input_conf.xkb_keymap) { + ret = shl_read_file(input_conf.xkb_keymap, &keymap, + NULL); + if (ret) + log_error("cannot read keymap file %s: %d", + input_conf.xkb_keymap, ret); + } + ret = uterm_input_new(&input, eloop, input_conf.xkb_model, input_conf.xkb_layout, input_conf.xkb_variant, input_conf.xkb_options, + keymap, 0, 0); if (ret) return; @@ -166,7 +178,9 @@ static void print_help() "\t --xkb-model [-] Set XkbModel for input devices\n" "\t --xkb-layout [-] Set XkbLayout for input devices\n" "\t --xkb-variant [-] Set XkbVariant for input devices\n" - "\t --xkb-options [-] Set XkbOptions for input devices\n", + "\t --xkb-options [-] Set XkbOptions for input devices\n" + "\t --xkb-keymap [-] Use a predefined keymap for\n" + "\t input devices\n", "test_input"); /* * 80 char line: @@ -184,6 +198,7 @@ struct conf_option options[] = { CONF_OPTION_STRING(0, "xkb-layout", &input_conf.xkb_layout, ""), CONF_OPTION_STRING(0, "xkb-variant", &input_conf.xkb_variant, ""), CONF_OPTION_STRING(0, "xkb-options", &input_conf.xkb_options, ""), + CONF_OPTION_STRING(0, "xkb-keymap", &input_conf.xkb_keymap, ""), }; int main(int argc, char **argv) diff --git a/tests/test_vt.c b/tests/test_vt.c index 8423f0c..26c5ed6 100644 --- a/tests/test_vt.c +++ b/tests/test_vt.c @@ -113,7 +113,7 @@ int main(int argc, char **argv) if (ret) goto err_exit; - ret = uterm_input_new(&input, eloop, "", "", "", "", 0, 0); + ret = uterm_input_new(&input, eloop, "", "", "", "", "", 0, 0); if (ret) goto err_vtm;