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 ! - 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

View file

@ -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
//**************************************** //****************************************

View file

@ -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
} }

View file

@ -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 )

View file

@ -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;

View file

@ -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 );

View file

@ -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;
}; };

View file

@ -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;

View file

@ -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 ));