diff options
Diffstat (limited to 'src/LuaRuntime.cpp')
| -rw-r--r-- | src/LuaRuntime.cpp | 270 |
1 files changed, 29 insertions, 241 deletions
diff --git a/src/LuaRuntime.cpp b/src/LuaRuntime.cpp index 127e014..cb5a69a 100644 --- a/src/LuaRuntime.cpp +++ b/src/LuaRuntime.cpp @@ -9,29 +9,14 @@ extern "C" { #include "AsyncEventLoop.hpp" #include "LuaRuntime.hpp" -#include "WindowActionRouter.hpp" +#include "LuaRuntimeApi.hpp" LuaRuntime::LuaRuntime() { state = luaL_newstate(); luaL_openlibs(state); - preserve_top(state, { init_web_lib(); }); - - auto lua_path = QString(PROJECT_LUA_PATH); - preserve_top(state, { - lua_getglobal(state, "package"); - lua_getfield(state, -1, "path"); - auto pkg_path = QString(lua_tostring(state, -1)) + ";" + lua_path; - lua_pop(state, 1); - lua_pushstring(state, pkg_path.toStdString().c_str()); - lua_setfield(state, -2, "path"); - - lua_getglobal(state, "require"); - lua_pushstring(state, "null-browser.api"); - if (lua_pcall(state, 1, 0, 0) != LUA_OK) { - qCritical() << "Unable to load browser api" << lua_tostring(state, -1); - } - }); + init_lua_package_path(); + init_web_api(); } void LuaRuntime::start_event_loop() { @@ -59,6 +44,31 @@ void LuaRuntime::stop_event_loop() { lua_gc(state, LUA_GCCOLLECT, 0); } +void LuaRuntime::init_web_api() { + luaL_newlib(state, internals_api); + lua_setglobal(state, internals_global_name); + + preserve_top(state, { + lua_getglobal(state, "require"); + lua_pushstring(state, "null-browser.api"); + if (lua_pcall(state, 1, 0, 0) != LUA_OK) { + qCritical() << "Unable to load browser api" << lua_tostring(state, -1); + } + }); +} + +void LuaRuntime::init_lua_package_path() { + auto lua_path = QString(PROJECT_LUA_PATH); + preserve_top(state, { + lua_getglobal(state, "package"); + lua_getfield(state, -1, "path"); + auto pkg_path = QString(lua_tostring(state, -1)) + ";" + lua_path; + lua_pop(state, 1); + lua_pushstring(state, pkg_path.toStdString().c_str()); + lua_setfield(state, -2, "path"); + }); +} + void LuaRuntime::evaluate(const QString &code) { queue_task([this, code]() { preserve_top(state, { @@ -67,7 +77,7 @@ void LuaRuntime::evaluate(const QString &code) { qDebug() << "Lua Error: " << value; emit evaluation_failed(value); } else { - const QVariant value = get_lua_value(-1); + const QVariant value = get_lua_value(state, -1); emit evaluation_completed(value); } }) @@ -82,228 +92,6 @@ void LuaRuntime::load_file_sync(const QString &path) { }); } -int LuaRuntime::lua_event_register(lua_State *state) { - EventHandlerRequest event; - auto top = lua_gettop(state); - - lua_getfield(state, 1, "events"); - auto event_names = LuaRuntime::lua_tostringlist(state); - - event.event_names.swap(event_names); - if (event.event_names.size() == 0) { - lua_settop(state, top); - lua_pushboolean(state, false); - return 1; - } - - lua_getfield(state, 1, "patterns"); - auto patterns = LuaRuntime::lua_tostringlist(state); - event.patterns.swap(patterns); - - lua_getfield(state, 1, "callback"); - if (!lua_isfunction(state, -1)) { - lua_settop(state, top); - lua_pushboolean(state, false); - return 1; - } - - const int function_ref = luaL_ref(state, LUA_REGISTRYINDEX); - event.function_ref = function_ref; - // TODO: Delete ref on clear callback - event.handler = [state, function_ref](BrowserEvent *event) { - preserve_top(state, { - lua_rawgeti(state, LUA_REGISTRYINDEX, function_ref); - event->lua_push(state); - lua_pcall(state, 1, 0, 0); - }) - }; - - WindowActionRouter::instance().register_event(event); - - lua_settop(state, top); - lua_pushboolean(state, true); - return 1; -} - -void LuaRuntime::init_web_lib() { - // NOLINTBEGIN(modernize-avoid-c-arrays) - - luaL_Reg internals[] = { - {"event_add_listener", &LuaRuntime::lua_event_register}, - {"config_set", &LuaRuntime::lua_config_set}, - {"config_get", &LuaRuntime::lua_config_get}, - {"keymap_set", &LuaRuntime::lua_keymap_set}, - {"view_close", &LuaRuntime::lua_view_close}, - {"view_create", &LuaRuntime::lua_view_create}, - {"view_current", &LuaRuntime::lua_view_current}, - {"view_list", &LuaRuntime::lua_view_list}, - {"view_select", &LuaRuntime::lua_view_select}, - {"view_set_url", &LuaRuntime::lua_open_url}, - {"history_back", &LuaRuntime::lua_history_back}, - {"history_forward", &LuaRuntime::lua_history_forward}, - {nullptr, nullptr}, - }; - luaL_newlib(state, internals); - lua_setglobal(state, internals_global_name); - - // NOLINTEND(modernize-avoid-c-arrays) -} - -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); - - if (lua_isboolean(state, idx)) - return lua_toboolean(state, idx); - - if (lua_isnumber(state, idx)) - return lua_tonumber(state, idx); - - return lua_tostring(state, idx); -} - -int LuaRuntime::lua_open_url(lua_State *state) { - const char *url = lua_tostring(state, 1); - WebViewId view_id = lua_isnoneornil(state, 2) ? 0 : lua_tointeger(state, 2); - auto &runtime = LuaRuntime::instance(); - emit runtime.url_opened(url, OpenType::OpenUrl, view_id); - return 1; -} - -int LuaRuntime::lua_view_create(lua_State *state) { - const char *url = luaL_optstring(state, 1, ""); - auto &runtime = LuaRuntime::instance(); - emit runtime.url_opened(url, OpenType::OpenUrlInView, 0); - return 1; -} - -int LuaRuntime::lua_config_set(lua_State *state) { - const char *key = lua_tostring(state, 1); - auto &runtime = LuaRuntime::instance(); - QVariant value = runtime.get_lua_value(2, ""); - emit runtime.config_updated(key, value); - return 1; -} - -int LuaRuntime::lua_config_get(lua_State *state) { - const char *key = lua_tostring(state, 1); - auto &router = WindowActionRouter::instance(); - auto value = router.fetch_config_value(key); - - if (value.typeId() == QMetaType::QString) - lua_pushstring(state, value.toString().toStdString().c_str()); - else if (value.typeId() == QMetaType::Int) - lua_pushinteger(state, value.toInt()); - else if (value.typeId() == QMetaType::Double) - lua_pushnumber(state, value.toDouble()); - else - lua_pushnil(state); - - return 1; -} - -int LuaRuntime::lua_keymap_set(lua_State *state) { - const char *mode = lua_tostring(state, 1); - const char *keyseq = lua_tostring(state, 2); - - lua_pushvalue(state, 3); - const int function_ref = luaL_ref(state, LUA_REGISTRYINDEX); - auto action = [state, function_ref]() { - preserve_top(state, { - lua_rawgeti(state, LUA_REGISTRYINDEX, function_ref); - if (lua_pcall(state, 0, 0, 0) != LUA_OK) { - const char *error = lua_tostring(state, -1); - qDebug() << "Error calling Lua function:" << error; - } - }) - }; - // TODO: Cleanup function ref on after keymap clear - - auto &runtime = LuaRuntime::instance(); - emit runtime.keymap_added(mode, keyseq, action); - - return 1; -} - -int LuaRuntime::lua_view_current(lua_State *state) { - auto &router = WindowActionRouter::instance(); - auto view_id = router.fetch_current_view_id(); - lua_pushinteger(state, view_id); - return 1; -} - -int LuaRuntime::lua_view_list(lua_State *state) { - auto &router = WindowActionRouter::instance(); - auto views = router.fetch_webview_data_list(); - lua_newtable(state); - - int index = 1; // 1-indexed - for (auto &view : views) { - lua_newtable(state); - - lua_pushstring(state, "id"); - lua_pushinteger(state, view.id); - lua_settable(state, -3); - - lua_pushstring(state, "url"); - lua_pushstring(state, view.url.toStdString().c_str()); - lua_settable(state, -3); - - lua_pushstring(state, "title"); - lua_pushstring(state, view.title.toStdString().c_str()); - lua_settable(state, -3); - - lua_rawseti(state, -2, index); - index++; - } - - 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); - - WebViewId view_id = lua_isnoneornil(state, 2) ? 0 : lua_tointeger(state, 2); - - emit runtime.history_back_requested(view_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); - - WebViewId view_id = lua_isnoneornil(state, 2) ? 0 : lua_tointeger(state, 2); - - emit runtime.history_forward_requested(view_id, history_index); - return 1; -} - -int LuaRuntime::lua_view_close(lua_State *state) { - auto &runtime = LuaRuntime::instance(); - - WebViewId view_id = lua_isnoneornil(state, 1) ? 0 : lua_tointeger(state, 1); - - emit runtime.webview_closed(view_id); - return 1; -} - -int LuaRuntime::lua_view_select(lua_State *state) { - if (lua_isnoneornil(state, 1)) - return 1; // TODO: return nil (for others too) - - auto &runtime = LuaRuntime::instance(); - WebViewId view_id = lua_tointeger(state, 1); - emit runtime.webview_selected(view_id); - return 1; -} - LuaRuntime::~LuaRuntime() { stop_event_loop(); lua_close(state); |
