diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/AsyncEventLoop.cpp | 3 | ||||
| -rw-r--r-- | src/InputMediator.cpp | 44 | ||||
| -rw-r--r-- | src/InputMediator.hpp | 14 | ||||
| -rw-r--r-- | src/LuaRuntime.cpp | 64 | ||||
| -rw-r--r-- | src/LuaRuntime.hpp | 10 | ||||
| -rw-r--r-- | src/utils.hpp | 6 | ||||
| -rw-r--r-- | src/widgets/WebViewStack.cpp | 109 | ||||
| -rw-r--r-- | src/widgets/WebViewStack.hpp | 19 |
8 files changed, 177 insertions, 92 deletions
diff --git a/src/AsyncEventLoop.cpp b/src/AsyncEventLoop.cpp index 3acbc41..0ee9986 100644 --- a/src/AsyncEventLoop.cpp +++ b/src/AsyncEventLoop.cpp @@ -31,6 +31,9 @@ void AsyncEventLoop::process_tasks() { { const std::lock_guard<std::mutex> lock(tasks_queue_mutex); + if (tasks_queue.empty()) + return; + tasks_queue.swap(tasks); } diff --git a/src/InputMediator.cpp b/src/InputMediator.cpp index aeb352b..1d86a2a 100644 --- a/src/InputMediator.cpp +++ b/src/InputMediator.cpp @@ -8,15 +8,23 @@ #include "widgets/WebViewStack.hpp" // TODO: Rename this -InputMediator::InputMediator(WebViewStack *web_view_stack, +InputMediator::InputMediator(WebViewStack *webview_stack, LuaRuntime *lua_runtime, KeymapEvaluator *keymap_evaluator) - : web_view_stack(web_view_stack), lua_runtime(lua_runtime), + : webview_stack(webview_stack), lua_runtime(lua_runtime), keymap_evaluator(keymap_evaluator) { - connect(lua_runtime, &LuaRuntime::url_opened, web_view_stack, + connect(lua_runtime, &LuaRuntime::url_opened, webview_stack, &WebViewStack::open_url); connect(lua_runtime, &LuaRuntime::keymap_add_requested, this, &InputMediator::add_keymap); + connect(lua_runtime, &LuaRuntime::history_back_requested, webview_stack, + &WebViewStack::webview_history_back); + connect(lua_runtime, &LuaRuntime::history_forward_requested, webview_stack, + &WebViewStack::webview_history_forward); + + lua_runtime->set_current_tab_id_fetcher([this]() { + return this->webview_stack->current_webview_index(); + }); } void InputMediator::add_keymap(const QString &mode_string, @@ -26,32 +34,4 @@ void InputMediator::add_keymap(const QString &mode_string, keymap_evaluator->add_keymap(mode, keyseq, std::move(action)); } -// void InputMediator::evaluate_command(QString command) { -// CommandParser parser; -// auto cmd = parser.parse(command); -// -// switch (cmd.command) { -// case CommandType::LuaEval: -// lua_runtime->evaluate(cmd.argsString); -// break; -// case CommandType::Open: -// open_url(cmd.argsString, OpenType::OpenUrl); -// break; -// case CommandType::TabOpen: -// open_url(cmd.argsString, OpenType::OpenUrlInTab); -// break; -// case CommandType::TabNext: -// next_web_view(); -// break; -// case CommandType::TabPrev: -// previous_web_view(); -// break; -// case CommandType::TabSelect: -// web_view_stack->focus_web_view(cmd.argsString.toLong()); -// break; -// case CommandType::Noop: -// break; -// } -// } - -InputMediator::~InputMediator() { delete web_view_stack; } +InputMediator::~InputMediator() { delete webview_stack; } diff --git a/src/InputMediator.hpp b/src/InputMediator.hpp index 2cd34f2..5933bd7 100644 --- a/src/InputMediator.hpp +++ b/src/InputMediator.hpp @@ -12,15 +12,15 @@ class InputMediator : public QObject { Q_OBJECT public: - InputMediator(WebViewStack *web_view_stack, LuaRuntime *lua_runtime, + InputMediator(WebViewStack *webview_stack, LuaRuntime *lua_runtime, KeymapEvaluator *keymap_evaluator); ~InputMediator() override; - DELEGATE(web_view_stack, open_url, open_url) - DELEGATE(web_view_stack, current_url, current_url) - DELEGATE(web_view_stack, next, next_web_view) - DELEGATE(web_view_stack, previous, previous_web_view) - DELEGATE(web_view_stack, close_current, close_current_web_view) + DELEGATE(webview_stack, open_url, open_url) + DELEGATE(webview_stack, current_url, current_url) + DELEGATE(webview_stack, next, next_webview) + DELEGATE(webview_stack, previous, previous_webview) + DELEGATE(webview_stack, close_current, close_current_webview) DELEGATE(keymap_evaluator, evaluate, evaluate_keymap) protected: @@ -28,7 +28,7 @@ protected: std::function<void()> action); private: - WebViewStack *web_view_stack; + WebViewStack *webview_stack; LuaRuntime *lua_runtime; KeymapEvaluator *keymap_evaluator; }; diff --git a/src/LuaRuntime.cpp b/src/LuaRuntime.cpp index eb61a19..0149e10 100644 --- a/src/LuaRuntime.cpp +++ b/src/LuaRuntime.cpp @@ -39,7 +39,7 @@ void LuaRuntime::stop_event_loop() { } void LuaRuntime::evaluate(const QString &code) { - event_loop->queue_task([this, code]() { + queue_task([this, code]() { preserve_top(state, { if (luaL_dostring(state, code.toStdString().c_str()) != LUA_OK) { const char *value = lua_tostring(state, -1); @@ -59,7 +59,10 @@ QVariant LuaRuntime::evaluate_sync(const QString &code) { return get_lua_value(-1); // TODO: error handling } -QVariant LuaRuntime::get_lua_value(int idx) { +QVariant LuaRuntime::get_lua_value(int idx, QVariant default_value) { + if (lua_isnoneornil(state, idx)) + return default_value; + if (lua_isstring(state, idx)) return lua_tostring(state, idx); @@ -69,9 +72,6 @@ QVariant LuaRuntime::get_lua_value(int idx) { if (lua_isboolean(state, idx)) return lua_toboolean(state, idx); - if (lua_isnil(state, idx)) - return 0; // TODO: nil representation - return lua_tostring(state, idx); } @@ -144,9 +144,63 @@ void LuaRuntime::init_web_lib() { lua_setfield(state, -2, "keymap"); // lua_pop(state, 1); + luaL_Reg tabslib[] = { + {"current", &LuaRuntime::lua_get_current_tab_id}, + }; + luaL_newlib(state, tabslib); // NOLINT(readability-math-missing-parentheses) + lua_setfield(state, -2, "tabs"); + + luaL_Reg historylib[] = { + {"back", &LuaRuntime::lua_history_back}, + {"forward", &LuaRuntime::lua_history_forward}, + }; + luaL_newlib(state, // NOLINT(readability-math-missing-parentheses) + historylib); + lua_setfield(state, -2, "history"); // NOLINTEND(modernize-avoid-c-arrays) } +int LuaRuntime::lua_get_current_tab_id(lua_State *state) { + auto *runtime = LuaRuntime::instance(); + auto tab_id = runtime->fetch_current_tab_id(); + lua_pushinteger(state, tab_id); + return 1; +} + +int LuaRuntime::lua_history_back(lua_State *state) { + auto *runtime = LuaRuntime::instance(); + + qsizetype history_index = + lua_isnoneornil(state, 1) ? 1 : lua_tointeger(state, 1); + + qsizetype tab_id; + if (lua_isnoneornil(state, 2)) { + tab_id = runtime->fetch_current_tab_id(); + } else { + tab_id = lua_tointeger(state, 2); + } + + emit runtime->history_back_requested(tab_id, history_index); + return 1; +} + +int LuaRuntime::lua_history_forward(lua_State *state) { + auto *runtime = LuaRuntime::instance(); + + qsizetype history_index = + lua_isnoneornil(state, 1) ? 1 : lua_tointeger(state, 1); + + qsizetype tab_id; + if (lua_isnoneornil(state, 2)) { + tab_id = runtime->fetch_current_tab_id(); + } else { + tab_id = lua_tointeger(state, 2); + } + + emit runtime->history_forward_requested(tab_id, history_index); + return 1; +} + LuaRuntime::~LuaRuntime() { stop_event_loop(); lua_close(state); diff --git a/src/LuaRuntime.hpp b/src/LuaRuntime.hpp index 94d24d8..c90049e 100644 --- a/src/LuaRuntime.hpp +++ b/src/LuaRuntime.hpp @@ -5,6 +5,7 @@ #include <lua.hpp> #include "AsyncEventLoop.hpp" +#include "utils.hpp" #include "widgets/WebViewStack.hpp" #define preserve_top(STATE, BODY) \ @@ -32,15 +33,19 @@ public: void start_event_loop(); DELEGATE(event_loop, queue_task, queue_task) - QVariant get_lua_value(int idx); + QVariant get_lua_value(int idx, QVariant default_value = 0); DEFINE_GETTER(get_state, state) + DEFINE_FETCHER(qsizetype(), current_tab_id) + signals: void url_opened(QString url, OpenType open_type); void evaluation_completed(QVariant value); void evaluation_failed(QString value); void keymap_add_requested(QString mode, QString keyseq, std::function<void()>); + void history_back_requested(WebViewId webview_id, qsizetype history_index); + void history_forward_requested(WebViewId webview_id, qsizetype history_index); // void output_produced(QVariant value); protected: @@ -50,6 +55,9 @@ protected: static int lua_on_url_open(lua_State *state); static int lua_on_url_tab_open(lua_State *state); static int lua_add_keymap(lua_State *state); + static int lua_get_current_tab_id(lua_State *state); + static int lua_history_back(lua_State *state); + static int lua_history_forward(lua_State *state); private: lua_State *state; diff --git a/src/utils.hpp b/src/utils.hpp index d5d4fc5..eace39e 100644 --- a/src/utils.hpp +++ b/src/utils.hpp @@ -10,3 +10,9 @@ #define DEFINE_GETTER(METHOD, EXPR) \ decltype(auto) METHOD() { return EXPR; } + +#define DEFINE_FETCHER(TYPE, NAME) \ + void set_##NAME##_fetcher(const std::function<TYPE> &fetcher) { \ + fetch_##NAME = fetcher; \ + } \ + std::function<qsizetype()> fetch_##NAME = []() { return -1; }; diff --git a/src/widgets/WebViewStack.cpp b/src/widgets/WebViewStack.cpp index 19e472e..2d3722a 100644 --- a/src/widgets/WebViewStack.cpp +++ b/src/widgets/WebViewStack.cpp @@ -1,6 +1,8 @@ #include <QStackedLayout> +#include <QWebEngineHistory> #include <QWebEngineNewWindowRequest> #include <QWebEngineProfile> +#include <cstdlib> #include <vector> #include "widgets/WebViewStack.hpp" @@ -12,7 +14,7 @@ WebViewStack::WebViewStack(const Configuration *configuration, layout->setContentsMargins(0, 0, 0, 0); layout->setStackingMode(QStackedLayout::StackOne); - create_new_web_view(configuration->new_tab_url, true); + create_new_webview(configuration->new_tab_url, true); } void WebViewStack::open_url(const QUrl &url, OpenType open_type) { @@ -21,125 +23,152 @@ void WebViewStack::open_url(const QUrl &url, OpenType open_type) { set_current_url(url); break; case OpenType::OpenUrlInTab: - create_new_web_view(url, true); + create_new_webview(url, true); break; case OpenType::OpenUrlInBgTab: - create_new_web_view(url, false); + create_new_webview(url, false); break; case OpenType::OpenUrlInWindow: - create_new_web_view(url, true); + create_new_webview(url, true); break; } } -WebView *WebViewStack::create_new_web_view(const QUrl &url, bool focus) { +WebView *WebViewStack::create_new_webview(const QUrl &url, bool focus) { auto *webview = new WebView(profile); webview->setUrl(url); layout->addWidget(webview); - web_view_list.append(webview); + webview_list.append(webview); connect(webview->page(), &QWebEnginePage::newWindowRequested, this, - &WebViewStack::on_new_web_view_request); + &WebViewStack::on_new_webview_request); if (focus) - focus_web_view(web_view_list.length() - 1); + focus_webview(webview_list.length() - 1); return webview; } -QList<Tab> WebViewStack::get_tab_list() { +QList<Tab> WebViewStack::get_webview_list() { QList<Tab> urls; - for (auto &view : web_view_list) + for (auto &view : webview_list) urls.append(Tab{.url = view->url().toString(), .title = view->title()}); return urls; } -void WebViewStack::on_new_web_view_request( +void WebViewStack::on_new_webview_request( const QWebEngineNewWindowRequest &request) { switch (request.destination()) { case QWebEngineNewWindowRequest::InNewTab: - create_new_web_view(request.requestedUrl(), true); + create_new_webview(request.requestedUrl(), true); break; case QWebEngineNewWindowRequest::InNewBackgroundTab: - create_new_web_view(request.requestedUrl(), false); + create_new_webview(request.requestedUrl(), false); break; case QWebEngineNewWindowRequest::InNewWindow: case QWebEngineNewWindowRequest::InNewDialog: // TODO: Impl - create_new_web_view(request.requestedUrl(), true); + create_new_webview(request.requestedUrl(), true); break; } } void WebViewStack::next() { - if (web_view_list.isEmpty()) + if (webview_list.isEmpty()) return; - auto index = current_web_view_index() + 1; - auto total = web_view_list.length(); + auto index = current_webview_index() + 1; + auto total = webview_list.length(); index = index >= total ? index % total : index; - focus_web_view(index); + focus_webview(index); } void WebViewStack::previous() { - if (web_view_list.isEmpty()) + if (webview_list.isEmpty()) return; - auto index = current_web_view_index() - 1; - auto total = web_view_list.length(); + auto index = current_webview_index() - 1; + auto total = webview_list.length(); index = index < 0 ? total + index : index; - focus_web_view(index); + focus_webview(index); } -void WebViewStack::close_current() { close(current_web_view_index()); } +void WebViewStack::close_current() { close(current_webview_index()); } -void WebViewStack::close(qsizetype index) { - if (index < 0 || index >= web_view_list.length()) +void WebViewStack::close(WebViewId index) { + if (index < 0 || index >= webview_list.length()) return; - auto *webview = web_view_list.at(index); + auto *webview = webview_list.at(index); layout->removeWidget(webview); - web_view_list.removeAt(index); + webview_list.removeAt(index); disconnect(webview->page()); webview->deleteLater(); - focus_web_view(current_web_view_index()); + focus_webview(current_webview_index()); - if (web_view_list.isEmpty()) { - create_new_web_view(configuration->new_tab_url, true); + if (webview_list.isEmpty()) { + create_new_webview(configuration->new_tab_url, true); } } +void WebViewStack::webview_history_back(WebViewId webview_id, + qsizetype history_index) { + if (webview_id < 0 || webview_id >= webview_list.length()) + return; + + // TODO: Change this + auto *webview = webview_list.at(webview_id); + auto *history = webview->history(); + for (auto i = abs(history_index); i > 0; i--) + if (history->canGoBack()) + history->back(); +} + +void WebViewStack::webview_history_forward(WebViewId webview_id, + qsizetype history_index) { + if (webview_id < 0 || webview_id >= webview_list.length()) + return; + + // TODO: Change this + auto *webview = webview_list.at(webview_id); + auto *history = webview->history(); + for (auto i = abs(history_index); i > 0; i--) + if (history->canGoForward()) + history->forward(); +} + std::vector<QUrl> WebViewStack::urls() { std::vector<QUrl> urls; - for (auto &view : web_view_list) + for (auto &view : webview_list) urls.push_back(view->url()); return urls; } -uint32_t WebViewStack::current_web_view_index() { +uint32_t WebViewStack::current_webview_index() { + qDebug() << "CIRR" << layout->currentIndex(); return layout->currentIndex(); } -uint32_t WebViewStack::count() { return web_view_list.length(); } +uint32_t WebViewStack::count() { return webview_list.length(); } -void WebViewStack::focus_web_view(qsizetype index) { - if (web_view_list.isEmpty()) +void WebViewStack::focus_webview(WebViewId index) { + if (webview_list.isEmpty()) return; index = std::max((long long)0, - std::min((long long)index, web_view_list.length() - 1)); + std::min((long long)index, webview_list.length() - 1)); layout->setCurrentIndex((int)index); } QUrl WebViewStack::current_url() { - if (current_web_view_index() >= web_view_list.length()) + if (current_webview_index() >= webview_list.length()) return QUrl{}; - return web_view_list.at(current_web_view_index())->url(); + return webview_list.at(current_webview_index())->url(); } void WebViewStack::set_current_url(const QUrl &url) { - if (current_web_view_index() >= web_view_list.length()) + if (current_webview_index() >= webview_list.length()) return; - web_view_list.at(current_web_view_index())->setUrl(url); + webview_list.at(current_webview_index())->setUrl(url); } diff --git a/src/widgets/WebViewStack.hpp b/src/widgets/WebViewStack.hpp index aa463cc..c975d16 100644 --- a/src/widgets/WebViewStack.hpp +++ b/src/widgets/WebViewStack.hpp @@ -8,6 +8,8 @@ #include "Configuration.hpp" #include "widgets/WebView.hpp" +using WebViewId = qsizetype; + enum OpenType : uint8_t { OpenUrl, OpenUrlInTab, @@ -31,28 +33,31 @@ public: void open_url(const QUrl &url, OpenType open_type = OpenType::OpenUrl); std::vector<QUrl> urls(); - QList<Tab> get_tab_list(); - uint32_t current_web_view_index(); + QList<Tab> get_webview_list(); + uint32_t current_webview_index(); uint32_t count(); QUrl current_url(); - void focus_web_view(qsizetype index); + void focus_webview(WebViewId index); void next(); void previous(); - void close(qsizetype index); + void close(WebViewId index); void close_current(); + void webview_history_back(WebViewId webview_id, qsizetype history_index); + void webview_history_forward(WebViewId webview_id, qsizetype history_index); + private slots: - void on_new_web_view_request(const QWebEngineNewWindowRequest &request); + void on_new_webview_request(const QWebEngineNewWindowRequest &request); protected: void set_current_url(const QUrl &url); - WebView *create_new_web_view(const QUrl &url, bool focus = false); + WebView *create_new_webview(const QUrl &url, bool focus = false); private: const Configuration *configuration; QWebEngineProfile *profile; QStackedLayout *layout; - QList<WebView *> web_view_list; + QList<WebView *> webview_list; }; |
