1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
use core::ptr;
use std::slice;
use x11::xrandr;
use crate::XHandle;
use crate::XrandrError;
use crate::output::Output;

// A wrapper that drops the pointer if it goes out of scope.
// Avoid having to deal with the various early returns
pub(crate) struct MonitorHandle {
    ptr: ptr::NonNull<xrandr::XRRMonitorInfo>,
    count: i32,
}

impl MonitorHandle {
    pub(crate) fn new(handle: &mut XHandle) -> Result<Self,XrandrError> {
        let mut count = 0;

        let raw_ptr = unsafe {
            xrandr::XRRGetMonitors(
                handle.sys.as_ptr(),
                handle.root(),
                0,
                &mut count,
            )
        };
        
        if count == -1 {
            return Err(XrandrError::GetMonitors);
        }
        
        let ptr = ptr::NonNull::new(raw_ptr)
            .ok_or(XrandrError::GetMonitors)?;

        Ok(Self { ptr, count })
    }

    pub(crate) fn as_slice(&self) -> &[xrandr::XRRMonitorInfo] {
        unsafe { 
            slice::from_raw_parts_mut(
                self.ptr.as_ptr(), 
                self.count as usize
            )
        }
    }
}

impl Drop for MonitorHandle {
    fn drop(&mut self) {
        unsafe { xrandr::XRRFreeMonitors(self.ptr.as_ptr()) };
    }
}

#[derive(Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub struct Monitor {
    pub name: String,
    pub is_primary: bool,
    pub is_automatic: bool,
    pub x: i32,
    pub y: i32,
    pub width_px: i32,
    pub height_px: i32,
    pub width_mm: i32,
    pub height_mm: i32,
    /// An Output describes an actual physical monitor or display. A [`Monitor`]
    /// can have more than one output.
    pub outputs: Vec<Output>,
}