From 303d61e9c2c336bb7b5fba6fbe46cd1b92785c7c Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sat, 1 Jun 2024 21:27:51 +0800 Subject: [PATCH] Improve touch-screen support on PGTK * lisp/touch-screen.el (touch-screen-translate-touch): Do not prepend posn if the symbol is such that keyboard.c will do so immediately after returning. * src/pgtkterm.c (pgtk_toolkit_position): Remove mistakenly ported code. (pgtk_create_terminal): Remove toolkit_position hook. (motion_notify_event, button_event): Ignore emulated pointer events, and apply an additional test to circumvent a GDK oversight. (touch_event_cb): Correct return type, and provide touch sequence initialization and removal events as `last_click_event's. (cherry picked from commit 7af5d6fc9a352d4f53f8e48a6bc9ae9a3bf235a3) --- lisp/touch-screen.el | 9 +++++- src/pgtkterm.c | 66 +++++++++++++++++++++++--------------------- 2 files changed, 42 insertions(+), 33 deletions(-) diff --git a/lisp/touch-screen.el b/lisp/touch-screen.el index b77f3a6e07d..828810e7b33 100644 --- a/lisp/touch-screen.el +++ b/lisp/touch-screen.el @@ -1852,10 +1852,17 @@ if POSN is on a link or a button, or `mouse-1' otherwise." ;; no key events have been translated. (if event (or (and prefix (consp event) ;; Only generate virtual function keys for - ;; mouse events. + ;; mouse events... (memq (car event) '(down-mouse-1 mouse-1 mouse-2 mouse-movement)) + ;; .. and provided that Emacs has never + ;; previously encountered an event of this + ;; description, so that its `event-kind' + ;; property has yet to be initialized and + ;; keyboard.c will not understand whether and + ;; how to append a function key prefix. + (null (get (car event) 'event-kind)) ;; If this is a mode line event, then ;; generate the appropriate function key. (vector prefix event)) diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 886f115c391..49b7ea406f8 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -224,34 +224,6 @@ pgtk_regenerate_devices (struct pgtk_display_info *dpyinfo) pgtk_enumerate_devices (dpyinfo, false); } -static void -pgtk_toolkit_position (struct frame *f, int x, int y, - bool *menu_bar_p, bool *tool_bar_p) -{ - GdkRectangle test_rect; - int scale; - - y += (FRAME_MENUBAR_HEIGHT (f) - + FRAME_TOOLBAR_TOP_HEIGHT (f)); - x += FRAME_TOOLBAR_LEFT_WIDTH (f); - - if (FRAME_EXTERNAL_MENU_BAR (f)) - *menu_bar_p = (x >= 0 && x < FRAME_PIXEL_WIDTH (f) - && y >= 0 && y < FRAME_MENUBAR_HEIGHT (f)); - - if (FRAME_X_OUTPUT (f)->toolbar_widget) - { - scale = xg_get_scale (f); - test_rect.x = x / scale; - test_rect.y = y / scale; - test_rect.width = 1; - test_rect.height = 1; - - *tool_bar_p = gtk_widget_intersect (FRAME_X_OUTPUT (f)->toolbar_widget, - &test_rect, NULL); - } -} - static Lisp_Object pgtk_get_device_for_event (struct pgtk_display_info *dpyinfo, GdkEvent *event) @@ -4042,8 +4014,8 @@ xg_scroll_callback (GtkRange * range, /* Callback for button release. Sets dragging to -1 when dragging is done. */ static gboolean -xg_end_scroll_callback (GtkWidget * widget, - GdkEventButton * event, gpointer user_data) +xg_end_scroll_callback (GtkWidget *widget, + GdkEventButton *event, gpointer user_data) { struct scroll_bar *bar = user_data; bar->dragging = -1; @@ -4889,7 +4861,6 @@ pgtk_create_terminal (struct pgtk_display_info *dpyinfo) terminal->focus_frame_hook = pgtk_focus_frame; terminal->set_frame_offset_hook = pgtk_set_offset; terminal->free_pixmap = pgtk_free_pixmap; - terminal->toolkit_position_hook = pgtk_toolkit_position; /* Other hooks are NULL by default. */ @@ -5929,6 +5900,17 @@ motion_notify_event (GtkWidget *widget, GdkEvent *event, struct frame *f, *frame; struct pgtk_display_info *dpyinfo; Mouse_HLInfo *hlinfo; + GdkDevice *device; + + /* Ignore emulated pointer events generated from a touch screen + event. */ + if (gdk_event_get_pointer_emulated (event) + /* The event must not have emerged from a touch device either, as + GDK does not set pointer_emulated in events generated on + Wayland as on X, and as the X Input Extension specifies. */ + || ((device = gdk_event_get_source_device (event)) + && (gdk_device_get_source (device) == GDK_SOURCE_TOUCHSCREEN))) + return FALSE; EVENT_INIT (inev.ie); inev.ie.kind = NO_EVENT; @@ -6068,6 +6050,17 @@ button_event (GtkWidget *widget, GdkEvent *event, bool tab_bar_p = false; bool tool_bar_p = false; Lisp_Object tab_bar_arg = Qnil; + GdkDevice *device; + + /* Ignore emulated pointer events generated from a touch screen + event. */ + if (gdk_event_get_pointer_emulated (event) + /* The event must not have emerged from a touch device either, as + GDK does not set pointer_emulated in events generated on + Wayland as on X, and as the X Input Extension specifies. */ + || ((device = gdk_event_get_source_device (event)) + && (gdk_device_get_source (device) == GDK_SOURCE_TOUCHSCREEN))) + return FALSE; EVENT_INIT (inev.ie); inev.ie.kind = NO_EVENT; @@ -6642,7 +6635,7 @@ pgtk_find_touch_point (struct pgtk_display_info *dpyinfo, return NULL; } -static bool +static gboolean touch_event_cb (GtkWidget *self, GdkEvent *event, gpointer user_data) { struct pgtk_display_info *dpyinfo; @@ -6742,6 +6735,15 @@ touch_event_cb (GtkWidget *self, GdkEvent *event, gpointer user_data) { inev.ie.device = pgtk_get_device_for_event (dpyinfo, event); evq_enqueue (&inev); + + /* Next, save this event for future menu activations, unless it is + only an update. */ + if (event->type != GDK_TOUCH_UPDATE) + { + if (dpyinfo->last_click_event != NULL) + gdk_event_free (dpyinfo->last_click_event); + dpyinfo->last_click_event = gdk_event_copy (event); + } } return inev.ie.kind != NO_EVENT; -- 2.39.2