Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'mcs/class/Managed.Windows.Forms/System.Windows.Forms/X11Keyboard.cs')
-rw-r--r--mcs/class/Managed.Windows.Forms/System.Windows.Forms/X11Keyboard.cs686
1 files changed, 686 insertions, 0 deletions
diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/X11Keyboard.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/X11Keyboard.cs
new file mode 100644
index 00000000000..e68f8ead190
--- /dev/null
+++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/X11Keyboard.cs
@@ -0,0 +1,686 @@
+// 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:
+// Jackson Harper (jackson@ximian.com)
+//
+//
+
+
+//
+// TODO:
+// - dead chars are not translated properly
+// - There is a lot of potential for optimmization in here
+//
+using System;
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace System.Windows.Forms {
+
+ internal class X11Keyboard {
+
+ private IntPtr display;
+ private int min_keycode, max_keycode, keysyms_per_keycode, syms;
+ private int [] keyc2vkey = new int [256];
+ private int [] keyc2scan = new int [256];
+ private byte [] key_state_table = new byte [256];
+ private bool num_state, cap_state;
+ private KeyboardLayout layout = KeyboardLayouts.Layouts [0];
+
+ // TODO
+ private int NumLockMask;
+ private int AltGrMask;
+
+ public X11Keyboard (IntPtr display)
+ {
+ this.display = display;
+ DetectLayout ();
+ CreateConversionArray (layout);
+ }
+
+ public Keys ModifierKeys {
+ get {
+ Keys keys = Keys.None;
+ if ((key_state_table [(int) VirtualKeys.VK_SHIFT] & 0x80) != 0)
+ keys |= Keys.Shift;
+ if ((key_state_table [(int) VirtualKeys.VK_CONTROL] & 0x80) != 0)
+ keys |= Keys.Control;
+ if ((key_state_table [(int) VirtualKeys.VK_MENU] & 0x80) != 0)
+ keys |= Keys.Alt;
+ return keys;
+ }
+ }
+
+ public void KeyEvent (IntPtr hwnd, XEvent xevent, ref MSG msg)
+ {
+ XKeySym keysym;
+
+ XLookupString (ref xevent, IntPtr.Zero, 0, out keysym, IntPtr.Zero);
+ if (((int) keysym >= (int) MiscKeys.XK_ISO_Lock &&
+ (int) keysym <= (int) MiscKeys.XK_ISO_Last_Group_Lock) ||
+ (int) keysym == (int) MiscKeys.XK_Mode_switch) {
+ UpdateKeyState (xevent);
+ return;
+ }
+
+ if ((xevent.KeyEvent.keycode >> 8) == 0x10)
+ xevent.KeyEvent.keycode = xevent.KeyEvent.keycode & 0xFF;
+
+ int event_time = (int)xevent.KeyEvent.time;
+
+ AltGrMask = xevent.KeyEvent.state & (0x6000 | (int) KeyMasks.ModMasks);
+ int vkey = EventToVkey (xevent);
+ if (vkey == 0)
+ return;
+
+ switch ((VirtualKeys) (vkey & 0xFF)) {
+ case VirtualKeys.VK_NUMLOCK:
+ GenerateMessage (VirtualKeys.VK_NUMLOCK, 0x45, xevent.type, event_time);
+ break;
+ case VirtualKeys.VK_CAPITAL:
+ GenerateMessage (VirtualKeys.VK_CAPITAL, 0x3A, xevent.type, event_time);
+ break;
+ default:
+
+ if (((key_state_table [(int) VirtualKeys.VK_NUMLOCK] & 0x01) == 0) != ((xevent.KeyEvent.state & NumLockMask) == 0)) {
+ GenerateMessage (VirtualKeys.VK_NUMLOCK, 0x45, XEventName.KeyPress, event_time);
+ GenerateMessage (VirtualKeys.VK_NUMLOCK, 0x45, XEventName.KeyRelease, event_time);
+ }
+
+ if (((key_state_table [(int) VirtualKeys.VK_CAPITAL] & 0x01) == 0) != ((xevent.KeyEvent.state & (int) KeyMasks.LockMask) == 0)) {
+ GenerateMessage (VirtualKeys.VK_CAPITAL, 0x3A, XEventName.KeyPress, event_time);
+ GenerateMessage (VirtualKeys.VK_CAPITAL, 0x3A, XEventName.KeyRelease, event_time);
+ }
+
+ num_state = false;
+ cap_state = false;
+
+ int bscan = (keyc2scan [xevent.KeyEvent.keycode] & 0xFF);
+ KeybdEventFlags dw_flags = KeybdEventFlags.None;
+ if (xevent.type == XEventName.KeyRelease)
+ dw_flags |= KeybdEventFlags.KeyUp;
+ if ((vkey & 0x100) != 0)
+ dw_flags |= KeybdEventFlags.ExtendedKey;
+ msg = SendKeyboardInput ((VirtualKeys) (vkey & 0xFF), bscan, dw_flags, event_time);
+ msg.hwnd = hwnd;
+ break;
+ }
+ }
+
+ public bool TranslateMessage (ref MSG msg)
+ {
+ bool res = false;
+
+ if (msg.message >= Msg.WM_KEYFIRST && msg.message <= Msg.WM_KEYLAST)
+ res = true;
+
+ if (msg.message != Msg.WM_KEYDOWN && msg.message != Msg.WM_SYSKEYDOWN)
+ return res;
+
+ string buffer;
+ Msg message;
+
+ int tu = ToUnicode ((int) msg.wParam, Control.HighOrder ((int) msg.lParam), out buffer);
+ switch (tu) {
+ case 1:
+ message = (msg.message == Msg.WM_KEYDOWN ? Msg.WM_CHAR : Msg.WM_SYSCHAR);
+ XplatUI.PostMessage (msg.hwnd, message, (IntPtr) buffer [0], msg.lParam);
+ break;
+ case -1:
+ message = (msg.message == Msg.WM_KEYDOWN ? Msg.WM_DEADCHAR : Msg.WM_SYSDEADCHAR);
+ XplatUI.PostMessage (msg.hwnd, message, (IntPtr) buffer [0], msg.lParam);
+ return true;
+ }
+
+ return res;
+ }
+
+ private int ToUnicode (int vkey, int scan, out string buffer)
+ {
+ if ((scan & 0x8000) != 0) {
+ buffer = String.Empty;
+ return 0;
+ }
+
+ XEvent e = new XEvent ();
+ e.KeyEvent.display = display;
+ e.KeyEvent.keycode = 0;
+ e.KeyEvent.state = 0;
+
+ if ((key_state_table [(int) VirtualKeys.VK_SHIFT] & 0x80) != 0) {
+ e.KeyEvent.state |= (int) KeyMasks.ShiftMask;
+ }
+
+ if ((key_state_table [(int) VirtualKeys.VK_CAPITAL] & 0x01) != 0) {
+ e.KeyEvent.state |= (int) KeyMasks.LockMask;
+ }
+
+ if ((key_state_table [(int) VirtualKeys.VK_CONTROL] & 0x80) != 0) {
+ e.KeyEvent.state |= (int) KeyMasks.ControlMask;
+ }
+
+ if ((key_state_table [(int) VirtualKeys.VK_NUMLOCK] & 0x01) != 0) {
+ e.KeyEvent.state |= NumLockMask;
+ }
+
+ e.KeyEvent.state |= AltGrMask;
+
+ for (int keyc = min_keycode; (keyc <= max_keycode) && (e.KeyEvent.keycode == 0); keyc++) {
+ // find keycode that could have generated this vkey
+ if ((keyc2vkey [keyc] & 0xFF) == vkey) {
+ // filter extended bit because it is not known
+ e.KeyEvent.keycode = keyc;
+ if ((EventToVkey (e) & 0xFF) != vkey) {
+ // Wrong one (ex: because of num,lock state)
+ e.KeyEvent.keycode = 0;
+ }
+ }
+ }
+
+ if ((vkey >= (int) VirtualKeys.VK_NUMPAD0) && (vkey <= (int) VirtualKeys.VK_NUMPAD9))
+ e.KeyEvent.keycode = XKeysymToKeycode (display, vkey - (int) VirtualKeys.VK_NUMPAD0 + (int) KeypadKeys.XK_KP_0);
+
+ if (vkey == (int) VirtualKeys.VK_DECIMAL)
+ e.KeyEvent.keycode = XKeysymToKeycode (display, (int) KeypadKeys.XK_KP_Decimal);
+
+ if (e.KeyEvent.keycode == 0) {
+ // And I couldn't find the keycode so i returned the vkey and was like whatever
+ Console.Error.WriteLine ("unknown virtual key {0:X}", vkey);
+ buffer = String.Empty;
+ return vkey;
+ }
+
+ IntPtr buf = Marshal.AllocHGlobal (2);
+ XKeySym t;
+ int res = XLookupString (ref e, buf, 2, out t, IntPtr.Zero);
+ int keysym = (int) t;
+
+ buffer = String.Empty;
+ if (res == 0) {
+ int dead_char = MapDeadKeySym (keysym);
+ if (dead_char != 0) {
+ byte [] bytes = new byte [1];
+ bytes [0] = (byte) dead_char;
+ Encoding encoding = Encoding.GetEncoding (layout.CodePage);
+ buffer = new string (encoding.GetChars (bytes));
+ res = -1;
+ }
+ } else {
+ // Shift + arrow, shift + home, ....
+ // X returns a char for it, but windows doesn't
+ if (((e.KeyEvent.state & NumLockMask) == 0) && ((e.KeyEvent.state & (int) KeyMasks.ShiftMask) != 0) &&
+ (keysym >= (int) KeypadKeys.XK_KP_0) && (keysym <= (int) KeypadKeys.XK_KP_9)) {
+ buffer = String.Empty;
+ res = 0;
+ }
+
+ // CTRL + number, X returns chars, windows does not
+ if ((e.KeyEvent.state & (int) KeyMasks.ControlMask) != 0) {
+ if (((keysym >= 33) && (keysym < 'A')) || ((keysym > 'Z') && (keysym < 'a'))) {
+ buffer = String.Empty;
+ res = 0;
+ }
+ }
+
+ // X returns a char for delete key on extended keyboards, windows does not
+ if (keysym == (int) TtyKeys.XK_Delete) {
+ buffer = String.Empty;
+ res = 0;
+ }
+
+ if (res != 0) {
+ byte [] bytes = new byte [2];
+ bytes [0] = Marshal.ReadByte (buf);
+ bytes [1] = Marshal.ReadByte (buf, 1);
+ Encoding encoding = Encoding.GetEncoding (layout.CodePage);
+ buffer = new string (encoding.GetChars (bytes));
+ }
+ }
+
+ return res;
+ }
+
+ private MSG SendKeyboardInput (VirtualKeys vkey, int scan, KeybdEventFlags dw_flags, int time)
+ {
+ Msg message;
+
+ if ((dw_flags & KeybdEventFlags.KeyUp) != 0) {
+ bool sys_key = (key_state_table [(int) VirtualKeys.VK_MENU] & 0x80) != 0 &&
+ ((key_state_table [(int) VirtualKeys.VK_CONTROL] & 0x80) == 0);
+ key_state_table [(int) vkey] &= unchecked ((byte) ~0x80);
+ message = (sys_key ? Msg.WM_SYSKEYUP : Msg.WM_KEYUP);
+ } else {
+ if ((key_state_table [(int) vkey] & 0x80) == 0) {
+ key_state_table [(int) vkey] ^= 0x01;
+ }
+ key_state_table [(int) vkey] |= 0x80;
+ bool sys_key = (key_state_table [(int) VirtualKeys.VK_MENU] & 0x80) != 0 &&
+ ((key_state_table [(int) VirtualKeys.VK_CONTROL] & 0x80) == 0);
+ message = (sys_key ? Msg.WM_SYSKEYDOWN : Msg.WM_KEYDOWN);
+ }
+
+ MSG msg = new MSG ();
+ msg.message = message;
+ msg.wParam = (IntPtr) vkey;
+ if ((key_state_table [(int) VirtualKeys.VK_MENU] & 0x80) != 0)
+ msg.lParam = new IntPtr (0x20000000);
+ else
+ msg.lParam = IntPtr.Zero;
+
+ return msg;
+ }
+
+ private void GenerateMessage (VirtualKeys vkey, int scan, XEventName type, int event_time)
+ {
+ bool state = (vkey == VirtualKeys.VK_NUMLOCK ? num_state : cap_state);
+ KeybdEventFlags up, down;
+
+ if (state) {
+ // The INTERMEDIARY state means : just after a 'press' event, if a 'release' event comes,
+ // don't treat it. It's from the same key press. Then the state goes to ON.
+ // And from there, a 'release' event will switch off the toggle key.
+ SetState (vkey, false);
+ } else {
+ down = (vkey == VirtualKeys.VK_NUMLOCK ? KeybdEventFlags.ExtendedKey : KeybdEventFlags.None);
+ up = (vkey == VirtualKeys.VK_NUMLOCK ? KeybdEventFlags.ExtendedKey :
+ KeybdEventFlags.None) | KeybdEventFlags.KeyUp;
+ if ((key_state_table [(int) vkey] & 0x1) != 0) { // it was on
+ if (type != XEventName.KeyPress) {
+ SendKeyboardInput (vkey, scan, down, event_time);
+ SendKeyboardInput (vkey, scan, up, event_time);
+ SetState (vkey, false);
+ key_state_table [(int) vkey] &= unchecked ((byte) ~0x01);
+ }
+ } else {
+ if (type == XEventName.KeyPress) {
+ SendKeyboardInput (vkey, scan, down, event_time);
+ SendKeyboardInput (vkey, scan, up, event_time);
+ SetState (vkey, true);
+ key_state_table [(int) vkey] |= 0x01;
+ }
+ }
+ }
+ }
+
+ private void UpdateKeyState (XEvent xevent)
+ {
+ int vkey = EventToVkey (xevent);
+
+ switch (xevent.type) {
+ case XEventName.KeyRelease:
+ key_state_table [(int) vkey] &= unchecked ((byte) ~0x80);
+ break;
+ case XEventName.KeyPress:
+ if ((key_state_table [(int) vkey] & 0x80) == 0) {
+ key_state_table [(int) vkey] ^= 0x01;
+ }
+ key_state_table [(int) vkey] |= 0x80;
+ break;
+ }
+ }
+
+ private void SetState (VirtualKeys key, bool state)
+ {
+ if (VirtualKeys.VK_NUMLOCK == key)
+ num_state = state;
+ else
+ cap_state = state;
+ }
+
+ public int EventToVkey (XEvent e)
+ {
+ XKeySym ks;
+
+ XLookupString (ref e, IntPtr.Zero, 0, out ks, IntPtr.Zero);
+ int keysym = (int) ks;
+
+ if ((keysym >= 0xFFAE) && (keysym <= 0xFFB9) && (keysym != 0xFFAF)
+ && ((e.KeyEvent.state & NumLockMask) !=0)) {
+ // Only the Keypad keys 0-9 and . send different keysyms
+ // depending on the NumLock state
+ return KeyboardLayouts.nonchar_key_vkey [keysym & 0xFF];
+ }
+
+ return keyc2vkey [e.KeyEvent.keycode];
+ }
+
+ public void CreateConversionArray (KeyboardLayout layout)
+ {
+
+ XEvent e2 = new XEvent ();
+ int keysym = 0;
+ int [] ckey = new int [] { 0, 0, 0, 0 };
+
+ e2.KeyEvent.display = display;
+ e2.KeyEvent.state = 0;
+
+ int oem_vkey = (int) VirtualKeys.VK_OEM_7;
+ for (int keyc = min_keycode; keyc <= max_keycode; keyc++) {
+ int vkey = 0;
+ int scan = 0;
+
+ e2.KeyEvent.keycode = keyc;
+ XKeySym t;
+ XLookupString (ref e2, IntPtr.Zero, 0, out t, IntPtr.Zero);
+ keysym = (int) t;
+ if (keysym != 0) {
+ if ((keysym >> 8) == 0xFF) {
+ vkey = KeyboardLayouts.nonchar_key_vkey [keysym & 0xFF];
+ scan = KeyboardLayouts.nonchar_key_scan [keysym & 0xFF];
+ // Set extended bit
+ if ((scan & 0x100) != 0)
+ vkey |= 0x100;
+ } else if (keysym == 0x20) { // spacebar
+ vkey = (int) VirtualKeys.VK_SPACE;
+ scan = 0x39;
+ } else {
+ // Search layout dependent scancodes
+ int maxlen = 0;
+ int maxval = -1;;
+ int ok;
+
+ for (int i = 0; i < syms; i++) {
+ keysym = (int) XKeycodeToKeysym (display, keyc, i);
+ if ((keysym < 0x800) && (keysym != ' '))
+ ckey [i] = keysym & 0xFF;
+ else
+ ckey [i] = MapDeadKeySym (keysym);
+ }
+
+ for (int keyn = 0; keyn < layout.Key.Length; keyn++) {
+ int i = 0;
+ int ml = (layout.Key [keyn].Length > 4 ? 4 : layout.Key [keyn].Length);
+ for (ok = layout.Key [keyn][i]; (ok != 0) && (i < ml); i++) {
+ if (layout.Key [keyn][i] != ckey [i])
+ ok = 0;
+ if ((ok != 0) || (i > maxlen)) {
+ maxlen = i;
+ maxval = keyn;
+ }
+ if (ok != 0)
+ break;
+ }
+ }
+ if (maxval >= 0) {
+ scan = layout.Scan [maxval];
+ vkey = (int) layout.VKey [maxval];
+ }
+
+ }
+
+ for (int i = 0; (i < keysyms_per_keycode) && (vkey == 0); i++) {
+ keysym = (int) XLookupKeysym (ref e2, i);
+ if ((keysym >= (int) VirtualKeys.VK_0 && keysym <= (int) VirtualKeys.VK_9) ||
+ (keysym >= (int) VirtualKeys.VK_A && keysym <= (int) VirtualKeys.VK_Z)) {
+ vkey = keysym;
+ }
+ }
+
+ for (int i = 0; (i < keysyms_per_keycode) && (vkey == 0); i++) {
+ keysym = (int) XLookupKeysym (ref e2, i);
+ switch ((char) keysym) {
+ case ';':
+ vkey = (int) VirtualKeys.VK_OEM_1;
+ break;
+ case '/':
+ vkey = (int) VirtualKeys.VK_OEM_2;
+ break;
+ case '`':
+ vkey = (int) VirtualKeys.VK_OEM_3;
+ break;
+ case '[':
+ vkey = (int) VirtualKeys.VK_OEM_4;
+ break;
+ case '\\':
+ vkey = (int) VirtualKeys.VK_OEM_5;
+ break;
+ case ']':
+ vkey = (int) VirtualKeys.VK_OEM_6;
+ break;
+ case '\'':
+ vkey = (int) VirtualKeys.VK_OEM_7;
+ break;
+ case ',':
+ vkey = (int) VirtualKeys.VK_OEM_COMMA;
+ break;
+ case '.':
+ vkey = (int) VirtualKeys.VK_OEM_PERIOD;
+ break;
+ case '-':
+ vkey = (int) VirtualKeys.VK_OEM_MINUS;
+ break;
+ case '+':
+ vkey = (int) VirtualKeys.VK_OEM_PLUS;
+ break;
+
+ }
+ }
+
+ if (vkey == 0) {
+ switch (++oem_vkey) {
+ case 0xc1:
+ oem_vkey = 0xDB;
+ break;
+ case 0xE5:
+ oem_vkey = 0xE9;
+ break;
+ case 0xF6:
+ oem_vkey = 0xF5;
+ break;
+ }
+ vkey = oem_vkey;
+ }
+ }
+ keyc2vkey [e2.KeyEvent.keycode] = vkey;
+ keyc2scan [e2.KeyEvent.keycode] = scan;
+ }
+
+
+ }
+
+ public void DetectLayout ()
+ {
+ XDisplayKeycodes (display, out min_keycode, out max_keycode);
+ IntPtr ksp = XGetKeyboardMapping (display, (byte) min_keycode,
+ max_keycode + 1 - min_keycode, out keysyms_per_keycode);
+ XplatUIX11.XFree (ksp);
+
+ syms = keysyms_per_keycode;
+ if (syms > 4) {
+ //Console.Error.WriteLine ("{0} keysymbols per a keycode is not supported, setting to 4", syms);
+ syms = 2;
+ }
+
+ IntPtr modmap_unmanaged;
+ XModifierKeymap xmk = new XModifierKeymap ();
+
+ modmap_unmanaged = XGetModifierMapping (display);
+ xmk = (XModifierKeymap) Marshal.PtrToStructure (modmap_unmanaged, typeof (XModifierKeymap));
+
+ int mmp = 0;
+ for (int i = 0; i < 8; i++) {
+ for (int j = 0; j < xmk.max_keypermod; j++, mmp++) {
+ byte b = Marshal.ReadByte (xmk.modifiermap, mmp);
+ if (b != 0) {
+ for (int k = 0; k < keysyms_per_keycode; k++) {
+ if ((int) XKeycodeToKeysym (display, b, k) == (int) MiscKeys.XK_Num_Lock)
+ NumLockMask = 1 << i;
+ }
+ }
+ }
+ }
+ XFreeModifiermap (modmap_unmanaged);
+
+ int [] ckey = new int [4];
+ KeyboardLayout layout = null;
+ int max_score = 0;
+ int max_seq = 0;
+
+ foreach (KeyboardLayout current in KeyboardLayouts.Layouts) {
+ int ok = 0;
+ int score = 0;
+ int match = 0;
+ int seq = 0;
+ int pkey = -1;
+ int key = min_keycode;
+
+ for (int keyc = min_keycode; keyc <= max_keycode; keyc++) {
+ for (int i = 0; i < syms; i++) {
+ int keysym = (int) XKeycodeToKeysym (display, keyc, i);
+
+ if ((keysym != 0xFF1B) && (keysym < 0x800) && (keysym != ' ')) {
+ ckey [i] = keysym & 0xFF;
+ } else {
+ ckey [i] = MapDeadKeySym (keysym);
+ }
+ }
+ if (ckey [0] != 0) {
+
+ for (key = 0; key < current.Key.Length; key++) {
+ ok = 0;
+ int ml = (current.Key [key].Length > syms ? syms : current.Key [key].Length);
+ for (int i = 0; (ok >= 0) && (i < ml); i++) {
+ if (ckey [i] != 0 && current.Key [key][i] == (char) ckey [i]) {
+ ok++;
+ }
+ if (ckey [i] != 0 && current.Key [key][i] != (char) ckey [i])
+ ok = -1;
+ }
+ if (ok >= 0) {
+ score += ok;
+ break;
+ }
+ }
+ if (ok > 0) {
+ match++;
+ if (key > pkey)
+ seq++;
+ pkey = key;
+ } else {
+ score -= syms;
+ }
+ }
+ }
+
+ if ((score > max_score) || ((score == max_score) && (seq > max_seq))) {
+ // best match so far
+ layout = current;
+ max_score = score;
+ max_seq = seq;
+ }
+ }
+
+ if (layout != null) {
+ this.layout = layout;
+ Console.WriteLine (Locale.GetText("Keyboard") + ": " + layout.Comment);
+ } else {
+ Console.WriteLine (Locale.GetText("Keyboard layout not recognized, using default layout: " + layout.Comment));
+ }
+ }
+
+ // TODO
+ private int MapDeadKeySym (int val)
+ {
+ switch (val) {
+ case (int) DeadKeys.XK_dead_tilde :
+ case 0x1000FE7E : // Xfree's Dtilde
+ return '~';
+ case (int) DeadKeys.XK_dead_acute :
+ case 0x1000FE27 : // Xfree's XK_Dacute_accent
+ return 0xb4;
+ case (int) DeadKeys.XK_dead_circumflex:
+ case 0x1000FE5E : // Xfree's XK_.Dcircumflex_accent
+ return '^';
+ case (int) DeadKeys.XK_dead_grave :
+ case 0x1000FE60 : // Xfree's XK_.Dgrave_accent
+ return '`';
+ case (int) DeadKeys.XK_dead_diaeresis :
+ case 0x1000FE22 : // Xfree's XK_.Ddiaeresis
+ return 0xa8;
+ case (int) DeadKeys.XK_dead_cedilla :
+ return 0xb8;
+ case (int) DeadKeys.XK_dead_macron :
+ return '-';
+ case (int) DeadKeys.XK_dead_breve :
+ return 0xa2;
+ case (int) DeadKeys.XK_dead_abovedot :
+ return 0xff;
+ case (int) DeadKeys.XK_dead_abovering :
+ return '0';
+ case (int) DeadKeys.XK_dead_doubleacute :
+ return 0xbd;
+ case (int) DeadKeys.XK_dead_caron :
+ return 0xb7;
+ case (int) DeadKeys.XK_dead_ogonek :
+ return 0xb2;
+ }
+
+ return 0;
+ }
+
+ [DllImport ("libX11")]
+ internal extern static int XLookupString(ref XEvent xevent, IntPtr buffer, int num_bytes, out IntPtr keysym, IntPtr status);
+ internal static int XLookupString (ref XEvent xevent, IntPtr buffer, int num_bytes, out XKeySym keysym, IntPtr status) {
+ IntPtr keysym_ret;
+ int ret;
+
+ ret = XLookupString (ref xevent, buffer, num_bytes, out keysym_ret, status);
+ keysym = (XKeySym)keysym_ret.ToInt32();
+
+ return ret;
+ }
+
+ [DllImport ("libX11", EntryPoint="XLookupKeysym")]
+ private static extern IntPtr XLookupKeysymX11(ref XEvent xevent, int index);
+ private static XKeySym XLookupKeysym(ref XEvent xevent, int index) {
+ return (XKeySym)XLookupKeysymX11(ref xevent, index).ToInt32();
+ }
+
+ [DllImport ("libX11")]
+ private static extern IntPtr XGetKeyboardMapping (IntPtr display, byte first_keycode, int keycode_count,
+ out int keysyms_per_keycode_return);
+
+ [DllImport ("libX11")]
+ private static extern void XDisplayKeycodes (IntPtr display, out int min, out int max);
+
+ [DllImport ("libX11", EntryPoint="XKeycodeToKeysym")]
+ private static extern IntPtr XKeycodeToKeysymX11(IntPtr display, int keycode, int index);
+ private static XKeySym XKeycodeToKeysym(IntPtr display, int keycode, int index) {
+ return (XKeySym)XKeycodeToKeysymX11(display, keycode, index).ToInt32();
+ }
+
+ [DllImport ("libX11")]
+ private static extern int XKeysymToKeycode (IntPtr display, IntPtr keysym);
+ private static int XKeysymToKeycode (IntPtr display, int keysym) {
+ return XKeysymToKeycode(display, (IntPtr)keysym);
+ }
+
+ [DllImport ("libX11")]
+ internal extern static IntPtr XGetModifierMapping (IntPtr display);
+
+ [DllImport ("libX11")]
+ internal extern static int XFreeModifiermap (IntPtr modmap);
+
+ }
+
+}
+