Distinguish between damage and repaints - damage is when windows contents

change, repaint just triggers repaint of the area (without e.g. the texture
updating for OpenGL).
addDamage() -> addRepaint()
CCMAIL: kwin@kde.org


svn path=/branches/work/kwin_composite/; revision=632866
This commit is contained in:
Luboš Luňák 2007-02-12 15:22:43 +00:00
parent c65b031e94
commit 4019dff500
26 changed files with 147 additions and 111 deletions

View file

@ -32,13 +32,6 @@ General TODO
and then the decoration - this should make it possible to paint the decoration
without the random alpha that is right now handled by the alpha hack
* don't add workspace damage in Toplevel::addDamage()
- instead add damage of windows to the screen only before doing the painting
- this should prevent repaints because of changing obscured windows
* - also, provide a call to just mark a window as needing repaint but not being damaged
- this will prevent rebinding the pixmap or updating the texture
- http://lists.kde.org/?l=kwin&m=116836151626848&w=2
* wait for decoration repaints
- it is sometimes visible that the window contents are painted first and the decoration
only afterwards with a small delay
@ -68,8 +61,6 @@ General TODO
- cleaning up Client/Unmanaged instances may still leave e.g. timers around if they're overlooked
- an extra class could copy some interesting data and "replace" the old instance
+ Deleted::windowType() does not work
% during screensaving, do no let non-screensaver windows show above screensaver
- kdesktop_lock watches for such things and raises again, but there's a small gap
@ -156,7 +147,7 @@ Effects framework TODO
- during some more complicated effects, input (at least mouse) should be disabled,
because currently there is no way to do input redirection
* pre-paint pass should be done completely before the paint pass
? pre-paint pass should be done completely before the paint pass
- currently prePaintWindow() is done only after paintScreen() has already started,
which means that if an effect sets PAINT_WINDOW_TRANSFORMED it needs to set it
also in prePaintScreen()

View file

@ -190,8 +190,8 @@ void Client::releaseWindow( bool on_shutdown )
leaveMoveResize();
finishWindowRules();
++block_geometry_updates;
if( isNormalState()) // is mapped?
workspace()->addDamage( geometry());
if( isOnCurrentDesktop() && isShown( true ))
workspace()->addRepaint( geometry());
setMappingState( WithdrawnState );
setModal( false ); // otherwise its mainwindow wouldn't get focus
hidden = true; // so that it's not considered visible anymore (can't use hideClient(), it would set flags)
@ -232,7 +232,6 @@ void Client::releaseWindow( bool on_shutdown )
XDestroyWindow( display(), frameId());
// frame = None;
--block_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry
workspace()->addDamage( geometry());
disownDataPassedToDeleted();
del->unrefWindow();
deleteClient( this, Allowed );
@ -257,8 +256,8 @@ void Client::destroyClient()
leaveMoveResize();
finishWindowRules();
++block_geometry_updates;
if( isNormalState()) // is mapped?
workspace()->addDamage( geometry());
if( isOnCurrentDesktop() && isShown( true ))
workspace()->addRepaint( geometry());
setModal( false );
hidden = true; // so that it's not considered visible anymore
workspace()->clientHidden( this );
@ -271,7 +270,6 @@ void Client::destroyClient()
XDestroyWindow( display(), frameId());
// frame = None;
--block_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry
workspace()->addDamage( geometry());
disownDataPassedToDeleted();
del->unrefWindow();
deleteClient( this, Allowed );
@ -315,7 +313,6 @@ void Client::updateDecoration( bool check_workspace_pos, bool force )
if( do_show )
decoration->widget()->show();
updateFrameExtents();
addDamageFull();
}
void Client::destroyDecoration()
@ -337,7 +334,6 @@ void Client::destroyDecoration()
discardWindowPixmap();
if( scene != NULL && !deleting )
scene->windowGeometryShapeChanged( this );
addDamageFull();
}
}
@ -466,7 +462,6 @@ void Client::updateShape()
discardWindowPixmap();
if( scene != NULL )
scene->windowGeometryShapeChanged( this );
addDamageFull();
// workaround for #19644 - shaped windows shouldn't have decoration
if( shape() && !noBorder())
{
@ -505,7 +500,6 @@ void Client::setMask( const QRegion& reg, int mode )
discardWindowPixmap();
if( scene != NULL )
scene->windowGeometryShapeChanged( this );
addDamageFull();
}
QRegion Client::mask() const
@ -788,6 +782,7 @@ void Client::setShade( ShadeMode mode )
// we're about to shade, texx xcompmgr to prepare
long _shade = 1;
XChangeProperty(display(), frameId(), atoms->net_wm_window_shade, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &_shade, 1L);
workspace()->addRepaint( geometry());
// shade
int h = height();
shade_geometry_change = true;
@ -824,13 +819,9 @@ void Client::setShade( ShadeMode mode )
// tell xcompmgr shade's done
_shade = 2;
XChangeProperty(display(), frameId(), atoms->net_wm_window_shade, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &_shade, 1L);
if( isNormalState()) // is mapped?
workspace()->addDamage( geometry());
}
else
{
if( isNormalState()) // is mapped?
workspace()->addDamage( geometry());
int h = height();
shade_geometry_change = true;
QSize s( sizeForClientSize( clientSize()));
@ -862,6 +853,7 @@ void Client::setShade( ShadeMode mode )
checkMaximizeGeometry();
info->setState( isShade() ? NET::Shaded : 0, NET::Shaded );
info->setState( isShown( false ) ? 0 : NET::Hidden, NET::Hidden );
discardWindowPixmap();
updateVisibility();
updateAllowedActions();
workspace()->updateMinimizedOfTransients( this );
@ -997,7 +989,7 @@ void Client::rawShow()
*/
void Client::rawHide()
{
workspace()->addDamage( geometry());
workspace()->addRepaint( geometry());
// Here it may look like a race condition, as some other client might try to unmap
// the window between these two XSelectInput() calls. However, they're supposed to
// use XWithdrawWindow(), which also sends a synthetic event to the root window,

View file

@ -119,7 +119,7 @@ void Workspace::setupCompositing()
else if( dynamic_cast< SceneBasic* >( scene ))
kDebug( 1212 ) << "X compositing" << endl;
new EffectsHandler(); // sets also the 'effects' pointer
addDamageFull();
addRepaintFull();
foreach( Client* c, clients )
c->setupCompositing();
foreach( Client* c, desktops )
@ -163,7 +163,7 @@ void Workspace::finishCompositing()
effects = NULL;
delete scene;
scene = NULL;
damage_region = QRegion();
repaints_region = QRegion();
for( ClientList::ConstIterator it = clients.begin();
it != clients.end();
++it )
@ -184,25 +184,25 @@ void Workspace::lostCMSelection()
finishCompositing();
}
void Workspace::addDamage( int x, int y, int w, int h )
void Workspace::addRepaint( int x, int y, int w, int h )
{
if( !compositing())
return;
damage_region += QRegion( x, y, w, h );
repaints_region += QRegion( x, y, w, h );
}
void Workspace::addDamage( const QRect& r )
void Workspace::addRepaint( const QRect& r )
{
if( !compositing())
return;
damage_region += r;
repaints_region += r;
}
void Workspace::addDamageFull()
void Workspace::addRepaintFull()
{
if( !compositing())
return;
damage_region = QRegion( 0, 0, displayWidth(), displayHeight());
repaints_region = QRegion( 0, 0, displayWidth(), displayHeight());
}
void Workspace::performCompositing()
@ -214,7 +214,7 @@ void Workspace::performCompositing()
// is started.
if( lastCompositePaint.elapsed() < 5 )
return;
if( damage_region.isEmpty()) // no damage
if( repaints_region.isEmpty() && !windowRepaintsPending()) // no damage
{
scene->idle();
return;
@ -237,10 +237,16 @@ void Workspace::performCompositing()
}
foreach( Deleted* c, deleted ) // TODO remember stacking order somehow
windows.append( c );
QRegion damage = damage_region;
// clear all damage, so that post-pass can add damage for the next repaint
damage_region = QRegion();
scene->paint( damage, windows );
foreach( Toplevel* c, windows )
{ // this could be possibly optimized WRT obscuring, but that'd need being already
// past prePaint() phase - probably not worth it
repaints_region |= c->repaints().translated( c->pos());
c->resetRepaints( c->rect());
}
QRegion repaints = repaints_region;
// clear all repaints, so that post-pass can add repaints for the next repaint
repaints_region = QRegion();
scene->paint( repaints, windows );
if( scene->waitSyncAvailable() && options->glVSync )
{ // if we're using vsync, then time the next paint pass to
// before the next available sync
@ -254,6 +260,23 @@ void Workspace::performCompositing()
lastCompositePaint.start();
}
bool Workspace::windowRepaintsPending() const
{
foreach( Toplevel* c, clients )
if( !c->repaints().isEmpty())
return true;
foreach( Toplevel* c, desktops )
if( !c->repaints().isEmpty())
return true;
foreach( Toplevel* c, unmanaged )
if( !c->repaints().isEmpty())
return true;
foreach( Toplevel* c, deleted )
if( !c->repaints().isEmpty())
return true;
return false;
}
bool Workspace::createOverlay()
{
assert( overlay == None );
@ -319,6 +342,7 @@ void Toplevel::finishCompositing()
XDamageDestroy( display(), damage_handle );
damage_handle = None;
damage_region = QRegion();
repaints_region = QRegion();
effect_window = NULL;
}
@ -328,6 +352,7 @@ void Toplevel::discardWindowPixmap()
return;
XFreePixmap( display(), window_pix );
window_pix = None;
addDamageFull();
}
Pixmap Toplevel::createWindowPixmap() const
@ -369,17 +394,15 @@ void Toplevel::addDamage( int x, int y, int w, int h )
// may be a damage event coming with size larger than the current window size
r &= rect();
damage_region += r;
r.translate( this->x(), this->y());
// this could be possibly optimized to damage Workspace only if the toplevel
// is actually visible there and not obscured by something, but I guess
// that's not really worth it
workspace()->addDamage( r );
repaints_region += r;
}
void Toplevel::addDamageFull()
{
damage_region = QRegion(); // first reset e.g. in case of shrinking
addDamage( rect());
if( !compositing())
return;
damage_region = rect();
repaints_region = rect();
}
void Toplevel::resetDamage( const QRect& r )
@ -387,6 +410,30 @@ void Toplevel::resetDamage( const QRect& r )
damage_region -= r;
}
void Toplevel::addRepaint( const QRect& r )
{
addRepaint( r.x(), r.y(), r.width(), r.height());
}
void Toplevel::addRepaint( int x, int y, int w, int h )
{
if( !compositing())
return;
QRect r( x, y, w, h );
r &= rect();
repaints_region += r;
}
void Toplevel::addRepaintFull()
{
repaints_region = rect();
}
void Toplevel::resetRepaints( const QRect& r )
{
repaints_region -= r;
}
#endif
} // namespace

View file

@ -85,7 +85,7 @@ void DesktopChangeSlideEffect::paintWindow( EffectWindow* w, int mask, QRegion r
void DesktopChangeSlideEffect::postPaintScreen()
{
if( progress != MAX_PROGRESS )
Workspace::self()->addDamageFull(); // trigger next animation repaint
Workspace::self()->addRepaintFull(); // trigger next animation repaint
effects->postPaintScreen();
}
@ -95,7 +95,7 @@ void DesktopChangeSlideEffect::desktopChanged( int old )
{
old_desktop = old;
progress = 0;
Workspace::self()->addDamageFull();
Workspace::self()->addRepaintFull();
}
}

View file

@ -63,7 +63,7 @@ void DialogParentEffect::postPaintWindow( EffectWindow* w )
// If strength is between 0 and 1, the effect is still in progress and the
// window has to be repainted during the next pass
if( s > 0.0 && s < 1.0 )
w->window()->addDamageFull(); // trigger next animation repaint
w->window()->addRepaintFull(); // trigger next animation repaint
// Call the next effect.
effects->postPaintWindow( w );
@ -71,7 +71,7 @@ void DialogParentEffect::postPaintWindow( EffectWindow* w )
void DialogParentEffect::windowActivated( EffectWindow* t )
{
// If this window is a dialog, we need to damage it's parent window, so
// If this window is a dialog, we need to repaint it's parent window, so
// that the effect could be run for it
// Set the window to be faded (or NULL if no window is active).
Client* c = qobject_cast<Client *>(t?t->window():NULL);
@ -80,13 +80,13 @@ void DialogParentEffect::windowActivated( EffectWindow* t )
// c is a modal dialog
ClientList mainclients = c->mainClients();
foreach( Client* parent, mainclients )
parent->addDamageFull();
parent->addRepaintFull();
}
}
void DialogParentEffect::windowClosed( EffectWindow* t )
{
// If this window is a dialog, we need to damage it's parent window, so
// If this window is a dialog, we need to repaint it's parent window, so
// that the effect could be run for it
// Set the window to be faded (or NULL if no window is active).
Client* c = qobject_cast<Client *>(t->window());
@ -95,7 +95,7 @@ void DialogParentEffect::windowClosed( EffectWindow* t )
// c is a modal dialog
ClientList mainclients = c->mainClients();
foreach( Client* parent, mainclients )
parent->addDamageFull();
parent->addRepaintFull();
}
}

View file

@ -65,7 +65,7 @@ void FadeEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowP
void FadeEffect::postPaintWindow( EffectWindow* w )
{
if( windows.contains( w ) && windows.value( w ).isFading())
w->window()->addDamageFull(); // trigger next animation repaint
w->window()->addRepaintFull(); // trigger next animation repaint
effects->postPaintWindow( w );
}
@ -97,7 +97,7 @@ void FadeEffect::windowOpacityChanged( EffectWindow* c )
}
}
windows[ c ].old_opacity = new_opacity;
c->window()->addDamageFull();
c->window()->addRepaintFull();
}
void FadeEffect::windowAdded( EffectWindow* c )
@ -119,7 +119,7 @@ void FadeEffect::windowAdded( EffectWindow* c )
windows[ c ].target = 1;
windows[ c ].step_mult = 1 / c->window()->opacity();
}
c->window()->addDamageFull();
c->window()->addRepaintFull();
}
void FadeEffect::windowClosed( EffectWindow* c )
@ -141,7 +141,7 @@ void FadeEffect::windowClosed( EffectWindow* c )
}
windows[ c ].deleted = true;
windows[ c ].target = 0;
c->window()->addDamageFull();
c->window()->addRepaintFull();
static_cast< Deleted* >( c->window())->refWindow();
}

View file

@ -43,7 +43,7 @@ void FadeInEffect::paintWindow( EffectWindow* w, int mask, QRegion region, Windo
void FadeInEffect::postPaintWindow( EffectWindow* w )
{
if( windows.contains( w ))
w->window()->addDamageFull(); // trigger next animation repaint
w->window()->addRepaintFull(); // trigger next animation repaint
effects->postPaintWindow( w );
}
@ -53,7 +53,7 @@ void FadeInEffect::windowAdded( EffectWindow* c )
if( cc == NULL || cc->isOnCurrentDesktop())
{
windows[ c ] = 0;
c->window()->addDamageFull();
c->window()->addRepaintFull();
}
}

View file

@ -48,7 +48,7 @@ void FadeOutEffect::paintWindow( EffectWindow* w, int mask, QRegion region, Wind
void FadeOutEffect::postPaintWindow( EffectWindow* w )
{
if( windows.contains( w ))
w->window()->addDamageFull(); // trigger next animation repaint
w->window()->addRepaintFull(); // trigger next animation repaint
effects->postPaintWindow( w );
}
@ -58,7 +58,7 @@ void FadeOutEffect::windowClosed( EffectWindow* c )
if( cc == NULL || cc->isOnCurrentDesktop())
{
windows[ c ] = 1; // count down to 0
c->window()->addDamageFull();
c->window()->addRepaintFull();
static_cast< Deleted* >( c->window())->refWindow();
}
}

View file

@ -108,16 +108,16 @@ void HowtoEffect::paintWindow( EffectWindow* w, int mask, QRegion region, Window
}
// The function that is called after the painting pass is finished. When an animation is going on,
// it can damage some areas so that the next painting pass has to repaint them again.
// it can add repaints of some areas so that the next painting pass has to repaint them again.
void HowtoEffect::postPaintWindow( EffectWindow* w )
{
// Is this the window to be faded out and in again?
if( w == fade_window )
{
// Damage the whole window, this will cause it to be repainted the next painting pass.
// Trigger repaint of the whole window, this will cause it to be repainted the next painting pass.
// Currently the API for effects is not complete, so for now window() is used to access
// internal class Toplevel. This should change in the future.
w->window()->addDamageFull(); // trigger next animation repaint
w->window()->addRepaintFull(); // trigger next animation repaint
}
// Call the next effect.
effects->postPaintWindow( w );
@ -132,8 +132,8 @@ void HowtoEffect::windowActivated( EffectWindow* c )
{
// If there is a window to be faded, reset the progress to zero.
progress = 0;
// And damage the window so that it needs to be repainted.
c->window()->addDamageFull();
// And add repaint to the window so that it needs to be repainted.
c->window()->addRepaintFull();
}
}

View file

@ -39,7 +39,7 @@ void MakeTransparentEffect::paintWindow( EffectWindow* w, int mask, QRegion regi
void MakeTransparentEffect::windowUserMovedResized( EffectWindow* c, bool first, bool last )
{
if( first || last )
c->window()->addDamageFull();
c->window()->addRepaintFull();
}
} // namespace

View file

@ -99,8 +99,8 @@ void MinimizeAnimationEffect::paintWindow( EffectWindow* w, int mask, QRegion re
void MinimizeAnimationEffect::postPaintScreen()
{
if( mActiveAnimations > 0 )
// Damage the workspace so that everything would be repainted next time
workspace()->addDamageFull();
// Repaint the workspace so that everything would be repainted next time
workspace()->addRepaintFull();
// Call the next effect.
effects->postPaintScreen();

View file

@ -107,7 +107,7 @@ void PresentWindowsEffect::postPaintScreen()
// If mActiveness is between 0 and 1, the effect is still in progress and the
// workspace has to be repainted during the next pass
if( mActiveness > 0.0 && mActiveness < 1.0 )
workspace()->addDamageFull(); // trigger next animation repaint
workspace()->addRepaintFull(); // trigger next animation repaint
// Call the next effect.
effects->postPaintScreen();
@ -190,7 +190,7 @@ void PresentWindowsEffect::rearrangeWindows()
calculateWindowTransformationsKompose( clientlist );
// Schedule entire desktop to be repainted
workspace()->addDamageFull();
workspace()->addRepaintFull();
}
void PresentWindowsEffect::calculateWindowTransformationsDumb(ClientList clientlist)

View file

@ -50,7 +50,7 @@ void ScaleInEffect::paintWindow( EffectWindow* w, int mask, QRegion region, Wind
void ScaleInEffect::postPaintWindow( EffectWindow* w )
{
if( windows.contains( w ))
w->window()->addDamageFull(); // trigger next animation repaint
w->window()->addRepaintFull(); // trigger next animation repaint
effects->postPaintWindow( w );
}
@ -60,7 +60,7 @@ void ScaleInEffect::windowAdded( EffectWindow* c )
if( cc == NULL || cc->isOnCurrentDesktop())
{
windows[ c ] = 0;
c->window()->addDamageFull();
c->window()->addRepaintFull();
}
}

View file

@ -55,8 +55,8 @@ void ShakyMoveEffect::windowUserMovedResized( EffectWindow* c, bool first, bool
else if( last )
{
windows.remove( c );
// just damage whole screen, transformation is involved
c->window()->workspace()->addDamageFull();
// just repaint whole screen, transformation is involved
c->window()->workspace()->addRepaintFull();
if( windows.isEmpty())
timer.stop();
}
@ -80,8 +80,8 @@ void ShakyMoveEffect::tick()
*it = 0;
else
++(*it);
// just damage whole screen, transformation is involved
it.key()->window()->workspace()->addDamageFull();
// just repaint whole screen, transformation is involved
it.key()->window()->workspace()->addRepaintFull();
}
}

View file

@ -44,14 +44,14 @@ void ShiftWorkspaceUpEffect::paintScreen( int mask, QRegion region, ScreenPaintD
void ShiftWorkspaceUpEffect::postPaintScreen()
{
if( up ? diff < 1000 : diff > 0 )
workspace()->addDamageFull(); // trigger next animation repaint
workspace()->addRepaintFull(); // trigger next animation repaint
effects->postPaintScreen();
}
void ShiftWorkspaceUpEffect::tick()
{
up = !up;
workspace()->addDamageFull();
workspace()->addRepaintFull();
}
} // namespace

View file

@ -217,7 +217,7 @@ void ShowFpsEffect::postPaintScreen()
paints[ paints_pos ] = t.elapsed();
if( ++paints_pos == NUM_PAINTS )
paints_pos = 0;
workspace()->addDamage( x, y, FPS_WIDTH + NUM_PAINTS, MAX_TIME );
workspace()->addRepaint( x, y, FPS_WIDTH + NUM_PAINTS, MAX_TIME );
}
} // namespace

View file

@ -83,8 +83,8 @@ void WavyWindowsEffect::paintWindow( EffectWindow* w, int mask, QRegion region,
void WavyWindowsEffect::postPaintScreen()
{
// Damage the workspace so that everything would be repainted next time
workspace()->addDamageFull();
// Repaint the workspace so that everything would be repainted next time
workspace()->addRepaintFull();
// Call the next effect.
effects->postPaintScreen();

View file

@ -53,7 +53,7 @@ void ZoomEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
void ZoomEffect::postPaintScreen()
{
if( zoom != target_zoom )
workspace()->addDamageFull();
workspace()->addRepaintFull();
effects->postPaintScreen();
}

View file

@ -479,7 +479,7 @@ bool Workspace::workspaceEvent( XEvent * e )
break;
case Expose:
if( e->xexpose.window == rootWindow() && compositing()) // root window needs repainting
addDamage( e->xexpose.x, e->xexpose.y, e->xexpose.width, e->xexpose.height );
addRepaint( e->xexpose.x, e->xexpose.y, e->xexpose.width, e->xexpose.height );
break;
default:
if( e->type == Extensions::randrNotifyEvent() && Extensions::randrAvailable() )
@ -595,7 +595,7 @@ bool Client::windowEvent( XEvent* e )
{
if( compositing())
{
addDamageFull();
addRepaintFull();
scene->windowOpacityChanged( this );
if( effects )
effects->windowOpacityChanged( effectWindow());
@ -1610,7 +1610,7 @@ bool Unmanaged::windowEvent( XEvent* e )
scene->windowOpacityChanged( this );
if( effects )
effects->windowOpacityChanged( effectWindow());
addDamageFull();
addRepaintFull();
}
switch (e->type)
{
@ -1630,7 +1630,6 @@ bool Unmanaged::windowEvent( XEvent* e )
if( e->type == Extensions::shapeNotifyEvent() )
{
detectShape( window());
addDamageFull();
if( compositing() )
discardWindowPixmap();
if( scene != NULL )
@ -1660,14 +1659,11 @@ void Unmanaged::configureNotifyEvent( XConfigureEvent* e )
QRect newgeom( e->x, e->y, e->width, e->height );
if( newgeom == geom )
return;
workspace()->addDamage( geometry()); // damage old area
workspace()->addRepaint( geometry()); // damage old area
geom = newgeom;
if( scene != NULL )
scene->windowGeometryShapeChanged( this );
// TODO add damage only if the window is not obscured
workspace()->addDamage( geometry());
// TODO maybe only damage changed area
addDamageFull();
discardWindowPixmap();
}
// ****************************************

View file

@ -1701,13 +1701,11 @@ void Client::setGeometry( int x, int y, int w, int h, ForceGeometry_t force )
checkMaximizeGeometry();
if( geom_before_block.size() != geom.size())
{
addDamageFull(); // damage window only if it actually was a resize
discardWindowPixmap();
if( scene != NULL )
scene->windowGeometryShapeChanged( this );
}
else
workspace()->addDamage( geom ); // damage window's new location
workspace()->addDamage( geom_before_block ); // TODO add damage only if not obscured
workspace()->addRepaint( geom_before_block );
geom_before_block = geom;
}
@ -1763,10 +1761,10 @@ void Client::plainResize( int w, int h, ForceGeometry_t force )
sendSyntheticConfigureNotify();
updateWindowRules();
checkMaximizeGeometry();
addDamageFull(); // TODO add damage only in added area?
discardWindowPixmap();
if( scene != NULL )
scene->windowGeometryShapeChanged( this );
workspace()->addDamage( geom_before_block ); // TODO add damage only if not obscured
workspace()->addRepaint( geom_before_block );
geom_before_block = geom;
}
@ -1789,8 +1787,8 @@ void Client::move( int x, int y, ForceGeometry_t force )
updateWindowRules();
checkMaximizeGeometry();
// client itself is not damaged
workspace()->addDamage( geom_before_block ); // TODO add damage only if not obscured
workspace()->addDamage( geom ); // damage window's new location
workspace()->addRepaint( geom_before_block );
workspace()->addRepaint( geom ); // trigger repaint of window's new location
geom_before_block = geom;
}

View file

@ -119,7 +119,7 @@ void Workspace::updateStackingOrder( bool propagate_new_clients )
if( changed || propagate_new_clients )
{
propagateClients( propagate_new_clients );
addDamageFull();
addRepaintFull();
}
}

View file

@ -101,6 +101,7 @@ void Toplevel::copyToDeleted( Toplevel* c )
window_pix = c->window_pix;
damage_handle = None;
damage_region = c->damage_region;
repaints_region = c->repaints_region;
is_shape = c->is_shape;
effect_window = c->effect_window;
if( effect_window != NULL )

View file

@ -81,9 +81,11 @@ class Toplevel
bool hasAlpha() const;
void setupCompositing();
void finishCompositing();
void addDamage( const QRect& r );
void addDamage( int x, int y, int w, int h );
void addDamageFull();
void addRepaint( const QRect& r );
void addRepaint( int x, int y, int w, int h );
void addRepaintFull();
QRegion repaints() const;
void resetRepaints( const QRect& r );
QRegion damage() const;
void resetDamage( const QRect& r );
EffectWindow* effectWindow();
@ -96,6 +98,9 @@ class Toplevel
void damageNotifyEvent( XDamageNotifyEvent* e );
Pixmap createWindowPixmap() const;
void discardWindowPixmap();
void addDamage( const QRect& r );
void addDamage( int x, int y, int w, int h );
void addDamageFull();
void getWmClientLeader();
void getWmClientMachine();
void getResourceClass();
@ -120,7 +125,8 @@ class Toplevel
Workspace* wspace;
Pixmap window_pix;
Damage damage_handle;
QRegion damage_region;
QRegion damage_region; // damage is really damaged window (XDamage) and texture needs
QRegion repaints_region; // updating, repaint just requires repaint of that area
bool is_shape;
EffectWindow* effect_window;
QByteArray resource_name;
@ -256,6 +262,11 @@ inline QRegion Toplevel::damage() const
return damage_region;
}
inline QRegion Toplevel::repaints() const
{
return repaints_region;
}
inline bool Toplevel::shape() const
{
return is_shape;

View file

@ -80,7 +80,7 @@ void Unmanaged::release()
if( Extensions::shapeAvailable())
XShapeSelectInput( display(), window(), NoEventMask );
XSelectInput( display(), window(), NoEventMask );
workspace()->addDamage( geometry());
workspace()->addRepaint( geometry());
disownDataPassedToDeleted();
del->unrefWindow();
deleteUnmanaged( this, Allowed );

View file

@ -131,7 +131,6 @@ Workspace::Workspace( bool restore )
forced_global_mouse_grab( false ),
cm_selection( NULL ),
compositeRate( 0 ),
damage_region( None ),
overlay( None ),
transSlider( NULL ),
transButton( NULL )

View file

@ -289,10 +289,10 @@ class Workspace : public QObject, public KDecorationDefines
void toggleTopDockShadows(bool on);
void addDamage( const QRect& r );
void addDamage( int x, int y, int w, int h );
void addDamageFull();
// creates XComposite overlay window, cal initOverlay() afterwards
void addRepaint( const QRect& r );
void addRepaint( int x, int y, int w, int h );
void addRepaintFull();
// creates XComposite overlay window, call initOverlay() afterwards
bool createOverlay();
// init overlay and the destination window in it
void setupOverlay( Window window );
@ -525,6 +525,7 @@ class Workspace : public QObject, public KDecorationDefines
void updateClientArea( bool force );
void finishCompositing();
bool windowRepaintsPending() const;
SystemTrayWindowList systemTrayWins;
@ -688,7 +689,7 @@ class Workspace : public QObject, public KDecorationDefines
QTimer compositeTimer;
QTime lastCompositePaint;
int compositeRate;
QRegion damage_region;
QRegion repaints_region;
Window overlay; // XComposite overlay window
QSlider *transSlider;
QPushButton *transButton;