aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/MinOverlapPlacement.cc176
-rw-r--r--src/MinOverlapPlacement.hh44
-rw-r--r--src/ScreenPlacement.cc2
-rw-r--r--src/ScreenPlacement.hh1
4 files changed, 108 insertions, 115 deletions
diff --git a/src/MinOverlapPlacement.cc b/src/MinOverlapPlacement.cc
index 559ff11..78cadb4 100644
--- a/src/MinOverlapPlacement.cc
+++ b/src/MinOverlapPlacement.cc
@@ -25,17 +25,75 @@
25#include "Window.hh" 25#include "Window.hh"
26#include "Screen.hh" 26#include "Screen.hh"
27 27
28ScreenPlacement::PlacementPolicy MinOverlapPlacement::s_policy = ScreenPlacement::ROWMINOVERLAPPLACEMENT; 28namespace {
29ScreenPlacement::RowDirection MinOverlapPlacement::s_row_dir = ScreenPlacement::LEFTRIGHT;
30ScreenPlacement::ColumnDirection MinOverlapPlacement::s_col_dir = ScreenPlacement::TOPBOTTOM;
31 29
32MinOverlapPlacement::MinOverlapPlacement(ScreenPlacement::PlacementPolicy policy) { 30inline void getWindowDimensions(const FluxboxWindow& win, int& left, int& top, int& right, int& bottom) {
33 s_policy = policy; 31
32 const int bw = 2 * win.frame().window().borderWidth();
33 left = win.x() - win.xOffset();
34 top = win.y() - win.yOffset();
35 right = left + win.width() + bw + win.widthOffset();
36 bottom = top + win.height() + bw + win.heightOffset();
34} 37}
35 38
39class Area {
40public:
41
42 enum Corner {
43 TOPLEFT,
44 TOPRIGHT,
45 BOTTOMLEFT,
46 BOTTOMRIGHT
47 } corner; // indicates the corner of the window that will be placed
48
49 Area(Corner _corner, int _x, int _y):
50 corner(_corner), x(_x), y(_y) { };
51
52 // do all STL set implementations use this for sorting?
53 bool operator <(const Area &o) const {
54 switch (s_policy) {
55 case ScreenPlacement::ROWMINOVERLAPPLACEMENT:
56 // if we're making rows, y-value is most important
57 if (y != o.y)
58 return ((y < o.y) ^ (s_col_dir == ScreenPlacement::BOTTOMTOP));
59 if (x != o.x)
60 return ((x < o.x) ^ (s_row_dir == ScreenPlacement::RIGHTLEFT));
61 return (corner < o.corner);
62 case ScreenPlacement::COLMINOVERLAPPLACEMENT:
63 // if we're making columns, x-value is most important
64 if (x != o.x)
65 return ((x < o.x) ^ (s_row_dir == ScreenPlacement::RIGHTLEFT));
66 if (y != o.y)
67 return ((y < o.y) ^ (s_col_dir == ScreenPlacement::BOTTOMTOP));
68 return (corner < o.corner);
69 default:
70 return false;
71 }
72 }
73
74 // position where the top left corner of the window will be placed
75 int x, y;
76
77 static ScreenPlacement::RowDirection s_row_dir;
78 static ScreenPlacement::ColumnDirection s_col_dir;
79 static ScreenPlacement::PlacementPolicy s_policy;
80};
81
82ScreenPlacement::RowDirection Area::s_row_dir = ScreenPlacement::LEFTRIGHT;
83ScreenPlacement::ColumnDirection Area::s_col_dir = ScreenPlacement::TOPBOTTOM;
84ScreenPlacement::PlacementPolicy Area::s_policy = ScreenPlacement::ROWMINOVERLAPPLACEMENT;
85
86} // end of anonymous namespace
87
88
36bool MinOverlapPlacement::placeWindow(const FluxboxWindow &win, int head, 89bool MinOverlapPlacement::placeWindow(const FluxboxWindow &win, int head,
37 int &place_x, int &place_y) { 90 int &place_x, int &place_y) {
38 91
92 int left;
93 int top;
94 int right;
95 int bottom;
96
39 std::list<FluxboxWindow *> windowlist; 97 std::list<FluxboxWindow *> windowlist;
40 const std::list<Focusable *> focusables = 98 const std::list<Focusable *> focusables =
41 win.screen().focusControl().focusedOrderWinList().clientList(); 99 win.screen().focusControl().focusedOrderWinList().clientList();
@@ -56,24 +114,26 @@ bool MinOverlapPlacement::placeWindow(const FluxboxWindow &win, int head,
56 int head_top = (signed) win.screen().maxTop(head); 114 int head_top = (signed) win.screen().maxTop(head);
57 int head_bot = (signed) win.screen().maxBottom(head); 115 int head_bot = (signed) win.screen().maxBottom(head);
58 116
59 const ScreenPlacement &screen_placement = win.screen().placementStrategy();
60 s_row_dir = screen_placement.rowDirection();
61 s_col_dir = screen_placement.colDirection();
62
63 int win_w = win.normalWidth() + win.fbWindow().borderWidth()*2 + 117 int win_w = win.normalWidth() + win.fbWindow().borderWidth()*2 +
64 win.widthOffset(); 118 win.widthOffset();
65 int win_h = win.normalHeight() + win.fbWindow().borderWidth()*2 + 119 int win_h = win.normalHeight() + win.fbWindow().borderWidth()*2 +
66 win.heightOffset(); 120 win.heightOffset();
67 121
68 // we keep a set of open spaces on the desktop, sorted by size/location 122 // we keep a set of open spaces on the desktop, sorted by size/location
69 std::set<Region> region_set; 123 std::set<Area> areas;
124
125 // setup stuff in order to make Area::operator< work
126 const ScreenPlacement& p = win.screen().placementStrategy();
127 Area::s_policy = p.placementPolicy();
128 Area::s_row_dir = p.rowDirection();
129 Area::s_col_dir = p.colDirection();
130
70 131
71 // initialize the set of regions to contain the entire head 132 // initialize the set of areas to contain the entire head
72 region_set.insert(Region(Region::TOPLEFT, head_left, head_top)); 133 areas.insert(Area(Area::TOPLEFT, head_left, head_top));
73 region_set.insert(Region(Region::TOPRIGHT, head_right - win_w, head_top)); 134 areas.insert(Area(Area::TOPRIGHT, head_right - win_w, head_top));
74 region_set.insert(Region(Region::BOTTOMLEFT, head_left, head_bot - win_h)); 135 areas.insert(Area(Area::BOTTOMLEFT, head_left, head_bot - win_h));
75 region_set.insert(Region(Region::BOTTOMRIGHT, head_right - win_w, 136 areas.insert(Area(Area::BOTTOMRIGHT, head_right - win_w, head_bot - win_h));
76 head_bot - win_h));
77 137
78 // go through the list of windows, creating other reasonable placements 138 // go through the list of windows, creating other reasonable placements
79 // at the end, we'll find the one with minimum overlap 139 // at the end, we'll find the one with minimum overlap
@@ -85,61 +145,45 @@ bool MinOverlapPlacement::placeWindow(const FluxboxWindow &win, int head,
85 for (; it != it_end; ++it) { 145 for (; it != it_end; ++it) {
86 if (*it == &win) continue; 146 if (*it == &win) continue;
87 147
88 // get the dimensions of the window 148 getWindowDimensions(*(*it), left, top, right, bottom);
89 int left = (*it)->x() - (*it)->xOffset();
90 int top = (*it)->y() - (*it)->yOffset();
91 int right = left + (*it)->width() +
92 2*(*it)->frame().window().borderWidth() +
93 (*it)->widthOffset();
94 int bottom = top + (*it)->height() +
95 2*(*it)->frame().window().borderWidth() +
96 (*it)->heightOffset();
97 149
98 // go through the list of regions 150 // go through the list of regions
99 // if this window overlaps that region and the new window still fits, 151 // if this window overlaps that region and the new window still fits,
100 // it will create new regions to test 152 // it will create new regions to test
101 std::set<Region>::iterator reg_it = region_set.begin(); 153 std::set<Area>::iterator ar_it = areas.begin();
102 for (; reg_it != region_set.end(); ++reg_it) { 154 for (; ar_it != areas.end(); ++ar_it) {
103 155
104 switch (reg_it->corner) { 156 switch (ar_it->corner) {
105 case Region::TOPLEFT: 157 case Area::TOPLEFT:
106 if (right > reg_it->x && bottom > reg_it->y) { 158 if (right > ar_it->x && bottom > ar_it->y) {
107 if (bottom + win_h <= head_bot) 159 if (bottom + win_h <= head_bot)
108 region_set.insert(Region(Region::TOPLEFT, 160 areas.insert(Area(Area::TOPLEFT, ar_it->x, bottom));
109 reg_it->x, bottom));
110 if (right + win_w <= head_right) 161 if (right + win_w <= head_right)
111 region_set.insert(Region(Region::TOPLEFT, 162 areas.insert(Area(Area::TOPLEFT, right, ar_it->y));
112 right, reg_it->y));
113 } 163 }
114 break; 164 break;
115 case Region::TOPRIGHT: 165 case Area::TOPRIGHT:
116 if (left < reg_it->x + win_w && bottom > reg_it->y) { 166 if (left < ar_it->x + win_w && bottom > ar_it->y) {
117 if (bottom + win_h <= head_bot) 167 if (bottom + win_h <= head_bot)
118 region_set.insert(Region(Region::TOPRIGHT, 168 areas.insert(Area(Area::TOPRIGHT, ar_it->x, bottom));
119 reg_it->x, bottom));
120 if (left - win_w >= head_left) 169 if (left - win_w >= head_left)
121 region_set.insert(Region(Region::TOPRIGHT, 170 areas.insert(Area(Area::TOPRIGHT, left - win_w, ar_it->y));
122 left - win_w, reg_it->y));
123 } 171 }
124 break; 172 break;
125 case Region::BOTTOMRIGHT: 173 case Area::BOTTOMRIGHT:
126 if (left < reg_it->x + win_w && top < reg_it->y + win_h) { 174 if (left < ar_it->x + win_w && top < ar_it->y + win_h) {
127 if (top - win_h >= head_top) 175 if (top - win_h >= head_top)
128 region_set.insert(Region(Region::BOTTOMRIGHT, 176 areas.insert(Area(Area::BOTTOMRIGHT, ar_it->x, top - win_h));
129 reg_it->x, top - win_h));
130 if (left - win_w >= head_left) 177 if (left - win_w >= head_left)
131 region_set.insert(Region(Region::BOTTOMRIGHT, 178 areas.insert(Area(Area::BOTTOMRIGHT, left - win_w, ar_it->y));
132 left - win_w, reg_it->y));
133 } 179 }
134 break; 180 break;
135 case Region::BOTTOMLEFT: 181 case Area::BOTTOMLEFT:
136 if (right > reg_it->x && top < reg_it->y + win_h) { 182 if (right > ar_it->x && top < ar_it->y + win_h) {
137 if (top - win_h >= head_top) 183 if (top - win_h >= head_top)
138 region_set.insert(Region(Region::BOTTOMLEFT, 184 areas.insert(Area(Area::BOTTOMLEFT, ar_it->x, top - win_h));
139 reg_it->x, top - win_h));
140 if (right + win_w <= head_right) 185 if (right + win_w <= head_right)
141 region_set.insert(Region(Region::BOTTOMLEFT, 186 areas.insert(Area(Area::BOTTOMLEFT, right, ar_it->y));
142 right, reg_it->y));
143 } 187 }
144 break; 188 break;
145 } 189 }
@@ -149,32 +193,22 @@ bool MinOverlapPlacement::placeWindow(const FluxboxWindow &win, int head,
149 193
150 // choose the region with minimum overlap 194 // choose the region with minimum overlap
151 int min_so_far = win_w * win_h * windowlist.size() + 1; 195 int min_so_far = win_w * win_h * windowlist.size() + 1;
152 std::set<Region>::iterator min_reg = region_set.end(); 196 std::set<Area>::iterator min_reg = areas.end();
153 197
154 std::set<Region>::iterator reg_it = region_set.begin(); 198 std::set<Area>::iterator ar_it = areas.begin();
155 for (; reg_it != region_set.end(); ++reg_it) { 199 for (; ar_it != areas.end(); ++ar_it) {
156 200
157 int overlap = 0; 201 int overlap = 0;
158 it = const_windowlist.rbegin(); 202 it = const_windowlist.rbegin();
159 for (; it != it_end; ++it) { 203 for (; it != it_end; ++it) {
160 204
161 // get the dimensions of the window 205 getWindowDimensions(*(*it), left, top, right, bottom);
162 int left = (*it)->x() - (*it)->xOffset();
163 int top = (*it)->y() - (*it)->yOffset();
164 int right = left + (*it)->width() +
165 2*(*it)->frame().window().borderWidth() +
166 (*it)->widthOffset();
167 int bottom = top + (*it)->height() +
168 2*(*it)->frame().window().borderWidth() +
169 (*it)->heightOffset();
170 206
171 // get the coordinates of the overlap region 207 // get the coordinates of the overlap region
172 int min_right = (right > reg_it->x + win_w) ? 208 int min_right = std::min(right, ar_it->x + win_w);
173 reg_it->x + win_w : right; 209 int min_bottom = std::min(bottom, ar_it->y + win_h);
174 int min_bottom = (bottom > reg_it->y + win_h) ? 210 int max_left = std::max(left, ar_it->x);
175 reg_it->y + win_h : bottom; 211 int max_top = std::max(top, ar_it->y);
176 int max_left = (left > reg_it->x) ? left : reg_it->x;
177 int max_top = (top > reg_it->y) ? top : reg_it->y;
178 212
179 // now compute the overlap and add to running total 213 // now compute the overlap and add to running total
180 if (min_right > max_left && min_bottom > max_top) 214 if (min_right > max_left && min_bottom > max_top)
@@ -184,7 +218,7 @@ bool MinOverlapPlacement::placeWindow(const FluxboxWindow &win, int head,
184 218
185 // if this placement is better, use it 219 // if this placement is better, use it
186 if (overlap < min_so_far) { 220 if (overlap < min_so_far) {
187 min_reg = reg_it; 221 min_reg = ar_it;
188 min_so_far = overlap; 222 min_so_far = overlap;
189 if (overlap == 0) // can't do better than this 223 if (overlap == 0) // can't do better than this
190 break; 224 break;
diff --git a/src/MinOverlapPlacement.hh b/src/MinOverlapPlacement.hh
index daf49f2..1c741ca 100644
--- a/src/MinOverlapPlacement.hh
+++ b/src/MinOverlapPlacement.hh
@@ -26,54 +26,12 @@
26 26
27class MinOverlapPlacement: public PlacementStrategy { 27class MinOverlapPlacement: public PlacementStrategy {
28public: 28public:
29 MinOverlapPlacement(ScreenPlacement::PlacementPolicy policy); 29 MinOverlapPlacement() { };
30 30
31 bool placeWindow(const FluxboxWindow &win, int head, 31 bool placeWindow(const FluxboxWindow &win, int head,
32 int &place_x, int &place_y); 32 int &place_x, int &place_y);
33 33
34private: 34private:
35 class Region {
36 public:
37
38 enum Corner {
39 TOPLEFT,
40 TOPRIGHT,
41 BOTTOMLEFT,
42 BOTTOMRIGHT
43 } corner; // indicates the corner of the window that will be placed
44
45 Region(Corner _corner, int _x, int _y):
46 corner(_corner), x(_x), y(_y) { };
47
48 // do all STL set implementations use this for sorting?
49 bool operator <(const Region &o) const {
50 switch (MinOverlapPlacement::s_policy) {
51 case ScreenPlacement::ROWMINOVERLAPPLACEMENT:
52 // if we're making rows, y-value is most important
53 if (y != o.y)
54 return ((y < o.y) ^ (s_col_dir == ScreenPlacement::BOTTOMTOP));
55 if (x != o.x)
56 return ((x < o.x) ^ (s_row_dir == ScreenPlacement::RIGHTLEFT));
57 return (corner < o.corner);
58 case ScreenPlacement::COLMINOVERLAPPLACEMENT:
59 // if we're making columns, x-value is most important
60 if (x != o.x)
61 return ((x < o.x) ^ (s_row_dir == ScreenPlacement::RIGHTLEFT));
62 if (y != o.y)
63 return ((y < o.y) ^ (s_col_dir == ScreenPlacement::BOTTOMTOP));
64 return (corner < o.corner);
65 default:
66 return false;
67 }
68 }
69
70 // position where the top left corner of the window will be placed
71 int x, y;
72 };
73
74 static ScreenPlacement::PlacementPolicy s_policy;
75 static ScreenPlacement::RowDirection s_row_dir;
76 static ScreenPlacement::ColumnDirection s_col_dir;
77}; 35};
78 36
79#endif // MINOVERLAPPLACEMENT_HH 37#endif // MINOVERLAPPLACEMENT_HH
diff --git a/src/ScreenPlacement.cc b/src/ScreenPlacement.cc
index 1da1700..73ddfa2 100644
--- a/src/ScreenPlacement.cc
+++ b/src/ScreenPlacement.cc
@@ -75,7 +75,7 @@ bool ScreenPlacement::placeWindow(const FluxboxWindow &win, int head,
75 break; 75 break;
76 case ROWMINOVERLAPPLACEMENT: 76 case ROWMINOVERLAPPLACEMENT:
77 case COLMINOVERLAPPLACEMENT: 77 case COLMINOVERLAPPLACEMENT:
78 m_strategy.reset(new MinOverlapPlacement(*m_placement_policy)); 78 m_strategy.reset(new MinOverlapPlacement());
79 break; 79 break;
80 case CASCADEPLACEMENT: 80 case CASCADEPLACEMENT:
81 m_strategy.reset(new CascadePlacement(win.screen())); 81 m_strategy.reset(new CascadePlacement(win.screen()));
diff --git a/src/ScreenPlacement.hh b/src/ScreenPlacement.hh
index 0e749d4..05db90d 100644
--- a/src/ScreenPlacement.hh
+++ b/src/ScreenPlacement.hh
@@ -71,6 +71,7 @@ public:
71 // places and show 'menu' at 'x','y' 71 // places and show 'menu' at 'x','y'
72 void placeAndShowMenu(FbTk::Menu& menu, int x, int y, bool respect_struts); 72 void placeAndShowMenu(FbTk::Menu& menu, int x, int y, bool respect_struts);
73 73
74 PlacementPolicy placementPolicy() const { return *m_placement_policy; }
74 RowDirection rowDirection() const { return *m_row_direction; } 75 RowDirection rowDirection() const { return *m_row_direction; }
75 ColumnDirection colDirection() const { return *m_col_direction; } 76 ColumnDirection colDirection() const { return *m_col_direction; }
76 77