Flutter Engine
The Flutter Engine
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
5#include "flutter/lib/ui/window/pointer_data_packet_converter.h"
6
7#include <cmath>
8#include <cstring>
9
10#include "flutter/fml/logging.h"
11
12namespace flutter {
13
15 : delegate_(delegate) {}
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 FML_DCHECK(states_.find(pointer_data.device) == states_.end());
78 EnsurePointerState(pointer_data);
79 converted_pointers.push_back(pointer_data);
80 break;
81 }
83 // Makes sure we have an existing pointer
84 auto iter = states_.find(pointer_data.device);
85 FML_DCHECK(iter != states_.end());
86 PointerState state = iter->second;
87
88 if (state.is_down) {
89 // Synthesizes cancel event if the pointer is down.
90 PointerData synthesized_cancel_event = pointer_data;
91 synthesized_cancel_event.change = PointerData::Change::kCancel;
92 synthesized_cancel_event.synthesized = 1;
93 UpdatePointerIdentifier(synthesized_cancel_event, state, false);
94
95 state.is_down = false;
96 states_[synthesized_cancel_event.device] = state;
97 converted_pointers.push_back(synthesized_cancel_event);
98 }
99
100 if (LocationNeedsUpdate(pointer_data, state)) {
101 // Synthesizes a hover event if the location does not match.
102 PointerData synthesized_hover_event = pointer_data;
103 synthesized_hover_event.change = PointerData::Change::kHover;
104 synthesized_hover_event.synthesized = 1;
105
106 UpdateDeltaAndState(synthesized_hover_event, state);
107 converted_pointers.push_back(synthesized_hover_event);
108 }
109
110 states_.erase(pointer_data.device);
111 converted_pointers.push_back(pointer_data);
112 break;
113 }
115 auto iter = states_.find(pointer_data.device);
116 PointerState state;
117 if (iter == states_.end()) {
118 // Synthesizes add event if the pointer is not previously added.
119 PointerData synthesized_add_event = pointer_data;
120 synthesized_add_event.change = PointerData::Change::kAdd;
121 synthesized_add_event.synthesized = 1;
122 synthesized_add_event.buttons = 0;
123 state = EnsurePointerState(synthesized_add_event);
124 converted_pointers.push_back(synthesized_add_event);
125 } else {
126 state = iter->second;
127 }
128
129 FML_DCHECK(!state.is_down);
130 state.buttons = pointer_data.buttons;
131 if (LocationNeedsUpdate(pointer_data, state)) {
132 UpdateDeltaAndState(pointer_data, state);
133 converted_pointers.push_back(pointer_data);
134 }
135 break;
136 }
138 auto iter = states_.find(pointer_data.device);
139 PointerState state;
140 if (iter == states_.end()) {
141 // Synthesizes a add event if the pointer is not previously added.
142 PointerData synthesized_add_event = pointer_data;
143 synthesized_add_event.change = PointerData::Change::kAdd;
144 synthesized_add_event.synthesized = 1;
145 synthesized_add_event.buttons = 0;
146 state = EnsurePointerState(synthesized_add_event);
147 converted_pointers.push_back(synthesized_add_event);
148 } else {
149 state = iter->second;
150 }
151
152 FML_DCHECK(!state.is_down);
153 if (LocationNeedsUpdate(pointer_data, state)) {
154 // Synthesizes a hover event if the location does not match.
155 PointerData synthesized_hover_event = pointer_data;
156 synthesized_hover_event.change = PointerData::Change::kHover;
157 synthesized_hover_event.synthesized = 1;
158 synthesized_hover_event.buttons = 0;
159
160 UpdateDeltaAndState(synthesized_hover_event, state);
161 converted_pointers.push_back(synthesized_hover_event);
162 }
163
164 UpdatePointerIdentifier(pointer_data, state, true);
165 state.is_down = true;
166 state.buttons = pointer_data.buttons;
167 states_[pointer_data.device] = state;
168 converted_pointers.push_back(pointer_data);
169 break;
170 }
172 // Makes sure we have an existing pointer in down state
173 auto iter = states_.find(pointer_data.device);
174 FML_DCHECK(iter != states_.end());
175 PointerState state = iter->second;
176 FML_DCHECK(state.is_down);
177
178 UpdatePointerIdentifier(pointer_data, state, false);
179 UpdateDeltaAndState(pointer_data, state);
180 state.buttons = pointer_data.buttons;
181 converted_pointers.push_back(pointer_data);
182 break;
183 }
185 // Makes sure we have an existing pointer in down state
186 auto iter = states_.find(pointer_data.device);
187 FML_DCHECK(iter != states_.end());
188 PointerState state = iter->second;
189 FML_DCHECK(state.is_down);
190
191 UpdatePointerIdentifier(pointer_data, state, false);
192
193 if (LocationNeedsUpdate(pointer_data, state)) {
194 // Synthesizes a move event if the location does not match.
195 PointerData synthesized_move_event = pointer_data;
196 synthesized_move_event.change = PointerData::Change::kMove;
197 synthesized_move_event.buttons = state.buttons;
198 synthesized_move_event.synthesized = 1;
199
200 UpdateDeltaAndState(synthesized_move_event, state);
201 converted_pointers.push_back(synthesized_move_event);
202 }
203
204 state.is_down = false;
205 state.buttons = pointer_data.buttons;
206 states_[pointer_data.device] = state;
207 converted_pointers.push_back(pointer_data);
208 break;
209 }
211 // Makes sure we have an existing pointer
212 auto iter = states_.find(pointer_data.device);
213 PointerState state;
214 if (iter == states_.end()) {
215 // Synthesizes add event if the pointer is not previously added.
216 PointerData synthesized_add_event = pointer_data;
217 synthesized_add_event.change = PointerData::Change::kAdd;
218 synthesized_add_event.synthesized = 1;
219 synthesized_add_event.buttons = 0;
220 state = EnsurePointerState(synthesized_add_event);
221 converted_pointers.push_back(synthesized_add_event);
222 } else {
223 state = iter->second;
224 }
225 FML_DCHECK(!state.is_down);
226 FML_DCHECK(!state.is_pan_zoom_active);
227 if (LocationNeedsUpdate(pointer_data, state)) {
228 // Synthesizes a hover event if the location does not match.
229 PointerData synthesized_hover_event = pointer_data;
230 synthesized_hover_event.change = PointerData::Change::kHover;
231 synthesized_hover_event.synthesized = 1;
232 synthesized_hover_event.buttons = 0;
233
234 UpdateDeltaAndState(synthesized_hover_event, state);
235 converted_pointers.push_back(synthesized_hover_event);
236 }
237
238 UpdatePointerIdentifier(pointer_data, state, true);
239 state.is_pan_zoom_active = true;
240 state.pan_x = 0;
241 state.pan_y = 0;
242 state.scale = 1;
243 state.rotation = 0;
244 states_[pointer_data.device] = state;
245 converted_pointers.push_back(pointer_data);
246 break;
247 }
249 // Makes sure we have an existing pointer in pan_zoom_active state
250 auto iter = states_.find(pointer_data.device);
251 FML_DCHECK(iter != states_.end());
252 PointerState state = iter->second;
253 FML_DCHECK(!state.is_down);
254 FML_DCHECK(state.is_pan_zoom_active);
255
256 UpdatePointerIdentifier(pointer_data, state, false);
257 UpdateDeltaAndState(pointer_data, state);
258
259 converted_pointers.push_back(pointer_data);
260 break;
261 }
263 // Makes sure we have an existing pointer in pan_zoom_active state
264 auto iter = states_.find(pointer_data.device);
265 FML_DCHECK(iter != states_.end());
266 PointerState state = iter->second;
267 FML_DCHECK(state.is_pan_zoom_active);
268
269 UpdatePointerIdentifier(pointer_data, state, false);
270
271 if (LocationNeedsUpdate(pointer_data, state)) {
272 // Synthesizes an update event if the location does not match.
273 PointerData synthesized_move_event = pointer_data;
274 synthesized_move_event.change = PointerData::Change::kPanZoomUpdate;
275 synthesized_move_event.pan_x = state.pan_x;
276 synthesized_move_event.pan_y = state.pan_y;
277 synthesized_move_event.pan_delta_x = 0;
278 synthesized_move_event.pan_delta_y = 0;
279 synthesized_move_event.scale = state.scale;
280 synthesized_move_event.rotation = state.rotation;
281 synthesized_move_event.synthesized = 1;
282
283 UpdateDeltaAndState(synthesized_move_event, state);
284 converted_pointers.push_back(synthesized_move_event);
285 }
286
287 state.is_pan_zoom_active = false;
288 states_[pointer_data.device] = state;
289 converted_pointers.push_back(pointer_data);
290 break;
291 }
292 default: {
293 converted_pointers.push_back(pointer_data);
294 break;
295 }
296 }
297 } else {
298 switch (pointer_data.signal_kind) {
302 // Makes sure we have an existing pointer
303 auto iter = states_.find(pointer_data.device);
304 PointerState state;
305
306 if (iter == states_.end()) {
307 // Synthesizes a add event if the pointer is not previously added.
308 PointerData synthesized_add_event = pointer_data;
309 synthesized_add_event.signal_kind = PointerData::SignalKind::kNone;
310 synthesized_add_event.change = PointerData::Change::kAdd;
311 synthesized_add_event.synthesized = 1;
312 synthesized_add_event.buttons = 0;
313 state = EnsurePointerState(synthesized_add_event);
314 converted_pointers.push_back(synthesized_add_event);
315 } else {
316 state = iter->second;
317 }
318
319 if (LocationNeedsUpdate(pointer_data, state)) {
320 if (state.is_down) {
321 // Synthesizes a move event if the pointer is down.
322 PointerData synthesized_move_event = pointer_data;
323 synthesized_move_event.signal_kind = PointerData::SignalKind::kNone;
324 synthesized_move_event.change = PointerData::Change::kMove;
325 synthesized_move_event.buttons = state.buttons;
326 synthesized_move_event.synthesized = 1;
327
328 UpdateDeltaAndState(synthesized_move_event, state);
329 converted_pointers.push_back(synthesized_move_event);
330 } else {
331 // Synthesizes a hover event if the pointer is up.
332 PointerData synthesized_hover_event = pointer_data;
333 synthesized_hover_event.signal_kind =
335 synthesized_hover_event.change = PointerData::Change::kHover;
336 synthesized_hover_event.buttons = 0;
337 synthesized_hover_event.synthesized = 1;
338
339 UpdateDeltaAndState(synthesized_hover_event, state);
340 converted_pointers.push_back(synthesized_hover_event);
341 }
342 }
343
344 converted_pointers.push_back(pointer_data);
345 break;
346 }
347 default: {
348 // Ignores unknown signal kind.
349 break;
350 }
351 }
352 }
353}
354
355PointerState PointerDataPacketConverter::EnsurePointerState(
356 PointerData pointer_data) {
357 PointerState state;
358 state.pointer_identifier = 0;
359 state.is_down = false;
360 state.is_pan_zoom_active = false;
361 state.physical_x = pointer_data.physical_x;
362 state.physical_y = pointer_data.physical_y;
363 state.pan_x = 0;
364 state.pan_y = 0;
365 states_[pointer_data.device] = state;
366 return state;
367}
368
369void PointerDataPacketConverter::UpdateDeltaAndState(PointerData& pointer_data,
370 PointerState& state) {
371 pointer_data.physical_delta_x = pointer_data.physical_x - state.physical_x;
372 pointer_data.physical_delta_y = pointer_data.physical_y - state.physical_y;
373 pointer_data.pan_delta_x = pointer_data.pan_x - state.pan_x;
374 pointer_data.pan_delta_y = pointer_data.pan_y - state.pan_y;
375 state.physical_x = pointer_data.physical_x;
376 state.physical_y = pointer_data.physical_y;
377 state.pan_x = pointer_data.pan_x;
378 state.pan_y = pointer_data.pan_y;
379 state.scale = pointer_data.scale;
380 state.rotation = pointer_data.rotation;
381 states_[pointer_data.device] = state;
382}
383
384bool PointerDataPacketConverter::LocationNeedsUpdate(
385 const PointerData pointer_data,
386 const PointerState state) {
387 return state.physical_x != pointer_data.physical_x ||
388 state.physical_y != pointer_data.physical_y;
389}
390
391void PointerDataPacketConverter::UpdatePointerIdentifier(
392 PointerData& pointer_data,
393 PointerState& state,
394 bool start_new_pointer) {
395 if (start_new_pointer) {
396 state.pointer_identifier = ++pointer_;
397 states_[pointer_data.device] = state;
398 }
399 pointer_data.pointer_identifier = state.pointer_identifier;
400}
401
402} // namespace flutter
int count
Definition: FontMgrTest.cpp:50
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_
AtkStateType state
#define FML_DCHECK(condition)
Definition: logging.h:103
SignalKind signal_kind
Definition: pointer_data.h:74