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.
This commit is contained in:
Vlad Zahorodnii 2023-02-26 13:41:11 +02:00
parent d563382350
commit 2dca6cd003
10 changed files with 47 additions and 42 deletions

View file

@ -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);
}

View file

@ -81,6 +81,10 @@ public:
{
return m_window;
}
void setWindow(Window *window)
{
m_window = window;
}
KDecoration2::DecoratedClient *decoratedClient()
{
return KDecoration2::DecoratedClientPrivate::client();

View file

@ -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;

View file

@ -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<VirtualDesktop *> 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<VirtualDesktop *> m_desktops;
QRectF decoration_left;
QRectF decoration_right;
QRectF decoration_top;
QRectF decoration_bottom;
Layer m_layer;
bool m_shade;
QList<Window *> m_mainWindows;

View file

@ -367,8 +367,6 @@ void InternalWindow::destroyWindow()
Deleted *deleted = Deleted::create(this);
Q_EMIT closed(deleted);
destroyDecoration();
workspace()->removeInternalWindow(this);
m_handle = nullptr;

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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<WinInfo *>(info)) {

View file

@ -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);