1 #include "util/array.h"
2 #include <assert.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <wayland-server-core.h>
6 #include <wlr/interfaces/wlr_keyboard.h>
7 #include <wlr/types/wlr_keyboard.h>
8 #include <wlr/util/log.h>
9 #include "types/wlr_keyboard.h"
10 #include "util/signal.h"
11 
keyboard_led_update(struct wlr_keyboard * keyboard)12 void keyboard_led_update(struct wlr_keyboard *keyboard) {
13 	if (keyboard->xkb_state == NULL) {
14 		return;
15 	}
16 
17 	uint32_t leds = 0;
18 	for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) {
19 		if (xkb_state_led_index_is_active(keyboard->xkb_state,
20 				keyboard->led_indexes[i])) {
21 			leds |= (1 << i);
22 		}
23 	}
24 	wlr_keyboard_led_update(keyboard, leds);
25 }
26 
27 /**
28  * Update the modifier state of the wlr-keyboard. Returns true if the modifier
29  * state changed.
30  */
keyboard_modifier_update(struct wlr_keyboard * keyboard)31 bool keyboard_modifier_update(struct wlr_keyboard *keyboard) {
32 	if (keyboard->xkb_state == NULL) {
33 		return false;
34 	}
35 
36 	xkb_mod_mask_t depressed = xkb_state_serialize_mods(keyboard->xkb_state,
37 		XKB_STATE_MODS_DEPRESSED);
38 	xkb_mod_mask_t latched = xkb_state_serialize_mods(keyboard->xkb_state,
39 		XKB_STATE_MODS_LATCHED);
40 	xkb_mod_mask_t locked = xkb_state_serialize_mods(keyboard->xkb_state,
41 		XKB_STATE_MODS_LOCKED);
42 	xkb_mod_mask_t group = xkb_state_serialize_layout(keyboard->xkb_state,
43 		XKB_STATE_LAYOUT_EFFECTIVE);
44 	if (depressed == keyboard->modifiers.depressed &&
45 			latched == keyboard->modifiers.latched &&
46 			locked == keyboard->modifiers.locked &&
47 			group == keyboard->modifiers.group) {
48 		return false;
49 	}
50 
51 	keyboard->modifiers.depressed = depressed;
52 	keyboard->modifiers.latched = latched;
53 	keyboard->modifiers.locked = locked;
54 	keyboard->modifiers.group = group;
55 
56 	return true;
57 }
58 
keyboard_key_update(struct wlr_keyboard * keyboard,struct wlr_event_keyboard_key * event)59 void keyboard_key_update(struct wlr_keyboard *keyboard,
60 		struct wlr_event_keyboard_key *event) {
61 	if (event->state == WLR_KEY_PRESSED) {
62 		set_add(keyboard->keycodes, &keyboard->num_keycodes,
63 			WLR_KEYBOARD_KEYS_CAP, event->keycode);
64 	}
65 	if (event->state == WLR_KEY_RELEASED) {
66 		set_remove(keyboard->keycodes, &keyboard->num_keycodes,
67 			WLR_KEYBOARD_KEYS_CAP, event->keycode);
68 	}
69 
70 	assert(keyboard->num_keycodes <= WLR_KEYBOARD_KEYS_CAP);
71 }
72 
wlr_keyboard_notify_modifiers(struct wlr_keyboard * keyboard,uint32_t mods_depressed,uint32_t mods_latched,uint32_t mods_locked,uint32_t group)73 void wlr_keyboard_notify_modifiers(struct wlr_keyboard *keyboard,
74 		uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked,
75 		uint32_t group) {
76 	if (keyboard->xkb_state == NULL) {
77 		return;
78 	}
79 	xkb_state_update_mask(keyboard->xkb_state, mods_depressed, mods_latched,
80 		mods_locked, 0, 0, group);
81 
82 	bool updated = keyboard_modifier_update(keyboard);
83 	if (updated) {
84 		wlr_signal_emit_safe(&keyboard->events.modifiers, keyboard);
85 	}
86 
87 	keyboard_led_update(keyboard);
88 }
89 
wlr_keyboard_notify_key(struct wlr_keyboard * keyboard,struct wlr_event_keyboard_key * event)90 void wlr_keyboard_notify_key(struct wlr_keyboard *keyboard,
91 		struct wlr_event_keyboard_key *event) {
92 	keyboard_key_update(keyboard, event);
93 	wlr_signal_emit_safe(&keyboard->events.key, event);
94 
95 	if (keyboard->xkb_state == NULL) {
96 		return;
97 	}
98 
99 	if (event->update_state) {
100 		uint32_t keycode = event->keycode + 8;
101 		xkb_state_update_key(keyboard->xkb_state, keycode,
102 			event->state == WLR_KEY_PRESSED ? XKB_KEY_DOWN : XKB_KEY_UP);
103 	}
104 
105 	bool updated = keyboard_modifier_update(keyboard);
106 	if (updated) {
107 		wlr_signal_emit_safe(&keyboard->events.modifiers, keyboard);
108 	}
109 
110 	keyboard_led_update(keyboard);
111 }
112 
wlr_keyboard_init(struct wlr_keyboard * kb,const struct wlr_keyboard_impl * impl)113 void wlr_keyboard_init(struct wlr_keyboard *kb,
114 		const struct wlr_keyboard_impl *impl) {
115 	kb->impl = impl;
116 	wl_signal_init(&kb->events.key);
117 	wl_signal_init(&kb->events.modifiers);
118 	wl_signal_init(&kb->events.keymap);
119 	wl_signal_init(&kb->events.repeat_info);
120 	wl_signal_init(&kb->events.destroy);
121 
122 	// Sane defaults
123 	kb->repeat_info.rate = 25;
124 	kb->repeat_info.delay = 600;
125 }
126 
wlr_keyboard_destroy(struct wlr_keyboard * kb)127 void wlr_keyboard_destroy(struct wlr_keyboard *kb) {
128 	if (kb == NULL) {
129 		return;
130 	}
131 	wlr_signal_emit_safe(&kb->events.destroy, kb);
132 	xkb_state_unref(kb->xkb_state);
133 	xkb_keymap_unref(kb->keymap);
134 	free(kb->keymap_string);
135 	if (kb->impl && kb->impl->destroy) {
136 		kb->impl->destroy(kb);
137 	} else {
138 		wl_list_remove(&kb->events.key.listener_list);
139 		free(kb);
140 	}
141 }
142 
wlr_keyboard_led_update(struct wlr_keyboard * kb,uint32_t leds)143 void wlr_keyboard_led_update(struct wlr_keyboard *kb, uint32_t leds) {
144 	if (kb->impl && kb->impl->led_update) {
145 		kb->impl->led_update(kb, leds);
146 	}
147 }
148 
wlr_keyboard_set_keymap(struct wlr_keyboard * kb,struct xkb_keymap * keymap)149 bool wlr_keyboard_set_keymap(struct wlr_keyboard *kb,
150 		struct xkb_keymap *keymap) {
151 	xkb_keymap_unref(kb->keymap);
152 	kb->keymap = xkb_keymap_ref(keymap);
153 
154 	xkb_state_unref(kb->xkb_state);
155 	kb->xkb_state = xkb_state_new(kb->keymap);
156 	if (kb->xkb_state == NULL) {
157 		wlr_log(WLR_ERROR, "Failed to create XKB state");
158 		goto err;
159 	}
160 
161 	const char *led_names[WLR_LED_COUNT] = {
162 		XKB_LED_NAME_NUM,
163 		XKB_LED_NAME_CAPS,
164 		XKB_LED_NAME_SCROLL,
165 	};
166 	for (size_t i = 0; i < WLR_LED_COUNT; ++i) {
167 		kb->led_indexes[i] = xkb_map_led_get_index(kb->keymap, led_names[i]);
168 	}
169 
170 	const char *mod_names[WLR_MODIFIER_COUNT] = {
171 		XKB_MOD_NAME_SHIFT,
172 		XKB_MOD_NAME_CAPS,
173 		XKB_MOD_NAME_CTRL, // "Control"
174 		XKB_MOD_NAME_ALT, // "Mod1"
175 		XKB_MOD_NAME_NUM, // "Mod2"
176 		"Mod3",
177 		XKB_MOD_NAME_LOGO, // "Mod4"
178 		"Mod5",
179 	};
180 	// TODO: there's also "Ctrl", "Alt"?
181 	for (size_t i = 0; i < WLR_MODIFIER_COUNT; ++i) {
182 		kb->mod_indexes[i] = xkb_map_mod_get_index(kb->keymap, mod_names[i]);
183 	}
184 
185 	char *tmp_keymap_string = xkb_keymap_get_as_string(kb->keymap,
186 		XKB_KEYMAP_FORMAT_TEXT_V1);
187 	if (tmp_keymap_string == NULL) {
188 		wlr_log(WLR_ERROR, "Failed to get string version of keymap");
189 		goto err;
190 	}
191 	free(kb->keymap_string);
192 	kb->keymap_string = tmp_keymap_string;
193 	kb->keymap_size = strlen(kb->keymap_string) + 1;
194 
195 	for (size_t i = 0; i < kb->num_keycodes; ++i) {
196 		xkb_keycode_t keycode = kb->keycodes[i] + 8;
197 		xkb_state_update_key(kb->xkb_state, keycode, XKB_KEY_DOWN);
198 	}
199 
200 	keyboard_modifier_update(kb);
201 
202 	wlr_signal_emit_safe(&kb->events.keymap, kb);
203 	return true;
204 
205 err:
206 	xkb_state_unref(kb->xkb_state);
207 	kb->xkb_state = NULL;
208 	xkb_keymap_unref(keymap);
209 	kb->keymap = NULL;
210 	free(kb->keymap_string);
211 	kb->keymap_string = NULL;
212 	return false;
213 }
214 
wlr_keyboard_set_repeat_info(struct wlr_keyboard * kb,int32_t rate,int32_t delay)215 void wlr_keyboard_set_repeat_info(struct wlr_keyboard *kb, int32_t rate,
216 		int32_t delay) {
217 	if (kb->repeat_info.rate == rate && kb->repeat_info.delay == delay) {
218 		return;
219 	}
220 	kb->repeat_info.rate = rate;
221 	kb->repeat_info.delay = delay;
222 	wlr_signal_emit_safe(&kb->events.repeat_info, kb);
223 }
224 
wlr_keyboard_get_modifiers(struct wlr_keyboard * kb)225 uint32_t wlr_keyboard_get_modifiers(struct wlr_keyboard *kb) {
226 	xkb_mod_mask_t mask = kb->modifiers.depressed | kb->modifiers.latched;
227 	uint32_t modifiers = 0;
228 	for (size_t i = 0; i < WLR_MODIFIER_COUNT; ++i) {
229 		if (kb->mod_indexes[i] != XKB_MOD_INVALID &&
230 				(mask & (1 << kb->mod_indexes[i]))) {
231 			modifiers |= (1 << i);
232 		}
233 	}
234 	return modifiers;
235 }
236 
wlr_keyboard_keymaps_match(struct xkb_keymap * km1,struct xkb_keymap * km2)237 bool wlr_keyboard_keymaps_match(struct xkb_keymap *km1,
238 		struct xkb_keymap *km2) {
239 	if (!km1 && !km2) {
240 		return true;
241 	}
242 	if (!km1 || !km2) {
243 		return false;
244 	}
245 	char *km1_str = xkb_keymap_get_as_string(km1, XKB_KEYMAP_FORMAT_TEXT_V1);
246 	char *km2_str = xkb_keymap_get_as_string(km2, XKB_KEYMAP_FORMAT_TEXT_V1);
247 	bool result = strcmp(km1_str, km2_str) == 0;
248 	free(km1_str);
249 	free(km2_str);
250 	return result;
251 }
252