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 std::for_each(stackingList
.begin(), stackingList
.end(),
465 std::mem_fun(&BlackboxWindow::show
));
467 XSync(screen
->getBlackbox()->getXDisplay(), False
);
469 if (screen
->doFocusLast()) {
470 if (! screen
->isSloppyFocus() && ! lastfocus
&& ! stackingList
.empty())
471 lastfocus
= stackingList
.front();
474 lastfocus
->setInputFocus();
479 bool Workspace::isCurrent(void) const {
480 return (id
== screen
->getCurrentWorkspaceID());
484 bool Workspace::isLastWindow(const BlackboxWindow
* const w
) const {
485 return (w
== windowList
.back());
489 void Workspace::setCurrent(void) {
490 screen
->changeWorkspaceID(id
);
494 void Workspace::readName(void) {
495 XAtom::StringVect namesList
;
496 unsigned long numnames
= id
+ 1;
498 // attempt to get from the _NET_WM_DESKTOP_NAMES property
499 if (xatom
->getValue(screen
->getRootWindow(), XAtom::net_desktop_names
,
500 XAtom::utf8
, numnames
, namesList
) &&
501 namesList
.size() > id
) {
502 name
= namesList
[id
];
504 clientmenu
->setLabel(name
);
505 clientmenu
->update();
508 Use a default name. This doesn't actually change the class. That will
509 happen after the setName changes the root property, and that change
510 makes its way back to this function.
512 string tmp
=i18n(WorkspaceSet
, WorkspaceDefaultNameFormat
,
514 assert(tmp
.length() < 32);
515 char default_name
[32];
516 sprintf(default_name
, tmp
.c_str(), id
+ 1);
518 setName(default_name
); // save this into the _NET_WM_DESKTOP_NAMES property
523 void Workspace::setName(const string
& new_name
) {
524 // set the _NET_WM_DESKTOP_NAMES property with the new name
525 XAtom::StringVect namesList
;
526 unsigned long numnames
= (unsigned) -1;
527 if (xatom
->getValue(screen
->getRootWindow(), XAtom::net_desktop_names
,
528 XAtom::utf8
, numnames
, namesList
) &&
529 namesList
.size() > id
)
530 namesList
[id
] = new_name
;
532 namesList
.push_back(new_name
);
534 xatom
->setValue(screen
->getRootWindow(), XAtom::net_desktop_names
,
535 XAtom::utf8
, namesList
);
540 * Calculate free space available for window placement.
542 typedef std::vector
<Rect
> rectList
;
544 static rectList
calcSpace(const Rect
&win
, const rectList
&spaces
) {
547 rectList::const_iterator siter
, end
= spaces
.end();
548 for (siter
= spaces
.begin(); siter
!= end
; ++siter
) {
549 const Rect
&curr
= *siter
;
551 if(! win
.intersects(curr
)) {
552 result
.push_back(curr
);
556 /* Use an intersection of win and curr to determine the space around
557 * curr that we can use.
559 * NOTE: the spaces calculated can overlap.
564 extra
.setCoords(curr
.left(), curr
.top(),
565 isect
.left() - 1, curr
.bottom());
566 if (extra
.valid()) result
.push_back(extra
);
569 extra
.setCoords(curr
.left(), curr
.top(),
570 curr
.right(), isect
.top() - 1);
571 if (extra
.valid()) result
.push_back(extra
);
574 extra
.setCoords(isect
.right() + 1, curr
.top(),
575 curr
.right(), curr
.bottom());
576 if (extra
.valid()) result
.push_back(extra
);
579 extra
.setCoords(curr
.left(), isect
.bottom() + 1,
580 curr
.right(), curr
.bottom());
581 if (extra
.valid()) result
.push_back(extra
);
587 static bool rowRLBT(const Rect
&first
, const Rect
&second
) {
588 if (first
.bottom() == second
.bottom())
589 return first
.right() > second
.right();
590 return first
.bottom() > second
.bottom();
593 static bool rowRLTB(const Rect
&first
, const Rect
&second
) {
594 if (first
.y() == second
.y())
595 return first
.right() > second
.right();
596 return first
.y() < second
.y();
599 static bool rowLRBT(const Rect
&first
, const Rect
&second
) {
600 if (first
.bottom() == second
.bottom())
601 return first
.x() < second
.x();
602 return first
.bottom() > second
.bottom();
605 static bool rowLRTB(const Rect
&first
, const Rect
&second
) {
606 if (first
.y() == second
.y())
607 return first
.x() < second
.x();
608 return first
.y() < second
.y();
611 static bool colLRTB(const Rect
&first
, const Rect
&second
) {
612 if (first
.x() == second
.x())
613 return first
.y() < second
.y();
614 return first
.x() < second
.x();
617 static bool colLRBT(const Rect
&first
, const Rect
&second
) {
618 if (first
.x() == second
.x())
619 return first
.bottom() > second
.bottom();
620 return first
.x() < second
.x();
623 static bool colRLTB(const Rect
&first
, const Rect
&second
) {
624 if (first
.right() == second
.right())
625 return first
.y() < second
.y();
626 return first
.right() > second
.right();
629 static bool colRLBT(const Rect
&first
, const Rect
&second
) {
630 if (first
.right() == second
.right())
631 return first
.bottom() > second
.bottom();
632 return first
.right() > second
.right();
636 bool Workspace::smartPlacement(Rect
& win
) {
639 //initially the entire screen is free
641 if (screen
->isXineramaActive() &&
642 screen
->getBlackbox()->doXineramaPlacement()) {
643 RectList availableAreas
= screen
->allAvailableAreas();
644 RectList::iterator it
, end
= availableAreas
.end();
646 for (it
= availableAreas
.begin(); it
!= end
; ++it
)
647 spaces
.push_back(*it
);
650 spaces
.push_back(screen
->availableArea());
653 BlackboxWindowList::const_iterator wit
= windowList
.begin(),
654 end
= windowList
.end();
656 for (; wit
!= end
; ++wit
) {
657 const BlackboxWindow
* const curr
= *wit
;
659 // watch for shaded windows and full-maxed windows
660 if (curr
->isShaded()) {
661 if (screen
->getPlaceIgnoreShaded()) continue;
662 } else if (curr
->isMaximizedFull()) {
663 if (screen
->getPlaceIgnoreMaximized()) continue;
666 tmp
.setRect(curr
->frameRect().x(), curr
->frameRect().y(),
667 curr
->frameRect().width() + screen
->getBorderWidth(),
668 curr
->frameRect().height() + screen
->getBorderWidth());
670 spaces
= calcSpace(tmp
, spaces
);
673 if (screen
->getPlacementPolicy() == BScreen::RowSmartPlacement
) {
674 if(screen
->getRowPlacementDirection() == BScreen::LeftRight
) {
675 if(screen
->getColPlacementDirection() == BScreen::TopBottom
)
676 std::sort(spaces
.begin(), spaces
.end(), rowLRTB
);
678 std::sort(spaces
.begin(), spaces
.end(), rowLRBT
);
680 if(screen
->getColPlacementDirection() == BScreen::TopBottom
)
681 std::sort(spaces
.begin(), spaces
.end(), rowRLTB
);
683 std::sort(spaces
.begin(), spaces
.end(), rowRLBT
);
686 if(screen
->getColPlacementDirection() == BScreen::TopBottom
) {
687 if(screen
->getRowPlacementDirection() == BScreen::LeftRight
)
688 std::sort(spaces
.begin(), spaces
.end(), colLRTB
);
690 std::sort(spaces
.begin(), spaces
.end(), colRLTB
);
692 if(screen
->getRowPlacementDirection() == BScreen::LeftRight
)
693 std::sort(spaces
.begin(), spaces
.end(), colLRBT
);
695 std::sort(spaces
.begin(), spaces
.end(), colRLBT
);
699 rectList::const_iterator sit
= spaces
.begin(), spaces_end
= spaces
.end();
700 for(; sit
!= spaces_end
; ++sit
) {
701 if (sit
->width() >= win
.width() && sit
->height() >= win
.height())
705 if (sit
== spaces_end
)
708 //set new position based on the empty space found
709 const Rect
& where
= *sit
;
713 // adjust the location() based on left/right and top/bottom placement
714 if (screen
->getPlacementPolicy() == BScreen::RowSmartPlacement
) {
715 if (screen
->getRowPlacementDirection() == BScreen::RightLeft
)
716 win
.setX(where
.right() - win
.width());
717 if (screen
->getColPlacementDirection() == BScreen::BottomTop
)
718 win
.setY(where
.bottom() - win
.height());
720 if (screen
->getColPlacementDirection() == BScreen::BottomTop
)
721 win
.setY(win
.y() + where
.height() - win
.height());
722 if (screen
->getRowPlacementDirection() == BScreen::RightLeft
)
723 win
.setX(win
.x() + where
.width() - win
.width());
729 bool Workspace::underMousePlacement(Rect
&win
) {
733 XQueryPointer(screen
->getBlackbox()->getXDisplay(), screen
->getRootWindow(),
734 &r
, &c
, &rx
, &ry
, &x
, &y
, &m
);
738 if (screen
->isXineramaActive() &&
739 screen
->getBlackbox()->doXineramaPlacement()) {
740 RectList availableAreas
= screen
->allAvailableAreas();
741 RectList::iterator it
, end
= availableAreas
.end();
743 for (it
= availableAreas
.begin(); it
!= end
; ++it
)
744 if (it
->contains(rx
, ry
)) break;
745 assert(it
!= end
); // the mouse isn't inside an area?
749 area
= screen
->availableArea();
751 x
= rx
- win
.width() / 2;
752 y
= ry
- win
.height() / 2;
758 if (x
+ win
.width() > area
.x() + area
.width())
759 x
= area
.x() + area
.width() - win
.width();
760 if (y
+ win
.height() > area
.y() + area
.height())
761 y
= area
.y() + area
.height() - win
.height();
770 bool Workspace::cascadePlacement(Rect
&win
, const int offset
) {
774 if (screen
->isXineramaActive() &&
775 screen
->getBlackbox()->doXineramaPlacement()) {
776 area
= screen
->allAvailableAreas()[cascade_region
];
779 area
= screen
->availableArea();
781 if ((static_cast<signed>(cascade_x
+ win
.width()) > area
.right() + 1) ||
782 (static_cast<signed>(cascade_y
+ win
.height()) > area
.bottom() + 1)) {
783 cascade_x
= cascade_y
= 0;
785 if (screen
->isXineramaActive() &&
786 screen
->getBlackbox()->doXineramaPlacement()) {
787 // go to the next xinerama region, and use its area
788 if (++cascade_region
>= screen
->allAvailableAreas().size())
790 area
= screen
->allAvailableAreas()[cascade_region
];
795 if (cascade_x
== 0) {
796 cascade_x
= area
.x() + offset
;
797 cascade_y
= area
.y() + offset
;
800 win
.setPos(cascade_x
, cascade_y
);
809 void Workspace::placeWindow(BlackboxWindow
*win
) {
810 Rect
new_win(0, 0, win
->frameRect().width(), win
->frameRect().height());
813 switch (screen
->getPlacementPolicy()) {
814 case BScreen::RowSmartPlacement
:
815 case BScreen::ColSmartPlacement
:
816 placed
= smartPlacement(new_win
);
818 case BScreen::UnderMousePlacement
:
819 case BScreen::ClickMousePlacement
:
820 placed
= underMousePlacement(new_win
);
822 break; // handled below
826 cascadePlacement(new_win
, (win
->getTitleHeight() +
827 screen
->getBorderWidth() * 2));
829 if (new_win
.right() > screen
->availableArea().right())
830 new_win
.setX(screen
->availableArea().left());
831 if (new_win
.bottom() > screen
->availableArea().bottom())
832 new_win
.setY(screen
->availableArea().top());
834 win
->configure(new_win
.x(), new_win
.y(), new_win
.width(), new_win
.height());