added mouse bindings to the keys file
This commit is contained in:
parent
93d8310c0c
commit
6fdda1a31d
16 changed files with 433 additions and 127 deletions
13
ChangeLog
13
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
|
||||
|
|
|
@ -33,3 +33,4 @@ session.colorsPerChannel: 4
|
|||
session.doubleClickInterval: 250
|
||||
session.cacheMax: 200
|
||||
session.imageDither: True
|
||||
session.configVersion: 1
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
79
src/Keys.cc
79
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<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
|
||||
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]) &&
|
||||
} 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
|
||||
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) {
|
||||
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)
|
||||
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<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_;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
43
src/Keys.hh
43
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<FbTk::Command> command = FbTk::RefCount<FbTk::Command>(0));
|
||||
t_key(t_key *k);
|
||||
~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++) {
|
||||
if (keylist[i]->key == key_ && keylist[i]->mod == FbTk::KeyUtil::instance().isolateModifierMask(mod_))
|
||||
return keylist[i];
|
||||
}
|
||||
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))
|
||||
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<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;
|
||||
keylist_t keylist;
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -42,44 +42,48 @@
|
|||
#include <functional>
|
||||
|
||||
void NextWindowCmd::execute() {
|
||||
BScreen *screen = Fluxbox::instance()->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);
|
||||
BScreen *screen = fb->keyScreen();
|
||||
if (screen != 0) {
|
||||
// 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
|
||||
Fluxbox::instance()->watchKeyRelease(*screen, mods);
|
||||
fb->watchKeyRelease(*screen, mods);
|
||||
screen->focusControl().nextFocus(m_option);
|
||||
}
|
||||
} else
|
||||
screen->focusControl().nextFocus(m_option | FocusControl::CYCLELINEAR);
|
||||
}
|
||||
}
|
||||
|
||||
void PrevWindowCmd::execute() {
|
||||
BScreen *screen = Fluxbox::instance()->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);
|
||||
BScreen *screen = fb->keyScreen();
|
||||
if (screen != 0) {
|
||||
// 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
|
||||
Fluxbox::instance()->watchKeyRelease(*screen, mods);
|
||||
fb->watchKeyRelease(*screen, mods);
|
||||
screen->focusControl().prevFocus(m_option);
|
||||
}
|
||||
} else
|
||||
screen->focusControl().nextFocus(m_option | FocusControl::CYCLELINEAR);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<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) {
|
||||
|
@ -936,59 +958,28 @@ void Fluxbox::handleEvent(XEvent * const e) {
|
|||
}
|
||||
|
||||
void Fluxbox::handleButtonEvent(XButtonEvent &be) {
|
||||
|
||||
switch (be.type) {
|
||||
case ButtonPress: {
|
||||
m_last_time = be.time;
|
||||
|
||||
BScreen *screen = searchScreen(be.window);
|
||||
if (screen == 0)
|
||||
break; // end case
|
||||
|
||||
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)
|
||||
if (be.type == ButtonRelease || !screen)
|
||||
// no bindings for this type yet
|
||||
return;
|
||||
|
||||
if (be.button == 1) {
|
||||
if (! screen->isRootColormapInstalled())
|
||||
if (be.button == 1 && !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
|
||||
|
|
|
@ -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
|
||||
|
|
197
util/fluxbox-update_configs.cc
Normal file
197
util/fluxbox-update_configs.cc
Normal 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;
|
||||
}
|
Loading…
Reference in a new issue