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>
39 #include "uterm_input.h"
41 #define LOG_SUBSYSTEM "input_uxkb"
43 int uxkb_desc_init(struct uterm_input *input,
49 struct xkb_rule_names rmlvo = {
57 input->ctx = xkb_context_new(0);
59 log_error("cannot create XKB context");
63 input->keymap = xkb_keymap_new_from_names(input->ctx, &rmlvo, 0);
65 log_warn("failed to create keymap (%s, %s, %s), "
66 "reverting to default system keymap",
67 layout, variant, options);
73 input->keymap = xkb_keymap_new_from_names(input->ctx,
76 log_warn("failed to create XKB keymap");
82 log_debug("new keyboard description (%s, %s, %s)",
83 layout, variant, options);
87 xkb_context_unref(input->ctx);
91 void uxkb_desc_destroy(struct uterm_input *input)
93 xkb_keymap_unref(input->keymap);
94 xkb_context_unref(input->ctx);
97 static void timer_event(struct ev_timer *timer, uint64_t num, void *data)
99 struct uterm_input_dev *dev = data;
101 dev->repeat_event.handled = false;
102 shl_hook_call(dev->input->hook, dev->input, &dev->repeat_event);
105 int uxkb_dev_init(struct uterm_input_dev *dev)
109 ret = ev_eloop_new_timer(dev->input->eloop, &dev->repeat_timer, NULL,
114 dev->state = xkb_state_new(dev->input->keymap);
116 log_error("cannot create XKB state");
124 ev_eloop_rm_timer(dev->repeat_timer);
128 void uxkb_dev_destroy(struct uterm_input_dev *dev)
130 xkb_state_unref(dev->state);
131 ev_eloop_rm_timer(dev->repeat_timer);
134 #define EVDEV_KEYCODE_OFFSET 8
141 static void uxkb_dev_update_keyboard_leds(struct uterm_input_dev *dev)
143 static const struct {
147 { LED_NUML, XKB_LED_NAME_NUM },
148 { LED_CAPSL, XKB_LED_NAME_CAPS },
149 { LED_SCROLLL, XKB_LED_NAME_SCROLL },
151 struct input_event events[sizeof(leds) / sizeof(*leds)];
154 if (!(dev->capabilities & UTERM_DEVICE_HAS_LEDS))
157 memset(events, 0, sizeof(events));
159 for (i = 0; i < sizeof(leds) / sizeof(*leds); i++) {
160 events[i].type = EV_LED;
161 events[i].code = leds[i].evdev_led;
162 if (xkb_state_led_name_is_active(dev->state,
163 leds[i].xkb_led) > 0)
167 write(dev->rfd, events, sizeof(events));
170 static inline int uxkb_dev_resize_event(struct uterm_input_dev *dev, size_t s)
174 if (s > dev->num_syms) {
175 tmp = realloc(dev->event.keysyms,
176 sizeof(uint32_t) * s);
178 log_warning("cannot reallocate keysym buffer");
181 dev->event.keysyms = tmp;
183 tmp = realloc(dev->event.codepoints,
184 sizeof(uint32_t) * s);
186 log_warning("cannot reallocate codepoints buffer");
189 dev->event.codepoints = tmp;
191 tmp = realloc(dev->repeat_event.keysyms,
192 sizeof(uint32_t) * s);
194 log_warning("cannot reallocate keysym buffer");
197 dev->repeat_event.keysyms = tmp;
199 tmp = realloc(dev->repeat_event.codepoints,
200 sizeof(uint32_t) * s);
202 log_warning("cannot reallocate codepoints buffer");
205 dev->repeat_event.codepoints = tmp;
213 static int uxkb_dev_fill_event(struct uterm_input_dev *dev,
214 struct uterm_input_event *ev,
217 const xkb_keysym_t *syms)
221 ret = uxkb_dev_resize_event(dev, num_syms);
226 ev->ascii = shl_get_ascii(dev->state, code, syms, num_syms);
227 ev->mods = shl_get_xkb_mods(dev->state);
228 ev->num_syms = num_syms;
229 memcpy(ev->keysyms, syms, sizeof(uint32_t) * num_syms);
231 for (i = 0; i < num_syms; ++i) {
232 ev->codepoints[i] = xkb_keysym_to_utf32(syms[i]);
233 if (!ev->codepoints[i])
234 ev->codepoints[i] = UTERM_INPUT_INVALID;
240 static void uxkb_dev_repeat(struct uterm_input_dev *dev, unsigned int state)
242 struct xkb_keymap *keymap = xkb_state_get_keymap(dev->state);
244 int num_keysyms, ret;
245 const uint32_t *keysyms;
246 struct itimerspec spec;
248 if (dev->repeating && dev->repeat_event.keycode == dev->event.keycode) {
249 if (state == KEY_RELEASED) {
250 dev->repeating = false;
251 ev_timer_update(dev->repeat_timer, NULL);
256 if (state == KEY_PRESSED &&
257 xkb_keymap_key_repeats(keymap, dev->event.keycode)) {
258 dev->repeat_event.keycode = dev->event.keycode;
259 dev->repeat_event.ascii = dev->event.ascii;
260 dev->repeat_event.mods = dev->event.mods;
261 dev->repeat_event.num_syms = dev->event.num_syms;
263 for (i = 0; i < dev->event.num_syms; ++i) {
264 dev->repeat_event.keysyms[i] = dev->event.keysyms[i];
265 dev->repeat_event.codepoints[i] =
266 dev->event.codepoints[i];
268 } else if (dev->repeating &&
269 !xkb_keymap_key_repeats(keymap, dev->event.keycode)) {
270 num_keysyms = xkb_state_key_get_syms(dev->state,
271 dev->repeat_event.keycode,
273 if (num_keysyms <= 0)
276 ret = uxkb_dev_fill_event(dev, &dev->repeat_event,
277 dev->repeat_event.keycode,
278 num_keysyms, keysyms);
287 dev->repeating = true;
288 spec.it_interval.tv_sec = 0;
289 spec.it_interval.tv_nsec = dev->input->repeat_rate * 1000000;
290 spec.it_value.tv_sec = 0;
291 spec.it_value.tv_nsec = dev->input->repeat_delay * 1000000;
292 ev_timer_update(dev->repeat_timer, &spec);
295 int uxkb_dev_process(struct uterm_input_dev *dev,
296 uint16_t key_state, uint16_t code)
298 struct xkb_state *state;
299 xkb_keycode_t keycode;
300 const xkb_keysym_t *keysyms;
301 int num_keysyms, ret;
302 enum xkb_state_component changed;
304 if (key_state == KEY_REPEATED)
308 keycode = code + EVDEV_KEYCODE_OFFSET;
310 num_keysyms = xkb_state_key_get_syms(state, keycode, &keysyms);
313 if (key_state == KEY_PRESSED)
314 changed = xkb_state_update_key(state, keycode, XKB_KEY_DOWN);
315 else if (key_state == KEY_RELEASED)
316 changed = xkb_state_update_key(state, keycode, XKB_KEY_UP);
318 if (changed & XKB_STATE_LEDS)
319 uxkb_dev_update_keyboard_leds(dev);
321 if (num_keysyms <= 0)
324 ret = uxkb_dev_fill_event(dev, &dev->event, keycode, num_keysyms,
329 uxkb_dev_repeat(dev, key_state);
331 if (key_state == KEY_RELEASED)
334 dev->event.handled = false;
335 shl_hook_call(dev->input->hook, dev->input, &dev->event);
341 * Call this when we regain control of the keyboard after losing it.
342 * We don't reset the locked group, this should survive a VT switch, etc.
344 void uxkb_dev_reset(struct uterm_input_dev *dev)
346 struct xkb_state *state;
348 /* TODO: Urghs, while the input device was closed we might have missed
349 * some events that affect internal state. As xkbcommon does not provide
350 * a way to reset the internal state, we simply recreate the state. This
351 * should have the same effect.
352 * It also has a bug that if the CTRL-Release event is skipped, then
353 * every further release will never perform a _real_ release. Kind of
354 * buggy so we should fix it upstream. */
355 state = xkb_state_new(dev->input->keymap);
357 log_warning("cannot recreate xkb-state");
360 xkb_state_unref(dev->state);
363 uxkb_dev_update_keyboard_leds(dev);