diff --git a/events.cpp b/events.cpp --- a/events.cpp +++ b/events.cpp @@ -328,8 +328,17 @@ 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 @@ // 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.h b/unmanaged.h --- a/unmanaged.h +++ b/unmanaged.h @@ -36,6 +36,7 @@ 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 @@ void configureNotifyEvent(xcb_configure_notify_event_t *e); QWindow *findInternalWindow() const; bool m_outline = false; + bool m_scheduledRelease = false; }; } // namespace diff --git a/unmanaged.cpp b/unmanaged.cpp --- a/unmanaged.cpp +++ b/unmanaged.cpp @@ -123,6 +123,11 @@ 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?