aboutsummaryrefslogtreecommitdiff
path: root/src/MinOverlapPlacement.cc
diff options
context:
space:
mode:
authormarkt <markt>2007-10-13 21:51:37 (GMT)
committermarkt <markt>2007-10-13 21:51:37 (GMT)
commita59428d67a95a9df16554962f0a6257d6378328a (patch)
treef856ed9300c34f7a17d499f22d895610cfbc08e5 /src/MinOverlapPlacement.cc
parent41b5c6dadb1f474675660cef18b812d4c2338ed2 (diff)
downloadfluxbox-a59428d67a95a9df16554962f0a6257d6378328a.zip
fluxbox-a59428d67a95a9df16554962f0a6257d6378328a.tar.bz2
merged changes from pre-devel
Diffstat (limited to 'src/MinOverlapPlacement.cc')
-rw-r--r--src/MinOverlapPlacement.cc186
1 files changed, 186 insertions, 0 deletions
diff --git a/src/MinOverlapPlacement.cc b/src/MinOverlapPlacement.cc
new file mode 100644
index 0000000..e7e80cb
--- /dev/null
+++ b/src/MinOverlapPlacement.cc
@@ -0,0 +1,186 @@
1// MinOverlapPlacement.cc
2// Copyright (c) 2007 Fluxbox Team (fluxgen at fluxbox dot org)
3//
4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the "Software"),
6// to deal in the Software without restriction, including without limitation
7// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8// and/or sell copies of the Software, and to permit persons to whom the
9// Software is furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR (*it)
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR (*it)WISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR (*it)
20// DEALINGS IN THE SOFTWARE.
21
22// $Id$
23
24#include "MinOverlapPlacement.hh"
25
26#include "Window.hh"
27#include "Screen.hh"
28
29ScreenPlacement::PlacementPolicy MinOverlapPlacement::s_policy = ScreenPlacement::ROWMINOVERLAPPLACEMENT;
30ScreenPlacement::RowDirection MinOverlapPlacement::s_row_dir = ScreenPlacement::LEFTRIGHT;
31ScreenPlacement::ColumnDirection MinOverlapPlacement::s_col_dir = ScreenPlacement::TOPBOTTOM;
32
33MinOverlapPlacement::MinOverlapPlacement(ScreenPlacement::PlacementPolicy policy) {
34 s_policy = policy;
35}
36
37bool MinOverlapPlacement::placeWindow(
38 const std::list<FluxboxWindow *> &windowlist,
39 const FluxboxWindow &win, int &place_x, int &place_y) {
40
41 // view (screen + head) constraints
42 int head = (signed) win.screen().getCurrHead();
43 int head_left = (signed) win.screen().maxLeft(head);
44 int head_right = (signed) win.screen().maxRight(head);
45 int head_top = (signed) win.screen().maxTop(head);
46 int head_bot = (signed) win.screen().maxBottom(head);
47
48 const ScreenPlacement &screen_placement =
49 dynamic_cast<const ScreenPlacement &>(win.screen().placementStrategy());
50 s_row_dir = screen_placement.rowDirection();
51 s_col_dir = screen_placement.colDirection();
52
53 int win_w = win.width() + win.fbWindow().borderWidth()*2 + win.widthOffset();
54 int win_h = win.height() + win.fbWindow().borderWidth()*2 + win.heightOffset();
55
56 // we keep a set of open spaces on the desktop, sorted by size/location
57 std::set<Region> region_set;
58
59 // initialize the set of regions to contain the entire head
60 region_set.insert(Region(Region::TOPLEFT, head_left, head_top));
61 region_set.insert(Region(Region::TOPRIGHT, head_right - win_w, head_top));
62 region_set.insert(Region(Region::BOTTOMLEFT, head_left, head_bot - win_h));
63 region_set.insert(Region(Region::BOTTOMRIGHT, head_right - win_w,
64 head_bot - win_h));
65
66 // go through the list of windows, creating other reasonable placements
67 // at the end, we'll find the one with minimum overlap
68 // the size of this set is at most 2(n+2)(n+1) (n = number of windows)
69 // finding overlaps is therefore O(n^3), but it can probably be improved
70 std::list<FluxboxWindow *>::const_reverse_iterator it = windowlist.rbegin(),
71 it_end = windowlist.rend();
72 for (; it != it_end; ++it) {
73
74 // get the dimensions of the window
75 int left = (*it)->x() - (*it)->xOffset();
76 int top = (*it)->y() - (*it)->yOffset();
77 int right = left + (*it)->width() +
78 2*(*it)->frame().window().borderWidth() +
79 (*it)->widthOffset();
80 int bottom = top + (*it)->height() +
81 2*(*it)->frame().window().borderWidth() +
82 (*it)->heightOffset();
83
84 // go through the list of regions
85 // if this window overlaps that region and the new window still fits,
86 // it will create new regions to test
87 std::set<Region>::iterator reg_it = region_set.begin();
88 for (; reg_it != region_set.end(); ++reg_it) {
89
90 switch (reg_it->corner) {
91 case Region::TOPLEFT:
92 if (right > reg_it->x && bottom > reg_it->y) {
93 if (bottom + win_h <= head_bot)
94 region_set.insert(Region(Region::TOPLEFT,
95 reg_it->x, bottom));
96 if (right + win_w <= head_right)
97 region_set.insert(Region(Region::TOPLEFT,
98 right, reg_it->y));
99 }
100 break;
101 case Region::TOPRIGHT:
102 if (left < reg_it->x + win_w && bottom > reg_it->y) {
103 if (bottom + win_h <= head_bot)
104 region_set.insert(Region(Region::TOPRIGHT,
105 reg_it->x, bottom));
106 if (left - win_w >= head_left)
107 region_set.insert(Region(Region::TOPRIGHT,
108 left - win_w, reg_it->y));
109 }
110 break;
111 case Region::BOTTOMRIGHT:
112 if (left < reg_it->x + win_w && top < reg_it->y + win_h) {
113 if (top - win_h >= head_top)
114 region_set.insert(Region(Region::BOTTOMRIGHT,
115 reg_it->x, top - win_h));
116 if (left - win_w >= head_left)
117 region_set.insert(Region(Region::BOTTOMRIGHT,
118 left - win_w, reg_it->y));
119 }
120 break;
121 case Region::BOTTOMLEFT:
122 if (right > reg_it->x && top < reg_it->y + win_h) {
123 if (top - win_h >= head_top)
124 region_set.insert(Region(Region::BOTTOMLEFT,
125 reg_it->x, top - win_h));
126 if (right + win_w <= head_right)
127 region_set.insert(Region(Region::BOTTOMLEFT,
128 right, reg_it->y));
129 }
130 break;
131 }
132
133 }
134 }
135
136 // choose the region with minimum overlap
137 int min_so_far = win_w * win_h * windowlist.size() + 1;
138 std::set<Region>::iterator min_reg = region_set.end();
139
140 std::set<Region>::iterator reg_it = region_set.begin();
141 for (; reg_it != region_set.end(); ++reg_it) {
142
143 int overlap = 0;
144 it = windowlist.rbegin();
145 for (; it != windowlist.rend(); ++it) {
146
147 // get the dimensions of the window
148 int left = (*it)->x() - (*it)->xOffset();
149 int top = (*it)->y() - (*it)->yOffset();
150 int right = left + (*it)->width() +
151 2*(*it)->frame().window().borderWidth() +
152 (*it)->widthOffset();
153 int bottom = top + (*it)->height() +
154 2*(*it)->frame().window().borderWidth() +
155 (*it)->heightOffset();
156
157 // get the coordinates of the overlap region
158 int min_right = (right > reg_it->x + win_w) ?
159 reg_it->x + win_w : right;
160 int min_bottom = (bottom > reg_it->y + win_h) ?
161 reg_it->y + win_h : bottom;
162 int max_left = (left > reg_it->x) ? left : reg_it->x;
163 int max_top = (top > reg_it->y) ? top : reg_it->y;
164
165 // now compute the overlap and add to running total
166 if (min_right > max_left && min_bottom > max_top)
167 overlap += (min_right - max_left) * (min_bottom - max_top);
168
169 }
170
171 // if this placement is better, use it
172 if (overlap < min_so_far) {
173 min_reg = reg_it;
174 min_so_far = overlap;
175 if (overlap == 0) // can't do better than this
176 break;
177 }
178
179 }
180
181 // place window
182 place_x = min_reg->x + win.xOffset();
183 place_y = min_reg->y + win.yOffset();
184
185 return true;
186}