From d906453916469769e68a2b35345813aa66737e7e Mon Sep 17 00:00:00 2001 From: Jan Dolinar Date: Tue, 18 Oct 2022 06:50:08 +0200 Subject: [PATCH] Fix go to symbol definition popup location --- src/callbacks.c | 2 +- src/editor.c | 2 +- src/msgwindow.c | 6 ++-- src/notebook.c | 2 +- src/plugins.c | 2 +- src/prefs.c | 2 +- src/sidebar.c | 6 ++-- src/symbols.c | 80 +------------------------------------------- src/ui_utils.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/ui_utils.h | 2 +- src/vte.c | 2 +- 11 files changed, 112 insertions(+), 95 deletions(-) diff --git a/src/callbacks.c b/src/callbacks.c index 59ff7b8d5..0190a5178 100644 --- a/src/callbacks.c +++ b/src/callbacks.c @@ -634,7 +634,7 @@ gboolean toolbar_popup_menu(GtkWidget *widget, GdkEventButton *event, gpointer u { if (event->button == 3) { - ui_menu_popup(GTK_MENU(ui_widgets.toolbar_menu), NULL, NULL, event->button, event->time); + ui_menu_popup(GTK_MENU(ui_widgets.toolbar_menu), NULL, event->button, event->time); return TRUE; } return FALSE; diff --git a/src/editor.c b/src/editor.c index d9da8a38a..7484fa0a0 100644 --- a/src/editor.c +++ b/src/editor.c @@ -346,7 +346,7 @@ static gboolean on_editor_button_press_event(GtkWidget *widget, GdkEventButton * g_signal_emit_by_name(geany_object, "update-editor-menu", current_word, editor_info.click_pos, doc); - ui_menu_popup(GTK_MENU(main_widgets.editor_menu), NULL, NULL, event->button, event->time); + ui_menu_popup(GTK_MENU(main_widgets.editor_menu), NULL, event->button, event->time); return TRUE; } return FALSE; diff --git a/src/msgwindow.c b/src/msgwindow.c index ce706cc45..a4fc8c8dc 100644 --- a/src/msgwindow.c +++ b/src/msgwindow.c @@ -1236,19 +1236,19 @@ static gboolean on_msgwin_button_press_event(GtkWidget *widget, GdkEventButton * { case MSG_STATUS: { - ui_menu_popup(GTK_MENU(msgwindow.popup_status_menu), NULL, NULL, + ui_menu_popup(GTK_MENU(msgwindow.popup_status_menu), NULL, event->button, event->time); break; } case MSG_MESSAGE: { - ui_menu_popup(GTK_MENU(msgwindow.popup_msg_menu), NULL, NULL, + ui_menu_popup(GTK_MENU(msgwindow.popup_msg_menu), NULL, event->button, event->time); break; } case MSG_COMPILER: { - ui_menu_popup(GTK_MENU(msgwindow.popup_compiler_menu), NULL, NULL, + ui_menu_popup(GTK_MENU(msgwindow.popup_compiler_menu), NULL, event->button, event->time); break; } diff --git a/src/notebook.c b/src/notebook.c index c645ac637..7e035739c 100644 --- a/src/notebook.c +++ b/src/notebook.c @@ -512,7 +512,7 @@ static void show_tab_bar_popup_menu(GdkEventButton *event, GeanyDocument *doc) gtk_container_add(GTK_CONTAINER(menu), menu_item); g_signal_connect(menu_item, "activate", G_CALLBACK(on_close_all1_activate), NULL); - ui_menu_popup(GTK_MENU(menu), NULL, NULL, event->button, event->time); + ui_menu_popup(GTK_MENU(menu), NULL, event->button, event->time); } diff --git a/src/plugins.c b/src/plugins.c index 8f952d2ba..d509bfa36 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -1642,7 +1642,7 @@ static gboolean pm_treeview_button_press_cb(GtkWidget *widget, GdkEventButton *e { if (event->button == 3) { - ui_menu_popup(GTK_MENU(pm_widgets.popup_menu), NULL, NULL, + ui_menu_popup(GTK_MENU(pm_widgets.popup_menu), NULL, event->button, event->time); } return FALSE; diff --git a/src/prefs.c b/src/prefs.c index 4489acb3a..ecabbd70e 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -247,7 +247,7 @@ static void kb_show_popup_menu(KbData *kbdata, GtkWidget *widget, GdkEventButton event_time = gtk_get_current_event_time(); } - ui_menu_popup(GTK_MENU(menu), NULL, NULL, button, event_time); + ui_menu_popup(GTK_MENU(menu), NULL, button, event_time); } diff --git a/src/sidebar.c b/src/sidebar.c index b47cf0f0c..2c7d568b5 100644 --- a/src/sidebar.c +++ b/src/sidebar.c @@ -145,7 +145,7 @@ on_default_tag_tree_button_press_event(GtkWidget *widget, GdkEventButton *event, { if (event->button == 3) { - ui_menu_popup(GTK_MENU(tv.popup_taglist), NULL, NULL, event->button, event->time); + ui_menu_popup(GTK_MENU(tv.popup_taglist), NULL, event->button, event->time); return TRUE; } return FALSE; @@ -1513,12 +1513,12 @@ static gboolean sidebar_button_press_cb(GtkWidget *widget, GdkEventButton *event /* update menu item sensitivity */ documents_menu_update(selection); - ui_menu_popup(GTK_MENU(openfiles_popup_menu), NULL, NULL, + ui_menu_popup(GTK_MENU(openfiles_popup_menu), NULL, event->button, event->time); } else { - ui_menu_popup(GTK_MENU(tv.popup_taglist), NULL, NULL, + ui_menu_popup(GTK_MENU(tv.popup_taglist), NULL, event->button, event->time); } handled = TRUE; diff --git a/src/symbols.c b/src/symbols.c index 720e792c0..c1a3539b6 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -1408,84 +1408,6 @@ static guint get_tag_class(const TMTag *tag) } -/* positions a popup at the caret from the ScintillaObject in @p data */ -static void goto_popup_position_func(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data) -{ - gint line_height; - GdkScreen *screen = gtk_widget_get_screen(GTK_WIDGET(menu)); - gint monitor_num; - GdkRectangle monitor; - GtkRequisition req; - GdkEventButton *event_button = g_object_get_data(G_OBJECT(menu), "geany-button-event"); - - if (event_button) - { - /* if we got a mouse click, popup at that position */ - *x = (gint) event_button->x_root; - *y = (gint) event_button->y_root; - line_height = 0; /* we don't want to offset below the line or anything */ - } - else /* keyboard positioning */ - { - ScintillaObject *sci = data; - GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(sci)); - gint pos = sci_get_current_position(sci); - gint line = sci_get_line_from_position(sci, pos); - gint pos_x = SSM(sci, SCI_POINTXFROMPOSITION, 0, pos); - gint pos_y = SSM(sci, SCI_POINTYFROMPOSITION, 0, pos); - - line_height = SSM(sci, SCI_TEXTHEIGHT, line, 0); - - gdk_window_get_origin(window, x, y); - *x += pos_x; - *y += pos_y; - } - - monitor_num = gdk_screen_get_monitor_at_point(screen, *x, *y); - - gtk_widget_get_preferred_size(GTK_WIDGET(menu), NULL, &req); - -#if GTK_CHECK_VERSION(3, 4, 0) - gdk_screen_get_monitor_workarea(screen, monitor_num, &monitor); -#else - gdk_screen_get_monitor_geometry(screen, monitor_num, &monitor); -#endif - - /* put on one size of the X position, but within the monitor */ - if (gtk_widget_get_direction(GTK_WIDGET(menu)) == GTK_TEXT_DIR_RTL) - { - if (*x - req.width - 1 >= monitor.x) - *x -= req.width + 1; - else if (*x + req.width > monitor.x + monitor.width) - *x = monitor.x; - else - *x += 1; - } - else - { - if (*x + req.width + 1 <= monitor.x + monitor.width) - *x = MAX(monitor.x, *x + 1); - else if (*x - req.width - 1 >= monitor.x) - *x -= req.width + 1; - else - *x = monitor.x + MAX(0, monitor.width - req.width); - } - - /* try to put, in order: - * 1. below the Y position, under the line - * 2. above the Y position - * 3. within the monitor */ - if (*y + line_height + req.height <= monitor.y + monitor.height) - *y = MAX(monitor.y, *y + line_height); - else if (*y - req.height >= monitor.y) - *y = *y - req.height; - else - *y = monitor.y + MAX(0, monitor.height - req.height); - - *push_in = FALSE; -} - - static void show_goto_popup(GeanyDocument *doc, GPtrArray *tags, gboolean have_best) { GtkWidget *first = NULL; @@ -1566,7 +1488,7 @@ static void show_goto_popup(GeanyDocument *doc, GPtrArray *tags, gboolean have_b g_object_set_data_full(G_OBJECT(menu), "geany-button-event", button_event, button_event ? (GDestroyNotify) gdk_event_free : NULL); - ui_menu_popup(GTK_MENU(menu), goto_popup_position_func, doc->editor->sci, + ui_menu_popup(GTK_MENU(menu), doc->editor->sci, button_event ? button_event->button : 0, gtk_get_current_event_time ()); g_object_unref(group); diff --git a/src/ui_utils.c b/src/ui_utils.c index 498a2e554..843dff6c8 100644 --- a/src/ui_utils.c +++ b/src/ui_utils.c @@ -3258,14 +3258,109 @@ gboolean ui_encodings_combo_box_set_active_encoding(GtkComboBox *combo, gint enc return FALSE; } -void ui_menu_popup(GtkMenu* menu, GtkMenuPositionFunc func, gpointer data, guint button, guint32 activate_time) + +#if GTK_CHECK_VERSION(3,22,0) +/* positions a popup at the caret from the ScintillaObject in @p data */ +static void position_at_caret(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data) +{ + gint line_height; + GdkScreen *screen = gtk_widget_get_screen(GTK_WIDGET(menu)); + gint monitor_num; + GdkRectangle monitor; + GtkRequisition req; + GdkEventButton *event_button = g_object_get_data(G_OBJECT(menu), "geany-button-event"); + + if (event_button) + { + /* if we got a mouse click, popup at that position */ + *x = (gint) event_button->x_root; + *y = (gint) event_button->y_root; + line_height = 0; /* we don't want to offset below the line or anything */ + } + else /* keyboard positioning */ + { + ScintillaObject *sci = data; + GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(sci)); + gint pos = sci_get_current_position(sci); + gint line = sci_get_line_from_position(sci, pos); + gint pos_x = SSM(sci, SCI_POINTXFROMPOSITION, 0, pos); + gint pos_y = SSM(sci, SCI_POINTYFROMPOSITION, 0, pos); + + line_height = SSM(sci, SCI_TEXTHEIGHT, line, 0); + + gdk_window_get_origin(window, x, y); + *x += pos_x; + *y += pos_y; + } + + monitor_num = gdk_screen_get_monitor_at_point(screen, *x, *y); + + gtk_widget_get_preferred_size(GTK_WIDGET(menu), NULL, &req); + +#if GTK_CHECK_VERSION(3, 4, 0) + gdk_screen_get_monitor_workarea(screen, monitor_num, &monitor); +#else + gdk_screen_get_monitor_geometry(screen, monitor_num, &monitor); +#endif + + /* put on one size of the X position, but within the monitor */ + if (gtk_widget_get_direction(GTK_WIDGET(menu)) == GTK_TEXT_DIR_RTL) + { + if (*x - req.width - 1 >= monitor.x) + *x -= req.width + 1; + else if (*x + req.width > monitor.x + monitor.width) + *x = monitor.x; + else + *x += 1; + } + else + { + if (*x + req.width + 1 <= monitor.x + monitor.width) + *x = MAX(monitor.x, *x + 1); + else if (*x - req.width - 1 >= monitor.x) + *x -= req.width + 1; + else + *x = monitor.x + MAX(0, monitor.width - req.width); + } + + /* try to put, in order: + * 1. below the Y position, under the line + * 2. above the Y position + * 3. within the monitor */ + if (*y + line_height + req.height <= monitor.y + monitor.height) + *y = MAX(monitor.y, *y + line_height); + else if (*y - req.height >= monitor.y) + *y = *y - req.height; + else + *y = monitor.y + MAX(0, monitor.height - req.height); + + *push_in = FALSE; +} +#endif + + +/* opens menu at caret position (if ScintillaObject is passed) or at current pointer position */ +void ui_menu_popup(GtkMenu* menu, ScintillaObject *sci, guint button, guint32 activate_time) { /* Use appropriate function for menu popup: - gtk_menu_popup_at_pointer is not available on GTK older than 3.22 - gtk_menu_popup is deprecated and causes issues on multimonitor wayland setups */ #if GTK_CHECK_VERSION(3,22,0) - gtk_menu_popup_at_pointer(GTK_MENU(menu), NULL); + if (!sci) + gtk_menu_popup_at_pointer(GTK_MENU(menu), NULL); + else + { + GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(sci)); + gint pos = sci_get_current_position(sci); + gint line = sci_get_line_from_position(sci, pos); + gint line_height = SSM(sci, SCI_TEXTHEIGHT, line, 0); + gint x = SSM(sci, SCI_POINTXFROMPOSITION, 0, pos); + gint y = SSM(sci, SCI_POINTYFROMPOSITION, 0, pos) + line_height; + GdkRectangle rect = {x, y, 0, 0}; + GdkGravity rect_anchor = gtk_widget_get_direction(GTK_WIDGET(menu)) == GTK_TEXT_DIR_RTL ? GDK_GRAVITY_NORTH_EAST : GDK_GRAVITY_NORTH_WEST; + gtk_menu_popup_at_rect(GTK_MENU(menu), window, &rect, rect_anchor, GDK_GRAVITY_NORTH_WEST, NULL); + } #else - gtk_menu_popup(GTK_MENU(menu), NULL, NULL, func, data, button, activate_time); + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, sci ? position_at_caret : NULL, sci, button, activate_time); #endif } diff --git a/src/ui_utils.h b/src/ui_utils.h index 7c46fa4a9..4ef7625fa 100644 --- a/src/ui_utils.h +++ b/src/ui_utils.h @@ -373,7 +373,7 @@ gchar *ui_get_project_directory(const gchar *path); void ui_menu_sort_by_label(GtkMenu *menu); -void ui_menu_popup(GtkMenu* menu, GtkMenuPositionFunc func, gpointer data, guint button, guint32 activate_time); +void ui_menu_popup(GtkMenu* menu, ScintillaObject *sci, guint button, guint32 activate_time); #endif /* GEANY_PRIVATE */ diff --git a/src/vte.c b/src/vte.c index 74bc8900c..e493eb7aa 100644 --- a/src/vte.c +++ b/src/vte.c @@ -526,7 +526,7 @@ static gboolean vte_button_pressed(GtkWidget *widget, GdkEventButton *event, gpo if (event->button == 3) { gtk_widget_grab_focus(vte_config.vte); - ui_menu_popup(GTK_MENU(vte_config.menu), NULL, NULL, event->button, event->time); + ui_menu_popup(GTK_MENU(vte_config.menu), NULL, event->button, event->time); return TRUE; } else if (event->button == 2) -- 2.11.4.GIT