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
48 #include "blackbox.hh"
49 #include "clientmenu.hh"
56 #include "workspace.hh"
57 #include "windowmenu.hh"
61 Workspace::Workspace(BScreen
*scrn
, unsigned int i
) {
63 xatom
= screen
->getBlackbox()->getXAtom();
65 cascade_x
= cascade_y
= 0;
72 clientmenu
= new Clientmenu(this);
74 lastfocus
= (BlackboxWindow
*) 0;
80 void Workspace::addWindow(BlackboxWindow
*w
, bool place
, bool sticky
) {
83 if (place
) placeWindow(w
);
85 stackingList
.push_front(w
);
90 if (! w
->isNormal()) {
92 // just give it some number, else bad things happen as it is assumed to
93 // not be on a workspace
94 w
->setWindowNumber(0);
98 w
->setWindowNumber(windowList
.size());
100 windowList
.push_back(w
);
102 clientmenu
->insert(w
->getTitle());
103 clientmenu
->update();
106 screen
->updateNetizenWindowAdd(w
->getClientWindow(), id
);
108 if (screen
->doFocusNew() || (w
->isTransient() && w
->getTransientFor() &&
109 w
->getTransientFor()->isFocused())) {
110 if (id
!= screen
->getCurrentWorkspaceID()) {
112 not on the focused workspace, so the window is not going to get focus
113 but if the user wants new windows focused, then it should get focus
114 when this workspace does become focused.
121 if (! w
->isDesktop())
128 void Workspace::removeWindow(BlackboxWindow
*w
, bool sticky
) {
131 stackingList
.remove(w
);
133 // pass focus to the next appropriate window
134 if ((w
->isFocused() || w
== lastfocus
) &&
135 ! screen
->getBlackbox()->doShutdown()) {
139 if (! w
->isNormal()) return;
141 BlackboxWindowList::iterator it
, end
= windowList
.end();
143 for (i
= 0, it
= windowList
.begin(); it
!= end
; ++it
, ++i
)
148 windowList
.erase(it
);
149 clientmenu
->remove(i
);
150 clientmenu
->update();
153 screen
->updateNetizenWindowDel(w
->getClientWindow());
155 BlackboxWindowList::iterator it
= windowList
.begin();
156 const BlackboxWindowList::iterator end
= windowList
.end();
158 for (; it
!= end
; ++it
, ++i
)
159 (*it
)->setWindowNumber(i
);
163 cascade_x
= cascade_y
= 0;
171 void Workspace::focusFallback(const BlackboxWindow
*old_window
) {
172 BlackboxWindow
*newfocus
= 0;
174 if (id
== screen
->getCurrentWorkspaceID()) {
175 // The window is on the visible workspace.
177 // if it's a transient, then try to focus its parent
178 if (old_window
&& old_window
->isTransient()) {
179 newfocus
= old_window
->getTransientFor();
182 newfocus
->isIconic() || // do not focus icons
183 newfocus
->getWorkspaceNumber() != id
|| // or other workspaces
184 ! newfocus
->setInputFocus())
189 BlackboxWindowList::iterator it
= stackingList
.begin(),
190 end
= stackingList
.end();
191 for (; it
!= end
; ++it
) {
192 BlackboxWindow
*tmp
= *it
;
193 if (tmp
&& tmp
->isNormal() && tmp
->setInputFocus()) {
194 // we found our new focus target
201 screen
->getBlackbox()->setFocusedWindow(newfocus
);
203 // The window is not on the visible workspace.
205 if (old_window
&& lastfocus
== old_window
) {
206 // The window was the last-focus target, so we need to replace it.
207 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
208 if (! stackingList
.empty())
209 win
= stackingList
.front();
210 setLastFocusedWindow(win
);
216 void Workspace::setFocused(const BlackboxWindow
*w
, bool focused
) {
217 BlackboxWindowList::iterator it
, end
= windowList
.end();
219 for (i
= 0, it
= windowList
.begin(); it
!= end
; ++it
, ++i
)
222 // if its == end, then a window thats not in the windowList
223 // got focused, such as a !isNormal() window.
225 clientmenu
->setItemSelected(i
, focused
);
229 void Workspace::removeAll(void) {
230 while (! windowList
.empty())
231 windowList
.front()->iconify();
234 void Workspace::showAll(void) {
235 BlackboxWindowList::iterator it
= stackingList
.begin();
236 const BlackboxWindowList::iterator end
= stackingList
.end();
237 for (; it
!= end
; ++it
) {
238 BlackboxWindow
*bw
= *it
;
239 // sticky windows arent unmapped on a workspace change so we don't have ot
240 // map them, but sometimes on a restart, another app can unmap our sticky
241 // windows, so we map on startup always
242 if (! bw
->isStuck() || screen
->getBlackbox()->isStartup())
248 void Workspace::hideAll(void) {
249 // withdraw in reverse order to minimize the number of Expose events
251 BlackboxWindowList
lst(stackingList
.rbegin(), stackingList
.rend());
253 BlackboxWindowList::iterator it
= lst
.begin();
254 const BlackboxWindowList::iterator end
= lst
.end();
255 for (; it
!= end
; ++it
) {
256 BlackboxWindow
*bw
= *it
;
257 // don't hide sticky windows, or they'll end up flickering on a workspace
267 * returns the number of transients for win, plus the number of transients
268 * associated with each transient of win
270 static unsigned int countTransients(const BlackboxWindow
* const win
) {
271 BlackboxWindowList transients
= win
->getTransients();
272 if (transients
.empty()) return 0;
274 unsigned int ret
= transients
.size();
275 BlackboxWindowList::const_iterator it
= transients
.begin(),
276 end
= transients
.end();
277 for (; it
!= end
; ++it
)
278 ret
+= countTransients(*it
);
285 * puts the transients of win into the stack. windows are stacked above
286 * the window before it in the stackvector being iterated, meaning
287 * stack[0] is on bottom, stack[1] is above stack[0], stack[2] is above
290 void Workspace::raiseTransients(const BlackboxWindow
* const win
,
291 StackVector::iterator
&stack
) {
292 if (win
->getTransients().empty()) return; // nothing to do
294 // put win's transients in the stack
295 BlackboxWindowList::const_iterator it
, end
= win
->getTransients().end();
296 for (it
= win
->getTransients().begin(); it
!= end
; ++it
) {
297 BlackboxWindow
*w
= *it
;
298 *stack
++ = w
->getFrameWindow();
299 screen
->updateNetizenWindowRaise(w
->getClientWindow());
301 if (! w
->isIconic()) {
302 Workspace
*wkspc
= screen
->getWorkspace(w
->getWorkspaceNumber());
303 wkspc
->stackingList
.remove(w
);
304 wkspc
->stackingList
.push_front(w
);
308 // put transients of win's transients in the stack
309 for (it
= win
->getTransients().begin(); it
!= end
; ++it
)
310 raiseTransients(*it
, stack
);
314 void Workspace::lowerTransients(const BlackboxWindow
* const win
,
315 StackVector::iterator
&stack
) {
316 if (win
->getTransients().empty()) return; // nothing to do
318 // put transients of win's transients in the stack
319 BlackboxWindowList::const_reverse_iterator it
,
320 end
= win
->getTransients().rend();
321 for (it
= win
->getTransients().rbegin(); it
!= end
; ++it
)
322 lowerTransients(*it
, stack
);
324 // put win's transients in the stack
325 for (it
= win
->getTransients().rbegin(); it
!= end
; ++it
) {
326 BlackboxWindow
*w
= *it
;
327 *stack
++ = w
->getFrameWindow();
328 screen
->updateNetizenWindowLower(w
->getClientWindow());
330 if (! w
->isIconic()) {
331 Workspace
*wkspc
= screen
->getWorkspace(w
->getWorkspaceNumber());
332 wkspc
->stackingList
.remove(w
);
333 wkspc
->stackingList
.push_back(w
);
339 void Workspace::raiseWindow(BlackboxWindow
*w
) {
340 BlackboxWindow
*win
= w
;
342 if (win
->isDesktop()) return;
344 // walk up the transient_for's to the window that is not a transient
345 while (win
->isTransient() && win
->getTransientFor())
346 win
= win
->getTransientFor();
348 // get the total window count (win and all transients)
349 unsigned int i
= 1 + countTransients(win
);
351 // stack the window with all transients above
352 StackVector
stack_vector(i
);
353 StackVector::iterator stack
= stack_vector
.begin();
355 *(stack
++) = win
->getFrameWindow();
356 screen
->updateNetizenWindowRaise(win
->getClientWindow());
357 if (! (win
->isIconic() || win
->isDesktop())) {
358 Workspace
*wkspc
= screen
->getWorkspace(win
->getWorkspaceNumber());
359 wkspc
->stackingList
.remove(win
);
360 wkspc
->stackingList
.push_front(win
);
363 raiseTransients(win
, stack
);
365 screen
->raiseWindows(&stack_vector
[0], stack_vector
.size());
369 void Workspace::lowerWindow(BlackboxWindow
*w
) {
370 BlackboxWindow
*win
= w
;
372 // walk up the transient_for's to the window that is not a transient
373 while (win
->isTransient() && win
->getTransientFor())
374 win
= win
->getTransientFor();
376 // get the total window count (win and all transients)
377 unsigned int i
= 1 + countTransients(win
);
379 // stack the window with all transients above
380 StackVector
stack_vector(i
);
381 StackVector::iterator stack
= stack_vector
.begin();
383 lowerTransients(win
, stack
);
385 *(stack
++) = win
->getFrameWindow();
386 screen
->updateNetizenWindowLower(win
->getClientWindow());
387 if (! (win
->isIconic() || win
->isDesktop())) {
388 Workspace
*wkspc
= screen
->getWorkspace(win
->getWorkspaceNumber());
389 wkspc
->stackingList
.remove(win
);
390 wkspc
->stackingList
.push_back(win
);
393 screen
->lowerWindows(&stack_vector
[0], stack_vector
.size());
397 void Workspace::reconfigure(void) {
398 clientmenu
->reconfigure();
399 std::for_each(windowList
.begin(), windowList
.end(),
400 std::mem_fun(&BlackboxWindow::reconfigure
));
404 BlackboxWindow
*Workspace::getWindow(unsigned int index
) {
405 if (index
< windowList
.size()) {
406 BlackboxWindowList::iterator it
= windowList
.begin();
407 while (index
-- > 0) // increment to index
417 Workspace::getNextWindowInList(BlackboxWindow
*w
) {
418 BlackboxWindowList::iterator it
= std::find(windowList
.begin(),
421 assert(it
!= windowList
.end()); // window must be in list
423 if (it
== windowList
.end())
424 return windowList
.front(); // if we walked off the end, wrap around
430 BlackboxWindow
* Workspace::getPrevWindowInList(BlackboxWindow
*w
) {
431 BlackboxWindowList::iterator it
= std::find(windowList
.begin(),
434 assert(it
!= windowList
.end()); // window must be in list
435 if (it
== windowList
.begin())
436 return windowList
.back(); // if we walked of the front, wrap around
442 BlackboxWindow
* Workspace::getTopWindowOnStack(void) const {
443 assert(! stackingList
.empty());
444 return stackingList
.front();
448 void Workspace::sendWindowList(Netizen
&n
) {
449 BlackboxWindowList::iterator it
= windowList
.begin(),
450 end
= windowList
.end();
451 for(; it
!= end
; ++it
)
452 n
.sendWindowAdd((*it
)->getClientWindow(), getID());
456 unsigned int Workspace::getCount(void) const {
457 return windowList
.size();
461 void Workspace::appendStackOrder(BlackboxWindowList
&stack_order
) const {
462 BlackboxWindowList::const_reverse_iterator it
= stackingList
.rbegin();
463 const BlackboxWindowList::const_reverse_iterator end
= stackingList
.rend();
464 for (; it
!= end
; ++it
)
465 // don't add desktop wnidows, or sticky windows more than once
466 if (! ( (*it
)->isDesktop() ||
467 ((*it
)->isStuck() && id
!= screen
->getCurrentWorkspaceID())))
468 stack_order
.push_back(*it
);
472 bool Workspace::isCurrent(void) const {
473 return (id
== screen
->getCurrentWorkspaceID());
477 bool Workspace::isLastWindow(const BlackboxWindow
* const w
) const {
478 return (w
== windowList
.back());
482 void Workspace::setCurrent(void) {
483 screen
->changeWorkspaceID(id
);
487 void Workspace::readName(void) {
488 XAtom::StringVect namesList
;
489 unsigned long numnames
= id
+ 1;
491 // attempt to get from the _NET_WM_DESKTOP_NAMES property
492 if (xatom
->getValue(screen
->getRootWindow(), XAtom::net_desktop_names
,
493 XAtom::utf8
, numnames
, namesList
) &&
494 namesList
.size() > id
) {
495 name
= namesList
[id
];
497 clientmenu
->setLabel(name
);
498 clientmenu
->update();
501 Use a default name. This doesn't actually change the class. That will
502 happen after the setName changes the root property, and that change
503 makes its way back to this function.
505 string tmp
=i18n(WorkspaceSet
, WorkspaceDefaultNameFormat
,
507 assert(tmp
.length() < 32);
508 char default_name
[32];
509 sprintf(default_name
, tmp
.c_str(), id
+ 1);
511 setName(default_name
); // save this into the _NET_WM_DESKTOP_NAMES property
516 void Workspace::setName(const string
& new_name
) {
517 // set the _NET_WM_DESKTOP_NAMES property with the new name
518 XAtom::StringVect namesList
;
519 unsigned long numnames
= (unsigned) -1;
520 if (xatom
->getValue(screen
->getRootWindow(), XAtom::net_desktop_names
,
521 XAtom::utf8
, numnames
, namesList
) &&
522 namesList
.size() > id
)
523 namesList
[id
] = new_name
;
525 namesList
.push_back(new_name
);
527 xatom
->setValue(screen
->getRootWindow(), XAtom::net_desktop_names
,
528 XAtom::utf8
, namesList
);
533 * Calculate free space available for window placement.
535 Workspace::rectList
Workspace::calcSpace(const Rect
&win
,
536 const rectList
&spaces
) const {
539 rectList::const_iterator siter
, end
= spaces
.end();
540 for (siter
= spaces
.begin(); siter
!= end
; ++siter
) {
541 const Rect
&curr
= *siter
;
543 if(! win
.intersects(curr
)) {
544 result
.push_back(curr
);
548 /* Use an intersection of win and curr to determine the space around
549 * curr that we can use.
551 * NOTE: the spaces calculated can overlap.
556 extra
.setCoords(curr
.left(), curr
.top(),
557 isect
.left() - screen
->getSnapOffset(), curr
.bottom());
558 if (extra
.valid()) result
.push_back(extra
);
561 extra
.setCoords(curr
.left(), curr
.top(),
562 curr
.right(), isect
.top() - screen
->getSnapOffset());
563 if (extra
.valid()) result
.push_back(extra
);
566 extra
.setCoords(isect
.right() + screen
->getSnapOffset(), curr
.top(),
567 curr
.right(), curr
.bottom());
568 if (extra
.valid()) result
.push_back(extra
);
571 extra
.setCoords(curr
.left(), isect
.bottom() + screen
->getSnapOffset(),
572 curr
.right(), curr
.bottom());
573 if (extra
.valid()) result
.push_back(extra
);
579 static bool rowRLBT(const Rect
&first
, const Rect
&second
) {
580 if (first
.bottom() == second
.bottom())
581 return first
.right() > second
.right();
582 return first
.bottom() > second
.bottom();
585 static bool rowRLTB(const Rect
&first
, const Rect
&second
) {
586 if (first
.y() == second
.y())
587 return first
.right() > second
.right();
588 return first
.y() < second
.y();
591 static bool rowLRBT(const Rect
&first
, const Rect
&second
) {
592 if (first
.bottom() == second
.bottom())
593 return first
.x() < second
.x();
594 return first
.bottom() > second
.bottom();
597 static bool rowLRTB(const Rect
&first
, const Rect
&second
) {
598 if (first
.y() == second
.y())
599 return first
.x() < second
.x();
600 return first
.y() < second
.y();
603 static bool colLRTB(const Rect
&first
, const Rect
&second
) {
604 if (first
.x() == second
.x())
605 return first
.y() < second
.y();
606 return first
.x() < second
.x();
609 static bool colLRBT(const Rect
&first
, const Rect
&second
) {
610 if (first
.x() == second
.x())
611 return first
.bottom() > second
.bottom();
612 return first
.x() < second
.x();
615 static bool colRLTB(const Rect
&first
, const Rect
&second
) {
616 if (first
.right() == second
.right())
617 return first
.y() < second
.y();
618 return first
.right() > second
.right();
621 static bool colRLBT(const Rect
&first
, const Rect
&second
) {
622 if (first
.right() == second
.right())
623 return first
.bottom() > second
.bottom();
624 return first
.right() > second
.right();
628 bool Workspace::smartPlacement(Rect
& win
) {
631 //initially the entire screen is free
633 if (screen
->isXineramaActive() &&
634 screen
->getBlackbox()->doXineramaPlacement()) {
635 RectList availableAreas
= screen
->allAvailableAreas();
636 RectList::iterator it
, end
= availableAreas
.end();
638 for (it
= availableAreas
.begin(); it
!= end
; ++it
) {
640 r
.setRect(r
.x() + screen
->getSnapOffset(),
641 r
.y() + screen
->getSnapOffset(),
642 r
.width() - screen
->getSnapOffset(),
643 r
.height() - screen
->getSnapOffset());
644 spaces
.push_back(*it
);
649 Rect r
= screen
->availableArea();
650 r
.setRect(r
.x() + screen
->getSnapOffset(),
651 r
.y() + screen
->getSnapOffset(),
652 r
.width() - screen
->getSnapOffset(),
653 r
.height() - screen
->getSnapOffset());
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());