#include "rktwebview_internal.h" #include #include #include #include //#include #include #include "rktwebview_qt.h" uint64_t current_ms() { using namespace std::chrono; return duration_cast(system_clock::now().time_since_epoch()).count(); } ///////////////////////////////////////////////////////////////////// // Main C Interface ///////////////////////////////////////////////////////////////////// //static int pipefd[2]; //static bool started = false; //static pid_t webview_process; //static bool cannot_fork_or_pipe = false; Rktwebview_qt *handler = nullptr; void destroyApp() { if (handler != nullptr) { QCoreApplication *app = QApplication::instance(); if (app != nullptr) { app->exit(0); delete app; } } } void rkt_webview_cleanup() { if (handler != nullptr) { rkt_webview_process_events(100); //QTimer app_quit; //QObject::connect(&app_quit, &QTimer::timeout, handler->app(), &QApplication::quit, Qt::ConnectionType::QueuedConnection); //app_quit.setSingleShot(true); //app_quit.start(250); //handler->app()->exec(); //fprintf(stderr, "cleanup: handler = %p\n", handler); // TODO // Do not delete the QApplication, although it will result in QThreadStorage warnings. // If the app is deleted, QtWebEngineProfileBuilder->createProfile will memory corrupt. //handler->deleteApp(); //delete handler; //handler = nullptr; //fprintf(stderr, "cleanup: handler = %p\n", handler); } } void rkt_webview_init() { if (handler == nullptr) { //fprintf(stderr, "init: handler = %p\n", handler); handler = new Rktwebview_qt(); //fprintf(stderr, "init: handler = %p\n", handler); atexit(destroyApp); } if (handler->app() == nullptr) { handler->initApp(); //QTimer app_exit; //QObject::connect(&app_exit, &QTimer::timeout, handler->app(), []() { // handler->app()->exit(0); //}, Qt::ConnectionType::QueuedConnection); //app_exit.setSingleShot(true); //app_exit.start(250); //QApplication *a = handler->app(); //a->exec(); } } rkt_wv_context_t rkt_webview_new_context(const char *boilerplate_js, const char *optional_server_cert_pem) { rkt_webview_init(); return handler->newContext(boilerplate_js, optional_server_cert_pem); } int rkt_webview_create(rkt_wv_context_t context, rktwebview_t parent, event_cb_t js_event_cb) { rkt_webview_init(); return handler->rktWebViewCreate(context, parent, js_event_cb); } void rkt_webview_close(rktwebview_t wv) { rkt_webview_init(); handler->rktWebViewClose(wv); } result_t rkt_webview_set_url(rktwebview_t wv, const char *url) { rkt_webview_init(); result_t r = handler->rktSetUrl(wv, url); return r; } result_t rkt_webview_set_html(rktwebview_t wv, const char *url) { 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; } rkt_data_t *rkt_webview_call_js(rktwebview_t wv, const char *js) { rkt_webview_init(); rkt_data_t *r = handler->rktCallJs(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(); uint64_t start_ms = current_ms(); uint64_t end_ms = start_ms + for_ms; while (current_ms() < end_ms) { QThread::usleep(500); // sleep 0.5 ms handler->doEvents(); } } 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); } result_t rkt_webview_hide(rktwebview_t w) { rkt_webview_init(); return handler->rktHideWindow(w); } result_t rkt_webview_show(rktwebview_t w) { rkt_webview_init(); return handler->rktShowWindow(w); } result_t rkt_webview_present(rktwebview_t w) { rkt_webview_init(); return handler->rktPresentWindow(w); } result_t rkt_webview_maximize(rktwebview_t w) { rkt_webview_init(); return handler->rktMaximizeWindow(w); } result_t rkt_webview_minimize(rktwebview_t w) { rkt_webview_init(); return handler->rktMinimizeWindow(w); } result_t rkt_webview_show_normal(rktwebview_t w) { rkt_webview_init(); return handler->rktShowNormalWindow(w); } window_state_t rkt_webview_window_state(rktwebview_t w) { rkt_webview_init(); return handler->rktWindowState(w); } result_t rkt_webview_set_title(rktwebview_t wv, const char *title) { rkt_webview_init(); return handler->rktWindowSetTitle(wv, title); } result_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); } result_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); } result_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); } 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; } result_t rkt_webview_message_box(rktwebview_t w, const char *title, const char *message, const char *submessage, rkt_messagetype_t type) { rkt_webview_init(); return handler->rktMessageBox(w, title, message, submessage, type); }