Flutter Linux Embedder
fl_scrolling_manager.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 #include "flutter/shell/platform/embedder/embedder.h"
8 
9 static constexpr int kMicrosecondsPerMillisecond = 1000;
10 
12  GObject parent_instance;
13 
14  GWeakRef engine;
15 
16  FlutterViewId view_id;
17 
18  gdouble last_x;
19  gdouble last_y;
20 
21  gboolean pan_started;
22  gdouble pan_x;
23  gdouble pan_y;
24 
25  gboolean zoom_started;
26  gboolean rotate_started;
27  gdouble scale;
28  gdouble rotation;
29 };
30 
31 G_DEFINE_TYPE(FlScrollingManager, fl_scrolling_manager, G_TYPE_OBJECT);
32 
33 static void fl_scrolling_manager_dispose(GObject* object) {
34  FlScrollingManager* self = FL_SCROLLING_MANAGER(object);
35 
36  g_weak_ref_clear(&self->engine);
37 
38  G_OBJECT_CLASS(fl_scrolling_manager_parent_class)->dispose(object);
39 }
40 
41 static void fl_scrolling_manager_class_init(FlScrollingManagerClass* klass) {
42  G_OBJECT_CLASS(klass)->dispose = fl_scrolling_manager_dispose;
43 }
44 
45 static void fl_scrolling_manager_init(FlScrollingManager* self) {}
46 
47 FlScrollingManager* fl_scrolling_manager_new(FlEngine* engine,
48  FlutterViewId view_id) {
49  g_return_val_if_fail(FL_IS_ENGINE(engine), nullptr);
50 
51  FlScrollingManager* self = FL_SCROLLING_MANAGER(
52  g_object_new(fl_scrolling_manager_get_type(), nullptr));
53 
54  g_weak_ref_init(&self->engine, engine);
55  self->view_id = view_id;
56  self->pan_started = FALSE;
57  self->zoom_started = FALSE;
58  self->rotate_started = FALSE;
59 
60  return self;
61 }
62 
63 void fl_scrolling_manager_set_last_mouse_position(FlScrollingManager* self,
64  gdouble x,
65  gdouble y) {
66  g_return_if_fail(FL_IS_SCROLLING_MANAGER(self));
67  self->last_x = x;
68  self->last_y = y;
69 }
70 
71 void fl_scrolling_manager_handle_scroll_event(FlScrollingManager* self,
72  GdkEventScroll* scroll_event,
73  gint scale_factor) {
74  g_return_if_fail(FL_IS_SCROLLING_MANAGER(self));
75 
76  g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
77  if (engine == nullptr) {
78  return;
79  }
80 
81  GdkEvent* event = reinterpret_cast<GdkEvent*>(scroll_event);
82 
83  guint event_time = gdk_event_get_time(event);
84  gdouble event_x = 0.0, event_y = 0.0;
85  gdk_event_get_coords(event, &event_x, &event_y);
86  gdouble scroll_delta_x = 0.0, scroll_delta_y = 0.0;
87  GdkScrollDirection event_direction = GDK_SCROLL_SMOOTH;
88  if (gdk_event_get_scroll_direction(event, &event_direction)) {
89  if (event_direction == GDK_SCROLL_UP) {
90  scroll_delta_x = 0;
91  scroll_delta_y = -1;
92  } else if (event_direction == GDK_SCROLL_DOWN) {
93  scroll_delta_x = 0;
94  scroll_delta_y = 1;
95  } else if (event_direction == GDK_SCROLL_LEFT) {
96  scroll_delta_x = -1;
97  scroll_delta_y = 0;
98  } else if (event_direction == GDK_SCROLL_RIGHT) {
99  scroll_delta_x = 1;
100  scroll_delta_y = 0;
101  }
102  } else {
103  gdk_event_get_scroll_deltas(event, &scroll_delta_x, &scroll_delta_y);
104  }
105 
106  // The multiplier is taken from the Chromium source
107  // (ui/events/x/events_x_utils.cc).
108  const int kScrollOffsetMultiplier = 53;
109  scroll_delta_x *= kScrollOffsetMultiplier * scale_factor;
110  scroll_delta_y *= kScrollOffsetMultiplier * scale_factor;
111 
112  GdkDevice* device = gdk_event_get_source_device(event);
113  if (device != nullptr &&
114  gdk_device_get_source(device) == GDK_SOURCE_TOUCHPAD) {
115  scroll_delta_x *= -1;
116  scroll_delta_y *= -1;
117  if (gdk_event_is_scroll_stop_event(event)) {
119  engine, self->view_id, event_time * kMicrosecondsPerMillisecond,
120  event_x * scale_factor, event_y * scale_factor, kPanZoomEnd,
121  self->pan_x, self->pan_y, 0, 0);
122  self->pan_started = FALSE;
123  } else {
124  if (!self->pan_started) {
125  self->pan_x = 0;
126  self->pan_y = 0;
128  engine, self->view_id, event_time * kMicrosecondsPerMillisecond,
129  event_x * scale_factor, event_y * scale_factor, kPanZoomStart, 0, 0,
130  0, 0);
131  self->pan_started = TRUE;
132  }
133  self->pan_x += scroll_delta_x;
134  self->pan_y += scroll_delta_y;
136  engine, self->view_id, event_time * kMicrosecondsPerMillisecond,
137  event_x * scale_factor, event_y * scale_factor, kPanZoomUpdate,
138  self->pan_x, self->pan_y, 1, 0);
139  }
140  } else {
141  self->last_x = event_x * scale_factor;
142  self->last_y = event_y * scale_factor;
144  engine, self->view_id,
145  FlutterPointerPhase::kMove /* arbitrary value, phase will be ignored as
146  this is a discrete scroll event */
147  ,
148  event_time * kMicrosecondsPerMillisecond, event_x * scale_factor,
149  event_y * scale_factor, kFlutterPointerDeviceKindMouse, scroll_delta_x,
150  scroll_delta_y, 0);
151  }
152 }
153 
154 void fl_scrolling_manager_handle_rotation_begin(FlScrollingManager* self) {
155  g_return_if_fail(FL_IS_SCROLLING_MANAGER(self));
156 
157  g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
158  if (engine == nullptr) {
159  return;
160  }
161 
162  self->rotate_started = TRUE;
163  if (!self->zoom_started) {
164  self->scale = 1;
165  self->rotation = 0;
167  engine, self->view_id, g_get_real_time(), self->last_x, self->last_y,
168  kPanZoomStart, 0, 0, 0, 0);
169  }
170 }
171 
172 void fl_scrolling_manager_handle_rotation_update(FlScrollingManager* self,
173  gdouble rotation) {
174  g_return_if_fail(FL_IS_SCROLLING_MANAGER(self));
175 
176  g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
177  if (engine == nullptr) {
178  return;
179  }
180 
181  self->rotation = rotation;
183  engine, self->view_id, g_get_real_time(), self->last_x, self->last_y,
184  kPanZoomUpdate, 0, 0, self->scale, self->rotation);
185 }
186 
187 void fl_scrolling_manager_handle_rotation_end(FlScrollingManager* self) {
188  g_return_if_fail(FL_IS_SCROLLING_MANAGER(self));
189 
190  g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
191  if (engine == nullptr) {
192  return;
193  }
194 
195  self->rotate_started = FALSE;
196  if (!self->zoom_started) {
198  engine, self->view_id, g_get_real_time(), self->last_x, self->last_y,
199  kPanZoomEnd, 0, 0, 0, 0);
200  }
201 }
202 
203 void fl_scrolling_manager_handle_zoom_begin(FlScrollingManager* self) {
204  g_return_if_fail(FL_IS_SCROLLING_MANAGER(self));
205 
206  g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
207  if (engine == nullptr) {
208  return;
209  }
210 
211  self->zoom_started = TRUE;
212  if (!self->rotate_started) {
213  self->scale = 1;
214  self->rotation = 0;
216  engine, self->view_id, g_get_real_time(), self->last_x, self->last_y,
217  kPanZoomStart, 0, 0, 0, 0);
218  }
219 }
220 
221 void fl_scrolling_manager_handle_zoom_update(FlScrollingManager* self,
222  gdouble scale) {
223  g_return_if_fail(FL_IS_SCROLLING_MANAGER(self));
224 
225  g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
226  if (engine == nullptr) {
227  return;
228  }
229 
230  self->scale = scale;
232  engine, self->view_id, g_get_real_time(), self->last_x, self->last_y,
233  kPanZoomUpdate, 0, 0, self->scale, self->rotation);
234 }
235 
236 void fl_scrolling_manager_handle_zoom_end(FlScrollingManager* self) {
237  g_return_if_fail(FL_IS_SCROLLING_MANAGER(self));
238 
239  g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
240  if (engine == nullptr) {
241  return;
242  }
243 
244  self->zoom_started = FALSE;
245  if (!self->rotate_started) {
247  engine, self->view_id, g_get_real_time(), self->last_x, self->last_y,
248  kPanZoomEnd, 0, 0, 0, 0);
249  }
250 }
g_autoptr(FlEngine) engine
return TRUE
void fl_engine_send_mouse_pointer_event(FlEngine *self, FlutterViewId view_id, FlutterPointerPhase phase, size_t timestamp, double x, double y, FlutterPointerDeviceKind device_kind, double scroll_delta_x, double scroll_delta_y, int64_t buttons)
Definition: fl_engine.cc:1176
void fl_engine_send_pointer_pan_zoom_event(FlEngine *self, FlutterViewId view_id, size_t timestamp, double x, double y, FlutterPointerPhase phase, double pan_x, double pan_y, double scale, double rotation)
Definition: fl_engine.cc:1358
void fl_scrolling_manager_handle_rotation_begin(FlScrollingManager *self)
static void fl_scrolling_manager_class_init(FlScrollingManagerClass *klass)
G_DEFINE_TYPE(FlScrollingManager, fl_scrolling_manager, G_TYPE_OBJECT)
void fl_scrolling_manager_set_last_mouse_position(FlScrollingManager *self, gdouble x, gdouble y)
void fl_scrolling_manager_handle_rotation_end(FlScrollingManager *self)
void fl_scrolling_manager_handle_scroll_event(FlScrollingManager *self, GdkEventScroll *scroll_event, gint scale_factor)
FlScrollingManager * fl_scrolling_manager_new(FlEngine *engine, FlutterViewId view_id)
void fl_scrolling_manager_handle_zoom_update(FlScrollingManager *self, gdouble scale)
static constexpr int kMicrosecondsPerMillisecond
void fl_scrolling_manager_handle_rotation_update(FlScrollingManager *self, gdouble rotation)
static void fl_scrolling_manager_dispose(GObject *object)
void fl_scrolling_manager_handle_zoom_begin(FlScrollingManager *self)
void fl_scrolling_manager_handle_zoom_end(FlScrollingManager *self)
static void fl_scrolling_manager_init(FlScrollingManager *self)
G_BEGIN_DECLS FlutterViewId view_id