diff --git a/client.cpp b/client.cpp index d9554ba956..194e15236b 100644 --- a/client.cpp +++ b/client.cpp @@ -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 ); diff --git a/client.h b/client.h index 47174bcbeb..6a3a38b33b 100644 --- a/client.h +++ b/client.h @@ -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; diff --git a/workspace.cpp b/workspace.cpp index 32f7f3a4f4..a16185af72 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -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 *)¤t_desktop, 1); + + QApplication::syncX(); KWM::switchToDesktop( current_desktop ); // ### compatibility } diff --git a/workspace.h b/workspace.h index 707f8a8ab1..7e2d1a0d3c 100644 --- a/workspace.h +++ b/workspace.h @@ -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;