Preliminary support for avoiding covering clients such as kicker
which want to be permanently visible. I've used an XAtom called '_NET_AVOID_SPEC'. This of course can change if need be. I think it's correct according to the wm spec, but the wm spec seems to be empty on gnome.org, so who knows. Windows can choose to be avoided by setting an XTextProperty with one value, which can be either 'N', 'S', 'E', or 'W', according to which screen edge they are anchored to. kwin then sets its 'clientArea' rect appropriately, so that (in theory at least) clients will not enter this area in some circumstances, such as when being mapped for the first time. You can see that this actually works if you start lots of konsoles. They don't appear over the panel. I don't know what happens if you move the panel, but I presume things will be screwed up, because I haven't looked at that yet. If you maximise a window, it'll still fill the screen, because the implementation of maximise in kwin/client.cpp doesn't take account of the workspace's clientArea rect. This is easy to fix, but I've been awake for too long, so I'll do it after 42 winks. svn path=/trunk/kdebase/kwin/; revision=46772
This commit is contained in:
parent
1f394879df
commit
330ea804b2
4 changed files with 153 additions and 4 deletions
56
client.cpp
56
client.cpp
|
@ -320,9 +320,10 @@ bool WindowWrapper::x11Event( XEvent * e)
|
||||||
Creates a client on workspace \a ws for window \a w.
|
Creates a client on workspace \a ws for window \a w.
|
||||||
*/
|
*/
|
||||||
Client::Client( Workspace *ws, WId w, QWidget *parent, const char *name, WFlags f )
|
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;
|
wspace = ws;
|
||||||
win = w;
|
win = w;
|
||||||
XWindowAttributes attr;
|
XWindowAttributes attr;
|
||||||
|
@ -359,6 +360,56 @@ Client::Client( Workspace *ws, WId w, QWidget *parent, const char *name, WFlags
|
||||||
if ( mainClient()->isSticky() )
|
if ( mainClient()->isSticky() )
|
||||||
setSticky( TRUE );
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NoBorderClient::NoBorderClient( Workspace *ws, WId w, QWidget *parent, const char *name )
|
NoBorderClient::NoBorderClient( Workspace *ws, WId w, QWidget *parent, const char *name )
|
||||||
: Client( ws, w, parent, name )
|
: Client( ws, w, parent, name )
|
||||||
{
|
{
|
||||||
|
|
6
client.h
6
client.h
|
@ -63,6 +63,9 @@ public:
|
||||||
bool isTransient() const;
|
bool isTransient() const;
|
||||||
Client* mainClient();
|
Client* mainClient();
|
||||||
|
|
||||||
|
bool avoid() const { return avoid_; }
|
||||||
|
int anchorEdge() const { return anchorEdge_; }
|
||||||
|
|
||||||
virtual bool windowEvent( XEvent * );
|
virtual bool windowEvent( XEvent * );
|
||||||
|
|
||||||
void manage( bool isMapped = FALSE );
|
void manage( bool isMapped = FALSE );
|
||||||
|
@ -230,6 +233,9 @@ private:
|
||||||
QPixmap miniicon_pix;
|
QPixmap miniicon_pix;
|
||||||
QRect geom_restore;
|
QRect geom_restore;
|
||||||
QRegion mask;
|
QRegion mask;
|
||||||
|
|
||||||
|
bool avoid_;
|
||||||
|
int anchorEdge_;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline WId Client::window() const
|
inline WId Client::window() const
|
||||||
|
|
|
@ -247,6 +247,7 @@ void Workspace::init()
|
||||||
inf.row = 0;
|
inf.row = 0;
|
||||||
cci.append(inf);
|
cci.append(inf);
|
||||||
}
|
}
|
||||||
|
updateClientArea();
|
||||||
}
|
}
|
||||||
|
|
||||||
Workspace::~Workspace()
|
Workspace::~Workspace()
|
||||||
|
@ -339,6 +340,7 @@ bool Workspace::workspaceEvent( XEvent * e )
|
||||||
if ( addDockwin( e->xmaprequest.window ) )
|
if ( addDockwin( e->xmaprequest.window ) )
|
||||||
return TRUE;
|
return TRUE;
|
||||||
c = clientFactory( this, e->xmaprequest.window );
|
c = clientFactory( this, e->xmaprequest.window );
|
||||||
|
updateClientArea();
|
||||||
if ( root != qt_xrootwin() ) {
|
if ( root != qt_xrootwin() ) {
|
||||||
// TODO may use QWidget:.create
|
// TODO may use QWidget:.create
|
||||||
XReparentWindow( qt_xdisplay(), c->winId(), root, 0, 0 );
|
XReparentWindow( qt_xdisplay(), c->winId(), root, 0, 0 );
|
||||||
|
@ -500,7 +502,7 @@ QRect Workspace::geometry() const
|
||||||
*/
|
*/
|
||||||
QRect Workspace::clientArea() 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
|
Raises the client \a c taking layers, transient windows and window
|
||||||
groups into account.
|
groups into account.
|
||||||
|
@ -2047,6 +2097,7 @@ void Workspace::slotResetAllClients()
|
||||||
delete oldClient;
|
delete oldClient;
|
||||||
newClient->manage( TRUE );
|
newClient->manage( TRUE );
|
||||||
}
|
}
|
||||||
|
updateClientArea();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -2117,3 +2168,39 @@ SessionInfo* Workspace::takeSessionInfo( Client* c )
|
||||||
|
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,8 @@ class KGlobalAccel;
|
||||||
|
|
||||||
typedef QValueList<Client*> ClientList;
|
typedef QValueList<Client*> ClientList;
|
||||||
|
|
||||||
|
enum AnchorEdge { AnchorNorth, AnchorSouth, AnchorEast, AnchorWest };
|
||||||
|
|
||||||
class DockWindow
|
class DockWindow
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -100,6 +102,7 @@ public:
|
||||||
void doPlacement( Client* c );
|
void doPlacement( Client* c );
|
||||||
QPoint adjustClientPosition( Client* c, QPoint pos );
|
QPoint adjustClientPosition( Client* c, QPoint pos );
|
||||||
void raiseClient( Client* c );
|
void raiseClient( Client* c );
|
||||||
|
void lowerClient( Client* c );
|
||||||
|
|
||||||
void clientHidden( Client* );
|
void clientHidden( Client* );
|
||||||
|
|
||||||
|
@ -234,6 +237,9 @@ private:
|
||||||
Atom kwm_command;
|
Atom kwm_command;
|
||||||
|
|
||||||
PluginMgr mgr;
|
PluginMgr mgr;
|
||||||
|
|
||||||
|
void updateClientArea();
|
||||||
|
QRect clientArea_;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline WId Workspace::rootWin() const
|
inline WId Workspace::rootWin() const
|
||||||
|
|
Loading…
Reference in a new issue