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;