keymap: Keep keymap fd management in one place

At the same time, reduce the distance between this and the Xwayland handling branch.
This commit is contained in:
Dorota Czaplejewicz
2020-10-06 09:53:02 +00:00
parent b21734bf57
commit 87eb775377
3 changed files with 53 additions and 38 deletions

View File

@ -28,33 +28,24 @@
#include <sys/random.h> // TODO: this is Linux-specific
#include <xkbcommon/xkbcommon.h>
#include "eek-keyboard.h"
void level_keyboard_free(LevelKeyboard *self) {
xkb_keymap_unref(self->keymap);
close(self->keymap_fd);
squeek_layout_free(self->layout);
g_free(self);
static void eek_key_map_deinit(struct keymap *self) {
if (self->fd < 0) {
g_error("Deinit called multiple times on KeyMap");
} else {
close(self->fd);
}
self->fd = -1;
}
LevelKeyboard*
level_keyboard_new (struct squeek_layout *layout)
{
LevelKeyboard *keyboard = g_new0(LevelKeyboard, 1);
if (!keyboard) {
g_error("Failed to create a keyboard");
}
keyboard->layout = layout;
static struct keymap eek_key_map_from_str(const char *keymap_str) {
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (!context) {
g_error("No context created");
}
const gchar *keymap_str = squeek_layout_get_keymap(keyboard->layout);
struct xkb_keymap *keymap = xkb_keymap_new_from_string(context, keymap_str,
XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
@ -62,10 +53,9 @@ level_keyboard_new (struct squeek_layout *layout)
g_error("Bad keymap:\n%s", keymap_str);
xkb_context_unref(context);
keyboard->keymap = keymap;
char * xkb_keymap_str = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
keyboard->keymap_len = strlen(xkb_keymap_str) + 1;
char *xkb_keymap_str = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
size_t keymap_len = strlen(xkb_keymap_str) + 1;
g_autofree char *path = strdup("/eek_keymap-XXXXXX");
char *r = &path[strlen(path) - 6];
@ -79,18 +69,42 @@ level_keyboard_new (struct squeek_layout *layout)
if (keymap_fd < 0) {
g_error("Failed to set up keymap fd");
}
keyboard->keymap_fd = keymap_fd;
shm_unlink(path);
if (ftruncate(keymap_fd, (off_t)keyboard->keymap_len)) {
if (ftruncate(keymap_fd, (off_t)keymap_len)) {
g_error("Failed to increase keymap fd size");
}
char *ptr = mmap(NULL, keyboard->keymap_len, PROT_WRITE, MAP_SHARED,
char *ptr = mmap(NULL, keymap_len, PROT_WRITE, MAP_SHARED,
keymap_fd, 0);
if ((void*)ptr == (void*)-1) {
g_error("Failed to set up mmap");
}
strncpy(ptr, xkb_keymap_str, keyboard->keymap_len);
strncpy(ptr, xkb_keymap_str, keymap_len);
munmap(ptr, keymap_len);
free(xkb_keymap_str);
munmap(ptr, keyboard->keymap_len);
xkb_keymap_unref(keymap);
struct keymap km = {
.fd = keymap_fd,
.fd_len = keymap_len,
};
return km;
}
void level_keyboard_free(LevelKeyboard *self) {
eek_key_map_deinit(&self->keymap);
squeek_layout_free(self->layout);
g_free(self);
}
LevelKeyboard*
level_keyboard_new (struct squeek_layout *layout)
{
LevelKeyboard *keyboard = g_new0(LevelKeyboard, 1);
if (!keyboard) {
g_error("Failed to create a keyboard");
}
keyboard->layout = layout;
const gchar *keymap_str = squeek_layout_get_keymap(keyboard->layout);
keyboard->keymap = eek_key_map_from_str(keymap_str);
return keyboard;
}