From a622739deb757dc01f6c3631ceafebec636671a7 Mon Sep 17 00:00:00 2001 From: Hans Dijkema Date: Wed, 4 Mar 2026 23:54:50 +0100 Subject: [PATCH] - --- private/lib/linux/librktwebview_qt.so | Bin 163088 -> 163072 bytes private/racket-webview.rkt | 131 +++++- private/utils.rkt | 44 +- rktwebview_qt/CMakeLists.txt | 1 + rktwebview_qt/command.cpp | 20 + rktwebview_qt/command.h | 54 +++ rktwebview_qt/main.cpp | 4 +- rktwebview_qt/rktutils.h | 16 +- rktwebview_qt/rktwebview_qt.cpp | 571 +++++++++++++------------- rktwebview_qt/rktwebview_qt.h | 21 +- rktwebview_qt/webviewwindow.cpp | 5 +- 11 files changed, 538 insertions(+), 329 deletions(-) create mode 100644 rktwebview_qt/command.cpp create mode 100644 rktwebview_qt/command.h diff --git a/private/lib/linux/librktwebview_qt.so b/private/lib/linux/librktwebview_qt.so index c8170bf89b7162f4a82d185de5d3e28299084f43..a3a89a96b347f17a11aa696bb76d432220128481 100755 GIT binary patch delta 57212 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

!5I7mOcMf*FD>Q$is6S(nQd2ImN8@p#gQEf$ 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 delta 56202 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 rXO wv? symbol?) - (let ((r (rkt-webview-close (wv-handle wv)))) + (begin + (rkt-webview-close (wv-handle wv)) (kill-thread (wv-webserver-thread wv)) - r) - ) + 'oke)) (define/contract (webview-bind! wv selector event) (-> wv? (or/c symbol? string?) symbol? list?) @@ -283,9 +300,12 @@ (if (webview-call-js-result? result) (if (eq? (car result) 'oke) (hash-ref (fromJson (cadr result)) 'result #f) - (error "Error calling javascript. Message: ~a" (hash-ref (fromJson (cadr result)) 'exn result)) + (error + (format "Error calling javascript. Message: ~a" + (hash-ref (fromJson (cadr result)) 'exn result))) ) - (error "Wrong result from webview-call-js: ~a" result) + (error + (format "Wrong result from webview-call-js: ~a" result)) ) ) ) @@ -331,12 +351,9 @@ " }\n" "};\n")) -> "f()")))) - (if (eq? (car v) 'oke) - (let ((h (fromJson (cadr v)))) - (hash-ref h 'result #f)) - #f) - ) - ) + (if (eq? v #f) + #f + v))) (define/contract (webview-value/number wv id) (-> wv? symbol? (or/c number? boolean?)) @@ -403,8 +420,96 @@ ) ) - (define/contract (webview-set-style! wv selector style-entries) + (-> wv? (or/c symbol? string?) (or/c kv? list-of-kv?) hash?) + (let ((sel (if (symbol? selector) + (format "#~a" selector) + selector)) + (cl (mk-js-array (if (kv? style-entries) + (list style-entries) + style-entries))) + ) + (webview-call-js wv + (with-selector sel + (format + (js-code + "function(id, el) {" + " let cl = ~a;" + " cl.forEach(function(st) {" + " el.style[st[0]] = st[1];" + " });" + " return id;" + "}") cl)) + ) + ) + ) + +(define/contract (webview-unset-style! wv selector style-entries) + (-> wv? (or/c symbol? string?) (or/c symbol? list-of-symbol?) hash?) + (let ((sel (if (symbol? selector) + (format "#~a" selector) + selector)) + (cl (mk-js-array (if (symbol? style-entries) + (list style-entries) + style-entries))) + ) + (webview-call-js wv + (with-selector sel + (format + (js-code + "function(id, el) {" + " let cl = ~a;" + " cl.forEach(function(st) {" + " el.style[st] = '';" + " });" + " return id;" + "}") cl) + ) + ) + ) + ) + +(define/contract (webview-set-attr! wv selector attr-entries) + (-> wv? (or/c symbol? string?) (or/c kv? list-of-kv?) hash?) + (let ((sel (if (symbol? selector) + (format "#~a" selector) + selector)) + (cl (mk-js-array (if (kv? attr-entries) + (list attr-entries) + attr-entries))) + ) + (webview-call-js wv + (with-selector sel + (format + (js-code + "function(id, el) {" + " let cl = ~a;" + " cl.forEach(function(av) {" + " el.setAttribute(av[0], av[1]);" + " });" + " return id;" + "}") cl)) + ) + ) + ) + +(define/contract (webview-attr wv id attr) + (-> wv? symbol? (or/c symbol? string?) (or/c string? boolean?)) + (let ((v (webview-call-js wv + (with-id id el + -> (format "el.getAttribute('~a');" attr)) + ))) + (if (eq? v 'null) + #f + v) + ) + ) + + + + + +#|(define/contract (webview-set-style! wv selector style-entries) (-> wv? (or/c symbol? string?) (or/c list? list-of-kv?) hash?) (define (webview-set-style!* wv selector h) @@ -435,7 +540,7 @@ ) ) ) - +|# ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; testing diff --git a/private/utils.rkt b/private/utils.rkt index e4d6033..af66f69 100644 --- a/private/utils.rkt +++ b/private/utils.rkt @@ -14,7 +14,10 @@ fromJson mk-js-array js-code + kv? list-of-kv? + list-of-symbol? + list-of? ) (define-syntax while @@ -82,12 +85,14 @@ (with-input-from-string str read-json)) (define (mk-js-array l) - (if (list? l) - (string-append "[ " (string-join (map (λ (e) (format "'~a'" - (esc-quote (format "~a" e)))) l) ", ") " ]") - (format "[ '~a' ]" (esc-quote (format "~a" l))) - ) - ) + (if (list-of-kv? l) + (string-append "[ " (string-join (map (λ (e) (mk-js-array e)) l) ", ") " ]") + (if (list? l) + (string-append "[ " (string-join (map (λ (e) (format "'~a'" + (esc-quote (format "~a" e)))) l) ", ") " ]") + (if (pair? l) + (format "[ '~a', '~a' ]" (car l) (cdr l)) + (format "[ '~a' ]" (esc-quote (format "~a" l))))))) (define (js-code . a) (define (code* l) @@ -97,21 +102,26 @@ ) ) (code* a)) - -(define (list-of-kv? l) - (define (kv? e) - (let ((e (car l))) - (and (list? e) - (= (length e) 2) - (symbol? (car e))))) - (define (all-kv? l) +(define (kv? e) + (or + (and (list? e) (= (length e) 2) (symbol? (car e))) + (and (pair? e) (symbol? (car e))))) + +(define (list-of? pred? l) + (define (all-pred? l) (if (null? l) #t - (if (kv? (car e)) - (all-kv? (cdr l)) + (if (pred? (car l)) + (all-pred? (cdr l)) #f))) (if (list? l) - (all-kv? l) + (all-pred? l) #f)) + +(define (list-of-kv? l) + (list-of? kv? l)) + +(define (list-of-symbol? l) + (list-of? symbol? l)) diff --git a/rktwebview_qt/CMakeLists.txt b/rktwebview_qt/CMakeLists.txt index f0a0c88..561471d 100644 --- a/rktwebview_qt/CMakeLists.txt +++ b/rktwebview_qt/CMakeLists.txt @@ -23,6 +23,7 @@ add_library(rktwebview_qt SHARED webviewwindow.h webviewwindow.cpp webviewapp.h webviewapp.cpp rktutils.h rktutils.cpp + command.h command.cpp ) target_link_libraries(rktwebview_qt PRIVATE Qt${QT_VERSION_MAJOR}::Widgets) diff --git a/rktwebview_qt/command.cpp b/rktwebview_qt/command.cpp new file mode 100644 index 0000000..970fe0e --- /dev/null +++ b/rktwebview_qt/command.cpp @@ -0,0 +1,20 @@ +#include "command.h" + + +Command::Command(int _cmd) +{ + cmd = _cmd; + done = false; + js_result_ok = true; +} + +Command *CommandEvent::cmd() +{ + return _cmd; +} + +CommandEvent::CommandEvent(Command *c) + : QEvent(COMMAND_EVENT) +{ + _cmd = c; +} diff --git a/rktwebview_qt/command.h b/rktwebview_qt/command.h new file mode 100644 index 0000000..5a92ca3 --- /dev/null +++ b/rktwebview_qt/command.h @@ -0,0 +1,54 @@ +#ifndef COMMAND_H +#define COMMAND_H + +#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 +#define COMMAND_CALL_JS 10 +#define COMMAND_HIDE_WIN 11 +#define COMMAND_SHOW_WIN 12 +#define COMMAND_MAX_WIN 13 +#define COMMAND_MIN_WIN 14 +#define COMMAND_PRESENT_WIN 15 +#define COMMAND_SHOW_NORMAL_WIN 16 +#define COMMAND_WINDOW_STATUS 17 +#define COMMAND_SET_TITLE 18 + +class Command +{ +public: + int cmd; + QVector args; + QVariant result; + bool done; + bool js_result_ok; +public: + Command(int _cmd); +}; + + +class CommandEvent : public QEvent +{ +private: + Command *_cmd; + +public: + Command *cmd(); + +public: + CommandEvent(Command *c); +}; + + +const QEvent::Type COMMAND_EVENT = static_cast(QEvent::User + 1); + +#endif // COMMAND_H diff --git a/rktwebview_qt/main.cpp b/rktwebview_qt/main.cpp index 8063193..b0570a7 100644 --- a/rktwebview_qt/main.cpp +++ b/rktwebview_qt/main.cpp @@ -23,10 +23,10 @@ int main(int argc, char *argv[]) wv1 = rkt_webview_create(0, eventCb); rkt_webview_move(wv1, 200, 300); rkt_webview_resize(wv1, 800, 600); - rkt_webview_set_url(wv1, "http://127.0.0.1:8083"); + rkt_webview_set_url(wv1, "https://wikipedia.org"); //"http://127.0.0.1:8083"); int i = 0; - while(i < 60) { + while(i < 35) { printf("Waiting...%d\n", i); rkt_webview_process_events(1000); diff --git a/rktwebview_qt/rktutils.h b/rktwebview_qt/rktutils.h index acedce0..013645b 100644 --- a/rktwebview_qt/rktutils.h +++ b/rktwebview_qt/rktutils.h @@ -15,21 +15,7 @@ public: QString mkEventJson(const EventContainer &kv); -class Command -{ -public: - int cmd; - QVector args; - QVariant result; - bool done; - bool js_result_ok; -public: - Command(int _cmd) { - cmd = _cmd; - done = false; - js_result_ok = true; - } -}; + #endif diff --git a/rktwebview_qt/rktwebview_qt.cpp b/rktwebview_qt/rktwebview_qt.cpp index 660d717..63cd873 100644 --- a/rktwebview_qt/rktwebview_qt.cpp +++ b/rktwebview_qt/rktwebview_qt.cpp @@ -9,272 +9,250 @@ #include #include #include +#include "command.h" -#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 -#define COMMAND_CALL_JS 10 -#define COMMAND_HIDE_WIN 11 -#define COMMAND_SHOW_WIN 12 -#define COMMAND_MAX_WIN 13 -#define COMMAND_MIN_WIN 14 -#define COMMAND_PRESENT_WIN 15 -#define COMMAND_SHOW_NORMAL_WIN 16 -#define COMMAND_WINDOW_STATUS 17 -#define COMMAND_SET_TITLE 18 - -void Rktwebview_qt::processCommands() +void Rktwebview_qt::processCommand(Command *cmd) { - 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(); - switch(cmd->cmd) { - case COMMAND_QUIT: { - _app->quit(); + 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(); + while(!w->windowCreated()) { + doEvents(); + } + + cmd->result = id; + cmd->done = true; + } + break; + case COMMAND_CLOSE: { + doEvents(); + 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: { + doEvents(); + 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: { + doEvents(); + 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_SET_TITLE: { + doEvents(); + int wv = cmd->args[0].toInt(); + QString title = cmd->args[1].toString(); + if (_views.contains(wv)) { + WebviewWindow *w = _views[wv]; + w->setWindowTitle(title); + cmd->result = true; + } else { + cmd->result = false; + } + cmd->done = true; + } + break; + case COMMAND_RUN_JS: { + doEvents(); + 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_CALL_JS: { + doEvents(); + int wv = cmd->args[0].toInt(); + QString js = cmd->args[1].toString(); + if (_views.contains(wv)) { + WebviewWindow *w = _views[wv]; + w->callJs(js, cmd); + } else { + cmd->result = false; + cmd->js_result_ok = false; 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; + } + break; + case COMMAND_DEV_TOOLS: { + doEvents(); + 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_SHOW_WIN: + case COMMAND_HIDE_WIN: + case COMMAND_PRESENT_WIN: + case COMMAND_MAX_WIN: + case COMMAND_MIN_WIN: + case COMMAND_SHOW_NORMAL_WIN: + { + doEvents(); + int wv = cmd->args[0].toInt(); + if (_views.contains(wv)) { + WebviewWindow *w = _views[wv]; + int c = cmd->cmd; + if (c == COMMAND_SHOW_WIN) w->show(); + else if (c == COMMAND_HIDE_WIN) w->hide(); + else if (c == COMMAND_MAX_WIN) w->showMaximized(); + else if (c == COMMAND_MIN_WIN) { + w->showMinimized(); } - - 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(); - while(!w->windowCreated()) { + else if (c == COMMAND_SHOW_NORMAL_WIN) w->showNormal(); + else if (c == COMMAND_PRESENT_WIN) { + w->show(); + w->raise(); + w->activateWindow(); + } + cmd->result = true; + } else { + cmd->result = false; + } + cmd->done = true; + } + break; + case COMMAND_WINDOW_STATUS: + { + doEvents(); + int wv = cmd->args[0].toInt(); + window_state_t ws = window_state_t::invalid; + if (_views.contains(wv)) { + WebviewWindow *w = _views[wv]; + if (w->isHidden()) { + ws = window_state_t::hidden; + } else if (w->isMinimized()) { + ws = window_state_t::minimized; + } else if (w->isMaximized()) { + if (w->isActiveWindow()) { + ws = window_state_t::maximized_active; + } else { + ws = window_state_t::maximized; + } + } else if (w->isVisible()) { + if (w->isActiveWindow()) { + ws = window_state_t::normal_active; + } else { + ws = window_state_t::normal; + } + } + } + cmd->result = static_cast(ws); + cmd->done = true; + } + break; + case COMMAND_MOVE: { + doEvents(); + 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]; + int move_count = w->moveCount(); + w->move(x, y); + while (w->moveCount() == move_count) { doEvents(); } - - cmd->result = id; - cmd->done = true; - } - break; - case COMMAND_CLOSE: { - doEvents(); - 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: { - doEvents(); - 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: { - doEvents(); - 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_SET_TITLE: { - doEvents(); - int wv = cmd->args[0].toInt(); - QString title = cmd->args[1].toString(); - if (_views.contains(wv)) { - WebviewWindow *w = _views[wv]; - w->setWindowTitle(title); - cmd->result = true; - } else { - cmd->result = false; - } - cmd->done = true; - } - break; - case COMMAND_RUN_JS: { - doEvents(); - 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_CALL_JS: { - doEvents(); - int wv = cmd->args[0].toInt(); - QString js = cmd->args[1].toString(); - if (_views.contains(wv)) { - WebviewWindow *w = _views[wv]; - w->callJs(js, cmd); - } else { - cmd->result = false; - cmd->js_result_ok = false; - cmd->done = true; - } - } - break; - case COMMAND_DEV_TOOLS: { - doEvents(); - 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_SHOW_WIN: - case COMMAND_HIDE_WIN: - case COMMAND_PRESENT_WIN: - case COMMAND_MAX_WIN: - case COMMAND_MIN_WIN: - case COMMAND_SHOW_NORMAL_WIN: - { - doEvents(); - int wv = cmd->args[0].toInt(); - if (_views.contains(wv)) { - WebviewWindow *w = _views[wv]; - int c = cmd->cmd; - if (c == COMMAND_SHOW_WIN) w->show(); - else if (c == COMMAND_HIDE_WIN) w->hide(); - else if (c == COMMAND_MAX_WIN) w->showMaximized(); - else if (c == COMMAND_MIN_WIN) { - w->showMinimized(); - } - else if (c == COMMAND_SHOW_NORMAL_WIN) w->showNormal(); - else if (c == COMMAND_PRESENT_WIN) { - w->show(); - w->raise(); - w->activateWindow(); - } - cmd->result = true; - } else { - cmd->result = false; - } - cmd->done = true; - } - break; - case COMMAND_WINDOW_STATUS: - { - doEvents(); - int wv = cmd->args[0].toInt(); - window_state_t ws = window_state_t::invalid; - if (_views.contains(wv)) { - WebviewWindow *w = _views[wv]; - if (w->isHidden()) { - ws = window_state_t::hidden; - } else if (w->isMinimized()) { - ws = window_state_t::minimized; - } else if (w->isMaximized()) { - if (w->isActiveWindow()) { - ws = window_state_t::maximized_active; - } else { - ws = window_state_t::maximized; - } - } else if (w->isVisible()) { - if (w->isActiveWindow()) { - ws = window_state_t::normal_active; - } else { - ws = window_state_t::normal; - } - } - } - cmd->result = static_cast(ws); - cmd->done = true; - } - break; - case COMMAND_MOVE: { - doEvents(); - 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]; - int move_count = w->moveCount(); - w->move(x, y); - while (w->moveCount() == move_count) { - doEvents(); - } - cmd->result = true; - } else { - cmd->result = false; - } - cmd->done = true; - } - break; - case COMMAND_RESIZE: { - doEvents(); - 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]; - int resize_count = w->resizeCount(); - w->resize(width, height); - while (w->resizeCount() == resize_count) { - doEvents(); - } - cmd->result = true; - } else { - cmd->result = false; - } - cmd->done = true; - } - break; - default: { + cmd->result = true; + } else { cmd->result = false; - cmd->done = true; } - break; + cmd->done = true; + } + break; + case COMMAND_RESIZE: { + doEvents(); + 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]; + int resize_count = w->resizeCount(); + w->resize(width, height); + while (w->resizeCount() == resize_count) { + doEvents(); + } + cmd->result = true; + } else { + cmd->result = false; } + cmd->done = true; + } + break; + default: { + cmd->result = false; + cmd->done = true; + } + break; } } @@ -314,7 +292,7 @@ int Rktwebview_qt::rktWebViewCreate(int parent, event_cb_t js_evt_cb) QVariant f(QVariant::fromValue(function)); c.args.push_back(f); - _command_queue.enqueue(&c); + postCommand(&c); while(!c.done) { doEvents(); } @@ -327,7 +305,7 @@ void Rktwebview_qt::rktWebViewClose(int wv) Command c(COMMAND_CLOSE); c.args.push_back(wv); - _command_queue.enqueue(&c); + postCommand(&c); while(!c.done) { doEvents(); } } @@ -338,7 +316,7 @@ result_t Rktwebview_qt::rktSetUrl(rktwebview_t wv, const char *url) QString _url(url); c.args.push_back(wv); c.args.push_back(_url); - _command_queue.enqueue(&c); + postCommand(&c); while(!c.done) { doEvents(); } @@ -353,7 +331,7 @@ result_t Rktwebview_qt::rktSetHtml(rktwebview_t wv, const char *html) QString _html(html); c.args.push_back(wv); c.args.push_back(_html); - _command_queue.enqueue(&c); + postCommand(&c); while(!c.done) { doEvents(); } @@ -368,7 +346,7 @@ rkt_js_result_t *Rktwebview_qt::rktCallJs(rktwebview_t wv, const char *js) QString _js(js); c.args.push_back(wv); c.args.push_back(_js); - _command_queue.enqueue(&c); + postCommand(&c); while(!c.done) { doEvents(); } rkt_js_result_t *r = static_cast(malloc(sizeof(rkt_js_result_t))); @@ -384,7 +362,7 @@ result_t Rktwebview_qt::rktRunJs(rktwebview_t wv, const char *js) QString _js(js); c.args.push_back(wv); c.args.push_back(_js); - _command_queue.enqueue(&c); + postCommand(&c); while(!c.done) { doEvents(); } bool r = c.result.toBool(); return r ? result_t::oke : result_t::eval_js_failed; @@ -396,7 +374,7 @@ result_t Rktwebview_qt::rktMove(rktwebview_t wv, int x, int y) c.args.push_back(wv); c.args.push_back(x); c.args.push_back(y); - _command_queue.enqueue(&c); + postCommand(&c); while(!c.done) { doEvents(); } bool r = c.result.toBool(); return r ? result_t::oke : result_t::move_failed; @@ -408,7 +386,7 @@ result_t Rktwebview_qt::rktResize(rktwebview_t wv, int w, int h) c.args.push_back(wv); c.args.push_back(w); c.args.push_back(h); - _command_queue.enqueue(&c); + postCommand(&c); while(!c.done) { doEvents(); } bool r = c.result.toBool(); return r ? result_t::oke : result_t::resize_failed; @@ -448,7 +426,7 @@ window_state_t Rktwebview_qt::rktWindowState(rktwebview_t w) { Command c(COMMAND_WINDOW_STATUS); c.args.push_back(w); - _command_queue.enqueue(&c); + postCommand(&c); while(!c.done) { doEvents(); } int r = c.result.toInt(); window_state_t ws = static_cast(r); @@ -460,7 +438,7 @@ result_t Rktwebview_qt::rktWindowSetTitle(rktwebview_t wv, const char *title) Command c(COMMAND_SET_TITLE); c.args.push_back(wv); c.args.push_back(title); - _command_queue.enqueue(&c); + postCommand(&c); while(!c.done) { doEvents(); } bool r = c.result.toBool(); return r ? result_t::oke : result_t::resize_failed; @@ -470,7 +448,7 @@ result_t Rktwebview_qt::doWindow(rktwebview_t w, int cmd) { Command c(cmd); c.args.push_back(w); - _command_queue.enqueue(&c); + postCommand(&c); while(!c.done) { doEvents(); } bool r = c.result.toBool(); return r ? result_t::oke : result_t::resize_failed; @@ -485,7 +463,7 @@ result_t Rktwebview_qt::rktOpenDevtools(rktwebview_t wv) { Command c(COMMAND_DEV_TOOLS); c.args.push_back(wv); - _command_queue.enqueue(&c); + postCommand(&c); while(!c.done) { doEvents(); } bool r = c.result.toBool(); return r ? result_t::oke : result_t::eval_js_failed; @@ -544,7 +522,7 @@ void Rktwebview_qt::rktQuit() } Command c(COMMAND_QUIT); - _command_queue.enqueue(&c); + postCommand(&c); while(!c.done) { doEvents(); } } @@ -558,11 +536,46 @@ void Rktwebview_qt::runJs(rktwebview_t wv, const char *js) } } + +void Rktwebview_qt::postCommand(Command *cmd) +{ + CommandEvent *e = new CommandEvent(cmd); + QApplication::postEvent(this, e); +} + +void Rktwebview_qt::handleCommandEvent(CommandEvent *e) +{ + Command *c = e->cmd(); + processCommand(c); +} + +void Rktwebview_qt::customEvent(QEvent *event) +{ + if (event->type() == COMMAND_EVENT) { + handleCommandEvent(static_cast(event)); + } +} + void Rktwebview_qt::doEvents() { - _app->processEvents(); + //_app->processEvents(); + if (_evt_loop_depth == 0) { + _evt_loop_depth += 1; + _evt_loop_timer.setSingleShot(true); + _evt_loop_timer.start(2); + //_evt_loop.exec(); + _app->exec(); + } } +void Rktwebview_qt::stopEventloop() +{ + //_evt_loop.exit(0); + _app->exit(0); + _evt_loop_depth -= 1; +} + + Rktwebview_qt::Rktwebview_qt(Rktwebview_qt **handler) : QObject() { @@ -573,19 +586,21 @@ Rktwebview_qt::Rktwebview_qt(Rktwebview_qt **handler) : _current_handle = 0; _handler = handler; + _evt_loop_depth = 0; _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); - const auto *eventDispatcher = QThread::currentThread()->eventDispatcher(); - QObject::connect(eventDispatcher, &QAbstractEventDispatcher::aboutToBlock, - QThread::currentThread(), []{ - if (QThread::currentThread()->loopLevel() == 0) - QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); - } - ); + connect(&_evt_loop_timer, &QTimer::timeout, this, &Rktwebview_qt::stopEventloop); + + //const auto *eventDispatcher = QThread::currentThread()->eventDispatcher(); + //QObject::connect(eventDispatcher, &QAbstractEventDispatcher::aboutToBlock, + // QThread::currentThread(), []{ + // if (QThread::currentThread()->loopLevel() == 0) + // QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); + // } + // ); *_handler = nullptr; } diff --git a/rktwebview_qt/rktwebview_qt.h b/rktwebview_qt/rktwebview_qt.h index 754b0da..398c4e7 100644 --- a/rktwebview_qt/rktwebview_qt.h +++ b/rktwebview_qt/rktwebview_qt.h @@ -12,11 +12,13 @@ #include #include #include +#include class WebViewQt; class WebviewWindow; class Command; +class CommandEvent; class RKTWEBVIEW_QT_EXPORT Rktwebview_qt : public QObject { @@ -27,10 +29,11 @@ private: QHash _views; QHash _view_js_callbacks; - QQueue _command_queue; - QTimer _process_commands; QTimer _process_events; + int _evt_loop_depth; + QTimer _evt_loop_timer; + Rktwebview_qt **_handler; int _argc; @@ -41,9 +44,20 @@ private: result_t doWindow(rktwebview_t w, int cmd); public slots: - void processCommands(); void processJsEventQueues(); +private slots: + void stopEventloop(); + +private: + void postCommand(Command *cmd); + void handleCommandEvent(CommandEvent *e); + void processCommand(Command *cmd); + + // QObject interface +protected: + void customEvent(QEvent *event); + public: void removeView(int id); @@ -91,6 +105,7 @@ public: public: Rktwebview_qt(Rktwebview_qt **handler); + }; #endif // RKTWEBVIEW_QT_H diff --git a/rktwebview_qt/webviewwindow.cpp b/rktwebview_qt/webviewwindow.cpp index 94a65e3..62cbc35 100644 --- a/rktwebview_qt/webviewwindow.cpp +++ b/rktwebview_qt/webviewwindow.cpp @@ -3,15 +3,16 @@ #include "webviewqt.h" #include "rktwebview_qt.h" #include "rktutils.h" +#include "command.h" #include #include #include #include #include #include - #include + WebviewWindow::WebviewWindow(QWidget *parent) : QMainWindow{parent} { @@ -194,6 +195,7 @@ void WebviewWindow::moveEvent(QMoveEvent *event) _move_timer.setSingleShot(true); _move_timer.start(500); _moved += 1; + //triggerMove(); } void WebviewWindow::triggerMove() @@ -211,6 +213,7 @@ void WebviewWindow::resizeEvent(QResizeEvent *event) _resize_timer.setSingleShot(true); _resize_timer.start(500); _resized += 1; + //triggerResize(); } void WebviewWindow::triggerResize()