]> Dogcows Code - chaz/openbox/blob - src/workspace.cc
big fat commit..
[chaz/openbox] / src / workspace.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #ifdef HAVE_CONFIG_H
4 # include "../config.h"
5 #endif // HAVE_CONFIG_H
6
7 extern "C" {
8 #include <X11/Xlib.h>
9 #include <X11/Xatom.h>
10
11 #ifdef HAVE_STDIO_H
12 # include <stdio.h>
13 #endif // HAVE_STDIO_H
14
15 #ifdef HAVE_STRING_H
16 # include <string.h>
17 #endif // HAVE_STRING_H
18 }
19
20 #include <assert.h>
21
22 #include <functional>
23 #include <string>
24
25 using std::string;
26
27 #include "blackbox.hh"
28 #include "font.hh"
29 #include "screen.hh"
30 #include "util.hh"
31 #include "window.hh"
32 #include "workspace.hh"
33 #include "xatom.hh"
34
35
36 Workspace::Workspace(BScreen *scrn, unsigned int i) {
37 screen = scrn;
38 xatom = screen->getBlackbox()->getXAtom();
39
40 cascade_x = cascade_y = 0;
41 #ifdef XINERAMA
42 cascade_region = 0;
43 #endif // XINERAMA
44
45 id = i;
46
47 lastfocus = (BlackboxWindow *) 0;
48
49 readName();
50 }
51
52
53 void Workspace::addWindow(BlackboxWindow *w, bool place, bool sticky) {
54 assert(w != 0);
55
56 if (place) placeWindow(w);
57
58 stackingList.push_front(w);
59
60 if (! sticky)
61 w->setWorkspace(id);
62
63 if (! w->isNormal()) {
64 if (! sticky) {
65 // just give it some number, else bad things happen as it is assumed to
66 // not be on a workspace
67 w->setWindowNumber(0);
68 }
69 } else {
70 if (! sticky)
71 w->setWindowNumber(windowList.size());
72
73 windowList.push_back(w);
74
75 if (screen->doFocusNew() || (w->isTransient() && w->getTransientFor() &&
76 w->getTransientFor()->isFocused())) {
77 if (id != screen->getCurrentWorkspaceID()) {
78 /*
79 not on the focused workspace, so the window is not going to get focus
80 but if the user wants new windows focused, then it should get focus
81 when this workspace does become focused.
82 */
83 lastfocus = w;
84 }
85 }
86 }
87
88 if (! w->isDesktop())
89 raiseWindow(w);
90 else
91 lowerWindow(w);
92 }
93
94
95 void Workspace::removeWindow(BlackboxWindow *w, bool sticky) {
96 assert(w != 0);
97
98 stackingList.remove(w);
99
100 // pass focus to the next appropriate window
101 if ((w->isFocused() || w == lastfocus) &&
102 ! screen->getBlackbox()->doShutdown()) {
103 focusFallback(w);
104 }
105
106 if (! w->isNormal()) return;
107
108 BlackboxWindowList::iterator it, end = windowList.end();
109 int i;
110 for (i = 0, it = windowList.begin(); it != end; ++it, ++i)
111 if (*it == w)
112 break;
113 assert(it != end);
114
115 windowList.erase(it);
116 if (! sticky) {
117 BlackboxWindowList::iterator it = windowList.begin();
118 const BlackboxWindowList::iterator end = windowList.end();
119 unsigned int i = 0;
120 for (; it != end; ++it, ++i)
121 (*it)->setWindowNumber(i);
122 }
123
124 if (i == 0) {
125 cascade_x = cascade_y = 0;
126 #ifdef XINERAMA
127 cascade_region = 0;
128 #endif // XINERAMA
129 }
130 }
131
132
133 void Workspace::focusFallback(const BlackboxWindow *old_window) {
134 BlackboxWindow *newfocus = 0;
135
136 if (id == screen->getCurrentWorkspaceID()) {
137 // The window is on the visible workspace.
138
139 // if it's a transient, then try to focus its parent
140 if (old_window && old_window->isTransient()) {
141 newfocus = old_window->getTransientFor();
142
143 if (! newfocus ||
144 newfocus->isIconic() || // do not focus icons
145 newfocus->getWorkspaceNumber() != id || // or other workspaces
146 ! newfocus->setInputFocus())
147 newfocus = 0;
148 }
149
150 if (! newfocus) {
151 BlackboxWindowList::iterator it = stackingList.begin(),
152 end = stackingList.end();
153 for (; it != end; ++it) {
154 BlackboxWindow *tmp = *it;
155 if (tmp && tmp->isNormal() && tmp->setInputFocus()) {
156 // we found our new focus target
157 newfocus = tmp;
158 break;
159 }
160 }
161 }
162
163 screen->getBlackbox()->setFocusedWindow(newfocus);
164 } else {
165 // The window is not on the visible workspace.
166
167 if (old_window && lastfocus == old_window) {
168 // The window was the last-focus target, so we need to replace it.
169 BlackboxWindow *win = (BlackboxWindow*) 0;
170 if (! stackingList.empty())
171 win = stackingList.front();
172 setLastFocusedWindow(win);
173 }
174 }
175 }
176
177
178 void Workspace::removeAll(void) {
179 while (! windowList.empty())
180 windowList.front()->iconify();
181 }
182
183 void Workspace::showAll(void) {
184 BlackboxWindowList::iterator it = stackingList.begin();
185 const BlackboxWindowList::iterator end = stackingList.end();
186 for (; it != end; ++it) {
187 BlackboxWindow *bw = *it;
188 // sticky windows arent unmapped on a workspace change so we don't have ot
189 // map them, but sometimes on a restart, another app can unmap our sticky
190 // windows, so we map on startup always
191 if (! bw->isStuck() || screen->getBlackbox()->isStartup())
192 bw->show();
193 }
194 }
195
196
197 void Workspace::hideAll(void) {
198 // withdraw in reverse order to minimize the number of Expose events
199
200 BlackboxWindowList lst(stackingList.rbegin(), stackingList.rend());
201
202 BlackboxWindowList::iterator it = lst.begin();
203 const BlackboxWindowList::iterator end = lst.end();
204 for (; it != end; ++it) {
205 BlackboxWindow *bw = *it;
206 // don't hide sticky windows, or they'll end up flickering on a workspace
207 // change
208 if (! bw->isStuck())
209 bw->withdraw();
210 }
211 }
212
213
214
215 /*
216 * returns the number of transients for win, plus the number of transients
217 * associated with each transient of win
218 */
219 static unsigned int countTransients(const BlackboxWindow * const win) {
220 BlackboxWindowList transients = win->getTransients();
221 if (transients.empty()) return 0;
222
223 unsigned int ret = transients.size();
224 BlackboxWindowList::const_iterator it = transients.begin(),
225 end = transients.end();
226 for (; it != end; ++it)
227 ret += countTransients(*it);
228
229 return ret;
230 }
231
232
233 /*
234 * puts the transients of win into the stack. windows are stacked above
235 * the window before it in the stackvector being iterated, meaning
236 * stack[0] is on bottom, stack[1] is above stack[0], stack[2] is above
237 * stack[1], etc...
238 */
239 void Workspace::raiseTransients(const BlackboxWindow * const win,
240 StackVector::iterator &stack) {
241 if (win->getTransients().empty()) return; // nothing to do
242
243 // put win's transients in the stack
244 BlackboxWindowList::const_iterator it, end = win->getTransients().end();
245 for (it = win->getTransients().begin(); it != end; ++it) {
246 BlackboxWindow *w = *it;
247 *stack++ = w->getFrameWindow();
248
249 if (! w->isIconic()) {
250 Workspace *wkspc = screen->getWorkspace(w->getWorkspaceNumber());
251 wkspc->stackingList.remove(w);
252 wkspc->stackingList.push_front(w);
253 }
254 }
255
256 // put transients of win's transients in the stack
257 for (it = win->getTransients().begin(); it != end; ++it)
258 raiseTransients(*it, stack);
259 }
260
261
262 void Workspace::lowerTransients(const BlackboxWindow * const win,
263 StackVector::iterator &stack) {
264 if (win->getTransients().empty()) return; // nothing to do
265
266 // put transients of win's transients in the stack
267 BlackboxWindowList::const_reverse_iterator it,
268 end = win->getTransients().rend();
269 for (it = win->getTransients().rbegin(); it != end; ++it)
270 lowerTransients(*it, stack);
271
272 // put win's transients in the stack
273 for (it = win->getTransients().rbegin(); it != end; ++it) {
274 BlackboxWindow *w = *it;
275 *stack++ = w->getFrameWindow();
276
277 if (! w->isIconic()) {
278 Workspace *wkspc = screen->getWorkspace(w->getWorkspaceNumber());
279 wkspc->stackingList.remove(w);
280 wkspc->stackingList.push_back(w);
281 }
282 }
283 }
284
285
286 void Workspace::raiseWindow(BlackboxWindow *w) {
287 BlackboxWindow *win = w;
288
289 if (win->isDesktop()) return;
290
291 // walk up the transient_for's to the window that is not a transient
292 while (win->isTransient() && win->getTransientFor())
293 win = win->getTransientFor();
294
295 // get the total window count (win and all transients)
296 unsigned int i = 1 + countTransients(win);
297
298 // stack the window with all transients above
299 StackVector stack_vector(i);
300 StackVector::iterator stack = stack_vector.begin();
301
302 *(stack++) = win->getFrameWindow();
303 if (! (win->isIconic() || win->isDesktop())) {
304 Workspace *wkspc = screen->getWorkspace(win->getWorkspaceNumber());
305 wkspc->stackingList.remove(win);
306 wkspc->stackingList.push_front(win);
307 }
308
309 raiseTransients(win, stack);
310
311 screen->raiseWindows(&stack_vector[0], stack_vector.size());
312 }
313
314
315 void Workspace::lowerWindow(BlackboxWindow *w) {
316 BlackboxWindow *win = w;
317
318 // walk up the transient_for's to the window that is not a transient
319 while (win->isTransient() && win->getTransientFor())
320 win = win->getTransientFor();
321
322 // get the total window count (win and all transients)
323 unsigned int i = 1 + countTransients(win);
324
325 // stack the window with all transients above
326 StackVector stack_vector(i);
327 StackVector::iterator stack = stack_vector.begin();
328
329 lowerTransients(win, stack);
330
331 *(stack++) = win->getFrameWindow();
332 if (! (win->isIconic() || win->isDesktop())) {
333 Workspace *wkspc = screen->getWorkspace(win->getWorkspaceNumber());
334 wkspc->stackingList.remove(win);
335 wkspc->stackingList.push_back(win);
336 }
337
338 screen->lowerWindows(&stack_vector[0], stack_vector.size());
339 }
340
341
342 void Workspace::reconfigure(void) {
343 std::for_each(windowList.begin(), windowList.end(),
344 std::mem_fun(&BlackboxWindow::reconfigure));
345 }
346
347
348 BlackboxWindow *Workspace::getWindow(unsigned int index) {
349 if (index < windowList.size()) {
350 BlackboxWindowList::iterator it = windowList.begin();
351 while (index-- > 0) // increment to index
352 ++it;
353 return *it;
354 }
355
356 return 0;
357 }
358
359
360 BlackboxWindow*
361 Workspace::getNextWindowInList(BlackboxWindow *w) {
362 BlackboxWindowList::iterator it = std::find(windowList.begin(),
363 windowList.end(),
364 w);
365 assert(it != windowList.end()); // window must be in list
366 ++it; // next window
367 if (it == windowList.end())
368 return windowList.front(); // if we walked off the end, wrap around
369
370 return *it;
371 }
372
373
374 BlackboxWindow* Workspace::getPrevWindowInList(BlackboxWindow *w) {
375 BlackboxWindowList::iterator it = std::find(windowList.begin(),
376 windowList.end(),
377 w);
378 assert(it != windowList.end()); // window must be in list
379 if (it == windowList.begin())
380 return windowList.back(); // if we walked of the front, wrap around
381
382 return *(--it);
383 }
384
385
386 BlackboxWindow* Workspace::getTopWindowOnStack(void) const {
387 assert(! stackingList.empty());
388 return stackingList.front();
389 }
390
391
392 unsigned int Workspace::getCount(void) const {
393 return windowList.size();
394 }
395
396
397 void Workspace::appendStackOrder(BlackboxWindowList &stack_order) const {
398 BlackboxWindowList::const_reverse_iterator it = stackingList.rbegin();
399 const BlackboxWindowList::const_reverse_iterator end = stackingList.rend();
400 for (; it != end; ++it)
401 // don't add desktop wnidows, or sticky windows more than once
402 if (! ( (*it)->isDesktop() ||
403 ((*it)->isStuck() && id != screen->getCurrentWorkspaceID())))
404 stack_order.push_back(*it);
405 }
406
407
408 bool Workspace::isCurrent(void) const {
409 return (id == screen->getCurrentWorkspaceID());
410 }
411
412
413 bool Workspace::isLastWindow(const BlackboxWindow* const w) const {
414 return (w == windowList.back());
415 }
416
417
418 void Workspace::setCurrent(void) {
419 screen->changeWorkspaceID(id);
420 }
421
422
423 void Workspace::readName(void) {
424 XAtom::StringVect namesList;
425 unsigned long numnames = id + 1;
426
427 // attempt to get from the _NET_WM_DESKTOP_NAMES property
428 if (xatom->getValue(screen->getRootWindow(), XAtom::net_desktop_names,
429 XAtom::utf8, numnames, namesList) &&
430 namesList.size() > id) {
431 name = namesList[id];
432
433 } else {
434 /*
435 Use a default name. This doesn't actually change the class. That will
436 happen after the setName changes the root property, and that change
437 makes its way back to this function.
438 */
439 string tmp = "Workspace %d";
440 assert(tmp.length() < 32);
441 char default_name[32];
442 sprintf(default_name, tmp.c_str(), id + 1);
443
444 setName(default_name); // save this into the _NET_WM_DESKTOP_NAMES property
445 }
446 }
447
448
449 void Workspace::setName(const string& new_name) {
450 // set the _NET_WM_DESKTOP_NAMES property with the new name
451 XAtom::StringVect namesList;
452 unsigned long numnames = (unsigned) -1;
453 if (xatom->getValue(screen->getRootWindow(), XAtom::net_desktop_names,
454 XAtom::utf8, numnames, namesList) &&
455 namesList.size() > id)
456 namesList[id] = new_name;
457 else
458 namesList.push_back(new_name);
459
460 xatom->setValue(screen->getRootWindow(), XAtom::net_desktop_names,
461 XAtom::utf8, namesList);
462 }
463
464
465 /*
466 * Calculate free space available for window placement.
467 */
468 Workspace::rectList Workspace::calcSpace(const Rect &win,
469 const rectList &spaces) const {
470 Rect isect, extra;
471 rectList result;
472 rectList::const_iterator siter, end = spaces.end();
473 for (siter = spaces.begin(); siter != end; ++siter) {
474 const Rect &curr = *siter;
475
476 if(! win.intersects(curr)) {
477 result.push_back(curr);
478 continue;
479 }
480
481 /* Use an intersection of win and curr to determine the space around
482 * curr that we can use.
483 *
484 * NOTE: the spaces calculated can overlap.
485 */
486 isect = curr & win;
487
488 // left
489 extra.setCoords(curr.left(), curr.top(),
490 isect.left() - screen->getSnapOffset(), curr.bottom());
491 if (extra.valid()) result.push_back(extra);
492
493 // top
494 extra.setCoords(curr.left(), curr.top(),
495 curr.right(), isect.top() - screen->getSnapOffset());
496 if (extra.valid()) result.push_back(extra);
497
498 // right
499 extra.setCoords(isect.right() + screen->getSnapOffset(), curr.top(),
500 curr.right(), curr.bottom());
501 if (extra.valid()) result.push_back(extra);
502
503 // bottom
504 extra.setCoords(curr.left(), isect.bottom() + screen->getSnapOffset(),
505 curr.right(), curr.bottom());
506 if (extra.valid()) result.push_back(extra);
507 }
508 return result;
509 }
510
511
512 static bool rowRLBT(const Rect &first, const Rect &second) {
513 if (first.bottom() == second.bottom())
514 return first.right() > second.right();
515 return first.bottom() > second.bottom();
516 }
517
518 static bool rowRLTB(const Rect &first, const Rect &second) {
519 if (first.y() == second.y())
520 return first.right() > second.right();
521 return first.y() < second.y();
522 }
523
524 static bool rowLRBT(const Rect &first, const Rect &second) {
525 if (first.bottom() == second.bottom())
526 return first.x() < second.x();
527 return first.bottom() > second.bottom();
528 }
529
530 static bool rowLRTB(const Rect &first, const Rect &second) {
531 if (first.y() == second.y())
532 return first.x() < second.x();
533 return first.y() < second.y();
534 }
535
536 static bool colLRTB(const Rect &first, const Rect &second) {
537 if (first.x() == second.x())
538 return first.y() < second.y();
539 return first.x() < second.x();
540 }
541
542 static bool colLRBT(const Rect &first, const Rect &second) {
543 if (first.x() == second.x())
544 return first.bottom() > second.bottom();
545 return first.x() < second.x();
546 }
547
548 static bool colRLTB(const Rect &first, const Rect &second) {
549 if (first.right() == second.right())
550 return first.y() < second.y();
551 return first.right() > second.right();
552 }
553
554 static bool colRLBT(const Rect &first, const Rect &second) {
555 if (first.right() == second.right())
556 return first.bottom() > second.bottom();
557 return first.right() > second.right();
558 }
559
560
561 bool Workspace::smartPlacement(Rect& win) {
562 rectList spaces;
563
564 //initially the entire screen is free
565 #ifdef XINERAMA
566 if (screen->isXineramaActive() &&
567 screen->getBlackbox()->doXineramaPlacement()) {
568 RectList availableAreas = screen->allAvailableAreas();
569 RectList::iterator it, end = availableAreas.end();
570
571 for (it = availableAreas.begin(); it != end; ++it) {
572 Rect r = *it;
573 r.setRect(r.x() + screen->getSnapOffset(),
574 r.y() + screen->getSnapOffset(),
575 r.width() - screen->getSnapOffset(),
576 r.height() - screen->getSnapOffset());
577 spaces.push_back(*it);
578 }
579 } else
580 #endif // XINERAMA
581 {
582 Rect r = screen->availableArea();
583 r.setRect(r.x() + screen->getSnapOffset(),
584 r.y() + screen->getSnapOffset(),
585 r.width() - screen->getSnapOffset(),
586 r.height() - screen->getSnapOffset());
587 spaces.push_back(r);
588 }
589
590 //Find Free Spaces
591 BlackboxWindowList::const_iterator wit = windowList.begin(),
592 end = windowList.end();
593 Rect tmp;
594 for (; wit != end; ++wit) {
595 const BlackboxWindow* const curr = *wit;
596
597 // watch for shaded windows and full-maxed windows
598 if (curr->isShaded()) {
599 if (screen->getPlaceIgnoreShaded()) continue;
600 } else if (curr->isMaximizedFull()) {
601 if (screen->getPlaceIgnoreMaximized()) continue;
602 }
603
604 tmp.setRect(curr->frameRect().x(), curr->frameRect().y(),
605 curr->frameRect().width() + screen->getBorderWidth(),
606 curr->frameRect().height() + screen->getBorderWidth());
607
608 spaces = calcSpace(tmp, spaces);
609 }
610
611 if (screen->getPlacementPolicy() == BScreen::RowSmartPlacement) {
612 if(screen->getRowPlacementDirection() == BScreen::LeftRight) {
613 if(screen->getColPlacementDirection() == BScreen::TopBottom)
614 std::sort(spaces.begin(), spaces.end(), rowLRTB);
615 else
616 std::sort(spaces.begin(), spaces.end(), rowLRBT);
617 } else {
618 if(screen->getColPlacementDirection() == BScreen::TopBottom)
619 std::sort(spaces.begin(), spaces.end(), rowRLTB);
620 else
621 std::sort(spaces.begin(), spaces.end(), rowRLBT);
622 }
623 } else {
624 if(screen->getColPlacementDirection() == BScreen::TopBottom) {
625 if(screen->getRowPlacementDirection() == BScreen::LeftRight)
626 std::sort(spaces.begin(), spaces.end(), colLRTB);
627 else
628 std::sort(spaces.begin(), spaces.end(), colRLTB);
629 } else {
630 if(screen->getRowPlacementDirection() == BScreen::LeftRight)
631 std::sort(spaces.begin(), spaces.end(), colLRBT);
632 else
633 std::sort(spaces.begin(), spaces.end(), colRLBT);
634 }
635 }
636
637 rectList::const_iterator sit = spaces.begin(), spaces_end = spaces.end();
638 for(; sit != spaces_end; ++sit) {
639 if (sit->width() >= win.width() && sit->height() >= win.height())
640 break;
641 }
642
643 if (sit == spaces_end)
644 return False;
645
646 //set new position based on the empty space found
647 const Rect& where = *sit;
648 win.setX(where.x());
649 win.setY(where.y());
650
651 // adjust the location() based on left/right and top/bottom placement
652 if (screen->getPlacementPolicy() == BScreen::RowSmartPlacement) {
653 if (screen->getRowPlacementDirection() == BScreen::RightLeft)
654 win.setX(where.right() - win.width());
655 if (screen->getColPlacementDirection() == BScreen::BottomTop)
656 win.setY(where.bottom() - win.height());
657 } else {
658 if (screen->getColPlacementDirection() == BScreen::BottomTop)
659 win.setY(win.y() + where.height() - win.height());
660 if (screen->getRowPlacementDirection() == BScreen::RightLeft)
661 win.setX(win.x() + where.width() - win.width());
662 }
663 return True;
664 }
665
666
667 bool Workspace::underMousePlacement(Rect &win) {
668 int x, y, rx, ry;
669 Window c, r;
670 unsigned int m;
671 XQueryPointer(screen->getBlackbox()->getXDisplay(), screen->getRootWindow(),
672 &r, &c, &rx, &ry, &x, &y, &m);
673
674 Rect area;
675 #ifdef XINERAMA
676 if (screen->isXineramaActive() &&
677 screen->getBlackbox()->doXineramaPlacement()) {
678 RectList availableAreas = screen->allAvailableAreas();
679 RectList::iterator it, end = availableAreas.end();
680
681 for (it = availableAreas.begin(); it != end; ++it)
682 if (it->contains(rx, ry)) break;
683 assert(it != end); // the mouse isn't inside an area?
684 area = *it;
685 } else
686 #endif // XINERAMA
687 area = screen->availableArea();
688
689 x = rx - win.width() / 2;
690 y = ry - win.height() / 2;
691
692 if (x < area.x())
693 x = area.x();
694 if (y < area.y())
695 y = area.y();
696 if (x + win.width() > area.x() + area.width())
697 x = area.x() + area.width() - win.width();
698 if (y + win.height() > area.y() + area.height())
699 y = area.y() + area.height() - win.height();
700
701 win.setX(x);
702 win.setY(y);
703
704 return True;
705 }
706
707
708 bool Workspace::cascadePlacement(Rect &win, const int offset) {
709 Rect area;
710
711 #ifdef XINERAMA
712 if (screen->isXineramaActive() &&
713 screen->getBlackbox()->doXineramaPlacement()) {
714 area = screen->allAvailableAreas()[cascade_region];
715 } else
716 #endif // XINERAMA
717 area = screen->availableArea();
718
719 if ((static_cast<signed>(cascade_x + win.width()) > area.right() + 1) ||
720 (static_cast<signed>(cascade_y + win.height()) > area.bottom() + 1)) {
721 cascade_x = cascade_y = 0;
722 #ifdef XINERAMA
723 if (screen->isXineramaActive() &&
724 screen->getBlackbox()->doXineramaPlacement()) {
725 // go to the next xinerama region, and use its area
726 if (++cascade_region >= screen->allAvailableAreas().size())
727 cascade_region = 0;
728 area = screen->allAvailableAreas()[cascade_region];
729 }
730 #endif // XINERAMA
731 }
732
733 if (cascade_x == 0) {
734 cascade_x = area.x() + offset;
735 cascade_y = area.y() + offset;
736 }
737
738 win.setPos(cascade_x, cascade_y);
739
740 cascade_x += offset;
741 cascade_y += offset;
742
743 return True;
744 }
745
746
747 void Workspace::placeWindow(BlackboxWindow *win) {
748 Rect new_win(0, 0, win->frameRect().width(), win->frameRect().height());
749 bool placed = False;
750
751 switch (screen->getPlacementPolicy()) {
752 case BScreen::RowSmartPlacement:
753 case BScreen::ColSmartPlacement:
754 placed = smartPlacement(new_win);
755 break;
756 case BScreen::UnderMousePlacement:
757 case BScreen::ClickMousePlacement:
758 placed = underMousePlacement(new_win);
759 default:
760 break; // handled below
761 } // switch
762
763 if (placed == False)
764 cascadePlacement(new_win, (win->getTitleHeight() +
765 screen->getBorderWidth() * 2));
766
767 if (new_win.right() > screen->availableArea().right())
768 new_win.setX(screen->availableArea().left());
769 if (new_win.bottom() > screen->availableArea().bottom())
770 new_win.setY(screen->availableArea().top());
771
772 win->configure(new_win.x(), new_win.y(), new_win.width(), new_win.height());
773 }
This page took 0.074156 seconds and 4 git commands to generate.