mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-27 06:00:22 +00:00
wayland: Add primary clipboard subclass
I decided to put this in a custom subclass, because then I could keep the whole gtk primary protocol self-contained. The other option would have been reusing GdkWaylandClipboard, but that didn't seem worth it, especially because that code needs to interact with the DND machinery, while the primary doesn't.
This commit is contained in:
parent
ef69daacdf
commit
ff577e6c2c
@ -34,6 +34,7 @@
|
||||
#include "gdkdeviceprivate.h"
|
||||
#include "gdkdevicepadprivate.h"
|
||||
#include "gdkdevicetoolprivate.h"
|
||||
#include "gdkprimary-wayland.h"
|
||||
#include "gdkseatprivate.h"
|
||||
#include "pointer-gestures-unstable-v1-client-protocol.h"
|
||||
#include "tablet-unstable-v2-client-protocol.h"
|
||||
@ -233,7 +234,6 @@ struct _GdkWaylandSeat
|
||||
|
||||
GdkClipboard *clipboard;
|
||||
GdkClipboard *primary_clipboard;
|
||||
struct gtk_primary_selection_device *primary_data_device;
|
||||
struct wl_data_device *data_device;
|
||||
GdkDragContext *drop_context;
|
||||
|
||||
@ -1211,45 +1211,6 @@ static const struct wl_data_device_listener data_device_listener = {
|
||||
data_device_selection
|
||||
};
|
||||
|
||||
static void
|
||||
primary_selection_data_offer (void *data,
|
||||
struct gtk_primary_selection_device *gtk_primary_selection_device,
|
||||
struct gtk_primary_selection_offer *gtk_primary_offer)
|
||||
{
|
||||
GdkWaylandSeat *seat = data;
|
||||
|
||||
GDK_NOTE (EVENTS,
|
||||
g_message ("primary selection offer, device %p, data offer %p",
|
||||
gtk_primary_selection_device, gtk_primary_offer));
|
||||
|
||||
gdk_wayland_selection_ensure_primary_offer (seat->display, gtk_primary_offer);
|
||||
}
|
||||
|
||||
static void
|
||||
primary_selection_selection (void *data,
|
||||
struct gtk_primary_selection_device *gtk_primary_selection_device,
|
||||
struct gtk_primary_selection_offer *gtk_primary_offer)
|
||||
{
|
||||
GdkWaylandSeat *seat = data;
|
||||
GdkAtom selection;
|
||||
|
||||
if (!seat->keyboard_focus)
|
||||
return;
|
||||
|
||||
GDK_NOTE (EVENTS,
|
||||
g_message ("primary selection selection, device %p, data offer %p",
|
||||
gtk_primary_selection_device, gtk_primary_offer));
|
||||
|
||||
selection = gdk_atom_intern_static_string ("PRIMARY");
|
||||
gdk_wayland_selection_set_offer (seat->display, selection, gtk_primary_offer);
|
||||
/* emit_selection_owner_change (seat->keyboard_focus, selection); */
|
||||
}
|
||||
|
||||
static const struct gtk_primary_selection_device_listener primary_selection_device_listener = {
|
||||
primary_selection_data_offer,
|
||||
primary_selection_selection,
|
||||
};
|
||||
|
||||
static GdkDevice * get_scroll_device (GdkWaylandSeat *seat,
|
||||
enum wl_pointer_axis_source source);
|
||||
|
||||
@ -4796,12 +4757,7 @@ _gdk_wayland_display_create_seat (GdkWaylandDisplay *display_wayland,
|
||||
|
||||
if (display_wayland->primary_selection_manager)
|
||||
{
|
||||
seat->primary_data_device =
|
||||
gtk_primary_selection_device_manager_get_device (display_wayland->primary_selection_manager,
|
||||
seat->wl_seat);
|
||||
gtk_primary_selection_device_add_listener (seat->primary_data_device,
|
||||
&primary_selection_device_listener, seat);
|
||||
seat->primary_clipboard = gdk_wayland_clipboard_new (display);
|
||||
seat->primary_clipboard = gdk_wayland_primary_new (seat);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -5016,23 +4972,6 @@ gdk_wayland_device_set_selection (GdkDevice *gdk_device,
|
||||
_gdk_wayland_display_get_serial (display_wayland));
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_seat_set_primary (GdkSeat *seat,
|
||||
struct gtk_primary_selection_source *source)
|
||||
{
|
||||
GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat);
|
||||
GdkWaylandDisplay *display_wayland;
|
||||
guint32 serial;
|
||||
|
||||
if (source)
|
||||
{
|
||||
display_wayland = GDK_WAYLAND_DISPLAY (gdk_seat_get_display (seat));
|
||||
serial = _gdk_wayland_display_get_serial (display_wayland);
|
||||
gtk_primary_selection_device_set_selection (wayland_seat->primary_data_device,
|
||||
source, serial);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_wayland_seat_get_wl_seat:
|
||||
* @device: (type GdkWaylandDevice): a #GdkDevice
|
||||
|
398
gdk/wayland/gdkprimary-wayland.c
Normal file
398
gdk/wayland/gdkprimary-wayland.c
Normal file
@ -0,0 +1,398 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2017 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkprimary-wayland.h"
|
||||
|
||||
#include "gdkclipboardprivate.h"
|
||||
#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 _GdkWaylandPrimaryClass GdkWaylandPrimaryClass;
|
||||
|
||||
struct _GdkWaylandPrimary
|
||||
{
|
||||
GdkClipboard parent;
|
||||
|
||||
struct gtk_primary_selection_device *primary_data_device;
|
||||
|
||||
struct gtk_primary_selection_offer *pending;
|
||||
GdkContentFormatsBuilder *pending_builder;
|
||||
|
||||
struct gtk_primary_selection_offer *offer;
|
||||
GdkContentFormats *offer_formats;
|
||||
|
||||
struct gtk_primary_selection_source *source;
|
||||
};
|
||||
|
||||
struct _GdkWaylandPrimaryClass
|
||||
{
|
||||
GdkClipboardClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GdkWaylandPrimary, gdk_wayland_primary, GDK_TYPE_CLIPBOARD)
|
||||
|
||||
static void
|
||||
gdk_wayland_primary_discard_pending (GdkWaylandPrimary *cb)
|
||||
{
|
||||
if (cb->pending_builder)
|
||||
{
|
||||
GdkContentFormats *ignore = gdk_content_formats_builder_free (cb->pending_builder);
|
||||
gdk_content_formats_unref (ignore);
|
||||
cb->pending_builder = NULL;
|
||||
}
|
||||
g_clear_pointer (&cb->pending, (GDestroyNotify) gtk_primary_selection_offer_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_primary_discard_offer (GdkWaylandPrimary *cb)
|
||||
{
|
||||
g_clear_pointer (&cb->offer_formats, gdk_content_formats_unref);
|
||||
g_clear_pointer (&cb->offer, (GDestroyNotify) gtk_primary_selection_offer_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_primary_discard_source (GdkWaylandPrimary *cb)
|
||||
{
|
||||
g_clear_pointer (&cb->source, (GDestroyNotify) wl_data_source_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_primary_finalize (GObject *object)
|
||||
{
|
||||
GdkWaylandPrimary *cb = GDK_WAYLAND_PRIMARY (object);
|
||||
|
||||
gdk_wayland_primary_discard_pending (cb);
|
||||
gdk_wayland_primary_discard_offer (cb);
|
||||
gdk_wayland_primary_discard_source (cb);
|
||||
|
||||
G_OBJECT_CLASS (gdk_wayland_primary_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_primary_claim_remote (GdkWaylandPrimary *cb,
|
||||
struct gtk_primary_selection_offer *offer,
|
||||
GdkContentFormats *formats)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_WAYLAND_PRIMARY (cb));
|
||||
|
||||
if (cb->source)
|
||||
{
|
||||
GDK_NOTE (CLIPBOARD, g_printerr ("%p: Ignoring clipboard offer for self\n", cb));
|
||||
return;
|
||||
}
|
||||
|
||||
gdk_wayland_primary_discard_offer (cb);
|
||||
|
||||
GDK_NOTE (CLIPBOARD, char *s = gdk_content_formats_to_string (formats);
|
||||
g_printerr ("%p: remote clipboard claim for %s\n", cb, s);
|
||||
g_free (s); );
|
||||
cb->offer_formats = formats;
|
||||
cb->offer = offer;
|
||||
|
||||
gdk_clipboard_claim_remote (GDK_CLIPBOARD (cb),
|
||||
cb->offer_formats);
|
||||
}
|
||||
|
||||
static void
|
||||
primary_offer_offer (void *data,
|
||||
struct gtk_primary_selection_offer *offer,
|
||||
const char *type)
|
||||
{
|
||||
GdkWaylandPrimary *cb = data;
|
||||
|
||||
if (cb->pending != offer)
|
||||
{
|
||||
GDK_NOTE (SELECTION, g_printerr ("%p: offer for unknown selection %p of %s\n",
|
||||
cb, offer, type));
|
||||
return;
|
||||
}
|
||||
|
||||
gdk_content_formats_builder_add_mime_type (cb->pending_builder, type);
|
||||
}
|
||||
|
||||
static const struct gtk_primary_selection_offer_listener primary_offer_listener = {
|
||||
primary_offer_offer,
|
||||
};
|
||||
|
||||
static void
|
||||
primary_selection_data_offer (void *data,
|
||||
struct gtk_primary_selection_device *device,
|
||||
struct gtk_primary_selection_offer *offer)
|
||||
{
|
||||
GdkWaylandPrimary *cb = data;
|
||||
|
||||
GDK_NOTE (SELECTION, g_printerr ("%p: new primary offer %p\n",
|
||||
cb, offer));
|
||||
|
||||
gdk_wayland_primary_discard_pending (cb);
|
||||
|
||||
cb->pending = offer;
|
||||
gtk_primary_selection_offer_add_listener (offer,
|
||||
&primary_offer_listener,
|
||||
cb);
|
||||
|
||||
cb->pending_builder = gdk_content_formats_builder_new ();
|
||||
}
|
||||
|
||||
static void
|
||||
primary_selection_selection (void *data,
|
||||
struct gtk_primary_selection_device *device,
|
||||
struct gtk_primary_selection_offer *offer)
|
||||
{
|
||||
GdkWaylandPrimary *cb = data;
|
||||
GdkContentFormats *formats;
|
||||
|
||||
if (offer == NULL)
|
||||
{
|
||||
gdk_wayland_primary_claim_remote (cb, NULL, gdk_content_formats_new (NULL, 0));
|
||||
return;
|
||||
}
|
||||
|
||||
if (cb->pending != offer)
|
||||
{
|
||||
GDK_NOTE (SELECTION, g_printerr ("%p: ignoring unknown data offer %p\n",
|
||||
cb, offer));
|
||||
return;
|
||||
}
|
||||
|
||||
formats = gdk_content_formats_builder_free (cb->pending_builder);
|
||||
cb->pending_builder = NULL;
|
||||
cb->pending = NULL;
|
||||
|
||||
gdk_wayland_primary_claim_remote (cb, offer, formats);
|
||||
}
|
||||
|
||||
static const struct gtk_primary_selection_device_listener primary_selection_device_listener = {
|
||||
primary_selection_data_offer,
|
||||
primary_selection_selection,
|
||||
};
|
||||
|
||||
static void
|
||||
gdk_wayland_primary_write_done (GObject *clipboard,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!gdk_clipboard_write_finish (GDK_CLIPBOARD (clipboard), result, &error))
|
||||
{
|
||||
GDK_NOTE (SELECTION, g_printerr ("%p: failed to write stream: %s\n", clipboard, error->message));
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_primary_data_source_send (void *data,
|
||||
struct gtk_primary_selection_source *source,
|
||||
const char *mime_type,
|
||||
int32_t fd)
|
||||
{
|
||||
GdkWaylandPrimary *cb = GDK_WAYLAND_PRIMARY (data);
|
||||
GOutputStream *stream;
|
||||
|
||||
GDK_NOTE (SELECTION, 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_primary_write_done,
|
||||
cb);
|
||||
g_object_unref (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_primary_data_source_cancelled (void *data,
|
||||
struct gtk_primary_selection_source *source)
|
||||
{
|
||||
GdkWaylandPrimary *cb = GDK_WAYLAND_PRIMARY (data);
|
||||
|
||||
GDK_NOTE (CLIPBOARD, g_printerr ("%p: data source cancelled\n", data));
|
||||
|
||||
if (cb->source == source)
|
||||
{
|
||||
gdk_wayland_primary_discard_source (cb);
|
||||
gdk_wayland_primary_claim_remote (cb, NULL, gdk_content_formats_new (NULL, 0));
|
||||
}
|
||||
}
|
||||
|
||||
static const struct gtk_primary_selection_source_listener primary_source_listener = {
|
||||
gdk_wayland_primary_data_source_send,
|
||||
gdk_wayland_primary_data_source_cancelled,
|
||||
};
|
||||
|
||||
static gboolean
|
||||
gdk_wayland_primary_claim (GdkClipboard *clipboard,
|
||||
GdkContentFormats *formats,
|
||||
gboolean local,
|
||||
GdkContentProvider *content)
|
||||
{
|
||||
GdkWaylandPrimary *cb = GDK_WAYLAND_PRIMARY (clipboard);
|
||||
|
||||
if (local)
|
||||
{
|
||||
GdkWaylandDisplay *wdisplay = GDK_WAYLAND_DISPLAY (gdk_clipboard_get_display (clipboard));
|
||||
const char * const *mime_types;
|
||||
gsize i, n_mime_types;
|
||||
|
||||
gdk_wayland_primary_discard_offer (cb);
|
||||
gdk_wayland_primary_discard_source (cb);
|
||||
|
||||
cb->source = gtk_primary_selection_device_manager_create_source (wdisplay->primary_selection_manager);
|
||||
gtk_primary_selection_source_add_listener (cb->source, &primary_source_listener, cb);
|
||||
|
||||
mime_types = gdk_content_formats_get_mime_types (formats, &n_mime_types);
|
||||
for (i = 0; i < n_mime_types; i++)
|
||||
{
|
||||
gtk_primary_selection_source_offer (cb->source, mime_types[i]);
|
||||
}
|
||||
|
||||
gtk_primary_selection_device_set_selection (cb->primary_data_device,
|
||||
cb->source,
|
||||
_gdk_wayland_display_get_serial (wdisplay));
|
||||
}
|
||||
|
||||
return GDK_CLIPBOARD_CLASS (gdk_wayland_primary_parent_class)->claim (clipboard, formats, local, content);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_primary_read_async (GdkClipboard *clipboard,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkWaylandPrimary *cb = GDK_WAYLAND_PRIMARY (clipboard);
|
||||
GInputStream *stream;
|
||||
const char *mime_type;
|
||||
int pipe_fd[2];
|
||||
GError *error = NULL;
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (clipboard, cancellable, callback, user_data);
|
||||
g_task_set_priority (task, io_priority);
|
||||
g_task_set_source_tag (task, gdk_wayland_primary_read_async);
|
||||
|
||||
GDK_NOTE (CLIPBOARD, char *s = gdk_content_formats_to_string (formats);
|
||||
g_printerr ("%p: read for %s\n", cb, s);
|
||||
g_free (s); );
|
||||
mime_type = gdk_content_formats_match_mime_type (formats, cb->offer_formats);
|
||||
if (mime_type == NULL)
|
||||
{
|
||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
_("No compatible transfer format found"));
|
||||
return;
|
||||
}
|
||||
/* offer formats should be empty if we have no offer */
|
||||
g_assert (cb->offer);
|
||||
|
||||
g_task_set_task_data (task, (gpointer) mime_type, NULL);
|
||||
|
||||
if (!g_unix_open_pipe (pipe_fd, FD_CLOEXEC, &error))
|
||||
{
|
||||
g_task_return_error (task, error);
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_primary_selection_offer_receive (cb->offer, mime_type, pipe_fd[1]);
|
||||
stream = g_unix_input_stream_new (pipe_fd[0], TRUE);
|
||||
close (pipe_fd[1]);
|
||||
g_task_return_pointer (task, stream, g_object_unref);
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
gdk_wayland_primary_read_finish (GdkClipboard *clipboard,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
GInputStream *stream;
|
||||
GTask *task;
|
||||
|
||||
g_return_val_if_fail (g_task_is_valid (result, G_OBJECT (clipboard)), NULL);
|
||||
task = G_TASK (result);
|
||||
g_return_val_if_fail (g_task_get_source_tag (task) == gdk_wayland_primary_read_async, NULL);
|
||||
|
||||
stream = g_task_propagate_pointer (task, error);
|
||||
|
||||
if (stream)
|
||||
{
|
||||
if (out_mime_type)
|
||||
*out_mime_type = g_task_get_task_data (task);
|
||||
g_object_ref (stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (out_mime_type)
|
||||
*out_mime_type = NULL;
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_primary_class_init (GdkWaylandPrimaryClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
GdkClipboardClass *clipboard_class = GDK_CLIPBOARD_CLASS (class);
|
||||
|
||||
object_class->finalize = gdk_wayland_primary_finalize;
|
||||
|
||||
clipboard_class->claim = gdk_wayland_primary_claim;
|
||||
clipboard_class->read_async = gdk_wayland_primary_read_async;
|
||||
clipboard_class->read_finish = gdk_wayland_primary_read_finish;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_primary_init (GdkWaylandPrimary *cb)
|
||||
{
|
||||
}
|
||||
|
||||
GdkClipboard *
|
||||
gdk_wayland_primary_new (GdkWaylandSeat *seat)
|
||||
{
|
||||
GdkWaylandDisplay *wdisplay;
|
||||
GdkWaylandPrimary *cb;
|
||||
|
||||
wdisplay = GDK_WAYLAND_DISPLAY (gdk_seat_get_display (GDK_SEAT (seat)));
|
||||
|
||||
cb = g_object_new (GDK_TYPE_WAYLAND_PRIMARY,
|
||||
"display", wdisplay,
|
||||
NULL);
|
||||
|
||||
cb->primary_data_device =
|
||||
gtk_primary_selection_device_manager_get_device (wdisplay->primary_selection_manager,
|
||||
gdk_wayland_seat_get_wl_seat (GDK_SEAT (seat)));
|
||||
gtk_primary_selection_device_add_listener (cb->primary_data_device,
|
||||
&primary_selection_device_listener, cb);
|
||||
|
||||
return GDK_CLIPBOARD (cb);
|
||||
}
|
41
gdk/wayland/gdkprimary-wayland.h
Normal file
41
gdk/wayland/gdkprimary-wayland.h
Normal file
@ -0,0 +1,41 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2017 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __GDK_PRIMARY_WAYLAND_H__
|
||||
#define __GDK_PRIMARY_WAYLAND_H__
|
||||
|
||||
#include "gdk/gdkclipboard.h"
|
||||
|
||||
#include "gdkseat-wayland.h"
|
||||
#include <wayland-client.h>
|
||||
#include "gtk-primary-selection-client-protocol.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_WAYLAND_PRIMARY (gdk_wayland_primary_get_type ())
|
||||
#define GDK_WAYLAND_PRIMARY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_WAYLAND_PRIMARY, GdkWaylandPrimary))
|
||||
#define GDK_IS_WAYLAND_PRIMARY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_WAYLAND_PRIMARY))
|
||||
|
||||
typedef struct _GdkWaylandPrimary GdkWaylandPrimary;
|
||||
|
||||
GType gdk_wayland_primary_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GdkClipboard * gdk_wayland_primary_new (GdkWaylandSeat *seat);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_PRIMARY_WAYLAND_H__ */
|
@ -184,9 +184,6 @@ struct wl_data_device * gdk_wayland_device_get_data_device (GdkDevice *gdk_devic
|
||||
void gdk_wayland_device_set_selection (GdkDevice *gdk_device,
|
||||
struct wl_data_source *source);
|
||||
|
||||
void gdk_wayland_seat_set_primary (GdkSeat *seat,
|
||||
struct gtk_primary_selection_source *source);
|
||||
|
||||
GdkDragContext * gdk_wayland_device_get_drop_context (GdkDevice *gdk_device);
|
||||
|
||||
void gdk_wayland_device_unset_touch_grab (GdkDevice *device,
|
||||
|
@ -82,7 +82,6 @@ struct _SelectionData
|
||||
};
|
||||
|
||||
enum {
|
||||
ATOM_PRIMARY,
|
||||
ATOM_DND,
|
||||
N_ATOMS
|
||||
};
|
||||
@ -100,9 +99,6 @@ struct _GdkWaylandSelection
|
||||
GArray *source_targets;
|
||||
GdkAtom requested_target;
|
||||
|
||||
struct gtk_primary_selection_source *primary_source;
|
||||
GdkWindow *primary_owner;
|
||||
|
||||
struct wl_data_source *dnd_source; /* Owned by the GdkDragContext */
|
||||
GdkWindow *dnd_owner;
|
||||
};
|
||||
@ -307,7 +303,6 @@ gdk_wayland_selection_new (void)
|
||||
gint i;
|
||||
|
||||
/* init atoms */
|
||||
atoms[ATOM_PRIMARY] = gdk_atom_intern_static_string ("PRIMARY");
|
||||
atoms[ATOM_DND] = gdk_atom_intern_static_string ("GdkWaylandSelection");
|
||||
|
||||
selection = g_new0 (GdkWaylandSelection, 1);
|
||||
@ -348,8 +343,6 @@ gdk_wayland_selection_free (GdkWaylandSelection *selection)
|
||||
if (selection->stored_selection.fd > 0)
|
||||
close (selection->stored_selection.fd);
|
||||
|
||||
if (selection->primary_source)
|
||||
gtk_primary_selection_source_destroy (selection->primary_source);
|
||||
if (selection->dnd_source)
|
||||
wl_data_source_destroy (selection->dnd_source);
|
||||
|
||||
@ -448,41 +441,11 @@ static const struct wl_data_offer_listener data_offer_listener = {
|
||||
data_offer_action
|
||||
};
|
||||
|
||||
static void
|
||||
primary_offer_offer (void *data,
|
||||
struct gtk_primary_selection_offer *gtk_offer,
|
||||
const char *type)
|
||||
{
|
||||
GdkWaylandSelection *selection = data;
|
||||
GdkContentFormatsBuilder *builder;
|
||||
DataOfferData *info;
|
||||
|
||||
info = g_hash_table_lookup (selection->offers, gtk_offer);
|
||||
|
||||
if (!info || gdk_content_formats_contain_mime_type (info->targets, type))
|
||||
return;
|
||||
|
||||
GDK_NOTE (EVENTS,
|
||||
g_message ("primary offer offer, offer %p, type = %s", gtk_offer, type));
|
||||
|
||||
builder = gdk_content_formats_builder_new ();
|
||||
gdk_content_formats_builder_add_formats (builder, info->targets);
|
||||
gdk_content_formats_builder_add_mime_type (builder, type);
|
||||
gdk_content_formats_unref (info->targets);
|
||||
info->targets = gdk_content_formats_builder_free (builder);
|
||||
}
|
||||
|
||||
static const struct gtk_primary_selection_offer_listener primary_offer_listener = {
|
||||
primary_offer_offer,
|
||||
};
|
||||
|
||||
static SelectionData *
|
||||
selection_lookup_offer_by_atom (GdkWaylandSelection *selection,
|
||||
GdkAtom selection_atom)
|
||||
{
|
||||
if (selection_atom == atoms[ATOM_PRIMARY])
|
||||
return &selection->selections[ATOM_PRIMARY];
|
||||
else if (selection_atom == atoms[ATOM_DND])
|
||||
if (selection_atom == atoms[ATOM_DND])
|
||||
return &selection->selections[ATOM_DND];
|
||||
else
|
||||
return NULL;
|
||||
@ -508,26 +471,6 @@ gdk_wayland_selection_ensure_offer (GdkDisplay *display,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_selection_ensure_primary_offer (GdkDisplay *display,
|
||||
struct gtk_primary_selection_offer *gtk_offer)
|
||||
{
|
||||
GdkWaylandSelection *selection = gdk_wayland_display_get_selection (display);
|
||||
DataOfferData *info;
|
||||
|
||||
info = g_hash_table_lookup (selection->offers, gtk_offer);
|
||||
|
||||
if (!info)
|
||||
{
|
||||
info = data_offer_data_new (gtk_offer,
|
||||
(GDestroyNotify) gtk_primary_selection_offer_destroy);
|
||||
g_hash_table_insert (selection->offers, gtk_offer, info);
|
||||
gtk_primary_selection_offer_add_listener (gtk_offer,
|
||||
&primary_offer_listener,
|
||||
selection);
|
||||
}
|
||||
}
|
||||
|
||||
GdkContentFormats *
|
||||
gdk_wayland_selection_steal_offer (GdkDisplay *display,
|
||||
gpointer wl_offer)
|
||||
@ -1006,55 +949,6 @@ static const struct wl_data_source_listener data_source_listener = {
|
||||
data_source_action,
|
||||
};
|
||||
|
||||
static void
|
||||
primary_source_send (void *data,
|
||||
struct gtk_primary_selection_source *source,
|
||||
const char *mime_type,
|
||||
int32_t fd)
|
||||
{
|
||||
GdkWaylandSelection *wayland_selection = data;
|
||||
|
||||
GDK_NOTE (EVENTS,
|
||||
g_message ("primary source send, source = %p, mime_type = %s, fd = %d",
|
||||
source, mime_type, fd));
|
||||
|
||||
if (!mime_type || !wayland_selection->primary_owner)
|
||||
{
|
||||
close (fd);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gdk_wayland_selection_request_target (wayland_selection,
|
||||
wayland_selection->primary_owner,
|
||||
atoms[ATOM_PRIMARY],
|
||||
gdk_atom_intern (mime_type, FALSE),
|
||||
fd))
|
||||
gdk_wayland_selection_check_write (wayland_selection);
|
||||
}
|
||||
|
||||
static void
|
||||
primary_source_cancelled (void *data,
|
||||
struct gtk_primary_selection_source *source)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
GdkAtom atom;
|
||||
|
||||
GDK_NOTE (EVENTS,
|
||||
g_message ("primary source cancelled, source = %p", source));
|
||||
|
||||
display = gdk_display_get_default ();
|
||||
|
||||
atom = atoms[ATOM_PRIMARY];
|
||||
emit_selection_clear (display, atom);
|
||||
gdk_selection_owner_set (NULL, atom, GDK_CURRENT_TIME, TRUE);
|
||||
gdk_wayland_selection_unset_data_source (display, atom);
|
||||
}
|
||||
|
||||
static const struct gtk_primary_selection_source_listener primary_source_listener = {
|
||||
primary_source_send,
|
||||
primary_source_cancelled,
|
||||
};
|
||||
|
||||
struct wl_data_source *
|
||||
gdk_wayland_selection_get_data_source (GdkWindow *owner,
|
||||
GdkAtom selection)
|
||||
@ -1070,18 +964,6 @@ gdk_wayland_selection_get_data_source (GdkWindow *owner,
|
||||
(!owner || owner == wayland_selection->dnd_owner))
|
||||
return wayland_selection->dnd_source;
|
||||
}
|
||||
else if (selection == atoms[ATOM_PRIMARY])
|
||||
{
|
||||
if (wayland_selection->primary_source &&
|
||||
(!owner || owner == wayland_selection->primary_owner))
|
||||
return (gpointer) wayland_selection->primary_source;
|
||||
|
||||
if (wayland_selection->primary_source)
|
||||
{
|
||||
gtk_primary_selection_source_destroy (wayland_selection->primary_source);
|
||||
wayland_selection->primary_source = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
|
||||
@ -1090,28 +972,13 @@ gdk_wayland_selection_get_data_source (GdkWindow *owner,
|
||||
|
||||
display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (owner));
|
||||
|
||||
if (selection == atoms[ATOM_PRIMARY])
|
||||
{
|
||||
if (display_wayland->primary_selection_manager)
|
||||
{
|
||||
source = gtk_primary_selection_device_manager_create_source (display_wayland->primary_selection_manager);
|
||||
gtk_primary_selection_source_add_listener (source,
|
||||
&primary_source_listener,
|
||||
wayland_selection);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
source = wl_data_device_manager_create_data_source (display_wayland->data_device_manager);
|
||||
wl_data_source_add_listener (source,
|
||||
&data_source_listener,
|
||||
wayland_selection);
|
||||
}
|
||||
source = wl_data_device_manager_create_data_source (display_wayland->data_device_manager);
|
||||
wl_data_source_add_listener (source,
|
||||
&data_source_listener,
|
||||
wayland_selection);
|
||||
|
||||
if (selection == atoms[ATOM_DND])
|
||||
wayland_selection->dnd_source = source;
|
||||
else if (selection == atoms[ATOM_PRIMARY])
|
||||
wayland_selection->primary_source = source;
|
||||
|
||||
return source;
|
||||
}
|
||||
@ -1122,19 +989,7 @@ gdk_wayland_selection_unset_data_source (GdkDisplay *display,
|
||||
{
|
||||
GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display);
|
||||
|
||||
if (selection == atoms[ATOM_PRIMARY])
|
||||
{
|
||||
GdkSeat *seat = gdk_display_get_default_seat (display);
|
||||
|
||||
gdk_wayland_seat_set_primary (seat, NULL);
|
||||
|
||||
if (wayland_selection->primary_source)
|
||||
{
|
||||
gtk_primary_selection_source_destroy (wayland_selection->primary_source);
|
||||
wayland_selection->primary_source = NULL;
|
||||
}
|
||||
}
|
||||
else if (selection == atoms[ATOM_DND])
|
||||
if (selection == atoms[ATOM_DND])
|
||||
{
|
||||
wayland_selection->dnd_source = NULL;
|
||||
}
|
||||
@ -1146,9 +1001,7 @@ _gdk_wayland_display_get_selection_owner (GdkDisplay *display,
|
||||
{
|
||||
GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display);
|
||||
|
||||
if (selection == atoms[ATOM_PRIMARY])
|
||||
return wayland_selection->primary_owner;
|
||||
else if (selection == atoms[ATOM_DND])
|
||||
if (selection == atoms[ATOM_DND])
|
||||
return wayland_selection->dnd_owner;
|
||||
|
||||
return NULL;
|
||||
@ -1163,12 +1016,7 @@ _gdk_wayland_display_set_selection_owner (GdkDisplay *display,
|
||||
{
|
||||
GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display);
|
||||
|
||||
if (selection == atoms[ATOM_PRIMARY])
|
||||
{
|
||||
wayland_selection->primary_owner = owner;
|
||||
return TRUE;
|
||||
}
|
||||
else if (selection == atoms[ATOM_DND])
|
||||
if (selection == atoms[ATOM_DND])
|
||||
{
|
||||
wayland_selection->dnd_owner = owner;
|
||||
return TRUE;
|
||||
@ -1311,10 +1159,9 @@ _gdk_wayland_display_convert_selection (GdkDisplay *display,
|
||||
return;
|
||||
}
|
||||
|
||||
if (selection != atoms[ATOM_PRIMARY])
|
||||
wl_data_offer_accept (offer,
|
||||
_gdk_wayland_display_get_serial (GDK_WAYLAND_DISPLAY (display)),
|
||||
mimetype);
|
||||
wl_data_offer_accept (offer,
|
||||
_gdk_wayland_display_get_serial (GDK_WAYLAND_DISPLAY (display)),
|
||||
mimetype);
|
||||
}
|
||||
|
||||
buffer_data = g_hash_table_lookup (selection_data->buffers, target);
|
||||
@ -1336,10 +1183,7 @@ _gdk_wayland_display_convert_selection (GdkDisplay *display,
|
||||
{
|
||||
g_unix_open_pipe (pipe_fd, FD_CLOEXEC, NULL);
|
||||
|
||||
if (selection == atoms[ATOM_PRIMARY])
|
||||
gtk_primary_selection_offer_receive (offer, mimetype, pipe_fd[1]);
|
||||
else
|
||||
wl_data_offer_receive (offer, mimetype, pipe_fd[1]);
|
||||
wl_data_offer_receive (offer, mimetype, pipe_fd[1]);
|
||||
|
||||
stream = g_unix_input_stream_new (pipe_fd[0], TRUE);
|
||||
close (pipe_fd[1]);
|
||||
@ -1501,14 +1345,6 @@ gdk_wayland_display_add_selection_targets (GdkDisplay *display,
|
||||
wl_data_source_offer (data_source, mimetype);
|
||||
g_free (mimetype);
|
||||
}
|
||||
|
||||
if (selection == atoms[ATOM_PRIMARY])
|
||||
{
|
||||
GdkSeat *seat;
|
||||
|
||||
seat = gdk_display_get_default_seat (display);
|
||||
gdk_wayland_seat_set_primary (seat, data_source);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -9,6 +9,7 @@ gdk_wayland_sources = files([
|
||||
'gdkglcontext-wayland.c',
|
||||
'gdkkeys-wayland.c',
|
||||
'gdkmonitor-wayland.c',
|
||||
'gdkprimary-wayland.c',
|
||||
'gdkselection-wayland.c',
|
||||
'gdkvulkancontext-wayland.c',
|
||||
'gdkwindow-wayland.c',
|
||||
|
Loading…
Reference in New Issue
Block a user