screencapturekit/shareable_content/
display.rs

1use crate::cg::CGRect;
2use core::fmt;
3use std::ffi::c_void;
4
5/// Opaque wrapper around `SCDisplay` from `ScreenCaptureKit`
6///
7/// Represents a physical or virtual display that can be captured.
8///
9/// # Examples
10///
11/// ```no_run
12/// use screencapturekit::shareable_content::SCShareableContent;
13///
14/// # fn example() -> Result<(), Box<dyn std::error::Error>> {
15/// let content = SCShareableContent::get()?;
16/// for display in content.displays() {
17///     println!("Display {}: {}x{}",
18///         display.display_id(),
19///         display.width(),
20///         display.height()
21///     );
22/// }
23/// # Ok(())
24/// # }
25/// ```
26#[repr(transparent)]
27pub struct SCDisplay(*const c_void);
28
29impl PartialEq for SCDisplay {
30    fn eq(&self, other: &Self) -> bool {
31        self.0 == other.0
32    }
33}
34
35impl Eq for SCDisplay {}
36
37impl std::hash::Hash for SCDisplay {
38    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
39        self.0.hash(state);
40    }
41}
42
43/// Raw pointer type for `SCDisplay` (for FFI compatibility)
44pub type SCDisplayRef = *const c_void;
45
46impl SCDisplay {
47    /// Create from raw pointer (used internally by shareable content)
48    pub(crate) unsafe fn from_ptr(ptr: *const c_void) -> Self {
49        Self(ptr)
50    }
51
52    /// Get the raw pointer (used internally)
53    pub(crate) fn as_ptr(&self) -> *const c_void {
54        self.0
55    }
56
57    /// Get display ID
58    ///
59    /// # Examples
60    ///
61    /// ```no_run
62    /// # use screencapturekit::shareable_content::SCShareableContent;
63    /// # fn example() -> Result<(), Box<dyn std::error::Error>> {
64    /// let content = SCShareableContent::get()?;
65    /// if let Some(display) = content.displays().first() {
66    ///     println!("Display ID: {}", display.display_id());
67    /// }
68    /// # Ok(())
69    /// # }
70    /// ```
71    pub fn display_id(&self) -> u32 {
72        unsafe { crate::ffi::sc_display_get_display_id(self.0) }
73    }
74
75    /// Get display frame (position and size)
76    pub fn frame(&self) -> CGRect {
77        unsafe {
78            let mut x = 0.0;
79            let mut y = 0.0;
80            let mut width = 0.0;
81            let mut height = 0.0;
82            crate::ffi::sc_display_get_frame(self.0, &mut x, &mut y, &mut width, &mut height);
83            CGRect::new(x, y, width, height)
84        }
85    }
86
87    /// Get display height in pixels
88    ///
89    /// # Examples
90    ///
91    /// ```no_run
92    /// # use screencapturekit::shareable_content::SCShareableContent;
93    /// # fn example() -> Result<(), Box<dyn std::error::Error>> {
94    /// let content = SCShareableContent::get()?;
95    /// if let Some(display) = content.displays().first() {
96    ///     println!("Display resolution: {}x{}", display.width(), display.height());
97    /// }
98    /// # Ok(())
99    /// # }
100    /// ```
101    pub fn height(&self) -> u32 {
102        // FFI returns isize but display dimensions are always positive and fit in u32
103        #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
104        unsafe {
105            crate::ffi::sc_display_get_height(self.0) as u32
106        }
107    }
108
109    /// Get display width in pixels
110    pub fn width(&self) -> u32 {
111        // FFI returns isize but display dimensions are always positive and fit in u32
112        #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
113        unsafe {
114            crate::ffi::sc_display_get_width(self.0) as u32
115        }
116    }
117}
118
119impl Drop for SCDisplay {
120    fn drop(&mut self) {
121        unsafe {
122            crate::ffi::sc_display_release(self.0);
123        }
124    }
125}
126
127impl Clone for SCDisplay {
128    fn clone(&self) -> Self {
129        unsafe { Self(crate::ffi::sc_display_retain(self.0)) }
130    }
131}
132
133unsafe impl Send for SCDisplay {}
134unsafe impl Sync for SCDisplay {}
135
136impl fmt::Debug for SCDisplay {
137    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138        f.debug_struct("SCDisplay")
139            .field("display_id", &self.display_id())
140            .field("width", &self.width())
141            .field("height", &self.height())
142            .finish()
143    }
144}
145
146impl fmt::Display for SCDisplay {
147    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148        write!(
149            f,
150            "Display {} ({}x{})",
151            self.display_id(),
152            self.width(),
153            self.height()
154        )
155    }
156}