1use super::application::*;
2use super::bindings;
3use super::container::*;
4use super::core::{self, *};
5use super::host::*;
6use super::workspace::*;
7use glam::Mat4;
8
9#[doc(hidden)]
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11#[repr(u32)]
12pub enum WindowAttrib {
13 Type = 0,
14 State = 1,
15 Focus = 3,
16 Dpi = 4,
17 Visibility = 5,
18 PreferredOrientation = 6,
19}
20
21impl From<WindowAttrib> for bindings::MirWindowAttrib {
22 fn from(value: WindowAttrib) -> Self {
23 value as bindings::MirWindowAttrib
24 }
25}
26
27impl TryFrom<bindings::MirWindowAttrib> for WindowAttrib {
28 type Error = ();
29
30 fn try_from(value: bindings::MirWindowAttrib) -> Result<Self, Self::Error> {
31 match value {
32 0 => Ok(Self::Type),
33 1 => Ok(Self::State),
34 3 => Ok(Self::Focus),
35 4 => Ok(Self::Dpi),
36 5 => Ok(Self::Visibility),
37 6 => Ok(Self::PreferredOrientation),
38 _ => Err(()),
39 }
40 }
41}
42
43#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
45#[repr(u32)]
46pub enum WindowType {
47 #[default]
49 Normal = 0,
50 Utility = 1,
52 Dialog = 2,
54 Gloss = 3,
56 Freestyle = 4,
58 Menu = 5,
60 InputMethod = 6,
62 Satellite = 7,
64 Tip = 8,
66 Decoration = 9,
68}
69
70impl From<WindowType> for bindings::MirWindowType {
71 fn from(value: WindowType) -> Self {
72 value as bindings::MirWindowType
73 }
74}
75
76impl TryFrom<bindings::MirWindowType> for WindowType {
77 type Error = ();
78
79 fn try_from(value: bindings::MirWindowType) -> Result<Self, Self::Error> {
80 match value {
81 0 => Ok(Self::Normal),
82 1 => Ok(Self::Utility),
83 2 => Ok(Self::Dialog),
84 3 => Ok(Self::Gloss),
85 4 => Ok(Self::Freestyle),
86 5 => Ok(Self::Menu),
87 6 => Ok(Self::InputMethod),
88 7 => Ok(Self::Satellite),
89 8 => Ok(Self::Tip),
90 9 => Ok(Self::Decoration),
91 _ => Err(()),
92 }
93 }
94}
95
96#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
98#[repr(u32)]
99pub enum WindowState {
100 #[default]
101 Unknown = 0,
102 Restored = 1,
103 Minimized = 2,
104 Maximized = 3,
105 VertMaximized = 4,
106 Fullscreen = 5,
107 HorizMaximized = 6,
108 Hidden = 7,
109 Attached = 8,
111}
112
113impl From<WindowState> for bindings::MirWindowState {
114 fn from(value: WindowState) -> Self {
115 value as bindings::MirWindowState
116 }
117}
118
119impl TryFrom<bindings::MirWindowState> for WindowState {
120 type Error = ();
121
122 fn try_from(value: bindings::MirWindowState) -> Result<Self, Self::Error> {
123 match value {
124 0 => Ok(Self::Unknown),
125 1 => Ok(Self::Restored),
126 2 => Ok(Self::Minimized),
127 3 => Ok(Self::Maximized),
128 4 => Ok(Self::VertMaximized),
129 5 => Ok(Self::Fullscreen),
130 6 => Ok(Self::HorizMaximized),
131 7 => Ok(Self::Hidden),
132 8 => Ok(Self::Attached),
133 _ => Err(()),
134 }
135 }
136}
137
138#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
140#[repr(u32)]
141pub enum WindowFocusState {
142 #[default]
144 Unfocused = 0,
145 Focused = 1,
147 Active = 2,
149}
150
151impl From<WindowFocusState> for bindings::MirWindowFocusState {
152 fn from(value: WindowFocusState) -> Self {
153 value as bindings::MirWindowFocusState
154 }
155}
156
157impl TryFrom<bindings::MirWindowFocusState> for WindowFocusState {
158 type Error = ();
159
160 fn try_from(value: bindings::MirWindowFocusState) -> Result<Self, Self::Error> {
161 match value {
162 0 => Ok(Self::Unfocused),
163 1 => Ok(Self::Focused),
164 2 => Ok(Self::Active),
165 _ => Err(()),
166 }
167 }
168}
169
170#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
172#[repr(u32)]
173pub enum WindowVisibility {
174 #[default]
176 Occluded = 0,
177 Exposed = 1,
179}
180
181impl From<WindowVisibility> for bindings::MirWindowVisibility {
182 fn from(value: WindowVisibility) -> Self {
183 value as bindings::MirWindowVisibility
184 }
185}
186
187impl TryFrom<bindings::MirWindowVisibility> for WindowVisibility {
188 type Error = ();
189
190 fn try_from(value: bindings::MirWindowVisibility) -> Result<Self, Self::Error> {
191 match value {
192 0 => Ok(Self::Occluded),
193 1 => Ok(Self::Exposed),
194 _ => Err(()),
195 }
196 }
197}
198
199#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
201#[repr(u32)]
202pub enum DepthLayer {
203 Background = 0,
205 Below = 1,
207 #[default]
209 Application = 2,
210 AlwaysOnTop = 3,
212 Above = 4,
214 Overlay = 5,
216}
217
218impl From<DepthLayer> for bindings::MirDepthLayer {
219 fn from(value: DepthLayer) -> Self {
220 value as bindings::MirDepthLayer
221 }
222}
223
224impl TryFrom<bindings::MirDepthLayer> for DepthLayer {
225 type Error = ();
226
227 fn try_from(value: bindings::MirDepthLayer) -> Result<Self, Self::Error> {
228 match value {
229 0 => Ok(Self::Background),
230 1 => Ok(Self::Below),
231 2 => Ok(Self::Application),
232 3 => Ok(Self::AlwaysOnTop),
233 4 => Ok(Self::Above),
234 5 => Ok(Self::Overlay),
235 _ => Err(()),
236 }
237 }
238}
239
240#[derive(Debug)]
245pub struct WindowInfo {
246 pub window_type: WindowType,
248 pub state: WindowState,
250 pub top_left: Point,
252 pub size: Size,
254 pub depth_layer: DepthLayer,
256 pub name: String,
258 pub transform: Mat4,
260 pub alpha: f32,
262 internal: u64,
264}
265
266impl WindowInfo {
267 #[doc(hidden)]
268 pub unsafe fn from_c_with_name(value: &bindings::miracle_window_info_t, name: String) -> Self {
269 Self {
270 window_type: WindowType::try_from(value.window_type).unwrap_or_default(),
271 state: WindowState::try_from(value.state).unwrap_or_default(),
272 top_left: value.top_left.into(),
273 size: value.size.into(),
274 depth_layer: DepthLayer::try_from(value.depth_layer).unwrap_or_default(),
275 name,
276 transform: core::mat4_from_f32_array(value.transform),
277 alpha: value.alpha,
278 internal: value.internal,
279 }
280 }
281
282 pub fn id(&self) -> u64 {
287 self.internal
288 }
289
290 pub fn application(&self) -> Option<ApplicationInfo> {
292 const NAME_BUF_LEN: usize = 256;
293 let mut name_buf: [u8; NAME_BUF_LEN] = [0; NAME_BUF_LEN];
294
295 unsafe {
296 let internal = miracle_window_info_get_application(
297 self.internal as i64,
298 name_buf.as_mut_ptr() as i32,
299 NAME_BUF_LEN as i32,
300 );
301
302 if internal == -1 {
303 return None;
304 }
305
306 let name_len = name_buf
308 .iter()
309 .position(|&c| c == 0)
310 .unwrap_or(NAME_BUF_LEN);
311 let name = String::from_utf8_lossy(&name_buf[..name_len]).into_owned();
312
313 Some(ApplicationInfo {
314 name,
315 internal: internal as u64,
316 })
317 }
318 }
319
320 pub fn container(&self) -> Option<Container> {
322 let mut container =
323 std::mem::MaybeUninit::<crate::bindings::miracle_container_t>::uninit();
324
325 unsafe {
326 let result = miracle_window_info_get_container(
327 self.internal as i64,
328 container.as_mut_ptr() as i32,
329 );
330
331 if result != 0 {
332 return None;
333 }
334
335 Some(Container::from(container.assume_init()))
336 }
337 }
338
339 pub fn workspace(&self) -> Option<Workspace> {
341 const NAME_BUF_LEN: usize = 256;
342 let mut workspace = std::mem::MaybeUninit::<crate::bindings::miracle_workspace_t>::uninit();
343 let mut name_buf: [u8; NAME_BUF_LEN] = [0; NAME_BUF_LEN];
344
345 unsafe {
346 let result = miracle_window_info_get_workspace(
347 self.internal as i64,
348 workspace.as_mut_ptr() as i32,
349 name_buf.as_mut_ptr() as i32,
350 NAME_BUF_LEN as i32,
351 );
352
353 if result != 0 {
354 return None;
355 }
356
357 let workspace = workspace.assume_init();
358 if workspace.is_set == 0 {
359 return None;
360 }
361
362 let name_len = name_buf
364 .iter()
365 .position(|&c| c == 0)
366 .unwrap_or(NAME_BUF_LEN);
367 let name = String::from_utf8_lossy(&name_buf[..name_len]).into_owned();
368
369 Some(Workspace::from_c_with_name(&workspace, name))
370 }
371 }
372}
373
374impl PartialEq for WindowInfo {
375 fn eq(&self, other: &Self) -> bool {
376 self.internal == other.internal
377 }
378}
379
380#[derive(Debug)]
386pub struct PluginWindow {
387 info: WindowInfo,
388}
389
390impl PluginWindow {
391 #[doc(hidden)]
392 pub fn from_window_info(info: WindowInfo) -> Self {
393 Self { info }
394 }
395
396 pub fn set_state(&self, state: WindowState) -> Result<(), ()> {
398 let r = unsafe { miracle_window_set_state(self.info.internal as i64, state as i32) };
399 if r == 0 { Ok(()) } else { Err(()) }
400 }
401
402 pub fn set_workspace(&self, workspace: &Workspace) -> Result<(), ()> {
404 let r = unsafe {
405 miracle_window_set_workspace(self.info.internal as i64, workspace.id() as i64)
406 };
407 if r == 0 { Ok(()) } else { Err(()) }
408 }
409
410 pub fn set_rectangle(&self, rect: Rectangle, animate: bool) -> Result<(), ()> {
412 let r = unsafe {
413 miracle_window_set_rectangle(
414 self.info.internal as i64,
415 rect.x,
416 rect.y,
417 rect.width,
418 rect.height,
419 if animate { 1 } else { 0 },
420 )
421 };
422 if r == 0 { Ok(()) } else { Err(()) }
423 }
424
425 pub fn set_transform(&self, transform: Mat4) -> Result<(), ()> {
427 let arr = transform.to_cols_array();
428 let r =
429 unsafe { miracle_window_set_transform(self.info.internal as i64, arr.as_ptr() as i32) };
430 if r == 0 { Ok(()) } else { Err(()) }
431 }
432
433 pub fn set_alpha(&self, alpha: f32) -> Result<(), ()> {
435 let r = unsafe {
436 miracle_window_set_alpha(self.info.internal as i64, (&alpha as *const f32) as i32)
437 };
438 if r == 0 { Ok(()) } else { Err(()) }
439 }
440
441 pub fn request_focus(&self) -> Result<(), ()> {
443 let r = unsafe { miracle_window_request_focus(self.info.internal as i64) };
444 if r == 0 { Ok(()) } else { Err(()) }
445 }
446}
447
448impl std::ops::Deref for PluginWindow {
449 type Target = WindowInfo;
450
451 fn deref(&self) -> &Self::Target {
452 &self.info
453 }
454}
455
456impl PartialEq for PluginWindow {
457 fn eq(&self, other: &Self) -> bool {
458 self.info == other.info
459 }
460}