Add support for showing effects for windows which have already been deleted.

Add a fade-out effect.


svn path=/branches/work/kwin_composite/; revision=623872
This commit is contained in:
Luboš Luňák 2007-01-15 18:03:04 +00:00
parent 921d8d4f22
commit ff6f889ffc
16 changed files with 374 additions and 182 deletions

View file

@ -52,6 +52,7 @@ set(kwin_KDEINIT_SRCS
glutils.cpp glutils.cpp
effects.cpp effects.cpp
effects/fadein.cpp effects/fadein.cpp
effects/fadeout.cpp
effects/maketransparent.cpp effects/maketransparent.cpp
effects/scalein.cpp effects/scalein.cpp
effects/shakymove.cpp effects/shakymove.cpp

View file

@ -45,9 +45,6 @@ General TODO
- maybe posted paint events need to be processed immediatelly, or maybe the compositing - maybe posted paint events need to be processed immediatelly, or maybe the compositing
code should not update the window until the decoration is finished painting code should not update the window until the decoration is finished painting
/ handle XRandr changes
- output buffers and similar probably need recreating when the screen size changes
! compile even without OpenGL or XRender ! compile even without OpenGL or XRender
- kwin_composite currently requires both OpenGL and XRender to build - kwin_composite currently requires both OpenGL and XRender to build
- compiling without either results in compile errors, needs to be fixed - compiling without either results in compile errors, needs to be fixed
@ -66,6 +63,10 @@ General TODO
+ make effects configurable without having to recompile + make effects configurable without having to recompile
- possibly also add something like KWIN_COMPOSE for debugging purposes - possibly also add something like KWIN_COMPOSE for debugging purposes
* handle properly stacking order of deleted windows for showing in effects
* handle properly deleted windows that reappear (windowReadded() function?)
OpenGL TODO OpenGL TODO
================================= =================================
@ -147,10 +148,7 @@ XRender TODO
Effects framework TODO Effects framework TODO
============================== ==============================
/ design framework for graphical effects / solve somehow disappearing windows
- modelling it after compiz seems to make a lot of sense
* solve somehow disappearing windows
- i.e. when a window is e.g. closed, the Client/Unmanaged object is destroyed, but animations - i.e. when a window is e.g. closed, the Client/Unmanaged object is destroyed, but animations
should be going on should be going on
? - maybe animations could be done actually before the state change, it makes sense to destroy ? - maybe animations could be done actually before the state change, it makes sense to destroy
@ -185,6 +183,14 @@ Effects framework TODO
which means that if an effect sets PAINT_WINDOW_TRANSFORMED it needs to set it which means that if an effect sets PAINT_WINDOW_TRANSFORMED it needs to set it
also in prePaintScreen() also in prePaintScreen()
* PAINT_WINDOW_DISABLED turning off from effects needs some utility functions
- 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
for minimized windows, because it may be disabled also for other reasons
- there should be some utility function that will be called by the effect
with arguments saying which disabled windows it wants enabled
Effects TODO Effects TODO
=============================== ===============================
@ -219,10 +225,8 @@ Effects TODO
- Client::animateMinimizeOrUnminimize() - Client::animateMinimizeOrUnminimize()
- Client::setShade() - Client::setShade()
+ zoom effect / zoom effect
- enlarge a portion of the screen - enlarge a portion of the screen
! - would require adding xScale/yScale to ScreenPaintData
- should be doable even for XRender
+ logout effect + logout effect
* - should be triggered by ksmserver somehow * - should be triggered by ksmserver somehow

View file

@ -108,7 +108,6 @@ Client::Client( Workspace *ws )
shade_mode = ShadeNone; shade_mode = ShadeNone;
active = false; active = false;
deleting = false;
keep_above = false; keep_above = false;
keep_below = false; keep_below = false;
motif_noborder = false; motif_noborder = false;
@ -175,9 +174,11 @@ void Client::deleteClient( Client* c, allowed_t )
*/ */
void Client::releaseWindow( bool on_shutdown ) void Client::releaseWindow( bool on_shutdown )
{ {
assert( !deleting ); assert( !deleting());
deleting = true; delete_refcount = 1;
finishCompositing(); if( effects )
effects->windowClosed( this );
finishCompositing( false ); // don't discard pixmap
workspace()->discardUsedWindowRules( this, true ); // remove ForceTemporarily rules workspace()->discardUsedWindowRules( this, true ); // remove ForceTemporarily rules
StackingUpdatesBlocker blocker( workspace()); StackingUpdatesBlocker blocker( workspace());
if (moveResizeMode) if (moveResizeMode)
@ -192,7 +193,9 @@ void Client::releaseWindow( bool on_shutdown )
if( !on_shutdown ) if( !on_shutdown )
workspace()->clientHidden( this ); workspace()->clientHidden( this );
XUnmapWindow( display(), frameId()); // destroying decoration would cause ugly visual effect XUnmapWindow( display(), frameId()); // destroying decoration would cause ugly visual effect
destroyDecoration(); // destroyDecoration();
delete decoration;
decoration = NULL;
cleanGrouping(); cleanGrouping();
if( !on_shutdown ) if( !on_shutdown )
{ {
@ -200,9 +203,11 @@ void Client::releaseWindow( bool on_shutdown )
// only when the window is being unmapped, not when closing down KWin // only when the window is being unmapped, not when closing down KWin
// (NETWM sections 5.5,5.7) // (NETWM sections 5.5,5.7)
info->setDesktop( 0 ); info->setDesktop( 0 );
desk = 0; // desk = 0; - do not reset internal state, it may still be used by effects
info->setState( 0, info->state()); // reset all state flags info->setState( 0, info->state()); // reset all state flags
} }
else
workspace()->addDeleted( this, Allowed );
XDeleteProperty( display(), client, atoms->kde_net_wm_user_creation_time); XDeleteProperty( display(), client, atoms->kde_net_wm_user_creation_time);
XDeleteProperty( display(), client, atoms->net_frame_extents ); XDeleteProperty( display(), client, atoms->net_frame_extents );
XDeleteProperty( display(), client, atoms->kde_net_wm_frame_strut ); XDeleteProperty( display(), client, atoms->kde_net_wm_frame_strut );
@ -220,22 +225,25 @@ void Client::releaseWindow( bool on_shutdown )
// may do map+unmap before we initially map the window by calling rawShow() from manage(). // may do map+unmap before we initially map the window by calling rawShow() from manage().
XUnmapWindow( display(), client ); XUnmapWindow( display(), client );
} }
cleanUp();
client = None; client = None;
XDestroyWindow( display(), wrapper ); XDestroyWindow( display(), wrapper );
wrapper = None; wrapper = None;
XDestroyWindow( display(), frameId()); XDestroyWindow( display(), frameId());
// frame = None; // frame = None;
--block_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry --block_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry
deleteClient( this, Allowed ); unrefWindow(); // will delete if recount is == 0
} }
// like releaseWindow(), but this one is called when the window has been already destroyed // like releaseWindow(), but this one is called when the window has been already destroyed
// (e.g. the application closed it) // (e.g. the application closed it)
void Client::destroyClient() void Client::destroyClient()
{ {
assert( !deleting ); assert( !deleting());
deleting = true; delete_refcount = 1;
finishCompositing(); if( effects )
effects->windowClosed( this );
finishCompositing( false ); // don't discard pixmap
workspace()->discardUsedWindowRules( this, true ); // remove ForceTemporarily rules workspace()->discardUsedWindowRules( this, true ); // remove ForceTemporarily rules
StackingUpdatesBlocker blocker( workspace()); StackingUpdatesBlocker blocker( workspace());
if (moveResizeMode) if (moveResizeMode)
@ -247,15 +255,50 @@ void Client::destroyClient()
setModal( false ); setModal( false );
hidden = true; // so that it's not considered visible anymore hidden = true; // so that it's not considered visible anymore
workspace()->clientHidden( this ); workspace()->clientHidden( this );
destroyDecoration(); // destroyDecoration();
delete decoration;
decoration = NULL;
cleanGrouping(); cleanGrouping();
workspace()->removeClient( this, Allowed ); workspace()->removeClient( this, Allowed );
cleanUp();
client = None; // invalidate client = None; // invalidate
XDestroyWindow( display(), wrapper ); XDestroyWindow( display(), wrapper );
wrapper = None; wrapper = None;
XDestroyWindow( display(), frameId()); XDestroyWindow( display(), frameId());
// frame = None; // frame = None;
--block_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry --block_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry
unrefWindow(); // will delete if recount is == 0
}
// All clean-up code shared between releaseWindow() and destroyClient().
// Clean up everything that should not affect a deleted Client until it's
// really deleted by unrefWindow(). I.e. stop watching events, turn off timers
// and so on.
void Client::cleanUp()
{
if( Extensions::shapeAvailable())
XShapeSelectInput( display(), client, NoEventMask );
XSelectInput( display(), client, NoEventMask );
delete autoRaiseTimer;
autoRaiseTimer = NULL;
delete shadeHoverTimer;
shadeHoverTimer = NULL;
delete ping_timer;
ping_timer = NULL;
delete process_killer;
process_killer = NULL;
delete demandAttentionKNotifyTimer;
demandAttentionKNotifyTimer = NULL;
}
void Client::unrefWindow()
{
if( --delete_refcount > 0 )
return;
workspace()->removeDeleted( this );
workspace()->addDamage( geometry());
destroyDecoration( true ); // only now gravitate etc., otherwise window pixmap would be wrong
discardWindowPixmap();
deleteClient( this, Allowed ); deleteClient( this, Allowed );
} }
@ -300,9 +343,9 @@ void Client::updateDecoration( bool check_workspace_pos, bool force )
addDamageFull(); addDamageFull();
} }
void Client::destroyDecoration() void Client::destroyDecoration( bool force )
{ {
if( decoration != NULL ) if( decoration != NULL || force )
{ {
delete decoration; delete decoration;
decoration = NULL; decoration = NULL;
@ -317,7 +360,7 @@ void Client::destroyDecoration()
workarea_diff_y = save_workarea_diff_y; workarea_diff_y = save_workarea_diff_y;
if( compositing() ) if( compositing() )
discardWindowPixmap(); discardWindowPixmap();
if( scene != NULL ) if( scene != NULL && !deleting())
scene->windowGeometryShapeChanged( this ); scene->windowGeometryShapeChanged( this );
addDamageFull(); addDamageFull();
} }
@ -852,7 +895,7 @@ void Client::toggleShade()
void Client::updateVisibility() void Client::updateVisibility()
{ {
if( deleting ) if( deleting())
return; return;
bool show = true; bool show = true;
if( hidden ) if( hidden )
@ -910,7 +953,7 @@ void Client::updateVisibility()
void Client::setMappingState(int s) void Client::setMappingState(int s)
{ {
assert( client != None ); assert( client != None );
assert( !deleting || s == WithdrawnState ); assert( !deleting() || s == WithdrawnState );
if( mapping_state == s ) if( mapping_state == s )
return; return;
bool was_unmanaged = ( mapping_state == WithdrawnState ); bool was_unmanaged = ( mapping_state == WithdrawnState );

175
client.h
View file

@ -28,6 +28,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include "workspace.h" #include "workspace.h"
#include "kdecoration.h" #include "kdecoration.h"
#include "rules.h" #include "rules.h"
#include "toplevel.h"
class QTimer; class QTimer;
class KProcess; class KProcess;
@ -42,7 +43,8 @@ class WinInfo;
class SessionInfo; class SessionInfo;
class Bridge; class Bridge;
class Client : public QObject, public KDecorationDefines class Client
: public Toplevel
{ {
Q_OBJECT Q_OBJECT
public: public:
@ -52,7 +54,6 @@ class Client : public QObject, public KDecorationDefines
Window wrapperId() const; Window wrapperId() const;
Window decorationId() const; Window decorationId() const;
Workspace* workspace() const;
const Client* transientFor() const; const Client* transientFor() const;
Client* transientFor(); Client* transientFor();
bool isTransient() const; bool isTransient() const;
@ -66,24 +67,20 @@ class Client : public QObject, public KDecorationDefines
const Group* group() const; const Group* group() const;
Group* group(); Group* group();
void checkGroup( Group* gr = NULL, bool force = false ); void checkGroup( Group* gr = NULL, bool force = false );
void changeClientLeaderGroup( Group* gr );
// prefer isXXX() instead
NET::WindowType windowType( bool direct = false, int supported_types = SUPPORTED_WINDOW_TYPES_MASK ) const;
const WindowRules* rules() const; const WindowRules* rules() const;
void removeRule( Rules* r ); void removeRule( Rules* r );
void setupWindowRules( bool ignore_temporary ); void setupWindowRules( bool ignore_temporary );
void applyWindowRules(); 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;
QRect geometry() const;
QSize size() const;
QSize minSize() const; QSize minSize() const;
QSize maxSize() const; QSize maxSize() const;
QPoint pos() const;
QRect rect() const;
int x() const;
int y() const;
int width() const;
int height() const;
QPoint clientPos() const; // inside of geometry() QPoint clientPos() const; // inside of geometry()
QSize clientSize() const; QSize clientSize() const;
@ -93,6 +90,8 @@ class Client : public QObject, public KDecorationDefines
bool manage( Window w, bool isMapped ); bool manage( Window w, bool isMapped );
void releaseWindow( bool on_shutdown = false ); void releaseWindow( bool on_shutdown = false );
void destroyClient();
virtual void unrefWindow();
enum Sizemode // how to resize the window in order to obey constains (mainly aspect ratios) enum Sizemode // how to resize the window in order to obey constains (mainly aspect ratios)
{ {
@ -166,24 +165,9 @@ class Client : public QObject, public KDecorationDefines
// auxiliary functions, depend on the windowType // auxiliary functions, depend on the windowType
bool wantsTabFocus() const; bool wantsTabFocus() const;
bool wantsInput() 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 isResizable() const;
bool isMovable() const;
bool isCloseable() const; // may be closed by the user (may have a close button) 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) void takeActivity( int flags, bool handled, allowed_t ); // takes ActivityFlags as arg (in utils.h)
@ -196,9 +180,10 @@ class Client : public QObject, public KDecorationDefines
void updateDecoration( bool check_workspace_pos, bool force = false ); void updateDecoration( bool check_workspace_pos, bool force = false );
void checkBorderSizes(); void checkBorderSizes();
// shape extensions
bool shape() const;
void updateShape(); void updateShape();
virtual double opacity() const;
void setOpacity( double opacity );
void setGeometry( int x, int y, int w, int h, ForceGeometry_t force = NormalGeometrySet ); void setGeometry( int x, int y, int w, int h, ForceGeometry_t force = NormalGeometrySet );
void setGeometry( const QRect& r, ForceGeometry_t force = NormalGeometrySet ); void setGeometry( const QRect& r, ForceGeometry_t force = NormalGeometrySet );
@ -284,10 +269,18 @@ class Client : public QObject, public KDecorationDefines
void showContextHelp(); void showContextHelp();
void cancelShadeHover(); void cancelShadeHover();
void cancelAutoRaise(); void cancelAutoRaise();
void destroyClient();
void checkActiveModal(); void checkActiveModal();
bool hasStrut() const; bool hasStrut() const;
bool isMove() const
{
return moveResizeMode && mode == PositionCenter;
}
bool isResize() const
{
return moveResizeMode && mode != PositionCenter;
}
private slots: private slots:
void autoRaise(); void autoRaise();
void shadeHover(); void shadeHover();
@ -321,6 +314,7 @@ class Client : public QObject, public KDecorationDefines
void clientMessageEvent( XClientMessageEvent* e ); void clientMessageEvent( XClientMessageEvent* e );
void enterNotifyEvent( XCrossingEvent* e ); void enterNotifyEvent( XCrossingEvent* e );
void leaveNotifyEvent( XCrossingEvent* e ); void leaveNotifyEvent( XCrossingEvent* e );
void visibilityNotifyEvent( XVisibilityEvent* e );
void focusInEvent( XFocusInEvent* e ); void focusInEvent( XFocusInEvent* e );
void focusOutEvent( XFocusOutEvent* e ); void focusOutEvent( XFocusOutEvent* e );
@ -330,6 +324,9 @@ class Client : public QObject, public KDecorationDefines
void processDecorationButtonPress( int button, int state, int x, int y, int x_root, int y_root ); void processDecorationButtonPress( int button, int state, int x, int y, int x_root, int y_root );
protected:
virtual void debug( kdbgstream& stream ) const;
private slots: private slots:
void pingTimeout(); void pingTimeout();
void processKillerExited(); void processKillerExited();
@ -361,6 +358,7 @@ class Client : public QObject, public KDecorationDefines
void updateWindowRules(); void updateWindowRules();
void finishWindowRules(); void finishWindowRules();
void setShortcutInternal( const KShortcut& cut ); void setShortcutInternal( const KShortcut& cut );
void cleanUp();
void updateWorkareaDiffs(); void updateWorkareaDiffs();
void checkDirection( int new_diff, int old_diff, QRect& rect, const QRect& area ); void checkDirection( int new_diff, int old_diff, QRect& rect, const QRect& area );
@ -368,7 +366,7 @@ class Client : public QObject, public KDecorationDefines
void configureRequest( int value_mask, int rx, int ry, int rw, int rh, int gravity, bool from_tool ); void configureRequest( int value_mask, int rx, int ry, int rw, int rh, int gravity, bool from_tool );
NETExtendedStrut strut() const; NETExtendedStrut strut() const;
int checkShadeGeometry( int w, int h ); int checkShadeGeometry( int w, int h );
void postponeGeometryUpdates( bool postpone ); void blockGeometryUpdates( bool block );
bool startMoveResize(); bool startMoveResize();
void finishMoveResize( bool cancel ); void finishMoveResize( bool cancel );
@ -389,7 +387,7 @@ class Client : public QObject, public KDecorationDefines
void embedClient( Window w, const XWindowAttributes &attr ); void embedClient( Window w, const XWindowAttributes &attr );
void detectNoBorder(); void detectNoBorder();
void destroyDecoration(); void destroyDecoration( bool force = false );
void updateFrameExtents(); void updateFrameExtents();
void rawShow(); // just shows it void rawShow(); // just shows it
@ -400,12 +398,10 @@ class Client : public QObject, public KDecorationDefines
Time readUserCreationTime() const; Time readUserCreationTime() const;
static bool sameAppWindowRoleMatch( const Client* c1, const Client* c2, bool active_hack ); static bool sameAppWindowRoleMatch( const Client* c1, const Client* c2, bool active_hack );
void startupIdChanged(); void startupIdChanged();
Window client; Window client;
Window wrapper; Window wrapper;
Window frame;
KDecoration* decoration; KDecoration* decoration;
Workspace* wspace;
Bridge* bridge; Bridge* bridge;
int desk; int desk;
bool buttonDown; bool buttonDown;
@ -413,14 +409,6 @@ class Client : public QObject, public KDecorationDefines
bool move_faked_activity; bool move_faked_activity;
Window move_resize_grab_window; Window move_resize_grab_window;
bool unrestrictedMoveResize; bool unrestrictedMoveResize;
bool isMove() const
{
return moveResizeMode && mode == PositionCenter;
}
bool isResize() const
{
return moveResizeMode && mode != PositionCenter;
}
Position mode; Position mode;
QPoint moveOffset; QPoint moveOffset;
@ -444,9 +432,7 @@ class Client : public QObject, public KDecorationDefines
ClientList transients_list; // SELI make this ordered in stacking order? ClientList transients_list; // SELI make this ordered in stacking order?
ShadeMode shade_mode; ShadeMode shade_mode;
uint active :1; uint active :1;
uint deleting : 1; // true when doing cleanup and destroying the client
uint keep_above : 1; // NET::KeepAbove (was stays_on_top) uint keep_above : 1; // NET::KeepAbove (was stays_on_top)
uint is_shape :1;
uint skip_taskbar :1; uint skip_taskbar :1;
uint original_skip_taskbar :1; // unaffected by KWin uint original_skip_taskbar :1; // unaffected by KWin
uint Pdeletewindow :1; // does the window understand the DeleteWindow protocol? uint Pdeletewindow :1; // does the window understand the DeleteWindow protocol?
@ -466,6 +452,7 @@ class Client : public QObject, public KDecorationDefines
uint modal : 1; // NET::Modal uint modal : 1; // NET::Modal
uint noborder : 1; uint noborder : 1;
uint user_noborder : 1; uint user_noborder : 1;
uint not_obscured : 1;
uint urgency : 1; // XWMHints, UrgencyHint uint urgency : 1; // XWMHints, UrgencyHint
uint ignore_focus_stealing : 1; // don't apply focus stealing prevention to this client uint ignore_focus_stealing : 1; // don't apply focus stealing prevention to this client
uint demands_attention : 1; uint demands_attention : 1;
@ -503,10 +490,10 @@ class Client : public QObject, public KDecorationDefines
Time ping_timestamp; Time ping_timestamp;
Time user_time; Time user_time;
unsigned long allowed_actions; unsigned long allowed_actions;
QRect frame_geometry;
QSize client_size; QSize client_size;
int postpone_geometry_updates; // >0 - new geometry is remembered, but not actually set int block_geometry_updates; // >0 - new geometry is remembered, but not actually set
bool pending_geometry_update; bool pending_geometry_update;
QRect geom_before_block;
bool shade_geometry_change; bool shade_geometry_change;
int border_left, border_right, border_top, border_bottom; int border_left, border_right, border_top, border_bottom;
QRegion _mask; QRegion _mask;
@ -516,22 +503,20 @@ class Client : public QObject, public KDecorationDefines
friend struct FetchNameInternalPredicate; friend struct FetchNameInternalPredicate;
friend struct CheckIgnoreFocusStealingProcedure; friend struct CheckIgnoreFocusStealingProcedure;
friend struct ResetupRulesProcedure; friend struct ResetupRulesProcedure;
friend class GeometryUpdatesPostponer; friend class GeometryUpdatesBlocker;
void show() { assert( false ); } // SELI remove after Client is no longer QWidget void show() { assert( false ); } // SELI remove after Client is no longer QWidget
void hide() { assert( false ); } void hide() { assert( false ); }
QTimer* demandAttentionKNotifyTimer; QTimer* demandAttentionKNotifyTimer;
friend bool performTransiencyCheck();
}; };
// helper for Client::postponeGeometryUpdates() being called in pairs (true/false) // helper for Client::blockGeometryUpdates() being called in pairs (true/false)
class GeometryUpdatesPostponer class GeometryUpdatesBlocker
{ {
public: public:
GeometryUpdatesPostponer( Client* c ) GeometryUpdatesBlocker( Client* c )
: cl( c ) { cl->postponeGeometryUpdates( true ); } : cl( c ) { cl->blockGeometryUpdates( true ); }
~GeometryUpdatesPostponer() ~GeometryUpdatesBlocker()
{ cl->postponeGeometryUpdates( false ); } { cl->blockGeometryUpdates( false ); }
private: private:
Client* cl; Client* cl;
}; };
@ -558,7 +543,7 @@ inline Window Client::window() const
inline Window Client::frameId() const inline Window Client::frameId() const
{ {
return frame; return handle();
} }
inline Window Client::wrapperId() const inline Window Client::wrapperId() const
@ -571,11 +556,6 @@ inline Window Client::decorationId() const
return decoration != NULL ? decoration->widget()->winId() : None; return decoration != NULL ? decoration->widget()->winId() : None;
} }
inline Workspace* Client::workspace() const
{
return wspace;
}
inline const Client* Client::transientFor() const inline const Client* Client::transientFor() const
{ {
return transient_for; return transient_for;
@ -731,12 +711,6 @@ inline bool Client::keepBelow() const
return keep_below; return keep_below;
} }
inline bool Client::shape() const
{
return is_shape;
}
inline bool Client::isFullScreen() const inline bool Client::isFullScreen() const
{ {
return fullscreen_mode != FullScreenNone; return fullscreen_mode != FullScreenNone;
@ -792,46 +766,6 @@ inline QByteArray Client::windowRole() const
return window_role; return window_role;
} }
inline QRect Client::geometry() const
{
return frame_geometry;
}
inline QSize Client::size() const
{
return frame_geometry.size();
}
inline QPoint Client::pos() const
{
return frame_geometry.topLeft();
}
inline int Client::x() const
{
return frame_geometry.x();
}
inline int Client::y() const
{
return frame_geometry.y();
}
inline int Client::width() const
{
return frame_geometry.width();
}
inline int Client::height() const
{
return frame_geometry.height();
}
inline QRect Client::rect() const
{
return QRect( 0, 0, width(), height());
}
inline QPoint Client::clientPos() const inline QPoint Client::clientPos() const
{ {
return QPoint( border_left, border_top ); return QPoint( border_left, border_top );
@ -877,7 +811,7 @@ inline const WindowRules* Client::rules() const
return &client_rules; return &client_rules;
} }
KWIN_PROCEDURE( CheckIgnoreFocusStealingProcedure, cl->ignore_focus_stealing = options->checkIgnoreFocusStealing( cl )); KWIN_PROCEDURE( CheckIgnoreFocusStealingProcedure, Client, cl->ignore_focus_stealing = options->checkIgnoreFocusStealing( cl ));
inline Window Client::moveResizeGrabWindow() const inline Window Client::moveResizeGrabWindow() const
{ {
@ -894,22 +828,9 @@ inline void Client::removeRule( Rules* rule )
client_rules.remove( rule ); client_rules.remove( rule );
} }
#ifdef NDEBUG KWIN_COMPARE_PREDICATE( WindowMatchPredicate, Client, Window, cl->window() == value );
inline KWIN_COMPARE_PREDICATE( FrameIdMatchPredicate, Client, Window, cl->frameId() == value );
kndbgstream& operator<<( kndbgstream& stream, const Client* ) { return stream; } KWIN_COMPARE_PREDICATE( WrapperIdMatchPredicate, Client, Window, cl->wrapperId() == value );
inline
kndbgstream& operator<<( kndbgstream& stream, const ClientList& ) { return stream; }
inline
kndbgstream& operator<<( kndbgstream& stream, const ConstClientList& ) { return stream; }
#else
kdbgstream& operator<<( kdbgstream& stream, const Client* );
kdbgstream& operator<<( kdbgstream& stream, const ClientList& );
kdbgstream& operator<<( kdbgstream& stream, const ConstClientList& );
#endif
KWIN_COMPARE_PREDICATE( WindowMatchPredicate, Window, cl->window() == value );
KWIN_COMPARE_PREDICATE( FrameIdMatchPredicate, Window, cl->frameId() == value );
KWIN_COMPARE_PREDICATE( WrapperIdMatchPredicate, Window, cl->wrapperId() == value );
} // namespace } // namespace

View file

@ -222,6 +222,8 @@ void Workspace::performCompositing()
else if( Unmanaged* c = findUnmanaged( HandleMatchPredicate( children[ i ] ))) else if( Unmanaged* c = findUnmanaged( HandleMatchPredicate( children[ i ] )))
windows.append( c ); windows.append( c );
} }
foreach( Toplevel* c, pending_deleted ) // TODO remember stacking order somehow
windows.append( c );
QRegion damage = damage_region; QRegion damage = damage_region;
// clear all damage, so that post-pass can add damage for the next repaint // clear all damage, so that post-pass can add damage for the next repaint
damage_region = QRegion(); damage_region = QRegion();
@ -290,12 +292,13 @@ void Toplevel::setupCompositing()
damage_region = QRegion( 0, 0, width(), height()); damage_region = QRegion( 0, 0, width(), height());
} }
void Toplevel::finishCompositing() void Toplevel::finishCompositing( bool discard_pixmap )
{ {
if( damage_handle == None ) if( damage_handle == None )
return; return;
XDamageDestroy( display(), damage_handle ); XDamageDestroy( display(), damage_handle );
discardWindowPixmap(); if( discard_pixmap )
discardWindowPixmap();
damage_handle = None; damage_handle = None;
damage_region = QRegion(); damage_region = QRegion();
} }

View file

@ -16,6 +16,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include "effects/dialogparent.h" #include "effects/dialogparent.h"
#include "effects/fadein.h" #include "effects/fadein.h"
#include "effects/fadeout.h"
#include "effects/howto.h" #include "effects/howto.h"
#include "effects/maketransparent.h" #include "effects/maketransparent.h"
#include "effects/presentwindows.h" #include "effects/presentwindows.h"
@ -46,6 +47,10 @@ void Effect::windowAdded( Toplevel* )
{ {
} }
void Effect::windowClosed( Toplevel* )
{
}
void Effect::windowDeleted( Toplevel* ) void Effect::windowDeleted( Toplevel* )
{ {
} }
@ -115,6 +120,7 @@ EffectsHandler::EffectsHandler( Workspace* ws )
// effects.append( new ShakyMoveEffect ); // effects.append( new ShakyMoveEffect );
// effects.append( new ShiftWorkspaceUpEffect( ws )); // effects.append( new ShiftWorkspaceUpEffect( ws ));
// effects.append( new FadeInEffect ); // effects.append( new FadeInEffect );
effects.append( new FadeOutEffect );
// effects.append( new ScaleInEffect ); // effects.append( new ScaleInEffect );
// effects.append( new DialogParentEffect ); // effects.append( new DialogParentEffect );
@ -147,6 +153,12 @@ void EffectsHandler::windowDeleted( Toplevel* c )
e->windowDeleted( c ); e->windowDeleted( c );
} }
void EffectsHandler::windowClosed( Toplevel* c )
{
foreach( Effect* e, effects )
e->windowClosed( c );
}
void EffectsHandler::windowActivated( Toplevel* c ) void EffectsHandler::windowActivated( Toplevel* c )
{ {
foreach( Effect* e, effects ) foreach( Effect* e, effects )

View file

@ -74,6 +74,7 @@ class Effect
virtual void windowUserMovedResized( Toplevel* c, bool first, bool last ); virtual void windowUserMovedResized( Toplevel* c, bool first, bool last );
virtual void windowAdded( Toplevel* c ); virtual void windowAdded( Toplevel* c );
virtual void windowDeleted( Toplevel* c ); virtual void windowDeleted( Toplevel* c );
virtual void windowClosed( Toplevel* c );
virtual void windowActivated( Toplevel* c ); virtual void windowActivated( Toplevel* c );
virtual void windowMinimized( Toplevel* c ); virtual void windowMinimized( Toplevel* c );
virtual void windowUnminimized( Toplevel* c ); virtual void windowUnminimized( Toplevel* c );
@ -110,6 +111,7 @@ class EffectsHandler
void startPaint(); void startPaint();
void windowUserMovedResized( Toplevel* c, bool first, bool last ); void windowUserMovedResized( Toplevel* c, bool first, bool last );
void windowAdded( Toplevel* c ); void windowAdded( Toplevel* c );
void windowClosed( Toplevel* c );
void windowDeleted( Toplevel* c ); void windowDeleted( Toplevel* c );
void windowActivated( Toplevel* c ); void windowActivated( Toplevel* c );
void windowMinimized( Toplevel* c ); void windowMinimized( Toplevel* c );

69
effects/fadeout.cpp Normal file
View file

@ -0,0 +1,69 @@
/*****************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2006 Lubos Lunak <l.lunak@kde.org>
You can Freely distribute this program under the GNU General Public
License. See the file "COPYING" for the exact licensing terms.
******************************************************************/
#include "fadeout.h"
#include <client.h>
namespace KWinInternal
{
void FadeOutEffect::prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int time )
{
if( windows.contains( w->window()))
{
windows[ w->window() ] -= time / 1000.; // complete change in 1000ms
if( windows[ w->window() ] > 0 )
{
*mask |= Scene::PAINT_WINDOW_TRANSLUCENT;
*mask &= ~( Scene::PAINT_WINDOW_OPAQUE | Scene::PAINT_WINDOW_DISABLED );
}
else
{
windows.remove( w->window());
w->window()->unrefWindow();
}
}
effects->prePaintWindow( w, mask, region, time );
}
void FadeOutEffect::paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data )
{
if( windows.contains( w->window()))
{
data.opacity *= windows[ w->window()];
}
effects->paintWindow( w, mask, region, data );
}
void FadeOutEffect::postPaintWindow( Scene::Window* w )
{
if( windows.contains( w->window()))
w->window()->addDamageFull(); // trigger next animation repaint
effects->postPaintWindow( w );
}
void FadeOutEffect::windowClosed( Toplevel* c )
{
Client* cc = dynamic_cast< Client* >( c );
if( cc == NULL || cc->isOnCurrentDesktop())
{
windows[ c ] = 1; // count down to 0
c->addDamageFull();
c->refWindow();
}
}
void FadeOutEffect::windowDeleted( Toplevel* c )
{
windows.remove( c );
}
} // namespace

37
effects/fadeout.h Normal file
View file

@ -0,0 +1,37 @@
/*****************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2006 Lubos Lunak <l.lunak@kde.org>
You can Freely distribute this program under the GNU General Public
License. See the file "COPYING" for the exact licensing terms.
******************************************************************/
// TODO MIT or some other licence, perhaps move to some lib
#ifndef KWIN_FADEOUT_H
#define KWIN_FADEOUT_H
#include <effects.h>
namespace KWinInternal
{
class FadeOutEffect
: public Effect
{
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 windowClosed( Toplevel* c );
virtual void windowDeleted( Toplevel* c );
private:
QMap< const Toplevel*, double > windows;
};
} // namespace
#endif

View file

@ -290,6 +290,8 @@ QRegion Scene::Window::shape() const
bool Scene::Window::isVisible() const bool Scene::Window::isVisible() const
{ {
if( toplevel->deleting())
return false;
if( Client* c = dynamic_cast< Client* >( toplevel )) if( Client* c = dynamic_cast< Client* >( toplevel ))
return c->isShown( true ) && c->isOnCurrentDesktop(); return c->isShown( true ) && c->isOnCurrentDesktop();
return true; // Unmanaged is always visible return true; // Unmanaged is always visible

View file

@ -15,6 +15,7 @@ namespace KWinInternal
Toplevel::Toplevel( Workspace* ws ) Toplevel::Toplevel( Workspace* ws )
: vis( None ) : vis( None )
, delete_refcount( -1 )
, id( None ) , id( None )
, wspace( ws ) , wspace( ws )
, window_pix( None ) , window_pix( None )

View file

@ -59,12 +59,18 @@ class Toplevel
int depth() const; int depth() const;
bool hasAlpha() const; bool hasAlpha() const;
void setupCompositing(); void setupCompositing();
void finishCompositing(); void finishCompositing( bool discard_pixmap = true );
void addDamage( const QRect& r ); void addDamage( const QRect& r );
void addDamage( int x, int y, int w, int h ); void addDamage( int x, int y, int w, int h );
void addDamageFull(); void addDamageFull();
QRegion damage() const; QRegion damage() const;
void resetDamage( const QRect& r ); void resetDamage( const QRect& r );
// used by effects to keep the window around for e.g. fadeout effects when it's destroyed
void refWindow();
virtual void unrefWindow() = 0;
bool deleting() const;
protected: protected:
virtual ~Toplevel(); virtual ~Toplevel();
void setHandle( Window id ); void setHandle( Window id );
@ -75,6 +81,7 @@ class Toplevel
QRect geom; QRect geom;
Visual* vis; Visual* vis;
int bit_depth; int bit_depth;
int delete_refcount;
virtual void debug( kdbgstream& stream ) const = 0; virtual void debug( kdbgstream& stream ) const = 0;
friend kdbgstream& operator<<( kdbgstream& stream, const Toplevel* ); friend kdbgstream& operator<<( kdbgstream& stream, const Toplevel* );
private: private:
@ -219,6 +226,17 @@ inline bool Toplevel::hasAlpha() const
return depth() == 32; return depth() == 32;
} }
inline void Toplevel::refWindow()
{
assert( delete_refcount >= 0 );
++delete_refcount;
}
inline bool Toplevel::deleting() const
{
return delete_refcount >= 0;
}
#ifdef NDEBUG #ifdef NDEBUG
inline inline
kndbgstream& operator<<( kndbgstream& stream, const Toplevel* ) { return stream; } kndbgstream& operator<<( kndbgstream& stream, const Toplevel* ) { return stream; }

View file

@ -70,10 +70,26 @@ bool Unmanaged::track( Window w )
void Unmanaged::release() void Unmanaged::release()
{ {
workspace()->addDamage( geometry()); assert( !deleting());
finishCompositing(); delete_refcount = 1;
if( effects )
effects->windowClosed( this );
finishCompositing( false ); // don't discard pixmap
workspace()->removeUnmanaged( this, Allowed ); workspace()->removeUnmanaged( this, Allowed );
delete this; if( Extensions::shapeAvailable())
XShapeSelectInput( display(), handle(), NoEventMask );
XSelectInput( display(), handle(), NoEventMask );
unrefWindow(); // will delete if recount is == 0
}
void Unmanaged::unrefWindow()
{
if( --delete_refcount > 0 )
return;
discardWindowPixmap();
workspace()->removeDeleted( this );
workspace()->addDamage( geometry());
deleteUnmanaged( this, Allowed );
} }
void Unmanaged::deleteUnmanaged( Unmanaged* c, allowed_t ) void Unmanaged::deleteUnmanaged( Unmanaged* c, allowed_t )

View file

@ -30,6 +30,7 @@ class Unmanaged
virtual NET::WindowType windowType( bool direct = false, int supported_types = SUPPORTED_WINDOW_TYPES_MASK ) const; virtual NET::WindowType windowType( bool direct = false, int supported_types = SUPPORTED_WINDOW_TYPES_MASK ) const;
static void deleteUnmanaged( Unmanaged* c, allowed_t ); static void deleteUnmanaged( Unmanaged* c, allowed_t );
virtual double opacity() const; virtual double opacity() const;
virtual void unrefWindow();
protected: protected:
virtual void debug( kdbgstream& stream ) const; virtual void debug( kdbgstream& stream ) const;
private: private:

View file

@ -583,10 +583,6 @@ void Workspace::removeClient( Client* c, allowed_t )
Notify::raise( Notify::Delete ); Notify::raise( Notify::Delete );
Q_ASSERT( clients.contains( c ) || desktops.contains( c )); Q_ASSERT( clients.contains( c ) || desktops.contains( c ));
if( scene )
scene->windowDeleted( c );
if( effects )
effects->windowDeleted( c );
clients.removeAll( c ); clients.removeAll( c );
desktops.removeAll( c ); desktops.removeAll( c );
unconstrained_stacking_order.removeAll( c ); unconstrained_stacking_order.removeAll( c );
@ -620,16 +616,31 @@ void Workspace::removeClient( Client* c, allowed_t )
tab_box->repaint(); tab_box->repaint();
updateClientArea(); updateClientArea();
addDeleted( c, Allowed );
} }
void Workspace::removeUnmanaged( Unmanaged* c, allowed_t ) void Workspace::removeUnmanaged( Unmanaged* c, allowed_t )
{ {
assert( unmanaged.contains( c )); assert( unmanaged.contains( c ));
unmanaged.removeAll( c );
addDeleted( c, Allowed );
}
void Workspace::addDeleted( Toplevel* c, allowed_t )
{
assert( !pending_deleted.contains( c ));
pending_deleted.append( c );
}
void Workspace::removeDeleted( Toplevel* c )
{
assert( pending_deleted.contains( c ));
if( scene ) if( scene )
scene->windowDeleted( c ); scene->windowDeleted( c );
if( effects ) if( effects )
effects->windowDeleted( c ); effects->windowDeleted( c );
unmanaged.removeAll( c ); pending_deleted.removeAll( c );
} }
void Workspace::updateFocusChains( Client* c, FocusChainChange change ) void Workspace::updateFocusChains( Client* c, FocusChainChange change )

View file

@ -18,6 +18,8 @@ License. See the file "COPYING" for the exact licensing terms.
#include <QCursor> #include <QCursor>
#include <netwm.h> #include <netwm.h>
#include <kxmessages.h> #include <kxmessages.h>
#include <qdatetime.h>
#include <kmanagerselection.h>
#include "utils.h" #include "utils.h"
#include "kdecoration.h" #include "kdecoration.h"
@ -77,7 +79,7 @@ class Workspace : public QObject, public KDecorationDefines
virtual ~Workspace(); virtual ~Workspace();
static Workspace * self() { return _self; } static Workspace * self() { return _self; }
bool workspaceEvent( XEvent * ); bool workspaceEvent( XEvent * );
KDecoration* createDecoration( KDecorationBridge* bridge ); KDecoration* createDecoration( KDecorationBridge* bridge );
@ -87,6 +89,9 @@ class Workspace : public QObject, public KDecorationDefines
template< typename T > Client* findClient( T predicate ); template< typename T > Client* findClient( T predicate );
template< typename T1, typename T2 > void forEachClient( T1 procedure, T2 predicate ); template< typename T1, typename T2 > void forEachClient( T1 procedure, T2 predicate );
template< typename T > void forEachClient( T procedure ); template< typename T > void forEachClient( T procedure );
template< typename T > Unmanaged* findUnmanaged( T predicate );
template< typename T1, typename T2 > void forEachUnmanaged( T1 procedure, T2 predicate );
template< typename T > void forEachUnmanaged( T procedure );
QRect clientArea( clientAreaOption, const QPoint& p, int desktop ) const; QRect clientArea( clientAreaOption, const QPoint& p, int desktop ) const;
QRect clientArea( clientAreaOption, const Client* c ) const; QRect clientArea( clientAreaOption, const Client* c ) const;
@ -181,7 +186,7 @@ class Workspace : public QObject, public KDecorationDefines
ClientList ensureStackingOrder( const ClientList& clients ) const; ClientList ensureStackingOrder( const ClientList& clients ) const;
Client* topClientOnDesktop( int desktop, bool unconstrained = false, bool only_normal = true ) const; Client* topClientOnDesktop( int desktop, bool unconstrained = false ) const;
Client* findDesktop( bool topmost, int desktop ) const; Client* findDesktop( bool topmost, int desktop ) const;
void sendClientToDesktop( Client* c, int desktop, bool dont_activate ); void sendClientToDesktop( Client* c, int desktop, bool dont_activate );
void windowToPreviousDesktop( Client* c ); void windowToPreviousDesktop( Client* c );
@ -234,14 +239,17 @@ class Workspace : public QObject, public KDecorationDefines
void sendPingToWindow( Window w, Time timestamp ); // called from Client::pingWindow() void sendPingToWindow( Window w, Time timestamp ); // called from Client::pingWindow()
void sendTakeActivity( Client* c, Time timestamp, long flags ); // called from Client::takeActivity() void sendTakeActivity( Client* c, Time timestamp, long flags ); // called from Client::takeActivity()
// only called from Client::destroyClient() or Client::releaseWindow() void removeClient( Client*, allowed_t ); // only called from Client::destroyClient() or Client::releaseWindow()
void removeClient( Client*, allowed_t );
void setActiveClient( Client*, allowed_t ); void setActiveClient( Client*, allowed_t );
Group* findGroup( Window leader ) const; Group* findGroup( Window leader ) const;
void addGroup( Group* group, allowed_t ); void addGroup( Group* group, allowed_t );
void removeGroup( Group* group, allowed_t ); void removeGroup( Group* group, allowed_t );
Group* findClientLeaderGroup( const Client* c ) const; Group* findClientLeaderGroup( const Client* c ) const;
void removeUnmanaged( Unmanaged*, allowed_t ); // only called from Unmanaged::release()
void removeDeleted( Toplevel* );
void addDeleted( Toplevel*, allowed_t );
bool checkStartupNotification( Window w, KStartupInfoId& id, KStartupInfoData& data ); bool checkStartupNotification( Window w, KStartupInfoId& id, KStartupInfoData& data );
void focusToNull(); // SELI public? void focusToNull(); // SELI public?
@ -276,6 +284,17 @@ class Workspace : public QObject, public KDecorationDefines
void requestDelayFocus( Client* ); void requestDelayFocus( Client* );
void toggleTopDockShadows(bool on); void toggleTopDockShadows(bool on);
void addDamage( const QRect& r );
void addDamage( int x, int y, int w, int h );
void addDamageFull();
// creates XComposite overlay window, cal initOverlay() afterwards
bool createOverlay();
// init overlay and the destination window in it
void setupOverlay( Window window );
// destroys XComposite overlay window
void destroyOverlay();
Window overlayWindow();
public slots: public slots:
void refresh(); void refresh();
@ -406,12 +425,10 @@ class Workspace : public QObject, public KDecorationDefines
void cleanupTemporaryRules(); void cleanupTemporaryRules();
void writeWindowRules(); void writeWindowRules();
void slotBlockShortcuts(int data); void slotBlockShortcuts(int data);
void slotReloadConfig(); void setPopupClientOpacity( QAction* action );
// kompmgr void setupCompositing();
void setPopupClientOpacity(int v); void performCompositing();
void resetClientOpacity(); void lostCMSelection();
void setTransButtonText(int value);
// end
protected: protected:
bool keyPressMouseEmulation( XKeyEvent& ev ); bool keyPressMouseEmulation( XKeyEvent& ev );
@ -459,6 +476,8 @@ class Workspace : public QObject, public KDecorationDefines
// this is the right way to create a new client // this is the right way to create a new client
Client* createClient( Window w, bool is_mapped ); Client* createClient( Window w, bool is_mapped );
void addClient( Client* c, allowed_t ); void addClient( Client* c, allowed_t );
Unmanaged* createUnmanaged( Window w );
void addUnmanaged( Unmanaged* c, allowed_t );
Window findSpecialEventWindow( XEvent* e ); Window findSpecialEventWindow( XEvent* e );
@ -500,6 +519,8 @@ class Workspace : public QObject, public KDecorationDefines
void closeActivePopup(); void closeActivePopup();
void updateClientArea( bool force ); void updateClientArea( bool force );
void finishCompositing();
SystemTrayWindowList systemTrayWins; SystemTrayWindowList systemTrayWins;
@ -536,10 +557,12 @@ class Workspace : public QObject, public KDecorationDefines
ClientList clients; ClientList clients;
ClientList desktops; ClientList desktops;
UnmanagedList unmanaged;
ToplevelList pending_deleted;
ClientList unconstrained_stacking_order; // topmost last ClientList unconstrained_stacking_order;
ClientList stacking_order; // topmost last ClientList stacking_order;
QVector< ClientList > focus_chain; // currently ative last QVector< ClientList > focus_chain;
ClientList global_focus_chain; // this one is only for things like tabbox's MRU ClientList global_focus_chain; // this one is only for things like tabbox's MRU
ClientList should_get_focus; // last is most recent ClientList should_get_focus; // last is most recent
ClientList attention_chain; ClientList attention_chain;
@ -573,6 +596,7 @@ class Workspace : public QObject, public KDecorationDefines
QMenu *popup; QMenu *popup;
QMenu *advanced_popup; QMenu *advanced_popup;
QMenu *trans_popup;
QMenu *desk_popup; QMenu *desk_popup;
int desk_popup_index; int desk_popup_index;
@ -656,12 +680,14 @@ class Workspace : public QObject, public KDecorationDefines
bool forced_global_mouse_grab; bool forced_global_mouse_grab;
friend class StackingUpdatesBlocker; friend class StackingUpdatesBlocker;
//kompmgr KSelectionOwner* cm_selection;
QTimer compositeTimer;
QTime lastCompositePaint;
int compositeRate;
QRegion damage_region;
Window overlay; // XComposite overlay window
QSlider *transSlider; QSlider *transSlider;
QPushButton *transButton; QPushButton *transButton;
private:
friend bool performTransiencyCheck();
}; };
// helper for Workspace::blockStackingUpdates() being called in pairs (true/false) // helper for Workspace::blockStackingUpdates() being called in pairs (true/false)
@ -804,6 +830,11 @@ inline bool Workspace::globalShortcutsDisabled() const
return global_shortcuts_disabled || global_shortcuts_disabled_for_client; return global_shortcuts_disabled || global_shortcuts_disabled_for_client;
} }
inline Window Workspace::overlayWindow()
{
return overlay;
}
template< typename T > template< typename T >
inline Client* Workspace::findClient( T predicate ) inline Client* Workspace::findClient( T predicate )
{ {
@ -831,7 +862,27 @@ inline void Workspace::forEachClient( T procedure )
return forEachClient( procedure, TruePredicate()); return forEachClient( procedure, TruePredicate());
} }
KWIN_COMPARE_PREDICATE( ClientMatchPredicate, const Client*, cl == value ); template< typename T >
inline Unmanaged* Workspace::findUnmanaged( T predicate )
{
return findUnmanagedInList( unmanaged, predicate );
}
template< typename T1, typename T2 >
inline void Workspace::forEachUnmanaged( T1 procedure, T2 predicate )
{
for ( UnmanagedList::ConstIterator it = unmanaged.begin(); it != unmanaged.end(); ++it)
if ( predicate( const_cast< const Unmanaged* >( *it)))
procedure( *it );
}
template< typename T >
inline void Workspace::forEachUnmanaged( T procedure )
{
return forEachUnmanaged( procedure, TruePredicate());
}
KWIN_COMPARE_PREDICATE( ClientMatchPredicate, Client, const Client*, cl == value );
inline bool Workspace::hasClient( const Client* c ) inline bool Workspace::hasClient( const Client* c )
{ {
return findClient( ClientMatchPredicate( c )); return findClient( ClientMatchPredicate( c ));