Skip to content
Merged
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
6 changes: 3 additions & 3 deletions crates/libs/composition/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ fn build(compositor: &Compositor) -> SpriteVisual {
}
```

Core types include `Compositor`, the visual types, brushes, shapes, and key-frame animations. For
system composition, create a `DispatcherQueueController` and `Compositor`, then host the root
visual with `Compositor::create_desktop_window_target`, which takes a
Core types include `Compositor`, the visual types, brushes, shapes, key-frame animations, and
animation groups. For system composition, create a `DispatcherQueueController` and `Compositor`,
then host the root visual with `Compositor::create_desktop_window_target`, which takes a
[`windows-window`][window-guide] `Window`. See the [composition
guide](https://github.com/microsoft/windows-rs/blob/master/docs/crates/windows-composition.md) for
the API and hosting options.
Expand Down
17 changes: 17 additions & 0 deletions crates/libs/composition/src/animation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,23 @@ impl Animation for Vector3KeyFrameAnimation {
}
}

/// A set of animations that start together.
#[derive(Clone)]
pub struct CompositionAnimationGroup(pub(crate) bindings::CompositionAnimationGroup);

impl CompositionAnimationGroup {
/// Adds an animation to the group.
pub fn add(&self, animation: &impl Animation) {
self.0.Add(&animation.as_animation().0).unwrap();
}

/// Returns the lifted group as an inspectable object for a WinUI host.
#[cfg(feature = "reactor")]
pub fn as_host(&self) -> windows_core::IInspectable {
self.0.cast().unwrap()
}
}

/// A map of property-name -> animation applied to a visual so that changes to
/// those properties animate automatically.
///
Expand Down
79 changes: 78 additions & 1 deletion crates/libs/composition/src/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,38 @@ impl windows_core::RuntimeName for CompositionAnimation {
unsafe impl Send for CompositionAnimation {}
unsafe impl Sync for CompositionAnimation {}
#[repr(transparent)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CompositionAnimationGroup(windows_core::IUnknown);
windows_core::imp::interface_hierarchy!(
CompositionAnimationGroup,
windows_core::IUnknown,
windows_core::IInspectable
);
windows_core::imp::required_hierarchy!(
CompositionAnimationGroup,
ICompositionAnimationBase,
CompositionObject
);
impl windows_core::RuntimeType for CompositionAnimationGroup {
const SIGNATURE: windows_core::imp::ConstBuffer =
windows_core::imp::ConstBuffer::for_class::<Self, ICompositionAnimationGroup>();
}
unsafe impl windows_core::Interface for CompositionAnimationGroup {
type Vtable = <ICompositionAnimationGroup as windows_core::Interface>::Vtable;
const IID: windows_core::GUID = <ICompositionAnimationGroup as windows_core::Interface>::IID;
}
impl core::ops::Deref for CompositionAnimationGroup {
type Target = ICompositionAnimationGroup;
fn deref(&self) -> &Self::Target {
unsafe { core::mem::transmute(self) }
}
}
impl windows_core::RuntimeName for CompositionAnimationGroup {
const NAME: &'static str = "Windows.UI.Composition.CompositionAnimationGroup";
}
unsafe impl Send for CompositionAnimationGroup {}
unsafe impl Sync for CompositionAnimationGroup {}
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct CompositionBatchTypes(pub u32);
impl CompositionBatchTypes {
Expand Down Expand Up @@ -1002,6 +1034,38 @@ impl ICompositionAnimationBase_Vtbl {
pub struct ICompositionAnimationBase_Vtbl {
pub base__: windows_core::IInspectable_Vtbl,
}
windows_core::imp::define_interface!(
ICompositionAnimationGroup,
ICompositionAnimationGroup_Vtbl,
0x5e7cc90c_cd14_4e07_8a55_c72527aabdac
);
impl windows_core::RuntimeType for ICompositionAnimationGroup {
const SIGNATURE: windows_core::imp::ConstBuffer =
windows_core::imp::ConstBuffer::for_interface::<Self>();
}
impl ICompositionAnimationGroup {
pub(crate) fn Add<P0>(&self, value: P0) -> windows_core::Result<()>
where
P0: windows_core::Param<CompositionAnimation>,
{
unsafe {
(windows_core::Interface::vtable(self).Add)(
windows_core::Interface::as_raw(self),
value.param().abi(),
)
.ok()
}
}
}
#[repr(C)]
pub struct ICompositionAnimationGroup_Vtbl {
pub base__: windows_core::IInspectable_Vtbl,
Count: usize,
pub Add: unsafe extern "system" fn(
*mut core::ffi::c_void,
*mut core::ffi::c_void,
) -> windows_core::HRESULT,
}
windows_core::imp::define_interface!(
ICompositionBrush,
ICompositionBrush_Vtbl,
Expand Down Expand Up @@ -1792,6 +1856,16 @@ impl windows_core::RuntimeType for ICompositor2 {
windows_core::imp::ConstBuffer::for_interface::<Self>();
}
impl ICompositor2 {
pub(crate) fn CreateAnimationGroup(&self) -> windows_core::Result<CompositionAnimationGroup> {
unsafe {
let mut result__ = core::mem::zeroed();
(windows_core::Interface::vtable(self).CreateAnimationGroup)(
windows_core::Interface::as_raw(self),
&mut result__,
)
.and_then(|| windows_core::Type::from_abi(result__))
}
}
pub(crate) fn CreateImplicitAnimationCollection(
&self,
) -> windows_core::Result<ImplicitAnimationCollection> {
Expand Down Expand Up @@ -1819,7 +1893,10 @@ impl ICompositor2 {
pub struct ICompositor2_Vtbl {
pub base__: windows_core::IInspectable_Vtbl,
CreateAmbientLight: usize,
CreateAnimationGroup: usize,
pub CreateAnimationGroup: unsafe extern "system" fn(
*mut core::ffi::c_void,
*mut *mut core::ffi::c_void,
) -> windows_core::HRESULT,
CreateBackdropBrush: usize,
CreateDistantLight: usize,
CreateDropShadow: usize,
Expand Down
79 changes: 78 additions & 1 deletion crates/libs/composition/src/bindings_lifted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,38 @@ impl windows_core::RuntimeName for CompositionAnimation {
unsafe impl Send for CompositionAnimation {}
unsafe impl Sync for CompositionAnimation {}
#[repr(transparent)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CompositionAnimationGroup(windows_core::IUnknown);
windows_core::imp::interface_hierarchy!(
CompositionAnimationGroup,
windows_core::IUnknown,
windows_core::IInspectable
);
windows_core::imp::required_hierarchy!(
CompositionAnimationGroup,
ICompositionAnimationBase,
CompositionObject
);
impl windows_core::RuntimeType for CompositionAnimationGroup {
const SIGNATURE: windows_core::imp::ConstBuffer =
windows_core::imp::ConstBuffer::for_class::<Self, ICompositionAnimationGroup>();
}
unsafe impl windows_core::Interface for CompositionAnimationGroup {
type Vtable = <ICompositionAnimationGroup as windows_core::Interface>::Vtable;
const IID: windows_core::GUID = <ICompositionAnimationGroup as windows_core::Interface>::IID;
}
impl core::ops::Deref for CompositionAnimationGroup {
type Target = ICompositionAnimationGroup;
fn deref(&self) -> &Self::Target {
unsafe { core::mem::transmute(self) }
}
}
impl windows_core::RuntimeName for CompositionAnimationGroup {
const NAME: &'static str = "Microsoft.UI.Composition.CompositionAnimationGroup";
}
unsafe impl Send for CompositionAnimationGroup {}
unsafe impl Sync for CompositionAnimationGroup {}
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct CompositionBatchTypes(pub u32);
impl CompositionBatchTypes {
Expand Down Expand Up @@ -645,6 +677,38 @@ impl ICompositionAnimationBase_Vtbl {
pub struct ICompositionAnimationBase_Vtbl {
pub base__: windows_core::IInspectable_Vtbl,
}
windows_core::imp::define_interface!(
ICompositionAnimationGroup,
ICompositionAnimationGroup_Vtbl,
0xa51cdcac_b972_5ae7_81d0_9d91c71ecb7a
);
impl windows_core::RuntimeType for ICompositionAnimationGroup {
const SIGNATURE: windows_core::imp::ConstBuffer =
windows_core::imp::ConstBuffer::for_interface::<Self>();
}
impl ICompositionAnimationGroup {
pub(crate) fn Add<P0>(&self, value: P0) -> windows_core::Result<()>
where
P0: windows_core::Param<CompositionAnimation>,
{
unsafe {
(windows_core::Interface::vtable(self).Add)(
windows_core::Interface::as_raw(self),
value.param().abi(),
)
.ok()
}
}
}
#[repr(C)]
pub struct ICompositionAnimationGroup_Vtbl {
pub base__: windows_core::IInspectable_Vtbl,
Count: usize,
pub Add: unsafe extern "system" fn(
*mut core::ffi::c_void,
*mut core::ffi::c_void,
) -> windows_core::HRESULT,
}
windows_core::imp::define_interface!(
ICompositionBrush,
ICompositionBrush_Vtbl,
Expand Down Expand Up @@ -1211,6 +1275,16 @@ impl windows_core::RuntimeType for ICompositor2 {
windows_core::imp::ConstBuffer::for_interface::<Self>();
}
impl ICompositor2 {
pub(crate) fn CreateAnimationGroup(&self) -> windows_core::Result<CompositionAnimationGroup> {
unsafe {
let mut result__ = core::mem::zeroed();
(windows_core::Interface::vtable(self).CreateAnimationGroup)(
windows_core::Interface::as_raw(self),
&mut result__,
)
.and_then(|| windows_core::Type::from_abi(result__))
}
}
pub(crate) fn CreateImplicitAnimationCollection(
&self,
) -> windows_core::Result<ImplicitAnimationCollection> {
Expand Down Expand Up @@ -1238,7 +1312,10 @@ impl ICompositor2 {
pub struct ICompositor2_Vtbl {
pub base__: windows_core::IInspectable_Vtbl,
CreateAmbientLight: usize,
CreateAnimationGroup: usize,
pub CreateAnimationGroup: unsafe extern "system" fn(
*mut core::ffi::c_void,
*mut *mut core::ffi::c_void,
) -> windows_core::HRESULT,
CreateBackdropBrush: usize,
CreateDistantLight: usize,
CreateDropShadow: usize,
Expand Down
6 changes: 6 additions & 0 deletions crates/libs/composition/src/compositor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@ impl Compositor {
Vector3KeyFrameAnimation(self.0.CreateVector3KeyFrameAnimation().unwrap())
}

/// Creates an empty group whose animations start together.
pub fn create_animation_group(&self) -> CompositionAnimationGroup {
let compositor: bindings::ICompositor2 = self.0.cast().unwrap();
CompositionAnimationGroup(compositor.CreateAnimationGroup().unwrap())
}

/// Creates a scalar (`f32`) key-frame animation.
pub fn create_scalar_key_frame_animation(&self) -> ScalarKeyFrameAnimation {
ScalarKeyFrameAnimation(self.0.CreateScalarKeyFrameAnimation().unwrap())
Expand Down
4 changes: 2 additions & 2 deletions crates/libs/composition/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ pub(crate) use sealed::Sealed;
pub(crate) use windows_core::Interface;

pub use animation::{
Animation, CompositionAnimation, CompositionEasingFunction, ImplicitAnimationCollection,
ScalarKeyFrameAnimation, Vector3KeyFrameAnimation,
Animation, CompositionAnimation, CompositionAnimationGroup, CompositionEasingFunction,
ImplicitAnimationCollection, ScalarKeyFrameAnimation, Vector3KeyFrameAnimation,
};
pub use batch::{BatchKind, CompositionScopedBatch};
pub use brush::{Brush, CompositionBrush, CompositionColorBrush, CompositionNineGridBrush};
Expand Down
57 changes: 57 additions & 0 deletions crates/libs/reactor/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,60 @@ builders convert to `Element` with `.into()`. `cx.use_state` returns the current
whose `call` schedules a rerender. `ReactorWindow` opens more top-level windows. See the [reactor
guide](https://github.com/microsoft/windows-rs/blob/master/docs/crates/windows-reactor.md) for
components, hooks, layout, styling, and widgets.

WinUI lightweight styling resources use typed values:

```rust,ignore
button("Delete").resource_overrides(|resources| {
resources
.set("ButtonBackground", Color::rgb(178, 34, 34))
.set("ButtonBorderThemeThickness", Thickness::uniform(0.0))
.set("ControlCornerRadius", CornerRadius::uniform(8.0))
})
```

Replacing or clearing the builder removes only the resource keys previously owned by Reactor.

`PointerEventInfo` reports both element-local `x`/`y` coordinates and stable window-relative
`window_x`/`window_y` coordinates for drag calculations whose target moves during the gesture.
Use `.capture_pointer_on_press()` for drag handles that must keep receiving moves outside their
hit-test bounds, and clear drag state from capture-lost and canceled callbacks.

`NavigationView` can keep pane state controlled and react to its actual responsive display mode:

```rust,ignore
NavigationView::new(items, content)
.pane_open(pane_open)
.on_pane_open_changed(set_pane_open)
.pane_display_mode(NavigationViewPaneDisplayMode::Auto)
.on_display_mode_changed(set_display_mode)
```

The callbacks report settled WinUI dependency-property values rather than pane transition intent.

Lifecycle transitions run when an element enters or leaves the WinUI visual tree:

```rust,ignore
button("Animated").transition(
Some(AnimationConfig::fade_in(Duration::from_millis(200))),
Some(AnimationConfig::fade_out(Duration::from_millis(300))),
)
```

Reactor removes the logical element immediately while WinUI Composition keeps the departing visual
alive until its exit animation finishes. See the `exit_transition` sample.

`TabItem::with_key` supplies the identity returned by `TabView::on_close_requested`. Key changes,
including removal, update the existing native item without leaving stale close-callback identity.
See the `tab_view_item_key` sample.

Icon-taking controls share one `Icon` model:

```rust,ignore
button("Confirm").icon(Icon::path("F1 M 0,8 L 6,14 L 16,2 L 14,0 L 6,10 L 2,6 Z"));
button("Mask").icon(Icon::bitmap_icon("ms-appx:///Assets/mask.png", true));
button("Logo").icon(Icon::image("ms-appx:///Assets/logo.svg"));
```

`bitmap_icon` uses WinUI `BitmapIcon` and makes monochrome rendering explicit. `image` uses
full-color `ImageIcon` and accepts raster, SVG, or surface sources.
Loading