Skip to content

Commit 69d7e8e

Browse files
authored
Correct button state on synthetic pointer events (flutter#23111)
This corrects the button state emitted on synthetic pointer move and hover events generated by the engine. When an embedder notifies the engine of a pointer up or down event, and the pointer's position has changed since the last move or hover event, `PointerDataPacketConverter` generates a synthetic move or hover to notify the framework of the change in position. In these cases, the current event from the embedder contains the new button state *after* the pointer up/down event, but the move/hover needs to be synthesized such that it occurs *before* the pointer up/down, with the previous button state. This patch stores the button state after each pointer down, up, move, or hover event such that it can be used by the next event if a synthetic event must be issued. The bug in the previous logic was revealed by the release of macOS 11 (Big Sur), which appears to issue move events between mouse down and mouse up, which did not use to be the case. This fixes flutter#64961, which is the desktop-specific tracking bug for the more general Big Sur mouse click umbrella issue flutter#71190.
1 parent b0c6686 commit 69d7e8e

File tree

3 files changed

+98
-54
lines changed

3 files changed

+98
-54
lines changed

lib/ui/window/pointer_data_packet_converter.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,15 @@ void PointerDataPacketConverter::ConvertPointerData(
119119
PointerData synthesized_add_event = pointer_data;
120120
synthesized_add_event.change = PointerData::Change::kAdd;
121121
synthesized_add_event.synthesized = 1;
122+
synthesized_add_event.buttons = 0;
122123
state = EnsurePointerState(synthesized_add_event);
123124
converted_pointers.push_back(synthesized_add_event);
124125
} else {
125126
state = iter->second;
126127
}
127128

128129
FML_DCHECK(!state.isDown);
130+
state.buttons = pointer_data.buttons;
129131
if (LocationNeedsUpdate(pointer_data, state)) {
130132
UpdateDeltaAndState(pointer_data, state);
131133
converted_pointers.push_back(pointer_data);
@@ -140,6 +142,7 @@ void PointerDataPacketConverter::ConvertPointerData(
140142
PointerData synthesized_add_event = pointer_data;
141143
synthesized_add_event.change = PointerData::Change::kAdd;
142144
synthesized_add_event.synthesized = 1;
145+
synthesized_add_event.buttons = 0;
143146
state = EnsurePointerState(synthesized_add_event);
144147
converted_pointers.push_back(synthesized_add_event);
145148
} else {
@@ -152,13 +155,15 @@ void PointerDataPacketConverter::ConvertPointerData(
152155
PointerData synthesized_hover_event = pointer_data;
153156
synthesized_hover_event.change = PointerData::Change::kHover;
154157
synthesized_hover_event.synthesized = 1;
158+
synthesized_hover_event.buttons = 0;
155159

156160
UpdateDeltaAndState(synthesized_hover_event, state);
157161
converted_pointers.push_back(synthesized_hover_event);
158162
}
159163

160164
UpdatePointerIdentifier(pointer_data, state, true);
161165
state.isDown = true;
166+
state.buttons = pointer_data.buttons;
162167
states_[pointer_data.device] = state;
163168
converted_pointers.push_back(pointer_data);
164169
break;
@@ -172,6 +177,7 @@ void PointerDataPacketConverter::ConvertPointerData(
172177

173178
UpdatePointerIdentifier(pointer_data, state, false);
174179
UpdateDeltaAndState(pointer_data, state);
180+
state.buttons = pointer_data.buttons;
175181
converted_pointers.push_back(pointer_data);
176182
break;
177183
}
@@ -188,13 +194,15 @@ void PointerDataPacketConverter::ConvertPointerData(
188194
// Synthesizes a move event if the location does not match.
189195
PointerData synthesized_move_event = pointer_data;
190196
synthesized_move_event.change = PointerData::Change::kMove;
197+
synthesized_move_event.buttons = state.buttons;
191198
synthesized_move_event.synthesized = 1;
192199

193200
UpdateDeltaAndState(synthesized_move_event, state);
194201
converted_pointers.push_back(synthesized_move_event);
195202
}
196203

197204
state.isDown = false;
205+
state.buttons = pointer_data.buttons;
198206
states_[pointer_data.device] = state;
199207
converted_pointers.push_back(pointer_data);
200208
break;
@@ -218,6 +226,7 @@ void PointerDataPacketConverter::ConvertPointerData(
218226
PointerData synthesized_move_event = pointer_data;
219227
synthesized_move_event.signal_kind = PointerData::SignalKind::kNone;
220228
synthesized_move_event.change = PointerData::Change::kMove;
229+
synthesized_move_event.buttons = state.buttons;
221230
synthesized_move_event.synthesized = 1;
222231

223232
UpdateDeltaAndState(synthesized_move_event, state);
@@ -228,6 +237,7 @@ void PointerDataPacketConverter::ConvertPointerData(
228237
synthesized_hover_event.signal_kind =
229238
PointerData::SignalKind::kNone;
230239
synthesized_hover_event.change = PointerData::Change::kHover;
240+
synthesized_hover_event.buttons = 0;
231241
synthesized_hover_event.synthesized = 1;
232242

233243
UpdateDeltaAndState(synthesized_hover_event, state);

lib/ui/window/pointer_data_packet_converter.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,23 @@
1616
namespace flutter {
1717

1818
//------------------------------------------------------------------------------
19-
/// The current information about a pointer. This struct is used by
20-
/// PointerDataPacketConverter to fill in necesarry information for raw pointer
21-
/// packet sent from embedding.
19+
/// The current information about a pointer.
20+
///
21+
/// This struct is used by PointerDataPacketConverter to fill in necessary
22+
/// information for the raw pointer packet sent from embedding. This struct also
23+
/// stores the button state of the last pointer down, up, move, or hover event.
24+
/// When an embedder issues a pointer up or down event where the pointer's
25+
/// position has changed since the last move or hover event,
26+
/// PointerDataPacketConverter generates a synthetic move or hover to notify the
27+
/// framework. In these cases, these events must be issued with the button state
28+
/// prior to the pointer up or down.
2229
///
2330
struct PointerState {
2431
int64_t pointer_identifier;
2532
bool isDown;
2633
double physical_x;
2734
double physical_y;
35+
int64_t buttons;
2836
};
2937

3038
//------------------------------------------------------------------------------

0 commit comments

Comments
 (0)