aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfluxgen <fluxgen>2006-02-19 11:11:22 (GMT)
committerfluxgen <fluxgen>2006-02-19 11:11:22 (GMT)
commitb772fd969f039f7683d2bd666b7573eeb9d468e3 (patch)
tree3d1ae639f5f314f9f55005aa3dad912524afa181
parentd099e7673a51f76b2e6f54484152901288f90ae2 (diff)
downloadfluxbox-b772fd969f039f7683d2bd666b7573eeb9d468e3.zip
fluxbox-b772fd969f039f7683d2bd666b7573eeb9d468e3.tar.bz2
moved placement strategies to different PlacementStrategy classes
-rw-r--r--src/CascadePlacement.cc75
-rw-r--r--src/CascadePlacement.hh45
-rw-r--r--src/ColSmartPlacement.cc136
-rw-r--r--src/ColSmartPlacement.hh36
-rw-r--r--src/Makefile.am5
-rw-r--r--src/RowSmartPlacement.cc155
-rw-r--r--src/RowSmartPlacement.hh37
-rw-r--r--src/Screen.cc9
-rw-r--r--src/Screen.hh23
-rw-r--r--src/ScreenPlacement.cc207
-rw-r--r--src/ScreenPlacement.hh77
-rw-r--r--src/ScreenResources.cc76
-rw-r--r--src/UnderMousePlacement.cc75
-rw-r--r--src/UnderMousePlacement.hh36
-rw-r--r--src/Workspace.cc279
15 files changed, 905 insertions, 366 deletions
diff --git a/src/CascadePlacement.cc b/src/CascadePlacement.cc
new file mode 100644
index 0000000..4cad9d0
--- /dev/null
+++ b/src/CascadePlacement.cc
@@ -0,0 +1,75 @@
1// CascadePlacement.cc
2// Copyright (c) 2006 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 OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22// $Id$
23
24#include "CascadePlacement.hh"
25
26#include "Window.hh"
27#include "Screen.hh"
28
29CascadePlacement::CascadePlacement(const BScreen &screen) {
30 // +1 ?
31 m_cascade_x = new int[screen.numHeads() + 1];
32 m_cascade_y = new int[screen.numHeads() + 1];
33 for (int i=0; i < screen.numHeads() + 1; i++) {
34 m_cascade_x[i] = 32 + screen.getHeadX(i);
35 m_cascade_y[i] = 32 + screen.getHeadY(i);
36 }
37
38}
39
40CascadePlacement::~CascadePlacement() {
41 delete [] m_cascade_x;
42 delete [] m_cascade_y;
43}
44
45bool CascadePlacement::placeWindow(const std::vector<FluxboxWindow *> &windowlist,
46 const FluxboxWindow &win,
47 int &place_x, int &place_y) {
48
49 int head = (signed) win.screen().getCurrHead();
50 int head_left = (signed) win.screen().maxLeft(head);
51 int head_right = (signed) win.screen().maxRight(head);
52 int head_top = (signed) win.screen().maxTop(head);
53 int head_bot = (signed) win.screen().maxBottom(head);
54
55 if ((m_cascade_x[head] > ((head_left + head_right) / 2)) ||
56 (m_cascade_y[head] > ((head_top + head_bot) / 2))) {
57 m_cascade_x[head] = head_left + 32;
58 m_cascade_y[head] = head_top + 32;
59 }
60
61 place_x = m_cascade_x[head];
62 place_y = m_cascade_y[head];
63
64 // just one borderwidth, so they can share a borderwidth (looks better)
65 int titlebar_height =
66 win.titlebarHeight() + win.fbWindow().borderWidth();
67 if (titlebar_height < 4) // make sure it is not insignificant
68 titlebar_height = 32;
69
70 m_cascade_x[head] += titlebar_height;
71 m_cascade_y[head] += titlebar_height;
72
73 return true;
74}
75
diff --git a/src/CascadePlacement.hh b/src/CascadePlacement.hh
new file mode 100644
index 0000000..6fde194
--- /dev/null
+++ b/src/CascadePlacement.hh
@@ -0,0 +1,45 @@
1// CascadePlacement.hh
2// Copyright (c) 2006 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 OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22// $Id$
23
24#ifndef CASCADEPLACEMENT_HH
25#define CASCADEPLACEMENT_HH
26
27#include "PlacementStrategy.hh"
28#include "FbTk/NotCopyable.hh"
29
30class BScreen;
31
32class CascadePlacement: public PlacementStrategy,
33 private FbTk::NotCopyable {
34public:
35 explicit CascadePlacement(const BScreen &screen);
36 ~CascadePlacement();
37 bool placeWindow(const std::vector<FluxboxWindow *> &windowlist,
38 const FluxboxWindow &window,
39 int &place_x, int &place_y);
40private:
41 int *m_cascade_x; ///< need a cascade for each head (Xinerama)
42 int *m_cascade_y; ///< need a cascade for each head (Xinerama)
43};
44
45#endif // CASCADEPLACEMENT_HH
diff --git a/src/ColSmartPlacement.cc b/src/ColSmartPlacement.cc
new file mode 100644
index 0000000..abb74d7
--- /dev/null
+++ b/src/ColSmartPlacement.cc
@@ -0,0 +1,136 @@
1// ColSmartPlacement.cc
2// Copyright (c) 2006 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 OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22// $Id$
23
24#include "ColSmartPlacement.hh"
25
26#include "Screen.hh"
27#include "ScreenPlacement.hh"
28#include "Window.hh"
29
30bool ColSmartPlacement::placeWindow(const std::vector<FluxboxWindow *> &windowlist,
31 const FluxboxWindow &win,
32 int &place_x, int &place_y) {
33
34 // xinerama head constraints
35 int head = (signed) win.screen().getCurrHead();
36 int head_left = (signed) win.screen().maxLeft(head);
37 int head_right = (signed) win.screen().maxRight(head);
38 int head_top = (signed) win.screen().maxTop(head);
39 int head_bot = (signed) win.screen().maxBottom(head);
40
41 bool placed = false;
42 int next_x, next_y;
43 const ScreenPlacement &screen_placement =
44 dynamic_cast<const ScreenPlacement &>(win.screen().placementStrategy());
45
46 bool top_bot = screen_placement.colDirection() == ScreenPlacement::TOPBOTTOM;
47 bool left_right = screen_placement.rowDirection() == ScreenPlacement::LEFTRIGHT;
48
49 int test_x;
50
51 int win_w = win.width() + win.fbWindow().borderWidth()*2;
52 int win_h = win.height() + win.fbWindow().borderWidth()*2;
53
54 if (left_right)
55 test_x = head_left;
56 else
57 test_x = head_right - win_w;
58
59 int change_y = 1;
60 if (screen_placement.colDirection() == ScreenPlacement::BOTTOMTOP)
61 change_y = -1;
62
63 while (!placed &&
64 (left_right ? test_x + win_w <= head_right
65 : test_x >= head_left)) {
66
67 if (left_right)
68 next_x = head_right; // it will get shrunk
69 else
70 next_x = head_left-1;
71
72 int test_y;
73 if (top_bot)
74 test_y = head_top;
75 else
76 test_y = head_bot - win_h;
77
78 while (!placed &&
79 (top_bot ? test_y + win_h <= head_bot
80 : test_y >= head_top)) {
81 placed = true;
82
83 next_y = test_y + change_y;
84
85 std::vector<FluxboxWindow *>::const_iterator it =
86 windowlist.begin();
87 std::vector<FluxboxWindow *>::const_iterator it_end =
88 windowlist.end();
89 for (; it != it_end && placed; ++it) {
90 int curr_x = (*it)->x();
91 int curr_y = (*it)->y();
92 int curr_w = (*it)->width() + (*it)->fbWindow().borderWidth()*2;
93 int curr_h = (*it)->height() + (*it)->fbWindow().borderWidth()*2;
94
95 if (curr_x < test_x + win_w &&
96 curr_x + curr_w > test_x &&
97 curr_y < test_y + win_h &&
98 curr_y + curr_h > test_y) {
99 // this window is in the way
100 placed = false;
101
102 // we find the next y that we can go to (a window will be in the way
103 // all the way to its bottom)
104 if (top_bot) {
105 if (curr_y + curr_h > next_y)
106 next_y = curr_y + curr_h;
107 } else {
108 if (curr_y - win_h < next_y)
109 next_y = curr_y - win_h;
110 }
111
112 // but we can only go to the nearest x, since that is where the
113 // next time current windows in the way will change
114 if (left_right) {
115 if (curr_x + curr_w < next_x)
116 next_x = curr_x + curr_w;
117 } else {
118 if (curr_x - win_w > next_x)
119 next_x = curr_x - win_w;
120 }
121 }
122 }
123
124 if (placed) {
125 place_x = test_x;
126 place_y = test_y;
127 }
128
129 test_y = next_y;
130 } // end while
131
132 test_x = next_x;
133 } // end while
134
135 return placed;
136}
diff --git a/src/ColSmartPlacement.hh b/src/ColSmartPlacement.hh
new file mode 100644
index 0000000..ad17d3b
--- /dev/null
+++ b/src/ColSmartPlacement.hh
@@ -0,0 +1,36 @@
1// ColSmartPlacement.hh
2// Copyright (c) 2006 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 OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22// $Id$
23
24#ifndef COLSMARTPLACEMENT_HH
25#define COLSMARTPLACEMENT_HH
26
27#include "PlacementStrategy.hh"
28
29class ColSmartPlacement: public PlacementStrategy {
30public:
31 bool placeWindow(const std::vector<FluxboxWindow *> &windowlist,
32 const FluxboxWindow &win,
33 int &place_x, int &place_y);
34};
35
36#endif // COLSMARTPLACEMENT_HH
diff --git a/src/Makefile.am b/src/Makefile.am
index f2f515d..156eff8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -128,6 +128,11 @@ fluxbox_SOURCES = AtomHandler.hh ArrowButton.hh ArrowButton.cc \
128 Resources.cc \ 128 Resources.cc \
129 WindowCmd.hh WindowCmd.cc \ 129 WindowCmd.hh WindowCmd.cc \
130 FocusControl.hh FocusControl.cc \ 130 FocusControl.hh FocusControl.cc \
131 CascadePlacement.hh CascadePlacement.cc \
132 ColSmartPlacement.hh ColSmartPlacement.cc \
133 RowSmartPlacement.hh RowSmartPlacement.cc \
134 ScreenPlacement.hh ScreenPlacement.cc \
135 UnderMousePlacement.hh UnderMousePlacement.cc \
131 ${newwmspec_SOURCE} ${gnome_SOURCE} \ 136 ${newwmspec_SOURCE} ${gnome_SOURCE} \
132 ${REMEMBER_SOURCE} ${TOOLBAR_SOURCE} 137 ${REMEMBER_SOURCE} ${TOOLBAR_SOURCE}
133 138
diff --git a/src/RowSmartPlacement.cc b/src/RowSmartPlacement.cc
new file mode 100644
index 0000000..eb2956b
--- /dev/null
+++ b/src/RowSmartPlacement.cc
@@ -0,0 +1,155 @@
1// RowSmartPlacement.cc
2// Copyright (c) 2006 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 OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22// $Id$
23
24#include "RowSmartPlacement.hh"
25
26#include "Window.hh"
27#include "Screen.hh"
28#include "ScreenPlacement.hh"
29
30bool RowSmartPlacement::placeWindow(const std::vector<FluxboxWindow *> &windowlist,
31 const FluxboxWindow &win,
32 int &place_x, int &place_y) {
33
34 bool placed = false;
35 int next_x, next_y;
36
37 // view (screen + head) constraints
38 int head = (signed) win.screen().getCurrHead();
39 int head_left = (signed) win.screen().maxLeft(head);
40 int head_right = (signed) win.screen().maxRight(head);
41 int head_top = (signed) win.screen().maxTop(head);
42 int head_bot = (signed) win.screen().maxBottom(head);
43
44 const ScreenPlacement &screen_placement =
45 dynamic_cast<const ScreenPlacement &>(win.screen().placementStrategy());
46
47 bool top_bot =
48 screen_placement.colDirection() == ScreenPlacement::TOPBOTTOM;
49 bool left_right =
50 screen_placement.rowDirection() == ScreenPlacement::LEFTRIGHT;
51
52 int change_x = 1, change_y = 1;
53
54 if (screen_placement.colDirection() == ScreenPlacement::BOTTOMTOP)
55 change_y = -1;
56
57 if (screen_placement.rowDirection() == ScreenPlacement::RIGHTLEFT)
58 change_x = -1;
59
60
61
62
63 int win_h = win.height() + win.fbWindow().borderWidth()*2;
64 int win_w = win.width() + win.fbWindow().borderWidth()*2;
65 int test_y;
66 if (top_bot)
67 test_y = head_top;
68 else
69 test_y = head_bot - win_h;
70
71 while (!placed &&
72 (top_bot ? test_y + win_h <= head_bot
73 : test_y >= head_top)) {
74
75 int test_x;
76 if (left_right)
77 test_x = head_left;
78 else
79 test_x = head_right - win_w;
80
81 // The trick here is that we set it to the furthest away one,
82 // then the code brings it back down to the safest one that
83 // we can go to (i.e. the next untested area)
84 if (top_bot)
85 next_y = head_bot; // will be shrunk
86 else
87 next_y = head_top-1;
88
89 while (!placed &&
90 (left_right ? test_x + win_w <= head_right
91 : test_x >= head_left)) {
92
93 placed = true;
94
95 next_x = test_x + change_x;
96
97 std::vector<FluxboxWindow *>::const_iterator win_it =
98 windowlist.begin();
99 std::vector<FluxboxWindow *>::const_iterator win_it_end =
100 windowlist.end();
101
102 for (; win_it != win_it_end && placed; ++win_it) {
103 FluxboxWindow &window = **win_it;
104
105 int curr_x = window.x();
106 int curr_y = window.y();
107 int curr_w = window.width() + window.fbWindow().borderWidth()*2;
108 int curr_h = window.height() + window.fbWindow().borderWidth()*2;
109
110 if (curr_x < test_x + win_w &&
111 curr_x + curr_w > test_x &&
112 curr_y < test_y + win_h &&
113 curr_y + curr_h > test_y) {
114 // this window is in the way
115 placed = false;
116
117 // we find the next x that we can go to (a window will be in the way
118 // all the way to its far side)
119 if (left_right) {
120 if (curr_x + curr_w > next_x)
121 next_x = curr_x + curr_w;
122 } else {
123 if (curr_x - win_w < next_x)
124 next_x = curr_x - win_w;
125 }
126
127 // but we can only go to the nearest y, since that is where the
128 // next time current windows in the way will change
129 if (top_bot) {
130 if (curr_y + curr_h < next_y)
131 next_y = curr_y + curr_h;
132 } else {
133 if (curr_y - win_h > next_y)
134 next_y = curr_y - win_h;
135 }
136 }
137 }
138
139
140 if (placed) {
141 place_x = test_x;
142 place_y = test_y;
143
144 break;
145 }
146
147 test_x = next_x;
148 } // end while
149
150 test_y = next_y;
151 } // end while
152
153
154 return placed;
155}
diff --git a/src/RowSmartPlacement.hh b/src/RowSmartPlacement.hh
new file mode 100644
index 0000000..43dbf55
--- /dev/null
+++ b/src/RowSmartPlacement.hh
@@ -0,0 +1,37 @@
1// RowSmartPlacement.hh
2// Copyright (c) 2006 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 OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22// $Id$
23
24#ifndef ROWSMARTPLACEMENT_HH
25#define ROWSMARTPLACEMENT_HH
26
27#include "PlacementStrategy.hh"
28
29class RowSmartPlacement: public PlacementStrategy {
30public:
31 bool placeWindow(const std::vector<FluxboxWindow *> &windowlist,
32 const FluxboxWindow &win,
33 int &place_x, int &place_y);
34};
35
36#endif // ROWSMARTPLACEMENT_HH
37
diff --git a/src/Screen.cc b/src/Screen.cc
index 8128384..2d58a01 100644
--- a/src/Screen.cc
+++ b/src/Screen.cc
@@ -33,6 +33,7 @@
33#include "Netizen.hh" 33#include "Netizen.hh"
34 34
35#include "FocusControl.hh" 35#include "FocusControl.hh"
36#include "ScreenPlacement.hh"
36 37
37// themes 38// themes
38#include "FbWinFrameTheme.hh" 39#include "FbWinFrameTheme.hh"
@@ -184,9 +185,7 @@ BScreen::ScreenResource::ScreenResource(FbTk::ResourceManager &rm,
184 menu_delay(rm, 0, scrname + ".menuDelay", altscrname+".MenuDelay"), 185 menu_delay(rm, 0, scrname + ".menuDelay", altscrname+".MenuDelay"),
185 menu_delay_close(rm, 0, scrname + ".menuDelayClose", altscrname+".MenuDelayClose"), 186 menu_delay_close(rm, 0, scrname + ".menuDelayClose", altscrname+".MenuDelayClose"),
186 menu_mode(rm, FbTk::MenuTheme::DELAY_OPEN, scrname+".menuMode", altscrname+".MenuMode"), 187 menu_mode(rm, FbTk::MenuTheme::DELAY_OPEN, scrname+".menuMode", altscrname+".MenuMode"),
187 placement_policy(rm, ROWSMARTPLACEMENT, scrname+".windowPlacement", altscrname+".WindowPlacement"), 188
188 row_direction(rm, LEFTRIGHT, scrname+".rowPlacementDirection", altscrname+".RowPlacementDirection"),
189 col_direction(rm, TOPBOTTOM, scrname+".colPlacementDirection", altscrname+".ColPlacementDirection"),
190 gc_line_width(rm, 1, scrname+".overlay.lineWidth", altscrname+".Overlay.LineWidth"), 189 gc_line_width(rm, 1, scrname+".overlay.lineWidth", altscrname+".Overlay.LineWidth"),
191 gc_line_style(rm, 190 gc_line_style(rm,
192 FbTk::GContext::LINESOLID, 191 FbTk::GContext::LINESOLID,
@@ -238,6 +237,7 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
238 m_name(screenname), 237 m_name(screenname),
239 m_altname(altscreenname), 238 m_altname(altscreenname),
240 m_focus_control(new FocusControl(*this)), 239 m_focus_control(new FocusControl(*this)),
240 m_placement_strategy(new ScreenPlacement(*this)),
241 m_xinerama_headinfo(0), 241 m_xinerama_headinfo(0),
242 m_shutdown(false) { 242 m_shutdown(false) {
243 243
@@ -446,7 +446,10 @@ BScreen::~BScreen() {
446 446
447 // TODO fluxgen: check if this is the right place 447 // TODO fluxgen: check if this is the right place
448 delete [] m_head_areas; 448 delete [] m_head_areas;
449
449 delete m_focus_control; 450 delete m_focus_control;
451 delete m_placement_strategy;
452
450} 453}
451 454
452void BScreen::initWindows() { 455void BScreen::initWindows() {
diff --git a/src/Screen.hh b/src/Screen.hh
index bb5db3a..4f91d9c 100644
--- a/src/Screen.hh
+++ b/src/Screen.hh
@@ -30,6 +30,7 @@
30 30
31#include "FbRootWindow.hh" 31#include "FbRootWindow.hh"
32#include "MenuTheme.hh" 32#include "MenuTheme.hh"
33#include "PlacementStrategy.hh"
33 34
34#include "FbTk/Resource.hh" 35#include "FbTk/Resource.hh"
35#include "FbTk/Subject.hh" 36#include "FbTk/Subject.hh"
@@ -63,6 +64,7 @@ class Strut;
63class Slit; 64class Slit;
64class HeadArea; 65class HeadArea;
65class FocusControl; 66class FocusControl;
67class PlacementStrategy;
66 68
67namespace FbTk { 69namespace FbTk {
68class Menu; 70class Menu;
@@ -90,15 +92,6 @@ public:
90 QUADRANTRESIZE, 92 QUADRANTRESIZE,
91 DEFAULTRESIZE = BOTTOMRESIZE }; 93 DEFAULTRESIZE = BOTTOMRESIZE };
92 94
93 enum PlacementPolicy {
94 ROWSMARTPLACEMENT,
95 COLSMARTPLACEMENT,
96 CASCADEPLACEMENT,
97 UNDERMOUSEPLACEMENT
98 };
99
100 enum RowDirection { LEFTRIGHT, RIGHTLEFT};
101 enum ColumnDirection { TOPBOTTOM, BOTTOMTOP};
102 95
103 typedef std::vector<FluxboxWindow *> Icons; 96 typedef std::vector<FluxboxWindow *> Icons;
104 97
@@ -218,10 +211,7 @@ public:
218 /// hide all windowmenus except the given one (if given) 211 /// hide all windowmenus except the given one (if given)
219 void hideWindowMenus(const FluxboxWindow* except= 0); 212 void hideWindowMenus(const FluxboxWindow* except= 0);
220 213
221 inline PlacementPolicy getPlacementPolicy() const { return *resource.placement_policy; }
222 inline int getEdgeSnapThreshold() const { return *resource.edge_snap_threshold; } 214 inline int getEdgeSnapThreshold() const { return *resource.edge_snap_threshold; }
223 inline RowDirection getRowPlacementDirection() const { return *resource.row_direction; }
224 inline ColumnDirection getColPlacementDirection() const { return *resource.col_direction; }
225 215
226 void setRootColormapInstalled(bool r) { root_colormap_installed = r; } 216 void setRootColormapInstalled(bool r) { root_colormap_installed = r; }
227 void saveRootCommand(std::string rootcmd) { *resource.rootcommand = rootcmd; } 217 void saveRootCommand(std::string rootcmd) { *resource.rootcommand = rootcmd; }
@@ -249,7 +239,9 @@ public:
249 const std::string &altName() const { return m_altname; } 239 const std::string &altName() const { return m_altname; }
250 bool isShuttingdown() const { return m_shutdown; } 240 bool isShuttingdown() const { return m_shutdown; }
251 241
252 242 PlacementStrategy &placementStrategy() { return *m_placement_strategy; }
243 const PlacementStrategy &placementStrategy() const { return *m_placement_strategy; }
244
253 int addWorkspace(); 245 int addWorkspace();
254 int removeLastWorkspace(); 246 int removeLastWorkspace();
255 // scroll workspaces 247 // scroll workspaces
@@ -442,9 +434,7 @@ private:
442 FbTk::Resource<int> workspaces, edge_snap_threshold, focused_alpha, 434 FbTk::Resource<int> workspaces, edge_snap_threshold, focused_alpha,
443 unfocused_alpha, menu_alpha, menu_delay, menu_delay_close; 435 unfocused_alpha, menu_alpha, menu_delay, menu_delay_close;
444 FbTk::Resource<FbTk::MenuTheme::MenuMode> menu_mode; 436 FbTk::Resource<FbTk::MenuTheme::MenuMode> menu_mode;
445 FbTk::Resource<PlacementPolicy> placement_policy; 437
446 FbTk::Resource<RowDirection> row_direction;
447 FbTk::Resource<ColumnDirection> col_direction;
448 FbTk::Resource<int> gc_line_width; 438 FbTk::Resource<int> gc_line_width;
449 FbTk::Resource<FbTk::GContext::LineStyle> gc_line_style; 439 FbTk::Resource<FbTk::GContext::LineStyle> gc_line_style;
450 FbTk::Resource<FbTk::GContext::JoinStyle> gc_join_style; 440 FbTk::Resource<FbTk::GContext::JoinStyle> gc_join_style;
@@ -458,6 +448,7 @@ private:
458 const std::string m_name, m_altname; 448 const std::string m_name, m_altname;
459 449
460 FocusControl *m_focus_control; 450 FocusControl *m_focus_control;
451 PlacementStrategy *m_placement_strategy;
461 452
462 // This is a map of windows to clients for clients that had a left 453 // This is a map of windows to clients for clients that had a left
463 // window set, but that window wasn't present at the time 454 // window set, but that window wasn't present at the time
diff --git a/src/ScreenPlacement.cc b/src/ScreenPlacement.cc
new file mode 100644
index 0000000..b455fc7
--- /dev/null
+++ b/src/ScreenPlacement.cc
@@ -0,0 +1,207 @@
1// ScreenPlacement.cc
2// Copyright (c) 2006 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 OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22// $Id$
23
24#include "ScreenPlacement.hh"
25
26
27#include "RowSmartPlacement.hh"
28#include "UnderMousePlacement.hh"
29#include "ColSmartPlacement.hh"
30#include "CascadePlacement.hh"
31
32#include "Screen.hh"
33#include "Window.hh"
34
35#include <iostream>
36#include <exception>
37using std::cerr;
38using std::endl;
39
40ScreenPlacement::ScreenPlacement(BScreen &screen):
41 m_row_direction(screen.resourceManager(), LEFTRIGHT,
42 screen.name()+".rowPlacementDirection",
43 screen.altName()+".RowPlacementDirection"),
44 m_col_direction(screen.resourceManager(), TOPBOTTOM,
45 screen.name()+".colPlacementDirection",
46 screen.altName()+".ColPlacementDirection"),
47 m_placement_policy(screen.resourceManager(), ROWSMARTPLACEMENT,
48 screen.name()+".windowPlacement",
49 screen.altName()+".WindowPlacement"),
50 m_old_policy(*m_placement_policy),
51 m_strategy(new RowSmartPlacement())
52{
53}
54
55bool ScreenPlacement::placeWindow(const std::vector<FluxboxWindow *> &windowlist,
56 const FluxboxWindow &win,
57 int &place_x, int &place_y) {
58
59 // check the resource placement and see if has changed
60 // and if so update the strategy
61 if (m_old_policy != *m_placement_policy) {
62 m_old_policy = *m_placement_policy;
63 switch (*m_placement_policy) {
64 case ROWSMARTPLACEMENT:
65 m_strategy.reset(new RowSmartPlacement());
66 break;
67 case COLSMARTPLACEMENT:
68 m_strategy.reset(new ColSmartPlacement());
69 break;
70 case CASCADEPLACEMENT:
71 m_strategy.reset(new CascadePlacement(win.screen()));
72 break;
73 case UNDERMOUSEPLACEMENT:
74 m_strategy.reset(new UnderMousePlacement());
75 break;
76 }
77 }
78
79 // view (screen + head) constraints
80 int head = (signed) win.screen().getCurrHead();
81 int head_left = (signed) win.screen().maxLeft(head);
82 int head_right = (signed) win.screen().maxRight(head);
83 int head_top = (signed) win.screen().maxTop(head);
84 int head_bot = (signed) win.screen().maxBottom(head);
85
86 // start placement, top left corner
87 place_x = head_left;
88 place_y = head_top;
89
90 bool placed = false;
91 try {
92 placed = m_strategy->placeWindow(windowlist,
93 win,
94 place_x, place_y);
95 } catch (std::bad_cast cast) {
96 // This should not happen.
97 // If for some reason we change the PlacementStrategy in Screen
98 // from ScreenPlacement to something else then we might get
99 // bad_cast from some placement strategies.
100 cerr<<"Failed to place window: "<<cast.what()<<endl;
101 }
102
103 if (!placed) {
104 // Create fallback strategy, when we need it the first time
105 // This strategy must succeed!
106 if (m_fallback_strategy.get() == 0)
107 m_fallback_strategy.reset(new CascadePlacement(win.screen()));
108
109 m_fallback_strategy->placeWindow(windowlist,
110 win,
111 place_x, place_y);
112 }
113
114
115
116 int win_w = win.width() + win.fbWindow().borderWidth()*2,
117 win_h = win.height() + win.fbWindow().borderWidth()*2;
118
119
120 // make sure the window is inside our screen(head) area
121 if (place_x + win_w > head_right)
122 place_x = (head_right - win_w) / 2;
123 if (place_y + win_h > head_bot)
124 place_y = (head_bot - win_h) / 2;
125
126 return true;
127}
128
129
130
131////////////////////// Placement Resources
132template <>
133void FbTk::Resource<ScreenPlacement::PlacementPolicy>::setFromString(const char *str) {
134 if (strcasecmp("RowSmartPlacement", str) == 0)
135 *(*this) = ScreenPlacement::ROWSMARTPLACEMENT;
136 else if (strcasecmp("ColSmartPlacement", str) == 0)
137 *(*this) = ScreenPlacement::COLSMARTPLACEMENT;
138 else if (strcasecmp("UnderMousePlacement", str) == 0)
139 *(*this) = ScreenPlacement::UNDERMOUSEPLACEMENT;
140 else if (strcasecmp("CascadePlacement", str) == 0)
141 *(*this) = ScreenPlacement::CASCADEPLACEMENT;
142 else
143 setDefaultValue();
144}
145
146template <>
147std::string FbTk::Resource<ScreenPlacement::PlacementPolicy>::getString() const {
148 switch (*(*this)) {
149 case ScreenPlacement::ROWSMARTPLACEMENT:
150 return "RowSmartPlacement";
151 case ScreenPlacement::COLSMARTPLACEMENT:
152 return "ColSmartPlacement";
153 case ScreenPlacement::UNDERMOUSEPLACEMENT:
154 return "UnderMousePlacement";
155 case ScreenPlacement::CASCADEPLACEMENT:
156 return "CascadePlacement";
157 }
158
159 return "RowSmartPlacement";
160}
161
162template <>
163void FbTk::Resource<ScreenPlacement::RowDirection>::setFromString(const char *str) {
164 if (strcasecmp("LeftToRight", str) == 0)
165 *(*this) = ScreenPlacement::LEFTRIGHT;
166 else if (strcasecmp("RightToLeft", str) == 0)
167 *(*this) = ScreenPlacement::RIGHTLEFT;
168 else
169 setDefaultValue();
170
171}
172
173template <>
174std::string FbTk::Resource<ScreenPlacement::RowDirection>::getString() const {
175 switch (*(*this)) {
176 case ScreenPlacement::LEFTRIGHT:
177 return "LeftToRight";
178 case ScreenPlacement::RIGHTLEFT:
179 return "RightToLeft";
180 }
181
182 return "LeftToRight";
183}
184
185
186template <>
187void FbTk::Resource<ScreenPlacement::ColumnDirection>::setFromString(const char *str) {
188 if (strcasecmp("TopToBottom", str) == 0)
189 *(*this) = ScreenPlacement::TOPBOTTOM;
190 else if (strcasecmp("BottomToTop", str) == 0)
191 *(*this) = ScreenPlacement::BOTTOMTOP;
192 else
193 setDefaultValue();
194
195}
196
197template <>
198std::string FbTk::Resource<ScreenPlacement::ColumnDirection>::getString() const {
199 switch (*(*this)) {
200 case ScreenPlacement::TOPBOTTOM:
201 return "TopToBottom";
202 case ScreenPlacement::BOTTOMTOP:
203 return "BottomToTop";
204 }
205
206 return "TopToBottom";
207}
diff --git a/src/ScreenPlacement.hh b/src/ScreenPlacement.hh
new file mode 100644
index 0000000..93e6a82
--- /dev/null
+++ b/src/ScreenPlacement.hh
@@ -0,0 +1,77 @@
1// ScreenPlacement.hh
2// Copyright (c) 2006 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 OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22// $Id$
23
24#ifndef SCREENPLACEMENT_HH
25#define SCREENPLACEMENT_HH
26
27#include "PlacementStrategy.hh"
28#include "FbTk/Resource.hh"
29
30class BScreen;
31
32/**
33 * Main class for strategy handling
34 * This is a bridge between screen and
35 * the real placement strategy (rowcol, undermouse etc)
36 * The placeWindow function in this class is guaranteed to succeed.
37 * It holds a pointer to the real placement strategy which is
38 * called upon placeWindow, it also holds the placement resources
39 */
40class ScreenPlacement: public PlacementStrategy {
41public:
42 enum PlacementPolicy {
43 ROWSMARTPLACEMENT,
44 COLSMARTPLACEMENT,
45 CASCADEPLACEMENT,
46 UNDERMOUSEPLACEMENT
47 };
48
49 enum RowDirection {
50 LEFTRIGHT, ///< from left to right
51 RIGHTLEFT ///< from right to left
52 };
53 enum ColumnDirection {
54 TOPBOTTOM, ///< from top to bottom
55 BOTTOMTOP ///< from bottom to top
56 };
57
58 explicit ScreenPlacement(BScreen &screen);
59 /// placeWindow is guaranteed to succeed, ignore return value
60 /// @return true
61 bool placeWindow(const std::vector<FluxboxWindow *> &windowlist,
62 const FluxboxWindow &window,
63 int &place_x, int &place_y);
64
65 RowDirection rowDirection() const { return *m_row_direction; }
66 ColumnDirection colDirection() const { return *m_col_direction; }
67
68private:
69 FbTk::Resource<RowDirection> m_row_direction; ///< row direction resource
70 FbTk::Resource<ColumnDirection> m_col_direction; ///< column direction resource
71 FbTk::Resource<PlacementPolicy> m_placement_policy; ///< placement policy resource
72 PlacementPolicy m_old_policy; ///< holds old policy, used to determine if resources has changed
73 std::auto_ptr<PlacementStrategy> m_strategy; ///< main strategy
74 std::auto_ptr<PlacementStrategy> m_fallback_strategy; ///< a fallback strategy if the main strategy fails
75};
76
77#endif // SCREENPLACEMENT_HH
diff --git a/src/ScreenResources.cc b/src/ScreenResources.cc
index 7b4d0c2..f26a376 100644
--- a/src/ScreenResources.cc
+++ b/src/ScreenResources.cc
@@ -29,82 +29,6 @@
29#include <string> 29#include <string>
30using namespace std; 30using namespace std;
31 31
32template <>
33void FbTk::Resource<BScreen::PlacementPolicy>::setFromString(const char *str) {
34 if (strcasecmp("RowSmartPlacement", str) == 0)
35 *(*this) = BScreen::ROWSMARTPLACEMENT;
36 else if (strcasecmp("ColSmartPlacement", str) == 0)
37 *(*this) = BScreen::COLSMARTPLACEMENT;
38 else if (strcasecmp("UnderMousePlacement", str) == 0)
39 *(*this) = BScreen::UNDERMOUSEPLACEMENT;
40 else if (strcasecmp("CascadePlacement", str) == 0)
41 *(*this) = BScreen::CASCADEPLACEMENT;
42 else
43 setDefaultValue();
44}
45
46template <>
47string FbTk::Resource<BScreen::PlacementPolicy>::getString() const {
48 switch (*(*this)) {
49 case BScreen::ROWSMARTPLACEMENT:
50 return "RowSmartPlacement";
51 case BScreen::COLSMARTPLACEMENT:
52 return "ColSmartPlacement";
53 case BScreen::UNDERMOUSEPLACEMENT:
54 return "UnderMousePlacement";
55 case BScreen::CASCADEPLACEMENT:
56 return "CascadePlacement";
57 }
58
59 return "RowSmartPlacement";
60}
61
62template <>
63void FbTk::Resource<BScreen::RowDirection>::setFromString(const char *str) {
64 if (strcasecmp("LeftToRight", str) == 0)
65 *(*this) = BScreen::LEFTRIGHT;
66 else if (strcasecmp("RightToLeft", str) == 0)
67 *(*this) = BScreen::RIGHTLEFT;
68 else
69 setDefaultValue();
70
71}
72
73template <>
74string FbTk::Resource<BScreen::RowDirection>::getString() const {
75 switch (*(*this)) {
76 case BScreen::LEFTRIGHT:
77 return "LeftToRight";
78 case BScreen::RIGHTLEFT:
79 return "RightToLeft";
80 }
81
82 return "LeftToRight";
83}
84
85
86template <>
87void FbTk::Resource<BScreen::ColumnDirection>::setFromString(const char *str) {
88 if (strcasecmp("TopToBottom", str) == 0)
89 *(*this) = BScreen::TOPBOTTOM;
90 else if (strcasecmp("BottomToTop", str) == 0)
91 *(*this) = BScreen::BOTTOMTOP;
92 else
93 setDefaultValue();
94
95}
96
97template <>
98string FbTk::Resource<BScreen::ColumnDirection>::getString() const {
99 switch (*(*this)) {
100 case BScreen::TOPBOTTOM:
101 return "TopToBottom";
102 case BScreen::BOTTOMTOP:
103 return "BottomToTop";
104 }
105
106 return "TopToBottom";
107}
108 32
109template <> 33template <>
110string FbTk::Resource<FbTk::MenuTheme::MenuMode>::getString() const { 34string FbTk::Resource<FbTk::MenuTheme::MenuMode>::getString() const {
diff --git a/src/UnderMousePlacement.cc b/src/UnderMousePlacement.cc
new file mode 100644
index 0000000..3e2bc41
--- /dev/null
+++ b/src/UnderMousePlacement.cc
@@ -0,0 +1,75 @@
1// UnderMousePlacement.cc
2// Copyright (c) 2006 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 OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22// $Id$
23
24#include "UnderMousePlacement.hh"
25
26#include "FbTk/App.hh"
27#include "Screen.hh"
28#include "Window.hh"
29
30bool UnderMousePlacement::placeWindow(const std::vector<FluxboxWindow *> &list,
31 const FluxboxWindow &win,
32 int &place_x, int &place_y) {
33
34 int root_x, root_y, ignore_i;
35
36 unsigned int ignore_ui;
37
38 Window ignore_w;
39
40 XQueryPointer(FbTk::App::instance()->display(),
41 win.screen().rootWindow().window(), &ignore_w,
42 &ignore_w, &root_x, &root_y,
43 &ignore_i, &ignore_i, &ignore_ui);
44
45 // 2*border = border on each side of the screen
46 int win_w = win.width() + win.fbWindow().borderWidth()*2,
47 win_h = win.height() + win.fbWindow().borderWidth()*2;
48
49 int test_x = root_x - (win_w / 2);
50 int test_y = root_y - (win_h / 2);
51
52 // keep the window inside the screen
53 int head = (signed) win.screen().getCurrHead();
54 int head_left = (signed) win.screen().maxLeft(head);
55 int head_right = (signed) win.screen().maxRight(head);
56 int head_top = (signed) win.screen().maxTop(head);
57 int head_bot = (signed) win.screen().maxBottom(head);
58
59 if (test_x < head_left)
60 test_x = head_left;
61
62 if (test_x + win_w > head_right)
63 test_x = head_right - win_w;
64
65 if (test_y < head_top)
66 test_y = head_top;
67
68 if (test_y + win_h > head_bot)
69 test_y = head_bot - win_h;
70
71 place_x = test_x;
72 place_y = test_y;
73
74 return true;
75}
diff --git a/src/UnderMousePlacement.hh b/src/UnderMousePlacement.hh
new file mode 100644
index 0000000..d89133c
--- /dev/null
+++ b/src/UnderMousePlacement.hh
@@ -0,0 +1,36 @@
1// UnderMousePlacement.hh
2// Copyright (c) 2006 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 OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22// $Id$
23
24#ifndef UNDERMOUSEPLACEMENT_HH
25#define UNDERMOUSEPLACEMENT_HH
26
27#include "PlacementStrategy.hh"
28
29class UnderMousePlacement: public PlacementStrategy {
30public:
31 bool placeWindow(const std::vector<FluxboxWindow *> &windowlist,
32 const FluxboxWindow &win,
33 int &place_x, int &place_y);
34};
35
36#endif // UNDERMOUSEPLACEMENT_HH
diff --git a/src/Workspace.cc b/src/Workspace.cc
index 07e76f0..7d53381 100644
--- a/src/Workspace.cc
+++ b/src/Workspace.cc
@@ -33,6 +33,7 @@
33#include "FbWinFrame.hh" 33#include "FbWinFrame.hh"
34#include "WindowCmd.hh" 34#include "WindowCmd.hh"
35#include "FocusControl.hh" 35#include "FocusControl.hh"
36#include "PlacementStrategy.hh"
36 37
37#include "FbTk/I18n.hh" 38#include "FbTk/I18n.hh"
38#include "FbTk/MenuItem.hh" 39#include "FbTk/MenuItem.hh"
@@ -140,21 +141,13 @@ Workspace::Workspace(BScreen &scrn, FbTk::MultLayers &layermanager,
140 m_name(name), 141 m_name(name),
141 m_id(id) { 142 m_id(id) {
142 143
143
144 m_cascade_x = new int[scrn.numHeads() + 1];
145 m_cascade_y = new int[scrn.numHeads() + 1];
146 for (int i=0; i < scrn.numHeads()+1; i++) {
147 m_cascade_x[i] = 32 + scrn.getHeadX(i);
148 m_cascade_y[i] = 32 + scrn.getHeadY(i);
149 }
150 menu().setInternalMenu(); 144 menu().setInternalMenu();
151 setName(name); 145 setName(name);
146
152} 147}
153 148
154 149
155Workspace::~Workspace() { 150Workspace::~Workspace() {
156 delete [] m_cascade_x;
157 delete [] m_cascade_y;
158} 151}
159 152
160void Workspace::setLastFocusedWindow(FluxboxWindow *win) { 153void Workspace::setLastFocusedWindow(FluxboxWindow *win) {
@@ -427,268 +420,12 @@ void Workspace::updateClientmenu() {
427} 420}
428 421
429void Workspace::placeWindow(FluxboxWindow &win) { 422void Workspace::placeWindow(FluxboxWindow &win) {
430 423 int place_x, place_y;
431 bool placed = false; 424 // we ignore the return value,
432 425 // the screen placement strategy is guaranteed to succeed.
433 // restrictions 426 screen().placementStrategy().placeWindow(m_windowlist,
434 int head = (signed) screen().getCurrHead(); 427 win,
435 int head_left = (signed) screen().maxLeft(head); 428 place_x, place_y);
436 int head_right = (signed) screen().maxRight(head);
437 int head_top = (signed) screen().maxTop(head);
438 int head_bot = (signed) screen().maxBottom(head);
439
440 int place_x = head_left, place_y = head_top, change_x = 1, change_y = 1;
441
442 if (screen().getColPlacementDirection() == BScreen::BOTTOMTOP)
443 change_y = -1;
444 if (screen().getRowPlacementDirection() == BScreen::RIGHTLEFT)
445 change_x = -1;
446
447 int win_w = win.width() + win.fbWindow().borderWidth()*2,
448 win_h = win.height() + win.fbWindow().borderWidth()*2;
449
450
451 int test_x, test_y, curr_x, curr_y, curr_w, curr_h;
452
453 switch (screen().getPlacementPolicy()) {
454 case BScreen::UNDERMOUSEPLACEMENT: {
455 int root_x, root_y, ignore_i;
456
457 unsigned int ignore_ui;
458
459 Window ignore_w;
460
461 XQueryPointer(FbTk::App::instance()->display(),
462 screen().rootWindow().window(), &ignore_w,
463 &ignore_w, &root_x, &root_y,
464 &ignore_i, &ignore_i, &ignore_ui);
465
466 test_x = root_x - (win_w / 2);
467 test_y = root_y - (win_h / 2);
468
469 // keep the window inside the screen
470
471 if (test_x < head_left)
472 test_x = head_left;
473
474 if (test_x + win_w > head_right)
475 test_x = head_right - win_w;
476
477 if (test_y < head_top)
478 test_y = head_top;
479
480 if (test_y + win_h > head_bot)
481 test_y = head_bot - win_h;
482
483 place_x = test_x;
484 place_y = test_y;
485
486 placed = true;
487
488 break;
489 } // end case UNDERMOUSEPLACEMENT
490
491 case BScreen::ROWSMARTPLACEMENT: {
492 int next_x, next_y;
493 bool top_bot = screen().getColPlacementDirection() == BScreen::TOPBOTTOM;
494 bool left_right = screen().getRowPlacementDirection() == BScreen::LEFTRIGHT;
495
496 if (top_bot)
497 test_y = head_top;
498 else
499 test_y = head_bot - win_h;
500
501 while (!placed &&
502 (top_bot ? test_y + win_h <= head_bot
503 : test_y >= head_top)) {
504
505 if (left_right)
506 test_x = head_left;
507 else
508 test_x = head_right - win_w;
509
510 // The trick here is that we set it to the furthest away one,
511 // then the code brings it back down to the safest one that
512 // we can go to (i.e. the next untested area)
513 if (top_bot)
514 next_y = head_bot; // will be shrunk
515 else
516 next_y = head_top-1;
517
518 while (!placed &&
519 (left_right ? test_x + win_w <= head_right
520 : test_x >= head_left)) {
521
522 placed = true;
523
524 next_x = test_x + change_x;
525
526 Windows::iterator win_it = m_windowlist.begin();
527 const Windows::iterator win_it_end = m_windowlist.end();
528
529 for (; win_it != win_it_end && placed; ++win_it) {
530 FluxboxWindow &window = **win_it;
531
532 curr_x = window.x();
533 curr_y = window.y();
534 curr_w = window.width() + window.fbWindow().borderWidth()*2;
535 curr_h = window.height() + window.fbWindow().borderWidth()*2;
536
537 if (curr_x < test_x + win_w &&
538 curr_x + curr_w > test_x &&
539 curr_y < test_y + win_h &&
540 curr_y + curr_h > test_y) {
541 // this window is in the way
542 placed = false;
543
544 // we find the next x that we can go to (a window will be in the way
545 // all the way to its far side)
546 if (left_right) {
547 if (curr_x + curr_w > next_x)
548 next_x = curr_x + curr_w;
549 } else {
550 if (curr_x - win_w < next_x)
551 next_x = curr_x - win_w;
552 }
553
554 // but we can only go to the nearest y, since that is where the
555 // next time current windows in the way will change
556 if (top_bot) {
557 if (curr_y + curr_h < next_y)
558 next_y = curr_y + curr_h;
559 } else {
560 if (curr_y - win_h > next_y)
561 next_y = curr_y - win_h;
562 }
563 }
564 }
565
566
567 if (placed) {
568 place_x = test_x;
569 place_y = test_y;
570
571 break;
572 }
573
574 test_x = next_x;
575 } // end while
576
577 test_y = next_y;
578 } // end while
579
580 break;
581 } // end case ROWSMARTPLACEMENT
582
583 case BScreen::COLSMARTPLACEMENT: {
584 int next_x, next_y;
585 bool top_bot = screen().getColPlacementDirection() == BScreen::TOPBOTTOM;
586 bool left_right = screen().getRowPlacementDirection() == BScreen::LEFTRIGHT;
587
588 if (left_right)
589 test_x = head_left;
590 else
591 test_x = head_right - win_w;
592
593 while (!placed &&
594 (left_right ? test_x + win_w <= head_right
595 : test_x >= head_left)) {
596
597 if (left_right)
598 next_x = head_right; // it will get shrunk
599 else
600 next_x = head_left-1;
601
602 if (top_bot)
603 test_y = head_top;
604 else
605 test_y = head_bot - win_h;
606
607 while (!placed &&
608 (top_bot ? test_y + win_h <= head_bot
609 : test_y >= head_top)) {
610 placed = True;
611
612 next_y = test_y + change_y;
613
614 Windows::iterator it = m_windowlist.begin();
615 Windows::iterator it_end = m_windowlist.end();
616 for (; it != it_end && placed; ++it) {
617 curr_x = (*it)->x();
618 curr_y = (*it)->y();
619 curr_w = (*it)->width() + (*it)->fbWindow().borderWidth()*2;
620 curr_h = (*it)->height() + (*it)->fbWindow().borderWidth()*2;
621
622 if (curr_x < test_x + win_w &&
623 curr_x + curr_w > test_x &&
624 curr_y < test_y + win_h &&
625 curr_y + curr_h > test_y) {
626 // this window is in the way
627 placed = False;
628
629 // we find the next y that we can go to (a window will be in the way
630 // all the way to its bottom)
631 if (top_bot) {
632 if (curr_y + curr_h > next_y)
633 next_y = curr_y + curr_h;
634 } else {
635 if (curr_y - win_h < next_y)
636 next_y = curr_y - win_h;
637 }
638
639 // but we can only go to the nearest x, since that is where the
640 // next time current windows in the way will change
641 if (left_right) {
642 if (curr_x + curr_w < next_x)
643 next_x = curr_x + curr_w;
644 } else {
645 if (curr_x - win_w > next_x)
646 next_x = curr_x - win_w;
647 }
648 }
649 }
650
651 if (placed) {
652 place_x = test_x;
653 place_y = test_y;
654 }
655
656 test_y = next_y;
657 } // end while
658
659 test_x = next_x;
660 } // end while
661
662 break;
663 } // end COLSMARTPLACEMENT
664
665 }
666
667 // cascade placement or smart placement failed
668 if (! placed) {
669
670 if ((m_cascade_x[head] > ((head_left + head_right) / 2)) ||
671 (m_cascade_y[head] > ((head_top + head_bot) / 2))) {
672 m_cascade_x[head] = head_left + 32;
673 m_cascade_y[head] = head_top + 32;
674 }
675
676 place_x = m_cascade_x[head];
677 place_y = m_cascade_y[head];
678
679 // just one borderwidth, so they can share a borderwidth (looks better)
680 int titlebar_height = win.titlebarHeight() + win.fbWindow().borderWidth();
681 if (titlebar_height < 4) // make sure it is not insignificant
682 titlebar_height = 32;
683 m_cascade_x[head] += titlebar_height;
684 m_cascade_y[head] += titlebar_height;
685 }
686
687 if (place_x + win_w > head_right)
688 place_x = (head_right - win_w) / 2;
689 if (place_y + win_h > head_bot)
690 place_y = (head_bot - win_h) / 2;
691
692 429
693 win.moveResize(place_x, place_y, win.width(), win.height()); 430 win.moveResize(place_x, place_y, win.width(), win.height());
694} 431}