Skip to content

Commit

Permalink
Merge branch 'pr/105' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
thefiddler committed Apr 28, 2014
2 parents a07a61a + 53d2c8d commit ffb7bd8
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 23 deletions.
2 changes: 0 additions & 2 deletions Source/OpenTK/Platform/MacOS/Cocoa/Cocoa.cs
Expand Up @@ -223,8 +223,6 @@ public static void Initialize()

AppKitLibrary = NS.LoadLibrary("/System/Library/Frameworks/AppKit.framework/AppKit");
FoundationLibrary = NS.LoadLibrary("/System/Library/Frameworks/Foundation.framework/Foundation");

NSApplication.Initialize();
}
}
}
32 changes: 31 additions & 1 deletion Source/OpenTK/Platform/MacOS/Cocoa/NSApplication.cs
Expand Up @@ -28,6 +28,7 @@
#endregion

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using OpenTK.Platform.MacOS;

Expand All @@ -38,13 +39,19 @@ static class NSApplication
internal static IntPtr Handle;
internal static IntPtr AutoreleasePool;

static readonly IntPtr selQuit = Selector.Get("quit");

internal static void Initialize()
{
// Create the NSAutoreleasePool
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
Handle = Cocoa.SendIntPtr(Class.Get("NSApplication"), Selector.Get("sharedApplication"));
Handle = Cocoa.SendIntPtr(nsapp, Selector.Get("sharedApplication"));

// Setup the application
Cocoa.SendBool(Handle, Selector.Get("setActivationPolicy:"), (int)NSApplicationActivationPolicy.Regular);
Expand All @@ -61,8 +68,31 @@ internal static void Initialize()
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);

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]).
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);
}
}
}
}
30 changes: 20 additions & 10 deletions Source/OpenTK/Platform/MacOS/CocoaNativeWindow.cs
Expand Up @@ -61,7 +61,6 @@ class CocoaNativeWindow : INativeWindow
static readonly IntPtr selNextEventMatchingMask = Selector.Get("nextEventMatchingMask:untilDate:inMode:dequeue:");
static readonly IntPtr selSendEvent = Selector.Get("sendEvent:");
//static readonly IntPtr selUpdateWindows = Selector.Get("updateWindows");
static readonly IntPtr selContentView = Selector.Get("contentView");
static readonly IntPtr selConvertRectFromScreen = Selector.Get("convertRectFromScreen:");
static readonly IntPtr selConvertRectToScreen = Selector.Get("convertRectToScreen:");
static readonly IntPtr selPerformClose = Selector.Get("performClose:");
Expand Down Expand Up @@ -120,6 +119,7 @@ class CocoaNativeWindow : INativeWindow
static CocoaNativeWindow()
{
Cocoa.Initialize();
NSApplication.Initialize(); // Problem: This does not allow creating a separate app and using CocoaNativeWindow.
NSDefaultRunLoopMode = Cocoa.GetStringConstant(Cocoa.FoundationLibrary, "NSDefaultRunLoopMode");
NSCursor = Class.Get("NSCursor");
}
Expand All @@ -128,7 +128,7 @@ static CocoaNativeWindow()
private IntPtr windowClass;
private IntPtr trackingArea;
private bool disposed = false;
private bool exists = true;
private bool exists;
private bool cursorVisible = true;
private System.Drawing.Icon icon;
private LegacyInputDriver inputDriver = new LegacyInputDriver();
Expand All @@ -154,6 +154,7 @@ public CocoaNativeWindow(int x, int y, int width, int height, string title, Grap
// 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@:@");
Expand Down Expand Up @@ -186,8 +187,12 @@ public CocoaNativeWindow(int x, int y, int width, int height, string title, Grap
SetTitle(title, false);

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 WindowDidMoveDelegate(IntPtr self, IntPtr cmd, IntPtr notification);
delegate void WindowDidBecomeKeyDelegate(IntPtr self, IntPtr cmd, IntPtr notification);
Expand All @@ -201,6 +206,11 @@ public CocoaNativeWindow(int x, int y, int width, int height, string title, Grap
delegate bool CanBecomeKeyWindowDelegate(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)
{
OnResize(true);
Expand All @@ -218,6 +228,12 @@ private void OnResize(bool resetTracking)
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)
{
// Problem: Called only when you stop moving for a brief moment,
Expand Down Expand Up @@ -392,10 +408,8 @@ public void ProcessEvents()
KeyPress(this, keyPressArgs);
}
}

// Steal all keydown events to avoid the annoying "bleep" sound.
return;
}
break;

case NSEventType.KeyUp:
{
Expand Down Expand Up @@ -940,6 +954,7 @@ protected virtual void Dispose(bool disposing)
return;

Debug.Print("Disposing of CocoaNativeWindow.");
NSApplication.Quit -= ApplicationQuit;

CursorVisible = true;
disposed = true;
Expand All @@ -965,11 +980,6 @@ protected virtual void Dispose(bool disposing)
Dispose(false);
}

public static IntPtr GetView(IntPtr windowHandle)
{
return Cocoa.SendIntPtr(windowHandle, selContentView);
}

private RectangleF GetContentViewFrame()
{
return Cocoa.SendRect(windowInfo.ViewHandle, selFrame);
Expand Down
29 changes: 19 additions & 10 deletions Source/OpenTK/Platform/MacOS/CocoaWindowInfo.cs
Expand Up @@ -40,7 +40,10 @@ namespace OpenTK.Platform.MacOS
/// </summary>
sealed class CocoaWindowInfo : IWindowInfo
{
static readonly IntPtr selContentView = Selector.Get("contentView");

IntPtr nsWindowRef;
IntPtr nsViewRef;

bool disposed = false;

Expand All @@ -49,10 +52,22 @@ sealed class CocoaWindowInfo : IWindowInfo
/// <summary>
/// Constructs a new instance with the specified parameters.
/// </summary>
/// <param name="nsWindowRef">A valid NSView reference.</param>
public CocoaWindowInfo(IntPtr nsWindowRef)
/// <remarks>This constructor assumes that the NSWindow's contentView is the NSView we want to attach to our context.</remarks>
/// <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.nsViewRef = nsViewRef;
}

#endregion
Expand All @@ -67,19 +82,13 @@ public CocoaWindowInfo(IntPtr nsWindowRef)
/// <summary>
/// Gets the view reference for this instance.
/// </summary>
public IntPtr ViewHandle
{
get
{
return CocoaNativeWindow.GetView(nsWindowRef);
}
}
public IntPtr ViewHandle { get { return nsViewRef; } }

/// <summary>Returns a System.String that represents the current window.</summary>
/// <returns>A System.String that represents the current window.</returns>
public override string ToString()
{
return String.Format("MacOS.CocoaWindowInfo: NSWindow {0}", nsWindowRef);
return String.Format("MacOS.CocoaWindowInfo: NSWindow {0}, NSView {1}", nsWindowRef, nsViewRef);
}

#endregion
Expand Down
12 changes: 12 additions & 0 deletions Source/OpenTK/Platform/Utilities.cs
Expand Up @@ -309,12 +309,24 @@ public static IWindowInfo CreateMacOSCarbonWindowInfo(IntPtr windowHandle, bool
/// Creates an IWindowInfo instance for the Mac OS X platform.
/// </summary>
/// <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>
public static IWindowInfo CreateMacOSWindowInfo(IntPtr 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

#region CreateDummyWindowInfo
Expand Down

0 comments on commit ffb7bd8

Please sign in to comment.