aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2025-05-01 23:41:54 +0530
committerAkshay Nair <phenax5@gmail.com>2025-05-02 16:21:45 +0530
commit9c812753e2b1f01b2e0c85be9904ff7694f0e6ec (patch)
treef308228c63fc8eeb526c901e80746d8da633b352
parentf0faa92246c1f5fc58546051ace2d047869447df (diff)
downloadnull-browser-9c812753e2b1f01b2e0c85be9904ff7694f0e6ec.tar.gz
null-browser-9c812753e2b1f01b2e0c85be9904ff7694f0e6ec.zip
Implement NotificationReceived event
Diffstat (limited to '')
-rw-r--r--TODO.org5
-rw-r--r--init.lua14
-rw-r--r--src/events/Event.hpp9
-rw-r--r--src/events/NotificationReceivedEvent.hpp47
-rw-r--r--src/events/PermissionRequestedEvent.hpp58
-rw-r--r--src/widgets/BrowserApp.cpp10
-rw-r--r--src/widgets/BrowserWindow.cpp4
-rw-r--r--src/widgets/BrowserWindow.hpp3
-rw-r--r--src/widgets/WebViewStack.cpp1
9 files changed, 106 insertions, 45 deletions
diff --git a/TODO.org b/TODO.org
index d869829..05819af 100644
--- a/TODO.org
+++ b/TODO.org
@@ -10,9 +10,10 @@
- [X] table extend/merge
- [X] window.opener controls (use tab for now?)
- [X] Permission requests handling
+- [X] Notifications
- [-] Tests for api
-- [ ] Permission requests persist
-- [ ] Notifications
+- [ ] Config permission persist (persist_permission_state = 'always' | 'never' | 'in_memory')
+- [ ] Permission list/allow/deny api
- [ ] Fullscreen
- [ ] Zoom in/out
diff --git a/init.lua b/init.lua
index af0458c..bbffb50 100644
--- a/init.lua
+++ b/init.lua
@@ -23,8 +23,7 @@ web.event.add_listener('PermissionRequested', {
callback = function(event)
dmenu.select({ 'Allow', 'Deny' }, { prompt = 'Requesting permission for ' .. event.permission_type },
function(err, choice)
- if err then return print('-- x permission ignored') end
- print('----- permission', event.permission_type, web.inspect(choice))
+ if err then return end
if web.utils.string_trim(choice) == 'Allow' then
event.accept()
else
@@ -34,4 +33,15 @@ web.event.add_listener('PermissionRequested', {
end,
})
+web.event.add_listener('NotificationReceived', {
+ callback = function(event)
+ local args = { '-a', 'null-browser', '-r', event.tag, event.title, event.message }
+ uv.spawn('notify-send', { args = args }, function(code)
+ if code ~= 0 then
+ print('[notify-send] Exit with status code: ' .. code)
+ end
+ end)
+ end,
+})
+
print('ending...')
diff --git a/src/events/Event.hpp b/src/events/Event.hpp
index a0853d6..11f1141 100644
--- a/src/events/Event.hpp
+++ b/src/events/Event.hpp
@@ -8,6 +8,15 @@
lua_push##TYPE(state, VALUE); \
lua_settable(state, -3);
+// Not a huge fan but looks nice
+#define SET_FIELD_CLOSURE_WITH_SELF(NAME, CLOSURE) \
+ lua_pushstring(state, NAME); \
+ lua_pushlightuserdata(state, (void *)this); \
+ lua_pushcclosure(state, CLOSURE, 1); \
+ lua_settable(state, -3);
+
+#define GET_CLOSURE_SELF(TYPE) static_cast<TYPE>(lua_touserdata(state, lua_upvalueindex(1)));
+
class Event {
public:
QString kind = "-";
diff --git a/src/events/NotificationReceivedEvent.hpp b/src/events/NotificationReceivedEvent.hpp
new file mode 100644
index 0000000..ade2132
--- /dev/null
+++ b/src/events/NotificationReceivedEvent.hpp
@@ -0,0 +1,47 @@
+#pragma once
+
+#include <QWebEngineNotification>
+#include <QtCore>
+#include <lua.hpp>
+
+#include "events/Event.hpp"
+
+class NotificationReceivedEvent : public Event {
+public:
+ std::unique_ptr<QWebEngineNotification> notification;
+
+ NotificationReceivedEvent(std::unique_ptr<QWebEngineNotification> notification)
+ : notification(std::move(notification)) {
+ kind = "NotificationReceived";
+ }
+
+ void lua_push(lua_State *state) const override {
+ lua_newtable(state);
+ SET_FIELD("type", string, kind.toStdString().c_str())
+ SET_FIELD("title", string, notification->title().toStdString().c_str())
+ SET_FIELD("message", string, notification->message().toStdString().c_str())
+ SET_FIELD("tag", string, notification->tag().toStdString().c_str())
+ SET_FIELD("origin", string, notification->origin().toString().toStdString().c_str())
+
+ SET_FIELD_CLOSURE_WITH_SELF("click", [](lua_State *state) {
+ auto *event = GET_CLOSURE_SELF(NotificationReceivedEvent *);
+ event->notification->click();
+ lua_pushnil(state);
+ return 1;
+ });
+
+ SET_FIELD_CLOSURE_WITH_SELF("show", [](lua_State *state) {
+ auto *event = GET_CLOSURE_SELF(NotificationReceivedEvent *);
+ event->notification->show();
+ lua_pushnil(state);
+ return 1;
+ });
+
+ SET_FIELD_CLOSURE_WITH_SELF("close", [](lua_State *state) {
+ auto *event = GET_CLOSURE_SELF(NotificationReceivedEvent *);
+ event->notification->close();
+ lua_pushnil(state);
+ return 1;
+ });
+ }
+};
diff --git a/src/events/PermissionRequestedEvent.hpp b/src/events/PermissionRequestedEvent.hpp
index 089cc99..ec03ea5 100644
--- a/src/events/PermissionRequestedEvent.hpp
+++ b/src/events/PermissionRequestedEvent.hpp
@@ -39,6 +39,28 @@ public:
win_id);
}
+ void lua_push(lua_State *state) const override {
+ lua_newtable(state);
+ SET_FIELD("type", string, kind.toStdString().c_str())
+ SET_FIELD("permission_type", string, permission_type())
+ SET_FIELD("view_id", integer, webview_id)
+ SET_FIELD("win_id", integer, win_id)
+
+ SET_FIELD_CLOSURE_WITH_SELF("accept", [](lua_State *state) {
+ auto *event = GET_CLOSURE_SELF(PermissionRequestedEvent *);
+ event->accept_request();
+ lua_pushnil(state);
+ return 1;
+ });
+
+ SET_FIELD_CLOSURE_WITH_SELF("reject", [](lua_State *state) {
+ auto *event = GET_CLOSURE_SELF(PermissionRequestedEvent *);
+ event->reject_request();
+ lua_pushnil(state);
+ return 1;
+ });
+ }
+
[[nodiscard]] const char *permission_type() const {
switch (premission_type) {
case QWebEnginePermission::PermissionType::MediaAudioCapture:
@@ -65,40 +87,4 @@ public:
return "Unsupported";
}
}
-
- void lua_push(lua_State *state) const override {
- lua_newtable(state);
- SET_FIELD("type", string, kind.toStdString().c_str())
- SET_FIELD("permission_type", string, permission_type())
- SET_FIELD("view_id", integer, webview_id)
- SET_FIELD("win_id", integer, win_id)
-
- lua_pushstring(state, "accept");
- lua_pushlightuserdata(state, (void *)this);
- lua_pushcclosure(
- state,
- [](lua_State *state) {
- void *userdata = lua_touserdata(state, lua_upvalueindex(1));
- auto *event = static_cast<PermissionRequestedEvent *>(userdata);
- event->accept_request();
- lua_pushnil(state);
- return 1;
- },
- 1);
- lua_settable(state, -3);
-
- lua_pushstring(state, "reject");
- lua_pushlightuserdata(state, (void *)this);
- lua_pushcclosure(
- state,
- [](lua_State *state) {
- void *userdata = lua_touserdata(state, lua_upvalueindex(1));
- auto *event = static_cast<PermissionRequestedEvent *>(userdata);
- event->reject_request();
- lua_pushnil(state);
- return 1;
- },
- 1);
- lua_settable(state, -3);
- }
};
diff --git a/src/widgets/BrowserApp.cpp b/src/widgets/BrowserApp.cpp
index 1362941..32ac598 100644
--- a/src/widgets/BrowserApp.cpp
+++ b/src/widgets/BrowserApp.cpp
@@ -1,9 +1,11 @@
#include <QDir>
#include <QKeyEvent>
+#include <QWebEngineNotification>
#include <QtCore>
#include "LuaRuntime.hpp"
#include "WindowActionRouter.hpp"
+#include "events/NotificationReceivedEvent.hpp"
#include "widgets/BrowserApp.hpp"
#include "widgets/BrowserWindow.hpp"
@@ -35,6 +37,12 @@ BrowserApp::BrowserApp(Configuration &configuration) : configuration(configurati
for (auto *profile : profiles) {
profile->setDownloadPath(configuration.downloads_dir());
profile->setHttpUserAgent(configuration.user_agent());
+ profile->setNotificationPresenter([](std::unique_ptr<QWebEngineNotification> notification) {
+ auto *event = new NotificationReceivedEvent(std::move(notification));
+ WindowActionRouter::instance().dispatch_event(event);
+ });
+ profile->setPersistentPermissionsPolicy(
+ QWebEngineProfile::PersistentPermissionsPolicy::StoreInMemory);
}
connect(&window_action_router, &WindowActionRouter::new_window_requested, this,
@@ -42,7 +50,7 @@ BrowserApp::BrowserApp(Configuration &configuration) : configuration(configurati
};
BrowserWindow *BrowserApp::create_window(const QStringList &urls) {
- auto *window = new BrowserWindow((const Configuration &)configuration, urls);
+ auto *window = new BrowserWindow((const Configuration &)configuration, &default_profile, urls);
window->setWindowTitle("null-browser");
WindowActionRouter::instance().add_window(window);
diff --git a/src/widgets/BrowserWindow.cpp b/src/widgets/BrowserWindow.cpp
index f4ea97d..ba0c244 100644
--- a/src/widgets/BrowserWindow.cpp
+++ b/src/widgets/BrowserWindow.cpp
@@ -10,7 +10,8 @@
#include "widgets/BrowserWindow.hpp"
#include "widgets/WebViewStack.hpp"
-BrowserWindow::BrowserWindow(const Configuration &configuration, const QStringList &urls)
+BrowserWindow::BrowserWindow(const Configuration &configuration, QWebEngineProfile *profile,
+ const QStringList &urls)
: QMainWindow(nullptr), configuration(configuration) {
setCentralWidget(new QWidget());
@@ -22,7 +23,6 @@ BrowserWindow::BrowserWindow(const Configuration &configuration, const QStringLi
centralWidget()->setLayout(layout);
// Webengine profile
- auto *profile = new QWebEngineProfile("null-browser");
profile->setDownloadPath(configuration.downloads_dir());
profile->setHttpUserAgent(configuration.user_agent());
diff --git a/src/widgets/BrowserWindow.hpp b/src/widgets/BrowserWindow.hpp
index 6f20e4b..ee59e5a 100644
--- a/src/widgets/BrowserWindow.hpp
+++ b/src/widgets/BrowserWindow.hpp
@@ -12,7 +12,8 @@ class BrowserWindow : public QMainWindow {
Q_OBJECT
public:
- BrowserWindow(const Configuration &configuration, const QStringList &urls = {});
+ BrowserWindow(const Configuration &configuration,
+ QWebEngineProfile *profile = new QWebEngineProfile, const QStringList &urls = {});
DEFINE_GETTER(mediator, win_mediator)
DEFINE_GETTER(get_id, win_id)
diff --git a/src/widgets/WebViewStack.cpp b/src/widgets/WebViewStack.cpp
index 37e7dca..6bbd5b5 100644
--- a/src/widgets/WebViewStack.cpp
+++ b/src/widgets/WebViewStack.cpp
@@ -2,7 +2,6 @@
#include <QWebEngineFindTextResult>
#include <QWebEngineHistory>
#include <QWebEngineNewWindowRequest>
-#include <QWebEngineNotification>
#include <QWebEngineProfile>
#include <cstdint>
#include <cstdlib>