Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion runtime/monotouch-support.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#ifndef __MONOTOUCH_SUPPORT_H__
#ifndef __MONOTOUCH_SUPPORT_H__
#define __MONOTOUCH_SUPPORT_H__

#ifdef __cplusplus
Expand All @@ -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);
Expand Down
10 changes: 10 additions & 0 deletions runtime/xamarin-support.m
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,13 @@ void objc_msgSendSuper_stret (void)

#endif

#ifdef MONOMAC
// <quote>Do not hard-code this parameter as a C string.</quote>
// 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
29 changes: 29 additions & 0 deletions src/Foundation/NSValue.cs
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style: complete word as parameter name - transform

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I thought about it - but it's the current name for iOS/tvOS/watchOS :(
so I decided to be consistent

{
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
}
}
11 changes: 8 additions & 3 deletions src/foundation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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:")]
Expand Down
17 changes: 17 additions & 0 deletions tests/monotouch-test/CoreGraphics/AffineTransformTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Rolf Bjarne Kvinge <rolf@xamarin.com>
//
// Copyright 2014 Xamarin Inc. All rights reserved.
// Copyright 2019 Microsoft Corporation
//

using System;
Expand Down Expand Up @@ -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");
}
}
}


Expand Down
2 changes: 0 additions & 2 deletions tests/xtro-sharpie/common-Foundation.ignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down