This commit is contained in:
2026-03-03 09:39:15 +01:00
parent 769d5681d4
commit 35aae3b707
9 changed files with 136 additions and 40 deletions

View File

@@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.14)
project(rktwebview_qt LANGUAGES CXX)
set(QT_DEBUG_FIND_PACKAGE ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

View File

@@ -4,7 +4,7 @@
#include <string.h>
#include <chrono>
#include <stdint.h>
#include <unistd.h>
//#include <unistd.h>
#include <fcntl.h>
#include "rktwebview_qt.h"
#include "webviewapp.h"
@@ -18,10 +18,10 @@ uint64_t current_ms() {
// Main C Interface
/////////////////////////////////////////////////////////////////////
static int pipefd[2];
static bool started = false;
static pid_t webview_process;
static bool cannot_fork_or_pipe = false;
//static int pipefd[2];
//static bool started = false;
//static pid_t webview_process;
//static bool cannot_fork_or_pipe = false;
Rktwebview_qt *handler = nullptr;
@@ -51,19 +51,21 @@ void rkt_webview_init()
}
}
int rkt_webview_create(int parent)
int rkt_webview_create(int parent, void (*js_event_cb)(const char *))
{
//rkt_webview_init();
return handler->rktWebViewCreate(parent);
rkt_webview_init();
return handler->rktWebViewCreate(parent, js_event_cb);
}
void rkt_webview_close(int wv)
{
rkt_webview_init();
handler->rktWebViewClose(wv);
}
result_t rkt_webview_set_url(int wv, const char *url)
{
rkt_webview_init();
result_t r = handler->rktSetUrl(wv, url);
return r;
}
@@ -151,7 +153,7 @@ void rkt_webview_process_events(int for_ms)
int64_t end_ms = start_ms + for_ms;
while (current_ms() < end_ms) {
usleep(500); // sleep 0.5 ms
QThread::usleep(500); // sleep 0.5 ms
handler->doEvents();
}
}

View File

@@ -47,7 +47,7 @@ typedef enum {
RKTWEBVIEW_QT_EXPORT void rkt_webview_init();
RKTWEBVIEW_QT_EXPORT void rkt_webview_process_events(int for_ms);
RKTWEBVIEW_QT_EXPORT int rkt_webview_create(int parent);
RKTWEBVIEW_QT_EXPORT int rkt_webview_create(int parent, void (*js_event_cb)(const char *msg));
RKTWEBVIEW_QT_EXPORT void rkt_webview_close(int wv);
RKTWEBVIEW_QT_EXPORT result_t rkt_webview_set_url(int wv, const char *url);
RKTWEBVIEW_QT_EXPORT result_t rkt_webview_set_html(int wv, const char *html);

View File

@@ -5,6 +5,8 @@
#include <QApplication>
#include <QTimer>
#include <QSemaphore>
#include <QJsonDocument>
#include <QJsonObject>
#define COMMAND_QUIT 1
#define COMMAND_CLOSE 2
@@ -25,9 +27,15 @@ public:
}
};
static QString jsonString(QJsonObject obj)
{
QJsonDocument doc(obj);
QString j = QString::fromUtf8(doc.toJson(QJsonDocument::JsonFormat::Compact));
return j;
}
void Rktwebview_qt::processCommands()
{
printf("COmmand processing\n");
while(!_command_queue.empty()) {
Command *cmd = _command_queue.dequeue();
@@ -39,6 +47,10 @@ void Rktwebview_qt::processCommands()
break;
case COMMAND_CREATE: {
int parent = cmd->args[0].toInt();
void *f = cmd->args[1].value<void *>();
void (*js_event_cb)(const char *msg) = reinterpret_cast <void(*)(const char *)>(f);
QWidget *p;
if (_views.contains(parent)) {
p = _views[parent];
@@ -53,6 +65,7 @@ void Rktwebview_qt::processCommands()
int id = view->id();
_views[id] = w;
_view_js_callbacks[id] = js_event_cb;
w->show();
@@ -98,10 +111,9 @@ void Rktwebview_qt::processCommands()
}
}
void Rktwebview_qt::interruptEventLoop()
void Rktwebview_qt::processJsEventQueue()
{
printf("Exeting application event loop\n");
//_app->quit();
}
void Rktwebview_qt::removeView(int id)
@@ -115,10 +127,13 @@ int Rktwebview_qt::nextHandle()
return h;
}
int Rktwebview_qt::rktWebViewCreate(int parent)
int Rktwebview_qt::rktWebViewCreate(int parent, void (*js_evt_cb)(const char *))
{
Command c(COMMAND_CREATE);
c.args.push_back(parent);
void *function = reinterpret_cast<void *>(js_evt_cb);
QVariant f(QVariant::fromValue(function));
c.args.push_back(f);
_command_queue.enqueue(&c);
@@ -153,6 +168,30 @@ result_t Rktwebview_qt::rktSetUrl(rktwebview_t wv, const char *url)
return r ? result_t::oke : result_t::set_navigate_failed;
}
void Rktwebview_qt::pageLoaded(rktwebview_t w, bool ok)
{
// Inject event handling code for the javascript side
runJs(w, "window.rkt_event_queue = [];\n"
"window.rkt_send_event = function(obj) { window.rkt_event_queue.push(obj); };\n"
"window.rkt_get_events = function() { "
" let q = window.rkt_event_queue; "
" window.rkt_event_queue = [];"
" let json_q = JSON.stringify(q);"
" return json_q;"
"};");
// trigger page loaded.
QJsonObject obj;
obj["event"] = "page-loaded";
obj["oke"] = ok;
triggerEvent(w, jsonString(obj));
}
void Rktwebview_qt::triggerEvent(rktwebview_t wv, const QString &msg)
{
}
void Rktwebview_qt::rktQuit()
{
QList<int> keys = _views.keys();
@@ -168,13 +207,18 @@ void Rktwebview_qt::rktQuit()
while(!c.done) { doEvents(); }
}
void Rktwebview_qt::runJs(rktwebview_t wv, const char *js)
{
if (_views.contains(wv)) {
QString _js(js);
WebViewQt *view = _views[wv]->view();
view->runJs(_js);
}
}
void Rktwebview_qt::doEvents()
{
//_quit_event_loop.start(2000);
//_app->exec();
//processCommands();
_app->processEvents();
}
Rktwebview_qt::Rktwebview_qt(Rktwebview_qt **handler) :
@@ -189,8 +233,7 @@ Rktwebview_qt::Rktwebview_qt(Rktwebview_qt **handler) :
_app = new QApplication(_argc, _argv);
connect(&_process_commands, &QTimer::timeout, this, &Rktwebview_qt::processCommands);
connect(&_quit_event_loop, &QTimer::timeout, this, &Rktwebview_qt::interruptEventLoop);
_process_commands.start(1000);
_process_commands.start(10);
*_handler = nullptr;
}

View File

@@ -24,10 +24,10 @@ private:
QApplication *_app;
rktwebview_t _current_handle;
QHash<int, WebviewWindow *> _views;
QHash<int, void(*)(const char *msg)> _view_js_callbacks;
QQueue<Command *> _command_queue;
QTimer _process_commands;
QTimer _quit_event_loop;
Rktwebview_qt **_handler;
@@ -36,7 +36,6 @@ private:
public slots:
void processCommands();
void interruptEventLoop();
public:
void removeView(int id);
@@ -44,17 +43,24 @@ public:
public:
int nextHandle();
public:
int rktWebViewCreate(int parent = 0); // threadsafe
int rktWebViewCreate(int parent, void(*js_evt_cb)(const char *msg));
void rktWebViewClose(int wv);
void rktQuit();
void runJs(rktwebview_t wv, const char *js); // threadsafe
item_t callJs(rktwebview_t wv, const char *js); // threadsafe
void runJs(rktwebview_t wv, const char *js);
item_t callJs(rktwebview_t wv, const char *js);
void setHtml(rktwebview_t wv, const char *html); // threadsafe
void navigate(rktwebview_t wv, const char *url); // threadsafe
void setHtml(rktwebview_t wv, const char *html);
void navigate(rktwebview_t wv, const char *url);
result_t rktSetUrl(rktwebview_t wv, const char *url);
public:
// Events for the backend
void pageLoaded(rktwebview_t w, bool ok);
public:
void triggerEvent(rktwebview_t wv, const QString &msg);
public:
void doEvents();

View File

@@ -1,4 +1,6 @@
#include "webviewqt.h"
#include <QWebEnginePage>
#include <QJsonDocument>
WebViewQt::WebViewQt(int id, QWidget *parent)
: QWebEngineView(parent)
@@ -11,9 +13,8 @@ int WebViewQt::id() const
return _id;
}
void WebViewQt::runJs(const char *js)
QString WebViewQt::runJs(const QString &js)
{
}

View File

@@ -2,9 +2,11 @@
#define WEBVIEWQT_H
#include <QWebEngineView>
#include <QTimer>
class WebViewQt : public QWebEngineView
{
Q_OBJECT
private:
int _id;
@@ -12,7 +14,11 @@ public:
int id() const;
public:
void runJs(const char *js);
QString runJs(const QString &js);
signals:
void pageLoaded(WebViewQt *, bool ok);
public:
WebViewQt(int id, QWidget *parent = nullptr);

View File

@@ -2,6 +2,32 @@
#include "webviewqt.h"
#include "rktwebview_qt.h"
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonParseError>
#include <QJsonObject>
void WebviewWindow::processJsEvents()
{
QWebEnginePage *p = _view->page();
p->runJavaScript("window.getPendingEvents();",
[this](const QVariant &v) {
QString s = v.toString();
QJsonParseError err;
QJsonDocument doc(QJsonDocument::fromJson(s.toUtf8(), &err));
if (err.error == QJsonParseError::NoError) {
QJsonArray a = doc.array();
int i, N;
for(i = 0, N = a.size(); i < N; i++) {
QJsonObject evt = a[i].toObject();
QJsonDocument doc_out(evt);
QString msg = doc_out.toJson(QJsonDocument::JsonFormat::Compact);
this->_container->triggerJsEvent(_view->id(), msg);
}
}
}
);
}
void WebviewWindow::closeEvent(QCloseEvent *evt)
{
@@ -13,6 +39,11 @@ void WebviewWindow::addView(WebViewQt *v, Rktwebview_qt *c)
_container = c;
_view = v;
this->setCentralWidget(v);
QWebEnginePage *page = _view->page();
connect(page, &QWebEnginePage::loadFinished, this, [this](bool ok) {
_container->pageLoaded(_view->id(), ok);
});
}
WebViewQt *WebviewWindow::view()
@@ -24,4 +55,5 @@ WebviewWindow::WebviewWindow(QWidget *parent)
: QMainWindow{parent}
{
_view = nullptr;
connect(&_process_js_events, &QTimer::timeout, this, &WebviewWindow::processJsEvents);
}

View File

@@ -2,6 +2,7 @@
#define WEBVIEWWINDOW_H
#include <QMainWindow>
#include <QTimer>
class WebViewQt;
class Rktwebview_qt;
@@ -12,6 +13,10 @@ class WebviewWindow : public QMainWindow
private:
Rktwebview_qt *_container;
WebViewQt *_view;
QTimer _process_js_events;
public slots:
void processJsEvents();
protected:
void closeEvent(QCloseEvent *evt);