Check for references to no longer existing windows in transiency checks

only when the list of windows is in consistent state.


svn path=/trunk/KDE/kdebase/workspace/; revision=613681
This commit is contained in:
Luboš Luňák 2006-12-14 16:32:55 +00:00
parent c271dd819a
commit 0cbf093fdd
4 changed files with 199 additions and 160 deletions

View file

@ -28,7 +28,6 @@ License. See the file "COPYING" for the exact licensing terms.
#include "atoms.h" #include "atoms.h"
#include "notifications.h" #include "notifications.h"
#include "rules.h" #include "rules.h"
#include "scene.h"
#include <X11/extensions/shape.h> #include <X11/extensions/shape.h>
#include <QX11Info> #include <QX11Info>
@ -64,10 +63,12 @@ namespace KWinInternal
is done in manage(). is done in manage().
*/ */
Client::Client( Workspace *ws ) Client::Client( Workspace *ws )
: Toplevel( ws ), : QObject( NULL ),
client( None ), client( None ),
wrapper( None ), wrapper( None ),
frame( None ),
decoration( NULL ), decoration( NULL ),
wspace( ws ),
bridge( new Bridge( this )), bridge( new Bridge( this )),
move_faked_activity( false ), move_faked_activity( false ),
move_resize_grab_window( None ), move_resize_grab_window( None ),
@ -81,7 +82,7 @@ Client::Client( Workspace *ws )
process_killer( NULL ), process_killer( NULL ),
user_time( CurrentTime ), // not known yet user_time( CurrentTime ), // not known yet
allowed_actions( 0 ), allowed_actions( 0 ),
block_geometry_updates( 0 ), postpone_geometry_updates( 0 ),
pending_geometry_update( false ), pending_geometry_update( false ),
shade_geometry_change( false ), shade_geometry_change( false ),
border_left( 0 ), border_left( 0 ),
@ -110,6 +111,7 @@ Client::Client( Workspace *ws )
deleting = false; deleting = false;
keep_above = false; keep_above = false;
keep_below = false; keep_below = false;
is_shape = false;
motif_noborder = false; motif_noborder = false;
motif_may_move = true; motif_may_move = true;
motif_may_resize = true; motif_may_resize = true;
@ -122,7 +124,6 @@ Client::Client( Workspace *ws )
modal = false; modal = false;
noborder = false; noborder = false;
user_noborder = false; user_noborder = false;
not_obscured = false;
urgency = false; urgency = false;
ignore_focus_stealing = false; ignore_focus_stealing = false;
demands_attention = false; demands_attention = false;
@ -141,7 +142,7 @@ Client::Client( Workspace *ws )
cmap = None; cmap = None;
geom = QRect( 0, 0, 100, 100 ); // so that decorations don't start with size being (0,0) frame_geometry = QRect( 0, 0, 100, 100 ); // so that decorations don't start with size being (0,0)
client_size = QSize( 100, 100 ); client_size = QSize( 100, 100 );
// SELI initialize xsizehints?? // SELI initialize xsizehints??
@ -154,10 +155,9 @@ Client::~Client()
{ {
assert(!moveResizeMode); assert(!moveResizeMode);
assert( client == None ); assert( client == None );
assert( wrapper == None ); assert( frame == None && wrapper == None );
// assert( frameId() == None );
assert( decoration == NULL ); assert( decoration == NULL );
assert( block_geometry_updates == 0 ); assert( postpone_geometry_updates == 0 );
assert( !check_active_modal ); assert( !check_active_modal );
delete info; delete info;
delete bridge; delete bridge;
@ -176,15 +176,15 @@ void Client::releaseWindow( bool on_shutdown )
{ {
assert( !deleting ); assert( !deleting );
deleting = true; deleting = true;
finishCompositing();
workspace()->discardUsedWindowRules( this, true ); // remove ForceTemporarily rules workspace()->discardUsedWindowRules( this, true ); // remove ForceTemporarily rules
StackingUpdatesBlocker blocker( workspace()); StackingUpdatesBlocker blocker( workspace());
if (moveResizeMode) if (moveResizeMode)
leaveMoveResize(); leaveMoveResize();
finishWindowRules(); finishWindowRules();
++block_geometry_updates; ++postpone_geometry_updates;
if( isNormalState()) // is mapped? // grab X during the release to make removing of properties, setting to withdrawn state
workspace()->addDamage( geometry()); // and repareting to root an atomic operation (http://lists.kde.org/?l=kde-devel&m=116448102901184&w=2)
grabXServer();
setMappingState( WithdrawnState ); setMappingState( WithdrawnState );
setModal( false ); // otherwise its mainwindow wouldn't get focus setModal( false ); // otherwise its mainwindow wouldn't get focus
hidden = true; // so that it's not considered visible anymore (can't use hideClient(), it would set flags) hidden = true; // so that it's not considered visible anymore (can't use hideClient(), it would set flags)
@ -222,10 +222,12 @@ void Client::releaseWindow( bool on_shutdown )
client = None; client = None;
XDestroyWindow( display(), wrapper ); XDestroyWindow( display(), wrapper );
wrapper = None; wrapper = None;
XDestroyWindow( display(), frameId()); XDestroyWindow( display(), frame );
// frame = None; frame = None;
--block_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry --postpone_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry
deleteClient( this, Allowed ); deleteClient( this, Allowed );
ungrabXServer();
checkNonExistentClients();
} }
// like releaseWindow(), but this one is called when the window has been already destroyed // like releaseWindow(), but this one is called when the window has been already destroyed
@ -234,15 +236,12 @@ void Client::destroyClient()
{ {
assert( !deleting ); assert( !deleting );
deleting = true; deleting = true;
finishCompositing();
workspace()->discardUsedWindowRules( this, true ); // remove ForceTemporarily rules workspace()->discardUsedWindowRules( this, true ); // remove ForceTemporarily rules
StackingUpdatesBlocker blocker( workspace()); StackingUpdatesBlocker blocker( workspace());
if (moveResizeMode) if (moveResizeMode)
leaveMoveResize(); leaveMoveResize();
finishWindowRules(); finishWindowRules();
++block_geometry_updates; ++postpone_geometry_updates;
if( isNormalState()) // is mapped?
workspace()->addDamage( geometry());
setModal( false ); setModal( false );
hidden = true; // so that it's not considered visible anymore hidden = true; // so that it's not considered visible anymore
workspace()->clientHidden( this ); workspace()->clientHidden( this );
@ -252,10 +251,11 @@ void Client::destroyClient()
client = None; // invalidate client = None; // invalidate
XDestroyWindow( display(), wrapper ); XDestroyWindow( display(), wrapper );
wrapper = None; wrapper = None;
XDestroyWindow( display(), frameId()); XDestroyWindow( display(), frame );
// frame = None; frame = None;
--block_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry --postpone_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry
deleteClient( this, Allowed ); deleteClient( this, Allowed );
checkNonExistentClients();
} }
void Client::updateDecoration( bool check_workspace_pos, bool force ) void Client::updateDecoration( bool check_workspace_pos, bool force )
@ -264,11 +264,12 @@ void Client::updateDecoration( bool check_workspace_pos, bool force )
|| ( decoration != NULL && !noBorder()))) || ( decoration != NULL && !noBorder())))
return; return;
bool do_show = false; bool do_show = false;
blockGeometryUpdates( true ); postponeGeometryUpdates( true );
if( force ) if( force )
destroyDecoration(); destroyDecoration();
if( !noBorder()) if( !noBorder())
{ {
setMask( QRegion()); // reset shape mask
decoration = workspace()->createDecoration( bridge ); decoration = workspace()->createDecoration( bridge );
// TODO check decoration's minimum size? // TODO check decoration's minimum size?
decoration->init(); decoration->init();
@ -283,18 +284,15 @@ void Client::updateDecoration( bool check_workspace_pos, bool force )
workarea_diff_x = save_workarea_diff_x; workarea_diff_x = save_workarea_diff_x;
workarea_diff_y = save_workarea_diff_y; workarea_diff_y = save_workarea_diff_y;
do_show = true; do_show = true;
if( scene != NULL )
scene->windowGeometryShapeChanged( this );
} }
else else
destroyDecoration(); destroyDecoration();
if( check_workspace_pos ) if( check_workspace_pos )
checkWorkspacePosition(); checkWorkspacePosition();
blockGeometryUpdates( false ); postponeGeometryUpdates( false );
if( do_show ) if( do_show )
decoration->widget()->show(); decoration->widget()->show();
updateFrameExtents(); updateFrameExtents();
addDamageFull();
} }
void Client::destroyDecoration() void Client::destroyDecoration()
@ -312,9 +310,6 @@ void Client::destroyDecoration()
move( grav ); move( grav );
workarea_diff_x = save_workarea_diff_x; workarea_diff_x = save_workarea_diff_x;
workarea_diff_y = save_workarea_diff_y; workarea_diff_y = save_workarea_diff_y;
if( scene != NULL )
scene->windowGeometryShapeChanged( this );
addDamageFull();
} }
} }
@ -327,7 +322,7 @@ void Client::checkBorderSizes()
if( new_left == border_left && new_right == border_right if( new_left == border_left && new_right == border_right
&& new_top == border_top && new_bottom == border_bottom ) && new_top == border_top && new_bottom == border_bottom )
return; return;
GeometryUpdatesBlocker blocker( this ); GeometryUpdatesPostponer blocker( this );
move( calculateGravitation( true )); move( calculateGravitation( true ));
border_left = new_left; border_left = new_left;
border_right = new_right; border_right = new_right;
@ -344,7 +339,7 @@ void Client::checkBorderSizes()
void Client::detectNoBorder() void Client::detectNoBorder()
{ {
if( shape()) if( Shape::hasShape( window()))
{ {
noborder = true; noborder = true;
return; return;
@ -432,22 +427,47 @@ void Client::setUserNoBorder( bool set )
void Client::updateShape() void Client::updateShape()
{ {
if ( shape() )
XShapeCombineShape(display(), frameId(), ShapeBounding,
clientPos().x(), clientPos().y(),
window(), ShapeBounding, ShapeSet);
else
XShapeCombineMask( display(), frameId(), ShapeBounding, 0, 0,
None, ShapeSet);
if( scene != NULL )
scene->windowGeometryShapeChanged( this );
addDamageFull();
// workaround for #19644 - shaped windows shouldn't have decoration // workaround for #19644 - shaped windows shouldn't have decoration
if( shape() && !noBorder()) if( shape() && !noBorder())
{ {
noborder = true; noborder = true;
updateDecoration( true ); updateDecoration( true );
} }
if( shape())
{
XShapeCombineShape(display(), frameId(), ShapeBounding,
clientPos().x(), clientPos().y(),
window(), ShapeBounding, ShapeSet);
}
// !shape() mask setting is done in setMask() when the decoration
// calls it or when the decoration is created/destroyed
if( Shape::version() >= 0x11 ) // 1.1, has input shape support
{ // There appears to be no way to find out if a window has input
// shape set or not, so always propagate the input shape
// (it's the same like the bounding shape by default).
// Also, build the shape using a helper window, not directly
// in the frame window, because the sequence set-shape-to-frame,
// remove-shape-of-client, add-input-shape-of-client has the problem
// that after the second step there's a hole in the input shape
// until the real shape of the client is added and that can make
// the window lose focus (which is a problem with mouse focus policies)
static Window helper_window = None;
if( helper_window == None )
helper_window = XCreateSimpleWindow( display(), rootWindow(),
0, 0, 1, 1, 0, 0, 0 );
XResizeWindow( display(), helper_window, width(), height());
XShapeCombineShape( display(), helper_window, ShapeInput, 0, 0,
frameId(), ShapeBounding, ShapeSet );
XShapeCombineShape( display(), helper_window, ShapeInput,
clientPos().x(), clientPos().y(),
window(), ShapeBounding, ShapeSubtract );
XShapeCombineShape( display(), helper_window, ShapeInput,
clientPos().x(), clientPos().y(),
window(), ShapeInput, ShapeUnion );
XShapeCombineShape( display(), frameId(), ShapeInput, 0, 0,
helper_window, ShapeInput, ShapeSet );
}
} }
void Client::setMask( const QRegion& reg, int mode ) void Client::setMask( const QRegion& reg, int mode )
@ -476,9 +496,7 @@ void Client::setMask( const QRegion& reg, int mode )
xrects, rects.count(), ShapeSet, mode ); xrects, rects.count(), ShapeSet, mode );
delete[] xrects; delete[] xrects;
} }
if( scene != NULL ) updateShape();
scene->windowGeometryShapeChanged( this );
addDamageFull();
} }
QRegion Client::mask() const QRegion Client::mask() const
@ -727,7 +745,7 @@ void Client::setShade( ShadeMode mode )
} }
assert( decoration != NULL ); // noborder windows can't be shaded assert( decoration != NULL ); // noborder windows can't be shaded
GeometryUpdatesBlocker blocker( this ); GeometryUpdatesPostponer blocker( this );
// decorations may turn off some borders when shaded // decorations may turn off some borders when shaded
decoration->borders( border_left, border_right, border_top, border_bottom ); decoration->borders( border_left, border_right, border_top, border_bottom );
@ -774,13 +792,9 @@ void Client::setShade( ShadeMode mode )
// tell xcompmgr shade's done // tell xcompmgr shade's done
_shade = 2; _shade = 2;
XChangeProperty(display(), frameId(), atoms->net_wm_window_shade, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &_shade, 1L); XChangeProperty(display(), frameId(), atoms->net_wm_window_shade, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &_shade, 1L);
if( isNormalState()) // is mapped?
workspace()->addDamage( geometry());
} }
else else
{ {
if( isNormalState()) // is mapped?
workspace()->addDamage( geometry());
int h = height(); int h = height();
shade_geometry_change = true; shade_geometry_change = true;
QSize s( sizeForClientSize( clientSize())); QSize s( sizeForClientSize( clientSize()));
@ -915,8 +929,8 @@ void Client::setMappingState(int s)
XChangeProperty(display(), window(), atoms->wm_state, atoms->wm_state, 32, XChangeProperty(display(), window(), atoms->wm_state, atoms->wm_state, 32,
PropModeReplace, (unsigned char *)data, 2); PropModeReplace, (unsigned char *)data, 2);
if( was_unmanaged ) // manage() did block_geometry_updates = 1, now it's ok to finally set the geometry if( was_unmanaged ) // manage() did postpone_geometry_updates = 1, now it's ok to finally set the geometry
blockGeometryUpdates( false ); postponeGeometryUpdates( false );
} }
/*! /*!
@ -927,7 +941,7 @@ void Client::rawShow()
{ {
if( decoration != NULL ) if( decoration != NULL )
decoration->widget()->show(); // not really necessary, but let it know the state decoration->widget()->show(); // not really necessary, but let it know the state
XMapWindow( display(), frameId()); XMapWindow( display(), frame );
if( !isShade()) if( !isShade())
{ {
XMapWindow( display(), wrapper ); XMapWindow( display(), wrapper );
@ -942,7 +956,6 @@ void Client::rawShow()
*/ */
void Client::rawHide() void Client::rawHide()
{ {
workspace()->addDamage( geometry());
// Here it may look like a race condition, as some other client might try to unmap // Here it may look like a race condition, as some other client might try to unmap
// the window between these two XSelectInput() calls. However, they're supposed to // the window between these two XSelectInput() calls. However, they're supposed to
// use XWithdrawWindow(), which also sends a synthetic event to the root window, // use XWithdrawWindow(), which also sends a synthetic event to the root window,
@ -950,7 +963,7 @@ void Client::rawHide()
// will be missed is also very minimal, so I don't think it's needed to grab the server // will be missed is also very minimal, so I don't think it's needed to grab the server
// here. // here.
XSelectInput( display(), wrapper, ClientWinMask ); // avoid getting UnmapNotify XSelectInput( display(), wrapper, ClientWinMask ); // avoid getting UnmapNotify
XUnmapWindow( display(), frameId()); XUnmapWindow( display(), frame );
XUnmapWindow( display(), wrapper ); XUnmapWindow( display(), wrapper );
XUnmapWindow( display(), client ); XUnmapWindow( display(), client );
XSelectInput( display(), wrapper, ClientWinMask | SubstructureNotifyMask ); XSelectInput( display(), wrapper, ClientWinMask | SubstructureNotifyMask );
@ -1295,7 +1308,7 @@ QString Client::readName() const
return KWin::readNameProperty( window(), XA_WM_NAME ); return KWin::readNameProperty( window(), XA_WM_NAME );
} }
KWIN_COMPARE_PREDICATE( FetchNameInternalPredicate, Client, const Client*, (!cl->isSpecialWindow() || cl->isToolbar()) && cl != value && cl->caption() == value->caption()); KWIN_COMPARE_PREDICATE( FetchNameInternalPredicate, const Client*, (!cl->isSpecialWindow() || cl->isToolbar()) && cl != value && cl->caption() == value->caption());
void Client::setCaption( const QString& _s, bool force ) void Client::setCaption( const QString& _s, bool force )
{ {
@ -1612,6 +1625,58 @@ bool Client::wantsInput() const
return rules()->checkAcceptFocus( input || Ptakefocus ); return rules()->checkAcceptFocus( input || Ptakefocus );
} }
bool Client::isDesktop() const
{
return windowType() == NET::Desktop;
}
bool Client::isDock() const
{
return windowType() == NET::Dock;
}
bool Client::isTopMenu() const
{
return windowType() == NET::TopMenu;
}
bool Client::isMenu() const
{
return windowType() == NET::Menu && !isTopMenu(); // because of backwards comp.
}
bool Client::isToolbar() const
{
return windowType() == NET::Toolbar;
}
bool Client::isSplash() const
{
return windowType() == NET::Splash;
}
bool Client::isUtility() const
{
return windowType() == NET::Utility;
}
bool Client::isDialog() const
{
return windowType() == NET::Dialog;
}
bool Client::isNormalWindow() const
{
return windowType() == NET::Normal;
}
bool Client::isSpecialWindow() const
{
return isDesktop() || isDock() || isSplash() || isTopMenu()
|| isToolbar(); // TODO
}
NET::WindowType Client::windowType( bool direct, int supported_types ) const NET::WindowType Client::windowType( bool direct, int supported_types ) const
{ {
NET::WindowType wt = info->windowType( supported_types ); NET::WindowType wt = info->windowType( supported_types );
@ -1643,12 +1708,6 @@ NET::WindowType Client::windowType( bool direct, int supported_types ) const
return wt; return wt;
} }
bool Client::isSpecialWindow() const
{
return isDesktop() || isDock() || isSplash() || isTopMenu()
|| isToolbar(); // TODO
}
/*! /*!
Sets an appropriate cursor shape for the logical mouse position \a m Sets an appropriate cursor shape for the logical mouse position \a m
@ -1745,24 +1804,46 @@ void Client::cancelAutoRaise()
autoRaiseTimer = 0; autoRaiseTimer = 0;
} }
double Client::opacity() const #ifndef NDEBUG
kdbgstream& operator<<( kdbgstream& stream, const Client* cl )
{ {
if( info->opacity() == 0xffffffff ) if( cl == NULL )
return 1.0; return stream << "\'NULL_CLIENT\'";
return info->opacity() * 1.0 / 0xffffffff; return stream << "\'ID:" << cl->window() << ";WMCLASS:" << cl->resourceClass() << ":" << cl->resourceName() << ";Caption:" << cl->caption() << "\'";
} }
kdbgstream& operator<<( kdbgstream& stream, const ClientList& list )
void Client::setOpacity( double opacity )
{ {
opacity = qBound( 0.0, opacity, 1.0 ); stream << "LIST:(";
info->setOpacity( static_cast< unsigned long >( opacity * 0xffffffff )); bool first = true;
// we'll react on PropertyNotify for( ClientList::ConstIterator it = list.begin();
it != list.end();
++it )
{
if( !first )
stream << ":";
first = false;
stream << *it;
}
stream << ")";
return stream;
} }
kdbgstream& operator<<( kdbgstream& stream, const ConstClientList& list )
void Client::debug( kdbgstream& stream ) const
{ {
stream << "\'ID:" << window() << ";WMCLASS:" << resourceClass() << ":" << resourceName() << ";Caption:" << caption() << "\'"; stream << "LIST:(";
bool first = true;
for( ConstClientList::ConstIterator it = list.begin();
it != list.end();
++it )
{
if( !first )
stream << ":";
first = false;
stream << *it;
}
stream << ")";
return stream;
} }
#endif
QPixmap * kwin_get_menu_pix_hack() QPixmap * kwin_get_menu_pix_hack()
{ {

View file

@ -48,6 +48,8 @@ namespace KWinInternal
#endif #endif
#ifdef ENABLE_TRANSIENCY_CHECK #ifdef ENABLE_TRANSIENCY_CHECK
static bool transiencyCheckNonExistent = false;
bool performTransiencyCheck() bool performTransiencyCheck()
{ {
bool ret = true; bool ret = true;
@ -73,7 +75,8 @@ bool performTransiencyCheck()
it2 != mains.end(); it2 != mains.end();
++it2 ) ++it2 )
{ {
if( !Workspace::self()->clients.contains( *it2 ) if( transiencyCheckNonExistent
&& !Workspace::self()->clients.contains( *it2 )
&& !Workspace::self()->desktops.contains( *it2 )) && !Workspace::self()->desktops.contains( *it2 ))
{ {
kDebug() << "TC:" << *it1 << " has non-existent main client " << endl; kDebug() << "TC:" << *it1 << " has non-existent main client " << endl;
@ -93,7 +96,8 @@ bool performTransiencyCheck()
it2 != trans.end(); it2 != trans.end();
++it2 ) ++it2 )
{ {
if( !Workspace::self()->clients.contains( *it2 ) if( transiencyCheckNonExistent
&& !Workspace::self()->clients.contains( *it2 )
&& !Workspace::self()->desktops.contains( *it2 )) && !Workspace::self()->desktops.contains( *it2 ))
{ {
kDebug() << "TC:" << *it1 << " has non-existent transient " << endl; kDebug() << "TC:" << *it1 << " has non-existent transient " << endl;
@ -114,13 +118,16 @@ bool performTransiencyCheck()
static QString transiencyCheckStartBt; static QString transiencyCheckStartBt;
static const Client* transiencyCheckClient; static const Client* transiencyCheckClient;
static int transiencyCheck = 0; static int transiencyCheck = 0;
static void startTransiencyCheck( const QString& bt, const Client* c )
static void startTransiencyCheck( const QString& bt, const Client* c, bool ne )
{ {
if( ++transiencyCheck == 1 ) if( ++transiencyCheck == 1 )
{ {
transiencyCheckStartBt = bt; transiencyCheckStartBt = bt;
transiencyCheckClient = c; transiencyCheckClient = c;
} }
if( ne )
transiencyCheckNonExistent = true;
} }
static void checkTransiency() static void checkTransiency()
{ {
@ -132,21 +139,32 @@ static void checkTransiency()
kdDebug() << "CLIENT:" << transiencyCheckClient << endl; kdDebug() << "CLIENT:" << transiencyCheckClient << endl;
assert( false ); assert( false );
} }
transiencyCheckNonExistent = false;
} }
} }
class TransiencyChecker class TransiencyChecker
{ {
public: public:
TransiencyChecker( const QString& bt, const Client*c ) { startTransiencyCheck( bt, c ); } TransiencyChecker( const QString& bt, const Client*c ) { startTransiencyCheck( bt, c, false ); }
~TransiencyChecker() { checkTransiency(); } ~TransiencyChecker() { checkTransiency(); }
}; };
void checkNonExistentClients()
{
startTransiencyCheck( kdBacktrace(), NULL, true );
checkTransiency();
}
#define TRANSIENCY_CHECK( c ) TransiencyChecker transiency_checker( kdBacktrace(), c ) #define TRANSIENCY_CHECK( c ) TransiencyChecker transiency_checker( kdBacktrace(), c )
#else #else
#define TRANSIENCY_CHECK( c ) #define TRANSIENCY_CHECK( c )
void checkNonExistentClients()
{
}
#endif #endif
//******************************************** //********************************************

103
utils.h
View file

@ -12,32 +12,6 @@ License. See the file "COPYING" for the exact licensing terms.
#ifndef KWIN_UTILS_H #ifndef KWIN_UTILS_H
#define KWIN_UTILS_H #define KWIN_UTILS_H
#include <config.h>
#include <config-X11.h>
#include <X11/Xlib.h>
#ifdef HAVE_XRANDR
#include <X11/extensions/Xrandr.h>
#endif
#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
#include <fixx11h.h>
#include <QWidget> #include <QWidget>
#include <kmanagerselection.h> #include <kmanagerselection.h>
#include <netwm_def.h> #include <netwm_def.h>
@ -48,13 +22,6 @@ License. See the file "COPYING" for the exact licensing terms.
namespace KWinInternal namespace KWinInternal
{ {
#ifndef HAVE_XDAMAGE
typedef long Damage;
struct XDamageNotifyEvent
{
};
#endif
const int SUPPORTED_WINDOW_TYPES_MASK = NET::NormalMask | NET::DesktopMask | NET::DockMask const int SUPPORTED_WINDOW_TYPES_MASK = NET::NormalMask | NET::DesktopMask | NET::DockMask
| NET::ToolbarMask | NET::MenuMask | NET::DialogMask /*| NET::OverrideMask*/ | NET::TopMenuMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask /*| NET::OverrideMask*/ | NET::TopMenuMask
| NET::UtilityMask | NET::SplashMask; | NET::UtilityMask | NET::SplashMask;
@ -72,18 +39,12 @@ const long ClientWinMask = KeyPressMask | KeyReleaseMask |
const QPoint invalidPoint( INT_MIN, INT_MIN ); const QPoint invalidPoint( INT_MIN, INT_MIN );
class Toplevel;
class Client; class Client;
class Unmanaged;
class Group; class Group;
class Options; class Options;
typedef QList< Toplevel* > ToplevelList;
typedef QList< const Toplevel* > ConstToplevelList;
typedef QList< Client* > ClientList; typedef QList< Client* > ClientList;
typedef QList< const Client* > ConstClientList; typedef QList< const Client* > ConstClientList;
typedef QList< Unmanaged* > UnmanagedList;
typedef QList< const Unmanaged* > ConstUnmanagedList;
typedef QList< Group* > GroupList; typedef QList< Group* > GroupList;
typedef QList< const Group* > ConstGroupList; typedef QList< const Group* > ConstGroupList;
@ -126,7 +87,6 @@ enum allowed_t { Allowed };
// some enums to have more readable code, instead of using bools // some enums to have more readable code, instead of using bools
enum ForceGeometry_t { NormalGeometrySet, ForceGeometrySet }; enum ForceGeometry_t { NormalGeometrySet, ForceGeometrySet };
// Areas, mostly related to Xinerama // Areas, mostly related to Xinerama
enum clientAreaOption enum clientAreaOption
{ {
@ -149,32 +109,24 @@ enum ShadeMode
ShadeActivated // "shaded", but visible due to alt+tab to the window ShadeActivated // "shaded", but visible due to alt+tab to the window
}; };
class Extensions class Shape
{ {
public: public:
static bool available() { return kwin_shape_version > 0; }
static int version() { return kwin_shape_version; } // as 16*major+minor, i.e. two hex digits
static bool hasShape( WId w);
static int shapeEvent();
static void init(); static void init();
static bool shapeAvailable() { return has_shape; }
static int shapeNotifyEvent();
static bool randrAvailable() { return has_randr; }
static int randrNotifyEvent();
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: private:
static bool has_shape; static int kwin_shape_version;
static int shape_event_base; static int kwin_shape_event;
static bool has_randr;
static int randr_event_base;
static bool has_damage;
static int damage_event_base;
static bool has_composite;
static bool has_composite_overlay;
static bool has_fixes;
}; };
// compile with XShape older than 1.0
#ifndef ShapeInput
const int ShapeInput = 2;
#endif
class Motif class Motif
{ {
public: public:
@ -274,38 +226,34 @@ int displayHeight()
return XDisplayHeight( display(), DefaultScreen( display())); return XDisplayHeight( display(), DefaultScreen( display()));
} }
class Scene;
extern Scene* scene;
inline bool compositing() { return scene != NULL; }
// the docs say it's UrgencyHint, but it's often #defined as XUrgencyHint // the docs say it's UrgencyHint, but it's often #defined as XUrgencyHint
#ifndef UrgencyHint #ifndef UrgencyHint
#define UrgencyHint XUrgencyHint #define UrgencyHint XUrgencyHint
#endif #endif
// for STL-like algo's // for STL-like algo's
#define KWIN_CHECK_PREDICATE( name, cls, check ) \ #define KWIN_CHECK_PREDICATE( name, check ) \
struct name \ struct name \
{ \ { \
inline bool operator()( const cls* cl ) { return check; }; \ inline bool operator()( const Client* cl ) { return check; }; \
} }
#define KWIN_COMPARE_PREDICATE( name, cls, type, check ) \ #define KWIN_COMPARE_PREDICATE( name, type, check ) \
struct name \ struct name \
{ \ { \
typedef type type_helper; /* in order to work also with type being 'const Client*' etc. */ \ typedef type type_helper; /* in order to work also with type being 'const Client*' etc. */ \
inline name( const type_helper& compare_value ) : value( compare_value ) {}; \ inline name( const type_helper& compare_value ) : value( compare_value ) {}; \
inline bool operator()( const cls* cl ) { return check; }; \ inline bool operator()( const Client* cl ) { return check; }; \
const type_helper& value; \ const type_helper& value; \
} }
#define KWIN_PROCEDURE( name, cls, action ) \ #define KWIN_PROCEDURE( name, action ) \
struct name \ struct name \
{ \ { \
inline void operator()( cls* cl ) { action; }; \ inline void operator()( Client* cl ) { action; }; \
} }
KWIN_CHECK_PREDICATE( TruePredicate, Client, cl == cl /*true, avoid warning about 'cl' */ ); KWIN_CHECK_PREDICATE( TruePredicate, cl == cl /*true, avoid warning about 'cl' */ );
template< typename T > template< typename T >
Client* findClientInList( const ClientList& list, T predicate ) Client* findClientInList( const ClientList& list, T predicate )
@ -318,17 +266,6 @@ Client* findClientInList( const ClientList& list, T predicate )
return NULL; return NULL;
} }
template< typename T >
Unmanaged* findUnmanagedInList( const UnmanagedList& list, T predicate )
{
for ( UnmanagedList::ConstIterator it = list.begin(); it != list.end(); ++it)
{
if ( predicate( const_cast< const Unmanaged* >( *it)))
return *it;
}
return NULL;
}
inline inline
int timestampCompare( Time time1, Time time2 ) // like strcmp() int timestampCompare( Time time1, Time time2 ) // like strcmp()
{ {
@ -343,6 +280,8 @@ Time timestampDiff( Time time1, Time time2 ) // returns time2 - time1
bool isLocalMachine( const QByteArray& host ); bool isLocalMachine( const QByteArray& host );
void checkNonExistentClients();
#ifndef KCMRULES #ifndef KCMRULES
// Qt dialogs emit no signal when closed :( // Qt dialogs emit no signal when closed :(
class ShortcutDialog class ShortcutDialog

View file

@ -516,6 +516,7 @@ void Workspace::addClient( Client* c, allowed_t )
updateStackingOrder( true ); // propagate new client updateStackingOrder( true ); // propagate new client
if( c->isUtility() || c->isMenu() || c->isToolbar()) if( c->isUtility() || c->isMenu() || c->isToolbar())
updateToolWindows( true ); updateToolWindows( true );
checkNonExistentClients();
} }
/* /*