private void RestoreWindowState() { suppressResize++; if (windowState == WindowState.Fullscreen) { SetMenuVisible(true); if (MacOSFactory.ExclusiveFullscreen) { CG.DisplayReleaseAll(); Cocoa.SendVoid(windowInfo.Handle, selSetLevel, normalLevel); } RestoreBorder(); InternalBounds = previousBounds; } else if (windowState == WindowState.Maximized) { RestoreBorder(); InternalBounds = previousBounds; } else if (windowState == WindowState.Minimized) { Cocoa.SendVoid(windowInfo.Handle, selDeminiaturize, windowInfo.Handle); } windowState = WindowState.Normal; suppressResize--; }
/// <summary> /// Disposes of the <see cref="NSAutoreleasePool" /> instance, draining it. /// </summary> public void Dispose() { if (_autoreleasePool != IntPtr.Zero) { Cocoa.SendVoid(_autoreleasePool, Selector.Get("drain")); } }
protected override void Dispose(bool disposing) { if (disposed) { return; } Debug.Print("Disposing of CocoaNativeWindow."); NSApplication.Quit -= ApplicationQuit; CursorVisible = true; disposed = true; exists = false; if (disposing) { if (trackingArea != IntPtr.Zero) { Cocoa.SendVoid(windowInfo.ViewHandle, selRemoveTrackingArea, trackingArea); Cocoa.SendVoid(trackingArea, Selector.Release); trackingArea = IntPtr.Zero; } windowInfo.Dispose(); } OnDisposed(EventArgs.Empty); }
static NSApplication() { Cocoa.Initialize(); // Register a Quit method to be called on cmd-q IntPtr nsapp = Class.Get("NSApplication"); Class.RegisterMethod(nsapp, OnQuitHandler, "quit", "v@:"); // Fetch the application handle Handle = Cocoa.SendIntPtr(nsapp, Selector.Get("sharedApplication")); // Setup the application Cocoa.SendBool(Handle, Selector.Get("setActivationPolicy:"), (int)NSApplicationActivationPolicy.Regular); Cocoa.SendVoid(Handle, Selector.Get("discardEventsMatchingMask:beforeEvent:"), uint.MaxValue, IntPtr.Zero); Cocoa.SendVoid(Handle, Selector.Get("activateIgnoringOtherApps:"), true); if (Cocoa.SendIntPtr(Handle, Selector.Get("mainMenu")) == IntPtr.Zero) { // Create the menu bar 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(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); // Tell cocoa we're ready to run the application (usually called by [NSApp run]). // Note: if a main menu exists, then this method has already been called and // calling it again will result in a crash. For this reason, we only call it // when we create our own main menu. Cocoa.SendVoid(Handle, Selector.Get("finishLaunching")); } // Disable momentum scrolling and long-press key pop-ups IntPtr settings = Cocoa.SendIntPtr(Class.NSDictionary, Selector.Alloc); //IntPtr momentum_scrolling = Cocoa.SendIntPtr(Class.NSNumber, Selector.Get("numberWithBool:"), false); IntPtr press_and_hold = Cocoa.SendIntPtr(Class.NSNumber, Selector.Get("numberWithBool:"), false); // Initialize and register the settings dictionary settings = Cocoa.SendIntPtr(settings, Selector.Get("initWithObjectsAndKeys:"), //momentum_scrolling, Cocoa.ToNSString("AppleMomentumScrollSupported"), press_and_hold, Cocoa.ToNSString("ApplePressAndHoldEnabled"), IntPtr.Zero); Cocoa.SendVoid( Cocoa.SendIntPtr(Class.NSUserDefaults, Selector.Get("standardUserDefaults")), Selector.Get("registerDefaults:"), settings); Cocoa.SendVoid(settings, Selector.Release); }
internal static void 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@:"); // Fetch the application handle Handle = Cocoa.SendIntPtr(nsapp, Selector.Get("sharedApplication")); // Setup the application Cocoa.SendBool(Handle, Selector.Get("setActivationPolicy:"), (int)NSApplicationActivationPolicy.Regular); 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); // 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); 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")); // Disable momentum scrolling and long-press key pop-ups IntPtr settings = Cocoa.SendIntPtr(Class.NSDictionary, Selector.Alloc); IntPtr momentum_scrolling = Cocoa.SendIntPtr(Class.NSNumber, Selector.Get("numberWithBool:"), false); IntPtr press_and_hold = Cocoa.SendIntPtr(Class.NSNumber, Selector.Get("numberWithBool:"), false); // Initialize and register the settings dictionary settings = Cocoa.SendIntPtr(settings, Selector.Get("initWithObjectsAndKeys:"), //momentum_scrolling, Cocoa.ToNSString("AppleMomentumScrollSupported"), press_and_hold, Cocoa.ToNSString("ApplePressAndHoldEnabled"), IntPtr.Zero); Cocoa.SendVoid( Cocoa.SendIntPtr(Class.NSUserDefaults, Selector.Get("standardUserDefaults")), Selector.Get("registerDefaults:"), settings); Cocoa.SendVoid(settings, Selector.Release); }
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"); NSImage = Class.Get("NSImage"); NSBitmapImageRep = Class.Get("NSBitmapImageRep"); }
public override System.Drawing.Point PointToScreen(System.Drawing.Point point) { var r = Cocoa.SendRect(windowInfo.Handle, selConvertRectToScreen, Cocoa.SendRect(windowInfo.ViewHandle, selConvertRectFromBacking, new RectangleF(point.X, Height - point.Y, 0, 0))); return(new Point((int)r.X, (int)(GetCurrentScreenFrame().Height - r.Y))); }
private void SetTitle(string newTitle, bool callEvent) { title = newTitle ?? ""; Cocoa.SendIntPtr(windowInfo.Handle, selSetTitle, Cocoa.ToNSString(title)); if (callEvent) { OnTitleChanged(EventArgs.Empty); } }
static void OnQuit(IntPtr self, IntPtr cmd) { var e = new CancelEventArgs(); Quit(null, e); if (!e.Cancel) { Cocoa.SendVoid(Handle, Selector.Get("terminate:"), Handle); } }
/// <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) { if (nsWindowRef == IntPtr.Zero) { nsWindowRef = Cocoa.SendIntPtr(nsViewRef, selWindow); } this.Handle = nsWindowRef; this.ViewHandle = nsViewRef; Cocoa.SendVoid(nsWindowRef, Selector.Retain); }
private void SetMenuVisible(bool visible) { var options = (NSApplicationPresentationOptions)Cocoa.SendInt(NSApplication.Handle, selPresentationOptions); var changedOptions = NSApplicationPresentationOptions.HideMenuBar | NSApplicationPresentationOptions.HideDock; if (!visible) { options |= changedOptions; } else { options &= ~changedOptions; } Cocoa.SendVoid(NSApplication.Handle, selSetPresentationOptions, (int)options); }
private void Dispose(bool disposing) { if (disposed) { return; } if (disposing) { Cocoa.SendVoid(Handle, Selector.Release); } else { Debug.Print("CocoaWindowInfo:{0} leaked, did you forget to call Dispose()?", Handle); } disposed = true; }
public static IntPtr ToNSString(string str) { if (str == null) { return(IntPtr.Zero); } unsafe { fixed(char *ptrFirstChar = str) { var handle = Cocoa.SendIntPtr(Class.Get("NSString"), Selector.Alloc); handle = Cocoa.SendIntPtr(handle, Selector.Get("initWithCharacters:length:"), (IntPtr)ptrFirstChar, str.Length); return(handle); } } }
public static unsafe IntPtr ToNSImage(Image img) { using (System.IO.MemoryStream s = new System.IO.MemoryStream()) { img.Save(s, ImageFormat.Png); byte[] b = s.ToArray(); fixed(byte *pBytes = b) { 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(Class.Get("NSImage"), Selector.Alloc), Selector.Get("initWithData:"), nsData); Cocoa.SendVoid(nsData, Selector.Release); return(nsImage); } } }
private void ResetTrackingArea() { 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); }
private void SetCursorVisible(bool visible) { // If the mouse is outside the window and we want to hide it, // move it inside the window first. // Otherwise, if we are making the cursor visible again, // we place it in the same spot as reported in the current // MouseState to avoid sudden jumps. if (!visible && !Bounds.Contains(new Point(MouseState.X, MouseState.Y))) { Mouse.SetPosition( (Bounds.Left + Bounds.Right) / 2, (Bounds.Top + Bounds.Bottom) / 2); } else if (visible) { var p = PointToScreen(new Point(MouseState.X, MouseState.Y)); Mouse.SetPosition((int)p.X, (int)p.Y); } CG.AssociateMouseAndMouseCursorPosition(visible); Cocoa.SendVoid(NSCursor, visible ? selUnhide : selHide); }
void ResetCursorRects(IntPtr sender, IntPtr cmd) { // We will add a new cursor rectangle that covers the complete view var rect = Cocoa.SendRect(windowInfo.ViewHandle, selBounds); // Inside this rectangle, the following NSCursor will be used var cursor = IntPtr.Zero; if (selectedCursor == MouseCursor.Default) { cursor = Cocoa.SendIntPtr(NSCursor, selArrowCursor); } else { cursor = ToNSCursor(selectedCursor); } // Setup the cursor rectangle if (cursor != IntPtr.Zero) { Cocoa.SendVoid(sender, selAddCursorRect, rect, cursor); } }
void InvalidateCursorRects() { Cocoa.SendVoid(windowInfo.Handle, selInvalidateCursorRectsForView, windowInfo.ViewHandle); }
public static IntPtr GetView(IntPtr windowHandle) { return(Cocoa.SendIntPtr(windowHandle, selContentView)); }
/// <summary> /// Allocates and initializes a new <see cref="NSAutoreleasePool" />. /// </summary> public NSAutoreleasePool() { var uninitializedPool = Cocoa.SendIntPtr(Class.NSAutoreleasePool, Selector.Alloc); _autoreleasePool = Cocoa.SendIntPtr(uninitializedPool, Selector.Init); }
private RectangleF GetContentViewFrame() { return(Cocoa.SendRect(windowInfo.ViewHandle, selFrame)); }
private IntPtr GetCurrentScreen() { return(Cocoa.SendIntPtr(windowInfo.Handle, selScreen)); }
/// <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.Handle = nsWindowRef; this.ViewHandle = nsViewRef; Cocoa.SendVoid(nsWindowRef, Selector.Retain); }
/// <summary> /// Constructs a new instance with the specified parameters. /// </summary> /// <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)) { }
private RectangleF GetCurrentScreenVisibleFrame() { return(Cocoa.SendRect(GetCurrentScreen(), selVisibleFrame)); }
static IntPtr ToNSCursor(MouseCursor cursor) { // We need to allocate a NSBitmapImageRep, fill it with pixels // and then convert it to a NSImage. // According to the documentation, alpha-enabled formats should // premultiply alpha, even though that "generally has negligible // 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); if (imgdata == IntPtr.Zero) { Debug.Print("Failed to create NSBitmapImageRep with size ({0},{1]})", cursor.Width, cursor.Height); return(IntPtr.Zero); } // Copy the cursor data int i = 0; IntPtr data = Cocoa.SendIntPtr(imgdata, selBitmapData); for (int y = 0; y < cursor.Height; y++) { for (int x = 0; x < cursor.Width; x++) { uint argb = unchecked ((uint)BitConverter.ToInt32(cursor.Data, i)); if (BitConverter.IsLittleEndian) { argb = (argb & 0x000000FFu) << 24 | (argb & 0x0000FF00u) << 8 | (argb & 0x00FF0000u) >> 8 | (argb & 0xFF000000u) >> 24; } Marshal.WriteInt32(data, i, unchecked ((int)argb)); i += 4; } } // Construct the actual NSImage IntPtr img = Cocoa.SendIntPtr( Cocoa.SendIntPtr( Cocoa.SendIntPtr(NSImage, Selector.Alloc), selInitWithSize, new SizeF(cursor.Width, cursor.Height)), Selector.Autorelease); if (img == IntPtr.Zero) { Debug.Print("Failed to construct NSImage from NSBitmapImageRep"); return(IntPtr.Zero); } Cocoa.SendVoid(img, selAddRepresentation, imgdata); // 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); return(nscursor); }
private void UpdateWindowBorder() { Cocoa.SendVoid(windowInfo.Handle, selSetStyleMask, (uint)GetStyleMask(windowBorder)); SetTitle(title, false); // Title gets lost after going borderless }
private NSWindowStyle GetStyleMask() { return((NSWindowStyle)Cocoa.SendUint(windowInfo.Handle, selStyleMask)); }
public override void ProcessEvents() { base.ProcessEvents(); while (true) { var e = Cocoa.SendIntPtr(NSApplication.Handle, selNextEventMatchingMask, uint.MaxValue, IntPtr.Zero, NSDefaultRunLoopMode, true); if (e == IntPtr.Zero) { break; } var type = (NSEventType)Cocoa.SendInt(e, selType); switch (type) { case NSEventType.KeyDown: { MacOSKeyCode keyCode = (MacOSKeyCode)Cocoa.SendUshort(e, selKeyCode); var isARepeat = Cocoa.SendBool(e, selIsARepeat); Key key = MacOSKeyMap.GetKey(keyCode); OnKeyDown(key, isARepeat); var s = Cocoa.FromNSString(Cocoa.SendIntPtr(e, selCharactersIgnoringModifiers)); foreach (var c in s) { int intVal = (int)c; if (!Char.IsControl(c) && (intVal < 63232 || intVal > 63235)) { // For some reason, arrow keys (mapped 63232-63235) // are seen as non-control characters, so get rid of those. OnKeyPress(c); } } } break; case NSEventType.KeyUp: { MacOSKeyCode keyCode = (MacOSKeyCode)Cocoa.SendUshort(e, selKeyCode); Key key = MacOSKeyMap.GetKey(keyCode); OnKeyUp(key); } break; case NSEventType.FlagsChanged: { var modifierFlags = (NSEventModifierMask)Cocoa.SendUint(e, selModifierFlags); UpdateModifierFlags(GetModifiers(modifierFlags)); } break; case NSEventType.MouseEntered: { var eventTrackingArea = Cocoa.SendIntPtr(e, selTrackingArea); var trackingAreaOwner = Cocoa.SendIntPtr(eventTrackingArea, selOwner); if (trackingAreaOwner == windowInfo.ViewHandle) { if (selectedCursor != MouseCursor.Default) { //SetCursor(selectedCursor); } OnMouseEnter(EventArgs.Empty); } } break; case NSEventType.MouseExited: { var eventTrackingArea = Cocoa.SendIntPtr(e, selTrackingArea); var trackingAreaOwner = Cocoa.SendIntPtr(eventTrackingArea, selOwner); if (trackingAreaOwner == windowInfo.ViewHandle) { if (selectedCursor != MouseCursor.Default) { //SetCursor(MouseCursor.Default); } OnMouseLeave(EventArgs.Empty); } } break; case NSEventType.LeftMouseDragged: case NSEventType.RightMouseDragged: case NSEventType.OtherMouseDragged: case NSEventType.MouseMoved: { Point p = new Point(MouseState.X, MouseState.Y); if (CursorVisible) { // Use absolute coordinates var pf = Cocoa.SendPoint(e, selLocationInWindowOwner); // Convert from points to pixel coordinates var rf = Cocoa.SendRect(windowInfo.Handle, selConvertRectToBacking, new RectangleF(pf.X, pf.Y, 0, 0)); // See CocoaDrawingGuide under "Converting from Window to View Coordinates" p = new Point( MathHelper.Clamp((int)Math.Round(rf.X), 0, Width), MathHelper.Clamp((int)Math.Round(Height - rf.Y), 0, Height)); } else { // Mouse has been disassociated, // use relative coordinates var dx = Cocoa.SendFloat(e, selDeltaX); var dy = Cocoa.SendFloat(e, selDeltaY); p = new Point( MathHelper.Clamp((int)Math.Round(p.X + dx), 0, Width), MathHelper.Clamp((int)Math.Round(p.Y + dy), 0, Height)); } // Only raise events when the mouse has actually moved if (MouseState.X != p.X || MouseState.Y != p.Y) { OnMouseMove(p.X, p.Y); } } break; case NSEventType.CursorUpdate: break; case NSEventType.ScrollWheel: { float dx, dy; if (Cocoa.SendBool(e, selHasPreciseScrollingDeltas)) { dx = Cocoa.SendFloat(e, selScrollingDeltaX) * MacOSFactory.ScrollFactor; dy = Cocoa.SendFloat(e, selScrollingDeltaY) * MacOSFactory.ScrollFactor; } else { dx = Cocoa.SendFloat(e, selDeltaX); dy = Cocoa.SendFloat(e, selDeltaY); } // Only raise wheel events when the user has actually scrolled if (dx != 0 || dy != 0) { OnMouseWheel(dx, dy); } } break; case NSEventType.LeftMouseDown: case NSEventType.RightMouseDown: case NSEventType.OtherMouseDown: { var buttonNumber = Cocoa.SendInt(e, selButtonNumber); OnMouseDown(GetMouseButton(buttonNumber)); } break; case NSEventType.LeftMouseUp: case NSEventType.RightMouseUp: case NSEventType.OtherMouseUp: { var buttonNumber = Cocoa.SendInt(e, selButtonNumber); OnMouseUp(GetMouseButton(buttonNumber)); } break; } Cocoa.SendVoid(NSApplication.Handle, selSendEvent, e); } // Handle closing 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); } } }
private MouseCursor selectedCursor = MouseCursor.Default; // user-selected cursor public CocoaNativeWindow(int x, int y, int width, int height, string title, GraphicsMode mode, GameWindowFlags options, DisplayDevice device) { // 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@:"); Class.RegisterClass(windowClass); IntPtr viewClass = Class.AllocateClass("OpenTK_NSView" + UniqueId, "NSView"); Class.RegisterMethod(viewClass, new ResetCursorRectsDelegate(ResetCursorRects), "resetCursorRects", "v@:"); Class.RegisterClass(viewClass); // Create window instance // Note: The coordinate system of Cocoa places (0,0) at the bottom left. // We need to get the height of the main screen and flip that in order // to place the window at the correct position. // Note: NSWindows are laid out relative to the main screen. var screenRect = Cocoa.SendRect( Cocoa.SendIntPtr( Cocoa.SendIntPtr(Class.Get("NSScreen"), Selector.Get("screens")), Selector.Get("objectAtIndex:"), 0), Selector.Get("frame")); var contentRect = new System.Drawing.RectangleF(x, screenRect.Height - height - y, width, height); 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); // 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")); // Our custom view with the same bounds: viewPtr = Cocoa.SendIntPtr( Cocoa.SendIntPtr(viewClass, Selector.Alloc), Selector.Get("initWithFrame:"), Cocoa.SendRect(viewPtr, selBounds)); if (viewPtr != IntPtr.Zero) { Cocoa.SendVoid(windowPtr, Selector.Get("setContentView:"), viewPtr); } windowInfo = new CocoaWindowInfo(windowPtr); // Set up behavior Cocoa.SendIntPtr(windowPtr, Selector.Get("setDelegate:"), windowPtr); // The window class acts as its own delegate Cocoa.SendVoid(windowPtr, Selector.Get("makeKeyWindow")); SetTitle(title, false); ResetTrackingArea(); exists = true; NSApplication.Quit += ApplicationQuit; }