From c7e105ee4254d00f591c4c002f32c223f4c2448a Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Mon, 4 Aug 2025 22:36:56 +0530 Subject: Add on_result callback for web.view.run_js --- src/LuaRuntime.cpp | 37 +++++++++++++++++++++++++++++++++++++ src/LuaRuntime.hpp | 4 +++- src/LuaRuntimeApi.hpp | 25 +++++++++++++++++++++++-- src/WindowActionRouter.cpp | 4 ++-- src/widgets/BrowserWindow.cpp | 5 +++-- src/widgets/BrowserWindow.hpp | 3 ++- src/widgets/Decorations.cpp | 5 +++-- src/widgets/Decorations.hpp | 4 +++- src/widgets/EdgeDecoration.cpp | 4 ++-- src/widgets/EdgeDecoration.hpp | 2 +- src/widgets/IWebViewMediator.hpp | 3 ++- src/widgets/WebView.hpp | 3 +++ src/widgets/WebViewStack.cpp | 5 +++-- src/widgets/WebViewStack.hpp | 3 ++- 14 files changed, 89 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/LuaRuntime.cpp b/src/LuaRuntime.cpp index 343266c..76dfb11 100644 --- a/src/LuaRuntime.cpp +++ b/src/LuaRuntime.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include extern "C" { #include @@ -157,3 +158,39 @@ QVariant LuaRuntime::get_lua_value(lua_State *state, int idx, QVariant default_v return lua_tostring(state, idx); } + +void LuaRuntime::push_qvariant(lua_State *state, std::optional opt) { + if (!opt.has_value()) { + lua_pushnil(state); + return; + } + + auto type = QString(opt.value().typeName()); + // qDebug() << type << opt.value(); + + // TODO: QVariantMap + // TODO: QVariantList + + if (type == "") { + lua_pushnil(state); + return; + } + + if (type == "bool") { + lua_pushboolean(state, opt.value().toBool()); + return; + } + + if (type == "int") { + lua_pushinteger(state, opt.value().toInt()); + return; + } + + if (type == "double") { + lua_pushnumber(state, opt.value().toDouble()); + return; + } + + // String default + lua_pushstring(state, opt.value().toString().toStdString().c_str()); +} diff --git a/src/LuaRuntime.hpp b/src/LuaRuntime.hpp index d5cd12c..78ae354 100644 --- a/src/LuaRuntime.hpp +++ b/src/LuaRuntime.hpp @@ -64,7 +64,8 @@ signals: void webview_scroll_bottom_requested(WebViewId webview_id); void decoration_set_enabled(DecorationType type, bool enabled, std::optional win_id); void webview_html_set_requested(const QString &html, WebViewId view_id); - void webview_js_eval_requested(const QString &js_code, WebViewId view_id); + void webview_js_eval_requested(const QString &js_code, WebViewId view_id, + const JsOnResultFunc &on_result); void schedule_for_next_tick(const std::function &action); void webview_rpc_action_defined(const QString &name, const RpcFunc &action, WebViewId view_id); void webview_reload_requested(WebViewId webview_id); @@ -83,4 +84,5 @@ public: static void inspect_lua_stack(lua_State *state); static std::vector lua_tostringlist(lua_State *state); static QVariant get_lua_value(lua_State *state, int idx, QVariant default_value = 0); + static void push_qvariant(lua_State *state, std::optional opt); }; diff --git a/src/LuaRuntimeApi.hpp b/src/LuaRuntimeApi.hpp index 0af1e9e..d6a78d5 100644 --- a/src/LuaRuntimeApi.hpp +++ b/src/LuaRuntimeApi.hpp @@ -49,9 +49,30 @@ int lua_api_view_set_html(lua_State *state) { int lua_api_view_run_js(lua_State *state) { const char *js_code = lua_tostring(state, 1); - WebViewId view_id = lua_isnoneornil(state, 2) ? 0 : lua_tointeger(state, 2); + + lua_getfield(state, 2, "view"); + WebViewId view_id = lua_isnoneornil(state, 3) ? 0 : lua_tointeger(state, 3); + lua_pop(state, 1); + + lua_getfield(state, 2, "on_result"); + JsOnResultFunc action = [](auto &) {}; + if (lua_isfunction(state, 3)) { + lua_pushvalue(state, 3); + const int function_ref = luaL_ref(state, LUA_REGISTRYINDEX); + action = [state, function_ref](const std::optional &value) { + preserve_top(state, { + lua_rawgeti(state, LUA_REGISTRYINDEX, function_ref); + LuaRuntime::push_qvariant(state, value); + lua_pcall(state, 1, 0, 0); + luaL_unref(state, LUA_REGISTRYINDEX, function_ref); + }) + }; + } + lua_pop(state, 1); + auto &runtime = LuaRuntime::instance(); - emit runtime.webview_js_eval_requested(js_code, view_id); + emit runtime.webview_js_eval_requested(js_code, view_id, action); + return 1; } diff --git a/src/WindowActionRouter.cpp b/src/WindowActionRouter.cpp index 558a46e..f513210 100644 --- a/src/WindowActionRouter.cpp +++ b/src/WindowActionRouter.cpp @@ -78,9 +78,9 @@ void WindowActionRouter::initialize(Configuration *config) { { window->expose_rpc_function(name, action, webview_id); }); }); connect(&runtime, &LuaRuntime::webview_js_eval_requested, this, - [this](const QString &js_code, WebViewId webview_id) { + [this](const QString &js_code, WebViewId webview_id, const JsOnResultFunc &on_result) { WITH_WEBVIEW_WINDOW(webview_id, window, - { window->run_javascript(js_code, webview_id); }); + { window->run_javascript(js_code, webview_id, on_result); }); }); connect(&runtime, &LuaRuntime::webview_reload_requested, this, [this](WebViewId webview_id) { WITH_WEBVIEW_WINDOW(webview_id, window, { window->reload(webview_id); }); diff --git a/src/widgets/BrowserWindow.cpp b/src/widgets/BrowserWindow.cpp index 87e315c..acb07f7 100644 --- a/src/widgets/BrowserWindow.cpp +++ b/src/widgets/BrowserWindow.cpp @@ -102,8 +102,9 @@ void BrowserWindow::set_html(const QString &html, WebViewId webview_id) { get_webview_mediator(webview_id)->set_html(html, webview_id); } -void BrowserWindow::run_javascript(const QString &js_code, WebViewId webview_id) { - get_webview_mediator(webview_id)->run_javascript(js_code, webview_id); +void BrowserWindow::run_javascript(const QString &js_code, WebViewId webview_id, + const JsOnResultFunc &on_result) { + get_webview_mediator(webview_id)->run_javascript(js_code, webview_id, on_result); } void BrowserWindow::expose_rpc_function(const QString &name, const RpcFunc &action, diff --git a/src/widgets/BrowserWindow.hpp b/src/widgets/BrowserWindow.hpp index de48c6e..2842983 100644 --- a/src/widgets/BrowserWindow.hpp +++ b/src/widgets/BrowserWindow.hpp @@ -38,7 +38,8 @@ public: bool has_webview(WebViewId webview_id); void open_url(const QUrl &url, OpenType open_type, WebViewId webview_id); void set_html(const QString &html, WebViewId webview_id); - void run_javascript(const QString &js_code, WebViewId webview_id); + void run_javascript(const QString &js_code, WebViewId webview_id, + const JsOnResultFunc &on_result); void expose_rpc_function(const QString &name, const RpcFunc &action, WebViewId webview_id); void reload(WebViewId webview_id); diff --git a/src/widgets/Decorations.cpp b/src/widgets/Decorations.cpp index 1cff3d4..22aa9f9 100644 --- a/src/widgets/Decorations.cpp +++ b/src/widgets/Decorations.cpp @@ -84,10 +84,11 @@ void Decorations::set_html(const QString &html, WebViewId view_id) { decoration.value()->set_html(html); } -void Decorations::run_javascript(const QString &js_code, WebViewId view_id) { +void Decorations::run_javascript(const QString &js_code, WebViewId view_id, + const JsOnResultFunc &on_result) { auto decoration = get_decoration_widget_by_view_id(view_id); if (decoration.has_value()) - decoration.value()->run_javascript(js_code); + decoration.value()->run_javascript(js_code, on_result); } std::optional Decorations::get_view_id(DecorationType type) { diff --git a/src/widgets/Decorations.hpp b/src/widgets/Decorations.hpp index 108b13e..3df4fd7 100644 --- a/src/widgets/Decorations.hpp +++ b/src/widgets/Decorations.hpp @@ -3,6 +3,7 @@ #include "WebViewData.hpp" #include "widgets/EdgeDecoration.hpp" #include "widgets/IWebViewMediator.hpp" +#include "widgets/WebView.hpp" #include #include #include @@ -29,7 +30,8 @@ public: bool has_webview(WebViewId view_id) override; void open_url(const QUrl &url, OpenType open_type, WebViewId view_id) override; void set_html(const QString &html, WebViewId view_id) override; - void run_javascript(const QString &js_code, WebViewId webview_id) override; + void run_javascript(const QString &js_code, WebViewId webview_id, + const JsOnResultFunc &on_result) override; void expose_rpc_function(const QString &name, const RpcFunc &action, WebViewId webview_id) override; void reload(WebViewId webview_id) override; diff --git a/src/widgets/EdgeDecoration.cpp b/src/widgets/EdgeDecoration.cpp index bb114bf..76974be 100644 --- a/src/widgets/EdgeDecoration.cpp +++ b/src/widgets/EdgeDecoration.cpp @@ -94,10 +94,10 @@ void EdgeDecoration::set_url(const QUrl &url) { webview.value()->setUrl(url); } -void EdgeDecoration::run_javascript(const QString &js_code) { +void EdgeDecoration::run_javascript(const QString &js_code, const JsOnResultFunc &on_result) { if (!webview.has_value()) return; - webview.value()->run_javascript(js_code); + webview.value()->run_javascript(js_code, on_result); } std::optional EdgeDecoration::get_view_id() { diff --git a/src/widgets/EdgeDecoration.hpp b/src/widgets/EdgeDecoration.hpp index 2c92de7..ed64658 100644 --- a/src/widgets/EdgeDecoration.hpp +++ b/src/widgets/EdgeDecoration.hpp @@ -21,7 +21,7 @@ public: void set_html(const QString &content); void set_enabled(bool enabled_value); void set_url(const QUrl &url); - void run_javascript(const QString &js_code); + void run_javascript(const QString &js_code, const JsOnResultFunc &on_result); std::optional get_view_id(); void expose_rpc_function(const QString &name, const RpcFunc &action); diff --git a/src/widgets/IWebViewMediator.hpp b/src/widgets/IWebViewMediator.hpp index a7007f2..a5a8fdb 100644 --- a/src/widgets/IWebViewMediator.hpp +++ b/src/widgets/IWebViewMediator.hpp @@ -12,6 +12,7 @@ public: virtual void set_html(const QString &html, WebViewId webview_id) = 0; virtual void expose_rpc_function(const QString &name, const RpcFunc &action, WebViewId webview_id) = 0; - virtual void run_javascript(const QString &js_code, WebViewId webview_id) = 0; + virtual void run_javascript(const QString &js_code, WebViewId webview_id, + const JsOnResultFunc &on_result) = 0; virtual void reload(WebViewId webview_id) = 0; }; diff --git a/src/widgets/WebView.hpp b/src/widgets/WebView.hpp index 36a252d..0f2bd43 100644 --- a/src/widgets/WebView.hpp +++ b/src/widgets/WebView.hpp @@ -20,6 +20,8 @@ using RpcArgs = std::unordered_map; using RpcFunc = std::function; +using JsOnResultFunc = std::function &value)>; + class WebView : public QWebEngineView { Q_OBJECT @@ -31,6 +33,7 @@ public: void scroll_to_bottom(); void enable_rpc_api(); void expose_rpc_function(const QString &name, const RpcFunc &action); + // void run_javascript(const QString &code, const JsOnResultFunc &on_result); DELEGATE(page(), runJavaScript, run_javascript) DEFINE_GETTER(get_id, id) diff --git a/src/widgets/WebViewStack.cpp b/src/widgets/WebViewStack.cpp index ab5808f..5503a3c 100644 --- a/src/widgets/WebViewStack.cpp +++ b/src/widgets/WebViewStack.cpp @@ -342,14 +342,15 @@ void WebViewStack::set_html(const QString &html, WebViewId webview_id) { webview->setHtml(html); } -void WebViewStack::run_javascript(const QString &js_code, WebViewId webview_id) { +void WebViewStack::run_javascript(const QString &js_code, WebViewId webview_id, + const JsOnResultFunc &on_result) { auto *webview = get_webview(webview_id); if (webview == nullptr) { qDebug() << "Webview does not exist"; return; } - webview->run_javascript(js_code); + webview->run_javascript(js_code, on_result); } void WebViewStack::expose_rpc_function(const QString &name, const RpcFunc & /* unused */, diff --git a/src/widgets/WebViewStack.hpp b/src/widgets/WebViewStack.hpp index bbee44c..cbff0be 100644 --- a/src/widgets/WebViewStack.hpp +++ b/src/widgets/WebViewStack.hpp @@ -62,7 +62,8 @@ public slots: void scroll_to_top(WebViewId webview_id); void scroll_to_bottom(WebViewId webview_id); void set_html(const QString &html, WebViewId webview_id = 0) override; - void run_javascript(const QString &js_code, WebViewId webview_id) override; + void run_javascript(const QString &js_code, WebViewId webview_id, + const JsOnResultFunc &on_result) override; void expose_rpc_function(const QString &name, const RpcFunc &action, WebViewId webview_id) override; void reload(WebViewId webview_id) override; -- cgit v1.3.1