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
This commit is contained in:
@@ -20,6 +20,7 @@ pub use crate::geometry::{CGPoint, CGRect, CGSize};
|
||||
use crate::image::CGImage;
|
||||
use core_foundation::base::{CFRetain, TCFType};
|
||||
use core_foundation::string::{CFString, CFStringRef};
|
||||
use core_graphics_types::base::kCGErrorSuccess;
|
||||
use foreign_types::{foreign_type, ForeignType};
|
||||
|
||||
pub type CGDirectDisplayID = u32;
|
||||
@@ -177,6 +178,90 @@ impl CGDisplay {
|
||||
CGDisplay::new(kCGNullDirectDisplayID)
|
||||
}
|
||||
|
||||
/// Return the number of online displays with bounds that include the
|
||||
/// specified point.
|
||||
#[inline]
|
||||
pub fn display_count_with_point(point: CGPoint) -> Result<u32, CGError> {
|
||||
let mut matching_display_count: u32 = 0;
|
||||
let result = unsafe {
|
||||
CGGetDisplaysWithPoint(point, 0, ptr::null_mut(), &mut matching_display_count)
|
||||
};
|
||||
if result == kCGErrorSuccess {
|
||||
Ok(matching_display_count)
|
||||
} else {
|
||||
Err(result)
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a list of online displays with bounds that include the specified
|
||||
/// point.
|
||||
#[inline]
|
||||
pub fn displays_with_point(
|
||||
point: CGPoint,
|
||||
max_displays: u32,
|
||||
) -> Result<(Vec<CGDirectDisplayID>, u32), CGError> {
|
||||
let count = CGDisplay::display_count_with_point(point)?;
|
||||
let count = u32::max(u32::min(count, max_displays), 1);
|
||||
|
||||
let mut matching_display_count: u32 = 0;
|
||||
let mut displays: Vec<CGDirectDisplayID> = vec![0; count as usize];
|
||||
let result = unsafe {
|
||||
CGGetDisplaysWithPoint(
|
||||
point,
|
||||
max_displays,
|
||||
displays.as_mut_ptr(),
|
||||
&mut matching_display_count,
|
||||
)
|
||||
};
|
||||
|
||||
if result == kCGErrorSuccess {
|
||||
Ok((displays, matching_display_count))
|
||||
} else {
|
||||
Err(result)
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the number of online displays with bounds that intersect the
|
||||
/// specified rectangle.
|
||||
#[inline]
|
||||
pub fn display_count_with_rect(rect: CGRect) -> Result<u32, CGError> {
|
||||
let mut matching_display_count: u32 = 0;
|
||||
let result =
|
||||
unsafe { CGGetDisplaysWithRect(rect, 0, ptr::null_mut(), &mut matching_display_count) };
|
||||
if result == kCGErrorSuccess {
|
||||
Ok(matching_display_count)
|
||||
} else {
|
||||
Err(result)
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a list of online displays with bounds that intersect the specified rectangle.
|
||||
#[inline]
|
||||
pub fn displays_with_rect(
|
||||
rect: CGRect,
|
||||
max_displays: u32,
|
||||
) -> Result<(Vec<CGDirectDisplayID>, u32), CGError> {
|
||||
let count = CGDisplay::display_count_with_rect(rect)?;
|
||||
let count = u32::max(u32::min(count, max_displays), 1);
|
||||
|
||||
let mut matching_display_count: u32 = 0;
|
||||
let mut displays: Vec<CGDirectDisplayID> = vec![0; count as usize];
|
||||
let result = unsafe {
|
||||
CGGetDisplaysWithRect(
|
||||
rect,
|
||||
max_displays,
|
||||
displays.as_mut_ptr(),
|
||||
&mut matching_display_count,
|
||||
)
|
||||
};
|
||||
|
||||
if result == kCGErrorSuccess {
|
||||
Ok((displays, matching_display_count))
|
||||
} else {
|
||||
Err(result)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the bounds of a display in the global display coordinate space.
|
||||
#[inline]
|
||||
pub fn bounds(&self) -> CGRect {
|
||||
@@ -714,6 +799,12 @@ extern "C" {
|
||||
active_displays: *mut CGDirectDisplayID,
|
||||
display_count: *mut u32,
|
||||
) -> CGError;
|
||||
pub fn CGGetDisplaysWithPoint(
|
||||
point: CGPoint,
|
||||
max_displays: u32,
|
||||
displays: *mut CGDirectDisplayID,
|
||||
matching_display_count: *mut u32,
|
||||
) -> CGError;
|
||||
pub fn CGGetDisplaysWithRect(
|
||||
rect: CGRect,
|
||||
max_displays: u32,
|
||||
@@ -839,3 +930,71 @@ extern "C" {
|
||||
imageOptions: CGWindowImageOption,
|
||||
) -> crate::sys::CGImageRef;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_display_count_with_point() {
|
||||
let result = CGDisplay::display_count_with_point(CGPoint::new(0., 0.));
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_displays_with_point_0() {
|
||||
let result = CGDisplay::displays_with_point(CGPoint::new(0., 0.), 0);
|
||||
assert!(result.is_ok());
|
||||
let (displays, count) = result.unwrap();
|
||||
assert_eq!(displays.len(), count as usize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_displays_with_point_5() {
|
||||
let result = CGDisplay::displays_with_point(CGPoint::new(0., 0.), 5);
|
||||
assert!(result.is_ok());
|
||||
let (displays, count) = result.unwrap();
|
||||
assert_eq!(displays.len(), count as usize);
|
||||
}
|
||||
|
||||
// NOTE: CGMainDisplayID must be called before CGGetDisplaysWithRect to avoid:
|
||||
// Assertion failed: (did_initialize), function CGS_REQUIRE_INIT, file CGInitialization.c, line 44.
|
||||
// See https://github.com/JXA-Cookbook/JXA-Cookbook/issues/27#issuecomment-277517668
|
||||
|
||||
#[test]
|
||||
fn test_display_count_with_rect() {
|
||||
let _ = CGDisplay::main();
|
||||
|
||||
let result = CGDisplay::display_count_with_rect(CGRect::new(
|
||||
&CGPoint::new(10., 10.),
|
||||
&CGSize::new(100., 100.),
|
||||
));
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_displays_with_rect_0() {
|
||||
let _ = CGDisplay::main();
|
||||
|
||||
let result = CGDisplay::displays_with_rect(
|
||||
CGRect::new(&CGPoint::new(0., 0.), &CGSize::new(100., 100.)),
|
||||
0,
|
||||
);
|
||||
assert!(result.is_ok());
|
||||
let (displays, count) = result.unwrap();
|
||||
assert_eq!(displays.len(), count as usize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_displays_with_rect_5() {
|
||||
let _ = CGDisplay::main();
|
||||
|
||||
let result = CGDisplay::displays_with_rect(
|
||||
CGRect::new(&CGPoint::new(0., 0.), &CGSize::new(100., 100.)),
|
||||
5,
|
||||
);
|
||||
assert!(result.is_ok());
|
||||
let (displays, count) = result.unwrap();
|
||||
assert_eq!(displays.len(), count as usize);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user