From 1177ef372039221c5b0cec56fff4a36cde44a0c1 Mon Sep 17 00:00:00 2001 From: Sian Cao Date: Thu, 24 Oct 2019 18:00:16 +0800 Subject: [PATCH] [x11] Check pending release when mapping Summary: when unmap notify is followed by a map, the old Unmanaged will get released and never be managed again. by checking if there is a pending release operation, we can safely re-manage the window again. BUG: 413350 Reviewers: #kwin, zzag Reviewed By: #kwin, zzag Subscribers: zzag, kwin, scao Tags: #kwin Differential Revision: https://phabricator.kde.org/D24878 --- events.cpp | 14 ++++++++++++-- unmanaged.cpp | 5 +++++ unmanaged.h | 2 ++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/events.cpp b/events.cpp index 00c4628854..8347581258 100644 --- a/events.cpp +++ b/events.cpp @@ -328,8 +328,17 @@ bool Workspace::workspaceEvent(xcb_generic_event_t *e) Unmanaged* c = findUnmanaged(event->window); if (c == nullptr) c = createUnmanaged(event->window); - if (c) - return c->windowEvent(e); + if (c) { + // if hasScheduledRelease is true, it means a unamp and map sequence has occurred. + // since release is scheduled after map notify, this old Unmanaged will get released + // before KWIN has chance to remanage it again. so release it right now. + if (c->hasScheduledRelease()) { + c->release(); + c = createUnmanaged(event->window); + } + if (c) + return c->windowEvent(e); + } } return (event->event != event->window); // hide wm typical event from Qt } @@ -1265,6 +1274,7 @@ bool Unmanaged::windowEvent(xcb_generic_event_t *e) // short enough to not cause problems in the close window animations. // It's of course still possible that we miss the destroy in which case non-fatal // X errors are reported to the event loop and logged by Qt. + m_scheduledRelease = true; QTimer::singleShot(1, this, SLOT(release())); break; } diff --git a/unmanaged.cpp b/unmanaged.cpp index 6c4c6abae4..2a4bb5b1a2 100644 --- a/unmanaged.cpp +++ b/unmanaged.cpp @@ -123,6 +123,11 @@ void Unmanaged::deleteUnmanaged(Unmanaged* c) delete c; } +bool Unmanaged::hasScheduledRelease() const +{ + return m_scheduledRelease; +} + int Unmanaged::desktop() const { return NET::OnAllDesktops; // TODO for some window types should be the current desktop? diff --git a/unmanaged.h b/unmanaged.h index cd486c4e1c..d2ada46317 100644 --- a/unmanaged.h +++ b/unmanaged.h @@ -36,6 +36,7 @@ public: explicit Unmanaged(); bool windowEvent(xcb_generic_event_t *e); bool track(xcb_window_t w); + bool hasScheduledRelease() const; static void deleteUnmanaged(Unmanaged* c); int desktop() const override; QStringList activities() const override; @@ -62,6 +63,7 @@ private: void configureNotifyEvent(xcb_configure_notify_event_t *e); QWindow *findInternalWindow() const; bool m_outline = false; + bool m_scheduledRelease = false; }; } // namespace