From 8f49007930d4de7a8c7afda27d7f01808a2a8383 Mon Sep 17 00:00:00 2001 From: Hans Dijkema Date: Tue, 3 Mar 2026 22:52:22 +0100 Subject: [PATCH] - --- private/racket-webview-qt.rkt | 4 +++ private/racket-webview.rkt | 10 +++--- private/web-racket.rkt | 59 +++++++++++++++++++++------------ rktwebview_qt/main.cpp | 16 +++++++++ rktwebview_qt/rktutils.h | 17 ++++++++++ rktwebview_qt/rktwebview.cpp | 18 ++++++++++ rktwebview_qt/rktwebview.h | 10 ++++++ rktwebview_qt/rktwebview_qt.cpp | 44 ++++++++++++++++-------- rktwebview_qt/rktwebview_qt.h | 1 + rktwebview_qt/webviewwindow.cpp | 25 ++++++++++++++ rktwebview_qt/webviewwindow.h | 2 ++ 11 files changed, 167 insertions(+), 39 deletions(-) diff --git a/private/racket-webview-qt.rkt b/private/racket-webview-qt.rkt index 053b7a7..8db1e5a 100644 --- a/private/racket-webview-qt.rkt +++ b/private/racket-webview-qt.rkt @@ -21,6 +21,7 @@ rkt-webview-set-url! rkt-webview-set-html! rkt-webview-run-js + rkt-webview-call-js rkt-webview-move rkt-webview-resize rkt-webview-exit @@ -200,6 +201,9 @@ (define (rkt-webview-run-js wv js) (rkt_webview_run_js (rkt-wv-win wv) js)) +(define (rkt-webview-call-js wv js) + (rkt_webview_call_js (rkt-wv-win wv) js)) + (define (rkt-webview-resize wv w h) (rkt_webview_resize (rkt-wv-win wv) w h)) diff --git a/private/racket-webview.rkt b/private/racket-webview.rkt index e7d301e..a11ec6d 100644 --- a/private/racket-webview.rkt +++ b/private/racket-webview.rkt @@ -18,10 +18,12 @@ webview-devtools webview-close webview-run-js + webview-call-js webview-move webview-resize webview-bind! webview-standard-file-getter + ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -113,7 +115,7 @@ #:parent [p 0]) (let* ((h (make-wv #f current-servlet-port -1 file-getter bj #f)) (server (let ((s (start-web-server h))) - (sleep 1) + (sleep 1) ;;; TODO: Check if web server is up. s)) (event-processor (λ (wv evt) (event-callback h (util-parse-event evt)))) @@ -166,9 +168,9 @@ (on-not-exist file base-path p) p))))) -;(define (webview-call-js wv js) -; (let ((result (rkt_webview_call_js (wv-handle wv) js))) -; result)) +(define (webview-call-js wv js) + (let ((result (rkt_webview_call_js (wv-handle wv) js))) + result)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; testing diff --git a/private/web-racket.rkt b/private/web-racket.rkt index 64484a8..17a29d9 100644 --- a/private/web-racket.rkt +++ b/private/web-racket.rkt @@ -79,6 +79,18 @@ (set! _std_x 50)) ))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Storage + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + (define windows (make-hash)) + + (define (ww-debug msg) + (displayln (format "DBG: ~a" msg))) + + (define (ww-error msg) + (displayln (format "ERR: ~a" msg))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Class representing an element in the HTML page ;; each element is identified by an id. @@ -94,9 +106,9 @@ (define/public (get-id) id) - (define/public (win) - (let ((w (hash-ref windows (ww-win-id win-id) #f))) - w)) + ;(define/public (win) + ; (let ((w (hash-ref windows (ww-win-id win-id) #f))) + ; w)) (define connected-callbacks (make-hash)) @@ -110,7 +122,7 @@ (apply cb args))))) (define/public (exec-js js) - (ww-exec-js win-id js)) + (webview-run-js win-id js)) (define/public (connect evt func) (hash-set! connected-callbacks evt func)) @@ -119,34 +131,34 @@ (hash-remove! connected-callbacks evt)) (define/public (add-style! st) - (ww-add-style win-id id st)) + (webview-add-style win-id id st)) (define/public (set-style! st) - (ww-set-style win-id id st)) + (webview-set-style win-id id st)) (define/public (style) - (ww-get-style win-id id)) + (webview-get-style win-id id)) (define/public (get-attr a) - (ww-get-attr win-id id a)) + (webview-get-attr win-id id a)) (define/public (set-attr! a val) - (ww-set-attr win-id id a val)) + (webview-set-attr win-id id a val)) (define/public (del-attr a) - (ww-del-attr win-id id a)) + (webview-del-attr win-id id a)) (define/public (get-attrs) - (ww-get-attrs win-id id)) + (webview-get-attrs win-id id)) (define/public (add-class! cl) - (ww-add-class win-id id cl)) + (webview-add-class win-id id cl)) (define/public (remove-class! cl) - (ww-remove-class win-id id cl)) + (webview-remove-class win-id id cl)) (define/public (has-class? cl) - (ww-has-class? win-id id cl)) + (webview-has-class? win-id id cl)) (define/public (enable) (send this remove-class! 'disabled)) @@ -175,7 +187,7 @@ (define/public (set-inner-html! html-or-sexpr) (if (string? html-or-sexpr) - (ww-set-inner-html win-id id html-or-sexpr) + (webview-set-inner-html! win-id id html-or-sexpr) (set-inner-html! (xexpr->html5 html-or-sexpr)))) (super-new) @@ -345,6 +357,8 @@ [height (if (eq? settings #f) _std_h (send settings get 'window-height _std_h))] [icon #f] [menu #f] + [base-path (build-path ".")] + [on-not-exist (λ (file base-path path) path)] [html-file #f] ) @@ -525,10 +539,10 @@ (ww-get-elements win-id selector)) (define/public (move x y) - (ww-move win-id x y)) + (webview-move win-id x y)) (define/public (resize x y) - (ww-resize win-id x y)) + (webview-resize win-id x y)) (define/public (get-x) x) (define/public (get-y) y) @@ -731,14 +745,17 @@ ; (ww-new profile use-browser) ; (ww-new profile use-browser parent-id))) (set! win-id (webview-create - (λ (file) file) + (webview-standard-file-getter base-path + #:not-exist not-exist) + event-handler)) + (when (eq? win-id #f) (error "Window could not be constructed")) - (hash-set! windows-evt-handlers (ww-win-id win-id) event-handler) + ;(hash-set! windows-evt-handlers (ww-win-id win-id) event-handler) (hash-set! windows (ww-win-id win-id) this) - (ww-resize win-id width height) + (webview-resize win-id width height) (when parent (let* ((parent-width (send parent get-width)) @@ -750,7 +767,7 @@ (set! y (+ parent-y (/ (- parent-height height) 2))) ) ) - (ww-move win-id x y) + (webview-move win-id x y) (send this set-title! title) diff --git a/rktwebview_qt/main.cpp b/rktwebview_qt/main.cpp index fdf00f8..4702f46 100644 --- a/rktwebview_qt/main.cpp +++ b/rktwebview_qt/main.cpp @@ -32,6 +32,22 @@ int main(int argc, char *argv[]) rkt_webview_open_devtools(wv1); } + if (i == 3) { + rkt_js_result_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->result, r->value); + } + + if (i == 4) { + rkt_js_result_t *r = rkt_webview_call_js(wv1, "let el = document.getElementById('hi');el.value = '10';"); + printf("rkt_js_result: %d: %s\n", r->result, r->value); + } + + if (i == 6) { + rkt_js_result_t *r = rkt_webview_call_js(wv1, "document.body.innerHTML = '

Hi!

'; return document.body.innerHTML;"); + printf("rkt_js_result: %d: %s\n", r->result, r->value); + } + + if (i == 10) { wv2 = rkt_webview_create(0, eventCb); } diff --git a/rktwebview_qt/rktutils.h b/rktwebview_qt/rktutils.h index ef3ac0f..acedce0 100644 --- a/rktwebview_qt/rktutils.h +++ b/rktwebview_qt/rktutils.h @@ -15,4 +15,21 @@ 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.cpp b/rktwebview_qt/rktwebview.cpp index c887b4e..ac8ea8b 100644 --- a/rktwebview_qt/rktwebview.cpp +++ b/rktwebview_qt/rktwebview.cpp @@ -66,6 +66,14 @@ result_t rkt_webview_run_js(rktwebview_t wv, const char *js) return r; } +rkt_js_result_t *rkt_webview_call_js(rktwebview_t wv, const char *js) +{ + rkt_webview_init(); + rkt_js_result_t *r = handler->rktCallJs(wv, js); + return r; +} + + result_t rkt_webview_open_devtools(rktwebview_t wv) { @@ -95,6 +103,14 @@ result_t rkt_webview_destroy_event(rkt_event_t *e) return result_t::oke; } +result_t rkt_webview_destroy_js_result(rkt_js_result_t *r) +{ + free(r->value); + free(r); + return result_t::oke; +} + + result_t rkt_webview_move(rktwebview_t wv, int x, int y) { rkt_webview_init(); @@ -118,3 +134,5 @@ bool rkt_webview_valid(rktwebview_t wv) rkt_webview_init(); return handler->rktValid(wv); } + + diff --git a/rktwebview_qt/rktwebview.h b/rktwebview_qt/rktwebview.h index 47c1626..7faa013 100644 --- a/rktwebview_qt/rktwebview.h +++ b/rktwebview_qt/rktwebview.h @@ -32,6 +32,13 @@ typedef enum { resize_failed = 13 } result_t; +typedef struct { + result_t result; + char *value; +} rkt_js_result_t; + + + RKTWEBVIEW_QT_EXPORT void rkt_webview_init(); RKTWEBVIEW_QT_EXPORT void rkt_webview_process_events(int for_ms); @@ -44,6 +51,9 @@ RKTWEBVIEW_QT_EXPORT result_t rkt_webview_set_url(rktwebview_t wv, const char *u RKTWEBVIEW_QT_EXPORT result_t rkt_webview_set_html(rktwebview_t wv, const char *html); RKTWEBVIEW_QT_EXPORT result_t rkt_webview_run_js(rktwebview_t wv, const char *js); +RKTWEBVIEW_QT_EXPORT rkt_js_result_t *rkt_webview_call_js(rktwebview_t wv, const char *js); +RKTWEBVIEW_QT_EXPORT result_t rkt_webview_destroy_js_result(rkt_js_result_t *r); + RKTWEBVIEW_QT_EXPORT result_t rkt_webview_open_devtools(rktwebview_t wv); RKTWEBVIEW_QT_EXPORT result_t rkt_webview_destroy_event(rkt_event_t *e); diff --git a/rktwebview_qt/rktwebview_qt.cpp b/rktwebview_qt/rktwebview_qt.cpp index 4c44b59..b453338 100644 --- a/rktwebview_qt/rktwebview_qt.cpp +++ b/rktwebview_qt/rktwebview_qt.cpp @@ -18,20 +18,7 @@ #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; - } -}; +#define COMMAND_CALL_JS 10 void Rktwebview_qt::processCommands() { @@ -127,6 +114,19 @@ void Rktwebview_qt::processCommands() cmd->done = true; } break; + case COMMAND_CALL_JS: { + 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: { int wv = cmd->args[0].toInt(); if (_views.contains(wv)) { @@ -260,6 +260,22 @@ result_t Rktwebview_qt::rktSetHtml(rktwebview_t wv, const char *html) return r ? result_t::oke : result_t::set_navigate_failed; } +rkt_js_result_t *Rktwebview_qt::rktCallJs(rktwebview_t wv, const char *js) +{ + Command c(COMMAND_CALL_JS); + QString _js(js); + c.args.push_back(wv); + c.args.push_back(_js); + _command_queue.enqueue(&c); + while(!c.done) { doEvents(); } + + rkt_js_result_t *r = static_cast(malloc(sizeof(rkt_js_result_t))); + r->result = c.js_result_ok ? result_t::oke : result_t::eval_js_failed; + r->value = strdup(c.result.toString().toUtf8()); + + return r; +} + result_t Rktwebview_qt::rktRunJs(rktwebview_t wv, const char *js) { Command c(COMMAND_RUN_JS); diff --git a/rktwebview_qt/rktwebview_qt.h b/rktwebview_qt/rktwebview_qt.h index 0cf6ccf..5aece18 100644 --- a/rktwebview_qt/rktwebview_qt.h +++ b/rktwebview_qt/rktwebview_qt.h @@ -57,6 +57,7 @@ public: result_t rktSetUrl(rktwebview_t wv, const char *url); result_t rktSetHtml(rktwebview_t wv, const char *html); result_t rktRunJs(rktwebview_t wv, const char *js); + rkt_js_result_t *rktCallJs(rktwebview_t wv, const char *js); result_t rktMove(rktwebview_t wv, int x, int y); result_t rktResize(rktwebview_t wv, int w, int h); bool rktValid(rktwebview_t wv); diff --git a/rktwebview_qt/webviewwindow.cpp b/rktwebview_qt/webviewwindow.cpp index 9e5f118..e5356b3 100644 --- a/rktwebview_qt/webviewwindow.cpp +++ b/rktwebview_qt/webviewwindow.cpp @@ -129,6 +129,31 @@ void WebviewWindow::runJs(const QString &js) p->runJavaScript(js); } +void WebviewWindow::callJs(const QString &js, Command *c) +{ + QWebEnginePage *p = _view->page(); + QString _js = QString("{\n") + + " let f = function() {\n" + + " " + js + "\n" + + " };\n" + + " try {\n" + + " let obj = { oke: true, result: f(), exn: false };\n" + + " obj;\n" + + " } catch(e) {\n" + + " let obj = { oke: false, result: false, exn: e.message };\n" + + " obj;\n" + + " }\n" + + "}"; + p->runJavaScript(_js, [c](const QVariant &v) { + c->result = v; + QJsonObject obj = v.toJsonObject(); + bool ok = obj["oke"].toBool(); + c->js_result_ok = ok; + c->result = QString::fromUtf8(QJsonDocument(obj).toJson(QJsonDocument::JsonFormat::Compact)); + c->done = true; + }); +} + void WebviewWindow::openDevTools() { _devtools = new QMainWindow(this); diff --git a/rktwebview_qt/webviewwindow.h b/rktwebview_qt/webviewwindow.h index 4e48520..cf266d8 100644 --- a/rktwebview_qt/webviewwindow.h +++ b/rktwebview_qt/webviewwindow.h @@ -6,6 +6,7 @@ class WebViewQt; class Rktwebview_qt; +class Command; class WebviewWindow : public QMainWindow { @@ -39,6 +40,7 @@ public: public: void runJs(const QString &js); + void callJs(const QString &js, Command *c); void openDevTools(); public: