From 6fdda1a31d2417c23f5f222114d30ce6abec8b40 Mon Sep 17 00:00:00 2001 From: markt Date: Fri, 9 Feb 2007 18:13:01 +0000 Subject: added mouse bindings to the keys file --- ChangeLog | 13 +++ data/init.in | 1 + data/keys | 6 ++ src/FbCommandFactory.cc | 3 + src/FbCommands.cc | 9 ++ src/FbCommands.hh | 5 ++ src/FbTk/KeyUtil.cc | 7 +- src/FbTk/KeyUtil.hh | 1 + src/Keys.cc | 95 +++++++++++++++----- src/Keys.hh | 43 +++++---- src/Screen.cc | 2 +- src/Screen.hh | 2 +- src/WorkspaceCmd.cc | 66 +++++++------- src/fluxbox.cc | 98 ++++++++++---------- util/Makefile.am | 12 ++- util/fluxbox-update_configs.cc | 197 +++++++++++++++++++++++++++++++++++++++++ 16 files changed, 433 insertions(+), 127 deletions(-) create mode 100644 util/fluxbox-update_configs.cc diff --git a/ChangeLog b/ChangeLog index 4a745e1..ddece80 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,18 @@ (Format: Year/Month/Day) Changes for 1.0rc3: +*07/02/09: + * Introduced support for mouse buttons in the keys file (Mark) + - Mouse buttons are bound to new `keys' Mouse1, Mouse2, etc. + - Also a new modifier `OnDesktop' to specify actions that should take place + when you click on the desktop -- without this, mouse bindings are global + - Obviously, more modifiers are planned, so don't ask + - Introduced new command HideMenus + - Added a utility to the project that automatically updates configuration + files when we change the syntax -- your current mouse bindings on the + desktop will be added to your keys file automatically + FbCommands.cc/hh FbCommandFactory.cc Keys.cc/hh Screen.cc/hh fluxbox.cc + FbTk/KeyUtil.cc/hh WorkspaceCmd.cc data/init.in data/keys util/Makefile.am + Added util/fluxbox-update_configs.cc *07/02/06: * Wrong window was being raised when attaching an unfocused window (Mark) Window.cc diff --git a/data/init.in b/data/init.in index 278ac80..76b4e08 100644 --- a/data/init.in +++ b/data/init.in @@ -33,3 +33,4 @@ session.colorsPerChannel: 4 session.doubleClickInterval: 250 session.cacheMax: 200 session.imageDither: True +session.configVersion: 1 diff --git a/data/keys b/data/keys index b78e2c3..d76b18f 100644 --- a/data/keys +++ b/data/keys @@ -1,3 +1,9 @@ +OnDesktop Mouse1 :HideMenus +OnDesktop Mouse2 :WorkspaceMenu +OnDesktop Mouse3 :RootMenu +OnDesktop Mouse4 :NextWorkspace +OnDesktop Mouse5 :PrevWorkspace + Mod1 Tab :NextWindow Mod1 Shift Tab :PrevWindow Mod1 F1 :Workspace 1 diff --git a/src/FbCommandFactory.cc b/src/FbCommandFactory.cc index b82332a..2f05e5a 100644 --- a/src/FbCommandFactory.cc +++ b/src/FbCommandFactory.cc @@ -77,6 +77,7 @@ FbCommandFactory::FbCommandFactory() { "focusleft", "focusright", "fullscreen", + "hidemenus", "iconify", "keymode", "killwindow", @@ -433,6 +434,8 @@ FbTk::Command *FbCommandFactory::stringToCommand(const std::string &command, return new ArrangeWindowsCmd(); else if (command == "showdesktop") return new ShowDesktopCmd(); + else if (command == "hidemenus") + return new HideMenuCmd(); else if (command == "rootmenu") return new ShowRootMenuCmd(); else if (command == "workspacemenu") diff --git a/src/FbCommands.cc b/src/FbCommands.cc index 5fbceab..692e12f 100644 --- a/src/FbCommands.cc +++ b/src/FbCommands.cc @@ -260,6 +260,15 @@ void KeyModeCmd::execute() { Fluxbox::instance()->keys()->keyMode(m_keymode); } +void HideMenuCmd::execute() { + BScreen *screen = Fluxbox::instance()->mouseScreen(); + screen->hideMenus(); + if (screen->rootMenu().isVisible()) + screen->rootMenu().hide(); + if (screen->workspaceMenu().isVisible()) + screen->workspaceMenu().hide(); +} + void ShowRootMenuCmd::execute() { BScreen *screen = Fluxbox::instance()->mouseScreen(); if (screen == 0) diff --git a/src/FbCommands.hh b/src/FbCommands.hh index 8ac40fa..59200d2 100644 --- a/src/FbCommands.hh +++ b/src/FbCommands.hh @@ -113,6 +113,11 @@ private: std::string m_end_args; }; +class HideMenuCmd: public FbTk::Command { +public: + void execute(); +}; + class ShowRootMenuCmd: public FbTk::Command { public: void execute(); diff --git a/src/FbTk/KeyUtil.cc b/src/FbTk/KeyUtil.cc index 3f413a9..6985139 100644 --- a/src/FbTk/KeyUtil.cc +++ b/src/FbTk/KeyUtil.cc @@ -138,7 +138,7 @@ void KeyUtil::grabButton(unsigned int button, unsigned int mod, Window win, for (int i = 0; i < 8; i++) { XGrabButton(display, button, mod | (i & 1 ? capsmod : 0) | (i & 2 ? nummod : 0) | (i & 4 ? scrollmod : 0), - win, True, event_mask, GrabModeAsync, GrabModeAsync, + win, False, event_mask, GrabModeAsync, GrabModeAsync, None, cursor); } @@ -180,6 +180,11 @@ void KeyUtil::ungrabKeys(Window win) { XUngrabKey(display, AnyKey, AnyModifier, win); } +void KeyUtil::ungrabButtons(Window win) { + Display * display = App::instance()->display(); + XUngrabButton(display, AnyButton, AnyModifier, win); +} + unsigned int KeyUtil::keycodeToModmask(unsigned int keycode) { XModifierKeymap *modmap = instance().m_modmap; diff --git a/src/FbTk/KeyUtil.hh b/src/FbTk/KeyUtil.hh index eb2cdd5..4909c5a 100644 --- a/src/FbTk/KeyUtil.hh +++ b/src/FbTk/KeyUtil.hh @@ -62,6 +62,7 @@ public: ungrabs all keys */ static void ungrabKeys(Window win); + static void ungrabButtons(Window win); /** Strip out modifiers we want to ignore diff --git a/src/Keys.cc b/src/Keys.cc index e7b7acd..dbcff67 100644 --- a/src/Keys.cc +++ b/src/Keys.cc @@ -114,6 +114,7 @@ Keys::Keys(): Keys::~Keys() { ungrabKeys(); + ungrabButtons(); deleteTree(); } @@ -140,6 +141,23 @@ void Keys::ungrabKeys() { FbTk::KeyUtil::ungrabKeys(*it); } +void Keys::grabButton(unsigned int button, unsigned int mod) { + std::list::iterator it = m_window_list.begin(); + std::list::iterator it_end = m_window_list.end(); + + for (; it != it_end; ++it) + FbTk::KeyUtil::grabButton(button, mod, *it, + ButtonPressMask|ButtonReleaseMask); +} + +void Keys::ungrabButtons() { + std::list::iterator it = m_window_list.begin(); + std::list::iterator it_end = m_window_list.end(); + + for (; it != it_end; ++it) + FbTk::KeyUtil::ungrabButtons(*it); +} + /** Load and grab keys TODO: error checking @@ -152,7 +170,7 @@ bool Keys::load(const char *filename) { //free memory of previous grabs deleteTree(); - m_map["default:"] = new t_key(0,0); + m_map["default:"] = new t_key(0,0,0,0); FbTk::App::instance()->sync(false); @@ -211,6 +229,7 @@ bool Keys::addBinding(const string &linebuffer) { return true; // still a valid line. unsigned int key = 0, mod = 0; + int type = 0, context = 0; size_t argc = 0; t_key *current_key=m_map["default:"]; t_key *first_new_keylist = current_key, *first_new_key=0; @@ -219,7 +238,7 @@ bool Keys::addBinding(const string &linebuffer) { argc++; keyspace_t::iterator it = m_map.find(val[0]); if (it == m_map.end()) - m_map[val[0]] = new t_key(0,0); + m_map[val[0]] = new t_key(0,0,0,0); current_key = m_map[val[0]]; } // for each argument @@ -230,41 +249,53 @@ bool Keys::addBinding(const string &linebuffer) { int tmpmod = FbTk::KeyUtil::getModifier(val[argc].c_str()); if(tmpmod) mod |= tmpmod; //If it's a modifier + else if (strcasecmp("ondesktop", val[argc].c_str()) == 0) + context |= ON_DESKTOP; else if (strcasecmp("NONE",val[argc].c_str())) { + // check if it's a mouse button + if (!strcasecmp(val[argc].substr(0,5).c_str(), "mouse") && + val[argc].length() > 5) { + type = ButtonPress; + key = atoi(val[argc].substr(5,val[argc].length()-5).c_str()); // keycode covers the following three two-byte cases: // 0x - hex // +[1-9] - number between +1 and +9 // numbers 10 and above // - if (val[argc].size() > 1 && (isdigit(val[argc][0]) && - (isdigit(val[argc][1]) || val[argc][1] == 'x') || - val[argc][0] == '+' && isdigit(val[argc][1])) ) { + } else if (val[argc].size() > 1 && (isdigit(val[argc][0]) && + (isdigit(val[argc][1]) || val[argc][1] == 'x') || + val[argc][0] == '+' && isdigit(val[argc][1])) ) { key = strtoul(val[argc].c_str(), NULL, 0); + type = KeyPress; if (errno == EINVAL || errno == ERANGE) key = 0; - } else // convert from string symbol + } else { // convert from string symbol key = FbTk::KeyUtil::getKey(val[argc].c_str()); + type = KeyPress; + } if (key == 0) return false; if (!first_new_key) { first_new_keylist = current_key; - current_key = current_key->find(key, mod); + current_key = current_key->find(type, mod, key, context); if (!current_key) { - first_new_key = new t_key(key, mod); + first_new_key = new t_key(type, mod, key, context); current_key = first_new_key; } else if (*current_key->m_command) // already being used return false; } else { - t_key *temp_key = new t_key(key, mod); + t_key *temp_key = new t_key(type, mod, key, context); current_key->keylist.push_back(temp_key); current_key = temp_key; } mod = 0; key = 0; + type = 0; + context = 0; } } else { // parse command line @@ -291,36 +322,43 @@ bool Keys::addBinding(const string &linebuffer) { } // return true if bound to a command, else false -bool Keys::doAction(XKeyEvent &ke) { - - ke.state = FbTk::KeyUtil::instance().cleanMods(ke.state); +bool Keys::doAction(int type, unsigned int mods, unsigned int key) { static t_key* next_key = m_keylist; if (!next_key) next_key = m_keylist; - t_key *temp_key = next_key->find(ke); + mods = FbTk::KeyUtil::instance().cleanMods(mods); + // at the moment, any key/button that gets here is on root window + // context will need to be added as an argument to doAction, though + t_key *temp_key = next_key->find(type, mods, key, ON_DESKTOP|GLOBAL); // need to save this for emacs-style keybindings static t_key *saved_keymode = 0; + // grab "None Escape" to exit keychain in the middle + unsigned int esc = FbTk::KeyUtil::getKey("Escape"); + if (temp_key && temp_key->keylist.size()) { // emacs-style - saved_keymode = m_keylist; + if (!saved_keymode) + saved_keymode = m_keylist; next_key = temp_key; setKeyMode(next_key); - // grab "None Escape" to exit keychain in the middle - unsigned int esc = FbTk::KeyUtil::getKey("Escape"); grabKey(esc,0); return true; } if (!temp_key || *temp_key->m_command == 0) { - next_key = 0; - if (saved_keymode) { - setKeyMode(saved_keymode); - saved_keymode = 0; + if (type == KeyPress && key == esc && mods == 0) { + // if we're in the middle of an emacs-style keychain, exit it + next_key = 0; + if (saved_keymode) { + setKeyMode(saved_keymode); + saved_keymode = 0; + } } return false; } + temp_key->m_command->execute(); if (saved_keymode) { if (next_key == m_keylist) // don't reset keymode if command changed it @@ -349,22 +387,33 @@ void Keys::keyMode(string keyMode) { void Keys::setKeyMode(t_key *keyMode) { ungrabKeys(); + ungrabButtons(); keylist_t::iterator it = keyMode->keylist.begin(); keylist_t::iterator it_end = keyMode->keylist.end(); - for (; it != it_end; ++it) - grabKey((*it)->key,(*it)->mod); + for (; it != it_end; ++it) { + if ((*it)->type == KeyPress) + grabKey((*it)->key,(*it)->mod); + else if ((*it)->context == GLOBAL) + grabButton((*it)->key,(*it)->mod); + // we must use root window's event mask to get ON_DESKTOP events + } m_keylist = keyMode; } -Keys::t_key::t_key(unsigned int key_, unsigned int mod_, FbTk::RefCount command) { +Keys::t_key::t_key(int type_, unsigned int mod_, unsigned int key_, + int context_, FbTk::RefCount command) { key = key_; mod = mod_; + type = type_; + context = context_ ? context_ : GLOBAL; m_command = command; } Keys::t_key::t_key(t_key *k) { key = k->key; mod = k->mod; + type = k->type; + context = k->context; m_command = k->m_command; } diff --git a/src/Keys.hh b/src/Keys.hh index 6602d49..0365cf8 100644 --- a/src/Keys.hh +++ b/src/Keys.hh @@ -38,6 +38,21 @@ class Keys:private FbTk::NotCopyable { public: + // contexts for events + // it's ok if there is overlap; it will be worked out in t_key::find() + // eventHandlers should submit bitwise-or of contexts the event happened in + enum { + GLOBAL = 0x01, + ON_DESKTOP = 0x02, + ON_TOOLBAR = 0x04, + ON_ICONBUTTON = 0x08, + ON_TITLEBAR = 0x10, + ON_WINDOW = 0x20, + ON_TAB = 0x40, + ON_SLIT = 0x80 + // and so on... + }; + /** Constructor @param display display connection @@ -65,7 +80,7 @@ public: /** do action from XKeyEvent; return false if not bound to anything */ - bool doAction(XKeyEvent &ke); + bool doAction(int type, unsigned int mods, unsigned int key); /** Reload configuration from filename @@ -79,6 +94,8 @@ private: void grabKey(unsigned int key, unsigned int mod); void ungrabKeys(); + void grabButton(unsigned int button, unsigned int mod); + void ungrabButtons(); std::string m_filename; @@ -87,33 +104,27 @@ private: class t_key { public: - t_key(unsigned int key, unsigned int mod, + t_key(int type, unsigned int mod, unsigned int key, int context, FbTk::RefCount command = FbTk::RefCount(0)); t_key(t_key *k); ~t_key(); - t_key *find(unsigned int key_, unsigned int mod_) { - for (size_t i = 0; i < keylist.size(); i++) { - if (keylist[i]->key == key_ && keylist[i]->mod == FbTk::KeyUtil::instance().isolateModifierMask(mod_)) - return keylist[i]; - } - return 0; - } - t_key *find(XKeyEvent &ke) { + t_key *find(int type_, unsigned int mod_, unsigned int key_, + int context_) { for (size_t i = 0; i < keylist.size(); i++) { - if (keylist[i]->key == ke.keycode && - keylist[i]->mod == FbTk::KeyUtil::instance().isolateModifierMask(ke.state)) + if (keylist[i]->type == type_ && keylist[i]->key == key_ && + (keylist[i]->context & context_) > 0 && keylist[i]->mod == + FbTk::KeyUtil::instance().isolateModifierMask(mod_)) return keylist[i]; } return 0; } - bool operator == (XKeyEvent &ke) const { - return (mod == FbTk::KeyUtil::instance().isolateModifierMask(ke.state) && key == ke.keycode); - } FbTk::RefCount m_command; - unsigned int key; + int context; // ON_TITLEBAR, etc.: bitwise-or of all desired contexts + int type; // KeyPress or ButtonPress + unsigned int key; // key code or button number unsigned int mod; keylist_t keylist; }; diff --git a/src/Screen.cc b/src/Screen.cc index d7fc19a..f3a5d01 100644 --- a/src/Screen.cc +++ b/src/Screen.cc @@ -2060,7 +2060,7 @@ void BScreen::renderPosWindow() { /** Called when a set of watched modifiers has been released */ -void BScreen::notifyReleasedKeys(XKeyEvent &ke) { +void BScreen::notifyReleasedKeys() { focusControl().stopCyclingFocus(); } diff --git a/src/Screen.hh b/src/Screen.hh index 739c458..de1dc78 100644 --- a/src/Screen.hh +++ b/src/Screen.hh @@ -294,7 +294,7 @@ public: void showGeometry(int width, int height); void hideGeometry(); - void notifyReleasedKeys(XKeyEvent &ke); + void notifyReleasedKeys(); void setLayer(FbTk::XLayerItem &item, int layernum); // remove? no, items are never removed from their layer until they die diff --git a/src/WorkspaceCmd.cc b/src/WorkspaceCmd.cc index 6c97808..d2bc3b7 100644 --- a/src/WorkspaceCmd.cc +++ b/src/WorkspaceCmd.cc @@ -42,44 +42,48 @@ #include void NextWindowCmd::execute() { - BScreen *screen = Fluxbox::instance()->keyScreen(); + Fluxbox *fb = Fluxbox::instance(); + BScreen *screen = fb->keyScreen(); if (screen != 0) { - Fluxbox *fb = Fluxbox::instance(); - // special case for commands from key events - if (fb->lastEvent().type == KeyPress) { - unsigned int mods = FbTk::KeyUtil::instance().cleanMods(fb->lastEvent().xkey.state); - mods = FbTk::KeyUtil::instance().isolateModifierMask(mods); - if (mods == 0) // can't stacked cycle unless there is a mod to grab - screen->focusControl().nextFocus(m_option | FocusControl::CYCLELINEAR); - else { - // if stacked cycling, then set a watch for - // the release of exactly these modifiers - Fluxbox::instance()->watchKeyRelease(*screen, mods); - screen->focusControl().nextFocus(m_option); - } - } else + // get modifiers from event that causes this for focus order cycling + unsigned int mods = 0; + XEvent ev = fb->lastEvent(); + if (ev.type == KeyPress) { + mods = FbTk::KeyUtil::instance().cleanMods(ev.xkey.state); + } else if (ev.type == ButtonPress) { + mods = FbTk::KeyUtil::instance().cleanMods(ev.xbutton.state); + } + if (mods == 0) // can't stacked cycle unless there is a mod to grab screen->focusControl().nextFocus(m_option | FocusControl::CYCLELINEAR); + else { + // if stacked cycling, then set a watch for + // the release of exactly these modifiers + fb->watchKeyRelease(*screen, mods); + screen->focusControl().nextFocus(m_option); + } } } void PrevWindowCmd::execute() { - BScreen *screen = Fluxbox::instance()->keyScreen(); + Fluxbox *fb = Fluxbox::instance(); + BScreen *screen = fb->keyScreen(); if (screen != 0) { - Fluxbox *fb = Fluxbox::instance(); - // special case for commands from key events - if (fb->lastEvent().type == KeyPress) { - unsigned int mods = FbTk::KeyUtil::instance().cleanMods(fb->lastEvent().xkey.state); - mods = FbTk::KeyUtil::instance().isolateModifierMask(mods); - if (mods == 0) // can't stacked cycle unless there is a mod to grab - screen->focusControl().prevFocus(m_option | FocusControl::CYCLELINEAR); - else { - // if stacked cycling, then set a watch for - // the release of exactly these modifiers - Fluxbox::instance()->watchKeyRelease(*screen, mods); - screen->focusControl().prevFocus(m_option); - } - } else - screen->focusControl().nextFocus(m_option | FocusControl::CYCLELINEAR); + // get modifiers from event that causes this for focus order cycling + unsigned int mods = 0; + XEvent ev = fb->lastEvent(); + if (ev.type == KeyPress) { + mods = FbTk::KeyUtil::instance().cleanMods(ev.xkey.state); + } else if (ev.type == ButtonPress) { + mods = FbTk::KeyUtil::instance().cleanMods(ev.xbutton.state); + } + if (mods == 0) // can't stacked cycle unless there is a mod to grab + screen->focusControl().prevFocus(m_option | FocusControl::CYCLELINEAR); + else { + // if stacked cycling, then set a watch for + // the release of exactly these modifiers + fb->watchKeyRelease(*screen, mods); + screen->focusControl().prevFocus(m_option); + } } } diff --git a/src/fluxbox.cc b/src/fluxbox.cc index 89b37fe..7958a27 100644 --- a/src/fluxbox.cc +++ b/src/fluxbox.cc @@ -649,6 +649,28 @@ void Fluxbox::setupConfigFiles() { if (create_init) FbTk::FileUtil::copyFile(DEFAULT_INITFILE, init_file.c_str()); +#define CONFIG_VERSION 1 + FbTk::Resource config_version(m_resourcemanager, 0, + "session.configVersion", "Session.ConfigVersion"); + if (*config_version < CONFIG_VERSION) { + // configs are out of date, so run fluxbox-update_configs + + string commandargs = "fluxbox-update_configs -rc "; + commandargs += init_file; + +#ifdef HAVE_GETPID + // add the fluxbox pid so fbuc can have us reload rc if necessary + pid_t bpid = getpid(); + char intbuff[64]; + sprintf(intbuff, "%d", bpid); + commandargs += " -pid "; + commandargs += intbuff; +#endif // HAVE_GETPID + + FbCommands::ExecuteCmd fbuc(commandargs, 0); + fbuc.execute(); + } + } void Fluxbox::handleEvent(XEvent * const e) { @@ -936,59 +958,28 @@ void Fluxbox::handleEvent(XEvent * const e) { } void Fluxbox::handleButtonEvent(XButtonEvent &be) { + m_last_time = be.time; - switch (be.type) { - case ButtonPress: { - m_last_time = be.time; - - BScreen *screen = searchScreen(be.window); - if (screen == 0) - break; // end case - - screen->hideMenus(); + BScreen *screen = searchScreen(be.window); + if (be.type == ButtonRelease || !screen) + // no bindings for this type yet + return; - // strip num/caps/scroll-lock and - // see if we're using any other modifier, - // if we're we shouldn't show the root menu - // this could happen if we're resizing aterm for instance - if (FbTk::KeyUtil::instance().cleanMods(be.state) != 0) - return; + if (be.button == 1 && !screen->isRootColormapInstalled()) + screen->imageControl().installRootColormap(); - if (be.button == 1) { - if (! screen->isRootColormapInstalled()) - screen->imageControl().installRootColormap(); - // hide menus - if (screen->rootMenu().isVisible()) - screen->rootMenu().hide(); - if (screen->workspaceMenu().isVisible()) - screen->workspaceMenu().hide(); - - } else if (be.button == 2) { - FbCommands::ShowWorkspaceMenuCmd cmd; - cmd.execute(); - } else if (be.button == 3) { - FbCommands::ShowRootMenuCmd cmd; - cmd.execute(); - } else if (screen->isDesktopWheeling() && be.button == 4) { - if(screen->isReverseWheeling()) { - screen->prevWorkspace(1); - } else { - screen->nextWorkspace(1); - } - } else if (screen->isDesktopWheeling() && be.button == 5) { - if(screen->isReverseWheeling()) { - screen->nextWorkspace(1); - } else { - screen->prevWorkspace(1); - } - } - - } break; - case ButtonRelease: - m_last_time = be.time; - break; - default: - break; + // see if we need to keep watching for key releases + BScreen *old_watching_screen = m_watching_screen; + m_watching_screen = 0; + if (!m_key->doAction(be.type, be.state, be.button)) + // no command run, so could still be cycling + m_watching_screen = old_watching_screen; + else if (old_watching_screen && + m_watching_screen != old_watching_screen) { + // no longer need to watch old screen, so stop cycling + old_watching_screen->notifyReleasedKeys(); + if (!m_watching_screen) + XUngrabKeyboard(FbTk::App::instance()->display(), CurrentTime); } } @@ -1126,11 +1117,12 @@ void Fluxbox::handleKeyEvent(XKeyEvent &ke) { case KeyPress: // see if we need to keep watching for key releases m_watching_screen = 0; - if (!m_key->doAction(ke)) // could still be cycling + if (!m_key->doAction(ke.type, ke.state, ke.keycode)) + // no command run, so could still be cycling m_watching_screen = old_watching_screen; else if (old_watching_screen && m_watching_screen != old_watching_screen) { - old_watching_screen->notifyReleasedKeys(ke); + old_watching_screen->notifyReleasedKeys(); if (!m_watching_screen) XUngrabKeyboard(FbTk::App::instance()->display(), CurrentTime); } @@ -1148,7 +1140,7 @@ void Fluxbox::handleKeyEvent(XKeyEvent &ke) { if ((m_watch_keyrelease & state) == 0) { - m_watching_screen->notifyReleasedKeys(ke); + m_watching_screen->notifyReleasedKeys(); XUngrabKeyboard(FbTk::App::instance()->display(), CurrentTime); // once they are released, we drop the watch diff --git a/util/Makefile.am b/util/Makefile.am index 53a61d7..263c456 100644 --- a/util/Makefile.am +++ b/util/Makefile.am @@ -2,10 +2,13 @@ SUBDIRS= fbrun INCLUDES= -I$(top_srcdir)/src -I$(top_srcdir)/src/FbTk bin_SCRIPTS= fbsetbg fluxbox-generate_menu startfluxbox -bin_PROGRAMS= fbsetroot +bin_PROGRAMS= fbsetroot fluxbox-update_configs fbsetroot_SOURCES= fbsetroot.cc fbsetroot.hh fbsetroot_LDADD=../src/FbRootWindow.o ../src/FbAtoms.o \ ../src/FbTk/libFbTk.a +fluxbox_update_configs_SOURCES= fluxbox-update_configs.cc +fluxbox_update_configs_LDADD= ../src/defaults.o ../src/Resources.o \ + ../src/FbTk/libFbTk.a MAINTAINERCLEANFILES= Makefile.in EXTRA_DIST= fbsetbg fluxbox-generate_menu.in \ @@ -22,6 +25,9 @@ clean-local: fbsetroot.o: fbsetroot.cc ../config.h $(srcdir)/fbsetroot.hh \ $(top_srcdir)/src/FbRootWindow.hh $(top_srcdir)/src/FbAtoms.hh +fluxbox-update_configs.o: fluxbox-update_configs.cc ../config.h \ + $(top_srcdir)/src/defaults.hh + startfluxbox: startfluxbox.in @regex_cmd@ -e "s,@pkgdatadir@,$(pkgdatadir),g" \ -e "s,@pkgbindir@,$(bindir),g" \ @@ -40,3 +46,7 @@ fluxbox-generate_menu: fluxbox-generate_menu.in cd ../src && ${MAKE} FbRootWindow.o ../src/FbAtoms.o: cd ../src && ${MAKE} FbAtoms.o +../src/defaults.o: + cd ../src && ${MAKE} defaults.o +../src/Resources.o: + cd ../src && ${MAKE} Resources.o diff --git a/util/fluxbox-update_configs.cc b/util/fluxbox-update_configs.cc new file mode 100644 index 0000000..de1fbb9 --- /dev/null +++ b/util/fluxbox-update_configs.cc @@ -0,0 +1,197 @@ +// fluxbox-update_configs.cc +// Copyright (c) 2007 Fluxbox Team (fluxgen at fluxbox dot org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#include "../src/FbTk/I18n.hh" +#include "../src/FbTk/Resource.hh" +#include "../src/FbTk/StringUtil.hh" + +#include "../src/defaults.hh" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif // HAVE_CONFIG_H + +#ifdef HAVE_SIGNAL_H +#include +#endif // HAVE_SIGNAL_H + +//use GNU extensions +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif // _GNU_SOURCE + +#ifdef HAVE_CSTDIO + #include +#else + #include +#endif +#ifdef HAVE_CSTDLIB + #include +#else + #include +#endif +#ifdef HAVE_CSTRING + #include +#else + #include +#endif +#include +#include + +using std::cout; +using std::cerr; +using std::endl; +using std::string; +using std::ifstream; +using std::ofstream; + +#define VERSION 1 + +int run_updates(int old_version, FbTk::ResourceManager rm) { + int new_version = old_version; + + if (old_version < 1) { // add mouse events to keys file + FbTk::Resource rc_keyfile(rm, DEFAULTKEYSFILE, + "session.keyFile", "Session.KeyFile"); + string keyfilename = FbTk::StringUtil::expandFilename(*rc_keyfile); + + // ok, I don't know anything about file handling in c++ + // what's it to you?!?! + // I assume there should be some error handling in here, but I sure + // don't know how, and I don't have documentation + + ifstream in_keyfile(keyfilename.c_str()); + string whole_keyfile = ""; + + while (!in_keyfile.eof()) { + string linebuffer; + + getline(in_keyfile, linebuffer); + whole_keyfile += linebuffer + "\n"; + } + in_keyfile.close(); + + ofstream out_keyfile(keyfilename.c_str()); + // let's put our new keybindings first, so they're easy to find + out_keyfile << "!mouse actions added by fluxbox-update_configs" << endl + << "OnDesktop Mouse1 :hideMenus" << endl + << "OnDesktop Mouse2 :workspaceMenu" << endl + << "OnDesktop Mouse3 :rootMenu" << endl; + + // scrolling on desktop needs to match user's desktop wheeling settings + // hmmm, what are the odds that somebody wants this to be different on + // different screens? the ability is going away until we make per-screen + // keys files, anyway, so let's just use the first screen's setting + FbTk::Resource rc_wheeling(rm, true, + "session.screen0.desktopwheeling", + "Session.Screen0.DesktopWheeling"); + FbTk::Resource rc_reverse(rm, false, + "session.screen0.reversewheeling", + "Session.Screen0.ReverseWheeling"); + if (*rc_wheeling) { + if (*rc_reverse) { // if you ask me, this should have been default + out_keyfile << "OnDesktop Mouse4 :prevWorkspace" << endl + << "OnDesktop Mouse5 :nextWorkspace" << endl; + } else { + out_keyfile << "OnDesktop Mouse4 :nextWorkspace" << endl + << "OnDesktop Mouse5 :prevWorkspace" << endl; + } + } + out_keyfile << endl; // just for good looks + + // now, restore user's old keybindings + out_keyfile << whole_keyfile; + new_version = 1; + } + + return new_version; +} + +int main(int argc, char **argv) { + string rc_filename; + int i = 1; + pid_t fb_pid = 0; + + FbTk::NLSInit("fluxbox.cat"); + _FB_USES_NLS; + + for (; i < argc; i++) { + if (strcmp(argv[i], "-rc") == 0) { + // look for alternative rc file to use + + if ((++i) >= argc) { + cerr<<_FB_CONSOLETEXT(main, RCRequiresArg, + "error: '-rc' requires an argument", "the -rc option requires a file argument")<= argc) { + // need translations for this, too + cerr<<"the -pid option requires a numeric argument"<\t\t\tuse alternate resource file.\n" + << " -pid \t\t\ttell fluxbox to reload configuration.\n" + << " -help\t\t\t\tdisplay this help text and exit.\n\n" + << endl; + exit(0); + } + } + + FbTk::ResourceManager resource_manager(rc_filename.c_str(),false); + if (rc_filename.empty() || !resource_manager.load(rc_filename.c_str())) { + // couldn't load rc file + if (!rc_filename.empty()) { + cerr<<_FB_CONSOLETEXT(Fluxbox, CantLoadRCFile, "Failed to load database", "Failed trying to read rc file")<<":"< config_version(resource_manager, 0, + "session.configVersion", "Session.ConfigVersion"); + int old_version = *config_version; + int new_version = run_updates(old_version, resource_manager); + if (new_version > old_version) { + config_version = new_version; + resource_manager.save(rc_filename.c_str(), rc_filename.c_str()); + +#ifdef HAVE_SIGNAL_H + // if we were given a fluxbox pid, send it a reconfigure signal + if (fb_pid > 0) + kill(fb_pid, SIGUSR2); +#endif // HAVE_SIGNAL_H + + } + + return 0; +} -- cgit v0.11.2