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 <cstring>
8 
9 #include "flutter/fml/logging.h"
10 
11 namespace flutter {
12 
14 
16 
17 std::unique_ptr<PointerDataPacket> PointerDataPacketConverter::Convert(
18  std::unique_ptr<PointerDataPacket> packet) {
19  size_t kBytesPerPointerData = kPointerDataFieldCount * kBytesPerField;
20  auto buffer = packet->data();
21  size_t buffer_length = buffer.size();
22 
23  std::vector<PointerData> converted_pointers;
24  // Converts each pointer data in the buffer and stores it in the
25  // converted_pointers.
26  for (size_t i = 0; i < buffer_length / kBytesPerPointerData; i++) {
27  PointerData pointer_data;
28  memcpy(&pointer_data, &buffer[i * kBytesPerPointerData],
29  sizeof(PointerData));
30  ConvertPointerData(pointer_data, converted_pointers);
31  }
32 
33  // Writes converted_pointers into converted_packet.
34  auto converted_packet =
35  std::make_unique<flutter::PointerDataPacket>(converted_pointers.size());
36  size_t count = 0;
37  for (auto& converted_pointer : converted_pointers) {
38  converted_packet->SetPointerData(count++, converted_pointer);
39  }
40 
41  return converted_packet;
42 }
43 
44 void PointerDataPacketConverter::ConvertPointerData(
45  PointerData pointer_data,
46  std::vector<PointerData>& converted_pointers) {
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);
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);
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  }
210  default: {
211  converted_pointers.push_back(pointer_data);
212  break;
213  }
214  }
215  } else {
216  switch (pointer_data.signal_kind) {
218  // Makes sure we have an existing pointer
219  auto iter = states_.find(pointer_data.device);
220  FML_DCHECK(iter != states_.end());
221 
222  PointerState state = iter->second;
223  if (LocationNeedsUpdate(pointer_data, state)) {
224  if (state.is_down) {
225  // Synthesizes a move event if the pointer is down.
226  PointerData synthesized_move_event = pointer_data;
227  synthesized_move_event.signal_kind = PointerData::SignalKind::kNone;
228  synthesized_move_event.change = PointerData::Change::kMove;
229  synthesized_move_event.buttons = state.buttons;
230  synthesized_move_event.synthesized = 1;
231 
232  UpdateDeltaAndState(synthesized_move_event, state);
233  converted_pointers.push_back(synthesized_move_event);
234  } else {
235  // Synthesizes a hover event if the pointer is up.
236  PointerData synthesized_hover_event = pointer_data;
237  synthesized_hover_event.signal_kind =
239  synthesized_hover_event.change = PointerData::Change::kHover;
240  synthesized_hover_event.buttons = 0;
241  synthesized_hover_event.synthesized = 1;
242 
243  UpdateDeltaAndState(synthesized_hover_event, state);
244  converted_pointers.push_back(synthesized_hover_event);
245  }
246  }
247 
248  converted_pointers.push_back(pointer_data);
249  break;
250  }
251  default: {
252  // Ignores unknown signal kind.
253  break;
254  }
255  }
256  }
257 }
258 
259 PointerState PointerDataPacketConverter::EnsurePointerState(
260  PointerData pointer_data) {
262  state.pointer_identifier = 0;
263  state.is_down = false;
264  state.physical_x = pointer_data.physical_x;
265  state.physical_y = pointer_data.physical_y;
266  states_[pointer_data.device] = state;
267  return state;
268 }
269 
270 void PointerDataPacketConverter::UpdateDeltaAndState(PointerData& pointer_data,
271  PointerState& state) {
272  pointer_data.physical_delta_x = pointer_data.physical_x - state.physical_x;
273  pointer_data.physical_delta_y = pointer_data.physical_y - state.physical_y;
274  state.physical_x = pointer_data.physical_x;
275  state.physical_y = pointer_data.physical_y;
276  states_[pointer_data.device] = state;
277 }
278 
279 bool PointerDataPacketConverter::LocationNeedsUpdate(
280  const PointerData pointer_data,
281  const PointerState state) {
282  return state.physical_x != pointer_data.physical_x ||
283  state.physical_y != pointer_data.physical_y;
284 }
285 
286 void PointerDataPacketConverter::UpdatePointerIdentifier(
287  PointerData& pointer_data,
288  PointerState& state,
289  bool start_new_pointer) {
290  if (start_new_pointer) {
291  state.pointer_identifier = ++pointer_;
292  states_[pointer_data.device] = state;
293  }
294  pointer_data.pointer_identifier = state.pointer_identifier;
295 }
296 
297 } // namespace flutter
static constexpr int kBytesPerField
Definition: pointer_data.h:14
static constexpr int kPointerDataFieldCount
Definition: pointer_data.h:13
#define FML_DCHECK(condition)
Definition: logging.h:86
SignalKind signal_kind
Definition: pointer_data.h:65
int64_t pointer_identifier
Definition: pointer_data.h:67
std::unique_ptr< PointerDataPacket > Convert(std::unique_ptr< PointerDataPacket > packet)
Converts pointer data packet into a form that framework understands. The raw pointer data packet from...
static const uint8_t buffer[]
AtkStateType state