diff --git a/runtime/monotouch-support.h b/runtime/monotouch-support.h index 845bebcc0047..e5c14a3dee2f 100644 --- a/runtime/monotouch-support.h +++ b/runtime/monotouch-support.h @@ -1,4 +1,4 @@ -#ifndef __MONOTOUCH_SUPPORT_H__ +#ifndef __MONOTOUCH_SUPPORT_H__ #define __MONOTOUCH_SUPPORT_H__ #ifdef __cplusplus @@ -15,6 +15,11 @@ void xamarin_start_wwan (const char *uri); const char * xamarin_GetFolderPath (int folder); #endif +#ifdef MONOMAC +const char * +xamarin_encode_CGAffineTransform (); +#endif + #if defined (__arm64__) void objc_msgSend_stret (void); void objc_msgSendSuper_stret (void); diff --git a/runtime/xamarin-support.m b/runtime/xamarin-support.m index 72dc38e7aee7..cf86a990cdeb 100644 --- a/runtime/xamarin-support.m +++ b/runtime/xamarin-support.m @@ -172,3 +172,13 @@ void objc_msgSendSuper_stret (void) #endif +#ifdef MONOMAC +// Do not hard-code this parameter as a C string. +// works on iOS (where we don't need it) and crash on macOS +const char * +xamarin_encode_CGAffineTransform () +{ + // COOP: no managed memory access: any mode. + return @encode (CGAffineTransform); +} +#endif diff --git a/src/Foundation/NSValue.cs b/src/Foundation/NSValue.cs index 38a25e071d02..dd9c0efa7320 100644 --- a/src/Foundation/NSValue.cs +++ b/src/Foundation/NSValue.cs @@ -1,6 +1,7 @@ // // Copyright 2010, Novell, Inc. // Copyright 2011, 2012, 2013 Xamarin Inc +// Copyright 2019 Microsoft Corporation // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the @@ -22,11 +23,14 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +using System; #if !NO_SYSTEM_DRAWING using System.Drawing; #endif using System.Runtime.InteropServices; +using CoreGraphics; + namespace Foundation { public partial class NSValue : NSObject { #if !COREBUILD @@ -64,6 +68,31 @@ public PointF PointFValue { get { return (PointF)CGPointValue; } } #endif + +#if MONOMAC + // @encode(CGAffineTransform) -> "{CGAffineTransform=dddddd}" but... + // using a C string crash on macOS (while it works fine on iOS) + [DllImport ("__Internal")] + extern static IntPtr xamarin_encode_CGAffineTransform (); + + // The `+valueWithCGAffineTransform:` selector comes from UIKit and is not available on macOS + public unsafe static NSValue FromCGAffineTransform (CGAffineTransform tran) + { + return Create ((IntPtr) (void*) &tran, xamarin_encode_CGAffineTransform ()); + } + + // The `CGAffineTransformValue` selector comes from UIKit and is not available on macOS + public unsafe virtual CGAffineTransform CGAffineTransformValue { + get { + var result = new CGAffineTransform (); + // avoid potential buffer overflow since we use the older `getValue:` API to cover all platforms + // and we can cheat here with the actual string comparison (since we are the one doing it) + if (ObjCType == "{CGAffineTransform=dddddd}") + StoreValueAtAddress ((IntPtr) (void*) &result); + return result; + } + } +#endif #endif } } diff --git a/src/foundation.cs b/src/foundation.cs index 3dc2839b7b8b..6d8262eace06 100644 --- a/src/foundation.cs +++ b/src/foundation.cs @@ -10879,14 +10879,19 @@ partial interface NSValue : NSSecureCoding, NSCopying { [Export ("getValue:")] void StoreValueAtAddress (IntPtr value); + [Watch (4,0), TV (11,0), Mac (10,13), iOS (11,0)] + [Export ("getValue:size:")] + void StoreValueAtAddress (IntPtr value, nuint size); + [Export ("objCType")][Internal] IntPtr ObjCTypePtr (); //[Export ("initWithBytes:objCType:")][Internal] //NSValue InitFromBytes (IntPtr byte_ptr, IntPtr char_ptr_type); - //[Export ("valueWithBytes:objCType:")][Static][Internal] - //+ (NSValue *)valueWithBytes:(const void *)value objCType:(const char *)type; - //+ (NSValue *)value:(const void *)value withObjCType:(const char *)type; + + [Static][Internal] + [Export ("valueWithBytes:objCType:")] + NSValue Create (IntPtr bytes, IntPtr objCType); [Static] [Export ("valueWithNonretainedObject:")] diff --git a/tests/monotouch-test/CoreGraphics/AffineTransformTest.cs b/tests/monotouch-test/CoreGraphics/AffineTransformTest.cs index 5f2e2014800f..fb477cef4d3d 100644 --- a/tests/monotouch-test/CoreGraphics/AffineTransformTest.cs +++ b/tests/monotouch-test/CoreGraphics/AffineTransformTest.cs @@ -5,6 +5,7 @@ // Rolf Bjarne Kvinge // // Copyright 2014 Xamarin Inc. All rights reserved. +// Copyright 2019 Microsoft Corporation // using System; @@ -334,6 +335,22 @@ public void Invert () Assert.AreEqual ((nfloat) 1.0, transform.x0, "x0"); Assert.AreEqual ((nfloat) (-2.0), transform.y0, "y0"); } + + [Test] + public void NSValueRoundtrip () + { + var transform = new CGAffineTransform (1, 2, 3, 4, 5, 6); + // looks simplistic but that NSValue logic is implemented by "us" on macOS + using (var nsv = NSValue.FromCGAffineTransform (transform)) { + var tback = nsv.CGAffineTransformValue; + Assert.AreEqual ((nfloat)1, tback.xx, "xx"); + Assert.AreEqual ((nfloat)2, tback.yx, "yx"); + Assert.AreEqual ((nfloat)3, tback.xy, "xy"); + Assert.AreEqual ((nfloat)4, tback.yy, "yy"); + Assert.AreEqual ((nfloat)5, tback.x0, "x0"); + Assert.AreEqual ((nfloat)6, tback.y0, "y0"); + } + } } diff --git a/tests/xtro-sharpie/common-Foundation.ignore b/tests/xtro-sharpie/common-Foundation.ignore index d7d33c9f3787..23b9a2916cc1 100644 --- a/tests/xtro-sharpie/common-Foundation.ignore +++ b/tests/xtro-sharpie/common-Foundation.ignore @@ -417,7 +417,6 @@ !missing-selector! +NSURLRequest::requestWithURL:cachePolicy:timeoutInterval: not bound !missing-selector! +NSURLRequest::supportsSecureCoding not bound !missing-selector! +NSValue::value:withObjCType: not bound -!missing-selector! +NSValue::valueWithBytes:objCType: not bound !missing-selector! +NSXPCInterface::interfaceWithProtocol: not bound !missing-selector! NSArray::addObserver:forKeyPath:options:context: not bound !missing-selector! NSArray::arrayByAddingObject: not bound @@ -837,7 +836,6 @@ !missing-selector! NSURLProtocol::task not bound !missing-selector! NSURLRequest::HTTPShouldUsePipelining not bound !missing-selector! NSUUID::initWithUUIDBytes: not bound -!missing-selector! NSValue::getValue:size: not bound !missing-selector! NSValue::initWithBytes:objCType: not bound !missing-selector! NSXPCConnection::auditSessionIdentifier not bound !missing-selector! NSXPCConnection::effectiveGroupIdentifier not bound