Compare commits

...

7 Commits

Author SHA1 Message Date
hans d33e8164c8 QtWebEngine select popup rendering issue observed with older Qt 6.x.
Symptom: native HTML <select> popup keeps growing/repainting while open;
QtWebEngine process busy, Racket process idle.
Resolved by upgrading to Qt 6.11.1.
2026-07-07 19:24:46 +02:00
hans 9caa41a6f5 Windows has been migrated to Qt 6.11.1 2026-07-07 17:57:56 +02:00
hans 48076b8a38 (js (= x y)) does noet work, needs to be (js (== x y)) 2026-07-03 22:02:43 +02:00
hans 8eeb02a9fa display weg 2026-07-03 19:14:58 +02:00
hans ee5cc863fa Don't display javascript code 2026-07-03 14:32:57 +02:00
hans 9a670acf15 js-maker integration 2026-07-02 15:36:03 +02:00
hans d71f326d88 js-maker integration part 1 2026-06-01 20:18:21 +02:00
5 changed files with 240 additions and 106 deletions
+8
View File
@@ -1,3 +1,11 @@
# racket-webview # racket-webview
Webview integration for racket Webview integration for racket
## Release v0.1.8
Uses release v0.2.2 of racket-webview-qt.
QtWebEngine select popup rendering issue observed with older Qt 6.x.
Symptom: native HTML <select> popup keeps growing/repainting while open;
QtWebEngine process busy, Racket process idle.
Resolved by upgrading to Qt 6.11.1.
+5
View File
@@ -19,6 +19,11 @@
</div> </div>
<p><span id="pos">screen coöords</span></p> <p><span id="pos">screen coöords</span></p>
<h2>Opening a link to some website</h2> <h2>Opening a link to some website</h2>
<label for="sel-lang">Hoi:</label>
<select id="sel-lang">
<option value="nl" selected="selected">Nederlands</option>
<option value="en">English</option>
</select>
<p> <p>
<ul> <ul>
<li><a href="https://wikipedia.org">To Wikipedia</a></li> <li><a href="https://wikipedia.org">To Wikipedia</a></li>
+2 -1
View File
@@ -1,7 +1,7 @@
#lang info #lang info
(define pkg-authors '(hnmdijkema)) (define pkg-authors '(hnmdijkema))
(define version "0.1.7") (define version "0.1.8")
(define license 'MIT) (define license 'MIT)
(define collection "racket-webview") (define collection "racket-webview")
(define pkg-desc "racket-webview - A Web Based GUI library, based on a Qt WebEngine backend") (define pkg-desc "racket-webview - A Web Based GUI library, based on a Qt WebEngine backend")
@@ -28,6 +28,7 @@
"web-server-lib" "web-server-lib"
"net-cookies-lib" "net-cookies-lib"
"simple-log" "simple-log"
"js-maker"
) )
) )
+1 -1
View File
@@ -26,7 +26,7 @@
(define rkt-qt-version-major 0) (define rkt-qt-version-major 0)
(define rkt-qt-version-minor 2) (define rkt-qt-version-minor 2)
(define rkt-qt-version-patch 1) (define rkt-qt-version-patch (if (eq? (system-type 'os) 'windows) 2 1))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Internal functions ;; Internal functions
+219 -99
View File
@@ -401,7 +401,9 @@
(syntax-rules () (syntax-rules ()
((_ id el e1 ...) ((_ id el e1 ...)
(js (let ((el (send document getElementById (eval id)))) (js (let ((el (send document getElementById (eval id))))
e1 ...))))) e1 ...)))
)
)
(define-syntax with-id (define-syntax with-id
(syntax-rules () (syntax-rules ()
@@ -427,9 +429,13 @@
(define-syntax with-selector (define-syntax with-selector
(syntax-rules () (syntax-rules ()
((_ selector func) ((_ selector func)
(format "return window.rkt_with_selector('~a', ~a)" (js
(esc-quote selector) (return (send window rkt_with_selector (eval selector) func))))
func)))) )
)
; (format "return window.rkt_with_selector('~a', ~a)"
; (esc-quote selector)
; func))))
(define (make-exts-filter list-of-pe) (define (make-exts-filter list-of-pe)
(define (mef pe) (define (mef pe)
@@ -579,22 +585,26 @@
(define/contract (webview-set-menu! wv menu) (define/contract (webview-set-menu! wv menu)
(-> wv-win? is-wv-menu? symbol?) (-> wv-win? is-wv-menu? symbol?)
(let* ((json (wv-menu->json menu)) (let* ((json (wv-menu->json menu))
(js (string-append "window._web_wire_menu('" (js-code (js (send window _web_wire_menu (eval json))))
json ;(string-append "window._web_wire_menu('"
"');")) ; json
; "');"))
) )
(webview-run-js wv js) (webview-run-js wv js-code)
) )
) )
(define/contract (webview-popup-menu! wv menu x y) (define/contract (webview-popup-menu! wv menu x y)
(-> wv-win? is-wv-menu? number? number? symbol?) (-> wv-win? is-wv-menu? number? number? symbol?)
(let* ((json (wv-menu->json menu)) (let* ((json (wv-menu->json menu))
(js (string-append "window._web_wire_popup_menu(JSON.parse('" (js-code (js (send window _web_wire_popup_menu
json "'), " (format "~a, ~a" x y) (send JSON parse (eval json))
");")) (eval x) (eval y))))
;(string-append "window._web_wire_popup_menu(JSON.parse('"
; json "'), " (format "~a, ~a" x y)
; ");"))
) )
(webview-run-js wv js))) (webview-run-js wv js-code)))
(define (loglevel? x) (define (loglevel? x)
(and (symbol? x) (and (symbol? x)
@@ -624,8 +634,10 @@
(define/contract (webview-navigate! wv place) (define/contract (webview-navigate! wv place)
(-> wv-win? string? symbol?) (-> wv-win? string? symbol?)
(webview-run-js wv (webview-run-js wv
(format "window.location = '~a';" (js (set! (js-dot window location) (eval place)))
(esc-quote place)))) ;(format "window.location = '~a';"
; (esc-quote place))))
))
(define/contract (webview-base-url wv) (define/contract (webview-base-url wv)
(-> wv-win? url?) (-> wv-win? url?)
@@ -772,7 +784,7 @@
(define/contract (webview-call-js wv js) (define/contract (webview-call-js wv js)
(-> wv-win? string? (or/c string? list? boolean? hash? symbol? number?)) (-> wv-win? string? (or/c string? list? boolean? hash? symbol? number?))
(displayln js) ;(displayln js)
(let ((result (rkt-webview-call-js (wv-win-handle wv) js))) (let ((result (rkt-webview-call-js (wv-win-handle wv) js)))
(if (webview-call-js-result? result) (if (webview-call-js-result? result)
(if (eq? (car result) 'oke) (if (eq? (car result) 'oke)
@@ -796,7 +808,7 @@
(let ((r (webview-call-js wv (let ((r (webview-call-js wv
(with-id->el id el (with-id->el id el
(set! (js-dot el innerHTML) (eval html)) (set! (js-dot el innerHTML) (eval html))
#t)))) (return #t)))))
;(with-id id el ;(with-id id el
; ("el.innerHTML = '~a'; return true;" ; ("el.innerHTML = '~a'; return true;"
; (esc-quote html)))))) ; (esc-quote html))))))
@@ -808,6 +820,26 @@
(define/contract (webview-set-value! wv id val) (define/contract (webview-set-value! wv id val)
(-> wv-win? symbol? (or/c symbol? string? number? boolean? g:date? g:time? g:datetime? rgba?) symbol?) (-> wv-win? symbol? (or/c symbol? string? number? boolean? g:date? g:time? g:datetime? rgba?) symbol?)
(webview-run-js wv (webview-run-js wv
(with-id->el id el
(if (or
(== (js-dot el type) "checkbox")
(== (js-dot el type) "radio"))
(set! (js-dot el checked)
(eval
(if (eq? val #f) #f #t)))
(set! (js-dot el value)
(eval
(cond
((g:date? val) (date->string val))
((g:time? val) (time->string val))
((g:datetime? val) (datetime->string val))
((rgba? val) (rgba->hex val))
(else val)))))
)
)
)
#|
(with-id id el (with-id id el
((string-append ((string-append
"if (el.type == 'checkbox' || el.type == 'radio') {\n" "if (el.type == 'checkbox' || el.type == 'radio') {\n"
@@ -831,19 +863,25 @@
) )
) )
) )
|#
(define/contract (webview-value wv id) (define/contract (webview-value wv id)
(-> wv-win? symbol? (or/c string? boolean?)) (-> wv-win? symbol? (or/c string? boolean?))
(let ((v (webview-call-js wv (let ((v (webview-call-js wv
(with-id id el (with-id->el id el
((string-append "let f = function() {\n" (if (or (== (js-dot el type) "checkbox")
" if (el.type == 'checkbox' || el.type == 'radio') {\n" (== (js-dot el type) "radio"))
" return '' + el.checked;\n" (return (js-dot el checked))
" } else {\n" (return (js-dot el value)))))))
" return el.value;\n" ;(with-id id el
" }\n" ; ((string-append "let f = function() {\n"
"};\n")) ; " if (el.type == 'checkbox' || el.type == 'radio') {\n"
-> "f()")))) ; " return '' + el.checked;\n"
; " } else {\n"
; " return el.value;\n"
; " }\n"
; "};\n"))
; -> "f()"))))
(if (eq? v #f) (if (eq? v #f)
#f #f
v))) v)))
@@ -875,94 +913,151 @@
(let ((sel (if (symbol? id-or-selector) (let ((sel (if (symbol? id-or-selector)
(format "#~a" id-or-selector) (format "#~a" id-or-selector)
id-or-selector)) id-or-selector))
(cl (mk-js-array class)) ;(cl (mk-js-array class))
(cl (if (list? class) class (list class)))
) )
(webview-call-js wv (with-selector sel (webview-call-js wv (with-selector sel
(format (λ (id el)
(js-code (let ((cl (eval cl)))
"function(id, el) {" (send cl forEach
" let cl = ~a;" (λ (c)
" cl.forEach(function(c) {" (send (js-dot el classList) add c)
" el.classList.add(c);"
" });"
" return id;"
"}") cl)))
) )
) )
(return id))))
)
)
)
; (format
; (js-code
; "function(id, el) {"
; " let cl = ~a;"
; " cl.forEach(function(c) {"
; " el.classList.add(c);"
; " });"
; " return id;"
; "}") cl)))
; )
; )
(define/contract (webview-remove-class! wv id-or-selector class) (define/contract (webview-remove-class! wv id-or-selector class)
(-> wv-win? (or/c symbol? string?) (or/c symbol? string? list?) (or/c hash? boolean?)) (-> wv-win? (or/c symbol? string?) (or/c symbol? string? list?) (or/c hash? boolean?))
(let ((sel (if (symbol? id-or-selector) (let ((sel (if (symbol? id-or-selector)
(format "#~a" id-or-selector) (format "#~a" id-or-selector)
id-or-selector)) id-or-selector))
(cl (mk-js-array class)) (cl (if (list? class) class (list class)))
) )
(webview-call-js wv (webview-call-js wv
(with-selector sel (with-selector sel
(format (λ (id el)
(js-code (let ((cl (eval cl)))
"function(id, el) {" (send cl forEach
" let cl = ~a;" (λ (c)
" cl.forEach(function(c) {" (send (js-dot el classList) remove c))))
" el.classList.remove(c);" id)))
" });"
" return id;"
"}") cl))
)
) )
) )
; (with-selector sel
; (format
;; (js-code
; "function(id, el) {"
; " let cl = ~a;"
; " cl.forEach(function(c) {"
; " el.classList.remove(c);"
; " });"
; " return id;"
; "}") cl))
; )
; )
; )
(define/contract (webview-set-style! wv selector style-entries) (define/contract (webview-set-style! wv selector style-entries)
(-> wv-win? (or/c symbol? string?) (or/c kv? list-of-kv?) (or/c hash? boolean?)) (-> wv-win? (or/c symbol? string?) (or/c kv? list-of-kv?) (or/c hash? boolean?))
(let ((sel (if (symbol? selector) (let ((sel (if (symbol? selector)
(format "#~a" selector) (format "#~a" selector)
selector)) selector))
(cl (mk-js-array (if (kv? style-entries) ;(cl (mk-js-array (if (kv? style-entries)
; (list style-entries)
; style-entries)))
(cl (if (kv? style-entries)
(list style-entries) (list style-entries)
style-entries))) style-entries))
) )
(webview-call-js wv (webview-call-js wv
(with-selector sel (with-selector sel
(format (λ (id el)
(js-code (let ((cl (eval cl)))
"function(id, el) {" (send cl forEach
" let cl = ~a;" (λ (st)
" cl.forEach(function(st) {" (set! (js-ref
" el.style[st[0]] = st[1];" (js-dot el style)
" });" (js-ref st 0))
" return id;" (js-ref st 1))))
"}") cl)) id)))
) )
) )
) )
; (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-get-style wv selector styles) (define/contract (webview-get-style wv selector styles)
(-> wv-win? (or/c symbol? string?) (or/c symbol? list-of-symbol?) (or/c list? hash?)) (-> wv-win? (or/c symbol? string?) (or/c symbol? list-of-symbol?) (or/c list? hash?))
(let ((sel (if (symbol? selector) (let ((sel (if (symbol? selector)
(format "#~a" selector) (format "#~a" selector)
selector)) selector))
(cl (mk-js-array (if (symbol? styles) (cl (if (symbol? styles)
(list styles) (list styles)
styles))) styles))
;(cl (mk-js-array (if (symbol? styles)
; (list styles)
; styles)))
) )
(let ((r (webview-call-js wv (let ((r (webview-call-js wv
(with-selector sel (with-selector sel
(format (λ (id el)
(js-code (let ((cl (eval cl))
"function(id, el) {" (r (make-hash)))
" let cl = ~a;" (send cl forEach
" let r = {};" (λ (st)
" cl.forEach(function(st) {" (let ((stl (send window getComputedStyle el)))
" let stl = window.getComputedStyle(el);" (set! (js-ref r st) (js-ref stl st)))))
" r[st] = stl[st];" (make-hash (list
" });" (list 'id id)
" return { id: id, style: r };" (list 'style r))))))
"}") cl)) )
))) ))
; (format
; (js-code
; "function(id, el) {"
; " let cl = ~a;"
; " let r = {};"
; " cl.forEach(function(st) {"
; " let stl = window.getComputedStyle(el);"
; " r[st] = stl[st];"
; " });"
; " return { id: id, style: r };"
; "}") cl))
; )))
(if (eq? r #f) (if (eq? r #f)
#f #f
(let ((h (hash-ref r 'with-ids))) (let ((h (hash-ref r 'with-ids)))
(let ((l (map (λ (e) (cons (string->symbol (hash-ref e 'id)) (hash-ref e 'style))) h))) (let ((l (map (λ (e)
(cons
(string->symbol (hash-ref e 'id))
(hash-ref e 'style))) h)))
(if (symbol? selector) (if (symbol? selector)
(cdr (car l)) (cdr (car l))
l)))) l))))
@@ -976,25 +1071,35 @@
(let ((sel (if (symbol? selector) (let ((sel (if (symbol? selector)
(format "#~a" selector) (format "#~a" selector)
selector)) selector))
(cl (mk-js-array (if (symbol? style-entries) (cl (if (symbol? style-entries)
(list style-entries) (list style-entries)
style-entries))) style-entries))
) )
(webview-call-js wv (webview-call-js wv
(with-selector sel (with-selector sel
(format (λ (id el)
(js-code (let ((cl (eval cl)))
"function(id, el) {" (send cl forEach
" let cl = ~a;" (λ (st)
" cl.forEach(function(st) {" (set! (js-ref
" el.style[st] = '';" (js-dot el style)
" });" st) "")))
" return id;" id))))
"}") cl)
)
)
) )
) )
; (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) (define/contract (webview-set-attr! wv selector attr-entries)
(-> wv-win? (or/c symbol? string?) (-> wv-win? (or/c symbol? string?)
@@ -1013,29 +1118,44 @@
([rgba? v] (rgba->hex v)) ([rgba? v] (rgba->hex v))
(else (format "~a" v)))) (else (format "~a" v))))
)) ae*)) )) ae*))
(cl (mk-js-array ae**)) ;(cl (mk-js-array ae**))
(cl ae**)
) )
;(display cl)
(webview-call-js wv (webview-call-js wv
(with-selector sel (with-selector sel
(format (λ (id el)
(js-code (let ((cl (eval cl)))
"function(id, el) {" (send cl forEach
" let cl = ~a;" (λ (av)
" cl.forEach(function(av) {" (send el setAttribute (js-ref av 0)
" el.setAttribute(av[0], av[1]);" (js-ref av 1))))
" });" id))))
" return id;"
"}") cl))
)
) )
) )
; (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) (define/contract (webview-attr wv id attr)
(-> wv-win? symbol? (or/c symbol? string?) (or/c string? boolean?)) (-> wv-win? symbol? (or/c symbol? string?) (or/c string? boolean?))
(let ((v (webview-call-js wv (let ((v (webview-call-js wv
(with-id id el (with-id->el id el
-> (format "el.getAttribute('~a');" attr)) (return (send el getAttribute (eval attr)))))))
))) ;(with-id id el
; -> (format "el.getAttribute('~a');" attr))
;)))
(if (eq? v 'null) (if (eq? v 'null)
#f #f
v) v)