32 bit compositing suspension

REVIEW: 108304
BUG: 308438
This commit is contained in:
Thomas Lübking 2013-01-09 16:03:54 +01:00
parent 31f20cb4b1
commit c8e2b61f48
2 changed files with 40 additions and 37 deletions

View file

@ -53,6 +53,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <xcb/composite.h> #include <xcb/composite.h>
#include <xcb/damage.h> #include <xcb/damage.h>
Q_DECLARE_METATYPE(KWin::Compositor::SuspendReason)
namespace KWin namespace KWin
{ {
@ -68,8 +70,7 @@ Compositor *Compositor::createCompositor(QObject *parent)
Compositor::Compositor(QObject* workspace) Compositor::Compositor(QObject* workspace)
: QObject(workspace) : QObject(workspace)
, m_suspended(!options->isUseCompositing()) , m_suspended(options->isUseCompositing() ? NoReasonSuspend : UserSuspend)
, m_blocked(false)
, cm_selection(NULL) , cm_selection(NULL)
, vBlankInterval(0) , vBlankInterval(0)
, fpsInterval(0) , fpsInterval(0)
@ -80,6 +81,7 @@ Compositor::Compositor(QObject* workspace)
, m_nextFrameDelay(0) , m_nextFrameDelay(0)
, m_scene(NULL) , m_scene(NULL)
{ {
qRegisterMetaType<Compositor::SuspendReason>("Compositor::SuspendReason");
new CompositingAdaptor(this); new CompositingAdaptor(this);
QDBusConnection dbus = QDBusConnection::sessionBus(); QDBusConnection dbus = QDBusConnection::sessionBus();
dbus.registerObject("/Compositor", this); dbus.registerObject("/Compositor", this);
@ -116,7 +118,7 @@ void Compositor::setup()
if (hasScene()) if (hasScene())
return; return;
if (m_suspended) { if (m_suspended) {
kDebug(1212) << "Compositing is suspended"; kDebug(1212) << "Compositing is suspended, reason:" << m_suspended;
return; return;
} else if (!CompositingPrefs::compositingPossible()) { } else if (!CompositingPrefs::compositingPossible()) {
kError(1212) << "Compositing is not possible"; kError(1212) << "Compositing is not possible";
@ -365,7 +367,7 @@ void Compositor::slotReinitialize()
// Restart compositing // Restart compositing
finish(); finish();
// resume compositing if suspended // resume compositing if suspended
m_suspended = false; m_suspended = NoReasonSuspend;
options->setCompositingInitialized(false); options->setCompositingInitialized(false);
setup(); setup();
@ -377,13 +379,17 @@ void Compositor::slotReinitialize()
// for the shortcut // for the shortcut
void Compositor::slotToggleCompositing() void Compositor::slotToggleCompositing()
{ {
setCompositing(m_suspended); if (m_suspended) { // direct user call; clear all bits
resume(AllReasonSuspend);
} else { // but only set the user one (sufficient to suspend)
suspend(UserSuspend);
}
} }
// for the dbus call // for the dbus call
void Compositor::toggleCompositing() void Compositor::toggleCompositing()
{ {
slotToggleCompositing(); slotToggleCompositing(); // TODO only operate on script level here?
if (m_suspended) { if (m_suspended) {
// when disabled show a shortcut how the user can get back compositing // when disabled show a shortcut how the user can get back compositing
QString shortcut, message; QString shortcut, message;
@ -407,14 +413,11 @@ void Compositor::updateCompositeBlocking(Client *c)
{ {
if (c) { // if c == 0 we just check if we can resume if (c) { // if c == 0 we just check if we can resume
if (c->isBlockingCompositing()) { if (c->isBlockingCompositing()) {
if (!m_blocked) // do NOT attempt to call suspend(true); from within the eventchain! if (!(m_suspended & BlockRuleSuspend)) // do NOT attempt to call suspend(true); from within the eventchain!
QMetaObject::invokeMethod(this, "suspend", Qt::QueuedConnection); QMetaObject::invokeMethod(this, "suspend", Qt::QueuedConnection, Q_ARG(Compositor::SuspendReason, BlockRuleSuspend));
m_blocked = true;
} }
} }
else if (m_blocked) { // lost a client and we're blocked - can we resume? else if (m_suspended & BlockRuleSuspend) { // lost a client and we're blocked - can we resume?
// NOTICE do NOT check for "m_Suspended" or "!compositing()"
// only "resume" if it was really disabled for a block
bool resume = true; bool resume = true;
for (ClientList::ConstIterator it = Workspace::self()->clientList().constBegin(); it != Workspace::self()->clientList().constEnd(); ++it) { for (ClientList::ConstIterator it = Workspace::self()->clientList().constBegin(); it != Workspace::self()->clientList().constEnd(); ++it) {
if ((*it)->isBlockingCompositing()) { if ((*it)->isBlockingCompositing()) {
@ -423,38 +426,31 @@ void Compositor::updateCompositeBlocking(Client *c)
} }
} }
if (resume) { // do NOT attempt to call suspend(false); from within the eventchain! if (resume) { // do NOT attempt to call suspend(false); from within the eventchain!
m_blocked = false; QMetaObject::invokeMethod(this, "resume", Qt::QueuedConnection, Q_ARG(Compositor::SuspendReason, BlockRuleSuspend));
if (m_suspended)
QMetaObject::invokeMethod(this, "resume", Qt::QueuedConnection);
} }
} }
} }
void Compositor::suspend() void Compositor::suspend(Compositor::SuspendReason reason)
{ {
if (m_suspended) { Q_ASSERT(reason != NoReasonSuspend);
return; m_suspended |= reason;
}
m_suspended = true;
finish(); finish();
} }
void Compositor::resume() void Compositor::resume(Compositor::SuspendReason reason)
{ {
if (!m_suspended && hasScene()) { Q_ASSERT(reason != NoReasonSuspend);
return; m_suspended &= ~reason;
} setup(); // signal "toggled" is eventually emitted from within setup
m_suspended = false;
// signal toggled is eventually emitted from within setup
setup();
} }
void Compositor::setCompositing(bool active) void Compositor::setCompositing(bool active)
{ {
if (active) { if (active) {
resume(); resume(ScriptSuspend);
} else { } else {
suspend(); suspend(ScriptSuspend);
} }
} }

View file

@ -66,6 +66,8 @@ class Compositor : public QObject {
**/ **/
Q_PROPERTY(QString compositingType READ compositingType) Q_PROPERTY(QString compositingType READ compositingType)
public: public:
enum SuspendReason { NoReasonSuspend = 0, UserSuspend = 1<<0, BlockRuleSuspend = 1<<1, ScriptSuspend = 1<<2, AllReasonSuspend = 0xff };
Q_DECLARE_FLAGS(SuspendReasons, SuspendReason)
~Compositor(); ~Compositor();
// when adding repaints caused by a window, you probably want to use // when adding repaints caused by a window, you probably want to use
// either Toplevel::addRepaint() or Toplevel::addWorkspaceRepaint() // either Toplevel::addRepaint() or Toplevel::addWorkspaceRepaint()
@ -186,7 +188,8 @@ public Q_SLOTS:
* @see resume * @see resume
* @see isActive * @see isActive
**/ **/
Q_SCRIPTABLE void suspend(); Q_SCRIPTABLE inline void suspend() { suspend(ScriptSuspend); }
void suspend(Compositor::SuspendReason reason);
/** /**
* @brief Resumes the Compositor if it is currently suspended. * @brief Resumes the Compositor if it is currently suspended.
* *
@ -204,7 +207,8 @@ public Q_SLOTS:
* @see isCompositingPossible * @see isCompositingPossible
* @see isOpenGLBroken * @see isOpenGLBroken
**/ **/
Q_SCRIPTABLE void resume(); Q_SCRIPTABLE inline void resume() { resume(ScriptSuspend); }
void resume(Compositor::SuspendReason reason);
/** /**
* @brief Tries to suspend or resume the Compositor based on @p active. * @brief Tries to suspend or resume the Compositor based on @p active.
* *
@ -218,6 +222,10 @@ public Q_SLOTS:
* Note: The starting of the Compositor can require some time and is partially done threaded. * Note: The starting of the Compositor can require some time and is partially done threaded.
* After this method returns the setup may not have been completed. * After this method returns the setup may not have been completed.
* *
* Note: This function only impacts whether compositing is suspended or resumed by scripts
* or dbus calls. Compositing may be suspended for user will or a window rule - no matter how
* often you call this function!
*
* @param active Whether the Compositor should be resumed (@c true) or suspended (@c false) * @param active Whether the Compositor should be resumed (@c true) or suspended (@c false)
* @return void * @return void
* @see suspend * @see suspend
@ -226,6 +234,8 @@ public Q_SLOTS:
* @see isCompositingPossible * @see isCompositingPossible
* @see isOpenGLBroken * @see isOpenGLBroken
**/ **/
// NOTICE this is atm. for script usage *ONLY* and needs to be extended like resume / suspend are
// if intended to be used from within KWin code!
Q_SCRIPTABLE void setCompositing(bool active); Q_SCRIPTABLE void setCompositing(bool active);
/** /**
* Actual slot to perform the toggling compositing. * Actual slot to perform the toggling compositing.
@ -289,13 +299,10 @@ private:
void restartKWin(const QString &reason); void restartKWin(const QString &reason);
/** /**
* Whether the Compositor is currently suspended. * Whether the Compositor is currently suspended, 8 bits encoding the reason
**/ **/
bool m_suspended; SuspendReasons m_suspended;
/**
* Whether the Compositor is currently blocked by at least one Client requesting full resources.
**/
bool m_blocked;
QBasicTimer compositeTimer; QBasicTimer compositeTimer;
KSelectionOwner* cm_selection; KSelectionOwner* cm_selection;
QTimer m_releaseSelectionTimer; QTimer m_releaseSelectionTimer;