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
|
||||
! - 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
|
||||
|
|
|
@ -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
|
||||
//****************************************
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
111
scene_opengl.cpp
111
scene_opengl.cpp
|
@ -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 )
|
||||
|
|
|
@ -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;
|
||||
|
|
17
utils.cpp
17
utils.cpp
|
@ -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 );
|
||||
|
|
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 <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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
@ -939,6 +979,11 @@ void Workspace::slotReconfigure()
|
|||
updateTopMenuGeometry();
|
||||
updateCurrentTopMenu();
|
||||
}
|
||||
|
||||
if( options->useTranslucency )
|
||||
setupCompositing();
|
||||
else
|
||||
finishCompositing();
|
||||
|
||||
loadWindowRules();
|
||||
for( ClientList::Iterator it = clients.begin();
|
||||
|
@ -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;
|
||||
|
|
68
workspace.h
68
workspace.h
|
@ -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"
|
||||
|
@ -77,7 +78,7 @@ class Workspace : public QObject, public KDecorationDefines
|
|||
virtual ~Workspace();
|
||||
|
||||
static Workspace * self() { return _self; }
|
||||
|
||||
|
||||
bool workspaceEvent( XEvent * );
|
||||
|
||||
KDecoration* createDecoration( KDecorationBridge* bridge );
|
||||
|
@ -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?
|
||||
|
@ -276,6 +283,17 @@ class Workspace : public QObject, public KDecorationDefines
|
|||
void requestDelayFocus( Client* );
|
||||
|
||||
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();
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -499,6 +518,9 @@ class Workspace : public QObject, public KDecorationDefines
|
|||
void closeActivePopup();
|
||||
|
||||
void updateClientArea( bool force );
|
||||
|
||||
void setupCompositing();
|
||||
void finishCompositing();
|
||||
|
||||
SystemTrayWindowList systemTrayWins;
|
||||
|
||||
|
@ -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 ));
|
||||
|
|
Loading…
Reference in a new issue