]> O.S.I.I.S - jp/crow.git/commitdiff
first tests X11Backend
authorjpbruyere <jp.bruyere@hotmail.com>
Fri, 3 Mar 2017 12:45:46 +0000 (13:45 +0100)
committerjpbruyere <jp.bruyere@hotmail.com>
Fri, 3 Mar 2017 12:45:46 +0000 (13:45 +0100)
21 files changed:
Crow.sln
CrowX/CrowWindow.cs [new file with mode: 0644]
CrowX/CrowX.csproj [new file with mode: 0644]
CrowX/HelloWorld.cs [new file with mode: 0644]
CrowX/X11/API.cs [new file with mode: 0644]
CrowX/X11/Bindings/DL.cs [new file with mode: 0644]
CrowX/X11/Bindings/Glx.cs [new file with mode: 0644]
CrowX/X11/Bindings/INotify.cs [new file with mode: 0644]
CrowX/X11/Bindings/XI.cs [new file with mode: 0644]
CrowX/X11/Bindings/Xkb.cs [new file with mode: 0644]
CrowX/X11/Functions.cs [new file with mode: 0644]
CrowX/X11/Structs.cs [new file with mode: 0644]
CrowX/X11/X11DisplayDevice.cs [new file with mode: 0644]
CrowX/X11/X11Input.cs [new file with mode: 0644]
CrowX/X11/X11KeyMap.cs [new file with mode: 0644]
CrowX/X11/X11Keyboard.cs [new file with mode: 0644]
CrowX/X11/X11Mouse.cs [new file with mode: 0644]
CrowX/X11/X11WindowInfo.cs [new file with mode: 0644]
CrowX/X11/XI2Input.cs [new file with mode: 0644]
CrowX/X11/XI2MouseKeyboard.cs [new file with mode: 0644]
Tests/Tests.csproj

index 83e55eb5e132a7321a844503c009150f823d580e..f73291ef09f01ff9c5552601dfc073f5938731bd 100644 (file)
--- a/Crow.sln
+++ b/Crow.sln
@@ -5,6 +5,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Crow", "Crow.csproj", "{C29
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{74289092-9F70-4941-AFCB-DFD7BE2140B6}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CrowX", "CrowX\CrowX.csproj", "{793AEC6E-C4B4-4B34-9E4F-AE6B455F86A9}"
+EndProject
 Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                Debug|Any CPU = Debug|Any CPU
@@ -15,6 +17,10 @@ Global
                {74289092-9F70-4941-AFCB-DFD7BE2140B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
                {74289092-9F70-4941-AFCB-DFD7BE2140B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {74289092-9F70-4941-AFCB-DFD7BE2140B6}.Release|Any CPU.Build.0 = Release|Any CPU
+               {793AEC6E-C4B4-4B34-9E4F-AE6B455F86A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {793AEC6E-C4B4-4B34-9E4F-AE6B455F86A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {793AEC6E-C4B4-4B34-9E4F-AE6B455F86A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {793AEC6E-C4B4-4B34-9E4F-AE6B455F86A9}.Release|Any CPU.Build.0 = Release|Any CPU
                {C2980F9B-4798-4C05-99E2-E174810F7C7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {C2980F9B-4798-4C05-99E2-E174810F7C7B}.Debug|Any CPU.Build.0 = Debug|Any CPU
                {C2980F9B-4798-4C05-99E2-E174810F7C7B}.Release|Any CPU.ActiveCfg = Release|Any CPU
diff --git a/CrowX/CrowWindow.cs b/CrowX/CrowWindow.cs
new file mode 100644 (file)
index 0000000..b959d30
--- /dev/null
@@ -0,0 +1,82 @@
+//
+// 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 System.Collections.Generic;
+using X11Sharp;
+using System.Runtime.InteropServices;
+
+namespace Crow
+{
+       public class CrowWindow : IValueChange, IDisposable
+    {
+               #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
+
+               public IntPtr handle, rootWindow, display;
+               public int screen;
+               XVisualInfo visualInfo;
+               public EventMask eventMask;
+
+               #region ctor
+               public CrowWindow(int _width = 800, int _height = 600)                  
+               {                       
+                       IntPtr test = API.DefaultDisplay;
+                       display = Functions.XOpenDisplay(IntPtr.Zero);
+                       using (new XLock(display))
+                       {
+                               XSetWindowAttributes attr = new XSetWindowAttributes();
+
+                               screen = Functions.XDefaultScreen(display);
+                               rootWindow = Functions.XRootWindow(display, screen);
+                               handle = Functions.XCreateWindow(display, rootWindow,
+                                               0, 0, _width, _height, 0, 0, CreateWindowArgs.CopyFromParent, IntPtr.Zero,
+                                               SetWindowValuemask.Nothing, attr);
+                       Functions.XSelectInput (display, handle, new IntPtr((int)(EventMask.ExposureMask | EventMask.KeyPressMask)));
+                       }
+
+//                             ProcessingThread = new Thread(ProcessEvents);
+//                             ProcessingThread.IsBackground = true;
+//                             ProcessingThread.Start();
+               }
+
+               #endregion
+
+               #region IDisposable implementation
+               public void Dispose ()
+               {
+                       Functions.XCloseDisplay(display);
+               }
+               #endregion
+    }
+}
diff --git a/CrowX/CrowX.csproj b/CrowX/CrowX.csproj
new file mode 100644 (file)
index 0000000..1815078
--- /dev/null
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{793AEC6E-C4B4-4B34-9E4F-AE6B455F86A9}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <RootNamespace>CrowX</RootNamespace>
+    <AssemblyName>CrowX</AssemblyName>
+    <ReleaseVersion>0.5</ReleaseVersion>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <OutputPath>$(SolutionDir)build/$(Configuration)</OutputPath>
+    <IntermediateOutputPath>$(SolutionDir)build/obj/$(Configuration)</IntermediateOutputPath>
+    <CustomCommands>
+      <CustomCommands>
+        <Command type="Execute" command="${TargetName}" workingdir="${SolutionDir}/build/${ProjectConfigName}" />
+      </CustomCommands>
+    </CustomCommands>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>full</DebugType>
+    <Optimize>true</Optimize>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <ItemGroup>
+    <Reference Include="cairo-sharp">
+      <Package>gtk-sharp-3.0</Package>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Crow.csproj">
+      <Project>{C2980F9B-4798-4C05-99E2-E174810F7C7B}</Project>
+      <Name>Crow</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="CrowWindow.cs" />
+    <Compile Include="HelloWorld.cs" />
+    <Compile Include="X11\API.cs" />
+    <Compile Include="X11\Functions.cs" />
+    <Compile Include="X11\Structs.cs" />
+    <Compile Include="X11\X11KeyMap.cs" />
+    <Compile Include="X11\Bindings\DL.cs" />
+    <Compile Include="X11\Bindings\INotify.cs" />
+    <Compile Include="X11\Bindings\XI.cs" />
+    <Compile Include="X11\Bindings\Xkb.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Folder Include="X11\" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="X11\X11DisplayDevice.cs" />
+    <None Include="X11\X11Keyboard.cs" />
+    <None Include="X11\X11Mouse.cs" />
+    <None Include="X11\X11WindowInfo.cs" />
+    <None Include="X11\XI2Input.cs" />
+    <None Include="X11\XI2MouseKeyboard.cs" />
+    <None Include="X11\X11Input.cs" />
+    <None Include="X11\Bindings\Glx.cs" />
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/CrowX/HelloWorld.cs b/CrowX/HelloWorld.cs
new file mode 100644 (file)
index 0000000..1b6ab44
--- /dev/null
@@ -0,0 +1,66 @@
+//
+// HelloWorld.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 X11Sharp;
+
+namespace Tests
+{
+       class HelloWorld : CrowWindow
+       {
+               public HelloWorld ()
+                       : base(800, 600)
+               {
+                       //AddWidget(new Label("Hello World"));
+               }
+
+               [STAThread]
+               static void Main ()
+               {                       
+                       using (HelloWorld win = new HelloWorld ()) {
+                               Functions.XMapWindow (win.display, win.handle);
+                               while (true) {
+                                       XEvent e = new XEvent ();;
+                                       Functions.XNextEvent (win.display, ref e);
+                                       /* draw or redraw the window */
+                                               
+                                       if (e.type == XEventName.Expose)
+                                       {
+                                               Functions.XFillRectangle(win.display, win.handle,
+                                                       Functions.XDefaultGC(win.display,win.screen), 20, 20, 100, 100);
+                                               //Functions.XDrawString(display, window, DefaultGC(display, s), 50, 50, msg, strlen(msg));
+                                       }
+                                       /* exit on key press */
+                                       if (e.type == XEventName.KeyPress)
+                                               break;
+                                       if (e.type == XEventName.ButtonPress)
+                                               break;
+                               }
+                       }
+               }
+       }
+}
\ No newline at end of file
diff --git a/CrowX/X11/API.cs b/CrowX/X11/API.cs
new file mode 100644 (file)
index 0000000..23c14ab
--- /dev/null
@@ -0,0 +1,1792 @@
+#region --- License ---
+/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
+ * Contributions from Erik Ylvisaker
+ * See license.txt for license info
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+
+#pragma warning disable 3019    // CLS-compliance checking
+#pragma warning disable 0649    // struct members not explicitly initialized
+#pragma warning disable 0169    // field / method is never used.
+#pragma warning disable 0414    // field assigned but never used.
+
+namespace X11Sharp
+{
+    #region Types
+
+    // using XID = System.Int32;
+    using Window = System.IntPtr;
+    using Drawable = System.IntPtr;
+    using Font = System.IntPtr;
+    using Pixmap = System.IntPtr;
+    using Cursor = System.IntPtr;
+    using Colormap = System.IntPtr;
+    using GContext = System.IntPtr;
+    using KeySym = System.IntPtr;
+    using Mask = System.IntPtr;
+    using Atom = System.IntPtr;
+    using VisualID = System.IntPtr;
+    using Time = System.IntPtr;
+    using KeyCode = System.Byte;    // Or maybe ushort?
+
+    using Display = System.IntPtr;
+    using XPointer = System.IntPtr;
+
+    using XcursorBool = System.Int32;
+    using XcursorUInt = System.UInt32;
+    using XcursorDim = System.UInt32;
+    using XcursorPixel = System.UInt32;
+
+    // Randr and Xrandr
+    using Bool = System.Boolean;
+    using XRRScreenConfiguration = System.IntPtr; // opaque datatype
+    using Rotation = System.UInt16;
+    using Status = System.Int32;
+    using SizeID = System.UInt16;
+
+    #endregion
+
+    #region internal static class API
+
+    internal static class API
+    {
+        #region --- Fields ---
+
+        private const string _dll_name = "libX11";
+        private const string _dll_name_vid = "libXxf86vm";
+
+        static Display defaultDisplay;
+        static int defaultScreen;
+        static Window rootWindow;
+        static int screenCount;
+
+        internal static Display DefaultDisplay { get { return defaultDisplay; } }
+        static int DefaultScreen { get { return defaultScreen; } }
+        //internal static Window RootWindow { get { return rootWindow; } }
+        internal static int ScreenCount { get { return screenCount; } }
+        
+        internal static object Lock = new object();
+
+        #endregion
+
+        static API()
+        {
+            int has_threaded_x = Functions.XInitThreads();
+            Debug.Print("Initializing threaded X11: {0}.", has_threaded_x.ToString());
+        
+            defaultDisplay = Functions.XOpenDisplay(IntPtr.Zero);
+                
+            if (defaultDisplay == IntPtr.Zero)
+                throw new Exception("Could not establish connection to the X-Server.");
+
+            using (new XLock(defaultDisplay))
+            {
+                screenCount = Functions.XScreenCount(DefaultDisplay);
+            }
+            Debug.Print("Display connection: {0}, Screen count: {1}", DefaultDisplay, ScreenCount);
+
+            //AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
+        }
+
+        static void CurrentDomain_ProcessExit(object sender, EventArgs e)
+        {
+            if (defaultDisplay != IntPtr.Zero)
+            {
+                Functions.XCloseDisplay(defaultDisplay);
+                defaultDisplay = IntPtr.Zero;
+                defaultScreen = 0;
+                rootWindow = IntPtr.Zero;
+            }
+        }
+
+        // Display management
+        //[DllImport(_dll_name, EntryPoint = "XOpenDisplay")]
+        //extern public static IntPtr OpenDisplay([MarshalAs(UnmanagedType.LPTStr)] string display_name);
+
+        //[DllImport(_dll_name, EntryPoint = "XCloseDisplay")]
+        //extern public static void CloseDisplay(Display display);
+
+        //[DllImport(_dll_name, EntryPoint = "XCreateColormap")]
+        //extern public static IntPtr CreateColormap(Display display, Window window, IntPtr visual, int alloc);
+
+        #region Window handling
+
+        [DllImport(_dll_name, EntryPoint = "XCreateSimpleWindow")]
+        public extern static Window CreateSimpleWindow(
+            Display display,
+            Window parent,
+            int x, int y,
+            int width, int height,
+            int border_width,
+            long border,
+            long background
+        );
+
+        [DllImport(_dll_name, EntryPoint = "XResizeWindow")]
+        public extern static int XResizeWindow(Display display, Window window, int width, int height);
+
+        [DllImport(_dll_name, EntryPoint = "XDestroyWindow")]
+        public extern static void DestroyWindow(Display display, Window window);
+
+        [DllImport(_dll_name, EntryPoint = "XMapWindow")]
+        extern public static void MapWindow(Display display, Window window);
+
+        [DllImport(_dll_name, EntryPoint = "XMapRaised")]
+        extern public static void MapRaised(Display display, Window window);
+
+        #endregion
+
+        [DllImport(_dll_name, EntryPoint = "XDefaultVisual")]
+        extern public static IntPtr DefaultVisual(Display display, int screen_number);
+
+        #region XFree
+
+        /// <summary>
+        /// Frees the memory used by an X structure. Only use on unmanaged structures!
+        /// </summary>
+        /// <param name="buffer">A pointer to the structure that will be freed.</param>
+        [DllImport(_dll_name, EntryPoint = "XFree")]
+        extern public static void Free(IntPtr buffer);
+
+        #endregion
+
+        #region Event queue management
+
+        [System.Security.SuppressUnmanagedCodeSecurity]
+        [DllImport(_dll_name, EntryPoint = "XEventsQueued")]
+        extern public static int EventsQueued(Display display, int mode);
+
+        [System.Security.SuppressUnmanagedCodeSecurity]
+        [DllImport(_dll_name, EntryPoint = "XPending")]
+        extern public static int Pending(Display display);
+
+        //[System.Security.SuppressUnmanagedCodeSecurity]
+        [DllImport(_dll_name, EntryPoint = "XNextEvent")]
+        extern public static void NextEvent(
+            Display display,
+            [MarshalAs(UnmanagedType.AsAny)][In, Out]object e);
+
+        [DllImport(_dll_name, EntryPoint = "XNextEvent")]
+        extern public static void NextEvent(Display display, [In, Out] IntPtr e);
+
+        [DllImport(_dll_name, EntryPoint = "XPeekEvent")]
+        extern public static void PeekEvent(
+            Display display,
+            [MarshalAs(UnmanagedType.AsAny)][In, Out]object event_return
+        );
+
+        [DllImport(_dll_name, EntryPoint = "XPeekEvent")]
+        extern public static void PeekEvent(Display display, [In, Out]XEvent event_return);
+
+        [DllImport(_dll_name, EntryPoint = "XSendEvent")]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        extern public static bool SendEvent(Display display, Window window, bool propagate,
+            [MarshalAs(UnmanagedType.SysInt)]EventMask event_mask, ref XEvent event_send);
+
+        /// <summary>
+        /// The XSelectInput() function requests that the X server report the events associated
+        /// with the specified event mask.
+        /// </summary>
+        /// <param name="display">Specifies the connection to the X server.</param>
+        /// <param name="w">Specifies the window whose events you are interested in.</param>
+        /// <param name="event_mask">Specifies the event mask.</param>
+        /// <remarks>
+        /// Initially, X will not report any of these events.
+        /// Events are reported relative to a window.
+        /// If a window is not interested in a device event,
+        /// it usually propagates to the closest ancestor that is interested,
+        /// unless the do_not_propagate mask prohibits it.
+        /// Setting the event-mask attribute of a window overrides any previous call for the same window but not for other clients. Multiple clients can select for the same events on the same window with the following restrictions: 
+        /// <para>Multiple clients can select events on the same window because their event masks are disjoint. When the X server generates an event, it reports it to all interested clients. </para>
+        /// <para>Only one client at a time can select CirculateRequest, ConfigureRequest, or MapRequest events, which are associated with the event mask SubstructureRedirectMask. </para>
+        /// <para>Only one client at a time can select a ResizeRequest event, which is associated with the event mask ResizeRedirectMask. </para>
+        /// <para>Only one client at a time can select a ButtonPress event, which is associated with the event mask ButtonPressMask. </para>
+        /// <para>The server reports the event to all interested clients. </para>
+        /// <para>XSelectInput() can generate a BadWindow error.</para>
+        /// </remarks>
+        [DllImport(_dll_name, EntryPoint = "XSelectInput")]
+        public static extern void SelectInput(Display display, Window w, EventMask event_mask);
+
+        /// <summary>
+        /// When the predicate procedure finds a match, XCheckIfEvent() copies the matched event into the client-supplied XEvent structure and returns True. (This event is removed from the queue.) If the predicate procedure finds no match, XCheckIfEvent() returns False, and the output buffer will have been flushed. All earlier events stored in the queue are not discarded.
+        /// </summary>
+        /// <param name="display">Specifies the connection to the X server.</param>
+        /// <param name="event_return">Returns a copy of the matched event's associated structure.</param>
+        /// <param name="predicate">Specifies the procedure that is to be called to determine if the next event in the queue matches what you want</param>
+        /// <param name="arg">Specifies the user-supplied argument that will be passed to the predicate procedure.</param>
+        /// <returns>true if the predicate returns true for some event, false otherwise</returns>
+        [DllImport(_dll_name, EntryPoint = "XCheckIfEvent")]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        public static extern bool CheckIfEvent(Display display, ref XEvent event_return,
+            /*[MarshalAs(UnmanagedType.FunctionPtr)] */ CheckEventPredicate predicate, /*XPointer*/ IntPtr arg);
+
+        [DllImport(_dll_name, EntryPoint = "XIfEvent")]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        public static extern bool IfEvent(Display display, ref XEvent event_return,
+            /*[MarshalAs(UnmanagedType.FunctionPtr)] */ CheckEventPredicate predicate, /*XPointer*/ IntPtr arg);
+
+        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+        public delegate bool CheckEventPredicate(Display display, ref XEvent @event, IntPtr arg);
+
+        [DllImport(_dll_name, EntryPoint = "XCheckMaskEvent")]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        public static extern bool CheckMaskEvent(Display display, EventMask event_mask, ref XEvent event_return);
+
+        #endregion
+
+        #region Pointer and Keyboard functions
+
+        [DllImport(_dll_name, EntryPoint = "XGrabPointer")]
+        extern public static ErrorCodes GrabPointer(Display display, IntPtr grab_window,
+            bool owner_events, int event_mask, GrabMode pointer_mode, GrabMode keyboard_mode,
+            IntPtr confine_to, IntPtr cursor, int time);
+
+        [DllImport(_dll_name, EntryPoint = "XUngrabPointer")]
+        extern public static ErrorCodes UngrabPointer(Display display, int time);
+
+        [DllImport(_dll_name, EntryPoint = "XGrabKeyboard")]
+        extern public static ErrorCodes GrabKeyboard(Display display, IntPtr grab_window,
+            bool owner_events, GrabMode pointer_mode, GrabMode keyboard_mode, int time);
+
+        [DllImport(_dll_name, EntryPoint = "XUngrabKeyboard")]
+        extern public static void UngrabKeyboard(Display display, int time);
+
+        /// <summary>
+        /// The XGetKeyboardMapping() function returns the symbols for the specified number of KeyCodes starting with first_keycode.
+        /// </summary>
+        /// <param name="display">Specifies the connection to the X server.</param>
+        /// <param name="first_keycode">Specifies the first KeyCode that is to be returned.</param>
+        /// <param name="keycode_count">Specifies the number of KeyCodes that are to be returned</param>
+        /// <param name="keysyms_per_keycode_return">Returns the number of KeySyms per KeyCode.</param>
+        /// <returns></returns>
+        /// <remarks>
+        /// <para>The value specified in first_keycode must be greater than or equal to min_keycode as returned by XDisplayKeycodes(), or a BadValue error results. In addition, the following expression must be less than or equal to max_keycode as returned by XDisplayKeycodes(): </para>
+        /// <para>first_keycode + keycode_count - 1 </para>
+        /// <para>If this is not the case, a BadValue error results. The number of elements in the KeySyms list is: </para>
+        /// <para>keycode_count * keysyms_per_keycode_return </para>
+        /// <para>KeySym number N, counting from zero, for KeyCode K has the following index in the list, counting from zero: </para>
+        /// <para> (K - first_code) * keysyms_per_code_return + N </para>
+        /// <para>The X server arbitrarily chooses the keysyms_per_keycode_return value to be large enough to report all requested symbols. A special KeySym value of NoSymbol is used to fill in unused elements for individual KeyCodes. To free the storage returned by XGetKeyboardMapping(), use XFree(). </para>
+        /// <para>XGetKeyboardMapping() can generate a BadValue error.</para>
+        /// <para>Diagnostics:</para>
+        /// <para>BadValue:    Some numeric value falls outside the range of values accepted by the request. Unless a specific range is specified for an argument, the full range defined by the argument's type is accepted. Any argument defined as a set of alternatives can generate this error.</para>
+        /// </remarks>
+        [DllImport(_dll_name, EntryPoint = "XGetKeyboardMapping")]
+        public static extern KeySym GetKeyboardMapping(Display display, KeyCode first_keycode, int keycode_count,
+            ref int keysyms_per_keycode_return);
+
+        /// <summary>
+        /// The XDisplayKeycodes() function returns the min-keycodes and max-keycodes supported by the specified display.
+        /// </summary>
+        /// <param name="display">Specifies the connection to the X server.</param>
+        /// <param name="min_keycodes_return">Returns the minimum number of KeyCodes</param>
+        /// <param name="max_keycodes_return">Returns the maximum number of KeyCodes.</param>
+        /// <remarks> The minimum number of KeyCodes returned is never less than 8, and the maximum number of KeyCodes returned is never greater than 255. Not all KeyCodes in this range are required to have corresponding keys.</remarks>
+        [DllImport(_dll_name, EntryPoint = "XDisplayKeycodes")]
+        public static extern void DisplayKeycodes(Display display, ref int min_keycodes_return, ref int max_keycodes_return);
+
+        #endregion
+
+        #region Xf86VidMode internal structures
+
+        [StructLayout(LayoutKind.Sequential)]
+        internal struct XF86VidModeModeLine
+        {
+            public short hdisplay;   /* Number of display pixels horizontally */
+            public short hsyncstart; /* Horizontal sync start */
+            public short hsyncend;   /* Horizontal sync end */
+            public short htotal;     /* Total horizontal pixels */
+            public short vdisplay;   /* Number of display pixels vertically */
+            public short vsyncstart; /* Vertical sync start */
+            public short vsyncend;   /* Vertical sync start */
+            public short vtotal;     /* Total vertical pixels */
+            public int flags;      /* Mode flags */
+            public int privsize;   /* Size of private */
+            public IntPtr _private;   /* Server privates */
+        }
+
+        /// <summary>
+        /// Specifies an XF86 display mode.
+        /// </summary>
+        [StructLayout(LayoutKind.Sequential)]
+        internal struct XF86VidModeModeInfo
+        {
+            /// <summary>
+            /// Pixel clock.
+            /// </summary>
+            public int dotclock;
+
+            /// <summary>
+            /// Number of display pixels horizontally
+            /// </summary>
+            public short hdisplay;
+
+            /// <summary>
+            /// Horizontal sync start
+            /// </summary>
+            public short hsyncstart;
+
+            /// <summary>
+            /// Horizontal sync end
+            /// </summary>
+            public short hsyncend;
+
+            /// <summary>
+            /// Total horizontal pixel
+            /// </summary>
+            public short htotal;
+
+            /// <summary>
+            /// 
+            /// </summary>
+            public short hskew;
+
+            /// <summary>
+            /// Number of display pixels vertically
+            /// </summary>
+            public short vdisplay;
+
+            /// <summary>
+            /// Vertical sync start
+            /// </summary>
+            public short vsyncstart;
+
+            /// <summary>
+            /// Vertical sync end
+            /// </summary>
+            public short vsyncend;
+
+            /// <summary>
+            /// Total vertical pixels
+            /// </summary>
+            public short vtotal;
+
+            /// <summary>
+            /// 
+            /// </summary>
+            public short vskew;
+
+            /// <summary>
+            /// Mode flags
+            /// </summary>
+            public int flags;
+
+            int privsize;   /* Size of private */
+            IntPtr _private;   /* Server privates */
+        }
+
+        //Monitor information:
+        [StructLayout(LayoutKind.Sequential)]
+        internal struct XF86VidModeMonitor
+        {
+            [MarshalAs(UnmanagedType.LPStr)]
+            string vendor;     /* Name of manufacturer */
+            [MarshalAs(UnmanagedType.LPStr)]
+            string model;      /* Model name */
+            float EMPTY;      /* unused, for backward compatibility */
+            byte nhsync;     /* Number of horiz sync ranges */
+            /*XF86VidModeSyncRange* */
+            IntPtr hsync;/* Horizontal sync ranges */
+            byte nvsync;     /* Number of vert sync ranges */
+            /*XF86VidModeSyncRange* */
+            IntPtr vsync;/* Vertical sync ranges */
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        internal struct XF86VidModeSyncRange
+        {
+            float hi;         /* Top of range */
+            float lo;         /* Bottom of range */
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        internal struct XF86VidModeNotifyEvent
+        {
+            int type;                      /* of event */
+            ulong serial;          /* # of last request processed by server */
+            bool send_event;               /* true if this came from a SendEvent req */
+            Display display;              /* Display the event was read from */
+            IntPtr root;                   /* root window of event screen */
+            int state;                     /* What happened */
+            int kind;                      /* What happened */
+            bool forced;                   /* extents of new region */
+            /* Time */
+            IntPtr time;                     /* event timestamp */
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        internal struct XF86VidModeGamma
+        {
+            float red;                     /* Red Gamma value */
+            float green;                   /* Green Gamma value */
+            float blue;                    /* Blue Gamma value */
+        }
+        #endregion
+
+        #region libXxf86vm Functions
+
+        [DllImport(_dll_name_vid)]
+        extern public static bool XF86VidModeQueryExtension(
+            Display display,
+            out int event_base_return,
+            out int error_base_return);
+        /*
+        [DllImport(_dll_name_vid)]
+        extern public static bool XF86VidModeSwitchMode(
+            Display display,
+            int screen,
+            int zoom);
+        */
+
+        [DllImport(_dll_name_vid)]
+        extern public static bool XF86VidModeSwitchToMode(
+            Display display,
+            int screen,
+            IntPtr
+            /*XF86VidModeModeInfo* */ modeline);
+
+
+        [DllImport(_dll_name_vid)]
+        extern public static bool XF86VidModeQueryVersion(
+            Display display,
+            out int major_version_return,
+            out int minor_version_return);
+
+        [DllImport(_dll_name_vid)]
+        extern public static bool XF86VidModeGetModeLine(
+            Display display,
+            int screen,
+            out int dotclock_return,
+            out XF86VidModeModeLine modeline);
+
+        [DllImport(_dll_name_vid)]
+        extern public static bool XF86VidModeGetAllModeLines(
+            Display display,
+            int screen,
+            out int modecount_return,
+            /*XF86VidModeModeInfo***  <-- yes, that's three *'s. */
+            out IntPtr modesinfo);
+
+        [DllImport(_dll_name_vid)]
+        extern public static bool XF86VidModeGetViewPort(
+            Display display,
+            int screen,
+            out int x_return,
+            out int y_return);
+
+        [DllImport(_dll_name_vid)]
+        extern public static bool XF86VidModeSetViewPort(
+            Display display,
+            int screen,
+            int x,
+            int y);
+
+        /*
+Bool XF86VidModeSetClientVersion(
+    Display *display);
+
+Bool XF86VidModeDeleteModeLine(
+    Display *display,
+    int screen,
+    XF86VidModeModeInfo *modeline);
+
+Bool XF86VidModeModModeLine(
+    Display *display,
+    int screen,
+    XF86VidModeModeLine *modeline);
+
+Status XF86VidModeValidateModeLine(
+    Display *display,
+    int screen,
+    XF86VidModeModeLine *modeline);
+
+Bool XF86VidModeLockModeSwitch(
+    Display *display,
+    int screen,
+    int lock);
+
+Bool XF86VidModeGetMonitor(
+    Display *display,
+    int screen,
+    XF86VidModeMonitor *monitor);
+
+XF86VidModeGetDotClocks(
+    Display *display,
+    int screen,
+    int *flags return,
+    int *number of clocks return,
+    int *max dot clock return,
+    int **clocks return);
+
+XF86VidModeGetGamma(
+    Display *display,
+    int screen,
+    XF86VidModeGamma *Gamma);
+
+XF86VidModeSetGamma(
+    Display *display,
+    int screen,
+    XF86VidModeGamma *Gamma);
+
+XF86VidModeGetGammaRamp(
+    Display *display,
+    int screen,
+    int size,
+    unsigned short *red array,
+    unsigned short *green array,
+    unsigned short *blue array);
+
+XF86VidModeSetGammaRamp(
+    Display *display,
+    int screen,
+    int size,
+    unsigned short *red array,
+    unsigned short *green array,
+    unsigned short *blue array);
+
+XF86VidModeGetGammaRampSize(
+    Display *display,
+    int screen,
+    int *size);
+         * */
+
+        #endregion
+
+        [DllImport(_dll_name, EntryPoint = "XLookupKeysym")]
+        public static extern KeySym LookupKeysym(ref XKeyEvent key_event, int index);
+
+    }
+    #endregion
+
+    #region X11 Structures
+
+    #region Xcursor
+
+    [StructLayout(LayoutKind.Sequential)]
+    unsafe struct XcursorImage
+    {
+        public XcursorUInt version;
+        public XcursorDim size;
+        public XcursorDim width;
+        public XcursorDim height;
+        public XcursorDim xhot;
+        public XcursorDim yhot;
+        public XcursorUInt delay;
+        public XcursorPixel* pixels;
+    }
+    
+    [StructLayout(LayoutKind.Sequential)]
+    unsafe struct XcursorImages 
+    {
+        public int nimage;
+        public XcursorImage **images;
+        public char *name;
+    }
+    
+    [StructLayout(LayoutKind.Sequential)]
+    unsafe struct XcursorCursors 
+    {
+        public Display dpy;
+        public int refcount;
+        public int ncursor;
+        public Cursor *cursors;
+    }
+    
+    [StructLayout(LayoutKind.Sequential)]
+    unsafe struct XcursorAnimate 
+    {
+        public XcursorCursors *cursors;
+        public int sequence;
+    }
+
+    #endregion
+
+    #region internal class XVisualInfo
+
+    [StructLayout(LayoutKind.Sequential)]
+    struct XVisualInfo
+    {
+        public IntPtr Visual;
+        public VisualID VisualID;
+        public int Screen;
+        public int Depth;
+        public XVisualClass Class;
+        public long RedMask;
+        public long GreenMask;
+        public long blueMask;
+        public int ColormapSize;
+        public int BitsPerRgb;
+
+        public override string ToString()
+        {
+            return String.Format("id ({0}), screen ({1}), depth ({2}), class ({3})",
+                VisualID, Screen, Depth, Class);
+        }
+    }
+
+    #endregion
+
+    #region internal class SetWindowAttributes
+
+    [StructLayout(LayoutKind.Sequential), Obsolete("Use XSetWindowAttributes instead")]
+    internal class SetWindowAttributes
+    {
+        /// <summary>
+        /// background, None, or ParentRelative
+        /// </summary>
+        public Pixmap background_pixmap;
+        /// <summary>
+        /// background pixel
+        /// </summary>
+        public long background_pixel;
+        /// <summary>
+        /// border of the window or CopyFromParent
+        /// </summary>
+        public Pixmap border_pixmap;
+        /// <summary>
+        /// border pixel value
+        /// </summary>
+        public long border_pixel;
+        /// <summary>
+        /// one of bit gravity values
+        /// </summary>
+        public int bit_gravity;
+        /// <summary>
+        /// one of the window gravity values
+        /// </summary>
+        public int win_gravity;
+        /// <summary>
+        /// NotUseful, WhenMapped, Always
+        /// </summary>
+        public int backing_store;
+        /// <summary>
+        /// planes to be preserved if possible
+        /// </summary>
+        public long backing_planes;
+        /// <summary>
+        /// value to use in restoring planes
+        /// </summary>
+        public long backing_pixel;
+        /// <summary>
+        /// should bits under be saved? (popups)
+        /// </summary>
+        public bool save_under;
+        /// <summary>
+        /// set of events that should be saved
+        /// </summary>
+        public EventMask event_mask;
+        /// <summary>
+        /// set of events that should not propagate
+        /// </summary>
+        public long do_not_propagate_mask;
+        /// <summary>
+        /// boolean value for override_redirect
+        /// </summary>
+        public bool override_redirect;
+        /// <summary>
+        /// color map to be associated with window
+        /// </summary>
+        public Colormap colormap;
+        /// <summary>
+        /// cursor to be displayed (or None)
+        /// </summary>
+        public Cursor cursor;
+    }
+
+    #endregion
+
+    #region internal struct SizeHints
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct SizeHints
+    {
+        public long flags;         /* marks which fields in this structure are defined */
+        public int x, y;           /* Obsolete */
+        public int width, height;  /* Obsolete */
+        public int min_width, min_height;
+        public int max_width, max_height;
+        public int width_inc, height_inc;
+        public Rectangle min_aspect, max_aspect;
+        public int base_width, base_height;
+        public int win_gravity;
+        internal struct Rectangle
+        {
+            public int x;       /* numerator */
+            public int y;       /* denominator */
+            private void stop_the_compiler_warnings() { x = y = 0; }
+        }
+        /* this structure may be extended in the future */
+    }
+
+    #endregion
+
+    #region internal struct XRRScreenSize
+
+    internal struct XRRScreenSize
+    {
+        internal int Width, Height;
+        internal int MWidth, MHeight;
+    };
+
+    #endregion
+
+    #region unsafe internal struct Screen
+
+    unsafe internal struct Screen
+    {
+        XExtData ext_data;    /* hook for extension to hang buffer */
+        IntPtr display;     /* back pointer to display structure */ /* _XDisplay */
+        Window root;        /* Root window id. */
+        int width, height;    /* width and height of screen */
+        int mwidth, mheight;    /* width and height of  in millimeters */
+        int ndepths;        /* number of depths possible */
+        //Depth *depths;        /* list of allowable depths on the screen */
+        int root_depth;        /* bits per pixel */
+        //Visual* root_visual;    /* root visual */
+        IntPtr default_gc;        /* GC for the root root visual */   // GC
+        Colormap cmap;        /* default color map */
+        UIntPtr white_pixel;    // unsigned long
+        UIntPtr black_pixel;    /* White and Black pixel values */  // unsigned long
+        int max_maps, min_maps;    /* max and min color maps */
+        int backing_store;    /* Never, WhenMapped, Always */
+        Bool save_unders;    
+        long root_input_mask;    /* initial root input mask */
+    }
+
+    #endregion
+
+    #region unsafe internal class XExtData
+
+    unsafe internal class XExtData
+    {
+        int number;        /* number returned by XRegisterExtension */
+        XExtData next;    /* next item on list of buffer for structure */
+        delegate int FreePrivateDelegate(XExtData extension);
+        FreePrivateDelegate FreePrivate;    /* called to free private storage */
+        XPointer private_data;    /* buffer private to this extension. */
+    };
+
+    #endregion
+    
+    #region Motif
+    
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct MotifWmHints
+    {
+        internal IntPtr flags;
+        internal IntPtr functions;
+        internal IntPtr decorations;
+        internal IntPtr input_mode;
+        internal IntPtr status;
+
+        public override string ToString ()
+        {
+            return string.Format("MotifWmHints <flags={0}, functions={1}, decorations={2}, input_mode={3}, status={4}", (MotifFlags) flags.ToInt32 (), (MotifFunctions) functions.ToInt32 (), (MotifDecorations) decorations.ToInt32 (), (MotifInputMode) input_mode.ToInt32 (), status.ToInt32 ());
+        }
+    }
+    
+    [Flags]
+    internal enum MotifFlags
+    {
+        Functions    = 1,
+        Decorations  = 2,
+        InputMode    = 4,
+        Status       = 8
+    }
+
+    [Flags]
+    internal enum MotifFunctions
+    {
+        All         = 0x01,
+        Resize      = 0x02,
+        Move        = 0x04,
+        Minimize    = 0x08,
+        Maximize    = 0x10,
+        Close       = 0x20
+    }
+
+    [Flags]
+    internal enum MotifDecorations
+    {
+        All         = 0x01,
+        Border      = 0x02,
+        ResizeH     = 0x04,
+        Title       = 0x08,
+        Menu        = 0x10,
+        Minimize    = 0x20,
+        Maximize    = 0x40,
+        
+    }
+
+    [Flags]
+    internal enum MotifInputMode
+    {
+        Modeless                = 0,
+        ApplicationModal        = 1,
+        SystemModal             = 2,
+        FullApplicationModal    = 3
+    }
+    
+    #endregion
+
+    #endregion
+
+    #region X11 Constants and Enums
+
+    internal struct Constants
+    {
+        public const int QueuedAlready = 0;
+        public const int QueuedAfterReading = 1;
+        public const int QueuedAfterFlush = 2;
+
+        public const int CopyFromParent = 0;
+        public const int CWX = 1;
+        public const int InputOutput = 1;
+        public const int InputOnly = 2;
+
+        /* The hints we recognize */
+        public const string XA_WIN_PROTOCOLS           = "_WIN_PROTOCOLS";
+        public const string XA_WIN_ICONS               = "_WIN_ICONS";
+        public const string XA_WIN_WORKSPACE           = "_WIN_WORKSPACE";
+        public const string XA_WIN_WORKSPACE_COUNT     = "_WIN_WORKSPACE_COUNT";
+        public const string XA_WIN_WORKSPACE_NAMES     = "_WIN_WORKSPACE_NAMES";
+        public const string XA_WIN_LAYER               = "_WIN_LAYER";
+        public const string XA_WIN_STATE               = "_WIN_STATE";
+        public const string XA_WIN_HINTS               = "_WIN_HINTS";
+        public const string XA_WIN_WORKAREA            = "_WIN_WORKAREA";
+        public const string XA_WIN_CLIENT_LIST         = "_WIN_CLIENT_LIST";
+        public const string XA_WIN_APP_STATE           = "_WIN_APP_STATE";
+        public const string XA_WIN_EXPANDED_SIZE       = "_WIN_EXPANDED_SIZE";
+        public const string XA_WIN_CLIENT_MOVING       = "_WIN_CLIENT_MOVING";
+        public const string XA_WIN_SUPPORTING_WM_CHECK = "_WIN_SUPPORTING_WM_CHECK";
+    }
+
+    internal enum WindowLayer
+    {
+        Desktop    = 0,
+        Below      = 2,
+        Normal     = 4,
+        OnTop      = 6,
+        Dock       = 8,
+        AboveDock  = 10,
+        Menu       = 12,
+    }
+
+    internal enum WindowState
+    {
+        Sticky           = (1<<0), /* everyone knows sticky */
+        Minimized        = (1<<1), /* ??? */
+        MaximizedVertically = (1<<2), /* window in maximized V state */
+        MaximizedHorizontally = (1<<3), /* window in maximized H state */
+        Hidden           = (1<<4), /* not on taskbar but window visible */
+        Shaded           = (1<<5), /* shaded (NeXT style), */
+        HID_WORKSPACE    = (1<<6), /* not on current desktop */
+        HID_TRANSIENT    = (1<<7), /* owner of transient is hidden */
+        FixedPosition    = (1<<8), /* window is fixed in position even */
+        ArrangeIgnore    = (1<<9),  /* ignore for auto arranging */
+    }
+
+    internal enum WindowHints
+    {
+        SkipFocus = (1<<0), /* "alt-tab" skips this win */
+        SkipWinlist = (1<<1), /* not in win list */
+        SkipTaskbar = (1<<2), /* not on taskbar */
+        GroupTransient = (1<<3), /* ??????? */
+        FocusOnClick = (1<<4), /* app only accepts focus when clicked */
+        DoNotCover = (1<<5),  /* attempt to not cover this window */
+    }
+
+    internal enum ErrorCodes : int
+    {
+        Success = 0,
+        BadRequest = 1,
+        BadValue = 2,
+        BadWindow = 3,
+        BadPixmap = 4,
+        BadAtom = 5,
+        BadCursor = 6,
+        BadFont = 7,
+        BadMatch = 8,
+        BadDrawable = 9,
+        BadAccess = 10,
+        BadAlloc = 11,
+        BadColor = 12,
+        BadGC = 13,
+        BadIDChoice = 14,
+        BadName = 15,
+        BadLength = 16,
+        BadImplementation = 17,
+    }
+
+    [Flags]
+    internal enum CreateWindowMask : long//: ulong
+    {
+        CWBackPixmap    = (1L<<0),
+        CWBackPixel     = (1L<<1),
+        CWSaveUnder        = (1L<<10),
+        CWEventMask        = (1L<<11),
+        CWDontPropagate    = (1L<<12),
+        CWColormap      = (1L<<13),
+        CWCursor        = (1L<<14),
+        CWBorderPixmap    = (1L<<2),
+        CWBorderPixel    = (1L<<3),
+        CWBitGravity    = (1L<<4),
+        CWWinGravity    = (1L<<5),
+        CWBackingStore    = (1L<<6),
+        CWBackingPlanes    = (1L<<7),
+        CWBackingPixel     = (1L<<8),
+        CWOverrideRedirect    = (1L<<9),
+
+        //CWY    = (1<<1),
+        //CWWidth    = (1<<2),
+        //CWHeight    = (1<<3),
+        //CWBorderWidth    = (1<<4),
+        //CWSibling    = (1<<5),
+        //CWStackMode    = (1<<6),
+    }
+
+    #region XKey
+
+    /// <summary>
+    /// Defines LATIN-1 and miscellaneous keys.
+    /// </summary>
+    [CLSCompliant(false)]
+    internal enum XKey
+    {
+        /*
+         * TTY function keys, cleverly chosen to map to ASCII, for convenience of
+         * programming, but could have been arbitrary (at the cost of lookup
+         * tables in client code).
+         */
+
+        BackSpace                   = 0xff08,  /* Back space, back char */
+        Tab                         = 0xff09,
+        Linefeed                    = 0xff0a,  /* Linefeed, LF */
+        Clear                       = 0xff0b,
+        Return                      = 0xff0d,  /* Return, enter */
+        Pause                       = 0xff13,  /* Pause, hold */
+        Scroll_Lock                 = 0xff14,
+        Sys_Req                     = 0xff15,
+        Escape                      = 0xff1b,
+        Delete                      = 0xffff,  /* Delete, rubout */
+
+
+
+        /* International & multi-key character composition */
+
+        Multi_key                   = 0xff20,  /* Multi-key character compose */
+        Codeinput                   = 0xff37,
+        SingleCandidate             = 0xff3c,
+        MultipleCandidate           = 0xff3d,
+        PreviousCandidate           = 0xff3e,
+                
+        /* Japanese keyboard support */
+
+        Kanji                       = 0xff21,  /* Kanji, Kanji convert */
+        Muhenkan                    = 0xff22,  /* Cancel Conversion */
+        Henkan_Mode                 = 0xff23,  /* Start/Stop Conversion */
+        Henkan                      = 0xff23,  /* Alias for Henkan_Mode */
+        Romaji                      = 0xff24,  /* to Romaji */
+        Hiragana                    = 0xff25,  /* to Hiragana */
+        Katakana                    = 0xff26,  /* to Katakana */
+        Hiragana_Katakana           = 0xff27,  /* Hiragana/Katakana toggle */
+        Zenkaku                     = 0xff28,  /* to Zenkaku */
+        Hankaku                     = 0xff29,  /* to Hankaku */
+        Zenkaku_Hankaku             = 0xff2a,  /* Zenkaku/Hankaku toggle */
+        Touroku                     = 0xff2b,  /* Add to Dictionary */
+        Massyo                      = 0xff2c,  /* Delete from Dictionary */
+        Kana_Lock                   = 0xff2d,  /* Kana Lock */
+        Kana_Shift                  = 0xff2e,  /* Kana Shift */
+        Eisu_Shift                  = 0xff2f,  /* Alphanumeric Shift */
+        Eisu_toggle                 = 0xff30,  /* Alphanumeric toggle */
+        Kanji_Bangou                = 0xff37,  /* Codeinput */
+        Zen_Koho                    = 0xff3d,  /* Multiple/All Candidate(s) */
+        Mae_Koho                    = 0xff3e,  /* Previous Candidate */
+
+        /* 0xff31 thru 0xff3f are under XK_KOREAN */
+
+        /* Cursor control & motion */
+
+        Home                        = 0xff50,
+        Left                        = 0xff51,  /* Move left, left arrow */
+        Up                          = 0xff52,  /* Move up, up arrow */
+        Right                       = 0xff53,  /* Move right, right arrow */
+        Down                        = 0xff54,  /* Move down, down arrow */
+        Prior                       = 0xff55,  /* Prior, previous */
+        Page_Up                     = 0xff55,
+        Next                        = 0xff56,  /* Next */
+        Page_Down                   = 0xff56,
+        End                         = 0xff57,  /* EOL */
+        Begin                       = 0xff58,  /* BOL */
+
+
+        /* Misc functions */
+
+        Select                      = 0xff60,  /* Select, mark */
+        Print                       = 0xff61,
+        Execute                     = 0xff62,  /* Execute, run, do */
+        Insert                      = 0xff63,  /* Insert, insert here */
+        Undo                        = 0xff65,
+        Redo                        = 0xff66,  /* Redo, again */
+        Menu                        = 0xff67,
+        Find                        = 0xff68,  /* Find, search */
+        Cancel                      = 0xff69,  /* Cancel, stop, abort, exit */
+        Help                        = 0xff6a,  /* Help */
+        Break                       = 0xff6b,
+        Mode_switch                 = 0xff7e,  /* Character set switch */
+        script_switch               = 0xff7e,  /* Alias for mode_switch */
+        Num_Lock                    = 0xff7f,
+
+        /* Keypad functions, keypad numbers cleverly chosen to map to ASCII */
+
+        KP_Space                    = 0xff80,  /* Space */
+        KP_Tab                      = 0xff89,
+        KP_Enter                    = 0xff8d,  /* Enter */
+        KP_F1                       = 0xff91,  /* PF1, KP_A, ... */
+        KP_F2                       = 0xff92,
+        KP_F3                       = 0xff93,
+        KP_F4                       = 0xff94,
+        KP_Home                     = 0xff95,
+        KP_Left                     = 0xff96,
+        KP_Up                       = 0xff97,
+        KP_Right                    = 0xff98,
+        KP_Down                     = 0xff99,
+        KP_Prior                    = 0xff9a,
+        KP_Page_Up                  = 0xff9a,
+        KP_Next                     = 0xff9b,
+        KP_Page_Down                = 0xff9b,
+        KP_End                      = 0xff9c,
+        KP_Begin                    = 0xff9d,
+        KP_Insert                   = 0xff9e,
+        KP_Delete                   = 0xff9f,
+        KP_Equal                    = 0xffbd,  /* Equals */
+        KP_Multiply                 = 0xffaa,
+        KP_Add                      = 0xffab,
+        KP_Separator                = 0xffac,  /* Separator, often comma */
+        KP_Subtract                 = 0xffad,
+        KP_Decimal                  = 0xffae,
+        KP_Divide                   = 0xffaf,
+
+        KP_0                        = 0xffb0,
+        KP_1                        = 0xffb1,
+        KP_2                        = 0xffb2,
+        KP_3                        = 0xffb3,
+        KP_4                        = 0xffb4,
+        KP_5                        = 0xffb5,
+        KP_6                        = 0xffb6,
+        KP_7                        = 0xffb7,
+        KP_8                        = 0xffb8,
+        KP_9                        = 0xffb9,
+
+        /*
+         * Auxiliary functions; note the duplicate definitions for left and right
+         * function keys;  Sun keyboards and a few other manufacturers have such
+         * function key groups on the left and/or right sides of the keyboard.
+         * We've not found a keyboard with more than 35 function keys total.
+         */
+
+        F1                          = 0xffbe,
+        F2                          = 0xffbf,
+        F3                          = 0xffc0,
+        F4                          = 0xffc1,
+        F5                          = 0xffc2,
+        F6                          = 0xffc3,
+        F7                          = 0xffc4,
+        F8                          = 0xffc5,
+        F9                          = 0xffc6,
+        F10                         = 0xffc7,
+        F11                         = 0xffc8,
+        L1                          = 0xffc8,
+        F12                         = 0xffc9,
+        L2                          = 0xffc9,
+        F13                         = 0xffca,
+        L3                          = 0xffca,
+        F14                         = 0xffcb,
+        L4                          = 0xffcb,
+        F15                         = 0xffcc,
+        L5                          = 0xffcc,
+        F16                         = 0xffcd,
+        L6                          = 0xffcd,
+        F17                         = 0xffce,
+        L7                          = 0xffce,
+        F18                         = 0xffcf,
+        L8                          = 0xffcf,
+        F19                         = 0xffd0,
+        L9                          = 0xffd0,
+        F20                         = 0xffd1,
+        L10                         = 0xffd1,
+        F21                         = 0xffd2,
+        R1                          = 0xffd2,
+        F22                         = 0xffd3,
+        R2                          = 0xffd3,
+        F23                         = 0xffd4,
+        R3                          = 0xffd4,
+        F24                         = 0xffd5,
+        R4                          = 0xffd5,
+        F25                         = 0xffd6,
+        R5                          = 0xffd6,
+        F26                         = 0xffd7,
+        R6                          = 0xffd7,
+        F27                         = 0xffd8,
+        R7                          = 0xffd8,
+        F28                         = 0xffd9,
+        R8                          = 0xffd9,
+        F29                         = 0xffda,
+        R9                          = 0xffda,
+        F30                         = 0xffdb,
+        R10                         = 0xffdb,
+        F31                         = 0xffdc,
+        R11                         = 0xffdc,
+        F32                         = 0xffdd,
+        R12                         = 0xffdd,
+        F33                         = 0xffde,
+        R13                         = 0xffde,
+        F34                         = 0xffdf,
+        R14                         = 0xffdf,
+        F35                         = 0xffe0,
+        R15                         = 0xffe0,
+
+        /* Modifiers */
+
+        Shift_L                     = 0xffe1,  /* Left shift */
+        Shift_R                     = 0xffe2,  /* Right shift */
+        Control_L                   = 0xffe3,  /* Left control */
+        Control_R                   = 0xffe4,  /* Right control */
+        Caps_Lock                   = 0xffe5,  /* Caps lock */
+        Shift_Lock                  = 0xffe6,  /* Shift lock */
+
+        Meta_L                      = 0xffe7,  /* Left meta */
+        Meta_R                      = 0xffe8,  /* Right meta */
+        Alt_L                       = 0xffe9,  /* Left alt */
+        Alt_R                       = 0xffea,  /* Right alt */
+        Super_L                     = 0xffeb,  /* Left super */
+        Super_R                     = 0xffec,  /* Right super */
+        Hyper_L                     = 0xffed,  /* Left hyper */
+        Hyper_R                     = 0xffee,  /* Right hyper */
+
+        ISO_Level3_Shift = 0xfe03,
+
+        /*
+         * Latin 1
+         * (ISO/IEC 8859-1 = Unicode U+0020..U+00FF)
+         * Byte 3 = 0
+         */
+
+        space                       = 0x0020,  /* U+0020 SPACE */
+        exclam                      = 0x0021,  /* U+0021 EXCLAMATION MARK */
+        quotedbl                    = 0x0022,  /* U+0022 QUOTATION MARK */
+        numbersign                  = 0x0023,  /* U+0023 NUMBER SIGN */
+        dollar                      = 0x0024,  /* U+0024 DOLLAR SIGN */
+        percent                     = 0x0025,  /* U+0025 PERCENT SIGN */
+        ampersand                   = 0x0026,  /* U+0026 AMPERSAND */
+        apostrophe                  = 0x0027,  /* U+0027 APOSTROPHE */
+        quoteright                  = 0x0027,  /* deprecated */
+        parenleft                   = 0x0028,  /* U+0028 LEFT PARENTHESIS */
+        parenright                  = 0x0029,  /* U+0029 RIGHT PARENTHESIS */
+        asterisk                    = 0x002a,  /* U+002A ASTERISK */
+        plus                        = 0x002b,  /* U+002B PLUS SIGN */
+        comma                       = 0x002c,  /* U+002C COMMA */
+        minus                       = 0x002d,  /* U+002D HYPHEN-MINUS */
+        period                      = 0x002e,  /* U+002E FULL STOP */
+        slash                       = 0x002f,  /* U+002F SOLIDUS */
+        Number0                           = 0x0030,  /* U+0030 DIGIT ZERO */
+        Number1                           = 0x0031,  /* U+0031 DIGIT ONE */
+        Number2                           = 0x0032,  /* U+0032 DIGIT TWO */
+        Number3                           = 0x0033,  /* U+0033 DIGIT THREE */
+        Number4                           = 0x0034,  /* U+0034 DIGIT FOUR */
+        Number5                           = 0x0035,  /* U+0035 DIGIT FIVE */
+        Number6                           = 0x0036,  /* U+0036 DIGIT SIX */
+        Number7                           = 0x0037,  /* U+0037 DIGIT SEVEN */
+        Number8                           = 0x0038,  /* U+0038 DIGIT EIGHT */
+        Number9                     = 0x0039,  /* U+0039 DIGIT NINE */
+        colon                       = 0x003a,  /* U+003A COLON */
+        semicolon                   = 0x003b,  /* U+003B SEMICOLON */
+        less                        = 0x003c,  /* U+003C LESS-THAN SIGN */
+        equal                       = 0x003d,  /* U+003D EQUALS SIGN */
+        greater                     = 0x003e,  /* U+003E GREATER-THAN SIGN */
+        question                    = 0x003f,  /* U+003F QUESTION MARK */
+        at                          = 0x0040,  /* U+0040 COMMERCIAL AT */
+        A                           = 0x0041,  /* U+0041 LATIN CAPITAL LETTER A */
+        B                           = 0x0042,  /* U+0042 LATIN CAPITAL LETTER B */
+        C                           = 0x0043,  /* U+0043 LATIN CAPITAL LETTER C */
+        D                           = 0x0044,  /* U+0044 LATIN CAPITAL LETTER D */
+        E                           = 0x0045,  /* U+0045 LATIN CAPITAL LETTER E */
+        F                           = 0x0046,  /* U+0046 LATIN CAPITAL LETTER F */
+        G                           = 0x0047,  /* U+0047 LATIN CAPITAL LETTER G */
+        H                           = 0x0048,  /* U+0048 LATIN CAPITAL LETTER H */
+        I                           = 0x0049,  /* U+0049 LATIN CAPITAL LETTER I */
+        J                           = 0x004a,  /* U+004A LATIN CAPITAL LETTER J */
+        K                           = 0x004b,  /* U+004B LATIN CAPITAL LETTER K */
+        L                           = 0x004c,  /* U+004C LATIN CAPITAL LETTER L */
+        M                           = 0x004d,  /* U+004D LATIN CAPITAL LETTER M */
+        N                           = 0x004e,  /* U+004E LATIN CAPITAL LETTER N */
+        O                           = 0x004f,  /* U+004F LATIN CAPITAL LETTER O */
+        P                           = 0x0050,  /* U+0050 LATIN CAPITAL LETTER P */
+        Q                           = 0x0051,  /* U+0051 LATIN CAPITAL LETTER Q */
+        R                           = 0x0052,  /* U+0052 LATIN CAPITAL LETTER R */
+        S                           = 0x0053,  /* U+0053 LATIN CAPITAL LETTER S */
+        T                           = 0x0054,  /* U+0054 LATIN CAPITAL LETTER T */
+        U                           = 0x0055,  /* U+0055 LATIN CAPITAL LETTER U */
+        V                           = 0x0056,  /* U+0056 LATIN CAPITAL LETTER V */
+        W                           = 0x0057,  /* U+0057 LATIN CAPITAL LETTER W */
+        X                           = 0x0058,  /* U+0058 LATIN CAPITAL LETTER X */
+        Y                           = 0x0059,  /* U+0059 LATIN CAPITAL LETTER Y */
+        Z                           = 0x005a,  /* U+005A LATIN CAPITAL LETTER Z */
+        bracketleft                 = 0x005b,  /* U+005B LEFT SQUARE BRACKET */
+        backslash                   = 0x005c,  /* U+005C REVERSE SOLIDUS */
+        bracketright                = 0x005d,  /* U+005D RIGHT SQUARE BRACKET */
+        asciicircum                 = 0x005e,  /* U+005E CIRCUMFLEX ACCENT */
+        underscore                  = 0x005f,  /* U+005F LOW LINE */
+        grave                       = 0x0060,  /* U+0060 GRAVE ACCENT */
+        quoteleft                   = 0x0060,  /* deprecated */
+        a                           = 0x0061,  /* U+0061 LATIN SMALL LETTER A */
+        b                           = 0x0062,  /* U+0062 LATIN SMALL LETTER B */
+        c                           = 0x0063,  /* U+0063 LATIN SMALL LETTER C */
+        d                           = 0x0064,  /* U+0064 LATIN SMALL LETTER D */
+        e                           = 0x0065,  /* U+0065 LATIN SMALL LETTER E */
+        f                           = 0x0066,  /* U+0066 LATIN SMALL LETTER F */
+        g                           = 0x0067,  /* U+0067 LATIN SMALL LETTER G */
+        h                           = 0x0068,  /* U+0068 LATIN SMALL LETTER H */
+        i                           = 0x0069,  /* U+0069 LATIN SMALL LETTER I */
+        j                           = 0x006a,  /* U+006A LATIN SMALL LETTER J */
+        k                           = 0x006b,  /* U+006B LATIN SMALL LETTER K */
+        l                           = 0x006c,  /* U+006C LATIN SMALL LETTER L */
+        m                           = 0x006d,  /* U+006D LATIN SMALL LETTER M */
+        n                           = 0x006e,  /* U+006E LATIN SMALL LETTER N */
+        o                           = 0x006f,  /* U+006F LATIN SMALL LETTER O */
+        p                           = 0x0070,  /* U+0070 LATIN SMALL LETTER P */
+        q                           = 0x0071,  /* U+0071 LATIN SMALL LETTER Q */
+        r                           = 0x0072,  /* U+0072 LATIN SMALL LETTER R */
+        s                           = 0x0073,  /* U+0073 LATIN SMALL LETTER S */
+        t                           = 0x0074,  /* U+0074 LATIN SMALL LETTER T */
+        u                           = 0x0075,  /* U+0075 LATIN SMALL LETTER U */
+        v                           = 0x0076,  /* U+0076 LATIN SMALL LETTER V */
+        w                           = 0x0077,  /* U+0077 LATIN SMALL LETTER W */
+        x                           = 0x0078,  /* U+0078 LATIN SMALL LETTER X */
+        y                           = 0x0079,  /* U+0079 LATIN SMALL LETTER Y */
+        z                           = 0x007a,  /* U+007A LATIN SMALL LETTER Z */
+        braceleft                   = 0x007b,  /* U+007B LEFT CURLY BRACKET */
+        bar                         = 0x007c,  /* U+007C VERTICAL LINE */
+        braceright                  = 0x007d,  /* U+007D RIGHT CURLY BRACKET */
+        asciitilde                  = 0x007e,  /* U+007E TILDE */
+
+        // Extra keys
+
+        XF86AudioMute = 0x1008ff12,
+        XF86AudioLowerVolume = 0x1008ff11,
+        XF86AudioRaiseVolume = 0x1008ff13,
+        XF86PowerOff = 0x1008ff2a,
+        XF86Suspend = 0x1008ffa7,
+        XF86Copy = 0x1008ff57,
+        XF86Paste = 0x1008ff6d,
+        XF86Cut = 0x1008ff58,
+        XF86MenuKB = 0x1008ff65,
+        XF86Calculator = 0x1008ff1d,
+        XF86Sleep = 0x1008ff2f,
+        XF86WakeUp = 0x1008ff2b ,
+        XF86Explorer = 0x1008ff5d,
+        XF86Send = 0x1008ff7b,
+        XF86Xfer = 0x1008ff8a,
+        XF86Launch1 = 0x1008ff41,
+        XF86Launch2 =     0x1008ff42,
+        XF86Launch3 = 0x1008ff43,
+        XF86Launch4 =     0x1008ff44,
+        XF86Launch5 = 0x1008ff45,
+        XF86LaunchA = 0x1008ff4a,
+        XF86LaunchB = 0x1008ff4b,
+        XF86WWW = 0x1008ff2e,
+        XF86DOS = 0x1008ff5a,
+        XF86ScreenSaver = 0x1008ff2d,
+        XF86RotateWindows = 0x1008ff74,
+        XF86Mail = 0x1008ff19,
+        XF86Favorites = 0x1008ff30,
+        XF86MyComputer = 0x1008ff33,
+        XF86Back = 0x1008ff26,
+        XF86Forward = 0x1008ff27 ,
+        XF86Eject = 0x1008ff2c,
+        XF86AudioPlay = 0x1008ff14,
+        XF86AudioStop = 0x1008ff15,
+        XF86AudioPrev = 0x1008ff16,
+        XF86AudioNext = 0x1008ff17,
+        XF86AudioRecord = 0x1008ff1c,
+        XF86AudioPause =0x1008ff31,
+        XF86AudioRewind = 0x1008ff3e,
+        XF86AudioForward = 0x1008ff97,
+        XF86Phone = 0x1008ff6e,
+        XF86Tools = 0x1008ff81,
+        XF86HomePage = 0x1008ff18,
+        XF86Close = 0x1008ff56,
+        XF86Reload = 0x1008ff73,
+        XF86ScrollUp = 0x1008ff78,
+        XF86ScrollDown = 0x1008ff79,
+        XF86New = 0x1008ff68,
+        XF86TouchpadToggle = 0x1008ffa9,
+        XF86WebCam = 0x1008ff8f,
+        XF86Search = 0x1008ff1b,
+        XF86Finance = 0x1008ff3c,
+        XF86Shop = 0x1008ff36,
+        XF86MonBrightnessDown = 0x1008ff03,
+        XF86MonBrightnessUp = 0x1008ff02,
+        XF86AudioMedia = 0x1008ff32,
+        XF86Display = 0x1008ff59,
+        XF86KbdLightOnOff = 0x1008ff04,
+        XF86KbdBrightnessDown = 0x1008ff06,
+        XF86KbdBrightnessUp = 0x1008ff05,
+        XF86Reply = 0x1008ff72,
+        XF86MailForward = 0x1008ff90,
+        XF86Save = 0x1008ff77,
+        XF86Documents = 0x1008ff5b,
+        XF86Battery = 0x1008ff93,
+        XF86Bluetooth = 0x1008ff94,
+        XF86WLAN = 0x1008ff95,
+
+         SunProps = 0x1005ff70,
+         SunOpen = 0x1005ff73,
+    }
+
+    #endregion
+
+#pragma warning disable 1591
+
+    public enum XVisualClass : int
+    {
+        StaticGray = 0,
+        GrayScale = 1,
+        StaticColor = 2,
+        PseudoColor = 3,
+        TrueColor = 4,
+        DirectColor = 5,
+    }
+
+#pragma warning restore 1591
+
+    [Flags]
+    internal enum XVisualInfoMask
+    {
+        No = 0x0,
+        ID = 0x1,
+        Screen = 0x2,
+        Depth = 0x4,
+        Class = 0x8,
+        Red = 0x10,
+        Green = 0x20,
+        Blue = 0x40,
+        ColormapSize = 0x80,
+        BitsPerRGB = 0x100,
+        All = 0x1FF,
+    }
+
+    #region internal enum MouseMask
+
+    internal enum MouseMask
+    {
+        Button1MotionMask = (1 << 8),
+        Button2MotionMask = (1 << 9),
+        Button3MotionMask = (1 << 10),
+        Button4MotionMask = (1 << 11),
+        Button5MotionMask = (1 << 12),
+        Button1Mask = (1 << 8),
+        Button2Mask = (1 << 9),
+        Button3Mask = (1 << 10),
+        Button4Mask = (1 << 11),
+        Button5Mask = (1 << 12),
+        Button6Mask = (1 << 13),
+        Button7Mask = (1 << 14),
+        Button8Mask = (1 << 15),
+        ShiftMask = (1 << 0),
+        LockMask = (1 << 1),
+        ControlMask = (1 << 2),
+        Mod1Mask = (1 << 3),
+        Mod2Mask = (1 << 4),
+        Mod3Mask = (1 << 5),
+        Mod4Mask = (1 << 6),
+        Mod5Mask = (1 << 7),
+    }
+
+    #endregion
+
+    #endregion
+
+    internal static partial class Functions
+    {
+        internal const string X11Library = "libX11";
+        internal const string XcursorLibrary = "libXcursor.so.1";
+
+        #region XCreateWindow
+
+        /// <summary>
+        /// The XCreateWindow function creates an unmapped subwindow for a specified parent window, returns the window ID of the created window, and causes the X server to generate a CreateNotify event. The created window is placed on top in the stacking order with respect to siblings.
+        /// </summary>
+        /// <param name="display">Specifies the connection to the X server.</param>
+        /// <param name="parent">Specifies the parent window.</param>
+        /// <param name="x">Specify the x coordinates, which are the top-left outside corner of the window's borders and are relative to the inside of the parent window's borders.</param>
+        /// <param name="y">Specify the y coordinates, which are the top-left outside corner of the window's borders and are relative to the inside of the parent window's borders.</param>
+        /// <param name="width">Specify the width, which is the created window's inside dimensions and do not include the created window's borders.</param>
+        /// <param name="height">Specify the height, which is the created window's inside dimensions and do not include the created window's borders.</param>
+        /// <param name="border_width">Specifies the width of the created window's border in pixels.</param>
+        /// <param name="depth">Specifies the window's depth. A depth of CopyFromParent means the depth is taken from the parent.</param>
+        /// <param name="class">Specifies the created window's class. You can pass InputOutput, InputOnly, or CopyFromParent. A class of CopyFromParent means the class is taken from the parent.</param>
+        /// <param name="visual">Specifies the visual type. A visual of CopyFromParent means the visual type is taken from the parent.</param>
+        /// <param name="valuemask">Specifies which window attributes are defined in the attributes argument. This mask is the bitwise inclusive OR of the valid attribute mask bits. If valuemask is zero, the attributes are ignored and are not referenced.</param>
+        /// <param name="attributes">Specifies the structure from which the values (as specified by the value mask) are to be taken. The value mask should have the appropriate bits set to indicate which attributes have been set in the structure.</param>
+        /// <returns>The window ID of the created window.</returns>
+        /// <remarks>
+        /// The coordinate system has the X axis horizontal and the Y axis vertical with the origin [0, 0] at the upper-left corner. Coordinates are integral, in terms of pixels, and coincide with pixel centers. Each window and pixmap has its own coordinate system. For a window, the origin is inside the border at the inside, upper-left corner. 
+        /// <para>The border_width for an InputOnly window must be zero, or a BadMatch error results. For class InputOutput, the visual type and depth must be a combination supported for the screen, or a BadMatch error results. The depth need not be the same as the parent, but the parent must not be a window of class InputOnly, or a BadMatch error results. For an InputOnly window, the depth must be zero, and the visual must be one supported by the screen. If either condition is not met, a BadMatch error results. The parent window, however, may have any depth and class. If you specify any invalid window attribute for a window, a BadMatch error results. </para>
+        /// <para>The created window is not yet displayed (mapped) on the user's display. To display the window, call XMapWindow(). The new window initially uses the same cursor as its parent. A new cursor can be defined for the new window by calling XDefineCursor(). The window will not be visible on the screen unless it and all of its ancestors are mapped and it is not obscured by any of its ancestors. </para>
+        /// <para>XCreateWindow can generate BadAlloc BadColor, BadCursor, BadMatch, BadPixmap, BadValue, and BadWindow errors. </para>
+        /// <para>The XCreateSimpleWindow function creates an unmapped InputOutput subwindow for a specified parent window, returns the window ID of the created window, and causes the X server to generate a CreateNotify event. The created window is placed on top in the stacking order with respect to siblings. Any part of the window that extends outside its parent window is clipped. The border_width for an InputOnly window must be zero, or a BadMatch error results. XCreateSimpleWindow inherits its depth, class, and visual from its parent. All other window attributes, except background and border, have their default values. </para>
+        /// <para>XCreateSimpleWindow can generate BadAlloc, BadMatch, BadValue, and BadWindow errors.</para>
+        /// </remarks>
+        public static Window XCreateWindow(Display display, Window parent,
+            int x, int y, int width, int height, int border_width, int depth,
+            CreateWindowArgs @class, IntPtr visual, SetWindowValuemask valuemask,
+            XSetWindowAttributes? attributes)
+        {
+            unsafe
+            {
+                if (attributes.HasValue)
+                {
+                    XSetWindowAttributes attr = attributes.Value;
+                    return XCreateWindow(display, parent, x, y, width, height, border_width, depth,
+                        (int)@class, visual, (IntPtr)valuemask, &attr);
+                }
+                else
+                {
+                    return XCreateWindow(display, parent, x, y, width, height, border_width, depth,
+                        (int)@class, visual, (IntPtr)valuemask, null);
+                }
+            }
+        }
+
+        #endregion
+
+        #region XChangeWindowAttributes
+
+        [DllImport(X11Library)]
+        internal static extern void XChangeWindowAttributes(Display display, Window w, UIntPtr valuemask, ref XSetWindowAttributes attributes);
+
+        internal static void XChangeWindowAttributes(Display display, Window w, SetWindowValuemask valuemask, ref XSetWindowAttributes attributes)
+        {
+            XChangeWindowAttributes(display, w, (UIntPtr)valuemask, ref attributes);
+        }
+
+        #endregion
+
+        #region Xcursor
+
+        [DllImport(XcursorLibrary)]
+        internal static unsafe extern XcursorImage* XcursorImageCreate(int width, int height);
+
+        [DllImport(XcursorLibrary)]
+        internal static unsafe extern void XcursorImageDestroy(XcursorImage* image);
+
+        [DllImport(XcursorLibrary)]
+        internal static unsafe extern Cursor XcursorImageLoadCursor(Display dpy, XcursorImage* image); 
+
+        #endregion
+
+        #region XQueryKeymap
+
+        /*
+        /// <summary>
+        /// The XQueryKeymap() function returns a bit vector for the logical state of the keyboard, where each bit set to 1 indicates that the corresponding key is currently pressed down. The vector is represented as 32 bytes. Byte N (from 0) contains the bits for keys 8N to 8N + 7 with the least-significant bit in the byte representing key 8N.
+        /// </summary>
+        /// <param name="display">Specifies the connection to the X server.</param>
+        /// <param name="keys">Returns an array of bytes that identifies which keys are pressed down. Each bit represents one key of the keyboard.</param>
+        /// <remarks>Note that the logical state of a device (as seen by client applications) may lag the physical state if device event processing is frozen.</remarks>
+        [DllImport(_dll_name, EntryPoint = "XQueryKeymap")]
+        extern public static void XQueryKeymap(IntPtr display, [MarshalAs(UnmanagedType.LPArray, SizeConst = 32), In, Out] Keymap keys);
+        */
+
+        /// <summary>
+        /// The XQueryKeymap() function returns a bit vector for the logical state of the keyboard, where each bit set to 1 indicates that the corresponding key is currently pressed down. The vector is represented as 32 bytes. Byte N (from 0) contains the bits for keys 8N to 8N + 7 with the least-significant bit in the byte representing key 8N.
+        /// </summary>
+        /// <param name="display">Specifies the connection to the X server.</param>
+        /// <param name="keys">Returns an array of bytes that identifies which keys are pressed down. Each bit represents one key of the keyboard.</param>
+        /// <remarks>Note that the logical state of a device (as seen by client applications) may lag the physical state if device event processing is frozen.</remarks>
+        [DllImport(X11Library, EntryPoint = "XQueryKeymap")]
+        extern public static void XQueryKeymap(IntPtr display, byte[] keys);
+
+        #endregion
+
+        #region XMaskEvent
+
+        /// <summary>
+        /// The XMaskEvent() function searches the event queue for the events associated with the specified mask. When it finds a match, XMaskEvent() removes that event and copies it into the specified XEvent structure. The other events stored in the queue are not discarded. If the event you requested is not in the queue, XMaskEvent() flushes the output buffer and blocks until one is received.
+        /// </summary>
+        /// <param name="display">Specifies the connection to the X server.</param>
+        /// <param name="event_mask">Specifies the event mask.</param>
+        /// <param name="e">Returns the matched event's associated structure.</param>
+        [DllImport(X11Library, EntryPoint = "XMaskEvent")]
+        extern public static void XMaskEvent(IntPtr display, EventMask event_mask, ref XEvent e);
+
+        #endregion
+
+        #region XPutBackEvent
+
+        /// <summary>
+        /// The XPutBackEvent() function pushes an event back onto the head of the display's event queue by copying the event into the queue. This can be useful if you read an event and then decide that you would rather deal with it later. There is no limit to the number of times in succession that you can call XPutBackEvent().
+        /// </summary>
+        /// <param name="display">Specifies the connection to the X server.</param>
+        /// <param name="event">Specifies the event.</param>
+        [DllImport(X11Library, EntryPoint = "XPutBackEvent")]
+        public static extern void XPutBackEvent(IntPtr display, ref XEvent @event);
+        
+        #endregion
+
+        #region Xrandr
+
+        const string XrandrLibrary = "libXrandr.so.2";
+
+        [DllImport(XrandrLibrary)]
+        public static extern Bool XRRQueryExtension(Display dpy, ref int event_basep, ref int error_basep);
+
+        [DllImport(XrandrLibrary)]
+        public static extern Status XRRQueryVersion(Display dpy, ref int major_versionp, ref int minor_versionp);
+
+        [DllImport(XrandrLibrary)]
+        public static extern XRRScreenConfiguration XRRGetScreenInfo(Display dpy, Drawable draw);
+
+        [DllImport(XrandrLibrary)]
+        public static extern void XRRFreeScreenConfigInfo(XRRScreenConfiguration config);
+
+        [DllImport(XrandrLibrary)]
+        public static extern Status XRRSetScreenConfig(Display dpy, XRRScreenConfiguration config,
+            Drawable draw, int size_index, Rotation rotation, Time timestamp);
+
+        [DllImport(XrandrLibrary)]
+        public static extern Status XRRSetScreenConfigAndRate(Display dpy, XRRScreenConfiguration config,
+            Drawable draw, int size_index, Rotation rotation, short rate, Time timestamp);
+
+        [DllImport(XrandrLibrary)]
+        public static extern Rotation XRRConfigRotations(XRRScreenConfiguration config, ref Rotation current_rotation);
+
+        [DllImport(XrandrLibrary)]
+        public static extern Time XRRConfigTimes(XRRScreenConfiguration config, ref Time config_timestamp);
+
+        [DllImport(XrandrLibrary)]
+        [return: MarshalAs(UnmanagedType.LPStruct)]
+        public static extern XRRScreenSize XRRConfigSizes(XRRScreenConfiguration config, int[] nsizes);
+
+        [DllImport(XrandrLibrary)]
+        unsafe public static extern short* XRRConfigRates(XRRScreenConfiguration config, int size_index, int[] nrates);
+
+        [DllImport(XrandrLibrary)]
+        public static extern SizeID XRRConfigCurrentConfiguration(XRRScreenConfiguration config, out Rotation rotation);
+
+        [DllImport(XrandrLibrary)]
+        public static extern short XRRConfigCurrentRate(XRRScreenConfiguration config);
+
+        [DllImport(XrandrLibrary)]
+        public static extern int XRRRootToScreen(Display dpy, Window root);
+
+        [DllImport(XrandrLibrary)]
+        public static extern XRRScreenConfiguration XRRScreenConfig(Display dpy, int screen);
+
+        [DllImport(XrandrLibrary)]
+        public static extern XRRScreenConfiguration XRRConfig(ref Screen screen);
+
+        [DllImport(XrandrLibrary)]
+        public static extern void XRRSelectInput(Display dpy, Window window, int mask);
+
+        /*
+         * intended to take RRScreenChangeNotify,  or
+         * ConfigureNotify (on the root window)
+         * returns 1 if it is an event type it understands, 0 if not
+         */
+        [DllImport(XrandrLibrary)]
+        public static extern int XRRUpdateConfiguration(ref XEvent @event);
+
+        /*
+         * the following are always safe to call, even if RandR is
+         * not implemented on a screen
+         */
+        [DllImport(XrandrLibrary)]
+        public static extern Rotation XRRRotations(Display dpy, int screen, ref Rotation current_rotation);
+
+        [DllImport(XrandrLibrary)]
+        unsafe static extern IntPtr XRRSizes(Display dpy, int screen, int* nsizes);
+
+        public static XRRScreenSize[] XRRSizes(Display dpy, int screen)
+        {
+            XRRScreenSize[] sizes;
+            //IntPtr ptr;
+            int count;
+            unsafe
+            {
+                //ptr = XRRSizes(dpy, screen, &nsizes);
+
+                byte* data = (byte*)XRRSizes(dpy, screen, &count);//(byte*)ptr;
+                if (count == 0)
+                    return null;
+                sizes = new XRRScreenSize[count];
+                for (int i = 0; i < count; i++)
+                {
+                    sizes[i] = new XRRScreenSize();
+                    sizes[i] = (XRRScreenSize)Marshal.PtrToStructure((IntPtr)data, typeof(XRRScreenSize));
+                    data += Marshal.SizeOf(typeof(XRRScreenSize));
+                }
+                //XFree(ptr);   // Looks like we must not free this.
+                return sizes;
+            }
+        }
+
+        [DllImport(XrandrLibrary)]
+        unsafe static extern short* XRRRates(Display dpy, int screen, int size_index, int* nrates);
+
+        public static short[] XRRRates(Display dpy, int screen, int size_index)
+        {
+            short[] rates;
+            int count;
+            unsafe
+            {
+                short* data = (short*)XRRRates(dpy, screen, size_index, &count);
+                if (count == 0)
+                    return null;
+                rates = new short[count];
+                for (int i = 0; i < count; i++)
+                    rates[i] = *(data + i);
+            }
+            return rates;
+        }
+
+        [DllImport(XrandrLibrary)]
+        public static extern Time XRRTimes(Display dpy, int screen, out Time config_timestamp);
+
+        #endregion
+
+        #region Display, Screen and Window functions
+
+        #region XScreenCount
+
+        [DllImport(X11Library)]
+        public static extern int XScreenCount(Display display);
+
+        #endregion
+
+        #region XListDepths
+
+        [DllImport(X11Library)]
+        unsafe static extern int *XListDepths(Display display, int screen_number, int* count_return);
+
+        public static int[] XListDepths(Display display, int screen_number)
+        {
+            unsafe
+            {
+                int count;
+                int* data = XListDepths(display, screen_number, &count);
+                if (count == 0)
+                    return null;
+                int[] depths = new int[count];
+                for (int i = 0; i < count; i++)
+                    depths[i] = *(data + i);
+
+                return depths;
+            }
+        }
+
+        #endregion
+
+        #endregion
+
+        public static Pixmap XCreateBitmapFromData(Display display, Window d, byte[,] data)
+        {
+            if (data == null)
+                throw new ArgumentNullException("data");
+
+            unsafe
+            {
+                fixed (byte* pdata = data)
+                {
+                    return XCreateBitmapFromData(display, d, pdata, data.GetLength(0), data.GetLength(1));
+                }
+            }
+        }
+
+        [DllImport(X11Library)]
+        unsafe public static extern Pixmap XCreateBitmapFromData(Display display, Window d, byte* data, int width, int height);
+
+        [DllImport("libX11", EntryPoint = "XAllocColor")]
+        public static extern Status XAllocNamedColor(Display display, Colormap colormap, string color_name, out XColor screen_def_return, out XColor exact_def_return);
+    }
+    /*
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct Keymap
+    {
+        unsafe fixed byte bits[32];
+
+        public bool this[KeyCode key]
+        {
+            get
+            {
+                unsafe
+                {
+                    fixed (Keymap* ptr = &this)
+                    {
+                        return ((ptr->bits[key / 8] >> (key % 8)) & 0x01) != 0;
+                    }
+                }
+            }
+        }
+    }
+    */
+
+    // Helper structure for calling XLock/UnlockDisplay
+    struct XLock : IDisposable
+    {
+        IntPtr _display;
+
+        public IntPtr Display
+        {
+            get
+            {
+                if (_display == IntPtr.Zero)
+                    throw new InvalidOperationException("Internal error (XLockDisplay with IntPtr.Zero). Please report this at http://www.opentk.com/node/add/project-issue/opentk");
+                return _display;
+            }
+            set
+            {
+                if (value == IntPtr.Zero)
+                    throw new ArgumentException();
+                _display = value;
+            }
+        }
+
+        public XLock(IntPtr display)
+            : this()
+        {
+            Display = display;
+            Functions.XLockDisplay(Display);
+        }
+
+        public void Dispose()
+        {
+            Functions.XUnlockDisplay(Display);
+        }
+    }
+
+    // XAllowEvent modes
+    enum EventMode
+    {
+        AsyncPointer = 0,
+        SyncPointer,
+        ReplayPointer,
+        AsyncKeyboard,
+        SyncKeyboard,
+        ReplayKeyboard,
+        AsyncBoth,
+        SyncBoth
+    }
+}
+
+#pragma warning restore 3019
+#pragma warning restore 0649
+#pragma warning restore 0169
+#pragma warning restore 0414
\ No newline at end of file
diff --git a/CrowX/X11/Bindings/DL.cs b/CrowX/X11/Bindings/DL.cs
new file mode 100644 (file)
index 0000000..8311676
--- /dev/null
@@ -0,0 +1,58 @@
+#region License
+//
+// DL.cs
+//
+// Author:
+//       Stefanos A. <stapostol@gmail.com>
+//
+// Copyright (c) 2006-2014 Stefanos Apostolopoulos
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace X11Sharp
+{
+    class DL
+    {
+        const string lib = "dl";
+
+        [DllImport(lib, EntryPoint = "dlopen")]
+        internal static extern IntPtr Open(string filename, DLOpenFlags flags);
+
+        [DllImport(lib, EntryPoint = "dlclose")]
+        internal static extern int Close(IntPtr handle);
+
+        [DllImport(lib, EntryPoint = "dlsym")]
+        internal static extern IntPtr Symbol(IntPtr handle, IntPtr name);
+    }
+
+    enum DLOpenFlags
+    {
+        Lazy = 0x0001,
+        Now = 0x0002,
+        Global = 0x0100,
+        Local = 0x0000,
+    }
+}
diff --git a/CrowX/X11/Bindings/Glx.cs b/CrowX/X11/Bindings/Glx.cs
new file mode 100644 (file)
index 0000000..624e50e
--- /dev/null
@@ -0,0 +1,516 @@
+#region --- License ---
+/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
+ * Contributions from Erik Ylvisaker
+ * See license.txt for license info
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Security;
+
+#pragma warning disable 1591
+
+namespace X11Sharp
+{
+    #region Enums
+
+    enum GLXAttribute : int
+    {
+        TRANSPARENT_BLUE_VALUE_EXT = 0x27,
+        GRAY_SCALE = 0x8006,
+        RGBA_TYPE = 0x8014,
+        TRANSPARENT_RGB_EXT = 0x8008,
+        ACCUM_BLUE_SIZE = 16,
+        SHARE_CONTEXT_EXT = 0x800A,
+        STEREO = 6,
+        ALPHA_SIZE = 11,
+        FLOAT_COMPONENTS_NV = 0x20B0,
+        NONE = 0x8000,
+        DEPTH_SIZE = 12,
+        TRANSPARENT_INDEX_VALUE_EXT = 0x24,
+        MAX_PBUFFER_WIDTH_SGIX = 0x8016,
+        GREEN_SIZE = 9,
+        X_RENDERABLE_SGIX = 0x8012,
+        LARGEST_PBUFFER = 0x801C,
+        DONT_CARE = unchecked((int)0xFFFFFFFF),
+        TRANSPARENT_ALPHA_VALUE_EXT = 0x28,
+        PSEUDO_COLOR_EXT = 0x8004,
+        USE_GL = 1,
+        SAMPLE_BUFFERS_SGIS = 100000,
+        TRANSPARENT_GREEN_VALUE_EXT = 0x26,
+        HYPERPIPE_ID_SGIX = 0x8030,
+        COLOR_INDEX_TYPE_SGIX = 0x8015,
+        SLOW_CONFIG = 0x8001,
+        PRESERVED_CONTENTS = 0x801B,
+        ACCUM_RED_SIZE = 14,
+        EVENT_MASK = 0x801F,
+        VISUAL_ID_EXT = 0x800B,
+        EVENT_MASK_SGIX = 0x801F,
+        SLOW_VISUAL_EXT = 0x8001,
+        TRANSPARENT_GREEN_VALUE = 0x26,
+        MAX_PBUFFER_WIDTH = 0x8016,
+        DIRECT_COLOR_EXT = 0x8003,
+        VISUAL_ID = 0x800B,
+        ACCUM_GREEN_SIZE = 15,
+        DRAWABLE_TYPE_SGIX = 0x8010,
+        SCREEN_EXT = 0x800C,
+        SAMPLES = 100001,
+        HEIGHT = 0x801E,
+        TRANSPARENT_INDEX_VALUE = 0x24,
+        SAMPLE_BUFFERS_ARB = 100000,
+        PBUFFER = 0x8023,
+        RGBA_TYPE_SGIX = 0x8014,
+        MAX_PBUFFER_HEIGHT = 0x8017,
+        FBCONFIG_ID_SGIX = 0x8013,
+        DRAWABLE_TYPE = 0x8010,
+        SCREEN = 0x800C,
+        RED_SIZE = 8,
+        VISUAL_SELECT_GROUP_SGIX = 0x8028,
+        VISUAL_CAVEAT_EXT = 0x20,
+        PSEUDO_COLOR = 0x8004,
+        PBUFFER_HEIGHT = 0x8040,
+        STATIC_GRAY = 0x8007,
+        PRESERVED_CONTENTS_SGIX = 0x801B,
+        RGBA_FLOAT_TYPE_ARB = 0x20B9,
+        TRANSPARENT_RED_VALUE = 0x25,
+        TRANSPARENT_ALPHA_VALUE = 0x28,
+        WINDOW = 0x8022,
+        X_RENDERABLE = 0x8012,
+        STENCIL_SIZE = 13,
+        TRANSPARENT_RGB = 0x8008,
+        LARGEST_PBUFFER_SGIX = 0x801C,
+        STATIC_GRAY_EXT = 0x8007,
+        TRANSPARENT_BLUE_VALUE = 0x27,
+        DIGITAL_MEDIA_PBUFFER_SGIX = 0x8024,
+        BLENDED_RGBA_SGIS = 0x8025,
+        NON_CONFORMANT_VISUAL_EXT = 0x800D,
+        COLOR_INDEX_TYPE = 0x8015,
+        TRANSPARENT_RED_VALUE_EXT = 0x25,
+        GRAY_SCALE_EXT = 0x8006,
+        WINDOW_SGIX = 0x8022,
+        X_VISUAL_TYPE = 0x22,
+        MAX_PBUFFER_HEIGHT_SGIX = 0x8017,
+        DOUBLEBUFFER = 5,
+        OPTIMAL_PBUFFER_WIDTH_SGIX = 0x8019,
+        X_VISUAL_TYPE_EXT = 0x22,
+        WIDTH_SGIX = 0x801D,
+        STATIC_COLOR_EXT = 0x8005,
+        BUFFER_SIZE = 2,
+        DIRECT_COLOR = 0x8003,
+        MAX_PBUFFER_PIXELS = 0x8018,
+        NONE_EXT = 0x8000,
+        HEIGHT_SGIX = 0x801E,
+        RENDER_TYPE = 0x8011,
+        FBCONFIG_ID = 0x8013,
+        TRANSPARENT_INDEX_EXT = 0x8009,
+        TRANSPARENT_INDEX = 0x8009,
+        TRANSPARENT_TYPE_EXT = 0x23,
+        ACCUM_ALPHA_SIZE = 17,
+        PBUFFER_SGIX = 0x8023,
+        MAX_PBUFFER_PIXELS_SGIX = 0x8018,
+        OPTIMAL_PBUFFER_HEIGHT_SGIX = 0x801A,
+        DAMAGED = 0x8020,
+        SAVED_SGIX = 0x8021,
+        TRANSPARENT_TYPE = 0x23,
+        MULTISAMPLE_SUB_RECT_WIDTH_SGIS = 0x8026,
+        NON_CONFORMANT_CONFIG = 0x800D,
+        BLUE_SIZE = 10,
+        TRUE_COLOR_EXT = 0x8002,
+        SAMPLES_SGIS = 100001,
+        SAMPLES_ARB = 100001,
+        TRUE_COLOR = 0x8002,
+        RGBA = 4,
+        AUX_BUFFERS = 7,
+        SAMPLE_BUFFERS = 100000,
+        SAVED = 0x8021,
+        MULTISAMPLE_SUB_RECT_HEIGHT_SGIS = 0x8027,
+        DAMAGED_SGIX = 0x8020,
+        STATIC_COLOR = 0x8005,
+        PBUFFER_WIDTH = 0x8041,
+        WIDTH = 0x801D,
+        LEVEL = 3,
+        CONFIG_CAVEAT = 0x20,
+        RENDER_TYPE_SGIX = 0x8011,
+        SWAP_INTERVAL_EXT = 0x20F1,
+        MAX_SWAP_INTERVAL_EXT = 0x20F2,
+    }
+
+    enum GLXHyperpipeAttrib : int
+    {
+        PIPE_RECT_LIMITS_SGIX = 0x00000002,
+        PIPE_RECT_SGIX = 0x00000001,
+        HYPERPIPE_STEREO_SGIX = 0x00000003,
+        HYPERPIPE_PIXEL_AVERAGE_SGIX = 0x00000004,
+    }
+
+    enum GLXStringName : int
+    {
+        EXTENSIONS = 0x3,
+        VERSION = 0x2,
+        VENDOR = 0x1,
+    }
+
+    enum GLXEventMask : int
+    {
+        PBUFFER_CLOBBER_MASK = 0x08000000,
+        BUFFER_CLOBBER_MASK_SGIX = 0x08000000,
+    }
+
+    enum GLXRenderTypeMask : int
+    {
+        COLOR_INDEX_BIT_SGIX = 0x00000002,
+        RGBA_BIT = 0x00000001,
+        RGBA_FLOAT_BIT_ARB = 0x00000004,
+        RGBA_BIT_SGIX = 0x00000001,
+        COLOR_INDEX_BIT = 0x00000002,
+    }
+
+    enum GLXHyperpipeTypeMask : int
+    {
+        HYPERPIPE_RENDER_PIPE_SGIX = 0x00000002,
+        HYPERPIPE_DISPLAY_PIPE_SGIX = 0x00000001,
+    }
+
+    enum GLXPbufferClobberMask : int
+    {
+        ACCUM_BUFFER_BIT_SGIX = 0x00000080,
+        FRONT_LEFT_BUFFER_BIT = 0x00000001,
+        BACK_RIGHT_BUFFER_BIT = 0x00000008,
+        FRONT_RIGHT_BUFFER_BIT_SGIX = 0x00000002,
+        STENCIL_BUFFER_BIT_SGIX = 0x00000040,
+        SAMPLE_BUFFERS_BIT_SGIX = 0x00000100,
+        STENCIL_BUFFER_BIT = 0x00000040,
+        BACK_RIGHT_BUFFER_BIT_SGIX = 0x00000008,
+        BACK_LEFT_BUFFER_BIT_SGIX = 0x00000004,
+        AUX_BUFFERS_BIT = 0x00000010,
+        DEPTH_BUFFER_BIT_SGIX = 0x00000020,
+        ACCUM_BUFFER_BIT = 0x00000080,
+        AUX_BUFFERS_BIT_SGIX = 0x00000010,
+        DEPTH_BUFFER_BIT = 0x00000020,
+        FRONT_LEFT_BUFFER_BIT_SGIX = 0x00000001,
+        BACK_LEFT_BUFFER_BIT = 0x00000004,
+        FRONT_RIGHT_BUFFER_BIT = 0x00000002,
+    }
+
+    enum GLXHyperpipeMisc : int
+    {
+        HYPERPIPE_PIPE_NAME_LENGTH_SGIX = 80,
+    }
+
+    enum GLXErrorCode : int
+    {
+        BAD_CONTEXT = 5,
+        NO_EXTENSION = 3,
+        BAD_HYPERPIPE_SGIX = 92,
+        BAD_ENUM = 7,
+        BAD_SCREEN = 1,
+        BAD_VALUE = 6,
+        BAD_ATTRIBUTE = 2,
+        BAD_VISUAL = 4,
+        BAD_HYPERPIPE_CONFIG_SGIX = 91,
+    }
+
+    enum GLXSyncType : int
+    {
+        SYNC_SWAP_SGIX = 0x00000001,
+        SYNC_FRAME_SGIX = 0x00000000,
+    }
+
+    enum GLXDrawableTypeMask : int
+    {
+        WINDOW_BIT = 0x00000001,
+        PIXMAP_BIT = 0x00000002,
+        PBUFFER_BIT_SGIX = 0x00000004,
+        PBUFFER_BIT = 0x00000004,
+        WINDOW_BIT_SGIX = 0x00000001,
+        PIXMAP_BIT_SGIX = 0x00000002,
+    }
+
+    enum ArbCreateContext : int
+    {
+        DebugBit = 0x0001,
+        ForwardCompatibleBit = 0x0002,
+        CoreProfileBit = 0x00000001,
+        CompatibilityProfileBit = 0x00000002,
+        MajorVersion = 0x2091,
+        MinorVersion = 0x2092,
+        LayerPlane = 0x2093,
+        Flags = 0x2094,
+        ErrorInvalidVersion = 0x2095,
+        ProfileMask = 0x9126
+    }
+
+    enum ErrorCode : int
+    {
+        NO_ERROR       = 0,
+        BAD_SCREEN     = 1,   /* screen # is bad */
+        BAD_ATTRIBUTE  = 2,   /* attribute to get is bad */
+        NO_EXTENSION   = 3,   /* no glx extension on server */
+        BAD_VISUAL     = 4,   /* visual # not known by GLX */
+        BAD_CONTEXT    = 5,   /* returned only by import_context EXT? */
+        BAD_VALUE      = 6,   /* returned only by glXSwapIntervalSGI? */
+        BAD_ENUM       = 7,   /* unused? */
+    }
+
+    #endregion
+
+    /// \internal
+    /// <summary>
+    /// Provides access to GLX functions.
+    /// </summary>
+    class Glx : Graphics.GraphicsBindingsBase
+    {
+        const string Library = "libGL.so.1";
+        static readonly object sync_root = new object();
+
+        static readonly byte[] EntryPointNames = new byte[]
+        {
+            // glXCreateContextAttribsARB
+            0x67, 0x6c, 0x58, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x73, 0x41, 0x52, 0x42, 0,
+            // glXSwapIntervalEXT
+            0x67, 0x6c, 0x58, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x45, 0x58, 0x54, 0,
+            // glXSwapIntervalMESA
+            0x67, 0x6c, 0x58, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x45, 0x53, 0x41, 0,
+            // glXGetSwapIntervalMESA
+            0x67, 0x6c, 0x58, 0x47, 0x65, 0x74, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x45, 0x53, 0x41, 0,
+            // glXSwapIntervalSGI
+            0x67, 0x6c, 0x58, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x53, 0x47, 0x49, 0,
+        };
+        static readonly int[] EntryPointOffsets = new int[5];
+        static IntPtr[] EntryPoints = new IntPtr[5];
+
+        internal Glx()
+        {
+            // GLX entry points are not bound to a context.
+            // This means we can load them without creating
+            // a context first! (unlike WGL)
+            _EntryPointsInstance = EntryPoints;
+            _EntryPointNamesInstance = EntryPointNames;
+            _EntryPointNameOffsetsInstance = EntryPointOffsets;
+
+            // Writing the entry point name offsets
+            // by hand is error prone. Do it in code
+            // instead:
+            int offset = 0;
+            for (int i = 0, j = 0; i < EntryPointNames.Length; i++)
+            {
+                if (EntryPointNames[i] == 0)
+                {
+                    EntryPointOffsets[j++] = offset;
+                    offset = i + 1;
+                }
+            }
+        }
+
+        protected override object SyncRoot { get { return sync_root; } }
+
+        protected override IntPtr GetAddress(string funcname)
+        {
+            return Arb.GetProcAddress(funcname);
+        }
+
+        internal override void LoadEntryPoints()
+        {
+            unsafe
+            {
+                fixed (byte* name = _EntryPointNamesInstance)
+                {
+                    for (int i = 0; i < _EntryPointsInstance.Length; i++)
+                    {
+                        _EntryPointsInstance[i] = Arb.GetProcAddress(
+                            new IntPtr(name + _EntryPointNameOffsetsInstance[i]));
+                    }
+                }
+            }
+        }
+
+        internal static bool SupportsFunction(string name)
+        {
+            int index = Array.IndexOf(EntryPointNames, name);
+            if (index >= 0)
+            {
+                return EntryPoints[index] != IntPtr.Zero;
+            }
+            return false;
+        }
+
+        #region GLX functions
+
+        [DllImport(Library, EntryPoint = "glXIsDirect")]
+        public static extern bool IsDirect(IntPtr dpy, IntPtr context);
+
+        [DllImport(Library, EntryPoint = "glXQueryDrawable")]
+        public static extern ErrorCode QueryDrawable(IntPtr dpy, IntPtr drawable, GLXAttribute attribute, out int value);
+
+        [DllImport(Library, EntryPoint = "glXQueryExtension")]
+        public static extern bool QueryExtension(IntPtr dpy, out int errorBase, out int eventBase);
+
+        [DllImport(Library, EntryPoint = "glXQueryExtensionsString")]
+        static extern IntPtr QueryExtensionsStringInternal(IntPtr dpy, int screen);
+
+        public static string QueryExtensionsString(IntPtr dpy, int screen)
+        {
+            return Marshal.PtrToStringAnsi(QueryExtensionsStringInternal(dpy, screen));
+        }
+
+        [DllImport(Library, EntryPoint = "glXQueryVersion")]
+        public static extern bool QueryVersion(IntPtr dpy, out int major, out int minor);
+
+        [DllImport(Library, EntryPoint = "glXCreateContext")]
+        public static extern IntPtr CreateContext(IntPtr dpy, IntPtr vis, IntPtr shareList, bool direct);
+
+        [DllImport(Library, EntryPoint = "glXCreateContext")]
+        public static extern IntPtr CreateContext(IntPtr dpy, ref XVisualInfo vis, IntPtr shareList, bool direct);
+    
+        [DllImport(Library, EntryPoint = "glXDestroyContext")]
+        public static extern void DestroyContext(IntPtr dpy, IntPtr context);
+
+        public static void DestroyContext(IntPtr dpy, ContextHandle context)
+        {
+            DestroyContext(dpy, context.Handle);
+        }
+
+        [DllImport(Library, EntryPoint = "glXGetCurrentContext")]
+        public static extern IntPtr GetCurrentContext();
+
+        [DllImport(Library, EntryPoint = "glXMakeCurrent")]
+        public static extern bool MakeCurrent(IntPtr display, IntPtr drawable, IntPtr context);
+
+        public static bool MakeCurrent(IntPtr display, IntPtr drawable, ContextHandle context)
+        {
+            return MakeCurrent(display, drawable, context.Handle);
+        }
+
+        [DllImport(Library, EntryPoint = "glXSwapBuffers")]
+        public static extern void SwapBuffers(IntPtr display, IntPtr drawable);
+
+        [DllImport(Library, EntryPoint = "glXGetProcAddress")]
+        public static extern IntPtr GetProcAddress([MarshalAs(UnmanagedType.LPTStr)] string procName);
+
+        [DllImport(Library, EntryPoint = "glXGetProcAddress")]
+        public static extern IntPtr GetProcAddress(IntPtr procName);
+
+        [DllImport(Library, EntryPoint = "glXGetConfig")]
+        public static extern int GetConfig(IntPtr dpy, ref XVisualInfo vis, GLXAttribute attrib, out int value);
+
+        #region glXChooseVisual
+
+        [DllImport(Library, EntryPoint = "glXChooseVisual")]
+        public extern static IntPtr ChooseVisual(IntPtr dpy, int screen, IntPtr attriblist);
+
+        [DllImport(Library, EntryPoint = "glXChooseVisual")]
+        public extern static IntPtr ChooseVisual(IntPtr dpy, int screen, ref int attriblist);
+
+        public static IntPtr ChooseVisual(IntPtr dpy, int screen, int[] attriblist)
+        {
+            unsafe
+            {
+                fixed (int* attriblist_ptr = attriblist)
+                {
+                    return ChooseVisual(dpy, screen, (IntPtr)attriblist_ptr);
+                }
+            }
+        }
+
+        // Returns an array of GLXFBConfig structures.
+        [DllImport(Library, EntryPoint = "glXChooseFBConfig")]
+        unsafe public extern static IntPtr* ChooseFBConfig(IntPtr dpy, int screen, int[] attriblist, out int fbount);
+
+        // Returns a pointer to an XVisualInfo structure.
+        [DllImport(Library, EntryPoint = "glXGetVisualFromFBConfig")]
+        public unsafe extern static IntPtr GetVisualFromFBConfig(IntPtr dpy, IntPtr fbconfig);
+
+        #endregion
+
+        public partial class Arb
+        {
+            #region CreateContextAttribs
+
+            [AutoGenerated(EntryPoint = "glXCreateContextAttribsARB")]
+            unsafe public static IntPtr CreateContextAttribs(IntPtr display, IntPtr fbconfig, IntPtr share_context, bool direct, int* attribs)
+            {
+                throw new NotImplementedException();
+            }
+
+            [AutoGenerated(EntryPoint = "glXCreateContextAttribsARB")]
+            public static IntPtr CreateContextAttribs(IntPtr display, IntPtr fbconfig, IntPtr share_context, bool direct, int[] attribs)
+            {
+                throw new NotImplementedException();
+            }
+
+            #endregion
+
+            #region GetProcAddress
+
+            // The linux OpenGL ABI 3.6 (1999) requires
+            // that glXGetProcAddressARB be available as
+            // a static export. The same is *not* true
+            // for glXGetProcAddress, so we should use
+            // glXGetProcAddressARB instead.
+            // See http://www.opengl.org/registry/ABI/
+            [DllImport(Library, EntryPoint = "glXGetProcAddressARB")]
+            public static extern IntPtr GetProcAddress([MarshalAs(UnmanagedType.LPTStr)] string procName);
+
+            [DllImport(Library, EntryPoint = "glXGetProcAddressARB")]
+            public static extern IntPtr GetProcAddress(IntPtr procName);
+
+            #endregion
+        }
+
+        public partial class Ext
+        {
+            [AutoGenerated(EntryPoint = "glXSwapIntervalEXT")]
+            public static ErrorCode SwapInterval(IntPtr display, IntPtr drawable, int interval)
+            {
+                throw new NotImplementedException();
+            }
+        }
+
+        public partial class Mesa
+        {
+            [AutoGenerated(EntryPoint = "glXSwapIntervalMESA")]
+            public static ErrorCode SwapInterval(int interval)
+            {
+                throw new NotImplementedException();
+            }
+
+            [AutoGenerated(EntryPoint = "glXGetSwapIntervalMESA")]
+            public static int GetSwapInterval()
+            {
+                throw new NotImplementedException();
+            }
+        }
+
+        public partial class Sgi
+        {
+            [AutoGenerated(EntryPoint = "glXSwapIntervalSGI")]
+            public static ErrorCode SwapInterval(int interval)
+            {
+                throw new NotImplementedException();
+            }
+        }
+
+        [Slot(0)]
+        [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
+        internal unsafe static extern IntPtr glXCreateContextAttribsARB(IntPtr display, IntPtr fbconfig, IntPtr share_context, bool direct, int* attribs);
+        [Slot(1)]
+        [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
+        internal static extern ErrorCode glXSwapIntervalEXT(IntPtr display, IntPtr drawable, int interval);
+        [Slot(2)]
+        [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
+        internal static extern ErrorCode glXSwapIntervalMESA(int interval);
+        [Slot(3)]
+        [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
+        internal static extern int glXGetSwapIntervalMESA();
+        [Slot(4)]
+        [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
+        internal static extern ErrorCode glXSwapIntervalSGI(int interval);
+
+        #endregion
+    }
+}
+
+#pragma warning restore 1591
\ No newline at end of file
diff --git a/CrowX/X11/Bindings/INotify.cs b/CrowX/X11/Bindings/INotify.cs
new file mode 100644 (file)
index 0000000..566b13a
--- /dev/null
@@ -0,0 +1,210 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace X11Sharp
+{
+    // Fully implemented but not currently used by OpenTK
+    // See System.IO.FileSystemWatcher for a cross-platform alternative
+#if false
+    class INotify
+    {
+        const string lib = "";
+
+        /// <summary>
+        /// Create and initialize inotify instance
+        /// </summary>
+        /// <returns></returns>
+        [DllImport(lib, EntryPoint = "inotify_init", ExactSpelling = true)]
+        public static extern int Init();
+
+        /// <summary>
+        /// Create and initialize inotify instance with specified flags
+        /// </summary>
+        /// <param name="flags">See <see cref="INotifyInitFlags"/></param>
+        /// <returns>A <c>System.Int32</c> handle to a inotify instance</returns>
+        [DllImport(lib, EntryPoint = "inotify_init1", ExactSpelling = true)]
+        public static extern int Init(INotifyFlags flags);
+
+        /// <summary>
+        /// Add watch of object pathname to inotify instance fd. Notify about
+        /// events specified by mask
+        /// </summary>
+        [DllImport(lib, EntryPoint = "inotify_add_watch", ExactSpelling = true)]
+        public static extern int AddWatch(int fd, string pathname, INotifyFlags mask);
+
+        /// <summary>
+        /// Remove the watch specified by wd from the inotify instance fd
+        /// </summary>
+        [DllImport(lib, EntryPoint = "inotify_rm_watch", ExactSpelling = true)]
+        public static extern int RemoveWatch(int fd, int wd);
+    }
+
+    /// <summary>
+    /// Describes an INotify event
+    /// </summary>
+    struct INotifyEvent
+    {
+        /// <summary>
+        /// Watch descriptor for wd parameter of INotify methods
+        /// </summary>
+        public int WatchDescriptor;
+
+        /// <summary>
+        /// Watch mask for mask parameter of INotify methods
+        /// </summary>
+        public INotifyFlags WatchMask;
+
+        /// <summary>
+        /// Cookie to synchronize two events
+        /// </summary>
+        public uint Cookie;
+
+        /// <summary>
+        /// Length (including NULs) of name
+        /// </summary>
+        public uint Length;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public IntPtr Name;
+    }
+
+    /// <summary>
+    /// Flags for the parameter of <see cref="INotify.Init(INotifyFlags)"/>
+    /// </summary>
+    [Flags]
+    enum INotifyInitFlags
+    {
+        CloExec = 02000000,
+        NonBlock = 04000
+    }
+
+    /// \internal
+    /// <summary>
+    /// Supported events suitable for MASK parameter of AddWatch.
+    /// </summary>
+    [Flags]
+    enum INotifyFlags
+    {
+        /// <summary>
+        /// File was accessed
+        /// </summary>
+        Access = 0x00000001,
+
+        /// <summary>
+        /// File was modified
+        /// </summary>
+        Modify = 0x00000002,
+
+        /// <summary>
+        /// Metadata changed
+        /// </summary>
+        Attrib = 0x00000004,
+
+        /// <summary>
+        /// Writable file was closed
+        /// </summary>
+        CloseWrite = 0x00000008,
+
+        /// <summary>
+        /// Unwritable file closed
+        /// </summary>
+        CloseNoWrite = 0x00000010,
+
+        /// <summary>
+        /// File closed
+        /// </summary>
+        Close = CloseWrite | CloseNoWrite,
+
+        /// <summary>
+        /// File was opened
+        /// </summary>
+        Open = 0x00000020,
+
+        /// <summary>
+        /// File was moved from X
+        /// </summary>
+        MovedFrom = 0x00000040,
+
+        /// <summary>
+        /// File was moved to Y
+        /// </summary>
+        MovedTo = 0x00000080,
+
+        /// <summary>
+        /// File was moved
+        /// </summary>
+        Move = MovedFrom | MovedTo,
+
+        /// <summary>
+        /// Subfile was created
+        /// </summary>
+        Create = 0x00000100,
+
+        /// <summary>
+        /// Subfile was deleted
+        /// </summary>
+        Delete = 0x00000200,
+
+        /// <summary>
+        /// Self was deleted
+        /// </summary>
+        DeleteSelf = 0x00000400,
+
+        /// <summary>
+        /// Self was moved
+        /// </summary>
+        MoveSelf = 0x00000800,
+
+        /// <summary>
+        /// Backing fs was unmounted
+        /// </summary>
+        Unmount = 0x00002000,
+
+        /// <summary>
+        /// Event queue overflowed
+        /// </summary>
+        QueueOverflow = 0x00004000,
+
+        /// <summary>
+        /// File was ignored
+        /// </summary>
+        Ignored = 0x00008000,
+
+        /// <summary>
+        /// Only watch the path if it is a directory
+        /// </summary>
+        OnlyDirectory = 0x01000000,
+
+        /// <summary>
+        /// Do not follow symlinks
+        /// </summary>
+        DontFollow = 0x02000000,
+
+        /// <summary>
+        /// Add to the mask of an already existing watch
+        /// </summary>
+        MaskAdd = 0x20000000,
+
+        /// <summary>
+        /// Event occurred against dir
+        /// </summary>
+        IsDirectory = 0x40000000,
+
+        /// <summary>
+        /// Only send event once
+        /// </summary>
+        Oneshot = 0x80000000,
+
+        /// <summary>
+        /// All events which a program can wait on
+        /// </summary>
+        AllEvents =
+            Access | Modify | Attrib | Close | Open | Move |
+            Create | Delete | DeleteSelf | MoveSelf
+    }
+#endif
+}
diff --git a/CrowX/X11/Bindings/XI.cs b/CrowX/X11/Bindings/XI.cs
new file mode 100644 (file)
index 0000000..98a80f3
--- /dev/null
@@ -0,0 +1,145 @@
+#region License
+//
+// The Open Toolkit Library License
+//
+// Copyright (c) 2006 - 2014 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.
+//
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace X11Sharp
+{
+    using Bool = Boolean;
+    using Cursor = IntPtr;
+    using Display = IntPtr;
+    using Status = ErrorCodes;
+    using Time = IntPtr;
+    using Window = IntPtr;
+
+    // Bindings for the XInput2 extension
+    class XI
+    {
+        const string lib = "libXi";
+
+        internal const int XIAllDevices = 0;
+        internal const int XIAllMasterDevices = 1;
+
+        // mouse
+        internal static readonly IntPtr ButtonLeft = Functions.XInternAtom(API.DefaultDisplay, "Button Left", false);
+        internal static readonly IntPtr ButtonMiddle = Functions.XInternAtom(API.DefaultDisplay, "Button Middle", false);
+        internal static readonly IntPtr ButtonRight = Functions.XInternAtom(API.DefaultDisplay, "Button Right", false);
+        internal static readonly IntPtr ButtonWheelUp = Functions.XInternAtom(API.DefaultDisplay, "Button Wheel Up", false);
+        internal static readonly IntPtr ButtonWheelDown = Functions.XInternAtom(API.DefaultDisplay, "Button Wheel Down", false);
+        internal static readonly IntPtr ButtonWheelLeft = Functions.XInternAtom(API.DefaultDisplay, "Button Horiz Wheel Left", false);
+        internal static readonly IntPtr ButtonWheelRight = Functions.XInternAtom(API.DefaultDisplay, "Button Horiz Wheel Right", false);
+        internal static readonly IntPtr RelativeX = Functions.XInternAtom(API.DefaultDisplay, "Rel X", false);
+        internal static readonly IntPtr RelativeY = Functions.XInternAtom(API.DefaultDisplay, "Rel Y", false);
+        internal static readonly IntPtr RelativeHWheel = Functions.XInternAtom(API.DefaultDisplay, "Rel Horiz Wheel", false);
+        internal static readonly IntPtr RelativeVWheel = Functions.XInternAtom(API.DefaultDisplay, "Rel Vert Wheel", false);
+        internal static readonly IntPtr RelativeHScroll = Functions.XInternAtom(API.DefaultDisplay, "Rel Horiz Scroll", false);
+        internal static readonly IntPtr RelativeVScroll = Functions.XInternAtom(API.DefaultDisplay, "Rel Vert Scroll", false);
+
+        // multitouch
+        internal static readonly IntPtr TouchX = Functions.XInternAtom(API.DefaultDisplay, "Abs MT Position X", false);
+        internal static readonly IntPtr TouchY = Functions.XInternAtom(API.DefaultDisplay, "Abs MT Position Y", false);
+        internal static readonly IntPtr TouchMajor = Functions.XInternAtom(API.DefaultDisplay, "Abs MT Touch Major", false);
+        internal static readonly IntPtr TouchMinor = Functions.XInternAtom(API.DefaultDisplay, "Abs MT Touch Minor", false);
+        internal static readonly IntPtr TouchPressure = Functions.XInternAtom(API.DefaultDisplay, "Abs MT Pressure", false);
+        internal static readonly IntPtr TouchId = Functions.XInternAtom(API.DefaultDisplay, "Abs MT Tracking ID", false);
+        internal static readonly IntPtr TouchMaxContacts = Functions.XInternAtom(API.DefaultDisplay, "Max Contacts", false);
+
+        // tablet
+        internal static readonly IntPtr AbsoluteX = Functions.XInternAtom(API.DefaultDisplay, "Abs X", false);
+        internal static readonly IntPtr AbsoluteY = Functions.XInternAtom(API.DefaultDisplay, "Abs Y", false);
+        internal static readonly IntPtr AbsolutePressure = Functions.XInternAtom(API.DefaultDisplay, "Abs Pressure", false);
+        internal static readonly IntPtr AbsoluteTiltX = Functions.XInternAtom(API.DefaultDisplay, "Abs Tilt X", false);
+        internal static readonly IntPtr AbsoluteTiltY = Functions.XInternAtom(API.DefaultDisplay, "Abs Tilt Y", false);
+        internal static readonly IntPtr AbsoluteWheel = Functions.XInternAtom(API.DefaultDisplay, "Abs Wheel", false);
+        internal static readonly IntPtr AbsoluteDistance = Functions.XInternAtom(API.DefaultDisplay, "Abs Distance", false);
+
+        [DllImport(lib, EntryPoint = "XISelectEvents")]
+        static extern int SelectEvents(IntPtr dpy, Window win, [In] XIEventMask[] masks, int num_masks);
+        
+        [DllImport(lib, EntryPoint = "XISelectEvents")]
+        static extern int SelectEvents(IntPtr dpy, Window win, [In] ref XIEventMask masks, int num_masks);
+
+        public static int SelectEvents(IntPtr dpy, Window win, XIEventMask[] masks)
+        {
+            return SelectEvents(dpy, win, masks, masks.Length);
+        }
+
+        public static int SelectEvents(IntPtr dpy, Window win, XIEventMask mask)
+        {
+            return SelectEvents(dpy, win, ref mask, 1);
+        }
+
+        [DllImport(lib, EntryPoint = "XIGrabDevice")]
+        static extern Status GrabDevice(IntPtr display, int deviceid, Window grab_window, Time time,
+            Cursor cursor, int grab_mode, int paired_device_mode, Bool owner_events, XIEventMask[] mask);
+
+        [DllImport(lib, EntryPoint = "XIUngrabDevice")]
+        static extern Status UngrabDevice(IntPtr display, int deviceid, Time time);
+
+        [DllImport(lib, EntryPoint = "XIWarpPointer")]
+        public static extern Bool XIWarpPointer(Display display,
+            int deviceid, Window src_w, Window dest_w,
+            double src_x, double src_y, int src_width, int src_height,
+            double dest_x, double dest_y);
+
+        [DllImport(lib, EntryPoint = "XIQueryDevice")]
+        public static extern IntPtr QueryDevice(Display display, int id, out int count);
+
+        [DllImport(lib, EntryPoint = "XIFreeDeviceInfo")]
+        public static extern void FreeDeviceInfo(IntPtr devices);
+
+        [DllImport(lib, EntryPoint = "XIQueryPointer")]
+        public static extern Bool QueryPointer(Display display,
+            int deviceid, Window win,
+            out Window root_return, out Window child_return,
+            out double root_x_return, out double root_y_return,
+            out double win_x_return, out double win_y_return,
+            out XIButtonState buttons_return, out XIModifierState modifiers_return,
+            out XIGroupState group_return);
+
+        [DllImport(lib, EntryPoint = "XIQueryVersion")]
+        internal static extern Status QueryVersion(Display display, ref int major, ref int minor);
+    }
+
+    enum XIDeviceType
+    {
+        MasterPointer = 1,
+        MasterKeyboard = 2,
+        SlavePointer = 3,
+        SlaveKeyboard = 4,
+        FloatingSlave = 5,
+    }
+
+    enum XIMode
+    {
+        Relative = 0,
+        Absolute = 1
+    }
+}
diff --git a/CrowX/X11/Bindings/Xkb.cs b/CrowX/X11/Bindings/Xkb.cs
new file mode 100644 (file)
index 0000000..a00a4f5
--- /dev/null
@@ -0,0 +1,304 @@
+#region License
+//
+// Xkb.cs
+//
+// Author:
+//       Stefanos Apostolopoulos <stapostol@gmail.com>
+//
+// Copyright (c) 2006-2014 
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+#endregion
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+#pragma warning disable 0169
+
+namespace X11Sharp
+{
+    using Atom = IntPtr;
+    using KeyCode = Byte;
+    using XkbControlsPtr = IntPtr;
+    using XkbServerMapPtr = IntPtr;
+    using XkbClientMapPtr = IntPtr;
+    using XkbIndicatorPtr = IntPtr;
+    using XkbCompatMapPtr = IntPtr;
+    using XkbGeometryPtr = IntPtr;
+
+    class Xkb
+    {
+        const string lib = "libX11";
+
+        internal const int KeyNameLength = 4;
+        internal const int NumModifiers = 8;
+        internal const int NumVirtualMods = 16;
+        internal const int NumIndicators = 32;
+        internal const int NumKbdGroups = 4;
+        internal const int UseCoreKeyboard = 0x0100;
+
+        [DllImport(lib, EntryPoint = "XkbFreeKeyboard")]
+        unsafe internal extern static void FreeKeyboard(XkbDesc* descr, int which, bool free);
+
+        [DllImport(lib, EntryPoint = "XkbAllocKeyboard")]
+        unsafe internal extern static XkbDesc* AllocKeyboard(IntPtr display);
+
+        [DllImport(lib, EntryPoint = "XkbGetKeyboard")]
+        internal extern static IntPtr GetKeyboard(IntPtr display, XkbKeyboardMask which, int device_id);
+
+        [DllImport(lib, EntryPoint = "XkbGetMap")]
+        internal extern static IntPtr GetMap(IntPtr display, XkbKeyboardMask which, int device_spec); 
+
+        [DllImport(lib, EntryPoint = "XkbGetNames")]
+        unsafe internal extern static IntPtr GetNames(IntPtr display, XkbNamesMask which, XkbDesc* xkb); 
+
+        [DllImport(lib, EntryPoint = "XkbKeycodeToKeysym")]
+        internal extern static XKey KeycodeToKeysym(IntPtr display, int keycode, int group, int level);
+
+        [DllImport(lib, EntryPoint = "XkbQueryExtension")]
+        internal extern static bool QueryExtension(IntPtr display, out int opcode_rtrn, out int event_rtrn,
+            out int error_rtrn, ref int major_in_out, ref int minor_in_out);
+
+        [DllImport(lib, EntryPoint = "XkbSetDetectableAutoRepeat")]
+        internal extern static bool SetDetectableAutoRepeat(IntPtr display, bool detectable, out bool supported);
+
+        internal static bool IsSupported(IntPtr display)
+        {
+            // The XkbQueryExtension manpage says that we cannot
+            // use XQueryExtension with XKB.
+            int opcode, error, ev;
+            int major = 1;
+            int minor = 0;
+            bool supported = QueryExtension(display, out opcode, out ev, out error, ref major, ref minor);
+            Debug.Print("XKB extension is {0}.", supported ? "supported" : "not supported");
+            if (supported)
+            {
+                Debug.Print("XKB version is {0}.{1}", major, minor);
+            }
+            return supported;
+        }
+    }
+
+    [Flags]
+    enum XkbKeyboardMask
+    {
+        Controls = 1 << 0,
+        ServerMap = 1 << 1,
+        IClientMap = 1 << 2,
+        IndicatorMap = 1 << 3,
+        Names = 1 << 4,
+        CompatibilityMap = 1 << 5,
+        Geometry = 1 << 6,
+        AllComponents = 1 << 7,
+    }
+
+    [Flags]
+    enum XkbNamesMask
+    {
+        Keycodes = 1 << 0,
+        Geometry = 1 << 1,
+        Symbols = 1 << 2,
+        PhysSymbols = 1 << 3,
+        Types = 1 << 4,
+        Compat = 1 << 5,
+        KeyType = 1 << 6,
+        KTLevel = 1 << 7,
+        Indicator = 1 << 8,
+        Key = 1 << 9,
+        KeyAliasesMask = 1 << 10,
+        VirtualMod = 1 << 11,
+        Group = 1 << 12,
+        RG = 1 << 13,
+        Component = 0x3f,
+        All = 0x3fff
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    unsafe struct XkbDesc
+    {
+        internal IntPtr dpy;
+        internal ushort flags;
+        internal ushort device_spec;
+        internal KeyCode min_key_code;
+        internal KeyCode max_key_code;
+
+        internal XkbControlsPtr ctrls;
+        internal XkbServerMapPtr server;
+        internal XkbClientMapPtr map;
+        internal XkbIndicatorPtr indicators;
+        internal XkbNames* names;
+        internal XkbCompatMapPtr compat;
+        internal XkbGeometryPtr geom;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    unsafe struct XkbKeyAlias
+    {
+        internal fixed byte real[Xkb.KeyNameLength];
+        internal fixed byte alias[Xkb.KeyNameLength];
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    unsafe struct XkbKeyName
+    {
+        internal fixed byte name[Xkb.KeyNameLength];
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    unsafe struct XkbNames
+    {
+        #region Structs
+
+        [StructLayout(LayoutKind.Sequential)]
+        internal struct Groups
+        {
+            Atom groups0;
+            Atom groups1;
+            Atom groups2;
+            Atom groups3;
+            internal Atom this[int i]
+            {
+                get
+                {
+                    if (i < 0 || i > 3)
+                        throw new IndexOutOfRangeException();
+
+                    unsafe
+                    {
+                        fixed (Atom* ptr = &groups0)
+                        {
+                            return *(ptr + i);
+                        }
+                    }
+                }
+            }
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        internal struct Indicators
+        {
+            Atom indicators0;
+            Atom indicators1;
+            Atom indicators2;
+            Atom indicators3;
+            Atom indicators4;
+            Atom indicators5;
+            Atom indicators6;
+            Atom indicators7;
+            Atom indicators8;
+            Atom indicators9;
+            Atom indicators10;
+            Atom indicators11;
+            Atom indicators12;
+            Atom indicators13;
+            Atom indicators14;
+            Atom indicators15;
+            Atom indicators16;
+            Atom indicators17;
+            Atom indicators18;
+            Atom indicators19;
+            Atom indicators20;
+            Atom indicators21;
+            Atom indicators22;
+            Atom indicators23;
+            Atom indicators24;
+            Atom indicators25;
+            Atom indicators26;
+            Atom indicators27;
+            Atom indicators28;
+            Atom indicators29;
+            Atom indicators30;
+            Atom indicators31;
+            internal Atom this[int i]
+            {
+                get
+                {
+                    if (i < 0 || i > 31)
+                        throw new IndexOutOfRangeException();
+
+                    unsafe
+                    {
+                        fixed (Atom* ptr = &indicators0)
+                        {
+                            return *(ptr + i);
+                        }                    }
+                }
+            }
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        internal struct VMods
+        {
+            Atom vmods0;
+            Atom vmods1;
+            Atom vmods2;
+            Atom vmods3;
+            Atom vmods4;
+            Atom vmods5;
+            Atom vmods6;
+            Atom vmods7;
+            Atom vmods8;
+            Atom vmods9;
+            Atom vmods10;
+            Atom vmods11;
+            Atom vmods12;
+            Atom vmods13;
+            Atom vmods14;
+            Atom vmods15;
+            internal Atom this[int i]
+            {
+                get
+                {
+                    if (i < 0 || i > 15)
+                        throw new IndexOutOfRangeException();
+
+                    unsafe
+                    {
+                        fixed (Atom* ptr = &vmods0)
+                        {
+                            return *(ptr + i);
+                        }
+                    }
+                }
+            }
+        }
+
+        #endregion
+
+        internal Atom keycodes;
+        internal Atom geometry;
+        internal Atom symbols;
+        internal Atom types;
+        internal Atom compat;
+        internal VMods vmods;
+        internal Indicators indicators;
+        internal Groups groups;
+        internal XkbKeyName* keys;
+        internal XkbKeyAlias* key_aliases;
+        internal Atom *radio_groups;
+        internal Atom phys_symbols;
+
+        internal byte num_keys;
+        internal byte num_key_aliases;
+        internal byte num_rg;
+    }
+}
+
diff --git a/CrowX/X11/Functions.cs b/CrowX/X11/Functions.cs
new file mode 100644 (file)
index 0000000..1e35ff5
--- /dev/null
@@ -0,0 +1,631 @@
+#region --- License ---
+/* Licensed under the MIT/X11 license.
+ * Copyright (c) 2006-2008 the OpenTK Team.
+ * This notice may not be removed from any source distribution.
+ * See license.txt for licensing detailed licensing details.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+#if !MINIMAL
+using System.Drawing;
+#endif
+#if ANDROID || IPHONE || MINIMAL
+using OpenTK.Minimal;
+#else
+using System.Drawing.Imaging;
+#endif
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace X11Sharp
+{
+    #region Types
+
+    // using XID = System.Int32;
+    using Window = System.IntPtr;
+    using Drawable = System.IntPtr;
+    using Font = System.IntPtr;
+    using Pixmap = System.IntPtr;
+    using Cursor = System.IntPtr;
+    using Colormap = System.IntPtr;
+    using GContext = System.IntPtr;
+    using KeySym = System.IntPtr;
+    using Mask = System.IntPtr;
+    using Atom = System.IntPtr;
+    using VisualID = System.IntPtr;
+    using Time = System.IntPtr;
+    using KeyCode = System.Byte;    // Or maybe ushort?
+
+    using Display = System.IntPtr;
+    using XPointer = System.IntPtr;
+
+    // Randr and Xrandr
+    using Bool = System.Boolean;
+    using XRRScreenConfiguration = System.IntPtr; // opaque datatype
+    using Rotation = System.UInt16;
+    using Status = System.Int32;
+    using SizeID = System.UInt16;
+
+    #endregion
+    
+    #region Structs
+   
+    #endregion
+
+    internal static partial class Functions
+    {
+        public static readonly object Lock = API.Lock;
+
+        [DllImport("libX11", EntryPoint = "XOpenDisplay")]
+        extern static IntPtr sys_XOpenDisplay(IntPtr display);
+        public static IntPtr XOpenDisplay(IntPtr display)
+        {
+            lock (Lock)
+            {
+                return sys_XOpenDisplay(display);
+            }
+        }
+
+        [DllImport("libX11", EntryPoint = "XCloseDisplay")]
+        public extern static int XCloseDisplay(IntPtr display);
+        [DllImport("libX11", EntryPoint = "XSynchronize")]
+        public extern static IntPtr XSynchronize(IntPtr display, bool onoff);
+
+        [DllImport("libX11", EntryPoint = "XCreateWindow")]
+        public unsafe extern static IntPtr XCreateWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, int depth, int xclass, IntPtr visual, IntPtr valuemask, XSetWindowAttributes* attributes);
+
+        [DllImport("libX11", EntryPoint = "XCreateSimpleWindow")]//, CLSCompliant(false)]
+        public extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
+        [DllImport("libX11", EntryPoint = "XCreateSimpleWindow")]
+        public extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, IntPtr border, IntPtr background);
+
+        [DllImport("libX11", EntryPoint = "XMapWindow")]
+        public extern static int XMapWindow(IntPtr display, IntPtr window);
+        [DllImport("libX11", EntryPoint = "XUnmapWindow")]
+        public extern static int XUnmapWindow(IntPtr display, IntPtr window);
+        [DllImport("libX11", EntryPoint = "XMapSubwindows")]
+        public extern static int XMapSubindows(IntPtr display, IntPtr window);
+        [DllImport("libX11", EntryPoint = "XUnmapSubwindows")]
+        public extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
+        [DllImport("libX11", EntryPoint = "XRootWindow")]
+        public extern static IntPtr XRootWindow(IntPtr display, int screen_number);
+
+        [DllImport("libX11", EntryPoint = "XNextEvent")]
+        public extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
+        [DllImport("libX11")]
+        public extern static Bool XWindowEvent(Display display, Window w, EventMask event_mask, ref XEvent event_return);
+        [DllImport("libX11")]
+        public extern static Bool XCheckWindowEvent(Display display, Window w, EventMask event_mask, ref XEvent event_return);
+        [DllImport("libX11")]
+        public extern static Bool XCheckTypedWindowEvent(Display display, Window w, XEventName event_type, ref XEvent event_return);
+        [DllImport("libX11")]
+        public extern static Bool XCheckTypedEvent(Display display, XEventName event_type, out XEvent event_return);
+
+        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        public delegate Bool EventPredicate(IntPtr display, ref XEvent e, IntPtr arg);
+        [DllImport("libX11")]
+        public extern static Bool XIfEvent(Display display, ref XEvent e, IntPtr predicate, IntPtr arg );
+        [DllImport("libX11")]
+        public extern static Bool XCheckIfEvent(Display display, ref XEvent e, IntPtr predicate, IntPtr arg );
+
+        [DllImport("libX11")]
+        public extern static int XConnectionNumber(IntPtr diplay);
+        [DllImport("libX11")]
+        public extern static int XPending(IntPtr diplay);
+
+        [DllImport("libX11", EntryPoint = "XSelectInput")]
+        public extern static int XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
+
+        [DllImport("libX11", EntryPoint = "XDestroyWindow")]
+        public extern static int XDestroyWindow(IntPtr display, IntPtr window);
+
+        [DllImport("libX11", EntryPoint = "XReparentWindow")]
+        public extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
+
+        [DllImport("libX11", EntryPoint = "XMoveResizeWindow")]
+        public extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
+
+        [DllImport("libX11", EntryPoint = "XMoveWindow")]
+        public extern static int XMoveWindow(IntPtr display, IntPtr w, int x, int y);
+        
+        [DllImport("libX11", EntryPoint = "XResizeWindow")]
+        public extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
+
+        [DllImport("libX11", EntryPoint = "XGetWindowAttributes")]
+        public extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
+
+        [DllImport("libX11", EntryPoint = "XFlush")]
+        public extern static int XFlush(IntPtr display);
+
+        [DllImport("libX11", EntryPoint = "XSetWMName")]
+        public extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
+
+        [DllImport("libX11", EntryPoint = "XStoreName")]
+        public extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
+
+        [DllImport("libX11", EntryPoint = "XFetchName")]
+        public extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
+
+        [DllImport("libX11", EntryPoint = "XSendEvent")]
+        public extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
+
+        public static int XSendEvent(IntPtr display, IntPtr window, bool propagate, EventMask event_mask, ref XEvent send_event)
+        {
+            return XSendEvent(display, window, propagate, new IntPtr((int)event_mask), ref send_event);
+        }
+
+        [DllImport("libX11", EntryPoint = "XQueryTree")]
+        public extern static int XQueryTree(IntPtr display, IntPtr window, out IntPtr root_return, out IntPtr parent_return, out IntPtr children_return, out int nchildren_return);
+
+        [DllImport("libX11", EntryPoint = "XFree")]
+        public extern static int XFree(IntPtr data);
+
+        [DllImport("libX11", EntryPoint = "XRaiseWindow")]
+        public extern static int XRaiseWindow(IntPtr display, IntPtr window);
+
+        [DllImport("libX11", EntryPoint = "XLowerWindow")]//, CLSCompliant(false)]
+        public extern static uint XLowerWindow(IntPtr display, IntPtr window);
+
+        [DllImport("libX11", EntryPoint = "XConfigureWindow")]//, CLSCompliant(false)]
+        public extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowAttributes value_mask, ref XWindowChanges values);
+
+        [DllImport("libX11", EntryPoint = "XInternAtom")]
+        public extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
+
+        [DllImport("libX11", EntryPoint = "XInternAtoms")]
+        public extern static int XInternAtoms(IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms);
+
+        [DllImport("libX11", EntryPoint = "XGetAtomName")]
+        public extern static IntPtr XGetAtomName(IntPtr display, IntPtr atom);
+
+        [DllImport("libX11", EntryPoint = "XSetWMProtocols")]
+        public extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
+
+        [DllImport("libX11", EntryPoint = "XGrabPointer")]
+        public extern static int XGrabPointer(IntPtr display, IntPtr window, bool owner_events, EventMask event_mask, GrabMode pointer_mode, GrabMode keyboard_mode, IntPtr confine_to, IntPtr cursor, IntPtr timestamp);
+
+        [DllImport("libX11", EntryPoint = "XUngrabPointer")]
+        public extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
+
+        [DllImport("libX11", EntryPoint = "XGrabButton")]
+        public extern static int XGrabButton(IntPtr display,
+            int button, uint modifiers, Window grab_window,
+            Bool owner_events, EventMask event_mask,
+            GrabMode pointer_mode, GrabMode keyboard_mode,
+            Window confine_to, Cursor cursor);
+
+        [DllImport("libX11", EntryPoint = "XUngrabButton")]
+        public extern static int XUngrabButton(IntPtr display, uint button, uint
+              modifiers, Window grab_window);
+
+        [DllImport("libX11", EntryPoint = "XQueryPointer")]
+        public extern static bool XQueryPointer(IntPtr display, IntPtr window, out IntPtr root, out IntPtr child, out int root_x, out int root_y, out int win_x, out int win_y, out int keys_buttons);
+
+        [DllImport("libX11", EntryPoint = "XTranslateCoordinates")]
+        public extern static bool XTranslateCoordinates(IntPtr display, IntPtr src_w, IntPtr dest_w, int src_x, int src_y, out int intdest_x_return, out int dest_y_return, out IntPtr child_return);
+
+
+        [DllImport("libX11")]
+        public extern static int XGrabKey(IntPtr display, int keycode, uint modifiers,
+            Window grab_window, bool owner_events, GrabMode pointer_mode, GrabMode keyboard_mode);
+
+        [DllImport("libX11")]
+        public extern static int XUngrabKey(IntPtr display, int keycode, uint modifiers, Window grab_window);
+
+        [DllImport("libX11", EntryPoint = "XGrabKeyboard")]
+        public extern static int XGrabKeyboard(IntPtr display, IntPtr window, bool owner_events,
+            GrabMode pointer_mode, GrabMode keyboard_mode, IntPtr timestamp);
+
+        [DllImport("libX11", EntryPoint = "XUngrabKeyboard")]
+        public extern static int XUngrabKeyboard(IntPtr display, IntPtr timestamp);
+
+        [DllImport("libX11")]
+        public extern static int XAllowEvents(IntPtr display, EventMode event_mode, Time time);
+
+        [DllImport("libX11", EntryPoint = "XGetGeometry")]
+        public extern static bool XGetGeometry(IntPtr display, IntPtr window, out IntPtr root, out int x, out int y, out int width, out int height, out int border_width, out int depth);
+
+        [DllImport("libX11", EntryPoint = "XGetGeometry")]
+        public extern static bool XGetGeometry(IntPtr display, IntPtr window, IntPtr root, out int x, out int y, out int width, out int height, IntPtr border_width, IntPtr depth);
+
+        [DllImport("libX11", EntryPoint = "XGetGeometry")]
+        public extern static bool XGetGeometry(IntPtr display, IntPtr window, IntPtr root, out int x, out int y, IntPtr width, IntPtr height, IntPtr border_width, IntPtr depth);
+
+        [DllImport("libX11", EntryPoint = "XGetGeometry")]
+        public extern static bool XGetGeometry(IntPtr display, IntPtr window, IntPtr root, IntPtr x, IntPtr y, out int width, out int height, IntPtr border_width, IntPtr depth);
+
+        [DllImport("libX11", EntryPoint = "XWarpPointer")]//, CLSCompliant(false)]
+        public extern static uint XWarpPointer(IntPtr display, IntPtr src_w, IntPtr dest_w, int src_x, int src_y, uint src_width, uint src_height, int dest_x, int dest_y);
+
+        [DllImport("libX11", EntryPoint = "XClearWindow")]
+        public extern static int XClearWindow(IntPtr display, IntPtr window);
+
+        [DllImport("libX11", EntryPoint = "XClearArea")]
+        public extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
+
+        // Colormaps
+        [DllImport("libX11", EntryPoint = "XDefaultScreenOfDisplay")]
+        public extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
+
+        [DllImport("libX11", EntryPoint = "XScreenNumberOfScreen")]
+        public extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
+
+        [DllImport("libX11", EntryPoint = "XDefaultVisual")]
+        public extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
+
+        [DllImport("libX11", EntryPoint = "XDefaultDepth")]//, CLSCompliant(false)]
+        public extern static uint XDefaultDepth(IntPtr display, int screen_number);
+
+        [DllImport("libX11", EntryPoint = "XDefaultScreen")]
+        public extern static int XDefaultScreen(IntPtr display);
+
+        [DllImport("libX11", EntryPoint = "XDefaultColormap")]
+        public extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
+
+        [DllImport("libX11", EntryPoint = "XLookupColor")]//, CLSCompliant(false)]
+        public extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
+
+        [DllImport("libX11", EntryPoint = "XAllocColor")]//, CLSCompliant(false)]
+        public extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
+
+        [DllImport("libX11", EntryPoint = "XSetTransientForHint")]
+        public extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
+
+        [DllImport("libX11", EntryPoint = "XChangeProperty")]
+        public extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
+
+        [DllImport("libX11", EntryPoint = "XChangeProperty")]//, CLSCompliant(false)]
+        public extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
+        [DllImport("libX11", EntryPoint = "XChangeProperty")]
+        public extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref int value, int nelements);
+
+        [DllImport("libX11", EntryPoint = "XChangeProperty")]//, CLSCompliant(false)]
+        public extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
+
+        [DllImport("libX11", EntryPoint = "XChangeProperty")]//, CLSCompliant(false)]
+        public extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
+
+        [DllImport("libX11", EntryPoint = "XChangeProperty")]
+        public extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
+
+        [DllImport("libX11", EntryPoint = "XChangeProperty")]
+        public extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
+
+        [DllImport("libX11", EntryPoint = "XChangeProperty")]
+        public extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
+
+        [DllImport("libX11", EntryPoint = "XChangeProperty", CharSet = CharSet.Ansi)]
+        public extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
+
+        [DllImport("libX11", EntryPoint = "XDeleteProperty")]
+        public extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
+
+        // Drawing
+        [DllImport("libX11", EntryPoint = "XCreateGC")]
+        public extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, XGCValues[] values);
+
+        [DllImport("libX11", EntryPoint = "XFreeGC")]
+        public extern static int XFreeGC(IntPtr display, IntPtr gc);
+
+               [DllImport("libX11", EntryPoint = "XDefaultGC")]
+               public extern static IntPtr XDefaultGC(IntPtr display, int screen);
+
+        [DllImport("libX11", EntryPoint = "XSetFunction")]
+        public extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
+
+        [DllImport("libX11", EntryPoint = "XSetLineAttributes")]
+        public extern static int XSetLineAttributes(IntPtr display, IntPtr gc, int line_width, GCLineStyle line_style, GCCapStyle cap_style, GCJoinStyle join_style);
+
+        [DllImport("libX11", EntryPoint = "XDrawLine")]
+        public extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
+
+        [DllImport("libX11", EntryPoint = "XDrawRectangle")]
+        public extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
+
+        [DllImport("libX11", EntryPoint = "XFillRectangle")]
+        public extern static int XFillRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
+
+        [DllImport("libX11", EntryPoint = "XSetWindowBackground")]
+        public extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
+
+        [DllImport("libX11", EntryPoint = "XCopyArea")]
+        public extern static int XCopyArea(IntPtr display, IntPtr src, IntPtr dest, IntPtr gc, int src_x, int src_y, int width, int height, int dest_x, int dest_y);
+
+        [DllImport("libX11", EntryPoint = "XGetWindowProperty")]
+        public extern static int XGetWindowProperty(IntPtr display, IntPtr window, IntPtr atom, IntPtr long_offset, IntPtr long_length, bool delete, IntPtr req_type, out IntPtr actual_type, out int actual_format, out IntPtr nitems, out IntPtr bytes_after, ref IntPtr prop);
+
+        [DllImport("libX11", EntryPoint = "XSetInputFocus")]
+        public extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
+
+        [DllImport("libX11", EntryPoint = "XIconifyWindow")]
+        public extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
+
+        [DllImport("libX11", EntryPoint = "XDefineCursor")]
+        public extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
+
+        [DllImport("libX11", EntryPoint = "XUndefineCursor")]
+        public extern static int XUndefineCursor(IntPtr display, IntPtr window);
+
+        [DllImport("libX11", EntryPoint = "XFreeCursor")]
+        public extern static int XFreeCursor(IntPtr display, IntPtr cursor);
+
+        [DllImport("libX11", EntryPoint = "XCreateFontCursor")]
+        public extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
+
+        [DllImport("libX11", EntryPoint = "XCreatePixmapCursor")]//, CLSCompliant(false)]
+        public extern static IntPtr XCreatePixmapCursor(IntPtr display, IntPtr source, IntPtr mask, ref XColor foreground_color, ref XColor background_color, int x_hot, int y_hot);
+
+        [DllImport("libX11", EntryPoint = "XCreatePixmapFromBitmapData")]
+        public extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
+
+        [DllImport("libX11", EntryPoint = "XCreatePixmap")]
+        public extern static IntPtr XCreatePixmap(IntPtr display, IntPtr d, int width, int height, int depth);
+
+        [DllImport("libX11", EntryPoint = "XFreePixmap")]
+        public extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
+
+        [DllImport("libX11", EntryPoint = "XQueryBestCursor")]
+        public extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
+
+        [DllImport("libX11", EntryPoint = "XQueryExtension")]
+        public extern static int XQueryExtension(IntPtr display, string extension_name, out int major, out int first_event, out int first_error);
+
+        [DllImport("libX11", EntryPoint = "XWhitePixel")]
+        public extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
+
+        [DllImport("libX11", EntryPoint = "XBlackPixel")]
+        public extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
+
+        [DllImport("libX11", EntryPoint = "XGrabServer")]
+        public extern static void XGrabServer(IntPtr display);
+
+        [DllImport("libX11", EntryPoint = "XUngrabServer")]
+        public extern static void XUngrabServer(IntPtr display);
+
+        [DllImport("libX11", EntryPoint = "XGetWMNormalHints")]
+        public extern static int XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
+
+        [DllImport("libX11", EntryPoint = "XSetWMNormalHints")]
+        public extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
+
+        [DllImport("libX11", EntryPoint = "XSetZoomHints")]
+        public extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
+
+        [DllImport("libX11")]
+        public static extern IntPtr XGetWMHints(Display display, Window w); // returns XWMHints*
+
+        [DllImport("libX11")]
+        public static extern void XSetWMHints(Display display, Window w, ref XWMHints wmhints);
+
+        [DllImport("libX11")]
+        public static extern IntPtr XAllocWMHints();
+        
+        [DllImport("libX11", EntryPoint = "XGetIconSizes")]
+        public extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
+
+        [DllImport("libX11", EntryPoint = "XSetErrorHandler")]
+        public extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
+
+        [DllImport("libX11", EntryPoint = "XGetErrorText")]
+        public extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
+
+        [DllImport("libX11", EntryPoint = "XInitThreads")]
+        public extern static int XInitThreads();
+
+        [DllImport("libX11", EntryPoint = "XConvertSelection")]
+        public extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
+
+        [DllImport("libX11", EntryPoint = "XGetSelectionOwner")]
+        public extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
+
+        [DllImport("libX11", EntryPoint = "XSetSelectionOwner")]
+        public extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
+
+        [DllImport("libX11", EntryPoint = "XSetPlaneMask")]
+        public extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
+
+        [DllImport("libX11", EntryPoint = "XSetForeground")]//, CLSCompliant(false)]
+        public extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
+        [DllImport("libX11", EntryPoint = "XSetForeground")]
+        public extern static int XSetForeground(IntPtr display, IntPtr gc, IntPtr foreground);
+
+        [DllImport("libX11", EntryPoint = "XSetBackground")]//, CLSCompliant(false)]
+        public extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
+        [DllImport("libX11", EntryPoint = "XSetBackground")]
+        public extern static int XSetBackground(IntPtr display, IntPtr gc, IntPtr background);
+
+        [DllImport("libX11", EntryPoint = "XBell")]
+        public extern static int XBell(IntPtr display, int percent);
+
+        [DllImport("libX11", EntryPoint = "XChangeActivePointerGrab")]
+        public extern static int XChangeActivePointerGrab(IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
+
+        [DllImport("libX11", EntryPoint = "XFilterEvent")]
+        public extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
+
+        [DllImport("libX11")]
+        public extern static void XPeekEvent(IntPtr display, ref XEvent xevent);
+
+        [DllImport("libX11", EntryPoint = "XGetVisualInfo")]
+        static extern IntPtr XGetVisualInfoInternal(IntPtr display, IntPtr vinfo_mask, ref XVisualInfo template, out int nitems);
+                                                    
+        public static IntPtr XGetVisualInfo(IntPtr display, XVisualInfoMask vinfo_mask, ref XVisualInfo template, out int nitems)
+        {
+            return XGetVisualInfoInternal(display, (IntPtr)(int)vinfo_mask, ref template, out nitems);
+        }
+        
+        [DllImport("libX11")]
+        public static extern IntPtr XCreateColormap(Display display, Window window, IntPtr visual, int alloc);
+        
+        [DllImport("libX11")]
+        public static extern void XLockDisplay(Display display);
+
+        [DllImport("libX11")]
+        public static extern void XUnlockDisplay(Display display);
+
+        [DllImport("libX11")]
+        public static extern Status XGetTransientForHint(Display display, Window w, out Window prop_window_return);
+
+        [DllImport("libX11")]
+        public static extern void XSync(Display display, bool discard);
+
+        [DllImport("libX11")]
+        public static extern void XAutoRepeatOff(IntPtr display);
+
+        [DllImport("libX11")]
+        public static extern void XAutoRepeatOn(IntPtr display);
+
+        [DllImport("libX11")]
+        public static extern IntPtr XDefaultRootWindow(IntPtr display);
+
+        [DllImport("libX11")]
+        public static extern int XBitmapBitOrder(Display display);
+
+        [DllImport("libX11")]
+        public static extern IntPtr XCreateImage(Display display, IntPtr visual,
+            uint depth, ImageFormat format, int offset, byte[] data, uint width, uint height,
+            int bitmap_pad, int bytes_per_line);
+
+        [DllImport("libX11")]
+        public static extern IntPtr XCreateImage(Display display, IntPtr visual,
+            uint depth, ImageFormat format, int offset, IntPtr data, uint width, uint height,
+            int bitmap_pad, int bytes_per_line);
+
+        [DllImport("libX11")]
+        public static extern void XPutImage(Display display, IntPtr drawable,
+            IntPtr gc, IntPtr image, int src_x, int src_y, int dest_x, int dest_y, uint width, uint height);
+
+        [DllImport("libX11")]
+        public static extern int XLookupString(ref XKeyEvent event_struct, [Out] byte[] buffer_return,
+            int bytes_buffer, [Out] KeySym[] keysym_return, IntPtr status_in_out);
+
+        [DllImport("libX11")]
+        public static extern KeyCode XKeysymToKeycode(IntPtr display, KeySym keysym);
+
+        [DllImport("libX11")]
+        public static extern KeySym XKeycodeToKeysym(IntPtr display, KeyCode keycode, int index);
+
+        [DllImport("libX11")]
+        public static extern int XRefreshKeyboardMapping(ref XMappingEvent event_map);
+
+        [DllImport("libX11")]
+        public static extern int XGetEventData(IntPtr display, ref XGenericEventCookie cookie);
+
+        [DllImport("libX11")]
+        public static extern void XFreeEventData(IntPtr display, ref XGenericEventCookie cookie);
+
+        [DllImport("libX11")]
+        public static extern void XSetClassHint(IntPtr display, IntPtr window, ref XClassHint hint);
+
+        static readonly IntPtr CopyFromParent = IntPtr.Zero;
+
+               public static void SendNetWMMessage(IntPtr display, IntPtr handle, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2)
+        {
+            XEvent xev;
+
+            xev = new XEvent();
+            xev.ClientMessageEvent.type = XEventName.ClientMessage;
+            xev.ClientMessageEvent.send_event = true;
+            xev.ClientMessageEvent.window = handle;
+            xev.ClientMessageEvent.message_type = message_type;
+            xev.ClientMessageEvent.format = 32;
+            xev.ClientMessageEvent.ptr1 = l0;
+            xev.ClientMessageEvent.ptr2 = l1;
+            xev.ClientMessageEvent.ptr3 = l2;
+
+            XSendEvent(display, handle, false,
+                       new IntPtr((int)(EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask)),
+                       ref xev);
+        }
+        
+        public static void SendNetClientMessage(IntPtr display, IntPtr handle, IntPtr message_type,
+                                                IntPtr l0, IntPtr l1, IntPtr l2)
+        {
+            XEvent xev;
+
+            xev = new XEvent();
+            xev.ClientMessageEvent.type = XEventName.ClientMessage;
+            xev.ClientMessageEvent.send_event = true;
+            xev.ClientMessageEvent.window = handle;
+            xev.ClientMessageEvent.message_type = message_type;
+            xev.ClientMessageEvent.format = 32;
+            xev.ClientMessageEvent.ptr1 = l0;
+            xev.ClientMessageEvent.ptr2 = l1;
+            xev.ClientMessageEvent.ptr3 = l2;
+
+            XSendEvent(display, handle, false, new IntPtr((int)EventMask.NoEventMask), ref xev);
+        }
+
+        [StructLayout(LayoutKind.Sequential, Pack = 1)]
+        struct  Pixel
+        {
+            public byte A, R, G, B;
+            public Pixel(byte a, byte r, byte g, byte b)
+            {
+                A= a;
+                R = r;
+                G = g;
+                B = b;
+            }
+            public static implicit operator Pixel(int argb)
+            {
+                return new Pixel(
+                    (byte)((argb >> 24) & 0xFF),
+                    (byte)((argb >> 16) & 0xFF),
+                    (byte)((argb >> 8) & 0xFF),
+                    (byte)(argb & 0xFF));
+            }
+        }
+        public static IntPtr CreatePixmapFromImage(Display display, Bitmap image) 
+        { 
+            int width = image.Width;
+            int height = image.Height;
+
+            BitmapData data = image.LockBits(new Rectangle(0, 0, width, height),
+                ImageLockMode.ReadOnly,
+                PixelFormat.Format32bppArgb);
+            
+            IntPtr ximage = XCreateImage(display, CopyFromParent, 24, ImageFormat.ZPixmap, 
+                0, data.Scan0, (uint)width, (uint)height, 32, 0); 
+            IntPtr pixmap = XCreatePixmap(display, XDefaultRootWindow(display), 
+                width, height, 24); 
+            IntPtr gc = XCreateGC(display, pixmap, IntPtr.Zero, null);
+            
+            XPutImage(display, pixmap, gc, ximage, 0, 0, 0, 0, (uint)width, (uint)height);
+            
+            XFreeGC(display, gc);
+            image.UnlockBits(data);
+
+            return pixmap; 
+        } 
+        
+        public static IntPtr CreateMaskFromImage(Display display, Bitmap image) 
+        { 
+            int width = image.Width; 
+            int height = image.Height; 
+            int stride = (width + 7) >> 3; 
+            byte[] mask = new byte[stride * height];
+            bool msbfirst = (XBitmapBitOrder(display) == 1); // 1 = MSBFirst
+        
+            for (int y = 0; y < height; ++y) 
+            { 
+                for (int x = 0; x < width; ++x) 
+                { 
+                    byte bit = (byte) (1 << (msbfirst ? (7 - (x & 7)) : (x & 7))); 
+                    int offset = y * stride + (x >> 3); 
+        
+                    if (image.GetPixel(x, y).A >= 128) 
+                        mask[offset] |= bit; 
+                } 
+            } 
+        
+            Pixmap pixmap = XCreatePixmapFromBitmapData(display, XDefaultRootWindow(display), 
+                mask, width, height, new IntPtr(1), IntPtr.Zero, 1); 
+        
+            return pixmap; 
+        }
+    }
+}
diff --git a/CrowX/X11/Structs.cs b/CrowX/X11/Structs.cs
new file mode 100644 (file)
index 0000000..b2e93d8
--- /dev/null
@@ -0,0 +1,1907 @@
+// 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.
+//
+// Copyright (c) 2004 Novell, Inc.
+//
+// Authors:
+//    Peter Bartok    pbartok@novell.com
+//
+
+
+// NOT COMPLETE
+
+using System;
+using System.ComponentModel;
+using System.Collections;
+#if !MINIMAL
+using System.Drawing;
+#endif
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+// Disable unused field warnings. This is interop, we don't use everything
+#pragma warning disable 0649
+
+// X11 Version
+namespace X11Sharp
+{
+    using Bool = System.Boolean;
+    using Time = System.IntPtr;
+    using Window = System.IntPtr;
+
+    //
+    // In the structures below, fields of type long are mapped to IntPtr.
+    // This will work on all platforms where sizeof(long)==sizeof(void*), which
+    // is almost all platforms except WIN64.
+    //
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XAnyEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr window;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XKeyEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr window;
+        public IntPtr root;
+        public IntPtr subwindow;
+        public IntPtr time;
+        public int x;
+        public int y;
+        public int x_root;
+        public int y_root;
+        public int state;
+        public int keycode;
+        public bool same_screen;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XButtonEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr window;
+        public IntPtr root;
+        public IntPtr subwindow;
+        public IntPtr time;
+        public int x;
+        public int y;
+        public int x_root;
+        public int y_root;
+        public int state;
+        public int button;
+        public bool same_screen;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XMotionEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr window;
+        public IntPtr root;
+        public IntPtr subwindow;
+        public IntPtr time;
+        public int x;
+        public int y;
+        public int x_root;
+        public int y_root;
+        public int state;
+        public byte is_hint;
+        public bool same_screen;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XCrossingEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr window;
+        public IntPtr root;
+        public IntPtr subwindow;
+        public IntPtr time;
+        public int x;
+        public int y;
+        public int x_root;
+        public int y_root;
+        public NotifyMode mode;
+        public NotifyDetail detail;
+        public bool same_screen;
+        public bool focus;
+        public int state;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XFocusChangeEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr window;
+        public int mode;
+        public NotifyDetail detail;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XKeymapEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr window;
+        public byte key_vector0;
+        public byte key_vector1;
+        public byte key_vector2;
+        public byte key_vector3;
+        public byte key_vector4;
+        public byte key_vector5;
+        public byte key_vector6;
+        public byte key_vector7;
+        public byte key_vector8;
+        public byte key_vector9;
+        public byte key_vector10;
+        public byte key_vector11;
+        public byte key_vector12;
+        public byte key_vector13;
+        public byte key_vector14;
+        public byte key_vector15;
+        public byte key_vector16;
+        public byte key_vector17;
+        public byte key_vector18;
+        public byte key_vector19;
+        public byte key_vector20;
+        public byte key_vector21;
+        public byte key_vector22;
+        public byte key_vector23;
+        public byte key_vector24;
+        public byte key_vector25;
+        public byte key_vector26;
+        public byte key_vector27;
+        public byte key_vector28;
+        public byte key_vector29;
+        public byte key_vector30;
+        public byte key_vector31;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XExposeEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr window;
+        public int x;
+        public int y;
+        public int width;
+        public int height;
+        public int count;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XGraphicsExposeEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr drawable;
+        public int x;
+        public int y;
+        public int width;
+        public int height;
+        public int count;
+        public int major_code;
+        public int minor_code;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XNoExposeEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr drawable;
+        public int major_code;
+        public int minor_code;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XVisibilityEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr window;
+        public int state;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XCreateWindowEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr parent;
+        public IntPtr window;
+        public int x;
+        public int y;
+        public int width;
+        public int height;
+        public int border_width;
+        public bool override_redirect;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XDestroyWindowEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr xevent;
+        public IntPtr window;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XUnmapEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr xevent;
+        public IntPtr window;
+        public bool from_configure;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XMapEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr xevent;
+        public IntPtr window;
+        public bool override_redirect;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XMapRequestEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr parent;
+        public IntPtr window;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XReparentEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr xevent;
+        public IntPtr window;
+        public IntPtr parent;
+        public int x;
+        public int y;
+        public bool override_redirect;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XConfigureEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr xevent;
+        public IntPtr window;
+        public int x;
+        public int y;
+        public int width;
+        public int height;
+        public int border_width;
+        public IntPtr above;
+        public bool override_redirect;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XGravityEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr xevent;
+        public IntPtr window;
+        public int x;
+        public int y;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XResizeRequestEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr window;
+        public int width;
+        public int height;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XConfigureRequestEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr parent;
+        public IntPtr window;
+        public int x;
+        public int y;
+        public int width;
+        public int height;
+        public int border_width;
+        public IntPtr above;
+        public int detail;
+        public IntPtr value_mask;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XCirculateEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr xevent;
+        public IntPtr window;
+        public int place;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XCirculateRequestEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr parent;
+        public IntPtr window;
+        public int place;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XPropertyEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr window;
+        public IntPtr atom;
+        public IntPtr time;
+        public int state;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XSelectionClearEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr window;
+        public IntPtr selection;
+        public IntPtr time;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XSelectionRequestEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr owner;
+        public IntPtr requestor;
+        public IntPtr selection;
+        public IntPtr target;
+        public IntPtr property;
+        public IntPtr time;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XSelectionEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr requestor;
+        public IntPtr selection;
+        public IntPtr target;
+        public IntPtr property;
+        public IntPtr time;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XColormapEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr window;
+        public IntPtr colormap;
+        public bool c_new;
+        public int state;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XClientMessageEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr window;
+        public IntPtr message_type;
+        public int format;
+        public IntPtr ptr1;
+        public IntPtr ptr2;
+        public IntPtr ptr3;
+        public IntPtr ptr4;
+        public IntPtr ptr5;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XMappingEvent
+    {
+        public XEventName type;
+        public IntPtr serial;
+        public bool send_event;
+        public IntPtr display;
+        public IntPtr window;
+        public int request;
+        public int first_keycode;
+        public int count;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XErrorEvent
+    {
+        public XEventName type;
+        public IntPtr display;
+        public IntPtr resourceid;
+        public IntPtr serial;
+        public byte error_code;
+        public XRequest request_code;
+        public byte minor_code;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XEventPad
+    {
+        public IntPtr pad0;
+        public IntPtr pad1;
+        public IntPtr pad2;
+        public IntPtr pad3;
+        public IntPtr pad4;
+        public IntPtr pad5;
+        public IntPtr pad6;
+        public IntPtr pad7;
+        public IntPtr pad8;
+        public IntPtr pad9;
+        public IntPtr pad10;
+        public IntPtr pad11;
+        public IntPtr pad12;
+        public IntPtr pad13;
+        public IntPtr pad14;
+        public IntPtr pad15;
+        public IntPtr pad16;
+        public IntPtr pad17;
+        public IntPtr pad18;
+        public IntPtr pad19;
+        public IntPtr pad20;
+        public IntPtr pad21;
+        public IntPtr pad22;
+        public IntPtr pad23;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XGenericEvent
+    {
+        public int type;         // of event. Always GenericEvent
+        public IntPtr serial;       // # of last request processed
+        public bool send_event;   // true if from SendEvent request
+        public IntPtr display;     // Display the event was read from
+        public int extension;    // major opcode of extension that caused the event
+        public int evtype;       // actual event type.
+    }
+
+    internal struct XGenericEventCookie
+    {
+        public int type;         // of event. Always GenericEvent
+        public IntPtr serial;       // # of last request processed
+        public bool send_event;   // true if from SendEvent request
+        public IntPtr display;     // Display the event was read from
+        public int extension;    // major opcode of extension that caused the event
+        public int evtype;       // actual event type.
+        public uint cookie;       // unique event cookie
+        public IntPtr data;        // actual event data
+    }
+
+    [StructLayout(LayoutKind.Explicit)]
+    internal struct XEvent
+    {
+        [FieldOffset(0)]
+        public XEventName type;
+        [FieldOffset(0)]
+        public XAnyEvent AnyEvent;
+        [FieldOffset(0)]
+        public XKeyEvent KeyEvent;
+        [FieldOffset(0)]
+        public XButtonEvent ButtonEvent;
+        [FieldOffset(0)]
+        public XMotionEvent MotionEvent;
+        [FieldOffset(0)]
+        public XCrossingEvent CrossingEvent;
+        [FieldOffset(0)]
+        public XFocusChangeEvent FocusChangeEvent;
+        [FieldOffset(0)]
+        public XExposeEvent ExposeEvent;
+        [FieldOffset(0)]
+        public XGraphicsExposeEvent GraphicsExposeEvent;
+        [FieldOffset(0)]
+        public XNoExposeEvent NoExposeEvent;
+        [FieldOffset(0)]
+        public XVisibilityEvent VisibilityEvent;
+        [FieldOffset(0)]
+        public XCreateWindowEvent CreateWindowEvent;
+        [FieldOffset(0)]
+        public XDestroyWindowEvent DestroyWindowEvent;
+        [FieldOffset(0)]
+        public XUnmapEvent UnmapEvent;
+        [FieldOffset(0)]
+        public XMapEvent MapEvent;
+        [FieldOffset(0)]
+        public XMapRequestEvent MapRequestEvent;
+        [FieldOffset(0)]
+        public XReparentEvent ReparentEvent;
+        [FieldOffset(0)]
+        public XConfigureEvent ConfigureEvent;
+        [FieldOffset(0)]
+        public XGravityEvent GravityEvent;
+        [FieldOffset(0)]
+        public XResizeRequestEvent ResizeRequestEvent;
+        [FieldOffset(0)]
+        public XConfigureRequestEvent ConfigureRequestEvent;
+        [FieldOffset(0)]
+        public XCirculateEvent CirculateEvent;
+        [FieldOffset(0)]
+        public XCirculateRequestEvent CirculateRequestEvent;
+        [FieldOffset(0)]
+        public XPropertyEvent PropertyEvent;
+        [FieldOffset(0)]
+        public XSelectionClearEvent SelectionClearEvent;
+        [FieldOffset(0)]
+        public XSelectionRequestEvent SelectionRequestEvent;
+        [FieldOffset(0)]
+        public XSelectionEvent SelectionEvent;
+        [FieldOffset(0)]
+        public XColormapEvent ColormapEvent;
+        [FieldOffset(0)]
+        public XClientMessageEvent ClientMessageEvent;
+        [FieldOffset(0)]
+        public XMappingEvent MappingEvent;
+        [FieldOffset(0)]
+        public XErrorEvent ErrorEvent;
+        [FieldOffset(0)]
+        public XKeymapEvent KeymapEvent;
+        [FieldOffset(0)]
+        public XGenericEvent GenericEvent;
+        [FieldOffset(0)]
+        public XGenericEventCookie GenericEventCookie;
+
+        //[MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=24)]
+        //[ FieldOffset(0) ] public int[] pad;
+        [FieldOffset(0)]
+        public XEventPad Pad;
+        public override string ToString()
+        {
+            switch (type)
+            {
+                case XEventName.PropertyNotify:
+                    return ToString(PropertyEvent);
+                case XEventName.ResizeRequest:
+                    return ToString(ResizeRequestEvent);
+                case XEventName.ConfigureNotify:
+                    return ToString(ConfigureEvent);
+                default:
+                    return type.ToString();
+            }
+        }
+
+        public static string ToString(object ev)
+        {
+            string result = string.Empty;
+            Type type = ev.GetType();
+            System.Reflection.FieldInfo[] fields = type.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Instance);
+            for (int i = 0; i < fields.Length; i++)
+            {
+                if (result != string.Empty)
+                {
+                    result += ", ";
+                }
+                object value = fields[i].GetValue(ev);
+                result += fields[i].Name + "=" + (value == null ? "<null>" : value.ToString());
+            }
+            return type.Name + " (" + result + ")";
+        }
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XSetWindowAttributes
+    {
+        public IntPtr background_pixmap;
+        public IntPtr background_pixel;
+        public IntPtr border_pixmap;
+        public IntPtr border_pixel;
+        public Gravity bit_gravity;
+        public Gravity win_gravity;
+        public int backing_store;
+        public IntPtr backing_planes;
+        public IntPtr backing_pixel;
+        public bool save_under;
+        public IntPtr event_mask;
+        public IntPtr do_not_propagate_mask;
+        public bool override_redirect;
+        public IntPtr colormap;
+        public IntPtr cursor;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XWindowAttributes
+    {
+        public int x;
+        public int y;
+        public int width;
+        public int height;
+        public int border_width;
+        public int depth;
+        public IntPtr visual;
+        public IntPtr root;
+        public int c_class;
+        public Gravity bit_gravity;
+        public Gravity win_gravity;
+        public int backing_store;
+        public IntPtr backing_planes;
+        public IntPtr backing_pixel;
+        public bool save_under;
+        public IntPtr colormap;
+        public bool map_installed;
+        public MapState map_state;
+        public IntPtr all_event_masks;
+        public IntPtr your_event_mask;
+        public IntPtr do_not_propagate_mask;
+        public bool override_direct;
+        public IntPtr screen;
+
+        public override string ToString()
+        {
+            return XEvent.ToString(this);
+        }
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XTextProperty
+    {
+        public string value;
+        public IntPtr encoding;
+        public int format;
+        public IntPtr nitems;
+    }
+
+    internal struct XClassHint
+    {
+        [MarshalAs(UnmanagedType.LPStr)]
+        public string Name;
+        [MarshalAs(UnmanagedType.LPStr)]
+        public string Class;
+    }
+
+    internal enum XWindowClass
+    {
+        InputOutput = 1,
+        InputOnly = 2
+    }
+
+    internal enum XEventName
+    {
+        KeyPress = 2,
+        KeyRelease = 3,
+        ButtonPress = 4,
+        ButtonRelease = 5,
+        MotionNotify = 6,
+        EnterNotify = 7,
+        LeaveNotify = 8,
+        FocusIn = 9,
+        FocusOut = 10,
+        KeymapNotify = 11,
+        Expose = 12,
+        GraphicsExpose = 13,
+        NoExpose = 14,
+        VisibilityNotify = 15,
+        CreateNotify = 16,
+        DestroyNotify = 17,
+        UnmapNotify = 18,
+        MapNotify = 19,
+        MapRequest = 20,
+        ReparentNotify = 21,
+        ConfigureNotify = 22,
+        ConfigureRequest = 23,
+        GravityNotify = 24,
+        ResizeRequest = 25,
+        CirculateNotify = 26,
+        CirculateRequest = 27,
+        PropertyNotify = 28,
+        SelectionClear = 29,
+        SelectionRequest = 30,
+        SelectionNotify = 31,
+        ColormapNotify = 32,
+        ClientMessage = 33,
+        MappingNotify = 34,
+        GenericEvent = 35,
+
+        LASTEvent
+    }
+
+    [Flags]
+    internal enum SetWindowValuemask
+    {
+        Nothing = 0,
+        BackPixmap = 1,
+        BackPixel = 2,
+        BorderPixmap = 4,
+        BorderPixel = 8,
+        BitGravity = 16,
+        WinGravity = 32,
+        BackingStore = 64,
+        BackingPlanes = 128,
+        BackingPixel = 256,
+        OverrideRedirect = 512,
+        SaveUnder = 1024,
+        EventMask = 2048,
+        DontPropagate = 4096,
+        ColorMap = 8192,
+        Cursor = 16384
+    }
+
+    internal enum CreateWindowArgs
+    {
+        CopyFromParent = 0,
+        ParentRelative = 1,
+        InputOutput = 1,
+        InputOnly = 2
+    }
+
+    internal enum Gravity
+    {
+        ForgetGravity = 0,
+        NorthWestGravity = 1,
+        NorthGravity = 2,
+        NorthEastGravity = 3,
+        WestGravity = 4,
+        CenterGravity = 5,
+        EastGravity = 6,
+        SouthWestGravity = 7,
+        SouthGravity = 8,
+        SouthEastGravity = 9,
+        StaticGravity = 10
+    }
+
+    internal enum XKeySym : uint
+    {
+        XK_BackSpace = 0xFF08,
+        XK_Tab = 0xFF09,
+        XK_Clear = 0xFF0B,
+        XK_Return = 0xFF0D,
+        XK_Home = 0xFF50,
+        XK_Left = 0xFF51,
+        XK_Up = 0xFF52,
+        XK_Right = 0xFF53,
+        XK_Down = 0xFF54,
+        XK_Page_Up = 0xFF55,
+        XK_Page_Down = 0xFF56,
+        XK_End = 0xFF57,
+        XK_Begin = 0xFF58,
+        XK_Menu = 0xFF67,
+        XK_Shift_L = 0xFFE1,
+        XK_Shift_R = 0xFFE2,
+        XK_Control_L = 0xFFE3,
+        XK_Control_R = 0xFFE4,
+        XK_Caps_Lock = 0xFFE5,
+        XK_Shift_Lock = 0xFFE6,
+        XK_Meta_L = 0xFFE7,
+        XK_Meta_R = 0xFFE8,
+        XK_Alt_L = 0xFFE9,
+        XK_Alt_R = 0xFFEA,
+        XK_Super_L = 0xFFEB,
+        XK_Super_R = 0xFFEC,
+        XK_Hyper_L = 0xFFED,
+        XK_Hyper_R = 0xFFEE,
+    }
+
+#pragma warning disable 1591
+
+    [Flags]
+    public enum EventMask
+    {
+        NoEventMask = 0,
+        KeyPressMask = 1 << 0,
+        KeyReleaseMask = 1 << 1,
+        ButtonPressMask = 1 << 2,
+        ButtonReleaseMask = 1 << 3,
+        EnterWindowMask = 1 << 4,
+        LeaveWindowMask = 1 << 5,
+        PointerMotionMask = 1 << 6,
+        PointerMotionHintMask = 1 << 7,
+        Button1MotionMask = 1 << 8,
+        Button2MotionMask = 1 << 9,
+        Button3MotionMask = 1 << 10,
+        Button4MotionMask = 1 << 11,
+        Button5MotionMask = 1 << 12,
+        ButtonMotionMask = 1 << 13,
+        KeymapStateMask = 1 << 14,
+        ExposureMask = 1 << 15,
+        VisibilityChangeMask = 1 << 16,
+        StructureNotifyMask = 1 << 17,
+        ResizeRedirectMask = 1 << 18,
+        SubstructureNotifyMask = 1 << 19,
+        SubstructureRedirectMask = 1 << 20,
+        FocusChangeMask = 1 << 21,
+        PropertyChangeMask = 1 << 22,
+        ColormapChangeMask = 1 << 23,
+        OwnerGrabButtonMask = 1 << 24
+    }
+
+#pragma warning restore 1591
+
+    internal enum GrabMode
+    {
+        GrabModeSync = 0,
+        GrabModeAsync = 1
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XStandardColormap
+    {
+        public IntPtr colormap;
+        public IntPtr red_max;
+        public IntPtr red_mult;
+        public IntPtr green_max;
+        public IntPtr green_mult;
+        public IntPtr blue_max;
+        public IntPtr blue_mult;
+        public IntPtr base_pixel;
+        public IntPtr visualid;
+        public IntPtr killid;
+    }
+
+    [StructLayout(LayoutKind.Sequential, Pack = 2)]
+    internal struct XColor
+    {
+        public IntPtr pixel;
+        public ushort red;
+        public ushort green;
+        public ushort blue;
+        public byte flags;
+        public byte pad;
+    }
+
+    internal enum AtomName
+    {
+        AnyPropertyType = 0,
+        XA_PRIMARY = 1,
+        XA_SECONDARY = 2,
+        XA_ARC = 3,
+        XA_ATOM = 4,
+        XA_BITMAP = 5,
+        XA_CARDINAL = 6,
+        XA_COLORMAP = 7,
+        XA_CURSOR = 8,
+        XA_CUT_BUFFER0 = 9,
+        XA_CUT_BUFFER1 = 10,
+        XA_CUT_BUFFER2 = 11,
+        XA_CUT_BUFFER3 = 12,
+        XA_CUT_BUFFER4 = 13,
+        XA_CUT_BUFFER5 = 14,
+        XA_CUT_BUFFER6 = 15,
+        XA_CUT_BUFFER7 = 16,
+        XA_DRAWABLE = 17,
+        XA_FONT = 18,
+        XA_INTEGER = 19,
+        XA_PIXMAP = 20,
+        XA_POINT = 21,
+        XA_RECTANGLE = 22,
+        XA_RESOURCE_MANAGER = 23,
+        XA_RGB_COLOR_MAP = 24,
+        XA_RGB_BEST_MAP = 25,
+        XA_RGB_BLUE_MAP = 26,
+        XA_RGB_DEFAULT_MAP = 27,
+        XA_RGB_GRAY_MAP = 28,
+        XA_RGB_GREEN_MAP = 29,
+        XA_RGB_RED_MAP = 30,
+        XA_STRING = 31,
+        XA_VISUALID = 32,
+        XA_WINDOW = 33,
+        XA_WM_COMMAND = 34,
+        XA_WM_HINTS = 35,
+        XA_WM_CLIENT_MACHINE = 36,
+        XA_WM_ICON_NAME = 37,
+        XA_WM_ICON_SIZE = 38,
+        XA_WM_NAME = 39,
+        XA_WM_NORMAL_HINTS = 40,
+        XA_WM_SIZE_HINTS = 41,
+        XA_WM_ZOOM_HINTS = 42,
+        XA_MIN_SPACE = 43,
+        XA_NORM_SPACE = 44,
+        XA_MAX_SPACE = 45,
+        XA_END_SPACE = 46,
+        XA_SUPERSCRIPT_X = 47,
+        XA_SUPERSCRIPT_Y = 48,
+        XA_SUBSCRIPT_X = 49,
+        XA_SUBSCRIPT_Y = 50,
+        XA_UNDERLINE_POSITION = 51,
+        XA_UNDERLINE_THICKNESS = 52,
+        XA_STRIKEOUT_ASCENT = 53,
+        XA_STRIKEOUT_DESCENT = 54,
+        XA_ITALIC_ANGLE = 55,
+        XA_X_HEIGHT = 56,
+        XA_QUAD_WIDTH = 57,
+        XA_WEIGHT = 58,
+        XA_POINT_SIZE = 59,
+        XA_RESOLUTION = 60,
+        XA_COPYRIGHT = 61,
+        XA_NOTICE = 62,
+        XA_FONT_NAME = 63,
+        XA_FAMILY_NAME = 64,
+        XA_FULL_NAME = 65,
+        XA_CAP_HEIGHT = 66,
+        XA_WM_CLASS = 67,
+        XA_WM_TRANSIENT_FOR = 68,
+
+        XA_LAST_PREDEFINED = 68
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XScreen
+    {
+        public IntPtr ext_data;
+        public IntPtr display;
+        public IntPtr root;
+        public int width;
+        public int height;
+        public int mwidth;
+        public int mheight;
+        public int ndepths;
+        public IntPtr depths;
+        public int root_depth;
+        public IntPtr root_visual;
+        public IntPtr default_gc;
+        public IntPtr cmap;
+        public IntPtr white_pixel;
+        public IntPtr black_pixel;
+        public int max_maps;
+        public int min_maps;
+        public int backing_store;
+        public bool save_unders;
+        public IntPtr root_input_mask;
+    }
+
+    [Flags]
+    internal enum ChangeWindowAttributes
+    {
+        X = 1 << 0,
+        Y = 1 << 1,
+        Width = 1 << 2,
+        Height = 1 << 3,
+        BorderWidth = 1 << 4,
+        Sibling = 1 << 5,
+        StackMode = 1 << 6,
+
+        //BackPixmap    (1L<<0)
+        //BackPixel    (1L<<1)
+        //SaveUnder    (1L<<10)
+        //EventMask    (1L<<11)
+        //DontPropagate    (1L<<12)
+        //Colormap    (1L<<13)
+        //Cursor    (1L<<14)
+        //BorderPixmap    (1L<<2)
+        //BorderPixel    (1L<<3)
+        //BitGravity    (1L<<4)
+        //WinGravity    (1L<<5)
+        //BackingStore    (1L<<6)
+        //BackingPlanes    (1L<<7)
+        //BackingPixel    (1L<<8)
+        OverrideRedirect = 1<<9,
+    }
+
+    internal enum StackMode
+    {
+        Above = 0,
+        Below = 1,
+        TopIf = 2,
+        BottomIf = 3,
+        Opposite = 4
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XWindowChanges
+    {
+        public int x;
+        public int y;
+        public int width;
+        public int height;
+        public int border_width;
+        public IntPtr sibling;
+        public StackMode stack_mode;
+    }
+
+    [Flags]
+    internal enum ColorFlags
+    {
+        DoRed = 1 << 0,
+        DoGreen = 1 << 1,
+        DoBlue = 1 << 2
+    }
+
+    internal enum NotifyMode
+    {
+        NotifyNormal = 0,
+        NotifyGrab = 1,
+        NotifyUngrab = 2
+    }
+
+    internal enum NotifyDetail
+    {
+        NotifyAncestor = 0,
+        NotifyVirtual = 1,
+        NotifyInferior = 2,
+        NotifyNonlinear = 3,
+        NotifyNonlinearVirtual = 4,
+        NotifyPointer = 5,
+        NotifyPointerRoot = 6,
+        NotifyDetailNone = 7
+    }
+
+    [Flags]
+    internal enum KeyMasks
+    {
+        ShiftMask = (1 << 0),
+        LockMask = (1 << 1),
+        ControlMask = (1 << 2),
+        Mod1Mask = (1 << 3),
+        Mod2Mask = (1 << 4),
+        Mod3Mask = (1 << 5),
+        Mod4Mask = (1 << 6),
+        Mod5Mask = (1 << 7),
+
+        ModMasks = Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XModifierKeymap
+    {
+        public int max_keypermod;
+        public IntPtr modifiermap;
+    }
+
+    internal enum PropertyMode
+    {
+        Replace = 0,
+        Prepend = 1,
+        Append = 2
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XKeyBoardState
+    {
+        public int key_click_percent;
+        public int bell_percent;
+        public uint bell_pitch, bell_duration;
+        public IntPtr led_mask;
+        public int global_auto_repeat;
+        public AutoRepeats auto_repeats;
+
+        [StructLayout(LayoutKind.Explicit)]
+        internal struct AutoRepeats
+        {
+            [FieldOffset(0)]
+            public byte first;
+
+            [FieldOffset(31)]
+            public byte last;
+        }
+    }
+
+    [Flags]
+    internal enum GCFunction
+    {
+        GCFunction = 1 << 0,
+        GCPlaneMask = 1 << 1,
+        GCForeground = 1 << 2,
+        GCBackground = 1 << 3,
+        GCLineWidth = 1 << 4,
+        GCLineStyle = 1 << 5,
+        GCCapStyle = 1 << 6,
+        GCJoinStyle = 1 << 7,
+        GCFillStyle = 1 << 8,
+        GCFillRule = 1 << 9,
+        GCTile = 1 << 10,
+        GCStipple = 1 << 11,
+        GCTileStipXOrigin = 1 << 12,
+        GCTileStipYOrigin = 1 << 13,
+        GCFont = 1 << 14,
+        GCSubwindowMode = 1 << 15,
+        GCGraphicsExposures = 1 << 16,
+        GCClipXOrigin = 1 << 17,
+        GCClipYOrigin = 1 << 18,
+        GCClipMask = 1 << 19,
+        GCDashOffset = 1 << 20,
+        GCDashList = 1 << 21,
+        GCArcMode = 1 << 22
+    }
+
+    internal enum GCJoinStyle
+    {
+        JoinMiter = 0,
+        JoinRound = 1,
+        JoinBevel = 2
+    }
+
+    internal enum GCLineStyle
+    {
+        LineSolid = 0,
+        LineOnOffDash = 1,
+        LineDoubleDash = 2
+    }
+
+    internal enum GCCapStyle
+    {
+        CapNotLast = 0,
+        CapButt = 1,
+        CapRound = 2,
+        CapProjecting = 3
+    }
+
+    internal enum GCFillStyle
+    {
+        FillSolid = 0,
+        FillTiled = 1,
+        FillStippled = 2,
+        FillOpaqueStppled = 3
+    }
+
+    internal enum GCFillRule
+    {
+        EvenOddRule = 0,
+        WindingRule = 1
+    }
+
+    internal enum GCArcMode
+    {
+        ArcChord = 0,
+        ArcPieSlice = 1
+    }
+
+    internal enum GCSubwindowMode
+    {
+        ClipByChildren = 0,
+        IncludeInferiors = 1
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XGCValues
+    {
+        public GXFunction function;
+        public IntPtr plane_mask;
+        public IntPtr foreground;
+        public IntPtr background;
+        public int line_width;
+        public GCLineStyle line_style;
+        public GCCapStyle cap_style;
+        public GCJoinStyle join_style;
+        public GCFillStyle fill_style;
+        public GCFillRule fill_rule;
+        public GCArcMode arc_mode;
+        public IntPtr tile;
+        public IntPtr stipple;
+        public int ts_x_origin;
+        public int ts_y_origin;
+        public IntPtr font;
+        public GCSubwindowMode subwindow_mode;
+        public bool graphics_exposures;
+        public int clip_x_origin;
+        public int clib_y_origin;
+        public IntPtr clip_mask;
+        public int dash_offset;
+        public byte dashes;
+    }
+
+    internal enum GXFunction
+    {
+        GXclear = 0x0,        /* 0 */
+        GXand = 0x1,        /* src AND dst */
+        GXandReverse = 0x2,        /* src AND NOT dst */
+        GXcopy = 0x3,        /* src */
+        GXandInverted = 0x4,        /* NOT src AND dst */
+        GXnoop = 0x5,        /* dst */
+        GXxor = 0x6,        /* src XOR dst */
+        GXor = 0x7,        /* src OR dst */
+        GXnor = 0x8,        /* NOT src AND NOT dst */
+        GXequiv = 0x9,        /* NOT src XOR dst */
+        GXinvert = 0xa,        /* NOT dst */
+        GXorReverse = 0xb,        /* src OR NOT dst */
+        GXcopyInverted = 0xc,        /* NOT src */
+        GXorInverted = 0xd,        /* NOT src OR dst */
+        GXnand = 0xe,        /* NOT src OR NOT dst */
+        GXset = 0xf        /* 1 */
+    }
+
+    internal enum NetWindowManagerState
+    {
+        Remove = 0,
+        Add = 1,
+        Toggle = 2
+    }
+
+    internal enum RevertTo
+    {
+        None = 0,
+        PointerRoot = 1,
+        Parent = 2
+    }
+
+    internal enum MapState
+    {
+        IsUnmapped = 0,
+        IsUnviewable = 1,
+        IsViewable = 2
+    }
+
+    internal enum CursorFontShape
+    {
+        XC_X_cursor = 0,
+        XC_arrow = 2,
+        XC_based_arrow_down = 4,
+        XC_based_arrow_up = 6,
+        XC_boat = 8,
+        XC_bogosity = 10,
+        XC_bottom_left_corner = 12,
+        XC_bottom_right_corner = 14,
+        XC_bottom_side = 16,
+        XC_bottom_tee = 18,
+        XC_box_spiral = 20,
+        XC_center_ptr = 22,
+
+        XC_circle = 24,
+        XC_clock = 26,
+        XC_coffee_mug = 28,
+        XC_cross = 30,
+        XC_cross_reverse = 32,
+        XC_crosshair = 34,
+        XC_diamond_cross = 36,
+        XC_dot = 38,
+        XC_dotbox = 40,
+        XC_double_arrow = 42,
+        XC_draft_large = 44,
+        XC_draft_small = 46,
+
+        XC_draped_box = 48,
+        XC_exchange = 50,
+        XC_fleur = 52,
+        XC_gobbler = 54,
+        XC_gumby = 56,
+        XC_hand1 = 58,
+        XC_hand2 = 60,
+        XC_heart = 62,
+        XC_icon = 64,
+        XC_iron_cross = 66,
+        XC_left_ptr = 68,
+        XC_left_side = 70,
+
+        XC_left_tee = 72,
+        XC_left_button = 74,
+        XC_ll_angle = 76,
+        XC_lr_angle = 78,
+        XC_man = 80,
+        XC_middlebutton = 82,
+        XC_mouse = 84,
+        XC_pencil = 86,
+        XC_pirate = 88,
+        XC_plus = 90,
+        XC_question_arrow = 92,
+        XC_right_ptr = 94,
+
+        XC_right_side = 96,
+        XC_right_tee = 98,
+        XC_rightbutton = 100,
+        XC_rtl_logo = 102,
+        XC_sailboat = 104,
+        XC_sb_down_arrow = 106,
+        XC_sb_h_double_arrow = 108,
+        XC_sb_left_arrow = 110,
+        XC_sb_right_arrow = 112,
+        XC_sb_up_arrow = 114,
+        XC_sb_v_double_arrow = 116,
+        XC_sb_shuttle = 118,
+
+        XC_sizing = 120,
+        XC_spider = 122,
+        XC_spraycan = 124,
+        XC_star = 126,
+        XC_target = 128,
+        XC_tcross = 130,
+        XC_top_left_arrow = 132,
+        XC_top_left_corner = 134,
+        XC_top_right_corner = 136,
+        XC_top_side = 138,
+        XC_top_tee = 140,
+        XC_trek = 142,
+
+        XC_ul_angle = 144,
+        XC_umbrella = 146,
+        XC_ur_angle = 148,
+        XC_watch = 150,
+        XC_xterm = 152,
+        XC_num_glyphs = 154
+    }
+
+    internal enum SystrayRequest
+    {
+        SYSTEM_TRAY_REQUEST_DOCK = 0,
+        SYSTEM_TRAY_BEGIN_MESSAGE = 1,
+        SYSTEM_TRAY_CANCEL_MESSAGE = 2
+    }
+
+    [Flags]
+    internal enum XSizeHintsFlags
+    {
+        USPosition = (1 << 0),
+        USSize = (1 << 1),
+        PPosition = (1 << 2),
+        PSize = (1 << 3),
+        PMinSize = (1 << 4),
+        PMaxSize = (1 << 5),
+        PResizeInc = (1 << 6),
+        PAspect = (1 << 7),
+        PAllHints = (PPosition | PSize | PMinSize | PMaxSize | PResizeInc | PAspect),
+        PBaseSize = (1 << 8),
+        PWinGravity = (1 << 9),
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XSizeHints
+    {
+        public IntPtr flags;
+        public int x;
+        public int y;
+        public int width;
+        public int height;
+        public int min_width;
+        public int min_height;
+        public int max_width;
+        public int max_height;
+        public int width_inc;
+        public int height_inc;
+        public int min_aspect_x;
+        public int min_aspect_y;
+        public int max_aspect_x;
+        public int max_aspect_y;
+        public int base_width;
+        public int base_height;
+        public int win_gravity;
+    }
+
+    [Flags]
+    internal enum XWMHintsFlags
+    {
+        InputHint = (1 << 0),
+        StateHint = (1 << 1),
+        IconPixmapHint = (1 << 2),
+        IconWindowHint = (1 << 3),
+        IconPositionHint = (1 << 4),
+        IconMaskHint = (1 << 5),
+        WindowGroupHint = (1 << 6),
+        AllHints = (InputHint | StateHint | IconPixmapHint | IconWindowHint | IconPositionHint | IconMaskHint | WindowGroupHint)
+    }
+
+    internal enum XInitialState
+    {
+        DontCareState = 0,
+        NormalState = 1,
+        ZoomState = 2,
+        IconicState = 3,
+        InactiveState = 4
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XWMHints
+    {
+        public IntPtr flags;
+        public bool input;
+        public XInitialState initial_state;
+        public IntPtr icon_pixmap;
+        public IntPtr icon_window;
+        public int icon_x;
+        public int icon_y;
+        public IntPtr icon_mask;
+        public IntPtr window_group;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct XIconSize
+    {
+        public int min_width;
+        public int min_height;
+        public int max_width;
+        public int max_height;
+        public int width_inc;
+        public int height_inc;
+    }
+
+    internal delegate int XErrorHandler(IntPtr DisplayHandle, ref XErrorEvent error_event);
+
+    internal enum XRequest : byte
+    {
+        X_CreateWindow = 1,
+        X_ChangeWindowAttributes = 2,
+        X_GetWindowAttributes = 3,
+        X_DestroyWindow = 4,
+        X_DestroySubwindows = 5,
+        X_ChangeSaveSet = 6,
+        X_ReparentWindow = 7,
+        X_MapWindow = 8,
+        X_MapSubwindows = 9,
+        X_UnmapWindow = 10,
+        X_UnmapSubwindows = 11,
+        X_ConfigureWindow = 12,
+        X_CirculateWindow = 13,
+        X_GetGeometry = 14,
+        X_QueryTree = 15,
+        X_InternAtom = 16,
+        X_GetAtomName = 17,
+        X_ChangeProperty = 18,
+        X_DeleteProperty = 19,
+        X_GetProperty = 20,
+        X_ListProperties = 21,
+        X_SetSelectionOwner = 22,
+        X_GetSelectionOwner = 23,
+        X_ConvertSelection = 24,
+        X_SendEvent = 25,
+        X_GrabPointer = 26,
+        X_UngrabPointer = 27,
+        X_GrabButton = 28,
+        X_UngrabButton = 29,
+        X_ChangeActivePointerGrab = 30,
+        X_GrabKeyboard = 31,
+        X_UngrabKeyboard = 32,
+        X_GrabKey = 33,
+        X_UngrabKey = 34,
+        X_AllowEvents = 35,
+        X_GrabServer = 36,
+        X_UngrabServer = 37,
+        X_QueryPointer = 38,
+        X_GetMotionEvents = 39,
+        X_TranslateCoords = 40,
+        X_WarpPointer = 41,
+        X_SetInputFocus = 42,
+        X_GetInputFocus = 43,
+        X_QueryKeymap = 44,
+        X_OpenFont = 45,
+        X_CloseFont = 46,
+        X_QueryFont = 47,
+        X_QueryTextExtents = 48,
+        X_ListFonts = 49,
+        X_ListFontsWithInfo = 50,
+        X_SetFontPath = 51,
+        X_GetFontPath = 52,
+        X_CreatePixmap = 53,
+        X_FreePixmap = 54,
+        X_CreateGC = 55,
+        X_ChangeGC = 56,
+        X_CopyGC = 57,
+        X_SetDashes = 58,
+        X_SetClipRectangles = 59,
+        X_FreeGC = 60,
+        X_ClearArea = 61,
+        X_CopyArea = 62,
+        X_CopyPlane = 63,
+        X_PolyPoint = 64,
+        X_PolyLine = 65,
+        X_PolySegment = 66,
+        X_PolyRectangle = 67,
+        X_PolyArc = 68,
+        X_FillPoly = 69,
+        X_PolyFillRectangle = 70,
+        X_PolyFillArc = 71,
+        X_PutImage = 72,
+        X_GetImage = 73,
+        X_PolyText8 = 74,
+        X_PolyText16 = 75,
+        X_ImageText8 = 76,
+        X_ImageText16 = 77,
+        X_CreateColormap = 78,
+        X_FreeColormap = 79,
+        X_CopyColormapAndFree = 80,
+        X_InstallColormap = 81,
+        X_UninstallColormap = 82,
+        X_ListInstalledColormaps = 83,
+        X_AllocColor = 84,
+        X_AllocNamedColor = 85,
+        X_AllocColorCells = 86,
+        X_AllocColorPlanes = 87,
+        X_FreeColors = 88,
+        X_StoreColors = 89,
+        X_StoreNamedColor = 90,
+        X_QueryColors = 91,
+        X_LookupColor = 92,
+        X_CreateCursor = 93,
+        X_CreateGlyphCursor = 94,
+        X_FreeCursor = 95,
+        X_RecolorCursor = 96,
+        X_QueryBestSize = 97,
+        X_QueryExtension = 98,
+        X_ListExtensions = 99,
+        X_ChangeKeyboardMapping = 100,
+        X_GetKeyboardMapping = 101,
+        X_ChangeKeyboardControl = 102,
+        X_GetKeyboardControl = 103,
+        X_Bell = 104,
+        X_ChangePointerControl = 105,
+        X_GetPointerControl = 106,
+        X_SetScreenSaver = 107,
+        X_GetScreenSaver = 108,
+        X_ChangeHosts = 109,
+        X_ListHosts = 110,
+        X_SetAccessControl = 111,
+        X_SetCloseDownMode = 112,
+        X_KillClient = 113,
+        X_RotateProperties = 114,
+        X_ForceScreenSaver = 115,
+        X_SetPointerMapping = 116,
+        X_GetPointerMapping = 117,
+        X_SetModifierMapping = 118,
+        X_GetModifierMapping = 119,
+        X_NoOperation = 127
+    }
+
+    [Flags]
+    internal enum XIMProperties
+    {
+        XIMPreeditArea = 0x0001,
+        XIMPreeditCallbacks = 0x0002,
+        XIMPreeditPosition = 0x0004,
+        XIMPreeditNothing = 0x0008,
+        XIMPreeditNone = 0x0010,
+        XIMStatusArea = 0x0100,
+        XIMStatusCallbacks = 0x0200,
+        XIMStatusNothing = 0x0400,
+        XIMStatusNone = 0x0800,
+    }
+
+    [Flags]
+    internal enum WindowType
+    {
+        Client = 1,
+        Whole = 2,
+        Both = 3
+    }
+
+    internal enum XEmbedMessage
+    {
+        EmbeddedNotify = 0,
+        WindowActivate = 1,
+        WindowDeactivate = 2,
+        RequestFocus = 3,
+        FocusIn = 4,
+        FocusOut = 5,
+        FocusNext = 6,
+        FocusPrev = 7,
+        /* 8-9 were used for XEMBED_GRAB_KEY/XEMBED_UNGRAB_KEY */
+        ModalityOn = 10,
+        ModalityOff = 11,
+        RegisterAccelerator = 12,
+        UnregisterAccelerator = 13,
+        ActivateAccelerator = 14
+    }
+
+    internal enum ImageFormat
+    {
+        XYPixmap = 1,
+        ZPixmap
+    }
+
+    // XInput2 structures
+
+    enum XIClassType
+    {
+        Button = 1,
+        Valuator = 2,
+        Scroll = 3,
+    }
+
+    enum XIScrollType
+    {
+        Vertical = 1,
+        Horizontal = 2
+    }
+
+    struct XIDeviceInfo
+    {
+        public int deviceid;
+        public IntPtr name; // byte*
+        public XIDeviceType use;
+        public int attachment;
+        public Bool enabled;
+        public int num_classes;
+        public IntPtr classes; // XIAnyClassInfo**
+    }
+
+    struct XIAnyClassInfo
+    {
+        public XIClassType type;
+        public int sourceid;
+    }
+
+    struct XIButtonClassInfo
+    {
+        public XIClassType type;
+        public int sourceid;
+        public int num_buttons;
+        public IntPtr labels; // Atom*
+        public XIButtonState state;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    struct XIScrollClassInfo
+    {
+        public XIClassType type;
+        public int sourceid;
+        public int number;
+        public XIScrollType scroll_type;
+        public double increment;
+        public int flags;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    struct XIValuatorClassInfo
+    {
+        public XIClassType type;
+        public int sourceid;
+        public int number;
+        public IntPtr label;
+        public double min;
+        public double max;
+        public double value;
+        public int resolution;
+        public XIMode mode;
+    }
+
+    struct XIDeviceEvent
+    {
+        public int           type;         /* GenericEvent */
+        public IntPtr serial;       /* # of last request processed by server */
+        public bool          send_event;   /* true if this came from a SendEvent request */
+        public IntPtr display;     /* Display the event was read from */
+        public int           extension;    /* XI extension offset */
+        public XIEventType           evtype;
+        public Time          time;
+        public int           deviceid;
+        public int           sourceid;
+        public int           detail;
+        public Window        root;
+        public Window        @event;
+        public Window        child;
+        public double        root_x;
+        public double        root_y;
+        public double        event_x;
+        public double        event_y;
+        public XIEventFlags        flags;
+        public XIButtonState       buttons;
+        public XIValuatorState     valuators;
+        public XIModifierState     mods;
+        public XIGroupState        @group;
+    }
+
+    struct XIRawEvent
+    {
+        public int           type;         /* GenericEvent */
+        public IntPtr serial;       /* # of last request processed by server */
+        public Bool          send_event;   /* true if this came from a SendEvent request */
+        public IntPtr display;     /* Display the event was read from */
+        public int           extension;    /* XI extension offset */
+        public XIEventType   evtype;       /* XI_RawKeyPress, XI_RawKeyRelease, etc. */
+        public Time          time;
+        public int           deviceid;
+        public int           sourceid;
+        public int           detail;
+        public XIEventFlags  flags;
+        public XIValuatorState valuators;
+        public IntPtr raw_values; // FP3232*
+    }
+
+    struct XIButtonState
+    {
+        public int           mask_len;
+        public IntPtr mask; // byte*
+    }
+
+    struct XIModifierState
+    {
+        public int    @base;
+        public int    latched;
+        public int    locked;
+        public int    effective;
+    }
+
+    struct XIGroupState
+    {
+        public int    @base;
+        public int    latched;
+        public int    locked;
+        public int    effective;
+    }
+
+    struct XIValuatorState
+    {
+        public int           mask_len;
+        public IntPtr mask; // byte*
+        public IntPtr values; // double*
+    }
+
+    struct XIEventMask : IDisposable
+    {
+        public int deviceid; // 0 = XIAllDevices, 1 = XIAllMasterDevices
+        int mask_len;
+        unsafe byte* mask;
+
+        public XIEventMask(int id, XIEventMasks m)
+        {
+            deviceid = id;
+            mask_len = sizeof(XIEventMasks);
+            unsafe
+            {
+                mask = (byte*)Marshal.AllocHGlobal(mask_len);
+                for (int i = 0; i < mask_len; i++)
+                    mask[i] = (byte)((uint)m >> i*8);
+            }
+        }
+
+        public void Dispose()
+        {
+            unsafe
+            {
+                Marshal.FreeHGlobal(new IntPtr((void*)mask));
+            }
+        }
+    }
+
+    enum XIEventType
+    {
+        DeviceChanged = 1,
+        KeyPress,
+        KeyRelease,
+        ButtonPress,
+        ButtonRelease,
+        Motion,
+        Enter,
+        Leave,
+        FocusIn,
+        FocusOut,
+        HierarchyChanged,
+        PropertyEvent,
+        RawKeyPress,
+        RawKeyRelease,
+        RawButtonPress,
+        RawButtonRelease,
+        RawMotion,
+        LastEvent = RawMotion
+    }
+
+    enum XIEventMasks
+    {
+        DeviceChangedMask =            (1 << (int)XIEventType.DeviceChanged),
+        KeyPressMask =                 (1 << (int)XIEventType.KeyPress),
+        KeyReleaseMask =               (1 << (int)XIEventType.KeyRelease),
+        ButtonPressMask =              (1 << (int)XIEventType.ButtonPress),
+        ButtonReleaseMask =            (1 << (int)XIEventType.ButtonRelease),
+        MotionMask =                   (1 << (int)XIEventType.Motion),
+        EnterMask =                    (1 << (int)XIEventType.Enter),
+        LeaveMask =                    (1 << (int)XIEventType.Leave),
+        FocusInMask =                  (1 << (int)XIEventType.FocusIn),
+        FocusOutMask =                 (1 << (int)XIEventType.FocusOut),
+        HierarchyChangedMask =         (1 << (int)XIEventType.HierarchyChanged),
+        PropertyEventMask =            (1 << (int)XIEventType.PropertyEvent),
+        RawKeyPressMask =              (1 << (int)XIEventType.RawKeyPress),
+        RawKeyReleaseMask =            (1 << (int)XIEventType.RawKeyRelease),
+        RawButtonPressMask =           (1 << (int)XIEventType.RawButtonPress),
+        RawButtonReleaseMask =         (1 << (int)XIEventType.RawButtonRelease),
+        RawMotionMask =                (1 << (int)XIEventType.RawMotion),
+    }
+
+    [Flags]
+    enum XIKeyEventFlags
+    {
+        Repeat = (1 << 16),
+    }
+
+    [Flags]
+    enum XIPointerEventFlags
+    {
+        Emulated = (1 << 16),
+    }
+
+    [Flags]
+    enum XITouchEventFlags
+    {
+        PendingEnd = (1 << 16),
+        EmulatingPointer = (1 << 17),
+    }
+
+    [Flags]
+    enum XIEventFlags
+    {
+        KeyRepeat = XIKeyEventFlags.Repeat,
+        PointerEmulated = XIPointerEventFlags.Emulated,
+        TouchPendingEnd = XITouchEventFlags.PendingEnd,
+        TouchEmulatingPointer = XITouchEventFlags.EmulatingPointer
+    }
+}
diff --git a/CrowX/X11/X11DisplayDevice.cs b/CrowX/X11/X11DisplayDevice.cs
new file mode 100644 (file)
index 0000000..0ef8740
--- /dev/null
@@ -0,0 +1,472 @@
+#region License
+//
+// The Open Toolkit Library License
+//
+// Copyright (c) 2006 - 2010 the Open Toolkit library.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights to 
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+// the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+#if !MINIMAL
+using System.Drawing;
+#endif
+using System.Runtime.InteropServices;
+
+namespace X11Sharp
+{
+    sealed class X11DisplayDevice : DisplayDeviceBase
+    {
+        // Store a mapping between resolutions and their respective
+        // size_index (needed for XRRSetScreenConfig). The size_index
+        // is simply the sequence number of the resolution as returned by
+        // XRRSizes. This is done per available screen.
+        readonly List<Dictionary<DisplayResolution, int>> screenResolutionToIndex =
+            new List<Dictionary<DisplayResolution, int>>();
+        // Store a mapping between DisplayDevices and their default resolutions.
+        readonly Dictionary<DisplayDevice, int> deviceToDefaultResolution = new Dictionary<DisplayDevice, int>();
+        // Store a mapping between DisplayDevices and X11 screens.
+        readonly Dictionary<DisplayDevice, int> deviceToScreen = new Dictionary<DisplayDevice, int>();
+        // Keep the time when the config of each screen was last updated.
+        readonly List<IntPtr> lastConfigUpdate = new List<IntPtr>();
+
+        bool xinerama_supported, xrandr_supported, xf86_supported;
+        
+        #region Constructors
+
+        public X11DisplayDevice()
+        {
+            RefreshDisplayDevices();
+        }
+
+        #endregion
+
+        #region Private Methods
+
+        void RefreshDisplayDevices()
+        {
+            using (new XLock(API.DefaultDisplay))
+            {
+                List<DisplayDevice> devices = new List<DisplayDevice>();
+                xinerama_supported = false;
+                try
+                {
+                    xinerama_supported = QueryXinerama(devices);
+                }
+                catch
+                {
+                    Debug.Print("Xinerama query failed.");
+                }
+
+                if (!xinerama_supported)
+                {
+                    // We assume that devices are equivalent to the number of available screens.
+                    // Note: this won't work correctly in the case of distinct X servers.
+                    for (int i = 0; i < API.ScreenCount; i++)
+                    {
+                        DisplayDevice dev = new DisplayDevice();
+                        dev.IsPrimary = i == Functions.XDefaultScreen(API.DefaultDisplay);
+                        devices.Add(dev);
+                        deviceToScreen.Add(dev, i);
+                    }
+                }
+
+                try
+                {
+                    xrandr_supported = QueryXRandR(devices);
+                }
+                catch { }
+
+                if (!xrandr_supported)
+                {
+                    Debug.Print("XRandR query failed, falling back to XF86.");
+                    try
+                    {
+                        xf86_supported = QueryXF86(devices);
+                    }
+                    catch { }
+
+                    if (!xf86_supported)
+                    {
+                        Debug.Print("XF86 query failed, no DisplayDevice support available.");
+                    }
+                }
+
+                AvailableDevices.Clear();
+                AvailableDevices.AddRange(devices);
+                Primary = FindDefaultDevice(devices);
+            }
+        }
+
+        static DisplayDevice FindDefaultDevice(IEnumerable<DisplayDevice> devices)
+        {
+                foreach (DisplayDevice dev in devices)
+                    if (dev.IsPrimary)
+                        return dev;
+
+            throw new InvalidOperationException("No primary display found. Please file a bug at http://www.opentk.com");
+        }
+
+        bool QueryXinerama(List<DisplayDevice> devices)
+        {
+            // Try to use Xinerama to obtain the geometry of all output devices.
+            int event_base, error_base;
+            if (NativeMethods.XineramaQueryExtension(API.DefaultDisplay, out event_base, out error_base) &&
+                NativeMethods.XineramaIsActive(API.DefaultDisplay))
+            {
+                IList<XineramaScreenInfo> screens = NativeMethods.XineramaQueryScreens(API.DefaultDisplay);
+                bool first = true;
+                foreach (XineramaScreenInfo screen in screens)
+                {
+                    DisplayDevice dev = new DisplayDevice();
+                    dev.Bounds = new Rectangle(screen.X, screen.Y, screen.Width, screen.Height);
+                    if (first)
+                    {
+                        // We consider the first device returned by Xinerama as the primary one.
+                        // Makes sense conceptually, but is there a way to verify this?
+                        dev.IsPrimary = true;
+                        first = false;
+                    }
+                    devices.Add(dev);
+                    // It seems that all X screens are equal to 0 is Xinerama is enabled, at least on Nvidia (verify?)
+                    deviceToScreen.Add(dev, 0 /*screen.ScreenNumber*/);
+                }
+            }
+            return (devices.Count>0);
+        }
+
+        bool QueryXRandR(List<DisplayDevice> devices)
+        {
+            // Get available resolutions. Then, for each resolution get all available rates.
+            foreach (DisplayDevice dev in devices)
+            {
+                int screen = deviceToScreen[dev];
+
+                IntPtr timestamp_of_last_update;
+                Functions.XRRTimes(API.DefaultDisplay, screen, out timestamp_of_last_update);
+                lastConfigUpdate.Add(timestamp_of_last_update);
+
+                List<DisplayResolution> available_res = new List<DisplayResolution>();
+
+                // Add info for a new screen.
+                screenResolutionToIndex.Add(new Dictionary<DisplayResolution, int>());
+
+                int[] depths = FindAvailableDepths(screen);
+
+                int resolution_count = 0;
+                foreach (XRRScreenSize size in FindAvailableResolutions(screen))
+                {
+                    if (size.Width == 0 || size.Height == 0)
+                    {
+                        Debug.Print("[Warning] XRandR returned an invalid resolution ({0}) for display device {1}", size, screen);
+                        continue;
+                    }
+                    short[] rates = null;
+                    rates = Functions.XRRRates(API.DefaultDisplay, screen, resolution_count);
+
+                    // It seems that XRRRates returns 0 for modes that are larger than the screen
+                    // can support, as well as for all supported modes. On Ubuntu 7.10 the tool
+                    // "Screens and Graphics" does report these modes, though.
+                    foreach (short rate in rates)
+                    {
+                        // Note: some X servers (like Xming on Windows) do not report any rates other than 0.
+                        // If we only have 1 rate, add it even if it is 0.
+                        if (rate != 0 || rates.Length == 1)
+                            foreach (int depth in depths)
+                                available_res.Add(new DisplayResolution(0, 0, size.Width, size.Height, depth, (float)rate));
+                    }
+                    // Keep the index of this resolution - we will need it for resolution changes later.
+                    foreach (int depth in depths)
+                    {
+                        // Note that Xinerama may return multiple devices for a single screen. XRandR will
+                        // not distinguish between the two as far as resolutions are supported (since XRandR
+                        // operates on X screens, not display devices) - we need to be careful not to add the
+                        // same resolution twice!
+                        DisplayResolution res = new DisplayResolution(0, 0, size.Width, size.Height, depth, 0);
+                        if (!screenResolutionToIndex[screen].ContainsKey(res))
+                            screenResolutionToIndex[screen].Add(res, resolution_count);
+                    }
+
+                    ++resolution_count;
+                }
+
+
+                // The resolution of the current DisplayDevice is discovered through XRRConfigCurrentConfiguration.
+                // Its refresh rate is discovered by the FindCurrentRefreshRate call.
+                // Its depth is discovered by the FindCurrentDepth call.
+                float current_refresh_rate = FindCurrentRefreshRate(screen);
+                int current_depth = FindCurrentDepth(screen);
+                IntPtr screen_config = Functions.XRRGetScreenInfo(API.DefaultDisplay, Functions.XRootWindow(API.DefaultDisplay, screen));
+                ushort current_rotation;  // Not needed.
+                int current_resolution_index = Functions.XRRConfigCurrentConfiguration(screen_config, out current_rotation);
+
+                if (dev.Bounds == Rectangle.Empty)
+                {
+                    // We have added depths.Length copies of each resolution
+                    // Adjust the return value of XRRGetScreenInfo to retrieve the correct resolution
+                    int index = current_resolution_index * depths.Length;
+                    
+                    // Make sure we are within the bounds of the available_res array
+                    if (index >= available_res.Count)
+                    {
+                        // If not, use the return value of XRRGetScreenInfo directly
+                        index = current_resolution_index;
+                    }
+                    DisplayResolution current_resolution = available_res[index];
+                    dev.Bounds = new Rectangle(0, 0, current_resolution.Width, current_resolution.Height);
+                }
+                dev.BitsPerPixel = current_depth;
+                dev.RefreshRate = current_refresh_rate;
+                dev.AvailableResolutions = available_res;
+
+                deviceToDefaultResolution.Add(dev, current_resolution_index);
+            }
+
+            return true;
+        }
+
+        bool QueryXF86(List<DisplayDevice> devices)
+        {
+            int major;
+            int minor;
+
+            try
+            {
+                if (!API.XF86VidModeQueryVersion(API.DefaultDisplay, out major, out minor))
+                    return false;
+            }
+            catch (DllNotFoundException)
+            {
+                return false;
+            }
+            
+            int currentScreen = 0;
+            Debug.Print("Using XF86 v" + major.ToString() + "." + minor.ToString());
+
+            foreach (DisplayDevice dev in devices)
+            {
+                int count;
+
+                IntPtr srcArray;
+                API.XF86VidModeGetAllModeLines(API.DefaultDisplay, currentScreen, out count, out srcArray);
+                Debug.Print(count.ToString() + " modes detected on screen " + currentScreen.ToString());
+                IntPtr[] array = new IntPtr[count];
+                Marshal.Copy(srcArray, array, 0, count);
+                API.XF86VidModeModeInfo Mode = new API.XF86VidModeModeInfo();
+
+                int x;
+                int y;
+                API.XF86VidModeGetViewPort(API.DefaultDisplay, currentScreen, out x, out y);
+                List<DisplayResolution> resolutions = new List<DisplayResolution>();
+                for (int i = 0; i < count; i++)
+                {
+                    Mode = (API.XF86VidModeModeInfo)Marshal.PtrToStructure(array[i], typeof(API.XF86VidModeModeInfo));
+                    resolutions.Add(new DisplayResolution(x, y, Mode.hdisplay, Mode.vdisplay, 24, (Mode.dotclock * 1000F) / (Mode.vtotal * Mode.htotal)));
+                }
+
+                dev.AvailableResolutions = resolutions;
+                int pixelClock;
+                API.XF86VidModeModeLine currentMode;
+                API.XF86VidModeGetModeLine(API.DefaultDisplay, currentScreen, out pixelClock, out currentMode);
+                dev.Bounds = new Rectangle(x, y, currentMode.hdisplay, (currentMode.vdisplay == 0) ? currentMode.vsyncstart : currentMode.vdisplay);
+                dev.BitsPerPixel = FindCurrentDepth(currentScreen);
+                dev.RefreshRate = (pixelClock * 1000F) / (currentMode.vtotal * currentMode.htotal);
+                currentScreen++;
+            }
+            return true;
+        }
+
+        #region static int[] FindAvailableDepths(int screen)
+
+        static int[] FindAvailableDepths(int screen)
+        {
+            return Functions.XListDepths(API.DefaultDisplay, screen);
+        }
+
+        #endregion
+
+        #region static XRRScreenSize[] FindAvailableResolutions(int screen)
+
+        static XRRScreenSize[] FindAvailableResolutions(int screen)
+        {
+            XRRScreenSize[] resolutions = null;
+            resolutions = Functions.XRRSizes(API.DefaultDisplay, screen);
+            if (resolutions == null)
+                throw new NotSupportedException("XRandR extensions not available.");
+            return resolutions;
+        }
+
+        #endregion
+
+        #region static float FindCurrentRefreshRate(int screen)
+
+        static float FindCurrentRefreshRate(int screen)
+        {
+            short rate = 0;
+            IntPtr screen_config = Functions.XRRGetScreenInfo(API.DefaultDisplay, Functions.XRootWindow(API.DefaultDisplay, screen));
+            rate = Functions.XRRConfigCurrentRate(screen_config);
+            Functions.XRRFreeScreenConfigInfo(screen_config);
+            return (float)rate;
+        }
+
+        #endregion
+
+        #region private static int FindCurrentDepth(int screen)
+
+        static int FindCurrentDepth(int screen)
+        {
+            return (int)Functions.XDefaultDepth(API.DefaultDisplay, screen);
+        }
+
+        #endregion
+
+        bool ChangeResolutionXRandR(DisplayDevice device, DisplayResolution resolution)
+        {
+            using (new XLock(API.DefaultDisplay))
+            {
+                int screen = deviceToScreen[device];
+                IntPtr root = Functions.XRootWindow(API.DefaultDisplay, screen);
+                IntPtr screen_config = Functions.XRRGetScreenInfo(API.DefaultDisplay, root);
+
+                ushort current_rotation;
+                int current_resolution_index = Functions.XRRConfigCurrentConfiguration(screen_config, out current_rotation);
+                int new_resolution_index;
+                if (resolution != null)
+                    new_resolution_index = screenResolutionToIndex[screen]
+                        [new DisplayResolution(0, 0, resolution.Width, resolution.Height, resolution.BitsPerPixel, 0)];
+                else
+                    new_resolution_index = deviceToDefaultResolution[device];
+
+                Debug.Print("Changing size of screen {0} from {1} to {2}",
+                    screen, current_resolution_index, new_resolution_index);
+
+                int ret = 0;
+                short refresh_rate =(short)(resolution != null ? resolution.RefreshRate : 0);
+                if (refresh_rate > 0)
+                {
+                    ret = Functions.XRRSetScreenConfigAndRate(API.DefaultDisplay,
+                    screen_config, root, new_resolution_index, current_rotation,
+                    refresh_rate, IntPtr.Zero);
+                }
+                else
+                {
+                    ret = Functions.XRRSetScreenConfig(API.DefaultDisplay,
+                    screen_config, root, new_resolution_index, current_rotation,
+                    IntPtr.Zero);
+                }
+
+                if (ret != 0)
+                {
+                    Debug.Print("[Error] Change to resolution {0} failed with error {1}.",
+                        resolution, (ErrorCode)ret);
+                }
+
+                return ret == 0;
+            }
+        }
+
+        static bool ChangeResolutionXF86(DisplayDevice device, DisplayResolution resolution)
+        {
+            return false;
+        }
+
+        #endregion
+
+        #region IDisplayDeviceDriver Members
+
+        public sealed override bool TryChangeResolution(DisplayDevice device, DisplayResolution resolution)
+        {
+            // If resolution is null, restore the default resolution (new_resolution_index = 0).
+
+            if (xrandr_supported)
+            {
+                return ChangeResolutionXRandR(device, resolution);
+            }
+            else if (xf86_supported)
+            {
+                return ChangeResolutionXF86(device, resolution);
+            }
+            else
+            {
+                return false;
+            }
+        }
+
+        public sealed override bool TryRestoreResolution(DisplayDevice device)
+        {
+            return TryChangeResolution(device, null);
+        }
+
+        #endregion
+
+        #region NativeMethods
+
+        static class NativeMethods
+        {
+            const string Xinerama = "libXinerama";
+
+            [DllImport(Xinerama)]
+            public static extern bool XineramaQueryExtension(IntPtr dpy, out int event_basep, out int error_basep);
+
+            [DllImport(Xinerama)]
+            public static extern int XineramaQueryVersion (IntPtr dpy, out int major_versionp, out int minor_versionp);
+
+            [DllImport(Xinerama)]
+            public static extern bool XineramaIsActive(IntPtr dpy);
+
+            [DllImport(Xinerama)]
+            static extern IntPtr XineramaQueryScreens(IntPtr dpy, out int number);
+
+            public static IList<XineramaScreenInfo> XineramaQueryScreens(IntPtr dpy)
+            {
+                int number;
+                IntPtr screen_ptr = XineramaQueryScreens(dpy, out number);
+                List<XineramaScreenInfo> screens = new List<XineramaScreenInfo>(number);
+
+                unsafe
+                {
+                    XineramaScreenInfo* ptr = (XineramaScreenInfo*)screen_ptr;
+                    while (--number >= 0)
+                    {
+                        screens.Add(*ptr);
+                        ptr++;
+                    }
+                }
+
+                return screens;
+            }
+        }
+
+        [StructLayout(LayoutKind.Sequential, Pack = 1)]
+        struct XineramaScreenInfo
+        {
+            public int ScreenNumber;
+            public short X;
+            public short Y;
+            public short Width;
+            public short Height;
+        }
+
+        #endregion
+    }
+}
diff --git a/CrowX/X11/X11Input.cs b/CrowX/X11/X11Input.cs
new file mode 100644 (file)
index 0000000..d84f9f7
--- /dev/null
@@ -0,0 +1,59 @@
+#region License
+//
+// X11Input.cs
+//
+// Author:
+//       thefiddler <stapostol@gmail.com>
+//
+// Copyright (c) 2006-2014 
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+#endregion
+
+using System;
+using System.Diagnostics;
+using OpenTK.Input;
+
+namespace X11Sharp
+{
+    class X11Input 
+    {
+        readonly X11Mouse mouse = new X11Mouse();
+        readonly X11Keyboard keyboard = new X11Keyboard();
+
+        internal X11Input()
+        {
+            Debug.WriteLine("Using X11 core input driver.");
+            Debug.WriteLine("[Warning] Mouse functionality will be significantly reduced.");
+            Debug.WriteLine("[Warning] Copy OpenTK.dll.config to use the XI2 input driver instead.");
+        }
+
+        #region IDisposable Members
+
+        public void Dispose()
+        {
+            joystick.Dispose();
+        }
+
+        #endregion
+
+    }
+}
+
diff --git a/CrowX/X11/X11KeyMap.cs b/CrowX/X11/X11KeyMap.cs
new file mode 100644 (file)
index 0000000..15a05ec
--- /dev/null
@@ -0,0 +1,726 @@
+#region License
+//
+// X11KeyMap.cs
+//
+// Author:
+//       Stefanos Apostolopoulos <stapostol@gmail.com>
+//
+// Copyright (c) 2006-2014 
+//
+// 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 Crow;
+
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Diagnostics;
+using OpenTK.Input;
+
+namespace X11Sharp
+{
+    class X11KeyMap
+    {
+        // Keycode lookup table for current layout
+        readonly Key[] keycodes = new Key[256];
+        readonly bool xkb_supported;
+
+        internal X11KeyMap(IntPtr display)
+        {
+            xkb_supported = Xkb.IsSupported(display);
+            if (xkb_supported)
+            {
+                RefreshKeycodes(display);
+            }
+        }
+
+        // Refreshes the keycodes lookup table based
+        // on the current keyboard layout.
+        internal void RefreshKeycodes(IntPtr display)
+        {
+            // Approach inspired by GLFW: http://www.glfw.org/
+            // Huge props to the GLFW team! 
+            if (xkb_supported)
+            {
+                unsafe
+                {
+                    // Xkb.GetKeyboard appears to be broken (multiple bug reports across distros)
+                    // so use Xkb.AllocKeyboard with Xkb.GetNames instead.
+                    XkbDesc* keyboard = Xkb.AllocKeyboard(display);
+                    if (keyboard != null)
+                    {
+                        Xkb.GetNames(display, XkbNamesMask.All, keyboard);
+
+                        for (int i = 0; i < keycodes.Length; i++)
+                        {
+                            keycodes[i] = Key.Unknown;
+                        }
+
+                        // Map all alphanumeric keys of this layout
+                        // Symbols are handled in GetKey() instead.
+                        for (int i = keyboard->min_key_code; i <= keyboard->max_key_code; ++i)
+                        {
+                            string name = new string((sbyte*)keyboard->names->keys[i].name, 0, Xkb.KeyNameLength);
+
+                            Key key = Key.Unknown;
+                            switch (name)
+                            {
+                                case "TLDE":
+                                    key = Key.Tilde;
+                                    break;
+                                case "AE01":
+                                    key = Key.Number1;
+                                    break;
+                                case "AE02":
+                                    key = Key.Number2;
+                                    break;
+                                case "AE03":
+                                    key = Key.Number3;
+                                    break;
+                                case "AE04":
+                                    key = Key.Number4;
+                                    break;
+                                case "AE05":
+                                    key = Key.Number5;
+                                    break;
+                                case "AE06":
+                                    key = Key.Number6;
+                                    break;
+                                case "AE07":
+                                    key = Key.Number7;
+                                    break;
+                                case "AE08":
+                                    key = Key.Number8;
+                                    break;
+                                case "AE09":
+                                    key = Key.Number9;
+                                    break;
+                                case "AE10":
+                                    key = Key.Number0;
+                                    break;
+                                case "AE11":
+                                    key = Key.Minus;
+                                    break;
+                                case "AE12":
+                                    key = Key.Plus;
+                                    break;
+                                case "AD01":
+                                    key = Key.Q;
+                                    break;
+                                case "AD02":
+                                    key = Key.W;
+                                    break;
+                                case "AD03":
+                                    key = Key.E;
+                                    break;
+                                case "AD04":
+                                    key = Key.R;
+                                    break;
+                                case "AD05":
+                                    key = Key.T;
+                                    break;
+                                case "AD06":
+                                    key = Key.Y;
+                                    break;
+                                case "AD07":
+                                    key = Key.U;
+                                    break;
+                                case "AD08":
+                                    key = Key.I;
+                                    break;
+                                case "AD09":
+                                    key = Key.O;
+                                    break;
+                                case "AD10":
+                                    key = Key.P;
+                                    break;
+                                case "AD11":
+                                    key = Key.BracketLeft;
+                                    break;
+                                case "AD12":
+                                    key = Key.BracketRight;
+                                    break;
+                                case "AC01":
+                                    key = Key.A;
+                                    break;
+                                case "AC02":
+                                    key = Key.S;
+                                    break;
+                                case "AC03":
+                                    key = Key.D;
+                                    break;
+                                case "AC04":
+                                    key = Key.F;
+                                    break;
+                                case "AC05":
+                                    key = Key.G;
+                                    break;
+                                case "AC06":
+                                    key = Key.H;
+                                    break;
+                                case "AC07":
+                                    key = Key.J;
+                                    break;
+                                case "AC08":
+                                    key = Key.K;
+                                    break;
+                                case "AC09":
+                                    key = Key.L;
+                                    break;
+                                case "AC10":
+                                    key = Key.Semicolon;
+                                    break;
+                                case "AC11":
+                                    key = Key.Quote;
+                                    break;
+                                case "AB01":
+                                    key = Key.Z;
+                                    break;
+                                case "AB02":
+                                    key = Key.X;
+                                    break;
+                                case "AB03":
+                                    key = Key.C;
+                                    break;
+                                case "AB04":
+                                    key = Key.V;
+                                    break;
+                                case "AB05":
+                                    key = Key.B;
+                                    break;
+                                case "AB06":
+                                    key = Key.N;
+                                    break;
+                                case "AB07":
+                                    key = Key.M;
+                                    break;
+                                case "AB08":
+                                    key = Key.Comma;
+                                    break;
+                                case "AB09":
+                                    key = Key.Period;
+                                    break;
+                                case "AB10":
+                                    key = Key.Slash;
+                                    break;
+                                case "BKSL":
+                                    key = Key.BackSlash;
+                                    break;
+                                case "LSGT":
+                                    key = Key.Unknown;
+                                    break;
+                                default:
+                                    key = Key.Unknown;
+                                    break;
+                            }
+
+                            keycodes[i] = key;
+                        }
+
+                        Xkb.FreeKeyboard(keyboard, 0, true);
+                    }
+                }
+            }
+
+            // Translate unknown keys (and symbols) using
+            // regular layout-dependent GetKey()
+            for (int i = 0; i < 256; i++)
+            {
+                if (keycodes[i] == Key.Unknown)
+                {
+                    // TranslateKeyCode expects a XKeyEvent structure
+                    // Make one up
+                    XKeyEvent e = new XKeyEvent();
+                    e.display = display;
+                    e.keycode = i;
+                    Key key = Key.Unknown;
+                    if (TranslateKeyEvent(ref e, out key))
+                    {
+                        keycodes[i] = key;
+                    }
+                }
+            }
+        }
+
+        static Key TranslateXKey(XKey key)
+        {
+            switch (key)
+            {
+                case XKey.Escape:
+                    return Key.Escape;
+                case XKey.Return:
+                    return Key.Enter;
+                case XKey.space:
+                    return Key.Space;
+                case XKey.BackSpace:
+                    return Key.BackSpace;
+
+                case XKey.Shift_L:
+                    return Key.ShiftLeft;
+                case XKey.Shift_R:
+                    return Key.ShiftRight;
+                case XKey.Alt_L:
+                    return Key.AltLeft;
+                case XKey.Alt_R:
+                    return Key.AltRight;
+                case XKey.Control_L:
+                    return Key.ControlLeft;
+                case XKey.Control_R:
+                    return Key.ControlRight;
+                case XKey.Super_L:
+                    return Key.WinLeft;
+                case XKey.Super_R:
+                    return Key.WinRight;
+                case XKey.Meta_L:
+                    return Key.WinLeft;
+                case XKey.Meta_R:
+                    return Key.WinRight;
+                case XKey.ISO_Level3_Shift:
+                    return Key.AltRight; // Normally AltGr
+
+                case XKey.Menu:
+                    return Key.Menu;
+                case XKey.Tab:
+                    return Key.Tab;
+                case XKey.minus:
+                    return Key.Minus;
+                case XKey.plus:
+                    return Key.Plus;
+                case XKey.equal:
+                    return Key.Plus;
+
+                case XKey.Caps_Lock:
+                    return Key.CapsLock;
+                case XKey.Num_Lock:
+                    return Key.NumLock;
+
+                case XKey.F1:
+                    return Key.F1;
+                case XKey.F2:
+                    return Key.F2;
+                case XKey.F3:
+                    return Key.F3;
+                case XKey.F4:
+                    return Key.F4;
+                case XKey.F5:
+                    return Key.F5;
+                case XKey.F6:
+                    return Key.F6;
+                case XKey.F7:
+                    return Key.F7;
+                case XKey.F8:
+                    return Key.F8;
+                case XKey.F9:
+                    return Key.F9;
+                case XKey.F10:
+                    return Key.F10;
+                case XKey.F11:
+                    return Key.F11;
+                case XKey.F12:
+                    return Key.F12;
+                case XKey.F13:
+                    return Key.F13;
+                case XKey.F14:
+                    return Key.F14;
+                case XKey.F15:
+                    return Key.F15;
+                case XKey.F16:
+                    return Key.F16;
+                case XKey.F17:
+                    return Key.F17;
+                case XKey.F18:
+                    return Key.F18;
+                case XKey.F19:
+                    return Key.F19;
+                case XKey.F20:
+                    return Key.F20;
+                case XKey.F21:
+                    return Key.F21;
+                case XKey.F22:
+                    return Key.F22;
+                case XKey.F23:
+                    return Key.F23;
+                case XKey.F24:
+                    return Key.F24;
+                case XKey.F25:
+                    return Key.F25;
+                case XKey.F26:
+                    return Key.F26;
+                case XKey.F27:
+                    return Key.F27;
+                case XKey.F28:
+                    return Key.F28;
+                case XKey.F29:
+                    return Key.F29;
+                case XKey.F30:
+                    return Key.F30;
+                case XKey.F31:
+                    return Key.F31;
+                case XKey.F32:
+                    return Key.F32;
+                case XKey.F33:
+                    return Key.F33;
+                case XKey.F34:
+                    return Key.F34;
+                case XKey.F35:
+                    return Key.F35;
+
+                case XKey.a:
+                case XKey.A:
+                    return Key.A;
+                case XKey.b:
+                case XKey.B:
+                    return Key.B;
+                case XKey.c:
+                case XKey.C:
+                    return Key.C;
+                case XKey.d:
+                case XKey.D:
+                    return Key.D;
+                case XKey.e:
+                case XKey.E:
+                    return Key.E;
+                case XKey.f:
+                case XKey.F:
+                    return Key.F;
+                case XKey.g:
+                case XKey.G:
+                    return Key.G;
+                case XKey.h:
+                case XKey.H:
+                    return Key.H;
+                case XKey.i:
+                case XKey.I:
+                    return Key.I;
+                case XKey.j:
+                case XKey.J:
+                    return Key.J;
+                case XKey.k:
+                case XKey.K:
+                    return Key.K;
+                case XKey.l:
+                case XKey.L:
+                    return Key.L;
+                case XKey.m:
+                case XKey.M:
+                    return Key.M;
+                case XKey.n:
+                case XKey.N:
+                    return Key.N;
+                case XKey.o:
+                case XKey.O:
+                    return Key.O;
+                case XKey.p:
+                case XKey.P:
+                    return Key.P;
+                case XKey.q:
+                case XKey.Q:
+                    return Key.Q;
+                case XKey.r:
+                case XKey.R:
+                    return Key.R;
+                case XKey.s:
+                case XKey.S:
+                    return Key.S;
+                case XKey.t:
+                case XKey.T:
+                    return Key.T;
+                case XKey.u:
+                case XKey.U:
+                    return Key.U;
+                case XKey.v:
+                case XKey.V:
+                    return Key.V;
+                case XKey.w:
+                case XKey.W:
+                    return Key.W;
+                case XKey.x:
+                case XKey.X:
+                    return Key.X;
+                case XKey.y:
+                case XKey.Y:
+                    return Key.Y;
+                case XKey.z:
+                case XKey.Z:
+                    return Key.Z;
+
+                case XKey.Number0:
+                    return Key.Number0;
+                case XKey.Number1:
+                    return Key.Number1;
+                case XKey.Number2:
+                    return Key.Number2;
+                case XKey.Number3:
+                    return Key.Number3;
+                case XKey.Number4:
+                    return Key.Number4;
+                case XKey.Number5:
+                    return Key.Number5;
+                case XKey.Number6:
+                    return Key.Number6;
+                case XKey.Number7:
+                    return Key.Number7;
+                case XKey.Number8:
+                    return Key.Number8;
+                case XKey.Number9:
+                    return Key.Number9;
+
+                case XKey.KP_0:
+                    return Key.Keypad0;
+                case XKey.KP_1:
+                    return Key.Keypad1;
+                case XKey.KP_2:
+                    return Key.Keypad2;
+                case XKey.KP_3:
+                    return Key.Keypad3;
+                case XKey.KP_4:
+                    return Key.Keypad4;
+                case XKey.KP_5:
+                    return Key.Keypad5;
+                case XKey.KP_6:
+                    return Key.Keypad6;
+                case XKey.KP_7:
+                    return Key.Keypad7;
+                case XKey.KP_8:
+                    return Key.Keypad8;
+                case XKey.KP_9:
+                    return Key.Keypad9;
+
+                case XKey.Pause:
+                    return Key.Pause;
+                case XKey.Break:
+                    return Key.Pause;
+                case XKey.Scroll_Lock:
+                    return Key.Pause;
+                case XKey.Insert:
+                    return Key.Insert;
+                case XKey.Print:
+                    return Key.PrintScreen;
+                case XKey.Sys_Req:
+                    return Key.PrintScreen;
+
+                case XKey.backslash:
+                    return Key.BackSlash;
+                case XKey.bar:
+                    return Key.BackSlash;
+                case XKey.braceleft:
+                    return Key.BracketLeft;
+                case XKey.bracketleft:
+                    return Key.BracketLeft;
+                case XKey.braceright:
+                    return Key.BracketRight;
+                case XKey.bracketright:
+                    return Key.BracketRight;
+                case XKey.colon:
+                    return Key.Semicolon;
+                case XKey.semicolon:
+                    return Key.Semicolon;
+                case XKey.quoteright:
+                    return Key.Quote;
+                case XKey.quotedbl:
+                    return Key.Quote;
+                case XKey.quoteleft:
+                    return Key.Tilde;
+                case XKey.asciitilde:
+                    return Key.Tilde;
+
+                case XKey.comma:
+                    return Key.Comma;
+                case XKey.less:
+                    return Key.Comma;
+                case XKey.period:
+                    return Key.Period;
+                case XKey.greater:
+                    return Key.Period;
+                case XKey.slash:
+                    return Key.Slash;
+                case XKey.question:
+                    return Key.Slash;
+
+                case XKey.Left:
+                    return Key.Left;
+                case XKey.Down:
+                    return Key.Down;
+                case XKey.Right:
+                    return Key.Right;
+                case XKey.Up:
+                    return Key.Up;
+
+                case XKey.Delete:
+                    return Key.Delete;
+                case XKey.Home:
+                    return Key.Home;
+                case XKey.End:
+                    return Key.End;
+            //case XKey.Prior: return Key.PageUp;   // XKey.Prior == XKey.Page_Up
+                case XKey.Page_Up:
+                    return Key.PageUp;
+                case XKey.Page_Down:
+                    return Key.PageDown;
+            //case XKey.Next: return Key.PageDown;  // XKey.Next == XKey.Page_Down
+
+                case XKey.KP_Add:
+                    return Key.KeypadAdd;
+                case XKey.KP_Subtract:
+                    return Key.KeypadSubtract;
+                case XKey.KP_Multiply:
+                    return Key.KeypadMultiply;
+                case XKey.KP_Divide:
+                    return Key.KeypadDivide;
+                case XKey.KP_Decimal:
+                    return Key.KeypadDecimal;
+                case XKey.KP_Insert:
+                    return Key.Keypad0;
+                case XKey.KP_End:
+                    return Key.Keypad1;
+                case XKey.KP_Down:
+                    return Key.Keypad2;
+                case XKey.KP_Page_Down:
+                    return Key.Keypad3;
+                case XKey.KP_Left:
+                    return Key.Keypad4;
+                case XKey.KP_Right:
+                    return Key.Keypad6;
+                case XKey.KP_Home:
+                    return Key.Keypad7;
+                case XKey.KP_Up:
+                    return Key.Keypad8;
+                case XKey.KP_Page_Up:
+                    return Key.Keypad9;
+                case XKey.KP_Delete:
+                    return Key.KeypadDecimal;
+                case XKey.KP_Enter:
+                    return Key.KeypadEnter;
+
+                default:
+                    return Key.Unknown;
+            }
+        }
+
+        bool TranslateKeyEvent(ref XKeyEvent e, out Key key)
+        {
+            if (xkb_supported)
+            {
+                return TranslateKeyXkb(e.display, e.keycode, out key);
+            }
+            else
+            {
+                return TranslateKeyX11(ref e, out key);
+            }
+        }
+
+        bool TranslateKeyX11(ref XKeyEvent e, out Key key)
+        {
+            XKey keysym = (XKey)API.LookupKeysym(ref e, 0);
+            XKey keysym2 = (XKey)API.LookupKeysym(ref e, 1);
+            key = X11KeyMap.TranslateXKey(keysym);
+            if (key == Key.Unknown)
+            {
+                key = X11KeyMap.TranslateXKey(keysym2);
+            }
+            if (key == Key.Unknown)
+            {
+                Debug.Print("KeyCode {0} (Keysym: {1}, {2}) not mapped.", e.keycode, (XKey)keysym, (XKey)keysym2);
+            }
+
+            return key != Key.Unknown;
+        }
+
+        bool TranslateKeyXkb(IntPtr display, int keycode, out Key key)
+        {
+            if (keycode < 8 || keycode > 255)
+            {
+                key = Key.Unknown;
+                return false;
+            }
+
+            // Translate the numeric keypad using the secondary group
+            // (equivalent to NumLock = on)
+            XKey keysym = Xkb.KeycodeToKeysym(display, keycode, 0, 1);
+            switch (keysym)
+            {
+                case XKey.KP_0: key = Key.Keypad0; return true;
+                case XKey.KP_1: key = Key.Keypad1; return true;
+                case XKey.KP_2: key = Key.Keypad2; return true;
+                case XKey.KP_3: key = Key.Keypad3; return true;
+                case XKey.KP_4: key = Key.Keypad4; return true;
+                case XKey.KP_5: key = Key.Keypad5; return true;
+                case XKey.KP_6: key = Key.Keypad6; return true;
+                case XKey.KP_7: key = Key.Keypad7; return true;
+                case XKey.KP_8: key = Key.Keypad8; return true;
+                case XKey.KP_9: key = Key.Keypad9; return true;
+                case XKey.KP_Separator:
+                case XKey.KP_Decimal: key = Key.KeypadDecimal; return true;
+                case XKey.KP_Equal: key = Key.Unknown; return false; // Todo: fixme
+                case XKey.KP_Enter: key = Key.KeypadEnter; return true;
+            }
+
+            // Translate non-alphanumeric keys using the primary group
+            keysym = Xkb.KeycodeToKeysym(display, keycode, 0, 0);
+            key = TranslateXKey(keysym);
+            return key != Key.Unknown;
+        }
+
+        internal bool TranslateKey(int keycode, out Key key)
+        {
+            if (keycode < 0 || keycode > 255)
+            {
+                key = Key.Unknown;
+            }
+            else
+            {
+                key = keycodes[keycode];
+            }
+            return key != Key.Unknown;
+        }
+
+        internal bool TranslateKey(ref XKeyEvent e, out Key key)
+        {
+            return TranslateKey(e.keycode, out key);
+        }
+
+        internal static MouseButton TranslateButton(int button, out float wheelx, out float wheely)
+        {
+            wheelx = 0;
+            wheely = 0;
+
+            switch (button)
+            {
+                case 1: return MouseButton.Left;
+                case 2: return MouseButton.Middle;
+                case 3: return MouseButton.Right;
+                case 4: wheely = +1; return MouseButton.LastButton;
+                case 5: wheely = -1; return MouseButton.LastButton;
+                case 6: wheelx = +1; return MouseButton.LastButton;
+                case 7: wheelx = -1; return MouseButton.LastButton;
+                case 8: return MouseButton.Button1;
+                case 9: return MouseButton.Button2;
+                case 10: return MouseButton.Button3;
+                case 11: return MouseButton.Button4;
+                case 12: return MouseButton.Button5;
+                case 13: return MouseButton.Button6;
+                case 14: return MouseButton.Button7;
+                default: return MouseButton.LastButton;
+            }
+        }
+    }
+}
diff --git a/CrowX/X11/X11Keyboard.cs b/CrowX/X11/X11Keyboard.cs
new file mode 100644 (file)
index 0000000..bdd5444
--- /dev/null
@@ -0,0 +1,119 @@
+#region License
+//
+// The Open Toolkit Library License
+//
+// Copyright (c) 2006 - 2010 the Open Toolkit library.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+// the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using OpenTK.Input;
+
+namespace X11Sharp
+{
+    // Standard keyboard driver that relies on xlib input events.
+    // Only one keyboard supported.
+    sealed class X11Keyboard : IKeyboardDriver2
+    {
+        readonly static string name = "Core X11 keyboard";
+        readonly byte[] keys = new byte[32];
+        readonly int KeysymsPerKeycode;
+        readonly X11KeyMap KeyMap;
+        KeyboardState state = new KeyboardState();
+
+        public X11Keyboard()
+        {
+            Debug.WriteLine("Using X11Keyboard.");
+            state.IsConnected = true;
+
+            IntPtr display = API.DefaultDisplay;
+            using (new XLock(display))
+            {
+                // Find the number of keysyms per keycode.
+                int first = 0, last = 0;
+                API.DisplayKeycodes(display, ref first, ref last);
+                IntPtr keysym_ptr =
+                    API.GetKeyboardMapping(display,
+                        (byte)first,
+                        last - first + 1,
+                        ref KeysymsPerKeycode);
+                Functions.XFree(keysym_ptr);
+
+                if (Xkb.IsSupported(display))
+                {
+                    // Request that auto-repeat is only set on devices that support it physically.
+                    // This typically means that it's turned off for keyboards what we want).
+                    // We prefer this method over XAutoRepeatOff/On, because the latter needs to
+                    // be reset before the program exits.
+                    bool supported;
+                    Xkb.SetDetectableAutoRepeat(display, true, out supported);
+                    KeyMap = new X11KeyMap(display);
+                }
+            }
+        }
+
+        public KeyboardState GetState()
+        {
+            ProcessEvents();
+            return state;
+        }
+
+        public KeyboardState GetState(int index)
+        {
+            // X11Keyboard supports a single keyboard only
+            ProcessEvents();
+            if (index == 0)
+                return state;
+            else
+                return new KeyboardState();
+        }
+
+        public string GetDeviceName(int index)
+        {
+            if (index == 0)
+                return name;
+            else
+                return String.Empty;
+        }
+
+        void ProcessEvents()
+        {
+            IntPtr display = API.DefaultDisplay;
+            using (new XLock(display))
+            {
+                Functions.XQueryKeymap(display, keys);
+                for (int keycode = 0; keycode < 256; keycode++)
+                {
+                    bool pressed = (keys[keycode >> 3] >> (keycode & 0x07) & 0x01) != 0;
+                    Key key;
+                    if (KeyMap.TranslateKey(keycode, out key))
+                    {
+                        state[key] = pressed;
+                    }
+                }
+            }
+        }
+    }
+}
+
diff --git a/CrowX/X11/X11Mouse.cs b/CrowX/X11/X11Mouse.cs
new file mode 100644 (file)
index 0000000..3743d87
--- /dev/null
@@ -0,0 +1,155 @@
+ #region License
+ //
+ // The Open Toolkit Library License
+ //
+ // Copyright (c) 2006 - 2010 the Open Toolkit library.
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
+ // of this software and associated documentation files (the "Software"), to deal
+ // in the Software without restriction, including without limitation the rights to 
+ // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ // the Software, and to permit persons to whom the Software is furnished to do
+ // so, subject to the following conditions:
+ //
+ // The above copyright notice and this permission notice shall be included in all
+ // copies or substantial portions of the Software.
+ //
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ // OTHER DEALINGS IN THE SOFTWARE.
+ //
+ #endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using OpenTK.Input;
+
+namespace X11Sharp
+{
+    // Note: we cannot create a background window to retrieve events,
+    // because X11 doesn't deliver core pointer events to background
+    // windows (unless we grab, which will break *everything*).
+    // The only solution is to poll.
+    // Note 2: this driver only supports absolute positions. Relative motion
+    // is faked through SetPosition. This is called automatically when
+    // NativeWindow.CursorVisible = false, otherwise it must be called
+    // by the user.
+    // Note 3: this driver cannot drive the mouse wheel reliably.
+    // See comments in ProcessEvents() for more information.
+    // (If someone knows of a solution, please tell!)
+    sealed class X11Mouse : IMouseDriver2
+    {
+        readonly IntPtr display;
+        readonly IntPtr root_window;
+        MouseState mouse = new MouseState();
+        MouseState cursor = new MouseState();
+
+        // When the mouse warps, "detach" the current location
+        // from the pointer.
+        bool mouse_detached;
+        int mouse_detached_x, mouse_detached_y;
+
+        public X11Mouse()
+        {
+            Debug.WriteLine("Using X11Mouse.");
+            mouse.IsConnected = true;
+            cursor.IsConnected = true;
+            display = API.DefaultDisplay;
+            root_window = Functions.XRootWindow(display, Functions.XDefaultScreen(display));
+        }
+
+        public MouseState GetState()
+        {
+            ProcessEvents();
+            return mouse;
+        }
+
+        public MouseState GetState(int index)
+        {
+            ProcessEvents();
+            // X11Mouse supports only one device
+            if (index == 0)
+                return mouse;
+            else
+                return new MouseState();
+        }
+
+        public MouseState GetCursorState()
+        {
+            ProcessEvents();
+            return cursor;
+        }
+
+        public void SetPosition(double x, double y)
+        {
+            // Update the current location, otherwise the pointer
+            // may become locked (for instance, if we call
+            // SetPosition too often, like X11GLNative does).
+            ProcessEvents();
+
+            using (new XLock(display))
+            {
+                // Mark the expected warp-event so it can be ignored.
+                mouse_detached = true;
+                mouse_detached_x = (int)x;
+                mouse_detached_y = (int)y;
+
+                Functions.XWarpPointer(display,
+                    IntPtr.Zero, root_window, 0, 0, 0, 0, (int)x, (int)y);
+            }
+        }
+
+        void ProcessEvents()
+        {
+            IntPtr root, child;
+            int root_x, root_y, win_x, win_y;
+            int buttons;
+
+            using (new XLock(display))
+            {
+                IntPtr window = root_window;
+                Functions.XQueryPointer(display, window, out root, out child,
+                    out root_x, out root_y, out win_x, out win_y, out buttons);
+
+                cursor.X = root_x;
+                cursor.Y = root_y;
+
+                if (!mouse_detached)
+                {
+                    mouse.X = root_x;
+                    mouse.Y = root_y;
+                }
+                else
+                {
+                    mouse.X += (int)root_x - mouse_detached_x;
+                    mouse.Y += (int)root_y - mouse_detached_y;
+                    mouse_detached_x = root_x;
+                    mouse_detached_y = root_y;
+                }
+                cursor[MouseButton.Left] = mouse[MouseButton.Left] = (buttons & (int)MouseMask.Button1Mask) != 0;
+                cursor[MouseButton.Middle] = mouse[MouseButton.Middle] = (buttons & (int)MouseMask.Button2Mask) != 0;
+                cursor[MouseButton.Right] = mouse[MouseButton.Right] = (buttons & (int)MouseMask.Button3Mask) != 0;
+                // Note: this will never work right, wheel events have a duration of 0
+                // (yes, zero). They are impposible to catch via polling.
+                // After spending a week on this, I simply don't care anymore.
+                // If someone can fix it, please do.
+                // Note 2: I have tried passively grabbing those buttons - no go (BadAccess).
+                // Maybe I am doing something wrong with the grab.
+                //if ((buttons & (int)MouseMask.Button4Mask) != 0)
+                //   mouse.WheelPrecise++;
+                //if ((buttons & (int)MouseMask.Button5Mask) != 0)
+                //    mouse.WheelPrecise--;
+                cursor[MouseButton.Button1] = mouse[MouseButton.Button1] = (buttons & (int)MouseMask.Button6Mask) != 0;
+                cursor[MouseButton.Button2] = mouse[MouseButton.Button2] = (buttons & (int)MouseMask.Button7Mask) != 0;
+                cursor[MouseButton.Button3] = mouse[MouseButton.Button3] = (buttons & (int)MouseMask.Button8Mask) != 0;
+            }
+        }
+    }
+}
+
diff --git a/CrowX/X11/X11WindowInfo.cs b/CrowX/X11/X11WindowInfo.cs
new file mode 100644 (file)
index 0000000..2873ed2
--- /dev/null
@@ -0,0 +1,165 @@
+#region License
+//
+// The Open Toolkit Library License
+//
+// Copyright (c) 2006 - 2009 the Open Toolkit library.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights to 
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+// the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace X11Sharp
+{
+    /// \internal
+    /// <summary>Describes an X11 window.</summary>
+    sealed class X11WindowInfo : IWindowInfo
+    {
+        IntPtr handle, rootWindow, display;
+        X11WindowInfo parent;
+        int screen;
+        XVisualInfo visualInfo;
+        EventMask eventMask;
+
+        #region --- Constructors ---
+
+        #region X11WindowInfo()
+
+        /// <summary>Constructs a new X11WindowInfo class.</summary>
+        public X11WindowInfo() { }
+
+        #endregion
+
+        #region X11WindowInfo(IntPtr handle, X11WindowInfo parent)
+
+        /// <summary>
+        /// Constructs a new X11WindowInfo class from the specified window handle and parent.
+        /// </summary>
+        /// <param name="handle">The handle of the window.</param>
+        /// <param name="parent">The parent of the window.</param>
+        public X11WindowInfo(IntPtr handle, X11WindowInfo parent)
+        {
+            this.handle = handle;
+            this.parent = parent;
+            if (parent != null)
+            {
+                this.rootWindow = parent.rootWindow;
+                this.display = parent.display;
+                this.screen = parent.screen;
+                this.visualInfo = parent.visualInfo;
+            }
+        }
+
+        #endregion
+
+        #endregion
+
+        #region --- Public Methods ---
+
+        /// <summary>Gets or sets the handle of the window.</summary>
+        public IntPtr Handle { get { return handle; } set { handle = value; } }
+        /// <summary>Gets or sets the parent of the window.</summary>
+        public X11WindowInfo Parent { get { return parent; } set { parent = value; } }
+        /// <summary>Gets or sets the X11 root window.</summary>
+        public IntPtr RootWindow { get { return rootWindow; } set { rootWindow = value; } }
+        /// <summary>Gets or sets the connection to the X11 display.</summary>
+        public IntPtr Display { get { return display; } set { display = value; } }
+        /// <summary>Gets or sets the X11 screen.</summary>
+        public int Screen { get { return screen; } set { screen = value; } }
+        /// <summary>Gets or sets the X11 VisualInfo.</summary>
+        public XVisualInfo VisualInfo
+        {
+            get
+            {
+                if (Visual != IntPtr.Zero)
+                {
+                    return (XVisualInfo)Marshal.PtrToStructure(Visual, typeof(XVisualInfo));
+                }
+                return default(XVisualInfo);
+            }
+        }
+        /// <summary>Gets or sets the X11 EventMask.</summary>
+        public EventMask EventMask { get { return eventMask; } set { eventMask = value; } }
+
+        // For compatibility with whoever thought it would be
+        // a good idea to access internal APIs through reflection
+        // (e.g. MonoGame)
+        public IntPtr WindowHandle { get { return Handle; } set { Handle = value; } }
+
+        public IntPtr Visual { get; set; }
+        public IntPtr FBConfig { get; set; }
+        public Graphics.GraphicsMode GraphicsMode { get; set; }
+
+        #endregion
+
+        #region --- IDisposable Members ---
+
+        /// <summary>
+        /// Disposes of this X11WindowInfo instance.
+        /// </summary>
+        public void Dispose()
+        {
+        }
+
+        #endregion
+
+        #region --- Overrides ---
+
+        #region public override string ToString()
+
+        /// <summary>Returns a System.String that represents the current window.</summary>
+        /// <returns>A System.String that represents the current window.</returns>
+        public override string ToString()
+        {
+            return String.Format("X11.WindowInfo: Display {0}, Screen {1}, Handle {2}, Parent: ({3})",
+                this.Display, this.Screen, this.Handle, this.Parent != null ? this.Parent.ToString() : "null");
+        }
+
+        #endregion
+
+        /// <summary>Checks if <c>this</c> and <c>obj</c> reference the same win32 window.</summary>
+        /// <param name="obj">The object to check against.</param>
+        /// <returns>True if <c>this</c> and <c>obj</c> reference the same win32 window; false otherwise.</returns>
+        public override bool Equals(object obj)
+        {
+            if (obj == null) return false;
+            if (this.GetType() != obj.GetType()) return false;
+            X11WindowInfo info = (X11WindowInfo)obj;
+
+            if (info == null) return false;
+            // TODO: Assumes windows will have unique handles per X11 display.
+            return object.Equals(display, info.display) &&
+                   handle.Equals(info.handle);
+        }
+
+        /// <summary>Returns the hash code for this instance.</summary>
+        /// <returns>A hash code for the current <c>X11WindowInfo</c>.</returns>
+        public override int GetHashCode()
+        {
+            return handle.GetHashCode() ^ display.GetHashCode();
+        }
+
+        #endregion
+    }
+}
diff --git a/CrowX/X11/XI2Input.cs b/CrowX/X11/XI2Input.cs
new file mode 100644 (file)
index 0000000..20d0588
--- /dev/null
@@ -0,0 +1,95 @@
+#region License
+//
+// XI2Input.cs
+//
+// Author:
+//       thefiddler <stapostol@gmail.com>
+//
+// Copyright (c) 2006-2014 
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+#endregion
+
+using System;
+using System.Diagnostics;
+using OpenTK.Input;
+
+namespace X11Sharp
+{
+    class XI2Input : IInputDriver2
+    {
+        readonly XI2MouseKeyboard mouse_keyboard = new XI2MouseKeyboard();
+        readonly Linux.LinuxJoystick joystick = new Linux.LinuxJoystick();
+        readonly IGamePadDriver gamepad = new MappedGamePadDriver();
+
+        internal XI2Input()
+        {
+            Debug.WriteLine("Using XI2 input driver.");
+        }
+
+        #region IInputDriver2 Members
+
+        public IMouseDriver2 MouseDriver
+        {
+            get
+            {
+                return mouse_keyboard;
+            }
+        }
+
+        public IKeyboardDriver2 KeyboardDriver
+        {
+            get
+            {
+                return mouse_keyboard;
+            }
+        }
+
+        public IGamePadDriver GamePadDriver
+        {
+            get
+            {
+                return gamepad;
+            }
+        }
+
+        public IJoystickDriver2 JoystickDriver
+        {
+            get
+            {
+                return joystick;
+            }
+        }
+
+        #endregion
+
+        #region IDisposable Members
+
+        public void Dispose()
+        {
+            mouse_keyboard.Dispose();
+            joystick.Dispose();
+        }
+
+        #endregion
+
+    }
+}
+
diff --git a/CrowX/X11/XI2MouseKeyboard.cs b/CrowX/X11/XI2MouseKeyboard.cs
new file mode 100644 (file)
index 0000000..d099c86
--- /dev/null
@@ -0,0 +1,675 @@
+ #region License
+ //
+ // The Open Toolkit Library License
+ //
+ // Copyright (c) 2006 - 2010 the Open Toolkit library.
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
+ // of this software and associated documentation files (the "Software"), to deal
+ // in the Software without restriction, including without limitation the rights to 
+ // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ // the Software, and to permit persons to whom the Software is furnished to do
+ // so, subject to the following conditions:
+ //
+ // The above copyright notice and this permission notice shall be included in all
+ // copies or substantial portions of the Software.
+ //
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ // OTHER DEALINGS IN THE SOFTWARE.
+ //
+using Crow;
+
+
+ #endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Threading;
+using OpenTK.Input;
+
+namespace X11Sharp
+{
+    sealed class XI2MouseKeyboard : IDisposable
+    {
+        static readonly IntPtr ExitAtom;
+        readonly object Sync = new object();
+        readonly Thread ProcessingThread;
+        readonly X11KeyMap KeyMap;
+        bool disposed;
+
+        class XIMouse
+        {
+            public MouseState State;
+            public XIDeviceInfo DeviceInfo;
+            public XIScrollClassInfo ScrollX = new XIScrollClassInfo { number = -1 };
+            public XIScrollClassInfo ScrollY = new XIScrollClassInfo { number = -1 };
+            public XIValuatorClassInfo MotionX = new XIValuatorClassInfo { number = -1 };
+            public XIValuatorClassInfo MotionY = new XIValuatorClassInfo { number = -1 };
+            public string Name;
+        }
+
+        class XIKeyboard
+        {
+            public KeyboardState State;
+            public XIDeviceInfo DeviceInfo;
+            public string Name;
+        }
+
+        long cursor_x, cursor_y; // For GetCursorState()
+        List<XIMouse> devices = new List<XIMouse>(); // list of connected mice
+        Dictionary<int, int> rawids = new Dictionary<int, int>(); // maps hardware device ids to XIMouse ids
+
+        List<XIKeyboard> keyboards = new List<XIKeyboard>(); // list of connected keybords
+        Dictionary<int, int> keyboard_ids = new Dictionary<int, int>(); // maps hardware device ids to XIKeyboard ids
+
+        internal readonly X11WindowInfo window;
+        internal static int XIOpCode { get; private set; }
+        internal static int XIVersion { get; private set; }
+
+        static readonly Functions.EventPredicate PredicateImpl = IsEventValid;
+        readonly IntPtr Predicate = Marshal.GetFunctionPointerForDelegate(PredicateImpl);
+
+        static XI2MouseKeyboard()
+        {
+            using (new XLock(API.DefaultDisplay))
+            {
+                ExitAtom = Functions.XInternAtom(API.DefaultDisplay, "Exit Input Thread Message", false);
+            }
+        }
+
+        public XI2MouseKeyboard()
+        {
+            window = new X11WindowInfo();
+
+            window.Display = Functions.XOpenDisplay(IntPtr.Zero);
+            using (new XLock(window.Display))
+            {
+                XSetWindowAttributes attr = new XSetWindowAttributes();
+
+                window.Screen = Functions.XDefaultScreen(window.Display);
+                window.RootWindow = Functions.XRootWindow(window.Display, window.Screen);
+                window.Handle = Functions.XCreateWindow(window.Display, window.RootWindow,
+                    0, 0, 1, 1, 0, 0,
+                    CreateWindowArgs.InputOnly, IntPtr.Zero,
+                    SetWindowValuemask.Nothing, attr);
+
+                KeyMap = new X11KeyMap(window.Display);
+            }
+
+            if (!IsSupported(window.Display))
+                throw new NotSupportedException("XInput2 not supported.");
+
+            // Enable XI2 mouse/keyboard events
+            // Note: the input event loop blocks waiting for these events
+            // *or* a custom ClientMessage event that instructs us to exit.
+            // See SendExitEvent() below.
+            using (new XLock(window.Display))
+            using (XIEventMask mask = new XIEventMask(1,
+                XIEventMasks.RawKeyPressMask |
+                XIEventMasks.RawKeyReleaseMask |
+                XIEventMasks.RawButtonPressMask |
+                XIEventMasks.RawButtonReleaseMask |
+                XIEventMasks.RawMotionMask |
+                XIEventMasks.MotionMask |
+                XIEventMasks.DeviceChangedMask))
+            {
+                XI.SelectEvents(window.Display, window.RootWindow, mask);
+                UpdateDevices();
+            }
+
+            ProcessingThread = new Thread(ProcessEvents);
+            ProcessingThread.IsBackground = true;
+            ProcessingThread.Start();
+        }
+
+        // Checks whether XInput2 is supported on the specified display.
+        // If a display is not specified, the default display is used.
+        internal static bool IsSupported(IntPtr display)
+        {
+            try
+            {
+                if (display == IntPtr.Zero)
+                {
+                    display = API.DefaultDisplay;
+                }
+
+                using (new XLock(display))
+                {
+                    int major, ev, error;
+                    if (Functions.XQueryExtension(display, "XInputExtension", out major, out ev, out error) != 0)
+                    {
+                        XIOpCode = major;
+
+                        int minor = 2;
+                        while (minor >= 0)
+                        {
+                            if (XI.QueryVersion(display, ref major, ref minor) == ErrorCodes.Success)
+                            {
+                                XIVersion = major * 100 + minor * 10;
+                                return true;
+                            }
+                            minor--;
+                        }
+                    }
+                }
+            }
+            catch (DllNotFoundException e)
+            {
+                Debug.Print(e.ToString());
+                Debug.Print("XInput2 extension not supported. Mouse support will suffer.");
+            }
+
+            return false;
+        }
+
+        #region IKeyboardDriver2 Members
+
+        KeyboardState IKeyboardDriver2.GetState()
+        {
+            lock (Sync)
+            {
+                KeyboardState state = new KeyboardState();
+                foreach (XIKeyboard k in keyboards)
+                {
+                    state.MergeBits(k.State);
+                }
+                return state;
+            }
+        }
+
+        KeyboardState IKeyboardDriver2.GetState(int index)
+        {
+            lock (Sync)
+            {
+                if (index >= 0 && index < keyboards.Count)
+                {
+                    return keyboards[index].State;
+                }
+                return new KeyboardState();
+            }
+        }
+
+        string IKeyboardDriver2.GetDeviceName(int index)
+        {
+            lock (Sync)
+            {
+                if (index >= 0 && index < keyboards.Count)
+                {
+                    return keyboards[index].Name;
+                }
+                return String.Empty;
+            } 
+        }
+
+        #endregion
+
+        #region IMouseDriver2 Members
+
+        MouseState IMouseDriver2.GetState()
+        {
+            lock (Sync)
+            {
+                MouseState master = new MouseState();
+                foreach (var d in devices)
+                {
+                    master.MergeBits(d.State);
+                }
+                return master;
+            }
+        }
+
+        MouseState IMouseDriver2.GetState(int index)
+        {
+            lock (Sync)
+            {
+                if (index >= 0 && index < devices.Count)
+                {
+                    return devices[index].State;
+                }
+                return new MouseState();
+            }
+        }
+
+        MouseState IMouseDriver2.GetCursorState()
+        {
+            lock (Sync)
+            {
+                MouseState master = (this as IMouseDriver2).GetState();
+                master.X = (int)Interlocked.Read(ref cursor_x);
+                master.Y = (int)Interlocked.Read(ref cursor_y);
+                return master;
+            }
+        }
+
+        void IMouseDriver2.SetPosition(double x, double y)
+        {
+            // Note: we cannot use window.Display here, because
+            // that will deadlock the input thread, which is
+            // blocking inside XIfEvent
+            using (new XLock(API.DefaultDisplay))
+            {
+                Functions.XWarpPointer(API.DefaultDisplay,
+                    IntPtr.Zero, window.RootWindow, 0, 0, 0, 0, (int)x, (int)y);
+                Functions.XFlush(API.DefaultDisplay);
+                Interlocked.Exchange(ref cursor_x, (long)x);
+                Interlocked.Exchange(ref cursor_y, (long)y);
+            }
+        }
+
+        #endregion
+
+        #region Private Members
+
+        void UpdateDevices()
+        {
+            lock (Sync)
+            {
+                devices.Clear();
+                keyboards.Clear();
+
+                int count;
+                unsafe
+                {
+                    XIDeviceInfo* list = (XIDeviceInfo*)XI.QueryDevice(window.Display,
+                        XI.XIAllDevices, out count);
+
+                    Debug.Print("Refreshing input device list");
+                    Debug.Print("{0} input devices detected", count);
+
+                    for (int i = 0; i < count; i++)
+                    {
+                        switch ((list + i)->use)
+                        {
+                            case XIDeviceType.MasterKeyboard:
+                            //case XIDeviceType.SlaveKeyboard:
+                                {
+                                    XIKeyboard k = new XIKeyboard();
+                                    k.DeviceInfo = *(list + i);
+                                    k.State.SetIsConnected(k.DeviceInfo.enabled);
+                                    k.Name = Marshal.PtrToStringAnsi(k.DeviceInfo.name);
+                                    int id = k.DeviceInfo.deviceid;
+                                    if (!keyboard_ids.ContainsKey(id))
+                                    {
+                                        keyboard_ids.Add(k.DeviceInfo.deviceid, 0);
+                                    }
+                                    keyboard_ids[id] = keyboards.Count;
+                                    keyboards.Add(k);
+                                }
+                                break;
+
+                            case XIDeviceType.MasterPointer:
+                            //case XIDeviceType.SlavePointer:
+                            case XIDeviceType.FloatingSlave:
+                                {
+                                    XIMouse d = new XIMouse();
+                                    d.DeviceInfo = *(list + i);
+                       
+                                    d.State.SetIsConnected(d.DeviceInfo.enabled);
+                                    d.Name = Marshal.PtrToStringAnsi(d.DeviceInfo.name);
+                                    Debug.Print("Device {0} \"{1}\" is {2} and has:",
+                                        i, d.Name, d.DeviceInfo.enabled ? "enabled" : "disabled");
+
+                                    // Decode the XIDeviceInfo to axes, buttons and scroll types
+                                    for (int j = 0; j < d.DeviceInfo.num_classes; j++)
+                                    {
+                                        XIAnyClassInfo* class_info = *((XIAnyClassInfo**)d.DeviceInfo.classes + j);
+                                        switch (class_info->type)
+                                        {
+                                            case XIClassType.Button:
+                                                {
+                                                    XIButtonClassInfo* button = (XIButtonClassInfo*)class_info;
+                                                    Debug.Print("\t{0} buttons", button->num_buttons);
+                                                }
+                                                break;
+
+                                            case XIClassType.Scroll:
+                                                {
+                                                    XIScrollClassInfo* scroll = (XIScrollClassInfo*)class_info;
+                                                    switch (scroll->scroll_type)
+                                                    {
+                                                        case XIScrollType.Vertical:
+                                                            Debug.WriteLine("\tSmooth vertical scrolling");
+                                                            d.ScrollY = *scroll;
+                                                            break;
+
+                                                        case XIScrollType.Horizontal:
+                                                            Debug.WriteLine("\tSmooth horizontal scrolling");
+                                                            d.ScrollX = *scroll;
+                                                            break;
+
+                                                        default:
+                                                            Debug.Print("\tUnknown scrolling type {0}", scroll->scroll_type);
+                                                            break;
+                                                    }
+                                                }
+                                                break;
+
+                                            case XIClassType.Valuator:
+                                                {
+                                                    // We use relative x/y valuators for mouse movement.
+                                                    // Iff these are not available, we fall back to
+                                                    // absolute x/y valuators.
+                                                    XIValuatorClassInfo* valuator = (XIValuatorClassInfo*)class_info;
+                                                    if (valuator->label == XI.RelativeX)
+                                                    {
+                                                        Debug.WriteLine("\tRelative X movement");
+                                                        d.MotionX = *valuator;
+                                                    }
+                                                    else if (valuator->label == XI.RelativeY)
+                                                    {
+                                                        Debug.WriteLine("\tRelative Y movement");
+                                                        d.MotionY = *valuator;
+                                                    }
+                                                    else if (valuator->label == XI.AbsoluteX)
+                                                    {
+                                                        Debug.WriteLine("\tAbsolute X movement");
+                                                        if (d.MotionX.number == -1)
+                                                            d.MotionX = *valuator;
+                                                    }
+                                                    else if (valuator->label == XI.AbsoluteY)
+                                                    {
+                                                        Debug.WriteLine("\tAbsolute X movement");
+                                                        if (d.MotionY.number == -1)
+                                                            d.MotionY = *valuator;
+                                                    }
+                                                    else
+                                                    {
+                                                        IntPtr label = Functions.XGetAtomName(window.Display, valuator->label);
+                                                        Debug.Print("\tUnknown valuator {0}",
+                                                            Marshal.PtrToStringAnsi(label));
+                                                        Functions.XFree(label);
+                                                    }
+                                                }
+                                                break;
+                                        }
+                                    }
+
+                                    // Map the hardware device id to the current XIMouse id
+                                    int id = d.DeviceInfo.deviceid;
+                                    if (!rawids.ContainsKey(id))
+                                    {
+                                        rawids.Add(id, 0);
+                                    }
+                                    rawids[id] = devices.Count;
+                                    devices.Add(d);
+                                }
+                                break;
+                        }
+                    }
+                    XI.FreeDeviceInfo((IntPtr)list);
+                }
+            }
+        }
+
+        void ProcessEvents()
+        {
+            while (!disposed)
+            {
+                XEvent e = new XEvent();
+                XGenericEventCookie cookie;
+
+                using (new XLock(window.Display))
+                {
+                    Functions.XIfEvent(window.Display, ref e, Predicate, new IntPtr(XIOpCode));
+
+                    if (e.type == XEventName.ClientMessage && e.ClientMessageEvent.ptr1 == ExitAtom)
+                    {
+                        Functions.XDestroyWindow(window.Display, window.Handle);
+                        window.Handle = IntPtr.Zero;
+                        break;
+                    }
+
+                    if (e.type == XEventName.GenericEvent && e.GenericEvent.extension == XIOpCode)
+                    {
+                        IntPtr dummy;
+                        int x, y, dummy2;
+                        Functions.XQueryPointer(window.Display, window.RootWindow,
+                            out dummy, out dummy, out x, out y,
+                            out dummy2, out dummy2, out dummy2);
+                        Interlocked.Exchange(ref cursor_x, (long)x);
+                        Interlocked.Exchange(ref cursor_y, (long)y);
+
+                        cookie = e.GenericEventCookie;
+                        if (Functions.XGetEventData(window.Display, ref cookie) != 0)
+                        {
+                            switch ((XIEventType)cookie.evtype)
+                            {
+                                case XIEventType.Motion:
+                                // Nothing to do
+                                    break;
+
+                                case XIEventType.RawKeyPress:
+                                case XIEventType.RawKeyRelease:
+                                case XIEventType.RawMotion:
+                                case XIEventType.RawButtonPress:
+                                case XIEventType.RawButtonRelease:
+                                // Delivered to all XIMouse instances
+                                    ProcessRawEvent(ref cookie);
+                                    break;
+
+                                case XIEventType.DeviceChanged:
+                                    UpdateDevices();
+                                    break;
+                            }
+                        }
+                        Functions.XFreeEventData(window.Display, ref cookie);
+                    }
+                }
+            }
+            Debug.WriteLine("[X11] Exiting input event loop.");
+        }
+
+        void ProcessRawEvent(ref XGenericEventCookie cookie)
+        {
+            lock (Sync)
+            {
+                unsafe
+                {
+                    XIRawEvent raw = *(XIRawEvent*)cookie.data;
+                    XIMouse mouse;
+                    XIKeyboard keyboard;
+
+                    switch (raw.evtype)
+                    {
+                        case XIEventType.RawMotion:
+                            if (GetMouseDevice(raw.deviceid, out mouse))
+                            {
+                                ProcessRawMotion(mouse, ref raw);
+                            }
+                            break;
+
+                        case XIEventType.RawButtonPress:
+                        case XIEventType.RawButtonRelease:
+                            if (GetMouseDevice(raw.deviceid, out mouse))
+                            {
+                                float dx, dy;
+                                MouseButton button = X11KeyMap.TranslateButton(raw.detail, out dx, out dy);
+                                mouse.State[button] = raw.evtype == XIEventType.RawButtonPress;
+                                if (mouse.ScrollX.number == -1 && mouse.ScrollY.number == -1)
+                                    mouse.State.SetScrollRelative(dx, dy);
+                            }
+                            break;
+
+                        case XIEventType.RawKeyPress:
+                        case XIEventType.RawKeyRelease:
+                            if (GetKeyboardDevice(raw.deviceid, out keyboard))
+                            {
+                                Key key;
+                                if (KeyMap.TranslateKey(raw.detail, out key))
+                                {
+                                    keyboard.State[key] = raw.evtype == XIEventType.RawKeyPress;
+                                }
+                            }
+                            break;
+                    }
+                }
+            }
+        }
+
+        bool GetMouseDevice(int deviceid, out XIMouse mouse)
+        {
+            if (!rawids.ContainsKey(deviceid))
+            {
+                Debug.Print("Unknown mouse device {0} encountered, ignoring.", deviceid);
+                mouse = null;
+                return false;
+            }
+            mouse = devices[rawids[deviceid]];
+            return true;
+        }
+
+        bool GetKeyboardDevice(int deviceid, out XIKeyboard keyboard)
+        {
+            if (!keyboard_ids.ContainsKey(deviceid))
+            {
+                Debug.Print("Unknown keyboard device {0} encountered, ignoring.", deviceid);
+                keyboard = null;
+                return false;
+            }
+            keyboard = keyboards[keyboard_ids[deviceid]];
+            return true;
+        }
+
+        unsafe static void ProcessRawMotion(XIMouse d, ref XIRawEvent raw)
+        {
+            // Note: we use the raw values here, without pointer
+            // ballistics and any other modification.
+            double x = 0;
+            double y = 0;
+            double h = 0;
+            double v = 0;
+            if (d.MotionX.number != -1)
+                x = ReadRawValue(ref raw, d.MotionX.number);
+            if (d.MotionY.number != -1)
+                y = ReadRawValue(ref raw, d.MotionY.number);
+            if (d.ScrollX.number != -1)
+                h = ReadRawValue(ref raw, d.ScrollX.number) / d.ScrollX.increment;
+            if (d.ScrollY.number != -1)
+                v = ReadRawValue(ref raw, d.ScrollY.number) / d.ScrollY.increment;
+
+            if (d.MotionX.mode == XIMode.Relative)
+                d.State.X += (int)Math.Round(x);
+            else
+                d.State.X = (int)Math.Round(x);
+            if (d.MotionY.mode == XIMode.Relative)
+                d.State.Y += (int)Math.Round(y);
+            else
+                d.State.Y = (int)Math.Round(y);
+
+            // Note: OpenTK follows the windows scrolling convention where
+            // (+h, +v) = (right, up). XI2 uses (+h, +v) = (right, down)
+            // instead, so we need to flip the vertical offset.
+            d.State.SetScrollRelative((float)h, (float)(-v));
+        }
+
+        unsafe static double ReadRawValue(ref XIRawEvent raw, int bit)
+        {
+            double value = 0;
+            if (IsBitSet(raw.valuators.mask, bit))
+            {
+                // Find the offset where this value is stored.
+                // The offset is equal to the number of bits
+                // set in raw.valuators.mask between [0, bit)
+                int offset = 0;
+                for (int i = 0; i < bit; i++)
+                {
+                    if (IsBitSet(raw.valuators.mask, i))
+                    {
+                        offset++;
+                    }
+                }
+                value = *((double*)raw.raw_values + offset);
+            }
+            return value;
+        }
+
+        static bool IsEventValid(IntPtr display, ref XEvent e, IntPtr arg)
+        {
+            bool valid = false;
+            switch (e.type)
+            {
+                case XEventName.GenericEvent:
+                {
+                    long extension = (long)e.GenericEventCookie.extension;
+                    valid =
+                        extension == arg.ToInt64() &&
+                        (e.GenericEventCookie.evtype == (int)XIEventType.RawKeyPress ||
+                        e.GenericEventCookie.evtype == (int)XIEventType.RawKeyRelease ||
+                        e.GenericEventCookie.evtype == (int)XIEventType.RawMotion ||
+                        e.GenericEventCookie.evtype == (int)XIEventType.RawButtonPress ||
+                        e.GenericEventCookie.evtype == (int)XIEventType.RawButtonRelease ||
+                        e.GenericEventCookie.evtype == (int)XIEventType.DeviceChanged);
+                    valid |= extension == 0;
+                    break;
+                }
+
+                case XEventName.ClientMessage:
+                    valid =
+                        e.ClientMessageEvent.ptr1 == ExitAtom;
+                    break;
+            }
+
+            return valid;
+        }
+
+        static bool IsBitSet(IntPtr mask, int bit)
+        {
+            unsafe
+            {
+                return bit >= 0 && (*((byte*)mask + (bit >> 3)) & (1 << (bit & 7))) != 0;
+            }
+        }
+
+        void SendExitEvent()
+        {
+            // Send a ClientMessage event to unblock XIfEvent
+            // and exit the input event loop.
+            using (new XLock(API.DefaultDisplay))
+            {
+                XEvent ev = new XEvent();
+                ev.type = XEventName.ClientMessage;
+                ev.ClientMessageEvent.display = window.Display;
+                ev.ClientMessageEvent.window = window.Handle;
+                ev.ClientMessageEvent.format = 32;
+                ev.ClientMessageEvent.ptr1 = ExitAtom;
+                Functions.XSendEvent(API.DefaultDisplay, window.Handle, false, 0, ref ev);
+                Functions.XFlush(API.DefaultDisplay);
+            }
+        }
+
+        #endregion
+
+        #region IDisposable Members
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        void Dispose(bool disposing)
+        {
+            if (!disposed)
+            {
+                disposed = true;
+                SendExitEvent();
+            }
+        }
+
+        ~XI2MouseKeyboard()
+        {
+            Dispose(false);
+        }
+
+        #endregion
+    }
+}
+
index 360f4400d2949267e7c49dbe8b56424001ca8e7c..c8ed0feb8e1469cd99cef19b3e4ef1d170df1610 100644 (file)
     <WarningLevel>4</WarningLevel>
     <ConsolePause>false</ConsolePause>
     <DefineConstants>DEBUG;TRACE;MEASURE_TIME</DefineConstants>
-    <IntermediateOutputPath>$(SolutionDir)build\obj\$(Configuration)</IntermediateOutputPath>
-    <OutputPath>$(SolutionDir)build\$(Configuration)</OutputPath>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <DebugType>none</DebugType>
     <Optimize>true</Optimize>
     <WarningLevel>0</WarningLevel>
     <ConsolePause>false</ConsolePause>
-    <IntermediateOutputPath>$(SolutionDir)build\obj\$(Configuration)</IntermediateOutputPath>
-    <OutputPath>$(SolutionDir)build\$(Configuration)</OutputPath>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />