Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-3.0-or-later
2 : : // SPDX-FileCopyrightText: Andy Holmes <andrew.g.r.holmes@gmail.com>
3 : : // SPDX-FileContributor: Jonas Ã…dahl <jadahl@gmail.com>
4 : :
5 : : #define G_LOG_DOMAIN "valent-xdp-input"
6 : :
7 : : #include "config.h"
8 : :
9 : : #include <linux/input-event-codes.h>
10 : :
11 : : #include <gio/gio.h>
12 : : #include <gio/gunixinputstream.h>
13 : : #include <libei.h>
14 : : #include <valent.h>
15 : : #include <xkbcommon/xkbcommon.h>
16 : :
17 : : #include "valent-ei-input.h"
18 : :
19 : : struct _ValentEiInput
20 : : {
21 : : ValentInputAdapter parent_instance;
22 : :
23 : : int fd;
24 : :
25 : : struct ei *ei;
26 : : GSource *ei_source;
27 : : struct ei_seat *ei_seat;
28 : : struct ei_device *ei_pointer;
29 : : struct ei_device *ei_pointer_abs;
30 : : struct ei_device *ei_keyboard;
31 : : struct ei_device *ei_touch;
32 : : uint32_t ei_sequence;
33 : :
34 : : struct xkb_context *xkb_context;
35 : : struct xkb_keymap *xkb_keymap;
36 : : struct xkb_state *xkb_state;
37 : : };
38 : :
39 : : static void g_initable_iface_init (GInitableIface *iface);
40 : : static void valent_ei_input_stop (ValentEiInput *self);
41 : :
42 : 0 : G_DEFINE_FINAL_TYPE_WITH_CODE (ValentEiInput, valent_ei_input, VALENT_TYPE_INPUT_ADAPTER,
43 : : G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, g_initable_iface_init))
44 : :
45 : : typedef enum {
46 : : PROP_FD = 1,
47 : : } ValentEiInputProperty;
48 : :
49 : : static GParamSpec *properties[PROP_FD + 1] = { NULL, };
50 : :
51 : : typedef enum
52 : : {
53 : : EVDEV_BUTTON_TYPE_NONE,
54 : : EVDEV_BUTTON_TYPE_KEY,
55 : : EVDEV_BUTTON_TYPE_BUTTON,
56 : : } EvdevButtonType;
57 : :
58 : : static EvdevButtonType
59 : 0 : _evdev_code_get_button_type (uint16_t code)
60 : : {
61 : 0 : switch (code)
62 : : {
63 : : case BTN_TOOL_PEN:
64 : : case BTN_TOOL_RUBBER:
65 : : case BTN_TOOL_BRUSH:
66 : : case BTN_TOOL_PENCIL:
67 : : case BTN_TOOL_AIRBRUSH:
68 : : case BTN_TOOL_MOUSE:
69 : : case BTN_TOOL_LENS:
70 : : case BTN_TOOL_QUINTTAP:
71 : : case BTN_TOOL_DOUBLETAP:
72 : : case BTN_TOOL_TRIPLETAP:
73 : : case BTN_TOOL_QUADTAP:
74 : : case BTN_TOOL_FINGER:
75 : : case BTN_TOUCH:
76 : : return EVDEV_BUTTON_TYPE_NONE;
77 : : }
78 : :
79 : 0 : if (code >= KEY_ESC && code <= KEY_MICMUTE)
80 : : return EVDEV_BUTTON_TYPE_KEY;
81 : 0 : if (code >= BTN_MISC && code <= BTN_GEAR_UP)
82 : : return EVDEV_BUTTON_TYPE_BUTTON;
83 : 0 : if (code >= KEY_OK && code <= KEY_LIGHTS_TOGGLE)
84 : : return EVDEV_BUTTON_TYPE_KEY;
85 : 0 : if (code >= BTN_DPAD_UP && code <= BTN_DPAD_RIGHT)
86 : : return EVDEV_BUTTON_TYPE_BUTTON;
87 : 0 : if (code >= KEY_ALS_TOGGLE && code <= KEY_KBDINPUTASSIST_CANCEL)
88 : : return EVDEV_BUTTON_TYPE_KEY;
89 : 0 : if (code >= BTN_TRIGGER_HAPPY && code <= BTN_TRIGGER_HAPPY40)
90 : 0 : return EVDEV_BUTTON_TYPE_BUTTON;
91 : :
92 : : return EVDEV_BUTTON_TYPE_NONE;
93 : : }
94 : :
95 : : /*
96 : : * XKB Helpers
97 : : */
98 : : static gboolean
99 : 0 : _xkb_keycode_from_keysym (struct xkb_keymap *xkb_keymap,
100 : : struct xkb_state *xkb_state,
101 : : uint32_t keysym,
102 : : uint32_t *keycode_out,
103 : : uint32_t *level_out)
104 : : {
105 : 0 : uint32_t layout;
106 : 0 : xkb_keycode_t min_keycode, max_keycode;
107 : :
108 : 0 : g_assert (xkb_keymap != NULL);
109 : 0 : g_assert (xkb_state != NULL);
110 : 0 : g_assert (keycode_out != NULL);
111 : :
112 : 0 : layout = xkb_state_serialize_layout (xkb_state, XKB_STATE_LAYOUT_EFFECTIVE);
113 : 0 : min_keycode = xkb_keymap_min_keycode (xkb_keymap);
114 : 0 : max_keycode = xkb_keymap_max_keycode (xkb_keymap);
115 : 0 : for (xkb_keycode_t keycode = min_keycode; keycode < max_keycode; keycode++)
116 : : {
117 : 0 : xkb_level_index_t num_levels;
118 : :
119 : 0 : num_levels = xkb_keymap_num_levels_for_key (xkb_keymap, keycode, layout);
120 : 0 : for (xkb_level_index_t level = 0; level < num_levels; level++)
121 : : {
122 : 0 : const xkb_keysym_t *syms;
123 : 0 : int num_syms;
124 : :
125 : 0 : num_syms = xkb_keymap_key_get_syms_by_level (xkb_keymap,
126 : : keycode,
127 : : layout,
128 : : level,
129 : : &syms);
130 : 0 : for (int sym = 0; sym < num_syms; sym++)
131 : : {
132 : 0 : if (syms[sym] == keysym)
133 : : {
134 : 0 : *keycode_out = keycode;
135 : 0 : if (level_out != NULL)
136 : 0 : *level_out = level;
137 : :
138 : 0 : return TRUE;
139 : : }
140 : : }
141 : : }
142 : : }
143 : :
144 : : return FALSE;
145 : : }
146 : :
147 : : static uint32_t
148 : 0 : _xkb_keycode_to_evdev_code (xkb_keycode_t keycode)
149 : : {
150 : 0 : return keycode - 8;
151 : : }
152 : :
153 : : /*
154 : : * libei
155 : : */
156 : : static gboolean
157 : 0 : process_keymap (ValentEiInput *self,
158 : : struct ei_device *device,
159 : : GError **error)
160 : : {
161 : 0 : g_autoptr (GInputStream) stream = NULL;
162 : 0 : struct ei_keymap *keymap;
163 : 0 : enum ei_keymap_type keymap_type;
164 : 0 : g_autofree char *keymap_str = NULL;
165 : 0 : size_t keymap_size;
166 : :
167 : 0 : g_clear_pointer (&self->xkb_context, xkb_context_unref);
168 : 0 : g_clear_pointer (&self->xkb_keymap, xkb_keymap_unref);
169 : 0 : g_clear_pointer (&self->xkb_state, xkb_state_unref);
170 : :
171 : 0 : keymap = ei_device_keyboard_get_keymap (device);
172 : 0 : if (keymap == NULL)
173 : : {
174 : : VALENT_NOTE ("No keymap");
175 : : return TRUE;
176 : : }
177 : :
178 : 0 : keymap_type = ei_keymap_get_type (keymap);
179 : 0 : switch ((enum ei_keymap_type)keymap_type)
180 : : {
181 : : case EI_KEYMAP_TYPE_XKB:
182 : 0 : break;
183 : :
184 : 0 : default:
185 : 0 : g_set_error (error,
186 : : G_IO_ERROR,
187 : : G_IO_ERROR_FAILED,
188 : : "Unknown keyboard layout type");
189 : 0 : return FALSE;
190 : : }
191 : :
192 : 0 : keymap_size = ei_keymap_get_size (keymap);
193 : 0 : keymap_str = g_malloc0 (keymap_size + 1);
194 : 0 : stream = g_unix_input_stream_new (ei_keymap_get_fd (keymap), FALSE);
195 : 0 : if (!g_input_stream_read_all (stream, keymap_str, keymap_size, NULL, NULL, NULL))
196 : : {
197 : 0 : g_set_error (error,
198 : : G_IO_ERROR,
199 : : G_IO_ERROR_FAILED,
200 : : "Failed to load EI keymap");
201 : 0 : return FALSE;
202 : : }
203 : :
204 : 0 : self->xkb_context = xkb_context_new (XKB_CONTEXT_NO_FLAGS);
205 : 0 : if (self->xkb_context == NULL)
206 : : {
207 : 0 : g_set_error (error,
208 : : G_IO_ERROR,
209 : : G_IO_ERROR_FAILED,
210 : : "Failed to create XKB context");
211 : 0 : return FALSE;
212 : : }
213 : :
214 : 0 : self->xkb_keymap = xkb_keymap_new_from_string (self->xkb_context,
215 : : keymap_str,
216 : : XKB_KEYMAP_FORMAT_TEXT_V1,
217 : : XKB_KEYMAP_COMPILE_NO_FLAGS);
218 : 0 : if (self->xkb_keymap == NULL)
219 : : {
220 : 0 : g_set_error (error,
221 : : G_IO_ERROR,
222 : : G_IO_ERROR_FAILED,
223 : : "Failed to create XKB keymap");
224 : 0 : g_clear_pointer (&self->xkb_context, xkb_context_unref);
225 : 0 : return FALSE;
226 : : }
227 : :
228 : 0 : self->xkb_state = xkb_state_new (self->xkb_keymap);
229 : 0 : if (self->xkb_state == NULL)
230 : : {
231 : 0 : g_set_error (error,
232 : : G_IO_ERROR,
233 : : G_IO_ERROR_FAILED,
234 : : "Failed to create XKB state");
235 : 0 : g_clear_pointer (&self->xkb_context, xkb_context_unref);
236 : 0 : g_clear_pointer (&self->xkb_keymap, xkb_keymap_unref);
237 : 0 : return FALSE;
238 : : }
239 : :
240 : : return TRUE;
241 : : }
242 : :
243 : : /*
244 : : * GSource
245 : : */
246 : : typedef struct _EiEventSource
247 : : {
248 : : GSource base;
249 : : ValentEiInput *self;
250 : : } EiEventSource;
251 : :
252 : : static gboolean
253 : 0 : ei_source_prepare (GSource *source,
254 : : int *timeout)
255 : : {
256 : 0 : EiEventSource *ei_source = (EiEventSource *) source;
257 : 0 : ValentEiInput *self = ei_source->self;
258 : :
259 : 0 : if (timeout != NULL)
260 : 0 : *timeout = -1;
261 : :
262 : 0 : return !!ei_peek_event (self->ei);
263 : : }
264 : :
265 : : static gboolean
266 : 0 : ei_source_dispatch (GSource *source,
267 : : GSourceFunc callback,
268 : : gpointer user_data)
269 : : {
270 : 0 : EiEventSource *ei_source = (EiEventSource *) source;
271 : 0 : ValentEiInput *self = ei_source->self;
272 : 0 : struct ei_event *event;
273 : :
274 : 0 : ei_dispatch (self->ei);
275 : :
276 : 0 : while ((event = ei_get_event (self->ei)) != NULL)
277 : : {
278 : 0 : enum ei_event_type event_type = ei_event_get_type (event);
279 : :
280 : 0 : VALENT_NOTE ("Event %s", ei_event_type_to_string (event_type));
281 : :
282 : 0 : switch ((enum ei_event_type)event_type)
283 : : {
284 : : case EI_EVENT_CONNECT:
285 : : {
286 : 0 : valent_extension_plugin_state_changed (VALENT_EXTENSION (self),
287 : : VALENT_PLUGIN_STATE_ACTIVE,
288 : : NULL);
289 : 0 : break;
290 : : }
291 : : case EI_EVENT_DISCONNECT:
292 : : {
293 : 0 : valent_extension_plugin_state_changed (VALENT_EXTENSION (self),
294 : : VALENT_PLUGIN_STATE_INACTIVE,
295 : : NULL);
296 : 0 : break;
297 : : }
298 : 0 : case EI_EVENT_SEAT_ADDED:
299 : : {
300 : 0 : if (self->ei_seat != NULL)
301 : : break;
302 : :
303 : 0 : self->ei_seat = ei_seat_ref (ei_event_get_seat (event));
304 : 0 : ei_seat_bind_capabilities (self->ei_seat,
305 : : EI_DEVICE_CAP_POINTER,
306 : : EI_DEVICE_CAP_KEYBOARD,
307 : : EI_DEVICE_CAP_POINTER_ABSOLUTE,
308 : : EI_DEVICE_CAP_BUTTON,
309 : : EI_DEVICE_CAP_SCROLL,
310 : : EI_DEVICE_CAP_TOUCH,
311 : : NULL);
312 : 0 : break;
313 : : }
314 : :
315 : 0 : case EI_EVENT_SEAT_REMOVED:
316 : : {
317 : 0 : if (ei_event_get_seat (event) == self->ei_seat)
318 : 0 : g_clear_pointer (&self->ei_seat, ei_seat_unref);
319 : :
320 : : break;
321 : : }
322 : :
323 : 0 : case EI_EVENT_DEVICE_ADDED:
324 : : {
325 : 0 : struct ei_device *device = ei_event_get_device (event);
326 : :
327 : 0 : if (ei_device_has_capability (device, EI_DEVICE_CAP_KEYBOARD))
328 : : {
329 : 0 : g_autoptr (GError) error = NULL;
330 : :
331 : 0 : g_clear_pointer (&self->ei_keyboard, ei_device_unref);
332 : 0 : self->ei_keyboard = ei_device_ref (device);
333 : 0 : if (!process_keymap (self, self->ei_keyboard, &error))
334 : : {
335 : 0 : valent_extension_plugin_state_changed (VALENT_EXTENSION (self),
336 : : VALENT_PLUGIN_STATE_ERROR,
337 : : error);
338 : 0 : ei_event_unref (event);
339 : 0 : valent_ei_input_stop (self);
340 : 0 : return G_SOURCE_REMOVE;
341 : : }
342 : : }
343 : :
344 : 0 : if (ei_device_has_capability (device, EI_DEVICE_CAP_POINTER))
345 : : {
346 : 0 : g_clear_pointer (&self->ei_pointer, ei_device_unref);
347 : 0 : self->ei_pointer = ei_device_ref (device);
348 : : }
349 : :
350 : 0 : if (ei_device_has_capability (device, EI_DEVICE_CAP_POINTER_ABSOLUTE))
351 : : {
352 : 0 : g_clear_pointer (&self->ei_pointer_abs, ei_device_unref);
353 : 0 : self->ei_pointer_abs = ei_device_ref (device);
354 : : }
355 : :
356 : 0 : if (ei_device_has_capability (device, EI_DEVICE_CAP_TOUCH))
357 : : {
358 : 0 : g_clear_pointer (&self->ei_touch, ei_device_unref);
359 : 0 : self->ei_touch = ei_device_ref (device);
360 : : }
361 : :
362 : : break;
363 : : }
364 : :
365 : 0 : case EI_EVENT_DEVICE_REMOVED:
366 : : {
367 : 0 : struct ei_device *device = ei_event_get_device (event);
368 : :
369 : 0 : if (device == self->ei_keyboard)
370 : 0 : g_clear_pointer (&self->ei_keyboard, ei_device_unref);
371 : 0 : if (device == self->ei_pointer)
372 : 0 : g_clear_pointer (&self->ei_pointer, ei_device_unref);
373 : 0 : if (device == self->ei_pointer_abs)
374 : 0 : g_clear_pointer (&self->ei_pointer_abs, ei_device_unref);
375 : 0 : if (device == self->ei_touch)
376 : 0 : g_clear_pointer (&self->ei_touch, ei_device_unref);
377 : :
378 : : break;
379 : : }
380 : :
381 : 0 : case EI_EVENT_DEVICE_RESUMED:
382 : : {
383 : 0 : struct ei_device *device = ei_event_get_device (event);
384 : :
385 : 0 : if (device == self->ei_pointer)
386 : 0 : ei_device_start_emulating (self->ei_pointer, ++self->ei_sequence);
387 : 0 : if (device == self->ei_pointer_abs)
388 : 0 : ei_device_start_emulating (self->ei_pointer_abs, ++self->ei_sequence);
389 : 0 : if (device == self->ei_keyboard)
390 : 0 : ei_device_start_emulating (self->ei_keyboard, ++self->ei_sequence);
391 : 0 : if (device == self->ei_touch)
392 : 0 : ei_device_start_emulating (self->ei_touch, ++self->ei_sequence);
393 : :
394 : : break;
395 : : }
396 : :
397 : : case EI_EVENT_DEVICE_PAUSED:
398 : : case EI_EVENT_KEYBOARD_MODIFIERS:
399 : : case EI_EVENT_PONG:
400 : : case EI_EVENT_SYNC:
401 : : case EI_EVENT_FRAME:
402 : : case EI_EVENT_DEVICE_START_EMULATING:
403 : : case EI_EVENT_DEVICE_STOP_EMULATING:
404 : : case EI_EVENT_POINTER_MOTION:
405 : : case EI_EVENT_POINTER_MOTION_ABSOLUTE:
406 : : case EI_EVENT_BUTTON_BUTTON:
407 : : case EI_EVENT_SCROLL_DELTA:
408 : : case EI_EVENT_SCROLL_STOP:
409 : : case EI_EVENT_SCROLL_CANCEL:
410 : : case EI_EVENT_SCROLL_DISCRETE:
411 : : case EI_EVENT_KEYBOARD_KEY:
412 : : case EI_EVENT_TOUCH_DOWN:
413 : : case EI_EVENT_TOUCH_UP:
414 : : case EI_EVENT_TOUCH_MOTION:
415 : : default:
416 : : break;
417 : : }
418 : :
419 : 0 : ei_event_unref (event);
420 : : }
421 : :
422 : : return G_SOURCE_CONTINUE;
423 : : }
424 : :
425 : : static GSourceFuncs ei_source_funcs =
426 : : {
427 : : .prepare = ei_source_prepare,
428 : : .dispatch = ei_source_dispatch,
429 : : };
430 : :
431 : : static GSource *
432 : 0 : valent_ei_input_create_source (ValentEiInput *self)
433 : : {
434 : 0 : GSource *source;
435 : :
436 : 0 : source = g_source_new (&ei_source_funcs, sizeof (EiEventSource));
437 : 0 : g_source_set_name (source, "valent-ei");
438 : 0 : g_source_add_unix_fd (source, ei_get_fd (self->ei), G_IO_IN | G_IO_ERR);
439 : 0 : ((EiEventSource *) source)->self = self;
440 : :
441 : 0 : return source;
442 : : }
443 : :
444 : : /*
445 : : * ValentInputAdapter
446 : : */
447 : : static void
448 : 0 : valent_ei_input_keyboard_modifiers (ValentEiInput *self,
449 : : uint64_t time_us,
450 : : uint32_t level,
451 : : uint32_t key_state)
452 : : {
453 : 0 : uint32_t keysym, keycode, evcode;
454 : :
455 : 0 : switch (level)
456 : : {
457 : : case 0:
458 : 0 : return;
459 : :
460 : : case 1:
461 : : keysym = XKB_KEY_Shift_L;
462 : : break;
463 : :
464 : 0 : case 2:
465 : 0 : keysym = XKB_KEY_ISO_Level3_Shift;
466 : 0 : break;
467 : :
468 : 0 : default:
469 : 0 : g_warning ("Unknown modifier level `%u`", level);
470 : 0 : return;
471 : : }
472 : :
473 : 0 : if (!_xkb_keycode_from_keysym (self->xkb_keymap,
474 : : self->xkb_state,
475 : : keysym,
476 : : &keycode,
477 : : NULL))
478 : : {
479 : : return;
480 : : }
481 : :
482 : 0 : evcode = _xkb_keycode_to_evdev_code (keycode);
483 : 0 : ei_device_keyboard_key (self->ei_keyboard, evcode, key_state);
484 : 0 : ei_device_frame (self->ei_keyboard, time_us);
485 : : }
486 : :
487 : : static void
488 : 0 : valent_ei_input_keyboard_keysym (ValentInputAdapter *adapter,
489 : : uint32_t keysym,
490 : : gboolean state)
491 : : {
492 : 0 : ValentEiInput *self = VALENT_EI_INPUT (adapter);
493 : 0 : int64_t timestamp;
494 : 0 : uint32_t keycode = 0;
495 : 0 : uint32_t level = 0;
496 : 0 : uint32_t evcode = 0;
497 : :
498 : 0 : g_assert (VALENT_IS_INPUT_ADAPTER (adapter));
499 : 0 : g_assert (VALENT_IS_EI_INPUT (self));
500 : :
501 : 0 : if (self->ei_keyboard == NULL || self->xkb_keymap == NULL)
502 : 0 : return;
503 : :
504 : 0 : timestamp = ei_now (self->ei);
505 : 0 : if (!_xkb_keycode_from_keysym (self->xkb_keymap,
506 : : self->xkb_state,
507 : : keysym,
508 : : &keycode,
509 : : &level))
510 : : {
511 : 0 : g_warning ("%s(): No keycode for keysym 0x%x in current group",
512 : : G_STRFUNC, keysym);
513 : 0 : return;
514 : : }
515 : :
516 : 0 : evcode = _xkb_keycode_to_evdev_code (keycode);
517 : 0 : if (_evdev_code_get_button_type (evcode) != EVDEV_BUTTON_TYPE_KEY)
518 : : {
519 : 0 : g_warning ("%s(): Invalid keycode 0x%x (keysym 0x%x) for keyboard",
520 : : G_STRFUNC, evcode, keysym);
521 : 0 : return;
522 : : }
523 : :
524 : 0 : if (state)
525 : 0 : valent_ei_input_keyboard_modifiers (self, timestamp, level, state);
526 : :
527 : 0 : ei_device_keyboard_key (self->ei_keyboard, evcode, state);
528 : 0 : ei_device_frame (self->ei_keyboard, timestamp);
529 : :
530 : 0 : if (!state)
531 : 0 : valent_ei_input_keyboard_modifiers (self, timestamp, level, state);
532 : : }
533 : :
534 : : static unsigned int
535 : 0 : translate_to_evdev_button (unsigned int button)
536 : : {
537 : 0 : switch (button)
538 : : {
539 : : case VALENT_POINTER_PRIMARY:
540 : : return BTN_LEFT;
541 : :
542 : : case VALENT_POINTER_MIDDLE:
543 : : return BTN_MIDDLE;
544 : :
545 : : case VALENT_POINTER_SECONDARY:
546 : : return BTN_RIGHT;
547 : :
548 : 0 : default:
549 : : /* Any other buttons go after the legacy scroll buttons (4-7). */
550 : 0 : return button + (BTN_LEFT - 1) - 4;
551 : : }
552 : : }
553 : :
554 : : static void
555 : 0 : valent_ei_input_pointer_axis (ValentInputAdapter *adapter,
556 : : double dx,
557 : : double dy)
558 : : {
559 : 0 : ValentEiInput *self = VALENT_EI_INPUT (adapter);
560 : :
561 : 0 : g_assert (VALENT_IS_INPUT_ADAPTER (adapter));
562 : 0 : g_assert (VALENT_IS_EI_INPUT (self));
563 : 0 : g_assert (!G_APPROX_VALUE (dx, 0.0, 0.01) || !G_APPROX_VALUE (dy, 0.0, 0.01));
564 : :
565 : 0 : if (self->ei_pointer == NULL)
566 : : return;
567 : :
568 : 0 : ei_device_scroll_delta (self->ei_pointer, dx, dy);
569 : 0 : ei_device_frame (self->ei_pointer, ei_now (self->ei));
570 : 0 : ei_device_scroll_stop (self->ei_pointer, TRUE, TRUE);
571 : 0 : ei_device_frame (self->ei_pointer, ei_now (self->ei));
572 : : }
573 : :
574 : : static void
575 : 0 : valent_ei_input_pointer_button (ValentInputAdapter *adapter,
576 : : unsigned int button,
577 : : gboolean pressed)
578 : : {
579 : 0 : ValentEiInput *self = VALENT_EI_INPUT (adapter);
580 : :
581 : 0 : g_assert (VALENT_IS_INPUT_ADAPTER (adapter));
582 : 0 : g_assert (VALENT_IS_EI_INPUT (self));
583 : :
584 : 0 : if (self->ei_pointer == NULL)
585 : : return;
586 : :
587 : 0 : button = translate_to_evdev_button (button);
588 : 0 : ei_device_button_button (self->ei_pointer, button, pressed);
589 : 0 : ei_device_frame (self->ei_pointer, ei_now (self->ei));
590 : : }
591 : :
592 : : static void
593 : 0 : valent_ei_input_pointer_motion (ValentInputAdapter *adapter,
594 : : double dx,
595 : : double dy)
596 : : {
597 : 0 : ValentEiInput *self = VALENT_EI_INPUT (adapter);
598 : :
599 : 0 : g_assert (VALENT_IS_INPUT_ADAPTER (adapter));
600 : 0 : g_assert (VALENT_IS_EI_INPUT (self));
601 : :
602 : 0 : if (self->ei_pointer == NULL)
603 : : return;
604 : :
605 : 0 : ei_device_pointer_motion (self->ei_pointer, dx, dy);
606 : 0 : ei_device_frame (self->ei_pointer, ei_now (self->ei));
607 : : }
608 : :
609 : : static void
610 : 0 : valent_ei_input_stop (ValentEiInput *self)
611 : : {
612 : 0 : g_assert (VALENT_IS_EI_INPUT (self));
613 : :
614 : 0 : if (self->ei_source != NULL)
615 : : {
616 : 0 : g_source_destroy (self->ei_source);
617 : 0 : g_clear_pointer (&self->ei_source, g_source_unref);
618 : : }
619 : :
620 : 0 : g_clear_pointer (&self->xkb_state, xkb_state_unref);
621 : 0 : g_clear_pointer (&self->xkb_keymap, xkb_keymap_unref);
622 : 0 : g_clear_pointer (&self->xkb_context, xkb_context_unref);
623 : :
624 : 0 : g_clear_pointer (&self->ei_touch, ei_device_unref);
625 : 0 : g_clear_pointer (&self->ei_keyboard, ei_device_unref);
626 : 0 : g_clear_pointer (&self->ei_pointer, ei_device_unref);
627 : 0 : g_clear_pointer (&self->ei_pointer_abs, ei_device_unref);
628 : 0 : g_clear_pointer (&self->ei_seat, ei_seat_unref);
629 : 0 : g_clear_pointer (&self->ei, ei_unref);
630 : 0 : }
631 : :
632 : : /*
633 : : * GInitable
634 : : */
635 : : static gboolean
636 : 0 : valent_ei_input_initable_init (GInitable *initable,
637 : : GCancellable *cancellable,
638 : : GError **error)
639 : : {
640 : 0 : ValentEiInput *self = VALENT_EI_INPUT (initable);
641 : :
642 : 0 : self->ei = ei_new_sender (self);
643 : 0 : ei_configure_name (self->ei, "valent");
644 : 0 : if (ei_setup_backend_fd (self->ei, self->fd) == -1)
645 : : {
646 : 0 : g_set_error (error,
647 : : G_IO_ERROR,
648 : : G_IO_ERROR_FAILED,
649 : : "Failed to setup libei backend");
650 : 0 : g_clear_pointer (&self->ei, ei_unref);
651 : 0 : return FALSE;
652 : : }
653 : :
654 : 0 : self->ei_source = valent_ei_input_create_source (self);
655 : 0 : g_source_attach (self->ei_source, NULL);
656 : :
657 : 0 : return TRUE;
658 : : }
659 : :
660 : : static void
661 : 0 : g_initable_iface_init (GInitableIface *iface)
662 : : {
663 : 0 : iface->init = valent_ei_input_initable_init;
664 : 0 : }
665 : :
666 : : /*
667 : : * ValentObject
668 : : */
669 : : static void
670 : 0 : valent_ei_input_destroy (ValentObject *object)
671 : : {
672 : 0 : ValentEiInput *self = VALENT_EI_INPUT (object);
673 : :
674 : 0 : valent_ei_input_stop (self);
675 : :
676 : 0 : VALENT_OBJECT_CLASS (valent_ei_input_parent_class)->destroy (object);
677 : 0 : }
678 : :
679 : : /*
680 : : * GObject
681 : : */
682 : : static void
683 : 0 : valent_ei_input_get_property (GObject *object,
684 : : guint prop_id,
685 : : GValue *value,
686 : : GParamSpec *pspec)
687 : : {
688 : 0 : ValentEiInput *self = VALENT_EI_INPUT (object);
689 : :
690 : 0 : switch ((ValentEiInputProperty)prop_id)
691 : : {
692 : 0 : case PROP_FD:
693 : 0 : g_value_set_int (value, self->fd);
694 : 0 : break;
695 : :
696 : 0 : default:
697 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
698 : : }
699 : 0 : }
700 : :
701 : : static void
702 : 0 : valent_ei_input_set_property (GObject *object,
703 : : guint prop_id,
704 : : const GValue *value,
705 : : GParamSpec *pspec)
706 : : {
707 : 0 : ValentEiInput *self = VALENT_EI_INPUT (object);
708 : :
709 : 0 : switch ((ValentEiInputProperty)prop_id)
710 : : {
711 : 0 : case PROP_FD:
712 : 0 : self->fd = g_value_get_int (value);
713 : 0 : break;
714 : :
715 : 0 : default:
716 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
717 : : }
718 : 0 : }
719 : :
720 : : static void
721 : 0 : valent_ei_input_class_init (ValentEiInputClass *klass)
722 : : {
723 : 0 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
724 : 0 : ValentObjectClass *vobject_class = VALENT_OBJECT_CLASS (klass);
725 : 0 : ValentInputAdapterClass *adapter_class = VALENT_INPUT_ADAPTER_CLASS (klass);
726 : :
727 : 0 : object_class->get_property = valent_ei_input_get_property;
728 : 0 : object_class->set_property = valent_ei_input_set_property;
729 : :
730 : 0 : vobject_class->destroy = valent_ei_input_destroy;
731 : :
732 : 0 : adapter_class->keyboard_keysym = valent_ei_input_keyboard_keysym;
733 : 0 : adapter_class->pointer_axis = valent_ei_input_pointer_axis;
734 : 0 : adapter_class->pointer_button = valent_ei_input_pointer_button;
735 : 0 : adapter_class->pointer_motion = valent_ei_input_pointer_motion;
736 : :
737 : : /**
738 : : * ValentEiInput:fd:
739 : : *
740 : : * The file descriptor for libei.
741 : : */
742 : 0 : properties [PROP_FD] =
743 : 0 : g_param_spec_int ("fd", NULL, NULL,
744 : : G_MININT, G_MAXINT,
745 : : -1,
746 : : (G_PARAM_READWRITE |
747 : : G_PARAM_CONSTRUCT_ONLY |
748 : : G_PARAM_EXPLICIT_NOTIFY |
749 : : G_PARAM_STATIC_STRINGS));
750 : :
751 : 0 : g_object_class_install_properties (object_class, G_N_ELEMENTS (properties), properties);
752 : 0 : }
753 : :
754 : : static void
755 : 0 : valent_ei_input_init (ValentEiInput *self)
756 : : {
757 : 0 : }
758 : :
|