[gnome-shell/wip/carlosg/x11less-clipboard: 33/33] st: Reimplement StClipboard on top of MetaSelection



commit f806e61f94af4fef6f73f82a915af85ee560ea32
Author: Carlos Garnacho <carlosg gnome org>
Date:   Mon Nov 26 12:54:23 2018 +0100

    st: Reimplement StClipboard on top of MetaSelection
    
    And stop using X11/gdk for this.
    
    https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/331

 src/shell-global.c    |   1 +
 src/st/meson.build    |   2 +-
 src/st/st-clipboard.c | 333 ++++++++++----------------------------------------
 src/st/st-clipboard.h |   5 +-
 4 files changed, 72 insertions(+), 269 deletions(-)
---
diff --git a/src/shell-global.c b/src/shell-global.c
index df84b6b0d..4295162a8 100644
--- a/src/shell-global.c
+++ b/src/shell-global.c
@@ -863,6 +863,7 @@ _shell_global_set_plugin (ShellGlobal *global,
     }
 
   st_entry_set_cursor_func (entry_cursor_func, global);
+  st_clipboard_set_selection (meta_display_get_selection (display));
 
   g_signal_connect (global->stage, "notify::width",
                     G_CALLBACK (global_stage_notify_width), global);
diff --git a/src/st/meson.build b/src/st/meson.build
index 21756eb07..c611c60a3 100644
--- a/src/st/meson.build
+++ b/src/st/meson.build
@@ -123,7 +123,7 @@ st_cflags = [
 libst = shared_library('st-1.0',
   sources: st_gir_sources + st_non_gir_sources,
   c_args: st_cflags,
-  dependencies: [clutter_dep, gtk_dep, croco_dep, x11_dep, m_dep],
+  dependencies: [clutter_dep, gtk_dep, croco_dep, mutter_dep, m_dep],
   install_rpath: mutter_typelibdir,
   install_dir: pkglibdir,
   install: true
diff --git a/src/st/st-clipboard.c b/src/st/st-clipboard.c
index 2c86f9a22..30e10ec38 100644
--- a/src/st/st-clipboard.c
+++ b/src/st/st-clipboard.c
@@ -19,251 +19,42 @@
 
 /**
  * SECTION:st-clipboard
- * @short_description: a simple representation of the X clipboard
+ * @short_description: a simple representation of the clipboard
  *
  * #StCliboard is a very simple object representation of the clipboard
  * available to applications. Text is always assumed to be UTF-8 and non-text
  * items are not handled.
  */
 
+#include "config.h"
 
 #include "st-clipboard.h"
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
-#include <gdk/gdk.h>
-#include <gdk/gdkx.h>
-#include <string.h>
 
-struct _StClipboardPrivate
-{
-  Window clipboard_window;
-  gchar *clipboard_text;
-
-  Atom  *supported_targets;
-  gint   n_targets;
-};
+#include <meta/display.h>
+#include <meta/meta-selection-source-memory.h>
+#include <meta/meta-selection.h>
 
-G_DEFINE_TYPE_WITH_PRIVATE (StClipboard, st_clipboard, G_TYPE_OBJECT)
+G_DEFINE_TYPE (StClipboard, st_clipboard, G_TYPE_OBJECT)
 
-typedef struct _EventFilterData EventFilterData;
-struct _EventFilterData
+typedef struct _TransferData TransferData;
+struct _TransferData
 {
   StClipboard            *clipboard;
   StClipboardCallbackFunc callback;
   gpointer                user_data;
+  GOutputStream          *stream;
 };
 
-static Atom __atom_primary = None;
-static Atom __atom_clip = None;
-static Atom __utf8_string = None;
-static Atom __atom_targets = None;
-
-static void
-st_clipboard_dispose (GObject *object)
-{
-  G_OBJECT_CLASS (st_clipboard_parent_class)->dispose (object);
-}
-
-static void
-st_clipboard_finalize (GObject *object)
-{
-  StClipboardPrivate *priv = ((StClipboard *) object)->priv;
-
-  g_free (priv->clipboard_text);
-  priv->clipboard_text = NULL;
-
-  g_free (priv->supported_targets);
-  priv->supported_targets = NULL;
-  priv->n_targets = 0;
-
-  G_OBJECT_CLASS (st_clipboard_parent_class)->finalize (object);
-}
-
-static GdkFilterReturn
-st_clipboard_provider (GdkXEvent *xevent_p,
-                       GdkEvent  *gev,
-                       void      *user_data)
-{
-  StClipboard *clipboard = user_data;
-  XEvent *xev = (XEvent *) xevent_p;
-  XSelectionEvent notify_event;
-  XSelectionRequestEvent *req_event;
-  GdkDisplay *display = gdk_display_get_default ();
-
-  if (xev->type != SelectionRequest ||
-      xev->xany.window != clipboard->priv->clipboard_window ||
-      !clipboard->priv->clipboard_text)
-    return GDK_FILTER_CONTINUE;
-
-  req_event = &xev->xselectionrequest;
-
-  gdk_x11_display_error_trap_push (display);
-
-  if (req_event->target == __atom_targets)
-    {
-      XChangeProperty (req_event->display,
-                       req_event->requestor,
-                       req_event->property,
-                       XA_ATOM,
-                       32,
-                       PropModeReplace,
-                       (guchar*) clipboard->priv->supported_targets,
-                       clipboard->priv->n_targets);
-    }
-  else
-    {
-      XChangeProperty (req_event->display,
-                       req_event->requestor,
-                       req_event->property,
-                       req_event->target,
-                       8,
-                       PropModeReplace,
-                       (guchar*) clipboard->priv->clipboard_text,
-                       strlen (clipboard->priv->clipboard_text));
-    }
-
-  notify_event.type = SelectionNotify;
-  notify_event.display = req_event->display;
-  notify_event.requestor = req_event->requestor;
-  notify_event.selection = req_event->selection;
-  notify_event.target = req_event->target;
-  notify_event.time = req_event->time;
-
-  if (req_event->property == None)
-    notify_event.property = req_event->target;
-  else
-    notify_event.property = req_event->property;
-
-  /* notify the requestor that they have a copy of the selection */
-  XSendEvent (req_event->display, req_event->requestor, False, 0,
-              (XEvent *) &notify_event);
-  /* Make it happen non async */
-  XSync (GDK_DISPLAY_XDISPLAY (display), FALSE);
-
-  if (gdk_x11_display_error_trap_pop (display))
-    {
-      /* FIXME: Warn here on fail ? */
-    }
-
-  return GDK_FILTER_REMOVE;
-}
-
+static MetaSelection *meta_selection = NULL;
 
 static void
 st_clipboard_class_init (StClipboardClass *klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-  object_class->dispose = st_clipboard_dispose;
-  object_class->finalize = st_clipboard_finalize;
 }
 
 static void
 st_clipboard_init (StClipboard *self)
 {
-  GdkDisplay *gdk_display;
-  Display *dpy;
-  StClipboardPrivate *priv;
-
-  priv = self->priv = st_clipboard_get_instance_private (self);
-
-  gdk_display = gdk_display_get_default ();
-  dpy = GDK_DISPLAY_XDISPLAY (gdk_display);
-
-  priv->clipboard_window =
-    XCreateSimpleWindow (dpy,
-                         gdk_x11_get_default_root_xwindow (),
-                         -1, -1, 1, 1, 0, 0, 0);
-
-  /* Only create once */
-  if (__atom_primary == None)
-    __atom_primary = XInternAtom (dpy, "PRIMARY", 0);
-
-  if (__atom_clip == None)
-    __atom_clip = XInternAtom (dpy, "CLIPBOARD", 0);
-
-  if (__utf8_string == None)
-    __utf8_string = XInternAtom (dpy, "UTF8_STRING", 0);
-
-  if (__atom_targets == None)
-    __atom_targets = XInternAtom (dpy, "TARGETS", 0);
-
-  priv->n_targets = 2;
-  priv->supported_targets = g_new (Atom, priv->n_targets);
-
-  priv->supported_targets[0] = __utf8_string;
-  priv->supported_targets[1] = __atom_targets;
-
-  gdk_window_add_filter (NULL, /* all windows */
-                         st_clipboard_provider,
-                         self);
-}
-
-static GdkFilterReturn
-st_clipboard_x11_event_filter (GdkXEvent *xevent_p,
-                               GdkEvent  *gev,
-                               void      *user_data)
-{
-  XEvent *xev = (XEvent *) xevent_p;
-  EventFilterData *filter_data = user_data;
-  StClipboardPrivate *priv = filter_data->clipboard->priv;
-  Atom actual_type;
-  int actual_format, result;
-  unsigned long nitems, bytes_after;
-  unsigned char *data = NULL;
-  GdkDisplay *display = gdk_display_get_default ();
-
-  if(xev->type != SelectionNotify ||
-     xev->xany.window != priv->clipboard_window)
-    return GDK_FILTER_CONTINUE;
-
-  if (xev->xselection.property == None)
-    {
-      /* clipboard empty */
-      filter_data->callback (filter_data->clipboard,
-                             NULL,
-                             filter_data->user_data);
-
-      gdk_window_remove_filter (NULL,
-                                st_clipboard_x11_event_filter,
-                                filter_data);
-      g_free (filter_data);
-      return GDK_FILTER_REMOVE;
-    }
-
-  gdk_x11_display_error_trap_push (display);
-
-  result = XGetWindowProperty (xev->xselection.display,
-                               xev->xselection.requestor,
-                               xev->xselection.property,
-                               0L, G_MAXINT,
-                               True,
-                               AnyPropertyType,
-                               &actual_type,
-                               &actual_format,
-                               &nitems,
-                               &bytes_after,
-                               &data);
-
-  if (gdk_x11_display_error_trap_pop (display) || result != Success)
-    {
-      /* FIXME: handle failure better */
-      g_warning ("Clipboard: prop retrival failed");
-    }
-
-  filter_data->callback (filter_data->clipboard, (char*) data,
-                         filter_data->user_data);
-
-  gdk_window_remove_filter (NULL,
-                            st_clipboard_x11_event_filter,
-                            filter_data);
-
-  g_free (filter_data);
-
-  if (data)
-    XFree (data);
-
-  return GDK_FILTER_REMOVE;
 }
 
 /**
@@ -287,10 +78,34 @@ st_clipboard_get_default (void)
   return default_clipboard;
 }
 
-static Atom
-atom_for_clipboard_type (StClipboardType type)
+static gboolean
+convert_type (StClipboardType    type,
+              MetaSelectionType *type_out)
+{
+  if (type == ST_CLIPBOARD_TYPE_PRIMARY)
+    *type_out = META_SELECTION_PRIMARY;
+  else if (type == ST_CLIPBOARD_TYPE_CLIPBOARD)
+    *type_out = META_SELECTION_CLIPBOARD;
+  else
+    return FALSE;
+
+  return TRUE;
+}
+
+static void
+transfer_cb (MetaSelection *selection,
+             GAsyncResult  *res,
+             TransferData  *data)
 {
-  return type == ST_CLIPBOARD_TYPE_CLIPBOARD ? __atom_clip : __atom_primary;
+  const gchar *text = NULL;
+
+  if (meta_selection_transfer_finish (selection, res, NULL))
+    text = g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (data->stream));
+
+  data->callback (data->clipboard, text, data->user_data);
+
+  g_object_unref (data->stream);
+  g_free (data);
 }
 
 /**
@@ -310,37 +125,28 @@ st_clipboard_get_text (StClipboard            *clipboard,
                        StClipboardCallbackFunc callback,
                        gpointer                user_data)
 {
-  EventFilterData *data;
-  GdkDisplay *gdk_display;
-  Display *dpy;
+  MetaSelectionType selection_type;
+  TransferData *data;
 
   g_return_if_fail (ST_IS_CLIPBOARD (clipboard));
+  g_return_if_fail (meta_selection == NULL);
   g_return_if_fail (callback != NULL);
 
-  data = g_new0 (EventFilterData, 1);
+  if (!convert_type (type, &selection_type))
+    return;
+
+  data = g_new0 (TransferData, 1);
   data->clipboard = clipboard;
   data->callback = callback;
   data->user_data = user_data;
-
-  gdk_window_add_filter (NULL, /* all windows */
-                         st_clipboard_x11_event_filter,
-                         data);
-
-  gdk_display = gdk_display_get_default ();
-  dpy = GDK_DISPLAY_XDISPLAY (gdk_display);
-
-  gdk_x11_display_error_trap_push (gdk_display);
-
-  XConvertSelection (dpy,
-                     atom_for_clipboard_type (type),
-                     __utf8_string, __utf8_string,
-                     clipboard->priv->clipboard_window,
-                     CurrentTime);
-
-  if (gdk_x11_display_error_trap_pop (gdk_display))
-    {
-      /* FIXME */
-    }
+  data->stream = g_memory_output_stream_new_resizable ();
+
+  meta_selection_transfer_async (meta_selection,
+                                 selection_type,
+                                 "text/plain;charset=utf-8", -1,
+                                 data->stream, NULL,
+                                 (GAsyncReadyCallback) transfer_cb,
+                                 data);
 }
 
 /**
@@ -356,31 +162,26 @@ st_clipboard_set_text (StClipboard     *clipboard,
                        StClipboardType  type,
                        const gchar     *text)
 {
-  StClipboardPrivate *priv;
-  GdkDisplay *gdk_display;
-  Display *dpy;
+  MetaSelectionType selection_type;
+  MetaSelectionSource *source;
+  GBytes *bytes;
 
   g_return_if_fail (ST_IS_CLIPBOARD (clipboard));
+  g_return_if_fail (meta_selection == NULL);
   g_return_if_fail (text != NULL);
 
-  priv = clipboard->priv;
-
-  /* make a copy of the text */
-  g_free (priv->clipboard_text);
-  priv->clipboard_text = g_strdup (text);
-
-  /* tell X we own the clipboard selection */
-  gdk_display = gdk_display_get_default ();
-  dpy = GDK_DISPLAY_XDISPLAY (gdk_display);
-
-  gdk_x11_display_error_trap_push (gdk_display);
+  if (!convert_type (type, &selection_type))
+    return;
 
-  XSetSelectionOwner (dpy, atom_for_clipboard_type (type), priv->clipboard_window, CurrentTime);
+  bytes = g_bytes_new_take (g_strdup (text), strlen (text));
+  source = meta_selection_source_memory_new ("text/plain;charset=utf-8", bytes);
+  g_bytes_unref (bytes);
 
-  XSync (dpy, FALSE);
+  meta_selection_set_owner (meta_selection, selection_type, source);
+}
 
-  if (gdk_x11_display_error_trap_pop (gdk_display))
-    {
-      /* FIXME */
-    }
+void
+st_clipboard_set_selection (MetaSelection *selection)
+{
+  meta_selection = selection;
 }
diff --git a/src/st/st-clipboard.h b/src/st/st-clipboard.h
index 9ea412e3b..86e67e1ee 100644
--- a/src/st/st-clipboard.h
+++ b/src/st/st-clipboard.h
@@ -25,6 +25,7 @@
 #define _ST_CLIPBOARD_H
 
 #include <glib-object.h>
+#include <meta/meta-selection.h>
 
 G_BEGIN_DECLS
 
@@ -32,7 +33,6 @@ G_BEGIN_DECLS
 G_DECLARE_FINAL_TYPE (StClipboard, st_clipboard, ST, CLIPBOARD, GObject)
 
 typedef struct _StClipboard StClipboard;
-typedef struct _StClipboardPrivate StClipboardPrivate;
 
 /**
  * StClipboard:
@@ -44,7 +44,6 @@ struct _StClipboard
 {
   /*< private >*/
   GObject parent;
-  StClipboardPrivate *priv;
 };
 
 typedef enum {
@@ -74,6 +73,8 @@ void st_clipboard_set_text (StClipboard             *clipboard,
                             StClipboardType          type,
                             const gchar             *text);
 
+void st_clipboard_set_selection (MetaSelection *selection);
+
 G_END_DECLS
 
 #endif /* _ST_CLIPBOARD_H */


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