@@ -20,6 +20,7 @@ pub use crate::geometry::{CGPoint, CGRect, CGSize};
20
20
use crate :: image:: CGImage ;
21
21
use core_foundation:: base:: { CFRetain , TCFType } ;
22
22
use core_foundation:: string:: { CFString , CFStringRef } ;
23
+ use core_graphics_types:: base:: kCGErrorSuccess;
23
24
use foreign_types:: { foreign_type, ForeignType } ;
24
25
25
26
pub type CGDirectDisplayID = u32 ;
@@ -177,6 +178,90 @@ impl CGDisplay {
177
178
CGDisplay :: new ( kCGNullDirectDisplayID)
178
179
}
179
180
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
+
180
265
/// Returns the bounds of a display in the global display coordinate space.
181
266
#[ inline]
182
267
pub fn bounds ( & self ) -> CGRect {
@@ -714,6 +799,12 @@ extern "C" {
714
799
active_displays : * mut CGDirectDisplayID ,
715
800
display_count : * mut u32 ,
716
801
) -> CGError ;
802
+ pub fn CGGetDisplaysWithPoint (
803
+ point : CGPoint ,
804
+ max_displays : u32 ,
805
+ displays : * mut CGDirectDisplayID ,
806
+ matching_display_count : * mut u32 ,
807
+ ) -> CGError ;
717
808
pub fn CGGetDisplaysWithRect (
718
809
rect : CGRect ,
719
810
max_displays : u32 ,
@@ -839,3 +930,71 @@ extern "C" {
839
930
imageOptions : CGWindowImageOption ,
840
931
) -> crate :: sys:: CGImageRef ;
841
932
}
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