Flutter Engine
 
Loading...
Searching...
No Matches
pointer_data_packet_converter.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 <cmath>
8#include <cstring>
9
10#include "flutter/fml/logging.h"
11
12namespace flutter {
13
16
18
19std::unique_ptr<PointerDataPacket> PointerDataPacketConverter::Convert(
20 const PointerDataPacket& packet) {
21 std::vector<PointerData> converted_pointers;
22 // Converts each pointer data in the buffer and stores it in the
23 // converted_pointers.
24 for (size_t i = 0; i < packet.GetLength(); i++) {
25 PointerData pointer_data = packet.GetPointerData(i);
26 ConvertPointerData(pointer_data, converted_pointers);
27 }
28
29 // Writes converted_pointers into converted_packet.
30 auto converted_packet =
31 std::make_unique<flutter::PointerDataPacket>(converted_pointers.size());
32 size_t count = 0;
33 for (auto& converted_pointer : converted_pointers) {
34 converted_packet->SetPointerData(count++, converted_pointer);
35 }
36
37 return converted_packet;
38}
39
40void PointerDataPacketConverter::ConvertPointerData(
41 PointerData pointer_data,
42 std::vector<PointerData>& converted_pointers) {
43 // Ignores pointer events with an invalid view ID.
44 if (!delegate_.ViewExists(pointer_data.view_id)) {
45 return;
46 }
47 if (pointer_data.signal_kind == PointerData::SignalKind::kNone) {
48 switch (pointer_data.change) {
50 // Android's three finger gesture will send a cancel event
51 // to a non-existing pointer. Drops the cancel if pointer
52 // is not previously added.
53 // https://github.com/flutter/flutter/issues/20517
54 auto iter = states_.find(pointer_data.device);
55 if (iter != states_.end()) {
56 PointerState state = iter->second;
57 FML_DCHECK(state.is_down);
58 UpdatePointerIdentifier(pointer_data, state, false);
59
60 if (LocationNeedsUpdate(pointer_data, state)) {
61 // Synthesizes a move event if the location does not match.
62 PointerData synthesized_move_event = pointer_data;
63 synthesized_move_event.change = PointerData::Change::kMove;
64 synthesized_move_event.synthesized = 1;
65
66 UpdateDeltaAndState(synthesized_move_event, state);
67 converted_pointers.push_back(synthesized_move_event);
68 }
69
70 state.is_down = false;
71 states_[pointer_data.device] = state;
72 converted_pointers.push_back(pointer_data);
73 }
74 break;
75 }
77 auto iter = states_.find(pointer_data.device);
78 if (iter != states_.end()) {
79 // Synthesizes a remove event if the pointer was not previously
80 // removed.
81 PointerState state = iter->second;
82 PointerData synthesized_data = pointer_data;
83 synthesized_data.physical_x = state.physical_x;
84 synthesized_data.physical_y = state.physical_y;
85 synthesized_data.pan_x = state.pan_x;
86 synthesized_data.pan_y = state.pan_y;
87 synthesized_data.scale = state.scale;
88 synthesized_data.rotation = state.rotation;
89 synthesized_data.buttons = state.buttons;
90 synthesized_data.synthesized = 1;
91
92 // The framework expects an add event to always follow a remove event,
93 // and remove events with invalid views are ignored.
94 // To meet the framework's expectations, the view ID of the add event
95 // is used for the remove event if the old view has been destroyed.
96 if (delegate_.ViewExists(state.view_id)) {
97 synthesized_data.view_id = state.view_id;
98
99 if (state.is_down) {
100 // Synthesizes cancel event if the pointer is down.
101 PointerData synthesized_cancel_event = synthesized_data;
102 synthesized_cancel_event.change = PointerData::Change::kCancel;
103 UpdatePointerIdentifier(synthesized_cancel_event, state, false);
104
105 state.is_down = false;
106 converted_pointers.push_back(synthesized_cancel_event);
107 }
108 }
109
110 PointerData synthesized_remove_event = synthesized_data;
111 synthesized_remove_event.change = PointerData::Change::kRemove;
112
113 converted_pointers.push_back(synthesized_remove_event);
114 }
115
116 EnsurePointerState(pointer_data);
117 converted_pointers.push_back(pointer_data);
118 break;
119 }
121 // Makes sure we have an existing pointer
122 auto iter = states_.find(pointer_data.device);
123 FML_DCHECK(iter != states_.end());
124 PointerState state = iter->second;
125 if (state.view_id != pointer_data.view_id) {
126 // Ignores remove event if the pointer was previously added to a
127 // different view.
128 break;
129 }
130
131 if (state.is_down) {
132 // Synthesizes cancel event if the pointer is down.
133 PointerData synthesized_cancel_event = pointer_data;
134 synthesized_cancel_event.change = PointerData::Change::kCancel;
135 synthesized_cancel_event.synthesized = 1;
136 UpdatePointerIdentifier(synthesized_cancel_event, state, false);
137
138 state.is_down = false;
139 states_[synthesized_cancel_event.device] = state;
140 converted_pointers.push_back(synthesized_cancel_event);
141 }
142
143 if (LocationNeedsUpdate(pointer_data, state)) {
144 // Synthesizes a hover event if the location does not match.
145 PointerData synthesized_hover_event = pointer_data;
146 synthesized_hover_event.change = PointerData::Change::kHover;
147 synthesized_hover_event.synthesized = 1;
148
149 UpdateDeltaAndState(synthesized_hover_event, state);
150 converted_pointers.push_back(synthesized_hover_event);
151 }
152
153 states_.erase(pointer_data.device);
154 converted_pointers.push_back(pointer_data);
155 break;
156 }
158 auto iter = states_.find(pointer_data.device);
159 PointerState state;
160 if (iter == states_.end()) {
161 // Synthesizes add event if the pointer is not previously added.
162 PointerData synthesized_add_event = pointer_data;
163 synthesized_add_event.change = PointerData::Change::kAdd;
164 synthesized_add_event.synthesized = 1;
165 synthesized_add_event.buttons = 0;
166 state = EnsurePointerState(synthesized_add_event);
167 converted_pointers.push_back(synthesized_add_event);
168 } else {
169 state = iter->second;
170 }
171
172 FML_DCHECK(!state.is_down);
173 state.buttons = pointer_data.buttons;
174 if (LocationNeedsUpdate(pointer_data, state)) {
175 UpdateDeltaAndState(pointer_data, state);
176 converted_pointers.push_back(pointer_data);
177 }
178 break;
179 }
181 auto iter = states_.find(pointer_data.device);
182 PointerState state;
183 if (iter == states_.end()) {
184 // Synthesizes a add event if the pointer is not previously added.
185 PointerData synthesized_add_event = pointer_data;
186 synthesized_add_event.change = PointerData::Change::kAdd;
187 synthesized_add_event.synthesized = 1;
188 synthesized_add_event.buttons = 0;
189 state = EnsurePointerState(synthesized_add_event);
190 converted_pointers.push_back(synthesized_add_event);
191 } else {
192 state = iter->second;
193 }
194
195 FML_DCHECK(!state.is_down);
196 if (LocationNeedsUpdate(pointer_data, state)) {
197 // Synthesizes a hover event if the location does not match.
198 PointerData synthesized_hover_event = pointer_data;
199 synthesized_hover_event.change = PointerData::Change::kHover;
200 synthesized_hover_event.synthesized = 1;
201 synthesized_hover_event.buttons = 0;
202
203 UpdateDeltaAndState(synthesized_hover_event, state);
204 converted_pointers.push_back(synthesized_hover_event);
205 }
206
207 UpdatePointerIdentifier(pointer_data, state, true);
208 state.is_down = true;
209 state.buttons = pointer_data.buttons;
210 states_[pointer_data.device] = state;
211 converted_pointers.push_back(pointer_data);
212 break;
213 }
215 // Makes sure we have an existing pointer in down state
216 auto iter = states_.find(pointer_data.device);
217 FML_DCHECK(iter != states_.end());
218 PointerState state = iter->second;
219 FML_DCHECK(state.is_down);
220
221 UpdatePointerIdentifier(pointer_data, state, false);
222 UpdateDeltaAndState(pointer_data, state);
223 state.buttons = pointer_data.buttons;
224 converted_pointers.push_back(pointer_data);
225 break;
226 }
228 // Makes sure we have an existing pointer in down state
229 auto iter = states_.find(pointer_data.device);
230 FML_DCHECK(iter != states_.end());
231 PointerState state = iter->second;
232 FML_DCHECK(state.is_down);
233
234 UpdatePointerIdentifier(pointer_data, state, false);
235
236 if (LocationNeedsUpdate(pointer_data, state)) {
237 // Synthesizes a move event if the location does not match.
238 PointerData synthesized_move_event = pointer_data;
239 synthesized_move_event.change = PointerData::Change::kMove;
240 synthesized_move_event.buttons = state.buttons;
241 synthesized_move_event.synthesized = 1;
242
243 UpdateDeltaAndState(synthesized_move_event, state);
244 converted_pointers.push_back(synthesized_move_event);
245 }
246
247 state.is_down = false;
248 state.buttons = pointer_data.buttons;
249 states_[pointer_data.device] = state;
250 converted_pointers.push_back(pointer_data);
251 break;
252 }
254 // Makes sure we have an existing pointer
255 auto iter = states_.find(pointer_data.device);
256 PointerState state;
257 if (iter == states_.end()) {
258 // Synthesizes add event if the pointer is not previously added.
259 PointerData synthesized_add_event = pointer_data;
260 synthesized_add_event.change = PointerData::Change::kAdd;
261 synthesized_add_event.synthesized = 1;
262 synthesized_add_event.buttons = 0;
263 state = EnsurePointerState(synthesized_add_event);
264 converted_pointers.push_back(synthesized_add_event);
265 } else {
266 state = iter->second;
267 }
268 FML_DCHECK(!state.is_down);
269 FML_DCHECK(!state.is_pan_zoom_active);
270 if (LocationNeedsUpdate(pointer_data, state)) {
271 // Synthesizes a hover event if the location does not match.
272 PointerData synthesized_hover_event = pointer_data;
273 synthesized_hover_event.change = PointerData::Change::kHover;
274 synthesized_hover_event.synthesized = 1;
275 synthesized_hover_event.buttons = 0;
276
277 UpdateDeltaAndState(synthesized_hover_event, state);
278 converted_pointers.push_back(synthesized_hover_event);
279 }
280
281 UpdatePointerIdentifier(pointer_data, state, true);
282 state.is_pan_zoom_active = true;
283 state.pan_x = 0;
284 state.pan_y = 0;
285 state.scale = 1;
286 state.rotation = 0;
287 states_[pointer_data.device] = state;
288 converted_pointers.push_back(pointer_data);
289 break;
290 }
292 // Makes sure we have an existing pointer in pan_zoom_active state
293 auto iter = states_.find(pointer_data.device);
294 FML_DCHECK(iter != states_.end());
295 PointerState state = iter->second;
296 FML_DCHECK(!state.is_down);
297 FML_DCHECK(state.is_pan_zoom_active);
298
299 UpdatePointerIdentifier(pointer_data, state, false);
300 UpdateDeltaAndState(pointer_data, state);
301
302 converted_pointers.push_back(pointer_data);
303 break;
304 }
306 // Makes sure we have an existing pointer in pan_zoom_active state
307 auto iter = states_.find(pointer_data.device);
308 FML_DCHECK(iter != states_.end());
309 PointerState state = iter->second;
310 FML_DCHECK(state.is_pan_zoom_active);
311
312 UpdatePointerIdentifier(pointer_data, state, false);
313
314 if (LocationNeedsUpdate(pointer_data, state)) {
315 // Synthesizes an update event if the location does not match.
316 PointerData synthesized_move_event = pointer_data;
317 synthesized_move_event.change = PointerData::Change::kPanZoomUpdate;
318 synthesized_move_event.pan_x = state.pan_x;
319 synthesized_move_event.pan_y = state.pan_y;
320 synthesized_move_event.pan_delta_x = 0;
321 synthesized_move_event.pan_delta_y = 0;
322 synthesized_move_event.scale = state.scale;
323 synthesized_move_event.rotation = state.rotation;
324 synthesized_move_event.synthesized = 1;
325
326 UpdateDeltaAndState(synthesized_move_event, state);
327 converted_pointers.push_back(synthesized_move_event);
328 }
329
330 state.is_pan_zoom_active = false;
331 states_[pointer_data.device] = state;
332 converted_pointers.push_back(pointer_data);
333 break;
334 }
335 default: {
336 converted_pointers.push_back(pointer_data);
337 break;
338 }
339 }
340 } else {
341 switch (pointer_data.signal_kind) {
345 // Makes sure we have an existing pointer
346 auto iter = states_.find(pointer_data.device);
347 PointerState state;
348
349 if (iter == states_.end()) {
350 // Synthesizes a add event if the pointer is not previously added.
351 PointerData synthesized_add_event = pointer_data;
352 synthesized_add_event.signal_kind = PointerData::SignalKind::kNone;
353 synthesized_add_event.change = PointerData::Change::kAdd;
354 synthesized_add_event.synthesized = 1;
355 synthesized_add_event.buttons = 0;
356 state = EnsurePointerState(synthesized_add_event);
357 converted_pointers.push_back(synthesized_add_event);
358 } else {
359 state = iter->second;
360 }
361
362 if (LocationNeedsUpdate(pointer_data, state)) {
363 if (state.is_down) {
364 // Synthesizes a move event if the pointer is down.
365 PointerData synthesized_move_event = pointer_data;
366 synthesized_move_event.signal_kind = PointerData::SignalKind::kNone;
367 synthesized_move_event.change = PointerData::Change::kMove;
368 synthesized_move_event.buttons = state.buttons;
369 synthesized_move_event.synthesized = 1;
370
371 UpdateDeltaAndState(synthesized_move_event, state);
372 converted_pointers.push_back(synthesized_move_event);
373 } else {
374 // Synthesizes a hover event if the pointer is up.
375 PointerData synthesized_hover_event = pointer_data;
376 synthesized_hover_event.signal_kind =
378 synthesized_hover_event.change = PointerData::Change::kHover;
379 synthesized_hover_event.buttons = 0;
380 synthesized_hover_event.synthesized = 1;
381
382 UpdateDeltaAndState(synthesized_hover_event, state);
383 converted_pointers.push_back(synthesized_hover_event);
384 }
385 }
386
387 converted_pointers.push_back(pointer_data);
388 break;
389 }
390 default: {
391 // Ignores unknown signal kind.
392 break;
393 }
394 }
395 }
396}
397
398PointerState PointerDataPacketConverter::EnsurePointerState(
399 PointerData pointer_data) {
400 PointerState state;
401 state.pointer_identifier = 0;
402 state.is_down = false;
403 state.is_pan_zoom_active = false;
404 state.physical_x = pointer_data.physical_x;
405 state.physical_y = pointer_data.physical_y;
406 state.pan_x = 0;
407 state.pan_y = 0;
408 state.view_id = pointer_data.view_id;
409 states_[pointer_data.device] = state;
410 return state;
411}
412
413void PointerDataPacketConverter::UpdateDeltaAndState(PointerData& pointer_data,
414 PointerState& state) {
415 pointer_data.physical_delta_x = pointer_data.physical_x - state.physical_x;
416 pointer_data.physical_delta_y = pointer_data.physical_y - state.physical_y;
417 pointer_data.pan_delta_x = pointer_data.pan_x - state.pan_x;
418 pointer_data.pan_delta_y = pointer_data.pan_y - state.pan_y;
419 state.physical_x = pointer_data.physical_x;
420 state.physical_y = pointer_data.physical_y;
421 state.pan_x = pointer_data.pan_x;
422 state.pan_y = pointer_data.pan_y;
423 state.scale = pointer_data.scale;
424 state.rotation = pointer_data.rotation;
425 states_[pointer_data.device] = state;
426}
427
428bool PointerDataPacketConverter::LocationNeedsUpdate(
429 const PointerData pointer_data,
430 const PointerState state) {
431 return state.physical_x != pointer_data.physical_x ||
432 state.physical_y != pointer_data.physical_y;
433}
434
435void PointerDataPacketConverter::UpdatePointerIdentifier(
436 PointerData& pointer_data,
437 PointerState& state,
438 bool start_new_pointer) {
439 if (start_new_pointer) {
440 state.pointer_identifier = ++pointer_;
441 states_[pointer_data.device] = state;
442 }
443 pointer_data.pointer_identifier = state.pointer_identifier;
444}
445
446} // namespace flutter
virtual bool ViewExists(int64_t view_id) const =0
PointerDataPacketConverter(const Delegate &delegate)
Create a PointerDataPacketConverter.
std::unique_ptr< PointerDataPacket > Convert(const PointerDataPacket &packet)
Converts pointer data packet into a form that framework understands. The raw pointer data packet from...
PointerData GetPointerData(size_t i) const
MockDelegate delegate_
#define FML_DCHECK(condition)
Definition logging.h:122