flowbox: correct the behavior with "can-focus"==FALSE
In fact there were two issues: 1. GtkFlowBoxChild with "can-focus"==FALSE should pass the focus to its child immediately. 2. GtkFlowBox with "can-focus"==FALSE should cease its custom keynav implementation and fall back to the default GtkContainer behavior which is more natural. Thanks to these changes the flow box can act as a better replacement for GtkGrid and similar containers. https://bugzilla.gnome.org/show_bug.cgi?id=753371
This commit is contained in:
parent
896f911ea1
commit
3c253c46a5
@ -292,6 +292,23 @@ gtk_flow_box_child_focus (GtkWidget *widget,
|
|||||||
|
|
||||||
child = gtk_bin_get_child (GTK_BIN (widget));
|
child = gtk_bin_get_child (GTK_BIN (widget));
|
||||||
|
|
||||||
|
/* Without "can-focus" flag try to pass the focus to the child immediately */
|
||||||
|
if (!gtk_widget_get_can_focus (widget))
|
||||||
|
{
|
||||||
|
if (child)
|
||||||
|
{
|
||||||
|
if (gtk_widget_child_focus (child, direction))
|
||||||
|
{
|
||||||
|
GtkFlowBox *box;
|
||||||
|
box = gtk_flow_box_child_get_box (GTK_FLOW_BOX_CHILD (widget));
|
||||||
|
if (box)
|
||||||
|
gtk_flow_box_update_cursor (box, GTK_FLOW_BOX_CHILD (widget));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
g_object_get (widget, "has-focus", &had_focus, NULL);
|
g_object_get (widget, "has-focus", &had_focus, NULL);
|
||||||
if (had_focus)
|
if (had_focus)
|
||||||
{
|
{
|
||||||
@ -3193,6 +3210,12 @@ gtk_flow_box_focus (GtkWidget *widget,
|
|||||||
GSequenceIter *iter;
|
GSequenceIter *iter;
|
||||||
GtkFlowBoxChild *next_focus_child;
|
GtkFlowBoxChild *next_focus_child;
|
||||||
|
|
||||||
|
/* Without "can-focus" flag fall back to the default behavior immediately */
|
||||||
|
if (!gtk_widget_get_can_focus (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_container_get_focus_child (GTK_CONTAINER (box));
|
||||||
next_focus_child = NULL;
|
next_focus_child = NULL;
|
||||||
|
|
||||||
@ -3313,7 +3336,7 @@ gtk_flow_box_toggle_cursor_child (GtkFlowBox *box)
|
|||||||
gtk_flow_box_select_and_activate (box, priv->cursor_child);
|
gtk_flow_box_select_and_activate (box, priv->cursor_child);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
gtk_flow_box_move_cursor (GtkFlowBox *box,
|
gtk_flow_box_move_cursor (GtkFlowBox *box,
|
||||||
GtkMovementStep step,
|
GtkMovementStep step,
|
||||||
gint count)
|
gint count)
|
||||||
@ -3331,6 +3354,10 @@ gtk_flow_box_move_cursor (GtkFlowBox *box,
|
|||||||
GtkAdjustment *adjustment;
|
GtkAdjustment *adjustment;
|
||||||
gboolean vertical;
|
gboolean vertical;
|
||||||
|
|
||||||
|
/* Without "can-focus" flag fall back to the default behavior immediately */
|
||||||
|
if (!gtk_widget_get_can_focus (GTK_WIDGET (box)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
vertical = priv->orientation == GTK_ORIENTATION_VERTICAL;
|
vertical = priv->orientation == GTK_ORIENTATION_VERTICAL;
|
||||||
|
|
||||||
if (vertical)
|
if (vertical)
|
||||||
@ -3479,17 +3506,25 @@ gtk_flow_box_move_cursor (GtkFlowBox *box,
|
|||||||
|
|
||||||
if (!gtk_widget_keynav_failed (GTK_WIDGET (box), direction))
|
if (!gtk_widget_keynav_failed (GTK_WIDGET (box), direction))
|
||||||
{
|
{
|
||||||
GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (box));
|
return FALSE;
|
||||||
|
|
||||||
if (toplevel)
|
|
||||||
gtk_widget_child_focus (toplevel,
|
|
||||||
direction == GTK_DIR_UP ?
|
|
||||||
GTK_DIR_TAB_BACKWARD :
|
|
||||||
GTK_DIR_TAB_FORWARD);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the child has its "can-focus" property set to FALSE then it will
|
||||||
|
* not grab the focus. We must pass the focus to its child directly.
|
||||||
|
*/
|
||||||
|
if (!gtk_widget_get_can_focus (GTK_WIDGET (child)))
|
||||||
|
{
|
||||||
|
GtkWidget *subchild;
|
||||||
|
|
||||||
|
subchild = gtk_bin_get_child (GTK_BIN (child));
|
||||||
|
if (subchild)
|
||||||
|
{
|
||||||
|
GtkDirectionType direction = count < 0 ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD;
|
||||||
|
gtk_widget_child_focus (subchild, direction);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get_current_selection_modifiers (GTK_WIDGET (box), &modify, &extend);
|
get_current_selection_modifiers (GTK_WIDGET (box), &modify, &extend);
|
||||||
@ -3497,6 +3532,7 @@ gtk_flow_box_move_cursor (GtkFlowBox *box,
|
|||||||
gtk_flow_box_update_cursor (box, child);
|
gtk_flow_box_update_cursor (box, child);
|
||||||
if (!modify)
|
if (!modify)
|
||||||
gtk_flow_box_update_selection (box, child, FALSE, extend);
|
gtk_flow_box_update_selection (box, child, FALSE, extend);
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Selection {{{2 */
|
/* Selection {{{2 */
|
||||||
@ -3845,8 +3881,6 @@ gtk_flow_box_class_init (GtkFlowBoxClass *class)
|
|||||||
* The ::move-cursor signal is a
|
* The ::move-cursor signal is a
|
||||||
* [keybinding signal][GtkBindingSignal]
|
* [keybinding signal][GtkBindingSignal]
|
||||||
* which gets emitted when the user initiates a cursor movement.
|
* which gets emitted when the user initiates a cursor movement.
|
||||||
* If the cursor is not visible in @text_view, this signal causes
|
|
||||||
* the viewport to be moved instead.
|
|
||||||
*
|
*
|
||||||
* Applications should not connect to it, but may emit it with
|
* Applications should not connect to it, but may emit it with
|
||||||
* g_signal_emit_by_name() if they need to control the cursor
|
* g_signal_emit_by_name() if they need to control the cursor
|
||||||
@ -3859,14 +3893,17 @@ gtk_flow_box_class_init (GtkFlowBoxClass *class)
|
|||||||
* - Arrow keys move by individual children
|
* - Arrow keys move by individual children
|
||||||
* - Home/End keys move to the ends of the box
|
* - Home/End keys move to the ends of the box
|
||||||
* - PageUp/PageDown keys move vertically by pages
|
* - PageUp/PageDown keys move vertically by pages
|
||||||
|
*
|
||||||
|
* Returns: %TRUE to stop other handlers from being invoked for the event.
|
||||||
|
* %FALSE to propagate the event further.
|
||||||
*/
|
*/
|
||||||
signals[MOVE_CURSOR] = g_signal_new (I_("move-cursor"),
|
signals[MOVE_CURSOR] = g_signal_new (I_("move-cursor"),
|
||||||
GTK_TYPE_FLOW_BOX,
|
GTK_TYPE_FLOW_BOX,
|
||||||
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
|
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
|
||||||
G_STRUCT_OFFSET (GtkFlowBoxClass, move_cursor),
|
G_STRUCT_OFFSET (GtkFlowBoxClass, move_cursor),
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
_gtk_marshal_VOID__ENUM_INT,
|
_gtk_marshal_BOOLEAN__ENUM_INT,
|
||||||
G_TYPE_NONE, 2,
|
G_TYPE_BOOLEAN, 2,
|
||||||
GTK_TYPE_MOVEMENT_STEP, G_TYPE_INT);
|
GTK_TYPE_MOVEMENT_STEP, G_TYPE_INT);
|
||||||
/**
|
/**
|
||||||
* GtkFlowBox::select-all:
|
* GtkFlowBox::select-all:
|
||||||
|
@ -61,7 +61,7 @@ struct _GtkFlowBoxClass
|
|||||||
void (*selected_children_changed) (GtkFlowBox *box);
|
void (*selected_children_changed) (GtkFlowBox *box);
|
||||||
void (*activate_cursor_child) (GtkFlowBox *box);
|
void (*activate_cursor_child) (GtkFlowBox *box);
|
||||||
void (*toggle_cursor_child) (GtkFlowBox *box);
|
void (*toggle_cursor_child) (GtkFlowBox *box);
|
||||||
void (*move_cursor) (GtkFlowBox *box,
|
gboolean (*move_cursor) (GtkFlowBox *box,
|
||||||
GtkMovementStep step,
|
GtkMovementStep step,
|
||||||
gint count);
|
gint count);
|
||||||
void (*select_all) (GtkFlowBox *box);
|
void (*select_all) (GtkFlowBox *box);
|
||||||
|
Loading…
Reference in New Issue
Block a user