summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wayland/meta-xwayland-dnd.c129
1 files changed, 99 insertions, 30 deletions
diff --git a/src/wayland/meta-xwayland-dnd.c b/src/wayland/meta-xwayland-dnd.c
index de61ccf73..fc0b0c297 100644
--- a/src/wayland/meta-xwayland-dnd.c
+++ b/src/wayland/meta-xwayland-dnd.c
@@ -57,9 +57,10 @@ struct _MetaXWaylandDnd
Time client_message_timestamp;
MetaWaylandDataSource *source; /* owned by MetaWaylandDataDevice */
MetaWaylandSurface *focus_surface;
- Window dnd_window; /* Mutter-internal window, acts as peer on wayland drop sites */
+ Window dnd_window[2]; /* Mutter-internal windows, act as peer on wayland drop sites */
Window dnd_dest; /* X11 drag dest window */
guint32 last_motion_time;
+ int current_dnd_window;
};
enum
@@ -133,6 +134,86 @@ atom_to_action (Atom atom)
return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
}
+static Window
+current_dnd_window (MetaXWaylandDnd *dnd)
+{
+ return dnd->dnd_window[dnd->current_dnd_window];
+}
+
+static Window
+next_dnd_window (MetaXWaylandDnd *dnd)
+{
+ dnd->current_dnd_window =
+ (dnd->current_dnd_window + 1) % G_N_ELEMENTS (dnd->dnd_window);
+
+ return current_dnd_window (dnd);
+}
+
+static void
+create_dnd_windows (MetaXWaylandDnd *dnd,
+ Display *xdisplay)
+{
+ XSetWindowAttributes attributes;
+ guint32 version = XDND_VERSION;
+ int i;
+
+ attributes.event_mask = PropertyChangeMask | SubstructureNotifyMask;
+ attributes.override_redirect = True;
+
+ for (i = 0; i < G_N_ELEMENTS (dnd->dnd_window); i++)
+ {
+ dnd->dnd_window[i] =
+ 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[i],
+ xdnd_atoms[ATOM_DND_AWARE],
+ XA_ATOM, 32, PropModeReplace,
+ (guchar*) &version, 1);
+ }
+}
+
+static void
+destroy_dnd_windows (MetaXWaylandDnd *dnd,
+ Display *xdisplay)
+{
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (dnd->dnd_window); i++)
+ {
+ XDestroyWindow (xdisplay, dnd->dnd_window[i]);
+ dnd->dnd_window[i] = None;
+ }
+}
+
+static void
+hide_dnd_window (MetaXWaylandDnd *dnd,
+ Display *xdisplay,
+ int index)
+{
+ g_assert (index < G_N_ELEMENTS (dnd->dnd_window));
+
+ XMoveResizeWindow (xdisplay, dnd->dnd_window[index], -1, -1, 1, 1);
+ XUnmapWindow (xdisplay, dnd->dnd_window[index]);
+}
+
+static void
+hide_all_dnd_windows (MetaXWaylandDnd *dnd,
+ Display *xdisplay)
+{
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (dnd->dnd_window); i++)
+ hide_dnd_window (dnd, xdisplay, i);
+}
+
static void
xdnd_send_enter (MetaXWaylandDnd *dnd,
Window dest)
@@ -295,7 +376,7 @@ xdnd_send_finished (MetaXWaylandDnd *dnd,
xev.xclient.format = 32;
xev.xclient.window = dest;
- xev.xclient.data.l[0] = dnd->dnd_window;
+ xev.xclient.data.l[0] = current_dnd_window (dnd);
if (accepted)
{
@@ -325,7 +406,7 @@ xdnd_send_status (MetaXWaylandDnd *dnd,
xev.xclient.format = 32;
xev.xclient.window = dest;
- xev.xclient.data.l[0] = dnd->dnd_window;
+ xev.xclient.data.l[0] = current_dnd_window (dnd);
xev.xclient.data.l[1] = 1 << 1; /* Bit 2: dest wants XdndPosition messages */
xev.xclient.data.l[4] = action_to_atom (action);
@@ -357,8 +438,7 @@ meta_xwayland_end_dnd_grab (MetaWaylandDataDevice *data_device,
meta_wayland_data_device_end_drag (data_device);
}
- XMoveResizeWindow (xdisplay, dnd->dnd_window, -1, -1, 1, 1);
- XUnmapWindow (xdisplay, dnd->dnd_window);
+ hide_all_dnd_windows (dnd, xdisplay);
}
static void
@@ -650,7 +730,8 @@ repick_drop_surface (MetaWaylandCompositor *compositor,
MetaWaylandDragGrab *drag_grab,
const ClutterEvent *event)
{
- Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+ MetaX11Display *x11_display = meta_get_display ()->x11_display;
+ Display *xdisplay = meta_x11_display_get_xdisplay (x11_display);
MetaXWaylandDnd *dnd = compositor->xwayland_manager.dnd;
MetaWaylandSurface *focus = NULL;
MetaWindow *focus_window;
@@ -669,8 +750,13 @@ repick_drop_surface (MetaWaylandCompositor *compositor,
if (focus_window &&
focus_window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
{
- XMapRaised (xdisplay, dnd->dnd_window);
- XMoveResizeWindow (xdisplay, dnd->dnd_window,
+ Window dnd_window;
+
+ hide_dnd_window (dnd, xdisplay, dnd->current_dnd_window);
+ dnd_window = next_dnd_window (dnd);
+
+ XMapRaised (xdisplay, dnd_window);
+ XMoveResizeWindow (xdisplay, dnd_window,
focus_window->rect.x,
focus_window->rect.y,
focus_window->rect.width,
@@ -678,8 +764,7 @@ repick_drop_surface (MetaWaylandCompositor *compositor,
}
else
{
- XMoveResizeWindow (xdisplay, dnd->dnd_window, -1, -1, 1, 1);
- XUnmapWindow (xdisplay, dnd->dnd_window);
+ hide_all_dnd_windows (dnd, xdisplay);
}
}
@@ -947,8 +1032,7 @@ meta_xwayland_init_dnd (Display *xdisplay)
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaXWaylandManager *manager = &compositor->xwayland_manager;
MetaXWaylandDnd *dnd = manager->dnd;
- XSetWindowAttributes attributes;
- guint32 i, version = XDND_VERSION;
+ guint32 i;
g_assert (manager->dnd == NULL);
@@ -957,22 +1041,8 @@ meta_xwayland_init_dnd (Display *xdisplay)
for (i = 0; i < N_DND_ATOMS; i++)
xdnd_atoms[i] = gdk_x11_get_xatom_by_name (atom_names[i]);
- 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);
+ create_dnd_windows (dnd, xdisplay);
+ dnd->current_dnd_window = 0;
}
void
@@ -984,8 +1054,7 @@ meta_xwayland_shutdown_dnd (Display *xdisplay)
g_assert (dnd != NULL);
- XDestroyWindow (xdisplay, dnd->dnd_window);
- dnd->dnd_window = None;
+ destroy_dnd_windows (dnd, xdisplay);
g_free (dnd);
manager->dnd = NULL;