diff --git a/COMPOSITE_TODO b/COMPOSITE_TODO index 44f98d0455..29f0a07489 100644 --- a/COMPOSITE_TODO +++ b/COMPOSITE_TODO @@ -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() diff --git a/client.cpp b/client.cpp index b41d0ea738..414c3cbc74 100644 --- a/client.cpp +++ b/client.cpp @@ -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, diff --git a/composite.cpp b/composite.cpp index a3e36a51f1..f5da1fa586 100644 --- a/composite.cpp +++ b/composite.cpp @@ -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 diff --git a/effects/desktopchangeslide.cpp b/effects/desktopchangeslide.cpp index 343c72e71f..f1d01705c3 100644 --- a/effects/desktopchangeslide.cpp +++ b/effects/desktopchangeslide.cpp @@ -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(); } } diff --git a/effects/dialogparent.cpp b/effects/dialogparent.cpp index d80bba0a61..ba176ec57c 100644 --- a/effects/dialogparent.cpp +++ b/effects/dialogparent.cpp @@ -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(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(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(); } } diff --git a/effects/fade.cpp b/effects/fade.cpp index 340a683d16..2ef2efb8ed 100644 --- a/effects/fade.cpp +++ b/effects/fade.cpp @@ -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(); } diff --git a/effects/fadein.cpp b/effects/fadein.cpp index 9209ab71cb..ad5a52560b 100644 --- a/effects/fadein.cpp +++ b/effects/fadein.cpp @@ -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(); } } diff --git a/effects/fadeout.cpp b/effects/fadeout.cpp index 2c4e9020b0..cf6ca339d8 100644 --- a/effects/fadeout.cpp +++ b/effects/fadeout.cpp @@ -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(); } } diff --git a/effects/howto.cpp b/effects/howto.cpp index 17535d1a3d..8b9f89682e 100644 --- a/effects/howto.cpp +++ b/effects/howto.cpp @@ -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(); } } diff --git a/effects/maketransparent.cpp b/effects/maketransparent.cpp index 8dfea11dab..40cc8d8c66 100644 --- a/effects/maketransparent.cpp +++ b/effects/maketransparent.cpp @@ -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 diff --git a/effects/minimizeanimation.cpp b/effects/minimizeanimation.cpp index 165f7af2e1..920363e2da 100644 --- a/effects/minimizeanimation.cpp +++ b/effects/minimizeanimation.cpp @@ -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(); diff --git a/effects/presentwindows.cpp b/effects/presentwindows.cpp index 44a86d54f4..f1a2825b71 100644 --- a/effects/presentwindows.cpp +++ b/effects/presentwindows.cpp @@ -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) diff --git a/effects/scalein.cpp b/effects/scalein.cpp index 5440c0136e..addb2cb8fd 100644 --- a/effects/scalein.cpp +++ b/effects/scalein.cpp @@ -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(); } } diff --git a/effects/shakymove.cpp b/effects/shakymove.cpp index e74acd5851..0eb86abf62 100644 --- a/effects/shakymove.cpp +++ b/effects/shakymove.cpp @@ -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(); } } diff --git a/effects/shiftworkspaceup.cpp b/effects/shiftworkspaceup.cpp index a7a3ba965b..35570b5632 100644 --- a/effects/shiftworkspaceup.cpp +++ b/effects/shiftworkspaceup.cpp @@ -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 diff --git a/effects/showfps.cpp b/effects/showfps.cpp index 1e3bf68e13..5dbd0671b5 100644 --- a/effects/showfps.cpp +++ b/effects/showfps.cpp @@ -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 diff --git a/effects/wavywindows.cpp b/effects/wavywindows.cpp index 68f89993d2..ea22e42275 100644 --- a/effects/wavywindows.cpp +++ b/effects/wavywindows.cpp @@ -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(); diff --git a/effects/zoom.cpp b/effects/zoom.cpp index 2ee160b8ee..b10bbfb295 100644 --- a/effects/zoom.cpp +++ b/effects/zoom.cpp @@ -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(); } diff --git a/events.cpp b/events.cpp index 40944081e4..f5ce945d7c 100644 --- a/events.cpp +++ b/events.cpp @@ -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(); } // **************************************** diff --git a/geometry.cpp b/geometry.cpp index 88d9039cca..219fb91d1e 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -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; } diff --git a/layers.cpp b/layers.cpp index 3317e9b51a..5e969aab19 100644 --- a/layers.cpp +++ b/layers.cpp @@ -119,7 +119,7 @@ void Workspace::updateStackingOrder( bool propagate_new_clients ) if( changed || propagate_new_clients ) { propagateClients( propagate_new_clients ); - addDamageFull(); + addRepaintFull(); } } diff --git a/toplevel.cpp b/toplevel.cpp index 9ce68d6b30..54960d0e8e 100644 --- a/toplevel.cpp +++ b/toplevel.cpp @@ -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 ) diff --git a/toplevel.h b/toplevel.h index dba7e707ab..b3f3dec0d7 100644 --- a/toplevel.h +++ b/toplevel.h @@ -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; diff --git a/unmanaged.cpp b/unmanaged.cpp index f3dea1b92a..fab53eaf60 100644 --- a/unmanaged.cpp +++ b/unmanaged.cpp @@ -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 ); diff --git a/workspace.cpp b/workspace.cpp index 96224df0b7..294dc91bb5 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -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 ) diff --git a/workspace.h b/workspace.h index 4f5f5b935b..2dac69770d 100644 --- a/workspace.h +++ b/workspace.h @@ -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;