Document the compositing framework and the scene backends,

describe the design, add links to external docs.
Restructure COMPOSITE_TODO into sections and add sort of priorities.


svn path=/branches/work/kwin_composite/; revision=600163
This commit is contained in:
Luboš Luňák 2006-10-29 19:23:45 +00:00
parent 5f03c77514
commit d92d3a8165
11 changed files with 545 additions and 156 deletions

View file

@ -1,93 +1,99 @@
* = not done
This file lists TODO items for the compositing code.
See file HACKING for details on developing KWin.
See effects/howto.* for a HOWTO on writting effects.
See documentation in source (mainly in scene.cpp) for description
of the design of the compositing framework.
TODO
=================================
* = not done, will be either done by me, or should be at least discussed first with me
+ = not done, I don't plan on doing it that soon
- in other words, these should be the best ones for you if you want to help
! = like +, but they should be relatively simple
- in other words, these should be the best if you want to get started with the code
/ = work in progress
? = should it be done?
See the HACKING file for KWin details. The composite-related sources are mostly
composite.cpp and scene_opengl.cpp (TODO: add comments and general overview).
Sources:
General TODO
=================================
- glcompmgr : http://lists.freedesktop.org/archives/xorg/2006-July/017006.html ,
http://www.mail-archive.com/compiz%40lists.freedesktop.org/msg00023.html
- simple and easy to understand
- works even without texture_from_pixmap extension
- claims to support several different gfx cards
- compiz : git clone git://anongit.freedesktop.org/git/xorg/app/compiz
- the ultimate <whatever>
- glxcompmgr : git clone git://anongit.freedesktop.org/git/xorg/app/glxcompgr
- a rather old version of compiz, but also simpler and as such simpler
to understand
- libcm (metacity) : cvs -d :pserver:anonymous@anoncvs.gnome.org:/cvs/gnome co libcm
- no idea about it
- http://opengl.org - documentation - OpenGL Redbook, GLX docs, extensions docs
TODO:
* Check/make it work with other gfx cards
- I've tested only with nvidia with the 9625 beta drivers and 8776 stable drivers so far
- I have absolutely no idea about other gfx cards, needs to be tested
* ati
* intel
* who knows what else
? Xgl support
- Compiz itself doesn't work when compiled with the libGL from nvidia,
it ships its own and links against it
? might be worth trying to use that libGL as well
- it may be just because of the special libGL, but when testing with Xgl
it even seemed non-conformant - none of the provided configs had
GLX_RENDER_TYPE with GLX_RGBA_BIT even though required by GLX
and other funny things. Indeed, it may be just me being still pretty
clueless about these things.
* is there a good reason to support Xgl? With the 9625 nvidia drivers
it seems to work fine without them
? AIGLX support
- no idea about this at all
* find out if it works
* XComposite overlay window
! 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
- I still run older X.Org here
- 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
! - 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
* when relying on extensions, detect that they are available
- some of the glcompmgr code probably depends on OpenGL/GLX extensions that may
not be always available, probably the same with compiz
* find out which code relies on extensions and add checks
- should be only needed for OpenGL code, I think this doesn't matter for XRender
? alpha clear hack
* find out if it affects performance
* if yes, try to find a better way of solving the problem
- since kompmgr has an option to make only the decoration transparent,
+ - find out if it affects performance
+ - if yes, try to find a better way of solving the problem
! - since kompmgr has an option to make only the decoration transparent,
it should be possible to do the same here - if the window has alpha and a decoration
or if there should be only the decoration transparent, paint first the contents
and then the decoration - this should make it possible to paint the decoration
without the random alpha that is right now handled by the alpha hack
/ design framework for graphical effects
- modelling it after compiz seems to make a lot of sense
* don't add workspace damage in Toplevel::addDamage()
- instead add damage of windows to the screen only before doing the painting
- this should prevent repaints because of changing obscured windows
* update only those parts of the screen that have been changed
- for paintSimpleScreen() - it currently sets region to the whole screen
* instead of using glXSwapBuffers() there should be glCopyPixels() used
- compiz has such code in evenLoop() in the if() block for COMP_SCREEN_DAMAGE_REGION_MASK
* perhaps syncing to vblank will be needed to avoid flicker
* XCopyArea() should not update the whole screen but only the affected areas
* wait for decoration repaints
- it is sometimes visible that the window contents are painted first and the decoration
only afterwards with a small delay
- maybe posted paint events need to be processed immediatelly, or maybe the compositing
code should not update the window until the decoration is finished painting
* sync to vblank
* handle XRandr changes
- output buffers and similar probably need recreating when the screen size changes
OpenGL TODO
=================================
+ Check/make it work with other gfx cards
- I've tested only with nvidia with the 9625 beta drivers and 8776 stable drivers so far
- I have absolutely no idea about other gfx cards, needs to be tested
+ - ati
+ - intel
+ - who knows what else
? Xgl support
- Compiz itself doesn't work when compiled with the libGL from nvidia,
it ships its own and links against it
? - might be worth trying to use that libGL as well
- it may be just because of the special libGL, but when testing with Xgl
it even seemed non-conformant - none of the provided configs had
GLX_RENDER_TYPE with GLX_RGBA_BIT even though required by GLX
and other funny things. Indeed, it may be just me being still pretty
clueless about these things.
? - is there a good reason to support Xgl? With the 9625 nvidia drivers
it seems to work fine without them and there's AIGLX
? AIGLX support
- no idea about this at all
+ - find out if it works
! when relying on extensions, detect that they are available
- some of the glcompmgr code probably depends on OpenGL/GLX extensions that may
not be always available, probably the same with compiz
! - find out which code relies on extensions and add checks
! - it seems that some systems (using older X.org?) will need local versions
of some #defines like GLX_TEXTURE_FORMAT_EXT
- Beryl has this code in beryl.h
+ sync to vblank
- currently the compositing code is run with 20ms timer, i.e. constant 50fps
- the GLX_SGI_video_sync extension should be used
- compiz uses this, no idea about it though
? GL_ARB_texture_rectangle vs GL_ARB_texture_non_power_of_two
+ GL_ARB_texture_rectangle vs GL_ARB_texture_non_power_of_two
- code currently uses GL_ARB_texture_rectangle (GL_TEXTURE_RECTANGLE_ARB), using
normal textures when GL_ARB_texture_non_power_of_two is available should(?) be
preferred
@ -95,26 +101,98 @@ TODO:
? in SceneOpenGL::bindTexture() with tfp_mode, with some gfx cards it seems
to be faster to not short-circuit the texture binding when there's been
no damage
* confirm and try to find out when to do it and when not
+ - confirm and try to find out when to do it and when not
* SceneXrender::Window::performPaint() doesn't use xScale/yScale
! update only those parts of the screen that have been changed
- for paintSimpleScreen() - it currently sets region to the whole screen
! - instead of using glXSwapBuffers() there should be glCopyPixels() used
- compiz has such code in evenLoop() in the if() block for COMP_SCREEN_DAMAGE_REGION_MASK
+ - perhaps syncing to vblank will be needed to avoid flicker
! - XCopyArea() should not update the whole screen but only the affected areas
XRender TODO
==============================
+ SceneXrender::Window::performPaint() doesn't use xScale/yScale
- XRenderSetPictureTransform() should be capable of doing this
- note that the matrix used seems to be weird (it doesn't act like the normal transformation
matrix as far as I can tell)
Effects framework TODO
==============================
/ design framework for graphical effects
- modelling it after compiz seems to make a lot of sense
* solve somehow disappearing windows
- i.e. when a window is e.g. closed, the Client/Unmanaged object is destroyed, but animations
should be going on
? maybe animations could be done actually before the state change, it makes sense to destroy
? - maybe animations could be done actually before the state change, it makes sense to destroy
the window only after it's finished exploding or really minimizing the window only after
the animation of minimizing to the taskbar is done, however this looks very hairy
and error-prone
? maybe the animation effects should keep the necessary info themselves, so that the object
? - maybe the animation effects should keep the necessary info themselves, so that the object
can be destroyed
- the problem here may be what to do when the window again reappears, a new object will
be created, but the old animation should be stopped - compare window id's?
? maybe just keep the object around in a special list
- another problem is that then the window won't exist at all in the scene functions,
so e.g. no paintWindow() will be called for it
? - maybe just keep the object around in a special list
* don't add workspace damage in Toplevel::addDamage()
- instead add damage of windows to the screen only before doing the painting
- this should prevent repaints because of obscured windows
* more notification functions for effects are needed
- currently there are only very few notification functions (windowAdded, windowActivated,...)
! - virtual desktop change
! - window state changes
? more
* shadows
* support for effects involving more virtual desktops
- currently effects are limited to only the active virtual desktop
* support for grabbing input
- during some more complicated effects, input (at least mouse) should be disabled,
because currently there is no way to do input redirection
Effects TODO
===============================
+ adapt the kcontrol module used by Kompmgr
- in kcmkwin/kwinoptions
! - uses ~/.xcompmgr, convert to use normal KConfig
? - I don't think these effects should be plugins or anything like that,
probably simply write to kwinrc and use the Option class in KWin
+ implements all effects Kompmgr could do
+ - all effects from the Opacity tab should be already doable
! - applying translucency only to the decoration
- use clientSize() and clientPos() from Client
- see also the alpha clear hack todo entry
! - not usign ARGB visuals
- just clear the alpha channel in the alpha clear hack
- or do it while painting (see also the alpha clear hack todo entry)
! - the rest - should be simple
* - shadows
- framework is not ready for them yet (see the todo entry)
+ - tab Effects
! - fade-in should be simple
+ - fade between changes
- will need notification about opacity changes
- not sure if this is doable for other opacity changes then the ones
initiated by the user or by the application
* - fade-out needs framework for disappearing windows (see the todo entry)
+ minimize/shade effects
- to replace the ones from KWin core
- Client::animateMinimizeOrUnminimize()
- Client::setShade()
+ zoom effect
- enlarge a portion of the screen
! - would require adding xScale/yScale to ScreenPaintData
- should be doable even for XRender
? other effects

View file

@ -8,6 +8,23 @@ You can Freely distribute this program under the GNU General Public
License. See the file "COPYING" for the exact licensing terms.
******************************************************************/
/*
Code related to compositing (redirecting windows to pixmaps and tracking
window damage).
Docs:
XComposite (the protocol, but the function calls map to it):
http://gitweb.freedesktop.org/?p=xorg/proto/compositeproto.git;a=blob;hb=HEAD;f=protocol
XDamage (again the protocol):
http://gitweb.freedesktop.org/?p=xorg/proto/damageproto.git;a=blob;hb=HEAD;f=protocol
Composite HOWTO from Fredrik:
http://ktown.kde.org/~fredrik/composite_howto.html
*/
#include "utils.h"
#include "workspace.h"
#include "client.h"
@ -125,7 +142,7 @@ void Workspace::addDamageFull()
damage_region = QRegion( 0, 0, displayWidth(), displayHeight());
}
void Workspace::compositeTimeout()
void Workspace::performCompositing()
{
// The event loop apparently tries to fire a QTimer as often as possible, even
// at the expense of not processing many X events. This means that the composite
@ -139,6 +156,8 @@ void Workspace::compositeTimeout()
scene->idle();
return;
}
// create a list of all windows in the stacking order
// TODO keep this list like now a stacking order of Client window is kept
ToplevelList windows;
Window* children;
unsigned int children_count;
@ -156,11 +175,13 @@ void Workspace::compositeTimeout()
else if( Unmanaged* c = findUnmanaged( HandleMatchPredicate( children[ i ] )))
windows.append( c );
}
scene->prePaint();
scene->initPaint();
scene->paint( damage_region, windows );
// clear all damage
damage_region = QRegion();
foreach( Toplevel* c, windows )
c->resetDamage();
// run post-pass only after clearing the damage
scene->postPaint();
lastCompositePaint.start();
}

110
scene.cpp
View file

@ -8,6 +8,65 @@ You can Freely distribute this program under the GNU General Public
License. See the file "COPYING" for the exact licensing terms.
******************************************************************/
/*
(NOTE: The compositing code is work in progress. As such this design
documentation may get outdated in some areas.)
The base class for compositing, implementing shared functionality
between the OpenGL and XRender backends.
Design:
When compositing is turned on, XComposite extension is used to redirect
drawing of windows to pixmaps and XDamage extension is used to get informed
about damage (changes) to window contents. This code is mostly in composite.cpp .
Workspace::performCompositing() starts one painting pass. Painting is done
by painting the screen, which in turn paints every window. Painting can be affected
using effects, which are chained. E.g. painting a screen means that actually
paintScreen() of the first effect is called, which possibly does modifications
and calls next effect's paintScreen() and so on, until Scene::finalPaintScreen()
is called.
There are 3 phases of every paint (not necessarily done together):
The pre-paint phase, the paint phase and the post-paint phase.
The pre-paint phase is used to find out about how the painting will be actually
done (i.e. what the effects will do). For example when only a part of the screen
needs to be updated and no effect will do any transformation it is possible to use
an optimized paint function. How the painting will be done is controlled
by the mask argument, see PAINT_WINDOW_* and PAINT_SCREEN_* flags in scene.h .
For example an effect that decides to paint a normal windows as translucent
will need to modify the mask in its prePaintWindow() to include
the PAINT_WINDOW_TRANSLUCENT flag. The paintWindow() function will then get
the mask with this flag turned on and will also paint using transparency.
The paint pass does the actual painting, based on the information collected
using the pre-paint pass. After running through the effects' paintScreen()
either paintGenericScreen() or optimized paintSimpleScreen() are called.
Those call paintWindow() on windows (not necessarily all), possibly using
clipping to optimize performance and calling paintWindow() first with only
PAINT_WINDOW_OPAQUE to paint the opaque parts and then later
with PAINT_WINDOW_TRANSLUCENT to paint the transparent parts. Function
paintWindow() again goes through effects' paintWindow() until
finalPaintWindow() is called, which calls the window's performPaint() to
do the actual painting.
The post-paint can be used for cleanups and is also used for scheduling
repaints during the next painting pass for animations. Effects wanting to
repaint certain parts can manually damage them during post-paint and repaint
of these parts will be done during the next paint pass.
Various notes:
- When the screen or a window are transformed (*_TRANSFORMED flag), clipping
and similar optimizations are not done (too complicated), so in such cases
infiniteRegion() should be always used. Make sure not to make any transformations
of such regions.
*/
#include "scene.h"
#include <X11/extensions/shape.h>
@ -33,7 +92,7 @@ Scene::~Scene()
{
}
void Scene::prePaint()
void Scene::initPaint()
{
effects->startPaint();
// do the rest of prepaint pass together with paint pass
@ -47,43 +106,48 @@ void Scene::paintScreen( int* mask, QRegion* region )
updateTimeDiff();
// preparation step
effects->prePaintScreen( mask, region, time_diff );
// optimized painting is not possible with transformations
if( *mask & ( PAINT_SCREEN_TRANSFORMED | PAINT_WINDOW_TRANSFORMED ))
*mask &= ~PAINT_SCREEN_REGION;
// TODO call also prePaintWindow() for all windows
ScreenPaintData data;
effects->paintScreen( *mask, *region, data );
}
// Compute time since the last painting pass.
void Scene::updateTimeDiff()
{
if( last_time.isNull())
{
// has been idle for some time, time_diff would be huge
// Painting has been idle (optimized out) for some time,
// which means time_diff would be huge and would break animations.
// Simply set it to zero.
time_diff = 0;
}
else
time_diff = last_time.elapsed();
if( time_diff < 0 )
if( time_diff < 0 ) // check time rollback
time_diff = 0;
last_time.start();;
}
// Painting pass is optimized away.
void Scene::idle()
{
// Don't break time since last paint for the next pass.
last_time = QTime();
}
// the function that'll be eventually called by paintScreen() above
void Scene::finalPaintScreen( int mask, QRegion region, ScreenPaintData& data )
{
if( mask & PAINT_SCREEN_REGION )
if( mask & PAINT_SCREEN_REGION ) // can do optimized case?
paintSimpleScreen( mask, region );
else
paintGenericScreen( mask, data );
}
// the generic painting code that should eventually handle even
// transformations
// The generic painting code that can handle even transformations.
// It simply paints bottom-to-top.
void Scene::paintGenericScreen( int orig_mask, ScreenPaintData )
{
paintBackground( infiniteRegion());
@ -99,9 +163,13 @@ void Scene::paintGenericScreen( int orig_mask, ScreenPaintData )
}
}
// the optimized case without any transformations at all
// The optimized case without any transformations at all.
// It can paint only the requested region and can use clipping
// to reduce painting and improve performance.
void Scene::paintSimpleScreen( int orig_mask, QRegion region )
{
// TODO PAINT_WINDOW_* flags don't belong here, that's why it's in the assert,
// perhaps the two enums should be separated
assert(( orig_mask & ( PAINT_WINDOW_TRANSFORMED | PAINT_SCREEN_TRANSFORMED
| PAINT_WINDOW_TRANSLUCENT | PAINT_WINDOW_OPAQUE )) == 0 );
QList< Phase2Data > phase2;
@ -120,12 +188,15 @@ void Scene::paintSimpleScreen( int orig_mask, QRegion region )
QRegion damage = region;
// preparation step
effects->prePaintWindow( w, &mask, &damage, time_diff );
// If the window is transparent, the transparent part will be done
// in the 2nd pass.
if( mask & PAINT_WINDOW_TRANSLUCENT )
phase2.prepend( Phase2Data( w, region, mask ));
if( mask & PAINT_WINDOW_OPAQUE )
{
paintWindow( w, mask, region );
if( ( mask & PAINT_WINDOW_TRANSLUCENT ) == 0 ) // window is not transparent, can clip windows below
// If the window is not transparent at all, it can clip windows below.
if( ( mask & PAINT_WINDOW_TRANSLUCENT ) == 0 )
region -= w->shape().translated( w->x(), w->y());
}
}
@ -159,25 +230,10 @@ void Scene::postPaint()
effects->postPaintScreen();
foreach( Window* w, stacking_order )
effects->postPaintWindow( w );
// do cleanup
stacking_order.clear();
}
void Scene::windowGeometryShapeChanged( Toplevel* )
{
}
void Scene::windowOpacityChanged( Toplevel* )
{
}
void Scene::windowAdded( Toplevel* )
{
}
void Scene::windowDeleted( Toplevel* )
{
}
//****************************************
// Scene::Window
//****************************************
@ -198,9 +254,13 @@ void Scene::Window::free()
void Scene::Window::discardShape()
{
// it is created on-demand and cached, simply
// reset the flag
shape_valid = false;
}
// Find out the shape of the window using the XShape extension
// or if not shape is set then simply it's the window geometry.
QRegion Scene::Window::shape() const
{
if( !shape_valid )

54
scene.h
View file

@ -23,45 +23,73 @@ class Workspace;
class WindowPaintData;
class ScreenPaintData;
// The base class for compositing backends.
class Scene
{
public:
Scene( Workspace* ws );
virtual ~Scene() = 0;
class Window;
virtual void prePaint();
// repaints the given screen areas, windows provides the stacking order
// Called before calling paint() to perform initialization (does not
// do the prepaint pass though)
virtual void initPaint();
// Repaints the given screen areas, windows provides the stacking order.
// The entry point for the main part of the painting pass.
virtual void paint( QRegion damage, ToplevelList windows ) = 0;
// Called to perform post paint cleanup and for animations to prepare
// for next pass.
virtual void postPaint();
// Notification function - KWin core informs about changes.
// Used to mainly discard cached data.
// shape/size of a window changed
virtual void windowGeometryShapeChanged( Toplevel* );
virtual void windowGeometryShapeChanged( Toplevel* ) = 0;
// opacity of a window changed
virtual void windowOpacityChanged( Toplevel* );
virtual void windowOpacityChanged( Toplevel* ) = 0;
// a new window has been created
virtual void windowAdded( Toplevel* );
virtual void windowAdded( Toplevel* ) = 0;
// a window has been destroyed
virtual void windowDeleted( Toplevel* );
virtual void windowDeleted( Toplevel* ) = 0;
// Flags controlling how painting is done.
enum
{
// Window (or at least part of it) will be painted opaque.
PAINT_WINDOW_OPAQUE = 1 << 0,
// Window (or at least part of it) will be painted translucent.
PAINT_WINDOW_TRANSLUCENT = 1 << 1,
// Window will be painted with transformed geometry.
PAINT_WINDOW_TRANSFORMED = 1 << 2,
// Paint only a region of the screen (can be optimized, cannot
// be used together with TRANSFORMED flags).
PAINT_SCREEN_REGION = 1 << 3,
// Whole screen will be painted with transformed geometry.
PAINT_SCREEN_TRANSFORMED = 1 << 4
};
// there's nothing to paint (adjust time_diff later)
void idle();
protected:
// shared implementation, starts painting the screen
void paintScreen( int* mask, QRegion* region );
friend class EffectsHandler;
// called after all effects had their paintScreen() called
void finalPaintScreen( int mask, QRegion region, ScreenPaintData& data );
// shared implementation of painting the screen in the generic
// (unoptimized) way
virtual void paintGenericScreen( int mask, ScreenPaintData data );
// shared implementation of painting the screen in an optimized way
virtual void paintSimpleScreen( int mask, QRegion region );
// paint the background (not the desktop background - the whole background)
virtual void paintBackground( QRegion region ) = 0;
// called after all effects had their paintWindow() called
void finalPaintWindow( Window* w, int mask, QRegion region, WindowPaintData& data );
// shared implementation, starts painting the window
virtual void paintWindow( Window* w, int mask, QRegion region );
// infinite region, i.e. everything
static QRegion infiniteRegion();
// compute time since the last repaint
void updateTimeDiff();
// saved data for 2nd pass of optimized screen painting
struct Phase2Data
{
Phase2Data( Window* w, QRegion r, int m ) : window( w ), region( r ), mask( m ) {}
@ -69,26 +97,36 @@ class Scene
QRegion region;
int mask;
};
// windows in their stacking order
QVector< Window* > stacking_order;
// time since last repaint
int time_diff;
QTime last_time;
Workspace* wspace;
};
// The base class for windows representations in composite backends
class Scene::Window
{
public:
Window( Toplevel* c );
virtual ~Window();
virtual void free(); // is often copied by value, use manually instead of dtor
// this class is often copied by value, use manually instead of dtor
virtual void free();
// perform the actual painting of the window
virtual void performPaint( int mask, QRegion region, WindowPaintData data ) = 0;
int x() const;
int y() const;
int width() const;
int height() const;
// access to the internal window class
// TODO eventually get rid of this
Toplevel* window();
// is the window visible at all
bool isVisible() const;
// is the window fully opaque
bool isOpaque() const;
// shape of the window
QRegion shape() const;
void discardShape();
Window() {} // QMap sucks even in Qt4
@ -103,7 +141,7 @@ extern Scene* scene;
inline
QRegion Scene::infiniteRegion()
{ // INT_MIN / 2 because it's width/height (INT_MIN+INT_MAX==-1)
{ // INT_MIN / 2 because width/height is used (INT_MIN+INT_MAX==-1)
return QRegion( INT_MIN / 2, INT_MIN / 2, INT_MAX, INT_MAX );
}

View file

@ -8,6 +8,13 @@ You can Freely distribute this program under the GNU General Public
License. See the file "COPYING" for the exact licensing terms.
******************************************************************/
/*
This is very simple compositing code using only plain X. It doesn't use any effects
or anything like that, it merely draws everything as it would be visible without
compositing. It was the first compositing code in KWin and is usable only for testing
and as the very simple "this is how it works".
*/
#include "scene_basic.h"
#include "utils.h"
@ -16,10 +23,6 @@ License. See the file "COPYING" for the exact licensing terms.
namespace KWinInternal
{
//****************************************
// SceneBasic
//****************************************
SceneBasic::SceneBasic( Workspace* ws )
: Scene( ws )
{
@ -56,9 +59,27 @@ void SceneBasic::paint( QRegion, ToplevelList windows )
XFlush( display());
}
// These functions are not used at all, SceneBasic
// is not using inherited functionality.
void SceneBasic::paintBackground( QRegion )
{
// empty, not using inherited functionality
}
void SceneBasic::windowGeometryShapeChanged( Toplevel* )
{
}
void SceneBasic::windowOpacityChanged( Toplevel* )
{
}
void SceneBasic::windowAdded( Toplevel* )
{
}
void SceneBasic::windowDeleted( Toplevel* )
{
}
} // namespace

View file

@ -25,6 +25,10 @@ class SceneBasic
virtual void paint( QRegion damage, ToplevelList windows );
protected:
virtual void paintBackground( QRegion region );
virtual void windowGeometryShapeChanged( Toplevel* );
virtual void windowOpacityChanged( Toplevel* );
virtual void windowAdded( Toplevel* );
virtual void windowDeleted( Toplevel* );
};
} // namespace

View file

@ -8,8 +8,49 @@ You can Freely distribute this program under the GNU General Public
License. See the file "COPYING" for the exact licensing terms.
Based on glcompmgr code by Felix Bellaby.
Using code from Compiz and Beryl.
******************************************************************/
/*
This is the OpenGL-based compositing code. It is the primary and most powerful
compositing backend.
Sources and other compositing managers:
=======================================
- http://opengl.org
- documentation
- OpenGL Redbook
- GLX docs
- extensions docs
- glcompmgr
- http://lists.freedesktop.org/archives/xorg/2006-July/017006.html ,
- http://www.mail-archive.com/compiz%40lists.freedesktop.org/msg00023.html
- simple and easy to understand
- works even without texture_from_pixmap extension
- claims to support several different gfx cards
- compiz
- git clone git://anongit.freedesktop.org/git/xorg/app/compiz
- the ultimate <whatever>
- glxcompmgr
- git clone git://anongit.freedesktop.org/git/xorg/app/glxcompgr
- a rather old version of compiz, but also simpler and as such simpler
to understand
- beryl
- the community fork of Compiz
- http://beryl-project.org
- svn co svn://metascape.afraid.org/svnroot/beryl
- libcm (metacity)
- cvs -d :pserver:anonymous@anoncvs.gnome.org:/cvs/gnome co libcm
- not much idea about it, the model differs a lot from KWin/Compiz/Beryl
- does not seem to be very powerful or with that much development going on
*/
#include "scene_opengl.h"
#include "utils.h"
@ -25,22 +66,39 @@ namespace KWinInternal
// SceneOpenGL
//****************************************
// the config used for windows
GLXFBConfig SceneOpenGL::fbcdrawable;
// GLX content
GLXContext SceneOpenGL::context;
GLXPixmap SceneOpenGL::glxroot;
// the destination drawable where the compositing is done
GLXDrawable SceneOpenGL::glxroot;
bool SceneOpenGL::tfp_mode; // using glXBindTexImageEXT (texture_from_pixmap)
bool SceneOpenGL::root_db; // destination drawable is double-buffered
bool SceneOpenGL::copy_buffer_hack; // workaround for nvidia < 1.0-9xxx drivers
// finding of OpenGL extensions functions
typedef void (*glXFuncPtr)();
typedef glXFuncPtr (*glXGetProcAddress_func)( const GLubyte* );
static glXFuncPtr getProcAddress( const char* name )
{
glXFuncPtr ret = NULL;
if( glXGetProcAddress != NULL )
ret = glXGetProcAddress( ( const GLubyte* ) name );
if( ret == NULL )
ret = ( glXFuncPtr ) dlsym( RTLD_DEFAULT, name );
return ret;
}
// texture_from_pixmap extension functions
typedef void (*glXBindTexImageEXT_func)( Display* dpy, GLXDrawable drawable,
int buffer, const int* attrib_list );
typedef void (*glXReleaseTexImageEXT_func)( Display* dpy, GLXDrawable drawable, int buffer );
typedef void (*glXFuncPtr)();
typedef glXFuncPtr (*glXGetProcAddress_func)( const GLubyte* );
glXBindTexImageEXT_func glXBindTexImageEXT;
glXReleaseTexImageEXT_func glXReleaseTexImageEXT;
glXGetProcAddress_func glXGetProcAddress;
glXBindTexImageEXT_func glXBindTexImageEXT;
// detect OpenGL error (add to various places in code to pinpoint the place)
static void checkGLError( const char* txt )
{
GLenum err = glGetError();
@ -48,6 +106,7 @@ static void checkGLError( const char* txt )
kWarning() << "GL error (" << txt << "): 0x" << QString::number( err, 16 ) << endl;
}
// attributes for finding a double-buffered root window config
const int root_db_attrs[] =
{
GLX_DOUBLEBUFFER, True,
@ -60,6 +119,7 @@ const int root_db_attrs[] =
None
};
// attributes for finding a non-double-buffered root window config
static const int root_buffer_attrs[] =
{
GLX_DOUBLEBUFFER, False,
@ -72,6 +132,7 @@ static const int root_buffer_attrs[] =
None
};
// attributes for finding config for windows
const int drawable_attrs[] =
{
GLX_DOUBLEBUFFER, False,
@ -85,6 +146,7 @@ const int drawable_attrs[] =
None
};
// attributes for finding config for windows when using tfp
const int drawable_tfp_attrs[] =
{
GLX_DOUBLEBUFFER, False,
@ -99,16 +161,6 @@ const int drawable_tfp_attrs[] =
None
};
static glXFuncPtr getProcAddress( const char* name )
{
glXFuncPtr ret = NULL;
if( glXGetProcAddress != NULL )
ret = glXGetProcAddress( ( const GLubyte* ) name );
if( ret == NULL )
ret = ( glXFuncPtr ) dlsym( RTLD_DEFAULT, name );
return ret;
}
SceneOpenGL::SceneOpenGL( Workspace* ws )
: Scene( ws )
{
@ -116,6 +168,7 @@ SceneOpenGL::SceneOpenGL( Workspace* ws )
int dummy;
if( !glXQueryExtension( display(), &dummy, &dummy ))
return;
// handle OpenGL extensions functions
glXGetProcAddress = (glXGetProcAddress_func) getProcAddress( "glxGetProcAddress" );
if( glXGetProcAddress == NULL )
glXGetProcAddress = (glXGetProcAddress_func) getProcAddress( "glxGetProcAddressARB" );
@ -125,7 +178,7 @@ SceneOpenGL::SceneOpenGL( Workspace* ws )
// use copy buffer hack from glcompmgr (called COPY_BUFFER there) - nvidia drivers older than
// 1.0-9xxx don't update pixmaps properly, so do a copy first
copy_buffer_hack = !tfp_mode; // TODO detect that it's nvidia < 1.0-9xxx driver
initBuffer();
initBuffer(); // create destination buffer
if( tfp_mode )
{
if( !findConfig( drawable_tfp_attrs, fbcdrawable ))
@ -140,6 +193,7 @@ SceneOpenGL::SceneOpenGL( Workspace* ws )
assert( false );
context = glXCreateNewContext( display(), fbcroot, GLX_RGBA_TYPE, NULL, GL_FALSE );
glXMakeContextCurrent( display(), glxroot, glxroot, context );
// OpenGL scene setup
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( 0, displayWidth(), 0, displayHeight(), 0, 65535 );
@ -167,6 +221,7 @@ SceneOpenGL::~SceneOpenGL()
checkGLError( "Cleanup" );
}
// create destination buffer
void SceneOpenGL::initBuffer()
{
XWindowAttributes attrs;
@ -182,12 +237,14 @@ void SceneOpenGL::initBuffer()
}
if( root_db )
{
// root window is double-buffered, paint directly to it
buffer = rootWindow();
glxroot = glXCreateWindow( display(), fbcroot, buffer, NULL );
glDrawBuffer( GL_BACK );
}
else
{
// no double-buffered root, paint to a buffer and copy to root window
XGCValues gcattr;
gcattr.subwindow_mode = IncludeInferiors;
gcroot = XCreateGC( display(), rootWindow(), GCSubwindowMode, &gcattr );
@ -197,6 +254,7 @@ void SceneOpenGL::initBuffer()
}
}
// print info about found configs
static void debugFBConfig( GLXFBConfig* fbconfigs, int i, const int* attrs )
{
int pos = 0;
@ -214,6 +272,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 )
{
int cnt;
@ -263,6 +322,7 @@ bool SceneOpenGL::findConfig( const int* attrs, GLXFBConfig& config, VisualID vi
return false;
}
// the entry function for painting
void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels )
{
foreach( Toplevel* c, toplevels )
@ -275,10 +335,13 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels )
glPushMatrix();
glClearColor( 0, 0, 0, 1 );
glClear( GL_COLOR_BUFFER_BIT );
// OpenGL has (0,0) in the bottom-left corner while X has it in the top-left corner,
// which is annoying and confusing. Therefore flip the whole OpenGL scene upside down
// and move it up, so that it actually uses the same coordinate system like X.
glScalef( 1, -1, 1 );
glTranslatef( 0, -displayHeight(), 0 );
int mask = 0;
paintScreen( &mask, &damage );
paintScreen( &mask, &damage ); // call generic implementation
glPopMatrix();
// TODO only partial repaint for mask & PAINT_SCREEN_REGION
if( root_db )
@ -296,7 +359,7 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels )
void SceneOpenGL::paintGenericScreen( int mask, ScreenPaintData data )
{
if( mask & PAINT_SCREEN_TRANSFORMED )
{
{ // apply screen transformations
glPushMatrix();
glTranslatef( data.xTranslate, data.yTranslate, 0 );
}
@ -309,6 +372,7 @@ void SceneOpenGL::paintGenericScreen( int mask, ScreenPaintData data )
void SceneOpenGL::paintSimpleScreen( int mask, QRegion region )
{
// TODO repaint only damaged areas (means also don't do glXSwapBuffers and similar)
// For now always force redrawing of the whole area.
region = QRegion( 0, 0, displayWidth(), displayHeight());
Scene::paintSimpleScreen( mask, region );
}
@ -376,16 +440,17 @@ void SceneOpenGL::Window::free()
discardTexture();
}
// Bind the window pixmap to an OpenGL texture.
void SceneOpenGL::Window::bindTexture()
{
if( texture != 0 && toplevel->damage().isEmpty()
&& !tfp_mode ) // interestingly this makes tfp slower
&& !tfp_mode ) // TODO interestingly this makes tfp slower with some gfx cards
{
// texture doesn't need updating, just bind it
glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texture );
return;
}
// TODO cache pixmaps here if possible
// Get the pixmap with the window contents
Pixmap window_pix = toplevel->createWindowPixmap();
Pixmap pix = window_pix;
// HACK
@ -425,11 +490,11 @@ void SceneOpenGL::Window::bindTexture()
glXWaitX();
}
if( tfp_mode )
{
{ // tfp mode, simply bind the pixmap to texture
if( texture == None )
glGenTextures( 1, &texture );
if( bound_pixmap != None )
{
{ // release old if needed
glXReleaseTexImageEXT( display(), bound_glxpixmap, GLX_FRONT_LEFT_EXT );
glXDestroyGLXPixmap( display(), bound_glxpixmap );
XFreePixmap( display(), bound_pixmap );
@ -448,7 +513,7 @@ void SceneOpenGL::Window::bindTexture()
glXBindTexImageEXT( display(), bound_glxpixmap, GLX_FRONT_LEFT_EXT, NULL );
}
else
{
{ // non-tfp case, copy pixmap contents to a texture
GLXDrawable pixmap = glXCreatePixmap( display(), fbcdrawable, pix, NULL );
glXMakeContextCurrent( display(), pixmap, pixmap, context );
glReadBuffer( GL_FRONT );
@ -509,6 +574,8 @@ void SceneOpenGL::Window::discardTexture()
texture = 0;
}
// paint a quad (rectangle), ty1/ty2 are texture coordinates (for handling
// swapped y coordinate, see below)
static void quadPaint( int x1, int y1, int x2, int y2, int ty1, int ty2 )
{
glTexCoord2i( x1, ty1 );
@ -521,8 +588,11 @@ static void quadPaint( int x1, int y1, int x2, int y2, int ty1, int ty2 )
glVertex2i( x1, y2 );
}
// paint the window
void SceneOpenGL::Window::performPaint( int mask, QRegion region, WindowPaintData data )
{
// check if there is something to paint (e.g. don't paint if the window
// is only opaque and only PAINT_WINDOW_TRANSLUCENT is requested)
bool opaque = isOpaque() && data.opacity == 1.0;
if( mask & ( PAINT_WINDOW_OPAQUE | PAINT_WINDOW_TRANSLUCENT ))
{}
@ -544,6 +614,7 @@ void SceneOpenGL::Window::performPaint( int mask, QRegion region, WindowPaintDat
return;
bindTexture();
glPushMatrix();
// do required transformations
int x = toplevel->x();
int y = toplevel->y();
if( mask & PAINT_WINDOW_TRANSFORMED )
@ -554,6 +625,7 @@ void SceneOpenGL::Window::performPaint( int mask, QRegion region, WindowPaintDat
glTranslatef( x, y, 0 );
if(( mask & PAINT_WINDOW_TRANSFORMED ) && ( data.xScale != 1 || data.yScale != 1 ))
glScalef( data.xScale, data.yScale, 1 );
// setup blending of transparent windows
bool was_blend = glIsEnabled( GL_BLEND );
if( !opaque )
{
@ -562,6 +634,8 @@ void SceneOpenGL::Window::performPaint( int mask, QRegion region, WindowPaintDat
}
if( data.opacity != 1.0 )
{
// the window is additionally configured to have its opacity adjusted,
// do it
if( toplevel->hasAlpha())
{
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
@ -580,6 +654,7 @@ void SceneOpenGL::Window::performPaint( int mask, QRegion region, WindowPaintDat
}
}
glEnable( GL_TEXTURE_RECTANGLE_ARB );
// actually paint the window
glBegin( GL_QUADS );
foreach( QRect r, region.rects())
{
@ -587,6 +662,8 @@ void SceneOpenGL::Window::performPaint( int mask, QRegion region, WindowPaintDat
int y2 = r.y() + r.height();
int ty1 = y1;
int ty2 = y2;
// tfp can result in the texture having y coordinate inverted (because
// of the internal format), so do the inversion if needed
if( !texture_y_inverted ) // "!" because of converting to OpenGL coords
{
ty1 = height() - y1;

View file

@ -64,9 +64,9 @@ class SceneOpenGL::Window
Window() {} // QMap sucks even in Qt4
private:
Texture texture;
bool texture_y_inverted;
Pixmap bound_pixmap;
GLXPixmap bound_glxpixmap; // only for tfp_mode
bool texture_y_inverted; // texture has y inverted
Pixmap bound_pixmap; // the pixmap the texture is bound to, only for tfp_mode
GLXPixmap bound_glxpixmap; // the glx pixmap the texture is bound to, only for tfp_mode
};
} // namespace

View file

@ -8,6 +8,27 @@ You can Freely distribute this program under the GNU General Public
License. See the file "COPYING" for the exact licensing terms.
******************************************************************/
/*
This is the XRender-based compositing code. The primary compositing
backend is the OpenGL-based one, which should be more powerful
and also possibly better documented. This backend is mostly for cases
when the OpenGL backend cannot be used for some reason (insufficient
performance, no usable OpenGL support at all, etc.)
The plan is to keep it around as long as needed/possible, but if it
proves to be too much hassle it will be dropped in the future.
Docs:
XRender (the protocol, but the function calls map to it):
http://webcvs.freedesktop.org/xlibs/Render/protocol
(I couldn't find it in the freedesktop git repository, so this one
is a bit older, but it shouldn't matter.)
XFixes (again, the protocol):
http://gitweb.freedesktop.org/?p=xorg/proto/fixesproto.git;a=blob;hb=HEAD;f=protocol
*/
#include "scene_xrender.h"
#ifdef HAVE_XRENDER
@ -23,12 +44,13 @@ namespace KWinInternal
// SceneXrender
//****************************************
// kDebug() support for the XserverRegion type
struct RegionDebug
{
RegionDebug( XserverRegion r ) : rr( r ) {}
XserverRegion rr;
};
#ifdef NDEBUG
inline
kndbgstream& operator<<( kndbgstream& stream, RegionDebug ) { return stream; }
@ -55,15 +77,11 @@ ScreenPaintData SceneXrender::screen_paint;
SceneXrender::SceneXrender( Workspace* ws )
: Scene( ws )
{
// create XRender picture for the root window
format = XRenderFindVisualFormat( display(), DefaultVisual( display(), DefaultScreen( display())));
XRenderPictureAttributes pa;
pa.subwindow_mode = IncludeInferiors;
front = XRenderCreatePicture( display(), rootWindow(), format, CPSubwindowMode, &pa );
XRectangle xr;
xr.x = SHRT_MIN / 2;
xr.y = SHRT_MIN / 2;
xr.width = SHRT_MAX;
xr.height = SHRT_MAX;
createBuffer();
}
@ -77,6 +95,7 @@ SceneXrender::~SceneXrender()
(*it).free();
}
// the entry point for painting
void SceneXrender::paint( QRegion damage, ToplevelList toplevels )
{
foreach( Toplevel* c, toplevels )
@ -112,6 +131,7 @@ void SceneXrender::paintGenericScreen( int mask, ScreenPaintData data )
Scene::paintGenericScreen( mask, data );
}
// fill the screen background
void SceneXrender::paintBackground( QRegion region )
{
if( region != infiniteRegion())
@ -156,8 +176,8 @@ void SceneXrender::windowAdded( Toplevel* c )
windows[ c ] = Window( c );
}
// TODO handle xrandr changes
// Create the compositing buffer. The root window is not double-buffered,
// so it is done manually using this buffer,
void SceneXrender::createBuffer()
{
if( buffer != None )
@ -167,6 +187,9 @@ void SceneXrender::createBuffer()
XFreePixmap( display(), pixmap ); // The picture owns the pixmap now
}
// Convert QRegion to XserverRegion. This code uses XserverRegion
// only when really necessary as the shared implementation uses
// QRegion.
XserverRegion SceneXrender::toXserverRegion( QRegion region )
{
QVector< QRect > rects = region.rects();
@ -204,6 +227,7 @@ void SceneXrender::Window::free()
discardShape();
}
// Create XRender picture for the pixmap with the window contents.
Picture SceneXrender::Window::picture()
{
if( !toplevel->damage().isEmpty() && _picture != None )
@ -213,9 +237,10 @@ Picture SceneXrender::Window::picture()
}
if( _picture == None && format != NULL )
{
// Get the pixmap with the window contents.
Pixmap window_pix = toplevel->createWindowPixmap();
Pixmap pix = window_pix;
// HACK the same like with opengl
// HACK the same alpha clear hack like with opengl, see there
Client* c = dynamic_cast< Client* >( toplevel );
bool alpha_clear = c != NULL && c->hasAlpha() && !c->noBorder();
#define ALPHA_CLEAR_COPY
@ -268,6 +293,7 @@ void SceneXrender::Window::discardAlpha()
alpha = None;
}
// Create XRender picture for the alpha mask.
Picture SceneXrender::Window::alphaMask( double opacity )
{
if( isOpaque() && opacity == 1.0 )
@ -285,6 +311,7 @@ Picture SceneXrender::Window::alphaMask( double opacity )
alpha_cached_opacity = 1.0;
return None;
}
// Create a 1x1 8bpp pixmap containing the given opacity in the alpha channel.
Pixmap pixmap = XCreatePixmap( display(), rootWindow(), 1, 1, 8 );
XRenderPictFormat* format = XRenderFindStandardFormat( display(), PictStandardA8 );
XRenderPictureAttributes pa;
@ -298,8 +325,10 @@ Picture SceneXrender::Window::alphaMask( double opacity )
return alpha;
}
// paint the window
void SceneXrender::Window::performPaint( int mask, QRegion region, WindowPaintData data )
{
// check if there is something to paint
bool opaque = isOpaque() && data.opacity == 1.0;
if( mask & ( PAINT_WINDOW_OPAQUE | PAINT_WINDOW_TRANSLUCENT ))
{}
@ -319,9 +348,10 @@ void SceneXrender::Window::performPaint( int mask, QRegion region, WindowPaintDa
XFixesSetPictureClipRegion( display(), buffer, 0, 0, clip_region );
XFixesDestroyRegion( display(), clip_region );
}
Picture pic = picture();
Picture pic = picture(); // get XRender picture
if( pic == None ) // The render format can be null for GL and/or Xv visuals
return;
// do required transformations
int x = toplevel->x();
int y = toplevel->y();
if( mask & PAINT_SCREEN_TRANSFORMED )

View file

@ -42,6 +42,9 @@ License. See the file "COPYING" for the exact licensing terms.
#include "group.h"
#include "rules.h"
#include "kwinadaptor.h"
#include "unmanaged.h"
#include "scene.h"
#include "effects.h"
#include <X11/extensions/shape.h>
#include <X11/keysym.h>
@ -122,7 +125,8 @@ 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 )
{
new KWinAdaptor( "org.kde.kwin", "/KWin", QDBusConnection::sessionBus(), this );
@ -166,10 +170,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 +324,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 +362,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 +429,7 @@ void Workspace::init()
Workspace::~Workspace()
{
finishCompositing();
blockStackingUpdates( true );
// TODO grabXServer();
// use stacking_order, so that kwin --replace keeps stacking order
@ -429,6 +441,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 +488,26 @@ 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 )
{
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 +550,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 +574,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 +613,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
@ -864,7 +919,7 @@ void Workspace::slotSettingsChanged(int category)
/*!
Reread settings
*/
KWIN_PROCEDURE( CheckBorderSizesProcedure, cl->checkBorderSizes() );
KWIN_PROCEDURE( CheckBorderSizesProcedure, Client, cl->checkBorderSizes() );
void Workspace::slotReconfigure()
{
@ -921,6 +976,11 @@ void Workspace::slotReconfigure()
updateTopMenuGeometry();
updateCurrentTopMenu();
}
if( options->useTranslucency )
setupCompositing();
else
finishCompositing();
loadWindowRules();
for( ClientList::Iterator it = clients.begin();
@ -1622,7 +1682,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;
@ -2335,7 +2395,7 @@ void Workspace::helperDialog( const QString& message, const Client* c )
{
KAction* action = keys->action( "Window Operations Menu" );
QString shortcut = QString( "%1 (%2)" ).arg( action->text() )
.arg( action->globalShortcut().seq( 0 ).toString());
.arg( action->shortcut().seq( 0 ).toString());
args << "--msgbox" <<
i18n( "You have selected to show a window without its border.\n"
"Without the border, you will not be able to enable the border "
@ -2348,7 +2408,7 @@ void Workspace::helperDialog( const QString& message, const Client* c )
{
KAction* action = keys->action( "Window Operations Menu" );
QString shortcut = QString( "%1 (%2)" ).arg( action->text() )
.arg( action->globalShortcut().seq( 0 ).toString());
.arg( action->shortcut().seq( 0 ).toString());
args << "--msgbox" <<
i18n( "You have selected to show a window in fullscreen mode.\n"
"If the application itself does not have an option to turn the fullscreen "

View file

@ -420,7 +420,7 @@ class Workspace : public QObject, public KDecorationDefines
void setPopupClientOpacity(int v);
void resetClientOpacity();
void setTransButtonText(int value);
void compositeTimeout();
void performCompositing();
protected:
bool keyPressMouseEmulation( XKeyEvent& ev );