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}