diff --git a/src/wayland/meta-xwayland-dnd.c b/src/wayland/meta-xwayland-dnd.c index b3b94914d..0aa4c5efb 100644 --- a/src/wayland/meta-xwayland-dnd.c +++ b/src/wayland/meta-xwayland-dnd.c @@ -58,9 +58,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 @@ -134,6 +135,90 @@ 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, + MetaX11Display *x11_display) +{ + Display *xdisplay = meta_x11_display_get_xdisplay (x11_display); + 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, + meta_x11_display_get_xroot (x11_display), + -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, + MetaX11Display *x11_display) +{ + Display *xdisplay = meta_x11_display_get_xdisplay (x11_display); + 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, + MetaX11Display *x11_display, + int index) +{ + Display *xdisplay = meta_x11_display_get_xdisplay (x11_display); + + 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, + MetaX11Display *x11_display) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (dnd->dnd_window); i++) + hide_dnd_window (dnd, x11_display, i); +} + static void xdnd_send_enter (MetaXWaylandDnd *dnd, Window dest) @@ -296,7 +381,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) { @@ -326,7 +411,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); @@ -344,7 +429,7 @@ static void meta_xwayland_end_dnd_grab (MetaWaylandDataDevice *data_device, gboolean success) { - Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); + MetaX11Display *x11_display = meta_get_display ()->x11_display; MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); MetaXWaylandManager *manager = &compositor->xwayland_manager; MetaWaylandDragGrab *drag_grab = compositor->seat->data_device.current_grab; @@ -358,8 +443,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, x11_display); } static void @@ -654,7 +738,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; @@ -673,8 +758,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, x11_display, 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, @@ -682,8 +772,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, x11_display); } } @@ -950,10 +1039,10 @@ meta_xwayland_init_dnd (MetaX11Display *x11_display) { MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); MetaXWaylandManager *manager = &compositor->xwayland_manager; - Display *xdisplay = meta_x11_display_get_xdisplay (x11_display); + MetaXWaylandDnd *dnd = manager->dnd; - XSetWindowAttributes attributes; - guint32 i, version = XDND_VERSION; + + guint32 i; g_assert (manager->dnd == NULL); @@ -962,22 +1051,8 @@ meta_xwayland_init_dnd (MetaX11Display *x11_display) 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, - meta_x11_display_get_xroot (x11_display), - -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, x11_display); + dnd->current_dnd_window = 0; } void @@ -988,8 +1063,7 @@ meta_xwayland_shutdown_dnd (MetaXWaylandManager *manager, g_assert (dnd != NULL); - XDestroyWindow (meta_x11_display_get_xdisplay (x11_display), dnd->dnd_window); - dnd->dnd_window = None; + destroy_dnd_windows (dnd, x11_display); g_free (dnd); manager->dnd = NULL;