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"
28 #include <QTextStream>
31 #include "workspace.h"
42 Placement::Placement(Workspace
* w
)
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
);
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
68 place(c
, area
, options
->placement
);
71 void Placement::place(Client
* c
, QRect
& area
, Policy policy
, Policy nextPlacement
)
73 if( policy
== Unknown
)
75 if( policy
== Default
)
76 policy
= options
->placement
;
77 if( policy
== NoPlacement
)
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
);
94 placeSmart(c
, area
, nextPlacement
);
98 Place the client \a c according to a simply "random" placement algorithm.
100 void Placement::placeAtRandom(Client
* c
, const QRect
& area
, Policy
/*next*/ )
103 static int px
= step
;
104 static int py
= 2 * step
;
107 const QRect maxRect
= checkArea( c
, area
);
109 if (px
< maxRect
.x())
111 if (py
< maxRect
.y())
117 if (px
> maxRect
.width()/2)
118 px
= maxRect
.x() + step
;
119 if (py
> maxRect
.height()/2)
120 py
= maxRect
.y() + step
;
123 if (tx
+ c
->width() > maxRect
.right())
125 tx
= maxRect
.right() - c
->width();
130 if (ty
+ c
->height() > maxRect
.bottom())
132 ty
= maxRect
.bottom() - c
->height();
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
;
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
;
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())
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)
210 overlap
+= (xr
- xl
) * (yb
- yt
);
216 //CT first time we get no overlap we stop.
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
;
237 // really need to loop? test if there's any overlap
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
;
264 if((basket
> x
) && (possible
> basket
)) possible
= basket
;
271 // ... else ==> not enough x dimension (overlap was wrong on horizontal)
272 else if (overlap
== w_wrong
)
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
;
295 if((basket
> y
) && (possible
> basket
)) possible
= basket
;
301 while((overlap
!= none
) && (overlap
!= h_wrong
) && (y
< maxRect
.bottom()));
303 if(ch
>= maxRect
.height())
304 y_optimal
=maxRect
.top();
307 c
->move(x_optimal
, y_optimal
);
311 void Placement::reinitCascading( int desktop
)
312 { // desktop == 0 - reinit all
316 for( int i
= 0; i
< m_WorkspacePtr
->numberOfDesktops(); i
++)
318 DesktopCascadingInfo inf
;
319 inf
.pos
= QPoint(-1,-1);
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)
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
;
380 place(c
,area
,nextPlacement
);
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.
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
)
399 xp
= delta_x
* cci
[dn
].col
;
401 if (yp
!= Y
&& xp
== X
)
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
);
416 c
->move(QPoint(xp
, yp
));
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;
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
);
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
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
;
486 for( ClientList::ConstIterator it
= mainwindows
.constBegin();
487 it
!= mainwindows
.constEnd();
490 if( mainwindows
.count() > 1 && (*it
)->isSpecialWindow())
491 continue; // don't consider toolbars etc when placing
494 if( (*it
)->isOnCurrentDesktop())
496 if( place_on
== NULL
)
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
);
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
);
517 place_on
= place_on2
; // use the only window filtered together with 'mains_count'
519 if( place_on
->isDesktop())
521 place( c
, area
, Centered
);
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
);
547 c
->resizeWithChecks( c
->maxSize().boundedTo( area
.size()));
548 place( c
, area
, nextPlacement
);
552 QRect
Placement::checkArea( const Client
* c
, const QRect
& area
)
555 return m_WorkspacePtr
->clientArea( PlacementArea
, c
->geometry().center(), c
->desktop());
562 Placement::Policy
Placement::policyFromString( const QString
& policy
, bool no_special
)
564 if( policy
== "NoPlacement" )
566 else if( policy
== "Default" && !no_special
)
568 else if( policy
== "Random" )
570 else if( policy
== "Cascade" )
572 else if( policy
== "Centered" )
574 else if( policy
== "ZeroCornered" )
576 else if( policy
== "UnderMouse" && !no_special
)
578 else if( policy
== "OnMainWindow" && !no_special
)
580 else if( policy
== "Maximizing" )
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
];
598 // ********************
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 ),
612 void Workspace::slotWindowPackRight()
614 if( active_client
&& active_client
->isMovable())
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()
637 active_client
->growHorizontal();
640 void Client::growHorizontal()
642 if( !isResizable() || isShade())
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
));
660 void Workspace::slotWindowShrinkHorizontal()
663 active_client
->shrinkHorizontal();
666 void Client::shrinkHorizontal()
668 if( !isResizable() || isShade())
670 QRect geom
= geometry();
671 geom
.setRight( workspace()->packPositionLeft( this, geom
.right(), false ));
672 if( geom
.width() <= 1 )
674 geom
.setSize( adjustedSize( geom
.size(), SizemodeFixedW
));
675 if( geom
.width() > 20 )
679 void Workspace::slotWindowGrowVertical()
682 active_client
->growVertical();
685 void Client::growVertical()
687 if( !isResizable() || isShade())
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
));
705 void Workspace::slotWindowShrinkVertical()
708 active_client
->shrinkVertical();
711 void Client::shrinkVertical()
713 if( !isResizable() || isShade())
715 QRect geom
= geometry();
716 geom
.setBottom( workspace()->packPositionUp( this, geom
.bottom(), false ));
717 if( geom
.height() <= 1 )
719 geom
.setSize( adjustedSize( geom
.size(), SizemodeFixedH
));
720 if( geom
.height() > 20 )
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();
732 for( ClientList::ConstIterator it
= clients
.constBegin();
733 it
!= clients
.constEnd();
736 if( !(*it
)->isShown( false ) || !(*it
)->isOnDesktop( active_client
->desktop()))
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()))
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();
755 for( ClientList::ConstIterator it
= clients
.constBegin();
756 it
!= clients
.constEnd();
759 if( !(*it
)->isShown( false ) || !(*it
)->isOnDesktop( cl
->desktop()))
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()))
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();
778 for( ClientList::ConstIterator it
= clients
.constBegin();
779 it
!= clients
.constEnd();
782 if( !(*it
)->isShown( false ) || !(*it
)->isOnDesktop( cl
->desktop()))
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()))
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();
801 for( ClientList::ConstIterator it
= clients
.constBegin();
802 it
!= clients
.constEnd();
805 if( !(*it
)->isShown( false ) || !(*it
)->isOnDesktop( cl
->desktop()))
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()))
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
);