GTK3: gtk_window_popup_at_widget() places popup at the wrong position if widget has window
Steps to reproduce
- Create a widget which has its own window, e.g. a
GtkDrawingArea
- Place that widget in a container somewhere not at 0,0 (e.g. place it under another one in a grid)
- Call
gtk_widget_popup_at_widget()
on that widget.
Sample program reproducing the issue
#include <stdio.h>
#include <gtk/gtk.h>
static void
item_activated (GtkMenuItem *item,
gpointer data G_GNUC_UNUSED)
{
fprintf (stderr, "Item %s activated\n", gtk_menu_item_get_label (item));
}
/* pops up a random menu using gtk_menu_popup_at_widget() */
static gboolean
popup_menu (GtkWidget *widget,
gpointer data G_GNUC_UNUSED)
{
GtkWidget *menu = gtk_menu_new ();
GtkWidget *item = gtk_menu_item_new_with_label ("Item");
g_signal_connect (item, "activate", G_CALLBACK (item_activated), NULL);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show_all (menu);
gtk_menu_popup_at_widget (GTK_MENU (menu), widget, GDK_GRAVITY_SOUTH_WEST,
GDK_GRAVITY_NORTH_WEST, NULL);
return TRUE;
}
/* just draw focus on the given widget */
static void
draw_area (GtkWidget *widget,
cairo_t *cr,
gpointer data G_GNUC_UNUSED)
{
if (gtk_widget_has_focus (widget))
{
gtk_render_focus (gtk_widget_get_style_context (widget), cr, 0, 0,
gtk_widget_get_allocated_width (widget),
gtk_widget_get_allocated_height (widget));
}
}
int
main (int argc,
char **argv)
{
gtk_init (&argc, &argv);
GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
GtkWidget *grid = gtk_grid_new ();
GtkWidget *label = gtk_label_new("gtk_menu_popup_at_widget() test");
g_signal_connect (label, "draw", G_CALLBACK (draw_area), NULL);
gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
GtkWidget *dw = gtk_drawing_area_new ();
/* Uncomment this below to fix the popup positioning */
//gtk_widget_set_has_window (dw, FALSE);
gtk_widget_set_can_focus (dw, TRUE);
gtk_widget_set_size_request (dw, 20, 20);
g_signal_connect (dw, "draw", G_CALLBACK (draw_area), NULL);
g_signal_connect (dw, "popup-menu", G_CALLBACK (popup_menu), NULL);
gtk_grid_attach (GTK_GRID (grid), dw, 0, 1, 1, 1);
gtk_container_add (GTK_CONTAINER (window), grid);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
Current behavior
- Under X11, the popup appears too far below/to the right. Effectively, the popup appears offset by its window's offset in its parent (e.g. it's origin).
- Under Wayland, the popup doesn't even pop up at all (it's not that you don't see it: focus is still in the main window, and keyboard interaction does not work as it would in the popup).
Expected outcome
The popup appears right next to the widget, following the given gravities.
Version information
3.24.38
Additional information
In the example code, uncommenting gtk_widget_set_has_window (dw, FALSE)
makes the popup appear correctly on both X11 and Wayland.