summaryrefslogtreecommitdiff
path: root/gtk/gtkwidget.c
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@redhat.com>2001-10-16 21:02:24 +0000
committerOwen Taylor <otaylor@src.gnome.org>2001-10-16 21:02:24 +0000
commit1ebe3b518b7fe1ac64d96aa4ee025d6aac435442 (patch)
tree5521b85a657a92cee4289904e0f8a9dce9890190 /gtk/gtkwidget.c
parent3612439d217cfb55f1066a95f5f0ee9e2124f8c4 (diff)
downloadgtk+-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.c161
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)