add more spacing
[personal-kdebase.git] / workspace / kwin / placement.cpp
bloba1e50db73e3f84764802b4ea10d9198fdf636b2f
1 /********************************************************************
2 KWin - the KDE window manager
3 This file is part of the KDE project.
5 Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
6 Copyright (C) 1997 to 2002 Cristian Tibirna <tibirna@kde.org>
7 Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 *********************************************************************/
23 #include "placement.h"
25 #include <QRect>
26 #include <assert.h>
28 #include <QTextStream>
30 #ifndef KCMRULES
31 #include "workspace.h"
32 #include "client.h"
33 #include "options.h"
34 #include "rules.h"
35 #endif
37 namespace KWin
40 #ifndef KCMRULES
42 Placement::Placement(Workspace* w)
44 m_WorkspacePtr = w;
46 reinitCascading( 0 );
49 /*!
50 Places the client \a c according to the workspace's layout policy
52 void Placement::place(Client* c, QRect& area )
54 Policy policy = c->rules()->checkPlacement( Default );
55 if( policy != Default )
57 place( c, area, policy );
58 return;
61 if( c->isUtility())
62 placeUtility(c, area, options->placement );
63 else if( c->isDialog())
64 placeDialog(c, area, options->placement );
65 else if( c->isSplash())
66 placeOnMainWindow( c, area ); // on mainwindow, if any, otherwise centered
67 else
68 place(c, area, options->placement);
71 void Placement::place(Client* c, QRect& area, Policy policy, Policy nextPlacement )
73 if( policy == Unknown )
74 policy = Default;
75 if( policy == Default )
76 policy = options->placement;
77 if( policy == NoPlacement )
78 return;
79 else if (policy == Random)
80 placeAtRandom(c, area, nextPlacement);
81 else if (policy == Cascade)
82 placeCascaded(c, area, nextPlacement);
83 else if (policy == Centered)
84 placeCentered(c, area, nextPlacement);
85 else if (policy == ZeroCornered)
86 placeZeroCornered(c, area, nextPlacement);
87 else if (policy == UnderMouse)
88 placeUnderMouse(c, area, nextPlacement);
89 else if (policy == OnMainWindow)
90 placeOnMainWindow(c, area, nextPlacement);
91 else if( policy == Maximizing )
92 placeMaximizing(c, area, nextPlacement);
93 else
94 placeSmart(c, area, nextPlacement);
97 /*!
98 Place the client \a c according to a simply "random" placement algorithm.
100 void Placement::placeAtRandom(Client* c, const QRect& area, Policy /*next*/ )
102 const int step = 24;
103 static int px = step;
104 static int py = 2 * step;
105 int tx,ty;
107 const QRect maxRect = checkArea( c, area );
109 if (px < maxRect.x())
110 px = maxRect.x();
111 if (py < maxRect.y())
112 py = maxRect.y();
114 px += step;
115 py += 2*step;
117 if (px > maxRect.width()/2)
118 px = maxRect.x() + step;
119 if (py > maxRect.height()/2)
120 py = maxRect.y() + step;
121 tx = px;
122 ty = py;
123 if (tx + c->width() > maxRect.right())
125 tx = maxRect.right() - c->width();
126 if (tx < 0)
127 tx = 0;
128 px = maxRect.x();
130 if (ty + c->height() > maxRect.bottom())
132 ty = maxRect.bottom() - c->height();
133 if (ty < 0)
134 ty = 0;
135 py = maxRect.y();
137 c->move(tx, ty);
141 Place the client \a c according to a really smart placement algorithm :-)
143 void Placement::placeSmart(Client* c, const QRect& area, Policy /*next*/ )
146 * SmartPlacement by Cristian Tibirna (tibirna@kde.org)
147 * adapted for kwm (16-19jan98) and for kwin (16Nov1999) using (with
148 * permission) ideas from fvwm, authored by
149 * Anthony Martin (amartin@engr.csulb.edu).
150 * Xinerama supported added by Balaji Ramani (balaji@yablibli.com)
151 * with ideas from xfce.
154 const int none = 0, h_wrong = -1, w_wrong = -2; // overlap types
155 long int overlap, min_overlap = 0;
156 int x_optimal, y_optimal;
157 int possible;
158 int desktop = c->desktop() == 0 || c->isOnAllDesktops() ? m_WorkspacePtr->currentDesktop() : c->desktop();
160 int cxl, cxr, cyt, cyb; //temp coords
161 int xl, xr, yt, yb; //temp coords
162 int basket; //temp holder
164 // get the maximum allowed windows space
165 const QRect maxRect = checkArea( c, area );
166 int x = maxRect.left(), y = maxRect.top();
167 x_optimal = x; y_optimal = y;
169 //client gabarit
170 int ch = c->height() - 1;
171 int cw = c->width() - 1;
173 bool first_pass = true; //CT lame flag. Don't like it. What else would do?
175 //loop over possible positions
178 //test if enough room in x and y directions
179 if (y + ch > maxRect.bottom() && ch < maxRect.height())
180 overlap = h_wrong; // this throws the algorithm to an exit
181 else if(x + cw > maxRect.right())
182 overlap = w_wrong;
183 else
185 overlap = none; //initialize
187 cxl = x; cxr = x + cw;
188 cyt = y; cyb = y + ch;
189 ClientList::ConstIterator l;
190 for(l = m_WorkspacePtr->stackingOrder().constBegin(); l != m_WorkspacePtr->stackingOrder().constEnd() ; ++l)
192 if((*l)->isOnDesktop(desktop) &&
193 (*l)->isShown( false ) && (*l) != c)
196 xl = (*l)->x(); yt = (*l)->y();
197 xr = xl + (*l)->width(); yb = yt + (*l)->height();
199 //if windows overlap, calc the overall overlapping
200 if((cxl < xr) && (cxr > xl) &&
201 (cyt < yb) && (cyb > yt))
203 xl = qMax(cxl, xl); xr = qMin(cxr, xr);
204 yt = qMax(cyt, yt); yb = qMin(cyb, yb);
205 if((*l)->keepAbove())
206 overlap += 16 * (xr - xl) * (yb - yt);
207 else if((*l)->keepBelow() && !(*l)->isDock()) // ignore KeepBelow windows
208 overlap += 0; // for placement (see Client::belongsToLayer() for Dock)
209 else
210 overlap += (xr - xl) * (yb - yt);
216 //CT first time we get no overlap we stop.
217 if (overlap == none)
219 x_optimal = x;
220 y_optimal = y;
221 break;
224 if (first_pass)
226 first_pass = false;
227 min_overlap = overlap;
229 //CT save the best position and the minimum overlap up to now
230 else if (overlap >= none && overlap < min_overlap)
232 min_overlap = overlap;
233 x_optimal = x;
234 y_optimal = y;
237 // really need to loop? test if there's any overlap
238 if (overlap > none)
241 possible = maxRect.right();
242 if (possible - cw > x) possible -= cw;
244 // compare to the position of each client on the same desk
245 ClientList::ConstIterator l;
246 for(l = m_WorkspacePtr->stackingOrder().constBegin(); l != m_WorkspacePtr->stackingOrder().constEnd() ; ++l)
249 if ((*l)->isOnDesktop(desktop) &&
250 (*l)->isShown( false ) && (*l) != c)
253 xl = (*l)->x(); yt = (*l)->y();
254 xr = xl + (*l)->width(); yb = yt + (*l)->height();
256 // if not enough room above or under the current tested client
257 // determine the first non-overlapped x position
258 if((y < yb) && (yt < ch + y))
261 if((xr > x) && (possible > xr)) possible = xr;
263 basket = xl - cw;
264 if((basket > x) && (possible > basket)) possible = basket;
268 x = possible;
271 // ... else ==> not enough x dimension (overlap was wrong on horizontal)
272 else if (overlap == w_wrong)
274 x = maxRect.left();
275 possible = maxRect.bottom();
277 if (possible - ch > y) possible -= ch;
279 //test the position of each window on the desk
280 ClientList::ConstIterator l;
281 for(l = m_WorkspacePtr->stackingOrder().constBegin(); l != m_WorkspacePtr->stackingOrder().constEnd() ; ++l)
283 if((*l)->isOnDesktop(desktop) &&
284 (*l) != c && c->isShown( false ))
287 xl = (*l)->x(); yt = (*l)->y();
288 xr = xl + (*l)->width(); yb = yt + (*l)->height();
290 // if not enough room to the left or right of the current tested client
291 // determine the first non-overlapped y position
292 if((yb > y) && (possible > yb)) possible = yb;
294 basket = yt - ch;
295 if((basket > y) && (possible > basket)) possible = basket;
298 y = possible;
301 while((overlap != none) && (overlap != h_wrong) && (y < maxRect.bottom()));
303 if(ch>= maxRect.height())
304 y_optimal=maxRect.top();
306 // place the window
307 c->move(x_optimal, y_optimal);
311 void Placement::reinitCascading( int desktop )
312 { // desktop == 0 - reinit all
313 if( desktop == 0 )
315 cci.clear();
316 for( int i = 0; i < m_WorkspacePtr->numberOfDesktops(); i++)
318 DesktopCascadingInfo inf;
319 inf.pos = QPoint(-1,-1);
320 inf.col = 0;
321 inf.row = 0;
322 cci.append(inf);
325 else
327 cci[desktop - 1].pos = QPoint(-1, -1);
328 cci[desktop - 1].col = cci[desktop - 1].row = 0;
333 Place windows in a cascading order, remembering positions for each desktop
335 void Placement::placeCascaded (Client* c, QRect& area, Policy nextPlacement)
337 /* cascadePlacement by Cristian Tibirna (tibirna@kde.org) (30Jan98)
339 // work coords
340 int xp, yp;
342 //CT how do I get from the 'Client' class the size that NW squarish "handle"
343 const int delta_x = 24;
344 const int delta_y = 24;
346 const int dn = c->desktop() == 0 || c->isOnAllDesktops() ? (m_WorkspacePtr->currentDesktop() - 1) : (c->desktop() - 1);
348 // get the maximum allowed windows space and desk's origin
349 QRect maxRect = checkArea( c, area );
351 // initialize often used vars: width and height of c; we gain speed
352 const int ch = c->height();
353 const int cw = c->width();
354 const int X = maxRect.left();
355 const int Y = maxRect.top();
356 const int H = maxRect.height();
357 const int W = maxRect.width();
359 if( nextPlacement == Unknown )
360 nextPlacement = Smart;
362 //initialize if needed
363 if (cci[dn].pos.x() < 0 || cci[dn].pos.x() < X || cci[dn].pos.y() < Y )
365 cci[dn].pos = QPoint(X, Y);
366 cci[dn].col = cci[dn].row = 0;
370 xp = cci[dn].pos.x();
371 yp = cci[dn].pos.y();
373 //here to touch in case people vote for resize on placement
374 if ((yp + ch) > H) yp = Y;
376 if ((xp + cw) > W)
378 if (!yp)
380 place(c,area,nextPlacement);
381 return;
383 else xp = X;
386 //if this isn't the first window
387 if (cci[dn].pos.x() != X && cci[dn].pos.y() != Y)
389 /* The following statements cause an internal compiler error with
390 * egcs-2.91.66 on SuSE Linux 6.3. The equivalent forms compile fine.
391 * 22-Dec-1999 CS
393 * if (xp != X && yp == Y) xp = delta_x * (++(cci[dn].col));
394 * if (yp != Y && xp == X) yp = delta_y * (++(cci[dn].row));
396 if (xp != X && yp == Y)
398 ++(cci[dn].col);
399 xp = delta_x * cci[dn].col;
401 if (yp != Y && xp == X)
403 ++(cci[dn].row);
404 yp = delta_y * cci[dn].row;
407 // last resort: if still doesn't fit, smart place it
408 if (((xp + cw) > W - X) || ((yp + ch) > H - Y))
410 place(c,area,nextPlacement);
411 return;
415 // place the window
416 c->move(QPoint(xp, yp));
418 // new position
419 cci[dn].pos = QPoint(xp + delta_x, yp + delta_y);
423 Place windows centered, on top of all others
425 void Placement::placeCentered (Client* c, const QRect& area, Policy /*next*/ )
428 // get the maximum allowed windows space and desk's origin
429 const QRect maxRect = checkArea( c, area );
431 const int xp = maxRect.left() + (maxRect.width() - c->width()) / 2;
432 const int yp = maxRect.top() + (maxRect.height() - c->height()) / 2;
434 // place the window
435 c->move(QPoint(xp, yp));
439 Place windows in the (0,0) corner, on top of all others
441 void Placement::placeZeroCornered(Client* c, const QRect& area, Policy /*next*/ )
443 // get the maximum allowed windows space and desk's origin
444 const QRect maxRect = checkArea( c, area );
446 // place the window
447 c->move(QPoint(maxRect.left(), maxRect.top()));
450 void Placement::placeUtility(Client* c, QRect& area, Policy /*next*/ )
452 // TODO kwin should try to place utility windows next to their mainwindow,
453 // preferably at the right edge, and going down if there are more of them
454 // if there's not enough place outside the mainwindow, it should prefer
455 // top-right corner
456 // use the default placement for now
457 place( c, area, Default );
461 void Placement::placeDialog(Client* c, QRect& area, Policy nextPlacement )
463 placeOnMainWindow( c, area, nextPlacement );
466 void Placement::placeUnderMouse(Client* c, QRect& area, Policy /*next*/ )
468 area = checkArea( c, area );
469 QRect geom = c->geometry();
470 geom.moveCenter( cursorPos());
471 c->move( geom.topLeft());
472 c->keepInArea( area ); // make sure it's kept inside workarea
475 void Placement::placeOnMainWindow(Client* c, QRect& area, Policy nextPlacement )
477 if( nextPlacement == Unknown )
478 nextPlacement = Centered;
479 if( nextPlacement == Maximizing ) // maximize if needed
480 placeMaximizing( c, area, NoPlacement );
481 area = checkArea( c, area );
482 ClientList mainwindows = c->mainClients();
483 Client* place_on = NULL;
484 Client* place_on2 = NULL;
485 int mains_count = 0;
486 for( ClientList::ConstIterator it = mainwindows.constBegin();
487 it != mainwindows.constEnd();
488 ++it )
490 if( mainwindows.count() > 1 && (*it)->isSpecialWindow())
491 continue; // don't consider toolbars etc when placing
492 ++mains_count;
493 place_on2 = *it;
494 if( (*it)->isOnCurrentDesktop())
496 if( place_on == NULL )
497 place_on = *it;
498 else
499 { // two or more on current desktop -> center
500 // That's the default at least. However, with maximizing placement
501 // policy as the default, the dialog should be either maximized or
502 // made as large as its maximum size and then placed centered.
503 // So the nextPlacement argument allows chaining. In this case, nextPlacement
504 // is Maximizing and it will call placeCentered().
505 place( c, area, Centered );
506 return;
510 if( place_on == NULL )
511 { // 'mains_count' is used because it doesn't include ignored mainwindows
512 if( mains_count != 1 )
514 place( c, area, Centered );
515 return;
517 place_on = place_on2; // use the only window filtered together with 'mains_count'
519 if( place_on->isDesktop())
521 place( c, area, Centered );
522 return;
524 QRect geom = c->geometry();
525 geom.moveCenter( place_on->geometry().center());
526 c->move( geom.topLeft());
527 // get area again, because the mainwindow may be on different xinerama screen
528 area = checkArea( c, QRect());
529 c->keepInArea( area ); // make sure it's kept inside workarea
532 void Placement::placeMaximizing(Client* c, QRect& area, Policy nextPlacement )
534 if( nextPlacement == Unknown )
535 nextPlacement = Smart;
536 if( c->isMaximizable() && c->maxSize().width() >= area.width() && c->maxSize().height() >= area.height())
538 if( m_WorkspacePtr->clientArea( MaximizeArea, c ) == area )
539 c->maximize( Client::MaximizeFull );
540 else // if the geometry doesn't match default maximize area (xinerama case?),
541 { // it's probably better to use the given area
542 c->setGeometry( area );
545 else
547 c->resizeWithChecks( c->maxSize().boundedTo( area.size()));
548 place( c, area, nextPlacement );
552 QRect Placement::checkArea( const Client* c, const QRect& area )
554 if( area.isNull())
555 return m_WorkspacePtr->clientArea( PlacementArea, c->geometry().center(), c->desktop());
556 return area;
559 #endif
562 Placement::Policy Placement::policyFromString( const QString& policy, bool no_special )
564 if( policy == "NoPlacement" )
565 return NoPlacement;
566 else if( policy == "Default" && !no_special )
567 return Default;
568 else if( policy == "Random" )
569 return Random;
570 else if( policy == "Cascade" )
571 return Cascade;
572 else if( policy == "Centered" )
573 return Centered;
574 else if( policy == "ZeroCornered" )
575 return ZeroCornered;
576 else if( policy == "UnderMouse" && !no_special)
577 return UnderMouse;
578 else if( policy == "OnMainWindow" && !no_special)
579 return OnMainWindow;
580 else if( policy == "Maximizing" )
581 return Maximizing;
582 else
583 return Smart;
586 const char* Placement::policyToString( Policy policy )
588 const char* const policies[] =
589 { "NoPlacement", "Default", "XXX should never see", "Random", "Smart", "Cascade", "Centered",
590 "ZeroCornered", "UnderMouse", "OnMainWindow", "Maximizing" };
591 assert( policy < int( sizeof( policies ) / sizeof( policies[ 0 ] )));
592 return policies[ policy ];
596 #ifndef KCMRULES
598 // ********************
599 // Workspace
600 // ********************
603 Moves active window left until in bumps into another window or workarea edge.
605 void Workspace::slotWindowPackLeft()
607 if( active_client && active_client->isMovable())
608 active_client->move( packPositionLeft( active_client, active_client->geometry().left(), true ),
609 active_client->y());
612 void Workspace::slotWindowPackRight()
614 if( active_client && active_client->isMovable())
615 active_client->move(
616 packPositionRight( active_client, active_client->geometry().right(), true )
617 - active_client->width() + 1, active_client->y());
620 void Workspace::slotWindowPackUp()
622 if( active_client && active_client->isMovable())
623 active_client->move( active_client->x(),
624 packPositionUp( active_client, active_client->geometry().top(), true ));
627 void Workspace::slotWindowPackDown()
629 if( active_client && active_client->isMovable())
630 active_client->move( active_client->x(),
631 packPositionDown( active_client, active_client->geometry().bottom(), true ) - active_client->height() + 1 );
634 void Workspace::slotWindowGrowHorizontal()
636 if( active_client )
637 active_client->growHorizontal();
640 void Client::growHorizontal()
642 if( !isResizable() || isShade())
643 return;
644 QRect geom = geometry();
645 geom.setRight( workspace()->packPositionRight( this, geom.right(), true ));
646 QSize adjsize = adjustedSize( geom.size(), SizemodeFixedW );
647 if( geometry().size() == adjsize && geom.size() != adjsize && xSizeHint.width_inc > 1 ) // take care of size increments
649 int newright = workspace()->packPositionRight( this, geom.right() + xSizeHint.width_inc - 1, true );
650 // check that it hasn't grown outside of the area, due to size increments
651 // TODO this may be wrong?
652 if( workspace()->clientArea( MovementArea,
653 QPoint(( x() + newright ) / 2, geometry().center().y()), desktop()).right() >= newright )
654 geom.setRight( newright );
656 geom.setSize( adjustedSize( geom.size(), SizemodeFixedW ));
657 setGeometry( geom );
660 void Workspace::slotWindowShrinkHorizontal()
662 if( active_client )
663 active_client->shrinkHorizontal();
666 void Client::shrinkHorizontal()
668 if( !isResizable() || isShade())
669 return;
670 QRect geom = geometry();
671 geom.setRight( workspace()->packPositionLeft( this, geom.right(), false ));
672 if( geom.width() <= 1 )
673 return;
674 geom.setSize( adjustedSize( geom.size(), SizemodeFixedW ));
675 if( geom.width() > 20 )
676 setGeometry( geom );
679 void Workspace::slotWindowGrowVertical()
681 if( active_client )
682 active_client->growVertical();
685 void Client::growVertical()
687 if( !isResizable() || isShade())
688 return;
689 QRect geom = geometry();
690 geom.setBottom( workspace()->packPositionDown( this, geom.bottom(), true ));
691 QSize adjsize = adjustedSize( geom.size(), SizemodeFixedH );
692 if( geometry().size() == adjsize && geom.size() != adjsize && xSizeHint.height_inc > 1 ) // take care of size increments
694 int newbottom = workspace()->packPositionDown( this, geom.bottom() + xSizeHint.height_inc - 1, true );
695 // check that it hasn't grown outside of the area, due to size increments
696 if( workspace()->clientArea( MovementArea,
697 QPoint( geometry().center().x(), ( y() + newbottom ) / 2 ), desktop()).bottom() >= newbottom )
698 geom.setBottom( newbottom );
700 geom.setSize( adjustedSize( geom.size(), SizemodeFixedH ));
701 setGeometry( geom );
705 void Workspace::slotWindowShrinkVertical()
707 if( active_client )
708 active_client->shrinkVertical();
711 void Client::shrinkVertical()
713 if( !isResizable() || isShade())
714 return;
715 QRect geom = geometry();
716 geom.setBottom( workspace()->packPositionUp( this, geom.bottom(), false ));
717 if( geom.height() <= 1 )
718 return;
719 geom.setSize( adjustedSize( geom.size(), SizemodeFixedH ));
720 if( geom.height() > 20 )
721 setGeometry( geom );
724 int Workspace::packPositionLeft( const Client* cl, int oldx, bool left_edge ) const
726 int newx = clientArea( MovementArea, cl ).left();
727 if( oldx <= newx ) // try another Xinerama screen
728 newx = clientArea( MovementArea,
729 QPoint( cl->geometry().left() - 1, cl->geometry().center().y()), cl->desktop()).left();
730 if( oldx <= newx )
731 return oldx;
732 for( ClientList::ConstIterator it = clients.constBegin();
733 it != clients.constEnd();
734 ++it)
736 if( !(*it)->isShown( false ) || !(*it)->isOnDesktop( active_client->desktop()))
737 continue;
738 int x = left_edge ? (*it)->geometry().right() + 1 : (*it)->geometry().left() - 1;
739 if( x > newx && x < oldx
740 && !( cl->geometry().top() > (*it)->geometry().bottom() // they overlap in Y direction
741 || cl->geometry().bottom() < (*it)->geometry().top()))
742 newx = x;
744 return newx;
747 int Workspace::packPositionRight( const Client* cl, int oldx, bool right_edge ) const
749 int newx = clientArea( MovementArea, cl ).right();
750 if( oldx >= newx ) // try another Xinerama screen
751 newx = clientArea( MovementArea,
752 QPoint( cl->geometry().right() + 1, cl->geometry().center().y()), cl->desktop()).right();
753 if( oldx >= newx )
754 return oldx;
755 for( ClientList::ConstIterator it = clients.constBegin();
756 it != clients.constEnd();
757 ++it)
759 if( !(*it)->isShown( false ) || !(*it)->isOnDesktop( cl->desktop()))
760 continue;
761 int x = right_edge ? (*it)->geometry().left() - 1 : (*it)->geometry().right() + 1;
762 if( x < newx && x > oldx
763 && !( cl->geometry().top() > (*it)->geometry().bottom()
764 || cl->geometry().bottom() < (*it)->geometry().top()))
765 newx = x;
767 return newx;
770 int Workspace::packPositionUp( const Client* cl, int oldy, bool top_edge ) const
772 int newy = clientArea( MovementArea, cl ).top();
773 if( oldy <= newy ) // try another Xinerama screen
774 newy = clientArea( MovementArea,
775 QPoint( cl->geometry().center().x(), cl->geometry().top() - 1 ), cl->desktop()).top();
776 if( oldy <= newy )
777 return oldy;
778 for( ClientList::ConstIterator it = clients.constBegin();
779 it != clients.constEnd();
780 ++it)
782 if( !(*it)->isShown( false ) || !(*it)->isOnDesktop( cl->desktop()))
783 continue;
784 int y = top_edge ? (*it)->geometry().bottom() + 1 : (*it)->geometry().top() - 1;
785 if( y > newy && y < oldy
786 && !( cl->geometry().left() > (*it)->geometry().right() // they overlap in X direction
787 || cl->geometry().right() < (*it)->geometry().left()))
788 newy = y;
790 return newy;
793 int Workspace::packPositionDown( const Client* cl, int oldy, bool bottom_edge ) const
795 int newy = clientArea( MovementArea, cl ).bottom();
796 if( oldy >= newy ) // try another Xinerama screen
797 newy = clientArea( MovementArea,
798 QPoint( cl->geometry().center().x(), cl->geometry().bottom() + 1 ), cl->desktop()).bottom();
799 if( oldy >= newy )
800 return oldy;
801 for( ClientList::ConstIterator it = clients.constBegin();
802 it != clients.constEnd();
803 ++it)
805 if( !(*it)->isShown( false ) || !(*it)->isOnDesktop( cl->desktop()))
806 continue;
807 int y = bottom_edge ? (*it)->geometry().top() - 1 : (*it)->geometry().bottom() + 1;
808 if( y < newy && y > oldy
809 && !( cl->geometry().left() > (*it)->geometry().right()
810 || cl->geometry().right() < (*it)->geometry().left()))
811 newy = y;
813 return newy;
817 Asks the internal positioning object to place a client
819 void Workspace::place(Client* c, QRect& area)
821 initPositioning->place( c, area );
824 void Workspace::placeSmart(Client* c, const QRect& area)
826 initPositioning->placeSmart( c, area );
829 #endif
831 } // namespace