private void CreateConversionArray (KeyboardLayouts layouts, KeyboardLayout layout) { XEvent e2 = new XEvent (); uint keysym = 0; int [] ckey = new int [] { 0, 0, 0, 0 }; e2.KeyEvent.display = display; e2.KeyEvent.state = 0; for (int keyc = min_keycode; keyc <= max_keycode; keyc++) { int vkey = 0; int scan = 0; e2.KeyEvent.keycode = keyc; XKeySym t; XLookupStatus status; LookupString (ref e2, 0, out t, out status); keysym = (uint) t; if (keysym != 0) { if ((keysym >> 8) == 0xFF) { vkey = nonchar_key_vkey [keysym & 0xFF]; scan = 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;; for (int i = 0; i < syms; i++) { keysym = XKeycodeToKeysym (display, keyc, i); if ((keysym < 0x800) && (keysym != ' ')) ckey [i] = (sbyte) (keysym & 0xFF); else ckey [i] = (sbyte) MapDeadKeySym ((int) keysym); } for (int keyn = 0; keyn < layout.Keys.Length; keyn++) { int ml = Math.Min (layout.Keys [keyn].Length, 4); int ok = -1; for (int i = 0; (ok != 0) && (i < ml); i++) { sbyte ck = (sbyte) layout.Keys [keyn][i]; if (ck != ckey [i]) ok = 0; if ((ok != 0) || (i > maxlen)) { maxlen = i; maxval = keyn; } if (ok != 0) break; } } if (maxval >= 0) { if (maxval < layouts.scan_table [(int) layout.ScanIndex].Length) scan = layouts.scan_table [(int) layout.ScanIndex][maxval]; if (maxval < layouts.vkey_table [(int) layout.VKeyIndex].Length) vkey = layouts.vkey_table [(int) layout.VKeyIndex][maxval]; } } } keyc2vkey [e2.KeyEvent.keycode] = vkey; keyc2scan [e2.KeyEvent.keycode] = scan; } }
private KeyboardLayout DetectLayout (KeyboardLayouts layouts) { XDisplayKeycodes (display, out min_keycode, out max_keycode); IntPtr ksp = XGetKeyboardMapping (display, (byte) min_keycode, max_keycode + 1 - min_keycode, out keysyms_per_keycode); lock (XlibLock) { 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 layouts.Layouts) { int ok = 0; int score = 0; int match = 0; int mismatch = 0; int seq = 0; int pkey = -1; int key = min_keycode; int i; for (int keyc = min_keycode; keyc <= max_keycode; keyc++) { for (i = 0; i < syms; i++) { uint keysym = XKeycodeToKeysym (display, keyc, i); if ((keysym < 0x800) && (keysym != ' ')) { ckey [i] = (sbyte) (keysym & 0xFF); } else { ckey [i] = (sbyte) MapDeadKeySym ((int) keysym); } } if (ckey [0] != 0) { for (key = 0; key < current.Keys.Length; key++) { int ml = Math.Min (syms, current.Keys [key].Length); for (ok = 0, i = 0; (ok >= 0) && (i < ml); i++) { sbyte ck = (sbyte) current.Keys [key][i]; if (ck != 0 && ck == ckey[i]) ok++; if (ck != 0 && ck != ckey[i]) ok = -1; } if (ok > 0) { score += ok; break; } } if (ok > 0) { match++; /* and how much the keycode order matches */ if (key > pkey) seq++; pkey = key; } else { /* print spaces instead of \0's */ mismatch++; 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) { return layout; } else { Console.WriteLine (Locale.GetText("Keyboard layout not recognized, using default layout: " + layouts.Layouts [0].Name)); } return layouts.Layouts [0]; }
public void EnsureLayoutInitialized () { if (initialized) return; KeyboardLayouts layouts = new KeyboardLayouts (); KeyboardLayout layout = DetectLayout (layouts); lcid = layout.Lcid; CreateConversionArray (layouts, layout); SetupXIM (); initialized = true; }