aboutsummaryrefslogtreecommitdiff
path: root/include/keymap
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2025-03-18 20:52:36 +0530
committerAkshay Nair <phenax5@gmail.com>2025-03-18 20:52:36 +0530
commit056b0b16947ac19a0c425aa9d2ff8f589378d3bc (patch)
treed062dc2de09711c1f7e980fc8475c19a97ff7d99 /include/keymap
parentdd6590a0fda614fa2fb0ca9e4ad11b086393372e (diff)
downloadnull-browser-056b0b16947ac19a0c425aa9d2ff8f589378d3bc.tar.gz
null-browser-056b0b16947ac19a0c425aa9d2ff8f589378d3bc.zip
Add keymap evaluation with strict event filter
Diffstat (limited to 'include/keymap')
-rw-r--r--include/keymap/KeySeqParser.hpp26
-rw-r--r--include/keymap/KeymapEvaluator.hpp71
2 files changed, 96 insertions, 1 deletions
diff --git a/include/keymap/KeySeqParser.hpp b/include/keymap/KeySeqParser.hpp
index aefcb62..fac2546 100644
--- a/include/keymap/KeySeqParser.hpp
+++ b/include/keymap/KeySeqParser.hpp
@@ -2,6 +2,7 @@
#include <QtCore/qnamespace.h>
#include <QtCore>
+#include <cmath>
struct KeyChord {
Qt::KeyboardModifiers mod;
@@ -9,11 +10,34 @@ struct KeyChord {
};
bool operator==(const KeyChord a, const KeyChord b);
+typedef QList<KeyChord> KeySequence;
+
+enum KeyMatchType {
+ NoMatch,
+ Match,
+ Pending,
+};
+
class KeySeqParser {
public:
+ static const KeyMatchType keySequenceMatch(const KeySequence target,
+ const KeySequence current) {
+ for (int i = 0; i < target.length(); i++) {
+ if (current.length() <= i)
+ return KeyMatchType::Pending;
+
+ if (target[i].key != current[i].key ||
+ !target[i].mod.testFlags(current[i].mod))
+ return KeyMatchType::NoMatch;
+ }
+
+ return KeyMatchType::Match;
+ }
+
+public:
KeySeqParser();
- QList<KeyChord> parse(QString keySequence);
+ KeySequence parse(QString keySequence);
private:
Qt::Key parseKey(QString keyName);
diff --git a/include/keymap/KeymapEvaluator.hpp b/include/keymap/KeymapEvaluator.hpp
new file mode 100644
index 0000000..ed468d2
--- /dev/null
+++ b/include/keymap/KeymapEvaluator.hpp
@@ -0,0 +1,71 @@
+#pragma once
+
+#include "keymap/KeySeqParser.hpp"
+#include <QWidget>
+#include <QtCore/qmap.h>
+#include <QtCore/qnamespace.h>
+#include <QtCore>
+#include <algorithm>
+
+struct KeyMap {
+ KeySequence keySequence;
+ QString action; // TODO: string for testing
+};
+
+class KeymapEvaluator : public QObject {
+ Q_OBJECT
+
+public:
+ KeymapEvaluator();
+
+ void addKeymap(QString mode, QString key, QString action) {
+ if (!modalKeys.contains(mode))
+ modalKeys.insert(mode, {});
+
+ auto keySeq = keySeqParser.parse(key);
+ // TODO: Add actions
+ modalKeys[mode].append((KeyMap){.keySequence = keySeq, .action = action});
+ }
+
+ void evaluate(Qt::KeyboardModifiers modifiers, Qt::Key key) {
+ if (key == Qt::Key_Control || key == Qt::Key_Shift || key == Qt::Key_Meta ||
+ key == Qt::Key_Alt)
+ return;
+
+ auto keymaps = currentModeKeys();
+ auto foundPendingMatches = false;
+
+ activeKeySequence.append((KeyChord){.mod = modifiers, .key = key});
+
+ for (auto &keymap : *keymaps) {
+ auto matchType =
+ KeySeqParser::keySequenceMatch(keymap.keySequence, activeKeySequence);
+
+ if (matchType == KeyMatchType::Match) {
+ qDebug() << "Matched!" << keymap.action;
+ activeKeySequence.clear();
+ return;
+ } else if (matchType == KeyMatchType::Pending) {
+ foundPendingMatches = true;
+ }
+ }
+
+ if (!foundPendingMatches)
+ activeKeySequence.clear();
+ }
+
+private:
+ const QList<KeyMap> *currentModeKeys() {
+ if (!modalKeys.contains(currentMode))
+ return new QList<KeyMap>();
+
+ return &modalKeys[currentMode];
+ }
+
+private:
+ QMap<QString, QList<KeyMap>> modalKeys;
+ KeySeqParser keySeqParser;
+ QString currentMode = "default";
+
+ KeySequence activeKeySequence;
+};