reload the apps file on flux reload
This commit is contained in:
parent
39cacd1da8
commit
53f869aa52
7 changed files with 159 additions and 23 deletions
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
140
src/Remember.cc
140
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<Application *> 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<Application *>::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 ["<<apps_string<<"]"<<endl;
|
||||
#endif // DEBUG
|
||||
ifstream apps_file(apps_string.c_str());
|
||||
|
||||
// we merge the old patterns with new ones
|
||||
Patterns *old_pats = m_pats.release();
|
||||
m_pats.reset(new Patterns());
|
||||
|
||||
if (!apps_file.fail()) {
|
||||
m_last_timestamp = timestamp;
|
||||
if (!apps_file.eof()) {
|
||||
string line;
|
||||
int row = 0;
|
||||
|
@ -494,8 +548,11 @@ void Remember::load() {
|
|||
ClientPattern *pat = new ClientPattern(line.c_str() + pos);
|
||||
if (!in_group) {
|
||||
if ((err = pat->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 "<<row<<", column "<<(err+pos)<<"."<<endl;
|
||||
|
@ -514,10 +571,21 @@ void Remember::load() {
|
|||
in_group = true;
|
||||
} else if (in_group) {
|
||||
// otherwise assume that it is the start of the attributes
|
||||
Application *app = new Application(true);
|
||||
Application *app = 0;
|
||||
// search for a matching app
|
||||
std::list<ClientPattern *>::iterator it = grouped_pats.begin();
|
||||
std::list<ClientPattern *>::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<Application *> 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<Application *>::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)<<endl;
|
||||
}
|
||||
|
||||
Patterns::iterator it = m_pats.begin();
|
||||
Patterns::iterator it_end = m_pats.end();
|
||||
Patterns::iterator it = m_pats->begin();
|
||||
Patterns::iterator it_end = m_pats->end();
|
||||
|
||||
std::set<Application *> 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]"<<git->first->toString()<<endl;
|
||||
|
@ -969,8 +1071,8 @@ void Remember::initForScreen(BScreen &screen) {
|
|||
|
||||
void Remember::updateFrameClose(FluxboxWindow &win) {
|
||||
// scan all applications and remove this fbw if it is a recorded group
|
||||
Patterns::iterator it = m_pats.begin();
|
||||
while (it != m_pats.end()) {
|
||||
Patterns::iterator it = m_pats->begin();
|
||||
while (it != m_pats->end()) {
|
||||
if (&win == it->second->group)
|
||||
it->second->group = 0;
|
||||
++it;
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <list>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
|
||||
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<Patterns> m_pats;
|
||||
Clients m_clients;
|
||||
|
||||
Startups m_startups;
|
||||
static Remember *s_instance;
|
||||
|
||||
time_t m_last_timestamp;
|
||||
};
|
||||
|
||||
#endif // REMEMBER_HH
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue