-
This commit is contained in:
@@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.14)
|
|||||||
|
|
||||||
project(rktwebview_qt LANGUAGES CXX)
|
project(rktwebview_qt LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(QT_DEBUG_FIND_PACKAGE ON)
|
||||||
set(CMAKE_AUTOUIC ON)
|
set(CMAKE_AUTOUIC ON)
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
set(CMAKE_AUTORCC ON)
|
set(CMAKE_AUTORCC ON)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <unistd.h>
|
//#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include "rktwebview_qt.h"
|
#include "rktwebview_qt.h"
|
||||||
#include "webviewapp.h"
|
#include "webviewapp.h"
|
||||||
@@ -18,10 +18,10 @@ uint64_t current_ms() {
|
|||||||
// Main C Interface
|
// Main C Interface
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static int pipefd[2];
|
//static int pipefd[2];
|
||||||
static bool started = false;
|
//static bool started = false;
|
||||||
static pid_t webview_process;
|
//static pid_t webview_process;
|
||||||
static bool cannot_fork_or_pipe = false;
|
//static bool cannot_fork_or_pipe = false;
|
||||||
|
|
||||||
Rktwebview_qt *handler = nullptr;
|
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();
|
rkt_webview_init();
|
||||||
return handler->rktWebViewCreate(parent);
|
return handler->rktWebViewCreate(parent, js_event_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rkt_webview_close(int wv)
|
void rkt_webview_close(int wv)
|
||||||
{
|
{
|
||||||
|
rkt_webview_init();
|
||||||
handler->rktWebViewClose(wv);
|
handler->rktWebViewClose(wv);
|
||||||
}
|
}
|
||||||
|
|
||||||
result_t rkt_webview_set_url(int wv, const char *url)
|
result_t rkt_webview_set_url(int wv, const char *url)
|
||||||
{
|
{
|
||||||
|
rkt_webview_init();
|
||||||
result_t r = handler->rktSetUrl(wv, url);
|
result_t r = handler->rktSetUrl(wv, url);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -151,7 +153,7 @@ void rkt_webview_process_events(int for_ms)
|
|||||||
int64_t end_ms = start_ms + for_ms;
|
int64_t end_ms = start_ms + for_ms;
|
||||||
|
|
||||||
while (current_ms() < end_ms) {
|
while (current_ms() < end_ms) {
|
||||||
usleep(500); // sleep 0.5 ms
|
QThread::usleep(500); // sleep 0.5 ms
|
||||||
handler->doEvents();
|
handler->doEvents();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ typedef enum {
|
|||||||
|
|
||||||
RKTWEBVIEW_QT_EXPORT void rkt_webview_init();
|
RKTWEBVIEW_QT_EXPORT void rkt_webview_init();
|
||||||
RKTWEBVIEW_QT_EXPORT void rkt_webview_process_events(int for_ms);
|
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 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_url(int wv, const char *url);
|
||||||
RKTWEBVIEW_QT_EXPORT result_t rkt_webview_set_html(int wv, const char *html);
|
RKTWEBVIEW_QT_EXPORT result_t rkt_webview_set_html(int wv, const char *html);
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QSemaphore>
|
#include <QSemaphore>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
#define COMMAND_QUIT 1
|
#define COMMAND_QUIT 1
|
||||||
#define COMMAND_CLOSE 2
|
#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()
|
void Rktwebview_qt::processCommands()
|
||||||
{
|
{
|
||||||
printf("COmmand processing\n");
|
|
||||||
while(!_command_queue.empty()) {
|
while(!_command_queue.empty()) {
|
||||||
Command *cmd = _command_queue.dequeue();
|
Command *cmd = _command_queue.dequeue();
|
||||||
|
|
||||||
@@ -39,6 +47,10 @@ void Rktwebview_qt::processCommands()
|
|||||||
break;
|
break;
|
||||||
case COMMAND_CREATE: {
|
case COMMAND_CREATE: {
|
||||||
int parent = cmd->args[0].toInt();
|
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;
|
QWidget *p;
|
||||||
if (_views.contains(parent)) {
|
if (_views.contains(parent)) {
|
||||||
p = _views[parent];
|
p = _views[parent];
|
||||||
@@ -53,6 +65,7 @@ void Rktwebview_qt::processCommands()
|
|||||||
int id = view->id();
|
int id = view->id();
|
||||||
|
|
||||||
_views[id] = w;
|
_views[id] = w;
|
||||||
|
_view_js_callbacks[id] = js_event_cb;
|
||||||
|
|
||||||
w->show();
|
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)
|
void Rktwebview_qt::removeView(int id)
|
||||||
@@ -115,10 +127,13 @@ int Rktwebview_qt::nextHandle()
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Rktwebview_qt::rktWebViewCreate(int parent)
|
int Rktwebview_qt::rktWebViewCreate(int parent, void (*js_evt_cb)(const char *))
|
||||||
{
|
{
|
||||||
Command c(COMMAND_CREATE);
|
Command c(COMMAND_CREATE);
|
||||||
c.args.push_back(parent);
|
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);
|
_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;
|
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()
|
void Rktwebview_qt::rktQuit()
|
||||||
{
|
{
|
||||||
QList<int> keys = _views.keys();
|
QList<int> keys = _views.keys();
|
||||||
@@ -168,13 +207,18 @@ void Rktwebview_qt::rktQuit()
|
|||||||
while(!c.done) { doEvents(); }
|
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()
|
void Rktwebview_qt::doEvents()
|
||||||
{
|
{
|
||||||
//_quit_event_loop.start(2000);
|
|
||||||
//_app->exec();
|
|
||||||
//processCommands();
|
|
||||||
_app->processEvents();
|
_app->processEvents();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rktwebview_qt::Rktwebview_qt(Rktwebview_qt **handler) :
|
Rktwebview_qt::Rktwebview_qt(Rktwebview_qt **handler) :
|
||||||
@@ -189,8 +233,7 @@ Rktwebview_qt::Rktwebview_qt(Rktwebview_qt **handler) :
|
|||||||
|
|
||||||
_app = new QApplication(_argc, _argv);
|
_app = new QApplication(_argc, _argv);
|
||||||
connect(&_process_commands, &QTimer::timeout, this, &Rktwebview_qt::processCommands);
|
connect(&_process_commands, &QTimer::timeout, this, &Rktwebview_qt::processCommands);
|
||||||
connect(&_quit_event_loop, &QTimer::timeout, this, &Rktwebview_qt::interruptEventLoop);
|
_process_commands.start(10);
|
||||||
_process_commands.start(1000);
|
|
||||||
|
|
||||||
*_handler = nullptr;
|
*_handler = nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,22 +21,21 @@ class RKTWEBVIEW_QT_EXPORT Rktwebview_qt : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
QApplication *_app;
|
QApplication *_app;
|
||||||
rktwebview_t _current_handle;
|
rktwebview_t _current_handle;
|
||||||
QHash<int, WebviewWindow *> _views;
|
QHash<int, WebviewWindow *> _views;
|
||||||
|
QHash<int, void(*)(const char *msg)> _view_js_callbacks;
|
||||||
|
|
||||||
QQueue<Command *> _command_queue;
|
QQueue<Command *> _command_queue;
|
||||||
QTimer _process_commands;
|
QTimer _process_commands;
|
||||||
QTimer _quit_event_loop;
|
|
||||||
|
|
||||||
Rktwebview_qt **_handler;
|
Rktwebview_qt **_handler;
|
||||||
|
|
||||||
int _argc;
|
int _argc;
|
||||||
char *_argv[1];
|
char *_argv[1];
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void processCommands();
|
void processCommands();
|
||||||
void interruptEventLoop();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void removeView(int id);
|
void removeView(int id);
|
||||||
@@ -44,17 +43,24 @@ public:
|
|||||||
public:
|
public:
|
||||||
int nextHandle();
|
int nextHandle();
|
||||||
public:
|
public:
|
||||||
int rktWebViewCreate(int parent = 0); // threadsafe
|
int rktWebViewCreate(int parent, void(*js_evt_cb)(const char *msg));
|
||||||
void rktWebViewClose(int wv);
|
void rktWebViewClose(int wv);
|
||||||
void rktQuit();
|
void rktQuit();
|
||||||
|
|
||||||
void runJs(rktwebview_t wv, const char *js); // threadsafe
|
void runJs(rktwebview_t wv, const char *js);
|
||||||
item_t callJs(rktwebview_t wv, const char *js); // threadsafe
|
item_t callJs(rktwebview_t wv, const char *js);
|
||||||
|
|
||||||
void setHtml(rktwebview_t wv, const char *html); // threadsafe
|
void setHtml(rktwebview_t wv, const char *html);
|
||||||
void navigate(rktwebview_t wv, const char *url); // threadsafe
|
void navigate(rktwebview_t wv, const char *url);
|
||||||
result_t rktSetUrl(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:
|
public:
|
||||||
void doEvents();
|
void doEvents();
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
#include "webviewqt.h"
|
#include "webviewqt.h"
|
||||||
|
#include <QWebEnginePage>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
|
||||||
WebViewQt::WebViewQt(int id, QWidget *parent)
|
WebViewQt::WebViewQt(int id, QWidget *parent)
|
||||||
: QWebEngineView(parent)
|
: QWebEngineView(parent)
|
||||||
@@ -11,9 +13,8 @@ int WebViewQt::id() const
|
|||||||
return _id;
|
return _id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebViewQt::runJs(const char *js)
|
QString WebViewQt::runJs(const QString &js)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,17 +2,23 @@
|
|||||||
#define WEBVIEWQT_H
|
#define WEBVIEWQT_H
|
||||||
|
|
||||||
#include <QWebEngineView>
|
#include <QWebEngineView>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
class WebViewQt : public QWebEngineView
|
class WebViewQt : public QWebEngineView
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
int _id;
|
int _id;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int id() const;
|
int id() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void runJs(const char *js);
|
QString runJs(const QString &js);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void pageLoaded(WebViewQt *, bool ok);
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WebViewQt(int id, QWidget *parent = nullptr);
|
WebViewQt(int id, QWidget *parent = nullptr);
|
||||||
|
|||||||
@@ -2,6 +2,32 @@
|
|||||||
|
|
||||||
#include "webviewqt.h"
|
#include "webviewqt.h"
|
||||||
#include "rktwebview_qt.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)
|
void WebviewWindow::closeEvent(QCloseEvent *evt)
|
||||||
{
|
{
|
||||||
@@ -13,6 +39,11 @@ void WebviewWindow::addView(WebViewQt *v, Rktwebview_qt *c)
|
|||||||
_container = c;
|
_container = c;
|
||||||
_view = v;
|
_view = v;
|
||||||
this->setCentralWidget(v);
|
this->setCentralWidget(v);
|
||||||
|
|
||||||
|
QWebEnginePage *page = _view->page();
|
||||||
|
connect(page, &QWebEnginePage::loadFinished, this, [this](bool ok) {
|
||||||
|
_container->pageLoaded(_view->id(), ok);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
WebViewQt *WebviewWindow::view()
|
WebViewQt *WebviewWindow::view()
|
||||||
@@ -24,4 +55,5 @@ WebviewWindow::WebviewWindow(QWidget *parent)
|
|||||||
: QMainWindow{parent}
|
: QMainWindow{parent}
|
||||||
{
|
{
|
||||||
_view = nullptr;
|
_view = nullptr;
|
||||||
|
connect(&_process_js_events, &QTimer::timeout, this, &WebviewWindow::processJsEvents);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define WEBVIEWWINDOW_H
|
#define WEBVIEWWINDOW_H
|
||||||
|
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
class WebViewQt;
|
class WebViewQt;
|
||||||
class Rktwebview_qt;
|
class Rktwebview_qt;
|
||||||
@@ -10,8 +11,12 @@ class WebviewWindow : public QMainWindow
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
Rktwebview_qt *_container;
|
Rktwebview_qt *_container;
|
||||||
WebViewQt *_view;
|
WebViewQt *_view;
|
||||||
|
QTimer _process_js_events;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void processJsEvents();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void closeEvent(QCloseEvent *evt);
|
void closeEvent(QCloseEvent *evt);
|
||||||
|
|||||||
Reference in New Issue
Block a user