/* Returns TRUE if a translation should be done */ static gboolean gtk_widget_get_translation_to_window (GtkWidget *widget, GdkWindow *window, int *x, int *y) { GdkWindow *w, *widget_window; if (! gtk_widget_get_has_window (widget)) { GtkAllocation allocation; gtk_widget_get_allocation (widget, &allocation); *x = -allocation.x; *y = -allocation.y; } else { *x = 0; *y = 0; } widget_window = gtk_widget_get_window (widget); for (w = window; w && w != widget_window; w = gdk_window_get_effective_parent (w)) { gdouble px, py; gdk_window_coords_to_parent (w, *x, *y, &px, &py); *x += px; *y += py; } if (w == NULL) { *x = 0; *y = 0; return FALSE; } return TRUE; }
/* Translates coordinates from window relative (x, y) to * allocation relative (x, y) of the returned widget. */ GtkWidget * _gtk_widget_find_at_coords (GdkWindow *window, gint window_x, gint window_y, gint *widget_x, gint *widget_y) { GtkWidget *event_widget; struct ChildLocation child_loc = { NULL, NULL, 0, 0 }; g_return_val_if_fail (GDK_IS_WINDOW (window), NULL); gdk_window_get_user_data (window, (void **)&event_widget); if (!event_widget) return NULL; #ifdef DEBUG_TOOLTIP g_print ("event window %p (belonging to %p (%s)) (%d, %d)\n", window, event_widget, gtk_widget_get_name (event_widget), window_x, window_y); #endif /* Coordinates are relative to event window */ child_loc.x = window_x; child_loc.y = window_y; /* We go down the window hierarchy to the widget->window, * coordinates stay relative to the current window. * We end up with window == widget->window, coordinates relative to that. */ while (window && window != gtk_widget_get_window (event_widget)) { gdouble px, py; gdk_window_coords_to_parent (window, child_loc.x, child_loc.y, &px, &py); child_loc.x = px; child_loc.y = py; window = gdk_window_get_effective_parent (window); } /* Failing to find widget->window can happen for e.g. a detached handle box; * chaining ::query-tooltip up to its parent probably makes little sense, * and users better implement tooltips on handle_box->child. * so we simply ignore the event for tooltips here. */ if (!window) return NULL; /* Convert the window relative coordinates to allocation * relative coordinates. */ window_to_alloc (event_widget, child_loc.x, child_loc.y, &child_loc.x, &child_loc.y); if (GTK_IS_CONTAINER (event_widget)) { GtkWidget *container = event_widget; child_loc.container = event_widget; child_loc.child = NULL; gtk_container_forall (GTK_CONTAINER (event_widget), child_location_foreach, &child_loc); /* Here we have a widget, with coordinates relative to * child_loc.container's allocation. */ if (child_loc.child) event_widget = child_loc.child; else if (child_loc.container) event_widget = child_loc.container; /* Translate to event_widget's allocation */ gtk_widget_translate_coordinates (container, event_widget, child_loc.x, child_loc.y, &child_loc.x, &child_loc.y); } /* We return (x, y) relative to the allocation of event_widget. */ if (widget_x) *widget_x = child_loc.x; if (widget_y) *widget_y = child_loc.y; return event_widget; }