diff --git a/effects.cpp b/effects.cpp
index 868364f406..4b1c242af5 100644
--- a/effects.cpp
+++ b/effects.cpp
@@ -152,6 +152,7 @@ void EffectsHandlerImpl::setupClientConnections(Client* c)
connect(c, SIGNAL(clientMinimized(KWin::Client*,bool)), this, SLOT(slotClientMinimized(KWin::Client*,bool)));
connect(c, SIGNAL(clientUnminimized(KWin::Client*,bool)), this, SLOT(slotClientUnminimized(KWin::Client*,bool)));
connect(c, SIGNAL(geometryShapeChanged(KWin::Toplevel*,QRect)), this, SLOT(slotGeometryShapeChanged(KWin::Toplevel*,QRect)));
+ connect(c, SIGNAL(paddingChanged(KWin::Toplevel*,QRect)), this, SLOT(slotPaddingChanged(KWin::Toplevel*,QRect)));
connect(c, SIGNAL(damaged(KWin::Toplevel*,QRect)), this, SLOT(slotWindowDamaged(KWin::Toplevel*,QRect)));
connect(c, SIGNAL(propertyNotify(KWin::Toplevel*,long)), this, SLOT(slotPropertyNotify(KWin::Toplevel*,long)));
}
@@ -161,6 +162,7 @@ void EffectsHandlerImpl::setupUnmanagedConnections(Unmanaged* u)
connect(u, SIGNAL(windowClosed(KWin::Toplevel*,KWin::Deleted*)), this, SLOT(slotWindowClosed(KWin::Toplevel*)));
connect(u, SIGNAL(opacityChanged(KWin::Toplevel*,qreal)), this, SLOT(slotOpacityChanged(KWin::Toplevel*,qreal)));
connect(u, SIGNAL(geometryShapeChanged(KWin::Toplevel*,QRect)), this, SLOT(slotGeometryShapeChanged(KWin::Toplevel*,QRect)));
+ connect(u, SIGNAL(paddingChanged(KWin::Toplevel*,QRect)), this, SLOT(slotPaddingChanged(KWin::Toplevel*,QRect)));
connect(u, SIGNAL(damaged(KWin::Toplevel*,QRect)), this, SLOT(slotWindowDamaged(KWin::Toplevel*,QRect)));
connect(u, SIGNAL(propertyNotify(KWin::Toplevel*,long)), this, SLOT(slotPropertyNotify(KWin::Toplevel*,long)));
}
@@ -484,6 +486,15 @@ void EffectsHandlerImpl::slotGeometryShapeChanged(Toplevel* t, const QRect& old)
emit windowGeometryShapeChanged(t->effectWindow(), old);
}
+void EffectsHandlerImpl::slotPaddingChanged(Toplevel* t, const QRect& old)
+{
+ // during late cleanup effectWindow() may be already NULL
+ // in some functions that may still call this
+ if (t == NULL || t->effectWindow() == NULL)
+ return;
+ emit windowPaddingChanged(t->effectWindow(), old);
+}
+
void EffectsHandlerImpl::setActiveFullScreenEffect(Effect* e)
{
fullscreen_effect = e;
diff --git a/effects.h b/effects.h
index a110242584..7278118228 100644
--- a/effects.h
+++ b/effects.h
@@ -197,6 +197,7 @@ protected Q_SLOTS:
void slotClientMinimized(KWin::Client *c, bool animate);
void slotClientUnminimized(KWin::Client *c, bool animate);
void slotGeometryShapeChanged(KWin::Toplevel *t, const QRect &old);
+ void slotPaddingChanged(KWin::Toplevel *t, const QRect &old);
void slotWindowDamaged(KWin::Toplevel *t, const QRect& r);
void slotPropertyNotify(KWin::Toplevel *t, long atom);
void slotPropertyNotify(long atom);
diff --git a/libkwineffects/kwinanimationeffect.cpp b/libkwineffects/kwinanimationeffect.cpp
index ee0772dbe4..481340f643 100644
--- a/libkwineffects/kwinanimationeffect.cpp
+++ b/libkwineffects/kwinanimationeffect.cpp
@@ -27,10 +27,10 @@ along with this program. If not, see .
namespace KWin {
struct AnimationEffectPrivate {
public:
- AnimationEffectPrivate() { m_animated = false; }
+ AnimationEffectPrivate() { m_animated = m_damageDirty = false; }
AnimationEffect::AniMap m_animations;
EffectWindowList m_zombies;
- bool m_animated;
+ bool m_animated, m_damageDirty, m_needSceneRepaint;
};
}
@@ -51,8 +51,12 @@ void AnimationEffect::init()
* connect it we can provide auto-referencing of animated and closed windows, since at the time
* our slot will be called, the slot of the subclass has been (SIGNAL/SLOT connections are FIFO)
* and has pot. started an animation so we have the window in our hash :) */
- connect ( effects, SIGNAL(windowClosed(KWin::EffectWindow*)), SLOT(_windowClosed(KWin::EffectWindow*)) );
- connect ( effects, SIGNAL(windowDeleted(KWin::EffectWindow*)), SLOT(_windowDeleted(KWin::EffectWindow*)) );
+ connect ( effects, SIGNAL(windowClosed(KWin::EffectWindow*)), SLOT(_windowClosed(KWin::EffectWindow*)) );
+ connect ( effects, SIGNAL(windowDeleted(KWin::EffectWindow*)), SLOT(_windowDeleted(KWin::EffectWindow*)) );
+ connect ( effects, SIGNAL(windowGeometryShapeChanged(KWin::EffectWindow*, const QRect&)),
+ SLOT(_expandedGeometryChanged(KWin::EffectWindow*, const QRect&)) );
+ connect ( effects, SIGNAL(windowPaddingChanged(KWin::EffectWindow*, const QRect&)),
+ SLOT(_expandedGeometryChanged(KWin::EffectWindow*, const QRect&)) );
}
bool AnimationEffect::isActive() const
@@ -124,17 +128,17 @@ void AnimationEffect::animate( EffectWindow *w, Attribute a, uint meta, int ms,
RELATIVE_XY(Source);
from.set( relative[0] ? from[0] * area.width() : from[0],
relative[1] ? from[1] * area.height() : from[1] );
- }
- else
+ } else {
from.set(w->width(), w->height());
+ }
if (to.isValid()) {
RELATIVE_XY(Target);
to.set( relative[0] ? to[0] * area.width() : to[0],
relative[1] ? to[1] * area.height() : to[1] );
- }
- else
+ } else {
from.set(w->width(), w->height());
+ }
} else if (a == Translation) {
@@ -143,27 +147,34 @@ void AnimationEffect::animate( EffectWindow *w, Attribute a, uint meta, int ms,
RELATIVE_XY(Source);
from.set( relative[0] ? from[0] * area.width() : from[0],
relative[1] ? from[1] * area.height() : from[1] );
- } else
+ } else {
from.set(0.0, 0.0);
+ }
if (to.isValid()) {
RELATIVE_XY(Target);
to.set( relative[0] ? to[0] * area.width() : to[0],
relative[1] ? to[1] * area.height() : to[1] );
- } else
+ } else {
to.set(0.0, 0.0);
+ }
}
Q_D(AnimationEffect);
AniMap::iterator it = d->m_animations.find(w);
if (it == d->m_animations.end())
- it = d->m_animations.insert(w, QList());
- it->append(AniData(a, meta, ms, to, curve, delay, from, waitAtSource));
+ it = d->m_animations.insert(w, QPair, QRect>(QList(), QRect()));
+ it->first.append(AniData(a, meta, ms, to, curve, delay, from, waitAtSource));
+ it->second = QRect();
- if (delay > 0)
+ if (delay > 0) {
QTimer::singleShot(delay, this, SLOT(triggerRepaint()));
- else
+ if (waitAtSource)
+ w->addLayerRepaint(0, 0, displayWidth(), displayHeight());
+ }
+ else {
triggerRepaint();
+ }
}
void AnimationEffect::prePaintScreen( ScreenPrePaintData& data, int time )
@@ -174,42 +185,55 @@ void AnimationEffect::prePaintScreen( ScreenPrePaintData& data, int time )
return;
}
- AniMap::iterator entry = d->m_animations.begin();
+ AniMap::iterator entry = d->m_animations.begin(), mapEnd = d->m_animations.end();
d->m_animated = false;
- while (entry != d->m_animations.end()) {
- QList::iterator anim = entry->begin();
- while (anim != entry->end()) {
+// short int transformed = 0;
+ while (entry != mapEnd) {
+ bool invalidateLayerRect = false;
+ QList::iterator anim = entry->first.begin(), animEnd = entry->first.end();
+ while (anim != animEnd) {
if (QTime::currentTime() < anim->startTime) {
if (!anim->waitAtSource) {
++anim;
continue;
}
- } else
+ } else {
anim->addTime(time);
+ }
if (anim->time < anim->duration) {
+// if (anim->attribute != Brightness && anim->attribute != Saturation && anim->attribute != Opacity)
+// transformed = true;
d->m_animated = true;
++anim;
- }
- else {
+ } else {
animationEnded(entry.key(), anim->attribute);
- anim = entry->erase(anim);
+ anim = entry->first.erase(anim);
+ invalidateLayerRect = d->m_damageDirty = true;
+ animEnd = entry->first.end();
}
}
- if (entry->isEmpty()) {
+ if (entry->first.isEmpty()) {
const int i = d->m_zombies.indexOf(entry.key());
if ( i > -1 ) {
d->m_zombies.removeAt( i );
entry.key()->unrefWindow();
}
+ data.paint |= entry->second;
+// d->m_damageDirty = true; // TODO likely no longer required
entry = d->m_animations.erase(entry);
- }
- else
+ mapEnd = d->m_animations.end();
+ } else {
+ if (invalidateLayerRect)
+ *const_cast(&(entry->second)) = QRect(); // invalidate
++entry;
+ }
}
- if ( d->m_animated )
- data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
+ // NOTICE PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_WITHOUT_FULL_REPAINTS and thus now no flag should be required
+ // ... unless we start to get glitches ;-)
+// if ( transformed )
+// data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_WITHOUT_FULL_REPAINTS; //PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
// janitorial...
if ( !(d->m_animations.count() || d->m_zombies.isEmpty()) )
@@ -229,14 +253,14 @@ void AnimationEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data,
AniMap::const_iterator entry = d->m_animations.constFind( w );
if ( entry != d->m_animations.constEnd() ) {
bool isUsed = false;
- for (QList::const_iterator anim = entry->constBegin(); anim != entry->constEnd(); ++anim) {
+ for (QList::const_iterator anim = entry->first.constBegin(); anim != entry->first.constEnd(); ++anim) {
if (QTime::currentTime() < anim->startTime && !anim->waitAtSource)
continue;
isUsed = true;
if (anim->attribute == Opacity)
data.setTranslucent();
- else {
+ else if (!(anim->attribute == Brightness || anim->attribute == Saturation)) {
data.setTransformed();
data.mask |= PAINT_WINDOW_TRANSFORMED;
}
@@ -248,8 +272,8 @@ void AnimationEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data,
w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DELETE );
else if ( !w->isOnCurrentDesktop() )
w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP );
- if( !w->isPaintingEnabled() && !effects->activeFullScreenEffect() )
- w->addRepaintFull();
+// if( !w->isPaintingEnabled() && !effects->activeFullScreenEffect() )
+// effects->addLayerRepaint(w->expandedGeometry());
}
}
}
@@ -290,7 +314,7 @@ void AnimationEffect::paintWindow( EffectWindow* w, int mask, QRegion region, Wi
if ( d->m_animated ) {
AniMap::const_iterator entry = d->m_animations.constFind( w );
if ( entry != d->m_animations.constEnd() ) {
- for ( QList::const_iterator anim = entry->constBegin(); anim != entry->constEnd(); ++anim ) {
+ for ( QList::const_iterator anim = entry->first.constBegin(); anim != entry->first.constEnd(); ++anim ) {
if (QTime::currentTime() < anim->startTime && !anim->waitAtSource)
continue;
@@ -395,8 +419,18 @@ void AnimationEffect::paintWindow( EffectWindow* w, int mask, QRegion region, Wi
void AnimationEffect::postPaintScreen()
{
Q_D(AnimationEffect);
- if ( d->m_animated )
- effects->addRepaintFull();
+ if ( d->m_animated ) {
+ if (d->m_damageDirty)
+ updateLayerRepaints();
+ if (d->m_needSceneRepaint) {
+ effects->addRepaintFull();
+ } else {
+ AniMap::const_iterator it = d->m_animations.constBegin(), end = d->m_animations.constEnd();
+ for (; it != end; ++it) {
+ it.key()->addLayerRepaint(it->second);
+ }
+ }
+ }
effects->postPaintScreen();
}
@@ -478,10 +512,153 @@ void AnimationEffect::setMetaData( MetaType type, uint value, uint &meta )
void AnimationEffect::triggerRepaint()
{
Q_D(AnimationEffect);
- if (!d->m_animated)
+ for (AniMap::const_iterator entry = d->m_animations.constBegin(), mapEnd = d->m_animations.constEnd(); entry != mapEnd; ++entry)
+ *const_cast(&(entry->second)) = QRect();
+ updateLayerRepaints();
+ if (d->m_needSceneRepaint) {
effects->addRepaintFull();
+ } else {
+ AniMap::const_iterator it = d->m_animations.constBegin(), end = d->m_animations.constEnd();
+ for (; it != end; ++it)
+ it.key()->addLayerRepaint(it->second);
+ }
}
+static float fixOvershoot(float f, const AniData &d, short int dir, float s = 1.1)
+{
+ switch(d.curve.type()) {
+ case QEasingCurve::InOutElastic:
+ case QEasingCurve::InOutBack:
+ return f * s;
+ case QEasingCurve::InElastic:
+ case QEasingCurve::OutInElastic:
+ case QEasingCurve::OutBack:
+ return (dir&2) ? f * s : f;
+ case QEasingCurve::OutElastic:
+ case QEasingCurve::InBack:
+ return (dir&1) ? f * s : f;
+ default:
+ return f;
+ }
+}
+
+void AnimationEffect::updateLayerRepaints()
+{
+ Q_D(AnimationEffect);
+ d->m_needSceneRepaint = false;
+ for (AniMap::const_iterator entry = d->m_animations.constBegin(), mapEnd = d->m_animations.constEnd(); entry != mapEnd; ++entry) {
+ if (!entry->second.isNull())
+ continue;
+ float f[2] = {1.0, 1.0};
+ float t[2] = {0.0, 0.0};
+ bool createRegion = false;
+ QList rects;
+ QRect *layerRect = const_cast(&(entry->second));
+ for (QList::const_iterator anim = entry->first.constBegin(), animEnd = entry->first.constEnd(); anim != animEnd; ++anim) {
+ if (QTime::currentTime() < anim->startTime)
+ continue;
+ switch (anim->attribute) {
+ case Opacity:
+ case Brightness:
+ case Saturation:
+ createRegion = true;
+ break;
+ case Rotation:
+ createRegion = false;
+ *layerRect = QRect(0, 0, displayWidth(), displayHeight());
+ goto region_creation; // sic! no need to do anything else
+ case Generic:
+ d->m_needSceneRepaint = true; // we don't know whether this will change visual stacking order
+ return; // sic! no need to do anything else
+ case Translation:
+ case Position: {
+ createRegion = true;
+ QRect r(entry.key()->geometry());
+ int x[2] = {0,0};
+ int y[2] = {0,0};
+ if (anim->attribute == Translation) {
+ x[0] = anim->from[0];
+ x[1] = anim->to[0];
+ y[0] = anim->from[1];
+ y[1] = anim->to[1];
+ } else {
+ if ( anim->from[0] >= 0.0 && anim->to[0] >= 0.0 ) {
+ x[0] = anim->from[0] - xCoord(r, metaData(SourceAnchor, anim->meta));
+ x[1] = anim->to[0] - xCoord(r, metaData(TargetAnchor, anim->meta));
+ }
+ if ( anim->from[1] >= 0.0 && anim->to[1] >= 0.0 ) {
+ y[0] = anim->from[1] - yCoord(r, metaData(SourceAnchor, anim->meta));
+ y[1] = anim->to[1] - yCoord(r, metaData(TargetAnchor, anim->meta));
+ }
+ }
+ r = entry.key()->expandedGeometry();
+ rects << r.translated(x[0], y[0]) << r.translated(x[1], y[1]);
+ break;
+ }
+ case Size:
+ case Scale: {
+ createRegion = true;
+ const QSize sz = entry.key()->geometry().size();
+ float fx = qMax(fixOvershoot(anim->from[0], *anim, 1), fixOvershoot(anim->to[0], *anim, 2));
+// float fx = qMax(interpolated(*anim,0), anim->to[0]);
+ if (fx >= 0.0) {
+ if (anim->attribute == Size)
+ fx /= sz.width();
+ f[0] *= fx;
+ t[0] += geometryCompensation( anim->meta & AnimationEffect::Horizontal, fx ) * sz.width();
+ }
+// float fy = qMax(interpolated(*anim,1), anim->to[1]);
+ float fy = qMax(fixOvershoot(anim->from[1], *anim, 1), fixOvershoot(anim->to[1], *anim, 2));
+ if (fy >= 0.0) {
+ if (anim->attribute == Size)
+ fy /= sz.height();
+ if (!anim->isOneDimensional()) {
+ f[1] *= fy;
+ t[1] += geometryCompensation( anim->meta & AnimationEffect::Vertical, fy ) * sz.height();
+ } else if ( ((anim->meta & AnimationEffect::Vertical)>>1) != (anim->meta & AnimationEffect::Horizontal) ) {
+ f[1] *= fx;
+ t[1] += geometryCompensation( anim->meta & AnimationEffect::Vertical, fx ) * sz.height();
+ }
+ }
+ break;
+ }
+ }
+ }
+region_creation:
+ if (createRegion) {
+ const QRect geo = entry.key()->expandedGeometry();
+ if (rects.isEmpty())
+ rects << geo;
+ QList::const_iterator r, rEnd = rects.constEnd();
+ for ( r = rects.constBegin(); r != rEnd; ++r) { // transform
+ const_cast(&(*r))->setSize(QSize(qRound(r->width()*f[0]), qRound(r->height()*f[1])));
+ const_cast(&(*r))->translate(t[0], t[1]); // "const_cast" - don't do that at home, kids ;-)
+ }
+ QRect rect = rects.at(0);
+ if (rects.count() > 1) {
+ for ( r = rects.constBegin() + 1; r != rEnd; ++r) // unite
+ rect |= *r;
+ const int dx = 110*(rect.width() - geo.width())/100 + 1 - rect.width() + geo.width();
+ const int dy = 110*(rect.height() - geo.height())/100 + 1 - rect.height() + geo.height();
+ rect.adjust(-dx,-dy,dx,dy); // fix pot. overshoot
+ }
+ *layerRect = rect;
+ }
+ }
+ d->m_damageDirty = false;
+}
+
+void AnimationEffect::_expandedGeometryChanged(KWin::EffectWindow *w, const QRect &old)
+{
+ Q_D(AnimationEffect);
+ AniMap::const_iterator entry = d->m_animations.constFind(w);
+ if (entry != d->m_animations.constEnd()) {
+ *const_cast(&(entry->second)) = QRect();
+ updateLayerRepaints();
+ if (!entry->second.isNull()) // actually got updated, ie. is in use - ensure it get's a repaint
+ w->addLayerRepaint(entry->second);
+ }
+}
void AnimationEffect::_windowClosed( EffectWindow* w )
{
@@ -495,6 +672,7 @@ void AnimationEffect::_windowClosed( EffectWindow* w )
void AnimationEffect::_windowDeleted( EffectWindow* w )
{
Q_D(AnimationEffect);
+ d->m_zombies.removeAll( w ); // TODO this line is a workaround for a bug in KWin 4.8.0 & 4.8.1
d->m_animations.remove( w );
}
diff --git a/libkwineffects/kwinanimationeffect.h b/libkwineffects/kwinanimationeffect.h
index 61dea357b1..2c356c8700 100644
--- a/libkwineffects/kwinanimationeffect.h
+++ b/libkwineffects/kwinanimationeffect.h
@@ -167,13 +167,15 @@ protected:
private:
float interpolated( const AniData&, int i = 0 ) const;
float progress( const AniData& ) const;
+ void updateLayerRepaints();
private Q_SLOTS:
void init();
void triggerRepaint();
void _windowClosed( KWin::EffectWindow* w );
void _windowDeleted( KWin::EffectWindow* w );
+ void _expandedGeometryChanged(KWin::EffectWindow *w, const QRect &old);
private:
- typedef QMap< EffectWindow*, QList > AniMap;
+ typedef QMap< EffectWindow*, QPair, QRect> > AniMap;
AnimationEffectPrivate * const d_ptr;
Q_DECLARE_PRIVATE(AnimationEffect)
};
diff --git a/libkwineffects/kwineffects.cpp b/libkwineffects/kwineffects.cpp
index 135c9ae165..b4228a9b77 100644
--- a/libkwineffects/kwineffects.cpp
+++ b/libkwineffects/kwineffects.cpp
@@ -307,6 +307,7 @@ WINDOW_HELPER(QPoint, pos, "pos")
WINDOW_HELPER(QSize, size, "size")
WINDOW_HELPER(int, screen, "screen")
WINDOW_HELPER(QRect, geometry, "geometry")
+WINDOW_HELPER(QRect, expandedGeometry, "visibleRect")
WINDOW_HELPER(QRect, rect, "rect")
WINDOW_HELPER(int, desktop, "desktop")
WINDOW_HELPER(bool, isDesktop, "desktopWindow")
diff --git a/libkwineffects/kwineffects.h b/libkwineffects/kwineffects.h
index 906aed3630..c8fa295dc9 100644
--- a/libkwineffects/kwineffects.h
+++ b/libkwineffects/kwineffects.h
@@ -954,6 +954,13 @@ Q_SIGNALS:
* @since 4.7
**/
void windowGeometryShapeChanged(KWin::EffectWindow *w, const QRect &old);
+ /**
+ * Signal emitted when the padding of a window changed. (eg. shadow size)
+ * @param w The window whose geometry changed
+ * @param old The previous expandedGeometry()
+ * @since 4.9
+ **/
+ void windowPaddingChanged(KWin::EffectWindow *w, const QRect &old);
/**
* Signal emitted when the windows opacity is changed.
* @param w The window whose opacity level is changed.
@@ -1097,6 +1104,7 @@ class KWIN_EXPORT EffectWindow : public QObject
Q_OBJECT
Q_PROPERTY(bool alpha READ hasAlpha CONSTANT)
Q_PROPERTY(QRect geometry READ geometry)
+ Q_PROPERTY(QRect expandedGeometry READ expandedGeometry)
Q_PROPERTY(int height READ height)
Q_PROPERTY(qreal opacity READ opacity)
Q_PROPERTY(QPoint pos READ pos)
@@ -1332,6 +1340,12 @@ public:
*/
QSize basicUnit() const;
QRect geometry() const;
+ /**
+ * Geometry of the window including decoration and potentially shadows.
+ * May be different from geometry() if the window has a shadow.
+ * @since 4.9
+ */
+ QRect expandedGeometry() const;
virtual QRegion shape() const = 0;
int screen() const;
/** @internal Do not use */
@@ -1344,6 +1358,7 @@ public:
bool isUserMove() const;
bool isUserResize() const;
QRect iconGeometry() const;
+
/**
* Geometry of the actual window contents inside the whole (including decorations) window.
*/
diff --git a/toplevel.cpp b/toplevel.cpp
index 05810025b0..70f543e00e 100644
--- a/toplevel.cpp
+++ b/toplevel.cpp
@@ -369,6 +369,7 @@ bool Toplevel::isOnScreen(int screen) const
void Toplevel::getShadow()
{
QRect dirtyRect; // old & new shadow region
+ const QRect oldVisibleRect = visibleRect();
if (hasShadow()) {
dirtyRect = shadow()->shadowRegion().boundingRect();
effectWindow()->sceneWindow()->shadow()->updateShadow();
@@ -377,6 +378,8 @@ void Toplevel::getShadow()
}
if (hasShadow())
dirtyRect |= shadow()->shadowRegion().boundingRect();
+ if (oldVisibleRect != visibleRect())
+ emit paddingChanged(this, oldVisibleRect);
if (dirtyRect.isValid()) {
dirtyRect.translate(pos());
addLayerRepaint(dirtyRect);
diff --git a/toplevel.h b/toplevel.h
index fabb129e74..5f189ff56b 100644
--- a/toplevel.h
+++ b/toplevel.h
@@ -49,6 +49,7 @@ class Toplevel
Q_PROPERTY(bool alpha READ hasAlpha CONSTANT)
Q_PROPERTY(qulonglong frameId READ frameId)
Q_PROPERTY(QRect geometry READ geometry NOTIFY geometryChanged)
+ Q_PROPERTY(QRect visibleRect READ visibleRect)
Q_PROPERTY(int height READ height)
Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged)
Q_PROPERTY(QPoint pos READ pos)
@@ -285,6 +286,7 @@ signals:
void propertyNotify(KWin::Toplevel* toplevel, long a);
void geometryChanged();
void geometryShapeChanged(KWin::Toplevel* toplevel, const QRect& old);
+ void paddingChanged(KWin::Toplevel* toplevel, const QRect& old);
void windowClosed(KWin::Toplevel* toplevel, KWin::Deleted* deleted);
void windowShown(KWin::Toplevel* toplevel);
/**