From 794d45fdeb7b37288a3adc531717648e5ca19136 Mon Sep 17 00:00:00 2001 From: Paul Kratt Date: Thu, 20 Feb 2014 20:27:17 -0600 Subject: [PATCH 1/4] Make GLControl work on OS X MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- Source/GLControl/CarbonGLControl.cs | 13 +++++++- Source/GLControl/GLControl.cs | 22 +++++++++++-- Source/OpenTK/Platform/MacOS/AglContext.cs | 32 ++++++++----------- .../OpenTK/Platform/MacOS/CarbonWindowInfo.cs | 26 +++++++++++++++ Source/OpenTK/Platform/Utilities.cs | 15 +++++++++ 5 files changed, 85 insertions(+), 23 deletions(-) diff --git a/Source/GLControl/CarbonGLControl.cs b/Source/GLControl/CarbonGLControl.cs index 22dfef8e..380a735f 100644 --- a/Source/GLControl/CarbonGLControl.cs +++ b/Source/GLControl/CarbonGLControl.cs @@ -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) diff --git a/Source/GLControl/GLControl.cs b/Source/GLControl/GLControl.cs index c2f616f6..fb592568 100644 --- a/Source/GLControl/GLControl.cs +++ b/Source/GLControl/GLControl.cs @@ -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); } + /// + /// Needed to delay the invoke on OS X. Also needed because OpenTK is .NET 2, otherwise I'd use an inline Action. + /// + public delegate void DelayUpdate(); + /// + /// Execute the delayed context update + /// + public void PerformContextUpdate(){ + if (context != null) + context.Update (Implementation.WindowInfo); + } + /// /// Raises the ParentChanged event. /// diff --git a/Source/OpenTK/Platform/MacOS/AglContext.cs b/Source/OpenTK/Platform/MacOS/AglContext.cs index f8e0fe0c..b572b8e4 100644 --- a/Source/OpenTK/Platform/MacOS/AglContext.cs +++ b/Source/OpenTK/Platform/MacOS/AglContext.cs @@ -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) { diff --git a/Source/OpenTK/Platform/MacOS/CarbonWindowInfo.cs b/Source/OpenTK/Platform/MacOS/CarbonWindowInfo.cs index 717a6c58..687857b2 100644 --- a/Source/OpenTK/Platform/MacOS/CarbonWindowInfo.cs +++ b/Source/OpenTK/Platform/MacOS/CarbonWindowInfo.cs @@ -32,6 +32,13 @@ using System.Text; namespace OpenTK.Platform.MacOS { + /// + /// This delegate represents any method that takes no arguments and returns an int. + /// I would have used Func but that requires .NET 4 + /// + /// The int value that your method returns + public delegate int GetInt(); + /// \internal /// /// Describes a Carbon window. @@ -45,6 +52,9 @@ namespace OpenTK.Platform.MacOS bool goFullScreenHack = false; bool goWindowedHack = false; + GetInt xOffset; + GetInt yOffset; + #region Constructors /// @@ -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 diff --git a/Source/OpenTK/Platform/Utilities.cs b/Source/OpenTK/Platform/Utilities.cs index 82fa91ab..f99a8d6a 100644 --- a/Source/OpenTK/Platform/Utilities.cs +++ b/Source/OpenTK/Platform/Utilities.cs @@ -276,6 +276,21 @@ namespace OpenTK.Platform return new OpenTK.Platform.MacOS.CarbonWindowInfo(windowHandle, false, isControl); } + /// + /// Creates an IWindowInfo instance for the Mac OS X platform with an X and Y offset for the GL viewport location. + /// + /// The handle of the window. + /// Ignored. This is reserved for future use. + /// Set to true if windowHandle corresponds to a System.Windows.Forms control. + /// The X offset for the GL viewport + /// The Y offset for the GL viewport + /// A new IWindowInfo instance. + 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 From ba0180ed77342e0a9f2ccc6dbc4d29df145f0e99 Mon Sep 17 00:00:00 2001 From: Paul Kratt Date: Fri, 21 Feb 2014 21:36:22 -0600 Subject: [PATCH 2/4] Fix potential exception that I was ignoring. This can happen, so we should handle it --- Source/GLControl/CarbonGLControl.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Source/GLControl/CarbonGLControl.cs b/Source/GLControl/CarbonGLControl.cs index 380a735f..58589f95 100644 --- a/Source/GLControl/CarbonGLControl.cs +++ b/Source/GLControl/CarbonGLControl.cs @@ -54,10 +54,13 @@ namespace OpenTK } 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; + if (control.TopLevelControl != null) { + 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; + } + return control.Location.Y; } #region IGLControl Members From 0df7c5560912dd2eb3cf91b08fa67756b33135d2 Mon Sep 17 00:00:00 2001 From: Paul Kratt Date: Sat, 22 Feb 2014 11:28:14 -0600 Subject: [PATCH 3/4] Update spacing and formatting to match existing style --- Source/GLControl/CarbonGLControl.cs | 29 +++++++++-------- Source/GLControl/GLControl.cs | 38 ++++++++++++---------- Source/OpenTK/Platform/MacOS/AglContext.cs | 7 ---- 3 files changed, 36 insertions(+), 38 deletions(-) diff --git a/Source/GLControl/CarbonGLControl.cs b/Source/GLControl/CarbonGLControl.cs index 58589f95..40cebef5 100644 --- a/Source/GLControl/CarbonGLControl.cs +++ b/Source/GLControl/CarbonGLControl.cs @@ -46,22 +46,25 @@ namespace OpenTK this.mode = mode; this.control = owner; - window_info = Utilities.CreateMacOSCarbonWindowInfo(control.Handle, false, true, GetXOffset, GetYOffset); + window_info = Utilities.CreateMacOSCarbonWindowInfo(control.Handle, false, true, GetXOffset, GetYOffset); } - private int GetXOffset(){ - return control.Location.X; - } + private int GetXOffset() + { + return control.Location.X; + } - private int GetYOffset(){ - if (control.TopLevelControl != null) { - 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; - } - return control.Location.Y; - } + private int GetYOffset() + { + if (control.TopLevelControl != null) + { + 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; + } + return control.Location.Y; + } #region IGLControl Members diff --git a/Source/GLControl/GLControl.cs b/Source/GLControl/GLControl.cs index fb592568..faba119d 100644 --- a/Source/GLControl/GLControl.cs +++ b/Source/GLControl/GLControl.cs @@ -270,27 +270,29 @@ namespace OpenTK return; } - 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); - + 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); } - /// - /// Needed to delay the invoke on OS X. Also needed because OpenTK is .NET 2, otherwise I'd use an inline Action. - /// - public delegate void DelayUpdate(); - /// - /// Execute the delayed context update - /// - public void PerformContextUpdate(){ - if (context != null) - context.Update (Implementation.WindowInfo); - } + /// + /// Needed to delay the invoke on OS X. Also needed because OpenTK is .NET 2, otherwise I'd use an inline Action. + /// + public delegate void DelayUpdate(); + /// + /// Execute the delayed context update + /// + public void PerformContextUpdate() + { + if (context != null) + context.Update (Implementation.WindowInfo); + } /// /// Raises the ParentChanged event. diff --git a/Source/OpenTK/Platform/MacOS/AglContext.cs b/Source/OpenTK/Platform/MacOS/AglContext.cs index b572b8e4..eab21a05 100644 --- a/Source/OpenTK/Platform/MacOS/AglContext.cs +++ b/Source/OpenTK/Platform/MacOS/AglContext.cs @@ -172,13 +172,6 @@ namespace OpenTK.Platform.MacOS if (carbonWindow.IsControl == false) return; - // Todo: See if there is a way around using WinForms. - //throw new NotImplementedException(); - /*System.Windows.Forms.Control ctrl = Control.FromHandle(carbonWindow.WindowHandle); - - if (ctrl.TopLevelControl == null) - return;*/ - Rect rect = API.GetControlBounds(carbonWindow.WindowHandle); Debug.Print("Setting buffer_rect for control."); From d9a7821319fde500ed57832bb416c245500cd2db Mon Sep 17 00:00:00 2001 From: Paul Kratt Date: Tue, 25 Feb 2014 18:52:34 -0600 Subject: [PATCH 4/4] Call the new code instead of leaving the old version untouched --- Source/OpenTK/Platform/Utilities.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/OpenTK/Platform/Utilities.cs b/Source/OpenTK/Platform/Utilities.cs index f99a8d6a..2de2dcea 100644 --- a/Source/OpenTK/Platform/Utilities.cs +++ b/Source/OpenTK/Platform/Utilities.cs @@ -273,7 +273,7 @@ namespace OpenTK.Platform /// A new IWindowInfo instance. public static IWindowInfo CreateMacOSCarbonWindowInfo(IntPtr windowHandle, bool ownHandle, bool isControl) { - return new OpenTK.Platform.MacOS.CarbonWindowInfo(windowHandle, false, isControl); + return CreateMacOSCarbonWindowInfo(windowHandle, ownHandle, isControl, null, null); } ///