aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2025-04-05 23:45:55 +0530
committerAkshay Nair <phenax5@gmail.com>2025-04-06 00:47:02 +0530
commitbbde1438e9c31cc83d8c4835ea97a0eaeae4e192 (patch)
tree88840b73176dee8bd7da70c36f19a32bafdd5d6c
parentb77a6444f94ce8d05962af9039c31851e224be5c (diff)
downloadnull-browser-bbde1438e9c31cc83d8c4835ea97a0eaeae4e192.tar.gz
null-browser-bbde1438e9c31cc83d8c4835ea97a0eaeae4e192.zip
Close window when no tabs left
Diffstat (limited to '')
-rw-r--r--TODO.org4
-rw-r--r--config.lua7
-rw-r--r--lua/null-browser/extras/dmenu.lua3
-rw-r--r--lua/null-browser/extras/history.lua4
-rw-r--r--spec/WebViewStackSpec.cpp9
-rw-r--r--src/Configuration.hpp2
-rw-r--r--src/WindowActionRouter.cpp18
-rw-r--r--src/WindowActionRouter.hpp2
-rw-r--r--src/WindowMediator.cpp14
-rw-r--r--src/WindowMediator.hpp1
-rw-r--r--src/widgets/BrowserWindow.cpp3
-rw-r--r--src/widgets/WebViewStack.cpp11
-rw-r--r--src/widgets/WebViewStack.hpp1
13 files changed, 54 insertions, 25 deletions
diff --git a/TODO.org b/TODO.org
index acf710e..5c72e73 100644
--- a/TODO.org
+++ b/TODO.org
@@ -18,7 +18,8 @@
- [X] Url changed event
- [X] History storage
- [X] History completion
-- [ ] Close window if last tab closed
+- [X] Close window if last tab closed
+- [ ] Configuration lua api
- [ ] Switch to __internals
- [ ] Tests for api
- [ ] Log stdout, errors and results from lua somewhere
@@ -88,4 +89,5 @@ web.history.back(1, { win = 1 }) -- Back for current tab in win 1
web.keymap.set('n', '<c-r>', ..., { tab = 1 }) -- Set keymap for tab 1
web.keymap.set('n', '<c-r>', ..., { win = 1 }) -- Set keymap for win 1
+web.opt.new_tab_url = 'https://duckduckgo.com'
#+end_src
diff --git a/config.lua b/config.lua
index 4199574..360ef11 100644
--- a/config.lua
+++ b/config.lua
@@ -43,6 +43,13 @@ web.keymap.set('n', '<s-o>', function()
web.tabs.set_url(trim(result))
end)
end)
+-- Delete from history
+web.keymap.set('n', '<c-h>d', function()
+ dmenu.select(history.list(), { prompt = 'Delete history:' }, function(err, result)
+ if err or not result then return end
+ history.delete(trim(result))
+ end)
+end)
-- Update current url
web.keymap.set('n', '<c-l>', function()
local tabs = web.tabs.list()
diff --git a/lua/null-browser/extras/dmenu.lua b/lua/null-browser/extras/dmenu.lua
index 1bd467f..d08eb6a 100644
--- a/lua/null-browser/extras/dmenu.lua
+++ b/lua/null-browser/extras/dmenu.lua
@@ -1,3 +1,6 @@
+--- @type table
+local uv = uv
+
local dmenu = {}
function dmenu.select(list, opts, callback)
diff --git a/lua/null-browser/extras/history.lua b/lua/null-browser/extras/history.lua
index fe3f72f..4304dc0 100644
--- a/lua/null-browser/extras/history.lua
+++ b/lua/null-browser/extras/history.lua
@@ -14,7 +14,7 @@ function history.list()
for line in string.gmatch(data, '[^\r\n]+') do
local already_exists = false
for _, url in ipairs(urls) do
- if url == line then already_exists = true end
+ if url == line or url .. '/' == line then already_exists = true end
end
if #urls >= history.max_entires then break end
if not already_exists then
@@ -43,7 +43,7 @@ end
function history.delete(url_to_delete)
history.update(function(urls)
- for index, url in urls do
+ for index, url in ipairs(urls) do
if url == url_to_delete then
table.remove(urls, index)
return urls
diff --git a/spec/WebViewStackSpec.cpp b/spec/WebViewStackSpec.cpp
index 0559b43..0563a5f 100644
--- a/spec/WebViewStackSpec.cpp
+++ b/spec/WebViewStackSpec.cpp
@@ -132,18 +132,17 @@ private slots:
context("when close is called on current webview");
context("- and there is only 1 tab");
- it("closes the tab and opens empty tab in its place") {
+ it("requests closing window") {
Configuration configuration;
WebViewStack webview_stack(&configuration);
+ QSignalSpy close_window_requested_spy(&webview_stack, &WebViewStack::close_window_requested);
webview_stack.open_url(QUrl("https://a.com"));
QCOMPARE(webview_stack.count(), 1);
webview_stack.close(webview_stack.current_webview_id());
+ close_window_requested_spy.wait(100);
- QCOMPARE(webview_stack.count(), 1);
- QCOMPARE(webview_stack.urls(), (std::vector<QUrl>{configuration.new_tab_url}));
- QCOMPARE(webview_stack.current_webview_index(), 0);
- QCOMPARE(webview_stack.current_url(), configuration.new_tab_url);
+ QCOMPARE(close_window_requested_spy.count(), 1);
}
context("when close is called");
diff --git a/src/Configuration.hpp b/src/Configuration.hpp
index 032d12e..837e3e6 100644
--- a/src/Configuration.hpp
+++ b/src/Configuration.hpp
@@ -9,4 +9,6 @@ public:
using QObject::QObject;
QUrl new_tab_url = QUrl("https://lite.duckduckgo.com");
+
+ bool close_window_when_no_tabs = true;
};
diff --git a/src/WindowActionRouter.cpp b/src/WindowActionRouter.cpp
index c1051ad..d1cd816 100644
--- a/src/WindowActionRouter.cpp
+++ b/src/WindowActionRouter.cpp
@@ -46,9 +46,21 @@ void WindowActionRouter::add_window(BrowserWindow *window) {
auto win_id = last_id;
last_id++;
- window_map.insert({win_id, window});
window->set_id(win_id);
- connect(window, &BrowserWindow::closed, this, [this, win_id]() { window_map.erase(win_id); });
+ {
+ const std::lock_guard<std::mutex> lock(window_map_mutex);
+ window_map.insert({win_id, window});
+ }
+
+ connect(window, &BrowserWindow::closed, this, [this, window]() {
+ window->disconnect();
+ LuaRuntime::instance().queue_task([this, window]() {
+ const std::lock_guard<std::mutex> lock(window_map_mutex);
+ window_map.erase(window->get_id());
+ });
+ });
+ connect(window->mediator(), &WindowMediator::close_window_requested, window,
+ [window]() { window->close(); });
connect(window->mediator(), &WindowMediator::new_window_requested, this,
&WindowActionRouter::new_window_requested);
}
@@ -63,6 +75,7 @@ void WindowActionRouter::add_keymap(const QString &mode_string, const QString &k
}
WebViewId WindowActionRouter::fetch_current_tab_id(WindowId win_id) {
+ const std::lock_guard<std::mutex> lock(window_map_mutex);
for (auto &pair : window_map) {
auto *win = pair.second;
auto is_current_window = win_id == win->get_id() || (win_id == 0 && win->isActiveWindow());
@@ -74,6 +87,7 @@ WebViewId WindowActionRouter::fetch_current_tab_id(WindowId win_id) {
}
QList<WebViewData> WindowActionRouter::fetch_webview_data_list(WindowId win_id) {
+ const std::lock_guard<std::mutex> lock(window_map_mutex);
for (auto &pair : window_map) {
auto *win = pair.second;
auto is_current_window = win_id == win->get_id() || (win_id == 0 && win->isActiveWindow());
diff --git a/src/WindowActionRouter.hpp b/src/WindowActionRouter.hpp
index c72aaaf..3c82b28 100644
--- a/src/WindowActionRouter.hpp
+++ b/src/WindowActionRouter.hpp
@@ -4,6 +4,7 @@
#include <QtCore>
#include <cstdint>
#include <functional>
+#include <mutex>
#include "EventQueue.hpp"
#include "widgets/BrowserWindow.hpp"
@@ -46,6 +47,7 @@ signals:
void new_window_requested(const QUrl &url);
private:
+ std::mutex window_map_mutex;
WindowMap window_map;
uint64_t last_id = 1;
Configuration *configuration;
diff --git a/src/WindowMediator.cpp b/src/WindowMediator.cpp
index 0596d28..942207d 100644
--- a/src/WindowMediator.cpp
+++ b/src/WindowMediator.cpp
@@ -5,23 +5,21 @@
#include "WindowMediator.hpp"
#include "widgets/WebViewStack.hpp"
-WindowMediator::WindowMediator(WebViewStack *webview_stack)
- : webview_stack(webview_stack) {
+WindowMediator::WindowMediator(WebViewStack *webview_stack) : webview_stack(webview_stack) {
connect(this, &WindowMediator::history_back_requested, webview_stack,
&WebViewStack::webview_history_back);
connect(this, &WindowMediator::history_forward_requested, webview_stack,
&WebViewStack::webview_history_forward);
- connect(this, &WindowMediator::url_opened, webview_stack,
- &WebViewStack::open_url);
- connect(this, &WindowMediator::webview_closed, webview_stack,
- &WebViewStack::close);
- connect(this, &WindowMediator::webview_selected, webview_stack,
- &WebViewStack::focus_webview);
+ connect(this, &WindowMediator::url_opened, webview_stack, &WebViewStack::open_url);
+ connect(this, &WindowMediator::webview_closed, webview_stack, &WebViewStack::close);
+ connect(this, &WindowMediator::webview_selected, webview_stack, &WebViewStack::focus_webview);
// Delegate signal
connect(webview_stack, &WebViewStack::new_window_requested, this,
&WindowMediator::new_window_requested);
+ connect(webview_stack, &WebViewStack::close_window_requested, this,
+ &WindowMediator::close_window_requested);
}
WindowMediator::~WindowMediator() {
diff --git a/src/WindowMediator.hpp b/src/WindowMediator.hpp
index e8050e9..ea1dd52 100644
--- a/src/WindowMediator.hpp
+++ b/src/WindowMediator.hpp
@@ -24,6 +24,7 @@ signals:
void webview_closed(WebViewId webview_id);
void webview_selected(WebViewId webview_id);
void new_window_requested(const QUrl &url);
+ void close_window_requested();
private:
WebViewStack *webview_stack;
diff --git a/src/widgets/BrowserWindow.cpp b/src/widgets/BrowserWindow.cpp
index aad551d..f1b786b 100644
--- a/src/widgets/BrowserWindow.cpp
+++ b/src/widgets/BrowserWindow.cpp
@@ -2,6 +2,7 @@
#include <QStackedLayout>
#include <QVBoxLayout>
#include <QtCore>
+#include <qmainwindow.h>
#include "Configuration.hpp"
#include "WindowMediator.hpp"
@@ -10,7 +11,7 @@
#include "widgets/WebViewStack.hpp"
BrowserWindow::BrowserWindow(const Configuration &configuration, const QStringList &urls)
- : configuration(configuration) {
+ : QMainWindow(nullptr), configuration(configuration) {
setCentralWidget(new QWidget());
// Root stacked layout
diff --git a/src/widgets/WebViewStack.cpp b/src/widgets/WebViewStack.cpp
index ae95ea6..8c432f1 100644
--- a/src/widgets/WebViewStack.cpp
+++ b/src/widgets/WebViewStack.cpp
@@ -125,13 +125,12 @@ void WebViewStack::close(WebViewId webview_id) {
disconnect(webview->page());
webview->deleteLater();
- // TODO: Focus on different webview
- // focus_webview();
-
- // TODO: Close window on empty
if (webview_list.isEmpty()) {
- // window()->close();
- create_new_webview(configuration->new_tab_url, true);
+ if (configuration->close_window_when_no_tabs) {
+ emit close_window_requested();
+ } else {
+ create_new_webview(configuration->new_tab_url, true);
+ }
}
}
diff --git a/src/widgets/WebViewStack.hpp b/src/widgets/WebViewStack.hpp
index 23b9382..7cc2143 100644
--- a/src/widgets/WebViewStack.hpp
+++ b/src/widgets/WebViewStack.hpp
@@ -47,6 +47,7 @@ public:
signals:
void current_webview_title_changed(int index);
void new_window_requested(const QUrl &url);
+ void close_window_requested();
protected:
void set_current_url(const QUrl &url);