[gtksourceview/wip/chergert/vim] read and write the system clipboard (and emulated primary)



commit 06d821fb131e59fc13bf33373dd6d2dcd6d6d480
Author: Christian Hergert <chergert redhat com>
Date:   Wed Nov 3 13:46:31 2021 -0700

    read and write the system clipboard (and emulated primary)

 gtksourceview/vim/gtk-source-vim-registers.c | 132 ++++++++++++++++++++++++++-
 1 file changed, 128 insertions(+), 4 deletions(-)
---
diff --git a/gtksourceview/vim/gtk-source-vim-registers.c b/gtksourceview/vim/gtk-source-vim-registers.c
index af55ec4e..536fd133 100644
--- a/gtksourceview/vim/gtk-source-vim-registers.c
+++ b/gtksourceview/vim/gtk-source-vim-registers.c
@@ -32,6 +32,9 @@ struct _GtkSourceVimRegisters
 
        GHashTable *values;
 
+       char *clipboard;
+       char *primary_clipboard;
+
        char *numbered[10];
        int numbered_pos;
 };
@@ -44,6 +47,8 @@ gtk_source_vim_registers_finalize (GObject *object)
        GtkSourceVimRegisters *self = (GtkSourceVimRegisters *)object;
 
        g_clear_pointer (&self->values, g_hash_table_unref);
+       g_clear_pointer (&self->clipboard, g_ref_string_release);
+       g_clear_pointer (&self->primary_clipboard, g_ref_string_release);
 
        for (guint i = 0; i < G_N_ELEMENTS (self->numbered); i++)
        {
@@ -70,6 +75,90 @@ gtk_source_vim_registers_init (GtkSourceVimRegisters *self)
                                              (GDestroyNotify)g_ref_string_release);
 }
 
+static void
+write_clipboard (GtkSourceVimRegisters *self,
+                 GdkClipboard          *clipboard,
+                 char                  *refstr)
+{
+       g_assert (GTK_SOURCE_IS_VIM_REGISTERS (self));
+       g_assert (GDK_IS_CLIPBOARD (clipboard));
+       g_assert (refstr != NULL);
+
+       gdk_clipboard_set_text (clipboard, refstr);
+}
+
+static gboolean
+cancel_cb (gpointer data)
+{
+       g_cancellable_cancel (data);
+       return G_SOURCE_REMOVE;
+}
+
+typedef struct
+{
+       char *text;
+       GMainLoop *main_loop;
+       GCancellable *cancellable;
+} ReadClipboard;
+
+static void
+read_clipboard_cb (GObject      *object,
+                   GAsyncResult *result,
+                   gpointer      user_data)
+{
+       ReadClipboard *clip = user_data;
+
+       g_assert (GDK_IS_CLIPBOARD (object));
+       g_assert (G_IS_ASYNC_RESULT (result));
+       g_assert (clip != NULL);
+       g_assert (clip->main_loop != NULL);
+       g_assert (G_IS_CANCELLABLE (clip->cancellable));
+
+       clip->text = gdk_clipboard_read_text_finish (GDK_CLIPBOARD (object), result, NULL);
+
+       g_main_loop_quit (clip->main_loop);
+}
+
+static void
+read_clipboard (GtkSourceVimRegisters  *self,
+                GdkClipboard           *clipboard,
+                char                  **text)
+{
+       ReadClipboard clip;
+       GSource *source;
+
+       g_assert (GTK_SOURCE_IS_VIM_REGISTERS (self));
+       g_assert (GDK_IS_CLIPBOARD (clipboard));
+
+       clip.text = NULL;
+       clip.main_loop = g_main_loop_new (NULL, FALSE);
+       clip.cancellable = g_cancellable_new ();
+
+       source = g_timeout_source_new (500);
+       g_source_set_name (source, "[gtksourceview cancel clipboard]");
+       g_source_set_callback (source, cancel_cb, clip.cancellable, NULL);
+       g_source_attach (source, NULL);
+
+       gdk_clipboard_read_text_async (clipboard,
+                                      clip.cancellable,
+                                      read_clipboard_cb,
+                                      &clip);
+
+       g_main_loop_run (clip.main_loop);
+
+       g_main_loop_unref (clip.main_loop);
+       g_object_unref (clip.cancellable);
+
+       g_source_destroy (source);
+
+       if (clip.text != NULL)
+       {
+               g_clear_pointer (text, g_ref_string_release);
+               *text = g_ref_string_new (clip.text);
+               g_free (clip.text);
+       }
+}
+
 GtkSourceVimState *
 gtk_source_vim_registers_new (void)
 {
@@ -80,6 +169,8 @@ const char *
 gtk_source_vim_registers_get (GtkSourceVimRegisters *self,
                               const char            *name)
 {
+       GtkSourceView *view;
+
        g_return_val_if_fail (GTK_SOURCE_IS_VIM_REGISTERS (self), NULL);
 
        if (name == NULL)
@@ -92,7 +183,24 @@ gtk_source_vim_registers_get (GtkSourceVimRegisters *self,
                return gtk_source_vim_registers_get_numbered (self, *name - '0');
        }
 
-       return g_hash_table_lookup (self->values, name);
+       view = gtk_source_vim_state_get_view (GTK_SOURCE_VIM_STATE (self));
+
+       if (g_str_equal (name, "+"))
+       {
+               GdkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (view));
+               read_clipboard (self, clipboard, &self->clipboard);
+               return self->clipboard;
+       }
+       else if (g_str_equal (name, "*"))
+       {
+               GdkClipboard *clipboard = gtk_widget_get_primary_clipboard (GTK_WIDGET (view));
+               read_clipboard (self, clipboard, &self->primary_clipboard);
+               return self->primary_clipboard;
+       }
+       else
+       {
+               return g_hash_table_lookup (self->values, name);
+       }
 }
 
 static inline char **
@@ -144,6 +252,7 @@ gtk_source_vim_registers_set (GtkSourceVimRegisters *self,
                               const char            *name,
                               const char            *value)
 {
+       GtkSourceView *view;
        char *str;
 
        g_return_if_fail (GTK_SOURCE_IS_VIM_REGISTERS (self));
@@ -166,9 +275,24 @@ gtk_source_vim_registers_set (GtkSourceVimRegisters *self,
        }
 
        str = g_ref_string_new (value);
-       g_hash_table_insert (self->values,
-                            (char *)g_intern_string (name),
-                            str);
+       view = gtk_source_vim_state_get_view (GTK_SOURCE_VIM_STATE (self));
+
+       if (g_str_equal (name, "+"))
+       {
+               GdkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (view));
+               write_clipboard (self, clipboard, str);
+       }
+       else if (g_str_equal (name, "*"))
+       {
+               GdkClipboard *clipboard = gtk_widget_get_primary_clipboard (GTK_WIDGET (view));
+               write_clipboard (self, clipboard, str);
+       }
+       else
+       {
+               g_hash_table_insert (self->values,
+                                    (char *)g_intern_string (name),
+                                    str);
+       }
 
        /* Push into the 0 numbered register and each 1..8 to
         * the next numbered register position.


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