From 2dca6cd003b344614551d249f146eae22e1eb47b Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Sun, 26 Feb 2023 13:41:11 +0200 Subject: [PATCH] Extend lifetime of decoration to lifetime of Deleted When a window is closed, a Deleted object will be constructed and the Window's properties will be copied over to it. The long term plan is to stop doing that, i.e. keep the Window alive but just flip a few flags to indicate that it's been closed. In order to unify decoration management, this change ensures that it's okay to have decorations live as long as the Deleted. --- src/decorations/decoratedclient.cpp | 27 +++++++++++++++++++++++++++ src/decorations/decoratedclient.h | 4 ++++ src/deleted.cpp | 20 -------------------- src/deleted.h | 8 -------- src/internalwindow.cpp | 2 -- src/scene/decorationitem.cpp | 4 ---- src/window.cpp | 11 ++++++++++- src/window.h | 4 ++-- src/x11window.cpp | 5 ++--- src/xdgshellwindow.cpp | 4 ++-- 10 files changed, 47 insertions(+), 42 deletions(-) diff --git a/src/decorations/decoratedclient.cpp b/src/decorations/decoratedclient.cpp index 91189019a6..bcbafb6e12 100644 --- a/src/decorations/decoratedclient.cpp +++ b/src/decorations/decoratedclient.cpp @@ -139,6 +139,9 @@ DELEGATE(WId, decorationId, frameId) #define DELEGATE(name, op) \ void DecoratedClientImpl::name() \ { \ + if (m_window->isDeleted()) { \ + return; \ + } \ Workspace::self()->performWindowOperation(m_window, Options::op); \ } @@ -152,6 +155,9 @@ DELEGATE(requestToggleKeepBelow, KeepBelowOp) #define DELEGATE(name, clientName) \ void DecoratedClientImpl::name() \ { \ + if (m_window->isDeleted()) { \ + return; \ + } \ m_window->clientName(); \ } @@ -166,6 +172,9 @@ void DecoratedClientImpl::requestMinimize() void DecoratedClientImpl::requestClose() { + if (m_window->isDeleted()) { + return; + } QMetaObject::invokeMethod(m_window, &Window::closeWindow, Qt::QueuedConnection); } @@ -181,6 +190,9 @@ QColor DecoratedClientImpl::color(KDecoration2::ColorGroup group, KDecoration2:: void DecoratedClientImpl::requestShowToolTip(const QString &text) { + if (m_window->isDeleted()) { + return; + } if (!workspace()->decorationBridge()->showToolTips()) { return; } @@ -200,21 +212,33 @@ void DecoratedClientImpl::requestHideToolTip() void DecoratedClientImpl::requestShowWindowMenu(const QRect &rect) { + if (m_window->isDeleted()) { + return; + } Workspace::self()->showWindowMenu(QRectF(m_window->pos() + rect.topLeft(), m_window->pos() + rect.bottomRight()).toRect(), m_window); } void DecoratedClientImpl::requestShowApplicationMenu(const QRect &rect, int actionId) { + if (m_window->isDeleted()) { + return; + } Workspace::self()->showApplicationMenu(rect, m_window, actionId); } void DecoratedClientImpl::showApplicationMenu(int actionId) { + if (m_window->isDeleted()) { + return; + } decoration()->showApplicationMenu(actionId); } void DecoratedClientImpl::requestToggleMaximization(Qt::MouseButtons buttons) { + if (m_window->isDeleted()) { + return; + } auto operation = options->operationMaxButtonClick(buttons); QMetaObject::invokeMethod( this, [this, operation] { @@ -225,6 +249,9 @@ void DecoratedClientImpl::requestToggleMaximization(Qt::MouseButtons buttons) void DecoratedClientImpl::delayedRequestToggleMaximization(Options::WindowOperation operation) { + if (m_window->isDeleted()) { + return; + } Workspace::self()->performWindowOperation(m_window, operation); } diff --git a/src/decorations/decoratedclient.h b/src/decorations/decoratedclient.h index 9bd5907a46..68fbb09bee 100644 --- a/src/decorations/decoratedclient.h +++ b/src/decorations/decoratedclient.h @@ -81,6 +81,10 @@ public: { return m_window; } + void setWindow(Window *window) + { + m_window = window; + } KDecoration2::DecoratedClient *decoratedClient() { return KDecoration2::DecoratedClientPrivate::client(); diff --git a/src/deleted.cpp b/src/deleted.cpp index b552803e4a..2b99c5e257 100644 --- a/src/deleted.cpp +++ b/src/deleted.cpp @@ -56,7 +56,6 @@ void Deleted::copyToDeleted(Window *window) { Q_ASSERT(!window->isDeleted()); Window::copyToDeleted(window); - m_frameMargins = window->frameMargins(); desk = window->desktop(); m_desktops = window->desktops(); activityList = window->activities(); @@ -66,12 +65,6 @@ void Deleted::copyToDeleted(Window *window) m_type = window->windowType(); m_windowRole = window->windowRole(); m_shade = window->isShade(); - if (window->isDecorated()) { - window->layoutDecorationRects(decoration_left, - decoration_top, - decoration_right, - decoration_bottom); - } m_mainWindows = window->mainWindows(); for (Window *w : std::as_const(m_mainWindows)) { connect(w, &Window::closed, this, &Deleted::mainWindowClosed); @@ -90,11 +83,6 @@ void Deleted::copyToDeleted(Window *window) m_wasLockScreen = window->isLockScreen(); } -QMargins Deleted::frameMargins() const -{ - return m_frameMargins; -} - int Deleted::desktop() const { return desk; @@ -115,14 +103,6 @@ QPointF Deleted::clientPos() const return contentsRect.topLeft(); } -void Deleted::layoutDecorationRects(QRectF &left, QRectF &top, QRectF &right, QRectF &bottom) const -{ - left = decoration_left; - top = decoration_top; - right = decoration_right; - bottom = decoration_bottom; -} - bool Deleted::isDeleted() const { return true; diff --git a/src/deleted.h b/src/deleted.h index cb1e594a5e..f4f179efe3 100644 --- a/src/deleted.h +++ b/src/deleted.h @@ -21,14 +21,12 @@ class KWIN_EXPORT Deleted : public Window public: static Deleted *create(Window *c); - QMargins frameMargins() const override; int desktop() const override; QStringList activities() const override; QVector desktops() const override; QPointF clientPos() const override; bool isDeleted() const override; xcb_window_t frameId() const override; - void layoutDecorationRects(QRectF &left, QRectF &top, QRectF &right, QRectF &bottom) const override; Layer layer() const override { return m_layer; @@ -107,18 +105,12 @@ private: void copyToDeleted(Window *c); ~Deleted() override; // deleted only using unrefWindow() - QMargins m_frameMargins; - int desk; QStringList activityList; QRectF contentsRect; // for clientPos()/clientSize() xcb_window_t m_frame; QVector m_desktops; - QRectF decoration_left; - QRectF decoration_right; - QRectF decoration_top; - QRectF decoration_bottom; Layer m_layer; bool m_shade; QList m_mainWindows; diff --git a/src/internalwindow.cpp b/src/internalwindow.cpp index c0da0020f2..77d55c27ac 100644 --- a/src/internalwindow.cpp +++ b/src/internalwindow.cpp @@ -367,8 +367,6 @@ void InternalWindow::destroyWindow() Deleted *deleted = Deleted::create(this); Q_EMIT closed(deleted); - destroyDecoration(); - workspace()->removeInternalWindow(this); m_handle = nullptr; diff --git a/src/scene/decorationitem.cpp b/src/scene/decorationitem.cpp index 5798277f5b..c483f6dba7 100644 --- a/src/scene/decorationitem.cpp +++ b/src/scene/decorationitem.cpp @@ -168,10 +168,6 @@ void DecorationItem::handleFrameGeometryChanged() void DecorationItem::handleWindowClosed(Window *deleted) { m_window = deleted; - - // If the decoration is about to be destroyed, render the decoration for the last time. - effects->makeOpenGLContextCurrent(); - preprocess(); } DecorationRenderer *DecorationItem::renderer() const diff --git a/src/window.cpp b/src/window.cpp index ee8bfe11d7..37757aba60 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -126,7 +126,6 @@ Window::~Window() m_tile->removeWindow(this); } Q_ASSERT(m_blockGeometryUpdates == 0); - Q_ASSERT(m_decoration.decoration == nullptr); delete info; } @@ -224,6 +223,16 @@ void Window::copyToDeleted(Window *c) m_modal = c->m_modal; m_keepAbove = c->m_keepAbove; m_keepBelow = c->m_keepBelow; + m_active = c->m_active; + m_palette = c->m_palette; + if (c->m_decoration.decoration) { + c->m_decoration.decoration->setParent(this); + m_decoration.decoration = c->m_decoration.decoration; + } + if (c->m_decoration.client) { + c->m_decoration.client->setWindow(this); + m_decoration.client = c->m_decoration.client; + } } // before being deleted, remove references to everything that's now diff --git a/src/window.h b/src/window.h index ee0b188f29..52649c3dea 100644 --- a/src/window.h +++ b/src/window.h @@ -592,7 +592,7 @@ public: * * Default implementation returns a margins object with all margins set to 0. */ - virtual QMargins frameMargins() const; + QMargins frameMargins() const; /** * The geometry of the Window which accepts input events. This might be larger * than the actual geometry, e.g. to support resizing outside the window. @@ -1237,7 +1237,7 @@ public: void setDecoratedClient(Decoration::DecoratedClientImpl *client); bool decorationHasAlpha() const; void triggerDecorationRepaint(); - virtual void layoutDecorationRects(QRectF &left, QRectF &top, QRectF &right, QRectF &bottom) const; + void layoutDecorationRects(QRectF &left, QRectF &top, QRectF &right, QRectF &bottom) const; void processDecorationMove(const QPointF &localPos, const QPointF &globalPos); bool processDecorationButtonPress(QMouseEvent *event, bool ignoreMenu = false); void processDecorationButtonRelease(QMouseEvent *event); diff --git a/src/x11window.cpp b/src/x11window.cpp index f236a76770..6f681dda29 100644 --- a/src/x11window.cpp +++ b/src/x11window.cpp @@ -386,7 +386,6 @@ void X11Window::releaseWindow(bool on_shutdown) workspace()->windowHidden(this); } m_frame.unmap(); // Destroying decoration would cause ugly visual effect - destroyDecoration(); cleanGrouping(); workspace()->removeX11Window(this); if (!on_shutdown) { @@ -401,7 +400,8 @@ void X11Window::releaseWindow(bool on_shutdown) m_client.deleteProperty(atoms->kde_net_wm_user_creation_time); m_client.deleteProperty(atoms->net_frame_extents); m_client.deleteProperty(atoms->kde_net_wm_frame_strut); - m_client.reparent(kwinApp()->x11RootWindow(), m_bufferGeometry.x(), m_bufferGeometry.y()); + const QPointF grav = calculateGravitation(true); + m_client.reparent(kwinApp()->x11RootWindow(), grav.x(), grav.y()); xcb_change_save_set(c, XCB_SET_MODE_DELETE, m_client); m_client.selectInput(XCB_EVENT_MASK_NO_EVENT); if (on_shutdown) { @@ -450,7 +450,6 @@ void X11Window::destroyWindow() setModal(false); hidden = true; // So that it's not considered visible anymore workspace()->windowHidden(this); - destroyDecoration(); cleanGrouping(); workspace()->removeX11Window(this); if (WinInfo *cinfo = dynamic_cast(info)) { diff --git a/src/xdgshellwindow.cpp b/src/xdgshellwindow.cpp index 7b1f8f7f81..17ad39f548 100644 --- a/src/xdgshellwindow.cpp +++ b/src/xdgshellwindow.cpp @@ -90,7 +90,6 @@ XdgSurfaceWindow::XdgSurfaceWindow(XdgSurfaceInterface *shellSurface) XdgSurfaceWindow::~XdgSurfaceWindow() { - qDeleteAll(m_configureEvents); } NET::WindowType XdgSurfaceWindow::windowType(bool direct, int supported_types) const @@ -294,12 +293,13 @@ void XdgSurfaceWindow::destroyWindow() Q_EMIT interactiveMoveResizeFinished(); } m_configureTimer->stop(); + qDeleteAll(m_configureEvents); + m_configureEvents.clear(); cleanTabBox(); Deleted *deleted = Deleted::create(this); Q_EMIT closed(deleted); StackingUpdatesBlocker blocker(workspace()); workspace()->rulebook()->discardUsed(this, true); - setDecoration(nullptr); cleanGrouping(); waylandServer()->removeWindow(this);