diff options
Diffstat (limited to 'src/FocusControl.cc')
-rw-r--r-- | src/FocusControl.cc | 117 |
1 files changed, 90 insertions, 27 deletions
diff --git a/src/FocusControl.cc b/src/FocusControl.cc index 2314f33..e653e22 100644 --- a/src/FocusControl.cc +++ b/src/FocusControl.cc | |||
@@ -60,18 +60,16 @@ FocusControl::FocusControl(BScreen &screen): | |||
60 | m_was_iconic(false), | 60 | m_was_iconic(false), |
61 | m_cycling_last(0) { | 61 | m_cycling_last(0) { |
62 | 62 | ||
63 | m_cycling_window = m_focused_list.end(); | 63 | m_cycling_window = m_focused_win_list.end(); |
64 | 64 | ||
65 | } | 65 | } |
66 | 66 | ||
67 | // true if the windows should be skiped else false | 67 | // true if the windows should be skiped else false |
68 | bool doSkipWindow(const WinClient &winclient, int opts) { | 68 | bool doSkipWindow(const Focusable &winclient, int opts) { |
69 | const FluxboxWindow *win = winclient.fbwindow(); | 69 | const FluxboxWindow *win = winclient.fbwindow(); |
70 | return (!win || | 70 | return (!win || |
71 | // skip if stuck | 71 | // skip if stuck |
72 | (opts & FocusControl::CYCLESKIPSTUCK) != 0 && win->isStuck() || | 72 | (opts & FocusControl::CYCLESKIPSTUCK) != 0 && win->isStuck() || |
73 | // skip if not active client (i.e. only visit each fbwin once) | ||
74 | (opts & FocusControl::CYCLEGROUPS) != 0 && win->winClient().window() != winclient.window() || | ||
75 | // skip if shaded | 73 | // skip if shaded |
76 | (opts & FocusControl::CYCLESKIPSHADED) != 0 && win->isShaded() || | 74 | (opts & FocusControl::CYCLESKIPSHADED) != 0 && win->isShaded() || |
77 | // skip if iconic | 75 | // skip if iconic |
@@ -82,6 +80,15 @@ bool doSkipWindow(const WinClient &winclient, int opts) { | |||
82 | } | 80 | } |
83 | 81 | ||
84 | void FocusControl::cycleFocus(FocusedWindows *window_list, int opts, bool cycle_reverse) { | 82 | void FocusControl::cycleFocus(FocusedWindows *window_list, int opts, bool cycle_reverse) { |
83 | Focusables tmp_list; | ||
84 | FocusedWindows::iterator it = window_list->begin(); | ||
85 | FocusedWindows::iterator it_end = window_list->end(); | ||
86 | for (; it != it_end; ++it) | ||
87 | tmp_list.push_back(*it); | ||
88 | cycleFocus(&tmp_list, opts, cycle_reverse); | ||
89 | } | ||
90 | |||
91 | void FocusControl::cycleFocus(Focusables *window_list, int opts, bool cycle_reverse) { | ||
85 | 92 | ||
86 | if (!m_cycling_list) { | 93 | if (!m_cycling_list) { |
87 | if (&m_screen == FbTk::EventManager::instance()->grabbingKeyboard()) | 94 | if (&m_screen == FbTk::EventManager::instance()->grabbingKeyboard()) |
@@ -92,12 +99,15 @@ void FocusControl::cycleFocus(FocusedWindows *window_list, int opts, bool cycle_ | |||
92 | } else if (m_cycling_list != window_list) | 99 | } else if (m_cycling_list != window_list) |
93 | m_cycling_list = window_list; | 100 | m_cycling_list = window_list; |
94 | 101 | ||
102 | Focusables::iterator it_begin = window_list->begin(); | ||
103 | Focusables::iterator it_end = window_list->end(); | ||
104 | |||
95 | // too many things can go wrong with remembering this | 105 | // too many things can go wrong with remembering this |
96 | m_cycling_window = find(window_list->begin(),window_list->end(),s_focused_window); | 106 | m_cycling_window = find(it_begin, it_end, s_focused_window); |
107 | if (m_cycling_window == it_end) | ||
108 | m_cycling_window = find(it_begin, it_end, s_focused_fbwindow); | ||
97 | 109 | ||
98 | FocusedWindows::iterator it = m_cycling_window; | 110 | Focusables::iterator it = m_cycling_window; |
99 | FocusedWindows::iterator it_begin = window_list->begin(); | ||
100 | FocusedWindows::iterator it_end = window_list->end(); | ||
101 | 111 | ||
102 | // find the next window in the list that works | 112 | // find the next window in the list that works |
103 | while (true) { | 113 | while (true) { |
@@ -121,7 +131,7 @@ void FocusControl::cycleFocus(FocusedWindows *window_list, int opts, bool cycle_ | |||
121 | // keep track of the originally selected window in a set | 131 | // keep track of the originally selected window in a set |
122 | WinClient &last_client = fbwin->winClient(); | 132 | WinClient &last_client = fbwin->winClient(); |
123 | 133 | ||
124 | if (! (doSkipWindow(**it, opts) || !fbwin->setCurrentClient(**it)) ) { | 134 | if (! (doSkipWindow(**it, opts) || !(*it)->focus()) ) { |
125 | // moved onto a new fbwin | 135 | // moved onto a new fbwin |
126 | if (!m_cycling_last || m_cycling_last->fbwindow() != fbwin) { | 136 | if (!m_cycling_last || m_cycling_last->fbwindow() != fbwin) { |
127 | if (m_cycling_last) { | 137 | if (m_cycling_last) { |
@@ -151,6 +161,38 @@ void FocusControl::cycleFocus(FocusedWindows *window_list, int opts, bool cycle_ | |||
151 | m_cycling_window = it; | 161 | m_cycling_window = it; |
152 | } | 162 | } |
153 | 163 | ||
164 | void FocusControl::goToWindowNumber(Focusables *winlist, int num, int options) { | ||
165 | if (num > 0 && winlist) { | ||
166 | Focusables::iterator it = winlist->begin(); | ||
167 | Focusables::iterator it_end = winlist->end(); | ||
168 | for (; it != it_end; ++it) { | ||
169 | if (!doSkipWindow(**it, options) && (*it)->acceptsFocus()) { | ||
170 | --num; | ||
171 | if (!num) { | ||
172 | if ((*it)->fbwindow() && (*it)->fbwindow()->isIconic()) | ||
173 | (*it)->fbwindow()->deiconify(); | ||
174 | (*it)->focus(); | ||
175 | return; | ||
176 | } | ||
177 | } | ||
178 | } | ||
179 | } else if (num < 0 && winlist) { | ||
180 | Focusables::reverse_iterator it = winlist->rbegin(); | ||
181 | Focusables::reverse_iterator it_end = winlist->rend(); | ||
182 | for (; it != it_end; ++it) { | ||
183 | if (!doSkipWindow(**it, options) && (*it)->acceptsFocus()) { | ||
184 | ++num; | ||
185 | if (!num) { | ||
186 | if ((*it)->fbwindow() && (*it)->fbwindow()->isIconic()) | ||
187 | (*it)->fbwindow()->deiconify(); | ||
188 | (*it)->focus(); | ||
189 | return; | ||
190 | } | ||
191 | } | ||
192 | } | ||
193 | } | ||
194 | } | ||
195 | |||
154 | void FocusControl::addFocusBack(WinClient &client) { | 196 | void FocusControl::addFocusBack(WinClient &client) { |
155 | m_focused_list.push_back(&client); | 197 | m_focused_list.push_back(&client); |
156 | m_creation_order_list.push_back(&client); | 198 | m_creation_order_list.push_back(&client); |
@@ -161,6 +203,16 @@ void FocusControl::addFocusFront(WinClient &client) { | |||
161 | m_creation_order_list.push_back(&client); | 203 | m_creation_order_list.push_back(&client); |
162 | } | 204 | } |
163 | 205 | ||
206 | void FocusControl::addFocusWinBack(Focusable &win) { | ||
207 | m_focused_win_list.push_back(&win); | ||
208 | m_creation_order_win_list.push_back(&win); | ||
209 | } | ||
210 | |||
211 | void FocusControl::addFocusWinFront(Focusable &win) { | ||
212 | m_focused_win_list.push_front(&win); | ||
213 | m_creation_order_win_list.push_back(&win); | ||
214 | } | ||
215 | |||
164 | // move all clients in given window to back of focused list | 216 | // move all clients in given window to back of focused list |
165 | void FocusControl::setFocusBack(FluxboxWindow *fbwin) { | 217 | void FocusControl::setFocusBack(FluxboxWindow *fbwin) { |
166 | // do nothing if there are no windows open | 218 | // do nothing if there are no windows open |
@@ -168,9 +220,9 @@ void FocusControl::setFocusBack(FluxboxWindow *fbwin) { | |||
168 | if (m_focused_list.empty() || s_reverting) | 220 | if (m_focused_list.empty() || s_reverting) |
169 | return; | 221 | return; |
170 | 222 | ||
171 | FocusedWindows::iterator it = m_focused_list.begin(); | 223 | Focusables::iterator it = m_focused_list.begin(); |
172 | // use back to avoid an infinite loop | 224 | // use back to avoid an infinite loop |
173 | FocusedWindows::iterator it_back = --m_focused_list.end(); | 225 | Focusables::iterator it_back = --m_focused_list.end(); |
174 | 226 | ||
175 | while (it != it_back) { | 227 | while (it != it_back) { |
176 | if ((*it)->fbwindow() == fbwin) { | 228 | if ((*it)->fbwindow() == fbwin) { |
@@ -184,6 +236,10 @@ void FocusControl::setFocusBack(FluxboxWindow *fbwin) { | |||
184 | m_focused_list.push_back(*it); | 236 | m_focused_list.push_back(*it); |
185 | m_focused_list.erase(it); | 237 | m_focused_list.erase(it); |
186 | } | 238 | } |
239 | |||
240 | m_focused_win_list.remove(fbwin); | ||
241 | m_focused_win_list.push_back(fbwin); | ||
242 | |||
187 | } | 243 | } |
188 | 244 | ||
189 | void FocusControl::stopCyclingFocus() { | 245 | void FocusControl::stopCyclingFocus() { |
@@ -191,7 +247,7 @@ void FocusControl::stopCyclingFocus() { | |||
191 | if (m_cycling_list == 0) | 247 | if (m_cycling_list == 0) |
192 | return; | 248 | return; |
193 | 249 | ||
194 | FocusedWindows::iterator it_end = m_cycling_list->end(); | 250 | Focusables::iterator it_end = m_cycling_list->end(); |
195 | m_cycling_last = 0; | 251 | m_cycling_last = 0; |
196 | m_cycling_list = 0; | 252 | m_cycling_list = 0; |
197 | 253 | ||
@@ -200,10 +256,9 @@ void FocusControl::stopCyclingFocus() { | |||
200 | // in which case we'll do a proper revert focus | 256 | // in which case we'll do a proper revert focus |
201 | if (m_cycling_window != it_end && (*m_cycling_window)->fbwindow() && | 257 | if (m_cycling_window != it_end && (*m_cycling_window)->fbwindow() && |
202 | (*m_cycling_window)->fbwindow()->isVisible()) { | 258 | (*m_cycling_window)->fbwindow()->isVisible()) { |
203 | WinClient *client = *m_cycling_window; | 259 | (*m_cycling_window)->fbwindow()->raise(); |
204 | m_focused_list.remove(client); | 260 | if (s_focused_window) |
205 | m_focused_list.push_front(client); | 261 | setScreenFocusedWindow(*s_focused_window); |
206 | client->fbwindow()->raise(); | ||
207 | } else | 262 | } else |
208 | revertFocus(m_screen); | 263 | revertFocus(m_screen); |
209 | } | 264 | } |
@@ -213,13 +268,13 @@ void FocusControl::stopCyclingFocus() { | |||
213 | * If workspace is outside the ID range, then the absolute last focused window | 268 | * If workspace is outside the ID range, then the absolute last focused window |
214 | * is given. | 269 | * is given. |
215 | */ | 270 | */ |
216 | WinClient *FocusControl::lastFocusedWindow(int workspace) { | 271 | Focusable *FocusControl::lastFocusedWindow(int workspace) { |
217 | if (m_focused_list.empty()) return 0; | 272 | if (m_focused_list.empty()) return 0; |
218 | if (workspace < 0 || workspace >= (int) m_screen.numberOfWorkspaces()) | 273 | if (workspace < 0 || workspace >= (int) m_screen.numberOfWorkspaces()) |
219 | return m_focused_list.front(); | 274 | return m_focused_list.front(); |
220 | 275 | ||
221 | FocusedWindows::iterator it = m_focused_list.begin(); | 276 | Focusables::iterator it = m_focused_win_list.begin(); |
222 | FocusedWindows::iterator it_end = m_focused_list.end(); | 277 | Focusables::iterator it_end = m_focused_win_list.end(); |
223 | for (; it != it_end; ++it) { | 278 | for (; it != it_end; ++it) { |
224 | if ((*it)->fbwindow() && | 279 | if ((*it)->fbwindow() && |
225 | ((((int)(*it)->fbwindow()->workspaceNumber()) == workspace || | 280 | ((((int)(*it)->fbwindow()->workspaceNumber()) == workspace || |
@@ -238,12 +293,12 @@ WinClient *FocusControl::lastFocusedWindow(int workspace) { | |||
238 | WinClient *FocusControl::lastFocusedWindow(FluxboxWindow &group, WinClient *ignore_client) { | 293 | WinClient *FocusControl::lastFocusedWindow(FluxboxWindow &group, WinClient *ignore_client) { |
239 | if (m_focused_list.empty()) return 0; | 294 | if (m_focused_list.empty()) return 0; |
240 | 295 | ||
241 | FocusedWindows::iterator it = m_focused_list.begin(); | 296 | Focusables::iterator it = m_focused_list.begin(); |
242 | FocusedWindows::iterator it_end = m_focused_list.end(); | 297 | Focusables::iterator it_end = m_focused_list.end(); |
243 | for (; it != it_end; ++it) { | 298 | for (; it != it_end; ++it) { |
244 | if (((*it)->fbwindow() == &group) && | 299 | if (((*it)->fbwindow() == &group) && |
245 | (*it) != ignore_client) | 300 | (*it) != ignore_client) |
246 | return *it; | 301 | return dynamic_cast<WinClient *>(*it); |
247 | } | 302 | } |
248 | return 0; | 303 | return 0; |
249 | } | 304 | } |
@@ -257,6 +312,8 @@ void FocusControl::setScreenFocusedWindow(WinClient &win_client) { | |||
257 | !Fluxbox::instance()->isStartup()) { | 312 | !Fluxbox::instance()->isStartup()) { |
258 | m_focused_list.remove(&win_client); | 313 | m_focused_list.remove(&win_client); |
259 | m_focused_list.push_front(&win_client); | 314 | m_focused_list.push_front(&win_client); |
315 | m_focused_win_list.remove(win_client.fbwindow()); | ||
316 | m_focused_win_list.push_front(win_client.fbwindow()); | ||
260 | } | 317 | } |
261 | } | 318 | } |
262 | 319 | ||
@@ -371,7 +428,7 @@ void FocusControl::removeClient(WinClient &client) { | |||
371 | if (client.screen().isShuttingdown()) | 428 | if (client.screen().isShuttingdown()) |
372 | return; | 429 | return; |
373 | 430 | ||
374 | WinClient *cyc = 0; | 431 | Focusable *cyc = 0; |
375 | if (m_cycling_list && m_cycling_window != m_cycling_list->end()) | 432 | if (m_cycling_list && m_cycling_window != m_cycling_list->end()) |
376 | cyc = *m_cycling_window; | 433 | cyc = *m_cycling_window; |
377 | 434 | ||
@@ -384,12 +441,18 @@ void FocusControl::removeClient(WinClient &client) { | |||
384 | } | 441 | } |
385 | } | 442 | } |
386 | 443 | ||
444 | void FocusControl::removeWindow(Focusable &win) { | ||
445 | m_focused_win_list.remove(&win); | ||
446 | m_creation_order_win_list.remove(&win); | ||
447 | } | ||
448 | |||
387 | void FocusControl::shutdown() { | 449 | void FocusControl::shutdown() { |
388 | // restore windows backwards so they get put back correctly on restart | 450 | // restore windows backwards so they get put back correctly on restart |
389 | FocusedWindows::reverse_iterator it = m_focused_list.rbegin(); | 451 | Focusables::reverse_iterator it = m_focused_list.rbegin(); |
390 | for (; it != m_focused_list.rend(); ++it) { | 452 | for (; it != m_focused_list.rend(); ++it) { |
391 | if (*it && (*it)->fbwindow()) | 453 | WinClient *client = dynamic_cast<WinClient *>(*it); |
392 | (*it)->fbwindow()->restore(*it, true); | 454 | if (client && client->fbwindow()) |
455 | client->fbwindow()->restore(client, true); | ||
393 | } | 456 | } |
394 | } | 457 | } |
395 | 458 | ||
@@ -406,7 +469,7 @@ void FocusControl::revertFocus(BScreen &screen) { | |||
406 | 469 | ||
407 | FocusControl::s_reverting = true; | 470 | FocusControl::s_reverting = true; |
408 | 471 | ||
409 | WinClient *next_focus = | 472 | Focusable *next_focus = |
410 | screen.focusControl().lastFocusedWindow(screen.currentWorkspaceID()); | 473 | screen.focusControl().lastFocusedWindow(screen.currentWorkspaceID()); |
411 | 474 | ||
412 | // if setting focus fails, or isn't possible, fallback correctly | 475 | // if setting focus fails, or isn't possible, fallback correctly |