diff --git a/Source/OpenTK/Graphics/GraphicsContext.cs b/Source/OpenTK/Graphics/GraphicsContext.cs
index f498b546..c8c0aea3 100644
--- a/Source/OpenTK/Graphics/GraphicsContext.cs
+++ b/Source/OpenTK/Graphics/GraphicsContext.cs
@@ -216,6 +216,14 @@ namespace OpenTK.Graphics
#endregion
+ ///
+ /// Hack for Mac OS full screen support.
+ ///
+ internal IGraphicsContext Implementation
+ {
+ get { return implementation; }
+ }
+
#region --- IGraphicsContext Members ---
///
diff --git a/Source/OpenTK/Platform/MacOS/AglContext.cs b/Source/OpenTK/Platform/MacOS/AglContext.cs
index 816fe5c3..8b7821dd 100644
--- a/Source/OpenTK/Platform/MacOS/AglContext.cs
+++ b/Source/OpenTK/Platform/MacOS/AglContext.cs
@@ -89,7 +89,7 @@ namespace OpenTK.Platform.MacOS
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ACCUM_BLUE_SIZE, mode.AccumulatorFormat.Blue);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ACCUM_ALPHA_SIZE, mode.AccumulatorFormat.Alpha);
}
- //AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_FULLSCREEN);
+ AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_FULLSCREEN);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_NONE);
Debug.Unindent();
@@ -103,7 +103,9 @@ namespace OpenTK.Platform.MacOS
IntPtr shareContextRef = IntPtr.Zero;
// Choose a pixel format with the attributes we specified.
- myAGLPixelFormat = Agl.aglChoosePixelFormat(IntPtr.Zero, 0, aglAttributes.ToArray());
+ myAGLPixelFormat = Agl.aglChoosePixelFormat(QuartzDisplayDeviceDriver.MainDisplay,
+ 0, aglAttributes.ToArray());
+
MyAGLReportError("aglChoosePixelFormat");
if (shareContext != null)
@@ -212,6 +214,16 @@ namespace OpenTK.Platform.MacOS
return Agl.aglGetCurrentContext();
}
+ internal void SetFullScreen()
+ {
+ Agl.aglSetFullScreen(contextRef, 0, 0, 0, 0);
+ }
+ internal void UnsetFullScreen()
+ {
+ SetDrawable(carbonWindow);
+ }
+
+
#region IGraphicsContext Members
bool first = false;
public void SwapBuffers()
diff --git a/Source/OpenTK/Platform/MacOS/CarbonBindings/CarbonAPI.cs b/Source/OpenTK/Platform/MacOS/CarbonBindings/CarbonAPI.cs
index bfd22492..067fcc2c 100644
--- a/Source/OpenTK/Platform/MacOS/CarbonBindings/CarbonAPI.cs
+++ b/Source/OpenTK/Platform/MacOS/CarbonBindings/CarbonAPI.cs
@@ -21,6 +21,12 @@ namespace OpenTK.Platform.MacOS.Carbon
{
internal short V;
internal short H;
+
+ public Point(int x, int y)
+ {
+ V = (short)x;
+ H = (short)y;
+ }
}
[StructLayout(LayoutKind.Sequential)]
@@ -346,6 +352,24 @@ namespace OpenTK.Platform.MacOS.Carbon
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 ---
@@ -778,6 +802,51 @@ namespace OpenTK.Platform.MacOS.Carbon
#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);
+ }
+ }
}
diff --git a/Source/OpenTK/Platform/MacOS/CarbonBindings/QuartzDisplayServicesAPI.cs b/Source/OpenTK/Platform/MacOS/CarbonBindings/QuartzDisplayServicesAPI.cs
index 45c48e92..59c95c94 100644
--- a/Source/OpenTK/Platform/MacOS/CarbonBindings/QuartzDisplayServicesAPI.cs
+++ b/Source/OpenTK/Platform/MacOS/CarbonBindings/QuartzDisplayServicesAPI.cs
@@ -44,5 +44,8 @@ namespace OpenTK.Platform.MacOS.Carbon
[DllImport(appServices, EntryPoint = "CGDisplayAvailableModes")]
internal static extern IntPtr DisplayAvailableModes(IntPtr display);
+ [DllImport(appServices, EntryPoint = "CGDisplaySwitchToMode")]
+ internal static extern IntPtr DisplaySwitchToMode(IntPtr display, IntPtr displayMode);
+
}
}
diff --git a/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs b/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs
index 5054cc8f..e4fdffc3 100644
--- a/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs
+++ b/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs
@@ -18,8 +18,8 @@ namespace OpenTK.Platform.MacOS
using Carbon;
using Graphics;
- class CarbonGLNative : INativeGLWindow
- {
+ class CarbonGLNative : INativeGLWindow
+ {
CarbonWindowInfo window;
CarbonInput mInputDriver;
GraphicsContext context;
@@ -45,9 +45,9 @@ namespace OpenTK.Platform.MacOS
Application.Initialize();
}
public CarbonGLNative()
- : this(WindowClass.Document,
- WindowAttributes.StandardDocument |
- WindowAttributes.StandardHandler |
+ : this(WindowClass.Document,
+ WindowAttributes.StandardDocument |
+ WindowAttributes.StandardHandler |
WindowAttributes.InWindowMenu |
WindowAttributes.LiveResize)
{
@@ -58,7 +58,7 @@ namespace OpenTK.Platform.MacOS
mWindowClass = @class;
mWindowAttrib = attrib;
-
+
}
~CarbonGLNative()
{
@@ -81,12 +81,12 @@ namespace OpenTK.Platform.MacOS
if (disposing)
{
- mWindows.Remove(window.WindowRef);
-
- window.Dispose();
+ mWindows.Remove(window.WindowRef);
+
+ window.Dispose();
window = null;
}
-
+
DisposeUPP();
}
@@ -131,12 +131,6 @@ namespace OpenTK.Platform.MacOS
System.Diagnostics.Debug.Print("Attached window events.");
}
-
- public void Activate()
- {
- API.SelectWindow(window.WindowRef);
- }
-
void ConnectEvents()
{
mInputDriver = new CarbonInput();
@@ -167,6 +161,7 @@ namespace OpenTK.Platform.MacOS
API.InstallWindowEventHandler(window.WindowRef, uppHandler, eventTypes, window.WindowRef, IntPtr.Zero);
}
+
public string Title
{
get
@@ -180,6 +175,10 @@ namespace OpenTK.Platform.MacOS
}
}
+ public void Activate()
+ {
+ API.SelectWindow(window.WindowRef);
+ }
public void Show()
{
IntPtr parent = IntPtr.Zero;
@@ -195,8 +194,8 @@ namespace OpenTK.Platform.MacOS
public bool Visible
{
get { return API.IsWindowVisible(window.WindowRef); }
- set
- {
+ set
+ {
if (value && Visible == false)
Show();
else
@@ -208,7 +207,6 @@ namespace OpenTK.Platform.MacOS
get { return mIsDisposed; }
}
-
public WindowPositionMethod WindowPositionMethod
{
get { return mPositionMethod; }
@@ -232,7 +230,7 @@ namespace OpenTK.Platform.MacOS
EventInfo evt = new EventInfo(inEvent);
CarbonGLNative window = (CarbonGLNative)reference.Target;
-
+
//Debug.Print("Processing {0} event for {1}.", evt, window.window);
if (window == null)
@@ -241,7 +239,7 @@ namespace OpenTK.Platform.MacOS
return OSStatus.EventNotHandled;
}
- switch(evt.EventClass)
+ switch (evt.EventClass)
{
case EventClass.Window:
return window.ProcessWindowEvent(inCaller, inEvent, evt, userData);
@@ -282,7 +280,7 @@ namespace OpenTK.Platform.MacOS
case KeyboardEventKind.RawKeyUp:
GetCharCodes(inEvent, out code, out charCode);
InputDriver.Keyboard[0][Keymap[code]] = false;
-
+
return OSStatus.EventNotHandled;
case KeyboardEventKind.RawKeyModifiersChanged:
@@ -295,12 +293,11 @@ namespace OpenTK.Platform.MacOS
}
-
private OSStatus ProcessWindowEvent(IntPtr inCaller, IntPtr inEvent, EventInfo evt, IntPtr userData)
{
System.Diagnostics.Debug.Assert(evt.EventClass == EventClass.Window);
- switch(evt.WindowEventKind)
+ switch (evt.WindowEventKind)
{
case WindowEventKind.WindowClose:
CancelEventArgs cancel = new CancelEventArgs();
@@ -343,7 +340,7 @@ namespace OpenTK.Platform.MacOS
(int)pt.X,
(int)(pt.Y - mTitlebarHeight));
- switch(evt.MouseEventKind)
+ switch (evt.MouseEventKind)
{
case MouseEventKind.MouseDown:
button = API.GetEventMouseButton(inEvent);
@@ -365,7 +362,7 @@ namespace OpenTK.Platform.MacOS
break;
-
+
case MouseEventKind.MouseUp:
switch (button)
{
@@ -381,14 +378,14 @@ namespace OpenTK.Platform.MacOS
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;
@@ -399,10 +396,9 @@ namespace OpenTK.Platform.MacOS
return OSStatus.EventNotHandled;
}
- return OSStatus.EventNotHandled;
+ return OSStatus.EventNotHandled;
}
-
private static void GetCharCodes(IntPtr inEvent, out MacOSKeyCode code, out char charCode)
{
code = API.GetEventKeyboardKeyCode(inEvent);
@@ -439,7 +435,6 @@ namespace OpenTK.Platform.MacOS
}
-
Rect GetRegion()
{
Rect retval = API.GetWindowBounds(window.WindowRef, WindowRegionCode.ContentRegion);
@@ -527,14 +522,13 @@ namespace OpenTK.Platform.MacOS
this.context.MakeCurrent(window);
context = this.context;
-
+
}
public void DestroyWindow()
{
Dispose();
}
-
public void ProcessEvents()
{
Application.ProcessEvents();
@@ -544,7 +538,6 @@ namespace OpenTK.Platform.MacOS
{
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.");
@@ -567,7 +560,7 @@ namespace OpenTK.Platform.MacOS
public OpenTK.Input.IInputDriver InputDriver
{
- get
+ get
{
return mInputDriver;
}
@@ -586,7 +579,6 @@ namespace OpenTK.Platform.MacOS
}
public event CreateEvent Create;
-
public event DestroyEvent Destroy;
#endregion
@@ -604,11 +596,65 @@ namespace OpenTK.Platform.MacOS
{
get
{
- return windowState;
+ 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)
+ {
+ ((AglContext)context.Implementation).UnsetFullScreen();
+ }
+ if (WindowState == WindowState.Minimized)
+ {
+ API.CollapseWindow(window.WindowRef, false);
+ }
+ Point idealSize;
+
+ switch (value)
+ {
+ case WindowState.Fullscreen:
+ ((AglContext)context.Implementation).SetFullScreen();
+ context.Update(WindowInfo);
+ break;
+
+ case WindowState.Maximized:
+ 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;
+
}
}
@@ -621,16 +667,16 @@ namespace OpenTK.Platform.MacOS
set
{
windowBorder = value;
-
+
if (windowBorder == WindowBorder.Resizable)
{
- API.ChangeWindowAttributes(window.WindowRef, WindowAttributes.Resizable | WindowAttributes.FullZoom,
- WindowAttributes.NoAttributes);
+ 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);
+ API.ChangeWindowAttributes(window.WindowRef, WindowAttributes.NoAttributes,
+ WindowAttributes.Resizable | WindowAttributes.FullZoom);
}
}
}
diff --git a/Source/OpenTK/Platform/MacOS/QuartzDisplayDeviceDriver.cs b/Source/OpenTK/Platform/MacOS/QuartzDisplayDeviceDriver.cs
index 3ce26174..58756cc7 100644
--- a/Source/OpenTK/Platform/MacOS/QuartzDisplayDeviceDriver.cs
+++ b/Source/OpenTK/Platform/MacOS/QuartzDisplayDeviceDriver.cs
@@ -11,7 +11,13 @@ namespace OpenTK.Platform.MacOS
class QuartzDisplayDeviceDriver : IDisplayDeviceDriver
{
static object display_lock = new object();
-
+
+ static Dictionary displayMap =
+ new Dictionary();
+
+ static IntPtr mainDisplay;
+ internal static IntPtr MainDisplay { get { return mainDisplay; } }
+
static QuartzDisplayDeviceDriver()
{
//lock (display_lock)
@@ -55,6 +61,9 @@ namespace OpenTK.Platform.MacOS
// main display.
bool primary = (i == 0);
+ if (primary)
+ mainDisplay = currentDisplay;
+
// gets current settings
int currentWidth = CG.DisplayPixelsWide(currentDisplay);
int currentHeight = CG.DisplayPixelsHigh(currentDisplay);
@@ -94,6 +103,8 @@ namespace OpenTK.Platform.MacOS
OpenTK.Graphics.DisplayDevice opentk_dev =
new DisplayDevice(opentk_dev_current_res, primary, opentk_dev_available_res);
+
+ displayMap.Add(opentk_dev, currentDisplay);
}
Debug.Unindent();
@@ -102,14 +113,55 @@ namespace OpenTK.Platform.MacOS
#region IDisplayDeviceDriver Members
+ Dictionary storedModes = new Dictionary();
+
+
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 &&
+ freq == resolution.RefreshRate)
+ {
+ CG.DisplaySwitchToMode(display, displayModes[j]);
+
+ return true;
+ }
+
+ }
return false;
}
public bool TryRestoreResolution(DisplayDevice device)
{
+ IntPtr display = displayMap[device];
+
+ if (storedModes.ContainsKey(display))
+ {
+ CG.DisplaySwitchToMode(display, storedModes[display]);
+ return true;
+ }
+
return false;
}