Ok, I give up, whoever wants more complicated transformations than just
translation are welcome to implement it themselves. I'm no graphics guy after all and this seems to be far beyond me. svn path=/branches/work/kwin_composite/; revision=559182
This commit is contained in:
parent
3da31a53af
commit
e6c23e4cd3
9 changed files with 191 additions and 100 deletions
|
@ -165,8 +165,7 @@ void Workspace::compositeTimeout()
|
||||||
else if( Unmanaged* c = findUnmanaged( HandleMatchPredicate( children[ i ] )))
|
else if( Unmanaged* c = findUnmanaged( HandleMatchPredicate( children[ i ] )))
|
||||||
windows.append( c );
|
windows.append( c );
|
||||||
}
|
}
|
||||||
scene->setWindows( windows );
|
scene->paint( damage, windows );
|
||||||
scene->paint( damage );
|
|
||||||
XFixesDestroyRegion( display(), damage );
|
XFixesDestroyRegion( display(), damage );
|
||||||
damage = None;
|
damage = None;
|
||||||
}
|
}
|
||||||
|
|
54
effects.cpp
54
effects.cpp
|
@ -132,11 +132,11 @@ void Effect::windowUserMovedResized( Toplevel* , bool, bool )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Effect::transformWindow( Toplevel*, EffectData& )
|
void Effect::transformWindow( Toplevel*, Matrix&, EffectData& )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Effect::transformWorkspace( Workspace*, EffectData& )
|
void Effect::transformWorkspace( Workspace*, Matrix&, EffectData& )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ void Effect::windowDeleted( Toplevel* )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void MakeHalfTransparent::transformWindow( Toplevel* c, EffectData& data )
|
void MakeHalfTransparent::transformWindow( Toplevel* c, Matrix&, EffectData& data )
|
||||||
{
|
{
|
||||||
if( c->isDialog())
|
if( c->isDialog())
|
||||||
data.opacity *= 0.8;
|
data.opacity *= 0.8;
|
||||||
|
@ -167,13 +167,13 @@ ShakyMove::ShakyMove()
|
||||||
static const int shaky_diff[] = { 0, 1, 2, 3, 2, 1, 0, -1, -2, -3, -2, -1 };
|
static const int shaky_diff[] = { 0, 1, 2, 3, 2, 1, 0, -1, -2, -3, -2, -1 };
|
||||||
static const int SHAKY_MAX = sizeof( shaky_diff ) / sizeof( shaky_diff[ 0 ] );
|
static const int SHAKY_MAX = sizeof( shaky_diff ) / sizeof( shaky_diff[ 0 ] );
|
||||||
|
|
||||||
void ShakyMove::transformWindow( Toplevel* c, EffectData& data )
|
void ShakyMove::transformWindow( Toplevel* c, Matrix& matrix, EffectData& )
|
||||||
{
|
{
|
||||||
if( windows.contains( c ))
|
if( windows.contains( c ))
|
||||||
{
|
{
|
||||||
Matrix m;
|
Matrix m;
|
||||||
m.m[ 0 ][ 3 ] = shaky_diff[ windows[ c ]];
|
m.m[ 0 ][ 3 ] = shaky_diff[ windows[ c ]];
|
||||||
data.matrix *= m;
|
matrix *= m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,8 +217,31 @@ void ShakyMove::tick()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GrowMove::transformWindow( Toplevel* c, Matrix& matrix, EffectData& )
|
||||||
|
{
|
||||||
|
if( Client* c2 = dynamic_cast< Client* >( c ))
|
||||||
|
if( c2->isMove())
|
||||||
|
{
|
||||||
|
Matrix m;
|
||||||
|
m.m[ 0 ][ 0 ] = 1.2;
|
||||||
|
m.m[ 1 ][ 1 ] = 1.4;
|
||||||
|
matrix *= m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GrowMove::windowUserMovedResized( Toplevel* c, bool first, bool last )
|
||||||
|
{
|
||||||
|
if( first || last )
|
||||||
|
{
|
||||||
|
c->workspace()->addDamage( c, c->geometry());
|
||||||
|
scene->updateTransformation( c );
|
||||||
|
c->workspace()->addDamage( c, c->geometry());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static MakeHalfTransparent* mht;
|
static MakeHalfTransparent* mht;
|
||||||
static ShakyMove* sm;
|
static ShakyMove* sm;
|
||||||
|
static GrowMove* gm;
|
||||||
|
|
||||||
//****************************************
|
//****************************************
|
||||||
// EffectsHandler
|
// EffectsHandler
|
||||||
|
@ -228,6 +251,7 @@ EffectsHandler::EffectsHandler()
|
||||||
{
|
{
|
||||||
mht = new MakeHalfTransparent;
|
mht = new MakeHalfTransparent;
|
||||||
sm = new ShakyMove;
|
sm = new ShakyMove;
|
||||||
|
// gm = new GrowMove;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectsHandler::windowUserMovedResized( Toplevel* c, bool first, bool last )
|
void EffectsHandler::windowUserMovedResized( Toplevel* c, bool first, bool last )
|
||||||
|
@ -236,22 +260,28 @@ void EffectsHandler::windowUserMovedResized( Toplevel* c, bool first, bool last
|
||||||
mht->windowUserMovedResized( c, first, last );
|
mht->windowUserMovedResized( c, first, last );
|
||||||
if( sm )
|
if( sm )
|
||||||
sm->windowUserMovedResized( c, first, last );
|
sm->windowUserMovedResized( c, first, last );
|
||||||
|
if( gm )
|
||||||
|
gm->windowUserMovedResized( c, first, last );
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectsHandler::transformWindow( Toplevel* c, EffectData& data )
|
void EffectsHandler::transformWindow( Toplevel* c, Matrix& matrix, EffectData& data )
|
||||||
{
|
{
|
||||||
if( mht )
|
if( mht )
|
||||||
mht->transformWindow( c, data );
|
mht->transformWindow( c, matrix, data );
|
||||||
if( sm )
|
if( sm )
|
||||||
sm->transformWindow( c, data );
|
sm->transformWindow( c, matrix, data );
|
||||||
|
if( gm )
|
||||||
|
gm->transformWindow( c, matrix, data );
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectsHandler::transformWorkspace( Workspace* w, EffectData& data )
|
void EffectsHandler::transformWorkspace( Workspace* w, Matrix& matrix, EffectData& data )
|
||||||
{
|
{
|
||||||
if( mht )
|
if( mht )
|
||||||
mht->transformWorkspace( w, data );
|
mht->transformWorkspace( w, matrix, data );
|
||||||
if( sm )
|
if( sm )
|
||||||
sm->transformWorkspace( w, data );
|
sm->transformWorkspace( w, matrix, data );
|
||||||
|
if( gm )
|
||||||
|
gm->transformWorkspace( w, matrix, data );
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectsHandler::windowDeleted( Toplevel* c )
|
void EffectsHandler::windowDeleted( Toplevel* c )
|
||||||
|
@ -260,6 +290,8 @@ void EffectsHandler::windowDeleted( Toplevel* c )
|
||||||
mht->windowDeleted( c );
|
mht->windowDeleted( c );
|
||||||
if( sm )
|
if( sm )
|
||||||
sm->windowDeleted( c );
|
sm->windowDeleted( c );
|
||||||
|
if( gm )
|
||||||
|
gm->windowDeleted( c );
|
||||||
}
|
}
|
||||||
|
|
||||||
EffectsHandler* effects;
|
EffectsHandler* effects;
|
||||||
|
|
20
effects.h
20
effects.h
|
@ -62,7 +62,6 @@ inline double Matrix::zTranslate() const
|
||||||
class EffectData
|
class EffectData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Matrix matrix;
|
|
||||||
double opacity;
|
double opacity;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -73,8 +72,8 @@ class Effect
|
||||||
// called when moved/resized or once after it's finished
|
// called when moved/resized or once after it's finished
|
||||||
virtual void windowUserMovedResized( Toplevel* c, bool first, bool last );
|
virtual void windowUserMovedResized( Toplevel* c, bool first, bool last );
|
||||||
virtual void windowDeleted( Toplevel* c );
|
virtual void windowDeleted( Toplevel* c );
|
||||||
virtual void transformWindow( Toplevel* c, EffectData& data );
|
virtual void transformWindow( Toplevel* c, Matrix& m, EffectData& data );
|
||||||
virtual void transformWorkspace( Workspace*, EffectData& data );
|
virtual void transformWorkspace( Workspace*, Matrix& m, EffectData& data );
|
||||||
};
|
};
|
||||||
|
|
||||||
class EffectsHandler
|
class EffectsHandler
|
||||||
|
@ -83,8 +82,8 @@ class EffectsHandler
|
||||||
EffectsHandler();
|
EffectsHandler();
|
||||||
void windowUserMovedResized( Toplevel* c, bool first, bool last );
|
void windowUserMovedResized( Toplevel* c, bool first, bool last );
|
||||||
void windowDeleted( Toplevel* c );
|
void windowDeleted( Toplevel* c );
|
||||||
void transformWindow( Toplevel* c, EffectData& data );
|
void transformWindow( Toplevel* c, Matrix& m, EffectData& data );
|
||||||
void transformWorkspace( Workspace*, EffectData& data );
|
void transformWorkspace( Workspace*, Matrix& m, EffectData& data );
|
||||||
};
|
};
|
||||||
|
|
||||||
extern EffectsHandler* effects;
|
extern EffectsHandler* effects;
|
||||||
|
@ -94,7 +93,7 @@ class MakeHalfTransparent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void windowUserMovedResized( Toplevel* c, bool first, bool last );
|
virtual void windowUserMovedResized( Toplevel* c, bool first, bool last );
|
||||||
virtual void transformWindow( Toplevel* c, EffectData& data );
|
virtual void transformWindow( Toplevel* c, Matrix& m, EffectData& data );
|
||||||
};
|
};
|
||||||
|
|
||||||
class ShakyMove
|
class ShakyMove
|
||||||
|
@ -104,7 +103,7 @@ class ShakyMove
|
||||||
public:
|
public:
|
||||||
ShakyMove();
|
ShakyMove();
|
||||||
virtual void windowUserMovedResized( Toplevel* c, bool first, bool last );
|
virtual void windowUserMovedResized( Toplevel* c, bool first, bool last );
|
||||||
virtual void transformWindow( Toplevel* c, EffectData& data );
|
virtual void transformWindow( Toplevel* c, Matrix& m, EffectData& data );
|
||||||
virtual void windowDeleted( Toplevel* c );
|
virtual void windowDeleted( Toplevel* c );
|
||||||
private slots:
|
private slots:
|
||||||
void tick();
|
void tick();
|
||||||
|
@ -113,6 +112,13 @@ class ShakyMove
|
||||||
QTimer timer;
|
QTimer timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GrowMove
|
||||||
|
: public Effect
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void windowUserMovedResized( Toplevel* c, bool first, bool last );
|
||||||
|
virtual void transformWindow( Toplevel* c, Matrix& m, EffectData& data );
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
|
@ -26,11 +26,6 @@ Scene::~Scene()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::setWindows( const ToplevelList& list )
|
|
||||||
{
|
|
||||||
windows = list;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scene::windowGeometryShapeChanged( Toplevel* )
|
void Scene::windowGeometryShapeChanged( Toplevel* )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
4
scene.h
4
scene.h
|
@ -23,8 +23,7 @@ class Scene
|
||||||
public:
|
public:
|
||||||
Scene( Workspace* ws );
|
Scene( Workspace* ws );
|
||||||
virtual ~Scene();
|
virtual ~Scene();
|
||||||
void setWindows( const ToplevelList& list );
|
virtual void paint( XserverRegion damage, ToplevelList windows ) = 0;
|
||||||
virtual void paint( XserverRegion damage ) = 0;
|
|
||||||
virtual void windowGeometryShapeChanged( Toplevel* );
|
virtual void windowGeometryShapeChanged( Toplevel* );
|
||||||
virtual void windowOpacityChanged( Toplevel* );
|
virtual void windowOpacityChanged( Toplevel* );
|
||||||
virtual void windowDeleted( Toplevel* );
|
virtual void windowDeleted( Toplevel* );
|
||||||
|
@ -32,7 +31,6 @@ class Scene
|
||||||
virtual void updateTransformation( Toplevel* );
|
virtual void updateTransformation( Toplevel* );
|
||||||
protected:
|
protected:
|
||||||
Workspace* wspace;
|
Workspace* wspace;
|
||||||
ToplevelList windows;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Scene* scene;
|
extern Scene* scene;
|
||||||
|
|
|
@ -29,7 +29,7 @@ SceneBasic::~SceneBasic()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneBasic::paint( XserverRegion )
|
void SceneBasic::paint( XserverRegion, ToplevelList windows )
|
||||||
{
|
{
|
||||||
Pixmap composite_pixmap = XCreatePixmap( display(), rootWindow(), displayWidth(), displayHeight(), QX11Info::appDepth());
|
Pixmap composite_pixmap = XCreatePixmap( display(), rootWindow(), displayWidth(), displayHeight(), QX11Info::appDepth());
|
||||||
XGCValues val;
|
XGCValues val;
|
||||||
|
|
|
@ -22,7 +22,7 @@ class SceneBasic
|
||||||
public:
|
public:
|
||||||
SceneBasic( Workspace* ws );
|
SceneBasic( Workspace* ws );
|
||||||
virtual ~SceneBasic();
|
virtual ~SceneBasic();
|
||||||
virtual void paint( XserverRegion damage );
|
virtual void paint( XserverRegion damage, ToplevelList windows );
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -42,9 +42,9 @@ SceneXrender::~SceneXrender()
|
||||||
(*it).free();
|
(*it).free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneXrender::paint( XserverRegion damage )
|
void SceneXrender::paint( XserverRegion damage, ToplevelList windows )
|
||||||
{
|
{
|
||||||
#if 0
|
#if 1
|
||||||
XRectangle r;
|
XRectangle r;
|
||||||
r.x = 0;
|
r.x = 0;
|
||||||
r.y = 0;
|
r.y = 0;
|
||||||
|
@ -54,8 +54,38 @@ void SceneXrender::paint( XserverRegion damage )
|
||||||
#endif
|
#endif
|
||||||
// Use the damage region as the clip region for the root window
|
// Use the damage region as the clip region for the root window
|
||||||
XFixesSetPictureClipRegion( display(), front, 0, 0, damage );
|
XFixesSetPictureClipRegion( display(), front, 0, 0, damage );
|
||||||
// Client list for clients that are either translucent or have a shadow
|
// Prepare pass for windows
|
||||||
ToplevelList translucents;
|
// Go top to bottom so that clipping is computed properly for phase1
|
||||||
|
for( int i = windows.count() - 1;
|
||||||
|
i >= 0;
|
||||||
|
--i )
|
||||||
|
{
|
||||||
|
Toplevel* c = windows[ i ];
|
||||||
|
resetWindowData( c );
|
||||||
|
WindowData& data = window_data[ c ];
|
||||||
|
Picture picture = windowPicture( c );
|
||||||
|
if( picture == None ) // The render format can be null for GL and/or Xv visuals
|
||||||
|
{
|
||||||
|
windows.removeAt( i );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
effects->transformWindow( c, data.matrix, data.effect ); // TODO remove, instead add initWindow() to effects
|
||||||
|
saveWindowClipRegion( c, damage );
|
||||||
|
if( data.simpleTransformation() && isOpaque( c ))
|
||||||
|
{ // is opaque, has simple shape, can be clipped, will be painted using simpler faster method
|
||||||
|
// Subtract the clients shape from the damage region
|
||||||
|
XserverRegion shape = windowShape( c );
|
||||||
|
assert( shape != None );
|
||||||
|
XFixesSubtractRegion( display(), damage, damage, shape );
|
||||||
|
data.phase = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
data.phase = 2; // will be painted later bottom to top
|
||||||
|
}
|
||||||
|
// Fill any areas of the root window not covered by windows
|
||||||
|
XFixesSetPictureClipRegion( display(), buffer, 0, 0, damage );
|
||||||
|
XRenderColor col = { 0xffff, 0xffff, 0xffff, 0xffff };
|
||||||
|
XRenderFillRectangle( display(), PictOpSrc, buffer, &col, 0, 0, displayWidth(), displayHeight());
|
||||||
// Draw each opaque window top to bottom, subtracting the bounding rect of
|
// Draw each opaque window top to bottom, subtracting the bounding rect of
|
||||||
// each window from the clip region after it's been drawn.
|
// each window from the clip region after it's been drawn.
|
||||||
for( int i = windows.count() - 1;
|
for( int i = windows.count() - 1;
|
||||||
|
@ -63,59 +93,50 @@ void SceneXrender::paint( XserverRegion damage )
|
||||||
--i )
|
--i )
|
||||||
{
|
{
|
||||||
Toplevel* c = windows[ i ];
|
Toplevel* c = windows[ i ];
|
||||||
checkWindowData( c );
|
|
||||||
WindowData& data = window_data[ c ];
|
WindowData& data = window_data[ c ];
|
||||||
effects->transformWindow( c, data.effect ); // TODO remove, instead add initWindow() to effects
|
if( data.phase != 1 )
|
||||||
if( isOpaque( c ))
|
continue;
|
||||||
{
|
XFixesSetPictureClipRegion( display(), buffer, 0, 0, savedWindowClipRegion( c ));
|
||||||
Picture picture = windowPicture( c );
|
Picture picture = windowPicture( c );
|
||||||
XserverRegion shape = windowShape( c );
|
XRenderComposite( display(), PictOpSrc, picture, None, buffer, 0, 0, 0, 0,
|
||||||
if( picture != None && shape != None )
|
c->x() + int( data.matrix.xTranslate()), c->y() + int( data.matrix.yTranslate()), c->width(), c->height());
|
||||||
{
|
|
||||||
// Set the clip region for the buffer to the damage region, and
|
|
||||||
// subtract the clients shape from the damage region
|
|
||||||
XFixesSetPictureClipRegion( display(), buffer, 0, 0, damage );
|
|
||||||
const Matrix& matrix = data.effect.matrix;
|
|
||||||
if( !matrix.isIdentity())
|
|
||||||
{
|
|
||||||
assert( matrix.isOnlyTranslate());
|
|
||||||
XFixesTranslateRegion( display(), shape, int( matrix.xTranslate()), int( matrix.yTranslate()));
|
|
||||||
}
|
|
||||||
XFixesSubtractRegion( display(), damage, damage, shape );
|
|
||||||
XRenderComposite( display(), PictOpSrc, picture, None, buffer, 0, 0, 0, 0,
|
|
||||||
c->x() + int( matrix.xTranslate()), c->y() + int( matrix.yTranslate()), c->width(), c->height());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
saveWindowClipRegion( c, damage );
|
|
||||||
translucents.prepend( c );
|
|
||||||
}
|
}
|
||||||
// Fill any areas of the root window not covered by windows
|
// Now walk the list bottom to top, drawing translucent and complicated windows.
|
||||||
XFixesSetPictureClipRegion( display(), buffer, 0, 0, damage );
|
// That we draw bottom to top is important now since we're drawing translucent objects
|
||||||
XRenderColor col = { 0xffff, 0xffff, 0xffff, 0xffff };
|
// and also are clipping only by opaque windows.
|
||||||
XRenderFillRectangle( display(), PictOpSrc, buffer, &col, 0, 0, displayWidth(), displayHeight());
|
|
||||||
// Now walk the list bottom to top, drawing translucent windows and shadows.
|
|
||||||
// That we draw bottom to top is important now since we're drawing translucent objects.
|
|
||||||
for( int i = 0;
|
for( int i = 0;
|
||||||
i < translucents.count();
|
i < windows.count();
|
||||||
++i )
|
++i )
|
||||||
{
|
{
|
||||||
Toplevel* c = translucents[ i ];
|
Toplevel* c = windows[ i ];
|
||||||
// Restore the previously saved clip region
|
WindowData& data = window_data[ c ];
|
||||||
XserverRegion r = savedWindowClipRegion( c );
|
if( data.phase != 2 && false)
|
||||||
XFixesSetPictureClipRegion( display(), buffer, 0, 0, r );
|
continue;
|
||||||
if( !isOpaque( c ))
|
XFixesSetPictureClipRegion( display(), buffer, 0, 0, savedWindowClipRegion( c ));
|
||||||
|
Picture picture = windowPicture( c );
|
||||||
|
Picture alpha = windowAlphaMask( c );
|
||||||
|
if( data.simpleTransformation())
|
||||||
{
|
{
|
||||||
Picture picture = windowPicture( c );
|
XRenderComposite( display(), PictOpOver, picture, alpha, buffer, 0, 0, 0, 0,
|
||||||
Picture alpha = windowAlphaMask( c );
|
c->x() + int( data.matrix.xTranslate()), c->y() + int( data.matrix.yTranslate()), c->width(), c->height());
|
||||||
if( picture != None )
|
|
||||||
{
|
|
||||||
const Matrix& matrix = window_data[ c ].effect.matrix;
|
|
||||||
// TODO clip also using shape? also above?
|
|
||||||
XRenderComposite( display(), PictOpOver, picture, alpha, buffer, 0, 0, 0, 0,
|
|
||||||
c->x() + int( matrix.xTranslate()), c->y() + int( matrix.yTranslate()), c->width(), c->height());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
XFixesDestroyRegion( display(), r );
|
else
|
||||||
|
{
|
||||||
|
// TODO Okay, I'm at loss here. Whoever wants advanced transformations can implement
|
||||||
|
// it themselves. If not, they actually don't want it that badly *shrug*.
|
||||||
|
// setPictureMatrix( picture, data.matrix );
|
||||||
|
XRenderComposite( display(), PictOpSrc, picture, alpha, buffer, 0, 0, 0, 0,
|
||||||
|
c->x(), c->y(), c->width(), c->height());
|
||||||
|
// setPictureMatrix( picture, Matrix());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// cleanup
|
||||||
|
for( int i = 0;
|
||||||
|
i < windows.count();
|
||||||
|
++i )
|
||||||
|
{
|
||||||
|
Toplevel* c = windows[ i ];
|
||||||
|
cleanup( c );
|
||||||
}
|
}
|
||||||
// copy composed buffer to the root window
|
// copy composed buffer to the root window
|
||||||
XFixesSetPictureClipRegion( display(), buffer, 0, 0, None );
|
XFixesSetPictureClipRegion( display(), buffer, 0, 0, None );
|
||||||
|
@ -127,24 +148,33 @@ void SceneXrender::transformWindowDamage( Toplevel* c, XserverRegion r ) const
|
||||||
{
|
{
|
||||||
if( !window_data.contains( c ))
|
if( !window_data.contains( c ))
|
||||||
return;
|
return;
|
||||||
const Matrix& matrix = window_data[ c ].effect.matrix;
|
const Matrix& matrix = window_data[ c ].matrix;
|
||||||
if( matrix.isIdentity())
|
if( matrix.isIdentity())
|
||||||
return;
|
return;
|
||||||
assert( matrix.isOnlyTranslate());
|
if( matrix.isOnlyTranslate())
|
||||||
// TODO the matrix here is not valid after it changes but before it's first painted
|
XFixesTranslateRegion( display(), r, int( matrix.xTranslate()), int( matrix.yTranslate()));
|
||||||
// (i.e. a changes to state where it should be translated but the matrix is not yet updated)
|
else
|
||||||
XFixesTranslateRegion( display(), r, int( matrix.xTranslate()), int( matrix.yTranslate()));
|
{
|
||||||
|
// The region here should be translated using the matrix, but that's not possible
|
||||||
|
// (well, maybe fetch the region and transform manually - TODO check). So simply
|
||||||
|
// mark whole screen as damaged.
|
||||||
|
XRectangle s;
|
||||||
|
s.x = s.y = 0;
|
||||||
|
s.width = displayWidth();
|
||||||
|
s.height = displayHeight();
|
||||||
|
XFixesSetRegion( display(), r, &s, 1 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneXrender::updateTransformation( Toplevel* c )
|
void SceneXrender::updateTransformation( Toplevel* c )
|
||||||
{
|
{
|
||||||
// TODO maybe only mark as invalid and update on-demand
|
// TODO maybe only mark as invalid and update on-demand
|
||||||
checkWindowData( c );
|
resetWindowData( c );
|
||||||
WindowData& data = window_data[ c ];
|
WindowData& data = window_data[ c ];
|
||||||
effects->transformWindow( c, data.effect );
|
effects->transformWindow( c, data.matrix, data.effect );
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneXrender::checkWindowData( Toplevel* c )
|
void SceneXrender::resetWindowData( Toplevel* c )
|
||||||
{
|
{
|
||||||
if( !window_data.contains( c ))
|
if( !window_data.contains( c ))
|
||||||
{
|
{
|
||||||
|
@ -152,7 +182,7 @@ void SceneXrender::checkWindowData( Toplevel* c )
|
||||||
window_data[ c ].format = XRenderFindVisualFormat( display(), c->visual());
|
window_data[ c ].format = XRenderFindVisualFormat( display(), c->visual());
|
||||||
}
|
}
|
||||||
WindowData& data = window_data[ c ];
|
WindowData& data = window_data[ c ];
|
||||||
data.effect.matrix = Matrix();
|
data.matrix = Matrix();
|
||||||
data.effect.opacity = c->opacity();
|
data.effect.opacity = c->opacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,11 +236,15 @@ void SceneXrender::saveWindowClipRegion( Toplevel* c, XserverRegion r )
|
||||||
}
|
}
|
||||||
|
|
||||||
XserverRegion SceneXrender::savedWindowClipRegion( Toplevel* c )
|
XserverRegion SceneXrender::savedWindowClipRegion( Toplevel* c )
|
||||||
{ // always called after saveWindowClipRegion(), also resets
|
{
|
||||||
|
return window_data[ c ].saved_clip_region;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneXrender::cleanup( Toplevel* c )
|
||||||
|
{
|
||||||
WindowData& data = window_data[ c ];
|
WindowData& data = window_data[ c ];
|
||||||
XserverRegion r = data.saved_clip_region;
|
XFixesDestroyRegion( display(), data.saved_clip_region );
|
||||||
data.saved_clip_region = None;
|
data.saved_clip_region = None;
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SceneXrender::isOpaque( Toplevel* c ) const
|
bool SceneXrender::isOpaque( Toplevel* c ) const
|
||||||
|
@ -249,10 +283,11 @@ Picture SceneXrender::windowAlphaMask( Toplevel* c )
|
||||||
return data.alpha;
|
return data.alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
XserverRegion SceneXrender::windowShape( Toplevel* c )
|
XserverRegion SceneXrender::windowShape( Toplevel* c )
|
||||||
{
|
{
|
||||||
#if 0 // it probably doesn't make sense to cache this, and perhaps some others - they aren't roundtrips
|
|
||||||
WindowData& data = window_data[ c ];
|
WindowData& data = window_data[ c ];
|
||||||
|
#if 0 // it probably doesn't make sense to cache this, and perhaps some others - they aren't roundtrips
|
||||||
if( data.shape == None )
|
if( data.shape == None )
|
||||||
{
|
{
|
||||||
data.shape = XFixesCreateRegionFromWindow( display(), c->handle(), WindowRegionBounding );
|
data.shape = XFixesCreateRegionFromWindow( display(), c->handle(), WindowRegionBounding );
|
||||||
|
@ -260,8 +295,15 @@ XserverRegion SceneXrender::windowShape( Toplevel* c )
|
||||||
}
|
}
|
||||||
return data.shape;
|
return data.shape;
|
||||||
#else
|
#else
|
||||||
|
if( !data.simpleTransformation())
|
||||||
|
{
|
||||||
|
// The region here should be translated using the matrix, but that's not possible
|
||||||
|
// (well, maybe fetch the region and transform manually - TODO check).
|
||||||
|
return None;
|
||||||
|
}
|
||||||
XserverRegion shape = XFixesCreateRegionFromWindow( display(), c->handle(), WindowRegionBounding );
|
XserverRegion shape = XFixesCreateRegionFromWindow( display(), c->handle(), WindowRegionBounding );
|
||||||
XFixesTranslateRegion( display(), shape, c->x(), c->y());
|
XFixesTranslateRegion( display(), shape,
|
||||||
|
c->x() + int( data.matrix.xTranslate()), c->y() + int( data.matrix.yTranslate()));
|
||||||
return shape;
|
return shape;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -281,19 +323,28 @@ void SceneXrender::setPictureMatrix( Picture pic, const Matrix& m )
|
||||||
{
|
{
|
||||||
if( pic == None )
|
if( pic == None )
|
||||||
return;
|
return;
|
||||||
|
#if 0
|
||||||
XTransform t;
|
XTransform t;
|
||||||
// ignore z axis
|
// ignore z axis
|
||||||
t.matrix[ 0 ][ 0 ] = XDoubleToFixed( m.m[ 0 ][ 0 ] );
|
t.matrix[ 0 ][ 0 ] = XDoubleToFixed( 1 / m.m[ 0 ][ 0 ] );
|
||||||
t.matrix[ 0 ][ 1 ] = XDoubleToFixed( m.m[ 0 ][ 1 ] );
|
t.matrix[ 0 ][ 1 ] = XDoubleToFixed( m.m[ 0 ][ 1 ] );
|
||||||
t.matrix[ 0 ][ 2 ] = -XDoubleToFixed( m.m[ 0 ][ 3 ] ); // translation seems to be inverted
|
t.matrix[ 0 ][ 2 ] = -XDoubleToFixed( m.m[ 0 ][ 3 ] ); // translation seems to be inverted
|
||||||
t.matrix[ 1 ][ 0 ] = XDoubleToFixed( m.m[ 1 ][ 0 ] );
|
t.matrix[ 1 ][ 0 ] = XDoubleToFixed( m.m[ 1 ][ 0 ] );
|
||||||
t.matrix[ 1 ][ 1 ] = XDoubleToFixed( m.m[ 1 ][ 1 ] );
|
t.matrix[ 1 ][ 1 ] = XDoubleToFixed( 1 / m.m[ 1 ][ 1 ] );
|
||||||
t.matrix[ 1 ][ 2 ] = -XDoubleToFixed( m.m[ 1 ][ 3 ] );
|
t.matrix[ 1 ][ 2 ] = -XDoubleToFixed( m.m[ 1 ][ 3 ] );
|
||||||
t.matrix[ 2 ][ 0 ] = XDoubleToFixed( m.m[ 3 ][ 0 ] );
|
t.matrix[ 2 ][ 0 ] = XDoubleToFixed( m.m[ 3 ][ 0 ] );
|
||||||
t.matrix[ 2 ][ 1 ] = XDoubleToFixed( m.m[ 3 ][ 1 ] );
|
t.matrix[ 2 ][ 1 ] = XDoubleToFixed( m.m[ 3 ][ 1 ] );
|
||||||
t.matrix[ 2 ][ 2 ] = XDoubleToFixed( m.m[ 3 ][ 3 ] );
|
t.matrix[ 2 ][ 2 ] = XDoubleToFixed( m.m[ 3 ][ 3 ] );
|
||||||
|
// and scaling seems to be wrong too
|
||||||
|
// or maybe I just don't get it, but anyway, for now
|
||||||
|
if( m.m[ 3 ][ 3 ] != 1 )
|
||||||
|
{
|
||||||
|
t.matrix[ 0 ][ 0 ] = XDoubleToFixed( 1 / m.m[ 0 ][ 0 ] * m.m[ 3 ][ 3 ] );
|
||||||
|
t.matrix[ 1 ][ 1 ] = XDoubleToFixed( 1 / m.m[ 1 ][ 1 ] * m.m[ 3 ][ 3 ] );
|
||||||
|
t.matrix[ 2 ][ 2 ] = XDoubleToFixed( 1 );
|
||||||
|
}
|
||||||
XRenderSetPictureTransform( display(), pic, &t );
|
XRenderSetPictureTransform( display(), pic, &t );
|
||||||
if( t.matrix[ 0 ][ 0 ] != XDoubleToFixed( 1 ) // fast filter for identity or translation
|
if( t.matrix[ 0 ][ 0 ] != XDoubleToFixed( 1 )
|
||||||
|| t.matrix[ 1 ][ 1 ] != XDoubleToFixed( 1 )
|
|| t.matrix[ 1 ][ 1 ] != XDoubleToFixed( 1 )
|
||||||
|| t.matrix[ 2 ][ 2 ] != XDoubleToFixed( 1 )
|
|| t.matrix[ 2 ][ 2 ] != XDoubleToFixed( 1 )
|
||||||
|| t.matrix[ 0 ][ 1 ] != XDoubleToFixed( 0 )
|
|| t.matrix[ 0 ][ 1 ] != XDoubleToFixed( 0 )
|
||||||
|
@ -301,10 +352,11 @@ void SceneXrender::setPictureMatrix( Picture pic, const Matrix& m )
|
||||||
{
|
{
|
||||||
XRenderSetPictureFilter( display(), pic, const_cast< char* >( FilterGood ), 0, 0 );
|
XRenderSetPictureFilter( display(), pic, const_cast< char* >( FilterGood ), 0, 0 );
|
||||||
}
|
}
|
||||||
else
|
else // fast filter for identity or translation
|
||||||
{
|
{
|
||||||
XRenderSetPictureFilter( display(), pic, const_cast< char* >( FilterFast ), 0, 0 );
|
XRenderSetPictureFilter( display(), pic, const_cast< char* >( FilterFast ), 0, 0 );
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SceneXrender::WindowData::WindowData()
|
SceneXrender::WindowData::WindowData()
|
||||||
|
@ -326,5 +378,10 @@ void SceneXrender::WindowData::free()
|
||||||
XRenderFreePicture( display(), shape );
|
XRenderFreePicture( display(), shape );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SceneXrender::WindowData::simpleTransformation() const
|
||||||
|
{
|
||||||
|
return ( matrix.isIdentity() || matrix.isOnlyTranslate());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -30,7 +30,7 @@ class SceneXrender
|
||||||
public:
|
public:
|
||||||
SceneXrender( Workspace* ws );
|
SceneXrender( Workspace* ws );
|
||||||
virtual ~SceneXrender();
|
virtual ~SceneXrender();
|
||||||
virtual void paint( XserverRegion damage );
|
virtual void paint( XserverRegion damage, ToplevelList windows );
|
||||||
virtual void windowGeometryShapeChanged( Toplevel* );
|
virtual void windowGeometryShapeChanged( Toplevel* );
|
||||||
virtual void windowOpacityChanged( Toplevel* );
|
virtual void windowOpacityChanged( Toplevel* );
|
||||||
virtual void windowDeleted( Toplevel* );
|
virtual void windowDeleted( Toplevel* );
|
||||||
|
@ -38,7 +38,7 @@ class SceneXrender
|
||||||
virtual void updateTransformation( Toplevel* );
|
virtual void updateTransformation( Toplevel* );
|
||||||
private:
|
private:
|
||||||
void createBuffer();
|
void createBuffer();
|
||||||
void checkWindowData( Toplevel* c );
|
void resetWindowData( Toplevel* c );
|
||||||
Picture windowPicture( Toplevel* c );
|
Picture windowPicture( Toplevel* c );
|
||||||
void saveWindowClipRegion( Toplevel* c, XserverRegion r );
|
void saveWindowClipRegion( Toplevel* c, XserverRegion r );
|
||||||
XserverRegion savedWindowClipRegion( Toplevel* c );
|
XserverRegion savedWindowClipRegion( Toplevel* c );
|
||||||
|
@ -46,6 +46,7 @@ class SceneXrender
|
||||||
Picture windowAlphaMask( Toplevel* c );
|
Picture windowAlphaMask( Toplevel* c );
|
||||||
XserverRegion windowShape( Toplevel* c );
|
XserverRegion windowShape( Toplevel* c );
|
||||||
static void setPictureMatrix( Picture pic, const Matrix& m );
|
static void setPictureMatrix( Picture pic, const Matrix& m );
|
||||||
|
void cleanup( Toplevel* c );
|
||||||
XRenderPictFormat* format;
|
XRenderPictFormat* format;
|
||||||
Picture front;
|
Picture front;
|
||||||
Picture buffer;
|
Picture buffer;
|
||||||
|
@ -53,13 +54,16 @@ class SceneXrender
|
||||||
{
|
{
|
||||||
WindowData();
|
WindowData();
|
||||||
void free();
|
void free();
|
||||||
|
bool simpleTransformation() const;
|
||||||
Picture picture;
|
Picture picture;
|
||||||
XRenderPictFormat* format;
|
XRenderPictFormat* format;
|
||||||
XserverRegion saved_clip_region;
|
XserverRegion saved_clip_region;
|
||||||
Picture alpha;
|
Picture alpha;
|
||||||
double alpha_cached_opacity;
|
double alpha_cached_opacity;
|
||||||
XserverRegion shape;
|
XserverRegion shape;
|
||||||
|
Matrix matrix;
|
||||||
EffectData effect;
|
EffectData effect;
|
||||||
|
int phase;
|
||||||
};
|
};
|
||||||
QMap< Toplevel*, WindowData > window_data;
|
QMap< Toplevel*, WindowData > window_data;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue