From b31cffb64868c0cf8e2b217f62989677e88029cc Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 3 Jun 2016 16:03:35 -0700 Subject: [PATCH 1/7] geometry: Make `CGPoint`, `CGRect`, and `CGSize` copyable and clonable. --- src/geometry.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/geometry.rs b/src/geometry.rs index fbe1280..67f4c2d 100644 --- a/src/geometry.rs +++ b/src/geometry.rs @@ -10,18 +10,21 @@ use base::CGFloat; #[repr(C)] +#[derive(Clone, Copy, Debug)] pub struct CGSize { pub width: CGFloat, pub height: CGFloat, } #[repr(C)] +#[derive(Clone, Copy, Debug)] pub struct CGPoint { pub x: CGFloat, pub y: CGFloat, } #[repr(C)] +#[derive(Clone, Copy, Debug)] pub struct CGRect { pub origin: CGPoint, pub size: CGSize From 9b16b0e21429db7132edc024388635107985a1b9 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 3 Jun 2016 16:04:03 -0700 Subject: [PATCH 2/7] geometry: Add `CG_ZERO_POINT` to match `CGZeroPoint`. --- src/geometry.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/geometry.rs b/src/geometry.rs index 67f4c2d..06741f0 100644 --- a/src/geometry.rs +++ b/src/geometry.rs @@ -9,6 +9,11 @@ use base::CGFloat; +pub const CG_ZERO_POINT: CGPoint = CGPoint { + x: 0.0, + y: 0.0, +}; + #[repr(C)] #[derive(Clone, Copy, Debug)] pub struct CGSize { From 508a240632324d4380f1111778ecbdf5fd9a5ebb Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 3 Jun 2016 16:04:40 -0700 Subject: [PATCH 3/7] geometry: Add some convenience constructors for geometry types. --- src/geometry.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/geometry.rs b/src/geometry.rs index 06741f0..b7f73b0 100644 --- a/src/geometry.rs +++ b/src/geometry.rs @@ -21,6 +21,16 @@ pub struct CGSize { pub height: CGFloat, } +impl CGSize { + #[inline] + pub fn new(width: CGFloat, height: CGFloat) -> CGSize { + CGSize { + width: width, + height: height, + } + } +} + #[repr(C)] #[derive(Clone, Copy, Debug)] pub struct CGPoint { @@ -28,9 +38,30 @@ pub struct CGPoint { pub y: CGFloat, } +impl CGPoint { + #[inline] + pub fn new(x: CGFloat, y: CGFloat) -> CGPoint { + CGPoint { + x: x, + y: y, + } + } +} + #[repr(C)] #[derive(Clone, Copy, Debug)] pub struct CGRect { pub origin: CGPoint, pub size: CGSize } + +impl CGRect { + #[inline] + pub fn new(origin: &CGPoint, size: &CGSize) -> CGRect { + CGRect { + origin: *origin, + size: *size, + } + } +} + From 35d51561822465041de29409450a29c36c5aadc6 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 3 Jun 2016 16:04:59 -0700 Subject: [PATCH 4/7] geometry: Add a binding to `CGRectInset`. --- src/geometry.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/geometry.rs b/src/geometry.rs index b7f73b0..e4145da 100644 --- a/src/geometry.rs +++ b/src/geometry.rs @@ -63,5 +63,22 @@ impl CGRect { size: *size, } } + + #[inline] + pub fn inset(&self, size: &CGSize) -> CGRect { + unsafe { + ffi::CGRectInset(*self, size.width, size.height) + } + } +} + +mod ffi { + use base::CGFloat; + use geometry::CGRect; + + #[link(name = "ApplicationServices", kind = "framework")] + extern { + pub fn CGRectInset(rect: CGRect, dx: CGFloat, dy: CGFloat) -> CGRect; + } } From 828a7fde4b529ed4c6016a739fd3630c63eea484 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 3 Jun 2016 16:05:44 -0700 Subject: [PATCH 5/7] private: Rename `CGSRegion` types to match reverse engineered headers available elsewhere. See: https://github.com/NUIKit/CGSInternal/blob/master/CGSRegion.h --- src/private.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/private.rs b/src/private.rs index ff9a57d..4758519 100644 --- a/src/private.rs +++ b/src/private.rs @@ -15,7 +15,7 @@ use geometry::CGRect; use std::ptr; pub struct CGSRegion { - region: ffi::CGSRegion, + region: ffi::CGSRegionRef, } impl Drop for CGSRegion { @@ -45,13 +45,14 @@ mod ffi { // This is an enum so that we can't easily make instances of this opaque type. enum CGSRegionObject {} - pub type CGSRegion = *mut CGSRegionObject; + pub type CGError = OSStatus; + pub type CGSRegionRef = *mut CGSRegionObject; pub type OSStatus = i32; #[link(name = "ApplicationServices", kind = "framework")] extern { - pub fn CGSRegionRelease(region: CGSRegion); - pub fn CGSNewRegionWithRect(rect: *const CGRect, region: *mut CGSRegion) -> OSStatus; + pub fn CGSRegionRelease(region: CGSRegionRef); + pub fn CGSNewRegionWithRect(rect: *const CGRect, outRegion: *mut CGSRegionRef) -> CGError; } } From 621a033730853a8660f6bc83f2e84f1794293470 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 3 Jun 2016 16:07:24 -0700 Subject: [PATCH 6/7] private: Add a binding to `CGSNewRegionWithRectList`. --- src/private.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/private.rs b/src/private.rs index 4758519..3be0f10 100644 --- a/src/private.rs +++ b/src/private.rs @@ -37,10 +37,24 @@ impl CGSRegion { } } } + + #[inline] + pub fn from_rects(rects: &[CGRect]) -> CGSRegion { + unsafe { + let mut region = ptr::null_mut(); + assert!(ffi::CGSNewRegionWithRectList(rects.as_ptr(), + rects.len() as c_uint, + &mut region) == 0); + CGSRegion { + region: region, + } + } + } } mod ffi { use geometry::CGRect; + use libc::c_uint; // This is an enum so that we can't easily make instances of this opaque type. enum CGSRegionObject {} @@ -53,6 +67,10 @@ mod ffi { extern { pub fn CGSRegionRelease(region: CGSRegionRef); pub fn CGSNewRegionWithRect(rect: *const CGRect, outRegion: *mut CGSRegionRef) -> CGError; + pub fn CGSNewRegionWithRectList(rects: *const CGRect, + rectCount: c_uint, + outRegion: *mut CGSRegionRef) + -> CGError; } } From 443e95792aa1f8ec5facf26899e35409484b34ee Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 3 Jun 2016 16:07:58 -0700 Subject: [PATCH 7/7] private: Add a binding to `CGSSetSurfaceShape`. This is useful to make OpenGL areas have rounded corners. It matches what the Cocoa framework does internally for this. --- src/private.rs | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/private.rs b/src/private.rs index 3be0f10..518c55c 100644 --- a/src/private.rs +++ b/src/private.rs @@ -12,6 +12,7 @@ //! These are liable to change at any time. Use with caution! use geometry::CGRect; +use libc::{c_int, c_uint}; use std::ptr; pub struct CGSRegion { @@ -52,9 +53,42 @@ impl CGSRegion { } } +/// This should always be memory-safe; the window server rejects any invalid surface IDs. +pub struct CGSSurface { + context_id: c_uint, + window_number: c_int, + surface_id: c_uint, +} + +impl CGSSurface { + #[inline] + pub fn from_ids(context_id: c_uint, window_number: c_int, surface_id: c_uint) -> CGSSurface { + CGSSurface { + context_id: context_id, + window_number: window_number, + surface_id: surface_id, + } + } + + #[inline] + pub fn id(&self) -> c_uint { + self.surface_id + } + + #[inline] + pub fn set_shape(&self, region: &CGSRegion) { + unsafe { + assert!(ffi::CGSSetSurfaceShape(self.context_id, + self.window_number, + self.surface_id, + region.region) == 0) + } + } +} + mod ffi { use geometry::CGRect; - use libc::c_uint; + use libc::{c_int, c_uint}; // This is an enum so that we can't easily make instances of this opaque type. enum CGSRegionObject {} @@ -71,6 +105,12 @@ mod ffi { rectCount: c_uint, outRegion: *mut CGSRegionRef) -> CGError; + + pub fn CGSSetSurfaceShape(contextID: c_uint, + windowNumber: c_int, + surfaceID: c_uint, + region: CGSRegionRef) + -> CGError; } }