| | | 1 | | // SPDX-FileCopyrightText: 2026 Alper Çelik |
| | | 2 | | // SPDX-License-Identifier: MIT OR Apache-2.0 |
| | | 3 | | |
| | | 4 | | //! Webview declarations (owned by the webview worker). |
| | | 5 | | //! |
| | | 6 | | //! C++ translation units include the cxx-generated header for this bridge: |
| | | 7 | | //! `#include "tauri-runtime-qt/src/bridge/webview.rs.h"`. |
| | | 8 | | |
| | | 9 | | #[cxx::bridge] |
| | | 10 | | pub mod ffi { |
| | | 11 | | /// Live geometry of a webview widget, in **physical (device) pixels**. |
| | | 12 | | /// |
| | | 13 | | /// Qt reports widget geometry in device-independent pixels, so |
| | | 14 | | /// `qt_webview.cpp` multiplies by the widget's `devicePixelRatioF()` before |
| | | 15 | | /// filling this in. `ok == false` (all other fields zero) means the handle |
| | | 16 | | /// is unknown: Rust turns that into an `Err` instead of inventing numbers. |
| | | 17 | | struct QtWebviewGeometry { |
| | | 18 | | ok: bool, |
| | | 19 | | x: i32, |
| | | 20 | | y: i32, |
| | | 21 | | width: i32, |
| | | 22 | | height: i32, |
| | | 23 | | } |
| | | 24 | | |
| | | 25 | | unsafe extern "C++" { |
| | | 26 | | include!("qt_webview.hpp"); |
| | | 27 | | |
| | | 28 | | // ---- webviews (qt_webview.cpp) ---- |
| | 21 | 29 | | fn qt_webview_create(window_id: u64, url: &str) -> u64; |
| | | 30 | | /// Injects a tauri initialization script at document creation. |
| | 189 | 31 | | fn qt_webview_add_init_script(id: u64, script: &str, main_frame_only: bool); |
| | 21 | 32 | | fn qt_webview_native_handle(id: u64) -> u64; |
| | 21 | 33 | | fn qt_webview_navigate(id: u64, url: &str); |
| | 63 | 34 | | fn qt_webview_url(id: u64) -> String; |
| | 0 | 35 | | fn qt_webview_reload(id: u64); |
| | 0 | 36 | | fn qt_webview_eval(id: u64, script: &str); |
| | 0 | 37 | | fn qt_webview_set_zoom(id: u64, factor: f64); |
| | 0 | 38 | | fn qt_webview_set_background_color(id: u64, r: i32, g: i32, b: i32, a: i32); |
| | 0 | 39 | | fn qt_webview_show(id: u64); |
| | 0 | 40 | | fn qt_webview_hide(id: u64); |
| | 0 | 41 | | fn qt_webview_open_devtools(id: u64); |
| | 0 | 42 | | fn qt_webview_close_devtools(id: u64); |
| | 0 | 43 | | fn qt_webview_is_devtools_open(id: u64) -> bool; |
| | 0 | 44 | | fn qt_webview_print(id: u64); |
| | 0 | 45 | | fn qt_webview_close(id: u64); |
| | | 46 | | |
| | | 47 | | // ---- geometry / focus / reparenting ---- |
| | | 48 | | /// Live widget geometry in physical pixels (see `QtWebviewGeometry`). |
| | 0 | 49 | | fn qt_webview_geometry(id: u64) -> QtWebviewGeometry; |
| | | 50 | | /// Resizes the widget; `physical == true` means the caller passed |
| | | 51 | | /// physical pixels, which are divided by the widget's devicePixelRatio |
| | | 52 | | /// (`false` = Qt device-independent pixels, used as-is). `false` as a |
| | | 53 | | /// return value means the handle is unknown. The first positional call |
| | | 54 | | /// takes the view out of the window's layout (see `ops/webview.rs`). |
| | 0 | 55 | | fn qt_webview_set_size(id: u64, width: i32, height: i32, physical: bool) -> bool; |
| | | 56 | | /// Moves the widget relative to its parent window; same unit rule as |
| | | 57 | | /// `qt_webview_set_size`. |
| | 0 | 58 | | fn qt_webview_set_position(id: u64, x: i32, y: i32, physical: bool) -> bool; |
| | | 59 | | /// `QWebEngineView::setFocus()`. |
| | 0 | 60 | | fn qt_webview_set_focus(id: u64) -> bool; |
| | | 61 | | /// Runs `script` and delivers the result as a JSON string to |
| | | 62 | | /// `qt_on_eval_result(request_id, result)`. |
| | 0 | 63 | | fn qt_webview_eval_with_callback(id: u64, request_id: u64, script: &str) -> bool; |
| | | 64 | | /// Reparents the view into the window identified by the |
| | | 65 | | /// `qt_window_create` handle `window_native`. |
| | 0 | 66 | | fn qt_webview_reparent(id: u64, window_native: u64) -> bool; |
| | | 67 | | /// Clears the browsing data Qt can clear (HTTP cache, cookies, visited |
| | | 68 | | /// links); see the C++ implementation for what cannot be cleared. |
| | 0 | 69 | | fn qt_webview_clear_browsing_data(id: u64) -> bool; |
| | | 70 | | } |
| | | 71 | | |
| | | 72 | | extern "Rust" { |
| | | 73 | | /// Result of a `QWebEnginePage::runJavaScript` started by |
| | | 74 | | /// `qt_webview_eval_with_callback`, as a JSON string (`null` for an |
| | | 75 | | /// undefined/unrepresentable value). Called on the Qt GUI thread; |
| | | 76 | | /// `request_id` is the id Rust allocated. Unknown/expired ids are |
| | | 77 | | /// dropped. |
| | | 78 | | fn qt_on_eval_result(request_id: u64, result: &str); |
| | | 79 | | |
| | | 80 | | /// Diagnostic trigger: the first webview calls this once when its first |
| | | 81 | | /// page load finishes. Rust runs the `TAURIQT_EVAL_DEBUG` smoke test |
| | | 82 | | /// (`document.title = 'eval-ok'` through `eval_with_callback`) and does |
| | | 83 | | /// nothing when the environment variable is unset. |
| | | 84 | | fn qt_webview_on_first_load(webview_id: u64); |
| | | 85 | | } |
| | | 86 | | } |
| | | 87 | | |
| | | 88 | | /// Delivers a `runJavaScript` result to the webview area. |
| | | 89 | | /// |
| | | 90 | | /// cxx requires an `extern "Rust"` function to be defined in the module that |
| | | 91 | | /// declares the bridge, so this stays a thin forwarder and the pending-request |
| | | 92 | | /// registry lives with the rest of the webview logic in `crate::ops::webview`. |
| | 0 | 93 | | pub fn qt_on_eval_result(request_id: u64, result: &str) { |
| | 0 | 94 | | crate::ops::webview::on_eval_result(request_id, result); |
| | 0 | 95 | | } |
| | | 96 | | |
| | | 97 | | /// `TAURIQT_EVAL_DEBUG` smoke-test trigger; see |
| | | 98 | | /// `crate::ops::webview::debug_hook_first_load`. |
| | 21 | 99 | | pub fn qt_webview_on_first_load(webview_id: u64) { |
| | 21 | 100 | | crate::ops::webview::debug_hook_first_load(webview_id); |
| | 21 | 101 | | } |