From 59b503b3c3fcf253ed3b39dd9c7f474ac25c97d5 Mon Sep 17 00:00:00 2001 From: the_fiddler Date: Sat, 4 Aug 2007 12:09:58 +0000 Subject: [PATCH] Bumped version numbers. WinRawInput now correctly subclasses WinGLNative or WinGLControl. WinRawKeyboard now correctly responds to events. Removed T10_GLSL_Cube.cs which was erroneously moved outside the Examples/Tutorial directory. Updated INativeWindow, IGameWindow and IGLControl interfaces. Updated examples to use the new GameWindow interface. Added documentation to GameWindow. Improved GameWindow error handling. More defensive programming. --- Source/Bind/Properties/AssemblyInfo.cs | 4 +- Source/Examples/ExampleLauncher.cs | 22 +- Source/Examples/Properties/AssemblyInfo.cs | 4 +- Source/Examples/T10_GLSL_Cube.cs | 228 ------ Source/Examples/Tests/S01_Call_Performance.cs | 9 + Source/Examples/Tests/S02_RawInput_Logger.cs | 80 ++- Source/Examples/Tutorial/T03_RotatingCube.cs | 24 +- .../Tutorial/T07_DisplayLists_Cube.cs | 25 +- Source/Examples/Tutorial/T08_VBO.cs | 16 +- Source/Examples/Tutorial/T10_GLSL_Cube.cs | 16 +- Source/Examples/WinForms/Cube.cs | 9 + Source/Examples/WinForms/W01_First_Window.cs | 9 + Source/OpenTK/GLControl.cs | 5 - Source/OpenTK/GameWindow.cs | 212 +++++- Source/OpenTK/Input/IInputDriver.cs | 4 +- Source/OpenTK/Input/IKeyboard.cs | 4 + Source/OpenTK/Input/IKeyboardDriver.cs | 11 + Source/OpenTK/Input/Keyboard.cs | 64 +- Source/OpenTK/InputDevices.cs | 8 +- Source/OpenTK/OpenGL/Bindings/GL.cs | 2 +- Source/OpenTK/OpenGL/Bindings/GLCore.cs | 2 +- Source/OpenTK/OpenGL/Bindings/GLDelegates.cs | 2 +- .../Platform/{IGLWindow.cs => IGLControl.cs} | 3 - Source/OpenTK/Platform/IGameWindow.cs | 10 +- Source/OpenTK/Platform/INativeWindow.cs | 11 +- Source/OpenTK/Platform/Windows/API.cs | 659 ++++++++++++------ .../OpenTK/Platform/Windows/WinGLControl.cs | 30 +- Source/OpenTK/Platform/Windows/WinGLNative.cs | 211 +++--- Source/OpenTK/Platform/Windows/WinRawInput.cs | 179 ++--- .../OpenTK/Platform/Windows/WinRawKeyboard.cs | 211 ++++-- Source/OpenTK/Platform/X11/X11GLControl.cs | 35 +- Source/OpenTK/Platform/X11/X11GLNative.cs | 70 +- Source/OpenTK/Properties/AssemblyInfo.cs | 4 +- 33 files changed, 1275 insertions(+), 908 deletions(-) delete mode 100644 Source/Examples/T10_GLSL_Cube.cs create mode 100644 Source/OpenTK/Input/IKeyboardDriver.cs rename Source/OpenTK/Platform/{IGLWindow.cs => IGLControl.cs} (84%) diff --git a/Source/Bind/Properties/AssemblyInfo.cs b/Source/Bind/Properties/AssemblyInfo.cs index d76d2917..11aad317 100644 --- a/Source/Bind/Properties/AssemblyInfo.cs +++ b/Source/Bind/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.9.7.2")] -[assembly: AssemblyFileVersion("0.9.7.2")] +[assembly: AssemblyVersion("0.9.7.3")] +[assembly: AssemblyFileVersion("0.9.7.3")] diff --git a/Source/Examples/ExampleLauncher.cs b/Source/Examples/ExampleLauncher.cs index 1bef7aba..1179e463 100644 --- a/Source/Examples/ExampleLauncher.cs +++ b/Source/Examples/ExampleLauncher.cs @@ -12,6 +12,7 @@ using System.Diagnostics; using System.Security; using System.Security.Permissions; using System.Security.Policy; +using System.IO; namespace Examples { @@ -29,13 +30,12 @@ namespace Examples Application.Run(exampleLauncher); } } - + StreamWriter sw = new StreamWriter(Path.Combine(System.Environment.CurrentDirectory, "keymap.log")); public ExampleLauncher() { InitializeComponent(); - System.Diagnostics.Debug.Listeners.Clear(); - System.Diagnostics.Debug.Listeners.Add(new TextWriterTraceListener(Console.Out)); + System.Diagnostics.Debug.Listeners.Add(new TextWriterTraceListener(sw)); System.Diagnostics.Debug.AutoFlush = true; System.Diagnostics.Trace.Listeners.Clear(); System.Diagnostics.Trace.Listeners.Add(new TextWriterTraceListener(Console.Out)); @@ -43,6 +43,12 @@ namespace Examples Trace.AutoFlush = true; } + ~ExampleLauncher() + { + sw.Flush(); + sw.Close(); + } + private void listBox1_DoubleClick(object sender, EventArgs e) { if (listBox1.SelectedItem != null) @@ -87,7 +93,15 @@ namespace Examples void Launch(object example) { Type ex = example as Type; - (ex.GetConstructor(Type.EmptyTypes).Invoke(null) as IExample).Launch(); + try + { + (ex.GetConstructor(Type.EmptyTypes).Invoke(null) as IExample).Launch(); + } + catch (Exception e) + { + Debug.WriteLine(e.ToString()); + //throw; + } //(example as Type).InvokeMember("Launch", BindingFlags.InvokeMethod, null, example, null); /* AppDomain app = AppDomain.CreateDomain((example as Type).Name); diff --git a/Source/Examples/Properties/AssemblyInfo.cs b/Source/Examples/Properties/AssemblyInfo.cs index 45b25efb..f0677815 100644 --- a/Source/Examples/Properties/AssemblyInfo.cs +++ b/Source/Examples/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.3.9.0")] -[assembly: AssemblyFileVersion("0.3.9.0")] +[assembly: AssemblyVersion("0.3.9.2")] +[assembly: AssemblyFileVersion("0.3.9.2")] diff --git a/Source/Examples/T10_GLSL_Cube.cs b/Source/Examples/T10_GLSL_Cube.cs deleted file mode 100644 index b0cd65a0..00000000 --- a/Source/Examples/T10_GLSL_Cube.cs +++ /dev/null @@ -1,228 +0,0 @@ -#region --- License --- -/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos - * See license.txt for license info - */ -#endregion - -#region --- Using Directives --- - -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Drawing; -using System.Text; -using System.Windows.Forms; -using System.Threading; - -using OpenTK.OpenGL; -using Enums = OpenTK.OpenGL.GL.Enums; -using OpenTK; -using OpenTK.Input; - -#endregion --- Using Directives --- - -namespace Examples.Tutorial -{ - public class T10_GLSL_Cube : GameWindow, IExample - { - #region --- Fields --- - - #region Shaders - - string[] vertex_shader_source = - { - "void main() {", - "gl_FrontColor = gl_Color;", - "gl_Position = ftransform();", - "}", - }; - - string[] fragment_shader_source = - { - "void main() { gl_FragColor = gl_Color; }\0" - }; - - #endregion - - static float angle; - - #endregion - - #region --- Constructors --- - - public T10_GLSL_Cube() - { - Context.MakeCurrent(); - - //Text = - // GL.GetString(Enums.StringName.VENDOR) + " " + - // GL.GetString(Enums.StringName.RENDERER) + " " + - // GL.GetString(Enums.StringName.VERSION); - - GL.ClearColor(0.1f, 0.1f, 0.5f, 0.0f); - GL.Enable(Enums.EnableCap.DEPTH_TEST); - - int vertex_shader_object, fragment_shader_object; - int status; - int shader_program; - - vertex_shader_object = GL.CreateShader(Enums.VERSION_2_0.VERTEX_SHADER); - fragment_shader_object = GL.CreateShader(Enums.VERSION_2_0.FRAGMENT_SHADER); - - GL.ShaderSource(vertex_shader_object, vertex_shader_source.Length, vertex_shader_source, (int[])null); - GL.CompileShader(vertex_shader_object); - GL.GetShader(vertex_shader_object, Enums.VERSION_2_0.COMPILE_STATUS, out status); - if (status != (int)Enums.Boolean.TRUE) - { - StringBuilder info = new StringBuilder(1024); - GL.GetShaderInfoLog(vertex_shader_object, info.MaxCapacity, (int[])null, info); - - throw new Exception(info.ToString()); - } - - GL.ShaderSource(fragment_shader_object, fragment_shader_source.Length, fragment_shader_source, (int[])null); - GL.CompileShader(fragment_shader_object); - GL.GetShader(fragment_shader_object, Enums.VERSION_2_0.COMPILE_STATUS, out status); - if (status != (int)Enums.Boolean.TRUE) - { - StringBuilder info = new StringBuilder(1024); - GL.GetShaderInfoLog(fragment_shader_object, 1024, (int[])null, info); - - throw new Exception(info.ToString()); - } - - shader_program = GL.CreateProgram(); - GL.AttachShader(shader_program, fragment_shader_object); - GL.AttachShader(shader_program, vertex_shader_object); - - GL.LinkProgram(shader_program); - GL.UseProgram(shader_program); - - OnResize(new OpenTK.Platform.ResizeEventArgs(this.Width, this.Height)); - } - - #endregion - - #region static public void Launch() - - /// - /// Launches this example. - /// - /// - /// Provides a simple way for the example launcher to launch the examples. - /// - static public void Launch() - { - using (T10_GLSL_Cube ex = new T10_GLSL_Cube()) - { - ex.Run(); - } - } - - #endregion - - #region OnResize - - protected override void OnResize(OpenTK.Platform.ResizeEventArgs e) - { - base.OnResize(e); - - GL.Viewport(0, 0, this.Width, this.Height); - - double ratio = 0.0; - ratio = this.Width / (double)this.Height; - - GL.MatrixMode(Enums.MatrixMode.PROJECTION); - GL.LoadIdentity(); - Glu.Perspective(45.0, ratio, 1.0, 64.0); - } - - #endregion - - #region UpdateFrame - - public override void UpdateFrame() - { - base.UpdateFrame(); - - if (Key[OpenTK.Input.Keys.Escape]) - { - this.Quit = true; - } - - GL.MatrixMode(Enums.MatrixMode.MODELVIEW); - GL.LoadIdentity(); - Glu.LookAt( - 0.0, 5.0, 5.0, - 0.0, 0.0, 0.0, - 0.0, 1.0, 0.0 - ); - GL.Rotatef(angle, 0.0f, 1.0f, 0.0f); - angle += 0.05f; - } - - #endregion - - #region RenderFrame - - public override void RenderFrame() - { - base.RenderFrame(); - - GL.Clear(Enums.ClearBufferMask.COLOR_BUFFER_BIT | Enums.ClearBufferMask.DEPTH_BUFFER_BIT); - - DrawCube(); - - Context.SwapBuffers(); - } - - #endregion - - #region DrawCube - - public void DrawCube() - { - GL.Begin(Enums.BeginMode.QUADS); - - GL.Color3(1, 0, 0); - GL.Vertex3(-1.0f, -1.0f, -1.0f); - GL.Vertex3(-1.0f, 1.0f, -1.0f); - GL.Vertex3(1.0f, 1.0f, -1.0f); - GL.Vertex3(1.0f, -1.0f, -1.0f); - - GL.Color3(1, 1, 0); - GL.Vertex3(-1.0f, -1.0f, -1.0f); - GL.Vertex3(1.0f, -1.0f, -1.0f); - GL.Vertex3(1.0f, -1.0f, 1.0f); - GL.Vertex3(-1.0f, -1.0f, 1.0f); - - GL.Color3(1, 0, 1); - GL.Vertex3(-1.0f, -1.0f, -1.0f); - GL.Vertex3(-1.0f, -1.0f, 1.0f); - GL.Vertex3(-1.0f, 1.0f, 1.0f); - GL.Vertex3(-1.0f, 1.0f, -1.0f); - - GL.Color3(0, 1, 0); - GL.Vertex3(-1.0f, -1.0f, 1.0f); - GL.Vertex3(1.0f, -1.0f, 1.0f); - GL.Vertex3(1.0f, 1.0f, 1.0f); - GL.Vertex3(-1.0f, 1.0f, 1.0f); - - GL.Color3(0, 0, 1); - GL.Vertex3(-1.0f, 1.0f, -1.0f); - GL.Vertex3(-1.0f, 1.0f, 1.0f); - GL.Vertex3(1.0f, 1.0f, 1.0f); - GL.Vertex3(1.0f, 1.0f, -1.0f); - - GL.Color3(0, 1, 1); - GL.Vertex3(1.0f, -1.0f, -1.0f); - GL.Vertex3(1.0f, 1.0f, -1.0f); - GL.Vertex3(1.0f, 1.0f, 1.0f); - GL.Vertex3(1.0f, -1.0f, 1.0f); - - GL.End(); - } - - #endregion - } -} diff --git a/Source/Examples/Tests/S01_Call_Performance.cs b/Source/Examples/Tests/S01_Call_Performance.cs index 19ec9d97..5a84fbcb 100644 --- a/Source/Examples/Tests/S01_Call_Performance.cs +++ b/Source/Examples/Tests/S01_Call_Performance.cs @@ -103,5 +103,14 @@ namespace Examples.Tests this.Close(); } } + + #region IExample Members + + public void Launch() + { + + } + + #endregion } } \ No newline at end of file diff --git a/Source/Examples/Tests/S02_RawInput_Logger.cs b/Source/Examples/Tests/S02_RawInput_Logger.cs index 762c5a89..900cb74d 100644 --- a/Source/Examples/Tests/S02_RawInput_Logger.cs +++ b/Source/Examples/Tests/S02_RawInput_Logger.cs @@ -18,46 +18,39 @@ namespace Examples.Tests public void Launch() { - using (StreamWriter sw = new StreamWriter(Path.Combine(System.Environment.CurrentDirectory, "keymap.log"))) + //using (S02_RawInput_Logger ex = new S02_RawInput_Logger()) { - //Debug.Listeners.Clear(); - Debug.Listeners.Add(new TextWriterTraceListener(sw)); - Debug.AutoFlush = true; - Debug.WriteLine("Starting key dump"); - - //using (S02_RawInput_Logger ex = new S02_RawInput_Logger()) + try { - try - { - //ex.Run(); - Run(); - } - catch (Exception expt) - { - System.Diagnostics.Debug.WriteLine( - String.Format( - "Exception: {3}{0}Stacktrace:{0}{1}{0}{0}{2}", - System.Environment.NewLine, - expt.TargetSite, - expt.StackTrace, - expt.Message - ) - ); - /*MessageBox.Show( - String.Format( - "Stacktrace:{0}{1}{0}{0}{2}", - System.Environment.NewLine, - expt.TargetSite, - expt.StackTrace - ), - expt.Message - );*/ - throw; - } + //ex.Run(); + Run(); + } + catch (Exception expt) + { + System.Diagnostics.Debug.WriteLine( + String.Format( + "Exception: {3}{0}Stacktrace:{0}{1}{0}{0}{2}", + System.Environment.NewLine, + expt.TargetSite, + expt.StackTrace, + expt.Message + ) + ); + /*MessageBox.Show( + String.Format( + "Stacktrace:{0}{1}{0}{0}{2}", + System.Environment.NewLine, + expt.TargetSite, + expt.StackTrace + ), + expt.Message + );*/ + throw; } - Debug.Flush(); - Debug.Close(); } + Debug.Flush(); + Debug.Close(); + } #endregion @@ -67,12 +60,23 @@ namespace Examples.Tests GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f); } - public override void RenderFrame() + public override void OnRenderFrame() { - base.RenderFrame(); + base.OnRenderFrame(); GL.Clear(GL.Enums.ClearBufferMask.COLOR_BUFFER_BIT); Context.SwapBuffers(); } + + public override void Run() + { + while (!Quit) + { + ProcessEvents(); + OnUpdateFrame(); + OnRenderFrame(); + Thread.Sleep(10); + } + } } } diff --git a/Source/Examples/Tutorial/T03_RotatingCube.cs b/Source/Examples/Tutorial/T03_RotatingCube.cs index 491bb1cb..60b5dcd6 100644 --- a/Source/Examples/Tutorial/T03_RotatingCube.cs +++ b/Source/Examples/Tutorial/T03_RotatingCube.cs @@ -34,6 +34,8 @@ namespace Examples.Tutorial public T03_RotatingCube() { + CreateWindow(new DisplayMode(800, 600)); + Context.MakeCurrent(); GL.ClearColor(0.1f, 0.1f, 0.5f, 0.0f); @@ -68,7 +70,7 @@ namespace Examples.Tutorial #endregion - #region UpdateFrame function + #region OnUpdateFrame function /// /// Prepares the next frame for rendering. @@ -77,16 +79,16 @@ namespace Examples.Tutorial /// Place your control logic here. This is the place to respond to user input, /// update object positions etc. /// - public override void UpdateFrame() + public override void OnUpdateFrame() { - if (Key[OpenTK.Input.Keys.Escape]) + if (Keyboard[0][OpenTK.Input.Keys.Escape]) { - Quit = true; + this.Exit(); return; } - if ((Key[OpenTK.Input.Keys.LeftAlt] || Key[OpenTK.Input.Keys.RightAlt]) && - Key[OpenTK.Input.Keys.Enter]) + if ((Keyboard[0][OpenTK.Input.Keys.LeftAlt] || Keyboard[0][OpenTK.Input.Keys.RightAlt]) && + Keyboard[0][OpenTK.Input.Keys.Enter]) { Fullscreen = true; } @@ -105,12 +107,12 @@ namespace Examples.Tutorial #endregion - #region RenderFrame function + #region OnRenderFrame function /// /// Place your rendering code here. /// - public override void RenderFrame() + public override void OnRenderFrame() { GL.Clear(Enums.ClearBufferMask.COLOR_BUFFER_BIT | Enums.ClearBufferMask.DEPTH_BUFFER_BIT); @@ -178,11 +180,7 @@ namespace Examples.Tutorial /// public void Launch() { - //using (T03_RotatingCube ex = new T03_RotatingCube()) - { - //ex.Run(); - Run(); - } + Run(); } #endregion diff --git a/Source/Examples/Tutorial/T07_DisplayLists_Cube.cs b/Source/Examples/Tutorial/T07_DisplayLists_Cube.cs index da3a19ee..a637497e 100644 --- a/Source/Examples/Tutorial/T07_DisplayLists_Cube.cs +++ b/Source/Examples/Tutorial/T07_DisplayLists_Cube.cs @@ -34,6 +34,7 @@ namespace Examples.Tutorial public T07_DisplayLists_Cube() { + this.CreateWindow(new OpenTK.Platform.DisplayMode(800, 600)); //Text = // "DisplayLists example (" + // GL.GetString(Enums.StringName.RENDERER) + " " + @@ -77,7 +78,7 @@ namespace Examples.Tutorial OnResize(new OpenTK.Platform.ResizeEventArgs(this.Width, this.Height)); } - #endregion + #endregion #region public void Launch() @@ -89,11 +90,7 @@ namespace Examples.Tutorial /// public void Launch() { - //using (T03_RotatingCube ex = new T03_RotatingCube()) - { - //ex.Run(); - Run(); - } + Run(); } #endregion @@ -123,11 +120,11 @@ namespace Examples.Tutorial #endregion - #region RenderFrame + #region OnRenderFrame - public override void RenderFrame() + public override void OnRenderFrame() { - base.RenderFrame(); + base.OnRenderFrame(); GL.MatrixMode(Enums.MatrixMode.MODELVIEW); GL.LoadIdentity(); @@ -151,15 +148,15 @@ namespace Examples.Tutorial #endregion - #region UpdateFrame + #region OnUpdateFrame - public override void UpdateFrame() + public override void OnUpdateFrame() { - base.UpdateFrame(); + base.OnUpdateFrame(); - if (Key[OpenTK.Input.Keys.Escape]) + if (Keyboard[0][OpenTK.Input.Keys.Escape]) { - this.Quit = true; + this.Exit(); } } diff --git a/Source/Examples/Tutorial/T08_VBO.cs b/Source/Examples/Tutorial/T08_VBO.cs index f7886f6a..eb56a43e 100644 --- a/Source/Examples/Tutorial/T08_VBO.cs +++ b/Source/Examples/Tutorial/T08_VBO.cs @@ -72,6 +72,8 @@ namespace Examples.Tutorial public T08_VBO() { + this.CreateWindow(new DisplayMode(800, 600)); + this.Context.MakeCurrent(); GL.ClearColor(0.1f, 0.1f, 0.5f, 0.0f); @@ -86,11 +88,11 @@ namespace Examples.Tutorial #endregion - #region RenderFrame + #region OnRenderFrame - public override void RenderFrame() + public override void OnRenderFrame() { - base.RenderFrame(); + base.OnRenderFrame(); GL.Clear( GL.Enums.ClearBufferMask.COLOR_BUFFER_BIT | @@ -117,7 +119,7 @@ namespace Examples.Tutorial #endregion - #region UpdateFrame + #region OnUpdateFrame /// /// Prepares the next frame for rendering. @@ -126,11 +128,11 @@ namespace Examples.Tutorial /// Place your control logic here. This is the place to respond to user input, /// update object positions etc. /// - public override void UpdateFrame() + public override void OnUpdateFrame() { - if (Key[OpenTK.Input.Keys.Escape]) + if (Keyboard[0][OpenTK.Input.Keys.Escape]) { - Quit = true; + this.Exit(); return; } diff --git a/Source/Examples/Tutorial/T10_GLSL_Cube.cs b/Source/Examples/Tutorial/T10_GLSL_Cube.cs index cc5b6f55..a104c602 100644 --- a/Source/Examples/Tutorial/T10_GLSL_Cube.cs +++ b/Source/Examples/Tutorial/T10_GLSL_Cube.cs @@ -138,15 +138,15 @@ namespace Examples.Tutorial #endregion - #region UpdateFrame + #region OnUpdateFrame - public override void UpdateFrame() + public override void OnUpdateFrame() { - base.UpdateFrame(); + base.OnUpdateFrame(); - if (Key[OpenTK.Input.Keys.Escape]) + if (Keyboard[0][OpenTK.Input.Keys.Escape]) { - this.Quit = true; + this.Exit(); } GL.MatrixMode(GL.Enums.MatrixMode.MODELVIEW); @@ -162,11 +162,11 @@ namespace Examples.Tutorial #endregion - #region RenderFrame + #region OnRenderFrame - public override void RenderFrame() + public override void OnRenderFrame() { - base.RenderFrame(); + base.OnRenderFrame(); GL.Clear(GL.Enums.ClearBufferMask.COLOR_BUFFER_BIT | GL.Enums.ClearBufferMask.DEPTH_BUFFER_BIT); diff --git a/Source/Examples/WinForms/Cube.cs b/Source/Examples/WinForms/Cube.cs index fe889e4c..6791ee09 100644 --- a/Source/Examples/WinForms/Cube.cs +++ b/Source/Examples/WinForms/Cube.cs @@ -206,5 +206,14 @@ namespace Examples.WinForms GL.End(); } #endregion + + #region IExample Members + + public void Launch() + { + + } + + #endregion } } \ No newline at end of file diff --git a/Source/Examples/WinForms/W01_First_Window.cs b/Source/Examples/WinForms/W01_First_Window.cs index 486c970a..a50cee13 100644 --- a/Source/Examples/WinForms/W01_First_Window.cs +++ b/Source/Examples/WinForms/W01_First_Window.cs @@ -71,5 +71,14 @@ namespace Examples.WinForms break; } } + + #region IExample Members + + public void Launch() + { + + } + + #endregion } } \ No newline at end of file diff --git a/Source/OpenTK/GLControl.cs b/Source/OpenTK/GLControl.cs index 81befbb6..75388948 100644 --- a/Source/OpenTK/GLControl.cs +++ b/Source/OpenTK/GLControl.cs @@ -249,11 +249,6 @@ namespace OpenTK #endregion - public void ProcessEvents() - { - throw new Exception("The method or operation is not implemented."); - } - #endregion #region --- IResizable Members --- diff --git a/Source/OpenTK/GameWindow.cs b/Source/OpenTK/GameWindow.cs index 8b65e309..5f2676d1 100644 --- a/Source/OpenTK/GameWindow.cs +++ b/Source/OpenTK/GameWindow.cs @@ -13,14 +13,23 @@ using OpenTK.Platform; namespace OpenTK { - public class GameWindow : OpenTK.Platform.IGLControl, OpenTK.Platform.IGameWindow + public class GameWindow : OpenTK.Platform.IGameWindow { private INativeWindow glWindow; private ResizeEventArgs resizeEventArgs = new ResizeEventArgs(); + private DisplayMode mode; - public Input.IKeyboard Keyboard { get { return inputDevices.Keyboards[0]; } } - - private InputDevices inputDevices = new InputDevices(); + private InputDevices inputDevices; + public IList Keyboard { get { return Input.Keyboards; } } + public InputDevices Input + { + get + { + if (inputDevices == null) + inputDevices = new InputDevices(this.Handle); + return inputDevices; + } + } #region --- Contructors --- @@ -29,13 +38,6 @@ namespace OpenTK /// public GameWindow() { - System.Diagnostics.Debug.Listeners.Clear(); - System.Diagnostics.Debug.Listeners.Add(new TextWriterTraceListener(Console.Out)); - System.Diagnostics.Debug.AutoFlush = true; - System.Diagnostics.Trace.Listeners.Clear(); - System.Diagnostics.Trace.Listeners.Add(new TextWriterTraceListener(Console.Out)); - System.Diagnostics.Trace.AutoFlush = true; - if (Environment.OSVersion.Platform == PlatformID.Win32NT || Environment.OSVersion.Platform == PlatformID.Win32Windows) { @@ -55,17 +57,15 @@ namespace OpenTK ); } - glWindow.Context.MakeCurrent(); - - // When the glWindow construction is complete, hook the resize events. - resizeEventArgs.Width = this.Width; - resizeEventArgs.Height = this.Height; glWindow.Resize += new ResizeEvent(glWindow_Resize); glWindow.Create += new CreateEvent(glWindow_Create); } void glWindow_Create(object sender, EventArgs e) { + //glWindow.Context.MakeCurrent(); + inputDevices = new InputDevices(this.Handle); + this.OnCreate(e); } @@ -76,10 +76,59 @@ namespace OpenTK #endregion - #region --- IGLControl Members --- + #region --- INativeWindow Members --- + + #region public void CreateWindow(DisplayMode mode) + + /// + /// Creates a new render window. + /// + /// The DisplayMode of the render window. + /// Occurs when a render window already exists. + public void CreateWindow(DisplayMode mode) + { + if (!Created) + { + glWindow.CreateWindow(mode); + } + else + { + throw new ApplicationException("A render window already exists"); + } + } + + #endregion + + #region public IntPtr Handle + + /// + /// Gets the handle of the current GameWindow. + /// + public IntPtr Handle + { + get { return glWindow.Handle; } + } + + #endregion + + #region public void Exit() + + /// + /// Gracefully exits the current GameWindow. + /// + public void Exit() + { + glWindow.Exit(); + } + + #endregion #region public bool IsIdle + /// + /// Gets a value indicating whether the current GameWindow is idle. + /// If true, the OnUpdateFrame and OnRenderFrame functions should be called. + /// public bool IsIdle { get { return glWindow.IsIdle; } @@ -87,6 +136,23 @@ namespace OpenTK #endregion + #region public bool Quit + + /// + /// Gets a value indicating whether the current GameWindow is quitting. + /// + /// + /// You should not call OnRenderFrame, Resize, and other GameWindow related function + /// when the quit sequence has been initiated, as indicated by the Quitting property. + /// NullReference- or ApplicationExceptions may occur otherwise. + /// + public bool Quit + { + get { return glWindow.Quit; } + } + + #endregion + #region public bool Fullscreen public bool Fullscreen @@ -97,21 +163,35 @@ namespace OpenTK #endregion - #region public OpenTK.Platform.IGLContext Context + #region public IGLContext Context - public OpenTK.Platform.IGLContext Context + /// + /// Returns the opengl IGLontext associated with the current GameWindow. + /// Forces window creation. + /// + public IGLContext Context { - get { return glWindow.Context; } + get + { + if (!glWindow.Created) + { + mode = new DisplayMode(640, 480); + this.CreateWindow(mode); + } + return glWindow.Context; + } } #endregion - #region public bool Quit + #region public bool Created - public bool Quit + /// + /// Gets a value indicating whether a render window has been created. + /// + public bool Created { - get { return glWindow.Quit; } - set { glWindow.Quit = value; } + get { return glWindow.Created; } } #endregion @@ -120,8 +200,10 @@ namespace OpenTK #region --- IGameWindow Members --- + #region public virtual void Run() + /// - /// Runs a default game loop on the GameWindow. + /// Runs the default game loop on GameWindow (process event->update frame->render frame). /// /// /// @@ -131,7 +213,7 @@ namespace OpenTK /// /// Override this function if you want to change the behaviour of the /// default game loop. If you override this function, you must place - /// a call to the ProcessEvents function, so that your window will respond + /// a call to the ProcessEvents function, to ensure window will respond /// to Operating System events. /// /// @@ -140,16 +222,33 @@ namespace OpenTK while (!this.Quit) { this.ProcessEvents(); - this.UpdateFrame(); - this.RenderFrame(); + this.OnUpdateFrame(); + this.OnRenderFrame(); } } + #endregion + + #region public void ProcessEvents() + + /// + /// Processes operating system events until the GameWindow becomes idle. + /// + /// + /// 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() { glWindow.ProcessEvents(); } + #endregion + #region public event CreateEvent Create; public event CreateEvent Create; @@ -164,20 +263,61 @@ namespace OpenTK #endregion - public virtual void RenderFrame() + #region public virtual void OnRenderFrame() + + /// + /// Raises the RenderFrame event. Override in derived classes to render a frame. + /// + /// + /// If overriden, the base.OnRenderFrame() function should be called, to ensure + /// listeners are notified of RenderFrame events. + /// + public virtual void OnRenderFrame() { - if (RenderFrameNotify != null) - RenderFrameNotify(EventArgs.Empty); + if (!this.Created) + { + Debug.Print("WARNING: RenderFrame event raised, without a valid render window. This may indicate a programming error. Creating render window."); + mode = new DisplayMode(640, 480); + this.CreateWindow(mode); + } + if (RenderFrame != null) + RenderFrame(EventArgs.Empty); } - public virtual void UpdateFrame() + #endregion + + #region public virtual void OnUpdateFrame() + + /// + /// Raises the UpdateFrame event. Override in derived classes to update a frame. + /// + /// + /// If overriden, the base.OnUpdateFrame() function should be called, to ensure + /// listeners are notified of UpdateFrame events. + /// + public virtual void OnUpdateFrame() { - if (UpdateFrameNotify != null) - UpdateFrameNotify(EventArgs.Empty); + if (!this.Created) + { + Debug.Print("WARNING: UpdateFrame event raised, without a valid render window. This may indicate a programming error. Creating render window."); + mode = new DisplayMode(640, 480); + this.CreateWindow(mode); + } + if (UpdateFrame != null) + UpdateFrame(EventArgs.Empty); } - public event UpdateFrameEvent UpdateFrameNotify; - public event RenderFrameEvent RenderFrameNotify; + #endregion + + /// + /// Occurs when it is time to update the next frame. + /// + public event UpdateFrameEvent UpdateFrame; + + /// + /// Occurs when it is time to render the next frame. + /// + public event RenderFrameEvent RenderFrame; #endregion diff --git a/Source/OpenTK/Input/IInputDriver.cs b/Source/OpenTK/Input/IInputDriver.cs index 40de652e..e5ce824c 100644 --- a/Source/OpenTK/Input/IInputDriver.cs +++ b/Source/OpenTK/Input/IInputDriver.cs @@ -4,10 +4,10 @@ using System.Text; namespace OpenTK.Input { - public interface IInputDriver + public interface IInputDriver : IKeyboardDriver { IList InputDevices { get; } - IList Keyboards { get; } + //void ProcessEvents //IEnumerable Mice { get; } //IEnumerable Hids { get; } } diff --git a/Source/OpenTK/Input/IKeyboard.cs b/Source/OpenTK/Input/IKeyboard.cs index 143cce2d..aa98f87c 100644 --- a/Source/OpenTK/Input/IKeyboard.cs +++ b/Source/OpenTK/Input/IKeyboard.cs @@ -9,5 +9,9 @@ namespace OpenTK.Input public interface IKeyboard : IInputDevice { bool this[Keys k] { get; } + int NumberOfKeys { get; } + int NumberOfFunctionKeys { get; } + int NumberOfLeds { get; } + long DeviceID { get; } } } \ No newline at end of file diff --git a/Source/OpenTK/Input/IKeyboardDriver.cs b/Source/OpenTK/Input/IKeyboardDriver.cs new file mode 100644 index 00000000..ac1b9caf --- /dev/null +++ b/Source/OpenTK/Input/IKeyboardDriver.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenTK.Input +{ + public interface IKeyboardDriver + { + IList Keyboards { get; } + } +} diff --git a/Source/OpenTK/Input/Keyboard.cs b/Source/OpenTK/Input/Keyboard.cs index 3902f988..fbe434e7 100644 --- a/Source/OpenTK/Input/Keyboard.cs +++ b/Source/OpenTK/Input/Keyboard.cs @@ -8,13 +8,20 @@ using System; +using OpenTK.Input; +using System.Diagnostics; + #endregion namespace OpenTK.Input { public class Keyboard : IKeyboard { - private IKeyboard keyboard; + //private IKeyboard keyboard; + private bool[] keys = new bool[(int)Keys.MaxKeys]; + private string description; + private int numKeys, numFKeys, numLeds; + private long devID; #region --- Constructors --- @@ -23,7 +30,7 @@ namespace OpenTK.Input if (Environment.OSVersion.Platform == PlatformID.Win32NT || Environment.OSVersion.Platform == PlatformID.Win32Windows) { - keyboard = new OpenTK.Platform.Windows.WinRawKeyboard(); + //keyboard = new OpenTK.Platform.Windows.WinRawKeyboard(); } else if (Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == (PlatformID)128) // some older versions of Mono reported 128. @@ -44,8 +51,39 @@ namespace OpenTK.Input public bool this[Keys k] { - get { return keyboard[k]; } - //set { keyboard[k] = value; } + get { return keys[(int)k]; } + internal set + { + Debug.Print("OpenTK key {0} {1}.", k, value ? "pressed" : "released"); + keys[(int)k] = value; + } + } + + public int NumberOfKeys + { + get { return numKeys; } + internal set { numKeys = value; } + } + + public int NumberOfFunctionKeys + { + get { return numFKeys; } + internal set { numFKeys = value; } + } + + public int NumberOfLeds + { + get { return numLeds; } + internal set { numLeds = value; } + } + + /// + /// Device dependent ID. + /// + public long DeviceID + { + get { return devID; } + internal set { devID = value; } } #endregion @@ -54,15 +92,29 @@ namespace OpenTK.Input public string Description { - get { return keyboard.Description; } + get { return description; } + internal set { description = value; } } public InputDeviceType DeviceType { - get { return keyboard.DeviceType; } + get { return InputDeviceType.Keyboard; } } #endregion + + public override int GetHashCode() + { + //return base.GetHashCode(); + return (int)(numKeys ^ numFKeys ^ numLeds ^ devID.GetHashCode() ^ description.GetHashCode()); + } + + public override string ToString() + { + //return base.ToString(); + return String.Format("Keyboard: '{0}', {1} keys, {2} function keys, {3} leds. Device ID: {4}", + description, NumberOfKeys, NumberOfFunctionKeys, NumberOfLeds, DeviceID); + } } #region public enum Keys : int diff --git a/Source/OpenTK/InputDevices.cs b/Source/OpenTK/InputDevices.cs index 68409117..ff3efbc5 100644 --- a/Source/OpenTK/InputDevices.cs +++ b/Source/OpenTK/InputDevices.cs @@ -10,12 +10,12 @@ namespace OpenTK { IInputDriver inputDriver; - public InputDevices() + public InputDevices(IntPtr parentHandle) { if (Environment.OSVersion.Version.Major > 5 || (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1)) { - inputDriver = new OpenTK.Platform.Windows.WinRawInput(); + inputDriver = new OpenTK.Platform.Windows.WinRawInput(parentHandle); } else { @@ -25,12 +25,12 @@ namespace OpenTK #region --- IInputDriver Members --- - IList OpenTK.Input.IInputDriver.InputDevices + IList IInputDriver.InputDevices { get { return inputDriver.InputDevices; } } - public IList Keyboards + public IList Keyboards { get { return inputDriver.Keyboards; } } diff --git a/Source/OpenTK/OpenGL/Bindings/GL.cs b/Source/OpenTK/OpenGL/Bindings/GL.cs index 89fea19d..e88436d5 100644 --- a/Source/OpenTK/OpenGL/Bindings/GL.cs +++ b/Source/OpenTK/OpenGL/Bindings/GL.cs @@ -12435,7 +12435,7 @@ namespace OpenTK.OpenGL } public static - void GetShaderInfoLog(Int32 shader, Int32 bufSize, [Out] out Int32 length, [In, Out] System.Text.StringBuilder infoLog) + void GetShaderInfoLog(Int32 shader, Int32 bufSize, [Out] out Int32 length, [Out] System.Text.StringBuilder infoLog) { length = default(Int32); infoLog = default(System.Text.StringBuilder); diff --git a/Source/OpenTK/OpenGL/Bindings/GLCore.cs b/Source/OpenTK/OpenGL/Bindings/GLCore.cs index ef14ab99..37c297e7 100644 --- a/Source/OpenTK/OpenGL/Bindings/GLCore.cs +++ b/Source/OpenTK/OpenGL/Bindings/GLCore.cs @@ -1527,7 +1527,7 @@ namespace OpenTK.OpenGL internal extern static unsafe void GetShaderiv(UInt32 shader, GL.Enums.VERSION_2_0 pname, [Out] Int32* @params); [System.Security.SuppressUnmanagedCodeSecurity()] [System.Runtime.InteropServices.DllImport(GL.Library, EntryPoint = "glGetShaderInfoLog", ExactSpelling = true)] - internal extern static unsafe void GetShaderInfoLog(UInt32 shader, Int32 bufSize, [Out] Int32* length, [In, Out] System.Text.StringBuilder infoLog); + internal extern static unsafe void GetShaderInfoLog(UInt32 shader, Int32 bufSize, [Out] Int32* length, [Out] System.Text.StringBuilder infoLog); [System.Security.SuppressUnmanagedCodeSecurity()] [System.Runtime.InteropServices.DllImport(GL.Library, EntryPoint = "glGetShaderSource", ExactSpelling = true)] internal extern static unsafe void GetShaderSource(UInt32 shader, Int32 bufSize, [Out] Int32* length, [Out] System.Text.StringBuilder[] source); diff --git a/Source/OpenTK/OpenGL/Bindings/GLDelegates.cs b/Source/OpenTK/OpenGL/Bindings/GLDelegates.cs index c94d49c4..d943d884 100644 --- a/Source/OpenTK/OpenGL/Bindings/GLDelegates.cs +++ b/Source/OpenTK/OpenGL/Bindings/GLDelegates.cs @@ -1528,7 +1528,7 @@ namespace OpenTK.OpenGL internal unsafe delegate void GetShaderiv(UInt32 shader, GL.Enums.VERSION_2_0 pname, [Out] Int32* @params); internal unsafe static GetShaderiv glGetShaderiv = (GetShaderiv)GL.GetDelegateForExtensionMethod("glGetShaderiv", typeof(GetShaderiv)) ?? new GetShaderiv(Imports.GetShaderiv); [System.Security.SuppressUnmanagedCodeSecurity()] - internal unsafe delegate void GetShaderInfoLog(UInt32 shader, Int32 bufSize, [Out] Int32* length, [In, Out] System.Text.StringBuilder infoLog); + internal unsafe delegate void GetShaderInfoLog(UInt32 shader, Int32 bufSize, [Out] Int32* length, [Out] System.Text.StringBuilder infoLog); internal unsafe static GetShaderInfoLog glGetShaderInfoLog = (GetShaderInfoLog)GL.GetDelegateForExtensionMethod("glGetShaderInfoLog", typeof(GetShaderInfoLog)) ?? new GetShaderInfoLog(Imports.GetShaderInfoLog); [System.Security.SuppressUnmanagedCodeSecurity()] internal unsafe delegate void GetShaderSource(UInt32 shader, Int32 bufSize, [Out] Int32* length, [Out] System.Text.StringBuilder[] source); diff --git a/Source/OpenTK/Platform/IGLWindow.cs b/Source/OpenTK/Platform/IGLControl.cs similarity index 84% rename from Source/OpenTK/Platform/IGLWindow.cs rename to Source/OpenTK/Platform/IGLControl.cs index 8923c71f..b62eb117 100644 --- a/Source/OpenTK/Platform/IGLWindow.cs +++ b/Source/OpenTK/Platform/IGLControl.cs @@ -14,12 +14,9 @@ namespace OpenTK.Platform { public interface IGLControl : IDisposable { - void ProcessEvents(); - event CreateEvent Create; bool IsIdle { get; } - //bool Quit { get; set; } bool Fullscreen { get; set; } IGLContext Context { get; } } diff --git a/Source/OpenTK/Platform/IGameWindow.cs b/Source/OpenTK/Platform/IGameWindow.cs index e347d70d..106be817 100644 --- a/Source/OpenTK/Platform/IGameWindow.cs +++ b/Source/OpenTK/Platform/IGameWindow.cs @@ -5,15 +5,15 @@ using System.Text; namespace OpenTK.Platform { - interface IGameWindow : IDisposable + interface IGameWindow : INativeWindow { void Run(); - void RenderFrame(); - void UpdateFrame(); + void OnRenderFrame(); + void OnUpdateFrame(); - event UpdateFrameEvent UpdateFrameNotify; - event RenderFrameEvent RenderFrameNotify; + event UpdateFrameEvent UpdateFrame; + event RenderFrameEvent RenderFrame; } public delegate void UpdateFrameEvent(EventArgs e); diff --git a/Source/OpenTK/Platform/INativeWindow.cs b/Source/OpenTK/Platform/INativeWindow.cs index 1640901e..491f9ea8 100644 --- a/Source/OpenTK/Platform/INativeWindow.cs +++ b/Source/OpenTK/Platform/INativeWindow.cs @@ -4,15 +4,16 @@ using System.Text; namespace OpenTK.Platform { - interface INativeWindow : IResizable, IDisposable + interface INativeWindow : IGLControl, IResizable { + void CreateWindow(DisplayMode mode); void ProcessEvents(); + void Exit(); event CreateEvent Create; - bool IsIdle { get; } - bool Quit { get; set; } - bool Fullscreen { get; set; } - IGLContext Context { get; } + bool Created { get; } + bool Quit { get; } + IntPtr Handle { get; } } } diff --git a/Source/OpenTK/Platform/Windows/API.cs b/Source/OpenTK/Platform/Windows/API.cs index d4351708..380f3754 100644 --- a/Source/OpenTK/Platform/Windows/API.cs +++ b/Source/OpenTK/Platform/Windows/API.cs @@ -10,6 +10,7 @@ using System; using System.Runtime.InteropServices; using System.Text; +using System.Security; #endregion @@ -41,15 +42,17 @@ namespace OpenTK.Platform.Windows using BOOL = System.Boolean; using INT = System.Int32; using UINT = System.UInt32; - + using LONG_PTR = System.IntPtr; + + using WNDPROC = System.IntPtr; #endregion /// - /// For internal use by OpenTK only! + /// For public use by OpenTK only! /// Exposes useful native WINAPI methods and structures. /// - internal static class API + public static class API { // Prevent BeforeFieldInit optimization, and initialize 'size' fields. static API() @@ -58,108 +61,109 @@ namespace OpenTK.Platform.Windows RawInputSize = (uint)Marshal.SizeOf(typeof(RawInput)); RawInputDeviceSize = (uint)Marshal.SizeOf(typeof(RawInputDevice)); RawInputDeviceListSize = (uint)Marshal.SizeOf(typeof(RawInputDeviceList)); + RawInputDeviceInfoSize = (uint)Marshal.SizeOf(typeof(RawInputDeviceInfo)); } #region Constants - internal struct Constants + public struct Constants { // Mouse indicator flags (found in winuser.h) - internal const int MOUSE_MOVE_RELATIVE = 0; - internal const int MOUSE_MOVE_ABSOLUTE = 1; - internal const int MOUSE_VIRTUAL_DESKTOP = 0x02; // the coordinates are mapped to the virtual desktop - internal const int MOUSE_ATTRIBUTES_CHANGED = 0x04; // requery for mouse attributes + public const int MOUSE_MOVE_RELATIVE = 0; + public const int MOUSE_MOVE_ABSOLUTE = 1; + public const int MOUSE_VIRTUAL_DESKTOP = 0x02; // the coordinates are mapped to the virtual desktop + public const int MOUSE_ATTRIBUTES_CHANGED = 0x04; // requery for mouse attributes // Found in winuser.h - internal const int KEYBOARD_OVERRUN_MAKE_CODE = 0xFF; + public const int KEYBOARD_OVERRUN_MAKE_CODE = 0xFF; // WM_ACTIVATE state values (found in winuser.h) - internal const int WA_INACTIVE = 0; - internal const int WA_ACTIVE = 1; - internal const int WA_CLICKACTIVE = 2; + public const int WA_INACTIVE = 0; + public const int WA_ACTIVE = 1; + public const int WA_CLICKACTIVE = 2; // Window Messages (found in winuser.h) - internal const int WM_NULL = 0x0000; - internal const int WM_CREATE = 0x0001; - internal const int WM_DESTROY = 0x0002; - internal const int WM_MOVE = 0x0003; - internal const int WM_SIZE = 0x0005; - internal const int WM_ACTIVATE = 0x0006; - internal const int WM_SETFOCUS = 0x0007; - internal const int WM_KILLFOCUS = 0x0008; - internal const int WM_ENABLE = 0x000A; - internal const int WM_SETREDRAW = 0x000B; - internal const int WM_SETTEXT = 0x000C; - internal const int WM_GETTEXT = 0x000D; - internal const int WM_GETTEXTLENGTH = 0x000E; - internal const int WM_PAINT = 0x000F; - internal const int WM_CLOSE = 0x0010; + public const int WM_NULL = 0x0000; + public const int WM_CREATE = 0x0001; + public const int WM_DESTROY = 0x0002; + public const int WM_MOVE = 0x0003; + public const int WM_SIZE = 0x0005; + public const int WM_ACTIVATE = 0x0006; + public const int WM_SETFOCUS = 0x0007; + public const int WM_KILLFOCUS = 0x0008; + public const int WM_ENABLE = 0x000A; + public const int WM_SETREDRAW = 0x000B; + public const int WM_SETTEXT = 0x000C; + public const int WM_GETTEXT = 0x000D; + public const int WM_GETTEXTLENGTH = 0x000E; + public const int WM_PAINT = 0x000F; + public const int WM_CLOSE = 0x0010; // _WIN32_WCE - internal const int WM_QUERYENDSESSION = 0x0011; - internal const int WM_QUERYOPEN = 0x0013; - internal const int WM_ENDSESSION = 0x0016; - internal const int WM_QUIT = 0x0012; - internal const int WM_ERASEBKGND = 0x0014; - internal const int WM_SYSCOLORCHANGE = 0x0015; - internal const int WM_SHOWWINDOW = 0x0018; - internal const int WM_WININICHANGE = 0x001A; + public const int WM_QUERYENDSESSION = 0x0011; + public const int WM_QUERYOPEN = 0x0013; + public const int WM_ENDSESSION = 0x0016; + public const int WM_QUIT = 0x0012; + public const int WM_ERASEBKGND = 0x0014; + public const int WM_SYSCOLORCHANGE = 0x0015; + public const int WM_SHOWWINDOW = 0x0018; + public const int WM_WININICHANGE = 0x001A; // WINVER >= 0x400 - internal const int WM_SETTINGCHANGE = WM_WININICHANGE; + public const int WM_SETTINGCHANGE = WM_WININICHANGE; - internal const int WM_DEVMODECHANGE = 0x001B; - internal const int WM_ACTIVATEAPP = 0x001C; - internal const int WM_FONTCHANGE = 0x001D; - internal const int WM_TIMECHANGE = 0x001E; - internal const int WM_CANCELMODE = 0x001F; - internal const int WM_SETCURSOR = 0x0020; - internal const int WM_MOUSEACTIVATE = 0x0021; - internal const int WM_CHILDACTIVATE = 0x0022; - internal const int WM_QUEUESYNC = 0x0023; + public const int WM_DEVMODECHANGE = 0x001B; + public const int WM_ACTIVATEAPP = 0x001C; + public const int WM_FONTCHANGE = 0x001D; + public const int WM_TIMECHANGE = 0x001E; + public const int WM_CANCELMODE = 0x001F; + public const int WM_SETCURSOR = 0x0020; + public const int WM_MOUSEACTIVATE = 0x0021; + public const int WM_CHILDACTIVATE = 0x0022; + public const int WM_QUEUESYNC = 0x0023; - internal const int WM_GETMINMAXINFO = 0x0024; + public const int WM_GETMINMAXINFO = 0x0024; - internal const int WM_WINDOWPOSCHANGING = 0x0046; - internal const int WM_WINDOWPOSCHANGED = 0x0047; + public const int WM_WINDOWPOSCHANGING = 0x0046; + public const int WM_WINDOWPOSCHANGED = 0x0047; // Keyboard events (found in winuser.h) - internal const int WM_INPUT = 0x00FF; // Raw input. XP and higher only. - internal const int WM_KEYDOWN = 0x0100; - internal const int WM_KEYUP = 0x101; - internal const int WM_SYSKEYDOWN = 0x0104; - internal const int WM_SYSKEYUP = 0x0105; - internal const int WM_COMMAND = 0x0111; - internal const int WM_SYSCOMMAND = 0x0112; - internal const int WM_ENTERIDLE = 0x121; + public const int WM_INPUT = 0x00FF; // Raw input. XP and higher only. + public const int WM_KEYDOWN = 0x0100; + public const int WM_KEYUP = 0x101; + public const int WM_SYSKEYDOWN = 0x0104; + public const int WM_SYSKEYUP = 0x0105; + public const int WM_COMMAND = 0x0111; + public const int WM_SYSCOMMAND = 0x0112; + public const int WM_ENTERIDLE = 0x121; // Pixel types (found in wingdi.h) - internal const byte PFD_TYPE_RGBA = 0; - internal const byte PFD_TYPE_COLORINDEX = 1; + public const byte PFD_TYPE_RGBA = 0; + public const byte PFD_TYPE_COLORINDEX = 1; // Layer types (found in wingdi.h) - internal const byte PFD_MAIN_PLANE = 0; - internal const byte PFD_OVERLAY_PLANE = 1; - internal const byte PFD_UNDERLAY_PLANE = unchecked((byte)-1); + public const byte PFD_MAIN_PLANE = 0; + public const byte PFD_OVERLAY_PLANE = 1; + public const byte PFD_UNDERLAY_PLANE = unchecked((byte)-1); // Device mode types (found in wingdi.h) - internal const int DM_BITSPERPEL = 0x00040000; - internal const int DM_PELSWIDTH = 0x00080000; - internal const int DM_PELSHEIGHT = 0x00100000; - internal const int DM_DISPLAYFLAGS = 0x00200000; - internal const int DM_DISPLAYFREQUENCY = 0x00400000; + public const int DM_BITSPERPEL = 0x00040000; + public const int DM_PELSWIDTH = 0x00080000; + public const int DM_PELSHEIGHT = 0x00100000; + public const int DM_DISPLAYFLAGS = 0x00200000; + public const int DM_DISPLAYFREQUENCY = 0x00400000; // ChangeDisplaySettings types (found in winuser.h) - internal const int CDS_UPDATEREGISTRY = 0x00000001; - internal const int CDS_TEST = 0x00000002; - internal const int CDS_FULLSCREEN = 0x00000004; + public const int CDS_UPDATEREGISTRY = 0x00000001; + public const int CDS_TEST = 0x00000002; + public const int CDS_FULLSCREEN = 0x00000004; // ChangeDisplaySettings results (found in winuser.h) - internal const int DISP_CHANGE_SUCCESSFUL = 0; - internal const int DISP_CHANGE_RESTART = 1; - internal const int DISP_CHANGE_FAILED = -1; + public const int DISP_CHANGE_SUCCESSFUL = 0; + public const int DISP_CHANGE_RESTART = 1; + public const int DISP_CHANGE_FAILED = -1; // (found in winuser.h) - internal const int ENUM_REGISTRY_SETTINGS = -2; - internal const int ENUM_CURRENT_SETTINGS = -1; + public const int ENUM_REGISTRY_SETTINGS = -2; + public const int ENUM_CURRENT_SETTINGS = -1; } #endregion @@ -182,7 +186,7 @@ namespace OpenTK.Platform.Windows [System.Security.SuppressUnmanagedCodeSecurity] [DllImport("User32.dll", CharSet = CharSet.Auto)] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool PeekMessage( + public static extern bool PeekMessage( out Message msg, IntPtr hWnd, int messageFilterMin, @@ -202,7 +206,7 @@ namespace OpenTK.Platform.Windows [System.Security.SuppressUnmanagedCodeSecurity] [DllImport("User32.dll", CharSet = CharSet.Auto)] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool PeekMessage( + public static extern bool PeekMessage( out System.Windows.Forms.Message msg, IntPtr hWnd, int messageFilterMin, @@ -230,8 +234,8 @@ namespace OpenTK.Platform.Windows /// [System.Security.SuppressUnmanagedCodeSecurity] [DllImport("User32.dll", CharSet = CharSet.Auto)] - [return: MarshalAs(UnmanagedType.Bool)] - internal static extern BOOL GetMessage( + //[return: MarshalAs(UnmanagedType.Bool)] + public static extern INT GetMessage( out System.Windows.Forms.Message msg, IntPtr windowHandle, int messageFilterMin, @@ -245,7 +249,7 @@ namespace OpenTK.Platform.Windows [System.Security.SuppressUnmanagedCodeSecurity] [DllImport("User32.dll", CharSet = CharSet.Auto)] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern BOOL PostMessage( + public static extern BOOL PostMessage( HWND hWnd, UINT Msg, WPARAM wParam, @@ -257,7 +261,46 @@ namespace OpenTK.Platform.Windows #region PostQuitMessage [DllImport("User32.dll", CharSet = CharSet.Auto)] - internal static extern void PostQuitMessage(int exitCode); + public static extern void PostQuitMessage(int exitCode); + + #endregion + + #region DispatchMessage + + [System.Security.SuppressUnmanagedCodeSecurity] + [DllImport("User32.dll", CharSet = CharSet.Auto)] + public static extern LRESULT DispatchMessage(ref System.Windows.Forms.Message lpmsg); + + #endregion + + #region GetQueueStatus + + /// + /// Indicates the type of messages found in the calling thread's message queue. + /// + /// + /// + /// The high-order word of the return value indicates the types of messages currently in the queue. + /// The low-order word indicates the types of messages that have been added to the queue and that are still + /// in the queue since the last call to the GetQueueStatus, GetMessage, or PeekMessage function. + /// + /// + /// The presence of a QS_ flag in the return value does not guarantee that + /// a subsequent call to the GetMessage or PeekMessage function will return a message. + /// GetMessage and PeekMessage perform some internal filtering that may cause the message + /// to be processed internally. For this reason, the return value from GetQueueStatus + /// should be considered only a hint as to whether GetMessage or PeekMessage should be called. + /// + /// The QS_ALLPOSTMESSAGE and QS_POSTMESSAGE flags differ in when they are cleared. + /// QS_POSTMESSAGE is cleared when you call GetMessage or PeekMessage, whether or not you are filtering messages. + /// QS_ALLPOSTMESSAGE is cleared when you call GetMessage or PeekMessage without filtering messages + /// (wMsgFilterMin and wMsgFilterMax are 0). This can be useful when you call PeekMessage multiple times + /// to get messages in different ranges. + /// + /// + [System.Security.SuppressUnmanagedCodeSecurity] + [DllImport("User32.dll", CharSet = CharSet.Auto)] + public static extern DWORD GetQueueStatus([MarshalAs(UnmanagedType.U4)] QueueStatusFlags flags); #endregion @@ -274,7 +317,7 @@ namespace OpenTK.Platform.Windows /// (?) [System.Security.SuppressUnmanagedCodeSecurity] [DllImport("winmm.dll")] - internal static extern IntPtr TimeBeginPeriod(int period); + public static extern IntPtr TimeBeginPeriod(int period); #endregion @@ -288,7 +331,7 @@ namespace OpenTK.Platform.Windows [System.Security.SuppressUnmanagedCodeSecurity] [DllImport("kernel32.dll")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool QueryPerformanceFrequency(ref long PerformanceFrequency); + public static extern bool QueryPerformanceFrequency(ref long PerformanceFrequency); #endregion @@ -302,7 +345,7 @@ namespace OpenTK.Platform.Windows [System.Security.SuppressUnmanagedCodeSecurity] [DllImport("kernel32.dll")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool QueryPerformanceCounter(ref long PerformanceCount); + public static extern bool QueryPerformanceCounter(ref long PerformanceCount); #endregion @@ -318,7 +361,7 @@ namespace OpenTK.Platform.Windows /// /// [DllImport("user32.dll")] - internal static extern IntPtr GetDC(IntPtr hwnd); + public static extern IntPtr GetDC(IntPtr hwnd); #endregion @@ -332,7 +375,7 @@ namespace OpenTK.Platform.Windows /// [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool ReleaseDC(IntPtr hwnd, IntPtr DC); + public static extern bool ReleaseDC(IntPtr hwnd, IntPtr DC); #endregion @@ -345,7 +388,7 @@ namespace OpenTK.Platform.Windows /// /// [DllImport("gdi32.dll")] - internal static extern int ChoosePixelFormat(IntPtr dc, [In, MarshalAs(UnmanagedType.LPStruct)]PixelFormatDescriptor pfd); + public static extern int ChoosePixelFormat(IntPtr dc, [In, MarshalAs(UnmanagedType.LPStruct)]PixelFormatDescriptor pfd); #endregion @@ -360,7 +403,7 @@ namespace OpenTK.Platform.Windows /// [DllImport("gdi32.dll")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool SetPixelFormat( + public static extern bool SetPixelFormat( IntPtr dc, int format, [In, MarshalAs(UnmanagedType.LPStruct)]PixelFormatDescriptor pfd @@ -377,7 +420,7 @@ namespace OpenTK.Platform.Windows /// [DllImport("gdi32.dll")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool SwapBuffers(IntPtr dc); + public static extern bool SwapBuffers(IntPtr dc); #endregion @@ -390,7 +433,7 @@ namespace OpenTK.Platform.Windows /// /// [DllImport("kernel32.dll")] - internal static extern IntPtr GetProcAddress(IntPtr handle, string funcname); + public static extern IntPtr GetProcAddress(IntPtr handle, string funcname); #endregion @@ -401,7 +444,7 @@ namespace OpenTK.Platform.Windows #region GetModuleHandle [DllImport("kernel32.dll")] - internal static extern IntPtr GetModuleHandle([MarshalAs(UnmanagedType.LPTStr)]string module_name); + public static extern IntPtr GetModuleHandle([MarshalAs(UnmanagedType.LPTStr)]string module_name); #endregion @@ -413,7 +456,7 @@ namespace OpenTK.Platform.Windows /// /// [DllImport("kernel32.dll", SetLastError = true)] - internal static extern IntPtr LoadLibrary(string dllName); + public static extern IntPtr LoadLibrary(string dllName); #endregion @@ -426,7 +469,7 @@ namespace OpenTK.Platform.Windows /// [DllImport("kernel32.dll")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool FreeLibrary(IntPtr handle); + public static extern bool FreeLibrary(IntPtr handle); #endregion @@ -441,7 +484,7 @@ namespace OpenTK.Platform.Windows [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool SetWindowPos( + public static extern bool SetWindowPos( IntPtr handle, WindowPlacementOptions placement, int x, int y, int cx, int cy, @@ -453,7 +496,7 @@ namespace OpenTK.Platform.Windows #region CreateWindowEx [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] - internal static extern IntPtr CreateWindowEx( + public static extern IntPtr CreateWindowEx( [In]ExtendedWindowStyle ExStyle, [In]string className, [In]string windowName, @@ -466,7 +509,7 @@ namespace OpenTK.Platform.Windows [In]IntPtr Param); /* [DllImport("user32.dll", SetLastError = true)] - internal static extern int CreateWindowEx( + public static extern int CreateWindowEx( [In]ExtendedWindowStyle ExStyle, [In]IntPtr ClassName, [In]IntPtr WindowName, @@ -479,7 +522,7 @@ namespace OpenTK.Platform.Windows [In]IntPtr Param); */ [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] - internal static extern IntPtr CreateWindowEx( + public static extern IntPtr CreateWindowEx( ExtendedWindowStyle ExStyle, IntPtr ClassName, IntPtr WindowName, @@ -491,7 +534,7 @@ namespace OpenTK.Platform.Windows IntPtr Instance, IntPtr Param); - internal enum WindowStyle : int + public enum WindowStyle : int { Overlapped = 0x00000000, Popup = unchecked((int)0x80000000), @@ -527,7 +570,7 @@ namespace OpenTK.Platform.Windows } [Flags] - internal enum ExtendedWindowStyle : int + public enum ExtendedWindowStyle : int { DialogModalFrame = 0x00000001, NoParentNotify = 0x00000004, @@ -583,27 +626,52 @@ namespace OpenTK.Platform.Windows [DllImport("user32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool DestroyWindow(IntPtr windowHandle); + public static extern bool DestroyWindow(IntPtr windowHandle); #endregion #region RegisterClass [DllImport("user32.dll", SetLastError = true)] - internal static extern short RegisterClass(WindowClass window_class); + public static extern short RegisterClass(WindowClass window_class); #endregion #region UnregisterClass [DllImport("user32.dll", SetLastError = true)] - internal static extern short UnregisterClass(string className, IntPtr instance); + public static extern short UnregisterClass(string className, IntPtr instance); [DllImport("user32.dll", SetLastError = true)] - internal static extern short UnregisterClass(IntPtr className, IntPtr instance); + public static extern short UnregisterClass(IntPtr className, IntPtr instance); #endregion + [SuppressUnmanagedCodeSecurity] + [DllImport("user32.dll", SetLastError = true)] + public static extern LRESULT CallWindowProc( + WNDPROC lpPrevWndFunc, + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam + ); + + [SuppressUnmanagedCodeSecurity] + [DllImport("user32.dll", SetLastError = true)] + public static extern LONG_PTR SetWindowLongPtr( + HWND hWnd, + GetWindowLongOffsets nIndex, + LONG_PTR dwNewLong + ); + + [SuppressUnmanagedCodeSecurity] + [DllImport("user32.dll", SetLastError = true)] + public static extern LONG_PTR GetWindowLongPtr( + HWND hWnd, + GetWindowLongOffsets nIndex + ); + #endregion #region Display settings @@ -616,13 +684,13 @@ namespace OpenTK.Platform.Windows /// /// [DllImport("user32.dll", SetLastError = true)] - internal static extern int ChangeDisplaySettings(DeviceMode device_mode, int flags); + public static extern int ChangeDisplaySettings(DeviceMode device_mode, int flags); #endregion int ChangeDisplaySettings(ref Gdi.DEVMODE devMode, int flags) #region EnumDisplaySettings [DllImport("user32.dll", SetLastError = true)] - internal static extern int EnumDisplaySettings([MarshalAs(UnmanagedType.LPTStr)] string device_name, + public static extern int EnumDisplaySettings([MarshalAs(UnmanagedType.LPTStr)] string device_name, int graphics_mode, IntPtr device_mode); #endregion @@ -861,11 +929,51 @@ namespace OpenTK.Platform.Windows [DllImport("user32.dll", SetLastError = true)] public static extern UINT GetRawInputDeviceInfo( HANDLE Device, - UINT Command, + [MarshalAs(UnmanagedType.U4)] RawInputDeviceInfoEnum Command, [In, Out] LPVOID Data, [In, Out] ref UINT Size ); + /// + /// Gets information about the raw input device. + /// + /// + /// Handle to the raw input device. This comes from the lParam of the WM_INPUT message, + /// from RawInputHeader.Device, or from GetRawInputDeviceList. + /// It can also be NULL if an application inserts input data, for example, by using SendInput. + /// + /// + /// Specifies what data will be returned in pData. It can be one of the following values. + /// RawInputDeviceInfoEnum.PREPARSEDDATA + /// Data points to the previously parsed data. + /// RawInputDeviceInfoEnum.DEVICENAME + /// Data points to a string that contains the device name. + /// For this Command only, the value in Size is the character count (not the byte count). + /// RawInputDeviceInfoEnum.DEVICEINFO + /// Data points to an RawInputDeviceInfo structure. + /// + /// + /// ointer to a buffer that contains the information specified by Command. + /// If Command is RawInputDeviceInfoEnum.DEVICEINFO, set RawInputDeviceInfo.Size to sizeof(RawInputDeviceInfo) + /// before calling GetRawInputDeviceInfo. (This is done automatically in OpenTK) + /// + /// + /// Pointer to a variable that contains the size, in bytes, of the data in Data. + /// + /// + /// If successful, this function returns a non-negative number indicating the number of bytes copied to Data. + /// If Data is not large enough for the data, the function returns -1. If Data is NULL, the function returns a value of zero. In both of these cases, Size is set to the minimum size required for the Data buffer. + /// Call GetLastError to identify any other errors. + /// + [System.Security.SuppressUnmanagedCodeSecurity] + [DllImport("user32.dll", SetLastError = true)] + public static extern UINT GetRawInputDeviceInfo( + HANDLE Device, + [MarshalAs(UnmanagedType.U4)] RawInputDeviceInfoEnum Command, + [In, Out] RawInputDeviceInfo Data, + [In, Out] ref UINT Size + ); + #endregion #region GetRawInputData @@ -943,16 +1051,16 @@ namespace OpenTK.Platform.Windows #region Message [StructLayout(LayoutKind.Sequential)] - internal struct Message + public struct Message { - internal IntPtr HWnd; - internal int Msg; - internal IntPtr WParam; - internal IntPtr LParam; - internal IntPtr Result; + public IntPtr HWnd; + public int Msg; + public IntPtr WParam; + public IntPtr LParam; + public IntPtr Result; - //internal int Time; - //internal System.Drawing.Point p; + //public int Time; + //public System.Drawing.Point p; //System.Drawing. } @@ -960,7 +1068,7 @@ namespace OpenTK.Platform.Windows #region CreateStruct - internal struct CreateStruct + public struct CreateStruct { /// /// Contains additional data which may be used to create the window. @@ -986,50 +1094,50 @@ namespace OpenTK.Platform.Windows /// may not be DWORD aligned. /// /// - internal LPVOID lpCreateParams; + public LPVOID lpCreateParams; /// /// Handle to the module that owns the new window. /// - internal HINSTANCE hInstance; + public HINSTANCE hInstance; /// /// Handle to the menu to be used by the new window. /// - internal HMENU hMenu; + public HMENU hMenu; /// /// Handle to the parent window, if the window is a child window. /// If the window is owned, this member identifies the owner window. /// If the window is not a child or owned window, this member is NULL. /// - internal HWND hwndParent; + public HWND hwndParent; /// /// Specifies the height of the new window, in pixels. /// - internal int cy; + public int cy; /// /// Specifies the width of the new window, in pixels. /// - internal int cx; + public int cx; /// /// Specifies the y-coordinate of the upper left corner of the new window. /// If the new window is a child window, coordinates are relative to the parent window. /// Otherwise, the coordinates are relative to the screen origin. /// - internal int y; + public int y; /// /// Specifies the x-coordinate of the upper left corner of the new window. /// If the new window is a child window, coordinates are relative to the parent window. /// Otherwise, the coordinates are relative to the screen origin. /// - internal int x; + public int x; /// /// Specifies the style for the new window. /// - internal LONG style; + public LONG style; /// /// Pointer to a null-terminated string that specifies the name of the new window. /// [MarshalAs(UnmanagedType.LPTStr)] - internal LPCTSTR lpszName; + public LPCTSTR lpszName; /// /// Either a pointer to a null-terminated string or an atom that specifies the class name /// of the new window. @@ -1039,11 +1147,11 @@ namespace OpenTK.Platform.Windows /// /// [MarshalAs(UnmanagedType.LPTStr)] - internal LPCTSTR lpszClass; + public LPCTSTR lpszClass; /// /// Specifies the extended window style for the new window. /// - internal DWORD dwExStyle; + public DWORD dwExStyle; } #endregion @@ -1054,37 +1162,37 @@ namespace OpenTK.Platform.Windows /// Found in WinGDI.h /// [StructLayout(LayoutKind.Sequential)] - internal class PixelFormatDescriptor + public class PixelFormatDescriptor { short Size = 40; // No need for the user to set the size, since it is predefined. - internal short Version = 1; - internal PixelFormatDescriptorFlags Flags = + public short Version = 1; + public PixelFormatDescriptorFlags Flags = //PixelFormatDescriptorFlags.DOUBLEBUFFER | PixelFormatDescriptorFlags.DRAW_TO_WINDOW | PixelFormatDescriptorFlags.SUPPORT_OPENGL; - internal byte PixelType = Constants.PFD_TYPE_RGBA; - internal byte ColorBits = 0; - internal byte RedBits = 0; - internal byte RedShift = 0; - internal byte GreenBits = 0; - internal byte GreenShift = 0; - internal byte BlueBits = 0; - internal byte BlueShift = 0; - internal byte AlphaBits = 8; - internal byte AlphaShift = 0; - internal byte AccumBits = 0; - internal byte AccumRedBits = 0; - internal byte AccumGreenBits = 0; - internal byte AccumBlueBits = 0; - internal byte AccumAlphaBits = 0; - internal byte DepthBits = 0; - internal byte StencilBits = 0; - internal byte AuxBuffers = 0; - internal byte LayerType = unchecked((byte)Constants.PFD_MAIN_PLANE); + public byte PixelType = Constants.PFD_TYPE_RGBA; + public byte ColorBits = 0; + public byte RedBits = 0; + public byte RedShift = 0; + public byte GreenBits = 0; + public byte GreenShift = 0; + public byte BlueBits = 0; + public byte BlueShift = 0; + public byte AlphaBits = 8; + public byte AlphaShift = 0; + public byte AccumBits = 0; + public byte AccumRedBits = 0; + public byte AccumGreenBits = 0; + public byte AccumBlueBits = 0; + public byte AccumAlphaBits = 0; + public byte DepthBits = 0; + public byte StencilBits = 0; + public byte AuxBuffers = 0; + public byte LayerType = unchecked((byte)Constants.PFD_MAIN_PLANE); byte Reserved = 0; - internal int LayerMask = 0; - internal int VisibleMask = 0; - internal int DamageMask = 0; + public int LayerMask = 0; + public int VisibleMask = 0; + public int DamageMask = 0; } #endregion @@ -1143,51 +1251,51 @@ namespace OpenTK.Platform.Windows } DEVMODE; */ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - internal class DeviceMode + public class DeviceMode { - internal DeviceMode() + public DeviceMode() { Size = (short)Marshal.SizeOf(this); } [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] - internal string DeviceName; - internal short SpecVersion; - internal short DriverVersion; + public string DeviceName; + public short SpecVersion; + public short DriverVersion; private short Size; - internal short DriverExtra; - internal int Fields; + public short DriverExtra; + public int Fields; - internal short Orientation; - internal short PaperSize; - internal short PaperLength; - internal short PaperWidth; - internal short Scale; - internal short Copies; - internal short DefaultSource; - internal short PrintQuality; + public short Orientation; + public short PaperSize; + public short PaperLength; + public short PaperWidth; + public short Scale; + public short Copies; + public short DefaultSource; + public short PrintQuality; - internal short Color; - internal short Duplex; - internal short YResolution; - internal short TTOption; - internal short Collate; + public short Color; + public short Duplex; + public short YResolution; + public short TTOption; + public short Collate; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] - internal string FormName; - internal short LogPixels; - internal int BitsPerPel; - internal int PelsWidth; - internal int PelsHeight; - internal int DisplayFlags; - internal int DisplayFrequency; - internal int ICMMethod; - internal int ICMIntent; - internal int MediaType; - internal int DitherType; - internal int Reserved1; - internal int Reserved2; - internal int PanningWidth; - internal int PanningHeight; + public string FormName; + public short LogPixels; + public int BitsPerPel; + public int PelsWidth; + public int PelsHeight; + public int DisplayFlags; + public int DisplayFrequency; + public int ICMMethod; + public int ICMIntent; + public int MediaType; + public int DitherType; + public int Reserved1; + public int Reserved2; + public int PanningWidth; + public int PanningHeight; } #endregion DeviceMode class @@ -1196,23 +1304,23 @@ namespace OpenTK.Platform.Windows #region WindowClass [StructLayout(LayoutKind.Sequential)] - internal class WindowClass + public class WindowClass { - internal WindowClassStyle style = WindowClassStyle.VRedraw | WindowClassStyle.HRedraw | WindowClassStyle.OwnDC; + public WindowClassStyle style = WindowClassStyle.VRedraw | WindowClassStyle.HRedraw | WindowClassStyle.OwnDC; [MarshalAs(UnmanagedType.FunctionPtr)] - internal WindowProcedureEventHandler WindowProcedure; - internal int ClassExtraBytes; - internal int WindowExtraBytes; + public WindowProcedureEventHandler WindowProcedure; + public int ClassExtraBytes; + public int WindowExtraBytes; //[MarshalAs(UnmanagedType. - internal IntPtr Instance; - internal IntPtr Icon; - internal IntPtr Cursor; - internal IntPtr BackgroundBrush; + public IntPtr Instance; + public IntPtr Icon; + public IntPtr Cursor; + public IntPtr BackgroundBrush; //[MarshalAs(UnmanagedType.LPStr)] - internal IntPtr MenuName; + public IntPtr MenuName; //[MarshalAs(UnmanagedType.LPStr)] - internal IntPtr ClassName; - //internal string ClassName; + public IntPtr ClassName; + //public string ClassName; } #endregion @@ -1623,6 +1731,8 @@ namespace OpenTK.Platform.Windows #region RawInputDeviceInfo + public static readonly uint RawInputDeviceInfoSize; + /// /// Defines the raw input data coming from any device. /// @@ -1635,13 +1745,18 @@ namespace OpenTK.Platform.Windows DWORD Size = Marshal.SizeOf(typeof(RawInputDeviceInfo)); /// /// Type of raw input data. + /// public RawInputDeviceType Type; + public DeviceStruct Device; [StructLayout(LayoutKind.Explicit)] - public struct Device - { - [FieldOffset(0)]RawInputMouseDeviceInfo Mouse; - [FieldOffset(0)]RawInputKeyboardDeviceInfo Keyboard; - [FieldOffset(0)]RawInputHIDDeviceInfo HID; + public struct DeviceStruct + { + [FieldOffset(0)] + public RawInputMouseDeviceInfo Mouse; + [FieldOffset(0)] + public RawInputKeyboardDeviceInfo Keyboard; + [FieldOffset(0)] + public RawInputHIDDeviceInfo HID; }; } @@ -1754,13 +1869,56 @@ namespace OpenTK.Platform.Windows #endregion + #region GetWindowLongOffsets + + /// + /// Window field offsets for GetWindowLong() and GetWindowLongPtr(). + /// + public static class GWL + { + private static bool x64; + static GWL() + { + unsafe + { + x64 = sizeof(void*) == 8; + } + + } + + public static readonly int WNDPROC = (-4); + public static readonly int HINSTANCE = (-6); + public static readonly int HWNDPARENT = (-8); + public static readonly int STYLE = (-16); + public static readonly int EXSTYLE = (-20); + public static readonly int USERDATA = (-21); + public static readonly int ID = (-12); + } + + #endregion + #endregion #region --- Enums --- - + + #region GetWindowLongOffsets enum + + public enum GetWindowLongOffsets : int + { + WNDPROC = (-4), + HINSTANCE = (-6), + HWNDPARENT = (-8), + STYLE = (-16), + EXSTYLE = (-20), + USERDATA = (-21), + ID = (-12), + } + + #endregion + #region PixelFormatDescriptorFlags enum [Flags] - internal enum PixelFormatDescriptorFlags : int + public enum PixelFormatDescriptorFlags : int { // PixelFormatDescriptor flags DOUBLEBUFFER, @@ -1787,7 +1945,7 @@ namespace OpenTK.Platform.Windows #region WindowPlacementOptions enum - internal enum WindowPlacementOptions + public enum WindowPlacementOptions { TOP = 0, BOTTOM = 1, @@ -1799,7 +1957,7 @@ namespace OpenTK.Platform.Windows #region WindowClassStyle enum [Flags] - internal enum WindowClassStyle + public enum WindowClassStyle { //None = 0x0000, VRedraw = 0x0001, @@ -2215,17 +2373,94 @@ namespace OpenTK.Platform.Windows #endregion + #region QueueStatusFlags + + [Flags] + /// + /// Queue status flags for GetQueueStatus() and MsgWaitForMultipleObjects() + /// + public enum QueueStatusFlags + { + /// + /// A WM_KEYUP, WM_KEYDOWN, WM_SYSKEYUP, or WM_SYSKEYDOWN message is in the queue. + /// + KEY = 0x0001, + /// + /// A WM_MOUSEMOVE message is in the queue. + /// + MOUSEMOVE = 0x0002, + /// + /// A mouse-button message (WM_LBUTTONUP, WM_RBUTTONDOWN, and so on). + /// + MOUSEBUTTON = 0x0004, + /// + /// A posted message (other than those listed here) is in the queue. + /// + POSTMESSAGE = 0x0008, + /// + /// A WM_TIMER message is in the queue. + /// + TIMER = 0x0010, + /// + /// A WM_PAINT message is in the queue. + /// + PAINT = 0x0020, + /// + /// A message sent by another thread or application is in the queue. + /// + SENDMESSAGE = 0x0040, + /// + /// A WM_HOTKEY message is in the queue. + /// + HOTKEY = 0x0080, + /// + /// A posted message (other than those listed here) is in the queue. + /// + ALLPOSTMESSAGE = 0x0100, + /// + /// A raw input message is in the queue. For more information, see Raw Input. + /// Windows XP and higher only. + /// + RAWINPUT = 0x0400, + /// + /// A WM_MOUSEMOVE message or mouse-button message (WM_LBUTTONUP, WM_RBUTTONDOWN, and so on). + /// + MOUSE = MOUSEMOVE | MOUSEBUTTON, + /// + /// An input message is in the queue. This is composed of KEY, MOUSE and RAWINPUT. + /// Windows XP and higher only. + /// + INPUT = MOUSE | KEY | RAWINPUT, + /// + /// An input message is in the queue. This is composed of QS_KEY and QS_MOUSE. + /// Windows 2000 and earlier. + /// + INPUT_LEGACY = MOUSE | KEY, + /// + /// An input, WM_TIMER, WM_PAINT, WM_HOTKEY, or posted message is in the queue. + /// + ALLEVENTS = INPUT | POSTMESSAGE | TIMER | PAINT | HOTKEY, + /// + /// Any message is in the queue. + /// + ALLINPUT = INPUT | POSTMESSAGE | TIMER | PAINT | HOTKEY | SENDMESSAGE + } + + #endregion + #endregion #region --- Callbacks --- - [UnmanagedFunctionPointerAttribute(CallingConvention.Winapi)] - internal delegate void WindowProcedureEventHandler(object sender, WindowProcedureEventArgs e); + public delegate void WindowProcedure(ref System.Windows.Forms.Message msg); - internal class WindowProcedureEventArgs : EventArgs + [UnmanagedFunctionPointerAttribute(CallingConvention.Winapi)] + public delegate void WindowProcedureEventHandler(object sender, WindowProcedureEventArgs e); + + public class WindowProcedureEventArgs : EventArgs { - private Message msg; - internal Message Message + private System.Windows.Forms.Message msg; + public System.Windows.Forms.Message Message { get { return msg; } set { msg = value; } diff --git a/Source/OpenTK/Platform/Windows/WinGLControl.cs b/Source/OpenTK/Platform/Windows/WinGLControl.cs index 71e40491..6f43541c 100644 --- a/Source/OpenTK/Platform/Windows/WinGLControl.cs +++ b/Source/OpenTK/Platform/Windows/WinGLControl.cs @@ -23,6 +23,7 @@ namespace OpenTK.Platform.Windows private ResizeEventArgs resizeEventArgs = new ResizeEventArgs(); private bool disposed; + private Message msg; // Used only by the IsIdle event. #region --- Constructors --- @@ -48,16 +49,6 @@ namespace OpenTK.Platform.Windows public event CreateEvent Create; - #region public void ProcessEvents() - - private API.Message msg; - public void ProcessEvents() - { - throw new Exception("The method or operation is not implemented."); - } - - #endregion - #region public bool IsIdle public bool IsIdle @@ -70,15 +61,6 @@ namespace OpenTK.Platform.Windows #endregion - #region public OpenTK.Platform.IGLContext Context - - public OpenTK.Platform.IGLContext Context - { - get { return glContext; } - } - - #endregion - #region public bool Fullscreen public bool Fullscreen @@ -90,12 +72,20 @@ namespace OpenTK.Platform.Windows set { throw new NotImplementedException(); - fullscreen = true; } } #endregion + #region public IGLContext Context + + public IGLContext Context + { + get { return glContext; } + } + + #endregion + #endregion #region --- IDisposable Members --- diff --git a/Source/OpenTK/Platform/Windows/WinGLNative.cs b/Source/OpenTK/Platform/Windows/WinGLNative.cs index 10b79587..94b60685 100644 --- a/Source/OpenTK/Platform/Windows/WinGLNative.cs +++ b/Source/OpenTK/Platform/Windows/WinGLNative.cs @@ -11,6 +11,7 @@ using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using System.Windows.Forms; +using System.Diagnostics; #endregion @@ -18,12 +19,16 @@ namespace OpenTK.Platform.Windows { sealed class WinGLNative : NativeWindow, OpenTK.Platform.INativeWindow, IDisposable { + #region --- Fields --- + private WinGLContext glContext; private DisplayMode mode = new DisplayMode(); - - private Input.IInputDriver inputDriver; private bool disposed; + private bool quit; + private bool created; + + #endregion #region --- Contructors --- @@ -32,24 +37,94 @@ namespace OpenTK.Platform.Windows /// public WinGLNative() { - mode = new DisplayMode(); - mode.Width = 640; - mode.Height = 480; - - this.CreateWindow(mode); } #endregion - #region private void CreateWindow() + #region protected override void WndProc(ref Message m) - private void CreateWindow(DisplayMode mode) + /// + /// For use in WndProc only. + /// + private int width, height; + + /// + /// Processes incoming WM_* messages. + /// + /// Reference to the incoming Windows Message. + protected override void WndProc(ref Message m) + { + switch (m.Msg) + { + case API.Constants.WM_WINDOWPOSCHANGED: + // Get window size + width = Marshal.ReadInt32(m.LParam, (int)Marshal.OffsetOf(typeof(API.WindowPosition), "cx")); + height = Marshal.ReadInt32(m.LParam, (int)Marshal.OffsetOf(typeof(API.WindowPosition), "cy")); + //if (resizeEventArgs.Width != width || resizeEventArgs.Height != height) + if (mode.Width != width || mode.Height != height) + { + // If the size has changed, raise the ResizeEvent. + resizeEventArgs.Width = width; + resizeEventArgs.Height = height; + this.OnResize(resizeEventArgs); + // The message was processed. + return; + } + // If the message was not a resize notification, send it to the default WndProc. + break; + + case API.Constants.WM_CREATE: + // Set the window width and height: + mode.Width = Marshal.ReadInt32(m.LParam, (int)Marshal.OffsetOf(typeof(API.CreateStruct), "cx")); + mode.Height = Marshal.ReadInt32(m.LParam, (int)Marshal.OffsetOf(typeof(API.CreateStruct), "cy")); + + // Raise the Create event + this.OnCreate(EventArgs.Empty); + + // Raise the resize event: + //resizeEventArgs.Width = width; + //resizeEventArgs.Height = height; + //this.OnResize(resizeEventArgs); + return; + + //case API.Constants.WM_KEYDOWN: // Legacy input events + //case API.Constants.WM_KEYUP: + // break; + + //case API.Constants.WM_INPUT: // Raw input + // WinRawInput.ProcessEvent(ref msg, key); + // break; + + case API.Constants.WM_CLOSE: + case API.Constants.WM_DESTROY: + Debug.Print("Window handle {0} destroyed.", this.Handle); + this.DestroyHandle(); + API.PostQuitMessage(0); + return; + + case API.Constants.WM_QUIT: + quit = true; + Debug.WriteLine("Window quit."); + return; + } + + //base.WndProc(ref m); + DefWndProc(ref m); + } + + #endregion + + #region --- INativeWindow Members --- + + #region private void CreateWindow(DisplayMode mode) + + public void CreateWindow(DisplayMode mode) { CreateParams cp = new CreateParams(); cp.ClassStyle = (int)API.WindowClassStyle.OwnDC | (int)API.WindowClassStyle.VRedraw | - (int)API.WindowClassStyle.HRedraw; + (int)API.WindowClassStyle.HRedraw | (int)API.WindowClassStyle.Ime; cp.Style = (int)API.WindowStyle.Visible | (int)API.WindowStyle.ClipChildren | @@ -72,6 +147,17 @@ namespace OpenTK.Platform.Windows 0.0f ) ); + + if (this.Handle != IntPtr.Zero && glContext != null) + { + created = true; + } + else + { + throw new ApplicationException(String.Format( + "Could not create native window and/or context. Handle: {0}, Context {1}", + this.Handle, this.Context.ToString())); + } } /* @@ -121,84 +207,34 @@ namespace OpenTK.Platform.Windows */ #endregion - #region protected override void WndProc(ref Message m) + #region public void Exit() /// - /// For use in WndProc only. + /// Starts the teardown sequence for the current window. /// - private int width, height; - - /// - /// Processes incoming WM_* messages. - /// - /// Reference to the incoming Windows Message. - protected override void WndProc(ref Message m) + public void Exit() { - switch (m.Msg) - { - case API.Constants.WM_WINDOWPOSCHANGED: - // Get window size - width = Marshal.ReadInt32(m.LParam, (int)Marshal.OffsetOf(typeof(API.WindowPosition), "cx")); - height = Marshal.ReadInt32(m.LParam, (int)Marshal.OffsetOf(typeof(API.WindowPosition), "cy")); - //if (resizeEventArgs.Width != width || resizeEventArgs.Height != height) - if (mode.Width != width || mode.Height != height) - { - // If the size has changed, raise the ResizeEvent. - resizeEventArgs.Width = width; - resizeEventArgs.Height = height; - this.OnResize(resizeEventArgs); - // The message was processed. - return; - } - // If the message was not a resize notification, send it to the default WndProc. - break; - - case API.Constants.WM_CREATE: - // Set the window width and height: - mode.Width = Marshal.ReadInt32(m.LParam, (int)Marshal.OffsetOf(typeof(API.CreateStruct), "cx")); - mode.Height = Marshal.ReadInt32(m.LParam, (int)Marshal.OffsetOf(typeof(API.CreateStruct), "cy")); - - // Raise the Create event - this.OnCreate(EventArgs.Empty); - - // Raise the resize event: - //resizeEventArgs.Width = width; - //resizeEventArgs.Height = height; - //this.OnResize(resizeEventArgs); - return; - - case API.Constants.WM_KEYDOWN: // Legacy input events - case API.Constants.WM_KEYUP: - break; - - //case API.Constants.WM_INPUT: // Raw input - // WinRawInput.ProcessEvent(ref msg, key); - // break; - - case API.Constants.WM_CLOSE: - API.PostQuitMessage(0); - return; - - case API.Constants.WM_QUIT: - quit = true; - break; - } - - base.WndProc(ref m); + API.PostMessage(this.Handle, (uint)API.Constants.WM_DESTROY, IntPtr.Zero, IntPtr.Zero); } #endregion - #region --- INativeWindow Members --- - #region public void ProcessEvents() - private System.Windows.Forms.Message msg; + private int ret; + System.Windows.Forms.Message msg; public void ProcessEvents() { - while (API.PeekMessage(out msg, IntPtr.Zero, 0, 0, 0)) + while (!IsIdle) { - API.GetMessage(out msg, IntPtr.Zero, 0, 0); + ret = API.GetMessage(out msg, Handle, 0, 0); + if (ret == -1) + { + throw new ApplicationException(String.Format( + "An error happened while processing the message queue. Windows error: {0}", + Marshal.GetLastWin32Error())); + } + API.DispatchMessage(ref msg); WndProc(ref msg); } } @@ -219,20 +255,23 @@ namespace OpenTK.Platform.Windows #endregion + #region public bool Created + + /// + /// Returns true if a render window/context exists. + /// + public bool Created + { + get { return created; } + } + + #endregion + #region public bool Quit - private bool quit; public bool Quit { get { return quit; } - set - { - if (value) - { - API.PostQuitMessage(0); - //quit = true; - } - } } #endregion @@ -269,7 +308,9 @@ namespace OpenTK.Platform.Windows { get { - return !API.PeekMessage(out msg, IntPtr.Zero, 0, 0, 0); + //return !API.PeekMessage(out msg, IntPtr.Zero, 0, 0, 0); + return !API.PeekMessage(out msg, this.Handle, 0, 0, 0); + //return API.GetQueueStatus(API.QueueStatusFlags.ALLEVENTS) == 0; } } diff --git a/Source/OpenTK/Platform/Windows/WinRawInput.cs b/Source/OpenTK/Platform/Windows/WinRawInput.cs index eb24c481..3a52a921 100644 --- a/Source/OpenTK/Platform/Windows/WinRawInput.cs +++ b/Source/OpenTK/Platform/Windows/WinRawInput.cs @@ -28,42 +28,33 @@ namespace OpenTK.Platform.Windows /// /// The list of keyboards connected to this system. /// - private List keyboards = new List(); - - WinRawKeyboard key; + //internal List keyboards = new List(); - internal IEnumerable InputDevices + private WinRawKeyboard keyboardDriver; + + internal WinRawInput(IntPtr parentHandle) { - get - { - return (IEnumerable)key; - } + Debug.WriteLine("Initalizing raw input driver."); + Debug.Indent(); + + AssignHandle(parentHandle); + Debug.Print("Input window attached to parent {0}", this.Handle); + keyboardDriver = new WinRawKeyboard(this.Handle); + + Debug.Unindent(); } - internal WinRawInput() - { - CreateParams cp = new CreateParams(); - /*cp.ClassStyle = - (int)API.WindowClassStyle.ParentDC; - cp.Style = - (int)API.WindowStyle.Disabled | - (int)API.WindowStyle.ChildWindow;*/ - - cp.Caption = "OpenTK hidden input handler window"; - base.CreateHandle(cp); - //key = new WinRawKeyboard(this.Handle); - - uint numKeyboards = WinRawKeyboard.Count; - } - - private static uint deviceCount; internal static uint DeviceCount { - get { return DeviceListChanged ? deviceCount : deviceCount; } + get + { + API.GetRawInputDeviceList(null, ref deviceCount, API.RawInputDeviceListSize); + return deviceCount; + } } - + /* /// /// Gets a value indicating whether the Device list has changed, for example /// by removing or adding a device. @@ -89,49 +80,65 @@ namespace OpenTK.Platform.Windows } } } - + */ #region protected override void WndProc(ref Message msg) + uint size = 0; + /// /// Processes the input Windows Message, routing the data to the correct Keyboard, Mouse or HID. /// /// The WM_INPUT message, containing the data on the input event. protected override void WndProc(ref Message msg) { - if (msg.Msg == API.Constants.WM_INPUT) + switch (msg.Msg) { - uint size = 0; - // Get the size of the input data - API.GetRawInputData(msg.LParam, API.GetRawInputDataEnum.INPUT, - IntPtr.Zero, ref size, API.RawInputHeaderSize); + case API.Constants.WM_INPUT: + size = 0; + // Get the size of the input data + API.GetRawInputData(msg.LParam, API.GetRawInputDataEnum.INPUT, + IntPtr.Zero, ref size, API.RawInputHeaderSize); - if (data == null || API.RawInputSize < size) - { - throw new ApplicationException("Critical error when processing raw windows input."); - } + //if (data == null || API.RawInputSize < size) + //{ + // throw new ApplicationException("Critical error when processing raw windows input."); + //} - if (size == API.GetRawInputData(msg.LParam, API.GetRawInputDataEnum.INPUT, - data, ref size, API.RawInputHeaderSize)) - { - switch (data.Header.Type) + if (size == API.GetRawInputData(msg.LParam, API.GetRawInputDataEnum.INPUT, + data, ref size, API.RawInputHeaderSize)) { - case API.RawInputDeviceType.KEYBOARD: - ProcessKeyboardEvent(data); - break; + switch (data.Header.Type) + { + case API.RawInputDeviceType.KEYBOARD: + keyboardDriver.ProcessKeyboardEvent(data); + break; - case API.RawInputDeviceType.MOUSE: - throw new NotImplementedException(); + case API.RawInputDeviceType.MOUSE: + //throw new NotImplementedException(); + break; - case API.RawInputDeviceType.HID: - throw new NotImplementedException(); + case API.RawInputDeviceType.HID: + //throw new NotImplementedException(); + break; + } } - } - else - { - throw new ApplicationException( - "GetRawInputData returned invalid data. Please file a bug at http://opentk.sourceforge.net" - ); - } + else + { + throw new ApplicationException(String.Format( + "GetRawInputData returned invalid data. Windows error {0}. Please file a bug at http://opentk.sourceforge.net", + Marshal.GetLastWin32Error())); + } + break; + + case API.Constants.WM_CLOSE: + case API.Constants.WM_DESTROY: + Debug.Print("Input window detached from parent {0}.", Handle); + ReleaseHandle(); + break; + + case API.Constants.WM_QUIT: + Debug.WriteLine("Input window quit."); + break; } base.WndProc(ref msg); @@ -139,64 +146,6 @@ namespace OpenTK.Platform.Windows #endregion - #region internal bool ProcessKeyboardEvent(API.RawInput rin) - - /// - /// Processes raw input events. - /// - /// - /// - internal bool ProcessKeyboardEvent(API.RawInput rin) - { - switch (rin.Header.Type) - { - case API.RawInputDeviceType.KEYBOARD: - bool pressed = - rin.Data.Keyboard.Message == API.Constants.WM_KEYDOWN || - rin.Data.Keyboard.Message == API.Constants.WM_SYSKEYDOWN; - - // Generic control, shift, alt keys may be sent instead of left/right. - // It seems you have to explicitly register left/right events. - switch (rin.Data.Keyboard.VKey) - { - case API.VirtualKeys.SHIFT: - key[Input.Keys.LeftShift] = key[Input.Keys.RightShift] = pressed; - return false; - - case API.VirtualKeys.CONTROL: - key[Input.Keys.LeftControl] = key[Input.Keys.RightControl] = pressed; - return false; - - case API.VirtualKeys.MENU: - key[Input.Keys.LeftAlt] = key[Input.Keys.RightAlt] = pressed; - return false; - - default: - if (!WinRawKeyboard.KeyMap.ContainsKey(rin.Data.Keyboard.VKey)) - { - Debug.Print("Virtual key {0} not mapped.", rin.Data.Keyboard.VKey); - OpenTK.OpenGL.GL.ClearColor(1.0f, 0.3f, 0.3f, 0.0f); - } - else - { - key[WinRawKeyboard.KeyMap[rin.Data.Keyboard.VKey]] = pressed; - OpenTK.OpenGL.GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f); - } - break; - } - break; - - case API.RawInputDeviceType.MOUSE: - break; - - case API.RawInputDeviceType.HID: - break; - } - return false; - } - - #endregion - #region --- IInputDriver Members --- IList Input.IInputDriver.InputDevices @@ -204,9 +153,9 @@ namespace OpenTK.Platform.Windows get { throw new Exception("The method or operation is not implemented."); } } - public IList Keyboards + public IList Keyboards { - get { return (IList)keyboards; } + get { return keyboardDriver.Keyboards; } } #endregion diff --git a/Source/OpenTK/Platform/Windows/WinRawKeyboard.cs b/Source/OpenTK/Platform/Windows/WinRawKeyboard.cs index 9956140c..d3642d0f 100644 --- a/Source/OpenTK/Platform/Windows/WinRawKeyboard.cs +++ b/Source/OpenTK/Platform/Windows/WinRawKeyboard.cs @@ -11,14 +11,17 @@ using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using System.Diagnostics; +using Microsoft.Win32; +using OpenTK.Input; #endregion namespace OpenTK.Platform.Windows { - internal class WinRawKeyboard : Input.IKeyboard + internal class WinRawKeyboard : IKeyboardDriver { - private bool[] keys = new bool[(int)Input.Keys.MaxKeys]; + private List keyboards = new List(); + private IntPtr windowHandle; #region internal static Dictionary KeyMap @@ -126,41 +129,6 @@ namespace OpenTK.Platform.Windows #endregion - /// - /// The count of physical keyboards connected to this computer. - /// - private static uint keyboardCount; - internal static uint Count - { - get - { - if (!WinRawInput.DeviceListChanged && keyboardCount != 0) - { - return keyboardCount; - } - else - { - UpdateKeyboardList(); - return keyboardCount; - } - } - } - - internal static void UpdateKeyboardList() - { - uint count = WinRawInput.DeviceCount; - API.RawInputDeviceList[] ridl = new API.RawInputDeviceList[count]; - for (int i = 0; i < count; i++) - ridl[i] = new API.RawInputDeviceList(); - API.GetRawInputDeviceList(ridl, ref count, API.RawInputDeviceListSize); - - for (int i = 0; i < count; i++) - { - //do something with the information (see section on GetRawInputDeviceInfo) - - } - } - #region --- Constructors --- internal WinRawKeyboard() @@ -170,15 +138,108 @@ namespace OpenTK.Platform.Windows internal WinRawKeyboard(IntPtr windowHandle) { - Debug.WriteLine("Keyboard driver: Windows raw input"); + Debug.WriteLine("Initializing keyboard driver."); + Debug.Indent(); + + this.windowHandle = windowHandle; + InitKeyMap(); + + UpdateKeyboardList(); + + Debug.Unindent(); + } + + #endregion + + #region internal static void UpdateKeyboardList() + + internal void UpdateKeyboardList() + { + uint count = WinRawInput.DeviceCount; + API.RawInputDeviceList[] ridl = new API.RawInputDeviceList[count]; + for (int i = 0; i < count; i++) + ridl[i] = new API.RawInputDeviceList(); + API.GetRawInputDeviceList(ridl, ref count, API.RawInputDeviceListSize); + + // Discover keyboard devices: + for (int i = 0; i < count; i++) + { + uint size = 0; + API.GetRawInputDeviceInfo(ridl[i].Device, API.RawInputDeviceInfoEnum.DEVICENAME, IntPtr.Zero, ref size); + IntPtr name_ptr = Marshal.AllocHGlobal((IntPtr)size); + API.GetRawInputDeviceInfo(ridl[i].Device, API.RawInputDeviceInfoEnum.DEVICENAME, name_ptr, ref size); + string name = Marshal.PtrToStringAnsi(name_ptr); + Marshal.FreeHGlobal(name_ptr); + if (name.ToLower().Contains("root")) + { + // This is a terminal services devices, skip it. + continue; + } + else if ( + ridl[i].Type == API.RawInputDeviceType.KEYBOARD || + ridl[i].Type == API.RawInputDeviceType.HID) + { + //It's a keyboard – or a USB device that could be a keyboard + + // remove the \??\ + name = name.Substring(4); + + string[] split = name.Split('#'); + + string id_01 = split[0]; // ACPI (Class code) + string id_02 = split[1]; // PNP0303 (SubClass code) + string id_03 = split[2]; // 3&13c0b0c5&0 (Protocol code) + // The final part is the class GUID and is not needed here + + + string findme = string.Format( + @"System\CurrentControlSet\Enum\{0}\{1}\{2}", + id_01, id_02, id_03); + + RegistryKey regkey = Registry.LocalMachine.OpenSubKey(findme); + + string deviceDesc = + (string)regkey.GetValue("DeviceDesc"); + string deviceClass = + (string)regkey.GetValue("Class"); + if (!String.IsNullOrEmpty(deviceClass) && deviceClass.ToLower().Equals("keyboard")) + { + Keyboard kb = new Keyboard(); + kb.Description = deviceDesc; + + // Register the keyboard: + API.RawInputDeviceInfo info = new API.RawInputDeviceInfo(); + uint devInfoSize = API.RawInputDeviceInfoSize; + API.GetRawInputDeviceInfo(ridl[i].Device, API.RawInputDeviceInfoEnum.DEVICEINFO, + info, ref devInfoSize); + + kb.NumberOfLeds = info.Device.Keyboard.NumberOfIndicators; + kb.NumberOfFunctionKeys = info.Device.Keyboard.NumberOfFunctionKeys; + kb.NumberOfKeys = info.Device.Keyboard.NumberOfKeysTotal; + kb.DeviceID = (info.Device.Keyboard.Type << 32) + info.Device.Keyboard.SubType; + + if (!keyboards.Contains(kb)) + { + this.RegisterKeyboardDevice(kb); + keyboards.Add(kb); + } + } + } + } + } + + #endregion + + #region internal void RegisterKeyboardDevice(Keyboard kb) + + internal void RegisterKeyboardDevice(Keyboard kb) + { API.RawInputDevice[] rid = new API.RawInputDevice[1]; // Keyboard is 1/6 (page/id). See http://www.microsoft.com/whdc/device/input/HID_HWID.mspx rid[0] = new API.RawInputDevice(); rid[0].UsagePage = 1; rid[0].Usage = 6; - rid[0].Flags = API.RawInputDeviceFlags.INPUTSINK; - rid[0].Target = windowHandle; if (!API.RegisterRawInputDevices(rid, 1, API.RawInputDeviceSize)) @@ -190,22 +251,67 @@ namespace OpenTK.Platform.Windows rid[0].ToString()) ); } - - InitKeyMap(); + else + { + Debug.Print("Registered keyboard {0}", kb.ToString()); + } } #endregion - #region --- IKeyboard members --- + #region internal bool ProcessKeyboardEvent(API.RawInput rin) - public bool this[Input.Keys k] + /// + /// Processes raw input events. + /// + /// + /// + internal bool ProcessKeyboardEvent(API.RawInput rin) { - get { return keys[(int)k]; } - internal set + //Keyboard key = keyboards[0]; + //rin.Header.Device; + switch (rin.Header.Type) { - Debug.Print("OpenTK key {0} {1}.", k, value ? "pressed" : "released"); - keys[(int)k] = value; + case API.RawInputDeviceType.KEYBOARD: + bool pressed = + rin.Data.Keyboard.Message == API.Constants.WM_KEYDOWN || + rin.Data.Keyboard.Message == API.Constants.WM_SYSKEYDOWN; + + // Generic control, shift, alt keys may be sent instead of left/right. + // It seems you have to explicitly register left/right events. + switch (rin.Data.Keyboard.VKey) + { + case API.VirtualKeys.SHIFT: + keyboards[0][Input.Keys.LeftShift] = keyboards[0][Input.Keys.RightShift] = pressed; + return false; + + case API.VirtualKeys.CONTROL: + keyboards[0][Input.Keys.LeftControl] = keyboards[0][Input.Keys.RightControl] = pressed; + return false; + + case API.VirtualKeys.MENU: + keyboards[0][Input.Keys.LeftAlt] = keyboards[0][Input.Keys.RightAlt] = pressed; + return false; + + default: + if (!WinRawKeyboard.KeyMap.ContainsKey(rin.Data.Keyboard.VKey)) + { + Debug.Print("Virtual key {0} not mapped.", rin.Data.Keyboard.VKey); + OpenTK.OpenGL.GL.ClearColor(1.0f, 0.3f, 0.3f, 0.0f); + } + else + { + keyboards[0][WinRawKeyboard.KeyMap[rin.Data.Keyboard.VKey]] = pressed; + OpenTK.OpenGL.GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f); + } + break; + } + break; + + default: + throw new ApplicationException("Windows raw keyboard driver received invalid data."); } + return false; } #endregion @@ -223,5 +329,14 @@ namespace OpenTK.Platform.Windows } #endregion + + #region --- IKeyboardDriver Members --- + + public IList Keyboards + { + get { return keyboards; } + } + + #endregion } } diff --git a/Source/OpenTK/Platform/X11/X11GLControl.cs b/Source/OpenTK/Platform/X11/X11GLControl.cs index 9e8dc498..7d7b1c5d 100644 --- a/Source/OpenTK/Platform/X11/X11GLControl.cs +++ b/Source/OpenTK/Platform/X11/X11GLControl.cs @@ -20,8 +20,8 @@ namespace OpenTK.Platform.X11 X11GLContext glContext; private bool quit; - private bool disposed; + private bool fullscreen; #region --- Contructors --- @@ -136,19 +136,7 @@ namespace OpenTK.Platform.X11 this.Create(sender, e); } - #region public bool Quit - - public bool Quit - { - get { return quit; } - set - { - throw new NotImplementedException(); - quit = value; - } - } - - #endregion + #region public bool IsIdle public bool IsIdle { @@ -158,11 +146,15 @@ namespace OpenTK.Platform.X11 } } + #endregion + + #region public bool Fullscreen + public bool Fullscreen { get { - throw new Exception("The method or operation is not implemented."); + return fullscreen; } set { @@ -170,7 +162,11 @@ namespace OpenTK.Platform.X11 } } - public OpenTK.Platform.IGLContext Context + #endregion + + #region public IGLContext Context + + public IGLContext Context { get { @@ -178,10 +174,7 @@ namespace OpenTK.Platform.X11 } } - public void ProcessEvents() - { - throw new Exception("The method or operation is not implemented."); - } + #endregion #endregion @@ -198,7 +191,7 @@ namespace OpenTK.Platform.X11 if (!disposed) { // Clean unmanaged resources: - + // Nothing if (manuallyCalled) { diff --git a/Source/OpenTK/Platform/X11/X11GLNative.cs b/Source/OpenTK/Platform/X11/X11GLNative.cs index 104372c4..642e3f49 100644 --- a/Source/OpenTK/Platform/X11/X11GLNative.cs +++ b/Source/OpenTK/Platform/X11/X11GLNative.cs @@ -26,6 +26,8 @@ namespace OpenTK.Platform.X11 private IntPtr window; private DisplayMode mode = new DisplayMode(); + + private bool created; //private X11Keyboard key; @@ -73,7 +75,18 @@ namespace OpenTK.Platform.X11 mode.Buffers = 2; Trace.WriteLine(String.Format("Display mode: {0}", mode)); - + + this.CreateWindow(mode); + } + + #endregion + + #region --- INativeWindow Members --- + + #region public void CreateWindow(DisplayMode mode) + + public void CreateWindow(DisplayMode mode) + { windowInfo.Display = display = API.OpenDisplay(null); // null == default display if (display == IntPtr.Zero) { @@ -101,7 +114,7 @@ namespace OpenTK.Platform.X11 wnd_attributes.background_pixel = 0; wnd_attributes.border_pixel = 0; wnd_attributes.colormap = glContext.XColormap; - //API.CreateColormap(display, rootWindow, glxVisualInfo.visual, 0/*AllocNone*/); + //API.CreateColormap(display, rootWindow, glxVisualInfo.visual, 0/*AllocNone*/); wnd_attributes.event_mask = EventMask.StructureNotifyMask | EventMask.ExposureMask | @@ -134,7 +147,7 @@ namespace OpenTK.Platform.X11 } Trace.WriteLine("done! (id: " + window + ")"); - + // Set the window hints /* SizeHints hints = new SizeHints(); @@ -157,6 +170,8 @@ namespace OpenTK.Platform.X11 */ //glContext.ContainingWindow = windowInfo.Window; + + glContext.windowInfo.Window = window; glContext.CreateContext(null, true); @@ -172,7 +187,20 @@ namespace OpenTK.Platform.X11 #endregion - #region --- INativeWindow Members --- + #region public void Exit() + + public void Exit() + { + /*Event e = new Event(); + X11Api.SendEvent( + display, + window, + false, + 0,*/ + //quit = true; + } + + #endregion #region public void ProcessEvents() @@ -270,11 +298,14 @@ namespace OpenTK.Platform.X11 #endregion - #region public Keyboard Key + #region public bool Created - public Input.IKeyboard Key + /// + /// Returns true if a render window/context exists. + /// + public bool Created { - get { throw new NotImplementedException(); } + get { return created; } } #endregion @@ -285,19 +316,6 @@ namespace OpenTK.Platform.X11 public bool Quit { get { return quit; } - set - { - if (value) - { - /*Event e = new Event(); - X11Api.SendEvent( - display, - window, - false, - 0,*/ - //quit = true; - } - } } #endregion @@ -336,6 +354,18 @@ namespace OpenTK.Platform.X11 #endregion + #region public IntPtr Handle + + /// + /// Gets the current window handle. + /// + public IntPtr Handle + { + get { return this.window; } + } + + #endregion + #endregion #region --- IResizable Members --- diff --git a/Source/OpenTK/Properties/AssemblyInfo.cs b/Source/OpenTK/Properties/AssemblyInfo.cs index 75db52aa..af176828 100644 --- a/Source/OpenTK/Properties/AssemblyInfo.cs +++ b/Source/OpenTK/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Runtime.InteropServices; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("0.3.9.4")] -[assembly: AssemblyFileVersion("0.3.9.4")] +[assembly: AssemblyVersion("0.3.9.5")] +[assembly: AssemblyFileVersion("0.3.9.5")]