2014-10-10 12:55:00 -04:00
|
|
|
/*
|
|
|
|
* Copyright © 2012 Intel Corporation
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, distribute, and sell this software and
|
|
|
|
* its documentation for any purpose is hereby granted without fee, provided
|
|
|
|
* that the above copyright notice appear in all copies and that both that
|
|
|
|
* copyright notice and this permission notice appear in supporting
|
|
|
|
* documentation, and that the name of the copyright holders not be used in
|
|
|
|
* advertising or publicity pertaining to distribution of the software
|
|
|
|
* without specific, written prior permission. The copyright holders make
|
|
|
|
* no representations about the suitability of this software for any
|
|
|
|
* purpose. It is provided "as is" without express or implied warranty.
|
|
|
|
*
|
|
|
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
|
|
|
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
|
|
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
|
|
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
|
|
|
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
|
|
|
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
|
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* The file is loosely based on xwayland/selection.c from Weston */
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <glib-unix.h>
|
|
|
|
#include <gio/gunixoutputstream.h>
|
|
|
|
#include <gio/gunixinputstream.h>
|
|
|
|
#include <gdk/gdkx.h>
|
|
|
|
#include <X11/Xatom.h>
|
2015-08-23 06:38:27 -04:00
|
|
|
#include <X11/extensions/Xfixes.h>
|
2016-09-06 06:49:03 -04:00
|
|
|
|
2014-10-10 12:55:00 -04:00
|
|
|
#include <meta/errors.h>
|
2016-09-06 06:49:03 -04:00
|
|
|
#include "meta-xwayland.h"
|
2014-10-10 12:55:00 -04:00
|
|
|
#include "meta-xwayland-private.h"
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
#include "meta-xwayland-selection-private.h"
|
2014-10-10 12:55:00 -04:00
|
|
|
#include "meta-wayland-data-device.h"
|
|
|
|
|
|
|
|
#define INCR_CHUNK_SIZE (128 * 1024)
|
2015-04-29 11:44:05 -04:00
|
|
|
#define XDND_VERSION 5
|
2014-10-10 12:55:00 -04:00
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
MetaXWaylandSelection *selection_data;
|
|
|
|
GInputStream *stream;
|
|
|
|
GCancellable *cancellable;
|
|
|
|
MetaWindow *window;
|
|
|
|
XSelectionRequestEvent request_event;
|
|
|
|
guchar buffer[INCR_CHUNK_SIZE];
|
|
|
|
gsize buffer_len;
|
|
|
|
guint incr : 1;
|
|
|
|
} WaylandSelectionData;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
MetaXWaylandSelection *selection_data;
|
|
|
|
GOutputStream *stream;
|
|
|
|
GCancellable *cancellable;
|
|
|
|
gchar *mime_type;
|
|
|
|
guint incr : 1;
|
|
|
|
} X11SelectionData;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
Atom selection_atom;
|
|
|
|
Window window;
|
|
|
|
Window owner;
|
|
|
|
Time timestamp;
|
2015-05-12 13:35:28 -04:00
|
|
|
MetaWaylandDataSource *source; /* owned by MetaWaylandDataDevice */
|
2014-10-10 12:55:00 -04:00
|
|
|
WaylandSelectionData *wayland_selection;
|
|
|
|
X11SelectionData *x11_selection;
|
|
|
|
|
|
|
|
struct wl_listener ownership_listener;
|
|
|
|
} MetaSelectionBridge;
|
|
|
|
|
2015-04-29 11:44:05 -04:00
|
|
|
typedef struct {
|
|
|
|
MetaSelectionBridge selection;
|
2015-05-12 13:35:28 -04:00
|
|
|
MetaWaylandSurface *focus_surface;
|
|
|
|
Window dnd_window; /* Mutter-internal window, acts as peer on wayland drop sites */
|
|
|
|
Window dnd_dest; /* X11 drag dest window */
|
|
|
|
guint32 last_motion_time;
|
2015-04-29 11:44:05 -04:00
|
|
|
} MetaDndBridge;
|
|
|
|
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
struct _MetaWaylandDataSourceXWayland
|
|
|
|
{
|
|
|
|
MetaWaylandDataSource parent;
|
|
|
|
|
|
|
|
MetaSelectionBridge *selection;
|
2015-09-28 08:27:10 -04:00
|
|
|
guint has_utf8_string_atom : 1;
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
};
|
|
|
|
|
2014-10-10 12:55:00 -04:00
|
|
|
struct _MetaXWaylandSelection {
|
|
|
|
MetaSelectionBridge clipboard;
|
2016-02-03 12:39:58 -05:00
|
|
|
MetaSelectionBridge primary;
|
2015-04-29 11:44:05 -04:00
|
|
|
MetaDndBridge dnd;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
|
|
|
ATOM_DND_SELECTION,
|
|
|
|
ATOM_DND_AWARE,
|
|
|
|
ATOM_DND_STATUS,
|
|
|
|
ATOM_DND_POSITION,
|
|
|
|
ATOM_DND_ENTER,
|
|
|
|
ATOM_DND_LEAVE,
|
|
|
|
ATOM_DND_DROP,
|
|
|
|
ATOM_DND_FINISHED,
|
|
|
|
ATOM_DND_PROXY,
|
|
|
|
ATOM_DND_TYPE_LIST,
|
|
|
|
ATOM_DND_ACTION_MOVE,
|
|
|
|
ATOM_DND_ACTION_COPY,
|
|
|
|
ATOM_DND_ACTION_ASK,
|
2015-04-07 10:05:46 -04:00
|
|
|
ATOM_DND_ACTION_PRIVATE,
|
2015-04-29 11:44:05 -04:00
|
|
|
N_DND_ATOMS
|
2014-10-10 12:55:00 -04:00
|
|
|
};
|
|
|
|
|
2015-04-29 11:44:05 -04:00
|
|
|
/* Matches order in enum above */
|
|
|
|
const gchar *atom_names[] = {
|
|
|
|
"XdndSelection",
|
|
|
|
"XdndAware",
|
|
|
|
"XdndStatus",
|
|
|
|
"XdndPosition",
|
|
|
|
"XdndEnter",
|
|
|
|
"XdndLeave",
|
|
|
|
"XdndDrop",
|
|
|
|
"XdndFinished",
|
|
|
|
"XdndProxy",
|
|
|
|
"XdndTypeList",
|
|
|
|
"XdndActionMove",
|
|
|
|
"XdndActionCopy",
|
|
|
|
"XdndActionAsk",
|
2015-04-07 10:05:46 -04:00
|
|
|
"XdndActionPrivate",
|
2015-04-29 11:44:05 -04:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
Atom xdnd_atoms[N_DND_ATOMS];
|
|
|
|
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
G_DEFINE_TYPE (MetaWaylandDataSourceXWayland, meta_wayland_data_source_xwayland,
|
|
|
|
META_TYPE_WAYLAND_DATA_SOURCE);
|
|
|
|
|
2015-04-29 11:44:05 -04:00
|
|
|
/* XDND helpers */
|
2015-04-07 10:05:46 -04:00
|
|
|
static Atom
|
|
|
|
action_to_atom (uint32_t action)
|
|
|
|
{
|
|
|
|
if (action & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
|
|
|
|
return xdnd_atoms[ATOM_DND_ACTION_COPY];
|
|
|
|
else if (action & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
|
|
|
|
return xdnd_atoms[ATOM_DND_ACTION_MOVE];
|
|
|
|
else if (action & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
|
|
|
|
return xdnd_atoms[ATOM_DND_ACTION_ASK];
|
|
|
|
else
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
|
|
|
static enum wl_data_device_manager_dnd_action
|
|
|
|
atom_to_action (Atom atom)
|
|
|
|
{
|
|
|
|
if (atom == xdnd_atoms[ATOM_DND_ACTION_COPY] ||
|
|
|
|
atom == xdnd_atoms[ATOM_DND_ACTION_PRIVATE])
|
|
|
|
return WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
|
|
|
|
else if (atom == xdnd_atoms[ATOM_DND_ACTION_MOVE])
|
|
|
|
return WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
|
|
|
|
else if (atom == xdnd_atoms[ATOM_DND_ACTION_ASK])
|
|
|
|
return WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
|
|
|
|
else
|
|
|
|
return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
|
|
|
|
}
|
|
|
|
|
2015-04-29 11:44:05 -04:00
|
|
|
static void
|
|
|
|
xdnd_send_enter (MetaXWaylandSelection *selection_data,
|
|
|
|
Window dest)
|
|
|
|
{
|
|
|
|
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
|
|
|
MetaSelectionBridge *selection = &selection_data->dnd.selection;
|
|
|
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
|
|
|
MetaWaylandDataSource *data_source;
|
|
|
|
XEvent xev = { 0 };
|
|
|
|
gchar **p;
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
struct wl_array *source_mime_types;
|
2015-04-29 11:44:05 -04:00
|
|
|
|
|
|
|
data_source = compositor->seat->data_device.dnd_data_source;
|
|
|
|
xev.xclient.type = ClientMessage;
|
|
|
|
xev.xclient.message_type = xdnd_atoms[ATOM_DND_ENTER];
|
|
|
|
xev.xclient.format = 32;
|
|
|
|
xev.xclient.window = dest;
|
|
|
|
|
|
|
|
xev.xclient.data.l[0] = selection->window;
|
|
|
|
xev.xclient.data.l[1] = XDND_VERSION << 24; /* version */
|
|
|
|
xev.xclient.data.l[2] = xev.xclient.data.l[3] = xev.xclient.data.l[4] = 0;
|
|
|
|
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
source_mime_types = meta_wayland_data_source_get_mime_types (data_source);
|
|
|
|
if (source_mime_types->size <= 3)
|
2015-04-29 11:44:05 -04:00
|
|
|
{
|
|
|
|
/* The mimetype atoms fit in this same message */
|
|
|
|
gint i = 2;
|
|
|
|
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
wl_array_for_each (p, source_mime_types)
|
2015-04-29 11:44:05 -04:00
|
|
|
{
|
|
|
|
xev.xclient.data.l[i++] = gdk_x11_get_xatom_by_name (*p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* We have more than 3 mimetypes, we must set up
|
|
|
|
* the mimetype list as a XdndTypeList property.
|
|
|
|
*/
|
|
|
|
Atom *atomlist;
|
|
|
|
gint i = 0;
|
|
|
|
|
|
|
|
xev.xclient.data.l[1] |= 1;
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
atomlist = g_new0 (Atom, source_mime_types->size);
|
2015-04-29 11:44:05 -04:00
|
|
|
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
wl_array_for_each (p, source_mime_types)
|
2015-04-29 11:44:05 -04:00
|
|
|
{
|
|
|
|
atomlist[i++] = gdk_x11_get_xatom_by_name (*p);
|
|
|
|
}
|
|
|
|
|
|
|
|
XChangeProperty (xdisplay, selection->window,
|
|
|
|
xdnd_atoms[ATOM_DND_TYPE_LIST],
|
|
|
|
XA_ATOM, 32, PropModeReplace,
|
|
|
|
(guchar *) atomlist, i);
|
|
|
|
}
|
|
|
|
|
|
|
|
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdnd_send_leave (MetaXWaylandSelection *selection_data,
|
|
|
|
Window dest)
|
|
|
|
{
|
|
|
|
MetaSelectionBridge *selection = &selection_data->dnd.selection;
|
|
|
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
|
|
|
XEvent xev = { 0 };
|
|
|
|
|
|
|
|
xev.xclient.type = ClientMessage;
|
|
|
|
xev.xclient.message_type = xdnd_atoms[ATOM_DND_LEAVE];
|
|
|
|
xev.xclient.format = 32;
|
|
|
|
xev.xclient.window = dest;
|
|
|
|
xev.xclient.data.l[0] = selection->window;
|
|
|
|
|
|
|
|
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdnd_send_position (MetaXWaylandSelection *selection_data,
|
|
|
|
Window dest,
|
|
|
|
uint32_t time,
|
|
|
|
int x,
|
|
|
|
int y)
|
|
|
|
{
|
2015-04-07 10:05:46 -04:00
|
|
|
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
2015-04-29 11:44:05 -04:00
|
|
|
MetaSelectionBridge *selection = &selection_data->dnd.selection;
|
2015-04-07 10:05:46 -04:00
|
|
|
MetaWaylandDataSource *source = compositor->seat->data_device.dnd_data_source;
|
2015-04-29 11:44:05 -04:00
|
|
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
2015-04-07 10:05:46 -04:00
|
|
|
uint32_t action = 0, user_action, actions;
|
2015-04-29 11:44:05 -04:00
|
|
|
XEvent xev = { 0 };
|
|
|
|
|
2015-04-07 10:05:46 -04:00
|
|
|
user_action = meta_wayland_data_source_get_user_action (source);
|
|
|
|
actions = meta_wayland_data_source_get_actions (source);
|
|
|
|
|
|
|
|
if (user_action & actions)
|
|
|
|
action = user_action;
|
|
|
|
if (!action)
|
|
|
|
action = actions;
|
|
|
|
|
2015-04-29 11:44:05 -04:00
|
|
|
xev.xclient.type = ClientMessage;
|
|
|
|
xev.xclient.message_type = xdnd_atoms[ATOM_DND_POSITION];
|
|
|
|
xev.xclient.format = 32;
|
|
|
|
xev.xclient.window = dest;
|
|
|
|
|
|
|
|
xev.xclient.data.l[0] = selection->window;
|
|
|
|
xev.xclient.data.l[1] = 0;
|
|
|
|
xev.xclient.data.l[2] = (x << 16) | y;
|
|
|
|
xev.xclient.data.l[3] = time;
|
2015-04-07 10:05:46 -04:00
|
|
|
xev.xclient.data.l[4] = action_to_atom (action);
|
2015-04-29 11:44:05 -04:00
|
|
|
|
|
|
|
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdnd_send_drop (MetaXWaylandSelection *selection_data,
|
|
|
|
Window dest,
|
|
|
|
uint32_t time)
|
|
|
|
{
|
|
|
|
MetaSelectionBridge *selection = &selection_data->dnd.selection;
|
|
|
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
|
|
|
XEvent xev = { 0 };
|
|
|
|
|
|
|
|
xev.xclient.type = ClientMessage;
|
|
|
|
xev.xclient.message_type = xdnd_atoms[ATOM_DND_DROP];
|
|
|
|
xev.xclient.format = 32;
|
|
|
|
xev.xclient.window = dest;
|
|
|
|
|
|
|
|
xev.xclient.data.l[0] = selection->window;
|
|
|
|
xev.xclient.data.l[2] = time;
|
|
|
|
|
|
|
|
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2015-05-12 13:35:28 -04:00
|
|
|
xdnd_send_finished (MetaXWaylandSelection *selection_data,
|
|
|
|
Window dest,
|
|
|
|
gboolean accepted)
|
|
|
|
{
|
|
|
|
MetaDndBridge *selection = &selection_data->dnd;
|
|
|
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
2015-04-07 10:05:46 -04:00
|
|
|
MetaWaylandDataSource *source = selection_data->dnd.selection.source;
|
|
|
|
uint32_t action = 0;
|
2015-05-12 13:35:28 -04:00
|
|
|
XEvent xev = { 0 };
|
|
|
|
|
|
|
|
xev.xclient.type = ClientMessage;
|
|
|
|
xev.xclient.message_type = xdnd_atoms[ATOM_DND_FINISHED];
|
|
|
|
xev.xclient.format = 32;
|
|
|
|
xev.xclient.window = dest;
|
|
|
|
|
|
|
|
xev.xclient.data.l[0] = selection->dnd_window;
|
|
|
|
|
|
|
|
if (accepted)
|
|
|
|
{
|
2015-04-07 10:05:46 -04:00
|
|
|
action = meta_wayland_data_source_get_current_action (source);
|
2015-05-12 13:35:28 -04:00
|
|
|
xev.xclient.data.l[1] = 1; /* Drop successful */
|
2015-04-07 10:05:46 -04:00
|
|
|
xev.xclient.data.l[2] = action_to_atom (action);
|
2015-05-12 13:35:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdnd_send_status (MetaXWaylandSelection *selection_data,
|
|
|
|
Window dest,
|
2015-04-07 10:05:46 -04:00
|
|
|
uint32_t action)
|
2015-04-29 11:44:05 -04:00
|
|
|
{
|
2015-05-12 13:35:28 -04:00
|
|
|
MetaDndBridge *selection = &selection_data->dnd;
|
|
|
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
|
|
|
XEvent xev = { 0 };
|
|
|
|
|
|
|
|
xev.xclient.type = ClientMessage;
|
|
|
|
xev.xclient.message_type = xdnd_atoms[ATOM_DND_STATUS];
|
|
|
|
xev.xclient.format = 32;
|
|
|
|
xev.xclient.window = dest;
|
|
|
|
|
|
|
|
xev.xclient.data.l[0] = selection->dnd_window;
|
|
|
|
xev.xclient.data.l[1] = 1 << 1; /* Bit 2: dest wants XdndPosition messages */
|
2015-04-07 10:05:46 -04:00
|
|
|
xev.xclient.data.l[4] = action_to_atom (action);
|
2015-05-12 13:35:28 -04:00
|
|
|
|
2015-04-07 10:05:46 -04:00
|
|
|
if (xev.xclient.data.l[4])
|
|
|
|
xev.xclient.data.l[1] |= 1 << 0; /* Bit 1: dest accepts the drop */
|
2015-05-12 13:35:28 -04:00
|
|
|
|
|
|
|
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_xwayland_init_dnd (MetaXWaylandManager *manager)
|
|
|
|
{
|
|
|
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
|
|
|
MetaDndBridge *dnd = &manager->selection_data->dnd;
|
|
|
|
XSetWindowAttributes attributes;
|
|
|
|
guint32 i, version = XDND_VERSION;
|
2015-04-29 11:44:05 -04:00
|
|
|
|
|
|
|
for (i = 0; i < N_DND_ATOMS; i++)
|
|
|
|
xdnd_atoms[i] = gdk_x11_get_xatom_by_name (atom_names[i]);
|
2015-05-12 13:35:28 -04:00
|
|
|
|
|
|
|
attributes.event_mask = PropertyChangeMask | SubstructureNotifyMask;
|
|
|
|
attributes.override_redirect = True;
|
|
|
|
|
|
|
|
dnd->dnd_window = XCreateWindow (xdisplay,
|
|
|
|
gdk_x11_window_get_xid (gdk_get_default_root_window ()),
|
|
|
|
-1, -1, 1, 1,
|
|
|
|
0, /* border width */
|
|
|
|
0, /* depth */
|
|
|
|
InputOnly, /* class */
|
|
|
|
CopyFromParent, /* visual */
|
|
|
|
CWEventMask | CWOverrideRedirect,
|
|
|
|
&attributes);
|
|
|
|
XChangeProperty (xdisplay, dnd->dnd_window,
|
|
|
|
xdnd_atoms[ATOM_DND_AWARE],
|
|
|
|
XA_ATOM, 32, PropModeReplace,
|
|
|
|
(guchar*) &version, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_xwayland_shutdown_dnd (MetaXWaylandManager *manager)
|
|
|
|
{
|
|
|
|
MetaDndBridge *dnd = &manager->selection_data->dnd;
|
|
|
|
|
|
|
|
XDestroyWindow (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
|
|
|
|
dnd->dnd_window);
|
|
|
|
dnd->dnd_window = None;
|
2015-04-29 11:44:05 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* X11/Wayland data bridges */
|
|
|
|
|
2014-10-10 12:55:00 -04:00
|
|
|
static MetaSelectionBridge *
|
|
|
|
atom_to_selection_bridge (MetaWaylandCompositor *compositor,
|
|
|
|
Atom selection_atom)
|
|
|
|
{
|
|
|
|
MetaXWaylandSelection *selection_data = compositor->xwayland_manager.selection_data;
|
|
|
|
|
|
|
|
if (selection_atom == selection_data->clipboard.selection_atom)
|
|
|
|
return &selection_data->clipboard;
|
2016-02-03 12:39:58 -05:00
|
|
|
else if (selection_atom == selection_data->primary.selection_atom)
|
|
|
|
return &selection_data->primary;
|
2015-04-29 11:44:05 -04:00
|
|
|
else if (selection_atom == selection_data->dnd.selection.selection_atom)
|
|
|
|
return &selection_data->dnd.selection;
|
2014-10-10 12:55:00 -04:00
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static X11SelectionData *
|
|
|
|
x11_selection_data_new (MetaXWaylandSelection *selection_data,
|
|
|
|
int fd,
|
|
|
|
const char *mime_type)
|
|
|
|
{
|
|
|
|
X11SelectionData *data;
|
|
|
|
|
|
|
|
data = g_slice_new0 (X11SelectionData);
|
|
|
|
data->selection_data = selection_data;
|
|
|
|
data->stream = g_unix_output_stream_new (fd, TRUE);
|
|
|
|
data->cancellable = g_cancellable_new ();
|
|
|
|
data->mime_type = g_strdup (mime_type);
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
x11_selection_data_free (X11SelectionData *data)
|
|
|
|
{
|
|
|
|
g_cancellable_cancel (data->cancellable);
|
|
|
|
g_object_unref (data->cancellable);
|
|
|
|
g_object_unref (data->stream);
|
|
|
|
g_free (data->mime_type);
|
|
|
|
g_slice_free (X11SelectionData, data);
|
|
|
|
}
|
|
|
|
|
2015-04-07 10:05:46 -04:00
|
|
|
static void
|
|
|
|
x11_selection_data_send_finished (MetaSelectionBridge *selection,
|
|
|
|
gboolean success)
|
|
|
|
{
|
|
|
|
uint32_t action = meta_wayland_data_source_get_current_action (selection->source);
|
|
|
|
|
|
|
|
if (!selection->x11_selection)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (success && action == WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
|
|
|
|
{
|
|
|
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
|
|
|
|
|
|
|
/* Request data deletion on the drag source */
|
|
|
|
XConvertSelection (xdisplay,
|
|
|
|
selection->selection_atom,
|
|
|
|
gdk_x11_get_xatom_by_name ("DELETE"),
|
|
|
|
gdk_x11_get_xatom_by_name ("_META_SELECTION"),
|
|
|
|
selection->window,
|
|
|
|
CurrentTime);
|
|
|
|
}
|
|
|
|
|
|
|
|
xdnd_send_finished (selection->x11_selection->selection_data,
|
|
|
|
selection->owner, success);
|
|
|
|
}
|
|
|
|
|
2015-05-12 13:35:28 -04:00
|
|
|
static void
|
|
|
|
x11_selection_data_finish (MetaSelectionBridge *selection,
|
|
|
|
gboolean success)
|
|
|
|
{
|
|
|
|
if (!selection->x11_selection)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (selection == &selection->x11_selection->selection_data->dnd.selection)
|
2015-04-07 10:05:46 -04:00
|
|
|
x11_selection_data_send_finished (selection, success);
|
2015-05-12 13:35:28 -04:00
|
|
|
|
|
|
|
g_clear_pointer (&selection->x11_selection,
|
|
|
|
(GDestroyNotify) x11_selection_data_free);
|
|
|
|
}
|
|
|
|
|
2015-04-07 10:05:46 -04:00
|
|
|
static void
|
|
|
|
x11_selection_data_close (X11SelectionData *data)
|
|
|
|
{
|
|
|
|
g_output_stream_close (data->stream, data->cancellable, NULL);
|
|
|
|
}
|
|
|
|
|
2014-10-10 12:55:00 -04:00
|
|
|
static void
|
|
|
|
x11_data_write_cb (GObject *object,
|
|
|
|
GAsyncResult *res,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
MetaSelectionBridge *selection = user_data;
|
|
|
|
X11SelectionData *data = selection->x11_selection;
|
|
|
|
GError *error = NULL;
|
2015-09-11 09:35:07 -04:00
|
|
|
gboolean success = TRUE;
|
2014-10-10 12:55:00 -04:00
|
|
|
|
|
|
|
g_output_stream_write_finish (G_OUTPUT_STREAM (object), res, &error);
|
|
|
|
|
2015-09-11 09:35:07 -04:00
|
|
|
if (error)
|
|
|
|
{
|
|
|
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
|
|
{
|
|
|
|
g_error_free (error);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_warning ("Error writing from X11 selection: %s\n", error->message);
|
|
|
|
g_error_free (error);
|
|
|
|
success = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (success && data->incr)
|
2014-10-10 12:55:00 -04:00
|
|
|
{
|
|
|
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
|
|
|
XDeleteProperty (xdisplay, selection->window,
|
|
|
|
gdk_x11_get_xatom_by_name ("_META_SELECTION"));
|
|
|
|
}
|
2015-09-11 09:35:07 -04:00
|
|
|
else
|
2014-10-10 12:55:00 -04:00
|
|
|
{
|
2015-04-07 10:05:46 -04:00
|
|
|
x11_selection_data_close (selection->x11_selection);
|
2015-09-11 09:35:07 -04:00
|
|
|
x11_selection_data_finish (selection, success);
|
2014-10-10 12:55:00 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
x11_selection_data_write (MetaSelectionBridge *selection,
|
|
|
|
guchar *buffer,
|
|
|
|
gulong len)
|
|
|
|
{
|
|
|
|
X11SelectionData *data = selection->x11_selection;
|
|
|
|
|
|
|
|
g_output_stream_write_async (data->stream, buffer, len,
|
|
|
|
G_PRIORITY_DEFAULT, data->cancellable,
|
|
|
|
x11_data_write_cb, selection);
|
|
|
|
}
|
|
|
|
|
|
|
|
static MetaWaylandDataSource *
|
|
|
|
data_device_get_active_source_for_atom (MetaWaylandDataDevice *data_device,
|
|
|
|
Atom selection_atom)
|
|
|
|
{
|
|
|
|
if (selection_atom == gdk_x11_get_xatom_by_name ("CLIPBOARD"))
|
|
|
|
return data_device->selection_data_source;
|
2016-02-03 12:39:58 -05:00
|
|
|
else if (selection_atom == gdk_x11_get_xatom_by_name ("PRIMARY"))
|
|
|
|
return data_device->primary_data_source;
|
2015-04-29 11:44:05 -04:00
|
|
|
else if (selection_atom == xdnd_atoms[ATOM_DND_SELECTION])
|
|
|
|
return data_device->dnd_data_source;
|
2014-10-10 12:55:00 -04:00
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static WaylandSelectionData *
|
|
|
|
wayland_selection_data_new (XSelectionRequestEvent *request_event,
|
|
|
|
MetaWaylandCompositor *compositor)
|
|
|
|
{
|
|
|
|
MetaWaylandDataDevice *data_device;
|
|
|
|
MetaWaylandDataSource *wayland_source;
|
|
|
|
MetaSelectionBridge *selection;
|
|
|
|
WaylandSelectionData *data;
|
|
|
|
const gchar *mime_type;
|
|
|
|
GError *error = NULL;
|
|
|
|
int p[2];
|
|
|
|
|
|
|
|
selection = atom_to_selection_bridge (compositor, request_event->selection);
|
|
|
|
|
|
|
|
if (!selection)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!g_unix_open_pipe (p, FD_CLOEXEC, &error))
|
|
|
|
{
|
|
|
|
g_critical ("Failed to open pipe: %s\n", error->message);
|
|
|
|
g_error_free (error);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
data_device = &compositor->seat->data_device;
|
|
|
|
mime_type = gdk_x11_get_xatom_name (request_event->target);
|
|
|
|
|
|
|
|
if (!g_unix_set_fd_nonblocking (p[0], TRUE, &error) ||
|
|
|
|
!g_unix_set_fd_nonblocking (p[1], TRUE, &error))
|
|
|
|
{
|
|
|
|
if (error)
|
|
|
|
{
|
|
|
|
g_critical ("Failed to make fds non-blocking: %s\n", error->message);
|
|
|
|
g_error_free (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
close (p[0]);
|
|
|
|
close (p[1]);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
wayland_source = data_device_get_active_source_for_atom (data_device,
|
|
|
|
selection->selection_atom),
|
|
|
|
meta_wayland_data_source_send (wayland_source, mime_type, p[1]);
|
|
|
|
|
|
|
|
data = g_slice_new0 (WaylandSelectionData);
|
|
|
|
data->request_event = *request_event;
|
|
|
|
data->cancellable = g_cancellable_new ();
|
|
|
|
data->stream = g_unix_input_stream_new (p[0], TRUE);
|
|
|
|
|
|
|
|
data->window = meta_display_lookup_x_window (meta_get_display (),
|
|
|
|
data->request_event.requestor);
|
|
|
|
|
|
|
|
if (!data->window)
|
|
|
|
{
|
|
|
|
/* Not a managed window, set the PropertyChangeMask
|
|
|
|
* for INCR deletion notifications.
|
|
|
|
*/
|
|
|
|
XSelectInput (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
|
|
|
|
data->request_event.requestor, PropertyChangeMask);
|
|
|
|
}
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
reply_selection_request (XSelectionRequestEvent *request_event,
|
|
|
|
gboolean accepted)
|
|
|
|
{
|
|
|
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
|
|
|
XSelectionEvent event;
|
|
|
|
|
|
|
|
memset(&event, 0, sizeof (XSelectionEvent));
|
|
|
|
event.type = SelectionNotify;
|
|
|
|
event.time = request_event->time;
|
|
|
|
event.requestor = request_event->requestor;
|
|
|
|
event.selection = request_event->selection;
|
|
|
|
event.target = request_event->target;
|
|
|
|
event.property = accepted ? request_event->property : None;
|
|
|
|
|
|
|
|
XSendEvent (xdisplay, request_event->requestor,
|
|
|
|
False, NoEventMask, (XEvent *) &event);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
wayland_selection_data_free (WaylandSelectionData *data)
|
|
|
|
{
|
|
|
|
if (!data->window)
|
|
|
|
{
|
|
|
|
MetaDisplay *display = meta_get_display ();
|
|
|
|
|
|
|
|
meta_error_trap_push (display);
|
|
|
|
XSelectInput (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
|
|
|
|
data->request_event.requestor, NoEventMask);
|
|
|
|
meta_error_trap_pop (display);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_cancellable_cancel (data->cancellable);
|
|
|
|
g_object_unref (data->cancellable);
|
|
|
|
g_object_unref (data->stream);
|
|
|
|
g_slice_free (WaylandSelectionData, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
wayland_selection_update_x11_property (WaylandSelectionData *data)
|
|
|
|
{
|
|
|
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
|
|
|
|
|
|
|
XChangeProperty (xdisplay,
|
|
|
|
data->request_event.requestor,
|
|
|
|
data->request_event.property,
|
|
|
|
data->request_event.target,
|
|
|
|
8, PropModeReplace,
|
|
|
|
data->buffer, data->buffer_len);
|
|
|
|
data->buffer_len = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
wayland_data_read_cb (GObject *object,
|
|
|
|
GAsyncResult *res,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
MetaSelectionBridge *selection = user_data;
|
|
|
|
WaylandSelectionData *data = selection->wayland_selection;
|
|
|
|
GError *error = NULL;
|
|
|
|
gsize bytes_read;
|
|
|
|
|
|
|
|
bytes_read = g_input_stream_read_finish (G_INPUT_STREAM (object),
|
|
|
|
res, &error);
|
|
|
|
if (error)
|
|
|
|
{
|
2016-03-02 10:38:20 -05:00
|
|
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
|
|
{
|
|
|
|
g_error_free (error);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-10 12:55:00 -04:00
|
|
|
g_warning ("Error transfering wayland clipboard to X11: %s\n",
|
|
|
|
error->message);
|
|
|
|
g_error_free (error);
|
|
|
|
|
2016-03-02 10:38:20 -05:00
|
|
|
if (data && data->stream == G_INPUT_STREAM (object))
|
2014-10-10 12:55:00 -04:00
|
|
|
{
|
|
|
|
reply_selection_request (&data->request_event, FALSE);
|
|
|
|
g_clear_pointer (&selection->wayland_selection,
|
|
|
|
(GDestroyNotify) wayland_selection_data_free);
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
data->buffer_len = bytes_read;
|
|
|
|
|
|
|
|
if (bytes_read == INCR_CHUNK_SIZE)
|
|
|
|
{
|
|
|
|
if (!data->incr)
|
|
|
|
{
|
|
|
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
|
|
|
guint32 incr_chunk_size = INCR_CHUNK_SIZE;
|
|
|
|
|
|
|
|
/* Not yet in incr */
|
|
|
|
data->incr = TRUE;
|
|
|
|
XChangeProperty (xdisplay,
|
|
|
|
data->request_event.requestor,
|
|
|
|
data->request_event.property,
|
|
|
|
gdk_x11_get_xatom_by_name ("INCR"),
|
|
|
|
32, PropModeReplace,
|
|
|
|
(guchar *) &incr_chunk_size, 1);
|
|
|
|
reply_selection_request (&data->request_event, TRUE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
wayland_selection_update_x11_property (data);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!data->incr)
|
|
|
|
{
|
|
|
|
/* Non-incr transfer finished */
|
|
|
|
wayland_selection_update_x11_property (data);
|
|
|
|
reply_selection_request (&data->request_event, TRUE);
|
|
|
|
}
|
|
|
|
else if (data->incr)
|
|
|
|
{
|
|
|
|
/* Incr transfer complete, setting a new property */
|
|
|
|
wayland_selection_update_x11_property (data);
|
|
|
|
|
|
|
|
if (bytes_read > 0)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_clear_pointer (&selection->wayland_selection,
|
|
|
|
(GDestroyNotify) wayland_selection_data_free);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
wayland_selection_data_read (MetaSelectionBridge *selection)
|
|
|
|
{
|
|
|
|
WaylandSelectionData *data = selection->wayland_selection;
|
|
|
|
|
|
|
|
g_input_stream_read_async (data->stream, data->buffer,
|
|
|
|
INCR_CHUNK_SIZE, G_PRIORITY_DEFAULT,
|
|
|
|
data->cancellable,
|
|
|
|
wayland_data_read_cb, selection);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_xwayland_selection_get_incr_chunk (MetaWaylandCompositor *compositor,
|
|
|
|
MetaSelectionBridge *selection)
|
|
|
|
{
|
|
|
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
|
|
|
gulong nitems_ret, bytes_after_ret;
|
|
|
|
guchar *prop_ret;
|
|
|
|
int format_ret;
|
|
|
|
Atom type_ret;
|
|
|
|
|
|
|
|
XGetWindowProperty (xdisplay,
|
|
|
|
selection->window,
|
|
|
|
gdk_x11_get_xatom_by_name ("_META_SELECTION"),
|
|
|
|
0, /* offset */
|
|
|
|
0x1fffffff, /* length */
|
|
|
|
False, /* delete */
|
|
|
|
AnyPropertyType,
|
|
|
|
&type_ret,
|
|
|
|
&format_ret,
|
|
|
|
&nitems_ret,
|
|
|
|
&bytes_after_ret,
|
|
|
|
&prop_ret);
|
|
|
|
|
|
|
|
if (nitems_ret > 0)
|
|
|
|
{
|
|
|
|
x11_selection_data_write (selection, prop_ret, nitems_ret);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Transfer has completed */
|
2015-04-07 10:05:46 -04:00
|
|
|
x11_selection_data_close (selection->x11_selection);
|
2015-05-12 13:35:28 -04:00
|
|
|
x11_selection_data_finish (selection, TRUE);
|
2014-10-10 12:55:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
XFree (prop_ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_x11_source_send (MetaWaylandDataSource *source,
|
|
|
|
const gchar *mime_type,
|
|
|
|
gint fd)
|
|
|
|
{
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
MetaWaylandDataSourceXWayland *source_xwayland =
|
|
|
|
META_WAYLAND_DATA_SOURCE_XWAYLAND (source);
|
2014-10-10 12:55:00 -04:00
|
|
|
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
|
|
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
MetaSelectionBridge *selection = source_xwayland->selection;
|
2014-10-10 12:55:00 -04:00
|
|
|
Atom type_atom;
|
|
|
|
|
2015-09-28 08:27:10 -04:00
|
|
|
if (source_xwayland->has_utf8_string_atom &&
|
|
|
|
strcmp (mime_type, "text/plain;charset=utf-8") == 0)
|
2014-10-10 12:55:00 -04:00
|
|
|
type_atom = gdk_x11_get_xatom_by_name ("UTF8_STRING");
|
|
|
|
else
|
|
|
|
type_atom = gdk_x11_get_xatom_by_name (mime_type);
|
|
|
|
|
2015-05-12 13:35:28 -04:00
|
|
|
/* Ensure we close previous transactions */
|
|
|
|
x11_selection_data_finish (selection, FALSE);
|
2014-10-10 12:55:00 -04:00
|
|
|
|
|
|
|
/* Takes ownership of fd */
|
|
|
|
selection->x11_selection =
|
|
|
|
x11_selection_data_new (compositor->xwayland_manager.selection_data,
|
|
|
|
fd, mime_type);
|
|
|
|
|
|
|
|
XConvertSelection (xdisplay,
|
|
|
|
selection->selection_atom, type_atom,
|
|
|
|
gdk_x11_get_xatom_by_name ("_META_SELECTION"),
|
|
|
|
selection->window,
|
|
|
|
CurrentTime);
|
|
|
|
XFlush (xdisplay);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_x11_source_target (MetaWaylandDataSource *source,
|
|
|
|
const gchar *mime_type)
|
|
|
|
{
|
2015-05-12 13:35:28 -04:00
|
|
|
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
MetaWaylandDataSourceXWayland *source_xwayland =
|
|
|
|
META_WAYLAND_DATA_SOURCE_XWAYLAND (source);
|
|
|
|
MetaSelectionBridge *selection = source_xwayland->selection;
|
2015-04-07 10:05:46 -04:00
|
|
|
uint32_t action = 0;
|
2015-05-12 13:35:28 -04:00
|
|
|
|
|
|
|
if (selection->selection_atom == xdnd_atoms[ATOM_DND_SELECTION])
|
|
|
|
{
|
2015-04-07 10:05:46 -04:00
|
|
|
if (mime_type)
|
|
|
|
action = meta_wayland_data_source_get_current_action (source);
|
|
|
|
|
2015-05-12 13:35:28 -04:00
|
|
|
xdnd_send_status (compositor->xwayland_manager.selection_data,
|
2015-04-07 10:05:46 -04:00
|
|
|
selection->owner, action);
|
2015-05-12 13:35:28 -04:00
|
|
|
}
|
2014-10-10 12:55:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_x11_source_cancel (MetaWaylandDataSource *source)
|
|
|
|
{
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
MetaWaylandDataSourceXWayland *source_xwayland =
|
|
|
|
META_WAYLAND_DATA_SOURCE_XWAYLAND (source);
|
|
|
|
MetaSelectionBridge *selection = source_xwayland->selection;
|
2014-10-10 12:55:00 -04:00
|
|
|
|
2015-04-07 10:05:46 -04:00
|
|
|
x11_selection_data_send_finished (selection, FALSE);
|
2014-10-10 12:55:00 -04:00
|
|
|
g_clear_pointer (&selection->x11_selection,
|
|
|
|
(GDestroyNotify) x11_selection_data_free);
|
|
|
|
}
|
|
|
|
|
2015-04-07 10:05:46 -04:00
|
|
|
static void
|
|
|
|
meta_x11_source_action (MetaWaylandDataSource *source,
|
|
|
|
uint32_t action)
|
|
|
|
{
|
|
|
|
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
|
|
|
MetaWaylandDataSourceXWayland *source_xwayland =
|
|
|
|
META_WAYLAND_DATA_SOURCE_XWAYLAND (source);
|
|
|
|
MetaSelectionBridge *selection = source_xwayland->selection;
|
|
|
|
|
|
|
|
if (selection->selection_atom == xdnd_atoms[ATOM_DND_SELECTION])
|
|
|
|
{
|
|
|
|
if (!meta_wayland_data_source_has_target (source))
|
|
|
|
action = 0;
|
|
|
|
|
|
|
|
xdnd_send_status (compositor->xwayland_manager.selection_data,
|
|
|
|
selection->owner, action);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_x11_source_drop_performed (MetaWaylandDataSource *source)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_x11_source_drag_finished (MetaWaylandDataSource *source)
|
|
|
|
{
|
|
|
|
MetaWaylandDataSourceXWayland *source_xwayland =
|
|
|
|
META_WAYLAND_DATA_SOURCE_XWAYLAND (source);
|
|
|
|
MetaSelectionBridge *selection = source_xwayland->selection;
|
|
|
|
|
|
|
|
if (selection->x11_selection)
|
|
|
|
x11_selection_data_send_finished (selection, TRUE);
|
|
|
|
}
|
|
|
|
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
static void
|
|
|
|
meta_wayland_data_source_xwayland_init (MetaWaylandDataSourceXWayland *source_xwayland)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_wayland_data_source_xwayland_class_init (MetaWaylandDataSourceXWaylandClass *klass)
|
|
|
|
{
|
|
|
|
MetaWaylandDataSourceClass *data_source_class =
|
|
|
|
META_WAYLAND_DATA_SOURCE_CLASS (klass);
|
|
|
|
|
|
|
|
data_source_class->send = meta_x11_source_send;
|
|
|
|
data_source_class->target = meta_x11_source_target;
|
|
|
|
data_source_class->cancel = meta_x11_source_cancel;
|
2015-04-07 10:05:46 -04:00
|
|
|
data_source_class->action = meta_x11_source_action;
|
|
|
|
data_source_class->drop_performed = meta_x11_source_drop_performed;
|
|
|
|
data_source_class->drag_finished = meta_x11_source_drag_finished;
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static MetaWaylandDataSource *
|
|
|
|
meta_wayland_data_source_xwayland_new (MetaSelectionBridge *selection)
|
|
|
|
{
|
|
|
|
MetaWaylandDataSourceXWayland *source_xwayland;
|
|
|
|
|
|
|
|
source_xwayland = g_object_new (META_TYPE_WAYLAND_DATA_SOURCE_XWAYLAND, NULL);
|
|
|
|
source_xwayland->selection = selection;
|
|
|
|
|
|
|
|
return META_WAYLAND_DATA_SOURCE (source_xwayland);
|
|
|
|
}
|
2014-10-10 12:55:00 -04:00
|
|
|
|
2015-04-29 11:44:05 -04:00
|
|
|
static void
|
|
|
|
meta_x11_drag_dest_focus_in (MetaWaylandDataDevice *data_device,
|
|
|
|
MetaWaylandSurface *surface,
|
|
|
|
MetaWaylandDataOffer *offer)
|
|
|
|
{
|
|
|
|
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
|
|
|
|
|
|
|
compositor->xwayland_manager.selection_data->dnd.dnd_dest = surface->window->xwindow;
|
|
|
|
xdnd_send_enter (compositor->xwayland_manager.selection_data,
|
|
|
|
compositor->xwayland_manager.selection_data->dnd.dnd_dest);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_x11_drag_dest_focus_out (MetaWaylandDataDevice *data_device,
|
|
|
|
MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
|
|
|
|
|
|
|
xdnd_send_leave (compositor->xwayland_manager.selection_data,
|
|
|
|
compositor->xwayland_manager.selection_data->dnd.dnd_dest);
|
|
|
|
compositor->xwayland_manager.selection_data->dnd.dnd_dest = None;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_x11_drag_dest_motion (MetaWaylandDataDevice *data_device,
|
|
|
|
MetaWaylandSurface *surface,
|
|
|
|
const ClutterEvent *event)
|
|
|
|
{
|
|
|
|
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
|
|
|
guint32 time;
|
|
|
|
gfloat x, y;
|
|
|
|
|
|
|
|
time = clutter_event_get_time (event);
|
|
|
|
clutter_event_get_coords (event, &x, &y);
|
|
|
|
xdnd_send_position (compositor->xwayland_manager.selection_data,
|
|
|
|
compositor->xwayland_manager.selection_data->dnd.dnd_dest,
|
|
|
|
time, x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_x11_drag_dest_drop (MetaWaylandDataDevice *data_device,
|
|
|
|
MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
|
|
|
|
|
|
|
xdnd_send_drop (compositor->xwayland_manager.selection_data,
|
|
|
|
compositor->xwayland_manager.selection_data->dnd.dnd_dest,
|
|
|
|
meta_display_get_current_time_roundtrip (meta_get_display ()));
|
|
|
|
}
|
|
|
|
|
2015-04-07 10:05:46 -04:00
|
|
|
static void
|
|
|
|
meta_x11_drag_dest_update (MetaWaylandDataDevice *data_device,
|
|
|
|
MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
|
|
|
MetaWaylandSeat *seat = compositor->seat;
|
|
|
|
ClutterPoint pos;
|
|
|
|
|
2016-04-01 04:39:30 -04:00
|
|
|
clutter_input_device_get_coords (seat->pointer->device, NULL, &pos);
|
2015-04-07 10:05:46 -04:00
|
|
|
xdnd_send_position (compositor->xwayland_manager.selection_data,
|
|
|
|
compositor->xwayland_manager.selection_data->dnd.dnd_dest,
|
|
|
|
clutter_get_current_event_time (),
|
|
|
|
pos.x, pos.y);
|
|
|
|
}
|
|
|
|
|
2015-04-29 11:44:05 -04:00
|
|
|
static const MetaWaylandDragDestFuncs meta_x11_drag_dest_funcs = {
|
|
|
|
meta_x11_drag_dest_focus_in,
|
|
|
|
meta_x11_drag_dest_focus_out,
|
|
|
|
meta_x11_drag_dest_motion,
|
2015-04-07 10:05:46 -04:00
|
|
|
meta_x11_drag_dest_drop,
|
|
|
|
meta_x11_drag_dest_update
|
2015-04-29 11:44:05 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
const MetaWaylandDragDestFuncs *
|
|
|
|
meta_xwayland_selection_get_drag_dest_funcs (void)
|
|
|
|
{
|
|
|
|
return &meta_x11_drag_dest_funcs;
|
|
|
|
}
|
|
|
|
|
2014-10-10 12:55:00 -04:00
|
|
|
static gboolean
|
|
|
|
meta_xwayland_data_source_fetch_mimetype_list (MetaWaylandDataSource *source,
|
|
|
|
Window window,
|
|
|
|
Atom prop)
|
|
|
|
{
|
2015-09-28 08:27:10 -04:00
|
|
|
MetaWaylandDataSourceXWayland *source_xwayland =
|
|
|
|
META_WAYLAND_DATA_SOURCE_XWAYLAND (source);
|
2014-10-10 12:55:00 -04:00
|
|
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
|
|
|
gulong nitems_ret, bytes_after_ret, i;
|
|
|
|
Atom *atoms, type_ret, utf8_string;
|
|
|
|
int format_ret;
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
struct wl_array *source_mime_types;
|
2014-10-10 12:55:00 -04:00
|
|
|
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
source_mime_types = meta_wayland_data_source_get_mime_types (source);
|
|
|
|
if (source_mime_types->size != 0)
|
2015-05-12 13:35:28 -04:00
|
|
|
return TRUE;
|
|
|
|
|
2014-10-10 12:55:00 -04:00
|
|
|
utf8_string = gdk_x11_get_xatom_by_name ("UTF8_STRING");
|
|
|
|
XGetWindowProperty (xdisplay, window, prop,
|
|
|
|
0, /* offset */
|
|
|
|
0x1fffffff, /* length */
|
|
|
|
True, /* delete */
|
|
|
|
AnyPropertyType,
|
|
|
|
&type_ret,
|
|
|
|
&format_ret,
|
|
|
|
&nitems_ret,
|
|
|
|
&bytes_after_ret,
|
|
|
|
(guchar **) &atoms);
|
|
|
|
|
|
|
|
if (nitems_ret == 0 || type_ret != XA_ATOM)
|
|
|
|
{
|
|
|
|
XFree (atoms);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < nitems_ret; i++)
|
|
|
|
{
|
|
|
|
const gchar *mime_type;
|
|
|
|
|
|
|
|
if (atoms[i] == utf8_string)
|
2015-09-28 08:27:10 -04:00
|
|
|
{
|
|
|
|
meta_wayland_data_source_add_mime_type (source,
|
|
|
|
"text/plain;charset=utf-8");
|
|
|
|
source_xwayland->has_utf8_string_atom = TRUE;
|
|
|
|
}
|
2014-10-10 12:55:00 -04:00
|
|
|
|
2015-09-28 08:27:10 -04:00
|
|
|
mime_type = gdk_x11_get_xatom_name (atoms[i]);
|
2014-10-10 12:55:00 -04:00
|
|
|
meta_wayland_data_source_add_mime_type (source, mime_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
XFree (atoms);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_xwayland_selection_get_x11_targets (MetaWaylandCompositor *compositor,
|
|
|
|
MetaSelectionBridge *selection)
|
|
|
|
{
|
|
|
|
MetaWaylandDataSource *data_source;
|
|
|
|
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
data_source = meta_wayland_data_source_xwayland_new (selection);
|
2014-10-10 12:55:00 -04:00
|
|
|
|
|
|
|
if (meta_xwayland_data_source_fetch_mimetype_list (data_source,
|
|
|
|
selection->window,
|
|
|
|
gdk_x11_get_xatom_by_name ("_META_SELECTION")))
|
|
|
|
{
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
g_clear_object (&selection->source);
|
2014-10-10 12:55:00 -04:00
|
|
|
selection->source = data_source;
|
|
|
|
|
|
|
|
if (selection->selection_atom == gdk_x11_get_xatom_by_name ("CLIPBOARD"))
|
|
|
|
{
|
|
|
|
meta_wayland_data_device_set_selection (&compositor->seat->data_device, data_source,
|
|
|
|
wl_display_next_serial (compositor->wayland_display));
|
|
|
|
}
|
2016-02-03 12:39:58 -05:00
|
|
|
else if (selection->selection_atom == gdk_x11_get_xatom_by_name ("PRIMARY"))
|
|
|
|
{
|
|
|
|
meta_wayland_data_device_set_primary (&compositor->seat->data_device, data_source,
|
|
|
|
wl_display_next_serial (compositor->wayland_display));
|
|
|
|
}
|
2014-10-10 12:55:00 -04:00
|
|
|
}
|
|
|
|
else
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
g_object_unref (data_source);
|
2014-10-10 12:55:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_xwayland_selection_get_x11_data (MetaWaylandCompositor *compositor,
|
|
|
|
MetaSelectionBridge *selection)
|
|
|
|
{
|
|
|
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
|
|
|
gulong nitems_ret, bytes_after_ret;
|
|
|
|
guchar *prop_ret;
|
|
|
|
int format_ret;
|
|
|
|
Atom type_ret;
|
|
|
|
|
|
|
|
if (!selection->x11_selection)
|
|
|
|
return;
|
|
|
|
|
|
|
|
XGetWindowProperty (xdisplay,
|
|
|
|
selection->window,
|
|
|
|
gdk_x11_get_xatom_by_name ("_META_SELECTION"),
|
|
|
|
0, /* offset */
|
|
|
|
0x1fffffff, /* length */
|
|
|
|
True, /* delete */
|
|
|
|
AnyPropertyType,
|
|
|
|
&type_ret,
|
|
|
|
&format_ret,
|
|
|
|
&nitems_ret,
|
|
|
|
&bytes_after_ret,
|
|
|
|
&prop_ret);
|
|
|
|
|
|
|
|
selection->x11_selection->incr = (type_ret == gdk_x11_get_xatom_by_name ("INCR"));
|
|
|
|
|
|
|
|
if (selection->x11_selection->incr)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (type_ret == gdk_x11_get_xatom_by_name (selection->x11_selection->mime_type))
|
|
|
|
x11_selection_data_write (selection, prop_ret, nitems_ret);
|
|
|
|
|
|
|
|
XFree (prop_ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
meta_xwayland_selection_handle_selection_notify (MetaWaylandCompositor *compositor,
|
|
|
|
XEvent *xevent)
|
|
|
|
{
|
|
|
|
XSelectionEvent *event = (XSelectionEvent *) xevent;
|
|
|
|
MetaSelectionBridge *selection;
|
|
|
|
|
|
|
|
selection = atom_to_selection_bridge (compositor, event->selection);
|
|
|
|
|
|
|
|
if (!selection)
|
|
|
|
return FALSE;
|
|
|
|
|
2016-10-07 07:58:35 -04:00
|
|
|
if (selection->window != event->requestor)
|
|
|
|
return FALSE;
|
|
|
|
|
2014-10-10 12:55:00 -04:00
|
|
|
/* convert selection failed */
|
|
|
|
if (event->property == None)
|
|
|
|
{
|
|
|
|
g_clear_pointer (&selection->x11_selection,
|
|
|
|
(GDestroyNotify) x11_selection_data_free);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (event->target == gdk_x11_get_xatom_by_name ("TARGETS"))
|
|
|
|
meta_xwayland_selection_get_x11_targets (compositor, selection);
|
|
|
|
else
|
|
|
|
meta_xwayland_selection_get_x11_data (compositor, selection);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_xwayland_selection_send_targets (MetaWaylandCompositor *compositor,
|
|
|
|
const MetaWaylandDataSource *data_source,
|
|
|
|
Window requestor,
|
|
|
|
Atom property)
|
|
|
|
{
|
|
|
|
Atom *targets;
|
|
|
|
gchar **p;
|
|
|
|
int i = 0;
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
struct wl_array *source_mime_types;
|
2014-10-10 12:55:00 -04:00
|
|
|
|
|
|
|
if (!data_source)
|
|
|
|
return;
|
|
|
|
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
source_mime_types = meta_wayland_data_source_get_mime_types (data_source);
|
|
|
|
if (source_mime_types->size == 0)
|
2014-10-10 12:55:00 -04:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* Make extra room for TIMESTAMP/TARGETS */
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
targets = g_new (Atom, source_mime_types->size + 2);
|
2014-10-10 12:55:00 -04:00
|
|
|
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
wl_array_for_each (p, source_mime_types)
|
2014-10-10 12:55:00 -04:00
|
|
|
{
|
|
|
|
targets[i++] = gdk_x11_get_xatom_by_name (*p);
|
|
|
|
}
|
|
|
|
|
|
|
|
targets[i++] = gdk_x11_get_xatom_by_name ("TIMESTAMP");
|
|
|
|
targets[i++] = gdk_x11_get_xatom_by_name ("TARGETS");
|
|
|
|
|
|
|
|
XChangeProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
|
|
|
|
requestor, property,
|
|
|
|
XA_ATOM, 32, PropModeReplace,
|
|
|
|
(guchar *) targets, i);
|
|
|
|
|
|
|
|
g_free (targets);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_xwayland_selection_send_timestamp (MetaWaylandCompositor *compositor,
|
|
|
|
Window requestor,
|
|
|
|
Atom property,
|
|
|
|
Time timestamp)
|
|
|
|
{
|
|
|
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
|
|
|
|
|
|
|
XChangeProperty (xdisplay, requestor, property,
|
|
|
|
XA_INTEGER, 32,
|
|
|
|
PropModeReplace,
|
|
|
|
(guchar *) ×tamp, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_xwayland_selection_send_incr_chunk (MetaWaylandCompositor *compositor,
|
|
|
|
MetaSelectionBridge *selection)
|
|
|
|
{
|
|
|
|
if (!selection->wayland_selection)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (selection->wayland_selection->buffer_len > 0)
|
|
|
|
wayland_selection_update_x11_property (selection->wayland_selection);
|
|
|
|
else
|
|
|
|
wayland_selection_data_read (selection);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
handle_incr_chunk (MetaWaylandCompositor *compositor,
|
|
|
|
MetaSelectionBridge *selection,
|
|
|
|
XPropertyEvent *event)
|
|
|
|
{
|
|
|
|
if (selection->x11_selection &&
|
|
|
|
selection->x11_selection->incr &&
|
|
|
|
event->window == selection->owner &&
|
|
|
|
event->state == PropertyNewValue &&
|
|
|
|
event->atom == gdk_x11_get_xatom_by_name ("_META_SELECTION"))
|
|
|
|
{
|
|
|
|
/* X11 to Wayland */
|
|
|
|
meta_xwayland_selection_get_incr_chunk (compositor, selection);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else if (selection->wayland_selection &&
|
|
|
|
selection->wayland_selection->incr &&
|
|
|
|
event->window == selection->window &&
|
|
|
|
event->state == PropertyDelete &&
|
|
|
|
event->atom == selection->wayland_selection->request_event.property)
|
|
|
|
{
|
|
|
|
/* Wayland to X11 */
|
|
|
|
meta_xwayland_selection_send_incr_chunk (compositor, selection);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
meta_xwayland_selection_handle_property_notify (MetaWaylandCompositor *compositor,
|
|
|
|
XEvent *xevent)
|
|
|
|
{
|
|
|
|
MetaXWaylandSelection *selection_data = compositor->xwayland_manager.selection_data;
|
|
|
|
XPropertyEvent *event = (XPropertyEvent *) xevent;
|
|
|
|
|
|
|
|
return handle_incr_chunk (compositor, &selection_data->clipboard, event);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
meta_xwayland_selection_handle_selection_request (MetaWaylandCompositor *compositor,
|
|
|
|
XEvent *xevent)
|
|
|
|
{
|
|
|
|
XSelectionRequestEvent *event = (XSelectionRequestEvent *) xevent;
|
|
|
|
MetaWaylandDataSource *data_source;
|
|
|
|
MetaSelectionBridge *selection;
|
|
|
|
|
|
|
|
selection = atom_to_selection_bridge (compositor, event->selection);
|
|
|
|
|
|
|
|
if (!selection)
|
|
|
|
return FALSE;
|
|
|
|
|
2016-10-07 07:58:35 -04:00
|
|
|
if (selection->window != event->owner)
|
|
|
|
return FALSE;
|
|
|
|
|
2014-10-10 12:55:00 -04:00
|
|
|
/* We must fetch from the currently active source, not the Xwayland one */
|
|
|
|
data_source = data_device_get_active_source_for_atom (&compositor->seat->data_device,
|
|
|
|
selection->selection_atom);
|
|
|
|
if (!data_source)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
g_clear_pointer (&selection->wayland_selection,
|
|
|
|
(GDestroyNotify) wayland_selection_data_free);
|
|
|
|
|
|
|
|
if (event->target == gdk_x11_get_xatom_by_name ("TARGETS"))
|
|
|
|
{
|
|
|
|
meta_xwayland_selection_send_targets (compositor,
|
|
|
|
data_source,
|
|
|
|
event->requestor,
|
|
|
|
event->property);
|
|
|
|
reply_selection_request (event, TRUE);
|
|
|
|
}
|
|
|
|
else if (event->target == gdk_x11_get_xatom_by_name ("TIMESTAMP"))
|
|
|
|
{
|
|
|
|
meta_xwayland_selection_send_timestamp (compositor,
|
|
|
|
event->requestor, event->property,
|
|
|
|
selection->timestamp);
|
|
|
|
reply_selection_request (event, TRUE);
|
|
|
|
}
|
2015-04-07 10:05:46 -04:00
|
|
|
else if (data_source && event->target == gdk_x11_get_xatom_by_name ("DELETE"))
|
|
|
|
{
|
|
|
|
reply_selection_request (event, TRUE);
|
|
|
|
}
|
2014-10-10 12:55:00 -04:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (data_source &&
|
|
|
|
meta_wayland_data_source_has_mime_type (data_source,
|
|
|
|
gdk_x11_get_xatom_name (event->target)))
|
|
|
|
{
|
|
|
|
selection->wayland_selection = wayland_selection_data_new (event,
|
|
|
|
compositor);
|
|
|
|
|
|
|
|
if (selection->wayland_selection)
|
|
|
|
wayland_selection_data_read (selection);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!selection->wayland_selection)
|
|
|
|
reply_selection_request (event, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2015-05-12 13:35:28 -04:00
|
|
|
static MetaWaylandSurface *
|
|
|
|
pick_drop_surface (MetaWaylandCompositor *compositor,
|
|
|
|
const ClutterEvent *event)
|
|
|
|
{
|
|
|
|
MetaDisplay *display = meta_get_display ();
|
|
|
|
MetaWindow *focus_window = NULL;
|
|
|
|
ClutterPoint pos;
|
|
|
|
|
|
|
|
clutter_event_get_coords (event, &pos.x, &pos.y);
|
|
|
|
focus_window = meta_stack_get_default_focus_window_at_point (display->screen->stack,
|
|
|
|
NULL, NULL,
|
|
|
|
pos.x, pos.y);
|
|
|
|
return focus_window ? focus_window->surface : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
repick_drop_surface (MetaWaylandCompositor *compositor,
|
|
|
|
MetaWaylandDragGrab *drag_grab,
|
|
|
|
const ClutterEvent *event)
|
|
|
|
{
|
|
|
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
|
|
|
MetaDndBridge *dnd = &compositor->xwayland_manager.selection_data->dnd;
|
|
|
|
MetaWaylandSurface *focus = NULL;
|
|
|
|
|
|
|
|
focus = pick_drop_surface (compositor, event);
|
|
|
|
dnd->focus_surface = focus;
|
|
|
|
|
|
|
|
if (meta_wayland_drag_grab_get_focus (drag_grab) == focus)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (focus &&
|
|
|
|
focus->window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
|
|
|
|
{
|
|
|
|
XMapWindow (xdisplay, dnd->dnd_window);
|
|
|
|
XMoveResizeWindow (xdisplay, dnd->dnd_window,
|
|
|
|
focus->window->rect.x,
|
|
|
|
focus->window->rect.y,
|
|
|
|
focus->window->rect.width,
|
|
|
|
focus->window->rect.height);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
XMoveResizeWindow (xdisplay, dnd->dnd_window, -1, -1, 1, 1);
|
|
|
|
XUnmapWindow (xdisplay, dnd->dnd_window);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
drag_xgrab_focus (MetaWaylandPointerGrab *grab,
|
|
|
|
MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
/* Do not update the focus here. First, the surface may perfectly
|
|
|
|
* be the X11 source DnD icon window's, so we can only be fooled
|
|
|
|
* here. Second, delaying focus handling to XdndEnter/Leave
|
|
|
|
* makes us do the negotiation orderly on the X11 side.
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
drag_xgrab_motion (MetaWaylandPointerGrab *grab,
|
|
|
|
const ClutterEvent *event)
|
|
|
|
{
|
|
|
|
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
|
|
|
MetaDndBridge *dnd = &compositor->xwayland_manager.selection_data->dnd;
|
|
|
|
MetaWaylandSeat *seat = compositor->seat;
|
|
|
|
|
|
|
|
repick_drop_surface (compositor,
|
|
|
|
(MetaWaylandDragGrab *) grab,
|
|
|
|
event);
|
|
|
|
|
|
|
|
dnd->last_motion_time = clutter_event_get_time (event);
|
2016-04-01 04:39:30 -04:00
|
|
|
meta_wayland_pointer_send_motion (seat->pointer, event);
|
2015-05-12 13:35:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
drag_xgrab_button (MetaWaylandPointerGrab *grab,
|
|
|
|
const ClutterEvent *event)
|
|
|
|
{
|
|
|
|
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
|
|
|
MetaWaylandSeat *seat = compositor->seat;
|
|
|
|
|
2016-04-01 04:39:30 -04:00
|
|
|
meta_wayland_pointer_send_button (seat->pointer, event);
|
2015-05-12 13:35:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static const MetaWaylandPointerGrabInterface drag_xgrab_interface = {
|
|
|
|
drag_xgrab_focus,
|
|
|
|
drag_xgrab_motion,
|
|
|
|
drag_xgrab_button,
|
|
|
|
};
|
|
|
|
|
2015-04-29 11:44:05 -04:00
|
|
|
static gboolean
|
|
|
|
meta_xwayland_selection_handle_client_message (MetaWaylandCompositor *compositor,
|
|
|
|
XEvent *xevent)
|
|
|
|
{
|
|
|
|
XClientMessageEvent *event = (XClientMessageEvent *) xevent;
|
2015-05-12 13:35:28 -04:00
|
|
|
MetaDndBridge *dnd = &compositor->xwayland_manager.selection_data->dnd;
|
|
|
|
MetaWaylandSeat *seat = compositor->seat;
|
2015-04-29 11:44:05 -04:00
|
|
|
|
|
|
|
/* Source side messages */
|
2015-05-12 13:35:28 -04:00
|
|
|
if (event->window == dnd->selection.window)
|
2015-04-29 11:44:05 -04:00
|
|
|
{
|
|
|
|
MetaWaylandDataSource *data_source;
|
2015-04-07 10:05:46 -04:00
|
|
|
uint32_t action = 0;
|
2015-04-29 11:44:05 -04:00
|
|
|
|
|
|
|
data_source = compositor->seat->data_device.dnd_data_source;
|
|
|
|
|
|
|
|
if (!data_source)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (event->message_type == xdnd_atoms[ATOM_DND_STATUS])
|
|
|
|
{
|
|
|
|
/* The first bit in data.l[1] is set if the drag was accepted */
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
meta_wayland_data_source_set_has_target (data_source,
|
|
|
|
(event->data.l[1] & 1) != 0);
|
2015-04-29 11:44:05 -04:00
|
|
|
|
2015-04-07 10:05:46 -04:00
|
|
|
/* data.l[4] contains the action atom */
|
|
|
|
if (event->data.l[4])
|
|
|
|
action = atom_to_action ((Atom) event->data.l[4]);
|
|
|
|
|
|
|
|
meta_wayland_data_source_set_current_action (data_source, action);
|
2015-04-29 11:44:05 -04:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else if (event->message_type == xdnd_atoms[ATOM_DND_FINISHED])
|
|
|
|
{
|
|
|
|
/* Reject messages mid-grab */
|
|
|
|
if (compositor->seat->data_device.current_grab)
|
|
|
|
return FALSE;
|
|
|
|
|
2015-04-07 10:05:46 -04:00
|
|
|
meta_wayland_data_source_notify_finish (data_source);
|
2015-04-29 11:44:05 -04:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
2015-05-12 13:35:28 -04:00
|
|
|
/* Dest side messages */
|
|
|
|
else if (dnd->selection.source &&
|
|
|
|
compositor->seat->data_device.current_grab &&
|
|
|
|
(Window) event->data.l[0] == dnd->selection.owner)
|
|
|
|
{
|
|
|
|
MetaWaylandDragGrab *drag_grab = compositor->seat->data_device.current_grab;
|
|
|
|
MetaWaylandSurface *drag_focus = meta_wayland_drag_grab_get_focus (drag_grab);
|
|
|
|
|
2015-04-07 10:05:46 -04:00
|
|
|
if (!drag_focus &&
|
|
|
|
event->message_type != xdnd_atoms[ATOM_DND_ENTER])
|
2015-09-28 08:40:53 -04:00
|
|
|
return FALSE;
|
|
|
|
|
2015-05-12 13:35:28 -04:00
|
|
|
if (event->message_type == xdnd_atoms[ATOM_DND_ENTER])
|
|
|
|
{
|
|
|
|
/* Bit 1 in data.l[1] determines whether there's 3 or less mimetype
|
|
|
|
* atoms (and are thus contained in this same message), or whether
|
|
|
|
* there's more than 3 and we need to check the XdndTypeList property
|
|
|
|
* for the full list.
|
|
|
|
*/
|
|
|
|
if (!(event->data.l[1] & 1))
|
|
|
|
{
|
|
|
|
/* Mimetypes are contained in this message */
|
|
|
|
const gchar *mimetype;
|
|
|
|
gint i;
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
struct wl_array *source_mime_types;
|
2015-05-12 13:35:28 -04:00
|
|
|
|
|
|
|
/* We only need to fetch once */
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
source_mime_types =
|
|
|
|
meta_wayland_data_source_get_mime_types (dnd->selection.source);
|
|
|
|
if (source_mime_types->size == 0)
|
2015-05-12 13:35:28 -04:00
|
|
|
{
|
|
|
|
for (i = 2; i <= 4; i++)
|
|
|
|
{
|
|
|
|
if (event->data.l[i] == None)
|
|
|
|
break;
|
|
|
|
|
|
|
|
mimetype = gdk_x11_get_xatom_name (event->data.l[i]);
|
|
|
|
meta_wayland_data_source_add_mime_type (dnd->selection.source,
|
|
|
|
mimetype);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Fetch mimetypes from type list */
|
|
|
|
meta_xwayland_data_source_fetch_mimetype_list (dnd->selection.source,
|
|
|
|
event->data.l[0],
|
|
|
|
xdnd_atoms[ATOM_DND_TYPE_LIST]);
|
|
|
|
}
|
|
|
|
|
|
|
|
meta_wayland_drag_grab_set_focus (drag_grab, dnd->focus_surface);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else if (event->message_type == xdnd_atoms[ATOM_DND_POSITION])
|
|
|
|
{
|
|
|
|
ClutterEvent *motion;
|
|
|
|
ClutterPoint pos;
|
2015-04-07 10:05:46 -04:00
|
|
|
uint32_t action = 0;
|
2015-05-12 13:35:28 -04:00
|
|
|
|
|
|
|
motion = clutter_event_new (CLUTTER_MOTION);
|
2016-04-01 04:39:30 -04:00
|
|
|
clutter_input_device_get_coords (seat->pointer->device, NULL, &pos);
|
2015-05-12 13:35:28 -04:00
|
|
|
clutter_event_set_coords (motion, pos.x, pos.y);
|
2016-04-01 04:39:30 -04:00
|
|
|
clutter_event_set_device (motion, seat->pointer->device);
|
|
|
|
clutter_event_set_source_device (motion, seat->pointer->device);
|
2015-05-12 13:35:28 -04:00
|
|
|
clutter_event_set_time (motion, dnd->last_motion_time);
|
|
|
|
|
2015-04-07 10:05:46 -04:00
|
|
|
action = atom_to_action ((Atom) event->data.l[4]);
|
|
|
|
meta_wayland_data_source_set_actions (dnd->selection.source, action);
|
|
|
|
|
2015-05-12 13:35:28 -04:00
|
|
|
meta_wayland_surface_drag_dest_motion (drag_focus, motion);
|
|
|
|
xdnd_send_status (compositor->xwayland_manager.selection_data,
|
|
|
|
(Window) event->data.l[0],
|
2015-04-07 10:05:46 -04:00
|
|
|
meta_wayland_data_source_get_current_action (dnd->selection.source));
|
2015-05-12 13:35:28 -04:00
|
|
|
|
|
|
|
clutter_event_free (motion);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else if (event->message_type == xdnd_atoms[ATOM_DND_LEAVE])
|
|
|
|
{
|
|
|
|
meta_wayland_drag_grab_set_focus (drag_grab, NULL);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else if (event->message_type == xdnd_atoms[ATOM_DND_DROP])
|
|
|
|
{
|
|
|
|
meta_wayland_surface_drag_dest_drop (drag_focus);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
2015-04-29 11:44:05 -04:00
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2014-10-10 12:55:00 -04:00
|
|
|
static gboolean
|
|
|
|
meta_xwayland_selection_handle_xfixes_selection_notify (MetaWaylandCompositor *compositor,
|
|
|
|
XEvent *xevent)
|
|
|
|
{
|
|
|
|
XFixesSelectionNotifyEvent *event = (XFixesSelectionNotifyEvent *) xevent;
|
|
|
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
|
|
|
MetaSelectionBridge *selection;
|
|
|
|
|
|
|
|
selection = atom_to_selection_bridge (compositor, event->selection);
|
|
|
|
|
|
|
|
if (!selection)
|
|
|
|
return FALSE;
|
|
|
|
|
2016-02-03 12:39:58 -05:00
|
|
|
if (selection->selection_atom == gdk_x11_get_xatom_by_name ("CLIPBOARD") ||
|
|
|
|
selection->selection_atom == gdk_x11_get_xatom_by_name ("PRIMARY"))
|
2014-10-10 12:55:00 -04:00
|
|
|
{
|
2015-05-28 06:07:49 -04:00
|
|
|
if (event->owner == None)
|
2014-10-10 12:55:00 -04:00
|
|
|
{
|
2015-05-28 06:07:49 -04:00
|
|
|
if (selection->source && selection->owner != selection->window)
|
2014-10-10 12:55:00 -04:00
|
|
|
{
|
2015-05-28 06:07:49 -04:00
|
|
|
/* An X client went away, clear the selection */
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
g_clear_object (&selection->source);
|
2014-10-10 12:55:00 -04:00
|
|
|
}
|
|
|
|
|
2015-05-28 06:07:49 -04:00
|
|
|
selection->owner = None;
|
2014-10-10 12:55:00 -04:00
|
|
|
}
|
2015-05-28 06:07:49 -04:00
|
|
|
else
|
|
|
|
{
|
|
|
|
selection->owner = event->owner;
|
2014-10-10 12:55:00 -04:00
|
|
|
|
2015-05-28 06:07:49 -04:00
|
|
|
if (selection->owner == selection->window)
|
|
|
|
{
|
|
|
|
/* This our own selection window */
|
|
|
|
selection->timestamp = event->timestamp;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_clear_pointer (&selection->x11_selection,
|
|
|
|
(GDestroyNotify) x11_selection_data_free);
|
2014-10-10 12:55:00 -04:00
|
|
|
|
2015-05-28 06:07:49 -04:00
|
|
|
XConvertSelection (xdisplay,
|
|
|
|
event->selection,
|
|
|
|
gdk_x11_get_xatom_by_name ("TARGETS"),
|
|
|
|
gdk_x11_get_xatom_by_name ("_META_SELECTION"),
|
|
|
|
selection->window,
|
2016-06-25 06:41:02 -04:00
|
|
|
CurrentTime);
|
2015-05-28 06:07:49 -04:00
|
|
|
XFlush (xdisplay);
|
|
|
|
}
|
2014-10-10 12:55:00 -04:00
|
|
|
}
|
2015-05-12 13:35:28 -04:00
|
|
|
else if (selection->selection_atom == xdnd_atoms[ATOM_DND_SELECTION])
|
|
|
|
{
|
|
|
|
MetaWaylandDataDevice *data_device = &compositor->seat->data_device;
|
|
|
|
MetaXWaylandSelection *selection_data = compositor->xwayland_manager.selection_data;
|
2016-09-06 06:49:03 -04:00
|
|
|
MetaWaylandSurface *focus;
|
2015-05-12 13:35:28 -04:00
|
|
|
|
|
|
|
selection->owner = event->owner;
|
2016-09-06 06:49:03 -04:00
|
|
|
focus = compositor->seat->pointer->focus_surface;
|
2015-05-12 13:35:28 -04:00
|
|
|
|
2016-09-06 06:49:03 -04:00
|
|
|
if (event->owner != None && event->owner != selection->window &&
|
|
|
|
focus && meta_xwayland_is_xwayland_surface (focus))
|
2015-05-12 13:35:28 -04:00
|
|
|
{
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
selection->source = meta_wayland_data_source_xwayland_new (selection);
|
2015-05-12 13:35:28 -04:00
|
|
|
meta_wayland_data_device_set_dnd_source (&compositor->seat->data_device,
|
|
|
|
selection->source);
|
|
|
|
|
|
|
|
meta_wayland_data_device_start_drag (data_device,
|
|
|
|
wl_resource_get_client (focus->resource),
|
|
|
|
&drag_xgrab_interface,
|
|
|
|
focus, selection->source,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
else if (event->owner == None)
|
|
|
|
{
|
|
|
|
meta_wayland_data_device_end_drag (data_device);
|
|
|
|
XUnmapWindow (xdisplay, selection_data->dnd.dnd_window);
|
|
|
|
}
|
|
|
|
}
|
2014-10-10 12:55:00 -04:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
meta_xwayland_selection_handle_event (XEvent *xevent)
|
|
|
|
{
|
|
|
|
MetaWaylandCompositor *compositor;
|
|
|
|
|
|
|
|
compositor = meta_wayland_compositor_get_default ();
|
|
|
|
|
|
|
|
if (!compositor->xwayland_manager.selection_data)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
switch (xevent->type)
|
|
|
|
{
|
|
|
|
case SelectionNotify:
|
|
|
|
return meta_xwayland_selection_handle_selection_notify (compositor, xevent);
|
|
|
|
case PropertyNotify:
|
|
|
|
return meta_xwayland_selection_handle_property_notify (compositor, xevent);
|
|
|
|
case SelectionRequest:
|
|
|
|
return meta_xwayland_selection_handle_selection_request (compositor, xevent);
|
2015-04-29 11:44:05 -04:00
|
|
|
case ClientMessage:
|
|
|
|
return meta_xwayland_selection_handle_client_message (compositor, xevent);
|
2014-10-10 12:55:00 -04:00
|
|
|
default:
|
|
|
|
{
|
|
|
|
MetaDisplay *display = meta_get_display ();
|
|
|
|
|
|
|
|
if (xevent->type - display->xfixes_event_base == XFixesSelectionNotify)
|
|
|
|
return meta_xwayland_selection_handle_xfixes_selection_notify (compositor, xevent);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_selection_bridge_ownership_notify (struct wl_listener *listener,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
|
|
|
MetaSelectionBridge *selection =
|
|
|
|
wl_container_of (listener, selection, ownership_listener);
|
|
|
|
MetaWaylandDataSource *owner = data;
|
|
|
|
|
|
|
|
if (!owner && selection->window == selection->owner)
|
|
|
|
{
|
2015-05-18 14:58:29 -04:00
|
|
|
XSetSelectionOwner (xdisplay, selection->selection_atom,
|
|
|
|
None, selection->timestamp);
|
2014-10-10 12:55:00 -04:00
|
|
|
}
|
2015-05-18 14:58:29 -04:00
|
|
|
else if (owner && selection->source != owner)
|
2014-10-10 12:55:00 -04:00
|
|
|
{
|
|
|
|
XSetSelectionOwner (xdisplay,
|
|
|
|
selection->selection_atom,
|
|
|
|
selection->window,
|
|
|
|
CurrentTime);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
init_selection_bridge (MetaSelectionBridge *selection,
|
|
|
|
Atom selection_atom,
|
|
|
|
struct wl_signal *signal)
|
|
|
|
{
|
|
|
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
|
|
|
XSetWindowAttributes attributes;
|
|
|
|
guint mask;
|
|
|
|
|
|
|
|
attributes.event_mask = PropertyChangeMask;
|
|
|
|
|
|
|
|
selection->ownership_listener.notify = meta_selection_bridge_ownership_notify;
|
|
|
|
wl_signal_add (signal, &selection->ownership_listener);
|
|
|
|
|
|
|
|
selection->selection_atom = selection_atom;
|
|
|
|
selection->window =
|
|
|
|
XCreateWindow (xdisplay,
|
|
|
|
gdk_x11_window_get_xid (gdk_get_default_root_window ()),
|
|
|
|
-1, -1, 1, 1, /* position */
|
|
|
|
0, /* border width */
|
|
|
|
0, /* depth */
|
|
|
|
InputOnly, /* class */
|
|
|
|
CopyFromParent, /* visual */
|
|
|
|
CWEventMask,
|
|
|
|
&attributes);
|
|
|
|
|
|
|
|
mask = XFixesSetSelectionOwnerNotifyMask |
|
|
|
|
XFixesSelectionWindowDestroyNotifyMask |
|
|
|
|
XFixesSelectionClientCloseNotifyMask;
|
|
|
|
|
|
|
|
XFixesSelectSelectionInput (xdisplay, selection->window,
|
|
|
|
selection_atom, mask);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shutdown_selection_bridge (MetaSelectionBridge *selection)
|
|
|
|
{
|
|
|
|
wl_list_remove (&selection->ownership_listener.link);
|
|
|
|
|
|
|
|
XDestroyWindow (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
|
|
|
|
selection->window);
|
|
|
|
g_clear_pointer (&selection->wayland_selection,
|
|
|
|
(GDestroyNotify) wayland_selection_data_free);
|
|
|
|
g_clear_pointer (&selection->x11_selection,
|
|
|
|
(GDestroyNotify) x11_selection_data_free);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_xwayland_init_selection (void)
|
|
|
|
{
|
|
|
|
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
|
|
|
MetaXWaylandManager *manager = &compositor->xwayland_manager;
|
|
|
|
|
|
|
|
g_assert (manager->selection_data == NULL);
|
|
|
|
|
|
|
|
manager->selection_data = g_slice_new0 (MetaXWaylandSelection);
|
|
|
|
|
2015-05-12 13:35:28 -04:00
|
|
|
meta_xwayland_init_dnd (manager);
|
2014-10-10 12:55:00 -04:00
|
|
|
init_selection_bridge (&manager->selection_data->clipboard,
|
|
|
|
gdk_x11_get_xatom_by_name ("CLIPBOARD"),
|
|
|
|
&compositor->seat->data_device.selection_ownership_signal);
|
2016-02-03 12:39:58 -05:00
|
|
|
init_selection_bridge (&manager->selection_data->primary,
|
|
|
|
gdk_x11_get_xatom_by_name ("PRIMARY"),
|
|
|
|
&compositor->seat->data_device.primary_ownership_signal);
|
2015-04-29 11:44:05 -04:00
|
|
|
init_selection_bridge (&manager->selection_data->dnd.selection,
|
|
|
|
xdnd_atoms[ATOM_DND_SELECTION],
|
|
|
|
&compositor->seat->data_device.dnd_ownership_signal);
|
2014-10-10 12:55:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_xwayland_shutdown_selection (void)
|
|
|
|
{
|
|
|
|
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
|
|
|
MetaXWaylandManager *manager = &compositor->xwayland_manager;
|
|
|
|
MetaXWaylandSelection *selection = manager->selection_data;
|
|
|
|
|
|
|
|
g_assert (selection != NULL);
|
|
|
|
|
wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.
An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.
This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.
Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.
https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-17 22:25:11 -04:00
|
|
|
g_clear_object (&selection->clipboard.source);
|
2014-10-10 12:55:00 -04:00
|
|
|
|
2015-05-12 13:35:28 -04:00
|
|
|
meta_xwayland_shutdown_dnd (manager);
|
2014-10-10 12:55:00 -04:00
|
|
|
shutdown_selection_bridge (&selection->clipboard);
|
2016-02-03 12:39:58 -05:00
|
|
|
shutdown_selection_bridge (&selection->primary);
|
2015-04-29 11:44:05 -04:00
|
|
|
shutdown_selection_bridge (&selection->dnd.selection);
|
2014-10-10 12:55:00 -04:00
|
|
|
|
|
|
|
g_slice_free (MetaXWaylandSelection, selection);
|
|
|
|
manager->selection_data = NULL;
|
|
|
|
}
|