Permalink
Browse files

[Mac] Cmd-Q should raise Closing events

It should also be cancelable.
  • Loading branch information...
1 parent 160e6ec commit 53d2c8d1e84abd73fc5de5f6dbcdaf7e183ae504 @thefiddler thefiddler committed Apr 28, 2014
@@ -28,6 +28,7 @@
#endregion
using System;
+using System.ComponentModel;
using System.Runtime.InteropServices;
using OpenTK.Platform.MacOS;
@@ -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);
@@ -65,7 +72,7 @@ internal static void Initialize()
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"), Selector.Get("terminate:"), Cocoa.ToNSString("q")),
+ Selector.Get("initWithTitle:action:keyEquivalent:"), Cocoa.ToNSString("Quit"), selQuit, Cocoa.ToNSString("q")),
Selector.Autorelease);
Cocoa.SendIntPtr(appMenu, Selector.Get("addItem:"), quitMenuItem);
@@ -74,5 +81,18 @@ internal static void Initialize()
// 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);
+ }
+ }
}
}
@@ -127,7 +127,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();
@@ -184,6 +184,9 @@ 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);
@@ -222,6 +225,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,
@@ -919,6 +928,7 @@ protected virtual void Dispose(bool disposing)
return;
Debug.Print("Disposing of CocoaNativeWindow.");
+ NSApplication.Quit -= ApplicationQuit;
CursorVisible = true;
disposed = true;

0 comments on commit 53d2c8d

Please sign in to comment.