[xwl] Support stack optimizing X drag source clients

Summary:
Some X clients acting as drag sources might try to optimize finding the current
target window by checking if a window manager, that sets the root window
_NET_CLIENT_LIST_STACKING property, is present. An example for this is Chromium
and since KWin sets the property the drag proxy windows must be added to this
list. Otherwise the origin client will not detect the proxy window and not send
an XdndEnter message.

Test Plan: Manually with Chromium.

Reviewers: #kwin

Subscribers: zzag, kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D15628
icc-effect-5.17.5
Roman Gilg 2018-08-24 23:10:48 +02:00
parent 522d2935e6
commit 4c18d156e2
3 changed files with 22 additions and 7 deletions

View File

@ -170,6 +170,8 @@ void Workspace::propagateClients(bool propagate_new_clients)
newWindowStack << ScreenEdges::self()->windows();
newWindowStack << manual_overlays;
newWindowStack.reserve(newWindowStack.size() + 2*stacking_order.size()); // *2 for inputWindow
for (int i = stacking_order.size() - 1; i >= 0; --i) {
@ -202,7 +204,10 @@ void Workspace::propagateClients(bool propagate_new_clients)
int pos = 0;
xcb_window_t *cl(nullptr);
if (propagate_new_clients) {
cl = new xcb_window_t[ desktops.count() + clients.count()];
cl = new xcb_window_t[ manual_overlays.count() + desktops.count() + clients.count()];
for (const auto win : manual_overlays) {
cl[pos++] = win;
}
// TODO this is still not completely in the map order
for (ClientList::ConstIterator it = desktops.constBegin(); it != desktops.constEnd(); ++it)
cl[pos++] = (*it)->window();
@ -212,12 +217,15 @@ void Workspace::propagateClients(bool propagate_new_clients)
delete [] cl;
}
cl = new xcb_window_t[ stacking_order.count()];
cl = new xcb_window_t[ manual_overlays.count() + stacking_order.count()];
pos = 0;
for (ToplevelList::ConstIterator it = stacking_order.constBegin(); it != stacking_order.constEnd(); ++it) {
if ((*it)->isClient())
cl[pos++] = (*it)->window();
}
for (const auto win : manual_overlays) {
cl[pos++] = win;
}
rootInfo()->setClientListStacking(cl, pos);
delete [] cl;

View File

@ -278,6 +278,13 @@ public:
void windowToNextDesktop(AbstractClient* c);
void sendClientToScreen(AbstractClient* c, int screen);
void addManualOverlay(xcb_window_t id) {
manual_overlays << id;
}
void removeManualOverlay(xcb_window_t id) {
manual_overlays.removeOne(id);
}
/**
* Shows the menu operations menu for the client and makes it active if
* it's not already.
@ -564,6 +571,7 @@ private:
ToplevelList unconstrained_stacking_order; // Topmost last
ToplevelList stacking_order; // Topmost last
QVector<xcb_window_t> manual_overlays; //Topmost last
bool force_restacking;
ToplevelList x_stacking; // From XQueryTree()
std::unique_ptr<Xcb::Tree> m_xStackingQueryTree;

View File

@ -316,12 +316,9 @@ WlVisit::WlVisit(AbstractClient *target, XToWlDrag *drag)
32, 1, &version);
xcb_map_window(xcbConn, m_window);
workspace()->addManualOverlay(m_window);
workspace()->updateStackingOrder(true);
const uint32_t stackValues[] = { XCB_STACK_MODE_ABOVE };
xcb_configure_window (xcbConn,
m_window,
XCB_CONFIG_WINDOW_STACK_MODE,
stackValues);
xcb_flush(xcbConn);
m_mapped = true;
}
@ -541,6 +538,8 @@ void WlVisit::unmapProxyWindow()
}
auto *xcbConn = kwinApp()->x11Connection();
xcb_unmap_window(xcbConn, m_window);
workspace()->removeManualOverlay(m_window);
workspace()->updateStackingOrder(true);
xcb_flush(xcbConn);
m_mapped = false;
}