aboutsummaryrefslogtreecommitdiff
path: root/src/FocusControl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/FocusControl.cc')
-rw-r--r--src/FocusControl.cc117
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
68bool doSkipWindow(const WinClient &winclient, int opts) { 68bool 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
84void FocusControl::cycleFocus(FocusedWindows *window_list, int opts, bool cycle_reverse) { 82void 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
91void 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
164void 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
154void FocusControl::addFocusBack(WinClient &client) { 196void 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
206void FocusControl::addFocusWinBack(Focusable &win) {
207 m_focused_win_list.push_back(&win);
208 m_creation_order_win_list.push_back(&win);
209}
210
211void 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
165void FocusControl::setFocusBack(FluxboxWindow *fbwin) { 217void 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
189void FocusControl::stopCyclingFocus() { 245void 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 */
216WinClient *FocusControl::lastFocusedWindow(int workspace) { 271Focusable *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) {
238WinClient *FocusControl::lastFocusedWindow(FluxboxWindow &group, WinClient *ignore_client) { 293WinClient *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
444void FocusControl::removeWindow(Focusable &win) {
445 m_focused_win_list.remove(&win);
446 m_creation_order_win_list.remove(&win);
447}
448
387void FocusControl::shutdown() { 449void 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