From 142ac6c679888cb1d9a0b7987c20d04444a32ea0 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Wed, 3 Dec 2025 15:24:58 +0000 Subject: [PATCH 01/73] Winit 0.31 WIP Signed-off-by: Nico Burns --- Cargo.lock | 360 +++++++++++++++++++-- Cargo.toml | 4 +- apps/readme/src/main.rs | 16 +- apps/readme/src/readme_application.rs | 99 +++--- packages/blitz-dom/src/events/ime.rs | 8 + packages/blitz-shell/src/accessibility.rs | 16 +- packages/blitz-shell/src/application.rs | 116 ++++--- packages/blitz-shell/src/convert_events.rs | 46 ++- packages/blitz-shell/src/event.rs | 74 +++-- packages/blitz-shell/src/lib.rs | 33 +- packages/blitz-shell/src/net.rs | 40 ++- packages/blitz-shell/src/window.rs | 78 ++--- packages/blitz-traits/src/events.rs | 23 +- 13 files changed, 667 insertions(+), 246 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e254674be..4b6d93952 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,7 +107,7 @@ dependencies = [ "accesskit_unix", "accesskit_windows", "raw-window-handle", - "winit", + "winit 0.30.12", ] [[package]] @@ -785,7 +785,7 @@ dependencies = [ "fastrand", "html-escape", "image", - "keyboard-types", + "keyboard-types 0.7.0", "linebender_resource_handle", "markup5ever", "objc2 0.6.3", @@ -893,10 +893,10 @@ dependencies = [ "blitz-traits", "data-url", "futures-util", - "keyboard-types", + "keyboard-types 0.7.0", "rfd", "tracing", - "winit", + "winit 0.31.0-beta.2", ] [[package]] @@ -907,9 +907,9 @@ dependencies = [ "bytes", "cursor-icon", "http", - "keyboard-types", + "keyboard-types 0.7.0", "serde", - "smol_str", + "smol_str 0.3.4", "url", ] @@ -959,6 +959,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" @@ -1085,14 +1094,27 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "calloop" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb9f6e1368bd4621d2c86baa7e37de77a938adf5221e5dd3d6133340101b309e" +dependencies = [ + "bitflags 2.10.0", + "polling", + "rustix 1.1.2", + "slab", + "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", + "calloop 0.14.3", + "rustix 1.1.2", "wayland-backend", "wayland-client", ] @@ -2008,7 +2030,7 @@ dependencies = [ "futures-channel", "futures-util", "generational-box", - "keyboard-types", + "keyboard-types 0.7.0", "lazy-js-bundle", "rustversion", "serde", @@ -2086,13 +2108,13 @@ dependencies = [ "dioxus-signals", "dioxus-stores", "futures-util", - "keyboard-types", + "keyboard-types 0.7.0", "manganis", "rustc-hash 1.1.0", "tokio", "tracing", "webbrowser", - "winit", + "winit 0.31.0-beta.2", ] [[package]] @@ -2105,7 +2127,7 @@ dependencies = [ "dioxus-core", "dioxus-html", "futures-util", - "keyboard-types", + "keyboard-types 0.7.0", "rustc-hash 1.1.0", "tracing", ] @@ -3759,6 +3781,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" @@ -4567,6 +4599,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", ] @@ -4579,6 +4612,7 @@ checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ "bitflags 2.10.0", "dispatch2", + "libc", "objc2 0.6.3", "objc2-core-foundation", "objc2-io-surface", @@ -4640,6 +4674,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" @@ -5527,7 +5572,7 @@ dependencies = [ "reqwest", "tokio", "url", - "winit", + "winit 0.31.0-beta.2", ] [[package]] @@ -5880,9 +5925,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", @@ -6241,24 +6286,26 @@ 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", + "calloop 0.14.3", "calloop-wayland-source", "cursor-icon", "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", @@ -6273,6 +6320,16 @@ dependencies = [ "serde", ] +[[package]] +name = "smol_str" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3498b0a27f93ef1402f20eefacfaa1691272ac4eca1cdc8c596cb0a245d6cbf5" +dependencies = [ + "borsh", + "serde_core", +] + [[package]] name = "socket2" version = "0.6.1" @@ -7139,6 +7196,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", @@ -7760,6 +7818,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.10" @@ -8637,13 +8721,11 @@ version = "0.30.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c66d4b9ed69c4009f6321f762d6e61ad8a2389cd431b97cb1e146812e9e6c732" dependencies = [ - "ahash", "android-activity", "atomic-waker", "bitflags 2.10.0", "block2 0.5.1", - "bytemuck", - "calloop", + "calloop 0.13.0", "cfg_aliases 0.2.1", "concurrent-queue", "core-foundation 0.9.4", @@ -8652,32 +8734,247 @@ dependencies = [ "dpi", "js-sys", "libc", - "memmap2 0.9.9", "ndk", "objc2 0.5.2", "objc2-app-kit 0.2.2", "objc2-foundation 0.2.2", "objc2-ui-kit 0.2.2", "orbclient", - "percent-encoding", "pin-project", "raw-window-handle", "redox_syscall 0.4.1", "rustix 0.38.44", - "sctk-adwaita", - "smithay-client-toolkit", - "smol_str", + "smol_str 0.2.2", "tracing", "unicode-segmentation", "wasm-bindgen", "wasm-bindgen-futures", + "web-sys", + "web-time", + "windows-sys 0.52.0", + "xkbcommon-dl", +] + +[[package]] +name = "winit" +version = "0.31.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2879d2854d1a43e48f67322d4bd097afcb6eb8f8f775c8de0260a71aea1df1aa" +dependencies = [ + "bitflags 2.10.0", + "cfg_aliases 0.2.1", + "cursor-icon", + "dpi", + "libc", + "raw-window-handle", + "rustix 1.1.2", + "smol_str 0.3.4", + "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", + "raw-window-handle", + "smol_str 0.3.4", + "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 0.3.4", + "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 0.3.4", + "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 0.3.4", + "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", + "raw-window-handle", + "redox_syscall 0.5.18", + "smol_str 0.3.4", + "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 0.3.2", + "raw-window-handle", + "smol_str 0.3.4", + "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 0.14.3", + "cursor-icon", + "dpi", + "libc", + "memmap2 0.9.9", + "raw-window-handle", + "rustix 1.1.2", + "sctk-adwaita", + "smithay-client-toolkit", + "smol_str 0.3.4", + "tracing", "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 0.3.4", + "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 0.3.4", + "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 0.14.3", + "cursor-icon", + "dpi", + "libc", + "percent-encoding", + "raw-window-handle", + "rustix 1.1.2", + "smol_str 0.3.4", + "tracing", + "winit-common", + "winit-core", "x11-dl", "x11rb", "xkbcommon-dl", @@ -8798,6 +9095,7 @@ dependencies = [ "once_cell", "rustix 1.1.3", "x11rb-protocol", + "xcursor", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 42529f71e..5e165d3e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -128,7 +128,7 @@ usvg = "0.46" # Windowing & Input raw-window-handle = "0.6.0" -winit = { version = "0.30.2", features = ["rwh_06"] } +winit = { version = "=0.31.0-beta.2" } accesskit_winit = "0.23" accesskit = "0.17" arboard = { version = "3.4.1", default-features = false } @@ -167,7 +167,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" diff --git a/apps/readme/src/main.rs b/apps/readme/src/main.rs index 5ecb72773..950bbbd38 100644 --- a/apps/readme/src/main.rs +++ b/apps/readme/src/main.rs @@ -37,18 +37,17 @@ 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 { @@ -74,9 +73,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 +98,6 @@ fn main() { // println!("{html}"); - let proxy = event_loop.create_proxy(); let navigation_provider = ReadmeNavigationProvider { proxy: proxy.clone(), }; @@ -121,6 +120,7 @@ fn main() { // Create application let mut application = ReadmeApplication::new( proxy.clone(), + event_queue, raw_url.clone(), net_provider, navigation_provider, @@ -131,7 +131,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 +145,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..911d9e8f8 100644 --- a/apps/readme/src/readme_application.rs +++ b/apps/readme/src/readme_application.rs @@ -4,12 +4,12 @@ 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}; use winit::window::{Theme, WindowId}; @@ -30,14 +30,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 +64,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 +80,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 +129,30 @@ impl ReadmeApplication { } } -impl ApplicationHandler for ReadmeApplication { - fn resumed(&mut self, event_loop: &ActiveEventLoop) { +impl ApplicationHandler for ReadmeApplication { + 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 +162,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 +180,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/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-shell/src/accessibility.rs b/packages/blitz-shell/src/accessibility.rs index 07aeb9c8d..17f521611 100644 --- a/packages/blitz-shell/src/accessibility.rs +++ b/packages/blitz-shell/src/accessibility.rs @@ -1,22 +1,22 @@ -use crate::event::BlitzShellEvent; -use accesskit_winit::Adapter; +use crate::event::{BlitzShellEvent, BlitzShellProxy}; +// use accesskit_winit::Adapter; use blitz_dom::BaseDocument; use winit::{event_loop::EventLoopProxy, window::Window}; /// 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: accesskit_winit::Adapter, } impl AccessibilityState { - pub fn new(window: &Window, proxy: EventLoopProxy) -> Self { + pub fn new(window: &dyn Window, proxy: BlitzShellProxy) -> Self { Self { - adapter: Adapter::with_event_loop_proxy(window, proxy.clone()), + // adapter: Adapter::with_event_loop_proxy(window, proxy.clone()), } } pub fn update_tree(&mut self, doc: &BaseDocument) { - self.adapter - .update_if_active(|| doc.build_accessibility_tree()); + // self.adapter + // .update_if_active(|| doc.build_accessibility_tree()); } } diff --git a/packages/blitz-shell/src/application.rs b/packages/blitz-shell/src/application.rs index eb7076a67..215752cfe 100644 --- a/packages/blitz-shell/src/application.rs +++ b/packages/blitz-shell/src/application.rs @@ -1,10 +1,11 @@ -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; use crate::{View, WindowConfig}; @@ -12,15 +13,17 @@ 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 +34,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_winit::WindowEvent::InitialTreeRequested => { + // window.build_accessibility_tree(); + // } + // accesskit_winit::WindowEvent::AccessibilityDeactivated => { + // // TODO + // } + // accesskit_winit::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 +100,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, ) { @@ -82,46 +139,9 @@ impl ApplicationHandler for BlitzApplicat let _ = 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(); - } - } - - #[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 - } - } - } - } - - 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). - } + 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); } } } diff --git a/packages/blitz-shell/src/convert_events.rs b/packages/blitz-shell/src/convert_events.rs index e3971fe34..bec3ba861 100644 --- a/packages/blitz-shell/src/convert_events.rs +++ b/packages/blitz-shell/src/convert_events.rs @@ -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, + }, } } @@ -65,7 +72,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 +87,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 +285,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 +337,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 +626,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..6b3ce497e 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}; +// #[cfg(feature = "accessibility")] +// use accesskit_winit::{Event as AccessKitEvent, WindowEvent as AccessKitWindowEvent}; #[derive(Debug, Clone)] pub enum BlitzShellEvent { @@ -17,11 +19,11 @@ pub enum BlitzShellEvent { }, /// An accessibility event from `accesskit`. - #[cfg(feature = "accessibility")] - Accessibility { - window_id: WindowId, - data: Arc, - }, + // #[cfg(feature = "accessibility")] + // Accessibility { + // window_id: WindowId, + // data: Arc, + // }, /// An arbitary event from the Blitz embedder Embedder(Arc), @@ -44,13 +46,48 @@ 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), - } +// #[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 +96,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..61856e8fc 100644 --- a/packages/blitz-shell/src/window.rs +++ b/packages/blitz-shell/src/window.rs @@ -3,7 +3,7 @@ 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, }; -use crate::event::{BlitzShellEvent, create_waker}; +use crate::event::{BlitzShellProxy, create_waker}; use anyrender::WindowRenderer; use blitz_dom::Document; use blitz_paint::paint_scene; @@ -18,8 +18,8 @@ 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 +34,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 +56,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 @@ -76,13 +76,15 @@ pub struct View { 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 theme = winit_window.theme().unwrap_or(Theme::Light); let color_scheme = theme_to_color_scheme(theme); @@ -111,7 +113,7 @@ 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, @@ -119,7 +121,7 @@ impl View { 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()), } } @@ -189,7 +191,8 @@ 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"); }; @@ -199,7 +202,7 @@ impl View { .render(|scene| paint_scene(scene, &inner, scale, width, height)); // 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) { @@ -279,7 +282,6 @@ impl View { pub fn handle_winit_event(&mut self, event: WindowEvent) { match event { - // Window lifecycle events WindowEvent::Destroyed => {} WindowEvent::ActivationTokenDone { .. } => {}, WindowEvent::CloseRequested => { @@ -288,8 +290,6 @@ impl View { WindowEvent::RedrawRequested => { self.redraw(); } - - // Window size/position events WindowEvent::Moved(_) => {} WindowEvent::Occluded(is_occluded) => { self.is_visible = !is_occluded; @@ -297,21 +297,17 @@ impl View { self.request_redraw(); } }, - WindowEvent::Resized(physical_size) => { + WindowEvent::SurfaceResized(physical_size) => { self.with_viewport(|v| v.window_size = (physical_size.width, physical_size.height)); } WindowEvent::ScaleFactorChanged { scale_factor, .. } => { self.with_viewport(|v| v.set_hidpi_scale(scale_factor as f32)); } - - // 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(); @@ -327,7 +323,7 @@ impl View { if event.state.is_pressed() { let ctrl = self.keyboard_modifiers.state().control_key(); - let meta = self.keyboard_modifiers.state().super_key(); + let meta = self.keyboard_modifiers.state().meta_key(); let alt = self.keyboard_modifiers.state().alt_key(); // Ctrl/Super keyboard shortcuts @@ -381,12 +377,9 @@ impl View { self.doc.handle_ui_event(event); } - - - // Mouse/pointer events - WindowEvent::CursorEntered { /*device_id*/.. } => {} - WindowEvent::CursorLeft { /*device_id*/.. } => {} - WindowEvent::CursorMoved { position, .. } => { + WindowEvent::PointerEntered { /*device_id*/.. } => {} + WindowEvent::PointerLeft { /*device_id*/.. } => {} + WindowEvent::PointerMoved { position, .. } => { let winit::dpi::LogicalPosition:: { x, y } = position.to_logical(self.window.scale_factor()); self.mouse_pos = (x, y); let event = UiEvent::MouseMove(BlitzMouseButtonEvent { @@ -398,12 +391,17 @@ impl View { }); self.doc.handle_ui_event(event); } - WindowEvent::MouseInput { button, state, .. } => { + WindowEvent::PointerButton { button, state, .. } => { let button = match button { - MouseButton::Left => MouseEventButton::Main, - MouseButton::Right => MouseEventButton::Secondary, - MouseButton::Middle => MouseEventButton::Auxiliary, + ButtonSource::Mouse(mouse_button) => match mouse_button { + MouseButton::Left => MouseEventButton::Main, + MouseButton::Right => MouseEventButton::Secondary, + MouseButton::Middle => MouseEventButton::Auxiliary, + // TODO: handle other button types + _ => return, + } _ => return, + }; match state { @@ -443,22 +441,16 @@ impl View { 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..9780a0171 100644 --- a/packages/blitz-traits/src/events.rs +++ b/packages/blitz-traits/src/events.rs @@ -439,7 +439,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 +449,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 +457,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, } From 1fbf26467cfe625e0e95be60575294652d3753ce Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Wed, 3 Dec 2025 16:35:20 +0000 Subject: [PATCH 02/73] Fixup Dioxus Native for Winit 0.31 --- apps/readme/src/main.rs | 3 +- packages/blitz-shell/src/application.rs | 2 +- packages/dioxus-native/src/assets.rs | 13 ++-- packages/dioxus-native/src/contexts.rs | 10 +-- .../dioxus-native/src/dioxus_application.rs | 63 +++++++++++-------- packages/dioxus-native/src/lib.rs | 28 ++++----- 6 files changed, 64 insertions(+), 55 deletions(-) diff --git a/apps/readme/src/main.rs b/apps/readme/src/main.rs index 950bbbd38..b1742621a 100644 --- a/apps/readme/src/main.rs +++ b/apps/readme/src/main.rs @@ -52,8 +52,7 @@ struct ReadmeNavigationProvider { impl NavigationProvider for ReadmeNavigationProvider { fn navigate_to(&self, opts: NavigationOptions) { - let _ = self - .proxy + self.proxy .send_event(BlitzShellEvent::Navigate(Box::new(opts))); } } diff --git a/packages/blitz-shell/src/application.rs b/packages/blitz-shell/src/application.rs index 215752cfe..3648c7298 100644 --- a/packages/blitz-shell/src/application.rs +++ b/packages/blitz-shell/src/application.rs @@ -136,7 +136,7 @@ impl ApplicationHandler for BlitzApplication { window.handle_winit_event(event); } - let _ = self.proxy.send_event(BlitzShellEvent::Poll { window_id }); + self.proxy.send_event(BlitzShellEvent::Poll { window_id }); } fn proxy_wake_up(&mut self, event_loop: &dyn ActiveEventLoop) { 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..1c4b5e3a6 100644 --- a/packages/dioxus-native/src/dioxus_application.rs +++ b/packages/dioxus-native/src/dioxus_application.rs @@ -1,10 +1,10 @@ -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 winit::application::ApplicationHandler; use winit::event::{StartCause, WindowEvent}; -use winit::event_loop::{ActiveEventLoop, EventLoopProxy}; +use winit::event_loop::ActiveEventLoop; use winit::window::WindowId; use crate::DioxusNativeWindowRenderer; @@ -30,18 +30,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 +48,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 +104,34 @@ impl DioxusNativeApplication { } } -impl ApplicationHandler for DioxusNativeApplication { - fn resumed(&mut self, event_loop: &ActiveEventLoop) { +impl ApplicationHandler for DioxusNativeApplication { + 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 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 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); }); @@ -146,34 +159,32 @@ impl ApplicationHandler for DioxusNativeApplication { self.inner.windows.insert(window_id, window); } - self.inner.resumed(event_loop); + self.inner.can_create_surfaces(event_loop); } - fn suspended(&mut self, event_loop: &ActiveEventLoop) { - self.inner.suspended(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..b4c7d53f6 100644 --- a/packages/dioxus-native/src/lib.rs +++ b/packages/dioxus-native/src/lib.rs @@ -58,7 +58,9 @@ pub use { dioxus_renderer::{use_wgpu, Features, Limits}, }; -use blitz_shell::{create_default_event_loop, BlitzShellEvent, Config, WindowConfig}; +use blitz_shell::{ + create_default_event_loop, BlitzShellEvent, BlitzShellProxy, Config, WindowConfig, +}; use dioxus_core::{ComponentFunction, Element, VirtualDom}; use link_handler::DioxusNativeNavigationProvider; use std::any::Any; @@ -130,7 +132,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 +148,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 +167,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 +226,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(); } From a18a99150029119a15604de7fc7c14c75c96ce87 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Wed, 3 Dec 2025 17:47:45 +0000 Subject: [PATCH 03/73] Add handlers for apple_standard_keybinding --- apps/readme/src/readme_application.rs | 5 +++++ packages/blitz-shell/src/application.rs | 19 ++++++++++++++++++- .../dioxus-native/src/dioxus_application.rs | 5 +++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/apps/readme/src/readme_application.rs b/apps/readme/src/readme_application.rs index 911d9e8f8..db45cf4c1 100644 --- a/apps/readme/src/readme_application.rs +++ b/apps/readme/src/readme_application.rs @@ -11,6 +11,7 @@ use winit::application::ApplicationHandler; use winit::event::{Modifiers, StartCause, WindowEvent}; use winit::event_loop::ActiveEventLoop; use winit::keyboard::{KeyCode, PhysicalKey}; +use winit::platform::macos::ApplicationHandlerExtMacOS; use winit::window::{Theme, WindowId}; use crate::fetch; @@ -130,6 +131,10 @@ impl ReadmeApplication { } impl ApplicationHandler for ReadmeApplication { + 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); } diff --git a/packages/blitz-shell/src/application.rs b/packages/blitz-shell/src/application.rs index 3648c7298..d1774f80f 100644 --- a/packages/blitz-shell/src/application.rs +++ b/packages/blitz-shell/src/application.rs @@ -3,10 +3,10 @@ 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; use winit::window::WindowId; +use winit::{application::ApplicationHandler, platform::macos::ApplicationHandlerExtMacOS}; use crate::{View, WindowConfig}; @@ -83,6 +83,10 @@ impl BlitzApplication { } impl ApplicationHandler for BlitzApplication { + fn macos_handler(&mut self) -> Option<&mut dyn ApplicationHandlerExtMacOS> { + Some(self) + } + fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { // Resume existing windows for (_, view) in self.windows.iter_mut() { @@ -145,3 +149,16 @@ impl ApplicationHandler for BlitzApplication { } } } + +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/dioxus-native/src/dioxus_application.rs b/packages/dioxus-native/src/dioxus_application.rs index 1c4b5e3a6..83605bd27 100644 --- a/packages/dioxus-native/src/dioxus_application.rs +++ b/packages/dioxus-native/src/dioxus_application.rs @@ -5,6 +5,7 @@ use std::rc::Rc; use winit::application::ApplicationHandler; use winit::event::{StartCause, WindowEvent}; use winit::event_loop::ActiveEventLoop; +use winit::platform::macos::ApplicationHandlerExtMacOS; use winit::window::WindowId; use crate::DioxusNativeWindowRenderer; @@ -105,6 +106,10 @@ impl DioxusNativeApplication { } impl ApplicationHandler for DioxusNativeApplication { + 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); } From 545830f6bfd81dac4475fdc4f4131b70b5fb9df1 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 8 Dec 2025 15:27:36 +0000 Subject: [PATCH 04/73] Disable accesskit_winit dep. This is pulling in Winit 0.30 --- Cargo.lock | 1108 +++---------------------------- packages/blitz-shell/Cargo.toml | 4 +- 2 files changed, 110 insertions(+), 1002 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4b6d93952..0dccbfa2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,92 +24,6 @@ version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3d3b8f9bae46a948369bc4a03e815d4ed6d616bd00de4051133a5019dc31c5a" -[[package]] -name = "accesskit_atspi_common" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c5dd55e6e94949498698daf4d48fb5659e824d7abec0d394089656ceaf99d4f" -dependencies = [ - "accesskit", - "accesskit_consumer", - "atspi-common", - "serde", - "thiserror 1.0.69", - "zvariant", -] - -[[package]] -name = "accesskit_consumer" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f47983a1084940ba9a39c077a8c63e55c619388be5476ac04c804cfbd1e63459" -dependencies = [ - "accesskit", - "hashbrown 0.15.5", - "immutable-chunkmap", -] - -[[package]] -name = "accesskit_macos" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7329821f3bd1101e03a7d2e03bd339e3ac0dc64c70b4c9f9ae1949e3ba8dece1" -dependencies = [ - "accesskit", - "accesskit_consumer", - "hashbrown 0.15.5", - "objc2 0.5.2", - "objc2-app-kit 0.2.2", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "accesskit_unix" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcee751cc20d88678c33edaf9c07e8b693cd02819fe89053776f5313492273f5" -dependencies = [ - "accesskit", - "accesskit_atspi_common", - "async-channel", - "async-executor", - "async-task", - "atspi", - "futures-lite", - "futures-util", - "serde", - "zbus", -] - -[[package]] -name = "accesskit_windows" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24fcd5d23d70670992b823e735e859374d694a3d12bfd8dd32bd3bd8bedb5d81" -dependencies = [ - "accesskit", - "accesskit_consumer", - "hashbrown 0.15.5", - "paste", - "static_assertions", - "windows 0.58.0", - "windows-core 0.58.0", -] - -[[package]] -name = "accesskit_winit" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6a48dad5530b6deb9fc7a52cc6c3bf72cdd9eb8157ac9d32d69f2427a5e879" -dependencies = [ - "accesskit", - "accesskit_macos", - "accesskit_unix", - "accesskit_windows", - "raw-window-handle", - "winit 0.30.12", -] - [[package]] name = "adler2" version = "2.0.1" @@ -277,12 +191,12 @@ dependencies = [ "hashbrown 0.16.1", "kurbo", "oaty", - "objc2 0.6.3", - "objc2-app-kit 0.3.2", + "objc2", + "objc2-app-kit", "objc2-core-foundation", - "objc2-metal 0.3.2", - "objc2-quartz-core 0.3.2", - "objc2-ui-kit 0.3.2", + "objc2-metal", + "objc2-quartz-core", + "objc2-ui-kit", "peniko", "pixels_window_renderer", "raw-window-handle", @@ -372,9 +286,9 @@ checksum = "0348a1c054491f4bfe6ab86a7b6ab1e44e45d899005de92f58b3df180b36ddaf" dependencies = [ "clipboard-win", "log", - "objc2 0.6.3", - "objc2-app-kit 0.3.2", - "objc2-foundation 0.3.2", + "objc2", + "objc2-app-kit", + "objc2-foundation", "parking_lot", "percent-encoding", "windows-sys 0.60.2", @@ -428,137 +342,6 @@ dependencies = [ "raw-window-metal", ] -[[package]] -name = "async-broadcast" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" -dependencies = [ - "event-listener", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-channel" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" -dependencies = [ - "concurrent-queue", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-executor" -version = "1.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "pin-project-lite", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" -dependencies = [ - "autocfg", - "cfg-if", - "concurrent-queue", - "futures-io", - "futures-lite", - "parking", - "polling", - "rustix 1.1.3", - "slab", - "windows-sys 0.61.2", -] - -[[package]] -name = "async-lock" -version = "3.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" -dependencies = [ - "event-listener", - "event-listener-strategy", - "pin-project-lite", -] - -[[package]] -name = "async-process" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" -dependencies = [ - "async-channel", - "async-io", - "async-lock", - "async-signal", - "async-task", - "blocking", - "cfg-if", - "event-listener", - "futures-lite", - "rustix 1.1.3", -] - -[[package]] -name = "async-recursion" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.114", -] - -[[package]] -name = "async-signal" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" -dependencies = [ - "async-io", - "async-lock", - "atomic-waker", - "cfg-if", - "futures-core", - "futures-io", - "rustix 1.1.3", - "signal-hook-registry", - "slab", - "windows-sys 0.61.2", -] - -[[package]] -name = "async-task" -version = "4.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" - [[package]] name = "async-trait" version = "0.1.89" @@ -588,57 +371,6 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41e67cd8309bbd06cd603a9e693a784ac2e5d1e955f11286e355089fcab3047c" -[[package]] -name = "atspi" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be534b16650e35237bb1ed189ba2aab86ce65e88cc84c66f4935ba38575cecbf" -dependencies = [ - "atspi-common", - "atspi-connection", - "atspi-proxies", -] - -[[package]] -name = "atspi-common" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1909ed2dc01d0a17505d89311d192518507e8a056a48148e3598fef5e7bb6ba7" -dependencies = [ - "enumflags2", - "serde", - "static_assertions", - "zbus", - "zbus-lockstep", - "zbus-lockstep-macros", - "zbus_names", - "zvariant", -] - -[[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", -] - -[[package]] -name = "atspi-proxies" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e6c5de3e524cf967569722446bcd458d5032348554d9a17d7d72b041ab7496" -dependencies = [ - "atspi-common", - "serde", - "zbus", - "zvariant", -] - [[package]] name = "autocfg" version = "1.5.0" @@ -788,7 +520,7 @@ dependencies = [ "keyboard-types 0.7.0", "linebender_resource_handle", "markup5ever", - "objc2 0.6.3", + "objc2", "parley", "percent-encoding", "rayon", @@ -884,7 +616,6 @@ name = "blitz-shell" version = "0.2.2" dependencies = [ "accesskit", - "accesskit_winit", "android-activity", "anyrender", "arboard", @@ -896,7 +627,7 @@ dependencies = [ "keyboard-types 0.7.0", "rfd", "tracing", - "winit 0.31.0-beta.2", + "winit", ] [[package]] @@ -909,7 +640,7 @@ dependencies = [ "http", "keyboard-types 0.7.0", "serde", - "smol_str 0.3.4", + "smol_str", "url", ] @@ -928,35 +659,13 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block2" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" -dependencies = [ - "objc2 0.5.2", -] - [[package]] name = "block2" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" dependencies = [ - "objc2 0.6.3", -] - -[[package]] -name = "blocking" -version = "1.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" -dependencies = [ - "async-channel", - "async-task", - "futures-io", - "futures-lite", - "piper", + "objc2", ] [[package]] @@ -1080,20 +789,6 @@ dependencies = [ "walkdir", ] -[[package]] -name = "calloop" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" -dependencies = [ - "bitflags 2.10.0", - "log", - "polling", - "rustix 0.38.44", - "slab", - "thiserror 1.0.69", -] - [[package]] name = "calloop" version = "0.14.3" @@ -1102,7 +797,7 @@ checksum = "cb9f6e1368bd4621d2c86baa7e37de77a938adf5221e5dd3d6133340101b309e" dependencies = [ "bitflags 2.10.0", "polling", - "rustix 1.1.2", + "rustix 1.1.3", "slab", "tracing", ] @@ -1113,8 +808,8 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138efcf0940a02ebf0cc8d1eff41a1682a46b431630f4c52450d6265876021fa" dependencies = [ - "calloop 0.14.3", - "rustix 1.1.2", + "calloop", + "rustix 1.1.3", "wayland-backend", "wayland-client", ] @@ -2114,7 +1809,7 @@ dependencies = [ "tokio", "tracing", "webbrowser", - "winit 0.31.0-beta.2", + "winit", ] [[package]] @@ -2239,12 +1934,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" @@ -2252,9 +1941,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" dependencies = [ "bitflags 2.10.0", - "block2 0.6.2", + "block2", "libc", - "objc2 0.6.3", + "objc2", ] [[package]] @@ -2374,39 +2063,12 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "endi" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" - [[package]] name = "entities" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5320ae4c3782150d900b79807611a59a99fc9a1d61d686faafc24b93fc8d7ca" -[[package]] -name = "enumflags2" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" -dependencies = [ - "enumflags2_derive", - "serde", -] - -[[package]] -name = "enumflags2_derive" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.114", -] - [[package]] name = "enumset" version = "1.1.10" @@ -2483,27 +2145,6 @@ dependencies = [ "serde", ] -[[package]] -name = "event-listener" -version = "5.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" -dependencies = [ - "event-listener", - "pin-project-lite", -] - [[package]] name = "fallible_collections" version = "0.4.9" @@ -2646,10 +2287,10 @@ dependencies = [ "icu_locale_core", "linebender_resource_handle", "memmap2 0.9.9", - "objc2 0.6.3", + "objc2", "objc2-core-foundation", "objc2-core-text", - "objc2-foundation 0.3.2", + "objc2-foundation", "read-fonts 0.35.0", "roxmltree 0.21.1", "smallvec", @@ -2777,19 +2418,6 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" -[[package]] -name = "futures-lite" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "parking", - "pin-project-lite", -] - [[package]] name = "futures-macro" version = "0.3.31" @@ -2979,10 +2607,10 @@ dependencies = [ "glutin_glx_sys", "glutin_wgl_sys 0.6.1", "libloading 0.8.9", - "objc2 0.6.3", - "objc2-app-kit 0.3.2", + "objc2", + "objc2-app-kit", "objc2-core-foundation", - "objc2-foundation 0.3.2", + "objc2-foundation", "once_cell", "raw-window-handle", "wayland-sys", @@ -3604,15 +3232,6 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09e54e57b4c48b40f7aec75635392b12b3421fa26fe8b4332e63138ed278459c" -[[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.13.0" @@ -4075,15 +3694,6 @@ dependencies = [ "libc", ] -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - [[package]] name = "metal" version = "0.27.0" @@ -4303,19 +3913,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" @@ -4479,22 +4076,6 @@ dependencies = [ "objc_exception", ] -[[package]] -name = "objc-sys" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" - -[[package]] -name = "objc2" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" -dependencies = [ - "objc-sys", - "objc2-encode", -] - [[package]] name = "objc2" version = "0.6.3" @@ -4504,22 +4085,6 @@ dependencies = [ "objc2-encode", ] -[[package]] -name = "objc2-app-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" -dependencies = [ - "bitflags 2.10.0", - "block2 0.5.1", - "libc", - "objc2 0.5.2", - "objc2-core-data 0.2.2", - "objc2-core-image 0.2.2", - "objc2-foundation 0.2.2", - "objc2-quartz-core 0.2.2", -] - [[package]] name = "objc2-app-kit" version = "0.3.2" @@ -4527,25 +4092,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ "bitflags 2.10.0", - "block2 0.6.2", - "objc2 0.6.3", + "block2", + "objc2", "objc2-core-foundation", "objc2-core-graphics", - "objc2-foundation 0.3.2", - "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", + "objc2-foundation", + "objc2-quartz-core", ] [[package]] @@ -4555,31 +4107,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" dependencies = [ "bitflags 2.10.0", - "objc2 0.6.3", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" -dependencies = [ - "bitflags 2.10.0", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", + "objc2", + "objc2-foundation", ] [[package]] @@ -4588,8 +4117,8 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" dependencies = [ - "objc2 0.6.3", - "objc2-foundation 0.3.2", + "objc2", + "objc2-foundation", ] [[package]] @@ -4599,9 +4128,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ "bitflags 2.10.0", - "block2 0.6.2", + "block2", "dispatch2", - "objc2 0.6.3", + "objc2", ] [[package]] @@ -4613,43 +4142,19 @@ dependencies = [ "bitflags 2.10.0", "dispatch2", "libc", - "objc2 0.6.3", + "objc2", "objc2-core-foundation", "objc2-io-surface", ] -[[package]] -name = "objc2-core-image" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" -dependencies = [ - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", - "objc2-metal 0.2.2", -] - [[package]] name = "objc2-core-image" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006" dependencies = [ - "objc2 0.6.3", - "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", + "objc2", + "objc2-foundation", ] [[package]] @@ -4658,8 +4163,8 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009" dependencies = [ - "objc2 0.6.3", - "objc2-foundation 0.3.2", + "objc2", + "objc2-foundation", ] [[package]] @@ -4669,7 +4174,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" dependencies = [ "bitflags 2.10.0", - "objc2 0.6.3", + "objc2", "objc2-core-foundation", "objc2-core-graphics", ] @@ -4691,19 +4196,6 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" -[[package]] -name = "objc2-foundation" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" -dependencies = [ - "bitflags 2.10.0", - "block2 0.5.1", - "dispatch", - "libc", - "objc2 0.5.2", -] - [[package]] name = "objc2-foundation" version = "0.3.2" @@ -4711,9 +4203,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ "bitflags 2.10.0", - "block2 0.6.2", + "block2", "libc", - "objc2 0.6.3", + "objc2", "objc2-core-foundation", ] @@ -4724,34 +4216,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ "bitflags 2.10.0", - "objc2 0.6.3", + "objc2", "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" -dependencies = [ - "bitflags 2.10.0", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", -] - [[package]] name = "objc2-metal" version = "0.3.2" @@ -4759,21 +4227,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794" dependencies = [ "bitflags 2.10.0", - "objc2 0.6.3", - "objc2-foundation 0.3.2", -] - -[[package]] -name = "objc2-quartz-core" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" -dependencies = [ - "bitflags 2.10.0", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", - "objc2-metal 0.2.2", + "objc2", + "objc2-foundation", ] [[package]] @@ -4783,41 +4238,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ "bitflags 2.10.0", - "objc2 0.6.3", + "objc2", "objc2-core-foundation", - "objc2-foundation 0.3.2", - "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", + "objc2-foundation", + "objc2-metal", ] [[package]] @@ -4827,42 +4251,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ "bitflags 2.10.0", - "block2 0.6.2", - "objc2 0.6.3", - "objc2-cloud-kit 0.3.2", - "objc2-core-data 0.3.2", + "block2", + "objc2", + "objc2-cloud-kit", + "objc2-core-data", "objc2-core-foundation", "objc2-core-graphics", - "objc2-core-image 0.3.2", - "objc2-core-location 0.3.2", + "objc2-core-image", + "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-foundation", + "objc2-quartz-core", + "objc2-user-notifications", ] [[package]] @@ -4871,8 +4271,8 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e" dependencies = [ - "objc2 0.6.3", - "objc2-foundation 0.3.2", + "objc2", + "objc2-foundation", ] [[package]] @@ -4974,16 +4374,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "ordered-stream" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" -dependencies = [ - "futures-core", - "pin-project-lite", -] - [[package]] name = "os_info" version = "3.14.0" @@ -4992,10 +4382,10 @@ checksum = "e4022a17595a00d6a369236fdae483f0de7f0a339960a53118b818238e132224" dependencies = [ "android_system_properties", "log", - "nix 0.30.1", - "objc2 0.6.3", - "objc2-foundation 0.3.2", - "objc2-ui-kit 0.3.2", + "nix", + "objc2", + "objc2-foundation", + "objc2-ui-kit", "serde", "windows-sys 0.61.2", ] @@ -5015,12 +4405,6 @@ version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52" -[[package]] -name = "parking" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" - [[package]] name = "parking_lot" version = "0.12.5" @@ -5173,17 +4557,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "piper" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" -dependencies = [ - "atomic-waker", - "fastrand", - "futures-io", -] - [[package]] name = "pixels" version = "0.15.0" @@ -5393,16 +4766,6 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" -[[package]] -name = "quick-xml" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" -dependencies = [ - "memchr", - "serde", -] - [[package]] name = "quick-xml" version = "0.38.4" @@ -5427,35 +4790,14 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - [[package]] name = "rand" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.3", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", + "rand_chacha", + "rand_core", ] [[package]] @@ -5465,16 +4807,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.17", + "rand_core", ] [[package]] @@ -5572,16 +4905,7 @@ dependencies = [ "reqwest", "tokio", "url", - "winit 0.31.0-beta.2", -] - -[[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", + "winit", ] [[package]] @@ -5727,15 +5051,15 @@ version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "069d6129dede311430d0dcf1ded88a7affc7a342c2d8e6336043d43ed14dac17" dependencies = [ - "block2 0.6.2", + "block2", "dispatch2", "js-sys", "libc", "log", - "objc2 0.6.3", - "objc2-app-kit 0.3.2", + "objc2", + "objc2-app-kit", "objc2-core-foundation", - "objc2-foundation 0.3.2", + "objc2-foundation", "percent-encoding", "pollster 0.4.0", "raw-window-handle", @@ -6149,16 +5473,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "signal-hook-registry" -version = "1.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" -dependencies = [ - "errno", - "libc", -] - [[package]] name = "simd-adler32" version = "0.3.8" @@ -6291,13 +5605,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0512da38f5e2b31201a93524adb8d3136276fa4fe4aafab4e1f727a82b534cc0" dependencies = [ "bitflags 2.10.0", - "calloop 0.14.3", + "calloop", "calloop-wayland-source", "cursor-icon", "libc", "log", "memmap2 0.9.9", - "rustix 1.1.2", + "rustix 1.1.3", "thiserror 2.0.17", "wayland-backend", "wayland-client", @@ -6313,18 +5627,9 @@ dependencies = [ [[package]] name = "smol_str" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" -dependencies = [ - "serde", -] - -[[package]] -name = "smol_str" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3498b0a27f93ef1402f20eefacfaa1691272ac4eca1cdc8c596cb0a245d6cbf5" +checksum = "0f7a918bd2a9951d18ee6e48f076843e8e73a9a5d22cf05bcd4b7a81bdd04e17" dependencies = [ "borsh", "serde_core", @@ -6353,11 +5658,11 @@ dependencies = [ "js-sys", "memmap2 0.9.9", "ndk", - "objc2 0.6.3", + "objc2", "objc2-core-foundation", "objc2-core-graphics", - "objc2-foundation 0.3.2", - "objc2-quartz-core 0.3.2", + "objc2-foundation", + "objc2-quartz-core", "raw-window-handle", "redox_syscall 0.5.18", "rustix 1.1.3", @@ -7289,7 +6594,7 @@ dependencies = [ "http", "httparse", "log", - "rand 0.9.2", + "rand", "sha1", "thiserror 2.0.17", "utf-8", @@ -7307,17 +6612,6 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" -[[package]] -name = "uds_windows" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" -dependencies = [ - "memoffset", - "tempfile", - "winapi", -] - [[package]] name = "ultraviolet" version = "0.9.2" @@ -7833,9 +7127,9 @@ dependencies = [ [[package]] name = "wayland-protocols-misc" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfe33d551eb8bffd03ff067a8b44bb963919157841a99957151299a6307d19c" +checksum = "791c58fdeec5406aa37169dd815327d1e47f334219b523444bc26d70ceb4c34e" dependencies = [ "bitflags 2.10.0", "wayland-backend", @@ -7877,7 +7171,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5423e94b6a63e68e439803a3e153a9252d5ead12fd853334e2ad33997e3889e3" dependencies = [ "proc-macro2", - "quick-xml 0.38.4", + "quick-xml", "quote", ] @@ -7935,8 +7229,8 @@ dependencies = [ "jni", "log", "ndk-context", - "objc2 0.6.3", - "objc2-foundation 0.3.2", + "objc2", + "objc2-foundation", "url", "web-sys", ] @@ -8715,46 +8009,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" -[[package]] -name = "winit" -version = "0.30.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66d4b9ed69c4009f6321f762d6e61ad8a2389cd431b97cb1e146812e9e6c732" -dependencies = [ - "android-activity", - "atomic-waker", - "bitflags 2.10.0", - "block2 0.5.1", - "calloop 0.13.0", - "cfg_aliases 0.2.1", - "concurrent-queue", - "core-foundation 0.9.4", - "core-graphics", - "cursor-icon", - "dpi", - "js-sys", - "libc", - "ndk", - "objc2 0.5.2", - "objc2-app-kit 0.2.2", - "objc2-foundation 0.2.2", - "objc2-ui-kit 0.2.2", - "orbclient", - "pin-project", - "raw-window-handle", - "redox_syscall 0.4.1", - "rustix 0.38.44", - "smol_str 0.2.2", - "tracing", - "unicode-segmentation", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "web-time", - "windows-sys 0.52.0", - "xkbcommon-dl", -] - [[package]] name = "winit" version = "0.31.0-beta.2" @@ -8767,8 +8021,8 @@ dependencies = [ "dpi", "libc", "raw-window-handle", - "rustix 1.1.2", - "smol_str 0.3.4", + "rustix 1.1.3", + "smol_str", "tracing", "winit-android", "winit-appkit", @@ -8793,7 +8047,7 @@ dependencies = [ "dpi", "ndk", "raw-window-handle", - "smol_str 0.3.4", + "smol_str", "tracing", "winit-core", ] @@ -8805,17 +8059,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21310ca07851a49c348e0c2cc768e36b52ca65afda2c2354d78ed4b90074d8aa" dependencies = [ "bitflags 2.10.0", - "block2 0.6.2", + "block2", "dispatch2", "dpi", - "objc2 0.6.3", - "objc2-app-kit 0.3.2", + "objc2", + "objc2-app-kit", "objc2-core-foundation", "objc2-core-graphics", "objc2-core-video", - "objc2-foundation 0.3.2", + "objc2-foundation", "raw-window-handle", - "smol_str 0.3.4", + "smol_str", "tracing", "winit-common", "winit-core", @@ -8828,9 +8082,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45375fbac4cbb77260d83a30b1f9d8105880dbac99a9ae97f56656694680ff69" dependencies = [ "memmap2 0.9.9", - "objc2 0.6.3", + "objc2", "objc2-core-foundation", - "smol_str 0.3.4", + "smol_str", "tracing", "winit-core", "x11-dl", @@ -8848,7 +8102,7 @@ dependencies = [ "dpi", "keyboard-types 0.8.3", "raw-window-handle", - "smol_str 0.3.4", + "smol_str", "web-time", ] @@ -8863,7 +8117,7 @@ dependencies = [ "orbclient", "raw-window-handle", "redox_syscall 0.5.18", - "smol_str 0.3.4", + "smol_str", "tracing", "winit-core", ] @@ -8875,15 +8129,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "680a356e798837d8eb274d4556e83bceaf81698194e31aafc5cfb8a9f2fab643" dependencies = [ "bitflags 2.10.0", - "block2 0.6.2", + "block2", "dispatch2", "dpi", - "objc2 0.6.3", + "objc2", "objc2-core-foundation", - "objc2-foundation 0.3.2", - "objc2-ui-kit 0.3.2", + "objc2-foundation", + "objc2-ui-kit", "raw-window-handle", - "smol_str 0.3.4", + "smol_str", "tracing", "winit-common", "winit-core", @@ -8897,16 +8151,16 @@ checksum = "8ce5afb2ba07da603f84b722c95f9f9396d2cedae3944fb6c0cda4a6f88de545" dependencies = [ "ahash", "bitflags 2.10.0", - "calloop 0.14.3", + "calloop", "cursor-icon", "dpi", "libc", "memmap2 0.9.9", "raw-window-handle", - "rustix 1.1.2", + "rustix 1.1.3", "sctk-adwaita", "smithay-client-toolkit", - "smol_str 0.3.4", + "smol_str", "tracing", "wayland-backend", "wayland-client", @@ -8930,7 +8184,7 @@ dependencies = [ "js-sys", "pin-project", "raw-window-handle", - "smol_str 0.3.4", + "smol_str", "tracing", "wasm-bindgen", "wasm-bindgen-futures", @@ -8949,7 +8203,7 @@ dependencies = [ "cursor-icon", "dpi", "raw-window-handle", - "smol_str 0.3.4", + "smol_str", "tracing", "unicode-segmentation", "windows-sys 0.59.0", @@ -8964,14 +8218,14 @@ checksum = "aa5b600756534c7041aa93cd0d244d44b09fca1b89e202bd1cd80dd9f3636c46" dependencies = [ "bitflags 2.10.0", "bytemuck", - "calloop 0.14.3", + "calloop", "cursor-icon", "dpi", "libc", "percent-encoding", "raw-window-handle", - "rustix 1.1.2", - "smol_str 0.3.4", + "rustix 1.1.3", + "smol_str", "tracing", "winit-common", "winit-core", @@ -9120,16 +8374,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" @@ -9217,105 +8461,6 @@ dependencies = [ "synstructure", ] -[[package]] -name = "zbus" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725" -dependencies = [ - "async-broadcast", - "async-executor", - "async-fs", - "async-io", - "async-lock", - "async-process", - "async-recursion", - "async-task", - "async-trait", - "blocking", - "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", - "zbus_names", - "zvariant", -] - -[[package]] -name = "zbus-lockstep" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca2c5dceb099bddaade154055c926bb8ae507a18756ba1d8963fd7b51d8ed1d" -dependencies = [ - "zbus_xml", - "zvariant", -] - -[[package]] -name = "zbus-lockstep-macros" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "709ab20fc57cb22af85be7b360239563209258430bccf38d8b979c5a2ae3ecce" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.114", - "zbus-lockstep", - "zbus_xml", - "zvariant", -] - -[[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.114", - "zvariant_utils", -] - -[[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", -] - -[[package]] -name = "zbus_xml" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3f374552b954f6abb4bd6ce979e6c9b38fb9d0cd7cc68a7d796e70c9f3a233" -dependencies = [ - "quick-xml 0.30.0", - "serde", - "static_assertions", - "zbus_names", - "zvariant", -] - [[package]] name = "zeno" version = "0.3.3" @@ -9421,40 +8566,3 @@ checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713" 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", -] - -[[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.114", - "zvariant_utils", -] - -[[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.114", -] diff --git a/packages/blitz-shell/Cargo.toml b/packages/blitz-shell/Cargo.toml index 6ffba20d7..7f08c84d1 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_winit", "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_winit = { workspace = true, optional = true } # Other dependencies tracing = { workspace = true, optional = true } From 70f9dc2fa3656cdf27144a8cce45631e02afef17 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 8 Dec 2025 15:53:49 +0000 Subject: [PATCH 05/73] cfg ApplicationHandlerExtMacOS to macos --- packages/blitz-shell/src/application.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/blitz-shell/src/application.rs b/packages/blitz-shell/src/application.rs index d1774f80f..7984f50f8 100644 --- a/packages/blitz-shell/src/application.rs +++ b/packages/blitz-shell/src/application.rs @@ -6,7 +6,10 @@ use std::sync::mpsc::Receiver; use winit::event::WindowEvent; use winit::event_loop::ActiveEventLoop; use winit::window::WindowId; -use winit::{application::ApplicationHandler, platform::macos::ApplicationHandlerExtMacOS}; +use winit::{application::ApplicationHandler}; + +#[cfg(target_os = "macos")] +use winit::platform::macos::ApplicationHandlerExtMacOS; use crate::{View, WindowConfig}; @@ -83,10 +86,6 @@ impl BlitzApplication { } impl ApplicationHandler for BlitzApplication { - fn macos_handler(&mut self) -> Option<&mut dyn ApplicationHandlerExtMacOS> { - Some(self) - } - fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { // Resume existing windows for (_, view) in self.windows.iter_mut() { @@ -148,8 +147,14 @@ impl ApplicationHandler for BlitzApplication { self.handle_blitz_shell_event(event_loop, event); } } + + #[cfg(target_os = "macos")] + fn macos_handler(&mut self) -> Option<&mut dyn ApplicationHandlerExtMacOS> { + Some(self) + } } +#[cfg(target_os = "macos")] impl ApplicationHandlerExtMacOS for BlitzApplication { fn standard_key_binding( &mut self, From 9e94edef45347dab5908a81426d94da292531197 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 8 Dec 2025 15:56:28 +0000 Subject: [PATCH 06/73] Bump MSRV to 1.89 (required for Winit 0.31) Signed-off-by: Nico Burns --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 5e165d3e6..ce27d6f7e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -214,7 +214,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] From 2dda62c853b6eb0b8856deccfc44639010f95bd4 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 8 Dec 2025 16:08:53 +0000 Subject: [PATCH 07/73] Fix warnings Signed-off-by: Nico Burns --- packages/blitz-shell/src/accessibility.rs | 7 +++++-- packages/blitz-shell/src/application.rs | 2 +- packages/dioxus-native/src/dioxus_application.rs | 5 ++++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/blitz-shell/src/accessibility.rs b/packages/blitz-shell/src/accessibility.rs index 17f521611..79fc8ac3d 100644 --- a/packages/blitz-shell/src/accessibility.rs +++ b/packages/blitz-shell/src/accessibility.rs @@ -1,7 +1,7 @@ -use crate::event::{BlitzShellEvent, BlitzShellProxy}; +use crate::event::BlitzShellProxy; // use accesskit_winit::Adapter; use blitz_dom::BaseDocument; -use winit::{event_loop::EventLoopProxy, window::Window}; +use winit::window::Window; /// State of the accessibility node tree and platform adapter. pub struct AccessibilityState { @@ -11,11 +11,14 @@ pub struct AccessibilityState { impl AccessibilityState { pub fn new(window: &dyn Window, proxy: BlitzShellProxy) -> Self { + let _ = window; + let _ = proxy; Self { // adapter: Adapter::with_event_loop_proxy(window, proxy.clone()), } } pub fn update_tree(&mut self, doc: &BaseDocument) { + let _ = doc; // self.adapter // .update_if_active(|| doc.build_accessibility_tree()); } diff --git a/packages/blitz-shell/src/application.rs b/packages/blitz-shell/src/application.rs index 7984f50f8..5a0fbc189 100644 --- a/packages/blitz-shell/src/application.rs +++ b/packages/blitz-shell/src/application.rs @@ -3,10 +3,10 @@ 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; use winit::window::WindowId; -use winit::{application::ApplicationHandler}; #[cfg(target_os = "macos")] use winit::platform::macos::ApplicationHandlerExtMacOS; diff --git a/packages/dioxus-native/src/dioxus_application.rs b/packages/dioxus-native/src/dioxus_application.rs index 83605bd27..c03ee7954 100644 --- a/packages/dioxus-native/src/dioxus_application.rs +++ b/packages/dioxus-native/src/dioxus_application.rs @@ -5,9 +5,11 @@ use std::rc::Rc; use winit::application::ApplicationHandler; use winit::event::{StartCause, WindowEvent}; use winit::event_loop::ActiveEventLoop; -use winit::platform::macos::ApplicationHandlerExtMacOS; use winit::window::WindowId; +#[cfg(target_os = "macos")] +use winit::platform::macos::ApplicationHandlerExtMacOS; + use crate::DioxusNativeWindowRenderer; use crate::{contexts::DioxusNativeDocument, BlitzShellEvent, DioxusDocument, WindowConfig}; @@ -106,6 +108,7 @@ impl DioxusNativeApplication { } impl ApplicationHandler for DioxusNativeApplication { + #[cfg(target_os = "macos")] fn macos_handler(&mut self) -> Option<&mut dyn ApplicationHandlerExtMacOS> { self.inner.macos_handler() } From f426492eaace912e8f346e4c1dc56030325bedb6 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Tue, 9 Dec 2025 13:44:36 +0000 Subject: [PATCH 08/73] Dioxus Native: Add use_window and use_raw_window_handle hooks --- Cargo.lock | 1 + apps/browser/Cargo.toml | 1 + .../dioxus-native/src/dioxus_application.rs | 6 ++++++ packages/dioxus-native/src/lib.rs | 20 +++++++++++++++++-- 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0dccbfa2f..79aa0fc73 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -699,6 +699,7 @@ dependencies = [ "linebender_resource_handle", "tracing-subscriber", "webbrowser", + "winit", ] [[package]] diff --git a/apps/browser/Cargo.toml b/apps/browser/Cargo.toml index 2c4bba537..0707ccd5c 100644 --- a/apps/browser/Cargo.toml +++ b/apps/browser/Cargo.toml @@ -42,3 +42,4 @@ blitz-html = { workspace = true } linebender_resource_handle = { workspace = true } tracing-subscriber = { workspace = true, optional = true } webbrowser = { workspace = true } +winit = { workspace = true } diff --git a/packages/dioxus-native/src/dioxus_application.rs b/packages/dioxus-native/src/dioxus_application.rs index c03ee7954..cb4617802 100644 --- a/packages/dioxus-native/src/dioxus_application.rs +++ b/packages/dioxus-native/src/dioxus_application.rs @@ -2,6 +2,7 @@ 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; @@ -131,6 +132,7 @@ impl ApplicationHandler for DioxusNativeApplication { if let Some(config) = self.pending_window.take() { 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::(); @@ -157,6 +159,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(); diff --git a/packages/dioxus-native/src/lib.rs b/packages/dioxus-native/src/lib.rs index b4c7d53f6..386379915 100644 --- a/packages/dioxus-native/src/lib.rs +++ b/packages/dioxus-native/src/lib.rs @@ -61,11 +61,27 @@ pub use { use blitz_shell::{ create_default_event_loop, BlitzShellEvent, BlitzShellProxy, Config, WindowConfig, }; -use dioxus_core::{ComponentFunction, Element, VirtualDom}; +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) { From b1715caea4888af5752cdf5d92d3b2cb953ec55d Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sat, 27 Dec 2025 20:44:29 +0000 Subject: [PATCH 09/73] Fix html example --- examples/wgpu_texture/src/html.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) 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#" From 23d537e027125eafe97b45d33265c7c4bf4cdda5 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 28 Dec 2025 01:37:33 +0000 Subject: [PATCH 10/73] Implement "safe area" support --- examples/screenshot.rs | 10 +++++++++- packages/blitz-paint/src/lib.rs | 5 ++++- packages/blitz-shell/src/window.rs | 24 +++++++++++++++++++----- wpt/runner/src/test_runners/ref_test.rs | 2 +- 4 files changed, 33 insertions(+), 8 deletions(-) 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/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-shell/src/window.rs b/packages/blitz-shell/src/window.rs index 61856e8fc..7a18ccaf4 100644 --- a/packages/blitz-shell/src/window.rs +++ b/packages/blitz-shell/src/window.rs @@ -12,6 +12,7 @@ use blitz_traits::events::{ UiEvent, }; use blitz_traits::shell::Viewport; +use winit::dpi::PhysicalInsets; use winit::keyboard::PhysicalKey; use std::any::Any; @@ -67,6 +68,7 @@ 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`. @@ -86,6 +88,7 @@ impl View { // 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); @@ -118,6 +121,7 @@ impl View { 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")] @@ -198,8 +202,10 @@ impl View { }; // Render - self.renderer - .render(|scene| paint_scene(scene, &inner, scale, width, height)); + let insets = self.safe_area_insets; + self.renderer.render(|scene| { + paint_scene(scene, &inner, scale, width, height, insets.left, insets.top) + }); // Set waker self.waker = Some(create_waker(&self.proxy, window_id)); @@ -246,8 +252,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; + self.renderer.render(|scene| { + paint_scene(scene, &inner, scale, width, height, insets.left, insets.top) + }); drop(inner); @@ -298,10 +306,16 @@ impl View { } }, WindowEvent::SurfaceResized(physical_size) => { - self.with_viewport(|v| v.window_size = (physical_size.width, physical_size.height)); + 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(); } WindowEvent::ThemeChanged(theme) => { let color_scheme = theme_to_color_scheme(self.theme_override.unwrap_or(theme)); 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, ); From 23693fb9fac1df088c6975d6032e166dd3a47882 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 28 Dec 2025 14:58:37 +0000 Subject: [PATCH 11/73] Fix blitz crate --- packages/blitz/src/lib.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) 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; From 6d67b8763d65a769cf903c47fd48e706fad5142a Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 28 Dec 2025 15:29:31 +0000 Subject: [PATCH 12/73] Fix inner_html example --- examples/inner_html.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) 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#" From 1fe95ce36b896f13d88a17defc4feb384cd59d66 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 28 Dec 2025 15:35:40 +0000 Subject: [PATCH 13/73] Rename MouseButton event to PointerEvent Signed-off-by: Nico Burns --- packages/blitz-dom/src/events/driver.rs | 8 +++---- packages/blitz-dom/src/events/mouse.rs | 8 +++---- packages/blitz-dom/src/node/node.rs | 6 ++--- packages/blitz-shell/src/window.rs | 6 ++--- packages/blitz-traits/src/events.rs | 28 ++++++++++++------------ packages/dioxus-native-dom/src/events.rs | 4 ++-- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/packages/blitz-dom/src/events/driver.rs b/packages/blitz-dom/src/events/driver.rs index 4daa2e378..a61bcaac5 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::{BlitzPointerEvent, DomEvent, DomEventData, EventState, UiEvent}; use std::collections::VecDeque; pub trait EventHandler { @@ -142,17 +142,17 @@ impl<'doc, Handler: EventHandler> EventDriver<'doc, Handler> { }; let data = match event { - UiEvent::MouseMove(data) => DomEventData::MouseMove(BlitzMouseButtonEvent { + UiEvent::MouseMove(data) => DomEventData::MouseMove(BlitzPointerEvent { 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 { + UiEvent::MouseUp(data) => DomEventData::MouseUp(BlitzPointerEvent { 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 { + UiEvent::MouseDown(data) => DomEventData::MouseDown(BlitzPointerEvent { x: data.x + viewport_scroll.x as f32 / zoom, y: data.y + viewport_scroll.y as f32 / zoom, ..data diff --git a/packages/blitz-dom/src/events/mouse.rs b/packages/blitz-dom/src/events/mouse.rs index b66441bf4..463b2b84e 100644 --- a/packages/blitz-dom/src/events/mouse.rs +++ b/packages/blitz-dom/src/events/mouse.rs @@ -2,7 +2,7 @@ use std::time::{Duration, Instant}; use blitz_traits::{ events::{ - BlitzInputEvent, BlitzMouseButtonEvent, BlitzWheelDelta, BlitzWheelEvent, DomEvent, + BlitzInputEvent, BlitzPointerEvent, BlitzWheelDelta, BlitzWheelEvent, DomEvent, DomEventData, MouseEventButton, MouseEventButtons, }, navigation::NavigationOptions, @@ -20,7 +20,7 @@ pub(crate) fn handle_mousemove( x: f32, y: f32, buttons: MouseEventButtons, - event: &BlitzMouseButtonEvent, + event: &BlitzPointerEvent, mut dispatch_event: F, ) -> bool { let mut changed = doc.set_hover_to(x, y); @@ -228,7 +228,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 { @@ -266,7 +266,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(); diff --git a/packages/blitz-dom/src/node/node.rs b/packages/blitz-dom/src/node/node.rs index 0fdf07d98..de61e9e65 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, DomEventData, HitResult}; use blitz_traits::shell::ShellProvider; use html_escape::encode_quoted_attribute_to_string; use keyboard_types::Modifiers; @@ -1047,12 +1047,12 @@ 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 { x, y, mods, diff --git a/packages/blitz-shell/src/window.rs b/packages/blitz-shell/src/window.rs index 7a18ccaf4..a9dc85acb 100644 --- a/packages/blitz-shell/src/window.rs +++ b/packages/blitz-shell/src/window.rs @@ -8,7 +8,7 @@ use anyrender::WindowRenderer; use blitz_dom::Document; use blitz_paint::paint_scene; use blitz_traits::events::{ - BlitzMouseButtonEvent, BlitzWheelDelta, BlitzWheelEvent, MouseEventButton, MouseEventButtons, + BlitzPointerEvent, BlitzWheelDelta, BlitzWheelEvent, MouseEventButton, MouseEventButtons, UiEvent, }; use blitz_traits::shell::Viewport; @@ -396,7 +396,7 @@ impl View { WindowEvent::PointerMoved { position, .. } => { let winit::dpi::LogicalPosition:: { x, y } = position.to_logical(self.window.scale_factor()); self.mouse_pos = (x, y); - let event = UiEvent::MouseMove(BlitzMouseButtonEvent { + let event = UiEvent::MouseMove(BlitzPointerEvent { x, y, button: Default::default(), @@ -423,7 +423,7 @@ impl View { ElementState::Released => self.buttons ^= button.into(), } - let event = BlitzMouseButtonEvent { + let event = BlitzPointerEvent { x: self.mouse_pos.0, y: self.mouse_pos.1, button, diff --git a/packages/blitz-traits/src/events.rs b/packages/blitz-traits/src/events.rs index 9780a0171..429a23f7e 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), @@ -308,7 +308,7 @@ pub struct HitResult { } #[derive(Clone, Debug)] -pub struct BlitzMouseButtonEvent { +pub struct BlitzPointerEvent { pub x: f32, pub y: f32, pub button: MouseEventButton, diff --git a/packages/dioxus-native-dom/src/events.rs b/packages/dioxus-native-dom/src/events.rs index e447e1fc1..90b6abec3 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,7 +297,7 @@ 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 { From feed7e182c28a0018233aaee67f107e1423e611a Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 28 Dec 2025 15:37:09 +0000 Subject: [PATCH 14/73] Add PointerId to PointerEvent Signed-off-by: Nico Burns --- packages/blitz-dom/src/node/node.rs | 3 ++- packages/blitz-shell/src/window.rs | 6 ++++-- packages/blitz-traits/src/events.rs | 7 +++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/blitz-dom/src/node/node.rs b/packages/blitz-dom/src/node/node.rs index de61e9e65..cef547833 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::{BlitzPointerEvent, 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; @@ -1053,6 +1053,7 @@ impl Node { let y = absolute_position.y + (self.final_layout.size.height / 2.0); BlitzPointerEvent { + id: BlitzPointerId::Mouse, x, y, mods, diff --git a/packages/blitz-shell/src/window.rs b/packages/blitz-shell/src/window.rs index a9dc85acb..99c4352f7 100644 --- a/packages/blitz-shell/src/window.rs +++ b/packages/blitz-shell/src/window.rs @@ -8,8 +8,8 @@ use anyrender::WindowRenderer; use blitz_dom::Document; use blitz_paint::paint_scene; use blitz_traits::events::{ - BlitzPointerEvent, BlitzWheelDelta, BlitzWheelEvent, MouseEventButton, MouseEventButtons, - UiEvent, + BlitzPointerEvent, BlitzPointerId, BlitzWheelDelta, BlitzWheelEvent, MouseEventButton, + MouseEventButtons, UiEvent, }; use blitz_traits::shell::Viewport; use winit::dpi::PhysicalInsets; @@ -397,6 +397,7 @@ impl View { let winit::dpi::LogicalPosition:: { x, y } = position.to_logical(self.window.scale_factor()); self.mouse_pos = (x, y); let event = UiEvent::MouseMove(BlitzPointerEvent { + id: BlitzPointerId::Mouse, x, y, button: Default::default(), @@ -424,6 +425,7 @@ impl View { } let event = BlitzPointerEvent { + id: BlitzPointerId::Mouse, x: self.mouse_pos.0, y: self.mouse_pos.1, button, diff --git a/packages/blitz-traits/src/events.rs b/packages/blitz-traits/src/events.rs index 429a23f7e..dbe41d84d 100644 --- a/packages/blitz-traits/src/events.rs +++ b/packages/blitz-traits/src/events.rs @@ -307,8 +307,15 @@ pub struct HitResult { pub y: f32, } +#[derive(Copy, Clone, Debug)] +pub enum BlitzPointerId { + Mouse, + Finger(u64), +} + #[derive(Clone, Debug)] pub struct BlitzPointerEvent { + pub id: BlitzPointerId, pub x: f32, pub y: f32, pub button: MouseEventButton, From 53612dbcec2734be03b47fcba3cae969721b678a Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 28 Dec 2025 16:46:12 +0000 Subject: [PATCH 15/73] Touch events WIP Signed-off-by: Nico Burns --- packages/blitz-dom/src/node/node.rs | 1 + packages/blitz-shell/src/convert_events.rs | 32 ++++++++++++++++++++-- packages/blitz-shell/src/window.rs | 23 +++++++++------- packages/blitz-traits/src/events.rs | 16 ++++++++++- packages/dioxus-native-dom/src/events.rs | 8 +----- 5 files changed, 59 insertions(+), 21 deletions(-) diff --git a/packages/blitz-dom/src/node/node.rs b/packages/blitz-dom/src/node/node.rs index cef547833..588f8e294 100644 --- a/packages/blitz-dom/src/node/node.rs +++ b/packages/blitz-dom/src/node/node.rs @@ -1054,6 +1054,7 @@ impl Node { BlitzPointerEvent { id: BlitzPointerId::Mouse, + is_primary: true, x, y, mods, diff --git a/packages/blitz-shell/src/convert_events.rs b/packages/blitz-shell/src/convert_events.rs index bec3ba861..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; @@ -61,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() { diff --git a/packages/blitz-shell/src/window.rs b/packages/blitz-shell/src/window.rs index 99c4352f7..4110876f2 100644 --- a/packages/blitz-shell/src/window.rs +++ b/packages/blitz-shell/src/window.rs @@ -1,15 +1,15 @@ 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::{BlitzShellProxy, create_waker}; use anyrender::WindowRenderer; use blitz_dom::Document; use blitz_paint::paint_scene; use blitz_traits::events::{ - BlitzPointerEvent, BlitzPointerId, BlitzWheelDelta, BlitzWheelEvent, MouseEventButton, - MouseEventButtons, UiEvent, + BlitzPointerEvent, BlitzWheelDelta, BlitzWheelEvent, MouseEventButton, MouseEventButtons, + UiEvent, }; use blitz_traits::shell::Viewport; use winit::dpi::PhysicalInsets; @@ -393,11 +393,13 @@ impl View { } WindowEvent::PointerEntered { /*device_id*/.. } => {} WindowEvent::PointerLeft { /*device_id*/.. } => {} - WindowEvent::PointerMoved { position, .. } => { + WindowEvent::PointerMoved { position, source, primary, .. } => { + let id = pointer_source_to_blitz(&source); let winit::dpi::LogicalPosition:: { x, y } = position.to_logical(self.window.scale_factor()); self.mouse_pos = (x, y); let event = UiEvent::MouseMove(BlitzPointerEvent { - id: BlitzPointerId::Mouse, + id, + is_primary: primary, x, y, button: Default::default(), @@ -406,8 +408,9 @@ impl View { }); self.doc.handle_ui_event(event); } - WindowEvent::PointerButton { button, state, .. } => { - let button = match button { + WindowEvent::PointerButton { button, state, primary, .. } => { + 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, @@ -425,7 +428,8 @@ impl View { } let event = BlitzPointerEvent { - id: BlitzPointerId::Mouse, + id, + is_primary: primary, x: self.mouse_pos.0, y: self.mouse_pos.1, button, @@ -450,7 +454,6 @@ 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()), }; diff --git a/packages/blitz-traits/src/events.rs b/packages/blitz-traits/src/events.rs index dbe41d84d..0207fa977 100644 --- a/packages/blitz-traits/src/events.rs +++ b/packages/blitz-traits/src/events.rs @@ -316,6 +316,7 @@ pub enum BlitzPointerId { #[derive(Clone, Debug)] pub struct BlitzPointerEvent { pub id: BlitzPointerId, + pub is_primary: bool, pub x: f32, pub y: f32, pub button: MouseEventButton, @@ -328,7 +329,6 @@ pub struct BlitzWheelEvent { pub delta: BlitzWheelDelta, pub x: f32, pub y: f32, - pub button: MouseEventButton, pub buttons: MouseEventButtons, pub mods: Modifiers, } @@ -349,6 +349,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. diff --git a/packages/dioxus-native-dom/src/events.rs b/packages/dioxus-native-dom/src/events.rs index 90b6abec3..332f107b2 100644 --- a/packages/dioxus-native-dom/src/events.rs +++ b/packages/dioxus-native-dom/src/events.rs @@ -414,13 +414,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 { From 4cccd37daaa92143784388b14e783875df8700a5 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 28 Dec 2025 20:10:31 +0000 Subject: [PATCH 16/73] Setup counter, todomvc, and browser crates for compiling to Android --- Cargo.lock | 3 + apps/browser/Cargo.toml | 4 + apps/browser/Dioxus.toml | 1 + apps/browser/MainActivity.kt.hbs | 4 + apps/browser/src/main.rs | 8 +- examples/counter/Cargo.toml | 13 ++- examples/counter/Dioxus.toml | 2 + examples/counter/MainActivity.kt.hbs | 4 + examples/counter/src/app.rs | 114 +++++++++++++++++++++++++ examples/counter/src/lib.rs | 10 +++ examples/counter/src/main.rs | 122 +++------------------------ examples/todomvc/Cargo.toml | 5 +- examples/todomvc/Dioxus.toml | 2 + examples/todomvc/MainActivity.kt.hbs | 4 + examples/todomvc/src/main.rs | 7 ++ justfile | 5 ++ packages/blitz-shell/Cargo.toml | 2 +- 17 files changed, 193 insertions(+), 117 deletions(-) create mode 100644 apps/browser/MainActivity.kt.hbs create mode 100644 examples/counter/Dioxus.toml create mode 100644 examples/counter/MainActivity.kt.hbs create mode 100644 examples/counter/src/app.rs create mode 100644 examples/counter/src/lib.rs create mode 100644 examples/todomvc/Dioxus.toml create mode 100644 examples/todomvc/MainActivity.kt.hbs diff --git a/Cargo.lock b/Cargo.lock index 79aa0fc73..197f86786 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -691,6 +691,7 @@ dependencies = [ name = "browser" version = "0.0.0" dependencies = [ + "android-activity", "blitz-dom", "blitz-html", "blitz-net", @@ -1238,6 +1239,7 @@ dependencies = [ name = "counter" version = "0.1.0" dependencies = [ + "android-activity", "blitz-dom", "blitz-paint", "dioxus-native", @@ -6301,6 +6303,7 @@ dependencies = [ name = "todomvc" version = "0.1.0" dependencies = [ + "android-activity", "dioxus-native", "idna_adapter", "tracing-subscriber", diff --git a/apps/browser/Cargo.toml b/apps/browser/Cargo.toml index 0707ccd5c..fd69d4f83 100644 --- a/apps/browser/Cargo.toml +++ b/apps/browser/Cargo.toml @@ -43,3 +43,7 @@ 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 = ["native-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..a0ce0e2c3 --- /dev/null +++ b/apps/browser/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/apps/browser/src/main.rs b/apps/browser/src/main.rs index ca929f40f..535ed5bd7 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) } 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/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/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/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/blitz-shell/Cargo.toml b/packages/blitz-shell/Cargo.toml index 7f08c84d1..165de0100 100644 --- a/packages/blitz-shell/Cargo.toml +++ b/packages/blitz-shell/Cargo.toml @@ -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 } From d6ae3f4b0bca2c680c38e3db669421c8a50486e7 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 28 Dec 2025 20:11:15 +0000 Subject: [PATCH 17/73] Make Enter key work on Android/iOS --- examples/todomvc/src/app.rs | 7 ++++++- packages/blitz-dom/src/events/keyboard.rs | 8 ++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) 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/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"); From 95570d6900648b95ee1a1cf3c74eee77662ec2d2 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 28 Dec 2025 20:11:46 +0000 Subject: [PATCH 18/73] Don't ignore keyboard events with no physical keycode --- packages/blitz-shell/src/window.rs | 89 +++++++++++++++--------------- 1 file changed, 45 insertions(+), 44 deletions(-) diff --git a/packages/blitz-shell/src/window.rs b/packages/blitz-shell/src/window.rs index 4110876f2..3a08bcc51 100644 --- a/packages/blitz-shell/src/window.rs +++ b/packages/blitz-shell/src/window.rs @@ -331,54 +331,55 @@ 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().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(), - _ => {} - }; - } + if let PhysicalKey::Code(key_code) = event.physical_key { + if 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(), + _ => {} + }; + } + } } // Unmodified keypresses From e308762e997bd52b342d8e92202e8ceab15f1391 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 28 Dec 2025 20:12:24 +0000 Subject: [PATCH 19/73] fixup safe area --- packages/blitz-paint/src/render.rs | 5 ++++- packages/blitz-shell/src/window.rs | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/blitz-paint/src/render.rs b/packages/blitz-paint/src/render.rs index 89d53294b..b6e346f18 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/src/window.rs b/packages/blitz-shell/src/window.rs index 3a08bcc51..3269ea9bb 100644 --- a/packages/blitz-shell/src/window.rs +++ b/packages/blitz-shell/src/window.rs @@ -202,7 +202,7 @@ impl View { }; // Render - let insets = self.safe_area_insets; + let insets = self.safe_area_insets.to_logical(scale); self.renderer.render(|scene| { paint_scene(scene, &inner, scale, width, height, insets.left, insets.top) }); @@ -252,7 +252,7 @@ impl View { let (width, height) = inner.viewport().window_size; let scale = inner.viewport().scale_f64(); let is_animating = inner.is_animating(); - let insets = self.safe_area_insets; + let insets = self.safe_area_insets.to_logical(scale); self.renderer.render(|scene| { paint_scene(scene, &inner, scale, width, height, insets.left, insets.top) }); From 09aa8bc01e4394cd237bbe16028e53f3345e1590 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 28 Dec 2025 20:12:56 +0000 Subject: [PATCH 20/73] Touch events WIP2 --- packages/blitz-shell/src/window.rs | 39 ++++++++++++++++++++++------- packages/blitz-traits/src/events.rs | 2 +- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/packages/blitz-shell/src/window.rs b/packages/blitz-shell/src/window.rs index 3269ea9bb..1ff6249a5 100644 --- a/packages/blitz-shell/src/window.rs +++ b/packages/blitz-shell/src/window.rs @@ -8,8 +8,8 @@ use anyrender::WindowRenderer; use blitz_dom::Document; use blitz_paint::paint_scene; use blitz_traits::events::{ - BlitzPointerEvent, BlitzWheelDelta, BlitzWheelEvent, MouseEventButton, MouseEventButtons, - UiEvent, + BlitzPointerEvent, BlitzPointerId, BlitzWheelDelta, BlitzWheelEvent, MouseEventButton, + MouseEventButtons, UiEvent, }; use blitz_traits::shell::Viewport; use winit::dpi::PhysicalInsets; @@ -394,10 +394,12 @@ impl View { } WindowEvent::PointerEntered { /*device_id*/.. } => {} WindowEvent::PointerLeft { /*device_id*/.. } => {} - WindowEvent::PointerMoved { position, source, primary, .. } => { + WindowEvent::PointerMoved { mut position, source, primary, .. } => { let id = pointer_source_to_blitz(&source); + position.x -= self.safe_area_insets.left as f64; + position.y -= self.safe_area_insets.top as f64; let winit::dpi::LogicalPosition:: { x, y } = position.to_logical(self.window.scale_factor()); - self.mouse_pos = (x, y); + let event = UiEvent::MouseMove(BlitzPointerEvent { id, is_primary: primary, @@ -409,7 +411,7 @@ impl View { }); self.doc.handle_ui_event(event); } - WindowEvent::PointerButton { button, state, primary, .. } => { + WindowEvent::PointerButton { button, state, primary, mut position, .. } => { let id = button_source_to_blitz(&button); let button = match &button { ButtonSource::Mouse(mouse_button) => match mouse_button { @@ -417,9 +419,9 @@ impl View { MouseButton::Right => MouseEventButton::Secondary, MouseButton::Middle => MouseEventButton::Auxiliary, // TODO: handle other button types - _ => return, + _ => MouseEventButton::Auxiliary, } - _ => return, + _ => MouseEventButton::Main, }; @@ -428,11 +430,29 @@ impl View { ElementState::Released => self.buttons ^= button.into(), } + position.x -= self.safe_area_insets.left as f64; + position.y -= self.safe_area_insets.top as f64; + let winit::dpi::LogicalPosition:: { x, y } = position.to_logical(self.window.scale_factor()); + + if id != BlitzPointerId::Mouse { + let event = UiEvent::MouseMove(BlitzPointerEvent { + id, + is_primary: primary, + x, + 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: self.mouse_pos.0, - y: self.mouse_pos.1, + x, + y, button, buttons: self.buttons, mods: winit_modifiers_to_kbt_modifiers(self.keyboard_modifiers.state()), @@ -442,6 +462,7 @@ impl View { ElementState::Pressed => UiEvent::MouseDown(event), ElementState::Released => UiEvent::MouseUp(event), }; + self.doc.handle_ui_event(event); self.request_redraw(); } diff --git a/packages/blitz-traits/src/events.rs b/packages/blitz-traits/src/events.rs index 0207fa977..e154b682c 100644 --- a/packages/blitz-traits/src/events.rs +++ b/packages/blitz-traits/src/events.rs @@ -307,7 +307,7 @@ pub struct HitResult { pub y: f32, } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum BlitzPointerId { Mouse, Finger(u64), From 4559336def2a3334b48e8dce6a9488ae5d73396d Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 28 Dec 2025 20:25:27 +0000 Subject: [PATCH 21/73] Fixup Enter key --- apps/browser/src/main.rs | 7 ++++++- packages/blitz-shell/src/window.rs | 2 -- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/browser/src/main.rs b/apps/browser/src/main.rs index 535ed5bd7..4e4b390a9 100644 --- a/apps/browser/src/main.rs +++ b/apps/browser/src/main.rs @@ -140,7 +140,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/packages/blitz-shell/src/window.rs b/packages/blitz-shell/src/window.rs index 1ff6249a5..3df9bad7f 100644 --- a/packages/blitz-shell/src/window.rs +++ b/packages/blitz-shell/src/window.rs @@ -332,8 +332,6 @@ impl View { } WindowEvent::KeyboardInput { event, .. } => { - if event.state.is_pressed() { - if let PhysicalKey::Code(key_code) = event.physical_key { if event.state.is_pressed() { let ctrl = self.keyboard_modifiers.state().control_key(); From 0b45861930cc1dceaea35d969d2b228594fe7c2f Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 28 Dec 2025 22:01:59 +0000 Subject: [PATCH 22/73] Fixup don't ignore keyboard events --- packages/blitz-shell/src/window.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/blitz-shell/src/window.rs b/packages/blitz-shell/src/window.rs index 3df9bad7f..548ffe9d3 100644 --- a/packages/blitz-shell/src/window.rs +++ b/packages/blitz-shell/src/window.rs @@ -332,8 +332,7 @@ impl View { } WindowEvent::KeyboardInput { event, .. } => { - if let PhysicalKey::Code(key_code) = event.physical_key { - if event.state.is_pressed() { + 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(); @@ -377,7 +376,6 @@ impl View { }; } - } } // Unmodified keypresses From 171efc296343aaca8b34a2728ad19b6f77e3e15e Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 28 Dec 2025 22:03:17 +0000 Subject: [PATCH 23/73] Initial touch-to-pan support --- packages/blitz-dom/src/document.rs | 35 ++++++++++++- packages/blitz-dom/src/events/driver.rs | 18 ++++--- packages/blitz-dom/src/events/mouse.rs | 65 +++++++++++++++++-------- packages/blitz-dom/src/node/node.rs | 7 +++ packages/blitz-shell/src/window.rs | 54 +++++++++++++------- packages/blitz-traits/src/events.rs | 8 ++- 6 files changed, 141 insertions(+), 46 deletions(-) diff --git a/packages/blitz-dom/src/document.rs b/packages/blitz-dom/src/document.rs index 0f57d198f..5c1afa729 100644 --- a/packages/blitz-dom/src/document.rs +++ b/packages/blitz-dom/src/document.rs @@ -174,6 +174,23 @@ pub enum DocumentEvent { ResourceLoad(ResourceLoadResponse), } +#[derive(Debug, Clone, PartialEq)] +pub(crate) struct PanState { + pub(crate) target: usize, + pub(crate) last_x: f32, + pub(crate) last_y: 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), +} + pub struct BaseDocument { /// ID of the document id: usize, @@ -234,7 +251,7 @@ 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, /// Text selection state (for non-input text) pub(crate) text_selection: TextSelection, @@ -412,7 +429,7 @@ impl BaseDocument { last_mousedown_time: None, mousedown_position: taffy::Point::ZERO, click_count: 0, - is_selecting: false, + drag_mode: DragMode::None, text_selection: TextSelection::default(), }; @@ -1443,6 +1460,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 a61bcaac5..e07b52b8b 100644 --- a/packages/blitz-dom/src/events/driver.rs +++ b/packages/blitz-dom/src/events/driver.rs @@ -143,18 +143,24 @@ impl<'doc, Handler: EventHandler> EventDriver<'doc, Handler> { let data = match event { UiEvent::MouseMove(data) => DomEventData::MouseMove(BlitzPointerEvent { - x: data.x + viewport_scroll.x as f32 / zoom, - y: data.y + viewport_scroll.y as f32 / zoom, + x: data.x / zoom, + y: data.y / zoom, + client_x: data.client_x / zoom, + client_y: data.client_y / zoom, ..data }), UiEvent::MouseUp(data) => DomEventData::MouseUp(BlitzPointerEvent { - x: data.x + viewport_scroll.x as f32 / zoom, - y: data.y + viewport_scroll.y as f32 / zoom, + x: data.x / zoom, + y: data.y / zoom, + client_x: data.client_x / zoom, + client_y: data.client_y / zoom, ..data }), UiEvent::MouseDown(data) => DomEventData::MouseDown(BlitzPointerEvent { - x: data.x + viewport_scroll.x as f32 / zoom, - y: data.y + viewport_scroll.y as f32 / zoom, + x: data.x / zoom, + y: data.y / zoom, + client_x: data.client_x / zoom, + client_y: data.client_y / zoom, ..data }), UiEvent::Wheel(data) => DomEventData::Wheel(data), diff --git a/packages/blitz-dom/src/events/mouse.rs b/packages/blitz-dom/src/events/mouse.rs index 463b2b84e..357f827a2 100644 --- a/packages/blitz-dom/src/events/mouse.rs +++ b/packages/blitz-dom/src/events/mouse.rs @@ -2,15 +2,19 @@ use std::time::{Duration, Instant}; use blitz_traits::{ events::{ - BlitzInputEvent, BlitzPointerEvent, 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, PanState}, + node::SpecialElementData, +}; use super::focus::generate_focus_events; @@ -26,14 +30,36 @@ pub(crate) fn handle_mousemove( 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, + }); + } + } } } + 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 target = state.target; + state.last_x = event.screen_x; + state.last_y = event.screen_y; + + let has_changed = doc.scroll_by(Some(target), dx, dy, &mut dispatch_event); + return has_changed; + } + let Some(hit) = doc.hit(x, y) else { return changed; }; @@ -123,7 +149,7 @@ 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; let Some(hit) = doc.hit(x, y) else { // Clear text selection when clicking outside any element @@ -243,11 +269,12 @@ pub(crate) fn handle_mouseup( return; } - // Don't dispatch click if we were doing a text selection drag - let do_click = !doc.is_selecting; + // Don't dispatch click if we were doing a text selection drag or panning + // the document with a touch + let do_click = doc.drag_mode == DragMode::None; // Reset selection state - doc.is_selecting = false; + doc.drag_mode = DragMode::None; // Dispatch a click event if do_click && event.button == MouseEventButton::Main { @@ -431,19 +458,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 588f8e294..6c4c145fc 100644 --- a/packages/blitz-dom/src/node/node.rs +++ b/packages/blitz-dom/src/node/node.rs @@ -1057,6 +1057,13 @@ impl Node { 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-shell/src/window.rs b/packages/blitz-shell/src/window.rs index 548ffe9d3..e54b581cf 100644 --- a/packages/blitz-shell/src/window.rs +++ b/packages/blitz-shell/src/window.rs @@ -12,7 +12,7 @@ use blitz_traits::events::{ MouseEventButtons, UiEvent, }; use blitz_traits::shell::Viewport; -use winit::dpi::PhysicalInsets; +use winit::dpi::{LogicalPosition, PhysicalInsets}; use winit::keyboard::PhysicalKey; use std::any::Any; @@ -390,24 +390,33 @@ impl View { } WindowEvent::PointerEntered { /*device_id*/.. } => {} WindowEvent::PointerLeft { /*device_id*/.. } => {} - WindowEvent::PointerMoved { mut position, source, primary, .. } => { + WindowEvent::PointerMoved { position, source, primary, .. } => { let id = pointer_source_to_blitz(&source); - position.x -= self.safe_area_insets.left as f64; - position.y -= self.safe_area_insets.top as f64; - let winit::dpi::LogicalPosition:: { x, y } = position.to_logical(self.window.scale_factor()); - + + 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, - y, + 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::PointerButton { button, state, primary, mut position, .. } => { + WindowEvent::PointerButton { button, state, primary, position, .. } => { let id = button_source_to_blitz(&button); let button = match &button { ButtonSource::Mouse(mouse_button) => match mouse_button { @@ -426,16 +435,24 @@ impl View { ElementState::Released => self.buttons ^= button.into(), } - position.x -= self.safe_area_insets.left as f64; - position.y -= self.safe_area_insets.top as f64; - let winit::dpi::LogicalPosition:: { x, y } = position.to_logical(self.window.scale_factor()); + 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, - y, + 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()), @@ -443,12 +460,15 @@ impl View { self.doc.handle_ui_event(event); } - let event = BlitzPointerEvent { id, is_primary: primary, - x, - y, + 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()), diff --git a/packages/blitz-traits/src/events.rs b/packages/blitz-traits/src/events.rs index e154b682c..aa4a3c8c6 100644 --- a/packages/blitz-traits/src/events.rs +++ b/packages/blitz-traits/src/events.rs @@ -317,8 +317,12 @@ pub enum BlitzPointerId { pub struct BlitzPointerEvent { pub id: BlitzPointerId, pub is_primary: bool, - pub x: f32, - pub y: f32, + 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, From f064ea44de956c29fcb69f03ba08c7c40a22b728 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 28 Dec 2025 22:31:23 +0000 Subject: [PATCH 24/73] Fixup: safe area texture size --- packages/blitz-shell/src/window.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/blitz-shell/src/window.rs b/packages/blitz-shell/src/window.rs index e54b581cf..7cf37837d 100644 --- a/packages/blitz-shell/src/window.rs +++ b/packages/blitz-shell/src/window.rs @@ -277,7 +277,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(); } } From 68e4b038141f95cb4082714268fe3055baa7948d Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 29 Dec 2025 00:07:16 +0000 Subject: [PATCH 25/73] Browser: Hardcode top padding on android due to lack of "safe area" support --- apps/browser/src/main.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/apps/browser/src/main.rs b/apps/browser/src/main.rs index 4e4b390a9..3c7cc506a 100644 --- a/apps/browser/src/main.rs +++ b/apps/browser/src/main.rs @@ -89,8 +89,17 @@ 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") { + "50px" + } else { + "" + }; + rsx!( div { id: "frame", + padding_top: TOP_PAD, title { "Blitz Browser" } document::Link { rel: "stylesheet", href: BROWSER_UI_STYLES } From 4c6bec7ddda9cf52fe40cad5f4293a56f76e2e35 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 29 Dec 2025 15:17:52 +0000 Subject: [PATCH 26/73] Momentum scrolling WIP --- packages/blitz-dom/src/document.rs | 38 +++++++++- packages/blitz-dom/src/events/mod.rs | 10 +-- packages/blitz-dom/src/events/mouse.rs | 99 +++++++++++++++++++++++--- packages/blitz-dom/src/resolve.rs | 28 ++++++++ 4 files changed, 156 insertions(+), 19 deletions(-) diff --git a/packages/blitz-dom/src/document.rs b/packages/blitz-dom/src/document.rs index 5c1afa729..08a86b5e9 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,11 +174,33 @@ 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)] @@ -191,6 +213,12 @@ pub(crate) enum DragMode { 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, @@ -252,6 +280,8 @@ pub struct BaseDocument { pub(crate) click_count: u16, /// Whether we're currently in a text selection drag (moved 2px+ from mousedown) 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, @@ -430,6 +460,7 @@ impl BaseDocument { mousedown_position: taffy::Point::ZERO, click_count: 0, drag_mode: DragMode::None, + scroll_animation: ScrollAnimationState::None, text_selection: TextSelection::default(), }; @@ -1259,7 +1290,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 diff --git a/packages/blitz-dom/src/events/mod.rs b/packages/blitz-dom/src/events/mod.rs index 45e4960a8..b6fbdea46 100644 --- a/packages/blitz-dom/src/events/mod.rs +++ b/packages/blitz-dom/src/events/mod.rs @@ -85,15 +85,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 357f827a2..1492ebecf 100644 --- a/packages/blitz-dom/src/events/mouse.rs +++ b/packages/blitz-dom/src/events/mouse.rs @@ -1,4 +1,7 @@ -use std::time::{Duration, Instant}; +use std::{ + collections::VecDeque, + time::{Duration, Instant, SystemTime, UNIX_EPOCH}, +}; use blitz_traits::{ events::{ @@ -12,7 +15,7 @@ use markup5ever::local_name; use crate::{ BaseDocument, - document::{DragMode, PanState}, + document::{DragMode, FlingState, PanSample, PanState, ScrollAnimationState}, node::SpecialElementData, }; @@ -21,12 +24,13 @@ use super::focus::generate_focus_events; pub(crate) fn handle_mousemove( doc: &mut BaseDocument, target: usize, - x: f32, - y: f32, - buttons: MouseEventButtons, 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) @@ -43,6 +47,7 @@ pub(crate) fn handle_mousemove( target, last_x: event.screen_x, last_y: event.screen_y, + samples: VecDeque::with_capacity(200), }); } } @@ -52,10 +57,33 @@ pub(crate) fn handle_mousemove( 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; } @@ -150,6 +178,7 @@ pub(crate) fn handle_mousedown( doc.last_mousedown_time = Some(Instant::now()); doc.mousedown_position = taffy::Point { x, y }; 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 @@ -269,12 +298,66 @@ pub(crate) fn handle_mouseup( return; } + // 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 = doc.drag_mode == DragMode::None; + 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) + }); - // Reset selection state - doc.drag_mode = DragMode::None; + 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 + }; + + let fling = FlingState { + target: state.target, + last_seen_time: time_ms as f64, + x_velocity: x_velocity as f64 * 16.6666, + y_velocity: y_velocity as f64 * 16.6666, + }; + + doc.scroll_animation = ScrollAnimationState::Fling(fling); + doc.shell_provider.request_redraw(); + } + } + } // Dispatch a click event if do_click && event.button == MouseEventButton::Main { diff --git a/packages/blitz-dom/src/resolve.rs b/packages/blitz-dom/src/resolve.rs index 37fa16972..69e887cd0 100644 --- a/packages/blitz-dom/src/resolve.rs +++ b/packages/blitz-dom/src/resolve.rs @@ -22,6 +22,7 @@ use taffy::AvailableSpace; use crate::{ BaseDocument, NON_INCREMENTAL, + document::ScrollAnimationState, layout::{ construct::{ ConstructionTask, ConstructionTaskData, ConstructionTaskResult, @@ -46,6 +47,8 @@ impl BaseDocument { // Process messages that have been sent to our message channel (e.g. loaded resource) self.handle_messages(); + self.resolve_scroll_animation(current_time_for_animations); + let root_node_id = self.root_element().id; debug_timer!(timer, feature = "log_phase_times"); @@ -110,6 +113,31 @@ impl BaseDocument { timer.print_times(&format!("Resolve({}): ", self.id())); } + pub fn resolve_scroll_animation(&mut self, animation_time: f64) { + match &mut self.scroll_animation { + ScrollAnimationState::Fling(fling_state) => { + // let time_diff_ms = animation_time - fling_state.last_seen_time; + + // TODO: consider time + fling_state.x_velocity *= 0.95; + fling_state.y_velocity *= 0.95; + fling_state.last_seen_time = animation_time; + 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() < 1.0 && fling_state.y_velocity.abs() < 1.0 { + 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); From 1d37689dd7815a15124eeb8e36780d400311bce2 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 29 Dec 2025 15:20:58 +0000 Subject: [PATCH 27/73] Homepage=wikipedia Signed-off-by: Nico Burns --- apps/browser/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/browser/src/main.rs b/apps/browser/src/main.rs index 3c7cc506a..758a54a0d 100644 --- a/apps/browser/src/main.rs +++ b/apps/browser/src/main.rs @@ -45,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); From 7d5c8f3fb5ccb8164c69bb6d2561bac2c7f7f1f1 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 29 Dec 2025 15:30:33 +0000 Subject: [PATCH 28/73] Fixup momentum scrolling --- packages/blitz-dom/src/events/mouse.rs | 4 ++-- packages/blitz-dom/src/resolve.rs | 32 +++++++++++++++++--------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/packages/blitz-dom/src/events/mouse.rs b/packages/blitz-dom/src/events/mouse.rs index 1492ebecf..4a1396f56 100644 --- a/packages/blitz-dom/src/events/mouse.rs +++ b/packages/blitz-dom/src/events/mouse.rs @@ -349,8 +349,8 @@ pub(crate) fn handle_mouseup( let fling = FlingState { target: state.target, last_seen_time: time_ms as f64, - x_velocity: x_velocity as f64 * 16.6666, - y_velocity: y_velocity as f64 * 16.6666, + x_velocity: x_velocity as f64, // * 16.6666, + y_velocity: y_velocity as f64, // * 16.6666, }; doc.scroll_animation = ScrollAnimationState::Fling(fling); diff --git a/packages/blitz-dom/src/resolve.rs b/packages/blitz-dom/src/resolve.rs index 69e887cd0..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; @@ -47,7 +50,7 @@ impl BaseDocument { // Process messages that have been sent to our message channel (e.g. loaded resource) self.handle_messages(); - self.resolve_scroll_animation(current_time_for_animations); + self.resolve_scroll_animation(); let root_node_id = self.root_element().id; debug_timer!(timer, feature = "log_phase_times"); @@ -113,22 +116,29 @@ impl BaseDocument { timer.print_times(&format!("Resolve({}): ", self.id())); } - pub fn resolve_scroll_animation(&mut self, animation_time: f64) { + pub fn resolve_scroll_animation(&mut self) { match &mut self.scroll_animation { ScrollAnimationState::Fling(fling_state) => { - // let time_diff_ms = animation_time - fling_state.last_seen_time; + 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); - // TODO: consider time - fling_state.x_velocity *= 0.95; - fling_state.y_velocity *= 0.95; - fling_state.last_seen_time = animation_time; + 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; + 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() < 1.0 && fling_state.y_velocity.abs() < 1.0 { + if fling_state.x_velocity.abs() < 0.1 && fling_state.y_velocity.abs() < 0.1 { self.scroll_animation = ScrollAnimationState::None; } } From 6063c68248b77e0aad784b688dbe5cdb252ce56f Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 29 Dec 2025 15:41:34 +0000 Subject: [PATCH 29/73] Fix request_redraw on iOS --- packages/blitz-shell/src/application.rs | 9 +++++++++ packages/blitz-shell/src/window.rs | 14 ++++++++++++++ packages/dioxus-native/src/dioxus_application.rs | 4 ++++ 3 files changed, 27 insertions(+) diff --git a/packages/blitz-shell/src/application.rs b/packages/blitz-shell/src/application.rs index 5a0fbc189..87962fb76 100644 --- a/packages/blitz-shell/src/application.rs +++ b/packages/blitz-shell/src/application.rs @@ -152,6 +152,15 @@ impl ApplicationHandler for BlitzApplication { fn macos_handler(&mut self) -> Option<&mut dyn ApplicationHandlerExtMacOS> { Some(self) } + + #[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")] diff --git a/packages/blitz-shell/src/window.rs b/packages/blitz-shell/src/window.rs index 7cf37837d..874139c0b 100644 --- a/packages/blitz-shell/src/window.rs +++ b/packages/blitz-shell/src/window.rs @@ -73,6 +73,13 @@ pub struct View { #[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 { @@ -126,6 +133,9 @@ impl View { is_visible: winit_window.is_visible().unwrap_or(true), #[cfg(feature = "accessibility")] accessibility: AccessibilityState::new(&*winit_window, proxy.clone()), + + #[cfg(target_os = "ios")] + ios_request_redraw: std::cell::Cell::new(false), } } @@ -239,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; diff --git a/packages/dioxus-native/src/dioxus_application.rs b/packages/dioxus-native/src/dioxus_application.rs index cb4617802..ee4ac7c8b 100644 --- a/packages/dioxus-native/src/dioxus_application.rs +++ b/packages/dioxus-native/src/dioxus_application.rs @@ -126,6 +126,10 @@ impl ApplicationHandler for DioxusNativeApplication { 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"); From f1135e27037e432de63508da730b6165e4e4adf0 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 29 Dec 2025 16:57:39 +0000 Subject: [PATCH 30/73] Fix mouse coordinates for sub documents --- packages/blitz-dom/src/events/driver.rs | 32 +++++-------------------- packages/blitz-dom/src/events/mod.rs | 19 ++++++++++----- 2 files changed, 19 insertions(+), 32 deletions(-) diff --git a/packages/blitz-dom/src/events/driver.rs b/packages/blitz-dom/src/events/driver.rs index e07b52b8b..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::{BlitzPointerEvent, 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,27 +140,9 @@ impl<'doc, Handler: EventHandler> EventDriver<'doc, Handler> { }; let data = match event { - UiEvent::MouseMove(data) => DomEventData::MouseMove(BlitzPointerEvent { - x: data.x / zoom, - y: data.y / zoom, - client_x: data.client_x / zoom, - client_y: data.client_y / zoom, - ..data - }), - UiEvent::MouseUp(data) => DomEventData::MouseUp(BlitzPointerEvent { - x: data.x / zoom, - y: data.y / zoom, - client_x: data.client_x / zoom, - client_y: data.client_y / zoom, - ..data - }), - UiEvent::MouseDown(data) => DomEventData::MouseDown(BlitzPointerEvent { - x: data.x / zoom, - y: data.y / zoom, - client_x: data.client_x / zoom, - client_y: data.client_y / 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/mod.rs b/packages/blitz-dom/src/events/mod.rs index b6fbdea46..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)) } From f709c0463e56a67c6592ef12f13fb11749586f61 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 29 Dec 2025 17:00:22 +0000 Subject: [PATCH 31/73] Implement client_coordinates, screen_coordinates, and page_coordinates for Dioxus Native click events. --- packages/dioxus-native-dom/src/events.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/dioxus-native-dom/src/events.rs b/packages/dioxus-native-dom/src/events.rs index 332f107b2..2a2a3bf73 100644 --- a/packages/dioxus-native-dom/src/events.rs +++ b/packages/dioxus-native-dom/src/events.rs @@ -301,16 +301,15 @@ 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) } } From eb2f21517111d7a2abc864052277e663d4cf34b7 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 29 Dec 2025 21:22:55 +0000 Subject: [PATCH 32/73] Fixup request_redraw unused variable --- packages/blitz-shell/src/application.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/blitz-shell/src/application.rs b/packages/blitz-shell/src/application.rs index 87962fb76..9b03501c7 100644 --- a/packages/blitz-shell/src/application.rs +++ b/packages/blitz-shell/src/application.rs @@ -154,7 +154,7 @@ impl ApplicationHandler for BlitzApplication { } #[cfg(target_os = "ios")] - fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) { + 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(); From 769bc633ff1e059e8ecc02bdaee6b1a6158ff975 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 29 Dec 2025 21:49:04 +0000 Subject: [PATCH 33/73] Add 2x factor to momentum scroll speed --- packages/blitz-dom/src/events/mouse.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/blitz-dom/src/events/mouse.rs b/packages/blitz-dom/src/events/mouse.rs index 4a1396f56..e3feba3a4 100644 --- a/packages/blitz-dom/src/events/mouse.rs +++ b/packages/blitz-dom/src/events/mouse.rs @@ -349,8 +349,8 @@ pub(crate) fn handle_mouseup( let fling = FlingState { target: state.target, last_seen_time: time_ms as f64, - x_velocity: x_velocity as f64, // * 16.6666, - y_velocity: y_velocity as f64, // * 16.6666, + x_velocity: x_velocity as f64 * 2.0, + y_velocity: y_velocity as f64 * 2.0, }; doc.scroll_animation = ScrollAnimationState::Fling(fling); From 807c7ce8c44ed1e763bf791bade7a531983c6062 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 29 Dec 2025 21:49:21 +0000 Subject: [PATCH 34/73] Tweak hacky android "safe area" --- apps/browser/assets/browser.css | 1 + apps/browser/src/main.rs | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) 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 758a54a0d..23c15a4e5 100644 --- a/apps/browser/src/main.rs +++ b/apps/browser/src/main.rs @@ -92,7 +92,12 @@ 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") { - "50px" + "30px" + } else { + "" + }; + const BOTTOM_PAD: &str = if cfg!(target_os = "android") { + "44px" } else { "" }; @@ -100,6 +105,7 @@ fn app() -> Element { rsx!( div { id: "frame", padding_top: TOP_PAD, + padding_bottom: BOTTOM_PAD, title { "Blitz Browser" } document::Link { rel: "stylesheet", href: BROWSER_UI_STYLES } From 5efa09215290dae43e8363cff781d678771bc431 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 4 Jan 2026 14:47:44 +0000 Subject: [PATCH 35/73] Add accesskit_xplat crate Signed-off-by: Nico Burns --- Cargo.lock | 891 ++++++++++++++++-- Cargo.toml | 1 + packages/accesskit_xplat/CHANGELOG.md | 885 +++++++++++++++++ packages/accesskit_xplat/Cargo.toml | 33 + packages/accesskit_xplat/src/lib.rs | 164 ++++ .../src/platform_impl/android.rs | 46 + .../src/platform_impl/macos.rs | 43 + .../accesskit_xplat/src/platform_impl/mod.rs | 50 + .../accesskit_xplat/src/platform_impl/null.rs | 24 + .../accesskit_xplat/src/platform_impl/unix.rs | 43 + .../src/platform_impl/windows.rs | 40 + 11 files changed, 2135 insertions(+), 85 deletions(-) create mode 100644 packages/accesskit_xplat/CHANGELOG.md create mode 100644 packages/accesskit_xplat/Cargo.toml create mode 100644 packages/accesskit_xplat/src/lib.rs create mode 100644 packages/accesskit_xplat/src/platform_impl/android.rs create mode 100644 packages/accesskit_xplat/src/platform_impl/macos.rs create mode 100644 packages/accesskit_xplat/src/platform_impl/mod.rs create mode 100644 packages/accesskit_xplat/src/platform_impl/null.rs create mode 100644 packages/accesskit_xplat/src/platform_impl/unix.rs create mode 100644 packages/accesskit_xplat/src/platform_impl/windows.rs diff --git a/Cargo.lock b/Cargo.lock index 197f86786..786f21e22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,6 +24,109 @@ version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3d3b8f9bae46a948369bc4a03e815d4ed6d616bd00de4051133a5019dc31c5a" +[[package]] +name = "accesskit" +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 = "d28b60a573c7165b1eb346d66c14e85a1f7923fe2e71e396ce936ca6afb519ae" +dependencies = [ + "accesskit 0.22.0", + "accesskit_consumer", + "jni", + "log", +] + +[[package]] +name = "accesskit_atspi_common" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb9cc46b7fb6987c4f891f0301b230b29d9e69b4854f060a0cf41fbc407ab77" +dependencies = [ + "accesskit 0.22.0", + "accesskit_consumer", + "atspi-common", + "serde", + "zvariant", +] + +[[package]] +name = "accesskit_consumer" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69d880a613f29621c90e801feec40f5dd61d837d7e20bf9b67676d45e7364a36" +dependencies = [ + "accesskit 0.22.0", + "hashbrown 0.16.1", +] + +[[package]] +name = "accesskit_macos" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0ddfc3fe3d457d11cc1c4989105986a03583a1d54d0c25053118944b62e100" +dependencies = [ + "accesskit 0.22.0", + "accesskit_consumer", + "hashbrown 0.16.1", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "accesskit_unix" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5d552169ef018149966ed139bb0311c6947b3343e9140d1b9f88d69da9528fd" +dependencies = [ + "accesskit 0.22.0", + "accesskit_atspi_common", + "async-channel", + "async-executor", + "async-task", + "atspi", + "futures-lite", + "futures-util", + "serde", + "tokio", + "tokio-stream", + "zbus", +] + +[[package]] +name = "accesskit_windows" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d277279d0a3b0c0021dd110b55aa1fe326b09ee2cbc338df28f847c7daf94e25" +dependencies = [ + "accesskit 0.22.0", + "accesskit_consumer", + "hashbrown 0.16.1", + "static_assertions", + "windows 0.61.3", + "windows-core 0.61.2", +] + +[[package]] +name = "accesskit_xplat" +version = "0.1.0" +dependencies = [ + "accesskit 0.22.0", + "accesskit_android", + "accesskit_macos", + "accesskit_unix", + "accesskit_windows", + "android-activity", + "raw-window-handle", + "winit-core", +] + [[package]] name = "adler2" version = "2.0.1" @@ -191,11 +294,11 @@ dependencies = [ "hashbrown 0.16.1", "kurbo", "oaty", - "objc2", - "objc2-app-kit", + "objc2 0.6.3", + "objc2-app-kit 0.3.2", "objc2-core-foundation", - "objc2-metal", - "objc2-quartz-core", + "objc2-metal 0.3.2", + "objc2-quartz-core 0.3.2", "objc2-ui-kit", "peniko", "pixels_window_renderer", @@ -286,9 +389,9 @@ checksum = "0348a1c054491f4bfe6ab86a7b6ab1e44e45d899005de92f58b3df180b36ddaf" dependencies = [ "clipboard-win", "log", - "objc2", - "objc2-app-kit", - "objc2-foundation", + "objc2 0.6.3", + "objc2-app-kit 0.3.2", + "objc2-foundation 0.3.2", "parking_lot", "percent-encoding", "windows-sys 0.60.2", @@ -342,6 +445,126 @@ dependencies = [ "raw-window-metal", ] +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix 1.1.3", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-lock" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix 1.1.3", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", +] + +[[package]] +name = "async-signal" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 1.1.3", + "signal-hook-registry", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + [[package]] name = "async-trait" version = "0.1.89" @@ -371,6 +594,43 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41e67cd8309bbd06cd603a9e693a784ac2e5d1e955f11286e355089fcab3047c" +[[package]] +name = "atspi" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c77886257be21c9cd89a4ae7e64860c6f0eefca799bb79127913052bd0eefb3d" +dependencies = [ + "atspi-common", + "atspi-proxies", +] + +[[package]] +name = "atspi-common" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20c5617155740c98003016429ad13fe43ce7a77b007479350a9f8bf95a29f63d" +dependencies = [ + "enumflags2", + "serde", + "static_assertions", + "zbus", + "zbus-lockstep", + "zbus-lockstep-macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "atspi-proxies" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2230e48787ed3eb4088996eab66a32ca20c0b67bbd4fd6cdfe79f04f1f04c9fc" +dependencies = [ + "atspi-common", + "serde", + "zbus", +] + [[package]] name = "autocfg" version = "1.5.0" @@ -504,7 +764,7 @@ dependencies = [ name = "blitz-dom" version = "0.2.2" dependencies = [ - "accesskit", + "accesskit 0.17.1", "app_units", "atomic_refcell", "bitflags 2.10.0", @@ -520,7 +780,7 @@ dependencies = [ "keyboard-types 0.7.0", "linebender_resource_handle", "markup5ever", - "objc2", + "objc2 0.6.3", "parley", "percent-encoding", "rayon", @@ -615,7 +875,7 @@ dependencies = [ name = "blitz-shell" version = "0.2.2" dependencies = [ - "accesskit", + "accesskit 0.17.1", "android-activity", "anyrender", "arboard", @@ -659,13 +919,35 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2 0.5.2", +] + [[package]] name = "block2" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" dependencies = [ - "objc2", + "objc2 0.6.3", +] + +[[package]] +name = "blocking" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", ] [[package]] @@ -1944,9 +2226,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" dependencies = [ "bitflags 2.10.0", - "block2", + "block2 0.6.2", "libc", - "objc2", + "objc2 0.6.3", ] [[package]] @@ -2066,12 +2348,39 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "endi" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" + [[package]] name = "entities" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5320ae4c3782150d900b79807611a59a99fc9a1d61d686faafc24b93fc8d7ca" +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", +] + [[package]] name = "enumset" version = "1.1.10" @@ -2148,6 +2457,27 @@ dependencies = [ "serde", ] +[[package]] +name = "event-listener" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + [[package]] name = "fallible_collections" version = "0.4.9" @@ -2290,10 +2620,10 @@ dependencies = [ "icu_locale_core", "linebender_resource_handle", "memmap2 0.9.9", - "objc2", + "objc2 0.6.3", "objc2-core-foundation", "objc2-core-text", - "objc2-foundation", + "objc2-foundation 0.3.2", "read-fonts 0.35.0", "roxmltree 0.21.1", "smallvec", @@ -2421,6 +2751,19 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + [[package]] name = "futures-macro" version = "0.3.31" @@ -2489,7 +2832,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" dependencies = [ "rustix 1.1.3", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -2610,10 +2953,10 @@ dependencies = [ "glutin_glx_sys", "glutin_wgl_sys 0.6.1", "libloading 0.8.9", - "objc2", - "objc2-app-kit", + "objc2 0.6.3", + "objc2-app-kit 0.3.2", "objc2-core-foundation", - "objc2-foundation", + "objc2-foundation 0.3.2", "once_cell", "raw-window-handle", "wayland-sys", @@ -3496,7 +3839,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -3697,6 +4040,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "metal" version = "0.27.0" @@ -4079,6 +4431,22 @@ dependencies = [ "objc_exception", ] +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + [[package]] name = "objc2" version = "0.6.3" @@ -4088,6 +4456,22 @@ dependencies = [ "objc2-encode", ] +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.10.0", + "block2 0.5.1", + "libc", + "objc2 0.5.2", + "objc2-core-data 0.2.2", + "objc2-core-image 0.2.2", + "objc2-foundation 0.2.2", + "objc2-quartz-core 0.2.2", +] + [[package]] name = "objc2-app-kit" version = "0.3.2" @@ -4095,12 +4479,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ "bitflags 2.10.0", - "block2", - "objc2", + "block2 0.6.2", + "objc2 0.6.3", "objc2-core-foundation", "objc2-core-graphics", - "objc2-foundation", - "objc2-quartz-core", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", ] [[package]] @@ -4110,8 +4494,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" dependencies = [ "bitflags 2.10.0", - "objc2", - "objc2-foundation", + "objc2 0.6.3", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.10.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", ] [[package]] @@ -4120,8 +4516,8 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" dependencies = [ - "objc2", - "objc2-foundation", + "objc2 0.6.3", + "objc2-foundation 0.3.2", ] [[package]] @@ -4131,9 +4527,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ "bitflags 2.10.0", - "block2", + "block2 0.6.2", "dispatch2", - "objc2", + "objc2 0.6.3", ] [[package]] @@ -4145,19 +4541,31 @@ dependencies = [ "bitflags 2.10.0", "dispatch2", "libc", - "objc2", + "objc2 0.6.3", "objc2-core-foundation", "objc2-io-surface", ] +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal 0.2.2", +] + [[package]] name = "objc2-core-image" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006" dependencies = [ - "objc2", - "objc2-foundation", + "objc2 0.6.3", + "objc2-foundation 0.3.2", ] [[package]] @@ -4166,8 +4574,8 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009" dependencies = [ - "objc2", - "objc2-foundation", + "objc2 0.6.3", + "objc2-foundation 0.3.2", ] [[package]] @@ -4177,7 +4585,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" dependencies = [ "bitflags 2.10.0", - "objc2", + "objc2 0.6.3", "objc2-core-foundation", "objc2-core-graphics", ] @@ -4199,6 +4607,18 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.10.0", + "block2 0.5.1", + "libc", + "objc2 0.5.2", +] + [[package]] name = "objc2-foundation" version = "0.3.2" @@ -4206,9 +4626,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ "bitflags 2.10.0", - "block2", + "block2 0.6.2", "libc", - "objc2", + "objc2 0.6.3", "objc2-core-foundation", ] @@ -4219,10 +4639,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ "bitflags 2.10.0", - "objc2", + "objc2 0.6.3", "objc2-core-foundation", ] +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.10.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + [[package]] name = "objc2-metal" version = "0.3.2" @@ -4230,8 +4662,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794" dependencies = [ "bitflags 2.10.0", - "objc2", - "objc2-foundation", + "objc2 0.6.3", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.10.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal 0.2.2", ] [[package]] @@ -4241,10 +4686,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ "bitflags 2.10.0", - "objc2", + "objc2 0.6.3", "objc2-core-foundation", - "objc2-foundation", - "objc2-metal", + "objc2-foundation 0.3.2", + "objc2-metal 0.3.2", ] [[package]] @@ -4254,17 +4699,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ "bitflags 2.10.0", - "block2", - "objc2", + "block2 0.6.2", + "objc2 0.6.3", "objc2-cloud-kit", - "objc2-core-data", + "objc2-core-data 0.3.2", "objc2-core-foundation", "objc2-core-graphics", - "objc2-core-image", + "objc2-core-image 0.3.2", "objc2-core-location", "objc2-core-text", - "objc2-foundation", - "objc2-quartz-core", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", "objc2-user-notifications", ] @@ -4274,8 +4719,8 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e" dependencies = [ - "objc2", - "objc2-foundation", + "objc2 0.6.3", + "objc2-foundation 0.3.2", ] [[package]] @@ -4377,6 +4822,16 @@ dependencies = [ "num-traits", ] +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "os_info" version = "3.14.0" @@ -4386,8 +4841,8 @@ dependencies = [ "android_system_properties", "log", "nix", - "objc2", - "objc2-foundation", + "objc2 0.6.3", + "objc2-foundation 0.3.2", "objc2-ui-kit", "serde", "windows-sys 0.61.2", @@ -4408,6 +4863,12 @@ version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52" +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" version = "0.12.5" @@ -4428,7 +4889,7 @@ dependencies = [ "libc", "redox_syscall 0.5.18", "smallvec", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -4560,6 +5021,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + [[package]] name = "pixels" version = "0.15.0" @@ -4776,6 +5248,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" dependencies = [ "memchr", + "serde", ] [[package]] @@ -5054,15 +5527,15 @@ version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "069d6129dede311430d0dcf1ded88a7affc7a342c2d8e6336043d43ed14dac17" dependencies = [ - "block2", + "block2 0.6.2", "dispatch2", "js-sys", "libc", "log", - "objc2", - "objc2-app-kit", + "objc2 0.6.3", + "objc2-app-kit 0.3.2", "objc2-core-foundation", - "objc2-foundation", + "objc2-foundation 0.3.2", "percent-encoding", "pollster 0.4.0", "raw-window-handle", @@ -5476,6 +5949,16 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + [[package]] name = "simd-adler32" version = "0.3.8" @@ -5661,11 +6144,11 @@ dependencies = [ "js-sys", "memmap2 0.9.9", "ndk", - "objc2", + "objc2 0.6.3", "objc2-core-foundation", "objc2-core-graphics", - "objc2-foundation", - "objc2-quartz-core", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", "raw-window-handle", "redox_syscall 0.5.18", "rustix 1.1.3", @@ -6616,6 +7099,17 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +[[package]] +name = "uds_windows" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" +dependencies = [ + "memoffset", + "tempfile", + "winapi", +] + [[package]] name = "ultraviolet" version = "0.9.2" @@ -6798,6 +7292,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" dependencies = [ "js-sys", + "serde_core", "wasm-bindgen", ] @@ -7233,8 +7728,8 @@ dependencies = [ "jni", "log", "ndk-context", - "objc2", - "objc2-foundation", + "objc2 0.6.3", + "objc2-foundation 0.3.2", "url", "web-sys", ] @@ -7598,16 +8093,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]] @@ -7641,6 +8158,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" @@ -7649,11 +8179,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" @@ -7661,8 +8202,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]] @@ -7709,12 +8250,28 @@ dependencies = [ "syn 2.0.114", ] +[[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" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", +] + [[package]] name = "windows-numerics" version = "0.3.1" @@ -7722,7 +8279,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" dependencies = [ "windows-core 0.62.2", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -7731,7 +8288,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" dependencies = [ - "windows-link", + "windows-link 0.2.1", "windows-result 0.4.1", "windows-strings 0.5.1", ] @@ -7745,13 +8302,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]] @@ -7764,13 +8330,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]] @@ -7815,7 +8390,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]] @@ -7855,7 +8430,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", @@ -7866,13 +8441,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]] @@ -8063,15 +8647,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21310ca07851a49c348e0c2cc768e36b52ca65afda2c2354d78ed4b90074d8aa" dependencies = [ "bitflags 2.10.0", - "block2", + "block2 0.6.2", "dispatch2", "dpi", - "objc2", - "objc2-app-kit", + "objc2 0.6.3", + "objc2-app-kit 0.3.2", "objc2-core-foundation", "objc2-core-graphics", "objc2-core-video", - "objc2-foundation", + "objc2-foundation 0.3.2", "raw-window-handle", "smol_str", "tracing", @@ -8086,7 +8670,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45375fbac4cbb77260d83a30b1f9d8105880dbac99a9ae97f56656694680ff69" dependencies = [ "memmap2 0.9.9", - "objc2", + "objc2 0.6.3", "objc2-core-foundation", "smol_str", "tracing", @@ -8133,12 +8717,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "680a356e798837d8eb274d4556e83bceaf81698194e31aafc5cfb8a9f2fab643" dependencies = [ "bitflags 2.10.0", - "block2", + "block2 0.6.2", "dispatch2", "dpi", - "objc2", + "objc2 0.6.3", "objc2-core-foundation", - "objc2-foundation", + "objc2-foundation 0.3.2", "objc2-ui-kit", "raw-window-handle", "smol_str", @@ -8465,6 +9049,103 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zbus" +version = "5.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17f79257df967b6779afa536788657777a0001f5b42524fcaf5038d4344df40b" +dependencies = [ + "async-broadcast", + "async-executor", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener", + "futures-core", + "futures-lite", + "hex", + "libc", + "ordered-stream", + "rustix 1.1.3", + "serde", + "serde_repr", + "tracing", + "uds_windows", + "uuid", + "windows-sys 0.61.2", + "winnow", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus-lockstep" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6998de05217a084b7578728a9443d04ea4cd80f2a0839b8d78770b76ccd45863" +dependencies = [ + "zbus_xml", + "zvariant", +] + +[[package]] +name = "zbus-lockstep-macros" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10da05367f3a7b7553c8cdf8fa91aee6b64afebe32b51c95177957efc47ca3a0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", + "zbus-lockstep", + "zbus_xml", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "5.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aad23e2d2f91cae771c7af7a630a49e755f1eb74f8a46e9f6d5f7a146edf5a37" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.114", + "zbus_names", + "zvariant", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffd8af6d5b78619bab301ff3c560a5bd22426150253db278f164d6cf3b72c50f" +dependencies = [ + "serde", + "winnow", + "zvariant", +] + +[[package]] +name = "zbus_xml" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "441a0064125265655bccc3a6af6bef56814d9277ac83fce48b1cd7e160b80eac" +dependencies = [ + "quick-xml", + "serde", + "zbus_names", + "zvariant", +] + [[package]] name = "zeno" version = "0.3.3" @@ -8570,3 +9251,43 @@ checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713" dependencies = [ "zune-core", ] + +[[package]] +name = "zvariant" +version = "5.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "326aaed414f04fe839777b4c443d4e94c74e7b3621093bd9c5e649ac8aa96543" +dependencies = [ + "endi", + "enumflags2", + "serde", + "winnow", + "zvariant_derive", + "zvariant_utils", +] + +[[package]] +name = "zvariant_derive" +version = "5.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba44e1f8f4da9e6e2d25d2a60b116ef8b9d0be174a7685e55bb12a99866279a7" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.114", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f75c23a64ef8f40f13a6989991e643554d9bef1d682a281160cf0c1bc389c5e9" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "syn 2.0.114", + "winnow", +] diff --git a/Cargo.toml b/Cargo.toml index ce27d6f7e..f2574bb98 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", 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..57e8eb926 --- /dev/null +++ b/packages/accesskit_xplat/src/lib.rs @@ -0,0 +1,164 @@ +// 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, +}; +use raw_window_handle::RawWindowHandle; + +mod platform_impl; + +#[derive(Clone, Debug, PartialEq)] +pub enum WindowEvent { + InitialTreeRequested, + ActionRequested(ActionRequest), + AccessibilityDeactivated, +} + +pub trait EventHandler: Send + '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..c68c9378a --- /dev/null +++ b/packages/accesskit_xplat/src/platform_impl/null.rs @@ -0,0 +1,24 @@ +// 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, TreeUpdate}; + +pub struct Adapter; + +impl Adapter { + pub fn new( + _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..50896a2a6 --- /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..b9475104f --- /dev/null +++ b/packages/accesskit_xplat/src/platform_impl/windows.rs @@ -0,0 +1,40 @@ +// 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, TreeUpdate}; +use accesskit_windows::{HWND, SubclassingAdapter}; +use raw_window_handle::RawWindowHandle; +use winit::{event::WindowEvent, event_loop::ActiveEventLoop, window::Window}; + +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) {} +} From 24652194220b94a8cf33da61cc8d60709c6218e7 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 4 Jan 2026 15:07:30 +0000 Subject: [PATCH 36/73] Re-enable accessibility support based on accesskit_xplat Signed-off-by: Nico Burns --- Cargo.lock | 25 ++++----- Cargo.toml | 4 +- packages/accesskit_xplat/src/lib.rs | 8 +-- packages/blitz-shell/Cargo.toml | 4 +- packages/blitz-shell/src/accessibility.rs | 67 ++++++++++++++++++++--- packages/blitz-shell/src/application.rs | 32 +++++------ packages/blitz-shell/src/event.rs | 24 +++----- packages/blitz-shell/src/window.rs | 5 ++ 8 files changed, 104 insertions(+), 65 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 786f21e22..df188b88b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,12 +18,6 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" -[[package]] -name = "accesskit" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3d3b8f9bae46a948369bc4a03e815d4ed6d616bd00de4051133a5019dc31c5a" - [[package]] name = "accesskit" version = "0.22.0" @@ -36,7 +30,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d28b60a573c7165b1eb346d66c14e85a1f7923fe2e71e396ce936ca6afb519ae" dependencies = [ - "accesskit 0.22.0", + "accesskit", "accesskit_consumer", "jni", "log", @@ -48,7 +42,7 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3eb9cc46b7fb6987c4f891f0301b230b29d9e69b4854f060a0cf41fbc407ab77" dependencies = [ - "accesskit 0.22.0", + "accesskit", "accesskit_consumer", "atspi-common", "serde", @@ -61,7 +55,7 @@ version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69d880a613f29621c90e801feec40f5dd61d837d7e20bf9b67676d45e7364a36" dependencies = [ - "accesskit 0.22.0", + "accesskit", "hashbrown 0.16.1", ] @@ -71,7 +65,7 @@ version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b0ddfc3fe3d457d11cc1c4989105986a03583a1d54d0c25053118944b62e100" dependencies = [ - "accesskit 0.22.0", + "accesskit", "accesskit_consumer", "hashbrown 0.16.1", "objc2 0.5.2", @@ -85,7 +79,7 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5d552169ef018149966ed139bb0311c6947b3343e9140d1b9f88d69da9528fd" dependencies = [ - "accesskit 0.22.0", + "accesskit", "accesskit_atspi_common", "async-channel", "async-executor", @@ -105,7 +99,7 @@ version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d277279d0a3b0c0021dd110b55aa1fe326b09ee2cbc338df28f847c7daf94e25" dependencies = [ - "accesskit 0.22.0", + "accesskit", "accesskit_consumer", "hashbrown 0.16.1", "static_assertions", @@ -117,7 +111,7 @@ dependencies = [ name = "accesskit_xplat" version = "0.1.0" dependencies = [ - "accesskit 0.22.0", + "accesskit", "accesskit_android", "accesskit_macos", "accesskit_unix", @@ -764,7 +758,7 @@ dependencies = [ name = "blitz-dom" version = "0.2.2" dependencies = [ - "accesskit 0.17.1", + "accesskit", "app_units", "atomic_refcell", "bitflags 2.10.0", @@ -875,7 +869,8 @@ dependencies = [ name = "blitz-shell" version = "0.2.2" dependencies = [ - "accesskit 0.17.1", + "accesskit", + "accesskit_xplat", "android-activity", "anyrender", "arboard", diff --git a/Cargo.toml b/Cargo.toml index f2574bb98..66c782558 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,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.11.0", package = "stylo" } @@ -130,8 +131,7 @@ usvg = "0.46" # Windowing & Input raw-window-handle = "0.6.0" winit = { version = "=0.31.0-beta.2" } -accesskit_winit = "0.23" -accesskit = "0.17" +accesskit = "0.22" arboard = { version = "3.4.1", default-features = false } rfd = { version = "0.17.1", default-features = false } keyboard-types = "0.7" diff --git a/packages/accesskit_xplat/src/lib.rs b/packages/accesskit_xplat/src/lib.rs index 57e8eb926..f47b57679 100644 --- a/packages/accesskit_xplat/src/lib.rs +++ b/packages/accesskit_xplat/src/lib.rs @@ -109,7 +109,7 @@ impl Adapter { /// 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, + #[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, @@ -118,7 +118,7 @@ impl Adapter { #[cfg(target_os = "android")] android_app, #[cfg(not(target_os = "android"))] - window, + &window, activation_handler, action_handler, deactivation_handler, @@ -128,7 +128,7 @@ impl Adapter { pub fn with_combined_handler( #[cfg(target_os = "android")] android_app: &AndroidApp, - #[cfg(not(target_os = "android"))] window: &RawWindowHandle, + #[cfg(not(target_os = "android"))] window: RawWindowHandle, handler: Arc, ) -> Self { let handler = CombinedHandler(handler); @@ -136,7 +136,7 @@ impl Adapter { #[cfg(target_os = "android")] android_app, #[cfg(not(target_os = "android"))] - window, + &window, handler.clone(), handler.clone(), handler, diff --git a/packages/blitz-shell/Cargo.toml b/packages/blitz-shell/Cargo.toml index 165de0100..989840b38 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 } diff --git a/packages/blitz-shell/src/accessibility.rs b/packages/blitz-shell/src/accessibility.rs index 79fc8ac3d..ab3f6e333 100644 --- a/packages/blitz-shell/src/accessibility.rs +++ b/packages/blitz-shell/src/accessibility.rs @@ -1,25 +1,74 @@ -use crate::event::BlitzShellProxy; -// 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::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: 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: &dyn Window, proxy: BlitzShellProxy) -> Self { - let _ = window; - let _ = proxy; + 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()); + 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 9b03501c7..2bd6bdd71 100644 --- a/packages/blitz-shell/src/application.rs +++ b/packages/blitz-shell/src/application.rs @@ -56,22 +56,22 @@ impl BlitzApplication { } } - // #[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(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). } diff --git a/packages/blitz-shell/src/event.rs b/packages/blitz-shell/src/event.rs index 6b3ce497e..1093ba357 100644 --- a/packages/blitz-shell/src/event.rs +++ b/packages/blitz-shell/src/event.rs @@ -5,8 +5,8 @@ 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}; +#[cfg(feature = "accessibility")] +use accesskit_xplat::WindowEvent as AccessKitEvent; #[derive(Debug, Clone)] pub enum BlitzShellEvent { @@ -19,11 +19,11 @@ pub enum BlitzShellEvent { }, /// An accessibility event from `accesskit`. - // #[cfg(feature = "accessibility")] - // Accessibility { - // window_id: WindowId, - // data: Arc, - // }, + #[cfg(feature = "accessibility")] + Accessibility { + window_id: WindowId, + data: Arc, + }, /// An arbitary event from the Blitz embedder Embedder(Arc), @@ -46,16 +46,6 @@ 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 { diff --git a/packages/blitz-shell/src/window.rs b/packages/blitz-shell/src/window.rs index 874139c0b..f754f3715 100644 --- a/packages/blitz-shell/src/window.rs +++ b/packages/blitz-shell/src/window.rs @@ -307,6 +307,11 @@ 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 { WindowEvent::Destroyed => {} WindowEvent::ActivationTokenDone { .. } => {}, From 67b51d7bc0eb37df94c7d21ffe75ebb51d00227c Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 4 Jan 2026 15:13:55 +0000 Subject: [PATCH 37/73] Fix clippy linux issues --- packages/accesskit_xplat/src/lib.rs | 2 +- packages/accesskit_xplat/src/platform_impl/unix.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/accesskit_xplat/src/lib.rs b/packages/accesskit_xplat/src/lib.rs index f47b57679..4e4984106 100644 --- a/packages/accesskit_xplat/src/lib.rs +++ b/packages/accesskit_xplat/src/lib.rs @@ -57,7 +57,7 @@ pub enum WindowEvent { AccessibilityDeactivated, } -pub trait EventHandler: Send + 'static { +pub trait EventHandler: Send + Sync + 'static { fn handle_accesskit_event(&self, event: WindowEvent); } diff --git a/packages/accesskit_xplat/src/platform_impl/unix.rs b/packages/accesskit_xplat/src/platform_impl/unix.rs index 50896a2a6..ee320e5c8 100644 --- a/packages/accesskit_xplat/src/platform_impl/unix.rs +++ b/packages/accesskit_xplat/src/platform_impl/unix.rs @@ -34,7 +34,7 @@ impl Adapter { } pub fn set_focus(&mut self, is_focused: bool) { - self.update_window_focus_state(*is_focused); + self.update_window_focus_state(is_focused); } pub fn set_window_bounds(&mut self, outer_bounds: Rect, inner_bounds: Rect) { From 18517805157cade9674be5bc864353b76e65fe40 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 4 Jan 2026 15:17:30 +0000 Subject: [PATCH 38/73] Feature flag MacOS handler Signed-off-by: Nico Burns --- apps/readme/src/readme_application.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/readme/src/readme_application.rs b/apps/readme/src/readme_application.rs index db45cf4c1..3e635d910 100644 --- a/apps/readme/src/readme_application.rs +++ b/apps/readme/src/readme_application.rs @@ -11,6 +11,7 @@ use winit::application::ApplicationHandler; use winit::event::{Modifiers, StartCause, WindowEvent}; use winit::event_loop::ActiveEventLoop; use winit::keyboard::{KeyCode, PhysicalKey}; +#[cfg(target_os = "macos")] use winit::platform::macos::ApplicationHandlerExtMacOS; use winit::window::{Theme, WindowId}; @@ -131,6 +132,7 @@ impl ReadmeApplication { } impl ApplicationHandler for ReadmeApplication { + #[cfg(target_os = "macos")] fn macos_handler(&mut self) -> Option<&mut dyn ApplicationHandlerExtMacOS> { self.inner.macos_handler() } From becf2e35fcd979e81528284a65670e31aba364a1 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 4 Jan 2026 15:21:15 +0000 Subject: [PATCH 39/73] Add Android and iOS CI tasks Signed-off-by: Nico Burns --- .github/workflows/ci.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f3c507f63..2ab189e98 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -157,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: false, + command: "build", + args: "--all", + } name: Test (${{ matrix.platform.name }}) From 89b8063135286743477b446215319ea5b156b9eb Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 4 Jan 2026 15:21:59 +0000 Subject: [PATCH 40/73] Import Rect Signed-off-by: Nico Burns --- packages/accesskit_xplat/src/platform_impl/null.rs | 2 +- packages/accesskit_xplat/src/platform_impl/windows.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/accesskit_xplat/src/platform_impl/null.rs b/packages/accesskit_xplat/src/platform_impl/null.rs index c68c9378a..6e3fe02d9 100644 --- a/packages/accesskit_xplat/src/platform_impl/null.rs +++ b/packages/accesskit_xplat/src/platform_impl/null.rs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0 (found in // the LICENSE-APACHE file). -use accesskit::{ActionHandler, ActivationHandler, DeactivationHandler, TreeUpdate}; +use accesskit::{ActionHandler, ActivationHandler, DeactivationHandler, Rect, TreeUpdate}; pub struct Adapter; diff --git a/packages/accesskit_xplat/src/platform_impl/windows.rs b/packages/accesskit_xplat/src/platform_impl/windows.rs index b9475104f..2421d2fb9 100644 --- a/packages/accesskit_xplat/src/platform_impl/windows.rs +++ b/packages/accesskit_xplat/src/platform_impl/windows.rs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0 (found in // the LICENSE-APACHE file). -use accesskit::{ActionHandler, ActivationHandler, DeactivationHandler, TreeUpdate}; +use accesskit::{ActionHandler, ActivationHandler, DeactivationHandler, Rect, TreeUpdate}; use accesskit_windows::{HWND, SubclassingAdapter}; use raw_window_handle::RawWindowHandle; use winit::{event::WindowEvent, event_loop::ActiveEventLoop, window::Window}; @@ -34,7 +34,7 @@ impl Adapter { } } - pub fn set_focus(&mut self, is_focused: bool) {} + pub fn set_focus(&mut self, _is_focused: bool) {} pub fn set_window_bounds(&mut self, outer_bounds: Rect, inner_bounds: Rect) {} } From adc0c56686c26655ca635478116a018d814aef7e Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 4 Jan 2026 15:29:40 +0000 Subject: [PATCH 41/73] More null backend fixes Signed-off-by: Nico Burns --- packages/accesskit_xplat/src/platform_impl/null.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/accesskit_xplat/src/platform_impl/null.rs b/packages/accesskit_xplat/src/platform_impl/null.rs index 6e3fe02d9..465342097 100644 --- a/packages/accesskit_xplat/src/platform_impl/null.rs +++ b/packages/accesskit_xplat/src/platform_impl/null.rs @@ -3,6 +3,7 @@ // the LICENSE-APACHE file). use accesskit::{ActionHandler, ActivationHandler, DeactivationHandler, Rect, TreeUpdate}; +use raw_window_handle::RawWindowHandle; pub struct Adapter; @@ -18,7 +19,7 @@ impl Adapter { pub fn update_if_active(&mut self, _updater: impl FnOnce() -> TreeUpdate) {} - pub fn set_focus(&mut self, is_focused: bool) {} + pub fn set_focus(&mut self, _is_focused: bool) {} - pub fn set_window_bounds(&mut self, outer_bounds: Rect, inner_bounds: Rect) {} + pub fn set_window_bounds(&mut self, _outer_bounds: Rect, _inner_bounds: Rect) {} } From c5cb33cce0cb7f6481a9e8ab2630d14bac9d00fb Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 4 Jan 2026 15:30:11 +0000 Subject: [PATCH 42/73] Install libssl-dev for Android Signed-off-by: Nico Burns --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2ab189e98..40bbcab2c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -207,7 +207,7 @@ 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: Setup From 3952c4935cff17b18400e9d574aa8ae5ac61b5dc Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 4 Jan 2026 15:42:12 +0000 Subject: [PATCH 43/73] Use rustls for reqwest Signed-off-by: Nico Burns --- Cargo.lock | 268 +++++++++++----------------------- Cargo.toml | 2 +- apps/browser/Cargo.toml | 2 +- packages/blitz-net/Cargo.toml | 3 +- 4 files changed, 90 insertions(+), 185 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index df188b88b..4b841758e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1208,7 +1208,7 @@ dependencies = [ "cocoa-foundation", "core-foundation 0.9.4", "core-graphics", - "foreign-types 0.5.0", + "foreign-types", "libc", "objc", ] @@ -1477,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", ] @@ -2627,15 +2627,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" @@ -2643,7 +2634,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]] @@ -2657,12 +2648,6 @@ dependencies = [ "syn 2.0.114", ] -[[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" @@ -2846,8 +2831,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -2857,9 +2844,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]] @@ -3384,22 +3373,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]] @@ -3421,11 +3395,9 @@ dependencies = [ "percent-encoding", "pin-project-lite", "socket2", - "system-configuration", "tokio", "tower-service", "tracing", - "windows-registry", ] [[package]] @@ -3911,6 +3883,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 = "macro-string" version = "0.1.4" @@ -4053,7 +4031,7 @@ dependencies = [ "bitflags 2.10.0", "block", "core-graphics-types 0.1.3", - "foreign-types 0.5.0", + "foreign-types", "log", "objc", "paste", @@ -4068,7 +4046,7 @@ dependencies = [ "bitflags 2.10.0", "block", "core-graphics-types 0.2.0", - "foreign-types 0.5.0", + "foreign-types", "log", "objc", "paste", @@ -4201,23 +4179,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" @@ -4739,50 +4700,6 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" -[[package]] -name = "openssl" -version = "0.10.75" -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", -] - -[[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.114", -] - -[[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" @@ -5246,6 +5163,61 @@ dependencies = [ "serde", ] +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "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 = "quinn-proto" +version = "0.11.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +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 = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases 0.2.1", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.60.2", +] + [[package]] name = "quote" version = "1.0.43" @@ -5474,22 +5446,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", @@ -5499,6 +5471,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", + "webpki-roots", ] [[package]] @@ -5623,6 +5596,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" dependencies = [ "once_cell", + "ring", "rustls-pki-types", "rustls-webpki", "subtle", @@ -5635,6 +5609,7 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282" dependencies = [ + "web-time", "zeroize", ] @@ -5697,15 +5672,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" @@ -5731,29 +5697,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.35.0" @@ -6500,27 +6443,6 @@ dependencies = [ "syn 2.0.114", ] -[[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" @@ -6813,16 +6735,6 @@ dependencies = [ "syn 2.0.114", ] -[[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" @@ -7297,12 +7209,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.7.0" @@ -7729,6 +7635,15 @@ dependencies = [ "web-sys", ] +[[package]] +name = "webpki-roots" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12bed680863276c63889429bfd6cab3b99943659923822de1c8a39c49e4d722c" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "weezl" version = "0.1.12" @@ -8277,17 +8192,6 @@ dependencies = [ "windows-link 0.2.1", ] -[[package]] -name = "windows-registry" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" -dependencies = [ - "windows-link 0.2.1", - "windows-result 0.4.1", - "windows-strings 0.5.1", -] - [[package]] name = "windows-result" version = "0.2.0" diff --git a/Cargo.toml b/Cargo.toml index 66c782558..ff82b6202 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -142,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 } diff --git a/apps/browser/Cargo.toml b/apps/browser/Cargo.toml index fd69d4f83..d72d14856 100644 --- a/apps/browser/Cargo.toml +++ b/apps/browser/Cargo.toml @@ -37,7 +37,7 @@ 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 } 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 From e09aace3d32b81c11cb9aee8345e7bac0043352b Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 4 Jan 2026 15:54:31 +0000 Subject: [PATCH 44/73] Use cross for Android CI Signed-off-by: Nico Burns --- .github/workflows/ci.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 40bbcab2c..65ddafdb4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -169,7 +169,7 @@ jobs: name: android, target: aarch64-linux-android, os: ubuntu-latest, - cross: false, + cross: true, command: "build", args: "--all", } @@ -210,6 +210,10 @@ jobs: 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 From ddf24455a45e16cece229d1ae83482785780791b Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 4 Jan 2026 16:06:04 +0000 Subject: [PATCH 45/73] Install python in Cross container Signed-off-by: Nico Burns --- Cross.toml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 Cross.toml 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 From 4d88b1160f54b09c610e7e0706b279ebb1a33cb4 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 4 Jan 2026 16:10:51 +0000 Subject: [PATCH 46/73] accesskit_xplat windows fixes Signed-off-by: Nico Burns --- packages/accesskit_xplat/src/platform_impl/windows.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/accesskit_xplat/src/platform_impl/windows.rs b/packages/accesskit_xplat/src/platform_impl/windows.rs index 2421d2fb9..3b001dc1d 100644 --- a/packages/accesskit_xplat/src/platform_impl/windows.rs +++ b/packages/accesskit_xplat/src/platform_impl/windows.rs @@ -5,7 +5,6 @@ use accesskit::{ActionHandler, ActivationHandler, DeactivationHandler, Rect, TreeUpdate}; use accesskit_windows::{HWND, SubclassingAdapter}; use raw_window_handle::RawWindowHandle; -use winit::{event::WindowEvent, event_loop::ActiveEventLoop, window::Window}; pub struct Adapter { adapter: SubclassingAdapter, @@ -36,5 +35,5 @@ impl Adapter { pub fn set_focus(&mut self, _is_focused: bool) {} - pub fn set_window_bounds(&mut self, outer_bounds: Rect, inner_bounds: Rect) {} + pub fn set_window_bounds(&mut self, _outer_bounds: Rect, _inner_bounds: Rect) {} } From d06b21f51cf826e56f142303b79cb16f0345331a Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 4 Jan 2026 16:11:27 +0000 Subject: [PATCH 47/73] Don't fail-fast tests Signed-off-by: Nico Burns --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 65ddafdb4..4d2610a8e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -131,6 +131,7 @@ jobs: env: RUST_CARGO_COMMAND: ${{ matrix.platform.cross == true && 'cross' || 'cargo' }} strategy: + fail-fast: false matrix: platform: - { From 7aabdfff28b316608f213d7a25d3525be40f9937 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 4 Jan 2026 16:17:06 +0000 Subject: [PATCH 48/73] Import AndroidApp on android Signed-off-by: Nico Burns --- packages/accesskit_xplat/src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/accesskit_xplat/src/lib.rs b/packages/accesskit_xplat/src/lib.rs index 4e4984106..83d2bc7ea 100644 --- a/packages/accesskit_xplat/src/lib.rs +++ b/packages/accesskit_xplat/src/lib.rs @@ -46,6 +46,11 @@ 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; From 235a4599a982bc21f2ff93a1ad0384d8358c3102 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 4 Jan 2026 16:22:45 +0000 Subject: [PATCH 49/73] fmt Signed-off-by: Nico Burns --- packages/accesskit_xplat/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/accesskit_xplat/src/lib.rs b/packages/accesskit_xplat/src/lib.rs index 83d2bc7ea..cfcac0827 100644 --- a/packages/accesskit_xplat/src/lib.rs +++ b/packages/accesskit_xplat/src/lib.rs @@ -47,7 +47,6 @@ use accesskit::{ ActionHandler, ActionRequest, ActivationHandler, DeactivationHandler, Rect, TreeUpdate, }; - #[cfg(target_os = "android")] use android_activity::AndroidApp; #[cfg(not(target_os = "android"))] From 4039298abf83612b9c1c6b80e5b8442e24169784 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 4 Jan 2026 16:24:27 +0000 Subject: [PATCH 50/73] Fix null backend on android Signed-off-by: Nico Burns --- packages/accesskit_xplat/src/platform_impl/null.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/accesskit_xplat/src/platform_impl/null.rs b/packages/accesskit_xplat/src/platform_impl/null.rs index 465342097..22ffa5dd1 100644 --- a/packages/accesskit_xplat/src/platform_impl/null.rs +++ b/packages/accesskit_xplat/src/platform_impl/null.rs @@ -9,7 +9,8 @@ pub struct Adapter; impl Adapter { pub fn new( - _window_handle: &RawWindowHandle, + #[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, From 4032855078cc6f8bca0005764ac1559cc8b34c53 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 5 Jan 2026 00:50:55 +0000 Subject: [PATCH 51/73] Remove winit-core dep from accesskit_xplat --- Cargo.lock | 1 - packages/accesskit_xplat/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4b841758e..7bf46ee9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -118,7 +118,6 @@ dependencies = [ "accesskit_windows", "android-activity", "raw-window-handle", - "winit-core", ] [[package]] diff --git a/packages/accesskit_xplat/Cargo.toml b/packages/accesskit_xplat/Cargo.toml index f8a13d2d7..60dba5c2f 100644 --- a/packages/accesskit_xplat/Cargo.toml +++ b/packages/accesskit_xplat/Cargo.toml @@ -15,7 +15,6 @@ 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] From 2eb58ff0fdea6414b124efc9553423c1967f7bef Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 5 Jan 2026 00:55:55 +0000 Subject: [PATCH 52/73] Fix: consistently use unreferenced RawWindowHandle Signed-off-by: Nico Burns --- packages/accesskit_xplat/src/lib.rs | 8 ++++---- packages/accesskit_xplat/src/platform_impl/macos.rs | 2 +- packages/accesskit_xplat/src/platform_impl/unix.rs | 2 +- packages/accesskit_xplat/src/platform_impl/windows.rs | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/accesskit_xplat/src/lib.rs b/packages/accesskit_xplat/src/lib.rs index cfcac0827..3ac7ee768 100644 --- a/packages/accesskit_xplat/src/lib.rs +++ b/packages/accesskit_xplat/src/lib.rs @@ -113,7 +113,7 @@ impl Adapter { /// 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, + #[cfg(not(target_os = "android"))] window_handle: RawWindowHandle, activation_handler: impl 'static + ActivationHandler + Send, action_handler: impl 'static + ActionHandler + Send, deactivation_handler: impl 'static + DeactivationHandler + Send, @@ -122,7 +122,7 @@ impl Adapter { #[cfg(target_os = "android")] android_app, #[cfg(not(target_os = "android"))] - &window, + window_handle, activation_handler, action_handler, deactivation_handler, @@ -132,7 +132,7 @@ impl Adapter { pub fn with_combined_handler( #[cfg(target_os = "android")] android_app: &AndroidApp, - #[cfg(not(target_os = "android"))] window: RawWindowHandle, + #[cfg(not(target_os = "android"))] window_handle: RawWindowHandle, handler: Arc, ) -> Self { let handler = CombinedHandler(handler); @@ -140,7 +140,7 @@ impl Adapter { #[cfg(target_os = "android")] android_app, #[cfg(not(target_os = "android"))] - &window, + window_handle, handler.clone(), handler.clone(), handler, diff --git a/packages/accesskit_xplat/src/platform_impl/macos.rs b/packages/accesskit_xplat/src/platform_impl/macos.rs index 88a565838..6a1ddb37f 100644 --- a/packages/accesskit_xplat/src/platform_impl/macos.rs +++ b/packages/accesskit_xplat/src/platform_impl/macos.rs @@ -12,7 +12,7 @@ pub struct Adapter { impl Adapter { pub fn new( - window_handle: &RawWindowHandle, + window_handle: RawWindowHandle, activation_handler: impl 'static + ActivationHandler, action_handler: impl 'static + ActionHandler, _deactivation_handler: impl 'static + DeactivationHandler, diff --git a/packages/accesskit_xplat/src/platform_impl/unix.rs b/packages/accesskit_xplat/src/platform_impl/unix.rs index ee320e5c8..542461e95 100644 --- a/packages/accesskit_xplat/src/platform_impl/unix.rs +++ b/packages/accesskit_xplat/src/platform_impl/unix.rs @@ -12,7 +12,7 @@ pub struct Adapter { impl Adapter { pub fn new( - _window_handle: &RawWindowHandle, + _window_handle: RawWindowHandle, activation_handler: impl 'static + ActivationHandler + Send, action_handler: impl 'static + ActionHandler + Send, deactivation_handler: impl 'static + DeactivationHandler + Send, diff --git a/packages/accesskit_xplat/src/platform_impl/windows.rs b/packages/accesskit_xplat/src/platform_impl/windows.rs index 3b001dc1d..ada159bac 100644 --- a/packages/accesskit_xplat/src/platform_impl/windows.rs +++ b/packages/accesskit_xplat/src/platform_impl/windows.rs @@ -12,7 +12,7 @@ pub struct Adapter { impl Adapter { pub fn new( - window_handle: &RawWindowHandle, + window_handle: RawWindowHandle, activation_handler: impl 'static + ActivationHandler, action_handler: impl 'static + ActionHandler + Send, _deactivation_handler: impl 'static + DeactivationHandler, From 85bcda2586bb5d40c005f91fb8446b7636c1064e Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 5 Jan 2026 00:57:22 +0000 Subject: [PATCH 53/73] Fix reference to AndroidApp in null backend --- packages/accesskit_xplat/src/platform_impl/null.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/accesskit_xplat/src/platform_impl/null.rs b/packages/accesskit_xplat/src/platform_impl/null.rs index 22ffa5dd1..b3a4bb550 100644 --- a/packages/accesskit_xplat/src/platform_impl/null.rs +++ b/packages/accesskit_xplat/src/platform_impl/null.rs @@ -9,7 +9,7 @@ pub struct Adapter; impl Adapter { pub fn new( - #[cfg(target_os = "android")] _android_app: &AndroidApp, + #[cfg(target_os = "android")] _android_app: &android_activity::AndroidApp, #[cfg(not(target_os = "android"))] _window_handle: RawWindowHandle, _activation_handler: impl 'static + ActivationHandler, _action_handler: impl 'static + ActionHandler, From 14b36b3701929bbefc4a1e30047faf1a0292b6f8 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 5 Jan 2026 01:51:37 +0000 Subject: [PATCH 54/73] Fix imports in null module again Signed-off-by: Nico Burns --- packages/accesskit_xplat/src/platform_impl/null.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/accesskit_xplat/src/platform_impl/null.rs b/packages/accesskit_xplat/src/platform_impl/null.rs index b3a4bb550..b4ad34058 100644 --- a/packages/accesskit_xplat/src/platform_impl/null.rs +++ b/packages/accesskit_xplat/src/platform_impl/null.rs @@ -3,13 +3,17 @@ // the LICENSE-APACHE file). use accesskit::{ActionHandler, ActivationHandler, DeactivationHandler, Rect, TreeUpdate}; + +#[cfg(target_os = "android")] +use android_activity::AndroidApp; +#[cfg(not(target_os = "android"))] use raw_window_handle::RawWindowHandle; pub struct Adapter; impl Adapter { pub fn new( - #[cfg(target_os = "android")] _android_app: &android_activity::AndroidApp, + #[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, From 605950b5c4b488f914555f4542d2a40f7f332ada Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 5 Jan 2026 01:59:02 +0000 Subject: [PATCH 55/73] Fix blitz_shell initializing accesskit_xplat on android Signed-off-by: Nico Burns --- packages/blitz-shell/src/accessibility.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/blitz-shell/src/accessibility.rs b/packages/blitz-shell/src/accessibility.rs index ab3f6e333..dab011027 100644 --- a/packages/blitz-shell/src/accessibility.rs +++ b/packages/blitz-shell/src/accessibility.rs @@ -33,6 +33,9 @@ impl AccessibilityState { let window_id = window.id(); Self { adapter: Adapter::with_combined_handler( + #[cfg(target_os = "android")] + &crate::current_android_app(), + #[cfg(not(target_os = "android"))] window.window_handle().unwrap().as_raw(), Arc::new(Handler { window_id, proxy }), ), From 95ae097d21d68d1b8dab8ab6a99c2a5fae78c2b3 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 5 Jan 2026 02:20:08 +0000 Subject: [PATCH 56/73] Install cross with cargo install Signed-off-by: Nico Burns --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4d2610a8e..bc8af9819 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -186,9 +186,11 @@ jobs: targets: ${{ matrix.platform.target }} components: rustfmt + # Install cross from source. Because latest release doesn't work with recent Rust + # when targeting Android. See https://github.com/cross-rs/cross/issues/1222 - name: Install cross if: ${{ matrix.platform.cross == true }} - uses: taiki-e/install-action@cross + run: cargo install cross --git https://github.com/cross-rs/cross --rev 426e811 - name: Free Disk Space (Ubuntu) if: ${{ matrix.platform.os == 'ubuntu-latest' }} From 1df2991a472de2bf18cbbb2224af0354937ecb21 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 5 Jan 2026 02:30:34 +0000 Subject: [PATCH 57/73] Remove duplicate cross install Signed-off-by: Nico Burns --- .github/workflows/ci.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bc8af9819..e0ef2fae0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -213,10 +213,6 @@ jobs: 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 From e4d2d9f0d06b4ec6d05711e2856f863f37800b32 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 5 Jan 2026 02:32:01 +0000 Subject: [PATCH 58/73] Disable free disk space task Signed-off-by: Nico Burns --- .github/workflows/ci.yml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e0ef2fae0..580ef83bf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -192,13 +192,17 @@ jobs: if: ${{ matrix.platform.cross == true }} run: cargo install cross --git https://github.com/cross-rs/cross --rev 426e811 - - name: Free Disk Space (Ubuntu) - if: ${{ matrix.platform.os == 'ubuntu-latest' }} - uses: jlumbroso/free-disk-space@v1.3.1 - with: # speed things up a bit - large-packages: false - docker-images: false - swap-storage: false + # This is currently disabled as Blitz's CI doesn't need the extra disk space. + # So this task is just taking up time for no reason. We will reinstate if our + # disk space requirement increase. + # + # - name: Free Disk Space (Ubuntu) + # if: ${{ matrix.platform.os == 'ubuntu-latest' }} + # uses: jlumbroso/free-disk-space@v1.3.1 + # with: # speed things up a bit + # large-packages: false + # docker-images: false + # swap-storage: false - uses: Swatinem/rust-cache@v2 with: From 44464392f12f41a580bba9aa068c907131e31bc0 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Thu, 22 Jan 2026 13:57:12 +0000 Subject: [PATCH 59/73] Rename x/y fields of PointerEvent to page_x/page_y Signed-off-by: Nico Burns --- packages/blitz-dom/src/events/driver.rs | 4 ++-- packages/blitz-dom/src/events/mod.rs | 16 ++++++++-------- packages/blitz-dom/src/events/mouse.rs | 4 ++-- packages/blitz-dom/src/node/node.rs | 4 ++-- packages/blitz-shell/src/window.rs | 12 ++++++------ packages/blitz-traits/src/events.rs | 4 ++-- packages/dioxus-native-dom/src/events.rs | 2 +- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/packages/blitz-dom/src/events/driver.rs b/packages/blitz-dom/src/events/driver.rs index 859914c2b..1884dc258 100644 --- a/packages/blitz-dom/src/events/driver.rs +++ b/packages/blitz-dom/src/events/driver.rs @@ -46,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; - let dom_y = event.y; + let dom_x = event.page_x; + let dom_y = event.page_y; let changed = doc.set_hover_to(dom_x, dom_y); let prev_hover_node_id = hover_node_id; diff --git a/packages/blitz-dom/src/events/mod.rs b/packages/blitz-dom/src/events/mod.rs index f4d05a982..6ab7fb7fd 100644 --- a/packages/blitz-dom/src/events/mod.rs +++ b/packages/blitz-dom/src/events/mod.rs @@ -30,23 +30,23 @@ pub(crate) fn handle_dom_event( // TODO: eliminate clone let ui_event = match event.data.clone() { DomEventData::MouseMove(mut mouse_event) => { - mouse_event.x -= pos.x - viewport_scroll.x as f32; - mouse_event.y -= pos.y - viewport_scroll.y as f32; + mouse_event.page_x -= pos.x - viewport_scroll.x as f32; + mouse_event.page_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 - viewport_scroll.x as f32; - mouse_event.y -= pos.y - viewport_scroll.y as f32; + mouse_event.page_x -= pos.x - viewport_scroll.x as f32; + mouse_event.page_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 - viewport_scroll.x as f32; - mouse_event.y -= pos.y - viewport_scroll.y as f32; + mouse_event.page_x -= pos.x - viewport_scroll.x as f32; + mouse_event.page_y -= pos.y - viewport_scroll.y as f32; mouse_event.client_x -= pos.x; mouse_event.client_y -= pos.y; set_focus = true; @@ -101,8 +101,8 @@ pub(crate) fn handle_dom_event( handle_mousedown( doc, target_node_id, - event.x, - event.y, + event.page_x, + event.page_y, event.mods, &mut dispatch_event, ); diff --git a/packages/blitz-dom/src/events/mouse.rs b/packages/blitz-dom/src/events/mouse.rs index e3feba3a4..f12e9895b 100644 --- a/packages/blitz-dom/src/events/mouse.rs +++ b/packages/blitz-dom/src/events/mouse.rs @@ -27,8 +27,8 @@ pub(crate) fn handle_mousemove( event: &BlitzPointerEvent, mut dispatch_event: F, ) -> bool { - let x = event.x; - let y = event.y; + let x = event.page_x; + let y = event.page_y; let buttons = event.buttons; let mut changed = doc.set_hover_to(x, y); diff --git a/packages/blitz-dom/src/node/node.rs b/packages/blitz-dom/src/node/node.rs index 6c4c145fc..dfdee6d89 100644 --- a/packages/blitz-dom/src/node/node.rs +++ b/packages/blitz-dom/src/node/node.rs @@ -1055,8 +1055,8 @@ impl Node { BlitzPointerEvent { id: BlitzPointerId::Mouse, is_primary: true, - x, - y, + page_x: x, + page_y: y, // TODO: should these be different? screen_x: x, diff --git a/packages/blitz-shell/src/window.rs b/packages/blitz-shell/src/window.rs index f754f3715..7825c241f 100644 --- a/packages/blitz-shell/src/window.rs +++ b/packages/blitz-shell/src/window.rs @@ -427,8 +427,8 @@ impl View { let event = UiEvent::MouseMove(BlitzPointerEvent { id, is_primary: primary, - x: page_x, - y: page_y, + page_x, + page_y, screen_x, screen_y, client_x, @@ -470,8 +470,8 @@ impl View { let event = UiEvent::MouseMove(BlitzPointerEvent { id, is_primary: primary, - x: page_x, - y: page_y, + page_x, + page_y, screen_x, screen_y, client_x, @@ -486,8 +486,8 @@ impl View { let event = BlitzPointerEvent { id, is_primary: primary, - x: page_x, - y: page_y, + page_x, + page_y, screen_x, screen_y, client_x, diff --git a/packages/blitz-traits/src/events.rs b/packages/blitz-traits/src/events.rs index aa4a3c8c6..20c88a2e1 100644 --- a/packages/blitz-traits/src/events.rs +++ b/packages/blitz-traits/src/events.rs @@ -317,8 +317,8 @@ pub enum BlitzPointerId { 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 page_x: f32, + pub page_y: f32, pub screen_x: f32, pub screen_y: f32, pub client_x: f32, diff --git a/packages/dioxus-native-dom/src/events.rs b/packages/dioxus-native-dom/src/events.rs index 2a2a3bf73..654de453e 100644 --- a/packages/dioxus-native-dom/src/events.rs +++ b/packages/dioxus-native-dom/src/events.rs @@ -309,7 +309,7 @@ impl InteractionLocation for NativeClickData { } fn page_coordinates(&self) -> PagePoint { - PagePoint::new(self.0.x as f64, self.0.y as f64) + PagePoint::new(self.0.page_x as f64, self.0.page_y as f64) } } From 73767b1c0de25be6584c4f639dccaef45704b696 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Thu, 22 Jan 2026 16:22:14 +0000 Subject: [PATCH 60/73] Create dedicated struct for pointer coordinates --- packages/blitz-dom/src/document.rs | 9 ++-- packages/blitz-dom/src/events/driver.rs | 4 +- packages/blitz-dom/src/events/mod.rs | 33 ++++++------ packages/blitz-dom/src/events/mouse.rs | 16 +++--- packages/blitz-dom/src/node/node.rs | 27 +++++----- packages/blitz-shell/src/window.rs | 68 ++++++++++-------------- packages/blitz-traits/src/events.rs | 40 ++++++++++++-- packages/dioxus-native-dom/src/events.rs | 6 +-- 8 files changed, 114 insertions(+), 89 deletions(-) diff --git a/packages/blitz-dom/src/document.rs b/packages/blitz-dom/src/document.rs index 08a86b5e9..6a5faa9a3 100644 --- a/packages/blitz-dom/src/document.rs +++ b/packages/blitz-dom/src/document.rs @@ -1519,14 +1519,11 @@ impl BaseDocument { /// Computes the size and position of the `Node` relative to the viewport pub fn get_client_bounding_rect(&self, node_id: usize) -> Option { let node = self.get_node(node_id)?; - - let mut pos = node.absolute_position(0.0, 0.0).map(|v| v as f64); - pos.x -= self.viewport_scroll.x; - pos.y -= self.viewport_scroll.y; + let pos = node.absolute_position(0.0, 0.0); Some(BoundingRect { - x: pos.x, - y: pos.y, + x: pos.x as f64 - self.viewport_scroll.x, + y: pos.y as f64 - self.viewport_scroll.y, width: node.unrounded_layout.size.width as f64, height: node.unrounded_layout.size.width as f64, }) diff --git a/packages/blitz-dom/src/events/driver.rs b/packages/blitz-dom/src/events/driver.rs index 1884dc258..d840b3eff 100644 --- a/packages/blitz-dom/src/events/driver.rs +++ b/packages/blitz-dom/src/events/driver.rs @@ -46,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.page_x; - let dom_y = event.page_y; + let dom_x = event.page_x(); + let dom_y = event.page_y(); let changed = doc.set_hover_to(dom_x, dom_y); let prev_hover_node_id = hover_node_id; diff --git a/packages/blitz-dom/src/events/mod.rs b/packages/blitz-dom/src/events/mod.rs index 6ab7fb7fd..b05f4fbdb 100644 --- a/packages/blitz-dom/src/events/mod.rs +++ b/packages/blitz-dom/src/events/mod.rs @@ -4,7 +4,8 @@ mod ime; mod keyboard; mod mouse; -use blitz_traits::events::{DomEvent, DomEventData, UiEvent}; +use crate::util::Point; +use blitz_traits::events::{DomEvent, DomEventData, PointerCoords, UiEvent}; pub use driver::{EventDriver, EventHandler, NoopEventHandler}; use focus::generate_focus_events; pub(crate) use ime::handle_ime_event; @@ -14,6 +15,17 @@ pub(crate) use mouse::{handle_click, handle_mousedown, handle_mousemove}; use crate::{BaseDocument, events::mouse::handle_wheel}; +fn adjust_coords_for_subdocument( + coords: &mut PointerCoords, + offset: Point, + viewport_scroll: Point, +) { + coords.page_x -= offset.x - viewport_scroll.x as f32; + coords.page_y -= offset.y - viewport_scroll.y as f32; + coords.client_x -= offset.x; + coords.client_y -= offset.y; +} + pub(crate) fn handle_dom_event( doc: &mut BaseDocument, event: &mut DomEvent, @@ -30,25 +42,16 @@ pub(crate) fn handle_dom_event( // TODO: eliminate clone let ui_event = match event.data.clone() { DomEventData::MouseMove(mut mouse_event) => { - mouse_event.page_x -= pos.x - viewport_scroll.x as f32; - mouse_event.page_y -= pos.y - viewport_scroll.y as f32; - mouse_event.client_x -= pos.x; - mouse_event.client_y -= pos.y; + adjust_coords_for_subdocument(&mut mouse_event.coords, pos, viewport_scroll); Some(UiEvent::MouseMove(mouse_event)) } DomEventData::MouseDown(mut mouse_event) => { - mouse_event.page_x -= pos.x - viewport_scroll.x as f32; - mouse_event.page_y -= pos.y - viewport_scroll.y as f32; - mouse_event.client_x -= pos.x; - mouse_event.client_y -= pos.y; + adjust_coords_for_subdocument(&mut mouse_event.coords, pos, viewport_scroll); set_focus = true; Some(UiEvent::MouseDown(mouse_event)) } DomEventData::MouseUp(mut mouse_event) => { - mouse_event.page_x -= pos.x - viewport_scroll.x as f32; - mouse_event.page_y -= pos.y - viewport_scroll.y as f32; - mouse_event.client_x -= pos.x; - mouse_event.client_y -= pos.y; + adjust_coords_for_subdocument(&mut mouse_event.coords, pos, viewport_scroll); set_focus = true; Some(UiEvent::MouseUp(mouse_event)) } @@ -101,8 +104,8 @@ pub(crate) fn handle_dom_event( handle_mousedown( doc, target_node_id, - event.page_x, - event.page_y, + event.page_x(), + event.page_y(), event.mods, &mut dispatch_event, ); diff --git a/packages/blitz-dom/src/events/mouse.rs b/packages/blitz-dom/src/events/mouse.rs index f12e9895b..f2182169b 100644 --- a/packages/blitz-dom/src/events/mouse.rs +++ b/packages/blitz-dom/src/events/mouse.rs @@ -27,8 +27,8 @@ pub(crate) fn handle_mousemove( event: &BlitzPointerEvent, mut dispatch_event: F, ) -> bool { - let x = event.page_x; - let y = event.page_y; + let x = event.page_x(); + let y = event.page_y(); let buttons = event.buttons; let mut changed = doc.set_hover_to(x, y); @@ -45,8 +45,8 @@ pub(crate) fn handle_mousemove( BlitzPointerId::Finger(_) => { doc.drag_mode = DragMode::Panning(PanState { target, - last_x: event.screen_x, - last_y: event.screen_y, + last_x: event.screen_x(), + last_y: event.screen_y(), samples: VecDeque::with_capacity(200), }); } @@ -55,16 +55,16 @@ pub(crate) fn handle_mousemove( } 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 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.last_x = event.screen_x(); + state.last_y = event.screen_y(); state.samples.push_back(PanSample { time: time_ms, diff --git a/packages/blitz-dom/src/node/node.rs b/packages/blitz-dom/src/node/node.rs index dfdee6d89..875592ebc 100644 --- a/packages/blitz-dom/src/node/node.rs +++ b/packages/blitz-dom/src/node/node.rs @@ -1,6 +1,8 @@ use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut}; use bitflags::bitflags; -use blitz_traits::events::{BlitzPointerEvent, BlitzPointerId, DomEventData, HitResult}; +use blitz_traits::events::{ + BlitzPointerEvent, BlitzPointerId, DomEventData, HitResult, PointerCoords, +}; use blitz_traits::shell::ShellProvider; use html_escape::encode_quoted_attribute_to_string; use keyboard_types::Modifiers; @@ -1031,7 +1033,7 @@ impl Node { } /// Computes the Document-relative coordinates of the `Node` - pub fn absolute_position(&self, x: f32, y: f32) -> taffy::Point { + pub fn absolute_position(&self, x: f32, y: f32) -> crate::util::Point { let x = x + self.final_layout.location.x - self.scroll_offset.x as f32; let y = y + self.final_layout.location.y - self.scroll_offset.y as f32; @@ -1039,7 +1041,7 @@ impl Node { self.layout_parent .get() .map(|i| self.with(i).absolute_position(x, y)) - .unwrap_or(taffy::Point { x, y }) + .unwrap_or(crate::util::Point { x, y }) } /// Creates a synthetic click event @@ -1055,15 +1057,16 @@ impl Node { BlitzPointerEvent { id: BlitzPointerId::Mouse, is_primary: true, - page_x: x, - page_y: y, - - // TODO: should these be different? - screen_x: x, - screen_y: y, - client_x: x, - client_y: y, - + coords: PointerCoords { + page_x: x, + page_y: 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-shell/src/window.rs b/packages/blitz-shell/src/window.rs index 7825c241f..ce5a49844 100644 --- a/packages/blitz-shell/src/window.rs +++ b/packages/blitz-shell/src/window.rs @@ -9,10 +9,10 @@ use blitz_dom::Document; use blitz_paint::paint_scene; use blitz_traits::events::{ BlitzPointerEvent, BlitzPointerId, BlitzWheelDelta, BlitzWheelEvent, MouseEventButton, - MouseEventButtons, UiEvent, + MouseEventButtons, PointerCoords, UiEvent, }; use blitz_traits::shell::Viewport; -use winit::dpi::{LogicalPosition, PhysicalInsets}; +use winit::dpi::{LogicalPosition, PhysicalInsets, PhysicalPosition}; use winit::keyboard::PhysicalKey; use std::any::Any; @@ -278,6 +278,28 @@ impl View { } } + pub fn pointer_coords(&self, position: PhysicalPosition) -> PointerCoords { + 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; + + PointerCoords { + screen_x, + screen_y, + client_x, + client_y, + page_x, + page_y, + } + } + pub fn window_id(&self) -> WindowId { self.window.id() } @@ -414,25 +436,10 @@ impl View { 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, + id: pointer_source_to_blitz(&source), is_primary: primary, - page_x, - page_y, - screen_x, - screen_y, - client_x, - client_y, + coords: self.pointer_coords(position), button: Default::default(), buttons: self.buttons, mods: winit_modifiers_to_kbt_modifiers(self.keyboard_modifiers.state()), @@ -441,6 +448,7 @@ impl View { } WindowEvent::PointerButton { button, state, primary, position, .. } => { let id = button_source_to_blitz(&button); + let coords = self.pointer_coords(position); let button = match &button { ButtonSource::Mouse(mouse_button) => match mouse_button { MouseButton::Left => MouseEventButton::Main, @@ -458,24 +466,11 @@ impl View { ElementState::Released => self.buttons ^= button.into(), } - 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, - page_x, - page_y, - screen_x, - screen_y, - client_x, - client_y, + coords, button: Default::default(), buttons: self.buttons, mods: winit_modifiers_to_kbt_modifiers(self.keyboard_modifiers.state()), @@ -486,12 +481,7 @@ impl View { let event = BlitzPointerEvent { id, is_primary: primary, - page_x, - page_y, - screen_x, - screen_y, - client_x, - client_y, + coords, button, buttons: self.buttons, mods: winit_modifiers_to_kbt_modifiers(self.keyboard_modifiers.state()), diff --git a/packages/blitz-traits/src/events.rs b/packages/blitz-traits/src/events.rs index 20c88a2e1..f7c42a6eb 100644 --- a/packages/blitz-traits/src/events.rs +++ b/packages/blitz-traits/src/events.rs @@ -313,21 +313,53 @@ pub enum BlitzPointerId { Finger(u64), } -#[derive(Clone, Debug)] -pub struct BlitzPointerEvent { - pub id: BlitzPointerId, - pub is_primary: bool, +#[derive(Copy, Clone, Debug)] +pub struct PointerCoords { pub page_x: f32, pub page_y: f32, pub screen_x: f32, pub screen_y: f32, pub client_x: f32, pub client_y: f32, +} + +#[derive(Clone, Debug)] +pub struct BlitzPointerEvent { + pub id: BlitzPointerId, + pub is_primary: bool, + pub coords: PointerCoords, pub button: MouseEventButton, pub buttons: MouseEventButtons, pub mods: Modifiers, } +impl BlitzPointerEvent { + #[inline(always)] + pub fn page_x(&self) -> f32 { + self.coords.page_x + } + #[inline(always)] + pub fn page_y(&self) -> f32 { + self.coords.page_y + } + #[inline(always)] + pub fn client_x(&self) -> f32 { + self.coords.client_x + } + #[inline(always)] + pub fn client_y(&self) -> f32 { + self.coords.client_y + } + #[inline(always)] + pub fn screen_x(&self) -> f32 { + self.coords.screen_x + } + #[inline(always)] + pub fn screen_y(&self) -> f32 { + self.coords.screen_y + } +} + #[derive(Clone, Debug)] pub struct BlitzWheelEvent { pub delta: BlitzWheelDelta, diff --git a/packages/dioxus-native-dom/src/events.rs b/packages/dioxus-native-dom/src/events.rs index 654de453e..d05259b5a 100644 --- a/packages/dioxus-native-dom/src/events.rs +++ b/packages/dioxus-native-dom/src/events.rs @@ -301,15 +301,15 @@ pub struct NativeClickData(pub(crate) BlitzPointerEvent); impl InteractionLocation for NativeClickData { fn client_coordinates(&self) -> ClientPoint { - ClientPoint::new(self.0.client_x as f64, self.0.client_y as f64) + ClientPoint::new(self.0.client_x() as f64, self.0.client_y() as f64) } fn screen_coordinates(&self) -> ScreenPoint { - ScreenPoint::new(self.0.screen_x as f64, self.0.screen_y as f64) + ScreenPoint::new(self.0.screen_x() as f64, self.0.screen_y() as f64) } fn page_coordinates(&self) -> PagePoint { - PagePoint::new(self.0.page_x as f64, self.0.page_y as f64) + PagePoint::new(self.0.page_x() as f64, self.0.page_y() as f64) } } From 376025b7be660d6a3f6044ac6220dec5216cea6c Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Thu, 22 Jan 2026 16:28:36 +0000 Subject: [PATCH 61/73] Add full pointer coordinates to wheel events Signed-off-by: Nico Burns --- packages/blitz-shell/src/window.rs | 10 +++---- packages/blitz-traits/src/events.rs | 38 ++++++++++++++++++++---- packages/dioxus-native-dom/src/events.rs | 6 ++-- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/packages/blitz-shell/src/window.rs b/packages/blitz-shell/src/window.rs index ce5a49844..a08eb1f7f 100644 --- a/packages/blitz-shell/src/window.rs +++ b/packages/blitz-shell/src/window.rs @@ -65,7 +65,7 @@ pub struct View { pub theme_override: Option, pub keyboard_modifiers: Modifiers, pub buttons: MouseEventButtons, - pub mouse_pos: (f32, f32), + pub pointer_pos: PhysicalPosition, pub animation_timer: Option, pub is_visible: bool, pub safe_area_insets: PhysicalInsets, @@ -129,7 +129,7 @@ impl View { theme_override: None, buttons: MouseEventButtons::None, safe_area_insets, - mouse_pos: Default::default(), + pointer_pos: Default::default(), is_visible: winit_window.is_visible().unwrap_or(true), #[cfg(feature = "accessibility")] accessibility: AccessibilityState::new(&*winit_window, proxy.clone()), @@ -436,6 +436,7 @@ impl View { WindowEvent::PointerEntered { /*device_id*/.. } => {} WindowEvent::PointerLeft { /*device_id*/.. } => {} WindowEvent::PointerMoved { position, source, primary, .. } => { + self.pointer_pos = position; let event = UiEvent::MouseMove(BlitzPointerEvent { id: pointer_source_to_blitz(&source), is_primary: primary, @@ -449,6 +450,7 @@ impl View { WindowEvent::PointerButton { button, state, primary, position, .. } => { let id = button_source_to_blitz(&button); let coords = self.pointer_coords(position); + self.pointer_pos = position; let button = match &button { ButtonSource::Mouse(mouse_button) => match mouse_button { MouseButton::Left => MouseEventButton::Main, @@ -458,7 +460,6 @@ impl View { _ => MouseEventButton::Auxiliary, } _ => MouseEventButton::Main, - }; match state { @@ -503,8 +504,7 @@ impl View { let event = BlitzWheelEvent { delta: blitz_delta, - x: self.mouse_pos.0, - y: self.mouse_pos.1, + coords: self.pointer_coords(self.pointer_pos), buttons: self.buttons, mods: winit_modifiers_to_kbt_modifiers(self.keyboard_modifiers.state()), }; diff --git a/packages/blitz-traits/src/events.rs b/packages/blitz-traits/src/events.rs index f7c42a6eb..29084b26f 100644 --- a/packages/blitz-traits/src/events.rs +++ b/packages/blitz-traits/src/events.rs @@ -360,19 +360,45 @@ impl BlitzPointerEvent { } } +#[derive(Clone, Debug)] +pub enum BlitzWheelDelta { + Lines(f64, f64), + Pixels(f64, f64), +} + #[derive(Clone, Debug)] pub struct BlitzWheelEvent { pub delta: BlitzWheelDelta, - pub x: f32, - pub y: f32, + pub coords: PointerCoords, pub buttons: MouseEventButtons, pub mods: Modifiers, } -#[derive(Clone, Debug)] -pub enum BlitzWheelDelta { - Lines(f64, f64), - Pixels(f64, f64), +impl BlitzWheelEvent { + #[inline(always)] + pub fn page_x(&self) -> f32 { + self.coords.page_x + } + #[inline(always)] + pub fn page_y(&self) -> f32 { + self.coords.page_y + } + #[inline(always)] + pub fn client_x(&self) -> f32 { + self.coords.client_x + } + #[inline(always)] + pub fn client_y(&self) -> f32 { + self.coords.client_y + } + #[inline(always)] + pub fn screen_x(&self) -> f32 { + self.coords.screen_x + } + #[inline(always)] + pub fn screen_y(&self) -> f32 { + self.coords.screen_y + } } #[derive(Clone, Debug)] diff --git a/packages/dioxus-native-dom/src/events.rs b/packages/dioxus-native-dom/src/events.rs index d05259b5a..2ed7de4de 100644 --- a/packages/dioxus-native-dom/src/events.rs +++ b/packages/dioxus-native-dom/src/events.rs @@ -435,14 +435,14 @@ impl InteractionElementOffset for NativeWheelData { impl InteractionLocation for NativeWheelData { 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) } 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.page_x() as f64, self.0.page_y() as f64) } } From 460134a55cb31b6fda9914b4d8dddef932a67b87 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Thu, 22 Jan 2026 16:29:40 +0000 Subject: [PATCH 62/73] Return (0.0, 0.0) from element_coordinates instead of panicking Signed-off-by: Nico Burns --- packages/dioxus-native-dom/src/events.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/dioxus-native-dom/src/events.rs b/packages/dioxus-native-dom/src/events.rs index 2ed7de4de..b6da4ba95 100644 --- a/packages/dioxus-native-dom/src/events.rs +++ b/packages/dioxus-native-dom/src/events.rs @@ -315,7 +315,8 @@ impl InteractionLocation for NativeClickData { impl InteractionElementOffset for NativeClickData { fn element_coordinates(&self) -> ElementPoint { - unimplemented!() + // TODO: implement element point + ElementPoint::new(0.0, 0.0) } } @@ -429,7 +430,8 @@ impl ModifiersInteraction for NativeWheelData { impl InteractionElementOffset for NativeWheelData { fn element_coordinates(&self) -> ElementPoint { - unimplemented!() + // TODO: implement element point + ElementPoint::new(0.0, 0.0) } } From 366f0a6bf56f40be8b82eb95f09c486a32e2911f Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Thu, 22 Jan 2026 17:36:02 +0000 Subject: [PATCH 63/73] Improve hover/mouseover behavior on mobile - Update hover position on pointer up/down - Clear hover on pointer up when pointer is a finger --- packages/blitz-dom/src/document.rs | 23 ++++ packages/blitz-dom/src/events/driver.rs | 165 +++++++++++++----------- 2 files changed, 114 insertions(+), 74 deletions(-) diff --git a/packages/blitz-dom/src/document.rs b/packages/blitz-dom/src/document.rs index 6a5faa9a3..48fa6c7e3 100644 --- a/packages/blitz-dom/src/document.rs +++ b/packages/blitz-dom/src/document.rs @@ -1244,6 +1244,29 @@ impl BaseDocument { true } + pub fn clear_hover(&mut self) -> bool { + let Some(hover_node_id) = self.hover_node_id else { + return false; + }; + + let old_node_path = self.maybe_node_layout_ancestors(Some(hover_node_id)); + for &id in old_node_path.iter() { + self.snapshot_node_and(id, |node| node.unhover()); + } + + self.hover_node_id = None; + self.hover_node_is_text = false; + + // Update the cursor + let cursor = self.get_cursor().unwrap_or_default(); + self.shell_provider.set_cursor(cursor); + + // Request redraw + self.shell_provider.request_redraw(); + + true + } + pub fn get_hover_node_id(&self) -> Option { self.hover_node_id } diff --git a/packages/blitz-dom/src/events/driver.rs b/packages/blitz-dom/src/events/driver.rs index d840b3eff..ef5b63d67 100644 --- a/packages/blitz-dom/src/events/driver.rs +++ b/packages/blitz-dom/src/events/driver.rs @@ -1,5 +1,7 @@ use crate::Document; -use blitz_traits::events::{DomEvent, DomEventData, EventState, UiEvent}; +use blitz_traits::events::{ + BlitzPointerEvent, BlitzPointerId, DomEvent, DomEventData, EventState, UiEvent, +}; use std::collections::VecDeque; pub trait EventHandler { @@ -35,9 +37,83 @@ impl<'doc, Handler: EventHandler> EventDriver<'doc, Handler> { EventDriver { doc, handler } } + pub fn handle_pointer_move(&mut self, event: &BlitzPointerEvent) -> Option { + let mut doc = self.doc.inner_mut(); + + let prev_hover_node_id = doc.hover_node_id; + let changed = doc.set_hover_to(event.page_x(), event.page_y()); + let hover_node_id = doc.hover_node_id; + + drop(doc); + + if !changed { + return prev_hover_node_id; + } + + let doc = self.doc.inner(); + let mut old_chain = prev_hover_node_id + .map(|id| doc.node_chain(id)) + .unwrap_or_default(); + let mut new_chain = hover_node_id + .map(|id| doc.node_chain(id)) + .unwrap_or_default(); + old_chain.reverse(); + new_chain.reverse(); + + // Find the difference in the node chain of the last hovered objected and the newest + let old_len = old_chain.len(); + let new_len = new_chain.len(); + + let first_difference_index = old_chain + .iter() + .zip(&new_chain) + .position(|(old, new)| old != new) + .unwrap_or_else(|| old_len.min(new_len)); + + drop(doc); + + if let Some(target) = prev_hover_node_id { + self.handle_dom_event(DomEvent::new(target, DomEventData::MouseOut(event.clone()))); + + // Send an mouseleave event to all old elements on the chain + for node_id in old_chain + .get(first_difference_index..) + .unwrap_or(&[]) + .iter() + { + self.handle_dom_event(DomEvent::new( + *node_id, + DomEventData::MouseLeave(event.clone()), + )); + } + } + + if let Some(target) = hover_node_id { + self.handle_dom_event(DomEvent::new( + target, + DomEventData::MouseOver(event.clone()), + )); + + // Send an mouseenter event to all new elements on the chain + for node_id in new_chain + .get(first_difference_index..) + .unwrap_or(&[]) + .iter() + { + self.handle_dom_event(DomEvent::new( + *node_id, + DomEventData::MouseEnter(event.clone()), + )); + } + } + + hover_node_id + } + pub fn handle_ui_event(&mut self, event: UiEvent) { let doc = self.doc.inner(); + let mut should_clear_hover = false; let mut hover_node_id = doc.hover_node_id; let focussed_node_id = doc.focus_node_id; drop(doc); @@ -45,86 +121,22 @@ impl<'doc, Handler: EventHandler> EventDriver<'doc, Handler> { // Update document input state (hover, focus, active, etc) match &event { UiEvent::MouseMove(event) => { - let mut doc = self.doc.inner_mut(); - let dom_x = event.page_x(); - let dom_y = event.page_y(); - let changed = doc.set_hover_to(dom_x, dom_y); - - let prev_hover_node_id = hover_node_id; - hover_node_id = doc.hover_node_id; - - drop(doc); - - if changed { - let doc = self.doc.inner(); - let mut old_chain = prev_hover_node_id - .map(|id| doc.node_chain(id)) - .unwrap_or_default(); - let mut new_chain = hover_node_id - .map(|id| doc.node_chain(id)) - .unwrap_or_default(); - old_chain.reverse(); - new_chain.reverse(); - - // Find the difference in the node chain of the last hovered objected and the newest - let old_len = old_chain.len(); - let new_len = new_chain.len(); - - let first_difference_index = old_chain - .iter() - .zip(&new_chain) - .position(|(old, new)| old != new) - .unwrap_or_else(|| old_len.min(new_len)); - - drop(doc); - - if let Some(target) = prev_hover_node_id { - self.handle_dom_event(DomEvent::new( - target, - DomEventData::MouseOut(event.clone()), - )); - - // Send an mouseleave event to all old elements on the chain - for node_id in old_chain - .get(first_difference_index..) - .unwrap_or(&[]) - .iter() - { - self.handle_dom_event(DomEvent::new( - *node_id, - DomEventData::MouseLeave(event.clone()), - )); - } - } - - if let Some(target) = hover_node_id { - self.handle_dom_event(DomEvent::new( - target, - DomEventData::MouseOver(event.clone()), - )); - - // Send an mouseenter event to all new elements on the chain - for node_id in new_chain - .get(first_difference_index..) - .unwrap_or(&[]) - .iter() - { - self.handle_dom_event(DomEvent::new( - *node_id, - DomEventData::MouseEnter(event.clone()), - )); - } - } - } + hover_node_id = self.handle_pointer_move(event); } - UiEvent::MouseDown(_) => { + UiEvent::MouseDown(event) => { + hover_node_id = self.handle_pointer_move(event); let mut doc = self.doc.inner_mut(); doc.active_node(); doc.set_mousedown_node_id(hover_node_id); } - UiEvent::MouseUp(_) => { + UiEvent::MouseUp(event) => { + hover_node_id = self.handle_pointer_move(event); let mut doc = self.doc.inner_mut(); doc.unactive_node(); + + if event.is_primary && matches!(event.id, BlitzPointerId::Finger(_)) { + should_clear_hover = true; + } } _ => {} }; @@ -153,6 +165,11 @@ impl<'doc, Handler: EventHandler> EventDriver<'doc, Handler> { let dom_event = DomEvent::new(target, data); self.handle_dom_event(dom_event); + + // Update document input state (hover, focus, active, etc) + if should_clear_hover { + self.doc.inner_mut().clear_hover(); + } } pub fn handle_dom_event(&mut self, event: DomEvent) { From fc37fab1337b6db153965588e36892cf4a852ccc Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Thu, 22 Jan 2026 17:48:26 +0000 Subject: [PATCH 64/73] Refactor pan/fling support Signed-off-by: Nico Burns --- packages/blitz-dom/src/document.rs | 49 +----- packages/blitz-dom/src/events/mod.rs | 4 +- packages/blitz-dom/src/events/mouse.rs | 197 ++++++++++++++++--------- packages/blitz-dom/src/resolve.rs | 2 +- 4 files changed, 132 insertions(+), 120 deletions(-) diff --git a/packages/blitz-dom/src/document.rs b/packages/blitz-dom/src/document.rs index 48fa6c7e3..c26f84667 100644 --- a/packages/blitz-dom/src/document.rs +++ b/packages/blitz-dom/src/document.rs @@ -1,4 +1,4 @@ -use crate::events::handle_dom_event; +use crate::events::{DragMode, ScrollAnimationState, handle_dom_event}; use crate::font_metrics::BlitzFontMetricsProvider; use crate::layout::construct::ConstructionTask; use crate::layout::damage::ALL_DAMAGE; @@ -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, VecDeque}; +use std::collections::{BTreeMap, Bound, HashMap, HashSet}; use std::ops::{Deref, DerefMut}; use std::rc::Rc; use std::str::FromStr; @@ -174,51 +174,6 @@ 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, diff --git a/packages/blitz-dom/src/events/mod.rs b/packages/blitz-dom/src/events/mod.rs index b05f4fbdb..668e14278 100644 --- a/packages/blitz-dom/src/events/mod.rs +++ b/packages/blitz-dom/src/events/mod.rs @@ -11,7 +11,9 @@ use focus::generate_focus_events; pub(crate) use ime::handle_ime_event; pub(crate) use keyboard::handle_keypress; use mouse::handle_mouseup; -pub(crate) use mouse::{handle_click, handle_mousedown, handle_mousemove}; +pub(crate) use mouse::{ + DragMode, ScrollAnimationState, handle_click, handle_mousedown, handle_mousemove, +}; use crate::{BaseDocument, events::mouse::handle_wheel}; diff --git a/packages/blitz-dom/src/events/mouse.rs b/packages/blitz-dom/src/events/mouse.rs index f2182169b..3bc47f799 100644 --- a/packages/blitz-dom/src/events/mouse.rs +++ b/packages/blitz-dom/src/events/mouse.rs @@ -13,14 +13,131 @@ use blitz_traits::{ use keyboard_types::Modifiers; use markup5ever::local_name; -use crate::{ - BaseDocument, - document::{DragMode, FlingState, PanSample, PanState, ScrollAnimationState}, - node::SpecialElementData, -}; +use crate::{BaseDocument, node::SpecialElementData}; use super::focus::generate_focus_events; +#[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) + } +} + +impl PanState { + fn update(&mut self, time_ms: u64, screen_x: f32, screen_y: f32) -> (f64, f64) { + let dx = (screen_x - self.last_x) as f64; + let dy = (screen_y - self.last_y) as f64; + self.last_x = screen_x; + self.last_y = screen_y; + + self.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 self.samples.len() > 50 && time_ms - self.samples.front().unwrap().time > 100 { + let idx = self + .samples + .partition_point(|sample| time_ms - sample.time > 100); + // FIXME: use truncate_front once stable + for _ in 0..idx { + self.samples.pop_front(); + } + } + + (dx, dy) + } + + fn generate_fling(&self, time_ms: u64) -> Option { + // Generate "fling" + if let Some(last_sample) = self.samples.back() + && time_ms - last_sample.time < 100 + { + let idx = self + .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 = self.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) = self + .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 + }; + + return Some(FlingState { + target: self.target, + last_seen_time: time_ms as f64, + x_velocity: x_velocity as f64 * 2.0, + y_velocity: y_velocity as f64 * 2.0, + }); + } + } + + None + } +} + pub(crate) fn handle_mousemove( doc: &mut BaseDocument, target: usize, @@ -55,34 +172,13 @@ pub(crate) fn handle_mousemove( } 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 (dx, dy) = state.update(time_ms, event.screen_x(), event.screen_y()); let has_changed = doc.scroll_by(Some(target), dx, dy, &mut dispatch_event); return has_changed; @@ -312,50 +408,9 @@ pub(crate) fn handle_mouseup( .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 - }; - - 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(); - } + if let Some(fling) = state.generate_fling(time_ms) { + doc.scroll_animation = ScrollAnimationState::Fling(fling); + doc.shell_provider.request_redraw(); } } diff --git a/packages/blitz-dom/src/resolve.rs b/packages/blitz-dom/src/resolve.rs index ff001ff7e..374d0d26a 100644 --- a/packages/blitz-dom/src/resolve.rs +++ b/packages/blitz-dom/src/resolve.rs @@ -25,7 +25,7 @@ use taffy::AvailableSpace; use crate::{ BaseDocument, NON_INCREMENTAL, - document::ScrollAnimationState, + events::ScrollAnimationState, layout::{ construct::{ ConstructionTask, ConstructionTaskData, ConstructionTaskResult, From 23968cdff2e4bc3081776a23af9bd1c2c06d6e09 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Thu, 22 Jan 2026 17:59:16 +0000 Subject: [PATCH 65/73] Rename mouse module to pointer Signed-off-by: Nico Burns --- packages/blitz-dom/src/events/mod.rs | 30 +++++++++---------- .../src/events/{mouse.rs => pointer.rs} | 0 2 files changed, 15 insertions(+), 15 deletions(-) rename packages/blitz-dom/src/events/{mouse.rs => pointer.rs} (100%) diff --git a/packages/blitz-dom/src/events/mod.rs b/packages/blitz-dom/src/events/mod.rs index 668e14278..0d61ed0de 100644 --- a/packages/blitz-dom/src/events/mod.rs +++ b/packages/blitz-dom/src/events/mod.rs @@ -2,7 +2,7 @@ mod driver; mod focus; mod ime; mod keyboard; -mod mouse; +mod pointer; use crate::util::Point; use blitz_traits::events::{DomEvent, DomEventData, PointerCoords, UiEvent}; @@ -10,12 +10,12 @@ pub use driver::{EventDriver, EventHandler, NoopEventHandler}; use focus::generate_focus_events; pub(crate) use ime::handle_ime_event; pub(crate) use keyboard::handle_keypress; -use mouse::handle_mouseup; -pub(crate) use mouse::{ +use pointer::handle_mouseup; +pub(crate) use pointer::{ DragMode, ScrollAnimationState, handle_click, handle_mousedown, handle_mousemove, }; -use crate::{BaseDocument, events::mouse::handle_wheel}; +use crate::{BaseDocument, events::pointer::handle_wheel}; fn adjust_coords_for_subdocument( coords: &mut PointerCoords, @@ -43,19 +43,19 @@ pub(crate) fn handle_dom_event( let viewport_scroll = sub_doc.inner().viewport_scroll(); // TODO: eliminate clone let ui_event = match event.data.clone() { - DomEventData::MouseMove(mut mouse_event) => { - adjust_coords_for_subdocument(&mut mouse_event.coords, pos, viewport_scroll); - Some(UiEvent::MouseMove(mouse_event)) + DomEventData::MouseMove(mut event) => { + adjust_coords_for_subdocument(&mut event.coords, pos, viewport_scroll); + Some(UiEvent::MouseMove(event)) } - DomEventData::MouseDown(mut mouse_event) => { - adjust_coords_for_subdocument(&mut mouse_event.coords, pos, viewport_scroll); + DomEventData::MouseDown(mut event) => { + adjust_coords_for_subdocument(&mut event.coords, pos, viewport_scroll); set_focus = true; - Some(UiEvent::MouseDown(mouse_event)) + Some(UiEvent::MouseDown(event)) } - DomEventData::MouseUp(mut mouse_event) => { - adjust_coords_for_subdocument(&mut mouse_event.coords, pos, viewport_scroll); + DomEventData::MouseUp(mut event) => { + adjust_coords_for_subdocument(&mut event.coords, pos, viewport_scroll); set_focus = true; - Some(UiEvent::MouseUp(mouse_event)) + Some(UiEvent::MouseUp(event)) } DomEventData::MouseEnter(_) => None, DomEventData::MouseLeave(_) => None, @@ -96,8 +96,8 @@ pub(crate) fn handle_dom_event( } match &event.data { - DomEventData::MouseMove(mouse_event) => { - let changed = handle_mousemove(doc, target_node_id, mouse_event, dispatch_event); + DomEventData::MouseMove(event) => { + let changed = handle_mousemove(doc, target_node_id, 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/pointer.rs similarity index 100% rename from packages/blitz-dom/src/events/mouse.rs rename to packages/blitz-dom/src/events/pointer.rs From 3ee51e19f8f7c356457d2110eefb3751b4868ecc Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Thu, 22 Jan 2026 18:05:51 +0000 Subject: [PATCH 66/73] Rename UiEvent mouse events to pointer Signed-off-by: Nico Burns --- packages/blitz-dom/src/events/driver.rs | 18 +++++++++--------- packages/blitz-dom/src/events/mod.rs | 6 +++--- packages/blitz-shell/src/window.rs | 8 ++++---- packages/blitz-traits/src/events.rs | 6 +++--- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/packages/blitz-dom/src/events/driver.rs b/packages/blitz-dom/src/events/driver.rs index ef5b63d67..3f8f7d159 100644 --- a/packages/blitz-dom/src/events/driver.rs +++ b/packages/blitz-dom/src/events/driver.rs @@ -120,16 +120,16 @@ impl<'doc, Handler: EventHandler> EventDriver<'doc, Handler> { // Update document input state (hover, focus, active, etc) match &event { - UiEvent::MouseMove(event) => { + UiEvent::PointerMove(event) => { hover_node_id = self.handle_pointer_move(event); } - UiEvent::MouseDown(event) => { + UiEvent::PointerDown(event) => { hover_node_id = self.handle_pointer_move(event); let mut doc = self.doc.inner_mut(); doc.active_node(); doc.set_mousedown_node_id(hover_node_id); } - UiEvent::MouseUp(event) => { + UiEvent::PointerUp(event) => { hover_node_id = self.handle_pointer_move(event); let mut doc = self.doc.inner_mut(); doc.unactive_node(); @@ -142,9 +142,9 @@ impl<'doc, Handler: EventHandler> EventDriver<'doc, Handler> { }; let target = match event { - UiEvent::MouseMove(_) => hover_node_id, - UiEvent::MouseUp(_) => hover_node_id, - UiEvent::MouseDown(_) => hover_node_id, + UiEvent::PointerMove(_) => hover_node_id, + UiEvent::PointerUp(_) => hover_node_id, + UiEvent::PointerDown(_) => hover_node_id, UiEvent::Wheel(_) => hover_node_id, UiEvent::KeyUp(_) => focussed_node_id, UiEvent::KeyDown(_) => focussed_node_id, @@ -152,9 +152,9 @@ impl<'doc, Handler: EventHandler> EventDriver<'doc, Handler> { }; let data = match event { - UiEvent::MouseMove(data) => DomEventData::MouseMove(data), - UiEvent::MouseUp(data) => DomEventData::MouseUp(data), - UiEvent::MouseDown(data) => DomEventData::MouseDown(data), + UiEvent::PointerMove(data) => DomEventData::MouseMove(data), + UiEvent::PointerUp(data) => DomEventData::MouseUp(data), + UiEvent::PointerDown(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/mod.rs b/packages/blitz-dom/src/events/mod.rs index 0d61ed0de..ef2481cce 100644 --- a/packages/blitz-dom/src/events/mod.rs +++ b/packages/blitz-dom/src/events/mod.rs @@ -45,17 +45,17 @@ pub(crate) fn handle_dom_event( let ui_event = match event.data.clone() { DomEventData::MouseMove(mut event) => { adjust_coords_for_subdocument(&mut event.coords, pos, viewport_scroll); - Some(UiEvent::MouseMove(event)) + Some(UiEvent::PointerMove(event)) } DomEventData::MouseDown(mut event) => { adjust_coords_for_subdocument(&mut event.coords, pos, viewport_scroll); set_focus = true; - Some(UiEvent::MouseDown(event)) + Some(UiEvent::PointerDown(event)) } DomEventData::MouseUp(mut event) => { adjust_coords_for_subdocument(&mut event.coords, pos, viewport_scroll); set_focus = true; - Some(UiEvent::MouseUp(event)) + Some(UiEvent::PointerUp(event)) } DomEventData::MouseEnter(_) => None, DomEventData::MouseLeave(_) => None, diff --git a/packages/blitz-shell/src/window.rs b/packages/blitz-shell/src/window.rs index a08eb1f7f..c37bda735 100644 --- a/packages/blitz-shell/src/window.rs +++ b/packages/blitz-shell/src/window.rs @@ -437,7 +437,7 @@ impl View { WindowEvent::PointerLeft { /*device_id*/.. } => {} WindowEvent::PointerMoved { position, source, primary, .. } => { self.pointer_pos = position; - let event = UiEvent::MouseMove(BlitzPointerEvent { + let event = UiEvent::PointerMove(BlitzPointerEvent { id: pointer_source_to_blitz(&source), is_primary: primary, coords: self.pointer_coords(position), @@ -468,7 +468,7 @@ impl View { } if id != BlitzPointerId::Mouse { - let event = UiEvent::MouseMove(BlitzPointerEvent { + let event = UiEvent::PointerMove(BlitzPointerEvent { id, is_primary: primary, coords, @@ -489,8 +489,8 @@ impl View { }; let event = match state { - ElementState::Pressed => UiEvent::MouseDown(event), - ElementState::Released => UiEvent::MouseUp(event), + ElementState::Pressed => UiEvent::PointerDown(event), + ElementState::Released => UiEvent::PointerUp(event), }; self.doc.handle_ui_event(event); diff --git a/packages/blitz-traits/src/events.rs b/packages/blitz-traits/src/events.rs index 29084b26f..0ee1d2fb4 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(BlitzPointerEvent), - MouseUp(BlitzPointerEvent), - MouseDown(BlitzPointerEvent), + PointerMove(BlitzPointerEvent), + PointerUp(BlitzPointerEvent), + PointerDown(BlitzPointerEvent), Wheel(BlitzWheelEvent), KeyUp(BlitzKeyEvent), KeyDown(BlitzKeyEvent), From ad2c038e5ec58ca41b564e5d93e89cc5b78cc86e Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Thu, 22 Jan 2026 18:25:25 +0000 Subject: [PATCH 67/73] Upgrade to AccessKit 0.23 Signed-off-by: Nico Burns --- Cargo.lock | 31 ++++++++++++++----------- Cargo.toml | 2 +- packages/accesskit_xplat/Cargo.toml | 10 ++++---- packages/blitz-dom/src/accessibility.rs | 3 ++- 4 files changed, 25 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7bf46ee9f..1dabed5e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,15 +20,18 @@ checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" [[package]] name = "accesskit" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eca13c82f9a5cd813120b2e9b6a5d10532c6e4cd140c295cebd1f770095c8a5" +checksum = "0467c58e646d849edd7fe043d6711b8ad58f27a39a5f33886f1f2ca9852e8259" +dependencies = [ + "uuid", +] [[package]] name = "accesskit_android" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d28b60a573c7165b1eb346d66c14e85a1f7923fe2e71e396ce936ca6afb519ae" +checksum = "4c8a5259ed376f659c26f18bb2ab3e1069d25a2f74f9d7472f6c768b2f4b799d" dependencies = [ "accesskit", "accesskit_consumer", @@ -38,9 +41,9 @@ dependencies = [ [[package]] name = "accesskit_atspi_common" -version = "0.15.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb9cc46b7fb6987c4f891f0301b230b29d9e69b4854f060a0cf41fbc407ab77" +checksum = "c6778622dca77b55464f993289ffa9c2f192976e5891c2c30e2439af61b6ddf2" dependencies = [ "accesskit", "accesskit_consumer", @@ -51,9 +54,9 @@ dependencies = [ [[package]] name = "accesskit_consumer" -version = "0.32.0" +version = "0.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d880a613f29621c90e801feec40f5dd61d837d7e20bf9b67676d45e7364a36" +checksum = "6fce4cd9f6ea13c76d53403ff1583163f7a9e58381ecfbf4c8449affd7c09c24" dependencies = [ "accesskit", "hashbrown 0.16.1", @@ -61,9 +64,9 @@ dependencies = [ [[package]] name = "accesskit_macos" -version = "0.23.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0ddfc3fe3d457d11cc1c4989105986a03583a1d54d0c25053118944b62e100" +checksum = "c001a603b958865ce466c92ac2487041ff402f994c705a3f12a5765e4e54a35e" dependencies = [ "accesskit", "accesskit_consumer", @@ -75,9 +78,9 @@ dependencies = [ [[package]] name = "accesskit_unix" -version = "0.18.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5d552169ef018149966ed139bb0311c6947b3343e9140d1b9f88d69da9528fd" +checksum = "f861c80792fd2f3d0fccd89be70ecd76295b9ea641e6116e331036cec0cec707" dependencies = [ "accesskit", "accesskit_atspi_common", @@ -95,9 +98,9 @@ dependencies = [ [[package]] name = "accesskit_windows" -version = "0.30.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d277279d0a3b0c0021dd110b55aa1fe326b09ee2cbc338df28f847c7daf94e25" +checksum = "ce3cdfe5e46c3f39d2d51bb6d6e5771347021889c5f6a7cade8ff7c401ccfbd7" dependencies = [ "accesskit", "accesskit_consumer", diff --git a/Cargo.toml b/Cargo.toml index ff82b6202..16548787f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -131,7 +131,7 @@ usvg = "0.46" # Windowing & Input raw-window-handle = "0.6.0" winit = { version = "=0.31.0-beta.2" } -accesskit = "0.22" +accesskit = "0.23" arboard = { version = "3.4.1", default-features = false } rfd = { version = "0.17.1", default-features = false } keyboard-types = "0.7" diff --git a/packages/accesskit_xplat/Cargo.toml b/packages/accesskit_xplat/Cargo.toml index 60dba5c2f..2af4a2a15 100644 --- a/packages/accesskit_xplat/Cargo.toml +++ b/packages/accesskit_xplat/Cargo.toml @@ -14,19 +14,19 @@ async-io = ["accesskit_unix/async-io"] tokio = ["accesskit_unix/tokio"] [dependencies] -accesskit = { version = "0.22" } +accesskit = { version = "0.23" } raw-window-handle = { version = "0.6.2", features = ["std"] } [target.'cfg(target_os = "windows")'.dependencies] -accesskit_windows = { version = "0.30.0" } +accesskit_windows = { version = "0.31.0" } [target.'cfg(target_os = "macos")'.dependencies] -accesskit_macos = { version = "0.23.0" } +accesskit_macos = { version = "0.24.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 } +accesskit_unix = { version = "0.19.0", optional = true, default-features = false } [target.'cfg(target_os = "android")'.dependencies] -accesskit_android = { version = "0.5.0", optional = true, features = ["embedded-dex"] } +accesskit_android = { version = "0.6.0", optional = true, features = ["embedded-dex"] } android-activity = { version = "0.6.0" } diff --git a/packages/blitz-dom/src/accessibility.rs b/packages/blitz-dom/src/accessibility.rs index 573b2fefa..58a1bffe1 100644 --- a/packages/blitz-dom/src/accessibility.rs +++ b/packages/blitz-dom/src/accessibility.rs @@ -1,5 +1,5 @@ use crate::{BaseDocument, Node as BlitzDomNode, local_name}; -use accesskit::{Node as AccessKitNode, NodeId, Role, Tree, TreeUpdate}; +use accesskit::{Node as AccessKitNode, NodeId, Role, Tree, TreeId, TreeUpdate}; impl BaseDocument { pub fn build_accessibility_tree(&self) -> TreeUpdate { @@ -25,6 +25,7 @@ impl BaseDocument { let tree = Tree::new(NodeId(u64::MAX)); TreeUpdate { + tree_id: TreeId::ROOT, nodes, tree: Some(tree), focus: NodeId(self.focus_node_id.map(|id| id as u64).unwrap_or(u64::MAX)), From 4d6dee83cafb011249ce79bbae1e2ce994f2726a Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Thu, 22 Jan 2026 19:48:30 +0000 Subject: [PATCH 68/73] Make text input work with NativeActivity on Android --- apps/browser/Dioxus.toml | 2 +- apps/browser/MainActivity.kt | 32 ++++++++++++++++++++++++++++ apps/browser/MainActivity.kt.hbs | 4 ---- examples/todomvc/Dioxus.toml | 2 +- examples/todomvc/MainActivity.kt | 31 +++++++++++++++++++++++++++ examples/todomvc/MainActivity.kt.hbs | 4 ---- 6 files changed, 65 insertions(+), 10 deletions(-) create mode 100644 apps/browser/MainActivity.kt delete mode 100644 apps/browser/MainActivity.kt.hbs create mode 100644 examples/todomvc/MainActivity.kt delete mode 100644 examples/todomvc/MainActivity.kt.hbs diff --git a/apps/browser/Dioxus.toml b/apps/browser/Dioxus.toml index eaf405d22..0fbc25e63 100644 --- a/apps/browser/Dioxus.toml +++ b/apps/browser/Dioxus.toml @@ -1,5 +1,5 @@ [application] -android_main_activity = "MainActivity.kt.hbs" +android_main_activity = "MainActivity.kt" [bundle] publisher = "DioxusLabs" diff --git a/apps/browser/MainActivity.kt b/apps/browser/MainActivity.kt new file mode 100644 index 000000000..4a63145ca --- /dev/null +++ b/apps/browser/MainActivity.kt @@ -0,0 +1,32 @@ +package dev.dioxus.main + +import android.app.NativeActivity +import android.os.Bundle +import android.view.View +import android.view.ViewGroup +import androidx.core.view.ViewCompat +import androidx.core.view.OnApplyWindowInsetsListener +import androidx.core.view.WindowInsetsCompat + +// Makes basic text input work with NativeActivity +// Copied from https://github.com/rust-mobile/android-activity/pull/178#issuecomment-2572817579 +class MainActivity : NativeActivity() { // ,OnApplyWindowInsetsListener { + private fun getNativeActivityView(): View { + // This is hacky as hell, but NativeActivity does not give any proper way of accessing it. + var parent = window.decorView as ViewGroup + parent = parent.getChildAt(0) as ViewGroup + parent = parent.getChildAt(1) as ViewGroup + return parent.getChildAt(0) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + val nativeActivityView = getNativeActivityView() + nativeActivityView.isFocusable = true + nativeActivityView.isFocusableInTouchMode = true + nativeActivityView.requestFocus() + + // ViewCompat.setOnApplyWindowInsetsListener(nativeActivityView, this) + } +} \ No newline at end of file diff --git a/apps/browser/MainActivity.kt.hbs b/apps/browser/MainActivity.kt.hbs deleted file mode 100644 index a0ce0e2c3..000000000 --- a/apps/browser/MainActivity.kt.hbs +++ /dev/null @@ -1,4 +0,0 @@ -package dev.dioxus.main; - -class MainActivity : android.app.NativeActivity() -//class MainActivity : com.google.androidgamesdk.GameActivity() diff --git a/examples/todomvc/Dioxus.toml b/examples/todomvc/Dioxus.toml index 3292650d6..9e8a5841f 100644 --- a/examples/todomvc/Dioxus.toml +++ b/examples/todomvc/Dioxus.toml @@ -1,2 +1,2 @@ [application] -android_main_activity = "MainActivity.kt.hbs" \ No newline at end of file +android_main_activity = "MainActivity.kt" \ No newline at end of file diff --git a/examples/todomvc/MainActivity.kt b/examples/todomvc/MainActivity.kt new file mode 100644 index 000000000..e4c4171de --- /dev/null +++ b/examples/todomvc/MainActivity.kt @@ -0,0 +1,31 @@ +package dev.dioxus.main + +import android.app.NativeActivity +import android.os.Bundle +import android.view.View +import android.view.ViewGroup +import androidx.core.view.ViewCompat +import androidx.core.view.OnApplyWindowInsetsListener +import androidx.core.view.WindowInsetsCompat + +// Makes basic text input work with NativeActivity +class MainActivity : NativeActivity() { // ,OnApplyWindowInsetsListener { + private fun getNativeActivityView(): View { + // This is hacky as hell, but NativeActivity does not give any proper way of accessing it. + var parent = window.decorView as ViewGroup + parent = parent.getChildAt(0) as ViewGroup + parent = parent.getChildAt(1) as ViewGroup + return parent.getChildAt(0) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + val nativeActivityView = getNativeActivityView() + nativeActivityView.isFocusable = true + nativeActivityView.isFocusableInTouchMode = true + nativeActivityView.requestFocus() + + // ViewCompat.setOnApplyWindowInsetsListener(nativeActivityView, this) + } +} \ No newline at end of file diff --git a/examples/todomvc/MainActivity.kt.hbs b/examples/todomvc/MainActivity.kt.hbs deleted file mode 100644 index a0ce0e2c3..000000000 --- a/examples/todomvc/MainActivity.kt.hbs +++ /dev/null @@ -1,4 +0,0 @@ -package dev.dioxus.main; - -class MainActivity : android.app.NativeActivity() -//class MainActivity : com.google.androidgamesdk.GameActivity() From d71387ebf011b67862dee0dfe7119bcd551af754 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Fri, 23 Jan 2026 14:22:47 +0000 Subject: [PATCH 69/73] Rename NativeClickData to NativePointerData --- packages/dioxus-native-dom/src/dioxus_document.rs | 4 ++-- packages/dioxus-native-dom/src/events.rs | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/dioxus-native-dom/src/dioxus_document.rs b/packages/dioxus-native-dom/src/dioxus_document.rs index 16a2e3a32..05368a31e 100644 --- a/packages/dioxus-native-dom/src/dioxus_document.rs +++ b/packages/dioxus-native-dom/src/dioxus_document.rs @@ -1,6 +1,6 @@ //! Integration between Dioxus and Blitz use crate::events::{ - BlitzKeyboardData, NativeClickData, NativeConverter, NativeFocusData, NativeFormData, + BlitzKeyboardData, NativePointerData, NativeConverter, NativeFocusData, NativeFormData, NativeScrollData, NativeWheelData, NodeHandle, }; use crate::mutation_writer::{DioxusState, MutationWriter}; @@ -282,7 +282,7 @@ impl EventHandler for DioxusEventHandler<'_> { | DomEventData::Click(mevent) | DomEventData::ContextMenu(mevent) | DomEventData::DoubleClick(mevent) => { - Some(wrap_event_data(NativeClickData(mevent.clone()))) + Some(wrap_event_data(NativePointerData(mevent.clone()))) } DomEventData::Scroll(sevent) => Some(wrap_event_data(NativeScrollData(sevent.clone()))), diff --git a/packages/dioxus-native-dom/src/events.rs b/packages/dioxus-native-dom/src/events.rs index b6da4ba95..179b45b93 100644 --- a/packages/dioxus-native-dom/src/events.rs +++ b/packages/dioxus-native-dom/src/events.rs @@ -44,7 +44,7 @@ impl HtmlEventConverter for NativeConverter { } fn convert_mouse_data(&self, event: &PlatformEventData) -> MouseData { - event.downcast::().unwrap().clone().into() + event.downcast::().unwrap().clone().into() } fn convert_keyboard_data(&self, event: &PlatformEventData) -> KeyboardData { @@ -297,9 +297,9 @@ impl HasKeyboardData for BlitzKeyboardData { } #[derive(Clone)] -pub struct NativeClickData(pub(crate) BlitzPointerEvent); +pub struct NativePointerData(pub(crate) BlitzPointerEvent); -impl InteractionLocation for NativeClickData { +impl InteractionLocation for NativePointerData { fn client_coordinates(&self) -> ClientPoint { ClientPoint::new(self.0.client_x() as f64, self.0.client_y() as f64) } @@ -313,20 +313,20 @@ impl InteractionLocation for NativeClickData { } } -impl InteractionElementOffset for NativeClickData { +impl InteractionElementOffset for NativePointerData { fn element_coordinates(&self) -> ElementPoint { // TODO: implement element point ElementPoint::new(0.0, 0.0) } } -impl ModifiersInteraction for NativeClickData { +impl ModifiersInteraction for NativePointerData { fn modifiers(&self) -> Modifiers { self.0.mods } } -impl PointerInteraction for NativeClickData { +impl PointerInteraction for NativePointerData { fn trigger_button(&self) -> Option { Some(match self.0.button { MouseEventButton::Main => MouseButton::Primary, @@ -341,7 +341,7 @@ impl PointerInteraction for NativeClickData { dioxus_html::input_data::decode_mouse_button_set(self.0.buttons.bits() as u16) } } -impl HasMouseData for NativeClickData { +impl HasMouseData for NativePointerData { fn as_any(&self) -> &dyn Any { self as &dyn Any } From 463e0fef1700c88b31cb1516294630bc7f357584 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Fri, 23 Jan 2026 14:53:41 +0000 Subject: [PATCH 70/73] Add DomEvent variants for pointer events --- packages/blitz-dom/src/events/driver.rs | 8 +- packages/blitz-dom/src/events/mod.rs | 60 +++++++++--- packages/blitz-dom/src/events/pointer.rs | 6 +- packages/blitz-traits/src/events.rs | 93 +++++++++++++++++++ .../dioxus-native-dom/src/dioxus_document.rs | 11 ++- packages/dioxus-native-dom/src/events.rs | 69 ++++++++++++-- 6 files changed, 218 insertions(+), 29 deletions(-) diff --git a/packages/blitz-dom/src/events/driver.rs b/packages/blitz-dom/src/events/driver.rs index 3f8f7d159..a2d59221b 100644 --- a/packages/blitz-dom/src/events/driver.rs +++ b/packages/blitz-dom/src/events/driver.rs @@ -150,18 +150,18 @@ impl<'doc, Handler: EventHandler> EventDriver<'doc, Handler> { UiEvent::KeyDown(_) => focussed_node_id, UiEvent::Ime(_) => focussed_node_id, }; + let target = target.unwrap_or_else(|| self.doc.inner().root_element().id); let data = match event { - UiEvent::PointerMove(data) => DomEventData::MouseMove(data), - UiEvent::PointerUp(data) => DomEventData::MouseUp(data), - UiEvent::PointerDown(data) => DomEventData::MouseDown(data), + UiEvent::PointerMove(data) => DomEventData::PointerMove(data), + UiEvent::PointerUp(data) => DomEventData::PointerUp(data), + UiEvent::PointerDown(data) => DomEventData::PointerDown(data), UiEvent::Wheel(data) => DomEventData::Wheel(data), UiEvent::KeyUp(data) => DomEventData::KeyUp(data), UiEvent::KeyDown(data) => DomEventData::KeyDown(data), UiEvent::Ime(data) => DomEventData::Ime(data), }; - let target = target.unwrap_or_else(|| self.doc.inner().root_element().id); let dom_event = DomEvent::new(target, data); self.handle_dom_event(dom_event); diff --git a/packages/blitz-dom/src/events/mod.rs b/packages/blitz-dom/src/events/mod.rs index ef2481cce..94a2410cc 100644 --- a/packages/blitz-dom/src/events/mod.rs +++ b/packages/blitz-dom/src/events/mod.rs @@ -10,10 +10,8 @@ pub use driver::{EventDriver, EventHandler, NoopEventHandler}; use focus::generate_focus_events; pub(crate) use ime::handle_ime_event; pub(crate) use keyboard::handle_keypress; -use pointer::handle_mouseup; -pub(crate) use pointer::{ - DragMode, ScrollAnimationState, handle_click, handle_mousedown, handle_mousemove, -}; +pub(crate) use pointer::{DragMode, ScrollAnimationState}; +use pointer::{handle_click, handle_pointerdown, handle_pointermove, handle_pointerup}; use crate::{BaseDocument, events::pointer::handle_wheel}; @@ -43,27 +41,42 @@ pub(crate) fn handle_dom_event( let viewport_scroll = sub_doc.inner().viewport_scroll(); // TODO: eliminate clone let ui_event = match event.data.clone() { - DomEventData::MouseMove(mut event) => { + DomEventData::PointerMove(mut event) => { adjust_coords_for_subdocument(&mut event.coords, pos, viewport_scroll); Some(UiEvent::PointerMove(event)) } - DomEventData::MouseDown(mut event) => { + DomEventData::PointerDown(mut event) => { adjust_coords_for_subdocument(&mut event.coords, pos, viewport_scroll); set_focus = true; Some(UiEvent::PointerDown(event)) } - DomEventData::MouseUp(mut event) => { + DomEventData::PointerUp(mut event) => { adjust_coords_for_subdocument(&mut event.coords, pos, viewport_scroll); set_focus = true; Some(UiEvent::PointerUp(event)) } + + // Enter/leave events will be recreated by sub-document's event driver + // based move events + DomEventData::PointerEnter(_) => None, + DomEventData::PointerLeave(_) => None, + DomEventData::PointerOver(_) => None, + DomEventData::PointerOut(_) => None, + + // Mouse events will be recreated by sub-document's event driver + // based pointer events + DomEventData::MouseMove(_) => None, + DomEventData::MouseDown(_) => None, + DomEventData::MouseUp(_) => None, DomEventData::MouseEnter(_) => None, DomEventData::MouseLeave(_) => None, DomEventData::MouseOver(_) => None, DomEventData::MouseOut(_) => None, + DomEventData::KeyDown(data) => Some(UiEvent::KeyDown(data)), DomEventData::KeyUp(data) => Some(UiEvent::KeyUp(data)), DomEventData::Ime(data) => Some(UiEvent::Ime(data)), + DomEventData::KeyPress(_) => None, DomEventData::Click(_) => None, DomEventData::ContextMenu(_) => None, @@ -96,14 +109,17 @@ pub(crate) fn handle_dom_event( } match &event.data { - DomEventData::MouseMove(event) => { - let changed = handle_mousemove(doc, target_node_id, event, dispatch_event); + DomEventData::PointerMove(event) => { + let changed = handle_pointermove(doc, target_node_id, event, dispatch_event); if changed { doc.shell_provider.request_redraw(); } } - DomEventData::MouseDown(event) => { - handle_mousedown( + DomEventData::MouseMove(_) => { + // Do nothing (handled in PointerMove) + } + DomEventData::PointerDown(event) => { + handle_pointerdown( doc, target_node_id, event.page_x(), @@ -112,8 +128,14 @@ pub(crate) fn handle_dom_event( &mut dispatch_event, ); } - DomEventData::MouseUp(event) => { - handle_mouseup(doc, target_node_id, event, dispatch_event); + DomEventData::MouseDown(_) => { + // Do nothing (handled in PointerDown) + } + DomEventData::PointerUp(event) => { + handle_pointerup(doc, target_node_id, event, dispatch_event); + } + DomEventData::MouseUp(_) => { + // Do nothing (handled in PointerUp) } DomEventData::Click(event) => { handle_click(doc, target_node_id, event, &mut dispatch_event); @@ -139,6 +161,18 @@ pub(crate) fn handle_dom_event( DomEventData::DoubleClick(_) => { // Do nothing (no default action) } + DomEventData::PointerEnter(_) => { + // Do nothing (no default action) + } + DomEventData::PointerLeave(_) => { + // Do nothing (no default action) + } + DomEventData::PointerOver(_) => { + // Do nothing (no default action) + } + DomEventData::PointerOut(_) => { + // Do nothing (no default action) + } DomEventData::MouseEnter(_) => { // Do nothing (no default action) } diff --git a/packages/blitz-dom/src/events/pointer.rs b/packages/blitz-dom/src/events/pointer.rs index 3bc47f799..1902ff0ab 100644 --- a/packages/blitz-dom/src/events/pointer.rs +++ b/packages/blitz-dom/src/events/pointer.rs @@ -138,7 +138,7 @@ impl PanState { } } -pub(crate) fn handle_mousemove( +pub(crate) fn handle_pointermove( doc: &mut BaseDocument, target: usize, event: &BlitzPointerEvent, @@ -247,7 +247,7 @@ pub(crate) fn handle_mousemove( changed } -pub(crate) fn handle_mousedown( +pub(crate) fn handle_pointerdown( doc: &mut BaseDocument, _target: usize, x: f32, @@ -376,7 +376,7 @@ pub(crate) fn handle_mousedown( } } -pub(crate) fn handle_mouseup( +pub(crate) fn handle_pointerup( doc: &mut BaseDocument, target: usize, event: &BlitzPointerEvent, diff --git a/packages/blitz-traits/src/events.rs b/packages/blitz-traits/src/events.rs index 0ee1d2fb4..04e250ea1 100644 --- a/packages/blitz-traits/src/events.rs +++ b/packages/blitz-traits/src/events.rs @@ -97,6 +97,14 @@ impl DomEvent { #[derive(Copy, Clone, Debug, PartialEq)] #[repr(u8)] pub enum DomEventKind { + PointerMove, + PointerDown, + PointerUp, + PointerEnter, + PointerLeave, + PointerOver, + PointerOut, + MouseMove, MouseDown, MouseUp, @@ -104,16 +112,20 @@ pub enum DomEventKind { MouseLeave, MouseOver, MouseOut, + Scroll, Wheel, + Click, ContextMenu, DoubleClick, + KeyPress, KeyDown, KeyUp, Input, Ime, + Focus, Blur, FocusIn, @@ -128,6 +140,14 @@ impl FromStr for DomEventKind { type Err = (); fn from_str(s: &str) -> Result { match s.trim_start_matches("on") { + "pointermove" => Ok(Self::PointerMove), + "pointerdown" => Ok(Self::PointerDown), + "pointerup" => Ok(Self::PointerUp), + "pointerenter" => Ok(Self::PointerEnter), + "pointerleave" => Ok(Self::PointerLeave), + "pointerover" => Ok(Self::PointerOver), + "pointerout" => Ok(Self::PointerOut), + "mousemove" => Ok(Self::MouseMove), "mousedown" => Ok(Self::MouseDown), "mouseup" => Ok(Self::MouseUp), @@ -135,16 +155,20 @@ impl FromStr for DomEventKind { "mouseleave" => Ok(Self::MouseLeave), "mouseover" => Ok(Self::MouseOver), "mouseout" => Ok(Self::MouseOut), + "scroll" => Ok(Self::Scroll), "wheel" => Ok(Self::Wheel), + "click" => Ok(Self::Click), "contextmenu" => Ok(Self::ContextMenu), "dblclick" => Ok(Self::DoubleClick), + "keypress" => Ok(Self::KeyPress), "keydown" => Ok(Self::KeyDown), "keyup" => Ok(Self::KeyUp), "input" => Ok(Self::Input), "composition" => Ok(Self::Ime), + "focus" => Ok(Self::Focus), "blur" => Ok(Self::Blur), "focusin" => Ok(Self::FocusIn), @@ -157,6 +181,14 @@ impl FromStr for DomEventKind { #[derive(Debug, Clone)] #[repr(u8)] pub enum DomEventData { + PointerMove(BlitzPointerEvent), + PointerDown(BlitzPointerEvent), + PointerUp(BlitzPointerEvent), + PointerEnter(BlitzPointerEvent), + PointerLeave(BlitzPointerEvent), + PointerOver(BlitzPointerEvent), + PointerOut(BlitzPointerEvent), + MouseMove(BlitzPointerEvent), MouseDown(BlitzPointerEvent), MouseUp(BlitzPointerEvent), @@ -164,16 +196,20 @@ pub enum DomEventData { MouseLeave(BlitzPointerEvent), MouseOver(BlitzPointerEvent), MouseOut(BlitzPointerEvent), + Scroll(BlitzScrollEvent), Wheel(BlitzWheelEvent), + Click(BlitzPointerEvent), ContextMenu(BlitzPointerEvent), DoubleClick(BlitzPointerEvent), + KeyPress(BlitzKeyEvent), KeyDown(BlitzKeyEvent), KeyUp(BlitzKeyEvent), Input(BlitzInputEvent), Ime(BlitzImeEvent), + Focus(BlitzFocusEvent), Blur(BlitzFocusEvent), FocusIn(BlitzFocusEvent), @@ -192,6 +228,14 @@ impl DomEventData { impl DomEventData { pub fn name(&self) -> &'static str { match self { + Self::PointerMove { .. } => "pointermove", + Self::PointerDown { .. } => "pointerdown", + Self::PointerUp { .. } => "pointerup", + Self::PointerEnter { .. } => "pointerenter", + Self::PointerLeave { .. } => "pointerleave", + Self::PointerOver { .. } => "pointerover", + Self::PointerOut { .. } => "pointerout", + Self::MouseMove { .. } => "mousemove", Self::MouseDown { .. } => "mousedown", Self::MouseUp { .. } => "mouseup", @@ -199,16 +243,20 @@ impl DomEventData { Self::MouseLeave { .. } => "mouseleave", Self::MouseOver { .. } => "mouseover", Self::MouseOut { .. } => "mouseout", + Self::Scroll { .. } => "scroll", Self::Wheel { .. } => "wheel", + Self::Click { .. } => "click", Self::ContextMenu { .. } => "contextmenu", Self::DoubleClick { .. } => "dblclick", + Self::KeyPress { .. } => "keypress", Self::KeyDown { .. } => "keydown", Self::KeyUp { .. } => "keyup", Self::Input { .. } => "input", Self::Ime { .. } => "composition", + Self::Focus { .. } => "focus", Self::Blur { .. } => "blur", Self::FocusIn { .. } => "focusin", @@ -218,6 +266,14 @@ impl DomEventData { pub fn kind(&self) -> DomEventKind { match self { + Self::PointerMove { .. } => DomEventKind::PointerMove, + Self::PointerDown { .. } => DomEventKind::PointerDown, + Self::PointerUp { .. } => DomEventKind::PointerUp, + Self::PointerEnter { .. } => DomEventKind::PointerEnter, + Self::PointerLeave { .. } => DomEventKind::PointerLeave, + Self::PointerOver { .. } => DomEventKind::PointerOver, + Self::PointerOut { .. } => DomEventKind::PointerOut, + Self::MouseMove { .. } => DomEventKind::MouseMove, Self::MouseDown { .. } => DomEventKind::MouseDown, Self::MouseUp { .. } => DomEventKind::MouseUp, @@ -225,16 +281,20 @@ impl DomEventData { Self::MouseLeave { .. } => DomEventKind::MouseLeave, Self::MouseOver { .. } => DomEventKind::MouseOver, Self::MouseOut { .. } => DomEventKind::MouseOut, + Self::Scroll { .. } => DomEventKind::Scroll, Self::Wheel { .. } => DomEventKind::Wheel, + Self::Click { .. } => DomEventKind::Click, Self::ContextMenu { .. } => DomEventKind::ContextMenu, Self::DoubleClick { .. } => DomEventKind::DoubleClick, + Self::KeyPress { .. } => DomEventKind::KeyPress, Self::KeyDown { .. } => DomEventKind::KeyDown, Self::KeyUp { .. } => DomEventKind::KeyUp, Self::Input { .. } => DomEventKind::Input, Self::Ime { .. } => DomEventKind::Ime, + Self::Focus { .. } => DomEventKind::Focus, Self::Blur { .. } => DomEventKind::Blur, Self::FocusIn { .. } => DomEventKind::FocusIn, @@ -244,6 +304,14 @@ impl DomEventData { pub fn cancelable(&self) -> bool { match self { + Self::PointerMove { .. } => true, + Self::PointerDown { .. } => true, + Self::PointerUp { .. } => true, + Self::PointerEnter { .. } => false, + Self::PointerLeave { .. } => false, + Self::PointerOver { .. } => true, + Self::PointerOut { .. } => true, + Self::MouseMove { .. } => true, Self::MouseDown { .. } => true, Self::MouseUp { .. } => true, @@ -251,16 +319,20 @@ impl DomEventData { Self::MouseLeave { .. } => false, Self::MouseOver { .. } => true, Self::MouseOut { .. } => true, + Self::Scroll { .. } => false, Self::Wheel { .. } => true, + Self::Click { .. } => true, Self::ContextMenu { .. } => true, Self::DoubleClick { .. } => true, + Self::KeyDown { .. } => true, Self::KeyUp { .. } => true, Self::KeyPress { .. } => true, Self::Ime { .. } => true, Self::Input { .. } => false, + Self::Focus { .. } => false, Self::Blur { .. } => false, Self::FocusIn { .. } => false, @@ -270,6 +342,14 @@ impl DomEventData { pub fn bubbles(&self) -> bool { match self { + Self::PointerMove { .. } => true, + Self::PointerDown { .. } => true, + Self::PointerUp { .. } => true, + Self::PointerEnter { .. } => false, + Self::PointerLeave { .. } => false, + Self::PointerOver { .. } => true, + Self::PointerOut { .. } => true, + Self::MouseMove { .. } => true, Self::MouseDown { .. } => true, Self::MouseUp { .. } => true, @@ -277,16 +357,20 @@ impl DomEventData { Self::MouseLeave { .. } => false, Self::MouseOver { .. } => true, Self::MouseOut { .. } => true, + Self::Scroll { .. } => false, Self::Wheel { .. } => true, + Self::Click { .. } => true, Self::ContextMenu { .. } => true, Self::DoubleClick { .. } => true, + Self::KeyDown { .. } => true, Self::KeyUp { .. } => true, Self::KeyPress { .. } => true, Self::Ime { .. } => true, Self::Input { .. } => true, + Self::Focus { .. } => false, Self::Blur { .. } => false, Self::FocusIn { .. } => true, @@ -334,6 +418,15 @@ pub struct BlitzPointerEvent { } impl BlitzPointerEvent { + #[inline(always)] + pub fn is_mouse(&self) -> bool { + matches!(self.id, BlitzPointerId::Mouse) + } + #[inline(always)] + pub fn is_finger(&self) -> bool { + matches!(self.id, BlitzPointerId::Finger(_)) + } + #[inline(always)] pub fn page_x(&self) -> f32 { self.coords.page_x diff --git a/packages/dioxus-native-dom/src/dioxus_document.rs b/packages/dioxus-native-dom/src/dioxus_document.rs index 05368a31e..7c01cd2ff 100644 --- a/packages/dioxus-native-dom/src/dioxus_document.rs +++ b/packages/dioxus-native-dom/src/dioxus_document.rs @@ -1,6 +1,6 @@ //! Integration between Dioxus and Blitz use crate::events::{ - BlitzKeyboardData, NativePointerData, NativeConverter, NativeFocusData, NativeFormData, + BlitzKeyboardData, NativeConverter, NativeFocusData, NativeFormData, NativePointerData, NativeScrollData, NativeWheelData, NodeHandle, }; use crate::mutation_writer::{DioxusState, MutationWriter}; @@ -272,7 +272,14 @@ impl EventHandler for DioxusEventHandler<'_> { } let event_data = match &event.data { - DomEventData::MouseMove(mevent) + DomEventData::PointerMove(mevent) + | DomEventData::PointerDown(mevent) + | DomEventData::PointerUp(mevent) + | DomEventData::PointerLeave(mevent) + | DomEventData::PointerEnter(mevent) + | DomEventData::PointerOver(mevent) + | DomEventData::PointerOut(mevent) + | DomEventData::MouseMove(mevent) | DomEventData::MouseDown(mevent) | DomEventData::MouseUp(mevent) | DomEventData::MouseLeave(mevent) diff --git a/packages/dioxus-native-dom/src/events.rs b/packages/dioxus-native-dom/src/events.rs index 179b45b93..d629b619b 100644 --- a/packages/dioxus-native-dom/src/events.rs +++ b/packages/dioxus-native-dom/src/events.rs @@ -1,7 +1,7 @@ use blitz_dom::{BaseDocument, Node}; use blitz_traits::events::{ - BlitzKeyEvent, BlitzPointerEvent, BlitzScrollEvent, BlitzWheelDelta, BlitzWheelEvent, - MouseEventButton, + BlitzKeyEvent, BlitzPointerEvent, BlitzPointerId, BlitzScrollEvent, BlitzWheelDelta, + BlitzWheelEvent, MouseEventButton, }; use dioxus_html::{ geometry::{ @@ -15,8 +15,8 @@ use dioxus_html::{ }, AnimationData, CancelData, ClipboardData, CompositionData, DragData, FocusData, FormData, FormValue, HasFileData, HasFocusData, HasFormData, HasKeyboardData, HasMouseData, - HasScrollData, HasWheelData, HtmlEventConverter, ImageData, KeyboardData, MediaData, - MountedData, MountedError, MountedResult, MouseData, PlatformEventData, PointerData, + HasPointerData, HasScrollData, HasWheelData, HtmlEventConverter, ImageData, KeyboardData, + MediaData, MountedData, MountedError, MountedResult, MouseData, PlatformEventData, PointerData, RenderedElementBacking, ResizeData, ScrollBehavior, ScrollData, ScrollToOptions, SelectionData, ToggleData, TouchData, TransitionData, VisibleData, WheelData, }; @@ -44,7 +44,11 @@ impl HtmlEventConverter for NativeConverter { } fn convert_mouse_data(&self, event: &PlatformEventData) -> MouseData { - event.downcast::().unwrap().clone().into() + event + .downcast::() + .unwrap() + .clone() + .into() } fn convert_keyboard_data(&self, event: &PlatformEventData) -> KeyboardData { @@ -87,8 +91,12 @@ impl HtmlEventConverter for NativeConverter { event.downcast::().unwrap().clone().into() } - fn convert_pointer_data(&self, _event: &PlatformEventData) -> PointerData { - unimplemented!("todo: convert_pointer_data in dioxus-native. requires support in blitz") + fn convert_pointer_data(&self, event: &PlatformEventData) -> PointerData { + event + .downcast::() + .unwrap() + .clone() + .into() } fn convert_scroll_data(&self, event: &PlatformEventData) -> ScrollData { @@ -347,6 +355,53 @@ impl HasMouseData for NativePointerData { } } +impl HasPointerData for NativePointerData { + fn pointer_id(&self) -> i32 { + match self.0.id { + BlitzPointerId::Mouse => 0, + BlitzPointerId::Finger(id) => id as i32, + } + } + + fn pointer_type(&self) -> String { + match self.0.id { + BlitzPointerId::Mouse => String::from("mouse"), + BlitzPointerId::Finger(_) => String::from("touch"), + } + } + + fn is_primary(&self) -> bool { + self.0.is_primary + } + + fn as_any(&self) -> &dyn Any { + self as &dyn Any + } + + // TODO: implement these fields with real values + fn width(&self) -> f64 { + 1.0 + } + fn height(&self) -> f64 { + 1.0 + } + fn pressure(&self) -> f32 { + 0.0 + } + fn tangential_pressure(&self) -> f32 { + 0.0 + } + fn tilt_x(&self) -> i32 { + 0 + } + fn tilt_y(&self) -> i32 { + 0 + } + fn twist(&self) -> i32 { + 0 + } +} + #[derive(Clone)] pub struct NativeFocusData; impl HasFocusData for NativeFocusData { From b651b1788a70b4eba2f70d6dfb9e1a0d7734e3f9 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Fri, 23 Jan 2026 15:01:36 +0000 Subject: [PATCH 71/73] Dispatch pointer events Only dispatch mouse events if the pointer is a mouse. --- packages/blitz-dom/src/events/driver.rs | 94 ++++++++++++++++++++----- 1 file changed, 78 insertions(+), 16 deletions(-) diff --git a/packages/blitz-dom/src/events/driver.rs b/packages/blitz-dom/src/events/driver.rs index a2d59221b..e4b3d7c92 100644 --- a/packages/blitz-dom/src/events/driver.rs +++ b/packages/blitz-dom/src/events/driver.rs @@ -72,8 +72,16 @@ impl<'doc, Handler: EventHandler> EventDriver<'doc, Handler> { drop(doc); + let is_mouse = event.is_mouse(); + if let Some(target) = prev_hover_node_id { - self.handle_dom_event(DomEvent::new(target, DomEventData::MouseOut(event.clone()))); + self.handle_dom_event(DomEvent::new( + target, + DomEventData::PointerOut(event.clone()), + )); + if is_mouse { + self.handle_dom_event(DomEvent::new(target, DomEventData::MouseOut(event.clone()))); + } // Send an mouseleave event to all old elements on the chain for node_id in old_chain @@ -83,17 +91,30 @@ impl<'doc, Handler: EventHandler> EventDriver<'doc, Handler> { { self.handle_dom_event(DomEvent::new( *node_id, - DomEventData::MouseLeave(event.clone()), + DomEventData::PointerLeave(event.clone()), )); + if is_mouse { + self.handle_dom_event(DomEvent::new( + *node_id, + DomEventData::MouseLeave(event.clone()), + )); + } } } if let Some(target) = hover_node_id { self.handle_dom_event(DomEvent::new( target, - DomEventData::MouseOver(event.clone()), + DomEventData::PointerOver(event.clone()), )); + if is_mouse { + self.handle_dom_event(DomEvent::new( + target, + DomEventData::MouseOver(event.clone()), + )); + } + // Send an mouseenter event to all new elements on the chain for node_id in new_chain .get(first_difference_index..) @@ -102,8 +123,15 @@ impl<'doc, Handler: EventHandler> EventDriver<'doc, Handler> { { self.handle_dom_event(DomEvent::new( *node_id, - DomEventData::MouseEnter(event.clone()), + DomEventData::PointerEnter(event.clone()), )); + + if is_mouse { + self.handle_dom_event(DomEvent::new( + *node_id, + DomEventData::MouseEnter(event.clone()), + )); + } } } @@ -152,20 +180,54 @@ impl<'doc, Handler: EventHandler> EventDriver<'doc, Handler> { }; let target = target.unwrap_or_else(|| self.doc.inner().root_element().id); - let data = match event { - UiEvent::PointerMove(data) => DomEventData::PointerMove(data), - UiEvent::PointerUp(data) => DomEventData::PointerUp(data), - UiEvent::PointerDown(data) => DomEventData::PointerDown(data), - UiEvent::Wheel(data) => DomEventData::Wheel(data), - UiEvent::KeyUp(data) => DomEventData::KeyUp(data), - UiEvent::KeyDown(data) => DomEventData::KeyDown(data), - UiEvent::Ime(data) => DomEventData::Ime(data), + match event { + UiEvent::PointerMove(data) => { + if data.is_mouse() { + self.handle_dom_event(DomEvent::new( + target, + DomEventData::PointerMove(data.clone()), + )); + self.handle_dom_event(DomEvent::new(target, DomEventData::MouseMove(data))); + } else { + self.handle_dom_event(DomEvent::new(target, DomEventData::PointerMove(data))); + } + } + UiEvent::PointerUp(data) => { + if data.is_mouse() { + self.handle_dom_event(DomEvent::new( + target, + DomEventData::PointerUp(data.clone()), + )); + self.handle_dom_event(DomEvent::new(target, DomEventData::MouseUp(data))); + } else { + self.handle_dom_event(DomEvent::new(target, DomEventData::PointerUp(data))); + } + } + UiEvent::PointerDown(data) => { + if data.is_mouse() { + self.handle_dom_event(DomEvent::new( + target, + DomEventData::PointerDown(data.clone()), + )); + self.handle_dom_event(DomEvent::new(target, DomEventData::MouseDown(data))); + } else { + self.handle_dom_event(DomEvent::new(target, DomEventData::PointerDown(data))); + } + } + UiEvent::Wheel(data) => { + self.handle_dom_event(DomEvent::new(target, DomEventData::Wheel(data))) + } + UiEvent::KeyUp(data) => { + self.handle_dom_event(DomEvent::new(target, DomEventData::KeyUp(data))) + } + UiEvent::KeyDown(data) => { + self.handle_dom_event(DomEvent::new(target, DomEventData::KeyDown(data))) + } + UiEvent::Ime(data) => { + self.handle_dom_event(DomEvent::new(target, DomEventData::Ime(data))) + } }; - let dom_event = DomEvent::new(target, data); - - self.handle_dom_event(dom_event); - // Update document input state (hover, focus, active, etc) if should_clear_hover { self.doc.inner_mut().clear_hover(); From 2cd1e843b684120d5945c1626fa3fb4d36bde76c Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Fri, 23 Jan 2026 15:29:56 +0000 Subject: [PATCH 72/73] Add touch/pen details to BlitzPointerEvent Signed-off-by: Nico Burns --- packages/blitz-dom/src/node/node.rs | 1 + packages/blitz-shell/src/convert_events.rs | 27 +++++++++++++- packages/blitz-shell/src/window.rs | 12 +++++-- packages/blitz-traits/src/events.rs | 12 +++++++ packages/dioxus-native-dom/src/events.rs | 41 +++++++++++----------- 5 files changed, 69 insertions(+), 24 deletions(-) diff --git a/packages/blitz-dom/src/node/node.rs b/packages/blitz-dom/src/node/node.rs index 875592ebc..36cd0cd72 100644 --- a/packages/blitz-dom/src/node/node.rs +++ b/packages/blitz-dom/src/node/node.rs @@ -1070,6 +1070,7 @@ impl Node { mods, button: Default::default(), buttons: Default::default(), + details: Default::default(), } } } diff --git a/packages/blitz-shell/src/convert_events.rs b/packages/blitz-shell/src/convert_events.rs index ba0df9b48..16cd747af 100644 --- a/packages/blitz-shell/src/convert_events.rs +++ b/packages/blitz-shell/src/convert_events.rs @@ -1,4 +1,6 @@ -use blitz_traits::events::{BlitzImeEvent, BlitzKeyEvent, BlitzPointerId, KeyState}; +use blitz_traits::events::{ + BlitzImeEvent, BlitzKeyEvent, BlitzPointerId, KeyState, PointerDetails, +}; use blitz_traits::shell::ColorScheme; use keyboard_types::{Code, Key, Location, Modifiers}; use winit::event::KeyEvent as WinitKeyEvent; @@ -87,6 +89,29 @@ pub(crate) fn button_source_to_blitz(source: &ButtonSource) -> BlitzPointerId { } } +pub(crate) fn pointer_source_to_blitz_details(source: &PointerSource) -> PointerDetails { + match source { + PointerSource::Mouse => PointerDetails::default(), + PointerSource::Unknown => PointerDetails::default(), + PointerSource::Touch { force, .. } => PointerDetails { + pressure: force.map(|force| force.normalized(None)).unwrap_or(0.0), + ..PointerDetails::default() + }, + PointerSource::TabletTool { data, .. } => PointerDetails { + pressure: data + .force + .map(|force| force.normalized(data.angle)) + .unwrap_or(0.0), + tangential_pressure: data.tangential_force.unwrap_or(0.0), + tilt_x: data.tilt.map(|tilt| tilt.x).unwrap_or(0), + tilt_y: data.tilt.map(|tilt| tilt.y).unwrap_or(0), + twist: data.twist.unwrap_or(0), + altitude: data.angle.map(|angle| angle.altitude).unwrap_or(0.0), + azimuth: data.angle.map(|angle| angle.azimuth).unwrap_or(0.0), + }, + } +} + pub(crate) fn winit_modifiers_to_kbt_modifiers(winit_modifiers: WinitModifiers) -> Modifiers { let mut modifiers = Modifiers::default(); if winit_modifiers.control_key() { diff --git a/packages/blitz-shell/src/window.rs b/packages/blitz-shell/src/window.rs index c37bda735..a329a94f4 100644 --- a/packages/blitz-shell/src/window.rs +++ b/packages/blitz-shell/src/window.rs @@ -1,7 +1,8 @@ use crate::BlitzShellProvider; use crate::convert_events::{ - 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, + button_source_to_blitz, color_scheme_to_theme, pointer_source_to_blitz, + pointer_source_to_blitz_details, theme_to_color_scheme, winit_ime_to_blitz, + winit_key_event_to_blitz, winit_modifiers_to_kbt_modifiers, }; use crate::event::{BlitzShellProxy, create_waker}; use anyrender::WindowRenderer; @@ -9,7 +10,7 @@ use blitz_dom::Document; use blitz_paint::paint_scene; use blitz_traits::events::{ BlitzPointerEvent, BlitzPointerId, BlitzWheelDelta, BlitzWheelEvent, MouseEventButton, - MouseEventButtons, PointerCoords, UiEvent, + MouseEventButtons, PointerCoords, PointerDetails, UiEvent, }; use blitz_traits::shell::Viewport; use winit::dpi::{LogicalPosition, PhysicalInsets, PhysicalPosition}; @@ -444,6 +445,7 @@ impl View { button: Default::default(), buttons: self.buttons, mods: winit_modifiers_to_kbt_modifiers(self.keyboard_modifiers.state()), + details: pointer_source_to_blitz_details(&source) }); self.doc.handle_ui_event(event); } @@ -475,6 +477,7 @@ impl View { button: Default::default(), buttons: self.buttons, mods: winit_modifiers_to_kbt_modifiers(self.keyboard_modifiers.state()), + details: PointerDetails::default() }); self.doc.handle_ui_event(event); } @@ -486,6 +489,9 @@ impl View { button, buttons: self.buttons, mods: winit_modifiers_to_kbt_modifiers(self.keyboard_modifiers.state()), + + // TODO: details for pointer up/down events + details: PointerDetails::default(), }; let event = match state { diff --git a/packages/blitz-traits/src/events.rs b/packages/blitz-traits/src/events.rs index 04e250ea1..fd89168b3 100644 --- a/packages/blitz-traits/src/events.rs +++ b/packages/blitz-traits/src/events.rs @@ -407,6 +407,17 @@ pub struct PointerCoords { pub client_y: f32, } +#[derive(Copy, Clone, Debug, Default)] +pub struct PointerDetails { + pub pressure: f64, // default 0.5 if buttons pressed else 0.0 + pub tangential_pressure: f32, + pub tilt_x: i8, + pub tilt_y: i8, + pub twist: u16, + pub altitude: f64, + pub azimuth: f64, +} + #[derive(Clone, Debug)] pub struct BlitzPointerEvent { pub id: BlitzPointerId, @@ -415,6 +426,7 @@ pub struct BlitzPointerEvent { pub button: MouseEventButton, pub buttons: MouseEventButtons, pub mods: Modifiers, + pub details: PointerDetails, } impl BlitzPointerEvent { diff --git a/packages/dioxus-native-dom/src/events.rs b/packages/dioxus-native-dom/src/events.rs index d629b619b..5ee7755a6 100644 --- a/packages/dioxus-native-dom/src/events.rs +++ b/packages/dioxus-native-dom/src/events.rs @@ -356,6 +356,14 @@ impl HasMouseData for NativePointerData { } impl HasPointerData for NativePointerData { + fn as_any(&self) -> &dyn Any { + self as &dyn Any + } + + fn is_primary(&self) -> bool { + self.0.is_primary + } + fn pointer_id(&self) -> i32 { match self.0.id { BlitzPointerId::Mouse => 0, @@ -370,35 +378,28 @@ impl HasPointerData for NativePointerData { } } - fn is_primary(&self) -> bool { - self.0.is_primary - } - - fn as_any(&self) -> &dyn Any { - self as &dyn Any - } - - // TODO: implement these fields with real values - fn width(&self) -> f64 { - 1.0 - } - fn height(&self) -> f64 { - 1.0 - } fn pressure(&self) -> f32 { - 0.0 + self.0.details.pressure as f32 } fn tangential_pressure(&self) -> f32 { - 0.0 + self.0.details.tangential_pressure } fn tilt_x(&self) -> i32 { - 0 + self.0.details.tilt_x as i32 } fn tilt_y(&self) -> i32 { - 0 + self.0.details.tilt_y as i32 } fn twist(&self) -> i32 { - 0 + self.0.details.twist as i32 + } + + // TODO: implement these fields with real values + fn width(&self) -> f64 { + 1.0 + } + fn height(&self) -> f64 { + 1.0 } } From 1358b62ca9934be3970796d535fd7357eb314ffd Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Fri, 23 Jan 2026 15:32:13 +0000 Subject: [PATCH 73/73] Add Pen type to BlitzPointerId --- packages/blitz-dom/src/events/pointer.rs | 2 +- packages/blitz-shell/src/convert_events.rs | 4 ++-- packages/blitz-traits/src/events.rs | 1 + packages/dioxus-native-dom/src/events.rs | 2 ++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/blitz-dom/src/events/pointer.rs b/packages/blitz-dom/src/events/pointer.rs index 1902ff0ab..e2351258b 100644 --- a/packages/blitz-dom/src/events/pointer.rs +++ b/packages/blitz-dom/src/events/pointer.rs @@ -156,7 +156,7 @@ pub(crate) fn handle_pointermove( let dy = y - doc.mousedown_position.y; if dx.abs() > 2.0 || dy.abs() > 2.0 { match event.id { - BlitzPointerId::Mouse => { + BlitzPointerId::Mouse | BlitzPointerId::Pen => { doc.drag_mode = DragMode::Selecting; } BlitzPointerId::Finger(_) => { diff --git a/packages/blitz-shell/src/convert_events.rs b/packages/blitz-shell/src/convert_events.rs index 16cd747af..2b32dec58 100644 --- a/packages/blitz-shell/src/convert_events.rs +++ b/packages/blitz-shell/src/convert_events.rs @@ -79,12 +79,12 @@ pub(crate) fn pointer_source_to_blitz(source: &PointerSource) -> BlitzPointerId pub(crate) fn button_source_to_blitz(source: &ButtonSource) -> BlitzPointerId { match source { ButtonSource::Mouse(_) => BlitzPointerId::Mouse, + ButtonSource::TabletTool { .. } => BlitzPointerId::Pen, ButtonSource::Touch { finger_id, .. } => { BlitzPointerId::Finger(finger_id.into_raw() as u64) } - // TODO: TabletTool and Unknown events - ButtonSource::TabletTool { .. } => BlitzPointerId::Mouse, + // TODO: Unknown events ButtonSource::Unknown(_) => BlitzPointerId::Mouse, } } diff --git a/packages/blitz-traits/src/events.rs b/packages/blitz-traits/src/events.rs index fd89168b3..98490f863 100644 --- a/packages/blitz-traits/src/events.rs +++ b/packages/blitz-traits/src/events.rs @@ -394,6 +394,7 @@ pub struct HitResult { #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum BlitzPointerId { Mouse, + Pen, Finger(u64), } diff --git a/packages/dioxus-native-dom/src/events.rs b/packages/dioxus-native-dom/src/events.rs index 5ee7755a6..a9810b85b 100644 --- a/packages/dioxus-native-dom/src/events.rs +++ b/packages/dioxus-native-dom/src/events.rs @@ -367,6 +367,7 @@ impl HasPointerData for NativePointerData { fn pointer_id(&self) -> i32 { match self.0.id { BlitzPointerId::Mouse => 0, + BlitzPointerId::Pen => 0, BlitzPointerId::Finger(id) => id as i32, } } @@ -374,6 +375,7 @@ impl HasPointerData for NativePointerData { fn pointer_type(&self) -> String { match self.0.id { BlitzPointerId::Mouse => String::from("mouse"), + BlitzPointerId::Pen => String::from("pen"), BlitzPointerId::Finger(_) => String::from("touch"), } }