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())
108 not on the focused workspace, so the window is not going to get focus
109 but if the user wants new windows focused, then it should get focus
110 when this workspace does become focused.
117 if (! w
->isDesktop())
124 void Workspace::removeWindow(BlackboxWindow
*w
, bool sticky
) {
127 stackingList
.remove(w
);
129 // pass focus to the next appropriate window
130 if ((w
->isFocused() || w
== lastfocus
) &&
131 ! screen
->getBlackbox()->doShutdown()) {
135 if (! w
->isNormal()) return;
137 BlackboxWindowList::iterator it
, end
= windowList
.end();
139 for (i
= 0, it
= windowList
.begin(); it
!= end
; ++it
, ++i
)
144 windowList
.erase(it
);
145 clientmenu
->remove(i
);
146 clientmenu
->update();
149 screen
->updateNetizenWindowDel(w
->getClientWindow());
151 BlackboxWindowList::iterator it
= windowList
.begin();
152 const BlackboxWindowList::iterator end
= windowList
.end();
154 for (; it
!= end
; ++it
, ++i
)
155 (*it
)->setWindowNumber(i
);
159 cascade_x
= cascade_y
= 0;
167 void Workspace::focusFallback(const BlackboxWindow
*old_window
) {
168 BlackboxWindow
*newfocus
= 0;
170 if (id
== screen
->getCurrentWorkspaceID()) {
171 // The window is on the visible workspace.
173 // if it's a transient, then try to focus its parent
174 if (old_window
&& old_window
->isTransient()) {
175 newfocus
= old_window
->getTransientFor();
178 newfocus
->isIconic() || // do not focus icons
179 newfocus
->getWorkspaceNumber() != id
|| // or other workspaces
180 ! newfocus
->setInputFocus())
185 BlackboxWindowList::iterator it
= stackingList
.begin(),
186 end
= stackingList
.end();
187 for (; it
!= end
; ++it
) {
188 BlackboxWindow
*tmp
= *it
;
189 if (tmp
&& tmp
->isNormal() && tmp
->setInputFocus()) {
190 // we found our new focus target
197 screen
->getBlackbox()->setFocusedWindow(newfocus
);
199 // The window is not on the visible workspace.
201 if (old_window
&& lastfocus
== old_window
) {
202 // The window was the last-focus target, so we need to replace it.
203 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
204 if (! stackingList
.empty())
205 win
= stackingList
.front();
206 setLastFocusedWindow(win
);
212 void Workspace::setFocused(const BlackboxWindow
*w
, bool focused
) {
213 BlackboxWindowList::iterator it
, end
= windowList
.end();
215 for (i
= 0, it
= windowList
.begin(); it
!= end
; ++it
, ++i
)
218 // if its == end, then a window thats not in the windowList
219 // got focused, such as a !isNormal() window.
221 clientmenu
->setItemSelected(i
, focused
);
225 void Workspace::removeAll(void) {
226 while (! windowList
.empty())
227 windowList
.front()->iconify();
232 * returns the number of transients for win, plus the number of transients
233 * associated with each transient of win
235 static unsigned int countTransients(const BlackboxWindow
* const win
) {
236 BlackboxWindowList transients
= win
->getTransients();
237 if (transients
.empty()) return 0;
239 unsigned int ret
= transients
.size();
240 BlackboxWindowList::const_iterator it
= transients
.begin(),
241 end
= transients
.end();
242 for (; it
!= end
; ++it
)
243 ret
+= countTransients(*it
);
250 * puts the transients of win into the stack. windows are stacked above
251 * the window before it in the stackvector being iterated, meaning
252 * stack[0] is on bottom, stack[1] is above stack[0], stack[2] is above
255 void Workspace::raiseTransients(const BlackboxWindow
* const win
,
256 StackVector::iterator
&stack
) {
257 if (win
->getTransients().empty()) return; // nothing to do
259 // put win's transients in the stack
260 BlackboxWindowList::const_iterator it
, end
= win
->getTransients().end();
261 for (it
= win
->getTransients().begin(); it
!= end
; ++it
) {
262 BlackboxWindow
*w
= *it
;
263 *stack
++ = w
->getFrameWindow();
264 screen
->updateNetizenWindowRaise(w
->getClientWindow());
266 if (! w
->isIconic()) {
267 Workspace
*wkspc
= screen
->getWorkspace(w
->getWorkspaceNumber());
268 wkspc
->stackingList
.remove(w
);
269 wkspc
->stackingList
.push_front(w
);
273 // put transients of win's transients in the stack
274 for (it
= win
->getTransients().begin(); it
!= end
; ++it
)
275 raiseTransients(*it
, stack
);
279 void Workspace::lowerTransients(const BlackboxWindow
* const win
,
280 StackVector::iterator
&stack
) {
281 if (win
->getTransients().empty()) return; // nothing to do
283 // put transients of win's transients in the stack
284 BlackboxWindowList::const_reverse_iterator it
,
285 end
= win
->getTransients().rend();
286 for (it
= win
->getTransients().rbegin(); it
!= end
; ++it
)
287 lowerTransients(*it
, stack
);
289 // put win's transients in the stack
290 for (it
= win
->getTransients().rbegin(); it
!= end
; ++it
) {
291 BlackboxWindow
*w
= *it
;
292 *stack
++ = w
->getFrameWindow();
293 screen
->updateNetizenWindowLower(w
->getClientWindow());
295 if (! w
->isIconic()) {
296 Workspace
*wkspc
= screen
->getWorkspace(w
->getWorkspaceNumber());
297 wkspc
->stackingList
.remove(w
);
298 wkspc
->stackingList
.push_back(w
);
304 void Workspace::raiseWindow(BlackboxWindow
*w
) {
305 BlackboxWindow
*win
= w
;
307 if (win
->isDesktop()) return;
309 // walk up the transient_for's to the window that is not a transient
310 while (win
->isTransient() && win
->getTransientFor())
311 win
= win
->getTransientFor();
313 // get the total window count (win and all transients)
314 unsigned int i
= 1 + countTransients(win
);
316 // stack the window with all transients above
317 StackVector
stack_vector(i
);
318 StackVector::iterator stack
= stack_vector
.begin();
320 *(stack
++) = win
->getFrameWindow();
321 screen
->updateNetizenWindowRaise(win
->getClientWindow());
322 if (! (win
->isIconic() || win
->isDesktop())) {
323 Workspace
*wkspc
= screen
->getWorkspace(win
->getWorkspaceNumber());
324 wkspc
->stackingList
.remove(win
);
325 wkspc
->stackingList
.push_front(win
);
328 raiseTransients(win
, stack
);
330 screen
->raiseWindows(&stack_vector
[0], stack_vector
.size());
334 void Workspace::lowerWindow(BlackboxWindow
*w
) {
335 BlackboxWindow
*win
= w
;
337 // walk up the transient_for's to the window that is not a transient
338 while (win
->isTransient() && win
->getTransientFor())
339 win
= win
->getTransientFor();
341 // get the total window count (win and all transients)
342 unsigned int i
= 1 + countTransients(win
);
344 // stack the window with all transients above
345 StackVector
stack_vector(i
);
346 StackVector::iterator stack
= stack_vector
.begin();
348 lowerTransients(win
, stack
);
350 *(stack
++) = win
->getFrameWindow();
351 screen
->updateNetizenWindowLower(win
->getClientWindow());
352 if (! (win
->isIconic() || win
->isDesktop())) {
353 Workspace
*wkspc
= screen
->getWorkspace(win
->getWorkspaceNumber());
354 wkspc
->stackingList
.remove(win
);
355 wkspc
->stackingList
.push_back(win
);
358 screen
->lowerWindows(&stack_vector
[0], stack_vector
.size());
362 void Workspace::reconfigure(void) {
363 clientmenu
->reconfigure();
364 std::for_each(windowList
.begin(), windowList
.end(),
365 std::mem_fun(&BlackboxWindow::reconfigure
));
369 BlackboxWindow
*Workspace::getWindow(unsigned int index
) {
370 if (index
< windowList
.size()) {
371 BlackboxWindowList::iterator it
= windowList
.begin();
372 while (index
-- > 0) // increment to index
382 Workspace::getNextWindowInList(BlackboxWindow
*w
) {
383 BlackboxWindowList::iterator it
= std::find(windowList
.begin(),
386 assert(it
!= windowList
.end()); // window must be in list
388 if (it
== windowList
.end())
389 return windowList
.front(); // if we walked off the end, wrap around
395 BlackboxWindow
* Workspace::getPrevWindowInList(BlackboxWindow
*w
) {
396 BlackboxWindowList::iterator it
= std::find(windowList
.begin(),
399 assert(it
!= windowList
.end()); // window must be in list
400 if (it
== windowList
.begin())
401 return windowList
.back(); // if we walked of the front, wrap around
407 BlackboxWindow
* Workspace::getTopWindowOnStack(void) const {
408 assert(! stackingList
.empty());
409 return stackingList
.front();
413 void Workspace::sendWindowList(Netizen
&n
) {
414 BlackboxWindowList::iterator it
= windowList
.begin(),
415 end
= windowList
.end();
416 for(; it
!= end
; ++it
)
417 n
.sendWindowAdd((*it
)->getClientWindow(), getID());
421 unsigned int Workspace::getCount(void) const {
422 return windowList
.size();
426 void Workspace::appendStackOrder(BlackboxWindowList
&stack_order
) const {
427 BlackboxWindowList::const_reverse_iterator it
= stackingList
.rbegin();
428 const BlackboxWindowList::const_reverse_iterator end
= stackingList
.rend();
429 for (; it
!= end
; ++it
)
430 if ((*it
)->isNormal())
431 stack_order
.push_back(*it
);
435 void Workspace::hide(void) {
436 BlackboxWindow
*focused
= screen
->getBlackbox()->getFocusedWindow();
437 if (focused
&& focused
->getScreen() == screen
) {
438 assert(focused
->isStuck() || focused
->getWorkspaceNumber() == id
);
442 // if no window had focus, no need to store a last focus
443 lastfocus
= (BlackboxWindow
*) 0;
446 // when we switch workspaces, unfocus whatever was focused
447 screen
->getBlackbox()->setFocusedWindow((BlackboxWindow
*) 0);
449 // withdraw windows in reverse order to minimize the number of Expose events
451 BlackboxWindowList::reverse_iterator it
= stackingList
.rbegin();
452 const BlackboxWindowList::reverse_iterator end
= stackingList
.rend();
453 for (; it
!= end
; ++it
) {
454 BlackboxWindow
*bw
= *it
;
455 // not normal windows cant focus from mouse enters anyways, so we dont
456 // need to unmap/remap them on workspace changes
457 if (! bw
->isStuck() || bw
->isNormal())
463 void Workspace::show(void) {
464 BlackboxWindowList::iterator it
= stackingList
.begin();
465 const BlackboxWindowList::iterator end
= stackingList
.end();
466 for (; it
!= end
; ++it
) {
467 BlackboxWindow
*bw
= *it
;
468 // not normal windows cant focus from mouse enters anyways, so we dont
469 // need to unmap/remap them on workspace changes
470 if (! bw
->isStuck() || bw
->isNormal())
474 XSync(screen
->getBlackbox()->getXDisplay(), False
);
476 if (screen
->doFocusLast()) {
477 if (! screen
->isSloppyFocus() && ! lastfocus
&& ! stackingList
.empty())
478 lastfocus
= stackingList
.front();
481 lastfocus
->setInputFocus();
486 bool Workspace::isCurrent(void) const {
487 return (id
== screen
->getCurrentWorkspaceID());
491 bool Workspace::isLastWindow(const BlackboxWindow
* const w
) const {
492 return (w
== windowList
.back());
496 void Workspace::setCurrent(void) {
497 screen
->changeWorkspaceID(id
);
501 void Workspace::readName(void) {
502 XAtom::StringVect namesList
;
503 unsigned long numnames
= id
+ 1;
505 // attempt to get from the _NET_WM_DESKTOP_NAMES property
506 if (xatom
->getValue(screen
->getRootWindow(), XAtom::net_desktop_names
,
507 XAtom::utf8
, numnames
, namesList
) &&
508 namesList
.size() > id
) {
509 name
= namesList
[id
];
511 clientmenu
->setLabel(name
);
512 clientmenu
->update();
515 Use a default name. This doesn't actually change the class. That will
516 happen after the setName changes the root property, and that change
517 makes its way back to this function.
519 string tmp
=i18n(WorkspaceSet
, WorkspaceDefaultNameFormat
,
521 assert(tmp
.length() < 32);
522 char default_name
[32];
523 sprintf(default_name
, tmp
.c_str(), id
+ 1);
525 setName(default_name
); // save this into the _NET_WM_DESKTOP_NAMES property
530 void Workspace::setName(const string
& new_name
) {
531 // set the _NET_WM_DESKTOP_NAMES property with the new name
532 XAtom::StringVect namesList
;
533 unsigned long numnames
= (unsigned) -1;
534 if (xatom
->getValue(screen
->getRootWindow(), XAtom::net_desktop_names
,
535 XAtom::utf8
, numnames
, namesList
) &&
536 namesList
.size() > id
)
537 namesList
[id
] = new_name
;
539 namesList
.push_back(new_name
);
541 xatom
->setValue(screen
->getRootWindow(), XAtom::net_desktop_names
,
542 XAtom::utf8
, namesList
);
547 * Calculate free space available for window placement.
549 typedef std::vector
<Rect
> rectList
;
551 static rectList
calcSpace(const Rect
&win
, const rectList
&spaces
) {
554 rectList::const_iterator siter
, end
= spaces
.end();
555 for (siter
= spaces
.begin(); siter
!= end
; ++siter
) {
556 const Rect
&curr
= *siter
;
558 if(! win
.intersects(curr
)) {
559 result
.push_back(curr
);
563 /* Use an intersection of win and curr to determine the space around
564 * curr that we can use.
566 * NOTE: the spaces calculated can overlap.
571 extra
.setCoords(curr
.left(), curr
.top(),
572 isect
.left() - 1, curr
.bottom());
573 if (extra
.valid()) result
.push_back(extra
);
576 extra
.setCoords(curr
.left(), curr
.top(),
577 curr
.right(), isect
.top() - 1);
578 if (extra
.valid()) result
.push_back(extra
);
581 extra
.setCoords(isect
.right() + 1, curr
.top(),
582 curr
.right(), curr
.bottom());
583 if (extra
.valid()) result
.push_back(extra
);
586 extra
.setCoords(curr
.left(), isect
.bottom() + 1,
587 curr
.right(), curr
.bottom());
588 if (extra
.valid()) result
.push_back(extra
);
594 static bool rowRLBT(const Rect
&first
, const Rect
&second
) {
595 if (first
.bottom() == second
.bottom())
596 return first
.right() > second
.right();
597 return first
.bottom() > second
.bottom();
600 static bool rowRLTB(const Rect
&first
, const Rect
&second
) {
601 if (first
.y() == second
.y())
602 return first
.right() > second
.right();
603 return first
.y() < second
.y();
606 static bool rowLRBT(const Rect
&first
, const Rect
&second
) {
607 if (first
.bottom() == second
.bottom())
608 return first
.x() < second
.x();
609 return first
.bottom() > second
.bottom();
612 static bool rowLRTB(const Rect
&first
, const Rect
&second
) {
613 if (first
.y() == second
.y())
614 return first
.x() < second
.x();
615 return first
.y() < second
.y();
618 static bool colLRTB(const Rect
&first
, const Rect
&second
) {
619 if (first
.x() == second
.x())
620 return first
.y() < second
.y();
621 return first
.x() < second
.x();
624 static bool colLRBT(const Rect
&first
, const Rect
&second
) {
625 if (first
.x() == second
.x())
626 return first
.bottom() > second
.bottom();
627 return first
.x() < second
.x();
630 static bool colRLTB(const Rect
&first
, const Rect
&second
) {
631 if (first
.right() == second
.right())
632 return first
.y() < second
.y();
633 return first
.right() > second
.right();
636 static bool colRLBT(const Rect
&first
, const Rect
&second
) {
637 if (first
.right() == second
.right())
638 return first
.bottom() > second
.bottom();
639 return first
.right() > second
.right();
643 bool Workspace::smartPlacement(Rect
& win
) {
646 //initially the entire screen is free
648 if (screen
->isXineramaActive() &&
649 screen
->getBlackbox()->doXineramaPlacement()) {
650 RectList availableAreas
= screen
->allAvailableAreas();
651 RectList::iterator it
, end
= availableAreas
.end();
653 for (it
= availableAreas
.begin(); it
!= end
; ++it
)
654 spaces
.push_back(*it
);
657 spaces
.push_back(screen
->availableArea());
660 BlackboxWindowList::const_iterator wit
= windowList
.begin(),
661 end
= windowList
.end();
663 for (; wit
!= end
; ++wit
) {
664 const BlackboxWindow
* const curr
= *wit
;
666 // watch for shaded windows and full-maxed windows
667 if (curr
->isShaded()) {
668 if (screen
->getPlaceIgnoreShaded()) continue;
669 } else if (curr
->isMaximizedFull()) {
670 if (screen
->getPlaceIgnoreMaximized()) continue;
673 tmp
.setRect(curr
->frameRect().x(), curr
->frameRect().y(),
674 curr
->frameRect().width() + screen
->getBorderWidth(),
675 curr
->frameRect().height() + screen
->getBorderWidth());
677 spaces
= calcSpace(tmp
, spaces
);
680 if (screen
->getPlacementPolicy() == BScreen::RowSmartPlacement
) {
681 if(screen
->getRowPlacementDirection() == BScreen::LeftRight
) {
682 if(screen
->getColPlacementDirection() == BScreen::TopBottom
)
683 std::sort(spaces
.begin(), spaces
.end(), rowLRTB
);
685 std::sort(spaces
.begin(), spaces
.end(), rowLRBT
);
687 if(screen
->getColPlacementDirection() == BScreen::TopBottom
)
688 std::sort(spaces
.begin(), spaces
.end(), rowRLTB
);
690 std::sort(spaces
.begin(), spaces
.end(), rowRLBT
);
693 if(screen
->getColPlacementDirection() == BScreen::TopBottom
) {
694 if(screen
->getRowPlacementDirection() == BScreen::LeftRight
)
695 std::sort(spaces
.begin(), spaces
.end(), colLRTB
);
697 std::sort(spaces
.begin(), spaces
.end(), colRLTB
);
699 if(screen
->getRowPlacementDirection() == BScreen::LeftRight
)
700 std::sort(spaces
.begin(), spaces
.end(), colLRBT
);
702 std::sort(spaces
.begin(), spaces
.end(), colRLBT
);
706 rectList::const_iterator sit
= spaces
.begin(), spaces_end
= spaces
.end();
707 for(; sit
!= spaces_end
; ++sit
) {
708 if (sit
->width() >= win
.width() && sit
->height() >= win
.height())
712 if (sit
== spaces_end
)
715 //set new position based on the empty space found
716 const Rect
& where
= *sit
;
720 // adjust the location() based on left/right and top/bottom placement
721 if (screen
->getPlacementPolicy() == BScreen::RowSmartPlacement
) {
722 if (screen
->getRowPlacementDirection() == BScreen::RightLeft
)
723 win
.setX(where
.right() - win
.width());
724 if (screen
->getColPlacementDirection() == BScreen::BottomTop
)
725 win
.setY(where
.bottom() - win
.height());
727 if (screen
->getColPlacementDirection() == BScreen::BottomTop
)
728 win
.setY(win
.y() + where
.height() - win
.height());
729 if (screen
->getRowPlacementDirection() == BScreen::RightLeft
)
730 win
.setX(win
.x() + where
.width() - win
.width());
736 bool Workspace::underMousePlacement(Rect
&win
) {
740 XQueryPointer(screen
->getBlackbox()->getXDisplay(), screen
->getRootWindow(),
741 &r
, &c
, &rx
, &ry
, &x
, &y
, &m
);
745 if (screen
->isXineramaActive() &&
746 screen
->getBlackbox()->doXineramaPlacement()) {
747 RectList availableAreas
= screen
->allAvailableAreas();
748 RectList::iterator it
, end
= availableAreas
.end();
750 for (it
= availableAreas
.begin(); it
!= end
; ++it
)
751 if (it
->contains(rx
, ry
)) break;
752 assert(it
!= end
); // the mouse isn't inside an area?
756 area
= screen
->availableArea();
758 x
= rx
- win
.width() / 2;
759 y
= ry
- win
.height() / 2;
765 if (x
+ win
.width() > area
.x() + area
.width())
766 x
= area
.x() + area
.width() - win
.width();
767 if (y
+ win
.height() > area
.y() + area
.height())
768 y
= area
.y() + area
.height() - win
.height();
777 bool Workspace::cascadePlacement(Rect
&win
, const int offset
) {
781 if (screen
->isXineramaActive() &&
782 screen
->getBlackbox()->doXineramaPlacement()) {
783 area
= screen
->allAvailableAreas()[cascade_region
];
786 area
= screen
->availableArea();
788 if ((static_cast<signed>(cascade_x
+ win
.width()) > area
.right() + 1) ||
789 (static_cast<signed>(cascade_y
+ win
.height()) > area
.bottom() + 1)) {
790 cascade_x
= cascade_y
= 0;
792 if (screen
->isXineramaActive() &&
793 screen
->getBlackbox()->doXineramaPlacement()) {
794 // go to the next xinerama region, and use its area
795 if (++cascade_region
>= screen
->allAvailableAreas().size())
797 area
= screen
->allAvailableAreas()[cascade_region
];
802 if (cascade_x
== 0) {
803 cascade_x
= area
.x() + offset
;
804 cascade_y
= area
.y() + offset
;
807 win
.setPos(cascade_x
, cascade_y
);
816 void Workspace::placeWindow(BlackboxWindow
*win
) {
817 Rect
new_win(0, 0, win
->frameRect().width(), win
->frameRect().height());
820 switch (screen
->getPlacementPolicy()) {
821 case BScreen::RowSmartPlacement
:
822 case BScreen::ColSmartPlacement
:
823 placed
= smartPlacement(new_win
);
825 case BScreen::UnderMousePlacement
:
826 case BScreen::ClickMousePlacement
:
827 placed
= underMousePlacement(new_win
);
829 break; // handled below
833 cascadePlacement(new_win
, (win
->getTitleHeight() +
834 screen
->getBorderWidth() * 2));
836 if (new_win
.right() > screen
->availableArea().right())
837 new_win
.setX(screen
->availableArea().left());
838 if (new_win
.bottom() > screen
->availableArea().bottom())
839 new_win
.setY(screen
->availableArea().top());
841 win
->configure(new_win
.x(), new_win
.y(), new_win
.width(), new_win
.height());