diff --git a/Source/OpenTK/OpenTK.csproj b/Source/OpenTK/OpenTK.csproj index 2e0a1526..a0566740 100644 --- a/Source/OpenTK/OpenTK.csproj +++ b/Source/OpenTK/OpenTK.csproj @@ -802,6 +802,7 @@ + diff --git a/Source/OpenTK/Platform/MacOS/Cocoa/Cocoa.cs b/Source/OpenTK/Platform/MacOS/Cocoa/Cocoa.cs index 5acd11b7..cc2d98d1 100644 --- a/Source/OpenTK/Platform/MacOS/Cocoa/Cocoa.cs +++ b/Source/OpenTK/Platform/MacOS/Cocoa/Cocoa.cs @@ -45,6 +45,9 @@ namespace OpenTK.Platform.MacOS [DllImport(LibObjC, EntryPoint="objc_msgSend")] public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, ulong ulong1); + [DllImport(LibObjC, EntryPoint="objc_msgSend")] + public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, NSSize size); + [DllImport(LibObjC, EntryPoint="objc_msgSend")] public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, IntPtr intPtr1); @@ -61,25 +64,25 @@ namespace OpenTK.Platform.MacOS public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, IntPtr intPtr1, IntPtr intPtr2, IntPtr intPtr3, IntPtr intPtr4, IntPtr intPtr5); [DllImport(LibObjC, EntryPoint="objc_msgSend")] - public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, IntPtr p1, PointF p2); + public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, IntPtr p1, NSPoint p2); [DllImport(LibObjC, EntryPoint="objc_msgSend")] public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, bool p1); [DllImport(LibObjC, EntryPoint="objc_msgSend")] - public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, SizeF p1); + public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, NSPoint p1); [DllImport(LibObjC, EntryPoint="objc_msgSend")] - public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, RectangleF rectangle1); + public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, NSRect rectangle1); [DllImport(LibObjC, EntryPoint="objc_msgSend")] - public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, RectangleF rectangle1, int int1, int int2, bool bool1); + public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, NSRect rectangle1, int int1, int int2, bool bool1); [DllImport(LibObjC, EntryPoint="objc_msgSend")] public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, uint uint1, IntPtr intPtr1, IntPtr intPtr2, bool bool1); [DllImport(LibObjC, EntryPoint="objc_msgSend")] - public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, RectangleF rectangle1, int int1, IntPtr intPtr1, IntPtr intPtr2); + public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, NSRect rectangle1, int int1, IntPtr intPtr1, IntPtr intPtr2); [DllImport(LibObjC, EntryPoint="objc_msgSend")] public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, IntPtr p1, int p2, int p3, int p4, int p5, int p6, int p7, IntPtr p8, NSBitmapFormat p9, int p10, int p11); @@ -112,13 +115,13 @@ namespace OpenTK.Platform.MacOS public extern static void SendVoid(IntPtr receiver, IntPtr selector, bool bool1); [DllImport(LibObjC, EntryPoint="objc_msgSend")] - public extern static void SendVoid(IntPtr receiver, IntPtr selector, PointF point1); + public extern static void SendVoid(IntPtr receiver, IntPtr selector, NSPoint point1); [DllImport(LibObjC, EntryPoint="objc_msgSend")] - public extern static void SendVoid(IntPtr receiver, IntPtr selector, RectangleF rect1, bool bool1); + public extern static void SendVoid(IntPtr receiver, IntPtr selector, NSRect rect1, bool bool1); [DllImport(LibObjC, EntryPoint="objc_msgSend")] - public extern static void SendVoid(IntPtr receiver, IntPtr selector, RectangleF rect1, IntPtr intPtr1); + public extern static void SendVoid(IntPtr receiver, IntPtr selector, NSRect rect1, IntPtr intPtr1); [DllImport(LibObjC, EntryPoint="objc_msgSend")] public extern static int SendInt(IntPtr receiver, IntPtr selector); @@ -151,27 +154,27 @@ namespace OpenTK.Platform.MacOS #endif } - // Not the _stret version, perhaps because a PointF fits in one register? + // Not the _stret version, perhaps because a NSPoint fits in one register? // thefiddler: gcc is indeed using objc_msgSend for NSPoint on i386 [DllImport (LibObjC, EntryPoint="objc_msgSend")] - public extern static PointF SendPoint(IntPtr receiver, IntPtr selector); + public extern static NSPoint SendPoint(IntPtr receiver, IntPtr selector); [DllImport (LibObjC, EntryPoint="objc_msgSend_stret")] - extern static void SendRect(out System.Drawing.RectangleF retval, IntPtr receiver, IntPtr selector); + extern static void SendRect(out NSRect retval, IntPtr receiver, IntPtr selector); [DllImport (LibObjC, EntryPoint="objc_msgSend_stret")] - extern static void SendRect(out System.Drawing.RectangleF retval, IntPtr receiver, IntPtr selector, RectangleF rect1); + extern static void SendRect(out NSRect retval, IntPtr receiver, IntPtr selector, NSRect rect1); - public static RectangleF SendRect(IntPtr receiver, IntPtr selector) + public static NSRect SendRect(IntPtr receiver, IntPtr selector) { - RectangleF r; + NSRect r; SendRect(out r, receiver, selector); return r; } - public static RectangleF SendRect(IntPtr receiver, IntPtr selector, RectangleF rect1) + public static NSRect SendRect(IntPtr receiver, IntPtr selector, NSRect rect1) { - RectangleF r; + NSRect r; SendRect(out r, receiver, selector, rect1); return r; } diff --git a/Source/OpenTK/Platform/MacOS/Cocoa/NSFloat.cs b/Source/OpenTK/Platform/MacOS/Cocoa/NSFloat.cs new file mode 100644 index 00000000..84750d62 --- /dev/null +++ b/Source/OpenTK/Platform/MacOS/Cocoa/NSFloat.cs @@ -0,0 +1,181 @@ +#region License +// +// NSFloat.cs +// +// Author: +// Stefanos A. +// +// Copyright (c) 2006-2014 Stefanos Apostolopoulos +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +#endregion + +using System; +using System.Drawing; +using System.Runtime.InteropServices; + +namespace OpenTK.Platform.MacOS +{ + // NSFloat is defined as float on 32bit systems and double on 64bit. + // We have to account for this peculiarity in order to run OpenTK on + // 64bit Mac platforms. + // We do this by adding implicit conversions between IntPtr and float/double. + // Note that this conversion is against C# best practices, as it can lose information. + // However, NSFloat is used internally in places where this precision loss does not matter. + struct NSFloat + { + IntPtr value; + + public static implicit operator NSFloat(float v) + { + NSFloat f; + unsafe + { + if (IntPtr.Size == 4) + { + f.value = *(IntPtr*)&v; + } + else + { + double d = v; + f.value = *(IntPtr*)&d; + } + } + return f; + } + + public static implicit operator NSFloat(double v) + { + NSFloat f; + unsafe + { + if (IntPtr.Size == 4) + { + float fv = (float)v; + f.value = *(IntPtr*)&fv; + } + else + { + f.value = *(IntPtr*)&v; + } + } + return f; + } + + public static implicit operator float(NSFloat f) + { + unsafe + { + if (IntPtr.Size == 4) + { + return *(float*)&f.value; + } + else + { + return (float)*(double*)&f.value; + } + } + } + + public static implicit operator double(NSFloat f) + { + unsafe + { + if (IntPtr.Size == 4) + { + return (double)*(float*)&f.value; + } + else + { + return *(float*)&f.value; + } + } + } + } + + [StructLayout(LayoutKind.Sequential)] + struct NSPoint + { + public NSFloat X; + public NSFloat Y; + + public static implicit operator NSPoint(PointF p) + { + return new NSPoint + { + X = p.X, + Y = p.Y + }; + } + + public static implicit operator PointF(NSPoint s) + { + return new PointF(s.X, s.Y); + } + } + + [StructLayout(LayoutKind.Sequential)] + struct NSSize + { + public NSFloat Width; + public NSFloat Height; + + public static implicit operator NSSize(SizeF s) + { + return new NSSize + { + Width = s.Width, + Height = s.Height + }; + } + + public static implicit operator SizeF(NSSize s) + { + return new SizeF(s.Width, s.Height); + } + } + + [StructLayout(LayoutKind.Sequential)] + struct NSRect + { + public NSPoint Location; + public NSSize Size; + + public NSFloat Width { get { return Size.Width; } } + public NSFloat Height { get { return Size.Height; } } + public NSFloat X { get { return Location.X; } } + public NSFloat Y { get { return Location.Y; } } + + public static implicit operator NSRect(RectangleF s) + { + return new NSRect + { + Location = s.Location, + Size = s.Size + }; + } + + public static implicit operator RectangleF(NSRect s) + { + return new RectangleF(s.Location, s.Size); + } + } +} +