diff --git a/Launcher2/Gui/PlatformDrawer.cs b/Launcher2/Gui/PlatformDrawer.cs
index ca2b38ffc..ae64ad76c 100644
--- a/Launcher2/Gui/PlatformDrawer.cs
+++ b/Launcher2/Gui/PlatformDrawer.cs
@@ -4,6 +4,7 @@ using ClassicalSharp;
using OpenTK.Platform;
using OpenTK.Platform.X11;
using OSX = OpenTK.Platform.MacOS.Carbon;
+using OSStatus = OpenTK.Platform.MacOS.OSStatus;
namespace Launcher2 {
@@ -19,7 +20,7 @@ namespace Launcher2 {
public sealed class WinPlatformDrawer : PlatformDrawer {
- Graphics g;
+ Graphics g;
public override void Init( IWindowInfo info ) {
g = Graphics.FromHwnd( info.WinHandle );
}
@@ -49,13 +50,38 @@ namespace Launcher2 {
}
public override void Draw( IWindowInfo info, Bitmap framebuffer ) {
- //g.DrawImage( framebuffer, 0, 0, framebuffer.Width, framebuffer.Height );
+
+ using( FastBitmap bmp = new FastBitmap( framebuffer, true ) ) {
+ IntPtr scan0 = bmp.Scan0;
+ int size = bmp.Width * bmp.Height * 4;
+
+ IntPtr colorSpace = OSX.API.CGColorSpaceCreateDeviceRGB();
+ IntPtr provider = OSX.API.CGDataProviderCreateWithData( IntPtr.Zero, scan0, size, IntPtr.Zero );
+ IntPtr image = OSX.API.CGImageCreate( bmp.Width, bmp.Height, 8, 8 * 4, bmp.Stride,
+ colorSpace, 4, provider, IntPtr.Zero, 0, 0 );
+ IntPtr context = IntPtr.Zero;
+ OSStatus err = OSX.API.QDBeginCGContext( windowPort, ref context );
+ OSX.API.CheckReturn( err );
+
+ OSX.HIRect rect = new OSX.HIRect();
+ rect.Origin.X = 0; rect.Origin.Y = 0;
+ rect.Size.X = bmp.Width; rect.Size.Y = bmp.Height;
+
+ OSX.API.CGContextDrawImage( context, rect, image );
+ OSX.API.CGContextSynchronize( context );
+ err = OSX.API.QDEndCGContext( windowPort, ref context );
+ OSX.API.CheckReturn( err );
+
+ OSX.API.CGImageRelease( image );
+ OSX.API.CGDataProviderRelease( provider );
+ OSX.API.CGColorSpaceRelease( colorSpace );
+ }
}
}
public sealed class X11PlatformDrawer : PlatformDrawer {
- IntPtr gc;
+ IntPtr gc;
public override void Init( IWindowInfo info ) {
gc = API.XCreateGC( API.DefaultDisplay, info.WinHandle, IntPtr.Zero, null );
}
diff --git a/OpenTK/OpenTK.csproj b/OpenTK/OpenTK.csproj
index a3a1fa415..7d7307066 100644
--- a/OpenTK/OpenTK.csproj
+++ b/OpenTK/OpenTK.csproj
@@ -92,7 +92,6 @@
-
diff --git a/OpenTK/Platform/MacOS/AglContext.cs b/OpenTK/Platform/MacOS/AglContext.cs
index c63592431..e86ca7d9f 100644
--- a/OpenTK/Platform/MacOS/AglContext.cs
+++ b/OpenTK/Platform/MacOS/AglContext.cs
@@ -106,15 +106,32 @@ namespace OpenTK.Platform.MacOS {
Update(carbonWindow);
MakeCurrent(carbonWindow);
+
Debug.Print("context: {0}", ContextHandle);
}
- private IntPtr GetQuartzDevice( CarbonWindowInfo carbonWindow ) {
- CarbonGLNative nativeWindow = carbonWindow.nativeWindow;
- return QuartzDisplayDeviceDriver.HandleTo( nativeWindow.TargetDisplayDevice );
+ private IntPtr GetQuartzDevice(CarbonWindowInfo carbonWindow)
+ {
+ IntPtr windowRef = carbonWindow.WindowRef;
+
+ if (!CarbonGLNative.WindowRefMap.ContainsKey(windowRef))
+ return IntPtr.Zero;
+
+ WeakReference nativeRef = CarbonGLNative.WindowRefMap[windowRef];
+ if (!nativeRef.IsAlive)
+ return IntPtr.Zero;
+
+ CarbonGLNative window = nativeRef.Target as CarbonGLNative;
+
+ if (window == null)
+ return IntPtr.Zero;
+
+ return QuartzDisplayDeviceDriver.HandleTo(window.TargetDisplayDevice);
+
}
- void SetDrawable(CarbonWindowInfo carbonWindow) {
+ void SetDrawable(CarbonWindowInfo carbonWindow)
+ {
IntPtr windowPort = API.GetWindowPort(carbonWindow.WindowRef);
//Debug.Print("Setting drawable for context {0} to window port: {1}", Handle.Handle, windowPort);
@@ -122,12 +139,14 @@ namespace OpenTK.Platform.MacOS {
Agl.CheckReturnValue( code, "aglSetDrawable" );
}
- public override void Update(IWindowInfo window) {
- CarbonWindowInfo winInfo = (CarbonWindowInfo)window;
+ public override void Update(IWindowInfo window)
+ {
+ CarbonWindowInfo carbonWindow = (CarbonWindowInfo)window;
- if (winInfo.goFullScreenHack) {
- winInfo.goFullScreenHack = false;
- CarbonGLNative wind = winInfo.nativeWindow;
+ if (carbonWindow.goFullScreenHack)
+ {
+ carbonWindow.goFullScreenHack = false;
+ CarbonGLNative wind = GetCarbonWindow(carbonWindow);
if (wind != null)
wind.SetFullscreen(this);
@@ -135,9 +154,11 @@ namespace OpenTK.Platform.MacOS {
Debug.Print("Could not find window!");
return;
- } else if (winInfo.goWindowedHack) {
- winInfo.goWindowedHack = false;
- CarbonGLNative wind = winInfo.nativeWindow;
+ }
+ else if (carbonWindow.goWindowedHack)
+ {
+ carbonWindow.goWindowedHack = false;
+ CarbonGLNative wind = GetCarbonWindow(carbonWindow);
if (wind != null)
wind.UnsetFullscreen(this);
@@ -149,13 +170,22 @@ namespace OpenTK.Platform.MacOS {
if (mIsFullscreen)
return;
- SetDrawable(winInfo);
+ SetDrawable(carbonWindow);
+
Agl.aglUpdateContext(ContextHandle);
}
+ private CarbonGLNative GetCarbonWindow(CarbonWindowInfo carbonWindow)
+ {
+ WeakReference r = CarbonGLNative.WindowRefMap[carbonWindow.WindowRef];
+ return r.IsAlive ? (CarbonGLNative)r.Target : null;
+ }
+
bool firstFullScreen = false;
- internal void SetFullScreen(CarbonWindowInfo info, out int width, out int height) {
- CarbonGLNative wind = info.nativeWindow;
+ internal void SetFullScreen(CarbonWindowInfo info, out int width, out int height)
+ {
+ CarbonGLNative wind = GetCarbonWindow(info);
+
Debug.Print("Switching to full screen {0}x{1} on context {2}",
wind.TargetDisplayDevice.Width, wind.TargetDisplayDevice.Height, ContextHandle);
@@ -175,10 +205,12 @@ namespace OpenTK.Platform.MacOS {
UnsetFullScreen(info);
SetFullScreen(info, out width, out height);
}
+
mIsFullscreen = true;
}
- internal void UnsetFullScreen(CarbonWindowInfo windowInfo) {
+ internal void UnsetFullScreen(CarbonWindowInfo windowInfo)
+ {
Debug.Print("Unsetting AGL fullscreen.");
byte code = Agl.aglSetDrawable(ContextHandle, IntPtr.Zero);
Agl.CheckReturnValue( code, "aglSetDrawable" );
@@ -192,6 +224,7 @@ namespace OpenTK.Platform.MacOS {
mIsFullscreen = false;
}
+
#region IGraphicsContext Members
public override void SwapBuffers() {
@@ -205,7 +238,7 @@ namespace OpenTK.Platform.MacOS {
}
public override bool IsCurrent {
- get { return ContextHandle == Agl.aglGetCurrentContext(); }
+ get { return ContextHandle == Agl.aglGetCurrentContext(); }
}
public override bool VSync {
@@ -281,4 +314,4 @@ namespace OpenTK.Platform.MacOS {
#endregion
}
-}
+}
\ No newline at end of file
diff --git a/OpenTK/Platform/MacOS/Application.cs b/OpenTK/Platform/MacOS/Application.cs
index e8c85c294..0943e7fa4 100644
--- a/OpenTK/Platform/MacOS/Application.cs
+++ b/OpenTK/Platform/MacOS/Application.cs
@@ -12,35 +12,41 @@ using System.Collections.Generic;
using System.IO;
using System.Text;
-namespace OpenTK.Platform.MacOS.Carbon {
-
- static class Application {
-
+namespace OpenTK.Platform.MacOS.Carbon
+{
+ static class Application
+ {
static bool mInitialized = false;
static IntPtr uppHandler;
- public static CarbonGLNative WindowEventHandler;
+ static CarbonGLNative eventHandler;
static int osMajor, osMinor, osBugfix;
- static Application() {
+ static Application()
+ {
Initialize();
}
- internal static void Initialize() {
+ internal static void Initialize()
+ {
if (mInitialized) return;
API.AcquireRootMenu();
+
ConnectEvents();
API.Gestalt(GestaltSelector.SystemVersionMajor, out osMajor);
API.Gestalt(GestaltSelector.SystemVersionMinor, out osMinor);
API.Gestalt(GestaltSelector.SystemVersionBugFix, out osBugfix);
+
Debug.Print("Running on Mac OS X {0}.{1}.{2}.", osMajor, osMinor, osBugfix);
TransformProcessToForeground();
}
- private static void TransformProcessToForeground() {
+ private static void TransformProcessToForeground()
+ {
Carbon.ProcessSerialNumber psn = new ProcessSerialNumber();
+
Debug.Print("Setting process to be foreground application.");
API.GetCurrentProcess(ref psn);
@@ -48,8 +54,16 @@ namespace OpenTK.Platform.MacOS.Carbon {
API.SetFrontProcess(ref psn);
}
- static void ConnectEvents() {
- EventTypeSpec[] eventTypes = new EventTypeSpec[] {
+ internal static CarbonGLNative WindowEventHandler
+ {
+ get { return eventHandler; }
+ set { eventHandler = value; }
+ }
+
+ static void ConnectEvents()
+ {
+ EventTypeSpec[] eventTypes = new EventTypeSpec[]
+ {
new EventTypeSpec(EventClass.Application, AppEventKind.AppActivated),
new EventTypeSpec(EventClass.Application, AppEventKind.AppDeactivated),
new EventTypeSpec(EventClass.Application, AppEventKind.AppQuit),
@@ -74,13 +88,17 @@ namespace OpenTK.Platform.MacOS.Carbon {
uppHandler = API.NewEventHandlerUPP(handler);
API.InstallApplicationEventHandler(
- uppHandler, eventTypes, IntPtr.Zero, IntPtr.Zero);
+ uppHandler, eventTypes, IntPtr.Zero, IntPtr.Zero);
+
mInitialized = true;
}
- static OSStatus EventHandler(IntPtr inCaller, IntPtr inEvent, IntPtr userData) {
- EventInfo evt = new EventInfo(inEvent);
- switch (evt.EventClass) {
+ static OSStatus EventHandler(IntPtr inCaller, IntPtr inEvent, IntPtr userData)
+ {
+ EventInfo evt = new EventInfo(inEvent);
+
+ switch (evt.EventClass)
+ {
case EventClass.AppleEvent:
// only event here is the apple event.
Debug.Print("Processing apple event.");
@@ -90,10 +108,12 @@ namespace OpenTK.Platform.MacOS.Carbon {
case EventClass.Keyboard:
case EventClass.Mouse:
if (WindowEventHandler != null)
+ {
return WindowEventHandler.DispatchEvent(inCaller, inEvent, evt, userData);
+ }
break;
}
return OSStatus.EventNotHandled;
}
}
-}
+}
\ No newline at end of file
diff --git a/OpenTK/Platform/MacOS/CarbonBindings/CarbonAPI.cs b/OpenTK/Platform/MacOS/CarbonBindings/CarbonAPI.cs
index 7b769e1f9..fe8258cd0 100644
--- a/OpenTK/Platform/MacOS/CarbonBindings/CarbonAPI.cs
+++ b/OpenTK/Platform/MacOS/CarbonBindings/CarbonAPI.cs
@@ -15,8 +15,8 @@ namespace OpenTK.Platform.MacOS.Carbon
[StructLayout(LayoutKind.Sequential)]
public struct CarbonPoint
{
- internal short V;
- internal short H;
+ public short V;
+ public short H;
public CarbonPoint(int x, int y)
{
@@ -33,26 +33,26 @@ namespace OpenTK.Platform.MacOS.Carbon
short bottom;
short right;
- internal Rect(short _left, short _top, short _width, short _height) {
+ public Rect(short _left, short _top, short _width, short _height) {
top = _top;
left = _left;
bottom = (short)(_top + _height);
right = (short)(_left + _width);
}
- internal short X {
+ public short X {
get { return left; }
}
- internal short Y {
+ public short Y {
get { return top; }
}
- internal short Width {
+ public short Width {
get { return (short)(right - left); }
}
- internal short Height {
+ public short Height {
get { return (short)(bottom - top); }
}
@@ -108,7 +108,7 @@ namespace OpenTK.Platform.MacOS.Carbon
}
[StructLayout(LayoutKind.Sequential)]
- internal struct HIRect {
+ public struct HIRect {
public HIPoint Origin;
public HIPoint Size;
@@ -120,6 +120,21 @@ namespace OpenTK.Platform.MacOS.Carbon
#endregion
+ public struct EventInfo {
+
+ public EventInfo(IntPtr eventRef) {
+ EventClass = API.GetEventClass(eventRef);
+ EventKind = API.GetEventKind(eventRef);
+ }
+
+ public uint EventKind;
+ public EventClass EventClass;
+
+ public override string ToString() {
+ return "Event: " + EventClass + ",kind: " + EventKind;
+ }
+ }
+
#region --- Types defined in CarbonEvents.h ---
enum EventAttributes : uint
@@ -132,34 +147,34 @@ namespace OpenTK.Platform.MacOS.Carbon
[StructLayout(LayoutKind.Sequential)]
public struct EventTypeSpec
{
- internal EventTypeSpec(EventClass evtClass, AppEventKind evtKind)
+ public EventTypeSpec(EventClass evtClass, AppEventKind evtKind)
{
this.EventClass = evtClass;
this.EventKind = (uint)evtKind;
}
- internal EventTypeSpec(EventClass evtClass, AppleEventKind appleKind)
+ public EventTypeSpec(EventClass evtClass, AppleEventKind appleKind)
{
this.EventClass = evtClass;
this.EventKind = (uint)appleKind;
}
- internal EventTypeSpec(EventClass evtClass, MouseEventKind evtKind)
+ public EventTypeSpec(EventClass evtClass, MouseEventKind evtKind)
{
this.EventClass = evtClass;
this.EventKind = (uint)evtKind;
}
- internal EventTypeSpec(EventClass evtClass, KeyboardEventKind evtKind)
+ public EventTypeSpec(EventClass evtClass, KeyboardEventKind evtKind)
{
this.EventClass = evtClass;
this.EventKind = (uint)evtKind;
}
- internal EventTypeSpec(EventClass evtClass, WindowEventKind evtKind)
+ public EventTypeSpec(EventClass evtClass, WindowEventKind evtKind)
{
this.EventClass = evtClass;
this.EventKind = (uint)evtKind;
}
- internal EventClass EventClass;
- internal uint EventKind;
+ public EventClass EventClass;
+ public uint EventKind;
}
public enum EventClass : int
@@ -182,7 +197,7 @@ namespace OpenTK.Platform.MacOS.Carbon
Menu = 0x6d656e75,
Window = 0x77696e64,
}
- internal enum WindowEventKind : int
+ public enum WindowEventKind : int
{
// window events
WindowUpdate = 1,
@@ -204,7 +219,7 @@ namespace OpenTK.Platform.MacOS.Carbon
WindowClose = 72,
WindowClosed = 73,
}
- internal enum MouseEventKind : int
+ public enum MouseEventKind : int
{
MouseDown = 1,
MouseUp = 2,
@@ -221,7 +236,7 @@ namespace OpenTK.Platform.MacOS.Carbon
Tertiary = 3,
}
- internal enum KeyboardEventKind : int
+ public enum KeyboardEventKind : int
{
// raw keyboard events
RawKeyDown = 1,
@@ -230,7 +245,7 @@ namespace OpenTK.Platform.MacOS.Carbon
RawKeyModifiersChanged = 4,
}
- internal enum AppEventKind : int
+ public enum AppEventKind : int
{
// application events
AppActivated = 1,
@@ -239,12 +254,12 @@ namespace OpenTK.Platform.MacOS.Carbon
AppLaunchNotification = 4,
}
- enum AppleEventKind : int
+ public enum AppleEventKind : int
{
AppleEvent = 1,
}
- internal enum EventParamName : int
+ public enum EventParamName : int
{
WindowRef = 0x77696e64, // typeWindowRef,
@@ -263,7 +278,7 @@ namespace OpenTK.Platform.MacOS.Carbon
KeyModifiers = 0x6b6d6f64, // typeUInt32
}
- internal enum EventParamType : int
+ public enum EventParamType : int
{
typeWindowRef = 0x77696e64,
@@ -283,7 +298,7 @@ namespace OpenTK.Platform.MacOS.Carbon
typeIEEE64BitFloatingPoint = 0x646f7562,
}
- internal enum EventMouseButton : int
+ public enum EventMouseButton : int
{
Primary = 0,
Secondary = 1,
@@ -354,7 +369,8 @@ namespace OpenTK.Platform.MacOS.Carbon
StandardFloating = (CloseBox | CollapseBox)
}
- public enum WindowPositionMethod : uint {
+ public enum WindowPositionMethod : uint
+ {
CenterOnMainScreen = 1,
CenterOnParentWindow = 2,
CenterOnParentWindowScreen = 3,
@@ -369,7 +385,8 @@ namespace OpenTK.Platform.MacOS.Carbon
public delegate OSStatus MacOSEventHandler(IntPtr inCaller, IntPtr inEvent, IntPtr userData);
- internal enum WindowPartCode : short {
+ public enum WindowPartCode : short
+ {
inDesk = 0,
inNoWindow = 0,
inMenuBar = 1,
@@ -400,11 +417,13 @@ namespace OpenTK.Platform.MacOS.Carbon
#endregion
#region --- Process Manager ---
- public enum ProcessApplicationTransformState : int {
+ public enum ProcessApplicationTransformState : int
+ {
kProcessTransformToForegroundApplication = 1,
}
- public struct ProcessSerialNumber {
+ public struct ProcessSerialNumber
+ {
public ulong high;
public ulong low;
}
@@ -422,8 +441,8 @@ namespace OpenTK.Platform.MacOS.Carbon
#region --- Carbon API Methods ---
- public static class API {
-
+ public class API
+ {
const string carbon = "/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon";
[DllImport(carbon)]
@@ -463,11 +482,12 @@ namespace OpenTK.Platform.MacOS.Carbon
[DllImport(carbon)]
static extern OSStatus GetWindowBounds(IntPtr window, WindowRegionCode regionCode, out Rect globalBounds);
- public static Rect GetWindowBounds(IntPtr window, WindowRegionCode regionCode) {
- Rect rect;
- OSStatus result = GetWindowBounds(window, regionCode, out rect);
- CheckReturn(result);
- return rect;
+ public static Rect GetWindowBounds(IntPtr window, WindowRegionCode regionCode)
+ {
+ Rect retval;
+ OSStatus error = GetWindowBounds(window, regionCode, out retval);
+ CheckReturn( error );
+ return retval;
}
//[DllImport(carbon)]
@@ -479,9 +499,11 @@ namespace OpenTK.Platform.MacOS.Carbon
[DllImport(carbon)]
static extern IntPtr GetEventDispatcherTarget();
- [DllImport(carbon)]
- static extern OSStatus ReceiveNextEvent(uint inNumTypes, IntPtr inList,
- double inTimeout, bool inPullEvent,
+ [DllImport(carbon,EntryPoint="ReceiveNextEvent")]
+ static extern OSStatus ReceiveNextEvent(uint inNumTypes,
+ IntPtr inList,
+ double inTimeout,
+ bool inPullEvent,
out IntPtr outEvent);
[DllImport(carbon)]
@@ -490,32 +512,56 @@ namespace OpenTK.Platform.MacOS.Carbon
[DllImport(carbon)]
static extern void ReleaseEvent(IntPtr theEvent);
+ public static void SendEvent(IntPtr theEvent)
+ {
+ IntPtr theTarget = GetEventDispatcherTarget();
+ SendEventToEventTarget(theEvent, theTarget);
+ }
+
// Processes events in the queue and then returns.
- public static void ProcessEvents() {
+ public static void ProcessEvents()
+ {
IntPtr theEvent;
IntPtr theTarget = GetEventDispatcherTarget();
- for (;;) {
+ for (;;)
+ {
OSStatus status = ReceiveNextEvent(0, IntPtr.Zero, 0.0, true, out theEvent);
if (status == OSStatus.EventLoopTimedOut)
break;
- if (status != OSStatus.NoError) {
+ if (status != OSStatus.NoError)
+ {
Debug.Print("Message Loop status: {0}", status);
break;
}
if (theEvent == IntPtr.Zero)
break;
- SendEventToEventTarget(theEvent, theTarget);
+ try
+ {
+ SendEventToEventTarget(theEvent, theTarget);
+ }
+ catch (System.ExecutionEngineException e)
+ {
+ Console.Error.WriteLine("ExecutionEngineException caught.");
+ Console.Error.WriteLine("theEvent: " + new EventInfo(theEvent).ToString());
+ Console.Error.WriteLine(e.Message);
+ Console.Error.WriteLine(e.StackTrace);
+ }
+
ReleaseEvent(theEvent);
}
}
-
+
+ #region --- Processing apple event ---
+
[StructLayout(LayoutKind.Sequential)]
- struct EventRecord {
+
+ struct EventRecord
+ {
public ushort what;
public uint message;
public uint when;
@@ -529,15 +575,33 @@ namespace OpenTK.Platform.MacOS.Carbon
[DllImport(carbon)]
static extern OSStatus AEProcessAppleEvent(ref EventRecord theEventRecord);
- public static void ProcessAppleEvent(IntPtr inEvent) {
+ static public void ProcessAppleEvent(IntPtr inEvent)
+ {
EventRecord record;
+
ConvertEventRefToEventRecord(inEvent, out record);
AEProcessAppleEvent(ref record);
}
-
+
#endregion
- #region --- Event handlers ---
+ #endregion
+ #region --- Getting Event Parameters ---
+
+ [DllImport(carbon)]
+ static extern OSStatus CreateEvent( IntPtr inAllocator,
+ EventClass inClassID, UInt32 kind, EventTime when,
+ EventAttributes flags, out IntPtr outEvent);
+
+ public 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(
@@ -549,7 +613,9 @@ namespace OpenTK.Platform.MacOS.Carbon
OSStatus result = API.GetEventParameter(inEvent,
EventParamName.KeyCode, EventParamType.typeUInt32, IntPtr.Zero,
sizeof(uint), IntPtr.Zero, (IntPtr)(void*)&code);
- CheckReturn(result);
+
+ if (result != OSStatus.NoError)
+ throw new MacOSException(result);
return (MacOSKeyCode)code;
}
@@ -558,7 +624,9 @@ namespace OpenTK.Platform.MacOS.Carbon
OSStatus result = API.GetEventParameter(inEvent,
EventParamName.KeyMacCharCode, EventParamType.typeChar, IntPtr.Zero,
Marshal.SizeOf(typeof(char)), IntPtr.Zero, (IntPtr)(void*)&code);
- CheckReturn(result);
+
+ if (result != OSStatus.NoError)
+ throw new MacOSException(result);
return code;
}
@@ -567,7 +635,9 @@ namespace OpenTK.Platform.MacOS.Carbon
OSStatus result = API.GetEventParameter(inEvent,
EventParamName.MouseButton, EventParamType.typeMouseButton, IntPtr.Zero,
sizeof(short), IntPtr.Zero, (IntPtr)(void*)&button);
- CheckReturn(result);
+
+ if (result != OSStatus.NoError)
+ throw new MacOSException(result);
return (MacOSMouseButton)button;
}
@@ -576,7 +646,9 @@ namespace OpenTK.Platform.MacOS.Carbon
OSStatus result = API.GetEventParameter(inEvent,
EventParamName.MouseWheelDelta, EventParamType.typeSInt32,
IntPtr.Zero, sizeof(int), IntPtr.Zero, (IntPtr)(void*)&delta);
- CheckReturn(result);
+
+ if (result != OSStatus.NoError)
+ throw new MacOSException(result);
return delta;
}
@@ -585,7 +657,7 @@ namespace OpenTK.Platform.MacOS.Carbon
OSStatus result = API.GetEventParameter(inEvent,
EventParamName.WindowMouseLocation, EventParamType.typeHIPoint, IntPtr.Zero,
Marshal.SizeOf(typeof(HIPoint)), IntPtr.Zero, (IntPtr)(void*)&point);
- //CheckReturn(result);
+
pt = point;
return result;
}
@@ -595,7 +667,7 @@ namespace OpenTK.Platform.MacOS.Carbon
OSStatus result = API.GetEventParameter(inEvent,
EventParamName.WindowRef, EventParamType.typeWindowRef, IntPtr.Zero,
sizeof(IntPtr), IntPtr.Zero, (IntPtr)(void*)&retval);
- //CheckReturn(result);
+
windowRef = retval;
return result;
}
@@ -605,7 +677,7 @@ namespace OpenTK.Platform.MacOS.Carbon
OSStatus result = API.GetEventParameter(inEvent,
EventParamName.MouseLocation, EventParamType.typeHIPoint, IntPtr.Zero,
Marshal.SizeOf(typeof(HIPoint)), IntPtr.Zero, (IntPtr)(void*)&point);
- //CheckReturn(result);
+
pt = point;
return result;
}
@@ -615,26 +687,33 @@ namespace OpenTK.Platform.MacOS.Carbon
OSStatus result = API.GetEventParameter(inEvent,
EventParamName.KeyModifiers, EventParamType.typeUInt32, IntPtr.Zero,
sizeof(uint), IntPtr.Zero, (IntPtr)(void*)&code);
- CheckReturn(result);
+
+ if (result != OSStatus.NoError)
+ throw new MacOSException(result);
return (MacOSKeyModifiers)code;
}
- [DllImport(carbon)]
- static extern OSStatus InstallEventHandler(
- IntPtr eventTargetRef, IntPtr handlerProc,
- int numtypes, EventTypeSpec[] typeList,
- IntPtr userData, IntPtr handlerRef);
+ #endregion
+ #region --- Event Handlers ---
- public static void InstallWindowEventHandler(IntPtr windowRef, IntPtr uppHandlerProc, EventTypeSpec[] eventTypes,
- IntPtr userData, IntPtr handlerRef) {
+ [DllImport(carbon)]
+ static extern OSStatus InstallEventHandler( IntPtr eventTargetRef, IntPtr handlerProc,
+ int numtypes, EventTypeSpec[] typeList,
+ IntPtr userData, IntPtr handlerRef);
+
+ public static void InstallWindowEventHandler(IntPtr windowRef, IntPtr uppHandlerProc,
+ EventTypeSpec[] eventTypes, IntPtr userData, IntPtr handlerRef)
+ {
IntPtr windowTarget = GetWindowEventTarget(windowRef);
- OSStatus error = InstallEventHandler(windowTarget, uppHandlerProc, eventTypes.Length,
- eventTypes, userData, handlerRef);
+ OSStatus error = InstallEventHandler(windowTarget, uppHandlerProc,
+ eventTypes.Length, eventTypes,
+ userData, handlerRef);
CheckReturn( error );
}
- public static void InstallApplicationEventHandler(IntPtr uppHandlerProc, EventTypeSpec[] eventTypes,
- IntPtr userData, IntPtr handlerRef) {
+ public static void InstallApplicationEventHandler(IntPtr uppHandlerProc,
+ EventTypeSpec[] eventTypes, IntPtr userData, IntPtr handlerRef)
+ {
OSStatus error = InstallEventHandler(GetApplicationEventTarget(), uppHandlerProc,
eventTypes.Length, eventTypes,
userData, handlerRef);
@@ -644,11 +723,17 @@ namespace OpenTK.Platform.MacOS.Carbon
[DllImport(carbon)]
public static extern OSStatus RemoveEventHandler(IntPtr inHandlerRef);
+ #endregion
+ #region --- GetWindowEventTarget ---
+
[DllImport(carbon)]
public static extern IntPtr GetWindowEventTarget(IntPtr window);
[DllImport(carbon)]
public static extern IntPtr GetApplicationEventTarget();
+
+ #endregion
+ #region --- UPP Event Handlers ---
[DllImport(carbon)]
public static extern IntPtr NewEventHandlerUPP(MacOSEventHandler handler);
@@ -672,24 +757,50 @@ namespace OpenTK.Platform.MacOS.Carbon
[DllImport(carbon)]
public extern static IntPtr CGColorSpaceCreateDeviceRGB();
[DllImport(carbon)]
- public extern static IntPtr CGDataProviderCreateWithData(IntPtr info, IntPtr[] data, int size, IntPtr releasefunc);
+ public extern static IntPtr CGDataProviderCreateWithData(IntPtr info, IntPtr data, int size, IntPtr releasefunc);
[DllImport(carbon)]
- public extern static IntPtr CGImageCreate(int width, int height, int bitsPerComponent, int bitsPerPixel, int bytesPerRow, IntPtr colorspace, uint bitmapInfo, IntPtr provider, IntPtr decode, int shouldInterpolate, int intent);
+ public extern static IntPtr CGImageCreate(int width, int height, int bitsPerComponent, int bitsPerPixel, int bytesPerRow, IntPtr colorspace,
+ uint bitmapInfo, IntPtr provider, IntPtr decode, int shouldInterpolate, int intent);
[DllImport(carbon)]
public extern static void SetApplicationDockTileImage(IntPtr imageRef);
[DllImport(carbon)]
public extern static void RestoreApplicationDockTileImage();
-
+ [DllImport(carbon)]
+ public extern static void CGImageRelease(IntPtr image);
+ [DllImport(carbon)]
+ public extern static void CGDataProviderRelease(IntPtr provider);
+ [DllImport(carbon)]
+ public extern static void CGColorSpaceRelease(IntPtr space);
+ [DllImport(carbon)]
+ public extern static void CGContextDrawImage( IntPtr context, HIRect rect, IntPtr image );
+ [DllImport(carbon)]
+ public extern static void CGContextSynchronize( IntPtr context );
+ [DllImport(carbon)]
+ public extern static OSStatus QDBeginCGContext( IntPtr port, ref IntPtr context );
+ [DllImport(carbon)]
+ public extern static OSStatus QDEndCGContext( IntPtr port, ref IntPtr context );
#endregion
+ [DllImport(carbon)]
+ public static extern OSStatus ActivateWindow (IntPtr inWindow, bool inActivate);
+
+ [DllImport(carbon)]
+ public static extern void RunApplicationEventLoop();
+
+ [DllImport(carbon)]
+ public static extern void QuitApplicationEventLoop();
+
#region --- SetWindowTitle ---
[DllImport(carbon)]
static extern void SetWindowTitleWithCFString(IntPtr windowRef, IntPtr title);
- public static void SetWindowTitle(IntPtr windowRef, string title) {
+ public static void SetWindowTitle(IntPtr windowRef, string title)
+ {
IntPtr str = __CFStringMakeConstantString(title);
+
Debug.Print("Setting window title: {0}, CFstring : {1}, Text : {2}", windowRef, str, title);
+
SetWindowTitleWithCFString(windowRef, str);
// Apparently releasing this reference to the CFConstantString here
@@ -712,30 +823,36 @@ namespace OpenTK.Platform.MacOS.Carbon
[DllImport(carbon)]
public static extern IntPtr GetWindowPort(IntPtr windowRef);
+
+ #region --- Menus ---
[DllImport(carbon)]
public static extern IntPtr AcquireRootMenu();
+
+ #endregion
+
[DllImport(carbon)]
public static extern bool IsWindowCollapsed(IntPtr windowRef);
[DllImport(carbon)]
public static extern OSStatus CollapseWindow(IntPtr windowRef, bool collapse);
+
+ public static void CheckReturn(OSStatus error ) {
+ if( error != OSStatus.NoError )
+ throw new MacOSException( error );
+ }
[DllImport(carbon, EntryPoint="IsWindowInStandardState")]
static extern bool _IsWindowInStandardState(IntPtr windowRef, IntPtr inIdealSize, IntPtr outIdealStandardState);
- public static bool IsWindowInStandardState(IntPtr windowRef) {
+ public static bool IsWindowInStandardState(IntPtr windowRef)
+ {
return _IsWindowInStandardState(windowRef, IntPtr.Zero, IntPtr.Zero);
}
[DllImport(carbon)]
public unsafe static extern OSStatus ZoomWindowIdeal(IntPtr windowRef, short inPartCode, ref CarbonPoint toIdealSize);
-
- public static void CheckReturn( OSStatus status ) {
- if( status != OSStatus.NoError )
- throw new MacOSException( status );
- }
[DllImport(carbon)]
public unsafe static extern OSStatus DMGetGDeviceByDisplayID(
@@ -792,8 +909,13 @@ namespace OpenTK.Platform.MacOS.Carbon
#endregion
const string gestaltlib = "/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon";
+
+
[DllImport(gestaltlib)]
public static extern OSStatus Gestalt(GestaltSelector selector, out int response);
}
+
#endregion
-}
\ No newline at end of file
+
+}
+
diff --git a/OpenTK/Platform/MacOS/CarbonGLNative.cs b/OpenTK/Platform/MacOS/CarbonGLNative.cs
index ddaff39bf..bb3a825a6 100644
--- a/OpenTK/Platform/MacOS/CarbonGLNative.cs
+++ b/OpenTK/Platform/MacOS/CarbonGLNative.cs
@@ -26,15 +26,17 @@
#endregion
using System;
+using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
-using OpenTK.Input;
+using OpenTK.Graphics;
using OpenTK.Platform.MacOS.Carbon;
+using OpenTK.Input;
-namespace OpenTK.Platform.MacOS {
-
- class CarbonGLNative : INativeWindow {
-
+namespace OpenTK.Platform.MacOS
+{
+ class CarbonGLNative : INativeWindow
+ {
CarbonWindowInfo window;
static MacOSKeyMap Keymap = new MacOSKeyMap();
IntPtr uppHandler;
@@ -42,88 +44,111 @@ namespace OpenTK.Platform.MacOS {
string title = "OpenTK Window";
Rectangle bounds, clientRectangle;
Rectangle windowedBounds;
- bool isDisposed = false;
- bool exists = true;
- DisplayDevice displayDevice;
+ bool mIsDisposed = false;
+ bool mExists = true;
+ DisplayDevice mDisplayDevice;
- WindowPositionMethod positionMethod = WindowPositionMethod.CenterOnMainScreen;
- int titlebarHeight;
+ WindowPositionMethod mPositionMethod = WindowPositionMethod.CenterOnMainScreen;
+ int mTitlebarHeight;
private WindowState windowState = WindowState.Normal;
+ static Dictionary mWindows = new Dictionary();
+ KeyPressEventArgs mKeyPressArgs = new KeyPressEventArgs();
+ bool mMouseIn = false;
+ bool mIsActive = false;
+ Icon mIcon;
- KeyPressEventArgs keyPressArgs = new KeyPressEventArgs();
- bool mouseIn = false, isActive = false;
- Icon icon;
- internal DisplayDevice TargetDisplayDevice { get { return displayDevice; } }
+ static internal Dictionary WindowRefMap { get { return mWindows; } }
+ internal DisplayDevice TargetDisplayDevice { get { return mDisplayDevice; } }
static CarbonGLNative() {
Application.Initialize();
}
-
- public CarbonGLNative(int x, int y, int width, int height, string title,
- GameWindowFlags options, DisplayDevice device) {
+
+ public CarbonGLNative(int x, int y, int width, int height, string title, GameWindowFlags options, DisplayDevice device)
+ {
this.title = title;
CreateNativeWindow(WindowClass.Document,
WindowAttributes.StandardDocument | WindowAttributes.StandardHandler |
WindowAttributes.InWindowMenu | WindowAttributes.LiveResize,
new Rect((short)x, (short)y, (short)width, (short)height));
- displayDevice = device;
+
+ mDisplayDevice = device;
}
- public void Dispose() {
+ #region IDisposable
+
+ public void Dispose()
+ {
Dispose(true);
GC.SuppressFinalize(this);
}
- protected virtual void Dispose(bool disposing) {
- if (isDisposed)
+ protected virtual void Dispose(bool disposing)
+ {
+ if (mIsDisposed)
return;
Debug.Print("Disposing of CarbonGLNative window.");
- API.DisposeWindow(window.WindowRef);
- isDisposed = true;
- exists = false;
- if (disposing) {
+ API.DisposeWindow(window.WindowRef);
+
+ mIsDisposed = true;
+ mExists = false;
+
+ if (disposing)
+ {
+ mWindows.Remove(window.WindowRef);
+
window.Dispose();
window = null;
}
DisposeUPP();
}
- ~CarbonGLNative() {
+ ~CarbonGLNative()
+ {
Dispose(false);
}
- void DisposeUPP() {
- if (uppHandler != IntPtr.Zero) {
- API.RemoveEventHandler(uppHandler);
- API.DisposeEventHandlerUPP(uppHandler);
+ #endregion
+
+ #region Private Members
+
+ void DisposeUPP()
+ {
+ 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...");
+
IntPtr windowRef;
OSStatus err = API.CreateNewWindow(@class, attrib, ref r, out windowRef);
- Debug.Print("Created Window: {0}", windowRef);
- API.CheckReturn(err);
-
+ API.CheckReturn( err );
+ Debug.Print( "Created window " + windowRef );
API.SetWindowTitle(windowRef, title);
- window = new CarbonWindowInfo(windowRef, this);
+
+ window = new CarbonWindowInfo(windowRef, true);
SetLocation(r.X, r.Y);
SetSize(r.Width, r.Height);
-
+ mWindows.Add(windowRef, new WeakReference(this));
LoadSize();
- Rect titleSize = API.GetWindowBounds(window.WindowRef, WindowRegionCode.TitleBarRegion);
- titlebarHeight = titleSize.Height;
+ Rect titleSize = API.GetWindowBounds(window.WindowRef, WindowRegionCode.TitleBarRegion);
+ mTitlebarHeight = titleSize.Height;
Debug.Print("Titlebar size: {0}", titleSize);
ConnectEvents();
Debug.Print("Attached window events.");
}
- void ConnectEvents() {
+ void ConnectEvents()
+ {
EventTypeSpec[] eventTypes = new EventTypeSpec[]
{
new EventTypeSpec(EventClass.Window, WindowEventKind.WindowClose),
@@ -146,9 +171,8 @@ namespace OpenTK.Platform.MacOS {
//new EventTypeSpec(EventClass.Keyboard, KeyboardEventKind.RawKeyModifiersChanged),
};
- uppHandler = API.NewEventHandlerUPP(EventHandler);
- // TODO: not sure if we need this.
- GC.KeepAlive( this ); // don't want to dispose the window as we need to keep the event handler open.
+ MacOSEventHandler handler = EventHandler;
+ uppHandler = API.NewEventHandlerUPP(handler);
API.InstallWindowEventHandler(window.WindowRef, uppHandler, eventTypes, window.WindowRef, IntPtr.Zero);
Application.WindowEventHandler = this;
}
@@ -159,7 +183,7 @@ namespace OpenTK.Platform.MacOS {
void Show() {
API.ShowWindow(window.WindowRef);
- API.RepositionWindow(window.WindowRef, IntPtr.Zero, positionMethod);
+ API.RepositionWindow(window.WindowRef, IntPtr.Zero, mPositionMethod);
API.SelectWindow(window.WindowRef);
}
@@ -177,7 +201,7 @@ namespace OpenTK.Platform.MacOS {
Debug.Print("New Size: {0}, {1}", Width, Height);
// TODO: if we go full screen we need to make this use the device specified.
- bounds = displayDevice.Bounds;
+ bounds = mDisplayDevice.Bounds;
windowState = WindowState.Fullscreen;
}
@@ -186,57 +210,82 @@ namespace OpenTK.Platform.MacOS {
Debug.Print("Telling Carbon to reset window state to " + windowState.ToString());
SetCarbonWindowState();
+
SetSize((short)windowedBounds.Width, (short)windowedBounds.Height);
}
- internal OSStatus DispatchEvent( IntPtr inCaller, IntPtr inEvent, EventInfo evt, IntPtr userData ) {
- switch (evt.EventClass) {
+ 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 OSStatus EventHandler( IntPtr inCaller, IntPtr inEvent, IntPtr userData ) {
+ protected static OSStatus EventHandler(IntPtr inCaller, IntPtr inEvent, IntPtr userData)
+ {
// bail out if the window passed in is not actually our window.
- if( window == null || userData != window.WindowRef )
+ // I think this happens if using winforms with a GameWindow sometimes.
+ if (!mWindows.ContainsKey(userData))
return OSStatus.EventNotHandled;
-
+
+ WeakReference reference = mWindows[userData];
+
+ // bail out if the CarbonGLNative window has been garbage collected.
+ if (!reference.IsAlive) {
+ mWindows.Remove(userData);
+ return OSStatus.EventNotHandled;
+ }
+
+ CarbonGLNative window = (CarbonGLNative)reference.Target;
+ //Debug.Print("Processing {0} event for {1}.", evt, window.window);
+ if (window == null) {
+ Debug.Print("Window for event not found.");
+ return OSStatus.EventNotHandled;
+ }
EventInfo evt = new EventInfo(inEvent);
- return DispatchEvent( inCaller, inEvent, evt, userData );
+ return window.DispatchEvent(inCaller, inEvent, evt, userData);
}
- private OSStatus ProcessKeyboardEvent( IntPtr inCaller, IntPtr inEvent, EventInfo evt, IntPtr userData ) {
+ private OSStatus ProcessKeyboardEvent(IntPtr inCaller, IntPtr inEvent, EventInfo evt, IntPtr userData) {
MacOSKeyCode code = (MacOSKeyCode)0;
char charCode = '\0';
//Debug.Print("Processing keyboard event {0}", evt.KeyboardEventKind);
- switch ((KeyboardEventKind)evt.EventKind) {
+ switch ((KeyboardEventKind)evt.EventKind)
+ {
case KeyboardEventKind.RawKeyDown:
case KeyboardEventKind.RawKeyRepeat:
case KeyboardEventKind.RawKeyUp:
GetCharCodes(inEvent, out code, out charCode);
- keyPressArgs.KeyChar = charCode;
+ mKeyPressArgs.KeyChar = charCode;
break;
- }
+ }
+
if( !Keymap.ContainsKey( code ) ) {
- Debug.Print( "{0} is not mapped, ignoring" );
+ Debug.Print( "{0} not mapped, ignoring press.", code );
return OSStatus.NoError;
}
- switch ((KeyboardEventKind)evt.EventKind) {
+ switch ((KeyboardEventKind)evt.EventKind)
+ {
case KeyboardEventKind.RawKeyRepeat:
keyboard.KeyRepeat = true;
goto case KeyboardEventKind.RawKeyDown;
case KeyboardEventKind.RawKeyDown:
- OnKeyPress(keyPressArgs);
+ OnKeyPress(mKeyPressArgs);
keyboard[Keymap[code]] = true;
return OSStatus.NoError;
@@ -254,7 +303,8 @@ namespace OpenTK.Platform.MacOS {
}
private OSStatus ProcessWindowEvent(IntPtr inCaller, IntPtr inEvent, EventInfo evt, IntPtr userData) {
- switch ((WindowEventKind)evt.EventKind) {
+ switch ((WindowEventKind)evt.EventKind)
+ {
case WindowEventKind.WindowClose:
CancelEventArgs cancel = new CancelEventArgs();
OnClosing(cancel);
@@ -265,7 +315,7 @@ namespace OpenTK.Platform.MacOS {
return OSStatus.EventNotHandled;
case WindowEventKind.WindowClosed:
- exists = false;
+ mExists = false;
OnClosed();
return OSStatus.NoError;
@@ -290,34 +340,40 @@ namespace OpenTK.Platform.MacOS {
return OSStatus.EventNotHandled;
default:
- Debug.Print("unhandled {0}", evt);
+ Debug.Print("{0}", evt);
+
return OSStatus.EventNotHandled;
}
}
-
- protected OSStatus ProcessMouseEvent(IntPtr inCaller, IntPtr inEvent, EventInfo evt, IntPtr userData) {
+ OSStatus ProcessMouseEvent(IntPtr inCaller, IntPtr inEvent, EventInfo evt, IntPtr userData) {
MacOSMouseButton button;
HIPoint pt = new HIPoint();
HIPoint screenLoc = new HIPoint();
OSStatus err = API.GetEventMouseLocation(inEvent, out screenLoc);
- if (this.windowState == WindowState.Fullscreen) {
+ if (this.windowState == WindowState.Fullscreen)
+ {
pt = screenLoc;
- } else {
+ }
+ else
+ {
err = API.GetEventWindowMouseLocation(inEvent, out pt);
}
- if (err != OSStatus.NoError) {
+ if (err != OSStatus.NoError)
+ {
// this error comes up from the application event handler.
- if (err != OSStatus.EventParameterNotFound) {
+ if (err != OSStatus.EventParameterNotFound)
+ {
throw new MacOSException(err);
}
}
Point mousePosInClient = new Point((int)pt.X, (int)pt.Y);
- if (this.windowState != WindowState.Fullscreen) {
- mousePosInClient.Y -= titlebarHeight;
+ if (this.windowState != WindowState.Fullscreen)
+ {
+ mousePosInClient.Y -= mTitlebarHeight;
}
// check for enter/leave events
@@ -325,7 +381,8 @@ namespace OpenTK.Platform.MacOS {
API.GetEventWindowRef(inEvent, out thisEventWindow);
CheckEnterLeaveEvents(thisEventWindow, mousePosInClient);
- switch ((MouseEventKind)evt.EventKind) {
+ switch ((MouseEventKind)evt.EventKind)
+ {
case MouseEventKind.MouseDown:
button = API.GetEventMouseButton(inEvent);
@@ -392,12 +449,13 @@ namespace OpenTK.Platform.MacOS {
return OSStatus.EventNotHandled;
default:
- Debug.Print("unhandled {0}", evt);
+ Debug.Print("{0}", evt);
return OSStatus.EventNotHandled;
}
}
- private void CheckEnterLeaveEvents(IntPtr eventWindowRef, Point pt) {
+ private void CheckEnterLeaveEvents(IntPtr eventWindowRef, Point pt)
+ {
if (window == null)
return;
@@ -406,21 +464,25 @@ namespace OpenTK.Platform.MacOS {
if (pt.Y < 0)
thisIn = false;
- if (thisIn == mouseIn) return;
- mouseIn = thisIn;
+ if (thisIn != mMouseIn)
+ {
+ mMouseIn = thisIn;
- if (mouseIn)
- OnMouseEnter();
- else
- OnMouseLeave();
+ if (mMouseIn)
+ OnMouseEnter();
+ else
+ OnMouseLeave();
+ }
}
- 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);
charCode = API.GetEventKeyboardChar(inEvent);
}
- private void ProcessModifierKey(IntPtr inEvent) {
+ private void ProcessModifierKey(IntPtr inEvent)
+ {
MacOSKeyModifiers modifiers = API.GetEventKeyModifiers(inEvent);
bool caps = (modifiers & MacOSKeyModifiers.CapsLock) != 0;
@@ -445,6 +507,11 @@ namespace OpenTK.Platform.MacOS {
if (keyboard[Key.CapsLock] ^ caps)
keyboard[Key.CapsLock] = caps;
+
+ }
+
+ Rect GetRegion() {
+ return API.GetWindowBounds(window.WindowRef, WindowRegionCode.ContentRegion);
}
void SetLocation(short x, short y) {
@@ -492,43 +559,53 @@ namespace OpenTK.Platform.MacOS {
clientRectangle = new Rectangle(0, 0, r.Width, r.Height);
}
+ #endregion
+
#region INativeWindow Members
- public void ProcessEvents() {
+ public void ProcessEvents()
+ {
API.ProcessEvents();
}
- public Point PointToClient(Point point) {
+ public Point PointToClient(Point point)
+ {
IntPtr handle = window.WindowRef;
+
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);
}
-
- public Point PointToScreen(Point point) {
+ public Point PointToScreen(Point point)
+ {
IntPtr handle = window.WindowRef;
+
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);
}
- public bool Exists {
- get { return exists; }
+ public bool Exists
+ {
+ get { return mExists; }
}
- public IWindowInfo WindowInfo {
+ public IWindowInfo WindowInfo
+ {
get { return window; }
}
public Icon Icon {
- get { return icon; }
+ get { return mIcon; }
set {
- icon = value;
SetIcon(value);
}
}
- private void SetIcon(Icon icon) {
+ private unsafe void SetIcon(Icon icon)
+ {
// The code for this function was adapted from Mono's
// XplatUICarbon implementation, written by Geoff Norton
// http://anonsvn.mono-project.com/viewvc/trunk/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUICarbon.cs?view=markup&pathrev=136932
@@ -572,37 +649,53 @@ namespace OpenTK.Platform.MacOS {
}
}
- IntPtr provider = API.CGDataProviderCreateWithData(IntPtr.Zero, data, size * 4, IntPtr.Zero);
- IntPtr image = API.CGImageCreate(128, 128, 8, 32, 4 * 128, API.CGColorSpaceCreateDeviceRGB(), 4, provider, IntPtr.Zero, 0, 0);
- API.SetApplicationDockTileImage(image);
+ fixed( IntPtr* ptr = data ) {
+ IntPtr provider = API.CGDataProviderCreateWithData(IntPtr.Zero, (IntPtr)(void*)ptr, size * 4, IntPtr.Zero);
+ IntPtr image = API.CGImageCreate(128, 128, 8, 32, 4 * 128, API.CGColorSpaceCreateDeviceRGB(), 4, provider, IntPtr.Zero, 0, 0);
+ API.SetApplicationDockTileImage(image);
+ }
}
}
- public string Title {
- get { return title; }
- set {
+ public string Title
+ {
+ get
+ {
+ return title;
+ }
+ set
+ {
API.SetWindowTitle(window.WindowRef, value);
title = value;
}
}
- public bool Visible {
+ public bool Visible
+ {
get { return API.IsWindowVisible(window.WindowRef); }
- set {
- if (value && !Visible)
+ set
+ {
+ if (value && Visible == false)
Show();
else
Hide();
}
}
- public bool Focused {
- get { return isActive; }
+ public bool Focused
+ {
+ get { return this.mIsActive; }
}
- public Rectangle Bounds {
- get { return bounds; }
- set {
+ public Rectangle Bounds
+ {
+ get
+ {
+
+ return bounds;
+ }
+ set
+ {
Location = value.Location;
Size = value.Size;
}
@@ -618,12 +711,14 @@ namespace OpenTK.Platform.MacOS {
set { SetSize((short)value.Width, (short)value.Height); }
}
- public int Width {
+ public int Width
+ {
get { return ClientRectangle.Width; }
set { SetClientSize((short)value, (short)Height); }
}
- public int Height {
+ public int Height
+ {
get { return ClientRectangle.Height; }
set { SetClientSize((short)Width, (short)value); }
}
@@ -638,24 +733,35 @@ namespace OpenTK.Platform.MacOS {
set { Location = new Point(X, value); }
}
- public Rectangle ClientRectangle {
- get { return clientRectangle; }
- set {
+ public Rectangle ClientRectangle
+ {
+ get
+ {
+ return clientRectangle;
+ }
+ set
+ {
// just set the size, and ignore the location value.
// this is the behavior of the Windows WinGLNative.
ClientSize = value.Size;
}
}
- public Size ClientSize {
- get { return clientRectangle.Size; }
- set {
+ public Size ClientSize
+ {
+ get
+ {
+ return clientRectangle.Size;
+ }
+ set
+ {
API.SizeWindow(window.WindowRef, (short)value.Width, (short)value.Height, true);
OnResize();
}
}
- public void Close() {
+ public void Close()
+ {
CancelEventArgs e = new CancelEventArgs();
OnClosing(e);
@@ -663,11 +769,14 @@ namespace OpenTK.Platform.MacOS {
return;
OnClosed();
+
Dispose();
}
- public WindowState WindowState {
- get {
+ public WindowState WindowState
+ {
+ get
+ {
if (windowState == WindowState.Fullscreen)
return WindowState.Fullscreen;
@@ -675,11 +784,14 @@ namespace OpenTK.Platform.MacOS {
return WindowState.Minimized;
if (Carbon.API.IsWindowInStandardState(window.WindowRef))
+ {
return WindowState.Maximized;
+ }
return WindowState.Normal;
}
- set {
+ set
+ {
if (value == WindowState)
return;
@@ -688,7 +800,8 @@ namespace OpenTK.Platform.MacOS {
windowState = value;
- if (oldState == WindowState.Fullscreen) {
+ if (oldState == WindowState.Fullscreen)
+ {
window.goWindowedHack = true;
// when returning from full screen, wait until the context is updated
@@ -708,8 +821,9 @@ namespace OpenTK.Platform.MacOS {
private void SetCarbonWindowState() {
CarbonPoint idealSize;
OSStatus err;
-
- switch (windowState) {
+
+ switch (windowState)
+ {
case WindowState.Fullscreen:
window.goFullScreenHack = true;
break;
@@ -724,7 +838,8 @@ namespace OpenTK.Platform.MacOS {
break;
case WindowState.Normal:
- if (WindowState == WindowState.Maximized) {
+ if (WindowState == WindowState.Maximized)
+ {
idealSize = new CarbonPoint();
err = API.ZoomWindowIdeal(window.WindowRef, (short)WindowPartCode.inZoomIn, ref idealSize);
API.CheckReturn( err );
@@ -736,53 +851,66 @@ namespace OpenTK.Platform.MacOS {
API.CheckReturn( err );
break;
}
-
+
OnWindowStateChanged();
OnResize();
}
- private void OnKeyPress(KeyPressEventArgs keyPressArgs) {
+ #region --- Event wrappers ---
+
+ private void OnKeyPress(KeyPressEventArgs keyPressArgs)
+ {
if (KeyPress != null)
KeyPress(this, keyPressArgs);
}
- private void OnWindowStateChanged() {
+
+ private void OnWindowStateChanged()
+ {
if (WindowStateChanged != null)
WindowStateChanged(this, EventArgs.Empty);
}
- protected virtual void OnClosing(CancelEventArgs e) {
+ protected virtual void OnClosing(CancelEventArgs e)
+ {
if (Closing != null)
Closing(this, e);
}
- protected virtual void OnClosed() {
+ protected virtual void OnClosed()
+ {
if (Closed != null)
Closed(this, EventArgs.Empty);
}
- private void OnMouseLeave() {
+
+ private void OnMouseLeave()
+ {
if (MouseLeave != null)
MouseLeave(this, EventArgs.Empty);
}
- private void OnMouseEnter() {
+ private void OnMouseEnter()
+ {
if (MouseEnter != null)
MouseEnter(this, EventArgs.Empty);
}
- private void OnActivate() {
- isActive = true;
+ private void OnActivate()
+ {
+ mIsActive = true;
if (FocusedChanged != null)
FocusedChanged(this, EventArgs.Empty);
}
-
- private void OnDeactivate() {
- isActive = false;
+ private void OnDeactivate()
+ {
+ mIsActive = false;
if (FocusedChanged != null)
FocusedChanged(this, EventArgs.Empty);
}
+ #endregion
+
public event EventHandler Load;
public event EventHandler Unload;
public event EventHandler Move;
@@ -799,9 +927,11 @@ namespace OpenTK.Platform.MacOS {
public event EventHandler KeyPress;
public event EventHandler MouseEnter;
public event EventHandler MouseLeave;
-
+
#endregion
+ #region IInputDriver Members
+
KeyboardDevice keyboard = new KeyboardDevice();
MouseDevice mouse = new MouseDevice();
@@ -840,5 +970,7 @@ namespace OpenTK.Platform.MacOS {
CG.CGDisplayHideCursor(CG.CGMainDisplayID());
}
}
+
+ #endregion
}
-}
+}
\ No newline at end of file
diff --git a/OpenTK/Platform/MacOS/CarbonWindowInfo.cs b/OpenTK/Platform/MacOS/CarbonWindowInfo.cs
index 0c83f6e28..02dcb7393 100644
--- a/OpenTK/Platform/MacOS/CarbonWindowInfo.cs
+++ b/OpenTK/Platform/MacOS/CarbonWindowInfo.cs
@@ -26,33 +26,86 @@
#endregion
using System;
+using System.Collections.Generic;
+using System.Text;
-namespace OpenTK.Platform.MacOS {
-
+namespace OpenTK.Platform.MacOS
+{
/// \internal
- /// Describes a Carbon window.
- sealed class CarbonWindowInfo : IWindowInfo {
-
- public IntPtr WindowRef;
+ ///
+ /// Describes a Carbon window.
+ ///
+ sealed class CarbonWindowInfo : IWindowInfo
+ {
+ IntPtr windowRef;
+ bool ownHandle = false;
bool disposed = false;
internal bool goFullScreenHack = false;
internal bool goWindowedHack = false;
- internal CarbonGLNative nativeWindow;
- public CarbonWindowInfo( IntPtr windowRef, CarbonGLNative nativeWindow ) {
- this.WindowRef = windowRef;
- this.nativeWindow = nativeWindow;
+ #region Constructors
+
+ ///
+ /// Constructs a new instance with the specified parameters.
+ ///
+ /// A valid Carbon window reference.
+ ///
+ public CarbonWindowInfo(IntPtr windowRef, bool ownHandle)
+ {
+ this.windowRef = windowRef;
+ this.ownHandle = ownHandle;
}
- public override string ToString() {
- return String.Format("CarbonWindowInfo: Handle {0}", WindowRef);
+ #endregion
+
+ #region Public Members
+
+ ///
+ /// Gets the window reference for this instance.
+ ///
+ internal IntPtr WindowRef
+ {
+ get { return this.windowRef; }
}
+ /// Returns a System.String that represents the current window.
+ /// A System.String that represents the current window.
+ public override string ToString()
+ {
+ return String.Format("MacOS.CarbonWindowInfo: Handle {0}", WindowRef);
+ }
+
+ #endregion
+
+ // TODO: I have no idea if this is right.
public IntPtr WinHandle {
- get { return WindowRef; }
+ get { return windowRef; }
}
+ #region IDisposable Members
+
public void Dispose() {
+ Dispose(true);
}
+
+ void Dispose(bool disposing) {
+ if (disposed)
+ return;
+
+ if (ownHandle)
+ {
+ Debug.Print("Disposing window {0}.", windowRef);
+ Carbon.API.DisposeWindow(this.windowRef);
+ windowRef = IntPtr.Zero;
+ }
+
+ disposed = true;
+ }
+
+ ~CarbonWindowInfo() {
+ Dispose(false);
+ }
+
+ #endregion
}
-}
+}
\ No newline at end of file
diff --git a/OpenTK/Platform/MacOS/EventInfo.cs b/OpenTK/Platform/MacOS/EventInfo.cs
deleted file mode 100644
index cc4e7960f..000000000
--- a/OpenTK/Platform/MacOS/EventInfo.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-//
-// xCSCarbon
-//
-// Created by Erik Ylvisaker on 3/17/08.
-// Copyright 2008 __MyCompanyName__. All rights reserved.
-//
-//
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-
-namespace OpenTK.Platform.MacOS.Carbon
-{
- internal struct EventInfo {
-
- internal EventInfo(IntPtr eventRef) {
- EventClass = API.GetEventClass(eventRef);
- EventKind = API.GetEventKind(eventRef);
- }
-
- public uint EventKind;
- public EventClass EventClass;
-
- public override string ToString() {
- return "Event class " + EventClass + ", kind: " + EventKind;
- }
- }
-}