[gnome-builder] keybindings: support different keybindings between default and vim mode



commit e7b4c79f4e799a2d7da9a35ab704d3734d4ab232
Author: Christian Hergert <christian hergert me>
Date:   Sun Dec 28 02:58:29 2014 -0800

    keybindings: support different keybindings between default and vim mode
    
    This reloads keybindings when vim-mode setting changes. This allows us to
    have custom keybinding themes for each.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=742043

 src/app/gb-application.c                  |  108 +++++++++++++++++++++++------
 src/keybindings/gb-keybindings.c          |   21 ++++++
 src/keybindings/gb-keybindings.h          |    2 +
 src/resources/gnome-builder.gresource.xml |    1 +
 src/resources/keybindings/default.ini     |    4 +-
 src/resources/keybindings/vim.ini         |   38 ++++++++++
 6 files changed, 151 insertions(+), 23 deletions(-)
---
diff --git a/src/app/gb-application.c b/src/app/gb-application.c
index 4a8a009..5937423 100644
--- a/src/app/gb-application.c
+++ b/src/app/gb-application.c
@@ -40,7 +40,13 @@
 #define LANGUAGE_PATH "/org/gnome/builder/editor/language/"
 #define GSV_PATH "resource:///org/gnome/builder/styles/"
 
-G_DEFINE_TYPE (GbApplication, gb_application, GTK_TYPE_APPLICATION)
+struct _GbApplicationPrivate
+{
+  GbKeybindings *keybindings;
+  GSettings     *editor_settings;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (GbApplication, gb_application, GTK_TYPE_APPLICATION)
 
 static void
 gb_application_setup_search_paths (void)
@@ -259,51 +265,92 @@ gb_application_register_theme_overrides (GbApplication *application)
 }
 
 static void
-gb_application_register_keybindings (GbApplication *self)
+gb_application_load_keybindings (GbApplication *application,
+                                 const gchar   *name)
 {
-  GbKeybindings *keybindings;
+  GbKeybindings *keybindings = NULL;
   GError *error = NULL;
-  GBytes *bytes;
+  GBytes *bytes = NULL;
   gchar *path;
 
-  ENTRY;
+  g_return_if_fail (GB_IS_APPLICATION (application));
 
-  g_assert (GB_IS_APPLICATION (self));
+  if (application->priv->keybindings)
+    {
+      gb_keybindings_unregister (application->priv->keybindings,
+                                 GTK_APPLICATION (application));
+      g_clear_object (&application->priv->keybindings);
+    }
+
+  path = g_strdup_printf ("/org/gnome/builder/keybindings/%s.ini", name);
+  bytes = g_resources_lookup_data (path, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
+  g_free (path);
+
+  if (!bytes)
+    {
+      g_warning (_("Failed to load keybindings."));
+      return;
+    }
 
   keybindings = gb_keybindings_new ();
 
-  /*
-   * Load bundled keybindings.
-   */
-  bytes = g_resources_lookup_data ("/org/gnome/builder/keybindings/default.ini",
-                                   G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
   if (!gb_keybindings_load_bytes (keybindings, bytes, &error))
     {
-      g_warning (_("Failed to load default keybindings: %s"), error->message);
-      g_clear_error (&error);
+      g_warning (_("Failed to load keybindings: %s"), error->message);
+      goto cleanup;
     }
-  g_bytes_unref (bytes);
 
-  /*
-   * Load local overrides from ~/.config/gnome-builder/keybindings.ini
-   */
   path = g_build_filename (g_get_user_config_dir (),
                            "gnome-builder",
                            "keybindings.ini",
                            NULL);
+
   if (g_file_test (path, G_FILE_TEST_EXISTS) &&
       !gb_keybindings_load_path (keybindings, path, &error))
     {
       g_warning (_("Failed to load local keybindings: %s"), error->message);
-      g_clear_error (&error);
+      goto cleanup;
     }
+
   g_free (path);
 
-  gb_keybindings_register (keybindings, GTK_APPLICATION (self));
+  gb_keybindings_register (keybindings, GTK_APPLICATION (application));
 
-  g_object_unref (keybindings);
+  application->priv->keybindings = g_object_ref (keybindings);
 
-  EXIT;
+cleanup:
+  g_clear_object (&keybindings);
+  g_clear_error (&error);
+  g_clear_pointer (&bytes, g_bytes_unref);
+}
+
+static void
+gb_application_vim_mode_changed (GbApplication *self,
+                                 const gchar   *key,
+                                 GSettings     *settings)
+{
+  g_return_if_fail (GB_IS_APPLICATION (self));
+  g_return_if_fail (G_IS_SETTINGS (settings));
+
+  if (g_settings_get_boolean (settings, "vim-mode"))
+    gb_application_load_keybindings (self, "vim");
+  else
+    gb_application_load_keybindings (self, "default");
+}
+
+static void
+gb_application_register_keybindings (GbApplication *self)
+{
+  g_return_if_fail (GB_IS_APPLICATION (self));
+  g_return_if_fail (!self->priv->editor_settings);
+
+  self->priv->editor_settings = g_settings_new ("org.gnome.builder.editor");
+  g_signal_connect_object (self->priv->editor_settings,
+                           "changed::vim-mode",
+                           G_CALLBACK (gb_application_vim_mode_changed),
+                           self,
+                           G_CONNECT_SWAPPED);
+  gb_application_vim_mode_changed (self, NULL, self->priv->editor_settings);
 }
 
 static GbWorkbench *
@@ -570,6 +617,23 @@ gb_application_constructed (GObject *object)
 }
 
 static void
+gb_application_finalize (GObject *object)
+{
+  GbApplicationPrivate *priv;
+
+  ENTRY;
+
+  priv = GB_APPLICATION (object)->priv;
+
+  g_clear_object (&priv->editor_settings);
+  g_clear_object (&priv->keybindings);
+
+  G_OBJECT_CLASS (gb_application_parent_class)->finalize (object);
+
+  EXIT;
+}
+
+static void
 gb_application_class_init (GbApplicationClass *klass)
 {
   GApplicationClass *app_class = G_APPLICATION_CLASS (klass);
@@ -578,6 +642,7 @@ gb_application_class_init (GbApplicationClass *klass)
   ENTRY;
 
   object_class->constructed = gb_application_constructed;
+  object_class->finalize = gb_application_finalize;
 
   app_class->activate = gb_application_activate;
   app_class->startup = gb_application_startup;
@@ -591,5 +656,6 @@ static void
 gb_application_init (GbApplication *application)
 {
   ENTRY;
+  application->priv = gb_application_get_instance_private (application);
   EXIT;
 }
diff --git a/src/keybindings/gb-keybindings.c b/src/keybindings/gb-keybindings.c
index 51c62c9..e202506 100644
--- a/src/keybindings/gb-keybindings.c
+++ b/src/keybindings/gb-keybindings.c
@@ -162,6 +162,27 @@ gb_keybindings_register (GbKeybindings  *keybindings,
     }
 }
 
+void
+gb_keybindings_unregister (GbKeybindings  *keybindings,
+                           GtkApplication *application)
+{
+  GHashTableIter iter;
+  const gchar *action_name;
+  const gchar *accelerator;
+  gchar *accels[] = { NULL };
+
+  g_return_if_fail (GB_IS_KEYBINDINGS (keybindings));
+  g_return_if_fail (GTK_IS_APPLICATION (application));
+
+  g_hash_table_iter_init (&iter, keybindings->priv->keybindings);
+
+  while (g_hash_table_iter_next (&iter,
+                                 (gpointer *)&action_name,
+                                 (gpointer *)&accelerator))
+    gtk_application_set_accels_for_action (application, action_name,
+                                           (const gchar * const *)accels);
+}
+
 static void
 gb_keybindings_finalize (GObject *object)
 {
diff --git a/src/keybindings/gb-keybindings.h b/src/keybindings/gb-keybindings.h
index 98717b0..7d449ce 100644
--- a/src/keybindings/gb-keybindings.h
+++ b/src/keybindings/gb-keybindings.h
@@ -58,6 +58,8 @@ gboolean       gb_keybindings_load_path  (GbKeybindings   *keybindings,
                                           GError         **error);
 void           gb_keybindings_register   (GbKeybindings   *keybindings,
                                           GtkApplication  *application);
+void           gb_keybindings_unregister (GbKeybindings   *keybindings,
+                                          GtkApplication  *application);
 
 G_END_DECLS
 
diff --git a/src/resources/gnome-builder.gresource.xml b/src/resources/gnome-builder.gresource.xml
index 71ff8ca..4fde4e9 100644
--- a/src/resources/gnome-builder.gresource.xml
+++ b/src/resources/gnome-builder.gresource.xml
@@ -9,6 +9,7 @@
     <file>gtk/menus.ui</file>
 
     <file>keybindings/default.ini</file>
+    <file>keybindings/vim.ini</file>
 
     <file>language/defaults.ini</file>
 
diff --git a/src/resources/keybindings/default.ini b/src/resources/keybindings/default.ini
index 8740a40..9bed259 100644
--- a/src/resources/keybindings/default.ini
+++ b/src/resources/keybindings/default.ini
@@ -11,10 +11,10 @@ save-all = <Control><Alt>S
 
 [workspace]
 new-document = <Control><Shift>N
-open = <Control><Shift>O
+open = <Control>O
 
 [editor-frame]
-find = <Control><Shift>F
+find = <Control>F
 reformat = <Control><Shift>R
 scroll-down = <Control>E
 scroll-up = <Control>Y
diff --git a/src/resources/keybindings/vim.ini b/src/resources/keybindings/vim.ini
new file mode 100644
index 0000000..8cd272e
--- /dev/null
+++ b/src/resources/keybindings/vim.ini
@@ -0,0 +1,38 @@
+[app]
+quit = <Control>q
+preferences = <Control>comma
+
+[win]
+go-forward = <Control>I
+go-backward = <Control>O
+show-command-bar = <Control>space
+global-search = <Control>period
+save-all = <Control><Alt>S
+
+[workspace]
+new-document = <Control><Shift>N
+open = <Control><Shift>O
+
+[editor-frame]
+reformat = <Control><Shift>R
+scroll-down = <Control>E
+scroll-up = <Control>Y
+
+[editor-view]
+toggle-split = <Control><Shift>J
+switch-pane = <Control>J
+
+[stack]
+close = <Control>W
+focus-search = <Control>K
+focus-left = <Control>H
+focus-right = <Control>L
+move-document-left = <Control><Shift>H
+move-document-right = <Control><Shift>L
+split-document-left = <Control><Alt>H
+split-document-right = <Control><Alt>L
+save = <Control>S
+save-as = <Control><Shift>S
+preview = <Control><Alt>P
+previous-document = <Control><Alt>Page_Up
+next-document = <Control><Alt>Page_Down


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]