Make GLControl work on OS X

This isn’t the greatest solution, but at least it doesn’t require us to
reference WinForms in OpenTK and it works perfectly for what I’m using.
This commit is contained in:
Paul Kratt 2014-02-20 20:27:17 -06:00
parent 172462d4ea
commit 794d45fdeb
5 changed files with 85 additions and 23 deletions

View file

@ -46,9 +46,20 @@ namespace OpenTK
this.mode = mode;
this.control = owner;
window_info = Utilities.CreateMacOSCarbonWindowInfo(control.Handle, false, true);
window_info = Utilities.CreateMacOSCarbonWindowInfo(control.Handle, false, true, GetXOffset, GetYOffset);
}
private int GetXOffset(){
return control.Location.X;
}
private int GetYOffset(){
System.Drawing.Point offset = control.PointToScreen(control.Location);
System.Drawing.Point windowOffset = control.TopLevelControl.PointToScreen(System.Drawing.Point.Empty);
int relativeY = offset.Y-windowOffset.Y; //control.TopLevelControl.Location.Y is not the same as windowOffset.Y for some reason.
return control.TopLevelControl.ClientSize.Height - control.Bottom - relativeY;
}
#region IGLControl Members
public IGraphicsContext CreateContext(int major, int minor, GraphicsContextFlags flags)

View file

@ -270,12 +270,28 @@ namespace OpenTK
return;
}
if (context != null)
context.Update(Implementation.WindowInfo);
if (Configuration.RunningOnMacOS) {
DelayUpdate delay = PerformContextUpdate;
BeginInvoke(delay); //Need the native window to resize first otherwise our control will be in the wrong place.
}
else if (context != null)
context.Update (Implementation.WindowInfo);
base.OnResize(e);
}
/// <summary>
/// Needed to delay the invoke on OS X. Also needed because OpenTK is .NET 2, otherwise I'd use an inline Action.
/// </summary>
public delegate void DelayUpdate();
/// <summary>
/// Execute the delayed context update
/// </summary>
public void PerformContextUpdate(){
if (context != null)
context.Update (Implementation.WindowInfo);
}
/// <summary>
/// Raises the ParentChanged event.
/// </summary>

View file

@ -173,31 +173,26 @@ namespace OpenTK.Platform.MacOS
return;
// Todo: See if there is a way around using WinForms.
throw new NotImplementedException();
#if false
System.Windows.Forms.Control ctrl = Control.FromHandle(carbonWindow.WindowRef);
//throw new NotImplementedException();
/*System.Windows.Forms.Control ctrl = Control.FromHandle(carbonWindow.WindowHandle);
if (ctrl.TopLevelControl == null)
return;
return;*/
Rect rect = API.GetControlBounds(carbonWindow.WindowRef);
System.Windows.Forms.Form frm = (System.Windows.Forms.Form)ctrl.TopLevelControl;
System.Drawing.Point loc = frm.PointToClient(ctrl.PointToScreen(System.Drawing.Point.Empty));
rect.X = (short)loc.X;
rect.Y = (short)loc.Y;
Rect rect = API.GetControlBounds(carbonWindow.WindowHandle);
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;
if (carbonWindow.XOffset != null)
glrect[0] = rect.X + carbonWindow.XOffset();
else
glrect[0] = rect.X;
if (carbonWindow.YOffset != null)
glrect[1] = rect.Y + carbonWindow.YOffset();
else
glrect[1] = rect.Y;
glrect[2] = rect.Width;
glrect[3] = rect.Height;
@ -206,7 +201,6 @@ namespace OpenTK.Platform.MacOS
Agl.aglEnable(Handle.Handle, Agl.ParameterNames.AGL_BUFFER_RECT);
MyAGLReportError("aglEnable");
#endif
}
void SetDrawable(CarbonWindowInfo carbonWindow)
{

View file

@ -32,6 +32,13 @@ using System.Text;
namespace OpenTK.Platform.MacOS
{
/// <summary>
/// This delegate represents any method that takes no arguments and returns an int.
/// I would have used Func but that requires .NET 4
/// </summary>
/// <returns>The int value that your method returns</returns>
public delegate int GetInt();
/// \internal
/// <summary>
/// Describes a Carbon window.
@ -45,6 +52,9 @@ namespace OpenTK.Platform.MacOS
bool goFullScreenHack = false;
bool goWindowedHack = false;
GetInt xOffset;
GetInt yOffset;
#region Constructors
/// <summary>
@ -60,6 +70,12 @@ namespace OpenTK.Platform.MacOS
this.isControl = isControl;
}
public CarbonWindowInfo(IntPtr windowRef, bool ownHandle, bool isControl, GetInt getX, GetInt getY) : this(windowRef, ownHandle, isControl)
{
this.xOffset = getX;
this.yOffset = getY;
}
#endregion
#region Public Members
@ -104,6 +120,16 @@ namespace OpenTK.Platform.MacOS
// (e.g. MonoGame)
public IntPtr WindowHandle { get { return Handle; } set { Handle = value; } }
public GetInt XOffset
{
get { return xOffset; }
set { xOffset = value; }
}
public GetInt YOffset
{
get { return yOffset; }
set { yOffset = value; }
}
#endregion
#region IDisposable Members

View file

@ -276,6 +276,21 @@ namespace OpenTK.Platform
return new OpenTK.Platform.MacOS.CarbonWindowInfo(windowHandle, false, isControl);
}
/// <summary>
/// Creates an IWindowInfo instance for the Mac OS X platform with an X and Y offset for the GL viewport location.
/// </summary>
/// <param name="windowHandle">The handle of the window.</param>
/// <param name="ownHandle">Ignored. This is reserved for future use.</param>
/// <param name="isControl">Set to true if windowHandle corresponds to a System.Windows.Forms control.</param>
/// <param name="xOffset">The X offset for the GL viewport</param>
/// <param name="yOffset">The Y offset for the GL viewport</param>
/// <returns>A new IWindowInfo instance.</returns>
public static IWindowInfo CreateMacOSCarbonWindowInfo(IntPtr windowHandle, bool ownHandle, bool isControl,
OpenTK.Platform.MacOS.GetInt xOffset, OpenTK.Platform.MacOS.GetInt yOffset)
{
return new OpenTK.Platform.MacOS.CarbonWindowInfo(windowHandle, false, isControl, xOffset, yOffset);
}
#endregion
#region CreateDummyWindowInfo