Skip to content

Commit 931b278

Browse files
committed
feat: window list auto refresh
1 parent d2cc7b7 commit 931b278

5 files changed

Lines changed: 84 additions & 69 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,13 +231,15 @@ blitz-net = { workspace = true }
231231
blitz = { workspace = true, features = ["net"] }
232232
dioxus = { workspace = true }
233233
dioxus-native = { workspace = true, features = ["vello", "floats", "svg"] }
234+
dioxus-native-dom = { workspace = true }
234235
euclid = { workspace = true }
235236
reqwest = { workspace = true }
236237
tokio = { workspace = true, features = ["macros"] }
237238
image = { workspace = true }
238239
png = { workspace = true }
239240
env_logger = "0.11"
240241
tracing-subscriber = "0.3"
242+
winit = { workspace = true }
241243

242244
# [patch.crates-io]
243245
# anyrender = { path = "../anyrender/crates/anyrender" }
@@ -253,4 +255,4 @@ tracing-subscriber = "0.3"
253255

254256
# [patch."https://github.com/nicoburns/parley"]
255257
# parley = { path = "../parley/parley" }
256-
# fontique = { path = "../parley/fontique" }
258+
# fontique = { path = "../parley/fontique" }

examples/multi_window.rs

Lines changed: 65 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
//! Demonstrate opening additional windows from a pure Dioxus app.
22
33
use dioxus::prelude::*;
4-
use dioxus_native::{DioxusWindowHandle, DioxusWindowInfo, DioxusWindowOptions};
4+
use dioxus_native::{DioxusWindowHandle, DioxusWindowInfo};
5+
use std::time::Duration;
6+
use winit::window::{WindowAttributes, WindowButtons};
57

68
fn main() {
7-
dioxus_native::launch(app);
9+
// Demonstrate how to pass custom WindowAttributes (title, size, decorations).
10+
let attrs = WindowAttributes::default()
11+
.with_title("Multi-window Demo")
12+
.with_inner_size(winit::dpi::LogicalSize::new(600.0, 800.0))
13+
.with_enabled_buttons(WindowButtons::all());
14+
dioxus_native::launch_cfg(app, vec![], vec![Box::new(attrs)]);
815
}
916

1017
fn app() -> Element {
@@ -20,39 +27,22 @@ fn app() -> Element {
2027
let known_windows_signal = known_windows.clone();
2128
let refresh_handle_for_list = refresh_handle.clone();
2229
let rename_counter = use_signal(|| 1u32);
23-
let window_rows = {
24-
let windows_snapshot = known_windows();
25-
windows_snapshot
26-
.into_iter()
27-
.map(|info| {
28-
let focus_handle = base_focus_handle.clone();
29-
let rename_handle = base_rename_handle.clone();
30-
let mut rename_counter_signal = rename_counter.clone();
31-
let mut update_list_signal = known_windows_signal.clone();
32-
let update_source = refresh_handle_for_list.clone();
33-
let id = info.id;
34-
let title = info.title;
35-
rsx! {
36-
li {
37-
"{title} (ID: {id:?})"
38-
button {
39-
onclick: move |_| focus_handle.focus_window(id),
40-
"Focus"
41-
}
42-
button {
43-
onclick: move |_| {
44-
let idx = rename_counter_signal();
45-
rename_handle.set_window_title(id, format!("Renamed {idx}"));
46-
rename_counter_signal += 1;
47-
update_list_signal.set(update_source.list_windows());
48-
},
49-
"Rename"
50-
}
51-
}
30+
31+
{
32+
let refresh_handle = window_handle.clone();
33+
let mut known_windows_signal = known_windows.clone();
34+
use_future(move || {
35+
let refresh_handle = refresh_handle.clone();
36+
async move {
37+
loop {
38+
tokio::time::sleep(Duration::from_millis(100)).await;
39+
known_windows_signal.set(refresh_handle.list_windows());
5240
}
53-
})
54-
.collect::<Vec<_>>()
55-
};
41+
}
42+
});
43+
}
44+
45+
let windows_snapshot = known_windows();
5646

5747
rsx! {
5848
main {
@@ -62,12 +52,13 @@ fn app() -> Element {
6252
div {
6353
button {
6454
onclick: move |_| {
65-
open_simple.open_window_with_options(
55+
open_simple.open_window_with_attributes(
6656
secondary_window,
67-
DioxusWindowOptions {
68-
title: Some("Secondary window".into()),
69-
..Default::default()
70-
},
57+
Some(
58+
WindowAttributes::default()
59+
.with_title("Secondary window")
60+
.with_inner_size(winit::dpi::LogicalSize::new(400.0, 300.0)),
61+
),
7162
);
7263
known_windows.set(open_simple.list_windows());
7364
},
@@ -76,15 +67,16 @@ fn app() -> Element {
7667
button {
7768
onclick: move |_| {
7869
let idx = counter();
79-
open_with_props.open_window_with_props_and_options(
70+
open_with_props.open_window_with_props_and_attributes(
8071
message_window,
8172
MessageWindowProps {
8273
message: format!("Window #{idx}"),
8374
},
84-
DioxusWindowOptions {
85-
title: Some(format!("Window #{idx}")),
86-
..Default::default()
87-
},
75+
Some(
76+
WindowAttributes::default()
77+
.with_title(format!("Window #{idx}"))
78+
.with_inner_size(winit::dpi::LogicalSize::new(320.0, 240.0)),
79+
),
8880
);
8981
counter += 1;
9082
known_windows.set(open_with_props.list_windows());
@@ -96,7 +88,35 @@ fn app() -> Element {
9688
"Refresh list"
9789
}
9890
}
99-
ul {{ window_rows.into_iter() }}
91+
ul {
92+
{windows_snapshot.into_iter().map(|info| {
93+
let focus_handle = base_focus_handle.clone();
94+
let rename_handle = base_rename_handle.clone();
95+
let mut rename_counter_signal = rename_counter.clone();
96+
let mut update_list_signal = known_windows_signal.clone();
97+
let update_source = refresh_handle_for_list.clone();
98+
let id = info.id;
99+
let title = info.title;
100+
rsx! {
101+
li {
102+
"{title} (ID: {id:?})"
103+
button {
104+
onclick: move |_| focus_handle.focus_window(id),
105+
"Focus"
106+
}
107+
button {
108+
onclick: move |_| {
109+
let idx = rename_counter_signal();
110+
rename_handle.set_window_title(id, format!("Renamed {idx}"));
111+
rename_counter_signal += 1;
112+
update_list_signal.set(update_source.list_windows());
113+
},
114+
"Rename"
115+
}
116+
}
117+
}
118+
})}
119+
}
100120
}
101121
}
102122
}

packages/dioxus-native/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub use dioxus_native_dom::*;
2727
use assets::DioxusNativeNetProvider;
2828
pub use dioxus_application::{DioxusNativeApplication, DioxusNativeEvent};
2929
pub use dioxus_renderer::DioxusNativeWindowRenderer;
30-
pub use windowing::{DioxusWindowHandle, DioxusWindowInfo, DioxusWindowOptions};
30+
pub use windowing::{DioxusWindowHandle, DioxusWindowInfo};
3131

3232
#[cfg(any(
3333
feature = "vello",

packages/dioxus-native/src/windowing.rs

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,19 @@ impl DioxusWindowTemplate {
4242
pub fn build_window(
4343
&self,
4444
component: fn() -> Element,
45-
options: DioxusWindowOptions,
45+
attributes_override: Option<WindowAttributes>,
4646
) -> QueuedWindow {
47-
self.build_window_with_props(component, (), options)
47+
self.build_window_with_props(component, (), attributes_override)
4848
}
4949

5050
pub fn build_window_with_props<P: Clone + 'static, M: 'static>(
5151
&self,
5252
component: impl ComponentFunction<P, M>,
5353
props: P,
54-
options: DioxusWindowOptions,
54+
attributes_override: Option<WindowAttributes>,
5555
) -> QueuedWindow {
56-
let mut attributes = options
57-
.attributes
58-
.unwrap_or_else(|| self.window_attributes.clone());
59-
let title = options.title.unwrap_or_else(|| attributes.title.clone());
60-
attributes.title = title.clone();
56+
let attributes = attributes_override.unwrap_or_else(|| self.window_attributes.clone());
57+
let title = attributes.title.clone();
6158

6259
let mut vdom = VirtualDom::new_with_props(component, props);
6360
for context in self.contexts.iter() {
@@ -92,12 +89,6 @@ pub struct QueuedWindow {
9289
pub title: String,
9390
}
9491

95-
#[derive(Clone, Default)]
96-
pub struct DioxusWindowOptions {
97-
pub title: Option<String>,
98-
pub attributes: Option<WindowAttributes>,
99-
}
100-
10192
#[derive(Clone, Debug)]
10293
pub struct DioxusWindowInfo {
10394
pub id: WindowId,
@@ -148,15 +139,15 @@ impl DioxusWindowHandle {
148139
}
149140

150141
pub fn open_window(&self, component: fn() -> Element) {
151-
self.open_window_with_options(component, DioxusWindowOptions::default());
142+
self.open_window_with_attributes(component, None);
152143
}
153144

154-
pub fn open_window_with_options(
145+
pub fn open_window_with_attributes(
155146
&self,
156147
component: fn() -> Element,
157-
options: DioxusWindowOptions,
148+
attributes: Option<WindowAttributes>,
158149
) {
159-
let queued = self.template.build_window(component, options);
150+
let queued = self.template.build_window(component, attributes);
160151
self.enqueue_and_signal(queued);
161152
}
162153

@@ -165,18 +156,18 @@ impl DioxusWindowHandle {
165156
component: impl ComponentFunction<P, M>,
166157
props: P,
167158
) {
168-
self.open_window_with_props_and_options(component, props, DioxusWindowOptions::default());
159+
self.open_window_with_props_and_attributes(component, props, None);
169160
}
170161

171-
pub fn open_window_with_props_and_options<P: Clone + 'static, M: 'static>(
162+
pub fn open_window_with_props_and_attributes<P: Clone + 'static, M: 'static>(
172163
&self,
173164
component: impl ComponentFunction<P, M>,
174165
props: P,
175-
options: DioxusWindowOptions,
166+
attributes: Option<WindowAttributes>,
176167
) {
177168
let queued = self
178169
.template
179-
.build_window_with_props(component, props, options);
170+
.build_window_with_props(component, props, attributes);
180171
self.enqueue_and_signal(queued);
181172
}
182173

0 commit comments

Comments
 (0)