aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2025-03-25 21:11:42 +0530
committerAkshay Nair <phenax5@gmail.com>2025-03-25 21:11:42 +0530
commita54f6ae81b54ca59bf913bba16f271a35ca08d9d (patch)
treed8e5be08f87cc2d90b984fc6a9e8323457785606
parent1284f8cf39e8ba44e837d4dac0bace89cb7a0c26 (diff)
downloadnull-browser-a54f6ae81b54ca59bf913bba16f271a35ca08d9d.tar.gz
null-browser-a54f6ae81b54ca59bf913bba16f271a35ca08d9d.zip
Add web.tabs.list and web.tabs.select + example for tab next/prev and selection ui
Diffstat (limited to '')
-rw-r--r--config.lua46
-rw-r--r--src/InputMediator.cpp4
-rw-r--r--src/LuaRuntime.cpp51
-rw-r--r--src/LuaRuntime.hpp4
-rw-r--r--src/utils.hpp2
-rw-r--r--src/widgets/WebViewStack.cpp8
-rw-r--r--src/widgets/WebViewStack.hpp21
7 files changed, 111 insertions, 25 deletions
diff --git a/config.lua b/config.lua
index 4bd725c..053db68 100644
--- a/config.lua
+++ b/config.lua
@@ -44,14 +44,14 @@ local urls = {
}
-- Open in new tab
-web.keymap.set('n', 't', function()
+web.keymap.set('n', 'o', function()
Dmenu.select(urls, { prompt = 'Open tab:' }, function(err, result)
if err or not result then return end
web.tabs.new(trim(result))
end)
end)
-- Open in current tab
-web.keymap.set('n', 'o', function()
+web.keymap.set('n', '<s-o>', function()
Dmenu.select(urls, { prompt = 'Open:' }, function(err, result)
if err or not result then return end
web.open(trim(result))
@@ -73,9 +73,45 @@ web.keymap.set('n', '<s-h>', function() web.history.back(); end)
web.keymap.set('n', '<s-l>', function() web.history.forward(); end)
web.keymap.set('n', '<c-w>', function() web.tabs.close(); end)
--- Dummy test keymap
-web.keymap.set('n', 'm', function()
- print('Hello world. Keypress test')
+-- Tab select
+web.keymap.set('n', 'b', function()
+ local tabsList = {}
+ for _, tab in ipairs(web.tabs.list()) do
+ table.insert(tabsList, tab.id .. ': ' .. tab.title .. ' (' .. tab.url)
+ end
+ Dmenu.select(tabsList, { prompt = 'Tab:' }, function(err, result)
+ if err or not result then return end
+ local id, _ = trim(result):gsub("%s*:.*$", "")
+ web.tabs.select(id)
+ end)
+end)
+
+local function get_current_tab_index()
+ local currentTab = web.tabs.current();
+ for index, tab in ipairs(web.tabs.list()) do
+ if tab.id == currentTab then
+ return index
+ end
+ end
+end
+
+-- Next tab
+web.keymap.set('n', 'tn', function()
+ local tabs = web.tabs.list()
+ if #tabs <= 1 then return end
+ local index = get_current_tab_index() + 1;
+ if index > #tabs then index = 1 end
+ web.tabs.select(tabs[index].id)
+end)
+
+-- Prev tab
+web.keymap.set('n', 'tp', function()
+ print('-----------')
+ local tabs = web.tabs.list()
+ if #tabs <= 1 then return end
+ local index = get_current_tab_index() - 1;
+ if index <= 0 then index = #tabs end
+ web.tabs.select(tabs[index].id)
end)
print('ending...')
diff --git a/src/InputMediator.cpp b/src/InputMediator.cpp
index 2a36665..91393c2 100644
--- a/src/InputMediator.cpp
+++ b/src/InputMediator.cpp
@@ -23,9 +23,13 @@ InputMediator::InputMediator(WebViewStack *webview_stack,
&WebViewStack::webview_history_forward);
connect(lua_runtime, &LuaRuntime::webview_closed, webview_stack,
&WebViewStack::close);
+ connect(lua_runtime, &LuaRuntime::webview_selected, webview_stack,
+ &WebViewStack::focus_webview);
lua_runtime->set_current_tab_id_fetcher(
[this]() { return this->webview_stack->current_webview_id(); });
+ lua_runtime->set_webview_data_list_fetcher(
+ [this]() { return this->webview_stack->get_webview_list(); });
}
void InputMediator::add_keymap(const QString &mode_string,
diff --git a/src/LuaRuntime.cpp b/src/LuaRuntime.cpp
index 1fb722a..0b5e698 100644
--- a/src/LuaRuntime.cpp
+++ b/src/LuaRuntime.cpp
@@ -1,3 +1,4 @@
+#include "widgets/WebViewStack.hpp"
#include <QtCore>
#include <lua.hpp>
extern "C" {
@@ -115,7 +116,6 @@ int LuaRuntime::lua_add_keymap(lua_State *state) {
void LuaRuntime::load_file(const QString &path) {
queue_task([this, path]() {
preserve_top(state, {
- qDebug() << "Loading: " << path;
if (luaL_dofile(state, path.toStdString().c_str()) != LUA_OK) {
qDebug() << "Load file error:" << lua_tostring(state, -1);
}
@@ -148,6 +148,8 @@ void LuaRuntime::init_web_lib() {
{"close", &LuaRuntime::lua_tab_closed},
{"new", &LuaRuntime::lua_on_url_tab_open},
{"current", &LuaRuntime::lua_get_current_tab_id},
+ {"list", &LuaRuntime::lua_get_tab_list},
+ {"select", &LuaRuntime::lua_tab_selected},
{nullptr, nullptr},
};
luaL_newlib(state, webtabs);
@@ -172,13 +174,40 @@ int LuaRuntime::lua_get_current_tab_id(lua_State *state) {
return 1;
}
+int LuaRuntime::lua_get_tab_list(lua_State *state) {
+ auto *runtime = LuaRuntime::instance();
+ auto tabs = runtime->fetch_webview_data_list();
+ lua_newtable(state);
+
+ int index = 1; // 1-indexed
+ for (auto &tab : tabs) {
+ lua_newtable(state);
+
+ lua_pushstring(state, "id");
+ lua_pushinteger(state, tab.id);
+ lua_settable(state, -3);
+
+ lua_pushstring(state, "url");
+ lua_pushstring(state, tab.url.toStdString().c_str());
+ lua_settable(state, -3);
+
+ lua_pushstring(state, "title");
+ lua_pushstring(state, tab.title.toStdString().c_str());
+ lua_settable(state, -3);
+
+ lua_rawseti(state, -2, 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);
- qsizetype tab_id;
+ WebViewId tab_id;
if (lua_isnoneornil(state, 2)) {
tab_id = runtime->fetch_current_tab_id();
} else {
@@ -195,7 +224,7 @@ int LuaRuntime::lua_history_forward(lua_State *state) {
qsizetype history_index =
lua_isnoneornil(state, 1) ? 1 : lua_tointeger(state, 1);
- qsizetype tab_id;
+ WebViewId tab_id;
if (lua_isnoneornil(state, 2)) {
tab_id = runtime->fetch_current_tab_id();
} else {
@@ -209,17 +238,27 @@ int LuaRuntime::lua_history_forward(lua_State *state) {
int LuaRuntime::lua_tab_closed(lua_State *state) {
auto *runtime = LuaRuntime::instance();
- qsizetype tab_id;
- if (lua_isnoneornil(state, 2)) {
+ WebViewId tab_id;
+ if (lua_isnoneornil(state, 1)) {
tab_id = runtime->fetch_current_tab_id();
} else {
- tab_id = lua_tointeger(state, 2);
+ tab_id = lua_tointeger(state, 1);
}
emit runtime->webview_closed(tab_id);
return 1;
}
+int LuaRuntime::lua_tab_selected(lua_State *state) {
+ if (lua_isnoneornil(state, 1))
+ return 1; // TODO: return nil (for others too)
+
+ auto *runtime = LuaRuntime::instance();
+ WebViewId tab_id = lua_tointeger(state, 1);
+ emit runtime->webview_selected(tab_id);
+ return 1;
+}
+
LuaRuntime::~LuaRuntime() {
stop_event_loop();
lua_close(state);
diff --git a/src/LuaRuntime.hpp b/src/LuaRuntime.hpp
index a13fe1e..209f8b7 100644
--- a/src/LuaRuntime.hpp
+++ b/src/LuaRuntime.hpp
@@ -37,6 +37,7 @@ public:
DEFINE_GETTER(get_state, state)
DEFINE_FETCHER(qsizetype(), current_tab_id)
+ DEFINE_FETCHER(QList<WebViewData>(), webview_data_list)
signals:
void url_opened(QString url, OpenType open_type);
@@ -46,6 +47,7 @@ signals:
void history_back_requested(WebViewId webview_id, qsizetype history_index);
void history_forward_requested(WebViewId webview_id, qsizetype history_index);
void webview_closed(WebViewId webview_id);
+ void webview_selected(WebViewId webview_id);
// void output_produced(QVariant value);
protected:
@@ -59,6 +61,8 @@ protected:
static int lua_history_back(lua_State *state);
static int lua_history_forward(lua_State *state);
static int lua_tab_closed(lua_State *state);
+ static int lua_get_tab_list(lua_State *state);
+ static int lua_tab_selected(lua_State *state);
private:
lua_State *state;
diff --git a/src/utils.hpp b/src/utils.hpp
index eace39e..e3de4dc 100644
--- a/src/utils.hpp
+++ b/src/utils.hpp
@@ -15,4 +15,4 @@
void set_##NAME##_fetcher(const std::function<TYPE> &fetcher) { \
fetch_##NAME = fetcher; \
} \
- std::function<qsizetype()> fetch_##NAME = []() { return -1; };
+ std::function<TYPE> fetch_##NAME;
diff --git a/src/widgets/WebViewStack.cpp b/src/widgets/WebViewStack.cpp
index 1d0a35e..fda4f28 100644
--- a/src/widgets/WebViewStack.cpp
+++ b/src/widgets/WebViewStack.cpp
@@ -50,10 +50,12 @@ WebView *WebViewStack::create_new_webview(const QUrl &url, bool focus) {
return webview;
}
-QList<Tab> WebViewStack::get_webview_list() {
- QList<Tab> urls;
+QList<WebViewData> WebViewStack::get_webview_list() {
+ QList<WebViewData> urls;
for (auto &view : webview_list)
- urls.append(Tab{.url = view->url().toString(), .title = view->title()});
+ urls.append(WebViewData{.id = view->get_id(),
+ .url = view->url().toString(),
+ .title = view->title()});
return urls;
}
diff --git a/src/widgets/WebViewStack.hpp b/src/widgets/WebViewStack.hpp
index 3c69888..b675af5 100644
--- a/src/widgets/WebViewStack.hpp
+++ b/src/widgets/WebViewStack.hpp
@@ -17,7 +17,8 @@ enum OpenType : uint8_t {
OpenUrlInWindow
};
-struct Tab {
+struct WebViewData {
+ WebViewId id;
QString url;
QString title;
};
@@ -31,29 +32,29 @@ public:
QWidget *parent = nullptr);
std::vector<QUrl> urls(); // TODO: Remove
- QList<Tab> get_webview_list();
+ QList<WebViewData> get_webview_list();
WebView *current_webview();
WebViewId current_webview_id();
uint32_t count();
QUrl current_url();
- WebView *get_webview(WebViewId webview_id);
uint32_t current_webview_index();
-public slots: // NOLINT(readability-redundant-access-specifiers)
+protected:
+ void set_current_url(const QUrl &url);
+ WebView *create_new_webview(const QUrl &url, bool focus = false);
+ int32_t get_webview_index(WebViewId webview_id);
+ WebView *get_webview(WebViewId webview_id);
+
+public slots:
void open_url(const QUrl &url, OpenType open_type = OpenType::OpenUrl);
void webview_history_back(WebViewId webview_id, qsizetype history_index);
void webview_history_forward(WebViewId webview_id, qsizetype history_index);
void close(WebViewId webview_id);
void focus_webview(WebViewId webview_id);
-private slots:
+protected slots:
void on_new_webview_request(const QWebEngineNewWindowRequest &request);
-protected:
- void set_current_url(const QUrl &url);
- WebView *create_new_webview(const QUrl &url, bool focus = false);
- int32_t get_webview_index(WebViewId webview_id);
-
private:
const Configuration *configuration;
QWebEngineProfile *profile;