--- /dev/null
+#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;
+
+namespace OpenTK.Platform.X11
+{
+ 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;
+ }
+}
+