Fix Xinerama placement. Thanks to Malte S. Stretz for help with debugging
and testing. svn path=/trunk/kdebase/kwin/; revision=278437
This commit is contained in:
parent
9fbfe0a925
commit
24cae23c66
6 changed files with 95 additions and 77 deletions
1
client.h
1
client.h
|
@ -206,6 +206,7 @@ class Client : public QObject, public KDecorationDefines
|
|||
// plainResize() simply resizes
|
||||
void plainResize( int w, int h, ForceGeometry_t force = NormalGeometrySet );
|
||||
void plainResize( const QSize& s, ForceGeometry_t force = NormalGeometrySet );
|
||||
void keepInArea( const QRect& area );
|
||||
|
||||
void growHorizontal();
|
||||
void shrinkHorizontal();
|
||||
|
|
29
geometry.cpp
29
geometry.cpp
|
@ -312,6 +312,7 @@ void Workspace::setClientIsMoving( Client *c )
|
|||
*/
|
||||
void Workspace::cascadeDesktop()
|
||||
{
|
||||
// TODO XINERAMA this probably is not right for xinerama
|
||||
Q_ASSERT( block_stacking_updates == 0 );
|
||||
ClientList::ConstIterator it(stackingOrder().begin());
|
||||
bool re_init_cascade_at_first_client = true;
|
||||
|
@ -322,7 +323,7 @@ void Workspace::cascadeDesktop()
|
|||
((*it)->isOnAllDesktops()) ||
|
||||
(!(*it)->isMovable()) )
|
||||
continue;
|
||||
initPositioning->placeCascaded(*it, re_init_cascade_at_first_client);
|
||||
initPositioning->placeCascaded(*it, QRect(), re_init_cascade_at_first_client);
|
||||
//CT is an if faster than an attribution??
|
||||
if (re_init_cascade_at_first_client)
|
||||
re_init_cascade_at_first_client = false;
|
||||
|
@ -343,7 +344,7 @@ void Workspace::unclutterDesktop()
|
|||
((*it)->isOnAllDesktops()) ||
|
||||
(!(*it)->isMovable()) )
|
||||
continue;
|
||||
initPositioning->placeSmart(*it);
|
||||
initPositioning->placeSmart(*it, QRect());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -387,6 +388,24 @@ void Workspace::updateTopMenuGeometry( Client* c )
|
|||
//********************************************
|
||||
|
||||
|
||||
void Client::keepInArea( const QRect& area )
|
||||
{
|
||||
if ( geometry().right() > area.right() && width() < area.width() )
|
||||
move( area.right() - width(), y() );
|
||||
if ( geometry().bottom() > area.bottom() && height() < area.height() )
|
||||
move( x(), area.bottom() - height() );
|
||||
if( !area.contains( geometry().topLeft() ))
|
||||
{
|
||||
int tx = x();
|
||||
int ty = y();
|
||||
if ( tx < area.x() )
|
||||
tx = area.x();
|
||||
if ( ty < area.y() )
|
||||
ty = area.y();
|
||||
move( tx, ty );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \a area with the client's strut taken into account.
|
||||
|
||||
|
@ -1271,7 +1290,7 @@ void Client::changeMaximize( bool vertical, bool horizontal, bool adjust )
|
|||
if( geom_restore.width() == 0 )
|
||||
{ // needs placement
|
||||
plainResize( adjustedSize(QSize(width(), clientArea.height()), SizemodeFixedH ));
|
||||
workspace()->placeSmart( this );
|
||||
workspace()->placeSmart( this, clientArea );
|
||||
}
|
||||
else
|
||||
setGeometry( QRect(QPoint( geom_restore.x(), clientArea.top()),
|
||||
|
@ -1291,7 +1310,7 @@ void Client::changeMaximize( bool vertical, bool horizontal, bool adjust )
|
|||
if( geom_restore.height() == 0 )
|
||||
{ // needs placement
|
||||
plainResize( adjustedSize(QSize(clientArea.width(), height()), SizemodeFixedW ));
|
||||
workspace()->placeSmart( this );
|
||||
workspace()->placeSmart( this, clientArea );
|
||||
}
|
||||
else
|
||||
setGeometry( QRect( QPoint(clientArea.left(), geom_restore.y()),
|
||||
|
@ -1326,7 +1345,7 @@ void Client::changeMaximize( bool vertical, bool horizontal, bool adjust )
|
|||
if( geom_restore.height() > 0 )
|
||||
s.setHeight( geom_restore.height());
|
||||
plainResize( adjustedSize( s ));
|
||||
workspace()->placeSmart( this );
|
||||
workspace()->placeSmart( this, clientArea );
|
||||
restore = geometry();
|
||||
if( geom_restore.width() > 0 )
|
||||
restore.moveLeft( geom_restore.x());
|
||||
|
|
23
manage.cpp
23
manage.cpp
|
@ -182,7 +182,9 @@ bool Client::manage( Window w, bool isMapped )
|
|||
geom = session->geometry;
|
||||
|
||||
QRect area;
|
||||
if( !isMapped && options->xineramaPlacementEnabled )
|
||||
if( isMapped )
|
||||
area = workspace()->clientArea( WorkArea, geom.center(), desktop());
|
||||
else if( options->xineramaPlacementEnabled )
|
||||
area = workspace()->clientArea( PlacementArea, QCursor::pos(), desktop());
|
||||
else
|
||||
area = workspace()->clientArea( PlacementArea, geom.center(), desktop());
|
||||
|
@ -263,27 +265,12 @@ bool Client::manage( Window w, bool isMapped )
|
|||
|
||||
if( !placementDone )
|
||||
{ // placement needs to be after setting size
|
||||
workspace()->place( this );
|
||||
workspace()->place( this, area );
|
||||
placementDone = TRUE;
|
||||
}
|
||||
|
||||
if (( !isSpecialWindow() || isToolbar()) && isMovable())
|
||||
{
|
||||
if ( geometry().right() > area.right() && width() < area.width() )
|
||||
move( area.right() - width(), y() );
|
||||
if ( geometry().bottom() > area.bottom() && height() < area.height() )
|
||||
move( x(), area.bottom() - height() );
|
||||
if( !area.contains( geometry().topLeft() ))
|
||||
{
|
||||
int tx = x();
|
||||
int ty = y();
|
||||
if ( tx < area.x() )
|
||||
tx = area.x();
|
||||
if ( ty < area.y() )
|
||||
ty = area.y();
|
||||
move( tx, ty );
|
||||
}
|
||||
}
|
||||
keepInArea( area );
|
||||
|
||||
XShapeSelectInput( qt_xdisplay(), window(), ShapeNotifyMask );
|
||||
if ( (is_shape = Shape::hasShape( window())) )
|
||||
|
|
|
@ -40,38 +40,38 @@ Placement::Placement(Workspace* w)
|
|||
/*!
|
||||
Places the client \a c according to the workspace's layout policy
|
||||
*/
|
||||
void Placement::place(Client* c)
|
||||
void Placement::place(Client* c, QRect& area )
|
||||
{
|
||||
if( c->isUtility())
|
||||
placeUtility(c);
|
||||
placeUtility(c, area);
|
||||
else if( c->isDialog())
|
||||
placeDialog(c);
|
||||
placeDialog(c, area);
|
||||
else if( c->isSplash())
|
||||
placeOnMainWindow( c ); // on mainwindow, if any, otherwise centered
|
||||
placeOnMainWindow( c, area ); // on mainwindow, if any, otherwise centered
|
||||
else
|
||||
placeInternal(c);
|
||||
placeInternal(c, area);
|
||||
}
|
||||
|
||||
void Placement::placeInternal(Client* c)
|
||||
void Placement::placeInternal(Client* c, const QRect& area )
|
||||
{
|
||||
if (options->placement == Options::Random) placeAtRandom(c);
|
||||
else if (options->placement == Options::Cascade) placeCascaded(c);
|
||||
else if (options->placement == Options::Centered) placeCentered(c);
|
||||
else if (options->placement == Options::ZeroCornered) placeZeroCornered(c);
|
||||
else placeSmart(c);
|
||||
if (options->placement == Options::Random) placeAtRandom(c, area);
|
||||
else if (options->placement == Options::Cascade) placeCascaded(c, area);
|
||||
else if (options->placement == Options::Centered) placeCentered(c, area);
|
||||
else if (options->placement == Options::ZeroCornered) placeZeroCornered(c, area);
|
||||
else placeSmart(c, area);
|
||||
}
|
||||
|
||||
/*!
|
||||
Place the client \a c according to a simply "random" placement algorithm.
|
||||
*/
|
||||
void Placement::placeAtRandom(Client* c)
|
||||
void Placement::placeAtRandom(Client* c, const QRect& area )
|
||||
{
|
||||
const int step = 24;
|
||||
static int px = step;
|
||||
static int py = 2 * step;
|
||||
int tx,ty;
|
||||
|
||||
const QRect maxRect = m_WorkspacePtr->clientArea( PlacementArea, c );
|
||||
const QRect maxRect = checkArea( c, area );
|
||||
|
||||
if (px < maxRect.x())
|
||||
px = maxRect.x();
|
||||
|
@ -107,7 +107,7 @@ void Placement::placeAtRandom(Client* c)
|
|||
/*!
|
||||
Place the client \a c according to a really smart placement algorithm :-)
|
||||
*/
|
||||
void Placement::placeSmart(Client* c)
|
||||
void Placement::placeSmart(Client* c, const QRect& area )
|
||||
{
|
||||
/*
|
||||
* SmartPlacement by Cristian Tibirna (tibirna@kde.org)
|
||||
|
@ -129,7 +129,7 @@ void Placement::placeSmart(Client* c)
|
|||
int basket; //temp holder
|
||||
|
||||
// get the maximum allowed windows space
|
||||
const QRect maxRect = m_WorkspacePtr->clientArea( PlacementArea, c );
|
||||
const QRect maxRect = checkArea( c, area );
|
||||
int x = maxRect.left(), y = maxRect.top();
|
||||
x_optimal = x; y_optimal = y;
|
||||
|
||||
|
@ -278,7 +278,7 @@ void Placement::placeSmart(Client* c)
|
|||
/*!
|
||||
Place windows in a cascading order, remembering positions for each desktop
|
||||
*/
|
||||
void Placement::placeCascaded (Client* c, bool re_init)
|
||||
void Placement::placeCascaded (Client* c, const QRect& area, bool re_init)
|
||||
{
|
||||
/* cascadePlacement by Cristian Tibirna (tibirna@kde.org) (30Jan98)
|
||||
*/
|
||||
|
@ -292,8 +292,7 @@ void Placement::placeCascaded (Client* c, bool re_init)
|
|||
const int dn = c->desktop() == 0 || c->isOnAllDesktops() ? (m_WorkspacePtr->currentDesktop() - 1) : (c->desktop() - 1);
|
||||
|
||||
// get the maximum allowed windows space and desk's origin
|
||||
// (CT 20Nov1999 - is this common to all desktops?)
|
||||
QRect maxRect = m_WorkspacePtr->clientArea( PlacementArea, c );
|
||||
QRect maxRect = checkArea( c, area );
|
||||
|
||||
// initialize often used vars: width and height of c; we gain speed
|
||||
const int ch = c->height();
|
||||
|
@ -320,7 +319,7 @@ void Placement::placeCascaded (Client* c, bool re_init)
|
|||
if ((xp + cw) > W)
|
||||
if (!yp)
|
||||
{
|
||||
placeSmart(c);
|
||||
placeSmart(c,area);
|
||||
return;
|
||||
}
|
||||
else xp = X;
|
||||
|
@ -349,7 +348,7 @@ void Placement::placeCascaded (Client* c, bool re_init)
|
|||
// last resort: if still doesn't fit, smart place it
|
||||
if (((xp + cw) > W - X) || ((yp + ch) > H - Y))
|
||||
{
|
||||
placeSmart(c);
|
||||
placeSmart(c,area);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -364,12 +363,11 @@ void Placement::placeCascaded (Client* c, bool re_init)
|
|||
/*!
|
||||
Place windows centered, on top of all others
|
||||
*/
|
||||
void Placement::placeCentered (Client* c)
|
||||
void Placement::placeCentered (Client* c, const QRect& area )
|
||||
{
|
||||
|
||||
// get the maximum allowed windows space and desk's origin
|
||||
// (CT 20Nov1999 - is this common to all desktops?)
|
||||
const QRect maxRect = m_WorkspacePtr->clientArea( PlacementArea, c );
|
||||
const QRect maxRect = checkArea( c, area );
|
||||
|
||||
const int xp = maxRect.left() + (maxRect.width() - c->width()) / 2;
|
||||
const int yp = maxRect.top() + (maxRect.height() - c->height()) / 2;
|
||||
|
@ -381,69 +379,73 @@ void Placement::placeCentered (Client* c)
|
|||
/*!
|
||||
Place windows in the (0,0) corner, on top of all others
|
||||
*/
|
||||
void Placement::placeZeroCornered(Client* c)
|
||||
void Placement::placeZeroCornered(Client* c, const QRect& area )
|
||||
{
|
||||
// get the maximum allowed windows space and desk's origin
|
||||
// (CT 20Nov1999 - is this common to all desktops?)
|
||||
const QRect maxRect = m_WorkspacePtr->clientArea( PlacementArea, c );
|
||||
const QRect maxRect = checkArea( c, area );
|
||||
|
||||
// place the window
|
||||
c->move(QPoint(maxRect.left(), maxRect.top()));
|
||||
}
|
||||
|
||||
void Placement::placeUtility(Client* c)
|
||||
void Placement::placeUtility(Client* c, QRect& area )
|
||||
{
|
||||
// TODO kwin should try to place utility windows next to their mainwindow,
|
||||
// preferably at the right edge, and going down if there are more of them
|
||||
// if there's not enough place outside the mainwindow, it should prefer
|
||||
// top-right corner
|
||||
// use the default placement for now
|
||||
placeInternal( c );
|
||||
placeInternal( c, area );
|
||||
}
|
||||
|
||||
|
||||
void Placement::placeDialog(Client* c)
|
||||
void Placement::placeDialog(Client* c, QRect& area )
|
||||
{
|
||||
// if the dialog is actually non-NETWM transient window, don't apply placement to it,
|
||||
// it breaks with too many things (xmms, display)
|
||||
if( !c->hasNETSupport())
|
||||
return;
|
||||
placeOnMainWindow( c );
|
||||
placeOnMainWindow( c, area );
|
||||
}
|
||||
|
||||
void Placement::placeUnderMouse(Client* c)
|
||||
void Placement::placeUnderMouse(Client* c, QRect& area )
|
||||
{
|
||||
area = checkArea( c, area );
|
||||
QRect geom = c->geometry();
|
||||
geom.moveCenter( QCursor::pos());
|
||||
c->move( geom.topLeft());
|
||||
c->keepInArea( area ); // make sure it's kept inside workarea
|
||||
}
|
||||
|
||||
void Placement::placeOnMainWindow(Client* c)
|
||||
void Placement::placeOnMainWindow(Client* c, QRect& area )
|
||||
{
|
||||
area = checkArea( c, area );
|
||||
ClientList mainwindows = c->mainClients();
|
||||
Client* place_on = NULL;
|
||||
int mains_count = 0;
|
||||
for( ClientList::ConstIterator it = mainwindows.begin();
|
||||
it != mainwindows.end();
|
||||
++it )
|
||||
{
|
||||
if( (*it)->isSpecialWindow() && !(*it)->isOverride())
|
||||
continue; // don't consider toolbars etc when placing
|
||||
++mains_count;
|
||||
if( (*it)->isOnCurrentDesktop())
|
||||
{
|
||||
if( place_on == NULL )
|
||||
place_on = *it;
|
||||
else
|
||||
{ // two or more on current desktop -> center
|
||||
placeCentered( c );
|
||||
placeCentered( c, area );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( place_on == NULL )
|
||||
{
|
||||
if( mainwindows.count() != 1 )
|
||||
{ // 'mains_count' is used because it doesn't include ignored mainwindows
|
||||
if( mains_count != 1 )
|
||||
{
|
||||
placeCentered( c );
|
||||
placeCentered( c, area );
|
||||
return;
|
||||
}
|
||||
place_on = mainwindows.first();
|
||||
|
@ -451,6 +453,15 @@ void Placement::placeOnMainWindow(Client* c)
|
|||
QRect geom = c->geometry();
|
||||
geom.moveCenter( place_on->geometry().center());
|
||||
c->move( geom.topLeft());
|
||||
// get area again, because the mainwindow may be on different xinerama screen
|
||||
area = checkArea( c, QRect());
|
||||
}
|
||||
|
||||
QRect Placement::checkArea( const Client* c, const QRect& area )
|
||||
{
|
||||
if( area.isNull())
|
||||
return m_WorkspacePtr->clientArea( PlacementArea, c->geometry().center(), c->desktop());
|
||||
return area;
|
||||
}
|
||||
|
||||
// ********************
|
||||
|
@ -666,15 +677,14 @@ int Workspace::packPositionDown( const Client* cl, int oldy, bool bottom_edge )
|
|||
/*!
|
||||
Asks the internal positioning object to place a client
|
||||
*/
|
||||
void Workspace::place(Client* c)
|
||||
void Workspace::place(Client* c, QRect& area)
|
||||
{
|
||||
initPositioning->place(c);
|
||||
initPositioning->place( c, area );
|
||||
}
|
||||
|
||||
void Workspace::placeSmart(Client* c)
|
||||
void Workspace::placeSmart(Client* c, const QRect& area)
|
||||
{
|
||||
initPositioning->placeSmart(c);
|
||||
initPositioning->placeSmart( c, area );
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
|
23
placement.h
23
placement.h
|
@ -28,21 +28,22 @@ class Placement
|
|||
|
||||
Placement(Workspace* w);
|
||||
|
||||
void place(Client* c);
|
||||
void place(Client* c, QRect& area );
|
||||
|
||||
void placeAtRandom (Client* c);
|
||||
void placeCascaded (Client* c, bool re_init = false);
|
||||
void placeSmart (Client* c);
|
||||
void placeCentered (Client* c);
|
||||
void placeZeroCornered(Client* c);
|
||||
void placeDialog (Client* c);
|
||||
void placeUtility (Client* c);
|
||||
void placeAtRandom (Client* c, const QRect& area );
|
||||
void placeCascaded (Client* c, const QRect& area, bool re_init = false);
|
||||
void placeSmart (Client* c, const QRect& area );
|
||||
void placeCentered (Client* c, const QRect& area );
|
||||
void placeZeroCornered(Client* c, const QRect& area );
|
||||
void placeDialog (Client* c, QRect& area );
|
||||
void placeUtility (Client* c, QRect& area );
|
||||
|
||||
private:
|
||||
|
||||
void placeInternal(Client* c);
|
||||
void placeUnderMouse(Client* c);
|
||||
void placeOnMainWindow(Client* c);
|
||||
void placeInternal(Client* c, const QRect& area );
|
||||
void placeUnderMouse(Client* c, QRect& area );
|
||||
void placeOnMainWindow(Client* c, QRect& area );
|
||||
QRect checkArea( const Client*c, const QRect& area );
|
||||
|
||||
Placement();
|
||||
|
||||
|
|
|
@ -126,8 +126,8 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine
|
|||
*/
|
||||
void setClientIsMoving( Client *c );
|
||||
|
||||
void place(Client *c);
|
||||
void placeSmart( Client* c );
|
||||
void place( Client *c, QRect& area );
|
||||
void placeSmart( Client* c, const QRect& area );
|
||||
|
||||
QPoint adjustClientPosition( Client* c, QPoint pos );
|
||||
void raiseClient( Client* c );
|
||||
|
|
Loading…
Reference in a new issue