From 62c4d449f5a5956c2db60a4d6cd9409eca08c778 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Thu, 23 Aug 2012 13:42:59 +0200 Subject: [PATCH] Use signals'n'slots instead of deep function call into Compositor For most actions where the compositor needs to perform an action (e.g. scheduling another repaint) signals were already emitted. So it's easier to just connect the signals to the Compositor which in turn makes the code much more readable. All signals are connected from the Workspace when either the Compositor gets constructed or a Toplevel gets created. --- activation.cpp | 4 ---- client.cpp | 5 ++--- client.h | 2 +- composite.cpp | 37 +++++++++++++++++++++++-------------- composite.h | 13 ++++++++++--- effects.cpp | 1 - events.cpp | 2 +- geometry.cpp | 10 +--------- toplevel.cpp | 1 + toplevel.h | 5 +++++ workspace.cpp | 12 +++++++++--- 11 files changed, 53 insertions(+), 39 deletions(-) diff --git a/activation.cpp b/activation.cpp index 0562e317ea..836e9983ba 100644 --- a/activation.cpp +++ b/activation.cpp @@ -41,7 +41,6 @@ along with this program. If not, see . #include "rules.h" #include "useractions.h" #include -#include "composite.h" namespace KWin { @@ -874,9 +873,6 @@ void Client::setActive(bool act) emit activeChanged(); updateMouseGrab(); updateUrgency(); // demand attention again if it's still urgent - if (workspace()->compositor()) { - workspace()->compositor()->checkUnredirect(); - } } void Client::startupIdChanged() diff --git a/client.cpp b/client.cpp index e6347d04c7..5694944181 100644 --- a/client.cpp +++ b/client.cpp @@ -2339,9 +2339,8 @@ void Client::setBlockingCompositing(bool block) { const bool usedToBlock = blocks_compositing; blocks_compositing = rules()->checkBlockCompositing(block); - if (usedToBlock != blocks_compositing && workspace()->compositor()) { - workspace()->compositor()->updateCompositeBlocking(blocks_compositing ? this : 0); - emit blockingCompositingChanged(); + if (usedToBlock != blocks_compositing) { + emit blockingCompositingChanged(blocks_compositing ? this : 0); } } diff --git a/client.h b/client.h index f31707b3d3..4c33ab4fdb 100644 --- a/client.h +++ b/client.h @@ -736,7 +736,7 @@ signals: /** * Emitted whenever the Client's block compositing state changes. **/ - void blockingCompositingChanged(); + void blockingCompositingChanged(KWin::Client *client); private: void exportMappingState(int s); // ICCCM 4.1.3.1, 4.1.4, NETWM 2.5.1 diff --git a/composite.cpp b/composite.cpp index 55b5d2b2ff..3fe4213fc9 100644 --- a/composite.cpp +++ b/composite.cpp @@ -212,9 +212,10 @@ void Compositor::slotCompositingOptionsInitialized() } else vBlankInterval = 1 << 10; // no sync - DO NOT set "0", would cause div-by-zero segfaults. m_timeSinceLastVBlank = fpsInterval - 1; // means "start now" - we don't have even a slight idea when the first vsync will occur - checkCompositeTimer(); + scheduleRepaint(); XCompositeRedirectSubwindows(display(), rootWindow(), CompositeRedirectManual); new EffectsHandlerImpl(m_scene); // sets also the 'effects' pointer + connect(effects, SIGNAL(screenGeometryChanged(QSize)), SLOT(addRepaintFull())); addRepaintFull(); foreach (Client * c, Workspace::self()->clientList()) c->setupCompositing(); @@ -228,7 +229,7 @@ void Compositor::slotCompositingOptionsInitialized() performCompositing(); } -void Compositor::checkCompositeTimer() +void Compositor::scheduleRepaint() { if (!compositeTimer.isActive()) setCompositeTimer(); @@ -366,6 +367,11 @@ QStringList Workspace::activeEffects() const return QStringList(); } +void Compositor::updateCompositeBlocking() +{ + updateCompositeBlocking(NULL); +} + void Compositor::updateCompositeBlocking(Client *c) { if (c) { // if c == 0 we just check if we can resume @@ -414,7 +420,7 @@ void Compositor::addRepaint(int x, int y, int w, int h) if (!hasScene()) return; repaints_region += QRegion(x, y, w, h); - checkCompositeTimer(); + scheduleRepaint(); } void Compositor::addRepaint(const QRect& r) @@ -422,7 +428,7 @@ void Compositor::addRepaint(const QRect& r) if (!hasScene()) return; repaints_region += r; - checkCompositeTimer(); + scheduleRepaint(); } void Compositor::addRepaint(const QRegion& r) @@ -430,7 +436,7 @@ void Compositor::addRepaint(const QRegion& r) if (!hasScene()) return; repaints_region += r; - checkCompositeTimer(); + scheduleRepaint(); } void Compositor::addRepaintFull() @@ -438,7 +444,7 @@ void Compositor::addRepaintFull() if (!hasScene()) return; repaints_region = QRegion(0, 0, displayWidth(), displayHeight()); - checkCompositeTimer(); + scheduleRepaint(); } void Compositor::timerEvent(QTimerEvent *te) @@ -491,7 +497,7 @@ void Compositor::performCompositing() // is called the next time. If there would be nothing pending, it will not restart the timer and // checkCompositeTime() would restart it again somewhen later, called from functions that // would again add something pending. - checkCompositeTimer(); + scheduleRepaint(); } void Compositor::performMousePoll() @@ -575,6 +581,11 @@ bool Compositor::isActive() return !m_finishing && hasScene(); } +void Compositor::checkUnredirect() +{ + checkUnredirect(false); +} + // force is needed when the list of windows changes (e.g. a window goes away) void Compositor::checkUnredirect(bool force) { @@ -901,7 +912,6 @@ void Toplevel::addDamage(int x, int y, int w, int h) effect_window->setData(LanczosCacheRole, QVariant()); } } - workspace()->compositor()->checkCompositeTimer(); } void Toplevel::addDamageFull() @@ -922,7 +932,6 @@ void Toplevel::addDamageFull() effect_window->setData(LanczosCacheRole, QVariant()); } } - workspace()->compositor()->checkCompositeTimer(); } void Toplevel::resetDamage(const QRect& r) @@ -940,7 +949,7 @@ void Toplevel::addRepaint(const QRect& r) return; } repaints_region += r; - workspace()->compositor()->checkCompositeTimer(); + emit needsRepaint(); } void Toplevel::addRepaint(int x, int y, int w, int h) @@ -955,7 +964,7 @@ void Toplevel::addRepaint(const QRegion& r) return; } repaints_region += r; - workspace()->compositor()->checkCompositeTimer(); + emit needsRepaint(); } void Toplevel::addLayerRepaint(const QRect& r) @@ -964,7 +973,7 @@ void Toplevel::addLayerRepaint(const QRect& r) return; } layer_repaints_region += r; - workspace()->compositor()->checkCompositeTimer(); + emit needsRepaint(); } void Toplevel::addLayerRepaint(int x, int y, int w, int h) @@ -978,13 +987,13 @@ void Toplevel::addLayerRepaint(const QRegion& r) if (!compositing()) return; layer_repaints_region += r; - workspace()->compositor()->checkCompositeTimer(); + emit needsRepaint(); } void Toplevel::addRepaintFull() { repaints_region = visibleRect().translated(-pos()); - workspace()->compositor()->checkCompositeTimer(); + emit needsRepaint(); } void Toplevel::resetRepaints() diff --git a/composite.h b/composite.h index 5e65371f0b..a4a37107ff 100644 --- a/composite.h +++ b/composite.h @@ -3,6 +3,7 @@ This file is part of the KDE project. Copyright (C) 2011 Arthur Arlt +Copyright (C) 2012 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,6 +30,7 @@ class KSelectionOwner; namespace KWin { +class Client; class Scene; class Compositor : public QObject { @@ -36,19 +38,16 @@ class Compositor : public QObject { public: Compositor(QObject *workspace); ~Compositor(); - void checkCompositeTimer(); // when adding repaints caused by a window, you probably want to use // either Toplevel::addRepaint() or Toplevel::addWorkspaceRepaint() void addRepaint(const QRect& r); void addRepaint(const QRegion& r); void addRepaint(int x, int y, int w, int h); - void checkUnredirect(bool force = false); /** * Called from the D-Bus interface. Does the same as slotToggleCompositing with the * addition to show a notification on how to revert the compositing state. **/ void toggleCompositing(); - void updateCompositeBlocking(Client* c = NULL); // Mouse polling void startMousePolling(); void stopMousePolling(); @@ -107,6 +106,14 @@ public Q_SLOTS: * Connected to the D-Bus signal org.kde.KWin /KWin reinitCompositing **/ void slotReinitialize(); + /** + * Schedules a new repaint if no repaint is currently scheduled. + **/ + void scheduleRepaint(); + void checkUnredirect(); + void checkUnredirect(bool force); + void updateCompositeBlocking(); + void updateCompositeBlocking(KWin::Client* c); Q_SIGNALS: void compositingToggled(bool active); diff --git a/effects.cpp b/effects.cpp index 5bd15201ce..b90030ce55 100644 --- a/effects.cpp +++ b/effects.cpp @@ -588,7 +588,6 @@ void EffectsHandlerImpl::desktopResized(const QSize &size) { m_scene->screenGeometryChanged(size); emit screenGeometryChanged(size); - Workspace::self()->compositor()->addRepaintFull(); } void EffectsHandlerImpl::slotPropertyNotify(Toplevel* t, long int atom) diff --git a/events.cpp b/events.cpp index 074a8d67fa..23e1921bfa 100644 --- a/events.cpp +++ b/events.cpp @@ -461,7 +461,7 @@ bool Workspace::workspaceEvent(XEvent * e) } } if (m_compositor) { - m_compositor->checkCompositeTimer(); + m_compositor->scheduleRepaint(); } } break; diff --git a/geometry.cpp b/geometry.cpp index 485ad9c022..19a911d097 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -1910,9 +1910,6 @@ void Client::setGeometry(int x, int y, int w, int h, ForceGeometry_t force) // to detect changes workspace()->checkActiveScreen(this); workspace()->updateStackingOrder(); - if (workspace()->compositor()) { - workspace()->compositor()->checkUnredirect(); - } // need to regenerate decoration pixmaps when either // - size is changed @@ -1986,9 +1983,6 @@ void Client::plainResize(int w, int h, ForceGeometry_t force) updateWindowRules(Rules::Position|Rules::Size); workspace()->checkActiveScreen(this); workspace()->updateStackingOrder(); - if (workspace()->compositor()) { - workspace()->compositor()->checkUnredirect(); - } discardWindowPixmap(); emit geometryShapeChanged(this, geom_before_block); const QRect deco_rect = visibleRect(); @@ -2034,6 +2028,7 @@ void Client::move(int x, int y, ForceGeometry_t force) workspace()->checkActiveScreen(this); workspace()->updateStackingOrder(); if (workspace()->compositor()) { + // TODO: move out of geometry.cpp, is this really needed here? workspace()->compositor()->checkUnredirect(); } // client itself is not damaged @@ -2381,9 +2376,6 @@ void Client::setFullScreen(bool set, bool user) } } updateWindowRules(Rules::Fullscreen|Rules::Position|Rules::Size); - if (workspace()->compositor()) { - workspace()->compositor()->checkUnredirect(); - } if (was_fs != isFullScreen()) { emit clientFullScreenSet(this, set, user); diff --git a/toplevel.cpp b/toplevel.cpp index 94178130e3..69fb7d77cd 100644 --- a/toplevel.cpp +++ b/toplevel.cpp @@ -45,6 +45,7 @@ Toplevel::Toplevel(Workspace* ws) , unredirect(false) , unredirectSuspend(false) { + connect(this, SIGNAL(damaged(KWin::Toplevel*,QRect)), SIGNAL(needsRepaint())); } Toplevel::~Toplevel() diff --git a/toplevel.h b/toplevel.h index 777056904a..4fc15429fb 100644 --- a/toplevel.h +++ b/toplevel.h @@ -299,6 +299,11 @@ signals: * decoration. **/ void shapedChanged(); + /** + * Emitted whenever the state changes in a way, that the Compositor should + * schedule a repaint of the scene. + **/ + void needsRepaint(); protected: virtual ~Toplevel(); diff --git a/workspace.cpp b/workspace.cpp index d5956297a6..c6afa93bc4 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -205,6 +205,7 @@ Workspace::Workspace(bool restore) #endif m_compositor = new Compositor(this); + connect(this, SIGNAL(currentDesktopChanged(int,KWin::Client*)), m_compositor, SLOT(addRepaintFull())); connect(m_compositor, SIGNAL(compositingToggled(bool)), SIGNAL(compositingToggled(bool))); connect(m_compositor, SIGNAL(compositingToggled(bool)), SLOT(slotCompositingToggled())); dbus.connect(QString(), "/KWin", "org.kde.KWin", "reinitCompositing", @@ -536,6 +537,12 @@ Client* Workspace::createClient(Window w, bool is_mapped) Client::deleteClient(c, Allowed); return NULL; } + connect(c, SIGNAL(needsRepaint()), m_compositor, SLOT(scheduleRepaint())); + connect(c, SIGNAL(activeChanged()), m_compositor, SLOT(checkUnredirect())); + connect(c, SIGNAL(fullScreenChanged()), m_compositor, SLOT(checkUnredirect())); + connect(c, SIGNAL(geometryChanged()), m_compositor, SLOT(checkUnredirect())); + connect(c, SIGNAL(geometryShapeChanged(KWin::Toplevel*,QRect)), m_compositor, SLOT(checkUnredirect())); + connect(c, SIGNAL(blockingCompositingChanged(KWin::Client*)), m_compositor, SLOT(updateCompositeBlocking(KWin::Client*))); addClient(c, Allowed); return c; } @@ -549,6 +556,7 @@ Unmanaged* Workspace::createUnmanaged(Window w) Unmanaged::deleteUnmanaged(c, Allowed); return NULL; } + connect(c, SIGNAL(needsRepaint()), m_compositor, SLOT(scheduleRepaint())); addUnmanaged(c, Allowed); emit unmanagedAdded(c); return c; @@ -699,6 +707,7 @@ void Workspace::addDeleted(Deleted* c, Toplevel *orig, allowed_t) stacking_order.append(c); } x_stacking_dirty = true; + connect(c, SIGNAL(needsRepaint()), m_compositor, SLOT(scheduleRepaint())); } void Workspace::removeDeleted(Deleted* c, allowed_t) @@ -1301,9 +1310,6 @@ bool Workspace::setCurrentDesktop(int new_desktop) // s += QString::number( desktop_focus_chain[i] ) + ", "; //kDebug( 1212 ) << s << "}\n"; - if (compositing() && m_compositor) - m_compositor->addRepaintFull(); - emit currentDesktopChanged(old_desktop, movingClient); return true; }