Flutter Linux Embedder
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 
6 
7 #include <cstring>
8 #include <vector>
9 
10 #include "gtest/gtest.h"
11 namespace {
12 typedef std::function<void(FlutterPointerPhase phase,
13  size_t timestamp,
14  double x,
15  double y,
16  double scroll_delta_x,
17  double scroll_delta_y,
18  int64_t buttons)>
19  MousePointerCallHandler;
20 typedef std::function<void(size_t timestamp,
21  double x,
22  double y,
23  FlutterPointerPhase phase,
24  double pan_x,
25  double pan_y,
26  double scale,
27  double rotation)>
28  PointerPanZoomCallHandler;
29 
30 typedef struct {
31  FlutterPointerPhase phase;
32  size_t timestamp;
33  double x;
34  double y;
35  double scroll_delta_x;
36  double scroll_delta_y;
37  int64_t buttons;
38 } MousePointerEventRecord;
39 
40 typedef struct {
41  size_t timestamp;
42  double x;
43  double y;
44  FlutterPointerPhase phase;
45  double pan_x;
46  double pan_y;
47  double scale;
48  double rotation;
49 } PointerPanZoomEventRecord;
50 
51 G_BEGIN_DECLS
52 
53 G_DECLARE_FINAL_TYPE(FlMockScrollingViewDelegate,
54  fl_mock_scrolling_view_delegate,
55  FL,
56  MOCK_SCROLLING_VIEW_DELEGATE,
57  GObject)
58 
59 G_END_DECLS
60 
61 /***** FlMockScrollingViewDelegate *****/
62 
63 struct _FlMockScrollingViewDelegate {
64  GObject parent_instance;
65 };
66 
67 struct FlMockScrollingViewDelegatePrivate {
68  MousePointerCallHandler mouse_handler;
69  PointerPanZoomCallHandler pan_zoom_handler;
70 };
71 
72 static void fl_mock_view_scroll_delegate_iface_init(
73  FlScrollingViewDelegateInterface* iface);
74 
76  FlMockScrollingViewDelegate,
77  fl_mock_scrolling_view_delegate,
78  G_TYPE_OBJECT,
79  G_IMPLEMENT_INTERFACE(fl_scrolling_view_delegate_get_type(),
80  fl_mock_view_scroll_delegate_iface_init);
81  G_ADD_PRIVATE(FlMockScrollingViewDelegate))
82 
84  static_cast<FlMockScrollingViewDelegatePrivate*>( \
85  fl_mock_scrolling_view_delegate_get_instance_private( \
86  FL_MOCK_SCROLLING_VIEW_DELEGATE(obj)))
87 
88 static void fl_mock_scrolling_view_delegate_init(
89  FlMockScrollingViewDelegate* self) {
90  FlMockScrollingViewDelegatePrivate* priv =
92 
93  new (priv) FlMockScrollingViewDelegatePrivate();
94 }
95 
96 static void fl_mock_scrolling_view_delegate_finalize(GObject* object) {
98  ->~FlMockScrollingViewDelegatePrivate();
99 }
100 
101 static void fl_mock_scrolling_view_delegate_dispose(GObject* object) {
102  G_OBJECT_CLASS(fl_mock_scrolling_view_delegate_parent_class)->dispose(object);
103 }
104 
105 static void fl_mock_scrolling_view_delegate_class_init(
106  FlMockScrollingViewDelegateClass* klass) {
107  G_OBJECT_CLASS(klass)->dispose = fl_mock_scrolling_view_delegate_dispose;
108  G_OBJECT_CLASS(klass)->finalize = fl_mock_scrolling_view_delegate_finalize;
109 }
110 
111 static void fl_mock_view_send_mouse_pointer_event(
112  FlScrollingViewDelegate* delegate,
113  FlutterPointerPhase phase,
114  size_t timestamp,
115  double x,
116  double y,
117  double scroll_delta_x,
118  double scroll_delta_y,
119  int64_t buttons) {
120  FlMockScrollingViewDelegatePrivate* priv =
122  priv->mouse_handler(phase, timestamp, x, y, scroll_delta_x, scroll_delta_y,
123  buttons);
124 }
125 
126 static void fl_mock_view_send_pointer_pan_zoom_event(
127  FlScrollingViewDelegate* delegate,
128  size_t timestamp,
129  double x,
130  double y,
131  FlutterPointerPhase phase,
132  double pan_x,
133  double pan_y,
134  double scale,
135  double rotation) {
136  FlMockScrollingViewDelegatePrivate* priv =
138  priv->pan_zoom_handler(timestamp, x, y, phase, pan_x, pan_y, scale, rotation);
139 }
140 
141 static void fl_mock_view_scroll_delegate_iface_init(
142  FlScrollingViewDelegateInterface* iface) {
143  iface->send_mouse_pointer_event = fl_mock_view_send_mouse_pointer_event;
144  iface->send_pointer_pan_zoom_event = fl_mock_view_send_pointer_pan_zoom_event;
145 }
146 
147 static FlMockScrollingViewDelegate* fl_mock_scrolling_view_delegate_new() {
148  FlMockScrollingViewDelegate* self = FL_MOCK_SCROLLING_VIEW_DELEGATE(
149  g_object_new(fl_mock_scrolling_view_delegate_get_type(), nullptr));
150 
151  // Added to stop compiler complaining about an unused function.
152  FL_IS_MOCK_SCROLLING_VIEW_DELEGATE(self);
153 
154  return self;
155 }
156 
157 static void fl_mock_scrolling_view_set_mouse_handler(
158  FlMockScrollingViewDelegate* self,
159  MousePointerCallHandler handler) {
160  FlMockScrollingViewDelegatePrivate* priv =
162 
163  priv->mouse_handler = std::move(handler);
164 }
165 
166 static void fl_mock_scrolling_view_set_pan_zoom_handler(
167  FlMockScrollingViewDelegate* self,
168  PointerPanZoomCallHandler handler) {
169  FlMockScrollingViewDelegatePrivate* priv =
171 
172  priv->pan_zoom_handler = std::move(handler);
173 }
174 
175 /***** End FlMockScrollingViewDelegate *****/
176 
177 class ScrollingTester {
178  public:
179  ScrollingTester() {
180  view_ = fl_mock_scrolling_view_delegate_new();
181  manager_ = fl_scrolling_manager_new(FL_SCROLLING_VIEW_DELEGATE(view_));
182  fl_mock_scrolling_view_set_mouse_handler(
183  view_,
184  [](FlutterPointerPhase phase, size_t timestamp, double x, double y,
185  double scroll_delta_x, double scroll_delta_y, int64_t buttons) {
186  // do nothing
187  });
188  fl_mock_scrolling_view_set_pan_zoom_handler(
189  view_,
190  [](size_t timestamp, double x, double y, FlutterPointerPhase phase,
191  double pan_x, double pan_y, double scale, double rotation) {
192  // do nothing
193  });
194  }
195 
196  ~ScrollingTester() {
197  g_clear_object(&view_);
198  g_clear_object(&manager_);
199  }
200 
201  FlScrollingManager* manager() { return manager_; }
202 
203  void recordMousePointerCallsTo(
204  std::vector<MousePointerEventRecord>& storage) {
205  fl_mock_scrolling_view_set_mouse_handler(
206  view_, [&storage](FlutterPointerPhase phase, size_t timestamp, double x,
207  double y, double scroll_delta_x,
208  double scroll_delta_y, int64_t buttons) {
209  storage.push_back(MousePointerEventRecord{
210  .phase = phase,
211  .timestamp = timestamp,
212  .x = x,
213  .y = y,
214  .scroll_delta_x = scroll_delta_x,
215  .scroll_delta_y = scroll_delta_y,
216  .buttons = buttons,
217  });
218  });
219  }
220 
221  void recordPointerPanZoomCallsTo(
222  std::vector<PointerPanZoomEventRecord>& storage) {
223  fl_mock_scrolling_view_set_pan_zoom_handler(
224  view_, [&storage](size_t timestamp, double x, double y,
225  FlutterPointerPhase phase, double pan_x, double pan_y,
226  double scale, double rotation) {
227  storage.push_back(PointerPanZoomEventRecord{
228  .timestamp = timestamp,
229  .x = x,
230  .y = y,
231  .phase = phase,
232  .pan_x = pan_x,
233  .pan_y = pan_y,
234  .scale = scale,
235  .rotation = rotation,
236  });
237  });
238  }
239 
240  private:
241  FlMockScrollingViewDelegate* view_;
242  FlScrollingManager* manager_;
243 };
244 
245 // Disgusting hack but could not find any way to create a GdkDevice
246 struct _FakeGdkDevice {
247  GObject parent_instance;
248  gchar* name;
249  GdkInputSource source;
250 };
251 GdkDevice* makeFakeDevice(GdkInputSource source) {
252  _FakeGdkDevice* device =
253  static_cast<_FakeGdkDevice*>(g_malloc0(sizeof(_FakeGdkDevice)));
254  device->source = source;
255  // Bully the type checker
256  (reinterpret_cast<GTypeInstance*>(device))->g_class =
257  static_cast<GTypeClass*>(g_malloc0(sizeof(GTypeClass)));
258  (reinterpret_cast<GTypeInstance*>(device))->g_class->g_type = GDK_TYPE_DEVICE;
259  return reinterpret_cast<GdkDevice*>(device);
260 }
261 
262 TEST(FlScrollingManagerTest, DiscreteDirectionional) {
263  ScrollingTester tester;
264  std::vector<MousePointerEventRecord> mouse_records;
265  std::vector<PointerPanZoomEventRecord> pan_zoom_records;
266  tester.recordMousePointerCallsTo(mouse_records);
267  tester.recordPointerPanZoomCallsTo(pan_zoom_records);
268  GdkDevice* mouse = makeFakeDevice(GDK_SOURCE_MOUSE);
269  GdkEventScroll* event =
270  reinterpret_cast<GdkEventScroll*>(gdk_event_new(GDK_SCROLL));
271  event->time = 1;
272  event->x = 4.0;
273  event->y = 8.0;
274  event->device = mouse;
275  event->direction = GDK_SCROLL_UP;
276  fl_scrolling_manager_handle_scroll_event(tester.manager(), event, 1.0);
277  EXPECT_EQ(pan_zoom_records.size(), 0u);
278  EXPECT_EQ(mouse_records.size(), 1u);
279  EXPECT_EQ(mouse_records[0].x, 4.0);
280  EXPECT_EQ(mouse_records[0].y, 8.0);
281  EXPECT_EQ(mouse_records[0].timestamp,
282  1000lu); // Milliseconds -> Microseconds
283  EXPECT_EQ(mouse_records[0].scroll_delta_x, 0);
284  EXPECT_EQ(mouse_records[0].scroll_delta_y, 53 * -1.0);
285  event->direction = GDK_SCROLL_DOWN;
286  fl_scrolling_manager_handle_scroll_event(tester.manager(), event, 1.0);
287  EXPECT_EQ(pan_zoom_records.size(), 0u);
288  EXPECT_EQ(mouse_records.size(), 2u);
289  EXPECT_EQ(mouse_records[1].x, 4.0);
290  EXPECT_EQ(mouse_records[1].y, 8.0);
291  EXPECT_EQ(mouse_records[1].timestamp,
292  1000lu); // Milliseconds -> Microseconds
293  EXPECT_EQ(mouse_records[1].scroll_delta_x, 0);
294  EXPECT_EQ(mouse_records[1].scroll_delta_y, 53 * 1.0);
295  event->direction = GDK_SCROLL_LEFT;
296  fl_scrolling_manager_handle_scroll_event(tester.manager(), event, 1.0);
297  EXPECT_EQ(pan_zoom_records.size(), 0u);
298  EXPECT_EQ(mouse_records.size(), 3u);
299  EXPECT_EQ(mouse_records[2].x, 4.0);
300  EXPECT_EQ(mouse_records[2].y, 8.0);
301  EXPECT_EQ(mouse_records[2].timestamp,
302  1000lu); // Milliseconds -> Microseconds
303  EXPECT_EQ(mouse_records[2].scroll_delta_x, 53 * -1.0);
304  EXPECT_EQ(mouse_records[2].scroll_delta_y, 0);
305  event->direction = GDK_SCROLL_RIGHT;
306  fl_scrolling_manager_handle_scroll_event(tester.manager(), event, 1.0);
307  EXPECT_EQ(pan_zoom_records.size(), 0u);
308  EXPECT_EQ(mouse_records.size(), 4u);
309  EXPECT_EQ(mouse_records[3].x, 4.0);
310  EXPECT_EQ(mouse_records[3].y, 8.0);
311  EXPECT_EQ(mouse_records[3].timestamp,
312  1000lu); // Milliseconds -> Microseconds
313  EXPECT_EQ(mouse_records[3].scroll_delta_x, 53 * 1.0);
314  EXPECT_EQ(mouse_records[3].scroll_delta_y, 0);
315 }
316 
317 TEST(FlScrollingManagerTest, DiscreteScrolling) {
318  ScrollingTester tester;
319  std::vector<MousePointerEventRecord> mouse_records;
320  std::vector<PointerPanZoomEventRecord> pan_zoom_records;
321  tester.recordMousePointerCallsTo(mouse_records);
322  tester.recordPointerPanZoomCallsTo(pan_zoom_records);
323  GdkDevice* mouse = makeFakeDevice(GDK_SOURCE_MOUSE);
324  GdkEventScroll* event =
325  reinterpret_cast<GdkEventScroll*>(gdk_event_new(GDK_SCROLL));
326  event->time = 1;
327  event->x = 4.0;
328  event->y = 8.0;
329  event->delta_x = 1.0;
330  event->delta_y = 2.0;
331  event->device = mouse;
332  event->direction = GDK_SCROLL_SMOOTH;
333  fl_scrolling_manager_handle_scroll_event(tester.manager(), event, 1.0);
334  EXPECT_EQ(pan_zoom_records.size(), 0u);
335  EXPECT_EQ(mouse_records.size(), 1u);
336  EXPECT_EQ(mouse_records[0].x, 4.0);
337  EXPECT_EQ(mouse_records[0].y, 8.0);
338  EXPECT_EQ(mouse_records[0].timestamp,
339  1000lu); // Milliseconds -> Microseconds
340  EXPECT_EQ(mouse_records[0].scroll_delta_x, 53 * 1.0);
341  EXPECT_EQ(mouse_records[0].scroll_delta_y, 53 * 2.0);
342 }
343 
344 TEST(FlScrollingManagerTest, Panning) {
345  ScrollingTester tester;
346  std::vector<MousePointerEventRecord> mouse_records;
347  std::vector<PointerPanZoomEventRecord> pan_zoom_records;
348  tester.recordMousePointerCallsTo(mouse_records);
349  tester.recordPointerPanZoomCallsTo(pan_zoom_records);
350  GdkDevice* touchpad = makeFakeDevice(GDK_SOURCE_TOUCHPAD);
351  GdkEventScroll* event =
352  reinterpret_cast<GdkEventScroll*>(gdk_event_new(GDK_SCROLL));
353  event->time = 1;
354  event->x = 4.0;
355  event->y = 8.0;
356  event->delta_x = 1.0;
357  event->delta_y = 2.0;
358  event->device = touchpad;
359  event->direction = GDK_SCROLL_SMOOTH;
360  fl_scrolling_manager_handle_scroll_event(tester.manager(), event, 1.0);
361  EXPECT_EQ(pan_zoom_records.size(), 2u);
362  EXPECT_EQ(mouse_records.size(), 0u);
363  EXPECT_EQ(pan_zoom_records[0].x, 4.0);
364  EXPECT_EQ(pan_zoom_records[0].y, 8.0);
365  EXPECT_EQ(pan_zoom_records[0].timestamp,
366  1000lu); // Milliseconds -> Microseconds
367  EXPECT_EQ(pan_zoom_records[0].phase, kPanZoomStart);
368  EXPECT_EQ(pan_zoom_records[1].x, 4.0);
369  EXPECT_EQ(pan_zoom_records[1].y, 8.0);
370  EXPECT_EQ(pan_zoom_records[1].timestamp,
371  1000lu); // Milliseconds -> Microseconds
372  EXPECT_EQ(pan_zoom_records[1].phase, kPanZoomUpdate);
373  EXPECT_EQ(pan_zoom_records[1].pan_x, 53 * -1.0); // directions get swapped
374  EXPECT_EQ(pan_zoom_records[1].pan_y, 53 * -2.0);
375  EXPECT_EQ(pan_zoom_records[1].scale, 1.0);
376  EXPECT_EQ(pan_zoom_records[1].rotation, 0.0);
377  fl_scrolling_manager_handle_scroll_event(tester.manager(), event, 1.0);
378  EXPECT_EQ(pan_zoom_records.size(), 3u);
379  EXPECT_EQ(mouse_records.size(), 0u);
380  EXPECT_EQ(pan_zoom_records[2].x, 4.0);
381  EXPECT_EQ(pan_zoom_records[2].y, 8.0);
382  EXPECT_EQ(pan_zoom_records[2].timestamp,
383  1000lu); // Milliseconds -> Microseconds
384  EXPECT_EQ(pan_zoom_records[2].phase, kPanZoomUpdate);
385  EXPECT_EQ(pan_zoom_records[2].pan_x, 53 * -2.0); // directions get swapped
386  EXPECT_EQ(pan_zoom_records[2].pan_y, 53 * -4.0);
387  EXPECT_EQ(pan_zoom_records[2].scale, 1.0);
388  EXPECT_EQ(pan_zoom_records[2].rotation, 0.0);
389  event->is_stop = true;
390  fl_scrolling_manager_handle_scroll_event(tester.manager(), event, 1.0);
391  EXPECT_EQ(pan_zoom_records.size(), 4u);
392  EXPECT_EQ(mouse_records.size(), 0u);
393  EXPECT_EQ(pan_zoom_records[3].x, 4.0);
394  EXPECT_EQ(pan_zoom_records[3].y, 8.0);
395  EXPECT_EQ(pan_zoom_records[3].timestamp,
396  1000lu); // Milliseconds -> Microseconds
397  EXPECT_EQ(pan_zoom_records[3].phase, kPanZoomEnd);
398 }
399 
400 TEST(FlScrollingManagerTest, Zooming) {
401  ScrollingTester tester;
402  std::vector<MousePointerEventRecord> mouse_records;
403  std::vector<PointerPanZoomEventRecord> pan_zoom_records;
404  tester.recordMousePointerCallsTo(mouse_records);
405  tester.recordPointerPanZoomCallsTo(pan_zoom_records);
406  size_t time_start = g_get_real_time();
407  fl_scrolling_manager_handle_zoom_begin(tester.manager());
408  EXPECT_EQ(pan_zoom_records.size(), 1u);
409  EXPECT_EQ(mouse_records.size(), 0u);
410  EXPECT_EQ(pan_zoom_records[0].x, 0);
411  EXPECT_EQ(pan_zoom_records[0].y, 0);
412  EXPECT_EQ(pan_zoom_records[0].phase, kPanZoomStart);
413  EXPECT_GE(pan_zoom_records[0].timestamp, time_start);
414  fl_scrolling_manager_handle_zoom_update(tester.manager(), 1.1);
415  EXPECT_EQ(pan_zoom_records.size(), 2u);
416  EXPECT_EQ(mouse_records.size(), 0u);
417  EXPECT_EQ(pan_zoom_records[1].x, 0);
418  EXPECT_EQ(pan_zoom_records[1].y, 0);
419  EXPECT_EQ(pan_zoom_records[1].phase, kPanZoomUpdate);
420  EXPECT_GE(pan_zoom_records[1].timestamp, pan_zoom_records[0].timestamp);
421  EXPECT_EQ(pan_zoom_records[1].pan_x, 0);
422  EXPECT_EQ(pan_zoom_records[1].pan_y, 0);
423  EXPECT_EQ(pan_zoom_records[1].scale, 1.1);
424  EXPECT_EQ(pan_zoom_records[1].rotation, 0);
425  fl_scrolling_manager_handle_zoom_end(tester.manager());
426  EXPECT_EQ(pan_zoom_records.size(), 3u);
427  EXPECT_EQ(mouse_records.size(), 0u);
428  EXPECT_EQ(pan_zoom_records[2].x, 0);
429  EXPECT_EQ(pan_zoom_records[2].y, 0);
430  EXPECT_EQ(pan_zoom_records[2].phase, kPanZoomEnd);
431  EXPECT_GE(pan_zoom_records[2].timestamp, pan_zoom_records[1].timestamp);
432 }
433 
434 TEST(FlScrollingManagerTest, Rotating) {
435  ScrollingTester tester;
436  std::vector<MousePointerEventRecord> mouse_records;
437  std::vector<PointerPanZoomEventRecord> pan_zoom_records;
438  tester.recordMousePointerCallsTo(mouse_records);
439  tester.recordPointerPanZoomCallsTo(pan_zoom_records);
440  size_t time_start = g_get_real_time();
442  EXPECT_EQ(pan_zoom_records.size(), 1u);
443  EXPECT_EQ(mouse_records.size(), 0u);
444  EXPECT_EQ(pan_zoom_records[0].x, 0);
445  EXPECT_EQ(pan_zoom_records[0].y, 0);
446  EXPECT_EQ(pan_zoom_records[0].phase, kPanZoomStart);
447  EXPECT_GE(pan_zoom_records[0].timestamp, time_start);
448  fl_scrolling_manager_handle_rotation_update(tester.manager(), 0.5);
449  EXPECT_EQ(pan_zoom_records.size(), 2u);
450  EXPECT_EQ(mouse_records.size(), 0u);
451  EXPECT_EQ(pan_zoom_records[1].x, 0);
452  EXPECT_EQ(pan_zoom_records[1].y, 0);
453  EXPECT_EQ(pan_zoom_records[1].phase, kPanZoomUpdate);
454  EXPECT_GE(pan_zoom_records[1].timestamp, pan_zoom_records[0].timestamp);
455  EXPECT_EQ(pan_zoom_records[1].pan_x, 0);
456  EXPECT_EQ(pan_zoom_records[1].pan_y, 0);
457  EXPECT_EQ(pan_zoom_records[1].scale, 1.0);
458  EXPECT_EQ(pan_zoom_records[1].rotation, 0.5);
460  EXPECT_EQ(pan_zoom_records.size(), 3u);
461  EXPECT_EQ(mouse_records.size(), 0u);
462  EXPECT_EQ(pan_zoom_records[2].x, 0);
463  EXPECT_EQ(pan_zoom_records[2].y, 0);
464  EXPECT_EQ(pan_zoom_records[2].phase, kPanZoomEnd);
465  EXPECT_GE(pan_zoom_records[2].timestamp, pan_zoom_records[1].timestamp);
466 }
467 
468 TEST(FlScrollingManagerTest, SynchronizedZoomingAndRotating) {
469  ScrollingTester tester;
470  std::vector<MousePointerEventRecord> mouse_records;
471  std::vector<PointerPanZoomEventRecord> pan_zoom_records;
472  tester.recordMousePointerCallsTo(mouse_records);
473  tester.recordPointerPanZoomCallsTo(pan_zoom_records);
474  size_t time_start = g_get_real_time();
475  fl_scrolling_manager_handle_zoom_begin(tester.manager());
476  EXPECT_EQ(pan_zoom_records.size(), 1u);
477  EXPECT_EQ(mouse_records.size(), 0u);
478  EXPECT_EQ(pan_zoom_records[0].x, 0);
479  EXPECT_EQ(pan_zoom_records[0].y, 0);
480  EXPECT_EQ(pan_zoom_records[0].phase, kPanZoomStart);
481  EXPECT_GE(pan_zoom_records[0].timestamp, time_start);
482  fl_scrolling_manager_handle_zoom_update(tester.manager(), 1.1);
483  EXPECT_EQ(pan_zoom_records.size(), 2u);
484  EXPECT_EQ(mouse_records.size(), 0u);
485  EXPECT_EQ(pan_zoom_records[1].x, 0);
486  EXPECT_EQ(pan_zoom_records[1].y, 0);
487  EXPECT_EQ(pan_zoom_records[1].phase, kPanZoomUpdate);
488  EXPECT_GE(pan_zoom_records[1].timestamp, pan_zoom_records[0].timestamp);
489  EXPECT_EQ(pan_zoom_records[1].pan_x, 0);
490  EXPECT_EQ(pan_zoom_records[1].pan_y, 0);
491  EXPECT_EQ(pan_zoom_records[1].scale, 1.1);
492  EXPECT_EQ(pan_zoom_records[1].rotation, 0);
494  EXPECT_EQ(pan_zoom_records.size(), 2u);
495  EXPECT_EQ(mouse_records.size(), 0u);
496  fl_scrolling_manager_handle_rotation_update(tester.manager(), 0.5);
497  EXPECT_EQ(pan_zoom_records.size(), 3u);
498  EXPECT_EQ(pan_zoom_records[2].x, 0);
499  EXPECT_EQ(pan_zoom_records[2].y, 0);
500  EXPECT_EQ(pan_zoom_records[2].phase, kPanZoomUpdate);
501  EXPECT_GE(pan_zoom_records[2].timestamp, pan_zoom_records[1].timestamp);
502  EXPECT_EQ(pan_zoom_records[2].pan_x, 0);
503  EXPECT_EQ(pan_zoom_records[2].pan_y, 0);
504  EXPECT_EQ(pan_zoom_records[2].scale, 1.1);
505  EXPECT_EQ(pan_zoom_records[2].rotation, 0.5);
506  fl_scrolling_manager_handle_zoom_end(tester.manager());
507  // End event should only be sent after both zoom and rotate complete.
508  EXPECT_EQ(pan_zoom_records.size(), 3u);
510  EXPECT_EQ(pan_zoom_records.size(), 4u);
511  EXPECT_EQ(mouse_records.size(), 0u);
512  EXPECT_EQ(pan_zoom_records[3].x, 0);
513  EXPECT_EQ(pan_zoom_records[3].y, 0);
514  EXPECT_EQ(pan_zoom_records[3].phase, kPanZoomEnd);
515  EXPECT_GE(pan_zoom_records[3].timestamp, pan_zoom_records[2].timestamp);
516 }
517 
518 // Make sure that zoom and rotate sequences which don't end at the same time
519 // don't cause any problems.
520 TEST(FlScrollingManagerTest, UnsynchronizedZoomingAndRotating) {
521  ScrollingTester tester;
522  std::vector<MousePointerEventRecord> mouse_records;
523  std::vector<PointerPanZoomEventRecord> pan_zoom_records;
524  tester.recordMousePointerCallsTo(mouse_records);
525  tester.recordPointerPanZoomCallsTo(pan_zoom_records);
526  size_t time_start = g_get_real_time();
527  fl_scrolling_manager_handle_zoom_begin(tester.manager());
528  EXPECT_EQ(pan_zoom_records.size(), 1u);
529  EXPECT_EQ(mouse_records.size(), 0u);
530  EXPECT_EQ(pan_zoom_records[0].x, 0);
531  EXPECT_EQ(pan_zoom_records[0].y, 0);
532  EXPECT_EQ(pan_zoom_records[0].phase, kPanZoomStart);
533  EXPECT_GE(pan_zoom_records[0].timestamp, time_start);
534  fl_scrolling_manager_handle_zoom_update(tester.manager(), 1.1);
535  EXPECT_EQ(pan_zoom_records.size(), 2u);
536  EXPECT_EQ(mouse_records.size(), 0u);
537  EXPECT_EQ(pan_zoom_records[1].x, 0);
538  EXPECT_EQ(pan_zoom_records[1].y, 0);
539  EXPECT_EQ(pan_zoom_records[1].phase, kPanZoomUpdate);
540  EXPECT_GE(pan_zoom_records[1].timestamp, pan_zoom_records[0].timestamp);
541  EXPECT_EQ(pan_zoom_records[1].pan_x, 0);
542  EXPECT_EQ(pan_zoom_records[1].pan_y, 0);
543  EXPECT_EQ(pan_zoom_records[1].scale, 1.1);
544  EXPECT_EQ(pan_zoom_records[1].rotation, 0);
546  EXPECT_EQ(pan_zoom_records.size(), 2u);
547  EXPECT_EQ(mouse_records.size(), 0u);
548  fl_scrolling_manager_handle_rotation_update(tester.manager(), 0.5);
549  EXPECT_EQ(pan_zoom_records.size(), 3u);
550  EXPECT_EQ(pan_zoom_records[2].x, 0);
551  EXPECT_EQ(pan_zoom_records[2].y, 0);
552  EXPECT_EQ(pan_zoom_records[2].phase, kPanZoomUpdate);
553  EXPECT_GE(pan_zoom_records[2].timestamp, pan_zoom_records[1].timestamp);
554  EXPECT_EQ(pan_zoom_records[2].pan_x, 0);
555  EXPECT_EQ(pan_zoom_records[2].pan_y, 0);
556  EXPECT_EQ(pan_zoom_records[2].scale, 1.1);
557  EXPECT_EQ(pan_zoom_records[2].rotation, 0.5);
558  fl_scrolling_manager_handle_zoom_end(tester.manager());
559  EXPECT_EQ(pan_zoom_records.size(), 3u);
560  fl_scrolling_manager_handle_rotation_update(tester.manager(), 1.0);
561  EXPECT_EQ(pan_zoom_records.size(), 4u);
562  EXPECT_EQ(mouse_records.size(), 0u);
563  EXPECT_EQ(pan_zoom_records[3].x, 0);
564  EXPECT_EQ(pan_zoom_records[3].y, 0);
565  EXPECT_EQ(pan_zoom_records[3].phase, kPanZoomUpdate);
566  EXPECT_GE(pan_zoom_records[3].timestamp, pan_zoom_records[2].timestamp);
567  EXPECT_EQ(pan_zoom_records[3].pan_x, 0);
568  EXPECT_EQ(pan_zoom_records[3].pan_y, 0);
569  EXPECT_EQ(pan_zoom_records[3].scale, 1.1);
570  EXPECT_EQ(pan_zoom_records[3].rotation, 1.0);
572  EXPECT_EQ(pan_zoom_records.size(), 5u);
573  EXPECT_EQ(mouse_records.size(), 0u);
574  EXPECT_EQ(pan_zoom_records[4].x, 0);
575  EXPECT_EQ(pan_zoom_records[4].y, 0);
576  EXPECT_EQ(pan_zoom_records[4].phase, kPanZoomEnd);
577  EXPECT_GE(pan_zoom_records[4].timestamp, pan_zoom_records[3].timestamp);
578 }
579 
580 } // namespace
event
FlKeyEvent * event
Definition: fl_key_channel_responder.cc:118
fl_scrolling_manager_handle_zoom_end
void fl_scrolling_manager_handle_zoom_end(FlScrollingManager *self)
Definition: fl_scrolling_manager.cc:207
FL_MOCK_SCROLLING_VIEW_DELEGATE_GET_PRIVATE
#define FL_MOCK_SCROLLING_VIEW_DELEGATE_GET_PRIVATE(obj)
fl_scrolling_manager_handle_scroll_event
void fl_scrolling_manager_handle_scroll_event(FlScrollingManager *self, GdkEventScroll *scroll_event, gint scale_factor)
Definition: fl_scrolling_manager.cc:74
priv
FlPixelBufferTexturePrivate * priv
Definition: fl_pixel_buffer_texture.cc:30
fl_scrolling_manager_new
FlScrollingManager * fl_scrolling_manager_new(FlScrollingViewDelegate *view_delegate)
Definition: fl_scrolling_manager.cc:47
fl_scrolling_manager.h
fl_scrolling_manager_handle_zoom_update
void fl_scrolling_manager_handle_zoom_update(FlScrollingManager *self, gdouble scale)
Definition: fl_scrolling_manager.cc:197
G_DECLARE_FINAL_TYPE
G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(FlAccessibleTextField, fl_accessible_text_field, FL, ACCESSIBLE_TEXT_FIELD, FlAccessibleNode)
fl_scrolling_manager_handle_rotation_update
void fl_scrolling_manager_handle_rotation_update(FlScrollingManager *self, gdouble rotation)
Definition: fl_scrolling_manager.cc:163
FL
FL
Definition: fl_binary_messenger.cc:27
fl_scrolling_manager_handle_rotation_end
void fl_scrolling_manager_handle_rotation_end(FlScrollingManager *self)
Definition: fl_scrolling_manager.cc:173
TEST
TEST(FlAccessibleNodeTest, BuildTree)
Definition: fl_accessible_node_test.cc:12
fl_scrolling_manager_handle_rotation_begin
void fl_scrolling_manager_handle_rotation_begin(FlScrollingManager *self)
Definition: fl_scrolling_manager.cc:150
fl_scrolling_manager_handle_zoom_begin
void fl_scrolling_manager_handle_zoom_begin(FlScrollingManager *self)
Definition: fl_scrolling_manager.cc:184
G_DEFINE_TYPE_WITH_CODE
G_DEFINE_TYPE_WITH_CODE(FlAccessibleNode, fl_accessible_node, ATK_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(ATK_TYPE_COMPONENT, fl_accessible_node_component_interface_init) G_IMPLEMENT_INTERFACE(ATK_TYPE_ACTION, fl_accessible_node_action_interface_init)) static gboolean flag_is_changed(FlutterSemanticsFlag old_flags