Merge branch 'focusable-containers' into 'master'
Focusable containers See merge request GNOME/gtk!929
This commit is contained in:
@@ -5522,31 +5522,79 @@ gtk_widget_real_style_updated (GtkWidget *widget)
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
direction_is_forward (GtkDirectionType direction)
|
||||
{
|
||||
switch (direction)
|
||||
{
|
||||
case GTK_DIR_TAB_FORWARD:
|
||||
case GTK_DIR_RIGHT:
|
||||
case GTK_DIR_DOWN:
|
||||
return TRUE;
|
||||
case GTK_DIR_TAB_BACKWARD:
|
||||
case GTK_DIR_LEFT:
|
||||
case GTK_DIR_UP:
|
||||
return FALSE;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_widget_real_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
if (gtk_widget_get_can_focus (widget))
|
||||
GtkWidget *focus;
|
||||
|
||||
/* The easy case: not focusable. Just try the children */
|
||||
if (!gtk_widget_get_can_focus (widget))
|
||||
{
|
||||
if (!gtk_widget_is_focus (widget))
|
||||
if (gtk_widget_focus_move (widget, direction))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* For focusable widgets, we want to focus the widget
|
||||
* before its children. We differentiate 3 cases:
|
||||
* 1) focus is currently on widget
|
||||
* 2) focus is on some child
|
||||
* 3) focus is outside
|
||||
*/
|
||||
|
||||
if (gtk_widget_is_focus (widget))
|
||||
{
|
||||
if (direction_is_forward (direction) &&
|
||||
gtk_widget_focus_move (widget, direction))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
focus = gtk_window_get_focus (GTK_WINDOW (gtk_widget_get_root (widget)));
|
||||
|
||||
if (focus && gtk_widget_is_ancestor (focus, widget))
|
||||
{
|
||||
if (gtk_widget_focus_move (widget, direction))
|
||||
return TRUE;
|
||||
|
||||
if (direction_is_forward (direction))
|
||||
return FALSE;
|
||||
else
|
||||
{
|
||||
gtk_widget_grab_focus (widget);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else if (_gtk_widget_get_first_child (widget) == NULL)
|
||||
|
||||
if (!direction_is_forward (direction))
|
||||
{
|
||||
/* No children, no possibility to focus anything */
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Try focusing any of the child widgets, depending on the given direction */
|
||||
if (gtk_widget_focus_move (widget, direction))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
gtk_widget_grab_focus (widget);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
5
testsuite/gtk/focus-chain/focusable-container.tab
Normal file
5
testsuite/gtk/focus-chain/focusable-container.tab
Normal file
@@ -0,0 +1,5 @@
|
||||
entry1 GtkText
|
||||
box
|
||||
entry2 GtkText
|
||||
entry3 GtkText
|
||||
WRAP
|
||||
@@ -0,0 +1,5 @@
|
||||
entry3 GtkText
|
||||
entry2 GtkText
|
||||
box
|
||||
entry1 GtkText
|
||||
WRAP
|
||||
29
testsuite/gtk/focus-chain/focusable-container.ui
Normal file
29
testsuite/gtk/focus-chain/focusable-container.ui
Normal file
@@ -0,0 +1,29 @@
|
||||
<interface>
|
||||
<object class="GtkWindow" id="window">
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkEntry">
|
||||
<property name="name">entry1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="name">box</property>
|
||||
<property name="can-focus">1</property>
|
||||
<child>
|
||||
<object class="GtkEntry">
|
||||
<property name="name">entry2</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry">
|
||||
<property name="name">entry3</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
@@ -136,6 +136,8 @@ focus_chain_tests = [
|
||||
[ 'basic', 'tab-backward' ],
|
||||
[ 'basic', 'left' ],
|
||||
[ 'basic', 'right' ],
|
||||
[ 'focusable-container', 'tab' ],
|
||||
[ 'focusable-container', 'tab-backward' ],
|
||||
]
|
||||
|
||||
focus_chain = executable(
|
||||
|
||||
@@ -92,9 +92,10 @@ generate_focus_chain (GtkWidget *window,
|
||||
{
|
||||
char *first = NULL;
|
||||
char *last = NULL;
|
||||
char *name;
|
||||
char *name = NULL;
|
||||
GString *output = g_string_new ("");
|
||||
GtkWidget *focus;
|
||||
int count = 0;
|
||||
|
||||
gtk_widget_show (window);
|
||||
|
||||
@@ -135,6 +136,7 @@ generate_focus_chain (GtkWidget *window,
|
||||
}
|
||||
|
||||
g_string_append_printf (output, "%s\n", name);
|
||||
count++;
|
||||
|
||||
if (!first)
|
||||
first = g_strdup (name);
|
||||
@@ -142,9 +144,16 @@ generate_focus_chain (GtkWidget *window,
|
||||
g_free (last);
|
||||
last = g_strdup (name);
|
||||
|
||||
if (count == 100)
|
||||
{
|
||||
g_string_append (output, "ABORT\n");
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
g_free (name);
|
||||
g_free (first);
|
||||
g_free (last);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user