added mouse bindings to the keys file

This commit is contained in:
markt 2007-02-09 18:13:01 +00:00
parent 93d8310c0c
commit 6fdda1a31d
16 changed files with 433 additions and 127 deletions

View file

@ -1,5 +1,18 @@
(Format: Year/Month/Day) (Format: Year/Month/Day)
Changes for 1.0rc3: 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: *07/02/06:
* Wrong window was being raised when attaching an unfocused window (Mark) * Wrong window was being raised when attaching an unfocused window (Mark)
Window.cc Window.cc

View file

@ -33,3 +33,4 @@ session.colorsPerChannel: 4
session.doubleClickInterval: 250 session.doubleClickInterval: 250
session.cacheMax: 200 session.cacheMax: 200
session.imageDither: True session.imageDither: True
session.configVersion: 1

View file

@ -1,3 +1,9 @@
OnDesktop Mouse1 :HideMenus
OnDesktop Mouse2 :WorkspaceMenu
OnDesktop Mouse3 :RootMenu
OnDesktop Mouse4 :NextWorkspace
OnDesktop Mouse5 :PrevWorkspace
Mod1 Tab :NextWindow Mod1 Tab :NextWindow
Mod1 Shift Tab :PrevWindow Mod1 Shift Tab :PrevWindow
Mod1 F1 :Workspace 1 Mod1 F1 :Workspace 1

View file

@ -77,6 +77,7 @@ FbCommandFactory::FbCommandFactory() {
"focusleft", "focusleft",
"focusright", "focusright",
"fullscreen", "fullscreen",
"hidemenus",
"iconify", "iconify",
"keymode", "keymode",
"killwindow", "killwindow",
@ -433,6 +434,8 @@ FbTk::Command *FbCommandFactory::stringToCommand(const std::string &command,
return new ArrangeWindowsCmd(); return new ArrangeWindowsCmd();
else if (command == "showdesktop") else if (command == "showdesktop")
return new ShowDesktopCmd(); return new ShowDesktopCmd();
else if (command == "hidemenus")
return new HideMenuCmd();
else if (command == "rootmenu") else if (command == "rootmenu")
return new ShowRootMenuCmd(); return new ShowRootMenuCmd();
else if (command == "workspacemenu") else if (command == "workspacemenu")

View file

@ -260,6 +260,15 @@ void KeyModeCmd::execute() {
Fluxbox::instance()->keys()->keyMode(m_keymode); 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() { void ShowRootMenuCmd::execute() {
BScreen *screen = Fluxbox::instance()->mouseScreen(); BScreen *screen = Fluxbox::instance()->mouseScreen();
if (screen == 0) if (screen == 0)

View file

@ -113,6 +113,11 @@ private:
std::string m_end_args; std::string m_end_args;
}; };
class HideMenuCmd: public FbTk::Command {
public:
void execute();
};
class ShowRootMenuCmd: public FbTk::Command { class ShowRootMenuCmd: public FbTk::Command {
public: public:
void execute(); void execute();

View file

@ -138,7 +138,7 @@ void KeyUtil::grabButton(unsigned int button, unsigned int mod, Window win,
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
XGrabButton(display, button, mod | (i & 1 ? capsmod : 0) | XGrabButton(display, button, mod | (i & 1 ? capsmod : 0) |
(i & 2 ? nummod : 0) | (i & 4 ? scrollmod : 0), (i & 2 ? nummod : 0) | (i & 4 ? scrollmod : 0),
win, True, event_mask, GrabModeAsync, GrabModeAsync, win, False, event_mask, GrabModeAsync, GrabModeAsync,
None, cursor); None, cursor);
} }
@ -180,6 +180,11 @@ void KeyUtil::ungrabKeys(Window win) {
XUngrabKey(display, AnyKey, AnyModifier, 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) { unsigned int KeyUtil::keycodeToModmask(unsigned int keycode) {
XModifierKeymap *modmap = instance().m_modmap; XModifierKeymap *modmap = instance().m_modmap;

View file

@ -62,6 +62,7 @@ public:
ungrabs all keys ungrabs all keys
*/ */
static void ungrabKeys(Window win); static void ungrabKeys(Window win);
static void ungrabButtons(Window win);
/** /**
Strip out modifiers we want to ignore Strip out modifiers we want to ignore

View file

@ -114,6 +114,7 @@ Keys::Keys():
Keys::~Keys() { Keys::~Keys() {
ungrabKeys(); ungrabKeys();
ungrabButtons();
deleteTree(); deleteTree();
} }
@ -140,6 +141,23 @@ void Keys::ungrabKeys() {
FbTk::KeyUtil::ungrabKeys(*it); FbTk::KeyUtil::ungrabKeys(*it);
} }
void Keys::grabButton(unsigned int button, unsigned int mod) {
std::list<Window>::iterator it = m_window_list.begin();
std::list<Window>::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<Window>::iterator it = m_window_list.begin();
std::list<Window>::iterator it_end = m_window_list.end();
for (; it != it_end; ++it)
FbTk::KeyUtil::ungrabButtons(*it);
}
/** /**
Load and grab keys Load and grab keys
TODO: error checking TODO: error checking
@ -152,7 +170,7 @@ bool Keys::load(const char *filename) {
//free memory of previous grabs //free memory of previous grabs
deleteTree(); deleteTree();
m_map["default:"] = new t_key(0,0); m_map["default:"] = new t_key(0,0,0,0);
FbTk::App::instance()->sync(false); FbTk::App::instance()->sync(false);
@ -211,6 +229,7 @@ bool Keys::addBinding(const string &linebuffer) {
return true; // still a valid line. return true; // still a valid line.
unsigned int key = 0, mod = 0; unsigned int key = 0, mod = 0;
int type = 0, context = 0;
size_t argc = 0; size_t argc = 0;
t_key *current_key=m_map["default:"]; t_key *current_key=m_map["default:"];
t_key *first_new_keylist = current_key, *first_new_key=0; t_key *first_new_keylist = current_key, *first_new_key=0;
@ -219,7 +238,7 @@ bool Keys::addBinding(const string &linebuffer) {
argc++; argc++;
keyspace_t::iterator it = m_map.find(val[0]); keyspace_t::iterator it = m_map.find(val[0]);
if (it == m_map.end()) 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]]; current_key = m_map[val[0]];
} }
// for each argument // for each argument
@ -230,41 +249,53 @@ bool Keys::addBinding(const string &linebuffer) {
int tmpmod = FbTk::KeyUtil::getModifier(val[argc].c_str()); int tmpmod = FbTk::KeyUtil::getModifier(val[argc].c_str());
if(tmpmod) if(tmpmod)
mod |= tmpmod; //If it's a modifier 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())) { 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: // keycode covers the following three two-byte cases:
// 0x - hex // 0x - hex
// +[1-9] - number between +1 and +9 // +[1-9] - number between +1 and +9
// numbers 10 and above // numbers 10 and above
// //
if (val[argc].size() > 1 && (isdigit(val[argc][0]) && } else if (val[argc].size() > 1 && (isdigit(val[argc][0]) &&
(isdigit(val[argc][1]) || val[argc][1] == 'x') || (isdigit(val[argc][1]) || val[argc][1] == 'x') ||
val[argc][0] == '+' && isdigit(val[argc][1])) ) { val[argc][0] == '+' && isdigit(val[argc][1])) ) {
key = strtoul(val[argc].c_str(), NULL, 0); key = strtoul(val[argc].c_str(), NULL, 0);
type = KeyPress;
if (errno == EINVAL || errno == ERANGE) if (errno == EINVAL || errno == ERANGE)
key = 0; key = 0;
} else // convert from string symbol } else { // convert from string symbol
key = FbTk::KeyUtil::getKey(val[argc].c_str()); key = FbTk::KeyUtil::getKey(val[argc].c_str());
type = KeyPress;
}
if (key == 0) if (key == 0)
return false; return false;
if (!first_new_key) { if (!first_new_key) {
first_new_keylist = current_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) { 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; current_key = first_new_key;
} else if (*current_key->m_command) // already being used } else if (*current_key->m_command) // already being used
return false; return false;
} else { } 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->keylist.push_back(temp_key);
current_key = temp_key; current_key = temp_key;
} }
mod = 0; mod = 0;
key = 0; key = 0;
type = 0;
context = 0;
} }
} else { // parse command line } else { // parse command line
@ -291,36 +322,43 @@ bool Keys::addBinding(const string &linebuffer) {
} }
// return true if bound to a command, else false // return true if bound to a command, else false
bool Keys::doAction(XKeyEvent &ke) { bool Keys::doAction(int type, unsigned int mods, unsigned int key) {
ke.state = FbTk::KeyUtil::instance().cleanMods(ke.state);
static t_key* next_key = m_keylist; static t_key* next_key = m_keylist;
if (!next_key) if (!next_key)
next_key = m_keylist; 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 // need to save this for emacs-style keybindings
static t_key *saved_keymode = 0; 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 if (temp_key && temp_key->keylist.size()) { // emacs-style
if (!saved_keymode)
saved_keymode = m_keylist; saved_keymode = m_keylist;
next_key = temp_key; next_key = temp_key;
setKeyMode(next_key); setKeyMode(next_key);
// grab "None Escape" to exit keychain in the middle
unsigned int esc = FbTk::KeyUtil::getKey("Escape");
grabKey(esc,0); grabKey(esc,0);
return true; return true;
} }
if (!temp_key || *temp_key->m_command == 0) { if (!temp_key || *temp_key->m_command == 0) {
if (type == KeyPress && key == esc && mods == 0) {
// if we're in the middle of an emacs-style keychain, exit it
next_key = 0; next_key = 0;
if (saved_keymode) { if (saved_keymode) {
setKeyMode(saved_keymode); setKeyMode(saved_keymode);
saved_keymode = 0; saved_keymode = 0;
} }
}
return false; return false;
} }
temp_key->m_command->execute(); temp_key->m_command->execute();
if (saved_keymode) { if (saved_keymode) {
if (next_key == m_keylist) // don't reset keymode if command changed it 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) { void Keys::setKeyMode(t_key *keyMode) {
ungrabKeys(); ungrabKeys();
ungrabButtons();
keylist_t::iterator it = keyMode->keylist.begin(); keylist_t::iterator it = keyMode->keylist.begin();
keylist_t::iterator it_end = keyMode->keylist.end(); keylist_t::iterator it_end = keyMode->keylist.end();
for (; it != it_end; ++it) for (; it != it_end; ++it) {
if ((*it)->type == KeyPress)
grabKey((*it)->key,(*it)->mod); 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; m_keylist = keyMode;
} }
Keys::t_key::t_key(unsigned int key_, unsigned int mod_, FbTk::RefCount<FbTk::Command> command) { Keys::t_key::t_key(int type_, unsigned int mod_, unsigned int key_,
int context_, FbTk::RefCount<FbTk::Command> command) {
key = key_; key = key_;
mod = mod_; mod = mod_;
type = type_;
context = context_ ? context_ : GLOBAL;
m_command = command; m_command = command;
} }
Keys::t_key::t_key(t_key *k) { Keys::t_key::t_key(t_key *k) {
key = k->key; key = k->key;
mod = k->mod; mod = k->mod;
type = k->type;
context = k->context;
m_command = k->m_command; m_command = k->m_command;
} }

View file

@ -38,6 +38,21 @@
class Keys:private FbTk::NotCopyable { class Keys:private FbTk::NotCopyable {
public: 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 Constructor
@param display display connection @param display display connection
@ -65,7 +80,7 @@ public:
/** /**
do action from XKeyEvent; return false if not bound to anything 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 Reload configuration from filename
@ -79,6 +94,8 @@ private:
void grabKey(unsigned int key, unsigned int mod); void grabKey(unsigned int key, unsigned int mod);
void ungrabKeys(); void ungrabKeys();
void grabButton(unsigned int button, unsigned int mod);
void ungrabButtons();
std::string m_filename; std::string m_filename;
@ -87,33 +104,27 @@ private:
class t_key { class t_key {
public: public:
t_key(unsigned int key, unsigned int mod, t_key(int type, unsigned int mod, unsigned int key, int context,
FbTk::RefCount<FbTk::Command> command = FbTk::RefCount<FbTk::Command>(0)); FbTk::RefCount<FbTk::Command> command = FbTk::RefCount<FbTk::Command>(0));
t_key(t_key *k); t_key(t_key *k);
~t_key(); ~t_key();
t_key *find(unsigned int key_, unsigned int mod_) { t_key *find(int type_, unsigned int mod_, unsigned int key_,
int context_) {
for (size_t i = 0; i < keylist.size(); i++) { for (size_t i = 0; i < keylist.size(); i++) {
if (keylist[i]->key == key_ && keylist[i]->mod == FbTk::KeyUtil::instance().isolateModifierMask(mod_)) if (keylist[i]->type == type_ && keylist[i]->key == key_ &&
return keylist[i]; (keylist[i]->context & context_) > 0 && keylist[i]->mod ==
} FbTk::KeyUtil::instance().isolateModifierMask(mod_))
return 0;
}
t_key *find(XKeyEvent &ke) {
for (size_t i = 0; i < keylist.size(); i++) {
if (keylist[i]->key == ke.keycode &&
keylist[i]->mod == FbTk::KeyUtil::instance().isolateModifierMask(ke.state))
return keylist[i]; return keylist[i];
} }
return 0; return 0;
} }
bool operator == (XKeyEvent &ke) const {
return (mod == FbTk::KeyUtil::instance().isolateModifierMask(ke.state) && key == ke.keycode);
}
FbTk::RefCount<FbTk::Command> m_command; FbTk::RefCount<FbTk::Command> 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; unsigned int mod;
keylist_t keylist; keylist_t keylist;
}; };

View file

@ -2060,7 +2060,7 @@ void BScreen::renderPosWindow() {
/** /**
Called when a set of watched modifiers has been released Called when a set of watched modifiers has been released
*/ */
void BScreen::notifyReleasedKeys(XKeyEvent &ke) { void BScreen::notifyReleasedKeys() {
focusControl().stopCyclingFocus(); focusControl().stopCyclingFocus();
} }

View file

@ -294,7 +294,7 @@ public:
void showGeometry(int width, int height); void showGeometry(int width, int height);
void hideGeometry(); void hideGeometry();
void notifyReleasedKeys(XKeyEvent &ke); void notifyReleasedKeys();
void setLayer(FbTk::XLayerItem &item, int layernum); void setLayer(FbTk::XLayerItem &item, int layernum);
// remove? no, items are never removed from their layer until they die // remove? no, items are never removed from their layer until they die

View file

@ -42,44 +42,48 @@
#include <functional> #include <functional>
void NextWindowCmd::execute() { void NextWindowCmd::execute() {
BScreen *screen = Fluxbox::instance()->keyScreen();
if (screen != 0) {
Fluxbox *fb = Fluxbox::instance(); Fluxbox *fb = Fluxbox::instance();
// special case for commands from key events BScreen *screen = fb->keyScreen();
if (fb->lastEvent().type == KeyPress) { if (screen != 0) {
unsigned int mods = FbTk::KeyUtil::instance().cleanMods(fb->lastEvent().xkey.state); // get modifiers from event that causes this for focus order cycling
mods = FbTk::KeyUtil::instance().isolateModifierMask(mods); 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 if (mods == 0) // can't stacked cycle unless there is a mod to grab
screen->focusControl().nextFocus(m_option | FocusControl::CYCLELINEAR); screen->focusControl().nextFocus(m_option | FocusControl::CYCLELINEAR);
else { else {
// if stacked cycling, then set a watch for // if stacked cycling, then set a watch for
// the release of exactly these modifiers // the release of exactly these modifiers
Fluxbox::instance()->watchKeyRelease(*screen, mods); fb->watchKeyRelease(*screen, mods);
screen->focusControl().nextFocus(m_option); screen->focusControl().nextFocus(m_option);
} }
} else
screen->focusControl().nextFocus(m_option | FocusControl::CYCLELINEAR);
} }
} }
void PrevWindowCmd::execute() { void PrevWindowCmd::execute() {
BScreen *screen = Fluxbox::instance()->keyScreen();
if (screen != 0) {
Fluxbox *fb = Fluxbox::instance(); Fluxbox *fb = Fluxbox::instance();
// special case for commands from key events BScreen *screen = fb->keyScreen();
if (fb->lastEvent().type == KeyPress) { if (screen != 0) {
unsigned int mods = FbTk::KeyUtil::instance().cleanMods(fb->lastEvent().xkey.state); // get modifiers from event that causes this for focus order cycling
mods = FbTk::KeyUtil::instance().isolateModifierMask(mods); 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 if (mods == 0) // can't stacked cycle unless there is a mod to grab
screen->focusControl().prevFocus(m_option | FocusControl::CYCLELINEAR); screen->focusControl().prevFocus(m_option | FocusControl::CYCLELINEAR);
else { else {
// if stacked cycling, then set a watch for // if stacked cycling, then set a watch for
// the release of exactly these modifiers // the release of exactly these modifiers
Fluxbox::instance()->watchKeyRelease(*screen, mods); fb->watchKeyRelease(*screen, mods);
screen->focusControl().prevFocus(m_option); screen->focusControl().prevFocus(m_option);
} }
} else
screen->focusControl().nextFocus(m_option | FocusControl::CYCLELINEAR);
} }
} }

View file

@ -649,6 +649,28 @@ void Fluxbox::setupConfigFiles() {
if (create_init) if (create_init)
FbTk::FileUtil::copyFile(DEFAULT_INITFILE, init_file.c_str()); FbTk::FileUtil::copyFile(DEFAULT_INITFILE, init_file.c_str());
#define CONFIG_VERSION 1
FbTk::Resource<int> 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) { void Fluxbox::handleEvent(XEvent * const e) {
@ -936,59 +958,28 @@ void Fluxbox::handleEvent(XEvent * const e) {
} }
void Fluxbox::handleButtonEvent(XButtonEvent &be) { void Fluxbox::handleButtonEvent(XButtonEvent &be) {
switch (be.type) {
case ButtonPress: {
m_last_time = be.time; m_last_time = be.time;
BScreen *screen = searchScreen(be.window); BScreen *screen = searchScreen(be.window);
if (screen == 0) if (be.type == ButtonRelease || !screen)
break; // end case // no bindings for this type yet
screen->hideMenus();
// 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; return;
if (be.button == 1) { if (be.button == 1 && !screen->isRootColormapInstalled())
if (! screen->isRootColormapInstalled())
screen->imageControl().installRootColormap(); screen->imageControl().installRootColormap();
// hide menus
if (screen->rootMenu().isVisible())
screen->rootMenu().hide();
if (screen->workspaceMenu().isVisible())
screen->workspaceMenu().hide();
} else if (be.button == 2) { // see if we need to keep watching for key releases
FbCommands::ShowWorkspaceMenuCmd cmd; BScreen *old_watching_screen = m_watching_screen;
cmd.execute(); m_watching_screen = 0;
} else if (be.button == 3) { if (!m_key->doAction(be.type, be.state, be.button))
FbCommands::ShowRootMenuCmd cmd; // no command run, so could still be cycling
cmd.execute(); m_watching_screen = old_watching_screen;
} else if (screen->isDesktopWheeling() && be.button == 4) { else if (old_watching_screen &&
if(screen->isReverseWheeling()) { m_watching_screen != old_watching_screen) {
screen->prevWorkspace(1); // no longer need to watch old screen, so stop cycling
} else { old_watching_screen->notifyReleasedKeys();
screen->nextWorkspace(1); if (!m_watching_screen)
} XUngrabKeyboard(FbTk::App::instance()->display(), CurrentTime);
} 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;
} }
} }
@ -1126,11 +1117,12 @@ void Fluxbox::handleKeyEvent(XKeyEvent &ke) {
case KeyPress: case KeyPress:
// see if we need to keep watching for key releases // see if we need to keep watching for key releases
m_watching_screen = 0; 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; m_watching_screen = old_watching_screen;
else if (old_watching_screen && else if (old_watching_screen &&
m_watching_screen != old_watching_screen) { m_watching_screen != old_watching_screen) {
old_watching_screen->notifyReleasedKeys(ke); old_watching_screen->notifyReleasedKeys();
if (!m_watching_screen) if (!m_watching_screen)
XUngrabKeyboard(FbTk::App::instance()->display(), CurrentTime); XUngrabKeyboard(FbTk::App::instance()->display(), CurrentTime);
} }
@ -1148,7 +1140,7 @@ void Fluxbox::handleKeyEvent(XKeyEvent &ke) {
if ((m_watch_keyrelease & state) == 0) { if ((m_watch_keyrelease & state) == 0) {
m_watching_screen->notifyReleasedKeys(ke); m_watching_screen->notifyReleasedKeys();
XUngrabKeyboard(FbTk::App::instance()->display(), CurrentTime); XUngrabKeyboard(FbTk::App::instance()->display(), CurrentTime);
// once they are released, we drop the watch // once they are released, we drop the watch

View file

@ -2,10 +2,13 @@
SUBDIRS= fbrun SUBDIRS= fbrun
INCLUDES= -I$(top_srcdir)/src -I$(top_srcdir)/src/FbTk INCLUDES= -I$(top_srcdir)/src -I$(top_srcdir)/src/FbTk
bin_SCRIPTS= fbsetbg fluxbox-generate_menu startfluxbox bin_SCRIPTS= fbsetbg fluxbox-generate_menu startfluxbox
bin_PROGRAMS= fbsetroot bin_PROGRAMS= fbsetroot fluxbox-update_configs
fbsetroot_SOURCES= fbsetroot.cc fbsetroot.hh fbsetroot_SOURCES= fbsetroot.cc fbsetroot.hh
fbsetroot_LDADD=../src/FbRootWindow.o ../src/FbAtoms.o \ fbsetroot_LDADD=../src/FbRootWindow.o ../src/FbAtoms.o \
../src/FbTk/libFbTk.a ../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 MAINTAINERCLEANFILES= Makefile.in
EXTRA_DIST= fbsetbg fluxbox-generate_menu.in \ EXTRA_DIST= fbsetbg fluxbox-generate_menu.in \
@ -22,6 +25,9 @@ clean-local:
fbsetroot.o: fbsetroot.cc ../config.h $(srcdir)/fbsetroot.hh \ fbsetroot.o: fbsetroot.cc ../config.h $(srcdir)/fbsetroot.hh \
$(top_srcdir)/src/FbRootWindow.hh $(top_srcdir)/src/FbAtoms.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 startfluxbox: startfluxbox.in
@regex_cmd@ -e "s,@pkgdatadir@,$(pkgdatadir),g" \ @regex_cmd@ -e "s,@pkgdatadir@,$(pkgdatadir),g" \
-e "s,@pkgbindir@,$(bindir),g" \ -e "s,@pkgbindir@,$(bindir),g" \
@ -40,3 +46,7 @@ fluxbox-generate_menu: fluxbox-generate_menu.in
cd ../src && ${MAKE} FbRootWindow.o cd ../src && ${MAKE} FbRootWindow.o
../src/FbAtoms.o: ../src/FbAtoms.o:
cd ../src && ${MAKE} FbAtoms.o cd ../src && ${MAKE} FbAtoms.o
../src/defaults.o:
cd ../src && ${MAKE} defaults.o
../src/Resources.o:
cd ../src && ${MAKE} Resources.o

View file

@ -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 <signal.h>
#endif // HAVE_SIGNAL_H
//use GNU extensions
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif // _GNU_SOURCE
#ifdef HAVE_CSTDIO
#include <cstdio>
#else
#include <stdio.h>
#endif
#ifdef HAVE_CSTDLIB
#include <cstdlib>
#else
#include <stdlib.h>
#endif
#ifdef HAVE_CSTRING
#include <cstring>
#else
#include <string.h>
#endif
#include <iostream>
#include <fstream>
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<string> 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<bool> rc_wheeling(rm, true,
"session.screen0.desktopwheeling",
"Session.Screen0.DesktopWheeling");
FbTk::Resource<bool> 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")<<endl;
exit(1);
}
rc_filename = argv[i];
} else if (strcmp(argv[i], "-pid") == 0) {
if ((++i) >= argc) {
// need translations for this, too
cerr<<"the -pid option requires a numeric argument"<<endl;
} else
fb_pid = atoi(argv[i]);
} else if (strcmp(argv[i], "-help") == 0 || strcmp(argv[i], "-h") == 0) {
// no NLS translations yet -- we'll just have to use English for now
cout << " -rc <string>\t\t\tuse alternate resource file.\n"
<< " -pid <int>\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")<<":"<<rc_filename<<endl;
cerr<<_FB_CONSOLETEXT(Fluxbox, CantLoadRCFileTrying, "Retrying with", "Retrying rc file loading with (the following file)")<<": "<<DEFAULT_INITFILE<<endl;
}
// couldn't load default rc file, either
if (!resource_manager.load(DEFAULT_INITFILE)) {
cerr<<_FB_CONSOLETEXT(Fluxbox, CantLoadRCFile, "Failed to load database", "")<<": "<<DEFAULT_INITFILE<<endl;
exit(1); // this is a fatal error for us
}
}
// run updates here
// I feel like putting this in a separate function for no apparent reason
FbTk::Resource<int> 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;
}