diff --git a/Source/OpenTK/GameWindow.cs b/Source/OpenTK/GameWindow.cs
index 2fa96467..def1ff3f 100644
--- a/Source/OpenTK/GameWindow.cs
+++ b/Source/OpenTK/GameWindow.cs
@@ -29,11 +29,11 @@ using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
+using System.Drawing;
using System.Threading;
using OpenTK.Graphics;
using OpenTK.Input;
using OpenTK.Platform;
-using System.Drawing;
namespace OpenTK
{
@@ -69,16 +69,20 @@ namespace OpenTK
/// parameters that
/// specify the logic update rate, and the render update rate.
///
- public class GameWindow : IGameWindow
+ public class GameWindow : NativeWindow0, IGameWindow, IDisposable
{
#region --- Fields ---
- INativeWindow glWindow;
- //DisplayMode mode;
+ //DisplayMode mode; // TODO: Removable?
+
+ object exit_lock = new object();
+
+ IGraphicsContext glContext;
- bool isExiting = false;
bool hasMainLoop;
- bool disposed;
+ bool isExiting = false;
+
+ int main_loop_thread_id;
double update_period, render_period;
double target_update_period, target_render_period;
@@ -89,18 +93,13 @@ namespace OpenTK
//InputDriver input_driver;
- IGraphicsContext glContext;
-
- int main_loop_thread_id;
- object exit_lock = new object();
-
#endregion
#region --- Contructors ---
#region public GameWindow()
- /// Constructs a new GameWindow with sensible default attributes..
+ /// Constructs a new GameWindow with sensible default attributes.
public GameWindow()
: this(640, 480, GraphicsMode.Default, "OpenTK Game Window", 0, DisplayDevice.Default) { }
@@ -169,7 +168,7 @@ namespace OpenTK
#region public GameWindow(int width, int height, GraphicsMode mode, string title, GameWindowFlags options, DisplayDevice device, int major, int minor, GraphicsContextFlags flags)
- /// Constructs a new GameWindow with the specified attributes.
+ /// Constructs a new GameWindow with the specified attributes.
/// The width of the GameWindow in pixels.
/// The height of the GameWindow in pixels.
/// The OpenTK.Graphics.GraphicsMode of the GameWindow.
@@ -200,305 +199,68 @@ namespace OpenTK
/// The GraphicsContextFlags version for the OpenGL GraphicsContext.
/// An IGraphicsContext to share resources with.
public GameWindow(int width, int height, GraphicsMode mode, string title, GameWindowFlags options, DisplayDevice device,
- int major, int minor, GraphicsContextFlags flags, IGraphicsContext sharedContext)
+ int major, int minor, GraphicsContextFlags flags, IGraphicsContext sharedContext)
+ : base(width, height, title, options,
+ mode == null ? GraphicsMode.Default : mode,
+ device == null ? DisplayDevice.Default : device)
{
- if (width <= 0)
- throw new ArgumentOutOfRangeException("width", "Must be greater than zero.");
- if (height <= 0)
- throw new ArgumentOutOfRangeException("height", "Must be greater than zero.");
- if (mode == null)
- mode = GraphicsMode.Default;
- if (device == null)
- device = DisplayDevice.Default;
-
try
{
- Rectangle window_bounds = new Rectangle();
- window_bounds.X = device.Bounds.Left + (device.Bounds.Width - width) / 2;
- window_bounds.Y = device.Bounds.Top + (device.Bounds.Height - height) / 2;
- window_bounds.Width = width;
- window_bounds.Height = height;
- glWindow = Platform.Factory.Default.CreateNativeWindow(
- window_bounds.X, window_bounds.Y,
- window_bounds.Width, window_bounds.Height,
- title, mode, options, device);
-
- glContext = new GraphicsContext(mode, glWindow.WindowInfo, major, minor, flags);
- glContext.MakeCurrent(this.WindowInfo);
+ glContext = new GraphicsContext(mode == null ? GraphicsMode.Default : mode, WindowInfo, major, minor, flags);
+ glContext.MakeCurrent(WindowInfo);
(glContext as IGraphicsContextInternal).LoadAll();
- if ((options & GameWindowFlags.Fullscreen) != 0)
- {
- device.ChangeResolution(width, height, mode.ColorFormat.BitsPerPixel, 0);
- this.WindowState = WindowState.Fullscreen;
- }
+ VSync = VSyncMode.On;
- this.VSync = VSyncMode.On;
-
- glWindow.Move += delegate(object sender, EventArgs e) { OnMoveInternal(e); };
- glWindow.Resize += delegate(object sender, EventArgs e) { OnResizeInternal(e); };
- glWindow.Closing += delegate(object sender, CancelEventArgs e) { OnClosingInternal(e); };
- glWindow.Closed += delegate(object sender, EventArgs e) { OnClosedInternal(e); };
//glWindow.WindowInfoChanged += delegate(object sender, EventArgs e) { OnWindowInfoChangedInternal(e); };
- glWindow.WindowBorderChanged += delegate(object sender, EventArgs e) { OnWindowBorderChangedInternal(e); };
- glWindow.WindowStateChanged += delegate(object sender, EventArgs e) { OnWindowStateChangedInternal(e); };
+ EnableEvents();
}
catch (Exception e)
{
Debug.Print(e.ToString());
- if (glWindow != null)
- glWindow.Dispose();
+ base.Dispose();
throw;
}
}
#endregion
-
- #endregion
-
- #region --- Private Methods ---
-
- #region void ExitInternal()
-
- // Stops the main loop, if one exists.
- void ExitInternal()
- {
- if (HasMainLoop)
- {
- throw new GameWindowExitException();
- }
- }
-
- #region void ExitAsync()
-
- // Gracefully exits the GameWindow. May be called from any thread.
- void ExitAsync()
- {
- HasMainLoop = false;
- isExiting = true;
- //UpdateFrame += delegate
- //{
- // ExitInternal();
- //};
- }
-
- #endregion
-
- #endregion
-
- #region bool MustResize
-
- bool MustResize
- {
- get { return glWindow.Width != this.Width || glWindow.Height != this.Height; }
- }
-
- #endregion
-
- #region bool HasMainLoop
-
- bool HasMainLoop
- {
- get { return hasMainLoop; }
- set { hasMainLoop = value; }
- }
-
- #endregion
-
- #region OnMoveInternal
-
- // Calls OnMove and raises the Move event.
- void OnMoveInternal(EventArgs e)
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- if (!this.Exists || this.IsExiting)
- return;
-
- OnMove(e);
-
- if (Move != null)
- Move(this, e);
- }
-
- #endregion
-
- #region OnResizeInternal
-
- // Calls OnResize and raises the Resize event.
- void OnResizeInternal(EventArgs e)
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- if (!this.Exists || this.IsExiting)
- return;
-
- OnResize(e);
-
- if (Resize != null)
- Resize(this, e);
- }
-
- #endregion
-
- #region OnClosingInternal
-
- void OnClosingInternal(CancelEventArgs e)
- {
- OnClosing(e);
-
- if (Closing != null)
- Closing(this, e);
-
- if (!e.Cancel)
- ExitAsync();
- }
-
- #endregion
-
- #region OnClosedInternal
-
- void OnClosedInternal(EventArgs e)
- {
- OnClosed(e);
-
- if (Closed != null)
- Closed(this, e);
- }
-
- #endregion
-
- #region OnWindowInfoChangedInternal
-
- void OnWindowInfoChangedInternal(EventArgs e)
- {
- glContext.MakeCurrent(WindowInfo);
-
- OnWindowInfoChanged(e);
- }
-
- #endregion
-
- #region OnWindowBorderChangedInternal
-
- void OnWindowBorderChangedInternal(EventArgs e)
- {
- OnWindowBorderChanged(e);
-
- WindowBorderChanged(this, EventArgs.Empty);
- }
-
- #endregion
-
- #region OnWindowStateChangedInternal
-
- void OnWindowStateChangedInternal(EventArgs e)
- {
- OnWindowStateChanged(e);
-
- WindowStateChanged(this, e);
- }
-
- #endregion
-
- #region OnUpdateFrameInternal
-
- private void OnUpdateFrameInternal(FrameEventArgs e)
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- if (!this.Exists || this.IsExiting)
- return;
-
- if (UpdateFrame != null)
- UpdateFrame(this, e);
-
- OnUpdateFrame(e);
- }
-
- #endregion
-
- #region OnRenderFrameInternal
-
- private void OnRenderFrameInternal(FrameEventArgs e)
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- if (!this.Exists || this.IsExiting)
- return;
-
- if (RenderFrame != null)
- RenderFrame(this, e);
-
- OnRenderFrame(e);
- }
-
- #endregion
-
- #endregion
-
- #region --- Protected Members ---
-
- ///
- /// Called when the GameWindow is moved.
- ///
- /// Not used.
- protected virtual void OnMove(EventArgs e)
- { }
-
- ///
- /// Called when the GameWindow is resized.
- ///
- /// Not used.
- protected virtual void OnResize(EventArgs e)
- { }
-
- ///
- /// Called when the GameWindow is about to close.
- ///
- ///
- /// The for this event.
- /// Set e.Cancel to true in order to stop the GameWindow from closing.
- protected virtual void OnClosing(CancelEventArgs e)
- { }
-
- ///
- /// Called when the GameWindow has closed.
- ///
- /// Not used.
- protected virtual void OnClosed(EventArgs e)
- { }
-
- ///
- /// Called when the WindowInfo for this GameWindow has changed.
- ///
- /// Not used.
- protected virtual void OnWindowInfoChanged(EventArgs e)
- { }
-
- ///
- /// Called when the WindowBorder for this GameWindow has changed.
- ///
- /// Not used.
- protected virtual void OnWindowBorderChanged(EventArgs e)
- { }
-
- ///
- /// Called when the WindowState for this GameWindow has changed.
- ///
- /// Not used.
- protected virtual void OnWindowStateChanged(EventArgs e)
- { }
#endregion
#region --- Public Members ---
- #region public virtual void Exit()
+ #region Methods
+
+ #region Dispose
+
+ ///
+ /// Disposes of the GameWindow, releasing all resources consumed by it.
+ ///
+ public new void Dispose()
+ {
+ try
+ {
+ Dispose(true);
+ }
+ finally
+ {
+ if (!IsDisposed())
+ {
+ if (glContext != null)
+ {
+ glContext.Dispose();
+ glContext = null;
+ }
+
+ base.Dispose();
+ }
+ }
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+
+ #region Exit
///
/// Gracefully exits the GameWindow. May be called from any thread.
@@ -511,18 +273,17 @@ namespace OpenTK
{
lock (exit_lock)
{
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
+ EnsureUndisposed();
if (!IsExiting && Exists)
{
CancelEventArgs e = new CancelEventArgs();
- OnClosingInternal(e);
+ OnClosing(e);
if (e.Cancel)
return;
isExiting = true;
-
+
if (HasMainLoop)
{
if (main_loop_thread_id == Thread.CurrentThread.ManagedThreadId)
@@ -536,83 +297,43 @@ namespace OpenTK
#endregion
- #region public IGraphicsContext Context
+ #region MakeCurrent
///
- /// Returns the opengl IGraphicsContext associated with the current GameWindow.
+ /// Makes the GraphicsContext current on the calling thread.
///
- public IGraphicsContext Context
+ public void MakeCurrent()
{
- get
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
- return glContext;
- }
+ EnsureUndisposed();
+ Context.MakeCurrent(WindowInfo);
}
#endregion
- #region public bool Exists
+ #region OnLoad
///
- /// Gets a value indicating whether a render window exists.
+ /// Occurs after establishing an OpenGL context, but before entering the main loop.
+ /// Override to load resources that should be maintained for the lifetime of the application.
///
- public bool Exists
+ /// Not used.
+ public virtual void OnLoad(EventArgs e)
{
- get { return glWindow == null ? false : glWindow.Exists; }
+ EnsureUndisposed(); //if (disposed) throw new ObjectDisposedException("GameWindow"); // What is the exact purpose?
}
#endregion
- #region public string Text
+ #region OnUnload
///
- /// Gets or sets the GameWindow title.
+ /// Occurs after after calling GameWindow.Exit, but before destroying the OpenGL context.
+ /// Override to unload application resources.
///
- public string Title
+ /// Not used.
+ public virtual void OnUnload(EventArgs e)
{
- get
- {
- if (disposed) throw new ObjectDisposedException(this.GetType().Name);
- return glWindow.Title;
- }
- set
- {
- if (disposed) throw new ObjectDisposedException(this.GetType().Name);
- glWindow.Title = value;
- }
- }
-
- #endregion
-
- #region public bool Visible
-#if false
- ///
- /// TODO: This property is not implemented
- /// Gets or sets a value indicating whether the GameWindow is visible.
- ///
- public bool Visible
- {
- get
- {
- throw new NotImplementedException();
- //return glWindow.Visible;
- }
- set
- {
- throw new NotImplementedException();
- //glWindow.Visible = value;
- }
- }
-#endif
- #endregion
-
- #region public IWindowInfo WindowInfo
-
- public IWindowInfo WindowInfo
- {
- get { if (disposed) throw new ObjectDisposedException("GameWindow"); return glWindow.WindowInfo; }
+ EnsureUndisposed(); //if (disposed) throw new ObjectDisposedException("GameWindow"); // What is the exact purpose?
}
#endregion
@@ -625,7 +346,6 @@ namespace OpenTK
///
public void Run()
{
- if (disposed) throw new ObjectDisposedException(this.GetType().Name);
Run(0.0, 0.0);
}
@@ -639,9 +359,6 @@ namespace OpenTK
///
public void Run(double updateRate)
{
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
Run(updateRate, 0.0);
}
@@ -652,19 +369,25 @@ namespace OpenTK
///
/// Enters the game loop of the GameWindow updating and rendering at the specified frequency.
///
+ ///
+ /// When overriding the default game loop you should call ProcessEvents()
+ /// to ensure that your GameWindow responds to operating system events.
+ ///
+ /// Once ProcessEvents() returns, it is time to call update and render the next frame.
+ ///
+ ///
/// The frequency of UpdateFrame events.
/// The frequency of RenderFrame events.
public void Run(double updates_per_second, double frames_per_second)
{
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
+ EnsureUndisposed();
try
{
// Necessary to be here, otherwise Exit() wouldn't work correctly when called inside OnLoad().
hasMainLoop = true;
main_loop_thread_id = Thread.CurrentThread.ManagedThreadId;
-
+
if (updates_per_second < 0.0 || updates_per_second > 200.0)
throw new ArgumentOutOfRangeException("updates_per_second", updates_per_second,
"Parameter should be inside the range [0.0, 200.0]");
@@ -685,7 +408,6 @@ namespace OpenTK
render_watch.Reset();
OnLoadInternal(EventArgs.Empty);
- OnResizeInternal(EventArgs.Empty);
Debug.Print("Entering main loop.");
while (!IsExiting && HasMainLoop)
@@ -778,136 +500,48 @@ namespace OpenTK
if (Exists)
{
- glContext.Dispose();
- glContext = null;
-
- glWindow.Dispose();
- while (this.Exists)
- this.ProcessEvents();
- glWindow = null;
+ Dispose();
+ //while (this.Exists) ProcessEvents(); // TODO: Should similar behaviour be retained, possibly on native window level?
}
}
}
#endregion
- #region public void ProcessEvents()
+ #region SwapBuffers
///
- /// Processes operating system events until the GameWindow becomes idle.
+ /// Swaps the front and back buffer, presenting the rendered scene to the user.
///
- ///
- /// When overriding the default GameWindow game loop (provided by the Run() function)
- /// you should call ProcessEvents() to ensure that your GameWindow responds to
- /// operating system events.
- ///
- /// Once ProcessEvents() returns, it is time to call update and render the next frame.
- ///
- ///
- public void ProcessEvents()
+ public void SwapBuffers()
{
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- glWindow.ProcessEvents();
+ EnsureUndisposed();
+ this.Context.SwapBuffers();
}
#endregion
- #region OnRenderFrame
-
- ///
- /// Override in derived classes to render a frame.
- ///
- /// Contains information necessary for frame rendering.
- ///
- /// The base implementation (base.OnRenderFrame) is empty, there is no need to call it.
- ///
- protected virtual void OnRenderFrame(FrameEventArgs e)
- {
- }
-
- ///
- /// Occurs when it is time to render a frame.
- ///
- public event EventHandler RenderFrame;
-
#endregion
- #region OnUpdateFrame
+ #region Properties
+
+ #region Context
///
- /// Override in derived classes to update a frame.
+ /// Returns the opengl IGraphicsContext associated with the current GameWindow.
///
- /// Contains information necessary for frame updating.
- ///
- /// The base implementation (base.OnUpdateFrame) is empty, there is no need to call it.
- ///
- protected virtual void OnUpdateFrame(FrameEventArgs e)
+ public IGraphicsContext Context
{
- }
-
- ///
- /// Occurs when it is time to update a frame.
- ///
- public event EventHandler UpdateFrame;
-
- #endregion
-
- #region OnLoad
-
- ///
- /// Raises the Load event, and calls the user's OnLoad override.
- ///
- ///
- private void OnLoadInternal(EventArgs e)
- {
- OnResizeInternal(EventArgs.Empty);
- Load(this, e);
- OnLoad(e);
- }
-
- ///
- /// Occurs after establishing an OpenGL context, but before entering the main loop.
- /// Override to load resources that should be maintained for the lifetime of the application.
- ///
- /// Not used.
- public virtual void OnLoad(EventArgs e)
- {
- if (disposed) throw new ObjectDisposedException("GameWindow");
- }
-
- #endregion
-
- #region OnUnload
-
- ///
- /// Raises the Unload event, and calls the user's OnUnload override.
- ///
- ///
- private void OnUnloadInternal(EventArgs e)
- {
- if (this.Unload != null)
+ get
{
- this.Unload(this, e);
+ EnsureUndisposed();
+ return glContext;
}
-
- OnUnload(e);
- }
-
- ///
- /// Occurs after after calling GameWindow.Exit, but before destroying the OpenGL context.
- /// Override to unload application resources.
- ///
- /// Not used.
- public virtual void OnUnload(EventArgs e)
- {
- if (disposed) throw new ObjectDisposedException("GameWindow");
}
#endregion
- #region public bool IsExiting
+ #region IsExiting
///
/// Gets a value indicating whether the shutdown sequence has been initiated
@@ -919,53 +553,14 @@ namespace OpenTK
{
get
{
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
+ EnsureUndisposed();
return isExiting;
}
}
#endregion
- #region public Keyboard Keyboard
-
- ///
- /// Gets the primary Keyboard device, or null if no Keyboard exists.
- ///
- [Obsolete]
- public KeyboardDevice Keyboard
- {
- get
- {
- if (InputDriver.Keyboard.Count > 0)
- return InputDriver.Keyboard[0];
- else
- return null;
- }
- }
-
- #endregion
-
- #region public Mouse Mouse
-
- ///
- /// Gets the primary Mouse device, or null if no Mouse exists.
- ///
- [Obsolete]
- public MouseDevice Mouse
- {
- get
- {
- if (InputDriver.Mouse.Count > 0)
- return InputDriver.Mouse[0];
- else
- return null;
- }
- }
-
- #endregion
-
- #region public IList Joysticks
+ #region Joysticks
///
/// Gets a readonly IList containing all available OpenTK.Input.JoystickDevices.
@@ -978,525 +573,32 @@ namespace OpenTK
#endregion
- #region public VSyncMode VSync
+ #region Keyboard
///
- /// Gets or sets the VSyncMode.
- ///
- public VSyncMode VSync
- {
- get
- {
- if (disposed)
- throw new ObjectDisposedException("GameWindow");
-
- GraphicsContext.Assert();
-
- return vsync;
- }
- set
- {
- if (disposed)
- throw new ObjectDisposedException("GameWindow");
-
- GraphicsContext.Assert();
-
- if (value == VSyncMode.Off)
- Context.VSync = false;
- else
- Context.VSync = true;
-
- vsync = value;
- }
- }
-
- #endregion
-
- #region MakeCurrent
-
- ///
- /// Makes the GraphicsContext current on the calling thread.
- ///
- public void MakeCurrent()
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- Context.MakeCurrent(WindowInfo);
- }
-
- #endregion
-
- #region public void SwapBuffers()
-
- ///
- /// Swaps the front and back buffer, presenting the rendered scene to the user.
- ///
- public void SwapBuffers()
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- this.Context.SwapBuffers();
- }
-
- #endregion
-
- #region public WindowState WindowState
-
- ///
- /// Gets or states the state of the GameWindow.
- ///
- public WindowState WindowState
- {
- get
- {
- return glWindow.WindowState;
- }
- set
- {
- glWindow.WindowState = value;
- }
- }
-
- #endregion
-
- #region public WindowBorder WindowBorder
-
- ///
- /// Gets or states the border of the GameWindow.
- ///
- public WindowBorder WindowBorder
- {
- get
- {
- return glWindow.WindowBorder;
- }
- set
- {
- glWindow.WindowBorder = value;
- }
- }
-
- #endregion
-
- #endregion
-
- #region --- INativeWindow Members ---
-
- #region Focused
-
- ///
- /// Gets a System.Boolean that indicates whether this GameWindow has input focus.
- ///
- public bool Focused
- {
- get
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- return glWindow.Focused;
- }
- }
-
- #endregion
-
- #region Visible
-
- ///
- /// Gets or sets a System.Boolean that indicates whether this GameWindow is visible.
- ///
- public bool Visible
- {
- get
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- return glWindow.Visible;
- }
- set
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- glWindow.Visible = value;
- }
- }
-
- #endregion
-
- #region Bounds
-
- ///
- /// Gets or sets a structure the contains the external bounds of this window, in screen coordinates.
- /// External bounds include the title bar, borders and drawing area of the window.
- ///
- public Rectangle Bounds
- {
- get
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- return glWindow.Bounds;
- }
- set
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- glWindow.Bounds = value;
- }
- }
-
- #endregion
-
- #region Location
-
- ///
- /// Gets or sets a structure that contains the location of this window on the desktop.
- ///
- public Point Location
- {
- get
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- return glWindow.Location;
- }
- set
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- glWindow.Location = value;
- }
- }
-
- #endregion
-
- #region Size
-
- ///
- /// Gets or sets a structure that contains the external size of this window.
- ///
- public Size Size
- {
- get
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- return glWindow.Size;
- }
- set
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- glWindow.Size = value;
- }
- }
-
- #endregion
-
- #region X
-
- ///
- /// Gets or sets the horizontal location of this window on the desktop.
- ///
- public int X
- {
- get
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- return glWindow.X;
- }
- set
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- glWindow.X = value;
- }
- }
-
- #endregion
-
- #region Y
-
- ///
- /// Gets or sets the vertical location of this window on the desktop.
- ///
- public int Y
- {
- get
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- return glWindow.Y;
- }
- set
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- glWindow.Y = value;
- }
- }
-
- #endregion
-
- #region Width
-
- ///
- /// Gets or sets the external width of this window.
- ///
- public int Width
- {
- get
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- return glWindow.Width;
- }
- set
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- glWindow.Width = value;
- }
- }
-
- #endregion
-
- #region Height
-
- ///
- /// Gets or sets the external height of this window.
- ///
- public int Height
- {
- get
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- return glWindow.Height;
- }
- set
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- glWindow.Height = value;
- }
- }
-
- #endregion
-
- #region ClientRectangle
-
- ///
- /// Gets or sets a structure that contains the internal bounds of this window, in client coordinates.
- /// The internal bounds include the drawing area of the window, but exclude the titlebar and window borders.
- ///
- public Rectangle ClientRectangle
- {
- get
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- return glWindow.ClientRectangle;
- }
- set
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- glWindow.ClientRectangle = value;
- }
- }
-
- #endregion
-
- #region ClientSize
-
- ///
- /// Gets or sets a structure that contains the internal size this window.
- ///
- public Size ClientSize
- {
- get
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- return glWindow.ClientSize;
- }
- set
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- glWindow.ClientSize = value;
- }
- }
-
- #endregion
-
- #region InputDriver
-
- ///
- /// This property is deprecated.
+ /// Gets the primary Keyboard device, or null if no Keyboard exists.
///
[Obsolete]
- public IInputDriver InputDriver
+ public KeyboardDevice Keyboard
{
- get
- {
- if (disposed)
- throw new ObjectDisposedException(this.GetType().Name);
-
- return glWindow.InputDriver;
- }
+ get { return InputDriver.Keyboard.Count > 0 ? InputDriver.Keyboard[0] : null; }
}
#endregion
- #region Close
+ #region Mouse
///
- /// Closes the GameWindow. Equivalent to calling .
+ /// Gets the primary Mouse device, or null if no Mouse exists.
///
- public void Close()
+ [Obsolete]
+ public MouseDevice Mouse
{
- Exit();
+ get { return InputDriver.Mouse.Count > 0 ? InputDriver.Mouse[0] : null; }
}
#endregion
- #region PointToClient
-
- ///
- /// Transforms the specified point from screen to client coordinates.
- ///
- ///
- /// A to transform.
- ///
- ///
- /// The point transformed to client coordinates.
- ///
- public System.Drawing.Point PointToClient(System.Drawing.Point point)
- {
- return glWindow.PointToClient(point);
- }
-
- #endregion
-
- #region PointToScreen
-
- ///
- /// Transforms the specified point from client to screen coordinates.
- ///
- ///
- /// A to transform.
- ///
- ///
- /// The point transformed to screen coordinates.
- ///
- public System.Drawing.Point PointToScreen(System.Drawing.Point point)
- {
- // Here we use the fact that PointToClient just translates the point, and PointToScreen
- // should perform the inverse operation.
- System.Drawing.Point trans = PointToClient(System.Drawing.Point.Empty);
- point.X -= trans.X;
- point.Y -= trans.Y;
- return point;
- }
-
- #endregion
-
- #region Events
-
- ///
- /// Occurs before the window is displayed for the first time.
- ///
- public event EventHandler Load = delegate { };
-
- ///
- /// Occurs before the window is destroyed.
- ///
- public event EventHandler Unload = delegate { };
-
- ///
- /// Occurs whenever the window is moved.
- ///
- public event EventHandler Move = delegate { };
-
- ///
- /// Occurs whenever the window is resized.
- ///
- public event EventHandler Resize = delegate { };
-
- ///
- /// Occurs when the window is about to close.
- ///
- public event EventHandler Closing = delegate { };
-
- ///
- /// Occurs after the window has closed.
- ///
- public event EventHandler Closed = delegate { };
-
- ///
- /// Occurs when the window is disposed.
- ///
- public event EventHandler Disposed = delegate { };
-
- ///
- /// Occurs when the property of the window changes.
- ///
- public event EventHandler TitleChanged = delegate { };
-
- ///
- /// Occurs when the property of the window changes.
- ///
- public event EventHandler VisibleChanged = delegate { };
-
- ///
- /// Occurs when the property of the window changes.
- ///
- public event EventHandler FocusedChanged = delegate { };
-
- ///
- /// Occurs when the property of the window changes.
- ///
- public event EventHandler WindowBorderChanged = delegate { };
-
- ///
- /// Occurs when the property of the window changes.
- ///
- public event EventHandler WindowStateChanged = delegate { };
-
- ///
- /// Occurs whenever a character is typed.
- ///
- public event EventHandler KeyPress = delegate { };
-
- #endregion
-
- #endregion
-
#region --- GameWindow Timing ---
// TODO: Disabled because it is not reliable enough. Use vsync as a workaround.
@@ -1511,7 +613,97 @@ namespace OpenTK
//#endregion
- #region public double TargetRenderPeriod
+ #region RenderFrequency
+
+ ///
+ /// Gets a double representing the actual frequency of RenderFrame events, in Herz (i.e. FPS or Frames Per Second).
+ ///
+ public double RenderFrequency
+ {
+ get
+ {
+ EnsureUndisposed();
+ if (render_period == 0.0)
+ return 1.0;
+ return 1.0 / render_period;
+ }
+ }
+
+ #endregion
+
+ #region RenderPeriod
+
+ ///
+ /// Gets a double representing the period of RenderFrame events, in seconds.
+ ///
+ public double RenderPeriod
+ {
+ get
+ {
+ EnsureUndisposed();
+ return render_period;
+ }
+ }
+
+ #endregion
+
+ #region RenderTime
+
+ ///
+ /// Gets a double representing the time spent in the RenderFrame function, in seconds.
+ ///
+ public double RenderTime
+ {
+ get
+ {
+ EnsureUndisposed();
+ return render_time;
+ }
+ protected set
+ {
+ EnsureUndisposed();
+ render_time = value;
+ }
+ }
+
+ #endregion
+
+ #region TargetRenderFrequency
+
+ ///
+ /// Gets or sets a double representing the target render frequency, in Herz.
+ ///
+ ///
+ /// A value of 0.0 indicates that RenderFrame events are generated at the maximum possible frequency (i.e. only limited by the hardware's capabilities).
+ /// Values lower than 1.0Hz are clamped to 1.0Hz. Values higher than 200.0Hz are clamped to 200.0Hz.
+ ///
+ public double TargetRenderFrequency
+ {
+ get
+ {
+ EnsureUndisposed();
+ if (TargetRenderPeriod == 0.0)
+ return 0.0;
+ return 1.0 / TargetRenderPeriod;
+ }
+ set
+ {
+ EnsureUndisposed();
+ if (value < 1.0)
+ {
+ TargetRenderPeriod = 0.0;
+ }
+ else if (value <= 200.0)
+ {
+ TargetRenderPeriod = 1.0 / value;
+ }
+ else Debug.Print("Target render frequency clamped to 200.0Hz."); // TODO: Where is it actually performed?
+ }
+ }
+
+ #endregion
+
+ #region TargetRenderPeriod
///
/// Gets or sets a double representing the target render period, in seconds.
@@ -1524,12 +716,12 @@ namespace OpenTK
{
get
{
- if (disposed) throw new ObjectDisposedException("GameWindow");
+ EnsureUndisposed();
return target_render_period;
}
set
{
- if (disposed) throw new ObjectDisposedException("GameWindow");
+ EnsureUndisposed();
if (value <= 0.005)
{
target_render_period = 0.0;
@@ -1544,75 +736,7 @@ namespace OpenTK
#endregion
- #region public double TargetRenderFrequency
-
- ///
- /// Gets or sets a double representing the target render frequency, in Herz.
- ///
- ///
- /// A value of 0.0 indicates that RenderFrame events are generated at the maximum possible frequency (i.e. only limited by the hardware's capabilities).
- /// Values lower than 1.0Hz are clamped to 1.0Hz. Values higher than 200.0Hz are clamped to 200.0Hz.
- ///
- public double TargetRenderFrequency
- {
- get
- {
- if (disposed) throw new ObjectDisposedException("GameWindow");
- if (TargetRenderPeriod == 0.0)
- return 0.0;
- return 1.0 / TargetRenderPeriod;
- }
- set
- {
- if (disposed) throw new ObjectDisposedException("GameWindow");
- if (value < 1.0)
- {
- TargetRenderPeriod = 0.0;
- }
- else if (value <= 200.0)
- {
- TargetRenderPeriod = 1.0 / value;
- }
- else Debug.Print("Target render frequency clamped to 200.0Hz.");
- }
- }
-
- #endregion
-
- #region public double TargetUpdatePeriod
-
- ///
- /// Gets or sets a double representing the target update period, in seconds.
- ///
- ///
- /// A value of 0.0 indicates that UpdateFrame events are generated at the maximum possible frequency (i.e. only limited by the hardware's capabilities).
- /// Values lower than 0.005 seconds (200Hz) are clamped to 0.0. Values higher than 1.0 seconds (1Hz) are clamped to 1.0.
- ///
- public double TargetUpdatePeriod
- {
- get
- {
- if (disposed) throw new ObjectDisposedException("GameWindow");
- return target_update_period;
- }
- set
- {
- if (disposed) throw new ObjectDisposedException("GameWindow");
- if (value <= 0.005)
- {
- target_update_period = 0.0;
- }
- else if (value <= 1.0)
- {
- target_update_period = value;
- }
- else Debug.Print("Target update period clamped to 1.0 seconds.");
- }
- }
-
- #endregion
-
- #region public double TargetUpdateFrequency
+ #region TargetUpdateFrequency
///
/// Gets or sets a double representing the target update frequency, in Herz.
@@ -1625,14 +749,14 @@ namespace OpenTK
{
get
{
- if (disposed) throw new ObjectDisposedException("GameWindow");
+ EnsureUndisposed();
if (TargetUpdatePeriod == 0.0)
return 0.0;
return 1.0 / TargetUpdatePeriod;
}
set
{
- if (disposed) throw new ObjectDisposedException("GameWindow");
+ EnsureUndisposed();
if (value < 1.0)
{
TargetUpdatePeriod = 0.0;
@@ -1641,47 +765,46 @@ namespace OpenTK
{
TargetUpdatePeriod = 1.0 / value;
}
- else Debug.Print("Target update frequency clamped to 200.0Hz.");
+ else Debug.Print("Target update frequency clamped to 200.0Hz."); // TODO: Where is it actually performed?
}
}
#endregion
- #region public double RenderFrequency
+ #region TargetUpdatePeriod
///
- /// Gets a double representing the actual frequency of RenderFrame events, in Herz (i.e. FPS or Frames Per Second).
+ /// Gets or sets a double representing the target update period, in seconds.
///
- public double RenderFrequency
+ ///
+ /// A value of 0.0 indicates that UpdateFrame events are generated at the maximum possible frequency (i.e. only limited by the hardware's capabilities).
+ /// Values lower than 0.005 seconds (200Hz) are clamped to 0.0. Values higher than 1.0 seconds (1Hz) are clamped to 1.0.
+ ///
+ public double TargetUpdatePeriod
{
get
{
- if (disposed) throw new ObjectDisposedException("GameWindow");
- if (render_period == 0.0)
- return 1.0;
- return 1.0 / render_period;
+ EnsureUndisposed();
+ return target_update_period;
}
- }
-
- #endregion
-
- #region public double RenderPeriod
-
- ///
- /// Gets a double representing the period of RenderFrame events, in seconds.
- ///
- public double RenderPeriod
- {
- get
+ set
{
- if (disposed) throw new ObjectDisposedException("GameWindow");
- return render_period;
+ EnsureUndisposed();
+ if (value <= 0.005)
+ {
+ target_update_period = 0.0;
+ }
+ else if (value <= 1.0)
+ {
+ target_update_period = value;
+ }
+ else Debug.Print("Target update period clamped to 1.0 seconds."); // TODO: Where is it actually performed?
}
}
#endregion
- #region public double UpdateFrequency
+ #region UpdateFrequency
///
/// Gets a double representing the frequency of UpdateFrame events, in Herz.
@@ -1690,7 +813,7 @@ namespace OpenTK
{
get
{
- if (disposed) throw new ObjectDisposedException("GameWindow");
+ EnsureUndisposed();
if (update_period == 0.0)
return 1.0;
return 1.0 / update_period;
@@ -1699,7 +822,7 @@ namespace OpenTK
#endregion
- #region public double UpdatePeriod
+ #region UpdatePeriod
///
/// Gets a double representing the period of UpdateFrame events, in seconds.
@@ -1708,88 +831,259 @@ namespace OpenTK
{
get
{
- if (disposed) throw new ObjectDisposedException("GameWindow");
+ EnsureUndisposed();
return update_period;
}
}
#endregion
- #region public double RenderTime
-
- ///
- /// Gets a double representing the time spent in the RenderFrame function, in seconds.
- ///
- public double RenderTime
- {
- get { if (disposed) throw new ObjectDisposedException("GameWindow"); return render_time; }
- protected set { if (disposed) throw new ObjectDisposedException("GameWindow"); render_time = value; }
- }
-
- #endregion
-
- #region public double RenderTime
+ #region UpdateTime
///
/// Gets a double representing the time spent in the UpdateFrame function, in seconds.
///
public double UpdateTime
{
- get { if (disposed) throw new ObjectDisposedException("GameWindow"); return update_time; }
+ get
+ {
+ EnsureUndisposed();
+ return update_time;
+ }
}
#endregion
#endregion
- #region --- IDisposable Members ---
+ #region VSync
///
- /// Disposes of the GameWindow, releasing all resources consumed by it.
+ /// Gets or sets the VSyncMode.
///
- public void Dispose()
+ public VSyncMode VSync
{
- try
+ get
{
- Dispose(true);
+ EnsureUndisposed();
+ GraphicsContext.Assert();
+ return vsync;
}
- finally
+ set
{
- DisposeInternal(true);
+ EnsureUndisposed();
+ GraphicsContext.Assert();
+ Context.VSync = (vsync = value) != VSyncMode.Off;
}
- GC.SuppressFinalize(this);
}
- private void DisposeInternal(bool manual)
- {
- if (!disposed)
- {
- if (manual)
- {
- if (glContext != null)
- {
- glContext.Dispose();
- glContext = null;
- }
+ #endregion
- if (glWindow != null)
- {
- glWindow.Dispose();
- glWindow = null;
- }
- }
- disposed = true;
- }
- }
+ #endregion
+
+ #region Events
+
+ ///
+ /// Occurs before the window is displayed for the first time.
+ ///
+ public event EventHandler Load;
+
+ ///
+ /// Occurs when it is time to render a frame.
+ ///
+ public event EventHandler RenderFrame;
+
+ ///
+ /// Occurs before the window is destroyed.
+ ///
+ public event EventHandler Unload;
+
+ ///
+ /// Occurs when it is time to update a frame.
+ ///
+ public event EventHandler UpdateFrame;
+
+ #endregion
+
+ #endregion
+
+ #region --- Protected Members ---
+
+ #region Dispose
///
/// Override to add custom cleanup logic.
///
/// True, if this method was called by the application; false if this was called by the finalizer thread.
- protected virtual void Dispose(bool manual)
+ protected virtual void Dispose(bool manual) { }
+
+ #endregion
+
+ #region OnRenderFrame
+
+ ///
+ /// Override in derived classes to render a frame.
+ ///
+ /// Contains information necessary for frame rendering.
+ ///
+ /// The base implementation (base.OnRenderFrame) is empty, there is no need to call it.
+ ///
+ protected virtual void OnRenderFrame(FrameEventArgs e) { }
+
+ #endregion
+
+ #region OnUpdateFrame
+
+ ///
+ /// Override in derived classes to update a frame.
+ ///
+ /// Contains information necessary for frame updating.
+ ///
+ /// The base implementation (base.OnUpdateFrame) is empty, there is no need to call it.
+ ///
+ protected virtual void OnUpdateFrame(FrameEventArgs e) { }
+
+ #endregion
+
+ #region OnWindowInfoChanged
+
+ ///
+ /// Called when the WindowInfo for this GameWindow has changed.
+ ///
+ /// Not used.
+ protected virtual void OnWindowInfoChanged(EventArgs e) { }
+
+ #endregion
+
+ #endregion
+
+ #region --- Assembly Members ---
+
+ #region Methods
+
+ #region ExitAsync
+
+ // Gracefully exits the GameWindow. May be called from any thread.
+ void ExitAsync()
{
+ HasMainLoop = false;
+ isExiting = true;
+ //UpdateFrame += delegate
+ //{
+ // ExitInternal();
+ //};
}
+ #endregion
+
+ #region ExitInternal
+
+ // Stops the main loop, if one exists.
+ void ExitInternal()
+ {
+ if (HasMainLoop)
+ {
+ throw new GameWindowExitException();
+ }
+ }
+
+ #endregion
+
+ #endregion
+
+ #region Properties
+
+ #region HasMainLoop
+
+ bool HasMainLoop
+ {
+ get { return hasMainLoop; }
+ set { hasMainLoop = value; }
+ }
+
+ #endregion
+
+ #endregion
+
+ #endregion
+
+ #region --- Private Members ---
+
+ #region OnLoadInternal
+
+ ///
+ /// Raises the Load event, and calls the user's OnLoad override.
+ ///
+ /// The event data.
+ private void OnLoadInternal(EventArgs e)
+ {
+ OnResize(EventArgs.Empty);
+
+ if (Load != null) Load(this, e);
+
+ OnLoad(e);
+ }
+
+ #endregion
+
+ #region OnRenderFrameInternal
+
+ private void OnRenderFrameInternal(FrameEventArgs e)
+ {
+ EnsureUndisposed();
+
+ if (!this.Exists || this.IsExiting) return; // TODO: Redundant because of EnsureUndisposed.
+
+ if (RenderFrame != null) RenderFrame(this, e);
+
+ OnRenderFrame(e);
+ }
+
+ #endregion
+
+ #region OnUnloadInternal
+
+ ///
+ /// Raises the Unload event, and calls the user's OnUnload override.
+ ///
+ /// The event data.
+ private void OnUnloadInternal(EventArgs e)
+ {
+ if (Unload != null) Unload(this, e);
+
+ OnUnload(e);
+ }
+
+ #endregion
+
+ #region OnUpdateFrameInternal
+
+ private void OnUpdateFrameInternal(FrameEventArgs e)
+ {
+ EnsureUndisposed();
+
+ if (!this.Exists || this.IsExiting) return; // TODO: Redundant because of EnsureUndisposed.
+
+ if (UpdateFrame != null) UpdateFrame(this, e);
+
+ OnUpdateFrame(e);
+ }
+
+ #endregion
+
+ #region OnWindowInfoChangedInternal
+
+ private void OnWindowInfoChangedInternal(EventArgs e)
+ {
+ glContext.MakeCurrent(WindowInfo);
+
+ OnWindowInfoChanged(e);
+ }
+
+ #endregion
+
+ #endregion
+
///// Finalizes unmanaged resources consumed by the GameWindow.
//~GameWindow()
//{
@@ -1797,7 +1091,6 @@ namespace OpenTK
// DisposeInternal(false);
//}
- #endregion
}
#region public enum VSyncMode
diff --git a/Source/OpenTK/NativeWindow.cs b/Source/OpenTK/NativeWindow.cs
new file mode 100644
index 00000000..73b57a62
--- /dev/null
+++ b/Source/OpenTK/NativeWindow.cs
@@ -0,0 +1,900 @@
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using OpenTK.Graphics;
+using OpenTK.Input;
+using OpenTK.Platform;
+
+namespace OpenTK
+{
+
+ ///
+ /// Instances of this class implement the interface on the current platform.
+ ///
+ public class NativeWindow0 : INativeWindow
+ {
+ #region --- Fields ---
+
+ private bool disposed;
+
+ private readonly INativeWindow implementation;
+
+ #endregion
+
+ #region --- Contructors ---
+
+ #region NativeWindow()
+
+ /// Constructs a new NativeWindow with default attributes without enabling events.
+ public NativeWindow0()
+ : this(640, 480, "OpenTK Native Window", GameWindowFlags.Default, GraphicsMode.Default, DisplayDevice.Default, false) { }
+
+ #endregion
+
+ #region
+
+ /// Constructs a new NativeWindow with default attributes.
+ /// Indicates to enable event processing as part of the NativeWindow construction.
+ public NativeWindow0(bool enableEvents)
+ : this(640, 480, "OpenTK Native Window", GameWindowFlags.Default, GraphicsMode.Default, DisplayDevice.Default, enableEvents) { }
+
+ #endregion
+
+ // TODO: Remaining constructors.
+
+ #region NativeWindow(int width, int height, string title, GameWindowFlags options, GraphicsMode mode, DisplayDevice device)
+
+ /// Constructs a new centered NativeWindow with the specified attributes without enabling events.
+ /// The width of the NativeWindow in pixels.
+ /// The height of the NativeWindow in pixels.
+ /// The title of the NativeWindow.
+ /// GameWindow options specifying window appearance and behavior.
+ /// The OpenTK.Graphics.GraphicsMode of the NativeWindow.
+ /// The OpenTK.Graphics.DisplayDevice to construct the NativeWindow in.
+ /// If width or height is less than 1.
+ /// If mode or device is null.
+ public NativeWindow0(int width, int height, string title, GameWindowFlags options, GraphicsMode mode, DisplayDevice device)
+ : this(width, height, title, options, mode, device, false) { }
+
+ #endregion
+
+ #region NativeWindow(int width, int height, string title, GameWindowFlags options, GraphicsMode mode, DisplayDevice device, bool enableEvents)
+
+ /// Constructs a new centered NativeWindow with the specified attributes.
+ /// The width of the NativeWindow in pixels.
+ /// The height of the NativeWindow in pixels.
+ /// The title of the NativeWindow.
+ /// GameWindow options specifying window appearance and behavior.
+ /// The OpenTK.Graphics.GraphicsMode of the NativeWindow.
+ /// The OpenTK.Graphics.DisplayDevice to construct the NativeWindow in.
+ /// Indicates to enable event processing as part of the NativeWindow construction.
+ /// If width or height is less than 1.
+ /// If mode or device is null.
+ public NativeWindow0(int width, int height, string title, GameWindowFlags options, GraphicsMode mode, DisplayDevice device, bool enableEvents)
+ : this(device.Bounds.Left + (device.Bounds.Width - width) / 2,
+ device.Bounds.Top + (device.Bounds.Height - height) / 2,
+ width, height, title, options, mode, device, enableEvents) { }
+
+ #endregion
+
+ #region NativeWindow0(int x, int y, int width, int height, string title, GameWindowFlags options, GraphicsMode mode, DisplayDevice device)
+
+ /// Constructs a new NativeWindow with the specified attributes without enabling events.
+ /// Horizontal screen space coordinate of the NativeWindow's origin.
+ /// Vertical screen space coordinate of the NativeWindow's origin.
+ /// The width of the NativeWindow in pixels.
+ /// The height of the NativeWindow in pixels.
+ /// The title of the NativeWindow.
+ /// GameWindow options specifying window appearance and behavior.
+ /// The OpenTK.Graphics.GraphicsMode of the NativeWindow.
+ /// The OpenTK.Graphics.DisplayDevice to construct the NativeWindow in.
+ /// If width or height is less than 1.
+ /// If mode or device is null.
+ public NativeWindow0(int x, int y, int width, int height, string title, GameWindowFlags options, GraphicsMode mode, DisplayDevice device)
+ : this(x, y, width, height, title, options, mode, device, false) { }
+
+ #endregion
+
+ #region NativeWindow0(int x, int y, int width, int height, string title, GameWindowFlags options, GraphicsMode mode, DisplayDevice device, bool enableEvents)
+
+ /// Constructs a new NativeWindow with the specified attributes.
+ /// Horizontal screen space coordinate of the NativeWindow's origin.
+ /// Vertical screen space coordinate of the NativeWindow's origin.
+ /// The width of the NativeWindow in pixels.
+ /// The height of the NativeWindow in pixels.
+ /// The title of the NativeWindow.
+ /// GameWindow options specifying window appearance and behavior.
+ /// The OpenTK.Graphics.GraphicsMode of the NativeWindow.
+ /// The OpenTK.Graphics.DisplayDevice to construct the NativeWindow in.
+ /// Indicates to enable event processing as part of the NativeWindow construction.
+ /// If width or height is less than 1.
+ /// If mode or device is null.
+ public NativeWindow0(int x, int y, int width, int height, string title, GameWindowFlags options, GraphicsMode mode, DisplayDevice device, bool enableEvents)
+ {
+ // TODO: Should a constraint be added for the position?
+ if (width < 1)
+ throw new ArgumentOutOfRangeException("width", "Must be greater than zero.");
+ if (height < 1)
+ throw new ArgumentOutOfRangeException("height", "Must be greater than zero.");
+ if (mode == null)
+ throw new ArgumentNullException("mode");
+ if (device == null)
+ throw new ArgumentNullException("device");
+
+ implementation = Factory.Default.CreateNativeWindow(x, y, width, height, title, mode, options, device);
+
+ if ((options & GameWindowFlags.Fullscreen) != 0)
+ {
+ device.ChangeResolution(width, height, mode.ColorFormat.BitsPerPixel, 0);
+ WindowState = WindowState.Fullscreen;
+ }
+
+ if (enableEvents) EnableEvents();
+ }
+
+ #endregion
+
+ #endregion
+
+ #region --- INativeWindow Members ---
+
+ #region Methods
+
+ #region Close
+
+ ///
+ /// Closes the NativeWindow. Equivalent to calling .
+ ///
+ public void Close()
+ {
+ Dispose();
+ }
+
+ #endregion
+
+ #region PointToClient
+
+ ///
+ /// Transforms the specified point from screen to client coordinates.
+ ///
+ ///
+ /// A to transform.
+ ///
+ ///
+ /// The point transformed to client coordinates.
+ ///
+ public System.Drawing.Point PointToClient(System.Drawing.Point point)
+ {
+ return implementation.PointToClient(point);
+ }
+
+ #endregion
+
+ #region PointToScreen
+
+ ///
+ /// Transforms the specified point from client to screen coordinates.
+ ///
+ ///
+ /// A to transform.
+ ///
+ ///
+ /// The point transformed to screen coordinates.
+ ///
+ public System.Drawing.Point PointToScreen(System.Drawing.Point point)
+ {
+ // Here we use the fact that PointToClient just translates the point, and PointToScreen
+ // should perform the inverse operation.
+ System.Drawing.Point trans = PointToClient(System.Drawing.Point.Empty);
+ point.X -= trans.X;
+ point.Y -= trans.Y;
+ return point;
+ }
+
+ #endregion
+
+ #region ProcessEvents
+
+ ///
+ /// Processes operating system events until the NativeWindow becomes idle.
+ ///
+ public void ProcessEvents()
+ {
+ EnsureUndisposed();
+ implementation.ProcessEvents();
+ }
+
+ #endregion
+
+ #endregion
+
+ #region Properties
+
+ #region Bounds
+
+ ///
+ /// Gets or sets a structure that contains the external bounds of this window, in screen coordinates.
+ /// External bounds include the title bar, borders and drawing area of the window.
+ ///
+ public Rectangle Bounds
+ {
+ get
+ {
+ EnsureUndisposed();
+ return implementation.Bounds;
+ }
+ set
+ {
+ EnsureUndisposed();
+ implementation.Bounds = value;
+ }
+ }
+
+ #endregion
+
+ #region ClientRectangle
+
+ ///
+ /// Gets or sets a structure that contains the internal bounds of this window, in client coordinates.
+ /// The internal bounds include the drawing area of the window, but exclude the titlebar and window borders.
+ ///
+ public Rectangle ClientRectangle
+ {
+ get
+ {
+ EnsureUndisposed();
+ return implementation.ClientRectangle;
+ }
+ set
+ {
+ EnsureUndisposed();
+ implementation.ClientRectangle = value;
+ }
+ }
+
+ #endregion
+
+ #region ClientSize
+
+ ///
+ /// Gets or sets a structure that contains the internal size this window.
+ ///
+ public Size ClientSize
+ {
+ get
+ {
+ EnsureUndisposed();
+ return implementation.ClientSize;
+ }
+ set
+ {
+ EnsureUndisposed();
+ implementation.ClientSize = value;
+ }
+ }
+
+ #endregion
+
+ #region Exists
+
+ ///
+ /// Gets a value indicating whether a render window exists.
+ ///
+ public bool Exists
+ {
+ get
+ {
+ return disposed ? false : implementation.Exists; // TODO: Should disposed be ignored instead?
+ }
+ }
+
+ #endregion
+
+ #region Focused
+
+ ///
+ /// Gets a System.Boolean that indicates whether this NativeWindow has input focus.
+ ///
+ public bool Focused
+ {
+ get
+ {
+ EnsureUndisposed();
+ return implementation.Focused;
+ }
+ }
+
+ #endregion
+
+ #region Height
+
+ ///
+ /// Gets or sets the external height of this window.
+ ///
+ public int Height
+ {
+ get
+ {
+ EnsureUndisposed();
+ return implementation.Height;
+ }
+ set
+ {
+ EnsureUndisposed();
+ implementation.Height = value;
+ }
+ }
+
+ #endregion
+
+ #region InputDriver
+
+ ///
+ /// This property is deprecated.
+ ///
+ [Obsolete]
+ public IInputDriver InputDriver
+ {
+ get
+ {
+ EnsureUndisposed();
+ return implementation.InputDriver;
+ }
+ }
+
+ #endregion
+
+ #region Location
+
+ ///
+ /// Gets or sets a structure that contains the location of this window on the desktop.
+ ///
+ public Point Location
+ {
+ get
+ {
+ EnsureUndisposed();
+ return implementation.Location;
+ }
+ set
+ {
+ EnsureUndisposed();
+ implementation.Location = value;
+ }
+ }
+
+ #endregion
+
+ #region Size
+
+ ///
+ /// Gets or sets a structure that contains the external size of this window.
+ ///
+ public Size Size
+ {
+ get
+ {
+ EnsureUndisposed();
+ return implementation.Size;
+ }
+ set
+ {
+ EnsureUndisposed();
+ implementation.Size = value;
+ }
+ }
+
+ #endregion
+
+ #region Title
+
+ ///
+ /// Gets or sets the NativeWindow title.
+ ///
+ public string Title
+ {
+ get
+ {
+ EnsureUndisposed();
+ return implementation.Title;
+ }
+ set
+ {
+ EnsureUndisposed();
+ implementation.Title = value;
+ }
+ }
+
+ #endregion
+
+ #region Visible
+
+ ///
+ /// Gets or sets a System.Boolean that indicates whether this NativeWindow is visible.
+ ///
+ public bool Visible
+ {
+ get
+ {
+ EnsureUndisposed();
+ return implementation.Visible;
+ }
+ set
+ {
+ EnsureUndisposed();
+ implementation.Visible = value;
+ }
+ }
+
+ #endregion
+
+ #region Width
+
+ ///
+ /// Gets or sets the external width of this window.
+ ///
+ public int Width
+ {
+ get
+ {
+ EnsureUndisposed();
+ return implementation.Width;
+ }
+ set
+ {
+ EnsureUndisposed();
+ implementation.Width = value;
+ }
+ }
+
+ #endregion
+
+ #region WindowBorder
+
+ ///
+ /// Gets or states the border of the NativeWindow.
+ ///
+ public WindowBorder WindowBorder
+ {
+ get
+ {
+ return implementation.WindowBorder;
+ }
+ set
+ {
+ implementation.WindowBorder = value;
+ }
+ }
+
+ #endregion
+
+ #region WindowInfo
+
+ ///
+ /// Gets the of this window.
+ ///
+ public IWindowInfo WindowInfo
+ {
+ get
+ {
+ EnsureUndisposed();
+ return implementation.WindowInfo;
+ }
+ }
+
+ #endregion
+
+ #region WindowState
+
+ ///
+ /// Gets or states the state of the NativeWindow.
+ ///
+ public WindowState WindowState
+ {
+ get
+ {
+ return implementation.WindowState;
+ }
+ set
+ {
+ implementation.WindowState = value;
+ }
+ }
+
+ #endregion
+
+ #region X
+
+ ///
+ /// Gets or sets the horizontal location of this window on the desktop.
+ ///
+ public int X
+ {
+ get
+ {
+ EnsureUndisposed();
+ return implementation.X;
+ }
+ set
+ {
+ EnsureUndisposed();
+ implementation.X = value;
+ }
+ }
+
+ #endregion
+
+ #region Y
+
+ ///
+ /// Gets or sets the vertical location of this window on the desktop.
+ ///
+ public int Y
+ {
+ get
+ {
+ EnsureUndisposed();
+ return implementation.Y;
+ }
+ set
+ {
+ EnsureUndisposed();
+ implementation.Y = value;
+ }
+ }
+
+ #endregion
+
+ #endregion
+
+ #region Events
+
+ ///
+ /// Occurs after the window has closed.
+ ///
+ public event EventHandler Closed;
+
+ ///
+ /// Occurs when the window is about to close.
+ ///
+ public event EventHandler Closing;
+
+ ///
+ /// Occurs when the window is disposed.
+ ///
+ public event EventHandler Disposed;
+
+ ///
+ /// Occurs when the property of the window changes.
+ ///
+ public event EventHandler FocusedChanged;
+
+ ///
+ /// Occurs whenever a character is typed.
+ ///
+ public event EventHandler KeyPress;
+
+ ///
+ /// Occurs whenever the window is moved.
+ ///
+ public event EventHandler Move;
+
+ ///
+ /// Occurs whenever the window is resized.
+ ///
+ public event EventHandler Resize;
+
+ ///
+ /// Occurs when the property of the window changes.
+ ///
+ public event EventHandler TitleChanged;
+
+ ///
+ /// Occurs when the property of the window changes.
+ ///
+ public event EventHandler VisibleChanged;
+
+ ///
+ /// Occurs when the property of the window changes.
+ ///
+ public event EventHandler WindowBorderChanged;
+
+ ///
+ /// Occurs when the property of the window changes.
+ ///
+ public event EventHandler WindowStateChanged;
+
+ #endregion
+
+ #endregion
+
+ #region --- IDisposable Members ---
+
+ #region Dispose
+
+ ///
+ /// Releases all non-managed resources belonging to this NativeWindow.
+ ///
+ public void Dispose()
+ {
+ implementation.Dispose();
+ disposed = true;
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+
+ #endregion
+
+ #region --- Protected Members ---
+
+ #region Methods
+
+ #region DisableEvents
+
+ ///
+ /// Disables the propagation of OS events.
+ ///
+ protected void DisableEvents()
+ {
+ EnsureUndisposed();
+ implementation.Closed -= OnClosedInternal;
+ implementation.Closing -= OnClosingInternal;
+ implementation.Disposed -= OnDisposedInternal;
+ implementation.FocusedChanged -= OnFocusedChangedInternal;
+ implementation.KeyPress -= OnKeyPressInternal;
+ implementation.Move -= OnMoveInternal;
+ implementation.Resize -= OnResizeInternal;
+ implementation.TitleChanged -= OnTitleChangedInternal;
+ implementation.VisibleChanged -= OnVisibleChangedInternal;
+ implementation.WindowBorderChanged -= OnWindowBorderChangedInternal;
+ implementation.WindowStateChanged -= OnWindowStateChangedInternal;
+ }
+
+ #endregion
+
+ #region EnableEvents
+
+ ///
+ /// Enables the propagation of OS events.
+ ///
+ protected void EnableEvents()
+ {
+ EnsureUndisposed();
+ implementation.Closed += OnClosedInternal;
+ implementation.Closing += OnClosingInternal;
+ implementation.Disposed += OnDisposedInternal;
+ implementation.FocusedChanged += OnFocusedChangedInternal;
+ implementation.KeyPress += OnKeyPressInternal;
+ implementation.Move += OnMoveInternal;
+ implementation.Resize += OnResizeInternal;
+ implementation.TitleChanged += OnTitleChangedInternal;
+ implementation.VisibleChanged += OnVisibleChangedInternal;
+ implementation.WindowBorderChanged += OnWindowBorderChangedInternal;
+ implementation.WindowStateChanged += OnWindowStateChangedInternal;
+ }
+
+ #endregion
+
+ #region EnsureUndisposed
+
+ ///
+ /// Ensures that this NativeWindow has not been disposed.
+ ///
+ ///
+ /// If this NativeWindow has been disposed.
+ ///
+ protected void EnsureUndisposed()
+ {
+ if (disposed) throw new ObjectDisposedException(GetType().Name);
+ }
+
+ #endregion
+
+ #region IsDisposed
+
+ protected bool IsDisposed() //TODO: Could be a property but with a different name than the variable because of the event. Alternatively the disposed variable could be renamed too.
+ {
+ return disposed;
+ }
+
+ #endregion
+
+ #region OnClosed
+
+ ///
+ /// Called when the NativeWindow has closed.
+ ///
+ /// Not used.
+ protected virtual void OnClosed(EventArgs e) { }
+
+ #endregion
+
+ #region OnClosing
+
+ ///
+ /// Called when the NativeWindow is about to close.
+ ///
+ ///
+ /// The for this event.
+ /// Set e.Cancel to true in order to stop the NativeWindow from closing.
+ protected virtual void OnClosing(CancelEventArgs e) { }
+
+ #endregion
+
+ #region OnMove
+
+ ///
+ /// Called when the NativeWindow is moved.
+ ///
+ /// Not used.
+ protected virtual void OnMove(EventArgs e) { }
+
+ #endregion
+
+ #region OnResize
+
+ ///
+ /// Called when the NativeWindow is resized.
+ ///
+ /// Not used.
+ protected virtual void OnResize(EventArgs e) { }
+
+ #endregion
+
+ #region OnWindowBorderChanged
+
+ ///
+ /// Called when the WindowBorder of this NativeWindow has changed.
+ ///
+ /// Not used.
+ protected virtual void OnWindowBorderChanged(EventArgs e) { }
+
+ #endregion
+
+ #region OnWindowStateChanged
+
+ ///
+ /// Called when the WindowState of this NativeWindow has changed.
+ ///
+ /// Not used.
+ protected virtual void OnWindowStateChanged(EventArgs e) { }
+
+ #endregion
+
+ #endregion
+
+ #endregion
+
+ #region --- Private Members ---
+
+ #region OnClosedInternal
+
+ private void OnClosedInternal(object sender, EventArgs e)
+ {
+ OnClosed(e);
+
+ if (Closed != null) Closed(this, e);
+ }
+
+ #endregion
+
+ #region OnClosingInternal
+
+ private void OnClosingInternal(object sender, CancelEventArgs e)
+ {
+ OnClosing(e);
+
+ if (Closing != null) Closing(this, e);
+
+ if (!e.Cancel) Close();
+ }
+
+ #endregion
+
+ #region OnDisposedInternal
+
+ private void OnDisposedInternal(object sender, EventArgs e)
+ {
+ // TODO: OnDisposed?
+ if (Disposed != null) Disposed(this, e);
+ }
+
+ #endregion
+
+ #region OnFocusedChangedInternal
+
+ private void OnFocusedChangedInternal(object sender, EventArgs e)
+ {
+ // TODO: OnFocusedChanged?
+ if (FocusedChanged != null) FocusedChanged(this, e);
+ }
+
+ #endregion
+
+ #region OnKeyPressInternal
+
+ private void OnKeyPressInternal(object sender, KeyPressEventArgs e)
+ {
+ // TODO: OnKeyPress?
+ if (KeyPress != null) KeyPress(this, e);
+ }
+
+ #endregion
+
+ #region OnMoveInternal
+
+ private void OnMoveInternal(object sender, EventArgs e)
+ {
+ EnsureUndisposed();
+
+ //if (!this.Exists || this.IsExiting) return; // TODO: See EnableEvents and DisableEvents.
+
+ OnMove(e);
+
+ if (Move != null) Move(this, e);
+ }
+
+ #endregion
+
+ #region OnResizeInternal
+
+ private void OnResizeInternal(object sender, EventArgs e)
+ {
+ EnsureUndisposed();
+
+ //if (!this.Exists || this.IsExiting) return; // TODO: See EnableEvents and DisableEvents.
+
+ OnResize(e);
+
+ if (Resize != null) Resize(this, e);
+ }
+
+ #endregion
+
+ #region OnTitleChangedInternal
+
+ private void OnTitleChangedInternal(object sender, EventArgs e)
+ {
+ // TODO: OnTitleChanged?
+ if (TitleChanged != null) TitleChanged(this, e);
+ }
+
+ #endregion
+
+ #region OnVisibleChangedInternal
+
+ private void OnVisibleChangedInternal(object sender, EventArgs e)
+ {
+ // TODO: OnVisibleChanged?
+ if (VisibleChanged != null) VisibleChanged(this, e);
+ }
+
+ #endregion
+
+ #region OnWindowBorderChangedInternal
+
+ private void OnWindowBorderChangedInternal(object sender, EventArgs e)
+ {
+ OnWindowBorderChanged(e);
+
+ if (WindowBorderChanged != null) WindowBorderChanged(this, e); // TODO: This was raised with EventArgs.Empty. Special reason?
+ }
+
+ #endregion
+
+ #region OnWindowStateChangedInternal
+
+ private void OnWindowStateChangedInternal(object sender, EventArgs e)
+ {
+ OnWindowStateChanged(e);
+
+ if (WindowStateChanged != null) WindowStateChanged(this, e);
+ }
+
+ #endregion
+
+ #endregion
+ }
+
+}