Skip to content

Commit 78d4f4b

Browse files
authored
xilem: WindowView::with_default_properties for runtime theme swap (#1822)
Scope One file: `xilem/src/window_view.rs`. Background [`RenderRoot::set_default_properties`] (added in #1821) lets a host swap the tree-wide default property set at runtime, but it's only reachable from code that holds a `RenderRoot`. Xilem apps go through `WindowView`, so they can't reach the new method at the moment. Fix Adds `WindowView::with_default_properties(Arc<DefaultProperties>)`. The new set gets pushed to the render root in `rebuild` only when the `Arc` identity changes (`Arc::ptr_eq`), so steady-state frames don't re-apply. `None` (the default) leaves the startup set untouched. Testing No tests in this PR. Xilem doesn't have masonry's `TestHarness`, and the propagation invariant is already covered by the test that landed with #1821. Anecdotally, when applied to my fork in my app, a theme toggle correctly recolors ContentColor-defaulted widgets without restart. I have screenshots or screen recordings available if desired. Disclosure: AI-assisted; still my responsibility. Closes #1819. Relevant issues: - #1765: related, still leaves `background_color()`, system light/dark detection, and the per-widget override API to that issue. - #1786: related, leaves per-widget-type styling for later. Signed-off-by: Markik <54276851+mark-ik@users.noreply.github.com>
1 parent cbd97ce commit 78d4f4b

1 file changed

Lines changed: 24 additions & 1 deletion

File tree

xilem/src/window_view.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// Copyright 2025 the Xilem Authors
22
// SPDX-License-Identifier: Apache-2.0
33

4-
use masonry::{theme::BACKGROUND_COLOR, util::debug_panic};
4+
use std::sync::Arc;
5+
6+
use masonry::{core::DefaultProperties, theme::BACKGROUND_COLOR, util::debug_panic};
57
use masonry_winit::app::{NewWindow, Window, WindowId};
68

79
use crate::core::{MessageCtx, Mut, View, ViewElement, ViewMarker};
@@ -16,6 +18,8 @@ pub struct WindowView<State: 'static> {
1618
pub(crate) masonry_root: MasonryRoot<State>,
1719
/// The base color of the window.
1820
pub(crate) base_color: Option<Color>,
21+
/// Tree-wide default properties, applied on `Arc` identity change.
22+
pub(crate) default_properties: Option<Arc<DefaultProperties>>,
1923
}
2024

2125
pub(crate) type WindowViewState = <Box<AnyWidgetView<(), ()>> as View<(), (), ViewCtx>>::ViewState;
@@ -37,6 +41,7 @@ pub fn window<V: WidgetView<State>, State: 'static>(
3741
options: WindowOptions::new(title),
3842
masonry_root: MasonryRoot::new(root_view),
3943
base_color: None,
44+
default_properties: None,
4045
}
4146
}
4247

@@ -57,6 +62,15 @@ impl<State> WindowView<State> {
5762
self.base_color = Some(color);
5863
self
5964
}
65+
66+
/// Set tree-wide default properties for runtime theme swaps.
67+
///
68+
/// Applied on `Arc` identity change; cache the value so a new identity
69+
/// only appears when the theme actually changes.
70+
pub fn with_default_properties(mut self, default_properties: Arc<DefaultProperties>) -> Self {
71+
self.default_properties = Some(default_properties);
72+
self
73+
}
6074
}
6175

6276
/// A newtype wrapper around [`NewWindow`] for implementing [`ViewElement`].
@@ -110,6 +124,15 @@ impl<State> View<State, (), ViewCtx> for WindowView<State> {
110124
*window.base_color() = base_color;
111125
}
112126

127+
if let Some(props) = &self.default_properties
128+
&& prev
129+
.default_properties
130+
.as_ref()
131+
.is_none_or(|p| !Arc::ptr_eq(p, props))
132+
{
133+
window.render_root().set_default_properties(props.clone());
134+
}
135+
113136
self.masonry_root.rebuild(
114137
&prev.masonry_root,
115138
root_widget_view_state,

0 commit comments

Comments
 (0)