aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsimonb <simonb>2006-04-23 14:51:04 (GMT)
committersimonb <simonb>2006-04-23 14:51:04 (GMT)
commit53f869aa528c6fee86d382ff4cfe6dc1046093c7 (patch)
treed6713a1a23193cc47392147f3e0611db9960bee4
parent39cacd1da802e4aa2cd4fdeacf0cf2b436d87dfa (diff)
downloadfluxbox-53f869aa528c6fee86d382ff4cfe6dc1046093c7.zip
fluxbox-53f869aa528c6fee86d382ff4cfe6dc1046093c7.tar.bz2
reload the apps file on flux reload
-rw-r--r--ChangeLog2
-rw-r--r--src/AtomHandler.hh2
-rw-r--r--src/ClientPattern.cc16
-rw-r--r--src/ClientPattern.hh3
-rw-r--r--src/Remember.cc140
-rw-r--r--src/Remember.hh13
-rw-r--r--src/fluxbox.cc6
7 files changed, 159 insertions, 23 deletions
diff --git a/ChangeLog b/ChangeLog
index 1b3fd87..447196c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,8 @@
1(Format: Year/Month/Day) 1(Format: Year/Month/Day)
2Changes for 0.9.16: 2Changes for 0.9.16:
3*06/04/23: 3*06/04/23:
4 * Reload the apps file on fluxbox reload (Simon)
5 Remember.hh/cc fluxbox.cc AtomHandler.hh ClientPattern.hh/cc
4 * Update documentation for Next/PrevWindow (Simon / thanks Jonas 6 * Update documentation for Next/PrevWindow (Simon / thanks Jonas
5 Koelker), sf.net patch #1474825 7 Koelker), sf.net patch #1474825
6 doc/asciidoc/fluxbox.txt 8 doc/asciidoc/fluxbox.txt
diff --git a/src/AtomHandler.hh b/src/AtomHandler.hh
index ca14d0e..b44d92f 100644
--- a/src/AtomHandler.hh
+++ b/src/AtomHandler.hh
@@ -59,6 +59,8 @@ public:
59 59
60 virtual bool propertyNotify(WinClient &winclient, Atom the_property) = 0; 60 virtual bool propertyNotify(WinClient &winclient, Atom the_property) = 0;
61 61
62 virtual void reconfigure() {}
63
62 /// should this object be updated or not? 64 /// should this object be updated or not?
63 bool update() const { return m_update; } 65 bool update() const { return m_update; }
64protected: 66protected:
diff --git a/src/ClientPattern.cc b/src/ClientPattern.cc
index 38d1602..d9469fa 100644
--- a/src/ClientPattern.cc
+++ b/src/ClientPattern.cc
@@ -257,3 +257,19 @@ std::string ClientPattern::getProperty(WinProperty prop, const WinClient &client
257 } 257 }
258 return client.getWMClassName(); 258 return client.getWMClassName();
259} 259}
260
261bool ClientPattern::equals(const ClientPattern &pat) const {
262 // we require the terms to be identical (order too)
263 Terms::const_iterator it = m_terms.begin();
264 Terms::const_iterator it_end = m_terms.end();
265 Terms::const_iterator other_it = pat.m_terms.begin();
266 Terms::const_iterator other_it_end = pat.m_terms.end();
267 for (; it != it_end, other_it != other_it_end; ++it, ++other_it) {
268 if ((*it)->orig != (*other_it)->orig)
269 return false;
270 }
271 if (it != it_end || other_it != other_it_end)
272 return false;
273
274 return true;
275}
diff --git a/src/ClientPattern.hh b/src/ClientPattern.hh
index ee7ebc7..6db9c83 100644
--- a/src/ClientPattern.hh
+++ b/src/ClientPattern.hh
@@ -73,6 +73,9 @@ public:
73 return match(win); 73 return match(win);
74 } 74 }
75 75
76 // whether this pattern has identical matching criteria
77 bool equals(const ClientPattern &pat) const;
78
76 /** 79 /**
77 * If there are no terms, then there is assumed to be an error 80 * If there are no terms, then there is assumed to be an error
78 * the column of the error is stored in m_matchlimit 81 * the column of the error is stored in m_matchlimit
diff --git a/src/Remember.cc b/src/Remember.cc
index c134741..b90a252 100644
--- a/src/Remember.cc
+++ b/src/Remember.cc
@@ -36,6 +36,7 @@
36 36
37#include "FbTk/I18n.hh" 37#include "FbTk/I18n.hh"
38#include "FbTk/StringUtil.hh" 38#include "FbTk/StringUtil.hh"
39#include "FbTk/FileUtil.hh"
39#include "FbTk/MenuItem.hh" 40#include "FbTk/MenuItem.hh"
40#include "FbTk/App.hh" 41#include "FbTk/App.hh"
41#include "FbTk/stringstream.hh" 42#include "FbTk/stringstream.hh"
@@ -230,13 +231,16 @@ Application::Application(bool grouped)
230 231
231Remember *Remember::s_instance = 0; 232Remember *Remember::s_instance = 0;
232 233
233Remember::Remember() { 234Remember::Remember():
235 m_pats(new Patterns()),
236 m_last_timestamp(0)
237{
234 if (s_instance != 0) 238 if (s_instance != 0)
235 throw string("Can not create more than one instance of Remember"); 239 throw string("Can not create more than one instance of Remember");
236 240
237 s_instance = this; 241 s_instance = this;
238 enableUpdate(); 242 enableUpdate();
239 load(); 243 reconfigure();
240} 244}
241 245
242Remember::~Remember() { 246Remember::~Remember() {
@@ -247,11 +251,11 @@ Remember::~Remember() {
247 // the client mapping shouldn't need cleaning 251 // the client mapping shouldn't need cleaning
248 Patterns::iterator it; 252 Patterns::iterator it;
249 std::set<Application *> all_apps; // no duplicates 253 std::set<Application *> all_apps; // no duplicates
250 while (!m_pats.empty()) { 254 while (!m_pats->empty()) {
251 it = m_pats.begin(); 255 it = m_pats->begin();
252 delete it->first; // ClientPattern 256 delete it->first; // ClientPattern
253 all_apps.insert(it->second); // Application, not necessarily unique 257 all_apps.insert(it->second); // Application, not necessarily unique
254 m_pats.erase(it); 258 m_pats->erase(it);
255 } 259 }
256 260
257 std::set<Application *>::iterator ait = all_apps.begin(); // no duplicates 261 std::set<Application *>::iterator ait = all_apps.begin(); // no duplicates
@@ -270,8 +274,8 @@ Application* Remember::find(WinClient &winclient) {
270 if (wc_it != m_clients.end()) 274 if (wc_it != m_clients.end())
271 return wc_it->second; 275 return wc_it->second;
272 else { 276 else {
273 Patterns::iterator it = m_pats.begin(); 277 Patterns::iterator it = m_pats->begin();
274 for (; it != m_pats.end(); it++) 278 for (; it != m_pats->end(); it++)
275 if (it->first->match(winclient)) { 279 if (it->first->match(winclient)) {
276 it->first->addMatch(); 280 it->first->addMatch();
277 m_clients[&winclient] = it->second; 281 m_clients[&winclient] = it->second;
@@ -289,7 +293,7 @@ Application * Remember::add(WinClient &winclient) {
289 p->addTerm(p->getProperty(ClientPattern::NAME, winclient), ClientPattern::NAME); 293 p->addTerm(p->getProperty(ClientPattern::NAME, winclient), ClientPattern::NAME);
290 m_clients[&winclient] = app; 294 m_clients[&winclient] = app;
291 p->addMatch(); 295 p->addMatch();
292 m_pats.push_back(make_pair(p, app)); 296 m_pats->push_back(make_pair(p, app));
293 return app; 297 return app;
294} 298}
295 299
@@ -463,16 +467,66 @@ int Remember::parseApp(ifstream &file, Application &app, string *first_line) {
463 return row; 467 return row;
464} 468}
465 469
466void Remember::load() { 470/*
471 This function is used to search for old instances of the same pattern
472 (when reloading apps file). More than one pattern might match, but only
473 if the application is the same (also note that they'll be adjacent).
474 We REMOVE and delete any matching patterns from the old list, as they're
475 effectively moved into the new
476*/
477
478Application *Remember::findMatchingPatterns(ClientPattern *pat, Patterns *patlist, bool is_group) {
479 Patterns::iterator it = patlist->begin();
480 Patterns::iterator it_end = patlist->end();
481 for (; it != it_end; ++it) {
482 if (it->first->equals(*pat) && is_group == it->second->is_grouped) {
483 Application *ret = it->second;
484
485 // find any previous or subsequent matching ones and delete
486
487 // rewind
488 Patterns::iterator tmpit = it;
489 while (tmpit != patlist->begin()) {
490 --tmpit;
491 if (tmpit->second == ret)
492 it = tmpit;
493 else
494 break;
495 }
496
497 // forward
498 while (it != it_end && it->second == ret) {
499 tmpit = it;
500 ++it;
501 delete tmpit->first;
502 patlist->erase(tmpit);
503 }
504 return ret;
505 }
506 }
467 507
508 return 0;
509}
510
511
512void Remember::reconfigure() {
468 string apps_string = FbTk::StringUtil::expandFilename(Fluxbox::instance()->getAppsFilename()); 513 string apps_string = FbTk::StringUtil::expandFilename(Fluxbox::instance()->getAppsFilename());
469 514
515 time_t timestamp = FbTk::FileUtil::getLastStatusChangeTimestamp(apps_string.c_str());
516 if (m_last_timestamp > 0 && m_last_timestamp == timestamp)
517 return;
518
470#ifdef DEBUG 519#ifdef DEBUG
471 cerr<<__FILE__<<"("<<__FUNCTION__<<"): Loading apps file ["<<apps_string<<"]"<<endl; 520 cerr<<__FILE__<<"("<<__FUNCTION__<<"): Loading apps file ["<<apps_string<<"]"<<endl;
472#endif // DEBUG 521#endif // DEBUG
473 ifstream apps_file(apps_string.c_str()); 522 ifstream apps_file(apps_string.c_str());
474 523
524 // we merge the old patterns with new ones
525 Patterns *old_pats = m_pats.release();
526 m_pats.reset(new Patterns());
527
475 if (!apps_file.fail()) { 528 if (!apps_file.fail()) {
529 m_last_timestamp = timestamp;
476 if (!apps_file.eof()) { 530 if (!apps_file.eof()) {
477 string line; 531 string line;
478 int row = 0; 532 int row = 0;
@@ -494,8 +548,11 @@ void Remember::load() {
494 ClientPattern *pat = new ClientPattern(line.c_str() + pos); 548 ClientPattern *pat = new ClientPattern(line.c_str() + pos);
495 if (!in_group) { 549 if (!in_group) {
496 if ((err = pat->error()) == 0) { 550 if ((err = pat->error()) == 0) {
497 Application *app = new Application(false); 551 Application *app = findMatchingPatterns(pat, old_pats, false);
498 m_pats.push_back(make_pair(pat, app)); 552 if (!app)
553 app = new Application(false);
554
555 m_pats->push_back(make_pair(pat, app));
499 row += parseApp(apps_file, *app); 556 row += parseApp(apps_file, *app);
500 } else { 557 } else {
501 cerr<<"Error reading apps file at line "<<row<<", column "<<(err+pos)<<"."<<endl; 558 cerr<<"Error reading apps file at line "<<row<<", column "<<(err+pos)<<"."<<endl;
@@ -514,10 +571,21 @@ void Remember::load() {
514 in_group = true; 571 in_group = true;
515 } else if (in_group) { 572 } else if (in_group) {
516 // otherwise assume that it is the start of the attributes 573 // otherwise assume that it is the start of the attributes
517 Application *app = new Application(true); 574 Application *app = 0;
575 // search for a matching app
576 std::list<ClientPattern *>::iterator it = grouped_pats.begin();
577 std::list<ClientPattern *>::iterator it_end = grouped_pats.end();
578 while (!app && it != it_end) {
579 app = findMatchingPatterns(*it, old_pats, true);
580 ++it;
581 }
582
583 if (!app)
584 app = new Application(true);
585
518 while (!grouped_pats.empty()) { 586 while (!grouped_pats.empty()) {
519 // associate all the patterns with this app 587 // associate all the patterns with this app
520 m_pats.push_back(make_pair(grouped_pats.front(), app)); 588 m_pats->push_back(make_pair(grouped_pats.front(), app));
521 grouped_pats.pop_front(); 589 grouped_pats.pop_front();
522 } 590 }
523 591
@@ -540,6 +608,40 @@ void Remember::load() {
540 } else { 608 } else {
541 cerr << "apps file failure" << endl; 609 cerr << "apps file failure" << endl;
542 } 610 }
611
612 // Clean up old state
613 // can't just delete old patterns list. Need to delete the
614 // patterns themselves, plus the applications!
615
616 Patterns::iterator it;
617 std::set<Application *> old_apps; // no duplicates
618 while (!old_pats->empty()) {
619 it = old_pats->begin();
620 delete it->first; // ClientPattern
621 old_apps.insert(it->second); // Application, not necessarily unique
622 old_pats->erase(it);
623 }
624
625 // now remove any client entries for the old apps
626 Clients::iterator cit = m_clients.begin();
627 Clients::iterator cit_end = m_clients.end();
628 while (cit != cit_end) {
629 if (old_apps.find(cit->second) != old_apps.end()) {
630 Clients::iterator tmpit = cit;
631 ++cit;
632 m_clients.erase(tmpit);
633 } else {
634 ++cit;
635 }
636 }
637
638 std::set<Application *>::iterator ait = old_apps.begin(); // no duplicates
639 while (ait != old_apps.end()) {
640 delete (*ait);
641 ++ait;
642 }
643
644 delete old_pats;
543} 645}
544 646
545void Remember::save() { 647void Remember::save() {
@@ -558,8 +660,8 @@ void Remember::save() {
558 apps_file<<"[startup] "<<(*sit)<<endl; 660 apps_file<<"[startup] "<<(*sit)<<endl;
559 } 661 }
560 662
561 Patterns::iterator it = m_pats.begin(); 663 Patterns::iterator it = m_pats->begin();
562 Patterns::iterator it_end = m_pats.end(); 664 Patterns::iterator it_end = m_pats->end();
563 665
564 std::set<Application *> grouped_apps; // no duplicates 666 std::set<Application *> grouped_apps; // no duplicates
565 667
@@ -572,8 +674,8 @@ void Remember::save() {
572 grouped_apps.insert(&a); 674 grouped_apps.insert(&a);
573 // otherwise output this whole group 675 // otherwise output this whole group
574 apps_file << "[group]" << endl; 676 apps_file << "[group]" << endl;
575 Patterns::iterator git = m_pats.begin(); 677 Patterns::iterator git = m_pats->begin();
576 Patterns::iterator git_end = m_pats.end(); 678 Patterns::iterator git_end = m_pats->end();
577 for (; git != git_end; git++) { 679 for (; git != git_end; git++) {
578 if (git->second == &a) { 680 if (git->second == &a) {
579 apps_file << " [app]"<<git->first->toString()<<endl; 681 apps_file << " [app]"<<git->first->toString()<<endl;
@@ -969,8 +1071,8 @@ void Remember::initForScreen(BScreen &screen) {
969 1071
970void Remember::updateFrameClose(FluxboxWindow &win) { 1072void Remember::updateFrameClose(FluxboxWindow &win) {
971 // scan all applications and remove this fbw if it is a recorded group 1073 // scan all applications and remove this fbw if it is a recorded group
972 Patterns::iterator it = m_pats.begin(); 1074 Patterns::iterator it = m_pats->begin();
973 while (it != m_pats.end()) { 1075 while (it != m_pats->end()) {
974 if (&win == it->second->group) 1076 if (&win == it->second->group)
975 it->second->group = 0; 1077 it->second->group = 0;
976 ++it; 1078 ++it;
diff --git a/src/Remember.hh b/src/Remember.hh
index 2fa2dd1..42edca3 100644
--- a/src/Remember.hh
+++ b/src/Remember.hh
@@ -35,6 +35,7 @@
35#include <list> 35#include <list>
36#include <string> 36#include <string>
37#include <utility> 37#include <utility>
38#include <memory>
38 39
39class FluxboxWindow; 40class FluxboxWindow;
40class BScreen; 41class BScreen;
@@ -193,7 +194,7 @@ public:
193 Application* find(WinClient &winclient); 194 Application* find(WinClient &winclient);
194 Application* add(WinClient &winclient); 195 Application* add(WinClient &winclient);
195 196
196 void load(); 197 void reconfigure(); // was load
197 void save(); 198 void save();
198 199
199 bool isRemembered(WinClient &win, Attribute attrib); 200 bool isRemembered(WinClient &win, Attribute attrib);
@@ -213,8 +214,6 @@ public:
213 // Functions we ignore (zero from AtomHandler) 214 // Functions we ignore (zero from AtomHandler)
214 // Leaving here in case they might be useful later 215 // Leaving here in case they might be useful later
215 216
216
217
218 void updateFocusedWindow(BScreen &, Window) { } 217 void updateFocusedWindow(BScreen &, Window) { }
219 void updateClientList(BScreen &screen) {} 218 void updateClientList(BScreen &screen) {}
220 void updateWorkspaceNames(BScreen &screen) {} 219 void updateWorkspaceNames(BScreen &screen) {}
@@ -233,16 +232,22 @@ public:
233 bool propertyNotify(WinClient &winclient, Atom the_property) { return false; } 232 bool propertyNotify(WinClient &winclient, Atom the_property) { return false; }
234 233
235 static Remember &instance() { return *s_instance; } 234 static Remember &instance() { return *s_instance; }
235
236private: 236private:
237 237
238 // returns number of lines read 238 // returns number of lines read
239 // optionally can give a line to read before the first (lookahead line) 239 // optionally can give a line to read before the first (lookahead line)
240 int parseApp(std::ifstream &file, Application &app, std::string *first_line = 0); 240 int parseApp(std::ifstream &file, Application &app, std::string *first_line = 0);
241 Patterns m_pats; 241
242 Application *findMatchingPatterns(ClientPattern *pat, Patterns *patlist, bool is_group);
243
244 std::auto_ptr<Patterns> m_pats;
242 Clients m_clients; 245 Clients m_clients;
243 246
244 Startups m_startups; 247 Startups m_startups;
245 static Remember *s_instance; 248 static Remember *s_instance;
249
250 time_t m_last_timestamp;
246}; 251};
247 252
248#endif // REMEMBER_HH 253#endif // REMEMBER_HH
diff --git a/src/fluxbox.cc b/src/fluxbox.cc
index 62eef50..f5066b7 100644
--- a/src/fluxbox.cc
+++ b/src/fluxbox.cc
@@ -1678,6 +1678,12 @@ void Fluxbox::real_reconfigure() {
1678 //reconfigure keys 1678 //reconfigure keys
1679 m_key->reconfigure(StringUtil::expandFilename(*m_rc_keyfile).c_str()); 1679 m_key->reconfigure(StringUtil::expandFilename(*m_rc_keyfile).c_str());
1680 1680
1681 // and atomhandlers
1682 for (AtomHandlerContainerIt it= m_atomhandler.begin();
1683 it != m_atomhandler.end();
1684 it++) {
1685 (*it).first->reconfigure();
1686 }
1681} 1687}
1682 1688
1683BScreen *Fluxbox::findScreen(int id) { 1689BScreen *Fluxbox::findScreen(int id) {