mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-27 06:00:22 +00:00
container: Remove focus widget sorting code
The more general version of this code lives in gtkwidgetfocus.s now.
This commit is contained in:
parent
ad85a75c2e
commit
3ca298ec94
@ -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)
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user