// SPDX-License-Identifier: GPL-3.0-only /* * XKB keymap manager. * * Copyright (c) 2024, Richard Acayan. All rights reserved. */ #include #include #include #include #include #include #include #include #include "keymap.h" #include "layout.h" #include "ufkbd.h" static int write_keysym(int fd, xkb_keysym_t sym) { char *name; int len, ret; len = xkb_keysym_get_name(sym, NULL, 0); if (len == -1) return len; name = malloc((size_t) len + 1); if (name == NULL) return -1; xkb_keysym_get_name(sym, name, (size_t) len + 1); ret = dprintf(fd, "%s", name); free(name); return ret; } static int maybe_write_modmap(int fd, int keyid, xkb_keysym_t sym) { if (sym == XKB_KEY_Shift_L || sym == XKB_KEY_Shift_R) return dprintf(fd, " modifier_map Shift { };\n", keyid); else if (sym == XKB_KEY_Control_L || sym == XKB_KEY_Control_R) return dprintf(fd, " modifier_map Control { };\n", keyid); else if (sym == XKB_KEY_Alt_L || sym == XKB_KEY_Alt_R) return dprintf(fd, " modifier_map Mod1 { };\n", keyid); return 0; } int ufkbd_keymap_add_key(struct ufkbd_keymap *keymap, xkb_keysym_t keysym) { xkb_keysym_t upper; int len; int keyid; keyid = keymap->count; if (keyid >= 256) return -1; upper = xkb_keysym_to_upper(keysym); len = dprintf(keymap->fd, " key { [ ", keyid); if (len == -1) return len; keymap->size += len; len = write_keysym(keymap->fd, keysym); if (len == -1) return len; keymap->size += len; len = dprintf(keymap->fd, ", "); if (len == -1) return len; keymap->size += len; len = write_keysym(keymap->fd, upper); if (len == -1) return len; keymap->size += len; len = dprintf(keymap->fd, " ] };\n"); if (len == -1) return len; keymap->size += len; len = maybe_write_modmap(keymap->fd, keyid, keysym); if (len == -1) return len; keymap->size += len; keymap->count++; return keyid; } void ufkbd_keymap_end(struct ufkbd_keymap *keymap) { int i; int fd = keymap->fd; size_t written; written = dprintf(fd, " };\n" "\n" " xkb_keycodes \"ufkbd\" {\n" " minimum = 8;\n" " maximum = 255;\n"); for (i = 8; i < keymap->count; i++) written += dprintf(fd, " = %d;\n", i, i); written += dprintf(fd, " indicator 1 = \"Caps Lock\";\n" " };\n" "\n" " xkb_types \"ufkbd\" {\n" " type \"TWO_LEVEL\" {\n" " modifiers = Shift;\n" " map[Shift] = Level2;\n" " level_name[Level1] = \"Base\";\n" " level_name[Level2] = \"Shift\";\n" " };\n" " };\n" "\n" " xkb_compatibility \"ufkbd\" {\n" " };\n" "};\n"); keymap->size += written; } struct ufkbd_keymap *ufkbd_keymap_init(void) { struct ufkbd_keymap *keymap; intmax_t pid; keymap = malloc(sizeof(*keymap)); if (keymap == NULL) return NULL; pid = getpid(); snprintf(keymap->path, 256, "/tmp/ufkbd-keymap-pid%ju", pid); keymap->fd = open(keymap->path, O_RDWR | O_CREAT | O_TRUNC, 0644); if (keymap->fd == -1) goto err; keymap->count = 8; keymap->size = dprintf(keymap->fd, "xkb_keymap {\n" " xkb_symbols \"ufkbd\" {\n"); return keymap; err: free(keymap); return NULL; } void ufkbd_keymap_uninit(struct ufkbd_keymap *keymap) { close(keymap->fd); unlink(keymap->path); free(keymap); }