miracle_plugin/
placement.rs

1use super::bindings;
2use super::container::*;
3use super::core::*;
4use super::window::*;
5use super::workspace::*;
6use glam::Mat4;
7
8/// Placement parameters for a tiled window.
9///
10/// Used with [`Placement::Tiled`].
11#[derive(Debug, Clone, Default)]
12pub struct TiledPlacement {
13    /// The parent container.
14    pub parent: Option<Container>,
15    /// The index at which to place the container.
16    pub index: u32,
17    /// The requested layout scheme.
18    pub layout_scheme: LayoutScheme,
19}
20
21impl From<TiledPlacement> for bindings::miracle_tiled_placement_t {
22    fn from(value: TiledPlacement) -> Self {
23        Self {
24            parent_internal: value.parent.map_or(0, |c| c.id()),
25            index: value.index,
26            layout_scheme: value.layout_scheme.into(),
27        }
28    }
29}
30
31/// Freestyle placement configuration.
32#[derive(Debug, Clone)]
33pub struct FreestylePlacement {
34    /// The top left position.
35    pub top_left: Point,
36    /// The depth layer.
37    pub depth_layer: DepthLayer,
38    /// The workspace
39    pub workspace: Option<Workspace>,
40    /// The size.
41    pub size: Size,
42    /// The 4x4 transform matrix applied to the window (column-major).
43    ///
44    /// Defaults to the identity matrix.
45    pub transform: Mat4,
46    /// The alpha (opacity) of the window.
47    ///
48    /// Defaults to 1.0 (fully opaque).
49    pub alpha: f32,
50    /// Whether the window can be resized.
51    ///
52    /// Defaults to true.
53    pub resizable: bool,
54    /// Whether the window can be moved.
55    ///
56    /// Defaults to true.
57    pub movable: bool,
58}
59
60impl Default for FreestylePlacement {
61    fn default() -> Self {
62        Self {
63            top_left: Point::default(),
64            depth_layer: DepthLayer::default(),
65            workspace: None,
66            size: Size::default(),
67            transform: Mat4::IDENTITY,
68            alpha: 1.0,
69            resizable: true,
70            movable: true,
71        }
72    }
73}
74
75impl From<FreestylePlacement> for bindings::miracle_freestyle_placement_t {
76    fn from(value: FreestylePlacement) -> Self {
77        Self {
78            top_left: value.top_left.into(),
79            depth_layer: value.depth_layer.into(),
80            workspace_internal: value.workspace.map_or(0, |w| w.id()),
81            size: value.size.into(),
82            transform: mat4_to_f32_array(value.transform),
83            alpha: value.alpha,
84            resizable: value.resizable as i32,
85            movable: value.movable as i32,
86        }
87    }
88}
89
90/// Complete placement specification returned from [`crate::plugin::Plugin::place_new_window`].
91#[derive(Debug, Clone)]
92pub enum Placement {
93    /// Window will be placed in the tiling grid.
94    Tiled(TiledPlacement),
95    /// Window behavior is entirely determined by the plugin.
96    Freestyle(FreestylePlacement),
97}
98
99impl From<Placement> for bindings::miracle_placement_t {
100    fn from(value: Placement) -> Self {
101        match value {
102            Placement::Tiled(tiled) => Self {
103                strategy: bindings::miracle_window_management_strategy_t_miracle_window_management_strategy_tiled,
104                freestyle_placement: Default::default(),
105                tiled_placement: tiled.into(),
106            },
107            Placement::Freestyle(freestyle) => Self {
108                strategy: bindings::miracle_window_management_strategy_t_miracle_window_management_strategy_freestyle,
109                freestyle_placement: freestyle.into(),
110                tiled_placement: Default::default(),
111            },
112        }
113    }
114}