Add post-painting pass to be used for triggering
repaints with animations. svn path=/branches/work/kwin_composite/; revision=600156
This commit is contained in:
parent
6b41c062c8
commit
3f9b754ee7
9 changed files with 95 additions and 36 deletions
|
@ -115,8 +115,6 @@ TODO:
|
|||
be created, but the old animation should be stopped - compare window id's?
|
||||
? maybe just keep the object around in a special list
|
||||
|
||||
* add a postpaint pass
|
||||
- needed for animations to trigger next repaint, currently window damage is reset after
|
||||
the painting pass, meaning the damage cannot be added from there
|
||||
- current workaround is to damage the whole screen, as there's a for resetting that damage
|
||||
in advance
|
||||
* 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 obscured windows
|
||||
|
|
|
@ -156,13 +156,12 @@ void Workspace::compositeTimeout()
|
|||
else if( Unmanaged* c = findUnmanaged( HandleMatchPredicate( children[ i ] )))
|
||||
windows.append( c );
|
||||
}
|
||||
effects->startPaint();
|
||||
// TODO when effects cause damage, it should be only enqueued for next repaint
|
||||
QRegion r = damage_region;
|
||||
scene->prePaint();
|
||||
scene->paint( damage_region, windows );
|
||||
damage_region = QRegion();
|
||||
scene->paint( r, windows );
|
||||
foreach( Toplevel* c, windows )
|
||||
c->resetDamage();
|
||||
scene->postPaint();
|
||||
lastCompositePaint.start();
|
||||
}
|
||||
|
||||
|
|
79
effects.cpp
79
effects.cpp
|
@ -46,6 +46,11 @@ void Effect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
|
|||
{
|
||||
effects->paintScreen( mask, region, data );
|
||||
}
|
||||
|
||||
void Effect::postPaintScreen()
|
||||
{
|
||||
effects->postPaintScreen();
|
||||
}
|
||||
|
||||
void Effect::prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int time )
|
||||
{
|
||||
|
@ -57,6 +62,11 @@ void Effect::paintWindow( Scene::Window* w, int mask, QRegion region, WindowPain
|
|||
effects->paintWindow( w, mask, region, data );
|
||||
}
|
||||
|
||||
void Effect::postPaintWindow( Scene::Window* w )
|
||||
{
|
||||
effects->postPaintWindow( w );
|
||||
}
|
||||
|
||||
void MakeHalfTransparent::prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int time )
|
||||
{
|
||||
const Client* c = dynamic_cast< const Client* >( w->window());
|
||||
|
@ -188,17 +198,9 @@ ShiftWorkspaceUp::ShiftWorkspaceUp( Workspace* ws )
|
|||
void ShiftWorkspaceUp::prePaintScreen( int* mask, QRegion* region, int time )
|
||||
{
|
||||
if( up && diff < 1000 )
|
||||
{
|
||||
diff = qBound( 0, diff + time, 1000 ); // KDE3: note this differs from KCLAMP
|
||||
if( diff < 1000 )
|
||||
wspace->addDamageFull(); // affects next redraw
|
||||
}
|
||||
if( !up && diff > 0 )
|
||||
{
|
||||
diff = qBound( 0, diff - time, 1000 );
|
||||
if( diff > 0 )
|
||||
wspace->addDamageFull(); // affects next redraw
|
||||
}
|
||||
if( diff != 0 )
|
||||
*mask |= Scene::PAINT_SCREEN_TRANSFORMED;
|
||||
effects->prePaintScreen( mask, region, time );
|
||||
|
@ -211,6 +213,13 @@ void ShiftWorkspaceUp::paintScreen( int mask, QRegion region, ScreenPaintData& d
|
|||
effects->paintScreen( mask, region, data );
|
||||
}
|
||||
|
||||
void ShiftWorkspaceUp::postPaintScreen()
|
||||
{
|
||||
if( up ? diff < 1000 : diff > 0 )
|
||||
wspace->addDamageFull(); // trigger next animation repaint
|
||||
effects->postPaintScreen();
|
||||
}
|
||||
|
||||
void ShiftWorkspaceUp::tick()
|
||||
{
|
||||
up = !up;
|
||||
|
@ -227,9 +236,6 @@ void FadeIn::prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int t
|
|||
{
|
||||
*mask |= Scene::PAINT_WINDOW_TRANSLUCENT;
|
||||
*mask &= ~Scene::PAINT_WINDOW_OPAQUE;
|
||||
// TODO this should just damage the window, but right now window
|
||||
// damage is cleared after the painting pass - a postpaint pass is needed
|
||||
w->window()->workspace()->addDamageFull();
|
||||
}
|
||||
else
|
||||
windows.remove( w->window());
|
||||
|
@ -246,6 +252,13 @@ void FadeIn::paintWindow( Scene::Window* w, int mask, QRegion region, WindowPain
|
|||
effects->paintWindow( w, mask, region, data );
|
||||
}
|
||||
|
||||
void FadeIn::postPaintWindow( Scene::Window* w )
|
||||
{
|
||||
if( windows.contains( w->window()))
|
||||
w->window()->addDamageFull(); // trigger next animation repaint
|
||||
effects->postPaintWindow( w );
|
||||
}
|
||||
|
||||
void FadeIn::windowAdded( Toplevel* c )
|
||||
{
|
||||
Client* cc = dynamic_cast< Client* >( c );
|
||||
|
@ -268,12 +281,7 @@ void ScaleIn::prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int
|
|||
{
|
||||
windows[ w->window() ] += time / 500.; // complete change in 500ms
|
||||
if( windows[ w->window() ] < 1 )
|
||||
{
|
||||
*mask |= Scene::PAINT_WINDOW_TRANSFORMED;
|
||||
// TODO this should just damage the window, but right now window
|
||||
// damage is cleared after the painting pass - a postpaint pass is needed
|
||||
w->window()->workspace()->addDamageFull();
|
||||
}
|
||||
else
|
||||
windows.remove( w->window());
|
||||
}
|
||||
|
@ -286,12 +294,19 @@ void ScaleIn::paintWindow( Scene::Window* w, int mask, QRegion region, WindowPai
|
|||
{
|
||||
data.xScale *= windows[ w->window()];
|
||||
data.yScale *= windows[ w->window()];
|
||||
data.xTranslate += w->window()->width() / 2 * ( 1 - windows[ w->window()] );
|
||||
data.yTranslate += w->window()->height() / 2 * ( 1 - windows[ w->window()] );
|
||||
data.xTranslate += int( w->window()->width() / 2 * ( 1 - windows[ w->window()] ));
|
||||
data.yTranslate += int( w->window()->height() / 2 * ( 1 - windows[ w->window()] ));
|
||||
}
|
||||
effects->paintWindow( w, mask, region, data );
|
||||
}
|
||||
|
||||
void ScaleIn::postPaintWindow( Scene::Window* w )
|
||||
{
|
||||
if( windows.contains( w->window()))
|
||||
w->window()->addDamageFull(); // trigger next animation repaint
|
||||
effects->postPaintWindow( w );
|
||||
}
|
||||
|
||||
void ScaleIn::windowAdded( Toplevel* c )
|
||||
{
|
||||
Client* cc = dynamic_cast< Client* >( c );
|
||||
|
@ -359,7 +374,7 @@ void EffectsHandler::startPaint()
|
|||
// the idea is that effects call this function again which calls the next one
|
||||
void EffectsHandler::prePaintScreen( int* mask, QRegion* region, int time )
|
||||
{
|
||||
if( current_paint_screen < effects.size() - 1 )
|
||||
if( current_paint_screen < effects.size())
|
||||
{
|
||||
effects[ current_paint_screen++ ]->prePaintScreen( mask, region, time );
|
||||
--current_paint_screen;
|
||||
|
@ -369,7 +384,7 @@ void EffectsHandler::prePaintScreen( int* mask, QRegion* region, int time )
|
|||
|
||||
void EffectsHandler::paintScreen( int mask, QRegion region, ScreenPaintData& data )
|
||||
{
|
||||
if( current_paint_screen < effects.size() - 1 )
|
||||
if( current_paint_screen < effects.size())
|
||||
{
|
||||
effects[ current_paint_screen++ ]->paintScreen( mask, region, data );
|
||||
--current_paint_screen;
|
||||
|
@ -378,9 +393,19 @@ void EffectsHandler::paintScreen( int mask, QRegion region, ScreenPaintData& dat
|
|||
scene->finalPaintScreen( mask, region, data );
|
||||
}
|
||||
|
||||
void EffectsHandler::postPaintScreen()
|
||||
{
|
||||
if( current_paint_screen < effects.size())
|
||||
{
|
||||
effects[ current_paint_screen++ ]->postPaintScreen();
|
||||
--current_paint_screen;
|
||||
}
|
||||
// no special final code
|
||||
}
|
||||
|
||||
void EffectsHandler::prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int time )
|
||||
{
|
||||
if( current_paint_window < effects.size() - 1 )
|
||||
if( current_paint_window < effects.size())
|
||||
{
|
||||
effects[ current_paint_window++ ]->prePaintWindow( w, mask, region, time );
|
||||
--current_paint_window;
|
||||
|
@ -390,7 +415,7 @@ void EffectsHandler::prePaintWindow( Scene::Window* w, int* mask, QRegion* regio
|
|||
|
||||
void EffectsHandler::paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data )
|
||||
{
|
||||
if( current_paint_window < effects.size() - 1 )
|
||||
if( current_paint_window < effects.size())
|
||||
{
|
||||
effects[ current_paint_window++ ]->paintWindow( w, mask, region, data );
|
||||
--current_paint_window;
|
||||
|
@ -399,6 +424,16 @@ void EffectsHandler::paintWindow( Scene::Window* w, int mask, QRegion region, Wi
|
|||
scene->finalPaintWindow( w, mask, region, data );
|
||||
}
|
||||
|
||||
void EffectsHandler::postPaintWindow( Scene::Window* w )
|
||||
{
|
||||
if( current_paint_window < effects.size())
|
||||
{
|
||||
effects[ current_paint_window++ ]->postPaintWindow( w );
|
||||
--current_paint_window;
|
||||
}
|
||||
// no special final code
|
||||
}
|
||||
|
||||
EffectsHandler* effects;
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -50,8 +50,10 @@ class Effect
|
|||
virtual ~Effect();
|
||||
virtual void prePaintScreen( int* mask, QRegion* region, int time );
|
||||
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
|
||||
virtual void postPaintScreen();
|
||||
virtual void prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int time );
|
||||
virtual void paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data );
|
||||
virtual void postPaintWindow( Scene::Window* w );
|
||||
// called when moved/resized or once after it's finished
|
||||
virtual void windowUserMovedResized( Toplevel* c, bool first, bool last );
|
||||
virtual void windowAdded( Toplevel* c );
|
||||
|
@ -66,8 +68,10 @@ class EffectsHandler
|
|||
// for use by effects
|
||||
void prePaintScreen( int* mask, QRegion* region, int time );
|
||||
void paintScreen( int mask, QRegion region, ScreenPaintData& data );
|
||||
void postPaintScreen();
|
||||
void prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int time );
|
||||
void paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data );
|
||||
void postPaintWindow( Scene::Window* w );
|
||||
// internal (used by kwin core or compositing code)
|
||||
void startPaint();
|
||||
void windowUserMovedResized( Toplevel* c, bool first, bool last );
|
||||
|
@ -126,6 +130,7 @@ class ShiftWorkspaceUp
|
|||
ShiftWorkspaceUp( Workspace* ws );
|
||||
virtual void prePaintScreen( int* mask, QRegion* region, int time );
|
||||
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
|
||||
virtual void postPaintScreen();
|
||||
private slots:
|
||||
void tick();
|
||||
private:
|
||||
|
@ -141,6 +146,7 @@ class FadeIn
|
|||
public:
|
||||
virtual void prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int time );
|
||||
virtual void paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data );
|
||||
virtual void postPaintWindow( Scene::Window* w );
|
||||
// TODO react also on virtual desktop changes
|
||||
virtual void windowAdded( Toplevel* c );
|
||||
virtual void windowDeleted( Toplevel* c );
|
||||
|
@ -154,6 +160,7 @@ class ScaleIn
|
|||
public:
|
||||
virtual void prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int time );
|
||||
virtual void paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data );
|
||||
virtual void postPaintWindow( Scene::Window* w );
|
||||
// TODO react also on virtual desktop changes
|
||||
virtual void windowAdded( Toplevel* c );
|
||||
virtual void windowDeleted( Toplevel* c );
|
||||
|
|
14
scene.cpp
14
scene.cpp
|
@ -33,6 +33,12 @@ Scene::~Scene()
|
|||
{
|
||||
}
|
||||
|
||||
void Scene::prePaint()
|
||||
{
|
||||
effects->startPaint();
|
||||
// do the rest of prepaint pass together with paint pass
|
||||
}
|
||||
|
||||
// returns mask and possibly modified region
|
||||
void Scene::paintScreen( int* mask, QRegion* region )
|
||||
{
|
||||
|
@ -148,6 +154,14 @@ void Scene::finalPaintWindow( Scene::Window* w, int mask, QRegion region, Window
|
|||
w->performPaint( mask, region, data );
|
||||
}
|
||||
|
||||
void Scene::postPaint()
|
||||
{
|
||||
effects->postPaintScreen();
|
||||
foreach( Window* w, stacking_order )
|
||||
effects->postPaintWindow( w );
|
||||
stacking_order.clear();
|
||||
}
|
||||
|
||||
void Scene::windowGeometryShapeChanged( Toplevel* )
|
||||
{
|
||||
}
|
||||
|
|
6
scene.h
6
scene.h
|
@ -29,8 +29,10 @@ class Scene
|
|||
Scene( Workspace* ws );
|
||||
virtual ~Scene() = 0;
|
||||
class Window;
|
||||
virtual void prePaint();
|
||||
// repaints the given screen areas, windows provides the stacking order
|
||||
virtual void paint( QRegion damage, ToplevelList windows ) = 0;
|
||||
virtual void postPaint();
|
||||
// shape/size of a window changed
|
||||
virtual void windowGeometryShapeChanged( Toplevel* );
|
||||
// opacity of a window changed
|
||||
|
@ -84,7 +86,7 @@ class Scene::Window
|
|||
int y() const;
|
||||
int width() const;
|
||||
int height() const;
|
||||
const Toplevel* window() const;
|
||||
Toplevel* window();
|
||||
bool isVisible() const;
|
||||
bool isOpaque() const;
|
||||
QRegion shape() const;
|
||||
|
@ -130,7 +132,7 @@ int Scene::Window::height() const
|
|||
}
|
||||
|
||||
inline
|
||||
const Toplevel* Scene::Window::window() const
|
||||
Toplevel* Scene::Window::window()
|
||||
{
|
||||
return toplevel;
|
||||
}
|
||||
|
|
|
@ -279,7 +279,6 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels )
|
|||
glTranslatef( 0, -displayHeight(), 0 );
|
||||
int mask = 0;
|
||||
paintScreen( &mask, &damage );
|
||||
stacking_order.clear();
|
||||
glPopMatrix();
|
||||
// TODO only partial repaint for mask & PAINT_SCREEN_REGION
|
||||
if( root_db )
|
||||
|
@ -292,7 +291,6 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels )
|
|||
XFlush( display());
|
||||
}
|
||||
ungrabXServer();
|
||||
checkGLError( "PostPaint" );
|
||||
}
|
||||
|
||||
void SceneOpenGL::paintGenericScreen( int mask, ScreenPaintData data )
|
||||
|
@ -320,6 +318,12 @@ void SceneOpenGL::paintBackground( QRegion )
|
|||
// TODO?
|
||||
}
|
||||
|
||||
void SceneOpenGL::postPaint()
|
||||
{
|
||||
checkGLError( "PostPaint" );
|
||||
Scene::postPaint();
|
||||
}
|
||||
|
||||
void SceneOpenGL::windowAdded( Toplevel* c )
|
||||
{
|
||||
assert( !windows.contains( c ));
|
||||
|
|
|
@ -26,6 +26,7 @@ class SceneOpenGL
|
|||
SceneOpenGL( Workspace* ws );
|
||||
virtual ~SceneOpenGL();
|
||||
virtual void paint( QRegion damage, ToplevelList windows );
|
||||
virtual void postPaint();
|
||||
virtual void windowGeometryShapeChanged( Toplevel* );
|
||||
virtual void windowOpacityChanged( Toplevel* );
|
||||
virtual void windowAdded( Toplevel* );
|
||||
|
|
|
@ -86,7 +86,6 @@ void SceneXrender::paint( QRegion damage, ToplevelList toplevels )
|
|||
}
|
||||
int mask = 0;
|
||||
paintScreen( &mask, &damage );
|
||||
stacking_order.clear();
|
||||
if( mask & PAINT_SCREEN_REGION )
|
||||
{
|
||||
// Use the damage region as the clip region for the root window
|
||||
|
|
Loading…
Reference in a new issue