miracle_plugin/
container.rs1use super::bindings;
2use super::host::*;
3use super::window::*;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
7#[repr(u32)]
8pub enum LayoutScheme {
9 #[default]
11 None = 0,
12 Horizontal = 1,
14 Vertical = 2,
16 Tabbed = 3,
18 Stacking = 4,
20}
21
22impl From<LayoutScheme> for bindings::miracle_layout_scheme {
23 fn from(value: LayoutScheme) -> Self {
24 value as bindings::miracle_layout_scheme
25 }
26}
27
28impl TryFrom<bindings::miracle_layout_scheme> for LayoutScheme {
29 type Error = ();
30
31 fn try_from(value: bindings::miracle_layout_scheme) -> Result<Self, Self::Error> {
32 match value {
33 0 => Ok(Self::None),
34 1 => Ok(Self::Horizontal),
35 2 => Ok(Self::Vertical),
36 3 => Ok(Self::Tabbed),
37 4 => Ok(Self::Stacking),
38 _ => Err(()),
39 }
40 }
41}
42
43#[derive(Debug, Clone, Copy)]
45pub struct WindowContainer {
46 pub is_floating: bool,
48 internal: u64,
49}
50
51impl WindowContainer {
52 pub fn window(&self) -> Option<WindowInfo> {
54 const NAME_BUF_LEN: usize = 256;
55 let mut window = std::mem::MaybeUninit::<crate::bindings::miracle_window_info_t>::uninit();
56 let mut name_buf: [u8; NAME_BUF_LEN] = [0; NAME_BUF_LEN];
57
58 unsafe {
59 let result = miracle_container_get_window(
60 self.internal as i64,
61 window.as_mut_ptr() as i32,
62 name_buf.as_mut_ptr() as i32,
63 NAME_BUF_LEN as i32,
64 );
65
66 if result != 0 {
67 return None;
68 }
69
70 let window = window.assume_init();
71
72 let name_len = name_buf
73 .iter()
74 .position(|&c| c == 0)
75 .unwrap_or(NAME_BUF_LEN);
76 let name = String::from_utf8_lossy(&name_buf[..name_len]).into_owned();
77
78 Some(WindowInfo::from_c_with_name(&window, name))
79 }
80 }
81}
82
83#[derive(Debug, Clone, Copy)]
85pub struct ParentContainer {
86 pub is_floating: bool,
88 pub layout_scheme: LayoutScheme,
90 pub num_children: u32,
92 internal: u64,
93}
94
95impl ParentContainer {
96 pub fn child_at(&self, index: u32) -> Option<Container> {
100 if index >= self.num_children {
101 return None;
102 }
103
104 let mut child_container =
105 std::mem::MaybeUninit::<crate::bindings::miracle_container_t>::uninit();
106 unsafe {
107 let result = miracle_container_get_child_at(
108 self.internal as i64,
109 index,
110 child_container.as_mut_ptr() as i32,
111 );
112
113 if result != 0 {
114 return None;
115 }
116
117 let child_container = child_container.assume_init();
118 Some(Container::from(child_container))
119 }
120 }
121
122 pub fn get_children(&self) -> Vec<Container> {
124 (0..self.num_children)
125 .filter_map(|i| self.child_at(i))
126 .collect()
127 }
128}
129
130#[derive(Debug, Clone, Copy)]
136pub enum Container {
137 Window(WindowContainer),
139 Parent(ParentContainer),
141}
142
143impl Container {
144 pub fn id(&self) -> u64 {
146 match self {
147 Container::Window(w) => w.internal,
148 Container::Parent(p) => p.internal,
149 }
150 }
151
152 pub fn is_floating(&self) -> bool {
154 match self {
155 Container::Window(w) => w.is_floating,
156 Container::Parent(p) => p.is_floating,
157 }
158 }
159
160 pub fn parent(&self) -> Option<Container> {
164 let mut parent =
165 std::mem::MaybeUninit::<crate::bindings::miracle_container_t>::uninit();
166
167 unsafe {
168 let result = miracle_container_get_parent(
169 self.id() as i64,
170 parent.as_mut_ptr() as i32,
171 );
172
173 if result != 0 {
174 return None;
175 }
176
177 Some(Container::from(parent.assume_init()))
178 }
179 }
180}
181
182impl From<bindings::miracle_container_t> for Container {
183 fn from(value: bindings::miracle_container_t) -> Self {
184 match value.type_ {
185 1 => Container::Parent(ParentContainer {
186 is_floating: value.is_floating != 0,
187 layout_scheme: LayoutScheme::try_from(value.layout_scheme).unwrap_or_default(),
188 num_children: value.num_child_containers,
189 internal: value.internal,
190 }),
191 _ => Container::Window(WindowContainer {
192 is_floating: value.is_floating != 0,
193 internal: value.internal,
194 }),
195 }
196 }
197}