From 3ba591750bf5a5f8c1eab08d225f4d93f54bfaf2 Mon Sep 17 00:00:00 2001 From: Jason Kasper Date: Tue, 17 Feb 2004 05:34:25 +0000 Subject: [PATCH] adding auto-config-checker timer, woot --- src/Config.cpp | 4 ++ src/Config.h | 3 +- src/KeyClient.cpp | 145 +++++++++++++++++++++++++++++++++++++++--------------- src/KeyClient.h | 23 ++++++--- src/main.cpp | 12 ++--- 5 files changed, 133 insertions(+), 54 deletions(-) diff --git a/src/Config.cpp b/src/Config.cpp index 3ebee5d..0f15016 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -106,6 +106,10 @@ void Config::setOption(const std::string &name, const std::string &value) } +void Config::reset() { + _configMap.clear(); +} + void Config::showOptions() { ConfigMap::const_iterator it = _configMap.begin(), end = _configMap.end(); for (; it != end; ++it) { diff --git a/src/Config.h b/src/Config.h index e1135cd..6e140b0 100644 --- a/src/Config.h +++ b/src/Config.h @@ -35,7 +35,7 @@ typedef std::map ConfigMap; class Config { private: ConfigMap _configMap; - + public: Config(); ~Config(); @@ -46,6 +46,7 @@ public: void setOption(const std::string & key, const std::string & value); void showOptions(); + void reset(); }; diff --git a/src/KeyClient.cpp b/src/KeyClient.cpp index 7d452b0..1363c1c 100644 --- a/src/KeyClient.cpp +++ b/src/KeyClient.cpp @@ -48,7 +48,7 @@ extern "C" { #include } - + #include "version.h" #include "KeyClient.h" @@ -60,50 +60,72 @@ extern "C" { #include //-------------------------------------------------------- -// Constructor/Destructor +// Constructor/Destructor //-------------------------------------------------------- KeyClient::KeyClient (int argc, char **argv, Config & config, std::string display): bt::Application(BBTOOL, display.c_str(), true), _config(config) { - + + // save off what we're constructed with for reconfiguring later... + _argc = argc; + _argv = argv; + // initialize our keyword map for the file tokenizer initKeywords(_keywordMap); - + // now connect to the X server _display = XDisplay(); if (! _display ) { - cerr << "ERROR: Can't connect to X Server. Bummer! Exiting\n"; + cerr << "KeyClient: ERROR: Can't connect to X Server. Bummer! Exiting\n"; exit(2); } // check to see if we've been handed another config-file to use - _configFileName = bt::expandTilde(_config.getStringValue("config", + _configFileName = bt::expandTilde(_config.getStringValue("config", "~/.bbkeysrc") ); struct stat buf; if (0 != stat(_configFileName.c_str(), &buf) ||!S_ISREG(buf.st_mode)) { - cerr << "ERROR: Couldn't load rc-file: [" << _configFileName + cerr << "KeyClient: ERROR: Couldn't load rc-file: [" << _configFileName << "], falling back to default: [" << DEFAULTRC << "]\n"; _configFileName = DEFAULTRC; + } else { + _last_time_config_changed = buf.st_mtime; } - _debug = _config.getBoolValue("debug", false); + // here's our friendly little general-purpose keygrabber + _keyGrabber = new KeyGrabber(_display, numLockMask(), scrollLockMask() ); + + _netclient = new Netclient(_display); + _active = _clients.end(); + + initialize(); +} + +KeyClient::~KeyClient () +{ + + // delete all screens + for_each(screenList.begin(), screenList.end(), bt::PointerAssassin()); + + if (_keybindings) delete _keybindings; + if (_netclient) delete _netclient; + if (_keyGrabber) delete _keyGrabber; +} + +void KeyClient::initialize() { + // now, read in our configuration file and set both program settings // and keybindings we're asked to handle handleConfigFile(); // parse command options again to override what we read in from config file - parseOptions( argc, argv, _config ); + parseOptions( _argc, _argv, _config ); - _netclient = new Netclient(_display); - _active = _clients.end(); - // here's our friendly little general-purpose keygrabber - _keyGrabber = new KeyGrabber(_display, numLockMask(), scrollLockMask() ); - // now create a screen handler for each screen that exists for (unsigned int i = 0; i < bt::Application::display().screenCount(); i++) { ScreenHandler *screen = new ScreenHandler(this, i); @@ -113,35 +135,52 @@ KeyClient::KeyClient (int argc, char **argv, } screen->initialize(); - + // add this screen to our collection screenList.push_back(screen); } if (screenList.empty()) { - cerr << "KeyClient::KeyClient: no compatible window managers found, aborting.\n"; + cerr << "KeyClient: initialize: no compatible window managers found, aborting.\n"; ::exit(3); - } - - -} -KeyClient::~KeyClient () -{ + } - // delete all screens - for_each(screenList.begin(), screenList.end(), bt::PointerAssassin()); + _autoConfigCheckTimeout = (_config.getNumberValue("autoConfigCheckTimeout", 10)) * 1000; + _autoConfig = _config.getBoolValue("autoConfig", true); + if (_autoConfig) { + if (!config_check_timer) { + config_check_timer = new bt::Timer(this, this); + } + config_check_timer->setTimeout(_autoConfigCheckTimeout); + config_check_timer->recurring(True); + config_check_timer->start(); + } - if (_keybindings) delete _keybindings; - if (_netclient) delete _netclient; - if (_keyGrabber) delete _keyGrabber; } //-------------------------------------------------------- -// reconfigure +// reconfigure //-------------------------------------------------------- void KeyClient::reconfigure () { - cout << "hey, goodie! I got a reconfigure request!!\n"; + if (_debug) + std::cout << "KeyClient: reconfigure: hey, goodie! I got a reconfigure request!!\n"; + + + // delete all screens + for_each(screenList.begin(), screenList.end(), bt::PointerAssassin()); + screenList.clear(); + + // initialize and/or clear our config + _config.reset(); + + // reset our timer + if (config_check_timer) { + config_check_timer->halt(); + } + + initialize(); + } @@ -157,9 +196,9 @@ void KeyClient::handleConfigFile() { } _keybindings->reset(); - + bool _doingConfig = false, _doingKeybindings = false; - + TokenBlock *block = 0; while ((block = tokenizer.next())) { switch (block->tag) { @@ -177,17 +216,17 @@ void KeyClient::handleConfigFile() { if (_debug) cout << "got a config option!, setting key: [" << block->name << "] to value: [" << block->data << "]\n"; - + _config.setOption(block->name, block->data); break; case ConfigOpts::keybindings: _doingKeybindings = true; setKeybindings(tokenizer); - + if (_debug) _keybindings->showTree(); - - break; + + break; default: cerr << "unknown tag found in ConfigOpts block: [" << block->tag << "], name: [" << block->name @@ -245,7 +284,7 @@ void KeyClient::setKeybindings(FileTokenizer & tokenizer) { cerr << "ERROR: No key or modifier given. Ignoring this one, Jimmy.\n"; if (block) delete block; continue; - } + } // first, split our string containing our keys/modifiers and separate // the keys from the modifiers vector results; @@ -258,11 +297,11 @@ void KeyClient::setKeybindings(FileTokenizer & tokenizer) { if (sym == 0) { cerr << "ERROR: Invalid key (" << _key << ")! This may cause odd behavior.\n"; } - + // now iterate through our modifiers and try to match the given string // to a modifier mask. if we find it, xor it together with what we already have unsigned int _mask=0; - + for (int j=0; j < (matches -1); j++) { bool found=false; @@ -332,7 +371,7 @@ void KeyClient::initKeywords(KeywordMap& keywords) { keywords.insert(KeywordMap::value_type("nextscreen", Action::nextScreen)); keywords.insert(KeywordMap::value_type("prevscreen", Action::prevScreen)); - + keywords.insert(KeywordMap::value_type("showrootmenu", Action::showRootMenu)); keywords.insert(KeywordMap::value_type("showworkspacemenu", Action::showWorkspaceMenu)); keywords.insert(KeywordMap::value_type("toggledecorations", Action::toggleDecorations)); @@ -364,7 +403,7 @@ bool KeyClient::process_signal(int sig) { void KeyClient::process_event(XEvent *e) { // Send the event through the default EventHandlers. - bt::Application::process_event(e); + bt::Application::process_event(e); } void KeyClient::cycleScreen(int current, bool forward) const { @@ -375,7 +414,7 @@ void KeyClient::cycleScreen(int current, bool forward) const { break; } assert(i < screenList.size()); // current is for an unmanaged screen - + int dest = current + (forward ? 1 : -1); if (dest < 0) dest = (signed)screenList.size() - 1; @@ -384,3 +423,27 @@ void KeyClient::cycleScreen(int current, bool forward) const { const XWindow *target = screenList[dest]->lastActiveWindow(); if (target) target->focus(); } + +void KeyClient::timeout(bt::Timer *timer) { + if (_debug) + std::cout << "KeyClient: timeout: got timeout from timer...." << std::endl; + if (timer == config_check_timer) { + checkConfigFile(); + } +} + +void KeyClient::checkConfigFile() { + + struct stat file_status; + + if (stat(_configFileName.c_str(), &file_status) != 0) { + if (_debug) + std::cerr << "Could not open config file: [" << _configFileName << "]"; + } else if (file_status.st_mtime != _last_time_config_changed) { + if (_debug) + std::cout << "KeyClient: checkConfigFile: config file time changed..." << std::endl; + _last_time_config_changed = file_status.st_mtime; + reconfigure(); + } +} + diff --git a/src/KeyClient.h b/src/KeyClient.h index 2b2cbe4..59b5552 100644 --- a/src/KeyClient.h +++ b/src/KeyClient.h @@ -44,12 +44,13 @@ #include #include #include +#include class ScreenHandler; class keytree; -class KeyClient : public bt::Application +class KeyClient : public bt::Application, public bt::TimeoutHandler { public: @@ -60,7 +61,7 @@ public: inline Netclient * getNetclient() { return _netclient; } inline Config * getConfig() { return &_config; } inline KeyGrabber * getKeyGrabber() { return _keyGrabber; } - inline bt::Application & getMainApplication() + inline bt::Application & getMainApplication() { return dynamic_cast (* this); } void cycleScreen(int current, bool forward) const; @@ -71,8 +72,11 @@ public: WindowList& clientsList() { return _clients; } WindowList::iterator& activeWindow() { return _active; } - + virtual void timeout(bt::Timer *timer); + private: + int _argc; + char **_argv; keytree *_keybindings; std::string _configFileName; Config & _config; @@ -84,19 +88,26 @@ private: bool _debug; typedef std::vector ScreenList; - ScreenList screenList; + ScreenList screenList; void handleConfigFile(); void initKeywords(KeywordMap &); - void reconfigure () ; + void reconfigure(); + void initialize(); void setKeybindings(FileTokenizer &); bool process_signal(int sig); void process_event(XEvent *e); WindowList _clients; - WindowList::iterator _active; + WindowList::iterator _active; + + bt::Timer *config_check_timer; + long _autoConfigCheckTimeout; + bool _autoConfig; + void checkConfigFile(); + time_t _last_time_config_changed; }; #endif diff --git a/src/main.cpp b/src/main.cpp index 5bab50a..8cb3022 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,7 +31,7 @@ bt::I18n bt::i18n; //-------------------------------------------------------- -// parseOptions +// parseOptions //-------------------------------------------------------- void parseOptions (int argc, char **argv, Config & _config) { @@ -44,7 +44,7 @@ void parseOptions (int argc, char **argv, Config & _config) exit(2); }; _config.setOption("display", argv[i]); - + // Applications we exec will need the proper display string disp = (string)"DISPLAY=" + argv[i]; putenv((char *)disp.c_str()); @@ -72,7 +72,7 @@ void parseOptions (int argc, char **argv, Config & _config) usage(); exit(2); }; - + } } @@ -84,7 +84,7 @@ void usage() { << " -d or --display X server to connect to" << endl << " -D or --debug print debugging information" << endl << " -c or --config configuration file" << endl - << " (default is ~/.blackbox/keybindings)" << endl + << " (default is ~/.bbkeysrc)" << endl << " -v or --version Display version number" << endl << " -h or --help Display this help" << endl; } @@ -99,12 +99,12 @@ int main(int argc, char **argv) std::string dpy_name = _config->getStringValue("display", getenv("DISPLAY")); - + KeyClient * _k=new KeyClient(argc, argv, *_config, dpy_name); _k->run(); delete _k; delete _config; - + return 0; } -- 2.11.4.GIT