1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // Workspace.cc for Blackbox - an X11 Window manager
3 // Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
4 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
6 // Permission is hereby granted, free of charge, to any person obtaining a
7 // copy of this software and associated documentation files (the "Software"),
8 // to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 // and/or sell copies of the Software, and to permit persons to whom the
11 // Software is furnished to do so, subject to the following conditions:
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 // DEALINGS IN THE SOFTWARE.
25 # include "../config.h"
26 #endif // HAVE_CONFIG_H
30 #include <X11/Xatom.h>
34 #endif // HAVE_STDIO_H
38 #endif // HAVE_STRING_H
49 #include "blackbox.hh"
50 #include "Clientmenu.hh"
57 #include "Workspace.hh"
58 #include "Windowmenu.hh"
62 Workspace::Workspace(BScreen
*scrn
, unsigned int i
) {
64 xatom
= screen
->getBlackbox()->getXAtom();
66 cascade_x
= cascade_y
= 0;
73 clientmenu
= new Clientmenu(this);
75 lastfocus
= (BlackboxWindow
*) 0;
81 void Workspace::addWindow(BlackboxWindow
*w
, bool place
, bool sticky
) {
84 if (place
) placeWindow(w
);
86 stackingList
.push_front(w
);
91 w
->setWindowNumber(windowList
.size());
94 windowList
.push_back(w
);
96 clientmenu
->insert(w
->getTitle());
100 screen
->updateNetizenWindowAdd(w
->getClientWindow(), id
);
102 if (screen
->doFocusNew() || (w
->isTransient() && w
->getTransientFor() &&
103 w
->getTransientFor()->isFocused())) {
104 if (id
!= screen
->getCurrentWorkspaceID()) {
106 not on the focused workspace, so the window is not going to get focus
107 but if the user wants new windows focused, then it should get focus
108 when this workspace does become focused.
115 if (! w
->isDesktop())
122 void Workspace::removeWindow(BlackboxWindow
*w
, bool sticky
) {
125 stackingList
.remove(w
);
127 // pass focus to the next appropriate window
128 if ((w
->isFocused() || w
== lastfocus
) &&
129 ! screen
->getBlackbox()->doShutdown()) {
133 if (! w
->isNormal()) return;
135 BlackboxWindowList::iterator it
, end
= windowList
.end();
137 for (i
= 0, it
= windowList
.begin(); it
!= end
; ++it
, ++i
)
142 windowList
.erase(it
);
143 clientmenu
->remove(i
);
144 clientmenu
->update();
147 screen
->updateNetizenWindowDel(w
->getClientWindow());
149 BlackboxWindowList::iterator it
= windowList
.begin();
150 const BlackboxWindowList::iterator end
= windowList
.end();
152 for (; it
!= end
; ++it
, ++i
)
153 (*it
)->setWindowNumber(i
);
157 cascade_x
= cascade_y
= 0;
165 void Workspace::focusFallback(const BlackboxWindow
*old_window
) {
166 BlackboxWindow
*newfocus
= 0;
168 if (id
== screen
->getCurrentWorkspaceID()) {
169 // The window is on the visible workspace.
171 // if it's a transient, then try to focus its parent
172 if (old_window
&& old_window
->isTransient()) {
173 newfocus
= old_window
->getTransientFor();
176 newfocus
->isIconic() || // do not focus icons
177 newfocus
->getWorkspaceNumber() != id
|| // or other workspaces
178 ! newfocus
->setInputFocus())
183 BlackboxWindowList::iterator it
= stackingList
.begin(),
184 end
= stackingList
.end();
185 for (; it
!= end
; ++it
) {
186 BlackboxWindow
*tmp
= *it
;
187 if (tmp
&& tmp
->isNormal() && tmp
->setInputFocus()) {
188 // we found our new focus target
195 screen
->getBlackbox()->setFocusedWindow(newfocus
);
197 // The window is not on the visible workspace.
199 if (old_window
&& lastfocus
== old_window
) {
200 // The window was the last-focus target, so we need to replace it.
201 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
202 if (! stackingList
.empty())
203 win
= stackingList
.front();
204 setLastFocusedWindow(win
);
210 void Workspace::setFocused(const BlackboxWindow
*w
, bool focused
) {
211 BlackboxWindowList::iterator it
, end
= windowList
.end();
213 for (i
= 0, it
= windowList
.begin(); it
!= end
; ++it
, ++i
)
216 // if its == end, then a window thats not in the windowList
217 // got focused, such as a !isNormal() window.
219 clientmenu
->setItemSelected(i
, focused
);
223 void Workspace::removeAll(void) {
224 while (! windowList
.empty())
225 windowList
.front()->iconify();
230 * returns the number of transients for win, plus the number of transients
231 * associated with each transient of win
233 static unsigned int countTransients(const BlackboxWindow
* const win
) {
234 BlackboxWindowList transients
= win
->getTransients();
235 if (transients
.empty()) return 0;
237 unsigned int ret
= transients
.size();
238 BlackboxWindowList::const_iterator it
= transients
.begin(),
239 end
= transients
.end();
240 for (; it
!= end
; ++it
)
241 ret
+= countTransients(*it
);
248 * puts the transients of win into the stack. windows are stacked above
249 * the window before it in the stackvector being iterated, meaning
250 * stack[0] is on bottom, stack[1] is above stack[0], stack[2] is above
253 void Workspace::raiseTransients(const BlackboxWindow
* const win
,
254 StackVector::iterator
&stack
) {
255 if (win
->getTransients().empty()) return; // nothing to do
257 // put win's transients in the stack
258 BlackboxWindowList::const_iterator it
, end
= win
->getTransients().end();
259 for (it
= win
->getTransients().begin(); it
!= end
; ++it
) {
260 BlackboxWindow
*w
= *it
;
261 *stack
++ = w
->getFrameWindow();
262 screen
->updateNetizenWindowRaise(w
->getClientWindow());
264 if (! w
->isIconic()) {
265 Workspace
*wkspc
= screen
->getWorkspace(w
->getWorkspaceNumber());
266 wkspc
->stackingList
.remove(w
);
267 wkspc
->stackingList
.push_front(w
);
271 // put transients of win's transients in the stack
272 for (it
= win
->getTransients().begin(); it
!= end
; ++it
)
273 raiseTransients(*it
, stack
);
277 void Workspace::lowerTransients(const BlackboxWindow
* const win
,
278 StackVector::iterator
&stack
) {
279 if (win
->getTransients().empty()) return; // nothing to do
281 // put transients of win's transients in the stack
282 BlackboxWindowList::const_reverse_iterator it
,
283 end
= win
->getTransients().rend();
284 for (it
= win
->getTransients().rbegin(); it
!= end
; ++it
)
285 lowerTransients(*it
, stack
);
287 // put win's transients in the stack
288 for (it
= win
->getTransients().rbegin(); it
!= end
; ++it
) {
289 BlackboxWindow
*w
= *it
;
290 *stack
++ = w
->getFrameWindow();
291 screen
->updateNetizenWindowLower(w
->getClientWindow());
293 if (! w
->isIconic()) {
294 Workspace
*wkspc
= screen
->getWorkspace(w
->getWorkspaceNumber());
295 wkspc
->stackingList
.remove(w
);
296 wkspc
->stackingList
.push_back(w
);
302 void Workspace::raiseWindow(BlackboxWindow
*w
) {
303 BlackboxWindow
*win
= w
;
305 if (win
->isDesktop()) return;
307 // walk up the transient_for's to the window that is not a transient
308 while (win
->isTransient() && win
->getTransientFor())
309 win
= win
->getTransientFor();
311 // get the total window count (win and all transients)
312 unsigned int i
= 1 + countTransients(win
);
314 // stack the window with all transients above
315 StackVector
stack_vector(i
);
316 StackVector::iterator stack
= stack_vector
.begin();
318 *(stack
++) = win
->getFrameWindow();
319 screen
->updateNetizenWindowRaise(win
->getClientWindow());
320 if (! (win
->isIconic() || win
->isDesktop())) {
321 Workspace
*wkspc
= screen
->getWorkspace(win
->getWorkspaceNumber());
322 wkspc
->stackingList
.remove(win
);
323 wkspc
->stackingList
.push_front(win
);
326 raiseTransients(win
, stack
);
328 screen
->raiseWindows(&stack_vector
[0], stack_vector
.size());
332 void Workspace::lowerWindow(BlackboxWindow
*w
) {
333 BlackboxWindow
*win
= w
;
335 // walk up the transient_for's to the window that is not a transient
336 while (win
->isTransient() && win
->getTransientFor())
337 win
= win
->getTransientFor();
339 // get the total window count (win and all transients)
340 unsigned int i
= 1 + countTransients(win
);
342 // stack the window with all transients above
343 StackVector
stack_vector(i
);
344 StackVector::iterator stack
= stack_vector
.begin();
346 lowerTransients(win
, stack
);
348 *(stack
++) = win
->getFrameWindow();
349 screen
->updateNetizenWindowLower(win
->getClientWindow());
350 if (! (win
->isIconic() || win
->isDesktop())) {
351 Workspace
*wkspc
= screen
->getWorkspace(win
->getWorkspaceNumber());
352 wkspc
->stackingList
.remove(win
);
353 wkspc
->stackingList
.push_back(win
);
356 screen
->lowerWindows(&stack_vector
[0], stack_vector
.size());
360 void Workspace::reconfigure(void) {
361 clientmenu
->reconfigure();
362 std::for_each(windowList
.begin(), windowList
.end(),
363 std::mem_fun(&BlackboxWindow::reconfigure
));
367 BlackboxWindow
*Workspace::getWindow(unsigned int index
) {
368 if (index
< windowList
.size()) {
369 BlackboxWindowList::iterator it
= windowList
.begin();
370 while (index
-- > 0) // increment to index
380 Workspace::getNextWindowInList(BlackboxWindow
*w
) {
381 BlackboxWindowList::iterator it
= std::find(windowList
.begin(),
384 assert(it
!= windowList
.end()); // window must be in list
386 if (it
== windowList
.end())
387 return windowList
.front(); // if we walked off the end, wrap around
393 BlackboxWindow
* Workspace::getPrevWindowInList(BlackboxWindow
*w
) {
394 BlackboxWindowList::iterator it
= std::find(windowList
.begin(),
397 assert(it
!= windowList
.end()); // window must be in list
398 if (it
== windowList
.begin())
399 return windowList
.back(); // if we walked of the front, wrap around
405 BlackboxWindow
* Workspace::getTopWindowOnStack(void) const {
406 assert(! stackingList
.empty());
407 return stackingList
.front();
411 void Workspace::sendWindowList(Netizen
&n
) {
412 BlackboxWindowList::iterator it
= windowList
.begin(),
413 end
= windowList
.end();
414 for(; it
!= end
; ++it
)
415 n
.sendWindowAdd((*it
)->getClientWindow(), getID());
419 unsigned int Workspace::getCount(void) const {
420 return windowList
.size();
424 void Workspace::appendStackOrder(BlackboxWindowList
&stack_order
) const {
425 BlackboxWindowList::const_reverse_iterator it
= stackingList
.rbegin();
426 const BlackboxWindowList::const_reverse_iterator end
= stackingList
.rend();
427 for (; it
!= end
; ++it
)
428 if ((*it
)->isNormal())
429 stack_order
.push_back(*it
);
433 void Workspace::hide(void) {
434 BlackboxWindow
*focused
= screen
->getBlackbox()->getFocusedWindow();
435 if (focused
&& focused
->getScreen() == screen
) {
436 assert(focused
->isStuck() || focused
->getWorkspaceNumber() == id
);
440 // if no window had focus, no need to store a last focus
441 lastfocus
= (BlackboxWindow
*) 0;
444 // when we switch workspaces, unfocus whatever was focused
445 screen
->getBlackbox()->setFocusedWindow((BlackboxWindow
*) 0);
447 // withdraw windows in reverse order to minimize the number of Expose events
449 BlackboxWindowList::reverse_iterator it
= stackingList
.rbegin();
450 const BlackboxWindowList::reverse_iterator end
= stackingList
.rend();
451 for (; it
!= end
; ++it
) {
452 BlackboxWindow
*bw
= *it
;
453 // not normal windows cant focus from mouse enters anyways, so we dont
454 // need to unmap/remap them on workspace changes
455 if (! bw
->isStuck() || bw
->isNormal())
461 void Workspace::show(void) {
462 BlackboxWindowList::iterator it
= stackingList
.begin();
463 const BlackboxWindowList::iterator end
= stackingList
.end();
464 for (; it
!= end
; ++it
) {
465 BlackboxWindow
*bw
= *it
;
466 // not normal windows cant focus from mouse enters anyways, so we dont
467 // need to unmap/remap them on workspace changes
468 if (! bw
->isStuck() || bw
->isNormal())
472 XSync(screen
->getBlackbox()->getXDisplay(), False
);
474 if (screen
->doFocusLast()) {
475 if (! screen
->isSloppyFocus() && ! lastfocus
&& ! stackingList
.empty())
476 lastfocus
= stackingList
.front();
479 lastfocus
->setInputFocus();
484 bool Workspace::isCurrent(void) const {
485 return (id
== screen
->getCurrentWorkspaceID());
489 bool Workspace::isLastWindow(const BlackboxWindow
* const w
) const {
490 return (w
== windowList
.back());
494 void Workspace::setCurrent(void) {
495 screen
->changeWorkspaceID(id
);
499 void Workspace::readName(void) {
500 XAtom::StringVect namesList
;
501 unsigned long numnames
= id
+ 1;
503 // attempt to get from the _NET_WM_DESKTOP_NAMES property
504 if (xatom
->getValue(screen
->getRootWindow(), XAtom::net_desktop_names
,
505 XAtom::utf8
, numnames
, namesList
) &&
506 namesList
.size() > id
) {
507 name
= namesList
[id
];
509 clientmenu
->setLabel(name
);
510 clientmenu
->update();
513 Use a default name. This doesn't actually change the class. That will
514 happen after the setName changes the root property, and that change
515 makes its way back to this function.
517 string tmp
=i18n(WorkspaceSet
, WorkspaceDefaultNameFormat
,
519 assert(tmp
.length() < 32);
520 char default_name
[32];
521 sprintf(default_name
, tmp
.c_str(), id
+ 1);
523 setName(default_name
); // save this into the _NET_WM_DESKTOP_NAMES property
528 void Workspace::setName(const string
& new_name
) {
529 // set the _NET_WM_DESKTOP_NAMES property with the new name
530 XAtom::StringVect namesList
;
531 unsigned long numnames
= (unsigned) -1;
532 if (xatom
->getValue(screen
->getRootWindow(), XAtom::net_desktop_names
,
533 XAtom::utf8
, numnames
, namesList
) &&
534 namesList
.size() > id
)
535 namesList
[id
] = new_name
;
537 namesList
.push_back(new_name
);
539 xatom
->setValue(screen
->getRootWindow(), XAtom::net_desktop_names
,
540 XAtom::utf8
, namesList
);
545 * Calculate free space available for window placement.
547 typedef std::vector
<Rect
> rectList
;
549 static rectList
calcSpace(const Rect
&win
, const rectList
&spaces
) {
552 rectList::const_iterator siter
, end
= spaces
.end();
553 for (siter
= spaces
.begin(); siter
!= end
; ++siter
) {
554 const Rect
&curr
= *siter
;
556 if(! win
.intersects(curr
)) {
557 result
.push_back(curr
);
561 /* Use an intersection of win and curr to determine the space around
562 * curr that we can use.
564 * NOTE: the spaces calculated can overlap.
569 extra
.setCoords(curr
.left(), curr
.top(),
570 isect
.left() - 1, curr
.bottom());
571 if (extra
.valid()) result
.push_back(extra
);
574 extra
.setCoords(curr
.left(), curr
.top(),
575 curr
.right(), isect
.top() - 1);
576 if (extra
.valid()) result
.push_back(extra
);
579 extra
.setCoords(isect
.right() + 1, curr
.top(),
580 curr
.right(), curr
.bottom());
581 if (extra
.valid()) result
.push_back(extra
);
584 extra
.setCoords(curr
.left(), isect
.bottom() + 1,
585 curr
.right(), curr
.bottom());
586 if (extra
.valid()) result
.push_back(extra
);
592 static bool rowRLBT(const Rect
&first
, const Rect
&second
) {
593 if (first
.bottom() == second
.bottom())
594 return first
.right() > second
.right();
595 return first
.bottom() > second
.bottom();
598 static bool rowRLTB(const Rect
&first
, const Rect
&second
) {
599 if (first
.y() == second
.y())
600 return first
.right() > second
.right();
601 return first
.y() < second
.y();
604 static bool rowLRBT(const Rect
&first
, const Rect
&second
) {
605 if (first
.bottom() == second
.bottom())
606 return first
.x() < second
.x();
607 return first
.bottom() > second
.bottom();
610 static bool rowLRTB(const Rect
&first
, const Rect
&second
) {
611 if (first
.y() == second
.y())
612 return first
.x() < second
.x();
613 return first
.y() < second
.y();
616 static bool colLRTB(const Rect
&first
, const Rect
&second
) {
617 if (first
.x() == second
.x())
618 return first
.y() < second
.y();
619 return first
.x() < second
.x();
622 static bool colLRBT(const Rect
&first
, const Rect
&second
) {
623 if (first
.x() == second
.x())
624 return first
.bottom() > second
.bottom();
625 return first
.x() < second
.x();
628 static bool colRLTB(const Rect
&first
, const Rect
&second
) {
629 if (first
.right() == second
.right())
630 return first
.y() < second
.y();
631 return first
.right() > second
.right();
634 static bool colRLBT(const Rect
&first
, const Rect
&second
) {
635 if (first
.right() == second
.right())
636 return first
.bottom() > second
.bottom();
637 return first
.right() > second
.right();
641 bool Workspace::smartPlacement(Rect
& win
) {
644 //initially the entire screen is free
646 if (screen
->isXineramaActive() &&
647 screen
->getBlackbox()->doXineramaPlacement()) {
648 RectList availableAreas
= screen
->allAvailableAreas();
649 RectList::iterator it
, end
= availableAreas
.end();
651 for (it
= availableAreas
.begin(); it
!= end
; ++it
)
652 spaces
.push_back(*it
);
655 spaces
.push_back(screen
->availableArea());
658 BlackboxWindowList::const_iterator wit
= windowList
.begin(),
659 end
= windowList
.end();
661 for (; wit
!= end
; ++wit
) {
662 const BlackboxWindow
* const curr
= *wit
;
664 // watch for shaded windows and full-maxed windows
665 if (curr
->isShaded()) {
666 if (screen
->getPlaceIgnoreShaded()) continue;
667 } else if (curr
->isMaximizedFull()) {
668 if (screen
->getPlaceIgnoreMaximized()) continue;
671 tmp
.setRect(curr
->frameRect().x(), curr
->frameRect().y(),
672 curr
->frameRect().width() + screen
->getBorderWidth(),
673 curr
->frameRect().height() + screen
->getBorderWidth());
675 spaces
= calcSpace(tmp
, spaces
);
678 if (screen
->getPlacementPolicy() == BScreen::RowSmartPlacement
) {
679 if(screen
->getRowPlacementDirection() == BScreen::LeftRight
) {
680 if(screen
->getColPlacementDirection() == BScreen::TopBottom
)
681 std::sort(spaces
.begin(), spaces
.end(), rowLRTB
);
683 std::sort(spaces
.begin(), spaces
.end(), rowLRBT
);
685 if(screen
->getColPlacementDirection() == BScreen::TopBottom
)
686 std::sort(spaces
.begin(), spaces
.end(), rowRLTB
);
688 std::sort(spaces
.begin(), spaces
.end(), rowRLBT
);
691 if(screen
->getColPlacementDirection() == BScreen::TopBottom
) {
692 if(screen
->getRowPlacementDirection() == BScreen::LeftRight
)
693 std::sort(spaces
.begin(), spaces
.end(), colLRTB
);
695 std::sort(spaces
.begin(), spaces
.end(), colRLTB
);
697 if(screen
->getRowPlacementDirection() == BScreen::LeftRight
)
698 std::sort(spaces
.begin(), spaces
.end(), colLRBT
);
700 std::sort(spaces
.begin(), spaces
.end(), colRLBT
);
704 rectList::const_iterator sit
= spaces
.begin(), spaces_end
= spaces
.end();
705 for(; sit
!= spaces_end
; ++sit
) {
706 if (sit
->width() >= win
.width() && sit
->height() >= win
.height())
710 if (sit
== spaces_end
)
713 //set new position based on the empty space found
714 const Rect
& where
= *sit
;
718 // adjust the location() based on left/right and top/bottom placement
719 if (screen
->getPlacementPolicy() == BScreen::RowSmartPlacement
) {
720 if (screen
->getRowPlacementDirection() == BScreen::RightLeft
)
721 win
.setX(where
.right() - win
.width());
722 if (screen
->getColPlacementDirection() == BScreen::BottomTop
)
723 win
.setY(where
.bottom() - win
.height());
725 if (screen
->getColPlacementDirection() == BScreen::BottomTop
)
726 win
.setY(win
.y() + where
.height() - win
.height());
727 if (screen
->getRowPlacementDirection() == BScreen::RightLeft
)
728 win
.setX(win
.x() + where
.width() - win
.width());
734 bool Workspace::underMousePlacement(Rect
&win
) {
738 XQueryPointer(screen
->getBlackbox()->getXDisplay(), screen
->getRootWindow(),
739 &r
, &c
, &rx
, &ry
, &x
, &y
, &m
);
743 if (screen
->isXineramaActive() &&
744 screen
->getBlackbox()->doXineramaPlacement()) {
745 RectList availableAreas
= screen
->allAvailableAreas();
746 RectList::iterator it
, end
= availableAreas
.end();
748 for (it
= availableAreas
.begin(); it
!= end
; ++it
)
749 if (it
->contains(rx
, ry
)) break;
750 assert(it
!= end
); // the mouse isn't inside an area?
754 area
= screen
->availableArea();
756 x
= rx
- win
.width() / 2;
757 y
= ry
- win
.height() / 2;
763 if (x
+ win
.width() > area
.x() + area
.width())
764 x
= area
.x() + area
.width() - win
.width();
765 if (y
+ win
.height() > area
.y() + area
.height())
766 y
= area
.y() + area
.height() - win
.height();
775 bool Workspace::cascadePlacement(Rect
&win
, const int offset
) {
779 if (screen
->isXineramaActive() &&
780 screen
->getBlackbox()->doXineramaPlacement()) {
781 area
= screen
->allAvailableAreas()[cascade_region
];
784 area
= screen
->availableArea();
786 if ((static_cast<signed>(cascade_x
+ win
.width()) > area
.right() + 1) ||
787 (static_cast<signed>(cascade_y
+ win
.height()) > area
.bottom() + 1)) {
788 cascade_x
= cascade_y
= 0;
790 if (screen
->isXineramaActive() &&
791 screen
->getBlackbox()->doXineramaPlacement()) {
792 // go to the next xinerama region, and use its area
793 if (++cascade_region
>= screen
->allAvailableAreas().size())
795 area
= screen
->allAvailableAreas()[cascade_region
];
800 if (cascade_x
== 0) {
801 cascade_x
= area
.x() + offset
;
802 cascade_y
= area
.y() + offset
;
805 win
.setPos(cascade_x
, cascade_y
);
814 void Workspace::placeWindow(BlackboxWindow
*win
) {
815 Rect
new_win(0, 0, win
->frameRect().width(), win
->frameRect().height());
818 switch (screen
->getPlacementPolicy()) {
819 case BScreen::RowSmartPlacement
:
820 case BScreen::ColSmartPlacement
:
821 placed
= smartPlacement(new_win
);
823 case BScreen::UnderMousePlacement
:
824 case BScreen::ClickMousePlacement
:
825 placed
= underMousePlacement(new_win
);
827 break; // handled below
831 cascadePlacement(new_win
, (win
->getTitleHeight() +
832 screen
->getBorderWidth() * 2));
834 if (new_win
.right() > screen
->availableArea().right())
835 new_win
.setX(screen
->availableArea().left());
836 if (new_win
.bottom() > screen
->availableArea().bottom())
837 new_win
.setY(screen
->availableArea().top());
839 win
->configure(new_win
.x(), new_win
.y(), new_win
.width(), new_win
.height());