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
This commit is contained in:
Philip Falkner 2007-02-11 17:36:32 +00:00
parent 949aa1a778
commit c16656d66d
10 changed files with 77 additions and 22 deletions

View file

@ -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

View file

@ -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();

View file

@ -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;

View file

@ -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
{

View file

@ -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
{

View file

@ -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

View file

@ -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() )

View file

@ -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

29
scene.h
View file

@ -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;
};

View file

@ -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.