diff --git a/Source/Examples/ExampleLauncher.Designer.cs b/Source/Examples/ExampleLauncher.Designer.cs
index 9aac5235..61adc0ee 100644
--- a/Source/Examples/ExampleLauncher.Designer.cs
+++ b/Source/Examples/ExampleLauncher.Designer.cs
@@ -1,4 +1,4 @@
-namespace Examples
+namespace Examples
{
partial class ExampleLauncher
{
@@ -85,9 +85,9 @@
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(292, 266);
+ this.ClientSize = new System.Drawing.Size(292, 366);
this.Controls.Add(this.splitContainer1);
- this.MinimumSize = new System.Drawing.Size(300, 300);
+ this.MinimumSize = new System.Drawing.Size(300, 400);
this.Name = "ExampleLauncher";
this.Text = "OpenTK Example Launcher";
this.Load += new System.EventHandler(this.ExampleLauncher_Load);
diff --git a/Source/Examples/Tests/GameWindowStates.cs b/Source/Examples/Tests/GameWindowStates.cs
index c722c478..14a17b52 100644
--- a/Source/Examples/Tests/GameWindowStates.cs
+++ b/Source/Examples/Tests/GameWindowStates.cs
@@ -82,6 +82,10 @@ namespace Examples.Tests
if (sender[Key.ShiftLeft] || sender[Key.ShiftRight])
WindowState = GetPrevious(WindowState);
+ else if (sender[Key.AltLeft] || sender[Key.AltRight])
+ WindowState = GetNext(GetNext(WindowState));
+ else if (sender[Key.ControlLeft] || sender[Key.ControlRight])
+ WindowState = GetPrevious(GetPrevious(WindowState));
else
WindowState = GetNext(WindowState);
diff --git a/Source/OpenTK/Configuration.cs b/Source/OpenTK/Configuration.cs
index 729e7242..7dc5903c 100644
--- a/Source/OpenTK/Configuration.cs
+++ b/Source/OpenTK/Configuration.cs
@@ -11,6 +11,7 @@ using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.IO;
+using System.Runtime.InteropServices;
[assembly: CLSCompliant(true)]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("OpenTK.Utilities")]
@@ -20,7 +21,7 @@ namespace OpenTK
/// Provides information about the underlying OS and runtime.
public static class Configuration
{
- static bool runningOnWindows, runningOnX11, runningOnOSX, runningOnLinux, runningOnMono;
+ static bool runningOnWindows, runningOnX11, runningOnMacOS, runningOnLinux, runningOnMono;
#region --- Constructors ---
@@ -47,7 +48,7 @@ namespace OpenTK
break;
case "Darwin":
- runningOnOSX = true;
+ runningOnMacOS = true;
break;
default:
@@ -64,7 +65,7 @@ namespace OpenTK
runningOnMono = true;
Debug.Print("Detected configuration: {0} / {1}",
- RunningOnWindows ? "Windows" : RunningOnLinux ? "Linux" : RunningOnOSX ? "MacOS" : RunningOnX11 ? "X11" : "Unknown Platform",
+ RunningOnWindows ? "Windows" : RunningOnLinux ? "Linux" : RunningOnMacOS ? "MacOS" : RunningOnX11 ? "X11" : "Unknown Platform",
RunningOnMono ? "Mono" : ".Net");
}
@@ -79,7 +80,7 @@ namespace OpenTK
#endregion
- #region public static bool RunningOnX11
+ #region public static bool RunningOnX11
/// Gets a System.Boolean indicating whether OpenTK is running on an X11 platform.
public static bool RunningOnX11 { get { return runningOnX11; } }
@@ -93,10 +94,10 @@ namespace OpenTK
#endregion
- #region public static bool RunningOnOSX
+ #region public static bool RunningOnMacOS
/// Gets a System.Boolean indicating whether OpenTK is running on a MacOS platform.
- public static bool RunningOnOSX { get { return runningOnOSX; } }
+ public static bool RunningOnMacOS { get { return runningOnMacOS; } }
#endregion
@@ -113,41 +114,55 @@ namespace OpenTK
#region private static string DetectUnixKernel()
- //
- // Executes "uname" which returns a string representing the name of the
- // underlying Unix kernel.
- //
- // "Unix", "Linux", "Darwin" or null.
- // Source code from "Mono: A Developer's Notebook"
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ struct utsname
+ {
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
+ public string sysname;
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
+ public string nodename;
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
+ public string release;
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
+ public string version;
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
+ public string machine;
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
+ public string extraJustInCase;
+
+ }
+
+ ///
+ /// Detects the unix kernel by p/invoking the uname call in libc.
+ ///
+ ///
private static string DetectUnixKernel()
{
- ProcessStartInfo startInfo = new ProcessStartInfo();
- startInfo.Arguments = "-s";
- startInfo.RedirectStandardOutput = true;
- startInfo.RedirectStandardError = true;
- startInfo.UseShellExecute = false;
- foreach (string unameprog in new string[] { "/usr/bin/uname", "/bin/uname", "uname" })
- {
- try
- {
- startInfo.FileName = unameprog;
- Process uname = Process.Start(startInfo);
- StreamReader stdout = uname.StandardOutput;
- return stdout.ReadLine().Trim();
- }
- catch (System.IO.FileNotFoundException)
- {
- // The requested executable doesn't exist, try next one.
- continue;
- }
- catch (System.ComponentModel.Win32Exception)
- {
- continue;
- }
- }
- return null;
+ Debug.Print("Size: {0}", Marshal.SizeOf(typeof(utsname)).ToString());
+ Debug.Flush();
+ utsname uts = new utsname();
+ uname(out uts);
+
+ Debug.WriteLine("System:");
+ Debug.Indent();
+ Debug.WriteLine(uts.sysname);
+ Debug.WriteLine(uts.nodename);
+ Debug.WriteLine(uts.release);
+ Debug.WriteLine(uts.version);
+ Debug.WriteLine(uts.machine);
+ Debug.Unindent();
+
+ return uts.sysname.ToString();
}
+ [DllImport("libc")]
+ private static extern void uname(out utsname uname_struct);
+
#endregion
#endregion
diff --git a/Source/OpenTK/GLControl.cs b/Source/OpenTK/GLControl.cs
index 83c9747e..94e92cfc 100644
--- a/Source/OpenTK/GLControl.cs
+++ b/Source/OpenTK/GLControl.cs
@@ -64,25 +64,36 @@ namespace OpenTK
// On Windows, you first need to create the window, then set the pixel format.
// On X11, you first need to select the visual, then create the window.
- // On OSX, ???
+ // On OSX, the pixel format needs to be selected before the GL context.
// Right now, pixel formats/visuals are selected during context creation. In the future,
// it would be better to decouple selection from context creation, which will allow us
// to clean up this hacky code. The best option is to do this along with multisampling
// support.
if (DesignMode)
implementation = new Platform.Dummy.DummyGLControl();
- else if (Configuration.RunningOnWindows)
- implementation = new Platform.Windows.WinGLControl(mode, this);
- else if (Configuration.RunningOnX11)
- implementation = new Platform.X11.X11GLControl(mode, this);
- else if (Configuration.RunningOnOSX)
- throw new PlatformNotSupportedException("Refer to http://www.opentk.com for more information.");
+ else
+ implementation = Platform.Factory.CreateGLControl(mode, this);
this.CreateControl();
}
#endregion
+ protected override void OnResize(EventArgs e)
+ {
+ if (context != null)
+ context.Update(window_info);
+
+ base.OnResize(e);
+ }
+ protected override void OnParentChanged(EventArgs e)
+ {
+ if (context != null)
+ context.Update(window_info);
+
+ base.OnParentChanged(e);
+ }
+
#region --- Protected Methods ---
/// Raises the HandleCreated event.
diff --git a/Source/OpenTK/GameWindow.cs b/Source/OpenTK/GameWindow.cs
index b8feeb96..df511272 100644
--- a/Source/OpenTK/GameWindow.cs
+++ b/Source/OpenTK/GameWindow.cs
@@ -153,14 +153,7 @@ namespace OpenTK
if (device == null)
device = DisplayDevice.Default;
- if (Configuration.RunningOnWindows)
- glWindow = new OpenTK.Platform.Windows.WinGLNative();
- else if (Configuration.RunningOnX11)
- glWindow = new OpenTK.Platform.X11.X11GLNative();
- else
- throw new PlatformNotSupportedException(
- "Your platform is not supported currently. Please, refer to http://www.opentk.com for more information.");
-
+ glWindow = Platform.Factory.CreateNativeGLWindow();
glWindow.Destroy += glWindow_Destroy;
try
@@ -182,14 +175,23 @@ namespace OpenTK
if ((options & GameWindowFlags.Fullscreen) != 0)
{
device.ChangeResolution(width, height, mode.ColorFormat.BitsPerPixel, 0);
- //this.Fullscreen = true;
- throw new NotImplementedException();
+ this.WindowState = WindowState.Fullscreen;
+ //throw new NotImplementedException();
}
this.VSync = VSyncMode.On; //VSyncMode.Adaptive;
+ glWindow.Resize += new ResizeEvent(glWindow_Resize);
}
+ void glWindow_Resize(object sender, ResizeEventArgs e)
+ {
+ Debug.Print("glWindow_Resize event fired.");
+
+ OnResizeInternal(e);
+ }
+
+
#endregion
///
@@ -230,9 +232,17 @@ namespace OpenTK
/// Stops the main loop.
void ExitInternal()
{
- //Debug.Print("Firing GameWindowExitException");
- throw new GameWindowExitException();
+ //Debug.Print("Firing GameWindowExitException");
+ if (HasMainLoop)
+ {
+ throw new GameWindowExitException();
+ }
+ if (CloseWindow != null)
+ {
+ CloseWindow(this, EventArgs.Empty);
+ }
}
+ public event EventHandler CloseWindow;
void CallExitInternal(GameWindow sender, UpdateFrameEventArgs e)
{
@@ -1268,11 +1278,7 @@ namespace OpenTK
///
/// Occurs when the GameWindow is resized. Derived classes should override the OnResize method for better performance.
///
- public event ResizeEvent Resize
- {
- add { if (disposed) throw new ObjectDisposedException("GameWindow"); glWindow.Resize += value; }
- remove { if (disposed) throw new ObjectDisposedException("GameWindow"); glWindow.Resize -= value; }
- }
+ public event ResizeEvent Resize;
///
/// Raises the Resize event.
@@ -1285,8 +1291,8 @@ namespace OpenTK
this.width = e.Width;
this.height = e.Height;
- //if (this.Resize != null)
- // this.Resize(this, e);
+ if (this.Resize != null)
+ this.Resize(this, e);
OnResize(e);
}
diff --git a/Source/OpenTK/Graphics/DisplayDevice.cs b/Source/OpenTK/Graphics/DisplayDevice.cs
index ef529bcc..9c6757b7 100644
--- a/Source/OpenTK/Graphics/DisplayDevice.cs
+++ b/Source/OpenTK/Graphics/DisplayDevice.cs
@@ -42,17 +42,8 @@ namespace OpenTK.Graphics
static DisplayDevice()
{
- switch (System.Environment.OSVersion.Platform)
- {
- case PlatformID.Unix:
- case (PlatformID)128:
- implementation = new OpenTK.Platform.X11.X11XrandrDisplayDevice();
- break;
-
- default:
- implementation = new OpenTK.Platform.Windows.WinDisplayDeviceDriver();
- break;
- }
+ implementation = Platform.Factory.CreateDisplayDeviceDriver();
+
//lock (display_lock)
//{
// int i = 0;
diff --git a/Source/OpenTK/Graphics/GL/GLHelper.cs b/Source/OpenTK/Graphics/GL/GLHelper.cs
index d7bb103f..f3fb4bf2 100644
--- a/Source/OpenTK/Graphics/GL/GLHelper.cs
+++ b/Source/OpenTK/Graphics/GL/GLHelper.cs
@@ -569,21 +569,22 @@ namespace OpenTK.Graphics
{
if (getProcAddress == null)
{
- if (System.Environment.OSVersion.Platform == PlatformID.Win32NT ||
- System.Environment.OSVersion.Platform == PlatformID.Win32S ||
- System.Environment.OSVersion.Platform == PlatformID.Win32Windows ||
- System.Environment.OSVersion.Platform == PlatformID.WinCE)
+ if (Configuration.RunningOnWindows)
{
getProcAddress = new GetProcAddressWindows();
}
- else if (System.Environment.OSVersion.Platform == PlatformID.Unix)
+ else if (Configuration.RunningOnMacOS)
+ {
+ getProcAddress = new GetProcAddressOSX();
+ }
+ else if (Configuration.RunningOnX11)
{
getProcAddress = new GetProcAddressX11();
}
else
{
throw new PlatformNotSupportedException(
- "Extension loading is only supported under X11 and Windows. We are sorry for the inconvience.");
+ "Extension loading is only supported under Mac OS X, X11 and Windows. We are sorry for the inconvience.");
}
}
diff --git a/Source/OpenTK/Graphics/GraphicsContext.cs b/Source/OpenTK/Graphics/GraphicsContext.cs
index 45cc2e5e..1c3432de 100644
--- a/Source/OpenTK/Graphics/GraphicsContext.cs
+++ b/Source/OpenTK/Graphics/GraphicsContext.cs
@@ -72,12 +72,8 @@ namespace OpenTK.Graphics
if (designMode)
implementation = new Platform.Dummy.DummyGLContext(mode);
- else if (Configuration.RunningOnWindows)
- implementation = new Platform.Windows.WinGLContext(mode, window, shareContext);
- else if (Configuration.RunningOnX11)
- implementation = new Platform.X11.X11GLContext(mode, window, shareContext, DirectRendering);
else
- throw new PlatformNotSupportedException("Please, refer to http://www.opentk.com for more information.");
+ implementation = Factory.CreateGLContext(mode, window, shareContext, DirectRendering);
lock (context_lock)
{
@@ -236,6 +232,10 @@ namespace OpenTK.Graphics
#endregion
+ internal IGraphicsContext Implementation
+ {
+ get { return implementation; }
+ }
#region --- IGraphicsContext Members ---
///
@@ -315,6 +315,16 @@ namespace OpenTK.Graphics
set { implementation.VSync = value; }
}
+ ///
+ /// Updates the graphics context. This must be called when the render target
+ /// is resized for proper behavior on Mac OS X.
+ ///
+ ///
+ public void Update(IWindowInfo window)
+ {
+ implementation.Update(window);
+ }
+
#endregion
#region --- IGraphicsContextInternal Members ---
diff --git a/Source/OpenTK/Graphics/GraphicsMode.cs b/Source/OpenTK/Graphics/GraphicsMode.cs
index 72c87882..26f10cfb 100644
--- a/Source/OpenTK/Graphics/GraphicsMode.cs
+++ b/Source/OpenTK/Graphics/GraphicsMode.cs
@@ -31,12 +31,7 @@ namespace OpenTK.Graphics
static GraphicsMode()
{
- if (Configuration.RunningOnWindows)
- implementation = new OpenTK.Platform.Windows.WinGraphicsMode();
- else if (Configuration.RunningOnX11)
- implementation = new OpenTK.Platform.X11.X11GraphicsMode();
- else
- throw new PlatformNotSupportedException("Please, refer to http://www.opentk.com for more information.");
+ implementation = Platform.Factory.CreateGraphicsMode();
}
#endregion
diff --git a/Source/OpenTK/Graphics/IGraphicsContext.cs b/Source/OpenTK/Graphics/IGraphicsContext.cs
index a91d1071..59e024bc 100644
--- a/Source/OpenTK/Graphics/IGraphicsContext.cs
+++ b/Source/OpenTK/Graphics/IGraphicsContext.cs
@@ -44,6 +44,13 @@ namespace OpenTK.Graphics
/// Gets or sets a value indicating whether VSyncing is enabled.
///
bool VSync { get; set; }
+
+ ///
+ /// Updates the graphics context. This must be called when the region the graphics context
+ /// is drawn to is resized.
+ ///
+ ///
+ void Update(IWindowInfo window);
}
public delegate void DestroyEvent(T sender, EventArgs e);
diff --git a/Source/OpenTK/OpenTK.dll.config b/Source/OpenTK/OpenTK.dll.config
index 1c21f56e..d6c9431a 100644
--- a/Source/OpenTK/OpenTK.dll.config
+++ b/Source/OpenTK/OpenTK.dll.config
@@ -3,4 +3,6 @@
-
\ No newline at end of file
+
+
+
diff --git a/Source/OpenTK/Platform/Dummy/DummyGLContext.cs b/Source/OpenTK/Platform/Dummy/DummyGLContext.cs
index 7eb26728..cf9b8c32 100644
--- a/Source/OpenTK/Platform/Dummy/DummyGLContext.cs
+++ b/Source/OpenTK/Platform/Dummy/DummyGLContext.cs
@@ -67,6 +67,10 @@ namespace OpenTK.Platform.Dummy
public bool VSync { get { return vsync; } set { vsync = value; } }
+ public void Update(IWindowInfo window)
+ {
+ }
+
#endregion
#region --- IDisposable Members ---
@@ -87,5 +91,6 @@ namespace OpenTK.Platform.Dummy
}
#endregion
+
}
}
diff --git a/Source/OpenTK/Platform/Factory.cs b/Source/OpenTK/Platform/Factory.cs
new file mode 100644
index 00000000..a65b739d
--- /dev/null
+++ b/Source/OpenTK/Platform/Factory.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace OpenTK.Platform
+{
+ using Graphics;
+
+ static class Factory
+ {
+ static IPlatformFactory implementation;
+
+ static Factory()
+ {
+ if (Configuration.RunningOnWindows) implementation = new Windows.WinFactory();
+ else if (Configuration.RunningOnX11) implementation = new X11.X11Factory();
+ else if (Configuration.RunningOnMacOS) implementation = new MacOS.MacOSFactory();
+ else implementation = new UnsupportedPlatform();
+ }
+
+ internal static INativeGLWindow CreateNativeGLWindow()
+ {
+ return implementation.CreateGLNative();
+ }
+
+ internal static IGLControl CreateGLControl(GraphicsMode mode, GLControl owner)
+ {
+ return implementation.CreateGLControl(mode, owner);
+ }
+
+ internal static IDisplayDeviceDriver CreateDisplayDeviceDriver()
+ {
+ return implementation.CreateDisplayDeviceDriver();
+ }
+
+ internal static IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool directRendering)
+ {
+ return implementation.CreateGLContext(mode, window, shareContext, directRendering);
+ }
+
+ internal static IGraphicsMode CreateGraphicsMode()
+ {
+ return implementation.CreateGraphicsMode();
+ }
+
+ class UnsupportedPlatform : IPlatformFactory
+ {
+ #region IPlatformFactory Members
+
+ public INativeGLWindow CreateGLNative()
+ {
+ throw new PlatformNotSupportedException("Please, refer to http://www.opentk.com for more information.");
+ }
+
+ public IGLControl CreateGLControl(GraphicsMode mode, GLControl owner)
+ {
+ throw new PlatformNotSupportedException("Please, refer to http://www.opentk.com for more information.");
+ }
+
+ public IDisplayDeviceDriver CreateDisplayDeviceDriver()
+ {
+ throw new PlatformNotSupportedException("Please, refer to http://www.opentk.com for more information.");
+ }
+
+ public IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool DirectRendering)
+ {
+ throw new PlatformNotSupportedException("Please, refer to http://www.opentk.com for more information.");
+ }
+
+ public IGraphicsMode CreateGraphicsMode()
+ {
+ throw new PlatformNotSupportedException("Please, refer to http://www.opentk.com for more information.");
+ }
+
+ #endregion
+ }
+ }
+}
diff --git a/Source/OpenTK/Platform/IPlatformFactory.cs b/Source/OpenTK/Platform/IPlatformFactory.cs
new file mode 100644
index 00000000..2b3fff7f
--- /dev/null
+++ b/Source/OpenTK/Platform/IPlatformFactory.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace OpenTK.Platform
+{
+ interface IPlatformFactory
+ {
+ INativeGLWindow CreateGLNative();
+
+ IGLControl CreateGLControl(OpenTK.Graphics.GraphicsMode mode, GLControl owner);
+
+ OpenTK.Graphics.IDisplayDeviceDriver CreateDisplayDeviceDriver();
+
+ OpenTK.Graphics.IGraphicsContext CreateGLContext(OpenTK.Graphics.GraphicsMode mode, IWindowInfo window, OpenTK.Graphics.IGraphicsContext shareContext, bool DirectRendering);
+
+ OpenTK.Graphics.IGraphicsMode CreateGraphicsMode();
+ }
+}
diff --git a/Source/OpenTK/Platform/MacOS/AglContext.cs b/Source/OpenTK/Platform/MacOS/AglContext.cs
new file mode 100644
index 00000000..7aa1288c
--- /dev/null
+++ b/Source/OpenTK/Platform/MacOS/AglContext.cs
@@ -0,0 +1,426 @@
+//
+//
+// AglContext.cs
+//
+// Created by Erik Ylvisaker on 3/17/08.
+// Copyright 2008. All rights reserved.
+//
+//
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using Control = System.Windows.Forms.Control;
+
+namespace OpenTK.Platform.MacOS
+{
+ using Carbon;
+ using Graphics;
+ using Graphics.OpenGL;
+
+ using AGLRendererInfo = IntPtr;
+ using AGLPixelFormat = IntPtr;
+ using AGLContext = IntPtr;
+ using AGLPbuffer = IntPtr;
+
+ class AglContext : IGraphicsContext, IGraphicsContextInternal
+ {
+ IntPtr contextRef;
+
+ bool mVSync = false;
+ IntPtr displayID;
+
+ GraphicsMode mode;
+ CarbonWindowInfo carbonWindow;
+ IntPtr shareContextRef;
+
+ static AglContext()
+ {
+ if (GraphicsContext.GetCurrentContext == null)
+ GraphicsContext.GetCurrentContext = AglContext.GetCurrentContext;
+ }
+ public AglContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext)
+ {
+ Debug.Print("Context Type: {0}", shareContext);
+ Debug.Print("Window info: {0}", window);
+
+ this.mode = mode;
+ this.carbonWindow = (CarbonWindowInfo)window;
+
+ if (shareContext is AglContext)
+ shareContextRef = ((AglContext)shareContext).contextRef;
+
+ CreateContext(mode, carbonWindow, shareContextRef, true);
+ }
+
+
+ private void AddPixelAttrib(List aglAttributes, Agl.PixelFormatAttribute pixelFormatAttribute)
+ {
+ Debug.Print(pixelFormatAttribute.ToString());
+
+ aglAttributes.Add((int)pixelFormatAttribute);
+ }
+ private void AddPixelAttrib(List aglAttributes, Agl.PixelFormatAttribute pixelFormatAttribute, int value)
+ {
+ Debug.Print("{0} : {1}", pixelFormatAttribute, value);
+
+ aglAttributes.Add((int)pixelFormatAttribute);
+ aglAttributes.Add(value);
+ }
+ void CreateContext(GraphicsMode mode, CarbonWindowInfo carbonWindow,
+ IntPtr shareContextRef, bool fullscreen)
+ {
+ List aglAttributes = new List();
+
+ Debug.Print("AGL pixel format attributes:");
+ Debug.Indent();
+
+ AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_RGBA);
+ AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_DOUBLEBUFFER);
+ AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_RED_SIZE, mode.ColorFormat.Red);
+ AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_GREEN_SIZE, mode.ColorFormat.Green);
+ AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_BLUE_SIZE, mode.ColorFormat.Blue);
+ AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ALPHA_SIZE, mode.ColorFormat.Alpha);
+
+ if (mode.Depth > 0)
+ AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_DEPTH_SIZE, mode.Depth);
+
+ if (mode.Stencil > 0)
+ AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_STENCIL_SIZE, mode.Stencil);
+
+ if (mode.AccumulatorFormat.BitsPerPixel > 0)
+ {
+ AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ACCUM_RED_SIZE, mode.AccumulatorFormat.Red);
+ AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ACCUM_GREEN_SIZE, mode.AccumulatorFormat.Green);
+ AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ACCUM_BLUE_SIZE, mode.AccumulatorFormat.Blue);
+ AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ACCUM_ALPHA_SIZE, mode.AccumulatorFormat.Alpha);
+ }
+
+ if (fullscreen)
+ {
+ AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_FULLSCREEN);
+ }
+ AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_NONE);
+
+ Debug.Unindent();
+
+ Debug.Write("Attribute array: ");
+ for (int i = 0; i < aglAttributes.Count; i++)
+ Debug.Write(aglAttributes[i].ToString() + " ");
+ Debug.WriteLine("");
+
+ AGLPixelFormat myAGLPixelFormat;
+
+ // Choose a pixel format with the attributes we specified.
+ if (fullscreen)
+ {
+ IntPtr gdevice;
+
+ OSStatus status = Carbon.API.DMGetGDeviceByDisplayID(
+ QuartzDisplayDeviceDriver.MainDisplay, out gdevice, false);
+
+ if (status != OSStatus.NoError)
+ throw new MacOSException(status, "DMGetGDeviceByDisplayID failed.");
+
+ myAGLPixelFormat = Agl.aglChoosePixelFormat(
+ ref gdevice, 1,
+ aglAttributes.ToArray());
+
+ Agl.AglError err = Agl.GetError();
+
+ if (err == Agl.AglError.BadPixelFormat)
+ {
+ Debug.Print("Failed to create full screen pixel format.");
+ Debug.Print("Trying again to create a non-fullscreen pixel format.");
+
+ CreateContext(mode, carbonWindow, shareContextRef, false);
+ return;
+ }
+ }
+ else
+ {
+ myAGLPixelFormat = Agl.aglChoosePixelFormat(
+ IntPtr.Zero, 0,
+ aglAttributes.ToArray());
+
+ MyAGLReportError("aglChoosePixelFormat");
+ }
+
+
+ // create the context and share it with the share reference.
+ this.contextRef = Agl.aglCreateContext(myAGLPixelFormat, shareContextRef);
+ MyAGLReportError("aglCreateContext");
+
+ // Free the pixel format from memory.
+ Agl.aglDestroyPixelFormat(myAGLPixelFormat);
+ MyAGLReportError("aglDestroyPixelFormat");
+
+ Debug.Print("IsControl: {0}", carbonWindow.IsControl);
+
+ SetDrawable(carbonWindow);
+ SetBufferRect(carbonWindow);
+ Update(carbonWindow);
+
+ MakeCurrent(carbonWindow);
+
+ Debug.Print("context: {0}", contextRef);
+ }
+
+ void SetBufferRect(CarbonWindowInfo carbonWindow)
+ {
+ if (carbonWindow.IsControl == false)
+ return;
+
+ System.Windows.Forms.Control ctrl = Control.FromHandle(carbonWindow.WindowRef);
+
+ if (ctrl.TopLevelControl == null)
+ return;
+
+ Rect rect = API.GetControlBounds(carbonWindow.WindowRef);
+
+ rect.X = (short)ctrl.Left;
+ rect.Y = (short)ctrl.Top;
+
+ Debug.Print("Setting buffer_rect for control.");
+ Debug.Print("MacOS Coordinate Rect: {0}", rect);
+
+ rect.Y = (short)(ctrl.TopLevelControl.ClientSize.Height - rect.Y - rect.Height);
+ Debug.Print(" AGL Coordinate Rect: {0}", rect);
+
+ int[] glrect = new int[4];
+
+ glrect[0] = rect.X;
+ glrect[1] = rect.Y;
+ glrect[2] = rect.Width;
+ glrect[3] = rect.Height;
+
+ Agl.aglSetInteger(contextRef, Agl.ParameterNames.AGL_BUFFER_RECT, glrect);
+ MyAGLReportError("aglSetInteger");
+
+ Agl.aglEnable(contextRef, Agl.ParameterNames.AGL_BUFFER_RECT);
+ MyAGLReportError("aglEnable");
+
+ }
+ void SetDrawable(CarbonWindowInfo carbonWindow)
+ {
+ IntPtr windowPort = GetWindowPortForWindowInfo(carbonWindow);
+
+ Agl.aglSetDrawable(contextRef, windowPort);
+
+ MyAGLReportError("aglSetDrawable");
+
+ }
+
+ private static IntPtr GetWindowPortForWindowInfo(CarbonWindowInfo carbonWindow)
+ {
+ IntPtr windowPort;
+ if (carbonWindow.IsControl)
+ {
+ IntPtr controlOwner = API.GetControlOwner(carbonWindow.WindowRef);
+
+ windowPort = API.GetWindowPort(controlOwner);
+ }
+ else
+ windowPort = API.GetWindowPort(carbonWindow.WindowRef);
+ return windowPort;
+ }
+ public void Update(IWindowInfo window)
+ {
+ CarbonWindowInfo carbonWindow = (CarbonWindowInfo)window;
+
+ SetDrawable(carbonWindow);
+ SetBufferRect(carbonWindow);
+
+ Agl.aglUpdateContext(contextRef);
+ }
+
+ void MyAGLReportError(string function)
+ {
+ Agl.AglError err = Agl.GetError();
+
+ if (err != Agl.AglError.NoError)
+ throw new MacOSException((OSStatus)err, string.Format(
+ "AGL Error from function {0}: {1} {2}",
+ function, err, Agl.ErrorString(err)));
+ }
+
+ static ContextHandle GetCurrentContext()
+ {
+ return (ContextHandle)Agl.aglGetCurrentContext();
+ }
+ bool firstFullScreen = false;
+
+ internal void SetFullScreen(CarbonWindowInfo info)
+ {
+ Agl.aglSetFullScreen(contextRef, 0, 0, 0, 0);
+
+ // This is a weird hack to workaround a bug where the first time a context
+ // is made fullscreen, we just end up with a blank screen. So we undo it as fullscreen
+ // and redo it as fullscreen.
+ if (firstFullScreen == false)
+ {
+ firstFullScreen = true;
+ UnsetFullScreen(info);
+ SetFullScreen(info);
+ }
+ }
+ internal void UnsetFullScreen(CarbonWindowInfo windowInfo)
+ {
+ Agl.aglSetDrawable(contextRef, IntPtr.Zero);
+ SetDrawable(windowInfo);
+ }
+
+
+ #region IGraphicsContext Members
+
+ bool firstSwap = false;
+ public void SwapBuffers()
+ {
+ // this is part of the hack to avoid dropping the first frame when
+ // using multiple GLControls.
+ if (firstSwap == false && carbonWindow.IsControl)
+ {
+ Debug.WriteLine("--> Resetting drawable. <--");
+ firstSwap = true;
+ SetDrawable(carbonWindow);
+ Update(carbonWindow);
+ }
+
+ Agl.aglSwapBuffers(contextRef);
+ MyAGLReportError("aglSwapBuffers");
+ }
+
+ public void MakeCurrent(IWindowInfo window)
+ {
+ if (Agl.aglSetCurrentContext(contextRef) == false)
+ MyAGLReportError("aglSetCurrentContext");
+ }
+
+ public bool IsCurrent
+ {
+ get
+ {
+ return (contextRef == Agl.aglGetCurrentContext());
+ }
+ }
+
+ public event DestroyEvent Destroy;
+ void OnDestroy()
+ {
+
+ if (Destroy != null)
+ {
+ Debug.Print("Destroy handlers: {0}", Destroy.GetInvocationList().Length);
+ Destroy(this, EventArgs.Empty);
+ }
+ }
+
+ public bool VSync
+ {
+ get
+ {
+ return mVSync;
+ }
+ set
+ {
+ int intVal = value ? 1 : 0;
+
+ Agl.aglSetInteger(this.contextRef, Agl.ParameterNames.AGL_SWAP_INTERVAL, ref intVal);
+
+ mVSync = value;
+ }
+ }
+
+ #endregion
+
+ #region IDisposable Members
+ ~AglContext()
+ {
+ Dispose(false);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ void Dispose(bool disposing)
+ {
+
+ if (contextRef == IntPtr.Zero)
+ return;
+
+ OnDestroy();
+ Debug.Print("Disposing of AGL context.");
+
+ try
+ {
+ throw new Exception();
+ }
+ catch (Exception e)
+ {
+ Debug.WriteLine(e.StackTrace);
+ }
+
+ Agl.aglSetCurrentContext(IntPtr.Zero);
+ Agl.aglSetDrawable(contextRef, IntPtr.Zero);
+
+ Debug.Print("Set drawable to null for context {0}.", contextRef);
+
+ if (Agl.aglDestroyContext(contextRef) == true)
+ {
+ contextRef = IntPtr.Zero;
+ return;
+ }
+
+ // failed to destroy context.
+ Debug.WriteLine("Failed to destroy context.");
+ Debug.WriteLine(Agl.ErrorString(Agl.GetError()));
+
+ // don't throw an exception from the finalizer thread.
+ if (disposing)
+ {
+ throw new MacOSException((OSStatus)Agl.GetError(), Agl.ErrorString(Agl.GetError()));
+ }
+ }
+
+ #endregion
+
+ #region IGraphicsContextInternal Members
+
+ void IGraphicsContextInternal.LoadAll()
+ {
+ GL.LoadAll();
+ Glu.LoadAll();
+ }
+
+ ContextHandle IGraphicsContextInternal.Context
+ {
+ get { return (ContextHandle)contextRef; }
+ }
+
+ GraphicsMode IGraphicsContextInternal.GraphicsMode
+ {
+ get { throw new Exception("The method or operation is not implemented."); }
+ }
+
+ void IGraphicsContextInternal.RegisterForDisposal(IDisposable resource)
+ {
+ throw new Exception("The method or operation is not implemented.");
+ }
+
+ void IGraphicsContextInternal.DisposeResources()
+ {
+ throw new Exception("The method or operation is not implemented.");
+ }
+
+ IntPtr IGraphicsContextInternal.GetAddress(string function)
+ {
+ throw new Exception("The method or operation is not implemented.");
+ }
+
+ #endregion
+
+ }
+}
diff --git a/Source/OpenTK/Platform/MacOS/Application.cs b/Source/OpenTK/Platform/MacOS/Application.cs
new file mode 100644
index 00000000..8c7ec796
--- /dev/null
+++ b/Source/OpenTK/Platform/MacOS/Application.cs
@@ -0,0 +1,130 @@
+//
+//
+// xCSCarbon
+//
+// Created by Erik Ylvisaker on 3/17/08.
+// Copyright 2008 __MyCompanyName__. All rights reserved.
+//
+//
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+
+namespace OpenTK.Platform.MacOS.Carbon
+{
+ static class Application
+ {
+ static bool mInitialized = false;
+ static IntPtr uppHandler;
+ static CarbonGLNative eventHandler;
+
+ static Application()
+ {
+ Initialize();
+ }
+
+ internal static void Initialize()
+ {
+ if (mInitialized) return;
+
+ API.AcquireRootMenu();
+
+ ConnectEvents();
+ }
+
+ 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),
+
+ 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),
+
+ new EventTypeSpec(EventClass.AppleEvent, AppleEventKind.AppleEvent),
+ };
+
+ MacOSEventHandler handler = EventHandler;
+ uppHandler = API.NewEventHandlerUPP(handler);
+
+ API.InstallApplicationEventHandler(
+ 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)
+ {
+ case EventClass.Application:
+ switch (evt.AppEventKind)
+ {
+ default:
+ return OSStatus.EventNotHandled;
+ }
+
+ case EventClass.AppleEvent:
+ // only event here is the apple event.
+ Debug.Print("Processing apple event.");
+ API.ProcessAppleEvent(inEvent);
+ break;
+
+ case EventClass.Keyboard:
+ case EventClass.Mouse:
+ if (WindowEventHandler != null)
+ {
+ return WindowEventHandler.DispatchEvent(inCaller, inEvent, evt, userData);
+ }
+ break;
+ }
+
+ return OSStatus.EventNotHandled;
+ }
+
+ public static void Run(CarbonGLNative window)
+ {
+ window.Destroy += MainWindowClosed;
+ window.Show();
+
+ API.RunApplicationEventLoop();
+
+ window.Destroy -= MainWindowClosed;
+ }
+
+ static void MainWindowClosed(object sender, EventArgs e)
+ {
+ Debug.Print("Quitting application event loop.");
+ API.QuitApplicationEventLoop();
+ }
+
+
+ internal static void ProcessEvents()
+ {
+ API.ProcessEvents();
+ }
+ }
+}
diff --git a/Source/OpenTK/Platform/MacOS/CarbonBindings/Agl.cs b/Source/OpenTK/Platform/MacOS/CarbonBindings/Agl.cs
new file mode 100644
index 00000000..312c941b
--- /dev/null
+++ b/Source/OpenTK/Platform/MacOS/CarbonBindings/Agl.cs
@@ -0,0 +1,462 @@
+//
+//
+// Agl.cs
+//
+// Created by Erik Ylvisaker on 3/17/08.
+// Copyright 2008. All rights reserved.
+//
+//
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace OpenTK.Platform.MacOS
+{
+ /*
+ ** Macintosh device type.
+ */
+ using AGLDevice = IntPtr;
+
+ /*
+ ** Macintosh drawable type.
+ */
+ using AGLDrawable = IntPtr;
+
+ /*
+ ** AGL opaque data.
+ */
+ using AGLRendererInfo = IntPtr;
+ using AGLPixelFormat = IntPtr;
+ using AGLContext = IntPtr;
+ using AGLPbuffer = IntPtr;
+
+ using GLenum = UInt32;
+
+ unsafe static partial class Agl
+ {
+
+ const string agl = "/System/Library/Frameworks/AGL.framework/Versions/Current/AGL";
+
+ /*
+ ** AGL API version.
+ */
+ const int AGL_VERSION_2_0 = 1;
+
+ /************************************************************************/
+
+ /*
+ ** Attribute names for aglChoosePixelFormat and aglDescribePixelFormat.
+ */
+ internal enum PixelFormatAttribute
+ {
+ AGL_NONE = 0,
+ AGL_ALL_RENDERERS = 1, /* choose from all available renderers */
+ AGL_BUFFER_SIZE = 2, /* depth of the index buffer */
+ AGL_LEVEL = 3, /* level in plane stacking */
+ AGL_RGBA = 4, /* choose an RGBA format */
+ AGL_DOUBLEBUFFER = 5, /* double buffering supported */
+ AGL_STEREO = 6, /* stereo buffering supported */
+ AGL_AUX_BUFFERS = 7, /* number of aux buffers */
+ AGL_RED_SIZE = 8, /* number of red component bits */
+ AGL_GREEN_SIZE = 9, /* number of green component bits */
+ AGL_BLUE_SIZE = 10, /* number of blue component bits */
+ AGL_ALPHA_SIZE = 11, /* number of alpha component bits */
+ AGL_DEPTH_SIZE = 12, /* number of depth bits */
+ AGL_STENCIL_SIZE = 13, /* number of stencil bits */
+ AGL_ACCUM_RED_SIZE = 14, /* number of red accum bits */
+ AGL_ACCUM_GREEN_SIZE = 15, /* number of green accum bits */
+ AGL_ACCUM_BLUE_SIZE = 16, /* number of blue accum bits */
+ AGL_ACCUM_ALPHA_SIZE = 17, /* number of alpha accum bits */
+ AGL_PIXEL_SIZE = 50,
+ AGL_MINIMUM_POLICY = 51,
+ AGL_MAXIMUM_POLICY = 52,
+ AGL_OFFSCREEN = 53,
+ AGL_FULLSCREEN = 54,
+ AGL_SAMPLE_BUFFERS_ARB = 55,
+ AGL_SAMPLES_ARB = 56,
+ AGL_AUX_DEPTH_STENCIL = 57,
+ AGL_COLOR_FLOAT = 58,
+ AGL_MULTISAMPLE = 59,
+ AGL_SUPERSAMPLE = 60,
+ AGL_SAMPLE_ALPHA = 61,
+ }
+ /*
+ ** Extended attributes
+ */
+ internal enum ExtendedAttribute
+ {
+ AGL_PIXEL_SIZE = 50, /* frame buffer bits per pixel */
+ AGL_MINIMUM_POLICY = 51, /* never choose smaller buffers than requested */
+ AGL_MAXIMUM_POLICY = 52, /* choose largest buffers of type requested */
+ AGL_OFFSCREEN = 53, /* choose an off-screen capable renderer */
+ AGL_FULLSCREEN = 54, /* choose a full-screen capable renderer */
+ AGL_SAMPLE_BUFFERS_ARB = 55, /* number of multi sample buffers */
+ AGL_SAMPLES_ARB = 56, /* number of samples per multi sample buffer */
+ AGL_AUX_DEPTH_STENCIL = 57, /* independent depth and/or stencil buffers for the aux buffer */
+ AGL_COLOR_FLOAT = 58, /* color buffers store floating point pixels */
+ AGL_MULTISAMPLE = 59, /* choose multisample */
+ AGL_SUPERSAMPLE = 60, /* choose supersample */
+ AGL_SAMPLE_ALPHA = 61, /* request alpha filtering */
+ }
+ /*
+ ** Renderer management
+ */
+ internal enum RendererManagement
+ {
+ AGL_RENDERER_ID = 70, /* request renderer by ID */
+ AGL_SINGLE_RENDERER = 71, /* choose a single renderer for all screens */
+ AGL_NO_RECOVERY = 72, /* disable all failure recovery systems */
+ AGL_ACCELERATED = 73, /* choose a hardware accelerated renderer */
+ AGL_CLOSEST_POLICY = 74, /* choose the closest color buffer to request */
+ AGL_ROBUST = 75, /* renderer does not need failure recovery */
+ AGL_BACKING_STORE = 76, /* back buffer contents are valid after swap */
+ AGL_MP_SAFE = 78, /* renderer is multi-processor safe */
+
+ AGL_WINDOW = 80, /* can be used to render to a window */
+ AGL_MULTISCREEN = 81, /* single window can span multiple screens */
+ AGL_VIRTUAL_SCREEN = 82, /* virtual screen number */
+ AGL_COMPLIANT = 83, /* renderer is opengl compliant */
+
+ AGL_PBUFFER = 90, /* can be used to render to a pbuffer */
+ AGL_REMOTE_PBUFFER = 91, /* can be used to render offline to a pbuffer */
+ }
+ /*
+ ** Property names for aglDescribeRenderer
+ */
+ internal enum RendererProperties
+ {
+ /* const int AGL_OFFSCREEN = 53 */
+ /* const int AGL_FULLSCREEN = 54 */
+ /* const int AGL_RENDERER_ID = 70 */
+ /* const int AGL_ACCELERATED = 73 */
+ /* const int AGL_ROBUST = 75 */
+ /* const int AGL_BACKING_STORE = 76 */
+ /* const int AGL_MP_SAFE = 78 */
+ /* const int AGL_WINDOW = 80 */
+ /* const int AGL_MULTISCREEN = 81 */
+ /* const int AGL_COMPLIANT = 83 */
+ /* const int AGL_PBUFFER = 90 */
+ AGL_BUFFER_MODES = 100,
+ AGL_MIN_LEVEL = 101,
+ AGL_MAX_LEVEL = 102,
+ AGL_COLOR_MODES = 103,
+ AGL_ACCUM_MODES = 104,
+ AGL_DEPTH_MODES = 105,
+ AGL_STENCIL_MODES = 106,
+ AGL_MAX_AUX_BUFFERS = 107,
+ AGL_VIDEO_MEMORY = 120,
+ AGL_TEXTURE_MEMORY = 121,
+ AGL_RENDERER_COUNT = 128,
+ }
+ /*
+ ** Integer parameter names
+ */
+ internal enum ParameterNames
+ {
+ AGL_SWAP_RECT = 200, /* Enable or set the swap rectangle */
+ AGL_BUFFER_RECT = 202, /* Enable or set the buffer rectangle */
+ AGL_SWAP_LIMIT = 203, /* Enable or disable the swap async limit */
+ AGL_COLORMAP_TRACKING = 210, /* Enable or disable colormap tracking */
+ AGL_COLORMAP_ENTRY = 212, /* Set a colormap entry to {index, r, g, b} */
+ AGL_RASTERIZATION = 220, /* Enable or disable all rasterization */
+ AGL_SWAP_INTERVAL = 222, /* 0 -> Don't sync, n -> Sync every n retrace */
+ AGL_STATE_VALIDATION = 230, /* Validate state for multi-screen functionality */
+ AGL_BUFFER_NAME = 231, /* Set the buffer name. Allows for multi ctx to share a buffer */
+ AGL_ORDER_CONTEXT_TO_FRONT = 232, /* Order the current context in front of all the other contexts. */
+ AGL_CONTEXT_SURFACE_ID = 233, /* aglGetInteger only - returns the ID of the drawable surface for the context */
+ AGL_CONTEXT_DISPLAY_ID = 234, /* aglGetInteger only - returns the display ID(s) of all displays touched by the context, up to a maximum of 32 displays */
+ AGL_SURFACE_ORDER = 235, /* Position of OpenGL surface relative to window: 1 -> Above window, -1 -> Below Window */
+ AGL_SURFACE_OPACITY = 236, /* Opacity of OpenGL surface: 1 -> Surface is opaque (default), 0 -> non-opaque */
+ AGL_CLIP_REGION = 254, /* Enable or set the drawable clipping region */
+ AGL_FS_CAPTURE_SINGLE = 255, /* Enable the capture of only a single display for aglFullScreen, normally disabled */
+ AGL_SURFACE_BACKING_SIZE = 304, /* 2 params. Width/height of surface backing size */
+ AGL_ENABLE_SURFACE_BACKING_SIZE = 305, /* Enable or disable surface backing size override */
+ AGL_SURFACE_VOLATILE = 306, /* Flag surface to candidate for deletion */
+ }
+ /*
+ ** Option names for aglConfigure.
+ */
+ internal enum OptionName
+ {
+ AGL_FORMAT_CACHE_SIZE = 501, /* Set the size of the pixel format cache */
+ AGL_CLEAR_FORMAT_CACHE = 502, /* Reset the pixel format cache */
+ AGL_RETAIN_RENDERERS = 503, /* Whether to retain loaded renderers in memory */
+ }
+ /* buffer_modes */
+ internal enum BufferModes
+ {
+ AGL_MONOSCOPIC_BIT = 0x00000001,
+ AGL_STEREOSCOPIC_BIT = 0x00000002,
+ AGL_SINGLEBUFFER_BIT = 0x00000004,
+ AGL_DOUBLEBUFFER_BIT = 0x00000008,
+ }
+
+ internal enum BitDepths
+ {
+ /* bit depths */
+ AGL_0_BIT = 0x00000001,
+ AGL_1_BIT = 0x00000002,
+ AGL_2_BIT = 0x00000004,
+ AGL_3_BIT = 0x00000008,
+ AGL_4_BIT = 0x00000010,
+ AGL_5_BIT = 0x00000020,
+ AGL_6_BIT = 0x00000040,
+ AGL_8_BIT = 0x00000080,
+ AGL_10_BIT = 0x00000100,
+ AGL_12_BIT = 0x00000200,
+ AGL_16_BIT = 0x00000400,
+ AGL_24_BIT = 0x00000800,
+ AGL_32_BIT = 0x00001000,
+ AGL_48_BIT = 0x00002000,
+ AGL_64_BIT = 0x00004000,
+ AGL_96_BIT = 0x00008000,
+ AGL_128_BIT = 0x00010000,
+ }
+ /* color modes */
+ internal enum ColorModes
+ {
+ AGL_RGB8_BIT = 0x00000001, /* 8 rgb bit/pixel, RGB=7:0, inverse colormap */
+ AGL_RGB8_A8_BIT = 0x00000002, /* 8-8 argb bit/pixel, A=7:0, RGB=7:0, inverse colormap */
+ AGL_BGR233_BIT = 0x00000004, /* 8 rgb bit/pixel, B=7:6, G=5:3, R=2:0 */
+ AGL_BGR233_A8_BIT = 0x00000008, /* 8-8 argb bit/pixel, A=7:0, B=7:6, G=5:3, R=2:0 */
+ AGL_RGB332_BIT = 0x00000010, /* 8 rgb bit/pixel, R=7:5, G=4:2, B=1:0 */
+ AGL_RGB332_A8_BIT = 0x00000020, /* 8-8 argb bit/pixel, A=7:0, R=7:5, G=4:2, B=1:0 */
+ AGL_RGB444_BIT = 0x00000040, /* 16 rgb bit/pixel, R=11:8, G=7:4, B=3:0 */
+ AGL_ARGB4444_BIT = 0x00000080, /* 16 argb bit/pixel, A=15:12, R=11:8, G=7:4, B=3:0 */
+ AGL_RGB444_A8_BIT = 0x00000100, /* 8-16 argb bit/pixel, A=7:0, R=11:8, G=7:4, B=3:0 */
+ AGL_RGB555_BIT = 0x00000200, /* 16 rgb bit/pixel, R=14:10, G=9:5, B=4:0 */
+ AGL_ARGB1555_BIT = 0x00000400, /* 16 argb bit/pixel, A=15, R=14:10, G=9:5, B=4:0 */
+ AGL_RGB555_A8_BIT = 0x00000800, /* 8-16 argb bit/pixel, A=7:0, R=14:10, G=9:5, B=4:0 */
+ AGL_RGB565_BIT = 0x00001000, /* 16 rgb bit/pixel, R=15:11, G=10:5, B=4:0 */
+ AGL_RGB565_A8_BIT = 0x00002000, /* 8-16 argb bit/pixel, A=7:0, R=15:11, G=10:5, B=4:0 */
+ AGL_RGB888_BIT = 0x00004000, /* 32 rgb bit/pixel, R=23:16, G=15:8, B=7:0 */
+ AGL_ARGB8888_BIT = 0x00008000, /* 32 argb bit/pixel, A=31:24, R=23:16, G=15:8, B=7:0 */
+ AGL_RGB888_A8_BIT = 0x00010000, /* 8-32 argb bit/pixel, A=7:0, R=23:16, G=15:8, B=7:0 */
+ AGL_RGB101010_BIT = 0x00020000, /* 32 rgb bit/pixel, R=29:20, G=19:10, B=9:0 */
+ AGL_ARGB2101010_BIT = 0x00040000, /* 32 argb bit/pixel, A=31:30 R=29:20, G=19:10, B=9:0 */
+ AGL_RGB101010_A8_BIT = 0x00080000, /* 8-32 argb bit/pixel, A=7:0 R=29:20, G=19:10, B=9:0 */
+ AGL_RGB121212_BIT = 0x00100000, /* 48 rgb bit/pixel, R=35:24, G=23:12, B=11:0 */
+ AGL_ARGB12121212_BIT = 0x00200000, /* 48 argb bit/pixel, A=47:36, R=35:24, G=23:12, B=11:0 */
+ AGL_RGB161616_BIT = 0x00400000, /* 64 rgb bit/pixel, R=47:32, G=31:16, B=15:0 */
+ AGL_ARGB16161616_BIT = 0x00800000, /* 64 argb bit/pixel, A=63:48, R=47:32, G=31:16, B=15:0 */
+ AGL_INDEX8_BIT = 0x20000000, /* 8 bit color look up table (deprecated) */
+ AGL_INDEX16_BIT = 0x40000000, /* 16 bit color look up table (deprecated) */
+ AGL_RGBFLOAT64_BIT = 0x01000000, /* 64 rgb bit/pixel, half float */
+ AGL_RGBAFLOAT64_BIT = 0x02000000, /* 64 argb bit/pixel, half float */
+ AGL_RGBFLOAT128_BIT = 0x04000000, /* 128 rgb bit/pixel, ieee float */
+ AGL_RGBAFLOAT128_BIT = 0x08000000, /* 128 argb bit/pixel, ieee float */
+ AGL_RGBFLOAT256_BIT = 0x10000000, /* 256 rgb bit/pixel, ieee double */
+ AGL_RGBAFLOAT256_BIT = 0x20000000, /* 256 argb bit/pixel, ieee double */
+ }
+ /*
+ ** Error return values from aglGetError.
+ */
+ internal enum AglError
+ {
+ NoError = 0, /* no error */
+
+ BadAttribute = 10000, /* invalid pixel format attribute */
+ BadProperty = 10001, /* invalid renderer property */
+ BadPixelFormat = 10002, /* invalid pixel format */
+ BadRendererInfo = 10003, /* invalid renderer info */
+ BadContext = 10004, /* invalid context */
+ BadDrawable = 10005, /* invalid drawable */
+ BadGraphicsDevice = 10006, /* invalid graphics device */
+ BadState = 10007, /* invalid context state */
+ BadValue = 10008, /* invalid numerical value */
+ BadMatch = 10009, /* invalid share context */
+ BadEnum = 10010, /* invalid enumerant */
+ BadOffscreen = 10011, /* invalid offscreen drawable */
+ BadFullscreen = 10012, /* invalid offscreen drawable */
+ BadWindow = 10013, /* invalid window */
+ BadPointer = 10014, /* invalid pointer */
+ BadModule = 10015, /* invalid code module */
+ BadAlloc = 10016, /* memory allocation failure */
+ BadConnection = 10017, /* invalid CoreGraphics connection */
+ }
+ /************************************************************************/
+
+ /*
+ ** Pixel format functions
+ */
+ [DllImport(agl)] internal static extern AGLPixelFormat aglChoosePixelFormat(ref AGLDevice gdevs, int ndev, int []attribs);
+ ///
+ /// Use this overload only with IntPtr.Zero for the first argument.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [DllImport(agl)] internal static extern AGLPixelFormat aglChoosePixelFormat(IntPtr gdevs, int ndev, int []attribs);
+ [DllImport(agl)] internal static extern void aglDestroyPixelFormat(AGLPixelFormat pix);
+ [DllImport(agl)] internal static extern AGLPixelFormat aglNextPixelFormat(AGLPixelFormat pix);
+ [DllImport(agl)] static extern byte aglDescribePixelFormat(AGLPixelFormat pix, int attrib, out int value);
+ [Obsolete("Use aglDisplaysOfPixelFormat instead.")]
+ [DllImport(agl)] static extern AGLDevice *aglDevicesOfPixelFormat(AGLPixelFormat pix, int *ndevs);
+
+ /*
+ ** Renderer information functions
+ */
+ [DllImport(agl)] static extern AGLRendererInfo aglQueryRendererInfo(AGLDevice[] gdevs, int ndev);
+ [DllImport(agl)] static extern void aglDestroyRendererInfo(AGLRendererInfo rend);
+ [DllImport(agl)] static extern AGLRendererInfo aglNextRendererInfo(AGLRendererInfo rend);
+ [DllImport(agl)] static extern byte aglDescribeRenderer(AGLRendererInfo rend, int prop, out int value);
+
+ /*
+ ** Context functions
+ */
+ [DllImport(agl)] internal static extern AGLContext aglCreateContext(AGLPixelFormat pix, AGLContext share);
+ [DllImport(agl,EntryPoint="aglDestroyContext")] static extern byte _aglDestroyContext(AGLContext ctx);
+ internal static bool aglDestroyContext(AGLContext context)
+ {
+ return (_aglDestroyContext(context) != 0) ? true : false;
+ }
+
+ [DllImport(agl)] static extern byte aglCopyContext(AGLContext src, AGLContext dst, uint mask);
+ [DllImport(agl)] internal static extern byte aglUpdateContext(AGLContext ctx);
+
+ /*
+ ** Current state functions
+ */
+ #region --- aglSetCurrentContext ---
+
+ [DllImport(agl,EntryPoint="aglSetCurrentContext")] static extern byte _aglSetCurrentContext(AGLContext ctx);
+ internal static bool aglSetCurrentContext(IntPtr context)
+ {
+ byte retval = _aglSetCurrentContext(context);
+
+ if (retval != 0)
+ return true;
+ else
+ return false;
+ }
+
+ #endregion
+
+ [DllImport(agl)] internal static extern AGLContext aglGetCurrentContext();
+
+
+ /*
+ ** Drawable Functions
+ */
+ [DllImport(agl,EntryPoint="aglSetDrawable")]
+ static extern byte _aglSetDrawable(AGLContext ctx, AGLDrawable draw);
+
+ internal static void aglSetDrawable(AGLContext ctx, AGLDrawable draw)
+ {
+ byte retval = _aglSetDrawable(ctx, draw);
+
+ if (retval == 0)
+ {
+ AglError err = GetError();
+
+ throw new MacOSException(err, ErrorString(err));
+ }
+ }
+ [DllImport(agl)] static extern byte aglSetOffScreen(AGLContext ctx, int width, int height, int rowbytes, IntPtr baseaddr);
+ [DllImport(agl)] static extern AGLDrawable aglGetDrawable(AGLContext ctx);
+
+ [DllImport(agl, EntryPoint = "aglSetFullScreen")]
+ static extern byte _aglSetFullScreen(AGLContext ctx, int width, int height, int freq, int device);
+ internal static void aglSetFullScreen(AGLContext ctx, int width, int height, int freq, int device)
+ {
+ byte retval = _aglSetFullScreen(ctx, width, height, freq, device);
+
+ if (retval == 0)
+ {
+ AglError err = GetError();
+ Debug.Print("AGL Error: {0}", err);
+ Debug.Indent();
+ Debug.Print(ErrorString(err));
+ Debug.Unindent();
+
+ throw new MacOSException(err, ErrorString(err));
+ }
+ }
+ /*
+ ** Virtual screen functions
+ */
+ [DllImport(agl)] static extern byte aglSetVirtualScreen(AGLContext ctx, int screen);
+ [DllImport(agl)] static extern int aglGetVirtualScreen(AGLContext ctx);
+
+ /*
+ ** Obtain version numbers
+ */
+ [DllImport(agl)] static extern void aglGetVersion(int *major, int *minor);
+
+ /*
+ ** Global library options
+ */
+ [DllImport(agl)] static extern byte aglConfigure(GLenum pname, uint param);
+
+ /*
+ ** Swap functions
+ */
+ [DllImport(agl)] internal static extern void aglSwapBuffers(AGLContext ctx);
+
+ /*
+ ** Per context options
+ */
+ [DllImport(agl)] internal static extern byte aglEnable(AGLContext ctx, ParameterNames pname);
+ [DllImport(agl)] internal static extern byte aglDisable(AGLContext ctx, ParameterNames pname);
+ [DllImport(agl)] static extern byte aglIsEnabled(AGLContext ctx, GLenum pname);
+ [DllImport(agl)]
+ internal static extern byte aglSetInteger(AGLContext ctx, ParameterNames pname, ref int @params);
+ [DllImport(agl)]
+ internal static extern byte aglSetInteger(AGLContext ctx, ParameterNames pname, int []@params);
+ [DllImport(agl)]
+ static extern byte aglGetInteger(AGLContext ctx, GLenum pname, int* @params);
+
+ /*
+ ** Font function
+ */
+ // TODO: face parameter should be of type StyleParameter in QuickDraw.
+ [DllImport(agl)] static extern byte aglUseFont(AGLContext ctx, int fontID, int face, int size, int first, int count, int @base);
+
+ /*
+ ** Error functions
+ */
+ [DllImport(agl,EntryPoint="aglGetError")] internal static extern AglError GetError();
+ [DllImport(agl,EntryPoint="aglErrorString")] static extern IntPtr _aglErrorString(AglError code);
+ internal static string ErrorString(AglError code)
+ {
+ return Marshal.PtrToStringAnsi(_aglErrorString(code));
+ }
+
+ /*
+ ** Soft reset function
+ */
+ [DllImport(agl)] static extern void aglResetLibrary();
+
+ /*
+ ** Surface texture function
+ */
+ [DllImport(agl)] static extern void aglSurfaceTexture (AGLContext context, GLenum target, GLenum internalformat, AGLContext surfacecontext) ;
+
+ /*
+ ** PBuffer functions
+ */
+ [DllImport(agl)] static extern byte aglCreatePBuffer (int width, int height, GLenum target, GLenum internalFormat, long max_level, AGLPbuffer *pbuffer);
+ [DllImport(agl)] static extern byte aglDestroyPBuffer (AGLPbuffer pbuffer);
+ [DllImport(agl)] static extern byte aglDescribePBuffer (AGLPbuffer pbuffer, int *width, int *height, GLenum *target, GLenum *internalFormat, int *max_level);
+ [DllImport(agl)] static extern byte aglTexImagePBuffer (AGLContext ctx, AGLPbuffer pbuffer, int source);
+
+ /*
+ ** Pbuffer Drawable Functions
+ */
+ [DllImport(agl)] static extern byte aglSetPBuffer (AGLContext ctx, AGLPbuffer pbuffer, int face, int level, int screen) ;
+ [DllImport(agl)] static extern byte aglGetPBuffer (AGLContext ctx, AGLPbuffer *pbuffer, int *face, int *level, int *screen) ;
+
+ /*
+ ** CGL functions
+ */
+ [DllImport(agl)] static extern byte aglGetCGLContext(AGLContext ctx, void **cgl_ctx) ;
+ [DllImport(agl)] static extern byte aglGetCGLPixelFormat(AGLPixelFormat pix, void **cgl_pix);
+
+ }
+}
diff --git a/Source/OpenTK/Platform/MacOS/CarbonBindings/CarbonAPI.cs b/Source/OpenTK/Platform/MacOS/CarbonBindings/CarbonAPI.cs
new file mode 100644
index 00000000..0b28a31d
--- /dev/null
+++ b/Source/OpenTK/Platform/MacOS/CarbonBindings/CarbonAPI.cs
@@ -0,0 +1,882 @@
+//
+//
+// Carbon.cs
+//
+// Created by Erik Ylvisaker on 3/17/08.
+// Copyright 2008. All rights reserved.
+//
+//
+
+using System;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+
+namespace OpenTK.Platform.MacOS.Carbon
+{
+
+ #region --- Types defined in MacTypes.h ---
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct Point
+ {
+ internal short V;
+ internal short H;
+
+ public Point(int x, int y)
+ {
+ V = (short)x;
+ H = (short)y;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct Rect
+ {
+ short top;
+ short left;
+ short bottom;
+ short right;
+
+ internal Rect(short _left, short _top, short _width, short _height)
+ {
+ top = _top;
+ left = _left;
+ bottom = (short)(_top + _height);
+ right = (short)(_left + _width);
+ }
+
+ internal short X
+ {
+ get { return left; }
+ set
+ {
+ short width = Width;
+ left = value;
+ right = (short)(left + width);
+ }
+ }
+ internal short Y
+ {
+ get { return top; }
+ set
+ {
+ short height = Height;
+ top = value;
+ bottom = (short)(top + height);
+ }
+ }
+ internal short Width
+ {
+ get { return (short)(right - left); }
+ set { right = (short)(left + value); }
+ }
+ internal short Height
+ {
+ get { return (short)(bottom - top); }
+ set { bottom = (short)(top + value); }
+ }
+
+ public override string ToString()
+ {
+ return string.Format(
+ "Rect: [{0}, {1}, {2}, {3}]", X, Y, Width, Height);
+ }
+ }
+
+ #endregion
+ #region --- Types defined in HIGeometry.h ---
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct HIPoint
+ {
+ public float X;
+ public float Y;
+ }
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct HISize
+ {
+ public float Width;
+ public float Height;
+ }
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct HIRect
+ {
+ public HIPoint Origin;
+ public HISize Size;
+
+ public override string ToString()
+ {
+ return string.Format(
+ "Rect: [{0}, {1}, {2}, {3}]", Origin.X, Origin.Y, Size.Width, Size.Height);
+ }
+ }
+
+ #endregion
+
+ #region --- Types defined in CarbonEvents.h ---
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct EventTypeSpec
+ {
+ internal EventTypeSpec(EventClass evtClass, AppEventKind evtKind)
+ {
+ this.EventClass = evtClass;
+ this.EventKind = (uint)evtKind;
+ }
+ internal EventTypeSpec(EventClass evtClass, AppleEventKind appleKind)
+ {
+ this.EventClass = evtClass;
+ this.EventKind = (uint)appleKind;
+ }
+ internal EventTypeSpec(EventClass evtClass, MouseEventKind evtKind)
+ {
+ this.EventClass = evtClass;
+ this.EventKind = (uint)evtKind;
+ }
+ internal EventTypeSpec(EventClass evtClass, KeyboardEventKind evtKind)
+ {
+ this.EventClass = evtClass;
+ this.EventKind = (uint)evtKind;
+ }
+ internal EventTypeSpec(EventClass evtClass, WindowEventKind evtKind)
+ {
+ this.EventClass = evtClass;
+ this.EventKind = (uint)evtKind;
+ }
+
+ internal EventClass EventClass;
+ internal uint EventKind;
+ }
+
+ public enum EventClass : int
+ {
+ /*
+ kEventClassMouse = FOUR_CHAR_CODE('mous'),
+ kEventClassKeyboard = FOUR_CHAR_CODE('keyb'),
+ kEventClassTextInput = FOUR_CHAR_CODE('text'),
+ kEventClassApplication = FOUR_CHAR_CODE('appl'),
+ kEventClassAppleEvent = FOUR_CHAR_CODE('eppc'),
+ kEventClassMenu = FOUR_CHAR_CODE('menu'),
+ kEventClassWindow = FOUR_CHAR_CODE('wind'),
+ kEventClassControl = FOUR_CHAR_CODE('cntl'),
+ kEventClassCommand = FOUR_CHAR_CODE('cmds')
+ */
+ Mouse = 0x6d6f7573,
+ Keyboard = 0x6b657962,
+ Application = 0x6170706c,
+ AppleEvent = 0x65707063,
+ Menu = 0x6d656e75,
+ Window = 0x77696e64,
+ }
+ public enum WindowEventKind : int
+ {
+ // window events
+ WindowUpdate = 1,
+ WindowDrawContent = 2,
+ WindowDrawStructure = 3,
+ WindowEraseContent = 4,
+ WindowActivate = 5,
+ WindowDeactivate = 6,
+ WindowSizeChanged = 23,
+ WindowBoundsChanging = 26,
+ WindowBoundsChanged = 27,
+ WindowClickDragRgn = 32,
+ WindowClickResizeRgn = 33,
+ WindowClickCollapseRgn = 34,
+ WindowClickCloseRgn = 35,
+ WindowClickZoomRgn = 36,
+ WindowClickContentRgn = 37,
+ WindowClickProxyIconRgn = 38,
+ WindowClose = 72,
+ WindowClosed = 73,
+ }
+ public enum MouseEventKind : int
+ {
+ MouseDown = 1,
+ MouseUp = 2,
+ MouseMoved = 5,
+ MouseDragged = 6,
+ MouseEntered = 8,
+ MouseExited = 9,
+ WheelMoved = 10,
+ }
+ public enum MouseButton : short
+ {
+ Primary = 1,
+ Secondary = 2,
+ Tertiary = 3,
+ }
+
+ public enum KeyboardEventKind : int
+ {
+ // raw keyboard events
+ RawKeyDown = 1,
+ RawKeyRepeat = 2,
+ RawKeyUp = 3,
+ RawKeyModifiersChanged = 4,
+ }
+
+ public enum AppEventKind : int
+ {
+ // application events
+ AppActivated = 1,
+ AppDeactivated = 2,
+ AppQuit = 3,
+ AppLaunchNotification = 4,
+ }
+
+ enum AppleEventKind : int
+ {
+ AppleEvent = 1,
+ }
+
+ internal enum EventParamName : int
+ {
+ // Mouse Events
+ MouseLocation = 0x6d6c6f63, // typeHIPoint
+ WindowMouseLocation = 0x776d6f75, // typeHIPoint
+ MouseButton = 0x6d62746e, // typeMouseButton
+ ClickCount = 0x63636e74, // typeUInt32
+ MouseWheelAxis = 0x6d776178, // typeMouseWheelAxis
+ MouseWheelDelta = 0x6d77646c, // typeSInt32
+ MouseDelta = 0x6d647461, // typeHIPoint
+
+ // Keyboard events
+ KeyCode = 0x6b636f64, // typeUInt32
+ KeyMacCharCode = 0x6b636872, // typechar
+ KeyModifiers = 0x6b6d6f64, // typeUInt32
+
+ }
+ internal enum EventParamType : int
+ {
+ typeMouseButton = 0x6d62746e,
+ typeMouseWheelAxis = 0x6d776178,
+ typeHIPoint = 0x68697074,
+ typeHISize = 0x6869737a,
+ typeHIRect = 0x68697263,
+
+ typeChar = 0x54455854,
+
+ typeUInt32 = 0x6d61676e,
+ typeSInt32 = 0x6c6f6e67,
+ typeSInt16 = 0x73686f72,
+ typeSInt64 = 0x636f6d70,
+ typeIEEE32BitFloatingPoint = 0x73696e67,
+ typeIEEE64BitFloatingPoint = 0x646f7562,
+ }
+
+ public enum EventMouseButton : int
+ {
+ Primary = 0,
+ Secondary = 1,
+ Tertiary = 2,
+ }
+
+ internal enum WindowRegionCode : int
+ {
+ TitleBarRegion = 0,
+ TitleTextRegion = 1,
+ CloseBoxRegion = 2,
+ ZoomBoxRegion = 3,
+ DragRegion = 5,
+ GrowRegion = 6,
+ CollapseBoxRegion = 7,
+ TitleProxyIconRegion = 8,
+ StructureRegion = 32,
+ ContentRegion = 33,
+ UpdateRegion = 34,
+ OpaqueRegion = 35,
+ GlobalPortRegion = 40,
+ ToolbarButtonRegion = 41
+ };
+
+ #endregion
+
+ #region --- MacWindows.h ---
+
+ internal enum WindowClass : uint
+ {
+ Alert = 1, /* "I need your attention now."*/
+ MovableAlert = 2, /* "I need your attention now, but I'm kind enough to let you switch out of this app to do other things."*/
+ Modal = 3, /* system modal, not draggable*/
+ MovableModal = 4, /* application modal, draggable*/
+ Floating = 5, /* floats above all other application windows*/
+ Document = 6, /* document windows*/
+ Desktop = 7, /* desktop window (usually only one of these exists) - OS X only in CarbonLib 1.0*/
+ Utility = 8, /* Available in CarbonLib 1.1 and later, and in Mac OS X*/
+ Help = 10, /* Available in CarbonLib 1.1 and later, and in Mac OS X*/
+ Sheet = 11, /* Available in CarbonLib 1.3 and later, and in Mac OS X*/
+ Toolbar = 12, /* Available in CarbonLib 1.1 and later, and in Mac OS X*/
+ Plain = 13, /* Available in CarbonLib 1.2.5 and later, and Mac OS X*/
+ Overlay = 14, /* Available in Mac OS X*/
+ SheetAlert = 15, /* Available in CarbonLib 1.3 and later, and in Mac OS X 10.1 and later*/
+ AltPlain = 16, /* Available in CarbonLib 1.3 and later, and in Mac OS X 10.1 and later*/
+ Drawer = 20, /* Available in Mac OS X 10.2 or later*/
+ All = 0xFFFFFFFFu /* for use with GetFrontWindowOfClass, FindWindowOfClass, GetNextWindowOfClass*/
+ }
+
+ [Flags]
+ internal enum WindowAttributes : uint
+ {
+ NoAttributes = 0u, /* no attributes*/
+ CloseBox = (1u << 0), /* window has a close box*/
+ HorizontalZoom = (1u << 1), /* window has horizontal zoom box*/
+ VerticalZoom = (1u << 2), /* window has vertical zoom box*/
+ FullZoom = (VerticalZoom | HorizontalZoom),
+ CollapseBox = (1u << 3), /* window has a collapse box*/
+ Resizable = (1u << 4), /* window is resizable*/
+ SideTitlebar = (1u << 5), /* window wants a titlebar on the side (floating window class only)*/
+ NoUpdates = (1u << 16), /* this window receives no update events*/
+ NoActivates = (1u << 17), /* this window receives no activate events*/
+ NoBuffering = (1u << 20), /* this window is not buffered (Mac OS X only)*/
+ StandardHandler = (1u << 25),
+ InWindowMenu = (1u << 27),
+ LiveResize = (1u << 28),
+ StandardDocument = (CloseBox | FullZoom | CollapseBox | Resizable),
+ StandardFloating = (CloseBox | CollapseBox)
+ }
+
+ internal enum WindowPositionMethod : uint
+ {
+ CenterOnMainScreen = 1,
+ CenterOnParentWindow = 2,
+ CenterOnParentWindowScreen = 3,
+ CascadeOnMainScreen = 4,
+ CascadeOnParentWindow = 5,
+ CascadeOnParentWindowScreen = 6,
+ CascadeStartAtParentWindowScreen = 10,
+ AlertPositionOnMainScreen = 7,
+ AlertPositionOnParentWindow = 8,
+ AlertPositionOnParentWindowScreen = 9
+ }
+
+ internal delegate OSStatus MacOSEventHandler(IntPtr inCaller, IntPtr inEvent, IntPtr userData);
+
+ internal enum WindowPartCode : short
+ {
+ inDesk = 0,
+ inNoWindow = 0,
+ inMenuBar = 1,
+ inSysWindow = 2,
+ inContent = 3,
+ inDrag = 4,
+ inGrow = 5,
+ inGoAway = 6,
+ inZoomIn = 7,
+ inZoomOut = 8,
+ inCollapseBox = 11,
+ inProxyIcon = 12,
+ inToolbarButton = 13,
+ inStructure = 15,
+ }
+
+ #endregion
+
+ #region --- Carbon API Methods ---
+
+ public partial class API
+ {
+ const string carbon = "/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon";
+
+ [DllImport(carbon)]
+ internal static extern EventClass GetEventClass(IntPtr inEvent);
+ [DllImport(carbon)]
+ internal static extern uint GetEventKind(IntPtr inEvent);
+
+ #region --- Window Construction ---
+
+ [DllImport(carbon,EntryPoint="CreateNewWindow")]
+ private static extern OSStatus _CreateNewWindow(WindowClass @class, WindowAttributes attributes, ref Rect r, out IntPtr window);
+
+ internal static IntPtr CreateNewWindow(WindowClass @class, WindowAttributes attributes, Rect r)
+ {
+ IntPtr retval;
+ OSStatus stat = _CreateNewWindow(@class, attributes, ref r, out retval);
+
+ Debug.Print("Created Window: {0}", retval);
+
+ if (stat != OSStatus.NoError)
+ {
+ throw new MacOSException(stat);
+ }
+
+ return retval;
+ }
+
+ [DllImport(carbon)]
+ internal static extern void DisposeWindow(IntPtr window);
+
+ #endregion
+ #region --- Showing / Hiding Windows ---
+
+ [DllImport(carbon)]
+ internal static extern void ShowWindow(IntPtr window);
+ [DllImport(carbon)]
+ internal static extern void HideWindow(IntPtr window);
+ [DllImport(carbon)]
+ internal static extern bool IsWindowVisible(IntPtr window);
+ [DllImport(carbon)]
+ internal static extern void SelectWindow(IntPtr window);
+
+ #endregion
+ #region --- Window Boundaries ---
+
+ [DllImport(carbon)]
+ internal static extern OSStatus RepositionWindow(IntPtr window, IntPtr parentWindow, WindowPositionMethod method);
+ [DllImport(carbon)]
+ internal static extern void SizeWindow(IntPtr window, short w, short h, bool fUpdate);
+
+ [DllImport(carbon)]
+ static extern OSStatus GetWindowBounds(IntPtr window, WindowRegionCode regionCode, out Rect globalBounds);
+ internal static Rect GetWindowBounds(IntPtr window, WindowRegionCode regionCode)
+ {
+ Rect retval;
+ OSStatus result = GetWindowBounds(window, regionCode, out retval);
+
+ if (result != OSStatus.NoError)
+ throw new MacOSException(result);
+
+ return retval;
+ }
+
+ //[DllImport(carbon)]
+ //internal static extern void MoveWindow(IntPtr window, short hGlobal, short vGlobal, bool front);
+
+ #endregion
+ #region --- Processing Events ---
+
+ [DllImport(carbon)]
+ static extern IntPtr GetEventDispatcherTarget();
+
+ [DllImport(carbon,EntryPoint="ReceiveNextEvent")]
+ static extern OSStatus ReceiveNextEvent(uint inNumTypes,
+ IntPtr inList,
+ double inTimeout,
+ bool inPullEvent,
+ out IntPtr outEvent);
+
+ [DllImport(carbon)]
+ static extern void SendEventToEventTarget(IntPtr theEvent, IntPtr theTarget);
+
+ [DllImport(carbon)]
+ static extern void ReleaseEvent(IntPtr theEvent);
+
+ // Processes events in the queue and then returns.
+ internal static void ProcessEvents()
+ {
+ IntPtr theEvent;
+ IntPtr theTarget = GetEventDispatcherTarget();
+
+ for (;;)
+ {
+ OSStatus status = ReceiveNextEvent(0, IntPtr.Zero, 0.0, true, out theEvent);
+
+ if (status == OSStatus.EventLoopTimedOut)
+ break;
+
+ if (status != OSStatus.NoError)
+ {
+ Debug.Print("Message Loop status: {0}", status);
+ break;
+ }
+ if (theEvent == IntPtr.Zero)
+ break;
+
+ 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
+ {
+ public ushort what;
+ public uint message;
+ public uint when;
+ public Point where;
+ public uint modifiers;
+ }
+
+ [DllImport(carbon)]
+ static extern bool ConvertEventRefToEventRecord(IntPtr inEvent, out EventRecord outEvent);
+
+ [DllImport(carbon)]
+ static extern OSStatus AEProcessAppleEvent(ref EventRecord theEventRecord);
+
+ static internal void ProcessAppleEvent(IntPtr inEvent)
+ {
+ EventRecord record;
+
+ ConvertEventRefToEventRecord(inEvent, out record);
+ AEProcessAppleEvent(ref record);
+ }
+
+ #endregion
+
+ #endregion
+ #region --- Getting Event Parameters ---
+
+ [DllImport(carbon)]
+ static extern OSStatus GetEventParameter(
+ IntPtr inEvent, EventParamName inName, EventParamType inDesiredType,
+ IntPtr outActualType, uint inBufferSize, IntPtr outActualSize, IntPtr outData);
+
+ static internal MacOSKeyCode GetEventKeyboardKeyCode(IntPtr inEvent)
+ {
+ int code;
+
+ unsafe
+ {
+ int* codeAddr = &code;
+
+ OSStatus result = API.GetEventParameter(inEvent,
+ EventParamName.KeyCode, EventParamType.typeUInt32, IntPtr.Zero,
+ (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(UInt32)), IntPtr.Zero,
+ (IntPtr) codeAddr);
+
+ if (result != OSStatus.NoError)
+ {
+ throw new MacOSException(result);
+ }
+ }
+
+ return (MacOSKeyCode)code;
+ }
+
+ internal static char GetEventKeyboardChar(IntPtr inEvent)
+ {
+ char code;
+
+ unsafe
+ {
+ char* codeAddr = &code;
+
+ OSStatus result = API.GetEventParameter(inEvent,
+ EventParamName.KeyMacCharCode, EventParamType.typeChar, IntPtr.Zero,
+ (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(char)), IntPtr.Zero,
+ (IntPtr)codeAddr);
+
+ if (result != OSStatus.NoError)
+ {
+ throw new MacOSException(result);
+ }
+ }
+
+ return code;
+ }
+
+ static internal MouseButton GetEventMouseButton(IntPtr inEvent)
+ {
+ int button;
+
+ unsafe
+ {
+ int* btn = &button;
+
+ OSStatus result = API.GetEventParameter(inEvent,
+ EventParamName.MouseButton, EventParamType.typeMouseButton, IntPtr.Zero,
+ (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(short)), IntPtr.Zero,
+ (IntPtr)btn);
+
+ if (result != OSStatus.NoError)
+ throw new MacOSException(result);
+ }
+
+ return (MouseButton)button;
+ }
+ static internal OSStatus GetEventWindowMouseLocation(IntPtr inEvent, out HIPoint pt)
+ {
+ HIPoint point;
+
+ unsafe
+ {
+ HIPoint* parm = &point;
+
+ OSStatus result = API.GetEventParameter(inEvent,
+ EventParamName.WindowMouseLocation, EventParamType.typeHIPoint, IntPtr.Zero,
+ (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(HIPoint)), IntPtr.Zero,
+ (IntPtr)parm);
+
+ pt = point;
+
+ return result;
+ }
+
+ }
+ static internal OSStatus GetEventMouseLocation(IntPtr inEvent, out HIPoint pt)
+ {
+ HIPoint point;
+
+ unsafe
+ {
+ HIPoint* parm = &point;
+
+ OSStatus result = API.GetEventParameter(inEvent,
+ EventParamName.MouseLocation, EventParamType.typeHIPoint, IntPtr.Zero,
+ (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(HIPoint)), IntPtr.Zero,
+ (IntPtr)parm);
+
+ pt = point;
+
+ return result;
+ }
+
+ }
+ static internal MacOSKeyModifiers GetEventKeyModifiers(IntPtr inEvent)
+ {
+ uint code;
+
+ unsafe
+ {
+ uint* codeAddr = &code;
+
+ OSStatus result = API.GetEventParameter(inEvent,
+ EventParamName.KeyModifiers, EventParamType.typeUInt32, IntPtr.Zero,
+ (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(uint)), IntPtr.Zero,
+ (IntPtr)codeAddr);
+
+ if (result != OSStatus.NoError)
+ {
+ throw new MacOSException(result);
+ }
+ }
+
+ return (MacOSKeyModifiers)code;
+ }
+
+ #endregion
+ #region --- Event Handlers ---
+
+ [DllImport(carbon,EntryPoint="InstallEventHandler")]
+ static extern OSStatus _InstallEventHandler(
+ IntPtr eventTargetRef, IntPtr handlerProc,
+ int numtypes, EventTypeSpec[] typeList,
+ IntPtr userData, IntPtr handlerRef);
+
+ internal static void InstallWindowEventHandler(IntPtr windowRef, IntPtr uppHandlerProc,
+ EventTypeSpec[] eventTypes, IntPtr userData, IntPtr handlerRef)
+ {
+ IntPtr windowTarget = GetWindowEventTarget(windowRef);
+
+ Debug.Print("Window: {0}", windowRef);
+ Debug.Print("Window Target: {0}", windowTarget);
+ Debug.Print("Handler: {0}", uppHandlerProc);
+ Debug.Print("Num Events: {0}", eventTypes.Length);
+ Debug.Print("User Data: {0}", userData);
+ Debug.Print("Handler Ref: {0}", handlerRef);
+
+ OSStatus error = _InstallEventHandler(windowTarget, uppHandlerProc,
+ eventTypes.Length, eventTypes,
+ userData, handlerRef);
+
+ Debug.Print("Status: {0}", error);
+
+ if (error != OSStatus.NoError)
+ {
+ throw new MacOSException(error);
+ }
+ }
+
+ internal static void InstallApplicationEventHandler(IntPtr uppHandlerProc,
+ EventTypeSpec[] eventTypes, IntPtr userData, IntPtr handlerRef)
+ {
+
+ OSStatus error = _InstallEventHandler(GetApplicationEventTarget(), uppHandlerProc,
+ eventTypes.Length, eventTypes,
+ userData, handlerRef);
+
+ if (error != OSStatus.NoError)
+ {
+ throw new MacOSException(error);
+ }
+
+ }
+
+ [DllImport(carbon)]
+ internal static extern OSStatus RemoveEventHandler(IntPtr inHandlerRef);
+
+ #endregion
+ #region --- GetWindowEventTarget ---
+
+ [DllImport(carbon)]
+ internal static extern IntPtr GetWindowEventTarget(IntPtr window);
+
+ [DllImport(carbon)]
+ internal static extern IntPtr GetApplicationEventTarget();
+
+ #endregion
+ #region --- UPP Event Handlers ---
+
+ [DllImport(carbon)]
+ internal static extern IntPtr NewEventHandlerUPP(MacOSEventHandler handler);
+
+ [DllImport(carbon)]
+ internal static extern void DisposeEventHandlerUPP(IntPtr userUPP);
+
+ #endregion
+
+ [DllImport(carbon)]
+ static extern IntPtr GetControlBounds(IntPtr control, out Rect bounds);
+
+ internal static Rect GetControlBounds(IntPtr control)
+ {
+ Rect retval;
+ GetControlBounds(control, out retval);
+
+ return retval;
+ }
+
+ [DllImport(carbon)]
+ internal static extern OSStatus ActivateWindow (IntPtr inWindow, bool inActivate);
+
+ [DllImport(carbon)]
+ internal static extern void RunApplicationEventLoop();
+
+ [DllImport(carbon)]
+ internal static extern void QuitApplicationEventLoop();
+
+ [DllImport(carbon)]
+ internal static extern IntPtr GetControlOwner(IntPtr control);
+
+ [DllImport(carbon)]
+ internal static extern IntPtr HIViewGetWindow(IntPtr inView);
+
+ [DllImport(carbon)]
+ static extern OSStatus HIViewGetFrame(IntPtr inView, out HIRect outRect);
+ internal static HIRect HIViewGetFrame(IntPtr inView)
+ {
+ HIRect retval;
+ OSStatus result = HIViewGetFrame(inView, out retval);
+
+ if (result != OSStatus.NoError)
+ throw new MacOSException(result);
+
+ return retval;
+ }
+ #region --- SetWindowTitle ---
+
+ [DllImport(carbon)]
+ static extern void SetWindowTitleWithCFString(IntPtr windowRef, IntPtr title);
+
+ internal 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
+ // causes the program to crash on the fourth window created. But I am
+ // afraid that not releasing the string would result in a memory leak, but that would
+ // only be a serious issue if the window title is changed a lot.
+ //CFRelease(str);
+ }
+
+ #endregion
+
+ [DllImport(carbon,EntryPoint="ChangeWindowAttributes")]
+ static extern OSStatus _ChangeWindowAttributes(IntPtr windowRef, WindowAttributes setTheseAttributes, WindowAttributes clearTheseAttributes);
+ internal static void ChangeWindowAttributes(IntPtr windowRef, WindowAttributes setTheseAttributes, WindowAttributes clearTheseAttributes)
+ {
+ OSStatus error = _ChangeWindowAttributes(windowRef, setTheseAttributes, clearTheseAttributes);
+
+ if (error != OSStatus.NoError)
+ {
+ throw new MacOSException(error);
+ }
+ }
+
+ [DllImport(carbon)]
+ static extern IntPtr __CFStringMakeConstantString(string cStr);
+
+ [DllImport(carbon)]
+ static extern void CFRelease(IntPtr cfStr);
+
+ [DllImport(carbon)]
+ internal static extern OSStatus CallNextEventHandler(IntPtr nextHandler, IntPtr theEvent);
+
+ [DllImport(carbon)]
+ internal static extern IntPtr GetWindowPort(IntPtr windowRef);
+
+ #region --- Menus ---
+
+ [DllImport(carbon)]
+ internal static extern IntPtr AcquireRootMenu();
+
+
+ #endregion
+
+ [DllImport(carbon)]
+ internal static extern bool IsWindowCollapsed(IntPtr windowRef);
+
+ [DllImport(carbon, EntryPoint = "CollapseWindow")]
+ static extern OSStatus _CollapseWindow(IntPtr windowRef, bool collapse);
+
+ internal static void CollapseWindow(IntPtr windowRef, bool collapse)
+ {
+ OSStatus error = _CollapseWindow(windowRef, collapse);
+
+ if (error != OSStatus.NoError)
+ {
+ throw new MacOSException(error);
+ }
+ }
+
+ [DllImport(carbon, EntryPoint="IsWindowInStandardState")]
+ static extern bool _IsWindowInStandardState(IntPtr windowRef, IntPtr inIdealSize, IntPtr outIdealStandardState);
+
+ internal static bool IsWindowInStandardState(IntPtr windowRef)
+ {
+ return _IsWindowInStandardState(windowRef, IntPtr.Zero, IntPtr.Zero);
+ }
+
+ [DllImport(carbon, EntryPoint = "ZoomWindowIdeal")]
+ unsafe static extern OSStatus _ZoomWindowIdeal(IntPtr windowRef, short inPartCode, IntPtr toIdealSize);
+
+ internal static void ZoomWindowIdeal(IntPtr windowRef, WindowPartCode inPartCode, ref Point toIdealSize)
+ {
+ Point pt = toIdealSize;
+ OSStatus error ;
+ IntPtr handle = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Point)));
+ Marshal.StructureToPtr(toIdealSize, handle, false);
+
+ error = _ZoomWindowIdeal(windowRef, (short)inPartCode, handle);
+
+ toIdealSize = (Point)Marshal.PtrToStructure(handle,typeof(Point));
+
+ Marshal.FreeHGlobal(handle);
+
+ if (error != OSStatus.NoError)
+ {
+ throw new MacOSException(error);
+ }
+ }
+
+ [DllImport(carbon)]
+ internal unsafe static extern OSStatus DMGetGDeviceByDisplayID(
+ IntPtr displayID, out IntPtr displayDevice, Boolean failToMain);
+
+
+ }
+
+ #endregion
+
+}
+
+
diff --git a/Source/OpenTK/Platform/MacOS/CarbonBindings/CoreFoundation.cs b/Source/OpenTK/Platform/MacOS/CarbonBindings/CoreFoundation.cs
new file mode 100644
index 00000000..58bdcb50
--- /dev/null
+++ b/Source/OpenTK/Platform/MacOS/CarbonBindings/CoreFoundation.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace OpenTK.Platform.MacOS.Carbon
+{
+ struct CFArray
+ {
+ IntPtr arrayRef;
+ public IntPtr Ref { get { return arrayRef; } set { arrayRef = value; } }
+
+ public CFArray(IntPtr reference)
+ {
+ arrayRef = reference;
+ }
+
+ public int Count
+ {
+ get { return CF.CFArrayGetCount(arrayRef); }
+ }
+ public IntPtr this[int index]
+ {
+ get
+ {
+ if (index >= Count || index < 0)
+ throw new IndexOutOfRangeException();
+
+ return CF.CFArrayGetValueAtIndex(arrayRef, index);
+ }
+ }
+ }
+ struct CFDictionary
+ {
+ public CFDictionary(IntPtr reference)
+ {
+ dictionaryRef = reference;
+ }
+
+ IntPtr dictionaryRef;
+ public IntPtr Ref { get { return dictionaryRef; } set { dictionaryRef = value; } }
+
+ public int Count
+ {
+ get
+ {
+ return CF.CFDictionaryGetCount(dictionaryRef);
+ }
+ }
+ public double GetNumberValue(string key)
+ {
+ unsafe
+ {
+ double retval;
+ IntPtr cfnum = CF.CFDictionaryGetValue(dictionaryRef,
+ CF.CFSTR(key));
+
+ CF.CFNumberGetValue(cfnum, CF.CFNumberType.kCFNumberDoubleType, &retval);
+
+ return retval;
+ }
+ }
+ }
+ class CF
+ {
+ const string appServices = "/System/Library/Frameworks/ApplicationServices.framework/Versions/Current/ApplicationServices";
+
+ [DllImport(appServices)]
+ internal static extern int CFArrayGetCount(IntPtr theArray);
+
+ [DllImport(appServices)]
+ internal static extern IntPtr CFArrayGetValueAtIndex(IntPtr theArray, int idx);
+
+ [DllImport(appServices)]
+ internal static extern int CFDictionaryGetCount(IntPtr theDictionary);
+
+ [DllImport(appServices)]
+ internal static extern IntPtr CFDictionaryGetValue(IntPtr theDictionary, IntPtr theKey);
+
+ // this mirrors the definition in CFString.h.
+ // I don't know why, but __CFStringMakeConstantString is marked as "private and should not be used directly"
+ // even though the CFSTR macro just calls it.
+ [DllImport(appServices)]
+ static extern IntPtr __CFStringMakeConstantString(string cStr);
+ internal static IntPtr CFSTR(string cStr)
+ {
+ return __CFStringMakeConstantString(cStr);
+ }
+
+ [DllImport(appServices)]
+ internal unsafe static extern bool CFNumberGetValue (IntPtr number, CFNumberType theType, int* valuePtr);
+ [DllImport(appServices)]
+ internal unsafe static extern bool CFNumberGetValue(IntPtr number, CFNumberType theType, double* valuePtr);
+
+ internal enum CFNumberType
+ {
+ kCFNumberSInt8Type = 1,
+ kCFNumberSInt16Type = 2,
+ kCFNumberSInt32Type = 3,
+ kCFNumberSInt64Type = 4,
+ kCFNumberFloat32Type = 5,
+ kCFNumberFloat64Type = 6,
+ kCFNumberCharType = 7,
+ kCFNumberShortType = 8,
+ kCFNumberIntType = 9,
+ kCFNumberLongType = 10,
+ kCFNumberLongLongType = 11,
+ kCFNumberFloatType = 12,
+ kCFNumberDoubleType = 13,
+ kCFNumberCFIndexType = 14,
+ kCFNumberNSIntegerType = 15,
+ kCFNumberCGFloatType = 16,
+ kCFNumberMaxType = 16
+ };
+ }
+}
diff --git a/Source/OpenTK/Platform/MacOS/CarbonBindings/MacOSKeys.cs b/Source/OpenTK/Platform/MacOS/CarbonBindings/MacOSKeys.cs
new file mode 100644
index 00000000..070dc1ac
--- /dev/null
+++ b/Source/OpenTK/Platform/MacOS/CarbonBindings/MacOSKeys.cs
@@ -0,0 +1,127 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace OpenTK.Platform.MacOS.Carbon
+{
+ enum MacOSKeyCode
+ {
+ A = 0,
+ B = 11,
+ C = 8,
+ D = 2,
+ E = 14,
+ F = 3,
+ G = 5,
+ H = 4,
+ I = 34,
+ J = 38,
+ K = 40,
+ L = 37,
+ M = 46,
+ N = 45,
+ O = 31,
+ P = 35,
+ Q = 12,
+ R = 15,
+ S = 1,
+ T = 17,
+ U = 32,
+ V = 9,
+ W = 13,
+ X = 7,
+ Y = 16,
+ Z = 6,
+
+ Key_1 = 18,
+ Key_2 = 19,
+ Key_3 = 20,
+ Key_4 = 21,
+ Key_5 = 23,
+ Key_6 = 22,
+ Key_7 = 26,
+ Key_8 = 28,
+ Key_9 = 25,
+ Key_0 = 29,
+
+ Space = 49,
+ Tilde = 50,
+
+ Minus = 27,
+ Equals = 24,
+ BracketLeft = 33,
+ BracketRight = 30,
+ Backslash = 42,
+ Semicolon = 41,
+ Quote = 39,
+ Comma = 43,
+ Period = 47,
+ Slash = 44,
+
+ Enter = 36,
+ Tab = 48,
+ Backspace = 51,
+ Return = 52,
+ Esc = 53,
+ KeyPad_Decimal = 65,
+ KeyPad_Multiply = 67,
+ KeyPad_Add = 69,
+ KeyPad_Divide = 75,
+ KeyPad_Enter = 76,
+ KeyPad_Subtract = 78,
+ KeyPad_Equal = 81,
+ KeyPad_0 = 82,
+ KeyPad_1 = 83,
+ KeyPad_2 = 84,
+ KeyPad_3 = 85,
+ KeyPad_4 = 86,
+ KeyPad_5 = 87,
+ KeyPad_6 = 88,
+ KeyPad_7 = 89,
+ KeyPad_8 = 91,
+ KeyPad_9 = 92,
+ F1 = 122,
+ F2 = 120,
+ F3 = 99,
+ F4 = 118,
+ F5 = 96,
+ F6 = 97,
+ F7 = 98,
+ F8 = 100,
+ F9 = 101,
+ F10 = 109,
+ F11 = 103,
+ F12 = 111,
+ F13 = 105,
+ F14 = 107,
+ F15 = 113,
+
+ Menu = 110,
+
+ Insert = 114,
+ Home = 115,
+ Pageup = 116,
+ Del = 117,
+ End = 119,
+ Pagedown = 121,
+ Up = 126,
+ Down = 125,
+ Left = 123,
+ Right = 124,
+
+
+ }
+ [Flags]
+ enum MacOSKeyModifiers
+ {
+ None = 0,
+ Shift = 0x0200,
+ CapsLock = 0x0400,
+ Control = 0x1000, //
+ Command = 0x0100, // Open-Apple - Windows key
+ Option = 0x0800, // Option key is same position as the alt key on non-mac keyboards.
+ }
+ partial class API
+ {
+ }
+}
diff --git a/Source/OpenTK/Platform/MacOS/CarbonBindings/QuartzDisplayServicesAPI.cs b/Source/OpenTK/Platform/MacOS/CarbonBindings/QuartzDisplayServicesAPI.cs
new file mode 100644
index 00000000..59c95c94
--- /dev/null
+++ b/Source/OpenTK/Platform/MacOS/CarbonBindings/QuartzDisplayServicesAPI.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+
+
+namespace OpenTK.Platform.MacOS.Carbon
+{
+ // Quartz Display services used here are available in MacOS X 10.3 and later.
+
+ enum CGDisplayErr
+ {
+
+ }
+
+ public static class CG
+ {
+ const string appServices = "/System/Library/Frameworks/ApplicationServices.framework/Versions/Current/ApplicationServices";
+
+ // CGPoint -> HIPoint
+ // CGSize -> HISize
+ // CGRect -> HIRect
+
+ [DllImport(appServices,EntryPoint="CGGetActiveDisplayList")]
+ internal unsafe static extern CGDisplayErr GetActiveDisplayList(int maxDisplays, IntPtr* activeDspys, out int dspyCnt);
+
+ [DllImport(appServices,EntryPoint="CGMainDisplayID")]
+ internal static extern IntPtr MainDisplayID();
+
+ [DllImport(appServices,EntryPoint="CGDisplayPixelsWide")]
+ internal static extern int DisplayPixelsWide(IntPtr display);
+
+ [DllImport(appServices,EntryPoint="CGDisplayPixelsHigh")]
+ internal static extern int DisplayPixelsHigh(IntPtr display);
+
+ [DllImport(appServices,EntryPoint="CGDisplayCurrentMode")]
+ internal static extern IntPtr DisplayCurrentMode(IntPtr display);
+
+ [DllImport(appServices,EntryPoint="CGDisplayCapture")]
+ internal static extern CGDisplayErr DisplayCapture(IntPtr display);
+
+ [DllImport(appServices,EntryPoint="CGDisplayRelease")]
+ internal static extern CGDisplayErr DisplayRelease(IntPtr display);
+
+ [DllImport(appServices, EntryPoint = "CGDisplayAvailableModes")]
+ internal static extern IntPtr DisplayAvailableModes(IntPtr display);
+
+ [DllImport(appServices, EntryPoint = "CGDisplaySwitchToMode")]
+ internal static extern IntPtr DisplaySwitchToMode(IntPtr display, IntPtr displayMode);
+
+ }
+}
diff --git a/Source/OpenTK/Platform/MacOS/CarbonBindings/SpeechChannel.cs b/Source/OpenTK/Platform/MacOS/CarbonBindings/SpeechChannel.cs
new file mode 100644
index 00000000..1be84963
--- /dev/null
+++ b/Source/OpenTK/Platform/MacOS/CarbonBindings/SpeechChannel.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace OpenTK.Platform.MacOS.Carbon
+{
+
+ public class SpeechChannel
+ {
+
+ private IntPtr _id;
+
+ protected const string appServicesPath = "/System/Library/Frameworks/ApplicationServices.framework/Versions/Current/ApplicationServices";
+
+ [DllImport(appServicesPath)]
+ private static extern short NewSpeechChannel(IntPtr voice, ref IntPtr result);
+
+
+ [DllImport(appServicesPath)]
+ private static extern short SpeakText(IntPtr channel, String text, long length);
+
+ public SpeechChannel()
+ {
+ short rc = NewSpeechChannel((IntPtr)null, ref _id);
+ Debug.WriteLine(rc);
+ }
+
+ public bool Speak(String text)
+ {
+ short rc = SpeakText(_id, text, (long)text.Length);
+ return (rc == 0);
+ }
+
+ }
+}
diff --git a/Source/OpenTK/Platform/MacOS/CarbonGLControl.cs b/Source/OpenTK/Platform/MacOS/CarbonGLControl.cs
new file mode 100644
index 00000000..98d4de49
--- /dev/null
+++ b/Source/OpenTK/Platform/MacOS/CarbonGLControl.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Forms;
+
+namespace OpenTK.Platform.MacOS
+{
+ using Graphics;
+
+ class CarbonGLControl : IGLControl
+ {
+ GraphicsMode mode;
+ Control control;
+
+ internal CarbonGLControl(GraphicsMode mode, Control owner)
+ {
+ this.mode = mode;
+ this.control = owner;
+ }
+
+ #region IGLControl Members
+
+ public OpenTK.Graphics.GraphicsContext CreateContext()
+ {
+ return new GraphicsContext(mode, WindowInfo);
+ }
+
+ // TODO: Fix this
+ bool lastIsIdle = false;
+ public bool IsIdle
+ {
+ get
+ {
+ lastIsIdle = !lastIsIdle;
+ return lastIsIdle;
+ }
+ }
+
+ public IWindowInfo WindowInfo
+ {
+ get
+ {
+ control.CreateControl();
+ return new CarbonWindowInfo(control.Handle, false, true);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs b/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs
new file mode 100644
index 00000000..99f7110e
--- /dev/null
+++ b/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs
@@ -0,0 +1,776 @@
+//
+//
+// xCSCarbon
+//
+// Created by Erik Ylvisaker on 3/17/08.
+// Copyright 2008 __MyCompanyName__. All rights reserved.
+//
+//
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Text;
+
+namespace OpenTK.Platform.MacOS
+{
+ using Carbon;
+ using Graphics;
+
+ class CarbonGLNative : INativeGLWindow
+ {
+ CarbonWindowInfo window;
+ CarbonInput mInputDriver;
+ GraphicsContext context;
+
+ static MacOSKeyMap Keymap = new MacOSKeyMap();
+
+ IntPtr uppHandler;
+
+ string title = "OpenTK Window";
+ short mWidth, mHeight;
+ short mWindowedWidth, mWindowedHeight;
+ 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 mWindows = new Dictionary();
+
+ static CarbonGLNative()
+ {
+ Application.Initialize();
+ }
+ public CarbonGLNative()
+ : this(WindowClass.Document,
+ WindowAttributes.StandardDocument |
+ WindowAttributes.StandardHandler |
+ WindowAttributes.InWindowMenu |
+ WindowAttributes.LiveResize)
+ {
+
+ }
+ private CarbonGLNative(WindowClass @class, WindowAttributes attrib)
+ {
+ mWindowClass = @class;
+ mWindowAttrib = attrib;
+
+
+ }
+ ~CarbonGLNative()
+ {
+ Dispose(false);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+ 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();
+ }
+
+ private 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...");
+ Debug.Indent();
+
+ IntPtr windowRef = API.CreateNewWindow(@class, attrib, r);
+ API.SetWindowTitle(windowRef, title);
+
+ window = new CarbonWindowInfo(windowRef, true, false);
+
+ 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.");
+ }
+ 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;
+ }
+
+
+ public string Title
+ {
+ get
+ {
+ return title;
+ }
+ set
+ {
+ API.SetWindowTitle(window.WindowRef, value);
+ title = value;
+ }
+ }
+
+ public void Activate()
+ {
+ API.SelectWindow(window.WindowRef);
+ }
+ public void Show()
+ {
+ IntPtr parent = IntPtr.Zero;
+
+ API.ShowWindow(window.WindowRef);
+ API.RepositionWindow(window.WindowRef, parent, WindowPositionMethod);
+ API.SelectWindow(window.WindowRef);
+ }
+ public void Hide()
+ {
+ API.HideWindow(window.WindowRef);
+ }
+ public bool Visible
+ {
+ get { return API.IsWindowVisible(window.WindowRef); }
+ set
+ {
+ if (value && Visible == false)
+ Show();
+ else
+ Hide();
+ }
+ }
+ public bool IsDisposed
+ {
+ get { return mIsDisposed; }
+ }
+
+ public WindowPositionMethod WindowPositionMethod
+ {
+ 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();
+ OnQueryWindowClose(cancel);
+
+ if (cancel.Cancel)
+ return OSStatus.NoError;
+ else
+ return OSStatus.EventNotHandled;
+
+ case WindowEventKind.WindowClosed:
+ OnWindowClosed();
+
+ 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();
+
+ OSStatus err ;
+
+ 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)
+ {
+ InputDriver.Mouse[0].Position =
+ new System.Drawing.Point(
+ (int)pt.X,
+ (int)pt.Y);
+ }
+ else
+ {
+ // ignore clicks in the title bar
+ if (pt.Y < mTitlebarHeight)
+ return OSStatus.EventNotHandled;
+
+ InputDriver.Mouse[0].Position =
+ new System.Drawing.Point(
+ (int)pt.X,
+ (int)(pt.Y - mTitlebarHeight));
+ }
+
+ 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;
+ }
+
+ public int Width
+ {
+ get { return mWidth; }
+ set { SetSize(value, mHeight); }
+ }
+ public int Height
+ {
+ get { return mHeight; }
+ set { SetSize(mWidth, value); }
+ }
+ public void SetSize(int width, int height)
+ {
+ if (WindowState == WindowState.Fullscreen)
+ return;
+
+ mWidth = (short)width;
+ mHeight = (short)height;
+
+ API.SizeWindow(window.WindowRef, mWidth, mHeight, true);
+
+ Rect contentBounds = API.GetWindowBounds(window.WindowRef, WindowRegionCode.ContentRegion);
+
+ Rect newSize = new Rect(0, 0,
+ (short)(2 * mWidth - contentBounds.Width),
+ (short)(2 * mHeight - contentBounds.Height));
+
+ 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);
+ }
+
+ protected void OnResize()
+ {
+ LoadSize();
+
+ if (context != null && this.windowState != WindowState.Fullscreen)
+ context.Update(window);
+
+ if (Resize != null)
+ {
+ Resize(this, new ResizeEventArgs(Width, Height));
+ }
+ }
+
+ private void LoadSize()
+ {
+ if (WindowState == WindowState.Fullscreen)
+ return;
+
+ Rect region = GetRegion();
+
+ mWidth = (short)(region.Width);
+ mHeight = (short)(region.Height);
+ }
+
+ protected virtual void OnQueryWindowClose(CancelEventArgs e)
+ {
+ if (QueryWindowClose != null)
+ QueryWindowClose(this, e);
+ }
+ protected virtual void OnWindowClosed()
+ {
+ if (Destroy != null)
+ Destroy(this, EventArgs.Empty);
+
+ }
+
+ public event CancelEventHandler QueryWindowClose;
+
+
+ #region INativeGLWindow Members
+
+ public void CreateWindow(int width, int height, OpenTK.Graphics.GraphicsMode mode, out OpenTK.Graphics.IGraphicsContext context)
+ {
+ Rect r = new Rect(0, 0, (short)width, (short)height);
+ CreateNativeWindow(mWindowClass, mWindowAttrib, r);
+
+ Show();
+
+ this.context = new Graphics.GraphicsContext(mode, window);
+ this.context.MakeCurrent(window);
+
+ context = this.context;
+
+ }
+
+ public void DestroyWindow()
+ {
+ Dispose();
+ }
+ public void ProcessEvents()
+ {
+ Application.ProcessEvents();
+ }
+
+ public void PointToClient(ref System.Drawing.Point p)
+ {
+ throw new Exception("The method or operation is not implemented.");
+ }
+ public void PointToScreen(ref System.Drawing.Point p)
+ {
+ throw new Exception("The method or operation is not implemented.");
+ }
+
+ 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();
+ }
+ }
+
+ public event CreateEvent Create;
+ public event DestroyEvent Destroy;
+
+ #endregion
+
+ #region IResizable Members
+
+ public event ResizeEvent Resize;
+
+ #endregion
+
+ #region INativeGLWindow Members
+
+
+ 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);
+ }
+ Point idealSize;
+
+ 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.
+ idealSize = new Point(9000, 9000);
+ API.ZoomWindowIdeal(window.WindowRef, WindowPartCode.inZoomOut, ref idealSize);
+ break;
+
+ case WindowState.Normal:
+ if (WindowState == WindowState.Maximized)
+ {
+ idealSize = new Point();
+ API.ZoomWindowIdeal(window.WindowRef, WindowPartCode.inZoomIn, ref idealSize);
+ }
+ break;
+
+ case WindowState.Minimized:
+ API.CollapseWindow(window.WindowRef, true);
+
+ break;
+ }
+
+ windowState = value;
+
+ OnResize();
+ }
+ }
+
+
+ private void SetFullscreen()
+ {
+ ((AglContext)context.Implementation).SetFullScreen(window);
+
+ mWindowedWidth = mWidth;
+ mWindowedHeight = mHeight;
+
+ Debug.Print("Prev Size: {0}, {1}", Width, Height);
+
+ mWidth = (short)DisplayDevice.Default.Width;
+ mHeight = (short)DisplayDevice.Default.Height;
+
+ Debug.Print("New Size: {0}, {1}", Width, Height);
+
+ }
+ private void UnsetFullscreen()
+ {
+ ((AglContext)context.Implementation).UnsetFullScreen(window);
+ SetSize(mWindowedWidth, mWindowedHeight);
+ }
+
+ public WindowBorder WindowBorder
+ {
+ get
+ {
+ return windowBorder;
+ }
+ set
+ {
+ 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);
+ }
+ }
+ }
+
+ #endregion
+
+ }
+}
diff --git a/Source/OpenTK/Platform/MacOS/CarbonInput.cs b/Source/OpenTK/Platform/MacOS/CarbonInput.cs
new file mode 100644
index 00000000..01a886d2
--- /dev/null
+++ b/Source/OpenTK/Platform/MacOS/CarbonInput.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text;
+
+namespace OpenTK.Platform.MacOS
+{
+ using Input;
+
+ class CarbonInput : IInputDriver
+ {
+ List dummy_keyboard_list = new List(1);
+ List dummy_mice_list = new List(1);
+
+ internal CarbonInput()
+ {
+ dummy_mice_list.Add(new MouseDevice());
+ dummy_keyboard_list.Add(new KeyboardDevice());
+
+ }
+ #region IInputDriver Members
+
+ public void Poll()
+ {
+ }
+
+ #endregion
+
+ #region IKeyboardDriver Members
+
+ public IList Keyboard
+ {
+ get { return dummy_keyboard_list; }
+ }
+
+ #endregion
+
+ #region IMouseDriver Members
+
+ public IList Mouse
+ {
+ get { return dummy_mice_list; }
+ }
+
+ #endregion
+
+ #region IDisposable Members
+
+ public void Dispose()
+ {
+ }
+
+ #endregion
+ }
+}
diff --git a/Source/OpenTK/Platform/MacOS/CarbonWindowInfo.cs b/Source/OpenTK/Platform/MacOS/CarbonWindowInfo.cs
new file mode 100644
index 00000000..f86b5133
--- /dev/null
+++ b/Source/OpenTK/Platform/MacOS/CarbonWindowInfo.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text;
+
+namespace OpenTK.Platform.MacOS
+{
+ sealed class CarbonWindowInfo : IWindowInfo
+ {
+ IntPtr windowRef;
+ bool ownHandle = false;
+ bool disposed = false;
+ bool isControl = false;
+
+ internal CarbonWindowInfo(IntPtr windowRef, bool ownHandle, bool isControl)
+ {
+ this.windowRef = windowRef;
+ this.ownHandle = ownHandle;
+ this.isControl = isControl;
+ }
+ ~CarbonWindowInfo()
+ {
+ Dispose(false);
+ }
+
+ internal IntPtr WindowRef
+ {
+ get { return this.windowRef; }
+ }
+
+ public bool IsControl
+ {
+ get { return isControl; }
+ }
+
+ /// 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}",
+ this.WindowRef);
+ }
+
+ #region IDisposable Members
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ void Dispose(bool disposing)
+ {
+ if (disposed)
+ return;
+
+ if (disposing)
+ {
+
+ }
+
+ if (ownHandle)
+ {
+ Debug.Print("Disposing window {0}.", windowRef);
+ Carbon.API.DisposeWindow(this.windowRef);
+ windowRef = IntPtr.Zero;
+ }
+
+ disposed = true;
+ }
+
+ #endregion
+ }
+}
diff --git a/Source/OpenTK/Platform/MacOS/EventInfo.cs b/Source/OpenTK/Platform/MacOS/EventInfo.cs
new file mode 100644
index 00000000..9216741f
--- /dev/null
+++ b/Source/OpenTK/Platform/MacOS/EventInfo.cs
@@ -0,0 +1,89 @@
+//
+//
+// 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
+{
+ public struct EventInfo
+ {
+ internal EventInfo(IntPtr eventRef)
+ {
+ this._eventClass = API.GetEventClass(eventRef);
+ this._eventKind = API.GetEventKind(eventRef);
+ }
+
+ uint _eventKind;
+ EventClass _eventClass;
+
+ public EventClass EventClass { get { return _eventClass; }}
+
+ public WindowEventKind WindowEventKind
+ {
+ get
+ {
+ if (EventClass == EventClass.Window)
+ return (WindowEventKind) _eventKind;
+ else
+ throw new InvalidCastException("Event is not a Window event.");
+ }
+ }
+ public KeyboardEventKind KeyboardEventKind
+ {
+ get
+ {
+ if (EventClass == EventClass.Keyboard)
+ return (KeyboardEventKind) _eventKind;
+ else
+ throw new InvalidCastException("Event is not a Keyboard event.");
+ }
+ }
+ public MouseEventKind MouseEventKind
+ {
+ get
+ {
+ if (EventClass == EventClass.Mouse)
+ return (MouseEventKind) _eventKind;
+ else
+ throw new InvalidCastException("Event is not an Mouse event.");
+ }
+ }
+ public AppEventKind AppEventKind
+ {
+ get
+ {
+ if (EventClass == EventClass.Application)
+ return (AppEventKind) _eventKind;
+ else
+ throw new InvalidCastException("Event is not an Application event.");
+ }
+ }
+
+
+ public override string ToString()
+ {
+ switch(EventClass)
+ {
+ case EventClass.Application:
+ return "Event: App " + AppEventKind.ToString();
+ case EventClass.Keyboard:
+ return "Event: Keyboard " + KeyboardEventKind.ToString();
+ case EventClass.Mouse:
+ return "Event: Mouse " + MouseEventKind.ToString();
+ case EventClass.Window:
+ return "Event: Window " + WindowEventKind.ToString();
+ }
+
+ return "Event: Unknown Class " + EventClass.ToString() + " kind: " + _eventKind.ToString();
+ }
+ }
+}
diff --git a/Source/OpenTK/Platform/MacOS/MacOSException.cs b/Source/OpenTK/Platform/MacOS/MacOSException.cs
new file mode 100644
index 00000000..a120d2f6
--- /dev/null
+++ b/Source/OpenTK/Platform/MacOS/MacOSException.cs
@@ -0,0 +1,96 @@
+
+using System;
+
+namespace OpenTK.Platform.MacOS
+{
+ public class MacOSException : Exception
+ {
+ OSStatus errorCode;
+
+ public MacOSException()
+ {}
+ public MacOSException(OSStatus errorCode)
+ : base("Error Code: " + errorCode.ToString())
+ {
+ this.errorCode = errorCode;
+ }
+ public MacOSException(OSStatus errorCode, string message)
+ : base(message)
+ {
+ this.errorCode = errorCode;
+ }
+ internal MacOSException(Agl.AglError errorCode, string message)
+ : base(message)
+ {
+ this.errorCode = (OSStatus)errorCode;
+ }
+
+ public OSStatus ErrorCode
+ {
+ get { return errorCode; }
+ }
+ }
+
+ public enum OSStatus
+ {
+ NoError = 0,
+
+ ParameterError = -50, /*error in user parameter list*/
+ NoHardwareError = -200, /*Sound Manager Error Returns*/
+ NotEnoughHardwareError = -201, /*Sound Manager Error Returns*/
+ UserCanceledError = -128,
+ QueueError = -1, /*queue element not found during deletion*/
+ VTypErr = -2, /*invalid queue element*/
+ CorErr = -3, /*core routine number out of range*/
+ UnimpErr = -4, /*unimplemented core routine*/
+ SlpTypeErr = -5, /*invalid queue element*/
+ SeNoDB = -8, /*no debugger installed to handle debugger command*/
+ ControlErr = -17, /*I/O System Errors*/
+ StatusErr = -18, /*I/O System Errors*/
+ ReadErr = -19, /*I/O System Errors*/
+ WritErr = -20, /*I/O System Errors*/
+ BadUnitErr = -21, /*I/O System Errors*/
+ UnitEmptyErr = -22, /*I/O System Errors*/
+ OpenErr = -23, /*I/O System Errors*/
+ ClosErr = -24, /*I/O System Errors*/
+ DRemovErr = -25, /*tried to remove an open driver*/
+ DInstErr = -26, /*DrvrInstall couldn't find driver in resources*/
+
+ // Window Manager result codes.
+ InvalidWindowPtr = -5600,
+ UnsupportedWindowAttributesForClass = -5601,
+ WindowDoesNotHaveProxy = -5602,
+ WindowPropertyNotFound = -5604,
+ UnrecognizedWindowClass = -5605,
+ CorruptWindowDescription = -5606,
+ UserWantsToDragWindow = -5607,
+ WindowsAlreadyInitialized = -5608,
+ FloatingWindowsNotInitialized = -5609,
+ WindowNotFound = -5610,
+ WindowDoesNotFitOnscreen = -5611,
+ WindowAttributeImmutable = -5612,
+ WindowAttributesConflict = -5613,
+ WindowManagerInternalError = -5614,
+ WindowWrongState = -5615,
+ WindowGroupInvalid = -5616,
+ WindowAppModalStateAlreadyExists = -5617,
+ WindowNoAppModalState = -5618,
+ WindowDoesntSupportFocus = -30583,
+ WindowRegionCodeInvalid = -30593,
+
+ // Event Manager result codes
+ EventAlreadyPosted = -9860,
+ EventTargetBusy = -9861,
+ EventDeferAccessibilityEvent = -9865,
+ EventInternalError = -9868,
+ EventParameterNotFound = -9870,
+ EventNotHandled = -9874,
+ EventLoopTimedOut = -9875,
+ EventLoopQuit = -9876,
+ EventNotInQueue = -9877,
+ HotKeyExists = -9878,
+ EventPassToNextTarget = -9880
+
+ }
+
+}
diff --git a/Source/OpenTK/Platform/MacOS/MacOSFactory.cs b/Source/OpenTK/Platform/MacOS/MacOSFactory.cs
new file mode 100644
index 00000000..39a85c4e
--- /dev/null
+++ b/Source/OpenTK/Platform/MacOS/MacOSFactory.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace OpenTK.Platform.MacOS
+{
+ using Graphics;
+
+ class MacOSFactory : IPlatformFactory
+ {
+ #region IPlatformFactory Members
+
+ public INativeGLWindow CreateGLNative()
+ {
+ return new CarbonGLNative();
+ }
+
+ public IGLControl CreateGLControl(GraphicsMode mode, GLControl owner)
+ {
+ return new CarbonGLControl(mode, owner);
+ }
+
+ public IDisplayDeviceDriver CreateDisplayDeviceDriver()
+ {
+ return new QuartzDisplayDeviceDriver();
+ }
+
+ public IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool DirectRendering)
+ {
+ return new AglContext(mode, window, shareContext);
+ }
+
+ public IGraphicsMode CreateGraphicsMode()
+ {
+ return new MacOSGraphicsMode();
+ }
+
+ #endregion
+ }
+}
diff --git a/Source/OpenTK/Platform/MacOS/MacOSGraphicsMode.cs b/Source/OpenTK/Platform/MacOS/MacOSGraphicsMode.cs
new file mode 100644
index 00000000..30fcebc8
--- /dev/null
+++ b/Source/OpenTK/Platform/MacOS/MacOSGraphicsMode.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace OpenTK.Platform.MacOS
+{
+ using Graphics;
+
+ class MacOSGraphicsMode : IGraphicsMode
+ {
+ #region IGraphicsMode Members
+
+ public GraphicsMode SelectGraphicsMode(ColorFormat color, int depth, int stencil, int samples, ColorFormat accum, int buffers, bool stereo)
+ {
+ GraphicsMode gfx = new GraphicsMode((IntPtr)1, color, depth, stencil, samples,
+ accum, buffers, stereo);
+
+ System.Diagnostics.Debug.Print("Created dummy graphics mode.");
+
+ return gfx;
+ }
+
+ #endregion
+ }
+}
diff --git a/Source/OpenTK/Platform/MacOS/MacOSKeyMap.cs b/Source/OpenTK/Platform/MacOS/MacOSKeyMap.cs
new file mode 100644
index 00000000..b03d2e62
--- /dev/null
+++ b/Source/OpenTK/Platform/MacOS/MacOSKeyMap.cs
@@ -0,0 +1,133 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace OpenTK.Platform.MacOS
+{
+ using Carbon;
+ using Input;
+
+ class MacOSKeyMap : Dictionary
+ {
+ public MacOSKeyMap()
+ {
+ // comments indicate members of the Key enum that are missing
+
+ Add(MacOSKeyCode.A, Key.A);
+ // AltLeft
+ // AltRight
+ Add(MacOSKeyCode.B, Key.B);
+
+ Add(MacOSKeyCode.Backslash, Key.BackSlash);
+ Add(MacOSKeyCode.Backspace, Key.BackSpace);
+ Add(MacOSKeyCode.BracketLeft, Key.BracketLeft);
+ Add(MacOSKeyCode.BracketRight, Key.BracketRight);
+ Add(MacOSKeyCode.C, Key.C);
+ // Capslock
+ // Clear
+ Add(MacOSKeyCode.Comma, Key.Comma);
+ // ControlLeft
+ // ControlRight
+ Add(MacOSKeyCode.D, Key.D);
+ Add(MacOSKeyCode.Del, Key.Delete);
+ Add(MacOSKeyCode.Down, Key.Down);
+ Add(MacOSKeyCode.E, Key.E);
+ Add(MacOSKeyCode.End, Key.End);
+ Add(MacOSKeyCode.Enter, Key.Enter);
+ Add(MacOSKeyCode.Return, Key.Enter);
+ Add(MacOSKeyCode.Esc, Key.Escape);
+ Add(MacOSKeyCode.F, Key.F);
+ Add(MacOSKeyCode.F1, Key.F1);
+ Add(MacOSKeyCode.F2, Key.F2);
+ Add(MacOSKeyCode.F3, Key.F3);
+ Add(MacOSKeyCode.F4, Key.F4);
+ Add(MacOSKeyCode.F5, Key.F5);
+ Add(MacOSKeyCode.F6, Key.F6);
+ Add(MacOSKeyCode.F7, Key.F7);
+ Add(MacOSKeyCode.F8, Key.F8);
+ Add(MacOSKeyCode.F9, Key.F9);
+ Add(MacOSKeyCode.F10, Key.F10);
+ Add(MacOSKeyCode.F11, Key.F11);
+ Add(MacOSKeyCode.F12, Key.F12);
+ Add(MacOSKeyCode.F13, Key.F13);
+ Add(MacOSKeyCode.F14, Key.F14);
+ Add(MacOSKeyCode.F15, Key.F15);
+ // F16-F35
+ Add(MacOSKeyCode.G, Key.G);
+ Add(MacOSKeyCode.H, Key.H);
+ Add(MacOSKeyCode.Home, Key.Home);
+ Add(MacOSKeyCode.I, Key.I);
+ Add(MacOSKeyCode.Insert, Key.Insert);
+ Add(MacOSKeyCode.J, Key.J);
+ Add(MacOSKeyCode.K, Key.K);
+ Add(MacOSKeyCode.KeyPad_0, Key.Keypad0);
+ Add(MacOSKeyCode.KeyPad_1, Key.Keypad1);
+ Add(MacOSKeyCode.KeyPad_2, Key.Keypad2);
+ Add(MacOSKeyCode.KeyPad_3, Key.Keypad3);
+ Add(MacOSKeyCode.KeyPad_4, Key.Keypad4);
+ Add(MacOSKeyCode.KeyPad_5, Key.Keypad5);
+ Add(MacOSKeyCode.KeyPad_6, Key.Keypad6);
+ Add(MacOSKeyCode.KeyPad_7, Key.Keypad7);
+ Add(MacOSKeyCode.KeyPad_8, Key.Keypad8);
+ Add(MacOSKeyCode.KeyPad_9, Key.Keypad9);
+ Add(MacOSKeyCode.KeyPad_Add, Key.KeypadAdd);
+ Add(MacOSKeyCode.KeyPad_Decimal, Key.KeypadDecimal);
+ Add(MacOSKeyCode.KeyPad_Divide, Key.KeypadDivide);
+ Add(MacOSKeyCode.KeyPad_Enter, Key.KeypadEnter);
+ Add(MacOSKeyCode.KeyPad_Multiply, Key.KeypadMultiply);
+ Add(MacOSKeyCode.KeyPad_Subtract, Key.KeypadSubtract);
+ //Add(MacOSKeyCode.KeyPad_Equal);
+ Add(MacOSKeyCode.L, Key.L);
+ Add(MacOSKeyCode.Left, Key.Left);
+ Add(MacOSKeyCode.M, Key.M);
+ //Key.MaxKeys
+ Add(MacOSKeyCode.Menu, Key.Menu);
+ Add(MacOSKeyCode.Minus, Key.Minus);
+ Add(MacOSKeyCode.N, Key.N);
+ Add(MacOSKeyCode.Key_0, Key.Number0);
+ Add(MacOSKeyCode.Key_1, Key.Number1);
+ Add(MacOSKeyCode.Key_2, Key.Number2);
+ Add(MacOSKeyCode.Key_3, Key.Number3);
+ Add(MacOSKeyCode.Key_4, Key.Number4);
+ Add(MacOSKeyCode.Key_5, Key.Number4);
+ Add(MacOSKeyCode.Key_6, Key.Number5);
+ Add(MacOSKeyCode.Key_7, Key.Number6);
+ Add(MacOSKeyCode.Key_8, Key.Number7);
+ Add(MacOSKeyCode.Key_9, Key.Number9);
+ // Numlock
+ Add(MacOSKeyCode.O, Key.O);
+ Add(MacOSKeyCode.P, Key.P);
+ Add(MacOSKeyCode.Pagedown, Key.PageDown);
+ Add(MacOSKeyCode.Pageup, Key.PageUp);
+ // Pause
+ Add(MacOSKeyCode.Period, Key.Period);
+ Add(MacOSKeyCode.Equals, Key.Plus);
+ // PrintScreen
+ Add(MacOSKeyCode.Q, Key.Q);
+ Add(MacOSKeyCode.Quote, Key.Quote);
+ Add(MacOSKeyCode.R, Key.R);
+ Add(MacOSKeyCode.Right, Key.Right);
+ Add(MacOSKeyCode.S, Key.S);
+ // ScrollLock
+ Add(MacOSKeyCode.Semicolon, Key.Semicolon);
+ //Key.ShiftLeft
+ //Key.ShiftRight
+ Add(MacOSKeyCode.Slash, Key.Slash);
+ // Key.Sleep
+ Add(MacOSKeyCode.Space, Key.Space);
+ Add(MacOSKeyCode.T, Key.T);
+ Add(MacOSKeyCode.Tab, Key.Tab);
+ Add(MacOSKeyCode.Tilde, Key.Tilde);
+ Add(MacOSKeyCode.U, Key.U);
+ Add(MacOSKeyCode.Up, Key.Up);
+ Add(MacOSKeyCode.V, Key.V);
+ Add(MacOSKeyCode.W, Key.W);
+ // WinKeyLeft
+ // WinKeyRight
+ Add(MacOSKeyCode.X, Key.X);
+ Add(MacOSKeyCode.Y, Key.Y);
+ Add(MacOSKeyCode.Z, Key.Z);
+
+ }
+ }
+}
diff --git a/Source/OpenTK/Platform/MacOS/QuartzDisplayDeviceDriver.cs b/Source/OpenTK/Platform/MacOS/QuartzDisplayDeviceDriver.cs
new file mode 100644
index 00000000..7616a206
--- /dev/null
+++ b/Source/OpenTK/Platform/MacOS/QuartzDisplayDeviceDriver.cs
@@ -0,0 +1,172 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text;
+
+namespace OpenTK.Platform.MacOS
+{
+ using Graphics;
+ using Carbon;
+
+ class QuartzDisplayDeviceDriver : IDisplayDeviceDriver
+ {
+ static object display_lock = new object();
+
+ static Dictionary displayMap =
+ new Dictionary();
+
+ static IntPtr mainDisplay;
+ internal static IntPtr MainDisplay { get { return mainDisplay; } }
+
+ static QuartzDisplayDeviceDriver()
+ {
+ lock (display_lock)
+ {
+ // To minimize the need to add static methods to OpenTK.Graphics.DisplayDevice
+ // we only allow settings to be set through its constructor.
+ // Thus, we save all necessary parameters in temporary variables
+ // and construct the device when every needed detail is available.
+ // The main DisplayDevice constructor adds the newly constructed device
+ // to the list of available devices.
+ const int maxDisplayCount = 20;
+ IntPtr[] displays = new IntPtr[maxDisplayCount];
+ int displayCount;
+
+ unsafe
+ {
+ fixed(IntPtr* displayPtr = displays)
+ {
+ CG.GetActiveDisplayList(maxDisplayCount, displayPtr, out displayCount);
+ }
+ }
+
+ Debug.Print("CoreGraphics reported {0} displays.", displayCount);
+ Debug.Indent();
+
+ for (int i = 0; i < displayCount; i++)
+ {
+ IntPtr currentDisplay = displays[i];
+
+ // according to docs, first element in the array is always the
+ // main display.
+ bool primary = (i == 0);
+
+ if (primary)
+ mainDisplay = currentDisplay;
+
+ // gets current settings
+ int currentWidth = CG.DisplayPixelsWide(currentDisplay);
+ int currentHeight = CG.DisplayPixelsHigh(currentDisplay);
+ Debug.Print("Display {0} is at {1}x{2}", i, currentWidth, currentHeight);
+
+ IntPtr displayModesPtr = CG.DisplayAvailableModes(currentDisplay);
+ CFArray displayModes = new CFArray(displayModesPtr);
+ Debug.Print("Supports {0} display modes.", displayModes.Count);
+
+ DisplayResolution opentk_dev_current_res = null;
+ List opentk_dev_available_res = new List();
+ IntPtr currentModePtr = CG.DisplayCurrentMode(currentDisplay);
+ CFDictionary currentMode = new CFDictionary(currentModePtr);
+
+ for (int j = 0; j < displayModes.Count; j++)
+ {
+ CFDictionary dict = new CFDictionary(displayModes[j]);
+
+ int width = (int) dict.GetNumberValue("Width");
+ int height = (int) dict.GetNumberValue("Height");
+ int bpp = (int) dict.GetNumberValue("BitsPerPixel");
+ double freq = dict.GetNumberValue("RefreshRate");
+ bool current = currentMode.Ref == dict.Ref;
+
+ //if (current) Debug.Write(" * ");
+ //else Debug.Write(" ");
+
+ //Debug.Print("Mode {0} is {1}x{2}x{3} @ {4}.", j, width, height, bpp, freq);
+
+ DisplayResolution thisRes = new DisplayResolution(width, height, bpp, (float)freq);
+ opentk_dev_available_res.Add(thisRes);
+
+ if (current)
+ opentk_dev_current_res = thisRes;
+
+ }
+
+ OpenTK.Graphics.DisplayDevice opentk_dev =
+ new DisplayDevice(opentk_dev_current_res, primary, opentk_dev_available_res);
+
+ displayMap.Add(opentk_dev, currentDisplay);
+ }
+
+ Debug.Unindent();
+ }
+ }
+
+ #region IDisplayDeviceDriver Members
+
+ Dictionary storedModes = new Dictionary();
+ List displaysCaptured = new List();
+
+ public bool TryChangeResolution(DisplayDevice device, DisplayResolution resolution)
+ {
+ IntPtr display = displayMap[device];
+ IntPtr currentModePtr = CG.DisplayCurrentMode(display);
+
+ if (storedModes.ContainsKey(display) == false)
+ {
+ storedModes.Add(display, currentModePtr);
+ }
+
+ IntPtr displayModesPtr = CG.DisplayAvailableModes(display);
+ CFArray displayModes = new CFArray(displayModesPtr);
+
+ for (int j = 0; j < displayModes.Count; j++)
+ {
+ CFDictionary dict = new CFDictionary(displayModes[j]);
+
+ int width = (int)dict.GetNumberValue("Width");
+ int height = (int)dict.GetNumberValue("Height");
+ int bpp = (int)dict.GetNumberValue("BitsPerPixel");
+ double freq = dict.GetNumberValue("RefreshRate");
+
+ if (width == resolution.Width &&
+ height == resolution.Height &&
+ bpp == resolution.BitsPerPixel &&
+ System.Math.Abs(freq - resolution.RefreshRate) < 1e-6)
+ {
+ if (displaysCaptured.Contains(display) == false)
+ {
+ CG.DisplayCapture(display);
+ }
+
+ Debug.Print("Changing resolution to {0}x{1}x{2}@{3}.", width, height, bpp, freq);
+
+ CG.DisplaySwitchToMode(display, displayModes[j]);
+
+ return true;
+ }
+
+ }
+ return false;
+ }
+
+ public bool TryRestoreResolution(DisplayDevice device)
+ {
+ IntPtr display = displayMap[device];
+
+ if (storedModes.ContainsKey(display))
+ {
+ Debug.Print("Restoring resolution.");
+
+ CG.DisplaySwitchToMode(display, storedModes[display]);
+ CG.DisplayRelease(display);
+ displaysCaptured.Remove(display);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ #endregion
+ }
+}
diff --git a/Source/OpenTK/Platform/OSX/Functions.cs b/Source/OpenTK/Platform/OSX/Functions.cs
deleted file mode 100644
index 2c68e307..00000000
--- a/Source/OpenTK/Platform/OSX/Functions.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-#region --- License ---
-/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
- * See license.txt for license info
- */
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Runtime.InteropServices;
-
-namespace OpenTK.Platform.OSX
-{
- public static partial class Functions
- {
- internal const string Library = "libdl.dylib";
-
- #region OSX GetProcAddress
-
- [DllImport(Library, EntryPoint = "NSIsSymbolNameDefined")]
- internal static extern bool NSIsSymbolNameDefined(string s);
- [DllImport(Library, EntryPoint = "NSLookupAndBindSymbol")]
- internal static extern IntPtr NSLookupAndBindSymbol(string s);
- [DllImport(Library, EntryPoint = "NSAddressOfSymbol")]
- internal static extern IntPtr NSAddressOfSymbol(IntPtr symbol);
-
- #endregion
- }
-}
diff --git a/Source/OpenTK/Platform/Utilities.cs b/Source/OpenTK/Platform/Utilities.cs
index db54a4ce..c4f485a2 100644
--- a/Source/OpenTK/Platform/Utilities.cs
+++ b/Source/OpenTK/Platform/Utilities.cs
@@ -1,4 +1,4 @@
-#region --- License ---
+#region --- License ---
/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
* See license.txt for license info
*/
@@ -265,7 +265,7 @@ namespace OpenTK.Platform
{
if (Configuration.RunningOnWindows) return CreateWinWindowInfo(controlHandle);
else if (Configuration.RunningOnX11) return CreateX11WindowInfo(mode, controlHandle);
- else if (Configuration.RunningOnOSX) return CreateOSXWindowInfo(controlHandle);
+ else if (Configuration.RunningOnMacOS) return CreateMacOSCarbonWindowInfo(controlHandle);
else
throw new PlatformNotSupportedException("Refer to http://www.opentk.com for more information.");
}
@@ -316,9 +316,9 @@ namespace OpenTK.Platform
#endregion
#region --- Mac OS X Platform-specific implementation ---
- private static IWindowInfo CreateOSXWindowInfo(IntPtr controlHandle)
+ private static IWindowInfo CreateMacOSCarbonWindowInfo(IntPtr controlHandle)
{
- throw new PlatformNotSupportedException("Refer to http://www.opentk.com for more information.");
+ return new OpenTK.Platform.MacOS.CarbonWindowInfo(controlHandle, false, true);
}
#endregion
diff --git a/Source/OpenTK/Platform/Windows/WinFactory.cs b/Source/OpenTK/Platform/Windows/WinFactory.cs
new file mode 100644
index 00000000..ce61788a
--- /dev/null
+++ b/Source/OpenTK/Platform/Windows/WinFactory.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace OpenTK.Platform.Windows
+{
+ using Graphics;
+
+ class WinFactory : IPlatformFactory
+ {
+ #region IPlatformFactory Members
+
+ public INativeGLWindow CreateGLNative()
+ {
+ return new WinGLNative();
+ }
+
+ public IGLControl CreateGLControl(GraphicsMode mode, GLControl owner)
+ {
+ return new WinGLControl(mode, owner);
+ }
+
+ public IDisplayDeviceDriver CreateDisplayDeviceDriver()
+ {
+ return new WinDisplayDeviceDriver();
+ }
+
+ public IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool DirectRendering)
+ {
+ return new WinGLContext(mode, window, shareContext);
+ }
+
+ public IGraphicsMode CreateGraphicsMode()
+ {
+ return new WinGraphicsMode();
+ }
+
+ #endregion
+ }
+}
diff --git a/Source/OpenTK/Platform/Windows/WinGLContext.cs b/Source/OpenTK/Platform/Windows/WinGLContext.cs
index 95912c0d..5bdbffee 100644
--- a/Source/OpenTK/Platform/Windows/WinGLContext.cs
+++ b/Source/OpenTK/Platform/Windows/WinGLContext.cs
@@ -210,6 +210,13 @@ namespace OpenTK.Platform.Windows
#endregion
+ #region public void Update
+ public void Update(IWindowInfo window)
+ {
+ }
+ #endregion
+
+
public event DestroyEvent Destroy;
#endregion
@@ -437,6 +444,12 @@ namespace OpenTK.Platform.Windows
#endregion
+ #endregion
+
+ #region IGraphicsContext Members
+
+
+
#endregion
}
}
diff --git a/Source/OpenTK/Platform/X11/X11Factory.cs b/Source/OpenTK/Platform/X11/X11Factory.cs
new file mode 100644
index 00000000..f863968d
--- /dev/null
+++ b/Source/OpenTK/Platform/X11/X11Factory.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace OpenTK.Platform.X11
+{
+ using Graphics;
+
+ class X11Factory : IPlatformFactory
+ {
+ #region IPlatformFactory Members
+
+ public INativeGLWindow CreateGLNative()
+ {
+ return new X11GLNative();
+ }
+
+ public IGLControl CreateGLControl(GraphicsMode mode, GLControl owner)
+ {
+ return new X11GLControl(mode, owner);
+ }
+
+ public IDisplayDeviceDriver CreateDisplayDeviceDriver()
+ {
+ return new X11XrandrDisplayDevice();
+ }
+
+ public IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool DirectRendering)
+ {
+ return new X11GLContext(mode, window, shareContext, DirectRendering);
+ }
+
+ public IGraphicsMode CreateGraphicsMode()
+ {
+ return new X11GraphicsMode();
+ }
+
+ #endregion
+ }
+}
diff --git a/Source/OpenTK/Platform/X11/X11GLContext.cs b/Source/OpenTK/Platform/X11/X11GLContext.cs
index db72dc26..8e25ed59 100644
--- a/Source/OpenTK/Platform/X11/X11GLContext.cs
+++ b/Source/OpenTK/Platform/X11/X11GLContext.cs
@@ -235,6 +235,12 @@ namespace OpenTK.Platform.X11
#endregion
+ #region public void Update
+ public void Update(IWindowInfo window)
+ {
+ }
+ #endregion
+
public void RegisterForDisposal(IDisposable resource)
{
throw new NotSupportedException("Use OpenTK.GraphicsContext instead.");