[mutter/wip/carlosg/clipboard-manager: 66/69] core: Add clipboard manager



commit c3ade7eda81b57ea2b6d4a1d1c6eb0f00c7094e3
Author: Carlos Garnacho <carlosg gnome org>
Date:   Mon Nov 19 19:57:15 2018 +0100

    core: Add clipboard manager
    
    This is a simple clipboard manager implementation on top of MetaSelection.
    It will inspect the clipboard content for UTF-8 text whenever any other
    selection source claims ownership, and claim it for itself whenever the
    clipboard goes unowned.
    
    The stored text has a maximum size of 4MB, any further content will be
    simply cut down.
    
    This is not quite a X11 clipboard manager, but also works there.

 src/Makefile.am                   |   2 +
 src/core/display-private.h        |   2 +
 src/core/display.c                |   4 ++
 src/core/meta-clipboard-manager.c | 119 ++++++++++++++++++++++++++++++++++++++
 src/core/meta-clipboard-manager.h |  29 ++++++++++
 src/meson.build                   |   2 +
 6 files changed, 158 insertions(+)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index b9052b87c..15c3f79a3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -287,6 +287,8 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES =      \
        core/constraints.c                      \
        core/constraints.h                      \
        core/core.c                             \
+       core/meta-clipboard-manager.c           \
+       core/meta-clipboard-manager.h           \
        core/meta-close-dialog.c                \
        meta/meta-close-dialog.h                \
        core/meta-close-dialog-default.c        \
diff --git a/src/core/display-private.h b/src/core/display-private.h
index c46dc9c59..824c42f1f 100644
--- a/src/core/display-private.h
+++ b/src/core/display-private.h
@@ -245,6 +245,8 @@ struct _MetaDisplay
 
   MetaSoundPlayer *sound_player;
 
+  MetaSelectionSource *selection_source;
+  GBytes *saved_clipboard;
   MetaSelection *selection;
 };
 
diff --git a/src/core/display.c b/src/core/display.c
index 9a7f24fb1..266614cb3 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -57,6 +57,7 @@
 #include "core/frame.h"
 #include "core/keybindings-private.h"
 #include "core/main-private.h"
+#include "core/meta-clipboard-manager.h"
 #include "core/meta-workspace-manager-private.h"
 #include "core/util-private.h"
 #include "core/window-private.h"
@@ -724,6 +725,7 @@ meta_display_open (void)
   display->bell = meta_bell_new (display);
 
   display->selection = meta_selection_new (display);
+  meta_clipboard_manager_init (display);
 
   if (meta_should_autostart_x11_display ())
     {
@@ -961,6 +963,8 @@ meta_display_close (MetaDisplay *display,
   g_clear_object (&display->workspace_manager);
   g_clear_object (&display->sound_player);
 
+  meta_clipboard_manager_shutdown (display);
+
   g_object_unref (display);
   the_display = NULL;
 
diff --git a/src/core/meta-clipboard-manager.c b/src/core/meta-clipboard-manager.c
new file mode 100644
index 000000000..8a5826671
--- /dev/null
+++ b/src/core/meta-clipboard-manager.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2018 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+#include "config.h"
+
+#include "core/meta-clipboard-manager.h"
+#include "core/meta-memory-selection-source.h"
+
+#define MAX_SIZE (4 * 1024 * 1024) /* 4MB */
+
+static void
+transfer_cb (MetaSelection *selection,
+             GAsyncResult  *result,
+             GOutputStream *stream)
+{
+  MetaDisplay *display = meta_get_display ();
+  GError *error = NULL;
+
+  if (!meta_selection_transfer_finish (selection, result, &error))
+    {
+      g_error_free (error);
+      return;
+    }
+
+  g_output_stream_close (stream, NULL, NULL);
+  display->saved_clipboard =
+    g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (stream));
+  g_object_unref (stream);
+}
+
+static void
+owner_changed_cb (MetaSelection       *selection,
+                  MetaSelectionType    selection_type,
+                  MetaSelectionSource *source,
+                  MetaDisplay         *display)
+{
+  /* Only track CLIPBOARD selection changed */
+  if (selection_type != META_SELECTION_CLIPBOARD)
+    return;
+
+  if (source && source != display->selection_source)
+    {
+      GOutputStream *output;
+      GList *mimetypes, *l;
+      const gchar *best = NULL;
+
+      /* New selection source, initiate inspection */
+      g_clear_object (&display->selection_source);
+      g_clear_pointer (&display->saved_clipboard, g_bytes_unref);
+
+      mimetypes = meta_selection_get_mimetypes (selection, selection_type);
+
+      for (l = mimetypes; l; l = l->next)
+        {
+          if (g_str_equal (l->data, "text/plain;charset=utf-8"))
+            best = l->data;
+          else if (!best && g_str_equal (l->data, "text/plain"))
+            best = l->data;
+        }
+
+      if (!best)
+        return;
+
+      output = g_memory_output_stream_new_resizable ();
+      meta_selection_transfer_async (selection,
+                                     META_SELECTION_CLIPBOARD,
+                                     best,
+                                     MAX_SIZE,
+                                     output,
+                                     NULL,
+                                     (GAsyncReadyCallback) transfer_cb,
+                                     output);
+    }
+  else if (!source && display->saved_clipboard)
+    {
+      /* Selection source is gone, time to take over */
+      source = meta_memory_selection_source_new ("text/plain;charset=utf-8",
+                                                 display->saved_clipboard);
+      g_set_object (&display->selection_source, source);
+      meta_selection_set_owner (selection, selection_type, source);
+    }
+}
+
+void
+meta_clipboard_manager_init (MetaDisplay *display)
+{
+  MetaSelection *selection;
+
+  selection = meta_display_get_selection (display);
+  g_signal_connect_after (selection, "owner-changed",
+                          G_CALLBACK (owner_changed_cb), display);
+}
+
+void
+meta_clipboard_manager_shutdown (MetaDisplay *display)
+{
+  MetaSelection *selection;
+
+  g_clear_pointer (&display->saved_clipboard, g_bytes_unref);
+  selection = meta_display_get_selection (display);
+  g_signal_handlers_disconnect_by_func (selection, owner_changed_cb, display);
+}
diff --git a/src/core/meta-clipboard-manager.h b/src/core/meta-clipboard-manager.h
new file mode 100644
index 000000000..e1ea75ceb
--- /dev/null
+++ b/src/core/meta-clipboard-manager.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2018 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+#ifndef META_CLIPBOARD_MANAGER_H
+#define META_CLIPBOARD_MANAGER_H
+
+#include "core/display-private.h"
+
+void meta_clipboard_manager_init     (MetaDisplay *display);
+void meta_clipboard_manager_shutdown (MetaDisplay *display);
+
+#endif /* META_CLIPBOARD_MANAGER_H */
diff --git a/src/meson.build b/src/meson.build
index 7c77eba8e..60c5604f0 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -324,6 +324,8 @@ mutter_sources = [
   'core/meta-accel-parse.h',
   'core/meta-border.c',
   'core/meta-border.h',
+  'core/meta-clipboard-manager.c',
+  'core/meta-clipboard-manager.h',
   'core/meta-close-dialog.c',
   'core/meta-close-dialog-default.c',
   'core/meta-close-dialog-default-private.h',


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