diff options
author | Owen Taylor <otaylor@redhat.com> | 2001-10-16 21:02:24 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2001-10-16 21:02:24 +0000 |
commit | 1ebe3b518b7fe1ac64d96aa4ee025d6aac435442 (patch) | |
tree | 5521b85a657a92cee4289904e0f8a9dce9890190 /gtk/gtkwidget.c | |
parent | 3612439d217cfb55f1066a95f5f0ee9e2124f8c4 (diff) | |
download | gtk+-1ebe3b518b7fe1ac64d96aa4ee025d6aac435442.tar.gz |
Add a utility function to translate coordinates relative to one widget's
Tue Oct 16 15:50:03 2001 Owen Taylor <otaylor@redhat.com>
* gtk/gtkwidget.c (gtk_widget_translate_coordinates): Add
a utility function to translate coordinates relative to
one widget's allocation to coordinates relative to another
widget's allocation.
* gtk/gtkradiobutton.c: Add a special ->focus() implementation
that:
- only accepts external focus if there is no active
member of the group or the button is active.
- makes arrow keys move the active button as well
as the focus
- make tab tab out directly.
This makes a radio button group act as a single focus location.
(#53577).
* gtk/gtkcontainer.c (gtk_container_focus): Remove prefiltering -
it was only a small optimization that didn't matter and made
things more complicated.
* gtk/gtkcontainer.c (gtk_container_focus_tab): Get rid of custom
sorter for FOCUS_TAB as we did for the other focus directions,
sort by center of widgets, not upper-left corner. (Shouldn't
matter in general.)
* gtk/gtkcontainer.c: Restructure code to remove duplicate code
from the different types of focusing: encapsulate sorting the
widgets for the focus direction into one routine
(gtk_container_focus_sort()) and then share the work of moving the
focus between the different focus directions.
* gtk/gtkcontainer.c: Fix bug where arrow navigation might not
work correctly with focus chains containing non-immediate
children. Sorting was being done using allocation coordinates for
each widget in the focus chain, and if there were intermediate
window-widgets, these allocations would not be in the same
coordinate system.
Diffstat (limited to 'gtk/gtkwidget.c')
-rw-r--r-- | gtk/gtkwidget.c | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 52f0203573..882bd57f34 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -2317,6 +2317,167 @@ gtk_widget_size_allocate (GtkWidget *widget, } } +/** + * gtk_widget_common_ancestor: + * @widget_a: a #GtkWidget + * @widget_b: a #GtkWidget + * + * Find the common ancestor of @widget_a and @widget_b that + * is closest to the two widgets. + * + * Return value: the closest common ancestor of @widget_a and + * @widget_b or %NULL if @widget_a and @widget_b do not + * share a common ancestor. + **/ +static GtkWidget * +gtk_widget_common_ancestor (GtkWidget *widget_a, + GtkWidget *widget_b) +{ + GtkWidget *parent_a; + GtkWidget *parent_b; + gint depth_a = 0; + gint depth_b = 0; + + parent_a = widget_a; + while (parent_a->parent) + { + parent_a = parent_a->parent; + depth_a++; + } + + parent_b = widget_b; + while (parent_b->parent) + { + parent_b = parent_b->parent; + depth_b++; + } + + if (parent_a != parent_b) + return NULL; + + while (depth_a > depth_b) + { + widget_a = widget_a->parent; + depth_a--; + } + + while (depth_b > depth_a) + { + widget_b = widget_b->parent; + depth_b--; + } + + while (widget_a != widget_b) + { + widget_a = widget_a->parent; + widget_b = widget_b->parent; + } + + return widget_a; +} + +/** + * gtk_widget_translate_coordinates: + * @src_widget: a #GtkWidget + * @dest_widget: a #GtkWidget + * @src_x: X position relative to @src_widget + * @src_y: Y position relative to @src_widget + * @dest_x: location to store X position relative to @dest_widget + * @dest_y: location to store Y position relative to @dest_widget + * + * Translate coordinates relative to @src_widget's allocation to coordinates + * relative to @dest_widget's allocations. In order to perform this + * operation, both widgets must be realized, and must share a common + * toplevel. + * + * Return value: %FALSE if either widget was not realized, or there + * was no common ancestor. In this case, nothing is stored in + * *@dest_x and *@dest_y. Otherwise %TRUE. + **/ +gboolean +gtk_widget_translate_coordinates (GtkWidget *src_widget, + GtkWidget *dest_widget, + gint src_x, + gint src_y, + gint *dest_x, + gint *dest_y) +{ + GtkWidget *ancestor; + GdkWindow *window; + + g_return_if_fail (GTK_IS_WIDGET (src_widget)); + g_return_if_fail (GTK_IS_WIDGET (dest_widget)); + + ancestor = gtk_widget_common_ancestor (src_widget, dest_widget); + if (!ancestor || !GTK_WIDGET_REALIZED (src_widget) || !GTK_WIDGET_REALIZED (dest_widget)) + return FALSE; + + /* Translate from allocation relative to window relative */ + if (!GTK_WIDGET_NO_WINDOW (src_widget) && src_widget->parent) + { + gint wx, wy; + gdk_window_get_position (src_widget->window, &wx, &wy); + + src_x -= wx - src_widget->allocation.x; + src_y -= wy - src_widget->allocation.y; + } + else + { + src_x += src_widget->allocation.x; + src_y += src_widget->allocation.y; + } + + /* Translate to the common ancestor */ + window = src_widget->window; + while (window != ancestor->window) + { + gint dx, dy; + + gdk_window_get_position (window, &dx, &dy); + + src_x += dx; + src_y += dy; + + window = gdk_window_get_parent (window); + } + + /* And back */ + window = dest_widget->window; + while (window != ancestor->window) + { + gint dx, dy; + + gdk_window_get_position (window, &dx, &dy); + + src_x -= dx; + src_y -= dy; + + window = gdk_window_get_parent (window); + } + + /* Translate from window relative to allocation relative */ + if (!GTK_WIDGET_NO_WINDOW (dest_widget) && dest_widget->parent) + { + gint wx, wy; + gdk_window_get_position (dest_widget->window, &wx, &wy); + + src_x += wx - dest_widget->allocation.x; + src_y += wy - dest_widget->allocation.y; + } + else + { + src_x -= dest_widget->allocation.x; + src_y -= dest_widget->allocation.y; + } + + if (dest_x) + *dest_x = src_x; + if (dest_y) + *dest_y = src_y; + + return TRUE; +} + static void gtk_widget_real_size_allocate (GtkWidget *widget, GtkAllocation *allocation) |