-
This commit is contained in:
@@ -1,20 +1,11 @@
|
||||
|
||||
window._web_wire_evt_queue = [];
|
||||
if (window.rkt_event_queue === undefined) { window.rkt_event_queue = []; }
|
||||
|
||||
window._web_wire_queue_worker = function() {
|
||||
if (typeof web_ui_wire_handle_event === 'function') {
|
||||
while (window._web_wire_evt_queue.length > 0) {
|
||||
let evt = window._web_wire_evt_queue.shift();
|
||||
web_ui_wire_handle_event(JSON.stringify(evt));
|
||||
}
|
||||
}
|
||||
window.setTimeout(window._web_wire_queue_worker, 5);
|
||||
window.rkt_put_evt = function(evt) {
|
||||
window.rkt_event_queue.push(evt);
|
||||
};
|
||||
window.setTimeout(window._web_wire_queue_worker, 15);
|
||||
|
||||
window._web_wire_put_evt = function(evt) { window._web_wire_evt_queue.push(evt); };
|
||||
|
||||
window._web_wire_event_info = function(e, id, evt) {
|
||||
window.rkt_event_info = function(e, id, evt) {
|
||||
let obj = {};
|
||||
if (e == 'input') {
|
||||
obj['data'] = evt.data;
|
||||
@@ -53,13 +44,7 @@ window._web_wire_event_info = function(e, id, evt) {
|
||||
return obj;
|
||||
};
|
||||
|
||||
window._web_wire_get_evts = function() {
|
||||
let v = _web_wire_evt_queue;
|
||||
_web_wire_evt_queue = [];
|
||||
return JSON.stringify(v); // This needs no extra type info, as it is internally used only
|
||||
};
|
||||
|
||||
window._web_wire_bind_evt_ids = function(win_nr, selector, event_kind) {
|
||||
window.rkt_bind_evt_ids = function(win_nr, selector, event_kind) {
|
||||
try {
|
||||
let nodelist = document.querySelectorAll(selector);
|
||||
if (nodelist === undefined || nodelist === null) {
|
||||
@@ -75,8 +60,8 @@ window._web_wire_bind_evt_ids = function(win_nr, selector, event_kind) {
|
||||
el.addEventListener(event_kind,
|
||||
function(e) {
|
||||
let obj = {evt: event_kind, id: el_id, selector: selector, window: win_nr,
|
||||
js_evt: window._web_wire_event_info(event_kind, el_id, e) };
|
||||
window._web_wire_put_evt(obj);
|
||||
js_evt: window.rkt_event_info(event_kind, el_id, e) };
|
||||
window.rkt_put_evt(obj);
|
||||
}
|
||||
);
|
||||
let info = [ el_id, el_tag, el_type ];
|
||||
@@ -89,35 +74,3 @@ window._web_wire_bind_evt_ids = function(win_nr, selector, event_kind) {
|
||||
}
|
||||
};
|
||||
|
||||
window._web_wire_resize_timeout = false;
|
||||
window.addEventListener('resize', function() {
|
||||
clearTimeout(window._web_wire_resize_timeout);
|
||||
let f = function() {
|
||||
let obj = { selector: 'global', evt: 'window-resize', h: window.outerWidth, w: window.outerHeight };
|
||||
window._web_wire_put_evt(obj);
|
||||
};
|
||||
window._web_wire_resize_timeout = setTimeout(f, 250);
|
||||
});
|
||||
|
||||
window._web_wire_x = window.screenX;
|
||||
window._web_wire_y = window.screenY;
|
||||
window._web_wire_move_interval = setInterval(function() {
|
||||
let x = window.screenX;
|
||||
let y = window.screenY;
|
||||
if (x != window._web_wire_x || y != window._web_wire_y) {
|
||||
window._web_wire_x = x;
|
||||
window._web_wire_y = y;
|
||||
let obj = { selector: 'global', evt: 'window-move', x: x, y: y };
|
||||
window._web_wire_put_evt(obj);
|
||||
}
|
||||
}, 500);
|
||||
|
||||
document.addEventListener('readystatechange', event => {
|
||||
|
||||
// When window loaded ( external resources are loaded too- `css`,`src`, etc...)
|
||||
if (event.target.readyState === "complete") {
|
||||
let obj = { selector: 'global', evt: 'html-loaded' };
|
||||
window._web_wire_put_evt(obj);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -13,6 +13,21 @@
|
||||
racket/path
|
||||
)
|
||||
|
||||
(provide rkt-wv
|
||||
rkt-wv-win
|
||||
|
||||
rkt-webview-create
|
||||
rkt-webview-close
|
||||
rkt-webview-set-url!
|
||||
rkt-webview-set-html!
|
||||
rkt-webview-run-js
|
||||
rkt-webview-move
|
||||
rkt-webview-resize
|
||||
rkt-webview-exit
|
||||
rkt-webview-valid?
|
||||
rkt-webview-open-devtools
|
||||
)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; FFI Library
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -34,10 +49,19 @@
|
||||
(define webview-lib (ffi-lib webview-lib-file))
|
||||
(define-ffi-definer define-rktwebview webview-lib)
|
||||
|
||||
(define callback-box (box '()))
|
||||
(define (applier thunk)
|
||||
(thunk))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Types
|
||||
;; Types / Functions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-cstruct _rkt_evt_t
|
||||
([w _int]
|
||||
[evt _pointer]
|
||||
))
|
||||
|
||||
;RKTWEBVIEW_QT_EXPORT void rkt_webview_init(int &argc, char **argv);
|
||||
(define-rktwebview rkt_webview_init
|
||||
(_fun -> _void))
|
||||
@@ -48,7 +72,8 @@
|
||||
|
||||
;RKTWEBVIEW_QT_EXPORT int rkt_webview_create(int parent);
|
||||
(define-rktwebview rkt_webview_create
|
||||
(_fun _int -> _int))
|
||||
(_fun _int (_fun #:keep callback-box #:async-apply applier
|
||||
_rkt_evt_t-pointer -> _void) -> _int))
|
||||
|
||||
;RKTWEBVIEW_QT_EXPORT void rkt_webview_close(int wv);
|
||||
(define-rktwebview rkt_webview_close
|
||||
@@ -59,6 +84,37 @@
|
||||
(_fun _int _string/utf-8 -> _int))
|
||||
|
||||
;RKTWEBVIEW_QT_EXPORT result_t rkt_webview_set_html(int wv, const char *html);
|
||||
(define-rktwebview rkt_webview_set_html
|
||||
(_fun _int _string/utf-8 -> _int))
|
||||
|
||||
;RKTWEBVIEW_QT_EXPORT result_t rkt_webview_run_js(int wv, const char *js);
|
||||
(define-rktwebview rkt_webview_run_js
|
||||
(_fun _int _string/utf-8 -> _int))
|
||||
|
||||
;RKTWEBVIEW_QT_EXPORT result_t rkt_webview_open_devtools(int wv);
|
||||
(define-rktwebview rkt_webview_open_devtools
|
||||
(_fun _int -> _int))
|
||||
|
||||
;RKTWEBVIEW_QT_EXPORT result_t rkt_webview_destroy_event(rkt_event_t e);
|
||||
(define-rktwebview rkt_webview_destroy_event
|
||||
(_fun _rkt_evt_t-pointer -> _int))
|
||||
|
||||
;RKTWEBVIEW_QT_EXPORT result_t rkt_webview_move(rktwebview_t w, int x, int y);
|
||||
(define-rktwebview rkt_webview_move
|
||||
(_fun _int _int _int -> _int))
|
||||
|
||||
;RKTWEBVIEW_QT_EXPORT result_t rkt_webview_resize(rktwebview_t w, int width, int height);
|
||||
(define-rktwebview rkt_webview_resize
|
||||
(_fun _int _int _int -> _int))
|
||||
|
||||
;RKTWEBVIEW_QT_EXPORT bool rkt_webview_valid(rktwebview_t wv);
|
||||
(define-rktwebview rkt_webview_valid
|
||||
(_fun _int -> _int))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Initialize and start library
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define process-events #t)
|
||||
|
||||
@@ -79,4 +135,95 @@
|
||||
|
||||
(rkt_webview_init)
|
||||
(start-event-processing)
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Provided features
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-struct rkt-wv
|
||||
(win evt-queue callback [valid #:mutable])
|
||||
#:transparent
|
||||
)
|
||||
|
||||
(define rkt-wv-store (make-hash))
|
||||
|
||||
(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)
|
||||
(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)))
|
||||
((rkt-wv-callback handle) handle evt)
|
||||
(rkt_webview_destroy_event e)
|
||||
(rkt-process-events handle)))
|
||||
)
|
||||
'done))
|
||||
|
||||
(define (rkt-webview-create parent evt-callback)
|
||||
(let ((evt-queue (make-queue)))
|
||||
(let ((wv (rkt_webview_create parent
|
||||
(λ (rkt-evt)
|
||||
(enqueue! evt-queue rkt-evt)))))
|
||||
(let ((handle (make-rkt-wv wv evt-queue evt-callback #t)))
|
||||
(thread (λ ()
|
||||
(sleep 1)
|
||||
(letrec ((f (λ ()
|
||||
(let ((r (rkt-process-events handle)))
|
||||
(if (eq? r 'quit)
|
||||
(begin
|
||||
(set-rkt-wv-valid! handle #f)
|
||||
(displayln "Quitting event loop")
|
||||
'done)
|
||||
(begin
|
||||
;(displayln "Waiting for events.")
|
||||
(sleep 0.01)
|
||||
(f)))))))
|
||||
(f))))
|
||||
(hash-set! rkt-wv-store (rkt-wv-win handle) handle)
|
||||
handle))))
|
||||
|
||||
(define (rkt-webview-close handle)
|
||||
(rkt_webview_close (rkt-wv-win handle))
|
||||
(enqueue! (rkt-wv-evt-queue handle) 'quit)
|
||||
#t)
|
||||
|
||||
(define (rkt-webview-set-url! wv url)
|
||||
(rkt_webview_set_url (rkt-wv-win wv) url))
|
||||
|
||||
(define (rkt-webview-set-html! wv html)
|
||||
(rkt_webview_set_html (rkt-wv-win wv) html))
|
||||
|
||||
(define (rkt-webview-run-js wv js)
|
||||
(rkt_webview_run_js (rkt-wv-win wv) js))
|
||||
|
||||
(define (rkt-webview-resize wv w h)
|
||||
(rkt_webview_resize (rkt-wv-win wv) w h))
|
||||
|
||||
(define (rkt-webview-move wv x y)
|
||||
(rkt_webview_move (rkt-wv-win wv) x y))
|
||||
|
||||
(define (rkt-webview-open-devtools wv)
|
||||
(rkt_webview_open_devtools (rkt-wv-win wv)))
|
||||
|
||||
(define (rkt-webview-valid? wv)
|
||||
(if (eq? (rkt-wv-valid wv) #f)
|
||||
#f
|
||||
(if (= (rkt_webview_valid wv) 0)
|
||||
#f
|
||||
#t)))
|
||||
|
||||
(define (rkt-webview-exit)
|
||||
(let ((open-windows (hash->list rkt-wv-store)))
|
||||
(for-each (λ (kv)
|
||||
(let ((win (car kv))
|
||||
(handle (cdr kv)))
|
||||
(rkt-webview-close handle)))
|
||||
open-windows))
|
||||
(stop-event-processing))
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#lang racket/base
|
||||
|
||||
(require "racket-webview-ffi.rkt"
|
||||
(require "racket-webview-qt.rkt"
|
||||
"utils.rkt"
|
||||
web-server/servlet
|
||||
web-server/servlet-env
|
||||
@@ -16,16 +16,17 @@
|
||||
|
||||
(provide webview-create
|
||||
webview-devtools
|
||||
webview-has-events?
|
||||
webview-event-count
|
||||
webview-get-event
|
||||
webview-set-event-callback!
|
||||
webview-clear-event-callback!
|
||||
webview-bind
|
||||
webview-close
|
||||
webview-run-js
|
||||
;webview-call-js
|
||||
webview-move
|
||||
webview-resize
|
||||
webview-bind!
|
||||
)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Web server
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define current-servlet-port 8083)
|
||||
(define current-window-nr 1)
|
||||
|
||||
@@ -36,10 +37,12 @@
|
||||
(file->string file)))
|
||||
|
||||
(define-struct wv
|
||||
(handle port window-nr
|
||||
[file-getter #:mutable]
|
||||
[boilerplate-js #:mutable]
|
||||
[webserver-thread #:mutable]))
|
||||
([handle #:mutable]
|
||||
port
|
||||
[window-nr #:mutable]
|
||||
[file-getter #:mutable]
|
||||
[boilerplate-js #:mutable]
|
||||
[webserver-thread #:mutable]))
|
||||
|
||||
(define (process-html wv-handle path out)
|
||||
(let ((html (file->string path))
|
||||
@@ -90,79 +93,65 @@
|
||||
#:stateless? #t
|
||||
;#:launch-browser #f
|
||||
#:servlet-regexp #rx""))))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Utilities
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define (util-parse-event evt)
|
||||
(let ((wv-d0 (with-input-from-string evt read-json)))
|
||||
wv-d0))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Webview functions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define (webview-create file-getter #:boilerplate-js [bj (default-boilerplate-js)])
|
||||
(let* ((wv (rkt_create_webview))
|
||||
(h (make-wv wv current-servlet-port current-window-nr file-getter bj #f))
|
||||
(define (webview-create file-getter event-callback
|
||||
#:boilerplate-js [bj (default-boilerplate-js)]
|
||||
#: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)
|
||||
s))
|
||||
(event-processor (λ (wv evt)
|
||||
(event-callback h (util-parse-event evt))))
|
||||
(wv (rkt-webview-create p event-processor))
|
||||
(base-req (format "http://127.0.0.1:~a"
|
||||
(wv-port h)))
|
||||
)
|
||||
(set-wv-webserver-thread! h (start-web-server h))
|
||||
(rkt_webview_navigate (wv-handle h) base-req)
|
||||
(set-wv-handle! h wv)
|
||||
(set-wv-window-nr! h (rkt-wv-win wv))
|
||||
(set-wv-webserver-thread! h server)
|
||||
(rkt-webview-set-url! (wv-handle h) base-req)
|
||||
(set! current-servlet-port (+ current-servlet-port 1))
|
||||
(set! current-window-nr (+ current-window-nr 1))
|
||||
h))
|
||||
|
||||
(define (webview-devtools wv)
|
||||
(rkt_webview_devtools (wv-handle wv)))
|
||||
(rkt-webview-open-devtools (wv-handle wv)))
|
||||
|
||||
(define (webview-parse-event evt)
|
||||
(let ((wv-d0 (with-input-from-string evt read-json)))
|
||||
;(displayln wv-d0)
|
||||
(let ((wv-d1 (with-input-from-string (hash-ref wv-d0 'data) read-json)))
|
||||
;(displayln wv-d1)
|
||||
(let ((wv-d2 (with-input-from-string (car wv-d1) read-json)))
|
||||
;(displayln wv-d2)
|
||||
wv-d2))))
|
||||
(define (webview-move wv x y)
|
||||
(rkt-webview-move (wv-handle wv) x y))
|
||||
|
||||
(define (webview-set-event-callback! wv cb)
|
||||
(rkt_webview_set_event_callback! (wv-handle wv) (wv-window-nr wv)
|
||||
(λ (context data)
|
||||
(let ((e (webview-parse-event data)))
|
||||
(cb context e)))))
|
||||
(define (webview-resize wv w h)
|
||||
(rkt-webview-resize (wv-handle wv) w h))
|
||||
|
||||
(define (webview-clear-event-callback! wv)
|
||||
(rkt_webview_clear_event_callback! (wv-handle wv) (wv-window-nr wv)))
|
||||
|
||||
|
||||
(define (webview-get-event wv)
|
||||
(if (> (rkt_webview_pending_events (wv-handle wv)) 0)
|
||||
(let ((item (rkt_webview_get_event (wv-handle wv))))
|
||||
(let ((data (rkt_webview_item_data item)))
|
||||
(rkt_webview_destroy_item item)
|
||||
(let ((wv-d0 (with-input-from-string data read-json)))
|
||||
;(displayln wv-d0)
|
||||
(let ((wv-d1 (with-input-from-string (hash-ref wv-d0 'data) read-json)))
|
||||
;(displayln wv-d1)
|
||||
(let ((wv-d2 (with-input-from-string (car wv-d1) read-json)))
|
||||
;(displayln wv-d2)
|
||||
wv-d2
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
#f)
|
||||
(define (webview-close wv)
|
||||
(rkt-webview-close (wv-handle wv))
|
||||
(kill-thread (wv-webserver-thread wv))
|
||||
)
|
||||
|
||||
(define (webview-has-events? wv)
|
||||
(>= (rkt_webview_pending_events (wv-handle wv)) 1)
|
||||
)
|
||||
|
||||
(define (webview-event-count wv)
|
||||
(rkt_webview_pending_events (wv-handle wv)))
|
||||
|
||||
(define (webview-bind wv selector event)
|
||||
(define (webview-bind! wv selector event)
|
||||
(let ((sel (if (symbol? selector)
|
||||
(format "#~a" selector)
|
||||
selector))
|
||||
(evt (format "~a" event)))
|
||||
(rkt_webview_run_js (wv-handle wv)
|
||||
(format "window._web_wire_bind_evt_ids(~a, '~a', '~a')"
|
||||
(webview-run-js wv
|
||||
(format "window.rkt_bind_evt_ids(~a, '~a', '~a')"
|
||||
(wv-window-nr wv) sel evt))))
|
||||
|
||||
(define (webview-run-js wv js)
|
||||
(rkt_webview_run_js (wv-handle wv) js))
|
||||
(rkt-webview-run-js (wv-handle wv) js))
|
||||
|
||||
;(define (webview-call-js wv js)
|
||||
; (let ((result (rkt_webview_call_js (wv-handle wv) js)))
|
||||
@@ -184,13 +173,16 @@
|
||||
p)))
|
||||
|
||||
(define (test)
|
||||
(let ((h (webview-create file-getter)))
|
||||
(displayln (webview-has-events? h))
|
||||
(let* ((cb (λ (handle evt)
|
||||
(displayln evt)))
|
||||
(h (webview-create file-getter cb)))
|
||||
h))
|
||||
|
||||
|
||||
(while (not (webview-has-events? h))
|
||||
(displayln "Waiting...")
|
||||
(sleep 1))
|
||||
(let ((evt (webview-get-event h)))
|
||||
(when (string=? (hash-ref evt 'evt) "html-loaded")
|
||||
(webview-bind h "button" "click")))
|
||||
h))
|
||||
; (while (not (webview-has-events? h))
|
||||
; (displayln "Waiting...")
|
||||
; (sleep 1))
|
||||
; (let ((evt (webview-get-event h)))
|
||||
; (when (string=? (hash-ref evt 'evt) "html-loaded")
|
||||
; (webview-bind h "button" "click")))
|
||||
; h))
|
||||
@@ -22,6 +22,7 @@ add_library(rktwebview_qt SHARED
|
||||
rktwebview_internal.h
|
||||
webviewwindow.h webviewwindow.cpp
|
||||
webviewapp.h webviewapp.cpp
|
||||
rktutils.h rktutils.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(rktwebview_qt PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
|
||||
@@ -40,6 +41,7 @@ add_executable(rktwebview_qt_test
|
||||
webviewwindow.h webviewwindow.cpp
|
||||
rktwebview_internal.h
|
||||
webviewapp.h webviewapp.cpp
|
||||
rktutils.h rktutils.cpp
|
||||
)
|
||||
|
||||
target_compile_definitions(rktwebview_qt_test PRIVATE RKTWEBVIEW_QT_LIBRARY)
|
||||
|
||||
@@ -5,6 +5,12 @@
|
||||
static int _argc;
|
||||
static char **_argv;
|
||||
|
||||
void eventCb(rkt_event_t *e)
|
||||
{
|
||||
printf("event: %s\n", e->event);
|
||||
rkt_webview_destroy_event(e);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int wv1;
|
||||
@@ -14,20 +20,30 @@ int main(int argc, char *argv[])
|
||||
_argv = argv;
|
||||
|
||||
rkt_webview_init();
|
||||
wv1 = rkt_webview_create(0);
|
||||
wv1 = rkt_webview_create(0, eventCb);
|
||||
rkt_webview_set_url(wv1, "https://wikipedia.org");
|
||||
|
||||
int i = 0;
|
||||
while(i < 20) {
|
||||
while(i < 60) {
|
||||
printf("Waiting...%d\n", i);
|
||||
rkt_webview_process_events(1000);
|
||||
|
||||
if (i == 10) {
|
||||
wv2 = rkt_webview_create(0);
|
||||
if (i == 6) {
|
||||
rkt_webview_open_devtools(wv1);
|
||||
}
|
||||
|
||||
if (i == 15) {
|
||||
rkt_webview_close(wv1);
|
||||
if (i == 10) {
|
||||
wv2 = rkt_webview_create(0, eventCb);
|
||||
}
|
||||
|
||||
if (i > 10) {
|
||||
char buf[1000];
|
||||
sprintf(buf, "{ let obj = { e: 'test', i: %d }; window.rkt_send_event(obj); }", i);
|
||||
rkt_webview_run_js(wv1, buf);
|
||||
}
|
||||
|
||||
if (i == 24) {
|
||||
rkt_webview_close(wv2);
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
27
rktwebview_qt/rktutils.cpp
Normal file
27
rktwebview_qt/rktutils.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "rktutils.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QMetaType>
|
||||
|
||||
QString mkEventJson(const EventContainer &kv)
|
||||
{
|
||||
QJsonObject obj;
|
||||
|
||||
QList<QString> keys = kv.keys();
|
||||
int i, N;
|
||||
for(i = 0, N = keys.length(); i < N; i++) {
|
||||
const QString &key = keys[i];
|
||||
const QVariant &v = kv[key];
|
||||
obj[key] = v.toJsonValue();
|
||||
}
|
||||
|
||||
QJsonDocument doc(obj);
|
||||
return QString::fromUtf8(doc.toJson(QJsonDocument::JsonFormat::Compact));
|
||||
}
|
||||
|
||||
QHash<QString, QVariant> mkEvent()
|
||||
{
|
||||
QHash<QString, QVariant> h;
|
||||
return h;
|
||||
}
|
||||
18
rktwebview_qt/rktutils.h
Normal file
18
rktwebview_qt/rktutils.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef __RKT_UTILS_H__
|
||||
#define __RKT_UTILS_H__
|
||||
|
||||
#include <QHash>
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
|
||||
class EventContainer : public QHash<QString, QVariant>
|
||||
{
|
||||
public:
|
||||
EventContainer(const QString &evt) {
|
||||
this->insert("event", evt);
|
||||
}
|
||||
};
|
||||
|
||||
QString mkEventJson(const EventContainer &kv);
|
||||
|
||||
#endif
|
||||
@@ -27,127 +27,56 @@ Rktwebview_qt *handler = nullptr;
|
||||
|
||||
void rkt_webview_init()
|
||||
{
|
||||
/*
|
||||
if (!started) {
|
||||
if (pipe(pipefd) != -1) {
|
||||
webview_process = fork();
|
||||
|
||||
if (webview_process < 0)
|
||||
cannot_fork_or_pipe = true;
|
||||
} else if (webview_process == 0) {
|
||||
WebViewApp app;
|
||||
|
||||
|
||||
|
||||
started = true;
|
||||
} else {
|
||||
cannot_fork_or_pipe = true;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (handler == nullptr) {
|
||||
handler = new Rktwebview_qt(&handler);
|
||||
}
|
||||
}
|
||||
|
||||
int rkt_webview_create(int parent, void (*js_event_cb)(const char *))
|
||||
int rkt_webview_create(rktwebview_t parent, event_cb_t js_event_cb)
|
||||
{
|
||||
rkt_webview_init();
|
||||
return handler->rktWebViewCreate(parent, js_event_cb);
|
||||
}
|
||||
|
||||
void rkt_webview_close(int wv)
|
||||
void rkt_webview_close(rktwebview_t wv)
|
||||
{
|
||||
rkt_webview_init();
|
||||
handler->rktWebViewClose(wv);
|
||||
}
|
||||
|
||||
result_t rkt_webview_set_url(int wv, const char *url)
|
||||
result_t rkt_webview_set_url(rktwebview_t wv, const char *url)
|
||||
{
|
||||
rkt_webview_init();
|
||||
result_t r = handler->rktSetUrl(wv, url);
|
||||
return r;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Supporting functions
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
void queue_init(queue_t **q)
|
||||
result_t rkt_webview_set_html(rktwebview_t wv, const char *url)
|
||||
{
|
||||
*q = static_cast<queue_t *>(malloc(sizeof(queue_t)));
|
||||
queue_t *Q = *q;
|
||||
Q->length = 0;
|
||||
Q->first = nullptr;
|
||||
Q->last = nullptr;
|
||||
}
|
||||
|
||||
void enqueue(queue_t *q, item_t item)
|
||||
{
|
||||
queue_item_t *itm = (queue_item_t *) malloc(sizeof(queue_item_t));
|
||||
itm->item.context = item.context;
|
||||
itm->item.data = strdup(item.data);
|
||||
if (q->first == nullptr) {
|
||||
q->first = itm;
|
||||
q->last = itm;
|
||||
itm->prev = nullptr;
|
||||
itm->next = nullptr;
|
||||
q->length = 1;
|
||||
} else {
|
||||
itm->prev = q->last;
|
||||
itm->next = nullptr;
|
||||
q->last->next = itm;
|
||||
q->last = itm;
|
||||
q->length += 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool dequeue(queue_t *q, item_t *item)
|
||||
{
|
||||
if (q->length == 0) {
|
||||
item->context = CONTEXT_INVALID;
|
||||
item->data = nullptr;
|
||||
return false;
|
||||
} else {
|
||||
queue_item_t *itm = q->first;
|
||||
q->first = q->first->next;
|
||||
q->length -= 1;
|
||||
if (q->length == 0) {
|
||||
q->first = nullptr;
|
||||
q->last = nullptr;
|
||||
}
|
||||
item->context = itm->item.context;
|
||||
item->data = itm->item.data;
|
||||
free(itm);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int queue_length(queue_t *q)
|
||||
{
|
||||
return q->length;
|
||||
}
|
||||
|
||||
void queue_destroy(queue_t *q)
|
||||
{
|
||||
item_t i;
|
||||
while(dequeue(q, &i)) {
|
||||
free(i.data);
|
||||
}
|
||||
free(q);
|
||||
}
|
||||
|
||||
void free_item(item_t item)
|
||||
{
|
||||
free(item.data);
|
||||
rkt_webview_init();
|
||||
result_t r = handler->rktSetHtml(wv, url);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
result_t rkt_webview_run_js(rktwebview_t wv, const char *js)
|
||||
{
|
||||
rkt_webview_init();
|
||||
result_t r = handler->rktRunJs(wv, js);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
result_t rkt_webview_open_devtools(rktwebview_t wv)
|
||||
{
|
||||
rkt_webview_init();
|
||||
result_t r = handler->rktOpenDevtools(wv);
|
||||
return r;
|
||||
}
|
||||
|
||||
void rkt_webview_process_events(int for_ms)
|
||||
{
|
||||
//rkt_webview_init();
|
||||
rkt_webview_init();
|
||||
|
||||
int64_t start_ms = current_ms();
|
||||
int64_t end_ms = start_ms + for_ms;
|
||||
@@ -157,3 +86,35 @@ void rkt_webview_process_events(int for_ms)
|
||||
handler->doEvents();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
result_t rkt_webview_destroy_event(rkt_event_t *e)
|
||||
{
|
||||
free(e->event);
|
||||
free(e);
|
||||
return result_t::oke;
|
||||
}
|
||||
|
||||
result_t rkt_webview_move(rktwebview_t wv, int x, int y)
|
||||
{
|
||||
rkt_webview_init();
|
||||
|
||||
result_t r = handler->rktMove(wv, x, y);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
result_t rkt_webview_resize(rktwebview_t wv, int width, int height)
|
||||
{
|
||||
rkt_webview_init();
|
||||
|
||||
result_t r = handler->rktResize(wv, width, height);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
bool rkt_webview_valid(rktwebview_t wv)
|
||||
{
|
||||
rkt_webview_init();
|
||||
return handler->rktValid(wv);
|
||||
}
|
||||
|
||||
@@ -3,31 +3,16 @@
|
||||
|
||||
#include "rktwebview_qt_global.h"
|
||||
|
||||
#define CONTEXT_QUIT -2
|
||||
#define CONTEXT_NIL -1
|
||||
#define CONTEXT_INVALID 0
|
||||
#define CONTEXT_BOUND_EVENT 1
|
||||
#define CONTEXT_WINDOW_RESIZE 2
|
||||
#define CONTEXT_WINDOW_MOVE 3
|
||||
#define CONTEXT_WINDOW_CAN_CLOSE 4
|
||||
#define CONTEXT_WINDOW_CLOSED 5
|
||||
#define CONTEXT_SET_HTML 6
|
||||
#define CONTEXT_NAVIGATE 7
|
||||
#define CONTEXT_EVAL_JS 8
|
||||
#define CONTEXT_OPEN_DEVTOOLS 9
|
||||
#define CONTEXT_CALL_JS 10
|
||||
#define CONTEXT_CMD_CLOSE 11
|
||||
#define CONTEXT_CMD_CREATE_VIEW 12
|
||||
|
||||
extern "C" {
|
||||
|
||||
typedef int rktwebview_t;
|
||||
|
||||
typedef struct {
|
||||
rktwebview_t wv;
|
||||
int context;
|
||||
char *data;
|
||||
} item_t;
|
||||
char *event;
|
||||
} rkt_event_t;
|
||||
|
||||
typedef void (*event_cb_t)(rkt_event_t *);
|
||||
|
||||
typedef enum {
|
||||
no_result_yet = -1,
|
||||
@@ -42,15 +27,29 @@ typedef enum {
|
||||
webview_invalid_state = 8,
|
||||
webview_invalid_argument = 9,
|
||||
webview_unspecified = 10,
|
||||
webview_dispatch_failed = 11
|
||||
webview_dispatch_failed = 11,
|
||||
move_failed = 12,
|
||||
resize_failed = 13
|
||||
} result_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(int parent, void (*js_event_cb)(const char *msg));
|
||||
RKTWEBVIEW_QT_EXPORT void rkt_webview_close(int wv);
|
||||
RKTWEBVIEW_QT_EXPORT result_t rkt_webview_set_url(int wv, const char *url);
|
||||
RKTWEBVIEW_QT_EXPORT result_t rkt_webview_set_html(int wv, const char *html);
|
||||
|
||||
RKTWEBVIEW_QT_EXPORT int rkt_webview_create(rktwebview_t parent, event_cb_t js_event_cb);
|
||||
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_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 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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -3,23 +3,4 @@
|
||||
|
||||
#include "rktwebview.h"
|
||||
|
||||
typedef struct _item {
|
||||
item_t item;
|
||||
struct _item *next;
|
||||
struct _item *prev;
|
||||
} queue_item_t;
|
||||
|
||||
typedef struct {
|
||||
queue_item_t *first;
|
||||
queue_item_t *last;
|
||||
int length;
|
||||
} queue_t;
|
||||
|
||||
void queue_init(queue_t **q);
|
||||
void enqueue(queue_t *q, item_t item);
|
||||
bool dequeue(queue_t *q, item_t *item);
|
||||
int queue_length(queue_t *q);
|
||||
void queue_destroy(queue_t *q);
|
||||
void free_item(item_t i);
|
||||
|
||||
#endif // RKTWEBVIEW_INTERNAL_H
|
||||
|
||||
@@ -2,16 +2,22 @@
|
||||
#include "webviewqt.h"
|
||||
#include "rktwebview.h"
|
||||
#include "webviewwindow.h"
|
||||
#include "rktutils.h"
|
||||
#include <QApplication>
|
||||
#include <QTimer>
|
||||
#include <QSemaphore>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
#define COMMAND_QUIT 1
|
||||
#define COMMAND_CLOSE 2
|
||||
#define COMMAND_CREATE 3
|
||||
#define COMMAND_SET_URL 4
|
||||
#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
|
||||
|
||||
class Command
|
||||
{
|
||||
@@ -27,13 +33,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
static QString jsonString(QJsonObject obj)
|
||||
{
|
||||
QJsonDocument doc(obj);
|
||||
QString j = QString::fromUtf8(doc.toJson(QJsonDocument::JsonFormat::Compact));
|
||||
return j;
|
||||
}
|
||||
|
||||
void Rktwebview_qt::processCommands()
|
||||
{
|
||||
while(!_command_queue.empty()) {
|
||||
@@ -49,7 +48,7 @@ void Rktwebview_qt::processCommands()
|
||||
int parent = cmd->args[0].toInt();
|
||||
|
||||
void *f = cmd->args[1].value<void *>();
|
||||
void (*js_event_cb)(const char *msg) = reinterpret_cast <void(*)(const char *)>(f);
|
||||
event_cb_t js_event_cb = reinterpret_cast <event_cb_t>(f);
|
||||
|
||||
QWidget *p;
|
||||
if (_views.contains(parent)) {
|
||||
@@ -78,8 +77,7 @@ void Rktwebview_qt::processCommands()
|
||||
if (_views.contains(wv)) {
|
||||
WebviewWindow *w= _views[wv];
|
||||
_views.remove(wv);
|
||||
w->close();
|
||||
w->deleteLater();
|
||||
w->closeView();
|
||||
cmd->result = true;
|
||||
} else {
|
||||
cmd->result = false;
|
||||
@@ -102,6 +100,73 @@ void Rktwebview_qt::processCommands()
|
||||
cmd->done = true;
|
||||
}
|
||||
break;
|
||||
case COMMAND_SET_HTML: {
|
||||
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_RUN_JS: {
|
||||
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_DEV_TOOLS: {
|
||||
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_MOVE: {
|
||||
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];
|
||||
w->move(x, y);
|
||||
cmd->result = true;
|
||||
} else {
|
||||
cmd->result = false;
|
||||
}
|
||||
cmd->done = true;
|
||||
}
|
||||
break;
|
||||
case COMMAND_RESIZE: {
|
||||
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];
|
||||
w->resize(width, height);
|
||||
cmd->result = true;
|
||||
} else {
|
||||
cmd->result = false;
|
||||
}
|
||||
cmd->done = true;
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
cmd->result = false;
|
||||
cmd->done = true;
|
||||
@@ -111,14 +176,26 @@ void Rktwebview_qt::processCommands()
|
||||
}
|
||||
}
|
||||
|
||||
void Rktwebview_qt::processJsEventQueue()
|
||||
void Rktwebview_qt::processJsEventQueues()
|
||||
{
|
||||
|
||||
QList<rktwebview_t> wvs = _views.keys();
|
||||
int i, N;
|
||||
for(i = 0, N = wvs.length(); i < N; i++) {
|
||||
int wv = wvs[i];
|
||||
if (_views.contains(wv)) {
|
||||
WebviewWindow *win = _views[wv];
|
||||
win->processJsEvents();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Rktwebview_qt::removeView(int id)
|
||||
{
|
||||
_views.remove(id);
|
||||
if (_views.contains(id)) {
|
||||
WebviewWindow *win = _views[id];
|
||||
_views.remove(id);
|
||||
_view_js_callbacks.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
int Rktwebview_qt::nextHandle()
|
||||
@@ -127,7 +204,7 @@ int Rktwebview_qt::nextHandle()
|
||||
return h;
|
||||
}
|
||||
|
||||
int Rktwebview_qt::rktWebViewCreate(int parent, void (*js_evt_cb)(const char *))
|
||||
int Rktwebview_qt::rktWebViewCreate(int parent, event_cb_t js_evt_cb)
|
||||
{
|
||||
Command c(COMMAND_CREATE);
|
||||
c.args.push_back(parent);
|
||||
@@ -168,28 +245,113 @@ result_t Rktwebview_qt::rktSetUrl(rktwebview_t wv, const char *url)
|
||||
return r ? result_t::oke : result_t::set_navigate_failed;
|
||||
}
|
||||
|
||||
result_t Rktwebview_qt::rktSetHtml(rktwebview_t wv, const char *html)
|
||||
{
|
||||
Command c(COMMAND_SET_HTML);
|
||||
QString _html(html);
|
||||
c.args.push_back(wv);
|
||||
c.args.push_back(_html);
|
||||
_command_queue.enqueue(&c);
|
||||
|
||||
while(!c.done) { doEvents(); }
|
||||
|
||||
bool r = c.result.toBool();
|
||||
|
||||
return r ? result_t::oke : result_t::set_navigate_failed;
|
||||
}
|
||||
|
||||
result_t Rktwebview_qt::rktRunJs(rktwebview_t wv, const char *js)
|
||||
{
|
||||
Command c(COMMAND_RUN_JS);
|
||||
QString _js(js);
|
||||
c.args.push_back(wv);
|
||||
c.args.push_back(_js);
|
||||
_command_queue.enqueue(&c);
|
||||
while(!c.done) { doEvents(); }
|
||||
bool r = c.result.toBool();
|
||||
return r ? result_t::oke : result_t::eval_js_failed;
|
||||
}
|
||||
|
||||
result_t Rktwebview_qt::rktMove(rktwebview_t wv, int x, int y)
|
||||
{
|
||||
Command c(COMMAND_MOVE);
|
||||
c.args.push_back(wv);
|
||||
c.args.push_back(x);
|
||||
c.args.push_back(y);
|
||||
_command_queue.enqueue(&c);
|
||||
while(!c.done) { doEvents(); }
|
||||
bool r = c.result.toBool();
|
||||
return r ? result_t::oke : result_t::move_failed;
|
||||
}
|
||||
|
||||
result_t Rktwebview_qt::rktResize(rktwebview_t wv, int w, int h)
|
||||
{
|
||||
Command c(COMMAND_RESIZE);
|
||||
c.args.push_back(wv);
|
||||
c.args.push_back(w);
|
||||
c.args.push_back(h);
|
||||
_command_queue.enqueue(&c);
|
||||
while(!c.done) { doEvents(); }
|
||||
bool r = c.result.toBool();
|
||||
return r ? result_t::oke : result_t::resize_failed;
|
||||
}
|
||||
|
||||
bool Rktwebview_qt::rktValid(rktwebview_t wv)
|
||||
{
|
||||
return _views.contains(wv);
|
||||
}
|
||||
|
||||
result_t Rktwebview_qt::rktOpenDevtools(rktwebview_t wv)
|
||||
{
|
||||
Command c(COMMAND_DEV_TOOLS);
|
||||
c.args.push_back(wv);
|
||||
_command_queue.enqueue(&c);
|
||||
while(!c.done) { doEvents(); }
|
||||
bool r = c.result.toBool();
|
||||
return r ? result_t::oke : result_t::eval_js_failed;
|
||||
}
|
||||
|
||||
void Rktwebview_qt::onPageLoad(rktwebview_t w)
|
||||
{
|
||||
}
|
||||
|
||||
void Rktwebview_qt::pageLoaded(rktwebview_t w, bool ok)
|
||||
{
|
||||
// Inject event handling code for the javascript side
|
||||
runJs(w, "window.rkt_event_queue = [];\n"
|
||||
"window.rkt_send_event = function(obj) { window.rkt_event_queue.push(obj); };\n"
|
||||
"window.rkt_get_events = function() { "
|
||||
" let q = window.rkt_event_queue; "
|
||||
" window.rkt_event_queue = [];"
|
||||
" let json_q = JSON.stringify(q);"
|
||||
" return json_q;"
|
||||
"};");
|
||||
runJs(w,
|
||||
"if (window.rkt_event_queue === undefined) { window.rkt_event_queue = []; }\n"
|
||||
"window.rkt_send_event = function(obj) {\n"
|
||||
" console.log('Sending event: ' + obj);\n"
|
||||
" window.rkt_event_queue.push(obj);\n"
|
||||
"};\n"
|
||||
"window.rkt_get_events = function() {\n"
|
||||
" let q = window.rkt_event_queue;\n"
|
||||
" window.rkt_event_queue = [];\n"
|
||||
" let json_q = JSON.stringify(q);\n"
|
||||
" return json_q;\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
// trigger page loaded.
|
||||
QJsonObject obj;
|
||||
obj["event"] = "page-loaded";
|
||||
obj["oke"] = ok;
|
||||
triggerEvent(w, jsonString(obj));
|
||||
EventContainer e("page-loaded");
|
||||
e["oke"] = ok;
|
||||
triggerEvent(w, e);
|
||||
}
|
||||
|
||||
void Rktwebview_qt::triggerEvent(rktwebview_t wv, const EventContainer &e)
|
||||
{
|
||||
triggerEvent(wv, mkEventJson(e));
|
||||
}
|
||||
|
||||
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<rkt_event_t *>(malloc(sizeof(rkt_event_t)));
|
||||
e->wv = wv;
|
||||
e->event = evt;
|
||||
js_event_cb(e);
|
||||
}
|
||||
}
|
||||
|
||||
void Rktwebview_qt::rktQuit()
|
||||
@@ -211,8 +373,8 @@ void Rktwebview_qt::runJs(rktwebview_t wv, const char *js)
|
||||
{
|
||||
if (_views.contains(wv)) {
|
||||
QString _js(js);
|
||||
WebViewQt *view = _views[wv]->view();
|
||||
view->runJs(_js);
|
||||
WebviewWindow *win = _views[wv];
|
||||
win->runJs(_js);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,6 +396,8 @@ Rktwebview_qt::Rktwebview_qt(Rktwebview_qt **handler) :
|
||||
_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);
|
||||
|
||||
*_handler = nullptr;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "rktwebview_qt_global.h"
|
||||
#include "rktwebview_internal.h"
|
||||
#include "rktutils.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QWebEngineView>
|
||||
@@ -24,18 +25,23 @@ private:
|
||||
QApplication *_app;
|
||||
rktwebview_t _current_handle;
|
||||
QHash<int, WebviewWindow *> _views;
|
||||
QHash<int, void(*)(const char *msg)> _view_js_callbacks;
|
||||
QHash<int, event_cb_t> _view_js_callbacks;
|
||||
|
||||
QQueue<Command *> _command_queue;
|
||||
QTimer _process_commands;
|
||||
QTimer _process_events;
|
||||
|
||||
Rktwebview_qt **_handler;
|
||||
|
||||
int _argc;
|
||||
char *_argv[1];
|
||||
|
||||
private:
|
||||
void runJs(rktwebview_t wv, const char *js);
|
||||
|
||||
public slots:
|
||||
void processCommands();
|
||||
void processJsEventQueues();
|
||||
|
||||
public:
|
||||
void removeView(int id);
|
||||
@@ -43,23 +49,26 @@ public:
|
||||
public:
|
||||
int nextHandle();
|
||||
public:
|
||||
int rktWebViewCreate(int parent, void(*js_evt_cb)(const char *msg));
|
||||
int rktWebViewCreate(int parent, event_cb_t js_evt_cb);
|
||||
void rktWebViewClose(int wv);
|
||||
void rktQuit();
|
||||
|
||||
void runJs(rktwebview_t wv, const char *js);
|
||||
item_t callJs(rktwebview_t wv, const char *js);
|
||||
|
||||
void setHtml(rktwebview_t wv, const char *html);
|
||||
void navigate(rktwebview_t wv, const char *url);
|
||||
result_t rktOpenDevtools(rktwebview_t wv);
|
||||
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);
|
||||
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);
|
||||
|
||||
public:
|
||||
// Events for the backend
|
||||
void pageLoaded(rktwebview_t w, bool ok);
|
||||
void onPageLoad(rktwebview_t w);
|
||||
|
||||
public:
|
||||
void triggerEvent(rktwebview_t wv, const QString &msg);
|
||||
void triggerEvent(rktwebview_t wv, const EventContainer &e);
|
||||
|
||||
public:
|
||||
void doEvents();
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#include "webviewqt.h"
|
||||
#include "webviewwindow.h"
|
||||
#include <QWebEnginePage>
|
||||
#include <QJsonDocument>
|
||||
|
||||
WebViewQt::WebViewQt(int id, QWidget *parent)
|
||||
: QWebEngineView(parent)
|
||||
WebViewQt::WebViewQt(int id, WebviewWindow *window)
|
||||
: QWebEngineView(window)
|
||||
{
|
||||
_id = id;
|
||||
_window = window;
|
||||
}
|
||||
|
||||
int WebViewQt::id() const
|
||||
@@ -13,8 +15,9 @@ int WebViewQt::id() const
|
||||
return _id;
|
||||
}
|
||||
|
||||
QString WebViewQt::runJs(const QString &js)
|
||||
WebviewWindow *WebViewQt::wvWin()
|
||||
{
|
||||
return _window;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,24 +4,25 @@
|
||||
#include <QWebEngineView>
|
||||
#include <QTimer>
|
||||
|
||||
class WebviewWindow;
|
||||
|
||||
class WebViewQt : public QWebEngineView
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
int _id;
|
||||
int _id;
|
||||
WebviewWindow *_window;
|
||||
|
||||
public:
|
||||
int id() const;
|
||||
|
||||
public:
|
||||
QString runJs(const QString &js);
|
||||
WebviewWindow *wvWin();
|
||||
|
||||
signals:
|
||||
void pageLoaded(WebViewQt *, bool ok);
|
||||
|
||||
|
||||
public:
|
||||
WebViewQt(int id, QWidget *parent = nullptr);
|
||||
WebViewQt(int id, WebviewWindow *window);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -2,15 +2,33 @@
|
||||
|
||||
#include "webviewqt.h"
|
||||
#include "rktwebview_qt.h"
|
||||
#include "rktutils.h"
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonParseError>
|
||||
#include <QJsonObject>
|
||||
#include <QWebEngineScriptCollection>
|
||||
#include <QWebEngineScript>
|
||||
|
||||
#include <QMoveEvent>
|
||||
|
||||
WebviewWindow::WebviewWindow(QWidget *parent)
|
||||
: QMainWindow{parent}
|
||||
{
|
||||
_view = nullptr;
|
||||
_must_close = false;
|
||||
|
||||
_devtools = nullptr;
|
||||
|
||||
connect(&_resize_timer, &QTimer::timeout, this, &WebviewWindow::triggerResize);
|
||||
connect(&_move_timer, &QTimer::timeout, this, &WebviewWindow::triggerMove);
|
||||
}
|
||||
|
||||
|
||||
void WebviewWindow::processJsEvents()
|
||||
{
|
||||
QWebEnginePage *p = _view->page();
|
||||
p->runJavaScript("window.getPendingEvents();",
|
||||
p->runJavaScript("if (window.rkt_get_events) { window.rkt_get_events(); } else { JSON.stringify([]); }",
|
||||
[this](const QVariant &v) {
|
||||
QString s = v.toString();
|
||||
QJsonParseError err;
|
||||
@@ -19,11 +37,15 @@ void WebviewWindow::processJsEvents()
|
||||
QJsonArray a = doc.array();
|
||||
int i, N;
|
||||
for(i = 0, N = a.size(); i < N; i++) {
|
||||
QJsonObject evt = a[i].toObject();
|
||||
QJsonDocument doc_out(evt);
|
||||
QString msg = doc_out.toJson(QJsonDocument::JsonFormat::Compact);
|
||||
this->_container->triggerJsEvent(_view->id(), msg);
|
||||
QJsonObject js_evt = a[i].toObject();
|
||||
|
||||
EventContainer e("js-evt");
|
||||
e["js-evt"] = js_evt;
|
||||
|
||||
this->_container->triggerEvent(_view->id(), e);
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -31,7 +53,25 @@ void WebviewWindow::processJsEvents()
|
||||
|
||||
void WebviewWindow::closeEvent(QCloseEvent *evt)
|
||||
{
|
||||
_container->removeView(_view->id());
|
||||
if (_must_close) {
|
||||
EventContainer e("closed");
|
||||
_container->triggerEvent(_view->id(), e);
|
||||
_container->removeView(_view->id());
|
||||
this->deleteLater();
|
||||
if (_devtools != nullptr) {
|
||||
_devtools->deleteLater();
|
||||
}
|
||||
} else {
|
||||
evt->ignore();
|
||||
EventContainer e("can-close?");
|
||||
_container->triggerEvent(_view->id(), e);
|
||||
}
|
||||
}
|
||||
|
||||
void WebviewWindow::closeView()
|
||||
{
|
||||
_must_close = true;
|
||||
close();
|
||||
}
|
||||
|
||||
void WebviewWindow::addView(WebViewQt *v, Rktwebview_qt *c)
|
||||
@@ -41,9 +81,41 @@ void WebviewWindow::addView(WebViewQt *v, Rktwebview_qt *c)
|
||||
this->setCentralWidget(v);
|
||||
|
||||
QWebEnginePage *page = _view->page();
|
||||
|
||||
// Inject event handling code for the javascript side
|
||||
QWebEngineScriptCollection &col = page->scripts();
|
||||
QWebEngineScript evt_script;
|
||||
evt_script.setInjectionPoint(QWebEngineScript::DocumentReady);
|
||||
evt_script.setName("rkt_webview_event_handling");
|
||||
evt_script.setSourceCode(
|
||||
"window.rkt_event_queue = [];\n"
|
||||
"window.rkt_send_event = function(obj) {\n"
|
||||
" console.log('Sending event: ' + obj);\n"
|
||||
" window.rkt_event_queue.push(obj);\n"
|
||||
"};\n"
|
||||
"window.rkt_get_events = function() {\n"
|
||||
" let q = window.rkt_event_queue;\n"
|
||||
" window.rkt_event_queue = [];\n"
|
||||
" let json_q = JSON.stringify(q);\n"
|
||||
" return json_q;\n"
|
||||
"};\n"
|
||||
"console.log('We have set:');\n"
|
||||
"console.log('window.rkt_event_queue:');\n"
|
||||
"console.log(window.rkt_event_queue);\n"
|
||||
"console.log('window.rkt_send_event:');\n"
|
||||
"console.log(window.rkt_send_event);\n"
|
||||
"console.log('window.rkt_get_events:');\n"
|
||||
"console.log(window.rkt_get_events);\n"
|
||||
);
|
||||
evt_script.setWorldId(QWebEngineScript::ApplicationWorld);
|
||||
//col.insert(evt_script);
|
||||
|
||||
connect(page, &QWebEnginePage::loadFinished, this, [this](bool ok) {
|
||||
_container->pageLoaded(_view->id(), ok);
|
||||
});
|
||||
connect(page, &QWebEnginePage::loadStarted, this, [this]() {
|
||||
_container->onPageLoad(_view->id());
|
||||
});
|
||||
}
|
||||
|
||||
WebViewQt *WebviewWindow::view()
|
||||
@@ -51,9 +123,70 @@ WebViewQt *WebviewWindow::view()
|
||||
return _view;
|
||||
}
|
||||
|
||||
WebviewWindow::WebviewWindow(QWidget *parent)
|
||||
: QMainWindow{parent}
|
||||
void WebviewWindow::runJs(const QString &js)
|
||||
{
|
||||
_view = nullptr;
|
||||
connect(&_process_js_events, &QTimer::timeout, this, &WebviewWindow::processJsEvents);
|
||||
QWebEnginePage *p = _view->page();
|
||||
p->runJavaScript(js);
|
||||
}
|
||||
|
||||
void WebviewWindow::openDevTools()
|
||||
{
|
||||
_devtools = new QMainWindow(this);
|
||||
QWebEngineView *devtools_view = new QWebEngineView(_devtools);
|
||||
_devtools->setCentralWidget(devtools_view);
|
||||
_devtools->resize(800, 600);
|
||||
_devtools->show();
|
||||
_view->page()->setDevToolsPage(devtools_view->page());
|
||||
connect(_devtools, &WebviewWindow::destroyed, this, [this](QObject *) {
|
||||
_devtools = nullptr;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void WebviewWindow::moveEvent(QMoveEvent *event)
|
||||
{
|
||||
_x = event->pos().x();
|
||||
_y = event->pos().y();
|
||||
_move_timer.setSingleShot(true);
|
||||
_move_timer.start(500);
|
||||
}
|
||||
|
||||
void WebviewWindow::triggerMove()
|
||||
{
|
||||
EventContainer xy("move");
|
||||
xy["x"] = _x;
|
||||
xy["y"] = _y;
|
||||
_container->triggerEvent(_view->id(), xy);
|
||||
}
|
||||
|
||||
void WebviewWindow::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
_w = event->size().width();
|
||||
_h = event->size().height();
|
||||
_resize_timer.setSingleShot(true);
|
||||
_resize_timer.start(500);
|
||||
}
|
||||
|
||||
void WebviewWindow::triggerResize()
|
||||
{
|
||||
EventContainer s("resize");
|
||||
s["w"] = _w;
|
||||
s["h"] = _h;
|
||||
_container->triggerEvent(_view->id(), s);
|
||||
}
|
||||
|
||||
void WebviewWindow::showEvent(QShowEvent *event)
|
||||
{
|
||||
EventContainer show("show");
|
||||
_container->triggerEvent(_view->id(), show);
|
||||
}
|
||||
|
||||
void WebviewWindow::hideEvent(QHideEvent *event)
|
||||
{
|
||||
if (!_must_close) {
|
||||
EventContainer hide("hide");
|
||||
_container->triggerEvent(_view->id(), hide);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,16 @@ class WebviewWindow : public QMainWindow
|
||||
private:
|
||||
Rktwebview_qt *_container;
|
||||
WebViewQt *_view;
|
||||
QTimer _process_js_events;
|
||||
QMainWindow *_devtools;
|
||||
|
||||
QTimer _resize_timer;
|
||||
QTimer _move_timer;
|
||||
|
||||
int _x;
|
||||
int _y;
|
||||
int _w;
|
||||
int _h;
|
||||
bool _must_close;
|
||||
|
||||
public slots:
|
||||
void processJsEvents();
|
||||
@@ -22,14 +31,31 @@ protected:
|
||||
void closeEvent(QCloseEvent *evt);
|
||||
|
||||
public:
|
||||
void addView(WebViewQt *v, Rktwebview_qt *c);
|
||||
void closeView();
|
||||
|
||||
public:
|
||||
void addView(WebViewQt *v, Rktwebview_qt *c);
|
||||
WebViewQt *view();
|
||||
|
||||
public:
|
||||
void runJs(const QString &js);
|
||||
void openDevTools();
|
||||
|
||||
public:
|
||||
explicit WebviewWindow(QWidget *parent = nullptr);
|
||||
|
||||
private slots:
|
||||
void triggerResize();
|
||||
void triggerMove();
|
||||
|
||||
signals:
|
||||
|
||||
// QWidget interface
|
||||
protected:
|
||||
void moveEvent(QMoveEvent *event);
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
void showEvent(QShowEvent *event);
|
||||
void hideEvent(QHideEvent *event);
|
||||
};
|
||||
|
||||
#endif // WEBVIEWWINDOW_H
|
||||
|
||||
Reference in New Issue
Block a user