Files
racket-webview/rktwebview_qt/webviewwindow.cpp
2026-03-03 16:10:38 +01:00

193 lines
5.3 KiB
C++

#include "webviewwindow.h"
#include "webviewqt.h"
#include "rktwebview_qt.h"
#include "rktutils.h"
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonParseError>
#include <QJsonObject>
#include <QWebEngineScriptCollection>
#include <QWebEngineScript>
#include <QMoveEvent>
WebviewWindow::WebviewWindow(QWidget *parent)
: QMainWindow{parent}
{
_view = nullptr;
_must_close = false;
_devtools = nullptr;
connect(&_resize_timer, &QTimer::timeout, this, &WebviewWindow::triggerResize);
connect(&_move_timer, &QTimer::timeout, this, &WebviewWindow::triggerMove);
}
void WebviewWindow::processJsEvents()
{
QWebEnginePage *p = _view->page();
p->runJavaScript("if (window.rkt_get_events) { window.rkt_get_events(); } else { JSON.stringify([]); }",
[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 js_evt = a[i].toObject();
EventContainer e("js-evt");
e["js-evt"] = js_evt;
this->_container->triggerEvent(_view->id(), e);
}
} else {
}
}
);
}
void WebviewWindow::closeEvent(QCloseEvent *evt)
{
if (_must_close) {
EventContainer e("closed");
_container->triggerEvent(_view->id(), e);
_container->removeView(_view->id());
this->deleteLater();
if (_devtools != nullptr) {
_devtools->deleteLater();
}
} else {
evt->ignore();
EventContainer e("can-close?");
_container->triggerEvent(_view->id(), e);
}
}
void WebviewWindow::closeView()
{
_must_close = true;
close();
}
void WebviewWindow::addView(WebViewQt *v, Rktwebview_qt *c)
{
_container = c;
_view = v;
this->setCentralWidget(v);
QWebEnginePage *page = _view->page();
// Inject event handling code for the javascript side
QWebEngineScriptCollection &col = page->scripts();
QWebEngineScript evt_script;
evt_script.setInjectionPoint(QWebEngineScript::DocumentReady);
evt_script.setName("rkt_webview_event_handling");
evt_script.setSourceCode(
"window.rkt_event_queue = [];\n"
"window.rkt_send_event = function(obj) {\n"
" console.log('Sending event: ' + obj);\n"
" window.rkt_event_queue.push(obj);\n"
"};\n"
"window.rkt_get_events = function() {\n"
" let q = window.rkt_event_queue;\n"
" window.rkt_event_queue = [];\n"
" let json_q = JSON.stringify(q);\n"
" return json_q;\n"
"};\n"
"console.log('We have set:');\n"
"console.log('window.rkt_event_queue:');\n"
"console.log(window.rkt_event_queue);\n"
"console.log('window.rkt_send_event:');\n"
"console.log(window.rkt_send_event);\n"
"console.log('window.rkt_get_events:');\n"
"console.log(window.rkt_get_events);\n"
);
evt_script.setWorldId(QWebEngineScript::ApplicationWorld);
//col.insert(evt_script);
connect(page, &QWebEnginePage::loadFinished, this, [this](bool ok) {
_container->pageLoaded(_view->id(), ok);
});
connect(page, &QWebEnginePage::loadStarted, this, [this]() {
_container->onPageLoad(_view->id());
});
}
WebViewQt *WebviewWindow::view()
{
return _view;
}
void WebviewWindow::runJs(const QString &js)
{
QWebEnginePage *p = _view->page();
p->runJavaScript(js);
}
void WebviewWindow::openDevTools()
{
_devtools = new QMainWindow(this);
QWebEngineView *devtools_view = new QWebEngineView(_devtools);
_devtools->setCentralWidget(devtools_view);
_devtools->resize(800, 600);
_devtools->show();
_view->page()->setDevToolsPage(devtools_view->page());
connect(_devtools, &WebviewWindow::destroyed, this, [this](QObject *) {
_devtools = nullptr;
});
}
void WebviewWindow::moveEvent(QMoveEvent *event)
{
_x = event->pos().x();
_y = event->pos().y();
_move_timer.setSingleShot(true);
_move_timer.start(500);
}
void WebviewWindow::triggerMove()
{
EventContainer xy("move");
xy["x"] = _x;
xy["y"] = _y;
_container->triggerEvent(_view->id(), xy);
}
void WebviewWindow::resizeEvent(QResizeEvent *event)
{
_w = event->size().width();
_h = event->size().height();
_resize_timer.setSingleShot(true);
_resize_timer.start(500);
}
void WebviewWindow::triggerResize()
{
EventContainer s("resize");
s["w"] = _w;
s["h"] = _h;
_container->triggerEvent(_view->id(), s);
}
void WebviewWindow::showEvent(QShowEvent *event)
{
EventContainer show("show");
_container->triggerEvent(_view->id(), show);
}
void WebviewWindow::hideEvent(QHideEvent *event)
{
if (!_must_close) {
EventContainer hide("hide");
_container->triggerEvent(_view->id(), hide);
}
}