diff --git a/gnu/local.mk b/gnu/local.mk index 4fed451747..1268e0c600 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -876,6 +876,7 @@ dist_patch_DATA = \ %D%/packages/patches/kinit-kdeinit-libpath.patch \ %D%/packages/patches/kio-search-smbd-on-PATH.patch \ %D%/packages/patches/kmod-module-directory.patch \ + %D%/packages/patches/kmscon-runtime-keymap-switch.patch \ %D%/packages/patches/kpackage-allow-external-paths.patch \ %D%/packages/patches/kobodeluxe-paths.patch \ %D%/packages/patches/kobodeluxe-enemies-pipe-decl.patch \ diff --git a/gnu/packages/patches/kmscon-runtime-keymap-switch.patch b/gnu/packages/patches/kmscon-runtime-keymap-switch.patch new file mode 100644 index 0000000000..656c76fa40 --- /dev/null +++ b/gnu/packages/patches/kmscon-runtime-keymap-switch.patch @@ -0,0 +1,229 @@ +From 360d44d67e7be46108bec982ff2e79b89f04a9a3 Mon Sep 17 00:00:00 2001 +From: Mathieu Othacehe +Date: Thu, 15 Nov 2018 14:34:40 +0900 +Subject: [PATCH] add runtime keymap switch support. + +--- + src/pty.c | 23 ++++++++++- + src/uterm_input.c | 2 + + src/uterm_input_internal.h | 5 +++ + src/uterm_input_uxkb.c | 83 ++++++++++++++++++++++++++++++++++++++ + 4 files changed, 111 insertions(+), 2 deletions(-) + +diff --git a/src/pty.c b/src/pty.c +index 1443f4a..f64cb5b 100644 +--- a/src/pty.c ++++ b/src/pty.c +@@ -46,6 +46,8 @@ + + #define KMSCON_NREAD 16384 + ++#define INPUT_KEYMAP_UPDATE_FILE "/tmp/kmscon-%d-keymap-update" ++ + struct kmscon_pty { + unsigned long ref; + struct ev_eloop *eloop; +@@ -241,9 +243,22 @@ static bool pty_is_open(struct kmscon_pty *pty) + return pty->fd >= 0; + } + ++static int kmscon_keymap_update(pid_t pid) ++{ ++ char *file; ++ int ret; ++ ++ ret = asprintf(&file, INPUT_KEYMAP_UPDATE_FILE, pid); ++ if (ret < 0) ++ return ret; ++ ++ return setenv("KEYMAP_UPDATE", file, 1); ++} ++ + static void __attribute__((noreturn)) + exec_child(const char *term, const char *colorterm, char **argv, +- const char *seat, const char *vtnr, bool env_reset) ++ const char *seat, const char *vtnr, bool env_reset, ++ pid_t kmscon_pid) + { + char **env; + char **def_argv; +@@ -277,6 +292,8 @@ exec_child(const char *term, const char *colorterm, char **argv, + if (vtnr) + setenv("XDG_VTNR", vtnr, 1); + ++ kmscon_keymap_update(kmscon_pid); ++ + execve(argv[0], argv, environ); + + log_err("failed to exec child %s: %m", argv[0]); +@@ -383,12 +400,14 @@ static int pty_spawn(struct kmscon_pty *pty, int master, + unsigned short width, unsigned short height) + { + pid_t pid; ++ pid_t kmscon_pid; + struct winsize ws; + + memset(&ws, 0, sizeof(ws)); + ws.ws_col = width; + ws.ws_row = height; + ++ kmscon_pid = getpid(); + pid = fork(); + switch (pid) { + case -1: +@@ -397,7 +416,7 @@ static int pty_spawn(struct kmscon_pty *pty, int master, + case 0: + setup_child(master, &ws); + exec_child(pty->term, pty->colorterm, pty->argv, pty->seat, +- pty->vtnr, pty->env_reset); ++ pty->vtnr, pty->env_reset, kmscon_pid); + exit(EXIT_FAILURE); + default: + log_debug("forking child %d", pid); +diff --git a/src/uterm_input.c b/src/uterm_input.c +index 6fcbc4b..990a09d 100644 +--- a/src/uterm_input.c ++++ b/src/uterm_input.c +@@ -178,6 +178,8 @@ static void input_new_dev(struct uterm_input *input, + if (ret) + goto err_rcodepoints; + ++ uxkb_dev_keymap_update(dev); ++ + if (input->awake > 0) { + ret = input_wake_up_dev(dev); + if (ret) +diff --git a/src/uterm_input_internal.h b/src/uterm_input_internal.h +index 04e6cc9..ec44459 100644 +--- a/src/uterm_input_internal.h ++++ b/src/uterm_input_internal.h +@@ -39,6 +39,8 @@ + #include "shl_misc.h" + #include "uterm_input.h" + ++#define INPUT_KEYMAP_UPDATE_FILE "/tmp/kmscon-%d-keymap-update" ++ + enum uterm_input_device_capability { + UTERM_DEVICE_HAS_KEYS = (1 << 0), + UTERM_DEVICE_HAS_LEDS = (1 << 1), +@@ -62,6 +64,8 @@ struct uterm_input_dev { + + bool repeating; + struct ev_timer *repeat_timer; ++ struct ev_fd *fd_update; ++ int rupdate_fd; + }; + + struct uterm_input { +@@ -95,6 +99,7 @@ void uxkb_desc_destroy(struct uterm_input *input); + + int uxkb_dev_init(struct uterm_input_dev *dev); + void uxkb_dev_destroy(struct uterm_input_dev *dev); ++int uxkb_dev_keymap_update(struct uterm_input_dev *dev); + int uxkb_dev_process(struct uterm_input_dev *dev, + uint16_t key_state, + uint16_t code); +diff --git a/src/uterm_input_uxkb.c b/src/uterm_input_uxkb.c +index 925c755..4760972 100644 +--- a/src/uterm_input_uxkb.c ++++ b/src/uterm_input_uxkb.c +@@ -31,6 +31,9 @@ + #include + #include + #include ++#include ++#include ++#include + #include + #include "shl_hook.h" + #include "shl_llog.h" +@@ -178,6 +181,86 @@ static void timer_event(struct ev_timer *timer, uint64_t num, void *data) + shl_hook_call(dev->input->hook, dev->input, &dev->repeat_event); + } + ++static void uxkb_keymap_update_handler(struct ev_fd *fd, int mask, void *data) ++{ ++ struct uterm_input_dev *dev = data; ++ char in; ++ char keymap[3][255]; ++ int pos = 0; ++ int curr_keymap = 0; ++ int ret; ++ char *model, *layout, *variant; ++ ++ if (!(mask & EV_READABLE)) ++ return; ++ ++ memset(keymap, 0, sizeof(keymap)); ++ ++ model = keymap[0]; ++ layout = keymap[1]; ++ variant = keymap[2]; ++ ++ do { ++ ret = read(dev->rupdate_fd, &in, sizeof(in)); ++ if (ret <= 0) ++ break; ++ ++ keymap[curr_keymap][pos++] = in; ++ ++ if (in == '\0') { ++ curr_keymap++; ++ pos = 0; ++ } ++ } while (1); ++ ++ llog_info(dev->input, "HANDLER CALLED %s|%s|%s\n", ++ model, layout, variant); ++ uxkb_desc_init(dev->input, model, layout, variant, NULL, NULL); ++ ++ dev->state = xkb_state_new(dev->input->keymap); ++ if (!dev->state) { ++ llog_error(dev->input, "cannot create XKB state"); ++ return; ++ } ++} ++ ++int uxkb_dev_keymap_update(struct uterm_input_dev *dev) ++{ ++ int ret; ++ char *file; ++ int pid = getpid(); ++ ++ ret = asprintf(&file, INPUT_KEYMAP_UPDATE_FILE, pid); ++ if (ret < 0) ++ return ret; ++ ++ ret = mkfifo(file, S_IRWXU); ++ if (ret < 0) { ++ llog_warn(dev->input, "could not open fifo"); ++ return -EFAULT; ++ } ++ dev->rupdate_fd = open(file, O_RDONLY | O_NONBLOCK); ++ if (dev->rupdate_fd < 0) { ++ llog_warn(dev->input, "cannot open file %s (%d): %m", ++ file, errno); ++ return -EFAULT; ++ } ++ ++ setenv("KEYMAP_UPDATE", file, 1); ++ ++ ret = ev_eloop_new_fd(dev->input->eloop, &dev->fd_update, ++ dev->rupdate_fd, EV_READABLE, ++ uxkb_keymap_update_handler, dev); ++ if (ret) { ++ llog_error(dev->input, "could not init keymap update"); ++ close(dev->rupdate_fd); ++ dev->rupdate_fd = -1; ++ return ret; ++ } ++ ++ return 0; ++} ++ + int uxkb_dev_init(struct uterm_input_dev *dev) + { + int ret; +-- +2.17.1 + diff --git a/gnu/packages/terminals.scm b/gnu/packages/terminals.scm index 5d99e17ee3..236923a2d6 100644 --- a/gnu/packages/terminals.scm +++ b/gnu/packages/terminals.scm @@ -242,6 +242,8 @@ (define-public kmscon (sha256 (base32 "0q62kjsvy2iwy8adfiygx2bfwlh83rphgxbis95ycspqidg9py87")) + (patches + (search-patches "kmscon-runtime-keymap-switch.patch")) (modules '((guix build utils))))) (build-system gnu-build-system) (arguments