summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--src/FocusControl.cc255
-rw-r--r--src/FocusControl.hh11
3 files changed, 75 insertions, 195 deletions
diff --git a/ChangeLog b/ChangeLog
index a96f021..283bb9d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
1(Format: Year/Month/Day) 1(Format: Year/Month/Day)
2Changes for 0.9.16: 2Changes for 0.9.16:
3*06/04/23:
4 * Tidy up window cycling, and make linear mode work in order of
5 creation (Thanks Mark Tiefenbruck, mark at tiefenbruck dot org)
6 FocusControl.hh/cc
3*06/04/22: 7*06/04/22:
4 * Fix workspace menu corruption when window title changes (Simon) 8 * Fix workspace menu corruption when window title changes (Simon)
5 sf.net bug #1113668 9 sf.net bug #1113668
diff --git a/src/FocusControl.cc b/src/FocusControl.cc
index a31270b..f7ed962 100644
--- a/src/FocusControl.cc
+++ b/src/FocusControl.cc
@@ -77,108 +77,84 @@ bool doSkipWindow(const WinClient &winclient, int opts) {
77 ); 77 );
78} 78}
79 79
80void FocusControl::prevFocus(int opts) { 80void FocusControl::cycleFocus(int opts, bool cycle_reverse) {
81 int num_windows = m_screen.currentWorkspace()->numberOfWindows(); 81 int num_windows = m_screen.currentWorkspace()->numberOfWindows();
82 82
83 if (num_windows < 1) 83 if (num_windows < 1)
84 return; 84 return;
85 85
86 if (!(opts & CYCLELINEAR)) { 86 FocusedWindows *window_list = (opts & CYCLELINEAR) ? &m_creation_order_list : &m_focused_list;
87 if (!m_cycling_focus) { 87 if (!m_cycling_focus) {
88 m_cycling_focus = true; 88 m_cycling_focus = true;
89 m_cycling_window = m_focused_list.end(); 89 if ((opts & CYCLELINEAR) && m_cycling_window != m_focused_list.end()) {
90 m_cycling_last = 0; 90 m_cycling_creation_order = true;
91 m_cycling_window = find(window_list->begin(),window_list->end(),*m_cycling_window);
91 } else { 92 } else {
92 // already cycling, so restack to put windows back in their proper order 93 m_cycling_creation_order = (opts & CYCLELINEAR);
93 m_screen.layerManager().restack(); 94 m_cycling_window = window_list->begin();
94 } 95 }
95 // if it is stacked, we want the highest window in the focused list 96 m_cycling_last = 0;
96 // that is on the same workspace 97 } else {
97 FocusedWindows::iterator it = m_cycling_window; 98 // already cycling, so restack to put windows back in their proper order
98 FocusedWindows::iterator it_end = m_focused_list.end(); 99 m_screen.layerManager().restack();
99 100 if (m_cycling_creation_order ^ (bool)(opts & CYCLELINEAR)) {
100 while (true) { 101 m_cycling_creation_order ^= true;
101 --it; 102 if (m_cycling_window != m_focused_list.end() && m_cycling_window != m_creation_order_list.end())
102 if (it == it_end) { 103 m_cycling_window = find(window_list->begin(),window_list->end(),*m_cycling_window);
103 it = m_focused_list.end(); 104 else
104 --it; 105 m_cycling_window = window_list->begin();
105 } 106 }
106 // give up [do nothing] if we reach the current focused again 107 }
107 if ((*it) == (*m_cycling_window)) { 108 // if it is stacked, we want the highest window in the focused list
108 break; 109 // that is on the same workspace
109 } 110 FocusedWindows::iterator it = m_cycling_window;
110 111 FocusedWindows::iterator it_begin = window_list->begin();
111 FluxboxWindow *fbwin = (*it)->fbwindow(); 112 FocusedWindows::iterator it_end = window_list->end();
112 if (fbwin && !fbwin->isIconic() && 113
113 (fbwin->isStuck() 114 while (true) {
114 || fbwin->workspaceNumber() == m_screen.currentWorkspaceID())) { 115 if (cycle_reverse && it == it_begin)
115 // either on this workspace, or stuck 116 it = it_end;
116 117 cycle_reverse ? --it : ++it;
117 // keep track of the originally selected window in a set 118 if (it == it_end)
118 WinClient &last_client = fbwin->winClient(); 119 it = it_begin;
119 120 // give up [do nothing] if we reach the current focused again
121 if ((*it) == (*m_cycling_window))
122 break;
120 123
121 if (! (doSkipWindow(**it, opts) || !fbwin->setCurrentClient(**it)) ) { 124 FluxboxWindow *fbwin = (*it)->fbwindow();
122 // moved onto a new fbwin 125 if (fbwin && !fbwin->isIconic() &&
123 if (!m_cycling_last || m_cycling_last->fbwindow() != fbwin) { 126 (fbwin->isStuck()
124 if (m_cycling_last) { 127 || fbwin->workspaceNumber() == m_screen.currentWorkspaceID())) {
125 // set back to orig current Client in that fbwin 128 // either on this workspace, or stuck
126 m_cycling_last->fbwindow()->setCurrentClient(*m_cycling_last, false); 129
127 } 130 // keep track of the originally selected window in a set
128 m_cycling_last = &last_client; 131 WinClient &last_client = fbwin->winClient();
132
133 if (! (doSkipWindow(**it, opts) || !fbwin->setCurrentClient(**it)) ) {
134 // moved onto a new fbwin
135 if (!m_cycling_last || m_cycling_last->fbwindow() != fbwin) {
136 if (m_cycling_last) {
137 // set back to orig current Client in that fbwin
138 m_cycling_last->fbwindow()->setCurrentClient(*m_cycling_last, false);
129 } 139 }
130 fbwin->tempRaise(); 140 m_cycling_last = &last_client;
131 break;
132 } 141 }
142 fbwin->tempRaise();
143 break;
133 } 144 }
134 } 145 }
135 m_cycling_window = it;
136 } else { // not stacked cycling
137
138 Workspace &wksp = *m_screen.currentWorkspace();
139 Workspace::Windows &wins = wksp.windowList();
140 Workspace::Windows::iterator it = wins.begin();
141
142 FluxboxWindow *focused_group = 0;
143 // start from the focused window
144 bool have_focused = false;
145 WinClient *focused = focusedWindow();
146 if (focused != 0) {
147 if (focused->screen().screenNumber() == m_screen.screenNumber()) {
148 have_focused = true;
149 focused_group = focused->fbwindow();
150 }
151 }
152
153 if (!have_focused) {
154 focused_group = (*it);
155 } else {
156 //get focused window iterator
157 for (; it != wins.end() && (*it) != focused_group; ++it)
158 continue;
159 }
160
161 do {
162 if (it == wins.begin())
163 it = wins.end();
164 --it;
165 // see if the window should be skipped
166 if (! (doSkipWindow((*it)->winClient(), opts) || !(*it)->setInputFocus()) )
167 break;
168 } while ((*it) != focused_group);
169
170 if ((*it) != focused_group && it != wins.end())
171 (*it)->raise();
172 } 146 }
173 147 m_cycling_window = it;
174} 148}
175 149
176void FocusControl::addFocusFront(WinClient &client) { 150void FocusControl::addFocusFront(WinClient &client) {
177 m_focused_list.push_front(&client); 151 m_focused_list.push_front(&client);
152 m_creation_order_list.push_back(&client);
178} 153}
179 154
180void FocusControl::addFocusBack(WinClient &client) { 155void FocusControl::addFocusBack(WinClient &client) {
181 m_focused_list.push_back(&client); 156 m_focused_list.push_back(&client);
157 m_creation_order_list.push_back(&client);
182} 158}
183 159
184void FocusControl::stopCyclingFocus() { 160void FocusControl::stopCyclingFocus() {
@@ -191,7 +167,9 @@ void FocusControl::stopCyclingFocus() {
191 // put currently focused window to top 167 // put currently focused window to top
192 // the iterator may be invalid if the window died 168 // the iterator may be invalid if the window died
193 // in which case we'll do a proper revert focus 169 // in which case we'll do a proper revert focus
194 if (m_cycling_window != m_focused_list.end()) { 170 if (m_cycling_creation_order && m_cycling_window != m_creation_order_list.end())
171 m_cycling_window = find(m_focused_list.begin(),m_focused_list.end(),*m_cycling_window);
172 if (m_cycling_window != m_focused_list.end() && m_cycling_window != m_creation_order_list.end()) {
195 WinClient *client = *m_cycling_window; 173 WinClient *client = *m_cycling_window;
196 m_focused_list.erase(m_cycling_window); 174 m_focused_list.erase(m_cycling_window);
197 m_focused_list.push_front(client); 175 m_focused_list.push_front(client);
@@ -244,108 +222,6 @@ WinClient *FocusControl::lastFocusedWindow(FluxboxWindow &group, WinClient *igno
244 return 0; 222 return 0;
245} 223}
246 224
247void FocusControl::nextFocus(int opts) {
248 const int num_windows = m_screen.currentWorkspace()->numberOfWindows();
249
250 if (num_windows < 1)
251 return;
252
253 if (!(opts & CYCLELINEAR)) {
254 if (!m_cycling_focus) {
255 m_cycling_focus = true;
256 m_cycling_window = m_focused_list.begin();
257 m_cycling_last = 0;
258 } else {
259 // already cycling, so restack to put windows back in their proper order
260 m_screen.layerManager().restack();
261 }
262 // if it is stacked, we want the highest window in the focused list
263 // that is on the same workspace
264 FocusedWindows::iterator it = m_cycling_window;
265 const FocusedWindows::iterator it_end = m_focused_list.end();
266 int safety_counter = 0;
267 while (true) {
268 ++it;
269 if (it == it_end) {
270 it = m_focused_list.begin();
271 safety_counter++;
272 if (safety_counter > 3)
273 break;
274 }
275 // give up [do nothing] if we reach the current focused again
276 if ((*it) == (*m_cycling_window)) {
277 break;
278 }
279
280 FluxboxWindow *fbwin = (*it)->fbwindow();
281 if (fbwin && !fbwin->isIconic() &&
282 (fbwin->isStuck()
283 || fbwin->workspaceNumber() == m_screen.currentWorkspaceID())) {
284 // either on this workspace, or stuck
285
286 // keep track of the originally selected window in a set
287 WinClient &last_client = fbwin->winClient();
288
289 if (! (doSkipWindow(**it, opts) || !fbwin->setCurrentClient(**it)) ) {
290 // moved onto a new fbwin
291 if (!m_cycling_last || m_cycling_last->fbwindow() != fbwin) {
292 if (m_cycling_last) {
293 // set back to orig current Client in that fbwin
294 m_cycling_last->fbwindow()->setCurrentClient(*m_cycling_last, false);
295 }
296 m_cycling_last = &last_client;
297 }
298 fbwin->tempRaise();
299 break;
300 }
301 }
302 }
303 m_cycling_window = it;
304 } else { // not stacked cycling
305 // I really don't like this, but evidently some people use it(!)
306 Workspace &wksp = *m_screen.currentWorkspace();
307 Workspace::Windows &wins = wksp.windowList();
308 Workspace::Windows::iterator it = wins.begin();
309
310 FluxboxWindow *focused_group = 0;
311 // start from the focused window
312 bool have_focused = false;
313 WinClient *focused = focusedWindow();
314 if (focused != 0) {
315 if (focused->screen().screenNumber() == m_screen.screenNumber()) {
316 have_focused = true;
317 focused_group = focused->fbwindow();
318 }
319 }
320
321 if (!have_focused) {
322 focused_group = (*it);
323 } else {
324 // get focused window iterator
325 for (; it != wins.end() && (*it) != focused_group; ++it)
326 continue;
327 }
328
329 int safety_counter = 0;
330 do {
331 ++it;
332 if (it == wins.end()) {
333 it = wins.begin();
334 safety_counter++;
335 if (safety_counter > 3)
336 break;
337 }
338 // see if the window should be skipped
339 if (! (doSkipWindow((*it)->winClient(), opts) || !(*it)->setInputFocus()) )
340 break;
341 } while ((*it) != focused_group);
342
343 if ((*it) != focused_group && it != wins.end())
344 (*it)->raise();
345 }
346
347}
348
349void FocusControl::raiseFocus() { 225void FocusControl::raiseFocus() {
350 bool have_focused = false; 226 bool have_focused = false;
351 227
@@ -483,17 +359,14 @@ void FocusControl::dirFocus(FluxboxWindow &win, FocusDir dir) {
483 359
484void FocusControl::removeClient(WinClient &client) { 360void FocusControl::removeClient(WinClient &client) {
485 WinClient *cyc = 0; 361 WinClient *cyc = 0;
486 if (m_cycling_window != m_focused_list.end()) 362 if (m_cycling_window != m_focused_list.end() && m_cycling_window != m_creation_order_list.end())
487 cyc = *m_cycling_window; 363 cyc = *m_cycling_window;
488 364
489 m_focused_list.remove(&client); 365 m_focused_list.remove(&client);
366 m_creation_order_list.remove(&client);
490 367
491 if (cyc == &client) { 368 if (cyc == &client)
492 m_cycling_window = m_focused_list.end(); 369 stopCyclingFocus();
493 }
494
495 if (m_cycling_last == &client)
496 m_cycling_last = 0;
497 370
498} 371}
499 372
diff --git a/src/FocusControl.hh b/src/FocusControl.hh
index 65363dd..fd8f56d 100644
--- a/src/FocusControl.hh
+++ b/src/FocusControl.hh
@@ -67,10 +67,11 @@ public:
67 67
68 explicit FocusControl(BScreen &screen); 68 explicit FocusControl(BScreen &screen);
69 69
70 void prevFocus() { prevFocus(0); } 70 void prevFocus() { cycleFocus(0, true); }
71 void nextFocus() { nextFocus(0); } 71 void nextFocus() { cycleFocus(0, false); }
72 void prevFocus(int options); 72 void prevFocus(int options) { cycleFocus(options, true); }
73 void nextFocus(int options); 73 void nextFocus(int options) { cycleFocus(options, false); }
74 void cycleFocus(int options, bool cycle_reverse);
74 void raiseFocus(); 75 void raiseFocus();
75 76
76 void setScreenFocusedWindow(WinClient &win_client); 77 void setScreenFocusedWindow(WinClient &win_client);
@@ -112,8 +113,10 @@ private:
112 // This list keeps the order of window focusing for this screen 113 // This list keeps the order of window focusing for this screen
113 // Screen global so it works for sticky windows too. 114 // Screen global so it works for sticky windows too.
114 FocusedWindows m_focused_list; 115 FocusedWindows m_focused_list;
116 FocusedWindows m_creation_order_list;
115 FocusedWindows::iterator m_cycling_window; 117 FocusedWindows::iterator m_cycling_window;
116 bool m_cycling_focus; 118 bool m_cycling_focus;
119 bool m_cycling_creation_order;
117 WinClient *m_cycling_last; 120 WinClient *m_cycling_last;
118 121
119 static WinClient *s_focused_window; 122 static WinClient *s_focused_window;