diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d212e21aa..f34211177 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,13 +23,13 @@ jobs: # We only run `cargo build` (not `cargo test`) so as to avoid requiring dev-dependencies to build with the MSRV # version. Building is likely sufficient as runtime errors varying between rust versions is very unlikely. build-msrv: - name: "MSRV Build [Rust 1.88]" + name: "MSRV Build [Rust 1.89]" runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master with: - toolchain: 1.88 + toolchain: 1.89 - run: perl -pi.bak -e 's/opt-level = 2/opt-level = 0/g' Cargo.toml - uses: awalsh128/cache-apt-pkgs-action@latest with: @@ -130,6 +130,7 @@ jobs: env: RUST_CARGO_COMMAND: ${{ matrix.platform.cross == true && 'cross' || 'cargo' }} strategy: + fail-fast: false matrix: platform: - { @@ -156,6 +157,22 @@ jobs: command: "test", args: "--all --tests", } + - { + name: ios, + target: aarch64-apple-ios, + os: macos-latest, + cross: false, + command: "build", + args: "--all", + } + - { + name: android, + target: aarch64-linux-android, + os: ubuntu-latest, + cross: true, + command: "build", + args: "--all", + } name: Test (${{ matrix.platform.name }}) @@ -190,9 +207,13 @@ jobs: if: ${{ matrix.platform.os == 'ubuntu-latest' }} uses: awalsh128/cache-apt-pkgs-action@latest with: - packages: libasound2-dev libatk1.0-dev libgtk-3-dev libudev-dev libpango1.0-dev libxdo-dev + packages: libasound2-dev libatk1.0-dev libgtk-3-dev libudev-dev libpango1.0-dev libxdo-dev libssl-dev version: 1.0 + - name: Install cross + if: ${{ matrix.platform.cross == true }} + uses: taiki-e/install-action@cross + - name: Setup run: ${{ matrix.platform.setup }} shell: bash diff --git a/Cargo.lock b/Cargo.lock index 1888413d8..26a1efd87 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,44 +20,54 @@ checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" [[package]] name = "accesskit" -version = "0.17.1" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eca13c82f9a5cd813120b2e9b6a5d10532c6e4cd140c295cebd1f770095c8a5" + +[[package]] +name = "accesskit_android" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3d3b8f9bae46a948369bc4a03e815d4ed6d616bd00de4051133a5019dc31c5a" +checksum = "d28b60a573c7165b1eb346d66c14e85a1f7923fe2e71e396ce936ca6afb519ae" +dependencies = [ + "accesskit", + "accesskit_consumer", + "jni", + "log", +] [[package]] name = "accesskit_atspi_common" -version = "0.10.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c5dd55e6e94949498698daf4d48fb5659e824d7abec0d394089656ceaf99d4f" +checksum = "3eb9cc46b7fb6987c4f891f0301b230b29d9e69b4854f060a0cf41fbc407ab77" dependencies = [ "accesskit", "accesskit_consumer", "atspi-common", "serde", - "thiserror 1.0.69", - "zvariant 4.2.0", + "zvariant", ] [[package]] name = "accesskit_consumer" -version = "0.26.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f47983a1084940ba9a39c077a8c63e55c619388be5476ac04c804cfbd1e63459" +checksum = "69d880a613f29621c90e801feec40f5dd61d837d7e20bf9b67676d45e7364a36" dependencies = [ "accesskit", - "hashbrown 0.15.5", - "immutable-chunkmap", + "hashbrown 0.16.1", ] [[package]] name = "accesskit_macos" -version = "0.18.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7329821f3bd1101e03a7d2e03bd339e3ac0dc64c70b4c9f9ae1949e3ba8dece1" +checksum = "5b0ddfc3fe3d457d11cc1c4989105986a03583a1d54d0c25053118944b62e100" dependencies = [ "accesskit", "accesskit_consumer", - "hashbrown 0.15.5", + "hashbrown 0.16.1", "objc2 0.5.2", "objc2-app-kit 0.2.2", "objc2-foundation 0.2.2", @@ -65,9 +75,9 @@ dependencies = [ [[package]] name = "accesskit_unix" -version = "0.13.1" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcee751cc20d88678c33edaf9c07e8b693cd02819fe89053776f5313492273f5" +checksum = "d5d552169ef018149966ed139bb0311c6947b3343e9140d1b9f88d69da9528fd" dependencies = [ "accesskit", "accesskit_atspi_common", @@ -78,36 +88,37 @@ dependencies = [ "futures-lite", "futures-util", "serde", - "zbus 4.4.0", + "tokio", + "tokio-stream", + "zbus", ] [[package]] name = "accesskit_windows" -version = "0.24.1" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24fcd5d23d70670992b823e735e859374d694a3d12bfd8dd32bd3bd8bedb5d81" +checksum = "d277279d0a3b0c0021dd110b55aa1fe326b09ee2cbc338df28f847c7daf94e25" dependencies = [ "accesskit", "accesskit_consumer", - "hashbrown 0.15.5", - "paste", + "hashbrown 0.16.1", "static_assertions", - "windows 0.58.0", - "windows-core 0.58.0", + "windows 0.61.3", + "windows-core 0.61.2", ] [[package]] -name = "accesskit_winit" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6a48dad5530b6deb9fc7a52cc6c3bf72cdd9eb8157ac9d32d69f2427a5e879" +name = "accesskit_xplat" +version = "0.1.0" dependencies = [ "accesskit", + "accesskit_android", "accesskit_macos", "accesskit_unix", "accesskit_windows", + "android-activity", "raw-window-handle", - "winit", + "winit-core", ] [[package]] @@ -264,9 +275,9 @@ dependencies = [ [[package]] name = "anyrender_skia" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cd23fede1c9b592693a3d6213eb8a4c3eb3855c5ccf6cd32c2babbc68c70a31" +checksum = "a462fde618a4394fdb9618a5e4733357f9a1c5b99b17c98704234461449e61b3" dependencies = [ "anyrender", "ash 0.38.0+1.3.281", @@ -282,6 +293,7 @@ dependencies = [ "objc2-core-foundation", "objc2-metal 0.3.2", "objc2-quartz-core 0.3.2", + "objc2-ui-kit", "peniko", "pixels_window_renderer", "raw-window-handle", @@ -436,7 +448,7 @@ dependencies = [ "enumflags2", "futures-channel", "futures-util", - "rand 0.9.2", + "rand", "raw-window-handle", "serde", "serde_repr", @@ -445,7 +457,7 @@ dependencies = [ "wayland-backend", "wayland-client", "wayland-protocols", - "zbus 5.12.0", + "zbus", ] [[package]] @@ -486,17 +498,6 @@ dependencies = [ "slab", ] -[[package]] -name = "async-fs" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5" -dependencies = [ - "async-lock", - "blocking", - "futures-lite", -] - [[package]] name = "async-io" version = "2.6.0" @@ -610,53 +611,39 @@ checksum = "41e67cd8309bbd06cd603a9e693a784ac2e5d1e955f11286e355089fcab3047c" [[package]] name = "atspi" -version = "0.22.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be534b16650e35237bb1ed189ba2aab86ce65e88cc84c66f4935ba38575cecbf" +checksum = "c77886257be21c9cd89a4ae7e64860c6f0eefca799bb79127913052bd0eefb3d" dependencies = [ "atspi-common", - "atspi-connection", "atspi-proxies", ] [[package]] name = "atspi-common" -version = "0.6.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1909ed2dc01d0a17505d89311d192518507e8a056a48148e3598fef5e7bb6ba7" +checksum = "20c5617155740c98003016429ad13fe43ce7a77b007479350a9f8bf95a29f63d" dependencies = [ "enumflags2", "serde", "static_assertions", - "zbus 4.4.0", + "zbus", "zbus-lockstep", "zbus-lockstep-macros", - "zbus_names 3.0.0", - "zvariant 4.2.0", -] - -[[package]] -name = "atspi-connection" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "430c5960624a4baaa511c9c0fcc2218e3b58f5dbcc47e6190cafee344b873333" -dependencies = [ - "atspi-common", - "atspi-proxies", - "futures-lite", - "zbus 4.4.0", + "zbus_names", + "zvariant", ] [[package]] name = "atspi-proxies" -version = "0.6.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e6c5de3e524cf967569722446bcd458d5032348554d9a17d7d72b041ab7496" +checksum = "2230e48787ed3eb4088996eab66a32ca20c0b67bbd4fd6cdfe79f04f1f04c9fc" dependencies = [ "atspi-common", "serde", - "zbus 4.4.0", - "zvariant 4.2.0", + "zbus", ] [[package]] @@ -805,7 +792,7 @@ dependencies = [ "fastrand", "html-escape", "image", - "keyboard-types", + "keyboard-types 0.7.0", "linebender_resource_handle", "markup5ever", "objc2 0.6.3", @@ -904,7 +891,7 @@ name = "blitz-shell" version = "0.2.2" dependencies = [ "accesskit", - "accesskit_winit", + "accesskit_xplat", "android-activity", "anyrender", "arboard", @@ -913,7 +900,7 @@ dependencies = [ "blitz-traits", "data-url", "futures-util", - "keyboard-types", + "keyboard-types 0.7.0", "rfd", "tracing", "winit", @@ -927,7 +914,7 @@ dependencies = [ "bytes", "cursor-icon", "http", - "keyboard-types", + "keyboard-types 0.7.0", "serde", "smol_str", "url", @@ -979,6 +966,15 @@ dependencies = [ "piper", ] +[[package]] +name = "borsh" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1da5ab77c1437701eeff7c88d968729e7766172279eab0676857b3d63af7a6f" +dependencies = [ + "cfg_aliases 0.2.1", +] + [[package]] name = "brotli-decompressor" version = "5.0.0" @@ -993,6 +989,7 @@ dependencies = [ name = "browser" version = "0.0.0" dependencies = [ + "android-activity", "blitz-dom", "blitz-html", "blitz-net", @@ -1001,6 +998,7 @@ dependencies = [ "linebender_resource_handle", "tracing-subscriber", "webbrowser", + "winit", ] [[package]] @@ -1093,26 +1091,25 @@ dependencies = [ [[package]] name = "calloop" -version = "0.13.0" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +checksum = "cb9f6e1368bd4621d2c86baa7e37de77a938adf5221e5dd3d6133340101b309e" dependencies = [ "bitflags 2.10.0", - "log", "polling", - "rustix 0.38.44", + "rustix 1.1.2", "slab", - "thiserror 1.0.69", + "tracing", ] [[package]] name = "calloop-wayland-source" -version = "0.3.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" +checksum = "138efcf0940a02ebf0cc8d1eff41a1682a46b431630f4c52450d6265876021fa" dependencies = [ "calloop", - "rustix 0.38.44", + "rustix 1.1.2", "wayland-backend", "wayland-client", ] @@ -1232,7 +1229,7 @@ dependencies = [ "cocoa-foundation", "core-foundation 0.9.4", "core-graphics", - "foreign-types 0.5.0", + "foreign-types", "libc", "objc", ] @@ -1480,7 +1477,7 @@ dependencies = [ "bitflags 1.3.2", "core-foundation 0.9.4", "core-graphics-types 0.1.3", - "foreign-types 0.5.0", + "foreign-types", "libc", ] @@ -1519,6 +1516,7 @@ dependencies = [ name = "counter" version = "0.1.0" dependencies = [ + "android-activity", "blitz-dom", "blitz-paint", "dioxus-native", @@ -2007,7 +2005,7 @@ dependencies = [ "futures-channel", "futures-util", "generational-box", - "keyboard-types", + "keyboard-types 0.7.0", "lazy-js-bundle", "rustversion", "serde", @@ -2085,7 +2083,7 @@ dependencies = [ "dioxus-signals", "dioxus-stores", "futures-util", - "keyboard-types", + "keyboard-types 0.7.0", "manganis", "rustc-hash 1.1.0", "tokio", @@ -2104,7 +2102,7 @@ dependencies = [ "dioxus-core", "dioxus-html", "futures-util", - "keyboard-types", + "keyboard-types 0.7.0", "rustc-hash 1.1.0", "tracing", ] @@ -2216,12 +2214,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - [[package]] name = "dispatch2" version = "0.3.0" @@ -2626,15 +2618,6 @@ dependencies = [ "yeslogic-fontconfig-sys", ] -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared 0.1.1", -] - [[package]] name = "foreign-types" version = "0.5.0" @@ -2642,7 +2625,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" dependencies = [ "foreign-types-macros", - "foreign-types-shared 0.3.1", + "foreign-types-shared", ] [[package]] @@ -2656,12 +2639,6 @@ dependencies = [ "syn 2.0.111", ] -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "foreign-types-shared" version = "0.3.1" @@ -2836,7 +2813,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" dependencies = [ "rustix 1.1.2", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -2855,8 +2832,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -2866,9 +2845,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi", "wasip2", + "wasm-bindgen", ] [[package]] @@ -3395,22 +3376,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", -] - -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", + "webpki-roots", ] [[package]] @@ -3432,11 +3398,9 @@ dependencies = [ "percent-encoding", "pin-project-lite", "socket2", - "system-configuration", "tokio", "tower-service", "tracing", - "windows-registry", ] [[package]] @@ -3584,15 +3548,6 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edcd27d72f2f071c64249075f42e205ff93c9a4c5f6c6da53e79ed9f9832c285" -[[package]] -name = "immutable-chunkmap" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3e98b1520e49e252237edc238a39869da9f3241f2ec19dc788c1d24694d1e4" -dependencies = [ - "arrayvec", -] - [[package]] name = "indexmap" version = "2.12.1" @@ -3761,6 +3716,16 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "keyboard-types" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fbe853b403ae61a04233030ae8a79d94975281ed9770a1f9e246732b534b28d" +dependencies = [ + "bitflags 2.10.0", + "serde", +] + [[package]] name = "khronos-egl" version = "6.0.0" @@ -3855,7 +3820,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -3932,6 +3897,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3bd0dd2cd90571056fdb71f6275fada10131182f84899f4b2a916e565d81d86" +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "mac" version = "0.1.1" @@ -4083,7 +4054,7 @@ dependencies = [ "bitflags 2.10.0", "block", "core-graphics-types 0.1.3", - "foreign-types 0.5.0", + "foreign-types", "log", "objc", "paste", @@ -4098,7 +4069,7 @@ dependencies = [ "bitflags 2.10.0", "block", "core-graphics-types 0.2.0", - "foreign-types 0.5.0", + "foreign-types", "log", "objc", "paste", @@ -4231,23 +4202,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "native-tls" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "ndk" version = "0.9.0" @@ -4293,19 +4247,6 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" -[[package]] -name = "nix" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" -dependencies = [ - "bitflags 2.10.0", - "cfg-if", - "cfg_aliases 0.2.1", - "libc", - "memoffset", -] - [[package]] name = "nix" version = "0.30.1" @@ -4526,19 +4467,6 @@ dependencies = [ "objc2-quartz-core 0.3.2", ] -[[package]] -name = "objc2-cloud-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" -dependencies = [ - "bitflags 2.10.0", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-core-location 0.2.2", - "objc2-foundation 0.2.2", -] - [[package]] name = "objc2-cloud-kit" version = "0.3.2" @@ -4550,17 +4478,6 @@ dependencies = [ "objc2-foundation 0.3.2", ] -[[package]] -name = "objc2-contacts" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" -dependencies = [ - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", -] - [[package]] name = "objc2-core-data" version = "0.2.2" @@ -4590,6 +4507,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ "bitflags 2.10.0", + "block2 0.6.2", "dispatch2", "objc2 0.6.3", ] @@ -4602,6 +4520,7 @@ checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ "bitflags 2.10.0", "dispatch2", + "libc", "objc2 0.6.3", "objc2-core-foundation", "objc2-io-surface", @@ -4629,18 +4548,6 @@ dependencies = [ "objc2-foundation 0.3.2", ] -[[package]] -name = "objc2-core-location" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" -dependencies = [ - "block2 0.5.1", - "objc2 0.5.2", - "objc2-contacts", - "objc2-foundation 0.2.2", -] - [[package]] name = "objc2-core-location" version = "0.3.2" @@ -4663,6 +4570,17 @@ dependencies = [ "objc2-core-graphics", ] +[[package]] +name = "objc2-core-video" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6" +dependencies = [ + "bitflags 2.10.0", + "objc2-core-foundation", + "objc2-core-graphics", +] + [[package]] name = "objc2-encode" version = "4.1.0" @@ -4677,7 +4595,6 @@ checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ "bitflags 2.10.0", "block2 0.5.1", - "dispatch", "libc", "objc2 0.5.2", ] @@ -4706,18 +4623,6 @@ dependencies = [ "objc2-core-foundation", ] -[[package]] -name = "objc2-link-presentation" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" -dependencies = [ - "block2 0.5.1", - "objc2 0.5.2", - "objc2-app-kit 0.2.2", - "objc2-foundation 0.2.2", -] - [[package]] name = "objc2-metal" version = "0.2.2" @@ -4767,37 +4672,6 @@ dependencies = [ "objc2-metal 0.3.2", ] -[[package]] -name = "objc2-symbols" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" -dependencies = [ - "objc2 0.5.2", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "objc2-ui-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" -dependencies = [ - "bitflags 2.10.0", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-cloud-kit 0.2.2", - "objc2-core-data 0.2.2", - "objc2-core-image 0.2.2", - "objc2-core-location 0.2.2", - "objc2-foundation 0.2.2", - "objc2-link-presentation", - "objc2-quartz-core 0.2.2", - "objc2-symbols", - "objc2-uniform-type-identifiers", - "objc2-user-notifications 0.2.2", -] - [[package]] name = "objc2-ui-kit" version = "0.3.2" @@ -4807,40 +4681,16 @@ dependencies = [ "bitflags 2.10.0", "block2 0.6.2", "objc2 0.6.3", - "objc2-cloud-kit 0.3.2", + "objc2-cloud-kit", "objc2-core-data 0.3.2", "objc2-core-foundation", "objc2-core-graphics", "objc2-core-image 0.3.2", - "objc2-core-location 0.3.2", + "objc2-core-location", "objc2-core-text", "objc2-foundation 0.3.2", "objc2-quartz-core 0.3.2", - "objc2-user-notifications 0.3.2", -] - -[[package]] -name = "objc2-uniform-type-identifiers" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" -dependencies = [ - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "objc2-user-notifications" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" -dependencies = [ - "bitflags 2.10.0", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-core-location 0.2.2", - "objc2-foundation 0.2.2", + "objc2-user-notifications", ] [[package]] @@ -4875,58 +4725,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] -name = "openssl" -version = "0.10.75" +name = "option-ext" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" -dependencies = [ - "bitflags 2.10.0", - "cfg-if", - "foreign-types 0.3.2", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.111", -] - -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - -[[package]] -name = "openssl-sys" -version = "0.9.111" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" - -[[package]] -name = "orbclient" -version = "0.3.49" +name = "orbclient" +version = "0.3.49" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "247ad146e19b9437f8604c21f8652423595cf710ad108af40e77d3ae6e96b827" dependencies = [ @@ -4969,10 +4775,10 @@ checksum = "e4022a17595a00d6a369236fdae483f0de7f0a339960a53118b818238e132224" dependencies = [ "android_system_properties", "log", - "nix 0.30.1", + "nix", "objc2 0.6.3", "objc2-foundation 0.3.2", - "objc2-ui-kit 0.3.2", + "objc2-ui-kit", "serde", "windows-sys 0.61.2", ] @@ -5018,7 +4824,7 @@ dependencies = [ "libc", "redox_syscall 0.5.18", "smallvec", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -5372,9 +5178,9 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quick-xml" -version = "0.30.0" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" dependencies = [ "memchr", "serde", @@ -5390,49 +5196,83 @@ dependencies = [ ] [[package]] -name = "quote" -version = "1.0.42" +name = "quinn" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" dependencies = [ - "proc-macro2", + "bytes", + "cfg_aliases 0.2.1", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.1.1", + "rustls", + "socket2", + "thiserror 2.0.17", + "tokio", + "tracing", + "web-time", ] [[package]] -name = "r-efi" -version = "5.3.0" +name = "quinn-proto" +version = "0.11.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +dependencies = [ + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand", + "ring", + "rustc-hash 2.1.1", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.17", + "tinyvec", + "tracing", + "web-time", +] [[package]] -name = "rand" -version = "0.8.5" +name = "quinn-udp" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" dependencies = [ + "cfg_aliases 0.2.1", "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", ] [[package]] -name = "rand" -version = "0.9.2" +name = "quote" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.3", + "proc-macro2", ] [[package]] -name = "rand_chacha" -version = "0.3.1" +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", + "rand_chacha", + "rand_core", ] [[package]] @@ -5442,16 +5282,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.3", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.16", + "rand_core", ] [[package]] @@ -5542,15 +5373,6 @@ dependencies = [ "winit", ] -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.5.18" @@ -5646,22 +5468,22 @@ dependencies = [ "http-body-util", "hyper", "hyper-rustls", - "hyper-tls", "hyper-util", "js-sys", "log", "mime", "mime_guess", - "native-tls", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-native-tls", + "tokio-rustls", "tokio-util", "tower", "tower-http", @@ -5671,6 +5493,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", + "webpki-roots", ] [[package]] @@ -5795,6 +5618,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" dependencies = [ "once_cell", + "ring", "rustls-pki-types", "rustls-webpki", "subtle", @@ -5807,6 +5631,7 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282" dependencies = [ + "web-time", "zeroize", ] @@ -5869,15 +5694,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "schannel" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" -dependencies = [ - "windows-sys 0.61.2", -] - [[package]] name = "scoped-tls" version = "1.0.1" @@ -5892,9 +5708,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sctk-adwaita" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" +checksum = "1dd3accc0f3f4bbaf2c9e1957a030dc582028130c67660d44c0a0345a22ca69b" dependencies = [ "ab_glyph", "log", @@ -5903,29 +5719,6 @@ dependencies = [ "tiny-skia", ] -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.10.0", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "selectors" version = "0.33.0" @@ -6242,9 +6035,9 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "smithay-client-toolkit" -version = "0.19.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" +checksum = "0512da38f5e2b31201a93524adb8d3136276fa4fe4aafab4e1f727a82b534cc0" dependencies = [ "bitflags 2.10.0", "calloop", @@ -6253,13 +6046,15 @@ dependencies = [ "libc", "log", "memmap2 0.9.9", - "rustix 0.38.44", - "thiserror 1.0.69", + "rustix 1.1.2", + "thiserror 2.0.17", "wayland-backend", "wayland-client", "wayland-csd-frame", "wayland-cursor", "wayland-protocols", + "wayland-protocols-experimental", + "wayland-protocols-misc", "wayland-protocols-wlr", "wayland-scanner", "xkeysym", @@ -6267,11 +6062,12 @@ dependencies = [ [[package]] name = "smol_str" -version = "0.2.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" +checksum = "3498b0a27f93ef1402f20eefacfaa1691272ac4eca1cdc8c596cb0a245d6cbf5" dependencies = [ - "serde", + "borsh", + "serde_core", ] [[package]] @@ -6660,27 +6456,6 @@ dependencies = [ "syn 2.0.111", ] -[[package]] -name = "system-configuration" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" -dependencies = [ - "bitflags 2.10.0", - "core-foundation 0.9.4", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "system-deps" version = "7.0.7" @@ -6942,6 +6717,7 @@ dependencies = [ name = "todomvc" version = "0.1.0" dependencies = [ + "android-activity", "dioxus-native", "idna_adapter", "tracing-subscriber", @@ -6975,16 +6751,6 @@ dependencies = [ "syn 2.0.111", ] -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.4" @@ -7145,6 +6911,7 @@ version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -7237,7 +7004,7 @@ dependencies = [ "http", "httparse", "log", - "rand 0.9.2", + "rand", "sha1", "thiserror 2.0.17", "utf-8", @@ -7463,12 +7230,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "vello" version = "0.6.0" @@ -7771,6 +7532,32 @@ dependencies = [ "wayland-scanner", ] +[[package]] +name = "wayland-protocols-experimental" +version = "20250721.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40a1f863128dcaaec790d7b4b396cc9b9a7a079e878e18c47e6c2d2c5a8dcbb1" +dependencies = [ + "bitflags 2.10.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-misc" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfe33d551eb8bffd03ff067a8b44bb963919157841a99957151299a6307d19c" +dependencies = [ + "bitflags 2.10.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + [[package]] name = "wayland-protocols-plasma" version = "0.3.9" @@ -7868,6 +7655,15 @@ dependencies = [ "web-sys", ] +[[package]] +name = "webpki-roots" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "weezl" version = "0.1.12" @@ -8225,16 +8021,38 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections 0.2.0", + "windows-core 0.61.2", + "windows-future 0.2.1", + "windows-link 0.1.3", + "windows-numerics 0.2.0", +] + [[package]] name = "windows" version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" dependencies = [ - "windows-collections", + "windows-collections 0.3.2", "windows-core 0.62.2", - "windows-future", - "windows-numerics", + "windows-future 0.3.2", + "windows-numerics 0.3.1", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core 0.61.2", ] [[package]] @@ -8268,6 +8086,19 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement 0.60.2", + "windows-interface 0.59.3", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + [[package]] name = "windows-core" version = "0.62.2" @@ -8276,11 +8107,22 @@ checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement 0.60.2", "windows-interface 0.59.3", - "windows-link", + "windows-link 0.2.1", "windows-result 0.4.1", "windows-strings 0.5.1", ] +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", + "windows-threading 0.1.0", +] + [[package]] name = "windows-future" version = "0.3.2" @@ -8288,8 +8130,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" dependencies = [ "windows-core 0.62.2", - "windows-link", - "windows-threading", + "windows-link 0.2.1", + "windows-threading 0.2.1", ] [[package]] @@ -8336,6 +8178,12 @@ dependencies = [ "syn 2.0.111", ] +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + [[package]] name = "windows-link" version = "0.2.1" @@ -8344,23 +8192,22 @@ checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-numerics" -version = "0.3.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" dependencies = [ - "windows-core 0.62.2", - "windows-link", + "windows-core 0.61.2", + "windows-link 0.1.3", ] [[package]] -name = "windows-registry" -version = "0.6.1" +name = "windows-numerics" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" dependencies = [ - "windows-link", - "windows-result 0.4.1", - "windows-strings 0.5.1", + "windows-core 0.62.2", + "windows-link 0.2.1", ] [[package]] @@ -8372,13 +8219,22 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", +] + [[package]] name = "windows-result" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -8391,13 +8247,22 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", +] + [[package]] name = "windows-strings" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -8442,7 +8307,7 @@ version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -8482,7 +8347,7 @@ version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link", + "windows-link 0.2.1", "windows_aarch64_gnullvm 0.53.1", "windows_aarch64_msvc 0.53.1", "windows_i686_gnu 0.53.1", @@ -8493,13 +8358,22 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link 0.1.3", +] + [[package]] name = "windows-threading" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" dependencies = [ - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -8642,51 +8516,224 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winit" -version = "0.30.12" +version = "0.31.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66d4b9ed69c4009f6321f762d6e61ad8a2389cd431b97cb1e146812e9e6c732" +checksum = "2879d2854d1a43e48f67322d4bd097afcb6eb8f8f775c8de0260a71aea1df1aa" dependencies = [ - "ahash", - "android-activity", - "atomic-waker", "bitflags 2.10.0", - "block2 0.5.1", - "bytemuck", - "calloop", "cfg_aliases 0.2.1", - "concurrent-queue", - "core-foundation 0.9.4", - "core-graphics", "cursor-icon", "dpi", - "js-sys", "libc", - "memmap2 0.9.9", + "raw-window-handle", + "rustix 1.1.2", + "smol_str", + "tracing", + "winit-android", + "winit-appkit", + "winit-common", + "winit-core", + "winit-orbital", + "winit-uikit", + "winit-wayland", + "winit-web", + "winit-win32", + "winit-x11", +] + +[[package]] +name = "winit-android" +version = "0.31.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d9c0d2cd93efec3a9f9ad819cfaf0834782403af7c0d248c784ec0c61761df" +dependencies = [ + "android-activity", + "bitflags 2.10.0", + "dpi", "ndk", - "objc2 0.5.2", - "objc2-app-kit 0.2.2", - "objc2-foundation 0.2.2", - "objc2-ui-kit 0.2.2", + "raw-window-handle", + "smol_str", + "tracing", + "winit-core", +] + +[[package]] +name = "winit-appkit" +version = "0.31.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21310ca07851a49c348e0c2cc768e36b52ca65afda2c2354d78ed4b90074d8aa" +dependencies = [ + "bitflags 2.10.0", + "block2 0.6.2", + "dispatch2", + "dpi", + "objc2 0.6.3", + "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-video", + "objc2-foundation 0.3.2", + "raw-window-handle", + "smol_str", + "tracing", + "winit-common", + "winit-core", +] + +[[package]] +name = "winit-common" +version = "0.31.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45375fbac4cbb77260d83a30b1f9d8105880dbac99a9ae97f56656694680ff69" +dependencies = [ + "memmap2 0.9.9", + "objc2 0.6.3", + "objc2-core-foundation", + "smol_str", + "tracing", + "winit-core", + "x11-dl", + "xkbcommon-dl", +] + +[[package]] +name = "winit-core" +version = "0.31.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4f0ccd7abb43740e2c6124ac7cae7d865ecec74eec63783e8922577ac232583" +dependencies = [ + "bitflags 2.10.0", + "cursor-icon", + "dpi", + "keyboard-types 0.8.3", + "raw-window-handle", + "smol_str", + "web-time", +] + +[[package]] +name = "winit-orbital" +version = "0.31.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51ea1fb262e7209f265f12bd0cc792c399b14355675e65531e9c8a87db287d46" +dependencies = [ + "bitflags 2.10.0", + "dpi", "orbclient", - "percent-encoding", - "pin-project", "raw-window-handle", - "redox_syscall 0.4.1", - "rustix 0.38.44", + "redox_syscall 0.5.18", + "smol_str", + "tracing", + "winit-core", +] + +[[package]] +name = "winit-uikit" +version = "0.31.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "680a356e798837d8eb274d4556e83bceaf81698194e31aafc5cfb8a9f2fab643" +dependencies = [ + "bitflags 2.10.0", + "block2 0.6.2", + "dispatch2", + "dpi", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-ui-kit", + "raw-window-handle", + "smol_str", + "tracing", + "winit-common", + "winit-core", +] + +[[package]] +name = "winit-wayland" +version = "0.31.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce5afb2ba07da603f84b722c95f9f9396d2cedae3944fb6c0cda4a6f88de545" +dependencies = [ + "ahash", + "bitflags 2.10.0", + "calloop", + "cursor-icon", + "dpi", + "libc", + "memmap2 0.9.9", + "raw-window-handle", + "rustix 1.1.2", "sctk-adwaita", "smithay-client-toolkit", "smol_str", "tracing", - "unicode-segmentation", - "wasm-bindgen", - "wasm-bindgen-futures", "wayland-backend", "wayland-client", "wayland-protocols", "wayland-protocols-plasma", + "winit-common", + "winit-core", +] + +[[package]] +name = "winit-web" +version = "0.31.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c2490a953fb776fbbd5e295d54f1c3847f4f15b6c3929ec53c09acda6487a92" +dependencies = [ + "atomic-waker", + "bitflags 2.10.0", + "concurrent-queue", + "cursor-icon", + "dpi", + "js-sys", + "pin-project", + "raw-window-handle", + "smol_str", + "tracing", + "wasm-bindgen", + "wasm-bindgen-futures", "web-sys", "web-time", - "windows-sys 0.52.0", + "winit-core", +] + +[[package]] +name = "winit-win32" +version = "0.31.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "644ea78af0e858aa3b092e5d1c67c41995a98220c81813f1353b28bc8bb91eaa" +dependencies = [ + "bitflags 2.10.0", + "cursor-icon", + "dpi", + "raw-window-handle", + "smol_str", + "tracing", + "unicode-segmentation", + "windows-sys 0.59.0", + "winit-core", +] + +[[package]] +name = "winit-x11" +version = "0.31.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa5b600756534c7041aa93cd0d244d44b09fca1b89e202bd1cd80dd9f3636c46" +dependencies = [ + "bitflags 2.10.0", + "bytemuck", + "calloop", + "cursor-icon", + "dpi", + "libc", + "percent-encoding", + "raw-window-handle", + "rustix 1.1.2", + "smol_str", + "tracing", + "winit-common", + "winit-core", "x11-dl", "x11rb", "xkbcommon-dl", @@ -8807,6 +8854,7 @@ dependencies = [ "once_cell", "rustix 1.1.2", "x11rb-protocol", + "xcursor", ] [[package]] @@ -8831,16 +8879,6 @@ version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" -[[package]] -name = "xdg-home" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - [[package]] name = "xkbcommon-dl" version = "0.4.2" @@ -8930,13 +8968,12 @@ dependencies = [ [[package]] name = "zbus" -version = "4.4.0" +version = "5.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725" +checksum = "b622b18155f7a93d1cd2dc8c01d2d6a44e08fb9ebb7b3f9e6ed101488bad6c91" dependencies = [ "async-broadcast", "async-executor", - "async-fs", "async-io", "async-lock", "async-process", @@ -8947,40 +8984,9 @@ dependencies = [ "enumflags2", "event-listener", "futures-core", - "futures-sink", - "futures-util", - "hex", - "nix 0.29.0", - "ordered-stream", - "rand 0.8.5", - "serde", - "serde_repr", - "sha1", - "static_assertions", - "tracing", - "uds_windows", - "windows-sys 0.52.0", - "xdg-home", - "zbus_macros 4.4.0", - "zbus_names 3.0.0", - "zvariant 4.2.0", -] - -[[package]] -name = "zbus" -version = "5.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b622b18155f7a93d1cd2dc8c01d2d6a44e08fb9ebb7b3f9e6ed101488bad6c91" -dependencies = [ - "async-broadcast", - "async-recursion", - "async-trait", - "enumflags2", - "event-listener", - "futures-core", "futures-lite", "hex", - "nix 0.30.1", + "nix", "ordered-stream", "serde", "serde_repr", @@ -8990,46 +8996,33 @@ dependencies = [ "uuid", "windows-sys 0.61.2", "winnow", - "zbus_macros 5.12.0", - "zbus_names 4.2.0", - "zvariant 5.8.0", + "zbus_macros", + "zbus_names", + "zvariant", ] [[package]] name = "zbus-lockstep" -version = "0.4.4" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca2c5dceb099bddaade154055c926bb8ae507a18756ba1d8963fd7b51d8ed1d" +checksum = "6998de05217a084b7578728a9443d04ea4cd80f2a0839b8d78770b76ccd45863" dependencies = [ "zbus_xml", - "zvariant 4.2.0", + "zvariant", ] [[package]] name = "zbus-lockstep-macros" -version = "0.4.4" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "709ab20fc57cb22af85be7b360239563209258430bccf38d8b979c5a2ae3ecce" +checksum = "10da05367f3a7b7553c8cdf8fa91aee6b64afebe32b51c95177957efc47ca3a0" dependencies = [ "proc-macro2", "quote", "syn 2.0.111", "zbus-lockstep", "zbus_xml", - "zvariant 4.2.0", -] - -[[package]] -name = "zbus_macros" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 2.0.111", - "zvariant_utils 2.1.0", + "zvariant", ] [[package]] @@ -9042,20 +9035,9 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.111", - "zbus_names 4.2.0", - "zvariant 5.8.0", - "zvariant_utils 3.2.1", -] - -[[package]] -name = "zbus_names" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" -dependencies = [ - "serde", - "static_assertions", - "zvariant 4.2.0", + "zbus_names", + "zvariant", + "zvariant_utils", ] [[package]] @@ -9067,20 +9049,20 @@ dependencies = [ "serde", "static_assertions", "winnow", - "zvariant 5.8.0", + "zvariant", ] [[package]] name = "zbus_xml" -version = "4.0.0" +version = "5.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3f374552b954f6abb4bd6ce979e6c9b38fb9d0cd7cc68a7d796e70c9f3a233" +checksum = "589e9a02bfafb9754bb2340a9e3b38f389772684c63d9637e76b1870377bec29" dependencies = [ - "quick-xml 0.30.0", + "quick-xml 0.36.2", "serde", "static_assertions", - "zbus_names 3.0.0", - "zvariant 4.2.0", + "zbus_names", + "zvariant", ] [[package]] @@ -9183,19 +9165,6 @@ dependencies = [ "zune-core", ] -[[package]] -name = "zvariant" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2084290ab9a1c471c38fc524945837734fbf124487e105daec2bb57fd48c81fe" -dependencies = [ - "endi", - "enumflags2", - "serde", - "static_assertions", - "zvariant_derive 4.2.0", -] - [[package]] name = "zvariant" version = "5.8.0" @@ -9207,21 +9176,8 @@ dependencies = [ "serde", "url", "winnow", - "zvariant_derive 5.8.0", - "zvariant_utils 3.2.1", -] - -[[package]] -name = "zvariant_derive" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 2.0.111", - "zvariant_utils 2.1.0", + "zvariant_derive", + "zvariant_utils", ] [[package]] @@ -9234,18 +9190,7 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.111", - "zvariant_utils 3.2.1", -] - -[[package]] -name = "zvariant_utils" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.111", + "zvariant_utils", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index ed1a301b3..d8017d9f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [workspace] members = [ + "packages/accesskit_xplat", "packages/debug_timer", "packages/blitz-traits", "packages/blitz-dom", @@ -29,7 +30,7 @@ homepage = "https://github.com/dioxuslabs/blitz" repository = "https://github.com/dioxuslabs/blitz" categories = ["gui"] edition = "2024" -rust-version = "1.88.0" +rust-version = "1.89.0" [workspace.dependencies] # Blitz dependencies(in-repo) @@ -44,6 +45,7 @@ stylo_taffy = { version = "0.2.0", path = "./packages/stylo_taffy", default-feat dioxus-native = { version = "0.7.0", path = "./packages/dioxus-native", default-features = false } dioxus-native-dom = { version = "0.7.0", path = "./packages/dioxus-native-dom", default-features = false } debug_timer = { version = "0.1.2", path = "./packages/debug_timer" } +accesskit_xplat = { version = "0.1", path = "./packages/accesskit_xplat", default-features = false } # Servo dependencies style = { version = "0.9.0", package = "stylo" } @@ -100,7 +102,7 @@ anyrender = { version = "0.6" } anyrender_vello = { version = "0.6" } anyrender_vello_cpu = { version = "0.8" } anyrender_vello_hybrid = { version = "0.1" } -anyrender_skia = { version = "0.3.0" } +anyrender_skia = { version = "0.3.1" } anyrender_svg = { version = "0.6" } wgpu_context = { version = "0.1.2" } @@ -128,9 +130,8 @@ usvg = "0.45.1" # Windowing & Input raw-window-handle = "0.6.0" -winit = { version = "0.30.2", features = ["rwh_06"] } -accesskit_winit = "0.23" -accesskit = "0.17" +winit = { version = "=0.31.0-beta.2" } +accesskit = "0.22" arboard = { version = "3.4.1", default-features = false } rfd = { version = "0.15.3", default-features = false } keyboard-types = "0.7" @@ -141,7 +142,7 @@ url = "2.5.0" http = "1.1.0" data-url = "0.3.1" tokio = "1.42" -reqwest = "0.12" +reqwest = { version = "0.12", default-features = false } reqwest-middleware = { version = "0.4.2", default-features = false } http-cache-reqwest = { version = "=1.0.0-alpha.2", default-features = false } @@ -167,7 +168,7 @@ tracing-subscriber = "0.3" futures-util = "0.3.30" futures-intrusive = "0.5.0" pollster = "0.4" -smol_str = "0.2" +smol_str = "0.3" bitflags = "2.8.0" bytemuck = "1" fastrand = "2.3.0" @@ -214,7 +215,7 @@ edition = "2024" description = "Top level crate for Blitz" license = "MIT OR Apache-2.0" keywords = ["dom", "ui", "gui", "react", "wasm"] -rust-version = "1.86.0" +rust-version = "1.89.0" publish = false [dev-dependencies] @@ -245,6 +246,7 @@ tracing-subscriber = "0.3" # anyrender_skia = { path = "../anyrender/crates/anyrender_skia" } # anyrender_vello = { path = "../anyrender/crates/anyrender_vello" } # anyrender_vello_cpu = { path = "../anyrender/crates/anyrender_vello_cpu" } +# anyrender_vello_hybrid = { path = "../anyrender/crates/anyrender_vello_hybrid" } # anyrender_svg = { path = "../anyrender/crates/anyrender_svg" } # wgpu_context = { path = "../anyrender/crates/wgpu_context" } diff --git a/Cross.toml b/Cross.toml new file mode 100644 index 000000000..8f70d451c --- /dev/null +++ b/Cross.toml @@ -0,0 +1,6 @@ +[build] + # additional commands to run prior to building the package +pre-build = [ + "dpkg --add-architecture $CROSS_DEB_ARCH", + "apt-get update && apt-get --assume-yes install python3:$CROSS_DEB_ARCH" +] \ No newline at end of file diff --git a/apps/browser/Cargo.toml b/apps/browser/Cargo.toml index e737a515f..f884fb987 100644 --- a/apps/browser/Cargo.toml +++ b/apps/browser/Cargo.toml @@ -36,8 +36,13 @@ dioxus-native = { workspace = true, features = [ ] } blitz-traits = { workspace = true } blitz-dom = { workspace = true, features = ["woff-rust", "parallel-construct"] } -blitz-net = { workspace = true } +blitz-net = { workspace = true, features = ["http2"] } blitz-html = { workspace = true } linebender_resource_handle = { workspace = true } tracing-subscriber = { workspace = true, optional = true } webbrowser = { workspace = true } +winit = { workspace = true } + + +[target.'cfg(target_os = "android")'.dependencies] +android-activity = { version = "0.6.0", features = ["game-activity"] } diff --git a/apps/browser/Dioxus.toml b/apps/browser/Dioxus.toml index e389d582f..eaf405d22 100644 --- a/apps/browser/Dioxus.toml +++ b/apps/browser/Dioxus.toml @@ -1,4 +1,5 @@ [application] +android_main_activity = "MainActivity.kt.hbs" [bundle] publisher = "DioxusLabs" diff --git a/apps/browser/MainActivity.kt.hbs b/apps/browser/MainActivity.kt.hbs new file mode 100644 index 000000000..195315507 --- /dev/null +++ b/apps/browser/MainActivity.kt.hbs @@ -0,0 +1,16 @@ +package dev.dioxus.main; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.view.WindowCompat; +import androidx.core.view.WindowInsetsCompat; +import androidx.core.view.WindowInsetsControllerCompat; +import com.google.androidgamesdk.GameActivity; + +// class MainActivity : android.app.NativeActivity() +class MainActivity : GameActivity() { + companion object { + init { + System.loadLibrary("dioxusmain") + } + } +} diff --git a/apps/browser/assets/browser.css b/apps/browser/assets/browser.css index 88c94b743..a3ad7dc09 100644 --- a/apps/browser/assets/browser.css +++ b/apps/browser/assets/browser.css @@ -12,6 +12,7 @@ html, body, #main, #frame { #frame { display: flex; flex-direction: column; + background: black; } .urlbar { diff --git a/apps/browser/src/main.rs b/apps/browser/src/main.rs index ca929f40f..23c15a4e5 100644 --- a/apps/browser/src/main.rs +++ b/apps/browser/src/main.rs @@ -25,10 +25,16 @@ use icons::IconButton; static BROWSER_UI_STYLES: Asset = asset!("../assets/browser.css"); +#[unsafe(no_mangle)] +#[cfg(target_os = "android")] +pub fn android_main(android_app: dioxus_native::AndroidApp) { + dioxus_native::set_android_app(android_app); + main() +} + fn main() { #[cfg(feature = "tracing")] tracing_subscriber::fmt::init(); - dioxus_native::launch(app) } @@ -39,7 +45,7 @@ fn use_sync_store(value: impl FnOnce() -> T) -> SyncSt } fn app() -> Element { - let home_url = use_hook(|| Url::parse("https://html.duckduckgo.com").unwrap()); + let home_url = use_hook(|| Url::parse("https://en.wikipedia.org/wiki/Main_Page").unwrap()); let mut url_input_handle = use_signal(|| None); let mut webview_node_handle: Signal> = use_signal(|| None); @@ -83,8 +89,23 @@ fn app() -> Element { } }); + // HACK: Winit doesn't support "safe area" on Android yet. + // So we just hardcode a fallback safe area. + const TOP_PAD: &str = if cfg!(target_os = "android") { + "30px" + } else { + "" + }; + const BOTTOM_PAD: &str = if cfg!(target_os = "android") { + "44px" + } else { + "" + }; + rsx!( div { id: "frame", + padding_top: TOP_PAD, + padding_bottom: BOTTOM_PAD, title { "Blitz Browser" } document::Link { rel: "stylesheet", href: BROWSER_UI_STYLES } @@ -134,7 +155,12 @@ fn app() -> Element { } }, onkeydown: move |evt| { - if evt.key() == Key::Enter { + let is_enter = match evt.key() { + Key::Enter => true, + Key::Character(s) if s == "\n" => true, + _ => false, + }; + if is_enter { evt.prevent_default(); let req = req_from_string(&url_input_value.read()); if let Some(req) = req { diff --git a/apps/readme/src/main.rs b/apps/readme/src/main.rs index 5ecb72773..b1742621a 100644 --- a/apps/readme/src/main.rs +++ b/apps/readme/src/main.rs @@ -37,24 +37,22 @@ use markdown::{BLITZ_MD_STYLES, GITHUB_MD_STYLES, markdown_to_html}; use notify::{Error as NotifyError, Event as NotifyEvent, RecursiveMode, Watcher as _}; use readme_application::{ReadmeApplication, ReadmeEvent}; -use blitz_shell::{BlitzShellEvent, BlitzShellNetWaker, WindowConfig, create_default_event_loop}; +use blitz_shell::{BlitzShellEvent, BlitzShellProxy, WindowConfig, create_default_event_loop}; use std::env::current_dir; use std::fs; use std::path::{Path, PathBuf}; use std::sync::Arc; use tokio::sync::oneshot; use url::Url; -use winit::event_loop::EventLoopProxy; use winit::window::WindowAttributes; struct ReadmeNavigationProvider { - proxy: EventLoopProxy, + proxy: BlitzShellProxy, } impl NavigationProvider for ReadmeNavigationProvider { fn navigate_to(&self, opts: NavigationOptions) { - let _ = self - .proxy + self.proxy .send_event(BlitzShellEvent::Navigate(Box::new(opts))); } } @@ -74,9 +72,10 @@ fn main() { let _guard = rt.enter(); let event_loop = create_default_event_loop(); - let proxy = event_loop.create_proxy(); + let winit_proxy = event_loop.create_proxy(); + let (proxy, event_queue) = BlitzShellProxy::new(winit_proxy); - let net_waker = Some(BlitzShellNetWaker::shared(proxy.clone())); + let net_waker = Some(Arc::new(proxy.clone()) as _); let net_provider = Arc::new(Provider::new(net_waker)); let (base_url, contents, is_md, file_path) = @@ -98,7 +97,6 @@ fn main() { // println!("{html}"); - let proxy = event_loop.create_proxy(); let navigation_provider = ReadmeNavigationProvider { proxy: proxy.clone(), }; @@ -121,6 +119,7 @@ fn main() { // Create application let mut application = ReadmeApplication::new( proxy.clone(), + event_queue, raw_url.clone(), net_provider, navigation_provider, @@ -131,7 +130,7 @@ fn main() { let mut watcher = notify::recommended_watcher(move |_: Result| { let event = BlitzShellEvent::Embedder(Arc::new(ReadmeEvent)); - proxy.send_event(event).unwrap(); + proxy.send_event(event); }) .unwrap(); @@ -145,7 +144,7 @@ fn main() { } // Run event loop - event_loop.run_app(&mut application).unwrap() + event_loop.run_app(application).unwrap() } async fn fetch( diff --git a/apps/readme/src/readme_application.rs b/apps/readme/src/readme_application.rs index ce22dd9ea..3e635d910 100644 --- a/apps/readme/src/readme_application.rs +++ b/apps/readme/src/readme_application.rs @@ -4,13 +4,15 @@ use crate::WindowRenderer; use blitz_dom::DocumentConfig; use blitz_html::HtmlDocument; use blitz_net::Provider; -use blitz_shell::{BlitzApplication, BlitzShellEvent, View, WindowConfig}; +use blitz_shell::{BlitzApplication, BlitzShellEvent, BlitzShellProxy, View, WindowConfig}; use blitz_traits::navigation::{NavigationOptions, NavigationProvider}; use tokio::runtime::Handle; use winit::application::ApplicationHandler; use winit::event::{Modifiers, StartCause, WindowEvent}; -use winit::event_loop::{ActiveEventLoop, EventLoopProxy}; +use winit::event_loop::ActiveEventLoop; use winit::keyboard::{KeyCode, PhysicalKey}; +#[cfg(target_os = "macos")] +use winit::platform::macos::ApplicationHandlerExtMacOS; use winit::window::{Theme, WindowId}; use crate::fetch; @@ -30,14 +32,15 @@ pub struct ReadmeApplication { impl ReadmeApplication { pub fn new( - proxy: EventLoopProxy, + proxy: BlitzShellProxy, + event_queue: std::sync::mpsc::Receiver, raw_url: String, net_provider: Arc, navigation_provider: Arc, ) -> Self { let handle = Handle::current(); Self { - inner: BlitzApplication::new(proxy.clone()), + inner: BlitzApplication::new(proxy, event_queue), handle, raw_url, net_provider, @@ -63,14 +66,12 @@ impl ReadmeApplication { self.handle.spawn(async move { let url = url; let (base_url, contents, is_md, _file_path) = fetch(&url, net_provider).await; - proxy - .send_event(BlitzShellEvent::NavigationLoad { - url: base_url, - contents, - is_md, - retain_scroll_position, - }) - .unwrap(); + proxy.send_event(BlitzShellEvent::NavigationLoad { + url: base_url, + contents, + is_md, + retain_scroll_position, + }); }); } @@ -81,14 +82,12 @@ impl ReadmeApplication { Box::new(move |result| { let (url, bytes) = result.unwrap(); let contents = std::str::from_utf8(&bytes).unwrap().to_string(); - proxy - .send_event(BlitzShellEvent::NavigationLoad { - url, - contents, - is_md: false, - retain_scroll_position: false, - }) - .unwrap(); + proxy.send_event(BlitzShellEvent::NavigationLoad { + url, + contents, + is_md: false, + retain_scroll_position: false, + }); }), ); } @@ -132,22 +131,35 @@ impl ReadmeApplication { } } -impl ApplicationHandler for ReadmeApplication { - fn resumed(&mut self, event_loop: &ActiveEventLoop) { +impl ApplicationHandler for ReadmeApplication { + #[cfg(target_os = "macos")] + fn macos_handler(&mut self) -> Option<&mut dyn ApplicationHandlerExtMacOS> { + self.inner.macos_handler() + } + + fn resumed(&mut self, event_loop: &dyn ActiveEventLoop) { self.inner.resumed(event_loop); } - fn suspended(&mut self, event_loop: &ActiveEventLoop) { + fn suspended(&mut self, event_loop: &dyn ActiveEventLoop) { self.inner.suspended(event_loop); } - fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: StartCause) { + fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { + self.inner.can_create_surfaces(event_loop); + } + + fn destroy_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { + self.inner.destroy_surfaces(event_loop); + } + + fn new_events(&mut self, event_loop: &dyn ActiveEventLoop, cause: StartCause) { self.inner.new_events(event_loop, cause); } fn window_event( &mut self, - event_loop: &ActiveEventLoop, + event_loop: &dyn ActiveEventLoop, window_id: WindowId, event: WindowEvent, ) { @@ -157,7 +169,7 @@ impl ApplicationHandler for ReadmeApplication { if let WindowEvent::KeyboardInput { event, .. } = &event { let mods = self.keyboard_modifiers.state(); - if !event.state.is_pressed() && (mods.control_key() || mods.super_key()) { + if !event.state.is_pressed() && (mods.control_key() || mods.meta_key()) { match event.physical_key { PhysicalKey::Code(KeyCode::KeyR) => self.reload_document(true), PhysicalKey::Code(KeyCode::KeyT) => self.toggle_theme(), @@ -175,28 +187,30 @@ impl ApplicationHandler for ReadmeApplication { self.inner.window_event(event_loop, window_id, event); } - fn user_event(&mut self, event_loop: &ActiveEventLoop, event: BlitzShellEvent) { - match event { - BlitzShellEvent::Embedder(event) => { - if let Some(_event) = event.downcast_ref::() { - self.reload_document(true); + fn proxy_wake_up(&mut self, event_loop: &dyn ActiveEventLoop) { + while let Ok(event) = self.inner.event_queue.try_recv() { + match event { + BlitzShellEvent::Embedder(event) => { + if let Some(_event) = event.downcast_ref::() { + self.reload_document(true); + } } + BlitzShellEvent::Navigate(options) => { + let old_url = std::mem::replace(&mut self.raw_url, options.url.to_string()); + self.url_history.push(old_url); + self.reload_document(false); + self.navigate(*options); + } + BlitzShellEvent::NavigationLoad { + url, + contents, + retain_scroll_position, + is_md, + } => { + self.load_document(contents, retain_scroll_position, url, is_md); + } + event => self.inner.handle_blitz_shell_event(event_loop, event), } - BlitzShellEvent::Navigate(options) => { - let old_url = std::mem::replace(&mut self.raw_url, options.url.to_string()); - self.url_history.push(old_url); - self.reload_document(false); - self.navigate(*options); - } - BlitzShellEvent::NavigationLoad { - url, - contents, - retain_scroll_position, - is_md, - } => { - self.load_document(contents, retain_scroll_position, url, is_md); - } - event => self.inner.user_event(event_loop, event), } } } diff --git a/examples/counter/Cargo.toml b/examples/counter/Cargo.toml index 111acc388..d4dae0579 100644 --- a/examples/counter/Cargo.toml +++ b/examples/counter/Cargo.toml @@ -5,20 +5,24 @@ edition = "2024" license.workspace = true publish = false +[lib] +crate-type = ["cdylib"] + [features] -default = ["system_fonts", "vello"] +default = ["vello"] system_fonts = ["blitz-dom/system_fonts"] vello = ["dioxus-native/vello"] cpu = ["cpu-pixels"] svg = ["blitz-paint/svg"] cpu-pixels = ["dioxus-native/vello-cpu-pixels"] cpu-softbuffer = ["dioxus-native/vello-cpu-softbuffer"] +skia = ["dioxus-native/skia"] incremental = ["dioxus-native/incremental"] log_frame_times = ["dioxus-native/log-frame-times"] log_phase_times = ["dioxus-native/log-phase-times"] [dependencies] -dioxus-native = { workspace = true, default-features = false, features = ["prelude"]} +dioxus-native = { workspace = true, default-features = false, features = ["prelude", "system-fonts"] } # Control whether system font support is enabled blitz-dom = { workspace = true, default-features = false } @@ -26,4 +30,7 @@ blitz-paint = { workspace = true, default-features = false } # Disable unicode URL support # See https://github.com/hsivonen/idna_adapter -idna_adapter = "=1.0.0" \ No newline at end of file +idna_adapter = "=1.0.0" + +[target.'cfg(target_os = "android")'.dependencies] +android-activity = { version = "0.6.0", features = ["native-activity"] } \ No newline at end of file diff --git a/examples/counter/Dioxus.toml b/examples/counter/Dioxus.toml new file mode 100644 index 000000000..3292650d6 --- /dev/null +++ b/examples/counter/Dioxus.toml @@ -0,0 +1,2 @@ +[application] +android_main_activity = "MainActivity.kt.hbs" \ No newline at end of file diff --git a/examples/counter/MainActivity.kt.hbs b/examples/counter/MainActivity.kt.hbs new file mode 100644 index 000000000..a0ce0e2c3 --- /dev/null +++ b/examples/counter/MainActivity.kt.hbs @@ -0,0 +1,4 @@ +package dev.dioxus.main; + +class MainActivity : android.app.NativeActivity() +//class MainActivity : com.google.androidgamesdk.GameActivity() diff --git a/examples/counter/src/app.rs b/examples/counter/src/app.rs new file mode 100644 index 000000000..1e6613de5 --- /dev/null +++ b/examples/counter/src/app.rs @@ -0,0 +1,114 @@ +//! Drive the renderer from Dioxus +use dioxus_native::prelude::*; + +pub fn app() -> Element { + let mut count = use_signal(|| 0); + + rsx! { + div { class: "container", + style { {CSS} } + h1 { class: "header", "Count: {count}" } + div { class: "buttons", + button { + class: "counter-button btn-green", + onclick: move |_| { count += 1 }, + "Increment" + } + button { + class: "counter-button btn-red", + onclick: move |_| { count -= 1 }, + "Decrement" + } + } + button { + class: "counter-button btn-blue", + onclick: move |_| { count.set(0) }, + "Reset" + } + } + } +} + +const CSS: &str = r#" + +html, body, #main { + padding: 0; + margin: 0; + background-color: green; + height: 100%; +} + +.header { + background-color: pink; + padding: 20px; + line-height: 1; + font-family: sans-serif; +} + +.container { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + height: 100%; + width: 100vw; + background: linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%), + linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%), + linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%); +} + +.buttons { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + margin: 20px 0; +} + +.counter-button { + margin: 0 10px; + padding: 10px 20px; + border-radius: 5px; + font-size: 1.5rem; + cursor: pointer; + line-height: 1; + font-family: sans-serif; + border-width: 2px; + border-style: solid; +} +.counter-button:focus { + outline: 4px solid black; +} + +.btn-green { + background-color: green; + border-color: green; + color: white; +} +.btn-green:hover { + color: green; + background-color: white; +} + +.btn-red { + background-color: red; + border-color: red; + color: white; +} +.btn-red:hover { + color: red; + background-color: white; +} + +.btn-blue { + background-color: blue; + border-color: blue; + color: white; +} +.btn-blue:hover { + color: blue; + background-color: white; +} + + +"#; diff --git a/examples/counter/src/lib.rs b/examples/counter/src/lib.rs new file mode 100644 index 000000000..98df23332 --- /dev/null +++ b/examples/counter/src/lib.rs @@ -0,0 +1,10 @@ +#![cfg(target_os = "android")] + +mod app; + +/// Run with `cargo apk run` +#[unsafe(no_mangle)] +pub fn android_main(android_app: dioxus_native::AndroidApp) { + dioxus_native::set_android_app(android_app); + dioxus_native::launch(app::app) +} diff --git a/examples/counter/src/main.rs b/examples/counter/src/main.rs index 38e7e65a3..0621c4f51 100644 --- a/examples/counter/src/main.rs +++ b/examples/counter/src/main.rs @@ -1,117 +1,17 @@ -//! Drive the renderer from Dioxus -use dioxus_native::prelude::*; - -fn main() { - dioxus_native::launch(app); -} - -fn app() -> Element { - let mut count = use_signal(|| 0); - - rsx! { - div { class: "container", - style { {CSS} } - h1 { class: "header", "Count: {count}" } - div { class: "buttons", - button { - class: "counter-button btn-green", - onclick: move |_| { count += 1 }, - "Increment" - } - button { - class: "counter-button btn-red", - onclick: move |_| { count -= 1 }, - "Decrement" - } - } - button { - class: "counter-button btn-blue", - onclick: move |_| { count.set(0) }, - "Reset" - } - } - } -} - -const CSS: &str = r#" - -html, body { - padding: 0; - margin: 0; - background-color: white; -} - -.header { - background-color: pink; - padding: 20px; - line-height: 1; - font-family: sans-serif; -} - -.container { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - height: 100vh; - width: 100vw; - background: linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%), - linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%), - linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%); -} +// On Windows do NOT show a console window when opening the app +#![cfg_attr(all(not(test), target_os = "windows"), windows_subsystem = "windows")] -.buttons { - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - margin: 20px 0; -} +//! Drive the renderer from Dioxus -.counter-button { - margin: 0 10px; - padding: 10px 20px; - border-radius: 5px; - font-size: 1.5rem; - cursor: pointer; - line-height: 1; - font-family: sans-serif; - border-width: 2px; - border-style: solid; -} -.counter-button:focus { - outline: 4px solid black; -} +mod app; -.btn-green { - background-color: green; - border-color: green; - color: white; -} -.btn-green:hover { - color: green; - background-color: white; +#[unsafe(no_mangle)] +#[cfg(target_os = "android")] +pub fn android_main(android_app: dioxus_native::AndroidApp) { + dioxus_native::set_android_app(android_app); + dioxus_native::launch(app::app) } -.btn-red { - background-color: red; - border-color: red; - color: white; -} -.btn-red:hover { - color: red; - background-color: white; -} - -.btn-blue { - background-color: blue; - border-color: blue; - color: white; -} -.btn-blue:hover { - color: blue; - background-color: white; +fn main() { + dioxus_native::launch(app::app) } - - -"#; diff --git a/examples/inner_html.rs b/examples/inner_html.rs index 03df3be4b..d2e4d8268 100644 --- a/examples/inner_html.rs +++ b/examples/inner_html.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use anyrender_vello::VelloWindowRenderer; use blitz_dom::DocumentConfig; use blitz_html::{HtmlDocument, HtmlProvider}; -use blitz_shell::{BlitzApplication, BlitzShellEvent, WindowConfig, create_default_event_loop}; +use blitz_shell::{BlitzApplication, BlitzShellProxy, WindowConfig, create_default_event_loop}; pub fn main() { // Create renderer @@ -22,14 +22,15 @@ pub fn main() { doc.resolve(0.0); // Create the Winit application and window - let event_loop = create_default_event_loop::(); - let mut application = BlitzApplication::new(event_loop.create_proxy()); + let event_loop = create_default_event_loop(); + let (proxy, reciever) = BlitzShellProxy::new(event_loop.create_proxy()); + let mut application = BlitzApplication::new(proxy, reciever); let renderer = VelloWindowRenderer::new(); let window = WindowConfig::new(Box::new(doc), renderer); application.add_window(window); // Run event loop - event_loop.run_app(&mut application).unwrap() + event_loop.run_app(application).unwrap() } static HTML: &str = r#" diff --git a/examples/screenshot.rs b/examples/screenshot.rs index 8a05dc25d..df3de74fd 100644 --- a/examples/screenshot.rs +++ b/examples/screenshot.rs @@ -117,7 +117,15 @@ async fn main() { ); // Render document - paint_scene(scene, document.as_ref(), scale, render_width, render_height); + paint_scene( + scene, + document.as_ref(), + scale, + render_width, + render_height, + 0, + 0, + ); }, render_width, render_height, diff --git a/examples/todomvc/Cargo.toml b/examples/todomvc/Cargo.toml index 6fbaaabbc..4de43cef3 100644 --- a/examples/todomvc/Cargo.toml +++ b/examples/todomvc/Cargo.toml @@ -29,4 +29,7 @@ tracing-subscriber = { workspace = true, optional = true} # Disable unicode URL support # See https://github.com/hsivonen/idna_adapter -idna_adapter = "=1.0.0" \ No newline at end of file +idna_adapter = "=1.0.0" + +[target.'cfg(target_os = "android")'.dependencies] +android-activity = { version = "0.6.0", features = ["native-activity"] } \ No newline at end of file diff --git a/examples/todomvc/Dioxus.toml b/examples/todomvc/Dioxus.toml new file mode 100644 index 000000000..3292650d6 --- /dev/null +++ b/examples/todomvc/Dioxus.toml @@ -0,0 +1,2 @@ +[application] +android_main_activity = "MainActivity.kt.hbs" \ No newline at end of file diff --git a/examples/todomvc/MainActivity.kt.hbs b/examples/todomvc/MainActivity.kt.hbs new file mode 100644 index 000000000..a0ce0e2c3 --- /dev/null +++ b/examples/todomvc/MainActivity.kt.hbs @@ -0,0 +1,4 @@ +package dev.dioxus.main; + +class MainActivity : android.app.NativeActivity() +//class MainActivity : com.google.androidgamesdk.GameActivity() diff --git a/examples/todomvc/src/app.rs b/examples/todomvc/src/app.rs index 300f85a5a..bbbabe6c2 100644 --- a/examples/todomvc/src/app.rs +++ b/examples/todomvc/src/app.rs @@ -113,7 +113,12 @@ fn TodoHeader(mut todos: Signal>) -> Element { let mut todo_id = use_signal(|| 0); let onkeydown = move |evt: KeyboardEvent| { - if evt.key() == Key::Enter && !draft.read().is_empty() { + let is_enter = match evt.key() { + Key::Enter => true, + Key::Character(s) if s == "\n" => true, + _ => false, + }; + if is_enter && !draft.read().is_empty() { let id = todo_id(); let todo = TodoItem { id, diff --git a/examples/todomvc/src/main.rs b/examples/todomvc/src/main.rs index 575086eaa..649a27add 100644 --- a/examples/todomvc/src/main.rs +++ b/examples/todomvc/src/main.rs @@ -5,6 +5,13 @@ mod app; +#[unsafe(no_mangle)] +#[cfg(target_os = "android")] +pub fn android_main(android_app: dioxus_native::AndroidApp) { + dioxus_native::set_android_app(android_app); + dioxus_native::launch(app::app) +} + fn main() { #[cfg(feature = "tracing")] tracing_subscriber::fmt::init(); diff --git a/examples/wgpu_texture/src/html.rs b/examples/wgpu_texture/src/html.rs index 77f10c244..0a28feeba 100644 --- a/examples/wgpu_texture/src/html.rs +++ b/examples/wgpu_texture/src/html.rs @@ -1,7 +1,7 @@ use anyrender_vello::{VelloRendererOptions, VelloWindowRenderer}; use blitz_dom::{qual_name, DocumentConfig}; use blitz_html::HtmlDocument; -use blitz_shell::{create_default_event_loop, BlitzApplication, BlitzShellEvent, WindowConfig}; +use blitz_shell::{create_default_event_loop, BlitzApplication, BlitzShellProxy, WindowConfig}; use crate::{limits, DemoPaintSource, FEATURES, STYLES}; @@ -30,13 +30,14 @@ pub fn launch_html() { .set_attribute(canvas_node_id, src_attr, &src_str); // Create the Winit application and window - let event_loop = create_default_event_loop::(); - let mut application = BlitzApplication::new(event_loop.create_proxy()); + let event_loop = create_default_event_loop(); + let (proxy, reciever) = BlitzShellProxy::new(event_loop.create_proxy()); + let mut application = BlitzApplication::new(proxy, reciever); let window = WindowConfig::new(Box::new(doc), renderer); application.add_window(window); // Run event loop - event_loop.run_app(&mut application).unwrap() + event_loop.run_app(application).unwrap() } static HTML: &str = r#" diff --git a/justfile b/justfile index d1fd010fb..73c539829 100644 --- a/justfile +++ b/justfile @@ -69,6 +69,11 @@ todoandroid *ARGS: export CARGO_APK_RELEASE_KEYSTORE_PASSWORD="android" cargo apk run --lib --no-default-features --features skia -p todomvc +counterandroid *ARGS: + export CARGO_APK_RELEASE_KEYSTORE="$HOME/.android/debug.keystore" + export CARGO_APK_RELEASE_KEYSTORE_PASSWORD="android" + cargo apk run --lib --no-default-features --features skia -p counter + ## Ops bump *ARGS: diff --git a/packages/accesskit_xplat/CHANGELOG.md b/packages/accesskit_xplat/CHANGELOG.md new file mode 100644 index 000000000..3a981878a --- /dev/null +++ b/packages/accesskit_xplat/CHANGELOG.md @@ -0,0 +1,885 @@ +# Changelog + +* The following workspace dependencies were updated + * dependencies + * accesskit_macos bumped from 0.1.4 to 0.1.5 + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.8.0 to 0.8.1 + * accesskit_windows bumped from 0.10.0 to 0.10.1 + * accesskit_macos bumped from 0.2.0 to 0.2.1 + +* The following workspace dependencies were updated + * dependencies + * accesskit_windows bumped from 0.10.1 to 0.10.2 + * accesskit_macos bumped from 0.2.1 to 0.3.0 + +* The following workspace dependencies were updated + * dependencies + * accesskit_macos bumped from 0.3.0 to 0.4.0 + +* The following workspace dependencies were updated + * dependencies + * accesskit_windows bumped from 0.10.3 to 0.10.4 + * accesskit_macos bumped from 0.4.1 to 0.4.2 + * accesskit_unix bumped from 0.1.0 to 0.1.1 + +* The following workspace dependencies were updated + * dependencies + * accesskit_unix bumped from 0.3.0 to 0.3.1 + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.10.0 to 0.10.1 + * accesskit_windows bumped from 0.13.0 to 0.13.1 + * accesskit_macos bumped from 0.6.0 to 0.6.1 + * accesskit_unix bumped from 0.3.1 to 0.3.2 + +* The following workspace dependencies were updated + * dependencies + * accesskit_windows bumped from 0.13.1 to 0.13.2 + +* The following workspace dependencies were updated + * dependencies + * accesskit_macos bumped from 0.6.1 to 0.6.2 + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.10.1 to 0.11.0 + * accesskit_windows bumped from 0.13.2 to 0.13.3 + * accesskit_macos bumped from 0.6.2 to 0.6.3 + * accesskit_unix bumped from 0.3.2 to 0.3.3 + +* The following workspace dependencies were updated + * dependencies + * accesskit_macos bumped from 0.7.0 to 0.7.1 + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.11.0 to 0.11.1 + * accesskit_windows bumped from 0.14.0 to 0.14.1 + * accesskit_macos bumped from 0.7.1 to 0.8.0 + * accesskit_unix bumped from 0.5.0 to 0.5.1 + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.11.1 to 0.11.2 + * accesskit_windows bumped from 0.14.1 to 0.14.2 + * accesskit_macos bumped from 0.8.0 to 0.9.0 + * accesskit_unix bumped from 0.5.1 to 0.5.2 + +* The following workspace dependencies were updated + * dependencies + * accesskit_windows bumped from 0.14.2 to 0.14.3 + +* The following workspace dependencies were updated + * dependencies + * accesskit_windows bumped from 0.16.0 to 0.16.1 + * accesskit_unix bumped from 0.7.1 to 0.7.2 + +* The following workspace dependencies were updated + * dependencies + * accesskit_unix bumped from 0.7.2 to 0.7.3 + +* The following workspace dependencies were updated + * dependencies + * accesskit_windows bumped from 0.16.1 to 0.16.2 + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.12.2 to 0.12.3 + * accesskit_windows bumped from 0.16.2 to 0.16.3 + * accesskit_macos bumped from 0.11.0 to 0.11.1 + * accesskit_unix bumped from 0.7.3 to 0.7.4 + +* The following workspace dependencies were updated + * dependencies + * accesskit_unix bumped from 0.7.4 to 0.7.5 + +* The following workspace dependencies were updated + * dependencies + * accesskit_windows bumped from 0.16.3 to 0.16.4 + +* The following workspace dependencies were updated + * dependencies + * accesskit_windows bumped from 0.18.0 to 0.18.1 + * accesskit_macos bumped from 0.13.0 to 0.13.1 + * accesskit_unix bumped from 0.9.0 to 0.9.1 + +* The following workspace dependencies were updated + * dependencies + * accesskit_windows bumped from 0.18.1 to 0.18.2 + * accesskit_macos bumped from 0.13.1 to 0.13.2 + * accesskit_unix bumped from 0.9.1 to 0.9.2 + +* The following workspace dependencies were updated + * dependencies + * accesskit_windows bumped from 0.18.2 to 0.19.0 + * accesskit_macos bumped from 0.13.2 to 0.14.0 + * accesskit_unix bumped from 0.9.2 to 0.10.0 + +* The following workspace dependencies were updated + * dependencies + * accesskit_windows bumped from 0.19.0 to 0.20.0 + * accesskit_macos bumped from 0.14.0 to 0.15.0 + * accesskit_unix bumped from 0.10.0 to 0.10.1 + +* The following workspace dependencies were updated + * dependencies + * accesskit_unix bumped from 0.11.0 to 0.11.1 + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.16.2 to 0.16.3 + * accesskit_windows bumped from 0.23.1 to 0.23.2 + * accesskit_macos bumped from 0.17.2 to 0.17.3 + * accesskit_unix bumped from 0.12.2 to 0.12.3 + +* The following workspace dependencies were updated + * dependencies + * accesskit_macos bumped from 0.17.3 to 0.17.4 + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.17.0 to 0.17.1 + * accesskit_windows bumped from 0.24.0 to 0.24.1 + * accesskit_macos bumped from 0.18.0 to 0.18.1 + * accesskit_unix bumped from 0.13.0 to 0.13.1 + +## [0.29.2](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.29.1...accesskit_winit-v0.29.2) (2025-10-20) + + +### Bug Fixes + +* Fix winit examples window not showing up under Wayland ([#625](https://github.com/AccessKit/accesskit/issues/625)) ([87ce769](https://github.com/AccessKit/accesskit/commit/87ce769282b00684f2b2ab6a3410ed6edb894f22)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit_windows bumped from 0.29.1 to 0.29.2 + * accesskit_macos bumped from 0.22.1 to 0.22.2 + * accesskit_unix bumped from 0.17.1 to 0.17.2 + * accesskit_android bumped from 0.4.1 to 0.4.2 + +## [0.29.1](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.29.0...accesskit_winit-v0.29.1) (2025-10-02) + + +### Bug Fixes + +* Impl `Clone` and `PartialEq` on `WindowEvent` ([#618](https://github.com/AccessKit/accesskit/issues/618)) ([3a4771b](https://github.com/AccessKit/accesskit/commit/3a4771b87455cc005c18152935535818a3f9f825)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.21.0 to 0.21.1 + * accesskit_windows bumped from 0.29.0 to 0.29.1 + * accesskit_macos bumped from 0.22.0 to 0.22.1 + * accesskit_unix bumped from 0.17.0 to 0.17.1 + * accesskit_android bumped from 0.4.0 to 0.4.1 + +## [0.29.0](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.28.0...accesskit_winit-v0.29.0) (2025-07-16) + + +### Features + +* Let parents declare actions supported on their children ([#593](https://github.com/AccessKit/accesskit/issues/593)) ([70b534b](https://github.com/AccessKit/accesskit/commit/70b534bed168a84b84cc35199588aa8ab784fb43)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.20.0 to 0.21.0 + * accesskit_windows bumped from 0.28.0 to 0.29.0 + * accesskit_macos bumped from 0.21.0 to 0.22.0 + * accesskit_unix bumped from 0.16.0 to 0.17.0 + * accesskit_android bumped from 0.3.0 to 0.4.0 + +## [0.28.0](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.27.0...accesskit_winit-v0.28.0) (2025-06-26) + + +### âš  BREAKING CHANGES + +* Force a semver-breaking release ([#589](https://github.com/AccessKit/accesskit/issues/589)) + +### Bug Fixes + +* Force a semver-breaking release ([#589](https://github.com/AccessKit/accesskit/issues/589)) ([2887cdd](https://github.com/AccessKit/accesskit/commit/2887cddde817ba3851688068d8d10de5cef7c624)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.19.0 to 0.20.0 + * accesskit_windows bumped from 0.27.0 to 0.28.0 + * accesskit_macos bumped from 0.20.0 to 0.21.0 + * accesskit_unix bumped from 0.15.0 to 0.16.0 + * accesskit_android bumped from 0.2.0 to 0.3.0 + +## [0.27.0](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.26.0...accesskit_winit-v0.27.0) (2025-05-06) + + +### âš  BREAKING CHANGES + +* Simplify the core Android adapter API ([#558](https://github.com/AccessKit/accesskit/issues/558)) +* Drop redundant `HasPopup::True` ([#550](https://github.com/AccessKit/accesskit/issues/550)) + +### Code Refactoring + +* Drop redundant `HasPopup::True` ([#550](https://github.com/AccessKit/accesskit/issues/550)) ([56abf17](https://github.com/AccessKit/accesskit/commit/56abf17356e4c7f13f64aaeaca6a63c8f7ede553)) +* Simplify the core Android adapter API ([#558](https://github.com/AccessKit/accesskit/issues/558)) ([7ac5911](https://github.com/AccessKit/accesskit/commit/7ac5911b11f3d6b8b777b91e6476e7073f6b0e4a)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.18.0 to 0.19.0 + * accesskit_windows bumped from 0.26.0 to 0.27.0 + * accesskit_macos bumped from 0.19.0 to 0.20.0 + * accesskit_unix bumped from 0.14.0 to 0.15.0 + * accesskit_android bumped from 0.1.1 to 0.2.0 + +## [0.26.0](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.25.0...accesskit_winit-v0.26.0) (2025-03-17) + + +### âš  BREAKING CHANGES + +* Panic if the window is visible when the adapter is created, for adapters where this is a problem ([#529](https://github.com/AccessKit/accesskit/issues/529)) + +### Bug Fixes + +* Panic if the window is visible when the adapter is created, for adapters where this is a problem ([#529](https://github.com/AccessKit/accesskit/issues/529)) ([c43c37b](https://github.com/AccessKit/accesskit/commit/c43c37ba2502656fcae4fd726b9b7db0bb520f31)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit_windows bumped from 0.25.0 to 0.26.0 + * accesskit_android bumped from 0.1.0 to 0.1.1 + +## [0.25.0](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.24.0...accesskit_winit-v0.25.0) (2025-03-08) + + +### âš  BREAKING CHANGES + +* Make accesskit_android an optional dependency of accesskit_winit ([#524](https://github.com/AccessKit/accesskit/issues/524)) + +### Bug Fixes + +* Make accesskit_android an optional dependency of accesskit_winit ([#524](https://github.com/AccessKit/accesskit/issues/524)) ([bb17d44](https://github.com/AccessKit/accesskit/commit/bb17d449b601eaffad1c7201ec5bf8de241bb8f8)) + +## [0.24.0](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.23.1...accesskit_winit-v0.24.0) (2025-03-06) + + +### âš  BREAKING CHANGES + +* Add event loop parameter to winit adapter constructors ([#517](https://github.com/AccessKit/accesskit/issues/517)) +* Drop `Tree::app_name` ([#492](https://github.com/AccessKit/accesskit/issues/492)) + +### Features + +* Android adapter ([#500](https://github.com/AccessKit/accesskit/issues/500)) ([7e65ac7](https://github.com/AccessKit/accesskit/commit/7e65ac77d7e108ac5b9f3722f488a2fdf2e3b3e0)) + + +### Bug Fixes + +* Update winit to 0.30.9 ([#511](https://github.com/AccessKit/accesskit/issues/511)) ([0be21e6](https://github.com/AccessKit/accesskit/commit/0be21e6a2979af483b573b1c9b07c677286b871d)) + + +### Code Refactoring + +* Add event loop parameter to winit adapter constructors ([#517](https://github.com/AccessKit/accesskit/issues/517)) ([0d15f24](https://github.com/AccessKit/accesskit/commit/0d15f246a301a68af4424f7602c2f3be25da9327)) +* Drop `Tree::app_name` ([#492](https://github.com/AccessKit/accesskit/issues/492)) ([089794c](https://github.com/AccessKit/accesskit/commit/089794c8f74957e91a19ae3df508e2a892f39ebc)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.17.1 to 0.18.0 + * accesskit_windows bumped from 0.24.1 to 0.25.0 + * accesskit_macos bumped from 0.18.1 to 0.19.0 + * accesskit_unix bumped from 0.13.1 to 0.14.0 + +## [0.23.0](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.22.4...accesskit_winit-v0.23.0) (2024-10-31) + + +### âš  BREAKING CHANGES + +* Rename `name` to `label` and use `value` for label content ([#475](https://github.com/AccessKit/accesskit/issues/475)) +* Rename `NodeBuilder` to `Node` and the old `Node` to `FrozenNode` ([#476](https://github.com/AccessKit/accesskit/issues/476)) +* Drop `DefaultActionVerb` ([#472](https://github.com/AccessKit/accesskit/issues/472)) +* Make the core crate no-std ([#468](https://github.com/AccessKit/accesskit/issues/468)) + +### Features + +* Make the core crate no-std ([#468](https://github.com/AccessKit/accesskit/issues/468)) ([2fa0d3f](https://github.com/AccessKit/accesskit/commit/2fa0d3f5b2b7ac11ef1751c133706f29e548bd6d)) + + +### Code Refactoring + +* Drop `DefaultActionVerb` ([#472](https://github.com/AccessKit/accesskit/issues/472)) ([ef3b003](https://github.com/AccessKit/accesskit/commit/ef3b0038224459094f650368412650bc3b69526b)) +* Rename `name` to `label` and use `value` for label content ([#475](https://github.com/AccessKit/accesskit/issues/475)) ([e0053a5](https://github.com/AccessKit/accesskit/commit/e0053a5399929e8e0d4f07aa18de604ed8766ace)) +* Rename `NodeBuilder` to `Node` and the old `Node` to `FrozenNode` ([#476](https://github.com/AccessKit/accesskit/issues/476)) ([7d8910e](https://github.com/AccessKit/accesskit/commit/7d8910e35f7bc0543724cc124941a3bd0304bcc0)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.16.3 to 0.17.0 + * accesskit_windows bumped from 0.23.2 to 0.24.0 + * accesskit_macos bumped from 0.17.4 to 0.18.0 + * accesskit_unix bumped from 0.12.3 to 0.13.0 + +## [0.22.2](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.22.1...accesskit_winit-v0.22.2) (2024-10-07) + + +### Bug Fixes + +* Update minimum supported Rust version to 1.75 ([#457](https://github.com/AccessKit/accesskit/issues/457)) ([fc622fe](https://github.com/AccessKit/accesskit/commit/fc622fe7657c80a4eedad6f6cded11d2538b54d5)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.16.1 to 0.16.2 + * accesskit_windows bumped from 0.23.0 to 0.23.1 + * accesskit_macos bumped from 0.17.1 to 0.17.2 + * accesskit_unix bumped from 0.12.1 to 0.12.2 + +## [0.22.1](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.22.0...accesskit_winit-v0.22.1) (2024-09-24) + + +### Bug Fixes + +* Use the new HWND type on accesskit_winit ([#453](https://github.com/AccessKit/accesskit/issues/453)) ([68a2462](https://github.com/AccessKit/accesskit/commit/68a24629381f0b18f6ed1ee008fe72ce9330092e)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.16.0 to 0.16.1 + * accesskit_windows bumped from 0.22.0 to 0.23.0 + * accesskit_macos bumped from 0.17.0 to 0.17.1 + * accesskit_unix bumped from 0.12.0 to 0.12.1 + +## [0.22.0](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.21.1...accesskit_winit-v0.22.0) (2024-06-29) + + +### âš  BREAKING CHANGES + +* Rename the `StaticText` role to `Label` ([#434](https://github.com/AccessKit/accesskit/issues/434)) + +### Code Refactoring + +* Rename the `StaticText` role to `Label` ([#434](https://github.com/AccessKit/accesskit/issues/434)) ([7086bc0](https://github.com/AccessKit/accesskit/commit/7086bc0fad446d3ed4a0fd5eff641a1e75f6c599)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.15.0 to 0.16.0 + * accesskit_windows bumped from 0.21.0 to 0.22.0 + * accesskit_macos bumped from 0.16.0 to 0.17.0 + * accesskit_unix bumped from 0.11.1 to 0.12.0 + +## [0.21.0](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.20.4...accesskit_winit-v0.21.0) (2024-06-09) + + +### Features + +* Add `author_id` property ([#424](https://github.com/AccessKit/accesskit/issues/424)) ([0d1c56f](https://github.com/AccessKit/accesskit/commit/0d1c56f0bdde58715e1c69f6015df600cb7cb8c1)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.14.0 to 0.15.0 + * accesskit_windows bumped from 0.20.0 to 0.21.0 + * accesskit_macos bumped from 0.15.0 to 0.16.0 + * accesskit_unix bumped from 0.10.1 to 0.11.0 + +## [0.20.0](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.19.0...accesskit_winit-v0.20.0) (2024-04-30) + + +### âš  BREAKING CHANGES + +* Update winit to 0.30 ([#397](https://github.com/AccessKit/accesskit/issues/397)) +* Drop `NodeClassSet` ([#389](https://github.com/AccessKit/accesskit/issues/389)) + +### Bug Fixes + +* Increase minimum supported Rust version to `1.70` ([#396](https://github.com/AccessKit/accesskit/issues/396)) ([a8398b8](https://github.com/AccessKit/accesskit/commit/a8398b847aa003de91042ac45e33126fc2cae053)) +* Update winit to 0.30 ([#397](https://github.com/AccessKit/accesskit/issues/397)) ([de93be3](https://github.com/AccessKit/accesskit/commit/de93be387c03a438fbf598670207e578686e6bcf)) + + +### Code Refactoring + +* Drop `NodeClassSet` ([#389](https://github.com/AccessKit/accesskit/issues/389)) ([1b153ed](https://github.com/AccessKit/accesskit/commit/1b153ed51f8421cdba2dc98beca2e8f5f8c781bc)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.13.0 to 0.14.0 + * accesskit_windows bumped from 0.17.0 to 0.18.0 + * accesskit_macos bumped from 0.12.0 to 0.13.0 + * accesskit_unix bumped from 0.8.0 to 0.9.0 + +## [0.19.0](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.18.7...accesskit_winit-v0.19.0) (2024-04-14) + + +### âš  BREAKING CHANGES + +* New approach to lazy initialization ([#375](https://github.com/AccessKit/accesskit/issues/375)) + +### Code Refactoring + +* New approach to lazy initialization ([#375](https://github.com/AccessKit/accesskit/issues/375)) ([9baebdc](https://github.com/AccessKit/accesskit/commit/9baebdceed7300389b6768815d7ae48f1ce401e4)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.12.3 to 0.13.0 + * accesskit_windows bumped from 0.16.4 to 0.17.0 + * accesskit_macos bumped from 0.11.1 to 0.12.0 + * accesskit_unix bumped from 0.7.5 to 0.8.0 + +## [0.18.1](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.18.0...accesskit_winit-v0.18.1) (2024-01-11) + + +### Bug Fixes + +* Run our own async executor on Unix ([#337](https://github.com/AccessKit/accesskit/issues/337)) ([8f937ba](https://github.com/AccessKit/accesskit/commit/8f937baaa510dd96da196501822b82f75f05b595)) +* Show an error at compile-time if no raw-window-handle feature is enabled for the winit adapter ([#339](https://github.com/AccessKit/accesskit/issues/339)) ([a24f5fd](https://github.com/AccessKit/accesskit/commit/a24f5fd443a683a6194b54244052ff3e1cc05de6)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit_unix bumped from 0.7.0 to 0.7.1 + +## [0.18.0](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.17.0...accesskit_winit-v0.18.0) (2024-01-03) + + +### âš  BREAKING CHANGES + +* Lazily activate Unix adapters ([#324](https://github.com/AccessKit/accesskit/issues/324)) +* Remove `accesskit_winit::Adapter::update` ([#325](https://github.com/AccessKit/accesskit/issues/325)) + +### Bug Fixes + +* Lazily activate Unix adapters ([#324](https://github.com/AccessKit/accesskit/issues/324)) ([54ed036](https://github.com/AccessKit/accesskit/commit/54ed036c99d87428a8eb5bb03fd77e9e31562d4c)) +* Remove `accesskit_winit::Adapter::update` ([#325](https://github.com/AccessKit/accesskit/issues/325)) ([f121bff](https://github.com/AccessKit/accesskit/commit/f121bffe9e651fd2ac6deb882f57e1c9b613b7eb)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.12.1 to 0.12.2 + * accesskit_windows bumped from 0.15.1 to 0.16.0 + * accesskit_macos bumped from 0.10.1 to 0.11.0 + * accesskit_unix bumped from 0.6.2 to 0.7.0 + +## [0.17.0](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.16.1...accesskit_winit-v0.17.0) (2023-12-14) + + +### âš  BREAKING CHANGES + +* Force a semver break for the winit rwh feature additions ([#322](https://github.com/AccessKit/accesskit/issues/322)) + +### Bug Fixes + +* Add a `rwh_05` feature flag to `accesskit_winit` ([#319](https://github.com/AccessKit/accesskit/issues/319)) ([f4d279c](https://github.com/AccessKit/accesskit/commit/f4d279c5ece16df2925c0e31dc82eaf192c40cd0)) +* Force a semver break for the winit rwh feature additions ([#322](https://github.com/AccessKit/accesskit/issues/322)) ([61acdb0](https://github.com/AccessKit/accesskit/commit/61acdb0ea083263c88a00ad4db637b25863852c0)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit_unix bumped from 0.6.1 to 0.6.2 + +## [0.16.1](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.16.0...accesskit_winit-v0.16.1) (2023-11-05) + + +### Bug Fixes + +* Account for window decorations when `accesskit_winit::Adapter::process_event` receives a resizing event on Unix ([#312](https://github.com/AccessKit/accesskit/issues/312)) ([e2b264c](https://github.com/AccessKit/accesskit/commit/e2b264c2e5b0fb699576f2ece905509c38ffc9be)) + +## [0.16.0](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.15.0...accesskit_winit-v0.16.0) (2023-11-04) + + +### âš  BREAKING CHANGES + +* Rename `accesskit_winit::Adapter::on_event` to `process_event` ([#307](https://github.com/AccessKit/accesskit/issues/307)) +* Bump winit to 0.29 ([#256](https://github.com/AccessKit/accesskit/issues/256)) + +### deps + +* Bump winit to 0.29 ([#256](https://github.com/AccessKit/accesskit/issues/256)) ([4eb21ff](https://github.com/AccessKit/accesskit/commit/4eb21ff64256fcf0a16ab831554b06b80de9b36e)) + + +### Bug Fixes + +* Add missing semicolons when not returning anything ([#303](https://github.com/AccessKit/accesskit/issues/303)) ([38d4de1](https://github.com/AccessKit/accesskit/commit/38d4de1442247e701047d75122a9638a2ed99b1f)) +* Use raw-window-handle 0.6 ([#310](https://github.com/AccessKit/accesskit/issues/310)) ([3fa69ab](https://github.com/AccessKit/accesskit/commit/3fa69ab4d9216b51b651d3cf2a9c8217a77069f4)) + + +### Code Refactoring + +* Rename `accesskit_winit::Adapter::on_event` to `process_event` ([#307](https://github.com/AccessKit/accesskit/issues/307)) ([6fbebde](https://github.com/AccessKit/accesskit/commit/6fbebdeb9d1e96b1776ed1faf7ad21d9cc0a68df)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.12.0 to 0.12.1 + * accesskit_windows bumped from 0.15.0 to 0.15.1 + * accesskit_macos bumped from 0.10.0 to 0.10.1 + * accesskit_unix bumped from 0.6.0 to 0.6.1 + +## [0.15.0](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.14.4...accesskit_winit-v0.15.0) (2023-09-27) + + +### âš  BREAKING CHANGES + +* Allow providing app_name, toolkit_name and toolkit_version in Tree, remove parameters from unix adapter constructor ([#291](https://github.com/AccessKit/accesskit/issues/291)) +* Make `ActionHandler::do_action` take `&mut self` ([#296](https://github.com/AccessKit/accesskit/issues/296)) +* Decouple in-tree focus from host window/view focus ([#278](https://github.com/AccessKit/accesskit/issues/278)) +* Switch to simple unsigned 64-bit integer for node IDs ([#276](https://github.com/AccessKit/accesskit/issues/276)) + +### Features + +* Allow providing app_name, toolkit_name and toolkit_version in Tree, remove parameters from unix adapter constructor ([#291](https://github.com/AccessKit/accesskit/issues/291)) ([5313860](https://github.com/AccessKit/accesskit/commit/531386023257150f49b5e4be942f359855fb7cb6)) + + +### Bug Fixes + +* Fix doc build for accesskit_winit ([#281](https://github.com/AccessKit/accesskit/issues/281)) ([e3b38b8](https://github.com/AccessKit/accesskit/commit/e3b38b8164d0c5442a5a1904165e2b05847376c2)) + + +### Code Refactoring + +* Decouple in-tree focus from host window/view focus ([#278](https://github.com/AccessKit/accesskit/issues/278)) ([d360d20](https://github.com/AccessKit/accesskit/commit/d360d20cf951e7643b81a5303006c9f7daa5bd56)) +* Make `ActionHandler::do_action` take `&mut self` ([#296](https://github.com/AccessKit/accesskit/issues/296)) ([4fc7846](https://github.com/AccessKit/accesskit/commit/4fc7846d732d61fb45c023060ebab96801a0053e)) +* Switch to simple unsigned 64-bit integer for node IDs ([#276](https://github.com/AccessKit/accesskit/issues/276)) ([3eadd48](https://github.com/AccessKit/accesskit/commit/3eadd48ec47854faa94a94ebf910ec08f514642f)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.11.2 to 0.12.0 + * accesskit_windows bumped from 0.14.3 to 0.15.0 + * accesskit_macos bumped from 0.9.0 to 0.10.0 + * accesskit_unix bumped from 0.5.2 to 0.6.0 + +## [0.14.0](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.13.0...accesskit_winit-v0.14.0) (2023-05-21) + + +### Features + +* Add features for async runtimes on Unix ([#248](https://github.com/AccessKit/accesskit/issues/248)) ([b56b4ea](https://github.com/AccessKit/accesskit/commit/b56b4ea7c967ee5a1dae21a2fa0dcd385346031e)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit_unix bumped from 0.4.0 to 0.5.0 + +## [0.13.0](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.12.5...accesskit_winit-v0.13.0) (2023-03-30) + + +### âš  BREAKING CHANGES + +* Force a semver-breaking version bump in downstream crates ([#234](https://github.com/AccessKit/accesskit/issues/234)) + +### Bug Fixes + +* Force a semver-breaking version bump in downstream crates ([#234](https://github.com/AccessKit/accesskit/issues/234)) ([773389b](https://github.com/AccessKit/accesskit/commit/773389bff857fa18edf15de426e029251fc34591)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit_windows bumped from 0.13.3 to 0.14.0 + * accesskit_macos bumped from 0.6.3 to 0.7.0 + * accesskit_unix bumped from 0.3.3 to 0.4.0 + +## [0.12.0](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.11.0...accesskit_winit-v0.12.0) (2023-02-18) + + +### Features + +* Feature-gate the Unix adapter in accesskit_winit ([#214](https://github.com/AccessKit/accesskit/issues/214)) ([be95807](https://github.com/AccessKit/accesskit/commit/be95807dda64f2a49b4d20cc9084b14a7aa2844e)) + +## [0.11.0](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.10.0...accesskit_winit-v0.11.0) (2023-02-12) + + +### âš  BREAKING CHANGES + +* Move thread synchronization into platform adapters; drop parking_lot ([#212](https://github.com/AccessKit/accesskit/issues/212)) + +### Code Refactoring + +* Move thread synchronization into platform adapters; drop parking_lot ([#212](https://github.com/AccessKit/accesskit/issues/212)) ([5df52e5](https://github.com/AccessKit/accesskit/commit/5df52e5545faddf6a51905409013c2f5be23981e)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.9.0 to 0.10.0 + * accesskit_windows bumped from 0.12.0 to 0.13.0 + * accesskit_macos bumped from 0.5.0 to 0.6.0 + * accesskit_unix bumped from 0.2.0 to 0.3.0 + +## [0.10.0](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.9.1...accesskit_winit-v0.10.0) (2023-02-05) + + +### âš  BREAKING CHANGES + +* Make `Node` opaque and optimize it for size ([#205](https://github.com/AccessKit/accesskit/issues/205)) + +### Code Refactoring + +* Make `Node` opaque and optimize it for size ([#205](https://github.com/AccessKit/accesskit/issues/205)) ([4811152](https://github.com/AccessKit/accesskit/commit/48111521439b76c1a8687418a4b20f9b705eac6d)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.8.1 to 0.9.0 + * accesskit_windows bumped from 0.11.0 to 0.12.0 + * accesskit_macos bumped from 0.4.2 to 0.5.0 + * accesskit_unix bumped from 0.1.1 to 0.2.0 + +## [0.9.1](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.9.0...accesskit_winit-v0.9.1) (2023-02-05) + + +### Bug Fixes + +* Don't force winit's X11 and Wayland features to be enabled ([#209](https://github.com/AccessKit/accesskit/issues/209)) ([a3ed357](https://github.com/AccessKit/accesskit/commit/a3ed35754ad8f69a8ed54adacc30b6d57c19329a)) + +## [0.9.0](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.8.1...accesskit_winit-v0.9.0) (2023-02-02) + + +### âš  BREAKING CHANGES + +* Update winit to 0.28 ([#207](https://github.com/AccessKit/accesskit/issues/207)) + +### Miscellaneous Chores + +* Update winit to 0.28 ([#207](https://github.com/AccessKit/accesskit/issues/207)) ([3ff0cf5](https://github.com/AccessKit/accesskit/commit/3ff0cf59f982af504499142a3804f7aeeb4defe0)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit_windows bumped from 0.10.4 to 0.11.0 + +## [0.8.0](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.7.3...accesskit_winit-v0.8.0) (2023-01-05) + + +### Features + +* Basic Unix platform adapter ([#198](https://github.com/AccessKit/accesskit/issues/198)) ([1cea32e](https://github.com/AccessKit/accesskit/commit/1cea32e44ee743b778ac941ceff9087ae745cb37)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit_windows bumped from 0.10.2 to 0.10.3 + * accesskit_macos bumped from 0.4.0 to 0.4.1 + +## [0.7.0](https://github.com/AccessKit/accesskit/compare/accesskit_winit-v0.6.6...accesskit_winit-v0.7.0) (2022-11-29) + + +### âš  BREAKING CHANGES + +* Move lazy initialization from the core platform adapter to the caller ([#179](https://github.com/AccessKit/accesskit/issues/179)) + +### Code Refactoring + +* Move lazy initialization from the core platform adapter to the caller ([#179](https://github.com/AccessKit/accesskit/issues/179)) ([f35c941](https://github.com/AccessKit/accesskit/commit/f35c941f395f3162db376a69cfaaaf770d376267)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit_windows bumped from 0.9.3 to 0.10.0 + * accesskit_macos bumped from 0.1.5 to 0.2.0 + +### [0.6.4](https://www.github.com/AccessKit/accesskit/compare/accesskit_winit-v0.6.3...accesskit_winit-v0.6.4) (2022-11-25) + + +### Bug Fixes + +* Reduce the winit version requirement to match egui ([#170](https://www.github.com/AccessKit/accesskit/issues/170)) ([1d27482](https://www.github.com/AccessKit/accesskit/commit/1d27482221140c1f3b3e3eaf93e7feaf8105611d)) + +## [0.6.0](https://www.github.com/AccessKit/accesskit/compare/accesskit_winit-v0.5.1...accesskit_winit-v0.6.0) (2022-11-23) + + +### Features + +* **platforms/macos:** Basic macOS platform adapter ([#158](https://www.github.com/AccessKit/accesskit/issues/158)) ([a06725e](https://www.github.com/AccessKit/accesskit/commit/a06725e952e6041dbd366944fa793b746c9f195e)) + + +### Bug Fixes + +* **platforms/macos:** Fix macOS crate version number ([#161](https://www.github.com/AccessKit/accesskit/issues/161)) ([e0a6a40](https://www.github.com/AccessKit/accesskit/commit/e0a6a401050cdcaea4efa870ed77ae94388f1ce0)) +* **platforms/windows:** Re-export the windows-rs HWND type ([#159](https://www.github.com/AccessKit/accesskit/issues/159)) ([389187a](https://www.github.com/AccessKit/accesskit/commit/389187ac5e96895ed1763d14d315d2f8f4256460)) + +### [0.5.1](https://www.github.com/AccessKit/accesskit/compare/accesskit_winit-v0.5.0...accesskit_winit-v0.5.1) (2022-11-17) + + +### Bug Fixes + +* **platforms/winit:** Eliminate some problematic indirect dependencies ([#154](https://www.github.com/AccessKit/accesskit/issues/154)) ([58048ae](https://www.github.com/AccessKit/accesskit/commit/58048aebedc293eda5c5819ea66db9b40b8926b0)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.7.0 to 0.8.0 + +## [0.5.0](https://www.github.com/AccessKit/accesskit/compare/accesskit_winit-v0.4.0...accesskit_winit-v0.5.0) (2022-11-14) + + +### Features + +* **platforms/winit:** Allow a custom action handler ([#149](https://www.github.com/AccessKit/accesskit/issues/149)) ([cdb1a16](https://www.github.com/AccessKit/accesskit/commit/cdb1a164de06f18cad497409a514f270a8336b4c)) + +## [0.4.0](https://www.github.com/AccessKit/accesskit/compare/accesskit_winit-v0.3.3...accesskit_winit-v0.4.0) (2022-11-12) + + +### âš  BREAKING CHANGES + +* **platforms/windows:** Update to windows-rs 0.42.0 (#148) + +### Bug Fixes + +* **consumer, platforms/windows, platforms/winit:** Update to parking_lot 0.12.1 ([#146](https://www.github.com/AccessKit/accesskit/issues/146)) ([6772855](https://www.github.com/AccessKit/accesskit/commit/6772855a7b540fd728faad15d8d208b05c1bbd8a)) +* **platforms/windows:** Update to windows-rs 0.42.0 ([#148](https://www.github.com/AccessKit/accesskit/issues/148)) ([70d1a89](https://www.github.com/AccessKit/accesskit/commit/70d1a89f51fd6c3a32b7192d9d7f3937db09d196)) + +### [0.3.3](https://www.github.com/AccessKit/accesskit/compare/accesskit_winit-v0.3.2...accesskit_winit-v0.3.3) (2022-11-11) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.6.1 to 0.7.0 + +### [0.3.2](https://www.github.com/AccessKit/accesskit/compare/accesskit_winit-v0.3.1...accesskit_winit-v0.3.2) (2022-10-11) + + +### Bug Fixes + +* **platforms/winit:** Derive `Debug` on `ActionRequestEvent` ([#141](https://www.github.com/AccessKit/accesskit/issues/141)) ([8b84c75](https://www.github.com/AccessKit/accesskit/commit/8b84c7547c6fdb52cd6d5c6d79f812dc614f08dd)) + +### [0.3.1](https://www.github.com/AccessKit/accesskit/compare/accesskit_winit-v0.3.0...accesskit_winit-v0.3.1) (2022-10-10) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.6.0 to 0.6.1 + +## [0.3.0](https://www.github.com/AccessKit/accesskit/compare/accesskit_winit-v0.2.1...accesskit_winit-v0.3.0) (2022-10-09) + + +### âš  BREAKING CHANGES + +* Wrap `TreeUpdate` nodes in `Arc` (#135) +* Store node ID in `TreeUpdate`, not `accesskit::Node` (#132) + +### Code Refactoring + +* Store node ID in `TreeUpdate`, not `accesskit::Node` ([#132](https://www.github.com/AccessKit/accesskit/issues/132)) ([0bb86dd](https://www.github.com/AccessKit/accesskit/commit/0bb86ddb298cb5a253a91f07be0bad8b84b2fda3)) +* Wrap `TreeUpdate` nodes in `Arc` ([#135](https://www.github.com/AccessKit/accesskit/issues/135)) ([907bc18](https://www.github.com/AccessKit/accesskit/commit/907bc1820b80d95833b6c5c3acaa2a8a4e93a6c2)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.5.1 to 0.6.0 + +### [0.2.1](https://www.github.com/AccessKit/accesskit/compare/accesskit_winit-v0.2.0...accesskit_winit-v0.2.1) (2022-10-03) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.5.0 to 0.5.1 + +## [0.2.0](https://www.github.com/AccessKit/accesskit/compare/accesskit_winit-v0.1.0...accesskit_winit-v0.2.0) (2022-09-23) + + +### âš  BREAKING CHANGES + +* Basic live regions (#128) +* **platforms/windows:** Bump windows-rs dependency (#126) +* **platforms/winit:** Bump winit dependency (#125) + +### Features + +* Basic live regions ([#128](https://www.github.com/AccessKit/accesskit/issues/128)) ([03d745b](https://www.github.com/AccessKit/accesskit/commit/03d745b891147175bde2693cc10b96a2f6e31f39)) + + +### Miscellaneous Chores + +* **platforms/windows:** Bump windows-rs dependency ([#126](https://www.github.com/AccessKit/accesskit/issues/126)) ([472a75e](https://www.github.com/AccessKit/accesskit/commit/472a75e4214b90396f3282f247df08100ed8362d)) +* **platforms/winit:** Bump winit dependency ([#125](https://www.github.com/AccessKit/accesskit/issues/125)) ([6026c1b](https://www.github.com/AccessKit/accesskit/commit/6026c1b2ecede3ca2f2076075ed158000154b34e)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.4.0 to 0.5.0 + +## 0.1.0 (2022-07-22) + + +### Features + +* **platforms/winit:** New winit adapter ([#121](https://www.github.com/AccessKit/accesskit/issues/121)) ([fdc274e](https://www.github.com/AccessKit/accesskit/commit/fdc274e7d3a901873d2ad0c7a4824a19111787ef)) + + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * accesskit bumped from 0.3.0 to 0.4.0 diff --git a/packages/accesskit_xplat/Cargo.toml b/packages/accesskit_xplat/Cargo.toml new file mode 100644 index 000000000..f8a13d2d7 --- /dev/null +++ b/packages/accesskit_xplat/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "accesskit_xplat" +version = "0.1.0" +license = "Apache-2.0" +description = "AccessKit UI accessibility infrastructure: cross-platform adapter" +keywords = ["gui", "ui", "accessibility"] +repository.workspace = true +edition.workspace = true +rust-version.workspace = true + +[features] +default = ["accesskit_unix", "async-io"] +async-io = ["accesskit_unix/async-io"] +tokio = ["accesskit_unix/tokio"] + +[dependencies] +accesskit = { version = "0.22" } +winit-core = { version = "0.31.0-beta.2", default-features = false } +raw-window-handle = { version = "0.6.2", features = ["std"] } + +[target.'cfg(target_os = "windows")'.dependencies] +accesskit_windows = { version = "0.30.0" } + +[target.'cfg(target_os = "macos")'.dependencies] +accesskit_macos = { version = "0.23.0" } + +[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies] +accesskit_unix = { version = "0.18.0", optional = true, default-features = false } + +[target.'cfg(target_os = "android")'.dependencies] +accesskit_android = { version = "0.5.0", optional = true, features = ["embedded-dex"] } +android-activity = { version = "0.6.0" } + diff --git a/packages/accesskit_xplat/src/lib.rs b/packages/accesskit_xplat/src/lib.rs new file mode 100644 index 000000000..cfcac0827 --- /dev/null +++ b/packages/accesskit_xplat/src/lib.rs @@ -0,0 +1,168 @@ +// Copyright 2022 The AccessKit Authors. All rights reserved. +// Licensed under the Apache License, Version 2.0 (found in +// the LICENSE-APACHE file). + +/// ## Compatibility with async runtimes +/// +/// The following only applies on Linux/Unix: +/// +/// While this crate's API is purely blocking, it internally spawns asynchronous tasks on an executor. +/// +/// - If you use tokio, make sure to enable the `tokio` feature of this crate. +/// - If you use another async runtime or if you don't use one at all, the default feature will suit your needs. + +#[cfg(all( + feature = "accesskit_unix", + any( + target_os = "linux", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd" + ), + not(feature = "async-io"), + not(feature = "tokio") +))] +compile_error!("Either \"async-io\" (default) or \"tokio\" feature must be enabled."); + +#[cfg(all( + feature = "accesskit_unix", + any( + target_os = "linux", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd" + ), + feature = "async-io", + feature = "tokio" +))] +compile_error!( + "Both \"async-io\" (default) and \"tokio\" features cannot be enabled at the same time." +); + +use std::sync::Arc; + +use accesskit::{ + ActionHandler, ActionRequest, ActivationHandler, DeactivationHandler, Rect, TreeUpdate, +}; + +#[cfg(target_os = "android")] +use android_activity::AndroidApp; +#[cfg(not(target_os = "android"))] +use raw_window_handle::RawWindowHandle; + +mod platform_impl; + +#[derive(Clone, Debug, PartialEq)] +pub enum WindowEvent { + InitialTreeRequested, + ActionRequested(ActionRequest), + AccessibilityDeactivated, +} + +pub trait EventHandler: Send + Sync + 'static { + fn handle_accesskit_event(&self, event: WindowEvent); +} + +#[derive(Clone)] +struct CombinedHandler(Arc); + +impl ActivationHandler for CombinedHandler { + fn request_initial_tree(&mut self) -> Option { + self.0 + .handle_accesskit_event(WindowEvent::InitialTreeRequested); + None + } +} +impl DeactivationHandler for CombinedHandler { + fn deactivate_accessibility(&mut self) { + self.0 + .handle_accesskit_event(WindowEvent::AccessibilityDeactivated); + } +} +impl ActionHandler for CombinedHandler { + fn do_action(&mut self, request: ActionRequest) { + self.0 + .handle_accesskit_event(WindowEvent::ActionRequested(request)); + } +} + +pub struct Adapter { + /// A user-supplied ID that we pass back to + inner: platform_impl::Adapter, +} + +impl Adapter { + /// Creates a new AccessKit adapter for a winit window. This must be done + /// before the window is shown for the first time. This means that you must + /// use [`winit::window::WindowAttributes::with_visible`] to make the window + /// initially invisible, then create the adapter, then show the window. + /// + /// Use this if you want to provide your own AccessKit handler callbacks + /// rather than dispatching requests through the winit event loop. This is + /// especially useful for the activation handler, because depending on + /// your application's architecture, implementing the handler directly may + /// allow you to return an initial tree synchronously, rather than requiring + /// some platform adapters to use a placeholder tree until you send + /// the first update. However, remember that each of these handlers may be + /// called on any thread, depending on the underlying platform adapter. + /// + /// # Panics + /// + /// Panics if the window is already visible. + pub fn with_split_handlers( + #[cfg(target_os = "android")] android_app: &AndroidApp, + #[cfg(not(target_os = "android"))] window: RawWindowHandle, + activation_handler: impl 'static + ActivationHandler + Send, + action_handler: impl 'static + ActionHandler + Send, + deactivation_handler: impl 'static + DeactivationHandler + Send, + ) -> Self { + let inner = platform_impl::Adapter::new( + #[cfg(target_os = "android")] + android_app, + #[cfg(not(target_os = "android"))] + &window, + activation_handler, + action_handler, + deactivation_handler, + ); + Self { inner } + } + + pub fn with_combined_handler( + #[cfg(target_os = "android")] android_app: &AndroidApp, + #[cfg(not(target_os = "android"))] window: RawWindowHandle, + handler: Arc, + ) -> Self { + let handler = CombinedHandler(handler); + let inner = platform_impl::Adapter::new( + #[cfg(target_os = "android")] + android_app, + #[cfg(not(target_os = "android"))] + &window, + handler.clone(), + handler.clone(), + handler, + ); + Self { inner } + } + + /// If and only if the tree has been initialized, call the provided function + /// and apply the resulting update. Note: If the caller's implementation of + /// [`ActivationHandler::request_initial_tree`] initially returned `None`, + /// or if the caller created the adapter using [`EventLoopProxy`], then + /// the [`TreeUpdate`] returned by the provided function must contain + /// a full tree. + pub fn update_if_active(&mut self, updater: impl FnOnce() -> TreeUpdate) { + self.inner.update_if_active(updater); + } + + pub fn set_focus(&mut self, is_focused: bool) { + self.inner.set_focus(is_focused); + } + + pub fn set_window_bounds(&mut self, outer_bounds: Rect, inner_bounds: Rect) { + self.inner.set_window_bounds(outer_bounds, inner_bounds); + } +} diff --git a/packages/accesskit_xplat/src/platform_impl/android.rs b/packages/accesskit_xplat/src/platform_impl/android.rs new file mode 100644 index 000000000..89f2dfd7f --- /dev/null +++ b/packages/accesskit_xplat/src/platform_impl/android.rs @@ -0,0 +1,46 @@ +// Copyright 2025 The AccessKit Authors. All rights reserved. +// Licensed under the Apache License, Version 2.0 (found in +// the LICENSE-APACHE file). + +use accesskit::{ActionHandler, ActivationHandler, DeactivationHandler, TreeUpdate}; +use accesskit_android::{ + InjectingAdapter, + jni::{JavaVM, objects::JObject}, +}; +use android_activity::AndroidApp; + +pub struct Adapter { + adapter: InjectingAdapter, +} + +impl Adapter { + pub fn new( + android_app: &AndroidApp, + activation_handler: impl 'static + ActivationHandler + Send, + action_handler: impl 'static + ActionHandler + Send, + _deactivation_handler: impl 'static + DeactivationHandler, + ) -> Self { + let vm = unsafe { JavaVM::from_raw(android_app.vm_as_ptr() as *mut _) }.unwrap(); + let mut env = vm.get_env().unwrap(); + let activity = unsafe { JObject::from_raw(android_app.activity_as_ptr() as *mut _) }; + let view = env + .get_field( + &activity, + "mSurfaceView", + "Lcom/google/androidgamesdk/GameActivity$InputEnabledSurfaceView;", + ) + .unwrap() + .l() + .unwrap(); + let adapter = InjectingAdapter::new(&mut env, &view, activation_handler, action_handler); + Self { adapter } + } + + pub fn update_if_active(&mut self, updater: impl FnOnce() -> TreeUpdate) { + self.adapter.update_if_active(updater); + } + + pub fn set_focus(&mut self, is_focused: bool) {} + + pub fn set_window_bounds(&mut self, outer_bounds: Rect, inner_bounds: Rect) {} +} diff --git a/packages/accesskit_xplat/src/platform_impl/macos.rs b/packages/accesskit_xplat/src/platform_impl/macos.rs new file mode 100644 index 000000000..88a565838 --- /dev/null +++ b/packages/accesskit_xplat/src/platform_impl/macos.rs @@ -0,0 +1,43 @@ +// Copyright 2022 The AccessKit Authors. All rights reserved. +// Licensed under the Apache License, Version 2.0 (found in +// the LICENSE-APACHE file). + +use accesskit::{ActionHandler, ActivationHandler, DeactivationHandler, Rect, TreeUpdate}; +use accesskit_macos::SubclassingAdapter; +use raw_window_handle::RawWindowHandle; + +pub struct Adapter { + adapter: SubclassingAdapter, +} + +impl Adapter { + pub fn new( + window_handle: &RawWindowHandle, + activation_handler: impl 'static + ActivationHandler, + action_handler: impl 'static + ActionHandler, + _deactivation_handler: impl 'static + DeactivationHandler, + ) -> Self { + let view = match window_handle { + RawWindowHandle::AppKit(handle) => handle.ns_view.as_ptr(), + RawWindowHandle::UiKit(_) => unimplemented!(), + _ => unreachable!(), + }; + + let adapter = unsafe { SubclassingAdapter::new(view, activation_handler, action_handler) }; + Self { adapter } + } + + pub fn update_if_active(&mut self, updater: impl FnOnce() -> TreeUpdate) { + if let Some(events) = self.adapter.update_if_active(updater) { + events.raise(); + } + } + + pub fn set_focus(&mut self, is_focused: bool) { + if let Some(events) = self.adapter.update_view_focus_state(is_focused) { + events.raise(); + } + } + + pub fn set_window_bounds(&mut self, _outer_bounds: Rect, _inner_bounds: Rect) {} +} diff --git a/packages/accesskit_xplat/src/platform_impl/mod.rs b/packages/accesskit_xplat/src/platform_impl/mod.rs new file mode 100644 index 000000000..27f7df0c5 --- /dev/null +++ b/packages/accesskit_xplat/src/platform_impl/mod.rs @@ -0,0 +1,50 @@ +// Copyright 2022 The AccessKit Authors. All rights reserved. +// Licensed under the Apache License, Version 2.0 (found in +// the LICENSE-APACHE file). + +// Based loosely on winit's src/platform_impl/mod.rs. + +pub use self::platform::*; + +#[cfg(target_os = "windows")] +#[path = "windows.rs"] +mod platform; + +#[cfg(target_os = "macos")] +#[path = "macos.rs"] +mod platform; + +#[cfg(all( + feature = "accesskit_unix", + any( + target_os = "linux", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd" + ) +))] +#[path = "unix.rs"] +mod platform; + +#[cfg(all(feature = "accesskit_android", target_os = "android"))] +#[path = "android.rs"] +mod platform; + +#[cfg(not(any( + target_os = "windows", + target_os = "macos", + all( + feature = "accesskit_unix", + any( + target_os = "linux", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd" + ) + ), + all(feature = "accesskit_android", target_os = "android") +)))] +#[path = "null.rs"] +mod platform; diff --git a/packages/accesskit_xplat/src/platform_impl/null.rs b/packages/accesskit_xplat/src/platform_impl/null.rs new file mode 100644 index 000000000..22ffa5dd1 --- /dev/null +++ b/packages/accesskit_xplat/src/platform_impl/null.rs @@ -0,0 +1,26 @@ +// Copyright 2022 The AccessKit Authors. All rights reserved. +// Licensed under the Apache License, Version 2.0 (found in +// the LICENSE-APACHE file). + +use accesskit::{ActionHandler, ActivationHandler, DeactivationHandler, Rect, TreeUpdate}; +use raw_window_handle::RawWindowHandle; + +pub struct Adapter; + +impl Adapter { + pub fn new( + #[cfg(target_os = "android")] _android_app: &AndroidApp, + #[cfg(not(target_os = "android"))] _window_handle: RawWindowHandle, + _activation_handler: impl 'static + ActivationHandler, + _action_handler: impl 'static + ActionHandler, + _deactivation_handler: impl 'static + DeactivationHandler, + ) -> Self { + Self {} + } + + pub fn update_if_active(&mut self, _updater: impl FnOnce() -> TreeUpdate) {} + + pub fn set_focus(&mut self, _is_focused: bool) {} + + pub fn set_window_bounds(&mut self, _outer_bounds: Rect, _inner_bounds: Rect) {} +} diff --git a/packages/accesskit_xplat/src/platform_impl/unix.rs b/packages/accesskit_xplat/src/platform_impl/unix.rs new file mode 100644 index 000000000..ee320e5c8 --- /dev/null +++ b/packages/accesskit_xplat/src/platform_impl/unix.rs @@ -0,0 +1,43 @@ +// Copyright 2022 The AccessKit Authors. All rights reserved. +// Licensed under the Apache License, Version 2.0 (found in +// the LICENSE-APACHE file). + +use accesskit::{ActionHandler, ActivationHandler, DeactivationHandler, Rect, TreeUpdate}; +use accesskit_unix::Adapter as UnixAdapter; +use raw_window_handle::RawWindowHandle; + +pub struct Adapter { + adapter: UnixAdapter, +} + +impl Adapter { + pub fn new( + _window_handle: &RawWindowHandle, + activation_handler: impl 'static + ActivationHandler + Send, + action_handler: impl 'static + ActionHandler + Send, + deactivation_handler: impl 'static + DeactivationHandler + Send, + ) -> Self { + let adapter = UnixAdapter::new(activation_handler, action_handler, deactivation_handler); + Self { adapter } + } + + fn set_root_window_bounds(&mut self, outer: Rect, inner: Rect) { + self.adapter.set_root_window_bounds(outer, inner); + } + + pub fn update_if_active(&mut self, updater: impl FnOnce() -> TreeUpdate) { + self.adapter.update_if_active(updater); + } + + fn update_window_focus_state(&mut self, is_focused: bool) { + self.adapter.update_window_focus_state(is_focused); + } + + pub fn set_focus(&mut self, is_focused: bool) { + self.update_window_focus_state(is_focused); + } + + pub fn set_window_bounds(&mut self, outer_bounds: Rect, inner_bounds: Rect) { + self.set_root_window_bounds(outer_bounds, inner_bounds) + } +} diff --git a/packages/accesskit_xplat/src/platform_impl/windows.rs b/packages/accesskit_xplat/src/platform_impl/windows.rs new file mode 100644 index 000000000..3b001dc1d --- /dev/null +++ b/packages/accesskit_xplat/src/platform_impl/windows.rs @@ -0,0 +1,39 @@ +// Copyright 2022 The AccessKit Authors. All rights reserved. +// Licensed under the Apache License, Version 2.0 (found in +// the LICENSE-APACHE file). + +use accesskit::{ActionHandler, ActivationHandler, DeactivationHandler, Rect, TreeUpdate}; +use accesskit_windows::{HWND, SubclassingAdapter}; +use raw_window_handle::RawWindowHandle; + +pub struct Adapter { + adapter: SubclassingAdapter, +} + +impl Adapter { + pub fn new( + window_handle: &RawWindowHandle, + activation_handler: impl 'static + ActivationHandler, + action_handler: impl 'static + ActionHandler + Send, + _deactivation_handler: impl 'static + DeactivationHandler, + ) -> Self { + let hwnd = match window_handle { + RawWindowHandle::Win32(handle) => handle.hwnd.get() as *mut _, + RawWindowHandle::WinRt(_) => unimplemented!(), + _ => unreachable!(), + }; + + let adapter = SubclassingAdapter::new(HWND(hwnd), activation_handler, action_handler); + Self { adapter } + } + + pub fn update_if_active(&mut self, updater: impl FnOnce() -> TreeUpdate) { + if let Some(events) = self.adapter.update_if_active(updater) { + events.raise(); + } + } + + pub fn set_focus(&mut self, _is_focused: bool) {} + + pub fn set_window_bounds(&mut self, _outer_bounds: Rect, _inner_bounds: Rect) {} +} diff --git a/packages/blitz-dom/src/document.rs b/packages/blitz-dom/src/document.rs index 2ada36754..56c479d93 100644 --- a/packages/blitz-dom/src/document.rs +++ b/packages/blitz-dom/src/document.rs @@ -29,7 +29,7 @@ use selectors::{Element, matching::QuirksMode}; use slab::Slab; use std::any::Any; use std::cell::RefCell; -use std::collections::{BTreeMap, Bound, HashMap, HashSet}; +use std::collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque}; use std::ops::{Deref, DerefMut}; use std::rc::Rc; use std::str::FromStr; @@ -174,6 +174,51 @@ pub enum DocumentEvent { ResourceLoad(ResourceLoadResponse), } +#[derive(Debug, Clone, PartialEq)] +pub(crate) struct FlingState { + pub(crate) target: usize, + pub(crate) last_seen_time: f64, + pub(crate) x_velocity: f64, + pub(crate) y_velocity: f64, +} + +#[derive(Debug, Clone, PartialEq)] +pub(crate) enum ScrollAnimationState { + None, + Fling(FlingState), +} + +#[derive(Debug, Clone, PartialEq)] +pub(crate) struct PanState { + pub(crate) target: usize, + pub(crate) last_x: f32, + pub(crate) last_y: f32, + pub(crate) samples: VecDeque, +} + +#[derive(Debug, Clone, PartialEq)] +pub(crate) struct PanSample { + pub(crate) time: u64, + pub(crate) dx: f32, + pub(crate) dy: f32, +} + +#[derive(Debug, Clone, PartialEq)] +pub(crate) enum DragMode { + /// We are not currently dragging + None, + /// We are currently dragging a selection (probably mouse) + Selecting, + /// We are currently panning the document with a drag (probably touch) + Panning(PanState), +} + +impl DragMode { + pub(crate) fn take(&mut self) -> DragMode { + std::mem::replace(self, DragMode::None) + } +} + pub struct BaseDocument { /// ID of the document id: usize, @@ -234,7 +279,9 @@ pub struct BaseDocument { /// How many clicks have been made in quick succession pub(crate) click_count: u16, /// Whether we're currently in a text selection drag (moved 2px+ from mousedown) - pub(crate) is_selecting: bool, + pub(crate) drag_mode: DragMode, + /// Whether and what kind of scroll animation is currently in progress + pub(crate) scroll_animation: ScrollAnimationState, /// Text selection state (for non-input text) pub(crate) text_selection: TextSelection, @@ -401,7 +448,8 @@ impl BaseDocument { last_mousedown_time: None, mousedown_position: taffy::Point::ZERO, click_count: 0, - is_selecting: false, + drag_mode: DragMode::None, + scroll_animation: ScrollAnimationState::None, text_selection: TextSelection::default(), }; @@ -1171,7 +1219,10 @@ impl BaseDocument { } pub fn is_animating(&self) -> bool { - self.has_canvas | self.has_active_animations | self.subdoc_is_animating + self.has_canvas + | self.has_active_animations + | self.subdoc_is_animating + | (self.scroll_animation != ScrollAnimationState::None) } /// Update the device and reset the stylist to process the new size @@ -1372,6 +1423,20 @@ impl BaseDocument { self.viewport_scroll != initial } + pub fn scroll_by( + &mut self, + anchor_node_id: Option, + scroll_x: f64, + scroll_y: f64, + dispatch_event: &mut dyn FnMut(DomEvent), + ) -> bool { + if let Some(anchor_node_id) = anchor_node_id { + self.scroll_node_by_has_changed(anchor_node_id, scroll_x, scroll_y, dispatch_event) + } else { + self.scroll_viewport_by_has_changed(scroll_x, scroll_y) + } + } + pub fn viewport_scroll(&self) -> crate::Point { self.viewport_scroll } diff --git a/packages/blitz-dom/src/events/driver.rs b/packages/blitz-dom/src/events/driver.rs index 4daa2e378..859914c2b 100644 --- a/packages/blitz-dom/src/events/driver.rs +++ b/packages/blitz-dom/src/events/driver.rs @@ -1,5 +1,5 @@ use crate::Document; -use blitz_traits::events::{BlitzMouseButtonEvent, DomEvent, DomEventData, EventState, UiEvent}; +use blitz_traits::events::{DomEvent, DomEventData, EventState, UiEvent}; use std::collections::VecDeque; pub trait EventHandler { @@ -37,8 +37,6 @@ impl<'doc, Handler: EventHandler> EventDriver<'doc, Handler> { pub fn handle_ui_event(&mut self, event: UiEvent) { let doc = self.doc.inner(); - let viewport_scroll = doc.viewport_scroll(); - let zoom = doc.viewport.zoom(); let mut hover_node_id = doc.hover_node_id; let focussed_node_id = doc.focus_node_id; @@ -48,8 +46,8 @@ impl<'doc, Handler: EventHandler> EventDriver<'doc, Handler> { match &event { UiEvent::MouseMove(event) => { let mut doc = self.doc.inner_mut(); - let dom_x = event.x + viewport_scroll.x as f32 / zoom; - let dom_y = event.y + viewport_scroll.y as f32 / zoom; + let dom_x = event.x; + let dom_y = event.y; let changed = doc.set_hover_to(dom_x, dom_y); let prev_hover_node_id = hover_node_id; @@ -142,21 +140,9 @@ impl<'doc, Handler: EventHandler> EventDriver<'doc, Handler> { }; let data = match event { - UiEvent::MouseMove(data) => DomEventData::MouseMove(BlitzMouseButtonEvent { - x: data.x + viewport_scroll.x as f32 / zoom, - y: data.y + viewport_scroll.y as f32 / zoom, - ..data - }), - UiEvent::MouseUp(data) => DomEventData::MouseUp(BlitzMouseButtonEvent { - x: data.x + viewport_scroll.x as f32 / zoom, - y: data.y + viewport_scroll.y as f32 / zoom, - ..data - }), - UiEvent::MouseDown(data) => DomEventData::MouseDown(BlitzMouseButtonEvent { - x: data.x + viewport_scroll.x as f32 / zoom, - y: data.y + viewport_scroll.y as f32 / zoom, - ..data - }), + UiEvent::MouseMove(data) => DomEventData::MouseMove(data), + UiEvent::MouseUp(data) => DomEventData::MouseUp(data), + UiEvent::MouseDown(data) => DomEventData::MouseDown(data), UiEvent::Wheel(data) => DomEventData::Wheel(data), UiEvent::KeyUp(data) => DomEventData::KeyUp(data), UiEvent::KeyDown(data) => DomEventData::KeyDown(data), diff --git a/packages/blitz-dom/src/events/ime.rs b/packages/blitz-dom/src/events/ime.rs index 635015681..ad629915a 100644 --- a/packages/blitz-dom/src/events/ime.rs +++ b/packages/blitz-dom/src/events/ime.rs @@ -41,6 +41,14 @@ pub(crate) fn handle_ime_event( } doc.shell_provider.request_redraw(); } + BlitzImeEvent::DeleteSurrounding { + before_bytes, + after_bytes, + } => { + let _ = before_bytes; + let _ = after_bytes; + // TODO + } } println!("Sent ime event to {node_id}"); } diff --git a/packages/blitz-dom/src/events/keyboard.rs b/packages/blitz-dom/src/events/keyboard.rs index ce8145001..d3611384a 100644 --- a/packages/blitz-dom/src/events/keyboard.rs +++ b/packages/blitz-dom/src/events/keyboard.rs @@ -237,6 +237,14 @@ fn apply_keypress_event( } return Some(GeneratedEvent::Input); } + Key::Character(c) if c == "\n" => { + if is_multiline { + driver.insert_or_replace_selection("\n"); + return Some(GeneratedEvent::Input); + } else { + return Some(GeneratedEvent::Submit); + } + } Key::Enter => { if is_multiline { driver.insert_or_replace_selection("\n"); diff --git a/packages/blitz-dom/src/events/mod.rs b/packages/blitz-dom/src/events/mod.rs index 45e4960a8..f4d05a982 100644 --- a/packages/blitz-dom/src/events/mod.rs +++ b/packages/blitz-dom/src/events/mod.rs @@ -26,22 +26,29 @@ pub(crate) fn handle_dom_event( let pos = node.absolute_position(0.0, 0.0); let mut set_focus = false; if let Some(sub_doc) = node.subdoc_mut() { + let viewport_scroll = sub_doc.inner().viewport_scroll(); // TODO: eliminate clone let ui_event = match event.data.clone() { DomEventData::MouseMove(mut mouse_event) => { - mouse_event.x -= pos.x; - mouse_event.y -= pos.y; + mouse_event.x -= pos.x - viewport_scroll.x as f32; + mouse_event.y -= pos.y - viewport_scroll.y as f32; + mouse_event.client_x -= pos.x; + mouse_event.client_y -= pos.y; Some(UiEvent::MouseMove(mouse_event)) } DomEventData::MouseDown(mut mouse_event) => { - mouse_event.x -= pos.x; - mouse_event.y -= pos.y; + mouse_event.x -= pos.x - viewport_scroll.x as f32; + mouse_event.y -= pos.y - viewport_scroll.y as f32; + mouse_event.client_x -= pos.x; + mouse_event.client_y -= pos.y; set_focus = true; Some(UiEvent::MouseDown(mouse_event)) } DomEventData::MouseUp(mut mouse_event) => { - mouse_event.x -= pos.x; - mouse_event.y -= pos.y; + mouse_event.x -= pos.x - viewport_scroll.x as f32; + mouse_event.y -= pos.y - viewport_scroll.y as f32; + mouse_event.client_x -= pos.x; + mouse_event.client_y -= pos.y; set_focus = true; Some(UiEvent::MouseUp(mouse_event)) } @@ -85,15 +92,7 @@ pub(crate) fn handle_dom_event( match &event.data { DomEventData::MouseMove(mouse_event) => { - let changed = handle_mousemove( - doc, - target_node_id, - mouse_event.x, - mouse_event.y, - mouse_event.buttons, - mouse_event, - dispatch_event, - ); + let changed = handle_mousemove(doc, target_node_id, mouse_event, dispatch_event); if changed { doc.shell_provider.request_redraw(); } diff --git a/packages/blitz-dom/src/events/mouse.rs b/packages/blitz-dom/src/events/mouse.rs index b66441bf4..e3feba3a4 100644 --- a/packages/blitz-dom/src/events/mouse.rs +++ b/packages/blitz-dom/src/events/mouse.rs @@ -1,37 +1,91 @@ -use std::time::{Duration, Instant}; +use std::{ + collections::VecDeque, + time::{Duration, Instant, SystemTime, UNIX_EPOCH}, +}; use blitz_traits::{ events::{ - BlitzInputEvent, BlitzMouseButtonEvent, BlitzWheelDelta, BlitzWheelEvent, DomEvent, - DomEventData, MouseEventButton, MouseEventButtons, + BlitzInputEvent, BlitzPointerEvent, BlitzPointerId, BlitzWheelDelta, BlitzWheelEvent, + DomEvent, DomEventData, MouseEventButton, MouseEventButtons, }, navigation::NavigationOptions, }; use keyboard_types::Modifiers; use markup5ever::local_name; -use crate::{BaseDocument, node::SpecialElementData}; +use crate::{ + BaseDocument, + document::{DragMode, FlingState, PanSample, PanState, ScrollAnimationState}, + node::SpecialElementData, +}; use super::focus::generate_focus_events; pub(crate) fn handle_mousemove( doc: &mut BaseDocument, target: usize, - x: f32, - y: f32, - buttons: MouseEventButtons, - event: &BlitzMouseButtonEvent, + event: &BlitzPointerEvent, mut dispatch_event: F, ) -> bool { + let x = event.x; + let y = event.y; + let buttons = event.buttons; + let mut changed = doc.set_hover_to(x, y); // Check if we've moved enough to be considered a selection drag (2px threshold) - if buttons != MouseEventButtons::None && !doc.is_selecting { - let dx = (x - doc.mousedown_position.x).abs(); - let dy = (y - doc.mousedown_position.y).abs(); - if dx > 2.0 || dy > 2.0 { - doc.is_selecting = true; + if buttons != MouseEventButtons::None && doc.drag_mode == DragMode::None { + let dx = x - doc.mousedown_position.x; + let dy = y - doc.mousedown_position.y; + if dx.abs() > 2.0 || dy.abs() > 2.0 { + match event.id { + BlitzPointerId::Mouse => { + doc.drag_mode = DragMode::Selecting; + } + BlitzPointerId::Finger(_) => { + doc.drag_mode = DragMode::Panning(PanState { + target, + last_x: event.screen_x, + last_y: event.screen_y, + samples: VecDeque::with_capacity(200), + }); + } + } + } + } + + if let DragMode::Panning(state) = &mut doc.drag_mode { + let dx = (event.screen_x - state.last_x) as f64; + let dy = (event.screen_y - state.last_y) as f64; + let time_ms = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis() as u64; + + let target = state.target; + state.last_x = event.screen_x; + state.last_y = event.screen_y; + + state.samples.push_back(PanSample { + time: time_ms, + // TODO: account for scroll delta not applied due to clamping + dx: dx as f32, + dy: dy as f32, + }); + + // Remove samples older than 100ms + if state.samples.len() > 50 && time_ms - state.samples.front().unwrap().time > 100 { + let idx = state + .samples + .partition_point(|sample| time_ms - sample.time > 100); + // FIXME: use truncate_front once stable + for _ in 0..idx { + state.samples.pop_front(); + } } + + let has_changed = doc.scroll_by(Some(target), dx, dy, &mut dispatch_event); + return has_changed; } let Some(hit) = doc.hit(x, y) else { @@ -123,7 +177,8 @@ pub(crate) fn handle_mousedown( // Update mousedown tracking for next click and selection drag detection doc.last_mousedown_time = Some(Instant::now()); doc.mousedown_position = taffy::Point { x, y }; - doc.is_selecting = false; + doc.drag_mode = DragMode::None; + doc.scroll_animation = ScrollAnimationState::None; let Some(hit) = doc.hit(x, y) else { // Clear text selection when clicking outside any element @@ -228,7 +283,7 @@ pub(crate) fn handle_mousedown( pub(crate) fn handle_mouseup( doc: &mut BaseDocument, target: usize, - event: &BlitzMouseButtonEvent, + event: &BlitzPointerEvent, mut dispatch_event: F, ) { if doc.devtools().highlight_hover { @@ -243,11 +298,66 @@ pub(crate) fn handle_mouseup( return; } - // Don't dispatch click if we were doing a text selection drag - let do_click = !doc.is_selecting; + // Reset Document's drag state to DragMode::None, storing the state + // locally for use within this function + let drag_mode = doc.drag_mode.take(); + + // Don't dispatch click if we were doing a text selection drag or panning + // the document with a touch + let do_click = drag_mode == DragMode::None; + + let time_ms = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis() as u64; + + if let DragMode::Panning(state) = &drag_mode { + // Generate "fling" + if let Some(last_sample) = state.samples.back() + && time_ms - last_sample.time < 100 + { + let idx = state + .samples + .partition_point(|sample| time_ms - sample.time > 100); + + // Compute pan_time. Will always be <= 100ms as we ignore samples older than that. + let pan_start_time = state.samples[idx].time; + let pan_time = (time_ms - pan_start_time) as f32; + + // Avoid division by 0 + if pan_time > 0.0 { + let (pan_x, pan_y) = state + .samples + .iter() + .skip(idx) + .fold((0.0, 0.0), |(dx, dy), sample| { + (dx + sample.dx, dy + sample.dy) + }); + + let x_velocity = if pan_x.abs() > pan_y.abs() { + pan_x / pan_time + } else { + 0.0 + }; + + let y_velocity = if pan_y.abs() > pan_x.abs() { + pan_y / pan_time + } else { + 0.0 + }; - // Reset selection state - doc.is_selecting = false; + let fling = FlingState { + target: state.target, + last_seen_time: time_ms as f64, + x_velocity: x_velocity as f64 * 2.0, + y_velocity: y_velocity as f64 * 2.0, + }; + + doc.scroll_animation = ScrollAnimationState::Fling(fling); + doc.shell_provider.request_redraw(); + } + } + } // Dispatch a click event if do_click && event.button == MouseEventButton::Main { @@ -266,7 +376,7 @@ pub(crate) fn handle_mouseup( pub(crate) fn handle_click( doc: &mut BaseDocument, target: usize, - event: &BlitzMouseButtonEvent, + event: &BlitzPointerEvent, dispatch_event: &mut dyn FnMut(DomEvent), ) { let double_click_event = event.clone(); @@ -431,19 +541,19 @@ pub(crate) fn handle_wheel( doc: &mut BaseDocument, _: usize, event: BlitzWheelEvent, - dispatch_event: F, + mut dispatch_event: F, ) { let (scroll_x, scroll_y) = match event.delta { BlitzWheelDelta::Lines(x, y) => (x * 20.0, y * 20.0), BlitzWheelDelta::Pixels(x, y) => (x, y), }; - let has_changed = if let Some(hover_node_id) = doc.get_hover_node_id() { - doc.scroll_node_by_has_changed(hover_node_id, scroll_x, scroll_y, dispatch_event) - } else { - doc.scroll_viewport_by_has_changed(scroll_x, scroll_y) - }; - + let has_changed = doc.scroll_by( + doc.get_hover_node_id(), + scroll_x, + scroll_y, + &mut dispatch_event, + ); if has_changed { doc.shell_provider.request_redraw(); } diff --git a/packages/blitz-dom/src/node/node.rs b/packages/blitz-dom/src/node/node.rs index 0fdf07d98..6c4c145fc 100644 --- a/packages/blitz-dom/src/node/node.rs +++ b/packages/blitz-dom/src/node/node.rs @@ -1,6 +1,6 @@ use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut}; use bitflags::bitflags; -use blitz_traits::events::{BlitzMouseButtonEvent, DomEventData, HitResult}; +use blitz_traits::events::{BlitzPointerEvent, BlitzPointerId, DomEventData, HitResult}; use blitz_traits::shell::ShellProvider; use html_escape::encode_quoted_attribute_to_string; use keyboard_types::Modifiers; @@ -1047,14 +1047,23 @@ impl Node { DomEventData::Click(self.synthetic_click_event_data(mods)) } - pub fn synthetic_click_event_data(&self, mods: Modifiers) -> BlitzMouseButtonEvent { + pub fn synthetic_click_event_data(&self, mods: Modifiers) -> BlitzPointerEvent { let absolute_position = self.absolute_position(0.0, 0.0); let x = absolute_position.x + (self.final_layout.size.width / 2.0); let y = absolute_position.y + (self.final_layout.size.height / 2.0); - BlitzMouseButtonEvent { + BlitzPointerEvent { + id: BlitzPointerId::Mouse, + is_primary: true, x, y, + + // TODO: should these be different? + screen_x: x, + screen_y: y, + client_x: x, + client_y: y, + mods, button: Default::default(), buttons: Default::default(), diff --git a/packages/blitz-dom/src/resolve.rs b/packages/blitz-dom/src/resolve.rs index 37fa16972..ff001ff7e 100644 --- a/packages/blitz-dom/src/resolve.rs +++ b/packages/blitz-dom/src/resolve.rs @@ -1,6 +1,9 @@ //! Resolve style and layout -use std::cell::RefCell; +use std::{ + cell::RefCell, + time::{SystemTime, UNIX_EPOCH}, +}; use debug_timer::debug_timer; use parley::LayoutContext; @@ -22,6 +25,7 @@ use taffy::AvailableSpace; use crate::{ BaseDocument, NON_INCREMENTAL, + document::ScrollAnimationState, layout::{ construct::{ ConstructionTask, ConstructionTaskData, ConstructionTaskResult, @@ -46,6 +50,8 @@ impl BaseDocument { // Process messages that have been sent to our message channel (e.g. loaded resource) self.handle_messages(); + self.resolve_scroll_animation(); + let root_node_id = self.root_element().id; debug_timer!(timer, feature = "log_phase_times"); @@ -110,6 +116,38 @@ impl BaseDocument { timer.print_times(&format!("Resolve({}): ", self.id())); } + pub fn resolve_scroll_animation(&mut self) { + match &mut self.scroll_animation { + ScrollAnimationState::Fling(fling_state) => { + let time_ms = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis() as u64 as f64; + + let time_diff_ms = time_ms - fling_state.last_seen_time; + + // 0.95 @ 60fps normalized to actual frame times + let deceleration = 1.0 - ((0.05 / 16.66666) * time_diff_ms); + + fling_state.x_velocity *= deceleration; + fling_state.y_velocity *= deceleration; + fling_state.last_seen_time = time_ms; + let fling_state = fling_state.clone(); + + let dx = fling_state.x_velocity * time_diff_ms; + let dy = fling_state.y_velocity * time_diff_ms; + + self.scroll_by(Some(fling_state.target), dx, dy, &mut |_| {}); + if fling_state.x_velocity.abs() < 0.1 && fling_state.y_velocity.abs() < 0.1 { + self.scroll_animation = ScrollAnimationState::None; + } + } + ScrollAnimationState::None => { + // Do nothing + } + } + } + /// Ensure that the layout_children field is populated for all nodes pub fn resolve_layout_children(&mut self) { resolve_layout_children_recursive(self, self.root_node().id); diff --git a/packages/blitz-net/Cargo.toml b/packages/blitz-net/Cargo.toml index e79183e10..30d0e6c86 100644 --- a/packages/blitz-net/Cargo.toml +++ b/packages/blitz-net/Cargo.toml @@ -11,6 +11,7 @@ edition.workspace = true rust-version.workspace = true [features] +http2 = ["reqwest/http2"] cookies = ["reqwest/cookies"] multipart = ["reqwest/multipart", "reqwest/stream"] cache = ["dep:reqwest-middleware", "dep:http-cache-reqwest", "dep:directories"] @@ -22,7 +23,7 @@ blitz-traits = { workspace = true } # Networking dependencies tokio = { workspace = true } -reqwest = { workspace = true } +reqwest = { workspace = true, features = ["charset", "rustls-tls"] } data-url = { workspace = true } # Caching diff --git a/packages/blitz-paint/src/lib.rs b/packages/blitz-paint/src/lib.rs index 62f56008e..9b3c4de91 100644 --- a/packages/blitz-paint/src/lib.rs +++ b/packages/blitz-paint/src/lib.rs @@ -31,8 +31,11 @@ pub fn paint_scene( scale: f64, width: u32, height: u32, + x_offset: u32, + y_offset: u32, ) { - let generator = BlitzDomPainter::new(dom, scale, width, height, 0.0, 0.0); + let generator = + BlitzDomPainter::new(dom, scale, width, height, x_offset as f64, y_offset as f64); generator.paint_scene(scene); // println!( diff --git a/packages/blitz-paint/src/render.rs b/packages/blitz-paint/src/render.rs index b395d54e2..d40ef6f14 100644 --- a/packages/blitz-paint/src/render.rs +++ b/packages/blitz-paint/src/render.rs @@ -141,7 +141,10 @@ impl<'dom> BlitzDomPainter<'dom> { if let Some(bg_color) = background_color { let bg_color = bg_color.as_srgb_color(); - let rect = Rect::from_origin_size((0.0, 0.0), (bg_width as f64, bg_height as f64)); + let rect = Rect::from_origin_size( + (self.initial_x * self.scale, self.initial_y * self.scale), + (bg_width as f64, bg_height as f64), + ); scene.fill(Fill::NonZero, Affine::IDENTITY, bg_color, None, &rect); } diff --git a/packages/blitz-shell/Cargo.toml b/packages/blitz-shell/Cargo.toml index 89d3416d6..bb79569b3 100644 --- a/packages/blitz-shell/Cargo.toml +++ b/packages/blitz-shell/Cargo.toml @@ -14,7 +14,7 @@ rust-version.workspace = true default = ["accessibility", "clipboard", "file_dialog"] accessibility = [ "dep:accesskit", - "dep:accesskit_winit", + "dep:accesskit_xplat", "blitz-dom/accessibility", ] clipboard = ["dep:arboard"] @@ -34,7 +34,7 @@ anyrender = { workspace = true } winit = { workspace = true } keyboard-types = { workspace = true } accesskit = { workspace = true, optional = true } -accesskit_winit = { workspace = true, optional = true } +accesskit_xplat = { workspace = true, optional = true } # Other dependencies tracing = { workspace = true, optional = true } @@ -42,7 +42,7 @@ futures-util = { workspace = true } data-url = { workspace = true, optional = true } [target.'cfg(target_os = "android")'.dependencies] -android-activity = { version = "0.6.0", features = ["native-activity"] } +android-activity = { version = "0.6.0" } [target.'cfg(any(target_os = "windows",target_os = "macos",target_os = "linux",target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))'.dependencies] arboard = { workspace = true, optional = true } diff --git a/packages/blitz-shell/src/accessibility.rs b/packages/blitz-shell/src/accessibility.rs index 07aeb9c8d..ab3f6e333 100644 --- a/packages/blitz-shell/src/accessibility.rs +++ b/packages/blitz-shell/src/accessibility.rs @@ -1,22 +1,74 @@ -use crate::event::BlitzShellEvent; -use accesskit_winit::Adapter; +use crate::{BlitzShellEvent, event::BlitzShellProxy}; +use accesskit::Rect; +use accesskit_xplat::{Adapter, EventHandler, WindowEvent as AccessKitEvent}; use blitz_dom::BaseDocument; -use winit::{event_loop::EventLoopProxy, window::Window}; +use std::sync::Arc; +use winit::{ + event::WindowEvent, + raw_window_handle::HasWindowHandle, + window::{Window, WindowId}, +}; /// State of the accessibility node tree and platform adapter. pub struct AccessibilityState { - /// Adapter to connect to the [`EventLoop`](`winit::event_loop::EventLoop`). - adapter: accesskit_winit::Adapter, + // /// Adapter to connect to the [`EventLoop`](`winit::event_loop::EventLoop`). + adapter: Adapter, +} + +struct Handler { + window_id: WindowId, + proxy: BlitzShellProxy, +} +impl EventHandler for Handler { + fn handle_accesskit_event(&self, event: AccessKitEvent) { + self.proxy.send_event(BlitzShellEvent::Accessibility { + window_id: self.window_id, + data: Arc::new(event), + }); + } } impl AccessibilityState { - pub fn new(window: &Window, proxy: EventLoopProxy) -> Self { + pub fn new(window: &dyn Window, proxy: BlitzShellProxy) -> Self { + let window_id = window.id(); Self { - adapter: Adapter::with_event_loop_proxy(window, proxy.clone()), + adapter: Adapter::with_combined_handler( + window.window_handle().unwrap().as_raw(), + Arc::new(Handler { window_id, proxy }), + ), } } pub fn update_tree(&mut self, doc: &BaseDocument) { + let _ = doc; self.adapter .update_if_active(|| doc.build_accessibility_tree()); } + + /// Allows reacting to window events. + /// + /// This must be called whenever a new window event is received + /// and before it is handled by the application. + pub fn process_window_event(&mut self, window: &dyn Window, event: &WindowEvent) { + match event { + WindowEvent::Focused(is_focused) => { + self.adapter.set_focus(*is_focused); + } + WindowEvent::Moved(_) | WindowEvent::SurfaceResized(_) => { + let outer_position: (_, _) = window + .outer_position() + .unwrap_or_default() + .cast::() + .into(); + let outer_size: (_, _) = window.outer_size().cast::().into(); + let inner_position: (_, _) = window.surface_position().cast::().into(); + let inner_size: (_, _) = window.surface_size().cast::().into(); + + self.adapter.set_window_bounds( + Rect::from_origin_size(outer_position, outer_size), + Rect::from_origin_size(inner_position, inner_size), + ) + } + _ => (), + } + } } diff --git a/packages/blitz-shell/src/application.rs b/packages/blitz-shell/src/application.rs index eb7076a67..2bd6bdd71 100644 --- a/packages/blitz-shell/src/application.rs +++ b/packages/blitz-shell/src/application.rs @@ -1,26 +1,32 @@ -use crate::event::BlitzShellEvent; +use crate::event::{BlitzShellEvent, BlitzShellProxy}; use anyrender::WindowRenderer; use std::collections::HashMap; +use std::sync::mpsc::Receiver; use winit::application::ApplicationHandler; use winit::event::WindowEvent; -use winit::event_loop::{ActiveEventLoop, EventLoopProxy}; +use winit::event_loop::ActiveEventLoop; use winit::window::WindowId; +#[cfg(target_os = "macos")] +use winit::platform::macos::ApplicationHandlerExtMacOS; + use crate::{View, WindowConfig}; pub struct BlitzApplication { pub windows: HashMap>, pub pending_windows: Vec>, - pub proxy: EventLoopProxy, + pub proxy: BlitzShellProxy, + pub event_queue: Receiver, } impl BlitzApplication { - pub fn new(proxy: EventLoopProxy) -> Self { + pub fn new(proxy: BlitzShellProxy, event_queue: Receiver) -> Self { BlitzApplication { windows: HashMap::new(), pending_windows: Vec::new(), proxy, + event_queue, } } @@ -31,10 +37,56 @@ impl BlitzApplication { fn window_mut_by_doc_id(&mut self, doc_id: usize) -> Option<&mut View> { self.windows.values_mut().find(|w| w.doc.id() == doc_id) } + + pub fn handle_blitz_shell_event( + &mut self, + _event_loop: &dyn ActiveEventLoop, + event: BlitzShellEvent, + ) { + match event { + BlitzShellEvent::Poll { window_id } => { + if let Some(window) = self.windows.get_mut(&window_id) { + window.poll(); + }; + } + BlitzShellEvent::RequestRedraw { doc_id } => { + // TODO: Handle multiple documents per window + if let Some(window) = self.window_mut_by_doc_id(doc_id) { + window.request_redraw(); + } + } + + #[cfg(feature = "accessibility")] + BlitzShellEvent::Accessibility { window_id, data } => { + if let Some(window) = self.windows.get_mut(&window_id) { + match &*data { + accesskit_xplat::WindowEvent::InitialTreeRequested => { + window.build_accessibility_tree(); + } + accesskit_xplat::WindowEvent::AccessibilityDeactivated => { + // TODO + } + accesskit_xplat::WindowEvent::ActionRequested(_req) => { + // TODO + } + } + } + } + BlitzShellEvent::Embedder(_) => { + // Do nothing. Should be handled by embedders (if required). + } + BlitzShellEvent::Navigate(_opts) => { + // Do nothing. Should be handled by embedders (if required). + } + BlitzShellEvent::NavigationLoad { .. } => { + // Do nothing. Should be handled by embedders (if required). + } + } + } } -impl ApplicationHandler for BlitzApplication { - fn resumed(&mut self, event_loop: &ActiveEventLoop) { +impl ApplicationHandler for BlitzApplication { + fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { // Resume existing windows for (_, view) in self.windows.iter_mut() { view.resume(); @@ -51,15 +103,23 @@ impl ApplicationHandler for BlitzApplicat } } - fn suspended(&mut self, _event_loop: &ActiveEventLoop) { + fn destroy_surfaces(&mut self, _event_loop: &dyn ActiveEventLoop) { for (_, view) in self.windows.iter_mut() { view.suspend(); } } + fn resumed(&mut self, _event_loop: &dyn ActiveEventLoop) { + // TODO + } + + fn suspended(&mut self, _event_loop: &dyn ActiveEventLoop) { + // TODO + } + fn window_event( &mut self, - event_loop: &ActiveEventLoop, + event_loop: &dyn ActiveEventLoop, window_id: WindowId, event: WindowEvent, ) { @@ -79,49 +139,40 @@ impl ApplicationHandler for BlitzApplicat window.handle_winit_event(event); } - let _ = self.proxy.send_event(BlitzShellEvent::Poll { window_id }); + self.proxy.send_event(BlitzShellEvent::Poll { window_id }); } - fn user_event(&mut self, _event_loop: &ActiveEventLoop, event: BlitzShellEvent) { - match event { - BlitzShellEvent::Poll { window_id } => { - if let Some(window) = self.windows.get_mut(&window_id) { - window.poll(); - }; - } - BlitzShellEvent::RequestRedraw { doc_id } => { - // TODO: Handle multiple documents per window - if let Some(window) = self.window_mut_by_doc_id(doc_id) { - window.request_redraw(); - } - } + fn proxy_wake_up(&mut self, event_loop: &dyn ActiveEventLoop) { + while let Ok(event) = self.event_queue.try_recv() { + self.handle_blitz_shell_event(event_loop, event); + } + } - #[cfg(feature = "accessibility")] - BlitzShellEvent::Accessibility { window_id, data } => { - if let Some(window) = self.windows.get_mut(&window_id) { - match &*data { - accesskit_winit::WindowEvent::InitialTreeRequested => { - window.build_accessibility_tree(); - } - accesskit_winit::WindowEvent::AccessibilityDeactivated => { - // TODO - } - accesskit_winit::WindowEvent::ActionRequested(_req) => { - // TODO - } - } - } - } + #[cfg(target_os = "macos")] + fn macos_handler(&mut self) -> Option<&mut dyn ApplicationHandlerExtMacOS> { + Some(self) + } - BlitzShellEvent::Embedder(_) => { - // Do nothing. Should be handled by embedders (if required). - } - BlitzShellEvent::Navigate(_opts) => { - // Do nothing. Should be handled by embedders (if required). - } - BlitzShellEvent::NavigationLoad { .. } => { - // Do nothing. Should be handled by embedders (if required). + #[cfg(target_os = "ios")] + fn about_to_wait(&mut self, _event_loop: &dyn ActiveEventLoop) { + for view in self.windows.values_mut() { + if view.ios_request_redraw.get() { + view.window.request_redraw(); } } } } + +#[cfg(target_os = "macos")] +impl ApplicationHandlerExtMacOS for BlitzApplication { + fn standard_key_binding( + &mut self, + event_loop: &dyn ActiveEventLoop, + window_id: WindowId, + action: &str, + ) { + let _ = event_loop; + let _ = window_id; + let _ = action; + } +} diff --git a/packages/blitz-shell/src/convert_events.rs b/packages/blitz-shell/src/convert_events.rs index e3971fe34..ba0df9b48 100644 --- a/packages/blitz-shell/src/convert_events.rs +++ b/packages/blitz-shell/src/convert_events.rs @@ -1,9 +1,9 @@ -use blitz_traits::events::{BlitzImeEvent, BlitzKeyEvent, KeyState}; +use blitz_traits::events::{BlitzImeEvent, BlitzKeyEvent, BlitzPointerId, KeyState}; use blitz_traits::shell::ColorScheme; use keyboard_types::{Code, Key, Location, Modifiers}; -use winit::event::ElementState; -use winit::event::Ime; use winit::event::KeyEvent as WinitKeyEvent; +use winit::event::{ButtonSource, ElementState}; +use winit::event::{Ime, PointerSource}; use winit::keyboard::Key as WinitKey; use winit::keyboard::KeyCode as WinitKeyCode; use winit::keyboard::KeyLocation as WinitKeyLocation; @@ -32,6 +32,13 @@ pub(crate) fn winit_ime_to_blitz(event: Ime) -> BlitzImeEvent { Ime::Disabled => BlitzImeEvent::Disabled, Ime::Preedit(text, cursor) => BlitzImeEvent::Preedit(text, cursor), Ime::Commit(text) => BlitzImeEvent::Commit(text), + Ime::DeleteSurrounding { + before_bytes, + after_bytes, + } => BlitzImeEvent::DeleteSurrounding { + before_bytes, + after_bytes, + }, } } @@ -54,6 +61,32 @@ pub(crate) fn winit_key_event_to_blitz( } } +pub(crate) fn pointer_source_to_blitz(source: &PointerSource) -> BlitzPointerId { + match source { + PointerSource::Mouse => BlitzPointerId::Mouse, + PointerSource::Touch { finger_id, .. } => { + BlitzPointerId::Finger(finger_id.into_raw() as u64) + } + + // TODO: TabletTool and Unknown events + PointerSource::TabletTool { .. } => BlitzPointerId::Mouse, + PointerSource::Unknown => BlitzPointerId::Mouse, + } +} + +pub(crate) fn button_source_to_blitz(source: &ButtonSource) -> BlitzPointerId { + match source { + ButtonSource::Mouse(_) => BlitzPointerId::Mouse, + ButtonSource::Touch { finger_id, .. } => { + BlitzPointerId::Finger(finger_id.into_raw() as u64) + } + + // TODO: TabletTool and Unknown events + ButtonSource::TabletTool { .. } => BlitzPointerId::Mouse, + ButtonSource::Unknown(_) => BlitzPointerId::Mouse, + } +} + pub(crate) fn winit_modifiers_to_kbt_modifiers(winit_modifiers: WinitModifiers) -> Modifiers { let mut modifiers = Modifiers::default(); if winit_modifiers.control_key() { @@ -65,7 +98,7 @@ pub(crate) fn winit_modifiers_to_kbt_modifiers(winit_modifiers: WinitModifiers) if winit_modifiers.shift_key() { modifiers.insert(Modifiers::SHIFT); } - if winit_modifiers.super_key() { + if winit_modifiers.meta_key() { modifiers.insert(Modifiers::SUPER); } modifiers @@ -80,15 +113,13 @@ pub(crate) fn winit_key_location_to_kbt_location(location: WinitKeyLocation) -> } } +#[allow(deprecated)] // Should cover all variants for conversion pub(crate) fn winit_physical_key_to_kbt_code(physical_key: &WinitPhysicalKey) -> Code { match physical_key { WinitPhysicalKey::Unidentified(_) => Code::Unidentified, WinitPhysicalKey::Code(key_code) => match key_code { - // Variants that don't match 1:1 - WinitKeyCode::Meta => Code::Super, - WinitKeyCode::SuperLeft => Code::Super, - WinitKeyCode::SuperRight => Code::Super, - + WinitKeyCode::MetaLeft => Code::Super, + WinitKeyCode::MetaRight => Code::Super, WinitKeyCode::Backquote => Code::Backquote, WinitKeyCode::Backslash => Code::Backslash, WinitKeyCode::BracketLeft => Code::BracketLeft, @@ -280,12 +311,37 @@ pub(crate) fn winit_physical_key_to_kbt_code(physical_key: &WinitPhysicalKey) -> WinitKeyCode::F33 => Code::F33, WinitKeyCode::F34 => Code::F34, WinitKeyCode::F35 => Code::F35, + WinitKeyCode::Super => Code::Super, + WinitKeyCode::Unidentified => Code::Unidentified, + WinitKeyCode::BrightnessDown => Code::BrightnessDown, + WinitKeyCode::BrightnessUp => Code::BrightnessUp, + WinitKeyCode::DisplayToggleIntExt => Code::DisplayToggleIntExt, + WinitKeyCode::KeyboardLayoutSelect => Code::KeyboardLayoutSelect, + WinitKeyCode::LaunchAssistant => Code::LaunchAssistant, + WinitKeyCode::LaunchControlPanel => Code::LaunchControlPanel, + WinitKeyCode::LaunchScreenSaver => Code::LaunchScreenSaver, + WinitKeyCode::MailForward => Code::MailForward, + WinitKeyCode::MailReply => Code::MailReply, + WinitKeyCode::MailSend => Code::MailSend, + WinitKeyCode::MediaFastForward => Code::MediaFastForward, + WinitKeyCode::MediaPause => Code::MediaPause, + WinitKeyCode::MediaPlay => Code::MediaPlay, + WinitKeyCode::MediaRecord => Code::MediaRecord, + WinitKeyCode::MediaRewind => Code::MediaRewind, + WinitKeyCode::MicrophoneMuteToggle => Code::MicrophoneMuteToggle, + WinitKeyCode::PrivacyScreenToggle => Code::PrivacyScreenToggle, + WinitKeyCode::SelectTask => Code::SelectTask, + WinitKeyCode::ShowAllWindows => Code::ShowAllWindows, + WinitKeyCode::ZoomToggle => Code::ZoomToggle, + + WinitKeyCode::KeyboardBacklightToggle => todo!(), _ => todo!(), }, } } pub(crate) fn winit_key_to_kbt_key(winit_key: &WinitKey) -> Key { + #[allow(deprecated)] // Should cover all variants for conversion match winit_key { WinitKey::Character(c) => Key::Character(c.to_string()), WinitKey::Unidentified(_) => Key::Unidentified, @@ -307,7 +363,6 @@ pub(crate) fn winit_key_to_kbt_key(winit_key: &WinitKey) -> Key { WinitNamedKey::Super => Key::Super, WinitNamedKey::Enter => Key::Enter, WinitNamedKey::Tab => Key::Tab, - WinitNamedKey::Space => Key::Character(" ".to_string()), WinitNamedKey::ArrowDown => Key::ArrowDown, WinitNamedKey::ArrowLeft => Key::ArrowLeft, WinitNamedKey::ArrowRight => Key::ArrowRight, @@ -597,6 +652,9 @@ pub(crate) fn winit_key_to_kbt_key(winit_key: &WinitKey) -> Key { WinitNamedKey::F33 => Key::F33, WinitNamedKey::F34 => Key::F34, WinitNamedKey::F35 => Key::F35, + WinitNamedKey::Unidentified => Key::Unidentified, + WinitNamedKey::Dead => Key::Dead, + _ => Key::Unidentified, }, } diff --git a/packages/blitz-shell/src/event.rs b/packages/blitz-shell/src/event.rs index 6df53ba9a..1093ba357 100644 --- a/packages/blitz-shell/src/event.rs +++ b/packages/blitz-shell/src/event.rs @@ -1,10 +1,12 @@ use blitz_traits::navigation::NavigationOptions; +use blitz_traits::net::NetWaker; use futures_util::task::ArcWake; +use std::sync::mpsc::{Receiver, Sender, channel}; use std::{any::Any, sync::Arc}; use winit::{event_loop::EventLoopProxy, window::WindowId}; #[cfg(feature = "accessibility")] -use accesskit_winit::{Event as AccessKitEvent, WindowEvent as AccessKitWindowEvent}; +use accesskit_xplat::WindowEvent as AccessKitEvent; #[derive(Debug, Clone)] pub enum BlitzShellEvent { @@ -20,7 +22,7 @@ pub enum BlitzShellEvent { #[cfg(feature = "accessibility")] Accessibility { window_id: WindowId, - data: Arc, + data: Arc, }, /// An arbitary event from the Blitz embedder @@ -44,13 +46,38 @@ impl BlitzShellEvent { } } -#[cfg(feature = "accessibility")] -impl From for BlitzShellEvent { - fn from(value: AccessKitEvent) -> Self { - Self::Accessibility { - window_id: value.window_id, - data: Arc::new(value.window_event), - } +#[derive(Clone)] +pub struct BlitzShellProxy(Arc); +pub struct BlitzShellProxyInner { + winit_proxy: EventLoopProxy, + sender: Sender, +} + +impl BlitzShellProxy { + pub fn new(winit_proxy: EventLoopProxy) -> (Self, Receiver) { + let (sender, receiver) = channel(); + let proxy = Self(Arc::new(BlitzShellProxyInner { + winit_proxy, + sender, + })); + (proxy, receiver) + } + + pub fn wake_up(&self) { + self.0.winit_proxy.wake_up(); + } + pub fn send_event(&self, event: impl Into) { + self.send_event_impl(event.into()); + } + fn send_event_impl(&self, event: BlitzShellEvent) { + let _ = self.0.sender.send(event); + self.wake_up(); + } +} + +impl NetWaker for BlitzShellProxy { + fn wake(&self, client_id: usize) { + self.send_event_impl(BlitzShellEvent::RequestRedraw { doc_id: client_id }) } } @@ -59,16 +86,17 @@ impl From for BlitzShellEvent { /// This lets the VirtualDom "come up for air" and process events while the main thread is blocked by the WebView. /// /// All other IO lives in the Tokio runtime, -pub fn create_waker(proxy: &EventLoopProxy, id: WindowId) -> std::task::Waker { +pub fn create_waker(proxy: &BlitzShellProxy, id: WindowId) -> std::task::Waker { struct DomHandle { - proxy: EventLoopProxy, + proxy: BlitzShellProxy, id: WindowId, } impl ArcWake for DomHandle { fn wake_by_ref(arc_self: &Arc) { - _ = arc_self.proxy.send_event(BlitzShellEvent::Poll { + let event = BlitzShellEvent::Poll { window_id: arc_self.id, - }) + }; + arc_self.proxy.send_event(event) } } diff --git a/packages/blitz-shell/src/lib.rs b/packages/blitz-shell/src/lib.rs index a8d442db4..4149085ce 100644 --- a/packages/blitz-shell/src/lib.rs +++ b/packages/blitz-shell/src/lib.rs @@ -18,8 +18,7 @@ mod window; mod accessibility; pub use crate::application::BlitzApplication; -pub use crate::event::BlitzShellEvent; -pub use crate::net::BlitzShellNetWaker; +pub use crate::event::{BlitzShellEvent, BlitzShellProxy}; pub use crate::window::{View, WindowConfig}; #[cfg(feature = "data-uri")] @@ -40,9 +39,11 @@ pub use crate::net::DataUriNetProvider; use blitz_traits::shell::FileDialogFilter; use blitz_traits::shell::ShellProvider; use std::sync::Arc; +use winit::cursor::{Cursor, CursorIcon}; use winit::dpi::{LogicalPosition, LogicalSize}; pub use winit::event_loop::{ControlFlow, EventLoop, EventLoopProxy}; -pub use winit::window::{CursorIcon, Window}; +pub use winit::window::Window; +use winit::window::{ImeCapabilities, ImeEnableRequest, ImeRequest, ImeRequestData}; #[derive(Default)] pub struct Config { @@ -51,8 +52,8 @@ pub struct Config { } /// Build an event loop for the application -pub fn create_default_event_loop() -> EventLoop { - let mut ev_builder = EventLoop::::with_user_event(); +pub fn create_default_event_loop() -> EventLoop { + let mut ev_builder = EventLoop::builder(); #[cfg(target_os = "android")] { use winit::platform::android::EventLoopBuilderExtAndroid; @@ -84,10 +85,10 @@ pub fn current_android_app() -> android_activity::AndroidApp { } pub struct BlitzShellProvider { - window: Arc, + window: Arc, } impl BlitzShellProvider { - pub fn new(window: Arc) -> Self { + pub fn new(window: Arc) -> Self { Self { window } } } @@ -97,17 +98,27 @@ impl ShellProvider for BlitzShellProvider { self.window.request_redraw(); } fn set_cursor(&self, icon: CursorIcon) { - self.window.set_cursor(icon); + self.window.set_cursor(Cursor::Icon(icon)); } fn set_window_title(&self, title: String) { self.window.set_title(&title); } fn set_ime_enabled(&self, is_enabled: bool) { - self.window.set_ime_allowed(is_enabled); + if is_enabled { + let _ = self.window.request_ime_update(ImeRequest::Enable( + ImeEnableRequest::new(ImeCapabilities::new(), ImeRequestData::default()).unwrap(), + )); + } else { + let _ = self.window.request_ime_update(ImeRequest::Disable); + } } fn set_ime_cursor_area(&self, x: f32, y: f32, width: f32, height: f32) { - self.window - .set_ime_cursor_area(LogicalPosition::new(x, y), LogicalSize::new(width, height)); + let _ = self.window.request_ime_update(ImeRequest::Update( + ImeRequestData::default().with_cursor_area( + LogicalPosition::new(x, y).into(), + LogicalSize::new(width, height).into(), + ), + )); } #[cfg(all( diff --git a/packages/blitz-shell/src/net.rs b/packages/blitz-shell/src/net.rs index 986c14c2c..f589ab2b2 100644 --- a/packages/blitz-shell/src/net.rs +++ b/packages/blitz-shell/src/net.rs @@ -1,29 +1,27 @@ -use std::sync::Arc; +// use std::sync::Arc; -use blitz_traits::net::NetWaker; -use winit::event_loop::EventLoopProxy; +// use blitz_traits::net::NetWaker; +// use winit::event_loop::EventLoopProxy; -use crate::BlitzShellEvent; +// use crate::{BlitzShellEvent, event::BlitzShellProxy}; -/// A NetWaker that wakes up our winit event loop -pub struct BlitzShellNetWaker(EventLoopProxy); +// /// A NetWaker that wakes up our winit event loop +// pub struct BlitzShellNetWaker(BlitzShellProxy); -impl BlitzShellNetWaker { - pub fn new(proxy: EventLoopProxy) -> Self { - Self(proxy) - } +// impl BlitzShellNetWaker { +// pub fn new(proxy: BlitzShellProxy) -> Self { +// Self(proxy) +// } - pub fn shared(proxy: EventLoopProxy) -> Arc { - Arc::new(Self(proxy)) - } -} -impl NetWaker for BlitzShellNetWaker { - fn wake(&self, doc_id: usize) { - self.0 - .send_event(BlitzShellEvent::RequestRedraw { doc_id }) - .unwrap() - } -} +// pub fn shared(proxy: BlitzShellProxy) -> Arc { +// Arc::new(Self(proxy)) +// } +// } +// impl NetWaker for BlitzShellNetWaker { +// fn wake(&self, doc_id: usize) { +// self.0.send_event(BlitzShellEvent::RequestRedraw { doc_id }) +// } +// } #[cfg(feature = "data-uri")] mod data_uri_net_provider { diff --git a/packages/blitz-shell/src/window.rs b/packages/blitz-shell/src/window.rs index 4b1eec39d..f754f3715 100644 --- a/packages/blitz-shell/src/window.rs +++ b/packages/blitz-shell/src/window.rs @@ -1,25 +1,26 @@ use crate::BlitzShellProvider; use crate::convert_events::{ - color_scheme_to_theme, theme_to_color_scheme, winit_ime_to_blitz, winit_key_event_to_blitz, - winit_modifiers_to_kbt_modifiers, + button_source_to_blitz, color_scheme_to_theme, pointer_source_to_blitz, theme_to_color_scheme, + winit_ime_to_blitz, winit_key_event_to_blitz, winit_modifiers_to_kbt_modifiers, }; -use crate::event::{BlitzShellEvent, create_waker}; +use crate::event::{BlitzShellProxy, create_waker}; use anyrender::WindowRenderer; use blitz_dom::Document; use blitz_paint::paint_scene; use blitz_traits::events::{ - BlitzMouseButtonEvent, BlitzWheelDelta, BlitzWheelEvent, MouseEventButton, MouseEventButtons, - UiEvent, + BlitzPointerEvent, BlitzPointerId, BlitzWheelDelta, BlitzWheelEvent, MouseEventButton, + MouseEventButtons, UiEvent, }; use blitz_traits::shell::Viewport; +use winit::dpi::{LogicalPosition, PhysicalInsets}; use winit::keyboard::PhysicalKey; use std::any::Any; use std::sync::Arc; use std::task::Waker; use std::time::Instant; -use winit::event::{ElementState, MouseButton}; -use winit::event_loop::{ActiveEventLoop, EventLoopProxy}; +use winit::event::{ButtonSource, ElementState, MouseButton}; +use winit::event_loop::ActiveEventLoop; use winit::window::{Theme, WindowAttributes, WindowId}; use winit::{event::Modifiers, event::WindowEvent, keyboard::KeyCode, window::Window}; @@ -34,7 +35,7 @@ pub struct WindowConfig { impl WindowConfig { pub fn new(doc: Box, renderer: Rend) -> Self { - Self::with_attributes(doc, renderer, Window::default_attributes()) + Self::with_attributes(doc, renderer, WindowAttributes::default()) } pub fn with_attributes( @@ -56,8 +57,8 @@ pub struct View { pub renderer: Rend, pub waker: Option, - pub event_loop_proxy: EventLoopProxy, - pub window: Arc, + pub proxy: BlitzShellProxy, + pub window: Arc, /// The state of the keyboard modifiers (ctrl, shift, etc). Winit/Tao don't track these for us so we /// need to store them in order to have access to them when processing keypress events @@ -67,23 +68,34 @@ pub struct View { pub mouse_pos: (f32, f32), pub animation_timer: Option, pub is_visible: bool, + pub safe_area_insets: PhysicalInsets, #[cfg(feature = "accessibility")] /// Accessibility adapter for `accesskit`. pub accessibility: AccessibilityState, + + // Calling request_redraw within a WindowEvent doesn't work on iOS. So on iOS we track the state + // with a boolean and call request_redraw in about_to_wait + // + // See https://github.com/rust-windowing/winit/issues/3406 + #[cfg(target_os = "ios")] + pub ios_request_redraw: std::cell::Cell, } impl View { pub fn init( config: WindowConfig, - event_loop: &ActiveEventLoop, - proxy: &EventLoopProxy, + event_loop: &dyn ActiveEventLoop, + proxy: &BlitzShellProxy, ) -> Self { - let winit_window = Arc::from(event_loop.create_window(config.attributes).unwrap()); + let winit_window: Arc = + Arc::from(event_loop.create_window(config.attributes).unwrap()); // Create viewport - let size = winit_window.inner_size(); + // TODO: account for the "safe area" + let size = winit_window.surface_size(); let scale = winit_window.scale_factor() as f32; + let safe_area_insets = winit_window.safe_area(); let theme = winit_window.theme().unwrap_or(Theme::Light); let color_scheme = theme_to_color_scheme(theme); let viewport = Viewport::new(size.width, size.height, scale, color_scheme); @@ -111,15 +123,19 @@ impl View { waker: None, animation_timer: None, keyboard_modifiers: Default::default(), - event_loop_proxy: proxy.clone(), + proxy: proxy.clone(), window: winit_window.clone(), doc, theme_override: None, buttons: MouseEventButtons::None, + safe_area_insets, mouse_pos: Default::default(), is_visible: winit_window.is_visible().unwrap_or(true), #[cfg(feature = "accessibility")] - accessibility: AccessibilityState::new(&winit_window, proxy.clone()), + accessibility: AccessibilityState::new(&*winit_window, proxy.clone()), + + #[cfg(target_os = "ios")] + ios_request_redraw: std::cell::Cell::new(false), } } @@ -189,17 +205,20 @@ impl View { // Resume renderer let (width, height) = inner.viewport().window_size; let scale = inner.viewport().scale_f64(); - self.renderer.resume(self.window.clone(), width, height); + self.renderer + .resume(Arc::new(self.window.clone()), width, height); if !self.renderer.is_active() { panic!("Renderer failed to resume"); }; // Render - self.renderer - .render(|scene| paint_scene(scene, &inner, scale, width, height)); + let insets = self.safe_area_insets.to_logical(scale); + self.renderer.render(|scene| { + paint_scene(scene, &inner, scale, width, height, insets.left, insets.top) + }); // Set waker - self.waker = Some(create_waker(&self.event_loop_proxy, window_id)); + self.waker = Some(create_waker(&self.proxy, window_id)); } pub fn suspend(&mut self) { @@ -230,10 +249,14 @@ impl View { pub fn request_redraw(&self) { if self.renderer.is_active() { self.window.request_redraw(); + #[cfg(target_os = "ios")] + self.ios_request_redraw.set(true); } } pub fn redraw(&mut self) { + #[cfg(target_os = "ios")] + self.ios_request_redraw.set(false); let animation_time = self.current_animation_time(); let is_visible = self.is_visible; @@ -243,8 +266,10 @@ impl View { let (width, height) = inner.viewport().window_size; let scale = inner.viewport().scale_f64(); let is_animating = inner.is_animating(); - self.renderer - .render(|scene| paint_scene(scene, &inner, scale, width, height)); + let insets = self.safe_area_insets.to_logical(scale); + self.renderer.render(|scene| { + paint_scene(scene, &inner, scale, width, height, insets.left, insets.top) + }); drop(inner); @@ -266,7 +291,11 @@ impl View { drop(viewport); drop(inner); if width > 0 && height > 0 { - self.renderer.set_size(width, height); + let insets = self.safe_area_insets; + self.renderer.set_size( + width + insets.left + insets.right, + height + insets.top + insets.bottom, + ); self.request_redraw(); } } @@ -278,8 +307,12 @@ impl View { } pub fn handle_winit_event(&mut self, event: WindowEvent) { + // Update accessibility focus and window size state in response to a Winit WindowEvent + #[cfg(feature = "accessibility")] + self.accessibility + .process_window_event(&*self.window, &event); + match event { - // Window lifecycle events WindowEvent::Destroyed => {} WindowEvent::ActivationTokenDone { .. } => {}, WindowEvent::CloseRequested => { @@ -288,8 +321,6 @@ impl View { WindowEvent::RedrawRequested => { self.redraw(); } - - // Window size/position events WindowEvent::Moved(_) => {} WindowEvent::Occluded(is_occluded) => { self.is_visible = !is_occluded; @@ -297,21 +328,23 @@ impl View { self.request_redraw(); } }, - WindowEvent::Resized(physical_size) => { - self.with_viewport(|v| v.window_size = (physical_size.width, physical_size.height)); + WindowEvent::SurfaceResized(physical_size) => { + self.safe_area_insets = self.window.safe_area(); + let insets = self.safe_area_insets; + let width = physical_size.width - insets.left - insets.right; + let height = physical_size.height - insets.top - insets.bottom; + self.with_viewport(|v| v.window_size = (width, height)); + self.request_redraw(); } WindowEvent::ScaleFactorChanged { scale_factor, .. } => { self.with_viewport(|v| v.set_hidpi_scale(scale_factor as f32)); + self.request_redraw(); } - - // Theme events WindowEvent::ThemeChanged(theme) => { let color_scheme = theme_to_color_scheme(self.theme_override.unwrap_or(theme)); let mut inner = self.doc.inner_mut(); inner.viewport_mut().color_scheme = color_scheme; } - - // Text / keyboard events WindowEvent::Ime(ime_event) => { self.doc.handle_ui_event(UiEvent::Ime(winit_ime_to_blitz(ime_event))); self.request_redraw(); @@ -321,53 +354,50 @@ impl View { self.keyboard_modifiers = new_state; } WindowEvent::KeyboardInput { event, .. } => { - let PhysicalKey::Code(key_code) = event.physical_key else { - return; - }; - - if event.state.is_pressed() { - let ctrl = self.keyboard_modifiers.state().control_key(); - let meta = self.keyboard_modifiers.state().super_key(); - let alt = self.keyboard_modifiers.state().alt_key(); - - // Ctrl/Super keyboard shortcuts - if ctrl | meta { - match key_code { - KeyCode::Equal => { - self.doc.inner_mut().viewport_mut().zoom_by(0.1); - self.request_redraw(); - }, - KeyCode::Minus => { - self.doc.inner_mut().viewport_mut().zoom_by(-0.1); - self.request_redraw(); - }, - KeyCode::Digit0 => { - self.doc.inner_mut().viewport_mut().set_zoom(1.0); - self.request_redraw(); - } - _ => {} - }; - } - // Alt keyboard shortcuts - if alt { - match key_code { - KeyCode::KeyD => { - let mut inner = self.doc.inner_mut(); - inner.devtools_mut().toggle_show_layout(); - drop(inner); - self.request_redraw(); - } - KeyCode::KeyH => { - let mut inner = self.doc.inner_mut(); - inner.devtools_mut().toggle_highlight_hover(); - drop(inner); - self.request_redraw(); - } - KeyCode::KeyT => self.doc.inner().print_taffy_tree(), - _ => {} - }; - } + if let PhysicalKey::Code(key_code) = event.physical_key && event.state.is_pressed() { + let ctrl = self.keyboard_modifiers.state().control_key(); + let meta = self.keyboard_modifiers.state().meta_key(); + let alt = self.keyboard_modifiers.state().alt_key(); + + // Ctrl/Super keyboard shortcuts + if ctrl | meta { + match key_code { + KeyCode::Equal => { + self.doc.inner_mut().viewport_mut().zoom_by(0.1); + self.request_redraw(); + }, + KeyCode::Minus => { + self.doc.inner_mut().viewport_mut().zoom_by(-0.1); + self.request_redraw(); + }, + KeyCode::Digit0 => { + self.doc.inner_mut().viewport_mut().set_zoom(1.0); + self.request_redraw(); + } + _ => {} + }; + } + + // Alt keyboard shortcuts + if alt { + match key_code { + KeyCode::KeyD => { + let mut inner = self.doc.inner_mut(); + inner.devtools_mut().toggle_show_layout(); + drop(inner); + self.request_redraw(); + } + KeyCode::KeyH => { + let mut inner = self.doc.inner_mut(); + inner.devtools_mut().toggle_highlight_hover(); + drop(inner); + self.request_redraw(); + } + KeyCode::KeyT => self.doc.inner().print_taffy_tree(), + _ => {} + }; + } } @@ -381,29 +411,46 @@ impl View { self.doc.handle_ui_event(event); } - - - // Mouse/pointer events - WindowEvent::CursorEntered { /*device_id*/.. } => {} - WindowEvent::CursorLeft { /*device_id*/.. } => {} - WindowEvent::CursorMoved { position, .. } => { - let winit::dpi::LogicalPosition:: { x, y } = position.to_logical(self.window.scale_factor()); - self.mouse_pos = (x, y); - let event = UiEvent::MouseMove(BlitzMouseButtonEvent { - x, - y, + WindowEvent::PointerEntered { /*device_id*/.. } => {} + WindowEvent::PointerLeft { /*device_id*/.. } => {} + WindowEvent::PointerMoved { position, source, primary, .. } => { + let id = pointer_source_to_blitz(&source); + + let scale = self.window.scale_factor(); + let LogicalPosition:: { x: screen_x, y: screen_y } = position.to_logical(scale); + let viewport_scroll_offset = self.doc.inner().viewport_scroll(); + let client_x = screen_x - (self.safe_area_insets.left as f64 / scale) as f32; + let client_y = screen_y - (self.safe_area_insets.top as f64 / scale) as f32; + let page_x = client_x + viewport_scroll_offset.x as f32; + let page_y = client_y + viewport_scroll_offset.y as f32; + + let event = UiEvent::MouseMove(BlitzPointerEvent { + id, + is_primary: primary, + x: page_x, + y: page_y, + screen_x, + screen_y, + client_x, + client_y, button: Default::default(), buttons: self.buttons, mods: winit_modifiers_to_kbt_modifiers(self.keyboard_modifiers.state()), }); self.doc.handle_ui_event(event); } - WindowEvent::MouseInput { button, state, .. } => { - let button = match button { - MouseButton::Left => MouseEventButton::Main, - MouseButton::Right => MouseEventButton::Secondary, - MouseButton::Middle => MouseEventButton::Auxiliary, - _ => return, + WindowEvent::PointerButton { button, state, primary, position, .. } => { + let id = button_source_to_blitz(&button); + let button = match &button { + ButtonSource::Mouse(mouse_button) => match mouse_button { + MouseButton::Left => MouseEventButton::Main, + MouseButton::Right => MouseEventButton::Secondary, + MouseButton::Middle => MouseEventButton::Auxiliary, + // TODO: handle other button types + _ => MouseEventButton::Auxiliary, + } + _ => MouseEventButton::Main, + }; match state { @@ -411,9 +458,40 @@ impl View { ElementState::Released => self.buttons ^= button.into(), } - let event = BlitzMouseButtonEvent { - x: self.mouse_pos.0, - y: self.mouse_pos.1, + let scale = self.window.scale_factor(); + let LogicalPosition:: { x: screen_x, y: screen_y } = position.to_logical(scale); + let viewport_scroll_offset = self.doc.inner().viewport_scroll(); + let client_x = screen_x - (self.safe_area_insets.left as f64 / scale) as f32; + let client_y = screen_y - (self.safe_area_insets.top as f64 / scale) as f32; + let page_x = client_x + viewport_scroll_offset.x as f32; + let page_y = client_y + viewport_scroll_offset.y as f32; + + if id != BlitzPointerId::Mouse { + let event = UiEvent::MouseMove(BlitzPointerEvent { + id, + is_primary: primary, + x: page_x, + y: page_y, + screen_x, + screen_y, + client_x, + client_y, + button: Default::default(), + buttons: self.buttons, + mods: winit_modifiers_to_kbt_modifiers(self.keyboard_modifiers.state()), + }); + self.doc.handle_ui_event(event); + } + + let event = BlitzPointerEvent { + id, + is_primary: primary, + x: page_x, + y: page_y, + screen_x, + screen_y, + client_x, + client_y, button, buttons: self.buttons, mods: winit_modifiers_to_kbt_modifiers(self.keyboard_modifiers.state()), @@ -423,6 +501,7 @@ impl View { ElementState::Pressed => UiEvent::MouseDown(event), ElementState::Released => UiEvent::MouseUp(event), }; + self.doc.handle_ui_event(event); self.request_redraw(); } @@ -436,29 +515,22 @@ impl View { delta: blitz_delta, x: self.mouse_pos.0, y: self.mouse_pos.1, - button: MouseEventButton::Main, // Acts as an uninitialized value in this case buttons: self.buttons, mods: winit_modifiers_to_kbt_modifiers(self.keyboard_modifiers.state()), }; self.doc.handle_ui_event(UiEvent::Wheel(event)); } - - // File events - WindowEvent::DroppedFile(_) => {} - WindowEvent::HoveredFile(_) => {} - WindowEvent::HoveredFileCancelled => {} WindowEvent::Focused(_) => {} - - // Touch and motion events - // Todo implement touch scrolling - WindowEvent::Touch(_) => {} WindowEvent::TouchpadPressure { .. } => {} - WindowEvent::AxisMotion { .. } => {} WindowEvent::PinchGesture { .. } => {}, WindowEvent::PanGesture { .. } => {}, WindowEvent::DoubleTapGesture { .. } => {}, WindowEvent::RotationGesture { .. } => {}, + WindowEvent::DragEntered { .. } => {}, + WindowEvent::DragMoved { .. } => {}, + WindowEvent::DragDropped { .. } => {}, + WindowEvent::DragLeft { .. } => {}, } } } diff --git a/packages/blitz-traits/src/events.rs b/packages/blitz-traits/src/events.rs index e9c174e34..aa4a3c8c6 100644 --- a/packages/blitz-traits/src/events.rs +++ b/packages/blitz-traits/src/events.rs @@ -47,9 +47,9 @@ impl EventState { #[derive(Debug, Clone)] #[repr(u8)] pub enum UiEvent { - MouseMove(BlitzMouseButtonEvent), - MouseUp(BlitzMouseButtonEvent), - MouseDown(BlitzMouseButtonEvent), + MouseMove(BlitzPointerEvent), + MouseUp(BlitzPointerEvent), + MouseDown(BlitzPointerEvent), Wheel(BlitzWheelEvent), KeyUp(BlitzKeyEvent), KeyDown(BlitzKeyEvent), @@ -157,18 +157,18 @@ impl FromStr for DomEventKind { #[derive(Debug, Clone)] #[repr(u8)] pub enum DomEventData { - MouseMove(BlitzMouseButtonEvent), - MouseDown(BlitzMouseButtonEvent), - MouseUp(BlitzMouseButtonEvent), - MouseEnter(BlitzMouseButtonEvent), - MouseLeave(BlitzMouseButtonEvent), - MouseOver(BlitzMouseButtonEvent), - MouseOut(BlitzMouseButtonEvent), + MouseMove(BlitzPointerEvent), + MouseDown(BlitzPointerEvent), + MouseUp(BlitzPointerEvent), + MouseEnter(BlitzPointerEvent), + MouseLeave(BlitzPointerEvent), + MouseOver(BlitzPointerEvent), + MouseOut(BlitzPointerEvent), Scroll(BlitzScrollEvent), Wheel(BlitzWheelEvent), - Click(BlitzMouseButtonEvent), - ContextMenu(BlitzMouseButtonEvent), - DoubleClick(BlitzMouseButtonEvent), + Click(BlitzPointerEvent), + ContextMenu(BlitzPointerEvent), + DoubleClick(BlitzPointerEvent), KeyPress(BlitzKeyEvent), KeyDown(BlitzKeyEvent), KeyUp(BlitzKeyEvent), @@ -307,10 +307,22 @@ pub struct HitResult { pub y: f32, } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum BlitzPointerId { + Mouse, + Finger(u64), +} + #[derive(Clone, Debug)] -pub struct BlitzMouseButtonEvent { - pub x: f32, - pub y: f32, +pub struct BlitzPointerEvent { + pub id: BlitzPointerId, + pub is_primary: bool, + pub x: f32, // page_x TODO: rename + pub y: f32, // page_y TODO: rename + pub screen_x: f32, + pub screen_y: f32, + pub client_x: f32, + pub client_y: f32, pub button: MouseEventButton, pub buttons: MouseEventButtons, pub mods: Modifiers, @@ -321,7 +333,6 @@ pub struct BlitzWheelEvent { pub delta: BlitzWheelDelta, pub x: f32, pub y: f32, - pub button: MouseEventButton, pub buttons: MouseEventButtons, pub mods: Modifiers, } @@ -342,6 +353,20 @@ pub struct BlitzScrollEvent { pub client_height: i32, } +// struct PointerInputState { +// id: BlitzPointerId, +// pointer_down_x: f32, +// pointer_down_y: f32, +// pointer_down_time: Option, +// click_count: u16, +// } + +// struct PointersInputState { +// initial_finger_active: bool, +// mouse: Option, +// fingers: Vec, +// } + bitflags! { /// The buttons property indicates which buttons are pressed on the mouse /// (or other input device) when a mouse event is triggered. @@ -439,7 +464,8 @@ pub enum BlitzImeEvent { /// Notifies when the IME was enabled. /// /// After getting this event you could receive [`Preedit`][Self::Preedit] and - /// [`Commit`][Self::Commit] events. + /// [`Commit`][Self::Commit] events. You should also start performing IME related requests + /// like [`Window::set_ime_cursor_area`]. Enabled, /// Notifies when a new composing text should be set at the cursor position. @@ -448,7 +474,7 @@ pub enum BlitzImeEvent { /// position. When it's `None`, the cursor should be hidden. When `String` is an empty string /// this indicates that preedit was cleared. /// - /// The cursor position is byte-wise indexed. + /// The cursor position is byte-wise indexed, assuming UTF-8. Preedit(String, Option<(usize, usize)>), /// Notifies when text should be inserted into the editor widget. @@ -456,9 +482,25 @@ pub enum BlitzImeEvent { /// Right before this event winit will send empty [`Self::Preedit`] event. Commit(String), + /// Delete text surrounding the cursor or selection. + /// + /// This event does not affect either the pre-edit string. + /// This means that the application must first remove the pre-edit, + /// then execute the deletion, then insert the removed text back. + /// + /// This event assumes text is stored in UTF-8. + DeleteSurrounding { + /// Bytes to remove before the selection + before_bytes: usize, + /// Bytes to remove after the selection + after_bytes: usize, + }, + /// Notifies when the IME was disabled. /// /// After receiving this event you won't get any more [`Preedit`][Self::Preedit] or - /// [`Commit`][Self::Commit] events until the next [`Enabled`][Self::Enabled] event. + /// [`Commit`][Self::Commit] events until the next [`Enabled`][Self::Enabled] event. You should + /// also stop issuing IME related requests like [`Window::set_ime_cursor_area`] and clear + /// pending preedit text. Disabled, } diff --git a/packages/blitz/src/lib.rs b/packages/blitz/src/lib.rs index 66e085b00..0f89192d5 100644 --- a/packages/blitz/src/lib.rs +++ b/packages/blitz/src/lib.rs @@ -17,7 +17,7 @@ use anyrender_vello::VelloWindowRenderer as WindowRenderer; use blitz_dom::DocumentConfig; use blitz_html::HtmlDocument; use blitz_shell::{ - BlitzApplication, BlitzShellEvent, Config, EventLoop, WindowConfig, create_default_event_loop, + BlitzApplication, BlitzShellProxy, Config, EventLoop, WindowConfig, create_default_event_loop, }; use blitz_traits::net::NetProvider; @@ -55,8 +55,10 @@ pub fn launch_url(url: &str) { .unwrap(); let _guard = rt.enter(); - let event_loop = create_default_event_loop::(); - let net_provider = create_net_provider(&event_loop); + let event_loop = create_default_event_loop(); + let (proxy, reciever) = BlitzShellProxy::new(event_loop.create_proxy()); + let net_provider = create_net_provider(proxy.clone()); + let application = BlitzApplication::new(proxy, reciever); let (url, bytes) = rt .block_on(net_provider.fetch_async(blitz_traits::net::Request::get(url))) @@ -70,6 +72,7 @@ pub fn launch_url(url: &str) { base_url: Some(url), }, event_loop, + application, net_provider, ) } @@ -88,16 +91,19 @@ pub fn launch_static_html_cfg(html: &str, cfg: Config) { #[cfg(feature = "net")] let _guard = rt.enter(); - let event_loop = create_default_event_loop::(); - let net_provider = create_net_provider(&event_loop); + let event_loop = create_default_event_loop(); + let (proxy, reciever) = BlitzShellProxy::new(event_loop.create_proxy()); + let net_provider = create_net_provider(proxy.clone()); + let application = BlitzApplication::new(proxy, reciever); - launch_internal(html, cfg, event_loop, net_provider) + launch_internal(html, cfg, event_loop, application, net_provider) } fn launch_internal( html: &str, cfg: Config, - event_loop: EventLoop, + event_loop: EventLoop, + mut application: BlitzApplication, net_provider: Arc, ) { let doc = HtmlDocument::from_html( @@ -113,11 +119,11 @@ fn launch_internal( let window = WindowConfig::new(Box::new(doc) as _, renderer); // Create application - let mut application = BlitzApplication::new(event_loop.create_proxy()); + application.add_window(window); // Run event loop - event_loop.run_app(&mut application).unwrap() + event_loop.run_app(application).unwrap() } #[cfg(feature = "net")] @@ -125,15 +131,9 @@ type EnabledNetProvider = blitz_net::Provider; #[cfg(not(feature = "net"))] type EnabledNetProvider = blitz_traits::net::DummyNetProvider; -fn create_net_provider( - event_loop: &blitz_shell::EventLoop, -) -> Arc { +fn create_net_provider(proxy: BlitzShellProxy) -> Arc { #[cfg(feature = "net")] - let net_provider = { - let proxy = event_loop.create_proxy(); - let waker = blitz_shell::BlitzShellNetWaker::shared(proxy); - Arc::new(blitz_net::Provider::new(Some(waker))) - }; + let net_provider = Arc::new(blitz_net::Provider::new(Some(Arc::new(proxy)))); #[cfg(not(feature = "net"))] let net_provider = { use blitz_traits::net::DummyNetProvider; diff --git a/packages/dioxus-native-dom/src/events.rs b/packages/dioxus-native-dom/src/events.rs index e447e1fc1..2a2a3bf73 100644 --- a/packages/dioxus-native-dom/src/events.rs +++ b/packages/dioxus-native-dom/src/events.rs @@ -1,6 +1,6 @@ use blitz_dom::{BaseDocument, Node}; use blitz_traits::events::{ - BlitzKeyEvent, BlitzMouseButtonEvent, BlitzScrollEvent, BlitzWheelDelta, BlitzWheelEvent, + BlitzKeyEvent, BlitzPointerEvent, BlitzScrollEvent, BlitzWheelDelta, BlitzWheelEvent, MouseEventButton, }; use dioxus_html::{ @@ -297,20 +297,19 @@ impl HasKeyboardData for BlitzKeyboardData { } #[derive(Clone)] -pub struct NativeClickData(pub(crate) BlitzMouseButtonEvent); +pub struct NativeClickData(pub(crate) BlitzPointerEvent); impl InteractionLocation for NativeClickData { fn client_coordinates(&self) -> ClientPoint { - ClientPoint::new(self.0.x as _, self.0.y as _) + ClientPoint::new(self.0.client_x as f64, self.0.client_y as f64) } - // these require blitz to pass them along, or a dom rect fn screen_coordinates(&self) -> ScreenPoint { - unimplemented!() + ScreenPoint::new(self.0.screen_x as f64, self.0.screen_y as f64) } fn page_coordinates(&self) -> PagePoint { - unimplemented!() + PagePoint::new(self.0.x as f64, self.0.y as f64) } } @@ -414,13 +413,7 @@ impl HasMouseData for NativeWheelData { impl PointerInteraction for NativeWheelData { fn trigger_button(&self) -> Option { - Some(match self.0.button { - MouseEventButton::Main => MouseButton::Primary, - MouseEventButton::Auxiliary => MouseButton::Auxiliary, - MouseEventButton::Secondary => MouseButton::Secondary, - MouseEventButton::Fourth => MouseButton::Fourth, - MouseEventButton::Fifth => MouseButton::Fifth, - }) + None } fn held_buttons(&self) -> MouseButtonSet { diff --git a/packages/dioxus-native/src/assets.rs b/packages/dioxus-native/src/assets.rs index 3332c5063..90fbd95a1 100644 --- a/packages/dioxus-native/src/assets.rs +++ b/packages/dioxus-native/src/assets.rs @@ -1,9 +1,7 @@ -use blitz_shell::BlitzShellNetWaker; +use blitz_shell::BlitzShellProxy; use std::sync::Arc; -use blitz_shell::BlitzShellEvent; use blitz_traits::net::{NetHandler, NetProvider, Request}; -use winit::event_loop::EventLoopProxy; pub struct DioxusNativeNetProvider { inner_net_provider: Option>, @@ -11,12 +9,13 @@ pub struct DioxusNativeNetProvider { #[allow(unused)] impl DioxusNativeNetProvider { - pub fn shared(proxy: EventLoopProxy) -> Arc { + pub fn shared(proxy: BlitzShellProxy) -> Arc { Arc::new(Self::new(proxy)) as Arc } - pub fn new(proxy: EventLoopProxy) -> Self { - let net_waker = Some(BlitzShellNetWaker::shared(proxy)); + pub fn new(proxy: BlitzShellProxy) -> Self { + #[cfg(any(feature = "data-uri", feature = "net"))] + let net_waker = Some(Arc::new(proxy) as _); #[cfg(feature = "net")] let inner_net_provider = Some(blitz_net::Provider::shared(net_waker.clone())); @@ -28,7 +27,7 @@ impl DioxusNativeNetProvider { Self { inner_net_provider } } - pub fn with_inner(proxy: EventLoopProxy, inner: Arc) -> Self { + pub fn with_inner(proxy: BlitzShellProxy, inner: Arc) -> Self { Self { inner_net_provider: Some(inner), } diff --git a/packages/dioxus-native/src/contexts.rs b/packages/dioxus-native/src/contexts.rs index 0cc6c5ab3..114186db9 100644 --- a/packages/dioxus-native/src/contexts.rs +++ b/packages/dioxus-native/src/contexts.rs @@ -1,16 +1,16 @@ -use blitz_shell::BlitzShellEvent; +use blitz_shell::{BlitzShellEvent, BlitzShellProxy}; use dioxus_document::{Document, NoOpDocument}; -use winit::{event_loop::EventLoopProxy, window::WindowId}; +use winit::window::WindowId; use crate::DioxusNativeEvent; pub struct DioxusNativeDocument { - pub(crate) proxy: EventLoopProxy, + pub(crate) proxy: BlitzShellProxy, pub(crate) window: WindowId, } impl DioxusNativeDocument { - pub(crate) fn new(proxy: EventLoopProxy, window: WindowId) -> Self { + pub(crate) fn new(proxy: BlitzShellProxy, window: WindowId) -> Self { Self { proxy, window } } } @@ -27,7 +27,7 @@ impl Document for DioxusNativeDocument { contents: Option, ) { let window = self.window; - _ = self.proxy.send_event(BlitzShellEvent::embedder_event( + self.proxy.send_event(BlitzShellEvent::embedder_event( DioxusNativeEvent::CreateHeadElement { name: name.to_string(), attributes: attributes diff --git a/packages/dioxus-native/src/dioxus_application.rs b/packages/dioxus-native/src/dioxus_application.rs index 4622b30a5..ee4ac7c8b 100644 --- a/packages/dioxus-native/src/dioxus_application.rs +++ b/packages/dioxus-native/src/dioxus_application.rs @@ -1,12 +1,16 @@ -use blitz_shell::{BlitzApplication, View}; +use blitz_shell::{BlitzApplication, BlitzShellProxy, View}; use dioxus_core::{provide_context, ScopeId}; use dioxus_history::{History, MemoryHistory}; use std::rc::Rc; +use std::sync::Arc; use winit::application::ApplicationHandler; use winit::event::{StartCause, WindowEvent}; -use winit::event_loop::{ActiveEventLoop, EventLoopProxy}; +use winit::event_loop::ActiveEventLoop; use winit::window::WindowId; +#[cfg(target_os = "macos")] +use winit::platform::macos::ApplicationHandlerExtMacOS; + use crate::DioxusNativeWindowRenderer; use crate::{contexts::DioxusNativeDocument, BlitzShellEvent, DioxusDocument, WindowConfig}; @@ -30,18 +34,17 @@ pub enum DioxusNativeEvent { pub struct DioxusNativeApplication { pending_window: Option>, inner: BlitzApplication, - proxy: EventLoopProxy, } impl DioxusNativeApplication { pub fn new( - proxy: EventLoopProxy, + proxy: BlitzShellProxy, + event_queue: std::sync::mpsc::Receiver, config: WindowConfig, ) -> Self { Self { pending_window: Some(config), - inner: BlitzApplication::new(proxy.clone()), - proxy, + inner: BlitzApplication::new(proxy, event_queue), } } @@ -49,9 +52,9 @@ impl DioxusNativeApplication { self.inner.add_window(window_config); } - fn handle_blitz_shell_event( + fn handle_dioxus_native_event( &mut self, - event_loop: &ActiveEventLoop, + event_loop: &dyn ActiveEventLoop, event: &DioxusNativeEvent, ) { match event { @@ -105,20 +108,44 @@ impl DioxusNativeApplication { } } -impl ApplicationHandler for DioxusNativeApplication { - fn resumed(&mut self, event_loop: &ActiveEventLoop) { +impl ApplicationHandler for DioxusNativeApplication { + #[cfg(target_os = "macos")] + fn macos_handler(&mut self) -> Option<&mut dyn ApplicationHandlerExtMacOS> { + self.inner.macos_handler() + } + + fn resumed(&mut self, event_loop: &dyn ActiveEventLoop) { + self.inner.resumed(event_loop); + } + + fn suspended(&mut self, event_loop: &dyn ActiveEventLoop) { + self.inner.suspended(event_loop); + } + + fn destroy_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { + self.inner.destroy_surfaces(event_loop); + } + + fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) { + self.inner.about_to_wait(event_loop); + } + + fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { #[cfg(feature = "tracing")] tracing::debug!("Injecting document provider into all windows"); if let Some(config) = self.pending_window.take() { - let mut window = View::init(config, event_loop, &self.proxy); + let mut window = View::init(config, event_loop, &self.inner.proxy); + let winit_window = Arc::clone(&window.window); let renderer = window.renderer.clone(); let window_id = window.window_id(); let doc = window.downcast_doc_mut::(); doc.vdom.in_scope(ScopeId::ROOT, || { - let shared: Rc = - Rc::new(DioxusNativeDocument::new(self.proxy.clone(), window_id)); + let shared: Rc = Rc::new(DioxusNativeDocument::new( + self.inner.proxy.clone(), + window_id, + )); provide_context(shared); }); @@ -136,6 +163,10 @@ impl ApplicationHandler for DioxusNativeApplication { doc.vdom .in_scope(ScopeId::ROOT, move || provide_context(renderer)); + // Add winit window + doc.vdom + .in_scope(ScopeId::ROOT, move || provide_context(winit_window)); + // Queue rebuild doc.initial_build(); @@ -146,34 +177,32 @@ impl ApplicationHandler for DioxusNativeApplication { self.inner.windows.insert(window_id, window); } - self.inner.resumed(event_loop); - } - - fn suspended(&mut self, event_loop: &ActiveEventLoop) { - self.inner.suspended(event_loop); + self.inner.can_create_surfaces(event_loop); } - fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: StartCause) { + fn new_events(&mut self, event_loop: &dyn ActiveEventLoop, cause: StartCause) { self.inner.new_events(event_loop, cause); } fn window_event( &mut self, - event_loop: &ActiveEventLoop, + event_loop: &dyn ActiveEventLoop, window_id: WindowId, event: WindowEvent, ) { self.inner.window_event(event_loop, window_id, event); } - fn user_event(&mut self, event_loop: &ActiveEventLoop, event: BlitzShellEvent) { - match event { - BlitzShellEvent::Embedder(event) => { - if let Some(event) = event.downcast_ref::() { - self.handle_blitz_shell_event(event_loop, event); + fn proxy_wake_up(&mut self, event_loop: &dyn ActiveEventLoop) { + while let Ok(event) = self.inner.event_queue.try_recv() { + match event { + BlitzShellEvent::Embedder(event) => { + if let Some(event) = event.downcast_ref::() { + self.handle_dioxus_native_event(event_loop, event); + } } + event => self.inner.handle_blitz_shell_event(event_loop, event), } - event => self.inner.user_event(event_loop, event), } } } diff --git a/packages/dioxus-native/src/lib.rs b/packages/dioxus-native/src/lib.rs index cc966a617..386379915 100644 --- a/packages/dioxus-native/src/lib.rs +++ b/packages/dioxus-native/src/lib.rs @@ -58,12 +58,30 @@ pub use { dioxus_renderer::{use_wgpu, Features, Limits}, }; -use blitz_shell::{create_default_event_loop, BlitzShellEvent, Config, WindowConfig}; -use dioxus_core::{ComponentFunction, Element, VirtualDom}; +use blitz_shell::{ + create_default_event_loop, BlitzShellEvent, BlitzShellProxy, Config, WindowConfig, +}; +use dioxus_core::{consume_context, use_hook, ComponentFunction, Element, VirtualDom}; use link_handler::DioxusNativeNavigationProvider; use std::any::Any; use std::sync::Arc; -use winit::window::WindowAttributes; +use winit::{ + raw_window_handle::{HasWindowHandle as _, RawWindowHandle}, + window::{Window, WindowAttributes}, +}; + +pub fn use_window() -> Arc { + use_hook(consume_context::>) +} + +pub fn use_raw_window_handle() -> RawWindowHandle { + use_hook(|| { + consume_context::>() + .window_handle() + .unwrap() + .as_raw() + }) +} /// Launch an interactive HTML/CSS renderer driven by the Dioxus virtualdom pub fn launch(app: fn() -> Element) { @@ -130,7 +148,9 @@ pub fn launch_cfg_with_props( let _ = cfg; } - let event_loop = create_default_event_loop::(); + let event_loop = create_default_event_loop(); + let winit_proxy = event_loop.create_proxy(); + let (proxy, event_queue) = BlitzShellProxy::new(winit_proxy); // Turn on the runtime and enter it #[cfg(feature = "net")] @@ -144,10 +164,10 @@ pub fn launch_cfg_with_props( // Setup hot-reloading if enabled. #[cfg(all(feature = "hot-reload", debug_assertions))] { - let proxy = event_loop.create_proxy(); + let proxy = proxy.clone(); dioxus_devtools::connect(move |event| { let dxn_event = DioxusNativeEvent::DevserverEvent(event); - let _ = proxy.send_event(BlitzShellEvent::embedder_event(dxn_event)); + proxy.send_event(BlitzShellEvent::embedder_event(dxn_event)); }) } @@ -163,22 +183,18 @@ pub fn launch_cfg_with_props( #[cfg(feature = "net")] let net_provider = { - use blitz_shell::BlitzShellNetWaker; - - let proxy = event_loop.create_proxy(); - let net_waker = Some(BlitzShellNetWaker::shared(proxy.clone())); - - let inner_net_provider = Arc::new(blitz_net::Provider::new(net_waker.clone())); + let net_waker = Some(Arc::new(proxy.clone()) as _); + let inner_net_provider = Arc::new(blitz_net::Provider::new(net_waker)); vdom.provide_root_context(Arc::clone(&inner_net_provider)); Arc::new(DioxusNativeNetProvider::with_inner( - proxy, + proxy.clone(), inner_net_provider as _, )) as Arc }; #[cfg(not(feature = "net"))] - let net_provider = DioxusNativeNetProvider::shared(event_loop.create_proxy()); + let net_provider = DioxusNativeNetProvider::shared(proxy.clone()); vdom.provide_root_context(Arc::clone(&net_provider)); @@ -226,8 +242,8 @@ pub fn launch_cfg_with_props( ); // Create application - let mut application = DioxusNativeApplication::new(event_loop.create_proxy(), config); + let application = DioxusNativeApplication::new(proxy, event_queue, config); // Run event loop - event_loop.run_app(&mut application).unwrap(); + event_loop.run_app(application).unwrap(); } diff --git a/wpt/runner/src/test_runners/ref_test.rs b/wpt/runner/src/test_runners/ref_test.rs index 8a09b2d4d..1154b7519 100644 --- a/wpt/runner/src/test_runners/ref_test.rs +++ b/wpt/runner/src/test_runners/ref_test.rs @@ -118,7 +118,7 @@ fn render_html_to_buffer( ctx.renderer.render_to_vec( |scene| { scene.reset(); - paint_scene(scene, document.as_ref(), SCALE, WIDTH, HEIGHT); + paint_scene(scene, document.as_ref(), SCALE, WIDTH, HEIGHT, 0, 0); }, buf, );