Support for XComposite overlay window.

svn path=/branches/work/kwin_composite/; revision=603137
This commit is contained in:
Luboš Luňák 2006-11-07 22:44:39 +00:00
parent f631e57a01
commit 4110fc1c3a
9 changed files with 264 additions and 102 deletions

View file

@ -49,6 +49,10 @@ General TODO
! - scene_xrender.cpp also requires XFixes
! - check whether it compiles fine without XComposite/XDamage
? XComposite overlay window
? - does it make any sense to use it instead of painting directly to the root window
when the root window's visual etc. are good?
OpenGL TODO
=================================
@ -90,17 +94,6 @@ OpenGL TODO
of some #defines like GLX_TEXTURE_FORMAT_EXT
- Beryl has this code in beryl.h
! XComposite overlay window
- X.Org 7.1 and newer have XComposite extension version 0.3, which allows
creating an overlay window to paint to instead of painting to the root window
- the code in glcompmgr for this is in HAVE_OVERLAYS, stealing primarily from
here should be better since it's simpler and the code so far has been
modelled more after glcompmgr
- the code in compiz for this is in USE_COW
! - use double-buffering with the overlay window - kwin already has code
for double-buffered destination drawable, but I haven't been able to test it
- should be only needed for OpenGL code, I think this doesn't matter for XRender
! improved GLXFBConfig support
- it seems a different config for each depth would be needed
- from http://lists.freedesktop.org/archives/xorg/2006-July/016859.html and

View file

@ -35,6 +35,8 @@ License. See the file "COPYING" for the exact licensing terms.
#include "scene_xrender.h"
#include "scene_opengl.h"
#include <X11/extensions/shape.h>
namespace KWinInternal
{
@ -186,6 +188,39 @@ void Workspace::performCompositing()
lastCompositePaint.start();
}
bool Workspace::createOverlay()
{
assert( overlay == None );
if( !Extensions::compositeOverlayAvailable())
return false;
#ifdef HAVE_XCOMPOSITE_OVERLAY
overlay = XCompositeGetOverlayWindow( display(), rootWindow());
if( overlay == None )
return false;
return true;
#else
return false;
#endif
}
void Workspace::setupOverlay( Window w )
{
assert( overlay != None );
XShapeCombineRectangles( display(), overlay, ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted );
XShapeCombineRectangles( display(), w, ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted );
XMapRaised( display(), overlay );
}
void Workspace::destroyOverlay()
{
if( overlay == None )
return;
#ifdef HAVE_XCOMPOSITE_OVERLAY
XCompositeReleaseOverlayWindow( display(), overlay );
#endif
overlay = None;
}
//****************************************
// Toplevel
//****************************************

View file

@ -385,10 +385,7 @@ bool Workspace::workspaceEvent( XEvent * e )
if( c == NULL )
c = createUnmanaged( e->xmap.window );
if( c )
{
c->windowEvent( e );
return true;
}
return c->windowEvent( e );
}
return ( e->xmap.event != e->xmap.window ); // hide wm typical event from Qt
}

View file

@ -74,12 +74,12 @@ namespace KWinInternal
// the config used for windows
GLXFBConfig SceneOpenGL::fbcdrawable;
// GLX content
GLXContext SceneOpenGL::ctxroot;
GLXContext SceneOpenGL::ctxbuffer;
GLXContext SceneOpenGL::ctxdrawable;
// the destination drawable where the compositing is done
GLXDrawable SceneOpenGL::glxroot;
GLXDrawable SceneOpenGL::glxbuffer;
bool SceneOpenGL::tfp_mode; // using glXBindTexImageEXT (texture_from_pixmap)
bool SceneOpenGL::root_db; // destination drawable is double-buffered
bool SceneOpenGL::db; // destination drawable is double-buffered
bool SceneOpenGL::copy_buffer_hack; // workaround for nvidia < 1.0-9xxx drivers
// finding of OpenGL extensions functions
@ -125,8 +125,21 @@ const int root_db_attrs[] =
None
};
// attributes for finding a non-double-buffered root window config
static const int root_buffer_attrs[] =
// attributes for finding a double-buffered destination window config
static const int buffer_db_attrs[] =
{
GLX_CONFIG_CAVEAT, GLX_NONE,
GLX_DOUBLEBUFFER, True,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
None
};
// attributes for finding a non-double-buffered destination pixmap config
static const int buffer_nondb_attrs[] =
{
GLX_CONFIG_CAVEAT, GLX_NONE,
GLX_DOUBLEBUFFER, False,
@ -189,19 +202,21 @@ SceneOpenGL::SceneOpenGL( Workspace* ws )
initBuffer(); // create destination buffer
if( tfp_mode )
{
if( !findConfig( drawable_tfp_attrs, fbcdrawable ))
if( !findConfig( drawable_tfp_attrs, &fbcdrawable ))
{
tfp_mode = false;
if( !findConfig( drawable_attrs, fbcdrawable ))
if( !findConfig( drawable_attrs, &fbcdrawable ))
assert( false );
}
}
else
if( !findConfig( drawable_attrs, fbcdrawable ))
if( !findConfig( drawable_attrs, &fbcdrawable ))
assert( false );
ctxroot = glXCreateNewContext( display(), fbcroot, GLX_RGBA_TYPE, NULL, GL_FALSE );
ctxdrawable = glXCreateNewContext( display(), fbcdrawable, GLX_RGBA_TYPE, ctxroot, GL_FALSE );
glXMakeContextCurrent( display(), glxroot, glxroot, ctxroot );
ctxbuffer = glXCreateNewContext( display(), fbcbuffer, GLX_RGBA_TYPE, NULL, GL_FALSE );
ctxdrawable = glXCreateNewContext( display(), fbcdrawable, GLX_RGBA_TYPE, ctxbuffer, GL_FALSE );
glXMakeContextCurrent( display(), glxbuffer, glxbuffer, ctxbuffer );
if( db )
glDrawBuffer( GL_BACK );
// OpenGL scene setup
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
@ -209,7 +224,7 @@ SceneOpenGL::SceneOpenGL( Workspace* ws )
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
checkGLError( "Init" );
kDebug() << "Root DB:" << root_db << ", TFP:" << tfp_mode << endl;
kDebug() << "DB:" << db << ", TFP:" << tfp_mode << endl;
}
SceneOpenGL::~SceneOpenGL()
@ -218,15 +233,22 @@ SceneOpenGL::~SceneOpenGL()
it != windows.end();
++it )
(*it).free();
if( root_db )
glXDestroyWindow( display(), glxroot );
// do cleanup after initBuffer()
if( buffer == rootWindow())
glXDestroyWindow( display(), glxbuffer );
else if( wspace->overlayWindow())
{
glXDestroyWindow( display(), glxbuffer );
XDestroyWindow( display(), buffer );
wspace->destroyOverlay();
}
else
{
glXDestroyPixmap( display(), glxroot );
glXDestroyPixmap( display(), glxbuffer );
XFreeGC( display(), gcroot );
XFreePixmap( display(), buffer );
}
glXDestroyContext( display(), ctxroot );
glXDestroyContext( display(), ctxbuffer );
glXDestroyContext( display(), ctxdrawable );
checkGLError( "Cleanup" );
}
@ -236,32 +258,39 @@ void SceneOpenGL::initBuffer()
{
XWindowAttributes attrs;
XGetWindowAttributes( display(), rootWindow(), &attrs );
if( findConfig( root_db_attrs, fbcroot, XVisualIDFromVisual( attrs.visual )))
root_db = true;
else
{
if( findConfig( root_buffer_attrs, fbcroot ))
root_db = false;
else
assert( false );
}
if( root_db )
if( findConfig( root_db_attrs, &fbcbuffer, XVisualIDFromVisual( attrs.visual )))
{
// root window is double-buffered, paint directly to it
// TODO no need to use overlay?
db = true;
buffer = rootWindow();
glxroot = glXCreateWindow( display(), fbcroot, buffer, NULL );
glDrawBuffer( GL_BACK );
glxbuffer = glXCreateWindow( display(), fbcbuffer, buffer, NULL );
}
else
{
// no double-buffered root, paint to a buffer and copy to root window
else if( findConfig( buffer_db_attrs, &fbcbuffer ) && wspace->createOverlay())
{ // we have overlay, try to create double-buffered window in it
XVisualInfo* visual = glXGetVisualFromFBConfig( display(), fbcbuffer );
kDebug() << "Using overlay visual 0x" << QString::number( visual->visualid ) << endl;
XSetWindowAttributes attrs;
attrs.colormap = XCreateColormap( display(), rootWindow(), visual->visual, AllocNone );
buffer = XCreateWindow( display(), wspace->overlayWindow(), 0, 0, displayWidth(), displayHeight(),
0, QX11Info::appDepth(), InputOutput, visual->visual, CWColormap, &attrs );
glxbuffer = glXCreateWindow( display(), fbcbuffer, buffer, NULL );
wspace->setupOverlay( buffer );
db = true;
XFree( visual );
}
else if( findConfig( buffer_nondb_attrs, &fbcbuffer ))
{ // cannot get any double-buffered drawable, will double-buffer using a pixmap
db = false;
XGCValues gcattr;
gcattr.subwindow_mode = IncludeInferiors;
gcroot = XCreateGC( display(), rootWindow(), GCSubwindowMode, &gcattr );
buffer = XCreatePixmap( display(), rootWindow(), displayWidth(), displayHeight(),
QX11Info::appDepth());
glxroot = glXCreatePixmap( display(), fbcroot, buffer, NULL );
glxbuffer = glXCreatePixmap( display(), fbcbuffer, buffer, NULL );
}
else
assert( false );
}
// print info about found configs
@ -283,7 +312,7 @@ static void debugFBConfig( GLXFBConfig* fbconfigs, int i, const int* attrs )
}
// find config matching the given attributes and possibly the given X visual
bool SceneOpenGL::findConfig( const int* attrs, GLXFBConfig& config, VisualID visual )
bool SceneOpenGL::findConfig( const int* attrs, GLXFBConfig* config, VisualID visual )
{
int cnt;
GLXFBConfig* fbconfigs = glXChooseFBConfig( display(), DefaultScreen( display()),
@ -292,7 +321,7 @@ bool SceneOpenGL::findConfig( const int* attrs, GLXFBConfig& config, VisualID vi
{
if( visual == None )
{
config = fbconfigs[ 0 ];
*config = fbconfigs[ 0 ];
kDebug() << "Found FBConfig" << endl;
debugFBConfig( fbconfigs, 0, attrs );
XFree( fbconfigs );
@ -309,7 +338,7 @@ bool SceneOpenGL::findConfig( const int* attrs, GLXFBConfig& config, VisualID vi
if( value == (int)visual )
{
kDebug() << "Found FBConfig" << endl;
config = fbconfigs[ i ];
*config = fbconfigs[ i ];
debugFBConfig( fbconfigs, i, attrs );
XFree( fbconfigs );
return true;
@ -354,8 +383,12 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels )
paintScreen( &mask, &damage ); // call generic implementation
glPopMatrix();
// TODO only partial repaint for mask & PAINT_SCREEN_REGION
if( root_db )
glXSwapBuffers( display(), glxroot );
if( db )
{
glXSwapBuffers( display(), glxbuffer );
glXWaitGL();
XFlush( display());
}
else
{
glFlush();
@ -561,9 +594,9 @@ void SceneOpenGL::Window::bindTexture()
glXWaitGL();
glXDestroyPixmap( display(), pixmap );
XFreePixmap( display(), pix );
if( root_db )
if( db )
glDrawBuffer( GL_BACK );
glXMakeContextCurrent( display(), glxroot, glxroot, ctxroot );
glXMakeContextCurrent( display(), glxbuffer, glxbuffer, ctxbuffer );
glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texture );
}
if( copy_buffer )

View file

@ -37,15 +37,15 @@ class SceneOpenGL
virtual void paintBackground( QRegion region );
private:
void initBuffer();
bool findConfig( const int* attrs, GLXFBConfig& config, VisualID visual = None );
bool findConfig( const int* attrs, GLXFBConfig* config, VisualID visual = None );
typedef GLuint Texture;
GC gcroot;
Drawable buffer;
GLXFBConfig fbcroot;
static bool root_db;
GLXFBConfig fbcbuffer;
static bool db;
static GLXFBConfig fbcdrawable;
static GLXDrawable glxroot;
static GLXContext ctxroot;
static GLXDrawable glxbuffer;
static GLXContext ctxbuffer;
static GLXContext ctxdrawable;
static bool tfp_mode;
static bool copy_buffer_hack;

View file

@ -43,12 +43,13 @@ namespace KWinInternal
#ifndef KCMRULES
bool Extensions::has_shape = 0;
bool Extensions::has_shape = false;
int Extensions::shape_event_base = 0;
bool Extensions::has_damage = 0;
bool Extensions::has_damage = false;
int Extensions::damage_event_base = 0;
bool Extensions::has_composite = 0;
bool Extensions::has_fixes = 0;
bool Extensions::has_composite = false;
bool Extensions::has_composite_overlay = false;
bool Extensions::has_fixes = false;
void Extensions::init()
{
@ -63,14 +64,14 @@ void Extensions::init()
has_composite = XCompositeQueryExtension( display(), &dummy, &dummy );
if( has_composite )
{
int major = 0;
int minor = 2;
int major, minor;
XCompositeQueryVersion( display(), &major, &minor );
if( major == 0 && minor < 2 )
has_composite = false;
has_composite = ( major > 0 || minor >= 2 );
has_composite_overlay = ( major > 0 || minor >= 3 );
}
#else
has_composite = false;
has_composite_overlay = false;
#endif
#ifdef HAVE_XFIXES
has_fixes = XFixesQueryExtension( display(), &dummy, &dummy );

View file

@ -16,12 +16,18 @@ License. See the file "COPYING" for the exact licensing terms.
#include <config-X11.h>
#include <X11/Xlib.h>
#ifdef HAVE_XCOMPOSITE
#include <X11/extensions/Xcomposite.h>
#if XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR >= 3
#define HAVE_XCOMPOSITE_OVERLAY
#endif
#endif
#ifdef HAVE_XDAMAGE
#include <X11/extensions/Xdamage.h>
#endif
#ifdef HAVE_XFIXES
#include <X11/extensions/Xfixes.h>
#endif
@ -148,6 +154,7 @@ class Extensions
static bool damageAvailable() { return has_damage; }
static int damageNotifyEvent();
static bool compositeAvailable() { return has_composite; }
static bool compositeOverlayAvailable() { return has_composite && has_composite_overlay; }
static bool fixesAvailable() { return has_fixes; }
static bool hasShape( Window w );
private:
@ -156,6 +163,7 @@ class Extensions
static bool has_damage;
static int damage_event_base;
static bool has_composite;
static bool has_composite_overlay;
static bool has_fixes;
};

View file

@ -42,6 +42,9 @@ License. See the file "COPYING" for the exact licensing terms.
#include "group.h"
#include "rules.h"
#include "kwinadaptor.h"
#include "unmanaged.h"
#include "scene.h"
#include "effects.h"
#include <X11/extensions/shape.h>
#include <X11/keysym.h>
@ -122,7 +125,9 @@ Workspace::Workspace( bool restore )
topmenu_space( NULL ),
set_active_client_recursion( 0 ),
block_stacking_updates( 0 ),
forced_global_mouse_grab( false )
forced_global_mouse_grab( false ),
damage_region( None ),
overlay( None )
{
new KWinAdaptor( "org.kde.kwin", "/KWin", QDBusConnection::sessionBus(), this );
@ -166,10 +171,12 @@ Workspace::Workspace( bool restore )
ColormapChangeMask |
SubstructureRedirectMask |
SubstructureNotifyMask |
FocusChangeMask // for NotifyDetailNone
FocusChangeMask | // for NotifyDetailNone
ExposureMask
);
Shape::init();
Extensions::init();
setupCompositing();
// compatibility
long data = 1;
@ -318,6 +325,7 @@ void Workspace::init()
connect(&reconfigureTimer, SIGNAL(timeout()), this,
SLOT(slotReconfigure()));
connect( &updateToolWindowsTimer, SIGNAL( timeout()), this, SLOT( slotUpdateToolWindows()));
connect( &compositeTimer, SIGNAL( timeout()), SLOT( performCompositing()));
connect(KGlobalSettings::self(), SIGNAL(appearanceChanged()), this,
SLOT(slotReconfigure()));
@ -355,7 +363,11 @@ void Workspace::init()
XWindowAttributes attr;
XGetWindowAttributes(display(), wins[i], &attr);
if (attr.override_redirect )
{
if( attr.map_state != IsUnmapped && attr.c_class != InputOnly && compositing())
createUnmanaged( wins[ i ] );
continue;
}
if( topmenu_space && topmenu_space->winId() == wins[ i ] )
continue;
if (attr.map_state != IsUnmapped)
@ -418,6 +430,7 @@ void Workspace::init()
Workspace::~Workspace()
{
finishCompositing();
blockStackingUpdates( true );
// TODO grabXServer();
// use stacking_order, so that kwin --replace keeps stacking order
@ -429,6 +442,10 @@ Workspace::~Workspace()
(*it)->releaseWindow( true );
// no removeClient() is called !
}
for( UnmanagedList::ConstIterator it = unmanaged.begin();
it != unmanaged.end();
++it )
(*it)->release();
delete desktop_widget;
delete tab_box;
delete popupinfo;
@ -472,6 +489,28 @@ Client* Workspace::createClient( Window w, bool is_mapped )
return NULL;
}
addClient( c, Allowed );
if( scene )
scene->windowAdded( c );
if( effects )
effects->windowAdded( c );
return c;
}
Unmanaged* Workspace::createUnmanaged( Window w )
{
if( w == overlay )
return NULL;
Unmanaged* c = new Unmanaged( this );
if( !c->track( w ))
{
Unmanaged::deleteUnmanaged( c, Allowed );
return NULL;
}
addUnmanaged( c, Allowed );
if( scene )
scene->windowAdded( c );
if( effects )
effects->windowAdded( c );
return c;
}
@ -514,6 +553,11 @@ void Workspace::addClient( Client* c, allowed_t )
updateToolWindows( true );
}
void Workspace::addUnmanaged( Unmanaged* c, allowed_t )
{
unmanaged.append( c );
}
/*
Destroys the client \a c
*/
@ -533,6 +577,10 @@ void Workspace::removeClient( Client* c, allowed_t )
Notify::raise( Notify::Delete );
Q_ASSERT( clients.contains( c ) || desktops.contains( c ));
if( scene )
scene->windowDeleted( c );
if( effects )
effects->windowDeleted( c );
clients.removeAll( c );
desktops.removeAll( c );
unconstrained_stacking_order.removeAll( c );
@ -568,6 +616,16 @@ void Workspace::removeClient( Client* c, allowed_t )
updateClientArea();
}
void Workspace::removeUnmanaged( Unmanaged* c, allowed_t )
{
assert( unmanaged.contains( c ));
if( scene )
scene->windowDeleted( c );
if( effects )
effects->windowDeleted( c );
unmanaged.removeAll( c );
}
void Workspace::updateFocusChains( Client* c, FocusChainChange change )
{
if( !c->wantsTabFocus()) // doesn't want tab focus, remove
@ -593,13 +651,7 @@ void Workspace::updateFocusChains( Client* c, FocusChainChange change )
focus_chain[ i ].prepend( c );
}
else if( !focus_chain[ i ].contains( c ))
{ // add it after the active one
if( active_client != NULL && active_client != c
&& !focus_chain[ i ].isEmpty() && focus_chain[ i ].last() == active_client )
focus_chain[ i ].insert( focus_chain[ i ].size() - 1, c );
else
focus_chain[ i ].append( c ); // otherwise add as the first one
}
focus_chain[ i ].prepend( c ); // otherwise add as the last one
}
}
else //now only on desktop, remove it anywhere else
@ -619,13 +671,7 @@ void Workspace::updateFocusChains( Client* c, FocusChainChange change )
focus_chain[ i ].prepend( c );
}
else if( !focus_chain[ i ].contains( c ))
{ // add it after the active one
if( active_client != NULL && active_client != c
&& !focus_chain[ i ].isEmpty() && focus_chain[ i ].last() == active_client )
focus_chain[ i ].insert( focus_chain[ i ].size() - 1, c );
else
focus_chain[ i ].append( c ); // otherwise add as the first one
}
focus_chain[ i ].prepend( c );
}
else
focus_chain[ i ].removeAll( c );
@ -642,13 +688,7 @@ void Workspace::updateFocusChains( Client* c, FocusChainChange change )
global_focus_chain.prepend( c );
}
else if( !global_focus_chain.contains( c ))
{ // add it after the active one
if( active_client != NULL && active_client != c
&& !global_focus_chain.isEmpty() && global_focus_chain.last() == active_client )
global_focus_chain.insert( global_focus_chain.size() - 1, c );
else
global_focus_chain.append( c ); // otherwise add as the first one
}
global_focus_chain.prepend( c );
}
void Workspace::updateCurrentTopMenu()
@ -882,7 +922,7 @@ void Workspace::slotSettingsChanged(int category)
/*!
Reread settings
*/
KWIN_PROCEDURE( CheckBorderSizesProcedure, cl->checkBorderSizes() );
KWIN_PROCEDURE( CheckBorderSizesProcedure, Client, cl->checkBorderSizes() );
void Workspace::slotReconfigure()
{
@ -940,6 +980,11 @@ void Workspace::slotReconfigure()
updateCurrentTopMenu();
}
if( options->useTranslucency )
setupCompositing();
else
finishCompositing();
loadWindowRules();
for( ClientList::Iterator it = clients.begin();
it != clients.end();
@ -1640,7 +1685,7 @@ void Workspace::slotGrabWindow()
QPixmap snapshot = QPixmap::grabWindow( active_client->frameId() );
//No XShape - no work.
if( Shape::available())
if( Extensions::shapeAvailable())
{
//As the first step, get the mask from XShape.
int count, order;

View file

@ -18,6 +18,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include <QCursor>
#include <netwm.h>
#include <kxmessages.h>
#include <qdatetime.h>
#include "utils.h"
#include "kdecoration.h"
@ -87,6 +88,9 @@ class Workspace : public QObject, public KDecorationDefines
template< typename T > Client* findClient( T predicate );
template< typename T1, typename T2 > void forEachClient( T1 procedure, T2 predicate );
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 Client* c ) const;
@ -242,6 +246,9 @@ class Workspace : public QObject, public KDecorationDefines
void removeGroup( Group* group, allowed_t );
Group* findClientLeaderGroup( const Client* c ) const;
// only called from Unmanaged::release()
void removeUnmanaged( Unmanaged*, allowed_t );
bool checkStartupNotification( Window w, KStartupInfoId& id, KStartupInfoData& data );
void focusToNull(); // SELI public?
@ -277,6 +284,17 @@ class Workspace : public QObject, public KDecorationDefines
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:
void refresh();
// keybindings
@ -406,11 +424,10 @@ class Workspace : public QObject, public KDecorationDefines
void cleanupTemporaryRules();
void writeWindowRules();
void slotBlockShortcuts(int data);
// kompmgr
void setPopupClientOpacity(int v);
void resetClientOpacity();
void setTransButtonText(int value);
// end
void performCompositing();
protected:
bool keyPressMouseEmulation( XKeyEvent& ev );
@ -458,6 +475,8 @@ class Workspace : public QObject, public KDecorationDefines
// this is the right way to create a new client
Client* createClient( Window w, bool is_mapped );
void addClient( Client* c, allowed_t );
Unmanaged* createUnmanaged( Window w );
void addUnmanaged( Unmanaged* c, allowed_t );
Window findSpecialEventWindow( XEvent* e );
@ -500,6 +519,9 @@ class Workspace : public QObject, public KDecorationDefines
void updateClientArea( bool force );
void setupCompositing();
void finishCompositing();
SystemTrayWindowList systemTrayWins;
int current_desktop;
@ -535,10 +557,11 @@ class Workspace : public QObject, public KDecorationDefines
ClientList clients;
ClientList desktops;
UnmanagedList unmanaged;
ClientList unconstrained_stacking_order; // topmost last
ClientList stacking_order; // topmost last
QVector< ClientList > focus_chain; // currently ative last
ClientList unconstrained_stacking_order;
ClientList stacking_order;
QVector< ClientList > focus_chain;
ClientList global_focus_chain; // this one is only for things like tabbox's MRU
ClientList should_get_focus; // last is most recent
ClientList attention_chain;
@ -654,8 +677,10 @@ class Workspace : public QObject, public KDecorationDefines
Window null_focus_window;
bool forced_global_mouse_grab;
friend class StackingUpdatesBlocker;
//kompmgr
QTimer compositeTimer;
QTime lastCompositePaint;
QRegion damage_region;
Window overlay; // XComposite overlay window
QSlider *transSlider;
QPushButton *transButton;
};
@ -800,6 +825,11 @@ inline bool Workspace::globalShortcutsDisabled() const
return global_shortcuts_disabled || global_shortcuts_disabled_for_client;
}
inline Window Workspace::overlayWindow()
{
return overlay;
}
template< typename T >
inline Client* Workspace::findClient( T predicate )
{
@ -827,7 +857,27 @@ inline void Workspace::forEachClient( T procedure )
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 )
{
return findClient( ClientMatchPredicate( c ));