diff options
Diffstat (limited to 'src/FocusControl.cc')
-rw-r--r-- | src/FocusControl.cc | 146 |
1 files changed, 78 insertions, 68 deletions
diff --git a/src/FocusControl.cc b/src/FocusControl.cc index c5ee939..c97b699 100644 --- a/src/FocusControl.cc +++ b/src/FocusControl.cc | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | #include "FocusControl.hh" | 24 | #include "FocusControl.hh" |
25 | 25 | ||
26 | #include "ClientPattern.hh" | ||
26 | #include "Screen.hh" | 27 | #include "Screen.hh" |
27 | #include "Window.hh" | 28 | #include "Window.hh" |
28 | #include "WinClient.hh" | 29 | #include "WinClient.hh" |
@@ -43,6 +44,22 @@ WinClient *FocusControl::s_focused_window = 0; | |||
43 | FluxboxWindow *FocusControl::s_focused_fbwindow = 0; | 44 | FluxboxWindow *FocusControl::s_focused_fbwindow = 0; |
44 | bool FocusControl::s_reverting = false; | 45 | bool FocusControl::s_reverting = false; |
45 | 46 | ||
47 | namespace { | ||
48 | |||
49 | bool doSkipWindow(const Focusable &win, const ClientPattern *pat) { | ||
50 | const FluxboxWindow *fbwin = win.fbwindow(); | ||
51 | if (!fbwin || fbwin->isFocusHidden()) | ||
52 | return true; // skip if no fbwindow or if focushidden | ||
53 | if (pat && !pat->match(win)) | ||
54 | return true; // skip if it doesn't match the pattern | ||
55 | if (fbwin->workspaceNumber() != win.screen().currentWorkspaceID() && | ||
56 | !fbwin->isStuck()) | ||
57 | return true; // for now, we only cycle through the current workspace | ||
58 | return false; // else don't skip | ||
59 | } | ||
60 | |||
61 | }; // end anonymous namespace | ||
62 | |||
46 | FocusControl::FocusControl(BScreen &screen): | 63 | FocusControl::FocusControl(BScreen &screen): |
47 | m_screen(screen), | 64 | m_screen(screen), |
48 | m_focus_model(screen.resourceManager(), | 65 | m_focus_model(screen.resourceManager(), |
@@ -64,43 +81,30 @@ FocusControl::FocusControl(BScreen &screen): | |||
64 | 81 | ||
65 | } | 82 | } |
66 | 83 | ||
67 | // true if the windows should be skiped else false | 84 | void FocusControl::cycleFocus(FocusedWindows &window_list, |
68 | bool doSkipWindow(const Focusable &winclient, int opts) { | 85 | const ClientPattern *pat, bool cycle_reverse) { |
69 | const FluxboxWindow *win = winclient.fbwindow(); | ||
70 | return (!win || | ||
71 | // skip if stuck | ||
72 | (opts & FocusControl::CYCLESKIPSTUCK) != 0 && win->isStuck() || | ||
73 | // skip if shaded | ||
74 | (opts & FocusControl::CYCLESKIPSHADED) != 0 && win->isShaded() || | ||
75 | // skip if iconic | ||
76 | (opts & FocusControl::CYCLESKIPICONIC) != 0 && win->isIconic() || | ||
77 | // skip if hidden | ||
78 | win->isFocusHidden() | ||
79 | ); | ||
80 | } | ||
81 | |||
82 | void FocusControl::cycleFocus(FocusedWindows *window_list, int opts, bool cycle_reverse) { | ||
83 | Focusables tmp_list; | 86 | Focusables tmp_list; |
84 | FocusedWindows::iterator it = window_list->begin(); | 87 | FocusedWindows::iterator it = window_list.begin(); |
85 | FocusedWindows::iterator it_end = window_list->end(); | 88 | FocusedWindows::iterator it_end = window_list.end(); |
86 | for (; it != it_end; ++it) | 89 | for (; it != it_end; ++it) |
87 | tmp_list.push_back(*it); | 90 | tmp_list.push_back(*it); |
88 | cycleFocus(&tmp_list, opts, cycle_reverse); | 91 | cycleFocus(tmp_list, pat, cycle_reverse); |
89 | } | 92 | } |
90 | 93 | ||
91 | void FocusControl::cycleFocus(Focusables *window_list, int opts, bool cycle_reverse) { | 94 | void FocusControl::cycleFocus(Focusables &window_list, const ClientPattern *pat, |
95 | bool cycle_reverse) { | ||
92 | 96 | ||
93 | if (!m_cycling_list) { | 97 | if (!m_cycling_list) { |
94 | if (&m_screen == FbTk::EventManager::instance()->grabbingKeyboard()) | 98 | if (&m_screen == FbTk::EventManager::instance()->grabbingKeyboard()) |
95 | // only set this when we're waiting for modifiers | 99 | // only set this when we're waiting for modifiers |
96 | m_cycling_list = window_list; | 100 | m_cycling_list = &window_list; |
97 | m_was_iconic = 0; | 101 | m_was_iconic = 0; |
98 | m_cycling_last = 0; | 102 | m_cycling_last = 0; |
99 | } else if (m_cycling_list != window_list) | 103 | } else if (m_cycling_list != &window_list) |
100 | m_cycling_list = window_list; | 104 | m_cycling_list = &window_list; |
101 | 105 | ||
102 | Focusables::iterator it_begin = window_list->begin(); | 106 | Focusables::iterator it_begin = window_list.begin(); |
103 | Focusables::iterator it_end = window_list->end(); | 107 | Focusables::iterator it_end = window_list.end(); |
104 | 108 | ||
105 | // too many things can go wrong with remembering this | 109 | // too many things can go wrong with remembering this |
106 | m_cycling_window = find(it_begin, it_end, s_focused_window); | 110 | m_cycling_window = find(it_begin, it_end, s_focused_window); |
@@ -108,6 +112,8 @@ void FocusControl::cycleFocus(Focusables *window_list, int opts, bool cycle_reve | |||
108 | m_cycling_window = find(it_begin, it_end, s_focused_fbwindow); | 112 | m_cycling_window = find(it_begin, it_end, s_focused_fbwindow); |
109 | 113 | ||
110 | Focusables::iterator it = m_cycling_window; | 114 | Focusables::iterator it = m_cycling_window; |
115 | FluxboxWindow *fbwin = 0; | ||
116 | WinClient *last_client = 0; | ||
111 | 117 | ||
112 | // find the next window in the list that works | 118 | // find the next window in the list that works |
113 | while (true) { | 119 | while (true) { |
@@ -123,50 +129,54 @@ void FocusControl::cycleFocus(Focusables *window_list, int opts, bool cycle_reve | |||
123 | if (it == it_end) | 129 | if (it == it_end) |
124 | continue; | 130 | continue; |
125 | 131 | ||
126 | FluxboxWindow *fbwin = (*it)->fbwindow(); | 132 | fbwin = (*it)->fbwindow(); |
127 | if (fbwin && (fbwin->isStuck() | 133 | if (!fbwin) |
128 | || fbwin->workspaceNumber() == m_screen.currentWorkspaceID())) { | 134 | continue; |
129 | // either on this workspace, or stuck | 135 | |
130 | 136 | // keep track of the originally selected window in a group | |
131 | // keep track of the originally selected window in a set | 137 | last_client = &fbwin->winClient(); |
132 | WinClient &last_client = fbwin->winClient(); | 138 | |
133 | 139 | // now we actually try to focus the window | |
134 | if (! (doSkipWindow(**it, opts) || !(*it)->focus()) ) { | 140 | if (!doSkipWindow(**it, pat) && (*it)->focus()) |
135 | // moved onto a new fbwin | 141 | break; |
136 | if (!m_cycling_last || m_cycling_last->fbwindow() != fbwin) { | ||
137 | if (m_cycling_last) { | ||
138 | // already cycling, so restack to put windows back in | ||
139 | // their proper order | ||
140 | m_screen.layerManager().restack(); | ||
141 | |||
142 | // set back to orig current Client in that fbwin | ||
143 | m_cycling_last->fbwindow()->setCurrentClient(*m_cycling_last, false); | ||
144 | if (m_was_iconic == m_cycling_last) { | ||
145 | s_reverting = true; // little hack | ||
146 | m_cycling_last->fbwindow()->iconify(); | ||
147 | s_reverting = false; | ||
148 | } | ||
149 | } | ||
150 | m_cycling_last = &last_client; | ||
151 | if (fbwin->isIconic()) | ||
152 | m_was_iconic = m_cycling_last; | ||
153 | if (m_cycling_list) | ||
154 | // else window will raise itself (if desired) on FocusIn | ||
155 | fbwin->tempRaise(); | ||
156 | } | ||
157 | break; | ||
158 | } | ||
159 | } | ||
160 | } | 142 | } |
143 | |||
161 | m_cycling_window = it; | 144 | m_cycling_window = it; |
145 | |||
146 | // if we're still in the same fbwin, there's nothing else to do | ||
147 | if (m_cycling_last && m_cycling_last->fbwindow() == fbwin) | ||
148 | return; | ||
149 | |||
150 | // if we were already cycling, then restore the old state | ||
151 | if (m_cycling_last) { | ||
152 | m_screen.layerManager().restack(); | ||
153 | |||
154 | // set back to originally selected window in that group | ||
155 | m_cycling_last->fbwindow()->setCurrentClient(*m_cycling_last, false); | ||
156 | |||
157 | if (m_was_iconic == m_cycling_last) { | ||
158 | s_reverting = true; // little hack | ||
159 | m_cycling_last->fbwindow()->iconify(); | ||
160 | s_reverting = false; | ||
161 | } | ||
162 | } | ||
163 | |||
164 | m_cycling_last = last_client; | ||
165 | if (fbwin->isIconic()) | ||
166 | m_was_iconic = m_cycling_last; | ||
167 | if (m_cycling_list) | ||
168 | // else window will raise itself (if desired) on FocusIn | ||
169 | fbwin->tempRaise(); | ||
170 | |||
162 | } | 171 | } |
163 | 172 | ||
164 | void FocusControl::goToWindowNumber(Focusables *winlist, int num, int options) { | 173 | void FocusControl::goToWindowNumber(Focusables &winlist, int num, |
165 | if (num > 0 && winlist) { | 174 | const ClientPattern *pat) { |
166 | Focusables::iterator it = winlist->begin(); | 175 | if (num > 0) { |
167 | Focusables::iterator it_end = winlist->end(); | 176 | Focusables::iterator it = winlist.begin(); |
177 | Focusables::iterator it_end = winlist.end(); | ||
168 | for (; it != it_end; ++it) { | 178 | for (; it != it_end; ++it) { |
169 | if (!doSkipWindow(**it, options) && (*it)->acceptsFocus()) { | 179 | if (!doSkipWindow(**it, pat) && (*it)->acceptsFocus()) { |
170 | --num; | 180 | --num; |
171 | if (!num) { | 181 | if (!num) { |
172 | if ((*it)->fbwindow() && (*it)->fbwindow()->isIconic()) | 182 | if ((*it)->fbwindow() && (*it)->fbwindow()->isIconic()) |
@@ -176,11 +186,11 @@ void FocusControl::goToWindowNumber(Focusables *winlist, int num, int options) { | |||
176 | } | 186 | } |
177 | } | 187 | } |
178 | } | 188 | } |
179 | } else if (num < 0 && winlist) { | 189 | } else if (num < 0) { |
180 | Focusables::reverse_iterator it = winlist->rbegin(); | 190 | Focusables::reverse_iterator it = winlist.rbegin(); |
181 | Focusables::reverse_iterator it_end = winlist->rend(); | 191 | Focusables::reverse_iterator it_end = winlist.rend(); |
182 | for (; it != it_end; ++it) { | 192 | for (; it != it_end; ++it) { |
183 | if (!doSkipWindow(**it, options) && (*it)->acceptsFocus()) { | 193 | if (!doSkipWindow(**it, pat) && (*it)->acceptsFocus()) { |
184 | ++num; | 194 | ++num; |
185 | if (!num) { | 195 | if (!num) { |
186 | if ((*it)->fbwindow() && (*it)->fbwindow()->isIconic()) | 196 | if ((*it)->fbwindow() && (*it)->fbwindow()->isIconic()) |