diff options
| author | Akshay Nair <phenax5@gmail.com> | 2025-03-18 20:52:36 +0530 |
|---|---|---|
| committer | Akshay Nair <phenax5@gmail.com> | 2025-03-18 20:52:36 +0530 |
| commit | 056b0b16947ac19a0c425aa9d2ff8f589378d3bc (patch) | |
| tree | d062dc2de09711c1f7e980fc8475c19a97ff7d99 | |
| parent | dd6590a0fda614fa2fb0ca9e4ad11b086393372e (diff) | |
| download | null-browser-056b0b16947ac19a0c425aa9d2ff8f589378d3bc.tar.gz null-browser-056b0b16947ac19a0c425aa9d2ff8f589378d3bc.zip | |
Add keymap evaluation with strict event filter
Diffstat (limited to '')
| -rw-r--r-- | include/keymap/KeySeqParser.hpp | 26 | ||||
| -rw-r--r-- | include/keymap/KeymapEvaluator.hpp | 71 | ||||
| -rw-r--r-- | include/widgets/InputLine.hpp | 2 | ||||
| -rw-r--r-- | include/widgets/MainWindow.hpp | 6 | ||||
| -rw-r--r-- | include/widgets/WebView.hpp | 13 | ||||
| -rw-r--r-- | include/widgets/WebViewStack.hpp | 9 | ||||
| -rw-r--r-- | spec/WebViewStackSpec.cpp | 5 | ||||
| -rw-r--r-- | src/keymap/KeymapEvaluator.cpp | 6 | ||||
| -rw-r--r-- | src/widgets/MainWindow.cpp | 24 | ||||
| -rw-r--r-- | src/widgets/WebView.cpp | 6 | ||||
| -rw-r--r-- | src/widgets/WebViewStack.cpp | 5 |
11 files changed, 156 insertions, 17 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; +}; diff --git a/include/widgets/InputLine.hpp b/include/widgets/InputLine.hpp index d5f65be..a382ff8 100644 --- a/include/widgets/InputLine.hpp +++ b/include/widgets/InputLine.hpp @@ -24,8 +24,6 @@ public: DELEGATE(input, text, getInputText) DELEGATE(promptPrefix, text, prompt) - // bool eventFilter(QObject *obj, QEvent *event) override; - signals: void submitted(QString text); void cancelled(); diff --git a/include/widgets/MainWindow.hpp b/include/widgets/MainWindow.hpp index 559a119..3e3a6d6 100644 --- a/include/widgets/MainWindow.hpp +++ b/include/widgets/MainWindow.hpp @@ -1,12 +1,10 @@ #pragma once #include <QMainWindow> -#include <QObject> -#include <QStackedLayout> -#include <QWebEngineView> #include "Configuration.hpp" #include "InputMediator.hpp" +#include "keymap/KeymapEvaluator.hpp" class MainWindow : public QMainWindow { public: @@ -14,8 +12,10 @@ public: private: void keyPressEvent(QKeyEvent *event) override; + bool eventFilter(QObject *object, QEvent *event) override; private: InputMediator *inputMediator; Configuration configuration; + KeymapEvaluator keymapEvaluator; }; diff --git a/include/widgets/WebView.hpp b/include/widgets/WebView.hpp new file mode 100644 index 0000000..8a95139 --- /dev/null +++ b/include/widgets/WebView.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include <QKeyEvent> +#include <QWebEngineView> +#include <QWidget> +#include <QtCore> + +class WebView : public QWebEngineView { + Q_OBJECT + +public: + WebView(QWebEngineProfile *profile); +}; diff --git a/include/widgets/WebViewStack.hpp b/include/widgets/WebViewStack.hpp index 34b1658..c315251 100644 --- a/include/widgets/WebViewStack.hpp +++ b/include/widgets/WebViewStack.hpp @@ -2,11 +2,11 @@ #include <QStackedLayout> #include <QWebEngineProfile> -#include <QWebEngineView> #include <sys/types.h> #include "Configuration.hpp" #include "completion/TabsModel.hpp" +#include "widgets/WebView.hpp" enum OpenType { OpenUrl, OpenUrlInTab, OpenUrlInBgTab, OpenUrlInWindow }; @@ -24,6 +24,7 @@ public: void openUrl(QUrl url, OpenType openType = OpenType::OpenUrl); std::vector<QUrl> urls(); + QList<Tab> getTabList(); u_int32_t currentWebViewIndex(); u_int32_t count(); QUrl currentUrl(); @@ -35,11 +36,9 @@ public: void close(long index); void closeCurrent(); - QList<Tab> getTabList(); - private: void setCurrentUrl(QUrl url); - QWebEngineView *createNewWebView(QUrl url, bool focus = false); + WebView *createNewWebView(QUrl url, bool focus = false); private slots: void onNewWebViewRequest(QWebEngineNewWindowRequest &request); @@ -48,5 +47,5 @@ private: const Configuration *configuration; QWebEngineProfile *profile; QStackedLayout *layout; - QList<QWebEngineView *> webViewList; + QList<WebView *> webViewList; }; diff --git a/spec/WebViewStackSpec.cpp b/spec/WebViewStackSpec.cpp index e8df0c1..040fb8f 100644 --- a/spec/WebViewStackSpec.cpp +++ b/spec/WebViewStackSpec.cpp @@ -4,6 +4,7 @@ #include "Configuration.hpp" #include "testUtils.h" +#include "widgets/WebView.hpp" #include "widgets/WebViewStack.hpp" class WebViewStackSpec : public QObject { @@ -247,7 +248,7 @@ private slots: Configuration configuration; WebViewStack webViewStack(&configuration); webViewStack.openUrl(QUrl("https://a.com"), OpenType::OpenUrl); - auto webview = webViewStack.findChild<QWebEngineView *>(); + auto webview = webViewStack.findChild<WebView *>(); QCOMPARE(webViewStack.count(), 1); FakeNewWindowRequest windowRequest( @@ -269,7 +270,7 @@ private slots: Configuration configuration; WebViewStack webViewStack(&configuration); webViewStack.openUrl(QUrl("https://a.com"), OpenType::OpenUrl); - auto webview = webViewStack.findChild<QWebEngineView *>(); + auto webview = webViewStack.findChild<WebView *>(); FakeNewWindowRequest windowRequest( FakeNewWindowRequest::DestinationType::InNewBackgroundTab, diff --git a/src/keymap/KeymapEvaluator.cpp b/src/keymap/KeymapEvaluator.cpp new file mode 100644 index 0000000..cca10e8 --- /dev/null +++ b/src/keymap/KeymapEvaluator.cpp @@ -0,0 +1,6 @@ +#include <QWidget> +#include <QtCore> + +#include "keymap/KeymapEvaluator.hpp" + +KeymapEvaluator::KeymapEvaluator() : QObject() {} diff --git a/src/widgets/MainWindow.cpp b/src/widgets/MainWindow.cpp index d2b1578..7d045bc 100644 --- a/src/widgets/MainWindow.cpp +++ b/src/widgets/MainWindow.cpp @@ -1,8 +1,9 @@ #include <QKeyEvent> #include <QStackedLayout> #include <QVBoxLayout> -#include <QWebEngineView> +#include <QtCore/qcoreevent.h> #include <QtCore/qnamespace.h> +#include <QtWidgets/qapplication.h> #include "InputMediator.hpp" #include "widgets/InputLine.hpp" @@ -13,6 +14,8 @@ MainWindow::MainWindow() { setStyleSheet("background-color: #000; color: #fff;"); setCentralWidget(new QWidget()); // TODO: manage widget memory + qApp->installEventFilter(this); + // Root stacked layout auto layout = new QStackedLayout(); layout->setContentsMargins(0, 0, 0, 0); @@ -31,6 +34,9 @@ MainWindow::MainWindow() { inputMediator = new InputMediator(inputLine, webViewStack, LuaRuntime::instance()); + + keymapEvaluator.addKeymap("default", "<c-t>a", "Stuff"); + keymapEvaluator.addKeymap("default", "<c-t>b", "Other stuff"); } void MainWindow::keyPressEvent(QKeyEvent *event) { @@ -57,3 +63,19 @@ void MainWindow::keyPressEvent(QKeyEvent *event) { inputMediator->closeCurrentWebView(); } } + +bool MainWindow::eventFilter(QObject *object, QEvent *event) { + if (event->type() != QEvent::KeyPress && event->type() != QEvent::KeyRelease) + return false; + + if (auto keyEvent = dynamic_cast<QKeyEvent *>(event)) { + if (keyEvent->type() == QEvent::KeyPress) + keymapEvaluator.evaluate(keyEvent->modifiers(), (Qt::Key)keyEvent->key()); + + // qDebug() << "EV SELF: " << (object == this) << " | " << event->type(); + // qDebug() << "Key: " << keyEvent->modifiers() << keyEvent->key(); + return true; + } + + return false; +} diff --git a/src/widgets/WebView.cpp b/src/widgets/WebView.cpp new file mode 100644 index 0000000..e00be1f --- /dev/null +++ b/src/widgets/WebView.cpp @@ -0,0 +1,6 @@ +#include <QWidget> +#include <QtCore> + +#include "widgets/WebView.hpp" + +WebView::WebView(QWebEngineProfile *profile) : QWebEngineView(profile) {} diff --git a/src/widgets/WebViewStack.cpp b/src/widgets/WebViewStack.cpp index d89db6e..f915d9e 100644 --- a/src/widgets/WebViewStack.cpp +++ b/src/widgets/WebViewStack.cpp @@ -1,6 +1,5 @@ #include <QStackedLayout> #include <QWebEngineNewWindowRequest> -#include <QWebEngineView> #include "widgets/WebViewStack.hpp" @@ -31,8 +30,8 @@ void WebViewStack::openUrl(QUrl url, OpenType openType) { } } -QWebEngineView *WebViewStack::createNewWebView(QUrl url, bool focus) { - auto webview = new QWebEngineView(profile); +WebView *WebViewStack::createNewWebView(QUrl url, bool focus) { + auto webview = new WebView(profile); webview->setUrl(url); layout->addWidget(webview); webViewList.append(webview); |
