1 #include <gtk/gtk.h>
2
3 #define GTK_COMPILATION
4 #include "gdk/gdkeventsprivate.h"
5
6 typedef struct {
7 GtkWidget *widget;
8 int x;
9 int y;
10 guint state;
11 guint pressed : 1;
12 } PointState;
13
14 static PointState mouse_state;
15 static PointState touch_state[10]; /* touchpoint 0 gets pointer emulation,
16 * use it first in tests for consistency.
17 */
18
19 #define EVENT_SEQUENCE(point) (GdkEventSequence*) ((point) - touch_state + 1)
20
21 static void
inject_event(GdkEvent * event)22 inject_event (GdkEvent *event)
23 {
24 gboolean handled;
25
26 g_signal_emit_by_name (event->surface, "event", event, &handled);
27 }
28
29 static void
point_press(PointState * point,GtkWidget * widget,guint button)30 point_press (PointState *point,
31 GtkWidget *widget,
32 guint button)
33 {
34 GdkDisplay *display;
35 GdkDevice *device;
36 GdkSeat *seat;
37 GdkSurface *surface;
38 GdkEvent *ev;
39
40 display = gtk_widget_get_display (widget);
41 seat = gdk_display_get_default_seat (display);
42 device = gdk_seat_get_pointer (seat);
43 surface = gtk_native_get_surface (gtk_widget_get_native (widget));
44
45 if (point == &mouse_state)
46 {
47 ev = gdk_button_event_new (GDK_BUTTON_PRESS,
48 surface,
49 device,
50 device,
51 NULL,
52 GDK_CURRENT_TIME,
53 point->x,
54 point->y,
55 button,
56 point->state);
57
58 point->state |= GDK_BUTTON1_MASK << (button - 1);
59 }
60 else
61 {
62 ev = gdk_touch_event_new (GDK_TOUCH_BEGIN,
63 EVENT_SEQUENCE (point),
64 surface,
65 device,
66 device,
67 GDK_CURRENT_TIME,
68 point->state,
69 point->x,
70 point->y,
71 point == &touch_state[0]);
72 }
73
74 inject_event (ev);
75
76 g_object_unref (ev);
77
78 point->widget = widget;
79 }
80
81 static void
point_update(PointState * point,GtkWidget * widget,double x,double y)82 point_update (PointState *point,
83 GtkWidget *widget,
84 double x,
85 double y)
86 {
87 GdkDisplay *display;
88 GdkDevice *device;
89 GdkSeat *seat;
90 GdkSurface *surface;
91 GdkEvent *ev;
92
93 display = gtk_widget_get_display (widget);
94 seat = gdk_display_get_default_seat (display);
95 device = gdk_seat_get_pointer (seat);
96 surface = gtk_native_get_surface (gtk_widget_get_native (widget));
97
98 point->x = x;
99 point->y = y;
100
101 if (point == &mouse_state)
102 {
103 ev = gdk_motion_event_new (surface,
104 device,
105 device,
106 NULL,
107 GDK_CURRENT_TIME,
108 point->state,
109 point->x,
110 point->y);
111 }
112 else
113 {
114 if (!point->widget || widget != point->widget)
115 return;
116
117 ev = gdk_touch_event_new (GDK_TOUCH_UPDATE,
118 EVENT_SEQUENCE (point),
119 surface,
120 device,
121 device,
122 GDK_CURRENT_TIME,
123 point->state,
124 point->x,
125 point->y,
126 point == &touch_state[0]);
127 }
128
129 inject_event (ev);
130
131 g_object_unref (ev);
132 }
133
134 static void
point_release(PointState * point,guint button)135 point_release (PointState *point,
136 guint button)
137 {
138 GdkDisplay *display;
139 GdkDevice *device;
140 GdkSeat *seat;
141 GdkSurface *surface;
142 GdkEvent *ev;
143
144 if (point->widget == NULL)
145 return;
146
147 display = gtk_widget_get_display (point->widget);
148 seat = gdk_display_get_default_seat (display);
149 device = gdk_seat_get_pointer (seat);
150 surface = gtk_native_get_surface (gtk_widget_get_native (point->widget));
151
152 if (!point->widget)
153 return;
154
155 if (point == &mouse_state)
156 {
157 if ((point->state & (GDK_BUTTON1_MASK << (button - 1))) == 0)
158 return;
159
160 ev = gdk_button_event_new (GDK_BUTTON_RELEASE,
161 surface,
162 device,
163 device,
164 NULL,
165 GDK_CURRENT_TIME,
166 point->x,
167 point->y,
168 button,
169 point->state);
170
171 point->state &= ~(GDK_BUTTON1_MASK << (button - 1));
172 }
173 else
174 {
175 ev = gdk_touch_event_new (GDK_TOUCH_END,
176 EVENT_SEQUENCE (point),
177 surface,
178 device,
179 device,
180 GDK_CURRENT_TIME,
181 point->state,
182 point->x,
183 point->y,
184 point == &touch_state[0]);
185 }
186
187 inject_event (ev);
188
189 g_object_unref (ev);
190 }
191
192 static const char *
phase_nick(GtkPropagationPhase phase)193 phase_nick (GtkPropagationPhase phase)
194 {
195 GTypeClass *class;
196 GEnumValue *value;
197
198 class = g_type_class_ref (GTK_TYPE_PROPAGATION_PHASE);
199 value = g_enum_get_value ((GEnumClass*)class, phase);
200 g_type_class_unref (class);
201
202 return value->value_nick;
203 }
204
205 static const char *
state_nick(GtkEventSequenceState state)206 state_nick (GtkEventSequenceState state)
207 {
208 GTypeClass *class;
209 GEnumValue *value;
210
211 class = g_type_class_ref (GTK_TYPE_EVENT_SEQUENCE_STATE);
212 value = g_enum_get_value ((GEnumClass*)class, state);
213 g_type_class_unref (class);
214
215 return value->value_nick;
216 }
217
218 typedef struct {
219 GtkEventController *controller;
220 GString *str;
221 gboolean exit;
222 } LegacyData;
223
224 static gboolean
legacy_cb(GtkEventControllerLegacy * c,GdkEvent * button,gpointer data)225 legacy_cb (GtkEventControllerLegacy *c, GdkEvent *button, gpointer data)
226 {
227 if (gdk_event_get_event_type (button) == GDK_BUTTON_PRESS)
228 {
229 LegacyData *ld = data;
230 GtkWidget *w;
231
232 w = gtk_event_controller_get_widget (ld->controller);
233
234 if (ld->str->len > 0)
235 g_string_append (ld->str, ", ");
236 g_string_append_printf (ld->str, "legacy %s", gtk_widget_get_name (w));
237
238 return ld->exit;
239 }
240
241 return GDK_EVENT_PROPAGATE;
242 }
243
244 typedef struct {
245 GString *str;
246 GtkEventSequenceState state;
247 } GestureData;
248
249 static void
press_cb(GtkGesture * g,int n_press,double x,double y,gpointer data)250 press_cb (GtkGesture *g, int n_press, double x, double y, gpointer data)
251 {
252 GtkEventController *c = GTK_EVENT_CONTROLLER (g);
253 GdkEventSequence *sequence;
254 GtkPropagationPhase phase;
255 GestureData *gd = data;
256 const char *name;
257
258 name = g_object_get_data (G_OBJECT (g), "name");
259 phase = gtk_event_controller_get_propagation_phase (c);
260
261 if (gd->str->len > 0)
262 g_string_append (gd->str, ", ");
263 g_string_append_printf (gd->str, "%s %s", phase_nick (phase), name);
264
265 sequence = gtk_gesture_get_last_updated_sequence (g);
266
267 if (sequence)
268 g_string_append_printf (gd->str, " (%x)", GPOINTER_TO_UINT (sequence));
269
270 if (gd->state != GTK_EVENT_SEQUENCE_NONE)
271 gtk_gesture_set_state (g, gd->state);
272 }
273
274 static void
cancel_cb(GtkGesture * g,GdkEventSequence * sequence,gpointer data)275 cancel_cb (GtkGesture *g, GdkEventSequence *sequence, gpointer data)
276 {
277 GestureData *gd = data;
278 const char *name;
279
280 name = g_object_get_data (G_OBJECT (g), "name");
281
282 if (gd->str->len > 0)
283 g_string_append (gd->str, ", ");
284 g_string_append_printf (gd->str, "%s cancelled", name);
285 }
286
287 static void
begin_cb(GtkGesture * g,GdkEventSequence * sequence,gpointer data)288 begin_cb (GtkGesture *g, GdkEventSequence *sequence, gpointer data)
289 {
290 GestureData *gd = data;
291 const char *name;
292
293 name = g_object_get_data (G_OBJECT (g), "name");
294
295 if (gd->str->len > 0)
296 g_string_append (gd->str, ", ");
297 g_string_append_printf (gd->str, "%s began", name);
298
299 if (gd->state != GTK_EVENT_SEQUENCE_NONE)
300 gtk_gesture_set_state (g, gd->state);
301 }
302
303 static void
end_cb(GtkGesture * g,GdkEventSequence * sequence,gpointer data)304 end_cb (GtkGesture *g, GdkEventSequence *sequence, gpointer data)
305 {
306 GestureData *gd = data;
307 const char *name;
308
309 name = g_object_get_data (G_OBJECT (g), "name");
310
311 if (gd->str->len > 0)
312 g_string_append (gd->str, ", ");
313 g_string_append_printf (gd->str, "%s ended", name);
314 }
315
316 static void
update_cb(GtkGesture * g,GdkEventSequence * sequence,gpointer data)317 update_cb (GtkGesture *g, GdkEventSequence *sequence, gpointer data)
318 {
319 GestureData *gd = data;
320 const char *name;
321
322 name = g_object_get_data (G_OBJECT (g), "name");
323
324 if (gd->str->len > 0)
325 g_string_append (gd->str, ", ");
326 g_string_append_printf (gd->str, "%s updated", name);
327 }
328
329 static void
state_changed_cb(GtkGesture * g,GdkEventSequence * sequence,GtkEventSequenceState state,gpointer data)330 state_changed_cb (GtkGesture *g, GdkEventSequence *sequence, GtkEventSequenceState state, gpointer data)
331 {
332 GestureData *gd = data;
333 const char *name;
334
335 name = g_object_get_data (G_OBJECT (g), "name");
336
337 if (gd->str->len > 0)
338 g_string_append (gd->str, ", ");
339 g_string_append_printf (gd->str, "%s state %s", name, state_nick (state));
340
341 if (sequence != NULL)
342 g_string_append_printf (gd->str, " (%x)", GPOINTER_TO_UINT (sequence));
343 }
344
345
346 static GtkGesture *
add_gesture(GtkWidget * w,const char * name,GtkPropagationPhase phase,GString * str,GtkEventSequenceState state)347 add_gesture (GtkWidget *w, const char *name, GtkPropagationPhase phase, GString *str, GtkEventSequenceState state)
348 {
349 GtkGesture *g;
350 GestureData *data;
351
352 data = g_new (GestureData, 1);
353 data->str = str;
354 data->state = state;
355
356 g = gtk_gesture_click_new ();
357 gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (g), FALSE);
358 gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (g), 1);
359 gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (g), phase);
360 gtk_widget_add_controller (w, GTK_EVENT_CONTROLLER (g));
361
362 g_object_set_data (G_OBJECT (g), "name", (gpointer)name);
363
364 g_signal_connect (g, "pressed", G_CALLBACK (press_cb), data);
365 g_signal_connect (g, "cancel", G_CALLBACK (cancel_cb), data);
366 g_signal_connect (g, "update", G_CALLBACK (update_cb), data);
367 g_signal_connect (g, "sequence-state-changed", G_CALLBACK (state_changed_cb), data);
368
369 return g;
370 }
371
372 static GtkGesture *
add_mt_gesture(GtkWidget * w,const char * name,GtkPropagationPhase phase,GString * str,GtkEventSequenceState state)373 add_mt_gesture (GtkWidget *w, const char *name, GtkPropagationPhase phase, GString *str, GtkEventSequenceState state)
374 {
375 GtkGesture *g;
376 GestureData *data;
377
378 data = g_new (GestureData, 1);
379 data->str = str;
380 data->state = state;
381
382 g = gtk_gesture_rotate_new ();
383 gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (g), phase);
384 gtk_widget_add_controller (w, GTK_EVENT_CONTROLLER (g));
385
386 g_object_set_data (G_OBJECT (g), "name", (gpointer)name);
387
388 g_signal_connect (g, "begin", G_CALLBACK (begin_cb), data);
389 g_signal_connect (g, "update", G_CALLBACK (update_cb), data);
390 g_signal_connect (g, "end", G_CALLBACK (end_cb), data);
391 g_signal_connect (g, "sequence-state-changed", G_CALLBACK (state_changed_cb), data);
392
393 return g;
394 }
395
396 static void
add_legacy(GtkWidget * w,GString * str,gboolean exit)397 add_legacy (GtkWidget *w, GString *str, gboolean exit)
398 {
399 LegacyData *data;
400
401 data = g_new (LegacyData, 1);
402 data->controller = gtk_event_controller_legacy_new ();
403 data->str = str;
404 data->exit = exit;
405
406 gtk_event_controller_set_propagation_phase (data->controller, GTK_PHASE_BUBBLE);
407 gtk_widget_add_controller (w, data->controller);
408 g_signal_connect (data->controller, "event", G_CALLBACK (legacy_cb), data);
409 }
410
411 static void
test_phases(void)412 test_phases (void)
413 {
414 GtkWidget *A, *B, *C;
415 GString *str;
416 GtkAllocation allocation;
417
418 A = gtk_window_new ();
419 gtk_widget_set_name (A, "A");
420 B = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
421 gtk_widget_set_name (B, "B");
422 C = gtk_image_new ();
423 gtk_widget_set_hexpand (C, TRUE);
424 gtk_widget_set_vexpand (C, TRUE);
425 gtk_widget_set_name (C, "C");
426
427 gtk_box_append (GTK_BOX (A), B);
428 gtk_box_append (GTK_BOX (B), C);
429
430 gtk_widget_show (A);
431
432 str = g_string_new ("");
433
434 add_gesture (A, "a1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
435 add_gesture (B, "b1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
436 add_gesture (C, "c1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
437 add_gesture (A, "a2", GTK_PHASE_TARGET, str, GTK_EVENT_SEQUENCE_NONE);
438 add_gesture (B, "b2", GTK_PHASE_TARGET, str, GTK_EVENT_SEQUENCE_NONE);
439 add_gesture (C, "c2", GTK_PHASE_TARGET, str, GTK_EVENT_SEQUENCE_NONE);
440 add_gesture (A, "a3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
441 add_gesture (B, "b3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
442 add_gesture (C, "c3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
443
444 gtk_widget_get_allocation (B, &allocation);
445
446 point_update (&mouse_state, A, allocation.x, allocation.y);
447 point_press (&mouse_state, A, 1);
448
449 g_assert_cmpstr (str->str, ==,
450 "capture a1, "
451 "capture b1, "
452 "capture c1, "
453 "target c2, "
454 "bubble c3, "
455 "bubble b3, "
456 "bubble a3");
457
458 g_string_free (str, TRUE);
459
460 gtk_window_destroy (A);
461 }
462
463 static void
test_mixed(void)464 test_mixed (void)
465 {
466 GtkWidget *A, *B, *C;
467 GString *str;
468 GtkAllocation allocation;
469
470 A = gtk_window_new ();
471 gtk_widget_set_name (A, "A");
472 B = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
473 gtk_widget_set_name (B, "B");
474 C = gtk_image_new ();
475 gtk_widget_set_hexpand (C, TRUE);
476 gtk_widget_set_vexpand (C, TRUE);
477 gtk_widget_set_name (C, "C");
478
479 gtk_box_append (GTK_BOX (A), B);
480 gtk_box_append (GTK_BOX (B), C);
481
482 gtk_widget_show (A);
483
484 str = g_string_new ("");
485
486 add_legacy (A, str, GDK_EVENT_PROPAGATE);
487 add_legacy (B, str, GDK_EVENT_PROPAGATE);
488 add_legacy (C, str, GDK_EVENT_PROPAGATE);
489
490 add_gesture (A, "a1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
491 add_gesture (B, "b1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
492 add_gesture (C, "c1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
493 add_gesture (A, "a2", GTK_PHASE_TARGET, str, GTK_EVENT_SEQUENCE_NONE);
494 add_gesture (B, "b2", GTK_PHASE_TARGET, str, GTK_EVENT_SEQUENCE_NONE);
495 add_gesture (C, "c2", GTK_PHASE_TARGET, str, GTK_EVENT_SEQUENCE_NONE);
496 add_gesture (A, "a3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
497 add_gesture (B, "b3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
498 add_gesture (C, "c3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
499
500 gtk_widget_get_allocation (B, &allocation);
501
502 point_update (&mouse_state, A, allocation.x, allocation.y);
503 point_press (&mouse_state, A, 1);
504
505 g_assert_cmpstr (str->str, ==,
506 "capture a1, "
507 "capture b1, "
508 "capture c1, "
509 "target c2, "
510 "bubble c3, "
511 "legacy C, "
512 "bubble b3, "
513 "legacy B, "
514 "bubble a3, "
515 "legacy A");
516
517 g_string_free (str, TRUE);
518
519 gtk_window_destroy (A);
520 }
521
522 static void
test_early_exit(void)523 test_early_exit (void)
524 {
525 GtkWidget *A, *B, *C;
526 GString *str;
527 GtkAllocation allocation;
528
529 A = gtk_window_new ();
530 gtk_widget_set_name (A, "A");
531 B = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
532 gtk_widget_set_name (B, "B");
533 C = gtk_image_new ();
534 gtk_widget_set_hexpand (C, TRUE);
535 gtk_widget_set_vexpand (C, TRUE);
536 gtk_widget_set_name (C, "C");
537
538 gtk_box_append (GTK_BOX (A), B);
539 gtk_box_append (GTK_BOX (B), C);
540
541 gtk_widget_show (A);
542
543 str = g_string_new ("");
544
545 add_legacy (A, str, GDK_EVENT_PROPAGATE);
546 add_legacy (B, str, GDK_EVENT_STOP);
547 add_legacy (C, str, GDK_EVENT_PROPAGATE);
548
549 add_gesture (A, "a1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
550 add_gesture (B, "b1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
551 add_gesture (C, "c1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
552 add_gesture (C, "c2", GTK_PHASE_TARGET, str, GTK_EVENT_SEQUENCE_NONE);
553 add_gesture (A, "a3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
554 add_gesture (B, "b3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
555 add_gesture (C, "c3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
556
557 gtk_widget_get_allocation (B, &allocation);
558
559 point_update (&mouse_state, A, allocation.x, allocation.y);
560 point_press (&mouse_state, A, 1);
561
562 g_assert_cmpstr (str->str, ==,
563 "capture a1, "
564 "capture b1, "
565 "capture c1, "
566 "target c2, "
567 "bubble c3, "
568 "legacy C, "
569 "bubble b3, "
570 "legacy B");
571
572 g_string_free (str, TRUE);
573
574 gtk_window_destroy (A);
575 }
576
577 static void
test_claim_capture(void)578 test_claim_capture (void)
579 {
580 GtkWidget *A, *B, *C;
581 GString *str;
582 GtkAllocation allocation;
583
584 A = gtk_window_new ();
585 gtk_widget_set_name (A, "A");
586 B = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
587 gtk_widget_set_name (B, "B");
588 C = gtk_image_new ();
589 gtk_widget_set_hexpand (C, TRUE);
590 gtk_widget_set_vexpand (C, TRUE);
591 gtk_widget_set_name (C, "C");
592
593 gtk_box_append (GTK_BOX (A), B);
594 gtk_box_append (GTK_BOX (B), C);
595
596 gtk_widget_show (A);
597
598 str = g_string_new ("");
599
600 add_gesture (A, "a1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
601 add_gesture (B, "b1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
602 add_gesture (C, "c1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_CLAIMED);
603 add_gesture (C, "c2", GTK_PHASE_TARGET, str, GTK_EVENT_SEQUENCE_NONE);
604 add_gesture (A, "a3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
605 add_gesture (B, "b3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
606 add_gesture (C, "c3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
607
608 gtk_widget_get_allocation (B, &allocation);
609
610 point_update (&mouse_state, A, allocation.x, allocation.y);
611 point_press (&mouse_state, A, 1);
612
613 g_assert_cmpstr (str->str, ==,
614 "capture a1, "
615 "capture b1, "
616 "capture c1, "
617 "c1 state claimed");
618
619 g_string_free (str, TRUE);
620
621 gtk_window_destroy (A);
622 }
623
624 static void
test_claim_target(void)625 test_claim_target (void)
626 {
627 GtkWidget *A, *B, *C;
628 GString *str;
629 GtkAllocation allocation;
630
631 A = gtk_window_new ();
632 gtk_widget_set_name (A, "A");
633 B = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
634 gtk_widget_set_name (B, "B");
635 C = gtk_image_new ();
636 gtk_widget_set_hexpand (C, TRUE);
637 gtk_widget_set_vexpand (C, TRUE);
638 gtk_widget_set_name (C, "C");
639
640 gtk_box_append (GTK_BOX (A), B);
641 gtk_box_append (GTK_BOX (B), C);
642
643 gtk_widget_show (A);
644
645 str = g_string_new ("");
646
647 add_gesture (A, "a1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
648 add_gesture (B, "b1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
649 add_gesture (C, "c1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
650 add_gesture (C, "c2", GTK_PHASE_TARGET, str, GTK_EVENT_SEQUENCE_CLAIMED);
651 add_gesture (A, "a3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
652 add_gesture (B, "b3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
653 add_gesture (C, "c3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
654
655 gtk_widget_get_allocation (B, &allocation);
656 point_update (&mouse_state, A, allocation.x, allocation.y);
657 point_press (&mouse_state, A, 1);
658
659 g_assert_cmpstr (str->str, ==,
660 "capture a1, "
661 "capture b1, "
662 "capture c1, "
663 "target c2, "
664 "c2 state claimed");
665
666 g_string_free (str, TRUE);
667
668 gtk_window_destroy (A);
669 }
670
671 static void
test_claim_bubble(void)672 test_claim_bubble (void)
673 {
674 GtkWidget *A, *B, *C;
675 GString *str;
676 GtkAllocation allocation;
677
678 A = gtk_window_new ();
679 gtk_widget_set_name (A, "A");
680 B = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
681 gtk_widget_set_name (B, "B");
682 C = gtk_image_new ();
683 gtk_widget_set_hexpand (C, TRUE);
684 gtk_widget_set_vexpand (C, TRUE);
685 gtk_widget_set_name (C, "C");
686
687 gtk_box_append (GTK_BOX (A), B);
688 gtk_box_append (GTK_BOX (B), C);
689
690 gtk_widget_show (A);
691
692 str = g_string_new ("");
693
694 add_gesture (A, "a1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
695 add_gesture (B, "b1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
696 add_gesture (C, "c1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
697 add_gesture (C, "c2", GTK_PHASE_TARGET, str, GTK_EVENT_SEQUENCE_NONE);
698 add_gesture (A, "a3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
699 add_gesture (B, "b3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_CLAIMED);
700 add_gesture (C, "c3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
701
702 gtk_widget_get_allocation (B, &allocation);
703 point_update (&mouse_state, A, allocation.x, allocation.y);
704 point_press (&mouse_state, A, 1);
705
706 g_assert_cmpstr (str->str, ==,
707 "capture a1, "
708 "capture b1, "
709 "capture c1, "
710 "target c2, "
711 "bubble c3, "
712 "bubble b3, "
713 "c3 cancelled, "
714 "c2 cancelled, "
715 "c1 cancelled, "
716 "b3 state claimed"
717 );
718
719 g_string_free (str, TRUE);
720
721 gtk_window_destroy (A);
722 }
723
724 static void
test_early_claim_capture(void)725 test_early_claim_capture (void)
726 {
727 GtkWidget *A, *B, *C;
728 GtkGesture *g;
729 GString *str;
730 GtkAllocation allocation;
731
732 A = gtk_window_new ();
733 gtk_widget_set_name (A, "A");
734 B = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
735 gtk_widget_set_name (B, "B");
736 C = gtk_image_new ();
737 gtk_widget_set_hexpand (C, TRUE);
738 gtk_widget_set_vexpand (C, TRUE);
739 gtk_widget_set_name (C, "C");
740
741 gtk_box_append (GTK_BOX (A), B);
742 gtk_box_append (GTK_BOX (B), C);
743
744 gtk_widget_show (A);
745
746 str = g_string_new ("");
747
748 add_gesture (A, "a1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
749 g = add_gesture (B, "b1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_CLAIMED);
750 add_gesture (C, "c1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_CLAIMED);
751 add_gesture (C, "c2", GTK_PHASE_TARGET, str, GTK_EVENT_SEQUENCE_NONE);
752 add_gesture (A, "a3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
753 add_gesture (B, "b3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
754 add_gesture (C, "c3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
755
756 gtk_widget_get_allocation (B, &allocation);
757 point_update (&mouse_state, A, allocation.x, allocation.y);
758 point_press (&mouse_state, A, 1);
759
760 g_assert_cmpstr (str->str, ==,
761 "capture a1, "
762 "capture b1, "
763 "b1 state claimed");
764
765 /* Reset the string */
766 g_string_erase (str, 0, str->len);
767
768 gtk_gesture_set_state (g, GTK_EVENT_SEQUENCE_DENIED);
769
770 g_assert_cmpstr (str->str, ==,
771 "capture c1, "
772 "c1 state claimed, "
773 "b1 state denied");
774
775 point_release (&mouse_state, 1);
776
777 g_string_free (str, TRUE);
778 gtk_window_destroy (A);
779 }
780
781 static void
test_late_claim_capture(void)782 test_late_claim_capture (void)
783 {
784 GtkWidget *A, *B, *C;
785 GtkGesture *g;
786 GString *str;
787 GtkAllocation allocation;
788
789 A = gtk_window_new ();
790 gtk_widget_set_name (A, "A");
791 B = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
792 gtk_widget_set_name (B, "B");
793 C = gtk_image_new ();
794 gtk_widget_set_hexpand (C, TRUE);
795 gtk_widget_set_vexpand (C, TRUE);
796 gtk_widget_set_name (C, "C");
797
798 gtk_box_append (GTK_BOX (A), B);
799 gtk_box_append (GTK_BOX (B), C);
800
801 gtk_widget_show (A);
802
803 str = g_string_new ("");
804
805 add_gesture (A, "a1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
806 g = add_gesture (B, "b1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
807 add_gesture (C, "c1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
808 add_gesture (C, "c2", GTK_PHASE_TARGET, str, GTK_EVENT_SEQUENCE_CLAIMED);
809 add_gesture (A, "a3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
810 add_gesture (B, "b3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
811 add_gesture (C, "c3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
812
813 gtk_widget_get_allocation (B, &allocation);
814 point_update (&mouse_state, A, allocation.x, allocation.y);
815 point_press (&mouse_state, A, 1);
816
817 g_assert_cmpstr (str->str, ==,
818 "capture a1, "
819 "capture b1, "
820 "capture c1, "
821 "target c2, "
822 "c2 state claimed");
823
824 /* Reset the string */
825 g_string_erase (str, 0, str->len);
826
827 gtk_gesture_set_state (g, GTK_EVENT_SEQUENCE_CLAIMED);
828
829 g_assert_cmpstr (str->str, ==,
830 "c2 cancelled, "
831 "c1 cancelled, "
832 "b1 state claimed");
833
834 point_release (&mouse_state, 1);
835
836 g_string_free (str, TRUE);
837 gtk_window_destroy (A);
838 }
839
840 static void
test_group(void)841 test_group (void)
842 {
843 GtkWidget *A, *B, *C;
844 GString *str;
845 GtkGesture *g1, *g2;
846 GtkAllocation allocation;
847
848 A = gtk_window_new ();
849 gtk_widget_set_name (A, "A");
850 B = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
851 gtk_widget_set_name (B, "B");
852 C = gtk_image_new ();
853 gtk_widget_set_hexpand (C, TRUE);
854 gtk_widget_set_vexpand (C, TRUE);
855 gtk_widget_set_name (C, "C");
856
857 gtk_box_append (GTK_BOX (A), B);
858 gtk_box_append (GTK_BOX (B), C);
859
860 gtk_widget_show (A);
861
862 str = g_string_new ("");
863
864 add_gesture (A, "a1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
865 add_gesture (B, "b1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
866 add_gesture (C, "c1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
867 g1 = add_gesture (C, "c2", GTK_PHASE_TARGET, str, GTK_EVENT_SEQUENCE_NONE);
868 g2 = add_gesture (C, "c3", GTK_PHASE_TARGET, str, GTK_EVENT_SEQUENCE_CLAIMED);
869 gtk_gesture_group (g1, g2);
870 add_gesture (A, "a3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
871 add_gesture (B, "b3", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
872 add_gesture (C, "c4", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
873
874 gtk_widget_get_allocation (B, &allocation);
875 point_update (&mouse_state, A, allocation.x, allocation.y);
876 point_press (&mouse_state, A, 1);
877
878 g_assert_cmpstr (str->str, ==,
879 "capture a1, "
880 "capture b1, "
881 "capture c1, "
882 "target c3, "
883 "c3 state claimed, "
884 "c2 state claimed, "
885 "target c2");
886
887 g_string_free (str, TRUE);
888
889 gtk_window_destroy (A);
890 }
891
892 static void
test_gestures_outside_grab(void)893 test_gestures_outside_grab (void)
894 {
895 GtkWidget *A, *B, *C, *D;
896 GString *str;
897 GtkAllocation allocation;
898
899 A = gtk_window_new ();
900 gtk_widget_set_name (A, "A");
901 B = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
902 gtk_widget_set_name (B, "B");
903 C = gtk_image_new ();
904 gtk_widget_set_hexpand (C, TRUE);
905 gtk_widget_set_vexpand (C, TRUE);
906 gtk_widget_set_name (C, "C");
907
908 gtk_box_append (GTK_BOX (A), B);
909 gtk_box_append (GTK_BOX (B), C);
910
911 gtk_widget_show (A);
912
913 D = gtk_window_new ();
914 gtk_widget_show (D);
915
916 str = g_string_new ("");
917
918 add_gesture (A, "a1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
919 add_gesture (B, "b1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
920 add_gesture (C, "c1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
921 add_gesture (C, "c2", GTK_PHASE_TARGET, str, GTK_EVENT_SEQUENCE_CLAIMED);
922 add_gesture (B, "b2", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
923 add_gesture (A, "a2", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
924
925 gtk_widget_get_allocation (B, &allocation);
926 point_update (&mouse_state, A, allocation.x, allocation.y);
927 point_press (&mouse_state, A, 1);
928
929 g_assert_cmpstr (str->str, ==,
930 "capture a1, "
931 "capture b1, "
932 "capture c1, "
933 "target c2, "
934 "c2 state claimed");
935
936 /* Set a grab on another window */
937 g_string_erase (str, 0, str->len);
938 gtk_grab_add (D);
939
940 g_assert_cmpstr (str->str, ==,
941 "c1 cancelled, "
942 "c2 cancelled, "
943 "b1 cancelled, "
944 "a1 cancelled");
945
946 g_string_free (str, TRUE);
947
948 gtk_window_destroy (A);
949 gtk_window_destroy (D);
950 }
951
952 static void
test_gestures_inside_grab(void)953 test_gestures_inside_grab (void)
954 {
955 GtkWidget *A, *B, *C;
956 GString *str;
957 GtkAllocation allocation;
958
959 A = gtk_window_new ();
960 gtk_widget_set_name (A, "A");
961 B = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
962 gtk_widget_set_name (B, "B");
963 C = gtk_image_new ();
964 gtk_widget_set_hexpand (C, TRUE);
965 gtk_widget_set_vexpand (C, TRUE);
966 gtk_widget_set_name (C, "C");
967
968 gtk_box_append (GTK_BOX (A), B);
969 gtk_box_append (GTK_BOX (B), C);
970
971 gtk_widget_show (A);
972
973 str = g_string_new ("");
974
975 add_gesture (A, "a1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
976 add_gesture (B, "b1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
977 add_gesture (C, "c1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
978 add_gesture (C, "c2", GTK_PHASE_TARGET, str, GTK_EVENT_SEQUENCE_CLAIMED);
979 add_gesture (B, "b2", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
980 add_gesture (A, "a2", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_NONE);
981
982 gtk_widget_get_allocation (B, &allocation);
983 point_update (&mouse_state, A, allocation.x, allocation.y);
984 point_press (&mouse_state, A, 1);
985
986 g_assert_cmpstr (str->str, ==,
987 "capture a1, "
988 "capture b1, "
989 "capture c1, "
990 "target c2, "
991 "c2 state claimed");
992
993 /* Set a grab on B */
994 g_string_erase (str, 0, str->len);
995 gtk_grab_add (B);
996 g_assert_cmpstr (str->str, ==,
997 "a1 cancelled");
998
999 /* Update with the grab under effect */
1000 g_string_erase (str, 0, str->len);
1001 point_update (&mouse_state, A, allocation.x, allocation.y);
1002 g_assert_cmpstr (str->str, ==,
1003 "b1 updated, "
1004 "c1 updated, "
1005 "c2 updated");
1006
1007 g_string_free (str, TRUE);
1008
1009 gtk_window_destroy (A);
1010 }
1011
1012 static void
test_multitouch_on_single(void)1013 test_multitouch_on_single (void)
1014 {
1015 GtkWidget *A, *B, *C;
1016 GString *str;
1017 GtkAllocation allocation;
1018
1019 A = gtk_window_new ();
1020 gtk_widget_set_name (A, "A");
1021 B = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1022 gtk_widget_set_name (B, "B");
1023 C = gtk_image_new ();
1024 gtk_widget_set_hexpand (C, TRUE);
1025 gtk_widget_set_vexpand (C, TRUE);
1026 gtk_widget_set_name (C, "C");
1027
1028 gtk_box_append (GTK_BOX (A), B);
1029 gtk_box_append (GTK_BOX (B), C);
1030
1031 gtk_widget_show (A);
1032
1033 str = g_string_new ("");
1034
1035 add_gesture (A, "a1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_NONE);
1036 add_gesture (B, "b1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_CLAIMED);
1037
1038 gtk_widget_get_allocation (B, &allocation);
1039
1040 /* First touch down */
1041 point_update (&touch_state[0], A, allocation.x, allocation.y);
1042 point_press (&touch_state[0], A, 1);
1043
1044 g_assert_cmpstr (str->str, ==,
1045 "capture a1 (1), "
1046 "capture b1 (1), "
1047 "b1 state claimed (1)");
1048
1049 /* Second touch down */
1050 g_string_erase (str, 0, str->len);
1051 point_update (&touch_state[1], A, allocation.x, allocation.y);
1052 point_press (&touch_state[1], A, 1);
1053
1054 g_assert_cmpstr (str->str, ==,
1055 "a1 state denied (2), "
1056 "b1 state denied (2)");
1057
1058 g_string_free (str, TRUE);
1059
1060 gtk_window_destroy (A);
1061 }
1062
1063 static void
test_multitouch_activation(void)1064 test_multitouch_activation (void)
1065 {
1066 GtkWidget *A, *B, *C;
1067 GString *str;
1068 GtkAllocation allocation;
1069
1070 A = gtk_window_new ();
1071 gtk_widget_set_name (A, "A");
1072 B = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1073 gtk_widget_set_name (B, "B");
1074 C = gtk_image_new ();
1075 gtk_widget_set_hexpand (C, TRUE);
1076 gtk_widget_set_vexpand (C, TRUE);
1077 gtk_widget_set_name (C, "C");
1078
1079 gtk_box_append (GTK_BOX (A), B);
1080 gtk_box_append (GTK_BOX (B), C);
1081
1082 gtk_widget_show (A);
1083
1084 str = g_string_new ("");
1085
1086 add_mt_gesture (C, "c1", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_CLAIMED);
1087 gtk_widget_get_allocation (B, &allocation);
1088
1089 /* First touch down */
1090 point_update (&touch_state[0], A, allocation.x, allocation.y);
1091 point_press (&touch_state[0], A, 1);
1092
1093 g_assert_cmpstr (str->str, ==, "");
1094
1095 /* Second touch down */
1096 point_update (&touch_state[1], A, allocation.x, allocation.y);
1097 point_press (&touch_state[1], A, 1);
1098
1099 g_assert_cmpstr (str->str, ==,
1100 "c1 began, "
1101 "c1 state claimed (2), "
1102 "c1 state claimed (1)");
1103
1104 /* First touch up */
1105 g_string_erase (str, 0, str->len);
1106 point_release (&touch_state[0], 1);
1107
1108 g_assert_cmpstr (str->str, ==,
1109 "c1 ended");
1110
1111 /* A third touch down triggering again action */
1112 g_string_erase (str, 0, str->len);
1113 point_update (&touch_state[2], A, allocation.x, allocation.y);
1114 point_press (&touch_state[2], A, 1);
1115
1116 g_assert_cmpstr (str->str, ==,
1117 "c1 began, "
1118 "c1 state claimed (3)");
1119
1120 /* One touch up, gesture is finished again */
1121 g_string_erase (str, 0, str->len);
1122 point_release (&touch_state[2], 1);
1123
1124 g_assert_cmpstr (str->str, ==,
1125 "c1 ended");
1126
1127 /* Another touch up, gesture remains inactive */
1128 g_string_erase (str, 0, str->len);
1129 point_release (&touch_state[1], 1);
1130
1131 g_assert_cmpstr (str->str, ==, "");
1132
1133 g_string_free (str, TRUE);
1134
1135 gtk_window_destroy (A);
1136 }
1137
1138 static void
test_multitouch_interaction(void)1139 test_multitouch_interaction (void)
1140 {
1141 GtkWidget *A, *B, *C;
1142 GtkGesture *g;
1143 GString *str;
1144 GtkAllocation allocation;
1145
1146 A = gtk_window_new ();
1147 gtk_widget_set_name (A, "A");
1148 B = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1149 gtk_widget_set_name (B, "B");
1150 C = gtk_image_new ();
1151 gtk_widget_set_hexpand (C, TRUE);
1152 gtk_widget_set_vexpand (C, TRUE);
1153 gtk_widget_set_name (C, "C");
1154
1155 gtk_box_append (GTK_BOX (A), B);
1156 gtk_box_append (GTK_BOX (B), C);
1157
1158 gtk_widget_show (A);
1159
1160 str = g_string_new ("");
1161
1162 g = add_gesture (A, "a1", GTK_PHASE_CAPTURE, str, GTK_EVENT_SEQUENCE_CLAIMED);
1163 add_mt_gesture (C, "c1", GTK_PHASE_BUBBLE, str, GTK_EVENT_SEQUENCE_CLAIMED);
1164 gtk_widget_get_allocation (B, &allocation);
1165
1166 /* First touch down, a1 claims the sequence */
1167 point_update (&touch_state[0], A, allocation.x, allocation.y);
1168 point_press (&touch_state[0], A, 1);
1169
1170 g_assert_cmpstr (str->str, ==,
1171 "capture a1 (1), "
1172 "a1 state claimed (1)");
1173
1174 /* Second touch down, a1 denies and c1 takes over */
1175 g_string_erase (str, 0, str->len);
1176 point_update (&touch_state[1], A, allocation.x, allocation.y);
1177 point_press (&touch_state[1], A, 1);
1178
1179 /* Denying sequences in touch-excess situation is a responsibility of the caller */
1180 gtk_gesture_set_state (g, GTK_EVENT_SEQUENCE_DENIED);
1181
1182 g_assert_cmpstr (str->str, ==,
1183 "a1 state denied (2), "
1184 "c1 began, "
1185 "c1 state claimed (1), "
1186 "c1 state claimed (2), "
1187 "a1 state denied (1)");
1188
1189 /* Move first point, only c1 should update */
1190 g_string_erase (str, 0, str->len);
1191 point_update (&touch_state[0], A, allocation.x, allocation.y);
1192
1193 g_assert_cmpstr (str->str, ==,
1194 "c1 updated");
1195
1196 /* First touch up */
1197 g_string_erase (str, 0, str->len);
1198 point_release (&touch_state[0], 1);
1199
1200 g_assert_cmpstr (str->str, ==,
1201 "c1 ended");
1202
1203 /* A third touch down triggering again action on c1 */
1204 g_string_erase (str, 0, str->len);
1205 point_update (&touch_state[2], A, allocation.x, allocation.y);
1206 point_press (&touch_state[2], A, 1);
1207
1208 g_assert_cmpstr (str->str, ==,
1209 "a1 state denied (3), "
1210 "c1 began, "
1211 "c1 state claimed (3)");
1212
1213 /* One touch up, gesture is finished again */
1214 g_string_erase (str, 0, str->len);
1215 point_release (&touch_state[2], 1);
1216
1217 g_assert_cmpstr (str->str, ==,
1218 "c1 ended");
1219
1220 /* Another touch up, gesture remains inactive */
1221 g_string_erase (str, 0, str->len);
1222 point_release (&touch_state[1], 1);
1223
1224 g_assert_cmpstr (str->str, ==, "");
1225
1226 g_string_free (str, TRUE);
1227
1228 gtk_window_destroy (A);
1229 }
1230
1231 int
main(int argc,char * argv[])1232 main (int argc, char *argv[])
1233 {
1234 gtk_test_init (&argc, &argv);
1235
1236 g_test_add_func ("/gestures/propagation/phases", test_phases);
1237 g_test_add_func ("/gestures/propagation/mixed", test_mixed);
1238 g_test_add_func ("/gestures/propagation/early-exit", test_early_exit);
1239 g_test_add_func ("/gestures/claim/capture", test_claim_capture);
1240 g_test_add_func ("/gestures/claim/target", test_claim_target);
1241 g_test_add_func ("/gestures/claim/bubble", test_claim_bubble);
1242 g_test_add_func ("/gestures/claim/early-capture", test_early_claim_capture);
1243 g_test_add_func ("/gestures/claim/late-capture", test_late_claim_capture);
1244 g_test_add_func ("/gestures/group", test_group);
1245 g_test_add_func ("/gestures/grabs/gestures-outside-grab", test_gestures_outside_grab);
1246 g_test_add_func ("/gestures/grabs/gestures-inside-grab", test_gestures_inside_grab);
1247 g_test_add_func ("/gestures/multitouch/gesture-single", test_multitouch_on_single);
1248 g_test_add_func ("/gestures/multitouch/multitouch-activation", test_multitouch_activation);
1249 g_test_add_func ("/gestures/multitouch/interaction", test_multitouch_interaction);
1250
1251 return g_test_run ();
1252 }
1253