From 68e293c81d8ef687500969461067dc774353968f Mon Sep 17 00:00:00 2001 From: Po Lu Date: Wed, 2 Mar 2022 19:00:21 +0800 Subject: [PATCH] Fix reporting of imaginary key prefixes on toolkit tool and menu bars * src/keyboard.c (make_lispy_position): Set imaginary prefix if the terminal says what widget the position is on top of. * src/termhooks.h (struct terminal): New field `toolkit_position_hook'. * src/xterm.c (x_toolkit_position): New function. (x_create_terminal): Register hook. --- src/keyboard.c | 16 ++++++++++++++++ src/termhooks.h | 7 +++++++ src/xterm.c | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/src/keyboard.c b/src/keyboard.c index da8c6c54d85..218f9a86c86 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -5247,6 +5247,8 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, Lisp_Object window_or_frame = f ? window_from_coordinates (f, mx, my, &part, true, true) : Qnil; + bool tool_bar_p = false; + bool menu_bar_p = false; /* Report mouse events on the tab bar and (on GUI frames) on the tool bar. */ @@ -5280,6 +5282,20 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, coordinates. FIXME! */ window_or_frame = Qnil; } + + if (FRAME_TERMINAL (f)->toolkit_position_hook) + { + FRAME_TERMINAL (f)->toolkit_position_hook (f, mx, my, &menu_bar_p, + &tool_bar_p); + + if (NILP (track_mouse) || EQ (track_mouse, Qt)) + { + if (menu_bar_p) + posn = Qmenu_bar; + else if (tool_bar_p) + posn = Qtool_bar; + } + } #endif if (f && !FRAME_WINDOW_P (f) diff --git a/src/termhooks.h b/src/termhooks.h index b7696fed4f8..8fb4837ee57 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -831,6 +831,13 @@ struct terminal frames on the terminal when it calls this hook, so infinite recursion is prevented. */ void (*delete_terminal_hook) (struct terminal *); + + /* Called to determine whether a position is on the toolkit tool bar + or menu bar. May be NULL. It should accept five arguments + FRAME, X, Y, MENU_BAR_P, TOOL_BAR_P, and store true into + `menu_bar_p' if X and Y are in FRAME's toolkit menu bar, and true + into `tool_bar_p` if X and Y are in FRAME's toolkit tool bar. */ + void (*toolkit_position_hook) (struct frame *, int, int, bool *, bool *); } GCALIGNED_STRUCT; INLINE bool diff --git a/src/xterm.c b/src/xterm.c index 3f693004172..9960f4930d2 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -854,6 +854,41 @@ record_event (char *locus, int type) #endif +#if defined USE_X_TOOLKIT || USE_GTK +static void +x_toolkit_position (struct frame *f, int x, int y, + bool *menu_bar_p, bool *tool_bar_p) +{ +#ifdef USE_GTK + 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); + } +#else + *menu_bar_p = (x > 0 && x < FRAME_PIXEL_WIDTH (f) + && (y < 0 && y >= -FRAME_MENUBAR_HEIGHT (f))); +#endif +} +#endif + static void x_update_opaque_region (struct frame *f, XEvent *configure) { @@ -17820,6 +17855,9 @@ x_create_terminal (struct x_display_info *dpyinfo) terminal->free_pixmap = x_free_pixmap; terminal->delete_frame_hook = x_destroy_window; terminal->delete_terminal_hook = x_delete_terminal; +#if defined USE_X_TOOLKIT || defined USE_GTK + terminal->toolkit_position_hook = x_toolkit_position; +#endif /* Other hooks are NULL by default. */ return terminal; -- 2.39.5