MacOS: Implement mouse enter / leave events.

This commit is contained in:
kanato 2009-11-15 03:55:29 +00:00
parent 52e89c13b1
commit 103190ebf4
2 changed files with 109 additions and 8 deletions

View file

@ -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;

View file

@ -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<EventArgs> Idle;