screencapturekit/shareable_content/
window.rs1use crate::cg::CGRect;
2use crate::utils::ffi_string::ffi_string_owned;
3use core::fmt;
4use std::ffi::c_void;
5
6use super::SCRunningApplication;
7
8#[repr(transparent)]
28pub struct SCWindow(*const c_void);
29
30impl PartialEq for SCWindow {
31 fn eq(&self, other: &Self) -> bool {
32 self.0 == other.0
33 }
34}
35
36impl Eq for SCWindow {}
37
38impl std::hash::Hash for SCWindow {
39 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
40 self.0.hash(state);
41 }
42}
43
44impl SCWindow {
45 pub(crate) unsafe fn from_ptr(ptr: *const c_void) -> Self {
47 Self(ptr)
48 }
49
50 pub(crate) unsafe fn from_retained_ptr(ptr: *const c_void) -> Option<Self> {
56 if ptr.is_null() {
57 None
58 } else {
59 Some(unsafe { Self::from_ptr(ptr) })
60 }
61 }
62
63 pub(crate) fn as_ptr(&self) -> *const c_void {
65 self.0
66 }
67
68 pub fn owning_application(&self) -> Option<SCRunningApplication> {
70 unsafe {
71 let app_ptr = crate::ffi::sc_window_get_owning_application(self.0);
72 SCRunningApplication::from_retained_ptr(app_ptr)
73 }
74 }
75
76 pub fn window_id(&self) -> u32 {
78 unsafe { crate::ffi::sc_window_get_window_id(self.0) }
79 }
80
81 pub fn frame(&self) -> CGRect {
83 let mut x = 0.0;
84 let mut y = 0.0;
85 let mut width = 0.0;
86 let mut height = 0.0;
87 unsafe {
88 crate::ffi::sc_window_get_frame_packed(
89 self.0,
90 &raw mut x,
91 &raw mut y,
92 &raw mut width,
93 &raw mut height,
94 );
95 }
96 CGRect::new(x, y, width, height)
97 }
98
99 pub fn title(&self) -> Option<String> {
101 unsafe { ffi_string_owned(|| crate::ffi::sc_window_get_title_owned(self.0)) }
102 }
103
104 pub fn window_layer(&self) -> i32 {
106 #[allow(clippy::cast_possible_truncation)]
108 unsafe {
109 crate::ffi::sc_window_get_window_layer(self.0) as i32
110 }
111 }
112
113 pub fn is_on_screen(&self) -> bool {
115 unsafe { crate::ffi::sc_window_is_on_screen(self.0) }
116 }
117
118 #[cfg(feature = "macos_13_0")]
124 pub fn is_active(&self) -> bool {
125 unsafe { crate::ffi::sc_window_is_active(self.0) }
126 }
127}
128
129crate::utils::retained::sc_retained!(
130 SCWindow,
131 retain = crate::ffi::sc_window_retain,
132 release = crate::ffi::sc_window_release,
133);
134
135impl fmt::Debug for SCWindow {
136 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137 let mut debug = f.debug_struct("SCWindow");
138 debug
139 .field("window_id", &self.window_id())
140 .field("title", &self.title())
141 .field("frame", &self.frame())
142 .field("window_layer", &self.window_layer())
143 .field("is_on_screen", &self.is_on_screen());
144 #[cfg(feature = "macos_13_0")]
145 debug.field("is_active", &self.is_active());
146 debug.finish()
147 }
148}
149
150impl fmt::Display for SCWindow {
151 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152 write!(
153 f,
154 "Window {} \"{}\" ({})",
155 self.window_id(),
156 self.title().unwrap_or_else(|| String::from("<untitled>")),
157 self.frame()
158 )
159 }
160}
161
162unsafe impl Send for SCWindow {}
166unsafe impl Sync for SCWindow {}