#include "rktwebview_qt.h" #include "webviewqt.h" #include "rktwebview.h" #include "webviewwindow.h" #include "rktutils.h" #include #include #include #include #include #define COMMAND_QUIT 1 #define COMMAND_CLOSE 2 #define COMMAND_CREATE 3 #define COMMAND_SET_URL 4 #define COMMAND_SET_HTML 5 #define COMMAND_RUN_JS 6 #define COMMAND_DEV_TOOLS 7 #define COMMAND_MOVE 8 #define COMMAND_RESIZE 9 class Command { public: int cmd; QVector args; QVariant result; bool done; public: Command(int _cmd) { cmd = _cmd; done = false; } }; void Rktwebview_qt::processCommands() { while(!_command_queue.empty()) { Command *cmd = _command_queue.dequeue(); switch(cmd->cmd) { case COMMAND_QUIT: { _app->quit(); cmd->done = true; } break; case COMMAND_CREATE: { int parent = cmd->args[0].toInt(); void *f = cmd->args[1].value(); event_cb_t js_event_cb = reinterpret_cast (f); QWidget *p; if (_views.contains(parent)) { p = _views[parent]; } else { p = nullptr; } WebviewWindow *w = new WebviewWindow(p); WebViewQt *view = new WebViewQt(nextHandle(), w); w->addView(view, this); int id = view->id(); _views[id] = w; _view_js_callbacks[id] = js_event_cb; w->show(); cmd->result = id; cmd->done = true; } break; case COMMAND_CLOSE: { int wv = cmd->args[0].toInt(); if (_views.contains(wv)) { WebviewWindow *w= _views[wv]; _views.remove(wv); w->closeView(); cmd->result = true; } else { cmd->result = false; } cmd->done = true; } break; case COMMAND_SET_URL: { int wv = cmd->args[0].toInt(); QString url = cmd->args[1].toString(); if (_views.contains(wv)) { WebviewWindow *w = _views[wv]; WebViewQt *v = w->view(); QUrl u(url); v->setUrl(u); cmd->result = true; } else { cmd->result = false; } cmd->done = true; } break; case COMMAND_SET_HTML: { int wv = cmd->args[0].toInt(); QString html = cmd->args[1].toString(); if (_views.contains(wv)) { WebviewWindow *w = _views[wv]; WebViewQt *v = w->view(); v->setHtml(html); cmd->result = true; } else { cmd->result = false; } cmd->done = true; } break; case COMMAND_RUN_JS: { int wv = cmd->args[0].toInt(); QString js = cmd->args[1].toString(); if (_views.contains(wv)) { WebviewWindow *w = _views[wv]; w->runJs(js); cmd->result = true; } else { cmd->result = false; } cmd->done = true; } break; case COMMAND_DEV_TOOLS: { int wv = cmd->args[0].toInt(); if (_views.contains(wv)) { WebviewWindow *w = _views[wv]; w->openDevTools(); cmd->result = true; } else { cmd->result = false; } cmd->done = true; } break; case COMMAND_MOVE: { int wv = cmd->args[0].toInt(); int x = cmd->args[1].toInt(); int y = cmd->args[2].toInt(); if (_views.contains(wv)) { WebviewWindow *w = _views[wv]; w->move(x, y); cmd->result = true; } else { cmd->result = false; } cmd->done = true; } break; case COMMAND_RESIZE: { int wv = cmd->args[0].toInt(); int width = cmd->args[1].toInt(); int height = cmd->args[2].toInt(); if (_views.contains(wv)) { WebviewWindow *w = _views[wv]; w->resize(width, height); cmd->result = true; } else { cmd->result = false; } cmd->done = true; } break; default: { cmd->result = false; cmd->done = true; } break; } } } void Rktwebview_qt::processJsEventQueues() { QList wvs = _views.keys(); int i, N; for(i = 0, N = wvs.length(); i < N; i++) { int wv = wvs[i]; if (_views.contains(wv)) { WebviewWindow *win = _views[wv]; win->processJsEvents(); } } } void Rktwebview_qt::removeView(int id) { if (_views.contains(id)) { WebviewWindow *win = _views[id]; _views.remove(id); _view_js_callbacks.remove(id); } } int Rktwebview_qt::nextHandle() { int h = ++_current_handle; return h; } int Rktwebview_qt::rktWebViewCreate(int parent, event_cb_t js_evt_cb) { Command c(COMMAND_CREATE); c.args.push_back(parent); void *function = reinterpret_cast(js_evt_cb); QVariant f(QVariant::fromValue(function)); c.args.push_back(f); _command_queue.enqueue(&c); while(!c.done) { doEvents(); } int id = c.result.toInt(); return id; } void Rktwebview_qt::rktWebViewClose(int wv) { Command c(COMMAND_CLOSE); c.args.push_back(wv); _command_queue.enqueue(&c); while(!c.done) { doEvents(); } } result_t Rktwebview_qt::rktSetUrl(rktwebview_t wv, const char *url) { Command c(COMMAND_SET_URL); QString _url(url); c.args.push_back(wv); c.args.push_back(_url); _command_queue.enqueue(&c); while(!c.done) { doEvents(); } bool r = c.result.toBool(); return r ? result_t::oke : result_t::set_navigate_failed; } result_t Rktwebview_qt::rktSetHtml(rktwebview_t wv, const char *html) { Command c(COMMAND_SET_HTML); QString _html(html); c.args.push_back(wv); c.args.push_back(_html); _command_queue.enqueue(&c); while(!c.done) { doEvents(); } bool r = c.result.toBool(); return r ? result_t::oke : result_t::set_navigate_failed; } result_t Rktwebview_qt::rktRunJs(rktwebview_t wv, const char *js) { Command c(COMMAND_RUN_JS); QString _js(js); c.args.push_back(wv); c.args.push_back(_js); _command_queue.enqueue(&c); while(!c.done) { doEvents(); } bool r = c.result.toBool(); return r ? result_t::oke : result_t::eval_js_failed; } result_t Rktwebview_qt::rktMove(rktwebview_t wv, int x, int y) { Command c(COMMAND_MOVE); c.args.push_back(wv); c.args.push_back(x); c.args.push_back(y); _command_queue.enqueue(&c); while(!c.done) { doEvents(); } bool r = c.result.toBool(); return r ? result_t::oke : result_t::move_failed; } result_t Rktwebview_qt::rktResize(rktwebview_t wv, int w, int h) { Command c(COMMAND_RESIZE); c.args.push_back(wv); c.args.push_back(w); c.args.push_back(h); _command_queue.enqueue(&c); while(!c.done) { doEvents(); } bool r = c.result.toBool(); return r ? result_t::oke : result_t::resize_failed; } bool Rktwebview_qt::rktValid(rktwebview_t wv) { return _views.contains(wv); } result_t Rktwebview_qt::rktOpenDevtools(rktwebview_t wv) { Command c(COMMAND_DEV_TOOLS); c.args.push_back(wv); _command_queue.enqueue(&c); while(!c.done) { doEvents(); } bool r = c.result.toBool(); return r ? result_t::oke : result_t::eval_js_failed; } void Rktwebview_qt::onPageLoad(rktwebview_t w) { } void Rktwebview_qt::pageLoaded(rktwebview_t w, bool ok) { runJs(w, "if (window.rkt_event_queue === undefined) { 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" ); // trigger page loaded. EventContainer e("page-loaded"); e["oke"] = ok; triggerEvent(w, e); } void Rktwebview_qt::triggerEvent(rktwebview_t wv, const EventContainer &e) { triggerEvent(wv, mkEventJson(e)); } void Rktwebview_qt::triggerEvent(rktwebview_t wv, const QString &msg) { if (_view_js_callbacks.contains(wv)) { event_cb_t js_event_cb = _view_js_callbacks[wv]; char *evt = strdup(msg.toUtf8().constData()); rkt_event_t *e = static_cast(malloc(sizeof(rkt_event_t))); e->wv = wv; e->event = evt; js_event_cb(e); } } void Rktwebview_qt::rktQuit() { QList keys = _views.keys(); int i; for(i = 0; i < keys.size(); i++) { int view_handle = keys[i]; rktWebViewClose(view_handle); } Command c(COMMAND_QUIT); _command_queue.enqueue(&c); while(!c.done) { doEvents(); } } void Rktwebview_qt::runJs(rktwebview_t wv, const char *js) { if (_views.contains(wv)) { QString _js(js); WebviewWindow *win = _views[wv]; win->runJs(_js); } } void Rktwebview_qt::doEvents() { _app->processEvents(); } Rktwebview_qt::Rktwebview_qt(Rktwebview_qt **handler) : QObject() { _argc = 1; _argv[0] = const_cast("Rktwebview_qt"); _current_handle = 0; _handler = handler; _app = new QApplication(_argc, _argv); connect(&_process_commands, &QTimer::timeout, this, &Rktwebview_qt::processCommands); _process_commands.start(10); connect(&_process_events, &QTimer::timeout, this, &Rktwebview_qt::processJsEventQueues); _process_events.start(5); *_handler = nullptr; }