]> O.S.I.I.S - jp/crow.git/commitdiff
test texture surface backend with sdl and xcb TestXCBandSDL
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Sat, 26 Aug 2017 02:57:51 +0000 (04:57 +0200)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Sat, 26 Aug 2017 02:57:51 +0000 (04:57 +0200)
17 files changed:
Crow.csproj
Crow.dll.config
Tests/BasicTests.cs
Tests/CrowWindow.cs
Tests/CrowWindow2.cs [new file with mode: 0644]
Tests/CrowWindow3.cs [new file with mode: 0644]
Tests/InterfaceControler.cs
Tests/Tests.csproj
Tests/sdl2.cs [new file with mode: 0644]
Tests/test-sdl2 (copier).cs [new file with mode: 0644]
Tests/test-sdl2.cs [new file with mode: 0644]
Tests/test_xcb.cs [new file with mode: 0644]
Tests/xcb.cs [new file with mode: 0644]
src/GraphicObjects/GraphicObject.cs
src/Interface.cs
src/Mono.Cairo/ImageSurface.cs
src/Mono.Cairo/Surface.cs

index 29bcd8e0462f46307a31407f86fdf50fd1611a80..949dbd8442eb884b0d5e51378cdc32795c37a9f5 100644 (file)
@@ -25,6 +25,7 @@
     <AssemblyOriginatorKeyFile>crow.key</AssemblyOriginatorKeyFile>
     <ProductVersion>8.0.30703</ProductVersion>
     <SchemaVersion>2.0</SchemaVersion>
+    <ReleaseVersion>0.5</ReleaseVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
index ef7562ac47aa7b4d9008d121bdc494f83e312639..43b2ed22bd00583f01a983f1239de1274dfc952b 100644 (file)
@@ -1,13 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <configuration>
-  <dllmap os="!windows,osx" dll="libgio-2.0-0.dll" target="libgio-2.0.so.0"/>
-  <dllmap os="!windows,osx" dll="libglib-2.0-0.dll" target="libglib-2.0.so.0"/>
-  <dllmap os="!windows,osx" dll="libgobject-2.0-0.dll" target="libgobject-2.0.so.0"/>
-  <dllmap os="!windows,osx" dll="libgdk-3-0.dll" target="libgdk-3.so.0"/>
-  <dllmap os="!windows,osx" dll="libgdk_pixbuf-2.0-0.dll" target="libgdk_pixbuf-2.0.so.0"/>
   <dllmap os="!windows,osx" dll="rsvg-2" target="librsvg-2.so.2"/>
-
-  
+  <dllmap os="!windows,osx" dll="libcairo-2.dll" target="/usr/local/lib/libcairo.so.2"/>
   <dllmap os="windows" dll="rsvg-2" target="librsvg-2-2.dll"/>
   
   <dllmap os="osx" dll="libgio-2.0-0.dll" target="libgio-2.0.0.dylib"/>
index 9340fe8810af2af9786ec1ffae71039dd06e68b5..a7b03cc6884644ac44e88e0e6e8b554e06b1ded3 100644 (file)
@@ -30,16 +30,27 @@ using System.Collections.Generic;
 using System.Linq;
 using System.IO;
 using System.Reflection;
+using System.Runtime.InteropServices;
 using System.Text;
 using System.Diagnostics;
+using Crow.SDL2;
+
+using Native;
+
+using XCBConnection = System.IntPtr;
+using XCBSetup = System.IntPtr;
+using XCBScreen = System.IntPtr;
+using XCBWindow = System.UInt32;
+using XCBColorMap = System.UInt32;
+using XCBVisualId = System.UInt32;
 
 
 namespace Tests
 {
-       class BasicTests : CrowWindow
+       class BasicTests : CrowWindow3
        {
                public BasicTests ()
-                       : base(800, 600,"test: press <F3> to toogle test files")
+                       //: base(800, 600,"test: press <F3> to toogle test files")
                {
                }
 
@@ -140,8 +151,8 @@ namespace Tests
                        this.KeyDown += KeyboardKeyDown1;
 
                        //testFiles = new string [] { @"Interfaces/Unsorted/testFileDialog.crow" };
-                       //testFiles = new string [] { @"Interfaces/Divers/colorPicker.crow" };
-                       testFiles = new string [] { @"Interfaces/Divers/welcome.crow" };
+                       testFiles = new string [] { @"Interfaces/Divers/colorPicker.crow" };
+                       //testFiles = new string [] { @"Interfaces/Divers/welcome.crow" };
                        testFiles = testFiles.Concat (Directory.GetFiles (@"Interfaces/GraphicObject", "*.crow")).ToArray ();
                        testFiles = testFiles.Concat (Directory.GetFiles (@"Interfaces/Container", "*.crow")).ToArray ();
                        testFiles = testFiles.Concat (Directory.GetFiles (@"Interfaces/Group", "*.crow")).ToArray ();
@@ -180,7 +191,7 @@ namespace Tests
                                return;
                        }else if (e.Key == OpenTK.Input.Key.F7) {
                                GraphicObject w = Load ("Interfaces/Divers/perfMeasures.crow");
-                               w.DataSource = this.ifaceControl[0];
+                               w.DataSource = this;
                                return;
                        } else if (e.Key == OpenTK.Input.Key.F2)
                                idx--;
@@ -190,7 +201,7 @@ namespace Tests
                                return;
 
                        try {
-                               ClearInterface ();
+                               CrowInterface.ClearInterface ();
 
                                if (idx == testFiles.Length)
                                        idx = 0;
index 2934af23c83a7f208a482d711d88ddfca70ad55c..82ba6a06a0990f1216ba8cd95dd2d7e9e8cdaba0 100644 (file)
@@ -74,6 +74,9 @@ namespace Crow
                }
 
                #if MEASURE_TIME
+               public List<PerformanceMeasure> PerfMeasures {
+                       get { return ifaceControl[0]?.PerfMeasures; }
+               }
                public PerformanceMeasure glDrawMeasure = new PerformanceMeasure("OpenGL Draw", 10);
 
                public int fpsMin = int.MaxValue;
diff --git a/Tests/CrowWindow2.cs b/Tests/CrowWindow2.cs
new file mode 100644 (file)
index 0000000..b28224b
--- /dev/null
@@ -0,0 +1,435 @@
+//
+// CrowWindow.cs
+//
+// Author:
+//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+using OpenTK;
+using OpenTK.Graphics.OpenGL;
+using System.Collections.Generic;
+using OpenTK.Platform;
+using Crow.SDL2;
+
+namespace Crow
+{
+       public class CrowWindow2 : GameWindow, IValueChange
+    {
+               #region IValueChange implementation
+               public event EventHandler<ValueChangeEventArgs> ValueChanged;
+               public virtual void NotifyValueChanged(string MemberName, object _value)
+               {
+                       if (ValueChanged != null)
+                               ValueChanged.Invoke(this, new ValueChangeEventArgs(MemberName, _value));
+               }
+               #endregion
+
+               #region FPS
+               int frameCpt = 0;
+               int _fps = 0;
+               public int fps {
+                       get { return _fps; }
+                       set {
+                               if (_fps == value)
+                                       return;
+
+                               _fps = value;
+                               #if MEASURE_TIME
+                               if (_fps > fpsMax) {
+                                       fpsMax = _fps;
+                                       ValueChanged.Raise(this, new ValueChangeEventArgs ("fpsMax", fpsMax));
+                               } else if (_fps < fpsMin) {
+                                       fpsMin = _fps;
+                                       ValueChanged.Raise(this, new ValueChangeEventArgs ("fpsMin", fpsMin));
+                               }
+                               #endif
+                               if (frameCpt % 3 == 0) {
+                                       ValueChanged.Raise (this, new ValueChangeEventArgs ("fps", _fps));
+                                       #if MEASURE_TIME
+                                       foreach (PerformanceMeasure m in PerfMeasures)
+                                               m.NotifyChanges ();
+                                       #endif
+                               }
+                       }
+               }
+
+               #if MEASURE_TIME
+               public List<PerformanceMeasure> PerfMeasures;
+               public PerformanceMeasure glDrawMeasure = new PerformanceMeasure("OpenGL Draw", 10);
+
+               public int fpsMin = int.MaxValue;
+               public int fpsMax = 0;
+
+               void resetFps ()
+               {
+                       fpsMin = int.MaxValue;
+                       fpsMax = 0;
+                       _fps = 0;
+               }
+               #endif
+               #endregion
+
+               #region ctor
+               public CrowWindow2(int _width = 800, int _height = 600, string _title="Crow",
+                       int colors = 32, int depth = 24, int stencil = 0, int samples = 1,
+                       int major=3, int minor=3)
+                       : this(_width, _height, new OpenTK.Graphics.GraphicsMode(colors, depth, stencil, samples),
+                               _title,GameWindowFlags.Default,DisplayDevice.Default, major, minor,OpenTK.Graphics.GraphicsContextFlags.Default)
+               {
+               }
+               public CrowWindow2 (int width, int height, OpenTK.Graphics.GraphicsMode mode, string title, GameWindowFlags options, DisplayDevice device, int major, int minor, OpenTK.Graphics.GraphicsContextFlags flags)
+                       : base(width,height,mode,title,options,device,major,minor,flags)
+               {
+               }
+               #endregion
+
+               IntPtr hCairoGLCtx;
+               Cairo.GLXDevice dev;
+               Cairo.GLSurface surf;
+
+               public Interface CrowInterface;
+
+               protected Matrix4 projection;
+               protected Shader shader;
+               public int texID;
+               public vaoMesh quad;
+               public bool mouseIsInInterface = false;
+
+               void initCrow() {                       
+                       CrowInterface = new Interface ();
+                       CrowInterface.MouseCursorChanged += CrowInterface_MouseCursorChanged;
+
+                       #if MEASURE_TIME
+                       PerfMeasures = new List<PerformanceMeasure> (
+                               new PerformanceMeasure[] {
+                                       CrowInterface.updateMeasure,
+                                       CrowInterface.layoutingMeasure,
+                                       CrowInterface.clippingMeasure,
+                                       CrowInterface.drawingMeasure,
+                                       glDrawMeasure
+                               }
+                       );
+                       #endif
+
+//                     Thread t = new Thread (interfaceThread);
+//                     t.IsBackground = true;
+//                     t.Start ();
+               }
+
+               void initCairo(){
+                       SysWMInfo sdlInfo;
+                       IntPtr hWnd = this.WindowInfo.Handle; 
+                       SDL.GL.SetAttribute (ContextAttribute.SHARE_WITH_CURRENT_CONTEXT, 1);
+                       SDL.GL.SetAttribute (ContextAttribute.CONTEXT_MAJOR_VERSION, 3);
+                       SDL.GL.SetAttribute (ContextAttribute.CONTEXT_MAJOR_VERSION, 0);
+                       int test;
+                       SDL.GL.GetAttribute (ContextAttribute.SHARE_WITH_CURRENT_CONTEXT, out test);
+                       SDL.GetWindowWMInfo (hWnd, out sdlInfo);
+
+                       hCairoGLCtx = SDL.GL.CreateContext (hWnd);
+
+
+                       dev = new Cairo.GLXDevice (sdlInfo.Info.X11.Display, hCairoGLCtx);
+               }
+
+//             void interfaceThread()
+//             {
+//                     while (CrowInterface.ClientRectangle.Size.Width == 0)
+//                             Thread.Sleep (5);
+//
+//                     while (true) {
+//                             CrowInterface.Update ();
+//                             Thread.Sleep (1);
+//                     }
+//             }
+
+               #region graphic context
+               public virtual void initGL(){
+                       #if DEBUG
+                       Console.WriteLine("\n\n*************************************");
+                       Console.WriteLine("GL version: " + GL.GetString (StringName.Version));
+                       Console.WriteLine("GL vendor: " + GL.GetString (StringName.Vendor));
+                       Console.WriteLine("GLSL version: " + GL.GetString (StringName.ShadingLanguageVersion));
+                       Console.WriteLine("*************************************\n");
+                       #endif
+
+                       shader = new Shader ();
+                       shader.Enable ();
+
+                       GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+                       projection = OpenTK.Matrix4.CreateOrthographicOffCenter (-0.5f, 0.5f, -0.5f, 0.5f, 1, -1);
+                       quad = new Crow.vaoMesh (0, 0, 0, 1, 1, 1, -1);
+
+                       createContext ();
+               }
+               /// <summary>Create the texture for the interface redering</summary>
+               public virtual void createContext()
+               {
+                       if (GL.IsTexture (texID))
+                               GL.DeleteTexture (texID);
+                       GL.GenTextures (1, out texID);
+                       GL.ActiveTexture (TextureUnit.Texture0);
+                       GL.BindTexture (TextureTarget.Texture2D, texID);
+                       GL.TexImage2D (TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba,
+                               CrowInterface.ClientRectangle.Width, CrowInterface.ClientRectangle.Height, 0,
+                               OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
+                       GL.TexParameter (TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
+                       GL.TexParameter (TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
+
+                       surf = new Cairo.GLSurface (dev, Cairo.Content.ColorAlpha, (uint)texID,
+                               CrowInterface.ClientRectangle.Width, CrowInterface.ClientRectangle.Height);
+
+                       SDL.GL.MakeCurrent(this.WindowInfo.Handle, hCairoGLCtx);
+                       using (Cairo.Context gr = new Cairo.Context (surf)) {
+                               gr.Rectangle (150, 100, 200, 100);
+                               gr.SetSourceRGBA (1.0, 0.0, 0.0,0.5);
+                               gr.Fill ();
+                               gr.Rectangle (200, 150, 200, 100);
+                               gr.SetSourceRGBA (0.0, 1.0, 0.0,0.5);
+                               gr.Fill ();
+                       }
+                       surf.Flush ();
+                       surf.SwapBuffers ();
+                       surf.WriteToPng ("/mnt/data/test.png");
+                       this.MakeCurrent ();
+                       CrowInterface.bmp = surf;
+                       //GL.BindTexture (TextureTarget.Texture2D, 0);
+               }
+
+               void openGLDraw(){
+                       //save GL states
+                       bool blend, depthTest, cullFace;
+                       GL.GetBoolean (GetPName.Blend, out blend);
+                       GL.GetBoolean (GetPName.DepthTest, out depthTest);
+                       GL.GetBoolean (GetPName.CullFace, out cullFace);
+                       GL.Enable (EnableCap.Blend);
+                       GL.Disable (EnableCap.DepthTest);
+                       GL.Disable (EnableCap.CullFace);
+                       GL.Viewport (0, 0, CrowInterface.ClientRectangle.Width, CrowInterface.ClientRectangle.Height);
+
+                       #if MEASURE_TIME
+                       glDrawMeasure.StartCycle();
+                       #endif
+
+                       shader.Enable ();
+                       shader.SetMVP (projection);
+
+                       GL.ActiveTexture (TextureUnit.Texture0);
+                       GL.BindTexture (TextureTarget.Texture2D, texID);
+//                     if (Monitor.TryEnter(CrowInterface.RenderMutex)) {
+//                             if (CrowInterface.IsDirty) {
+//                                     byte[] data = null;
+//                                     if (CrowInterface.dirtyBmp != null)
+//                                             data = (CrowInterface.dirtyBmp as Cairo.ImageSurface).Data;
+//                                     GL.TexSubImage2D (TextureTarget.Texture2D, 0,
+//                                             CrowInterface.DirtyRect.Left, CrowInterface.DirtyRect.Top,
+//                                             CrowInterface.DirtyRect.Width, CrowInterface.DirtyRect.Height,
+//                                             OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data);
+//                                     CrowInterface.IsDirty = false;
+//                             }
+//                             Monitor.Exit (CrowInterface.RenderMutex);
+//                     }
+//
+                       quad.Render (BeginMode.TriangleStrip);
+                       GL.BindTexture(TextureTarget.Texture2D, 0);
+
+                       #if MEASURE_TIME
+                       glDrawMeasure.StopCycle();
+                       #endif
+                       //restore GL states
+                       if (!blend)
+                               GL.Disable (EnableCap.Blend);
+                       if (depthTest)
+                               GL.Enable (EnableCap.DepthTest);
+                       if (cullFace)
+                               GL.Enable (EnableCap.CullFace);
+               }
+               #endregion
+
+               public void Quit (object sender, EventArgs e)
+               {
+                       dev.Dispose ();
+                       SDL.GL.MakeCurrent (this.WindowInfo.Handle, IntPtr.Zero);
+                       SDL.GL.DeleteContext (hCairoGLCtx);
+                       this.MakeCurrent ();
+
+                       this.Exit ();
+               }
+
+               void CrowInterface_MouseCursorChanged (object sender, MouseCursorChangedEventArgs e)
+               {
+                       this.Cursor = new MouseCursor(
+                               (int)e.NewCursor.Xhot,
+                               (int)e.NewCursor.Yhot,
+                               (int)e.NewCursor.Width,
+                               (int)e.NewCursor.Height,
+                               e.NewCursor.data);
+               }
+
+               #region Events are raised only if mouse isn't in a graphic object
+               public event EventHandler<OpenTK.Input.MouseWheelEventArgs> MouseWheelChanged;
+               public event EventHandler<OpenTK.Input.MouseButtonEventArgs> MouseButtonUp;
+               public event EventHandler<OpenTK.Input.MouseButtonEventArgs> MouseButtonDown;
+               public event EventHandler<OpenTK.Input.MouseButtonEventArgs> MouseClick;
+               public event EventHandler<OpenTK.Input.MouseMoveEventArgs> MouseMove;
+               public event EventHandler<OpenTK.Input.KeyboardKeyEventArgs> KeyboardKeyDown;
+               public event EventHandler<OpenTK.Input.KeyboardKeyEventArgs> KeyboardKeyUp;
+               #endregion
+
+
+               public GraphicObject AddWidget (GraphicObject g){
+                       CrowInterface.AddWidget (g);
+                       return g;
+               }
+               public void DeleteWidget (GraphicObject g){
+                       CrowInterface.DeleteWidget (g);
+               }
+               public GraphicObject Load (string path){                        
+                       return CrowInterface.LoadInterface (path);
+               }
+               public GraphicObject FindByName (string nameToFind){
+                       return CrowInterface.FindByName (nameToFind);
+               }
+
+               /// <summary>Override this method for your OpenGL rendering calls</summary>
+               public virtual void OnRender(FrameEventArgs e)
+               {
+               }
+               /// <summary>Override this method to customize clear method between frames</summary>
+               public virtual void GLClear()
+               {
+                       GL.Clear (ClearBufferMask.ColorBufferBit|ClearBufferMask.DepthBufferBit);
+               }
+
+               #region Game win overrides
+               protected override void OnLoad(EventArgs e)
+               {
+                       base.OnLoad(e);
+
+                       this.KeyPress += new EventHandler<OpenTK.KeyPressEventArgs>(OpenTKGameWindow_KeyPress);
+                       Keyboard.KeyDown += new EventHandler<OpenTK.Input.KeyboardKeyEventArgs>(Keyboard_KeyDown);
+                       Keyboard.KeyUp += new EventHandler<OpenTK.Input.KeyboardKeyEventArgs>(Keyboard_KeyUp);
+                       Mouse.WheelChanged += new EventHandler<OpenTK.Input.MouseWheelEventArgs>(GL_Mouse_WheelChanged);
+                       Mouse.ButtonDown += new EventHandler<OpenTK.Input.MouseButtonEventArgs>(GL_Mouse_ButtonDown);
+                       Mouse.ButtonUp += new EventHandler<OpenTK.Input.MouseButtonEventArgs>(GL_Mouse_ButtonUp);
+                       Mouse.Move += new EventHandler<OpenTK.Input.MouseMoveEventArgs>(GL_Mouse_Move);
+
+                       initCairo ();
+                       initCrow ();
+                       initGL ();
+               }
+               protected override void OnUpdateFrame(FrameEventArgs e)
+               {
+                       base.OnUpdateFrame(e);
+                       fps = (int)RenderFrequency;
+
+                       #if MEASURE_TIME
+                       if (frameCpt > 500) {
+                               resetFps ();
+                               frameCpt = 0;
+//                             #if DEBUG
+//                             GC.Collect();
+//                             GC.WaitForPendingFinalizers();
+//                             NotifyValueChanged("memory", GC.GetTotalMemory (false).ToString());
+//                             #endif
+                       }
+                       #endif
+
+                       frameCpt++;
+
+                       SDL.GL.MakeCurrent (this.WindowInfo.Handle, hCairoGLCtx);
+                       CrowInterface.Update ();
+                       surf.Flush ();
+                       surf.SwapBuffers ();
+                       surf.WriteToPng ("/mnt/data/test1.png");
+                       this.MakeCurrent ();
+               }
+               protected override void OnRenderFrame(FrameEventArgs e)
+               {
+                       GLClear ();
+
+                       base.OnRenderFrame(e);
+
+                       OnRender (e);
+                       openGLDraw ();
+
+                       SwapBuffers ();
+               }
+               protected override void OnResize(EventArgs e)
+               {
+                       base.OnResize (e);
+
+                       lock (CrowInterface.UpdateMutex) {
+                               CrowInterface.ClientRectangle = this.ClientRectangle;
+                               createContext ();
+                               CrowInterface.ProcessResize ();
+                       }
+               }
+               #endregion
+
+               #region Mouse and Keyboard Handling
+               void update_mouseButtonStates(ref MouseState e, OpenTK.Input.MouseState otk_e){
+                       for (int i = 0; i < MouseState.MaxButtons; i++) {
+                               if (otk_e.IsButtonDown ((OpenTK.Input.MouseButton)i))
+                                       e.EnableBit (i);
+                       }
+               }
+               protected virtual void GL_Mouse_Move(object sender, OpenTK.Input.MouseMoveEventArgs otk_e)
+        {
+                       if (!CrowInterface.ProcessMouseMove (otk_e.X, otk_e.Y))
+                               MouseMove.Raise (sender, otk_e);
+        }
+               protected virtual void GL_Mouse_ButtonUp(object sender, OpenTK.Input.MouseButtonEventArgs otk_e)
+        {
+                       if (!CrowInterface.ProcessMouseButtonUp ((int)otk_e.Button))
+                               MouseButtonUp.Raise (sender, otk_e);
+        }
+               protected virtual void GL_Mouse_ButtonDown(object sender, OpenTK.Input.MouseButtonEventArgs otk_e)
+               {
+                       if (!CrowInterface.ProcessMouseButtonDown ((int)otk_e.Button))
+                               MouseButtonDown.Raise (sender, otk_e);
+        }
+               protected virtual void GL_Mouse_WheelChanged(object sender, OpenTK.Input.MouseWheelEventArgs otk_e)
+        {
+                       if (!CrowInterface.ProcessMouseWheelChanged (otk_e.DeltaPrecise))
+                               MouseWheelChanged.Raise (sender, otk_e);
+        }
+               protected virtual void Keyboard_KeyDown(object sender, OpenTK.Input.KeyboardKeyEventArgs otk_e)
+               {                       
+                       if (!CrowInterface.ProcessKeyDown((int)otk_e.Key))
+                               KeyboardKeyDown.Raise (this, otk_e);
+        }
+               protected virtual void Keyboard_KeyUp(object sender, OpenTK.Input.KeyboardKeyEventArgs otk_e)
+               {
+                       if (!CrowInterface.ProcessKeyUp((int)otk_e.Key))
+                               KeyboardKeyUp.Raise (this, otk_e);
+               }
+               protected virtual void OpenTKGameWindow_KeyPress (object sender, OpenTK.KeyPressEventArgs e)
+               {
+                       CrowInterface.ProcessKeyPress (e.KeyChar);                              
+                       //TODO:create keyboardkeypress evt
+               }
+        #endregion
+    }
+}
diff --git a/Tests/CrowWindow3.cs b/Tests/CrowWindow3.cs
new file mode 100644 (file)
index 0000000..fce2840
--- /dev/null
@@ -0,0 +1,428 @@
+//
+// CrowWindow.cs
+//
+// Author:
+//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+using OpenTK;
+using OpenTK.Graphics.OpenGL;
+using System.Collections.Generic;
+using OpenTK.Platform;
+using Crow.SDL2;
+
+namespace Crow
+{
+       public class CrowWindow3 : GameWindow, IValueChange
+    {
+               #region IValueChange implementation
+               public event EventHandler<ValueChangeEventArgs> ValueChanged;
+               public virtual void NotifyValueChanged(string MemberName, object _value)
+               {
+                       if (ValueChanged != null)
+                               ValueChanged.Invoke(this, new ValueChangeEventArgs(MemberName, _value));
+               }
+               #endregion
+
+               #region FPS
+               int frameCpt = 0;
+               int _fps = 0;
+               public int fps {
+                       get { return _fps; }
+                       set {
+                               if (_fps == value)
+                                       return;
+
+                               _fps = value;
+                               #if MEASURE_TIME
+                               if (_fps > fpsMax) {
+                                       fpsMax = _fps;
+                                       ValueChanged.Raise(this, new ValueChangeEventArgs ("fpsMax", fpsMax));
+                               } else if (_fps < fpsMin) {
+                                       fpsMin = _fps;
+                                       ValueChanged.Raise(this, new ValueChangeEventArgs ("fpsMin", fpsMin));
+                               }
+                               #endif
+                               if (frameCpt % 3 == 0) {
+                                       ValueChanged.Raise (this, new ValueChangeEventArgs ("fps", _fps));
+                                       #if MEASURE_TIME
+                                       foreach (PerformanceMeasure m in PerfMeasures)
+                                               m.NotifyChanges ();
+                                       #endif
+                               }
+                       }
+               }
+
+               #if MEASURE_TIME
+               public List<PerformanceMeasure> PerfMeasures;
+               public PerformanceMeasure glDrawMeasure = new PerformanceMeasure("OpenGL Draw", 10);
+
+               public int fpsMin = int.MaxValue;
+               public int fpsMax = 0;
+
+               void resetFps ()
+               {
+                       fpsMin = int.MaxValue;
+                       fpsMax = 0;
+                       _fps = 0;
+               }
+               #endif
+               #endregion
+
+               #region ctor
+               public CrowWindow3(int _width = 800, int _height = 600, string _title="Crow",
+                       int colors = 32, int depth = 24, int stencil = 0, int samples = 1,
+                       int major=3, int minor=0)
+                       : this(_width, _height, new OpenTK.Graphics.GraphicsMode(colors, depth, stencil, samples),
+                               _title,GameWindowFlags.Default,DisplayDevice.Default, major, minor,OpenTK.Graphics.GraphicsContextFlags.Default)
+               {
+               }
+               public CrowWindow3 (int width, int height, OpenTK.Graphics.GraphicsMode mode, string title, GameWindowFlags options, DisplayDevice device, int major, int minor, OpenTK.Graphics.GraphicsContextFlags flags)
+                       : base(width,height,mode,title,options,device,major,minor,flags)
+               {
+               }
+               #endregion
+
+               IntPtr hCairoGLCtx;
+               Cairo.GLXDevice dev;
+               Cairo.GLSurface surf;
+
+               public Interface CrowInterface;
+
+               protected Matrix4 projection;
+               public int texID;
+               public bool mouseIsInInterface = false;
+
+               void initCrow() {                       
+                       CrowInterface = new Interface ();
+                       CrowInterface.MouseCursorChanged += CrowInterface_MouseCursorChanged;
+
+                       #if MEASURE_TIME
+                       PerfMeasures = new List<PerformanceMeasure> (
+                               new PerformanceMeasure[] {
+                                       CrowInterface.updateMeasure,
+                                       CrowInterface.layoutingMeasure,
+                                       CrowInterface.clippingMeasure,
+                                       CrowInterface.drawingMeasure,
+                                       glDrawMeasure
+                               }
+                       );
+                       #endif
+
+//                     Thread t = new Thread (interfaceThread);
+//                     t.IsBackground = true;
+//                     t.Start ();
+               }
+
+               void initCairo(){
+                       SysWMInfo sdlInfo;
+                       IntPtr hWnd = this.WindowInfo.Handle; 
+                       SDL.GL.SetAttribute (ContextAttribute.SHARE_WITH_CURRENT_CONTEXT, 1);
+                       int test;
+                       SDL.GL.GetAttribute (ContextAttribute.SHARE_WITH_CURRENT_CONTEXT, out test);
+                       SDL.GetWindowWMInfo (hWnd, out sdlInfo);
+
+                       hCairoGLCtx = SDL.GL.CreateContext (hWnd);
+
+
+                       dev = new Cairo.GLXDevice (sdlInfo.Info.X11.Display, hCairoGLCtx);
+               }
+
+//             void interfaceThread()
+//             {
+//                     while (CrowInterface.ClientRectangle.Size.Width == 0)
+//                             Thread.Sleep (5);
+//
+//                     while (true) {
+//                             CrowInterface.Update ();
+//                             Thread.Sleep (1);
+//                     }
+//             }
+
+               #region graphic context
+               public virtual void initGL(){
+                       #if DEBUG
+                       Console.WriteLine("\n\n*************************************");
+                       Console.WriteLine("GL version: " + GL.GetString (StringName.Version));
+                       Console.WriteLine("GL vendor: " + GL.GetString (StringName.Vendor));
+                       Console.WriteLine("GLSL version: " + GL.GetString (StringName.ShadingLanguageVersion));
+                       Console.WriteLine("*************************************\n");
+                       #endif
+
+                       GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+                       projection = OpenTK.Matrix4.CreateOrthographicOffCenter (-0.5f, 0.5f, -0.5f, 0.5f, 1, -1);
+
+                       createContext ();
+               }
+               /// <summary>Create the texture for the interface redering</summary>
+               public virtual void createContext()
+               {
+                       if (GL.IsTexture (texID))
+                               GL.DeleteTexture (texID);
+                       GL.GenTextures (1, out texID);
+                       GL.ActiveTexture (TextureUnit.Texture0);
+                       GL.BindTexture (TextureTarget.Texture2D, texID);
+                       GL.TexImage2D (TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba,
+                               CrowInterface.ClientRectangle.Width, CrowInterface.ClientRectangle.Height, 0,
+                               OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
+                       GL.TexParameter (TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
+                       GL.TexParameter (TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
+
+                       surf = new Cairo.GLSurface (dev, Cairo.Content.ColorAlpha, (uint)texID,
+                               CrowInterface.ClientRectangle.Width, CrowInterface.ClientRectangle.Height);
+
+                       CrowInterface.bmp = surf;
+                       GL.BindTexture (TextureTarget.Texture2D, 0);
+               }
+
+               void openGLDraw(){
+                       //save GL states
+                       bool blend, depthTest, cullFace;
+                       GL.GetBoolean (GetPName.Blend, out blend);
+                       GL.GetBoolean (GetPName.DepthTest, out depthTest);
+                       GL.GetBoolean (GetPName.CullFace, out cullFace);
+                       GL.Enable (EnableCap.Texture2D);
+                       GL.Enable (EnableCap.Blend);
+                       GL.BlendFunc (BlendingFactorSrc.One, BlendingFactorDest.OneMinusSrcAlpha);
+                       GL.Disable (EnableCap.DepthTest);
+                       GL.Disable (EnableCap.CullFace);
+                       GL.Viewport (0, 0, CrowInterface.ClientRectangle.Width, CrowInterface.ClientRectangle.Height);
+
+                       #if MEASURE_TIME
+                       glDrawMeasure.StartCycle();
+                       #endif
+
+
+                       GL.ActiveTexture (TextureUnit.Texture0);
+                       GL.BindTexture (TextureTarget.Texture2D, texID);
+//                     if (Monitor.TryEnter(CrowInterface.RenderMutex)) {
+//                             if (CrowInterface.IsDirty) {
+//                                     byte[] data = null;
+//                                     if (CrowInterface.dirtyBmp != null)
+//                                             data = (CrowInterface.dirtyBmp as Cairo.ImageSurface).Data;
+//                                     GL.TexSubImage2D (TextureTarget.Texture2D, 0,
+//                                             CrowInterface.DirtyRect.Left, CrowInterface.DirtyRect.Top,
+//                                             CrowInterface.DirtyRect.Width, CrowInterface.DirtyRect.Height,
+//                                             OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data);
+//                                     CrowInterface.IsDirty = false;
+//                             }
+//                             Monitor.Exit (CrowInterface.RenderMutex);
+//                     }
+//
+
+                       Matrix4 proj = Matrix4.CreateOrthographicOffCenter (-1f, 1f, -1f, 1f, 1.0f, -1.0f);
+                       GL.MatrixMode(MatrixMode.Projection);
+                       GL.LoadMatrix (ref proj);
+                       GL.MatrixMode(MatrixMode.Modelview);
+                       GL.LoadIdentity();
+
+                       GL.BindTexture (TextureTarget.Texture2D, texID);
+
+                       GL.Begin(PrimitiveType.Quads);
+                       GL.TexCoord2(0, 1);     GL.Vertex2(-1, -1);
+                       GL.TexCoord2(0, 0);     GL.Vertex2(-1, 1);
+                       GL.TexCoord2(1, 0);     GL.Vertex2(1, 1);
+                       GL.TexCoord2(1, 1);     GL.Vertex2(1, -1);
+                       GL.End();
+
+                       GL.BindTexture(TextureTarget.Texture2D, 0);
+
+                       #if MEASURE_TIME
+                       glDrawMeasure.StopCycle();
+                       #endif
+                       //restore GL states
+                       if (!blend)
+                               GL.Disable (EnableCap.Blend);
+                       if (depthTest)
+                               GL.Enable (EnableCap.DepthTest);
+                       if (cullFace)
+                               GL.Enable (EnableCap.CullFace);
+               }
+               #endregion
+
+               public void Quit (object sender, EventArgs e)
+               {
+                       dev.Dispose ();
+                       SDL.GL.MakeCurrent (this.WindowInfo.Handle, IntPtr.Zero);
+                       SDL.GL.DeleteContext (hCairoGLCtx);
+                       this.MakeCurrent ();
+
+                       this.Exit ();
+               }
+
+               void CrowInterface_MouseCursorChanged (object sender, MouseCursorChangedEventArgs e)
+               {
+                       this.Cursor = new MouseCursor(
+                               (int)e.NewCursor.Xhot,
+                               (int)e.NewCursor.Yhot,
+                               (int)e.NewCursor.Width,
+                               (int)e.NewCursor.Height,
+                               e.NewCursor.data);
+               }
+
+               #region Events are raised only if mouse isn't in a graphic object
+               public event EventHandler<OpenTK.Input.MouseWheelEventArgs> MouseWheelChanged;
+               public event EventHandler<OpenTK.Input.MouseButtonEventArgs> MouseButtonUp;
+               public event EventHandler<OpenTK.Input.MouseButtonEventArgs> MouseButtonDown;
+               public event EventHandler<OpenTK.Input.MouseButtonEventArgs> MouseClick;
+               public event EventHandler<OpenTK.Input.MouseMoveEventArgs> MouseMove;
+               public event EventHandler<OpenTK.Input.KeyboardKeyEventArgs> KeyboardKeyDown;
+               public event EventHandler<OpenTK.Input.KeyboardKeyEventArgs> KeyboardKeyUp;
+               #endregion
+
+
+               public GraphicObject AddWidget (GraphicObject g){
+                       CrowInterface.AddWidget (g);
+                       return g;
+               }
+               public void DeleteWidget (GraphicObject g){
+                       CrowInterface.DeleteWidget (g);
+               }
+               public GraphicObject Load (string path){                        
+                       return CrowInterface.LoadInterface (path);
+               }
+               public GraphicObject FindByName (string nameToFind){
+                       return CrowInterface.FindByName (nameToFind);
+               }
+
+               /// <summary>Override this method for your OpenGL rendering calls</summary>
+               public virtual void OnRender(FrameEventArgs e)
+               {
+               }
+               /// <summary>Override this method to customize clear method between frames</summary>
+               public virtual void GLClear()
+               {
+                       GL.Clear (ClearBufferMask.ColorBufferBit|ClearBufferMask.DepthBufferBit);
+               }
+
+               #region Game win overrides
+               protected override void OnLoad(EventArgs e)
+               {
+                       base.OnLoad(e);
+
+                       this.KeyPress += new EventHandler<OpenTK.KeyPressEventArgs>(OpenTKGameWindow_KeyPress);
+                       Keyboard.KeyDown += new EventHandler<OpenTK.Input.KeyboardKeyEventArgs>(Keyboard_KeyDown);
+                       Keyboard.KeyUp += new EventHandler<OpenTK.Input.KeyboardKeyEventArgs>(Keyboard_KeyUp);
+                       Mouse.WheelChanged += new EventHandler<OpenTK.Input.MouseWheelEventArgs>(GL_Mouse_WheelChanged);
+                       Mouse.ButtonDown += new EventHandler<OpenTK.Input.MouseButtonEventArgs>(GL_Mouse_ButtonDown);
+                       Mouse.ButtonUp += new EventHandler<OpenTK.Input.MouseButtonEventArgs>(GL_Mouse_ButtonUp);
+                       Mouse.Move += new EventHandler<OpenTK.Input.MouseMoveEventArgs>(GL_Mouse_Move);
+
+                       initCairo ();
+                       initCrow ();
+                       initGL ();
+               }
+               protected override void OnUpdateFrame(FrameEventArgs e)
+               {
+                       base.OnUpdateFrame(e);
+                       fps = (int)RenderFrequency;
+
+                       #if MEASURE_TIME
+                       if (frameCpt > 500) {
+                               resetFps ();
+                               frameCpt = 0;
+//                             #if DEBUG
+//                             GC.Collect();
+//                             GC.WaitForPendingFinalizers();
+//                             NotifyValueChanged("memory", GC.GetTotalMemory (false).ToString());
+//                             #endif
+                       }
+                       #endif
+
+                       frameCpt++;
+
+                       SDL.GL.MakeCurrent (this.WindowInfo.Handle, hCairoGLCtx);
+                       CrowInterface.Update ();
+                       surf.Flush ();
+                       surf.SwapBuffers ();
+                       this.MakeCurrent ();
+               }
+               protected override void OnRenderFrame(FrameEventArgs e)
+               {
+                       GLClear ();
+
+                       base.OnRenderFrame(e);
+
+                       OnRender (e);
+                       openGLDraw ();
+
+                       SwapBuffers ();
+               }
+               protected override void OnResize(EventArgs e)
+               {
+                       base.OnResize (e);
+
+                       lock (CrowInterface.UpdateMutex) {
+                               CrowInterface.ClientRectangle = this.ClientRectangle;
+                               createContext ();
+                               CrowInterface.ProcessResize ();
+                       }
+               }
+               #endregion
+
+               #region Mouse and Keyboard Handling
+               void update_mouseButtonStates(ref MouseState e, OpenTK.Input.MouseState otk_e){
+                       for (int i = 0; i < MouseState.MaxButtons; i++) {
+                               if (otk_e.IsButtonDown ((OpenTK.Input.MouseButton)i))
+                                       e.EnableBit (i);
+                       }
+               }
+               protected virtual void GL_Mouse_Move(object sender, OpenTK.Input.MouseMoveEventArgs otk_e)
+        {
+                       if (!CrowInterface.ProcessMouseMove (otk_e.X, otk_e.Y))
+                               MouseMove.Raise (sender, otk_e);
+        }
+               protected virtual void GL_Mouse_ButtonUp(object sender, OpenTK.Input.MouseButtonEventArgs otk_e)
+        {
+                       if (!CrowInterface.ProcessMouseButtonUp ((int)otk_e.Button))
+                               MouseButtonUp.Raise (sender, otk_e);
+        }
+               protected virtual void GL_Mouse_ButtonDown(object sender, OpenTK.Input.MouseButtonEventArgs otk_e)
+               {
+                       if (!CrowInterface.ProcessMouseButtonDown ((int)otk_e.Button))
+                               MouseButtonDown.Raise (sender, otk_e);
+        }
+               protected virtual void GL_Mouse_WheelChanged(object sender, OpenTK.Input.MouseWheelEventArgs otk_e)
+        {
+                       if (!CrowInterface.ProcessMouseWheelChanged (otk_e.DeltaPrecise))
+                               MouseWheelChanged.Raise (sender, otk_e);
+        }
+               protected virtual void Keyboard_KeyDown(object sender, OpenTK.Input.KeyboardKeyEventArgs otk_e)
+               {                       
+                       if (!CrowInterface.ProcessKeyDown((int)otk_e.Key))
+                               KeyboardKeyDown.Raise (this, otk_e);
+        }
+               protected virtual void Keyboard_KeyUp(object sender, OpenTK.Input.KeyboardKeyEventArgs otk_e)
+               {
+                       if (!CrowInterface.ProcessKeyUp((int)otk_e.Key))
+                               KeyboardKeyUp.Raise (this, otk_e);
+               }
+               protected virtual void OpenTKGameWindow_KeyPress (object sender, OpenTK.KeyPressEventArgs e)
+               {
+                       CrowInterface.ProcessKeyPress (e.KeyChar);                              
+                       //TODO:create keyboardkeypress evt
+               }
+        #endregion
+    }
+}
index 4d988c10b63b51c88c25370b10bc1db0dac99177..af0fe3d94984a861d4b3c80f7c44d99eabdc1de8 100644 (file)
@@ -52,7 +52,8 @@ namespace Crow
                public override void initGL(){
                        quad = new Crow.vaoMesh (0, 0, 0, 1, 1, 1, -1);
                        //ifaceModelMat = Matrix4.CreateRotationX(MathHelper.PiOver2) * Matrix4.CreateTranslation(Vector3.UnitY);
-                       CrowInterface.ProcessResize(iRect);
+                       //Cairo.Device dev = new Cairo.Device();
+                       CrowInterface.ProcessResize();
                        createContext ();
                        //CrowInterface.ProcessResize (iRect);
                }
@@ -162,14 +163,14 @@ namespace Crow
 
                        while (true) {
                                CrowInterface.Update ();
-                               //Thread.Sleep (1);
+                               Thread.Sleep (1);
                        }
                }
 
                #region Mouse And Keyboard handling
                public virtual void ProcessResize(Rectangle newSize){
                        iRect = newSize;
-                       CrowInterface.ProcessResize(newSize);
+                       CrowInterface.ProcessResize();
                        createContext ();
                        GL.Viewport (0, 0, newSize.Width, newSize.Height);//TODO:find a better place for this
                }
@@ -214,12 +215,16 @@ namespace Crow
                        GL.ActiveTexture (TextureUnit.Texture0);
                        GL.BindTexture(TextureTarget.Texture2D, texID);
 
+                       byte[] data = null;
+                       if (CrowInterface.bmp != null)
+                               data = (CrowInterface.bmp as Cairo.ImageSurface).Data;
+
                        GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba,
                                iRect.Width, iRect.Height, 0,
-                               OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, CrowInterface.bmp);
+                               OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data);
 
-                       GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
-                       GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
+                       GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
+                       GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
 
                        GL.BindTexture(TextureTarget.Texture2D, 0);
                }
@@ -234,10 +239,13 @@ namespace Crow
                        GL.BindTexture (TextureTarget.Texture2D, texID);
                        if (Monitor.TryEnter(CrowInterface.RenderMutex)) {
                                if (CrowInterface.IsDirty) {
+                                       byte[] data = null;
+                                       if (CrowInterface.dirtyBmp != null)
+                                               data = (CrowInterface.dirtyBmp as Cairo.ImageSurface).Data;
                                        GL.TexSubImage2D (TextureTarget.Texture2D, 0,
                                                CrowInterface.DirtyRect.Left, CrowInterface.DirtyRect.Top,
                                                CrowInterface.DirtyRect.Width, CrowInterface.DirtyRect.Height,
-                                               OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, CrowInterface.dirtyBmp);
+                                               OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data);
                                        CrowInterface.IsDirty = false;
                                }
                                Monitor.Exit (CrowInterface.RenderMutex);
index 2adcdb16b88ff81baa386c3c2c99f0d7894d731f..16d63764687260f731444c0b75addc36b4779f63 100644 (file)
@@ -8,7 +8,7 @@
     <OutputType>Exe</OutputType>
     <RootNamespace>Tests</RootNamespace>
     <AssemblyName>Tests</AssemblyName>
-    <StartupObject>Tests.Showcase</StartupObject>
+    <StartupObject>Tests.BasicTests</StartupObject>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <ReleaseVersion>0.5</ReleaseVersion>
     <Optimize>false</Optimize>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <ConsolePause>false</ConsolePause>
     <DefineConstants>DEBUG;TRACE;MEASURE_TIME</DefineConstants>
     <IntermediateOutputPath>$(SolutionDir)build\obj\$(Configuration)</IntermediateOutputPath>
-    <OutputPath>$(SolutionDir)build\$(Configuration)</OutputPath>
+    <OutputPath>$(SolutionDir)build\Debug</OutputPath>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <Externalconsole>true</Externalconsole>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <DebugType>none</DebugType>
@@ -37,7 +38,8 @@
     <WarningLevel>0</WarningLevel>
     <ConsolePause>false</ConsolePause>
     <IntermediateOutputPath>$(SolutionDir)build\obj\$(Configuration)</IntermediateOutputPath>
-    <OutputPath>$(SolutionDir)build\$(Configuration)</OutputPath>
+    <OutputPath>$(SolutionDir)build\Release</OutputPath>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Compile Include="OpenGL\Extensions.cs" />
     <Compile Include="InterfaceControler.cs" />
     <Compile Include="Showcase.cs" />
+    <Compile Include="test-sdl2.cs" />
+    <Compile Include="test-sdl2 %28copier%29.cs" />
+    <Compile Include="sdl2.cs" />
+    <Compile Include="CrowWindow3.cs" />
+    <Compile Include="xcb.cs" />
+    <Compile Include="test_xcb.cs" />
+    <Compile Include="CrowWindow2.cs" />
   </ItemGroup>
   <ItemGroup>
     <None Include="image\u.svg">
diff --git a/Tests/sdl2.cs b/Tests/sdl2.cs
new file mode 100644 (file)
index 0000000..9237be9
--- /dev/null
@@ -0,0 +1,1752 @@
+//
+// The Open Toolkit Library License
+//
+// Copyright (c) 2006 - 2013 Stefanos Apostolopoulos for the Open Toolkit library.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+// the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Diagnostics;
+using System.Security;
+using System.Runtime.InteropServices;
+
+#pragma warning disable 0169
+
+namespace Crow.SDL2
+{
+       using Surface = IntPtr;
+       using Cursor = IntPtr;
+
+       internal partial class SDL
+       {
+               #if ANDROID
+               const string lib = "libSDL2.so";
+               #elif IPHONE
+               const string lib = "__Internal";
+               #else
+               private const string lib = "SDL2.dll";
+               #endif
+
+               public readonly static object Sync = new object();
+               private static Nullable<Version> version;
+               public static Version Version
+               {
+                       get
+                       {
+                               try
+                               {
+                                       if (!version.HasValue)
+                                       {
+                                               version = GetVersion();
+                                       }
+                                       return version.Value;
+                               }
+                               catch
+                               {
+                                       // nom nom
+                                       Debug.Print("[SDL2] Failed to retrieve version");
+                                       return new Version();
+                               }
+                       }
+               }
+
+               private static string IntPtrToString(IntPtr ptr)
+               {
+                       return Marshal.PtrToStringAnsi(ptr);
+                       //int strlen = 0;
+                       //while (Marshal.ReadByte(ptr) != 0)
+                       //    strlen++;
+               }
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_CreateColorCursor", ExactSpelling = true)]
+               public static extern Cursor CreateColorCursor(Surface surface, int hot_x, int hot_y);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_FreeCursor", ExactSpelling = true)]
+               public static extern void FreeCursor(Cursor cursor);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetDefaultCursor", ExactSpelling = true)]
+               public static extern IntPtr GetDefaultCursor();
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_SetCursor", ExactSpelling = true)]
+               public static extern void SetCursor(Cursor cursor);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_AddEventWatch", ExactSpelling = true)]
+               public static extern void AddEventWatch(EventFilter filter, IntPtr userdata);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_AddEventWatch", ExactSpelling = true)]
+               public static extern void AddEventWatch(IntPtr filter, IntPtr userdata);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_CreateRGBSurfaceFrom", ExactSpelling = true)]
+               public static extern IntPtr CreateRGBSurfaceFrom(IntPtr pixels,
+                       int width, int height, int depth, int pitch,
+                       uint Rmask, uint Gmask, uint Bmask, uint Amask);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_CreateWindow", ExactSpelling = true)]
+               public static extern IntPtr CreateWindow(string title, int x, int y, int w, int h, WindowFlags flags);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_CreateWindowFrom", ExactSpelling = true)]
+               public static extern IntPtr CreateWindowFrom(IntPtr data);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_DelEventWatch", ExactSpelling = true)]
+               public static extern void DelEventWatch(EventFilter filter, IntPtr userdata);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_DelEventWatch", ExactSpelling = true)]
+               public static extern void DelEventWatch(IntPtr filter, IntPtr userdata);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_DestroyWindow", ExactSpelling = true)]
+               public static extern void DestroyWindow(IntPtr window);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_FreeSurface", ExactSpelling = true)]
+               public static extern void FreeSurface(IntPtr surface);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport (lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_free", ExactSpelling = true)]
+               public static extern void Free(IntPtr memblock);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GameControllerEventState", ExactSpelling = true)]
+               public static extern EventState GameControllerEventState(EventState state);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GameControllerGetAxis", ExactSpelling = true)]
+               public static extern short GameControllerGetAxis(IntPtr gamecontroller, GameControllerAxis axis);
+
+               /// <summary>
+               /// Gets the SDL joystick layer binding for the specified game controller axis
+               /// </summary>
+               /// <param name="gamecontroller">Pointer to a game controller instance returned by <c>GameControllerOpen</c>.</param>
+               /// <param name="axis">A value from the <c>GameControllerAxis</c> enumeration</param>
+               /// <returns>A GameControllerButtonBind instance describing the specified binding</returns>
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GameControllerGetBindForAxis", ExactSpelling = true)]
+               public static extern GameControllerButtonBind GameControllerGetBindForAxis(IntPtr gamecontroller, GameControllerAxis axis);
+
+               /// <summary>
+               /// Gets the SDL joystick layer binding for the specified game controller button
+               /// </summary>
+               /// <param name="gamecontroller">Pointer to a game controller instance returned by <c>GameControllerOpen</c>.</param>
+               /// <param name="button">A value from the <c>GameControllerButton</c> enumeration</param>
+               /// <returns>A GameControllerButtonBind instance describing the specified binding</returns>
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GameControllerGetBindForButton", ExactSpelling = true)]
+               public static extern GameControllerButtonBind GameControllerGetBindForButton(
+                       IntPtr gamecontroller, GameControllerButton button);
+
+               /// <summary>
+               /// Gets the current state of a button on a game controller.
+               /// </summary>
+               /// <param name="gamecontroller">A game controller handle previously opened with <c>GameControllerOpen</c>.</param>
+               /// <param name="button">A zero-based <c>GameControllerButton</c> value.</param>
+               /// <returns><c>true</c> if the specified button is pressed; <c>false</c> otherwise.</returns>
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GameControllerGetButton", ExactSpelling = true)]
+               public static extern bool GameControllerGetButton(IntPtr gamecontroller, GameControllerButton button);
+
+               /// <summary>
+               /// Retrieve the joystick handle that corresponds to the specified game controller.
+               /// </summary>
+               /// <param name="gamecontroller">A game controller handle previously opened with <c>GameControllerOpen</c>.</param>
+               /// <returns>A handle to a joystick, or IntPtr.Zero in case of error. The pointer is owned by the callee. Use <c>SDL.GetError</c> to retrieve error information</returns>
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GameControllerGetJoystick", ExactSpelling = true)]
+               public static extern IntPtr GameControllerGetJoystick(IntPtr gamecontroller);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetCurrentDisplayMode", ExactSpelling = true)]
+               public static extern int GetCurrentDisplayMode(int displayIndex, out DisplayMode mode);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GameControllerName", ExactSpelling = true)]
+               private static extern IntPtr GameControllerNameInternal(IntPtr gamecontroller);
+
+               /// <summary>
+               /// Return the name for an openend game controller instance.
+               /// </summary>
+               /// <returns>The name of the game controller name.</returns>
+               /// <param name="gamecontroller">Pointer to a game controller instance returned by <c>GameControllerOpen</c>.</param>
+               public static string GameControllerName(IntPtr gamecontroller)
+               {
+                       unsafe
+                       {
+                               return new string((sbyte*)GameControllerNameInternal(gamecontroller));
+                       }
+               }
+
+               /// <summary>
+               /// Opens a game controller for use.
+               /// </summary>
+               /// <param name="joystick_index">
+               /// A zero-based index for the game controller.
+               /// This index is the value which will identify this controller in future controller events.
+               /// </param>
+               /// <returns>A handle to the game controller instance, or IntPtr.Zero in case of error.</returns>
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GameControllerOpen", ExactSpelling = true)]
+               public static extern IntPtr GameControllerOpen(int joystick_index);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetDisplayBounds", ExactSpelling = true)]
+               public static extern int GetDisplayBounds(int displayIndex, out Rect rect);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetDisplayMode", ExactSpelling = true)]
+               public static extern int GetDisplayMode(int displayIndex, int modeIndex, out DisplayMode mode);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetError", ExactSpelling = true)]
+               private static extern IntPtr GetErrorInternal();
+               public static string GetError()
+               {
+                       return IntPtrToString(GetErrorInternal());
+               }
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetModState", ExactSpelling = true)]
+               public static extern Keymod GetModState();
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetMouseState", ExactSpelling = true)]
+               public static extern ButtonFlags GetMouseState(out int hx, out int hy);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetGlobalMouseState", ExactSpelling = true)]
+               public static extern ButtonFlags GetGlobalMouseState(out int hx, out int hy);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetNumDisplayModes", ExactSpelling = true)]
+               public static extern int GetNumDisplayModes(int displayIndex);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetNumVideoDisplays", ExactSpelling = true)]
+               public static extern int GetNumVideoDisplays();
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetScancodeFromKey", ExactSpelling = true)]
+               public static extern Scancode GetScancodeFromKey(Keycode key);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetVersion", ExactSpelling = true)]
+               public static extern void GetVersion(out Version version);
+               public static Version GetVersion()
+               {
+                       Version v;
+                       GetVersion(out v);
+                       return v;
+               }
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetWindowID", ExactSpelling = true)]
+               public static extern uint GetWindowID(IntPtr window);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetWindowPosition", ExactSpelling = true)]
+               public static extern void GetWindowPosition(IntPtr window, out int x, out int y);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetWindowSize", ExactSpelling = true)]
+               public static extern void GetWindowSize(IntPtr window, out int w, out int h);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetWindowTitle", ExactSpelling = true)]
+               private static extern IntPtr GetWindowTitlePrivate(IntPtr window);
+               public static string GetWindowTitle(IntPtr window)
+               {
+                       return Marshal.PtrToStringAnsi(GetWindowTitlePrivate(window));
+               }
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_HideWindow", ExactSpelling = true)]
+               public static extern void HideWindow(IntPtr window);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_DisableScreenSaver", ExactSpelling = true)]
+               public static extern void DisableScreenSaver();
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_Init", ExactSpelling = true)]
+               public static extern int Init(SystemFlags flags);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_InitSubSystem", ExactSpelling = true)]
+               public static extern int InitSubSystem(SystemFlags flags);
+
+               /// <summary>
+               /// Determines if the specified joystick is supported by the GameController API.
+               /// </summary>
+               /// <returns><c>true</c> if joystick_index is supported by the GameController API; <c>false</c> otherwise.</returns>
+               /// <param name="joystick_index">The index of the joystick to check.</param>
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_IsGameController", ExactSpelling = true)]
+               public static extern bool IsGameController(int joystick_index);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickClose", ExactSpelling = true)]
+               public static extern void JoystickClose(IntPtr joystick);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickEventState", ExactSpelling = true)]
+               public static extern EventState JoystickEventState(EventState enabled);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickGetAxis", ExactSpelling = true)]
+               public static extern short JoystickGetAxis(IntPtr joystick, int axis);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickGetButton", ExactSpelling = true)]
+               public static extern byte JoystickGetButton(IntPtr joystick, int button);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickGetGUID", ExactSpelling = true)]
+               public static extern JoystickGuid JoystickGetGUID(IntPtr joystick);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickInstanceID", ExactSpelling = true)]
+               public static extern int JoystickInstanceID(IntPtr joystick);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickName", ExactSpelling = true)]
+               private static extern IntPtr JoystickNameInternal(IntPtr joystick);
+               public static string JoystickName(IntPtr joystick)
+               {
+                       unsafe
+                       {
+                               return new string((sbyte*)JoystickNameInternal(joystick));
+                       }
+               }
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickNumAxes", ExactSpelling = true)]
+               public static extern int JoystickNumAxes(IntPtr joystick);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickNumBalls", ExactSpelling = true)]
+               public static extern int JoystickNumBalls(IntPtr joystick);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickNumButtons", ExactSpelling = true)]
+               public static extern int JoystickNumButtons(IntPtr joystick);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickNumHats", ExactSpelling = true)]
+               public static extern int JoystickNumHats(IntPtr joystick);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickOpen", ExactSpelling = true)]
+               public static extern IntPtr JoystickOpen(int device_index);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickUpdate", ExactSpelling = true)]
+               public static extern void JoystickUpdate();
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_MaximizeWindow", ExactSpelling = true)]
+               public static extern void MaximizeWindow(IntPtr window);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_MinimizeWindow", ExactSpelling = true)]
+               public static extern void MinimizeWindow(IntPtr window);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_NumJoysticks", ExactSpelling = true)]
+               public static extern int NumJoysticks();
+
+               public static int PeepEvents(ref Event e, EventAction action, EventType min, EventType max)
+               {
+                       unsafe
+                       {
+                               fixed (Event* pe = &e)
+                               {
+                                       return PeepEvents(pe, 1, action, min, max);
+                               }
+                       }
+               }
+
+               public static int PeepEvents(Event[] e, int count, EventAction action, EventType min, EventType max)
+               {
+                       if (e == null)
+                       {
+                               throw new ArgumentNullException();
+                       }
+                       if (count <= 0 || count > e.Length)
+                       {
+                               throw new ArgumentOutOfRangeException();
+                       }
+
+                       unsafe
+                       {
+                               fixed (Event *pe = e)
+                               {
+                                       return PeepEvents(pe, count, action, min, max);
+                               }
+                       }
+               }
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_PeepEvents", ExactSpelling = true)]
+               private unsafe static extern int PeepEvents(Event* e, int count, EventAction action, EventType min, EventType max);
+
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_PixelFormatEnumToMasks", ExactSpelling = true)]
+               public static extern bool PixelFormatEnumToMasks(uint format, out int bpp,
+                       out uint rmask, out uint gmask, out uint bmask, out uint amask);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_PollEvent", ExactSpelling = true)]
+               public static extern int PollEvent(out Event e);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_PumpEvents", ExactSpelling = true)]
+               public static extern void PumpEvents();
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_PushEvent", ExactSpelling = true)]
+               public static extern int PushEvent(ref Event @event);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_RaiseWindow", ExactSpelling = true)]
+               public static extern void RaiseWindow(IntPtr window);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_RestoreWindow", ExactSpelling = true)]
+               public static extern void RestoreWindow(IntPtr window);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_SetRelativeMouseMode", ExactSpelling = true)]
+               public static extern int SetRelativeMouseMode(bool enabled);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_SetWindowBordered", ExactSpelling = true)]
+               public static extern void SetWindowBordered(IntPtr window, bool bordered);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_SetWindowFullscreen", ExactSpelling = true)]
+               public static extern int SetWindowFullscreen(IntPtr window, uint flags);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_SetWindowGrab", ExactSpelling = true)]
+               public static extern void SetWindowGrab(IntPtr window, bool grabbed);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_SetWindowIcon", ExactSpelling = true)]
+               public static extern void SetWindowIcon(IntPtr window, IntPtr icon);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_SetWindowPosition", ExactSpelling = true)]
+               public static extern void SetWindowPosition(IntPtr window, int x, int y);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_SetWindowSize", ExactSpelling = true)]
+               public static extern void SetWindowSize(IntPtr window, int x, int y);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_SetWindowTitle", ExactSpelling = true)]
+               public static extern void SetWindowTitle(IntPtr window, string title);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_ShowCursor", ExactSpelling = true)]
+               public static extern int ShowCursor(bool toggle);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_ShowWindow", ExactSpelling = true)]
+               public static extern void ShowWindow(IntPtr window);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_WasInit", ExactSpelling = true)]
+               public static extern bool WasInit(SystemFlags flags);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_WarpMouseInWindow", ExactSpelling = true)]
+               public static extern void WarpMouseInWindow(IntPtr window, int x, int y);
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport (lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_WarpMouseGlobal", ExactSpelling = true)]
+               public static extern void WarpMouseGlobal(int x, int y);
+
+               /// <summary>
+               /// Retrieves driver-dependent window information.
+               /// </summary>
+               /// <param name="window">
+               /// The window about which information is being requested.
+               /// </param>
+               /// <param name="info">
+               /// Returns driver-dependent information about the specified window.
+               /// </param>
+               /// <returns>
+               /// True, if the function is implemented and the version number of the info struct is valid;
+               /// false, otherwise.
+               /// </returns>
+               public static bool GetWindowWMInfo(IntPtr window, out SysWMInfo info)
+               {
+                       info = new SysWMInfo();
+                       info.Version = GetVersion();
+                       return GetWindowWMInfoInternal(window, ref info);
+               }
+
+               [SuppressUnmanagedCodeSecurity]
+               [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetWindowWMInfo", ExactSpelling = true)]
+               private static extern bool GetWindowWMInfoInternal(IntPtr window, ref SysWMInfo info);
+
+               public partial class GL
+               {
+                       [SuppressUnmanagedCodeSecurity]
+                       [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_CreateContext", ExactSpelling = true)]
+                       public static extern IntPtr CreateContext(IntPtr window);
+
+                       [SuppressUnmanagedCodeSecurity]
+                       [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_DeleteContext", ExactSpelling = true)]
+                       public static extern void DeleteContext(IntPtr context);
+
+                       [SuppressUnmanagedCodeSecurity]
+                       [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetAttribute", ExactSpelling = true)]
+                       public static extern int GetAttribute(ContextAttribute attr, out int value);
+
+                       [SuppressUnmanagedCodeSecurity]
+                       [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetCurrentContext", ExactSpelling = true)]
+                       public static extern IntPtr GetCurrentContext();
+
+                       [SuppressUnmanagedCodeSecurity]
+                       [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetDrawableSize", ExactSpelling = true)]
+                       public static extern void GetDrawableSize(IntPtr window, out int w, out int h);
+
+                       [SuppressUnmanagedCodeSecurity]
+                       [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetProcAddress", ExactSpelling = true)]
+                       public static extern IntPtr GetProcAddress(IntPtr proc);
+                       public static IntPtr GetProcAddress(string proc)
+                       {
+                               IntPtr p = Marshal.StringToHGlobalAnsi(proc);
+                               try
+                               {
+                                       return GetProcAddress(p);
+                               }
+                               finally
+                               {
+                                       Marshal.FreeHGlobal(p);
+                               }
+                       }
+
+                       [SuppressUnmanagedCodeSecurity]
+                       [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetSwapInterval", ExactSpelling = true)]
+                       public static extern int GetSwapInterval();
+
+                       [SuppressUnmanagedCodeSecurity]
+                       [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_MakeCurrent", ExactSpelling = true)]
+                       public static extern int MakeCurrent(IntPtr window, IntPtr context);
+
+                       [SuppressUnmanagedCodeSecurity]
+                       [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_SetAttribute", ExactSpelling = true)]
+                       public static extern int SetAttribute(ContextAttribute attr, int value);
+                       public static int SetAttribute(ContextAttribute attr, ContextFlags value)
+                       {
+                               return SetAttribute(attr, (int)value);
+                       }
+                       public static int SetAttribute(ContextAttribute attr, ContextProfileFlags value)
+                       {
+                               return SetAttribute(attr, (int)value);
+                       }
+
+                       [SuppressUnmanagedCodeSecurity]
+                       [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_SetSwapInterval", ExactSpelling = true)]
+                       public static extern int SetSwapInterval(int interval);
+
+                       [SuppressUnmanagedCodeSecurity]
+                       [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_SwapWindow", ExactSpelling = true)]
+                       public static extern void SwapWindow(IntPtr window);
+               }
+       }
+
+       [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+       internal delegate int EventFilter(IntPtr userdata, IntPtr @event);
+
+       internal enum Button : byte
+       {
+               Left = 1,
+               Middle,
+               Right,
+               X1,
+               X2
+       }
+
+       [Flags]
+       internal enum ButtonFlags
+       {
+               Left = 1 << (Button.Left - 1),
+               Middle = 1 << (Button.Middle - 1),
+               Right = 1 << (Button.Right - 1),
+               X1 = 1 << (Button.X1 - 1),
+               X2 = 1 << (Button.X2 - 1),
+       }
+
+       internal enum ContextAttribute
+       {
+               RED_SIZE,
+               GREEN_SIZE,
+               BLUE_SIZE,
+               ALPHA_SIZE,
+               BUFFER_SIZE,
+               DOUBLEBUFFER,
+               DEPTH_SIZE,
+               STENCIL_SIZE,
+               ACCUM_RED_SIZE,
+               ACCUM_GREEN_SIZE,
+               ACCUM_BLUE_SIZE,
+               ACCUM_ALPHA_SIZE,
+               STEREO,
+               MULTISAMPLEBUFFERS,
+               MULTISAMPLESAMPLES,
+               ACCELERATED_VISUAL,
+               RETAINED_BACKING,
+               CONTEXT_MAJOR_VERSION,
+               CONTEXT_MINOR_VERSION,
+               CONTEXT_EGL,
+               CONTEXT_FLAGS,
+               CONTEXT_PROFILE_MASK,
+               SHARE_WITH_CURRENT_CONTEXT
+       }
+
+       [Flags]
+       internal enum ContextFlags
+       {
+               DEBUG = 0x0001,
+               FORWARD_COMPATIBLE = 0x0002,
+               ROBUST_ACCESS = 0x0004,
+               RESET_ISOLATION = 0x0008
+       }
+
+       [Flags]
+       internal enum ContextProfileFlags
+       {
+               CORE = 0x0001,
+               COMPATIBILITY = 0x0002,
+               ES = 0x0004
+       }
+
+       internal enum EventAction
+       {
+               Add,
+               Peek,
+               Get
+       }
+
+       internal enum EventState
+       {
+               Query = -1,
+               Ignore = 0,
+               Enable = 1
+       }
+
+       internal enum EventType
+       {
+               FIRSTEVENT = 0,
+               QUIT = 0x100,
+               WINDOWEVENT = 0x200,
+               SYSWMEVENT,
+               KEYDOWN = 0x300,
+               KEYUP,
+               TEXTEDITING,
+               TEXTINPUT,
+               MOUSEMOTION = 0x400,
+               MOUSEBUTTONDOWN,
+               MOUSEBUTTONUP,
+               MOUSEWHEEL,
+               JOYAXISMOTION = 0x600,
+               JOYBALLMOTION,
+               JOYHATMOTION,
+               JOYBUTTONDOWN,
+               JOYBUTTONUP,
+               JOYDEVICEADDED,
+               JOYDEVICEREMOVED,
+               CONTROLLERAXISMOTION = 0x650,
+               CONTROLLERBUTTONDOWN,
+               CONTROLLERBUTTONUP,
+               CONTROLLERDEVICEADDED,
+               CONTROLLERDEVICEREMOVED,
+               CONTROLLERDEVICEREMAPPED,
+               FINGERDOWN = 0x700,
+               FINGERUP,
+               FINGERMOTION,
+               DOLLARGESTURE = 0x800,
+               DOLLARRECORD,
+               MULTIGESTURE,
+               CLIPBOARDUPDATE = 0x900,
+               DROPFILE = 0x1000,
+               USEREVENT = 0x8000,
+               LASTEVENT = 0xFFFF
+       }
+
+       internal enum GameControllerAxis : byte
+       {
+               Invalid = 0xff,
+               LeftX = 0,
+               LeftY,
+               RightX,
+               RightY,
+               TriggerLeft,
+               TriggerRight,
+               Max
+       }
+
+       internal enum GameControllerButton : byte
+       {
+               INVALID = 0xff,
+               A = 0,
+               B,
+               X,
+               Y,
+               BACK,
+               GUIDE,
+               START,
+               LEFTSTICK,
+               RIGHTSTICK,
+               LEFTSHOULDER,
+               RIGHTSHOULDER,
+               DPAD_UP,
+               DPAD_DOWN,
+               DPAD_LEFT,
+               DPAD_RIGHT,
+               Max
+       }
+
+       internal enum GameControllerBindType : byte
+       {
+               None = 0,
+               Button,
+               Axis,
+               Hat
+       }
+
+       [Flags]
+       internal enum HatPosition : byte
+       {
+               Centered = 0x00,
+               Up = 0x01,
+               Right = 0x02,
+               Down = 0x04,
+               Left = 0x08,
+               RightUp = Right | Up,
+               RightDown = Right | Down,
+               LeftUp = Left | Up,
+               LeftDown = Left | Down
+       }
+
+       internal enum Keycode
+       {
+               UNKNOWN = 0,
+               RETURN = '\r',
+               ESCAPE = 27, // '\033' octal
+               BACKSPACE = '\b',
+               TAB = '\t',
+               SPACE = ' ',
+               EXCLAIM = '!',
+               QUOTEDBL = '"',
+               HASH = '#',
+               PERCENT = '%',
+               DOLLAR = '$',
+               AMPERSAND = '&',
+               QUOTE = '\'',
+               LEFTPAREN = '(',
+               RIGHTPAREN = ')',
+               ASTERISK = '*',
+               PLUS = '+',
+               COMMA = ',',
+               MINUS = '-',
+               PERIOD = '.',
+               SLASH = '/',
+               Num0 = '0',
+               Num1 = '1',
+               Num2 = '2',
+               Num3 = '3',
+               Num4 = '4',
+               Num5 = '5',
+               Num6 = '6',
+               Num7 = '7',
+               Num8 = '8',
+               Num9 = '9',
+               COLON = ':',
+               SEMICOLON = ';',
+               LESS = '<',
+               EQUALS = '=',
+               GREATER = '>',
+               QUESTION = '?',
+               AT = '@',
+               LEFTBRACKET = '[',
+               BACKSLASH = '\\',
+               RIGHTBRACKET = ']',
+               CARET = '^',
+               UNDERSCORE = '_',
+               BACKQUOTE = '`',
+               a = 'a',
+               b = 'b',
+               c = 'c',
+               d = 'd',
+               e = 'e',
+               f = 'f',
+               g = 'g',
+               h = 'h',
+               i = 'i',
+               j = 'j',
+               k = 'k',
+               l = 'l',
+               m = 'm',
+               n = 'n',
+               o = 'o',
+               p = 'p',
+               q = 'q',
+               r = 'r',
+               s = 's',
+               t = 't',
+               u = 'u',
+               v = 'v',
+               w = 'w',
+               x = 'x',
+               y = 'y',
+               z = 'z',
+               CAPSLOCK = (1 << 30) | (int)Scancode.CAPSLOCK,
+               F1 = (1 << 30) | (int)Scancode.F1,
+               F2 = (1 << 30) | (int)Scancode.F2,
+               F3 = (1 << 30) | (int)Scancode.F3,
+               F4 = (1 << 30) | (int)Scancode.F4,
+               F5 = (1 << 30) | (int)Scancode.F5,
+               F6 = (1 << 30) | (int)Scancode.F6,
+               F7 = (1 << 30) | (int)Scancode.F7,
+               F8 = (1 << 30) | (int)Scancode.F8,
+               F9 = (1 << 30) | (int)Scancode.F9,
+               F10 = (1 << 30) | (int)Scancode.F10,
+               F11 = (1 << 30) | (int)Scancode.F11,
+               F12 = (1 << 30) | (int)Scancode.F12,
+               PRINTSCREEN = (1 << 30) | (int)Scancode.PRINTSCREEN,
+               SCROLLLOCK = (1 << 30) | (int)Scancode.SCROLLLOCK,
+               PAUSE = (1 << 30) | (int)Scancode.PAUSE,
+               INSERT = (1 << 30) | (int)Scancode.INSERT,
+               HOME = (1 << 30) | (int)Scancode.HOME,
+               PAGEUP = (1 << 30) | (int)Scancode.PAGEUP,
+               DELETE = 127, // '\177' octal
+               END = (1 << 30) | (int)Scancode.END,
+               PAGEDOWN = (1 << 30) | (int)Scancode.PAGEDOWN,
+               RIGHT = (1 << 30) | (int)Scancode.RIGHT,
+               LEFT = (1 << 30) | (int)Scancode.LEFT,
+               DOWN = (1 << 30) | (int)Scancode.DOWN,
+               UP = (1 << 30) | (int)Scancode.UP,
+               NUMLOCKCLEAR = (1 << 30) | (int)Scancode.NUMLOCKCLEAR,
+               KP_DIVIDE = (1 << 30) | (int)Scancode.KP_DIVIDE,
+               KP_MULTIPLY = (1 << 30) | (int)Scancode.KP_MULTIPLY,
+               KP_MINUS = (1 << 30) | (int)Scancode.KP_MINUS,
+               KP_PLUS = (1 << 30) | (int)Scancode.KP_PLUS,
+               KP_ENTER = (1 << 30) | (int)Scancode.KP_ENTER,
+               KP_1 = (1 << 30) | (int)Scancode.KP_1,
+               KP_2 = (1 << 30) | (int)Scancode.KP_2,
+               KP_3 = (1 << 30) | (int)Scancode.KP_3,
+               KP_4 = (1 << 30) | (int)Scancode.KP_4,
+               KP_5 = (1 << 30) | (int)Scancode.KP_5,
+               KP_6 = (1 << 30) | (int)Scancode.KP_6,
+               KP_7 = (1 << 30) | (int)Scancode.KP_7,
+               KP_8 = (1 << 30) | (int)Scancode.KP_8,
+               KP_9 = (1 << 30) | (int)Scancode.KP_9,
+               KP_0 = (1 << 30) | (int)Scancode.KP_0,
+               KP_PERIOD = (1 << 30) | (int)Scancode.KP_PERIOD,
+               APPLICATION = (1 << 30) | (int)Scancode.APPLICATION,
+               POWER = (1 << 30) | (int)Scancode.POWER,
+               KP_EQUALS = (1 << 30) | (int)Scancode.KP_EQUALS,
+               F13 = (1 << 30) | (int)Scancode.F13,
+               F14 = (1 << 30) | (int)Scancode.F14,
+               F15 = (1 << 30) | (int)Scancode.F15,
+               F16 = (1 << 30) | (int)Scancode.F16,
+               F17 = (1 << 30) | (int)Scancode.F17,
+               F18 = (1 << 30) | (int)Scancode.F18,
+               F19 = (1 << 30) | (int)Scancode.F19,
+               F20 = (1 << 30) | (int)Scancode.F20,
+               F21 = (1 << 30) | (int)Scancode.F21,
+               F22 = (1 << 30) | (int)Scancode.F22,
+               F23 = (1 << 30) | (int)Scancode.F23,
+               F24 = (1 << 30) | (int)Scancode.F24,
+               EXECUTE = (1 << 30) | (int)Scancode.EXECUTE,
+               HELP = (1 << 30) | (int)Scancode.HELP,
+               MENU = (1 << 30) | (int)Scancode.MENU,
+               SELECT = (1 << 30) | (int)Scancode.SELECT,
+               STOP = (1 << 30) | (int)Scancode.STOP,
+               AGAIN = (1 << 30) | (int)Scancode.AGAIN,
+               UNDO = (1 << 30) | (int)Scancode.UNDO,
+               CUT = (1 << 30) | (int)Scancode.CUT,
+               COPY = (1 << 30) | (int)Scancode.COPY,
+               PASTE = (1 << 30) | (int)Scancode.PASTE,
+               FIND = (1 << 30) | (int)Scancode.FIND,
+               MUTE = (1 << 30) | (int)Scancode.MUTE,
+               VOLUMEUP = (1 << 30) | (int)Scancode.VOLUMEUP,
+               VOLUMEDOWN = (1 << 30) | (int)Scancode.VOLUMEDOWN,
+               KP_COMMA = (1 << 30) | (int)Scancode.KP_COMMA,
+               KP_EQUALSAS400 = (1 << 30) | (int)Scancode.KP_EQUALSAS400,
+               ALTERASE = (1 << 30) | (int)Scancode.ALTERASE,
+               SYSREQ = (1 << 30) | (int)Scancode.SYSREQ,
+               CANCEL = (1 << 30) | (int)Scancode.CANCEL,
+               CLEAR = (1 << 30) | (int)Scancode.CLEAR,
+               PRIOR = (1 << 30) | (int)Scancode.PRIOR,
+               RETURN2 = (1 << 30) | (int)Scancode.RETURN2,
+               SEPARATOR = (1 << 30) | (int)Scancode.SEPARATOR,
+               OUT = (1 << 30) | (int)Scancode.OUT,
+               OPER = (1 << 30) | (int)Scancode.OPER,
+               CLEARAGAIN = (1 << 30) | (int)Scancode.CLEARAGAIN,
+               CRSEL = (1 << 30) | (int)Scancode.CRSEL,
+               EXSEL = (1 << 30) | (int)Scancode.EXSEL,
+               KP_00 = (1 << 30) | (int)Scancode.KP_00,
+               KP_000 = (1 << 30) | (int)Scancode.KP_000,
+               THOUSANDSSEPARATOR = (1 << 30) | (int)Scancode.THOUSANDSSEPARATOR,
+               DECIMALSEPARATOR = (1 << 30) | (int)Scancode.DECIMALSEPARATOR,
+               CURRENCYUNIT = (1 << 30) | (int)Scancode.CURRENCYUNIT,
+               CURRENCYSUBUNIT = (1 << 30) | (int)Scancode.CURRENCYSUBUNIT,
+               KP_LEFTPAREN = (1 << 30) | (int)Scancode.KP_LEFTPAREN,
+               KP_RIGHTPAREN = (1 << 30) | (int)Scancode.KP_RIGHTPAREN,
+               KP_LEFTBRACE = (1 << 30) | (int)Scancode.KP_LEFTBRACE,
+               KP_RIGHTBRACE = (1 << 30) | (int)Scancode.KP_RIGHTBRACE,
+               KP_TAB = (1 << 30) | (int)Scancode.KP_TAB,
+               KP_BACKSPACE = (1 << 30) | (int)Scancode.KP_BACKSPACE,
+               KP_A = (1 << 30) | (int)Scancode.KP_A,
+               KP_B = (1 << 30) | (int)Scancode.KP_B,
+               KP_C = (1 << 30) | (int)Scancode.KP_C,
+               KP_D = (1 << 30) | (int)Scancode.KP_D,
+               KP_E = (1 << 30) | (int)Scancode.KP_E,
+               KP_F = (1 << 30) | (int)Scancode.KP_F,
+               KP_XOR = (1 << 30) | (int)Scancode.KP_XOR,
+               KP_POWER = (1 << 30) | (int)Scancode.KP_POWER,
+               KP_PERCENT = (1 << 30) | (int)Scancode.KP_PERCENT,
+               KP_LESS = (1 << 30) | (int)Scancode.KP_LESS,
+               KP_GREATER = (1 << 30) | (int)Scancode.KP_GREATER,
+               KP_AMPERSAND = (1 << 30) | (int)Scancode.KP_AMPERSAND,
+               KP_DBLAMPERSAND = (1 << 30) | (int)Scancode.KP_DBLAMPERSAND,
+               KP_VERTICALBAR = (1 << 30) | (int)Scancode.KP_VERTICALBAR,
+               KP_DBLVERTICALBAR = (1 << 30) | (int)Scancode.KP_DBLVERTICALBAR,
+               KP_COLON = (1 << 30) | (int)Scancode.KP_COLON,
+               KP_HASH = (1 << 30) | (int)Scancode.KP_HASH,
+               KP_SPACE = (1 << 30) | (int)Scancode.KP_SPACE,
+               KP_AT = (1 << 30) | (int)Scancode.KP_AT,
+               KP_EXCLAM = (1 << 30) | (int)Scancode.KP_EXCLAM,
+               KP_MEMSTORE = (1 << 30) | (int)Scancode.KP_MEMSTORE,
+               KP_MEMRECALL = (1 << 30) | (int)Scancode.KP_MEMRECALL,
+               KP_MEMCLEAR = (1 << 30) | (int)Scancode.KP_MEMCLEAR,
+               KP_MEMADD = (1 << 30) | (int)Scancode.KP_MEMADD,
+               KP_MEMSUBTRACT = (1 << 30) | (int)Scancode.KP_MEMSUBTRACT,
+               KP_MEMMULTIPLY = (1 << 30) | (int)Scancode.KP_MEMMULTIPLY,
+               KP_MEMDIVIDE = (1 << 30) | (int)Scancode.KP_MEMDIVIDE,
+               KP_PLUSMINUS = (1 << 30) | (int)Scancode.KP_PLUSMINUS,
+               KP_CLEAR = (1 << 30) | (int)Scancode.KP_CLEAR,
+               KP_CLEARENTRY = (1 << 30) | (int)Scancode.KP_CLEARENTRY,
+               KP_BINARY = (1 << 30) | (int)Scancode.KP_BINARY,
+               KP_OCTAL = (1 << 30) | (int)Scancode.KP_OCTAL,
+               KP_DECIMAL = (1 << 30) | (int)Scancode.KP_DECIMAL,
+               KP_HEXADECIMAL = (1 << 30) | (int)Scancode.KP_HEXADECIMAL,
+               LCTRL = (1 << 30) | (int)Scancode.LCTRL,
+               LSHIFT = (1 << 30) | (int)Scancode.LSHIFT,
+               LALT = (1 << 30) | (int)Scancode.LALT,
+               LGUI = (1 << 30) | (int)Scancode.LGUI,
+               RCTRL = (1 << 30) | (int)Scancode.RCTRL,
+               RSHIFT = (1 << 30) | (int)Scancode.RSHIFT,
+               RALT = (1 << 30) | (int)Scancode.RALT,
+               RGUI = (1 << 30) | (int)Scancode.RGUI,
+               MODE = (1 << 30) | (int)Scancode.MODE,
+               AUDIONEXT = (1 << 30) | (int)Scancode.AUDIONEXT,
+               AUDIOPREV = (1 << 30) | (int)Scancode.AUDIOPREV,
+               AUDIOSTOP = (1 << 30) | (int)Scancode.AUDIOSTOP,
+               AUDIOPLAY = (1 << 30) | (int)Scancode.AUDIOPLAY,
+               AUDIOMUTE = (1 << 30) | (int)Scancode.AUDIOMUTE,
+               MEDIASELECT = (1 << 30) | (int)Scancode.MEDIASELECT,
+               WWW = (1 << 30) | (int)Scancode.WWW,
+               MAIL = (1 << 30) | (int)Scancode.MAIL,
+               CALCULATOR = (1 << 30) | (int)Scancode.CALCULATOR,
+               COMPUTER = (1 << 30) | (int)Scancode.COMPUTER,
+               AC_SEARCH = (1 << 30) | (int)Scancode.AC_SEARCH,
+               AC_HOME = (1 << 30) | (int)Scancode.AC_HOME,
+               AC_BACK = (1 << 30) | (int)Scancode.AC_BACK,
+               AC_FORWARD = (1 << 30) | (int)Scancode.AC_FORWARD,
+               AC_STOP = (1 << 30) | (int)Scancode.AC_STOP,
+               AC_REFRESH = (1 << 30) | (int)Scancode.AC_REFRESH,
+               AC_BOOKMARKS = (1 << 30) | (int)Scancode.AC_BOOKMARKS,
+               BRIGHTNESSDOWN = (1 << 30) | (int)Scancode.BRIGHTNESSDOWN,
+               BRIGHTNESSUP = (1 << 30) | (int)Scancode.BRIGHTNESSUP,
+               DISPLAYSWITCH = (1 << 30) | (int)Scancode.DISPLAYSWITCH,
+               KBDILLUMTOGGLE = (1 << 30) | (int)Scancode.KBDILLUMTOGGLE,
+               KBDILLUMDOWN = (1 << 30) | (int)Scancode.KBDILLUMDOWN,
+               KBDILLUMUP = (1 << 30) | (int)Scancode.KBDILLUMUP,
+               EJECT = (1 << 30) | (int)Scancode.EJECT,
+               SLEEP = (1 << 30) | (int)Scancode.SLEEP
+       }
+
+       [Flags]
+       internal enum Keymod : ushort
+       {
+               NONE = 0x0000,
+               LSHIFT = 0x0001,
+               RSHIFT = 0x0002,
+               LCTRL = 0x0040,
+               RCTRL = 0x0080,
+               LALT = 0x0100,
+               RALT = 0x0200,
+               LGUI = 0x0400,
+               RGUI = 0x0800,
+               NUM = 0x1000,
+               CAPS = 0x2000,
+               MODE = 0x4000,
+               RESERVED = 0x8000,
+               CTRL = (LCTRL | RCTRL),
+               SHIFT = (LSHIFT | RSHIFT),
+               ALT = (LALT | RALT),
+               GUI = (LGUI | RGUI)
+       }
+
+       internal enum Scancode
+       {
+               UNKNOWN = 0,
+               A = 4,
+               B = 5,
+               C = 6,
+               D = 7,
+               E = 8,
+               F = 9,
+               G = 10,
+               H = 11,
+               I = 12,
+               J = 13,
+               K = 14,
+               L = 15,
+               M = 16,
+               N = 17,
+               O = 18,
+               P = 19,
+               Q = 20,
+               R = 21,
+               S = 22,
+               T = 23,
+               U = 24,
+               V = 25,
+               W = 26,
+               X = 27,
+               Y = 28,
+               Z = 29,
+               Num1 = 30,
+               Num2 = 31,
+               Num3 = 32,
+               Num4 = 33,
+               Num5 = 34,
+               Num6 = 35,
+               Num7 = 36,
+               Num8 = 37,
+               Num9 = 38,
+               Num0 = 39,
+               RETURN = 40,
+               ESCAPE = 41,
+               BACKSPACE = 42,
+               TAB = 43,
+               SPACE = 44,
+               MINUS = 45,
+               EQUALS = 46,
+               LEFTBRACKET = 47,
+               RIGHTBRACKET = 48,
+               BACKSLASH = 49,
+               NONUSHASH = 50,
+               SEMICOLON = 51,
+               APOSTROPHE = 52,
+               GRAVE = 53,
+               COMMA = 54,
+               PERIOD = 55,
+               SLASH = 56,
+               CAPSLOCK = 57,
+               F1 = 58,
+               F2 = 59,
+               F3 = 60,
+               F4 = 61,
+               F5 = 62,
+               F6 = 63,
+               F7 = 64,
+               F8 = 65,
+               F9 = 66,
+               F10 = 67,
+               F11 = 68,
+               F12 = 69,
+               PRINTSCREEN = 70,
+               SCROLLLOCK = 71,
+               PAUSE = 72,
+               INSERT = 73,
+               HOME = 74,
+               PAGEUP = 75,
+               DELETE = 76,
+               END = 77,
+               PAGEDOWN = 78,
+               RIGHT = 79,
+               LEFT = 80,
+               DOWN = 81,
+               UP = 82,
+               NUMLOCKCLEAR = 83,
+               KP_DIVIDE = 84,
+               KP_MULTIPLY = 85,
+               KP_MINUS = 86,
+               KP_PLUS = 87,
+               KP_ENTER = 88,
+               KP_1 = 89,
+               KP_2 = 90,
+               KP_3 = 91,
+               KP_4 = 92,
+               KP_5 = 93,
+               KP_6 = 94,
+               KP_7 = 95,
+               KP_8 = 96,
+               KP_9 = 97,
+               KP_0 = 98,
+               KP_PERIOD = 99,
+               NONUSBACKSLASH = 100,
+               APPLICATION = 101,
+               POWER = 102,
+               KP_EQUALS = 103,
+               F13 = 104,
+               F14 = 105,
+               F15 = 106,
+               F16 = 107,
+               F17 = 108,
+               F18 = 109,
+               F19 = 110,
+               F20 = 111,
+               F21 = 112,
+               F22 = 113,
+               F23 = 114,
+               F24 = 115,
+               EXECUTE = 116,
+               HELP = 117,
+               MENU = 118,
+               SELECT = 119,
+               STOP = 120,
+               AGAIN = 121,
+               UNDO = 122,
+               CUT = 123,
+               COPY = 124,
+               PASTE = 125,
+               FIND = 126,
+               MUTE = 127,
+               VOLUMEUP = 128,
+               VOLUMEDOWN = 129,
+               // not sure whether there's a reason to enable these
+               //  LOCKINGCAPSLOCK = 130,
+               //  LOCKINGNUMLOCK = 131,
+               //  LOCKINGSCROLLLOCK = 132,
+               KP_COMMA = 133,
+               KP_EQUALSAS400 = 134,
+               INTERNATIONAL1 = 135,
+               INTERNATIONAL2 = 136,
+               INTERNATIONAL3 = 137,
+               INTERNATIONAL4 = 138,
+               INTERNATIONAL5 = 139,
+               INTERNATIONAL6 = 140,
+               INTERNATIONAL7 = 141,
+               INTERNATIONAL8 = 142,
+               INTERNATIONAL9 = 143,
+               LANG1 = 144,
+               LANG2 = 145,
+               LANG3 = 146,
+               LANG4 = 147,
+               LANG5 = 148,
+               LANG6 = 149,
+               LANG7 = 150,
+               LANG8 = 151,
+               LANG9 = 152,
+               ALTERASE = 153,
+               SYSREQ = 154,
+               CANCEL = 155,
+               CLEAR = 156,
+               PRIOR = 157,
+               RETURN2 = 158,
+               SEPARATOR = 159,
+               OUT = 160,
+               OPER = 161,
+               CLEARAGAIN = 162,
+               CRSEL = 163,
+               EXSEL = 164,
+               KP_00 = 176,
+               KP_000 = 177,
+               THOUSANDSSEPARATOR = 178,
+               DECIMALSEPARATOR = 179,
+               CURRENCYUNIT = 180,
+               CURRENCYSUBUNIT = 181,
+               KP_LEFTPAREN = 182,
+               KP_RIGHTPAREN = 183,
+               KP_LEFTBRACE = 184,
+               KP_RIGHTBRACE = 185,
+               KP_TAB = 186,
+               KP_BACKSPACE = 187,
+               KP_A = 188,
+               KP_B = 189,
+               KP_C = 190,
+               KP_D = 191,
+               KP_E = 192,
+               KP_F = 193,
+               KP_XOR = 194,
+               KP_POWER = 195,
+               KP_PERCENT = 196,
+               KP_LESS = 197,
+               KP_GREATER = 198,
+               KP_AMPERSAND = 199,
+               KP_DBLAMPERSAND = 200,
+               KP_VERTICALBAR = 201,
+               KP_DBLVERTICALBAR = 202,
+               KP_COLON = 203,
+               KP_HASH = 204,
+               KP_SPACE = 205,
+               KP_AT = 206,
+               KP_EXCLAM = 207,
+               KP_MEMSTORE = 208,
+               KP_MEMRECALL = 209,
+               KP_MEMCLEAR = 210,
+               KP_MEMADD = 211,
+               KP_MEMSUBTRACT = 212,
+               KP_MEMMULTIPLY = 213,
+               KP_MEMDIVIDE = 214,
+               KP_PLUSMINUS = 215,
+               KP_CLEAR = 216,
+               KP_CLEARENTRY = 217,
+               KP_BINARY = 218,
+               KP_OCTAL = 219,
+               KP_DECIMAL = 220,
+               KP_HEXADECIMAL = 221,
+               LCTRL = 224,
+               LSHIFT = 225,
+               LALT = 226,
+               LGUI = 227,
+               RCTRL = 228,
+               RSHIFT = 229,
+               RALT = 230,
+               RGUI = 231,
+               MODE = 257,
+               // These come from the USB consumer page (0x0C)
+               AUDIONEXT = 258,
+               AUDIOPREV = 259,
+               AUDIOSTOP = 260,
+               AUDIOPLAY = 261,
+               AUDIOMUTE = 262,
+               MEDIASELECT = 263,
+               WWW = 264,
+               MAIL = 265,
+               CALCULATOR = 266,
+               COMPUTER = 267,
+               AC_SEARCH = 268,
+               AC_HOME = 269,
+               AC_BACK = 270,
+               AC_FORWARD = 271,
+               AC_STOP = 272,
+               AC_REFRESH = 273,
+               AC_BOOKMARKS = 274,
+               // These come from other sources, and are mostly mac related
+               BRIGHTNESSDOWN = 275,
+               BRIGHTNESSUP = 276,
+               DISPLAYSWITCH = 277,
+               KBDILLUMTOGGLE = 278,
+               KBDILLUMDOWN = 279,
+               KBDILLUMUP = 280,
+               EJECT = 281,
+               SLEEP = 282,
+               APP1 = 283,
+               APP2 = 284,
+               // This is not a key, simply marks the number of scancodes
+               // so that you know how big to make your arrays.
+               SDL_NUM_SCANCODES = 512
+       }
+
+       internal enum State : byte
+       {
+               Released = 0,
+               Pressed = 1
+       }
+
+       [Flags]
+       internal enum SystemFlags : uint
+       {
+               Default = 0,
+               TIMER = 0x00000001,
+               AUDIO = 0x00000010,
+               VIDEO = 0x00000020,
+               JOYSTICK = 0x00000200,
+               HAPTIC = 0x00001000,
+               GAMECONTROLLER = 0x00002000,
+               NOPARACHUTE = 0x00100000,
+               EVERYTHING = TIMER | AUDIO | VIDEO |
+                       JOYSTICK | HAPTIC | GAMECONTROLLER
+       }
+
+       internal enum SysWMType
+       {
+               Unknown = 0,
+               Windows,
+               X11,
+               Wayland,
+               DirectFB,
+               Cocoa,
+               UIKit,
+       }
+
+       internal enum WindowEventID : byte
+       {
+               NONE,
+               SHOWN,
+               HIDDEN,
+               EXPOSED,
+               MOVED,
+               RESIZED,
+               SIZE_CHANGED,
+               MINIMIZED,
+               MAXIMIZED,
+               RESTORED,
+               ENTER,
+               LEAVE,
+               FOCUS_GAINED,
+               FOCUS_LOST,
+               CLOSE,
+       }
+
+       internal enum WindowFlags
+       {
+               Default = 0,
+               FULLSCREEN = 0x00000001,
+               OPENGL = 0x00000002,
+               SHOWN = 0x00000004,
+               HIDDEN = 0x00000008,
+               BORDERLESS = 0x00000010,
+               RESIZABLE = 0x00000020,
+               MINIMIZED = 0x00000040,
+               MAXIMIZED = 0x00000080,
+               INPUT_GRABBED = 0x00000100,
+               INPUT_FOCUS = 0x00000200,
+               MOUSE_FOCUS = 0x00000400,
+               FULLSCREEN_DESKTOP = (FULLSCREEN | 0x00001000),
+               FOREIGN = 0x00000800,
+               ALLOW_HIGHDPI = 0x00002000,
+       }
+
+       internal struct ControllerAxisEvent
+       {
+               public EventType Type;
+               public uint Timestamp;
+               public int Which;
+               public GameControllerAxis Axis;
+               private byte padding1;
+               private byte padding2;
+               private byte padding3;
+               public short Value;
+               private ushort padding4;
+       }
+
+       internal struct ControllerButtonEvent
+       {
+               public EventType Type;
+               public uint Timestamp;
+               public int Which;
+               public GameControllerButton Button;
+               public State State;
+               private byte padding1;
+               private byte padding2;
+       }
+
+       internal struct ControllerDeviceEvent
+       {
+               public EventType Type;
+               public uint Timestamp;
+
+               /// <summary>
+               /// The joystick device index for the ADDED event, instance id for the REMOVED or REMAPPED event
+               /// </summary>
+               public int Which;
+       }
+
+       internal struct DisplayMode
+       {
+               public uint Format;
+               public int Width;
+               public int Height;
+               public int RefreshRate;
+               public IntPtr DriverData;
+       }
+
+       [StructLayout(LayoutKind.Explicit)]
+       internal struct Event
+       {
+               [FieldOffset(0)]
+               public EventType Type;
+               [FieldOffset(0)]
+               public WindowEvent Window;
+               [FieldOffset(0)]
+               public KeyboardEvent Key;
+               [FieldOffset(0)]
+               public TextEditingEvent Edit;
+               [FieldOffset(0)]
+               public TextInputEvent Text;
+               [FieldOffset(0)]
+               public MouseMotionEvent Motion;
+               [FieldOffset(0)]
+               public MouseButtonEvent Button;
+               [FieldOffset(0)]
+               public MouseWheelEvent Wheel;
+               [FieldOffset(0)]
+               public JoyAxisEvent JoyAxis;
+               [FieldOffset(0)]
+               public JoyBallEvent JoyBall;
+               [FieldOffset(0)]
+               public JoyHatEvent JoyHat;
+               [FieldOffset(0)]
+               public JoyButtonEvent JoyButton;
+               [FieldOffset(0)]
+               public JoyDeviceEvent JoyDevice;
+               [FieldOffset(0)]
+               public ControllerAxisEvent ControllerAxis;
+               [FieldOffset(0)]
+               public ControllerButtonEvent ControllerButton;
+               [FieldOffset(0)]
+               public ControllerDeviceEvent ControllerDevice;
+               [FieldOffset(0)]
+               public DropEvent Drop;
+               #if false
+               [FieldOffset(0)]
+               public QuitEvent quit;
+               [FieldOffset(0)]
+               public UserEvent user;
+               [FieldOffset(0)]
+               public SysWMEvent syswm;
+               [FieldOffset(0)]
+               public TouchFingerEvent tfinger;
+               [FieldOffset(0)]
+               public MultiGestureEvent mgesture;
+               [FieldOffset(0)]
+               public DollarGestureEvent dgesture;
+               #endif
+
+               // Ensure the structure is big enough
+               // This hack is necessary to ensure compatibility
+               // with different SDL versions, which might have
+               // different sizeof(SDL_Event).
+               [FieldOffset(0)]
+               private unsafe fixed byte reserved[128];
+       }
+
+       [StructLayout(LayoutKind.Explicit)]
+       internal struct GameControllerButtonBind
+       {
+               [FieldOffset(0)]
+               public GameControllerBindType BindType;
+               [FieldOffset(4)]
+               public Button Button;
+               [FieldOffset(4)]
+               public GameControllerAxis Axis;
+               [FieldOffset(4)]
+               public int Hat;
+               [FieldOffset(8)]
+               public int HatMask;
+       }
+
+       internal struct JoyAxisEvent
+       {
+               public EventType Type;
+               public UInt32 Timestamp;
+               public Int32 Which; // SDL_JoystickID
+               public byte Axis;
+               private byte padding1;
+               private byte padding2;
+               private byte padding3;
+               public Int16 Value;
+               private UInt16 padding4;
+       }
+
+       internal struct JoyBallEvent
+       {
+               public EventType Type;
+               public uint Timestamp;
+               public int Which;
+               public byte Ball;
+               private byte padding1;
+               private byte padding2;
+               private byte padding3;
+               public short Xrel;
+               public short Yrel;
+       }
+
+       internal struct JoyButtonEvent
+       {
+               public EventType Type;
+               public uint Timestamp;
+               public int Which;
+               public byte Button;
+               public State State;
+               private byte padding1;
+               private byte padding2;
+       }
+
+       internal struct JoyDeviceEvent
+       {
+               public EventType Type;
+               public uint Timestamp;
+               public int Which;
+       }
+
+       internal struct JoyHatEvent
+       {
+               public EventType Type;
+               public uint Timestamp;
+               public int Which;
+               public byte Hat;
+               public HatPosition Value;
+               private byte padding1;
+               private byte padding2;
+       }
+
+       internal struct JoystickGuid
+       {
+               private long data0;
+               private long data1;
+
+               public Guid ToGuid()
+               {
+                       byte[] data = new byte[16];
+
+                       unsafe
+                       {
+                               fixed (JoystickGuid* pdata = &this)
+                               {
+                                       Marshal.Copy(new IntPtr(pdata), data, 0, data.Length);
+                               }
+                       }
+
+                       // The Guid(byte[]) constructor swaps the first 4+2+2 bytes.
+                       // Compensate for that, otherwise we will not be able to match
+                       // the Guids in the configuration database.
+                       if (BitConverter.IsLittleEndian)
+                       {
+                               Array.Reverse(data, 0, 4);
+                               Array.Reverse(data, 4, 2);
+                               Array.Reverse(data, 6, 2);
+                       }
+
+                       return new Guid(data);
+               }
+       }
+
+       internal struct KeyboardEvent
+       {
+               public EventType Type;
+               public uint Timestamp;
+               public uint WindowID;
+               public State State;
+               public byte Repeat;
+               private byte padding2;
+               private byte padding3;
+               public Keysym Keysym;
+       }
+
+       internal struct Keysym
+       {
+               public Scancode Scancode;
+               public Keycode Sym;
+               public Keymod Mod;
+               [Obsolete]
+               public uint Unicode;
+       }
+
+       internal struct MouseButtonEvent
+       {
+               public EventType Type;
+               public UInt32 Timestamp;
+               public UInt32 WindowID;
+               public UInt32 Which;
+               public Button Button;
+               public State State;
+               public byte Clicks;
+               private byte padding1;
+               public Int32 X;
+               public Int32 Y;
+       }
+
+       internal struct MouseMotionEvent
+       {
+               public EventType Type;
+               public uint Timestamp;
+               public uint WindowID;
+               public uint Which;
+               public ButtonFlags State;
+               public Int32 X;
+               public Int32 Y;
+               public Int32 Xrel;
+               public Int32 Yrel;
+       }
+
+       internal struct MouseWheelEvent
+       {
+               public EventType Type;
+               public uint Timestamp;
+               public uint WindowID;
+               public uint Which;
+               public int X;
+               public int Y;
+
+               public enum EventType : uint
+               {
+                       /* Touch events */
+                       FingerDown      = 0x700,
+                       FingerUp,
+                       FingerMotion,
+
+                       /* Gesture events */
+                       DollarGesture   = 0x800,
+                       DollarRecord,
+                       MultiGesture,
+               }
+
+               public const uint TouchMouseID = 0xffffffff;
+       }
+
+       internal struct Rect
+       {
+               public int X;
+               public int Y;
+               public int Width;
+               public int Height;
+       }
+
+       internal struct SysWMInfo
+       {
+               public Version Version;
+               public SysWMType Subsystem;
+               public SysInfo Info;
+
+               [StructLayout(LayoutKind.Explicit)]
+               public struct SysInfo
+               {
+                       [FieldOffset(0)]
+                       public WindowsInfo Windows;
+                       [FieldOffset(0)]
+                       public X11Info X11;
+                       [FieldOffset(0)]
+                       public WaylandInfo Wayland;
+                       [FieldOffset(0)]
+                       public DirectFBInfo DirectFB;
+                       [FieldOffset(0)]
+                       public CocoaInfo Cocoa;
+                       [FieldOffset(0)]
+                       public UIKitInfo UIKit;
+
+                       public struct WindowsInfo
+                       {
+                               public IntPtr Window;
+                       }
+
+                       public struct X11Info
+                       {
+                               public IntPtr Display;
+                               public IntPtr Window;
+                       }
+
+                       public struct WaylandInfo
+                       {
+                               public IntPtr Display;
+                               public IntPtr Surface;
+                               public IntPtr ShellSurface;
+                       }
+
+                       public struct DirectFBInfo
+                       {
+                               public IntPtr Dfb;
+                               public IntPtr Window;
+                               public IntPtr Surface;
+                       }
+
+                       public struct CocoaInfo
+                       {
+                               public IntPtr Window;
+                       }
+
+                       public struct UIKitInfo
+                       {
+                               public IntPtr Window;
+                       }
+               }
+       }
+
+       internal struct TextEditingEvent
+       {
+               public const int TextSize = 32;
+
+               public EventType Type;
+               public UInt32 Timestamp;
+               public UInt32 WindowID;
+               public unsafe fixed byte Text[TextSize];
+               public Int32 Start;
+               public Int32 Length;
+       }
+
+       internal struct TextInputEvent
+       {
+               public const int TextSize = 32;
+
+               public EventType Type;
+               public UInt32 Timestamp;
+               public UInt32 WindowID;
+               public unsafe fixed byte Text[TextSize];
+       }
+
+       internal struct Version
+       {
+               public byte Major;
+               public byte Minor;
+               public byte Patch;
+
+               public int Number
+               {
+                       get { return 1000 * Major + 100 * Minor + Patch; }
+               }
+       }
+
+       internal struct WindowEvent
+       {
+               public EventType Type;
+               public UInt32 Timestamp;
+               public UInt32 WindowID;
+               public WindowEventID Event;
+               private byte padding1;
+               private byte padding2;
+               private byte padding3;
+               public Int32 Data1;
+               public Int32 Data2;
+       }
+
+       /// <summary>
+       /// Drop event for SDL2 interop. For detailed info look: https://wiki.libsdl.org/SDL_DropEvent
+       /// </summary>
+       internal struct DropEvent
+       {
+               public UInt32 Type;
+               public UInt32 Timestamp;
+               public IntPtr File;
+               public UInt32 WindowID;
+       }
+}
+
diff --git a/Tests/test-sdl2 (copier).cs b/Tests/test-sdl2 (copier).cs
new file mode 100644 (file)
index 0000000..6bc2c64
--- /dev/null
@@ -0,0 +1,162 @@
+//
+// test-sdl2.cs
+//
+// Author:
+//       jp <>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using OpenTK;
+using OpenTK.Graphics.OpenGL;
+using OpenTK.Platform;
+using Crow.SDL2;
+
+namespace Crow
+{
+       public class test_sdl2_2
+       {
+               public test_sdl2_2 ()
+               {
+               }
+
+               static int colors = 32, depth=24, stencil=0,samples=1;
+               static int width=500,height=500;
+
+               static void Main(){
+                       SysWMInfo sdlInfo;
+
+                       SDL.Init (SystemFlags.EVERYTHING);
+
+
+
+
+                       IntPtr hWin = SDL.CreateWindow ("test sdl2", 0, 0, width, height, WindowFlags.OPENGL | WindowFlags.SHOWN);
+
+//                     SDL.GL.SetAttribute (ContextAttribute.CONTEXT_MAJOR_VERSION, 4);
+//                     SDL.GL.SetAttribute (ContextAttribute.CONTEXT_MAJOR_VERSION, 5);
+                       SDL.GL.SetAttribute (ContextAttribute.SHARE_WITH_CURRENT_CONTEXT, 1);
+
+                       IntPtr hCtx = SDL.GL.CreateContext (hWin);
+                       IntPtr hCairoCtx = SDL.GL.CreateContext (hWin);
+
+                       SDL.GetWindowWMInfo (hWin, out sdlInfo);
+                       SDL.GL.MakeCurrent(hWin,hCtx);
+
+                       int major, minor;
+                       SDL.GL.GetAttribute (ContextAttribute.CONTEXT_MAJOR_VERSION, out major);
+                       SDL.GL.GetAttribute (ContextAttribute.CONTEXT_MINOR_VERSION, out minor);
+                       Console.WriteLine ("gl context = {0}.{1}\n", major, minor);
+
+                       Toolkit.Init();
+                       IWindowInfo wi = Utilities.CreateSdl2WindowInfo (hWin);
+                       ContextHandle otkCtx = new ContextHandle (hCtx);
+//                     //OpenTK.Graphics.GraphicsMode gm = new OpenTK.Graphics.GraphicsMode (colors, depth, stencil, samples);
+                       OpenTK.Graphics.GraphicsContext ctx = new OpenTK.Graphics.GraphicsContext (otkCtx, wi);
+//                     ctx.MakeCurrent(wi);
+
+
+                       ctx.LoadAll();
+
+                       Cairo.GLXDevice dev = new Cairo.GLXDevice (sdlInfo.Info.X11.Display, hCairoCtx);
+
+                       int tex = GL.GenTexture ();
+                       GL.BindTexture (TextureTarget.Texture2D, tex);
+                       GL.TexImage2D (TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0,
+                               PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
+
+                       //dev.Acquire ();
+                       Cairo.GLSurface surf = new Cairo.GLSurface (dev,Cairo.Content.ColorAlpha,(uint)tex, width,height);
+
+                       SDL.GL.MakeCurrent(hWin,hCairoCtx);
+                       using (Cairo.Context gr = new Cairo.Context (surf)) {
+                               gr.Rectangle (150, 100, 200, 100);
+                               gr.SetSourceRGBA (1.0, 0.0, 0.0,0.5);
+                               gr.Fill ();
+                               gr.Rectangle (200, 150, 200, 100);
+                               gr.SetSourceRGBA (0.0, 1.0, 0.0,0.5);
+                               gr.Fill ();
+                       }
+                       surf.Flush ();
+                       surf.SwapBuffers ();
+                       //surf.WriteToPng ("/mnt/data/test.png");
+
+                       SDL.GL.MakeCurrent(hWin,hCtx);
+
+
+                       Matrix4 proj = Matrix4.CreateOrthographicOffCenter (-1f, 1f, -1f, 1f, 1.0f, -1.0f);
+                       GL.MatrixMode(MatrixMode.Projection);
+                       GL.LoadMatrix (ref proj);
+                       GL.MatrixMode(MatrixMode.Modelview);
+                       GL.LoadIdentity();
+
+                       GL.ClearColor(0.0f, 0.0f, 0.5f, 1.0f);
+                       GL.Clear (ClearBufferMask.ColorBufferBit|ClearBufferMask.DepthBufferBit);
+
+                       GL.Viewport (0, 0, width, height);
+
+                       GL.Enable(EnableCap.DepthTest);
+                       GL.Enable(EnableCap.Texture2D);
+                       GL.Enable (EnableCap.Blend);
+                       GL.BlendFunc (BlendingFactorSrc.One, BlendingFactorDest.OneMinusSrcAlpha);
+
+                       GL.BindTexture (TextureTarget.Texture2D, tex);
+                       GL.Begin(PrimitiveType.Quads);
+
+                       // Bottom-Left
+                       GL.TexCoord2(0, 1);
+                       GL.Vertex2(-1, -1);
+
+                       // Upper-Left
+                       GL.TexCoord2(0, 0);
+                       GL.Vertex2(-1, 1);
+
+                       // Upper-Right
+                       GL.TexCoord2(1, 0);
+                       GL.Vertex2(1, 1);
+
+                       // Bottom-Right
+                       GL.TexCoord2(1, 1);
+                       GL.Vertex2(1, -1);
+
+                       GL.End();
+       
+                       //ctx.SwapBuffers ();
+                       SDL.GL.SwapWindow (hWin);
+
+                       System.Threading.Thread.Sleep (1000);
+
+                       surf.Dispose();
+                       GL.DeleteTexture (tex);
+                       dev.Dispose ();
+
+
+                       SDL.GL.MakeCurrent (hWin, IntPtr.Zero);
+                       SDL.GL.DeleteContext (hCairoCtx);
+                       SDL.GL.DeleteContext (hCtx);
+                       SDL.DestroyWindow (hWin);
+
+
+
+
+               }
+       }
+}
+
diff --git a/Tests/test-sdl2.cs b/Tests/test-sdl2.cs
new file mode 100644 (file)
index 0000000..d405696
--- /dev/null
@@ -0,0 +1,159 @@
+//
+// test-sdl2.cs
+//
+// Author:
+//       jp <>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using OpenTK;
+using OpenTK.Graphics.OpenGL;
+using OpenTK.Platform;
+using Crow.SDL2;
+
+namespace Crow
+{
+       public class test_sdl2
+       {
+               public test_sdl2 ()
+               {
+               }
+
+               static int colors = 32, depth=24, stencil=0,samples=1;
+               static int width=500,height=500;
+
+               static void Main(){
+                       SysWMInfo sdlInfo;
+
+                       SDL.Init (SystemFlags.EVERYTHING);
+
+
+                       IntPtr hWin = SDL.CreateWindow ("test sdl2", 0, 0, width, height, WindowFlags.OPENGL | WindowFlags.SHOWN);
+
+                       SDL.GL.SetAttribute (ContextAttribute.CONTEXT_MAJOR_VERSION, 3);
+                       SDL.GL.SetAttribute (ContextAttribute.CONTEXT_MAJOR_VERSION, 3);
+                       SDL.GL.SetAttribute (ContextAttribute.SHARE_WITH_CURRENT_CONTEXT, 1);
+
+                       IntPtr hCtx = SDL.GL.CreateContext (hWin);
+                       IntPtr hCairoCtx = SDL.GL.CreateContext (hWin);
+
+                       SDL.GetWindowWMInfo (hWin, out sdlInfo);
+                       SDL.GL.MakeCurrent(hWin,hCtx);
+
+                       int major, minor;
+                       SDL.GL.GetAttribute (ContextAttribute.CONTEXT_MAJOR_VERSION, out major);
+                       SDL.GL.GetAttribute (ContextAttribute.CONTEXT_MINOR_VERSION, out minor);
+                       Console.WriteLine ("gl context = {0}.{1}\n", major, minor);
+
+                       Toolkit.Init();
+                       IWindowInfo wi = Utilities.CreateSdl2WindowInfo (hWin);
+                       ContextHandle otkCtx = new ContextHandle (hCtx);
+
+                       OpenTK.Graphics.GraphicsContext ctx = new OpenTK.Graphics.GraphicsContext (otkCtx, wi);
+
+
+
+                       ctx.LoadAll();
+
+                       Cairo.GLXDevice dev = new Cairo.GLXDevice (sdlInfo.Info.X11.Display, hCairoCtx);
+
+                       int tex = GL.GenTexture ();
+                       GL.BindTexture (TextureTarget.Texture2D, tex);
+                       GL.TexImage2D (TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0,
+                               PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
+
+                       //dev.Acquire ();
+                       Cairo.GLSurface surf = new Cairo.GLSurface (dev,Cairo.Content.ColorAlpha,(uint)tex, width,height);
+
+                       SDL.GL.MakeCurrent(hWin,hCairoCtx);
+                       using (Cairo.Context gr = new Cairo.Context (surf)) {
+                               gr.Rectangle (150, 100, 200, 100);
+                               gr.SetSourceRGBA (1.0, 0.0, 0.0,0.5);
+                               gr.Fill ();
+                               gr.Rectangle (200, 150, 200, 100);
+                               gr.SetSourceRGBA (0.0, 1.0, 0.0,0.5);
+                               gr.Fill ();
+                       }
+                       surf.Flush ();
+                       surf.SwapBuffers ();
+
+                       SDL.GL.MakeCurrent(hWin,hCtx);
+
+
+                       Matrix4 proj = Matrix4.CreateOrthographicOffCenter (-1f, 1f, -1f, 1f, 1.0f, -1.0f);
+                       GL.MatrixMode(MatrixMode.Projection);
+                       GL.LoadMatrix (ref proj);
+                       GL.MatrixMode(MatrixMode.Modelview);
+                       GL.LoadIdentity();
+
+                       GL.ClearColor(0.0f, 0.0f, 0.5f, 1.0f);
+                       GL.Clear (ClearBufferMask.ColorBufferBit|ClearBufferMask.DepthBufferBit);
+
+                       GL.Viewport (0, 0, width, height);
+
+                       GL.Enable(EnableCap.DepthTest);
+                       GL.Enable(EnableCap.Texture2D);
+                       GL.Enable (EnableCap.Blend);
+                       GL.BlendFunc (BlendingFactorSrc.One, BlendingFactorDest.OneMinusSrcAlpha);
+
+                       GL.BindTexture (TextureTarget.Texture2D, tex);
+                       GL.Begin(PrimitiveType.Quads);
+
+                       // Bottom-Left
+                       GL.TexCoord2(0, 1);
+                       GL.Vertex2(-1, -1);
+
+                       // Upper-Left
+                       GL.TexCoord2(0, 0);
+                       GL.Vertex2(-1, 1);
+
+                       // Upper-Right
+                       GL.TexCoord2(1, 0);
+                       GL.Vertex2(1, 1);
+
+                       // Bottom-Right
+                       GL.TexCoord2(1, 1);
+                       GL.Vertex2(1, -1);
+
+                       GL.End();
+       
+                       //ctx.SwapBuffers ();
+                       SDL.GL.SwapWindow (hWin);
+
+                       System.Threading.Thread.Sleep (1000);
+
+                       surf.Dispose();
+                       GL.DeleteTexture (tex);
+                       dev.Dispose ();
+
+
+                       SDL.GL.MakeCurrent (hWin, IntPtr.Zero);
+                       SDL.GL.DeleteContext (hCairoCtx);
+                       SDL.GL.DeleteContext (hCtx);
+                       SDL.DestroyWindow (hWin);
+
+
+
+
+               }
+       }
+}
+
diff --git a/Tests/test_xcb.cs b/Tests/test_xcb.cs
new file mode 100644 (file)
index 0000000..62e0a4d
--- /dev/null
@@ -0,0 +1,145 @@
+//
+// BasicTests.cs
+//
+// Author:
+//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using Crow;
+using System.Collections.Generic;
+using System.Linq;
+using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Diagnostics;
+using Crow.SDL2;
+
+using Native;
+
+using XCBConnection = System.IntPtr;
+using XCBSetup = System.IntPtr;
+using XCBScreen = System.IntPtr;
+using XCBWindow = System.UInt32;
+using XCBColorMap = System.UInt32;
+using XCBVisualId = System.UInt32;
+
+
+namespace Tests
+{
+       class test_xcb
+       {
+//             static IntPtr findVisual(XCBConnection conn, XCBVisualId visualId){                     
+//                     Xcb.GenericIterator iter = Xcb.SetupRootsIterator (Xcb.GetSetup (conn));
+//                     for (; iter.rem > 0; Xcb.ScreenNext(ref iter)) {
+//                             
+//                             Xcb.Screen screen = Marshal.PtrToStructure<Xcb.Screen> (iter.data);
+//                             Xcb.GenericIterator depthIter = Xcb.ScreenAllowedDepthsIterator (ref screen);
+//                             for (; depthIter.rem > 0; Xcb.DepthNext (ref depthIter)) {
+//                                     Xcb.Depth depth = Marshal.PtrToStructure<Xcb.Depth> (depthIter.data);
+//                                     Console.WriteLine ("Depth = {0}\n\tVisuals: ", depth.depth);
+//                                     Xcb.GenericIterator visualIter = Xcb.DepthVisualsIterator (ref depth);
+//                                     for (; visualIter.rem > 0; Xcb.VisualtypeNext (ref visualIter)) {
+//                                             Xcb.VisualType visual = Marshal.PtrToStructure<Xcb.VisualType> (visualIter.data);
+//                                             Console.WriteLine ("{0}, ", visual.visual_id);
+//                                             if (visualId == visual.visual_id)
+//                                                     return visualIter.data;
+//                                     }
+//                             }
+//                     }
+//                     return IntPtr.Zero;
+//             }
+
+               [STAThread]
+               static void Main ()
+               {
+                       XCBConnection conn = Xcb.Connect ();
+
+                       Xcb.Result res = Xcb.ConnectionHasError (conn);
+
+                       if (res != Xcb.Result.SUCCESS) 
+                               Console.WriteLine ("error");
+
+                       IntPtr screenPtr = Xcb.SetupRootsIterator (Xcb.GetSetup (conn)).data;
+                       XCBWindow win = Xcb.GenerateId (conn);
+
+                       Xcb.Screen scr = Marshal.PtrToStructure<Xcb.Screen> (screenPtr);
+
+                       int[] mask = {1,(int)(Xcb.EventMask.EXPOSURE|Xcb.EventMask.KEY_PRESS|Xcb.EventMask.BUTTON_PRESS)};
+
+                       int maskSize =sizeof(int)*mask.Length;
+
+                       //IntPtr pMask = Marshal.AllocHGlobal(mask.Length * sizeof(uint));
+                       IntPtr pMask = Marshal.AllocHGlobal(sizeof(int)*mask.Length);
+                       Marshal.Copy(mask, 0, pMask, mask.Length);
+
+                       uint result = Xcb.CreateWindow (conn, 0, win, scr.root, 10, 10, 200, 200, 1, (ushort)Xcb.WindowClass.INPUT_OUTPUT, scr.root_visual,
+                               Xcb.Cw.OVERRIDE_REDIRECT | Xcb.Cw.EVENT_MASK, pMask);
+                       
+                       Marshal.FreeHGlobal(pMask);
+
+                       result = Xcb.MapWindow (conn, win);
+
+                       IntPtr visual = Xcb.FindVisual (conn, scr.root_visual);
+
+                       Console.WriteLine ("visual={0:X}", visual);
+                       if (visual == IntPtr.Zero)
+                               throw new Exception ("visual not found");
+
+                       Cairo.XcbSurface surf = new Cairo.XcbSurface (conn, win, visual, 200, 200);
+                       if (surf.Status != Cairo.Status.Success)
+                               Console.WriteLine ("surf.status: " + surf.Status);
+
+                       bool quit = false;
+
+                       Xcb.Flush (conn);
+
+                       while (!quit) {
+                               IntPtr pEvt = Xcb.WaitForEvent (conn);
+                               Xcb.GenericEvent e = Marshal.PtrToStructure<Xcb.GenericEvent> (pEvt);
+
+                               switch (e.response_type) {
+                               case Xcb.EventType.EXPOSE:
+                                       using (Cairo.Context ctx = new Cairo.Context (surf)) {
+                                               ctx.SetSourceRGBA (0.0, 0.0, 1.0, 1.0);
+                                               ctx.Rectangle (10, 10, 100, 100);
+                                               ctx.Fill ();
+                                       }
+                                       surf.Flush ();
+                                       break;
+                               case Xcb.EventType.BUTTON_PRESS:
+                                       quit = true;
+                                       break;
+                               default:
+                                       break;
+                               }
+                               Xcb.Flush (conn);
+                       }
+
+                       surf.Finish ();
+                       surf.Dispose ();
+
+                       Xcb.Disconnect (conn);
+               }
+       }
+}
diff --git a/Tests/xcb.cs b/Tests/xcb.cs
new file mode 100644 (file)
index 0000000..40250f4
--- /dev/null
@@ -0,0 +1,244 @@
+//
+// xcb.cs
+//
+// Author:
+//       jp <>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+
+using XCBConnection = System.IntPtr;
+using XCBSetup = System.IntPtr;
+using XCBScreen = System.IntPtr;
+using XCBWindow = System.UInt32;
+using XCBColorMap = System.UInt32;
+using XCBVisualId = System.UInt32;
+
+using System.Runtime.InteropServices;
+
+namespace Native
+{
+       
+
+       public static class Xcb
+       {               
+
+               const string lib = "libxcb.so.1";
+
+               public enum Result {
+                       SUCCESS = 0,
+                       ERROR = 1,                              /** xcb connection errors because of socket, pipe and other stream errors. */
+                       EXT_NOTSUPPORTED = 2,   /** xcb connection shutdown because of extension not supported */               
+                       MEM_INSUFFICIENT = 3,   /** malloc(), calloc() and realloc() error upon failure, for eg ENOMEM */               
+                       REQ_LEN_EXCEED = 4,             /** Connection closed, exceeding request length that server accepts. */         
+                       PARSE_ERR = 5,                  /** Connection closed, error during parsing display string. */          
+                       INVALID_SCREEN = 6,             /** Connection closed because the server does not have a screen matching the display. */                
+                       FDPASSING_FAILED = 7,   /** Connection closed because some FD passing operation failed */
+               }
+               public enum EventMask : uint {
+                       NO_EVENT = 0,
+                       KEY_PRESS = 1,
+                       KEY_RELEASE = 2,
+                       BUTTON_PRESS = 4,
+                       BUTTON_RELEASE = 8,
+                       ENTER_WINDOW = 16,
+                       LEAVE_WINDOW = 32,
+                       POINTER_MOTION = 64,
+                       POINTER_MOTION_HINT = 128,
+                       BUTTON_1_MOTION = 256,
+                       BUTTON_2_MOTION = 512,
+                       BUTTON_3_MOTION = 1024,
+                       BUTTON_4_MOTION = 2048,
+                       BUTTON_5_MOTION = 4096,
+                       BUTTON_MOTION = 8192,
+                       KEYMAP_STATE = 16384,
+                       EXPOSURE = 32768,
+                       VISIBILITY_CHANGE = 65536,
+                       STRUCTURE_NOTIFY = 131072,
+                       RESIZE_REDIRECT = 262144,
+                       SUBSTRUCTURE_NOTIFY = 524288,
+                       SUBSTRUCTURE_REDIRECT = 1048576,
+                       FOCUS_CHANGE = 2097152,
+                       PROPERTY_CHANGE = 4194304,
+                       COLOR_MAP_CHANGE = 8388608,
+                       OWNER_GRAB_BUTTON = 16777216
+               }
+               public enum WindowClass : ushort {
+                       COPY_FROM_PARENT = 0,
+                       INPUT_OUTPUT = 1,
+                       INPUT_ONLY = 2
+               }
+               public enum Cw : uint {
+                       BACK_PIXMAP = 1,
+                       BACK_PIXEL = 2,
+                       BORDER_PIXMAP = 4,
+                       BORDER_PIXEL = 8,
+                       BIT_GRAVITY = 16,
+                       WIN_GRAVITY = 32,
+                       BACKING_STORE = 64,
+                       BACKING_PLANES = 128,
+                       BACKING_PIXEL = 256,
+                       OVERRIDE_REDIRECT = 512,
+                       SAVE_UNDER = 1024,
+                       EVENT_MASK = 2048,
+                       DONT_PROPAGATE = 4096,
+                       COLORMAP = 8192,
+                       CURSOR = 16384
+               }
+
+               public enum EventType : byte {
+                       KEY_PRESS = 2,
+                       KEY_RELEASE = 3,
+                       BUTTON_PRESS = 4,
+                       BUTTON_RELEASE = 5,
+                       MOTION_NOTIFY = 6,
+                       ENTER_NOTIFY = 7,
+                       LEAVE_NOTIFY = 8,
+                       FOCUS_IN = 9,
+                       FOCUS_OUT = 10,
+                       KEYMAP_NOTIFY = 11,
+                       EXPOSE = 12
+               }
+
+               [StructLayout(LayoutKind.Sequential)]
+               public struct GenericIterator {
+                       public IntPtr data;   /**< Data of the current iterator */
+                       public int rem;    /**< remaining elements */
+                       public int index;  /**< index of the current iterator */
+               }
+               [StructLayout(LayoutKind.Sequential)]
+               public struct Screen {
+                       public XCBWindow        root;
+                       public XCBColorMap      default_colormap;
+                       public uint                     white_pixel;
+                       public uint                     black_pixel;
+                       public uint                     current_input_masks;
+                       public ushort           width_in_pixels;
+                       public ushort           height_in_pixels;
+                       public ushort           width_in_millimeters;
+                       public ushort           height_in_millimeters;
+                       public ushort           min_installed_maps;
+                       public ushort           max_installed_maps;
+                       public XCBVisualId      root_visual;
+                       public byte                     backing_stores;
+                       public byte                     save_unders;
+                       public byte                     root_depth;
+                       public byte                     allowed_depths_len;
+               }
+               [StructLayout(LayoutKind.Explicit,Size=8)]
+//             [StructLayout(LayoutKind.Sequential)]
+               public struct Depth {
+                       [FieldOffset(0)]        public byte             depth;
+                       [FieldOffset(2)]        public ushort   visuals_len;
+//                     public byte  depth;
+//                     public byte  pad0;
+//                     public ushort visuals_len;
+//                     public byte  pad1;
+//                     public byte  pad2;
+//                     public byte  pad3;
+//                     public byte  pad4;
+               }
+
+               [StructLayout(LayoutKind.Explicit, Size=24)]
+               public struct VisualType {
+                       [FieldOffset(0)]public XCBVisualId      visual_id;
+                       [FieldOffset(4)]public byte                     _class;
+                       [FieldOffset(5)]public byte                     bits_per_rgb_value;
+                       [FieldOffset(6)]public ushort           colormap_entries;
+                       [FieldOffset(8)]public uint                     red_mask;
+                       [FieldOffset(12)]public uint                    green_mask;
+                       [FieldOffset(16)]public uint                    blue_mask;
+               }
+               [StructLayout(LayoutKind.Explicit, Size = 36)]
+               public struct GenericEvent {
+                       [FieldOffset(0)]        public EventType        response_type;  // Type of the response
+                       [FieldOffset(2)]        public ushort           sequence;               // Sequence number
+                       [FieldOffset(32)]       public uint                     full_sequence;  // full sequence
+               };
+
+//             struct GenericReply {
+//                     byte    response_type;
+//                     byte    pad0;
+//                     UInt16  sequence;
+//                     UInt32  length;
+//             }
+
+               [DllImport(lib, EntryPoint = "xcb_connect", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+               public extern static XCBConnection Connect([MarshalAs(UnmanagedType.LPStr)] string displayname = null, IntPtr screen = default(IntPtr));
+               [DllImport(lib, EntryPoint = "xcb_disconnect", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+               public extern static void Disconnect(XCBConnection connection);
+
+               [DllImport(lib, EntryPoint = "xcb_connection_has_error", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+               public extern static Result ConnectionHasError(XCBConnection connection);
+               [DllImport(lib, EntryPoint = "xcb_get_setup", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+               public extern static XCBSetup GetSetup(XCBConnection connection);
+               [DllImport(lib, EntryPoint = "xcb_setup_roots_iterator", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+               public extern static GenericIterator SetupRootsIterator (XCBSetup setup);
+               [DllImport(lib, EntryPoint = "xcb_generate_id", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+               public extern static XCBWindow GenerateId(XCBConnection connection);
+
+               /*xcb_void_cookie_t
+               xcb_create_window (xcb_connection_t *c,
+                       uint8_t           depth,
+                       xcb_window_t      wid,
+                       xcb_window_t      parent,
+                       int16_t           x,
+                       int16_t           y,
+                       uint16_t          width,
+                       uint16_t          height,
+                       uint16_t          border_width,
+                       uint16_t          _class,
+                       xcb_visualid_t    visual,
+                       uint32_t          value_mask,
+                       const void       *value_list);*/
+
+               [DllImport(lib, EntryPoint = "xcb_create_window", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+               public extern static uint CreateWindow (
+                       XCBConnection conn, byte depth, XCBWindow wid, XCBWindow parent,
+                       short x, short y, ushort width, ushort height, ushort border_width, ushort _class,
+                       XCBVisualId visual, Cw value_mask, IntPtr value_list);
+               
+               [DllImport(lib, EntryPoint = "xcb_map_window", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+               public extern static uint MapWindow (XCBConnection conn, XCBWindow window);
+
+               [DllImport(lib, EntryPoint = "xcb_screen_next", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+               public extern static void ScreenNext (ref GenericIterator iter);
+//             [DllImport(lib, EntryPoint = "xcb_screen_allowed_depths_length", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+//             public extern static IntPtr ScreenAllowedDepthsLength (ref Xcb.Screen screen);
+               [DllImport(lib, EntryPoint = "xcb_screen_allowed_depths_iterator", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+               public extern static GenericIterator ScreenAllowedDepthsIterator (ref Xcb.Screen screen);
+               [DllImport(lib, EntryPoint = "xcb_depth_next", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+               public extern static void DepthNext (ref GenericIterator iter);
+               [DllImport(lib, EntryPoint = "xcb_depth_visuals_iterator", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+               public extern static GenericIterator DepthVisualsIterator (ref Xcb.Depth depth);
+               [DllImport(lib, EntryPoint = "xcb_visualtype_next", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+               public extern static void VisualtypeNext (ref GenericIterator iter);
+
+               [DllImport(lib, EntryPoint = "xcb_flush", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+               public extern static int Flush(XCBConnection conn);
+               [DllImport(lib, EntryPoint = "xcb_wait_for_event", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+               public extern static IntPtr WaitForEvent(XCBConnection conn);
+
+               [DllImport("/mnt/devel/gts/tests/libxcb-helper.so", EntryPoint = "find_visual", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+               public extern static IntPtr FindVisual(XCBConnection conn, XCBVisualId visualId);
+       }
+}
+
index 41738802701ade171c2351652aedd9b3dc719ceb..f593b09989df38590caae7d18f595aaca100c687 100644 (file)
@@ -1120,7 +1120,7 @@ namespace Crow
                        IsDirty = false;
                        if (bmp != null)
                                bmp.Dispose ();
-                       bmp = new ImageSurface (Format.Argb32, Slot.Width, Slot.Height);
+                       bmp = CurrentInterface.bmp.CreateSimilar(Content.ColorAlpha, Slot.Width, Slot.Height);
                        using (Context gr = new Context (bmp)) {
                                gr.Antialias = Interface.Antialias;
                                onDraw (gr);
index adcb283095acb695be13207dd1427b9c7488fcb5..f79d7a2ed9913bf022c89cc0e65f520fb52e8ce0 100644 (file)
@@ -124,9 +124,9 @@ namespace Crow
                /// <summary>Graphic Tree of this interface</summary>
                public List<GraphicObject> GraphicTree = new List<GraphicObject>();
                /// <summary>Interface's resulting bitmap</summary>
-               public byte[] bmp;
+               public Surface bmp;
                /// <summary>resulting bitmap limited to last redrawn part</summary>
-               public byte[] dirtyBmp;
+               public Surface dirtyBmp;
                /// <summary>True when host has to repaint Interface</summary>
                public bool IsDirty = false;
                /// <summary>Coordinate of the dirty bmp on the original bmp</summary>
@@ -500,64 +500,62 @@ namespace Crow
                        #if MEASURE_TIME
                        drawingMeasure.StartCycle();
                        #endif
-                       using (surf = new ImageSurface (bmp, Format.Argb32, ClientRectangle.Width, ClientRectangle.Height, ClientRectangle.Width * 4)) {
-                               using (ctx = new Context (surf)){
-                                       if (!clipping.IsEmpty) {
-
-                                               for (int i = 0; i < clipping.NumRectangles; i++)
-                                                       ctx.Rectangle(clipping.GetRectangle(i));
-                                               ctx.ClipPreserve();
-                                               ctx.Operator = Operator.Clear;
-                                               ctx.Fill();
-                                               ctx.Operator = Operator.Over;
-
-                                               for (int i = GraphicTree.Count -1; i >= 0 ; i--){
-                                                       GraphicObject p = GraphicTree[i];
-                                                       if (!p.Visible)
-                                                               continue;
-                                                       if (clipping.Contains (p.Slot) == RegionOverlap.Out)
-                                                               continue;
-
-                                                       ctx.Save ();
-                                                       p.Paint (ref ctx);
-                                                       ctx.Restore ();
-                                               }
 
-                                               #if DEBUG_CLIP_RECTANGLE
-                                               clipping.stroke (ctx, Color.Red.AdjustAlpha(0.5));
-                                               #endif
-                                               lock (RenderMutex) {
-//                                                     Array.Copy (bmp, dirtyBmp, bmp.Length);
+                       using (ctx = new Context (bmp)){
+                               if (!clipping.IsEmpty) {
+
+                                       for (int i = 0; i < clipping.NumRectangles; i++)
+                                               ctx.Rectangle(clipping.GetRectangle(i));
+                                       ctx.ClipPreserve();
+                                       ctx.Operator = Operator.Clear;
+                                       ctx.Fill();
+                                       ctx.Operator = Operator.Over;
+
+                                       for (int i = GraphicTree.Count -1; i >= 0 ; i--){
+                                               GraphicObject p = GraphicTree[i];
+                                               if (!p.Visible)
+                                                       continue;
+                                               if (clipping.Contains (p.Slot) == RegionOverlap.Out)
+                                                       continue;
+
+                                               ctx.Save ();
+                                               p.Paint (ref ctx);
+                                               ctx.Restore ();
+                                       }
 
-                                                       IsDirty = true;
-                                                       if (IsDirty)
-                                                               DirtyRect += clipping.Extents;
-                                                       else
-                                                               DirtyRect = clipping.Extents;
-
-                                                       DirtyRect.Left = Math.Max (0, DirtyRect.Left);
-                                                       DirtyRect.Top = Math.Max (0, DirtyRect.Top);
-                                                       DirtyRect.Width = Math.Min (ClientRectangle.Width - DirtyRect.Left, DirtyRect.Width);
-                                                       DirtyRect.Height = Math.Min (ClientRectangle.Height - DirtyRect.Top, DirtyRect.Height);
-                                                       DirtyRect.Width = Math.Max (0, DirtyRect.Width);
-                                                       DirtyRect.Height = Math.Max (0, DirtyRect.Height);
-
-                                                       if (DirtyRect.Width > 0 && DirtyRect.Height >0) {
-                                                               dirtyBmp = new byte[4 * DirtyRect.Width * DirtyRect.Height];
-                                                               for (int y = 0; y < DirtyRect.Height; y++) {
-                                                                       Array.Copy (bmp,
-                                                                               ((DirtyRect.Top + y) * ClientRectangle.Width * 4) + DirtyRect.Left * 4,
-                                                                               dirtyBmp, y * DirtyRect.Width * 4, DirtyRect.Width * 4);
-                                                               }
+                                       #if DEBUG_CLIP_RECTANGLE
+                                       clipping.stroke (ctx, Color.Red.AdjustAlpha(0.5));
+                                       #endif
+                                       lock (RenderMutex) {
+//                                                     Array.Copy (bmp, dirtyBmp, bmp.Length);
 
-                                                       } else
-                                                               IsDirty = false;
-                                               }
-                                               clipping.Dispose ();
-                                               clipping = new Region ();
+                                               IsDirty = true;
+                                               if (IsDirty)
+                                                       DirtyRect += clipping.Extents;
+                                               else
+                                                       DirtyRect = clipping.Extents;
+
+                                               DirtyRect.Left = Math.Max (0, DirtyRect.Left);
+                                               DirtyRect.Top = Math.Max (0, DirtyRect.Top);
+                                               DirtyRect.Width = Math.Min (ClientRectangle.Width - DirtyRect.Left, DirtyRect.Width);
+                                               DirtyRect.Height = Math.Min (ClientRectangle.Height - DirtyRect.Top, DirtyRect.Height);
+                                               DirtyRect.Width = Math.Max (0, DirtyRect.Width);
+                                               DirtyRect.Height = Math.Max (0, DirtyRect.Height);
+
+                                               if (DirtyRect.Width > 0 && DirtyRect.Height >0) {
+                                                       dirtyBmp?.Dispose ();
+                                                       dirtyBmp = bmp.CreateSimilar (Content.ColorAlpha, DirtyRect.Width, DirtyRect.Height);
+                                                       using (Context dctx = new Context (dirtyBmp)) {
+                                                               dctx.SetSourceSurface (bmp, DirtyRect.Left, DirtyRect.Top);
+                                                               dctx.Paint ();
+                                                       }
+                                               } else
+                                                       IsDirty = false;
                                        }
-                                       //surf.WriteToPng (@"/mnt/data/test.png");
+                                       clipping.Dispose ();
+                                       clipping = new Region ();
                                }
+                               //bmp.WriteToPng (@"/mnt/data/test.png");
                        }
                        #if MEASURE_TIME
                        drawingMeasure.StopCycle();
@@ -659,19 +657,10 @@ namespace Crow
                }
                #endregion
 
-               public void ProcessResize(Rectangle bounds){
-                       lock (UpdateMutex) {
-                               clientRectangle = bounds;
-                               int stride = 4 * ClientRectangle.Width;
-                               int bmpSize = Math.Abs (stride) * ClientRectangle.Height;
-                               bmp = new byte[bmpSize];
-                               dirtyBmp = new byte[bmpSize];
-
-                               foreach (GraphicObject g in GraphicTree)
-                                       g.RegisterForLayouting (LayoutingType.All);
-
-                               RegisterClip (clientRectangle);
-                       }
+               public void ProcessResize(){                    
+                       foreach (GraphicObject g in GraphicTree)
+                               g.RegisterForLayouting (LayoutingType.All);
+                       RegisterClip (clientRectangle);
                }
 
                #region Mouse and Keyboard Handling
@@ -906,6 +895,7 @@ namespace Crow
 
                public Rectangle ClientRectangle {
                        get { return clientRectangle; }
+                       set { clientRectangle = value; }
                }
                public Interface HostContainer {
                        get { return this; }
index 98143fe8e22543efeda94ddba4631f6ea29b1efd..f109718b0f44e632307043c84a1421f93a94bbc6 100644 (file)
@@ -100,5 +100,13 @@ namespace Cairo {
                public int Stride {
                        get { return NativeMethods.cairo_image_surface_get_stride (Handle); }
                }
+
+               public override Surface CreateSimilar (Content content, int width, int height)
+               {
+                       IntPtr p = NativeMethods.cairo_surface_create_similar (
+                               this.Handle, content, width, height);
+
+                       return new Cairo.ImageSurface (p, true);
+               }
        }
 }
index d38b75556e5eb93b1f384103f7025beeefe66443..cdf26d10f6793d50bcb4ed1ddbc3a22390d9196b 100644 (file)
@@ -114,7 +114,7 @@ namespace Cairo {
                }
 
 
-               public Cairo.Surface CreateSimilar (
+               public virtual Cairo.Surface CreateSimilar (
                        Cairo.Content content, int width, int height)
                {
                        IntPtr p = NativeMethods.cairo_surface_create_similar (