# HG changeset patch # User bsmith@81767d24-ef19-dc11-ae90-00e081727c95 # Date 1641224715 0 # Node ID b91bc30d0e4a4b1cbcb1518abc123b27b2623993 # Parent 4f09bf72b3919efe19f733f422f916e1b4796529 GTK4: dw_menu_popup() coordinates are relative to the parent window. The coordinates in the context events in GTK4 had been relative to the container or tree widget, causing the menu to popup in offset locations. Added a function to convert from the widget coordinate to the window. The events now pass window relative coordinates so when passed to dw_menu_popup() the menu appears in about the right location. diff -r 4f09bf72b391 -r b91bc30d0e4a gtk4/dw.c --- a/gtk4/dw.c Mon Jan 03 00:35:21 2022 +0000 +++ b/gtk4/dw.c Mon Jan 03 15:45:15 2022 +0000 @@ -990,6 +990,38 @@ return retval; } +/* Convert coordinate system from the widget to the window */ +void _dw_event_coordinates_to_window(GtkWidget *widget, double *x, double *y) +{ + GtkRoot *root = (widget && GTK_IS_WIDGET(widget)) ? gtk_widget_get_root(widget) : NULL; + + if(root && GTK_IS_WIDGET(root)) + { + GtkWidget *parent = GTK_WIDGET(root); + + /* If the parent is a window, try to use the box attached to it... */ + if(GTK_IS_WINDOW(parent)) + { + GtkWidget *box = g_object_get_data(G_OBJECT(parent), "_dw_grid"); + + if(box && GTK_IS_GRID(box)) + parent = box; + } + + graphene_point_t *treepoint = graphene_point_init(graphene_point_alloc(), (float)*x, (float)*y); + graphene_point_t *windowpoint = graphene_point_alloc(); + + if(gtk_widget_compute_point(widget, GTK_WIDGET(root), treepoint, windowpoint)) + { + *x = (double)windowpoint->x; + *y = (double)windowpoint->y; + } + + graphene_point_free(treepoint); + graphene_point_free(windowpoint); + } +} + #define _DW_DATA_TYPE_STRING 0 #define _DW_DATA_TYPE_POINTER 1 @@ -1008,7 +1040,9 @@ char *text = NULL; void *itemdata = NULL; GtkWidget *widget = work.window; - + + _dw_event_coordinates_to_window(widget, &x, &y); + /* Containers and trees are inside scrolled window widgets */ if(GTK_IS_SCROLLED_WINDOW(widget)) widget = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "_dw_user"));