[gtk/wip/matthiasc/focus2: 32/32] label: Bring back link focus
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/matthiasc/focus2: 32/32] label: Bring back link focus
- Date: Sun, 3 Mar 2019 19:11:14 +0000 (UTC)
commit c0a5737427db0bd1e62ee56d2f9c3cdf5b6cfb54
Author: Matthias Clasen <mclasen redhat com>
Date: Sun Mar 3 14:06:15 2019 -0500
label: Bring back link focus
Handle key-pressed ourselves to maintain the intra-label
focus location for links. This works almost as well as
it did previously. One issue is that our ::focus-in
handler does not know which direction the focus is coming
from, so we always select the first link, whereas previously
we would select the last link for Shift-Tab.
gtk/gtklabel.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 136 insertions(+), 5 deletions(-)
---
diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
index c4c4db43d5..9ca02781ad 100644
--- a/gtk/gtklabel.c
+++ b/gtk/gtklabel.c
@@ -527,6 +527,7 @@ static void emit_activate_link (GtkLabel *label,
static gboolean range_is_in_ellipsis (GtkLabel *label,
gint range_start,
gint range_end);
+static GtkLabelLink *gtk_label_get_focus_link (GtkLabel *label);
/* Event controller callbacks */
static void gtk_label_multipress_gesture_pressed (GtkGestureMultiPress *gesture,
@@ -1129,8 +1130,12 @@ focus_in_cb (GtkEventControllerKey *controller,
{
GtkLabel *label = GTK_LABEL (widget);
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
+ GtkLabelSelectionInfo *info = priv->select_info;
- if (priv->select_info->selectable)
+ if (!info)
+ return;
+
+ if (info->selectable)
{
gboolean select_on_focus;
@@ -1144,18 +1149,20 @@ focus_in_cb (GtkEventControllerKey *controller,
}
else
{
- if (priv->select_info->links && !priv->in_click)
+ if (info->links && !priv->in_click)
{
GList *l;
+ int i;
- for (l = priv->select_info->links; l; l = l->next)
+ for (l = info->links, i = 0; l; l = l->next, i++)
{
GtkLabelLink *link = l->data;
if (!range_is_in_ellipsis (label, link->start, link->end))
{
- priv->select_info->selection_anchor = link->start;
- priv->select_info->selection_end = link->start;
+ info->selection_anchor = link->start;
+ info->selection_end = link->start;
_gtk_label_accessible_focus_link_changed (label);
+ gtk_widget_queue_draw (widget);
break;
}
}
@@ -1163,6 +1170,129 @@ focus_in_cb (GtkEventControllerKey *controller,
}
}
+static gboolean
+key_press_cb (GtkEventControllerKey *controller,
+ guint keyval,
+ guint keycode,
+ GdkModifierType modifiers,
+ GtkWidget *widget)
+{
+ GtkLabel *label = GTK_LABEL (widget);
+ GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
+ GtkLabelSelectionInfo *info = priv->select_info;
+ GtkDirectionType direction;
+ GtkLabelLink *focus_link;
+ GList *l;
+
+ if (keyval != GDK_KEY_Tab && keyval != GDK_KEY_KP_Tab)
+ return FALSE;
+
+ if ((modifiers & GDK_SHIFT_MASK) != 0)
+ direction = GTK_DIR_TAB_BACKWARD;
+ else
+ direction = GTK_DIR_TAB_FORWARD;
+
+ if (!info)
+ return FALSE;
+
+ if (info->selectable)
+ {
+ int index;
+ int i;
+
+ if (info->selection_anchor != info->selection_end)
+ return FALSE;
+
+ index = info->selection_anchor;
+
+ if (direction == GTK_DIR_TAB_FORWARD)
+ {
+ for (l = info->links, i = 0; l; l = l->next, i++)
+ {
+ GtkLabelLink *link = l->data;
+
+ if (link->start > index)
+ {
+ if (!range_is_in_ellipsis (label, link->start, link->end))
+ {
+ gtk_label_select_region_index (label, link->start, link->start);
+ _gtk_label_accessible_focus_link_changed (label);
+ gtk_widget_queue_draw (widget);
+ return TRUE;
+ }
+ }
+ }
+ }
+ else
+ {
+ for (l = g_list_last (info->links), i = g_list_length (info->links) - 1; l; l = l->prev, i--)
+ {
+ GtkLabelLink *link = l->data;
+
+ if (link->end < index)
+ {
+ if (!range_is_in_ellipsis (label, link->start, link->end))
+ {
+ gtk_label_select_region_index (label, link->start, link->start);
+ _gtk_label_accessible_focus_link_changed (label);
+ gtk_widget_queue_draw (widget);
+ return TRUE;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ focus_link = gtk_label_get_focus_link (label);
+ if (direction == GTK_DIR_TAB_FORWARD)
+ {
+ if (focus_link)
+ {
+ l = g_list_find (info->links, focus_link);
+ l = l->next;
+ }
+ else
+ l = info->links;
+ for (; l; l = l->next)
+ {
+ GtkLabelLink *link = l->data;
+ if (!range_is_in_ellipsis (label, link->start, link->end))
+ break;
+ }
+ }
+ else
+ {
+ if (focus_link)
+ {
+ l = g_list_find (info->links, focus_link);
+ l = l->prev;
+ }
+ else
+ l = g_list_last (info->links);
+ for (; l; l = l->prev)
+ {
+ GtkLabelLink *link = l->data;
+ if (!range_is_in_ellipsis (label, link->start, link->end))
+ break;
+ }
+ }
+
+ if (l)
+ {
+ focus_link = l->data;
+ info->selection_anchor = focus_link->start;
+ info->selection_end = focus_link->start;
+ _gtk_label_accessible_focus_link_changed (label);
+ gtk_widget_queue_draw (widget);
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
static void
gtk_label_set_property (GObject *object,
guint prop_id,
@@ -1348,6 +1478,7 @@ gtk_label_init (GtkLabel *label)
controller = gtk_event_controller_key_new ();
g_signal_connect (controller, "focus-in", G_CALLBACK (focus_in_cb), label);
+ g_signal_connect (controller, "key-pressed", G_CALLBACK (key_press_cb), label);
gtk_widget_add_controller (GTK_WIDGET (label), controller);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]