Support for XComposite overlay window.
svn path=/branches/work/kwin_composite/; revision=603137
This commit is contained in:
parent
f631e57a01
commit
4110fc1c3a
9 changed files with 264 additions and 102 deletions
|
@ -49,6 +49,10 @@ General TODO
|
||||||
! - scene_xrender.cpp also requires XFixes
|
! - scene_xrender.cpp also requires XFixes
|
||||||
! - check whether it compiles fine without XComposite/XDamage
|
! - 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
|
OpenGL TODO
|
||||||
=================================
|
=================================
|
||||||
|
@ -90,17 +94,6 @@ OpenGL TODO
|
||||||
of some #defines like GLX_TEXTURE_FORMAT_EXT
|
of some #defines like GLX_TEXTURE_FORMAT_EXT
|
||||||
- Beryl has this code in beryl.h
|
- 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
|
! improved GLXFBConfig support
|
||||||
- it seems a different config for each depth would be needed
|
- it seems a different config for each depth would be needed
|
||||||
- from http://lists.freedesktop.org/archives/xorg/2006-July/016859.html and
|
- from http://lists.freedesktop.org/archives/xorg/2006-July/016859.html and
|
||||||
|
|
|
@ -35,6 +35,8 @@ License. See the file "COPYING" for the exact licensing terms.
|
||||||
#include "scene_xrender.h"
|
#include "scene_xrender.h"
|
||||||
#include "scene_opengl.h"
|
#include "scene_opengl.h"
|
||||||
|
|
||||||
|
#include <X11/extensions/shape.h>
|
||||||
|
|
||||||
namespace KWinInternal
|
namespace KWinInternal
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -186,6 +188,39 @@ void Workspace::performCompositing()
|
||||||
lastCompositePaint.start();
|
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
|
// Toplevel
|
||||||
//****************************************
|
//****************************************
|
||||||
|
|
|
@ -385,10 +385,7 @@ bool Workspace::workspaceEvent( XEvent * e )
|
||||||
if( c == NULL )
|
if( c == NULL )
|
||||||
c = createUnmanaged( e->xmap.window );
|
c = createUnmanaged( e->xmap.window );
|
||||||
if( c )
|
if( c )
|
||||||
{
|
return c->windowEvent( e );
|
||||||
c->windowEvent( e );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ( e->xmap.event != e->xmap.window ); // hide wm typical event from Qt
|
return ( e->xmap.event != e->xmap.window ); // hide wm typical event from Qt
|
||||||
}
|
}
|
||||||
|
|
111
scene_opengl.cpp
111
scene_opengl.cpp
|
@ -74,12 +74,12 @@ namespace KWinInternal
|
||||||
// the config used for windows
|
// the config used for windows
|
||||||
GLXFBConfig SceneOpenGL::fbcdrawable;
|
GLXFBConfig SceneOpenGL::fbcdrawable;
|
||||||
// GLX content
|
// GLX content
|
||||||
GLXContext SceneOpenGL::ctxroot;
|
GLXContext SceneOpenGL::ctxbuffer;
|
||||||
GLXContext SceneOpenGL::ctxdrawable;
|
GLXContext SceneOpenGL::ctxdrawable;
|
||||||
// the destination drawable where the compositing is done
|
// 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::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
|
bool SceneOpenGL::copy_buffer_hack; // workaround for nvidia < 1.0-9xxx drivers
|
||||||
|
|
||||||
// finding of OpenGL extensions functions
|
// finding of OpenGL extensions functions
|
||||||
|
@ -125,8 +125,21 @@ const int root_db_attrs[] =
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
// attributes for finding a non-double-buffered root window config
|
// attributes for finding a double-buffered destination window config
|
||||||
static const int root_buffer_attrs[] =
|
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_CONFIG_CAVEAT, GLX_NONE,
|
||||||
GLX_DOUBLEBUFFER, False,
|
GLX_DOUBLEBUFFER, False,
|
||||||
|
@ -189,19 +202,21 @@ SceneOpenGL::SceneOpenGL( Workspace* ws )
|
||||||
initBuffer(); // create destination buffer
|
initBuffer(); // create destination buffer
|
||||||
if( tfp_mode )
|
if( tfp_mode )
|
||||||
{
|
{
|
||||||
if( !findConfig( drawable_tfp_attrs, fbcdrawable ))
|
if( !findConfig( drawable_tfp_attrs, &fbcdrawable ))
|
||||||
{
|
{
|
||||||
tfp_mode = false;
|
tfp_mode = false;
|
||||||
if( !findConfig( drawable_attrs, fbcdrawable ))
|
if( !findConfig( drawable_attrs, &fbcdrawable ))
|
||||||
assert( false );
|
assert( false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if( !findConfig( drawable_attrs, fbcdrawable ))
|
if( !findConfig( drawable_attrs, &fbcdrawable ))
|
||||||
assert( false );
|
assert( false );
|
||||||
ctxroot = glXCreateNewContext( display(), fbcroot, GLX_RGBA_TYPE, NULL, GL_FALSE );
|
ctxbuffer = glXCreateNewContext( display(), fbcbuffer, GLX_RGBA_TYPE, NULL, GL_FALSE );
|
||||||
ctxdrawable = glXCreateNewContext( display(), fbcdrawable, GLX_RGBA_TYPE, ctxroot, GL_FALSE );
|
ctxdrawable = glXCreateNewContext( display(), fbcdrawable, GLX_RGBA_TYPE, ctxbuffer, GL_FALSE );
|
||||||
glXMakeContextCurrent( display(), glxroot, glxroot, ctxroot );
|
glXMakeContextCurrent( display(), glxbuffer, glxbuffer, ctxbuffer );
|
||||||
|
if( db )
|
||||||
|
glDrawBuffer( GL_BACK );
|
||||||
// OpenGL scene setup
|
// OpenGL scene setup
|
||||||
glMatrixMode( GL_PROJECTION );
|
glMatrixMode( GL_PROJECTION );
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
|
@ -209,7 +224,7 @@ SceneOpenGL::SceneOpenGL( Workspace* ws )
|
||||||
glMatrixMode( GL_MODELVIEW );
|
glMatrixMode( GL_MODELVIEW );
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
checkGLError( "Init" );
|
checkGLError( "Init" );
|
||||||
kDebug() << "Root DB:" << root_db << ", TFP:" << tfp_mode << endl;
|
kDebug() << "DB:" << db << ", TFP:" << tfp_mode << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
SceneOpenGL::~SceneOpenGL()
|
SceneOpenGL::~SceneOpenGL()
|
||||||
|
@ -218,15 +233,22 @@ SceneOpenGL::~SceneOpenGL()
|
||||||
it != windows.end();
|
it != windows.end();
|
||||||
++it )
|
++it )
|
||||||
(*it).free();
|
(*it).free();
|
||||||
if( root_db )
|
// do cleanup after initBuffer()
|
||||||
glXDestroyWindow( display(), glxroot );
|
if( buffer == rootWindow())
|
||||||
|
glXDestroyWindow( display(), glxbuffer );
|
||||||
|
else if( wspace->overlayWindow())
|
||||||
|
{
|
||||||
|
glXDestroyWindow( display(), glxbuffer );
|
||||||
|
XDestroyWindow( display(), buffer );
|
||||||
|
wspace->destroyOverlay();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glXDestroyPixmap( display(), glxroot );
|
glXDestroyPixmap( display(), glxbuffer );
|
||||||
XFreeGC( display(), gcroot );
|
XFreeGC( display(), gcroot );
|
||||||
XFreePixmap( display(), buffer );
|
XFreePixmap( display(), buffer );
|
||||||
}
|
}
|
||||||
glXDestroyContext( display(), ctxroot );
|
glXDestroyContext( display(), ctxbuffer );
|
||||||
glXDestroyContext( display(), ctxdrawable );
|
glXDestroyContext( display(), ctxdrawable );
|
||||||
checkGLError( "Cleanup" );
|
checkGLError( "Cleanup" );
|
||||||
}
|
}
|
||||||
|
@ -236,32 +258,39 @@ void SceneOpenGL::initBuffer()
|
||||||
{
|
{
|
||||||
XWindowAttributes attrs;
|
XWindowAttributes attrs;
|
||||||
XGetWindowAttributes( display(), rootWindow(), &attrs );
|
XGetWindowAttributes( display(), rootWindow(), &attrs );
|
||||||
if( findConfig( root_db_attrs, fbcroot, XVisualIDFromVisual( attrs.visual )))
|
if( findConfig( root_db_attrs, &fbcbuffer, XVisualIDFromVisual( attrs.visual )))
|
||||||
root_db = true;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if( findConfig( root_buffer_attrs, fbcroot ))
|
|
||||||
root_db = false;
|
|
||||||
else
|
|
||||||
assert( false );
|
|
||||||
}
|
|
||||||
if( root_db )
|
|
||||||
{
|
{
|
||||||
// root window is double-buffered, paint directly to it
|
// root window is double-buffered, paint directly to it
|
||||||
|
// TODO no need to use overlay?
|
||||||
|
db = true;
|
||||||
buffer = rootWindow();
|
buffer = rootWindow();
|
||||||
glxroot = glXCreateWindow( display(), fbcroot, buffer, NULL );
|
glxbuffer = glXCreateWindow( display(), fbcbuffer, buffer, NULL );
|
||||||
glDrawBuffer( GL_BACK );
|
|
||||||
}
|
}
|
||||||
else
|
else if( findConfig( buffer_db_attrs, &fbcbuffer ) && wspace->createOverlay())
|
||||||
{
|
{ // we have overlay, try to create double-buffered window in it
|
||||||
// no double-buffered root, paint to a buffer and copy to root window
|
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;
|
XGCValues gcattr;
|
||||||
gcattr.subwindow_mode = IncludeInferiors;
|
gcattr.subwindow_mode = IncludeInferiors;
|
||||||
gcroot = XCreateGC( display(), rootWindow(), GCSubwindowMode, &gcattr );
|
gcroot = XCreateGC( display(), rootWindow(), GCSubwindowMode, &gcattr );
|
||||||
buffer = XCreatePixmap( display(), rootWindow(), displayWidth(), displayHeight(),
|
buffer = XCreatePixmap( display(), rootWindow(), displayWidth(), displayHeight(),
|
||||||
QX11Info::appDepth());
|
QX11Info::appDepth());
|
||||||
glxroot = glXCreatePixmap( display(), fbcroot, buffer, NULL );
|
glxbuffer = glXCreatePixmap( display(), fbcbuffer, buffer, NULL );
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
assert( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
// print info about found configs
|
// 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
|
// 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;
|
int cnt;
|
||||||
GLXFBConfig* fbconfigs = glXChooseFBConfig( display(), DefaultScreen( display()),
|
GLXFBConfig* fbconfigs = glXChooseFBConfig( display(), DefaultScreen( display()),
|
||||||
|
@ -292,7 +321,7 @@ bool SceneOpenGL::findConfig( const int* attrs, GLXFBConfig& config, VisualID vi
|
||||||
{
|
{
|
||||||
if( visual == None )
|
if( visual == None )
|
||||||
{
|
{
|
||||||
config = fbconfigs[ 0 ];
|
*config = fbconfigs[ 0 ];
|
||||||
kDebug() << "Found FBConfig" << endl;
|
kDebug() << "Found FBConfig" << endl;
|
||||||
debugFBConfig( fbconfigs, 0, attrs );
|
debugFBConfig( fbconfigs, 0, attrs );
|
||||||
XFree( fbconfigs );
|
XFree( fbconfigs );
|
||||||
|
@ -309,7 +338,7 @@ bool SceneOpenGL::findConfig( const int* attrs, GLXFBConfig& config, VisualID vi
|
||||||
if( value == (int)visual )
|
if( value == (int)visual )
|
||||||
{
|
{
|
||||||
kDebug() << "Found FBConfig" << endl;
|
kDebug() << "Found FBConfig" << endl;
|
||||||
config = fbconfigs[ i ];
|
*config = fbconfigs[ i ];
|
||||||
debugFBConfig( fbconfigs, i, attrs );
|
debugFBConfig( fbconfigs, i, attrs );
|
||||||
XFree( fbconfigs );
|
XFree( fbconfigs );
|
||||||
return true;
|
return true;
|
||||||
|
@ -354,8 +383,12 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels )
|
||||||
paintScreen( &mask, &damage ); // call generic implementation
|
paintScreen( &mask, &damage ); // call generic implementation
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
// TODO only partial repaint for mask & PAINT_SCREEN_REGION
|
// TODO only partial repaint for mask & PAINT_SCREEN_REGION
|
||||||
if( root_db )
|
if( db )
|
||||||
glXSwapBuffers( display(), glxroot );
|
{
|
||||||
|
glXSwapBuffers( display(), glxbuffer );
|
||||||
|
glXWaitGL();
|
||||||
|
XFlush( display());
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glFlush();
|
glFlush();
|
||||||
|
@ -561,9 +594,9 @@ void SceneOpenGL::Window::bindTexture()
|
||||||
glXWaitGL();
|
glXWaitGL();
|
||||||
glXDestroyPixmap( display(), pixmap );
|
glXDestroyPixmap( display(), pixmap );
|
||||||
XFreePixmap( display(), pix );
|
XFreePixmap( display(), pix );
|
||||||
if( root_db )
|
if( db )
|
||||||
glDrawBuffer( GL_BACK );
|
glDrawBuffer( GL_BACK );
|
||||||
glXMakeContextCurrent( display(), glxroot, glxroot, ctxroot );
|
glXMakeContextCurrent( display(), glxbuffer, glxbuffer, ctxbuffer );
|
||||||
glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texture );
|
glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texture );
|
||||||
}
|
}
|
||||||
if( copy_buffer )
|
if( copy_buffer )
|
||||||
|
|
|
@ -37,15 +37,15 @@ class SceneOpenGL
|
||||||
virtual void paintBackground( QRegion region );
|
virtual void paintBackground( QRegion region );
|
||||||
private:
|
private:
|
||||||
void initBuffer();
|
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;
|
typedef GLuint Texture;
|
||||||
GC gcroot;
|
GC gcroot;
|
||||||
Drawable buffer;
|
Drawable buffer;
|
||||||
GLXFBConfig fbcroot;
|
GLXFBConfig fbcbuffer;
|
||||||
static bool root_db;
|
static bool db;
|
||||||
static GLXFBConfig fbcdrawable;
|
static GLXFBConfig fbcdrawable;
|
||||||
static GLXDrawable glxroot;
|
static GLXDrawable glxbuffer;
|
||||||
static GLXContext ctxroot;
|
static GLXContext ctxbuffer;
|
||||||
static GLXContext ctxdrawable;
|
static GLXContext ctxdrawable;
|
||||||
static bool tfp_mode;
|
static bool tfp_mode;
|
||||||
static bool copy_buffer_hack;
|
static bool copy_buffer_hack;
|
||||||
|
|
17
utils.cpp
17
utils.cpp
|
@ -43,12 +43,13 @@ namespace KWinInternal
|
||||||
|
|
||||||
#ifndef KCMRULES
|
#ifndef KCMRULES
|
||||||
|
|
||||||
bool Extensions::has_shape = 0;
|
bool Extensions::has_shape = false;
|
||||||
int Extensions::shape_event_base = 0;
|
int Extensions::shape_event_base = 0;
|
||||||
bool Extensions::has_damage = 0;
|
bool Extensions::has_damage = false;
|
||||||
int Extensions::damage_event_base = 0;
|
int Extensions::damage_event_base = 0;
|
||||||
bool Extensions::has_composite = 0;
|
bool Extensions::has_composite = false;
|
||||||
bool Extensions::has_fixes = 0;
|
bool Extensions::has_composite_overlay = false;
|
||||||
|
bool Extensions::has_fixes = false;
|
||||||
|
|
||||||
void Extensions::init()
|
void Extensions::init()
|
||||||
{
|
{
|
||||||
|
@ -63,14 +64,14 @@ void Extensions::init()
|
||||||
has_composite = XCompositeQueryExtension( display(), &dummy, &dummy );
|
has_composite = XCompositeQueryExtension( display(), &dummy, &dummy );
|
||||||
if( has_composite )
|
if( has_composite )
|
||||||
{
|
{
|
||||||
int major = 0;
|
int major, minor;
|
||||||
int minor = 2;
|
|
||||||
XCompositeQueryVersion( display(), &major, &minor );
|
XCompositeQueryVersion( display(), &major, &minor );
|
||||||
if( major == 0 && minor < 2 )
|
has_composite = ( major > 0 || minor >= 2 );
|
||||||
has_composite = false;
|
has_composite_overlay = ( major > 0 || minor >= 3 );
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
has_composite = false;
|
has_composite = false;
|
||||||
|
has_composite_overlay = false;
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_XFIXES
|
#ifdef HAVE_XFIXES
|
||||||
has_fixes = XFixesQueryExtension( display(), &dummy, &dummy );
|
has_fixes = XFixesQueryExtension( display(), &dummy, &dummy );
|
||||||
|
|
8
utils.h
8
utils.h
|
@ -16,12 +16,18 @@ License. See the file "COPYING" for the exact licensing terms.
|
||||||
#include <config-X11.h>
|
#include <config-X11.h>
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
#ifdef HAVE_XCOMPOSITE
|
#ifdef HAVE_XCOMPOSITE
|
||||||
#include <X11/extensions/Xcomposite.h>
|
#include <X11/extensions/Xcomposite.h>
|
||||||
|
#if XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR >= 3
|
||||||
|
#define HAVE_XCOMPOSITE_OVERLAY
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_XDAMAGE
|
#ifdef HAVE_XDAMAGE
|
||||||
#include <X11/extensions/Xdamage.h>
|
#include <X11/extensions/Xdamage.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_XFIXES
|
#ifdef HAVE_XFIXES
|
||||||
#include <X11/extensions/Xfixes.h>
|
#include <X11/extensions/Xfixes.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -148,6 +154,7 @@ class Extensions
|
||||||
static bool damageAvailable() { return has_damage; }
|
static bool damageAvailable() { return has_damage; }
|
||||||
static int damageNotifyEvent();
|
static int damageNotifyEvent();
|
||||||
static bool compositeAvailable() { return has_composite; }
|
static bool compositeAvailable() { return has_composite; }
|
||||||
|
static bool compositeOverlayAvailable() { return has_composite && has_composite_overlay; }
|
||||||
static bool fixesAvailable() { return has_fixes; }
|
static bool fixesAvailable() { return has_fixes; }
|
||||||
static bool hasShape( Window w );
|
static bool hasShape( Window w );
|
||||||
private:
|
private:
|
||||||
|
@ -156,6 +163,7 @@ class Extensions
|
||||||
static bool has_damage;
|
static bool has_damage;
|
||||||
static int damage_event_base;
|
static int damage_event_base;
|
||||||
static bool has_composite;
|
static bool has_composite;
|
||||||
|
static bool has_composite_overlay;
|
||||||
static bool has_fixes;
|
static bool has_fixes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,9 @@ License. See the file "COPYING" for the exact licensing terms.
|
||||||
#include "group.h"
|
#include "group.h"
|
||||||
#include "rules.h"
|
#include "rules.h"
|
||||||
#include "kwinadaptor.h"
|
#include "kwinadaptor.h"
|
||||||
|
#include "unmanaged.h"
|
||||||
|
#include "scene.h"
|
||||||
|
#include "effects.h"
|
||||||
|
|
||||||
#include <X11/extensions/shape.h>
|
#include <X11/extensions/shape.h>
|
||||||
#include <X11/keysym.h>
|
#include <X11/keysym.h>
|
||||||
|
@ -122,7 +125,9 @@ Workspace::Workspace( bool restore )
|
||||||
topmenu_space( NULL ),
|
topmenu_space( NULL ),
|
||||||
set_active_client_recursion( 0 ),
|
set_active_client_recursion( 0 ),
|
||||||
block_stacking_updates( 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 );
|
new KWinAdaptor( "org.kde.kwin", "/KWin", QDBusConnection::sessionBus(), this );
|
||||||
|
|
||||||
|
@ -166,10 +171,12 @@ Workspace::Workspace( bool restore )
|
||||||
ColormapChangeMask |
|
ColormapChangeMask |
|
||||||
SubstructureRedirectMask |
|
SubstructureRedirectMask |
|
||||||
SubstructureNotifyMask |
|
SubstructureNotifyMask |
|
||||||
FocusChangeMask // for NotifyDetailNone
|
FocusChangeMask | // for NotifyDetailNone
|
||||||
|
ExposureMask
|
||||||
);
|
);
|
||||||
|
|
||||||
Shape::init();
|
Extensions::init();
|
||||||
|
setupCompositing();
|
||||||
|
|
||||||
// compatibility
|
// compatibility
|
||||||
long data = 1;
|
long data = 1;
|
||||||
|
@ -318,6 +325,7 @@ void Workspace::init()
|
||||||
connect(&reconfigureTimer, SIGNAL(timeout()), this,
|
connect(&reconfigureTimer, SIGNAL(timeout()), this,
|
||||||
SLOT(slotReconfigure()));
|
SLOT(slotReconfigure()));
|
||||||
connect( &updateToolWindowsTimer, SIGNAL( timeout()), this, SLOT( slotUpdateToolWindows()));
|
connect( &updateToolWindowsTimer, SIGNAL( timeout()), this, SLOT( slotUpdateToolWindows()));
|
||||||
|
connect( &compositeTimer, SIGNAL( timeout()), SLOT( performCompositing()));
|
||||||
|
|
||||||
connect(KGlobalSettings::self(), SIGNAL(appearanceChanged()), this,
|
connect(KGlobalSettings::self(), SIGNAL(appearanceChanged()), this,
|
||||||
SLOT(slotReconfigure()));
|
SLOT(slotReconfigure()));
|
||||||
|
@ -355,7 +363,11 @@ void Workspace::init()
|
||||||
XWindowAttributes attr;
|
XWindowAttributes attr;
|
||||||
XGetWindowAttributes(display(), wins[i], &attr);
|
XGetWindowAttributes(display(), wins[i], &attr);
|
||||||
if (attr.override_redirect )
|
if (attr.override_redirect )
|
||||||
|
{
|
||||||
|
if( attr.map_state != IsUnmapped && attr.c_class != InputOnly && compositing())
|
||||||
|
createUnmanaged( wins[ i ] );
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if( topmenu_space && topmenu_space->winId() == wins[ i ] )
|
if( topmenu_space && topmenu_space->winId() == wins[ i ] )
|
||||||
continue;
|
continue;
|
||||||
if (attr.map_state != IsUnmapped)
|
if (attr.map_state != IsUnmapped)
|
||||||
|
@ -418,6 +430,7 @@ void Workspace::init()
|
||||||
|
|
||||||
Workspace::~Workspace()
|
Workspace::~Workspace()
|
||||||
{
|
{
|
||||||
|
finishCompositing();
|
||||||
blockStackingUpdates( true );
|
blockStackingUpdates( true );
|
||||||
// TODO grabXServer();
|
// TODO grabXServer();
|
||||||
// use stacking_order, so that kwin --replace keeps stacking order
|
// use stacking_order, so that kwin --replace keeps stacking order
|
||||||
|
@ -429,6 +442,10 @@ Workspace::~Workspace()
|
||||||
(*it)->releaseWindow( true );
|
(*it)->releaseWindow( true );
|
||||||
// no removeClient() is called !
|
// no removeClient() is called !
|
||||||
}
|
}
|
||||||
|
for( UnmanagedList::ConstIterator it = unmanaged.begin();
|
||||||
|
it != unmanaged.end();
|
||||||
|
++it )
|
||||||
|
(*it)->release();
|
||||||
delete desktop_widget;
|
delete desktop_widget;
|
||||||
delete tab_box;
|
delete tab_box;
|
||||||
delete popupinfo;
|
delete popupinfo;
|
||||||
|
@ -472,6 +489,28 @@ Client* Workspace::createClient( Window w, bool is_mapped )
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
addClient( c, Allowed );
|
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;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,6 +553,11 @@ void Workspace::addClient( Client* c, allowed_t )
|
||||||
updateToolWindows( true );
|
updateToolWindows( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Workspace::addUnmanaged( Unmanaged* c, allowed_t )
|
||||||
|
{
|
||||||
|
unmanaged.append( c );
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Destroys the client \a c
|
Destroys the client \a c
|
||||||
*/
|
*/
|
||||||
|
@ -533,6 +577,10 @@ 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 );
|
||||||
|
@ -568,6 +616,16 @@ void Workspace::removeClient( Client* c, allowed_t )
|
||||||
updateClientArea();
|
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 )
|
void Workspace::updateFocusChains( Client* c, FocusChainChange change )
|
||||||
{
|
{
|
||||||
if( !c->wantsTabFocus()) // doesn't want tab focus, remove
|
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 );
|
focus_chain[ i ].prepend( c );
|
||||||
}
|
}
|
||||||
else if( !focus_chain[ i ].contains( c ))
|
else if( !focus_chain[ i ].contains( c ))
|
||||||
{ // add it after the active one
|
focus_chain[ i ].prepend( c ); // otherwise add as the last 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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else //now only on desktop, remove it anywhere else
|
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 );
|
focus_chain[ i ].prepend( c );
|
||||||
}
|
}
|
||||||
else if( !focus_chain[ i ].contains( c ))
|
else if( !focus_chain[ i ].contains( c ))
|
||||||
{ // add it after the active one
|
focus_chain[ i ].prepend( c );
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
focus_chain[ i ].removeAll( c );
|
focus_chain[ i ].removeAll( c );
|
||||||
|
@ -642,13 +688,7 @@ void Workspace::updateFocusChains( Client* c, FocusChainChange change )
|
||||||
global_focus_chain.prepend( c );
|
global_focus_chain.prepend( c );
|
||||||
}
|
}
|
||||||
else if( !global_focus_chain.contains( c ))
|
else if( !global_focus_chain.contains( c ))
|
||||||
{ // add it after the active one
|
global_focus_chain.prepend( c );
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspace::updateCurrentTopMenu()
|
void Workspace::updateCurrentTopMenu()
|
||||||
|
@ -882,7 +922,7 @@ void Workspace::slotSettingsChanged(int category)
|
||||||
/*!
|
/*!
|
||||||
Reread settings
|
Reread settings
|
||||||
*/
|
*/
|
||||||
KWIN_PROCEDURE( CheckBorderSizesProcedure, cl->checkBorderSizes() );
|
KWIN_PROCEDURE( CheckBorderSizesProcedure, Client, cl->checkBorderSizes() );
|
||||||
|
|
||||||
void Workspace::slotReconfigure()
|
void Workspace::slotReconfigure()
|
||||||
{
|
{
|
||||||
|
@ -939,6 +979,11 @@ void Workspace::slotReconfigure()
|
||||||
updateTopMenuGeometry();
|
updateTopMenuGeometry();
|
||||||
updateCurrentTopMenu();
|
updateCurrentTopMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( options->useTranslucency )
|
||||||
|
setupCompositing();
|
||||||
|
else
|
||||||
|
finishCompositing();
|
||||||
|
|
||||||
loadWindowRules();
|
loadWindowRules();
|
||||||
for( ClientList::Iterator it = clients.begin();
|
for( ClientList::Iterator it = clients.begin();
|
||||||
|
@ -1640,7 +1685,7 @@ void Workspace::slotGrabWindow()
|
||||||
QPixmap snapshot = QPixmap::grabWindow( active_client->frameId() );
|
QPixmap snapshot = QPixmap::grabWindow( active_client->frameId() );
|
||||||
|
|
||||||
//No XShape - no work.
|
//No XShape - no work.
|
||||||
if( Shape::available())
|
if( Extensions::shapeAvailable())
|
||||||
{
|
{
|
||||||
//As the first step, get the mask from XShape.
|
//As the first step, get the mask from XShape.
|
||||||
int count, order;
|
int count, order;
|
||||||
|
|
68
workspace.h
68
workspace.h
|
@ -18,6 +18,7 @@ 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 "utils.h"
|
#include "utils.h"
|
||||||
#include "kdecoration.h"
|
#include "kdecoration.h"
|
||||||
|
@ -77,7 +78,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 +88,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;
|
||||||
|
@ -242,6 +246,9 @@ class Workspace : public QObject, public KDecorationDefines
|
||||||
void removeGroup( Group* group, allowed_t );
|
void removeGroup( Group* group, allowed_t );
|
||||||
Group* findClientLeaderGroup( const Client* c ) const;
|
Group* findClientLeaderGroup( const Client* c ) const;
|
||||||
|
|
||||||
|
// only called from Unmanaged::release()
|
||||||
|
void removeUnmanaged( Unmanaged*, 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 +283,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,11 +424,10 @@ class Workspace : public QObject, public KDecorationDefines
|
||||||
void cleanupTemporaryRules();
|
void cleanupTemporaryRules();
|
||||||
void writeWindowRules();
|
void writeWindowRules();
|
||||||
void slotBlockShortcuts(int data);
|
void slotBlockShortcuts(int data);
|
||||||
// kompmgr
|
|
||||||
void setPopupClientOpacity(int v);
|
void setPopupClientOpacity(int v);
|
||||||
void resetClientOpacity();
|
void resetClientOpacity();
|
||||||
void setTransButtonText(int value);
|
void setTransButtonText(int value);
|
||||||
// end
|
void performCompositing();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool keyPressMouseEmulation( XKeyEvent& ev );
|
bool keyPressMouseEmulation( XKeyEvent& ev );
|
||||||
|
@ -458,6 +475,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 );
|
||||||
|
|
||||||
|
@ -499,6 +518,9 @@ class Workspace : public QObject, public KDecorationDefines
|
||||||
void closeActivePopup();
|
void closeActivePopup();
|
||||||
|
|
||||||
void updateClientArea( bool force );
|
void updateClientArea( bool force );
|
||||||
|
|
||||||
|
void setupCompositing();
|
||||||
|
void finishCompositing();
|
||||||
|
|
||||||
SystemTrayWindowList systemTrayWins;
|
SystemTrayWindowList systemTrayWins;
|
||||||
|
|
||||||
|
@ -535,10 +557,11 @@ class Workspace : public QObject, public KDecorationDefines
|
||||||
|
|
||||||
ClientList clients;
|
ClientList clients;
|
||||||
ClientList desktops;
|
ClientList desktops;
|
||||||
|
UnmanagedList unmanaged;
|
||||||
|
|
||||||
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;
|
||||||
|
@ -654,8 +677,10 @@ class Workspace : public QObject, public KDecorationDefines
|
||||||
Window null_focus_window;
|
Window null_focus_window;
|
||||||
bool forced_global_mouse_grab;
|
bool forced_global_mouse_grab;
|
||||||
friend class StackingUpdatesBlocker;
|
friend class StackingUpdatesBlocker;
|
||||||
|
QTimer compositeTimer;
|
||||||
//kompmgr
|
QTime lastCompositePaint;
|
||||||
|
QRegion damage_region;
|
||||||
|
Window overlay; // XComposite overlay window
|
||||||
QSlider *transSlider;
|
QSlider *transSlider;
|
||||||
QPushButton *transButton;
|
QPushButton *transButton;
|
||||||
};
|
};
|
||||||
|
@ -800,6 +825,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 )
|
||||||
{
|
{
|
||||||
|
@ -827,7 +857,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 ));
|
||||||
|
|
Loading…
Reference in a new issue