Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Split Dioxus and HTML "wrappers" into separate crates #118

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# members = ["packages/dom"]
# members = ["packages/blitz", "packages/dom", "packages/dioxus-blitz"]
# exclude = ["packages/blitz", "packages/dioxus-blitz"]
members = ["packages/blitz", "packages/dom", "packages/dioxus-blitz"]
members = ["packages/blitz", "packages/blitz_winit", "packages/dom", "packages/dioxus-blitz"]
resolver = "2"

[workspace.dependencies]
Expand Down
38 changes: 38 additions & 0 deletions packages/blitz-winit/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[package]
name = "dioxus-blitz"
version = "0.0.0"
edition = "2021"

[features]
accessibility = ["dep:accesskit", "dep:accesskit_winit"]
hot-reload = ["dep:dioxus-cli-config", "dep:dioxus-hot-reload"]
menu = ["dep:muda"]
tracing = ["dep:tracing"]
default = ["accessibility", "hot-reload", "menu", "tracing"]

[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"], optional = true }
tokio = { workspace = true, features = ["full"] }
dioxus = { workspace = true }
dioxus-cli-config = { git = "https://github.com/dioxuslabs/dioxus", rev = "a3aa6ae771a2d0a4d8cb6055c41efc0193b817ef", optional = true }
dioxus-hot-reload = { git = "https://github.com/dioxuslabs/dioxus", rev = "a3aa6ae771a2d0a4d8cb6055c41efc0193b817ef", optional = true }
futures-util = "0.3.30"
vello = { workspace = true }
wgpu = { workspace = true }
style = { workspace = true }
tracing = { workspace = true, optional = true }
blitz = { path = "../blitz" }
blitz-dom = { path = "../dom" }
url = { version = "2.5.0", features = ["serde"] }
ureq = "2.9"
rustc-hash = "1.1.0"

[target.'cfg(target_os = "android")'.dependencies]
android-activity = { version = "0.6.0", features = ["native-activity"] }

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub struct AccessibilityState {
}

impl AccessibilityState {
pub fn new(window: &Window, proxy: EventLoopProxy<BlitzEvent>) -> Self {
pub fn new<D: Send + 'static>(window: &Window, proxy: EventLoopProxy<BlitzEvent<D>>) -> Self {
Self {
adapter: accesskit_winit::Adapter::with_event_loop_proxy(window, proxy.clone()),
next_id: 1,
Expand Down
118 changes: 118 additions & 0 deletions packages/blitz-winit/src/application.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
use crate::waker::{BlitzEvent, BlitzWindowEvent, BlitzWindowId};

use blitz_dom::DocumentLike;
use std::collections::HashMap;
use winit::application::ApplicationHandler;
use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, EventLoopProxy};
use winit::window::WindowId;

use crate::{View, WindowConfig};

pub struct Application<Doc: DocumentLike> {
pub rt: tokio::runtime::Runtime,
pub windows: HashMap<WindowId, View<Doc>>,
pub pending_windows: Vec<WindowConfig<Doc>>,
pub proxy: EventLoopProxy<BlitzEvent<Doc::DocumentEvent>>,

#[cfg(all(feature = "menu", not(any(target_os = "android", target_os = "ios"))))]
pub menu_channel: muda::MenuEventReceiver,
}

impl<Doc: DocumentLike> Application<Doc> {
pub fn new(
rt: tokio::runtime::Runtime,
proxy: EventLoopProxy<BlitzEvent<Doc::DocumentEvent>>,
) -> Self {
Application {
windows: HashMap::new(),
pending_windows: Vec::new(),
rt,
proxy,

#[cfg(all(feature = "menu", not(any(target_os = "android", target_os = "ios"))))]
menu_channel: muda::MenuEvent::receiver().clone(),
}
}

pub fn add_window(&mut self, window_config: WindowConfig<Doc>) {
self.pending_windows.push(window_config);
}
}

impl<Doc: DocumentLike> ApplicationHandler<BlitzEvent<Doc::DocumentEvent>> for Application<Doc> {
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
// Resume existing windows
for (_, view) in self.windows.iter_mut() {
view.resume(&self.rt);
}

// Initialise pending windows
for window_config in self.pending_windows.drain(..) {
let mut view = View::init(window_config, event_loop, &self.proxy);
view.resume(&self.rt);
if !view.renderer.is_active() {
continue;
}
self.windows.insert(view.window_id(), view);
}
}

fn suspended(&mut self, _event_loop: &ActiveEventLoop) {
for (_, view) in self.windows.iter_mut() {
view.suspend();
}
}

fn new_events(&mut self, _event_loop: &ActiveEventLoop, _cause: winit::event::StartCause) {
_ = self.proxy.send_event(BlitzEvent::Window {
window_id: BlitzWindowId::AllWindows,
data: BlitzWindowEvent::Poll,
});

#[cfg(all(feature = "menu", not(any(target_os = "android", target_os = "ios"))))]
if let Ok(event) = self.menu_channel.try_recv() {
if event.id == muda::MenuId::new("dev.show_layout") {
for (_, view) in self.windows.iter_mut() {
view.devtools.show_layout = !view.devtools.show_layout;
view.request_redraw();
}
}
}
}

fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
window_id: WindowId,
event: WindowEvent,
) {
// Exit the app when window close is requested. TODO: Only exit when last window is closed.
if matches!(event, WindowEvent::CloseRequested) {
event_loop.exit();
return;
}

if let Some(window) = self.windows.get_mut(&window_id) {
window.handle_winit_event(event);
}
}

fn user_event(&mut self, event_loop: &ActiveEventLoop, event: BlitzEvent<Doc::DocumentEvent>) {
match event {
BlitzEvent::Window { data, window_id } => match window_id {
BlitzWindowId::AllWindows => {
for view in self.windows.values_mut() {
view.handle_blitz_event(data.clone());
}
}
BlitzWindowId::SpecificWindow(window_id) => {
if let Some(view) = self.windows.get_mut(&window_id) {
view.handle_blitz_event(data);
};
}
},
BlitzEvent::Exit => event_loop.exit(),
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
use std::rc::Rc;

use blitz_dom::{
events::EventData, namespace_url, node::Attribute, ns, Atom, Document, DocumentLike,
ElementNodeData, NodeData, QualName, TextNodeData, Viewport,
document::DocumentEventApi, events::EventData, namespace_url, node::Attribute, ns, Atom,
Document, DocumentLike, ElementNodeData, NodeData, QualName, TextNodeData, Viewport,
};

use dioxus::{
Expand Down Expand Up @@ -53,6 +53,8 @@ impl From<DioxusDocument> for Document {
}
}
impl DocumentLike for DioxusDocument {
type DocumentEvent = crate::DioxusBlitzEvent;

fn poll(&mut self, mut cx: std::task::Context) -> bool {
{
let fut = self.vdom.wait_for_work();
Expand All @@ -72,6 +74,34 @@ impl DocumentLike for DioxusDocument {
true
}

fn handle_document_event(
&mut self,
event: Self::DocumentEvent,
mut api: impl DocumentEventApi<Self::DocumentEvent>,
) {
match event {
#[cfg(all(
feature = "hot-reload",
debug_assertions,
not(target_os = "android"),
not(target_os = "ios")
))]
crate::DioxusBlitzEvent::HotReloadEvent(msg) => {
use dioxus_hot_reload::HotReloadMsg;
match msg {
HotReloadMsg::UpdateTemplate(template) => {
self.vdom.replace_template(template);
api.request_redraw();
}
HotReloadMsg::Shutdown => api.exit(),
HotReloadMsg::UpdateAsset(_asset) => {
// TODO dioxus-desktop seems to handle this by forcing a reload of all stylesheets.
}
}
}
}
}

fn handle_event(&mut self, event: blitz_dom::events::RendererEvent) -> bool {
// Collect the nodes into a chain by traversing upwards
// This is important so the "capture" phase can be implemented
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ impl From<HtmlDocument> for Document {
}
}
impl DocumentLike for HtmlDocument {
type DocumentEvent = ();

fn handle_event(&mut self, event: blitz_dom::events::RendererEvent) -> bool {
self.inner.as_mut().handle_event(event)
}
Expand Down
Loading