summaryrefslogtreecommitdiff
path: root/keybinds.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'keybinds.cpp')
-rw-r--r--keybinds.cpp144
1 files changed, 121 insertions, 23 deletions
diff --git a/keybinds.cpp b/keybinds.cpp
index 8448eed..b51bf6e 100644
--- a/keybinds.cpp
+++ b/keybinds.cpp
@@ -2,53 +2,98 @@
#include <X11/Xlib.h>
#include <iostream>
#include <sstream>
+#include <utility>
#include <vector>
+#include "commands.h"
#include "error.h"
#include "keybinds.h"
#include "util.h"
using std::string, std::cout, std::endl;
+bool Keybind::operator<(const Keybind &o) const {
+ if(key != o.key)
+ {
+ return key < o.key;
+ }
+ else return modifiers < o.modifiers;
+}
+bool Keybind::operator==(const Keybind &o) const {
+ return (key == o.key && modifiers == o.modifiers);
+}
+
KeybindsModule::KeybindsModule(CommandsModule& commandsModule, Config& cfg, Globals& globals, void (*updateMousePos)())
:commandsModule(commandsModule),
globals(globals),
cfg(cfg)
{
commandsModule.addCommand("bind", &KeybindsModule::bind, 2, {STR, STR_REST}, this);
+ commandsModule.addCommand("quitkey", &KeybindsModule::quitKey, 1, {STR}, this);
this->updateMousePos = updateMousePos;
+ keyMaps.insert({0, std::map<Keybind, KeyFunction>()});
+}
+
+void KeybindsModule::changeMap(int newMapID)
+{
+ if(currentMapID == newMapID)
+ return;
+ if(currentMapID != 0)
+ XUngrabKeyboard(globals.dpy, CurrentTime);
+ XUngrabButton(globals.dpy, AnyKey, AnyModifier, globals.root);
+ currentMapID = newMapID;
+ if(newMapID == 0)
+ {
+ for(std::pair<Keybind, KeyFunction> pair : getKeymap(currentMapID))
+ {
+ Keybind bind = pair.first;
+ KeyCode c = XKeysymToKeycode(globals.dpy, bind.key);
+ XGrabKey(globals.dpy, c, bind.modifiers, globals.root, false, GrabModeAsync, GrabModeAsync);
+ }
+ }
+ else
+ {
+ XGrabKeyboard(globals.dpy, globals.root, false, GrabModeAsync, GrabModeAsync, CurrentTime);
+ }
}
const void KeybindsModule::handleKeypress(XKeyEvent e)
{
if(e.same_screen!=1) return;
- //cout << "Key Pressed" << endl;
- //cout << "\tState: " << e.state << endl;
- //cout << "\tCode: " << XKeysymToString(XKeycodeToKeysym(globals.dpy, e.keycode, 0)) << endl;
+ // cout << "Key Pressed" << endl;
+ // cout << "\tState: " << e.state << endl;
+ // cout << "\tCode: " << XKeysymToString(XKeycodeToKeysym(globals.dpy, e.keycode, 0)) << endl;
updateMousePos();
const unsigned int masks = ShiftMask | ControlMask | Mod1Mask | Mod4Mask;
- for(Keybind bind : binds)
+ Keybind k = {XLookupKeysym(&e, 0), e.state & masks};
+ if(k == exitBind)
{
- if(bind.modifiers == (e.state & masks) && bind.key == XLookupKeysym(&e, 0))
+ changeMap(0);
+ }
+ else if(getKeymap(currentMapID).count(k) > 0)
+ {
+ KeyFunction& c = getKeymap(currentMapID).find(k)->second;
+ if(getKeymap(c.mapID).size() == 0)
+ {
+ commandsModule.runCommand(c.command);
+ changeMap(0);
+ }
+ else
{
- commandsModule.runCommand(bind.command);
+ XUngrabButton(globals.dpy, AnyKey, AnyModifier, globals.root);
+ changeMap(c.mapID);
}
}
+ else if(std::find(std::begin(ignoredKeys), std::end(ignoredKeys), e.keycode) == std::end(ignoredKeys))
+ {
+ changeMap(0);
+ }
}
-const void KeybindsModule::bind(const CommandArg* argv)
+Keybind KeybindsModule::getKeybind(string bindString)
{
- std::vector<Err> errs = commandsModule.checkCommand(argv[1].str);
- for(Err e : errs)
- {
- if(e.code != NOERR)
- {
- e.message = "Binding fail - " + e.message;
- throw e;
- }
- }
- std::vector<string> keys = split(argv[0].str, '+');
+ std::vector<string> keys = split(bindString, '+');
Keybind bind;
bind.modifiers = 0;
for(string key : keys)
@@ -75,19 +120,72 @@ const void KeybindsModule::bind(const CommandArg* argv)
bind.key = s;
if(bind.key == NoSymbol)
{
- throw Err(CFG_ERR_KEYBIND, "Keybind '" + string(argv[0].str) + "' is invalid!");
+ throw Err(CFG_ERR_KEYBIND, "Keybind '" + bindString + "' is invalid!");
continue;
}
}
}
- bind.command = argv[1].str;
- KeyCode c = XKeysymToKeycode(globals.dpy, bind.key);
- XGrabKey(globals.dpy, c, bind.modifiers, globals.root, False, GrabModeAsync, GrabModeAsync);
- binds.push_back(bind);
+ return bind;
+}
+
+const void KeybindsModule::bind(const CommandArg* argv)
+{
+ std::vector<Err> errs = commandsModule.checkCommand(argv[1].str);
+ for(Err e : errs)
+ {
+ if(e.code != NOERR)
+ {
+ e.message = "Binding fail - " + e.message;
+ throw e;
+ }
+ }
+ std::vector<string> keys = split(argv[0].str, ' ');
+ int currentBindingMap = 0;
+ for(int i = 0; i < keys.size() - 1; i++)
+ {
+ Keybind bind = getKeybind(keys[i]);
+ if(getKeymap(currentBindingMap).count(bind) > 0)
+ {
+ currentBindingMap = getKeymap(currentBindingMap).find(bind)->second.mapID;
+ }
+ else
+ {
+ KeyFunction newMap = {"", nextKeymapID};
+ keyMaps.insert({nextKeymapID, std::map<Keybind, KeyFunction>()});
+ nextKeymapID++;
+ getKeymap(currentBindingMap).insert({bind, newMap});
+ currentBindingMap = getKeymap(currentBindingMap).find(bind)->second.mapID;
+ }
+ }
+ Keybind bind = getKeybind(keys[keys.size() - 1]);
+ if(getKeymap(currentBindingMap).count(bind) <= 0)
+ {
+ KeyFunction function = {argv[1].str, nextKeymapID};
+ keyMaps.insert({nextKeymapID, std::map<Keybind, KeyFunction>()});
+ nextKeymapID++;
+ getKeymap(currentBindingMap).insert({bind, function});
+ if(currentBindingMap == currentMapID)
+ {
+ KeyCode c = XKeysymToKeycode(globals.dpy, bind.key);
+ XGrabKey(globals.dpy, c, bind.modifiers, globals.root, false, GrabModeAsync, GrabModeAsync);
+ }
+ }
+ else
+ {
+ throw Err(CFG_ERR_KEYBIND, "Bind is a keymap already!");
+ }
+ // cout << "Added bind" << endl;
+ // cout << "\t" << argv[0].str << endl;
+}
+
+const void KeybindsModule::quitKey(const CommandArg* argv)
+{
+ exitBind = getKeybind(argv[0].str);
}
const void KeybindsModule::clearKeybinds()
{
XUngrabButton(globals.dpy, AnyKey, AnyModifier, globals.root);
- binds = std::vector<Keybind>();
+ keyMaps = std::map<int, std::map<Keybind, KeyFunction>>();
+ keyMaps.insert({0, std::map<Keybind, KeyFunction>()});
}