Ignore setActive() for windows that are being deleted

We may call setActive() on a window that is being deleted. We cannot
guarantee that at that moment the X11 window or the Wayland surface is
still valid. So, the best course of actions is to do nothing.

BUG: 424255
This commit is contained in:
Vlad Zahorodnii 2020-07-16 10:17:19 +03:00
parent 6139ea7874
commit 4a6badc22c
7 changed files with 30 additions and 23 deletions

View file

@ -201,6 +201,9 @@ void AbstractClient::setIcon(const QIcon &icon)
void AbstractClient::setActive(bool act)
{
if (isZombie()) {
return;
}
if (m_active == act) {
return;
}
@ -235,6 +238,17 @@ void AbstractClient::doSetActive()
{
}
bool AbstractClient::isZombie() const
{
return m_zombie;
}
void AbstractClient::markAsZombie()
{
Q_ASSERT(!m_zombie);
m_zombie = true;
}
Layer AbstractClient::layer() const
{
if (m_layer == UnknownLayer)

View file

@ -358,6 +358,7 @@ public:
return m_icon;
}
bool isZombie() const;
bool isActive() const {
return m_active;
}
@ -927,6 +928,7 @@ protected:
void startAutoRaise();
void autoRaise();
bool isMostRecentlyRaised() const;
void markAsZombie();
/**
* Whether the window accepts focus.
* The difference to wantsInput is that the implementation should not check rules and return
@ -1237,6 +1239,7 @@ private:
bool m_skipSwitcher = false;
QIcon m_icon;
bool m_active = false;
bool m_zombie = false;
bool m_keepAbove = false;
bool m_keepBelow = false;
bool m_demandsAttention = false;

View file

@ -408,6 +408,7 @@ void InternalClient::showOnScreenEdge()
void InternalClient::destroyClient()
{
markAsZombie();
if (isMoveResize()) {
leaveMoveResize();
}

View file

@ -146,7 +146,6 @@ X11Client::X11Client()
info = nullptr;
deleting = false;
m_fullscreenMode = FullScreenNone;
hidden = false;
noborder = false;
@ -214,8 +213,7 @@ void X11Client::deleteClient(X11Client *c)
*/
void X11Client::releaseWindow(bool on_shutdown)
{
Q_ASSERT(!deleting);
deleting = true;
markAsZombie();
#ifdef KWIN_BUILD_TABBOX
TabBox::TabBox *tabBox = TabBox::TabBox::self();
if (tabBox->isDisplayed() && tabBox->currentClient() == this) {
@ -288,8 +286,7 @@ void X11Client::releaseWindow(bool on_shutdown)
*/
void X11Client::destroyClient()
{
Q_ASSERT(!deleting);
deleting = true;
markAsZombie();
#ifdef KWIN_BUILD_TABBOX
TabBox::TabBox *tabBox = TabBox::TabBox::self();
if (tabBox && tabBox->isDisplayed() && tabBox->currentClient() == this) {
@ -1099,7 +1096,7 @@ void X11Client::destroyDecoration()
move(grav);
if (compositing())
discardWindowPixmap();
if (!deleting) {
if (!isZombie()) {
emit geometryShapeChanged(this, oldgeom);
}
}
@ -1533,7 +1530,7 @@ void X11Client::doSetShade(ShadeMode previousShadeMode)
void X11Client::updateVisibility()
{
if (deleting)
if (isZombie())
return;
if (hidden) {
info->setState(NET::Hidden, NET::Hidden);
@ -1579,7 +1576,7 @@ void X11Client::updateVisibility()
void X11Client::exportMappingState(int s)
{
Q_ASSERT(m_client != XCB_WINDOW_NONE);
Q_ASSERT(!deleting || s == XCB_ICCCM_WM_STATE_WITHDRAWN);
Q_ASSERT(!isZombie() || s == XCB_ICCCM_WM_STATE_WITHDRAWN);
if (s == XCB_ICCCM_WM_STATE_WITHDRAWN) {
m_client.deleteProperty(atoms->wm_state);
return;
@ -2202,7 +2199,7 @@ void X11Client::fetchIconicName()
void X11Client::setClientShown(bool shown)
{
if (deleting)
if (isZombie())
return; // Don't change shown status if this client is being deleted
if (shown != hidden)
return; // nothing to change

View file

@ -491,7 +491,6 @@ private:
xcb_window_t m_transientForId;
xcb_window_t m_originalTransientForId;
X11Client *shade_below;
uint deleting : 1; ///< True when doing cleanup and destroying the client
Xcb::MotifHints m_motif;
uint hidden : 1; ///< Forcibly hidden by calling hide()
uint noborder : 1;

View file

@ -188,7 +188,7 @@ bool XdgSurfaceClient::stateCompare() const
void XdgSurfaceClient::scheduleConfigure()
{
if (isClosing()) {
if (isZombie()) {
return;
}
@ -518,7 +518,7 @@ void XdgSurfaceClient::addDamage(const QRegion &damage)
bool XdgSurfaceClient::isShown(bool shaded_is_shown) const
{
Q_UNUSED(shaded_is_shown)
return !isClosing() && !isHidden() && !isMinimized();
return !isZombie() && !isHidden() && !isMinimized();
}
bool XdgSurfaceClient::isHiddenInternal() const
@ -564,14 +564,9 @@ void XdgSurfaceClient::internalHide()
emit windowHidden(this);
}
bool XdgSurfaceClient::isClosing() const
{
return m_isClosing;
}
void XdgSurfaceClient::destroyClient()
{
m_isClosing = true;
markAsZombie();
m_configureTimer->stop();
if (isMoveResize()) {
leaveMoveResize();
@ -1076,7 +1071,7 @@ bool XdgToplevelClient::acceptsFocus() const
return m_plasmaShellSurface->panelTakesFocus();
}
}
return !isClosing() && readyForPainting();
return !isZombie() && readyForPainting();
}
Layer XdgToplevelClient::layerForDock() const
@ -1427,7 +1422,7 @@ void XdgToplevelClient::installServerDecoration(ServerSideDecorationInterface *d
m_serverDecoration = decoration;
connect(m_serverDecoration, &ServerSideDecorationInterface::destroyed, this, [this] {
if (!isClosing() && readyForPainting()) {
if (!isZombie() && readyForPainting()) {
updateDecoration(/* check_workspace_pos */ true);
}
});
@ -1449,7 +1444,7 @@ void XdgToplevelClient::installXdgDecoration(XdgToplevelDecorationV1Interface *d
m_xdgDecoration = decoration;
connect(m_xdgDecoration, &XdgToplevelDecorationV1Interface::destroyed, this, [this] {
if (!isClosing() && m_isInitialized) {
if (!isZombie() && m_isInitialized) {
updateDecoration(/* check_workspace_pos */ true);
}
});

View file

@ -82,7 +82,6 @@ public:
QRect requestedClientGeometry() const;
QSize requestedClientSize() const;
QRect clientGeometry() const;
bool isClosing() const;
bool isHidden() const;
protected:
@ -121,7 +120,6 @@ private:
QRect m_requestedFrameGeometry;
QRect m_bufferGeometry;
QRect m_requestedClientGeometry;
bool m_isClosing = false;
bool m_isHidden = false;
bool m_haveNextWindowGeometry = false;
};