diff --git a/client.cpp b/client.cpp index 95957e72f8..e4d99a4114 100644 --- a/client.cpp +++ b/client.cpp @@ -320,9 +320,10 @@ bool WindowWrapper::x11Event( XEvent * e) Creates a client on workspace \a ws for window \a w. */ Client::Client( Workspace *ws, WId w, QWidget *parent, const char *name, WFlags f ) - : QWidget( parent, name, f | WStyle_Customize | WStyle_NoBorder ) + : QWidget( parent, name, f | WStyle_Customize | WStyle_NoBorder ), + avoid_(false), + anchorEdge_(AnchorNorth) { - wspace = ws; win = w; XWindowAttributes attr; @@ -359,6 +360,56 @@ Client::Client( Workspace *ws, WId w, QWidget *parent, const char *name, WFlags if ( mainClient()->isSticky() ) setSticky( TRUE ); + // Find out if we should be avoided. + + // If this atom isn't set, set it now. + Atom avoidAtom = XInternAtom(qt_xdisplay(), "_NET_AVOID_SPEC", False); + + XTextProperty avoidProp; + + Status avoidStatus = + XGetTextProperty(qt_xdisplay(), w, &avoidProp, avoidAtom); + + if (0 != avoidStatus) { + + char ** avoidList; + int avoidListCount; + + Status convertStatus = + XTextPropertyToStringList(&avoidProp, &avoidList, &avoidListCount); + + if (0 != convertStatus) { + + avoid_ = true; + + if (avoidListCount != 1) { +// qDebug("Extra values in avoidance list. Ignoring."); + } + + char * itemZero = avoidList[0]; + + switch (*itemZero) { + + case 'N': + anchorEdge_ = AnchorNorth; + break; + case 'S': + anchorEdge_ = AnchorSouth; + break; + case 'E': + anchorEdge_ = AnchorEast; + break; + case 'W': + anchorEdge_ = AnchorWest; + break; + default: + anchorEdge_ = AnchorNorth; + break; + } + + XFreeStringList(avoidList); + } + } } /*! @@ -1848,7 +1899,6 @@ QCString Client::sessionId() return result; } - NoBorderClient::NoBorderClient( Workspace *ws, WId w, QWidget *parent, const char *name ) : Client( ws, w, parent, name ) { diff --git a/client.h b/client.h index 02f7323817..f4d0e5d818 100644 --- a/client.h +++ b/client.h @@ -63,6 +63,9 @@ public: bool isTransient() const; Client* mainClient(); + bool avoid() const { return avoid_; } + int anchorEdge() const { return anchorEdge_; } + virtual bool windowEvent( XEvent * ); void manage( bool isMapped = FALSE ); @@ -230,6 +233,9 @@ private: QPixmap miniicon_pix; QRect geom_restore; QRegion mask; + + bool avoid_; + int anchorEdge_; }; inline WId Client::window() const diff --git a/workspace.cpp b/workspace.cpp index ff36965ce6..7d7eea3452 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -247,6 +247,7 @@ void Workspace::init() inf.row = 0; cci.append(inf); } + updateClientArea(); } Workspace::~Workspace() @@ -339,6 +340,7 @@ bool Workspace::workspaceEvent( XEvent * e ) if ( addDockwin( e->xmaprequest.window ) ) return TRUE; c = clientFactory( this, e->xmaprequest.window ); + updateClientArea(); if ( root != qt_xrootwin() ) { // TODO may use QWidget:.create XReparentWindow( qt_xdisplay(), c->winId(), root, 0, 0 ); @@ -500,7 +502,7 @@ QRect Workspace::geometry() const */ QRect Workspace::clientArea() const { - return geometry(); // for now + return clientArea_; } @@ -1312,6 +1314,54 @@ void Workspace::deskCleanup(CleanupType ct) } } +/*! + Lowers the client \a c taking layers, transient windows and window + groups into account. + */ +void Workspace::lowerClient( Client* c ) +{ + if ( !c ) + return; + + if ( c == desktop_client ) + return; // deny + + stacking_order.remove( c ); + stacking_order.prepend( c ); + + // Not sure what this is doing. Disable for now. +#if 0 + ClientList saveset; + + if ( c->transientFor() ) { + + saveset.append( c ); + Client* t = findClient( c->transientFor() ); + Client* tmp; + while ( t && !saveset.contains( t ) && t->transientFor() ) { + tmp = findClient( t->transientFor() ); + if ( !tmp ) + break; + saveset.append( t ); + t = tmp; + } + if ( t && !saveset.contains( t ) && t != desktop_client ) { + raiseClient( t ); + return; + } + } + + saveset.clear(); + saveset.append( c ); + raiseTransientsOf(saveset, c ); +#endif + + XLowerWindow(qt_xdisplay(), c->winId()); + + propagateClients( TRUE ); +} + + /*! Raises the client \a c taking layers, transient windows and window groups into account. @@ -2047,6 +2097,7 @@ void Workspace::slotResetAllClients() delete oldClient; newClient->manage( TRUE ); } + updateClientArea(); } /*! @@ -2117,3 +2168,39 @@ SessionInfo* Workspace::takeSessionInfo( Client* c ) return 0; } + + void +Workspace::updateClientArea() +{ + clientArea_ = geometry(); + + for (ClientList::ConstIterator it(clients.begin()); it != clients.end(); ++it) + { + if ((*it)->avoid()) { + + switch (AnchorEdge((*it)->anchorEdge())) { + + case AnchorNorth: + clientArea_ + .setTop(QMAX(clientArea_.top(), (*it)->geometry().bottom())); + break; + + case AnchorSouth: + clientArea_ + .setBottom(QMIN(clientArea_.bottom(), (*it)->geometry().top())); + break; + + case AnchorEast: + clientArea_ + .setRight(QMIN(clientArea_.right(), (*it)->geometry().left())); + break; + + case AnchorWest: + clientArea_ + .setLeft(QMAX(clientArea_.left(), (*it)->geometry().right())); + break; + } + } + } +} + diff --git a/workspace.h b/workspace.h index 4c4f3df2d9..a82965aa7a 100644 --- a/workspace.h +++ b/workspace.h @@ -23,6 +23,8 @@ class KGlobalAccel; typedef QValueList ClientList; +enum AnchorEdge { AnchorNorth, AnchorSouth, AnchorEast, AnchorWest }; + class DockWindow { public: @@ -100,6 +102,7 @@ public: void doPlacement( Client* c ); QPoint adjustClientPosition( Client* c, QPoint pos ); void raiseClient( Client* c ); + void lowerClient( Client* c ); void clientHidden( Client* ); @@ -234,6 +237,9 @@ private: Atom kwm_command; PluginMgr mgr; + + void updateClientArea(); + QRect clientArea_; }; inline WId Workspace::rootWin() const