1/* Gestures
2 * #Keywords: GtkGesture
3 *
4 * Perform gestures on touchscreens and other input devices. This
5 * demo reacts to long presses and swipes from all devices, plus
6 * multi-touch rotate and zoom gestures.
7 */
8
9#include <gtk/gtk.h>
10
11static GtkGesture *rotate = NULL;
12static GtkGesture *zoom = NULL;
13static double swipe_x = 0;
14static double swipe_y = 0;
15static gboolean long_pressed = FALSE;
16
17static gboolean
18touchpad_swipe_gesture_begin (GtkGesture *gesture,
19 GdkEventSequence *sequence,
20 GtkWidget *widget)
21{
22 /* Disallow touchscreen events here */
23 if (sequence != NULL)
24 gtk_gesture_set_state (gesture, state: GTK_EVENT_SEQUENCE_DENIED);
25 return sequence == NULL;
26}
27
28static void
29swipe_gesture_swept (GtkGestureSwipe *gesture,
30 double velocity_x,
31 double velocity_y,
32 GtkWidget *widget)
33{
34 swipe_x = velocity_x / 10;
35 swipe_y = velocity_y / 10;
36 gtk_widget_queue_draw (widget);
37}
38
39static void
40long_press_gesture_pressed (GtkGestureLongPress *gesture,
41 double x,
42 double y,
43 GtkWidget *widget)
44{
45 long_pressed = TRUE;
46 gtk_widget_queue_draw (widget);
47}
48
49static void
50long_press_gesture_end (GtkGesture *gesture,
51 GdkEventSequence *sequence,
52 GtkWidget *widget)
53{
54 long_pressed = FALSE;
55 gtk_widget_queue_draw (widget);
56}
57
58static void
59rotation_angle_changed (GtkGestureRotate *gesture,
60 double angle,
61 double delta,
62 GtkWidget *widget)
63{
64 gtk_widget_queue_draw (widget);
65}
66
67static void
68zoom_scale_changed (GtkGestureZoom *gesture,
69 double scale,
70 GtkWidget *widget)
71{
72 gtk_widget_queue_draw (widget);
73}
74
75static void
76drawing_area_draw (GtkDrawingArea *area,
77 cairo_t *cr,
78 int width,
79 int height,
80 gpointer data)
81{
82 if (swipe_x != 0 || swipe_y != 0)
83 {
84 cairo_save (cr);
85 cairo_set_line_width (cr, width: 6);
86 cairo_move_to (cr, x: width / 2, y: height / 2);
87 cairo_rel_line_to (cr, dx: swipe_x, dy: swipe_y);
88 cairo_set_source_rgba (cr, red: 1, green: 0, blue: 0, alpha: 0.5);
89 cairo_stroke (cr);
90 cairo_restore (cr);
91 }
92
93 if (gtk_gesture_is_recognized (gesture: rotate) || gtk_gesture_is_recognized (gesture: zoom))
94 {
95 cairo_pattern_t *pat;
96 cairo_matrix_t matrix;
97 double angle, scale;
98 double x_center, y_center;
99
100 gtk_gesture_get_bounding_box_center (GTK_GESTURE (zoom), x: &x_center, y: &y_center);
101
102 cairo_get_matrix (cr, matrix: &matrix);
103 cairo_matrix_translate (matrix: &matrix, tx: x_center, ty: y_center);
104
105 cairo_save (cr);
106
107 angle = gtk_gesture_rotate_get_angle_delta (GTK_GESTURE_ROTATE (rotate));
108 cairo_matrix_rotate (matrix: &matrix, radians: angle);
109
110 scale = gtk_gesture_zoom_get_scale_delta (GTK_GESTURE_ZOOM (zoom));
111 cairo_matrix_scale (matrix: &matrix, sx: scale, sy: scale);
112
113 cairo_set_matrix (cr, matrix: &matrix);
114 cairo_rectangle (cr, x: -100, y: -100, width: 200, height: 200);
115
116 pat = cairo_pattern_create_linear (x0: -100, y0: 0, x1: 200, y1: 0);
117 cairo_pattern_add_color_stop_rgb (pattern: pat, offset: 0, red: 0, green: 0, blue: 1);
118 cairo_pattern_add_color_stop_rgb (pattern: pat, offset: 1, red: 1, green: 0, blue: 0);
119 cairo_set_source (cr, source: pat);
120 cairo_fill (cr);
121
122 cairo_restore (cr);
123
124 cairo_pattern_destroy (pattern: pat);
125 }
126
127 if (long_pressed)
128 {
129 cairo_save (cr);
130 cairo_arc (cr,
131 xc: width / 2, yc: height / 2,
132 radius: 50, angle1: 0, angle2: 2 * G_PI);
133
134 cairo_set_source_rgba (cr, red: 0, green: 1, blue: 0, alpha: 0.5);
135 cairo_stroke (cr);
136
137 cairo_restore (cr);
138 }
139}
140
141GtkWidget *
142do_gestures (GtkWidget *do_widget)
143{
144 static GtkWidget *window = NULL;
145 GtkWidget *drawing_area;
146 GtkGesture *gesture;
147
148 if (!window)
149 {
150 window = gtk_window_new ();
151 gtk_window_set_default_size (GTK_WINDOW (window), width: 400, height: 400);
152 gtk_window_set_title (GTK_WINDOW (window), title: "Gestures");
153 g_object_add_weak_pointer (G_OBJECT (window), weak_pointer_location: (gpointer *)&window);
154
155 drawing_area = gtk_drawing_area_new ();
156 gtk_window_set_child (GTK_WINDOW (window), child: drawing_area);
157
158 gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (drawing_area),
159 draw_func: drawing_area_draw,
160 NULL, NULL);
161
162 /* Swipe */
163 gesture = gtk_gesture_swipe_new ();
164 g_signal_connect (gesture, "swipe",
165 G_CALLBACK (swipe_gesture_swept), drawing_area);
166 gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (gesture),
167 phase: GTK_PHASE_BUBBLE);
168 gtk_widget_add_controller (widget: drawing_area, GTK_EVENT_CONTROLLER (gesture));
169
170 /* 3fg swipe for touchpads */
171 gesture = g_object_new (GTK_TYPE_GESTURE_SWIPE,
172 first_property_name: "n-points", 3,
173 NULL);
174 g_signal_connect (gesture, "begin",
175 G_CALLBACK (touchpad_swipe_gesture_begin), drawing_area);
176 g_signal_connect (gesture, "swipe",
177 G_CALLBACK (swipe_gesture_swept), drawing_area);
178 gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (gesture),
179 phase: GTK_PHASE_BUBBLE);
180 gtk_widget_add_controller (widget: drawing_area, GTK_EVENT_CONTROLLER (gesture));
181
182
183 /* Long press */
184 gesture = gtk_gesture_long_press_new ();
185 g_signal_connect (gesture, "pressed",
186 G_CALLBACK (long_press_gesture_pressed), drawing_area);
187 g_signal_connect (gesture, "end",
188 G_CALLBACK (long_press_gesture_end), drawing_area);
189 gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (gesture),
190 phase: GTK_PHASE_BUBBLE);
191 gtk_widget_add_controller (widget: drawing_area, GTK_EVENT_CONTROLLER (gesture));
192
193 /* Rotate */
194 rotate = gesture = gtk_gesture_rotate_new ();
195 g_signal_connect (gesture, "angle-changed",
196 G_CALLBACK (rotation_angle_changed), drawing_area);
197 gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (gesture),
198 phase: GTK_PHASE_BUBBLE);
199 gtk_widget_add_controller (widget: drawing_area, GTK_EVENT_CONTROLLER (gesture));
200
201 /* Zoom */
202 zoom = gesture = gtk_gesture_zoom_new ();
203 g_signal_connect (gesture, "scale-changed",
204 G_CALLBACK (zoom_scale_changed), drawing_area);
205 gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (gesture),
206 phase: GTK_PHASE_BUBBLE);
207 gtk_widget_add_controller (widget: drawing_area, GTK_EVENT_CONTROLLER (gesture));
208 }
209
210 if (!gtk_widget_get_visible (widget: window))
211 gtk_widget_show (widget: window);
212 else
213 gtk_window_destroy (GTK_WINDOW (window));
214
215 return window;
216}
217

source code of gtk/demos/gtk-demo/gestures.c