[gtk/wip/matthiasc/focus2: 5/6] widget: Add a next-focus-child API
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/matthiasc/focus2: 5/6] widget: Add a next-focus-child API
- Date: Sat, 2 Mar 2019 19:40:45 +0000 (UTC)
commit d3771c57edf782c2a1dbd29d85e3f2ed8bda13b5
Author: Matthias Clasen <mclasen redhat com>
Date: Sat Mar 2 14:35:14 2019 -0500
widget: Add a next-focus-child API
Move things around to make the focus chain introspectable.
Use the next-focus-child api in the move-focus implementation.
We add a next_focus_child vfunc that containers can
override to tweak the behavior.
gtk/gtkwidget.c | 9 ++++--
gtk/gtkwidget.h | 6 ++++
gtk/gtkwidgetfocus.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++-
gtk/gtkwidgetprivate.h | 3 ++
4 files changed, 89 insertions(+), 4 deletions(-)
---
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 0aaa77579c..8905298be9 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -931,6 +931,7 @@ gtk_widget_class_init (GtkWidgetClass *klass)
klass->mnemonic_activate = gtk_widget_real_mnemonic_activate;
klass->grab_focus = gtk_widget_real_grab_focus;
klass->focus = gtk_widget_real_focus;
+ klass->next_focus_child = gtk_widget_next_focus_child;
klass->move_focus = gtk_widget_real_move_focus;
klass->keynav_failed = gtk_widget_real_keynav_failed;
klass->drag_begin = NULL;
@@ -5441,10 +5442,12 @@ static void
gtk_widget_real_move_focus (GtkWidget *widget,
GtkDirectionType direction)
{
- GtkWidget *toplevel = _gtk_widget_get_toplevel (widget);
+ GtkWidget *focus_child;
+ GtkWidget *next_focus;
- if (widget != toplevel && GTK_IS_WINDOW (toplevel))
- g_signal_emit (toplevel, widget_signals[MOVE_FOCUS], 0, direction);
+ focus_child = gtk_root_get_focus (gtk_widget_get_root (widget));
+ next_focus = gtk_widget_get_next_focus (focus_child, direction);
+ gtk_widget_grab_focus (next_focus);
}
static gboolean
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index db4a81272c..c9d7d566aa 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -280,6 +280,9 @@ struct _GtkWidgetClass
void (* grab_focus) (GtkWidget *widget);
gboolean (* focus) (GtkWidget *widget,
GtkDirectionType direction);
+ GtkWidget * (* next_focus_child) (GtkWidget *widget,
+ GtkWidget *child,
+ GtkDirectionType direction);
/* keyboard navigation */
void (* move_focus) (GtkWidget *widget,
@@ -480,6 +483,9 @@ gboolean gtk_widget_has_visible_focus (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_widget_grab_focus (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
+GtkWidget *gtk_widget_get_next_focus (GtkWidget *widget,
+ GtkDirectionType direction);
+GDK_AVAILABLE_IN_ALL
void gtk_widget_set_focus_on_click (GtkWidget *widget,
gboolean focus_on_click);
GDK_AVAILABLE_IN_ALL
diff --git a/gtk/gtkwidgetfocus.c b/gtk/gtkwidgetfocus.c
index c29adfdbe0..59c2c713eb 100644
--- a/gtk/gtkwidgetfocus.c
+++ b/gtk/gtkwidgetfocus.c
@@ -422,7 +422,8 @@ gtk_widget_focus_sort (GtkWidget *widget,
child != NULL;
child = _gtk_widget_get_next_sibling (child))
{
- if (_gtk_widget_get_realized (child))
+ if (_gtk_widget_get_realized (child) &&
+ gtk_widget_get_sensitive (child))
g_ptr_array_add (focus_order, child);
}
}
@@ -483,3 +484,75 @@ gtk_widget_focus_move (GtkWidget *widget,
return ret;
}
+
+/**
+ * gtk_widget_get_next_focus:
+ * @widget: a #GtkWidget
+ * @direction: diretion to move in
+ *
+ * Finds the widget that would get focused if @widget was
+ * the focus widget, and focus was moved in @direcion.
+ *
+ * Returns: (nullable): (transfer none): the next focus widget
+ */
+GtkWidget *
+gtk_widget_get_next_focus (GtkWidget *widget,
+ GtkDirectionType dir)
+{
+ GtkWidget *prev;
+ GtkWidget *next;
+
+ prev = NULL;
+ do {
+ next = GTK_WIDGET_GET_CLASS (widget)->next_focus_child (widget, prev, dir);
+ if (gtk_widget_get_can_focus (next))
+ {
+ return next;
+ }
+ else if (next == NULL)
+ {
+ prev = widget;
+ widget = gtk_widget_get_parent (widget);
+ }
+ else
+ {
+ widget = next;
+ prev = NULL;
+ }
+ } while (widget);
+
+ return NULL;
+}
+
+GtkWidget *
+gtk_widget_next_focus_child (GtkWidget *widget,
+ GtkWidget *focus_child,
+ GtkDirectionType direction)
+{
+ GPtrArray *focus_order;
+ int i;
+ GtkWidget *next_child = NULL;
+
+ focus_order = g_ptr_array_new ();
+ gtk_widget_focus_sort (widget, direction, focus_order);
+
+ 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;
+ }
+ else
+ {
+ next_child = child;
+ break;
+ }
+ }
+
+ g_ptr_array_unref (focus_order);
+
+ return next_child;
+}
diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h
index 6510565ddb..ec4ca27fae 100644
--- a/gtk/gtkwidgetprivate.h
+++ b/gtk/gtkwidgetprivate.h
@@ -319,6 +319,9 @@ void gtk_widget_focus_sort (GtkWidget *wi
GPtrArray *focus_order);
gboolean gtk_widget_focus_move (GtkWidget *widget,
GtkDirectionType direction);
+GtkWidget * gtk_widget_next_focus_child (GtkWidget *widget,
+ GtkWidget *child,
+ GtkDirectionType direction);
void gtk_widget_get_surface_allocation (GtkWidget *widget,
GtkAllocation *allocation);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]