From c16656d66db3a61158adeb68b677db2dc941ae66 Mon Sep 17 00:00:00 2001 From: Philip Falkner Date: Sun, 11 Feb 2007 17:36:32 +0000 Subject: [PATCH] Rework how window painting is disabled; now effects can indicate reasons they want particular windows painted or not. This solves a few problems, but may need revisiting in the future. svn path=/branches/work/kwin_composite/; revision=632581 --- COMPOSITE_TODO | 2 +- effects.cpp | 10 +++++++++ effects.h | 2 ++ effects/desktopchangeslide.cpp | 4 ++-- effects/fadeout.cpp | 3 ++- effects/minimizeanimation.cpp | 2 +- effects/presentwindows.cpp | 2 +- scene.cpp | 40 +++++++++++++++++++++++++++++----- scene.h | 29 ++++++++++++++++++------ scene_xrender.cpp | 5 ++--- 10 files changed, 77 insertions(+), 22 deletions(-) diff --git a/COMPOSITE_TODO b/COMPOSITE_TODO index e05594b38b..44f98d0455 100644 --- a/COMPOSITE_TODO +++ b/COMPOSITE_TODO @@ -161,7 +161,7 @@ Effects framework TODO which means that if an effect sets PAINT_WINDOW_TRANSFORMED it needs to set it also in prePaintScreen() -* PAINT_WINDOW_DISABLED turning off from effects needs some utility functions +* PAINT_DISABLED turning off from effects needs some improvement - a window may have painting disabled for various reasons and their numbers may increase over time - so e.g. an effect showing minimized windows cannot simply turn off DISABLED diff --git a/effects.cpp b/effects.cpp index 0d3b486283..9c22c2970d 100644 --- a/effects.cpp +++ b/effects.cpp @@ -443,6 +443,16 @@ EffectWindow::EffectWindow() { } +void EffectWindow::enablePainting( int reason ) + { + sceneWindow()->enablePainting( reason ); + } + +void EffectWindow::disablePainting( int reason ) + { + sceneWindow()->disablePainting( reason ); + } + int EffectWindow::desktop() const { return toplevel->desktop(); diff --git a/effects.h b/effects.h index b83f194682..f18396690d 100644 --- a/effects.h +++ b/effects.h @@ -169,6 +169,8 @@ class EffectWindow EffectWindow(); const Toplevel* window() const; Toplevel* window(); + void enablePainting( int reason ); + void disablePainting( int reason ); bool isOnDesktop( int d ) const; bool isOnCurrentDesktop() const; bool isOnAllDesktops() const; diff --git a/effects/desktopchangeslide.cpp b/effects/desktopchangeslide.cpp index 015408c72b..343c72e71f 100644 --- a/effects/desktopchangeslide.cpp +++ b/effects/desktopchangeslide.cpp @@ -40,9 +40,9 @@ void DesktopChangeSlideEffect::prePaintWindow( EffectWindow* w, int* mask, QRegi if( painting_old_desktop ) { if( w->isOnDesktop( old_desktop ) && !w->isOnCurrentDesktop()) - *mask &= ~Scene::PAINT_WINDOW_DISABLED; // paint windows on old desktop + w->enablePainting( Scene::Window::PAINT_DISABLED_BY_DESKTOP ); else - *mask |= Scene::PAINT_WINDOW_DISABLED; + w->disablePainting( Scene::Window::PAINT_DISABLED_BY_DESKTOP ); } else { diff --git a/effects/fadeout.cpp b/effects/fadeout.cpp index 016fba62c8..2c4e9020b0 100644 --- a/effects/fadeout.cpp +++ b/effects/fadeout.cpp @@ -24,7 +24,8 @@ void FadeOutEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* region, if( windows[ w ] > 0 ) { *mask |= Scene::PAINT_WINDOW_TRANSLUCENT; - *mask &= ~( Scene::PAINT_WINDOW_OPAQUE | Scene::PAINT_WINDOW_DISABLED ); + *mask &= ~Scene::PAINT_WINDOW_OPAQUE; + w->enablePainting( Scene::Window::PAINT_DISABLED_BY_DELETE ); } else { diff --git a/effects/minimizeanimation.cpp b/effects/minimizeanimation.cpp index ab295341c6..165f7af2e1 100644 --- a/effects/minimizeanimation.cpp +++ b/effects/minimizeanimation.cpp @@ -62,7 +62,7 @@ void MinimizeAnimationEffect::prePaintWindow( EffectWindow* w, int* mask, QRegio { // We'll transform this window *mask |= Scene::PAINT_WINDOW_TRANSFORMED; - *mask &= ~Scene::PAINT_WINDOW_DISABLED; + w->enablePainting( Scene::Window::PAINT_DISABLED_BY_MINIMIZE ); } else // Animation just finished diff --git a/effects/presentwindows.cpp b/effects/presentwindows.cpp index 3e1e6a518e..44a86d54f4 100644 --- a/effects/presentwindows.cpp +++ b/effects/presentwindows.cpp @@ -69,7 +69,7 @@ void PresentWindowsEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* { // This window will be transformed by the effect *mask |= Scene::PAINT_WINDOW_TRANSFORMED; - *mask &= ~Scene::PAINT_WINDOW_DISABLED; + w->enablePainting( Scene::Window::PAINT_DISABLED_BY_MINIMIZE ); // If it's minimized window and effect is not fully active, then apply // some transparency if( mActiveness < 1.0f && static_cast< Client* >( w->window() )->isMinimized() ) diff --git a/scene.cpp b/scene.cpp index 6f176c212d..4d74a4ee91 100644 --- a/scene.cpp +++ b/scene.cpp @@ -160,12 +160,11 @@ void Scene::paintGenericScreen( int orig_mask, ScreenPaintData ) foreach( Window* w, stacking_order ) // bottom to top { int mask = orig_mask | ( w->isOpaque() ? PAINT_WINDOW_OPAQUE : PAINT_WINDOW_TRANSLUCENT ); - if( !w->isVisible()) - mask |= PAINT_WINDOW_DISABLED; + w->resetPaintingEnabled(); QRegion damage = infiniteRegion(); // preparation step effects->prePaintWindow( effectWindow( w ), &mask, &damage, time_diff ); - if( mask & PAINT_WINDOW_DISABLED ) + if( !w->isPaintingEnabled()) continue; paintWindow( w, mask, damage ); } @@ -191,12 +190,11 @@ void Scene::paintSimpleScreen( int orig_mask, QRegion region ) if( region.isEmpty()) // completely clipped continue; int mask = orig_mask | ( w->isOpaque() ? PAINT_WINDOW_OPAQUE : PAINT_WINDOW_TRANSLUCENT ); - if( !w->isVisible()) - mask |= PAINT_WINDOW_DISABLED; + w->resetPaintingEnabled(); QRegion damage = region; // preparation step effects->prePaintWindow( effectWindow( w ), &mask, &damage, time_diff ); - if( mask & PAINT_WINDOW_DISABLED ) + if( !w->isPaintingEnabled()) continue; // If the window is transparent, the transparent part will be done // in the 2nd pass. @@ -243,6 +241,7 @@ void Scene::finalPaintWindow( EffectWindow* w, int mask, QRegion region, WindowP Scene::Window::Window( Toplevel * c ) : toplevel( c ) , filter( ImageFilterFast ) + , disable_painting( 0 ) , shape_valid( false ) { } @@ -314,4 +313,33 @@ bool Scene::Window::isOpaque() const return toplevel->opacity() == 1.0 && !toplevel->hasAlpha(); } +bool Scene::Window::isPaintingEnabled() const + { + return !disable_painting; + } + +void Scene::Window::resetPaintingEnabled() + { + disable_painting = 0; + if( dynamic_cast< Deleted* >( toplevel ) != NULL ) + disable_painting |= PAINT_DISABLED_BY_DELETE; + if( !toplevel->isOnCurrentDesktop()) + disable_painting |= PAINT_DISABLED_BY_DESKTOP; + if( Client* c = dynamic_cast< Client* >( toplevel )) + { + if( c->isMinimized() ) + disable_painting |= PAINT_DISABLED_BY_MINIMIZE; + } + } + +void Scene::Window::enablePainting( int reason ) + { + disable_painting &= ~reason; + } + +void Scene::Window::disablePainting( int reason ) + { + disable_painting |= reason; + } + } // namespace diff --git a/scene.h b/scene.h index d7e5eb9fab..ab7c9e3b76 100644 --- a/scene.h +++ b/scene.h @@ -58,18 +58,15 @@ class Scene PAINT_WINDOW_TRANSLUCENT = 1 << 1, // Window will be painted with transformed geometry. PAINT_WINDOW_TRANSFORMED = 1 << 2, - // When set, the window won't be painted (set by default - // for hidden windows, can be unset in pre-paint). - PAINT_WINDOW_DISABLED = 1 << 3, // Paint only a region of the screen (can be optimized, cannot // be used together with TRANSFORMED flags). - PAINT_SCREEN_REGION = 1 << 4, + PAINT_SCREEN_REGION = 1 << 3, // Whole screen will be painted with transformed geometry. - PAINT_SCREEN_TRANSFORMED = 1 << 5, + PAINT_SCREEN_TRANSFORMED = 1 << 4, // At least one window will be painted with transformed geometry. - PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS = 1 << 6, + PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS = 1 << 5, // Clear whole background as the very first step, without optimizing it - PAINT_SCREEN_BACKGROUND_FIRST = 1 << 7 + PAINT_SCREEN_BACKGROUND_FIRST = 1 << 6 }; // types of filtering available enum ImageFilterType { ImageFilterFast, ImageFilterGood }; @@ -132,6 +129,23 @@ class Scene::Window // access to the internal window class // TODO eventually get rid of this Toplevel* window(); + // should the window be painted + bool isPaintingEnabled() const; + void resetPaintingEnabled(); + // Flags explaining why painting should be disabled + enum + { + // Window will not be painted + PAINT_DISABLED = 1 << 0, + // Window will not be painted because it is deleted + PAINT_DISABLED_BY_DELETE = 1 << 1, + // Window will not be painted because of which desktop it's on + PAINT_DISABLED_BY_DESKTOP = 1 << 2, + // Window will not be painted because it is minimized + PAINT_DISABLED_BY_MINIMIZE = 1 << 3, + }; + void enablePainting( int reason ); + void disablePainting( int reason ); // is the window visible at all bool isVisible() const; // is the window fully opaque @@ -145,6 +159,7 @@ class Scene::Window Toplevel* toplevel; ImageFilterType filter; private: + int disable_painting; mutable QRegion shape_region; mutable bool shape_valid; }; diff --git a/scene_xrender.cpp b/scene_xrender.cpp index fecd8f43c7..7ec6d42942 100644 --- a/scene_xrender.cpp +++ b/scene_xrender.cpp @@ -169,12 +169,11 @@ void SceneXrender::paintTransformedScreen( int orig_mask ) if( region.isEmpty()) // completely clipped continue; int mask = orig_mask | ( w->isOpaque() ? PAINT_WINDOW_OPAQUE : PAINT_WINDOW_TRANSLUCENT ); - if( !w->isVisible()) - mask |= PAINT_WINDOW_DISABLED; + w->resetPaintingEnabled(); QRegion damage = region; // preparation step effects->prePaintWindow( effectWindow( w ), &mask, &damage, time_diff ); - if( mask & PAINT_WINDOW_DISABLED ) + if( !w->isPaintingEnabled()) continue; // If the window is transparent, the transparent part will be done // in the 2nd pass.