Merged in macos branch for Mac OS X support.

This commit is contained in:
kanato 2009-02-20 18:57:57 +00:00
parent de7f93823e
commit c2fd0e5eb2
38 changed files with 4082 additions and 128 deletions

View file

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

View file

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

View file

@ -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
/// <summary>Provides information about the underlying OS and runtime.</summary>
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
/// <summary>Gets a System.Boolean indicating whether OpenTK is running on an X11 platform.</summary>
public static bool RunningOnX11 { get { return runningOnX11; } }
@ -93,10 +94,10 @@ namespace OpenTK
#endregion
#region public static bool RunningOnOSX
#region public static bool RunningOnMacOS
/// <summary>Gets a System.Boolean indicating whether OpenTK is running on a MacOS platform.</summary>
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()
// <summary>
// Executes "uname" which returns a string representing the name of the
// underlying Unix kernel.
// </summary>
// <returns>"Unix", "Linux", "Darwin" or null.</returns>
// <remarks>Source code from "Mono: A Developer's Notebook"</remarks>
[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;
}
/// <summary>
/// Detects the unix kernel by p/invoking the uname call in libc.
/// </summary>
/// <returns></returns>
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

View file

@ -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 ---
/// <summary>Raises the HandleCreated event.</summary>

View file

@ -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
/// <summary>
@ -230,9 +232,17 @@ namespace OpenTK
/// <summary>Stops the main loop.</summary>
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
/// <summary>
/// Occurs when the GameWindow is resized. Derived classes should override the OnResize method for better performance.
/// </summary>
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;
/// <summary>
/// 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);
}

View file

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

View file

@ -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.");
}
}

View file

@ -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 ---
/// <summary>
@ -315,6 +315,16 @@ namespace OpenTK.Graphics
set { implementation.VSync = value; }
}
/// <summary>
/// Updates the graphics context. This must be called when the render target
/// is resized for proper behavior on Mac OS X.
/// </summary>
/// <param name="window"></param>
public void Update(IWindowInfo window)
{
implementation.Update(window);
}
#endregion
#region --- IGraphicsContextInternal Members ---

View file

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

View file

@ -44,6 +44,13 @@ namespace OpenTK.Graphics
/// Gets or sets a value indicating whether VSyncing is enabled.
/// </summary>
bool VSync { get; set; }
/// <summary>
/// Updates the graphics context. This must be called when the region the graphics context
/// is drawn to is resized.
/// </summary>
/// <param name="window"></param>
void Update(IWindowInfo window);
}
public delegate void DestroyEvent<T>(T sender, EventArgs e);

View file

@ -3,4 +3,6 @@
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
<dllmap os="linux" dll="openal32.dll" target="libopenal.so.0"/>
<dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
</configuration>
<dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
<dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
</configuration>

View file

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

View file

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

View file

@ -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();
}
}

View file

@ -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<int> aglAttributes, Agl.PixelFormatAttribute pixelFormatAttribute)
{
Debug.Print(pixelFormatAttribute.ToString());
aglAttributes.Add((int)pixelFormatAttribute);
}
private void AddPixelAttrib(List<int> 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<int> aglAttributes = new List<int>();
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<IGraphicsContext> 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
}
}

View file

@ -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();
}
}
}

View file

@ -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);
/// <summary>
/// Use this overload only with IntPtr.Zero for the first argument.
/// </summary>
/// <param name="gdevs">
/// </param>
/// <param name="ndev">
/// </param>
/// <param name="attribs">
/// </param>
/// <returns>
/// </returns>
[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);
}
}

View file

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

View file

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

View file

@ -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
{
}
}

View file

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

View file

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

View file

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

View file

@ -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<IntPtr, WeakReference> mWindows = new Dictionary<IntPtr, WeakReference>();
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
}
}

View file

@ -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<KeyboardDevice> dummy_keyboard_list = new List<KeyboardDevice>(1);
List<MouseDevice> dummy_mice_list = new List<MouseDevice>(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<KeyboardDevice> Keyboard
{
get { return dummy_keyboard_list; }
}
#endregion
#region IMouseDriver Members
public IList<MouseDevice> Mouse
{
get { return dummy_mice_list; }
}
#endregion
#region IDisposable Members
public void Dispose()
{
}
#endregion
}
}

View file

@ -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; }
}
/// <summary>Returns a System.String that represents the current window.</summary>
/// <returns>A System.String that represents the current window.</returns>
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
}
}

View file

@ -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();
}
}
}

View file

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

View file

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

View file

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

View file

@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace OpenTK.Platform.MacOS
{
using Carbon;
using Input;
class MacOSKeyMap : Dictionary<MacOSKeyCode, Key>
{
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);
}
}
}

View file

@ -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<DisplayDevice, IntPtr> displayMap =
new Dictionary<DisplayDevice, IntPtr>();
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<DisplayResolution> opentk_dev_available_res = new List<DisplayResolution>();
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<IntPtr, IntPtr> storedModes = new Dictionary<IntPtr, IntPtr>();
List<IntPtr> displaysCaptured = new List<IntPtr>();
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
}
}

View file

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

View file

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

View file

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

View file

@ -210,6 +210,13 @@ namespace OpenTK.Platform.Windows
#endregion
#region public void Update
public void Update(IWindowInfo window)
{
}
#endregion
public event DestroyEvent<IGraphicsContext> Destroy;
#endregion
@ -437,6 +444,12 @@ namespace OpenTK.Platform.Windows
#endregion
#endregion
#region IGraphicsContext Members
#endregion
}
}

View file

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

View file

@ -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.");