From 103190ebf408f27f9241ac100af15fe23c8e10c1 Mon Sep 17 00:00:00 2001 From: kanato Date: Sun, 15 Nov 2009 03:55:29 +0000 Subject: [PATCH] MacOS: Implement mouse enter / leave events. --- .../MacOS/CarbonBindings/CarbonAPI.cs | 59 ++++++++++++++++++- .../OpenTK/Platform/MacOS/CarbonGLNative.cs | 58 +++++++++++++++--- 2 files changed, 109 insertions(+), 8 deletions(-) diff --git a/Source/OpenTK/Platform/MacOS/CarbonBindings/CarbonAPI.cs b/Source/OpenTK/Platform/MacOS/CarbonBindings/CarbonAPI.cs index e91f0ebd..e924fed1 100644 --- a/Source/OpenTK/Platform/MacOS/CarbonBindings/CarbonAPI.cs +++ b/Source/OpenTK/Platform/MacOS/CarbonBindings/CarbonAPI.cs @@ -11,6 +11,8 @@ using System; using System.Runtime.InteropServices; using System.Diagnostics; using System.Drawing; +using EventTime = System.Double; + namespace OpenTK.Platform.MacOS.Carbon { @@ -121,6 +123,13 @@ namespace OpenTK.Platform.MacOS.Carbon #region --- Types defined in CarbonEvents.h --- + enum EventAttributes : uint + { + kEventAttributeNone = 0, + kEventAttributeUserEvent = (1 << 0), + kEventAttributeMonitored = 1 << 3, + } + [StructLayout(LayoutKind.Sequential)] internal struct EventTypeSpec { @@ -238,6 +247,8 @@ namespace OpenTK.Platform.MacOS.Carbon internal enum EventParamName : int { + WindowRef = 0x77696e64, // typeWindowRef, + // Mouse Events MouseLocation = 0x6d6c6f63, // typeHIPoint WindowMouseLocation = 0x776d6f75, // typeHIPoint @@ -255,6 +266,8 @@ namespace OpenTK.Platform.MacOS.Carbon } internal enum EventParamType : int { + typeWindowRef = 0x77696e64, + typeMouseButton = 0x6d62746e, typeMouseWheelAxis = 0x6d776178, typeHIPoint = 0x68697074, @@ -409,7 +422,7 @@ namespace OpenTK.Platform.MacOS.Carbon ScreenPixel = 2, Window = 3, View = 4 -}; + }; #region --- Carbon API Methods --- @@ -502,6 +515,12 @@ namespace OpenTK.Platform.MacOS.Carbon [DllImport(carbon)] static extern void ReleaseEvent(IntPtr theEvent); + internal static void SendEvent(IntPtr theEvent) + { + IntPtr theTarget = GetEventDispatcherTarget(); + SendEventToEventTarget(theEvent, theTarget); + } + // Processes events in the queue and then returns. internal static void ProcessEvents() { @@ -572,6 +591,26 @@ namespace OpenTK.Platform.MacOS.Carbon #endregion #region --- Getting Event Parameters --- + [DllImport(carbon,EntryPoint="CreateEvent")] + static extern OSStatus _CreateEvent( IntPtr inAllocator, + EventClass inClassID, UInt32 kind, EventTime when, + EventAttributes flags,out IntPtr outEvent); + + internal static IntPtr CreateWindowEvent(WindowEventKind kind) + { + IntPtr retval; + + OSStatus stat = _CreateEvent(IntPtr.Zero, EventClass.Window, (uint)kind, + 0, EventAttributes.kEventAttributeNone, out retval); + + if (stat != OSStatus.NoError) + { + throw new MacOSException(stat); + } + + return retval; + } + [DllImport(carbon)] static extern OSStatus GetEventParameter( IntPtr inEvent, EventParamName inName, EventParamType inDesiredType, @@ -678,6 +717,24 @@ namespace OpenTK.Platform.MacOS.Carbon } } + + static internal OSStatus GetEventWindowRef(IntPtr inEvent, out IntPtr windowRef) + { + IntPtr retval; + + unsafe + { + IntPtr* parm = &retval; + OSStatus result = API.GetEventParameter(inEvent, + EventParamName.WindowRef, EventParamType.typeWindowRef, IntPtr.Zero, + (uint)sizeof(IntPtr), IntPtr.Zero, (IntPtr)parm); + + windowRef = retval; + + return result; + } + } + static internal OSStatus GetEventMouseLocation(IntPtr inEvent, out HIPoint pt) { HIPoint point; diff --git a/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs b/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs index f1899bdb..df1b912d 100644 --- a/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs +++ b/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs @@ -66,6 +66,8 @@ namespace OpenTK.Platform.MacOS KeyPressEventArgs mKeyPressArgs = new KeyPressEventArgs((char)0); + bool mMouseIn = false; + #endregion #region AGL Device Hack @@ -421,12 +423,13 @@ namespace OpenTK.Platform.MacOS System.Diagnostics.Debug.Assert(evt.EventClass == EventClass.Mouse); MouseButton button = MouseButton.Primary; HIPoint pt = new HIPoint(); + HIPoint screenLoc = new HIPoint(); - OSStatus err; + OSStatus err = API.GetEventMouseLocation(inEvent, out screenLoc); if (this.windowState == WindowState.Fullscreen) { - err = API.GetEventMouseLocation(inEvent, out pt); + pt = screenLoc; } else { @@ -442,6 +445,17 @@ namespace OpenTK.Platform.MacOS } } + Point mousePosInClient = new Point((int)pt.X, (int)pt.Y); + if (this.windowState != WindowState.Fullscreen) + { + mousePosInClient.Y -= mTitlebarHeight; + } + + // check for enter/leave events + IntPtr thisEventWindow; + API.GetEventWindowRef(inEvent, out thisEventWindow); + CheckEnterLeaveEvents(thisEventWindow, mousePosInClient); + switch (evt.MouseEventKind) { case MouseEventKind.MouseDown: @@ -497,11 +511,11 @@ namespace OpenTK.Platform.MacOS case MouseEventKind.MouseMoved: case MouseEventKind.MouseDragged: + + //Debug.Print("Mouse Location: {0}, {1}", pt.X, pt.Y); if (this.windowState == WindowState.Fullscreen) { - Point mousePosInClient = new Point((int)pt.X, (int)pt.Y); - if (mousePosInClient.X != InputDriver.Mouse[0].X || mousePosInClient.Y != InputDriver.Mouse[0].Y) { @@ -511,11 +525,9 @@ namespace OpenTK.Platform.MacOS else { // ignore clicks in the title bar - if (pt.Y < mTitlebarHeight) + if (pt.Y < 0) return OSStatus.EventNotHandled; - Point mousePosInClient = new Point((int)pt.X, (int)(pt.Y - mTitlebarHeight)); - if (mousePosInClient.X != InputDriver.Mouse[0].X || mousePosInClient.Y != InputDriver.Mouse[0].Y) { @@ -532,6 +544,24 @@ namespace OpenTK.Platform.MacOS } } + private void CheckEnterLeaveEvents(IntPtr eventWindowRef, Point pt) + { + bool thisIn = eventWindowRef == window.WindowRef; + + if (pt.Y < 0) + thisIn = false; + + if (thisIn != mMouseIn) + { + mMouseIn = thisIn; + + if (mMouseIn) + OnMouseEnter(); + else + OnMouseLeave(); + } + } + private static void GetCharCodes(IntPtr inEvent, out MacOSKeyCode code, out char charCode) { code = API.GetEventKeyboardKeyCode(inEvent); @@ -984,6 +1014,20 @@ namespace OpenTK.Platform.MacOS Closed(this, EventArgs.Empty); } + + private void OnMouseLeave() + { + if (MouseLeave != null) + MouseLeave(this, EventArgs.Empty); + } + + private void OnMouseEnter() + { + if (MouseEnter != null) + MouseEnter(this, EventArgs.Empty); + } + + #endregion public event EventHandler Idle;