From 53f869aa528c6fee86d382ff4cfe6dc1046093c7 Mon Sep 17 00:00:00 2001 From: simonb Date: Sun, 23 Apr 2006 14:51:04 +0000 Subject: reload the apps file on flux reload --- ChangeLog | 2 + src/AtomHandler.hh | 2 + src/ClientPattern.cc | 16 ++++++ src/ClientPattern.hh | 3 ++ src/Remember.cc | 140 ++++++++++++++++++++++++++++++++++++++++++++------- src/Remember.hh | 13 +++-- src/fluxbox.cc | 6 +++ 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 @@ (Format: Year/Month/Day) Changes for 0.9.16: *06/04/23: + * Reload the apps file on fluxbox reload (Simon) + Remember.hh/cc fluxbox.cc AtomHandler.hh ClientPattern.hh/cc * Update documentation for Next/PrevWindow (Simon / thanks Jonas Koelker), sf.net patch #1474825 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: virtual bool propertyNotify(WinClient &winclient, Atom the_property) = 0; + virtual void reconfigure() {} + /// should this object be updated or not? bool update() const { return m_update; } protected: 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 } return client.getWMClassName(); } + +bool ClientPattern::equals(const ClientPattern &pat) const { + // we require the terms to be identical (order too) + Terms::const_iterator it = m_terms.begin(); + Terms::const_iterator it_end = m_terms.end(); + Terms::const_iterator other_it = pat.m_terms.begin(); + Terms::const_iterator other_it_end = pat.m_terms.end(); + for (; it != it_end, other_it != other_it_end; ++it, ++other_it) { + if ((*it)->orig != (*other_it)->orig) + return false; + } + if (it != it_end || other_it != other_it_end) + return false; + + return true; +} 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: return match(win); } + // whether this pattern has identical matching criteria + bool equals(const ClientPattern &pat) const; + /** * If there are no terms, then there is assumed to be an error * 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 @@ #include "FbTk/I18n.hh" #include "FbTk/StringUtil.hh" +#include "FbTk/FileUtil.hh" #include "FbTk/MenuItem.hh" #include "FbTk/App.hh" #include "FbTk/stringstream.hh" @@ -230,13 +231,16 @@ Application::Application(bool grouped) Remember *Remember::s_instance = 0; -Remember::Remember() { +Remember::Remember(): + m_pats(new Patterns()), + m_last_timestamp(0) +{ if (s_instance != 0) throw string("Can not create more than one instance of Remember"); s_instance = this; enableUpdate(); - load(); + reconfigure(); } Remember::~Remember() { @@ -247,11 +251,11 @@ Remember::~Remember() { // the client mapping shouldn't need cleaning Patterns::iterator it; std::set all_apps; // no duplicates - while (!m_pats.empty()) { - it = m_pats.begin(); + while (!m_pats->empty()) { + it = m_pats->begin(); delete it->first; // ClientPattern all_apps.insert(it->second); // Application, not necessarily unique - m_pats.erase(it); + m_pats->erase(it); } std::set::iterator ait = all_apps.begin(); // no duplicates @@ -270,8 +274,8 @@ Application* Remember::find(WinClient &winclient) { if (wc_it != m_clients.end()) return wc_it->second; else { - Patterns::iterator it = m_pats.begin(); - for (; it != m_pats.end(); it++) + Patterns::iterator it = m_pats->begin(); + for (; it != m_pats->end(); it++) if (it->first->match(winclient)) { it->first->addMatch(); m_clients[&winclient] = it->second; @@ -289,7 +293,7 @@ Application * Remember::add(WinClient &winclient) { p->addTerm(p->getProperty(ClientPattern::NAME, winclient), ClientPattern::NAME); m_clients[&winclient] = app; p->addMatch(); - m_pats.push_back(make_pair(p, app)); + m_pats->push_back(make_pair(p, app)); return app; } @@ -463,16 +467,66 @@ int Remember::parseApp(ifstream &file, Application &app, string *first_line) { return row; } -void Remember::load() { +/* + This function is used to search for old instances of the same pattern + (when reloading apps file). More than one pattern might match, but only + if the application is the same (also note that they'll be adjacent). + We REMOVE and delete any matching patterns from the old list, as they're + effectively moved into the new +*/ + +Application *Remember::findMatchingPatterns(ClientPattern *pat, Patterns *patlist, bool is_group) { + Patterns::iterator it = patlist->begin(); + Patterns::iterator it_end = patlist->end(); + for (; it != it_end; ++it) { + if (it->first->equals(*pat) && is_group == it->second->is_grouped) { + Application *ret = it->second; + + // find any previous or subsequent matching ones and delete + + // rewind + Patterns::iterator tmpit = it; + while (tmpit != patlist->begin()) { + --tmpit; + if (tmpit->second == ret) + it = tmpit; + else + break; + } + + // forward + while (it != it_end && it->second == ret) { + tmpit = it; + ++it; + delete tmpit->first; + patlist->erase(tmpit); + } + return ret; + } + } + return 0; +} + + +void Remember::reconfigure() { string apps_string = FbTk::StringUtil::expandFilename(Fluxbox::instance()->getAppsFilename()); + time_t timestamp = FbTk::FileUtil::getLastStatusChangeTimestamp(apps_string.c_str()); + if (m_last_timestamp > 0 && m_last_timestamp == timestamp) + return; + #ifdef DEBUG cerr<<__FILE__<<"("<<__FUNCTION__<<"): Loading apps file ["<error()) == 0) { - Application *app = new Application(false); - m_pats.push_back(make_pair(pat, app)); + Application *app = findMatchingPatterns(pat, old_pats, false); + if (!app) + app = new Application(false); + + m_pats->push_back(make_pair(pat, app)); row += parseApp(apps_file, *app); } else { cerr<<"Error reading apps file at line "<::iterator it = grouped_pats.begin(); + std::list::iterator it_end = grouped_pats.end(); + while (!app && it != it_end) { + app = findMatchingPatterns(*it, old_pats, true); + ++it; + } + + if (!app) + app = new Application(true); + while (!grouped_pats.empty()) { // associate all the patterns with this app - m_pats.push_back(make_pair(grouped_pats.front(), app)); + m_pats->push_back(make_pair(grouped_pats.front(), app)); grouped_pats.pop_front(); } @@ -540,6 +608,40 @@ void Remember::load() { } else { cerr << "apps file failure" << endl; } + + // Clean up old state + // can't just delete old patterns list. Need to delete the + // patterns themselves, plus the applications! + + Patterns::iterator it; + std::set old_apps; // no duplicates + while (!old_pats->empty()) { + it = old_pats->begin(); + delete it->first; // ClientPattern + old_apps.insert(it->second); // Application, not necessarily unique + old_pats->erase(it); + } + + // now remove any client entries for the old apps + Clients::iterator cit = m_clients.begin(); + Clients::iterator cit_end = m_clients.end(); + while (cit != cit_end) { + if (old_apps.find(cit->second) != old_apps.end()) { + Clients::iterator tmpit = cit; + ++cit; + m_clients.erase(tmpit); + } else { + ++cit; + } + } + + std::set::iterator ait = old_apps.begin(); // no duplicates + while (ait != old_apps.end()) { + delete (*ait); + ++ait; + } + + delete old_pats; } void Remember::save() { @@ -558,8 +660,8 @@ void Remember::save() { apps_file<<"[startup] "<<(*sit)<begin(); + Patterns::iterator it_end = m_pats->end(); std::set grouped_apps; // no duplicates @@ -572,8 +674,8 @@ void Remember::save() { grouped_apps.insert(&a); // otherwise output this whole group apps_file << "[group]" << endl; - Patterns::iterator git = m_pats.begin(); - Patterns::iterator git_end = m_pats.end(); + Patterns::iterator git = m_pats->begin(); + Patterns::iterator git_end = m_pats->end(); for (; git != git_end; git++) { if (git->second == &a) { apps_file << " [app]"<first->toString()<begin(); + while (it != m_pats->end()) { if (&win == it->second->group) it->second->group = 0; ++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 @@ #include #include #include +#include class FluxboxWindow; class BScreen; @@ -193,7 +194,7 @@ public: Application* find(WinClient &winclient); Application* add(WinClient &winclient); - void load(); + void reconfigure(); // was load void save(); bool isRemembered(WinClient &win, Attribute attrib); @@ -213,8 +214,6 @@ public: // Functions we ignore (zero from AtomHandler) // Leaving here in case they might be useful later - - void updateFocusedWindow(BScreen &, Window) { } void updateClientList(BScreen &screen) {} void updateWorkspaceNames(BScreen &screen) {} @@ -233,16 +232,22 @@ public: bool propertyNotify(WinClient &winclient, Atom the_property) { return false; } static Remember &instance() { return *s_instance; } + private: // returns number of lines read // optionally can give a line to read before the first (lookahead line) int parseApp(std::ifstream &file, Application &app, std::string *first_line = 0); - Patterns m_pats; + + Application *findMatchingPatterns(ClientPattern *pat, Patterns *patlist, bool is_group); + + std::auto_ptr m_pats; Clients m_clients; Startups m_startups; static Remember *s_instance; + + time_t m_last_timestamp; }; #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() { //reconfigure keys m_key->reconfigure(StringUtil::expandFilename(*m_rc_keyfile).c_str()); + // and atomhandlers + for (AtomHandlerContainerIt it= m_atomhandler.begin(); + it != m_atomhandler.end(); + it++) { + (*it).first->reconfigure(); + } } BScreen *Fluxbox::findScreen(int id) { -- cgit v0.11.2