keynav in the new shell, continued



I've amended my previous patch to fix arrow navigation between
categories. I'm very happy with how this works now.

The patch uses brandnew gtk api that I've only added in the 2.21.1
release earlier today.

Matthias
diff --git a/shell/gnome-control-center.c b/shell/gnome-control-center.c
index e859fa9..e764287 100644
--- a/shell/gnome-control-center.c
+++ b/shell/gnome-control-center.c
@@ -218,6 +218,149 @@ 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 (GtkWidget          *current_view,
+               GtkDirectionType    direction,
+               GnomeControlCenter *shell)
+{
+  GList *views, *v;
+  GtkWidget *new_view;
+  GtkTreePath *path;
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+  gint col;
+  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 (GTK_ICON_VIEW (current_view), &path, NULL))
+        {
+          col = gtk_icon_view_get_item_column (GTK_ICON_VIEW (current_view), path);
+          gtk_tree_path_free (path);
+
+          sel = NULL;
+          model = gtk_icon_view_get_model (GTK_ICON_VIEW (new_view));
+          gtk_tree_model_get_iter_first (model, &iter);
+          do {
+            path = gtk_tree_model_get_path (model, &iter);
+            if (gtk_icon_view_get_item_column (GTK_ICON_VIEW (new_view), path) == col)
+              {
+                sel = path;
+                break;
+              }
+          } while (gtk_tree_model_iter_next (model, &iter));
+
+          gtk_icon_view_set_cursor (GTK_ICON_VIEW (new_view), sel, NULL, FALSE);
+          gtk_tree_path_free (sel);
+        }
+
+      gtk_widget_grab_focus (new_view);
+
+      res = TRUE;
+    }
+
+  if (direction == GTK_DIR_UP && v->prev != NULL)
+    {
+      new_view = v->prev->data;
+
+      if (gtk_icon_view_get_cursor (GTK_ICON_VIEW (current_view), &path, NULL))
+        {
+          col = gtk_icon_view_get_item_column (GTK_ICON_VIEW (current_view), path);
+          gtk_tree_path_free (path);
+
+          sel = NULL;
+          model = gtk_icon_view_get_model (GTK_ICON_VIEW (new_view));
+          gtk_tree_model_get_iter_first (model, &iter);
+          do {
+            path = gtk_tree_model_get_path (model, &iter);
+            if (gtk_icon_view_get_item_column (GTK_ICON_VIEW (new_view), path) == col)
+              {
+                if (sel)
+                  gtk_tree_path_free (sel);
+                sel = path;
+              }
+            else
+              gtk_tree_path_free (path);
+          } while (gtk_tree_model_iter_next (model, &iter));
+
+          gtk_icon_view_set_cursor (GTK_ICON_VIEW (new_view), sel, NULL, FALSE);
+          gtk_tree_path_free (sel);
+        }
+
+      gtk_widget_grab_focus (new_view);
+
+      res = TRUE;
+    }
+
+  g_list_free (views);
+
+  return res;
+}
+
+static gboolean
 model_filter_func (GtkTreeModel              *model,
                    GtkTreeIter               *iter,
                    GnomeControlCenterPrivate *priv)
@@ -394,10 +537,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 +588,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]