diff options
-rw-r--r-- | src/wayland/meta-xwayland-dnd.c | 129 |
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; |