Skip to main content

windows_composition/
compositor.rs

1use super::*;
2
3/// Factory for visuals, brushes, and window targets.
4#[derive(Clone)]
5pub struct Compositor(pub(crate) bindings::Compositor);
6
7impl Compositor {
8    /// Creates a compositor. A dispatcher queue must exist on the current thread.
9    ///
10    /// ```no_run
11    /// use windows_composition::{Compositor, DispatcherQueueController};
12    ///
13    /// let _queue = DispatcherQueueController::create_on_current_thread()?;
14    /// let compositor = Compositor::new()?;
15    /// # windows_core::Result::Ok(())
16    /// ```
17    #[cfg(feature = "system")]
18    pub fn new() -> Result<Self> {
19        Ok(Self(bindings::Compositor::new()?))
20    }
21
22    /// Wraps a lifted compositor reported by a Reactor composition host.
23    #[cfg(feature = "reactor")]
24    pub fn from_host(compositor: windows_core::IUnknown) -> Result<Self> {
25        Ok(Self(compositor.cast()?))
26    }
27
28    /// Creates a window target. Keep it alive while the visual tree is shown.
29    ///
30    /// ```no_run
31    /// use windows_composition::{Compositor, DispatcherQueueController};
32    /// use windows_window::Window;
33    ///
34    /// let window = Window::new("Composition").create()?;
35    /// let _queue = DispatcherQueueController::create_on_current_thread()?;
36    /// let compositor = Compositor::new()?;
37    /// let target = compositor.create_desktop_window_target(&window, false)?;
38    /// # windows_core::Result::Ok(())
39    /// ```
40    #[cfg(feature = "system")]
41    pub fn create_desktop_window_target(
42        &self,
43        window: &windows_window::Window,
44        is_topmost: bool,
45    ) -> Result<DesktopWindowTarget> {
46        // SAFETY: `window` owns a live `HWND` for as long as the borrow lasts.
47        unsafe { self.create_desktop_window_target_for_hwnd(window.hwnd(), is_topmost) }
48    }
49
50    /// Creates a composition target for a raw window handle.
51    ///
52    /// # Safety
53    ///
54    /// `hwnd` must be a valid, live window handle owned by the calling thread.
55    #[cfg(feature = "system")]
56    pub unsafe fn create_desktop_window_target_for_hwnd(
57        &self,
58        hwnd: *mut core::ffi::c_void,
59        is_topmost: bool,
60    ) -> Result<DesktopWindowTarget> {
61        let interop: bindings::ICompositorDesktopInterop = self.0.cast()?;
62        let target = unsafe { interop.CreateDesktopWindowTarget(hwnd, is_topmost)? };
63        Ok(DesktopWindowTarget::new(target))
64    }
65
66    /// Creates an empty container visual that hosts a child visual tree.
67    pub fn create_container_visual(&self) -> ContainerVisual {
68        ContainerVisual::new(self.0.CreateContainerVisual().unwrap())
69    }
70
71    /// Creates a sprite visual that paints itself with a brush.
72    pub fn create_sprite_visual(&self) -> SpriteVisual {
73        SpriteVisual::new(self.0.CreateSpriteVisual().unwrap())
74    }
75
76    /// Creates a solid-color brush.
77    pub fn create_color_brush(&self, color: Color) -> CompositionColorBrush {
78        CompositionColorBrush(self.0.CreateColorBrushWithColor(color.0).unwrap())
79    }
80
81    /// Creates a nine-grid brush.
82    pub fn create_nine_grid_brush(&self) -> CompositionNineGridBrush {
83        let compositor: bindings::ICompositor2 = self.0.cast().unwrap();
84        CompositionNineGridBrush(compositor.CreateNineGridBrush().unwrap())
85    }
86
87    /// Creates a shape visual that renders composition shapes.
88    pub fn create_shape_visual(&self) -> ShapeVisual {
89        let compositor: bindings::ICompositor5 = self.0.cast().unwrap();
90        ShapeVisual::new(compositor.CreateShapeVisual().unwrap())
91    }
92
93    /// Creates an empty container shape that groups child shapes.
94    pub fn create_container_shape(&self) -> CompositionContainerShape {
95        let compositor: bindings::ICompositor5 = self.0.cast().unwrap();
96        CompositionContainerShape(compositor.CreateContainerShape().unwrap())
97    }
98
99    /// Creates an ellipse geometry.
100    pub fn create_ellipse_geometry(&self) -> CompositionEllipseGeometry {
101        let compositor: bindings::ICompositor5 = self.0.cast().unwrap();
102        CompositionEllipseGeometry(compositor.CreateEllipseGeometry().unwrap())
103    }
104
105    /// Creates a sprite shape that fills the given geometry with a brush.
106    pub fn create_sprite_shape(
107        &self,
108        geometry: &CompositionEllipseGeometry,
109    ) -> CompositionSpriteShape {
110        let compositor: bindings::ICompositor5 = self.0.cast().unwrap();
111        CompositionSpriteShape(
112            compositor
113                .CreateSpriteShapeWithGeometry(&geometry.as_geometry().0)
114                .unwrap(),
115        )
116    }
117
118    /// Creates a scoped batch that tracks the completion of the given kind of
119    /// work.
120    pub fn create_scoped_batch(&self, kind: BatchKind) -> CompositionScopedBatch {
121        CompositionScopedBatch(self.0.CreateScopedBatch(kind.into()).unwrap())
122    }
123
124    /// Creates a `Vector3` key-frame animation.
125    pub fn create_vector3_key_frame_animation(&self) -> Vector3KeyFrameAnimation {
126        Vector3KeyFrameAnimation(self.0.CreateVector3KeyFrameAnimation().unwrap())
127    }
128
129    /// Creates an empty group whose animations start together.
130    pub fn create_animation_group(&self) -> CompositionAnimationGroup {
131        let compositor: bindings::ICompositor2 = self.0.cast().unwrap();
132        CompositionAnimationGroup(compositor.CreateAnimationGroup().unwrap())
133    }
134
135    /// Creates a scalar (`f32`) key-frame animation.
136    pub fn create_scalar_key_frame_animation(&self) -> ScalarKeyFrameAnimation {
137        ScalarKeyFrameAnimation(self.0.CreateScalarKeyFrameAnimation().unwrap())
138    }
139
140    /// Creates a linear easing function.
141    pub fn create_linear_easing_function(&self) -> CompositionEasingFunction {
142        CompositionEasingFunction(self.0.CreateLinearEasingFunction().unwrap().cast().unwrap())
143    }
144
145    /// Creates a cubic-bezier easing function through the two control points
146    /// (each in `0.0..=1.0`), matching the CSS `cubic-bezier()` convention.
147    pub fn create_cubic_bezier_easing_function(
148        &self,
149        control1: Vector2,
150        control2: Vector2,
151    ) -> CompositionEasingFunction {
152        CompositionEasingFunction(
153            self.0
154                .CreateCubicBezierEasingFunction(control1, control2)
155                .unwrap()
156                .cast()
157                .unwrap(),
158        )
159    }
160
161    /// Creates an empty implicit-animation collection to attach to a visual
162    /// with [`Visual::set_implicit_animations`](crate::Visual::set_implicit_animations).
163    pub fn create_implicit_animation_collection(&self) -> ImplicitAnimationCollection {
164        let compositor: bindings::ICompositor2 = self.0.cast().unwrap();
165        ImplicitAnimationCollection(compositor.CreateImplicitAnimationCollection().unwrap())
166    }
167
168    /// Creates a composition graphics device backed by a Direct2D or DXGI device.
169    #[cfg(feature = "system")]
170    pub fn create_graphics_device(
171        &self,
172        rendering_device: &impl Interface,
173    ) -> Result<CompositionGraphicsDevice> {
174        let interop: bindings::ICompositorInterop = self.0.cast()?;
175        let device: windows_core::IUnknown = rendering_device.cast()?;
176        let graphics = unsafe { interop.CreateGraphicsDevice(&device)? };
177        Ok(CompositionGraphicsDevice(graphics.cast()?))
178    }
179
180    /// Creates a brush that paints a visual with a composition drawing surface.
181    #[cfg(feature = "system")]
182    pub fn create_surface_brush(
183        &self,
184        surface: &CompositionDrawingSurface,
185    ) -> CompositionSurfaceBrush {
186        CompositionSurfaceBrush(
187            self.0
188                .CreateSurfaceBrushWithSurface(&surface.as_surface())
189                .unwrap(),
190        )
191    }
192}