* Platform/MacOS/CarbonGLNative.cs:

Implemented CursorVisible property. Aligned mouse behavior to win32 &
x11. General code cleanup.
This commit is contained in:
the_fiddler 2010-11-26 11:01:51 +00:00
parent 37a744acb3
commit db6cc338f5

View file

@ -62,7 +62,8 @@ namespace OpenTK.Platform.MacOS
private WindowBorder windowBorder = WindowBorder.Resizable; private WindowBorder windowBorder = WindowBorder.Resizable;
private WindowState windowState = WindowState.Normal; private WindowState windowState = WindowState.Normal;
static Dictionary<IntPtr, WeakReference> mWindows = new Dictionary<IntPtr, WeakReference>(); static Dictionary<IntPtr, WeakReference> mWindows =
new Dictionary<IntPtr, WeakReference>(new IntPtrEqualityComparer());
KeyPressEventArgs mKeyPressArgs = new KeyPressEventArgs((char)0); KeyPressEventArgs mKeyPressArgs = new KeyPressEventArgs((char)0);
@ -71,6 +72,10 @@ namespace OpenTK.Platform.MacOS
Icon mIcon; Icon mIcon;
// Used to accumulate mouse motion when the cursor is hidden.
float mouse_rel_x;
float mouse_rel_y;
#endregion #endregion
#region AGL Device Hack #region AGL Device Hack
@ -93,21 +98,26 @@ namespace OpenTK.Platform.MacOS
Application.Initialize(); Application.Initialize();
} }
CarbonGLNative() : this(WindowClass.Document, WindowAttributes.StandardDocument | WindowAttributes.StandardHandler | WindowAttributes.InWindowMenu | WindowAttributes.LiveResize) CarbonGLNative() : this(WindowClass.Document,
WindowAttributes.StandardDocument | WindowAttributes.StandardHandler |
WindowAttributes.InWindowMenu | WindowAttributes.LiveResize)
{ {
} }
CarbonGLNative(WindowClass @class, WindowAttributes attrib) CarbonGLNative(WindowClass @class, WindowAttributes attrib)
{ {
mWindowClass = @class; mWindowClass = @class;
mWindowAttrib = attrib; mWindowAttrib = attrib;
} }
public CarbonGLNative(int x, int y, int width, int height, string title, GraphicsMode mode, GameWindowFlags options, DisplayDevice device) public CarbonGLNative(int x, int y, int width, int height, string title,
GraphicsMode mode, GameWindowFlags options, DisplayDevice device)
{ {
CreateNativeWindow(WindowClass.Document, WindowAttributes.StandardDocument | WindowAttributes.StandardHandler | WindowAttributes.InWindowMenu | WindowAttributes.LiveResize, new Rect((short)x, (short)y, (short)width, (short)height)); CreateNativeWindow(WindowClass.Document,
WindowAttributes.StandardDocument | WindowAttributes.StandardHandler |
WindowAttributes.InWindowMenu | WindowAttributes.LiveResize,
new Rect((short)x, (short)y, (short)width, (short)height));
mDisplayDevice = device; mDisplayDevice = device;
} }
@ -125,14 +135,16 @@ namespace OpenTK.Platform.MacOS
{ {
if (mIsDisposed) if (mIsDisposed)
return; return;
Debug.Print("Disposing of CarbonGLNative window."); Debug.Print("Disposing of CarbonGLNative window.");
CursorVisible = true;
API.DisposeWindow(window.WindowRef); API.DisposeWindow(window.WindowRef);
mIsDisposed = true; mIsDisposed = true;
mExists = false; mExists = false;
CG.SetLocalEventsSuppressionInterval(0.25);
if (disposing) if (disposing)
{ {
mWindows.Remove(window.WindowRef); mWindows.Remove(window.WindowRef);
@ -140,9 +152,9 @@ namespace OpenTK.Platform.MacOS
window.Dispose(); window.Dispose();
window = null; window = null;
} }
DisposeUPP(); DisposeUPP();
Disposed(this, EventArgs.Empty); Disposed(this, EventArgs.Empty);
} }
@ -199,8 +211,15 @@ namespace OpenTK.Platform.MacOS
void ConnectEvents() void ConnectEvents()
{ {
mInputDriver = new CarbonInput(); mInputDriver = new CarbonInput();
EventTypeSpec[] eventTypes = new EventTypeSpec[]
{
new EventTypeSpec(EventClass.Window, WindowEventKind.WindowClose),
new EventTypeSpec(EventClass.Window, WindowEventKind.WindowClosed),
new EventTypeSpec(EventClass.Window, WindowEventKind.WindowBoundsChanged),
new EventTypeSpec(EventClass.Window, WindowEventKind.WindowActivate),
new EventTypeSpec(EventClass.Window, WindowEventKind.WindowDeactivate),
//new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseDown), //new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseDown),
//new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseUp), //new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseUp),
//new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseMoved), //new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseMoved),
@ -208,17 +227,18 @@ namespace OpenTK.Platform.MacOS
//new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseEntered), //new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseEntered),
//new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseExited), //new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseExited),
//new EventTypeSpec(EventClass.Mouse, MouseEventKind.WheelMoved), //new EventTypeSpec(EventClass.Mouse, MouseEventKind.WheelMoved),
//new EventTypeSpec(EventClass.Keyboard, KeyboardEventKind.RawKeyDown), //new EventTypeSpec(EventClass.Keyboard, KeyboardEventKind.RawKeyDown),
//new EventTypeSpec(EventClass.Keyboard, KeyboardEventKind.RawKeyRepeat), //new EventTypeSpec(EventClass.Keyboard, KeyboardEventKind.RawKeyRepeat),
//new EventTypeSpec(EventClass.Keyboard, KeyboardEventKind.RawKeyUp), //new EventTypeSpec(EventClass.Keyboard, KeyboardEventKind.RawKeyUp),
//new EventTypeSpec(EventClass.Keyboard, KeyboardEventKind.RawKeyModifiersChanged), //new EventTypeSpec(EventClass.Keyboard, KeyboardEventKind.RawKeyModifiersChanged),
EventTypeSpec[] eventTypes = new EventTypeSpec[] { new EventTypeSpec(EventClass.Window, WindowEventKind.WindowClose), new EventTypeSpec(EventClass.Window, WindowEventKind.WindowClosed), new EventTypeSpec(EventClass.Window, WindowEventKind.WindowBoundsChanged), new EventTypeSpec(EventClass.Window, WindowEventKind.WindowActivate), new EventTypeSpec(EventClass.Window, WindowEventKind.WindowDeactivate) }; };
MacOSEventHandler handler = EventHandler; MacOSEventHandler handler = EventHandler;
uppHandler = API.NewEventHandlerUPP(handler); uppHandler = API.NewEventHandlerUPP(handler);
API.InstallWindowEventHandler(window.WindowRef, uppHandler, eventTypes, window.WindowRef, IntPtr.Zero); API.InstallWindowEventHandler(window.WindowRef, uppHandler, eventTypes,
window.WindowRef, IntPtr.Zero);
Application.WindowEventHandler = this; Application.WindowEventHandler = this;
} }
@ -439,149 +459,124 @@ namespace OpenTK.Platform.MacOS
return OSStatus.EventNotHandled; return OSStatus.EventNotHandled;
} }
} }
protected OSStatus ProcessMouseEvent(IntPtr inCaller, IntPtr inEvent, EventInfo evt, IntPtr userData) protected OSStatus ProcessMouseEvent(IntPtr inCaller, IntPtr inEvent, EventInfo evt, IntPtr userData)
{ {
System.Diagnostics.Debug.Assert(evt.EventClass == EventClass.Mouse); System.Diagnostics.Debug.Assert(evt.EventClass == EventClass.Mouse);
MouseButton button = MouseButton.Primary; MouseButton button = MouseButton.Primary;
HIPoint pt = new HIPoint(); HIPoint pt = new HIPoint();
HIPoint screenLoc = new HIPoint(); HIPoint screenLoc = new HIPoint();
IntPtr thisEventWindow;
API.GetEventWindowRef(inEvent, out thisEventWindow);
OSStatus err = API.GetEventMouseLocation(inEvent, out screenLoc); OSStatus err = API.GetEventMouseLocation(inEvent, out screenLoc);
if (this.windowState == WindowState.Fullscreen) if (this.windowState == WindowState.Fullscreen)
{ {
pt = screenLoc; pt = screenLoc;
} }
else if (CursorVisible)
else
{ {
err = API.GetEventWindowMouseLocation(inEvent, out pt); err = API.GetEventWindowMouseLocation(inEvent, out pt);
pt.Y -= mTitlebarHeight;
}
else
{
err = API.GetEventMouseDelta(inEvent, out pt);
pt.X += mouse_rel_x;
pt.Y += mouse_rel_y;
pt = ConfineMouseToWindow(thisEventWindow, pt);
ResetMouseToWindowCenter();
mouse_rel_x = pt.X;
mouse_rel_y = pt.Y;
} }
if (err != OSStatus.NoError) if (err != OSStatus.NoError && err != OSStatus.EventParameterNotFound)
{ {
// this error comes up from the application event handler. // this error comes up from the application event handler.
if (err != OSStatus.EventParameterNotFound) throw new MacOSException(err);
{
throw new MacOSException(err);
}
} }
Point mousePosInClient = new Point((int)pt.X, (int)pt.Y); 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); CheckEnterLeaveEvents(thisEventWindow, mousePosInClient);
switch (evt.MouseEventKind) switch (evt.MouseEventKind)
{ {
case MouseEventKind.MouseDown: case MouseEventKind.MouseDown:
button = API.GetEventMouseButton(inEvent); case MouseEventKind.MouseUp:
button = API.GetEventMouseButton(inEvent);
switch (button) bool pressed = evt.MouseEventKind == MouseEventKind.MouseDown;
{
case MouseButton.Primary:
InputDriver.Mouse[0][OpenTK.Input.MouseButton.Left] = true;
break;
case MouseButton.Secondary:
InputDriver.Mouse[0][OpenTK.Input.MouseButton.Right] = true;
break;
case MouseButton.Tertiary:
InputDriver.Mouse[0][OpenTK.Input.MouseButton.Middle] = true;
break;
}
switch (button)
return OSStatus.NoError;
case MouseEventKind.MouseUp:
button = API.GetEventMouseButton(inEvent);
switch (button)
{
case MouseButton.Primary:
InputDriver.Mouse[0][OpenTK.Input.MouseButton.Left] = false;
break;
case MouseButton.Secondary:
InputDriver.Mouse[0][OpenTK.Input.MouseButton.Right] = false;
break;
case MouseButton.Tertiary:
InputDriver.Mouse[0][OpenTK.Input.MouseButton.Middle] = false;
break;
}
button = API.GetEventMouseButton(inEvent);
return OSStatus.NoError;
case MouseEventKind.WheelMoved:
int delta = API.GetEventMouseWheelDelta(inEvent) / 3;
InputDriver.Mouse[0].Wheel += delta;
return OSStatus.NoError;
case MouseEventKind.MouseMoved:
case MouseEventKind.MouseDragged:
//Debug.Print("Mouse Location: {0}, {1}", pt.X, pt.Y);
if (this.windowState == WindowState.Fullscreen)
{
if (mousePosInClient.X != InputDriver.Mouse[0].X || mousePosInClient.Y != InputDriver.Mouse[0].Y)
{ {
InputDriver.Mouse[0].Position = mousePosInClient; case MouseButton.Primary:
} InputDriver.Mouse[0][OpenTK.Input.MouseButton.Left] = pressed;
} break;
else case MouseButton.Secondary:
{ InputDriver.Mouse[0][OpenTK.Input.MouseButton.Right] = pressed;
// ignore clicks in the title bar break;
if (pt.Y < 0)
return OSStatus.EventNotHandled; case MouseButton.Tertiary:
InputDriver.Mouse[0][OpenTK.Input.MouseButton.Middle] = pressed;
if (mousePosInClient.X != InputDriver.Mouse[0].X || mousePosInClient.Y != InputDriver.Mouse[0].Y) break;
}
return OSStatus.NoError;
case MouseEventKind.WheelMoved:
float delta = API.GetEventMouseWheelDelta(inEvent);
InputDriver.Mouse[0].WheelPrecise += delta;
return OSStatus.NoError;
case MouseEventKind.MouseMoved:
case MouseEventKind.MouseDragged:
if (this.windowState == WindowState.Fullscreen)
{ {
InputDriver.Mouse[0].Position = mousePosInClient; if (mousePosInClient.X != InputDriver.Mouse[0].X || mousePosInClient.Y != InputDriver.Mouse[0].Y)
{
InputDriver.Mouse[0].Position = mousePosInClient;
}
} }
} else
{
// ignore clicks in the title bar
if (pt.Y < 0)
return OSStatus.EventNotHandled;
if (mousePosInClient.X != InputDriver.Mouse[0].X || mousePosInClient.Y != InputDriver.Mouse[0].Y)
return OSStatus.EventNotHandled; {
default: InputDriver.Mouse[0].Position = mousePosInClient;
}
Debug.Print("{0}", evt); }
return OSStatus.EventNotHandled;
return OSStatus.EventNotHandled;
default:
Debug.Print("{0}", evt);
return OSStatus.EventNotHandled;
} }
} }
void ResetMouseToWindowCenter()
{
OpenTK.Input.Mouse.SetPosition(
(Bounds.Left + Bounds.Right) / 2,
(Bounds.Top + Bounds.Bottom) / 2);
}
private void CheckEnterLeaveEvents(IntPtr eventWindowRef, Point pt) private void CheckEnterLeaveEvents(IntPtr eventWindowRef, Point pt)
{ {
if (window == null) if (window == null)
return; return;
bool thisIn = eventWindowRef == window.WindowRef; bool thisIn = eventWindowRef == window.WindowRef;
if (pt.Y < 0) if (pt.Y < 0)
thisIn = false; thisIn = false;
if (thisIn != mMouseIn) if (thisIn != mMouseIn)
{ {
mMouseIn = thisIn; mMouseIn = thisIn;
if (mMouseIn) if (mMouseIn)
OnMouseEnter(); OnMouseEnter();
else else
@ -589,11 +584,28 @@ namespace OpenTK.Platform.MacOS
} }
} }
// Point in client (window) coordinates
private HIPoint ConfineMouseToWindow(IntPtr window, HIPoint client)
{
if (client.X < 0)
client.X = 0;
if (client.X >= Width)
client.X = Width - 1;
if (client.Y < 0)
client.Y = 0;
if (client.Y >= Height)
client.Y = Height - 1;
Debug.Print("[{0}:{1}]", client.X, client.Y);
return client;
}
private static void GetCharCodes(IntPtr inEvent, out MacOSKeyCode code, out char charCode) private static void GetCharCodes(IntPtr inEvent, out MacOSKeyCode code, out char charCode)
{ {
code = API.GetEventKeyboardKeyCode(inEvent); code = API.GetEventKeyboardKeyCode(inEvent);
charCode = API.GetEventKeyboardChar(inEvent); charCode = API.GetEventKeyboardChar(inEvent);
} }
private void ProcessModifierKey(IntPtr inEvent) private void ProcessModifierKey(IntPtr inEvent)
{ {
MacOSKeyModifiers modifiers = API.GetEventKeyModifiers(inEvent); MacOSKeyModifiers modifiers = API.GetEventKeyModifiers(inEvent);
@ -662,7 +674,6 @@ namespace OpenTK.Platform.MacOS
API.SizeWindow(window.WindowRef, width, height, true); API.SizeWindow(window.WindowRef, width, height, true);
} }
private void LoadSize() private void LoadSize()
{ {
if (WindowState == WindowState.Fullscreen) if (WindowState == WindowState.Fullscreen)
@ -687,15 +698,12 @@ namespace OpenTK.Platform.MacOS
public Point PointToClient(Point point) public Point PointToClient(Point point)
{ {
Rect r = Carbon.API.GetWindowBounds(window.WindowRef, WindowRegionCode.ContentRegion); Rect r = Carbon.API.GetWindowBounds(window.WindowRef, WindowRegionCode.ContentRegion);
Debug.Print("Rect: {0}", r);
return new Point(point.X - r.X, point.Y - r.Y); return new Point(point.X - r.X, point.Y - r.Y);
} }
public Point PointToScreen(Point point) public Point PointToScreen(Point point)
{ {
Rect r = Carbon.API.GetWindowBounds(window.WindowRef, WindowRegionCode.ContentRegion); Rect r = Carbon.API.GetWindowBounds(window.WindowRef, WindowRegionCode.ContentRegion);
Debug.Print("Rect: {0}", r);
return new Point(point.X + r.X, point.Y + r.Y); return new Point(point.X + r.X, point.Y + r.Y);
} }
@ -719,7 +727,6 @@ namespace OpenTK.Platform.MacOS
get { return mInputDriver; } get { return mInputDriver; }
} }
public Icon Icon public Icon Icon
{ {
get { return mIcon; } get { return mIcon; }
@ -892,8 +899,21 @@ namespace OpenTK.Platform.MacOS
public bool CursorVisible public bool CursorVisible
{ {
get { return true; } get { return CG.CursorIsVisible(); }
set { } set
{
if (value)
{
CG.DisplayShowCursor(IntPtr.Zero);
CG.AssociateMouseAndMouseCursorPosition(true);
}
else
{
CG.DisplayHideCursor(IntPtr.Zero);
ResetMouseToWindowCenter();
CG.AssociateMouseAndMouseCursorPosition(false);
}
}
} }
public void Close() public void Close()