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