Skip to content

Commit 4f461b2

Browse files
authored
Handle right and middle mouse button clicks (#30)
1 parent 5e40ba6 commit 4f461b2

File tree

8 files changed

+261
-84
lines changed

8 files changed

+261
-84
lines changed

flutter/shell/platform/tizen/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ template("embedder") {
204204
"//flutter/shell/platform/common:common_cpp_input",
205205
"//flutter/shell/platform/common:common_cpp_library_headers",
206206
"//flutter/shell/platform/common/client_wrapper:client_wrapper",
207+
"//flutter/shell/platform/embedder:embedder_headers",
207208
"//third_party/rapidjson",
208209
]
209210

flutter/shell/platform/tizen/flutter_tizen.cc

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "flutter/shell/platform/common/client_wrapper/include/flutter/plugin_registrar.h"
99
#include "flutter/shell/platform/common/client_wrapper/include/flutter/standard_message_codec.h"
1010
#include "flutter/shell/platform/common/incoming_message_dispatcher.h"
11+
#include "flutter/shell/platform/embedder/embedder.h"
1112
#include "flutter/shell/platform/tizen/flutter_project_bundle.h"
1213
#include "flutter/shell/platform/tizen/flutter_tizen_engine.h"
1314
#include "flutter/shell/platform/tizen/flutter_tizen_view.h"
@@ -251,19 +252,23 @@ void FlutterDesktopViewOnPointerEvent(FlutterDesktopViewRef view,
251252
double y,
252253
size_t timestamp,
253254
int32_t device_id) {
255+
// TODO(swift-kim): Add support for mouse devices.
256+
FlutterPointerDeviceKind device_kind = kFlutterPointerDeviceKindTouch;
257+
FlutterPointerMouseButtons button = kFlutterPointerButtonMousePrimary;
258+
254259
switch (type) {
255260
case FlutterDesktopPointerEventType::kMouseDown:
256261
default:
257-
ViewFromHandle(view)->OnPointerDown(
258-
x, y, timestamp, kFlutterPointerDeviceKindTouch, device_id);
262+
ViewFromHandle(view)->OnPointerDown(x, y, button, timestamp, device_kind,
263+
device_id);
259264
break;
260265
case FlutterDesktopPointerEventType::kMouseUp:
261-
ViewFromHandle(view)->OnPointerUp(
262-
x, y, timestamp, kFlutterPointerDeviceKindTouch, device_id);
266+
ViewFromHandle(view)->OnPointerUp(x, y, button, timestamp, device_kind,
267+
device_id);
263268
break;
264269
case FlutterDesktopPointerEventType::kMouseMove:
265-
ViewFromHandle(view)->OnPointerMove(
266-
x, y, timestamp, kFlutterPointerDeviceKindTouch, device_id);
270+
ViewFromHandle(view)->OnPointerMove(x, y, timestamp, device_kind,
271+
device_id);
267272
break;
268273
}
269274
}

flutter/shell/platform/tizen/flutter_tizen_view.cc

Lines changed: 91 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ const std::vector<std::string> kBindableSystemKeys = {
4545
"XF86Exit",
4646
};
4747

48+
// The multiplier is taken from the Chromium source
49+
// (ui/events/x/events_x_utils.cc).
50+
constexpr int32_t kScrollOffsetMultiplier = 53;
51+
4852
} // namespace
4953

5054
namespace flutter {
@@ -200,46 +204,91 @@ void FlutterTizenView::OnRotate(int32_t degree) {
200204
SendWindowMetrics(geometry.left, geometry.top, width, height, 0.0);
201205
}
202206

207+
FlutterTizenView::PointerState* FlutterTizenView::GetOrCreatePointerState(
208+
FlutterPointerDeviceKind device_kind,
209+
int32_t device_id) {
210+
// Create a virtual pointer ID that is unique across all device types
211+
// to prevent pointers from clashing in the engine's converter
212+
// (lib/ui/window/pointer_data_packet_converter.cc)
213+
int32_t pointer_id = (static_cast<int32_t>(device_kind) << 28) | device_id;
214+
215+
auto [iter, added] = pointer_states_.try_emplace(pointer_id, nullptr);
216+
if (added) {
217+
auto state = std::make_unique<PointerState>();
218+
state->device_kind = device_kind;
219+
state->pointer_id = pointer_id;
220+
iter->second = std::move(state);
221+
}
222+
return iter->second.get();
223+
}
224+
225+
FlutterPointerPhase FlutterTizenView::GetPointerPhaseFromState(
226+
const PointerState* state) const {
227+
// For details about this logic, see FlutterPointerPhase in the embedder.h
228+
// file.
229+
if (state->buttons == 0) {
230+
return state->flutter_state_is_down ? FlutterPointerPhase::kUp
231+
: FlutterPointerPhase::kHover;
232+
} else {
233+
return state->flutter_state_is_down ? FlutterPointerPhase::kMove
234+
: FlutterPointerPhase::kDown;
235+
}
236+
}
237+
203238
void FlutterTizenView::OnPointerMove(double x,
204239
double y,
205240
size_t timestamp,
206241
FlutterPointerDeviceKind device_kind,
207242
int32_t device_id) {
208-
if (pointer_state_) {
209-
SendFlutterPointerEvent(kMove, x, y, 0, 0, timestamp, device_kind,
210-
device_id);
211-
}
243+
PointerState* state = GetOrCreatePointerState(device_kind, device_id);
244+
FlutterPointerPhase phase = GetPointerPhaseFromState(state);
245+
SendFlutterPointerEvent(phase, x, y, 0, 0, timestamp, state);
212246
}
213247

214248
void FlutterTizenView::OnPointerDown(double x,
215249
double y,
250+
FlutterPointerMouseButtons button,
216251
size_t timestamp,
217252
FlutterPointerDeviceKind device_kind,
218253
int32_t device_id) {
219-
pointer_state_ = true;
220-
SendFlutterPointerEvent(kDown, x, y, 0, 0, timestamp, device_kind, device_id);
254+
if (button != 0) {
255+
PointerState* state = GetOrCreatePointerState(device_kind, device_id);
256+
state->buttons |= button;
257+
FlutterPointerPhase phase = GetPointerPhaseFromState(state);
258+
SendFlutterPointerEvent(phase, x, y, 0, 0, timestamp, state);
259+
260+
state->flutter_state_is_down = true;
261+
}
221262
}
222263

223264
void FlutterTizenView::OnPointerUp(double x,
224265
double y,
266+
FlutterPointerMouseButtons button,
225267
size_t timestamp,
226268
FlutterPointerDeviceKind device_kind,
227269
int32_t device_id) {
228-
pointer_state_ = false;
229-
SendFlutterPointerEvent(kUp, x, y, 0, 0, timestamp, device_kind, device_id);
270+
if (button != 0) {
271+
PointerState* state = GetOrCreatePointerState(device_kind, device_id);
272+
state->buttons &= ~button;
273+
FlutterPointerPhase phase = GetPointerPhaseFromState(state);
274+
SendFlutterPointerEvent(phase, x, y, 0, 0, timestamp, state);
275+
276+
if (phase == FlutterPointerPhase::kUp) {
277+
state->flutter_state_is_down = false;
278+
}
279+
}
230280
}
231281

232282
void FlutterTizenView::OnScroll(double x,
233283
double y,
234284
double delta_x,
235285
double delta_y,
236-
int scroll_offset_multiplier,
237286
size_t timestamp,
238287
FlutterPointerDeviceKind device_kind,
239288
int32_t device_id) {
240-
SendFlutterPointerEvent(
241-
pointer_state_ ? kMove : kHover, x, y, delta_x * scroll_offset_multiplier,
242-
delta_y * scroll_offset_multiplier, timestamp, device_kind, device_id);
289+
PointerState* state = GetOrCreatePointerState(device_kind, device_id);
290+
FlutterPointerPhase phase = GetPointerPhaseFromState(state);
291+
SendFlutterPointerEvent(phase, x, y, delta_x, delta_y, timestamp, state);
243292
}
244293

245294
void FlutterTizenView::OnKey(const char* key,
@@ -341,15 +390,13 @@ void FlutterTizenView::SendWindowMetrics(int32_t left,
341390
engine_->SendWindowMetrics(left, top, width, height, computed_pixel_ratio);
342391
}
343392

344-
void FlutterTizenView::SendFlutterPointerEvent(
345-
FlutterPointerPhase phase,
346-
double x,
347-
double y,
348-
double delta_x,
349-
double delta_y,
350-
size_t timestamp,
351-
FlutterPointerDeviceKind device_kind,
352-
int device_id) {
393+
void FlutterTizenView::SendFlutterPointerEvent(FlutterPointerPhase phase,
394+
double x,
395+
double y,
396+
double delta_x,
397+
double delta_y,
398+
size_t timestamp,
399+
PointerState* state) {
353400
TizenGeometry geometry = tizen_view_->GetGeometry();
354401
double new_x = x, new_y = y;
355402

@@ -364,6 +411,24 @@ void FlutterTizenView::SendFlutterPointerEvent(
364411
new_y = geometry.width - x;
365412
}
366413

414+
// If the pointer isn't already added, synthesize an add to satisfy Flutter's
415+
// expectations about events.
416+
if (!state->flutter_state_is_added) {
417+
FlutterPointerEvent event = {};
418+
event.struct_size = sizeof(event);
419+
event.phase = FlutterPointerPhase::kAdd;
420+
event.x = new_x;
421+
event.y = new_y;
422+
event.buttons = 0;
423+
event.timestamp = timestamp * 1000;
424+
event.device = state->pointer_id;
425+
event.device_kind = state->device_kind;
426+
event.buttons = state->buttons;
427+
engine_->SendPointerEvent(event);
428+
429+
state->flutter_state_is_added = true;
430+
}
431+
367432
FlutterPointerEvent event = {};
368433
event.struct_size = sizeof(event);
369434
event.phase = phase;
@@ -372,12 +437,12 @@ void FlutterTizenView::SendFlutterPointerEvent(
372437
if (delta_x != 0 || delta_y != 0) {
373438
event.signal_kind = kFlutterPointerSignalKindScroll;
374439
}
375-
event.scroll_delta_x = delta_x;
376-
event.scroll_delta_y = delta_y;
440+
event.scroll_delta_x = delta_x * kScrollOffsetMultiplier;
441+
event.scroll_delta_y = delta_y * kScrollOffsetMultiplier;
377442
event.timestamp = timestamp * 1000;
378-
event.device = device_id;
379-
event.device_kind = kFlutterPointerDeviceKindTouch;
380-
443+
event.device = state->pointer_id;
444+
event.device_kind = state->device_kind;
445+
event.buttons = state->buttons;
381446
engine_->SendPointerEvent(event);
382447
}
383448

flutter/shell/platform/tizen/flutter_tizen_view.h

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,14 @@ class FlutterTizenView : public TizenViewEventHandlerDelegate {
6969

7070
void OnPointerDown(double x,
7171
double y,
72+
FlutterPointerMouseButtons button,
7273
size_t timestamp,
7374
FlutterPointerDeviceKind device_kind,
7475
int32_t device_id) override;
7576

7677
void OnPointerUp(double x,
7778
double y,
79+
FlutterPointerMouseButtons button,
7880
size_t timestamp,
7981
FlutterPointerDeviceKind device_kind,
8082
int32_t device_id) override;
@@ -83,7 +85,6 @@ class FlutterTizenView : public TizenViewEventHandlerDelegate {
8385
double y,
8486
double delta_x,
8587
double delta_y,
86-
int scroll_offset_multiplier,
8788
size_t timestamp,
8889
FlutterPointerDeviceKind device_kind,
8990
int32_t device_id) override;
@@ -112,6 +113,35 @@ class FlutterTizenView : public TizenViewEventHandlerDelegate {
112113
TextInputChannel* text_input_channel() { return text_input_channel_.get(); }
113114

114115
private:
116+
// Struct holding the state of an individual pointer. The engine doesn't keep
117+
// track of which buttons have been pressed, so it's the embedder's
118+
// responsibility.
119+
struct PointerState {
120+
// The device kind.
121+
FlutterPointerDeviceKind device_kind = kFlutterPointerDeviceKindTouch;
122+
123+
// A virtual pointer ID that is unique across all device kinds.
124+
int32_t pointer_id = 0;
125+
126+
// True if the last event sent to Flutter had at least one button pressed.
127+
bool flutter_state_is_down = false;
128+
129+
// True if kAdd has been sent to Flutter. Used to determine whether
130+
// to send a kAdd event before sending an incoming pointer event, since
131+
// Flutter expects pointers to be added before events are sent for them.
132+
bool flutter_state_is_added = false;
133+
134+
// The currently pressed buttons, as represented in FlutterPointerEvent.
135+
uint64_t buttons = 0;
136+
};
137+
138+
// Creates a PointerState object unless it already exists.
139+
PointerState* GetOrCreatePointerState(FlutterPointerDeviceKind device_kind,
140+
int32_t device_id);
141+
142+
// Returns a FlutterPointerPhase corresponding to the current pointer state.
143+
FlutterPointerPhase GetPointerPhaseFromState(const PointerState* state) const;
144+
115145
// Sends a window metrics update to the Flutter engine using current window
116146
// dimensions in physical.
117147
void SendWindowMetrics(int32_t left,
@@ -127,15 +157,17 @@ class FlutterTizenView : public TizenViewEventHandlerDelegate {
127157
double delta_x,
128158
double delta_y,
129159
size_t timestamp,
130-
FlutterPointerDeviceKind device_kind,
131-
int device_id);
160+
PointerState* state);
132161

133162
// The engine associated with this view.
134163
std::unique_ptr<FlutterTizenEngine> engine_;
135164

136165
// The platform view associated with this Flutter view.
137166
std::unique_ptr<TizenViewBase> tizen_view_;
138167

168+
// Keeps track of pointer states.
169+
std::unordered_map<int32_t, std::unique_ptr<PointerState>> pointer_states_;
170+
139171
// The plugin registrar managing internal plugins.
140172
std::unique_ptr<PluginRegistrar> internal_plugin_registrar_;
141173

@@ -151,9 +183,6 @@ class FlutterTizenView : public TizenViewEventHandlerDelegate {
151183
// The current view rotation degree.
152184
int32_t rotation_degree_ = 0;
153185

154-
// The current pointer state to distinguish move or hover event.
155-
bool pointer_state_ = false;
156-
157186
// The current view transformation.
158187
FlutterTransformation flutter_transformation_ = {1.0, 0.0, 0.0, 0.0, 1.0,
159188
0.0, 0.0, 0.0, 1.0};

0 commit comments

Comments
 (0)