summary refs log tree commit diff
diff options
context:
space:
mode:
authorMathieu Othacehe <m.othacehe@gmail.com>2018-11-16 20:40:26 +0900
committerLudovic Courtès <ludo@gnu.org>2019-01-17 14:04:20 +0100
commit08af580bde01ffd8e6968b6f9f9eff14c4f9cc5a (patch)
tree6b6d52be35e6733c5dfe2789856e9cc4ce5eaf74
parent76421cf0d2e1feb637f174c5c9891e8286965c58 (diff)
downloadguix-08af580bde01ffd8e6968b6f9f9eff14c4f9cc5a.tar.gz
gnu: kmscon: Add runtime keymap update support.
* gnu/packages/patches/kmscon-runtime-keymap-switch.patch: New file.
* gnu/local.mk (dist_patch_DATA): Add it.
* gnu/packages/terminals.scm (kmscon)[source]: Add patch.
-rw-r--r--gnu/local.mk1
-rw-r--r--gnu/packages/patches/kmscon-runtime-keymap-switch.patch229
-rw-r--r--gnu/packages/terminals.scm2
3 files changed, 232 insertions, 0 deletions
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 <m.othacehe@gmail.com>
+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 <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
+ #include <xkbcommon/xkbcommon.h>
+ #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 @@ compatibility to existing emulators like xterm, gnome-terminal, konsole, etc.")
                 (sha256
                  (base32
                   "0q62kjsvy2iwy8adfiygx2bfwlh83rphgxbis95ycspqidg9py87"))
+                (patches
+                 (search-patches "kmscon-runtime-keymap-switch.patch"))
                 (modules '((guix build utils)))))
       (build-system gnu-build-system)
       (arguments