diff --git a/shell/platform/linux/fl_engine.cc b/shell/platform/linux/fl_engine.cc index f2c8040aa41d2..91aa555b2f082 100644 --- a/shell/platform/linux/fl_engine.cc +++ b/shell/platform/linux/fl_engine.cc @@ -772,6 +772,7 @@ void fl_engine_send_mouse_pointer_event(FlEngine* self, size_t timestamp, double x, double y, + FlutterPointerDeviceKind device_kind, double scroll_delta_x, double scroll_delta_y, int64_t buttons) { @@ -792,7 +793,7 @@ void fl_engine_send_mouse_pointer_event(FlEngine* self, } fl_event.scroll_delta_x = scroll_delta_x; fl_event.scroll_delta_y = scroll_delta_y; - fl_event.device_kind = kFlutterPointerDeviceKindMouse; + fl_event.device_kind = device_kind; fl_event.buttons = buttons; fl_event.device = kMousePointerDeviceId; // TODO(dkwingsmt): Assign the correct view ID once the Linux embedder diff --git a/shell/platform/linux/fl_engine_private.h b/shell/platform/linux/fl_engine_private.h index 10d57a7e7fccf..9225b481cd67c 100644 --- a/shell/platform/linux/fl_engine_private.h +++ b/shell/platform/linux/fl_engine_private.h @@ -188,6 +188,7 @@ void fl_engine_send_window_state_event(FlEngine* engine, * @timestamp: time when event occurred in microseconds. * @x: x location of mouse cursor. * @y: y location of mouse cursor. + * @device_kind: kind of pointing device. * @scroll_delta_x: x offset of scroll. * @scroll_delta_y: y offset of scroll. * @buttons: buttons that are pressed. @@ -199,6 +200,7 @@ void fl_engine_send_mouse_pointer_event(FlEngine* engine, size_t timestamp, double x, double y, + FlutterPointerDeviceKind device_kind, double scroll_delta_x, double scroll_delta_y, int64_t buttons); diff --git a/shell/platform/linux/fl_engine_test.cc b/shell/platform/linux/fl_engine_test.cc index a7329a6997b0f..ce690c0535a90 100644 --- a/shell/platform/linux/fl_engine_test.cc +++ b/shell/platform/linux/fl_engine_test.cc @@ -70,8 +70,9 @@ TEST(FlEngineTest, MousePointer) { g_autoptr(GError) error = nullptr; EXPECT_TRUE(fl_engine_start(engine, &error)); EXPECT_EQ(error, nullptr); - fl_engine_send_mouse_pointer_event(engine, kDown, 1234567890, 800, 600, 1.2, - -3.4, kFlutterPointerButtonMouseSecondary); + fl_engine_send_mouse_pointer_event(engine, kDown, 1234567890, 800, 600, + kFlutterPointerDeviceKindMouse, 1.2, -3.4, + kFlutterPointerButtonMouseSecondary); EXPECT_TRUE(called); } diff --git a/shell/platform/linux/fl_scrolling_manager.cc b/shell/platform/linux/fl_scrolling_manager.cc index aee1b52aed724..81b4fc5a03824 100644 --- a/shell/platform/linux/fl_scrolling_manager.cc +++ b/shell/platform/linux/fl_scrolling_manager.cc @@ -143,7 +143,8 @@ void fl_scrolling_manager_handle_scroll_event(FlScrollingManager* self, this is a discrete scroll event */ , event_time * kMicrosecondsPerMillisecond, event_x * scale_factor, - event_y * scale_factor, scroll_delta_x, scroll_delta_y, 0); + event_y * scale_factor, kFlutterPointerDeviceKindMouse, scroll_delta_x, + scroll_delta_y, 0); } } diff --git a/shell/platform/linux/fl_scrolling_manager_test.cc b/shell/platform/linux/fl_scrolling_manager_test.cc index 59b67bc925382..7715bc92e95d6 100644 --- a/shell/platform/linux/fl_scrolling_manager_test.cc +++ b/shell/platform/linux/fl_scrolling_manager_test.cc @@ -13,6 +13,7 @@ typedef std::function @@ -32,6 +33,7 @@ typedef struct { size_t timestamp; double x; double y; + FlutterPointerDeviceKind device_kind; double scroll_delta_x; double scroll_delta_y; int64_t buttons; @@ -114,13 +116,14 @@ static void fl_mock_view_send_mouse_pointer_event( size_t timestamp, double x, double y, + FlutterPointerDeviceKind device_kind, double scroll_delta_x, double scroll_delta_y, int64_t buttons) { FlMockScrollingViewDelegatePrivate* priv = FL_MOCK_SCROLLING_VIEW_DELEGATE_GET_PRIVATE(delegate); - priv->mouse_handler(phase, timestamp, x, y, scroll_delta_x, scroll_delta_y, - buttons); + priv->mouse_handler(phase, timestamp, x, y, device_kind, scroll_delta_x, + scroll_delta_y, buttons); } static void fl_mock_view_send_pointer_pan_zoom_event( @@ -182,7 +185,8 @@ class ScrollingTester { fl_mock_scrolling_view_set_mouse_handler( view_, [](FlutterPointerPhase phase, size_t timestamp, double x, double y, - double scroll_delta_x, double scroll_delta_y, int64_t buttons) { + FlutterPointerDeviceKind device_kind, double scroll_delta_x, + double scroll_delta_y, int64_t buttons) { // do nothing }); fl_mock_scrolling_view_set_pan_zoom_handler( @@ -204,13 +208,15 @@ class ScrollingTester { std::vector& storage) { fl_mock_scrolling_view_set_mouse_handler( view_, [&storage](FlutterPointerPhase phase, size_t timestamp, double x, - double y, double scroll_delta_x, - double scroll_delta_y, int64_t buttons) { + double y, FlutterPointerDeviceKind device_kind, + double scroll_delta_x, double scroll_delta_y, + int64_t buttons) { storage.push_back(MousePointerEventRecord{ .phase = phase, .timestamp = timestamp, .x = x, .y = y, + .device_kind = device_kind, .scroll_delta_x = scroll_delta_x, .scroll_delta_y = scroll_delta_y, .buttons = buttons, @@ -278,6 +284,7 @@ TEST(FlScrollingManagerTest, DiscreteDirectionional) { EXPECT_EQ(mouse_records.size(), 1u); EXPECT_EQ(mouse_records[0].x, 4.0); EXPECT_EQ(mouse_records[0].y, 8.0); + EXPECT_EQ(mouse_records[0].device_kind, kFlutterPointerDeviceKindMouse); EXPECT_EQ(mouse_records[0].timestamp, 1000lu); // Milliseconds -> Microseconds EXPECT_EQ(mouse_records[0].scroll_delta_x, 0); @@ -288,6 +295,7 @@ TEST(FlScrollingManagerTest, DiscreteDirectionional) { EXPECT_EQ(mouse_records.size(), 2u); EXPECT_EQ(mouse_records[1].x, 4.0); EXPECT_EQ(mouse_records[1].y, 8.0); + EXPECT_EQ(mouse_records[1].device_kind, kFlutterPointerDeviceKindMouse); EXPECT_EQ(mouse_records[1].timestamp, 1000lu); // Milliseconds -> Microseconds EXPECT_EQ(mouse_records[1].scroll_delta_x, 0); @@ -298,6 +306,7 @@ TEST(FlScrollingManagerTest, DiscreteDirectionional) { EXPECT_EQ(mouse_records.size(), 3u); EXPECT_EQ(mouse_records[2].x, 4.0); EXPECT_EQ(mouse_records[2].y, 8.0); + EXPECT_EQ(mouse_records[2].device_kind, kFlutterPointerDeviceKindMouse); EXPECT_EQ(mouse_records[2].timestamp, 1000lu); // Milliseconds -> Microseconds EXPECT_EQ(mouse_records[2].scroll_delta_x, 53 * -1.0); @@ -308,6 +317,7 @@ TEST(FlScrollingManagerTest, DiscreteDirectionional) { EXPECT_EQ(mouse_records.size(), 4u); EXPECT_EQ(mouse_records[3].x, 4.0); EXPECT_EQ(mouse_records[3].y, 8.0); + EXPECT_EQ(mouse_records[3].device_kind, kFlutterPointerDeviceKindMouse); EXPECT_EQ(mouse_records[3].timestamp, 1000lu); // Milliseconds -> Microseconds EXPECT_EQ(mouse_records[3].scroll_delta_x, 53 * 1.0); @@ -335,6 +345,7 @@ TEST(FlScrollingManagerTest, DiscreteScrolling) { EXPECT_EQ(mouse_records.size(), 1u); EXPECT_EQ(mouse_records[0].x, 4.0); EXPECT_EQ(mouse_records[0].y, 8.0); + EXPECT_EQ(mouse_records[0].device_kind, kFlutterPointerDeviceKindMouse); EXPECT_EQ(mouse_records[0].timestamp, 1000lu); // Milliseconds -> Microseconds EXPECT_EQ(mouse_records[0].scroll_delta_x, 53 * 1.0); diff --git a/shell/platform/linux/fl_scrolling_view_delegate.cc b/shell/platform/linux/fl_scrolling_view_delegate.cc index 1a9c904524c03..2d8ce60aaae14 100644 --- a/shell/platform/linux/fl_scrolling_view_delegate.cc +++ b/shell/platform/linux/fl_scrolling_view_delegate.cc @@ -17,13 +17,15 @@ void fl_scrolling_view_delegate_send_mouse_pointer_event( size_t timestamp, double x, double y, + FlutterPointerDeviceKind device_kind, double scroll_delta_x, double scroll_delta_y, int64_t buttons) { g_return_if_fail(FL_IS_SCROLLING_VIEW_DELEGATE(self)); FL_SCROLLING_VIEW_DELEGATE_GET_IFACE(self)->send_mouse_pointer_event( - self, phase, timestamp, x, y, scroll_delta_x, scroll_delta_y, buttons); + self, phase, timestamp, x, y, device_kind, scroll_delta_x, scroll_delta_y, + buttons); } void fl_scrolling_view_delegate_send_pointer_pan_zoom_event( FlScrollingViewDelegate* self, diff --git a/shell/platform/linux/fl_scrolling_view_delegate.h b/shell/platform/linux/fl_scrolling_view_delegate.h index d00ef7a2a6e13..e0def169824df 100644 --- a/shell/platform/linux/fl_scrolling_view_delegate.h +++ b/shell/platform/linux/fl_scrolling_view_delegate.h @@ -38,6 +38,7 @@ struct _FlScrollingViewDelegateInterface { size_t timestamp, double x, double y, + FlutterPointerDeviceKind device_kind, double scroll_delta_x, double scroll_delta_y, int64_t buttons); @@ -59,6 +60,7 @@ void fl_scrolling_view_delegate_send_mouse_pointer_event( size_t timestamp, double x, double y, + FlutterPointerDeviceKind device_kind, double scroll_delta_x, double scroll_delta_y, int64_t buttons); diff --git a/shell/platform/linux/fl_view.cc b/shell/platform/linux/fl_view.cc index 0d1fb4709f703..2e4b24a5eb4e0 100644 --- a/shell/platform/linux/fl_view.cc +++ b/shell/platform/linux/fl_view.cc @@ -124,6 +124,25 @@ static void init_scrolling(FlView* self) { fl_scrolling_manager_new(FL_SCROLLING_VIEW_DELEGATE(self)); } +static FlutterPointerDeviceKind get_device_kind(GdkEvent* event) { + GdkDevice* device = gdk_event_get_source_device(event); + GdkInputSource source = gdk_device_get_source(device); + switch (source) { + case GDK_SOURCE_PEN: + case GDK_SOURCE_ERASER: + case GDK_SOURCE_CURSOR: + case GDK_SOURCE_TABLET_PAD: + return kFlutterPointerDeviceKindStylus; + case GDK_SOURCE_TOUCHSCREEN: + return kFlutterPointerDeviceKindTouch; + case GDK_SOURCE_TOUCHPAD: // trackpad device type is reserved for gestures + case GDK_SOURCE_TRACKPOINT: + case GDK_SOURCE_KEYBOARD: + case GDK_SOURCE_MOUSE: + return kFlutterPointerDeviceKindMouse; + } +} + // Converts a GDK button event into a Flutter event and sends it to the engine. static gboolean send_pointer_button_event(FlView* self, GdkEvent* event) { guint event_time = gdk_event_get_time(event); @@ -180,7 +199,8 @@ static gboolean send_pointer_button_event(FlView* self, GdkEvent* event) { event_state, event_time); fl_engine_send_mouse_pointer_event( self->engine, phase, event_time * kMicrosecondsPerMillisecond, - event_x * scale_factor, event_y * scale_factor, 0, 0, self->button_state); + event_x * scale_factor, event_y * scale_factor, + get_device_kind((GdkEvent*)event), 0, 0, self->button_state); return TRUE; } @@ -197,7 +217,8 @@ static void check_pointer_inside(FlView* self, GdkEvent* event) { fl_engine_send_mouse_pointer_event( self->engine, kAdd, gdk_event_get_time(event) * kMicrosecondsPerMillisecond, - x * scale_factor, y * scale_factor, 0, 0, self->button_state); + x * scale_factor, y * scale_factor, get_device_kind(event), 0, 0, + self->button_state); } } } @@ -320,13 +341,14 @@ static void fl_view_scrolling_delegate_iface_init( FlScrollingViewDelegateInterface* iface) { iface->send_mouse_pointer_event = [](FlScrollingViewDelegate* view_delegate, FlutterPointerPhase phase, - size_t timestamp, double x, double y, double scroll_delta_x, + size_t timestamp, double x, double y, + FlutterPointerDeviceKind device_kind, double scroll_delta_x, double scroll_delta_y, int64_t buttons) { FlView* self = FL_VIEW(view_delegate); if (self->engine != nullptr) { fl_engine_send_mouse_pointer_event(self->engine, phase, timestamp, x, - y, scroll_delta_x, scroll_delta_y, - buttons); + y, device_kind, scroll_delta_x, + scroll_delta_y, buttons); } }; iface->send_pointer_pan_zoom_event = @@ -413,7 +435,8 @@ static gboolean motion_notify_event_cb(FlView* self, fl_engine_send_mouse_pointer_event( self->engine, self->button_state != 0 ? kMove : kHover, event_time * kMicrosecondsPerMillisecond, event_x * scale_factor, - event_y * scale_factor, 0, 0, self->button_state); + event_y * scale_factor, get_device_kind((GdkEvent*)event), 0, 0, + self->button_state); return TRUE; } @@ -456,8 +479,8 @@ static gboolean leave_notify_event_cb(FlView* self, gint scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(self)); fl_engine_send_mouse_pointer_event( self->engine, kRemove, event_time * kMicrosecondsPerMillisecond, - event_x * scale_factor, event_y * scale_factor, 0, 0, - self->button_state); + event_x * scale_factor, event_y * scale_factor, + get_device_kind((GdkEvent*)event), 0, 0, self->button_state); self->pointer_inside = FALSE; }