[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
This commit is contained in:
parent
522d2935e6
commit
4c18d156e2
3 changed files with 22 additions and 7 deletions
12
layers.cpp
12
layers.cpp
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue