commit d509875

Michael Forney  ·  2015-05-20 05:05:51 +0000 UTC
parent b752d54
Fold xkb.{c,h} into keyboard.{c,h}
5 files changed,  +124, -223
+104, -7
  1@@ -33,11 +33,15 @@
  2 #include "util.h"
  3 
  4 #include <assert.h>
  5+#include <fcntl.h>
  6 #include <stdio.h>
  7 #include <string.h>
  8+#include <sys/mman.h>
  9+#include <unistd.h>
 10 #include <xkbcommon/xkbcommon.h>
 11 
 12 static const int repeat_delay = 500, repeat_rate = 40;
 13+static const char keymap_file_template[] = "swc-xkb-keymap-XXXXXX";
 14 
 15 static void
 16 enter(struct input_focus_handler *handler, struct wl_resource *resource, struct compositor_view *view)
 17@@ -103,16 +107,91 @@ client_handle_modifiers(struct keyboard *keyboard, const struct keyboard_modifie
 18 	return true;
 19 }
 20 
 21+static bool
 22+update_keymap(struct xkb *xkb)
 23+{
 24+	const char *keymap_directory = getenv("XDG_RUNTIME_DIR") ?: "/tmp";
 25+	char *keymap_string;
 26+	char keymap_path[strlen(keymap_directory) + 1 + sizeof keymap_file_template];
 27+
 28+	xkb->indices.ctrl = xkb_keymap_mod_get_index(xkb->keymap.map, XKB_MOD_NAME_CTRL);
 29+	xkb->indices.alt = xkb_keymap_mod_get_index(xkb->keymap.map, XKB_MOD_NAME_ALT);
 30+	xkb->indices.super = xkb_keymap_mod_get_index(xkb->keymap.map, XKB_MOD_NAME_LOGO);
 31+	xkb->indices.shift = xkb_keymap_mod_get_index(xkb->keymap.map, XKB_MOD_NAME_SHIFT);
 32+
 33+	/* In order to send the keymap to clients, we must first convert it to a
 34+	 * string and then mmap it to a file. */
 35+	keymap_string = xkb_keymap_get_as_string(xkb->keymap.map, XKB_KEYMAP_FORMAT_TEXT_V1);
 36+
 37+	if (!keymap_string) {
 38+		WARNING("Could not get XKB keymap as a string\n");
 39+		goto error0;
 40+	}
 41+
 42+	sprintf(keymap_path, "%s/%s", keymap_directory, keymap_file_template);
 43+
 44+	xkb->keymap.size = strlen(keymap_string) + 1;
 45+	xkb->keymap.fd = mkostemp(keymap_path, O_CLOEXEC);
 46+
 47+	if (xkb->keymap.fd == -1) {
 48+		WARNING("Could not create XKB keymap file\n");
 49+		goto error1;
 50+	}
 51+
 52+	unlink(keymap_path);
 53+
 54+	if (posix_fallocate(xkb->keymap.fd, 0, xkb->keymap.size) != 0) {
 55+		WARNING("Could not resize XKB keymap file\n");
 56+		goto error2;
 57+	}
 58+
 59+	xkb->keymap.area = mmap(NULL, xkb->keymap.size, PROT_READ | PROT_WRITE, MAP_SHARED, xkb->keymap.fd, 0);
 60+
 61+	if (xkb->keymap.area == MAP_FAILED) {
 62+		WARNING("Could not mmap XKB keymap string\n");
 63+		goto error2;
 64+	}
 65+
 66+	strcpy(xkb->keymap.area, keymap_string);
 67+	free(keymap_string);
 68+
 69+	return true;
 70+
 71+error2:
 72+	close(xkb->keymap.fd);
 73+error1:
 74+	free(keymap_string);
 75+error0:
 76+	return false;
 77+}
 78+
 79 bool
 80 keyboard_initialize(struct keyboard *keyboard)
 81 {
 82-	if (!xkb_initialize(&keyboard->xkb)) {
 83-		ERROR("Could not initialize XKB\n");
 84+	struct xkb *xkb = &keyboard->xkb;
 85+
 86+	if (!(xkb->context = xkb_context_new(0))) {
 87+		ERROR("Could not create XKB context\n");
 88 		goto error0;
 89 	}
 90 
 91-	if (!input_focus_initialize(&keyboard->focus, &keyboard->focus_handler))
 92+	if (!(xkb->keymap.map = xkb_keymap_new_from_names(xkb->context, NULL, 0))) {
 93+		ERROR("Could not create XKB keymap\n");
 94 		goto error1;
 95+	}
 96+
 97+	if (!(xkb->state = xkb_state_new(xkb->keymap.map))) {
 98+		ERROR("Could not create XKB state\n");
 99+		goto error2;
100+	}
101+
102+	if (!update_keymap(xkb)) {
103+		ERROR("Could not update XKB keymap\n");
104+		goto error3;
105+	}
106+
107+	if (!input_focus_initialize(&keyboard->focus, &keyboard->focus_handler))
108+		goto error3;
109 
110 	keyboard->modifier_state = (struct keyboard_modifier_state){};
111 	keyboard->modifiers = 0;
112@@ -127,8 +206,12 @@ keyboard_initialize(struct keyboard *keyboard)
113 
114 	return true;
115 
116+error3:
117+	xkb_state_unref(keyboard->xkb.state);
118+error2:
119+	xkb_keymap_unref(keyboard->xkb.keymap.map);
120 error1:
121-	xkb_finalize(&keyboard->xkb);
122+	xkb_context_unref(keyboard->xkb.context);
123 error0:
124 	return false;
125 }
126@@ -139,14 +222,19 @@ keyboard_finalize(struct keyboard *keyboard)
127 	wl_array_release(&keyboard->client_keys);
128 	wl_array_release(&keyboard->keys);
129 	input_focus_finalize(&keyboard->focus);
130-	xkb_finalize(&keyboard->xkb);
131+	munmap(keyboard->xkb.keymap.area, keyboard->xkb.keymap.size);
132+	close(keyboard->xkb.keymap.fd);
133+	xkb_state_unref(keyboard->xkb.state);
134+	xkb_keymap_unref(keyboard->xkb.keymap.map);
135+	xkb_context_unref(keyboard->xkb.context);
136 }
137 
138-void
139+bool
140 keyboard_reset(struct keyboard *keyboard)
141 {
142 	struct key *key;
143 	uint32_t time = get_time();
144+	struct xkb_state *state;
145 
146 	/* Send simulated key release events for all current key handlers. */
147 	wl_array_for_each (key, &keyboard->keys) {
148@@ -165,7 +253,16 @@ keyboard_reset(struct keyboard *keyboard)
149 	keyboard->keys.size = 0;
150 	keyboard->modifier_state = (struct keyboard_modifier_state){};
151 	keyboard->modifiers = 0;
152-	xkb_reset_state(&keyboard->xkb);
153+
154+	if (!(state = xkb_state_new(keyboard->xkb.keymap.map))) {
155+		ERROR("Failed to allocate new XKB state\n");
156+		return false;
157+	}
158+
159+	xkb_state_unref(keyboard->xkb.state);
160+	keyboard->xkb.state = state;
161+
162+	return true;
163 }
164 
165 /**
+20, -2
 1@@ -25,10 +25,12 @@
 2 #define SWC_KEYBOARD_H
 3 
 4 #include "input.h"
 5-#include "xkb.h"
 6 
 7 #include <wayland-util.h>
 8 
 9+/* Keycodes are offset by 8 in XKB. */
10+#define XKB_KEY(key) ((key) + 8)
11+
12 struct keyboard;
13 struct wl_client;
14 
15@@ -51,6 +53,22 @@ struct keyboard_handler {
16 	struct wl_list link;
17 };
18 
19+struct xkb {
20+	struct xkb_context *context;
21+	struct xkb_state *state;
22+
23+	struct {
24+		struct xkb_keymap *map;
25+		int fd;
26+		uint32_t size;
27+		char *area;
28+	} keymap;
29+
30+	struct {
31+		uint32_t ctrl, alt, super, shift;
32+	} indices;
33+};
34+
35 struct keyboard {
36 	struct input_focus focus;
37 	struct input_focus_handler focus_handler;
38@@ -67,7 +85,7 @@ struct keyboard {
39 
40 bool keyboard_initialize(struct keyboard *keyboard);
41 void keyboard_finalize(struct keyboard *keyboard);
42-void keyboard_reset(struct keyboard *keyboard);
43+bool keyboard_reset(struct keyboard *keyboard);
44 void keyboard_set_focus(struct keyboard *keyboard, struct compositor_view *view);
45 struct wl_resource *keyboard_bind(struct keyboard *keyboard, struct wl_client *client, uint32_t version, uint32_t id);
46 void keyboard_handle_key(struct keyboard *keyboard, uint32_t time, uint32_t key, uint32_t state);
+0, -1
1@@ -54,7 +54,6 @@ SWC_SOURCES =                       \
2     libswc/xdg_popup.c              \
3     libswc/xdg_shell.c              \
4     libswc/xdg_surface.c            \
5-    libswc/xkb.c                    \
6     protocol/swc-protocol.c         \
7     protocol/wayland-drm-protocol.c \
8     protocol/xdg-shell-protocol.c
+0, -159
  1@@ -1,159 +0,0 @@
  2-/* swc: libswc/xkb.c
  3- *
  4- * Copyright (c) 2013, 2014 Michael Forney
  5- *
  6- * Permission is hereby granted, free of charge, to any person obtaining a copy
  7- * of this software and associated documentation files (the "Software"), to deal
  8- * in the Software without restriction, including without limitation the rights
  9- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 10- * copies of the Software, and to permit persons to whom the Software is
 11- * furnished to do so, subject to the following conditions:
 12- *
 13- * The above copyright notice and this permission notice shall be included in
 14- * all copies or substantial portions of the Software.
 15- *
 16- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 21- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 22- * SOFTWARE.
 23- */
 24-
 25-#include "xkb.h"
 26-#include "util.h"
 27-
 28-#include <stdlib.h>
 29-#include <fcntl.h>
 30-#include <unistd.h>
 31-#include <string.h>
 32-#include <sys/mman.h>
 33-#include <xkbcommon/xkbcommon.h>
 34-
 35-static const char keymap_file_template[] = "swc-xkb-keymap-XXXXXX";
 36-
 37-bool
 38-xkb_initialize(struct xkb *xkb)
 39-{
 40-	xkb->context = xkb_context_new(0);
 41-
 42-	if (!xkb->context) {
 43-		ERROR("Could not create XKB context\n");
 44-		goto error0;
 45-	}
 46-
 47-	xkb->keymap.map = xkb_keymap_new_from_names(xkb->context, NULL, 0);
 48-
 49-	if (!xkb->keymap.map) {
 50-		ERROR("Could not create XKB keymap\n");
 51-		goto error1;
 52-	}
 53-
 54-	xkb->state = xkb_state_new(xkb->keymap.map);
 55-
 56-	if (!xkb->state) {
 57-		ERROR("Could not create XKB state\n");
 58-		goto error2;
 59-	}
 60-
 61-	if (!xkb_update_keymap(xkb)) {
 62-		ERROR("Could not update XKB keymap\n");
 63-		goto error3;
 64-	}
 65-
 66-	return true;
 67-
 68-error3:
 69-	xkb_state_unref(xkb->state);
 70-error2:
 71-	xkb_keymap_unref(xkb->keymap.map);
 72-error1:
 73-	xkb_context_unref(xkb->context);
 74-error0:
 75-	return false;
 76-}
 77-
 78-void
 79-xkb_finalize(struct xkb *xkb)
 80-{
 81-	munmap(xkb->keymap.area, xkb->keymap.size);
 82-	close(xkb->keymap.fd);
 83-	xkb_state_unref(xkb->state);
 84-	xkb_keymap_unref(xkb->keymap.map);
 85-	xkb_context_unref(xkb->context);
 86-}
 87-
 88-bool
 89-xkb_reset_state(struct xkb *xkb)
 90-{
 91-	struct xkb_state *state;
 92-
 93-	if (!(state = xkb_state_new(xkb->keymap.map))) {
 94-		ERROR("Failed to allocate new XKB state\n");
 95-		return false;
 96-	}
 97-
 98-	xkb_state_unref(xkb->state);
 99-	xkb->state = state;
100-	return true;
101-}
102-
103-bool
104-xkb_update_keymap(struct xkb *xkb)
105-{
106-	const char *keymap_directory = getenv("XDG_RUNTIME_DIR") ?: "/tmp";
107-	char *keymap_string;
108-	char keymap_path[strlen(keymap_directory) + 1 + sizeof keymap_file_template];
109-
110-	xkb->indices.ctrl = xkb_keymap_mod_get_index(xkb->keymap.map, XKB_MOD_NAME_CTRL);
111-	xkb->indices.alt = xkb_keymap_mod_get_index(xkb->keymap.map, XKB_MOD_NAME_ALT);
112-	xkb->indices.super = xkb_keymap_mod_get_index(xkb->keymap.map, XKB_MOD_NAME_LOGO);
113-	xkb->indices.shift = xkb_keymap_mod_get_index(xkb->keymap.map, XKB_MOD_NAME_SHIFT);
114-
115-	/* In order to send the keymap to clients, we must first convert it to a
116-     * string and then mmap it to a file. */
117-	keymap_string = xkb_keymap_get_as_string(xkb->keymap.map, XKB_KEYMAP_FORMAT_TEXT_V1);
118-
119-	if (!keymap_string) {
120-		WARNING("Could not get XKB keymap as a string\n");
121-		goto error0;
122-	}
123-
124-	sprintf(keymap_path, "%s/%s", keymap_directory, keymap_file_template);
125-
126-	xkb->keymap.size = strlen(keymap_string) + 1;
127-	xkb->keymap.fd = mkostemp(keymap_path, O_CLOEXEC);
128-
129-	if (xkb->keymap.fd == -1) {
130-		WARNING("Could not create XKB keymap file\n");
131-		goto error1;
132-	}
133-
134-	unlink(keymap_path);
135-
136-	if (posix_fallocate(xkb->keymap.fd, 0, xkb->keymap.size) != 0) {
137-		WARNING("Could not resize XKB keymap file\n");
138-		goto error2;
139-	}
140-
141-	xkb->keymap.area = mmap(NULL, xkb->keymap.size, PROT_READ | PROT_WRITE, MAP_SHARED, xkb->keymap.fd, 0);
142-
143-	if (xkb->keymap.area == MAP_FAILED) {
144-		WARNING("Could not mmap XKB keymap string\n");
145-		goto error2;
146-	}
147-
148-	strcpy(xkb->keymap.area, keymap_string);
149-
150-	free(keymap_string);
151-
152-	return true;
153-
154-error2:
155-	close(xkb->keymap.fd);
156-error1:
157-	free(keymap_string);
158-error0:
159-	return false;
160-}
+0, -54
 1@@ -1,54 +0,0 @@
 2-/* swc: libswc/xkb.h
 3- *
 4- * Copyright (c) 2013, 2014 Michael Forney
 5- *
 6- * Permission is hereby granted, free of charge, to any person obtaining a copy
 7- * of this software and associated documentation files (the "Software"), to deal
 8- * in the Software without restriction, including without limitation the rights
 9- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10- * copies of the Software, and to permit persons to whom the Software is
11- * furnished to do so, subject to the following conditions:
12- *
13- * The above copyright notice and this permission notice shall be included in
14- * all copies or substantial portions of the Software.
15- *
16- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22- * SOFTWARE.
23- */
24-
25-#ifndef SWC_XKB_H
26-#define SWC_XKB_H
27-
28-#include <stdbool.h>
29-#include <stdint.h>
30-
31-/* Keycodes are offset by 8 in XKB. */
32-#define XKB_KEY(key) ((key) + 8)
33-
34-struct xkb {
35-	struct xkb_context *context;
36-	struct xkb_state *state;
37-
38-	struct {
39-		struct xkb_keymap *map;
40-		int fd;
41-		uint32_t size;
42-		char *area;
43-	} keymap;
44-
45-	struct {
46-		uint32_t ctrl, alt, super, shift;
47-	} indices;
48-};
49-
50-bool xkb_initialize(struct xkb *xkb);
51-void xkb_finalize(struct xkb *xkb);
52-bool xkb_reset_state(struct xkb *xkb);
53-bool xkb_update_keymap(struct xkb *xkb);
54-
55-#endif