Merge branch 'pr/105' into develop

This commit is contained in:
thefiddler 2014-04-28 16:19:17 +02:00
commit ffb7bd8a4c
5 changed files with 82 additions and 23 deletions

View file

@ -223,8 +223,6 @@ namespace OpenTK.Platform.MacOS
AppKitLibrary = NS.LoadLibrary("/System/Library/Frameworks/AppKit.framework/AppKit"); AppKitLibrary = NS.LoadLibrary("/System/Library/Frameworks/AppKit.framework/AppKit");
FoundationLibrary = NS.LoadLibrary("/System/Library/Frameworks/Foundation.framework/Foundation"); FoundationLibrary = NS.LoadLibrary("/System/Library/Frameworks/Foundation.framework/Foundation");
NSApplication.Initialize();
} }
} }
} }

View file

@ -28,6 +28,7 @@
#endregion #endregion
using System; using System;
using System.ComponentModel;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using OpenTK.Platform.MacOS; using OpenTK.Platform.MacOS;
@ -38,13 +39,19 @@ namespace OpenTK.Platform.MacOS
internal static IntPtr Handle; internal static IntPtr Handle;
internal static IntPtr AutoreleasePool; internal static IntPtr AutoreleasePool;
static readonly IntPtr selQuit = Selector.Get("quit");
internal static void Initialize() internal static void Initialize()
{ {
// Create the NSAutoreleasePool // Create the NSAutoreleasePool
AutoreleasePool = Cocoa.SendIntPtr(Cocoa.SendIntPtr(Class.Get("NSAutoreleasePool"), Selector.Alloc), Selector.Init); AutoreleasePool = Cocoa.SendIntPtr(Cocoa.SendIntPtr(Class.Get("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@:");
// Fetch the application handle // Fetch the application handle
Handle = Cocoa.SendIntPtr(Class.Get("NSApplication"), Selector.Get("sharedApplication")); Handle = Cocoa.SendIntPtr(nsapp, Selector.Get("sharedApplication"));
// Setup the application // Setup the application
Cocoa.SendBool(Handle, Selector.Get("setActivationPolicy:"), (int)NSApplicationActivationPolicy.Regular); Cocoa.SendBool(Handle, Selector.Get("setActivationPolicy:"), (int)NSApplicationActivationPolicy.Regular);
@ -61,8 +68,31 @@ namespace OpenTK.Platform.MacOS
Cocoa.SendIntPtr(menubar, Selector.Get("addItem:"), menuItem); Cocoa.SendIntPtr(menubar, Selector.Get("addItem:"), menuItem);
Cocoa.SendIntPtr(Handle, Selector.Get("setMainMenu:"), menubar); 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);
Cocoa.SendIntPtr(appMenu, Selector.Get("addItem:"), quitMenuItem);
Cocoa.SendIntPtr(menuItem, Selector.Get("setSubmenu:"), appMenu);
// Tell cocoa we're ready to run the application (usually called by [NSApp run]). // Tell cocoa we're ready to run the application (usually called by [NSApp run]).
Cocoa.SendVoid(Handle, Selector.Get("finishLaunching")); Cocoa.SendVoid(Handle, Selector.Get("finishLaunching"));
} }
internal static event EventHandler<CancelEventArgs> Quit = delegate { };
delegate void OnQuitDelegate(IntPtr self, IntPtr cmd);
static void OnQuit(IntPtr self, IntPtr cmd)
{
var e = new CancelEventArgs();
Quit(null, e);
if (!e.Cancel)
{
Cocoa.SendVoid(Handle, Selector.Get("terminate:"), Handle);
}
}
} }
} }

View file

@ -61,7 +61,6 @@ namespace OpenTK.Platform.MacOS
static readonly IntPtr selNextEventMatchingMask = Selector.Get("nextEventMatchingMask:untilDate:inMode:dequeue:"); static readonly IntPtr selNextEventMatchingMask = Selector.Get("nextEventMatchingMask:untilDate:inMode:dequeue:");
static readonly IntPtr selSendEvent = Selector.Get("sendEvent:"); static readonly IntPtr selSendEvent = Selector.Get("sendEvent:");
//static readonly IntPtr selUpdateWindows = Selector.Get("updateWindows"); //static readonly IntPtr selUpdateWindows = Selector.Get("updateWindows");
static readonly IntPtr selContentView = Selector.Get("contentView");
static readonly IntPtr selConvertRectFromScreen = Selector.Get("convertRectFromScreen:"); static readonly IntPtr selConvertRectFromScreen = Selector.Get("convertRectFromScreen:");
static readonly IntPtr selConvertRectToScreen = Selector.Get("convertRectToScreen:"); static readonly IntPtr selConvertRectToScreen = Selector.Get("convertRectToScreen:");
static readonly IntPtr selPerformClose = Selector.Get("performClose:"); static readonly IntPtr selPerformClose = Selector.Get("performClose:");
@ -120,6 +119,7 @@ namespace OpenTK.Platform.MacOS
static CocoaNativeWindow() static CocoaNativeWindow()
{ {
Cocoa.Initialize(); Cocoa.Initialize();
NSApplication.Initialize(); // Problem: This does not allow creating a separate app and using CocoaNativeWindow.
NSDefaultRunLoopMode = Cocoa.GetStringConstant(Cocoa.FoundationLibrary, "NSDefaultRunLoopMode"); NSDefaultRunLoopMode = Cocoa.GetStringConstant(Cocoa.FoundationLibrary, "NSDefaultRunLoopMode");
NSCursor = Class.Get("NSCursor"); NSCursor = Class.Get("NSCursor");
} }
@ -128,7 +128,7 @@ namespace OpenTK.Platform.MacOS
private IntPtr windowClass; private IntPtr windowClass;
private IntPtr trackingArea; private IntPtr trackingArea;
private bool disposed = false; private bool disposed = false;
private bool exists = true; private bool exists;
private bool cursorVisible = true; private bool cursorVisible = true;
private System.Drawing.Icon icon; private System.Drawing.Icon icon;
private LegacyInputDriver inputDriver = new LegacyInputDriver(); private LegacyInputDriver inputDriver = new LegacyInputDriver();
@ -154,6 +154,7 @@ namespace OpenTK.Platform.MacOS
// Create the window class // Create the window class
Interlocked.Increment(ref UniqueId); Interlocked.Increment(ref UniqueId);
windowClass = Class.AllocateClass("OpenTK_GameWindow" + UniqueId, "NSWindow"); 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 WindowDidResizeDelegate(WindowDidResize), "windowDidResize:", "v@:@");
Class.RegisterMethod(windowClass, new WindowDidMoveDelegate(WindowDidMove), "windowDidMove:", "v@:@"); Class.RegisterMethod(windowClass, new WindowDidMoveDelegate(WindowDidMove), "windowDidMove:", "v@:@");
Class.RegisterMethod(windowClass, new WindowDidBecomeKeyDelegate(WindowDidBecomeKey), "windowDidBecomeKey:", "v@:@"); Class.RegisterMethod(windowClass, new WindowDidBecomeKeyDelegate(WindowDidBecomeKey), "windowDidBecomeKey:", "v@:@");
@ -186,8 +187,12 @@ namespace OpenTK.Platform.MacOS
SetTitle(title, false); SetTitle(title, false);
ResetTrackingArea(); ResetTrackingArea();
exists = true;
NSApplication.Quit += ApplicationQuit;
} }
delegate void WindowKeyDownDelegate(IntPtr self, IntPtr cmd, IntPtr notification);
delegate void WindowDidResizeDelegate(IntPtr self, IntPtr cmd, IntPtr notification); delegate void WindowDidResizeDelegate(IntPtr self, IntPtr cmd, IntPtr notification);
delegate void WindowDidMoveDelegate(IntPtr self, IntPtr cmd, IntPtr notification); delegate void WindowDidMoveDelegate(IntPtr self, IntPtr cmd, IntPtr notification);
delegate void WindowDidBecomeKeyDelegate(IntPtr self, IntPtr cmd, IntPtr notification); delegate void WindowDidBecomeKeyDelegate(IntPtr self, IntPtr cmd, IntPtr notification);
@ -201,6 +206,11 @@ namespace OpenTK.Platform.MacOS
delegate bool CanBecomeKeyWindowDelegate(IntPtr self, IntPtr cmd); delegate bool CanBecomeKeyWindowDelegate(IntPtr self, IntPtr cmd);
delegate bool CanBecomeMainWindowDelegate(IntPtr self, IntPtr cmd); delegate bool CanBecomeMainWindowDelegate(IntPtr self, IntPtr cmd);
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.
}
private void WindowDidResize(IntPtr self, IntPtr cmd, IntPtr notification) private void WindowDidResize(IntPtr self, IntPtr cmd, IntPtr notification)
{ {
OnResize(true); OnResize(true);
@ -218,6 +228,12 @@ namespace OpenTK.Platform.MacOS
Resize(this, EventArgs.Empty); Resize(this, EventArgs.Empty);
} }
private void ApplicationQuit(object sender, CancelEventArgs e)
{
bool close = WindowShouldClose(windowInfo.Handle, IntPtr.Zero, IntPtr.Zero);
e.Cancel |= !close;
}
private void WindowDidMove(IntPtr self, IntPtr cmd, IntPtr notification) private void WindowDidMove(IntPtr self, IntPtr cmd, IntPtr notification)
{ {
// Problem: Called only when you stop moving for a brief moment, // Problem: Called only when you stop moving for a brief moment,
@ -392,10 +408,8 @@ namespace OpenTK.Platform.MacOS
KeyPress(this, keyPressArgs); KeyPress(this, keyPressArgs);
} }
} }
// Steal all keydown events to avoid the annoying "bleep" sound.
return;
} }
break;
case NSEventType.KeyUp: case NSEventType.KeyUp:
{ {
@ -940,6 +954,7 @@ namespace OpenTK.Platform.MacOS
return; return;
Debug.Print("Disposing of CocoaNativeWindow."); Debug.Print("Disposing of CocoaNativeWindow.");
NSApplication.Quit -= ApplicationQuit;
CursorVisible = true; CursorVisible = true;
disposed = true; disposed = true;
@ -965,11 +980,6 @@ namespace OpenTK.Platform.MacOS
Dispose(false); Dispose(false);
} }
public static IntPtr GetView(IntPtr windowHandle)
{
return Cocoa.SendIntPtr(windowHandle, selContentView);
}
private RectangleF GetContentViewFrame() private RectangleF GetContentViewFrame()
{ {
return Cocoa.SendRect(windowInfo.ViewHandle, selFrame); return Cocoa.SendRect(windowInfo.ViewHandle, selFrame);

View file

@ -40,7 +40,10 @@ namespace OpenTK.Platform.MacOS
/// </summary> /// </summary>
sealed class CocoaWindowInfo : IWindowInfo sealed class CocoaWindowInfo : IWindowInfo
{ {
static readonly IntPtr selContentView = Selector.Get("contentView");
IntPtr nsWindowRef; IntPtr nsWindowRef;
IntPtr nsViewRef;
bool disposed = false; bool disposed = false;
@ -49,10 +52,22 @@ namespace OpenTK.Platform.MacOS
/// <summary> /// <summary>
/// Constructs a new instance with the specified parameters. /// Constructs a new instance with the specified parameters.
/// </summary> /// </summary>
/// <param name="nsWindowRef">A valid NSView reference.</param> /// <remarks>This constructor assumes that the NSWindow's contentView is the NSView we want to attach to our context.</remarks>
public CocoaWindowInfo(IntPtr nsWindowRef) /// <param name="nsWindowRef">A valid NSWindow reference.</param>
public CocoaWindowInfo(IntPtr nsWindowRef) : this(nsWindowRef, Cocoa.SendIntPtr(nsWindowRef, selContentView))
{
}
/// <summary>
/// Constructs a new instance with the specified parameters.
/// </summary>
/// <param name="nsWindowRef">A valid NSWindow reference.</param>
/// <param name="nsViewRef">A valid NSView reference.</param>
public CocoaWindowInfo(IntPtr nsWindowRef, IntPtr nsViewRef)
{ {
this.nsWindowRef = nsWindowRef; this.nsWindowRef = nsWindowRef;
this.nsViewRef = nsViewRef;
} }
#endregion #endregion
@ -67,19 +82,13 @@ namespace OpenTK.Platform.MacOS
/// <summary> /// <summary>
/// Gets the view reference for this instance. /// Gets the view reference for this instance.
/// </summary> /// </summary>
public IntPtr ViewHandle public IntPtr ViewHandle { get { return nsViewRef; } }
{
get
{
return CocoaNativeWindow.GetView(nsWindowRef);
}
}
/// <summary>Returns a System.String that represents the current window.</summary> /// <summary>Returns a System.String that represents the current window.</summary>
/// <returns>A System.String that represents the current window.</returns> /// <returns>A System.String that represents the current window.</returns>
public override string ToString() public override string ToString()
{ {
return String.Format("MacOS.CocoaWindowInfo: NSWindow {0}", nsWindowRef); return String.Format("MacOS.CocoaWindowInfo: NSWindow {0}, NSView {1}", nsWindowRef, nsViewRef);
} }
#endregion #endregion

View file

@ -309,12 +309,24 @@ namespace OpenTK.Platform
/// Creates an IWindowInfo instance for the Mac OS X platform. /// Creates an IWindowInfo instance for the Mac OS X platform.
/// </summary> /// </summary>
/// <param name="windowHandle">The handle of the NSWindow.</param> /// <param name="windowHandle">The handle of the NSWindow.</param>
/// <remarks>Assumes that the NSWindow's contentView is the NSView we want to attach to our context.</remarks>
/// <returns>A new IWindowInfo instance.</returns> /// <returns>A new IWindowInfo instance.</returns>
public static IWindowInfo CreateMacOSWindowInfo(IntPtr windowHandle) public static IWindowInfo CreateMacOSWindowInfo(IntPtr windowHandle)
{ {
return new OpenTK.Platform.MacOS.CocoaWindowInfo(windowHandle); return new OpenTK.Platform.MacOS.CocoaWindowInfo(windowHandle);
} }
/// <summary>
/// Creates an IWindowInfo instance for the Mac OS X platform.
/// </summary>
/// <param name="windowHandle">The handle of the NSWindow.</param>
/// <param name="viewHandle">The handle of the NSView.</param>
/// <returns>A new IWindowInfo instance.</returns>
public static IWindowInfo CreateMacOSWindowInfo(IntPtr windowHandle, IntPtr viewHandle)
{
return new OpenTK.Platform.MacOS.CocoaWindowInfo(windowHandle, viewHandle);
}
#endregion #endregion
#region CreateDummyWindowInfo #region CreateDummyWindowInfo