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); } } }