2 * uterm - Linux User-Space Terminal
4 * Copyright (c) 2011 Ran Benita <ran234@gmail.com>
5 * Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com>
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files
9 * (the "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 #include <linux/input.h>
34 #include <xkbcommon/xkbcommon.h>
38 #include "uterm_input.h"
39 #include "uterm_input_internal.h"
41 #define LOG_SUBSYSTEM "input_uxkb"
43 int uxkb_desc_init(struct uterm_input *input,
50 struct xkb_rule_names rmlvo = {
58 input->ctx = xkb_context_new(0);
60 log_error("cannot create XKB context");
64 input->keymap = xkb_keymap_new_from_names(input->ctx, &rmlvo, 0);
66 log_warn("failed to create keymap (%s, %s, %s, %s), "
67 "reverting to default system keymap",
68 model, layout, variant, options);
75 input->keymap = xkb_keymap_new_from_names(input->ctx,
78 log_warn("failed to create XKB keymap");
84 log_debug("new keyboard description (%s, %s, %s, %s)",
85 model, layout, variant, options);
89 xkb_context_unref(input->ctx);
93 void uxkb_desc_destroy(struct uterm_input *input)
95 xkb_keymap_unref(input->keymap);
96 xkb_context_unref(input->ctx);
99 static void timer_event(struct ev_timer *timer, uint64_t num, void *data)
101 struct uterm_input_dev *dev = data;
103 dev->repeat_event.handled = false;
104 shl_hook_call(dev->input->hook, dev->input, &dev->repeat_event);
107 int uxkb_dev_init(struct uterm_input_dev *dev)
111 ret = ev_eloop_new_timer(dev->input->eloop, &dev->repeat_timer, NULL,
116 dev->state = xkb_state_new(dev->input->keymap);
118 log_error("cannot create XKB state");
126 ev_eloop_rm_timer(dev->repeat_timer);
130 void uxkb_dev_destroy(struct uterm_input_dev *dev)
132 xkb_state_unref(dev->state);
133 ev_eloop_rm_timer(dev->repeat_timer);
136 #define EVDEV_KEYCODE_OFFSET 8
143 static void uxkb_dev_update_keyboard_leds(struct uterm_input_dev *dev)
145 static const struct {
149 { LED_NUML, XKB_LED_NAME_NUM },
150 { LED_CAPSL, XKB_LED_NAME_CAPS },
151 { LED_SCROLLL, XKB_LED_NAME_SCROLL },
153 struct input_event events[sizeof(leds) / sizeof(*leds)];
156 if (!(dev->capabilities & UTERM_DEVICE_HAS_LEDS))
159 memset(events, 0, sizeof(events));
161 for (i = 0; i < sizeof(leds) / sizeof(*leds); i++) {
162 events[i].type = EV_LED;
163 events[i].code = leds[i].evdev_led;
164 if (xkb_state_led_name_is_active(dev->state,
165 leds[i].xkb_led) > 0)
169 ret = write(dev->rfd, events, sizeof(events));
170 if (ret != sizeof(events))
171 log_warning("cannot update LED state (%d): %m", errno);
174 static inline int uxkb_dev_resize_event(struct uterm_input_dev *dev, size_t s)
178 if (s > dev->num_syms) {
179 tmp = realloc(dev->event.keysyms,
180 sizeof(uint32_t) * s);
182 log_warning("cannot reallocate keysym buffer");
185 dev->event.keysyms = tmp;
187 tmp = realloc(dev->event.codepoints,
188 sizeof(uint32_t) * s);
190 log_warning("cannot reallocate codepoints buffer");
193 dev->event.codepoints = tmp;
195 tmp = realloc(dev->repeat_event.keysyms,
196 sizeof(uint32_t) * s);
198 log_warning("cannot reallocate keysym buffer");
201 dev->repeat_event.keysyms = tmp;
203 tmp = realloc(dev->repeat_event.codepoints,
204 sizeof(uint32_t) * s);
206 log_warning("cannot reallocate codepoints buffer");
209 dev->repeat_event.codepoints = tmp;
217 static int uxkb_dev_fill_event(struct uterm_input_dev *dev,
218 struct uterm_input_event *ev,
221 const xkb_keysym_t *syms)
225 ret = uxkb_dev_resize_event(dev, num_syms);
230 ev->ascii = shl_get_ascii(dev->state, code, syms, num_syms);
231 ev->mods = shl_get_xkb_mods(dev->state);
232 ev->num_syms = num_syms;
233 memcpy(ev->keysyms, syms, sizeof(uint32_t) * num_syms);
235 for (i = 0; i < num_syms; ++i) {
236 ev->codepoints[i] = xkb_keysym_to_utf32(syms[i]);
237 if (!ev->codepoints[i])
238 ev->codepoints[i] = UTERM_INPUT_INVALID;
244 static void uxkb_dev_repeat(struct uterm_input_dev *dev, unsigned int state)
246 struct xkb_keymap *keymap = xkb_state_get_keymap(dev->state);
248 int num_keysyms, ret;
249 const uint32_t *keysyms;
250 struct itimerspec spec;
252 if (dev->repeating && dev->repeat_event.keycode == dev->event.keycode) {
253 if (state == KEY_RELEASED) {
254 dev->repeating = false;
255 ev_timer_update(dev->repeat_timer, NULL);
260 if (state == KEY_PRESSED &&
261 xkb_keymap_key_repeats(keymap, dev->event.keycode)) {
262 dev->repeat_event.keycode = dev->event.keycode;
263 dev->repeat_event.ascii = dev->event.ascii;
264 dev->repeat_event.mods = dev->event.mods;
265 dev->repeat_event.num_syms = dev->event.num_syms;
267 for (i = 0; i < dev->event.num_syms; ++i) {
268 dev->repeat_event.keysyms[i] = dev->event.keysyms[i];
269 dev->repeat_event.codepoints[i] =
270 dev->event.codepoints[i];
272 } else if (dev->repeating &&
273 !xkb_keymap_key_repeats(keymap, dev->event.keycode)) {
274 num_keysyms = xkb_state_key_get_syms(dev->state,
275 dev->repeat_event.keycode,
277 if (num_keysyms <= 0)
280 ret = uxkb_dev_fill_event(dev, &dev->repeat_event,
281 dev->repeat_event.keycode,
282 num_keysyms, keysyms);
291 dev->repeating = true;
292 spec.it_interval.tv_sec = 0;
293 spec.it_interval.tv_nsec = dev->input->repeat_rate * 1000000;
294 spec.it_value.tv_sec = 0;
295 spec.it_value.tv_nsec = dev->input->repeat_delay * 1000000;
296 ev_timer_update(dev->repeat_timer, &spec);
299 int uxkb_dev_process(struct uterm_input_dev *dev,
300 uint16_t key_state, uint16_t code)
302 struct xkb_state *state;
303 xkb_keycode_t keycode;
304 const xkb_keysym_t *keysyms;
305 int num_keysyms, ret;
306 enum xkb_state_component changed;
308 if (key_state == KEY_REPEATED)
312 keycode = code + EVDEV_KEYCODE_OFFSET;
314 num_keysyms = xkb_state_key_get_syms(state, keycode, &keysyms);
317 if (key_state == KEY_PRESSED)
318 changed = xkb_state_update_key(state, keycode, XKB_KEY_DOWN);
319 else if (key_state == KEY_RELEASED)
320 changed = xkb_state_update_key(state, keycode, XKB_KEY_UP);
322 if (changed & XKB_STATE_LEDS)
323 uxkb_dev_update_keyboard_leds(dev);
325 if (num_keysyms <= 0)
328 ret = uxkb_dev_fill_event(dev, &dev->event, keycode, num_keysyms,
333 uxkb_dev_repeat(dev, key_state);
335 if (key_state == KEY_RELEASED)
338 dev->event.handled = false;
339 shl_hook_call(dev->input->hook, dev->input, &dev->event);
344 void uxkb_dev_sleep(struct uterm_input_dev *dev)
347 * While the device is asleep, we don't receive key events. This
348 * means that when we wake up, the keyboard state may be different
349 * (e.g. some key is pressed but we don't know about it). This can
350 * cause various problems, like stuck modifiers: consider if we
351 * miss a release of the left Shift key. When the user presses it
352 * again, xkb_state_update_key() will think there is *another* left
353 * Shift key that was pressed. When the key is released, it's as if
354 * this "second" key was released, but the "first" is still left
356 * To handle this, when the device goes to sleep, we save our
357 * current knowledge of the keyboard's press/release state. On wake
358 * up, we compare the states before and after, and just feed
359 * xkb_state_update_key() the deltas.
361 memset(dev->key_state_bits, 0, sizeof(dev->key_state_bits));
363 ioctl(dev->rfd, EVIOCGKEY(sizeof(dev->key_state_bits)),
364 dev->key_state_bits);
366 log_warn("failed to save keyboard state (%d): %m", errno);
369 void uxkb_dev_wake_up(struct uterm_input_dev *dev)
372 char *old_bits, cur_bits[sizeof(dev->key_state_bits)];
373 char old_bit, cur_bit;
375 old_bits = dev->key_state_bits;
377 memset(cur_bits, 0, sizeof(cur_bits));
379 ioctl(dev->rfd, EVIOCGKEY(sizeof(cur_bits)), cur_bits);
381 log_warn("failed to get current keyboard state (%d): %m",
386 for (code = 0; code < KEY_CNT; code++) {
387 old_bit = (old_bits[code / 8] & (1 << (code % 8)));
388 cur_bit = (cur_bits[code / 8] & (1 << (code % 8)));
390 if (old_bit == cur_bit)
393 xkb_state_update_key(dev->state, code + EVDEV_KEYCODE_OFFSET,
394 cur_bit ? XKB_KEY_DOWN : XKB_KEY_UP);
397 uxkb_dev_update_keyboard_leds(dev);