[Xfce4-commits] <xfce4-settings:xfce-4.8> Start using the gsd clipboard manager again (bug #7588).
Nick Schermer
noreply at xfce.org
Tue May 17 20:50:05 CEST 2011
Updating branch refs/heads/xfce-4.8
to b6d4d7f2fb1ebd7a23a80b4f92d2d1cfbfd1fac2 (commit)
from 8359af4bf58080ad5f35d8adbc7dda2766d0544a (commit)
commit b6d4d7f2fb1ebd7a23a80b4f92d2d1cfbfd1fac2
Author: Nick Schermer <nick at xfce.org>
Date: Tue May 17 20:43:03 2011 +0200
Start using the gsd clipboard manager again (bug #7588).
Merged code of the following commits in master:
23f3a2c972e887330acbef1a4062a7b1ff834dd2 Add missing include.
2598bfcc4239b6cd50f0cedd9ae1325320911d86 Fix gdk 2.24 functions.
dc6f833ade8904490febe2d17bfdc4f208fda801 Cleanup includes.
a3e511c8d37b9e4036d6db3e6be6e7a01b6f466f Missed two memory allocation conversions.
3213df6a2ecc810da22cb8d484b52dc230326a47 Start using the gsd clipboard manager again (bug #7588).
682b5e7025e86f3803bb9789925796586abaa09a Share xserver time function for clipboard manager.
xfce4-settings-helper/clipboard-manager.c | 1240 +++++++++++++++++++++--------
xfce4-settings-helper/clipboard-manager.h | 43 +-
xfce4-settings-helper/main.c | 17 +-
3 files changed, 954 insertions(+), 346 deletions(-)
diff --git a/xfce4-settings-helper/clipboard-manager.c b/xfce4-settings-helper/clipboard-manager.c
index b65ad02..4e6b513 100644
--- a/xfce4-settings-helper/clipboard-manager.c
+++ b/xfce4-settings-helper/clipboard-manager.c
@@ -4,7 +4,7 @@
* Copyright (C) 2007 Anders Carlsson
* Copyright (C) 2007 Rodrigo Moya
* Copyright (C) 2007 William Jon McCann <mccann at jhu.edu>
- * Copyright (C) 2009-2011 Mike Massonnet <mmassonnet at xfce.org>
+ * Copyright (C) 2011 Nick Schermer <nick at xfce.org>
*
* 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
@@ -19,441 +19,1031 @@
* 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.
+ *
*/
-#include "config.h"
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
-#include <glib.h>
-#include <gdk/gdkx.h>
-#include <gtk/gtk.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+
#include "clipboard-manager.h"
-struct _XfceClipboardManagerClass
+struct _GsdClipboardManagerPrivate
{
- GObjectClass __parent__;
+ guint start_idle_id;
+ Display *display;
+ Window window;
+ Time timestamp;
+
+ GSList *contents;
+ GSList *conversions;
+
+ Window requestor;
+ Atom property;
+ Time time;
};
-struct _XfceClipboardManager
+typedef struct
{
- GObject __parent__;
+ guchar *data;
+ gulong length;
+ Atom target;
+ Atom type;
+ gint format;
+ gint refcount;
+} TargetData;
+
+typedef struct
+{
+ Atom target;
+ TargetData *data;
+ Atom property;
+ Window requestor;
+ gint offset;
+} IncrConversion;
- GtkClipboard *default_clipboard;
- GtkClipboard *primary_clipboard;
+static void gsd_clipboard_manager_finalize (GObject *object);
+static void clipboard_manager_watch_cb (GsdClipboardManager *manager,
+ Window window,
+ Bool is_start,
+ long mask,
+ void *cb_data);
- GSList *default_cache;
- gchar *primary_cache;
+static gulong SELECTION_MAX_SIZE = 0;
- gboolean default_internal_change;
- gboolean primary_timeout;
- gboolean primary_internal_change;
-};
+static Atom XA_ATOM_PAIR = None;
+static Atom XA_CLIPBOARD_MANAGER = None;
+static Atom XA_CLIPBOARD = None;
+static Atom XA_DELETE = None;
+static Atom XA_INCR = None;
+static Atom XA_INSERT_PROPERTY = None;
+static Atom XA_INSERT_SELECTION = None;
+static Atom XA_MANAGER = None;
+static Atom XA_MULTIPLE = None;
+static Atom XA_NULL = None;
+static Atom XA_SAVE_TARGETS = None;
+static Atom XA_TARGETS = None;
+static Atom XA_TIMESTAMP = None;
-G_DEFINE_TYPE (XfceClipboardManager, xfce_clipboard_manager, G_TYPE_OBJECT)
+G_DEFINE_TYPE (GsdClipboardManager, gsd_clipboard_manager, G_TYPE_OBJECT)
-static void
-xfce_clipboard_manager_class_init (XfceClipboardManagerClass *klass)
+
+static Bool
+xfce_xsettings_helper_timestamp_predicate (Display *xdisplay,
+ XEvent *xevent,
+ XPointer arg)
{
+ Window window = GPOINTER_TO_UINT (arg);
+
+ return (xevent->type == PropertyNotify
+ && xevent->xproperty.window == window
+ && xevent->xproperty.atom == XInternAtom (xdisplay, "_TIMESTAMP_PROP", False));
}
-static void
-xfce_clipboard_manager_init (XfceClipboardManager *manager)
+static Time
+xfce_xsettings_get_server_time (Display *xdisplay,
+ Window window)
{
- manager->default_clipboard =
- gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
- manager->primary_clipboard =
- gtk_clipboard_get (GDK_SELECTION_PRIMARY);
-
- manager->default_cache = NULL;
- manager->primary_cache = NULL;
+ Atom timestamp_atom;
+ guchar c = 'a';
+ XEvent xevent;
+
+ /* get the current xserver timestamp */
+ timestamp_atom = XInternAtom (xdisplay, "_TIMESTAMP_PROP", False);
+ XChangeProperty (xdisplay, window, timestamp_atom, timestamp_atom,
+ 8, PropModeReplace, &c, 1);
+ XIfEvent (xdisplay, &xevent, xfce_xsettings_helper_timestamp_predicate,
+ GUINT_TO_POINTER (window));
+
+ return xevent.xproperty.time;
}
static void
-xfce_clipboard_manager_default_store (XfceClipboardManager *manager)
+gsd_clipboard_manager_class_init (GsdClipboardManagerClass *klass)
{
- GtkSelectionData *selection_data;
- GdkAtom *atoms;
- gint n_atoms;
- gint i;
-
- g_return_if_fail (XFCE_IS_CLIPBOARD_MANAGER (manager));
-
- if (!gtk_clipboard_wait_for_targets (manager->default_clipboard, &atoms, &n_atoms))
- return;
-
- if (manager->default_cache != NULL)
- {
- g_slist_foreach (manager->default_cache, (GFunc)gtk_selection_data_free, NULL);
- g_slist_free (manager->default_cache);
- manager->default_cache = NULL;
- }
-
- for (i = 0; i < n_atoms; i++)
- {
- if (atoms[i] == gdk_atom_intern_static_string ("TARGETS")
- || atoms[i] == gdk_atom_intern_static_string ("MULTIPLE")
- || atoms[i] == gdk_atom_intern_static_string ("DELETE")
- || atoms[i] == gdk_atom_intern_static_string ("INSERT_PROPERTY")
- || atoms[i] == gdk_atom_intern_static_string ("INSERT_SELECTION")
- || atoms[i] == gdk_atom_intern_static_string ("PIXMAP"))
- {
- continue;
- }
-
- selection_data = gtk_clipboard_wait_for_contents (manager->default_clipboard, atoms[i]);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
- if (selection_data == NULL)
- continue;
+ object_class->finalize = gsd_clipboard_manager_finalize;
- manager->default_cache = g_slist_prepend (manager->default_cache, selection_data);
- }
+ g_type_class_add_private (klass, sizeof (GsdClipboardManagerPrivate));
}
-
-
static void
-xfce_clipboard_manager_default_get_func (GtkClipboard *clipboard,
- GtkSelectionData *selection_data,
- guint info,
- gpointer user_data)
+gsd_clipboard_manager_init (GsdClipboardManager *manager)
{
- XfceClipboardManager *manager = XFCE_CLIPBOARD_MANAGER (user_data);
- GSList *list;
- GtkSelectionData *selection_data_cache = NULL;
-
- g_return_if_fail (XFCE_IS_CLIPBOARD_MANAGER (manager));
+ manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager,
+ GSD_TYPE_CLIPBOARD_MANAGER,
+ GsdClipboardManagerPrivate);
- list = manager->default_cache;
+ manager->priv->display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
- for (; list != NULL && list->next != NULL; list = list->next)
- {
- selection_data_cache = list->data;
-
- if (gtk_selection_data_get_target (selection_data) ==
- gtk_selection_data_get_target (selection_data_cache))
- break;
+}
- selection_data_cache = NULL;
- }
+static void
+gsd_clipboard_manager_finalize (GObject *object)
+{
+ GsdClipboardManager *clipboard_manager = GSD_CLIPBOARD_MANAGER (object);
- if (selection_data_cache == NULL)
- return;
+ if (clipboard_manager->priv->start_idle_id !=0)
+ g_source_remove (clipboard_manager->priv->start_idle_id);
- gtk_selection_data_set (selection_data,
- gtk_selection_data_get_target (selection_data_cache),
- gtk_selection_data_get_format (selection_data_cache),
- gtk_selection_data_get_data (selection_data_cache),
- gtk_selection_data_get_length (selection_data_cache));
+ G_OBJECT_CLASS (gsd_clipboard_manager_parent_class)->finalize (object);
}
-
+/* We need to use reference counting for the target data, since we may
+ * need to keep the data around after loosing the CLIPBOARD ownership
+ * to complete incremental transfers.
+ */
+static TargetData *
+target_data_ref (TargetData *data)
+{
+ data->refcount++;
+ return data;
+}
static void
-xfce_clipboard_manager_default_clear_func (GtkClipboard *clipboard,
- gpointer user_data)
+target_data_unref (TargetData *data)
{
+ data->refcount--;
+ if (data->refcount == 0) {
+ g_free (data->data);
+ g_slice_free (TargetData, data);
+ }
}
-
+static void
+conversion_free (IncrConversion *rdata)
+{
+ if (rdata->data)
+ target_data_unref (rdata->data);
+ g_slice_free (IncrConversion, rdata);
+}
static void
-xfce_clipboard_manager_default_restore (XfceClipboardManager *manager)
+send_selection_notify (GsdClipboardManager *manager,
+ Bool success)
{
- GtkTargetList *target_list;
- GtkTargetEntry *targets;
- gint n_targets;
- GtkSelectionData *sdata;
- GSList *list;
+ XSelectionEvent notify;
+
+ notify.type = SelectionNotify;
+ notify.serial = 0;
+ notify.send_event = True;
+ notify.display = manager->priv->display;
+ notify.requestor = manager->priv->requestor;
+ notify.selection = XA_CLIPBOARD_MANAGER;
+ notify.target = XA_SAVE_TARGETS;
+ notify.property = success ? manager->priv->property : None;
+ notify.time = manager->priv->time;
- g_return_if_fail (XFCE_IS_CLIPBOARD_MANAGER (manager));
+ gdk_error_trap_push ();
- list = manager->default_cache;
- if (list == NULL)
- return;
+ XSendEvent (manager->priv->display,
+ manager->priv->requestor,
+ False,
+ NoEventMask,
+ (XEvent *)¬ify);
+ XSync (manager->priv->display, False);
- target_list = gtk_target_list_new (NULL, 0);
+ gdk_error_trap_pop ();
+}
- for (; list->next != NULL; list = list->next)
- {
- sdata = list->data;
- gtk_target_list_add (target_list,
- gtk_selection_data_get_target (sdata),
- 0, 0);
- }
+static void
+finish_selection_request (GsdClipboardManager *manager,
+ XEvent *xev,
+ Bool success)
+{
+ XSelectionEvent notify;
+
+ notify.type = SelectionNotify;
+ notify.serial = 0;
+ notify.send_event = True;
+ notify.display = xev->xselectionrequest.display;
+ notify.requestor = xev->xselectionrequest.requestor;
+ notify.selection = xev->xselectionrequest.selection;
+ notify.target = xev->xselectionrequest.target;
+ notify.property = success ? xev->xselectionrequest.property : None;
+ notify.time = xev->xselectionrequest.time;
- targets = gtk_target_table_new_from_list (target_list, &n_targets);
+ gdk_error_trap_push ();
- gtk_target_list_unref (target_list);
+ XSendEvent (xev->xselectionrequest.display,
+ xev->xselectionrequest.requestor,
+ False, NoEventMask, (XEvent *) ¬ify);
+ XSync (manager->priv->display, False);
- gtk_clipboard_set_with_data (manager->default_clipboard,
- targets, n_targets,
- xfce_clipboard_manager_default_get_func,
- xfce_clipboard_manager_default_clear_func,
- manager);
+ gdk_error_trap_pop ();
}
+static int
+clipboard_bytes_per_item (int format)
+{
+ switch (format) {
+ case 8: return sizeof (char);
+ case 16: return sizeof (short);
+ case 32: return sizeof (long);
+ default: ;
+ }
+ return 0;
+}
static void
-xfce_clipboard_manager_default_owner_change (XfceClipboardManager *manager,
- GdkEventOwnerChange *event)
+save_targets (GsdClipboardManager *manager,
+ Atom *targets,
+ int nitems)
{
- g_return_if_fail (XFCE_IS_CLIPBOARD_MANAGER (manager));
+ gint nout, i;
+ Atom *multiple;
+ TargetData *tdata;
+
+ multiple = g_new (Atom, 2 * nitems);
+
+ nout = 0;
+ for (i = 0; i < nitems; i++) {
+ if (targets[i] != XA_TARGETS &&
+ targets[i] != XA_MULTIPLE &&
+ targets[i] != XA_DELETE &&
+ targets[i] != XA_INSERT_PROPERTY &&
+ targets[i] != XA_INSERT_SELECTION &&
+ targets[i] != XA_PIXMAP) {
+ tdata = g_slice_new (TargetData);
+ tdata->data = NULL;
+ tdata->length = 0;
+ tdata->target = targets[i];
+ tdata->type = None;
+ tdata->format = 0;
+ tdata->refcount = 1;
+ manager->priv->contents = g_slist_prepend (manager->priv->contents, tdata);
+
+ multiple[nout++] = targets[i];
+ multiple[nout++] = targets[i];
+ }
+ }
- if (event->send_event == TRUE)
- return;
+ XFree (targets);
- if (event->owner != 0)
- {
- if (manager->default_internal_change)
- {
- manager->default_internal_change = FALSE;
- return;
- }
+ XChangeProperty (manager->priv->display, manager->priv->window,
+ XA_MULTIPLE, XA_ATOM_PAIR,
+ 32, PropModeReplace, (const guchar *) multiple, nout);
+ g_free (multiple);
- xfce_clipboard_manager_default_store (manager);
- }
- else
- {
- /* This 'bug' happens with Mozilla applications, it means that
- * we restored the clipboard (we own it now) but somehow we are
- * being noticed twice about that fact where first the owner is
- * 0 (which is when we must restore) but then again where the
- * owner is ourself (which is what normally only happens and
- * also that means that we have to store the clipboard content
- * e.g. owner is not 0). By the second time we would store
- * ourself back with an empty clipboard... solution is to jump
- * over the first time and don't try to restore empty data. */
- if (manager->default_internal_change)
- return;
-
- manager->default_internal_change = TRUE;
- xfce_clipboard_manager_default_restore (manager);
- }
+ XConvertSelection (manager->priv->display, XA_CLIPBOARD,
+ XA_MULTIPLE, XA_MULTIPLE,
+ manager->priv->window, manager->priv->time);
}
+static int
+find_content_target (TargetData *tdata,
+ Atom *target)
+{
+ return !(tdata->target == *target);
+}
-
-static gboolean
-xfce_clipboard_manager_primary_clipboard_store (XfceClipboardManager *manager)
+static int
+find_content_type (TargetData *tdata,
+ Atom *type)
{
- GdkModifierType state;
- gchar *text;
+ return !(tdata->type == *type);
+}
- gdk_window_get_pointer (NULL, NULL, NULL, &state);
+static int
+find_conversion_requestor (IncrConversion *rdata,
+ XEvent *xev)
+{
+ return !(rdata->requestor == xev->xproperty.window
+ && rdata->property == xev->xproperty.atom);
+}
- if (state & (GDK_BUTTON1_MASK|GDK_SHIFT_MASK))
- return TRUE;
+static void
+get_property (TargetData *tdata,
+ GsdClipboardManager *manager)
+{
+ Atom type;
+ gint format;
+ gulong length;
+ gulong remaining;
+ guchar *data;
+
+ XGetWindowProperty (manager->priv->display,
+ manager->priv->window,
+ tdata->target,
+ 0,
+ 0x1FFFFFFF,
+ True,
+ AnyPropertyType,
+ &type,
+ &format,
+ &length,
+ &remaining,
+ &data);
+
+ if (type == None) {
+ manager->priv->contents = g_slist_remove (manager->priv->contents, tdata);
+ g_slice_free (TargetData, tdata);
+ } else if (type == XA_INCR) {
+ tdata->type = type;
+ tdata->length = 0;
+ XFree (data);
+ } else {
+ tdata->type = type;
+ tdata->data = data;
+ tdata->length = length * clipboard_bytes_per_item (format);
+ tdata->format = format;
+ }
+}
- text = gtk_clipboard_wait_for_text (manager->primary_clipboard);
+static Bool
+receive_incrementally (GsdClipboardManager *manager,
+ XEvent *xev)
+{
+ GSList *list;
+ TargetData *tdata;
+ Atom type;
+ gint format;
+ gulong length, nitems, remaining;
+ guchar *data;
+
+ if (xev->xproperty.window != manager->priv->window)
+ return False;
+
+ list = g_slist_find_custom (manager->priv->contents,
+ &xev->xproperty.atom,
+ (GCompareFunc) find_content_target);
+
+ if (!list)
+ return False;
+
+ tdata = (TargetData *) list->data;
+
+ if (tdata->type != XA_INCR)
+ return False;
+
+ XGetWindowProperty (xev->xproperty.display,
+ xev->xproperty.window,
+ xev->xproperty.atom,
+ 0, 0x1FFFFFFF, True, AnyPropertyType,
+ &type, &format, &nitems, &remaining, &data);
+
+ length = nitems * clipboard_bytes_per_item (format);
+ if (length == 0) {
+ tdata->type = type;
+ tdata->format = format;
+
+ if (!g_slist_find_custom (manager->priv->contents,
+ &XA_INCR, (GCompareFunc) find_content_type)) {
+
+ /* all incremental transfers done */
+ send_selection_notify (manager, True);
+ manager->priv->requestor = None;
+ }
+
+ XFree (data);
+ } else {
+ if (!tdata->data) {
+ tdata->data = data;
+ tdata->length = length;
+ } else {
+ tdata->data = g_realloc (tdata->data, tdata->length + length + 1);
+ memcpy (tdata->data + tdata->length, data, length + 1);
+ tdata->length += length;
+ XFree (data);
+ }
+ }
- if (text != NULL)
- {
- g_free (manager->primary_cache);
- manager->primary_cache = text;
- }
+ return True;
+}
- manager->primary_timeout = 0;
+static Bool
+send_incrementally (GsdClipboardManager *manager,
+ XEvent *xev)
+{
+ GSList *list;
+ IncrConversion *rdata;
+ gulong length;
+ gulong items;
+ guchar *data;
+
+ list = g_slist_find_custom (manager->priv->conversions, xev,
+ (GCompareFunc) find_conversion_requestor);
+ if (list == NULL)
+ return False;
+
+ rdata = (IncrConversion *) list->data;
+
+ data = rdata->data->data + rdata->offset;
+ length = rdata->data->length - rdata->offset;
+ if (length > SELECTION_MAX_SIZE)
+ length = SELECTION_MAX_SIZE;
+
+ rdata->offset += length;
+
+ items = length / clipboard_bytes_per_item (rdata->data->format);
+ XChangeProperty (manager->priv->display, rdata->requestor,
+ rdata->property, rdata->data->type,
+ rdata->data->format, PropModeAppend,
+ data, items);
+
+ if (length == 0) {
+ manager->priv->conversions = g_slist_remove (manager->priv->conversions, rdata);
+ conversion_free (rdata);
+ }
- return FALSE;
+ return True;
}
+static void
+convert_clipboard_manager (GsdClipboardManager *manager,
+ XEvent *xev)
+{
+ Atom type = None;
+ gint format;
+ gulong nitems;
+ gulong remaining;
+ Atom *targets = NULL;
+ Atom targets2[3];
+ gint n_targets;
+
+ if (xev->xselectionrequest.target == XA_SAVE_TARGETS) {
+ if (manager->priv->requestor != None || manager->priv->contents != NULL) {
+ /* We're in the middle of a conversion request, or own
+ * the CLIPBOARD already
+ */
+ finish_selection_request (manager, xev, False);
+ } else {
+ gdk_error_trap_push ();
+
+ clipboard_manager_watch_cb (manager,
+ xev->xselectionrequest.requestor,
+ True,
+ StructureNotifyMask,
+ NULL);
+ XSelectInput (manager->priv->display,
+ xev->xselectionrequest.requestor,
+ StructureNotifyMask);
+ XSync (manager->priv->display, False);
+
+ if (gdk_error_trap_pop () != Success)
+ return;
+
+ gdk_error_trap_push ();
+
+ if (xev->xselectionrequest.property != None) {
+ XGetWindowProperty (manager->priv->display,
+ xev->xselectionrequest.requestor,
+ xev->xselectionrequest.property,
+ 0, 0x1FFFFFFF, False, XA_ATOM,
+ &type, &format, &nitems, &remaining,
+ (guchar **) &targets);
+
+ if (gdk_error_trap_pop () != Success) {
+ if (targets)
+ XFree (targets);
+
+ return;
+ }
+ }
+
+ manager->priv->requestor = xev->xselectionrequest.requestor;
+ manager->priv->property = xev->xselectionrequest.property;
+ manager->priv->time = xev->xselectionrequest.time;
+
+ if (type == None)
+ XConvertSelection (manager->priv->display, XA_CLIPBOARD,
+ XA_TARGETS, XA_TARGETS,
+ manager->priv->window, manager->priv->time);
+ else
+ save_targets (manager, targets, nitems);
+ }
+ } else if (xev->xselectionrequest.target == XA_TIMESTAMP) {
+ XChangeProperty (manager->priv->display,
+ xev->xselectionrequest.requestor,
+ xev->xselectionrequest.property,
+ XA_INTEGER, 32, PropModeReplace,
+ (guchar *) &manager->priv->timestamp, 1);
+
+ finish_selection_request (manager, xev, True);
+ } else if (xev->xselectionrequest.target == XA_TARGETS) {
+ n_targets = 0;
+ targets2[n_targets++] = XA_TARGETS;
+ targets2[n_targets++] = XA_TIMESTAMP;
+ targets2[n_targets++] = XA_SAVE_TARGETS;
+
+ XChangeProperty (manager->priv->display,
+ xev->xselectionrequest.requestor,
+ xev->xselectionrequest.property,
+ XA_ATOM, 32, PropModeReplace,
+ (guchar *) targets2, n_targets);
+
+ finish_selection_request (manager, xev, True);
+ } else
+ finish_selection_request (manager, xev, False);
+}
-static gboolean
-xfce_clipboard_manager_primary_clipboard_restore (XfceClipboardManager *manager)
+static void
+convert_clipboard_target (IncrConversion *rdata,
+ GsdClipboardManager *manager)
{
- if (manager->primary_cache != NULL)
- {
- gtk_clipboard_set_text (manager->primary_clipboard,
- manager->primary_cache,
- -1);
- manager->primary_internal_change = TRUE;
- }
-
- return FALSE;
+ TargetData *tdata;
+ Atom *targets;
+ gint n_targets;
+ GSList *list;
+ gulong items;
+ XWindowAttributes atts;
+
+ if (rdata->target == XA_TARGETS) {
+ n_targets = g_slist_length (manager->priv->contents) + 2;
+ targets = g_new (Atom, n_targets);
+
+ n_targets = 0;
+ targets[n_targets++] = XA_TARGETS;
+ targets[n_targets++] = XA_MULTIPLE;
+
+ for (list = manager->priv->contents; list; list = list->next) {
+ tdata = (TargetData *) list->data;
+ targets[n_targets++] = tdata->target;
+ }
+
+ XChangeProperty (manager->priv->display, rdata->requestor,
+ rdata->property,
+ XA_ATOM, 32, PropModeReplace,
+ (guchar *) targets, n_targets);
+ g_free (targets);
+ } else {
+ /* Convert from stored CLIPBOARD data */
+ list = g_slist_find_custom (manager->priv->contents,
+ &rdata->target,
+ (GCompareFunc) find_content_target);
+
+ /* We got a target that we don't support */
+ if (!list)
+ return;
+
+ tdata = (TargetData *)list->data;
+ if (tdata->type == XA_INCR) {
+ /* we haven't completely received this target yet */
+ rdata->property = None;
+ return;
+ }
+
+ rdata->data = target_data_ref (tdata);
+ items = tdata->length / clipboard_bytes_per_item (tdata->format);
+ if (tdata->length <= SELECTION_MAX_SIZE)
+ XChangeProperty (manager->priv->display, rdata->requestor,
+ rdata->property,
+ tdata->type, tdata->format, PropModeReplace,
+ tdata->data, items);
+ else {
+ /* start incremental transfer */
+ rdata->offset = 0;
+
+ gdk_error_trap_push ();
+
+ XGetWindowAttributes (manager->priv->display, rdata->requestor, &atts);
+ XSelectInput (manager->priv->display, rdata->requestor,
+ atts.your_event_mask | PropertyChangeMask);
+
+ XChangeProperty (manager->priv->display, rdata->requestor,
+ rdata->property,
+ XA_INCR, 32, PropModeReplace,
+ (guchar *) &items, 1);
+
+ XSync (manager->priv->display, False);
+
+ gdk_error_trap_pop ();
+ }
+ }
}
+static void
+collect_incremental (IncrConversion *rdata,
+ GsdClipboardManager *manager)
+{
+ if (rdata->offset >= 0)
+ manager->priv->conversions = g_slist_prepend (manager->priv->conversions, rdata);
+ else
+ conversion_free (rdata);
+}
static void
-xfce_clipboard_manager_primary_owner_change (XfceClipboardManager *manager,
- GdkEventOwnerChange *event)
+convert_clipboard (GsdClipboardManager *manager,
+ XEvent *xev)
{
- g_return_if_fail (XFCE_IS_CLIPBOARD_MANAGER (manager));
-
- if (event->send_event == TRUE)
- return;
-
- if (manager->primary_timeout != 0)
- {
- g_source_remove (manager->primary_timeout);
- manager->primary_timeout = 0;
- }
-
- if (event->owner != 0)
- {
- if (manager->primary_internal_change == TRUE)
- {
- manager->primary_internal_change = FALSE;
- return;
+ GSList *list;
+ GSList *conversions = NULL;
+ IncrConversion *rdata;
+ Atom type = None;
+ gint format;
+ gulong i, nitems;
+ gulong remaining;
+ Atom *multiple;
+
+ if (xev->xselectionrequest.target == XA_MULTIPLE) {
+ XGetWindowProperty (xev->xselectionrequest.display,
+ xev->xselectionrequest.requestor,
+ xev->xselectionrequest.property,
+ 0, 0x1FFFFFFF, False, XA_ATOM_PAIR,
+ &type, &format, &nitems, &remaining,
+ (guchar **) &multiple);
+
+ if (type != XA_ATOM_PAIR || nitems == 0) {
+ if (multiple)
+ g_free (multiple);
+ return;
+ }
+
+ for (i = 0; i < nitems; i += 2) {
+ rdata = g_slice_new (IncrConversion);
+ rdata->requestor = xev->xselectionrequest.requestor;
+ rdata->target = multiple[i];
+ rdata->property = multiple[i+1];
+ rdata->data = NULL;
+ rdata->offset = -1;
+ conversions = g_slist_prepend (conversions, rdata);
+ }
+ } else {
+ multiple = NULL;
+
+ rdata = g_slice_new (IncrConversion);
+ rdata->requestor = xev->xselectionrequest.requestor;
+ rdata->target = xev->xselectionrequest.target;
+ rdata->property = xev->xselectionrequest.property;
+ rdata->data = NULL;
+ rdata->offset = -1;
+ conversions = g_slist_prepend (conversions, rdata);
}
- manager->primary_timeout = g_timeout_add (250, (GSourceFunc)xfce_clipboard_manager_primary_clipboard_store, manager);
- }
- else if (gtk_clipboard_wait_is_text_available (manager->primary_clipboard) == FALSE)
- {
- manager->primary_timeout = g_timeout_add (250, (GSourceFunc)xfce_clipboard_manager_primary_clipboard_restore, manager);
- }
-}
+ g_slist_foreach (conversions, (GFunc) convert_clipboard_target, manager);
+
+ if (conversions->next == NULL &&
+ ((IncrConversion *) conversions->data)->property == None) {
+ finish_selection_request (manager, xev, False);
+ } else {
+ if (multiple) {
+ i = 0;
+ for (list = conversions; list; list = list->next) {
+ rdata = (IncrConversion *)list->data;
+ multiple[i++] = rdata->target;
+ multiple[i++] = rdata->property;
+ }
+ XChangeProperty (xev->xselectionrequest.display,
+ xev->xselectionrequest.requestor,
+ xev->xselectionrequest.property,
+ XA_ATOM_PAIR, 32, PropModeReplace,
+ (guchar *) multiple, nitems);
+ }
+ finish_selection_request (manager, xev, True);
+ }
+ g_slist_foreach (conversions, (GFunc) collect_incremental, manager);
+ g_slist_free (conversions);
+ g_free (multiple);
+}
-static gboolean
-xfce_clipboard_manager_selection_owner (const gchar *selection_name,
- gboolean force,
- GdkFilterFunc filter_func)
+static Bool
+clipboard_manager_process_event (GsdClipboardManager *manager,
+ XEvent *xev)
{
-#ifdef GDK_WINDOWING_X11
- GdkDisplay *gdpy = gdk_display_get_default ();
- GtkWidget *invisible;
- Display *dpy = GDK_DISPLAY_XDISPLAY (gdpy);
- GdkWindow *rootwin = gdk_screen_get_root_window (gdk_display_get_screen (gdpy, 0));
- GdkWindow *invisible_window;
- Window xroot = GDK_WINDOW_XID (rootwin);
- GdkAtom selection_atom;
- Atom selection_atom_x11;
- XClientMessageEvent xev;
- gboolean has_owner;
-
- g_return_val_if_fail (selection_name != NULL, FALSE);
-
- selection_atom = gdk_atom_intern (selection_name, FALSE);
- selection_atom_x11 = gdk_x11_atom_to_xatom_for_display (gdpy, selection_atom);
-
- /* can't use gdk for the selection owner here because it returns NULL
- * if the selection owner is in another process */
- if (!force)
- {
- gdk_error_trap_push ();
- has_owner = XGetSelectionOwner (dpy, selection_atom_x11) != None;
- gdk_flush ();
- gdk_error_trap_pop ();
- if (has_owner)
- return FALSE;
- }
-
- invisible = gtk_invisible_new ();
- gtk_widget_realize (invisible);
- gtk_widget_add_events (invisible, GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK);
-
- invisible_window = gtk_widget_get_window (invisible);
-
- if (!gdk_selection_owner_set_for_display (gdpy, invisible_window,
- selection_atom, GDK_CURRENT_TIME,
- TRUE))
- {
- g_critical ("Unable to get selection %s", selection_name);
- gtk_widget_destroy (invisible);
- return FALSE;
- }
-
- /* but we can use gdk here since we only care if it's our window */
- if (gdk_selection_owner_get_for_display (gdpy, selection_atom) != invisible_window)
- {
- gtk_widget_destroy (invisible);
- return FALSE;
- }
-
- xev.type = ClientMessage;
- xev.window = xroot;
- xev.message_type = gdk_x11_get_xatom_by_name_for_display (gdpy, "MANAGER");
- xev.format = 32;
- xev.data.l[0] = CurrentTime;
- xev.data.l[1] = selection_atom_x11;
- xev.data.l[2] = GDK_WINDOW_XID (invisible_window);
- xev.data.l[3] = xev.data.l[4] = 0;
-
- gdk_error_trap_push ();
- XSendEvent (dpy, xroot, False, StructureNotifyMask, (XEvent *)&xev);
- gdk_flush ();
- if (gdk_error_trap_pop ())
- g_critical ("Failed to send client event");
-
- if (filter_func != NULL)
- gdk_window_add_filter (invisible_window, filter_func, invisible);
-#endif
+ Atom type;
+ gint format;
+ gulong nitems;
+ gulong remaining;
+ Atom *targets = NULL;
+ GSList *tmp;
+
+ switch (xev->xany.type) {
+ case DestroyNotify:
+ if (xev->xdestroywindow.window == manager->priv->requestor) {
+ g_slist_foreach (manager->priv->contents, (GFunc) target_data_unref, NULL);
+ g_slist_free (manager->priv->contents);
+ manager->priv->contents = NULL;
+
+ clipboard_manager_watch_cb (manager,
+ manager->priv->requestor,
+ False,
+ 0,
+ NULL);
+ manager->priv->requestor = None;
+ }
+ break;
+
+ case PropertyNotify:
+ if (xev->xproperty.state == PropertyNewValue) {
+ return receive_incrementally (manager, xev);
+ } else {
+ return send_incrementally (manager, xev);
+ }
+ break;
+
+ case SelectionClear:
+ if (xev->xany.window != manager->priv->window)
+ return False;
+
+ if (xev->xselectionclear.selection == XA_CLIPBOARD_MANAGER) {
+ /* We lost the manager selection */
+ if (manager->priv->contents) {
+ g_slist_foreach (manager->priv->contents, (GFunc) target_data_unref, NULL);
+ g_slist_free (manager->priv->contents);
+ manager->priv->contents = NULL;
+
+ XSetSelectionOwner (manager->priv->display,
+ XA_CLIPBOARD,
+ None, manager->priv->time);
+ }
+
+ return True;
+ }
+ if (xev->xselectionclear.selection == XA_CLIPBOARD) {
+ /* We lost the clipboard selection */
+ g_slist_foreach (manager->priv->contents, (GFunc) target_data_unref, NULL);
+ g_slist_free (manager->priv->contents);
+ manager->priv->contents = NULL;
+ clipboard_manager_watch_cb (manager,
+ manager->priv->requestor,
+ False,
+ 0,
+ NULL);
+ manager->priv->requestor = None;
+
+ return True;
+ }
+ break;
+
+ case SelectionNotify:
+ if (xev->xany.window != manager->priv->window)
+ return False;
+
+ if (xev->xselection.selection == XA_CLIPBOARD) {
+ /* a CLIPBOARD conversion is done */
+ if (xev->xselection.property == XA_TARGETS) {
+ XGetWindowProperty (xev->xselection.display,
+ xev->xselection.requestor,
+ xev->xselection.property,
+ 0, 0x1FFFFFFF, True, XA_ATOM,
+ &type, &format, &nitems, &remaining,
+ (guchar **) &targets);
+
+ save_targets (manager, targets, nitems);
+ } else if (xev->xselection.property == XA_MULTIPLE) {
+ tmp = g_slist_copy (manager->priv->contents);
+ g_slist_foreach (tmp, (GFunc) get_property, manager);
+ g_slist_free (tmp);
+
+ manager->priv->time = xev->xselection.time;
+ XSetSelectionOwner (manager->priv->display, XA_CLIPBOARD,
+ manager->priv->window, manager->priv->time);
+
+ if (manager->priv->property != None)
+ XChangeProperty (manager->priv->display,
+ manager->priv->requestor,
+ manager->priv->property,
+ XA_ATOM, 32, PropModeReplace,
+ (guchar *)&XA_NULL, 1);
+
+ if (!g_slist_find_custom (manager->priv->contents,
+ &XA_INCR, (GCompareFunc) find_content_type)) {
+ /* all transfers done */
+ send_selection_notify (manager, True);
+ clipboard_manager_watch_cb (manager,
+ manager->priv->requestor,
+ False,
+ 0,
+ NULL);
+ manager->priv->requestor = None;
+ }
+ }
+ else if (xev->xselection.property == None) {
+ send_selection_notify (manager, False);
+ clipboard_manager_watch_cb (manager,
+ manager->priv->requestor,
+ False,
+ 0,
+ NULL);
+ manager->priv->requestor = None;
+ }
+
+ return True;
+ }
+ break;
+
+ case SelectionRequest:
+ if (xev->xany.window != manager->priv->window) {
+ return False;
+ }
+
+ if (xev->xselectionrequest.selection == XA_CLIPBOARD_MANAGER) {
+ convert_clipboard_manager (manager, xev);
+ return True;
+ } else if (xev->xselectionrequest.selection == XA_CLIPBOARD) {
+ convert_clipboard (manager, xev);
+ return True;
+ }
+ break;
+
+ default:;
+ }
- return TRUE;
+ return False;
}
+static GdkFilterReturn
+clipboard_manager_event_filter (GdkXEvent *xevent,
+ GdkEvent *event,
+ GsdClipboardManager *manager)
+{
+ if (clipboard_manager_process_event (manager, (XEvent *)xevent)) {
+ return GDK_FILTER_REMOVE;
+ } else {
+ return GDK_FILTER_CONTINUE;
+ }
+}
-
-XfceClipboardManager *
-xfce_clipboard_manager_new (void)
+static void
+clipboard_manager_watch_cb (GsdClipboardManager *manager,
+ Window window,
+ Bool is_start,
+ long mask,
+ void *cb_data)
{
- return g_object_new (XFCE_TYPE_CLIPBOARD_MANAGER, NULL);
+ GdkWindow *gdkwin;
+ GdkDisplay *display;
+
+ display = gdk_display_get_default ();
+#if GTK_CHECK_VERSION (2, 24, 0)
+ gdkwin = gdk_x11_window_lookup_for_display (display, window);
+#else
+ gdkwin = gdk_window_lookup_for_display (display, window);
+#endif
+
+ if (is_start) {
+ if (gdkwin == NULL) {
+#if GTK_CHECK_VERSION (2, 24, 0)
+ gdkwin = gdk_x11_window_foreign_new_for_display (display, window);
+#else
+ gdkwin = gdk_window_foreign_new_for_display (display, window);
+#endif
+ } else {
+ g_object_ref (gdkwin);
+ }
+
+ gdk_window_add_filter (gdkwin,
+ (GdkFilterFunc) clipboard_manager_event_filter,
+ manager);
+ } else {
+ if (gdkwin == NULL) {
+ return;
+ }
+ gdk_window_remove_filter (gdkwin,
+ (GdkFilterFunc) clipboard_manager_event_filter,
+ manager);
+ g_object_unref (gdkwin);
+ }
}
+static void
+init_atoms (Display *display)
+{
+ gulong max_request_size;
+ if (SELECTION_MAX_SIZE > 0)
+ return;
+
+ XA_ATOM_PAIR = XInternAtom (display, "ATOM_PAIR", False);
+ XA_CLIPBOARD_MANAGER = XInternAtom (display, "CLIPBOARD_MANAGER", False);
+ XA_CLIPBOARD = XInternAtom (display, "CLIPBOARD", False);
+ XA_DELETE = XInternAtom (display, "DELETE", False);
+ XA_INCR = XInternAtom (display, "INCR", False);
+ XA_INSERT_PROPERTY = XInternAtom (display, "INSERT_PROPERTY", False);
+ XA_INSERT_SELECTION = XInternAtom (display, "INSERT_SELECTION", False);
+ XA_MANAGER = XInternAtom (display, "MANAGER", False);
+ XA_MULTIPLE = XInternAtom (display, "MULTIPLE", False);
+ XA_NULL = XInternAtom (display, "NULL", False);
+ XA_SAVE_TARGETS = XInternAtom (display, "SAVE_TARGETS", False);
+ XA_TARGETS = XInternAtom (display, "TARGETS", False);
+ XA_TIMESTAMP = XInternAtom (display, "TIMESTAMP", False);
+
+ max_request_size = XExtendedMaxRequestSize (display);
+ if (max_request_size == 0)
+ max_request_size = XMaxRequestSize (display);
+
+ SELECTION_MAX_SIZE = max_request_size - 100;
+ if (SELECTION_MAX_SIZE > 262144)
+ SELECTION_MAX_SIZE = 262144;
+}
gboolean
-xfce_clipboard_manager_start (XfceClipboardManager *manager)
+gsd_clipboard_manager_start (GsdClipboardManager *manager,
+ gboolean replace)
{
- g_return_val_if_fail (XFCE_IS_CLIPBOARD_MANAGER (manager), FALSE);
-
- /* Check if there is a clipboard manager running */
- if (gdk_display_supports_clipboard_persistence (gdk_display_get_default ()))
- {
- g_message ("A clipboard manager is already running.");
- return FALSE;
- }
-
- if (!xfce_clipboard_manager_selection_owner ("CLIPBOARD_MANAGER", FALSE, NULL))
- {
- g_warning ("Unable to get the clipboard manager selection.");
- return FALSE;
- }
-
- g_signal_connect_swapped (manager->default_clipboard, "owner-change",
- G_CALLBACK (xfce_clipboard_manager_default_owner_change),
- manager);
- g_signal_connect_swapped (manager->primary_clipboard, "owner-change",
- G_CALLBACK (xfce_clipboard_manager_primary_owner_change),
- manager);
-
- return TRUE;
-}
+ XClientMessageEvent xev;
+ init_atoms (manager->priv->display);
+ /* check if there is a clipboard manager running */
+ if (!replace
+ && XGetSelectionOwner (manager->priv->display, XA_CLIPBOARD_MANAGER)) {
+ return FALSE;
+ }
+
+ manager->priv->contents = NULL;
+ manager->priv->conversions = NULL;
+ manager->priv->requestor = None;
+
+ manager->priv->window = XCreateSimpleWindow (manager->priv->display,
+ DefaultRootWindow (manager->priv->display),
+ 0, 0, 10, 10, 0,
+ WhitePixel (manager->priv->display,
+ DefaultScreen (manager->priv->display)),
+ WhitePixel (manager->priv->display,
+ DefaultScreen (manager->priv->display)));
+ clipboard_manager_watch_cb (manager,
+ manager->priv->window,
+ True,
+ PropertyChangeMask,
+ NULL);
+ XSelectInput (manager->priv->display,
+ manager->priv->window,
+ PropertyChangeMask);
+ manager->priv->timestamp = xfce_xsettings_get_server_time (manager->priv->display, manager->priv->window);
+
+ XSetSelectionOwner (manager->priv->display,
+ XA_CLIPBOARD_MANAGER,
+ manager->priv->window,
+ manager->priv->timestamp);
+
+ /* Check to see if we managed to claim the selection. If not,
+ * we treat it as if we got it then immediately lost it
+ */
+ if (XGetSelectionOwner (manager->priv->display, XA_CLIPBOARD_MANAGER) == manager->priv->window) {
+ xev.type = ClientMessage;
+ xev.window = DefaultRootWindow (manager->priv->display);
+ xev.message_type = XA_MANAGER;
+ xev.format = 32;
+ xev.data.l[0] = manager->priv->timestamp;
+ xev.data.l[1] = XA_CLIPBOARD_MANAGER;
+ xev.data.l[2] = manager->priv->window;
+ xev.data.l[3] = 0; /* manager specific data */
+ xev.data.l[4] = 0; /* manager specific data */
+
+ XSendEvent (manager->priv->display,
+ DefaultRootWindow (manager->priv->display),
+ False,
+ StructureNotifyMask,
+ (XEvent *)&xev);
+ } else {
+ clipboard_manager_watch_cb (manager,
+ manager->priv->window,
+ False,
+ 0,
+ NULL);
+ }
+
+ manager->priv->start_idle_id = 0;
+
+ return TRUE;
+}
void
-xfce_clipboard_manager_stop (XfceClipboardManager *manager)
+gsd_clipboard_manager_stop (GsdClipboardManager *manager)
{
- g_return_if_fail (XFCE_IS_CLIPBOARD_MANAGER (manager));
-
- g_signal_handlers_disconnect_by_func (manager->default_clipboard,
- xfce_clipboard_manager_default_owner_change,
- manager);
- g_signal_handlers_disconnect_by_func (manager->primary_clipboard,
- xfce_clipboard_manager_primary_owner_change,
- manager);
+ if (manager->priv->window != None) {
+ clipboard_manager_watch_cb (manager,
+ manager->priv->window,
+ False,
+ 0,
+ NULL);
+ XDestroyWindow (manager->priv->display, manager->priv->window);
+ manager->priv->window = None;
+ }
- if (manager->default_cache != NULL)
- {
- g_slist_foreach (manager->default_cache, (GFunc)gtk_selection_data_free, NULL);
- g_slist_free (manager->default_cache);
- manager->default_cache = NULL;
- }
+ if (manager->priv->conversions != NULL) {
+ g_slist_foreach (manager->priv->conversions, (GFunc) conversion_free, NULL);
+ g_slist_free (manager->priv->conversions);
+ manager->priv->conversions = NULL;
+ }
- if (manager->primary_cache != NULL)
- g_free (manager->primary_cache);
+ if (manager->priv->contents != NULL) {
+ g_slist_foreach (manager->priv->contents, (GFunc) target_data_unref, NULL);
+ g_slist_free (manager->priv->contents);
+ manager->priv->contents = NULL;
+ }
}
diff --git a/xfce4-settings-helper/clipboard-manager.h b/xfce4-settings-helper/clipboard-manager.h
index 86c9bf2..5b74895 100644
--- a/xfce4-settings-helper/clipboard-manager.h
+++ b/xfce4-settings-helper/clipboard-manager.h
@@ -18,29 +18,42 @@
*
*/
-#ifndef __XFCE_CLIPBOARD_MANAGER_H
-#define __XFCE_CLIPBOARD_MANAGER_H
+#ifndef __GSD_CLIPBOARD_MANAGER_H
+#define __GSD_CLIPBOARD_MANAGER_H
#include <glib-object.h>
G_BEGIN_DECLS
-typedef struct _XfceClipboardManager XfceClipboardManager;
-typedef struct _XfceClipboardManagerClass XfceClipboardManagerClass;
+typedef struct _GsdClipboardManager GsdClipboardManager;
+typedef struct _GsdClipboardManagerClass GsdClipboardManagerClass;
+typedef struct _GsdClipboardManagerPrivate GsdClipboardManagerPrivate;
-#define XFCE_TYPE_CLIPBOARD_MANAGER (xfce_clipboard_manager_get_type ())
-#define XFCE_CLIPBOARD_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), XFCE_TYPE_CLIPBOARD_MANAGER, XfceClipboardManager))
-#define XFCE_CLIPBOARD_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), XFCE_TYPE_CLIPBOARD_MANAGER, XfceClipboardManagerClass))
-#define XFCE_IS_CLIPBOARD_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), XFCE_TYPE_CLIPBOARD_MANAGER))
-#define XFCE_IS_CLIPBOARD_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), XFCE_TYPE_CLIPBOARD_MANAGER))
-#define XFCE_CLIPBOARD_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), XFCE_TYPE_CLIPBOARD_MANAGER, XfceClipboardManagerClass))
+#define GSD_TYPE_CLIPBOARD_MANAGER (gsd_clipboard_manager_get_type ())
+#define GSD_CLIPBOARD_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_CLIPBOARD_MANAGER, GsdClipboardManager))
+#define GSD_CLIPBOARD_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_CLIPBOARD_MANAGER, GsdClipboardManagerClass))
+#define GSD_IS_CLIPBOARD_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_CLIPBOARD_MANAGER))
+#define GSD_IS_CLIPBOARD_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_CLIPBOARD_MANAGER))
+#define GSD_CLIPBOARD_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_CLIPBOARD_MANAGER, GsdClipboardManagerClass))
-GType xfce_clipboard_manager_get_type (void);
+struct _GsdClipboardManager
+{
+ GObject parent;
+ GsdClipboardManagerPrivate *priv;
+};
-XfceClipboardManager *xfce_clipboard_manager_new (void);
-gboolean xfce_clipboard_manager_start (XfceClipboardManager *manager);
-void xfce_clipboard_manager_stop (XfceClipboardManager *manager);
+struct _GsdClipboardManagerClass
+{
+ GObjectClass parent_class;
+};
+
+GType gsd_clipboard_manager_get_type (void);
+
+gboolean gsd_clipboard_manager_start (GsdClipboardManager *manager,
+ gboolean replace);
+
+void gsd_clipboard_manager_stop (GsdClipboardManager *manager);
G_END_DECLS
-#endif /* __XFCE_CLIPBOARD_MANAGER_H */
+#endif /* __GSD_CLIPBOARD_MANAGER_H */
diff --git a/xfce4-settings-helper/main.c b/xfce4-settings-helper/main.c
index 453fd92..9c43f55 100644
--- a/xfce4-settings-helper/main.c
+++ b/xfce4-settings-helper/main.c
@@ -125,7 +125,6 @@ xfce_settings_helper_set_autostart_enabled (gboolean enabled)
gint
main (gint argc, gchar **argv)
{
- XfceClipboardManager *clipboard_daemon;
GError *error = NULL;
GOptionContext *context;
gboolean in_session;
@@ -134,6 +133,7 @@ main (gint argc, gchar **argv)
GObject *accessibility_helper;
GObject *shortcuts_helper;
GObject *keyboard_layout_helper;
+ GObject *clipboard_daemon = NULL;
#ifdef HAVE_XRANDR
GObject *displays_helper;
#endif
@@ -249,11 +249,16 @@ main (gint argc, gchar **argv)
keyboard_layout_helper = g_object_new (XFCE_TYPE_KEYBOARD_LAYOUT_HELPER, NULL);
workspaces_helper = g_object_new (XFCE_TYPE_WORKSPACES_HELPER, NULL);
- clipboard_daemon = xfce_clipboard_manager_new ();
- if (!xfce_clipboard_manager_start (clipboard_daemon))
+ if (g_getenv ("XFSETTINGSD_NO_CLIPBOARD") == NULL)
{
- g_object_unref (G_OBJECT (clipboard_daemon));
- clipboard_daemon = NULL;
+ clipboard_daemon = g_object_new (GSD_TYPE_CLIPBOARD_MANAGER, NULL);
+ if (!gsd_clipboard_manager_start (GSD_CLIPBOARD_MANAGER (clipboard_daemon), FALSE))
+ {
+ g_object_unref (G_OBJECT (clipboard_daemon));
+ clipboard_daemon = NULL;
+
+ g_printerr (G_LOG_DOMAIN ": %s\n", "Another clipboard manager is already running.");
+ }
}
/* setup signal handlers to properly quit the main loop */
@@ -282,7 +287,7 @@ main (gint argc, gchar **argv)
if (G_LIKELY (clipboard_daemon != NULL))
{
- xfce_clipboard_manager_stop (clipboard_daemon);
+ gsd_clipboard_manager_stop (GSD_CLIPBOARD_MANAGER (clipboard_daemon));
g_object_unref (G_OBJECT (clipboard_daemon));
}
More information about the Xfce4-commits
mailing list