screencapturekit/stream/configuration/
dimensions.rs

1//! Dimension and scaling configuration for stream capture
2//!
3//! This module provides methods to configure the output dimensions, scaling behavior,
4//! and source/destination rectangles for captured streams.
5
6use crate::cg::CGRect;
7
8use super::internal::SCStreamConfiguration;
9
10impl SCStreamConfiguration {
11    /// Set the output width in pixels
12    ///
13    /// The width determines the width of captured frames.
14    ///
15    /// # Examples
16    ///
17    /// ```
18    /// use screencapturekit::prelude::*;
19    ///
20    /// let mut config = SCStreamConfiguration::default();
21    /// config.set_width(1920);
22    /// assert_eq!(config.get_width(), 1920);
23    /// ```
24    pub fn set_width(&mut self, width: u32) {
25        // FFI expects isize; u32 may wrap on 32-bit platforms (acceptable)
26        #[allow(clippy::cast_possible_wrap)]
27        unsafe {
28            crate::ffi::sc_stream_configuration_set_width(self.as_ptr(), width as isize);
29        }
30    }
31
32    /// Get the configured output width in pixels
33    ///
34    /// # Examples
35    ///
36    /// ```
37    /// use screencapturekit::prelude::*;
38    ///
39    /// let mut config = SCStreamConfiguration::default();
40    /// config.set_width(1920);
41    /// assert_eq!(config.get_width(), 1920);
42    /// ```
43    pub fn get_width(&self) -> u32 {
44        // FFI returns isize but width is always positive and fits in u32
45        #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
46        unsafe {
47            crate::ffi::sc_stream_configuration_get_width(self.as_ptr()) as u32
48        }
49    }
50
51    /// Set the output height in pixels
52    ///
53    /// The height determines the height of captured frames.
54    ///
55    /// # Examples
56    ///
57    /// ```
58    /// use screencapturekit::prelude::*;
59    ///
60    /// let mut config = SCStreamConfiguration::default();
61    /// config.set_height(1080);
62    /// assert_eq!(config.get_height(), 1080);
63    /// ```
64    pub fn set_height(&mut self, height: u32) {
65        // FFI expects isize; u32 may wrap on 32-bit platforms (acceptable)
66        #[allow(clippy::cast_possible_wrap)]
67        unsafe {
68            crate::ffi::sc_stream_configuration_set_height(self.as_ptr(), height as isize);
69        }
70    }
71
72    /// Get the configured output height in pixels
73    ///
74    /// # Examples
75    ///
76    /// ```
77    /// use screencapturekit::prelude::*;
78    ///
79    /// let mut config = SCStreamConfiguration::default();
80    /// config.set_height(1080);
81    /// assert_eq!(config.get_height(), 1080);
82    /// ```
83    pub fn get_height(&self) -> u32 {
84        // FFI returns isize but height is always positive and fits in u32
85        #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
86        unsafe {
87            crate::ffi::sc_stream_configuration_get_height(self.as_ptr()) as u32
88        }
89    }
90
91    /// Enable or disable scaling to fit the output dimensions
92    ///
93    /// When enabled, the source content will be scaled to fit within the
94    /// configured width and height, potentially changing aspect ratio.
95    ///
96    /// # Examples
97    ///
98    /// ```
99    /// use screencapturekit::prelude::*;
100    ///
101    /// let mut config = SCStreamConfiguration::default();
102    /// config.set_scales_to_fit(true);
103    /// assert!(config.get_scales_to_fit());
104    /// ```
105    pub fn set_scales_to_fit(&mut self, scales_to_fit: bool) {
106        unsafe {
107            crate::ffi::sc_stream_configuration_set_scales_to_fit(self.as_ptr(), scales_to_fit);
108        }
109    }
110
111    /// Check if scaling to fit is enabled
112    pub fn get_scales_to_fit(&self) -> bool {
113        unsafe { crate::ffi::sc_stream_configuration_get_scales_to_fit(self.as_ptr()) }
114    }
115
116    /// Set the source rectangle to capture
117    ///
118    /// Defines which portion of the source content to capture. Coordinates are
119    /// relative to the source content's coordinate system.
120    ///
121    /// # Examples
122    ///
123    /// ```
124    /// use screencapturekit::prelude::*;
125    /// use screencapturekit::cg::CGRect;
126    ///
127    /// // Capture only top-left quarter of screen
128    /// let rect = CGRect::new(0.0, 0.0, 960.0, 540.0);
129    /// let mut config = SCStreamConfiguration::default();
130    /// config.set_source_rect(rect);
131    /// ```
132    pub fn set_source_rect(&mut self, source_rect: CGRect) {
133        unsafe {
134            crate::ffi::sc_stream_configuration_set_source_rect(
135                self.as_ptr(),
136                source_rect.x,
137                source_rect.y,
138                source_rect.width,
139                source_rect.height,
140            );
141        }
142    }
143
144    /// Get the configured source rectangle
145    pub fn get_source_rect(&self) -> CGRect {
146        unsafe {
147            let mut x = 0.0;
148            let mut y = 0.0;
149            let mut width = 0.0;
150            let mut height = 0.0;
151            crate::ffi::sc_stream_configuration_get_source_rect(
152                self.as_ptr(),
153                &mut x,
154                &mut y,
155                &mut width,
156                &mut height,
157            );
158            CGRect::new(x, y, width, height)
159        }
160    }
161
162    /// Set the destination rectangle for captured content
163    ///
164    /// Defines where the captured content will be placed in the output frame.
165    /// Useful for picture-in-picture or multi-source compositions.
166    ///
167    /// # Examples
168    ///
169    /// ```
170    /// use screencapturekit::prelude::*;
171    /// use screencapturekit::cg::CGRect;
172    ///
173    /// // Place captured content in top-left corner
174    /// let rect = CGRect::new(0.0, 0.0, 640.0, 480.0);
175    /// let mut config = SCStreamConfiguration::default();
176    /// config.set_destination_rect(rect);
177    /// ```
178    pub fn set_destination_rect(&mut self, destination_rect: CGRect) {
179        unsafe {
180            crate::ffi::sc_stream_configuration_set_destination_rect(
181                self.as_ptr(),
182                destination_rect.x,
183                destination_rect.y,
184                destination_rect.width,
185                destination_rect.height,
186            );
187        }
188    }
189
190    /// Get the configured destination rectangle
191    pub fn get_destination_rect(&self) -> CGRect {
192        unsafe {
193            let mut x = 0.0;
194            let mut y = 0.0;
195            let mut width = 0.0;
196            let mut height = 0.0;
197            crate::ffi::sc_stream_configuration_get_destination_rect(
198                self.as_ptr(),
199                &mut x,
200                &mut y,
201                &mut width,
202                &mut height,
203            );
204            CGRect::new(x, y, width, height)
205        }
206    }
207
208    /// Preserve aspect ratio when scaling
209    ///
210    /// When enabled, the content will be scaled while maintaining its original
211    /// aspect ratio, potentially adding letterboxing or pillarboxing.
212    ///
213    /// Note: This property requires macOS 14.0+. On older versions, the setter
214    /// is a no-op and the getter returns `false`.
215    ///
216    /// # Examples
217    ///
218    /// ```
219    /// use screencapturekit::prelude::*;
220    ///
221    /// let mut config = SCStreamConfiguration::default();
222    /// config.set_preserves_aspect_ratio(true);
223    /// // Returns true on macOS 14.0+, false on older versions
224    /// let _ = config.get_preserves_aspect_ratio();
225    /// ```
226    pub fn set_preserves_aspect_ratio(&mut self, preserves_aspect_ratio: bool) {
227        unsafe {
228            crate::ffi::sc_stream_configuration_set_preserves_aspect_ratio(
229                self.as_ptr(),
230                preserves_aspect_ratio,
231            );
232        }
233    }
234
235    /// Check if aspect ratio preservation is enabled
236    pub fn get_preserves_aspect_ratio(&self) -> bool {
237        unsafe { crate::ffi::sc_stream_configuration_get_preserves_aspect_ratio(self.as_ptr()) }
238    }
239
240    /// Preserve aspect ratio when scaling (alternative API)
241    ///
242    /// This is an alternative to `set_preserves_aspect_ratio` for compatibility.
243    pub fn set_preserve_aspect_ratio(&mut self, preserve_aspect_ratio: bool) {
244        unsafe {
245            crate::ffi::sc_stream_configuration_set_preserve_aspect_ratio(
246                self.as_ptr(),
247                preserve_aspect_ratio,
248            );
249        }
250    }
251
252    /// Check if aspect ratio preservation is enabled (alternative API)
253    pub fn get_preserve_aspect_ratio(&self) -> bool {
254        unsafe { crate::ffi::sc_stream_configuration_get_preserve_aspect_ratio(self.as_ptr()) }
255    }
256
257    /// Enable or disable increased resolution for Retina displays
258    ///
259    /// When enabled, the captured content will be scaled up to match the backing
260    /// scale factor of Retina displays, providing higher quality output.
261    /// Available on macOS 13.0+
262    ///
263    /// # Examples
264    ///
265    /// ```
266    /// use screencapturekit::prelude::*;
267    ///
268    /// let mut config = SCStreamConfiguration::default();
269    /// config.set_increase_resolution_for_retina_displays(true);
270    /// // Note: Getter may not return the set value on all macOS versions
271    /// let _ = config.get_increase_resolution_for_retina_displays();
272    /// ```
273    pub fn set_increase_resolution_for_retina_displays(&mut self, increase_resolution: bool) {
274        unsafe {
275            crate::ffi::sc_stream_configuration_set_increase_resolution_for_retina_displays(
276                self.as_ptr(),
277                increase_resolution,
278            );
279        }
280    }
281
282    /// Check if increased resolution for Retina displays is enabled
283    pub fn get_increase_resolution_for_retina_displays(&self) -> bool {
284        unsafe {
285            crate::ffi::sc_stream_configuration_get_increase_resolution_for_retina_displays(
286                self.as_ptr(),
287            )
288        }
289    }
290}