wayland: Implement taking over the clipboard
The clipboard is now complete. That was fast.
This commit is contained in:
@@ -22,10 +22,12 @@
|
||||
|
||||
#include "gdkcontentformats.h"
|
||||
#include "gdkintl.h"
|
||||
#include "gdkprivate-wayland.h"
|
||||
#include "gdk-private.h"
|
||||
|
||||
#include <glib-unix.h>
|
||||
#include <gio/gunixinputstream.h>
|
||||
#include <gio/gunixoutputstream.h>
|
||||
|
||||
typedef struct _GdkWaylandClipboardClass GdkWaylandClipboardClass;
|
||||
|
||||
@@ -35,6 +37,8 @@ struct _GdkWaylandClipboard
|
||||
|
||||
struct wl_data_offer *offer;
|
||||
GdkContentFormats *offer_formats;
|
||||
|
||||
struct wl_data_source *source;
|
||||
};
|
||||
|
||||
struct _GdkWaylandClipboardClass
|
||||
@@ -51,16 +55,116 @@ gdk_wayland_clipboard_discard_offer (GdkWaylandClipboard *cb)
|
||||
g_clear_pointer (&cb->offer, (GDestroyNotify) wl_data_offer_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_clipboard_discard_source (GdkWaylandClipboard *cb)
|
||||
{
|
||||
g_clear_pointer (&cb->source, (GDestroyNotify) wl_data_source_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_clipboard_finalize (GObject *object)
|
||||
{
|
||||
GdkWaylandClipboard *cb = GDK_WAYLAND_CLIPBOARD (object);
|
||||
|
||||
gdk_wayland_clipboard_discard_offer (cb);
|
||||
gdk_wayland_clipboard_discard_source (cb);
|
||||
|
||||
G_OBJECT_CLASS (gdk_wayland_clipboard_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_clipboard_data_source_target (void *data,
|
||||
struct wl_data_source *source,
|
||||
const char *mime_type)
|
||||
{
|
||||
GDK_NOTE (CLIPBOARD, g_printerr ("%p: Huh? data_source.target() events?\n", data));
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_clipboard_write_done (GObject *clipboard,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!gdk_clipboard_write_finish (GDK_CLIPBOARD (clipboard), result, &error))
|
||||
{
|
||||
GDK_NOTE(CLIPBOARD, g_printerr ("%p: failed to write stream: %s\n", clipboard, error->message));
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_clipboard_data_source_send (void *data,
|
||||
struct wl_data_source *source,
|
||||
const char *mime_type,
|
||||
int32_t fd)
|
||||
{
|
||||
GdkWaylandClipboard *cb = GDK_WAYLAND_CLIPBOARD (data);
|
||||
GOutputStream *stream;
|
||||
|
||||
GDK_NOTE (CLIPBOARD, g_printerr ("%p: data source send request for %s on fd %d\n",
|
||||
source, mime_type, fd));
|
||||
|
||||
mime_type = gdk_intern_mime_type (mime_type);
|
||||
stream = g_unix_output_stream_new (fd, TRUE);
|
||||
|
||||
gdk_clipboard_write_async (GDK_CLIPBOARD (cb),
|
||||
mime_type,
|
||||
stream,
|
||||
G_PRIORITY_DEFAULT,
|
||||
NULL,
|
||||
gdk_wayland_clipboard_write_done,
|
||||
cb);
|
||||
g_object_unref (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_clipboard_data_source_cancelled (void *data,
|
||||
struct wl_data_source *source)
|
||||
{
|
||||
GdkWaylandClipboard *cb = GDK_WAYLAND_CLIPBOARD (data);
|
||||
|
||||
GDK_NOTE (CLIPBOARD, g_printerr ("%p: data source cancelled\n", data));
|
||||
|
||||
if (cb->source == source)
|
||||
{
|
||||
gdk_wayland_clipboard_discard_source (cb);
|
||||
gdk_wayland_clipboard_claim_remote (cb, NULL, gdk_content_formats_new (NULL, 0));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_clipboard_data_source_dnd_drop_performed (void *data,
|
||||
struct wl_data_source *source)
|
||||
{
|
||||
GDK_NOTE (CLIPBOARD, g_printerr ("%p: Huh? data_source.dnd_drop_performed() events?\n", data));
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_clipboard_data_source_dnd_finished (void *data,
|
||||
struct wl_data_source *source)
|
||||
{
|
||||
GDK_NOTE (CLIPBOARD, g_printerr ("%p: Huh? data_source.dnd_finished() events?\n", data));
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_clipboard_data_source_action (void *data,
|
||||
struct wl_data_source *source,
|
||||
uint32_t action)
|
||||
{
|
||||
GDK_NOTE (CLIPBOARD, g_printerr ("%p: Huh? data_source.action() events?\n", data));
|
||||
}
|
||||
|
||||
static const struct wl_data_source_listener data_source_listener = {
|
||||
gdk_wayland_clipboard_data_source_target,
|
||||
gdk_wayland_clipboard_data_source_send,
|
||||
gdk_wayland_clipboard_data_source_cancelled,
|
||||
gdk_wayland_clipboard_data_source_dnd_drop_performed,
|
||||
gdk_wayland_clipboard_data_source_dnd_finished,
|
||||
gdk_wayland_clipboard_data_source_action,
|
||||
};
|
||||
|
||||
static gboolean
|
||||
gdk_wayland_clipboard_claim (GdkClipboard *clipboard,
|
||||
GdkContentFormats *formats,
|
||||
@@ -71,8 +175,25 @@ gdk_wayland_clipboard_claim (GdkClipboard *clipboard,
|
||||
|
||||
if (local)
|
||||
{
|
||||
/* not handled yet */
|
||||
cb->offer = NULL;
|
||||
GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY (gdk_clipboard_get_display (clipboard));
|
||||
GdkDevice *device;
|
||||
const char * const *mime_types;
|
||||
gsize i, n_mime_types;
|
||||
|
||||
gdk_wayland_clipboard_discard_offer (cb);
|
||||
gdk_wayland_clipboard_discard_source (cb);
|
||||
|
||||
cb->source = wl_data_device_manager_create_data_source (wayland_display->data_device_manager);
|
||||
wl_data_source_add_listener (cb->source, &data_source_listener, cb);
|
||||
|
||||
mime_types = gdk_content_formats_get_mime_types (formats, &n_mime_types);
|
||||
for (i = 0; i < n_mime_types; i++)
|
||||
{
|
||||
wl_data_source_offer (cb->source, mime_types[i]);
|
||||
}
|
||||
|
||||
device = gdk_seat_get_pointer (gdk_display_get_default_seat (GDK_DISPLAY (wayland_display)));
|
||||
gdk_wayland_device_set_selection (device, cb->source);
|
||||
}
|
||||
|
||||
return GDK_CLIPBOARD_CLASS (gdk_wayland_clipboard_parent_class)->claim (clipboard, formats, local, content);
|
||||
@@ -163,10 +284,6 @@ gdk_wayland_clipboard_class_init (GdkWaylandClipboardClass *class)
|
||||
object_class->finalize = gdk_wayland_clipboard_finalize;
|
||||
|
||||
clipboard_class->claim = gdk_wayland_clipboard_claim;
|
||||
#if 0
|
||||
clipboard_class->store_async = gdk_wayland_clipboard_store_async;
|
||||
clipboard_class->store_finish = gdk_wayland_clipboard_store_finish;
|
||||
#endif
|
||||
clipboard_class->read_async = gdk_wayland_clipboard_read_async;
|
||||
clipboard_class->read_finish = gdk_wayland_clipboard_read_finish;
|
||||
}
|
||||
@@ -195,6 +312,12 @@ gdk_wayland_clipboard_claim_remote (GdkWaylandClipboard *cb,
|
||||
{
|
||||
g_return_if_fail (GDK_IS_WAYLAND_CLIPBOARD (cb));
|
||||
|
||||
if (cb->source)
|
||||
{
|
||||
GDK_NOTE (CLIPBOARD, g_printerr ("%p: Ignoring clipboard offer for self\n", cb));
|
||||
return;
|
||||
}
|
||||
|
||||
gdk_wayland_clipboard_discard_offer (cb);
|
||||
|
||||
GDK_NOTE (CLIPBOARD, char *s = gdk_content_formats_to_string (formats);
|
||||
|
||||
@@ -83,7 +83,6 @@ struct _SelectionData
|
||||
|
||||
enum {
|
||||
ATOM_PRIMARY,
|
||||
ATOM_CLIPBOARD,
|
||||
ATOM_DND,
|
||||
N_ATOMS
|
||||
};
|
||||
@@ -104,9 +103,6 @@ struct _GdkWaylandSelection
|
||||
struct gtk_primary_selection_source *primary_source;
|
||||
GdkWindow *primary_owner;
|
||||
|
||||
struct wl_data_source *clipboard_source;
|
||||
GdkWindow *clipboard_owner;
|
||||
|
||||
struct wl_data_source *dnd_source; /* Owned by the GdkDragContext */
|
||||
GdkWindow *dnd_owner;
|
||||
};
|
||||
@@ -312,7 +308,6 @@ gdk_wayland_selection_new (void)
|
||||
|
||||
/* init atoms */
|
||||
atoms[ATOM_PRIMARY] = gdk_atom_intern_static_string ("PRIMARY");
|
||||
atoms[ATOM_CLIPBOARD] = gdk_atom_intern_static_string ("CLIPBOARD");
|
||||
atoms[ATOM_DND] = gdk_atom_intern_static_string ("GdkWaylandSelection");
|
||||
|
||||
selection = g_new0 (GdkWaylandSelection, 1);
|
||||
@@ -355,8 +350,6 @@ gdk_wayland_selection_free (GdkWaylandSelection *selection)
|
||||
|
||||
if (selection->primary_source)
|
||||
gtk_primary_selection_source_destroy (selection->primary_source);
|
||||
if (selection->clipboard_source)
|
||||
wl_data_source_destroy (selection->clipboard_source);
|
||||
if (selection->dnd_source)
|
||||
wl_data_source_destroy (selection->dnd_source);
|
||||
|
||||
@@ -489,8 +482,6 @@ selection_lookup_offer_by_atom (GdkWaylandSelection *selection,
|
||||
{
|
||||
if (selection_atom == atoms[ATOM_PRIMARY])
|
||||
return &selection->selections[ATOM_PRIMARY];
|
||||
else if (selection_atom == atoms[ATOM_CLIPBOARD])
|
||||
return &selection->selections[ATOM_CLIPBOARD];
|
||||
else if (selection_atom == atoms[ATOM_DND])
|
||||
return &selection->selections[ATOM_DND];
|
||||
else
|
||||
@@ -903,11 +894,6 @@ data_source_send (void *data,
|
||||
window = wayland_selection->dnd_owner;
|
||||
selection = atoms[ATOM_DND];
|
||||
}
|
||||
else if (source == wayland_selection->clipboard_source)
|
||||
{
|
||||
window = wayland_selection->clipboard_owner;
|
||||
selection = atoms[ATOM_CLIPBOARD];
|
||||
}
|
||||
else
|
||||
{
|
||||
close (fd);
|
||||
@@ -940,8 +926,6 @@ data_source_cancelled (void *data,
|
||||
|
||||
if (source == wayland_selection->dnd_source)
|
||||
atom = atoms[ATOM_DND];
|
||||
else if (source == wayland_selection->clipboard_source)
|
||||
atom = atoms[ATOM_CLIPBOARD];
|
||||
else
|
||||
return;
|
||||
|
||||
@@ -1098,18 +1082,6 @@ gdk_wayland_selection_get_data_source (GdkWindow *owner,
|
||||
wayland_selection->primary_source = NULL;
|
||||
}
|
||||
}
|
||||
else if (selection == atoms[ATOM_CLIPBOARD])
|
||||
{
|
||||
if (wayland_selection->clipboard_source &&
|
||||
(!owner || owner == wayland_selection->clipboard_owner))
|
||||
return wayland_selection->clipboard_source;
|
||||
|
||||
if (wayland_selection->clipboard_source)
|
||||
{
|
||||
wl_data_source_destroy (wayland_selection->clipboard_source);
|
||||
wayland_selection->clipboard_source = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
|
||||
@@ -1140,8 +1112,6 @@ gdk_wayland_selection_get_data_source (GdkWindow *owner,
|
||||
wayland_selection->dnd_source = source;
|
||||
else if (selection == atoms[ATOM_PRIMARY])
|
||||
wayland_selection->primary_source = source;
|
||||
else if (selection == atoms[ATOM_CLIPBOARD])
|
||||
wayland_selection->clipboard_source = source;
|
||||
|
||||
return source;
|
||||
}
|
||||
@@ -1152,21 +1122,7 @@ gdk_wayland_selection_unset_data_source (GdkDisplay *display,
|
||||
{
|
||||
GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display);
|
||||
|
||||
if (selection == atoms[ATOM_CLIPBOARD])
|
||||
{
|
||||
GdkDevice *device;
|
||||
|
||||
device = gdk_seat_get_pointer (gdk_display_get_default_seat (display));
|
||||
|
||||
gdk_wayland_device_set_selection (device, NULL);
|
||||
|
||||
if (wayland_selection->clipboard_source)
|
||||
{
|
||||
wl_data_source_destroy (wayland_selection->clipboard_source);
|
||||
wayland_selection->clipboard_source = NULL;
|
||||
}
|
||||
}
|
||||
else if (selection == atoms[ATOM_PRIMARY])
|
||||
if (selection == atoms[ATOM_PRIMARY])
|
||||
{
|
||||
GdkSeat *seat = gdk_display_get_default_seat (display);
|
||||
|
||||
@@ -1190,9 +1146,7 @@ _gdk_wayland_display_get_selection_owner (GdkDisplay *display,
|
||||
{
|
||||
GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display);
|
||||
|
||||
if (selection == atoms[ATOM_CLIPBOARD])
|
||||
return wayland_selection->clipboard_owner;
|
||||
else if (selection == atoms[ATOM_PRIMARY])
|
||||
if (selection == atoms[ATOM_PRIMARY])
|
||||
return wayland_selection->primary_owner;
|
||||
else if (selection == atoms[ATOM_DND])
|
||||
return wayland_selection->dnd_owner;
|
||||
@@ -1209,12 +1163,7 @@ _gdk_wayland_display_set_selection_owner (GdkDisplay *display,
|
||||
{
|
||||
GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display);
|
||||
|
||||
if (selection == atoms[ATOM_CLIPBOARD])
|
||||
{
|
||||
wayland_selection->clipboard_owner = owner;
|
||||
return TRUE;
|
||||
}
|
||||
else if (selection == atoms[ATOM_PRIMARY])
|
||||
if (selection == atoms[ATOM_PRIMARY])
|
||||
{
|
||||
wayland_selection->primary_owner = owner;
|
||||
return TRUE;
|
||||
@@ -1553,16 +1502,7 @@ gdk_wayland_display_add_selection_targets (GdkDisplay *display,
|
||||
g_free (mimetype);
|
||||
}
|
||||
|
||||
if (selection == atoms[ATOM_CLIPBOARD])
|
||||
{
|
||||
GdkDisplay *display;
|
||||
GdkDevice *device;
|
||||
|
||||
display = gdk_window_get_display (window);
|
||||
device = gdk_seat_get_pointer (gdk_display_get_default_seat (display));
|
||||
gdk_wayland_device_set_selection (device, data_source);
|
||||
}
|
||||
else if (selection == atoms[ATOM_PRIMARY])
|
||||
if (selection == atoms[ATOM_PRIMARY])
|
||||
{
|
||||
GdkSeat *seat;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user