mirror of
				https://github.com/Ryujinx/Opentk.git
				synced 2025-11-04 15:44:53 +00:00 
			
		
		
		
	Merge pull request #158 from thefiddler/fuzzfix
[Mac] Improve stability under Cocoa
This commit is contained in:
		
						commit
						ed7b83178f
					
				| 
						 | 
				
			
			@ -150,6 +150,7 @@ namespace OpenTK.Graphics
 | 
			
		|||
 | 
			
		||||
                        implementation = factory.CreateGLContext(mode, window, shareContext, direct_rendering, major, minor, flags);
 | 
			
		||||
                        handle_cached = ((IGraphicsContextInternal)implementation).Context;
 | 
			
		||||
                        factory.RegisterResource(this);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    AddContext(this);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,44 +1,47 @@
 | 
			
		|||
#region License
 | 
			
		||||
//
 | 
			
		||||
// The Open Toolkit Library License
 | 
			
		||||
// GraphicsContextBase.cs
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2006 - 2009 the Open Toolkit library.
 | 
			
		||||
// Author:
 | 
			
		||||
//       Stefanos A. <stapostol@gmail.com>
 | 
			
		||||
//
 | 
			
		||||
// 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:
 | 
			
		||||
// 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 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.
 | 
			
		||||
// 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;
 | 
			
		||||
using OpenTK.Platform;
 | 
			
		||||
 | 
			
		||||
namespace OpenTK.Graphics
 | 
			
		||||
{
 | 
			
		||||
    // Provides the foundation for all IGraphicsContext implementations.
 | 
			
		||||
    abstract class GraphicsContextBase : IGraphicsContext, IGraphicsContextInternal
 | 
			
		||||
    abstract class GraphicsContextBase : IGraphicsContext, IGraphicsContextInternal, IEquatable<IGraphicsContextInternal>
 | 
			
		||||
    {
 | 
			
		||||
        #region Fields
 | 
			
		||||
 | 
			
		||||
        bool disposed;
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        protected ContextHandle Handle;
 | 
			
		||||
        protected GraphicsMode Mode;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -106,7 +109,53 @@ namespace OpenTK.Graphics
 | 
			
		|||
 | 
			
		||||
        #region IDisposable Members
 | 
			
		||||
 | 
			
		||||
        public abstract void Dispose();
 | 
			
		||||
        public void Dispose()
 | 
			
		||||
        {
 | 
			
		||||
            Dispose(true);
 | 
			
		||||
            GC.SuppressFinalize(this);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected abstract void Dispose(bool disposing);
 | 
			
		||||
 | 
			
		||||
        #if DEBUG
 | 
			
		||||
        ~GraphicsContextBase()
 | 
			
		||||
        {
 | 
			
		||||
            Dispose(false);
 | 
			
		||||
            Debug.Print("[Warning] {0}:{1} leaked. Did you forget to call Dispose()?",
 | 
			
		||||
                GetType().FullName, Handle);
 | 
			
		||||
        }
 | 
			
		||||
        #endif
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region IEquatable<IGraphicsContextInternal> Members
 | 
			
		||||
 | 
			
		||||
        public bool Equals(IGraphicsContextInternal other)
 | 
			
		||||
        {
 | 
			
		||||
            return Context.Equals(other.Context);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Public Members
 | 
			
		||||
 | 
			
		||||
        public override string ToString()
 | 
			
		||||
        {
 | 
			
		||||
            return string.Format("[{0}: IsCurrent={1}, IsDisposed={2}, VSync={3}, SwapInterval={4}, GraphicsMode={5}, ErrorChecking={6}, Implementation={7}, Context={8}]",
 | 
			
		||||
                GetType().Name, IsCurrent, IsDisposed, VSync, SwapInterval, GraphicsMode, ErrorChecking, Implementation, Context);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override int GetHashCode()
 | 
			
		||||
        {
 | 
			
		||||
            return Handle.GetHashCode();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override bool Equals(object obj)
 | 
			
		||||
        {
 | 
			
		||||
            return 
 | 
			
		||||
                obj is IGraphicsContextInternal &&
 | 
			
		||||
                Equals((IGraphicsContextInternal)obj);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -102,7 +102,9 @@ namespace OpenTK
 | 
			
		|||
            this.options = options;
 | 
			
		||||
            this.device = device;
 | 
			
		||||
 | 
			
		||||
            implementation = Factory.Default.CreateNativeWindow(x, y, width, height, title, mode, options, this.device);
 | 
			
		||||
            IPlatformFactory factory = Factory.Default;
 | 
			
		||||
            implementation = factory.CreateNativeWindow(x, y, width, height, title, mode, options, this.device);
 | 
			
		||||
            factory.RegisterResource(this);
 | 
			
		||||
 | 
			
		||||
            if ((options & GameWindowFlags.Fullscreen) != 0)
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -113,7 +113,7 @@ namespace OpenTK.Platform.Dummy
 | 
			
		|||
 | 
			
		||||
        #region --- IDisposable Members ---
 | 
			
		||||
 | 
			
		||||
        public override void Dispose() { IsDisposed = true; }
 | 
			
		||||
        protected override void Dispose(bool disposing) { IsDisposed = true; }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -180,15 +180,9 @@ namespace OpenTK.Platform.Egl
 | 
			
		|||
 | 
			
		||||
        #region IDisposable Members
 | 
			
		||||
 | 
			
		||||
        public override void Dispose()
 | 
			
		||||
        {
 | 
			
		||||
            Dispose(true);
 | 
			
		||||
            GC.SuppressFinalize(this);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Todo: cross-reference the specs. What should happen if the context is destroyed from a different
 | 
			
		||||
        // thread?
 | 
			
		||||
        protected virtual void Dispose(bool manual)
 | 
			
		||||
        protected override void Dispose(bool manual)
 | 
			
		||||
        {
 | 
			
		||||
            if (!IsDisposed)
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -197,19 +191,10 @@ namespace OpenTK.Platform.Egl
 | 
			
		|||
                    Egl.MakeCurrent(WindowInfo.Display, WindowInfo.Surface, WindowInfo.Surface, IntPtr.Zero);
 | 
			
		||||
                    Egl.DestroyContext(WindowInfo.Display, HandleAsEGLContext);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    Debug.Print("[Warning] {0}:{1} was not disposed.", this.GetType().Name, HandleAsEGLContext);
 | 
			
		||||
                }
 | 
			
		||||
                IsDisposed = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ~EglContext()
 | 
			
		||||
        {
 | 
			
		||||
            Dispose(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,6 +47,11 @@ namespace OpenTK.Platform
 | 
			
		|||
        #region Constructors
 | 
			
		||||
 | 
			
		||||
        static Factory()
 | 
			
		||||
        {
 | 
			
		||||
            Toolkit.Init();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Factory()
 | 
			
		||||
        {
 | 
			
		||||
            // Ensure we are correctly initialized.
 | 
			
		||||
            Toolkit.Init();
 | 
			
		||||
| 
						 | 
				
			
			@ -160,6 +165,11 @@ namespace OpenTK.Platform
 | 
			
		|||
            #pragma warning restore 612,618
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void RegisterResource(IDisposable resource)
 | 
			
		||||
        {
 | 
			
		||||
            default_implementation.RegisterResource(resource);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        class UnsupportedPlatform : PlatformFactoryBase
 | 
			
		||||
        {
 | 
			
		||||
            #region Fields
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,5 +55,7 @@ namespace OpenTK.Platform
 | 
			
		|||
 | 
			
		||||
        [Obsolete]
 | 
			
		||||
        Input.IJoystickDriver CreateLegacyJoystickDriver();
 | 
			
		||||
 | 
			
		||||
        void RegisterResource(IDisposable resource);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,6 +55,9 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
        [DllImport (Cocoa.LibObjC)]
 | 
			
		||||
        extern static void objc_registerClassPair(IntPtr classToRegister);
 | 
			
		||||
 | 
			
		||||
        [DllImport (Cocoa.LibObjC)]
 | 
			
		||||
        extern static void objc_disposeClassPair(IntPtr cls);
 | 
			
		||||
 | 
			
		||||
        public static IntPtr Get(string name)
 | 
			
		||||
        {
 | 
			
		||||
            var id = objc_getClass(name);
 | 
			
		||||
| 
						 | 
				
			
			@ -75,7 +78,10 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
            objc_registerClassPair(handle);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        static List<Delegate> storedDelegates = new List<Delegate>();
 | 
			
		||||
        public static void DisposeClass(IntPtr handle)
 | 
			
		||||
        {
 | 
			
		||||
            objc_disposeClassPair(handle);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void RegisterMethod(IntPtr handle, Delegate d, string selector, string typeString)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -89,8 +95,6 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
            {
 | 
			
		||||
                throw new ArgumentException("Could not register method " + d + " in class + " + class_getName(handle));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            storedDelegates.Add(d); // Don't let the garbage collector eat our delegates.
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -209,14 +209,13 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
 | 
			
		||||
                fixed (byte* pBytes = b)
 | 
			
		||||
                {
 | 
			
		||||
                    IntPtr nsData = Cocoa.SendIntPtr(Cocoa.SendIntPtr(Cocoa.SendIntPtr(Class.Get("NSData"), Selector.Alloc),
 | 
			
		||||
                        Selector.Get("initWithBytes:length:"), (IntPtr)pBytes, b.Length),
 | 
			
		||||
                        Selector.Autorelease);
 | 
			
		||||
                    IntPtr nsData = Cocoa.SendIntPtr(Cocoa.SendIntPtr(Class.Get("NSData"), Selector.Alloc),
 | 
			
		||||
                        Selector.Get("initWithBytes:length:"), (IntPtr)pBytes, b.Length);
 | 
			
		||||
 | 
			
		||||
                    IntPtr nsImage = Cocoa.SendIntPtr(Cocoa.SendIntPtr(Cocoa.SendIntPtr(Class.Get("NSImage"), Selector.Alloc), 
 | 
			
		||||
                        Selector.Get("initWithData:"), nsData),
 | 
			
		||||
                        Selector.Autorelease);
 | 
			
		||||
                    IntPtr nsImage = Cocoa.SendIntPtr(Cocoa.SendIntPtr(Class.Get("NSImage"), Selector.Alloc), 
 | 
			
		||||
                        Selector.Get("initWithData:"), nsData);
 | 
			
		||||
 | 
			
		||||
                    Cocoa.SendVoid(nsData, Selector.Release);
 | 
			
		||||
                    return nsImage;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,7 +29,9 @@
 | 
			
		|||
 | 
			
		||||
using System;
 | 
			
		||||
using System.ComponentModel;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.Runtime.InteropServices;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using OpenTK.Platform.MacOS;
 | 
			
		||||
 | 
			
		||||
namespace OpenTK.Platform.MacOS
 | 
			
		||||
| 
						 | 
				
			
			@ -41,14 +43,21 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
 | 
			
		||||
        static readonly IntPtr selQuit = Selector.Get("quit");
 | 
			
		||||
 | 
			
		||||
        internal static void Initialize()
 | 
			
		||||
        static readonly int ThreadId =
 | 
			
		||||
            System.Threading.Thread.CurrentThread.ManagedThreadId;
 | 
			
		||||
 | 
			
		||||
        internal static void Initialize() { }
 | 
			
		||||
 | 
			
		||||
        static NSApplication()
 | 
			
		||||
        {
 | 
			
		||||
            Cocoa.Initialize();
 | 
			
		||||
 | 
			
		||||
            // Create the NSAutoreleasePool
 | 
			
		||||
            AutoreleasePool = Cocoa.SendIntPtr(Cocoa.SendIntPtr(Class.NSAutoreleasePool, Selector.Alloc), Selector.Init);
 | 
			
		||||
 | 
			
		||||
            // Register a Quit method to be called on cmd-q
 | 
			
		||||
            IntPtr nsapp = Class.Get("NSApplication");
 | 
			
		||||
            Class.RegisterMethod(nsapp, new OnQuitDelegate(OnQuit), "quit", "v@:");
 | 
			
		||||
            Class.RegisterMethod(nsapp, OnQuitHandler, "quit", "v@:");
 | 
			
		||||
 | 
			
		||||
            // Fetch the application handle
 | 
			
		||||
            Handle = Cocoa.SendIntPtr(nsapp, Selector.Get("sharedApplication"));
 | 
			
		||||
| 
						 | 
				
			
			@ -58,22 +67,17 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
            Cocoa.SendVoid(Handle, Selector.Get("activateIgnoringOtherApps:"), true);
 | 
			
		||||
 | 
			
		||||
            // 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);
 | 
			
		||||
            var menubar = Cocoa.SendIntPtr(Class.Get("NSMenu"), Selector.Alloc);
 | 
			
		||||
            var menuItem = Cocoa.SendIntPtr(Class.Get("NSMenuItem"), Selector.Alloc);
 | 
			
		||||
 | 
			
		||||
            // Add menu item to bar, and bar to application
 | 
			
		||||
            Cocoa.SendIntPtr(menubar, Selector.Get("addItem:"), menuItem);
 | 
			
		||||
            Cocoa.SendIntPtr(Handle, Selector.Get("setMainMenu:"), menubar);
 | 
			
		||||
 | 
			
		||||
            // Add a "Quit" menu item and bind the button.
 | 
			
		||||
            var appMenu = Cocoa.SendIntPtr(Cocoa.SendIntPtr(Class.Get("NSMenu"), Selector.Alloc),
 | 
			
		||||
                Selector.Autorelease);
 | 
			
		||||
            var quitMenuItem = Cocoa.SendIntPtr(Cocoa.SendIntPtr(Cocoa.SendIntPtr(Class.Get("NSMenuItem"), Selector.Alloc),
 | 
			
		||||
                Selector.Get("initWithTitle:action:keyEquivalent:"), Cocoa.ToNSString("Quit"), selQuit, Cocoa.ToNSString("q")),
 | 
			
		||||
                Selector.Autorelease);
 | 
			
		||||
            var appMenu = Cocoa.SendIntPtr(Class.Get("NSMenu"), Selector.Alloc);
 | 
			
		||||
            var quitMenuItem = Cocoa.SendIntPtr(Cocoa.SendIntPtr(Class.Get("NSMenuItem"), Selector.Alloc),
 | 
			
		||||
                Selector.Get("initWithTitle:action:keyEquivalent:"), Cocoa.ToNSString("Quit"), selQuit, Cocoa.ToNSString("q"));
 | 
			
		||||
 | 
			
		||||
            Cocoa.SendIntPtr(appMenu, Selector.Get("addItem:"), quitMenuItem);
 | 
			
		||||
            Cocoa.SendIntPtr(menuItem, Selector.Get("setSubmenu:"), appMenu);
 | 
			
		||||
| 
						 | 
				
			
			@ -99,9 +103,27 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
            Cocoa.SendVoid(settings, Selector.Release);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal static bool IsUIThread
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                int thread_id = Thread.CurrentThread.ManagedThreadId;
 | 
			
		||||
                bool is_ui_thread = thread_id == NSApplication.ThreadId;
 | 
			
		||||
                if (!is_ui_thread)
 | 
			
		||||
                {
 | 
			
		||||
                    Debug.Print("[Warning] UI resources must be disposed in the UI thread #{0}, not #{1}.",
 | 
			
		||||
                        NSApplication.ThreadId, thread_id);
 | 
			
		||||
                }
 | 
			
		||||
                return is_ui_thread;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal static event EventHandler<CancelEventArgs> Quit = delegate { };
 | 
			
		||||
 | 
			
		||||
        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
 | 
			
		||||
        delegate void OnQuitDelegate(IntPtr self, IntPtr cmd);
 | 
			
		||||
 | 
			
		||||
        static OnQuitDelegate OnQuitHandler = OnQuit;
 | 
			
		||||
        static void OnQuit(IntPtr self, IntPtr cmd)
 | 
			
		||||
        {
 | 
			
		||||
            var e = new CancelEventArgs();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -326,23 +326,16 @@ namespace OpenTK
 | 
			
		|||
 | 
			
		||||
        #region IDisposable Members
 | 
			
		||||
 | 
			
		||||
        ~CocoaContext()
 | 
			
		||||
        {
 | 
			
		||||
            Dispose(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void Dispose()
 | 
			
		||||
        {
 | 
			
		||||
            Dispose(true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void Dispose(bool disposing)
 | 
			
		||||
        protected override void Dispose(bool disposing)
 | 
			
		||||
        {
 | 
			
		||||
            if (IsDisposed || Handle.Handle == IntPtr.Zero)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            Debug.Print("Disposing of Cocoa context.");
 | 
			
		||||
 | 
			
		||||
            if (!NSApplication.IsUIThread)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            Cocoa.SendVoid(NSOpenGLContext, Selector.Get("clearCurrentContext"));
 | 
			
		||||
            Cocoa.SendVoid(Handle.Handle, Selector.Get("clearDrawable"));
 | 
			
		||||
            Cocoa.SendVoid(Handle.Handle, Selector.Get("release"));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -128,6 +128,7 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
        private CocoaWindowInfo windowInfo;
 | 
			
		||||
        private IntPtr windowClass;
 | 
			
		||||
        private IntPtr trackingArea;
 | 
			
		||||
        private IntPtr current_icon_handle;
 | 
			
		||||
        private bool disposed = false;
 | 
			
		||||
        private bool exists;
 | 
			
		||||
        private bool cursorVisible = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -145,26 +146,44 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
 | 
			
		||||
        public CocoaNativeWindow(int x, int y, int width, int height, string title, GraphicsMode mode, GameWindowFlags options, DisplayDevice device)
 | 
			
		||||
        {
 | 
			
		||||
            // Create callback methods. We need to store those,
 | 
			
		||||
            // otherwise the GC may collect them while they are
 | 
			
		||||
            // still active.
 | 
			
		||||
            WindowKeyDownHandler = WindowKeyDown;
 | 
			
		||||
            WindowDidResizeHandler = WindowDidResize;
 | 
			
		||||
            WindowDidMoveHandler = WindowDidMove;
 | 
			
		||||
            WindowDidBecomeKeyHandler = WindowDidBecomeKey;
 | 
			
		||||
            WindowDidResignKeyHandler = WindowDidResignKey;
 | 
			
		||||
            WindowWillMiniaturizeHandler = WindowWillMiniaturize;
 | 
			
		||||
            WindowDidMiniaturizeHandler = WindowDidMiniaturize;
 | 
			
		||||
            WindowDidDeminiaturizeHandler = WindowDidDeminiaturize;
 | 
			
		||||
            WindowShouldZoomToFrameHandler = WindowShouldZoomToFrame;
 | 
			
		||||
            WindowShouldCloseHandler = WindowShouldClose;
 | 
			
		||||
            AcceptsFirstResponderHandler = AcceptsFirstResponder;
 | 
			
		||||
            CanBecomeKeyWindowHandler = CanBecomeKeyWindow;
 | 
			
		||||
            CanBecomeMainWindowHandler = CanBecomeMainWindow;
 | 
			
		||||
            ResetCursorRectsHandler = ResetCursorRects;
 | 
			
		||||
 | 
			
		||||
            // Create the window class
 | 
			
		||||
            Interlocked.Increment(ref UniqueId);
 | 
			
		||||
            windowClass = Class.AllocateClass("OpenTK_GameWindow" + UniqueId, "NSWindow");
 | 
			
		||||
            Class.RegisterMethod(windowClass, new WindowKeyDownDelegate(WindowKeyDown), "keyDown:", "v@:@");
 | 
			
		||||
            Class.RegisterMethod(windowClass, new WindowDidResizeDelegate(WindowDidResize), "windowDidResize:", "v@:@");
 | 
			
		||||
            Class.RegisterMethod(windowClass, new WindowDidMoveDelegate(WindowDidMove), "windowDidMove:", "v@:@");
 | 
			
		||||
            Class.RegisterMethod(windowClass, new WindowDidBecomeKeyDelegate(WindowDidBecomeKey), "windowDidBecomeKey:", "v@:@");
 | 
			
		||||
            Class.RegisterMethod(windowClass, new WindowDidResignKeyDelegate(WindowDidResignKey), "windowDidResignKey:", "v@:@");
 | 
			
		||||
            Class.RegisterMethod(windowClass, new WindowWillMiniaturizeDelegate(WindowWillMiniaturize), "windowWillMiniaturize:", "v@:@");
 | 
			
		||||
            Class.RegisterMethod(windowClass, new WindowDidMiniaturizeDelegate(WindowDidMiniaturize), "windowDidMiniaturize:", "v@:@");
 | 
			
		||||
            Class.RegisterMethod(windowClass, new WindowDidDeminiaturizeDelegate(WindowDidDeminiaturize), "windowDidDeminiaturize:", "v@:@");
 | 
			
		||||
            Class.RegisterMethod(windowClass, new WindowShouldZoomToFrameDelegate(WindowShouldZoomToFrame), "windowShouldZoom:toFrame:", "b@:@{NSRect={NSPoint=ff}{NSSize=ff}}");
 | 
			
		||||
            Class.RegisterMethod(windowClass, new WindowShouldCloseDelegate(WindowShouldClose), "windowShouldClose:", "b@:@");
 | 
			
		||||
            Class.RegisterMethod(windowClass, new AcceptsFirstResponderDelegate(AcceptsFirstResponder), "acceptsFirstResponder", "b@:");
 | 
			
		||||
            Class.RegisterMethod(windowClass, new CanBecomeKeyWindowDelegate(CanBecomeKeyWindow), "canBecomeKeyWindow", "b@:");
 | 
			
		||||
            Class.RegisterMethod(windowClass, new CanBecomeMainWindowDelegate(CanBecomeMainWindow), "canBecomeMainWindow", "b@:");
 | 
			
		||||
            int unique_id = Interlocked.Increment(ref UniqueId);
 | 
			
		||||
            windowClass = Class.AllocateClass("OpenTK_GameWindow" + unique_id, "NSWindow");
 | 
			
		||||
            Class.RegisterMethod(windowClass, WindowKeyDownHandler, "keyDown:", "v@:@");
 | 
			
		||||
            Class.RegisterMethod(windowClass, WindowDidResizeHandler, "windowDidResize:", "v@:@");
 | 
			
		||||
            Class.RegisterMethod(windowClass, WindowDidMoveHandler, "windowDidMove:", "v@:@");
 | 
			
		||||
            Class.RegisterMethod(windowClass, WindowDidBecomeKeyHandler, "windowDidBecomeKey:", "v@:@");
 | 
			
		||||
            Class.RegisterMethod(windowClass, WindowDidResignKeyHandler, "windowDidResignKey:", "v@:@");
 | 
			
		||||
            Class.RegisterMethod(windowClass, WindowWillMiniaturizeHandler, "windowWillMiniaturize:", "v@:@");
 | 
			
		||||
            Class.RegisterMethod(windowClass, WindowDidMiniaturizeHandler, "windowDidMiniaturize:", "v@:@");
 | 
			
		||||
            Class.RegisterMethod(windowClass, WindowDidDeminiaturizeHandler, "windowDidDeminiaturize:", "v@:@");
 | 
			
		||||
            Class.RegisterMethod(windowClass, WindowShouldZoomToFrameHandler, "windowShouldZoom:toFrame:", "b@:@{NSRect={NSPoint=ff}{NSSize=ff}}");
 | 
			
		||||
            Class.RegisterMethod(windowClass, WindowShouldCloseHandler, "windowShouldClose:", "b@:@");
 | 
			
		||||
            Class.RegisterMethod(windowClass, AcceptsFirstResponderHandler, "acceptsFirstResponder", "b@:");
 | 
			
		||||
            Class.RegisterMethod(windowClass, CanBecomeKeyWindowHandler, "canBecomeKeyWindow", "b@:");
 | 
			
		||||
            Class.RegisterMethod(windowClass, CanBecomeMainWindowHandler, "canBecomeMainWindow", "b@:");
 | 
			
		||||
            Class.RegisterClass(windowClass);
 | 
			
		||||
 | 
			
		||||
            IntPtr viewClass = Class.AllocateClass("OpenTK_NSView" + UniqueId, "NSView");
 | 
			
		||||
            Class.RegisterMethod(viewClass, new ResetCursorRectsDelegate(ResetCursorRects), "resetCursorRects", "v@:");
 | 
			
		||||
            IntPtr viewClass = Class.AllocateClass("OpenTK_NSView" + unique_id, "NSView");
 | 
			
		||||
            Class.RegisterMethod(viewClass, ResetCursorRectsHandler, "resetCursorRects", "v@:");
 | 
			
		||||
            Class.RegisterClass(viewClass);
 | 
			
		||||
 | 
			
		||||
            // Create window instance
 | 
			
		||||
| 
						 | 
				
			
			@ -182,15 +201,34 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
            var style = GetStyleMask(windowBorder);
 | 
			
		||||
            var bufferingType = NSBackingStore.Buffered;
 | 
			
		||||
 | 
			
		||||
            IntPtr windowPtr;
 | 
			
		||||
            windowPtr = Cocoa.SendIntPtr(windowClass, Selector.Alloc);
 | 
			
		||||
            windowPtr = Cocoa.SendIntPtr(windowPtr, Selector.Get("initWithContentRect:styleMask:backing:defer:"), contentRect, (int)style, (int)bufferingType, false);
 | 
			
		||||
            IntPtr classPtr;
 | 
			
		||||
            classPtr = Cocoa.SendIntPtr(windowClass, Selector.Alloc);
 | 
			
		||||
            if (classPtr == IntPtr.Zero)
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Print("[Error] Failed to allocate window class.");
 | 
			
		||||
                throw new PlatformException();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            bool defer = false;
 | 
			
		||||
            IntPtr windowPtr = Cocoa.SendIntPtr(classPtr, Selector.Get("initWithContentRect:styleMask:backing:defer:"), contentRect, (int)style, (int)bufferingType, defer);
 | 
			
		||||
            if (windowPtr == IntPtr.Zero)
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Print("[Error] Failed to initialize window with ({0}, {1}, {2}, {3}).",
 | 
			
		||||
                    contentRect, style, bufferingType, defer);
 | 
			
		||||
                throw new PlatformException();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Replace view with our custom implementation
 | 
			
		||||
            // that overrides resetCursorRects (maybe there is
 | 
			
		||||
            // a better way to implement this override?)
 | 
			
		||||
            // Existing view:
 | 
			
		||||
            IntPtr viewPtr = Cocoa.SendIntPtr(windowPtr, Selector.Get("contentView"));
 | 
			
		||||
            if (viewPtr == IntPtr.Zero)
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Print("[Error] Failed to retrieve content view for window {0}.", windowPtr);
 | 
			
		||||
                throw new PlatformException();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Our custom view with the same bounds:
 | 
			
		||||
            viewPtr = Cocoa.SendIntPtr(
 | 
			
		||||
                Cocoa.SendIntPtr(viewClass, Selector.Alloc),
 | 
			
		||||
| 
						 | 
				
			
			@ -200,6 +238,11 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
            {
 | 
			
		||||
                Cocoa.SendVoid(windowPtr, Selector.Get("setContentView:"), viewPtr);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Print("[Error] Failed to initialize content view with frame {0}.", selBounds);
 | 
			
		||||
                throw new PlatformException();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            windowInfo = new CocoaWindowInfo(windowPtr);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -214,21 +257,50 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
            NSApplication.Quit += ApplicationQuit;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
 | 
			
		||||
        delegate void WindowKeyDownDelegate(IntPtr self, IntPtr cmd, IntPtr notification);
 | 
			
		||||
        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
 | 
			
		||||
        delegate void WindowDidResizeDelegate(IntPtr self, IntPtr cmd, IntPtr notification);
 | 
			
		||||
        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
 | 
			
		||||
        delegate void WindowDidMoveDelegate(IntPtr self, IntPtr cmd, IntPtr notification);
 | 
			
		||||
        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
 | 
			
		||||
        delegate void WindowDidBecomeKeyDelegate(IntPtr self, IntPtr cmd, IntPtr notification);
 | 
			
		||||
        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
 | 
			
		||||
        delegate void WindowDidResignKeyDelegate(IntPtr self, IntPtr cmd, IntPtr notification);
 | 
			
		||||
        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
 | 
			
		||||
        delegate void WindowWillMiniaturizeDelegate(IntPtr self, IntPtr cmd, IntPtr notification);
 | 
			
		||||
        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
 | 
			
		||||
        delegate void WindowDidMiniaturizeDelegate(IntPtr self, IntPtr cmd, IntPtr notification);
 | 
			
		||||
        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
 | 
			
		||||
        delegate void WindowDidDeminiaturizeDelegate(IntPtr self, IntPtr cmd, IntPtr notification);
 | 
			
		||||
        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
 | 
			
		||||
        delegate bool WindowShouldZoomToFrameDelegate(IntPtr self, IntPtr cmd, IntPtr nsWindow, RectangleF toFrame);
 | 
			
		||||
        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
 | 
			
		||||
        delegate bool WindowShouldCloseDelegate(IntPtr self, IntPtr cmd, IntPtr sender);
 | 
			
		||||
        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
 | 
			
		||||
        delegate bool AcceptsFirstResponderDelegate(IntPtr self, IntPtr cmd);
 | 
			
		||||
        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
 | 
			
		||||
        delegate bool CanBecomeKeyWindowDelegate(IntPtr self, IntPtr cmd);
 | 
			
		||||
        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
 | 
			
		||||
        delegate bool CanBecomeMainWindowDelegate(IntPtr self, IntPtr cmd);
 | 
			
		||||
        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
 | 
			
		||||
        delegate void ResetCursorRectsDelegate(IntPtr self, IntPtr cmd);
 | 
			
		||||
 | 
			
		||||
        WindowKeyDownDelegate WindowKeyDownHandler;
 | 
			
		||||
        WindowDidResizeDelegate WindowDidResizeHandler;
 | 
			
		||||
        WindowDidMoveDelegate WindowDidMoveHandler;
 | 
			
		||||
        WindowDidBecomeKeyDelegate WindowDidBecomeKeyHandler;
 | 
			
		||||
        WindowDidResignKeyDelegate WindowDidResignKeyHandler;
 | 
			
		||||
        WindowWillMiniaturizeDelegate WindowWillMiniaturizeHandler;
 | 
			
		||||
        WindowDidMiniaturizeDelegate WindowDidMiniaturizeHandler;
 | 
			
		||||
        WindowDidDeminiaturizeDelegate WindowDidDeminiaturizeHandler;
 | 
			
		||||
        WindowShouldZoomToFrameDelegate WindowShouldZoomToFrameHandler;
 | 
			
		||||
        WindowShouldCloseDelegate WindowShouldCloseHandler;
 | 
			
		||||
        AcceptsFirstResponderDelegate AcceptsFirstResponderHandler;
 | 
			
		||||
        CanBecomeKeyWindowDelegate CanBecomeKeyWindowHandler;
 | 
			
		||||
        CanBecomeMainWindowDelegate CanBecomeMainWindowHandler;
 | 
			
		||||
        ResetCursorRectsDelegate ResetCursorRectsHandler;
 | 
			
		||||
 | 
			
		||||
        private void WindowKeyDown(IntPtr self, IntPtr cmd, IntPtr notification)
 | 
			
		||||
        {
 | 
			
		||||
            // Steal the event to remove the "beep" sound that is normally played for unhandled key events.
 | 
			
		||||
| 
						 | 
				
			
			@ -236,7 +308,14 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
 | 
			
		||||
        private void WindowDidResize(IntPtr self, IntPtr cmd, IntPtr notification)
 | 
			
		||||
        {
 | 
			
		||||
            OnResize(true);
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                OnResize(true);
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Print(e.ToString());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnResize(bool resetTracking)
 | 
			
		||||
| 
						 | 
				
			
			@ -258,77 +337,141 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
 | 
			
		||||
        private void ApplicationQuit(object sender, CancelEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            bool close = WindowShouldClose(windowInfo.Handle, IntPtr.Zero, IntPtr.Zero);
 | 
			
		||||
            e.Cancel |= !close;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                bool close = WindowShouldClose(windowInfo.Handle, IntPtr.Zero, IntPtr.Zero);
 | 
			
		||||
                e.Cancel |= !close;
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Print(ex.ToString());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WindowDidMove(IntPtr self, IntPtr cmd, IntPtr notification)
 | 
			
		||||
        {
 | 
			
		||||
            // Problem: Called only when you stop moving for a brief moment,
 | 
			
		||||
            // not each frame as it is on PC.
 | 
			
		||||
            OnMove(EventArgs.Empty);
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                // Problem: Called only when you stop moving for a brief moment,
 | 
			
		||||
                // not each frame as it is on PC.
 | 
			
		||||
                OnMove(EventArgs.Empty);
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Print(e.ToString());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WindowDidBecomeKey(IntPtr self, IntPtr cmd, IntPtr notification)
 | 
			
		||||
        {
 | 
			
		||||
            OnFocusedChanged(EventArgs.Empty);
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                OnFocusedChanged(EventArgs.Empty);
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Print(e.ToString());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WindowDidResignKey(IntPtr self, IntPtr cmd, IntPtr notification)
 | 
			
		||||
        {
 | 
			
		||||
            OnFocusedChanged(EventArgs.Empty);
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                OnFocusedChanged(EventArgs.Empty);
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Print(e.ToString());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WindowWillMiniaturize(IntPtr self, IntPtr cmd, IntPtr notification)
 | 
			
		||||
        {
 | 
			
		||||
            // Can get stuck in weird states if we maximize, then minimize; 
 | 
			
		||||
            // restoring to the old state would override the normalBounds.
 | 
			
		||||
            // To avoid this without adding complexity, just restore state here.
 | 
			
		||||
            RestoreWindowState(); // Avoid getting in weird states
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                // Can get stuck in weird states if we maximize, then minimize; 
 | 
			
		||||
                // restoring to the old state would override the normalBounds.
 | 
			
		||||
                // To avoid this without adding complexity, just restore state here.
 | 
			
		||||
                RestoreWindowState(); // Avoid getting in weird states
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Print(e.ToString());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WindowDidMiniaturize(IntPtr self, IntPtr cmd, IntPtr notification)
 | 
			
		||||
        {
 | 
			
		||||
            windowState = WindowState.Minimized;
 | 
			
		||||
            OnWindowStateChanged(EventArgs.Empty);
 | 
			
		||||
            OnResize(false); // Don't set tracking area when we minimize
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                windowState = WindowState.Minimized;
 | 
			
		||||
                OnWindowStateChanged(EventArgs.Empty);
 | 
			
		||||
                OnResize(false); // Don't set tracking area when we minimize
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Print(e.ToString());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WindowDidDeminiaturize(IntPtr self, IntPtr cmd, IntPtr notification)
 | 
			
		||||
        {
 | 
			
		||||
            windowState = WindowState.Normal;
 | 
			
		||||
            OnWindowStateChanged(EventArgs.Empty);
 | 
			
		||||
            OnResize(true);
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                windowState = WindowState.Normal;
 | 
			
		||||
                OnWindowStateChanged(EventArgs.Empty);
 | 
			
		||||
                OnResize(true);
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Print(e.ToString());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private bool WindowShouldZoomToFrame(IntPtr self, IntPtr cmd, IntPtr nsWindow, RectangleF toFrame)
 | 
			
		||||
        {
 | 
			
		||||
            if (windowState == WindowState.Maximized)
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                WindowState = WindowState.Normal;
 | 
			
		||||
                if (windowState == WindowState.Maximized)
 | 
			
		||||
                {
 | 
			
		||||
                    WindowState = WindowState.Normal;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    previousBounds = InternalBounds;
 | 
			
		||||
                    previousWindowBorder = WindowBorder;
 | 
			
		||||
 | 
			
		||||
                    InternalBounds = toFrame;
 | 
			
		||||
                    windowState = WindowState.Maximized;
 | 
			
		||||
 | 
			
		||||
                    OnWindowStateChanged(EventArgs.Empty);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                previousBounds = InternalBounds;
 | 
			
		||||
                previousWindowBorder = WindowBorder;
 | 
			
		||||
 | 
			
		||||
                InternalBounds = toFrame;
 | 
			
		||||
                windowState = WindowState.Maximized;
 | 
			
		||||
 | 
			
		||||
                OnWindowStateChanged(EventArgs.Empty);
 | 
			
		||||
                Debug.Print(e.ToString());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private bool WindowShouldClose(IntPtr self, IntPtr cmd, IntPtr sender)
 | 
			
		||||
        {
 | 
			
		||||
            var cancelArgs = new CancelEventArgs();
 | 
			
		||||
            OnClosing(cancelArgs);
 | 
			
		||||
 | 
			
		||||
            if (!cancelArgs.Cancel)
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                OnClosed(EventArgs.Empty);
 | 
			
		||||
                return true;
 | 
			
		||||
                var cancelArgs = new CancelEventArgs();
 | 
			
		||||
                OnClosing(cancelArgs);
 | 
			
		||||
 | 
			
		||||
                if (!cancelArgs.Cancel)
 | 
			
		||||
                {
 | 
			
		||||
                    OnClosed(EventArgs.Empty);
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Print(e.ToString());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -351,24 +494,31 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
 | 
			
		||||
        private void ResetTrackingArea()
 | 
			
		||||
        {
 | 
			
		||||
            var owner = windowInfo.ViewHandle;
 | 
			
		||||
            if (trackingArea != IntPtr.Zero)
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                Cocoa.SendVoid(owner, selRemoveTrackingArea, trackingArea);
 | 
			
		||||
                Cocoa.SendVoid(trackingArea, Selector.Release);
 | 
			
		||||
                var owner = windowInfo.ViewHandle;
 | 
			
		||||
                if (trackingArea != IntPtr.Zero)
 | 
			
		||||
                {
 | 
			
		||||
                    Cocoa.SendVoid(owner, selRemoveTrackingArea, trackingArea);
 | 
			
		||||
                    Cocoa.SendVoid(trackingArea, Selector.Release);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var ownerBounds = Cocoa.SendRect(owner, selBounds);
 | 
			
		||||
                var options = (int)(
 | 
			
		||||
                    NSTrackingAreaOptions.MouseEnteredAndExited |
 | 
			
		||||
                    NSTrackingAreaOptions.ActiveInKeyWindow |
 | 
			
		||||
                    NSTrackingAreaOptions.MouseMoved |
 | 
			
		||||
                    NSTrackingAreaOptions.CursorUpdate);
 | 
			
		||||
 | 
			
		||||
                trackingArea = Cocoa.SendIntPtr(Cocoa.SendIntPtr(Class.Get("NSTrackingArea"), Selector.Alloc),
 | 
			
		||||
                    selInitWithRect, ownerBounds, options, owner, IntPtr.Zero);
 | 
			
		||||
 | 
			
		||||
                Cocoa.SendVoid(owner, selAddTrackingArea, trackingArea);
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Print(e.ToString());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var ownerBounds = Cocoa.SendRect(owner, selBounds);
 | 
			
		||||
            var options = (int)(
 | 
			
		||||
                NSTrackingAreaOptions.MouseEnteredAndExited |
 | 
			
		||||
                NSTrackingAreaOptions.ActiveInKeyWindow |
 | 
			
		||||
                NSTrackingAreaOptions.MouseMoved |
 | 
			
		||||
                NSTrackingAreaOptions.CursorUpdate);
 | 
			
		||||
 | 
			
		||||
            trackingArea = Cocoa.SendIntPtr(Cocoa.SendIntPtr(Class.Get("NSTrackingArea"), Selector.Alloc),
 | 
			
		||||
                selInitWithRect, ownerBounds, options, owner, IntPtr.Zero);
 | 
			
		||||
 | 
			
		||||
            Cocoa.SendVoid(owner, selAddTrackingArea, trackingArea);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void Close()
 | 
			
		||||
| 
						 | 
				
			
			@ -573,20 +723,7 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
            if (shouldClose)
 | 
			
		||||
            {
 | 
			
		||||
                shouldClose = false;
 | 
			
		||||
 | 
			
		||||
                // PerformClose is equivalent to pressing the close-button, which
 | 
			
		||||
                // does not work in a borderless window. Handle this special case.
 | 
			
		||||
                if (GetStyleMask() == NSWindowStyle.Borderless)
 | 
			
		||||
                {
 | 
			
		||||
                    if (WindowShouldClose(IntPtr.Zero, IntPtr.Zero, IntPtr.Zero))
 | 
			
		||||
                    {
 | 
			
		||||
                        Cocoa.SendVoid(windowInfo.Handle, selClose);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    Cocoa.SendVoid(windowInfo.Handle, selPerformClose, windowInfo.Handle);
 | 
			
		||||
                }
 | 
			
		||||
                CloseWindow(false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -613,13 +750,35 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
            get { return icon; }
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                icon = value;
 | 
			
		||||
                using (Image img = icon.ToBitmap())
 | 
			
		||||
                if (value != null && value != icon)
 | 
			
		||||
                {
 | 
			
		||||
                    IntPtr nsimg = Cocoa.ToNSImage(img);
 | 
			
		||||
                    Cocoa.SendVoid(NSApplication.Handle, selSetApplicationIconImage, nsimg);
 | 
			
		||||
                    // Create and set new icon
 | 
			
		||||
                    IntPtr nsimg = IntPtr.Zero;
 | 
			
		||||
                    using (Image img = value.ToBitmap())
 | 
			
		||||
                    {
 | 
			
		||||
                        nsimg = Cocoa.ToNSImage(img);
 | 
			
		||||
                        if (nsimg != IntPtr.Zero)
 | 
			
		||||
                        {
 | 
			
		||||
                            Cocoa.SendVoid(NSApplication.Handle, selSetApplicationIconImage, nsimg);
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            Debug.Print("[Mac] Failed to create NSImage for {0}", value);
 | 
			
		||||
                            return;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    // Release previous icon
 | 
			
		||||
                    if (current_icon_handle != IntPtr.Zero)
 | 
			
		||||
                    {
 | 
			
		||||
                        Cocoa.SendVoid(current_icon_handle, Selector.Release);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    // Raise IconChanged event
 | 
			
		||||
                    current_icon_handle = nsimg;
 | 
			
		||||
                    icon = value;
 | 
			
		||||
                    OnIconChanged(EventArgs.Empty);
 | 
			
		||||
                }
 | 
			
		||||
                OnIconChanged(EventArgs.Empty);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -889,21 +1048,19 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
            // effect on output quality."
 | 
			
		||||
            IntPtr imgdata =
 | 
			
		||||
                Cocoa.SendIntPtr(
 | 
			
		||||
                    Cocoa.SendIntPtr(
 | 
			
		||||
                        Cocoa.SendIntPtr(NSBitmapImageRep, Selector.Alloc),
 | 
			
		||||
                        selInitWithBitmapDataPlanes,
 | 
			
		||||
                        IntPtr.Zero,
 | 
			
		||||
                        cursor.Width,
 | 
			
		||||
                        cursor.Height,
 | 
			
		||||
                        8,
 | 
			
		||||
                        4,
 | 
			
		||||
                        1,
 | 
			
		||||
                        0,
 | 
			
		||||
                        NSDeviceRGBColorSpace,
 | 
			
		||||
                        NSBitmapFormat.AlphaFirst,
 | 
			
		||||
                        4 * cursor.Width,
 | 
			
		||||
                        32),
 | 
			
		||||
                    Selector.Autorelease);
 | 
			
		||||
                    Cocoa.SendIntPtr(NSBitmapImageRep, Selector.Alloc),
 | 
			
		||||
                    selInitWithBitmapDataPlanes,
 | 
			
		||||
                    IntPtr.Zero,
 | 
			
		||||
                    cursor.Width,
 | 
			
		||||
                    cursor.Height,
 | 
			
		||||
                    8,
 | 
			
		||||
                    4,
 | 
			
		||||
                    1,
 | 
			
		||||
                    0,
 | 
			
		||||
                    NSDeviceRGBColorSpace,
 | 
			
		||||
                    NSBitmapFormat.AlphaFirst,
 | 
			
		||||
                    4 * cursor.Width,
 | 
			
		||||
                    32);
 | 
			
		||||
            if (imgdata == IntPtr.Zero)
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Print("Failed to create NSBitmapImageRep with size ({0},{1]})",
 | 
			
		||||
| 
						 | 
				
			
			@ -935,14 +1092,13 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
            // Construct the actual NSImage
 | 
			
		||||
            IntPtr img = 
 | 
			
		||||
                Cocoa.SendIntPtr(
 | 
			
		||||
                    Cocoa.SendIntPtr(
 | 
			
		||||
                        Cocoa.SendIntPtr(NSImage, Selector.Alloc),
 | 
			
		||||
                        selInitWithSize,
 | 
			
		||||
                        new SizeF(cursor.Width, cursor.Height)),
 | 
			
		||||
                    Selector.Autorelease);
 | 
			
		||||
                    Cocoa.SendIntPtr(NSImage, Selector.Alloc),
 | 
			
		||||
                    selInitWithSize,
 | 
			
		||||
                    new SizeF(cursor.Width, cursor.Height));
 | 
			
		||||
            if (img == IntPtr.Zero)
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Print("Failed to construct NSImage from NSBitmapImageRep");
 | 
			
		||||
                Cocoa.SendVoid(imgdata, Selector.Release);
 | 
			
		||||
                return IntPtr.Zero;
 | 
			
		||||
            }
 | 
			
		||||
            Cocoa.SendVoid(img, selAddRepresentation, imgdata);
 | 
			
		||||
| 
						 | 
				
			
			@ -950,14 +1106,13 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
            // Convert the NSImage to a NSCursor
 | 
			
		||||
            IntPtr nscursor =
 | 
			
		||||
                Cocoa.SendIntPtr(
 | 
			
		||||
                    Cocoa.SendIntPtr(
 | 
			
		||||
                        Cocoa.SendIntPtr(NSCursor, Selector.Alloc),
 | 
			
		||||
                        selInitWithImageHotSpot,
 | 
			
		||||
                        img,
 | 
			
		||||
                        new PointF(cursor.X, cursor.Y)
 | 
			
		||||
                    ),
 | 
			
		||||
                    Selector.Autorelease);
 | 
			
		||||
                    Cocoa.SendIntPtr(NSCursor, Selector.Alloc),
 | 
			
		||||
                    selInitWithImageHotSpot,
 | 
			
		||||
                    img,
 | 
			
		||||
                    new PointF(cursor.X, cursor.Y));
 | 
			
		||||
 | 
			
		||||
            Cocoa.SendVoid(imgdata, Selector.Release);
 | 
			
		||||
            Cocoa.SendVoid(img, Selector.Release);
 | 
			
		||||
            return nscursor;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -994,15 +1149,15 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
            get { return cursorVisible; }
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                cursorVisible = value;
 | 
			
		||||
                if (value)
 | 
			
		||||
                if (value && !cursorVisible)
 | 
			
		||||
                {
 | 
			
		||||
                    SetCursorVisible(true);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                else if (!value && cursorVisible)
 | 
			
		||||
                {
 | 
			
		||||
                    SetCursorVisible(false);
 | 
			
		||||
                }
 | 
			
		||||
                cursorVisible = value;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1011,15 +1166,21 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
            if (disposed)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            Debug.Print("Disposing of CocoaNativeWindow.");
 | 
			
		||||
            NSApplication.Quit -= ApplicationQuit;
 | 
			
		||||
            Debug.Print("Disposing of CocoaNativeWindow (disposing={0}).", disposing);
 | 
			
		||||
 | 
			
		||||
            CursorVisible = true;
 | 
			
		||||
            disposed = true;
 | 
			
		||||
            exists = false;
 | 
			
		||||
            if (!NSApplication.IsUIThread)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            NSApplication.Quit -= ApplicationQuit;
 | 
			
		||||
 | 
			
		||||
            if (disposing)
 | 
			
		||||
            {
 | 
			
		||||
                CursorVisible = true;
 | 
			
		||||
                if (exists)
 | 
			
		||||
                {
 | 
			
		||||
                    CloseWindow(true);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (trackingArea != IntPtr.Zero)
 | 
			
		||||
                {
 | 
			
		||||
                    Cocoa.SendVoid(windowInfo.ViewHandle, selRemoveTrackingArea, trackingArea);
 | 
			
		||||
| 
						 | 
				
			
			@ -1027,9 +1188,15 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
                    trackingArea = IntPtr.Zero;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                Debug.Print("[Mac] Disposing {0}", windowInfo);
 | 
			
		||||
                windowInfo.Dispose();
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Print("{0} leaked, did you forget to call Dispose()?", GetType().FullName);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            disposed = true;
 | 
			
		||||
            OnDisposed(EventArgs.Empty);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1119,5 +1286,28 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
        {
 | 
			
		||||
            return (NSWindowStyle)Cocoa.SendUint(windowInfo.Handle, selStyleMask);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void CloseWindow(bool shutdown)
 | 
			
		||||
        {
 | 
			
		||||
            if (!Exists)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            exists = false;
 | 
			
		||||
 | 
			
		||||
            // PerformClose is equivalent to pressing the close-button, which
 | 
			
		||||
            // does not work in a borderless window. Handle this special case.
 | 
			
		||||
            if (GetStyleMask() == NSWindowStyle.Borderless || shutdown)
 | 
			
		||||
            {
 | 
			
		||||
                if (WindowShouldClose(IntPtr.Zero, IntPtr.Zero, IntPtr.Zero))
 | 
			
		||||
                {
 | 
			
		||||
                    Cocoa.SendVoid(windowInfo.Handle, selClose);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                Cocoa.SendVoid(windowInfo.Handle, selPerformClose, windowInfo.Handle);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -77,7 +77,7 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
                new Dictionary<IOHIDElementRef, JoystickHat>(new IntPtrEqualityComparer());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        readonly IOHIDManagerRef hidmanager;
 | 
			
		||||
        IOHIDManagerRef hidmanager;
 | 
			
		||||
 | 
			
		||||
        readonly Dictionary<IntPtr, MouseData> MouseDevices =
 | 
			
		||||
            new Dictionary<IntPtr, MouseData>(new IntPtrEqualityComparer());
 | 
			
		||||
| 
						 | 
				
			
			@ -94,7 +94,7 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
        readonly Dictionary<int, IntPtr> JoystickIndexToDevice =
 | 
			
		||||
            new Dictionary<int, IntPtr>();
 | 
			
		||||
 | 
			
		||||
        readonly CFRunLoop RunLoop = CF.CFRunLoopGetMain();
 | 
			
		||||
        readonly CFRunLoop RunLoop;
 | 
			
		||||
        readonly CFString InputLoopMode = CF.RunLoopModeDefault;
 | 
			
		||||
        readonly CFDictionary DeviceTypes = new CFDictionary();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -118,12 +118,28 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
        {
 | 
			
		||||
            Debug.Print("Using HIDInput.");
 | 
			
		||||
 | 
			
		||||
            RunLoop = CF.CFRunLoopGetMain();
 | 
			
		||||
            if (RunLoop == IntPtr.Zero)
 | 
			
		||||
                RunLoop = CF.CFRunLoopGetCurrent();
 | 
			
		||||
            if (RunLoop == IntPtr.Zero)
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Print("[Error] No CFRunLoop found for {0}", GetType().FullName);
 | 
			
		||||
                throw new InvalidOperationException();
 | 
			
		||||
            }
 | 
			
		||||
            CF.CFRetain(RunLoop);
 | 
			
		||||
 | 
			
		||||
            HandleDeviceAdded = DeviceAdded;
 | 
			
		||||
            HandleDeviceRemoved = DeviceRemoved;
 | 
			
		||||
            HandleDeviceValueReceived = DeviceValueReceived;
 | 
			
		||||
 | 
			
		||||
            // For retrieving input directly from the hardware
 | 
			
		||||
            hidmanager = CreateHIDManager();
 | 
			
		||||
            if (hidmanager == IntPtr.Zero)
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Print("[Mac] Failed to create IO HID manager, HIDInput driver not supported.");
 | 
			
		||||
                throw new NotSupportedException();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            RegisterHIDCallbacks(hidmanager);
 | 
			
		||||
 | 
			
		||||
            // For retrieving the global cursor position
 | 
			
		||||
| 
						 | 
				
			
			@ -164,53 +180,61 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
            IntPtr @event,
 | 
			
		||||
            IntPtr refcon)
 | 
			
		||||
        {
 | 
			
		||||
            CursorState.SetIsConnected(true);
 | 
			
		||||
 | 
			
		||||
            switch (type)
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                case CGEventType.MouseMoved:
 | 
			
		||||
                case CGEventType.LeftMouseDragged:
 | 
			
		||||
                case CGEventType.RightMouseDragged:
 | 
			
		||||
                case CGEventType.OtherMouseDragged:
 | 
			
		||||
                    {
 | 
			
		||||
                        Carbon.HIPoint p = CG.EventGetLocation(@event);
 | 
			
		||||
                        CursorState.X = (int)Math.Round(p.X);
 | 
			
		||||
                        CursorState.Y = (int)Math.Round(p.Y);
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
                CursorState.SetIsConnected(true);
 | 
			
		||||
 | 
			
		||||
                case CGEventType.ScrollWheel:
 | 
			
		||||
                    {
 | 
			
		||||
                        // Note: OpenTK follows the win32 convention, where
 | 
			
		||||
                        // (+h, +v) = (right, up). MacOS reports (+h, +v) = (left, up)
 | 
			
		||||
                        // so we need to flip the horizontal scroll direction.
 | 
			
		||||
                        double h = CG.EventGetDoubleValueField(@event, CGEventField.ScrollWheelEventPointDeltaAxis2) * MacOSFactory.ScrollFactor;
 | 
			
		||||
                        double v = CG.EventGetDoubleValueField(@event, CGEventField.ScrollWheelEventPointDeltaAxis1) * MacOSFactory.ScrollFactor;
 | 
			
		||||
                        CursorState.SetScrollRelative((float)(-h), (float)v);
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
                switch (type)
 | 
			
		||||
                {
 | 
			
		||||
                    case CGEventType.MouseMoved:
 | 
			
		||||
                    case CGEventType.LeftMouseDragged:
 | 
			
		||||
                    case CGEventType.RightMouseDragged:
 | 
			
		||||
                    case CGEventType.OtherMouseDragged:
 | 
			
		||||
                        {
 | 
			
		||||
                            Carbon.HIPoint p = CG.EventGetLocation(@event);
 | 
			
		||||
                            CursorState.X = (int)Math.Round(p.X);
 | 
			
		||||
                            CursorState.Y = (int)Math.Round(p.Y);
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
 | 
			
		||||
                case CGEventType.LeftMouseDown:
 | 
			
		||||
                case CGEventType.RightMouseDown:
 | 
			
		||||
                case CGEventType.OtherMouseDown:
 | 
			
		||||
                    {
 | 
			
		||||
                        int n = CG.EventGetIntegerValueField(@event, CGEventField.MouseEventButtonNumber);
 | 
			
		||||
                        n = n == 1 ? 2 : n == 2 ? 1 : n; // flip middle and right button numbers to match OpenTK
 | 
			
		||||
                        MouseButton b = MouseButton.Left + n;
 | 
			
		||||
                        CursorState[b] = true;
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
                    case CGEventType.ScrollWheel:
 | 
			
		||||
                        {
 | 
			
		||||
                            // Note: OpenTK follows the win32 convention, where
 | 
			
		||||
                            // (+h, +v) = (right, up). MacOS reports (+h, +v) = (left, up)
 | 
			
		||||
                            // so we need to flip the horizontal scroll direction.
 | 
			
		||||
                            double h = CG.EventGetDoubleValueField(@event, CGEventField.ScrollWheelEventPointDeltaAxis2) * MacOSFactory.ScrollFactor;
 | 
			
		||||
                            double v = CG.EventGetDoubleValueField(@event, CGEventField.ScrollWheelEventPointDeltaAxis1) * MacOSFactory.ScrollFactor;
 | 
			
		||||
                            CursorState.SetScrollRelative((float)(-h), (float)v);
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
 | 
			
		||||
                case CGEventType.LeftMouseUp:
 | 
			
		||||
                case CGEventType.RightMouseUp:
 | 
			
		||||
                case CGEventType.OtherMouseUp:
 | 
			
		||||
                    {
 | 
			
		||||
                        int n = CG.EventGetIntegerValueField(@event, CGEventField.MouseEventButtonNumber);
 | 
			
		||||
                        n = n == 1 ? 2 : n == 2 ? 1 : n; // flip middle and right button numbers to match OpenTK
 | 
			
		||||
                        MouseButton b = MouseButton.Left + n;
 | 
			
		||||
                        CursorState[b] = false;
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
                    case CGEventType.LeftMouseDown:
 | 
			
		||||
                    case CGEventType.RightMouseDown:
 | 
			
		||||
                    case CGEventType.OtherMouseDown:
 | 
			
		||||
                        {
 | 
			
		||||
                            int n = CG.EventGetIntegerValueField(@event, CGEventField.MouseEventButtonNumber);
 | 
			
		||||
                            n = n == 1 ? 2 : n == 2 ? 1 : n; // flip middle and right button numbers to match OpenTK
 | 
			
		||||
                            MouseButton b = MouseButton.Left + n;
 | 
			
		||||
                            CursorState[b] = true;
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
 | 
			
		||||
                    case CGEventType.LeftMouseUp:
 | 
			
		||||
                    case CGEventType.RightMouseUp:
 | 
			
		||||
                    case CGEventType.OtherMouseUp:
 | 
			
		||||
                        {
 | 
			
		||||
                            int n = CG.EventGetIntegerValueField(@event, CGEventField.MouseEventButtonNumber);
 | 
			
		||||
                            n = n == 1 ? 2 : n == 2 ? 1 : n; // flip middle and right button numbers to match OpenTK
 | 
			
		||||
                            MouseButton b = MouseButton.Left + n;
 | 
			
		||||
                            CursorState[b] = false;
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                // Do not let any exceptions escape into unmanaged code!
 | 
			
		||||
                Debug.Print(e.ToString());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return @event;
 | 
			
		||||
| 
						 | 
				
			
			@ -234,8 +258,6 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
 | 
			
		||||
            NativeMethods.IOHIDManagerSetDeviceMatching(hidmanager, DeviceTypes.Ref);
 | 
			
		||||
            NativeMethods.IOHIDManagerOpen(hidmanager, IOOptionBits.Zero);
 | 
			
		||||
 | 
			
		||||
            OpenTK.Platform.MacOS.Carbon.CF.CFRunLoopRunInMode(InputLoopMode, 0.0, true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void DeviceAdded(IntPtr context, IOReturn res, IntPtr sender, IOHIDDeviceRef device)
 | 
			
		||||
| 
						 | 
				
			
			@ -322,6 +344,7 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
                {
 | 
			
		||||
                    NativeMethods.IOHIDDeviceRegisterInputValueCallback(device, IntPtr.Zero, IntPtr.Zero);
 | 
			
		||||
                    NativeMethods.IOHIDDeviceUnscheduleFromRunLoop(device, RunLoop, InputLoopMode);
 | 
			
		||||
                    NativeMethods.IOHIDDeviceClose(device, IOOptionBits.Zero);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
| 
						 | 
				
			
			@ -1032,7 +1055,11 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
 | 
			
		||||
            [DllImport(hid)]
 | 
			
		||||
            public static extern IOHIDManagerRef IOHIDManagerCreate(
 | 
			
		||||
                CFAllocatorRef allocator, IOOptionBits options) ;
 | 
			
		||||
                CFAllocatorRef allocator, IOOptionBits options);
 | 
			
		||||
 | 
			
		||||
            [DllImport(hid)]
 | 
			
		||||
            public static extern IOReturn IOHIDManagerClose(
 | 
			
		||||
                IOHIDManagerRef allocator, IOOptionBits options);
 | 
			
		||||
 | 
			
		||||
            // This routine will be called when a new (matching) device is connected.
 | 
			
		||||
            [DllImport(hid)]
 | 
			
		||||
| 
						 | 
				
			
			@ -1075,7 +1102,7 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
            [DllImport(hid)]
 | 
			
		||||
            public static extern void IOHIDManagerSetDeviceMatching(
 | 
			
		||||
                IOHIDManagerRef manager,
 | 
			
		||||
                CFDictionaryRef matching) ;
 | 
			
		||||
                CFDictionaryRef matching);
 | 
			
		||||
 | 
			
		||||
            [DllImport(hid)]
 | 
			
		||||
            public static extern IOReturn IOHIDManagerOpen(
 | 
			
		||||
| 
						 | 
				
			
			@ -1087,6 +1114,11 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
                IOHIDDeviceRef manager,
 | 
			
		||||
                IOOptionBits opts);
 | 
			
		||||
 | 
			
		||||
            [DllImport(hid)]
 | 
			
		||||
            public static extern IOReturn IOHIDDeviceClose(
 | 
			
		||||
                IOHIDDeviceRef device,
 | 
			
		||||
                IOOptionBits options);
 | 
			
		||||
 | 
			
		||||
            [DllImport(hid)]
 | 
			
		||||
            public static extern CFTypeRef IOHIDDeviceGetProperty(
 | 
			
		||||
                IOHIDDeviceRef device,
 | 
			
		||||
| 
						 | 
				
			
			@ -1724,6 +1756,15 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
            {
 | 
			
		||||
                if (manual)
 | 
			
		||||
                {
 | 
			
		||||
                    if (MouseEventTapSource != IntPtr.Zero)
 | 
			
		||||
                    {
 | 
			
		||||
                        // Note: releasing the mach port (tap source)
 | 
			
		||||
                        // automatically releases the event tap.
 | 
			
		||||
                        CF.RunLoopRemoveSource(RunLoop, MouseEventTapSource, CF.RunLoopModeDefault);
 | 
			
		||||
                        CF.CFRelease(MouseEventTapSource);
 | 
			
		||||
                        MouseEventTapSource = IntPtr.Zero;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    NativeMethods.IOHIDManagerRegisterDeviceMatchingCallback(
 | 
			
		||||
                        hidmanager, IntPtr.Zero, IntPtr.Zero);
 | 
			
		||||
                    NativeMethods.IOHIDManagerRegisterDeviceRemovalCallback(
 | 
			
		||||
| 
						 | 
				
			
			@ -1746,19 +1787,15 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
                        DeviceRemoved(IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, device);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    HandleDeviceAdded = null;
 | 
			
		||||
                    HandleDeviceRemoved = null;
 | 
			
		||||
                    HandleDeviceValueReceived = null;
 | 
			
		||||
 | 
			
		||||
                    if (MouseEventTap != IntPtr.Zero)
 | 
			
		||||
                    if (hidmanager != IntPtr.Zero)
 | 
			
		||||
                    {
 | 
			
		||||
                        CF.CFRelease(MouseEventTap);
 | 
			
		||||
                        MouseEventTap = IntPtr.Zero;
 | 
			
		||||
                        NativeMethods.IOHIDManagerClose(hidmanager, IOOptionBits.Zero);
 | 
			
		||||
                        hidmanager = IntPtr.Zero;
 | 
			
		||||
                    }
 | 
			
		||||
                    if (MouseEventTapSource != IntPtr.Zero)
 | 
			
		||||
 | 
			
		||||
                    if (RunLoop != IntPtr.Zero)
 | 
			
		||||
                    {
 | 
			
		||||
                        CF.CFRelease(MouseEventTapSource);
 | 
			
		||||
                        MouseEventTapSource = IntPtr.Zero;
 | 
			
		||||
                        CF.CFRelease(RunLoop);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,7 +43,13 @@ namespace OpenTK.Platform.MacOS
 | 
			
		|||
        internal const float ScrollFactor = 0.1f;
 | 
			
		||||
        internal static bool ExclusiveFullscreen = false;
 | 
			
		||||
 | 
			
		||||
        readonly IInputDriver2 InputDriver = new HIDInput();
 | 
			
		||||
        readonly IInputDriver2 InputDriver;
 | 
			
		||||
 | 
			
		||||
        public MacOSFactory()
 | 
			
		||||
        {
 | 
			
		||||
            NSApplication.Initialize();
 | 
			
		||||
            InputDriver = new HIDInput();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region IPlatformFactory Members
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -112,6 +112,9 @@ namespace OpenTK.Platform.MacOS.Carbon
 | 
			
		|||
        [DllImport(appServices)]
 | 
			
		||||
        internal static extern IntPtr CFDictionaryGetValue(IntPtr theDictionary, IntPtr theKey);
 | 
			
		||||
 | 
			
		||||
        [DllImport(appServices)]
 | 
			
		||||
        internal static extern IntPtr CFRetain(CFTypeRef cf);
 | 
			
		||||
 | 
			
		||||
        [DllImport(appServices)]
 | 
			
		||||
        internal static extern void CFRelease(CFTypeRef cf);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -230,5 +233,11 @@ namespace OpenTK.Platform.MacOS.Carbon
 | 
			
		|||
            CFRunLoopRef rl,
 | 
			
		||||
            CFRunLoopSourceRef source,
 | 
			
		||||
            CFStringRef mode);
 | 
			
		||||
 | 
			
		||||
        [DllImport(appServices, EntryPoint = "CFRunLoopRemoveSource")]
 | 
			
		||||
        internal static extern void RunLoopRemoveSource(
 | 
			
		||||
            CFRunLoopRef rl,
 | 
			
		||||
            CFRunLoopSourceRef source,
 | 
			
		||||
            CFStringRef mode);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,10 +10,22 @@ using System;
 | 
			
		|||
 | 
			
		||||
namespace OpenTK
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>Defines a plaftorm specific exception.</summary>
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Defines a plaftorm-specific exception.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class PlatformException : Exception
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>Constructs a new PlatformException.</summary>
 | 
			
		||||
        public PlatformException(string s) : base(s) { }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Initializes a new instance of the <see cref="OpenTK.PlatformException"/> class.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public PlatformException()
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Initializes a new instance of the <see cref="OpenTK.PlatformException"/> class.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="message">A message explaining the cause for this exception.</param>
 | 
			
		||||
        public PlatformException(string message) : base(message) { }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -28,6 +28,7 @@
 | 
			
		|||
#endregion
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using OpenTK.Graphics;
 | 
			
		||||
using OpenTK.Input;
 | 
			
		||||
| 
						 | 
				
			
			@ -42,6 +43,9 @@ namespace OpenTK.Platform
 | 
			
		|||
    /// </summary>
 | 
			
		||||
    abstract class PlatformFactoryBase : IPlatformFactory
 | 
			
		||||
    {
 | 
			
		||||
        static readonly object sync = new object();
 | 
			
		||||
        readonly List<IDisposable> Resources = new List<IDisposable>();
 | 
			
		||||
 | 
			
		||||
        protected bool IsDisposed;
 | 
			
		||||
 | 
			
		||||
        public PlatformFactoryBase()
 | 
			
		||||
| 
						 | 
				
			
			@ -80,6 +84,14 @@ namespace OpenTK.Platform
 | 
			
		|||
            return new LegacyJoystickDriver();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void RegisterResource(IDisposable resource)
 | 
			
		||||
        {
 | 
			
		||||
            lock (sync)
 | 
			
		||||
            {
 | 
			
		||||
                Resources.Add(resource);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region IDisposable implementation
 | 
			
		||||
| 
						 | 
				
			
			@ -96,10 +108,19 @@ namespace OpenTK.Platform
 | 
			
		|||
            {
 | 
			
		||||
                if (manual)
 | 
			
		||||
                {
 | 
			
		||||
                    lock (sync)
 | 
			
		||||
                    {
 | 
			
		||||
                        foreach (var resource in Resources)
 | 
			
		||||
                        {
 | 
			
		||||
                            resource.Dispose();
 | 
			
		||||
                        }
 | 
			
		||||
                        Resources.Clear();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    Debug.Print("[OpenTK] {0} leaked, did you forget to call Dispose()?", GetType());
 | 
			
		||||
                    Debug.Print("[OpenTK] {0} leaked with {1} live resources, did you forget to call Dispose()?",
 | 
			
		||||
                        GetType().FullName, Resources.Count);
 | 
			
		||||
                }
 | 
			
		||||
                IsDisposed = true;
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -376,7 +376,7 @@ namespace OpenTK.Platform.SDL2
 | 
			
		|||
 | 
			
		||||
        #region IDisposable Members
 | 
			
		||||
 | 
			
		||||
        void Dispose(bool manual)
 | 
			
		||||
        protected override void Dispose(bool manual)
 | 
			
		||||
        {
 | 
			
		||||
            if (!IsDisposed)
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -397,17 +397,6 @@ namespace OpenTK.Platform.SDL2
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void Dispose()
 | 
			
		||||
        {
 | 
			
		||||
            Dispose(true);
 | 
			
		||||
            GC.SuppressFinalize(this);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ~Sdl2GraphicsContext()
 | 
			
		||||
        {
 | 
			
		||||
            Dispose(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -465,13 +465,7 @@ namespace OpenTK.Platform.Windows
 | 
			
		|||
 | 
			
		||||
        #region IDisposable Members
 | 
			
		||||
 | 
			
		||||
        public override void Dispose()
 | 
			
		||||
        {
 | 
			
		||||
            Dispose(true);
 | 
			
		||||
            GC.SuppressFinalize(this);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void Dispose(bool calledManually)
 | 
			
		||||
        protected override void Dispose(bool calledManually)
 | 
			
		||||
        {
 | 
			
		||||
            if (!IsDisposed)
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -479,20 +473,10 @@ namespace OpenTK.Platform.Windows
 | 
			
		|||
                {
 | 
			
		||||
                    DestroyContext();
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    Debug.Print("[Warning] OpenGL context {0} leaked. Did you forget to call IGraphicsContext.Dispose()?",
 | 
			
		||||
                        Handle.Handle);
 | 
			
		||||
                }
 | 
			
		||||
                IsDisposed = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ~WinGLContext()
 | 
			
		||||
        {
 | 
			
		||||
            Dispose(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region private void DestroyContext()
 | 
			
		||||
 | 
			
		||||
        private void DestroyContext()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -483,13 +483,7 @@ namespace OpenTK.Platform.X11
 | 
			
		|||
 | 
			
		||||
        #region --- IDisposable Members ---
 | 
			
		||||
 | 
			
		||||
        public override void Dispose()
 | 
			
		||||
        {
 | 
			
		||||
            this.Dispose(true);
 | 
			
		||||
            GC.SuppressFinalize(this);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void Dispose(bool manuallyCalled)
 | 
			
		||||
        protected override void Dispose(bool manuallyCalled)
 | 
			
		||||
        {
 | 
			
		||||
            if (!IsDisposed)
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -516,12 +510,6 @@ namespace OpenTK.Platform.X11
 | 
			
		|||
            }
 | 
			
		||||
            IsDisposed = true;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        ~X11GLContext()
 | 
			
		||||
        {
 | 
			
		||||
            this.Dispose(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -178,22 +178,19 @@ namespace OpenTK
 | 
			
		|||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Print("OpenTK.Toolkit leaked, did you forget to call Dispose()?");
 | 
			
		||||
                platform_factory = null;
 | 
			
		||||
                toolkit = null;
 | 
			
		||||
                initialized = false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #if DEBUG
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Finalizes this instance.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        ~Toolkit()
 | 
			
		||||
        {
 | 
			
		||||
            Dispose(false);
 | 
			
		||||
            Debug.Print("[Warning] {0} leaked, did you forget to call Dispose()?");
 | 
			
		||||
            // We may not Dispose() the toolkit from the finalizer thread,
 | 
			
		||||
            // as that will crash on many operating systems.
 | 
			
		||||
        }
 | 
			
		||||
        #endif
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue