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 : :
4 : : #define G_LOG_DOMAIN "valent-input-remote"
5 : :
6 : : #include "config.h"
7 : :
8 : : #include <adwaita.h>
9 : : #include <glib/gi18n-lib.h>
10 : : #include <gtk/gtk.h>
11 : : #include <valent.h>
12 : :
13 : : #include "valent-input-remote.h"
14 : : #include "valent-ui-utils-private.h"
15 : :
16 : : #define CAPTURE_THRESHOLD_MS 50
17 : :
18 : :
19 : : struct _ValentInputRemote
20 : : {
21 : : AdwWindow parent_instance;
22 : :
23 : : GListModel *adapters;
24 : : ValentInputAdapter *adapter;
25 : :
26 : : /* Keyboard State */
27 : : unsigned int capture_keyboard : 1;
28 : : unsigned int capture_keyboard_release : 1;
29 : :
30 : : /* Pointer State */
31 : : unsigned int claimed : 1;
32 : : uint32_t timestamp;
33 : : double last_x;
34 : : double last_y;
35 : : double last_v;
36 : : int scale;
37 : :
38 : : /* template */
39 : : GtkDropDown *input_adapter;
40 : : GtkEventController *keyboard;
41 : : GtkWidget *touchpad;
42 : : GtkGesture *pointer_scroll;
43 : : GtkGesture *touch_single;
44 : : GtkGesture *touch_double;
45 : : GtkGesture *touch_triple;
46 : : GtkTextBuffer *compose_text;
47 : : GtkFilter *filter;
48 : : GtkFilterListModel *model;
49 : : };
50 : :
51 [ + + + - ]: 36 : G_DEFINE_FINAL_TYPE (ValentInputRemote, valent_input_remote, ADW_TYPE_WINDOW)
52 : :
53 : : typedef enum {
54 : : PROP_ADAPTERS = 1,
55 : : PROP_CAPTURE_KEYBOARD,
56 : : } ValentInputRemoteProperty;
57 : :
58 : : static GParamSpec *properties[PROP_CAPTURE_KEYBOARD + 1] = { NULL, };
59 : :
60 : : static gboolean
61 : 1 : valent_input_remote_filter (gpointer item,
62 : : gpointer user_data)
63 : : {
64 : 1 : ValentResource *resource = VALENT_RESOURCE (item);
65 : :
66 : 1 : return VALENT_IS_DEVICE (valent_resource_get_source (resource));
67 : : }
68 : :
69 : : static inline gboolean
70 : 0 : valent_input_remote_check_adapter (ValentInputRemote *self)
71 : : {
72 [ # # ]: 0 : g_assert (VALENT_IS_INPUT_REMOTE (self));
73 : :
74 [ # # ]: 0 : if G_UNLIKELY (self->adapter == NULL)
75 : : {
76 : 0 : self->claimed = FALSE;
77 : 0 : self->timestamp = 0;
78 : 0 : self->last_x = 0.0;
79 : 0 : self->last_y = 0.0;
80 : 0 : self->last_v = 0.0;
81 : :
82 : 0 : return FALSE;
83 : : }
84 : :
85 : : return TRUE;
86 : : }
87 : :
88 : : /*
89 : : * Keyboard Input
90 : : */
91 : : static gboolean
92 : 0 : on_key_pressed (GtkEventControllerKey *controller,
93 : : unsigned int keyval,
94 : : unsigned int keycode,
95 : : GdkModifierType state,
96 : : ValentInputRemote *self)
97 : : {
98 [ # # ]: 0 : g_assert (VALENT_IS_INPUT_REMOTE (self));
99 : :
100 [ # # ]: 0 : if (!self->capture_keyboard)
101 : : return FALSE;
102 : :
103 : : /* Check for <Control_L> + <Alt_L> capture release shortcut
104 : : */
105 [ # # ]: 0 : if ((keyval == GDK_KEY_Alt_L && state == GDK_CONTROL_MASK) ||
106 [ # # ]: 0 : (keyval == GDK_KEY_Control_L && state == GDK_ALT_MASK))
107 : : {
108 : 0 : self->capture_keyboard_release = TRUE;
109 : : }
110 : : else
111 : : {
112 : 0 : self->capture_keyboard_release = FALSE;
113 : : }
114 : :
115 [ # # ]: 0 : if (valent_input_remote_check_adapter (self))
116 : 0 : valent_input_adapter_keyboard_keysym (self->adapter, keyval, TRUE);
117 : :
118 : : return TRUE;
119 : : }
120 : :
121 : : static void
122 : 0 : on_key_released (GtkEventControllerKey *controller,
123 : : unsigned int keyval,
124 : : unsigned int keycode,
125 : : GdkModifierType state,
126 : : ValentInputRemote *self)
127 : : {
128 [ # # ]: 0 : g_assert (VALENT_IS_INPUT_REMOTE (self));
129 : :
130 [ # # ]: 0 : if (!self->capture_keyboard)
131 : : return;
132 : :
133 : : /* Check for <Control_L> + <Alt_L> capture release shortcut
134 : : */
135 [ # # ]: 0 : if (self->capture_keyboard_release)
136 : : {
137 [ # # ]: 0 : if ((keyval == GDK_KEY_Alt_L && state == GDK_ALT_MASK) ||
138 [ # # ]: 0 : (keyval == GDK_KEY_Control_L && state == GDK_CONTROL_MASK))
139 : : {
140 : 0 : self->capture_keyboard_release = FALSE;
141 : 0 : self->capture_keyboard = FALSE;
142 : 0 : g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CAPTURE_KEYBOARD]);
143 : : }
144 : : }
145 : :
146 [ # # ]: 0 : if (valent_input_remote_check_adapter (self))
147 : 0 : valent_input_adapter_keyboard_keysym (self->adapter, keyval, FALSE);
148 : : }
149 : :
150 : : /*
151 : : * Pointer Input
152 : : */
153 : : static inline void
154 : 0 : get_last_update_time (GtkGesture *gesture,
155 : : GdkEventSequence *sequence,
156 : : uint32_t *timestamp)
157 : : {
158 : 0 : GdkEvent *event = NULL;
159 : :
160 [ # # ]: 0 : if (sequence != NULL)
161 : 0 : event = gtk_gesture_get_last_event (gesture, sequence);
162 : :
163 [ # # ]: 0 : if (event != NULL)
164 : 0 : *timestamp = gdk_event_get_time (event);
165 : 0 : }
166 : :
167 : : static inline gboolean
168 : 0 : calculate_delta (ValentInputRemote *self,
169 : : double dx,
170 : : double dy,
171 : : uint32_t dt,
172 : : double *cx,
173 : : double *cy)
174 : : {
175 : 0 : double dr, v, m;
176 : :
177 : 0 : dr = sqrt (pow (dx, 2) + pow (dy, 2));
178 : 0 : v = dr / dt;
179 : :
180 [ # # # # ]: 0 : if (!G_APPROX_VALUE (self->last_v, 0.0, 0.01))
181 : 0 : self->last_v = (v + self->last_v) / 2;
182 : : else
183 : 0 : self->last_v = v;
184 : :
185 : : // TODO: acceleration setting
186 : 0 : m = pow (self->last_v, 1.0);
187 : 0 : m = fmin (4.0, fmax (m, 0.25));
188 : :
189 : 0 : *cx = round (dx * m);
190 : 0 : *cy = round (dy * m);
191 : :
192 : 0 : return dt >= CAPTURE_THRESHOLD_MS;
193 : : }
194 : :
195 : : static inline void
196 : 0 : valent_input_remote_pointer_reset (ValentInputRemote *self)
197 : : {
198 : 0 : self->claimed = FALSE;
199 : 0 : self->last_v = 0.0;
200 : 0 : self->last_x = 0.0;
201 : 0 : self->last_y = 0.0;
202 : 0 : self->timestamp = 0;
203 : 0 : }
204 : :
205 : : /*
206 : : * Scroll Mapping
207 : : */
208 : : static gboolean
209 : 0 : on_scroll (GtkEventControllerScroll *controller,
210 : : double dx,
211 : : double dy,
212 : : ValentInputRemote *self)
213 : : {
214 [ # # ]: 0 : g_assert (VALENT_IS_INPUT_REMOTE (self));
215 : :
216 [ # # ]: 0 : if (valent_input_remote_check_adapter (self))
217 : 0 : valent_input_adapter_pointer_axis (self->adapter, dx, dy);
218 : :
219 : 0 : return TRUE;
220 : : }
221 : :
222 : : /*
223 : : * Pointer Button Mapping
224 : : *
225 : : * This gesture maps pointer button presses and releases directly, except in the
226 : : * case of a press-move sequence of the primary button, which is used to emulate
227 : : * touchpad motion.
228 : : */
229 : : static void
230 : 0 : on_single_begin (GtkGestureDrag *gesture,
231 : : double start_x,
232 : : double start_y,
233 : : ValentInputRemote *self)
234 : : {
235 : 0 : GtkGestureSingle *single = GTK_GESTURE_SINGLE (gesture);
236 : 0 : unsigned int button = 0;
237 : :
238 [ # # ]: 0 : g_assert (VALENT_IS_INPUT_REMOTE (self));
239 : :
240 [ # # ]: 0 : if (!valent_input_remote_check_adapter (self))
241 : : return;
242 : :
243 : : /* Relative pointer motion is only emulated for the primary button, otherwise
244 : : * presses and releases are mapped directly to the adapter. */
245 : 0 : button = gtk_gesture_single_get_current_button (single);
246 : :
247 [ # # ]: 0 : if (button == GDK_BUTTON_PRIMARY)
248 : : {
249 : 0 : GdkEventSequence *sequence = NULL;
250 : 0 : uint32_t timestamp = 0;
251 : :
252 : 0 : sequence = gtk_gesture_single_get_current_sequence (single);
253 : 0 : get_last_update_time (GTK_GESTURE (gesture), sequence, ×tamp);
254 : :
255 : 0 : self->last_x = start_x;
256 : 0 : self->last_y = start_y;
257 : 0 : self->timestamp = timestamp;
258 : : }
259 : :
260 : : /* Always pass through the button press, since pointer motion is only
261 : : * emulated behaviour. */
262 : 0 : valent_input_adapter_pointer_button (self->adapter, button, TRUE);
263 : : }
264 : :
265 : : static void
266 : 0 : on_single_update (GtkGesture *gesture,
267 : : GdkEventSequence *sequence,
268 : : ValentInputRemote *self)
269 : : {
270 : 0 : unsigned int button = 0;
271 : 0 : uint32_t timestamp = 0;
272 : 0 : double x, y;
273 : 0 : double dx, dy;
274 : 0 : uint32_t dt;
275 : 0 : double cx, cy;
276 : :
277 [ # # ]: 0 : g_assert (VALENT_IS_INPUT_REMOTE (self));
278 : :
279 [ # # ]: 0 : if (!valent_input_remote_check_adapter (self))
280 : 0 : return;
281 : :
282 : 0 : button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
283 : :
284 [ # # ]: 0 : if (button != GDK_BUTTON_PRIMARY)
285 : : return;
286 : :
287 : 0 : get_last_update_time (gesture, sequence, ×tamp);
288 : 0 : gtk_gesture_get_point (gesture, sequence, &x, &y);
289 : :
290 : 0 : dt = timestamp - self->timestamp;
291 : 0 : dx = (x - self->last_x) * self->scale;
292 : 0 : dy = (y - self->last_y) * self->scale;
293 : :
294 [ # # ]: 0 : if (!calculate_delta (self, dx, dy, dt, &cx, &cy))
295 : : return;
296 : :
297 [ # # # # : 0 : if (dx >= 1.0 || dx <= -1.0 || dy >= 1.0 || dy <= -1.0)
# # # # ]
298 : : {
299 : 0 : self->claimed = TRUE;
300 : 0 : gtk_gesture_set_state (gesture, GTK_EVENT_SEQUENCE_CLAIMED);
301 : :
302 : 0 : self->last_x = x;
303 : 0 : self->last_y = y;
304 : 0 : self->timestamp = timestamp;
305 : :
306 : 0 : valent_input_adapter_pointer_motion (self->adapter, cx, cy);
307 : : }
308 : : }
309 : :
310 : : static void
311 : 0 : on_single_end (GtkGestureDrag *gesture,
312 : : double offset_x,
313 : : double offset_y,
314 : : ValentInputRemote *self)
315 : : {
316 : 0 : unsigned int button = 0;
317 : :
318 [ # # ]: 0 : g_assert (VALENT_IS_INPUT_REMOTE (self));
319 : :
320 [ # # ]: 0 : if (!valent_input_remote_check_adapter (self))
321 : : return;
322 : :
323 : 0 : button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
324 : 0 : valent_input_adapter_pointer_button (self->adapter, button, FALSE);
325 : 0 : valent_input_remote_pointer_reset (self);
326 : : }
327 : :
328 : : /*
329 : : * Touchpad Emulation
330 : : *
331 : : * These callbacks map gestures on the "touchpad" area to events including:
332 : : *
333 : : * - two-finger tap -> right click
334 : : * - three-finger tap -> middle click
335 : : */
336 : : static void
337 : 0 : on_double_begin (GtkGestureDrag *gesture,
338 : : double start_x,
339 : : double start_y,
340 : : ValentInputRemote *self)
341 : : {
342 [ # # ]: 0 : g_assert (VALENT_IS_INPUT_REMOTE (self));
343 : :
344 : : // TODO: In order to map two-finger presses directly to the input adapter,
345 : : // the implementation has to handle unpaired press-release sequences.
346 : : #if 0
347 : : if (!valent_input_remote_check_adapter (self))
348 : : return;
349 : :
350 : : valent_input_adapter_pointer_button (self->adapter,
351 : : GDK_BUTTON_SECONDARY,
352 : : TRUE);
353 : : #endif
354 : 0 : }
355 : :
356 : : static void
357 : 0 : on_double_end (GtkGestureDrag *gesture,
358 : : double offset_x,
359 : : double offset_y,
360 : : ValentInputRemote *self)
361 : : {
362 [ # # ]: 0 : g_assert (VALENT_IS_INPUT_REMOTE (self));
363 : :
364 [ # # ]: 0 : if (!valent_input_remote_check_adapter (self))
365 : : return;
366 : :
367 : : /* If the two-finger press wasn't claimed as a scroll event on the y-axis,
368 : : * simulate a right click by pressing and releasing the secondary button. */
369 : 0 : valent_input_adapter_pointer_button (self->adapter,
370 : : GDK_BUTTON_SECONDARY,
371 : : TRUE);
372 : 0 : valent_input_adapter_pointer_button (self->adapter,
373 : : GDK_BUTTON_SECONDARY,
374 : : FALSE);
375 : : }
376 : :
377 : : static void
378 : 0 : on_triple_begin (GtkGestureDrag *gesture,
379 : : double offset_x,
380 : : double offset_y,
381 : : ValentInputRemote *self)
382 : : {
383 [ # # ]: 0 : g_assert (VALENT_IS_INPUT_REMOTE (self));
384 : :
385 [ # # ]: 0 : if (!valent_input_remote_check_adapter (self))
386 : : return;
387 : :
388 : : /* Since there is no high-level event for three-finger drags, three-finger
389 : : * presses and releases can be mapped directly. */
390 : 0 : gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
391 : 0 : valent_input_adapter_pointer_button (self->adapter,
392 : : GDK_BUTTON_MIDDLE,
393 : : TRUE);
394 : : }
395 : :
396 : : static void
397 : 0 : on_triple_end (GtkGestureDrag *gesture,
398 : : double offset_x,
399 : : double offset_y,
400 : : ValentInputRemote *self)
401 : : {
402 [ # # ]: 0 : g_assert (VALENT_IS_INPUT_REMOTE (self));
403 : :
404 [ # # ]: 0 : if (!valent_input_remote_check_adapter (self))
405 : : return;
406 : :
407 : 0 : valent_input_adapter_pointer_button (self->adapter,
408 : : GDK_BUTTON_MIDDLE,
409 : : FALSE);
410 : : }
411 : :
412 : : /*
413 : : * Compose
414 : : */
415 : : static void
416 : 0 : on_compose_text_changed (GtkTextBuffer *buffer,
417 : : ValentInputRemote *self)
418 : : {
419 : 0 : gboolean enabled = FALSE;
420 : :
421 [ # # ]: 0 : if (gtk_text_buffer_get_char_count (buffer) > 0)
422 : 0 : enabled = valent_input_remote_check_adapter (self);
423 : :
424 : 0 : gtk_widget_action_set_enabled (GTK_WIDGET (self),
425 : : "remote.compose-send",
426 : : enabled);
427 : 0 : gtk_widget_action_set_enabled (GTK_WIDGET (self),
428 : : "remote.compose-clear",
429 : : enabled);
430 : 0 : }
431 : :
432 : : /*
433 : : * UI Callbacks
434 : : */
435 : : static void
436 : 0 : on_selected_item (GObject *object,
437 : : GParamSpec *pspec,
438 : : ValentInputRemote *self)
439 : : {
440 : 0 : ValentInputAdapter *adapter = NULL;
441 : :
442 [ # # ]: 0 : g_assert (VALENT_IS_INPUT_REMOTE (self));
443 : :
444 : 0 : adapter = gtk_drop_down_get_selected_item (GTK_DROP_DOWN (object));
445 [ # # ]: 0 : if (g_set_object (&self->adapter, adapter))
446 : 0 : valent_input_remote_check_adapter (self);
447 : :
448 : 0 : on_compose_text_changed (self->compose_text, self);
449 : 0 : }
450 : :
451 : : static void
452 : 0 : on_stack_page_changed (GObject *object,
453 : : GParamSpec *pspec,
454 : : ValentInputRemote *self)
455 : : {
456 : 0 : AdwViewStack *stack = ADW_VIEW_STACK (object);
457 : 0 : const char *page_name = NULL;
458 : :
459 [ # # ]: 0 : g_assert (VALENT_IS_INPUT_REMOTE (self));
460 : :
461 : 0 : page_name = adw_view_stack_get_visible_child_name (stack);
462 [ # # # # ]: 0 : if (self->capture_keyboard && g_strcmp0 (page_name, "touchpad") != 0)
463 : 0 : g_object_set (self, "capture-keyboard", FALSE, NULL);
464 : 0 : }
465 : :
466 : : /*
467 : : * GActions
468 : : */
469 : : static void
470 : 0 : remote_compose_send_action (GtkWidget *widget,
471 : : const char *action_name,
472 : : GVariant *parameter)
473 : : {
474 : 0 : ValentInputRemote *self = VALENT_INPUT_REMOTE (widget);
475 : 0 : g_autofree char *text = NULL;
476 : 0 : const char *next;
477 : 0 : gunichar codepoint;
478 : :
479 [ # # ]: 0 : g_assert (VALENT_IS_INPUT_REMOTE (self));
480 : :
481 [ # # # # ]: 0 : if (!valent_input_remote_check_adapter (self) ||
482 : 0 : gtk_text_buffer_get_char_count (self->compose_text) == 0)
483 : 0 : return;
484 : :
485 : 0 : g_object_get (self->compose_text, "text", &text, NULL);
486 : 0 : g_object_set (self->compose_text, "text", "", NULL);
487 : :
488 : 0 : next = text;
489 [ # # ]: 0 : while ((codepoint = g_utf8_get_char (next)) != 0)
490 : : {
491 : 0 : uint32_t keysym;
492 : :
493 : 0 : keysym = gdk_unicode_to_keyval (codepoint);
494 : 0 : valent_input_adapter_keyboard_keysym (self->adapter, keysym, TRUE);
495 : 0 : valent_input_adapter_keyboard_keysym (self->adapter, keysym, FALSE);
496 : 0 : next = g_utf8_next_char (next);
497 : : }
498 : : }
499 : :
500 : : static void
501 : 0 : remote_compose_clear_action (GtkWidget *widget,
502 : : const char *action_name,
503 : : GVariant *parameter)
504 : : {
505 : 0 : ValentInputRemote *self = VALENT_INPUT_REMOTE (widget);
506 : :
507 [ # # ]: 0 : g_assert (VALENT_IS_INPUT_REMOTE (self));
508 : :
509 [ # # ]: 0 : if (gtk_text_buffer_get_char_count (self->compose_text) > 0)
510 : 0 : g_object_set (self->compose_text, "text", "", NULL);
511 : 0 : }
512 : :
513 : : /*
514 : : * GObject
515 : : */
516 : : static void
517 : 1 : valent_input_remote_dispose (GObject *object)
518 : : {
519 : 1 : ValentInputRemote *self = VALENT_INPUT_REMOTE (object);
520 : :
521 [ - + ]: 1 : g_clear_object (&self->adapter);
522 [ + - ]: 1 : g_clear_object (&self->adapters);
523 : :
524 : 1 : gtk_widget_dispose_template (GTK_WIDGET (object), VALENT_TYPE_INPUT_REMOTE);
525 : :
526 : 1 : G_OBJECT_CLASS (valent_input_remote_parent_class)->dispose (object);
527 : 1 : }
528 : :
529 : : static void
530 : 7 : valent_input_remote_get_property (GObject *object,
531 : : guint prop_id,
532 : : GValue *value,
533 : : GParamSpec *pspec)
534 : : {
535 : 7 : ValentInputRemote *self = VALENT_INPUT_REMOTE (object);
536 : :
537 [ + + - ]: 7 : switch ((ValentInputRemoteProperty)prop_id)
538 : : {
539 : 3 : case PROP_ADAPTERS:
540 : 3 : g_value_set_object (value, self->adapters);
541 : 3 : break;
542 : :
543 : 4 : case PROP_CAPTURE_KEYBOARD:
544 : 4 : g_value_set_boolean (value, self->capture_keyboard);
545 : 4 : break;
546 : :
547 : 0 : default:
548 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
549 : : }
550 : 7 : }
551 : :
552 : : static void
553 : 1 : valent_input_remote_set_property (GObject *object,
554 : : guint prop_id,
555 : : const GValue *value,
556 : : GParamSpec *pspec)
557 : : {
558 : 1 : ValentInputRemote *self = VALENT_INPUT_REMOTE (object);
559 : :
560 [ + - - ]: 1 : switch ((ValentInputRemoteProperty)prop_id)
561 : : {
562 : 1 : case PROP_ADAPTERS:
563 : 1 : self->adapters = g_value_dup_object (value);
564 : 1 : break;
565 : :
566 : 0 : case PROP_CAPTURE_KEYBOARD:
567 : 0 : self->capture_keyboard = g_value_get_boolean (value);
568 : 0 : break;
569 : :
570 : 0 : default:
571 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
572 : : }
573 : 1 : }
574 : :
575 : : static void
576 : 1 : valent_input_remote_class_init (ValentInputRemoteClass *klass)
577 : : {
578 : 1 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
579 : 1 : GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
580 : :
581 : 1 : object_class->dispose = valent_input_remote_dispose;
582 : 1 : object_class->get_property = valent_input_remote_get_property;
583 : 1 : object_class->set_property = valent_input_remote_set_property;
584 : :
585 : 1 : gtk_widget_class_set_template_from_resource (widget_class, "/plugins/gnome/valent-input-remote.ui");
586 : 1 : gtk_widget_class_bind_template_child (widget_class, ValentInputRemote, input_adapter);
587 : 1 : gtk_widget_class_bind_template_child (widget_class, ValentInputRemote, keyboard);
588 : 1 : gtk_widget_class_bind_template_child (widget_class, ValentInputRemote, pointer_scroll);
589 : 1 : gtk_widget_class_bind_template_child (widget_class, ValentInputRemote, touchpad);
590 : 1 : gtk_widget_class_bind_template_child (widget_class, ValentInputRemote, touch_single);
591 : 1 : gtk_widget_class_bind_template_child (widget_class, ValentInputRemote, touch_double);
592 : 1 : gtk_widget_class_bind_template_child (widget_class, ValentInputRemote, touch_triple);
593 : 1 : gtk_widget_class_bind_template_child (widget_class, ValentInputRemote, compose_text);
594 : 1 : gtk_widget_class_bind_template_child (widget_class, ValentInputRemote, filter);
595 : 1 : gtk_widget_class_bind_template_child (widget_class, ValentInputRemote, model);
596 : :
597 : 1 : gtk_widget_class_bind_template_callback (widget_class, on_selected_item);
598 : 1 : gtk_widget_class_bind_template_callback (widget_class, on_stack_page_changed);
599 : 1 : gtk_widget_class_bind_template_callback (widget_class, on_key_pressed);
600 : 1 : gtk_widget_class_bind_template_callback (widget_class, on_key_released);
601 : 1 : gtk_widget_class_bind_template_callback (widget_class, on_scroll);
602 : 1 : gtk_widget_class_bind_template_callback (widget_class, on_single_begin);
603 : 1 : gtk_widget_class_bind_template_callback (widget_class, on_single_update);
604 : 1 : gtk_widget_class_bind_template_callback (widget_class, on_single_end);
605 : 1 : gtk_widget_class_bind_template_callback (widget_class, on_double_begin);
606 : 1 : gtk_widget_class_bind_template_callback (widget_class, on_double_end);
607 : 1 : gtk_widget_class_bind_template_callback (widget_class, on_triple_begin);
608 : 1 : gtk_widget_class_bind_template_callback (widget_class, on_triple_end);
609 : 1 : gtk_widget_class_bind_template_callback (widget_class, on_compose_text_changed);
610 : :
611 : 2 : properties [PROP_ADAPTERS] =
612 : 1 : g_param_spec_object ("adapters", NULL, NULL,
613 : : G_TYPE_LIST_MODEL,
614 : : (G_PARAM_READWRITE |
615 : : G_PARAM_CONSTRUCT_ONLY |
616 : : G_PARAM_STATIC_STRINGS));
617 : :
618 : 2 : properties [PROP_CAPTURE_KEYBOARD] =
619 : 1 : g_param_spec_boolean ("capture-keyboard", NULL, NULL,
620 : : FALSE,
621 : : (G_PARAM_READWRITE |
622 : : G_PARAM_STATIC_STRINGS));
623 : :
624 : 1 : g_object_class_install_properties (object_class, G_N_ELEMENTS (properties), properties);
625 : :
626 : 1 : gtk_widget_class_install_action (widget_class, "remote.compose-clear", NULL, remote_compose_clear_action);
627 : 1 : gtk_widget_class_install_action (widget_class, "remote.compose-send", NULL, remote_compose_send_action);
628 : 1 : gtk_widget_class_install_property_action (widget_class,
629 : : "remote.capture-keyboard",
630 : : "capture-keyboard");
631 : 1 : }
632 : :
633 : : static void
634 : 1 : valent_input_remote_init (ValentInputRemote *self)
635 : : {
636 : 1 : gtk_widget_init_template (GTK_WIDGET (self));
637 : 1 : gtk_gesture_group (self->touch_single, self->touch_double);
638 : 1 : gtk_gesture_group (self->touch_single, self->touch_triple);
639 : 1 : gtk_custom_filter_set_filter_func (GTK_CUSTOM_FILTER (self->filter),
640 : : valent_input_remote_filter,
641 : : self,
642 : : NULL);
643 : 1 : self->scale = gtk_widget_get_scale_factor (GTK_WIDGET (self));
644 : 1 : }
645 : :
|