blob: 86bd2351e07192230e08c779652789cb3d374a0a [file] [log] [blame]
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -07001/*
2 * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
David Sodmanbf3f2842014-11-12 08:26:58 -08007#include <ctype.h>
David Sodman8ef20062015-01-06 09:23:40 -08008#include <errno.h>
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -07009#include <fcntl.h>
David Sodman8ef20062015-01-06 09:23:40 -080010#include <libudev.h>
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -070011#include <stdint.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
Dominik Behr93899452014-08-18 22:16:21 -070015#include <sys/select.h>
David Sodman8ef20062015-01-06 09:23:40 -080016#include <unistd.h>
17
David Sodmanbbcb0522014-09-19 10:34:07 -070018#include "dbus.h"
Stéphane Marchesin6cbb7332016-01-07 21:18:43 -080019#include "dbus_interface.h"
Stéphane Marchesin62561a12015-12-11 17:32:37 -080020#include "input.h"
David Sodmanbf3f2842014-11-12 08:26:58 -080021#include "keysym.h"
David Sodmanbbcb0522014-09-19 10:34:07 -070022#include "util.h"
David Sodman8ef20062015-01-06 09:23:40 -080023
Dominik Behr44e07e62016-01-13 19:43:57 -080024struct input_key_event {
25 uint16_t code;
26 unsigned char value;
27};
28
Dominik Behr93899452014-08-18 22:16:21 -070029struct input_dev {
30 int fd;
Stéphane Marchesin00ff1872015-12-14 13:40:09 -080031 char* path;
Dominik Behr93899452014-08-18 22:16:21 -070032};
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -070033
David Sodmanbf3f2842014-11-12 08:26:58 -080034struct keyboard_state {
35 int shift_state;
36 int control_state;
37 int alt_state;
David Sodmane0cc8312014-11-18 11:16:36 -080038 int search_state;
David Sodmanbf3f2842014-11-12 08:26:58 -080039};
40
Dylan Reid342aed02015-06-18 12:15:52 -070041/*
42 * structure to keep input state:
43 * udev - for udev events.
44 * udev_monitor - used to listen for udev events.
45 * udev_fd - to poll for udev messages.
46 * ndevs - number of input devices.
47 * devs - input devices to listen to.
48 * kbd_state - tracks modifier keys that are pressed.
Dylan Reid342aed02015-06-18 12:15:52 -070049 */
Dominik Behr93899452014-08-18 22:16:21 -070050struct {
Stéphane Marchesin00ff1872015-12-14 13:40:09 -080051 struct udev* udev;
52 struct udev_monitor* udev_monitor;
Dominik Behr93899452014-08-18 22:16:21 -070053 int udev_fd;
54 unsigned int ndevs;
Stéphane Marchesin00ff1872015-12-14 13:40:09 -080055 struct input_dev* devs;
David Sodmanbf3f2842014-11-12 08:26:58 -080056 struct keyboard_state kbd_state;
Dominik Behr93899452014-08-18 22:16:21 -070057} input = {
58 .udev = NULL,
59 .udev_monitor = NULL,
60 .udev_fd = -1,
61 .ndevs = 0,
62 .devs = NULL,
Dominik Behr93899452014-08-18 22:16:21 -070063};
64
Stéphane Marchesin00ff1872015-12-14 13:40:09 -080065static int input_special_key(struct input_key_event* ev)
David Sodmanbf3f2842014-11-12 08:26:58 -080066{
Stéphane Marchesin00ff1872015-12-14 13:40:09 -080067 terminal_t* terminal;
David Sodmanbf3f2842014-11-12 08:26:58 -080068
69 uint32_t ignore_keys[] = {
70 BTN_TOUCH, // touchpad events
71 BTN_TOOL_FINGER,
72 BTN_TOOL_DOUBLETAP,
73 BTN_TOOL_TRIPLETAP,
74 BTN_TOOL_QUADTAP,
75 BTN_TOOL_QUINTTAP,
76 BTN_LEFT, // mouse buttons
77 BTN_RIGHT,
78 BTN_MIDDLE,
79 BTN_SIDE,
80 BTN_EXTRA,
81 BTN_FORWARD,
82 BTN_BACK,
83 BTN_TASK
84 };
85
Dominik Behr4defb362016-01-13 12:36:14 -080086 terminal = term_get_current_terminal();
David Sodmanafba0d92015-01-27 19:07:46 -080087
Stéphane Marchesinac14d292015-12-14 15:27:18 -080088 for (unsigned int i = 0; i < ARRAY_SIZE(ignore_keys); i++)
David Sodmanbf3f2842014-11-12 08:26:58 -080089 if (ev->code == ignore_keys[i])
90 return 1;
91
92 switch (ev->code) {
93 case KEY_LEFTSHIFT:
94 case KEY_RIGHTSHIFT:
95 input.kbd_state.shift_state = ! !ev->value;
96 return 1;
97 case KEY_LEFTCTRL:
98 case KEY_RIGHTCTRL:
99 input.kbd_state.control_state = ! !ev->value;
100 return 1;
101 case KEY_LEFTALT:
102 case KEY_RIGHTALT:
103 input.kbd_state.alt_state = ! !ev->value;
104 return 1;
David Sodmane0cc8312014-11-18 11:16:36 -0800105 case KEY_LEFTMETA: // search key
106 input.kbd_state.search_state = ! !ev->value;
107 return 1;
David Sodmanbf3f2842014-11-12 08:26:58 -0800108 }
109
David Sodmanafba0d92015-01-27 19:07:46 -0800110 if (term_is_active(terminal)) {
111 if (input.kbd_state.shift_state && ev->value) {
112 switch (ev->code) {
113 case KEY_PAGEUP:
Stéphane Marchesin08c08e72016-01-07 16:44:08 -0800114 term_page_up(terminal);
David Sodmane0cc8312014-11-18 11:16:36 -0800115 return 1;
David Sodmanafba0d92015-01-27 19:07:46 -0800116 case KEY_PAGEDOWN:
Stéphane Marchesin08c08e72016-01-07 16:44:08 -0800117 term_page_down(terminal);
David Sodmane0cc8312014-11-18 11:16:36 -0800118 return 1;
David Sodmanafba0d92015-01-27 19:07:46 -0800119 case KEY_UP:
Dominik Behr58bb8e12015-09-22 14:30:41 -0700120 if (input.kbd_state.search_state)
Stéphane Marchesin08c08e72016-01-07 16:44:08 -0800121 term_page_up(terminal);
Dominik Behr58bb8e12015-09-22 14:30:41 -0700122 else
Stéphane Marchesin08c08e72016-01-07 16:44:08 -0800123 term_line_up(terminal);
David Sodmanafba0d92015-01-27 19:07:46 -0800124 return 1;
125 case KEY_DOWN:
Dominik Behr58bb8e12015-09-22 14:30:41 -0700126 if (input.kbd_state.search_state)
Stéphane Marchesin08c08e72016-01-07 16:44:08 -0800127 term_page_down(terminal);
Dominik Behr58bb8e12015-09-22 14:30:41 -0700128 else
Stéphane Marchesin08c08e72016-01-07 16:44:08 -0800129 term_line_down(terminal);
Dominik Behr58bb8e12015-09-22 14:30:41 -0700130 return 1;
David Sodmanafba0d92015-01-27 19:07:46 -0800131 }
132 }
133
134 if (!(input.kbd_state.search_state || input.kbd_state.alt_state ||
135 input.kbd_state.control_state) &&
136 ev->value && (ev->code >= KEY_F1) && (ev->code <= KEY_F10)) {
137 switch (ev->code) {
138 case KEY_F1:
139 case KEY_F2:
140 case KEY_F3:
141 case KEY_F4:
142 case KEY_F5:
143 break;
144 case KEY_F6:
145 case KEY_F7:
Dominik Behr797a3832016-01-11 15:53:11 -0800146 dbus_report_user_activity(USER_ACTIVITY_BRIGHTNESS_DOWN_KEY_PRESS -
147 (ev->code - KEY_F6));
David Sodmanafba0d92015-01-27 19:07:46 -0800148 break;
149 case KEY_F8:
150 case KEY_F9:
151 case KEY_F10:
152 break;
153 }
154 return 1;
David Sodmane0cc8312014-11-18 11:16:36 -0800155 }
156 }
157
David Sodmanbf3f2842014-11-12 08:26:58 -0800158 if (input.kbd_state.alt_state && input.kbd_state.control_state && ev->value) {
David Sodman1d1c67f2015-03-12 11:01:08 -0700159 /*
160 * Special case for key sequence that is used by external program. Just
161 * explicitly ignore here and do nothing.
162 */
163 if (input.kbd_state.shift_state)
164 return 1;
165
David Sodmanb0697c22014-12-12 10:29:25 -0800166 if (ev->code == KEY_F1) {
David Sodmanb0697c22014-12-12 10:29:25 -0800167 if (term_is_active(terminal)) {
David Sodmanf0a925a2015-05-04 11:19:19 -0700168 term_deactivate(terminal);
Stéphane Marchesin08c08e72016-01-07 16:44:08 -0800169 if (term_get_terminal(SPLASH_TERMINAL) != NULL) {
170 term_activate(term_get_terminal(SPLASH_TERMINAL));
David Sodmanf0a925a2015-05-04 11:19:19 -0700171 } else {
Dominik Behr797a3832016-01-11 15:53:11 -0800172 dbus_take_display_ownership();
David Sodmanf0a925a2015-05-04 11:19:19 -0700173 }
David Sodman8ef20062015-01-06 09:23:40 -0800174 }
David Sodmanf0a925a2015-05-04 11:19:19 -0700175 } else if ((ev->code >= KEY_F2) && (ev->code < KEY_F2 + MAX_STD_TERMINALS)) {
Dominik Behr797a3832016-01-11 15:53:11 -0800176 dbus_release_display_ownership();
David Sodmanbf3f2842014-11-12 08:26:58 -0800177 if (term_is_active(terminal))
David Sodmanf0a925a2015-05-04 11:19:19 -0700178 term_deactivate(terminal);
Dominik Behr4defb362016-01-13 12:36:14 -0800179 term_set_current(ev->code - KEY_F2);
180 terminal = term_get_current_terminal();
David Sodmanbf3f2842014-11-12 08:26:58 -0800181 if (terminal == NULL) {
Dominik Behr4defb362016-01-13 12:36:14 -0800182 term_set_current_terminal(term_init(true, NULL));
David Sodmanbf3f2842014-11-12 08:26:58 -0800183 terminal =
Dominik Behr4defb362016-01-13 12:36:14 -0800184 term_get_current_terminal();
David Sodman8ef20062015-01-06 09:23:40 -0800185 term_activate(terminal);
David Sodmanbf3f2842014-11-12 08:26:58 -0800186 if (!term_is_valid(terminal)) {
187 LOG(ERROR, "Term init failed");
188 return 1;
189 }
190 }
Dominik Behr4defb362016-01-13 12:36:14 -0800191 term_activate(term_get_current_terminal());
David Sodmanbf3f2842014-11-12 08:26:58 -0800192 }
193
194 return 1;
195
196 }
197
198 return 0;
199}
200
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800201static void input_get_keysym_and_unicode(struct input_key_event* event,
202 uint32_t* keysym, uint32_t* unicode)
David Sodmanbf3f2842014-11-12 08:26:58 -0800203{
204 struct {
205 uint32_t code;
206 uint32_t keysym;
Dominik Behr58bb8e12015-09-22 14:30:41 -0700207 } search_keys[] = {
208 { KEY_F1, KEYSYM_F1},
209 { KEY_F2, KEYSYM_F2},
210 { KEY_F3, KEYSYM_F3},
211 { KEY_F4, KEYSYM_F4},
212 { KEY_F5, KEYSYM_F5},
213 { KEY_F6, KEYSYM_F6},
214 { KEY_F7, KEYSYM_F7},
215 { KEY_F8, KEYSYM_F8},
216 { KEY_F9, KEYSYM_F8},
217 { KEY_F10, KEYSYM_F10},
218 { KEY_UP, KEYSYM_PAGEUP},
219 { KEY_DOWN, KEYSYM_PAGEDOWN},
220 { KEY_LEFT, KEYSYM_HOME},
221 { KEY_RIGHT, KEYSYM_END},
222 };
223
224 struct {
225 uint32_t code;
226 uint32_t keysym;
David Sodmanbf3f2842014-11-12 08:26:58 -0800227 } non_ascii_keys[] = {
228 { KEY_ESC, KEYSYM_ESC},
229 { KEY_HOME, KEYSYM_HOME},
230 { KEY_LEFT, KEYSYM_LEFT},
231 { KEY_UP, KEYSYM_UP},
232 { KEY_RIGHT, KEYSYM_RIGHT},
233 { KEY_DOWN, KEYSYM_DOWN},
234 { KEY_PAGEUP, KEYSYM_PAGEUP},
235 { KEY_PAGEDOWN, KEYSYM_PAGEDOWN},
236 { KEY_END, KEYSYM_END},
237 { KEY_INSERT, KEYSYM_INSERT},
238 { KEY_DELETE, KEYSYM_DELETE},
239 };
240
Dominik Behr58bb8e12015-09-22 14:30:41 -0700241 if (input.kbd_state.search_state) {
242 for (unsigned i = 0; i < ARRAY_SIZE(search_keys); i++) {
243 if (search_keys[i].code == event->code) {
244 *keysym = search_keys[i].keysym;
245 *unicode = -1;
246 return;
247 }
248 }
249 }
250
David Sodmanbf3f2842014-11-12 08:26:58 -0800251 for (unsigned i = 0; i < ARRAY_SIZE(non_ascii_keys); i++) {
252 if (non_ascii_keys[i].code == event->code) {
253 *keysym = non_ascii_keys[i].keysym;
254 *unicode = -1;
255 return;
256 }
257 }
258
259 if (event->code >= ARRAY_SIZE(keysym_table) / 2) {
260 *keysym = '?';
261 } else {
262 *keysym = keysym_table[event->code * 2 + input.kbd_state.shift_state];
263 if ((input.kbd_state.control_state) && isascii(*keysym))
264 *keysym = tolower(*keysym) - 'a' + 1;
265 }
266
267 *unicode = *keysym;
268}
269
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800270static int input_add(const char* devname)
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700271{
Dominik Behr93899452014-08-18 22:16:21 -0700272 int ret = 0, fd = -1;
Stéphane Marchesinedece332015-12-14 15:10:58 -0800273
Dominik Behr93899452014-08-18 22:16:21 -0700274 /* for some reason every device has a null enumerations and notifications
275 of every device come with NULL string first */
276 if (!devname) {
277 ret = -EINVAL;
278 goto errorret;
279 }
Haixia Shid288e032015-09-14 18:33:11 -0700280 /* check for duplicates */
Stéphane Marchesinac14d292015-12-14 15:27:18 -0800281 for (unsigned int i = 0; i < input.ndevs; ++i) {
Haixia Shid288e032015-09-14 18:33:11 -0700282 if (strcmp(devname, input.devs[i].path) == 0) {
Stéphane Marchesinc02260b2016-01-07 22:46:45 -0800283 LOG(INFO, "Skipping duplicate input device %s", devname);
Haixia Shid288e032015-09-14 18:33:11 -0700284 ret = -EINVAL;
285 goto errorret;
286 }
287 }
Dominik Behr93899452014-08-18 22:16:21 -0700288 ret = fd = open(devname, O_RDONLY);
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700289 if (fd < 0)
Dominik Behr93899452014-08-18 22:16:21 -0700290 goto errorret;
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700291
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800292 ret = ioctl(fd, EVIOCGRAB, (void*) 1);
David Sodmaneef3fd22015-08-20 15:08:52 -0700293 if (!ret) {
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800294 ret = ioctl(fd, EVIOCGRAB, (void*) 0);
David Sodmaneef3fd22015-08-20 15:08:52 -0700295 if (ret)
296 LOG(ERROR,
297 "EVIOCGRAB succeeded but the corresponding ungrab failed: %m");
298 } else {
299 LOG(ERROR, "Evdev device %s grabbed by another process",
300 devname);
301 ret = -EBUSY;
302 goto closefd;
303 }
304
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800305 struct input_dev* newdevs =
Dominik Behr93899452014-08-18 22:16:21 -0700306 realloc(input.devs, (input.ndevs + 1) * sizeof (struct input_dev));
307 if (!newdevs) {
308 ret = -ENOMEM;
309 goto closefd;
310 }
311 input.devs = newdevs;
312 input.devs[input.ndevs].fd = fd;
313 input.devs[input.ndevs].path = strdup(devname);
314 if (!input.devs[input.ndevs].path) {
315 ret = -ENOMEM;
316 goto closefd;
317 }
318 input.ndevs++;
319
320 return fd;
321
322closefd:
323 close(fd);
324errorret:
325 return ret;
326}
327
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800328static void input_remove(const char* devname)
Dominik Behr93899452014-08-18 22:16:21 -0700329{
Dominik Behr93899452014-08-18 22:16:21 -0700330 unsigned int u;
Stéphane Marchesinedece332015-12-14 15:10:58 -0800331
332 if (!devname)
333 return;
334
Dominik Behr93899452014-08-18 22:16:21 -0700335 for (u = 0; u < input.ndevs; u++) {
336 if (!strcmp(devname, input.devs[u].path)) {
337 free(input.devs[u].path);
338 close(input.devs[u].fd);
339 input.ndevs--;
340 if (u != input.ndevs) {
341 input.devs[u] = input.devs[input.ndevs];
342 }
343 return;
344 }
345 }
346}
347
Dominik Behr93899452014-08-18 22:16:21 -0700348
349int input_init()
350{
351 input.udev = udev_new();
352 if (!input.udev)
353 return -ENOENT;
Stéphane Marchesinedece332015-12-14 15:10:58 -0800354
Dominik Behr93899452014-08-18 22:16:21 -0700355 input.udev_monitor = udev_monitor_new_from_netlink(input.udev, "udev");
356 if (!input.udev_monitor) {
357 udev_unref(input.udev);
358 return -ENOENT;
359 }
360 udev_monitor_filter_add_match_subsystem_devtype(input.udev_monitor, "input",
361 NULL);
362 udev_monitor_enable_receiving(input.udev_monitor);
363 input.udev_fd = udev_monitor_get_fd(input.udev_monitor);
364
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800365 struct udev_enumerate* udev_enum;
366 struct udev_list_entry* devices, *deventry;
Dominik Behr93899452014-08-18 22:16:21 -0700367 udev_enum = udev_enumerate_new(input.udev);
368 udev_enumerate_add_match_subsystem(udev_enum, "input");
369 udev_enumerate_scan_devices(udev_enum);
370 devices = udev_enumerate_get_list_entry(udev_enum);
371 udev_list_entry_foreach(deventry, devices) {
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800372 const char* syspath;
373 struct udev_device* dev;
Dominik Behr93899452014-08-18 22:16:21 -0700374 syspath = udev_list_entry_get_name(deventry);
375 dev = udev_device_new_from_syspath(input.udev, syspath);
376 input_add(udev_device_get_devnode(dev));
377 udev_device_unref(dev);
378 }
379 udev_enumerate_unref(udev_enum);
380
381 if (!isatty(fileno(stdout)))
382 setbuf(stdout, NULL);
383
David Sodmanbbcb0522014-09-19 10:34:07 -0700384 if (input.ndevs == 0) {
385 LOG(ERROR, "No valid inputs for terminal");
386 exit(EXIT_SUCCESS);
387 }
388
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700389 return 0;
390}
391
392void input_close()
393{
Dominik Behr93899452014-08-18 22:16:21 -0700394 unsigned int u;
Stéphane Marchesinedece332015-12-14 15:10:58 -0800395
Dominik Behr93899452014-08-18 22:16:21 -0700396 for (u = 0; u < input.ndevs; u++) {
397 free(input.devs[u].path);
398 close(input.devs[u].fd);
399 }
400 free(input.devs);
401 input.devs = NULL;
402 input.ndevs = 0;
403
404 udev_monitor_unref(input.udev_monitor);
405 input.udev_monitor = NULL;
406 udev_unref(input.udev);
407 input.udev = NULL;
408 input.udev_fd = -1;
David Sodmanbbcb0522014-09-19 10:34:07 -0700409}
410
Dominik Behrd7112672016-01-20 16:59:34 -0800411void input_add_fds(fd_set* read_set, fd_set* exception_set, int *maxfd)
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700412{
Dominik Behr93899452014-08-18 22:16:21 -0700413 unsigned int u;
Stéphane Marchesinedece332015-12-14 15:10:58 -0800414
Dominik Behr93899452014-08-18 22:16:21 -0700415 for (u = 0; u < input.ndevs; u++) {
416 FD_SET(input.devs[u].fd, read_set);
417 FD_SET(input.devs[u].fd, exception_set);
Dominik Behrd7112672016-01-20 16:59:34 -0800418 if (input.devs[u].fd > *maxfd)
419 *maxfd = input.devs[u].fd;
Dominik Behr93899452014-08-18 22:16:21 -0700420 }
421
422 FD_SET(input.udev_fd, read_set);
423 FD_SET(input.udev_fd, exception_set);
Dominik Behrd7112672016-01-20 16:59:34 -0800424 if (input.udev_fd > *maxfd)
425 *maxfd = input.udev_fd;
Dominik Behr93899452014-08-18 22:16:21 -0700426}
427
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800428struct input_key_event* input_get_event(fd_set* read_set,
429 fd_set* exception_set)
Dominik Behr93899452014-08-18 22:16:21 -0700430{
431 unsigned int u;
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700432 struct input_event ev;
433 int ret;
434
Dominik Behr93899452014-08-18 22:16:21 -0700435 if (FD_ISSET(input.udev_fd, exception_set)) {
436 /* udev died on us? */
David Sodmanbbcb0522014-09-19 10:34:07 -0700437 LOG(ERROR, "Exception on udev fd");
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700438 }
439
Dominik Behr93899452014-08-18 22:16:21 -0700440 if (FD_ISSET(input.udev_fd, read_set)
441 && !FD_ISSET(input.udev_fd, exception_set)) {
442 /* we got an udev notification */
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800443 struct udev_device* dev =
Dominik Behr93899452014-08-18 22:16:21 -0700444 udev_monitor_receive_device(input.udev_monitor);
445 if (dev) {
446 if (!strcmp("add", udev_device_get_action(dev))) {
447 input_add(udev_device_get_devnode(dev));
448 } else
449 if (!strcmp("remove", udev_device_get_action(dev)))
450 {
451 input_remove(udev_device_get_devnode(dev));
452 }
453 udev_device_unref(dev);
454 }
455 }
456
457 for (u = 0; u < input.ndevs; u++) {
458 if (FD_ISSET(input.devs[u].fd, read_set)
459 && !FD_ISSET(input.devs[u].fd, exception_set)) {
460 ret =
461 read(input.devs[u].fd, &ev, sizeof (struct input_event));
Michael Spang24d20122015-04-22 13:58:16 -0400462 if (ret < 0) {
463 if (errno == EINTR || errno == EAGAIN)
464 continue;
465 if (errno != ENODEV) {
466 LOG(ERROR, "read: %s: %s", input.devs[u].path,
467 strerror(errno));
468 }
469 input_remove(input.devs[u].path);
470 return NULL;
471 } else if (ret < (int) sizeof (struct input_event)) {
David Sodmanbbcb0522014-09-19 10:34:07 -0700472 LOG(ERROR, "expected %d bytes, got %d",
Dominik Behr93899452014-08-18 22:16:21 -0700473 (int) sizeof (struct input_event), ret);
474 return NULL;
475 }
476
477 if (ev.type == EV_KEY) {
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800478 struct input_key_event* event =
Dominik Behr93899452014-08-18 22:16:21 -0700479 malloc(sizeof (*event));
480 event->code = ev.code;
481 event->value = ev.value;
Dominik Behr93899452014-08-18 22:16:21 -0700482 return event;
483 }
484 }
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700485 }
486
487 return NULL;
488}
489
Dominik Behr4defb362016-01-13 12:36:14 -0800490void input_put_event(struct input_key_event* event)
491{
492 free(event);
493}
494
Dominik Behr44e07e62016-01-13 19:43:57 -0800495void input_dispatch_io(fd_set* read_set, fd_set* exception_set)
David Sodmanf0a925a2015-05-04 11:19:19 -0700496{
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800497 terminal_t* terminal;
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800498 struct input_key_event* event;
Dominik Behr44e07e62016-01-13 19:43:57 -0800499
500 event = input_get_event(read_set, exception_set);
David Sodmanf0a925a2015-05-04 11:19:19 -0700501 if (event) {
502 if (!input_special_key(event) && event->value) {
503 uint32_t keysym, unicode;
504 // current_terminal can possibly change during
505 // execution of input_special_key
Dominik Behr4defb362016-01-13 12:36:14 -0800506 terminal = term_get_current_terminal();
David Sodmanf0a925a2015-05-04 11:19:19 -0700507 if (term_is_active(terminal)) {
508 // Only report user activity when the terminal is active
Dominik Behr797a3832016-01-11 15:53:11 -0800509 dbus_report_user_activity(USER_ACTIVITY_OTHER);
David Sodmanf0a925a2015-05-04 11:19:19 -0700510 input_get_keysym_and_unicode(
511 event, &keysym, &unicode);
512 term_key_event(terminal,
513 keysym, unicode);
514 }
515 }
516 input_put_event(event);
517 }
David Sodmanbf3f2842014-11-12 08:26:58 -0800518}