Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6fea9c3a51 | |||
| 26d2cab0bc | |||
| 4367147434 | |||
| f657576bff | |||
| c556dac321 | |||
| fff036e8ba | |||
| 3c2bb1f138 | |||
| f1b66ba707 | |||
| 40ffdd54d8 | |||
| da8e26e18d | |||
| 96263109f0 | |||
| 5d0af49041 | |||
| becd059464 | |||
| 658246a1e4 | |||
| f86128d4a7 | |||
| a349d53645 | |||
| 1c90f3e4ec | |||
| db520ca9af | |||
| 726e9bfb17 | |||
| 4934e04239 |
@@ -720,8 +720,6 @@ gtk_container_check_resize
|
||||
gtk_container_foreach
|
||||
gtk_container_get_children
|
||||
gtk_container_get_path_for_child
|
||||
gtk_container_get_focus_child
|
||||
gtk_container_set_focus_child
|
||||
gtk_container_get_focus_vadjustment
|
||||
gtk_container_set_focus_vadjustment
|
||||
gtk_container_get_focus_hadjustment
|
||||
@@ -4755,7 +4753,6 @@ gtk_window_set_screen
|
||||
gtk_window_get_screen
|
||||
gtk_window_is_active
|
||||
gtk_window_is_maximized
|
||||
gtk_window_has_toplevel_focus
|
||||
gtk_window_list_toplevels
|
||||
gtk_window_add_mnemonic
|
||||
gtk_window_remove_mnemonic
|
||||
|
||||
@@ -931,6 +931,7 @@ gtk_base_c_sources = \
|
||||
gtkvolumebutton.c \
|
||||
gtkviewport.c \
|
||||
gtkwidget.c \
|
||||
gtkwidgetfocus.c \
|
||||
gtkwidgetpath.c \
|
||||
gtkwindow.c \
|
||||
gtkwindowgroup.c \
|
||||
|
||||
@@ -935,7 +935,7 @@ window_removed (AtkObject *atk_obj,
|
||||
* Deactivate window if it is still focused and we are removing it. This
|
||||
* can happen when a dialog displayed by gok is removed.
|
||||
*/
|
||||
if (gtk_window_is_active (window) && gtk_window_has_toplevel_focus (window))
|
||||
if (gtk_window_is_active (window))
|
||||
g_signal_emit_by_name (child, "deactivate");
|
||||
|
||||
g_signal_handlers_disconnect_by_func (widget, (gpointer) window_focus, NULL);
|
||||
|
||||
@@ -251,7 +251,7 @@ gtk_window_accessible_ref_state_set (AtkObject *accessible)
|
||||
|
||||
window = GTK_WINDOW (widget);
|
||||
|
||||
if (gtk_window_has_toplevel_focus (window) && gtk_window_is_active (window))
|
||||
if (gtk_window_is_active (window))
|
||||
atk_state_set_add_state (state_set, ATK_STATE_ACTIVE);
|
||||
|
||||
gdk_window = gtk_widget_get_window (widget);
|
||||
|
||||
+9
-56
@@ -276,8 +276,6 @@
|
||||
|
||||
struct _GtkContainerPrivate
|
||||
{
|
||||
GtkWidget *focus_child;
|
||||
|
||||
GdkFrameClock *resize_clock;
|
||||
guint resize_handler;
|
||||
|
||||
@@ -1590,12 +1588,7 @@ gtk_container_remove_unimplemented (GtkContainer *container,
|
||||
static void
|
||||
gtk_container_init (GtkContainer *container)
|
||||
{
|
||||
GtkContainerPrivate *priv;
|
||||
|
||||
container->priv = gtk_container_get_instance_private (container);
|
||||
priv = container->priv;
|
||||
|
||||
priv->focus_child = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1607,8 +1600,6 @@ gtk_container_destroy (GtkWidget *widget)
|
||||
if (priv->restyle_pending)
|
||||
priv->restyle_pending = FALSE;
|
||||
|
||||
g_clear_object (&priv->focus_child);
|
||||
|
||||
/* do this before walking child widgets, to avoid
|
||||
* removing children from focus chain one by one.
|
||||
*/
|
||||
@@ -1987,28 +1978,6 @@ gtk_container_set_focus_child (GtkContainer *container,
|
||||
g_signal_emit (container, container_signals[SET_FOCUS_CHILD], 0, child);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_container_get_focus_child:
|
||||
* @container: a #GtkContainer
|
||||
*
|
||||
* Returns the current focus child widget inside @container. This is not the
|
||||
* currently focused widget. That can be obtained by calling
|
||||
* gtk_window_get_focus().
|
||||
*
|
||||
* Returns: (nullable) (transfer none): The child widget which will receive the
|
||||
* focus inside @container when the @container is focused,
|
||||
* or %NULL if none is set.
|
||||
*
|
||||
* Since: 2.14
|
||||
**/
|
||||
GtkWidget *
|
||||
gtk_container_get_focus_child (GtkContainer *container)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CONTAINER (container), NULL);
|
||||
|
||||
return container->priv->focus_child;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_container_get_children:
|
||||
* @container: a #GtkContainer
|
||||
@@ -2081,48 +2050,33 @@ static void
|
||||
gtk_container_real_set_focus_child (GtkContainer *container,
|
||||
GtkWidget *child)
|
||||
{
|
||||
GtkContainerPrivate *priv;
|
||||
GtkWidget *focus_child;
|
||||
|
||||
g_return_if_fail (GTK_IS_CONTAINER (container));
|
||||
g_return_if_fail (child == NULL || GTK_IS_WIDGET (child));
|
||||
|
||||
priv = container->priv;
|
||||
|
||||
if (child != priv->focus_child)
|
||||
{
|
||||
if (priv->focus_child)
|
||||
g_object_unref (priv->focus_child);
|
||||
priv->focus_child = child;
|
||||
if (priv->focus_child)
|
||||
g_object_ref (priv->focus_child);
|
||||
}
|
||||
|
||||
focus_child = gtk_widget_get_focus_child (GTK_WIDGET (container));
|
||||
|
||||
/* check for h/v adjustments
|
||||
*/
|
||||
if (priv->focus_child)
|
||||
if (focus_child)
|
||||
{
|
||||
GtkAdjustment *hadj;
|
||||
GtkAdjustment *vadj;
|
||||
GtkAllocation allocation;
|
||||
GtkWidget *focus_child;
|
||||
gint x, y;
|
||||
|
||||
hadj = g_object_get_qdata (G_OBJECT (container), hadjustment_key_id);
|
||||
vadj = g_object_get_qdata (G_OBJECT (container), vadjustment_key_id);
|
||||
if (hadj || vadj)
|
||||
{
|
||||
while (gtk_widget_get_focus_child (focus_child))
|
||||
focus_child = gtk_widget_get_focus_child (focus_child);
|
||||
|
||||
focus_child = priv->focus_child;
|
||||
while (GTK_IS_CONTAINER (focus_child) && gtk_container_get_focus_child (GTK_CONTAINER (focus_child)))
|
||||
{
|
||||
focus_child = gtk_container_get_focus_child (GTK_CONTAINER (focus_child));
|
||||
}
|
||||
|
||||
gtk_widget_translate_coordinates (focus_child, priv->focus_child,
|
||||
gtk_widget_translate_coordinates (focus_child, focus_child,
|
||||
0, 0, &x, &y);
|
||||
|
||||
_gtk_widget_get_allocation (priv->focus_child, &allocation);
|
||||
_gtk_widget_get_allocation (focus_child, &allocation);
|
||||
x += allocation.x;
|
||||
y += allocation.y;
|
||||
|
||||
@@ -2310,7 +2264,7 @@ find_old_focus (GtkContainer *container,
|
||||
|
||||
parent = _gtk_widget_get_parent (widget);
|
||||
|
||||
if (parent && (gtk_container_get_focus_child (GTK_CONTAINER (parent)) != widget))
|
||||
if (parent && (gtk_widget_get_focus_child (parent) != widget))
|
||||
goto next;
|
||||
|
||||
widget = parent;
|
||||
@@ -2670,11 +2624,10 @@ gtk_container_focus_move (GtkContainer *container,
|
||||
GList *children,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
GtkContainerPrivate *priv = container->priv;
|
||||
GtkWidget *focus_child;
|
||||
GtkWidget *child;
|
||||
|
||||
focus_child = priv->focus_child;
|
||||
focus_child = gtk_widget_get_focus_child (GTK_WIDGET (container));
|
||||
|
||||
while (children)
|
||||
{
|
||||
|
||||
@@ -153,13 +153,6 @@ GDK_AVAILABLE_IN_ALL
|
||||
void gtk_container_unset_focus_chain (GtkContainer *container);
|
||||
|
||||
/* Widget-level methods */
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_container_set_focus_child (GtkContainer *container,
|
||||
GtkWidget *child);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget *
|
||||
gtk_container_get_focus_child (GtkContainer *container);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_container_set_focus_vadjustment (GtkContainer *container,
|
||||
GtkAdjustment *adjustment);
|
||||
|
||||
@@ -28,20 +28,19 @@ G_BEGIN_DECLS
|
||||
|
||||
void gtk_container_queue_resize_handler (GtkContainer *container);
|
||||
void _gtk_container_queue_restyle (GtkContainer *container);
|
||||
void _gtk_container_clear_resize_widgets (GtkContainer *container);
|
||||
gchar* _gtk_container_child_composite_name (GtkContainer *container,
|
||||
GtkWidget *child);
|
||||
void _gtk_container_dequeue_resize_handler (GtkContainer *container);
|
||||
GList * _gtk_container_focus_sort (GtkContainer *container,
|
||||
GList *children,
|
||||
GtkDirectionType direction,
|
||||
GtkWidget *old_focus);
|
||||
gboolean _gtk_container_get_reallocate_redraws (GtkContainer *container);
|
||||
|
||||
void _gtk_container_stop_idle_sizer (GtkContainer *container);
|
||||
void _gtk_container_maybe_start_idle_sizer (GtkContainer *container);
|
||||
void gtk_container_get_children_clip (GtkContainer *container,
|
||||
GtkAllocation *out_clip);
|
||||
void gtk_container_set_focus_child (GtkContainer *container,
|
||||
GtkWidget *child);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
+2
-2
@@ -798,7 +798,7 @@ focus_current_site (GtkExpander *expander,
|
||||
{
|
||||
GtkWidget *current_focus;
|
||||
|
||||
current_focus = gtk_container_get_focus_child (GTK_CONTAINER (expander));
|
||||
current_focus = gtk_widget_get_focus_child (GTK_WIDGET (expander));
|
||||
|
||||
if (!current_focus)
|
||||
return FALSE;
|
||||
@@ -963,7 +963,7 @@ gtk_expander_focus (GtkWidget *widget,
|
||||
FocusSite site = FOCUS_NONE;
|
||||
|
||||
widget_is_focus = gtk_widget_is_focus (widget);
|
||||
old_focus_child = gtk_container_get_focus_child (GTK_CONTAINER (widget));
|
||||
old_focus_child = gtk_widget_get_focus_child (GTK_WIDGET (widget));
|
||||
|
||||
if (old_focus_child && old_focus_child == expander->priv->label_widget)
|
||||
site = FOCUS_LABEL;
|
||||
|
||||
+2
-2
@@ -342,7 +342,7 @@ gtk_flow_box_child_focus (GtkWidget *widget,
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
else if (gtk_container_get_focus_child (GTK_CONTAINER (widget)) != NULL)
|
||||
else if (gtk_widget_get_focus_child (widget) != NULL)
|
||||
{
|
||||
/* Child has focus, always navigate inside it first */
|
||||
if (gtk_widget_child_focus (child, direction))
|
||||
@@ -3230,7 +3230,7 @@ gtk_flow_box_focus (GtkWidget *widget,
|
||||
return GTK_WIDGET_CLASS (gtk_flow_box_parent_class)->focus (widget, direction);
|
||||
}
|
||||
|
||||
focus_child = gtk_container_get_focus_child (GTK_CONTAINER (box));
|
||||
focus_child = gtk_widget_get_focus_child (widget);
|
||||
next_focus_child = NULL;
|
||||
|
||||
if (focus_child != NULL)
|
||||
|
||||
+3
-1
@@ -4735,9 +4735,11 @@ gtk_label_focus (GtkWidget *widget,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!info)
|
||||
|
||||
+2
-2
@@ -2016,7 +2016,7 @@ gtk_list_box_focus (GtkWidget *widget,
|
||||
GtkWidget *row;
|
||||
GtkWidget *header;
|
||||
|
||||
focus_child = gtk_container_get_focus_child ((GtkContainer *)box);
|
||||
focus_child = gtk_widget_get_focus_child (widget);
|
||||
|
||||
next_focus_row = NULL;
|
||||
if (focus_child != NULL)
|
||||
@@ -3207,7 +3207,7 @@ gtk_list_box_row_focus (GtkWidget *widget,
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
else if (gtk_container_get_focus_child (GTK_CONTAINER (row)) != NULL)
|
||||
else if (gtk_widget_get_focus_child (widget) != NULL)
|
||||
{
|
||||
/* Child has focus, always navigate inside it first */
|
||||
if (gtk_widget_child_focus (child, direction))
|
||||
|
||||
+2
-5
@@ -1436,7 +1436,7 @@ gtk_notebook_move_focus_out (GtkNotebook *notebook,
|
||||
GtkDirectionType effective_direction = get_effective_direction (notebook, direction_type);
|
||||
GtkWidget *toplevel;
|
||||
|
||||
if (gtk_container_get_focus_child (GTK_CONTAINER (notebook)) && effective_direction == GTK_DIR_UP)
|
||||
if (gtk_widget_get_focus_child (GTK_WIDGET (notebook)) && effective_direction == GTK_DIR_UP)
|
||||
if (focus_tabs_in (notebook))
|
||||
return;
|
||||
if (gtk_widget_is_focus (GTK_WIDGET (notebook)) && effective_direction == GTK_DIR_DOWN)
|
||||
@@ -4180,9 +4180,6 @@ gtk_notebook_focus (GtkWidget *widget,
|
||||
gint last_action;
|
||||
|
||||
gboolean widget_is_focus;
|
||||
GtkContainer *container;
|
||||
|
||||
container = GTK_CONTAINER (widget);
|
||||
|
||||
if (priv->tab_pos == GTK_POS_TOP ||
|
||||
priv->tab_pos == GTK_POS_LEFT)
|
||||
@@ -4203,7 +4200,7 @@ gtk_notebook_focus (GtkWidget *widget,
|
||||
}
|
||||
|
||||
widget_is_focus = gtk_widget_is_focus (widget);
|
||||
old_focus_child = gtk_container_get_focus_child (container);
|
||||
old_focus_child = gtk_widget_get_focus_child (widget);
|
||||
|
||||
effective_direction = get_effective_direction (notebook, direction);
|
||||
|
||||
|
||||
+3
-5
@@ -2449,7 +2449,7 @@ gtk_paned_set_focus_child (GtkContainer *container,
|
||||
if (GTK_IS_PANED (w))
|
||||
last_focus = w;
|
||||
|
||||
container_focus_child = gtk_container_get_focus_child (container);
|
||||
container_focus_child = gtk_widget_get_focus_child (GTK_WIDGET (container));
|
||||
if (container_focus_child == priv->child1)
|
||||
gtk_paned_set_last_child1_focus (paned, last_focus);
|
||||
else if (container_focus_child == priv->child2)
|
||||
@@ -2467,7 +2467,6 @@ gtk_paned_get_cycle_chain (GtkPaned *paned,
|
||||
GList **widgets)
|
||||
{
|
||||
GtkPanedPrivate *priv = paned->priv;
|
||||
GtkContainer *container = GTK_CONTAINER (paned);
|
||||
GtkWidget *ancestor = NULL;
|
||||
GtkWidget *focus_child;
|
||||
GtkWidget *parent;
|
||||
@@ -2504,7 +2503,7 @@ gtk_paned_get_cycle_chain (GtkPaned *paned,
|
||||
* priv->last_child?_focus before priv->child?, both when we
|
||||
* are going forward and backward.
|
||||
*/
|
||||
focus_child = gtk_container_get_focus_child (container);
|
||||
focus_child = gtk_widget_get_focus_child (GTK_WIDGET (paned));
|
||||
if (direction == GTK_DIR_TAB_FORWARD)
|
||||
{
|
||||
if (focus_child == priv->child1)
|
||||
@@ -2880,14 +2879,13 @@ gtk_paned_cycle_handle_focus (GtkPaned *paned,
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkContainer *container = GTK_CONTAINER (paned);
|
||||
GtkPaned *focus;
|
||||
GtkPaned *first;
|
||||
GtkWidget *toplevel;
|
||||
GtkWidget *focus_child;
|
||||
|
||||
gtk_paned_find_neighbours (paned, &next, &prev);
|
||||
focus_child = gtk_container_get_focus_child (container);
|
||||
focus_child = gtk_widget_get_focus_child (GTK_WIDGET (paned));
|
||||
|
||||
if (focus_child == priv->child1)
|
||||
{
|
||||
|
||||
+1
-1
@@ -1511,7 +1511,7 @@ gtk_popover_focus (GtkWidget *widget,
|
||||
*/
|
||||
while (focus && focus != widget)
|
||||
{
|
||||
gtk_container_set_focus_child (GTK_CONTAINER (focus), NULL);
|
||||
gtk_widget_set_focus_child (focus, NULL);
|
||||
focus = gtk_widget_get_parent (focus);
|
||||
}
|
||||
|
||||
|
||||
@@ -3642,7 +3642,7 @@ gtk_scrolled_window_focus (GtkWidget *widget,
|
||||
GtkWidget *child;
|
||||
gboolean had_focus_child;
|
||||
|
||||
had_focus_child = gtk_container_get_focus_child (GTK_CONTAINER (widget)) != NULL;
|
||||
had_focus_child = gtk_widget_get_focus_child (widget) != NULL;
|
||||
|
||||
if (priv->focus_out)
|
||||
{
|
||||
|
||||
+1
-4
@@ -5959,13 +5959,10 @@ static gboolean
|
||||
gtk_text_view_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
GtkContainer *container;
|
||||
gboolean result;
|
||||
|
||||
container = GTK_CONTAINER (widget);
|
||||
|
||||
if (!gtk_widget_is_focus (widget) &&
|
||||
gtk_container_get_focus_child (container) == NULL)
|
||||
gtk_widget_get_focus_child (widget) == NULL)
|
||||
{
|
||||
if (gtk_widget_get_can_focus (widget))
|
||||
{
|
||||
|
||||
+3
-4
@@ -1836,7 +1836,7 @@ gtk_toolbar_focus_home_or_end (GtkToolbar *toolbar,
|
||||
{
|
||||
GtkWidget *child = list->data;
|
||||
|
||||
if (gtk_container_get_focus_child (GTK_CONTAINER (toolbar)) == child)
|
||||
if (gtk_widget_get_focus_child (GTK_WIDGET (toolbar)) == child)
|
||||
break;
|
||||
|
||||
if (gtk_widget_get_mapped (child) && gtk_widget_child_focus (child, dir))
|
||||
@@ -1856,13 +1856,12 @@ gtk_toolbar_move_focus (GtkWidget *widget,
|
||||
GtkDirectionType dir)
|
||||
{
|
||||
GtkToolbar *toolbar = GTK_TOOLBAR (widget);
|
||||
GtkContainer *container = GTK_CONTAINER (toolbar);
|
||||
GtkWidget *focus_child;
|
||||
GList *list;
|
||||
gboolean try_focus = FALSE;
|
||||
GList *children;
|
||||
|
||||
focus_child = gtk_container_get_focus_child (container);
|
||||
focus_child = gtk_widget_get_focus_child (widget);
|
||||
|
||||
if (focus_child && gtk_widget_child_focus (focus_child, dir))
|
||||
return;
|
||||
@@ -1899,7 +1898,7 @@ gtk_toolbar_focus (GtkWidget *widget,
|
||||
* arrow keys or Ctrl TAB (both of which are handled by the
|
||||
* gtk_toolbar_move_focus() keybinding function.
|
||||
*/
|
||||
if (gtk_container_get_focus_child (GTK_CONTAINER (widget)))
|
||||
if (gtk_widget_get_focus_child (widget))
|
||||
return FALSE;
|
||||
|
||||
children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
|
||||
|
||||
+2
-3
@@ -8292,7 +8292,7 @@ gtk_tree_view_header_focus (GtkTreeView *tree_view,
|
||||
if (! tree_view->priv->headers_visible)
|
||||
return FALSE;
|
||||
|
||||
focus_child = gtk_container_get_focus_child (GTK_CONTAINER (tree_view));
|
||||
focus_child = gtk_widget_get_focus_child (GTK_WIDGET (tree_view));
|
||||
|
||||
first_column = tree_view->priv->columns;
|
||||
while (first_column)
|
||||
@@ -8489,13 +8489,12 @@ gtk_tree_view_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
|
||||
GtkContainer *container = GTK_CONTAINER (widget);
|
||||
GtkWidget *focus_child;
|
||||
|
||||
if (!gtk_widget_is_sensitive (widget) || !gtk_widget_get_can_focus (widget))
|
||||
return FALSE;
|
||||
|
||||
focus_child = gtk_container_get_focus_child (container);
|
||||
focus_child = gtk_widget_get_focus_child (widget);
|
||||
|
||||
gtk_tree_view_stop_editing (GTK_TREE_VIEW (widget), FALSE);
|
||||
/* Case 1. Headers currently have focus. */
|
||||
|
||||
+110
-93
@@ -4008,11 +4008,8 @@ gtk_widget_unparent (GtkWidget *widget)
|
||||
if (_gtk_widget_is_toplevel (toplevel))
|
||||
_gtk_window_unset_focus_and_default (GTK_WINDOW (toplevel), widget);
|
||||
|
||||
if (GTK_IS_CONTAINER (priv->parent))
|
||||
{
|
||||
if (gtk_container_get_focus_child (GTK_CONTAINER (priv->parent)) == widget)
|
||||
gtk_container_set_focus_child (GTK_CONTAINER (priv->parent), NULL);
|
||||
}
|
||||
if (gtk_widget_get_focus_child (priv->parent) == widget)
|
||||
gtk_widget_set_focus_child (priv->parent, NULL);
|
||||
|
||||
if (_gtk_widget_is_drawable (priv->parent))
|
||||
gtk_widget_queue_draw_area (priv->parent,
|
||||
@@ -7152,87 +7149,78 @@ static void
|
||||
reset_focus_recurse (GtkWidget *widget,
|
||||
gpointer data)
|
||||
{
|
||||
if (GTK_IS_CONTAINER (widget))
|
||||
{
|
||||
GtkContainer *container;
|
||||
gtk_widget_set_focus_child (widget, NULL);
|
||||
|
||||
container = GTK_CONTAINER (widget);
|
||||
gtk_container_set_focus_child (container, NULL);
|
||||
|
||||
gtk_container_foreach (container,
|
||||
reset_focus_recurse,
|
||||
NULL);
|
||||
}
|
||||
gtk_widget_forall (widget,
|
||||
reset_focus_recurse,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_widget_real_grab_focus (GtkWidget *focus_widget)
|
||||
{
|
||||
if (gtk_widget_get_can_focus (focus_widget))
|
||||
GtkWidget *toplevel;
|
||||
GtkWidget *widget;
|
||||
|
||||
/* clear the current focus setting, break if the current widget
|
||||
* is the focus widget's parent, since containers above that will
|
||||
* be set by the next loop.
|
||||
*/
|
||||
toplevel = _gtk_widget_get_toplevel (focus_widget);
|
||||
if (_gtk_widget_is_toplevel (toplevel) && GTK_IS_WINDOW (toplevel))
|
||||
{
|
||||
GtkWidget *toplevel;
|
||||
GtkWidget *widget;
|
||||
widget = gtk_window_get_focus (GTK_WINDOW (toplevel));
|
||||
|
||||
/* clear the current focus setting, break if the current widget
|
||||
* is the focus widget's parent, since containers above that will
|
||||
* be set by the next loop.
|
||||
*/
|
||||
toplevel = _gtk_widget_get_toplevel (focus_widget);
|
||||
if (_gtk_widget_is_toplevel (toplevel) && GTK_IS_WINDOW (toplevel))
|
||||
{
|
||||
widget = gtk_window_get_focus (GTK_WINDOW (toplevel));
|
||||
if (widget == focus_widget)
|
||||
{
|
||||
/* We call _gtk_window_internal_set_focus() here so that the
|
||||
* toplevel window can request the focus if necessary.
|
||||
* This is needed when the toplevel is a GtkPlug
|
||||
*/
|
||||
if (!gtk_widget_has_focus (widget))
|
||||
_gtk_window_internal_set_focus (GTK_WINDOW (toplevel), focus_widget);
|
||||
|
||||
if (widget == focus_widget)
|
||||
{
|
||||
/* We call _gtk_window_internal_set_focus() here so that the
|
||||
* toplevel window can request the focus if necessary.
|
||||
* This is needed when the toplevel is a GtkPlug
|
||||
*/
|
||||
if (!gtk_widget_has_focus (widget))
|
||||
_gtk_window_internal_set_focus (GTK_WINDOW (toplevel), focus_widget);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (widget)
|
||||
{
|
||||
GtkWidget *common_ancestor = gtk_widget_common_ancestor (widget, focus_widget);
|
||||
|
||||
if (widget)
|
||||
{
|
||||
GtkWidget *common_ancestor = gtk_widget_common_ancestor (widget, focus_widget);
|
||||
|
||||
if (widget != common_ancestor)
|
||||
{
|
||||
while (widget->priv->parent)
|
||||
{
|
||||
widget = widget->priv->parent;
|
||||
gtk_widget_set_focus_child (widget, NULL);
|
||||
if (widget == common_ancestor)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (toplevel != focus_widget)
|
||||
{
|
||||
/* gtk_widget_grab_focus() operates on a tree without window...
|
||||
* actually, this is very questionable behavior.
|
||||
*/
|
||||
|
||||
gtk_container_foreach (GTK_CONTAINER (toplevel),
|
||||
reset_focus_recurse,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* now propagate the new focus up the widget tree and finally
|
||||
* set it on the window
|
||||
*/
|
||||
widget = focus_widget;
|
||||
while (widget->priv->parent)
|
||||
{
|
||||
gtk_widget_set_focus_child (widget->priv->parent, widget);
|
||||
widget = widget->priv->parent;
|
||||
}
|
||||
if (GTK_IS_WINDOW (widget))
|
||||
_gtk_window_internal_set_focus (GTK_WINDOW (widget), focus_widget);
|
||||
if (widget != common_ancestor)
|
||||
{
|
||||
while (widget->priv->parent)
|
||||
{
|
||||
widget = widget->priv->parent;
|
||||
gtk_widget_set_focus_child (widget, NULL);
|
||||
if (widget == common_ancestor)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (toplevel != focus_widget)
|
||||
{
|
||||
/* gtk_widget_grab_focus() operates on a tree without window...
|
||||
* actually, this is very questionable behavior.
|
||||
*/
|
||||
|
||||
gtk_widget_forall (toplevel,
|
||||
reset_focus_recurse,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* now propagate the new focus up the widget tree and finally
|
||||
* set it on the window
|
||||
*/
|
||||
widget = focus_widget;
|
||||
while (widget->priv->parent)
|
||||
{
|
||||
gtk_widget_set_focus_child (widget->priv->parent, widget);
|
||||
widget = widget->priv->parent;
|
||||
}
|
||||
if (GTK_IS_WINDOW (widget))
|
||||
_gtk_window_internal_set_focus (GTK_WINDOW (widget), focus_widget);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -7322,16 +7310,36 @@ static gboolean
|
||||
gtk_widget_real_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
if (!gtk_widget_get_can_focus (widget))
|
||||
return FALSE;
|
||||
|
||||
if (!gtk_widget_is_focus (widget))
|
||||
if (gtk_widget_get_can_focus (widget))
|
||||
{
|
||||
gtk_widget_grab_focus (widget);
|
||||
return TRUE;
|
||||
if (!gtk_widget_is_focus (widget))
|
||||
{
|
||||
gtk_widget_grab_focus (widget);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else if (_gtk_widget_get_first_child (widget) == NULL)
|
||||
{
|
||||
/* No children, no possibility to focus anything */
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
{
|
||||
GPtrArray *focus_order = g_ptr_array_new ();
|
||||
gboolean ret = FALSE;
|
||||
|
||||
/* Try focusing any of the child widgets, depending on the given @direction */
|
||||
|
||||
gtk_widget_focus_sort (widget, direction, focus_order);
|
||||
ret = gtk_widget_focus_move (widget, direction, focus_order);
|
||||
|
||||
g_ptr_array_unref (focus_order);
|
||||
|
||||
if (ret)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -9165,6 +9173,7 @@ gtk_widget_set_parent_window (GtkWidget *widget,
|
||||
GdkWindow *old_parent_window;
|
||||
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
g_return_if_fail (!GTK_IS_WINDOW (widget));
|
||||
|
||||
old_parent_window = g_object_get_qdata (G_OBJECT (widget),
|
||||
quark_parent_window);
|
||||
@@ -9177,13 +9186,6 @@ gtk_widget_set_parent_window (GtkWidget *widget,
|
||||
g_object_unref (old_parent_window);
|
||||
if (parent_window)
|
||||
g_object_ref (parent_window);
|
||||
|
||||
/* Unset toplevel flag when adding a parent window to a widget,
|
||||
* this is the primary entry point to allow toplevels to be
|
||||
* embeddable.
|
||||
*/
|
||||
if (GTK_IS_WINDOW (widget))
|
||||
_gtk_window_set_is_toplevel (GTK_WINDOW (widget), parent_window == NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9490,12 +9492,10 @@ gtk_widget_child_focus (GtkWidget *widget,
|
||||
!gtk_widget_is_sensitive (widget))
|
||||
return FALSE;
|
||||
|
||||
/* child widgets must set CAN_FOCUS, containers
|
||||
* don't have to though.
|
||||
/* Emit ::focus in any case, even if can-focus is FALSE,
|
||||
* since any widget might have child widgets that will take
|
||||
* focus
|
||||
*/
|
||||
if (!GTK_IS_CONTAINER (widget) &&
|
||||
!gtk_widget_get_can_focus (widget))
|
||||
return FALSE;
|
||||
|
||||
g_signal_emit (widget,
|
||||
widget_signals[FOCUS],
|
||||
@@ -15768,16 +15768,33 @@ void
|
||||
gtk_widget_set_focus_child (GtkWidget *widget,
|
||||
GtkWidget *child)
|
||||
{
|
||||
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
|
||||
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
|
||||
if (child == priv->focus_child)
|
||||
return;
|
||||
|
||||
if (child != NULL)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_WIDGET (child));
|
||||
g_return_if_fail (gtk_widget_get_parent (child) == widget);
|
||||
}
|
||||
|
||||
g_set_object (&priv->focus_child, child);
|
||||
|
||||
if (GTK_IS_CONTAINER (widget))
|
||||
gtk_container_set_focus_child (GTK_CONTAINER (widget), child);
|
||||
|
||||
/* TODO: ??? */
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gtk_widget_get_focus_child (GtkWidget *widget)
|
||||
{
|
||||
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
|
||||
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
|
||||
|
||||
return priv->focus_child;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,490 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "gtkwidgetprivate.h"
|
||||
#include "gtkwindow.h"
|
||||
|
||||
typedef struct _CompareInfo CompareInfo;
|
||||
|
||||
enum Axis {
|
||||
HORIZONTAL = 0,
|
||||
VERTICAL = 1
|
||||
};
|
||||
|
||||
struct _CompareInfo
|
||||
{
|
||||
GtkWidget *widget;
|
||||
int x;
|
||||
int y;
|
||||
guint reverse : 1;
|
||||
guint axis : 1;
|
||||
};
|
||||
|
||||
static inline void
|
||||
get_axis_info (const GdkRectangle *rect,
|
||||
int axis,
|
||||
int *origin,
|
||||
int *bounds)
|
||||
{
|
||||
if (axis == HORIZONTAL)
|
||||
{
|
||||
*origin = rect->x;
|
||||
*bounds = rect->width;
|
||||
}
|
||||
else if (axis == VERTICAL)
|
||||
{
|
||||
*origin = rect->y;
|
||||
*bounds = rect->height;
|
||||
}
|
||||
else
|
||||
g_assert(FALSE);
|
||||
}
|
||||
|
||||
/* Utility function, equivalent to g_list_reverse */
|
||||
static void
|
||||
reverse_ptr_array (GPtrArray *arr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < arr->len / 2; i ++)
|
||||
{
|
||||
void *a = g_ptr_array_index (arr, i);
|
||||
void *b = g_ptr_array_index (arr, arr->len - 1 - i);
|
||||
|
||||
arr->pdata[i] = b;
|
||||
arr->pdata[arr->len - 1 - i] = a;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get coordinates of @widget's allocation with respect to
|
||||
* allocation of @container.
|
||||
*/
|
||||
static gboolean
|
||||
get_allocation_coords (GtkWidget *widget,
|
||||
GtkWidget *child,
|
||||
GdkRectangle *allocation)
|
||||
{
|
||||
gtk_widget_get_allocation (child, allocation);
|
||||
|
||||
return gtk_widget_translate_coordinates (child, widget,
|
||||
0, 0, &allocation->x, &allocation->y);
|
||||
}
|
||||
|
||||
static int
|
||||
tab_sort_func (gconstpointer a,
|
||||
gconstpointer b,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkAllocation child1_allocation, child2_allocation;
|
||||
const GtkWidget *child1 = *((GtkWidget **)a);
|
||||
const GtkWidget *child2 = *((GtkWidget **)b);
|
||||
GtkTextDirection text_direction = GPOINTER_TO_INT (user_data);
|
||||
int 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)
|
||||
{
|
||||
int x1 = child1_allocation.x + child1_allocation.width / 2;
|
||||
int 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 void
|
||||
focus_sort_tab (GtkWidget *widget,
|
||||
GtkDirectionType direction,
|
||||
GPtrArray *focus_order)
|
||||
{
|
||||
GtkTextDirection text_direction = _gtk_widget_get_direction (widget);
|
||||
|
||||
g_ptr_array_sort_with_data (focus_order, tab_sort_func, GINT_TO_POINTER (text_direction));
|
||||
|
||||
if (direction == GTK_DIR_TAB_BACKWARD)
|
||||
reverse_ptr_array (focus_order);
|
||||
}
|
||||
|
||||
/* 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 (GtkWidget *widget,
|
||||
GPtrArray *children)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < children->len; i ++)
|
||||
{
|
||||
GtkWidget *child = g_ptr_array_index (children, i);
|
||||
GtkWidget *child_ptr = child;
|
||||
|
||||
while (child_ptr && child_ptr != widget)
|
||||
{
|
||||
GtkWidget *parent;
|
||||
|
||||
parent = _gtk_widget_get_parent (child_ptr);
|
||||
|
||||
if (parent && (gtk_widget_get_focus_child (parent) != child_ptr))
|
||||
{
|
||||
child = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
child_ptr = parent;
|
||||
}
|
||||
|
||||
if (child)
|
||||
return child;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
old_focus_coords (GtkWidget *widget,
|
||||
GdkRectangle *old_focus_rect)
|
||||
{
|
||||
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 (widget, old_focus, old_focus_rect);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int
|
||||
axis_compare (gconstpointer a,
|
||||
gconstpointer b,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkRectangle allocation1;
|
||||
GdkRectangle allocation2;
|
||||
CompareInfo *compare = user_data;
|
||||
int origin1, origin2;
|
||||
int bounds1, bounds2;
|
||||
|
||||
get_allocation_coords (compare->widget, *((GtkWidget **)a), &allocation1);
|
||||
get_allocation_coords (compare->widget, *((GtkWidget **)b), &allocation2);
|
||||
|
||||
get_axis_info (&allocation1, compare->axis, &origin1, &bounds1);
|
||||
get_axis_info (&allocation2, compare->axis, &origin2, &bounds2);
|
||||
|
||||
origin1 = origin1 + (bounds1 / 2);
|
||||
origin2 = origin2 + (bounds2 / 2);
|
||||
|
||||
if (origin1 == origin2)
|
||||
{
|
||||
/* Now use origin/bounds to compare the 2 widgets on the other axis */
|
||||
get_axis_info (&allocation1, 1 - compare->axis, &origin1, &bounds1);
|
||||
get_axis_info (&allocation2, 1 - compare->axis, &origin2, &bounds2);
|
||||
|
||||
int x1 = abs (origin1 + (bounds2 / 2) - compare->x);
|
||||
int x2 = abs (origin2 + (bounds2 / 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 (origin1 < origin2) ? -1 : 1;
|
||||
}
|
||||
|
||||
static void
|
||||
focus_sort_left_right (GtkWidget *widget,
|
||||
GtkDirectionType direction,
|
||||
GPtrArray *focus_order)
|
||||
{
|
||||
CompareInfo compare_info;
|
||||
GdkRectangle old_allocation;
|
||||
GtkWidget *old_focus = gtk_widget_get_focus_child (widget);
|
||||
|
||||
compare_info.widget = widget;
|
||||
compare_info.reverse = (direction == GTK_DIR_LEFT);
|
||||
|
||||
if (!old_focus)
|
||||
old_focus = find_old_focus (widget, focus_order);
|
||||
|
||||
if (old_focus && get_allocation_coords (widget, old_focus, &old_allocation))
|
||||
{
|
||||
int compare_y1;
|
||||
int compare_y2;
|
||||
int compare_x;
|
||||
int i;
|
||||
|
||||
/* 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;
|
||||
|
||||
for (i = 0; i < focus_order->len; i ++)
|
||||
{
|
||||
GtkWidget *child = g_ptr_array_index (focus_order, i);
|
||||
int child_y1, child_y2;
|
||||
GdkRectangle child_allocation;
|
||||
|
||||
if (child != old_focus)
|
||||
{
|
||||
if (get_allocation_coords (widget, 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 */
|
||||
{
|
||||
g_ptr_array_remove_index (focus_order, i);
|
||||
i --;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_ptr_array_remove_index (focus_order, i);
|
||||
i --;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
compare_info.y = (compare_y1 + compare_y2) / 2;
|
||||
compare_info.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;
|
||||
GdkRectangle old_focus_rect;
|
||||
|
||||
_gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
if (old_focus_coords (widget, &old_focus_rect))
|
||||
{
|
||||
compare_info.y = old_focus_rect.y + old_focus_rect.height / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_gtk_widget_get_has_window (widget))
|
||||
compare_info.y = allocation.y + allocation.height / 2;
|
||||
else
|
||||
compare_info.y = allocation.height / 2;
|
||||
}
|
||||
|
||||
if (!_gtk_widget_get_has_window (widget))
|
||||
compare_info.x = (direction == GTK_DIR_RIGHT) ? allocation.x : allocation.x + allocation.width;
|
||||
else
|
||||
compare_info.x = (direction == GTK_DIR_RIGHT) ? 0 : allocation.width;
|
||||
}
|
||||
|
||||
|
||||
compare_info.axis = HORIZONTAL;
|
||||
g_ptr_array_sort_with_data (focus_order, axis_compare, &compare_info);
|
||||
|
||||
if (compare_info.reverse)
|
||||
reverse_ptr_array (focus_order);
|
||||
}
|
||||
|
||||
static void
|
||||
focus_sort_up_down (GtkWidget *widget,
|
||||
GtkDirectionType direction,
|
||||
GPtrArray *focus_order)
|
||||
{
|
||||
CompareInfo compare_info;
|
||||
GdkRectangle old_allocation;
|
||||
GtkWidget *old_focus = gtk_widget_get_focus_child (widget);
|
||||
|
||||
compare_info.widget = widget;
|
||||
compare_info.reverse = (direction == GTK_DIR_UP);
|
||||
|
||||
if (!old_focus)
|
||||
old_focus = find_old_focus (widget, focus_order);
|
||||
|
||||
if (old_focus && get_allocation_coords (widget, old_focus, &old_allocation))
|
||||
{
|
||||
int compare_x1;
|
||||
int compare_x2;
|
||||
int compare_y;
|
||||
int i;
|
||||
|
||||
/* 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;
|
||||
|
||||
for (i = 0; i < focus_order->len; i ++)
|
||||
{
|
||||
GtkWidget *child = g_ptr_array_index (focus_order, i);
|
||||
int child_x1, child_x2;
|
||||
GdkRectangle child_allocation;
|
||||
|
||||
if (child != old_focus)
|
||||
{
|
||||
if (get_allocation_coords (widget, 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 */
|
||||
{
|
||||
g_ptr_array_remove_index (focus_order, i);
|
||||
i --;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_ptr_array_remove_index (focus_order, i);
|
||||
i --;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
compare_info.x = (compare_x1 + compare_x2) / 2;
|
||||
compare_info.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;
|
||||
GdkRectangle old_focus_rect;
|
||||
|
||||
_gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
if (old_focus_coords (widget, &old_focus_rect))
|
||||
{
|
||||
compare_info.x = old_focus_rect.x + old_focus_rect.width / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_gtk_widget_get_has_window (widget))
|
||||
compare_info.x = allocation.x + allocation.width / 2;
|
||||
else
|
||||
compare_info.x = allocation.width / 2;
|
||||
}
|
||||
|
||||
if (!_gtk_widget_get_has_window (widget))
|
||||
compare_info.y = (direction == GTK_DIR_DOWN) ? allocation.y : allocation.y + allocation.height;
|
||||
else
|
||||
compare_info.y = (direction == GTK_DIR_DOWN) ? 0 : + allocation.height;
|
||||
}
|
||||
|
||||
compare_info.axis = VERTICAL;
|
||||
g_ptr_array_sort_with_data (focus_order, axis_compare, &compare_info);
|
||||
|
||||
if (compare_info.reverse)
|
||||
reverse_ptr_array (focus_order);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_widget_focus_sort (GtkWidget *widget,
|
||||
GtkDirectionType direction,
|
||||
GPtrArray *focus_order)
|
||||
{
|
||||
GtkWidget *child;
|
||||
|
||||
g_assert (focus_order->len == 0);
|
||||
|
||||
/* Initialize the list with all realized child widgets */
|
||||
for (child = _gtk_widget_get_first_child (widget);
|
||||
child != NULL;
|
||||
child = _gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
if (_gtk_widget_get_realized (child))
|
||||
g_ptr_array_add (focus_order, child);
|
||||
}
|
||||
|
||||
/* Now sort that list depending on @direction */
|
||||
switch (direction)
|
||||
{
|
||||
case GTK_DIR_TAB_FORWARD:
|
||||
case GTK_DIR_TAB_BACKWARD:
|
||||
focus_sort_tab (widget, direction, focus_order);
|
||||
break;
|
||||
case GTK_DIR_UP:
|
||||
case GTK_DIR_DOWN:
|
||||
focus_sort_up_down (widget, direction, focus_order);
|
||||
break;
|
||||
case GTK_DIR_LEFT:
|
||||
case GTK_DIR_RIGHT:
|
||||
focus_sort_left_right (widget, direction, focus_order);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gboolean
|
||||
gtk_widget_focus_move (GtkWidget *widget,
|
||||
GtkDirectionType direction,
|
||||
GPtrArray *focus_order)
|
||||
{
|
||||
GtkWidget *focus_child = gtk_widget_get_focus_child (widget);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < focus_order->len; i ++)
|
||||
{
|
||||
GtkWidget *child = g_ptr_array_index (focus_order, i);
|
||||
|
||||
if (focus_child)
|
||||
{
|
||||
if (focus_child == child)
|
||||
{
|
||||
focus_child = NULL;
|
||||
|
||||
if (gtk_widget_child_focus (child, direction))
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else if (_gtk_widget_is_drawable (child) &&
|
||||
gtk_widget_is_ancestor (child, widget))
|
||||
{
|
||||
if (gtk_widget_child_focus (child, direction))
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -158,6 +158,8 @@ struct _GtkWidgetPrivate
|
||||
GtkWidget *next_sibling;
|
||||
GtkWidget *first_child;
|
||||
GtkWidget *last_child;
|
||||
|
||||
GtkWidget *focus_child;
|
||||
};
|
||||
|
||||
GtkCssNode * gtk_widget_get_css_node (GtkWidget *widget);
|
||||
@@ -303,6 +305,15 @@ void gtk_widget_forall (GtkWidget
|
||||
GtkCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
GtkWidget *gtk_widget_get_focus_child (GtkWidget *widget);
|
||||
|
||||
void gtk_widget_focus_sort (GtkWidget *widget,
|
||||
GtkDirectionType direction,
|
||||
GPtrArray *focus_order);
|
||||
gboolean gtk_widget_focus_move (GtkWidget *widget,
|
||||
GtkDirectionType direction,
|
||||
GPtrArray *focus_order);
|
||||
|
||||
/* inline getters */
|
||||
|
||||
static inline gboolean
|
||||
|
||||
+25
-185
@@ -236,9 +236,7 @@ struct _GtkWindowPrivate
|
||||
guint destroy_with_parent : 1;
|
||||
guint focus_on_map : 1;
|
||||
guint fullscreen_initially : 1;
|
||||
guint has_focus : 1;
|
||||
guint has_user_ref_count : 1;
|
||||
guint has_toplevel_focus : 1;
|
||||
guint hide_titlebar_when_maximized : 1;
|
||||
guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
|
||||
guint is_active : 1;
|
||||
@@ -324,7 +322,6 @@ enum {
|
||||
PROP_APPLICATION,
|
||||
/* Readonly properties */
|
||||
PROP_IS_ACTIVE,
|
||||
PROP_HAS_TOPLEVEL_FOCUS,
|
||||
|
||||
/* Writeonly properties */
|
||||
PROP_STARTUP_ID,
|
||||
@@ -528,7 +525,6 @@ static gchar *default_icon_name = NULL;
|
||||
static guint default_icon_serial = 0;
|
||||
static gboolean disable_startup_notification = FALSE;
|
||||
|
||||
static GQuark quark_gtk_embedded = 0;
|
||||
static GQuark quark_gtk_window_key_hash = 0;
|
||||
static GQuark quark_gtk_window_icon_info = 0;
|
||||
static GQuark quark_gtk_buildable_accels = 0;
|
||||
@@ -743,7 +739,6 @@ gtk_window_class_init (GtkWindowClass *klass)
|
||||
widget_class = (GtkWidgetClass*) klass;
|
||||
container_class = (GtkContainerClass*) klass;
|
||||
|
||||
quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
|
||||
quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
|
||||
quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
|
||||
quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
|
||||
@@ -957,13 +952,6 @@ gtk_window_class_init (GtkWindowClass *klass)
|
||||
FALSE,
|
||||
GTK_PARAM_READABLE);
|
||||
|
||||
window_props[PROP_HAS_TOPLEVEL_FOCUS] =
|
||||
g_param_spec_boolean ("has-toplevel-focus",
|
||||
P_("Focus in Toplevel"),
|
||||
P_("Whether the input focus is within this GtkWindow"),
|
||||
FALSE,
|
||||
GTK_PARAM_READABLE);
|
||||
|
||||
window_props[PROP_TYPE_HINT] =
|
||||
g_param_spec_enum ("type-hint",
|
||||
P_("Type hint"),
|
||||
@@ -1917,9 +1905,6 @@ gtk_window_get_property (GObject *object,
|
||||
case PROP_IS_ACTIVE:
|
||||
g_value_set_boolean (value, priv->is_active);
|
||||
break;
|
||||
case PROP_HAS_TOPLEVEL_FOCUS:
|
||||
g_value_set_boolean (value, priv->has_toplevel_focus);
|
||||
break;
|
||||
case PROP_TYPE_HINT:
|
||||
g_value_set_enum (value, priv->type_hint);
|
||||
break;
|
||||
@@ -2508,21 +2493,16 @@ void
|
||||
gtk_window_set_focus (GtkWindow *window,
|
||||
GtkWidget *focus)
|
||||
{
|
||||
GtkWindowPrivate *priv;
|
||||
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
|
||||
GtkWidget *parent;
|
||||
|
||||
g_return_if_fail (GTK_IS_WINDOW (window));
|
||||
|
||||
priv = window->priv;
|
||||
|
||||
if (focus)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_WIDGET (focus));
|
||||
g_return_if_fail (gtk_widget_get_can_focus (focus));
|
||||
}
|
||||
|
||||
if (focus)
|
||||
{
|
||||
if (!gtk_widget_get_visible (GTK_WIDGET (window)))
|
||||
priv->initial_focus = focus;
|
||||
else
|
||||
@@ -7858,7 +7838,6 @@ gtk_window_focus_in_event (GtkWidget *widget,
|
||||
*/
|
||||
if (gtk_widget_get_visible (widget))
|
||||
{
|
||||
_gtk_window_set_has_toplevel_focus (window, TRUE);
|
||||
_gtk_window_set_is_active (window, TRUE);
|
||||
|
||||
if (gtk_window_has_mnemonic_modifier_pressed (window))
|
||||
@@ -7874,7 +7853,6 @@ gtk_window_focus_out_event (GtkWidget *widget,
|
||||
{
|
||||
GtkWindow *window = GTK_WINDOW (widget);
|
||||
|
||||
_gtk_window_set_has_toplevel_focus (window, FALSE);
|
||||
_gtk_window_set_is_active (window, FALSE);
|
||||
|
||||
/* set the mnemonic-visible property to false */
|
||||
@@ -7918,11 +7896,7 @@ gtk_window_remove (GtkContainer *container,
|
||||
static void
|
||||
gtk_window_check_resize (GtkContainer *container)
|
||||
{
|
||||
/* If the window is not toplevel anymore than it's embedded somewhere,
|
||||
* so handle it like a normal window */
|
||||
if (!_gtk_widget_is_toplevel (GTK_WIDGET (container)))
|
||||
GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
|
||||
else if (!_gtk_widget_get_alloc_needed (GTK_WIDGET (container)))
|
||||
if (!_gtk_widget_get_alloc_needed (GTK_WIDGET (container)))
|
||||
GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
|
||||
else if (gtk_widget_get_visible (GTK_WIDGET (container)))
|
||||
gtk_window_move_resize (GTK_WINDOW (container));
|
||||
@@ -7978,7 +7952,7 @@ gtk_window_focus (GtkWidget *widget,
|
||||
priv = window->priv;
|
||||
bin = GTK_BIN (widget);
|
||||
|
||||
old_focus_child = gtk_container_get_focus_child (container);
|
||||
old_focus_child = gtk_widget_get_focus_child (widget);
|
||||
|
||||
/* We need a special implementation here to deal properly with wrapping
|
||||
* around in the tab chain without the danger of going into an
|
||||
@@ -8004,7 +7978,7 @@ gtk_window_focus (GtkWidget *widget,
|
||||
parent = _gtk_widget_get_parent (priv->focus_widget);
|
||||
while (parent)
|
||||
{
|
||||
gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
|
||||
gtk_widget_set_focus_child (parent, NULL);
|
||||
parent = _gtk_widget_get_parent (parent);
|
||||
}
|
||||
|
||||
@@ -8043,7 +8017,7 @@ gtk_window_move_focus (GtkWidget *widget,
|
||||
|
||||
gtk_widget_child_focus (widget, dir);
|
||||
|
||||
if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
|
||||
if (!gtk_widget_get_focus_child (widget))
|
||||
gtk_window_set_focus (GTK_WINDOW (widget), NULL);
|
||||
}
|
||||
|
||||
@@ -8087,7 +8061,7 @@ gtk_window_real_set_focus (GtkWindow *window,
|
||||
|
||||
priv->focus_widget = NULL;
|
||||
|
||||
if (priv->has_focus)
|
||||
if (priv->is_active)
|
||||
do_focus_change (old_focus, FALSE);
|
||||
|
||||
g_object_notify (G_OBJECT (old_focus), "is-focus");
|
||||
@@ -8110,7 +8084,7 @@ gtk_window_real_set_focus (GtkWindow *window,
|
||||
_gtk_widget_set_has_default (priv->default_widget, FALSE);
|
||||
}
|
||||
|
||||
if (priv->has_focus)
|
||||
if (priv->is_active)
|
||||
do_focus_change (priv->focus_widget, TRUE);
|
||||
|
||||
/* It's possible for do_focus_change() above to have callbacks
|
||||
@@ -8209,7 +8183,7 @@ _gtk_window_unset_focus_and_default (GtkWindow *window,
|
||||
g_object_ref (widget);
|
||||
|
||||
parent = _gtk_widget_get_parent (widget);
|
||||
if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
|
||||
if (gtk_widget_get_focus_child (parent) == widget)
|
||||
{
|
||||
child = priv->focus_widget;
|
||||
|
||||
@@ -10267,7 +10241,6 @@ _gtk_window_get_screen (GtkWindow *window)
|
||||
* The return value is %TRUE if the window is active toplevel itself.
|
||||
* You might use this function if you wanted to draw a widget
|
||||
* differently in an active window from a widget in an inactive window.
|
||||
* See gtk_window_has_toplevel_focus()
|
||||
*
|
||||
* Returns: %TRUE if the window part of the current active window.
|
||||
*
|
||||
@@ -10281,26 +10254,6 @@ gtk_window_is_active (GtkWindow *window)
|
||||
return window->priv->is_active;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_window_has_toplevel_focus:
|
||||
* @window: a #GtkWindow
|
||||
*
|
||||
* Returns whether the input focus is within this GtkWindow.
|
||||
* For real toplevel windows, this is identical to gtk_window_is_active(),
|
||||
* but for embedded windows, like #GtkPlug, the results will differ.
|
||||
*
|
||||
* Returns: %TRUE if the input focus is within this GtkWindow
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
gboolean
|
||||
gtk_window_has_toplevel_focus (GtkWindow *window)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
|
||||
|
||||
return window->priv->has_toplevel_focus;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_window_get_group:
|
||||
* @window: (allow-none): a #GtkWindow, or %NULL
|
||||
@@ -10663,34 +10616,6 @@ gtk_window_activate_key (GtkWindow *window,
|
||||
return gtk_window_activate_menubar (window, event);
|
||||
}
|
||||
|
||||
static void
|
||||
window_update_has_focus (GtkWindow *window)
|
||||
{
|
||||
GtkWindowPrivate *priv = window->priv;
|
||||
GtkWidget *widget = GTK_WIDGET (window);
|
||||
gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
|
||||
|
||||
if (has_focus != priv->has_focus)
|
||||
{
|
||||
priv->has_focus = has_focus;
|
||||
|
||||
if (has_focus)
|
||||
{
|
||||
if (priv->focus_widget &&
|
||||
priv->focus_widget != widget &&
|
||||
!gtk_widget_has_focus (priv->focus_widget))
|
||||
do_focus_change (priv->focus_widget, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (priv->focus_widget &&
|
||||
priv->focus_widget != widget &&
|
||||
gtk_widget_has_focus (priv->focus_widget))
|
||||
do_focus_change (priv->focus_widget, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_window_set_is_active:
|
||||
* @window: a #GtkWindow
|
||||
@@ -10714,114 +10639,29 @@ _gtk_window_set_is_active (GtkWindow *window,
|
||||
|
||||
if (is_active != priv->is_active)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (window);
|
||||
|
||||
priv->is_active = is_active;
|
||||
window_update_has_focus (window);
|
||||
|
||||
if (is_active)
|
||||
{
|
||||
if (priv->focus_widget &&
|
||||
priv->focus_widget != widget &&
|
||||
!gtk_widget_has_focus (priv->focus_widget))
|
||||
do_focus_change (priv->focus_widget, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (priv->focus_widget &&
|
||||
priv->focus_widget != widget &&
|
||||
gtk_widget_has_focus (priv->focus_widget))
|
||||
do_focus_change (priv->focus_widget, FALSE);
|
||||
}
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_IS_ACTIVE]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_window_set_is_toplevel:
|
||||
* @window: a #GtkWindow
|
||||
* @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
|
||||
* child of the root window); %FALSE if it is not (for example, for an
|
||||
* in-process, parented GtkPlug)
|
||||
*
|
||||
* Internal function used by #GtkPlug when it gets parented/unparented by a
|
||||
* #GtkSocket. This keeps the @window’s #GTK_WINDOW_TOPLEVEL flag in sync
|
||||
* with the global list of toplevel windows.
|
||||
*/
|
||||
void
|
||||
_gtk_window_set_is_toplevel (GtkWindow *window,
|
||||
gboolean is_toplevel)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GtkWidget *toplevel;
|
||||
|
||||
widget = GTK_WIDGET (window);
|
||||
|
||||
if (_gtk_widget_is_toplevel (widget))
|
||||
g_assert (g_slist_find (toplevel_list, window) != NULL);
|
||||
else
|
||||
g_assert (g_slist_find (toplevel_list, window) == NULL);
|
||||
|
||||
if (is_toplevel == _gtk_widget_is_toplevel (widget))
|
||||
return;
|
||||
|
||||
if (is_toplevel)
|
||||
{
|
||||
/* Pass through regular pathways of an embedded toplevel
|
||||
* to go through unmapping and hiding the widget before
|
||||
* becomming a toplevel again.
|
||||
*
|
||||
* We remain hidden after becomming toplevel in order to
|
||||
* avoid problems during an embedded toplevel's dispose cycle
|
||||
* (When a toplevel window is shown it tries to grab focus again,
|
||||
* this causes problems while disposing).
|
||||
*/
|
||||
gtk_widget_hide (widget);
|
||||
|
||||
/* Save the toplevel this widget was previously anchored into before
|
||||
* propagating a hierarchy-changed.
|
||||
*
|
||||
* Usually this happens by way of gtk_widget_unparent() and we are
|
||||
* already unanchored at this point, just adding this clause incase
|
||||
* things happen differently.
|
||||
*/
|
||||
toplevel = _gtk_widget_get_toplevel (widget);
|
||||
if (!_gtk_widget_is_toplevel (toplevel))
|
||||
toplevel = NULL;
|
||||
|
||||
_gtk_widget_set_is_toplevel (widget, TRUE);
|
||||
|
||||
/* When a window becomes toplevel after being embedded and anchored
|
||||
* into another window we need to unset its anchored flag so that
|
||||
* the hierarchy changed signal kicks in properly.
|
||||
*/
|
||||
_gtk_widget_set_anchored (widget, FALSE);
|
||||
_gtk_widget_propagate_hierarchy_changed (widget, toplevel);
|
||||
|
||||
toplevel_list = g_slist_prepend (toplevel_list, window);
|
||||
}
|
||||
else
|
||||
{
|
||||
_gtk_widget_set_is_toplevel (widget, FALSE);
|
||||
toplevel_list = g_slist_remove (toplevel_list, window);
|
||||
_gtk_widget_propagate_hierarchy_changed (widget, widget);
|
||||
}
|
||||
gtk_window_update_debugging ();
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_window_set_has_toplevel_focus:
|
||||
* @window: a #GtkWindow
|
||||
* @has_toplevel_focus: %TRUE if the in
|
||||
*
|
||||
* Internal function that sets whether the keyboard focus for the
|
||||
* toplevel window (taking into account inter-process embedding.)
|
||||
**/
|
||||
void
|
||||
_gtk_window_set_has_toplevel_focus (GtkWindow *window,
|
||||
gboolean has_toplevel_focus)
|
||||
{
|
||||
GtkWindowPrivate *priv;
|
||||
|
||||
g_return_if_fail (GTK_IS_WINDOW (window));
|
||||
|
||||
priv = window->priv;
|
||||
|
||||
has_toplevel_focus = has_toplevel_focus != FALSE;
|
||||
|
||||
if (has_toplevel_focus != priv->has_toplevel_focus)
|
||||
{
|
||||
priv->has_toplevel_focus = has_toplevel_focus;
|
||||
window_update_has_focus (window);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_HAS_TOPLEVEL_FOCUS]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_window_set_auto_startup_notification:
|
||||
* @setting: %TRUE to automatically do startup notification
|
||||
|
||||
@@ -263,8 +263,6 @@ GdkScreen* gtk_window_get_screen (GtkWindow *window);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_window_is_active (GtkWindow *window);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_window_has_toplevel_focus (GtkWindow *window);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_window_set_decorated (GtkWindow *window,
|
||||
|
||||
@@ -46,17 +46,12 @@ gboolean _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *
|
||||
GtkWidget *widget,
|
||||
GdkDevice *device);
|
||||
|
||||
void _gtk_window_set_has_toplevel_focus (GtkWindow *window,
|
||||
gboolean has_toplevel_focus);
|
||||
void _gtk_window_unset_focus_and_default (GtkWindow *window,
|
||||
GtkWidget *widget);
|
||||
|
||||
void _gtk_window_set_is_active (GtkWindow *window,
|
||||
gboolean is_active);
|
||||
|
||||
void _gtk_window_set_is_toplevel (GtkWindow *window,
|
||||
gboolean is_toplevel);
|
||||
|
||||
void _gtk_window_set_allocation (GtkWindow *window,
|
||||
const GtkAllocation *allocation,
|
||||
GtkAllocation *allocation_out);
|
||||
|
||||
@@ -3,10 +3,6 @@
|
||||
<!-- interface-requires gtk+ 3.10 -->
|
||||
<template class="GtkStatusbar" parent="GtkBox">
|
||||
<property name="spacing">2</property>
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">6</property>
|
||||
<property name="margin-bottom">6</property>
|
||||
<child>
|
||||
<object class="GtkFrame" id="frame">
|
||||
<property name="shadow-type">none</property>
|
||||
|
||||
@@ -156,6 +156,7 @@ noinst_PROGRAMS = $(TEST_PROGS) \
|
||||
testpopup \
|
||||
testpopupat \
|
||||
testgaction \
|
||||
testwidgetfocus \
|
||||
$(NULL)
|
||||
|
||||
if USE_X11
|
||||
@@ -268,6 +269,7 @@ testrevealer2_DEPENDENCIES = $(TEST_DEPS)
|
||||
testtitlebar_DEPENDENCIES = $(TEST_DEPS)
|
||||
testwindowsize_DEPENDENCIES = $(TEST_DEPS)
|
||||
listmodel_DEPENDENCIES = $(TEST_DEPS)
|
||||
testwidgetfoucs_DEPENDENCIES = $(TEST_DEPS)
|
||||
|
||||
animated_resizing_SOURCES = \
|
||||
animated-resizing.c \
|
||||
@@ -457,6 +459,8 @@ testglblending_SOURCES = \
|
||||
|
||||
listmodel_SOURCES = listmodel.c
|
||||
|
||||
testwidgetfocus_SOURCES = testwidgetfocus.c
|
||||
|
||||
EXTRA_DIST += \
|
||||
gradient1.png \
|
||||
testgtk.1 \
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
|
||||
|
||||
typedef struct _GtkFocusWidget GtkFocusWidget;
|
||||
typedef struct _GtkFocusWidgetClass GtkFocusWidgetClass;
|
||||
|
||||
#define GTK_TYPE_FOCUS_WIDGET (gtk_focus_widget_get_type ())
|
||||
#define GTK_FOCUS_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj, GTK_TYPE_FOCUS_WIDGET, GtkFocusWidget))
|
||||
#define GTK_FOCUS_WIDGET_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST(cls, GTK_TYPE_FOCUS_WIDGET, GtkFocusWidgetClass))
|
||||
#define GTK_IS_FOCUS_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE(obj, GTK_TYPE_FOCUS_WIDGET))
|
||||
#define GTK_IS_FOCUS_WIDGET_CLASS(cls) (G_TYPE_CHECK_CLASS_TYPE(cls, GTK_TYPE_FOCUS_WIDGET))
|
||||
#define GTK_FOCUS_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS(obj, GTK_TYPE_FOCUS_WIDGET, GtkFocusWidgetClass))
|
||||
|
||||
#define SPACING 30
|
||||
|
||||
struct _GtkFocusWidget
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
union {
|
||||
struct {
|
||||
GtkWidget *child1;
|
||||
GtkWidget *child2;
|
||||
GtkWidget *child3;
|
||||
GtkWidget *child4;
|
||||
};
|
||||
GtkWidget* children[4];
|
||||
};
|
||||
};
|
||||
|
||||
struct _GtkFocusWidgetClass
|
||||
{
|
||||
GtkWidgetClass parent_class;
|
||||
};
|
||||
|
||||
GType gtk_focus_widget_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
G_DEFINE_TYPE(GtkFocusWidget, gtk_focus_widget, GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
gtk_focus_widget_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
|
||||
{
|
||||
GtkFocusWidget *self = GTK_FOCUS_WIDGET (widget);
|
||||
int child_width = (allocation->width - (3 * SPACING)) / 2;
|
||||
int child_height = (allocation->height - (3 * SPACING)) / 2;
|
||||
GtkAllocation child_alloc;
|
||||
|
||||
child_alloc.x = SPACING + allocation->x;
|
||||
child_alloc.y = SPACING + allocation->y;
|
||||
child_alloc.width = child_width;
|
||||
child_alloc.height = child_height;
|
||||
|
||||
gtk_widget_size_allocate (self->child1, &child_alloc);
|
||||
|
||||
child_alloc.x += SPACING + child_width;
|
||||
|
||||
gtk_widget_size_allocate (self->child2, &child_alloc);
|
||||
|
||||
child_alloc.y += SPACING + child_height;
|
||||
|
||||
gtk_widget_size_allocate (self->child4, &child_alloc);
|
||||
|
||||
child_alloc.x -= SPACING + child_width;
|
||||
|
||||
gtk_widget_size_allocate (self->child3, &child_alloc);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_focus_widget_measure (GtkWidget *widget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural,
|
||||
int *minimum_baseline,
|
||||
int *natural_baseline)
|
||||
{
|
||||
GtkFocusWidget *self = GTK_FOCUS_WIDGET (widget);
|
||||
int min, nat;
|
||||
int i;
|
||||
|
||||
*minimum = 0;
|
||||
*natural = 0;
|
||||
|
||||
for (i = 0; i < 4; i ++)
|
||||
{
|
||||
gtk_widget_measure (self->children[i], orientation, for_size,
|
||||
&min, &nat, NULL, NULL);
|
||||
|
||||
*minimum = MAX (*minimum, min);
|
||||
*natural = MAX (*natural, nat);
|
||||
}
|
||||
|
||||
*minimum *= 2;
|
||||
*natural *= 2;
|
||||
|
||||
*minimum += SPACING * 3;
|
||||
*natural += SPACING * 3;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_focus_widget_snapshot (GtkWidget *widget, GtkSnapshot *snapshot)
|
||||
{
|
||||
GtkFocusWidget *self = GTK_FOCUS_WIDGET (widget);
|
||||
|
||||
gtk_widget_snapshot_child (widget, self->child1, snapshot);
|
||||
gtk_widget_snapshot_child (widget, self->child2, snapshot);
|
||||
gtk_widget_snapshot_child (widget, self->child3, snapshot);
|
||||
gtk_widget_snapshot_child (widget, self->child4, snapshot);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_focus_widget_finalize (GObject *object)
|
||||
{
|
||||
GtkFocusWidget *self = GTK_FOCUS_WIDGET (object);
|
||||
|
||||
gtk_widget_unparent (self->child1);
|
||||
gtk_widget_unparent (self->child2);
|
||||
gtk_widget_unparent (self->child3);
|
||||
gtk_widget_unparent (self->child4);
|
||||
|
||||
G_OBJECT_CLASS (gtk_focus_widget_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_focus_widget_init (GtkFocusWidget *self)
|
||||
{
|
||||
gtk_widget_set_has_window (GTK_WIDGET (self), FALSE);
|
||||
|
||||
self->child1 = gtk_button_new_with_label ("1");
|
||||
gtk_widget_set_parent (self->child1, GTK_WIDGET (self));
|
||||
self->child2 = gtk_button_new_with_label ("2");
|
||||
gtk_widget_set_parent (self->child2, GTK_WIDGET (self));
|
||||
self->child3 = gtk_button_new_with_label ("3");
|
||||
gtk_widget_set_parent (self->child3, GTK_WIDGET (self));
|
||||
self->child4 = gtk_button_new_with_label ("4");
|
||||
gtk_widget_set_parent (self->child4, GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_focus_widget_class_init (GtkFocusWidgetClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->finalize = gtk_focus_widget_finalize;
|
||||
|
||||
widget_class->snapshot = gtk_focus_widget_snapshot;
|
||||
widget_class->measure = gtk_focus_widget_measure;
|
||||
widget_class->size_allocate = gtk_focus_widget_size_allocate;
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *widget;
|
||||
gtk_init ();
|
||||
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
widget = g_object_new (GTK_TYPE_FOCUS_WIDGET, NULL);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (window), widget);
|
||||
g_signal_connect (window, "delete-event", G_CALLBACK (gtk_main_quit), NULL);
|
||||
|
||||
gtk_widget_show (window);
|
||||
|
||||
gtk_main ();
|
||||
}
|
||||
Reference in New Issue
Block a user