2009-06-02 15:49:39 +00:00
|
|
|
#region License
|
2009-02-22 10:43:35 +00:00
|
|
|
//
|
2009-06-02 15:49:39 +00:00
|
|
|
// The Open Toolkit Library License
|
2009-02-22 10:43:35 +00:00
|
|
|
//
|
2009-06-02 15:49:39 +00:00
|
|
|
// Copyright (c) 2006 - 2009 the Open Toolkit library.
|
2009-02-22 10:43:35 +00:00
|
|
|
//
|
2009-06-02 15:49:39 +00:00
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
|
|
// in the Software without restriction, including without limitation the rights to
|
|
|
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
|
|
// the Software, and to permit persons to whom the Software is furnished to do
|
|
|
|
// so, subject to the following conditions:
|
2009-02-22 10:43:35 +00:00
|
|
|
//
|
2009-06-02 15:49:39 +00:00
|
|
|
// The above copyright notice and this permission notice shall be included in all
|
|
|
|
// copies or substantial portions of the Software.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
|
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
|
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
|
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
|
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
|
|
// OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
//
|
|
|
|
#endregion
|
2009-02-22 10:43:35 +00:00
|
|
|
|
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.ComponentModel;
|
|
|
|
using System.Diagnostics;
|
2009-11-01 12:44:38 +00:00
|
|
|
using System.Drawing;
|
2009-02-22 10:43:35 +00:00
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
namespace OpenTK.Platform.MacOS
|
|
|
|
{
|
|
|
|
using Carbon;
|
|
|
|
using Graphics;
|
|
|
|
|
2009-06-24 14:38:48 +00:00
|
|
|
class CarbonGLNative : INativeWindow
|
2009-02-22 10:43:35 +00:00
|
|
|
{
|
2009-06-02 15:49:39 +00:00
|
|
|
#region Fields
|
|
|
|
|
2009-02-22 10:43:35 +00:00
|
|
|
CarbonWindowInfo window;
|
|
|
|
CarbonInput mInputDriver;
|
|
|
|
GraphicsContext context;
|
|
|
|
|
|
|
|
static MacOSKeyMap Keymap = new MacOSKeyMap();
|
|
|
|
|
|
|
|
IntPtr uppHandler;
|
|
|
|
|
|
|
|
string title = "OpenTK Window";
|
2009-11-01 12:44:38 +00:00
|
|
|
Rectangle bounds, windowedBounds, clientRectangle;
|
2009-02-22 10:43:35 +00:00
|
|
|
bool mIsDisposed = false;
|
|
|
|
|
|
|
|
WindowAttributes mWindowAttrib;
|
|
|
|
WindowClass mWindowClass;
|
|
|
|
WindowPositionMethod mPositionMethod = WindowPositionMethod.CenterOnMainScreen;
|
|
|
|
int mTitlebarHeight;
|
|
|
|
private WindowBorder windowBorder = WindowBorder.Resizable;
|
|
|
|
private WindowState windowState = WindowState.Normal;
|
|
|
|
|
|
|
|
static Dictionary<IntPtr, WeakReference> mWindows = new Dictionary<IntPtr, WeakReference>();
|
|
|
|
|
2009-06-02 15:49:39 +00:00
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region Constructors
|
|
|
|
|
2009-02-22 10:43:35 +00:00
|
|
|
static CarbonGLNative()
|
|
|
|
{
|
|
|
|
Application.Initialize();
|
|
|
|
}
|
2009-06-02 15:49:39 +00:00
|
|
|
|
|
|
|
CarbonGLNative()
|
2009-02-22 10:43:35 +00:00
|
|
|
: this(WindowClass.Document,
|
|
|
|
WindowAttributes.StandardDocument |
|
|
|
|
WindowAttributes.StandardHandler |
|
|
|
|
WindowAttributes.InWindowMenu |
|
|
|
|
WindowAttributes.LiveResize)
|
2009-06-02 15:49:39 +00:00
|
|
|
{ }
|
2009-02-22 10:43:35 +00:00
|
|
|
|
2009-06-02 15:49:39 +00:00
|
|
|
|
|
|
|
CarbonGLNative(WindowClass @class, WindowAttributes attrib)
|
2009-02-22 10:43:35 +00:00
|
|
|
{
|
|
|
|
mWindowClass = @class;
|
|
|
|
mWindowAttrib = attrib;
|
|
|
|
}
|
2009-06-02 15:49:39 +00:00
|
|
|
|
|
|
|
public CarbonGLNative(int x, int y, int width, int height, string title, GraphicsMode mode, GameWindowFlags options, DisplayDevice device)
|
2009-02-22 10:43:35 +00:00
|
|
|
{
|
2009-06-02 15:49:39 +00:00
|
|
|
CreateNativeWindow(WindowClass.Document,
|
|
|
|
WindowAttributes.StandardDocument | WindowAttributes.StandardHandler |
|
|
|
|
WindowAttributes.InWindowMenu | WindowAttributes.LiveResize,
|
|
|
|
new Rect((short)x, (short)y, (short)width, (short)height));
|
2009-02-22 10:43:35 +00:00
|
|
|
}
|
|
|
|
|
2009-06-02 15:49:39 +00:00
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region IDisposable
|
|
|
|
|
2009-02-22 10:43:35 +00:00
|
|
|
public void Dispose()
|
|
|
|
{
|
|
|
|
Dispose(true);
|
|
|
|
GC.SuppressFinalize(this);
|
|
|
|
}
|
2009-06-02 15:49:39 +00:00
|
|
|
|
2009-02-22 10:43:35 +00:00
|
|
|
protected virtual void Dispose(bool disposing)
|
|
|
|
{
|
|
|
|
if (mIsDisposed)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Debug.Print("Disposing of CarbonGLNative window.");
|
|
|
|
|
|
|
|
mIsDisposed = true;
|
|
|
|
|
|
|
|
if (disposing)
|
|
|
|
{
|
|
|
|
mWindows.Remove(window.WindowRef);
|
|
|
|
|
|
|
|
window.Dispose();
|
|
|
|
window = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
DisposeUPP();
|
|
|
|
}
|
|
|
|
|
2009-06-02 15:49:39 +00:00
|
|
|
~CarbonGLNative()
|
|
|
|
{
|
|
|
|
Dispose(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region Private Members
|
|
|
|
|
|
|
|
void DisposeUPP()
|
2009-02-22 10:43:35 +00:00
|
|
|
{
|
|
|
|
if (uppHandler != IntPtr.Zero)
|
|
|
|
{
|
|
|
|
//API.RemoveEventHandler(uppHandler);
|
|
|
|
//API.DisposeEventHandlerUPP(uppHandler);
|
|
|
|
}
|
|
|
|
|
|
|
|
uppHandler = IntPtr.Zero;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CreateNativeWindow(WindowClass @class, WindowAttributes attrib, Rect r)
|
|
|
|
{
|
|
|
|
Debug.Print("Creating window...");
|
|
|
|
Debug.Indent();
|
|
|
|
|
|
|
|
IntPtr windowRef = API.CreateNewWindow(@class, attrib, r);
|
|
|
|
API.SetWindowTitle(windowRef, title);
|
|
|
|
|
|
|
|
window = new CarbonWindowInfo(windowRef, true, false);
|
|
|
|
|
2009-06-02 15:49:39 +00:00
|
|
|
SetLocation(r.X, r.Y);
|
2009-02-22 10:43:35 +00:00
|
|
|
SetSize(r.Width, r.Height);
|
|
|
|
|
|
|
|
Debug.Unindent();
|
|
|
|
Debug.Print("Created window.");
|
|
|
|
|
|
|
|
mWindows.Add(windowRef, new WeakReference(this));
|
|
|
|
|
|
|
|
LoadSize();
|
|
|
|
|
|
|
|
Rect titleSize = API.GetWindowBounds(window.WindowRef, WindowRegionCode.TitleBarRegion);
|
|
|
|
mTitlebarHeight = titleSize.Height;
|
|
|
|
|
|
|
|
Debug.Print("Titlebar size: {0}", titleSize);
|
|
|
|
|
|
|
|
ConnectEvents();
|
|
|
|
|
|
|
|
System.Diagnostics.Debug.Print("Attached window events.");
|
|
|
|
}
|
2009-06-02 15:49:39 +00:00
|
|
|
|
2009-02-22 10:43:35 +00:00
|
|
|
void ConnectEvents()
|
|
|
|
{
|
|
|
|
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.Mouse, MouseEventKind.MouseDown),
|
|
|
|
//new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseUp),
|
|
|
|
//new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseMoved),
|
|
|
|
//new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseDragged),
|
|
|
|
//new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseEntered),
|
|
|
|
//new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseExited),
|
|
|
|
//new EventTypeSpec(EventClass.Mouse, MouseEventKind.WheelMoved),
|
|
|
|
|
|
|
|
//new EventTypeSpec(EventClass.Keyboard, KeyboardEventKind.RawKeyDown),
|
|
|
|
//new EventTypeSpec(EventClass.Keyboard, KeyboardEventKind.RawKeyRepeat),
|
|
|
|
//new EventTypeSpec(EventClass.Keyboard, KeyboardEventKind.RawKeyUp),
|
|
|
|
//new EventTypeSpec(EventClass.Keyboard, KeyboardEventKind.RawKeyModifiersChanged),
|
|
|
|
};
|
|
|
|
|
|
|
|
MacOSEventHandler handler = EventHandler;
|
|
|
|
uppHandler = API.NewEventHandlerUPP(handler);
|
|
|
|
|
|
|
|
API.InstallWindowEventHandler(window.WindowRef, uppHandler, eventTypes, window.WindowRef, IntPtr.Zero);
|
|
|
|
|
|
|
|
Application.WindowEventHandler = this;
|
|
|
|
}
|
|
|
|
|
2009-06-02 15:49:39 +00:00
|
|
|
void Activate()
|
2009-02-22 10:43:35 +00:00
|
|
|
{
|
|
|
|
API.SelectWindow(window.WindowRef);
|
|
|
|
}
|
2009-06-02 15:49:39 +00:00
|
|
|
|
|
|
|
void Show()
|
2009-02-22 10:43:35 +00:00
|
|
|
{
|
|
|
|
IntPtr parent = IntPtr.Zero;
|
|
|
|
|
|
|
|
API.ShowWindow(window.WindowRef);
|
|
|
|
API.RepositionWindow(window.WindowRef, parent, WindowPositionMethod);
|
|
|
|
API.SelectWindow(window.WindowRef);
|
|
|
|
}
|
2009-06-02 15:49:39 +00:00
|
|
|
|
|
|
|
void Hide()
|
2009-02-22 10:43:35 +00:00
|
|
|
{
|
|
|
|
API.HideWindow(window.WindowRef);
|
|
|
|
}
|
2009-06-02 15:49:39 +00:00
|
|
|
|
|
|
|
void SetFullscreen()
|
2009-02-22 10:43:35 +00:00
|
|
|
{
|
2009-06-02 15:49:39 +00:00
|
|
|
windowedBounds = bounds;
|
|
|
|
|
|
|
|
((AglContext)(context as IGraphicsContextInternal).Implementation).SetFullScreen(window);
|
|
|
|
|
|
|
|
Debug.Print("Prev Size: {0}, {1}", Width, Height);
|
|
|
|
|
|
|
|
bounds = DisplayDevice.Default.Bounds;
|
|
|
|
|
|
|
|
Debug.Print("New Size: {0}, {1}", Width, Height);
|
2009-02-22 10:43:35 +00:00
|
|
|
}
|
2009-06-02 15:49:39 +00:00
|
|
|
|
|
|
|
void UnsetFullscreen()
|
|
|
|
{
|
|
|
|
((AglContext)(context as IGraphicsContextInternal).Implementation).UnsetFullScreen(window);
|
|
|
|
SetSize((short)windowedBounds.Width, (short)windowedBounds.Height);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsDisposed
|
2009-02-22 10:43:35 +00:00
|
|
|
{
|
|
|
|
get { return mIsDisposed; }
|
|
|
|
}
|
|
|
|
|
2009-06-02 15:49:39 +00:00
|
|
|
WindowPositionMethod WindowPositionMethod
|
2009-02-22 10:43:35 +00:00
|
|
|
{
|
|
|
|
get { return mPositionMethod; }
|
|
|
|
set { mPositionMethod = value; }
|
|
|
|
}
|
|
|
|
|
|
|
|
internal OSStatus DispatchEvent(IntPtr inCaller, IntPtr inEvent, EventInfo evt, IntPtr userData)
|
|
|
|
{
|
|
|
|
switch (evt.EventClass)
|
|
|
|
{
|
|
|
|
case EventClass.Window:
|
|
|
|
return ProcessWindowEvent(inCaller, inEvent, evt, userData);
|
|
|
|
|
|
|
|
case EventClass.Mouse:
|
|
|
|
return ProcessMouseEvent(inCaller, inEvent, evt, userData);
|
|
|
|
|
|
|
|
case EventClass.Keyboard:
|
|
|
|
return ProcessKeyboardEvent(inCaller, inEvent, evt, userData);
|
|
|
|
|
|
|
|
default:
|
|
|
|
return OSStatus.EventNotHandled;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected static OSStatus EventHandler(IntPtr inCaller, IntPtr inEvent, IntPtr userData)
|
|
|
|
{
|
|
|
|
// bail out if the window passed in is not actually our window.
|
|
|
|
// I think this happens if using winforms with a GameWindow sometimes.
|
|
|
|
if (mWindows.ContainsKey(userData) == false)
|
|
|
|
return OSStatus.EventNotHandled;
|
|
|
|
|
|
|
|
WeakReference reference = mWindows[userData];
|
|
|
|
|
|
|
|
// bail out if the CarbonGLNative window has been garbage collected.
|
|
|
|
if (reference.IsAlive == false)
|
|
|
|
{
|
|
|
|
mWindows.Remove(userData);
|
|
|
|
return OSStatus.EventNotHandled;
|
|
|
|
}
|
|
|
|
|
|
|
|
EventInfo evt = new EventInfo(inEvent);
|
|
|
|
CarbonGLNative window = (CarbonGLNative)reference.Target;
|
|
|
|
|
|
|
|
//Debug.Print("Processing {0} event for {1}.", evt, window.window);
|
|
|
|
|
|
|
|
if (window == null)
|
|
|
|
{
|
|
|
|
Debug.WriteLine("Window for event not found.");
|
|
|
|
return OSStatus.EventNotHandled;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (evt.EventClass)
|
|
|
|
{
|
|
|
|
case EventClass.Window:
|
|
|
|
return window.ProcessWindowEvent(inCaller, inEvent, evt, userData);
|
|
|
|
|
|
|
|
case EventClass.Mouse:
|
|
|
|
return window.ProcessMouseEvent(inCaller, inEvent, evt, userData);
|
|
|
|
|
|
|
|
case EventClass.Keyboard:
|
|
|
|
return window.ProcessKeyboardEvent(inCaller, inEvent, evt, userData);
|
|
|
|
|
|
|
|
default:
|
|
|
|
return OSStatus.EventNotHandled;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private OSStatus ProcessKeyboardEvent(IntPtr inCaller, IntPtr inEvent, EventInfo evt, IntPtr userData)
|
|
|
|
{
|
|
|
|
System.Diagnostics.Debug.Assert(evt.EventClass == EventClass.Keyboard);
|
|
|
|
MacOSKeyCode code;
|
|
|
|
char charCode;
|
|
|
|
|
|
|
|
switch (evt.KeyboardEventKind)
|
|
|
|
{
|
|
|
|
case KeyboardEventKind.RawKeyRepeat:
|
|
|
|
GetCharCodes(inEvent, out code, out charCode);
|
|
|
|
InputDriver.Keyboard[0].KeyRepeat = true;
|
|
|
|
goto case KeyboardEventKind.RawKeyDown;
|
|
|
|
|
|
|
|
case KeyboardEventKind.RawKeyDown:
|
|
|
|
GetCharCodes(inEvent, out code, out charCode);
|
|
|
|
InputDriver.Keyboard[0][Keymap[code]] = true;
|
|
|
|
return OSStatus.EventNotHandled;
|
|
|
|
|
|
|
|
case KeyboardEventKind.RawKeyUp:
|
|
|
|
GetCharCodes(inEvent, out code, out charCode);
|
|
|
|
InputDriver.Keyboard[0][Keymap[code]] = false;
|
|
|
|
|
|
|
|
return OSStatus.EventNotHandled;
|
|
|
|
|
|
|
|
case KeyboardEventKind.RawKeyModifiersChanged:
|
|
|
|
ProcessModifierKey(inEvent);
|
|
|
|
return OSStatus.EventNotHandled;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return OSStatus.EventNotHandled;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
private OSStatus ProcessWindowEvent(IntPtr inCaller, IntPtr inEvent, EventInfo evt, IntPtr userData)
|
|
|
|
{
|
|
|
|
System.Diagnostics.Debug.Assert(evt.EventClass == EventClass.Window);
|
|
|
|
|
|
|
|
switch (evt.WindowEventKind)
|
|
|
|
{
|
|
|
|
case WindowEventKind.WindowClose:
|
|
|
|
CancelEventArgs cancel = new CancelEventArgs();
|
2009-06-02 15:49:39 +00:00
|
|
|
OnClosing(cancel);
|
2009-02-22 10:43:35 +00:00
|
|
|
|
|
|
|
if (cancel.Cancel)
|
|
|
|
return OSStatus.NoError;
|
|
|
|
else
|
|
|
|
return OSStatus.EventNotHandled;
|
|
|
|
|
|
|
|
case WindowEventKind.WindowClosed:
|
2009-06-02 15:49:39 +00:00
|
|
|
OnClosed();
|
2009-02-22 10:43:35 +00:00
|
|
|
|
|
|
|
return OSStatus.NoError;
|
|
|
|
|
|
|
|
case WindowEventKind.WindowBoundsChanged:
|
|
|
|
int thisWidth = Width;
|
|
|
|
int thisHeight = Height;
|
|
|
|
|
|
|
|
LoadSize();
|
|
|
|
|
|
|
|
if (thisWidth != Width || thisHeight != Height)
|
|
|
|
OnResize();
|
|
|
|
|
|
|
|
return OSStatus.EventNotHandled;
|
|
|
|
|
|
|
|
default:
|
|
|
|
Debug.Print("{0}", evt);
|
|
|
|
|
|
|
|
return OSStatus.EventNotHandled;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
protected OSStatus ProcessMouseEvent(IntPtr inCaller, IntPtr inEvent, EventInfo evt, IntPtr userData)
|
|
|
|
{
|
|
|
|
System.Diagnostics.Debug.Assert(evt.EventClass == EventClass.Mouse);
|
|
|
|
MouseButton button = MouseButton.Primary;
|
|
|
|
HIPoint pt = new HIPoint();
|
|
|
|
|
2009-06-02 15:49:39 +00:00
|
|
|
OSStatus err;
|
2009-02-22 10:43:35 +00:00
|
|
|
|
|
|
|
if (this.windowState == WindowState.Fullscreen)
|
|
|
|
{
|
|
|
|
err = API.GetEventMouseLocation(inEvent, out pt);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
err = API.GetEventWindowMouseLocation(inEvent, out pt);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (err != OSStatus.NoError)
|
|
|
|
{
|
|
|
|
// this error comes up from the application event handler.
|
|
|
|
if (err != OSStatus.EventParameterNotFound)
|
|
|
|
{
|
|
|
|
throw new MacOSException(err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (this.windowState == WindowState.Fullscreen)
|
|
|
|
{
|
2009-11-01 12:44:38 +00:00
|
|
|
InputDriver.Mouse[0].Position = new Point((int)pt.X, (int)pt.Y);
|
2009-02-22 10:43:35 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// ignore clicks in the title bar
|
|
|
|
if (pt.Y < mTitlebarHeight)
|
|
|
|
return OSStatus.EventNotHandled;
|
|
|
|
|
2009-11-01 12:44:38 +00:00
|
|
|
InputDriver.Mouse[0].Position =
|
|
|
|
new Point((int)pt.X, (int)(pt.Y - mTitlebarHeight));
|
2009-02-22 10:43:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (evt.MouseEventKind)
|
|
|
|
{
|
|
|
|
case MouseEventKind.MouseDown:
|
|
|
|
button = API.GetEventMouseButton(inEvent);
|
|
|
|
|
|
|
|
switch (button)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseEventKind.MouseUp:
|
|
|
|
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);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseEventKind.MouseMoved:
|
|
|
|
case MouseEventKind.MouseDragged:
|
|
|
|
|
|
|
|
//Debug.Print("MouseMoved: {0}", InputDriver.Mouse[0].Position);
|
|
|
|
|
|
|
|
return OSStatus.EventNotHandled;
|
|
|
|
|
|
|
|
default:
|
|
|
|
Debug.Print("{0}", evt);
|
|
|
|
|
|
|
|
return OSStatus.EventNotHandled;
|
|
|
|
}
|
|
|
|
|
|
|
|
return OSStatus.EventNotHandled;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void GetCharCodes(IntPtr inEvent, out MacOSKeyCode code, out char charCode)
|
|
|
|
{
|
|
|
|
code = API.GetEventKeyboardKeyCode(inEvent);
|
|
|
|
charCode = API.GetEventKeyboardChar(inEvent);
|
|
|
|
}
|
|
|
|
private void ProcessModifierKey(IntPtr inEvent)
|
|
|
|
{
|
|
|
|
MacOSKeyModifiers modifiers = API.GetEventKeyModifiers(inEvent);
|
|
|
|
|
|
|
|
bool caps = (modifiers & MacOSKeyModifiers.CapsLock) != 0 ? true : false;
|
|
|
|
bool control = (modifiers & MacOSKeyModifiers.Control) != 0 ? true : false;
|
|
|
|
bool command = (modifiers & MacOSKeyModifiers.Command) != 0 ? true : false;
|
|
|
|
bool option = (modifiers & MacOSKeyModifiers.Option) != 0 ? true : false;
|
|
|
|
bool shift = (modifiers & MacOSKeyModifiers.Shift) != 0 ? true : false;
|
|
|
|
|
|
|
|
Debug.Print("Modifiers Changed: {0}", modifiers);
|
|
|
|
|
|
|
|
Input.KeyboardDevice keyboard = InputDriver.Keyboard[0];
|
|
|
|
|
|
|
|
if (keyboard[OpenTK.Input.Key.AltLeft] ^ option)
|
|
|
|
keyboard[OpenTK.Input.Key.AltLeft] = option;
|
|
|
|
|
|
|
|
if (keyboard[OpenTK.Input.Key.ShiftLeft] ^ shift)
|
|
|
|
keyboard[OpenTK.Input.Key.ShiftLeft] = shift;
|
|
|
|
|
|
|
|
if (keyboard[OpenTK.Input.Key.WinLeft] ^ command)
|
|
|
|
keyboard[OpenTK.Input.Key.WinLeft] = command;
|
|
|
|
|
|
|
|
if (keyboard[OpenTK.Input.Key.ControlLeft] ^ control)
|
|
|
|
keyboard[OpenTK.Input.Key.ControlLeft] = control;
|
|
|
|
|
|
|
|
if (keyboard[OpenTK.Input.Key.CapsLock] ^ caps)
|
|
|
|
keyboard[OpenTK.Input.Key.CapsLock] = caps;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Rect GetRegion()
|
|
|
|
{
|
|
|
|
Rect retval = API.GetWindowBounds(window.WindowRef, WindowRegionCode.ContentRegion);
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2009-06-02 15:49:39 +00:00
|
|
|
void SetLocation(short x, short y)
|
2009-02-22 10:43:35 +00:00
|
|
|
{
|
2009-06-02 15:49:39 +00:00
|
|
|
if (windowState == WindowState.Fullscreen)
|
|
|
|
return;
|
|
|
|
|
|
|
|
API.MoveWindow(window.WindowRef, x, y, false);
|
2009-02-22 10:43:35 +00:00
|
|
|
}
|
2009-06-02 15:49:39 +00:00
|
|
|
|
|
|
|
void SetSize(short width, short height)
|
2009-02-22 10:43:35 +00:00
|
|
|
{
|
|
|
|
if (WindowState == WindowState.Fullscreen)
|
|
|
|
return;
|
|
|
|
|
2009-06-02 15:49:39 +00:00
|
|
|
// Todo: why call SizeWindow twice?
|
|
|
|
API.SizeWindow(window.WindowRef, width, height, true);
|
|
|
|
bounds.Width = (short)width;
|
|
|
|
bounds.Height = (short)height;
|
2009-02-22 10:43:35 +00:00
|
|
|
|
|
|
|
Rect contentBounds = API.GetWindowBounds(window.WindowRef, WindowRegionCode.ContentRegion);
|
|
|
|
|
|
|
|
Rect newSize = new Rect(0, 0,
|
2009-06-02 15:49:39 +00:00
|
|
|
(short)(2 * width - contentBounds.Width),
|
|
|
|
(short)(2 * height - contentBounds.Height));
|
2009-02-22 10:43:35 +00:00
|
|
|
|
|
|
|
Debug.Print("Content region was: {0}", contentBounds);
|
|
|
|
Debug.Print("Resizing window to: {0}", newSize);
|
|
|
|
|
|
|
|
API.SizeWindow(window.WindowRef, newSize.Width, newSize.Height, true);
|
|
|
|
|
|
|
|
contentBounds = API.GetWindowBounds(window.WindowRef, WindowRegionCode.ContentRegion);
|
|
|
|
Debug.Print("New content region size: {0}", contentBounds);
|
2009-06-02 15:49:39 +00:00
|
|
|
clientRectangle = contentBounds.ToRectangle();
|
2009-02-22 10:43:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected void OnResize()
|
|
|
|
{
|
|
|
|
LoadSize();
|
|
|
|
|
|
|
|
if (context != null && this.windowState != WindowState.Fullscreen)
|
|
|
|
context.Update(window);
|
|
|
|
|
|
|
|
if (Resize != null)
|
|
|
|
{
|
2009-06-04 11:31:02 +00:00
|
|
|
Resize(this, EventArgs.Empty);
|
2009-02-22 10:43:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void LoadSize()
|
|
|
|
{
|
|
|
|
if (WindowState == WindowState.Fullscreen)
|
|
|
|
return;
|
|
|
|
|
2009-06-02 15:49:39 +00:00
|
|
|
bounds = GetRegion().ToRectangle();
|
2009-02-22 10:43:35 +00:00
|
|
|
}
|
|
|
|
|
2009-06-02 15:49:39 +00:00
|
|
|
protected virtual void OnClosing(CancelEventArgs e)
|
2009-02-22 10:43:35 +00:00
|
|
|
{
|
2009-06-02 15:49:39 +00:00
|
|
|
if (Closing != null)
|
|
|
|
Closing(this, e);
|
2009-02-22 10:43:35 +00:00
|
|
|
}
|
|
|
|
|
2009-06-02 15:49:39 +00:00
|
|
|
protected virtual void OnClosed()
|
|
|
|
{
|
|
|
|
if (Closed != null)
|
|
|
|
Closed(this, EventArgs.Empty);
|
2009-02-22 10:43:35 +00:00
|
|
|
}
|
|
|
|
|
2009-06-02 15:49:39 +00:00
|
|
|
#endregion
|
2009-02-22 10:43:35 +00:00
|
|
|
|
|
|
|
#region INativeGLWindow Members
|
|
|
|
|
2009-08-14 13:13:28 +00:00
|
|
|
public void CreateWindow(int width, int height, GraphicsMode mode, int major, int minor, GraphicsContextFlags flags, out IGraphicsContext context)
|
2009-02-22 10:43:35 +00:00
|
|
|
{
|
|
|
|
Rect r = new Rect(0, 0, (short)width, (short)height);
|
|
|
|
CreateNativeWindow(mWindowClass, mWindowAttrib, r);
|
|
|
|
|
|
|
|
Show();
|
|
|
|
|
2009-08-14 13:13:28 +00:00
|
|
|
this.context = new GraphicsContext(mode, window, major, minor, flags);
|
2009-02-22 10:43:35 +00:00
|
|
|
this.context.MakeCurrent(window);
|
|
|
|
|
|
|
|
context = this.context;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void DestroyWindow()
|
|
|
|
{
|
|
|
|
Dispose();
|
|
|
|
}
|
|
|
|
public void ProcessEvents()
|
|
|
|
{
|
|
|
|
Application.ProcessEvents();
|
|
|
|
}
|
|
|
|
|
2009-11-01 12:44:38 +00:00
|
|
|
public Point PointToClient(Point point)
|
2009-02-22 10:43:35 +00:00
|
|
|
{
|
2009-05-07 19:48:22 +00:00
|
|
|
IntPtr handle = window.WindowRef;
|
|
|
|
|
2009-05-11 01:10:09 +00:00
|
|
|
Rect r = Carbon.API.GetWindowBounds(window.WindowRef, WindowRegionCode.ContentRegion);
|
|
|
|
Console.WriteLine("Rect: {0}", r);
|
|
|
|
|
2009-11-01 12:44:38 +00:00
|
|
|
return new Point(point.X - r.X, point.Y - r.Y);
|
2009-02-22 10:43:35 +00:00
|
|
|
}
|
2009-11-01 12:44:38 +00:00
|
|
|
public Point PointToScreen(Point point)
|
2009-02-22 10:43:35 +00:00
|
|
|
{
|
2009-05-07 19:48:22 +00:00
|
|
|
throw new NotImplementedException();
|
2009-02-22 10:43:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public bool Exists
|
|
|
|
{
|
|
|
|
get { return !mIsDisposed; }
|
|
|
|
}
|
|
|
|
|
|
|
|
public IWindowInfo WindowInfo
|
|
|
|
{
|
|
|
|
get { return window; }
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool IsIdle
|
|
|
|
{
|
|
|
|
get { return true; }
|
|
|
|
}
|
|
|
|
|
|
|
|
public OpenTK.Input.IInputDriver InputDriver
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return mInputDriver;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool Fullscreen
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
set
|
|
|
|
{
|
|
|
|
throw new NotImplementedException();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
2009-06-02 15:49:39 +00:00
|
|
|
#region INativeWindow Members
|
|
|
|
|
2009-10-18 16:52:07 +00:00
|
|
|
public System.Drawing.Icon Icon
|
|
|
|
{
|
|
|
|
get { return null; }
|
|
|
|
set { }
|
|
|
|
}
|
|
|
|
|
2009-06-02 15:49:39 +00:00
|
|
|
public string Title
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return title;
|
|
|
|
}
|
|
|
|
set
|
|
|
|
{
|
|
|
|
API.SetWindowTitle(window.WindowRef, value);
|
|
|
|
title = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool Visible
|
|
|
|
{
|
|
|
|
get { return API.IsWindowVisible(window.WindowRef); }
|
|
|
|
set
|
|
|
|
{
|
|
|
|
if (value && Visible == false)
|
|
|
|
Show();
|
|
|
|
else
|
|
|
|
Hide();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool Focused
|
|
|
|
{
|
|
|
|
get { throw new NotImplementedException(); }
|
|
|
|
}
|
|
|
|
|
2009-11-01 12:44:38 +00:00
|
|
|
public Rectangle Bounds
|
2009-06-02 15:49:39 +00:00
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return bounds;
|
|
|
|
}
|
|
|
|
set
|
|
|
|
{
|
|
|
|
Location = value.Location;
|
|
|
|
Size = value.Size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-01 12:44:38 +00:00
|
|
|
public Point Location
|
2009-06-02 15:49:39 +00:00
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return bounds.Location;
|
|
|
|
}
|
|
|
|
set
|
|
|
|
{
|
|
|
|
SetLocation((short)value.X, (short)value.Y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-01 12:44:38 +00:00
|
|
|
public Size Size
|
2009-06-02 15:49:39 +00:00
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return bounds.Size;
|
|
|
|
}
|
|
|
|
set
|
|
|
|
{
|
|
|
|
SetSize((short)value.Width, (short)value.Height);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public int Width
|
|
|
|
{
|
|
|
|
get { return Bounds.Width; }
|
2009-11-01 12:44:38 +00:00
|
|
|
set { Size = new Size(value, Height); }
|
2009-06-02 15:49:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public int Height
|
|
|
|
{
|
|
|
|
get { return Bounds.Height; }
|
2009-11-01 12:44:38 +00:00
|
|
|
set { Size = new Size(Width, value); }
|
2009-06-02 15:49:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public int X
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return bounds.X;
|
|
|
|
}
|
|
|
|
set
|
|
|
|
{
|
2009-11-01 12:44:38 +00:00
|
|
|
Location = new Point(value, Y);
|
2009-06-02 15:49:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public int Y
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return bounds.Y;
|
|
|
|
}
|
|
|
|
set
|
|
|
|
{
|
2009-11-01 12:44:38 +00:00
|
|
|
Location = new Point(X, value);
|
2009-06-02 15:49:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-01 12:44:38 +00:00
|
|
|
public Rectangle ClientRectangle
|
2009-06-02 15:49:39 +00:00
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return clientRectangle;
|
|
|
|
}
|
|
|
|
set
|
|
|
|
{
|
|
|
|
throw new NotImplementedException();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-01 12:44:38 +00:00
|
|
|
public Size ClientSize
|
2009-06-02 15:49:39 +00:00
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return clientRectangle.Size;
|
|
|
|
}
|
|
|
|
set
|
|
|
|
{
|
|
|
|
throw new NotImplementedException();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Close()
|
|
|
|
{
|
|
|
|
throw new NotImplementedException();
|
|
|
|
}
|
|
|
|
|
2009-08-17 09:34:15 +00:00
|
|
|
public WindowState WindowState
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
if (windowState == WindowState.Fullscreen)
|
|
|
|
return WindowState.Fullscreen;
|
|
|
|
|
|
|
|
if (Carbon.API.IsWindowCollapsed(window.WindowRef))
|
|
|
|
return WindowState.Minimized;
|
|
|
|
|
|
|
|
|
|
|
|
if (Carbon.API.IsWindowInStandardState(window.WindowRef))
|
|
|
|
{
|
|
|
|
return WindowState.Maximized;
|
|
|
|
}
|
|
|
|
|
|
|
|
return WindowState.Normal;
|
|
|
|
}
|
|
|
|
set
|
|
|
|
{
|
|
|
|
if (value == WindowState)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Debug.Print("Switching window state from {0} to {1}", WindowState, value);
|
|
|
|
|
|
|
|
if (WindowState == WindowState.Fullscreen)
|
|
|
|
{
|
|
|
|
UnsetFullscreen();
|
|
|
|
}
|
|
|
|
if (WindowState == WindowState.Minimized)
|
|
|
|
{
|
|
|
|
API.CollapseWindow(window.WindowRef, false);
|
|
|
|
}
|
2009-11-01 12:44:38 +00:00
|
|
|
CarbonPoint idealSize;
|
2009-08-17 09:34:15 +00:00
|
|
|
|
|
|
|
switch (value)
|
|
|
|
{
|
|
|
|
case WindowState.Fullscreen:
|
|
|
|
SetFullscreen();
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WindowState.Maximized:
|
|
|
|
// hack because mac os has no concept of maximized. Instead windows are "zoomed"
|
|
|
|
// meaning they are maximized up to their reported ideal size. So we report a
|
|
|
|
// large ideal size.
|
2009-11-01 12:44:38 +00:00
|
|
|
idealSize = new CarbonPoint(9000, 9000);
|
2009-08-17 09:34:15 +00:00
|
|
|
API.ZoomWindowIdeal(window.WindowRef, WindowPartCode.inZoomOut, ref idealSize);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WindowState.Normal:
|
|
|
|
if (WindowState == WindowState.Maximized)
|
|
|
|
{
|
2009-11-01 12:44:38 +00:00
|
|
|
idealSize = new CarbonPoint();
|
2009-08-17 09:34:15 +00:00
|
|
|
API.ZoomWindowIdeal(window.WindowRef, WindowPartCode.inZoomIn, ref idealSize);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WindowState.Minimized:
|
|
|
|
API.CollapseWindow(window.WindowRef, true);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
windowState = value;
|
|
|
|
|
|
|
|
if (WindowStateChanged != null)
|
|
|
|
WindowStateChanged(this, EventArgs.Empty);
|
|
|
|
|
|
|
|
OnResize();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public WindowBorder WindowBorder
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return windowBorder;
|
|
|
|
}
|
|
|
|
set
|
|
|
|
{
|
|
|
|
if (windowBorder != value)
|
|
|
|
{
|
|
|
|
windowBorder = value;
|
|
|
|
|
|
|
|
if (windowBorder == WindowBorder.Resizable)
|
|
|
|
{
|
|
|
|
API.ChangeWindowAttributes(window.WindowRef, WindowAttributes.Resizable | WindowAttributes.FullZoom,
|
|
|
|
WindowAttributes.NoAttributes);
|
|
|
|
}
|
|
|
|
else if (windowBorder == WindowBorder.Fixed)
|
|
|
|
{
|
|
|
|
API.ChangeWindowAttributes(window.WindowRef, WindowAttributes.NoAttributes,
|
|
|
|
WindowAttributes.Resizable | WindowAttributes.FullZoom);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (WindowBorderChanged != null)
|
|
|
|
WindowBorderChanged(this, EventArgs.Empty);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-02 15:49:39 +00:00
|
|
|
public event EventHandler<EventArgs> Idle;
|
|
|
|
|
|
|
|
public event EventHandler<EventArgs> Load;
|
|
|
|
|
|
|
|
public event EventHandler<EventArgs> Unload;
|
|
|
|
|
|
|
|
public event EventHandler<EventArgs> Move;
|
|
|
|
|
|
|
|
public event EventHandler<EventArgs> Resize;
|
|
|
|
|
|
|
|
public event EventHandler<CancelEventArgs> Closing;
|
|
|
|
|
|
|
|
public event EventHandler<EventArgs> Closed;
|
|
|
|
|
|
|
|
public event EventHandler<EventArgs> Disposed;
|
|
|
|
|
|
|
|
public event EventHandler<EventArgs> IconChanged;
|
|
|
|
|
|
|
|
public event EventHandler<EventArgs> TitleChanged;
|
|
|
|
|
|
|
|
public event EventHandler<EventArgs> ClientSizeChanged;
|
|
|
|
|
|
|
|
public event EventHandler<EventArgs> VisibleChanged;
|
|
|
|
|
|
|
|
public event EventHandler<EventArgs> WindowInfoChanged;
|
|
|
|
|
|
|
|
public event EventHandler<EventArgs> FocusedChanged;
|
|
|
|
|
2009-08-17 09:34:15 +00:00
|
|
|
public event EventHandler<EventArgs> WindowBorderChanged;
|
|
|
|
|
|
|
|
public event EventHandler<EventArgs> WindowStateChanged;
|
|
|
|
|
2009-07-19 17:49:51 +00:00
|
|
|
public event EventHandler<KeyPressEventArgs> KeyPress;
|
|
|
|
|
2009-10-27 23:57:44 +00:00
|
|
|
public event EventHandler<EventArgs> MouseEnter;
|
|
|
|
|
|
|
|
public event EventHandler<EventArgs> MouseLeave;
|
|
|
|
|
2009-06-02 15:49:39 +00:00
|
|
|
#endregion
|
2009-02-22 10:43:35 +00:00
|
|
|
}
|
|
|
|
}
|