diff options
Diffstat (limited to 'src/Workspace.cc')
-rw-r--r-- | src/Workspace.cc | 240 |
1 files changed, 8 insertions, 232 deletions
diff --git a/src/Workspace.cc b/src/Workspace.cc index 2f575af..cce8dfe 100644 --- a/src/Workspace.cc +++ b/src/Workspace.cc | |||
@@ -30,13 +30,10 @@ | |||
30 | #include "Window.hh" | 30 | #include "Window.hh" |
31 | #include "WinClient.hh" | 31 | #include "WinClient.hh" |
32 | #include "FbWinFrame.hh" | 32 | #include "FbWinFrame.hh" |
33 | #include "WindowCmd.hh" | ||
34 | #include "FocusControl.hh" | 33 | #include "FocusControl.hh" |
35 | #include "PlacementStrategy.hh" | 34 | #include "PlacementStrategy.hh" |
36 | #include "Layer.hh" | ||
37 | 35 | ||
38 | #include "FbTk/I18n.hh" | 36 | #include "FbTk/I18n.hh" |
39 | #include "FbTk/MenuItem.hh" | ||
40 | #include "FbTk/StringUtil.hh" | 37 | #include "FbTk/StringUtil.hh" |
41 | #include "FbTk/FbString.hh" | 38 | #include "FbTk/FbString.hh" |
42 | 39 | ||
@@ -64,95 +61,18 @@ | |||
64 | #endif | 61 | #endif |
65 | 62 | ||
66 | #include <algorithm> | 63 | #include <algorithm> |
67 | #include <iostream> | ||
68 | #include <iterator> | ||
69 | 64 | ||
70 | using std::string; | 65 | using std::string; |
71 | using std::vector; | ||
72 | using std::ifstream; | ||
73 | 66 | ||
74 | #ifdef DEBUG | 67 | #ifdef DEBUG |
68 | #include <iostream> | ||
75 | using std::cerr; | 69 | using std::cerr; |
76 | using std::endl; | 70 | using std::endl; |
77 | #endif // DEBUG | 71 | #endif // DEBUG |
78 | 72 | ||
79 | namespace { // anonymous | 73 | Workspace::Workspace(BScreen &scrn, const string &name, unsigned int id): |
80 | |||
81 | int countTransients(const WinClient &client) { | ||
82 | if (client.transientList().empty()) | ||
83 | return 0; | ||
84 | // now go throu the entire tree and count transients | ||
85 | size_t ret = client.transientList().size(); | ||
86 | WinClient::TransientList::const_iterator it = client.transientList().begin(); | ||
87 | WinClient::TransientList::const_iterator it_end = client.transientList().end(); | ||
88 | for (; it != it_end; ++it) | ||
89 | ret += countTransients(*(*it)); | ||
90 | |||
91 | return ret; | ||
92 | } | ||
93 | |||
94 | class ClientMenuItem:public FbTk::MenuItem { | ||
95 | public: | ||
96 | ClientMenuItem(WinClient &client): | ||
97 | FbTk::MenuItem(client.title().c_str(), &client.screen().windowMenu()), | ||
98 | m_client(client) { | ||
99 | |||
100 | } | ||
101 | FbTk::Menu *submenu() { return &m_client.screen().windowMenu(); } | ||
102 | const FbTk::Menu *submenu() const { return &m_client.screen().windowMenu(); } | ||
103 | |||
104 | void showSubmenu() { | ||
105 | WindowCmd<void>::setClient(&m_client); | ||
106 | FbTk::MenuItem::showSubmenu(); | ||
107 | } | ||
108 | |||
109 | void click(int button, int time) { | ||
110 | if (m_client.fbwindow() == 0) | ||
111 | return; | ||
112 | FluxboxWindow &win = *m_client.fbwindow(); | ||
113 | |||
114 | if (win.screen().currentWorkspaceID() != win.workspaceNumber() && | ||
115 | !win.isStuck()) { | ||
116 | win.menu().hide(); | ||
117 | BScreen::FollowModel model = win.screen().getUserFollowModel(); | ||
118 | if (model == BScreen::IGNORE_OTHER_WORKSPACES) | ||
119 | return; | ||
120 | // fetch the window to the current workspace | ||
121 | else if ((button == 3) ^ (model == BScreen::FETCH_ACTIVE_WINDOW || | ||
122 | win.isIconic() && model == BScreen::SEMIFOLLOW_ACTIVE_WINDOW)) { | ||
123 | win.screen().sendToWorkspace(win.screen().currentWorkspaceID(), &win, true); | ||
124 | return; | ||
125 | } | ||
126 | // warp to the workspace of the window | ||
127 | win.screen().changeWorkspaceID(win.workspaceNumber()); | ||
128 | } | ||
129 | win.setCurrentClient(m_client); | ||
130 | win.raiseAndFocus(); | ||
131 | } | ||
132 | |||
133 | const string &label() const { return m_client.title(); } | ||
134 | bool isSelected() const { | ||
135 | if (m_client.fbwindow() == 0) | ||
136 | return false; | ||
137 | if (m_client.fbwindow()->isFocused() == false) | ||
138 | return false; | ||
139 | return (&(m_client.fbwindow()->winClient()) == &m_client); | ||
140 | |||
141 | } | ||
142 | private: | ||
143 | WinClient &m_client; | ||
144 | }; | ||
145 | |||
146 | }; | ||
147 | |||
148 | Workspace::GroupList Workspace::m_groups; | ||
149 | |||
150 | Workspace::Workspace(BScreen &scrn, FbTk::MultLayers &layermanager, | ||
151 | const string &name, unsigned int id): | ||
152 | m_screen(scrn), | 74 | m_screen(scrn), |
153 | m_clientmenu(scrn.menuTheme(), scrn.imageControl(), | 75 | m_clientmenu(scrn, m_windowlist, &m_clientlist_sig), |
154 | *scrn.layerManager().getLayer(Layer::MENU)), | ||
155 | m_layermanager(layermanager), | ||
156 | m_name(name), | 76 | m_name(name), |
157 | m_id(id) { | 77 | m_id(id) { |
158 | 78 | ||
@@ -171,23 +91,12 @@ void Workspace::addWindow(FluxboxWindow &w, bool place) { | |||
171 | return; | 91 | return; |
172 | 92 | ||
173 | w.setWorkspace(m_id); | 93 | w.setWorkspace(m_id); |
174 | // attach signals | ||
175 | w.titleSig().attach(this); | ||
176 | 94 | ||
177 | if (place) | 95 | if (place) |
178 | placeWindow(w); | 96 | placeWindow(w); |
179 | 97 | ||
180 | m_windowlist.push_back(&w); | 98 | m_windowlist.push_back(&w); |
181 | updateClientmenu(); | 99 | m_clientlist_sig.notify(); |
182 | |||
183 | if (!w.isStuck()) { | ||
184 | FluxboxWindow::ClientList::iterator client_it = | ||
185 | w.clientList().begin(); | ||
186 | FluxboxWindow::ClientList::iterator client_it_end = | ||
187 | w.clientList().end(); | ||
188 | for (; client_it != client_it_end; ++client_it) | ||
189 | screen().updateNetizenWindowAdd((*client_it)->window(), m_id); | ||
190 | } | ||
191 | 100 | ||
192 | } | 101 | } |
193 | 102 | ||
@@ -200,28 +109,11 @@ int Workspace::removeWindow(FluxboxWindow *w, bool still_alive) { | |||
200 | if (w == 0) | 109 | if (w == 0) |
201 | return -1; | 110 | return -1; |
202 | 111 | ||
203 | // detach from signals | ||
204 | w->titleSig().detach(this); | ||
205 | |||
206 | if (w->isFocused() && still_alive) | 112 | if (w->isFocused() && still_alive) |
207 | FocusControl::unfocusWindow(w->winClient(), true, true); | 113 | FocusControl::unfocusWindow(w->winClient(), true, true); |
208 | 114 | ||
209 | // we don't remove it from the layermanager, as it may be being moved | 115 | m_windowlist.remove(w); |
210 | Windows::iterator erase_it = remove(m_windowlist.begin(), | 116 | m_clientlist_sig.notify(); |
211 | m_windowlist.end(), w); | ||
212 | if (erase_it != m_windowlist.end()) | ||
213 | m_windowlist.erase(erase_it); | ||
214 | |||
215 | updateClientmenu(); | ||
216 | |||
217 | if (!w->isStuck()) { | ||
218 | FluxboxWindow::ClientList::iterator client_it = | ||
219 | w->clientList().begin(); | ||
220 | FluxboxWindow::ClientList::iterator client_it_end = | ||
221 | w->clientList().end(); | ||
222 | for (; client_it != client_it_end; ++client_it) | ||
223 | screen().updateNetizenWindowDel((*client_it)->window()); | ||
224 | } | ||
225 | 117 | ||
226 | return m_windowlist.size(); | 118 | return m_windowlist.size(); |
227 | } | 119 | } |
@@ -239,7 +131,7 @@ void Workspace::hideAll(bool interrupt_moving) { | |||
239 | Windows::reverse_iterator it_end = m_windowlist.rend(); | 131 | Windows::reverse_iterator it_end = m_windowlist.rend(); |
240 | for (; it != it_end; ++it) { | 132 | for (; it != it_end; ++it) { |
241 | if (! (*it)->isStuck()) | 133 | if (! (*it)->isStuck()) |
242 | (*it)->withdraw(interrupt_moving); | 134 | (*it)->hide(interrupt_moving); |
243 | } | 135 | } |
244 | } | 136 | } |
245 | 137 | ||
@@ -268,107 +160,6 @@ size_t Workspace::numberOfWindows() const { | |||
268 | return m_windowlist.size(); | 160 | return m_windowlist.size(); |
269 | } | 161 | } |
270 | 162 | ||
271 | namespace { | ||
272 | // helper class for checkGrouping | ||
273 | class FindInGroup { | ||
274 | public: | ||
275 | FindInGroup(const FluxboxWindow &w):m_w(w) { } | ||
276 | bool operator ()(const string &name) const { | ||
277 | return (name == m_w.winClient().getWMClassName()); | ||
278 | } | ||
279 | private: | ||
280 | const FluxboxWindow &m_w; | ||
281 | }; | ||
282 | |||
283 | }; | ||
284 | |||
285 | //Note: this function doesn't check if the window is groupable | ||
286 | bool Workspace::checkGrouping(FluxboxWindow &win) { | ||
287 | if (win.numClients() == 0) | ||
288 | return false; | ||
289 | #ifdef DEBUG | ||
290 | cerr<<__FILE__<<"("<<__LINE__<<"): Checking grouping. ("<<win.title()<<")"<<endl; | ||
291 | #endif // DEBUG | ||
292 | if (!win.isGroupable()) { // make sure this window can hold a tab | ||
293 | #ifdef DEBUG | ||
294 | cerr<<__FILE__<<"("<<__LINE__<<"): window can't use a tab"<<endl; | ||
295 | #endif // DEBUG | ||
296 | return false; | ||
297 | } | ||
298 | |||
299 | string instance_name = win.winClient().getWMClassName(); | ||
300 | |||
301 | // go through every group and search for matching win instancename | ||
302 | GroupList::iterator g(m_groups.begin()); | ||
303 | GroupList::iterator g_end(m_groups.end()); | ||
304 | for (; g != g_end; ++g) { | ||
305 | Group::iterator name((*g).begin()); | ||
306 | Group::iterator name_end((*g).end()); | ||
307 | for (; name != name_end; ++name) { | ||
308 | |||
309 | if ((*name) != instance_name) | ||
310 | continue; | ||
311 | |||
312 | // find a window with the specific name | ||
313 | Windows::iterator wit(m_windowlist.begin()); | ||
314 | Windows::iterator wit_end(m_windowlist.end()); | ||
315 | for (; wit != wit_end; ++wit) { | ||
316 | #ifdef DEBUG | ||
317 | cerr<<__FILE__<<" check group with : "<<(*wit)->winClient().getWMClassName()<<endl; | ||
318 | #endif // DEBUG | ||
319 | if (find_if((*g).begin(), | ||
320 | (*g).end(), | ||
321 | FindInGroup(*(*wit))) != (*g).end()) { | ||
322 | // make sure the window is groupable | ||
323 | // and don't group with ourself | ||
324 | if ( !(*wit)->isGroupable() || (*wit)->winClient().fbwindow() == &win) | ||
325 | break; // try next name | ||
326 | #ifdef DEBUG | ||
327 | cerr<<__FILE__<<"("<<__FUNCTION__<<"): window ("<<*wit<<") attaching window ("<<&win<<")"<<endl; | ||
328 | #endif // DEBUG | ||
329 | WinClient &client = win.winClient(); | ||
330 | (*wit)->attachClient(client); | ||
331 | if (client.screen().focusControl().focusNew()) | ||
332 | (*wit)->setCurrentClient(client); | ||
333 | return true; // grouping done | ||
334 | |||
335 | } | ||
336 | |||
337 | } | ||
338 | |||
339 | } | ||
340 | |||
341 | } | ||
342 | |||
343 | return false; | ||
344 | } | ||
345 | |||
346 | bool Workspace::loadGroups(const string &filename) { | ||
347 | string real_filename = FbTk::StringUtil::expandFilename(filename); | ||
348 | FbTk::StringUtil::removeTrailingWhitespace(real_filename); | ||
349 | ifstream infile(real_filename.c_str()); | ||
350 | if (!infile) | ||
351 | return false; | ||
352 | |||
353 | m_groups.clear(); // erase old groups | ||
354 | |||
355 | // load new groups | ||
356 | while (!infile.eof()) { | ||
357 | string line; | ||
358 | vector<string> names; | ||
359 | getline(infile, line); | ||
360 | FbTk::StringUtil::stringtok(names, line); | ||
361 | m_groups.push_back(names); | ||
362 | } | ||
363 | |||
364 | return true; | ||
365 | } | ||
366 | |||
367 | void Workspace::update(FbTk::Subject *subj) { | ||
368 | updateClientmenu(); | ||
369 | } | ||
370 | |||
371 | |||
372 | void Workspace::setName(const string &name) { | 163 | void Workspace::setName(const string &name) { |
373 | if (!name.empty() && name != "") { | 164 | if (!name.empty() && name != "") { |
374 | if (name == m_name) | 165 | if (name == m_name) |
@@ -404,22 +195,7 @@ void Workspace::shutdown() { | |||
404 | } | 195 | } |
405 | 196 | ||
406 | void Workspace::updateClientmenu() { | 197 | void Workspace::updateClientmenu() { |
407 | // remove all items and then add them again | 198 | m_clientlist_sig.notify(); |
408 | menu().removeAll(); | ||
409 | // for each fluxboxwindow add every client in them to our clientlist | ||
410 | Windows::iterator win_it = m_windowlist.begin(); | ||
411 | Windows::iterator win_it_end = m_windowlist.end(); | ||
412 | for (; win_it != win_it_end; ++win_it) { | ||
413 | // add every client in this fluxboxwindow to menu | ||
414 | FluxboxWindow::ClientList::iterator client_it = | ||
415 | (*win_it)->clientList().begin(); | ||
416 | FluxboxWindow::ClientList::iterator client_it_end = | ||
417 | (*win_it)->clientList().end(); | ||
418 | for (; client_it != client_it_end; ++client_it) | ||
419 | menu().insert(new ClientMenuItem(*(*client_it))); | ||
420 | } | ||
421 | |||
422 | menu().updateMenu(); | ||
423 | } | 199 | } |
424 | 200 | ||
425 | void Workspace::placeWindow(FluxboxWindow &win) { | 201 | void Workspace::placeWindow(FluxboxWindow &win) { |