Commit 0489d4a2 authored by Vlad Zahorodnii's avatar Vlad Zahorodnii
Browse files

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.
parent fa0143fb
......@@ -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;
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;
}
// 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();
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 &region)
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;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment