From 746da37c4d569c024c3b92a6b198eaa50b5368fe Mon Sep 17 00:00:00 2001 From: Thierry Bultel Date: Mon, 27 Sep 2021 14:00:16 +0200 Subject: [PATCH] Fix missing mouse events when using gesture events in wxGTK When touch events were enabled, normal mouse move and click events were not generated any longer. Fix this by doing the following two things: First, emulate the LeftDown, LeftUp, and Motion events, that are no longer triggered when using the "touch-event". In addition, remove GDK_BUTTON1_MASK in the press callback, that is never set when using a mouse, but that is set for some reason by GTK when using a touchscreen. See https://github.com/wxWidgets/wxWidgets/pull/2539 Closes #19265. Signed-off-by: Thierry Bultel --- src/gtk/window.cpp | 94 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index ba59cb5cdd..b9fc42d760 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -1594,6 +1594,13 @@ gtk_window_button_press_callback( GtkWidget* WXUNUSED_IN_GTK3(widget), GdkEventButton *gdk_event, wxWindowGTK *win ) { + /* + GTK does not set the button1 mask when the event comes from the left + button of a mouse. but for some reason, it sets it when the event comes + from a touchscreen, so we simply remove it here for consistency. + */ + gdk_event->state &= ~GDK_BUTTON1_MASK; + wxPROCESS_EVENT_ONCE(GdkEventButton, gdk_event); wxCOMMON_CALLBACK_PROLOGUE(gdk_event, win); @@ -3371,9 +3378,91 @@ wxEmitPressAndTapEvent(GdkEventTouch* gdk_event, wxWindow* win) win->GTKProcessEvent(event); } +namespace +{ + +template +void +wxEventMouseFromEventTouch(EventType* event, + const GdkEventTouch* gdk_event_touch) +{ + event->window = gdk_event_touch->window; + event->send_event = gdk_event_touch->send_event; + event->time = gdk_event_touch->time; + event->x = gdk_event_touch->x; + event->y = gdk_event_touch->y; + event->axes = gdk_event_touch->axes; + event->state = gdk_event_touch->state; + event->device = gdk_event_touch->device; + event->x_root = gdk_event_touch->x_root; + event->y_root = gdk_event_touch->y_root; +} + +void +wxEventButtonFromEventTouch(GdkEventButton* gdk_event_button, + const GdkEventTouch* gdk_event_touch) +{ + wxEventMouseFromEventTouch(gdk_event_button, gdk_event_touch); + + gdk_event_button->type = GDK_BUTTON_PRESS; + gdk_event_button->button = 1; // left button +} + +void +wxEventMotionFromEventTouch(GdkEventMotion* gdk_event_motion, + const GdkEventTouch* gdk_event_touch) +{ + wxEventMouseFromEventTouch(gdk_event_motion, gdk_event_touch); + + gdk_event_motion->type = GDK_MOTION_NOTIFY; + gdk_event_motion->is_hint = true; +} + +void +wxEmulateLeftDownEvent(GtkWidget* widget, GdkEventTouch* gdk_event, wxWindow* win) +{ + GdkEventButton gdk_event_button; + + if (!gdk_event->emulating_pointer) + return; + + wxEventButtonFromEventTouch(&gdk_event_button, gdk_event); + gtk_window_button_press_callback( widget, + &gdk_event_button, + win ); +} + +void +wxEmulateLeftUpEvent(GtkWidget* widget,GdkEventTouch* gdk_event, wxWindow* win) +{ + GdkEventButton gdk_event_button; + + if (!gdk_event->emulating_pointer) + return; + + wxEventButtonFromEventTouch(&gdk_event_button, gdk_event); + gtk_window_button_release_callback( widget, + &gdk_event_button, + win ); +} + +void +wxEmulateMotionEvent(GtkWidget* widget, GdkEventTouch* gdk_event, wxWindow* win) +{ + GdkEventMotion gdk_event_motion; + + if (!gdk_event->emulating_pointer) + return; + + wxEventMotionFromEventTouch(&gdk_event_motion, gdk_event); + gtk_window_motion_notify_callback(widget, &gdk_event_motion, win); +} + +} // anonymous namespace + extern "C" { static void -touch_callback(GtkWidget* WXUNUSED(widget), GdkEventTouch* gdk_event, wxWindow* win) +touch_callback(GtkWidget* widget, GdkEventTouch* gdk_event, wxWindow* win) { wxWindowGesturesData* const data = wxWindowGestures::FromObject(win); if ( !data ) @@ -3382,6 +3471,7 @@ touch_callback(GtkWidget* WXUNUSED(widget), GdkEventTouch* gdk_event, wxWindow* switch ( gdk_event->type ) { case GDK_TOUCH_BEGIN: + wxEmulateLeftDownEvent(widget, gdk_event, win); data->m_touchCount++; data->m_allowedGestures &= ~two_finger_tap; @@ -3411,6 +3501,7 @@ touch_callback(GtkWidget* WXUNUSED(widget), GdkEventTouch* gdk_event, wxWindow* break; case GDK_TOUCH_UPDATE: + wxEmulateMotionEvent(widget, gdk_event, win); // If press and tap gesture is active and touch corresponding to that gesture is moving if ( (data->m_activeGestures & press_and_tap) && gdk_event->sequence == data->m_touchSequence ) { @@ -3421,6 +3512,7 @@ touch_callback(GtkWidget* WXUNUSED(widget), GdkEventTouch* gdk_event, wxWindow* case GDK_TOUCH_END: case GDK_TOUCH_CANCEL: + wxEmulateLeftUpEvent(widget, gdk_event, win); data->m_touchCount--; if ( data->m_touchCount == 1 )