From e8176ef7cf4bfdb30ff619fd235414b8809ad284 Mon Sep 17 00:00:00 2001 From: thefiddler Date: Thu, 15 May 2014 00:32:37 +0200 Subject: [PATCH] [X11] Added XKB bindings --- Source/OpenTK/OpenTK.csproj | 2 + Source/OpenTK/Platform/X11/Bindings/Xkb.cs | 302 +++++++++++++++++++++ 2 files changed, 304 insertions(+) create mode 100644 Source/OpenTK/Platform/X11/Bindings/Xkb.cs diff --git a/Source/OpenTK/OpenTK.csproj b/Source/OpenTK/OpenTK.csproj index 502877fb..2824d678 100644 --- a/Source/OpenTK/OpenTK.csproj +++ b/Source/OpenTK/OpenTK.csproj @@ -790,6 +790,7 @@ + @@ -798,6 +799,7 @@ Code + diff --git a/Source/OpenTK/Platform/X11/Bindings/Xkb.cs b/Source/OpenTK/Platform/X11/Bindings/Xkb.cs new file mode 100644 index 00000000..0be69717 --- /dev/null +++ b/Source/OpenTK/Platform/X11/Bindings/Xkb.cs @@ -0,0 +1,302 @@ +#region License +// +// Xkb.cs +// +// Author: +// Stefanos Apostolopoulos +// +// 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; + } +} +