[gnome-builder/wip/gtk4-port: 404/736] plugins/vim: toggle vim input-method based on setting




commit af2ad723ead0b4b87f6f505562899189f9c271a0
Author: Christian Hergert <chergert redhat com>
Date:   Tue Apr 5 10:42:40 2022 -0700

    plugins/vim: toggle vim input-method based on setting
    
    We can use the GbpVimWorkspaceAddin:active property to determine if the
    GtkSourceVimIMContext should be enabled with the key controller. Some fixes
    are needed in GtkSourceView for this which were found by using this method
    of enabling/disabling the "client widget".

 src/plugins/vim/gbp-vim-editor-page-addin.c | 158 ++++++++++++++++++++--------
 1 file changed, 116 insertions(+), 42 deletions(-)
---
diff --git a/src/plugins/vim/gbp-vim-editor-page-addin.c b/src/plugins/vim/gbp-vim-editor-page-addin.c
index 9ce7ab424..dc80667c7 100644
--- a/src/plugins/vim/gbp-vim-editor-page-addin.c
+++ b/src/plugins/vim/gbp-vim-editor-page-addin.c
@@ -28,42 +28,132 @@
 #include "gbp-vim-editor-page-addin.h"
 #include "gbp-vim-workspace-addin.h"
 
+static void gbp_vim_editor_page_addin_load                       (IdeEditorPageAddin    *addin,
+                                                                  IdeEditorPage         *page);
+static void gbp_vim_editor_page_addin_unload                     (IdeEditorPageAddin    *addin,
+                                                                  IdeEditorPage         *page);
+static void gbp_vim_editor_page_addin_notify_active_cb           (GbpVimEditorPageAddin *self,
+                                                                  GParamSpec            *pspec,
+                                                                  GbpVimWorkspaceAddin  *workspace_addin);
+static void gbp_vim_editor_page_addin_notify_command_bar_text_cb (GbpVimEditorPageAddin *self,
+                                                                  GParamSpec            *pspec,
+                                                                  GtkSourceVimIMContext *im_context);
+static void gbp_vim_editor_page_addin_notify_command_text_cb     (GbpVimEditorPageAddin *self,
+                                                                  GParamSpec            *pspec,
+                                                                  GtkSourceVimIMContext *im_context);
+static void gbp_vim_editor_page_addin_update                     (GbpVimEditorPageAddin *self);
+
 struct _GbpVimEditorPageAddin
 {
   GObject               parent_instance;
+
+  /* Unowned pointers */
   IdeEditorPage        *page;
   GbpVimWorkspaceAddin *workspace_addin;
+
+  /* Owned references */
+  GtkEventController   *key_controller;
+
+  guint                 enabled : 1;
 };
 
+static void
+editor_page_addin_iface_init (IdeEditorPageAddinInterface *iface)
+{
+  iface->load = gbp_vim_editor_page_addin_load;
+  iface->unload = gbp_vim_editor_page_addin_unload;
+}
+
+G_DEFINE_FINAL_TYPE_WITH_CODE (GbpVimEditorPageAddin, gbp_vim_editor_page_addin, G_TYPE_OBJECT,
+                               G_IMPLEMENT_INTERFACE (IDE_TYPE_EDITOR_PAGE_ADDIN, 
editor_page_addin_iface_init))
+
+static void
+gbp_vim_editor_page_addin_class_init (GbpVimEditorPageAddinClass *klass)
+{
+}
+
+static void
+gbp_vim_editor_page_addin_init (GbpVimEditorPageAddin *self)
+{
+}
+
 static void
 gbp_vim_editor_page_addin_update (GbpVimEditorPageAddin *self)
 {
   IdeWorkspaceAddin *workspace_addin;
+  IdeSourceView *view;
   IdeWorkspace *workspace;
+  GtkIMContext *im_context;
 
   IDE_ENTRY;
 
   g_assert (IDE_IS_EDITOR_PAGE_ADDIN (self));
   g_assert (IDE_IS_EDITOR_PAGE (self->page));
 
-  self->workspace_addin = NULL;
+  view = ide_editor_page_get_view (self->page);
+  im_context = gtk_event_controller_key_get_im_context (GTK_EVENT_CONTROLLER_KEY (self->key_controller));
+
+  if (self->workspace_addin != NULL)
+    {
+      g_signal_handlers_disconnect_by_func (self->workspace_addin,
+                                            G_CALLBACK (gbp_vim_editor_page_addin_notify_active_cb),
+                                            self);
+      self->workspace_addin = NULL;
+    }
 
   workspace = ide_widget_get_workspace (GTK_WIDGET (self->page));
   workspace_addin = ide_workspace_addin_find_by_module_name (workspace, "vim");
 
   if (workspace_addin == NULL || !GBP_IS_VIM_WORKSPACE_ADDIN (workspace_addin))
-    IDE_GOTO (failure);
+    IDE_GOTO (disabled);
 
   self->workspace_addin = GBP_VIM_WORKSPACE_ADDIN (workspace_addin);
 
-failure:
+  g_signal_connect_object (self->workspace_addin,
+                           "notify::active",
+                           G_CALLBACK (gbp_vim_editor_page_addin_notify_active_cb),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  if (!gbp_vim_workspace_addin_get_active (self->workspace_addin))
+    IDE_GOTO (disabled);
+
+  if (!self->enabled)
+    {
+      self->enabled = TRUE;
+      gtk_im_context_set_client_widget (im_context, GTK_WIDGET (view));
+      gtk_widget_add_controller (GTK_WIDGET (view), g_object_ref (self->key_controller));
+    }
+
+  IDE_EXIT;
+
+disabled:
+  if (self->enabled)
+    {
+      self->enabled = FALSE;
+      gtk_im_context_set_client_widget (im_context, NULL);
+      gtk_widget_remove_controller (GTK_WIDGET (view), self->key_controller);
+      gtk_event_controller_reset (self->key_controller);
+    }
+
   IDE_EXIT;
 }
 
 static void
-notify_command_bar_text_cb (GbpVimEditorPageAddin *self,
-                            GParamSpec            *pspec,
-                            GtkSourceVimIMContext *im_context)
+gbp_vim_editor_page_addin_notify_active_cb (GbpVimEditorPageAddin *self,
+                                            GParamSpec            *pspec,
+                                            GbpVimWorkspaceAddin  *workspace_addin)
+{
+  g_assert (GBP_IS_VIM_EDITOR_PAGE_ADDIN (self));
+  g_assert (GBP_IS_VIM_WORKSPACE_ADDIN (workspace_addin));
+
+  gbp_vim_editor_page_addin_update (self);
+}
+
+static void
+gbp_vim_editor_page_addin_notify_command_bar_text_cb (GbpVimEditorPageAddin *self,
+                                                      GParamSpec            *pspec,
+                                                      GtkSourceVimIMContext *im_context)
 {
   const char *command_bar;
 
@@ -77,9 +167,9 @@ notify_command_bar_text_cb (GbpVimEditorPageAddin *self,
 }
 
 static void
-notify_command_text_cb (GbpVimEditorPageAddin *self,
-                        GParamSpec            *pspec,
-                        GtkSourceVimIMContext *im_context)
+gbp_vim_editor_page_addin_notify_command_text_cb (GbpVimEditorPageAddin *self,
+                                                  GParamSpec            *pspec,
+                                                  GtkSourceVimIMContext *im_context)
 {
   const char *command;
 
@@ -97,8 +187,6 @@ gbp_vim_editor_page_addin_load (IdeEditorPageAddin *addin,
                                 IdeEditorPage      *page)
 {
   GbpVimEditorPageAddin *self = (GbpVimEditorPageAddin *)addin;
-  GtkEventController *key;
-  IdeSourceView *view;
   GtkIMContext *im_context;
 
   IDE_ENTRY;
@@ -108,34 +196,27 @@ gbp_vim_editor_page_addin_load (IdeEditorPageAddin *addin,
 
   self->page = page;
 
-  gbp_vim_editor_page_addin_update (self);
-
-  view = ide_editor_page_get_view (page);
-  key = gtk_event_controller_key_new ();
+  self->key_controller = gtk_event_controller_key_new ();
   im_context = gtk_source_vim_im_context_new ();
-  gtk_im_context_set_client_widget (im_context, GTK_WIDGET (view));
-  gtk_event_controller_set_propagation_phase (key, GTK_PHASE_CAPTURE);
-  gtk_event_controller_key_set_im_context (GTK_EVENT_CONTROLLER_KEY (key), im_context);
-  gtk_widget_add_controller (GTK_WIDGET (view), key);
-
-  /* TODO: Make this toggleable via GSettings, and bind a property from
-   * the workspace addin to enable this.
-   */
+  gtk_event_controller_set_propagation_phase (self->key_controller, GTK_PHASE_CAPTURE);
+  gtk_event_controller_key_set_im_context (GTK_EVENT_CONTROLLER_KEY (self->key_controller), im_context);
 
   g_signal_connect_object (im_context,
                            "notify::command-bar-text",
-                           G_CALLBACK (notify_command_bar_text_cb),
+                           G_CALLBACK (gbp_vim_editor_page_addin_notify_command_bar_text_cb),
                            self,
                            G_CONNECT_SWAPPED);
 
   g_signal_connect_object (im_context,
                            "notify::command-text",
-                           G_CALLBACK (notify_command_text_cb),
+                           G_CALLBACK (gbp_vim_editor_page_addin_notify_command_text_cb),
                            self,
                            G_CONNECT_SWAPPED);
 
   g_object_unref (im_context);
 
+  gbp_vim_editor_page_addin_update (self);
+
   IDE_EXIT;
 }
 
@@ -150,25 +231,18 @@ gbp_vim_editor_page_addin_unload (IdeEditorPageAddin *addin,
   g_assert (IDE_IS_EDITOR_PAGE_ADDIN (self));
   g_assert (IDE_IS_EDITOR_PAGE (page));
 
-  IDE_EXIT;
-}
+  if (self->enabled)
+    {
+      IdeSourceView *view = ide_editor_page_get_view (page);
 
-static void
-editor_page_addin_iface_init (IdeEditorPageAddinInterface *iface)
-{
-  iface->load = gbp_vim_editor_page_addin_load;
-  iface->unload = gbp_vim_editor_page_addin_unload;
-}
+      self->enabled = FALSE;
+      gtk_widget_remove_controller (GTK_WIDGET (view), self->key_controller);
+    }
 
-G_DEFINE_FINAL_TYPE_WITH_CODE (GbpVimEditorPageAddin, gbp_vim_editor_page_addin, G_TYPE_OBJECT,
-                               G_IMPLEMENT_INTERFACE (IDE_TYPE_EDITOR_PAGE_ADDIN, 
editor_page_addin_iface_init))
+  g_clear_object (&self->key_controller);
 
-static void
-gbp_vim_editor_page_addin_class_init (GbpVimEditorPageAddinClass *klass)
-{
-}
+  self->page = NULL;
+  self->workspace_addin = NULL;
 
-static void
-gbp_vim_editor_page_addin_init (GbpVimEditorPageAddin *self)
-{
+  IDE_EXIT;
 }


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