Merge Workspace::stackingOrder() and Workspace::xStackingOrder()
The Workspace has two stacks - one with managed windows and deleted windows, the other includes windows from the first stack + override redirect windows. This change merges both stacks. It has several benefits - we will be able to move window elevation stuff to Workspace and streamline the scene stuff, for example it will be possible to have a root item. Another advantage is that unmanaged windows will have Window::stackingOrder() property set, which can be useful in the future in qml effects or (qtquick scene if we push harder in that front). Another advantage is that kwin will make less X11 calls when restacking managed windows.
This commit is contained in:
parent
fa0143fb97
commit
0489d4a2f6
11 changed files with 41 additions and 73 deletions
|
@ -364,7 +364,6 @@ void Compositor::startupWithWorkspace()
|
|||
this, &Compositor::cleanupX11, Qt::UniqueConnection);
|
||||
initializeX11();
|
||||
|
||||
Workspace::self()->markXStackingOrderAsDirty();
|
||||
Q_ASSERT(m_scene);
|
||||
m_scene->initialize();
|
||||
|
||||
|
@ -891,7 +890,7 @@ void X11Compositor::composite(RenderLoop *renderLoop)
|
|||
return;
|
||||
}
|
||||
|
||||
QList<Window *> windows = Workspace::self()->xStackingOrder();
|
||||
QList<Window *> windows = workspace()->stackingOrder();
|
||||
QList<SurfaceItemX11 *> dirtyItems;
|
||||
|
||||
// Reset the damage state of each window and fetch the damage region
|
||||
|
|
|
@ -1110,7 +1110,7 @@ EffectWindow *EffectsHandlerImpl::findWindow(const QUuid &id) const
|
|||
|
||||
EffectWindowList EffectsHandlerImpl::stackingOrder() const
|
||||
{
|
||||
QList<Window *> list = Workspace::self()->xStackingOrder();
|
||||
QList<Window *> list = workspace()->stackingOrder();
|
||||
EffectWindowList ret;
|
||||
for (Window *t : list) {
|
||||
if (EffectWindow *w = t->effectWindow()) {
|
||||
|
|
|
@ -154,14 +154,12 @@ bool Workspace::workspaceEvent(xcb_generic_event_t *e)
|
|||
return false; // let Qt process it, it'll be intercepted again in eventFilter()
|
||||
}
|
||||
|
||||
// events that should be handled before windows can get them
|
||||
switch (eventType) {
|
||||
case XCB_CONFIGURE_NOTIFY:
|
||||
if (reinterpret_cast<xcb_configure_notify_event_t *>(e)->event == kwinApp()->x11RootWindow()) {
|
||||
markXStackingOrderAsDirty();
|
||||
if (eventType == XCB_CONFIGURE_NOTIFY) {
|
||||
const auto configureNotifyEvent = reinterpret_cast<xcb_configure_notify_event_t *>(e);
|
||||
if (configureNotifyEvent->override_redirect && configureNotifyEvent->event == kwinApp()->x11RootWindow()) {
|
||||
updateXStackingOrder();
|
||||
}
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
const xcb_window_t eventWindow = findEventWindow(e);
|
||||
if (eventWindow != XCB_WINDOW_NONE) {
|
||||
|
|
|
@ -108,7 +108,6 @@ void Workspace::updateStackingOrder(bool propagate_new_windows)
|
|||
stacking_order = new_stacking_order;
|
||||
if (changed || propagate_new_windows) {
|
||||
propagateWindows(propagate_new_windows);
|
||||
markXStackingOrderAsDirty();
|
||||
|
||||
for (int i = 0; i < stacking_order.size(); ++i) {
|
||||
stacking_order[i]->setStackingOrder(i);
|
||||
|
@ -628,15 +627,6 @@ QList<Window *> Workspace::ensureStackingOrder(const QList<Window *> &list) cons
|
|||
return ensureStackingOrderInList(stacking_order, list);
|
||||
}
|
||||
|
||||
// Returns all windows in their stacking order on the root window.
|
||||
QList<Window *> Workspace::xStackingOrder() const
|
||||
{
|
||||
if (m_xStackingDirty) {
|
||||
const_cast<Workspace *>(this)->updateXStackingOrder();
|
||||
}
|
||||
return x_stacking;
|
||||
}
|
||||
|
||||
QList<Window *> Workspace::unconstrainedStackingOrder() const
|
||||
{
|
||||
return unconstrained_stacking_order;
|
||||
|
@ -644,30 +634,27 @@ QList<Window *> Workspace::unconstrainedStackingOrder() const
|
|||
|
||||
void Workspace::updateXStackingOrder()
|
||||
{
|
||||
// use our own stacking order, not the X one, as they may differ
|
||||
x_stacking = stacking_order;
|
||||
// we use our stacking order for managed windows, but X's for override-redirect windows
|
||||
Xcb::Tree tree(kwinApp()->x11RootWindow());
|
||||
xcb_window_t *windows = tree.children();
|
||||
|
||||
if (m_xStackingQueryTree && !m_xStackingQueryTree->isNull()) {
|
||||
std::unique_ptr<Xcb::Tree> tree{std::move(m_xStackingQueryTree)};
|
||||
xcb_window_t *windows = tree->children();
|
||||
const auto count = tree->data()->children_len;
|
||||
int foundUnmanagedCount = m_unmanaged.count();
|
||||
for (unsigned int i = 0; i < count; ++i) {
|
||||
for (auto it = m_unmanaged.constBegin(); it != m_unmanaged.constEnd(); ++it) {
|
||||
Unmanaged *u = *it;
|
||||
if (u->window() == windows[i]) {
|
||||
x_stacking.append(u);
|
||||
foundUnmanagedCount--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (foundUnmanagedCount == 0) {
|
||||
break;
|
||||
}
|
||||
const auto count = tree.data()->children_len;
|
||||
int remainingCount = m_unmanaged.count();
|
||||
for (unsigned int i = 0; i < count; ++i) {
|
||||
auto window = findUnmanaged(windows[i]);
|
||||
if (window) {
|
||||
unconstrained_stacking_order.removeAll(window);
|
||||
unconstrained_stacking_order.append(window);
|
||||
remainingCount--;
|
||||
}
|
||||
if (remainingCount == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_xStackingDirty = false;
|
||||
if (!m_unmanaged.isEmpty()) {
|
||||
updateStackingOrder();
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************
|
||||
|
|
|
@ -546,7 +546,7 @@ void Scene::paintSimpleScreen(int, const QRegion ®ion)
|
|||
void Scene::createStackingOrder()
|
||||
{
|
||||
// Create a list of all windows in the stacking order
|
||||
QList<Window *> windows = Workspace::self()->xStackingOrder();
|
||||
QList<Window *> windows = workspace()->stackingOrder();
|
||||
|
||||
// Move elevated windows to the top of the stacking order
|
||||
const QList<EffectWindow *> elevatedList = static_cast<EffectsHandlerImpl *>(effects)->elevatedWindows();
|
||||
|
|
|
@ -214,6 +214,11 @@ bool Unmanaged::isOutline() const
|
|||
return m_outline;
|
||||
}
|
||||
|
||||
bool Unmanaged::isUnmanaged() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
QWindow *Unmanaged::findInternalWindow() const
|
||||
{
|
||||
const QWindowList windows = kwinApp()->topLevelWindows();
|
||||
|
|
|
@ -30,12 +30,9 @@ public:
|
|||
QStringList activities() const override;
|
||||
QVector<VirtualDesktop *> desktops() const override;
|
||||
QPoint clientPos() const override;
|
||||
Layer layer() const override
|
||||
{
|
||||
return UnmanagedLayer;
|
||||
}
|
||||
NET::WindowType windowType(bool direct = false, int supported_types = 0) const override;
|
||||
bool isOutline() const override;
|
||||
bool isUnmanaged() const override;
|
||||
|
||||
QString captionNormal() const override { return {}; }
|
||||
QString captionSuffix() const override { return {}; }
|
||||
|
|
|
@ -533,6 +533,11 @@ bool Window::isClient() const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Window::isUnmanaged() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Window::isDeleted() const
|
||||
{
|
||||
return false;
|
||||
|
@ -902,7 +907,7 @@ Layer Window::belongsToLayer() const
|
|||
// and the docks move into the NotificationLayer (which is between Above- and
|
||||
// ActiveLayer, so that active fullscreen windows will still cover everything)
|
||||
// Since the desktop is also activated, nothing should be in the ActiveLayer, though
|
||||
if (isInternal()) {
|
||||
if (isUnmanaged() || isInternal()) {
|
||||
return UnmanagedLayer;
|
||||
}
|
||||
if (isLockScreen()) {
|
||||
|
|
|
@ -640,6 +640,7 @@ public:
|
|||
QRect visibleGeometry() const;
|
||||
virtual bool isClient() const;
|
||||
virtual bool isDeleted() const;
|
||||
virtual bool isUnmanaged() const;
|
||||
|
||||
/**
|
||||
* Maps the specified @a point from the global screen coordinates to the frame coordinates.
|
||||
|
|
|
@ -467,7 +467,6 @@ void Workspace::cleanupX11()
|
|||
m_nullFocus.reset();
|
||||
m_syncAlarmFilter.reset();
|
||||
m_wasUserInteractionFilter.reset();
|
||||
m_xStackingQueryTree.reset();
|
||||
}
|
||||
|
||||
Workspace::~Workspace()
|
||||
|
@ -698,7 +697,6 @@ void Workspace::addX11Window(X11Window *window)
|
|||
m_x11Clients.append(window);
|
||||
m_allClients.append(window);
|
||||
addToStack(window);
|
||||
markXStackingOrderAsDirty();
|
||||
updateClientArea(); // This cannot be in manage(), because the window got added only now
|
||||
window->updateLayer();
|
||||
if (window->isDesktop()) {
|
||||
|
@ -720,7 +718,7 @@ void Workspace::addX11Window(X11Window *window)
|
|||
void Workspace::addUnmanaged(Unmanaged *window)
|
||||
{
|
||||
m_unmanaged.append(window);
|
||||
markXStackingOrderAsDirty();
|
||||
addToStack(window);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -749,8 +747,8 @@ void Workspace::removeUnmanaged(Unmanaged *window)
|
|||
{
|
||||
Q_ASSERT(m_unmanaged.contains(window));
|
||||
m_unmanaged.removeAll(window);
|
||||
removeFromStack(window);
|
||||
Q_EMIT unmanagedRemoved(window);
|
||||
markXStackingOrderAsDirty();
|
||||
}
|
||||
|
||||
void Workspace::addDeleted(Deleted *c, Window *orig)
|
||||
|
@ -758,7 +756,6 @@ void Workspace::addDeleted(Deleted *c, Window *orig)
|
|||
Q_ASSERT(!deleted.contains(c));
|
||||
deleted.append(c);
|
||||
replaceInStack(orig, c);
|
||||
markXStackingOrderAsDirty();
|
||||
}
|
||||
|
||||
void Workspace::removeDeleted(Deleted *c)
|
||||
|
@ -767,7 +764,6 @@ void Workspace::removeDeleted(Deleted *c)
|
|||
Q_EMIT deletedRemoved(c);
|
||||
deleted.removeAll(c);
|
||||
removeFromStack(c);
|
||||
markXStackingOrderAsDirty();
|
||||
if (!c->wasClient()) {
|
||||
return;
|
||||
}
|
||||
|
@ -800,7 +796,6 @@ void Workspace::addWaylandWindow(Window *window)
|
|||
m_allClients.append(window);
|
||||
addToStack(window);
|
||||
|
||||
markXStackingOrderAsDirty();
|
||||
updateStackingOrder(true);
|
||||
updateClientArea();
|
||||
if (window->wantsInput() && !window->isMinimized()) {
|
||||
|
@ -809,7 +804,6 @@ void Workspace::addWaylandWindow(Window *window)
|
|||
updateTabbox();
|
||||
connect(window, &Window::windowShown, this, [this, window] {
|
||||
window->updateLayer();
|
||||
markXStackingOrderAsDirty();
|
||||
updateStackingOrder(true);
|
||||
updateClientArea();
|
||||
if (window->wantsInput()) {
|
||||
|
@ -818,7 +812,6 @@ void Workspace::addWaylandWindow(Window *window)
|
|||
});
|
||||
connect(window, &Window::windowHidden, this, [this] {
|
||||
// TODO: update tabbox if it's displayed
|
||||
markXStackingOrderAsDirty();
|
||||
updateStackingOrder(true);
|
||||
updateClientArea();
|
||||
});
|
||||
|
@ -854,7 +847,6 @@ void Workspace::removeAbstractClient(Window *window)
|
|||
}
|
||||
|
||||
Q_EMIT windowRemoved(window);
|
||||
markXStackingOrderAsDirty();
|
||||
|
||||
updateStackingOrder(true);
|
||||
updateClientArea();
|
||||
|
@ -1235,7 +1227,7 @@ void Workspace::slotOutputDisabled(Output *output)
|
|||
disconnect(output, &Output::geometryChanged, this, &Workspace::desktopResized);
|
||||
desktopResized();
|
||||
|
||||
const auto stack = xStackingOrder();
|
||||
const auto stack = stackingOrder();
|
||||
for (Window *window : stack) {
|
||||
if (window->output() == output) {
|
||||
window->setOutput(kwinApp()->platform()->outputAt(window->frameGeometry().center()));
|
||||
|
@ -1884,14 +1876,6 @@ Window *Workspace::findInternal(QWindow *w) const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void Workspace::markXStackingOrderAsDirty()
|
||||
{
|
||||
m_xStackingDirty = true;
|
||||
if (kwinApp()->x11Connection() && !kwinApp()->isClosingX11Connection()) {
|
||||
m_xStackingQueryTree.reset(new Xcb::Tree(kwinApp()->x11RootWindow()));
|
||||
}
|
||||
}
|
||||
|
||||
void Workspace::setWasUserInteraction()
|
||||
{
|
||||
if (was_user_interaction) {
|
||||
|
@ -1928,7 +1912,6 @@ void Workspace::addInternalWindow(InternalWindow *window)
|
|||
Placement::self()->place(window, area);
|
||||
}
|
||||
|
||||
markXStackingOrderAsDirty();
|
||||
updateStackingOrder(true);
|
||||
updateClientArea();
|
||||
|
||||
|
@ -1939,7 +1922,6 @@ void Workspace::removeInternalWindow(InternalWindow *window)
|
|||
{
|
||||
m_internalWindows.removeOne(window);
|
||||
|
||||
markXStackingOrderAsDirty();
|
||||
updateStackingOrder(true);
|
||||
updateClientArea();
|
||||
|
||||
|
|
|
@ -280,7 +280,6 @@ public:
|
|||
* at the last position
|
||||
*/
|
||||
const QList<Window *> &stackingOrder() const;
|
||||
QList<Window *> xStackingOrder() const;
|
||||
QList<Window *> unconstrainedStackingOrder() const;
|
||||
QList<X11Window *> ensureStackingOrder(const QList<X11Window *> &windows) const;
|
||||
QList<Window *> ensureStackingOrder(const QList<Window *> &windows) const;
|
||||
|
@ -388,8 +387,6 @@ public:
|
|||
return m_moveResizeWindow;
|
||||
}
|
||||
|
||||
void markXStackingOrderAsDirty();
|
||||
|
||||
void quickTileWindow(QuickTileMode mode);
|
||||
|
||||
enum Direction {
|
||||
|
@ -630,9 +627,6 @@ private:
|
|||
QList<Window *> stacking_order; // Topmost last
|
||||
QVector<xcb_window_t> manual_overlays; // Topmost last
|
||||
bool force_restacking;
|
||||
QList<Window *> x_stacking; // From XQueryTree()
|
||||
std::unique_ptr<Xcb::Tree> m_xStackingQueryTree;
|
||||
bool m_xStackingDirty = false;
|
||||
QList<Window *> should_get_focus; // Last is most recent
|
||||
QList<Window *> attention_chain;
|
||||
|
||||
|
|
Loading…
Reference in a new issue