miracle_plugin/
container.rs1use super::bindings;
2use super::host::*;
3use super::window::*;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
6#[repr(u32)]
7pub enum ContainerType {
8 #[default]
10 Window = 0,
11 Parent = 1,
13}
14
15impl From<ContainerType> for bindings::miracle_container_type {
16 fn from(value: ContainerType) -> Self {
17 value as bindings::miracle_container_type
18 }
19}
20
21impl TryFrom<bindings::miracle_container_type> for ContainerType {
22 type Error = ();
23
24 fn try_from(value: bindings::miracle_container_type) -> Result<Self, Self::Error> {
25 match value {
26 0 => Ok(Self::Window),
27 1 => Ok(Self::Parent),
28 _ => Err(()),
29 }
30 }
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
34#[repr(u32)]
35pub enum LayoutScheme {
36 #[default]
37 None = 0,
38 Horizontal = 1,
39 Vertical = 2,
40 Tabbed = 3,
41 Stacking = 4,
42}
43
44impl From<LayoutScheme> for bindings::miracle_layout_scheme {
45 fn from(value: LayoutScheme) -> Self {
46 value as bindings::miracle_layout_scheme
47 }
48}
49
50impl TryFrom<bindings::miracle_layout_scheme> for LayoutScheme {
51 type Error = ();
52
53 fn try_from(value: bindings::miracle_layout_scheme) -> Result<Self, Self::Error> {
54 match value {
55 0 => Ok(Self::None),
56 1 => Ok(Self::Horizontal),
57 2 => Ok(Self::Vertical),
58 3 => Ok(Self::Tabbed),
59 4 => Ok(Self::Stacking),
60 _ => Err(()),
61 }
62 }
63}
64
65#[derive(Debug, Clone, Copy)]
66pub struct Container {
67 pub container_type: ContainerType,
69 pub is_floating: bool,
71 pub layout_scheme: LayoutScheme,
73 pub num_children: u32,
75 internal: u64,
76}
77
78impl Container {
79 pub fn id(&self) -> u64 {
80 self.internal
81 }
82
83 pub fn child_at(&self, index: u32) -> Option<Container> {
88 if self.container_type != ContainerType::Parent || index >= self.num_children {
89 return None;
90 }
91
92 let mut child_container =
93 std::mem::MaybeUninit::<crate::bindings::miracle_container_t>::uninit();
94 unsafe {
95 let result = miracle_container_get_child_at(
96 self.internal as i64,
97 index,
98 child_container.as_mut_ptr() as i32,
99 );
100
101 if result != 0 {
102 return None;
103 }
104
105 let child_container = child_container.assume_init();
106 Some(Container::from(child_container))
107 }
108 }
109
110 pub fn get_children(&self) -> Vec<Container> {
114 if self.container_type != ContainerType::Parent {
115 return Vec::new();
116 }
117 (0..self.num_children)
118 .filter_map(|i| self.child_at(i))
119 .collect()
120 }
121
122 pub fn window(&self) -> Option<WindowInfo> {
126 if self.container_type != ContainerType::Window {
127 return None;
128 }
129
130 const NAME_BUF_LEN: usize = 256;
131 let mut window = std::mem::MaybeUninit::<crate::bindings::miracle_window_info_t>::uninit();
132 let mut name_buf: [u8; NAME_BUF_LEN] = [0; NAME_BUF_LEN];
133
134 unsafe {
135 let result = miracle_container_get_window(
136 self.internal as i64,
137 window.as_mut_ptr() as i32,
138 name_buf.as_mut_ptr() as i32,
139 NAME_BUF_LEN as i32,
140 );
141
142 if result != 0 {
143 return None;
144 }
145
146 let window = window.assume_init();
147
148 let name_len = name_buf
150 .iter()
151 .position(|&c| c == 0)
152 .unwrap_or(NAME_BUF_LEN);
153 let name = String::from_utf8_lossy(&name_buf[..name_len]).into_owned();
154
155 Some(WindowInfo::from_c_with_name(&window, name))
156 }
157 }
158}
159
160impl From<bindings::miracle_container_t> for Container {
161 fn from(value: bindings::miracle_container_t) -> Self {
162 Self {
163 container_type: ContainerType::try_from(value.type_).unwrap_or_default(),
164 is_floating: value.is_floating != 0,
165 layout_scheme: LayoutScheme::try_from(value.layout_scheme).unwrap_or_default(),
166 num_children: value.num_child_containers,
167 internal: value.internal,
168 }
169 }
170}