@@ -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
5054namespace 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+
203238void 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
214248void 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
223264void 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
232282void 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
245294void 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
0 commit comments