Skip to content

Commit 743b793

Browse files
authored
feat(CGDisplay): add displays_with_point and displays_with_rect (#657)
* feat(CGDisplay): add displays_with_point and displays_with_rect * inline to match other fns in this module * add tests for CGDisplay::displays_with_point and displays_with_rect * refactor: use kCGErrorSuccess
1 parent 6541d9a commit 743b793

File tree

1 file changed

+159
-0
lines changed

1 file changed

+159
-0
lines changed

core-graphics/src/display.rs

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub use crate::geometry::{CGPoint, CGRect, CGSize};
2020
use crate::image::CGImage;
2121
use core_foundation::base::{CFRetain, TCFType};
2222
use core_foundation::string::{CFString, CFStringRef};
23+
use core_graphics_types::base::kCGErrorSuccess;
2324
use foreign_types::{foreign_type, ForeignType};
2425

2526
pub type CGDirectDisplayID = u32;
@@ -177,6 +178,90 @@ impl CGDisplay {
177178
CGDisplay::new(kCGNullDirectDisplayID)
178179
}
179180

181+
/// Return the number of online displays with bounds that include the
182+
/// specified point.
183+
#[inline]
184+
pub fn display_count_with_point(point: CGPoint) -> Result<u32, CGError> {
185+
let mut matching_display_count: u32 = 0;
186+
let result = unsafe {
187+
CGGetDisplaysWithPoint(point, 0, ptr::null_mut(), &mut matching_display_count)
188+
};
189+
if result == kCGErrorSuccess {
190+
Ok(matching_display_count)
191+
} else {
192+
Err(result)
193+
}
194+
}
195+
196+
/// Return a list of online displays with bounds that include the specified
197+
/// point.
198+
#[inline]
199+
pub fn displays_with_point(
200+
point: CGPoint,
201+
max_displays: u32,
202+
) -> Result<(Vec<CGDirectDisplayID>, u32), CGError> {
203+
let count = CGDisplay::display_count_with_point(point)?;
204+
let count = u32::max(u32::min(count, max_displays), 1);
205+
206+
let mut matching_display_count: u32 = 0;
207+
let mut displays: Vec<CGDirectDisplayID> = vec![0; count as usize];
208+
let result = unsafe {
209+
CGGetDisplaysWithPoint(
210+
point,
211+
max_displays,
212+
displays.as_mut_ptr(),
213+
&mut matching_display_count,
214+
)
215+
};
216+
217+
if result == kCGErrorSuccess {
218+
Ok((displays, matching_display_count))
219+
} else {
220+
Err(result)
221+
}
222+
}
223+
224+
/// Return the number of online displays with bounds that intersect the
225+
/// specified rectangle.
226+
#[inline]
227+
pub fn display_count_with_rect(rect: CGRect) -> Result<u32, CGError> {
228+
let mut matching_display_count: u32 = 0;
229+
let result =
230+
unsafe { CGGetDisplaysWithRect(rect, 0, ptr::null_mut(), &mut matching_display_count) };
231+
if result == kCGErrorSuccess {
232+
Ok(matching_display_count)
233+
} else {
234+
Err(result)
235+
}
236+
}
237+
238+
/// Return a list of online displays with bounds that intersect the specified rectangle.
239+
#[inline]
240+
pub fn displays_with_rect(
241+
rect: CGRect,
242+
max_displays: u32,
243+
) -> Result<(Vec<CGDirectDisplayID>, u32), CGError> {
244+
let count = CGDisplay::display_count_with_rect(rect)?;
245+
let count = u32::max(u32::min(count, max_displays), 1);
246+
247+
let mut matching_display_count: u32 = 0;
248+
let mut displays: Vec<CGDirectDisplayID> = vec![0; count as usize];
249+
let result = unsafe {
250+
CGGetDisplaysWithRect(
251+
rect,
252+
max_displays,
253+
displays.as_mut_ptr(),
254+
&mut matching_display_count,
255+
)
256+
};
257+
258+
if result == kCGErrorSuccess {
259+
Ok((displays, matching_display_count))
260+
} else {
261+
Err(result)
262+
}
263+
}
264+
180265
/// Returns the bounds of a display in the global display coordinate space.
181266
#[inline]
182267
pub fn bounds(&self) -> CGRect {
@@ -714,6 +799,12 @@ extern "C" {
714799
active_displays: *mut CGDirectDisplayID,
715800
display_count: *mut u32,
716801
) -> CGError;
802+
pub fn CGGetDisplaysWithPoint(
803+
point: CGPoint,
804+
max_displays: u32,
805+
displays: *mut CGDirectDisplayID,
806+
matching_display_count: *mut u32,
807+
) -> CGError;
717808
pub fn CGGetDisplaysWithRect(
718809
rect: CGRect,
719810
max_displays: u32,
@@ -839,3 +930,71 @@ extern "C" {
839930
imageOptions: CGWindowImageOption,
840931
) -> crate::sys::CGImageRef;
841932
}
933+
934+
#[cfg(test)]
935+
mod test {
936+
use super::*;
937+
938+
#[test]
939+
fn test_display_count_with_point() {
940+
let result = CGDisplay::display_count_with_point(CGPoint::new(0., 0.));
941+
assert!(result.is_ok());
942+
}
943+
944+
#[test]
945+
fn test_displays_with_point_0() {
946+
let result = CGDisplay::displays_with_point(CGPoint::new(0., 0.), 0);
947+
assert!(result.is_ok());
948+
let (displays, count) = result.unwrap();
949+
assert_eq!(displays.len(), count as usize);
950+
}
951+
952+
#[test]
953+
fn test_displays_with_point_5() {
954+
let result = CGDisplay::displays_with_point(CGPoint::new(0., 0.), 5);
955+
assert!(result.is_ok());
956+
let (displays, count) = result.unwrap();
957+
assert_eq!(displays.len(), count as usize);
958+
}
959+
960+
// NOTE: CGMainDisplayID must be called before CGGetDisplaysWithRect to avoid:
961+
// Assertion failed: (did_initialize), function CGS_REQUIRE_INIT, file CGInitialization.c, line 44.
962+
// See https://github.com/JXA-Cookbook/JXA-Cookbook/issues/27#issuecomment-277517668
963+
964+
#[test]
965+
fn test_display_count_with_rect() {
966+
let _ = CGDisplay::main();
967+
968+
let result = CGDisplay::display_count_with_rect(CGRect::new(
969+
&CGPoint::new(10., 10.),
970+
&CGSize::new(100., 100.),
971+
));
972+
assert!(result.is_ok());
973+
}
974+
975+
#[test]
976+
fn test_displays_with_rect_0() {
977+
let _ = CGDisplay::main();
978+
979+
let result = CGDisplay::displays_with_rect(
980+
CGRect::new(&CGPoint::new(0., 0.), &CGSize::new(100., 100.)),
981+
0,
982+
);
983+
assert!(result.is_ok());
984+
let (displays, count) = result.unwrap();
985+
assert_eq!(displays.len(), count as usize);
986+
}
987+
988+
#[test]
989+
fn test_displays_with_rect_5() {
990+
let _ = CGDisplay::main();
991+
992+
let result = CGDisplay::displays_with_rect(
993+
CGRect::new(&CGPoint::new(0., 0.), &CGSize::new(100., 100.)),
994+
5,
995+
);
996+
assert!(result.is_ok());
997+
let (displays, count) = result.unwrap();
998+
assert_eq!(displays.len(), count as usize);
999+
}
1000+
}

0 commit comments

Comments
 (0)