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 if (! w
->isNormal()) {
93 // just give it some number, else bad things happen as it is assumed to
94 // not be on a workspace
95 w
->setWindowNumber(0);
99 w
->setWindowNumber(windowList
.size());
101 windowList
.push_back(w
);
103 clientmenu
->insert(w
->getTitle());
104 clientmenu
->update();
107 screen
->updateNetizenWindowAdd(w
->getClientWindow(), id
);
109 if (screen
->doFocusNew() || (w
->isTransient() && w
->getTransientFor() &&
110 w
->getTransientFor()->isFocused())) {
111 if (id
!= screen
->getCurrentWorkspaceID()) {
113 not on the focused workspace, so the window is not going to get focus
114 but if the user wants new windows focused, then it should get focus
115 when this workspace does become focused.
122 if (! w
->isDesktop())
129 void Workspace::removeWindow(BlackboxWindow
*w
, bool sticky
) {
132 stackingList
.remove(w
);
134 // pass focus to the next appropriate window
135 if ((w
->isFocused() || w
== lastfocus
) &&
136 ! screen
->getBlackbox()->doShutdown()) {
140 if (! w
->isNormal()) return;
142 BlackboxWindowList::iterator it
, end
= windowList
.end();
144 for (i
= 0, it
= windowList
.begin(); it
!= end
; ++it
, ++i
)
149 windowList
.erase(it
);
150 clientmenu
->remove(i
);
151 clientmenu
->update();
154 screen
->updateNetizenWindowDel(w
->getClientWindow());
156 BlackboxWindowList::iterator it
= windowList
.begin();
157 const BlackboxWindowList::iterator end
= windowList
.end();
159 for (; it
!= end
; ++it
, ++i
)
160 (*it
)->setWindowNumber(i
);
164 cascade_x
= cascade_y
= 0;
172 void Workspace::focusFallback(const BlackboxWindow
*old_window
) {
173 BlackboxWindow
*newfocus
= 0;
175 if (id
== screen
->getCurrentWorkspaceID()) {
176 // The window is on the visible workspace.
178 // if it's a transient, then try to focus its parent
179 if (old_window
&& old_window
->isTransient()) {
180 newfocus
= old_window
->getTransientFor();
183 newfocus
->isIconic() || // do not focus icons
184 newfocus
->getWorkspaceNumber() != id
|| // or other workspaces
185 ! newfocus
->setInputFocus())
190 BlackboxWindowList::iterator it
= stackingList
.begin(),
191 end
= stackingList
.end();
192 for (; it
!= end
; ++it
) {
193 BlackboxWindow
*tmp
= *it
;
194 if (tmp
&& tmp
->isNormal() && tmp
->setInputFocus()) {
195 // we found our new focus target
202 screen
->getBlackbox()->setFocusedWindow(newfocus
);
204 // The window is not on the visible workspace.
206 if (old_window
&& lastfocus
== old_window
) {
207 // The window was the last-focus target, so we need to replace it.
208 BlackboxWindow
*win
= (BlackboxWindow
*) 0;
209 if (! stackingList
.empty())
210 win
= stackingList
.front();
211 setLastFocusedWindow(win
);
217 void Workspace::setFocused(const BlackboxWindow
*w
, bool focused
) {
218 BlackboxWindowList::iterator it
, end
= windowList
.end();
220 for (i
= 0, it
= windowList
.begin(); it
!= end
; ++it
, ++i
)
223 // if its == end, then a window thats not in the windowList
224 // got focused, such as a !isNormal() window.
226 clientmenu
->setItemSelected(i
, focused
);
230 void Workspace::removeAll(void) {
231 while (! windowList
.empty())
232 windowList
.front()->iconify();
235 void Workspace::showAll(void) {
236 BlackboxWindowList::iterator it
= stackingList
.begin();
237 const BlackboxWindowList::iterator end
= stackingList
.end();
238 for (; it
!= end
; ++it
) {
239 BlackboxWindow
*bw
= *it
;
240 // not normal windows cant focus from mouse enters anyways, so we dont
241 // need to unmap/remap them on workspace changes
242 if (! bw
->isStuck() || bw
->isNormal())
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 // not normal windows cant focus from mouse enters anyways, so we dont
258 // need to unmap/remap them on workspace changes
259 if (! bw
->isStuck() || bw
->isNormal())
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 if ((*it
)->isNormal())
466 stack_order
.push_back(*it
);
470 bool Workspace::isCurrent(void) const {
471 return (id
== screen
->getCurrentWorkspaceID());
475 bool Workspace::isLastWindow(const BlackboxWindow
* const w
) const {
476 return (w
== windowList
.back());
480 void Workspace::setCurrent(void) {
481 screen
->changeWorkspaceID(id
);
485 void Workspace::readName(void) {
486 XAtom::StringVect namesList
;
487 unsigned long numnames
= id
+ 1;
489 // attempt to get from the _NET_WM_DESKTOP_NAMES property
490 if (xatom
->getValue(screen
->getRootWindow(), XAtom::net_desktop_names
,
491 XAtom::utf8
, numnames
, namesList
) &&
492 namesList
.size() > id
) {
493 name
= namesList
[id
];
495 clientmenu
->setLabel(name
);
496 clientmenu
->update();
499 Use a default name. This doesn't actually change the class. That will
500 happen after the setName changes the root property, and that change
501 makes its way back to this function.
503 string tmp
=i18n(WorkspaceSet
, WorkspaceDefaultNameFormat
,
505 assert(tmp
.length() < 32);
506 char default_name
[32];
507 sprintf(default_name
, tmp
.c_str(), id
+ 1);
509 setName(default_name
); // save this into the _NET_WM_DESKTOP_NAMES property
514 void Workspace::setName(const string
& new_name
) {
515 // set the _NET_WM_DESKTOP_NAMES property with the new name
516 XAtom::StringVect namesList
;
517 unsigned long numnames
= (unsigned) -1;
518 if (xatom
->getValue(screen
->getRootWindow(), XAtom::net_desktop_names
,
519 XAtom::utf8
, numnames
, namesList
) &&
520 namesList
.size() > id
)
521 namesList
[id
] = new_name
;
523 namesList
.push_back(new_name
);
525 xatom
->setValue(screen
->getRootWindow(), XAtom::net_desktop_names
,
526 XAtom::utf8
, namesList
);
531 * Calculate free space available for window placement.
533 typedef std::vector
<Rect
> rectList
;
535 static rectList
calcSpace(const Rect
&win
, const rectList
&spaces
) {
538 rectList::const_iterator siter
, end
= spaces
.end();
539 for (siter
= spaces
.begin(); siter
!= end
; ++siter
) {
540 const Rect
&curr
= *siter
;
542 if(! win
.intersects(curr
)) {
543 result
.push_back(curr
);
547 /* Use an intersection of win and curr to determine the space around
548 * curr that we can use.
550 * NOTE: the spaces calculated can overlap.
555 extra
.setCoords(curr
.left(), curr
.top(),
556 isect
.left() - 1, curr
.bottom());
557 if (extra
.valid()) result
.push_back(extra
);
560 extra
.setCoords(curr
.left(), curr
.top(),
561 curr
.right(), isect
.top() - 1);
562 if (extra
.valid()) result
.push_back(extra
);
565 extra
.setCoords(isect
.right() + 1, curr
.top(),
566 curr
.right(), curr
.bottom());
567 if (extra
.valid()) result
.push_back(extra
);
570 extra
.setCoords(curr
.left(), isect
.bottom() + 1,
571 curr
.right(), curr
.bottom());
572 if (extra
.valid()) result
.push_back(extra
);
578 static bool rowRLBT(const Rect
&first
, const Rect
&second
) {
579 if (first
.bottom() == second
.bottom())
580 return first
.right() > second
.right();
581 return first
.bottom() > second
.bottom();
584 static bool rowRLTB(const Rect
&first
, const Rect
&second
) {
585 if (first
.y() == second
.y())
586 return first
.right() > second
.right();
587 return first
.y() < second
.y();
590 static bool rowLRBT(const Rect
&first
, const Rect
&second
) {
591 if (first
.bottom() == second
.bottom())
592 return first
.x() < second
.x();
593 return first
.bottom() > second
.bottom();
596 static bool rowLRTB(const Rect
&first
, const Rect
&second
) {
597 if (first
.y() == second
.y())
598 return first
.x() < second
.x();
599 return first
.y() < second
.y();
602 static bool colLRTB(const Rect
&first
, const Rect
&second
) {
603 if (first
.x() == second
.x())
604 return first
.y() < second
.y();
605 return first
.x() < second
.x();
608 static bool colLRBT(const Rect
&first
, const Rect
&second
) {
609 if (first
.x() == second
.x())
610 return first
.bottom() > second
.bottom();
611 return first
.x() < second
.x();
614 static bool colRLTB(const Rect
&first
, const Rect
&second
) {
615 if (first
.right() == second
.right())
616 return first
.y() < second
.y();
617 return first
.right() > second
.right();
620 static bool colRLBT(const Rect
&first
, const Rect
&second
) {
621 if (first
.right() == second
.right())
622 return first
.bottom() > second
.bottom();
623 return first
.right() > second
.right();
627 bool Workspace::smartPlacement(Rect
& win
) {
630 //initially the entire screen is free
632 if (screen
->isXineramaActive() &&
633 screen
->getBlackbox()->doXineramaPlacement()) {
634 RectList availableAreas
= screen
->allAvailableAreas();
635 RectList::iterator it
, end
= availableAreas
.end();
637 for (it
= availableAreas
.begin(); it
!= end
; ++it
)
638 spaces
.push_back(*it
);
641 spaces
.push_back(screen
->availableArea());
644 BlackboxWindowList::const_iterator wit
= windowList
.begin(),
645 end
= windowList
.end();
647 for (; wit
!= end
; ++wit
) {
648 const BlackboxWindow
* const curr
= *wit
;
650 // watch for shaded windows and full-maxed windows
651 if (curr
->isShaded()) {
652 if (screen
->getPlaceIgnoreShaded()) continue;
653 } else if (curr
->isMaximizedFull()) {
654 if (screen
->getPlaceIgnoreMaximized()) continue;
657 tmp
.setRect(curr
->frameRect().x(), curr
->frameRect().y(),
658 curr
->frameRect().width() + screen
->getBorderWidth(),
659 curr
->frameRect().height() + screen
->getBorderWidth());
661 spaces
= calcSpace(tmp
, spaces
);
664 if (screen
->getPlacementPolicy() == BScreen::RowSmartPlacement
) {
665 if(screen
->getRowPlacementDirection() == BScreen::LeftRight
) {
666 if(screen
->getColPlacementDirection() == BScreen::TopBottom
)
667 std::sort(spaces
.begin(), spaces
.end(), rowLRTB
);
669 std::sort(spaces
.begin(), spaces
.end(), rowLRBT
);
671 if(screen
->getColPlacementDirection() == BScreen::TopBottom
)
672 std::sort(spaces
.begin(), spaces
.end(), rowRLTB
);
674 std::sort(spaces
.begin(), spaces
.end(), rowRLBT
);
677 if(screen
->getColPlacementDirection() == BScreen::TopBottom
) {
678 if(screen
->getRowPlacementDirection() == BScreen::LeftRight
)
679 std::sort(spaces
.begin(), spaces
.end(), colLRTB
);
681 std::sort(spaces
.begin(), spaces
.end(), colRLTB
);
683 if(screen
->getRowPlacementDirection() == BScreen::LeftRight
)
684 std::sort(spaces
.begin(), spaces
.end(), colLRBT
);
686 std::sort(spaces
.begin(), spaces
.end(), colRLBT
);
690 rectList::const_iterator sit
= spaces
.begin(), spaces_end
= spaces
.end();
691 for(; sit
!= spaces_end
; ++sit
) {
692 if (sit
->width() >= win
.width() && sit
->height() >= win
.height())
696 if (sit
== spaces_end
)
699 //set new position based on the empty space found
700 const Rect
& where
= *sit
;
704 // adjust the location() based on left/right and top/bottom placement
705 if (screen
->getPlacementPolicy() == BScreen::RowSmartPlacement
) {
706 if (screen
->getRowPlacementDirection() == BScreen::RightLeft
)
707 win
.setX(where
.right() - win
.width());
708 if (screen
->getColPlacementDirection() == BScreen::BottomTop
)
709 win
.setY(where
.bottom() - win
.height());
711 if (screen
->getColPlacementDirection() == BScreen::BottomTop
)
712 win
.setY(win
.y() + where
.height() - win
.height());
713 if (screen
->getRowPlacementDirection() == BScreen::RightLeft
)
714 win
.setX(win
.x() + where
.width() - win
.width());
720 bool Workspace::underMousePlacement(Rect
&win
) {
724 XQueryPointer(screen
->getBlackbox()->getXDisplay(), screen
->getRootWindow(),
725 &r
, &c
, &rx
, &ry
, &x
, &y
, &m
);
729 if (screen
->isXineramaActive() &&
730 screen
->getBlackbox()->doXineramaPlacement()) {
731 RectList availableAreas
= screen
->allAvailableAreas();
732 RectList::iterator it
, end
= availableAreas
.end();
734 for (it
= availableAreas
.begin(); it
!= end
; ++it
)
735 if (it
->contains(rx
, ry
)) break;
736 assert(it
!= end
); // the mouse isn't inside an area?
740 area
= screen
->availableArea();
742 x
= rx
- win
.width() / 2;
743 y
= ry
- win
.height() / 2;
749 if (x
+ win
.width() > area
.x() + area
.width())
750 x
= area
.x() + area
.width() - win
.width();
751 if (y
+ win
.height() > area
.y() + area
.height())
752 y
= area
.y() + area
.height() - win
.height();
761 bool Workspace::cascadePlacement(Rect
&win
, const int offset
) {
765 if (screen
->isXineramaActive() &&
766 screen
->getBlackbox()->doXineramaPlacement()) {
767 area
= screen
->allAvailableAreas()[cascade_region
];
770 area
= screen
->availableArea();
772 if ((static_cast<signed>(cascade_x
+ win
.width()) > area
.right() + 1) ||
773 (static_cast<signed>(cascade_y
+ win
.height()) > area
.bottom() + 1)) {
774 cascade_x
= cascade_y
= 0;
776 if (screen
->isXineramaActive() &&
777 screen
->getBlackbox()->doXineramaPlacement()) {
778 // go to the next xinerama region, and use its area
779 if (++cascade_region
>= screen
->allAvailableAreas().size())
781 area
= screen
->allAvailableAreas()[cascade_region
];
786 if (cascade_x
== 0) {
787 cascade_x
= area
.x() + offset
;
788 cascade_y
= area
.y() + offset
;
791 win
.setPos(cascade_x
, cascade_y
);
800 void Workspace::placeWindow(BlackboxWindow
*win
) {
801 Rect
new_win(0, 0, win
->frameRect().width(), win
->frameRect().height());
804 switch (screen
->getPlacementPolicy()) {
805 case BScreen::RowSmartPlacement
:
806 case BScreen::ColSmartPlacement
:
807 placed
= smartPlacement(new_win
);
809 case BScreen::UnderMousePlacement
:
810 case BScreen::ClickMousePlacement
:
811 placed
= underMousePlacement(new_win
);
813 break; // handled below
817 cascadePlacement(new_win
, (win
->getTitleHeight() +
818 screen
->getBorderWidth() * 2));
820 if (new_win
.right() > screen
->availableArea().right())
821 new_win
.setX(screen
->availableArea().left());
822 if (new_win
.bottom() > screen
->availableArea().bottom())
823 new_win
.setY(screen
->availableArea().top());
825 win
->configure(new_win
.x(), new_win
.y(), new_win
.width(), new_win
.height());