This commit is contained in:
2026-03-25 01:27:39 +01:00
parent eb4e15c66b
commit 8fe7e726a4
26 changed files with 1896 additions and 517 deletions

View File

@@ -1,94 +1,325 @@
#include "rktwebview.h"
#include <QThread>
#include <QFile>
#include <QApplication>
static int _argc;
static char **_argv;
#include "rkt_protocol.h"
#include "shm.h"
#include "shmqueue.h"
#include "command.h"
void eventCb(rkt_data_t *e)
#include <QJsonDocument>
#include <QJsonObject>
#include "rktwebview_qt.h"
static void free_data(rkt_data_t *d)
{
printf("event: %s\n", e->data.event.event);
rkt_webview_free_data(e);
if (d->kind == version) {
free(d);
} else if (d->kind == event) {
free(d->data.event.event);
free(d);
} else if (d->kind == js_result) {
free(d->data.js_result.value);
free(d);
} else {
fprintf(stderr, "UNEXPECTED: data kind %d cannot be freed\n", d->kind);
}
}
class Handler : public QThread
{
public:
Shm *shm;
ShmQueue *command_queue;
ShmQueue *result_queue;
ShmQueue *event_queue;
Rktwebview_qt *webview_handler;
// QThread interface
protected:
void run();
};
static Handler *_handler;
static void event_cb(rkt_data_t *data)
{
if (data->kind != rkt_data_kind_t::event) {
return;
}
int wv = data->data.event.wv;
char *evt = data->data.event.event;
std::string evt_d(evt);
_handler->event_queue->enqueue(wv, evt_d);
free_data(data);
}
int main(int argc, char *argv[])
{
int wv1;
int wv2;
const char *me = argv[0];
_argc = argc;
_argv = argv;
int k = 0;
while(k < 2) {
rkt_webview_init();
int context = rkt_webview_new_context("console.log('boilerplate!');", nullptr);
wv1 = rkt_webview_create(context, 0, eventCb);
rkt_webview_move(wv1, 200, 300);
rkt_webview_resize(wv1, 800, 600);
rkt_webview_set_url(wv1, "https://wikipedia.org"); //"http://127.0.0.1:8083");
k += 1;
int i = 0;
while(i < 10) {
printf("Waiting...%d\n", i);
rkt_webview_process_events(1000);
if (i == 6) {
rkt_webview_open_devtools(wv1);
}
if (i == 3) {
rkt_data_t *r = rkt_webview_call_js(wv1, "{ let a = 7 * 6; console.log('a = ' + a); return a; }");
printf("rkt_js_result: %d: %s\n", r->data.js_result.result, r->data.js_result.value);
rkt_webview_free_data(r);
}
if (i == 4) {
rkt_data_t *r = rkt_webview_call_js(wv1, "let el = document.getElementById('hi');el.value = '10';");
printf("rkt_js_result: %d: %s\n", r->data.js_result.result, r->data.js_result.value);
rkt_webview_free_data(r);
}
if (i == 6) {
//rkt_data_t *r = rkt_webview_call_js(wv1, "document.body.innerHTML = '<h1>Hi!</h1>'; return document.body.innerHTML;");
//printf("rkt_js_result: %d: %s\n", r->data.js_result.result, r->data.js_result.value);
//rkt_webview_free_data(r);
}
if (i == 7) {
result_t r = rkt_webview_message_box(wv1, "This is a title", "This is my message", "This is my submessage", rkt_messagetype_t::yes_no);
}
if (i == 10) {
wv2 = rkt_webview_create(context, wv1, eventCb);
rkt_webview_move(wv2, 400, 200);
rkt_webview_resize(wv2, 800, 600);
rkt_webview_set_url(wv2, "https://127.0.0.1");
}
if (i > 10) {
char buf[1000];
sprintf(buf, "{ let obj = { e: 'test', i: %d }; window.rkt_send_event(obj); }", i);
rkt_webview_run_js(wv1, buf);
}
if (i == 15) {
rkt_webview_close(wv2);
}
i += 1;
}
rkt_webview_close(wv1);
rkt_webview_cleanup();
if (argc < 6) {
fprintf(stderr, "%s: wrong number of arguments\n", me);
exit(1);
}
const char *shm_name = argv[1];
const char *shm_size_str = argv[2];
const char *cmd_slot_str = argv[3];
const char *res_slot_str = argv[4];
const char *evt_slot_str = argv[5];
size_t shm_size = atoi(shm_size_str);
int cmd_slot = atoi(cmd_slot_str);
int res_slot = atoi(res_slot_str);
int evt_slot = atoi(evt_slot_str);
fprintf(stderr, "%s %s %s %s %s %s\n", me, shm_name, shm_size_str, cmd_slot_str, res_slot_str, evt_slot_str);
fprintf(stderr, "%s %s %ld %d %d %d\n", me, shm_name, shm_size, cmd_slot, res_slot, evt_slot);
if (!(shm_size > 0 && cmd_slot > 0 && res_slot > 0 && evt_slot > 0)) {
fprintf(stderr, "%s: Invalid shm size or slots\n", me);
exit(2);
}
Handler *handler = new Handler();
_handler = handler;
handler->shm = new Shm(shm_name, shm_size, false);
handler->command_queue = new ShmQueue(handler->shm, cmd_slot, false);
handler->result_queue = new ShmQueue(handler->shm, res_slot, false);
handler->event_queue = new ShmQueue(handler->shm, evt_slot, false);
handler->webview_handler = new Rktwebview_qt(argc, argv);
handler->start();
handler->webview_handler->initApp();
handler->webview_handler->execApp();
fprintf(stderr, "waiting for thread to end\n");
handler->wait();
fprintf(stderr, "cleaning up shm\n");
delete handler->webview_handler;
delete handler->command_queue;
delete handler->result_queue;
delete handler->event_queue;
delete handler->shm;
delete handler;
return 0;
}
void Handler::run()
{
bool quit = false;
while (!quit) {
int cmd;
std::string data;
command_queue->dequeue(cmd, data, true);
QJsonObject data_obj = QJsonDocument::fromJson(data.c_str()).object();
switch(cmd) {
case CMD_QUIT: {
fprintf(stderr, "Got quit message\n");
webview_handler->rktQuit();
fprintf(stderr, "Enqueing RESULT_QUIT to result queue\n");
result_queue->enqueue(RESULT_QUIT);
quit = true;
}
break;
case CMD_HANDLE_IS_VALID: {
int wv = data_obj["wv"].toInt();
bool oke = webview_handler->rktValid(wv);
result_queue->enqueue(oke);
}
break;
case CMD_CONTEXT_NEW: {
QString boilerplate_js = data_obj["boilerplate_js"].toString();
bool has_pem_cert = data_obj["has_pem_cert"].toBool();
QString pem_cert = data_obj["pem_cert"].toString();
int context = webview_handler->newContext(boilerplate_js, has_pem_cert, pem_cert);
result_queue->enqueue(context);
}
break;
case CMD_CREATE_WV: {
int context = data_obj["context"].toInt();
int parent = data_obj["parent"].toInt();
int wv = webview_handler->rktWebViewCreate(context, parent, event_cb);
result_queue->enqueue(wv);
}
break;
case CMD_CLOSE_WV: {
int wv = data_obj["wv"].toInt();
webview_handler->rktWebViewClose(wv);
}
break;
case CMD_SET_URL: {
int wv = data_obj["wv"].toInt();
QString url = data_obj["url"].toString();
result_t r = webview_handler->rktSetUrl(wv, url.toUtf8().constData());
result_queue->enqueue(r);
}
break;
case CMD_SET_HTML: {
int wv = data_obj["wv"].toInt();
QString html = data_obj["html"].toString();
result_t r = webview_handler->rktSetHtml(wv, html.toUtf8().constData());
result_queue->enqueue(r);
}
break;
case CMD_RUN_JS: {
int wv = data_obj["wv"].toInt();
QString js = data_obj["js"].toString();
result_t r = webview_handler->rktRunJs(wv, js);
result_queue->enqueue(r);
}
break;
case CMD_CALL_JS: {
fprintf(stderr, "Calljs\n");
int wv = data_obj["wv"].toInt();
QString js = data_obj["js"].toString();
rkt_data_t *res = webview_handler->rktCallJs(wv, js.toUtf8().constData());
result_queue->enqueue(res->data.js_result.result, res->data.js_result.value);
free_data(res);
}
break;
case CMD_OPEN_DEVTOOLS: {
int wv = data_obj["wv"].toInt();
result_t r = webview_handler->rktOpenDevtools(wv);
result_queue->enqueue(r);
}
break;
case CMD_MOVE: {
int wv = data_obj["wv"].toInt();
int x = data_obj["x"].toInt();
int y = data_obj["y"].toInt();
result_t r = webview_handler->rktMove(wv, x, y);
result_queue->enqueue(r);
}
break;
case CMD_RESIZE: {
int wv = data_obj["wv"].toInt();
int w = data_obj["w"].toInt();
int h = data_obj["h"].toInt();
result_t r = webview_handler->rktResize(wv, w, h);
result_queue->enqueue(r);
}
break;
case CMD_HIDE: {
int wv = data_obj["wv"].toInt();
result_t r = webview_handler->rktHideWindow(wv);
result_queue->enqueue(r);
}
break;
case CMD_SHOW: {
int wv = data_obj["wv"].toInt();
result_t r = webview_handler->rktShowWindow(wv);
result_queue->enqueue(r);
}
break;
case CMD_PRESENT: {
int wv = data_obj["wv"].toInt();
result_t r = webview_handler->rktPresentWindow(wv);
result_queue->enqueue(r);
}
break;
case CMD_MAXIMIZE: {
int wv = data_obj["wv"].toInt();
result_t r = webview_handler->rktMaximizeWindow(wv);
result_queue->enqueue(r);
}
break;
case CMD_MINIMIZE: {
int wv = data_obj["wv"].toInt();
result_t r = webview_handler->rktMinimizeWindow(wv);
result_queue->enqueue(r);
}
break;
case CMD_SHOW_NORMAL: {
int wv = data_obj["wv"].toInt();
result_t r = webview_handler->rktShowNormalWindow(wv);
result_queue->enqueue(r);
}
break;
case CMD_WINDOW_STATE: {
int wv = data_obj["wv"].toInt();
window_state_t r = webview_handler->rktWindowState(wv);
result_queue->enqueue(r);
}
break;
case CMD_SET_TITLE: {
int wv = data_obj["wv"].toInt();
QString title = data_obj["title"].toString();
result_t r = webview_handler->rktWindowSetTitle(wv, title.toUtf8().constData());
result_queue->enqueue(r);
}
break;
case CMD_CHOOSE_DIR: {
int wv = data_obj["wv"].toInt();
QString title = data_obj["title"].toString();
QString base_dir = data_obj["base_dir"].toString();
result_t r = webview_handler->rktChooseDir(wv,
title.toUtf8().constData(),
base_dir.toUtf8().constData()
);
result_queue->enqueue(r);
}
break;
case CMD_FILE_OPEN: {
int wv = data_obj["wv"].toInt();
QString title = data_obj["title"].toString();
QString base_dir = data_obj["base_dir"].toString();
QString permitted_exts = data_obj["permitted_exts"].toString();
result_t r = webview_handler->rktFileOpen(wv,
title.toUtf8().constData(),
base_dir.toUtf8().constData(),
permitted_exts.toUtf8().constData()
);
result_queue->enqueue(r);
}
break;
case CMD_FILE_SAVE: {
int wv = data_obj["wv"].toInt();
QString title = data_obj["title"].toString();
QString base_dir = data_obj["base_dir"].toString();
QString permitted_exts = data_obj["permitted_exts"].toString();
result_t r = webview_handler->rktFileSave(wv,
title.toUtf8().constData(),
base_dir.toUtf8().constData(),
permitted_exts.toUtf8().constData()
);
result_queue->enqueue(r);
}
break;
case CMD_SET_OU_TOKEN: {
int wv = data_obj["wv"].toInt();
QString token = data_obj["token"].toString();
webview_handler->rktSetOUToken(wv, token.toUtf8().constData());
}
break;
case CMD_MSG_BOX: {
int wv = data_obj["wv"].toInt();
QString title = data_obj["title"].toString();
QString message = data_obj["message"].toString();
QString submsg = data_obj["submessage"].toString();
int type = data_obj["type"].toInt();
result_t r = webview_handler->rktMessageBox(wv,
title.toUtf8().constData(),
message.toUtf8().constData(),
submsg.toUtf8().constData(),
static_cast<rkt_messagetype_t>(type)
);
result_queue->enqueue(r);
}
break;
default: {
fprintf(stderr, "Unknown command: %d\n", cmd);
}
}
}
QCoreApplication *app = QApplication::instance();
delete app;
printf("%p\n", QApplication::instance());
}