1use super::bindings;
2use super::core::{Point, Size};
3use super::host::*;
4use super::workspace::*;
5
6#[derive(Debug, Clone)]
11pub struct Output {
12 pub position: Point,
14 pub size: Size,
16 pub name: String,
18 pub is_primary: bool,
20 pub num_workspaces: u32,
22 internal: u64,
24}
25
26impl Output {
27 pub fn id(&self) -> u64 {
29 self.internal
30 }
31
32 #[doc(hidden)]
33 pub fn from_c_with_name(value: &bindings::miracle_output_t, name: String) -> Self {
34 Self {
35 position: value.position.into(),
36 size: value.size.into(),
37 name,
38 is_primary: value.is_primary != 0,
39 num_workspaces: value.num_workspaces,
40 internal: value.internal,
41 }
42 }
43
44 pub fn workspaces(&self) -> Vec<Workspace> {
46 (0..self.num_workspaces)
47 .filter_map(|i| self.workspace(i))
48 .collect()
49 }
50
51 pub fn workspace(&self, index: u32) -> Option<Workspace> {
53 if index >= self.num_workspaces {
54 return None;
55 }
56
57 const NAME_BUF_LEN: usize = 256;
58 let mut workspace = std::mem::MaybeUninit::<crate::bindings::miracle_workspace_t>::uninit();
59 let mut name_buf: [u8; NAME_BUF_LEN] = [0; NAME_BUF_LEN];
60
61 unsafe {
62 let result = miracle_output_get_workspace(
63 self.internal as i64,
64 index,
65 workspace.as_mut_ptr() as i32,
66 name_buf.as_mut_ptr() as i32,
67 NAME_BUF_LEN as i32,
68 );
69
70 if result != 0 {
71 return None;
72 }
73
74 let workspace = workspace.assume_init();
75
76 let name_len = name_buf
78 .iter()
79 .position(|&c| c == 0)
80 .unwrap_or(NAME_BUF_LEN);
81 let name = String::from_utf8_lossy(&name_buf[..name_len]).into_owned();
82
83 Some(Workspace::from_c_with_name(&workspace, name))
84 }
85 }
86}