Add support for translation and add two "plugins" that
make windows transparent or shake them while moving. svn path=/branches/work/kwin_composite/; revision=559013
This commit is contained in:
parent
391bb6b28d
commit
0516e1e73b
18 changed files with 498 additions and 136 deletions
58
client.cpp
58
client.cpp
|
@ -1600,58 +1600,6 @@ bool Client::wantsInput() const
|
|||
return rules()->checkAcceptFocus( input || Ptakefocus );
|
||||
}
|
||||
|
||||
bool Client::isDesktop() const
|
||||
{
|
||||
return windowType() == NET::Desktop;
|
||||
}
|
||||
|
||||
bool Client::isDock() const
|
||||
{
|
||||
return windowType() == NET::Dock;
|
||||
}
|
||||
|
||||
bool Client::isTopMenu() const
|
||||
{
|
||||
return windowType() == NET::TopMenu;
|
||||
}
|
||||
|
||||
|
||||
bool Client::isMenu() const
|
||||
{
|
||||
return windowType() == NET::Menu && !isTopMenu(); // because of backwards comp.
|
||||
}
|
||||
|
||||
bool Client::isToolbar() const
|
||||
{
|
||||
return windowType() == NET::Toolbar;
|
||||
}
|
||||
|
||||
bool Client::isSplash() const
|
||||
{
|
||||
return windowType() == NET::Splash;
|
||||
}
|
||||
|
||||
bool Client::isUtility() const
|
||||
{
|
||||
return windowType() == NET::Utility;
|
||||
}
|
||||
|
||||
bool Client::isDialog() const
|
||||
{
|
||||
return windowType() == NET::Dialog;
|
||||
}
|
||||
|
||||
bool Client::isNormalWindow() const
|
||||
{
|
||||
return windowType() == NET::Normal;
|
||||
}
|
||||
|
||||
bool Client::isSpecialWindow() const
|
||||
{
|
||||
return isDesktop() || isDock() || isSplash() || isTopMenu()
|
||||
|| isToolbar(); // TODO
|
||||
}
|
||||
|
||||
NET::WindowType Client::windowType( bool direct, int supported_types ) const
|
||||
{
|
||||
NET::WindowType wt = info->windowType( supported_types );
|
||||
|
@ -1683,6 +1631,12 @@ NET::WindowType Client::windowType( bool direct, int supported_types ) const
|
|||
return wt;
|
||||
}
|
||||
|
||||
bool Client::isSpecialWindow() const
|
||||
{
|
||||
return isDesktop() || isDock() || isSplash() || isTopMenu()
|
||||
|| isToolbar(); // TODO
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets an appropriate cursor shape for the logical mouse position \a m
|
||||
|
||||
|
|
43
client.h
43
client.h
|
@ -67,12 +67,17 @@ class Client
|
|||
const Group* group() const;
|
||||
Group* group();
|
||||
void checkGroup( Group* gr = NULL, bool force = false );
|
||||
// prefer isXXX() instead
|
||||
NET::WindowType windowType( bool direct = false, int supported_types = SUPPORTED_WINDOW_TYPES_MASK ) const;
|
||||
const WindowRules* rules() const;
|
||||
void removeRule( Rules* r );
|
||||
void setupWindowRules( bool ignore_temporary );
|
||||
void applyWindowRules();
|
||||
virtual NET::WindowType windowType( bool direct = false, int supported_types = SUPPORTED_WINDOW_TYPES_MASK ) const;
|
||||
// returns true for "special" windows and false for windows which are "normal"
|
||||
// (normal=window which has a border, can be moved by the user, can be closed, etc.)
|
||||
// true for Desktop, Dock, Splash, Override and TopMenu (and Toolbar??? - for now)
|
||||
// false for Normal, Dialog, Utility and Menu (and Toolbar??? - not yet) TODO
|
||||
bool isSpecialWindow() const;
|
||||
bool hasNETSupport() const;
|
||||
|
||||
QSize minSize() const;
|
||||
QSize maxSize() const;
|
||||
|
@ -158,24 +163,9 @@ class Client
|
|||
// auxiliary functions, depend on the windowType
|
||||
bool wantsTabFocus() const;
|
||||
bool wantsInput() const;
|
||||
bool hasNETSupport() const;
|
||||
bool isMovable() const;
|
||||
bool isDesktop() const;
|
||||
bool isDock() const;
|
||||
bool isToolbar() const;
|
||||
bool isTopMenu() const;
|
||||
bool isMenu() const;
|
||||
bool isNormalWindow() const; // normal as in 'NET::Normal or NET::Unknown non-transient'
|
||||
bool isDialog() const;
|
||||
bool isSplash() const;
|
||||
bool isUtility() const;
|
||||
// returns true for "special" windows and false for windows which are "normal"
|
||||
// (normal=window which has a border, can be moved by the user, can be closed, etc.)
|
||||
// true for Desktop, Dock, Splash, Override and TopMenu (and Toolbar??? - for now)
|
||||
// false for Normal, Dialog, Utility and Menu (and Toolbar??? - not yet) TODO
|
||||
bool isSpecialWindow() const;
|
||||
|
||||
bool isResizable() const;
|
||||
bool isMovable() const;
|
||||
bool isCloseable() const; // may be closed by the user (may have a close button)
|
||||
|
||||
void takeActivity( int flags, bool handled, allowed_t ); // takes ActivityFlags as arg (in utils.h)
|
||||
|
@ -283,6 +273,15 @@ class Client
|
|||
void checkActiveModal();
|
||||
bool hasStrut() const;
|
||||
|
||||
bool isMove() const
|
||||
{
|
||||
return moveResizeMode && mode == PositionCenter;
|
||||
}
|
||||
bool isResize() const
|
||||
{
|
||||
return moveResizeMode && mode != PositionCenter;
|
||||
}
|
||||
|
||||
private slots:
|
||||
void autoRaise();
|
||||
void shadeHover();
|
||||
|
@ -411,14 +410,6 @@ class Client
|
|||
bool move_faked_activity;
|
||||
Window move_resize_grab_window;
|
||||
bool unrestrictedMoveResize;
|
||||
bool isMove() const
|
||||
{
|
||||
return moveResizeMode && mode == PositionCenter;
|
||||
}
|
||||
bool isResize() const
|
||||
{
|
||||
return moveResizeMode && mode != PositionCenter;
|
||||
}
|
||||
|
||||
Position mode;
|
||||
QPoint moveOffset;
|
||||
|
|
|
@ -74,6 +74,8 @@ void Workspace::addDamage( const QRect& r )
|
|||
|
||||
void Workspace::addDamage( int x, int y, int w, int h )
|
||||
{
|
||||
if( !compositing())
|
||||
return;
|
||||
XRectangle r;
|
||||
r.x = x;
|
||||
r.y = y;
|
||||
|
@ -104,6 +106,44 @@ void Workspace::addDamage( XserverRegion r, bool destroy )
|
|||
}
|
||||
}
|
||||
|
||||
void Workspace::addDamage( Toplevel* c, const QRect& r )
|
||||
{
|
||||
addDamage( c, r.x(), r.y(), r.width(), r.height());
|
||||
}
|
||||
|
||||
void Workspace::addDamage( Toplevel* c, int x, int y, int w, int h )
|
||||
{
|
||||
if( !compositing())
|
||||
return;
|
||||
XRectangle r;
|
||||
r.x = x;
|
||||
r.y = y;
|
||||
r.width = w;
|
||||
r.height = h;
|
||||
addDamage( c, XFixesCreateRegion( display(), &r, 1 ), true );
|
||||
}
|
||||
|
||||
void Workspace::addDamage( Toplevel* c, XserverRegion r, bool destroy )
|
||||
{
|
||||
if( !compositing())
|
||||
return;
|
||||
if( !destroy )
|
||||
{
|
||||
XserverRegion r2 = XFixesCreateRegion( display(), NULL, 0 );
|
||||
XFixesCopyRegion( display(), r2, r );
|
||||
r = r2;
|
||||
destroy = true;
|
||||
}
|
||||
scene->transformWindowDamage( c, r );
|
||||
if( damage != None )
|
||||
{
|
||||
XFixesUnionRegion( display(), damage, damage, r );
|
||||
XFixesDestroyRegion( display(), r );
|
||||
}
|
||||
else
|
||||
damage = r;
|
||||
}
|
||||
|
||||
void Workspace::compositeTimeout()
|
||||
{
|
||||
if( damage == None )
|
||||
|
@ -177,7 +217,7 @@ void Toplevel::damageNotifyEvent( XDamageNotifyEvent* e )
|
|||
{
|
||||
XserverRegion r = XFixesCreateRegion( display(), &e->area, 1 );
|
||||
XFixesTranslateRegion( display(), r, x(), y());
|
||||
workspace()->addDamage( r, true );
|
||||
workspace()->addDamage( this, r, true );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
190
effects.cpp
190
effects.cpp
|
@ -10,6 +10,10 @@ License. See the file "COPYING" for the exact licensing terms.
|
|||
|
||||
#include "effects.h"
|
||||
|
||||
#include "toplevel.h"
|
||||
#include "client.h"
|
||||
#include "scene.h"
|
||||
|
||||
namespace KWinInternal
|
||||
{
|
||||
|
||||
|
@ -37,6 +41,67 @@ Matrix::Matrix()
|
|||
m[ 3 ][ 3 ] = 1;
|
||||
}
|
||||
|
||||
Matrix operator*( const Matrix& m1, const Matrix& m2 )
|
||||
{
|
||||
Matrix r;
|
||||
for( int i = 0;
|
||||
i < 4;
|
||||
++i )
|
||||
for( int j = 0;
|
||||
j < 4;
|
||||
++j )
|
||||
{
|
||||
double s = 0;
|
||||
for( int k = 0;
|
||||
k < 4;
|
||||
++k )
|
||||
s += m1.m[ i ][ k ] * m2.m[ k ][ j ];
|
||||
r.m[ i ][ j ] = s;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
bool Matrix::isIdentity() const
|
||||
{
|
||||
return m[ 0 ][ 0 ] == 1
|
||||
&& m[ 0 ][ 1 ] == 0
|
||||
&& m[ 0 ][ 2 ] == 0
|
||||
&& m[ 0 ][ 3 ] == 0
|
||||
&& m[ 1 ][ 0 ] == 0
|
||||
&& m[ 1 ][ 1 ] == 1
|
||||
&& m[ 1 ][ 2 ] == 0
|
||||
&& m[ 1 ][ 3 ] == 0
|
||||
&& m[ 2 ][ 0 ] == 0
|
||||
&& m[ 2 ][ 1 ] == 0
|
||||
&& m[ 2 ][ 2 ] == 1
|
||||
&& m[ 2 ][ 3 ] == 0
|
||||
&& m[ 3 ][ 0 ] == 0
|
||||
&& m[ 3 ][ 1 ] == 0
|
||||
&& m[ 3 ][ 2 ] == 0
|
||||
&& m[ 3 ][ 3 ] == 1;
|
||||
}
|
||||
|
||||
|
||||
bool Matrix::isOnlyTranslate() const
|
||||
{
|
||||
return m[ 0 ][ 0 ] == 1
|
||||
&& m[ 0 ][ 1 ] == 0
|
||||
&& m[ 0 ][ 2 ] == 0
|
||||
// && m[ 0 ][ 3 ] ==
|
||||
&& m[ 1 ][ 0 ] == 0
|
||||
&& m[ 1 ][ 1 ] == 1
|
||||
&& m[ 1 ][ 2 ] == 0
|
||||
// && m[ 1 ][ 3 ] ==
|
||||
&& m[ 2 ][ 0 ] == 0
|
||||
&& m[ 2 ][ 1 ] == 0
|
||||
&& m[ 2 ][ 2 ] == 1
|
||||
// && m[ 2 ][ 3 ] ==
|
||||
&& m[ 3 ][ 0 ] == 0
|
||||
&& m[ 3 ][ 1 ] == 0
|
||||
&& m[ 3 ][ 2 ] == 0
|
||||
&& m[ 3 ][ 3 ] == 1;
|
||||
}
|
||||
|
||||
//****************************************
|
||||
// Effect
|
||||
//****************************************
|
||||
|
@ -45,61 +110,142 @@ Effect::~Effect()
|
|||
{
|
||||
}
|
||||
|
||||
void Effect::windowUserMoved( Toplevel* )
|
||||
void Effect::windowUserMovedResized( Toplevel* , bool, bool )
|
||||
{
|
||||
}
|
||||
|
||||
void Effect::windowUserResized( Toplevel* )
|
||||
void Effect::transformWindow( Toplevel*, EffectData& )
|
||||
{
|
||||
}
|
||||
|
||||
void Effect::paintWindow( Toplevel*, EffectData& )
|
||||
void Effect::transformWorkspace( Workspace*, EffectData& )
|
||||
{
|
||||
}
|
||||
|
||||
void Effect::paintWorkspace( Workspace*, EffectData& )
|
||||
void Effect::windowDeleted( Toplevel* )
|
||||
{
|
||||
}
|
||||
|
||||
void MakeHalfTransparent::transformWindow( Toplevel* c, EffectData& data )
|
||||
{
|
||||
if( c->isDialog())
|
||||
data.opacity *= 0.8;
|
||||
if( Client* c2 = dynamic_cast< Client* >( c ))
|
||||
if( c2->isMove() || c2->isResize())
|
||||
data.opacity *= 0.5;
|
||||
}
|
||||
|
||||
void MakeHalfTransparent::windowUserMovedResized( Toplevel* c, bool first, bool last )
|
||||
{
|
||||
if( first || last )
|
||||
c->workspace()->addDamage( c, c->geometry());
|
||||
}
|
||||
|
||||
ShakyMove::ShakyMove()
|
||||
{
|
||||
connect( &timer, SIGNAL( timeout()), SLOT( tick()));
|
||||
}
|
||||
|
||||
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 ] );
|
||||
|
||||
void ShakyMove::transformWindow( Toplevel* c, EffectData& data )
|
||||
{
|
||||
if( windows.contains( c ))
|
||||
{
|
||||
Matrix m;
|
||||
m.m[ 0 ][ 3 ] = shaky_diff[ windows[ c ]];
|
||||
data.matrix *= m;
|
||||
}
|
||||
}
|
||||
|
||||
void ShakyMove::windowUserMovedResized( Toplevel* c, bool first, bool last )
|
||||
{
|
||||
if( first )
|
||||
{
|
||||
if( windows.isEmpty())
|
||||
timer.start( 50 );
|
||||
windows[ c ] = 0;
|
||||
}
|
||||
else if( last )
|
||||
{
|
||||
windows.remove( c );
|
||||
scene->updateTransformation( c );
|
||||
c->workspace()->addDamage( c, c->geometry().adjusted( -3, 7, 0, 0 ));
|
||||
if( windows.isEmpty())
|
||||
timer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
void ShakyMove::windowDeleted( Toplevel* c )
|
||||
{
|
||||
windows.remove( c );
|
||||
if( windows.isEmpty())
|
||||
timer.stop();
|
||||
}
|
||||
|
||||
void ShakyMove::tick()
|
||||
{
|
||||
for( QMap< Toplevel*, int >::Iterator it = windows.begin();
|
||||
it != windows.end();
|
||||
++it )
|
||||
{
|
||||
if( *it == SHAKY_MAX - 1 )
|
||||
*it = 0;
|
||||
else
|
||||
++(*it);
|
||||
scene->updateTransformation( it.key());
|
||||
it.key()->workspace()->addDamage( it.key(), it.key()->geometry().adjusted( -1, 2, 0, 0 ));
|
||||
}
|
||||
}
|
||||
|
||||
static MakeHalfTransparent* mht;
|
||||
static ShakyMove* sm;
|
||||
|
||||
//****************************************
|
||||
// EffectsHandler
|
||||
//****************************************
|
||||
|
||||
class MakeHalfTransparent
|
||||
: public Effect
|
||||
{
|
||||
public:
|
||||
virtual void paintWindow( Toplevel* c, EffectData& data );
|
||||
};
|
||||
|
||||
void MakeHalfTransparent::paintWindow( Toplevel*, EffectData& data )
|
||||
{
|
||||
data.opacity *= 0.8;
|
||||
}
|
||||
|
||||
static MakeHalfTransparent* mht;
|
||||
EffectsHandler::EffectsHandler()
|
||||
{
|
||||
mht = new MakeHalfTransparent;
|
||||
sm = new ShakyMove;
|
||||
}
|
||||
|
||||
void EffectsHandler::windowUserMoved( Toplevel* )
|
||||
void EffectsHandler::windowUserMovedResized( Toplevel* c, bool first, bool last )
|
||||
{
|
||||
if( mht )
|
||||
mht->windowUserMovedResized( c, first, last );
|
||||
if( sm )
|
||||
sm->windowUserMovedResized( c, first, last );
|
||||
}
|
||||
|
||||
void EffectsHandler::windowUserResized( Toplevel* )
|
||||
void EffectsHandler::transformWindow( Toplevel* c, EffectData& data )
|
||||
{
|
||||
if( mht )
|
||||
mht->transformWindow( c, data );
|
||||
if( sm )
|
||||
sm->transformWindow( c, data );
|
||||
}
|
||||
|
||||
void EffectsHandler::paintWindow( Toplevel* c, EffectData& data )
|
||||
void EffectsHandler::transformWorkspace( Workspace* w, EffectData& data )
|
||||
{
|
||||
mht->paintWindow( c, data );
|
||||
if( mht )
|
||||
mht->transformWorkspace( w, data );
|
||||
if( sm )
|
||||
sm->transformWorkspace( w, data );
|
||||
}
|
||||
|
||||
void EffectsHandler::paintWorkspace( Workspace*, EffectData& )
|
||||
void EffectsHandler::windowDeleted( Toplevel* c )
|
||||
{
|
||||
if( mht )
|
||||
mht->windowDeleted( c );
|
||||
if( sm )
|
||||
sm->windowDeleted( c );
|
||||
}
|
||||
|
||||
EffectsHandler* effects;
|
||||
|
||||
} // namespace
|
||||
|
||||
#include "effects.moc"
|
||||
|
|
73
effects.h
73
effects.h
|
@ -13,6 +13,9 @@ License. See the file "COPYING" for the exact licensing terms.
|
|||
#ifndef KWIN_EFFECTS_H
|
||||
#define KWIN_EFFECTS_H
|
||||
|
||||
#include <QMap>
|
||||
#include <QTimer>
|
||||
|
||||
namespace KWinInternal
|
||||
{
|
||||
|
||||
|
@ -23,9 +26,37 @@ class Matrix
|
|||
{
|
||||
public:
|
||||
Matrix();
|
||||
Matrix& operator*=( const Matrix& m );
|
||||
bool isOnlyTranslate() const;
|
||||
bool isIdentity() const;
|
||||
double xTranslate() const;
|
||||
double yTranslate() const;
|
||||
double zTranslate() const;
|
||||
double m[ 4 ][ 4 ];
|
||||
};
|
||||
|
||||
Matrix operator*( const Matrix& m1, const Matrix& m2 );
|
||||
|
||||
inline Matrix& Matrix::operator*=( const Matrix& m )
|
||||
{
|
||||
return *this = *this * m;
|
||||
}
|
||||
|
||||
inline double Matrix::xTranslate() const
|
||||
{
|
||||
return m[ 0 ][ 3 ];
|
||||
}
|
||||
|
||||
inline double Matrix::yTranslate() const
|
||||
{
|
||||
return m[ 1 ][ 3 ];
|
||||
}
|
||||
|
||||
inline double Matrix::zTranslate() const
|
||||
{
|
||||
return m[ 2 ][ 3 ];
|
||||
}
|
||||
|
||||
class EffectData
|
||||
{
|
||||
public:
|
||||
|
@ -37,24 +68,50 @@ class Effect
|
|||
{
|
||||
public:
|
||||
virtual ~Effect();
|
||||
virtual void windowUserMoved( Toplevel* c );
|
||||
virtual void windowUserResized( Toplevel* c );
|
||||
virtual void paintWindow( Toplevel* c, EffectData& data );
|
||||
virtual void paintWorkspace( Workspace*, EffectData& data );
|
||||
// called when moved/resized or once after it's finished
|
||||
virtual void windowUserMovedResized( Toplevel* c, bool first, bool last );
|
||||
virtual void windowDeleted( Toplevel* c );
|
||||
virtual void transformWindow( Toplevel* c, EffectData& data );
|
||||
virtual void transformWorkspace( Workspace*, EffectData& data );
|
||||
};
|
||||
|
||||
class EffectsHandler
|
||||
{
|
||||
public:
|
||||
EffectsHandler();
|
||||
void windowUserMoved( Toplevel* c );
|
||||
void windowUserResized( Toplevel* c );
|
||||
void paintWindow( Toplevel* c, EffectData& data );
|
||||
void paintWorkspace( Workspace*, EffectData& data );
|
||||
void windowUserMovedResized( Toplevel* c, bool first, bool last );
|
||||
void windowDeleted( Toplevel* c );
|
||||
void transformWindow( Toplevel* c, EffectData& data );
|
||||
void transformWorkspace( Workspace*, EffectData& data );
|
||||
};
|
||||
|
||||
extern EffectsHandler* effects;
|
||||
|
||||
class MakeHalfTransparent
|
||||
: public Effect
|
||||
{
|
||||
public:
|
||||
virtual void windowUserMovedResized( Toplevel* c, bool first, bool last );
|
||||
virtual void transformWindow( Toplevel* c, EffectData& data );
|
||||
};
|
||||
|
||||
class ShakyMove
|
||||
: public QObject, public Effect
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ShakyMove();
|
||||
virtual void windowUserMovedResized( Toplevel* c, bool first, bool last );
|
||||
virtual void transformWindow( Toplevel* c, EffectData& data );
|
||||
virtual void windowDeleted( Toplevel* c );
|
||||
private slots:
|
||||
void tick();
|
||||
private:
|
||||
QMap< Toplevel*, int > windows;
|
||||
QTimer timer;
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
|
|
@ -577,7 +577,7 @@ bool Client::windowEvent( XEvent* e )
|
|||
{
|
||||
if( compositing())
|
||||
{
|
||||
workspace()->addDamage( geometry());
|
||||
workspace()->addDamage( this, geometry());
|
||||
scene->windowOpacityChanged( this );
|
||||
}
|
||||
else
|
||||
|
@ -1613,7 +1613,7 @@ bool Unmanaged::windowEvent( XEvent* e )
|
|||
if( dirty[ NETWinInfo::PROTOCOLS2 ] & NET::WM2Opacity )
|
||||
{
|
||||
scene->windowOpacityChanged( this );
|
||||
workspace()->addDamage( geometry());
|
||||
workspace()->addDamage( this, geometry());
|
||||
}
|
||||
switch (e->type)
|
||||
{
|
||||
|
@ -1647,9 +1647,9 @@ void Unmanaged::configureNotifyEvent( XConfigureEvent* e )
|
|||
{
|
||||
resetWindowPixmap();
|
||||
// add old and new geometry to damage
|
||||
workspace()->addDamage( geometry());
|
||||
workspace()->addDamage( this, geometry());
|
||||
geom = QRect( e->x, e->y, e->width, e->height );
|
||||
workspace()->addDamage( geometry());
|
||||
workspace()->addDamage( this, geometry());
|
||||
}
|
||||
|
||||
// ****************************************
|
||||
|
|
22
geometry.cpp
22
geometry.cpp
|
@ -1660,7 +1660,7 @@ void Client::setGeometry( int x, int y, int w, int h, ForceGeometry_t force )
|
|||
}
|
||||
if( force == NormalGeometrySet && geom == QRect( x, y, w, h ))
|
||||
return;
|
||||
workspace()->addDamage( geometry()); // TODO cache the previous real geometry
|
||||
workspace()->addDamage( this, geometry()); // TODO cache the previous real geometry
|
||||
geom = QRect( x, y, w, h );
|
||||
updateWorkareaDiffs();
|
||||
if( postpone_geometry_updates != 0 )
|
||||
|
@ -1686,7 +1686,7 @@ void Client::setGeometry( int x, int y, int w, int h, ForceGeometry_t force )
|
|||
updateWindowRules();
|
||||
checkMaximizeGeometry();
|
||||
resetWindowPixmap();
|
||||
workspace()->addDamage( geometry());
|
||||
workspace()->addDamage( this, geometry());
|
||||
}
|
||||
|
||||
void Client::plainResize( int w, int h, ForceGeometry_t force )
|
||||
|
@ -1718,7 +1718,7 @@ void Client::plainResize( int w, int h, ForceGeometry_t force )
|
|||
}
|
||||
if( force == NormalGeometrySet && geom.size() == QSize( w, h ))
|
||||
return;
|
||||
workspace()->addDamage( geometry()); // TODO cache the previous real geometry
|
||||
workspace()->addDamage( this, geometry()); // TODO cache the previous real geometry
|
||||
geom.setSize( QSize( w, h ));
|
||||
updateWorkareaDiffs();
|
||||
if( postpone_geometry_updates != 0 )
|
||||
|
@ -1743,7 +1743,7 @@ void Client::plainResize( int w, int h, ForceGeometry_t force )
|
|||
updateWindowRules();
|
||||
checkMaximizeGeometry();
|
||||
resetWindowPixmap();
|
||||
workspace()->addDamage( geometry());
|
||||
workspace()->addDamage( this, geometry());
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -1753,7 +1753,7 @@ void Client::move( int x, int y, ForceGeometry_t force )
|
|||
{
|
||||
if( force == NormalGeometrySet && geom.topLeft() == QPoint( x, y ))
|
||||
return;
|
||||
workspace()->addDamage( geometry()); // TODO cache the previous real geometry
|
||||
workspace()->addDamage( this, geometry()); // TODO cache the previous real geometry
|
||||
geom.moveTopLeft( QPoint( x, y ));
|
||||
updateWorkareaDiffs();
|
||||
if( postpone_geometry_updates != 0 )
|
||||
|
@ -1765,7 +1765,7 @@ void Client::move( int x, int y, ForceGeometry_t force )
|
|||
sendSyntheticConfigureNotify();
|
||||
updateWindowRules();
|
||||
checkMaximizeGeometry();
|
||||
workspace()->addDamage( geometry());
|
||||
workspace()->addDamage( this, geometry());
|
||||
}
|
||||
|
||||
void Client::postponeGeometryUpdates( bool postpone )
|
||||
|
@ -2265,6 +2265,8 @@ bool Client::startMoveResize()
|
|||
// not needed anymore? kapp->installEventFilter( eater );
|
||||
}
|
||||
Notify::raise( isResize() ? Notify::ResizeStart : Notify::MoveStart );
|
||||
if( effects )
|
||||
effects->windowUserMovedResized( this, true, false );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2278,6 +2280,8 @@ void Client::finishMoveResize( bool cancel )
|
|||
checkMaximizeGeometry();
|
||||
// FRAME update();
|
||||
Notify::raise( isResize() ? Notify::ResizeEnd : Notify::MoveEnd );
|
||||
if( effects )
|
||||
effects->windowUserMovedResized( this, false, true );
|
||||
}
|
||||
|
||||
void Client::leaveMoveResize()
|
||||
|
@ -2541,10 +2545,8 @@ void Client::handleMoveResize( int x, int y, int x_root, int y_root )
|
|||
}
|
||||
if ( isMove() )
|
||||
workspace()->clientMoved(globalPos, xTime());
|
||||
if( isMove())
|
||||
effects->windowUserMoved( this );
|
||||
else
|
||||
effects->windowUserResized( this );
|
||||
if( effects )
|
||||
effects->windowUserMovedResized( this, false, false );
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -523,7 +523,7 @@ bool Client::manage( Window w, bool isMapped )
|
|||
delete session;
|
||||
|
||||
if( isMapped ) // otherwise damage will come when the client paints it
|
||||
workspace()->addDamage( geometry());
|
||||
workspace()->addDamage( this, geometry());
|
||||
|
||||
ungrabXServer();
|
||||
|
||||
|
|
|
@ -43,6 +43,14 @@ void Scene::windowDeleted( Toplevel* )
|
|||
{
|
||||
}
|
||||
|
||||
void Scene::transformWindowDamage( Toplevel*, XserverRegion ) const
|
||||
{
|
||||
}
|
||||
|
||||
void Scene::updateTransformation( Toplevel* )
|
||||
{
|
||||
}
|
||||
|
||||
Scene* scene;
|
||||
|
||||
} // namespace
|
||||
|
|
2
scene.h
2
scene.h
|
@ -28,6 +28,8 @@ class Scene
|
|||
virtual void windowGeometryShapeChanged( Toplevel* );
|
||||
virtual void windowOpacityChanged( Toplevel* );
|
||||
virtual void windowDeleted( Toplevel* );
|
||||
virtual void transformWindowDamage( Toplevel*, XserverRegion ) const;
|
||||
virtual void updateTransformation( Toplevel* );
|
||||
protected:
|
||||
Workspace* wspace;
|
||||
ToplevelList windows;
|
||||
|
|
|
@ -64,19 +64,26 @@ void SceneXrender::paint( XserverRegion damage )
|
|||
{
|
||||
Toplevel* c = windows[ i ];
|
||||
checkWindowData( c );
|
||||
effects->paintWindow( c, window_data[ c ].effect );
|
||||
WindowData& data = window_data[ c ];
|
||||
effects->transformWindow( c, data.effect ); // TODO remove, instead add initWindow() to effects
|
||||
if( isOpaque( c ))
|
||||
{
|
||||
Picture picture = windowPicture( c );
|
||||
Picture shape = windowShape( c );
|
||||
XserverRegion shape = windowShape( c );
|
||||
if( picture != None && shape != None )
|
||||
{
|
||||
// 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(), c->y(), c->width(), c->height());
|
||||
c->x() + int( matrix.xTranslate()), c->y() + int( matrix.yTranslate()), c->width(), c->height());
|
||||
}
|
||||
}
|
||||
saveWindowClipRegion( c, damage );
|
||||
|
@ -102,9 +109,10 @@ void SceneXrender::paint( XserverRegion damage )
|
|||
Picture alpha = windowAlphaMask( c );
|
||||
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(), c->y(), c->width(), c->height());
|
||||
c->x() + int( matrix.xTranslate()), c->y() + int( matrix.yTranslate()), c->width(), c->height());
|
||||
}
|
||||
}
|
||||
XFixesDestroyRegion( display(), r );
|
||||
|
@ -115,6 +123,27 @@ void SceneXrender::paint( XserverRegion damage )
|
|||
XFlush( display());
|
||||
}
|
||||
|
||||
void SceneXrender::transformWindowDamage( Toplevel* c, XserverRegion r ) const
|
||||
{
|
||||
if( !window_data.contains( c ))
|
||||
return;
|
||||
const Matrix& matrix = window_data[ c ].effect.matrix;
|
||||
if( matrix.isIdentity())
|
||||
return;
|
||||
assert( matrix.isOnlyTranslate());
|
||||
// TODO the matrix here is not valid after it changes but before it's first painted
|
||||
// (i.e. a changes to state where it should be translated but the matrix is not yet updated)
|
||||
XFixesTranslateRegion( display(), r, int( matrix.xTranslate()), int( matrix.yTranslate()));
|
||||
}
|
||||
|
||||
void SceneXrender::updateTransformation( Toplevel* c )
|
||||
{
|
||||
// TODO maybe only mark as invalid and update on-demand
|
||||
checkWindowData( c );
|
||||
WindowData& data = window_data[ c ];
|
||||
effects->transformWindow( c, data.effect );
|
||||
}
|
||||
|
||||
void SceneXrender::checkWindowData( Toplevel* c )
|
||||
{
|
||||
if( !window_data.contains( c ))
|
||||
|
@ -139,7 +168,7 @@ void SceneXrender::windowGeometryShapeChanged( Toplevel* c )
|
|||
XRenderFreePicture( display(), data.alpha );
|
||||
data.alpha = None;
|
||||
if( data.shape != None )
|
||||
XRenderFreePicture( display(), data.shape );
|
||||
XFixesDestroyRegion( display(), data.shape );
|
||||
data.shape = None;
|
||||
}
|
||||
|
||||
|
@ -220,8 +249,9 @@ Picture SceneXrender::windowAlphaMask( Toplevel* c )
|
|||
return data.alpha;
|
||||
}
|
||||
|
||||
Picture 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 ];
|
||||
if( data.shape == None )
|
||||
{
|
||||
|
@ -229,6 +259,11 @@ Picture SceneXrender::windowShape( Toplevel* c )
|
|||
XFixesTranslateRegion( display(), data.shape, c->x(), c->y());
|
||||
}
|
||||
return data.shape;
|
||||
#else
|
||||
XserverRegion shape = XFixesCreateRegionFromWindow( display(), c->handle(), WindowRegionBounding );
|
||||
XFixesTranslateRegion( display(), shape, c->x(), c->y());
|
||||
return shape;
|
||||
#endif
|
||||
}
|
||||
|
||||
// TODO handle xrandr changes
|
||||
|
@ -242,6 +277,36 @@ void SceneXrender::createBuffer()
|
|||
XFreePixmap( display(), pixmap ); // The picture owns the pixmap now
|
||||
}
|
||||
|
||||
void SceneXrender::setPictureMatrix( Picture pic, const Matrix& m )
|
||||
{
|
||||
if( pic == None )
|
||||
return;
|
||||
XTransform t;
|
||||
// ignore z axis
|
||||
t.matrix[ 0 ][ 0 ] = XDoubleToFixed( m.m[ 0 ][ 0 ] );
|
||||
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[ 1 ][ 0 ] = XDoubleToFixed( m.m[ 1 ][ 0 ] );
|
||||
t.matrix[ 1 ][ 1 ] = XDoubleToFixed( m.m[ 1 ][ 1 ] );
|
||||
t.matrix[ 1 ][ 2 ] = -XDoubleToFixed( m.m[ 1 ][ 3 ] );
|
||||
t.matrix[ 2 ][ 0 ] = XDoubleToFixed( m.m[ 3 ][ 0 ] );
|
||||
t.matrix[ 2 ][ 1 ] = XDoubleToFixed( m.m[ 3 ][ 1 ] );
|
||||
t.matrix[ 2 ][ 2 ] = XDoubleToFixed( m.m[ 3 ][ 3 ] );
|
||||
XRenderSetPictureTransform( display(), pic, &t );
|
||||
if( t.matrix[ 0 ][ 0 ] != XDoubleToFixed( 1 ) // fast filter for identity or translation
|
||||
|| t.matrix[ 1 ][ 1 ] != XDoubleToFixed( 1 )
|
||||
|| t.matrix[ 2 ][ 2 ] != XDoubleToFixed( 1 )
|
||||
|| t.matrix[ 0 ][ 1 ] != XDoubleToFixed( 0 )
|
||||
|| t.matrix[ 1 ][ 0 ] != XDoubleToFixed( 0 ))
|
||||
{
|
||||
XRenderSetPictureFilter( display(), pic, const_cast< char* >( FilterGood ), 0, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
XRenderSetPictureFilter( display(), pic, const_cast< char* >( FilterFast ), 0, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
SceneXrender::WindowData::WindowData()
|
||||
: picture( None )
|
||||
, format( NULL )
|
||||
|
|
|
@ -34,6 +34,8 @@ class SceneXrender
|
|||
virtual void windowGeometryShapeChanged( Toplevel* );
|
||||
virtual void windowOpacityChanged( Toplevel* );
|
||||
virtual void windowDeleted( Toplevel* );
|
||||
virtual void transformWindowDamage( Toplevel*, XserverRegion ) const;
|
||||
virtual void updateTransformation( Toplevel* );
|
||||
private:
|
||||
void createBuffer();
|
||||
void checkWindowData( Toplevel* c );
|
||||
|
@ -42,7 +44,8 @@ class SceneXrender
|
|||
XserverRegion savedWindowClipRegion( Toplevel* c );
|
||||
bool isOpaque( Toplevel* c ) const;
|
||||
Picture windowAlphaMask( Toplevel* c );
|
||||
Picture windowShape( Toplevel* c );
|
||||
XserverRegion windowShape( Toplevel* c );
|
||||
static void setPictureMatrix( Picture pic, const Matrix& m );
|
||||
XRenderPictFormat* format;
|
||||
Picture front;
|
||||
Picture buffer;
|
||||
|
|
59
toplevel.h
59
toplevel.h
|
@ -39,6 +39,20 @@ class Toplevel
|
|||
int y() const;
|
||||
int width() const;
|
||||
int height() const;
|
||||
|
||||
// prefer isXXX() instead
|
||||
virtual NET::WindowType windowType( bool direct = false, int supported_types = SUPPORTED_WINDOW_TYPES_MASK ) const = 0;
|
||||
bool hasNETSupport() const;
|
||||
bool isDesktop() const;
|
||||
bool isDock() const;
|
||||
bool isToolbar() const;
|
||||
bool isTopMenu() const;
|
||||
bool isMenu() const;
|
||||
bool isNormalWindow() const; // normal as in 'NET::Normal or NET::Unknown non-transient'
|
||||
bool isDialog() const;
|
||||
bool isSplash() const;
|
||||
bool isUtility() const;
|
||||
|
||||
Pixmap windowPixmap() const;
|
||||
Visual* visual() const;
|
||||
virtual double opacity() const = 0;
|
||||
|
@ -120,6 +134,51 @@ inline Visual* Toplevel::visual() const
|
|||
return vis;
|
||||
}
|
||||
|
||||
inline bool Toplevel::isDesktop() const
|
||||
{
|
||||
return windowType() == NET::Desktop;
|
||||
}
|
||||
|
||||
inline bool Toplevel::isDock() const
|
||||
{
|
||||
return windowType() == NET::Dock;
|
||||
}
|
||||
|
||||
inline bool Toplevel::isTopMenu() const
|
||||
{
|
||||
return windowType() == NET::TopMenu;
|
||||
}
|
||||
|
||||
inline bool Toplevel::isMenu() const
|
||||
{
|
||||
return windowType() == NET::Menu && !isTopMenu(); // because of backwards comp.
|
||||
}
|
||||
|
||||
inline bool Toplevel::isToolbar() const
|
||||
{
|
||||
return windowType() == NET::Toolbar;
|
||||
}
|
||||
|
||||
inline bool Toplevel::isSplash() const
|
||||
{
|
||||
return windowType() == NET::Splash;
|
||||
}
|
||||
|
||||
inline bool Toplevel::isUtility() const
|
||||
{
|
||||
return windowType() == NET::Utility;
|
||||
}
|
||||
|
||||
inline bool Toplevel::isDialog() const
|
||||
{
|
||||
return windowType() == NET::Dialog;
|
||||
}
|
||||
|
||||
inline bool Toplevel::isNormalWindow() const
|
||||
{
|
||||
return windowType() == NET::Normal;
|
||||
}
|
||||
|
||||
#ifdef NDEBUG
|
||||
inline
|
||||
kndbgstream& operator<<( kndbgstream& stream, const Toplevel* ) { return stream; }
|
||||
|
|
|
@ -47,7 +47,7 @@ bool Unmanaged::track( Window w )
|
|||
|
||||
setupCompositing();
|
||||
resetWindowPixmap();
|
||||
workspace()->addDamage( geometry());
|
||||
workspace()->addDamage( this, geometry());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -63,6 +63,11 @@ void Unmanaged::deleteUnmanaged( Unmanaged* c, allowed_t )
|
|||
delete c;
|
||||
}
|
||||
|
||||
NET::WindowType Unmanaged::windowType( bool, int supported_types ) const
|
||||
{
|
||||
return info->windowType( supported_types );
|
||||
}
|
||||
|
||||
double Unmanaged::opacity() const
|
||||
{
|
||||
if( info->opacity() == 0xffffffff )
|
||||
|
|
|
@ -28,6 +28,7 @@ class Unmanaged
|
|||
bool windowEvent( XEvent* e );
|
||||
void release();
|
||||
bool track( Window w );
|
||||
virtual NET::WindowType windowType( bool direct = false, int supported_types = SUPPORTED_WINDOW_TYPES_MASK ) const;
|
||||
static void deleteUnmanaged( Unmanaged* c, allowed_t );
|
||||
virtual double opacity() const;
|
||||
protected:
|
||||
|
|
16
utils.cpp
16
utils.cpp
|
@ -315,6 +315,20 @@ bool grabbedXServer()
|
|||
return server_grab_count > 0;
|
||||
}
|
||||
|
||||
kdbgstream& operator<<( kdbgstream& stream, RegionDebug r )
|
||||
{
|
||||
if( r.rr == None )
|
||||
return stream << "EMPTY";
|
||||
int num;
|
||||
XRectangle* rects = XFixesFetchRegion( display(), r.rr, &num );
|
||||
if( rects == NULL || num == 0 )
|
||||
return stream << "EMPTY";
|
||||
for( int i = 0;
|
||||
i < num;
|
||||
++i )
|
||||
stream << "[" << rects[ i ].x << "+" << rects[ i ].y << " " << rects[ i ].width << "x" << rects[ i ].height << "]";
|
||||
return stream;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool isLocalMachine( const QByteArray& host )
|
||||
|
@ -381,8 +395,6 @@ void ShortcutDialog::accept()
|
|||
KShortcutDialog::accept();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#ifndef KCMRULES
|
||||
|
|
14
utils.h
14
utils.h
|
@ -120,6 +120,20 @@ enum allowed_t { Allowed };
|
|||
// some enums to have more readable code, instead of using bools
|
||||
enum ForceGeometry_t { NormalGeometrySet, ForceGeometrySet };
|
||||
|
||||
|
||||
struct RegionDebug
|
||||
{
|
||||
RegionDebug( XserverRegion r ) : rr( r ) {}
|
||||
XserverRegion rr;
|
||||
};
|
||||
|
||||
#ifdef NDEBUG
|
||||
inline
|
||||
kndbgstream& operator<<( kndbgstream& stream, RegionDebug ) { return stream; }
|
||||
#else
|
||||
kdbgstream& operator<<( kdbgstream& stream, RegionDebug r );
|
||||
#endif
|
||||
|
||||
// Areas, mostly related to Xinerama
|
||||
enum clientAreaOption
|
||||
{
|
||||
|
|
|
@ -286,6 +286,9 @@ class Workspace : public QObject, public KDecorationDefines
|
|||
void addDamage( const QRect& r );
|
||||
void addDamage( int x, int y, int w, int h );
|
||||
void addDamage( XserverRegion r, bool destroy );
|
||||
void addDamage( Toplevel* c, const QRect& r );
|
||||
void addDamage( Toplevel* c, int x, int y, int w, int h );
|
||||
void addDamage( Toplevel* c, XserverRegion r, bool destroy );
|
||||
|
||||
public slots:
|
||||
void refresh();
|
||||
|
|
Loading…
Reference in a new issue