diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c index 05e0a837dc..f3cc9c83c7 100644 --- a/gtk/gtkcontainer.c +++ b/gtk/gtkcontainer.c @@ -2029,443 +2029,6 @@ gtk_container_focus (GtkWidget *widget, return return_val; } -static gint -tab_compare (gconstpointer a, - gconstpointer b, - gpointer data) -{ - GtkAllocation child1_allocation, child2_allocation; - const GtkWidget *child1 = a; - const GtkWidget *child2 = b; - GtkTextDirection text_direction = GPOINTER_TO_INT (data); - gint y1, y2; - - _gtk_widget_get_allocation ((GtkWidget *) child1, &child1_allocation); - _gtk_widget_get_allocation ((GtkWidget *) child2, &child2_allocation); - - y1 = child1_allocation.y + child1_allocation.height / 2; - y2 = child2_allocation.y + child2_allocation.height / 2; - - if (y1 == y2) - { - gint x1 = child1_allocation.x + child1_allocation.width / 2; - gint x2 = child2_allocation.x + child2_allocation.width / 2; - - if (text_direction == GTK_TEXT_DIR_RTL) - return (x1 < x2) ? 1 : ((x1 == x2) ? 0 : -1); - else - return (x1 < x2) ? -1 : ((x1 == x2) ? 0 : 1); - } - else - return (y1 < y2) ? -1 : 1; -} - -static GList * -gtk_container_focus_sort_tab (GtkContainer *container, - GList *children, - GtkDirectionType direction, - GtkWidget *old_focus) -{ - GtkTextDirection text_direction = _gtk_widget_get_direction (GTK_WIDGET (container)); - children = g_list_sort_with_data (children, tab_compare, GINT_TO_POINTER (text_direction)); - - /* if we are going backwards then reverse the order - * of the children. - */ - if (direction == GTK_DIR_TAB_BACKWARD) - children = g_list_reverse (children); - - return children; -} - -/* Get coordinates of @widget's allocation with respect to - * allocation of @container. - */ -static gboolean -get_allocation_coords (GtkContainer *container, - GtkWidget *widget, - GdkRectangle *allocation) -{ - gtk_widget_get_allocation (widget, allocation); - - return gtk_widget_translate_coordinates (widget, GTK_WIDGET (container), - 0, 0, &allocation->x, &allocation->y); -} - -/* Look for a child in @children that is intermediate between - * the focus widget and container. This widget, if it exists, - * acts as the starting widget for focus navigation. - */ -static GtkWidget * -find_old_focus (GtkContainer *container, - GList *children) -{ - GList *tmp_list = children; - while (tmp_list) - { - GtkWidget *child = tmp_list->data; - GtkWidget *widget = child; - - while (widget && widget != (GtkWidget *)container) - { - GtkWidget *parent; - - parent = _gtk_widget_get_parent (widget); - - if (parent && (gtk_widget_get_focus_child (parent) != widget)) - goto next; - - widget = parent; - } - - return child; - - next: - tmp_list = tmp_list->next; - } - - return NULL; -} - -static gboolean -old_focus_coords (GtkContainer *container, - GdkRectangle *old_focus_rect) -{ - GtkWidget *widget = GTK_WIDGET (container); - GtkWidget *toplevel = _gtk_widget_get_toplevel (widget); - GtkWidget *old_focus; - - if (GTK_IS_WINDOW (toplevel)) - { - old_focus = gtk_window_get_focus (GTK_WINDOW (toplevel)); - if (old_focus) - return get_allocation_coords (container, old_focus, old_focus_rect); - } - - return FALSE; -} - -typedef struct _CompareInfo CompareInfo; - -struct _CompareInfo -{ - GtkContainer *container; - gint x; - gint y; - gboolean reverse; -}; - -static gint -up_down_compare (gconstpointer a, - gconstpointer b, - gpointer data) -{ - GdkRectangle allocation1; - GdkRectangle allocation2; - CompareInfo *compare = data; - gint y1, y2; - - get_allocation_coords (compare->container, (GtkWidget *)a, &allocation1); - get_allocation_coords (compare->container, (GtkWidget *)b, &allocation2); - - y1 = allocation1.y + allocation1.height / 2; - y2 = allocation2.y + allocation2.height / 2; - - if (y1 == y2) - { - gint x1 = abs (allocation1.x + allocation1.width / 2 - compare->x); - gint x2 = abs (allocation2.x + allocation2.width / 2 - compare->x); - - if (compare->reverse) - return (x1 < x2) ? 1 : ((x1 == x2) ? 0 : -1); - else - return (x1 < x2) ? -1 : ((x1 == x2) ? 0 : 1); - } - else - return (y1 < y2) ? -1 : 1; -} - -static GList * -gtk_container_focus_sort_up_down (GtkContainer *container, - GList *children, - GtkDirectionType direction, - GtkWidget *old_focus) -{ - CompareInfo compare; - GList *tmp_list; - GdkRectangle old_allocation; - - compare.container = container; - compare.reverse = (direction == GTK_DIR_UP); - - if (!old_focus) - old_focus = find_old_focus (container, children); - - if (old_focus && get_allocation_coords (container, old_focus, &old_allocation)) - { - gint compare_x1; - gint compare_x2; - gint compare_y; - - /* Delete widgets from list that don't match minimum criteria */ - - compare_x1 = old_allocation.x; - compare_x2 = old_allocation.x + old_allocation.width; - - if (direction == GTK_DIR_UP) - compare_y = old_allocation.y; - else - compare_y = old_allocation.y + old_allocation.height; - - tmp_list = children; - while (tmp_list) - { - GtkWidget *child = tmp_list->data; - GList *next = tmp_list->next; - gint child_x1, child_x2; - GdkRectangle child_allocation; - - if (child != old_focus) - { - if (get_allocation_coords (container, child, &child_allocation)) - { - child_x1 = child_allocation.x; - child_x2 = child_allocation.x + child_allocation.width; - - if ((child_x2 <= compare_x1 || child_x1 >= compare_x2) /* No horizontal overlap */ || - (direction == GTK_DIR_DOWN && child_allocation.y + child_allocation.height < compare_y) || /* Not below */ - (direction == GTK_DIR_UP && child_allocation.y > compare_y)) /* Not above */ - { - children = g_list_delete_link (children, tmp_list); - } - } - else - children = g_list_delete_link (children, tmp_list); - } - - tmp_list = next; - } - - compare.x = (compare_x1 + compare_x2) / 2; - compare.y = old_allocation.y + old_allocation.height / 2; - } - else - { - /* No old focus widget, need to figure out starting x,y some other way - */ - GtkAllocation allocation; - GtkWidget *widget = GTK_WIDGET (container); - GdkRectangle old_focus_rect; - - _gtk_widget_get_allocation (widget, &allocation); - - if (old_focus_coords (container, &old_focus_rect)) - { - compare.x = old_focus_rect.x + old_focus_rect.width / 2; - } - else - { - if (!_gtk_widget_get_has_window (widget)) - compare.x = allocation.x + allocation.width / 2; - else - compare.x = allocation.width / 2; - } - - if (!_gtk_widget_get_has_window (widget)) - compare.y = (direction == GTK_DIR_DOWN) ? allocation.y : allocation.y + allocation.height; - else - compare.y = (direction == GTK_DIR_DOWN) ? 0 : + allocation.height; - } - - children = g_list_sort_with_data (children, up_down_compare, &compare); - - if (compare.reverse) - children = g_list_reverse (children); - - return children; -} - -static gint -left_right_compare (gconstpointer a, - gconstpointer b, - gpointer data) -{ - GdkRectangle allocation1; - GdkRectangle allocation2; - CompareInfo *compare = data; - gint x1, x2; - - get_allocation_coords (compare->container, (GtkWidget *)a, &allocation1); - get_allocation_coords (compare->container, (GtkWidget *)b, &allocation2); - - x1 = allocation1.x + allocation1.width / 2; - x2 = allocation2.x + allocation2.width / 2; - - if (x1 == x2) - { - gint y1 = abs (allocation1.y + allocation1.height / 2 - compare->y); - gint y2 = abs (allocation2.y + allocation2.height / 2 - compare->y); - - if (compare->reverse) - return (y1 < y2) ? 1 : ((y1 == y2) ? 0 : -1); - else - return (y1 < y2) ? -1 : ((y1 == y2) ? 0 : 1); - } - else - return (x1 < x2) ? -1 : 1; -} - -static GList * -gtk_container_focus_sort_left_right (GtkContainer *container, - GList *children, - GtkDirectionType direction, - GtkWidget *old_focus) -{ - CompareInfo compare; - GList *tmp_list; - GdkRectangle old_allocation; - - compare.container = container; - compare.reverse = (direction == GTK_DIR_LEFT); - - if (!old_focus) - old_focus = find_old_focus (container, children); - - if (old_focus && get_allocation_coords (container, old_focus, &old_allocation)) - { - gint compare_y1; - gint compare_y2; - gint compare_x; - - /* Delete widgets from list that don't match minimum criteria */ - - compare_y1 = old_allocation.y; - compare_y2 = old_allocation.y + old_allocation.height; - - if (direction == GTK_DIR_LEFT) - compare_x = old_allocation.x; - else - compare_x = old_allocation.x + old_allocation.width; - - tmp_list = children; - while (tmp_list) - { - GtkWidget *child = tmp_list->data; - GList *next = tmp_list->next; - gint child_y1, child_y2; - GdkRectangle child_allocation; - - if (child != old_focus) - { - if (get_allocation_coords (container, child, &child_allocation)) - { - child_y1 = child_allocation.y; - child_y2 = child_allocation.y + child_allocation.height; - - if ((child_y2 <= compare_y1 || child_y1 >= compare_y2) /* No vertical overlap */ || - (direction == GTK_DIR_RIGHT && child_allocation.x + child_allocation.width < compare_x) || /* Not to left */ - (direction == GTK_DIR_LEFT && child_allocation.x > compare_x)) /* Not to right */ - { - children = g_list_delete_link (children, tmp_list); - } - } - else - children = g_list_delete_link (children, tmp_list); - } - - tmp_list = next; - } - - compare.y = (compare_y1 + compare_y2) / 2; - compare.x = old_allocation.x + old_allocation.width / 2; - } - else - { - /* No old focus widget, need to figure out starting x,y some other way - */ - GtkAllocation allocation; - GtkWidget *widget = GTK_WIDGET (container); - GdkRectangle old_focus_rect; - - _gtk_widget_get_allocation (widget, &allocation); - - if (old_focus_coords (container, &old_focus_rect)) - { - compare.y = old_focus_rect.y + old_focus_rect.height / 2; - } - else - { - if (!_gtk_widget_get_has_window (widget)) - compare.y = allocation.y + allocation.height / 2; - else - compare.y = allocation.height / 2; - } - - if (!_gtk_widget_get_has_window (widget)) - compare.x = (direction == GTK_DIR_RIGHT) ? allocation.x : allocation.x + allocation.width; - else - compare.x = (direction == GTK_DIR_RIGHT) ? 0 : allocation.width; - } - - children = g_list_sort_with_data (children, left_right_compare, &compare); - - if (compare.reverse) - children = g_list_reverse (children); - - return children; -} - -/** - * gtk_container_focus_sort: - * @container: a #GtkContainer - * @children: a list of descendents of @container (they don't - * have to be direct children) - * @direction: focus direction - * @old_focus: (allow-none): widget to use for the starting position, or %NULL - * to determine this automatically. - * (Note, this argument isn’t used for GTK_DIR_TAB_*, - * which is the only @direction we use currently, - * so perhaps this argument should be removed) - * - * Sorts @children in the correct order for focusing with - * direction type @direction. - * - * Returns: a copy of @children, sorted in correct focusing order, - * with children that aren’t suitable for focusing in this direction - * removed. - **/ -GList * -_gtk_container_focus_sort (GtkContainer *container, - GList *children, - GtkDirectionType direction, - GtkWidget *old_focus) -{ - GList *visible_children = NULL; - - while (children) - { - if (_gtk_widget_get_realized (children->data)) - visible_children = g_list_prepend (visible_children, children->data); - children = children->next; - } - - switch (direction) - { - case GTK_DIR_TAB_FORWARD: - case GTK_DIR_TAB_BACKWARD: - return gtk_container_focus_sort_tab (container, visible_children, direction, old_focus); - case GTK_DIR_UP: - case GTK_DIR_DOWN: - return gtk_container_focus_sort_up_down (container, visible_children, direction, old_focus); - case GTK_DIR_LEFT: - case GTK_DIR_RIGHT: - return gtk_container_focus_sort_left_right (container, visible_children, direction, old_focus); - default: - g_assert_not_reached (); - return NULL; - } -} - static void gtk_container_children_callback (GtkWidget *widget, gpointer client_data) diff --git a/gtk/gtkcontainerprivate.h b/gtk/gtkcontainerprivate.h index fdbb5d4b7c..67adf69e1a 100644 --- a/gtk/gtkcontainerprivate.h +++ b/gtk/gtkcontainerprivate.h @@ -29,11 +29,6 @@ G_BEGIN_DECLS void gtk_container_queue_resize_handler (GtkContainer *container); void _gtk_container_queue_restyle (GtkContainer *container); void _gtk_container_dequeue_resize_handler (GtkContainer *container); -GList * _gtk_container_focus_sort (GtkContainer *container, - GList *children, - GtkDirectionType direction, - GtkWidget *old_focus); - void _gtk_container_stop_idle_sizer (GtkContainer *container); void _gtk_container_maybe_start_idle_sizer (GtkContainer *container); void gtk_container_set_focus_child (GtkContainer *container,