diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | doc/asciidoc/fluxbox.txt | 7 | ||||
-rw-r--r-- | src/Remember.cc | 77 | ||||
-rw-r--r-- | src/Remember.hh | 17 |
4 files changed, 73 insertions, 37 deletions
@@ -1,5 +1,14 @@ | |||
1 | (Format: Year/Month/Day) | 1 | (Format: Year/Month/Day) |
2 | Changes for 1.0rc3: | 2 | Changes for 1.0rc3: |
3 | *07/02/05: | ||
4 | * Made some changes to the way autogrouping in the apps file works (Mark) | ||
5 | - Introduced new syntax [group] (workspace) to group new windows only with | ||
6 | windows on the current workspace | ||
7 | - Fixed an unreported bug with grouping windows on multiple screens | ||
8 | - Groups are now associated with clients rather than windows, so they | ||
9 | will be more robust when attaching or detaching tabs and when restarting | ||
10 | fluxbox | ||
11 | Remember.cc/hh | ||
3 | *07/02/04: | 12 | *07/02/04: |
4 | * Layer wasn't set properly on remembered windows, and the layer menu | 13 | * Layer wasn't set properly on remembered windows, and the layer menu |
5 | wasn't getting updated properly, bugs #1535304, #1572683, #1646740 | 14 | wasn't getting updated properly, bugs #1535304, #1572683, #1646740 |
diff --git a/doc/asciidoc/fluxbox.txt b/doc/asciidoc/fluxbox.txt index 409163f..24e4bc0 100644 --- a/doc/asciidoc/fluxbox.txt +++ b/doc/asciidoc/fluxbox.txt | |||
@@ -1510,9 +1510,10 @@ If no `property' is specified, the name property is assumed. You can find out | |||
1510 | the value for these fields for a particular window by running xprop(1). | 1510 | the value for these fields for a particular window by running xprop(1). |
1511 | 1511 | ||
1512 | You can also place [group] tag around several [app] tags, with an [end] tag to | 1512 | You can also place [group] tag around several [app] tags, with an [end] tag to |
1513 | indicate the end of the group. You can also specify dimensions, positions, | 1513 | indicate the end of the group. If you place (workspace) after the [group] tag, a |
1514 | etc. for the group as for normal app entries. Here is a short example | 1514 | new window will only get grouped with other windows on the current workspace. |
1515 | of an `apps' file: | 1515 | You can also specify dimensions, positions, etc. for the group as for normal app |
1516 | entries. Here is a short example of an `apps' file: | ||
1516 | 1517 | ||
1517 | ......................................................... | 1518 | ......................................................... |
1518 | [startup] {xterm} | 1519 | [startup] {xterm} |
diff --git a/src/Remember.cc b/src/Remember.cc index 6db1f9c..62c0d18 100644 --- a/src/Remember.cc +++ b/src/Remember.cc | |||
@@ -230,9 +230,8 @@ bool handleStartupItem(const string &line, int offset) { | |||
230 | }; // end anonymous namespace | 230 | }; // end anonymous namespace |
231 | 231 | ||
232 | 232 | ||
233 | Application::Application(bool grouped) | 233 | Application::Application(int grouped) |
234 | : is_grouped(grouped), | 234 | : is_grouped(grouped) |
235 | group(0) | ||
236 | { | 235 | { |
237 | decostate_remember = | 236 | decostate_remember = |
238 | dimensions_remember = | 237 | dimensions_remember = |
@@ -312,7 +311,7 @@ Application* Remember::find(WinClient &winclient) { | |||
312 | 311 | ||
313 | Application * Remember::add(WinClient &winclient) { | 312 | Application * Remember::add(WinClient &winclient) { |
314 | ClientPattern *p = new ClientPattern(); | 313 | ClientPattern *p = new ClientPattern(); |
315 | Application *app = new Application(false); | 314 | Application *app = new Application(0); |
316 | 315 | ||
317 | // by default, we match against the WMClass of a window. | 316 | // by default, we match against the WMClass of a window. |
318 | string win_name = p->getProperty(ClientPattern::NAME, winclient); | 317 | string win_name = p->getProperty(ClientPattern::NAME, winclient); |
@@ -534,7 +533,7 @@ int Remember::parseApp(ifstream &file, Application &app, string *first_line) { | |||
534 | effectively moved into the new | 533 | effectively moved into the new |
535 | */ | 534 | */ |
536 | 535 | ||
537 | Application *Remember::findMatchingPatterns(ClientPattern *pat, Patterns *patlist, bool is_group) { | 536 | Application *Remember::findMatchingPatterns(ClientPattern *pat, Patterns *patlist, int is_group) { |
538 | Patterns::iterator it = patlist->begin(); | 537 | Patterns::iterator it = patlist->begin(); |
539 | Patterns::iterator it_end = patlist->end(); | 538 | Patterns::iterator it_end = patlist->end(); |
540 | for (; it != it_end; ++it) { | 539 | for (; it != it_end; ++it) { |
@@ -590,7 +589,7 @@ void Remember::reconfigure() { | |||
590 | if (!apps_file.eof()) { | 589 | if (!apps_file.eof()) { |
591 | string line; | 590 | string line; |
592 | int row = 0; | 591 | int row = 0; |
593 | bool in_group = false; | 592 | int in_group = 0; |
594 | list<ClientPattern *> grouped_pats; | 593 | list<ClientPattern *> grouped_pats; |
595 | while (getline(apps_file, line) && ! apps_file.eof()) { | 594 | while (getline(apps_file, line) && ! apps_file.eof()) { |
596 | row++; | 595 | row++; |
@@ -606,11 +605,11 @@ void Remember::reconfigure() { | |||
606 | 605 | ||
607 | if (pos > 0 && strcasecmp(key.c_str(), "app") == 0) { | 606 | if (pos > 0 && strcasecmp(key.c_str(), "app") == 0) { |
608 | ClientPattern *pat = new ClientPattern(line.c_str() + pos); | 607 | ClientPattern *pat = new ClientPattern(line.c_str() + pos); |
609 | if (!in_group) { | 608 | if (in_group == 0) { |
610 | if ((err = pat->error()) == 0) { | 609 | if ((err = pat->error()) == 0) { |
611 | Application *app = findMatchingPatterns(pat, old_pats, false); | 610 | Application *app = findMatchingPatterns(pat, old_pats, 0); |
612 | if (!app) | 611 | if (!app) |
613 | app = new Application(false); | 612 | app = new Application(0); |
614 | 613 | ||
615 | m_pats->push_back(make_pair(pat, app)); | 614 | m_pats->push_back(make_pair(pat, app)); |
616 | row += parseApp(apps_file, *app); | 615 | row += parseApp(apps_file, *app); |
@@ -629,7 +628,12 @@ void Remember::reconfigure() { | |||
629 | // save the item even if it was bad (aren't we nice) | 628 | // save the item even if it was bad (aren't we nice) |
630 | m_startups.push_back(line.substr(pos)); | 629 | m_startups.push_back(line.substr(pos)); |
631 | } else if (pos > 0 && strcasecmp(key.c_str(), "group") == 0) { | 630 | } else if (pos > 0 && strcasecmp(key.c_str(), "group") == 0) { |
632 | in_group = true; | 631 | in_group = Application::IS_GROUPED; |
632 | pos = FbTk::StringUtil::getStringBetween(key, | ||
633 | line.c_str() + pos, | ||
634 | '(', ')'); | ||
635 | if (pos > 0 && strcasecmp(key.c_str(), "workspace") == 0) | ||
636 | in_group |= Application::MATCH_WORKSPACE; | ||
633 | } else if (in_group) { | 637 | } else if (in_group) { |
634 | // otherwise assume that it is the start of the attributes | 638 | // otherwise assume that it is the start of the attributes |
635 | Application *app = 0; | 639 | Application *app = 0; |
@@ -637,12 +641,12 @@ void Remember::reconfigure() { | |||
637 | list<ClientPattern *>::iterator it = grouped_pats.begin(); | 641 | list<ClientPattern *>::iterator it = grouped_pats.begin(); |
638 | list<ClientPattern *>::iterator it_end = grouped_pats.end(); | 642 | list<ClientPattern *>::iterator it_end = grouped_pats.end(); |
639 | while (!app && it != it_end) { | 643 | while (!app && it != it_end) { |
640 | app = findMatchingPatterns(*it, old_pats, true); | 644 | app = findMatchingPatterns(*it, old_pats, in_group); |
641 | ++it; | 645 | ++it; |
642 | } | 646 | } |
643 | 647 | ||
644 | if (!app) | 648 | if (!app) |
645 | app = new Application(true); | 649 | app = new Application(in_group); |
646 | 650 | ||
647 | while (!grouped_pats.empty()) { | 651 | while (!grouped_pats.empty()) { |
648 | // associate all the patterns with this app | 652 | // associate all the patterns with this app |
@@ -656,7 +660,7 @@ void Remember::reconfigure() { | |||
656 | if (!(pos>0 && strcasecmp(key.c_str(), "end") == 0)) { | 660 | if (!(pos>0 && strcasecmp(key.c_str(), "end") == 0)) { |
657 | row += parseApp(apps_file, *app, &line); | 661 | row += parseApp(apps_file, *app, &line); |
658 | } | 662 | } |
659 | in_group = false; | 663 | in_group = 0; |
660 | } else | 664 | } else |
661 | cerr<<"Error in apps file on line "<<row<<"."<<endl; | 665 | cerr<<"Error in apps file on line "<<row<<"."<<endl; |
662 | 666 | ||
@@ -733,7 +737,11 @@ void Remember::save() { | |||
733 | continue; | 737 | continue; |
734 | grouped_apps.insert(&a); | 738 | grouped_apps.insert(&a); |
735 | // otherwise output this whole group | 739 | // otherwise output this whole group |
736 | apps_file << "[group]" << endl; | 740 | apps_file << "[group]"; |
741 | if (a.is_grouped & Application::MATCH_WORKSPACE) | ||
742 | apps_file << " (workspace)"; | ||
743 | apps_file << endl; | ||
744 | |||
737 | Patterns::iterator git = m_pats->begin(); | 745 | Patterns::iterator git = m_pats->begin(); |
738 | Patterns::iterator git_end = m_pats->end(); | 746 | Patterns::iterator git_end = m_pats->end(); |
739 | for (; git != git_end; git++) { | 747 | for (; git != git_end; git++) { |
@@ -1035,9 +1043,6 @@ void Remember::setupFrame(FluxboxWindow &win) { | |||
1035 | // first, set the options that aren't preserved as window properties on | 1043 | // first, set the options that aren't preserved as window properties on |
1036 | // restart, then return if fluxbox is restarting -- we want restart to | 1044 | // restart, then return if fluxbox is restarting -- we want restart to |
1037 | // disturb the current window state as little as possible | 1045 | // disturb the current window state as little as possible |
1038 | Window leftwin = winclient.getGroupLeftWindow(); | ||
1039 | if (app->is_grouped && app->group == 0 && leftwin == None) | ||
1040 | app->group = &win; | ||
1041 | 1046 | ||
1042 | if (app->focushiddenstate_remember) | 1047 | if (app->focushiddenstate_remember) |
1043 | win.setFocusHidden(app->focushiddenstate); | 1048 | win.setFocusHidden(app->focushiddenstate); |
@@ -1133,14 +1138,37 @@ void Remember::setupClient(WinClient &winclient) { | |||
1133 | if (app == 0) | 1138 | if (app == 0) |
1134 | return; // nothing to do | 1139 | return; // nothing to do |
1135 | 1140 | ||
1136 | if (winclient.fbwindow() == 0 && app->is_grouped && app->group) { | 1141 | FluxboxWindow *group; |
1137 | app->group->attachClient(winclient); | 1142 | if (winclient.fbwindow() == 0 && app->is_grouped && |
1143 | (group = findGroup(app, winclient.screen()))) { | ||
1144 | group->attachClient(winclient); | ||
1138 | if (app->jumpworkspace_remember && app->jumpworkspace) | 1145 | if (app->jumpworkspace_remember && app->jumpworkspace) |
1139 | // jump to window, not saved workspace | 1146 | // jump to window, not saved workspace |
1140 | winclient.screen().changeWorkspaceID(app->group->workspaceNumber()); | 1147 | winclient.screen().changeWorkspaceID(group->workspaceNumber()); |
1141 | } | 1148 | } |
1142 | } | 1149 | } |
1143 | 1150 | ||
1151 | FluxboxWindow *Remember::findGroup(Application *app, BScreen &screen) { | ||
1152 | if (!app || !app->is_grouped) | ||
1153 | return 0; | ||
1154 | |||
1155 | // find the first client associated with the app and return its fbwindow | ||
1156 | Clients::iterator it = m_clients.begin(); | ||
1157 | Clients::iterator it_end = m_clients.end(); | ||
1158 | for (; it != it_end; ++it) { | ||
1159 | if (it->second == app && it->first->fbwindow() && | ||
1160 | &screen == &it->first->screen() && | ||
1161 | (!(app->is_grouped & Application::MATCH_WORKSPACE) || | ||
1162 | it->first->fbwindow()->workspaceNumber() == | ||
1163 | screen.currentWorkspaceID())) | ||
1164 | |||
1165 | return it->first->fbwindow(); | ||
1166 | } | ||
1167 | |||
1168 | // there weren't any open, but that's ok | ||
1169 | return 0; | ||
1170 | } | ||
1171 | |||
1144 | void Remember::updateClientClose(WinClient &winclient) { | 1172 | void Remember::updateClientClose(WinClient &winclient) { |
1145 | reconfigure(); // reload if it's changed | 1173 | reconfigure(); // reload if it's changed |
1146 | Application *app = find(winclient); | 1174 | Application *app = find(winclient); |
@@ -1172,12 +1200,3 @@ void Remember::initForScreen(BScreen &screen) { | |||
1172 | createRememberMenu(screen)); | 1200 | createRememberMenu(screen)); |
1173 | 1201 | ||
1174 | } | 1202 | } |
1175 | |||
1176 | void Remember::updateFrameClose(FluxboxWindow &win) { | ||
1177 | // scan all applications and remove this fbw if it is a recorded group | ||
1178 | Patterns::iterator it = m_pats->begin(); | ||
1179 | for (; it != m_pats->end(); ++it) { | ||
1180 | if (&win == it->second->group) | ||
1181 | it->second->group = 0; | ||
1182 | } | ||
1183 | } | ||
diff --git a/src/Remember.hh b/src/Remember.hh index d78e226..581e525 100644 --- a/src/Remember.hh +++ b/src/Remember.hh | |||
@@ -44,7 +44,7 @@ class ClientPattern; | |||
44 | 44 | ||
45 | class Application { | 45 | class Application { |
46 | public: | 46 | public: |
47 | Application(bool grouped); | 47 | Application(int grouped); |
48 | inline void forgetWorkspace() { workspace_remember = false; } | 48 | inline void forgetWorkspace() { workspace_remember = false; } |
49 | inline void forgetHead() { head_remember = false; } | 49 | inline void forgetHead() { head_remember = false; } |
50 | inline void forgetDimensions() { dimensions_remember = false; } | 50 | inline void forgetDimensions() { dimensions_remember = false; } |
@@ -137,8 +137,14 @@ public: | |||
137 | bool save_on_close_remember; | 137 | bool save_on_close_remember; |
138 | bool save_on_close; | 138 | bool save_on_close; |
139 | 139 | ||
140 | bool is_grouped; | 140 | enum { |
141 | FluxboxWindow *group; | 141 | IS_GROUPED = 0x01, |
142 | MATCH_WORKSPACE = 0x02 | ||
143 | // MATCH_HEAD, STUCK, ICONIFIED, etc.? | ||
144 | // this will probably evolve into a ClientPattern as soon as they | ||
145 | // match things like currentworkspace | ||
146 | }; | ||
147 | int is_grouped; | ||
142 | 148 | ||
143 | }; | 149 | }; |
144 | 150 | ||
@@ -201,6 +207,7 @@ public: | |||
201 | 207 | ||
202 | Application* find(WinClient &winclient); | 208 | Application* find(WinClient &winclient); |
203 | Application* add(WinClient &winclient); | 209 | Application* add(WinClient &winclient); |
210 | FluxboxWindow* findGroup(Application *, BScreen &screen); | ||
204 | 211 | ||
205 | void reconfigure(); // was load | 212 | void reconfigure(); // was load |
206 | void save(); | 213 | void save(); |
@@ -214,7 +221,6 @@ public: | |||
214 | // Functions we actually use | 221 | // Functions we actually use |
215 | void setupFrame(FluxboxWindow &win); | 222 | void setupFrame(FluxboxWindow &win); |
216 | void setupClient(WinClient &winclient); | 223 | void setupClient(WinClient &winclient); |
217 | void updateFrameClose(FluxboxWindow &win); | ||
218 | void updateClientClose(WinClient &winclient); | 224 | void updateClientClose(WinClient &winclient); |
219 | 225 | ||
220 | void initForScreen(BScreen &screen); | 226 | void initForScreen(BScreen &screen); |
@@ -233,6 +239,7 @@ public: | |||
233 | void updateState(FluxboxWindow &win) {} | 239 | void updateState(FluxboxWindow &win) {} |
234 | void updateHints(FluxboxWindow &win) {} | 240 | void updateHints(FluxboxWindow &win) {} |
235 | void updateLayer(FluxboxWindow &win) {} | 241 | void updateLayer(FluxboxWindow &win) {} |
242 | void updateFrameClose(FluxboxWindow &win) {} | ||
236 | 243 | ||
237 | bool checkClientMessage(const XClientMessageEvent &ce, | 244 | bool checkClientMessage(const XClientMessageEvent &ce, |
238 | BScreen * screen, WinClient * const winclient) { return false; } | 245 | BScreen * screen, WinClient * const winclient) { return false; } |
@@ -247,7 +254,7 @@ private: | |||
247 | // optionally can give a line to read before the first (lookahead line) | 254 | // optionally can give a line to read before the first (lookahead line) |
248 | int parseApp(std::ifstream &file, Application &app, std::string *first_line = 0); | 255 | int parseApp(std::ifstream &file, Application &app, std::string *first_line = 0); |
249 | 256 | ||
250 | Application *findMatchingPatterns(ClientPattern *pat, Patterns *patlist, bool is_group); | 257 | Application *findMatchingPatterns(ClientPattern *pat, Patterns *patlist, int is_group); |
251 | 258 | ||
252 | std::auto_ptr<Patterns> m_pats; | 259 | std::auto_ptr<Patterns> m_pats; |
253 | Clients m_clients; | 260 | Clients m_clients; |