aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--doc/asciidoc/fluxbox.txt7
-rw-r--r--src/Remember.cc77
-rw-r--r--src/Remember.hh17
4 files changed, 73 insertions, 37 deletions
diff --git a/ChangeLog b/ChangeLog
index 328f320..4976b30 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
1 (Format: Year/Month/Day) 1 (Format: Year/Month/Day)
2Changes for 1.0rc3: 2Changes 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
1510the value for these fields for a particular window by running xprop(1). 1510the value for these fields for a particular window by running xprop(1).
1511 1511
1512You can also place [group] tag around several [app] tags, with an [end] tag to 1512You can also place [group] tag around several [app] tags, with an [end] tag to
1513indicate the end of the group. You can also specify dimensions, positions, 1513indicate the end of the group. If you place (workspace) after the [group] tag, a
1514etc. for the group as for normal app entries. Here is a short example 1514new window will only get grouped with other windows on the current workspace.
1515of an `apps' file: 1515You can also specify dimensions, positions, etc. for the group as for normal app
1516entries. 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
233Application::Application(bool grouped) 233Application::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
313Application * Remember::add(WinClient &winclient) { 312Application * 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
537Application *Remember::findMatchingPatterns(ClientPattern *pat, Patterns *patlist, bool is_group) { 536Application *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
1151FluxboxWindow *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
1144void Remember::updateClientClose(WinClient &winclient) { 1172void 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
1176void 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
45class Application { 45class Application {
46public: 46public:
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;