[gnome-control-center] shell: Improve keyboard navigation
- From: Thomas Wood <thos src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-control-center] shell: Improve keyboard navigation
- Date: Wed, 2 Jun 2010 11:01:26 +0000 (UTC)
commit e14803b391276260d25bf5cab506a898f9f3c4ff
Author: Matthias Clasen <mclasen redhat com>
Date: Tue Jun 1 08:38:34 2010 -0400
shell: Improve keyboard navigation
When using keynav in the category views, the fact that the categories are
separate icon views leads to confusion, because each category will end up
with its own selected icon, so that you can end up with multiple selected
items (and the difference between focused/non-focused is not visually
obvious here). Also, since the category views appear visually as a single
unit, it is irritating that arrow keynav stops at category borders.
This commit arranges things so that only one category will ever have a
selected item by unselecting on focus-out. Furthermore, it uses the
keynav-failed signal and some new GTK+ api to make arrow up/down work across
category borders, in the expected way.
configure.ac | 2 +-
shell/gnome-control-center.c | 168 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 169 insertions(+), 1 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index aa9e4f7..25375cf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -106,7 +106,7 @@ dnl ==============================================
dnl Check that we meet the dependencies
dnl ==============================================
-COMMON_MODULES="gtk+-2.0 >= 2.20.0 dnl
+COMMON_MODULES="gtk+-2.0 >= 2.21.1 dnl
glib-2.0 >= 2.17.4 dnl
gthread-2.0 dnl
gio-2.0 dnl
diff --git a/shell/gnome-control-center.c b/shell/gnome-control-center.c
index e859fa9..cef8921 100644
--- a/shell/gnome-control-center.c
+++ b/shell/gnome-control-center.c
@@ -218,6 +218,160 @@ item_activated_cb (CcShellCategoryView *view,
}
static gboolean
+category_focus_out (GtkWidget *view,
+ GdkEventFocus *event,
+ GnomeControlCenter *shell)
+{
+ gtk_icon_view_unselect_all (GTK_ICON_VIEW (view));
+
+ return FALSE;
+}
+
+static gboolean
+category_focus_in (GtkWidget *view,
+ GdkEventFocus *event,
+ GnomeControlCenter *shell)
+{
+ GtkTreePath *path;
+
+ if (!gtk_icon_view_get_cursor (GTK_ICON_VIEW (view), &path, NULL))
+ {
+ path = gtk_tree_path_new_from_indices (0, -1);
+ gtk_icon_view_set_cursor (GTK_ICON_VIEW (view), path, NULL, FALSE);
+ }
+
+ gtk_icon_view_select_path (GTK_ICON_VIEW (view), path);
+ gtk_tree_path_free (path);
+
+ return FALSE;
+}
+
+static GList *
+get_item_views (GnomeControlCenter *shell)
+{
+ GnomeControlCenterPrivate *priv = shell->priv;
+ GtkWidget *vbox;
+ GList *list, *l;
+ GList *res;
+
+ vbox = W (priv->builder, "main-vbox");
+
+ list = gtk_container_get_children (GTK_CONTAINER (vbox));
+ res = NULL;
+ for (l = list; l; l = l->next)
+ {
+ res = g_list_append (res, cc_shell_category_view_get_item_view (CC_SHELL_CATEGORY_VIEW (l->data)));
+ }
+
+ g_list_free (list);
+
+ return res;
+}
+
+static gboolean
+keynav_failed (GtkIconView *current_view,
+ GtkDirectionType direction,
+ GnomeControlCenter *shell)
+{
+ GList *views, *v;
+ GtkIconView *new_view;
+ GtkTreePath *path;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gint col, c, dist, d;
+ GtkTreePath *sel;
+ gboolean res;
+
+ res = FALSE;
+
+ views = get_item_views (shell);
+
+ for (v = views; v; v = v->next)
+ {
+ if (v->data == current_view)
+ break;
+ }
+
+ if (direction == GTK_DIR_DOWN && v->next != NULL)
+ {
+ new_view = v->next->data;
+
+ if (gtk_icon_view_get_cursor (current_view, &path, NULL))
+ {
+ col = gtk_icon_view_get_item_column (current_view, path);
+ gtk_tree_path_free (path);
+
+ sel = NULL;
+ dist = 1000;
+ model = gtk_icon_view_get_model (new_view);
+ gtk_tree_model_get_iter_first (model, &iter);
+ do {
+ path = gtk_tree_model_get_path (model, &iter);
+ c = gtk_icon_view_get_item_column (new_view, path);
+ d = ABS (c - col);
+ if (d < dist)
+ {
+ if (sel)
+ gtk_tree_path_free (sel);
+ sel = path;
+ dist = d;
+ }
+ else
+ gtk_tree_path_free (path);
+ } while (gtk_tree_model_iter_next (model, &iter));
+
+ gtk_icon_view_set_cursor (new_view, sel, NULL, FALSE);
+ gtk_tree_path_free (sel);
+ }
+
+ gtk_widget_grab_focus (GTK_WIDGET (new_view));
+
+ res = TRUE;
+ }
+
+ if (direction == GTK_DIR_UP && v->prev != NULL)
+ {
+ new_view = v->prev->data;
+
+ if (gtk_icon_view_get_cursor (current_view, &path, NULL))
+ {
+ col = gtk_icon_view_get_item_column (current_view, path);
+ gtk_tree_path_free (path);
+
+ sel = NULL;
+ dist = 1000;
+ model = gtk_icon_view_get_model (new_view);
+ gtk_tree_model_get_iter_first (model, &iter);
+ do {
+ path = gtk_tree_model_get_path (model, &iter);
+ c = gtk_icon_view_get_item_column (new_view, path);
+ d = ABS (c - col);
+ if (d <= dist)
+ {
+ if (sel)
+ gtk_tree_path_free (sel);
+ sel = path;
+ dist = d;
+ }
+ else
+ gtk_tree_path_free (path);
+ } while (gtk_tree_model_iter_next (model, &iter));
+
+ gtk_icon_view_set_cursor (new_view, sel, NULL, FALSE);
+ gtk_tree_path_free (sel);
+ }
+
+ gtk_widget_grab_focus (GTK_WIDGET (new_view));
+
+ res = TRUE;
+ }
+
+ g_list_free (views);
+
+ return res;
+}
+
+static gboolean
model_filter_func (GtkTreeModel *model,
GtkTreeIter *iter,
GnomeControlCenterPrivate *priv)
@@ -394,10 +548,14 @@ fill_model (GnomeControlCenter *shell)
GMenuTreeDirectory *d;
GMenuTree *tree;
GtkWidget *vbox;
+ GtkWidget *sw;
GnomeControlCenterPrivate *priv = shell->priv;
vbox = W (priv->builder, "main-vbox");
+ sw = W (priv->builder, "scrolledwindow1");
+ gtk_container_set_focus_vadjustment (GTK_CONTAINER (vbox),
+ gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (sw)));
tree = gmenu_tree_lookup (MENUDIR "/gnomecc.menu", 0);
@@ -441,6 +599,16 @@ fill_model (GnomeControlCenter *shell)
"desktop-item-activated",
G_CALLBACK (item_activated_cb), shell);
gtk_widget_show (categoryview);
+ g_signal_connect (cc_shell_category_view_get_item_view (CC_SHELL_CATEGORY_VIEW (categoryview)),
+ "focus-in-event",
+ G_CALLBACK (category_focus_in), shell);
+ g_signal_connect (cc_shell_category_view_get_item_view (CC_SHELL_CATEGORY_VIEW (categoryview)),
+ "focus-out-event",
+ G_CALLBACK (category_focus_out), shell);
+ g_signal_connect (cc_shell_category_view_get_item_view (CC_SHELL_CATEGORY_VIEW (categoryview)),
+ "keynav-failed",
+ G_CALLBACK (keynav_failed), shell);
+
/* add the items from this category to the model */
for (f = contents; f; f = f->next)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]