diff --git a/example/index.html b/example/index.html
index 688829c..f2b9088 100644
--- a/example/index.html
+++ b/example/index.html
@@ -17,7 +17,7 @@ Some input text:
Some input date:
-Some color input:
+Some color input:
diff --git a/example1/example-1.html b/example1/example-1.html
index 9b67683..bd07432 100644
--- a/example1/example-1.html
+++ b/example1/example-1.html
@@ -34,6 +34,7 @@
+
Menu responses
diff --git a/example1/example.rkt b/example1/example.rkt
index 0d8b11c..5d11a26 100644
--- a/example1/example.rkt
+++ b/example1/example.rkt
@@ -11,13 +11,17 @@
example-1-window%
)
+(define ww-debug displayln)
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Example 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-runtime-path html-start "example-1.html")
(define-runtime-path dialog-html "example-1-dialog.html")
+(define-runtime-path cur-dir ".")
+#|
(define test-menu (menu 'main-menu
(menu-item 'm-file "File"
#:submenu
@@ -46,33 +50,34 @@
)
)
))
+|#
(define example-1-dialog%
- (class ww-webview-dialog%
+ (class wv-dialog%
(inherit-field settings)
- (super-new [html-file dialog-html]
- [width 400]
- [height 300])
+ (super-new [window-context 'example-1-dialog]
+ [file-not-found-handler (root-file-not-found-handler "example-1-dialog.html")]
+ )
- (define/override (html-loaded)
- (super html-loaded)
+ (define/override (page-loaded oke)
+ (super page-loaded oke)
- (ww-debug "html-loaded for example-1-dialog%")
- (let* ((btn (send this element 'ok-btn)))
- (send btn connect 'click (λ (data)
- (send this close))))
+ ;(ww-debug "html-loaded for example-1-dialog%")
+ (send this bind! 'ok-btn 'click (λ (el evt data)
+ (send this close)))
- (let* ((inp1 (send this element 'inp1))
- (inp2 (send this element 'inp2))
- (inp3 (send this element 'inp3)))
+ (let* ((inp1 (send this element 'inp1 'text))
+ (inp2 (send this element 'inp2 'text))
+ (inp3 (send this element 'inp3 'text)))
(send inp1 set! (send settings get 'inp1 ""))
(send inp2 set! (send settings get 'inp2 ""))
(send inp3 set! (send settings get 'inp3 ""))
- (send inp1 on-change!
- (λ (val)
- (send settings set! 'inp1 val)))
- (send inp2 on-change! (λ (val) (send settings set! 'inp2 val)))
- (send inp3 on-change! (λ (val) (send settings set! 'inp3 val)))
+ (send this bind! 'inp1 'change (λ (el evt data)
+ (displayln (format "~a ~a ~a" el evt data))
+ (displayln (format "get = ~a" (send el get)))
+ (send settings set! 'inp1 (send el get))))
+ (send this bind! 'inp2 'change (λ (el evt data) (send settings set! 'inp2 (send el get))))
+ (send this bind! 'inp3 'change (λ (el evt data) (send settings set! 'inp3 (send el get))))
)
)
)
@@ -86,10 +91,11 @@
var))))
(define example-1-window%
- (class ww-webview%
+ (class wv-window%
- (inherit-field settings)
- (super-new [html-file html-start]
+ (inherit-field settings app-context)
+ (super-new [file-not-found-handler (root-file-not-found-handler "example-1.html")]
+ [window-context 'example-1-main]
)
(define go-on-counter #f)
@@ -97,14 +103,21 @@
(define counter-inc 1)
(define counter-thread #f)
(define div-counter #f)
- (define my-dir (send settings get 'folder "."))
+ (define my-dir (send settings get/global 'folder "."))
(define/override (can-close?)
(eq? counter-thread #f))
- (define/public (reset-counter)
+ (define start-stop-btn #f)
+
+ (define/public (stop-counter)
+ (send start-stop-btn set-innerHTML! "Start Counter")
(set! go-on-counter #f)
+ )
+
+ (define/public (reset-counter)
+ (stop-counter)
(set! counter-thread #f)
)
@@ -117,25 +130,26 @@
(send this update-counter))
(define/public (update-counter)
- (send div-counter set-inner-html! (format "Count = ~a" c-counter))
+ (send div-counter set-innerHTML! (format "Count = ~a" c-counter))
(when (and (> c-counter 0) (<= c-counter 100))
(send div-counter set-style!
- (css-style '((background white)))))
+ '((background white))))
(when (and (> c-counter 100) (<= c-counter 200))
(send div-counter set-style!
- (css-style '((background green) (color white)))))
+ '((background green) (color white))))
(when (and (> c-counter 200) (<= c-counter 300))
(send div-counter set-style!
- (css-style '((background yellow) (font-size: 120%)))))
+ '((background yellow) (color black) (font-size: 120%))))
(when (and (> c-counter 300) (<= c-counter 400))
(send div-counter set-style!
- (css-style '((color white) (background orange) (font-size 110%)))))
+ '((color white) (background orange) (font-size 110%))))
(when (and (> c-counter 400))
(send div-counter set-style!
- (css-style '((color white) (background red) (font-size 120%) (font-weight bold)))))
+ '((color white) (background red) (font-size 120%) (font-weight bold))))
)
(define/public (start-counter)
+ (send start-stop-btn set-innerHTML! "Stop Counter")
(set! counter-thread
(thread
(λ ()
@@ -150,65 +164,68 @@
(define/public (set-folder new-dir)
(set! my-dir new-dir)
- (send settings set 'folder new-dir)
+ (send settings set/global! 'folder new-dir)
(let ((el (send this element 'folder)))
- (send el set-inner-html! (format "Selected folder: ~a" my-dir))
+ (send el set-innerHTML! (format "Selected folder: ~a" my-dir))
)
)
(define/override (choose-dir)
- (let ((handle (super choose-dir "Select a folder" my-dir)))
- (displayln (format "choosen dir handle: ~a" handle))
+ (let ((result (super choose-dir "Select a folder" my-dir)))
+ (displayln (format "choosen dir handle: ~a" result))
+ (unless (eq? result 'canceled)
+ (send this set-folder result))
)
)
- (define/override (dir-choosen handle choosen dir)
- (displayln (format "dir-choosen: ~a ~a ~a" handle choosen dir))
- (when choosen
- (send this set-folder dir)))
-
(define/public (prefs)
- (new example-1-dialog% [parent this] [settings (send this clone-settings 'example-1-dialog)]))
+ (stop-counter)
+ (set! go-on-counter #f)
+ (new example-1-dialog%
+ [parent this]
+ )
+ ) ; (send this clone-settings 'example-1-dialog)]))
- (define/override (handle-navigate url type kind)
- (send this reset-counter)
- (super handle-navigate url type kind))
+ ;(define/override (handle-navigate url type kind)
+ ; (send this reset-counter)
+ ; (super handle-navigate url type kind))
- (define/override (html-loaded)
+ (define/override (page-loaded oke)
(ww-debug "HTML LOADED")
- (super html-loaded)
+ (super page-loaded oke)
(set! div-counter (send this element 'div-counter))
(send this update-counter)
(send this set-folder my-dir)
(ww-debug "CONNECTING BUTTONS")
- (let* ((dialog-btn (send this element 'dialog-button))
- (start-stop-btn (send this element 'start-stop-button))
- (choose-dir-btn (send this element 'select-dir-button))
- )
- (send dialog-btn connect 'click
- (λ (data) (send this prefs)))
-
- (send start-stop-btn connect 'click
- (λ (data)
- (if (eq? counter-thread #f)
- (begin
- (send this start-counter)
- (send start-stop-btn set-inner-html! "Stop Counter"))
- (begin
- (send this reset-counter)
- (send start-stop-btn set-inner-html! "Start Counter"))
+ (send this bind! 'dialog-button 'click (λ (el evt data)
+ (send this prefs)))
+
+ (set! start-stop-btn (send this element 'start-stop-button))
+ (send this bind! 'start-stop-button 'click
+ (λ (el evt data)
+ (if (eq? counter-thread #f)
+ (begin
+ (send this start-counter)
)
- )
+ (begin
+ (send this reset-counter)
+ )
+ )
)
- (send choose-dir-btn connect 'click
- (λ (data)
- (send this choose-dir)))
- )
+ )
+
+ (send this bind! 'devtools 'click
+ (λ (el evt data) (send this devtools)))
+
+ (send this bind! 'select-dir-button 'click
+ (λ (el evt data)
+ (send this choose-dir)))
- (ww-debug "SETTING MENU")
- (let* ((div-open (send this element 'div-open))
+
+ ;(ww-debug "SETTING MENU")
+ #|(let* ((div-open (send this element 'div-open))
(c-open 0)
(div-close (send this element 'div-close))
(c-close 0)
@@ -250,7 +267,7 @@
(λ () (send this choose-dir)))
)
- )
+ )|#
)
(begin
@@ -261,7 +278,9 @@
(define (run-example)
(let* ((ini (new ini% [file 'web-racket-example1]))
- (settings (new ww-simple-ini% [ini ini] [section 'example-1-window]))
- (window (new example-1-window% [settings settings]))
+ (window (new example-1-window%
+ [app-context 'example-1]
+ [ini ini]
+ [base-dir cur-dir]))
)
window))
diff --git a/private/lib/linux/x86_64/librktwebview_qt.so b/private/lib/linux/x86_64/librktwebview_qt.so
index 10af4ac..e0ff9e7 100755
Binary files a/private/lib/linux/x86_64/librktwebview_qt.so and b/private/lib/linux/x86_64/librktwebview_qt.so differ
diff --git a/private/mimetypes.rkt b/private/mimetypes.rkt
index f6e9aca..03f6214 100644
--- a/private/mimetypes.rkt
+++ b/private/mimetypes.rkt
@@ -722,4 +722,3 @@
(addMimeType "Zip Archive" "application/zip" '(zip) "Wikipedia: Zip")
(addMimeType "ZVUE Media Manager" "application/vnd.handheld-entertainment+xml" '(zmm) "IANA: ZVUE Media Manager")
(addMimeType "Zzazz Deck" "application/vnd.zzazz.deck+xml" '(zaz) "IANA: Zzazz")
-
diff --git a/private/racket-webview-qt.rkt b/private/racket-webview-qt.rkt
index 003e56b..ac7418d 100644
--- a/private/racket-webview-qt.rkt
+++ b/private/racket-webview-qt.rkt
@@ -39,6 +39,7 @@
rkt-webview-choose-dir
rkt-webview-file-open
rkt-webview-file-save
+ rkt-webview-version
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -48,6 +49,7 @@
(define lib-type 'release)
(define os (system-type 'os*))
+(define arch (system-type 'arch))
(define supported-os '(windows linux))
(unless (ormap (λ (o) (eq? os o)) supported-os)
@@ -77,7 +79,27 @@
Qt6WebEngineWidgets.dll
))
([eq? os 'linux]
- '())
+ '(libQt6XcbQpa
+ ;libQt6WaylandClient
+ ;libQt6EglFSDeviceIntegration
+ libQt6Core
+ libQt6Positioning
+ libQt6Gui
+ libQt6Widgets
+ libQt6Svg
+ libQt6Network
+ libQt6OpenGL
+ libQt6PrintSupport
+ libQt6Qml
+ libQt6QmlModels
+ libQt6QmlWorkerScript
+ libQt6QmlMeta
+ libQt6Quick
+ libQt6QuickWidgets
+ libQt6WebChannel
+ libQt6WebEngineCore
+ libQt6WebEngineWidgets
+ ))
)
)
@@ -88,26 +110,51 @@
)
)
+(define os-lib-dir (build-path lib-dir (symbol->string os) (symbol->string arch)))
+
(define (libname lib-symbol)
- (build-path lib-dir (symbol->string os) (symbol->string lib-symbol)))
+ (build-path os-lib-dir (symbol->string lib-symbol)))
; c:\qt\6.10.2\msvc2022_64\bin\windeployqt.exe rktwebview_qt_test.exe
-(when (eq? os 'windows)
- (putenv "QT_PLUGIN_PATH"
- (path->string (build-path lib-dir (symbol->string os))))
- (putenv "QTWEBENGINEPROCESS_PATH"
- (path->string (build-path lib-dir (symbol->string os) "QtWebEngineProcess.exe")))
- (putenv "QTWEBENGINE_RESOURCES_PATH"
- (path->string (build-path lib-dir (symbol->string os) "resources")))
- (putenv "QTWEBENGINE_LOCALES_PATH"
- (path->string (build-path lib-dir (symbol->string os) "translations" "qtwebengine_locales")))
- )
+(define quiet-call #t)
+(set! quiet-call
+ (when (or (eq? os 'windows) (eq? os 'linux))
+ (putenv "QT_PLUGIN_PATH"
+ (path->string (build-path os-lib-dir)))
+ (putenv "QTWEBENGINEPROCESS_PATH"
+ (path->string (build-path os-lib-dir "QtWebEngineProcess.exe")))
+ (putenv "QTWEBENGINE_RESOURCES_PATH"
+ (path->string (build-path os-lib-dir "resources")))
+ (putenv "QTWEBENGINE_LOCALES_PATH"
+ (path->string (build-path os-lib-dir "translations" "qtwebengine_locales")))
+ (when (eq? os 'linux)
+ (putenv "QT_QPA_PLATFORM" "xcb")
+ (putenv "LD_LIBRARY_PATH"
+ (string-append
+ (path->string (build-path os-lib-dir)) ":"
+ (path->string (build-path os-lib-dir "platforms"))
+ )
+ )
+ )
+ )
+ )
+
;;; Preload libraries
(for-each (λ (lib-symbol)
- (let ((load-lib (libname lib-symbol)))
- (ffi-lib load-lib)))
+ (let* ((libn (if (list? lib-symbol) (car lib-symbol) lib-symbol))
+ (versions (if (list? lib-symbol) (cons (cadr lib-symbol) '(#f)) (list #f)))
+ (load-lib (if (list? lib-symbol)
+ (if (eq? (caddr lib-symbol) #f)
+ (symbol->string libn)
+ (libname libn))
+ (libname libn)))
+ )
+ ;(displayln (format "loading ~a" load-lib))
+ (ffi-lib load-lib versions)
+ )
+ )
libraries-to-preload)
;;; Actual FFI integration
@@ -130,7 +177,7 @@
ffi-library os exp))))
)
])
- (ffi-lib webview-lib-file)))
+ (ffi-lib webview-lib-file '("6" #f) #:get-lib-dirs (list os-lib-dir))))
(define-ffi-definer define-rktwebview webview-lib)
@@ -170,6 +217,24 @@
)
)
+(define _rkt_data_kind
+ (_enum '(version = -1
+ event = 2
+ js-result = 3
+ )
+ )
+ )
+
+(define-cstruct _rkt_version_t
+ ([qt-major _int]
+ [qt-minor _int]
+ [qt-patch _int]
+ [api-major _int]
+ [api-minor _int]
+ [api-patch _int]
+ )
+ )
+
(define-cstruct _rkt_evt_t
([w _int]
[evt _pointer]
@@ -180,6 +245,13 @@
[value _pointer]
))
+(define-cstruct _rkt_data_t
+ ([kind _rkt_data_kind]
+ [data (_union _rkt_version_t _rkt_evt_t _rkt_js_result_t)]
+ )
+ )
+
+
;RKTWEBVIEW_QT_EXPORT void rkt_webview_init(int &argc, char **argv);
(define-rktwebview rkt_webview_init
(_fun -> _void))
@@ -188,10 +260,23 @@
(define-rktwebview rkt_webview_process_events
(_fun _int -> _void))
-;RKTWEBVIEW_QT_EXPORT int rkt_webview_create(int parent);
+;RKTWEBVIEW_QT_EXPORT void rkt_webview_free_data(rkt_data_t *d);
+(define-rktwebview rkt_webview_free_data
+ (_fun _rkt_data_t-pointer -> _void))
+
+;RKTWEBVIEW_QT_EXPORT rkt_data_t *rkt_webview_version();
+(define-rktwebview rkt_webview_version
+ (_fun -> _rkt_data_t-pointer))
+
+;RKTWEBVIEW_QT_EXPORT int rkt_webview_create(rktwebview_t parent,
+; event_cb_t js_event_cb,
+; const char *optional_server_cert_pem);
(define-rktwebview rkt_webview_create
- (_fun _int (_fun #:keep callback-box #:async-apply applier
- _rkt_evt_t-pointer -> _void) -> _int))
+ (_fun _int
+ (_fun #:keep callback-box #:async-apply applier
+ _rkt_data_t-pointer -> _void)
+ _bytes
+ -> _int))
;RKTWEBVIEW_QT_EXPORT void rkt_webview_close(int wv);
(define-rktwebview rkt_webview_close
@@ -215,20 +300,12 @@
;RKTWEBVIEW_QT_EXPORT rkt_js_result_t *rkt_webview_call_js(rktwebview_t wv, const char *js);
(define-rktwebview rkt_webview_call_js
- (_fun _int _string/utf-8 -> _rkt_js_result_t-pointer))
+ (_fun _int _string/utf-8 -> _rkt_data_t-pointer))
-;RKTWEBVIEW_QT_EXPORT result_t rkt_webview_destroy_js_result(rkt_js_result_t *r);
-(define-rktwebview rkt_webview_destroy_js_result
- (_fun _rkt_js_result_t-pointer -> _rkt_result_t))
-
;RKTWEBVIEW_QT_EXPORT result_t rkt_webview_open_devtools(int wv);
(define-rktwebview rkt_webview_open_devtools
(_fun _int -> _rkt_result_t))
-;RKTWEBVIEW_QT_EXPORT result_t rkt_webview_destroy_event(rkt_event_t e);
-(define-rktwebview rkt_webview_destroy_event
- (_fun _rkt_evt_t-pointer -> _rkt_result_t))
-
;RKTWEBVIEW_QT_EXPORT result_t rkt_webview_move(rktwebview_t w, int x, int y);
(define-rktwebview rkt_webview_move
(_fun _int _int _int -> _rkt_result_t))
@@ -275,15 +352,15 @@
;RKTWEBVIEW_QT_EXPORT rkt_js_result_t *rkt_webview_choose_dir(rktwebview_t w, const char *title, const char *base_dir);
(define-rktwebview rkt_webview_choose_dir
- (_fun _int _string/utf-8 _string/utf-8 -> _rkt_js_result_t-pointer))
+ (_fun _int _string/utf-8 _string/utf-8 -> _rkt_data_t-pointer))
;RKTWEBVIEW_QT_EXPORT rkt_js_result_t *rkt_webview_file_open(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts);
(define-rktwebview rkt_webview_file_open
- (_fun _int _string/utf-8 _string/utf-8 _string/utf-8 -> _rkt_js_result_t-pointer))
+ (_fun _int _string/utf-8 _string/utf-8 _string/utf-8 -> _rkt_data_t-pointer))
;RKTWEBVIEW_QT_EXPORT rkt_js_result_t *rkt_webview_file_save(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts);
(define-rktwebview rkt_webview_file_save
- (_fun _int _string/utf-8 _string/utf-8 _string/utf-8 -> _rkt_js_result_t-pointer))
+ (_fun _int _string/utf-8 _string/utf-8 _string/utf-8 -> _rkt_data_t-pointer))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -308,7 +385,7 @@
(f)))))
(rkt_webview_init)
-(start-event-processing)
+(set! quiet-call (start-event-processing))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Provided features
@@ -323,27 +400,29 @@
(define (rkt-process-events handle)
(if (> (queue-length (rkt-wv-evt-queue handle)) 0)
- (let ((e (dequeue! (rkt-wv-evt-queue handle))))
- (if (symbol? e)
- (if (eq? e 'quit)
+ (let ((data (dequeue! (rkt-wv-evt-queue handle))))
+ (if (symbol? data)
+ (if (eq? data 'quit)
(begin
(hash-remove! rkt-wv-store (rkt-wv-win handle))
'quit)
(rkt-process-events handle))
- (let ((evt (cast (rkt_evt_t-evt e) _pointer _string*/utf-8)))
+ (let* ((e (union-ref (rkt_data_t-data data) 1))
+ (evt (cast (rkt_evt_t-evt e) _pointer _string*/utf-8)))
((rkt-wv-callback handle) handle evt)
- (rkt_webview_destroy_event e)
+ (rkt_webview_free_data data)
(rkt-process-events handle)))
)
'done))
-(define (rkt-webview-create parent evt-callback close-callback)
+(define (rkt-webview-create parent evt-callback close-callback server-cert)
(let* ((evt-queue (make-queue))
(parent-win (if (eq? parent #f) 0 (rkt-wv-win parent)))
)
(let ((wv (rkt_webview_create parent-win
(λ (rkt-evt)
- (enqueue! evt-queue rkt-evt)))))
+ (enqueue! evt-queue rkt-evt))
+ server-cert)))
(let ((handle (make-rkt-wv wv evt-queue evt-callback #t close-callback)))
(thread (λ ()
(sleep 1)
@@ -385,10 +464,11 @@
(rkt_webview_run_js (rkt-wv-win wv) js))
(define (rkt-webview-call-js wv js)
- (let* ((r (rkt_webview_call_js (rkt-wv-win wv) js))
+ (let* ((d (rkt_webview_call_js (rkt-wv-win wv) js))
+ (r (union-ref (rkt_data_t-data d) 2))
(value (cast (rkt_js_result_t-value r) _pointer _string*/utf-8))
(result (rkt_js_result_t-result r)))
- (rkt_webview_destroy_js_result r)
+ (rkt_webview_free_data d)
(list result value)))
(define (rkt-webview-resize wv w h)
@@ -415,26 +495,47 @@
(rkt_webview_open_devtools (rkt-wv-win wv)))
(define (rkt-webview-choose-dir wv title base-dir)
- (let* ((r (rkt_webview_choose_dir (rkt-wv-win wv) title base-dir))
+ (let* ((d (rkt_webview_choose_dir (rkt-wv-win wv) title base-dir))
+ (r (union-ref (rkt_data_t-data d) 2))
(value (cast (rkt_js_result_t-value r) _pointer _string*/utf-8))
(result (rkt_js_result_t-result r)))
- (rkt_webview_destroy_js_result r)
+ (rkt_webview_free_data d)
(list result value)))
(define (rkt-webview-file-open wv title base-dir permitted-exts)
- (let* ((r (rkt_webview_file_open (rkt-wv-win wv) title base-dir permitted-exts))
+ (let* ((d (rkt_webview_file_open (rkt-wv-win wv) title base-dir permitted-exts))
+ (r (union-ref (rkt_data_t-data d) 2))
(value (cast (rkt_js_result_t-value r) _pointer _string*/utf-8))
(result (rkt_js_result_t-result r)))
- (rkt_webview_destroy_js_result r)
+ (rkt_webview_free_data d)
(list result value)))
(define (rkt-webview-file-save wv title base-dir permitted-exts)
- (let* ((r (rkt_webview_file_save (rkt-wv-win wv) title base-dir permitted-exts))
+ (let* ((d (rkt_webview_file_save (rkt-wv-win wv) title base-dir permitted-exts))
+ (r (union-ref (rkt_data_t-data d) 2))
(value (cast (rkt_js_result_t-value r) _pointer _string*/utf-8))
(result (rkt_js_result_t-result r)))
- (rkt_webview_destroy_js_result r)
+ (rkt_webview_free_data d)
(list result value)))
+(define (rkt-webview-version)
+ (let ((d (rkt_webview_version)))
+ (let ((v (union-ref (rkt_data_t-data d) 0)))
+ (let ((qt-major (rkt_version_t-qt-major v))
+ (qt-minor (rkt_version_t-qt-minor v))
+ (qt-patch (rkt_version_t-qt-patch v))
+ (api-major (rkt_version_t-api-major v))
+ (api-minor (rkt_version_t-api-minor v))
+ (api-patch (rkt_version_t-api-patch v))
+ )
+ (rkt_webview_free_data d)
+ (list (list 'webview-c-api api-major api-minor api-patch)
+ (list 'qt qt-major qt-minor qt-patch))
+ )
+ )
+ )
+ )
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Administration
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -459,9 +560,10 @@
;; Cleanup on exit
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(plumber-add-flush! (current-plumber)
- (λ (handle)
- (rkt-webview-exit)))
+(set! quiet-call
+ (plumber-add-flush! (current-plumber)
+ (λ (handle)
+ (rkt-webview-exit))))
diff --git a/private/racket-webview.rkt b/private/racket-webview.rkt
index 4100fcf..d9b35e6 100644
--- a/private/racket-webview.rkt
+++ b/private/racket-webview.rkt
@@ -1,6 +1,7 @@
#lang racket/base
(require "racket-webview-qt.rkt"
+ "racket-webview-version.rkt"
"utils.rkt"
"mimetypes.rkt"
"rgba.rkt"
@@ -99,6 +100,11 @@
webview-standard-file-getter
+ webview-version
+
+ wv-base-url
+ wv-window-nr
+
test
)
@@ -393,12 +399,13 @@
(cert (generate-self-signed-cert 2048 365 '("127.0.0.1" "localhost")
"NL" "Dijkema"
#:ou (wv-cert-ou-token h)))
+ (server-cert (certificate cert))
(event-processor (λ (wv evt)
(event-callback h (util-parse-event evt))))
(close-callback (λ ()
(remove-cert-files h)))
(ph (if (wv? p) (wv-handle p) #f))
- (wv (let ((internal-handle (rkt-webview-create ph event-processor close-callback)))
+ (wv (let ((internal-handle (rkt-webview-create ph event-processor close-callback server-cert)))
(set-wv-handle! h internal-handle)
(set-wv-window-nr! h (rkt-wv-win internal-handle))
internal-handle))
@@ -870,7 +877,11 @@
(wva webview-attr/date g:date? string->date)
(wva webview-attr/time g:time? string->time)
(wva webview-attr/datetime g:datetime string->datetime)
-(wvv webview-attr/boolean boolean? (λ (e) (if (string=? e "true") #t #f)))
+(wva webview-attr/boolean boolean? (λ (e) (if (string=? e "true") #t #f)))
+
+(define (webview-version)
+ (cons (list 'webview webview-major webview-minor webview-patch)
+ (rkt-webview-version)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; testing
diff --git a/rktwebview_qt/command.h b/rktwebview_qt/command.h
index fea5d76..ca484de 100644
--- a/rktwebview_qt/command.h
+++ b/rktwebview_qt/command.h
@@ -26,6 +26,7 @@
#define COMMAND_FILE_OPEN 20
#define COMMAND_FILE_SAVE 21
#define COMMAND_SET_OU_TOKEN 22
+#define COMMAND_SET_CERTIFICATE 23
class Command
{
diff --git a/rktwebview_qt/main.cpp b/rktwebview_qt/main.cpp
index 604e3d8..66a0e89 100644
--- a/rktwebview_qt/main.cpp
+++ b/rktwebview_qt/main.cpp
@@ -1,14 +1,15 @@
#include "rktwebview.h"
#include
+#include
static int _argc;
static char **_argv;
-void eventCb(rkt_event_t *e)
+void eventCb(rkt_data_t *e)
{
- printf("event: %s\n", e->event);
- rkt_webview_destroy_event(e);
+ printf("event: %s\n", e->data.event.event);
+ rkt_webview_free_data(e);
}
int main(int argc, char *argv[])
@@ -20,7 +21,9 @@ int main(int argc, char *argv[])
_argv = argv;
rkt_webview_init();
- wv1 = rkt_webview_create(0, eventCb);
+
+ wv1 = rkt_webview_create(0, eventCb, nullptr);
+
rkt_webview_move(wv1, 200, 300);
rkt_webview_resize(wv1, 800, 600);
rkt_webview_set_url(wv1, "https://wikipedia.org"); //"http://127.0.0.1:8083");
@@ -35,23 +38,26 @@ int main(int argc, char *argv[])
}
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);
+ rkt_data_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->data.js_result.result, r->data.js_result.value);
+ rkt_webview_free_data(r);
}
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);
+ rkt_data_t *r = rkt_webview_call_js(wv1, "let el = document.getElementById('hi');el.value = '10';");
+ printf("rkt_js_result: %d: %s\n", r->data.js_result.result, r->data.js_result.value);
+ rkt_webview_free_data(r);
}
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);
+ rkt_data_t *r = rkt_webview_call_js(wv1, "document.body.innerHTML = 'Hi!
'; return document.body.innerHTML;");
+ printf("rkt_js_result: %d: %s\n", r->data.js_result.result, r->data.js_result.value);
+ rkt_webview_free_data(r);
}
if (i == 10) {
- wv2 = rkt_webview_create(wv1, eventCb);
+ wv2 = rkt_webview_create(wv1, eventCb, nullptr);
rkt_webview_move(wv2, 400, 200);
rkt_webview_resize(wv2, 800, 600);
rkt_webview_set_url(wv2, "https://127.0.0.1");
diff --git a/rktwebview_qt/rktwebview.cpp b/rktwebview_qt/rktwebview.cpp
index 43366d4..d8a4cc6 100644
--- a/rktwebview_qt/rktwebview.cpp
+++ b/rktwebview_qt/rktwebview.cpp
@@ -32,10 +32,10 @@ void rkt_webview_init()
}
}
-int rkt_webview_create(rktwebview_t parent, event_cb_t js_event_cb)
+int rkt_webview_create(rktwebview_t parent, event_cb_t js_event_cb, const char *optional_server_cert_pem)
{
rkt_webview_init();
- return handler->rktWebViewCreate(parent, js_event_cb);
+ return handler->rktWebViewCreate(parent, js_event_cb, optional_server_cert_pem);
}
void rkt_webview_close(rktwebview_t wv)
@@ -66,10 +66,10 @@ 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_data_t *rkt_webview_call_js(rktwebview_t wv, const char *js)
{
rkt_webview_init();
- rkt_js_result_t *r = handler->rktCallJs(wv, js);
+ rkt_data_t *r = handler->rktCallJs(wv, js);
return r;
}
@@ -95,22 +95,6 @@ void rkt_webview_process_events(int for_ms)
}
}
-
-result_t rkt_webview_destroy_event(rkt_event_t *e)
-{
- free(e->event);
- free(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();
@@ -184,19 +168,19 @@ result_t rkt_webview_set_title(rktwebview_t wv, const char *title)
return handler->rktWindowSetTitle(wv, title);
}
-rkt_js_result_t *rkt_webview_choose_dir(rktwebview_t w, const char *title, const char *base_dir)
+rkt_data_t *rkt_webview_choose_dir(rktwebview_t w, const char *title, const char *base_dir)
{
rkt_webview_init();
return handler->rktChooseDir(w, title, base_dir);
}
-rkt_js_result_t *rkt_webview_file_open(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts)
+rkt_data_t *rkt_webview_file_open(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts)
{
rkt_webview_init();
return handler->rktFileOpen(w, title, base_dir, permitted_exts);
}
-rkt_js_result_t *rkt_webview_file_save(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts)
+rkt_data_t *rkt_webview_file_save(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts)
{
rkt_webview_init();
return handler->rktFileSave(w, title, base_dir, permitted_exts);
@@ -207,3 +191,31 @@ void rkt_webview_set_ou_token(rktwebview_t wv, const char *token)
rkt_webview_init();
handler->rktSetOUToken(wv, token);
}
+
+void rkt_webview_free_data(rkt_data_t *d)
+{
+ if (d->kind == version) {
+ free(d);
+ } else if (d->kind == event) {
+ free(d->data.event.event);
+ free(d);
+ } else if (d->kind == js_result) {
+ free(d->data.js_result.value);
+ free(d);
+ } else {
+ fprintf(stderr, "UNEXPECTED: data kind %d cannot be freed\n", d->kind);
+ }
+}
+
+rkt_data_t *rkt_webview_version()
+{
+ rkt_data_t *d = static_cast(malloc(sizeof(rkt_data_t)));
+ d->kind = version;
+ d->data.version.api_major = RKT_WEBVIEW_API_MAJOR;
+ d->data.version.api_minor = RKT_WEBVIEW_API_MINOR;
+ d->data.version.api_patch = RKT_WEBVIEW_API_PATCH;
+ d->data.version.qt_major = QT_VERSION_MAJOR;
+ d->data.version.qt_minor = QT_VERSION_MINOR;
+ d->data.version.qt_patch = QT_VERSION_PATCH;
+ return d;
+}
diff --git a/rktwebview_qt/rktwebview.h b/rktwebview_qt/rktwebview.h
index bf06380..6c19a44 100644
--- a/rktwebview_qt/rktwebview.h
+++ b/rktwebview_qt/rktwebview.h
@@ -3,6 +3,10 @@
#include "rktwebview_qt_global.h"
+#define RKT_WEBVIEW_API_MAJOR 0
+#define RKT_WEBVIEW_API_MINOR 1
+#define RKT_WEBVIEW_API_PATCH 1
+
extern "C" {
typedef int rktwebview_t;
@@ -12,8 +16,6 @@ typedef struct {
char *event;
} rkt_event_t;
-typedef void (*event_cb_t)(rkt_event_t *);
-
typedef enum {
no_result_yet = -1,
oke = 0,
@@ -51,27 +53,53 @@ typedef enum {
maximized_active = 18
} window_state_t;
+typedef struct {
+ int qt_major;
+ int qt_minor;
+ int qt_patch;
+ int api_major;
+ int api_minor;
+ int api_patch;
+} rkt_version_t;
+
+typedef enum {
+ version = 1,
+ event = 2,
+ js_result = 3
+} rkt_data_kind_t;
+
+typedef struct {
+ rkt_data_kind_t kind;
+ union {
+ rkt_version_t version;
+ rkt_event_t event;
+ rkt_js_result_t js_result;
+ } data;
+} rkt_data_t;
+
+typedef void (*event_cb_t)(rkt_data_t *);
+
RKTWEBVIEW_QT_EXPORT void rkt_webview_init();
RKTWEBVIEW_QT_EXPORT void rkt_webview_process_events(int for_ms);
-RKTWEBVIEW_QT_EXPORT int rkt_webview_create(rktwebview_t parent, event_cb_t js_event_cb);
+RKTWEBVIEW_QT_EXPORT void rkt_webview_free_data(rkt_data_t *d);
+
+RKTWEBVIEW_QT_EXPORT rkt_data_t *rkt_webview_version();
+
+RKTWEBVIEW_QT_EXPORT int rkt_webview_create(rktwebview_t parent, event_cb_t js_event_cb, const char *optional_server_cert_pem);
RKTWEBVIEW_QT_EXPORT void rkt_webview_close(rktwebview_t wv);
RKTWEBVIEW_QT_EXPORT bool rkt_webview_valid(rktwebview_t wv);
RKTWEBVIEW_QT_EXPORT result_t rkt_webview_set_title(rktwebview_t wv, const char *title);
RKTWEBVIEW_QT_EXPORT void rkt_webview_set_ou_token(rktwebview_t wv, const char *token);
-
RKTWEBVIEW_QT_EXPORT result_t rkt_webview_set_url(rktwebview_t wv, const char *url);
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 rkt_data_t *rkt_webview_call_js(rktwebview_t wv, const char *js);
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);
-
RKTWEBVIEW_QT_EXPORT result_t rkt_webview_move(rktwebview_t w, int x, int y);
RKTWEBVIEW_QT_EXPORT result_t rkt_webview_resize(rktwebview_t w, int width, int height);
RKTWEBVIEW_QT_EXPORT result_t rkt_webview_hide(rktwebview_t w);
@@ -82,9 +110,9 @@ RKTWEBVIEW_QT_EXPORT result_t rkt_webview_maximize(rktwebview_t w);
RKTWEBVIEW_QT_EXPORT result_t rkt_webview_minimize(rktwebview_t w);
RKTWEBVIEW_QT_EXPORT window_state_t rkt_webview_window_state(rktwebview_t w);
-RKTWEBVIEW_QT_EXPORT rkt_js_result_t *rkt_webview_choose_dir(rktwebview_t w, const char *title, const char *base_dir);
-RKTWEBVIEW_QT_EXPORT rkt_js_result_t *rkt_webview_file_open(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts);
-RKTWEBVIEW_QT_EXPORT rkt_js_result_t *rkt_webview_file_save(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts);
+RKTWEBVIEW_QT_EXPORT rkt_data_t *rkt_webview_choose_dir(rktwebview_t w, const char *title, const char *base_dir);
+RKTWEBVIEW_QT_EXPORT rkt_data_t *rkt_webview_file_open(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts);
+RKTWEBVIEW_QT_EXPORT rkt_data_t *rkt_webview_file_save(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts);
}
diff --git a/rktwebview_qt/rktwebview_qt.cpp b/rktwebview_qt/rktwebview_qt.cpp
index f4fa58c..0dc6ded 100644
--- a/rktwebview_qt/rktwebview_qt.cpp
+++ b/rktwebview_qt/rktwebview_qt.cpp
@@ -12,6 +12,14 @@
#include "command.h"
#include
+static inline char *copyString(const char *s)
+{
+ int l = strlen(s);
+ char *cpy = static_cast(malloc(l + 1));
+ memcpy(cpy, s, l + 1);
+ return cpy;
+}
+
void Rktwebview_qt::processCommand(Command *cmd)
{
switch(cmd->cmd) {
@@ -26,6 +34,9 @@ void Rktwebview_qt::processCommand(Command *cmd)
void *f = cmd->args[1].value();
event_cb_t js_event_cb = reinterpret_cast (f);
+ bool has_scp = cmd->args[2].toBool();
+ QByteArray scp_pem = cmd->args[3].toByteArray();
+
WebviewWindow *p;
if (_views.contains(parent)) {
p = _views[parent];
@@ -33,7 +44,7 @@ void Rktwebview_qt::processCommand(Command *cmd)
p = nullptr;
}
- WebviewWindow *w = new WebviewWindow(p);
+ WebviewWindow *w = new WebviewWindow(p, has_scp, scp_pem);
WebViewQt *view = new WebViewQt(nextHandle(), w);
w->addView(view, this);
@@ -359,13 +370,17 @@ int Rktwebview_qt::nextHandle()
return h;
}
-int Rktwebview_qt::rktWebViewCreate(int parent, event_cb_t js_evt_cb)
+int Rktwebview_qt::rktWebViewCreate(int parent, event_cb_t js_evt_cb, const char *optional_server_cert_pem)
{
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);
+ bool has_scp = (optional_server_cert_pem != nullptr);
+ c.args.push_back(has_scp);
+ QByteArray scp = (optional_server_cert_pem == nullptr) ? QByteArray("") : QByteArray(optional_server_cert_pem);
+ c.args.push_back(scp);
postCommand(&c);
@@ -427,7 +442,7 @@ result_t Rktwebview_qt::rktSetHtml(rktwebview_t wv, const char *html)
return r ? result_t::oke : result_t::set_html_failed;
}
-rkt_js_result_t *Rktwebview_qt::rktCallJs(rktwebview_t wv, const char *js)
+rkt_data_t *Rktwebview_qt::rktCallJs(rktwebview_t wv, const char *js)
{
Command c(COMMAND_CALL_JS);
QString _js(js);
@@ -436,9 +451,10 @@ rkt_js_result_t *Rktwebview_qt::rktCallJs(rktwebview_t wv, const char *js)
postCommand(&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());
+ rkt_data_t *r = static_cast(malloc(sizeof(rkt_data_t)));
+ r->kind = js_result;
+ r->data.js_result.result = c.js_result_ok ? result_t::oke : result_t::eval_js_failed;
+ r->data.js_result.value = copyString(c.result.toString().toUtf8());
return r;
}
@@ -520,7 +536,7 @@ window_state_t Rktwebview_qt::rktWindowState(rktwebview_t w)
return ws;
}
-rkt_js_result_t *Rktwebview_qt::rktChooseDir(rktwebview_t w, const char *title, const char *base_dir)
+rkt_data_t *Rktwebview_qt::rktChooseDir(rktwebview_t w, const char *title, const char *base_dir)
{
Command c(COMMAND_CHOOSE_DIR);
c.args.push_back(w);
@@ -537,15 +553,15 @@ rkt_js_result_t *Rktwebview_qt::rktChooseDir(rktwebview_t w, const char *title,
bool oke = c.js_result_ok;
- rkt_js_result_t *r = static_cast(malloc(sizeof(rkt_js_result_t)));
- r->result = c.js_result_ok ? result_t::oke : result_t::choose_dir_failed;
-
- r->value = strdup(c.result.toString().toUtf8());
+ rkt_data_t *r = static_cast(malloc(sizeof(rkt_js_result_t)));
+ r->kind = js_result;
+ r->data.js_result.result = c.js_result_ok ? result_t::oke : result_t::choose_dir_failed;
+ r->data.js_result.value = copyString(c.result.toString().toUtf8());
return r;
}
-rkt_js_result_t *Rktwebview_qt::rktFileOpen(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts)
+rkt_data_t *Rktwebview_qt::rktFileOpen(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts)
{
Command c(COMMAND_FILE_OPEN);
c.args.push_back(w);
@@ -565,15 +581,15 @@ rkt_js_result_t *Rktwebview_qt::rktFileOpen(rktwebview_t w, const char *title, c
bool oke = c.js_result_ok;
- rkt_js_result_t *r = static_cast(malloc(sizeof(rkt_js_result_t)));
- r->result = c.js_result_ok ? result_t::oke : result_t::choose_dir_failed;
-
- r->value = strdup(c.result.toString().toUtf8());
+ rkt_data_t *r = static_cast(malloc(sizeof(rkt_data_t)));
+ r->kind = js_result;
+ r->data.js_result.result = c.js_result_ok ? result_t::oke : result_t::choose_dir_failed;
+ r->data.js_result.value = copyString(c.result.toString().toUtf8());
return r;
}
-rkt_js_result_t *Rktwebview_qt::rktFileSave(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts)
+rkt_data_t *Rktwebview_qt::rktFileSave(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts)
{
Command c(COMMAND_FILE_SAVE);
c.args.push_back(w);
@@ -593,10 +609,10 @@ rkt_js_result_t *Rktwebview_qt::rktFileSave(rktwebview_t w, const char *title, c
bool oke = c.js_result_ok;
- rkt_js_result_t *r = static_cast(malloc(sizeof(rkt_js_result_t)));
- r->result = c.js_result_ok ? result_t::oke : result_t::choose_dir_failed;
-
- r->value = strdup(c.result.toString().toUtf8());
+ rkt_data_t *r = static_cast(malloc(sizeof(rkt_data_t)));
+ r->kind = js_result;
+ r->data.js_result.result = c.js_result_ok ? result_t::oke : result_t::choose_dir_failed;
+ r->data.js_result.value = copyString(c.result.toString().toUtf8());
return r;
}
@@ -672,11 +688,12 @@ 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);
+ char *evt = copyString(msg.toUtf8().constData());
+ rkt_data_t *d = static_cast(malloc(sizeof(rkt_data_t)));
+ d->kind = rkt_data_kind_t::event;
+ d->data.event.wv = wv;
+ d->data.event.event = evt;
+ js_event_cb(d);
}
}
@@ -726,21 +743,29 @@ void Rktwebview_qt::customEvent(QEvent *event)
void Rktwebview_qt::doEvents()
{
- //_app->processEvents();
- if (_evt_loop_depth == 0) {
+ //QTime ct = QTime::currentTime();
+ //QTime expire = QTime::currentTime().addMSecs(2);
+ //while(QTime::currentTime() <= expire) {
+ _app->processEvents();
+ //}
+
+ // Qt 6.10 --> this leads to a core dump
+ // together with the stopEventloop stuff.
+ // Qt 6.4 seem stable.
+ /*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;
+ //_app->exit(0);
+ //_evt_loop_depth -= 1;
}
@@ -760,15 +785,18 @@ Rktwebview_qt::Rktwebview_qt(Rktwebview_qt **handler) :
connect(&_process_events, &QTimer::timeout, this, &Rktwebview_qt::processJsEventQueues);
_process_events.start(5);
- connect(&_evt_loop_timer, &QTimer::timeout, this, &Rktwebview_qt::stopEventloop);
+ // See Qt 6.10 remark at doEvents.
+ //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);
- // }
- // );
+ // Because we are using processEvents only (Qt 6.10), we need this dispatcher to
+ // handle deferred Deletes.
+ 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 abf088d..dcb7f72 100644
--- a/rktwebview_qt/rktwebview_qt.h
+++ b/rktwebview_qt/rktwebview_qt.h
@@ -64,7 +64,7 @@ public:
public:
int nextHandle();
public:
- int rktWebViewCreate(int parent, event_cb_t js_evt_cb);
+ int rktWebViewCreate(int parent, event_cb_t js_evt_cb, const char *optional_server_cert_pem);
void rktWebViewClose(int wv);
void rktSetOUToken(rktwebview_t wv, const char *ou_token);
void rktQuit();
@@ -73,7 +73,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);
+ rkt_data_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);
@@ -85,9 +85,9 @@ public:
result_t rktShowNormalWindow(rktwebview_t w);
window_state_t rktWindowState(rktwebview_t w);
- rkt_js_result_t *rktChooseDir(rktwebview_t w, const char *title, const char *base_dir);
- rkt_js_result_t * rktFileOpen(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts);
- rkt_js_result_t * rktFileSave(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts);
+ rkt_data_t *rktChooseDir(rktwebview_t w, const char *title, const char *base_dir);
+ rkt_data_t *rktFileOpen(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts);
+ rkt_data_t *rktFileSave(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts);
result_t rktWindowSetTitle(rktwebview_t wv, const char *title);
@@ -110,7 +110,7 @@ public:
public:
Rktwebview_qt(Rktwebview_qt **handler);
- };
+};
diff --git a/rktwebview_qt/webviewqt.cpp b/rktwebview_qt/webviewqt.cpp
index 9526b5e..0d575ea 100644
--- a/rktwebview_qt/webviewqt.cpp
+++ b/rktwebview_qt/webviewqt.cpp
@@ -4,7 +4,7 @@
#include
WebViewQt::WebViewQt(int id, WebviewWindow *window)
- : QWebEngineView(window)
+ : QWebEngineView(window->profile(), window)
{
_id = id;
_window = window;
diff --git a/rktwebview_qt/webviewwindow.cpp b/rktwebview_qt/webviewwindow.cpp
index 47c2870..8bcd6ea 100644
--- a/rktwebview_qt/webviewwindow.cpp
+++ b/rktwebview_qt/webviewwindow.cpp
@@ -10,13 +10,37 @@
#include
#include
#include
+#include
+#include
+#include
#include
#include
+#include
-WebviewWindow::WebviewWindow(WebviewWindow *parent)
+/*
+static void displ(QSslCertificate & cert, QSslCertificate::SubjectInfo &a) {
+ QStringList issuerInfo = cert.issuerInfo(a);
+ int i, N;
+ printf("%d\n", a);
+ for(i = 0, N = issuerInfo.size(); i < N; i++) {
+ printf("%d[%d]: %s\n", a, i, issuerInfo[i].toUtf8().constData());
+ }
+};
+
+static void displ1(QSslCertificate &cert, QList l) {
+ int i, N;
+ for(i = 0, N = l.size(); i < N; i++) {
+ displ(cert, l[i]);
+ }
+};
+*/
+
+WebviewWindow::WebviewWindow(WebviewWindow *parent, bool has_scp, QByteArray scp_pem)
: QMainWindow{parent}
{
+ static int profile_nr = 0;
+
_view = nullptr;
_must_close = false;
@@ -27,6 +51,22 @@ WebviewWindow::WebviewWindow(WebviewWindow *parent)
_moved = 0;
_resized = 0;
+ QWebEngineProfileBuilder b;
+ if (has_scp) {
+ profile_nr += 1;
+ char buf[100];
+ sprintf(buf, "profile-%d", profile_nr);
+ QString name(buf);
+ QSslCertificate cert(scp_pem);
+
+ QList certs;
+ certs.append(cert);
+ b.setAdditionalTrustedCertificates(certs);
+ _profile = b.createProfile(name);
+ } else {
+ _profile = QWebEngineProfile::defaultProfile();
+ }
+
if (parent != nullptr) {
setWindowModality(Qt::WindowModality::WindowModal);
setWindowFlag(Qt::WindowType::Dialog, true);
@@ -36,9 +76,63 @@ WebviewWindow::WebviewWindow(WebviewWindow *parent)
connect(&_move_timer, &QTimer::timeout, this, &WebviewWindow::triggerMove);
}
+void WebviewWindow::navigationRequested(QWebEngineNavigationRequest &req)
+{
+ if (req.navigationType() == QWebEngineNavigationRequest::NavigationType::TypedNavigation) {
+ req.accept();
+ } else {
+ EventContainer e("navigation-request");
+
+ e["url"] = req.url().toString();
+
+ QString type;
+ switch (req.navigationType()) {
+ case QWebEngineNavigationRequest::NavigationType::LinkClickedNavigation: type = "link-clicked";
+ break;
+ case QWebEngineNavigationRequest::NavigationType::TypedNavigation: type = "typed";
+ break;
+ case QWebEngineNavigationRequest::NavigationType::FormSubmittedNavigation: type = "form-submit";
+ break;
+ case QWebEngineNavigationRequest::NavigationType::BackForwardNavigation: type = "back-or-forward";
+ break;
+ case QWebEngineNavigationRequest::NavigationType::ReloadNavigation: type = "reload";
+ break;
+ case QWebEngineNavigationRequest::NavigationType::RedirectNavigation: type = "redirect";
+ break;
+ default: type = "other";
+ break;
+ }
+
+ e["type"] = type;
+ _container->triggerEvent(_view->id(), e);
+
+ req.reject();
+ }
+}
void WebviewWindow::handleCertificate(const QWebEngineCertificateError &certificateError)
{
+ /*
+ QList certs = _view->page()->profile()->additionalTrustedCertificates();
+
+ auto dodisp = [](QList certs)
+ {
+ int i;
+ for(i = 0; i < certs.size(); i++) {
+ QSslCertificate cert = certs[i];
+ QList attrs;
+ attrs.append(QSslCertificate::Organization);
+ attrs.append(QSslCertificate::OrganizationalUnitName);
+ attrs.append(QSslCertificate::CountryName);
+ attrs.append(QSslCertificate::CommonName);
+ displ1(cert, attrs);
+ }
+ };
+ dodisp(certs);
+ dodisp(certificateError.certificateChain());
+*/
+
+ fprintf(stderr, "Certificate Error: %s\n", certificateError.description().toUtf8().constData());
QList chain = certificateError.certificateChain();
int i;
for(i = 0; i < chain.size(); i++) {
@@ -88,6 +182,7 @@ void WebviewWindow::closeEvent(QCloseEvent *evt)
EventContainer e("closed");
_container->triggerEvent(_view->id(), e);
_container->removeView(_view->id());
+ _view->deleteLater();
this->deleteLater();
if (_devtools != nullptr) {
_devtools->deleteLater();
@@ -131,7 +226,14 @@ void WebviewWindow::addView(WebViewQt *v, Rktwebview_qt *c)
_view = v;
this->setCentralWidget(v);
- QWebEnginePage *page = _view->page();
+ QWebEnginePage *page;
+
+ if (_profile == nullptr) {
+ page = _view->page();
+ } else {
+ page = new QWebEnginePage(_profile, this);
+ _view->setPage(page);
+ }
// Inject event handling code for the javascript side
QWebEngineScriptCollection &col = page->scripts();
@@ -160,6 +262,8 @@ void WebviewWindow::addView(WebViewQt *v, Rktwebview_qt *c)
connect(page, &QWebEnginePage::loadStarted, this, [this]() {
_container->onPageLoad(_view->id());
});
+ connect(page, &QWebEnginePage::navigationRequested, this, &WebviewWindow::navigationRequested);
+
connect(page, &QWebEnginePage::certificateError, this, &WebviewWindow::handleCertificate);
}
@@ -231,6 +335,11 @@ void WebviewWindow::triggerMove()
_container->triggerEvent(_view->id(), xy);
}
+QWebEngineProfile *WebviewWindow::profile()
+{
+ return _profile;
+}
+
void WebviewWindow::resizeEvent(QResizeEvent *event)
{
_w = event->size().width();
diff --git a/rktwebview_qt/webviewwindow.h b/rktwebview_qt/webviewwindow.h
index 94d27d6..d86a8af 100644
--- a/rktwebview_qt/webviewwindow.h
+++ b/rktwebview_qt/webviewwindow.h
@@ -4,6 +4,8 @@
#include
#include
#include
+#include
+#include
class WebViewQt;
class Rktwebview_qt;
@@ -33,8 +35,11 @@ private:
QString _ou_token;
+ QWebEngineProfile *_profile;
+
private slots:
void handleCertificate(const QWebEngineCertificateError &certificateError);
+ void navigationRequested(QWebEngineNavigationRequest &req);
public slots:
void processJsEvents();
@@ -60,12 +65,15 @@ public:
void openDevTools();
public:
- explicit WebviewWindow(WebviewWindow *parent = nullptr);
+ explicit WebviewWindow(WebviewWindow *parent, bool has_scp, QByteArray scp_pem);
private slots:
void triggerResize();
void triggerMove();
+public:
+ QWebEngineProfile *profile();
+
signals:
// QWidget interface