found a smart way to get rid of the race conditions (that sometimes

made windows lose their decorations)

svn path=/trunk/kdebase/kwin/; revision=33867
This commit is contained in:
Matthias Ettrich 1999-11-15 00:52:05 +00:00
parent 49eb95bd94
commit 3293927ed4
4 changed files with 56 additions and 16 deletions

View file

@ -117,15 +117,15 @@ WindowWrapper::WindowWrapper( WId w, Client *parent, const char* name)
EnterWindowMask | LeaveWindowMask |
FocusChangeMask |
ExposureMask |
StructureNotifyMask |
StructureNotifyMask |
SubstructureRedirectMask |
SubstructureNotifyMask
);
XSelectInput( qt_xdisplay(), w,
FocusChangeMask |
PropertyChangeMask |
StructureNotifyMask
PropertyChangeMask
// StructureNotifyMask
);
// install a passive grab to catch mouse button events
@ -172,7 +172,7 @@ void WindowWrapper::showEvent( QShowEvent* )
void WindowWrapper::hideEvent( QHideEvent* )
{
if ( win )
XUnmapWindow( qt_xdisplay(), win );
XUnmapWindow( qt_xdisplay(), win );
}
void WindowWrapper::invalidateWindow()
@ -253,13 +253,13 @@ Client::Client( Workspace *ws, WId w, QWidget *parent, const char *name, WFlags
: QWidget( parent, name, f | WStyle_Customize | WStyle_NoBorder )
{
reparented = FALSE;
wspace = ws;
win = w;
XWindowAttributes attr;
if (XGetWindowAttributes(qt_xdisplay(), win, &attr)){
original_geometry.setRect(attr.x, attr.y, attr.width, attr.height );
}
mapped = 0;
wwrap = new WindowWrapper( w, this );
wwrap->installEventFilter( this );
@ -417,7 +417,17 @@ bool Client::windowEvent( XEvent * e)
{
switch (e->type) {
case UnmapNotify:
if ( e->xunmap.window == winId() ) {
mapped = 0;
return FALSE;
}
return unmapNotify( e->xunmap );
case MapNotify:
if ( e->xmap.window == winId() ) {
mapped = 1;
return FALSE;
}
break;
case MapRequest:
return mapRequest( e->xmaprequest );
case ConfigureRequest:
@ -445,7 +455,6 @@ bool Client::windowEvent( XEvent * e)
setActive( FALSE );
break;
case ReparentNotify:
reparented = TRUE;
break;
default:
break;
@ -482,6 +491,9 @@ bool Client::mapRequest( XMapRequestEvent& /* e */ )
bool Client::unmapNotify( XUnmapEvent& e )
{
if ( e.event != windowWrapper()->winId() && !e.send_event )
return TRUE;
switch ( mappingState() ) {
case IconicState:
// only react on sent events, all others are produced by us
@ -489,14 +501,11 @@ bool Client::unmapNotify( XUnmapEvent& e )
withdraw();
break;
case NormalState:
if ( !reparented )
return TRUE; // we produced this event
if ( !windowWrapper()->isVisible() && !e.send_event )
return TRUE; // this event was produced by us as well
if ( !mapped && !e.send_event )
return TRUE; // this event was produced by us as well
// maybe we will be destroyed soon. Check this first.
XEvent ev;
QApplication::syncX();
if ( XCheckTypedWindowEvent (qt_xdisplay(), win,
DestroyNotify, &ev) ){
workspace()->destroyClient( this );

View file

@ -130,8 +130,8 @@ public:
void move( int x, int y );
void move( const QPoint & p )
{ move( p.x(), p.y() ); }
public slots:
void iconify();
@ -203,7 +203,6 @@ private:
void sendSynteticConfigureNotify();
int state;
bool active;
bool reparented;
QRect original_geometry;
QRect geom; //### TODO
bool shaded;
@ -214,6 +213,7 @@ private:
void getWindowProtocols();
uint Pdeletewindow :1; // does the window understand the DeleteWindow protocol?
uint Ptakefocus :1;// does the window understand the TakeFocus protocol?
uint mapped :1; // keeps track of our visiblity within the asynchronous event flow
QPixmap icon_pix;
QPixmap miniicon_pix;
QRect geom_restore;

View file

@ -222,7 +222,7 @@ bool Workspace::workspaceEvent( XEvent * e )
break;
case UnmapNotify:
// this is special due to
// SubstructureRedirectMask. e->xany.window is the window the
// SubstructureNotifyMask. e->xany.window is the window the
// event is reported to. Take care not to confuse Qt.
c = findClient( e->xunmap.window );
@ -233,8 +233,24 @@ bool Workspace::workspaceEvent( XEvent * e )
if ( removeDockwin( e->xunmap.window ) )
return TRUE;
if ( e->xunmap.event == root ) {
// keep track of map/unmap for own own windows to avoid
// race conditions
c = findClientWidthId( e->xunmap.window );
if ( c )
return c->windowEvent( e );
}
if ( e->xunmap.event != e->xunmap.window ) // hide wm typical event from Qt
return TRUE;
case MapNotify:
if ( e->xunmap.event == root ) {
// keep track of map/unmap for own own windows to avoid
// race conditions
c = findClientWidthId( e->xmap.window );
if ( c )
return c->windowEvent( e );
}
case ReparentNotify:
c = findClient( e->xreparent.window );
if ( c )
@ -337,6 +353,18 @@ Client* Workspace::findClient( WId w ) const
return 0;
}
/*!
Finds the client with window id \a w
*/
Client* Workspace::findClientWidthId( WId w ) const
{
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) {
if ( (*it)->winId() == w )
return *it;
}
return 0;
}
/*!
Returns the workspace's geometry
@ -980,6 +1008,8 @@ void Workspace::setCurrentDesktop( int new_desktop ){
XChangeProperty(qt_xdisplay(), qt_xrootwin(),
atoms->net_current_desktop, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *)&current_desktop, 1);
QApplication::syncX();
KWM::switchToDesktop( current_desktop ); // ### compatibility
}

View file

@ -26,7 +26,7 @@ public:
DockWindow( WId w, WId wf )
: dockWin(w),dockFor(wf)
{}
bool operator==( const DockWindow& other )
{ return dockWin == other.dockWin; }
WId dockWin;
@ -138,6 +138,7 @@ private:
Client* desktop_client;
int current_desktop;
int number_of_desktops;
Client* findClientWidthId( WId w ) const;
Client* popup_client;
QWidget* desktop_widget;