Fix #457642, reported by Christian Persch.

2007-08-21  Kristian Rietveld  <kris@imendio.com>

	Fix #457642, reported by Christian Persch.

	* gtk/gtktooltip.c: added debugging output which can be compiled
	in with a #define, annotated all coordinate translations in the
	source code,
	(find_widget_under_pointer): remove the "no-window correction";
	always convert the coordinates from window relative to allocation
	relative; after recursing through a container, translate the
	coordinates from container allocation relative to child widget
	allocation relative;
	(find_topmost_widget_from_event): now we get allocation relative
	coordinates here we do not have to distinguish no-window and window
	widgets.


svn path=/trunk/; revision=18663
This commit is contained in:
Kristian Rietveld 2007-08-21 10:52:43 +00:00 committed by Kristian Rietveld
parent cefd6732fc
commit f6235caef9
2 changed files with 96 additions and 24 deletions

View File

@ -1,3 +1,19 @@
2007-08-21 Kristian Rietveld <kris@imendio.com>
Fix #457642, reported by Christian Persch.
* gtk/gtktooltip.c: added debugging output which can be compiled
in with a #define, annotated all coordinate translations in the
source code,
(find_widget_under_pointer): remove the "no-window correction";
always convert the coordinates from window relative to allocation
relative; after recursing through a container, translate the
coordinates from container allocation relative to child widget
allocation relative;
(find_topmost_widget_from_event): now we get allocation relative
coordinates here we do not have to distinguish no-window and window
widgets.
2007-08-18 Cody Russell <bratsche@gnome.org>
* gtk/gtkimcontextsimple.c: Fixed incorrect compose mapping

View File

@ -33,6 +33,8 @@
#include <string.h>
#undef DEBUG_TOOLTIP
#define GTK_TOOLTIP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_TOOLTIP, GtkTooltipClass))
#define GTK_IS_TOOLTIP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_TOOLTIP))
@ -456,11 +458,27 @@ child_location_foreach (GtkWidget *child,
if (!GTK_WIDGET_DRAWABLE (child))
return;
/* (child_loc->x, child_loc->y) are relative to
* child_loc->container's allocation.
*/
if (!child_loc->child &&
gtk_widget_translate_coordinates (child_loc->container, child,
child_loc->x, child_loc->y,
&x, &y))
{
#ifdef DEBUG_TOOLTIP
g_print ("candidate: %s alloc=[(%d,%d) %dx%d] (%d, %d)->(%d, %d)\n",
gtk_widget_get_name (child),
child->allocation.x,
child->allocation.y,
child->allocation.width,
child->allocation.height,
child_loc->x, child_loc->y,
x, y);
#endif /* DEBUG_TOOLTIP */
/* (x, y) relative to child's allocation. */
if (x >= 0 && x < child->allocation.width
&& y >= 0 && y < child->allocation.height)
{
@ -468,6 +486,9 @@ child_location_foreach (GtkWidget *child,
{
struct ChildLocation tmp = { NULL, NULL, 0, 0 };
/* Take (x, y) relative the child's allocation and
* recurse.
*/
tmp.x = x;
tmp.y = y;
tmp.container = child;
@ -486,6 +507,9 @@ child_location_foreach (GtkWidget *child,
}
}
/* Translates coordinates from dest_widget->window relative (src_x, src_y),
* to allocation relative (dest_x, dest_y) of dest_widget.
*/
static void
window_to_alloc (GtkWidget *dest_widget,
gint src_x,
@ -499,6 +523,9 @@ window_to_alloc (GtkWidget *dest_widget,
gint wx, wy;
gdk_window_get_position (dest_widget->window, &wx, &wy);
/* Offset coordinates if widget->window is smaller than
* widget->allocation.
*/
src_x += wx - dest_widget->allocation.x;
src_y += wy - dest_widget->allocation.y;
}
@ -514,6 +541,9 @@ window_to_alloc (GtkWidget *dest_widget,
*dest_y = src_y;
}
/* Translates coordinates from window relative (x, y) to
* allocation relative (x, y) of the returned widget.
*/
static GtkWidget *
find_widget_under_pointer (GdkWindow *window,
gint *x,
@ -527,9 +557,20 @@ find_widget_under_pointer (GdkWindow *window,
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),
*x, *y);
#endif
/* Coordinates are relative to event window */
child_loc.x = *x;
child_loc.y = *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 != event_widget->window)
{
gint px, py;
@ -541,12 +582,6 @@ find_widget_under_pointer (GdkWindow *window,
window = gdk_window_get_parent (window);
}
if (GTK_WIDGET_NO_WINDOW (event_widget))
{
child_loc.x += event_widget->allocation.x;
child_loc.y += event_widget->allocation.y;
}
/* 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.
@ -555,11 +590,16 @@ find_widget_under_pointer (GdkWindow *window,
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))
{
window_to_alloc (event_widget,
child_loc.x, child_loc.y,
&child_loc.x, &child_loc.y);
GtkWidget *container = event_widget;
child_loc.container = event_widget;
child_loc.child = NULL;
@ -567,12 +607,23 @@ find_widget_under_pointer (GdkWindow *window,
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 (x)
*x = child_loc.x;
if (y)
@ -581,6 +632,9 @@ find_widget_under_pointer (GdkWindow *window,
return event_widget;
}
/* Ignores (x, y) on input, translates event coordinates to
* allocation relative (x, y) of the returned widget.
*/
static GtkWidget *
find_topmost_widget_coords_from_event (GdkEvent *event,
gint *x,
@ -594,26 +648,16 @@ find_topmost_widget_coords_from_event (GdkEvent *event,
tx = dx;
ty = dy;
/* Returns coordinates relative to tmp's allocation. */
tmp = find_widget_under_pointer (event->any.window, &tx, &ty);
if (!tmp)
return NULL;
/* Make sure the pointer can actually be on the widget returned */
if (GTK_WIDGET_NO_WINDOW (tmp))
{
if (tx < tmp->allocation.x ||
tx >= tmp->allocation.x + tmp->allocation.width ||
ty < tmp->allocation.y ||
ty >= tmp->allocation.y + tmp->allocation.height)
return NULL;
}
else
{
if (tx < 0 || tx >= tmp->allocation.width ||
ty < 0 || ty >= tmp->allocation.height)
return NULL;
}
/* Make sure the pointer can actually be on the widget returned. */
if (tx < 0 || tx >= tmp->allocation.width ||
ty < 0 || ty >= tmp->allocation.height)
return NULL;
if (x)
*x = tx;
@ -1093,6 +1137,7 @@ _gtk_tooltip_handle_event (GdkEvent *event)
if (touchscreen)
return;
/* Returns coordinates relative to has_tooltip_widget's allocation. */
has_tooltip_widget = find_topmost_widget_coords_from_event (event, &x, &y);
display = gdk_drawable_get_display (event->any.window);
current_tooltip = g_object_get_data (G_OBJECT (display),
@ -1124,6 +1169,17 @@ _gtk_tooltip_handle_event (GdkEvent *event)
return;
}
#ifdef DEBUG_TOOLTIP
if (has_tooltip_widget)
g_print ("%p (%s) at (%d, %d) %dx%d pointer: (%d, %d)\n",
has_tooltip_widget, gtk_widget_get_name (has_tooltip_widget),
has_tooltip_widget->allocation.x,
has_tooltip_widget->allocation.y,
has_tooltip_widget->allocation.width,
has_tooltip_widget->allocation.height,
x, y);
#endif /* DEBUG_TOOLTIP */
/* Always poll for a next motion event */
gdk_event_request_motions (&event->motion);