diff --git a/Source/OpenTK/Input/IInputDriver2.cs b/Source/OpenTK/Input/IInputDriver2.cs index 1ff89748..7cd788aa 100644 --- a/Source/OpenTK/Input/IInputDriver2.cs +++ b/Source/OpenTK/Input/IInputDriver2.cs @@ -1,41 +1,41 @@ -#region License -// -// The Open Toolkit Library License -// -// Copyright (c) 2006 - 2010 the Open Toolkit library. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do -// so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -#endregion - -using System; -using System.Collections.Generic; -using System.Text; - -namespace OpenTK.Input -{ - // Defines the interface for a 2nd generation input driver. - interface IInputDriver2 - { - IMouseDriver2 MouseDriver { get; } - IKeyboardDriver2 KeyboardDriver { get; } - IGamePadDriver GamePadDriver { get; } - } -} +#region License +// +// The Open Toolkit Library License +// +// Copyright (c) 2006 - 2010 the Open Toolkit library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +#endregion + +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenTK.Input +{ + // Defines the interface for a 2nd generation input driver. + interface IInputDriver2 : IDisposable + { + IMouseDriver2 MouseDriver { get; } + IKeyboardDriver2 KeyboardDriver { get; } + IGamePadDriver GamePadDriver { get; } + } +} diff --git a/Source/OpenTK/Platform/Factory.cs b/Source/OpenTK/Platform/Factory.cs index e2c4b0e9..2fe318db 100644 --- a/Source/OpenTK/Platform/Factory.cs +++ b/Source/OpenTK/Platform/Factory.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Text; namespace OpenTK.Platform @@ -37,6 +38,7 @@ namespace OpenTK.Platform { #region Fields + bool disposed; static IPlatformFactory default_implementation, embedded_implementation; #endregion @@ -133,7 +135,8 @@ namespace OpenTK.Platform class UnsupportedPlatform : IPlatformFactory { #region Fields - + + bool disposed; static readonly string error_string = "Please, refer to http://www.opentk.com for more information."; #endregion @@ -191,6 +194,72 @@ namespace OpenTK.Platform } #endregion + + #region IDisposable Members + + void Dispose(bool manual) + { + if (!disposed) + { + if (manual) + { + // nothing to do + } + else + { + Debug.Print("{0} leaked, did you forget to call Dispose()?", GetType()); + } + disposed = true; + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + ~UnsupportedPlatform() + { + Dispose(false); + } + + #endregion + } + + #endregion + + #region IDisposable Members + + void Dispose(bool manual) + { + if (!disposed) + { + if (manual) + { + Default.Dispose(); + if (Embedded != Default) + { + Embedded.Dispose(); + } + } + else + { + Debug.Print("{0} leaked, did you forget to call Dispose()?", GetType()); + } + disposed = true; + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + ~Factory() + { + Dispose(false); } #endregion diff --git a/Source/OpenTK/Platform/IPlatformFactory.cs b/Source/OpenTK/Platform/IPlatformFactory.cs index 4b968cc9..541c8710 100644 --- a/Source/OpenTK/Platform/IPlatformFactory.cs +++ b/Source/OpenTK/Platform/IPlatformFactory.cs @@ -33,7 +33,7 @@ using OpenTK.Graphics; namespace OpenTK.Platform { - interface IPlatformFactory + interface IPlatformFactory : IDisposable { INativeWindow CreateNativeWindow(int x, int y, int width, int height, string title, GraphicsMode mode, GameWindowFlags options, DisplayDevice device); diff --git a/Source/OpenTK/Platform/MacOS/Application.cs b/Source/OpenTK/Platform/MacOS/Application.cs index a972f1c1..093d4369 100644 --- a/Source/OpenTK/Platform/MacOS/Application.cs +++ b/Source/OpenTK/Platform/MacOS/Application.cs @@ -120,28 +120,32 @@ namespace OpenTK.Platform.MacOS.Carbon switch (evt.EventClass) { - case EventClass.Application: - switch (evt.AppEventKind) - { - default: - return OSStatus.EventNotHandled; - } + case EventClass.Application: + switch (evt.AppEventKind) + { + case AppEventKind.AppQuit: + API.RemoveEventHandler(uppHandler); + return OSStatus.EventNotHandled; + + default: + return OSStatus.EventNotHandled; + } - case EventClass.AppleEvent: + case EventClass.AppleEvent: // only event here is the apple event. - Debug.Print("Processing apple event."); - API.ProcessAppleEvent(inEvent); - break; + 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); - } + case EventClass.Keyboard: + case EventClass.Mouse: + if (WindowEventHandler != null) + { + return WindowEventHandler.DispatchEvent(inCaller, inEvent, evt, userData); + } - break; + break; } return OSStatus.EventNotHandled; diff --git a/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs b/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs index 15a0b8d9..cfa5f16a 100644 --- a/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs +++ b/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs @@ -175,8 +175,8 @@ namespace OpenTK.Platform.MacOS { if (uppHandler != IntPtr.Zero) { - //API.RemoveEventHandler(uppHandler); - //API.DisposeEventHandlerUPP(uppHandler); + API.RemoveEventHandler(uppHandler); + API.DisposeEventHandlerUPP(uppHandler); } uppHandler = IntPtr.Zero; @@ -925,8 +925,6 @@ namespace OpenTK.Platform.MacOS return; OnClosed(); - - Dispose(); } public WindowState WindowState diff --git a/Source/OpenTK/Platform/MacOS/HIDInput.cs b/Source/OpenTK/Platform/MacOS/HIDInput.cs index c040ff6d..8e3c6011 100755 --- a/Source/OpenTK/Platform/MacOS/HIDInput.cs +++ b/Source/OpenTK/Platform/MacOS/HIDInput.cs @@ -69,9 +69,11 @@ namespace OpenTK.Platform.MacOS readonly CFString InputLoopMode = CF.RunLoopModeDefault; readonly CFDictionary DeviceTypes = new CFDictionary(); - readonly NativeMethods.IOHIDDeviceCallback HandleDeviceAdded; - readonly NativeMethods.IOHIDDeviceCallback HandleDeviceRemoved; - readonly NativeMethods.IOHIDValueCallback HandleDeviceValueReceived; + NativeMethods.IOHIDDeviceCallback HandleDeviceAdded; + NativeMethods.IOHIDDeviceCallback HandleDeviceRemoved; + NativeMethods.IOHIDValueCallback HandleDeviceValueReceived; + + bool disposed; #endregion @@ -164,6 +166,7 @@ namespace OpenTK.Platform.MacOS // Thanks to Jase: http://www.opentk.com/node/2800 NativeMethods.IOHIDDeviceRegisterInputValueCallback(device, HandleDeviceValueReceived, device); + NativeMethods.IOHIDDeviceScheduleWithRunLoop(device, RunLoop, InputLoopMode); } } @@ -192,12 +195,19 @@ namespace OpenTK.Platform.MacOS KeyboardDevices[device] = state; } - NativeMethods.IOHIDDeviceRegisterInputValueCallback(device, null, IntPtr.Zero); + NativeMethods.IOHIDDeviceRegisterInputValueCallback(device, IntPtr.Zero, IntPtr.Zero); NativeMethods.IOHIDDeviceUnscheduleWithRunLoop(device, RunLoop, InputLoopMode); } void DeviceValueReceived(IntPtr context, IOReturn res, IntPtr sender, IOHIDValueRef val) { + if (disposed) + { + Debug.Print("DeviceValueReceived({0}, {1}, {2}, {3}) called on disposed {4}", + context, res, sender, val, GetType()); + return; + } + MouseState mouse; KeyboardState keyboard; if (MouseDevices.TryGetValue(context, out mouse)) @@ -383,6 +393,12 @@ namespace OpenTK.Platform.MacOS IOHIDDeviceCallback inIOHIDDeviceCallback, IntPtr inContext); + [DllImport(hid)] + public static extern void IOHIDManagerRegisterDeviceMatchingCallback( + IOHIDManagerRef inIOHIDManagerRef, + IntPtr inIOHIDDeviceCallback, + IntPtr inContext); + // This routine will be called when a (matching) device is disconnected. [DllImport(hid)] public static extern void IOHIDManagerRegisterDeviceRemovalCallback( @@ -390,6 +406,12 @@ namespace OpenTK.Platform.MacOS IOHIDDeviceCallback inIOHIDDeviceCallback, IntPtr inContext); + [DllImport(hid)] + public static extern void IOHIDManagerRegisterDeviceRemovalCallback( + IOHIDManagerRef inIOHIDManagerRef, + IntPtr inIOHIDDeviceCallback, + IntPtr inContext); + [DllImport(hid)] public static extern void IOHIDManagerScheduleWithRunLoop( IOHIDManagerRef inIOHIDManagerRef, @@ -428,6 +450,12 @@ namespace OpenTK.Platform.MacOS IOHIDValueCallback callback, IntPtr context); + [DllImport(hid)] + public static extern void IOHIDDeviceRegisterInputValueCallback( + IOHIDDeviceRef device, + IntPtr callback, + IntPtr context); + [DllImport(hid)] public static extern void IOHIDDeviceScheduleWithRunLoop( IOHIDDeviceRef device, @@ -939,6 +967,59 @@ namespace OpenTK.Platform.MacOS }; #endregion + + #region IDisposable Members + + + void Dispose(bool manual) + { + if (!disposed) + { + if (manual) + { + NativeMethods.IOHIDManagerRegisterDeviceMatchingCallback( + hidmanager, IntPtr.Zero, IntPtr.Zero); + NativeMethods.IOHIDManagerRegisterDeviceRemovalCallback( + hidmanager, IntPtr.Zero, IntPtr.Zero); + NativeMethods.IOHIDManagerScheduleWithRunLoop( + hidmanager, IntPtr.Zero, IntPtr.Zero); + + foreach (var device in MouseDevices.Keys) + { + NativeMethods.IOHIDDeviceRegisterInputValueCallback( + device, IntPtr.Zero, IntPtr.Zero); + } + + foreach (var device in KeyboardDevices.Keys) + { + NativeMethods.IOHIDDeviceRegisterInputValueCallback( + device, IntPtr.Zero, IntPtr.Zero); + } + + HandleDeviceAdded = null; + HandleDeviceRemoved = null; + HandleDeviceValueReceived = null; + } + else + { + Debug.Print("{0} leaked, did you forget to call Dispose()?", GetType()); + } + disposed = true; + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + ~HIDInput() + { + Dispose(false); + } + + #endregion } } diff --git a/Source/OpenTK/Platform/MacOS/MacOSFactory.cs b/Source/OpenTK/Platform/MacOS/MacOSFactory.cs index 3bae0c4c..142ef76d 100644 --- a/Source/OpenTK/Platform/MacOS/MacOSFactory.cs +++ b/Source/OpenTK/Platform/MacOS/MacOSFactory.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Text; using OpenTK.Input; @@ -38,6 +39,7 @@ namespace OpenTK.Platform.MacOS { #region Fields + bool disposed; readonly IInputDriver2 InputDriver = new HIDInput(); #endregion @@ -93,5 +95,36 @@ namespace OpenTK.Platform.MacOS } #endregion + + #region IDisposable Members + + void Dispose(bool manual) + { + if (!disposed) + { + if (manual) + { + InputDriver.Dispose(); + } + else + { + Debug.Print("{0} leaked, did you forget to call Dispose()?", GetType()); + } + disposed = true; + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + ~MacOSFactory() + { + Dispose(false); + } + + #endregion } } diff --git a/Source/OpenTK/Platform/SDL2/Sdl2Factory.cs b/Source/OpenTK/Platform/SDL2/Sdl2Factory.cs index 357af984..ee569a06 100644 --- a/Source/OpenTK/Platform/SDL2/Sdl2Factory.cs +++ b/Source/OpenTK/Platform/SDL2/Sdl2Factory.cs @@ -34,6 +34,7 @@ namespace OpenTK.Platform.SDL2 class Sdl2Factory : IPlatformFactory { readonly IInputDriver2 InputDriver = new Sdl2InputDriver(); + bool disposed; public Sdl2Factory() { @@ -102,6 +103,33 @@ namespace OpenTK.Platform.SDL2 } #endregion + + #region IDisposable Members + + void Dispose(bool manual) + { + if (!disposed) + { + if (manual) + { + InputDriver.Dispose(); + } + disposed = true; + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + ~Sdl2Factory() + { + Dispose(false); + } + + #endregion } } diff --git a/Source/OpenTK/Platform/SDL2/Sdl2InputDriver.cs b/Source/OpenTK/Platform/SDL2/Sdl2InputDriver.cs index cffb38a3..c8c1d368 100644 --- a/Source/OpenTK/Platform/SDL2/Sdl2InputDriver.cs +++ b/Source/OpenTK/Platform/SDL2/Sdl2InputDriver.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading; using OpenTK.Input; @@ -38,6 +39,7 @@ namespace OpenTK.Platform.SDL2 readonly Sdl2Keyboard keyboard_driver = new Sdl2Keyboard(); readonly Sdl2Mouse mouse_driver = new Sdl2Mouse(); readonly SDL.SDL_EventFilter EventFilterDelegate; + bool disposed; public Sdl2InputDriver() { @@ -109,6 +111,37 @@ namespace OpenTK.Platform.SDL2 } #endregion + + #region IDisposable Members + + void Dispose(bool manual) + { + if (!disposed) + { + if (manual) + { + SDL.SDL_DelEventWatch(EventFilterDelegate, IntPtr.Zero); + } + else + { + Debug.WriteLine("Sdl2InputDriver leaked, did you forget to call Dispose()?"); + } + disposed = true; + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + ~Sdl2InputDriver() + { + Dispose(false); + } + + #endregion } } diff --git a/Source/OpenTK/Platform/SDL2/Sdl2NativeWindow.cs b/Source/OpenTK/Platform/SDL2/Sdl2NativeWindow.cs index 8e1142c4..7588073c 100644 --- a/Source/OpenTK/Platform/SDL2/Sdl2NativeWindow.cs +++ b/Source/OpenTK/Platform/SDL2/Sdl2NativeWindow.cs @@ -49,6 +49,7 @@ namespace OpenTK.Platform.SDL2 WindowState previous_window_state = WindowState.Normal; WindowBorder window_border = WindowBorder.Resizable; Icon icon; + string window_title; KeyboardDevice keyboard = new KeyboardDevice(); MouseDevice mouse = new MouseDevice(); @@ -84,6 +85,7 @@ namespace OpenTK.Platform.SDL2 window = new Sdl2WindowInfo(handle, null); window_id = SDL.SDL_GetWindowID(handle); windows.Add(window_id, this); + window_title = title; keyboard.Description = "Standard Windows keyboard"; keyboard.NumberOfFunctionKeys = 12; @@ -227,6 +229,7 @@ namespace OpenTK.Platform.SDL2 { exists = false; + SDL.SDL_DelEventWatch(EventFilterDelegate, IntPtr.Zero); if (windows.ContainsKey(window_id)) { windows.Remove(window_id); @@ -245,10 +248,10 @@ namespace OpenTK.Platform.SDL2 SDL.SDL_SetRelativeMouseMode( grab ? SDL.SDL_bool.SDL_TRUE : SDL.SDL_bool.SDL_FALSE); - if (grab) - { - mouse.Position = new Point(0, 0); - } + //if (grab) + //{ + // mouse.Position = new Point(0, 0); + //} } // Hack to force WindowState events to be pumped @@ -458,6 +461,7 @@ namespace OpenTK.Platform.SDL2 set { SDL.SDL_SetWindowTitle(window.Handle, value); + window_title = value; } } diff --git a/Source/OpenTK/Platform/Windows/WMInput.cs b/Source/OpenTK/Platform/Windows/WMInput.cs index 084f20fb..b4860dbe 100644 --- a/Source/OpenTK/Platform/Windows/WMInput.cs +++ b/Source/OpenTK/Platform/Windows/WMInput.cs @@ -49,10 +49,11 @@ namespace OpenTK.Platform.Windows readonly object MouseLock = new object(); readonly object KeyboardLock = new object(); readonly WinMMJoystick gamepad_driver = new WinMMJoystick(); + readonly WinKeyMap KeyMap = new WinKeyMap(); + KeyboardState keyboard = new KeyboardState(); MouseState mouse = new MouseState(); - - readonly WinKeyMap KeyMap = new WinKeyMap(); + bool disposed; #endregion @@ -173,5 +174,36 @@ namespace OpenTK.Platform.Windows } #endregion + + #region IDisposable Members + + void Dispose(bool manual) + { + if (!disposed) + { + if (manual) + { + // Todo: implement this + } + else + { + Debug.Print("{0} leaked, did you forget to call Dispose()?", GetType()); + } + disposed = true; + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + ~WMInput() + { + Dispose(false); + } + + #endregion } } diff --git a/Source/OpenTK/Platform/Windows/WinFactory.cs b/Source/OpenTK/Platform/Windows/WinFactory.cs index 877d63f3..58f78ec6 100644 --- a/Source/OpenTK/Platform/Windows/WinFactory.cs +++ b/Source/OpenTK/Platform/Windows/WinFactory.cs @@ -37,6 +37,7 @@ namespace OpenTK.Platform.Windows class WinFactory : IPlatformFactory { + bool disposed; readonly object SyncRoot = new object(); IInputDriver2 inputDriver; @@ -123,5 +124,36 @@ namespace OpenTK.Platform.Windows } } } + + #region IDisposable Members + + void Dispose(bool manual) + { + if (!disposed) + { + if (manual) + { + InputDriver.Dispose(); + } + else + { + Debug.Print("{0} leaked, did you forget to call Dispose()?", GetType()); + } + disposed = true; + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + ~WinFactory() + { + Dispose(false); + } + + #endregion } } diff --git a/Source/OpenTK/Platform/X11/X11Factory.cs b/Source/OpenTK/Platform/X11/X11Factory.cs index e437e119..d62f618d 100644 --- a/Source/OpenTK/Platform/X11/X11Factory.cs +++ b/Source/OpenTK/Platform/X11/X11Factory.cs @@ -33,6 +33,8 @@ namespace OpenTK.Platform.X11 { class X11Factory : IPlatformFactory { + bool disposed; + #region Constructors public X11Factory() @@ -97,5 +99,36 @@ namespace OpenTK.Platform.X11 } #endregion + + #region IDisposable Members + + void Dispose(bool manual) + { + if (!disposed) + { + if (manual) + { + // nothing to do + } + else + { + Debug.Print("{0} leaked, did you forget to call Dispose()?", GetType()); + } + disposed = true; + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + ~X11Factory() + { + Dispose(false); + } + + #endregion } } diff --git a/Source/OpenTK/Toolkit.cs b/Source/OpenTK/Toolkit.cs index 00085470..332ea375 100644 --- a/Source/OpenTK/Toolkit.cs +++ b/Source/OpenTK/Toolkit.cs @@ -1,79 +1,94 @@ -#region License -// -// The Open Toolkit Library License -// -// Copyright (c) 2006 - 2009 the Open Toolkit library. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do -// so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -#endregion - -using System; -using System.Collections.Generic; -using System.Text; - -namespace OpenTK -{ - /// - /// Provides static methods to manage an OpenTK application. - /// - public sealed class Toolkit - { - volatile static bool initialized; - static readonly object InitLock = new object(); - - #region Constructors - - Toolkit() { } - - #endregion - - #region Public Members - - /// - /// Initializes OpenTK. This method is necessary only if you are using OpenTK - /// alongside a different windowing toolkit (e.g. GTK#) and should be the very - /// first method called by your application (i.e. calling this method should be - /// the very first statement executed by the "Main" method). - /// - /// - /// Some windowing toolkits do not configure the underlying platform - /// correctly or configure it in a way that is incompatible with OpenTK. - /// Calling this method first ensures that OpenTK is given the chance to - /// initialize itself and configure the platform correctly. - /// - public static void Init() - { - lock (InitLock) - { - if (!initialized) - { - initialized = true; - Configuration.Init(); - // The actual initialization takes place in the platform-specific factory - // constructors. - new Platform.Factory(); - } - } - } - - #endregion - } -} +#region License +// +// The Open Toolkit Library License +// +// Copyright (c) 2006 - 2009 the Open Toolkit library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +#endregion + +using System; +using System.Collections.Generic; +using System.Text; +using OpenTK.Platform; + +namespace OpenTK +{ + /// + /// Provides static methods to manage an OpenTK application. + /// + public sealed class Toolkit + { + static Factory platform_factory; + + volatile static bool initialized; + static readonly object InitLock = new object(); + + #region Constructors + + Toolkit() { } + + #endregion + + #region Public Members + + /// + /// Initializes OpenTK. This method is necessary only if you are using OpenTK + /// alongside a different windowing toolkit (e.g. GTK#) and should be the very + /// first method called by your application (i.e. calling this method should be + /// the very first statement executed by the "Main" method). + /// + /// + /// Some windowing toolkits do not configure the underlying platform + /// correctly or configure it in a way that is incompatible with OpenTK. + /// Calling this method first ensures that OpenTK is given the chance to + /// initialize itself and configure the platform correctly. + /// + public static IDisposable Init() + { + lock (InitLock) + { + if (!initialized) + { + initialized = true; + Configuration.Init(); + // The actual initialization takes place in the platform-specific factory + // constructors. + platform_factory = new Platform.Factory(); + AppDomain.CurrentDomain.DomainUnload += Deinit; + } + return platform_factory; + } + } + + #endregion + + #region Private Members + + static void Deinit(object sender, EventArgs e) + { + AppDomain.CurrentDomain.DomainUnload -= Deinit; + platform_factory.Dispose(); + } + + #endregion + } +}