commit d50987538ff11a13a72f1f06d1538d99b46f9ee1
parent b752d5487c56c71ceee49caa5b74e58bff9cc48c
Author: Michael Forney <mforney@mforney.org>
Date: Wed, 20 May 2015 05:05:51 +0000
Fold xkb.{c,h} into keyboard.{c,h}
Diffstat:
5 files changed, 124 insertions(+), 223 deletions(-)
diff --git a/libswc/keyboard.c b/libswc/keyboard.c
@@ -33,11 +33,15 @@
#include "util.h"
#include <assert.h>
+#include <fcntl.h>
#include <stdio.h>
#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
#include <xkbcommon/xkbcommon.h>
static const int repeat_delay = 500, repeat_rate = 40;
+static const char keymap_file_template[] = "swc-xkb-keymap-XXXXXX";
static void
enter(struct input_focus_handler *handler, struct wl_resource *resource, struct compositor_view *view)
@@ -103,16 +107,91 @@ client_handle_modifiers(struct keyboard *keyboard, const struct keyboard_modifie
return true;
}
+static bool
+update_keymap(struct xkb *xkb)
+{
+ const char *keymap_directory = getenv("XDG_RUNTIME_DIR") ?: "/tmp";
+ char *keymap_string;
+ char keymap_path[strlen(keymap_directory) + 1 + sizeof keymap_file_template];
+
+ xkb->indices.ctrl = xkb_keymap_mod_get_index(xkb->keymap.map, XKB_MOD_NAME_CTRL);
+ xkb->indices.alt = xkb_keymap_mod_get_index(xkb->keymap.map, XKB_MOD_NAME_ALT);
+ xkb->indices.super = xkb_keymap_mod_get_index(xkb->keymap.map, XKB_MOD_NAME_LOGO);
+ xkb->indices.shift = xkb_keymap_mod_get_index(xkb->keymap.map, XKB_MOD_NAME_SHIFT);
+
+ /* In order to send the keymap to clients, we must first convert it to a
+ * string and then mmap it to a file. */
+ keymap_string = xkb_keymap_get_as_string(xkb->keymap.map, XKB_KEYMAP_FORMAT_TEXT_V1);
+
+ if (!keymap_string) {
+ WARNING("Could not get XKB keymap as a string\n");
+ goto error0;
+ }
+
+ sprintf(keymap_path, "%s/%s", keymap_directory, keymap_file_template);
+
+ xkb->keymap.size = strlen(keymap_string) + 1;
+ xkb->keymap.fd = mkostemp(keymap_path, O_CLOEXEC);
+
+ if (xkb->keymap.fd == -1) {
+ WARNING("Could not create XKB keymap file\n");
+ goto error1;
+ }
+
+ unlink(keymap_path);
+
+ if (posix_fallocate(xkb->keymap.fd, 0, xkb->keymap.size) != 0) {
+ WARNING("Could not resize XKB keymap file\n");
+ goto error2;
+ }
+
+ xkb->keymap.area = mmap(NULL, xkb->keymap.size, PROT_READ | PROT_WRITE, MAP_SHARED, xkb->keymap.fd, 0);
+
+ if (xkb->keymap.area == MAP_FAILED) {
+ WARNING("Could not mmap XKB keymap string\n");
+ goto error2;
+ }
+
+ strcpy(xkb->keymap.area, keymap_string);
+ free(keymap_string);
+
+ return true;
+
+error2:
+ close(xkb->keymap.fd);
+error1:
+ free(keymap_string);
+error0:
+ return false;
+}
+
bool
keyboard_initialize(struct keyboard *keyboard)
{
- if (!xkb_initialize(&keyboard->xkb)) {
- ERROR("Could not initialize XKB\n");
+ struct xkb *xkb = &keyboard->xkb;
+
+ if (!(xkb->context = xkb_context_new(0))) {
+ ERROR("Could not create XKB context\n");
goto error0;
}
- if (!input_focus_initialize(&keyboard->focus, &keyboard->focus_handler))
+ if (!(xkb->keymap.map = xkb_keymap_new_from_names(xkb->context, NULL, 0))) {
+ ERROR("Could not create XKB keymap\n");
goto error1;
+ }
+
+ if (!(xkb->state = xkb_state_new(xkb->keymap.map))) {
+ ERROR("Could not create XKB state\n");
+ goto error2;
+ }
+
+ if (!update_keymap(xkb)) {
+ ERROR("Could not update XKB keymap\n");
+ goto error3;
+ }
+
+ if (!input_focus_initialize(&keyboard->focus, &keyboard->focus_handler))
+ goto error3;
keyboard->modifier_state = (struct keyboard_modifier_state){};
keyboard->modifiers = 0;
@@ -127,8 +206,12 @@ keyboard_initialize(struct keyboard *keyboard)
return true;
+error3:
+ xkb_state_unref(keyboard->xkb.state);
+error2:
+ xkb_keymap_unref(keyboard->xkb.keymap.map);
error1:
- xkb_finalize(&keyboard->xkb);
+ xkb_context_unref(keyboard->xkb.context);
error0:
return false;
}
@@ -139,14 +222,19 @@ keyboard_finalize(struct keyboard *keyboard)
wl_array_release(&keyboard->client_keys);
wl_array_release(&keyboard->keys);
input_focus_finalize(&keyboard->focus);
- xkb_finalize(&keyboard->xkb);
+ munmap(keyboard->xkb.keymap.area, keyboard->xkb.keymap.size);
+ close(keyboard->xkb.keymap.fd);
+ xkb_state_unref(keyboard->xkb.state);
+ xkb_keymap_unref(keyboard->xkb.keymap.map);
+ xkb_context_unref(keyboard->xkb.context);
}
-void
+bool
keyboard_reset(struct keyboard *keyboard)
{
struct key *key;
uint32_t time = get_time();
+ struct xkb_state *state;
/* Send simulated key release events for all current key handlers. */
wl_array_for_each (key, &keyboard->keys) {
@@ -165,7 +253,16 @@ keyboard_reset(struct keyboard *keyboard)
keyboard->keys.size = 0;
keyboard->modifier_state = (struct keyboard_modifier_state){};
keyboard->modifiers = 0;
- xkb_reset_state(&keyboard->xkb);
+
+ if (!(state = xkb_state_new(keyboard->xkb.keymap.map))) {
+ ERROR("Failed to allocate new XKB state\n");
+ return false;
+ }
+
+ xkb_state_unref(keyboard->xkb.state);
+ keyboard->xkb.state = state;
+
+ return true;
}
/**
diff --git a/libswc/keyboard.h b/libswc/keyboard.h
@@ -25,10 +25,12 @@
#define SWC_KEYBOARD_H
#include "input.h"
-#include "xkb.h"
#include <wayland-util.h>
+/* Keycodes are offset by 8 in XKB. */
+#define XKB_KEY(key) ((key) + 8)
+
struct keyboard;
struct wl_client;
@@ -51,6 +53,22 @@ struct keyboard_handler {
struct wl_list link;
};
+struct xkb {
+ struct xkb_context *context;
+ struct xkb_state *state;
+
+ struct {
+ struct xkb_keymap *map;
+ int fd;
+ uint32_t size;
+ char *area;
+ } keymap;
+
+ struct {
+ uint32_t ctrl, alt, super, shift;
+ } indices;
+};
+
struct keyboard {
struct input_focus focus;
struct input_focus_handler focus_handler;
@@ -67,7 +85,7 @@ struct keyboard {
bool keyboard_initialize(struct keyboard *keyboard);
void keyboard_finalize(struct keyboard *keyboard);
-void keyboard_reset(struct keyboard *keyboard);
+bool keyboard_reset(struct keyboard *keyboard);
void keyboard_set_focus(struct keyboard *keyboard, struct compositor_view *view);
struct wl_resource *keyboard_bind(struct keyboard *keyboard, struct wl_client *client, uint32_t version, uint32_t id);
void keyboard_handle_key(struct keyboard *keyboard, uint32_t time, uint32_t key, uint32_t state);
diff --git a/libswc/local.mk b/libswc/local.mk
@@ -54,7 +54,6 @@ SWC_SOURCES = \
libswc/xdg_popup.c \
libswc/xdg_shell.c \
libswc/xdg_surface.c \
- libswc/xkb.c \
protocol/swc-protocol.c \
protocol/wayland-drm-protocol.c \
protocol/xdg-shell-protocol.c
diff --git a/libswc/xkb.c b/libswc/xkb.c
@@ -1,159 +0,0 @@
-/* swc: libswc/xkb.c
- *
- * Copyright (c) 2013, 2014 Michael Forney
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include "xkb.h"
-#include "util.h"
-
-#include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <xkbcommon/xkbcommon.h>
-
-static const char keymap_file_template[] = "swc-xkb-keymap-XXXXXX";
-
-bool
-xkb_initialize(struct xkb *xkb)
-{
- xkb->context = xkb_context_new(0);
-
- if (!xkb->context) {
- ERROR("Could not create XKB context\n");
- goto error0;
- }
-
- xkb->keymap.map = xkb_keymap_new_from_names(xkb->context, NULL, 0);
-
- if (!xkb->keymap.map) {
- ERROR("Could not create XKB keymap\n");
- goto error1;
- }
-
- xkb->state = xkb_state_new(xkb->keymap.map);
-
- if (!xkb->state) {
- ERROR("Could not create XKB state\n");
- goto error2;
- }
-
- if (!xkb_update_keymap(xkb)) {
- ERROR("Could not update XKB keymap\n");
- goto error3;
- }
-
- return true;
-
-error3:
- xkb_state_unref(xkb->state);
-error2:
- xkb_keymap_unref(xkb->keymap.map);
-error1:
- xkb_context_unref(xkb->context);
-error0:
- return false;
-}
-
-void
-xkb_finalize(struct xkb *xkb)
-{
- munmap(xkb->keymap.area, xkb->keymap.size);
- close(xkb->keymap.fd);
- xkb_state_unref(xkb->state);
- xkb_keymap_unref(xkb->keymap.map);
- xkb_context_unref(xkb->context);
-}
-
-bool
-xkb_reset_state(struct xkb *xkb)
-{
- struct xkb_state *state;
-
- if (!(state = xkb_state_new(xkb->keymap.map))) {
- ERROR("Failed to allocate new XKB state\n");
- return false;
- }
-
- xkb_state_unref(xkb->state);
- xkb->state = state;
- return true;
-}
-
-bool
-xkb_update_keymap(struct xkb *xkb)
-{
- const char *keymap_directory = getenv("XDG_RUNTIME_DIR") ?: "/tmp";
- char *keymap_string;
- char keymap_path[strlen(keymap_directory) + 1 + sizeof keymap_file_template];
-
- xkb->indices.ctrl = xkb_keymap_mod_get_index(xkb->keymap.map, XKB_MOD_NAME_CTRL);
- xkb->indices.alt = xkb_keymap_mod_get_index(xkb->keymap.map, XKB_MOD_NAME_ALT);
- xkb->indices.super = xkb_keymap_mod_get_index(xkb->keymap.map, XKB_MOD_NAME_LOGO);
- xkb->indices.shift = xkb_keymap_mod_get_index(xkb->keymap.map, XKB_MOD_NAME_SHIFT);
-
- /* In order to send the keymap to clients, we must first convert it to a
- * string and then mmap it to a file. */
- keymap_string = xkb_keymap_get_as_string(xkb->keymap.map, XKB_KEYMAP_FORMAT_TEXT_V1);
-
- if (!keymap_string) {
- WARNING("Could not get XKB keymap as a string\n");
- goto error0;
- }
-
- sprintf(keymap_path, "%s/%s", keymap_directory, keymap_file_template);
-
- xkb->keymap.size = strlen(keymap_string) + 1;
- xkb->keymap.fd = mkostemp(keymap_path, O_CLOEXEC);
-
- if (xkb->keymap.fd == -1) {
- WARNING("Could not create XKB keymap file\n");
- goto error1;
- }
-
- unlink(keymap_path);
-
- if (posix_fallocate(xkb->keymap.fd, 0, xkb->keymap.size) != 0) {
- WARNING("Could not resize XKB keymap file\n");
- goto error2;
- }
-
- xkb->keymap.area = mmap(NULL, xkb->keymap.size, PROT_READ | PROT_WRITE, MAP_SHARED, xkb->keymap.fd, 0);
-
- if (xkb->keymap.area == MAP_FAILED) {
- WARNING("Could not mmap XKB keymap string\n");
- goto error2;
- }
-
- strcpy(xkb->keymap.area, keymap_string);
-
- free(keymap_string);
-
- return true;
-
-error2:
- close(xkb->keymap.fd);
-error1:
- free(keymap_string);
-error0:
- return false;
-}
diff --git a/libswc/xkb.h b/libswc/xkb.h
@@ -1,54 +0,0 @@
-/* swc: libswc/xkb.h
- *
- * Copyright (c) 2013, 2014 Michael Forney
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef SWC_XKB_H
-#define SWC_XKB_H
-
-#include <stdbool.h>
-#include <stdint.h>
-
-/* Keycodes are offset by 8 in XKB. */
-#define XKB_KEY(key) ((key) + 8)
-
-struct xkb {
- struct xkb_context *context;
- struct xkb_state *state;
-
- struct {
- struct xkb_keymap *map;
- int fd;
- uint32_t size;
- char *area;
- } keymap;
-
- struct {
- uint32_t ctrl, alt, super, shift;
- } indices;
-};
-
-bool xkb_initialize(struct xkb *xkb);
-void xkb_finalize(struct xkb *xkb);
-bool xkb_reset_state(struct xkb *xkb);
-bool xkb_update_keymap(struct xkb *xkb);
-
-#endif