diff --git a/packages/blitz/Cargo.toml b/packages/blitz/Cargo.toml index e2631030..2235901b 100644 --- a/packages/blitz/Cargo.toml +++ b/packages/blitz/Cargo.toml @@ -3,10 +3,6 @@ name = "blitz" version = "0.1.0" edition = "2021" -[features] -accesskit = ["dep:accesskit"] -default = ["accesskit"] - [dependencies] slab = "0.4.9" style = { workspace = true, features = ["servo"] } @@ -18,7 +14,6 @@ tokio = { workspace = true, features = ["full"] } vello = { workspace = true } wgpu = { workspace = true } -accesskit = { version = "0.15.0", optional = true } app_units = "0.7.3" atomic_refcell = { version = "0.1.13", features = ["serde"] } fxhash = "0.2.1" diff --git a/packages/dioxus-blitz/Cargo.toml b/packages/dioxus-blitz/Cargo.toml index 6e7abc50..94ada8f7 100644 --- a/packages/dioxus-blitz/Cargo.toml +++ b/packages/dioxus-blitz/Cargo.toml @@ -4,10 +4,13 @@ version = "0.0.0" edition = "2021" [features] +accesskit = ["dep:accesskit", "dep:accesskit_winit"] hot-reload = [] -default = [] +default = ["accesskit"] [dependencies] +accesskit = { version = "0.15.0", optional = true } +accesskit_winit = { version = "0.21.1", optional = true } winit = { version = "0.30.2", features = ["rwh_06"] } muda = { version = "0.11.5", features = ["serde"] } tokio = { workspace = true, features = ["full"] } diff --git a/packages/dioxus-blitz/src/lib.rs b/packages/dioxus-blitz/src/lib.rs index 2e7290bd..2b90cec7 100644 --- a/packages/dioxus-blitz/src/lib.rs +++ b/packages/dioxus-blitz/src/lib.rs @@ -106,6 +106,7 @@ fn launch_with_window(window: View<'static, Doc>) { #[cfg(not(any(target_os = "android", target_os = "ios")))] let mut initial = true; + // Setup hot-reloading if enabled. #[cfg(all( feature = "hot-reload", @@ -126,6 +127,8 @@ fn launch_with_window(window: View<'static, Doc>) { }); } + + // the move to winit wants us to use a struct with a run method instead of the callback approach // we want to just keep the callback approach for now #[allow(deprecated)] @@ -177,45 +180,52 @@ fn launch_with_window(window: View<'static, Doc>) { }; } - Event::UserEvent(UserEvent::Window { - data: EventData::Poll, - window_id: id, - }) => { - if let Some(view) = windows.get_mut(&id) { - if view.poll() { - view.request_redraw(); + Event::UserEvent(user_event) => match user_event { + UserEvent::Window { + data: EventData::Poll, + window_id: id, + } => { + if let Some(view) = windows.get_mut(&id) { + if view.poll() { + view.request_redraw(); + } + }; + } + #[cfg(feature = "accesskit")] + UserEvent::Accessibility(accessibility_event) => { + if let Some(window) = windows.get_mut(&accessibility_event.window_id) { + window.handle_accessibility_event(&accessibility_event); } - }; - } - - #[cfg(all( - feature = "hot-reload", - debug_assertions, - not(target_os = "android"), - not(target_os = "ios") - ))] - Event::UserEvent(UserEvent::HotReloadEvent(msg)) => match msg { - dioxus_hot_reload::HotReloadMsg::UpdateTemplate(template) => { - for window in windows.values_mut() { - if let Some(dx_doc) = window - .renderer - .dom - .as_any_mut() - .downcast_mut::() - { - dx_doc.vdom.replace_template(template); - - if window.poll() { - window.request_redraw(); + } + #[cfg(all( + feature = "hot-reload", + debug_assertions, + not(target_os = "android"), + not(target_os = "ios") + ))] + UserEvent::HotReloadEvent(msg) => match msg { + dioxus_hot_reload::HotReloadMsg::UpdateTemplate(template) => { + for window in windows.values_mut() { + if let Some(dx_doc) = window + .renderer + .dom + .as_any_mut() + .downcast_mut::() + { + dx_doc.vdom.replace_template(template); + + if window.poll() { + window.request_redraw(); + } } } } - } - dioxus_hot_reload::HotReloadMsg::Shutdown => event_loop.exit(), - dioxus_hot_reload::HotReloadMsg::UpdateAsset(asset) => { - // TODO dioxus-desktop seems to handle this by forcing a reload of all stylesheets. - dbg!("Update asset {:?}", asset); - } + dioxus_hot_reload::HotReloadMsg::Shutdown => event_loop.exit(), + dioxus_hot_reload::HotReloadMsg::UpdateAsset(asset) => { + // TODO dioxus-desktop seems to handle this by forcing a reload of all stylesheets. + dbg!("Update asset {:?}", asset); + } + }, }, // Event::UserEvent(_redraw) => { @@ -245,7 +255,7 @@ fn launch_with_window(window: View<'static, Doc>) { } => { if let Some(window) = windows.get_mut(&window_id) { window.handle_window_event(event); - }; + } } _ => (), diff --git a/packages/dioxus-blitz/src/waker.rs b/packages/dioxus-blitz/src/waker.rs index 2c20983e..1fd5faf2 100644 --- a/packages/dioxus-blitz/src/waker.rs +++ b/packages/dioxus-blitz/src/waker.rs @@ -2,13 +2,21 @@ use futures_util::task::ArcWake; use std::sync::Arc; use winit::{event_loop::EventLoopProxy, window::WindowId}; +#[cfg(feature = "accesskit")] +use accesskit_winit::Event as AccessibilityEvent; + #[derive(Debug, Clone)] pub enum UserEvent { Window { window_id: WindowId, data: EventData, }, - /// Handle a hotreload event, basically telling us to update our templates + + /// An accessibility event from `accesskit`. + #[cfg(feature = "accesskit")] + Accessibility(Arc), + + /// A hotreload event, basically telling us to update our templates. #[cfg(all( feature = "hot-reload", debug_assertions, @@ -18,6 +26,14 @@ pub enum UserEvent { HotReloadEvent(dioxus_hot_reload::HotReloadMsg), } +#[cfg(feature = "accesskit")] +impl From for UserEvent { + fn from(value: AccessibilityEvent) -> Self { + Self::Accessibility(Arc::new(value)) + } +} + + #[derive(Debug, Clone)] pub enum EventData { Poll, diff --git a/packages/dioxus-blitz/src/window.rs b/packages/dioxus-blitz/src/window.rs index ae4c3de2..9e07cc08 100644 --- a/packages/dioxus-blitz/src/window.rs +++ b/packages/dioxus-blitz/src/window.rs @@ -15,6 +15,15 @@ use winit::event::{ElementState, MouseButton}; use winit::event_loop::{ActiveEventLoop, EventLoopProxy}; use winit::{event::WindowEvent, keyboard::KeyCode, keyboard::ModifiersState, window::Window}; +struct State { + /// Accessibility adapter for `accesskit`. + #[cfg(feature = "accesskit")] + adapter: accesskit_winit::Adapter, + + /// Main menu bar of this view's window. + _menu: Menu, +} + pub(crate) struct View<'s, Doc: DocumentLike> { pub(crate) renderer: Renderer<'s, Window, Doc>, pub(crate) scene: Scene, @@ -23,8 +32,8 @@ pub(crate) struct View<'s, Doc: DocumentLike> { /// need to store them in order to have access to them when processing keypress events keyboard_modifiers: ModifiersState, - /// Main menu bar of this view's window. - menu: Option, + /// State of this view, created on [`View::resume`]. + state: Option, } impl<'a, Doc: DocumentLike> View<'a, Doc> { @@ -34,7 +43,7 @@ impl<'a, Doc: DocumentLike> View<'a, Doc> { scene: Scene::new(), waker: None, keyboard_modifiers: Default::default(), - menu: None, + state: None, } } } @@ -268,6 +277,11 @@ impl<'a, Doc: DocumentLike> View<'a, Doc> { } } + #[cfg(feature = "accesskit")] + pub fn handle_accessibility_event(&mut self, event: &accesskit_winit::Event) { + todo!() + } + pub fn resume( &mut self, event_loop: &ActiveEventLoop, @@ -282,10 +296,16 @@ impl<'a, Doc: DocumentLike> View<'a, Doc> { })) .unwrap(); - self.menu = Some(init_menu( + // Initialize the menu and accessibility adapter in this view's state. + let menu = init_menu( #[cfg(target_os = "windows")] &window, - )); + ); + self.state = Some(State { + #[cfg(feature = "accesskit")] + adapter: accesskit_winit::Adapter::with_event_loop_proxy(&window, proxy.clone()), + _menu: menu, + }); let size: winit::dpi::PhysicalSize = window.inner_size(); let mut viewport = Viewport::new((size.width, size.height));