* EventInfo.cs:
* AglContext.cs: * MacOSKeyMap.cs: * CarbonInput.cs: * Application.cs: * MacOSFactory.cs: * CarbonGLNative.cs: * CarbonWindowInfo.cs: * MacOSGraphicsMode.cs: * QuartzDisplayDeviceDriver.cs: Normalized code formatting.
This commit is contained in:
parent
bde71543f5
commit
7e344e2ac2
10 changed files with 882 additions and 949 deletions
|
@ -23,41 +23,40 @@ namespace OpenTK.Platform.MacOS
|
||||||
using AGLContext = IntPtr;
|
using AGLContext = IntPtr;
|
||||||
using AGLPbuffer = IntPtr;
|
using AGLPbuffer = IntPtr;
|
||||||
|
|
||||||
class AglContext : DesktopGraphicsContext
|
class AglContext : DesktopGraphicsContext
|
||||||
{
|
{
|
||||||
bool mVSync = false;
|
bool mVSync = false;
|
||||||
// Todo: keep track of which display adapter was specified when the context was created.
|
// Todo: keep track of which display adapter was specified when the context was created.
|
||||||
// IntPtr displayID;
|
// IntPtr displayID;
|
||||||
|
|
||||||
GraphicsMode graphics_mode;
|
GraphicsMode graphics_mode;
|
||||||
CarbonWindowInfo carbonWindow;
|
CarbonWindowInfo carbonWindow;
|
||||||
IntPtr shareContextRef;
|
IntPtr shareContextRef;
|
||||||
DisplayDevice device;
|
DisplayDevice device;
|
||||||
bool mIsFullscreen = false;
|
bool mIsFullscreen = false;
|
||||||
|
|
||||||
public AglContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext)
|
public AglContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext)
|
||||||
{
|
{
|
||||||
Debug.Print("Context Type: {0}", shareContext);
|
Debug.Print("Context Type: {0}", shareContext);
|
||||||
Debug.Print("Window info: {0}", window);
|
Debug.Print("Window info: {0}", window);
|
||||||
|
|
||||||
this.graphics_mode = mode;
|
this.graphics_mode = mode;
|
||||||
this.carbonWindow = (CarbonWindowInfo)window;
|
this.carbonWindow = (CarbonWindowInfo)window;
|
||||||
|
|
||||||
if (shareContext is AglContext)
|
if (shareContext is AglContext)
|
||||||
shareContextRef = ((AglContext)shareContext).Handle.Handle;
|
shareContextRef = ((AglContext)shareContext).Handle.Handle;
|
||||||
if (shareContext is GraphicsContext)
|
if (shareContext is GraphicsContext)
|
||||||
{
|
{
|
||||||
ContextHandle shareHandle = shareContext != null ?
|
ContextHandle shareHandle = shareContext != null ? (shareContext as IGraphicsContextInternal).Context : (ContextHandle)IntPtr.Zero;
|
||||||
(shareContext as IGraphicsContextInternal).Context : (ContextHandle)IntPtr.Zero;
|
|
||||||
|
shareContextRef = shareHandle.Handle;
|
||||||
shareContextRef = shareHandle.Handle;
|
}
|
||||||
}
|
|
||||||
|
if (shareContextRef == IntPtr.Zero)
|
||||||
if (shareContextRef == IntPtr.Zero)
|
{
|
||||||
{
|
Debug.Print("No context sharing will take place.");
|
||||||
Debug.Print("No context sharing will take place.");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
CreateContext(mode, carbonWindow, shareContextRef, true);
|
CreateContext(mode, carbonWindow, shareContextRef, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +66,7 @@ namespace OpenTK.Platform.MacOS
|
||||||
throw new ArgumentException("handle");
|
throw new ArgumentException("handle");
|
||||||
if (window == null)
|
if (window == null)
|
||||||
throw new ArgumentNullException("window");
|
throw new ArgumentNullException("window");
|
||||||
|
|
||||||
Handle = handle;
|
Handle = handle;
|
||||||
carbonWindow = (CarbonWindowInfo)window;
|
carbonWindow = (CarbonWindowInfo)window;
|
||||||
}
|
}
|
||||||
|
@ -76,37 +75,36 @@ namespace OpenTK.Platform.MacOS
|
||||||
private void AddPixelAttrib(List<int> aglAttributes, Agl.PixelFormatAttribute pixelFormatAttribute)
|
private void AddPixelAttrib(List<int> aglAttributes, Agl.PixelFormatAttribute pixelFormatAttribute)
|
||||||
{
|
{
|
||||||
Debug.Print(pixelFormatAttribute.ToString());
|
Debug.Print(pixelFormatAttribute.ToString());
|
||||||
|
|
||||||
aglAttributes.Add((int)pixelFormatAttribute);
|
aglAttributes.Add((int)pixelFormatAttribute);
|
||||||
}
|
}
|
||||||
private void AddPixelAttrib(List<int> aglAttributes, Agl.PixelFormatAttribute pixelFormatAttribute, int value)
|
private void AddPixelAttrib(List<int> aglAttributes, Agl.PixelFormatAttribute pixelFormatAttribute, int value)
|
||||||
{
|
{
|
||||||
Debug.Print("{0} : {1}", pixelFormatAttribute, value);
|
Debug.Print("{0} : {1}", pixelFormatAttribute, value);
|
||||||
|
|
||||||
aglAttributes.Add((int)pixelFormatAttribute);
|
aglAttributes.Add((int)pixelFormatAttribute);
|
||||||
aglAttributes.Add(value);
|
aglAttributes.Add(value);
|
||||||
}
|
}
|
||||||
void CreateContext(GraphicsMode mode, CarbonWindowInfo carbonWindow,
|
void CreateContext(GraphicsMode mode, CarbonWindowInfo carbonWindow, IntPtr shareContextRef, bool fullscreen)
|
||||||
IntPtr shareContextRef, bool fullscreen)
|
|
||||||
{
|
{
|
||||||
List<int> aglAttributes = new List<int>();
|
List<int> aglAttributes = new List<int>();
|
||||||
|
|
||||||
Debug.Print("AGL pixel format attributes:");
|
Debug.Print("AGL pixel format attributes:");
|
||||||
Debug.Indent();
|
Debug.Indent();
|
||||||
|
|
||||||
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_RGBA);
|
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_RGBA);
|
||||||
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_DOUBLEBUFFER);
|
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_DOUBLEBUFFER);
|
||||||
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_RED_SIZE, mode.ColorFormat.Red);
|
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_GREEN_SIZE, mode.ColorFormat.Green);
|
||||||
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_BLUE_SIZE, mode.ColorFormat.Blue);
|
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_BLUE_SIZE, mode.ColorFormat.Blue);
|
||||||
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ALPHA_SIZE, mode.ColorFormat.Alpha);
|
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ALPHA_SIZE, mode.ColorFormat.Alpha);
|
||||||
|
|
||||||
if (mode.Depth > 0)
|
if (mode.Depth > 0)
|
||||||
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_DEPTH_SIZE, mode.Depth);
|
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_DEPTH_SIZE, mode.Depth);
|
||||||
|
|
||||||
if (mode.Stencil > 0)
|
if (mode.Stencil > 0)
|
||||||
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_STENCIL_SIZE, mode.Stencil);
|
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_STENCIL_SIZE, mode.Stencil);
|
||||||
|
|
||||||
if (mode.AccumulatorFormat.BitsPerPixel > 0)
|
if (mode.AccumulatorFormat.BitsPerPixel > 0)
|
||||||
{
|
{
|
||||||
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ACCUM_RED_SIZE, mode.AccumulatorFormat.Red);
|
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ACCUM_RED_SIZE, mode.AccumulatorFormat.Red);
|
||||||
|
@ -120,72 +118,68 @@ namespace OpenTK.Platform.MacOS
|
||||||
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_SAMPLE_BUFFERS_ARB, 1);
|
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_SAMPLE_BUFFERS_ARB, 1);
|
||||||
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_SAMPLES_ARB, mode.Samples);
|
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_SAMPLES_ARB, mode.Samples);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fullscreen)
|
if (fullscreen)
|
||||||
{
|
{
|
||||||
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_FULLSCREEN);
|
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_FULLSCREEN);
|
||||||
}
|
}
|
||||||
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_NONE);
|
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_NONE);
|
||||||
|
|
||||||
Debug.Unindent();
|
Debug.Unindent();
|
||||||
|
|
||||||
Debug.Write("Attribute array: ");
|
Debug.Write("Attribute array: ");
|
||||||
for (int i = 0; i < aglAttributes.Count; i++)
|
for (int i = 0; i < aglAttributes.Count; i++)
|
||||||
Debug.Write(aglAttributes[i].ToString() + " ");
|
Debug.Write(aglAttributes[i].ToString() + " ");
|
||||||
Debug.WriteLine("");
|
Debug.WriteLine("");
|
||||||
|
|
||||||
AGLPixelFormat myAGLPixelFormat;
|
AGLPixelFormat myAGLPixelFormat;
|
||||||
|
|
||||||
// Choose a pixel format with the attributes we specified.
|
// Choose a pixel format with the attributes we specified.
|
||||||
if (fullscreen)
|
if (fullscreen)
|
||||||
{
|
{
|
||||||
IntPtr gdevice;
|
IntPtr gdevice;
|
||||||
IntPtr cgdevice = GetQuartzDevice(carbonWindow);
|
IntPtr cgdevice = GetQuartzDevice(carbonWindow);
|
||||||
|
|
||||||
if (cgdevice == IntPtr.Zero)
|
if (cgdevice == IntPtr.Zero)
|
||||||
cgdevice = QuartzDisplayDeviceDriver.MainDisplay;
|
cgdevice = QuartzDisplayDeviceDriver.MainDisplay;
|
||||||
|
|
||||||
OSStatus status = Carbon.API.DMGetGDeviceByDisplayID(
|
OSStatus status = Carbon.API.DMGetGDeviceByDisplayID(cgdevice, out gdevice, false);
|
||||||
cgdevice, out gdevice, false);
|
|
||||||
|
|
||||||
if (status != OSStatus.NoError)
|
if (status != OSStatus.NoError)
|
||||||
throw new MacOSException(status, "DMGetGDeviceByDisplayID failed.");
|
throw new MacOSException(status, "DMGetGDeviceByDisplayID failed.");
|
||||||
|
|
||||||
myAGLPixelFormat = Agl.aglChoosePixelFormat(
|
myAGLPixelFormat = Agl.aglChoosePixelFormat(ref gdevice, 1, aglAttributes.ToArray());
|
||||||
ref gdevice, 1,
|
|
||||||
aglAttributes.ToArray());
|
|
||||||
|
|
||||||
Agl.AglError err = Agl.GetError();
|
Agl.AglError err = Agl.GetError();
|
||||||
|
|
||||||
if (err == Agl.AglError.BadPixelFormat)
|
if (err == Agl.AglError.BadPixelFormat)
|
||||||
{
|
{
|
||||||
Debug.Print("Failed to create full screen pixel format.");
|
Debug.Print("Failed to create full screen pixel format.");
|
||||||
Debug.Print("Trying again to create a non-fullscreen pixel format.");
|
Debug.Print("Trying again to create a non-fullscreen pixel format.");
|
||||||
|
|
||||||
CreateContext(mode, carbonWindow, shareContextRef, false);
|
CreateContext(mode, carbonWindow, shareContextRef, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
myAGLPixelFormat = Agl.aglChoosePixelFormat(
|
myAGLPixelFormat = Agl.aglChoosePixelFormat(IntPtr.Zero, 0, aglAttributes.ToArray());
|
||||||
IntPtr.Zero, 0,
|
|
||||||
aglAttributes.ToArray());
|
|
||||||
|
|
||||||
MyAGLReportError("aglChoosePixelFormat");
|
MyAGLReportError("aglChoosePixelFormat");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Debug.Print("Creating AGL context. Sharing with {0}", shareContextRef);
|
Debug.Print("Creating AGL context. Sharing with {0}", shareContextRef);
|
||||||
|
|
||||||
// create the context and share it with the share reference.
|
// create the context and share it with the share reference.
|
||||||
Handle = new ContextHandle( Agl.aglCreateContext(myAGLPixelFormat, shareContextRef));
|
Handle = new ContextHandle(Agl.aglCreateContext(myAGLPixelFormat, shareContextRef));
|
||||||
MyAGLReportError("aglCreateContext");
|
MyAGLReportError("aglCreateContext");
|
||||||
|
|
||||||
// Free the pixel format from memory.
|
// Free the pixel format from memory.
|
||||||
Agl.aglDestroyPixelFormat(myAGLPixelFormat);
|
Agl.aglDestroyPixelFormat(myAGLPixelFormat);
|
||||||
MyAGLReportError("aglDestroyPixelFormat");
|
MyAGLReportError("aglDestroyPixelFormat");
|
||||||
|
|
||||||
Debug.Print("IsControl: {0}", carbonWindow.IsControl);
|
Debug.Print("IsControl: {0}", carbonWindow.IsControl);
|
||||||
|
|
||||||
SetDrawable(carbonWindow);
|
SetDrawable(carbonWindow);
|
||||||
|
@ -193,29 +187,29 @@ namespace OpenTK.Platform.MacOS
|
||||||
Update(carbonWindow);
|
Update(carbonWindow);
|
||||||
|
|
||||||
MakeCurrent(carbonWindow);
|
MakeCurrent(carbonWindow);
|
||||||
|
|
||||||
Debug.Print("context: {0}", Handle.Handle);
|
Debug.Print("context: {0}", Handle.Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntPtr GetQuartzDevice(CarbonWindowInfo carbonWindow)
|
private IntPtr GetQuartzDevice(CarbonWindowInfo carbonWindow)
|
||||||
{
|
{
|
||||||
IntPtr windowRef = carbonWindow.WindowRef;
|
IntPtr windowRef = carbonWindow.WindowRef;
|
||||||
|
|
||||||
if (CarbonGLNative.WindowRefMap.ContainsKey(windowRef) == false)
|
if (CarbonGLNative.WindowRefMap.ContainsKey(windowRef) == false)
|
||||||
return IntPtr.Zero;
|
return IntPtr.Zero;
|
||||||
|
|
||||||
WeakReference nativeRef = CarbonGLNative.WindowRefMap[windowRef];
|
WeakReference nativeRef = CarbonGLNative.WindowRefMap[windowRef];
|
||||||
if (nativeRef.IsAlive == false)
|
if (nativeRef.IsAlive == false)
|
||||||
return IntPtr.Zero;
|
return IntPtr.Zero;
|
||||||
|
|
||||||
CarbonGLNative window = nativeRef.Target as CarbonGLNative;
|
CarbonGLNative window = nativeRef.Target as CarbonGLNative;
|
||||||
|
|
||||||
if (window == null)
|
if (window == null)
|
||||||
return IntPtr.Zero;
|
return IntPtr.Zero;
|
||||||
|
|
||||||
return QuartzDisplayDeviceDriver.HandleTo(window.TargetDisplayDevice);
|
return QuartzDisplayDeviceDriver.HandleTo(window.TargetDisplayDevice);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetBufferRect(CarbonWindowInfo carbonWindow)
|
void SetBufferRect(CarbonWindowInfo carbonWindow)
|
||||||
{
|
{
|
||||||
|
@ -223,16 +217,15 @@ namespace OpenTK.Platform.MacOS
|
||||||
return;
|
return;
|
||||||
|
|
||||||
System.Windows.Forms.Control ctrl = Control.FromHandle(carbonWindow.WindowRef);
|
System.Windows.Forms.Control ctrl = Control.FromHandle(carbonWindow.WindowRef);
|
||||||
|
|
||||||
if (ctrl.TopLevelControl == null)
|
if (ctrl.TopLevelControl == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Rect rect = API.GetControlBounds(carbonWindow.WindowRef);
|
Rect rect = API.GetControlBounds(carbonWindow.WindowRef);
|
||||||
System.Windows.Forms.Form frm = (System.Windows.Forms.Form) ctrl.TopLevelControl;
|
System.Windows.Forms.Form frm = (System.Windows.Forms.Form)ctrl.TopLevelControl;
|
||||||
|
|
||||||
System.Drawing.Point loc =
|
System.Drawing.Point loc = frm.PointToClient(ctrl.PointToScreen(System.Drawing.Point.Empty));
|
||||||
frm.PointToClient(ctrl.PointToScreen(System.Drawing.Point.Empty));
|
|
||||||
|
|
||||||
rect.X = (short)loc.X;
|
rect.X = (short)loc.X;
|
||||||
rect.Y = (short)loc.Y;
|
rect.Y = (short)loc.Y;
|
||||||
|
|
||||||
|
@ -243,28 +236,28 @@ namespace OpenTK.Platform.MacOS
|
||||||
Debug.Print(" AGL Coordinate Rect: {0}", rect);
|
Debug.Print(" AGL Coordinate Rect: {0}", rect);
|
||||||
|
|
||||||
int[] glrect = new int[4];
|
int[] glrect = new int[4];
|
||||||
|
|
||||||
glrect[0] = rect.X;
|
glrect[0] = rect.X;
|
||||||
glrect[1] = rect.Y;
|
glrect[1] = rect.Y;
|
||||||
glrect[2] = rect.Width;
|
glrect[2] = rect.Width;
|
||||||
glrect[3] = rect.Height;
|
glrect[3] = rect.Height;
|
||||||
|
|
||||||
Agl.aglSetInteger(Handle.Handle, Agl.ParameterNames.AGL_BUFFER_RECT, glrect);
|
Agl.aglSetInteger(Handle.Handle, Agl.ParameterNames.AGL_BUFFER_RECT, glrect);
|
||||||
MyAGLReportError("aglSetInteger");
|
MyAGLReportError("aglSetInteger");
|
||||||
|
|
||||||
Agl.aglEnable(Handle.Handle, Agl.ParameterNames.AGL_BUFFER_RECT);
|
Agl.aglEnable(Handle.Handle, Agl.ParameterNames.AGL_BUFFER_RECT);
|
||||||
MyAGLReportError("aglEnable");
|
MyAGLReportError("aglEnable");
|
||||||
|
|
||||||
}
|
}
|
||||||
void SetDrawable(CarbonWindowInfo carbonWindow)
|
void SetDrawable(CarbonWindowInfo carbonWindow)
|
||||||
{
|
{
|
||||||
IntPtr windowPort = GetWindowPortForWindowInfo(carbonWindow);
|
IntPtr windowPort = GetWindowPortForWindowInfo(carbonWindow);
|
||||||
//Debug.Print("Setting drawable for context {0} to window port: {1}", Handle.Handle, windowPort);
|
//Debug.Print("Setting drawable for context {0} to window port: {1}", Handle.Handle, windowPort);
|
||||||
|
|
||||||
Agl.aglSetDrawable(Handle.Handle, windowPort);
|
Agl.aglSetDrawable(Handle.Handle, windowPort);
|
||||||
|
|
||||||
MyAGLReportError("aglSetDrawable");
|
MyAGLReportError("aglSetDrawable");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IntPtr GetWindowPortForWindowInfo(CarbonWindowInfo carbonWindow)
|
private static IntPtr GetWindowPortForWindowInfo(CarbonWindowInfo carbonWindow)
|
||||||
|
@ -276,109 +269,109 @@ namespace OpenTK.Platform.MacOS
|
||||||
|
|
||||||
windowPort = API.GetWindowPort(controlOwner);
|
windowPort = API.GetWindowPort(controlOwner);
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
windowPort = API.GetWindowPort(carbonWindow.WindowRef);
|
windowPort = API.GetWindowPort(carbonWindow.WindowRef);
|
||||||
|
|
||||||
return windowPort;
|
return windowPort;
|
||||||
}
|
}
|
||||||
public override void Update(IWindowInfo window)
|
public override void Update(IWindowInfo window)
|
||||||
{
|
{
|
||||||
CarbonWindowInfo carbonWindow = (CarbonWindowInfo)window;
|
CarbonWindowInfo carbonWindow = (CarbonWindowInfo)window;
|
||||||
|
|
||||||
|
if (carbonWindow.GoFullScreenHack)
|
||||||
|
{
|
||||||
|
carbonWindow.GoFullScreenHack = false;
|
||||||
|
CarbonGLNative wind = GetCarbonWindow(carbonWindow);
|
||||||
|
|
||||||
|
if (wind != null)
|
||||||
|
wind.SetFullscreen(this);
|
||||||
|
else
|
||||||
|
Debug.Print("Could not find window!");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (carbonWindow.GoFullScreenHack)
|
else if (carbonWindow.GoWindowedHack)
|
||||||
{
|
{
|
||||||
carbonWindow.GoFullScreenHack = false;
|
carbonWindow.GoWindowedHack = false;
|
||||||
CarbonGLNative wind = GetCarbonWindow(carbonWindow);
|
CarbonGLNative wind = GetCarbonWindow(carbonWindow);
|
||||||
|
|
||||||
if (wind != null)
|
if (wind != null)
|
||||||
wind.SetFullscreen(this);
|
wind.UnsetFullscreen(this);
|
||||||
else
|
else
|
||||||
Debug.Print("Could not find window!");
|
Debug.Print("Could not find window!");
|
||||||
|
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
else if (carbonWindow.GoWindowedHack)
|
if (mIsFullscreen)
|
||||||
{
|
return;
|
||||||
carbonWindow.GoWindowedHack = false;
|
|
||||||
CarbonGLNative wind = GetCarbonWindow(carbonWindow);
|
|
||||||
|
|
||||||
if (wind != null)
|
|
||||||
wind.UnsetFullscreen(this);
|
|
||||||
else
|
|
||||||
Debug.Print("Could not find window!");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mIsFullscreen)
|
|
||||||
return;
|
|
||||||
|
|
||||||
SetDrawable(carbonWindow);
|
SetDrawable(carbonWindow);
|
||||||
SetBufferRect(carbonWindow);
|
SetBufferRect(carbonWindow);
|
||||||
|
|
||||||
Agl.aglUpdateContext(Handle.Handle);
|
Agl.aglUpdateContext(Handle.Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CarbonGLNative GetCarbonWindow(CarbonWindowInfo carbonWindow)
|
private CarbonGLNative GetCarbonWindow(CarbonWindowInfo carbonWindow)
|
||||||
{
|
{
|
||||||
WeakReference r = CarbonGLNative.WindowRefMap[carbonWindow.WindowRef];
|
WeakReference r = CarbonGLNative.WindowRefMap[carbonWindow.WindowRef];
|
||||||
|
|
||||||
|
if (r.IsAlive)
|
||||||
|
{
|
||||||
|
return (CarbonGLNative)r.Target;
|
||||||
|
}
|
||||||
|
|
||||||
if (r.IsAlive)
|
else
|
||||||
{
|
return null;
|
||||||
return (CarbonGLNative) r.Target;
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyAGLReportError(string function)
|
void MyAGLReportError(string function)
|
||||||
{
|
{
|
||||||
Agl.AglError err = Agl.GetError();
|
Agl.AglError err = Agl.GetError();
|
||||||
|
|
||||||
if (err != Agl.AglError.NoError)
|
if (err != Agl.AglError.NoError)
|
||||||
throw new MacOSException((OSStatus)err, string.Format(
|
throw new MacOSException((OSStatus)err, string.Format("AGL Error from function {0}: {1} {2}", function, err, Agl.ErrorString(err)));
|
||||||
"AGL Error from function {0}: {1} {2}",
|
|
||||||
function, err, Agl.ErrorString(err)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool firstFullScreen = false;
|
bool firstFullScreen = false;
|
||||||
|
|
||||||
internal void SetFullScreen(CarbonWindowInfo info, out int width, out int height)
|
internal void SetFullScreen(CarbonWindowInfo info, out int width, out int height)
|
||||||
{
|
{
|
||||||
CarbonGLNative wind = GetCarbonWindow(info);
|
CarbonGLNative wind = GetCarbonWindow(info);
|
||||||
|
|
||||||
Debug.Print("Switching to full screen {0}x{1} on context {2}",
|
Debug.Print("Switching to full screen {0}x{1} on context {2}", wind.TargetDisplayDevice.Width, wind.TargetDisplayDevice.Height, Handle.Handle);
|
||||||
wind.TargetDisplayDevice.Width, wind.TargetDisplayDevice.Height, Handle.Handle);
|
|
||||||
|
CG.DisplayCapture(GetQuartzDevice(info));
|
||||||
CG.DisplayCapture(GetQuartzDevice(info));
|
Agl.aglSetFullScreen(Handle.Handle, wind.TargetDisplayDevice.Width, wind.TargetDisplayDevice.Height, 0, 0);
|
||||||
Agl.aglSetFullScreen(Handle.Handle, wind.TargetDisplayDevice.Width, wind.TargetDisplayDevice.Height, 0, 0);
|
MakeCurrent(info);
|
||||||
MakeCurrent(info);
|
|
||||||
|
width = wind.TargetDisplayDevice.Width;
|
||||||
width = wind.TargetDisplayDevice.Width;
|
height = wind.TargetDisplayDevice.Height;
|
||||||
height = wind.TargetDisplayDevice.Height;
|
|
||||||
|
|
||||||
// This is a weird hack to workaround a bug where the first time a context
|
// 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
|
// is made fullscreen, we just end up with a blank screen. So we undo it as fullscreen
|
||||||
// and redo it as fullscreen.
|
// and redo it as fullscreen.
|
||||||
if (firstFullScreen == false)
|
if (firstFullScreen == false)
|
||||||
{
|
{
|
||||||
firstFullScreen = true;
|
firstFullScreen = true;
|
||||||
UnsetFullScreen(info);
|
UnsetFullScreen(info);
|
||||||
SetFullScreen(info, out width, out height);
|
SetFullScreen(info, out width, out height);
|
||||||
}
|
}
|
||||||
|
|
||||||
mIsFullscreen = true;
|
mIsFullscreen = true;
|
||||||
}
|
}
|
||||||
internal void UnsetFullScreen(CarbonWindowInfo windowInfo)
|
internal void UnsetFullScreen(CarbonWindowInfo windowInfo)
|
||||||
{
|
{
|
||||||
Debug.Print("Unsetting AGL fullscreen.");
|
Debug.Print("Unsetting AGL fullscreen.");
|
||||||
Agl.aglSetDrawable(Handle.Handle, IntPtr.Zero);
|
Agl.aglSetDrawable(Handle.Handle, IntPtr.Zero);
|
||||||
Agl.aglUpdateContext(Handle.Handle);
|
Agl.aglUpdateContext(Handle.Handle);
|
||||||
|
|
||||||
CG.DisplayRelease(GetQuartzDevice(windowInfo));
|
CG.DisplayRelease(GetQuartzDevice(windowInfo));
|
||||||
Debug.Print("Resetting drawable.");
|
Debug.Print("Resetting drawable.");
|
||||||
SetDrawable(windowInfo);
|
SetDrawable(windowInfo);
|
||||||
|
|
||||||
mIsFullscreen = false;
|
mIsFullscreen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -393,14 +386,14 @@ namespace OpenTK.Platform.MacOS
|
||||||
{
|
{
|
||||||
Debug.WriteLine("--> Resetting drawable. <--");
|
Debug.WriteLine("--> Resetting drawable. <--");
|
||||||
firstSwap = true;
|
firstSwap = true;
|
||||||
SetDrawable(carbonWindow);
|
SetDrawable(carbonWindow);
|
||||||
Update(carbonWindow);
|
Update(carbonWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
Agl.aglSwapBuffers(Handle.Handle);
|
Agl.aglSwapBuffers(Handle.Handle);
|
||||||
MyAGLReportError("aglSwapBuffers");
|
MyAGLReportError("aglSwapBuffers");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void MakeCurrent(IWindowInfo window)
|
public override void MakeCurrent(IWindowInfo window)
|
||||||
{
|
{
|
||||||
if (Agl.aglSetCurrentContext(Handle.Handle) == false)
|
if (Agl.aglSetCurrentContext(Handle.Handle) == false)
|
||||||
|
@ -409,24 +402,18 @@ namespace OpenTK.Platform.MacOS
|
||||||
|
|
||||||
public override bool IsCurrent
|
public override bool IsCurrent
|
||||||
{
|
{
|
||||||
get
|
get { return (Handle.Handle == Agl.aglGetCurrentContext()); }
|
||||||
{
|
|
||||||
return (Handle.Handle == Agl.aglGetCurrentContext());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool VSync
|
public override bool VSync
|
||||||
{
|
{
|
||||||
get
|
get { return mVSync; }
|
||||||
{
|
|
||||||
return mVSync;
|
|
||||||
}
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
int intVal = value ? 1 : 0;
|
int intVal = value ? 1 : 0;
|
||||||
|
|
||||||
Agl.aglSetInteger(Handle.Handle, Agl.ParameterNames.AGL_SWAP_INTERVAL, ref intVal);
|
Agl.aglSetInteger(Handle.Handle, Agl.ParameterNames.AGL_SWAP_INTERVAL, ref intVal);
|
||||||
|
|
||||||
mVSync = value;
|
mVSync = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -449,34 +436,34 @@ namespace OpenTK.Platform.MacOS
|
||||||
{
|
{
|
||||||
if (IsDisposed || Handle.Handle == IntPtr.Zero)
|
if (IsDisposed || Handle.Handle == IntPtr.Zero)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Debug.Print("Disposing of AGL context.");
|
Debug.Print("Disposing of AGL context.");
|
||||||
Agl.aglSetCurrentContext(IntPtr.Zero);
|
Agl.aglSetCurrentContext(IntPtr.Zero);
|
||||||
|
|
||||||
//Debug.Print("Setting drawable to null for context {0}.", Handle.Handle);
|
//Debug.Print("Setting drawable to null for context {0}.", Handle.Handle);
|
||||||
//Agl.aglSetDrawable(Handle.Handle, IntPtr.Zero);
|
//Agl.aglSetDrawable(Handle.Handle, IntPtr.Zero);
|
||||||
|
|
||||||
// I do not know MacOS allows us to destroy a context from a separate thread,
|
// I do not know MacOS allows us to destroy a context from a separate thread,
|
||||||
// like the finalizer thread. It's untested, but worst case is probably
|
// like the finalizer thread. It's untested, but worst case is probably
|
||||||
// an exception on application exit, which would be logged to the console.
|
// an exception on application exit, which would be logged to the console.
|
||||||
Debug.Print("Destroying context");
|
Debug.Print("Destroying context");
|
||||||
if (Agl.aglDestroyContext(Handle.Handle) == true)
|
if (Agl.aglDestroyContext(Handle.Handle) == true)
|
||||||
{
|
{
|
||||||
Debug.Print("Context destruction completed successfully.");
|
Debug.Print("Context destruction completed successfully.");
|
||||||
Handle = ContextHandle.Zero;
|
Handle = ContextHandle.Zero;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// failed to destroy context.
|
// failed to destroy context.
|
||||||
Debug.WriteLine("Failed to destroy context.");
|
Debug.WriteLine("Failed to destroy context.");
|
||||||
Debug.WriteLine(Agl.ErrorString(Agl.GetError()));
|
Debug.WriteLine(Agl.ErrorString(Agl.GetError()));
|
||||||
|
|
||||||
// don't throw an exception from the finalizer thread.
|
// don't throw an exception from the finalizer thread.
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
throw new MacOSException((OSStatus)Agl.GetError(), Agl.ErrorString(Agl.GetError()));
|
throw new MacOSException((OSStatus)Agl.GetError(), Agl.ErrorString(Agl.GetError()));
|
||||||
}
|
}
|
||||||
|
|
||||||
IsDisposed = true;
|
IsDisposed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -484,7 +471,7 @@ namespace OpenTK.Platform.MacOS
|
||||||
|
|
||||||
#region IGraphicsContextInternal Members
|
#region IGraphicsContextInternal Members
|
||||||
|
|
||||||
private const string Library = "libdl.dylib";
|
private const string Library = "libdl.dylib";
|
||||||
|
|
||||||
[DllImport(Library, EntryPoint = "NSIsSymbolNameDefined")]
|
[DllImport(Library, EntryPoint = "NSIsSymbolNameDefined")]
|
||||||
private static extern bool NSIsSymbolNameDefined(string s);
|
private static extern bool NSIsSymbolNameDefined(string s);
|
||||||
|
@ -498,14 +485,14 @@ namespace OpenTK.Platform.MacOS
|
||||||
string fname = "_" + function;
|
string fname = "_" + function;
|
||||||
if (!NSIsSymbolNameDefined(fname))
|
if (!NSIsSymbolNameDefined(fname))
|
||||||
return IntPtr.Zero;
|
return IntPtr.Zero;
|
||||||
|
|
||||||
IntPtr symbol = NSLookupAndBindSymbol(fname);
|
IntPtr symbol = NSLookupAndBindSymbol(fname);
|
||||||
if (symbol != IntPtr.Zero)
|
if (symbol != IntPtr.Zero)
|
||||||
symbol = NSAddressOfSymbol(symbol);
|
symbol = NSAddressOfSymbol(symbol);
|
||||||
|
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,35 +27,36 @@ namespace OpenTK.Platform.MacOS.Carbon
|
||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void Initialize()
|
static internal void Initialize()
|
||||||
{
|
{
|
||||||
if (mInitialized) return;
|
if (mInitialized)
|
||||||
|
return;
|
||||||
|
|
||||||
API.AcquireRootMenu();
|
API.AcquireRootMenu();
|
||||||
|
|
||||||
ConnectEvents();
|
ConnectEvents();
|
||||||
|
|
||||||
API.Gestalt(GestaltSelector.SystemVersionMajor, out osMajor);
|
API.Gestalt(GestaltSelector.SystemVersionMajor, out osMajor);
|
||||||
API.Gestalt(GestaltSelector.SystemVersionMinor, out osMinor);
|
API.Gestalt(GestaltSelector.SystemVersionMinor, out osMinor);
|
||||||
API.Gestalt(GestaltSelector.SystemVersionBugFix, out osBugfix);
|
API.Gestalt(GestaltSelector.SystemVersionBugFix, out osBugfix);
|
||||||
|
|
||||||
Debug.Print("Running on Mac OS X {0}.{1}.{2}.", osMajor, osMinor, osBugfix);
|
Debug.Print("Running on Mac OS X {0}.{1}.{2}.", osMajor, osMinor, osBugfix);
|
||||||
|
|
||||||
TransformProcessToForeground();
|
TransformProcessToForeground();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void TransformProcessToForeground()
|
private static void TransformProcessToForeground()
|
||||||
{
|
{
|
||||||
Carbon.ProcessSerialNumber psn = new ProcessSerialNumber();
|
Carbon.ProcessSerialNumber psn = new ProcessSerialNumber();
|
||||||
|
|
||||||
|
Debug.Print("Setting process to be foreground application.");
|
||||||
|
|
||||||
|
API.GetCurrentProcess(ref psn);
|
||||||
|
API.TransformProcessType(ref psn, ProcessApplicationTransformState.kProcessTransformToForegroundApplication);
|
||||||
|
API.SetFrontProcess(ref psn);
|
||||||
|
}
|
||||||
|
|
||||||
Debug.Print("Setting process to be foreground application.");
|
static internal CarbonGLNative WindowEventHandler
|
||||||
|
|
||||||
API.GetCurrentProcess(ref psn);
|
|
||||||
API.TransformProcessType(ref psn, ProcessApplicationTransformState.kProcessTransformToForegroundApplication);
|
|
||||||
API.SetFrontProcess(ref psn);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static CarbonGLNative WindowEventHandler
|
|
||||||
{
|
{
|
||||||
get { return eventHandler; }
|
get { return eventHandler; }
|
||||||
set { eventHandler = value; }
|
set { eventHandler = value; }
|
||||||
|
@ -63,33 +64,16 @@ namespace OpenTK.Platform.MacOS.Carbon
|
||||||
|
|
||||||
static void ConnectEvents()
|
static void ConnectEvents()
|
||||||
{
|
{
|
||||||
EventTypeSpec[] eventTypes = new EventTypeSpec[]
|
|
||||||
{
|
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.Application, AppEventKind.AppActivated),
|
|
||||||
new EventTypeSpec(EventClass.Application, AppEventKind.AppDeactivated),
|
|
||||||
new EventTypeSpec(EventClass.Application, AppEventKind.AppQuit),
|
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) };
|
||||||
|
|
||||||
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;
|
MacOSEventHandler handler = EventHandler;
|
||||||
uppHandler = API.NewEventHandlerUPP(handler);
|
uppHandler = API.NewEventHandlerUPP(handler);
|
||||||
|
|
||||||
API.InstallApplicationEventHandler(
|
API.InstallApplicationEventHandler(uppHandler, eventTypes, IntPtr.Zero, IntPtr.Zero);
|
||||||
uppHandler, eventTypes, IntPtr.Zero, IntPtr.Zero);
|
|
||||||
|
|
||||||
mInitialized = true;
|
mInitialized = true;
|
||||||
}
|
}
|
||||||
|
@ -100,28 +84,30 @@ namespace OpenTK.Platform.MacOS.Carbon
|
||||||
|
|
||||||
switch (evt.EventClass)
|
switch (evt.EventClass)
|
||||||
{
|
{
|
||||||
case EventClass.Application:
|
case EventClass.Application:
|
||||||
switch (evt.AppEventKind)
|
switch (evt.AppEventKind)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
return OSStatus.EventNotHandled;
|
return OSStatus.EventNotHandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
case EventClass.AppleEvent:
|
|
||||||
// only event here is the apple event.
|
case EventClass.AppleEvent:
|
||||||
Debug.Print("Processing apple event.");
|
// only event here is the apple event.
|
||||||
API.ProcessAppleEvent(inEvent);
|
Debug.Print("Processing apple event.");
|
||||||
break;
|
API.ProcessAppleEvent(inEvent);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EventClass.Keyboard:
|
||||||
|
case EventClass.Mouse:
|
||||||
|
if (WindowEventHandler != null)
|
||||||
|
{
|
||||||
|
return WindowEventHandler.DispatchEvent(inCaller, inEvent, evt, userData);
|
||||||
|
}
|
||||||
|
|
||||||
case EventClass.Keyboard:
|
break;
|
||||||
case EventClass.Mouse:
|
|
||||||
if (WindowEventHandler != null)
|
|
||||||
{
|
|
||||||
return WindowEventHandler.DispatchEvent(inCaller, inEvent, evt, userData);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return OSStatus.EventNotHandled;
|
return OSStatus.EventNotHandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,9 +115,9 @@ namespace OpenTK.Platform.MacOS.Carbon
|
||||||
{
|
{
|
||||||
window.Closed += MainWindowClosed;
|
window.Closed += MainWindowClosed;
|
||||||
window.Visible = true;
|
window.Visible = true;
|
||||||
|
|
||||||
API.RunApplicationEventLoop();
|
API.RunApplicationEventLoop();
|
||||||
|
|
||||||
window.Closed -= MainWindowClosed;
|
window.Closed -= MainWindowClosed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +128,7 @@ namespace OpenTK.Platform.MacOS.Carbon
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal static void ProcessEvents()
|
static internal void ProcessEvents()
|
||||||
{
|
{
|
||||||
API.ProcessEvents();
|
API.ProcessEvents();
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -65,17 +65,26 @@ namespace OpenTK.Platform.MacOS
|
||||||
|
|
||||||
public IMouseDriver2 MouseDriver
|
public IMouseDriver2 MouseDriver
|
||||||
{
|
{
|
||||||
get { throw new NotImplementedException(); }
|
get
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IKeyboardDriver2 KeyboardDriver
|
public IKeyboardDriver2 KeyboardDriver
|
||||||
{
|
{
|
||||||
get { throw new NotImplementedException(); }
|
get
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IGamePadDriver GamePadDriver
|
public IGamePadDriver GamePadDriver
|
||||||
{
|
{
|
||||||
get { throw new NotImplementedException(); }
|
get
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,14 +36,14 @@ namespace OpenTK.Platform.MacOS
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Describes a Carbon window.
|
/// Describes a Carbon window.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
sealed class CarbonWindowInfo : IWindowInfo
|
sealed class CarbonWindowInfo : IWindowInfo
|
||||||
{
|
{
|
||||||
IntPtr windowRef;
|
IntPtr windowRef;
|
||||||
bool ownHandle = false;
|
bool ownHandle = false;
|
||||||
bool disposed = false;
|
bool disposed = false;
|
||||||
bool isControl = false;
|
bool isControl = false;
|
||||||
bool goFullScreenHack = false;
|
bool goFullScreenHack = false;
|
||||||
bool goWindowedHack = false;
|
bool goWindowedHack = false;
|
||||||
|
|
||||||
#region Constructors
|
#region Constructors
|
||||||
|
|
||||||
|
@ -72,16 +72,16 @@ namespace OpenTK.Platform.MacOS
|
||||||
get { return this.windowRef; }
|
get { return this.windowRef; }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool GoFullScreenHack
|
internal bool GoFullScreenHack
|
||||||
{
|
{
|
||||||
get { return goFullScreenHack; }
|
get { return goFullScreenHack; }
|
||||||
set { goFullScreenHack = value; }
|
set { goFullScreenHack = value; }
|
||||||
}
|
}
|
||||||
internal bool GoWindowedHack
|
internal bool GoWindowedHack
|
||||||
{
|
{
|
||||||
get { return goWindowedHack; }
|
get { return goWindowedHack; }
|
||||||
set { goWindowedHack = value; }
|
set { goWindowedHack = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -96,8 +96,7 @@ namespace OpenTK.Platform.MacOS
|
||||||
/// <returns>A System.String that represents the current window.</returns>
|
/// <returns>A System.String that represents the current window.</returns>
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return String.Format("MacOS.CarbonWindowInfo: Handle {0}",
|
return String.Format("MacOS.CarbonWindowInfo: Handle {0}", this.WindowRef);
|
||||||
this.WindowRef);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -113,19 +112,19 @@ namespace OpenTK.Platform.MacOS
|
||||||
{
|
{
|
||||||
if (disposed)
|
if (disposed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ownHandle)
|
if (ownHandle)
|
||||||
{
|
{
|
||||||
Debug.Print("Disposing window {0}.", windowRef);
|
Debug.Print("Disposing window {0}.", windowRef);
|
||||||
Carbon.API.DisposeWindow(this.windowRef);
|
Carbon.API.DisposeWindow(this.windowRef);
|
||||||
windowRef = IntPtr.Zero;
|
windowRef = IntPtr.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
disposed = true;
|
disposed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +132,7 @@ namespace OpenTK.Platform.MacOS
|
||||||
{
|
{
|
||||||
Dispose(false);
|
Dispose(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,14 +25,17 @@ namespace OpenTK.Platform.MacOS.Carbon
|
||||||
uint _eventKind;
|
uint _eventKind;
|
||||||
EventClass _eventClass;
|
EventClass _eventClass;
|
||||||
|
|
||||||
public EventClass EventClass { get { return _eventClass; }}
|
public EventClass EventClass
|
||||||
|
{
|
||||||
|
get { return _eventClass; }
|
||||||
|
}
|
||||||
|
|
||||||
public WindowEventKind WindowEventKind
|
public WindowEventKind WindowEventKind
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (EventClass == EventClass.Window)
|
if (EventClass == EventClass.Window)
|
||||||
return (WindowEventKind) _eventKind;
|
return (WindowEventKind)_eventKind;
|
||||||
else
|
else
|
||||||
throw new InvalidCastException("Event is not a Window event.");
|
throw new InvalidCastException("Event is not a Window event.");
|
||||||
}
|
}
|
||||||
|
@ -42,7 +45,7 @@ namespace OpenTK.Platform.MacOS.Carbon
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (EventClass == EventClass.Keyboard)
|
if (EventClass == EventClass.Keyboard)
|
||||||
return (KeyboardEventKind) _eventKind;
|
return (KeyboardEventKind)_eventKind;
|
||||||
else
|
else
|
||||||
throw new InvalidCastException("Event is not a Keyboard event.");
|
throw new InvalidCastException("Event is not a Keyboard event.");
|
||||||
}
|
}
|
||||||
|
@ -52,7 +55,7 @@ namespace OpenTK.Platform.MacOS.Carbon
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (EventClass == EventClass.Mouse)
|
if (EventClass == EventClass.Mouse)
|
||||||
return (MouseEventKind) _eventKind;
|
return (MouseEventKind)_eventKind;
|
||||||
else
|
else
|
||||||
throw new InvalidCastException("Event is not an Mouse event.");
|
throw new InvalidCastException("Event is not an Mouse event.");
|
||||||
}
|
}
|
||||||
|
@ -62,7 +65,7 @@ namespace OpenTK.Platform.MacOS.Carbon
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (EventClass == EventClass.Application)
|
if (EventClass == EventClass.Application)
|
||||||
return (AppEventKind) _eventKind;
|
return (AppEventKind)_eventKind;
|
||||||
else
|
else
|
||||||
throw new InvalidCastException("Event is not an Application event.");
|
throw new InvalidCastException("Event is not an Application event.");
|
||||||
}
|
}
|
||||||
|
@ -71,18 +74,18 @@ namespace OpenTK.Platform.MacOS.Carbon
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
switch(EventClass)
|
switch (EventClass)
|
||||||
{
|
{
|
||||||
case EventClass.Application:
|
case EventClass.Application:
|
||||||
return "Event: App " + AppEventKind.ToString();
|
return "Event: App " + AppEventKind.ToString();
|
||||||
case EventClass.Keyboard:
|
case EventClass.Keyboard:
|
||||||
return "Event: Keyboard " + KeyboardEventKind.ToString();
|
return "Event: Keyboard " + KeyboardEventKind.ToString();
|
||||||
case EventClass.Mouse:
|
case EventClass.Mouse:
|
||||||
return "Event: Mouse " + MouseEventKind.ToString();
|
return "Event: Mouse " + MouseEventKind.ToString();
|
||||||
case EventClass.Window:
|
case EventClass.Window:
|
||||||
return "Event: Window " + WindowEventKind.ToString();
|
return "Event: Window " + WindowEventKind.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return "Event: Unknown Class " + EventClass.ToString() + " kind: " + _eventKind.ToString();
|
return "Event: Unknown Class " + EventClass.ToString() + " kind: " + _eventKind.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ namespace OpenTK.Platform.MacOS
|
||||||
public virtual IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags)
|
public virtual IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags)
|
||||||
{
|
{
|
||||||
return new AglContext(handle, window, shareContext);
|
return new AglContext(handle, window, shareContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext()
|
public virtual GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext()
|
||||||
{
|
{
|
||||||
|
@ -79,7 +79,7 @@ namespace OpenTK.Platform.MacOS
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,20 +6,19 @@ namespace OpenTK.Platform.MacOS
|
||||||
{
|
{
|
||||||
using Graphics;
|
using Graphics;
|
||||||
|
|
||||||
class MacOSGraphicsMode : IGraphicsMode
|
class MacOSGraphicsMode : IGraphicsMode
|
||||||
{
|
{
|
||||||
#region IGraphicsMode Members
|
#region IGraphicsMode Members
|
||||||
|
|
||||||
public GraphicsMode SelectGraphicsMode(ColorFormat color, int depth, int stencil, int samples, ColorFormat accum, int buffers, bool stereo)
|
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,
|
GraphicsMode gfx = new GraphicsMode((IntPtr)1, color, depth, stencil, samples, accum, buffers, stereo);
|
||||||
accum, buffers, stereo);
|
|
||||||
|
|
||||||
System.Diagnostics.Debug.Print("Created dummy graphics mode.");
|
System.Diagnostics.Debug.Print("Created dummy graphics mode.");
|
||||||
|
|
||||||
return gfx;
|
return gfx;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace OpenTK.Platform.MacOS
|
||||||
public MacOSKeyMap()
|
public MacOSKeyMap()
|
||||||
{
|
{
|
||||||
// comments indicate members of the Key enum that are missing
|
// comments indicate members of the Key enum that are missing
|
||||||
|
|
||||||
Add(MacOSKeyCode.A, Key.A);
|
Add(MacOSKeyCode.A, Key.A);
|
||||||
// AltLeft
|
// AltLeft
|
||||||
// AltRight
|
// AltRight
|
||||||
|
@ -127,7 +127,7 @@ namespace OpenTK.Platform.MacOS
|
||||||
Add(MacOSKeyCode.X, Key.X);
|
Add(MacOSKeyCode.X, Key.X);
|
||||||
Add(MacOSKeyCode.Y, Key.Y);
|
Add(MacOSKeyCode.Y, Key.Y);
|
||||||
Add(MacOSKeyCode.Z, Key.Z);
|
Add(MacOSKeyCode.Z, Key.Z);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,13 @@ namespace OpenTK.Platform.MacOS
|
||||||
{
|
{
|
||||||
static object display_lock = new object();
|
static object display_lock = new object();
|
||||||
|
|
||||||
static Dictionary<DisplayDevice, IntPtr> displayMap =
|
static Dictionary<DisplayDevice, IntPtr> displayMap = new Dictionary<DisplayDevice, IntPtr>();
|
||||||
new Dictionary<DisplayDevice, IntPtr>();
|
|
||||||
|
|
||||||
static IntPtr mainDisplay;
|
static IntPtr mainDisplay;
|
||||||
internal static IntPtr MainDisplay { get { return mainDisplay; } }
|
static internal IntPtr MainDisplay
|
||||||
|
{
|
||||||
|
get { return mainDisplay; }
|
||||||
|
}
|
||||||
|
|
||||||
static QuartzDisplayDeviceDriver()
|
static QuartzDisplayDeviceDriver()
|
||||||
{
|
{
|
||||||
|
@ -30,135 +32,130 @@ namespace OpenTK.Platform.MacOS
|
||||||
const int maxDisplayCount = 20;
|
const int maxDisplayCount = 20;
|
||||||
IntPtr[] displays = new IntPtr[maxDisplayCount];
|
IntPtr[] displays = new IntPtr[maxDisplayCount];
|
||||||
int displayCount;
|
int displayCount;
|
||||||
|
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
fixed(IntPtr* displayPtr = displays)
|
fixed (IntPtr* displayPtr = displays)
|
||||||
{
|
{
|
||||||
CG.GetActiveDisplayList(maxDisplayCount, displayPtr, out displayCount);
|
CG.GetActiveDisplayList(maxDisplayCount, displayPtr, out displayCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Print("CoreGraphics reported {0} display(s).", displayCount);
|
Debug.Print("CoreGraphics reported {0} display(s).", displayCount);
|
||||||
Debug.Indent();
|
Debug.Indent();
|
||||||
|
|
||||||
for (int i = 0; i < displayCount; i++)
|
for (int i = 0; i < displayCount; i++)
|
||||||
{
|
{
|
||||||
IntPtr currentDisplay = displays[i];
|
IntPtr currentDisplay = displays[i];
|
||||||
|
|
||||||
// according to docs, first element in the array is always the
|
// according to docs, first element in the array is always the
|
||||||
// main display.
|
// main display.
|
||||||
bool primary = (i == 0);
|
bool primary = (i == 0);
|
||||||
|
|
||||||
if (primary)
|
if (primary)
|
||||||
mainDisplay = currentDisplay;
|
mainDisplay = currentDisplay;
|
||||||
|
|
||||||
// gets current settings
|
// gets current settings
|
||||||
int currentWidth = CG.DisplayPixelsWide(currentDisplay);
|
int currentWidth = CG.DisplayPixelsWide(currentDisplay);
|
||||||
int currentHeight = CG.DisplayPixelsHigh(currentDisplay);
|
int currentHeight = CG.DisplayPixelsHigh(currentDisplay);
|
||||||
Debug.Print("Display {0} is at {1}x{2}", i, currentWidth, currentHeight);
|
Debug.Print("Display {0} is at {1}x{2}", i, currentWidth, currentHeight);
|
||||||
|
|
||||||
IntPtr displayModesPtr = CG.DisplayAvailableModes(currentDisplay);
|
IntPtr displayModesPtr = CG.DisplayAvailableModes(currentDisplay);
|
||||||
CFArray displayModes = new CFArray(displayModesPtr);
|
CFArray displayModes = new CFArray(displayModesPtr);
|
||||||
Debug.Print("Supports {0} display modes.", displayModes.Count);
|
Debug.Print("Supports {0} display modes.", displayModes.Count);
|
||||||
|
|
||||||
DisplayResolution opentk_dev_current_res = null;
|
DisplayResolution opentk_dev_current_res = null;
|
||||||
List<DisplayResolution> opentk_dev_available_res = new List<DisplayResolution>();
|
List<DisplayResolution> opentk_dev_available_res = new List<DisplayResolution>();
|
||||||
IntPtr currentModePtr = CG.DisplayCurrentMode(currentDisplay);
|
IntPtr currentModePtr = CG.DisplayCurrentMode(currentDisplay);
|
||||||
CFDictionary currentMode = new CFDictionary(currentModePtr);
|
CFDictionary currentMode = new CFDictionary(currentModePtr);
|
||||||
|
|
||||||
for (int j = 0; j < displayModes.Count; j++)
|
for (int j = 0; j < displayModes.Count; j++)
|
||||||
{
|
{
|
||||||
CFDictionary dict = new CFDictionary(displayModes[j]);
|
CFDictionary dict = new CFDictionary(displayModes[j]);
|
||||||
|
|
||||||
int width = (int) dict.GetNumberValue("Width");
|
int width = (int)dict.GetNumberValue("Width");
|
||||||
int height = (int) dict.GetNumberValue("Height");
|
int height = (int)dict.GetNumberValue("Height");
|
||||||
int bpp = (int) dict.GetNumberValue("BitsPerPixel");
|
int bpp = (int)dict.GetNumberValue("BitsPerPixel");
|
||||||
double freq = dict.GetNumberValue("RefreshRate");
|
double freq = dict.GetNumberValue("RefreshRate");
|
||||||
bool current = currentMode.Ref == dict.Ref;
|
bool current = currentMode.Ref == dict.Ref;
|
||||||
|
|
||||||
//if (current) Debug.Write(" * ");
|
//if (current) Debug.Write(" * ");
|
||||||
//else Debug.Write(" ");
|
//else Debug.Write(" ");
|
||||||
|
|
||||||
//Debug.Print("Mode {0} is {1}x{2}x{3} @ {4}.", j, width, height, bpp, freq);
|
//Debug.Print("Mode {0} is {1}x{2}x{3} @ {4}.", j, width, height, bpp, freq);
|
||||||
|
|
||||||
DisplayResolution thisRes = new DisplayResolution(0, 0, width, height, bpp, (float)freq);
|
DisplayResolution thisRes = new DisplayResolution(0, 0, width, height, bpp, (float)freq);
|
||||||
opentk_dev_available_res.Add(thisRes);
|
opentk_dev_available_res.Add(thisRes);
|
||||||
|
|
||||||
if (current)
|
if (current)
|
||||||
opentk_dev_current_res = thisRes;
|
opentk_dev_current_res = thisRes;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HIRect bounds = CG.DisplayBounds(currentDisplay);
|
HIRect bounds = CG.DisplayBounds(currentDisplay);
|
||||||
Rectangle newRect = new Rectangle(
|
Rectangle newRect = new Rectangle((int)bounds.Origin.X, (int)bounds.Origin.Y, (int)bounds.Size.Width, (int)bounds.Size.Height);
|
||||||
(int)bounds.Origin.X, (int)bounds.Origin.Y, (int)bounds.Size.Width, (int)bounds.Size.Height);
|
|
||||||
|
Debug.Print("Display {0} bounds: {1}", i, newRect);
|
||||||
Debug.Print("Display {0} bounds: {1}", i, newRect);
|
|
||||||
|
DisplayDevice opentk_dev = new DisplayDevice(opentk_dev_current_res, primary, opentk_dev_available_res, newRect);
|
||||||
DisplayDevice opentk_dev =
|
|
||||||
new DisplayDevice(opentk_dev_current_res, primary, opentk_dev_available_res, newRect);
|
|
||||||
|
|
||||||
displayMap.Add(opentk_dev, currentDisplay);
|
displayMap.Add(opentk_dev, currentDisplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Unindent();
|
Debug.Unindent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal static IntPtr HandleTo(DisplayDevice displayDevice)
|
static internal IntPtr HandleTo(DisplayDevice displayDevice)
|
||||||
{
|
{
|
||||||
if (displayMap.ContainsKey(displayDevice))
|
if (displayMap.ContainsKey(displayDevice))
|
||||||
return displayMap[displayDevice];
|
return displayMap[displayDevice];
|
||||||
else
|
else
|
||||||
return IntPtr.Zero;
|
return IntPtr.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IDisplayDeviceDriver Members
|
#region IDisplayDeviceDriver Members
|
||||||
|
|
||||||
Dictionary<IntPtr, IntPtr> storedModes = new Dictionary<IntPtr, IntPtr>();
|
Dictionary<IntPtr, IntPtr> storedModes = new Dictionary<IntPtr, IntPtr>();
|
||||||
List<IntPtr> displaysCaptured = new List<IntPtr>();
|
List<IntPtr> displaysCaptured = new List<IntPtr>();
|
||||||
|
|
||||||
public bool TryChangeResolution(DisplayDevice device, DisplayResolution resolution)
|
public bool TryChangeResolution(DisplayDevice device, DisplayResolution resolution)
|
||||||
{
|
{
|
||||||
IntPtr display = displayMap[device];
|
IntPtr display = displayMap[device];
|
||||||
IntPtr currentModePtr = CG.DisplayCurrentMode(display);
|
IntPtr currentModePtr = CG.DisplayCurrentMode(display);
|
||||||
|
|
||||||
if (storedModes.ContainsKey(display) == false)
|
if (storedModes.ContainsKey(display) == false)
|
||||||
{
|
{
|
||||||
storedModes.Add(display, currentModePtr);
|
storedModes.Add(display, currentModePtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
IntPtr displayModesPtr = CG.DisplayAvailableModes(display);
|
IntPtr displayModesPtr = CG.DisplayAvailableModes(display);
|
||||||
CFArray displayModes = new CFArray(displayModesPtr);
|
CFArray displayModes = new CFArray(displayModesPtr);
|
||||||
|
|
||||||
for (int j = 0; j < displayModes.Count; j++)
|
for (int j = 0; j < displayModes.Count; j++)
|
||||||
{
|
{
|
||||||
CFDictionary dict = new CFDictionary(displayModes[j]);
|
CFDictionary dict = new CFDictionary(displayModes[j]);
|
||||||
|
|
||||||
int width = (int)dict.GetNumberValue("Width");
|
int width = (int)dict.GetNumberValue("Width");
|
||||||
int height = (int)dict.GetNumberValue("Height");
|
int height = (int)dict.GetNumberValue("Height");
|
||||||
int bpp = (int)dict.GetNumberValue("BitsPerPixel");
|
int bpp = (int)dict.GetNumberValue("BitsPerPixel");
|
||||||
double freq = dict.GetNumberValue("RefreshRate");
|
double freq = dict.GetNumberValue("RefreshRate");
|
||||||
|
|
||||||
if (width == resolution.Width &&
|
if (width == resolution.Width && height == resolution.Height && bpp == resolution.BitsPerPixel && System.Math.Abs(freq - resolution.RefreshRate) < 1e-6)
|
||||||
height == resolution.Height &&
|
|
||||||
bpp == resolution.BitsPerPixel &&
|
|
||||||
System.Math.Abs(freq - resolution.RefreshRate) < 1e-6)
|
|
||||||
{
|
{
|
||||||
if (displaysCaptured.Contains(display) == false)
|
if (displaysCaptured.Contains(display) == false)
|
||||||
{
|
{
|
||||||
CG.DisplayCapture(display);
|
CG.DisplayCapture(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Print("Changing resolution to {0}x{1}x{2}@{3}.", width, height, bpp, freq);
|
Debug.Print("Changing resolution to {0}x{1}x{2}@{3}.", width, height, bpp, freq);
|
||||||
|
|
||||||
CG.DisplaySwitchToMode(display, displayModes[j]);
|
CG.DisplaySwitchToMode(display, displayModes[j]);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -166,22 +163,22 @@ namespace OpenTK.Platform.MacOS
|
||||||
public bool TryRestoreResolution(DisplayDevice device)
|
public bool TryRestoreResolution(DisplayDevice device)
|
||||||
{
|
{
|
||||||
IntPtr display = displayMap[device];
|
IntPtr display = displayMap[device];
|
||||||
|
|
||||||
if (storedModes.ContainsKey(display))
|
if (storedModes.ContainsKey(display))
|
||||||
{
|
{
|
||||||
Debug.Print("Restoring resolution.");
|
Debug.Print("Restoring resolution.");
|
||||||
|
|
||||||
CG.DisplaySwitchToMode(display, storedModes[display]);
|
CG.DisplaySwitchToMode(display, storedModes[display]);
|
||||||
CG.DisplayRelease(display);
|
CG.DisplayRelease(display);
|
||||||
displaysCaptured.Remove(display);
|
displaysCaptured.Remove(display);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue