diff --git a/private/lib/linux/librktwebview_qt.so b/private/lib/linux/librktwebview_qt.so index c8170bf..a3a89a9 100755 Binary files a/private/lib/linux/librktwebview_qt.so and b/private/lib/linux/librktwebview_qt.so differ diff --git a/private/racket-webview.rkt b/private/racket-webview.rkt index 8f3a686..259d7cd 100644 --- a/private/racket-webview.rkt +++ b/private/racket-webview.rkt @@ -43,12 +43,29 @@ webview-value/bool webview-value/symbol webview-value/number + ;webview-value/date + ;webview-value/time + ;webview-value/datetime webview-add-class! webview-remove-class! webview-set-style! + webview-unset-style! + + webview-set-attr! + webview-attr + ;webview-attr/bool + ;webview-attr/symbol + ;webview-attr/number + ;webview-attr/date + ;webview-attr/time + ;webview-attr/datetime + + ;webview-del-attr! webview-standard-file-getter + + test ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -242,10 +259,10 @@ (define/contract (webview-close wv) (-> 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()