Instead of the somewhat fragile way of trying to clean up Client/Unmanaged

instances and keeping them around after the window is closed, create
class Deleted as a representation of a closed window.


svn path=/branches/work/kwin_composite/; revision=626356
icc-effect-5.14.5
Luboš Luňák 2007-01-22 22:51:30 +00:00
parent 0fdc6c4469
commit 77f803a563
36 changed files with 190 additions and 147 deletions

View File

@ -50,6 +50,7 @@ set(kwin_KDEINIT_SRCS
scene_xrender.cpp
scene_opengl.cpp
glutils.cpp
deleted.cpp
effects.cpp
effects/fadein.cpp
effects/fadeout.cpp

View File

@ -67,10 +67,12 @@ General TODO
* handle properly deleted windows that reappear (windowReadded() function?)
? consider using an extra class for representing deleted windows
/ consider using an extra class for representing deleted windows
- cleaning up Client/Unmanaged instances may still leave e.g. timers around if they're overlooked
- an extra class could copy some interesting data and "replace" the old instance
+ Deleted::windowType() does not work
OpenGL TODO
=================================
@ -224,6 +226,10 @@ Effects TODO
initiated by the user or by the application
* - fade-out needs framework for disappearing windows (see the todo entry)
+ add API that'll hide the internals (for making backwards compatibility easier, etc.)
- effects should have access only to classes from this API
- hide the fact that Client/Unmanaged become Deleted in windowClosed()
+ minimize/shade effects
- to replace the ones from KWin core
- Client::animateMinimizeOrUnminimize()

View File

@ -30,6 +30,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include "rules.h"
#include "scene.h"
#include "effects.h"
#include "deleted.h"
#include <X11/extensions/shape.h>
#include <QX11Info>
@ -108,6 +109,7 @@ Client::Client( Workspace *ws )
shade_mode = ShadeNone;
active = false;
deleting = false;
keep_above = false;
keep_below = false;
motif_noborder = false;
@ -174,11 +176,16 @@ void Client::deleteClient( Client* c, allowed_t )
*/
void Client::releaseWindow( bool on_shutdown )
{
assert( !deleting());
delete_refcount = 1;
assert( !deleting );
deleting = true;
if( effects )
effects->windowClosed( this );
finishCompositing( false ); // don't discard pixmap
{
Deleted* del = Deleted::create( this );
effects->windowClosed( this, del );
scene->windowClosed( this, del );
del->unrefWindow();
}
finishCompositing();
workspace()->discardUsedWindowRules( this, true ); // remove ForceTemporarily rules
StackingUpdatesBlocker blocker( workspace());
if (moveResizeMode)
@ -193,9 +200,7 @@ void Client::releaseWindow( bool on_shutdown )
if( !on_shutdown )
workspace()->clientHidden( this );
XUnmapWindow( display(), frameId()); // destroying decoration would cause ugly visual effect
// destroyDecoration();
delete decoration;
decoration = NULL;
destroyDecoration();
cleanGrouping();
if( !on_shutdown )
{
@ -203,11 +208,9 @@ void Client::releaseWindow( bool on_shutdown )
// only when the window is being unmapped, not when closing down KWin
// (NETWM sections 5.5,5.7)
info->setDesktop( 0 );
// desk = 0; - do not reset internal state, it may still be used by effects
desk = 0;
info->setState( 0, info->state()); // reset all state flags
}
else
workspace()->addDeleted( this, Allowed );
XDeleteProperty( display(), client, atoms->kde_net_wm_user_creation_time);
XDeleteProperty( display(), client, atoms->net_frame_extents );
XDeleteProperty( display(), client, atoms->kde_net_wm_frame_strut );
@ -225,25 +228,30 @@ void Client::releaseWindow( bool on_shutdown )
// may do map+unmap before we initially map the window by calling rawShow() from manage().
XUnmapWindow( display(), client );
}
cleanUp();
client = None;
XDestroyWindow( display(), wrapper );
wrapper = None;
XDestroyWindow( display(), frameId());
// frame = None;
--block_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry
unrefWindow(); // will delete if recount is == 0
workspace()->addDamage( geometry());
deleteClient( this, Allowed );
}
// like releaseWindow(), but this one is called when the window has been already destroyed
// (e.g. the application closed it)
void Client::destroyClient()
{
assert( !deleting());
delete_refcount = 1;
assert( !deleting );
deleting = true;
if( effects )
effects->windowClosed( this );
finishCompositing( false ); // don't discard pixmap
{
Deleted* del = Deleted::create( this );
effects->windowClosed( this, del );
scene->windowClosed( this, del );
del->unrefWindow();
}
finishCompositing();
workspace()->discardUsedWindowRules( this, true ); // remove ForceTemporarily rules
StackingUpdatesBlocker blocker( workspace());
if (moveResizeMode)
@ -255,50 +263,16 @@ void Client::destroyClient()
setModal( false );
hidden = true; // so that it's not considered visible anymore
workspace()->clientHidden( this );
// destroyDecoration();
delete decoration;
decoration = NULL;
destroyDecoration();
cleanGrouping();
workspace()->removeClient( this, Allowed );
cleanUp();
client = None; // invalidate
XDestroyWindow( display(), wrapper );
wrapper = None;
XDestroyWindow( display(), frameId());
// frame = None;
--block_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry
unrefWindow(); // will delete if recount is == 0
}
// All clean-up code shared between releaseWindow() and destroyClient().
// Clean up everything that should not affect a deleted Client until it's
// really deleted by unrefWindow(). I.e. stop watching events, turn off timers
// and so on.
void Client::cleanUp()
{
if( Extensions::shapeAvailable())
XShapeSelectInput( display(), client, NoEventMask );
XSelectInput( display(), client, NoEventMask );
delete autoRaiseTimer;
autoRaiseTimer = NULL;
delete shadeHoverTimer;
shadeHoverTimer = NULL;
delete ping_timer;
ping_timer = NULL;
delete process_killer;
process_killer = NULL;
delete demandAttentionKNotifyTimer;
demandAttentionKNotifyTimer = NULL;
}
void Client::unrefWindow()
{
if( --delete_refcount > 0 )
return;
workspace()->removeDeleted( this );
workspace()->addDamage( geometry());
destroyDecoration( true ); // only now gravitate etc., otherwise window pixmap would be wrong
discardWindowPixmap();
deleteClient( this, Allowed );
}
@ -343,9 +317,9 @@ void Client::updateDecoration( bool check_workspace_pos, bool force )
addDamageFull();
}
void Client::destroyDecoration( bool force )
void Client::destroyDecoration()
{
if( decoration != NULL || force )
if( decoration != NULL )
{
delete decoration;
decoration = NULL;
@ -360,7 +334,7 @@ void Client::destroyDecoration( bool force )
workarea_diff_y = save_workarea_diff_y;
if( compositing() )
discardWindowPixmap();
if( scene != NULL && !deleting())
if( scene != NULL && !deleting )
scene->windowGeometryShapeChanged( this );
addDamageFull();
}
@ -895,7 +869,7 @@ void Client::toggleShade()
void Client::updateVisibility()
{
if( deleting())
if( deleting )
return;
bool show = true;
if( hidden )
@ -953,7 +927,7 @@ void Client::updateVisibility()
void Client::setMappingState(int s)
{
assert( client != None );
assert( !deleting() || s == WithdrawnState );
assert( !deleting || s == WithdrawnState );
if( mapping_state == s )
return;
bool was_unmanaged = ( mapping_state == WithdrawnState );

View File

@ -91,7 +91,6 @@ class Client
void releaseWindow( bool on_shutdown = false );
void destroyClient();
virtual void unrefWindow();
enum Sizemode // how to resize the window in order to obey constains (mainly aspect ratios)
{
@ -358,7 +357,6 @@ class Client
void updateWindowRules();
void finishWindowRules();
void setShortcutInternal( const KShortcut& cut );
void cleanUp();
void updateWorkareaDiffs();
void checkDirection( int new_diff, int old_diff, QRect& rect, const QRect& area );
@ -387,7 +385,7 @@ class Client
void embedClient( Window w, const XWindowAttributes &attr );
void detectNoBorder();
void destroyDecoration( bool force = false );
void destroyDecoration();
void updateFrameExtents();
void rawShow(); // just shows it
@ -432,6 +430,7 @@ class Client
ClientList transients_list; // SELI make this ordered in stacking order?
ShadeMode shade_mode;
uint active :1;
uint deleting : 1; // true when doing cleanup and destroying the client
uint keep_above : 1; // NET::KeepAbove (was stays_on_top)
uint skip_taskbar :1;
uint original_skip_taskbar :1; // unaffected by KWin

View File

@ -29,6 +29,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include "workspace.h"
#include "client.h"
#include "unmanaged.h"
#include "deleted.h"
#include "effects.h"
#include "scene.h"
#include "scene_basic.h"
@ -137,13 +138,17 @@ void Workspace::finishCompositing()
return;
delete cm_selection;
foreach( Client* c, clients )
scene->windowDeleted( c );
scene->windowClosed( c, NULL );
foreach( Unmanaged* c, unmanaged )
scene->windowClosed( c, NULL );
foreach( Deleted* c, deleted )
scene->windowDeleted( c );
foreach( Client* c, clients )
c->finishCompositing();
foreach( Unmanaged* c, unmanaged )
c->finishCompositing();
foreach( Deleted* c, deleted )
c->finishCompositing();
XCompositeUnredirectSubwindows( display(), rootWindow(), CompositeRedirectManual );
compositeTimer.stop();
delete effects;
@ -222,7 +227,7 @@ void Workspace::performCompositing()
else if( Unmanaged* c = findUnmanaged( HandleMatchPredicate( children[ i ] )))
windows.append( c );
}
foreach( Toplevel* c, pending_deleted ) // TODO remember stacking order somehow
foreach( Deleted* c, deleted ) // TODO remember stacking order somehow
windows.append( c );
QRegion damage = damage_region;
// clear all damage, so that post-pass can add damage for the next repaint
@ -292,13 +297,12 @@ void Toplevel::setupCompositing()
damage_region = QRegion( 0, 0, width(), height());
}
void Toplevel::finishCompositing( bool discard_pixmap )
void Toplevel::finishCompositing()
{
if( damage_handle == None )
return;
XDamageDestroy( display(), damage_handle );
if( discard_pixmap )
discardWindowPixmap();
discardWindowPixmap();
damage_handle = None;
damage_region = QRegion();
}

View File

@ -47,11 +47,11 @@ void Effect::windowAdded( Toplevel* )
{
}
void Effect::windowClosed( Toplevel* )
void Effect::windowClosed( Toplevel*, Deleted* )
{
}
void Effect::windowDeleted( Toplevel* )
void Effect::windowDeleted( Deleted* )
{
}
@ -147,16 +147,16 @@ void EffectsHandler::windowAdded( Toplevel* c )
e->windowAdded( c );
}
void EffectsHandler::windowDeleted( Toplevel* c )
void EffectsHandler::windowDeleted( Deleted* c )
{
foreach( Effect* e, effects )
e->windowDeleted( c );
}
void EffectsHandler::windowClosed( Toplevel* c )
void EffectsHandler::windowClosed( Toplevel* c, Deleted* deleted )
{
foreach( Effect* e, effects )
e->windowClosed( c );
e->windowClosed( c, deleted );
}
void EffectsHandler::windowActivated( Toplevel* c )

View File

@ -73,8 +73,8 @@ class Effect
// called when moved/resized or once after it's finished
virtual void windowUserMovedResized( Toplevel* c, bool first, bool last );
virtual void windowAdded( Toplevel* c );
virtual void windowDeleted( Toplevel* c );
virtual void windowClosed( Toplevel* c );
virtual void windowClosed( Toplevel* c, Deleted* deleted );
virtual void windowDeleted( Deleted* c );
virtual void windowActivated( Toplevel* c );
virtual void windowMinimized( Toplevel* c );
virtual void windowUnminimized( Toplevel* c );
@ -111,8 +111,8 @@ class EffectsHandler
void startPaint();
void windowUserMovedResized( Toplevel* c, bool first, bool last );
void windowAdded( Toplevel* c );
void windowClosed( Toplevel* c );
void windowDeleted( Toplevel* c );
void windowClosed( Toplevel* c, Deleted* deleted );
void windowDeleted( Deleted* c );
void windowActivated( Toplevel* c );
void windowMinimized( Toplevel* c );
void windowUnminimized( Toplevel* c );

View File

@ -84,7 +84,7 @@ void DialogParentEffect::windowActivated( Toplevel* t )
}
}
void DialogParentEffect::windowDeleted( Toplevel* t )
void DialogParentEffect::windowClosed( Toplevel* t, Deleted* )
{
// If this window is a dialog, we need to damage it's parent window, so
// that the effect could be run for it

View File

@ -32,7 +32,7 @@ class DialogParentEffect
virtual void paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintWindow( Scene::Window* w );
virtual void windowDeleted( Toplevel* c );
virtual void windowClosed( Toplevel* c, Deleted* );
virtual void windowActivated( Toplevel* c );
protected:

View File

@ -57,7 +57,7 @@ void FadeInEffect::windowAdded( Toplevel* c )
}
}
void FadeInEffect::windowDeleted( Toplevel* c )
void FadeInEffect::windowClosed( Toplevel* c, Deleted* )
{
windows.remove( c );
}

View File

@ -27,7 +27,7 @@ class FadeInEffect
virtual void postPaintWindow( Scene::Window* w );
// TODO react also on virtual desktop changes
virtual void windowAdded( Toplevel* c );
virtual void windowDeleted( Toplevel* c );
virtual void windowClosed( Toplevel* c, Deleted* );
private:
QMap< const Toplevel*, double > windows;
};

View File

@ -11,6 +11,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include "fadeout.h"
#include <client.h>
#include <deleted.h>
namespace KWinInternal
{
@ -28,7 +29,7 @@ void FadeOutEffect::prePaintWindow( Scene::Window* w, int* mask, QRegion* region
else
{
windows.remove( w->window());
w->window()->unrefWindow();
static_cast< Deleted* >( w->window())->unrefWindow();
}
}
effects->prePaintWindow( w, mask, region, time );
@ -50,18 +51,18 @@ void FadeOutEffect::postPaintWindow( Scene::Window* w )
effects->postPaintWindow( w );
}
void FadeOutEffect::windowClosed( Toplevel* c )
void FadeOutEffect::windowClosed( Toplevel* c, Deleted* d )
{
Client* cc = dynamic_cast< Client* >( c );
if( cc == NULL || cc->isOnCurrentDesktop())
{
windows[ c ] = 1; // count down to 0
c->addDamageFull();
c->refWindow();
windows[ d ] = 1; // count down to 0
d->addDamageFull();
d->refWindow();
}
}
void FadeOutEffect::windowDeleted( Toplevel* c )
void FadeOutEffect::windowDeleted( Deleted* c )
{
windows.remove( c );
}

View File

@ -26,8 +26,8 @@ class FadeOutEffect
virtual void paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintWindow( Scene::Window* w );
// TODO react also on virtual desktop changes
virtual void windowClosed( Toplevel* c );
virtual void windowDeleted( Toplevel* c );
virtual void windowClosed( Toplevel* c, Deleted* d );
virtual void windowDeleted( Deleted* c );
private:
QMap< const Toplevel*, double > windows;
};

View File

@ -20,6 +20,7 @@ License. See the file "COPYING" for the exact licensing terms.
// Include the class definition.
#include "howto.h"
#include "deleted.h"
// Note that currently effects need to be manually enabled in the EffectsHandler
// class constructor (in effects.cpp).
@ -137,8 +138,15 @@ void HowtoEffect::windowActivated( Toplevel* c )
}
}
// TODO
void HowtoEffect::windowClosed( Toplevel* c, Deleted* d )
{
if( fade_window == c )
fade_window = d;
}
// This function is called when a window is destroyed.
void HowtoEffect::windowDeleted( Toplevel* c )
void HowtoEffect::windowDeleted( Deleted* c )
{
// If the window to be faded out and in is destroyed, just reset the pointer.
// This effect then will do nothing and just call the next effect.

View File

@ -51,8 +51,11 @@ class HowtoEffect
// Notification functions: These inform the effect about changes such as a new window
// being activated.
// TODO
virtual void windowClosed( Toplevel* c, Deleted* d );
// The given window has been deleted (destroyed).
virtual void windowDeleted( Toplevel* c );
virtual void windowDeleted( Deleted* c );
// The given window has been activated.
virtual void windowActivated( Toplevel* c );

View File

@ -131,7 +131,7 @@ void PresentWindowsEffect::windowActivated( Toplevel* t )
rearrangeWindows();
}
void PresentWindowsEffect::windowDeleted( Toplevel* t )
void PresentWindowsEffect::windowClosed( Toplevel* t, Deleted* )
{
rearrangeWindows();
}

View File

@ -35,7 +35,7 @@ class PresentWindowsEffect
virtual void paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintScreen();
virtual void windowDeleted( Toplevel* c );
virtual void windowClosed( Toplevel* c, Deleted* );
virtual void windowActivated( Toplevel* c );
virtual void windowInputMouseEvent( Window w, QEvent* e );

View File

@ -65,7 +65,7 @@ void ScaleInEffect::windowAdded( Toplevel* c )
}
}
void ScaleInEffect::windowDeleted( Toplevel* c )
void ScaleInEffect::windowClosed( Toplevel* c, Deleted* )
{
windows.remove( c );
}

View File

@ -28,7 +28,7 @@ class ScaleInEffect
virtual void postPaintWindow( Scene::Window* w );
// TODO react also on virtual desktop changes
virtual void windowAdded( Toplevel* c );
virtual void windowDeleted( Toplevel* c );
virtual void windowClosed( Toplevel* c, Deleted* );
private:
QMap< const Toplevel*, double > windows;
};

View File

@ -62,7 +62,7 @@ void ShakyMoveEffect::windowUserMovedResized( Toplevel* c, bool first, bool last
}
}
void ShakyMoveEffect::windowDeleted( Toplevel* c )
void ShakyMoveEffect::windowClosed( Toplevel* c, Deleted* )
{
windows.remove( c );
if( windows.isEmpty())

View File

@ -30,7 +30,7 @@ class ShakyMoveEffect
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int time );
virtual void paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data );
virtual void windowDeleted( Toplevel* c );
virtual void windowClosed( Toplevel* c, Deleted* );
private slots:
void tick();
private:

View File

@ -64,6 +64,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include <X11/extensions/shape.h>
#include "client.h"
#include "deleted.h"
#include "effects.h"
namespace KWinInternal
@ -290,7 +291,7 @@ QRegion Scene::Window::shape() const
bool Scene::Window::isVisible() const
{
if( toplevel->deleting())
if( dynamic_cast< Deleted* >( toplevel ) != NULL )
return false;
if( Client* c = dynamic_cast< Client* >( toplevel ))
return c->isShown( true ) && c->isOnCurrentDesktop();

12
scene.h
View File

@ -20,6 +20,7 @@ namespace KWinInternal
{
class Workspace;
class Deleted;
class WindowPaintData;
class ScreenPaintData;
@ -43,8 +44,10 @@ class Scene
virtual void windowOpacityChanged( Toplevel* ) = 0;
// a new window has been created
virtual void windowAdded( Toplevel* ) = 0;
// a window has been closed
virtual void windowClosed( Toplevel*, Deleted* ) = 0;
// a window has been destroyed
virtual void windowDeleted( Toplevel* ) = 0;
virtual void windowDeleted( Deleted* ) = 0;
// Flags controlling how painting is done.
enum
{
@ -128,6 +131,7 @@ class Scene::Window
// shape of the window
QRegion shape() const;
void discardShape();
void updateToplevel( Toplevel* c );
Window() {} // QMap sucks even in Qt4
protected:
Toplevel* toplevel;
@ -174,6 +178,12 @@ Toplevel* Scene::Window::window()
return toplevel;
}
inline
void Scene::Window::updateToplevel( Toplevel* c )
{
toplevel = c;
}
} // namespace
#endif

View File

@ -77,7 +77,11 @@ void SceneBasic::windowAdded( Toplevel* )
{
}
void SceneBasic::windowDeleted( Toplevel* )
void SceneBasic::windowClosed( Toplevel*, Deleted* )
{
}
void SceneBasic::windowDeleted( Deleted* )
{
}

View File

@ -28,7 +28,8 @@ class SceneBasic
virtual void windowGeometryShapeChanged( Toplevel* );
virtual void windowOpacityChanged( Toplevel* );
virtual void windowAdded( Toplevel* );
virtual void windowDeleted( Toplevel* );
virtual void windowClosed( Toplevel*, Deleted* );
virtual void windowDeleted( Deleted* );
};
} // namespace

View File

@ -59,6 +59,7 @@ Sources and other compositing managers:
#include "utils.h"
#include "client.h"
#include "deleted.h"
#include "effects.h"
#include "glutils.h"
@ -565,7 +566,24 @@ void SceneOpenGL::windowAdded( Toplevel* c )
windows[ c ] = Window( c );
}
void SceneOpenGL::windowDeleted( Toplevel* c )
void SceneOpenGL::windowClosed( Toplevel* c, Deleted* deleted )
{
assert( windows.contains( c ));
if( deleted != NULL )
{ // replace c with deleted
Window& w = windows[ c ];
w.updateToplevel( deleted );
windows[ deleted ] = w;
windows.remove( c );
}
else
{
windows[ c ].free();
windows.remove( c );
}
}
void SceneOpenGL::windowDeleted( Deleted* c )
{
assert( windows.contains( c ));
windows[ c ].free();

View File

@ -31,7 +31,8 @@ class SceneOpenGL
virtual void windowGeometryShapeChanged( Toplevel* );
virtual void windowOpacityChanged( Toplevel* );
virtual void windowAdded( Toplevel* );
virtual void windowDeleted( Toplevel* );
virtual void windowClosed( Toplevel*, Deleted* );
virtual void windowDeleted( Deleted* );
protected:
virtual void paintGenericScreen( int mask, ScreenPaintData data );
virtual void paintBackground( QRegion region );

View File

@ -33,6 +33,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include "toplevel.h"
#include "client.h"
#include "deleted.h"
#include "effects.h"
namespace KWinInternal
@ -230,7 +231,24 @@ void SceneXrender::windowOpacityChanged( Toplevel* c )
w.discardAlpha();
}
void SceneXrender::windowDeleted( Toplevel* c )
void SceneXrender::windowClosed( Toplevel* c, Deleted* deleted )
{
assert( windows.contains( c ));
if( deleted != NULL )
{ // replace c with deleted
Window& w = windows[ c ];
w.updateToplevel( deleted );
windows[ deleted ] = w;
windows.remove( c );
}
else
{
windows[ c ].free();
windows.remove( c );
}
}
void SceneXrender::windowDeleted( Deleted* c )
{
assert( windows.contains( c ));
windows[ c ].free();

View File

@ -33,7 +33,8 @@ class SceneXrender
virtual void windowGeometryShapeChanged( Toplevel* );
virtual void windowOpacityChanged( Toplevel* );
virtual void windowAdded( Toplevel* );
virtual void windowDeleted( Toplevel* );
virtual void windowClosed( Toplevel*, Deleted* );
virtual void windowDeleted( Deleted* );
Picture bufferPicture();
protected:
virtual void paintBackground( QRegion region );

View File

@ -15,7 +15,6 @@ namespace KWinInternal
Toplevel::Toplevel( Workspace* ws )
: vis( None )
, delete_refcount( -1 )
, id( None )
, wspace( ws )
, window_pix( None )
@ -79,6 +78,21 @@ void Toplevel::detectShape( Window id )
is_shape = Extensions::hasShape( id );
}
// used only by Deleted::copy()
void Toplevel::copyToDeleted( Toplevel* c )
{
geom = c->geom;
vis = c->vis;
bit_depth = c->bit_depth;
id = c->id;
wspace = c->wspace;
window_pix = c->window_pix;
c->window_pix = None;
damage_handle = None;
damage_region = c->damage_region;
is_shape = c->is_shape;
}
} // namespace
#include "toplevel.moc"

View File

@ -59,18 +59,13 @@ class Toplevel
int depth() const;
bool hasAlpha() const;
void setupCompositing();
void finishCompositing( bool discard_pixmap = true );
void finishCompositing();
void addDamage( const QRect& r );
void addDamage( int x, int y, int w, int h );
void addDamageFull();
QRegion damage() const;
void resetDamage( const QRect& r );
// used by effects to keep the window around for e.g. fadeout effects when it's destroyed
void refWindow();
virtual void unrefWindow() = 0;
bool deleting() const;
protected:
virtual ~Toplevel();
void setHandle( Window id );
@ -81,10 +76,11 @@ class Toplevel
QRect geom;
Visual* vis;
int bit_depth;
int delete_refcount;
virtual void debug( kdbgstream& stream ) const = 0;
void copyToDeleted( Toplevel* c );
friend kdbgstream& operator<<( kdbgstream& stream, const Toplevel* );
private:
// when adding new data members, check also copyToDeleted()
Window id;
Workspace* wspace;
Pixmap window_pix;
@ -226,17 +222,6 @@ inline bool Toplevel::hasAlpha() const
return depth() == 32;
}
inline void Toplevel::refWindow()
{
assert( delete_refcount >= 0 );
++delete_refcount;
}
inline bool Toplevel::deleting() const
{
return delete_refcount >= 0;
}
#ifdef NDEBUG
inline
kndbgstream& operator<<( kndbgstream& stream, const Toplevel* ) { return stream; }

View File

@ -12,6 +12,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include "workspace.h"
#include "effects.h"
#include "deleted.h"
#include <X11/extensions/shape.h>
@ -70,24 +71,18 @@ bool Unmanaged::track( Window w )
void Unmanaged::release()
{
assert( !deleting());
delete_refcount = 1;
if( effects )
effects->windowClosed( this );
finishCompositing( false ); // don't discard pixmap
{
Deleted* del = Deleted::create( this );
effects->windowClosed( this, del );
scene->windowClosed( this, del );
del->unrefWindow();
}
finishCompositing();
workspace()->removeUnmanaged( this, Allowed );
if( Extensions::shapeAvailable())
XShapeSelectInput( display(), handle(), NoEventMask );
XSelectInput( display(), handle(), NoEventMask );
unrefWindow(); // will delete if recount is == 0
}
void Unmanaged::unrefWindow()
{
if( --delete_refcount > 0 )
return;
discardWindowPixmap();
workspace()->removeDeleted( this );
workspace()->addDamage( geometry());
deleteUnmanaged( this, Allowed );
}

View File

@ -30,7 +30,6 @@ class Unmanaged
virtual NET::WindowType windowType( bool direct = false, int supported_types = SUPPORTED_WINDOW_TYPES_MASK ) const;
static void deleteUnmanaged( Unmanaged* c, allowed_t );
virtual double opacity() const;
virtual void unrefWindow();
protected:
virtual void debug( kdbgstream& stream ) const;
private:

View File

@ -75,6 +75,7 @@ const QPoint invalidPoint( INT_MIN, INT_MIN );
class Toplevel;
class Client;
class Unmanaged;
class Deleted;
class Group;
class Options;
@ -84,6 +85,8 @@ typedef QList< Client* > ClientList;
typedef QList< const Client* > ConstClientList;
typedef QList< Unmanaged* > UnmanagedList;
typedef QList< const Unmanaged* > ConstUnmanagedList;
typedef QList< Deleted* > DeletedList;
typedef QList< const Deleted* > ConstDeletedList;
typedef QList< Group* > GroupList;
typedef QList< const Group* > ConstGroupList;

View File

@ -616,31 +616,28 @@ void Workspace::removeClient( Client* c, allowed_t )
tab_box->repaint();
updateClientArea();
addDeleted( c, Allowed );
}
void Workspace::removeUnmanaged( Unmanaged* c, allowed_t )
{
assert( unmanaged.contains( c ));
unmanaged.removeAll( c );
addDeleted( c, Allowed );
}
void Workspace::addDeleted( Toplevel* c, allowed_t )
void Workspace::addDeleted( Deleted* c, allowed_t )
{
assert( !pending_deleted.contains( c ));
pending_deleted.append( c );
assert( !deleted.contains( c ));
deleted.append( c );
}
void Workspace::removeDeleted( Toplevel* c )
void Workspace::removeDeleted( Deleted* c, allowed_t )
{
assert( pending_deleted.contains( c ));
assert( deleted.contains( c ));
if( scene )
scene->windowDeleted( c );
if( effects )
effects->windowDeleted( c );
pending_deleted.removeAll( c );
deleted.removeAll( c );
}
void Workspace::updateFocusChains( Client* c, FocusChainChange change )

View File

@ -247,8 +247,8 @@ class Workspace : public QObject, public KDecorationDefines
Group* findClientLeaderGroup( const Client* c ) const;
void removeUnmanaged( Unmanaged*, allowed_t ); // only called from Unmanaged::release()
void removeDeleted( Toplevel* );
void addDeleted( Toplevel*, allowed_t );
void removeDeleted( Deleted*, allowed_t );
void addDeleted( Deleted*, allowed_t );
bool checkStartupNotification( Window w, KStartupInfoId& id, KStartupInfoData& data );
@ -558,7 +558,7 @@ class Workspace : public QObject, public KDecorationDefines
ClientList clients;
ClientList desktops;
UnmanagedList unmanaged;
ToplevelList pending_deleted;
DeletedList deleted;
ClientList unconstrained_stacking_order;
ClientList stacking_order;