Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
fl_scrolling_manager_test.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
8
9#include <gdk/gdkwayland.h>
10#include <cstring>
11#include <vector>
12
14#include "gtest/gtest.h"
15
17
18TEST_F(FlScrollingManagerTest, DiscreteDirectional) {
19 StartEngine();
20
21 std::vector<FlutterPointerEvent> pointer_events;
23 SendPointerEvent,
24 ([&pointer_events](auto engine, const FlutterPointerEvent* events,
25 size_t events_count) {
26 for (size_t i = 0; i < events_count; i++) {
27 pointer_events.push_back(events[i]);
28 }
29
30 return kSuccess;
31 }));
32
33 g_autoptr(FlScrollingManager) manager = fl_scrolling_manager_new(engine, 0);
34
35 GdkDevice* mouse =
36 GDK_DEVICE(g_object_new(gdk_wayland_device_get_type(), "input-source",
37 GDK_SOURCE_MOUSE, nullptr));
38 GdkEventScroll* event =
39 reinterpret_cast<GdkEventScroll*>(gdk_event_new(GDK_SCROLL));
40 event->time = 1;
41 event->x = 4.0;
42 event->y = 8.0;
43 event->device = mouse;
44 event->direction = GDK_SCROLL_UP;
46 EXPECT_EQ(pointer_events.size(), 1u);
47 EXPECT_EQ(pointer_events[0].x, 4.0);
48 EXPECT_EQ(pointer_events[0].y, 8.0);
49 EXPECT_EQ(pointer_events[0].device_kind, kFlutterPointerDeviceKindMouse);
50 EXPECT_EQ(pointer_events[0].timestamp,
51 1000lu); // Milliseconds -> Microseconds
52 EXPECT_EQ(pointer_events[0].scroll_delta_x, 0);
53 EXPECT_EQ(pointer_events[0].scroll_delta_y, 53 * -1.0);
54 event->direction = GDK_SCROLL_DOWN;
56 EXPECT_EQ(pointer_events.size(), 2u);
57 EXPECT_EQ(pointer_events[1].x, 4.0);
58 EXPECT_EQ(pointer_events[1].y, 8.0);
59 EXPECT_EQ(pointer_events[1].device_kind, kFlutterPointerDeviceKindMouse);
60 EXPECT_EQ(pointer_events[1].timestamp,
61 1000lu); // Milliseconds -> Microseconds
62 EXPECT_EQ(pointer_events[1].scroll_delta_x, 0);
63 EXPECT_EQ(pointer_events[1].scroll_delta_y, 53 * 1.0);
64 event->direction = GDK_SCROLL_LEFT;
66 EXPECT_EQ(pointer_events.size(), 3u);
67 EXPECT_EQ(pointer_events[2].x, 4.0);
68 EXPECT_EQ(pointer_events[2].y, 8.0);
69 EXPECT_EQ(pointer_events[2].device_kind, kFlutterPointerDeviceKindMouse);
70 EXPECT_EQ(pointer_events[2].timestamp,
71 1000lu); // Milliseconds -> Microseconds
72 EXPECT_EQ(pointer_events[2].scroll_delta_x, 53 * -1.0);
73 EXPECT_EQ(pointer_events[2].scroll_delta_y, 0);
74 event->direction = GDK_SCROLL_RIGHT;
76 EXPECT_EQ(pointer_events.size(), 4u);
77 EXPECT_EQ(pointer_events[3].x, 4.0);
78 EXPECT_EQ(pointer_events[3].y, 8.0);
79 EXPECT_EQ(pointer_events[3].device_kind, kFlutterPointerDeviceKindMouse);
80 EXPECT_EQ(pointer_events[3].timestamp,
81 1000lu); // Milliseconds -> Microseconds
82 EXPECT_EQ(pointer_events[3].scroll_delta_x, 53 * 1.0);
83 EXPECT_EQ(pointer_events[3].scroll_delta_y, 0);
84}
85
86TEST_F(FlScrollingManagerTest, DiscreteScrolling) {
87 StartEngine();
88
89 std::vector<FlutterPointerEvent> pointer_events;
91 SendPointerEvent,
92 ([&pointer_events](auto engine, const FlutterPointerEvent* events,
93 size_t events_count) {
94 for (size_t i = 0; i < events_count; i++) {
95 pointer_events.push_back(events[i]);
96 }
97
98 return kSuccess;
99 }));
100
101 g_autoptr(FlScrollingManager) manager = fl_scrolling_manager_new(engine, 0);
102
103 GdkDevice* mouse =
104 GDK_DEVICE(g_object_new(gdk_wayland_device_get_type(), "input-source",
105 GDK_SOURCE_MOUSE, nullptr));
106 GdkEventScroll* event =
107 reinterpret_cast<GdkEventScroll*>(gdk_event_new(GDK_SCROLL));
108 event->time = 1;
109 event->x = 4.0;
110 event->y = 8.0;
111 event->delta_x = 1.0;
112 event->delta_y = 2.0;
113 event->device = mouse;
114 event->direction = GDK_SCROLL_SMOOTH;
115 fl_scrolling_manager_handle_scroll_event(manager, event, 1.0);
116 EXPECT_EQ(pointer_events.size(), 1u);
117 EXPECT_EQ(pointer_events[0].x, 4.0);
118 EXPECT_EQ(pointer_events[0].y, 8.0);
119 EXPECT_EQ(pointer_events[0].device_kind, kFlutterPointerDeviceKindMouse);
120 EXPECT_EQ(pointer_events[0].timestamp,
121 1000lu); // Milliseconds -> Microseconds
122 EXPECT_EQ(pointer_events[0].scroll_delta_x, 53 * 1.0);
123 EXPECT_EQ(pointer_events[0].scroll_delta_y, 53 * 2.0);
124}
125
127 StartEngine();
128
129 std::vector<FlutterPointerEvent> pointer_events;
131 SendPointerEvent,
132 ([&pointer_events](auto engine, const FlutterPointerEvent* events,
133 size_t events_count) {
134 for (size_t i = 0; i < events_count; i++) {
135 pointer_events.push_back(events[i]);
136 }
137
138 return kSuccess;
139 }));
140
141 g_autoptr(FlScrollingManager) manager = fl_scrolling_manager_new(engine, 0);
142
143 GdkDevice* touchpad =
144 GDK_DEVICE(g_object_new(gdk_wayland_device_get_type(), "input-source",
145 GDK_SOURCE_TOUCHPAD, nullptr));
146 GdkEventScroll* event =
147 reinterpret_cast<GdkEventScroll*>(gdk_event_new(GDK_SCROLL));
148 event->time = 1;
149 event->x = 4.0;
150 event->y = 8.0;
151 event->delta_x = 1.0;
152 event->delta_y = 2.0;
153 event->device = touchpad;
154 event->direction = GDK_SCROLL_SMOOTH;
155 fl_scrolling_manager_handle_scroll_event(manager, event, 1.0);
156 EXPECT_EQ(pointer_events.size(), 2u);
157 EXPECT_EQ(pointer_events[0].x, 4.0);
158 EXPECT_EQ(pointer_events[0].y, 8.0);
159 EXPECT_EQ(pointer_events[0].timestamp,
160 1000lu); // Milliseconds -> Microseconds
161 EXPECT_EQ(pointer_events[0].phase, kPanZoomStart);
162 EXPECT_EQ(pointer_events[1].x, 4.0);
163 EXPECT_EQ(pointer_events[1].y, 8.0);
164 EXPECT_EQ(pointer_events[1].timestamp,
165 1000lu); // Milliseconds -> Microseconds
166 EXPECT_EQ(pointer_events[1].phase, kPanZoomUpdate);
167 EXPECT_EQ(pointer_events[1].pan_x, 53 * -1.0); // directions get swapped
168 EXPECT_EQ(pointer_events[1].pan_y, 53 * -2.0);
169 EXPECT_EQ(pointer_events[1].scale, 1.0);
170 EXPECT_EQ(pointer_events[1].rotation, 0.0);
171 fl_scrolling_manager_handle_scroll_event(manager, event, 1.0);
172 EXPECT_EQ(pointer_events.size(), 3u);
173 EXPECT_EQ(pointer_events[2].x, 4.0);
174 EXPECT_EQ(pointer_events[2].y, 8.0);
175 EXPECT_EQ(pointer_events[2].timestamp,
176 1000lu); // Milliseconds -> Microseconds
177 EXPECT_EQ(pointer_events[2].phase, kPanZoomUpdate);
178 EXPECT_EQ(pointer_events[2].pan_x, 53 * -2.0); // directions get swapped
179 EXPECT_EQ(pointer_events[2].pan_y, 53 * -4.0);
180 EXPECT_EQ(pointer_events[2].scale, 1.0);
181 EXPECT_EQ(pointer_events[2].rotation, 0.0);
182 event->is_stop = true;
183 fl_scrolling_manager_handle_scroll_event(manager, event, 1.0);
184 EXPECT_EQ(pointer_events.size(), 4u);
185 EXPECT_EQ(pointer_events[3].x, 4.0);
186 EXPECT_EQ(pointer_events[3].y, 8.0);
187 EXPECT_EQ(pointer_events[3].timestamp,
188 1000lu); // Milliseconds -> Microseconds
189 EXPECT_EQ(pointer_events[3].phase, kPanZoomEnd);
190}
191
193 StartEngine();
194
195 std::vector<FlutterPointerEvent> pointer_events;
197 SendPointerEvent,
198 ([&pointer_events](auto engine, const FlutterPointerEvent* events,
199 size_t events_count) {
200 for (size_t i = 0; i < events_count; i++) {
201 pointer_events.push_back(events[i]);
202 }
203
204 return kSuccess;
205 }));
206
207 g_autoptr(FlScrollingManager) manager = fl_scrolling_manager_new(engine, 0);
208
209 size_t time_start = g_get_real_time();
211 EXPECT_EQ(pointer_events.size(), 1u);
212 EXPECT_EQ(pointer_events[0].x, 0);
213 EXPECT_EQ(pointer_events[0].y, 0);
214 EXPECT_EQ(pointer_events[0].phase, kPanZoomStart);
215 EXPECT_GE(pointer_events[0].timestamp, time_start);
217 EXPECT_EQ(pointer_events.size(), 2u);
218 EXPECT_EQ(pointer_events[1].x, 0);
219 EXPECT_EQ(pointer_events[1].y, 0);
220 EXPECT_EQ(pointer_events[1].phase, kPanZoomUpdate);
221 EXPECT_GE(pointer_events[1].timestamp, pointer_events[0].timestamp);
222 EXPECT_EQ(pointer_events[1].pan_x, 0);
223 EXPECT_EQ(pointer_events[1].pan_y, 0);
224 EXPECT_EQ(pointer_events[1].scale, 1.1);
225 EXPECT_EQ(pointer_events[1].rotation, 0);
227 EXPECT_EQ(pointer_events.size(), 3u);
228 EXPECT_EQ(pointer_events[2].x, 0);
229 EXPECT_EQ(pointer_events[2].y, 0);
230 EXPECT_EQ(pointer_events[2].phase, kPanZoomEnd);
231 EXPECT_GE(pointer_events[2].timestamp, pointer_events[1].timestamp);
232}
233
235 StartEngine();
236
237 std::vector<FlutterPointerEvent> pointer_events;
239 SendPointerEvent,
240 ([&pointer_events](auto engine, const FlutterPointerEvent* events,
241 size_t events_count) {
242 for (size_t i = 0; i < events_count; i++) {
243 pointer_events.push_back(events[i]);
244 }
245
246 return kSuccess;
247 }));
248
249 g_autoptr(FlScrollingManager) manager = fl_scrolling_manager_new(engine, 0);
250
251 size_t time_start = g_get_real_time();
253 EXPECT_EQ(pointer_events.size(), 1u);
254 EXPECT_EQ(pointer_events[0].x, 0);
255 EXPECT_EQ(pointer_events[0].y, 0);
256 EXPECT_EQ(pointer_events[0].phase, kPanZoomStart);
257 EXPECT_GE(pointer_events[0].timestamp, time_start);
259 EXPECT_EQ(pointer_events.size(), 2u);
260 EXPECT_EQ(pointer_events[1].x, 0);
261 EXPECT_EQ(pointer_events[1].y, 0);
262 EXPECT_EQ(pointer_events[1].phase, kPanZoomUpdate);
263 EXPECT_GE(pointer_events[1].timestamp, pointer_events[0].timestamp);
264 EXPECT_EQ(pointer_events[1].pan_x, 0);
265 EXPECT_EQ(pointer_events[1].pan_y, 0);
266 EXPECT_EQ(pointer_events[1].scale, 1.0);
267 EXPECT_EQ(pointer_events[1].rotation, 0.5);
269 EXPECT_EQ(pointer_events.size(), 3u);
270 EXPECT_EQ(pointer_events[2].x, 0);
271 EXPECT_EQ(pointer_events[2].y, 0);
272 EXPECT_EQ(pointer_events[2].phase, kPanZoomEnd);
273 EXPECT_GE(pointer_events[2].timestamp, pointer_events[1].timestamp);
274}
275
276TEST_F(FlScrollingManagerTest, SynchronizedZoomingAndRotating) {
277 StartEngine();
278
279 std::vector<FlutterPointerEvent> pointer_events;
281 SendPointerEvent,
282 ([&pointer_events](auto engine, const FlutterPointerEvent* events,
283 size_t events_count) {
284 for (size_t i = 0; i < events_count; i++) {
285 pointer_events.push_back(events[i]);
286 }
287
288 return kSuccess;
289 }));
290
291 g_autoptr(FlScrollingManager) manager = fl_scrolling_manager_new(engine, 0);
292
293 size_t time_start = g_get_real_time();
295 EXPECT_EQ(pointer_events.size(), 1u);
296 EXPECT_EQ(pointer_events[0].x, 0);
297 EXPECT_EQ(pointer_events[0].y, 0);
298 EXPECT_EQ(pointer_events[0].phase, kPanZoomStart);
299 EXPECT_GE(pointer_events[0].timestamp, time_start);
301 EXPECT_EQ(pointer_events.size(), 2u);
302 EXPECT_EQ(pointer_events[1].x, 0);
303 EXPECT_EQ(pointer_events[1].y, 0);
304 EXPECT_EQ(pointer_events[1].phase, kPanZoomUpdate);
305 EXPECT_GE(pointer_events[1].timestamp, pointer_events[0].timestamp);
306 EXPECT_EQ(pointer_events[1].pan_x, 0);
307 EXPECT_EQ(pointer_events[1].pan_y, 0);
308 EXPECT_EQ(pointer_events[1].scale, 1.1);
309 EXPECT_EQ(pointer_events[1].rotation, 0);
311 EXPECT_EQ(pointer_events.size(), 2u);
313 EXPECT_EQ(pointer_events.size(), 3u);
314 EXPECT_EQ(pointer_events[2].x, 0);
315 EXPECT_EQ(pointer_events[2].y, 0);
316 EXPECT_EQ(pointer_events[2].phase, kPanZoomUpdate);
317 EXPECT_GE(pointer_events[2].timestamp, pointer_events[1].timestamp);
318 EXPECT_EQ(pointer_events[2].pan_x, 0);
319 EXPECT_EQ(pointer_events[2].pan_y, 0);
320 EXPECT_EQ(pointer_events[2].scale, 1.1);
321 EXPECT_EQ(pointer_events[2].rotation, 0.5);
323 // End event should only be sent after both zoom and rotate complete.
324 EXPECT_EQ(pointer_events.size(), 3u);
326 EXPECT_EQ(pointer_events.size(), 4u);
327 EXPECT_EQ(pointer_events[3].x, 0);
328 EXPECT_EQ(pointer_events[3].y, 0);
329 EXPECT_EQ(pointer_events[3].phase, kPanZoomEnd);
330 EXPECT_GE(pointer_events[3].timestamp, pointer_events[2].timestamp);
331}
332
333// Make sure that zoom and rotate sequences which don't end at the same time
334// don't cause any problems.
335TEST_F(FlScrollingManagerTest, UnsynchronizedZoomingAndRotating) {
336 StartEngine();
337
338 std::vector<FlutterPointerEvent> pointer_events;
340 SendPointerEvent,
341 ([&pointer_events](auto engine, const FlutterPointerEvent* events,
342 size_t events_count) {
343 for (size_t i = 0; i < events_count; i++) {
344 pointer_events.push_back(events[i]);
345 }
346
347 return kSuccess;
348 }));
349
350 g_autoptr(FlScrollingManager) manager = fl_scrolling_manager_new(engine, 0);
351
352 size_t time_start = g_get_real_time();
354 EXPECT_EQ(pointer_events.size(), 1u);
355 EXPECT_EQ(pointer_events[0].x, 0);
356 EXPECT_EQ(pointer_events[0].y, 0);
357 EXPECT_EQ(pointer_events[0].phase, kPanZoomStart);
358 EXPECT_GE(pointer_events[0].timestamp, time_start);
360 EXPECT_EQ(pointer_events.size(), 2u);
361 EXPECT_EQ(pointer_events[1].x, 0);
362 EXPECT_EQ(pointer_events[1].y, 0);
363 EXPECT_EQ(pointer_events[1].phase, kPanZoomUpdate);
364 EXPECT_GE(pointer_events[1].timestamp, pointer_events[0].timestamp);
365 EXPECT_EQ(pointer_events[1].pan_x, 0);
366 EXPECT_EQ(pointer_events[1].pan_y, 0);
367 EXPECT_EQ(pointer_events[1].scale, 1.1);
368 EXPECT_EQ(pointer_events[1].rotation, 0);
370 EXPECT_EQ(pointer_events.size(), 2u);
372 EXPECT_EQ(pointer_events.size(), 3u);
373 EXPECT_EQ(pointer_events[2].x, 0);
374 EXPECT_EQ(pointer_events[2].y, 0);
375 EXPECT_EQ(pointer_events[2].phase, kPanZoomUpdate);
376 EXPECT_GE(pointer_events[2].timestamp, pointer_events[1].timestamp);
377 EXPECT_EQ(pointer_events[2].pan_x, 0);
378 EXPECT_EQ(pointer_events[2].pan_y, 0);
379 EXPECT_EQ(pointer_events[2].scale, 1.1);
380 EXPECT_EQ(pointer_events[2].rotation, 0.5);
382 EXPECT_EQ(pointer_events.size(), 3u);
384 EXPECT_EQ(pointer_events.size(), 4u);
385 EXPECT_EQ(pointer_events[3].x, 0);
386 EXPECT_EQ(pointer_events[3].y, 0);
387 EXPECT_EQ(pointer_events[3].phase, kPanZoomUpdate);
388 EXPECT_GE(pointer_events[3].timestamp, pointer_events[2].timestamp);
389 EXPECT_EQ(pointer_events[3].pan_x, 0);
390 EXPECT_EQ(pointer_events[3].pan_y, 0);
391 EXPECT_EQ(pointer_events[3].scale, 1.1);
392 EXPECT_EQ(pointer_events[3].rotation, 1.0);
394 EXPECT_EQ(pointer_events.size(), 5u);
395 EXPECT_EQ(pointer_events[4].x, 0);
396 EXPECT_EQ(pointer_events[4].y, 0);
397 EXPECT_EQ(pointer_events[4].phase, kPanZoomEnd);
398 EXPECT_GE(pointer_events[4].timestamp, pointer_events[3].timestamp);
399}
int32_t x
@ kPanZoomUpdate
The pan/zoom updated.
Definition embedder.h:1303
@ kPanZoomStart
A pan/zoom started on this pointer.
Definition embedder.h:1301
@ kPanZoomEnd
The pan/zoom ended.
Definition embedder.h:1305
@ kSuccess
Definition embedder.h:73
@ kFlutterPointerDeviceKindMouse
Definition embedder.h:1310
FlutterEngine engine
Definition main.cc:84
g_autoptr(FlEngine) engine
FlutterEngineProcTable * fl_engine_get_embedder_api(FlEngine *self)
Definition fl_engine.cc:920
void fl_scrolling_manager_handle_rotation_begin(FlScrollingManager *self)
void fl_scrolling_manager_handle_rotation_end(FlScrollingManager *self)
void fl_scrolling_manager_handle_scroll_event(FlScrollingManager *self, GdkEventScroll *scroll_event, gint scale_factor)
void fl_scrolling_manager_handle_zoom_update(FlScrollingManager *self, gdouble scale)
void fl_scrolling_manager_handle_rotation_update(FlScrollingManager *self, gdouble rotation)
FlScrollingManager * fl_scrolling_manager_new(FlEngine *engine, FlutterViewId view_id)
void fl_scrolling_manager_handle_zoom_begin(FlScrollingManager *self)
void fl_scrolling_manager_handle_zoom_end(FlScrollingManager *self)
TEST_F(FlScrollingManagerTest, DiscreteDirectional)
double y
#define MOCK_ENGINE_PROC(proc, mock_impl)
FlutterEngineSendPointerEventFnPtr SendPointerEvent
Definition embedder.h:3775