From 986d9e5613a58a9a705254c7a05a7332639a29f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Sun, 14 Oct 2012 12:18:35 +0200 Subject: [PATCH] Delay releasing the compositor selection When turning off the compositor do not release the compositor selection directly but delay it through a timer. The idea is that the internal change when e.g. restarting the compositor or switching from XRender to OpenGL should not be visible to the outside world. This hopefully makes restarting the compositor more robust in Plasma due to the SelectionWatcher sometimes reporting incorrect results. When restarting KWin the change does not matter as the selection gets force claimed by the new instance anyway. CCBUG: 179042 REVIEW: 106844 --- composite.cpp | 47 ++++++++++++++++++++++++++++++++++++++++++----- composite.h | 3 +++ 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/composite.cpp b/composite.cpp index ed2e26475b..8bb2a1ebf8 100644 --- a/composite.cpp +++ b/composite.cpp @@ -118,6 +118,11 @@ Compositor::Compositor(QObject* workspace) unredirectTimer.setSingleShot(true); compositeResetTimer.setSingleShot(true); nextPaintReference.invalidate(); // Initialize the timer + + m_releaseSelectionTimer.setSingleShot(true); + // 2 sec which should be enough to restart the compositor + m_releaseSelectionTimer.setInterval(2000); + connect(&m_releaseSelectionTimer, SIGNAL(timeout()), SLOT(releaseCompositorSelection())); // delay the call to setup by one event cycle // The ctor of this class is invoked from the Workspace ctor, that means before // Workspace is completely constructed, so calling Workspace::self() would result @@ -128,6 +133,7 @@ Compositor::Compositor(QObject* workspace) Compositor::~Compositor() { finish(); + delete cm_selection; } @@ -142,6 +148,7 @@ void Compositor::setup() kError(1212) << "Compositing is not possible"; return; } + m_starting = true; if (!options->isCompositingInitialized()) { #ifndef KWIN_HAVE_OPENGLES @@ -166,8 +173,10 @@ void Compositor::slotCompositingOptionsInitialized() { char selection_name[ 100 ]; sprintf(selection_name, "_NET_WM_CM_S%d", DefaultScreen(display())); - cm_selection = new KSelectionOwner(selection_name); - connect(cm_selection, SIGNAL(lostOwnership()), SLOT(finish())); + if (!cm_selection) { + cm_selection = new KSelectionOwner(selection_name); + connect(cm_selection, SIGNAL(lostOwnership()), SLOT(finish())); + } cm_selection->claim(true); // force claiming switch(options->compositingMode()) { @@ -214,7 +223,8 @@ void Compositor::slotCompositingOptionsInitialized() #endif default: kDebug(1212) << "No compositing enabled"; - delete cm_selection; + m_starting = false; + cm_selection->release(); return; } if (m_scene == NULL || m_scene->initFailed()) { @@ -222,7 +232,8 @@ void Compositor::slotCompositingOptionsInitialized() kError(1212) << "Consult http://techbase.kde.org/Projects/KWin/4.0-release-notes#Setting_up"; delete m_scene; m_scene = NULL; - delete cm_selection; + m_starting = false; + cm_selection->release(); return; } m_xrrRefreshRate = KWin::currentRefreshRate(); @@ -247,6 +258,11 @@ void Compositor::slotCompositingOptionsInitialized() emit compositingToggled(true); + m_starting = false; + if (m_releaseSelectionTimer.isActive()) { + m_releaseSelectionTimer.stop(); + } + // render at least once compositeTimer.stop(); performCompositing(); @@ -263,7 +279,7 @@ void Compositor::finish() if (!hasScene()) return; m_finishing = true; - delete cm_selection; + m_releaseSelectionTimer.start(); foreach (Client * c, Workspace::self()->clientList()) m_scene->windowClosed(c, NULL); foreach (Client * c, Workspace::self()->desktopList()) @@ -304,6 +320,27 @@ void Compositor::finish() emit compositingToggled(false); } +void Compositor::releaseCompositorSelection() +{ + if (hasScene() && !m_finishing) { + // compositor is up and running again, no need to release the selection + return; + } + if (m_starting) { + // currently still starting the compositor, it might fail, so restart the timer to test again + m_releaseSelectionTimer.start(); + return; + } + + if (m_finishing) { + // still shutting down, a restart might follow, so restart the timer to test again + m_releaseSelectionTimer.start(); + return; + } + kDebug(1212) << "Releasing compositor selection"; + cm_selection->release(); +} + // OpenGL self-check failed, fallback to XRender void Compositor::fallbackToXRenderCompositing() { diff --git a/composite.h b/composite.h index e9045a6ec4..1655ffeedd 100644 --- a/composite.h +++ b/composite.h @@ -275,6 +275,7 @@ private Q_SLOTS: void performMousePoll(); void delayedCheckUnredirect(); void slotConfigChanged(); + void releaseCompositorSelection(); private: Compositor(QObject *workspace); @@ -298,6 +299,7 @@ private: bool m_blocked; QBasicTimer compositeTimer; KSelectionOwner* cm_selection; + QTimer m_releaseSelectionTimer; uint vBlankInterval, fpsInterval; int m_xrrRefreshRate; QElapsedTimer nextPaintReference; @@ -308,6 +310,7 @@ private: bool forceUnredirectCheck; QTimer compositeResetTimer; // for compressing composite resets bool m_finishing; // finish() sets this variable while shutting down + bool m_starting; // start() sets this variable while starting int m_timeSinceLastVBlank, m_nextFrameDelay; Scene *m_scene;