screencapturekit/shareable_content/
window.rs1use crate::cg::CGRect;
2use crate::utils::ffi_string::{ffi_string_from_buffer, DEFAULT_BUFFER_SIZE};
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
44pub type SCWindowRef = *const c_void;
46
47impl SCWindow {
48 pub(crate) unsafe fn from_ptr(ptr: *const c_void) -> Self {
50 Self(ptr)
51 }
52
53 pub(crate) fn as_ptr(&self) -> *const c_void {
55 self.0
56 }
57
58 pub fn owning_application(&self) -> Option<SCRunningApplication> {
60 unsafe {
61 let app_ptr = crate::ffi::sc_window_get_owning_application(self.0);
62 if app_ptr.is_null() {
63 None
64 } else {
65 Some(SCRunningApplication::from_ptr(app_ptr))
66 }
67 }
68 }
69
70 pub fn window_id(&self) -> u32 {
72 unsafe { crate::ffi::sc_window_get_window_id(self.0) }
73 }
74
75 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_window_get_frame(self.0, &mut x, &mut y, &mut width, &mut height);
83 CGRect::new(x, y, width, height)
84 }
85 }
86
87 pub fn title(&self) -> Option<String> {
89 unsafe {
90 ffi_string_from_buffer(DEFAULT_BUFFER_SIZE, |buf, len| {
91 crate::ffi::sc_window_get_title(self.0, buf, len)
92 })
93 }
94 }
95
96 pub fn window_layer(&self) -> i32 {
98 #[allow(clippy::cast_possible_truncation)]
100 unsafe {
101 crate::ffi::sc_window_get_window_layer(self.0) as i32
102 }
103 }
104
105 pub fn is_on_screen(&self) -> bool {
107 unsafe { crate::ffi::sc_window_is_on_screen(self.0) }
108 }
109
110 pub fn is_active(&self) -> bool {
112 unsafe { crate::ffi::sc_window_is_active(self.0) }
113 }
114}
115
116impl Drop for SCWindow {
117 fn drop(&mut self) {
118 if !self.0.is_null() {
119 unsafe {
120 crate::ffi::sc_window_release(self.0);
121 }
122 }
123 }
124}
125
126impl Clone for SCWindow {
127 fn clone(&self) -> Self {
128 unsafe { Self(crate::ffi::sc_window_retain(self.0)) }
129 }
130}
131
132impl fmt::Debug for SCWindow {
133 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134 f.debug_struct("SCWindow")
135 .field("window_id", &self.window_id())
136 .field("title", &self.title())
137 .field("frame", &self.frame())
138 .field("window_layer", &self.window_layer())
139 .field("is_on_screen", &self.is_on_screen())
140 .field("is_active", &self.is_active())
141 .finish()
142 }
143}
144
145impl fmt::Display for SCWindow {
146 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147 write!(
148 f,
149 "Window {} \"{}\" ({})",
150 self.window_id(),
151 self.title().unwrap_or_else(|| String::from("<untitled>")),
152 self.frame()
153 )
154 }
155}
156
157unsafe impl Send for SCWindow {}
158unsafe impl Sync for SCWindow {}