From 5e1b7c82aba32c6d7d4abcaab9c004c41f35d41f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olle=20H=C3=A5kansson?= Date: Fri, 18 Apr 2014 22:30:50 +0200 Subject: [PATCH] Cocoa bindings through libobjc.dylib --- Source/OpenTK/OpenTK.csproj | 15 + Source/OpenTK/Platform/MacOS/Cocoa/Class.cs | 21 ++ Source/OpenTK/Platform/MacOS/Cocoa/Cocoa.cs | 93 ++++++ .../Platform/MacOS/Cocoa/NSApplication.cs | 37 +++ .../Cocoa/NSApplicationActivationPolicy.cs | 9 + .../Platform/MacOS/Cocoa/NSBackingStore.cs | 9 + .../Cocoa/NSOpenGLPixelFormatAttribute.cs | 47 +++ .../Platform/MacOS/Cocoa/NSOpenGLProfile.cs | 8 + .../Platform/MacOS/Cocoa/NSWindowStyle.cs | 22 ++ .../OpenTK/Platform/MacOS/Cocoa/Selector.cs | 18 ++ Source/OpenTK/Platform/MacOS/CocoaContext.cs | 263 +++++++++++++++ .../Platform/MacOS/CocoaNativeWindow.cs | 306 ++++++++++++++++++ .../OpenTK/Platform/MacOS/CocoaWindowInfo.cs | 113 +++++++ Source/OpenTK/Platform/MacOS/MacOSFactory.cs | 8 +- Source/OpenTK/Platform/MacOS/NS.cs | 22 ++ 15 files changed, 987 insertions(+), 4 deletions(-) create mode 100644 Source/OpenTK/Platform/MacOS/Cocoa/Class.cs create mode 100644 Source/OpenTK/Platform/MacOS/Cocoa/Cocoa.cs create mode 100644 Source/OpenTK/Platform/MacOS/Cocoa/NSApplication.cs create mode 100755 Source/OpenTK/Platform/MacOS/Cocoa/NSApplicationActivationPolicy.cs create mode 100755 Source/OpenTK/Platform/MacOS/Cocoa/NSBackingStore.cs create mode 100755 Source/OpenTK/Platform/MacOS/Cocoa/NSOpenGLPixelFormatAttribute.cs create mode 100755 Source/OpenTK/Platform/MacOS/Cocoa/NSOpenGLProfile.cs create mode 100755 Source/OpenTK/Platform/MacOS/Cocoa/NSWindowStyle.cs create mode 100755 Source/OpenTK/Platform/MacOS/Cocoa/Selector.cs create mode 100644 Source/OpenTK/Platform/MacOS/CocoaContext.cs create mode 100644 Source/OpenTK/Platform/MacOS/CocoaNativeWindow.cs create mode 100644 Source/OpenTK/Platform/MacOS/CocoaWindowInfo.cs diff --git a/Source/OpenTK/OpenTK.csproj b/Source/OpenTK/OpenTK.csproj index 74d9f6ed..7aac63a1 100644 --- a/Source/OpenTK/OpenTK.csproj +++ b/Source/OpenTK/OpenTK.csproj @@ -803,6 +803,18 @@ + + + + + + + + + + + + @@ -832,4 +844,7 @@ + + + \ No newline at end of file diff --git a/Source/OpenTK/Platform/MacOS/Cocoa/Class.cs b/Source/OpenTK/Platform/MacOS/Cocoa/Class.cs new file mode 100644 index 00000000..594ebebf --- /dev/null +++ b/Source/OpenTK/Platform/MacOS/Cocoa/Class.cs @@ -0,0 +1,21 @@ +using System.Runtime.InteropServices; +using System; + +namespace OpenTK.Platform.MacOS +{ + static class Class + { + [DllImport (Cocoa.LibObjC)] + extern static IntPtr objc_getClass(string name); + + public static IntPtr Get(string name) + { + var id = objc_getClass(name); + if (id == IntPtr.Zero) + { + throw new ArgumentException("Unknown class: " + name); + } + return id; + } + } +} diff --git a/Source/OpenTK/Platform/MacOS/Cocoa/Cocoa.cs b/Source/OpenTK/Platform/MacOS/Cocoa/Cocoa.cs new file mode 100644 index 00000000..e4b07364 --- /dev/null +++ b/Source/OpenTK/Platform/MacOS/Cocoa/Cocoa.cs @@ -0,0 +1,93 @@ +using System.Runtime.InteropServices; +using System; +using System.Drawing; + +namespace OpenTK.Platform.MacOS +{ + static class Cocoa + { + internal const string LibObjC = "/usr/lib/libobjc.dylib"; + + [DllImport(LibObjC, EntryPoint="objc_msgSend")] + public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector); + + [DllImport(LibObjC, EntryPoint="objc_msgSend")] + public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, IntPtr intPtr1); + + [DllImport(LibObjC, EntryPoint="objc_msgSend")] + public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, IntPtr intPtr1, int int1); + + [DllImport(LibObjC, EntryPoint="objc_msgSend")] + public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, IntPtr intPtr1, IntPtr intPtr2); + + [DllImport(LibObjC, EntryPoint="objc_msgSend")] + public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, RectangleF rectangle1, int int1, int int2, bool bool1); + + [DllImport(LibObjC, EntryPoint="objc_msgSend")] + public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, uint mask, IntPtr intPtr1, IntPtr intPtr2, bool bool1); + + [DllImport(LibObjC, EntryPoint="objc_msgSend")] + public extern static bool SendBool(IntPtr receiver, IntPtr selector, int int1); + + [DllImport(LibObjC, EntryPoint="objc_msgSend")] + public extern static void SendVoid(IntPtr receiver, IntPtr selector); + + [DllImport(LibObjC, EntryPoint="objc_msgSend")] + public extern static void SendVoid(IntPtr receiver, IntPtr selector, IntPtr intPtr1); + + [DllImport(LibObjC, EntryPoint="objc_msgSend")] + public extern static void SendVoid(IntPtr receiver, IntPtr selector, int int1); + + [DllImport(LibObjC, EntryPoint="objc_msgSend")] + 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 static IntPtr ToNative(string str) + { + if (str == null) + return IntPtr.Zero; + + unsafe + { + fixed (char* ptrFirstChar = str) + { + var handle = Cocoa.SendIntPtr(Class.Get("NSString"), Selector.Alloc); + handle = Cocoa.SendIntPtr(handle, Selector.Get("initWithCharacters:length:"), (IntPtr)ptrFirstChar, str.Length); + return handle; + } + } + } + + public static IntPtr GetStringConstant(IntPtr handle, string symbol) + { + var indirect = NS.GetSymbol(handle, symbol); + if (indirect == IntPtr.Zero) + return IntPtr.Zero; + + var actual = Marshal.ReadIntPtr(indirect); + if (actual == IntPtr.Zero) + return IntPtr.Zero; + + return actual; + //return (NSString) Runtime.GetNSObject (actual); + } + + public static IntPtr AppKitLibrary; + public static IntPtr FoundationLibrary; + + public static void Initialize() + { + if (AppKitLibrary != IntPtr.Zero) + { + return; + } + + AppKitLibrary = NS.LoadLibrary("/System/Library/Frameworks/AppKit.framework/AppKit"); + FoundationLibrary = NS.LoadLibrary("/System/Library/Frameworks/Foundation.framework/Foundation"); + + NSApplication.Initialize(); + } + } +} diff --git a/Source/OpenTK/Platform/MacOS/Cocoa/NSApplication.cs b/Source/OpenTK/Platform/MacOS/Cocoa/NSApplication.cs new file mode 100644 index 00000000..badc24f8 --- /dev/null +++ b/Source/OpenTK/Platform/MacOS/Cocoa/NSApplication.cs @@ -0,0 +1,37 @@ +using System; +using System.Runtime.InteropServices; +using OpenTK.Platform.MacOS; + +namespace OpenTK.Platform.MacOS +{ + static class NSApplication + { + internal static IntPtr Handle; + + internal static void Initialize() + { + // Create the NSAutoreleasePool + Cocoa.SendIntPtr(Cocoa.SendIntPtr(Class.Get("NSAutoreleasePool"), Selector.Alloc), + Selector.Init); + + // Fetch the application handle + Handle = Cocoa.SendIntPtr(Class.Get("NSApplication"), Selector.Get("sharedApplication")); + + // Setup the application + Cocoa.SendBool(Handle, Selector.Get("setActivationPolicy:"), (int)NSApplicationActivationPolicy.Regular); + Cocoa.SendVoid(Handle, Selector.Get("activateIgnoringOtherApps:"), true); + Cocoa.SendVoid(Handle, Selector.Get("finishLaunching")); + + // Create the menu bar + var menubar = Cocoa.SendIntPtr(Cocoa.SendIntPtr(Class.Get("NSMenu"), Selector.Alloc), + Selector.Autorelease); + + var menuItem = Cocoa.SendIntPtr(Cocoa.SendIntPtr(Class.Get("NSMenuItem"), Selector.Alloc), + Selector.Autorelease); + + // Add menu item to bar, and bar to application + Cocoa.SendIntPtr(menubar, Selector.Get("addItem:"), menuItem); + Cocoa.SendIntPtr(Handle, Selector.Get("setMainMenu:"), menubar); + } + } +} diff --git a/Source/OpenTK/Platform/MacOS/Cocoa/NSApplicationActivationPolicy.cs b/Source/OpenTK/Platform/MacOS/Cocoa/NSApplicationActivationPolicy.cs new file mode 100755 index 00000000..5c3be778 --- /dev/null +++ b/Source/OpenTK/Platform/MacOS/Cocoa/NSApplicationActivationPolicy.cs @@ -0,0 +1,9 @@ +namespace OpenTK.Platform.MacOS +{ + enum NSApplicationActivationPolicy + { + Regular, + Accessory, + Prohibited, + } +} diff --git a/Source/OpenTK/Platform/MacOS/Cocoa/NSBackingStore.cs b/Source/OpenTK/Platform/MacOS/Cocoa/NSBackingStore.cs new file mode 100755 index 00000000..7d3d99e7 --- /dev/null +++ b/Source/OpenTK/Platform/MacOS/Cocoa/NSBackingStore.cs @@ -0,0 +1,9 @@ +namespace OpenTK.Platform.MacOS +{ + enum NSBackingStore + { + Retained, + Nonretained, + Buffered, + } +} diff --git a/Source/OpenTK/Platform/MacOS/Cocoa/NSOpenGLPixelFormatAttribute.cs b/Source/OpenTK/Platform/MacOS/Cocoa/NSOpenGLPixelFormatAttribute.cs new file mode 100755 index 00000000..e2bd04af --- /dev/null +++ b/Source/OpenTK/Platform/MacOS/Cocoa/NSOpenGLPixelFormatAttribute.cs @@ -0,0 +1,47 @@ +using System; + +namespace OpenTK.Platform.MacOS +{ + enum NSOpenGLPixelFormatAttribute + { + AllRenderers = 1, + TrippleBuffer = 3, // Lion + DoubleBuffer = 5, + Stereo = 6, + AuxBuffers = 7, + ColorSize = 8, + AlphaSize = 11, + DepthSize = 12, + StencilSize = 13, + AccumSize = 14, + MinimumPolicy = 51, + MaximumPolicy = 52, + OffScreen = 53, + FullScreen = 54, + SampleBuffers = 55, + Samples = 56, + AuxDepthStencil = 57, + ColorFloat = 58, + Multisample = 59, + Supersample = 60, + SampleAlpha = 61, + RendererID = 70, + SingleRenderer = 71, + NoRecovery = 72, + Accelerated = 73, + ClosestPolicy = 74, + [Obsolete] Robust = 75, + BackingStore = 76, + [Obsolete] MPSafe = 78, + Window = 80, + [Obsolete] MultiScreen = 81, + Compliant = 83, + ScreenMask = 84, + PixelBuffer = 90, + RemotePixelBuffer = 91, + AllowOfflineRenderers = 96, + AcceleratedCompute = 97, + OpenGLProfile = 99, // Lion + VirtualScreenCount = 128, + } +} diff --git a/Source/OpenTK/Platform/MacOS/Cocoa/NSOpenGLProfile.cs b/Source/OpenTK/Platform/MacOS/Cocoa/NSOpenGLProfile.cs new file mode 100755 index 00000000..9f07bf96 --- /dev/null +++ b/Source/OpenTK/Platform/MacOS/Cocoa/NSOpenGLProfile.cs @@ -0,0 +1,8 @@ +namespace OpenTK.Platform.MacOS +{ + enum NSOpenGLProfile + { + VersionLegacy = 4096, + Version3_2Core = 12800, + } +} diff --git a/Source/OpenTK/Platform/MacOS/Cocoa/NSWindowStyle.cs b/Source/OpenTK/Platform/MacOS/Cocoa/NSWindowStyle.cs new file mode 100755 index 00000000..26dcfd34 --- /dev/null +++ b/Source/OpenTK/Platform/MacOS/Cocoa/NSWindowStyle.cs @@ -0,0 +1,22 @@ +using System; + +namespace OpenTK.Platform.MacOS +{ + [Flags] + public enum NSWindowStyle + { + Borderless = 0, + Titled = 1, + Closable = 2, + Miniaturizable = 4, + Resizable = 8, + Utility = 16, + DocModal = 64, + NonactivatingPanel = 128, + TexturedBackground = 256, + Unscaled = 2048, + UnifiedTitleAndToolbar = 4096, + Hud = 8192, + FullScreenWindow = 16384, + } +} diff --git a/Source/OpenTK/Platform/MacOS/Cocoa/Selector.cs b/Source/OpenTK/Platform/MacOS/Cocoa/Selector.cs new file mode 100755 index 00000000..424d7d48 --- /dev/null +++ b/Source/OpenTK/Platform/MacOS/Cocoa/Selector.cs @@ -0,0 +1,18 @@ +using System; +using System.Runtime.InteropServices; + +namespace OpenTK.Platform.MacOS +{ + static class Selector + { + // Frequently used selectors + public static readonly IntPtr Init = Selector.Get("init"); + public static readonly IntPtr InitWithCoder = Selector.Get("initWithCoder:"); + public static readonly IntPtr Alloc = Selector.Get("alloc"); + public static readonly IntPtr Release = Selector.Get("release"); + public static readonly IntPtr Autorelease = Selector.Get("autorelease"); + + [DllImport ("/usr/lib/libobjc.dylib", EntryPoint="sel_registerName")] + public extern static IntPtr Get(string name); + } +} diff --git a/Source/OpenTK/Platform/MacOS/CocoaContext.cs b/Source/OpenTK/Platform/MacOS/CocoaContext.cs new file mode 100644 index 00000000..5100e972 --- /dev/null +++ b/Source/OpenTK/Platform/MacOS/CocoaContext.cs @@ -0,0 +1,263 @@ +using System; +using OpenTK.Platform; +using OpenTK.Graphics; +using OpenTK.Platform.MacOS; +using System.Diagnostics; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace OpenTK +{ + class CocoaContext : DesktopGraphicsContext + { + private CocoaWindowInfo cocoaWindow; + private IntPtr shareContextRef; + + static readonly IntPtr NSOpenGLContext = Class.Get("NSOpenGLContext"); + static readonly IntPtr currentContext = Selector.Get("currentContext"); + static readonly IntPtr flushBuffer = Selector.Get("flushBuffer"); + static readonly IntPtr makeCurrentContext = Selector.Get("makeCurrentContext"); + static readonly IntPtr update = Selector.Get("update"); + + static CocoaContext() + { + Cocoa.Initialize(); + } + + public CocoaContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, int majorVersion, int minorVersion) + { + Debug.Print("Context Type: {0}", shareContext); + Debug.Print("Window info: {0}", window); + + cocoaWindow = (CocoaWindowInfo)window; + + if (shareContext is CocoaContext) + shareContextRef = ((CocoaContext)shareContext).Handle.Handle; + + if (shareContext is GraphicsContext) + { + ContextHandle shareHandle = shareContext != null ? (shareContext as IGraphicsContextInternal).Context : (ContextHandle)IntPtr.Zero; + shareContextRef = shareHandle.Handle; + } + + if (shareContextRef == IntPtr.Zero) + { + Debug.Print("No context sharing will take place."); + } + + CreateContext(mode, cocoaWindow, shareContextRef, majorVersion, minorVersion, true); + } + + public CocoaContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, int majorVersion, int minorVersion) + { + if (handle == ContextHandle.Zero) + throw new ArgumentException("handle"); + if (window == null) + throw new ArgumentNullException("window"); + + Handle = handle; + cocoaWindow = (CocoaWindowInfo)window; + } + + private void AddPixelAttrib(List attributes, NSOpenGLPixelFormatAttribute attribute) + { + Debug.Print(attribute.ToString()); + + attributes.Add(attribute); + } + + private void AddPixelAttrib(List attributes, NSOpenGLPixelFormatAttribute attribute, int value) + { + Debug.Print("{0} : {1}", attribute, value); + + attributes.Add(attribute); + attributes.Add((NSOpenGLPixelFormatAttribute)value); + } + + private void CreateContext(GraphicsMode mode, CocoaWindowInfo cocoaWindow, IntPtr shareContextRef, int majorVersion, int minorVersion, bool fullscreen) + { + // Prepare attributes + List attributes = new List(); + + var profile = NSOpenGLProfile.VersionLegacy; + if (majorVersion > 3 || (majorVersion == 3 && minorVersion >= 2)) + { + profile = NSOpenGLProfile.Version3_2Core; + Debug.Print("Running the OpenGL core profile."); + } + else + { + Debug.Print("Running the legacy OpenGL profile. Start with version major=3, minor=2 or later for the 3.2 profile."); + } + + Debug.Print("NSGL pixel format attributes:"); + Debug.Indent(); + + AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.OpenGLProfile, (int)profile); + AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.DoubleBuffer); + AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.Accelerated); + AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.ColorSize, mode.ColorFormat.BitsPerPixel); + + if (mode.Depth > 0) + AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.DepthSize, mode.Depth); + + if (mode.Stencil > 0) + AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.StencilSize, mode.Stencil); + + if (mode.AccumulatorFormat.BitsPerPixel > 0) + { + AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.AccumSize, mode.AccumulatorFormat.BitsPerPixel); + } + + if (mode.Samples > 1) + { + AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.SampleBuffers, 1); + AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.Samples, mode.Samples); + } + + AddPixelAttrib(attributes, (NSOpenGLPixelFormatAttribute)0); + + Debug.Unindent(); + + Debug.Write("Attribute array: "); + for (int i = 0; i < attributes.Count; i++) + Debug.Write(attributes[i].ToString() + " "); + Debug.WriteLine(""); + + // Create pixel format + var pixelFormat = Cocoa.SendIntPtr(Class.Get("NSOpenGLPixelFormat"), Selector.Alloc); + + unsafe + { + fixed (NSOpenGLPixelFormatAttribute* ptr = attributes.ToArray()) + { + pixelFormat = Cocoa.SendIntPtr(pixelFormat, Selector.Get("initWithAttributes:"), (IntPtr)ptr); + } + } + + // Create context + var context = Cocoa.SendIntPtr(NSOpenGLContext, Selector.Alloc); + context = Cocoa.SendIntPtr(context, Selector.Get("initWithFormat:shareContext:"), pixelFormat, shareContextRef); + + // Release pixel format + Cocoa.SendVoid(pixelFormat, Selector.Release); + pixelFormat = IntPtr.Zero; + + // Attach the view + Cocoa.SendVoid(context, Selector.Get("setView:"), cocoaWindow.ViewHandle); + Cocoa.SendVoid(cocoaWindow.ViewHandle, Selector.Get("setWantsBestResolutionOpenGLSurface:"), true); + + // Finalize + Handle = new ContextHandle(context); + Update(cocoaWindow); + MakeCurrent(cocoaWindow); + } + + public override void SwapBuffers() + { + Cocoa.SendVoid(Handle.Handle, flushBuffer); + } + + public override void MakeCurrent(IWindowInfo window) + { + Cocoa.SendVoid(Handle.Handle, makeCurrentContext); + } + + public override bool IsCurrent + { + get + { + return Handle.Handle == CurrentContext; + } + } + + public static IntPtr CurrentContext + { + get + { + return Cocoa.SendIntPtr(NSOpenGLContext, currentContext); + } + } + +// private unsafe void SetContextValue (int val, NSOpenGLContextParameter par) +// { +// int *p = &val; +// context.SetValues ((IntPtr)p, par); +// } +// +// private unsafe int GetContextValue (NSOpenGLContextParameter par) +// { +// int ret; +// int *p = &ret; +// context.GetValues ((IntPtr)p, par); +// +// return ret; +// } + + public override int SwapInterval + { + get + { + return 0; + //return GetContextValue(NSOpenGLContextParameter.SwapInterval); + } + set + { + + //SetContextValue(value, NSOpenGLContextParameter.SwapInterval); + } + } + + public override void Update(IWindowInfo window) + { + Cocoa.SendVoid(Handle.Handle, update); + } + + #region IDisposable Members + + ~CocoaContext() + { + Dispose(false); + } + + public override void Dispose() + { + Dispose(true); + } + + void Dispose(bool disposing) + { + if (IsDisposed || Handle.Handle == IntPtr.Zero) + return; + + Debug.Print("Disposing of Cocoa context."); + + Cocoa.SendIntPtr(NSOpenGLContext, Selector.Get("clearCurrentContext")); + +// NSOpenGLContext.ClearCurrentContext(); +// context.ClearDrawable(); +// context.Dispose(); +// context = null; + Handle = ContextHandle.Zero; + + IsDisposed = true; + } + + #endregion + + #region IGraphicsContextInternal Members + + public override IntPtr GetAddress(string function) + { + return NS.GetAddress(function); + } + + public override IntPtr GetAddress(IntPtr function) + { + return NS.GetAddress(function); + } + + #endregion + } +} + diff --git a/Source/OpenTK/Platform/MacOS/CocoaNativeWindow.cs b/Source/OpenTK/Platform/MacOS/CocoaNativeWindow.cs new file mode 100644 index 00000000..6a42d48b --- /dev/null +++ b/Source/OpenTK/Platform/MacOS/CocoaNativeWindow.cs @@ -0,0 +1,306 @@ +using System; +using OpenTK.Graphics; + +namespace OpenTK.Platform.MacOS +{ + class CocoaNativeWindow : INativeWindow + { + public event System.EventHandler Move; + public event System.EventHandler Resize; + public event System.EventHandler Closing; + public event System.EventHandler Closed; + public event System.EventHandler Disposed; + public event System.EventHandler IconChanged; + public event System.EventHandler TitleChanged; + public event System.EventHandler VisibleChanged; + public event System.EventHandler FocusedChanged; + public event System.EventHandler WindowBorderChanged; + public event System.EventHandler WindowStateChanged; + public event System.EventHandler KeyDown; + public event System.EventHandler KeyPress; + public event System.EventHandler KeyUp; + public event System.EventHandler MouseLeave; + public event System.EventHandler MouseEnter; + + private CocoaWindowInfo windowInfo; + + static readonly IntPtr nextEventMatchingMask = Selector.Get("nextEventMatchingMask:untilDate:inMode:dequeue:"); + static readonly IntPtr sendEvent = Selector.Get("sendEvent:"); + static readonly IntPtr updateWindows = Selector.Get("updateWindows"); + static readonly IntPtr contentView = Selector.Get("contentView"); + static readonly IntPtr NSDefaultRunLoopMode; + + static CocoaNativeWindow() + { + Cocoa.Initialize(); + NSDefaultRunLoopMode = Cocoa.GetStringConstant(Cocoa.FoundationLibrary, "NSDefaultRunLoopMode"); + } + + public CocoaNativeWindow(int x, int y, int width, int height, string title, GraphicsMode mode, GameWindowFlags options, DisplayDevice device) + { + var contentRect = new System.Drawing.RectangleF(x, y, width, height); + var style = NSWindowStyle.Titled | NSWindowStyle.Resizable; + var bufferingType = NSBackingStore.Buffered; + + IntPtr windowPtr; + windowPtr = Cocoa.SendIntPtr(Class.Get("NSWindow"), Selector.Alloc); + windowPtr = Cocoa.SendIntPtr(windowPtr, Selector.Get("initWithContentRect:styleMask:backing:defer:"), contentRect, (int)style, (int)bufferingType, false); + windowPtr = Cocoa.SendIntPtr(windowPtr, Selector.Autorelease); + + Cocoa.SendVoid(windowPtr, Selector.Get("cascadeTopLeftFromPoint:"), new System.Drawing.PointF(20, 20)); + Cocoa.SendVoid(windowPtr, Selector.Get("setTitle:"), Cocoa.ToNative(title)); + Cocoa.SendVoid(windowPtr, Selector.Get("makeKeyAndOrderFront:"), IntPtr.Zero); + + windowInfo = new CocoaWindowInfo(windowPtr); + } + + public static IntPtr GetView(IntPtr windowHandle) + { + return Cocoa.SendIntPtr(windowHandle, contentView); + } + + public void Close() + { + throw new System.NotImplementedException(); + } + + public void ProcessEvents() + { + var e = Cocoa.SendIntPtr(NSApplication.Handle, nextEventMatchingMask, uint.MaxValue, IntPtr.Zero, NSDefaultRunLoopMode, true); + + if (e == IntPtr.Zero) + return; + + Cocoa.SendVoid(NSApplication.Handle, sendEvent, e); + Cocoa.SendVoid(NSApplication.Handle, updateWindows); + } + + public System.Drawing.Point PointToClient(System.Drawing.Point point) + { + throw new System.NotImplementedException(); + } + + public System.Drawing.Point PointToScreen(System.Drawing.Point point) + { + throw new System.NotImplementedException(); + } + + public System.Drawing.Icon Icon + { + get + { + throw new System.NotImplementedException(); + } + set + { + throw new System.NotImplementedException(); + } + } + + public string Title + { + get + { + throw new System.NotImplementedException(); + } + set + { + throw new System.NotImplementedException(); + } + } + + public bool Focused + { + get + { + throw new System.NotImplementedException(); + } + } + + public bool Visible + { + get + { + //throw new System.NotImplementedException(); + return true; + } + set + { + //throw new System.NotImplementedException(); + } + } + + public bool Exists + { + get + { + return true; + } + } + + public IWindowInfo WindowInfo + { + get + { + return windowInfo; + } + } + + public WindowState WindowState + { + get + { + throw new System.NotImplementedException(); + } + set + { + throw new System.NotImplementedException(); + } + } + + public WindowBorder WindowBorder + { + get + { + throw new System.NotImplementedException(); + } + set + { + throw new System.NotImplementedException(); + } + } + + public System.Drawing.Rectangle Bounds + { + get + { + throw new System.NotImplementedException(); + } + set + { + throw new System.NotImplementedException(); + } + } + + public System.Drawing.Point Location + { + get + { + throw new System.NotImplementedException(); + } + set + { + throw new System.NotImplementedException(); + } + } + + public System.Drawing.Size Size + { + get + { + throw new System.NotImplementedException(); + } + set + { + throw new System.NotImplementedException(); + } + } + + public int X + { + get + { + throw new System.NotImplementedException(); + } + set + { + throw new System.NotImplementedException(); + } + } + + public int Y + { + get + { + throw new System.NotImplementedException(); + } + set + { + throw new System.NotImplementedException(); + } + } + + public int Width + { + get + { + throw new System.NotImplementedException(); + } + set + { + throw new System.NotImplementedException(); + } + } + + public int Height + { + get + { + throw new System.NotImplementedException(); + } + set + { + throw new System.NotImplementedException(); + } + } + + public System.Drawing.Rectangle ClientRectangle + { + get + { + throw new System.NotImplementedException(); + } + set + { + throw new System.NotImplementedException(); + } + } + + public System.Drawing.Size ClientSize + { + get + { + throw new System.NotImplementedException(); + } + set + { + throw new System.NotImplementedException(); + } + } + + public OpenTK.Input.IInputDriver InputDriver + { + get + { + throw new System.NotImplementedException(); + } + } + + public bool CursorVisible + { + get + { + throw new System.NotImplementedException(); + } + set + { + throw new System.NotImplementedException(); + } + } + + public void Dispose() + { + + } + } +} diff --git a/Source/OpenTK/Platform/MacOS/CocoaWindowInfo.cs b/Source/OpenTK/Platform/MacOS/CocoaWindowInfo.cs new file mode 100644 index 00000000..c9b44341 --- /dev/null +++ b/Source/OpenTK/Platform/MacOS/CocoaWindowInfo.cs @@ -0,0 +1,113 @@ +#region License +// +// The Open Toolkit Library License +// +// Copyright (c) 2006 - 2009 the Open Toolkit library. +// +// 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.Collections.Generic; +using System.Diagnostics; +using System.Text; + +namespace OpenTK.Platform.MacOS +{ + /// \internal + /// + /// Describes a Cocoa window. + /// + sealed class CocoaWindowInfo : IWindowInfo + { + IntPtr nsWindowRef; + + bool disposed = false; + + #region Constructors + + /// + /// Constructs a new instance with the specified parameters. + /// + /// A valid NSView reference. + public CocoaWindowInfo(IntPtr nsWindowRef) + { + this.nsWindowRef = nsWindowRef; + } + + #endregion + + #region Public Members + + /// + /// Gets the window reference for this instance. + /// + public IntPtr Handle { get { return nsWindowRef; } } + + /// + /// Gets the view reference for this instance. + /// + public IntPtr ViewHandle + { + get + { + return CocoaNativeWindow.GetView(nsWindowRef); + } + } + + /// Returns a System.String that represents the current window. + /// A System.String that represents the current window. + public override string ToString() + { + return String.Format("MacOS.CocoaWindowInfo: NSWindow {0}", nsWindowRef); + } + + #endregion + + #region IDisposable Members + + public void Dispose() + { + Dispose(true); + } + + void Dispose(bool disposing) + { + if (disposed) + return; + + if (disposing) + { + + } + + disposed = true; + } + + ~CocoaWindowInfo() + { + Dispose(false); + } + + #endregion + } +} \ No newline at end of file diff --git a/Source/OpenTK/Platform/MacOS/MacOSFactory.cs b/Source/OpenTK/Platform/MacOS/MacOSFactory.cs index 8a72db56..d96b0a0b 100644 --- a/Source/OpenTK/Platform/MacOS/MacOSFactory.cs +++ b/Source/OpenTK/Platform/MacOS/MacOSFactory.cs @@ -43,7 +43,7 @@ namespace OpenTK.Platform.MacOS public override INativeWindow CreateNativeWindow(int x, int y, int width, int height, string title, GraphicsMode mode, GameWindowFlags options, DisplayDevice device) { - return new CarbonGLNative(x, y, width, height, title, mode, options, device); + return new CocoaNativeWindow(x, y, width, height, title, mode, options, device); } public override IDisplayDeviceDriver CreateDisplayDeviceDriver() @@ -53,19 +53,19 @@ namespace OpenTK.Platform.MacOS public override IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags) { - return new AglContext(mode, window, shareContext); + return new CocoaContext(mode, window, shareContext, major, minor); } public override IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags) { - return new AglContext(handle, window, shareContext); + return new CocoaContext(handle, window, shareContext, major, minor); } public override GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext() { return (GraphicsContext.GetCurrentContextDelegate)delegate { - return new ContextHandle(Cgl.GetCurrentContext()); + return new ContextHandle(CocoaContext.CurrentContext); }; } diff --git a/Source/OpenTK/Platform/MacOS/NS.cs b/Source/OpenTK/Platform/MacOS/NS.cs index 945a7e25..a23a8179 100644 --- a/Source/OpenTK/Platform/MacOS/NS.cs +++ b/Source/OpenTK/Platform/MacOS/NS.cs @@ -48,6 +48,12 @@ namespace OpenTK.Platform.MacOS static extern IntPtr NSLookupAndBindSymbol(IntPtr s); [DllImport(Library, EntryPoint = "NSAddressOfSymbol")] static extern IntPtr NSAddressOfSymbol(IntPtr symbol); + [DllImport(Library)] + private static extern IntPtr dlopen(String fileName, int flags); + [DllImport(Library)] + private static extern int dlclose(IntPtr handle); + [DllImport (Library)] + private static extern IntPtr dlsym (IntPtr handle, string symbol); public static IntPtr GetAddress(string function) { @@ -87,6 +93,22 @@ namespace OpenTK.Platform.MacOS } return symbol; } + + public static IntPtr GetSymbol(IntPtr handle, string symbol) + { + return dlsym(handle, symbol); + } + + public static IntPtr LoadLibrary(string fileName) + { + const int RTLD_NOW = 2; + return dlopen(fileName, RTLD_NOW); + } + + public static void FreeLibrary(IntPtr handle) + { + dlclose(handle); + } } }