author | Fred Lee <PhaethonH@gmail.com> |
Wed, 29 Jun 2011 08:32:07 -0700 | |
changeset 0 | 5bc1cc448eb5 |
child 1 | 83b6104a256b |
layouts.py | file | annotate | diff | comparison | revisions | |
main.py | file | annotate | diff | comparison | revisions | |
predefs.py | file | annotate | diff | comparison | revisions |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/layouts.py Wed Jun 29 08:32:07 2011 -0700 @@ -0,0 +1,1787 @@ + +# encoding=utf8 + +keyboard = { } + + +ATTR_SHIFTER = 0x0001 + + +keyboard['en/US 101'] = [ + [ + [ 142, 0, None, None ], + ], + + # Row 1 + [ + # width, height, keysym (app-specific), keytop (displayed), flags + [ 6, 1, "esc", "Esc" ], + [ 5, 1, "", "" ], + [ 6, 1, "function-1", "F1" ], + [ 6, 1, "function-2", "F2" ], + [ 6, 1, "function-3", "F3" ], + [ 6, 1, "function-4", "F4" ], + [ 3, 1, "", "" ], + [ 6, 1, "function-5", "F5" ], + [ 6, 1, "function-6", "F6" ], + [ 6, 1, "function-7", "F7" ], + [ 6, 1, "function-8", "F8" ], + [ 3, 1, "", "" ], + [ 6, 1, "function-9", "F9" ], + [ 6, 1, "function-10", "F10" ], + [ 6, 1, "function-11", "F11" ], + [ 6, 1, "function-12", "F12" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "print", "Print" ], + [ 6, 1, "scroll", "Scroll" ], + [ 6, 1, "pause", "Pause" ], + ], + + # Row spacing. + [ ], + + # Row 2 + [ + # width, height, keysym, keytop, flags + [ 6, 1, "`", "`" ], + [ 6, 1, "1", "1" ], + [ 6, 1, "2", "2" ], + [ 6, 1, "3", "3" ], + [ 6, 1, "4", "4" ], + [ 6, 1, "5", "5" ], + [ 6, 1, "6", "6" ], + [ 6, 1, "7", "7" ], + [ 6, 1, "8", "8" ], + [ 6, 1, "9", "9" ], + [ 6, 1, "0", "0" ], + [ 6, 1, "-", "-" ], + [ 6, 1, "=", "=" ], + [ 6, 1, "\\", "\\" ], + [ 6, 1, "backspace", "BS" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "cursor-insert", "Ins" ], + [ 6, 1, "cursor-home", "Home" ], + [ 6, 1, "cursor-pagedown", "PgUp" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "numlock", "NL" ], + [ 6, 1, "keypad-divide", "/" ], + [ 6, 1, "keypad-multiply", "*" ], + [ 6, 1, "keypad-minus", "-" ], + ], + + # Row 3 + [ + [ 9, 1, "tab", "Tab" ], + [ 6, 1, "q", "Q" ], + [ 6, 1, "w", "W" ], + [ 6, 1, "e", "E" ], + [ 6, 1, "r", "R" ], + [ 6, 1, "t", "T" ], + [ 6, 1, "y", "Y" ], + [ 6, 1, "u", "U" ], + [ 6, 1, "i", "I" ], + [ 6, 1, "o", "O" ], + [ 6, 1, "p", "P" ], + [ 6, 1, "[", "[" ], + [ 6, 1, "]", "]" ], + [ 9, 1, "\\", "\\" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "cursor-delete", "Del" ], + [ 6, 1, "cursor-end", "End" ], + [ 6, 1, "cursor-pagedown", "PgDn" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "keypad-7", "7" ], + [ 6, 1, "keypad-8", "8" ], + [ 6, 1, "keypad-9", "9" ], + [ 6, 2, "keypad-plus", "+" ], + ], + + # Row 4 + [ + [ 11, 1, "", "Caps" ], + [ 6, 1, "a", "A" ], + [ 6, 1, "s", "S" ], + [ 6, 1, "d", "D" ], + [ 6, 1, "f", "F" ], + [ 6, 1, "g", "G" ], + [ 6, 1, "h", "H" ], + [ 6, 1, "j", "J" ], + [ 6, 1, "k", "K" ], + [ 6, 1, "l", "L" ], + [ 6, 1, ";", ";" ], + [ 6, 1, "'", "'" ], + [ 13, 1, "return", "Enter" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "", "" ], + [ 6, 1, "", "" ], + [ 6, 1, "", "" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "keypad-4", "4" ], + [ 6, 1, "keypad-5", "5" ], + [ 6, 1, "keypad-6", "6" ], + ], + + # Row 5 + [ + [ 13, 1, "shift", "Shift" ], + [ 6, 1, "z", "Z" ], + [ 6, 1, "x", "X" ], + [ 6, 1, "c", "C" ], + [ 6, 1, "v", "V" ], + [ 6, 1, "b", "B" ], + [ 6, 1, "n", "N" ], + [ 6, 1, "m", "M" ], + [ 6, 1, ",", "," ], + [ 6, 1, ".", "." ], + [ 6, 1, "/", "/" ], + [ 17, 1, "shift", "Shift" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "", "" ], + [ 6, 1, "cursor-up", "Up" ], + [ 6, 1, "", "" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "keypad-1", "1" ], + [ 6, 1, "keypad-2", "2" ], + [ 6, 1, "keypad-3", "3" ], + [ 6, 2, "keypad-enter", "RET" ], + ], + + # Row 6 + [ + [ 8, 1, "ctrl", "Ctrl" ], + [ 7, 1, "", "" ], + [ 8, 1, "alt", "Alt" ], + [ 44, 1, "space", "Space" ], + [ 8, 1, "alt", "Alt" ], + [ 7, 1, "", "" ], + [ 8, 1, "ctrl", "Ctrl" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "cursor-left", "Left" ], + [ 6, 1, "cursor-down", "Down" ], + [ 6, 1, "cursor-right", "Right" ], + + [ 3, 1, "", "" ], + + [ 12, 1, "keypad-0", "0" ], + [ 6, 1, "keypad-.", "." ], + ] +] + + +keyboard['en/US 104'] = [ + [ + [ 142, 0, None, None ], + ], + + # Row 1 + [ + # width, height, keysym (app-specific), keytop (displayed), flags + [ 6, 1, "esc", "Esc" ], + [ 4, 1, "", "" ], + [ 6, 1, "function-1", "F1" ], + [ 6, 1, "function-2", "F2" ], + [ 6, 1, "function-3", "F3" ], + [ 6, 1, "function-4", "F4" ], + [ 4, 1, "", "" ], + [ 6, 1, "function-5", "F5" ], + [ 6, 1, "function-6", "F6" ], + [ 6, 1, "function-7", "F7" ], + [ 6, 1, "function-8", "F8" ], + [ 4, 1, "", "" ], + [ 6, 1, "function-9", "F9" ], + [ 6, 1, "function-10", "F10" ], + [ 6, 1, "function-11", "F11" ], + [ 6, 1, "function-12", "F12" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "print", "Print" ], + [ 6, 1, "scroll", "Scroll" ], + [ 6, 1, "pause", "Pause" ], + ], + + # Row spacing. + [ ], + + # Row 2 + [ + # width, height, keysym, keytop, flags + [ 6, 1, "`", "`" ], + [ 6, 1, "1", "1" ], + [ 6, 1, "2", "2" ], + [ 6, 1, "3", "3" ], + [ 6, 1, "4", "4" ], + [ 6, 1, "5", "5" ], + [ 6, 1, "6", "6" ], + [ 6, 1, "7", "7" ], + [ 6, 1, "8", "8" ], + [ 6, 1, "9", "9" ], + [ 6, 1, "0", "0" ], + [ 6, 1, "-", "-" ], + [ 6, 1, "=", "=" ], + [ 6, 1, "\\", "\\" ], + [ 6, 1, "backspace", "BS" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "cursor-insert", "Ins" ], + [ 6, 1, "cursor-home", "Home" ], + [ 6, 1, "cursor-pagedown", "PgUp" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "numlock", "NL" ], + [ 6, 1, "keypad-divide", "/" ], + [ 6, 1, "keypad-multiply", "*" ], + [ 6, 1, "keypad-minus", "-" ], + ], + + # Row 3 + [ + [ 9, 1, "tab", "Tab" ], + [ 6, 1, "q", "Q" ], + [ 6, 1, "w", "W" ], + [ 6, 1, "e", "E" ], + [ 6, 1, "r", "R" ], + [ 6, 1, "t", "T" ], + [ 6, 1, "y", "Y" ], + [ 6, 1, "u", "U" ], + [ 6, 1, "i", "I" ], + [ 6, 1, "o", "O" ], + [ 6, 1, "p", "P" ], + [ 6, 1, "[", "[" ], + [ 6, 1, "]", "]" ], + [ 9, 1, "\\", "\\" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "cursor-delete", "Del" ], + [ 6, 1, "cursor-end", "End" ], + [ 6, 1, "cursor-pagedown", "PgDn" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "keypad-7", "7" ], + [ 6, 1, "keypad-8", "8" ], + [ 6, 1, "keypad-9", "9" ], + [ 6, 2, "keypad-plus", "+" ], + ], + + # Row 4 + [ + [ 11, 1, "", "Caps" ], + [ 6, 1, "a", "A" ], + [ 6, 1, "s", "S" ], + [ 6, 1, "d", "D" ], + [ 6, 1, "f", "F" ], + [ 6, 1, "g", "G" ], + [ 6, 1, "h", "H" ], + [ 6, 1, "j", "J" ], + [ 6, 1, "k", "K" ], + [ 6, 1, "l", "L" ], + [ 6, 1, ";", ";" ], + [ 6, 1, "'", "'" ], + [ 13, 1, "return", "Enter" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "", "" ], + [ 6, 1, "", "" ], + [ 6, 1, "", "" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "keypad-4", "4" ], + [ 6, 1, "keypad-5", "5" ], + [ 6, 1, "keypad-6", "6" ], + ], + + # Row 5 + [ + [ 13, 1, "shift", "Shift" ], + [ 6, 1, "z", "Z" ], + [ 6, 1, "x", "X" ], + [ 6, 1, "c", "C" ], + [ 6, 1, "v", "V" ], + [ 6, 1, "b", "B" ], + [ 6, 1, "n", "N" ], + [ 6, 1, "m", "M" ], + [ 6, 1, ",", "," ], + [ 6, 1, ".", "." ], + [ 6, 1, "/", "/" ], + [ 17, 1, "shift", "Shift" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "", "" ], + [ 6, 1, "cursor-up", "Up" ], + [ 6, 1, "", "" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "keypad-1", "1" ], + [ 6, 1, "keypad-2", "2" ], + [ 6, 1, "keypad-3", "3" ], + [ 6, 2, "keypad-enter", "RET" ], + ], + + # Row 6 + [ + [ 8, 1, "ctrl", "Ctrl" ], + [ 7, 1, "logo", "Logo" ], + [ 8, 1, "alt", "Alt" ], + [ 37, 1, "space", "Space" ], + [ 8, 1, "alt", "Alt" ], + [ 7, 1, "logo", "Logo" ], + [ 7, 1, "menu", "Menu" ], + [ 8, 1, "ctrl", "Ctrl" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "cursor-left", "Left" ], + [ 6, 1, "cursor-down", "Down" ], + [ 6, 1, "cursor-right", "Right" ], + + [ 3, 1, "", "" ], + + [ 12, 1, "keypad-0", "0" ], + [ 6, 1, "keypad-.", "." ], + ] +] + + + +keyboard['en/US-dvorak 104'] = [ + [ + [ 142, 0, None, None ], + ], + + # Row 1 + [ + # width, height, keysym (app-specific), keytop (displayed), flags + [ 6, 1, "esc", "Esc" ], + [ 5, 1, "", "" ], + [ 6, 1, "function-1", "F1" ], + [ 6, 1, "function-2", "F2" ], + [ 6, 1, "function-3", "F3" ], + [ 6, 1, "function-4", "F4" ], + [ 3, 1, "", "" ], + [ 6, 1, "function-5", "F5" ], + [ 6, 1, "function-6", "F6" ], + [ 6, 1, "function-7", "F7" ], + [ 6, 1, "function-8", "F8" ], + [ 3, 1, "", "" ], + [ 6, 1, "function-9", "F9" ], + [ 6, 1, "function-10", "F10" ], + [ 6, 1, "function-11", "F11" ], + [ 6, 1, "function-12", "F12" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "print", "Print" ], + [ 6, 1, "scroll", "Scroll" ], + [ 6, 1, "pause", "Pause" ], + ], + + # Row spacing. + [ ], + + # Row 2 + [ + # width, height, keysym, keytop, flags + [ 6, 1, "`", "`" ], + [ 6, 1, "1", "1" ], + [ 6, 1, "2", "2" ], + [ 6, 1, "3", "3" ], + [ 6, 1, "4", "4" ], + [ 6, 1, "5", "5" ], + [ 6, 1, "6", "6" ], + [ 6, 1, "7", "7" ], + [ 6, 1, "8", "8" ], + [ 6, 1, "9", "9" ], + [ 6, 1, "0", "0" ], + [ 6, 1, "[", "[" ], + [ 6, 1, "]", "]" ], + [ 12, 1, "backspace", "BS" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "cursor-insert", "Ins" ], + [ 6, 1, "cursor-home", "Home" ], + [ 6, 1, "cursor-pagedown", "PgUp" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "numlock", "NL" ], + [ 6, 1, "keypad-divide", "/" ], + [ 6, 1, "keypad-multiply", "*" ], + [ 6, 1, "keypad-minus", "-" ], + ], + + # Row 3 + [ + [ 9, 1, "tab", "Tab" ], + [ 6, 1, "'", "'" ], + [ 6, 1, ",", "," ], + [ 6, 1, ".", "." ], + [ 6, 1, "p", "P" ], + [ 6, 1, "y", "Y" ], + [ 6, 1, "f", "F" ], + [ 6, 1, "g", "G" ], + [ 6, 1, "c", "C" ], + [ 6, 1, "r", "R" ], + [ 6, 1, "l", "L" ], + [ 6, 1, "/", "/" ], + [ 6, 1, "=", "=" ], + [ 9, 1, "\\", "\\" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "cursor-delete", "Del" ], + [ 6, 1, "cursor-end", "End" ], + [ 6, 1, "cursor-pagedown", "PgDn" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "keypad-7", "7" ], + [ 6, 1, "keypad-8", "8" ], + [ 6, 1, "keypad-9", "9" ], + [ 6, 2, "keypad-plus", "+" ], + ], + + # Row 4 + [ + [ 11, 1, "", "Caps" ], + [ 6, 1, "a", "A" ], + [ 6, 1, "o", "O" ], + [ 6, 1, "e", "E" ], + [ 6, 1, "u", "U" ], + [ 6, 1, "i", "I" ], + [ 6, 1, "d", "D" ], + [ 6, 1, "h", "H" ], + [ 6, 1, "t", "T" ], + [ 6, 1, "n", "N" ], + [ 6, 1, "s", "S" ], + [ 6, 1, "-", "-" ], + [ 13, 1, "return", "Enter" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "", "" ], + [ 6, 1, "", "" ], + [ 6, 1, "", "" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "keypad-4", "4" ], + [ 6, 1, "keypad-5", "5" ], + [ 6, 1, "keypad-6", "6" ], + ], + + # Row 5 + [ + [ 13, 1, "shift", "Shift" ], + [ 6, 1, ";", ";" ], + [ 6, 1, "q", "Q" ], + [ 6, 1, "j", "J" ], + [ 6, 1, "k", "K" ], + [ 6, 1, "x", "X" ], + [ 6, 1, "b", "B" ], + [ 6, 1, "m", "M" ], + [ 6, 1, "w", "W" ], + [ 6, 1, "v", "V" ], + [ 6, 1, "z", "Z" ], + [ 17, 1, "shift", "Shift" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "", "" ], + [ 6, 1, "cursor-up", "Up" ], + [ 6, 1, "", "" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "keypad-1", "1" ], + [ 6, 1, "keypad-2", "2" ], + [ 6, 1, "keypad-3", "3" ], + [ 6, 2, "keypad-enter", "RET" ], + ], + + # Row 6 + [ + [ 8, 1, "ctrl", "Ctrl" ], + [ 7, 1, "logo", "Logo" ], + [ 8, 1, "alt", "Alt" ], + [ 37, 1, "space", "Space" ], + [ 8, 1, "alt", "Alt" ], + [ 7, 1, "logo", "Logo" ], + [ 7, 1, "menu", "Menu" ], + [ 8, 1, "ctrl", "Ctrl" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "cursor-left", "Left" ], + [ 6, 1, "cursor-down", "Down" ], + [ 6, 1, "cursor-right", "Right" ], + + [ 3, 1, "", "" ], + + [ 12, 1, "keypad-0", "0" ], + [ 6, 1, "keypad-.", "." ], + ] +] + + + +keyboard['en/US AppleProAlFull' ] = [ + [ + [ 142, 0, None, None ], + ], + + # Row 1 + [ + # width, height, keysym (app-specific), keytop (displayed), flags + [ 6, 1, "esc", "Esc" ], + [ 7, 1, "function-1", "F1" ], + [ 6, 1, "function-2", "F2" ], + [ 6, 1, "function-3", "F3" ], + [ 6, 1, "function-4", "F4" ], + [ 6, 1, "function-5", "F5" ], + [ 6, 1, "function-6", "F6" ], + [ 6, 1, "function-7", "F7" ], + [ 6, 1, "function-8", "F8" ], + [ 7, 1, "function-9", "F9" ], + [ 6, 1, "function-10", "F10" ], + [ 6, 1, "function-11", "F11" ], + [ 6, 1, "function-12", "F12" ], + [ 6, 1, "eject", "eject" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "function-13", "F13" ], + [ 6, 1, "function-14", "F14" ], + [ 6, 1, "function-15", "F15" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "function-16", "F16" ], + [ 6, 1, "function-17", "F17" ], + [ 6, 1, "function-18", "F18" ], + [ 6, 1, "function-19", "F19" ], + ], + + # Row 2 + [ + # width, height, keysym, keytop, flags + [ 6, 1, "`", "`" ], + [ 6, 1, "1", "1" ], + [ 6, 1, "2", "2" ], + [ 6, 1, "3", "3" ], + [ 6, 1, "4", "4" ], + [ 6, 1, "5", "5" ], + [ 6, 1, "6", "6" ], + [ 6, 1, "7", "7" ], + [ 6, 1, "8", "8" ], + [ 6, 1, "9", "9" ], + [ 6, 1, "0", "0" ], + [ 6, 1, "-", "-" ], + [ 6, 1, "=", "=" ], + [ 8, 1, "backspace", "BS" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "", "Fn" ], + [ 6, 1, "cursor-home", "Home" ], + [ 6, 1, "cursor-pagedown", "PgUp" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "keypad-clear", "clear" ], + [ 6, 1, "keypad-equal", "=" ], + [ 6, 1, "keypad-divide", "/" ], + [ 6, 1, "keypad-multiply", "*" ], +# [ 6, 1, "keypad-minus", "-" ], + ], + + # Row 3 + [ + [ 9, 1, "tab", "Tab" ], + [ 6, 1, "q", "Q" ], + [ 6, 1, "w", "W" ], + [ 6, 1, "e", "E" ], + [ 6, 1, "r", "R" ], + [ 6, 1, "t", "T" ], + [ 6, 1, "y", "Y" ], + [ 6, 1, "u", "U" ], + [ 6, 1, "i", "I" ], + [ 6, 1, "o", "O" ], + [ 6, 1, "p", "P" ], + [ 6, 1, "[", "[" ], + [ 6, 1, "]", "]" ], + [ 5, 1, "\\", "\\" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "cursor-delete", "Del" ], + [ 6, 1, "cursor-end", "End" ], + [ 6, 1, "cursor-pagedown", "PgDn" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "keypad-7", "7" ], + [ 6, 1, "keypad-8", "8" ], + [ 6, 1, "keypad-9", "9" ], +# [ 6, 2, "keypad-plus", "+" ], + [ 6, 1, "keypad-plus", "-" ], + ], + + # Row 4 + [ + [ 11, 1, "", "Caps" ], + [ 6, 1, "a", "A" ], + [ 6, 1, "s", "S" ], + [ 6, 1, "d", "D" ], + [ 6, 1, "f", "F" ], + [ 6, 1, "g", "G" ], + [ 6, 1, "h", "H" ], + [ 6, 1, "j", "J" ], + [ 6, 1, "k", "K" ], + [ 6, 1, "l", "L" ], + [ 6, 1, ";", ";" ], + [ 6, 1, "'", "'" ], + [ 9, 1, "return", "Return" ], + [ 6, 1, "cursor-insert", "Ins" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "", "" ], + [ 6, 1, "", "" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "keypad-4", "4" ], + [ 6, 1, "keypad-5", "5" ], + [ 6, 1, "keypad-6", "6" ], + [ 6, 1, "keypad-add", "+" ], + ], + + # Row 5 + [ + [ 13, 1, "shift", "Shift" ], + [ 6, 1, "z", "Z" ], + [ 6, 1, "x", "X" ], + [ 6, 1, "c", "C" ], + [ 6, 1, "v", "V" ], + [ 6, 1, "b", "B" ], + [ 6, 1, "n", "N" ], + [ 6, 1, "m", "M" ], + [ 6, 1, ",", "," ], + [ 6, 1, ".", "." ], + [ 6, 1, "/", "/" ], + [ 13, 1, "shift", "Shift" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "", "" ], + [ 6, 1, "cursor-up", "Up" ], + [ 6, 1, "", "" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "keypad-1", "1" ], + [ 6, 1, "keypad-2", "2" ], + [ 6, 1, "keypad-3", "3" ], + [ 6, 2, "keypad-enter", "ENT" ], + ], + + # Row 6 + [ + [ 9, 1, "ctrl", "Ctrl" ], + [ 7, 1, "alt", "Opt" ], + [ 9, 1, "command", "Cmd" ], + [ 36, 1, "space", "Space" ], + [ 9, 1, "command", "Cmd" ], + [ 7, 1, "alt", "Opt" ], + [ 9, 1, "ctrl", "Ctrl" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "cursor-left", "Left" ], + [ 6, 1, "cursor-down", "Down" ], + [ 6, 1, "cursor-right", "Right" ], + + [ 3, 1, "", "" ], + + [ 12, 1, "keypad-0", "0" ], + [ 6, 1, "keypad-.", "." ], + ] +] + + + +keyboard['en/US HappyHacking' ] = [ + [ + [ 142, 0, None, None ], + ], + + # Row 1 + [ + # width, height, keysym (app-specific), keytop (displayed), flags + [ 6, 1, "esc", "Esc" ], + [ 6, 1, "1", "1" ], + [ 6, 1, "2", "2" ], + [ 6, 1, "3", "3" ], + [ 6, 1, "4", "4" ], + [ 6, 1, "5", "5" ], + [ 6, 1, "6", "6" ], + [ 6, 1, "7", "7" ], + [ 6, 1, "8", "8" ], + [ 6, 1, "9", "9" ], + [ 6, 1, "0", "0" ], + [ 6, 1, "-", "-" ], + [ 6, 1, "=", "=" ], + [ 6, 1, "\\", "\\" ], + [ 6, 1, "`", "`" ], + ], + + # Row 3 + [ + [ 9, 1, "tab", "Tab" ], + [ 6, 1, "q", "Q" ], + [ 6, 1, "w", "W" ], + [ 6, 1, "e", "E" ], + [ 6, 1, "r", "R" ], + [ 6, 1, "t", "T" ], + [ 6, 1, "y", "Y" ], + [ 6, 1, "u", "U" ], + [ 6, 1, "i", "I" ], + [ 6, 1, "o", "O" ], + [ 6, 1, "p", "P" ], + [ 6, 1, "[", "[" ], + [ 6, 1, "]", "]" ], + [ 9, 1, "cursor-delete", "Delete" ], + ], + + # Row 4 + [ + [ 11, 1, "ctrl", "Control" ], + [ 6, 1, "a", "A" ], + [ 6, 1, "s", "S" ], + [ 6, 1, "d", "D" ], + [ 6, 1, "f", "F" ], + [ 6, 1, "g", "G" ], + [ 6, 1, "h", "H" ], + [ 6, 1, "j", "J" ], + [ 6, 1, "k", "K" ], + [ 6, 1, "l", "L" ], + [ 6, 1, ";", ";" ], + [ 6, 1, "'", "'" ], + [ 13, 1, "return", "Return" ], + ], + + # Row 5 + [ + [ 13, 1, "shift", "Shift" ], + [ 6, 1, "z", "Z" ], + [ 6, 1, "x", "X" ], + [ 6, 1, "c", "C" ], + [ 6, 1, "v", "V" ], + [ 6, 1, "b", "B" ], + [ 6, 1, "n", "N" ], + [ 6, 1, "m", "M" ], + [ 6, 1, ",", "," ], + [ 6, 1, ".", "." ], + [ 6, 1, "/", "/" ], + [ 11, 1, "shift", "Shift" ], + [ 6, 1, "", "Fn" ], + ], + + # Row 6 + [ + [ 9, 1, "", "" ], + [ 7, 1, "alt", "Alt" ], + [ 9, 1, "meta", "Meta" ], + [ 34, 1, "space", "Space" ], + [ 9, 1, "meta", "Meta" ], + [ 7, 1, "alt", "Alt" ], + [ 9, 1, "", "" ], + ] +] + + +keyboard['en/US HappyHackingPro2' ] = [ + [ + [ 142, 0, None, None ], + ], + + # Row 1 + [ + # width, height, keysym (app-specific), keytop (displayed), flags + [ 6, 1, "esc", " " ], + [ 6, 1, "1", " " ], + [ 6, 1, "2", " " ], + [ 6, 1, "3", " " ], + [ 6, 1, "4", " " ], + [ 6, 1, "5", " " ], + [ 6, 1, "6", " " ], + [ 6, 1, "7", " " ], + [ 6, 1, "8", " " ], + [ 6, 1, "9", " " ], + [ 6, 1, "0", " " ], + [ 6, 1, "-", " " ], + [ 6, 1, "=", " " ], + [ 6, 1, "\\", " " ], + [ 6, 1, "`", " " ], + ], + + # Row 3 + [ + [ 9, 1, "tab", " " ], + [ 6, 1, "q", " " ], + [ 6, 1, "w", " " ], + [ 6, 1, "e", " " ], + [ 6, 1, "r", " " ], + [ 6, 1, "t", " " ], + [ 6, 1, "y", " " ], + [ 6, 1, "u", " " ], + [ 6, 1, "i", " " ], + [ 6, 1, "o", " " ], + [ 6, 1, "p", " " ], + [ 6, 1, "[", " " ], + [ 6, 1, "]", " " ], + [ 9, 1, "cursor-delete", " " ], + ], + + # Row 4 + [ + [ 11, 1, "ctrl", " " ], + [ 6, 1, "a", " " ], + [ 6, 1, "s", " " ], + [ 6, 1, "d", " " ], + [ 6, 1, "f", " " ], + [ 6, 1, "g", " " ], + [ 6, 1, "h", " " ], + [ 6, 1, "j", " " ], + [ 6, 1, "k", " " ], + [ 6, 1, "l", " " ], + [ 6, 1, ";", " " ], + [ 6, 1, "'", " " ], + [ 13, 1, "return", " " ], + ], + + # Row 5 + [ + [ 13, 1, "shift", " " ], + [ 6, 1, "z", " " ], + [ 6, 1, "x", " " ], + [ 6, 1, "c", " " ], + [ 6, 1, "v", " " ], + [ 6, 1, "b", " " ], + [ 6, 1, "n", " " ], + [ 6, 1, "m", " " ], + [ 6, 1, ",", " " ], + [ 6, 1, ".", " " ], + [ 6, 1, "/", " " ], + [ 11, 1, "shift", " " ], + [ 6, 1, "", " " ], + ], + + # Row 6 + [ + [ 9, 1, "", "" ], + [ 7, 1, "alt", " " ], + [ 9, 1, "meta", " " ], + [ 34, 1, "space", " " ], + [ 9, 1, "meta", " " ], + [ 7, 1, "alt", " " ], + [ 9, 1, "", "" ], + ] +] + + + +keyboard['en/US HappyHackingLite2' ] = [ + [ + [ 142, 0, None, None ], + ], + + # Row 1 + [ + # width, height, keysym (app-specific), keytop (displayed), flags + [ 92, 1, "", "" ], + [ 1, 1, "", "" ], + [ 6, 1, "function-1", "F1" ], + [ 6, 1, "function-2", "F2" ], + [ 6, 1, "function-3", "F3" ], + [ 6, 1, "function-4", "F4" ], + [ 6, 1, "function-5", "F5" ], + [ 6, 1, "function-6", "F6" ], + [ 6, 1, "function-7", "F7" ], + ], + + # Row 2 + [ + # width, height, keysym (app-specific), keytop (displayed), flags + [ 6, 1, "esc", "Esc" ], + [ 6, 1, "1", "1" ], + [ 6, 1, "2", "2" ], + [ 6, 1, "3", "3" ], + [ 6, 1, "4", "4" ], + [ 6, 1, "5", "5" ], + [ 6, 1, "6", "6" ], + [ 6, 1, "7", "7" ], + [ 6, 1, "8", "8" ], + [ 6, 1, "9", "9" ], + [ 6, 1, "0", "0" ], + [ 6, 1, "-", "-" ], + [ 6, 1, "=", "=" ], + [ 6, 1, "\\", "\\" ], + [ 6, 1, "`", "`" ], + + [ 3, 1, "", "" ], + [ 2, 1, "", "" ], + [ 6, 1, "function-8", "F8" ], + [ 6, 1, "function-9", "F9" ], + [ 6, 1, "function-10", "F10" ], + [ 6, 1, "function-11", "F11" ], + [ 6, 1, "function-12", "F12" ], + [ 6, 1, "cursor-insert", "Ins" ], + [ 6, 1, "cursor-delete", "Del" ], + ], + + # Row 3 + [ + [ 9, 1, "tab", "Tab" ], + [ 6, 1, "q", "Q" ], + [ 6, 1, "w", "W" ], + [ 6, 1, "e", "E" ], + [ 6, 1, "r", "R" ], + [ 6, 1, "t", "T" ], + [ 6, 1, "y", "Y" ], + [ 6, 1, "u", "U" ], + [ 6, 1, "i", "I" ], + [ 6, 1, "o", "O" ], + [ 6, 1, "p", "P" ], + [ 6, 1, "[", "[" ], + [ 6, 1, "]", "]" ], + [ 9, 1, "cursor-delete", "Delete" ], + + [ 3, 1, "", "" ], + [ 5, 1, "", "U" ], + [ 6, 1, "print", "Print" ], + [ 6, 1, "scroll", "Scroll Lock" ], + [ 6, 1, "pause", "Pause" ], + [ 6, 1, "up", "Up" ], + [ 6, 1, "", "]" ], + [ 9, 1, "backspace", "BS" ], + ], + + # Row 4 + [ + [ 11, 1, "ctrl", "Control" ], + [ 6, 1, "a", "A" ], + [ 6, 1, "s", "S" ], + [ 6, 1, "d", "D" ], + [ 6, 1, "f", "F" ], + [ 6, 1, "g", "G" ], + [ 6, 1, "h", "H" ], + [ 6, 1, "j", "J" ], + [ 6, 1, "k", "K" ], + [ 6, 1, "l", "L" ], + [ 6, 1, ";", ";" ], + [ 6, 1, "'", "'" ], + [ 13, 1, "return", "Return" ], + + [ 3, 1, "", "" ], + [ 1, 1, "", "" ], + [ 6, 1, "", "J" ], + [ 6, 1, "cursor-home", "Home" ], + [ 6, 1, "cursor-pageup", "PgUp" ], + [ 6, 1, "cursor-left", "Left" ], + [ 6, 1, "cursor-right", "Right" ], + [ 13, 1, "", "Enter" ], + ], + + # Row 5 + [ + [ 13, 1, "shift", "Shift" ], + [ 6, 1, "z", "Z" ], + [ 6, 1, "x", "X" ], + [ 6, 1, "c", "C" ], + [ 6, 1, "v", "V" ], + [ 6, 1, "b", "B" ], + [ 6, 1, "n", "N" ], + [ 6, 1, "m", "M" ], + [ 6, 1, ",", "," ], + [ 6, 1, ".", "." ], + [ 6, 1, "/", "/" ], + [ 11, 1, "shift", "Shift" ], + [ 6, 1, "", "Fn" ], + + [ 3, 1, "", "" ], + [ 3, 1, "", "" ], + [ 6, 1, "", "M" ], + [ 6, 1, "cursor-end", "End" ], + [ 6, 1, "cursor-pagedown", "PgDn" ], + [ 6, 1, "cursor-down", "Down" ], + [ 11, 1, "", "Shift" ], + [ 6, 1, "", "Fn" ], + ], + + # Row 6 + [ + [ 6, 1, "", "" ], + [ 6, 1, "", "Fn" ], + [ 6, 1, "alt", "Alt" ], + [ 6, 1, "meta", "Meta" ], + [ 35, 1, "space", "Space" ], + [ 6, 1, "meta", "Meta" ], + [ 6, 1, "alt", "Alt" ], + [ 2, 1, "", "" ], + [ 6, 1, "", "" ], + [ 5, 1, "cursor-up", "Up" ], + [ 6, 1, "", "" ], + + [ 3, 1, "", "" ], + [ 13, 1, "", "Space" ], + [ 6, 1, "logo", "Win" ], + [ 6, 1, "", "Alt" ], + [ 2, 1, "", "" ], + [ 6, 1, "", "" ], + [ 5, 1, "cursor-pageup", "PgUp" ], + [ 6, 1, "", "" ], + ], + + # Row 6.5 + [ + [ 73, 1, "", "" ], + [ 6, 1, "cursor-left", "Left" ], + [ 5, 1, "cursor-down", "Down" ], + [ 6, 1, "cursor-right", "Right" ], + + [ 3, 1, "", "" ], + [ 27, 1, "", "" ], + [ 6, 1, "cursor-home", "Home" ], + [ 5, 1, "cursor-pagedown", "PgDn" ], + [ 6, 1, "cursor-end", "End" ], + ] +] + + + +keyboard['de/DE 104'] = [ + [ + [ 142, 0, None, None ], + ], + + # Row 1 + [ + # width, height, keysym (app-specific), keytop (displayed), flags + [ 6, 1, "esc", "Esc" ], + [ 5, 1, "", "" ], + [ 6, 1, "function-1", "F1" ], + [ 6, 1, "function-2", "F2" ], + [ 6, 1, "function-3", "F3" ], + [ 6, 1, "function-4", "F4" ], + [ 3, 1, "", "" ], + [ 6, 1, "function-5", "F5" ], + [ 6, 1, "function-6", "F6" ], + [ 6, 1, "function-7", "F7" ], + [ 6, 1, "function-8", "F8" ], + [ 3, 1, "", "" ], + [ 6, 1, "function-9", "F9" ], + [ 6, 1, "function-10", "F10" ], + [ 6, 1, "function-11", "F11" ], + [ 6, 1, "function-12", "F12" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "print", "Druck" ], + [ 6, 1, "scroll", "Rolln" ], + [ 6, 1, "pause", "Pause" ], + ], + + # Row spacing. + [ ], + + # Row 2 + [ + # width, height, keysym, keytop, flags + [ 6, 1, "^", "^" ], + [ 6, 1, "1", "1" ], + [ 6, 1, "2", "2" ], + [ 6, 1, "3", "3" ], + [ 6, 1, "4", "4" ], + [ 6, 1, "5", "5" ], + [ 6, 1, "6", "6" ], + [ 6, 1, "7", "7" ], + [ 6, 1, "8", "8" ], + [ 6, 1, "9", "9" ], + [ 6, 1, "0", "0" ], + [ 6, 1, "ß", "ß" ], + [ 6, 1, "acute", "´" ], + [ 12, 1, "backspace", "BS" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "cursor-insert", "Einfg" ], + [ 6, 1, "cursor-home", "Pos1" ], + [ 6, 1, "cursor-pagedown", "Bild↑" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "numlock", "NL" ], + [ 6, 1, "keypad-divide", "÷" ], + [ 6, 1, "keypad-multiply", "×" ], + [ 6, 1, "keypad-minus", "-" ], + ], + + # Row 3 + [ + [ 9, 1, "tab", "Tab" ], + [ 6, 1, "q", "Q" ], + [ 6, 1, "w", "W" ], + [ 6, 1, "e", "E" ], + [ 6, 1, "r", "R" ], + [ 6, 1, "t", "T" ], + [ 6, 1, "z", "Z" ], + [ 6, 1, "u", "U" ], + [ 6, 1, "i", "I" ], + [ 6, 1, "o", "O" ], + [ 6, 1, "p", "P" ], + [ 6, 1, "ü", "Ü" ], + [ 6, 1, "+", "+" ], + [ 9, 1, "return", "Enter" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "cursor-delete", "Entf" ], + [ 6, 1, "cursor-end", "Ende" ], + [ 6, 1, "cursor-pagedown", "Bild↓" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "keypad-7", "7" ], + [ 6, 1, "keypad-8", "8" ], + [ 6, 1, "keypad-9", "9" ], + [ 6, 2, "keypad-plus", "+" ], + ], + + # Row 4 + [ + [ 11, 1, "", "Caps" ], + [ 6, 1, "a", "A" ], + [ 6, 1, "s", "S" ], + [ 6, 1, "d", "D" ], + [ 6, 1, "f", "F" ], + [ 6, 1, "g", "G" ], + [ 6, 1, "h", "H" ], + [ 6, 1, "j", "J" ], + [ 6, 1, "k", "K" ], + [ 6, 1, "l", "L" ], + [ 6, 1, "ö", "Ö" ], + [ 6, 1, "ä", "Ä" ], + [ 6, 1, "#", "#" ], + [ 7, 1, "return", "Enter" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "", "" ], + [ 6, 1, "", "" ], + [ 6, 1, "", "" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "keypad-4", "4" ], + [ 6, 1, "keypad-5", "5" ], + [ 6, 1, "keypad-6", "6" ], + ], + + # Row 5 + [ + [ 7, 1, "shift", "Shift" ], + [ 6, 1, "less-than", "<" ], + [ 6, 1, "y", "Y" ], + [ 6, 1, "x", "X" ], + [ 6, 1, "c", "C" ], + [ 6, 1, "v", "V" ], + [ 6, 1, "b", "B" ], + [ 6, 1, "n", "N" ], + [ 6, 1, "m", "M" ], + [ 6, 1, ",", "," ], + [ 6, 1, ".", "." ], + [ 6, 1, "-", "-" ], + [ 11, 1, "shift", "Shift" ], + [ 6, 1, "", "♦" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "", "" ], + [ 6, 1, "cursor-up", "Up" ], + [ 6, 1, "", "" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "keypad-1", "1" ], + [ 6, 1, "keypad-2", "2" ], + [ 6, 1, "keypad-3", "3" ], + [ 6, 2, "keypad-enter", "RET" ], + ], + + # Row 6 + [ + [ 8, 1, "ctrl", "Strg" ], + [ 7, 1, "logo", "◊" ], + [ 8, 1, "alt", "Alt" ], + [ 44, 1, "space", "Space" ], + [ 8, 1, "altgr", "AltGr" ], + [ 7, 1, "logo", "Logo" ], + [ 8, 1, "ctrl", "Strg" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "cursor-left", "Left" ], + [ 6, 1, "cursor-down", "Down" ], + [ 6, 1, "cursor-right", "Right" ], + + [ 3, 1, "", "" ], + + [ 12, 1, "keypad-0", "0" ], + [ 6, 1, "keypad-.", "." ], + ] +] + + +keyboard['en/GB 104'] = [ + [ + [ 142, 0, None, None ], + ], + + # Row 1 + [ + # width, height, keysym (app-specific), keytop (displayed), flags + [ 6, 1, "esc", "Esc" ], + [ 5, 1, "", "" ], + [ 6, 1, "function-1", "F1" ], + [ 6, 1, "function-2", "F2" ], + [ 6, 1, "function-3", "F3" ], + [ 6, 1, "function-4", "F4" ], + [ 3, 1, "", "" ], + [ 6, 1, "function-5", "F5" ], + [ 6, 1, "function-6", "F6" ], + [ 6, 1, "function-7", "F7" ], + [ 6, 1, "function-8", "F8" ], + [ 3, 1, "", "" ], + [ 6, 1, "function-9", "F9" ], + [ 6, 1, "function-10", "F10" ], + [ 6, 1, "function-11", "F11" ], + [ 6, 1, "function-12", "F12" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "print", "Print" ], + [ 6, 1, "scroll", "Scroll" ], + [ 6, 1, "pause", "Pause" ], + ], + + # Row spacing. + [ ], + + # Row 2 + [ + # width, height, keysym, keytop, flags + [ 6, 1, "`", "`" ], + [ 6, 1, "1", "1" ], + [ 6, 1, "2", "2" ], + [ 6, 1, "3", "3" ], + [ 6, 1, "4", "4" ], + [ 6, 1, "5", "5" ], + [ 6, 1, "6", "6" ], + [ 6, 1, "7", "7" ], + [ 6, 1, "8", "8" ], + [ 6, 1, "9", "9" ], + [ 6, 1, "0", "0" ], + [ 6, 1, "-", "-" ], + [ 6, 1, "=", "=" ], + [ 12, 1, "backspace", "BS" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "cursor-insert", "Ins" ], + [ 6, 1, "cursor-home", "Home" ], + [ 6, 1, "cursor-pagedown", "PgUp" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "numlock", "NL" ], + [ 6, 1, "keypad-divide", "/" ], + [ 6, 1, "keypad-multiply", "*" ], + [ 6, 1, "keypad-minus", "-" ], + ], + + # Row 3 + [ + [ 9, 1, "tab", "Tab" ], + [ 6, 1, "q", "Q" ], + [ 6, 1, "w", "W" ], + [ 6, 1, "e", "E" ], + [ 6, 1, "r", "R" ], + [ 6, 1, "t", "T" ], + [ 6, 1, "y", "Y" ], + [ 6, 1, "u", "U" ], + [ 6, 1, "i", "I" ], + [ 6, 1, "o", "O" ], + [ 6, 1, "p", "P" ], + [ 6, 1, "[", "[" ], + [ 6, 1, "]", "]" ], + [ 9, 1, "return", "Enter" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "cursor-delete", "Del" ], + [ 6, 1, "cursor-end", "End" ], + [ 6, 1, "cursor-pagedown", "PgDn" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "keypad-7", "7" ], + [ 6, 1, "keypad-8", "8" ], + [ 6, 1, "keypad-9", "9" ], + [ 6, 2, "keypad-plus", "+" ], + ], + + # Row 4 + [ + [ 11, 1, "", "Caps" ], + [ 6, 1, "a", "A" ], + [ 6, 1, "s", "S" ], + [ 6, 1, "d", "D" ], + [ 6, 1, "f", "F" ], + [ 6, 1, "g", "G" ], + [ 6, 1, "h", "H" ], + [ 6, 1, "j", "J" ], + [ 6, 1, "k", "K" ], + [ 6, 1, "l", "L" ], + [ 6, 1, ";", ";" ], + [ 6, 1, "'", "'" ], + [ 6, 1, "#", "#" ], + [ 7, 1, "return", "Enter" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "", "" ], + [ 6, 1, "", "" ], + [ 6, 1, "", "" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "keypad-4", "4" ], + [ 6, 1, "keypad-5", "5" ], + [ 6, 1, "keypad-6", "6" ], + ], + + # Row 5 + [ + [ 7, 1, "shift", "Shift" ], + [ 6, 1, "\\", "\\" ], + [ 6, 1, "z", "Z" ], + [ 6, 1, "x", "X" ], + [ 6, 1, "c", "C" ], + [ 6, 1, "v", "V" ], + [ 6, 1, "b", "B" ], + [ 6, 1, "n", "N" ], + [ 6, 1, "m", "M" ], + [ 6, 1, ",", "," ], + [ 6, 1, ".", "." ], + [ 6, 1, "/", "/" ], + [ 17, 1, "shift", "Shift" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "", "" ], + [ 6, 1, "cursor-up", "Up" ], + [ 6, 1, "", "" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "keypad-1", "1" ], + [ 6, 1, "keypad-2", "2" ], + [ 6, 1, "keypad-3", "3" ], + [ 6, 2, "keypad-enter", "RET" ], + ], + + # Row 6 + [ + [ 8, 1, "ctrl", "Ctrl" ], + [ 7, 1, "logo", "Logo" ], + [ 8, 1, "alt", "Alt" ], + [ 37, 1, "space", "Space" ], + [ 8, 1, "alt", "Alt" ], + [ 7, 1, "logo", "Logo" ], + [ 7, 1, "menu", "Menu" ], + [ 8, 1, "ctrl", "Ctrl" ], + + [ 3, 1, "", "" ], + + [ 6, 1, "cursor-left", "Left" ], + [ 6, 1, "cursor-down", "Down" ], + [ 6, 1, "cursor-right", "Right" ], + + [ 3, 1, "", "" ], + + [ 12, 1, "keypad-0", "0" ], + [ 6, 1, "keypad-.", "." ], + ] +] + + + + + + + +mouse = [ + [ + [ 160, 0, None, None ], + ], + + # Row 1 + [ + [ 14, 1, "axis:mouse-0.0", "MOUSEX" ], + [ 14, 1, "axis:mouse-0.1", "MOUSEY" ], + [ 8, 1, "", "" ], + [ 14, 1, "mouse-0.0", "MOUSE0" ], + [ 8, 1, "mouse-0.1", "1" ], + [ 8, 1, "mouse-0.2", "2" ], + [ 8, 1, "mouse-0.3", "3" ], + [ 8, 1, "mouse-0.4", "4" ], + [ 8, 1, "mouse-0.5", "5" ], + [ 8, 1, "mouse-0.6", "6" ], + [ 8, 1, "mouse-0.7", "7" ], + [ 8, 1, "mouse-0.8", "8" ], + [ 8, 1, "mouse-0.9", "9" ], + ], +# [ +# [ 14, 1, "", "MOUSE0" ], +# [ 14, 1, "", "MOUSE1" ], +# [ 14, 1, "", "MOUSE2" ], +# [ 14, 1, "", "MOUSE3" ], +# [ 14, 1, "", "MOUSE4" ], +# [ 14, 1, "", "MOUSE5" ], +# [ 14, 1, "", "MOUSE6" ], +# [ 14, 1, "", "MOUSE7" ], +# [ 14, 1, "", "MOUSE8" ], +# [ 14, 1, "", "MOUSE9" ], +# ], +# +# # Row 2 +# [ +# [ 14, 1, "", "MOUSEX" ], +# [ 14, 1, "", "MOUSEY" ], +# ], +] + +joystick = [ + [ + [ 200, 0, None, None ], + ], + + # Row 1 + [ + [ 11, 1, "joystick-0.0", "JOY0" ], + [ 11, 1, "joystick-0.1", "JOY1" ], + [ 11, 1, "joystick-0.2", "JOY2" ], + [ 11, 1, "joystick-0.3", "JOY3" ], + [ 11, 1, "joystick-0.4", "JOY4" ], + [ 11, 1, "joystick-0.5", "JOY5" ], + [ 11, 1, "joystick-0.6", "JOY6" ], + [ 11, 1, "joystick-0.7", "JOY7" ], + [ 11, 1, "joystick-0.8", "JOY8" ], + [ 11, 1, "joystick-0.9", "JOY9" ], + [ 11, 1, "joystick-0.10", "JOY10" ], + [ 11, 1, "joystick-0.11", "JOY11" ], + ], + + # Row 2 + [ + [ 11, 1, "joystick-0.12", "JOY12" ], + [ 11, 1, "joystick-0.13", "JOY13" ], + [ 11, 1, "joystick-0.14", "JOY14" ], + [ 11, 1, "joystick-0.15", "JOY15" ], + [ 11, 1, "joystick-0.16", "JOY16" ], + [ 11, 1, "joystick-0.17", "JOY17" ], + [ 11, 1, "joystick-0.18", "JOY18" ], + [ 11, 1, "joystick-0.19", "JOY19" ], + [ 11, 1, "joystick-0.20", "JOY20" ], + [ 11, 1, "joystick-0.21", "JOY21" ], + [ 11, 1, "joystick-0.22", "JOY22" ], + [ 11, 1, "joystick-0.23", "JOY23" ], + ], + + # Row 3 + [ + [ 16, 1, "axis:joystick-0.0", "AXIS0" ], + [ 16, 1, "axis:joystick-0.1", "AXIS1" ], + [ 16, 1, "axis:joystick-0.2", "AXIS2" ], + [ 16, 1, "axis:joystick-0.3", "AXIS3" ], + [ 16, 1, "axis:joystick-0.4", "AXIS4" ], + [ 16, 1, "axis:joystick-0.5", "AXIS5" ], + [ 16, 1, "axis:joystick-0.6", "AXIS6" ], + [ 16, 1, "axis:joystick-0.7", "AXIS7" ], + ], + + # Row 4 + [ + [ 14, 1, "digital-hatswitch:0.leftup", "DHAT0.↖" ], + [ 14, 1, "digital-hatswitch:0.up", "DHAT0.↑" ], + [ 14, 1, "digital-hatswitch:0.rightup", "DHAT0.↗" ], + [ 14, 1, "", "" ], + [ 14, 1, "digital-hatswitch:1.leftup", "DHAT1.↖" ], + [ 14, 1, "digital-hatswitch:1.up", "DHAT1.↑" ], + [ 14, 1, "digital-hatswitch:1.rightup", "DHAT1.↗" ], + ], + + # Row 5 + [ + [ 14, 1, "digital-hatswitch:0.left", "DHAT0.←" ], + [ 14, 1, "digital-hatswitch:0.center", "DHAT0.⊙" ], + [ 14, 1, "digital-hatswitch:0.right", "DHAT0.→" ], + [ 14, 1, "", "" ], + [ 14, 1, "digital-hatswitch:1.left", "DHAT1.←" ], + [ 14, 1, "digital-hatswitch:1.center", "DHAT1.⊙" ], + [ 14, 1, "digital-hatswitch:1.right", "DHAT1.→" ], + ], + + # Row 6 + [ + [ 14, 1, "digital-hatswitch:0.leftdown", "DHAT0.↙" ], + [ 14, 1, "digital-hatswitch:0.down", "DHAT0.↓" ], + [ 14, 1, "digital-hatswitch:0.rightdown", "DHAT0.↘" ], + [ 14, 1, "", "" ], + [ 14, 1, "digital-hatswitch:1.leftdown", "DHAT1.↙" ], + [ 14, 1, "digital-hatswitch:1.down", "DHAT1.↓" ], + [ 14, 1, "digital-hatswitch:1.rightdown", "DHAT1.↘" ], + ], + + # Row 7 + [ + [ 13, 1, "hatswitch:0.0", "AHAT0.0" ], + [ 13, 1, "hatswitch:0.1", "AHAT0.1" ], + [ 13, 1, "hatswitch:0.2", "AHAT0.2" ], + [ 13, 1, "hatswitch:0.3", "AHAT0.3" ], + [ 13, 1, "hatswitch:0.4", "AHAT0.4" ], + [ 13, 1, "hatswitch:0.5", "AHAT0.5" ], + [ 13, 1, "hatswitch:0.6", "AHAT0.6" ], + [ 13, 1, "hatswitch:0.7", "AHAT0.7" ], + [ 13, 1, "hatswitch:0.8", "AHAT0.8" ], + [ 13, 1, "hatswitch:0.9", "AHAT0.9" ], + ], + + # Row 8 + [ + [ 13, 1, "hatswitch:1.0", "AHAT1.0" ], + [ 13, 1, "hatswitch:1.1", "AHAT1.1" ], + [ 13, 1, "hatswitch:1.2", "AHAT1.2" ], + [ 13, 1, "hatswitch:1.3", "AHAT1.3" ], + [ 13, 1, "hatswitch:1.4", "AHAT1.4" ], + [ 13, 1, "hatswitch:1.5", "AHAT1.5" ], + [ 13, 1, "hatswitch:1.6", "AHAT1.6" ], + [ 13, 1, "hatswitch:1.7", "AHAT1.7" ], + [ 13, 1, "hatswitch:1.8", "AHAT1.8" ], + [ 13, 1, "hatswitch:1.9", "AHAT1.9" ], + ], +] + + +shiftmap = {} +shiftmap['en/US 101'] = { + "`": "~", + "1": "!", + "2": "@", + "3": "#", + "4": "$", + "5": "%", + "6": "^", + "7": "&", + "8": "*", + "9": "(", + "0": ")", + "-": "_", + "=": "+", + "[": "{", + "]": "}", + "\\": "|", + ";": ":", + "'": "\"", + ",": "less-than", + ".": "greater-than", + "/": "?", + "a": "A", + "b": "B", + "c": "C", + "d": "D", + "e": "E", + "f": "F", + "g": "G", + "h": "H", + "i": "I", + "j": "J", + "k": "K", + "l": "L", + "m": "M", + "n": "N", + "o": "O", + "p": "P", + "q": "Q", + "r": "R", + "s": "S", + "t": "T", + "u": "U", + "v": "V", + "w": "W", + "x": "X", + "y": "Y", + "z": "Z", +} + + +shiftmap['de/DE 104'] = { + "^": "˚", # circumflex, ring + "1": "!", + "2": "\"", + "3": "§", + "4": "$", + "5": "%", + "6": "&", + "7": "/", + "8": "(", + "9": ")", + "0": "=", + "ß": "?", + "´": "`", # acute, grave + "ü": "Ü", + "+": "*", + "ö": "Ö", + "ä": "Ä", + "#": "'", + "less-than": "greater-than", + ",": ";", + ".": ":", + "-": "_", + "a": "A", + "b": "B", + "c": "C", + "d": "D", + "e": "E", + "f": "F", + "g": "G", + "h": "H", + "i": "I", + "j": "J", + "k": "K", + "l": "L", + "m": "M", + "n": "N", + "o": "O", + "p": "P", + "q": "Q", + "r": "R", + "s": "S", + "t": "T", + "u": "U", + "v": "V", + "w": "W", + "x": "X", + "y": "Y", + "z": "Z", +} + + +shiftmap['en/GB 104'] = { + "`": "¬", + "1": "!", + "2": "\"", + "3": "£", + "4": "$", + "5": "%", + "6": "^", + "7": "&", + "8": "*", + "9": "(", + "0": ")", + "-": "_", + "=": "+", + "[": "{", + "]": "}", + ";": ":", + "'": "@", + "#": "~", + "\\": "|", + ",": "less-than", + ".": "greater-than", + "/": "?", + "a": "A", + "b": "B", + "c": "C", + "d": "D", + "e": "E", + "f": "F", + "g": "G", + "h": "H", + "i": "I", + "j": "J", + "k": "K", + "l": "L", + "m": "M", + "n": "N", + "o": "O", + "p": "P", + "q": "Q", + "r": "R", + "s": "S", + "t": "T", + "u": "U", + "v": "V", + "w": "W", + "x": "X", + "y": "Y", + "z": "Z", +} + + + +shiftmap['en/US 104'] = shiftmap['en/US 101'] +shiftmap['en/US-dvorak 104'] = shiftmap['en/US 101'] +shiftmap['en/US AppleProAlFull'] = shiftmap['en/US 101'] +shiftmap['en/US HappyHacking'] = shiftmap['en/US 101'] +shiftmap['en/US HappyHackingLite2'] = shiftmap['en/US 101'] +shiftmap['en/US HappyHackingPro2'] = shiftmap['en/US 101'] + + +unshiftmap = {} +for name,mapping in shiftmap.items(): + rmapping = {} + for k,v in mapping.items(): + rmapping[v] = k + unshiftmap[name] = rmapping +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.py Wed Jun 29 08:32:07 2011 -0700 @@ -0,0 +1,1826 @@ +#!/usr/bin/env python +# Expecting python 2.6 + +from __future__ import print_function + +LICENSE_LONG = r""" + VegaStrike 0.5.x PyKeyBinder v0.13 + Copyright (C) 2011 Frederick Lee <phaethon@icculus.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +""" + +PACKAGE = "VegaStrike 0.5.x - PyKeyBinder" +VERSION = "0.20" +ICON = None +DESCRIPTION = "Establish keybindings for VegaStrike 0.5.x" +COPYRIGHT = "Copyright 2011 - distributed under terms of GPL 2.0 or later" +LICENSE = LICENSE_LONG + +HOMEPAGE = "http://www.icculus.org/~phaethon/vegastrike/vegastrikebind/vegastrikebind.html" +DEVELOPERS = ( "Frederick Lee <PhaethonH@gmail.com>", ) + + + +#TODO: +# [X] save +# [X] the 'preset' menu +# [X] saner state information on current layout +# [X] factor out duplicated make_menu() + + + +# Initial (default) layout. +LAYOUT0 = 'en/US 104' + + +import threading +import wx, wx.grid +import xml, xml.dom.minidom +import layouts, predefs + +try: + import pygame, pygame.joystick + pass +except: + pass + +try: + import OpenGL.GLUT +except: + pass + + + + +def crumb (msg): + print(msg) + + + + +# Vegastrike uses either SDL or GLUT for joystick interface, preferring SDL if available. + + + + +class IJoystickReader (object): + """Interface for querying joystick properties.""" + def OpenAll (self): pass + def CloseAll (self): pass + def CountDevices (self): pass + def CountAxes (self, idx): pass + def CountHats (self, idx): pass + def CountButtons (self, idx): pass + +class JoystickReaderDummy (IJoystickReader): + """Implements IJoystickReader. + +Dummy object (returns values from the commented-out sample values in vegastrike.config (from VegaStrike 0.5.0). Provided so that those without an actual joystick, or one that reports back inaccurate values, can play around with joystick binds. +""" + def __init__ (self): + self.joys = [] + pass + def OpenAll (self): + self.joys = [ None ] # dummy object. + def CloseAll (close): + pass + def CountDevices (self): + return 1 + def CountAxes (self, idx): + return 8 + def CountButtons (self, idx): + return 24 + def CountHats (self, idx): + return 2 + + +class JoystickReaderWx (IJoystickReader): + """Implements IJoystickReader. + +Use wxWidgets library for querying joystick. +""" + def __init__ (self): + self.joys = [] + pass + def OpenAll (self): + js = wx.Joystick() +# maxjs = wx.Joystick.GetNumberJoysticks() + if js: + maxjs = js.GetNumberJoysticks() + for n in xrange(0, maxjs): + if n > wx.JOYSTICK1: + js = wx.Joystick(wx.JOYSTICK1 + n) + self.joys.append(js) + #crumb("JoystickReaderWx ready") + pass + def CloseAll (close): + for n in xrange(0, len(self.joys)): + del self.joys[n] + self.joys = [] + pass + def CountDevices (self): +# return wx.Joystick.GetNumberJoysticks() + retval = 0 + if self.joys: +# retval = self.joys[0].GetNumberJoysticks() + retval = len(self.joys) + else: + js = wx.Joystick() + retval = js.GetNumberJoysticks() + del js + #crumb("JoystickReaderWx: CountDevices=%d" % retval) + return retval + def CountAxes (self, idx): + retval = 0 + if (0 <= idx) and (idx < len(self.joys)): + retval = self.joys[idx].GetNumberAxes() + #crumb("JoystickReaderWx: CountAxes=%d" % retval) + return retval + def CountButtons (self, idx): + retval = 0 + if (0 <= idx) and (idx < len(self.joys)): + retval = self.joys[idx].GetNumberButtons() + #crumb("JoystickReaderWx: CountButtons=%d" % retval) + return retval + def CountHats (self, idx): + retval = 0 + #crumb("JoystickReaderWx: CountHats=%d" % retval) + return retval + +class JoystickReaderSDL (IJoystickReader): + """Implements IJoystickReader. + +Uses SDL for querying joystick. + +This implementation is the preferred one over the others, as VegaStrike itself uses SDL for joystick. +""" + def __init__ (self): + pygame.joystick.init() + self.joys = [] + pass + def OpenAll (self): + maxjs = pygame.joystick.get_count() + self.joys = [] # Rely on gc to clean up (previously-)opened devices. + for n in xrange(0, maxjs): + js = pygame.joystick.Joystick(n) + js.init() + self.joys.append(js) + pass + def CloseAll (self): + pass + def CountDevices (self): + return pygame.joystick.get_count() + def CountAxes (self, idx): + retval = 0 + if (0 <= idx) and (idx < len(self.joys)): + retval = self.joys[idx].get_numaxes() + return retval + def CountButtons (self, idx): + retval = 0 + if (0 <= idx) and (idx < len(self.joys)): + retval = self.joys[idx].get_numbuttons() + return retval + def CountHats (self, idx): + retval = 0 + if (0 <= idx) and (idx < len(self.joys)): + retval = self.joys[idx].get_numhats() + return retval + +class JoystickReaderGLUT (IJoystickReader): + # *** ABANDONED *** + """Implements IJoystickReader. + +Uses GLUT for querying joystick. Implemented because I saw GLUT code in VegaStrike, but that piece doesn't seem to be used at all, thus abandoned. But it remains anyway as a demonstration of something else implementing IJoystickReader. +""" + def __init__ (self): + OpenGL.GLUT.glutInit(sys.argv) + valid = OpenGL.GLUT.glutDeviceGet(OpenGL.GLUT.GLUT_HAS_STICK) + pollrate = 50 # [ms] ; arbitrary for this app. + OpenGL.GLUT.glutJoystickFunc(self.jscallback, pollrate) + pass + +class JoystickReader (object): + """Wrapper to the JoystickReader objects. Attempts to test each one for a viable interface. + +Order of preference is: +1. SDL +2. wxWidgets +3. dummy +""" + def __init__ (self): + self.backend = None + if not self.backend: + try: + self.backend = JoystickReaderSDL() + except: + print("Error opening joystick with pygame.") + if not self.backend: + try: + self.backend = JoystickReaderWx() + except: + print ("Error opening joystick with wx.") + if not self.backend: + self.backend = JoystickReaderDummy() + self.backend.OpenAll() + def make_layout (self): + layoutdata = [ [] ] + + njoys = self.backend.CountDevices() + #njoys = 2 + + for joyidx in xrange(0, njoys): + nbtns = 24 + naxes = 9 + nhats = 0 + + nbtns = self.backend.CountButtons(joyidx) + naxes = self.backend.CountAxes(joyidx) + nhats = self.backend.CountHats(joyidx) + + layoutrow = [] + + # Joystick buttons. 12 to a row, 11 wide each. + for btnidx in xrange(0, nbtns): + if (btnidx % 12) == 0: + if layoutrow: + layoutdata.append(layoutrow) + layoutrow = [] + ksym = "joystick-%d.%d" % (joyidx, btnidx) + ktop = "JOY%d" % btnidx + layoutrow.append( [11, 1, ksym, ktop ] ) + if layoutrow: + layoutdata.append(layoutrow) + + layoutrow = [] + # Joystick axes. 8 to a row, 16 wide each. + for axisidx in xrange(0, naxes): + if (axisidx % 8) == 0: + if layoutrow: + layoutdata.append(layoutrow) + layoutrow = [] + ksym = "axis:joystick-%d.%d" % (joyidx, axisidx) + ktop = "AXIS%d" % axisidx + layoutrow.append( [16, 1, ksym, ktop] ) + if layoutrow: + layoutdata.append(layoutrow) + + return layoutdata + + +def build_joylayout (): + """Build the joystick layout description based on JoystickReader results.""" + + #crumb("build_joylayout...") + js = JoystickReader() + retval = js.make_layout() + #crumb("build_joylayout done: %s" % retval) + return retval + + # TODO: elide dead code. + njoys = 1 + nbtns = 24 + naxes = 9 + + layoutdata = [ [] ] + layoutrow = [] + + joyidx = 0 + # Joystick buttons. 12 to a row, 11 wide each. + for btnidx in xrange(0, nbtns): + if (btnidx % 12) == 0: + if layoutrow: + layoutdata.append(layoutrow) + layoutrow = [] + ksym = "joystick-%d.%d" % (joyidx, btnidx) + ktop = "JOY%d" % btnidx + layoutrow.append( [11, 1, ksym, ktop ] ) + if layoutrow: + layoutdata.append(layoutrow) + + layoutrow = [] + # Joystick axes. 8 to a row, 16 wide each. + for axisidx in xrange(0, naxes): + if (axisidx % 8) == 0: + if layoutrow: + layoutdata.append(layoutrow) + layoutrow = [] + ksym = "axis:joystick-%d.%d" % (joyidx, axisidx) + ktop = "AXIS%d" % axisidx + layoutrow.append( [16, 1, ksym, ktop] ) + if layoutrow: + layoutdata.append(layoutrow) + + return layoutdata + pass + + + + + +def make_menu (self, data): + """Construct a menu from a list of lists.... + +TODO: describe menu description format. +""" + menu = wx.Menu() + for item in data: + if item is None: + # Separator + menu.AppendSeparator() + pass + elif type(item) == str: + lbl = item + menuitem = menu.Append(-1, lbl) + try: + wx.EVT_MENU(self, menuitem.GetId(), self.guiOneField) + except: + # Just ignore if guiOneField() does not exist. + pass + pass + elif (type(item) == list) or (type(item) == tuple): + if len(item) == 2: + # 2-field item. Could be submenu or string-with-tooltip. + car = item[0] + cadr = item[1] +# crumb("type %s" % type(cadr)) + if type(cadr) == list: + lbl = car + # Second field is list -- submenu. +# crumb("submenu <- %s %s" % (cadr, lbl)) + submenu = make_menu(self, cadr) + menuitem = menu.AppendSubMenu(submenu, lbl) + else: + # Second field not a list -- string-with-tooltip. + (lbl, tooltip) = item +# crumb("Build 2-field menuitem (%s, %s)" % (lbl, tooltip)) + op = menu.Append + if lbl: + if lbl[0] == '+': + lbl, op = lbl[1:], menu.AppendCheckItem + if lbl[0] == '@': + lbl, op = lbl[1:], menu.AppendRadioItem + if tooltip: + menuitem = apply(op, (-1, lbl, tooltip)) + #crumb("GetHelp: %s" % menuitem.GetHelp()) + else: + menuitem = apply(op, (-1, lbl)) + try: + wx.EVT_MENU(self, menuitem.GetId(), self.guiTwoField) + except: + # Just ignore if guiTwoField() does not exist. + pass + else: + # Assume 4-field entry. +# crumb("4-field: %s" % item) + ( lbl, wxid, callback, tooltip ) = item + op = menu.Append + if lbl: + if lbl[0] == '+': + lbl, op = lbl[1:], menu.AppendCheckItem + if lbl[0] == '@': + lbl, op = lbl[1:], menu.AppendRadioItem + menuitem = apply(op, (wxid, lbl, tooltip)) + if (callback is None) or (callback == self.guiNop): + menuitem.Enable(False) + pass + else: + wxid = menuitem.GetId() + wx.EVT_MENU(self, wxid, callback) + return menu + + + + + + + + + +class SDLKeyCapturer (wx.Button): + + class SDLEventWatcher (threading.Thread): + def __init__ (self): + threading.Thread.__init__(self) + self.active = False + pass + def run (self): + self.active = True + js = JoystickReader() + prev_keyb = None + prev_mouseb = None + prev_mousem = None + prev_joyb = None + prev_joya = None + prev_joyh = None + while self.active: + # Query all devices. + keyb = pygame.key.get_pressed() + mouseb = pygame.mouse.get_pressed() + mousem = pygame.mouse.get_rel() + joyb = [] + joya = [] + joyh = [] + n = js.backend.CountDevices() + for i in xrange(0, n): + jobj = js.backend.joys[i] + b = [] + for j in xrange(0, jobj.get_numbuttons()): + b.append(jobj.get_button(j)) + a = [] + for j in xrange(0, jobj.get_numaxes()): + a.append(jobj.get_axis(j)) + h = [] + for j in xrange(0, jobj.get_numhats()): + h.append(jobj.get_hat(j)) + pass + # Do stuff. + pass + pass + prev_keyb = keyb + prev_mouseb = mouseb + prev_mousem = mousem + prev_joyb = joyb + prev_joya = joya + prev_joyh = joyh +# def + + def __init__ (self, parent, wxid): + crumb("SDLKeyCapturer::<ctor>") + wx.Button.__init__(self, parent, wxid, "Press key") + # When getting focus, kick in SDL event watching. + wx.EVT_SET_FOCUS(self, self.OnFocus) + wx.EVT_KILL_FOCUS(self, self.OffFocus) + + def OnFocus (self, evt): + # Kick in SDL event watching: keyboard, mouse, joystick. + crumb("SDLKeyCapturer::OnFocus") + pass + + def OffFocus (self, evt): + # Kick out SDL event watching. + crumb("SDLKeyCapturer::OffFocus") + pass + + def Reset (self, *args): + crumb("SDLKeyCapturer::Reset") + pass + + + + + + + + + +class VegastrikeFunctionBindPanel (wx.Panel): + """Set bindings from a function-centric view (pick action, then assign key).""" + + class BindCellEditor (wx.grid.PyGridCellEditor): + # Takes pieces from demo program GridCustEditor.py + def __init__ (self): + wx.grid.PyGridCellEditor.__init__(self) + self.created = False + self.avatar = None + self.wxid = None + pass + + def Create (self, parent, wxid, evtHandler): + crumb("BindCellEditor::Create") + self.created = True + #self.avatar = wx.StaticText(parent, wxid, "Press key") + #self.avatar = wx.TextCtrl(parent, wxid, "Press key") + #self.avatar = wx.Button(parent, wxid, "Press key") + self.avatar = SDLKeyCapturer(parent, wxid) + #self.avatar.SetEditable(False) + self.SetControl(self.avatar) + self.wxid = self.avatar.GetId() + if evtHandler: + crumb("-- evtHandler=%s" % evtHandler) + self.avatar.PushEventHandler(evtHandler) + + def Show (self, show, attr): + wx.grid.PyGridCellEditor.Show(self, show, attr) + #self.base_Show(show, attr) + + def SetSize (self, rect): + self.avatar.SetDimensions(rect.x, rect.y, rect.width+2, rect.height+2, wx.SIZE_ALLOW_MINUS_ONE) + pass + + def IsAcceptedKey (self, evt): + crumb("IsAcceptedKey: %s" % evt) + return True + + def BeginEdit (self, row, col, grid): + crumb("BindCellEditor::BeginEdit") + # Capture all key, mouse click, and joystick events. + #win = self.avatar.GetParent() + #win.Connect(self.wxid, -1, wx.wxEVT_KEY_DOWN, self.BindCaptureHandler) + #self.avatar.Connect(self.wxid, self.wxid, wx.wxEVT_KEY_DOWN, self.BindCaptureHandler) +# win = wx.GetApp().GetTopWindow() +# #win.Connect(self.wxid, -1, wx.wxEVT_KEY_DOWN, self.BindCaptureHandler) +# self.avatar.Bind(wx.EVT_KEY_DOWN, self.BindCaptureHandler) +# self.avatar.Bind(wx.EVT_KEY_UP, self.BindCaptureHandler) +# self.avatar.Bind(wx.EVT_JOY_BUTTON_DOWN, self.BindCaptureHandler) +# #self.avatar.Bind(wx.EVT_JOY_MOVE, self.BindCaptureHandler) +# self.avatar.Bind(wx.EVT_MOUSEWHEEL, self.BindCaptureHandler) +# #self.avatar.Bind(wx.EVT_MOTION, self.BindCaptureHandler) +# self.avatar.Bind(wx.EVT_LEFT_DOWN, self.BindCaptureHandler) +# self.avatar.Bind(wx.EVT_MIDDLE_DOWN, self.BindCaptureHandler) +# self.avatar.Bind(wx.EVT_RIGHT_DOWN, self.BindCaptureHandler) +# self.avatar.SetFocus() + #win.Bind(wx.EVT_KEY_DOWN, self.BindCaptureHandler) + self.avatar.SetFocus() + pass + + def EndEdit (self, row, col, grid): + crumb("BindCellEditor::EndEdit") + #win = self.avatar.GetParent() + #win.Disconnect(self.wxid, wx.wxEVT_KEYDOWN, self.BindCaptureHandler) + #self.avatar.Disconnect(self.wxid, self.wxid, wx.wxEVT_KEY_DOWN, self.BindCaptureHandler) +# win = wx.GetApp().GetTopWindow() +# #win.Connect(self.wxid, -1, wx.wxEVT_KEY_DOWN, self.BindCaptureHandler) +# self.avatar.Unbind(wx.EVT_KEY_DOWN) +# unbindstuff = [ +# wx.EVT_KEY_DOWN, wx.EVT_KEY_UP, +# wx.EVT_JOY_BUTTON_DOWN, +# wx.EVT_MOUSEWHEEL, +# wx.EVT_LEFT_DOWN, wx.EVT_MIDDLE_DOWN, wx.EVT_RIGHT_DOWN, +# ] +# for evt in unbindstuff: +# self.avatar.Unbind(evt) + #win.Unbind(wx.EVT_KEY_DOWN) + ksym = '' + grid.GetTable().SetValue(row, col, ksym) + pass + + def Reset (self): + pass + + def BindCaptureHandler (self, evt): + crumb("BindCaptureHandler %s" % evt) + pass + + pass + + def __init__ (self, parent, wxid=wx.ID_ANY): + wx.Panel.__init__(self, parent, wxid) + self.build_ui() + + def build_ui (self): + self.celleditor = self.BindCellEditor() + + topsizer = wx.BoxSizer(wx.VERTICAL) + + table = wx.grid.Grid(self, wx.ID_ANY) + table.CreateGrid(0, 4) +# table.SetCellValue(0, 0, "cell") +# table.SetCellValue(0, 1, "cell") + + table.SetRowLabelSize(240) + table.SetColLabelValue(0, "Primary") + table.SetColLabelValue(1, "Secondary") + table.SetColLabelValue(2, "Mouse") + table.SetColLabelValue(3, "Joystick") + +# row = 1 +# attr = table.GetTable().GetAttr(1, 1, 0) +# crumb("GetAttr: %s" % attr) +## attr.SetReadOnly(True) +## table.SetRowAttr(attr) + + rownum = 0 + table.SetRowLabelAlignment(wx.ALIGN_LEFT, wx.ALIGN_CENTRE) + for category in predefs.Commands: + name = category[0] + cmds = category[1] + + if cmds: + # Category divider/header + table.SetRowLabelValue(rownum, "== %s ==" % name) + for i in xrange(0, table.GetNumberCols()): + table.SetReadOnly(rownum, i, True) + #table.SetCellBackgroundColour(rownum, i, (wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))) + table.SetCellBackgroundColour(rownum, i, (0,0,0)) + table.AppendRows(1, True) + rownum += 1 + for cmd in cmds: + if type(cmd) == tuple: + cmd = cmd[1] + table.SetRowLabelValue(rownum, cmd) + table.AppendRows(1, True) + for i in xrange(0, table.GetNumberCols()): + #crumb("SetCellEditor(%d, %d, %s)" % (rownum, i, self.celleditor)) + #table.SetCellEditor(rownum, i, self.celleditor.Clone()) + table.SetCellEditor(rownum, i, self.BindCellEditor()) + rownum += 1 + + topsizer.Add(table, 1, wx.EXPAND) + self.SetSizer(topsizer) + pass + + + + +class VegastrikeLayoutBindPanel (wx.Panel): + """Set binds from a layout/keyboard centric view (pick key, then assign function).""" + RGB_NORMAL = None + RGB_BOUND = (0xee, 0xee, 0xee) + RGB_HILITE = (0xcc, 0xcc, 0xff) + RGB_SELECT = (0xff, 0xff, 0x00) + + def __init__ (self, parent, wxid, title=""): + """Constructor. Set up object state. Gui constructed delegated to build_ui().""" + wx.Panel.__init__(self, parent, wxid) + + # ** state information ** + # mapping from keysym name to wxID + self.keylookup = {} + # mapping of wxID to key description + self.btndata = {} + # Previously-selected key (wxID); should also be currently selected key after setting. + self.prevkey = None + # Previously-selected key's background prior to being selected. + self.prevbg = None + # Flyover mode (show hovering bind information over (bound) key) + self.flyover = False + # Current keyboard layout. + self.kbdlayout = LAYOUT0 # TODO: from preferences +# self.kbdlayout = 'en/US HappyHackingLite2' + + self.build_ui() + + def status (self, msg=None): + """Update status bar.""" +# if msg: +# self.SetStatusText(msg) +# else: +# self.SetStatusText("") + self.GetParent().GetParent().status(msg) + pass + + def build_ui (self): + """Construct GUI elements. Separated out to allow delayed building, and/or using build code from a GUI building tool (e.g. Boa Constructor).""" + #crumb("BindPanel.build_ui") + topsizer = wx.BoxSizer(wx.VERTICAL) + +# line = wx.BoxSizer(wx.HORIZONTAL) +# line.Add(wx.StaticText(self, -1, "Layout:"), flag=wx.ALIGN_CENTER) +# self.pickLayout = self.make_pickLayout() +# line.Add(self.pickLayout) +# topsizer.AddSizer(line) + + #crumb("BindPanel.makeReviewPanel") + self.reviewpanel = self.make_reviewPanel() + topsizer.Add(self.reviewpanel, 1, flag=wx.EXPAND) + + #crumb("BindPanel.make_inpdev(KEYBAORD)") + self.keyb = self.make_inpdev(self.kbdlayout) + topsizer.Add(self.keyb, 5, flag=wx.EXPAND|wx.ALL, border=1) + + #crumb("BindPanel.make_inpdev(MOUSE)") +# self.mouse = self.make_inpdev('mouse') + self.mouse = self.make_inpdev(layouts.mouse) + topsizer.Add(self.mouse, 1, flag=wx.EXPAND|wx.ALL, border=1) + + #crumb("BindPanel.make_inpdev(JOYSTICK)") +# if 1: +# data = build_joylayout() +# layouts.keyboard['joystick'] = data +# self.joy = self.make_inpdev('joystick') +# self.joy = self.make_inpdev(layouts.joystick) + joydata = build_joylayout() + #crumb("BindPanel.make_inpdev(JOYSTICK)...") + self.joy = self.make_inpdev(joydata) + topsizer.Add(self.joy, 5, flag=wx.EXPAND|wx.ALL, border=1) + +# line = wx.BoxSizer(wx.HORIZONTAL) +# self.flyover = wx.CheckBox(self, -1, "Enable tooltip/flyover mode") +# line.Add(self.flyover, 1, wx.ALIGN_TOP) +# topsizer.Add(line) + + self.SetSizer(topsizer) + #crumb("BindPanel ready.") + pass + + def make_legend (self): + pass + + def make_pickLayout (self): + # DEPRECATED + """Generate GUI control element for choosing a keyboard layout. + +Returns wxChoice object (wxControl). +""" + pickLayout = wx.Choice(self, -1) + pickLayout.Append("en_US_101") + pickLayout.Append("en_US_104") + pickLayout.Append("de_DE_104") + return pickLayout + + def make_reviewPanel (self): + """Build the GUI element + +Returns wxFlexGridSizer object (wxSizer).""" + +# reviewpanel = wx.FlexGridSizer(2, 4) + reviewpanel = wx.FlexGridSizer(2, 3) + lbl0 = wx.StaticText(self, -1, "Modifier") + lbl1 = wx.StaticText(self, -1, "Key") + lbl2 = wx.StaticText(self, -1, "Command") +# lbl3 = wx.StaticText(self, -1, "Presets") +# map(lambda x: reviewpanel.AddGrowableCol(x), range(0, 4)) +# map(lambda x: reviewpanel.AddGrowableCol(x), range(2, 4)) +# map(lambda x: reviewpanel.AddGrowableCol(x), range(1, 3)) + reviewpanel.AddGrowableCol(1, 1) + reviewpanel.AddGrowableCol(2, 3) + reviewpanel.Add(lbl0, 1, wx.ALIGN_CENTER) + reviewpanel.Add(lbl1, 1, wx.ALIGN_CENTER) + reviewpanel.Add(lbl2, 4, wx.ALIGN_CENTER) +# reviewpanel.Add(lbl3, 1, wx.ALIGN_CENTER) + + self.pickModifier = wx.Choice(self, -1) + options = [ ('(none)', 0), + ('shift', 0x01), + ('ctrl', 0x02), + ('ctrl+shift', 0x03), + ('alt', 0x04), + ('alt+shift', 0x05), + ('ctrl+alt', 0x06), + ('ctrl+alt+shift', 0x07), + ] + for option in options: + (lbl, val) = option + self.pickModifier.Append(lbl) + self.pickModifier.SetSelection(0) + self.entryKey = wx.TextCtrl(self, -1, style=wx.TE_READONLY) + self.entryCommand = wx.TextCtrl(self, -1) +# self.entryCommand = wx.ComboBox(self, -1, wx.CB_DROPDOWN) + self.pickPreset = wx.Button(self, -1, "[v preset]") + cmdcell = wx.BoxSizer(wx.HORIZONTAL) + cmdcell.Add(self.entryCommand, 1) + cmdcell.Add(self.pickPreset) +# presetcell = wx.BoxSizer(wx.HORIZONTAL) +# self.usePreset = wx.Button(self, -1, "<- use") + #self.pickPreset = wx.Choice(self, -1) +# self.pickPreset = wx.ComboBox(self, -1, style=wx.CB_READONLY) + +# presetcell.Add(self.usePreset) +# presetcell.Add(self.pickPreset, 1, wx.EXPAND) + reviewpanel.Add(self.pickModifier, 1) + reviewpanel.Add(self.entryKey, 1, wx.EXPAND) + #reviewpanel.Add(self.entryCommand, 4, wx.EXPAND) + reviewpanel.Add(cmdcell, 4, wx.EXPAND) +# reviewpanel.Add(presetcell, 1, wx.EXPAND) + + self.presetMenu = self.make_menu(predefs.Commands) + + self.reviewBind(None) + wx.EVT_BUTTON(self, self.pickPreset.GetId(), self.guiCommandPreset) + wx.EVT_CHOICE(self, self.pickModifier.GetId(), self.guiChangeModifier) + wx.EVT_TEXT(self, self.entryCommand.GetId(), self.guiChangeCommand) + return reviewpanel + + + + def make_inpdev (self, layoutname=None, oldwidget=None): + """make_inpdev(self, layoutname=None, oldwidget=None) + +Build GUI component the reflects the keyboard(?) layout described by (or in) 'layoutname'. + +layoutname - if string, index in layouts.keyboard that specifies a layout description (i.e. a reference to). If a list, a literal layout description. +oldwidget - optional widget within which to (re)construct the layout. + +'oldwidget' is used to for changing layouts, where all the contents of self.keyb (et al.) are destroyed and rebuilt from the layout description. + +Returns new wxPanel, or oldwidget itself if provided. +""" + + if not layoutname: + layoutname = self.kbdlayout + + if type(layoutname) == list: + # Assume direct description. + layout = layoutname + else: + layout = layouts.keyboard[layoutname] + + #crumb("using layout data: %s" % layout) + + if oldwidget: + inpdev = oldwidget + # Remove all children. +# inpdev.DestroyChildren() +# self.keylookup = {} +# self.btndata = {} + for child in self.GetChildren(): + childid = child.GetId() + ksym = self.btndata.get(childid, [None,None,None,None])[2] + #crumb("%s" % self.btndata) + #crumb("DestroyChildren: wxid=%d, ksym=%s" % (childid, self.btndata[childid])) + if self.btndata.has_key(childid): + del self.btndata[childid] + if not ksym is None: + if self.keylookup.has_key(ksym): + #crumb("DestroyChildren: remove from keylookup: %s,%d" % (ksym, childid)) + self.keylookup[ksym].remove(childid) + inpdev.Freeze() + inpdev.DestroyChildren() + else: + inpdev = wx.Panel(self, -1) + inpdev.Freeze() + +# wx.StaticBox(inpdev, -1, "Input Device") + w0, h0 = 5, 28 + ncols, nrow = 160, 8 + rowidx, colidx = -1, 0 + devwidth, devheight = 1, 1 + keyid = 8 + for keyrow in layout: + colidx = 1 + for keycol in keyrow: + keydata = keycol + #crumb("keydata=%s" % keydata) + (kwidth, kheight, ksym, ktop) = keydata + if kheight == 0: + devwidth = kwidth + continue + if ktop is None: + ktop = "" + btn = None + if ktop: +# crumb("ktop='%s'" % ktop) + btn = wx.Button(inpdev, -1, ktop) +# btn = wx.ToggleButton(self, -1, ktop) +# btn.SetBackgroundColour((0xcc, 0xcc, 0xff)) +# btn.SetBackgroundColour(self.RGB_BOUND) + if ksym: + wx.EVT_ENTER_WINDOW(btn, self.guiHoverKey) + wx.EVT_LEAVE_WINDOW(btn, self.guiHoverKey) + wx.EVT_BUTTON(self, btn.GetId(), self.guiSelectKey) + btn.SetName(ksym) + btn.ksym = ksym + if not self.keylookup.has_key(ksym): + self.keylookup[ksym] = [] + self.keylookup[ksym].append(btn.GetId()) + #crumb("LOOKUP [%s] => %d" % (ksym, btn.GetId())) + self.btndata[btn.GetId()] = keydata + else: + btn.Enable(0) + keyid += 1 + else: + btn = wx.StaticText(inpdev, -1, "") + x, w = colidx * w0, kwidth * w0 + y, h = rowidx * h0, kheight * h0 + btn.SetSize((w, h)) + btn.Move((x, y)) + colidx += kwidth + rowidx += 1 + devheight += 1 + inpdev.SetSize((devwidth * w0, devheight * h0)) + inpdev.Thaw() + #crumb("finished btndata = %s" % self.btndata) + return inpdev + + inpdev0 = wx.Panel(self, -1) + #inpdev.SetParent(inpdev0) + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(wx.StaticBox(inpdev0, -1), 1, wx.EXPAND) + #wx.StaticBox(inpdev0, -1) + sizer.Add(inpdev, 1, wx.EXPAND) + inpdev0.SetSizer(sizer) + return inpdev0 + pass + + + def reviewBind (self, keyid): + """Update the reviewBind view with the specified keyid. Used for assigning command to key.""" + #crumb("reviewBind: %s" % keyid) + if keyid is None: + self.entryCommand.Enable(False) + self.entryCommand.SetValue("") + self.entryKey.Enable(False) + self.entryKey.SetValue("") + self.pickPreset.Enable(False) + self.status(None) + return + else: + self.entryCommand.Enable(True) + self.entryKey.Enable(True) + self.pickPreset.Enable(True) + btn = self.FindWindowById(keyid) + ksym = btn.ksym + if (ksym is None) or (ksym == ''): + # no symbol, use keytop label. + ksym = btn.GetLabel() + # copy keysym name + self.entryKey.SetValue(ksym) + # copy binding + #self.entryCommand.SetValue("BINDING HERE") + binding = wx.GetApp().GetBinding(ksym) + if binding is None: + self.entryCommand.SetValue("") + else: + self.entryCommand.SetValue(binding) + self.status("Binding key '%s'" % ksym) + + + def guiNop (self, evt): + """Do nothing.""" + pass + + def guiChangeModifier (self, evt): + """Change in the shift modifier, drop-down list.""" + response = evt.GetSelection() + #crumb("ChangeModifier => %s" % response) + wx.GetApp().UseModifierLevel(response) + evt.Skip() + pass + + def guiHoverKey (self, evt): + """Mouse hovers over key. Trigger flyover tooltip if enabled.""" + wxid = evt.GetId() + if self.flyover: + if wxid: + #crumb("Hovering over: %s" % wxid) + #btn = self.FindWindowById(wxid) + btndata = self.btndata[wxid] + #ksym = btn.ksym + ksym = btndata[2] + binding = wx.GetApp().GetBinding(ksym) + #crumb("flyover binding => %s" % binding) + self.show_flyover(evt.GetPosition(), binding) + else: + self.show_flyover((0,0), None) + evt.Skip() + pass + + def guiSelectKey (self, evt): + """User clicked on a key. Should update the reviewPanel.""" + #crumb("guiSelectKey") + keyid = evt.GetId() + if keyid: + obj = self.FindWindowById(keyid) + try: + ksym = obj.ksym + except: + ksym = obj.GetLable() + #crumb("selected obj [%d] = '%s'" % (keyid, obj.GetLabel())) + #crumb("selected obj [%d] = '%s'" % (keyid, ksym)) + self.SetButtonBg(self.prevkey, self.prevbg) +# if self.prevkey: +# prevbtn = self.FindWindowById(self.prevkey) +# #prevbtn.SetBackgroundColour(self.prevbg) +# prevbtn.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)) + self.prevbg = self.SetButtonBg(keyid, self.RGB_SELECT) +# btn = self.FindWindowById(keyid) +# self.prevbg = btn.GetBackgroundColour() +# btn.SetBackgroundColour(self.RGB_SELECT) + self.prevkey = keyid + + self.reviewBind(keyid) + evt.Skip() + pass + + def guiOneField (self, evt): + """Handle one-field menu item in 'Presets' popup menu.""" + #crumb("guiOneField") + wxid = evt.GetId() + menuitem = self.presetMenu.FindItemById(wxid) + lbl = menuitem.GetItemLabelText() + #crumb("Using preset %s" % lbl) + if (lbl[0] == '('): + lbl = '' + self.fill_command(lbl) + + def guiTwoField (self, evt): + """Handle two-field menu item in 'Presets' popup menu.""" + #crumb("guiTwoField") + wxid = evt.GetId() + menuitem = self.presetMenu.FindItemById(wxid) + lbl = menuitem.GetItemLabelText() + #crumb("Using preset %s" % lbl) + if (lbl[0] == '('): + lbl = '' + self.fill_command(lbl) + + def guiChangeCommand (self, evt): + """User edited the 'command' text entry, either directly by typing or by using the 'Presets' popup menu.""" + ksym = self.entryKey.GetValue() + cmd = self.entryCommand.GetValue() + wx.GetApp().SetBinding(None, ksym, cmd) + if cmd: + self.prevbg = self.RGB_BOUND + else: + self.prevbg = self.RGB_NORMAL + evt.Skip() + + def SetButtonBg (self, wxid, rgb): + """Set button background color. If rgb is None, then use normal system color.""" + btn = None + if wxid is None: + return + if type(wxid) == int: + btn = self.FindWindowById(wxid) + else: + btn = wxid + prevrgb = btn.GetBackgroundColour() + if rgb is None: + btn.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)) + else: + btn.SetBackgroundColour(rgb) + return prevrgb + + def guiCommandPreset (self, evt): + """User clicked on a button/control that opens up the 'Preset' popup menu.""" + popup = self.PopupMenu(self.presetMenu, self.pickPreset.GetPosition()) + pass + + def make_menu (self, data): + """Construct a menu from a list of lists.... + +TODO: describe menu description format. +""" + return make_menu(self, data) + + def load_config (self, path=None): + """Load configuration file. Delegate to wxApp instance.""" + wx.GetApp().LoadConfig(upath) + + def show_flyover (self, pos, binding): + """Show the flyover display. May be a tooltip window, or just showing in status bar, or something else. + +Call with binding=None to hide flyover text. +""" + if binding is None: + # Hide/remove + self.status("") + else: + self.status(binding) + + def update_all_keys (self): + """Update colors on all bind buttons, e.g. after a command was just assigned, or after loading a config file.""" + for ksym in self.keylookup: + wxidlist = self.keylookup[ksym] + for wxid in wxidlist: +# wxid = self.keylookup[ksym] + btn = self.FindWindowById(wxid) + if not btn: + continue + binding = wx.GetApp().GetBinding(ksym) + if binding is None: + # Set normal. + if btn.GetId() == self.prevkey: + self.prevbg = self.RGB_NORMAL + self.reviewBind(self.prevkey) + else: + self.SetButtonBg(wxid, self.RGB_NORMAL) + else: + #crumb("Marking bound %d[%s] (prev=[%s])" % (btn.GetId(), btn.ksym, self.prevkey)) + if btn.GetId() == self.prevkey: + self.prevbg = self.RGB_BOUND + self.reviewBind(self.prevkey) + else: + self.SetButtonBg(wxid, self.RGB_BOUND) + pass # if not binding + pass # for ksym + pass # for ksymlist + pass + + def change_layout (self, newlayoutname): + """Cause change in keyboard layout.""" + #crumb("Change layout to '%s'" % newlayoutname) + self.make_inpdev(newlayoutname, self.keyb) + self.kbdlayout = newlayoutname + self.prevkey = None + self.prevbg = None + self.reviewBind(None) + wx.GetApp().UseModifierLevel() + + def fill_command (self, cmdval): + """Paste content into the 'command' text entry (assign command to key). + +Used by the 'Presets' menu. +""" + self.entryCommand.SetValue(cmdval) + + pass + + + + + + + + +class TestPanel (wx.Panel): + """testing puposes...""" + def __init__ (self, parent, wxid): + wx.Panel.__init__(self, parent, wxid) + wx.StaticText(self, -1, "Test Panel", (30, 20)) + + + +class VegastrikeKeyBinderFrame (wx.Frame): + """Main window. Contains menu bar, status bar, and the main frame with notebook tabs. +""" + ID_FLYOVER = 1000 + ID_VIEWFUNC = 1001 + ID_REJOYSTICK = 1002 + ID_KBDLAYOUT = 1003 + + def __init__ (self, parent, wxid, title): + """Initialize object state, build GUI.""" + wx.Frame.__init__(self, parent, wxid, title) + self.build_ui() + + def status (self, msg=None): + """Set status.""" + if msg: + self.SetStatusText(msg) + else: + self.SetStatusText("") + + def build_ui (self): + """Build GUI. Delayed construction and/or call code generated by a GUI building tool (Boa Constructor).""" + #crumb("BinderFrame: init") + self.CreateStatusBar() +# self.SetStatusText("-- initialised statusbar --") + self.status("First, click on key to set binding") + + #crumb("BinderFrame: make menubar") + menubar = self.make_menubar() + self.SetMenuBar(menubar) + + topsizer = wx.BoxSizer(wx.VERTICAL) + + #crumb("BinderFrame: notebook") + nb = wx.Notebook(self) +# +# #crumb("BinderFrame: notebook page 1") + page = self.layoutpanel = VegastrikeLayoutBindPanel(nb, -1) + nb.AddPage(page, "Layout") +# page = TestPanel(nb, -1) +# nb.AddPage(page, "WTF") + #crumb("BinderFrame: notebook page 2") + # TODO: function-bind panel. +# page = self.funcpanel = VegastrikeFunctionBindPanel(nb, -1) +# nb.AddPage(page, "Function") +# +# nb.SetSelection(1) + + topsizer.Add(nb) + + #crumb("BinderFrame: munge menu") + # Updated selected layout. + currlayout = self.layoutpanel.kbdlayout + # 1. Assumes all the layout-setting items are grouped in same submenu. + firstlayoutitem = self.GetMenuBar().FindItemById(self.ID_KBDLAYOUT) + if firstlayoutitem: + #crumb("firstlayoutitem=%s" % firstlayoutitem) + # 2. Get the menu the item belongs to. Sibling items have same menuID. + layoutsubmenu = firstlayoutitem.GetMenu() + if layoutsubmenu: + #crumb("layoutsmenu=%s" % layoutsubmenu) + # 3. Search sibling items until label matches current keyboard layout. + for itemidx in xrange(0, layoutsubmenu.GetMenuItemCount()): + langitem = layoutsubmenu.FindItemByPosition(itemidx) + if langitem.GetItemLabelText() == currlayout: + # 4. Matching item - set checked. Check final one if multi-match. + #crumb("langitem = %d/%s: %s" % (itemidx, langitem, langitem.GetItemLabelText())) + langitem.Check(1) + #crumb("BinderFrame: done") + pass + + def make_legend (self): + # ??? + pass + + + def guiNop (self, evt): + """Do nothing.""" + pass + + def guiQuit (self, evt): + """Handle GUI Quit action.""" + print("Quitting") + self.Close(True) + pass + + def guiAbout (self, evt): + """Handle GUI About action.""" + #dlg = VegastrikeLayoutBindAbout(self, -1, "About %s %s" % (PACKAGE, VERSION)) + #response = dlg.ShowModal() + aboutinfo = wx.AboutDialogInfo() + if ICON: + aboutinfo.SetIcon(ICON) + aboutinfo.SetName(PACKAGE) + aboutinfo.SetVersion(VERSION) + aboutinfo.SetDescription(DESCRIPTION) + aboutinfo.SetCopyright(COPYRIGHT) + aboutinfo.SetLicence(LICENSE) + aboutinfo.SetWebSite(HOMEPAGE) + for dev in DEVELOPERS: + aboutinfo.AddDeveloper(dev) + + aboutbox = wx.AboutBox(aboutinfo) + pass + + def guiHelp (self, evt): + """Handle GUI Help action.""" + pass + + def guiNew (self, evt): + """Handle GUI File>New action.""" + pass + + def guiLoad (self, evt): + """Handle GUI File>Load action.""" + # Select a file. + title = "Open Vegastrike configuration file" + cwd = "" + fname = "" + wildcard = "|".join(["Vegastrike (*.config)|*.config", "Any (*.*)|*.*"]) + style = wx.FD_OPEN | wx.FD_CHANGE_DIR + dlg = wx.FileDialog(self, title, cwd, fname, wildcard, style) + response = dlg.ShowModal() + if response == wx.ID_OK: + upath = dlg.GetPath() + crumb("Loading %s" % upath) + self.load_config(upath) + pass + + def guiRevert (self, evt): + """Handle GUI File>Revert action.""" + pass + + def guiSave (self, evt): + """Handle GUI File>Save action.""" + upath = wx.GetApp().GetConfigName() + if upath: + self.status("Saving to '%s'" % wx.GetApp().GetConfigName()) + wx.GetApp().SyncConfig() + self.save_config(upath) + else: + self.guiSaveAs(evt) + pass + + def guiSaveAs (self, evt): + """Handle GUI File>Save As action.""" + self.status("Saving to named file...") + # Select a file. + title = "Save Vegastrike configuration file" + cwd = "" + fname = "" + wildcard = "|".join(["Vegastrike (*.config)|*.config", "Any (*.*)|*.*"]) + style = wx.FD_SAVE | wx.FD_CHANGE_DIR + dlg = wx.FileDialog(self, title, cwd, fname, wildcard, style) + response = dlg.ShowModal() + if response == wx.ID_OK: + upath = dlg.GetPath() + crumb("Saving %s" % upath) + self.save_config(upath) + else: + self.status("Save cancelled") + pass + + def guiDump (self, evt): + """Handle GUI File>Dump action; debug use.""" + wx.GetApp().DumpConfig() + + + def guiCopy (self, evt): + """Handle GUI Edit>Copy action.""" + pass + + def guiCut (self, evt): + """Handle GUI Edit>Cut action.""" + pass + + def guiPaste (self, evt): + """Handle GUI Edit>Paste action.""" + pass + + def guiPrefs (self, evt): + """Handle GUI Preferences action.""" + pass + + def guiKeylayout (self, evt): + """Handle GUI Keyboard (layout) action.""" + wxid = evt.GetId() + #crumb("guiKeylayout: %d" % wxid) + menuitem = self.GetMenuBar().FindItemById(wxid) + newlayoutname = menuitem.GetItemLabelText() + #crumb("switch to layout: %s" % newlayoutname) + self.layoutpanel.change_layout(newlayoutname) + pass + + def guiFlyover (self, evt): + """Handle GUI Flyover [toggle] action.""" + if evt.IsChecked(): + self.layoutpanel.flyover = True + self.status("Flyover enabled. Place mouse over key to view its binding.") + else: + self.layoutpanel.flyover = False + self.status("Flyover disabled.") + pass + + def make_menubar (self): + """Build menubar object. +Returns wxMenuBar. +""" + menubar = wx.MenuBar() + + # Collect names of all stored layouts. + layoutnames = [ n for n in layouts.keyboard ] + layoutnames.sort() + menudata_layouts = [] + layoutid = self.ID_KBDLAYOUT # First item only, siblings get -1. + for item in layoutnames: + #menuitemdata = ("@%s" % item, -1, self.guiKeylayout, '') + menuitemdata = ("@%s" % item, layoutid, self.guiKeylayout, '') + layoutid = -1 # yeah, it does it over and over again... + menudata_layouts.append(menuitemdata) + + menudata_layouts0 = [ + ('@en/US 101', -1, self.guiKeylayout, ''), + ('@en/US 104+deadkeys', -1, self.guiKeylayout, ''), + ('@en/US 104', -1, self.guiKeylayout, ''), + ] + +# crumb("menudata=%s" % menudata_layouts) +# crumb("menudata=%s" % menudata_layouts0) + + # item <- ( lbl, id, callback, tooltip ) + data = [ + ( '&File', + [ +# ( '&New', wx.ID_NEW, self.guiNew, 'Start with blank bindings.' ), + ( '&New', wx.ID_NEW, self.guiNop, '' ), + ( '&Load', wx.ID_OPEN, self.guiLoad, '' ), +# ( '&Revert', wx.ID_REVERT, self.guiRevert, '' ), + ( '&Revert', wx.ID_REVERT, self.guiNop, '' ), + ( '&Save', wx.ID_SAVE, self.guiSave, '' ), + ( 'Save &As', wx.ID_SAVEAS, self.guiSaveAs, '' ), +# ( 'Dump Config [debug]', -1, self.guiDump, '' ), + None, + ( '&Quit', wx.ID_EXIT, self.guiQuit, '' ), + ] ), + ( '&Edit', + [ + ( '&Copy', wx.ID_COPY, self.guiCopy, '' ), + ( 'C&ut', wx.ID_CUT, self.guiCut, '' ), + ( '&Paste', wx.ID_PASTE, self.guiPaste, '' ), + None, +# ( 'Prefere&nces', wx.ID_PREFERENCES, self.guiPrefs, '' ), + ( 'Prefere&nces', wx.ID_PREFERENCES, self.guiNop, '' ), + ] ), + ( '&View', + [ + ( '&Layouts', +# [ +# ('@en/US 101', -1, self.guiKeylayout, ''), +# ('@en/US 104+deadkeys', -1, self.guiKeylayout, ''), +# ('@en/US 104', -1, self.guiKeylayout, ''), +# ] + menudata_layouts + ), + ( 'Recheck &Joysticks', self.ID_REJOYSTICK, self.guiNop, 'Reconstruct joystick information from currently attached joysticks.' ), + ( '+&Flyover', self.ID_FLYOVER, self.guiFlyover, 'Place mouse over key to view its binding'), + None, + ( 'Change to Function &View', self.ID_VIEWFUNC, self.guiNop, 'View function-centric binding'), + ] ), + ( '&Help', + [ + ( '&About', wx.ID_ABOUT, self.guiAbout, '' ), + None, + ( '&Content', wx.ID_HELP, self.guiHelp, '' ), + ] ), + ] + for baritem in data: + ( lbl, submenu ) = baritem + submenu = self.make_menu(submenu) + menubar.Append(submenu, lbl) + + return menubar + + def make_menu (self, data): + """Build menu. +""" + return make_menu(self, data) + + def load_config (self, path=None): + """Called by File>Load menu item.""" + wx.GetApp().LoadConfig(path) + + def save_config (self, path=None): + """Called by File>Save(As) menu item(s).""" + if wx.GetApp().SaveConfig(path): + self.status("Saved to file '%s'" % path) + else: + self.status("Failed to save file '%s'" % path) + + def update_all_keys (self): + """Called by keyboard layout menu item.""" + self.layoutpanel.update_all_keys() + pass + + + + + + + + + + + +class VegastrikeKeyBinderApp (wx.App): + """wxApp instance.""" + + MODVAL_SHIFT = 1 + MODVAL_CTRL = 2 + MODVAL_ALT = 4 + + def OnInit (self): + #crumb("AppInit.") + appname = "%s %s" % (PACKAGE, VERSION) + #frame = self.frame = VegastrikeLayoutBindFrame(None, -1, appname) + frame = self.frame = VegastrikeKeyBinderFrame(None, -1, appname) + frame.SetSize((700, 600)) + frame.SetMinSize((320, 240)) + frame.Show(True) + self.SetTopWindow(frame) + + #crumb("AppInit: form bindings.") + # *** app internal state *** + # Dictionary for each modifier level (8 of them). + # Dictionary maps keysym => command. + self.bindings = [] + for i in xrange(0, 8): + self.bindings.append({}) + # Current modifier level. + self.modifier = 0 + # Current selected keyboard layout + self.layoutname = None + # Path of current loaded configuration file. + self.cfgname = None + # Currently loaded configuration data. + self.cfgdom = None + + #self.UseLayout("en/US 104") + + # Elide later + #crumb("AppInit: Load config") + self.LoadConfig("./vegastrike.config") + self.SyncConfig() + + return True + + def GetLayout (self): + """Get currently selected keyboard layout name.""" + return self.layoutname + + def UseLayout (self, layoutname): + """Change keyboard layout.""" + self.layoutname = layoutname + self.frame.layoutpanel.change_layout(layoutname) + + def GetModifierLevel (self): + """Get current shift modifier level.""" + return self.modifier + + def UseModifierLevel (self, modlevel=None): + """Change shift modifier level.""" + if not modlevel is None: + self.modifier = modlevel + #crumb("Using modifier level %d" % self.modifier) + # TODO: and do stuff... update all keys? + self.frame.update_all_keys() + pass + + def GetBinding (self, modlevel__keysym, __keysym=None): + """Get binding for specified keysym (with optionally specified shift modifier level).""" + binding = None + modlevel, keysym = 0, None + if __keysym: + # 2-arg form + modlevel = modlevel__keysym + keysym = __keysym + else: + # 1-arg form + modlevel = self.modifier + keysym = modlevel__keysym + try: + binding = self.bindings[modlevel][keysym] + except (IndexError, KeyError): + binding = None + #crumb("retrieving binding '%d:%s' => %s" % (modlevel, keysym, binding)) + return binding + + def SetBinding (self, modlevel, keysym, command): + """Set binding for keysym at specified shift modifier level.""" + # hack to handle the way Vegastrike config handles shift. +# layoutname = "en/US 101" + layoutname = self.frame.layoutpanel.kbdlayout + if modlevel is None: + modlevel = self.modifier + if keysym in layouts.unshiftmap[layoutname]: + # Shifted character. Mark 'shift'. + modlevel += self.MODVAL_SHIFT + #crumb("Unshifting %s -> %s" % (keysym, layouts.unshiftmap[layoutname][keysym])) + keysym = layouts.unshiftmap[layoutname][keysym] + + self.bindings[modlevel][keysym] = command + #crumb("/bind %d:%s '%s'" % (modlevel, keysym, command)) + +# def modattr2modlevel (self, attrstr, ksym=None): + def modattr2modlevel (self, attrstr): + """Convert modifier string in config file into modlevel value: +shift => +=1 +ctrl => +=2 +alt => +=4 +""" + modlevel = 0 + if attrstr: + if "ctrl" in attrstr: + modlevel += self.MODVAL_CTRL + if "alt" in attrstr: + modlevel += self.MODVAL_ALT + # any "shift" is implied in 'key' (e.g. shift+s => 'S') +# if ksym: +# if ksym in layouts.unshiftmap['en_US_101']: +# # Shifted character. Mark 'shift'. +# modlevel += 1 + return modlevel + + def modlevel2modattr (self, modlevel): + """Convert modlevel to modifier string: +modlevel & 1 => +'shift' ?? +modlevel & 2 => +'ctrl' +modlevel & 4 => +'alt' +""" + modarr = [] + if not modlevel: + modarr.append("none") + if modlevel & 0x02: + modarr.append("ctrl") + if modlevel & 0x04: + modarr.append("alt") + modattr = "+".join(modarr) + return modattr + + def GetCandidateAB (self, domlist, modattr, ksym, eigenattr, battr): + """Retrieve bind node based on a keysym pattern <modlevel>:<EIGENATTR>-<A>.<B> +""" + apos = ksym.find("-") + 1 + bpos = ksym.find(".") + a = int(ksym[apos:bpos]) + b = int(ksym[bpos+1:]) + # Find by matching mouse number and button number. + candidates = [ n for n in domlist if n.hasAttribute(eigenattr) and int(n.getAttribute(eigenattr)) == a and int(n.getAttribute(battr)) == b ] + # Filter out just this modlevel. + candidates = [ n for n in candidates if (n.hasAttribute("modifier") and n.getAttribute("modifier") == modattr) or ( (not n.hasAttribute("modifier")) and (modattr == "none") ) ] + if candidates: + return candidates[0] + return None # Not found. + + def GetConfigName (self): + """Get currently loaded config file name (for use with File>Save).""" + return self.cfgname + + def SyncConfig (self): + """Copy contents of active bindings (app data) into DOM tree, in preparation for saving.""" + #crumb("SyncConfig") + # Update configuration DOM with current settings. + bindingsdom = self.cfgdom.getElementsByTagName("bindings")[0] + + #crumb("bindings dump: %s" % self.bindings) + + # Scour all entries in bindings + for modlevel in xrange(0, len(self.bindings)): + modattr = self.modlevel2modattr(modlevel) + for ksym in self.bindings[modlevel]: + bound = self.bindings[modlevel][ksym] + #crumb("synchronzing %d:%s" % (modlevel, ksym)) + bindnode = None + bindnodes = self.cfgdom.getElementsByTagName("bind") + axisnodes = self.cfgdom.getElementsByTagName("axis") + if ksym.find("mouse-") == 0: + # Get those nodes that have attribute "mouse" + candidate = self.GetCandidateAB(bindnodes, modattr, ksym, "mouse", "button") + #crumb("mouse/candidates=%s" % candidate) + pass + elif ksym.find("joystick-") == 0: + candidate = self.GetCandidateAB(bindnodes, modattr, ksym, "joystick", "button") + #crumb("joystick/candidates=%s" % candidate) + pass + elif ksym.find("digital-hatswitch-") == 0: + candidate = self.GetCandidateAB(bindnodes, modattr, ksym, "digital-hatswitch", "button") + #crumb("digital-hatswitch/candidates=%s" % candidate) + pass + elif ksym.find("axis:mouse-") == 0: + candidate = self.GetCandidateAB(axisnodes, modattr, ksym, "mouse", "axis") + #crumb("axis:mouse/candidates=%s" % candidate) + elif ksym.find("axis:joystick-") == 0: + candidate = self.GetCandidateAB(axisnodes, modattr, ksym, "mouse", "axis") + #crumb("axis:joystick/candidates=%s" % candidate) + pass + else: + # Keyboard + # Find by matching dev number and button number. + keyname = ksym + + if modlevel & self.MODVAL_SHIFT: + currlayout = self.frame.layoutpanel.kbdlayout + # Get shifted keysym + keyname = layouts.shiftmap[currlayout][ksym] + #crumb("from shift1 => keyname now '%s'" % keyname) + # "shift" => "none" + emodlevel = modlevel & ~(self.MODVAL_SHIFT) # Effective modifier level. + modattr = self.modlevel2modattr(modlevel & ~(self.MODVAL_SHIFT)) + #crumb("pull binding [%s][%s]" % (modlevel, ksym)) + #bound = self.bindings[emodlevel][ksym] + bound = self.bindings[modlevel][ksym] + + eigenattr = "key" + candidates = [ n for n in bindnodes if n.hasAttribute(eigenattr) and n.getAttribute(eigenattr) == keyname ] + #crumb("Candidates@1 : %d" % len(candidates)) + # Filter out just this modlevel. + candidates = [ n for n in candidates if (n.hasAttribute("modifier") and n.getAttribute("modifier") == modattr) or ( (not n.hasAttribute("modifier")) and (modattr == "none") ) ] + #crumb("Candidates@2 : %d" % len(candidates)) + if candidates: + candidate = candidates[0] +# crumb("key/candidates[%s@%s]=%s" % (keyname, modattr, candidate)) + #crumb("key/candidates[%s@%s]=%s" % (keyname, modattr, candidate.getAttribute("command"))) + else: + candidate = None + if candidate: + if not bound: + # erase node. + #crumb("erase node '%s'" % candidate) + parentnode = candidate.parentNode + parentnode.removeChild(candidate) + candidate = None + else: + # modify node. + candidate.setAttribute("command", bound) + else: + if bound: + bindnode = self.cfgdom.createElement("bind") + attrs = { + "key": keyname, + "modifier": modattr, + "command": bound + } + for k,v in attrs.items(): + bindnode.setAttribute(k, v) + txt = "\n" + "".join([" "] * 16) + bindingsdom.appendChild(self.cfgdom.createTextNode(txt)) + bindingsdom.appendChild(bindnode) + #crumb("<bindings>.appendChild(%s)" % bindnode) + pass + pass + pass +# crumb("dump SyncConfig:") +# crumb(self.cfgdom.toprettyxml()) + pass + + def DumpConfig (self): + """Dump current bindings as DOM tree (debug save).""" + self.SyncConfig() + crumb("DumpConfig:") + crumb(self.cfgdom.toxml()) +# crumb(self.cfgdom.toprettyxml()) + + def SaveConfig (self, path=None): + """Save DOM tree to file.""" + if path: + crumb("Saving config %s" % path) + savefile = open(path, "wt") + savefile.write(self.cfgdom.toxml()) + savefile.close() + return True + return False + + def LoadConfig (self, path=None): + """Load key bindings from file.""" + if path: + crumb("Loading config %s" % path) + self.cfgname = path + self.cfgdom = xml.dom.minidom.parse(path) + try: + bindingsnode = self.cfgdom.getElementsByTagName("bindings")[0] + except IndexError: + crumb("ERROR: 'bindings' section not found (is the config file correct? Corrupt?).") + return + for childnode in bindingsnode.childNodes: + if childnode.nodeType == childnode.COMMENT_NODE: + pass + if childnode.nodeType == childnode.ELEMENT_NODE: + if childnode.tagName == 'bind': + # Digital (boolean) controls. + mod = childnode.getAttribute("modifier") + cmd = childnode.getAttribute("command") + + modlevel = self.modattr2modlevel(mod) + + if childnode.hasAttribute("key"): + # bind to keyboard key + key = childnode.getAttribute("key") +# modlevel = self.modattr2modlevel(mod, key) + self.SetBinding(modlevel, key, cmd) + pass + elif childnode.hasAttribute("mouse"): + # bind to mouse + mouse = int(childnode.getAttribute("mouse")) + if childnode.hasAttribute("button"): + button = childnode.getAttribute("button") + key = "mouse-%s.%s" % (mouse, button) + self.SetBinding(modlevel, key, cmd) + pass + elif childnode.hasAttribute("joystick"): + joystick = childnode.getAttribute("joystick") + if childnode.hasAttribute("button"): + # joystick button + button = childnode.getAttribute("button") + key = "joystick-%s.%s" % (joystick, button) + self.SetBinding(modlevel, key, cmd) + pass + elif childnode.hasAttribute("digital-hatswitch"): + # hatswitch. + hatswitch = int(childnode.getAttribute("digital-hatswitch")) + direction = childnode.getAttribute("direction") + key = "digital-hatswitch:%d.%s" % (hatswitch, direction) + self.SetBinding(modlevel, key, cmd) + pass + pass + elif childnode.hasAttribute("hatswitch"): + pass + elif childnode.tagName == 'axis': + # Analog controls. + mod = childnode.getAttribute("modifier") + #cmd = childnode.getAttribute("command") + cmd = childnode.getAttribute("name") # what? + modlevel = self.modattr2modlevel(mod) + if childnode.hasAttribute("mouse"): + if childnode.hasAttribute("axis"): + axis = childnode.getAttribute("axis") + mouse = childnode.getAttribute("mouse") + key = "axis:mouse-%s.%s" % (mouse, axis) + self.SetBinding(modlevel, key, cmd) + elif childnode.hasAttribute("joystick"): + joystick = childnode.getAttribute("joystick") + if childnode.hasAttribute("hatswitch"): + # analog hatswitch + axisnum = int(childnode.getAttribute("axis")) + devnum = int(childnode.getAttribute("devnum")) + hatnum = int(childnode.getAttribute("hatnum")) + margval = float(childnode.getAttribute("margin")) + key = "hatswitch:%d" % hatnum + self.SetBinding(modlevel, key, cmd) + for axischild in childnode.childNodes: + if axischild.nodeType == axischild.ELEMENT_NODE and axischild.tagName == 'hatswitch': + # axis hatswitch + # TODO: what do I do with this? + pass + pass + elif childnode.hasAttribute("axis"): + # regular joystick axis + axis = childnode.getAttribute("axis") + name = childnode.getAttribute("name") + key = "axis:joystick-%s.%s" % (joystick, axis) + self.SetBinding(modlevel, key, cmd) + pass + pass + pass + # Update all keys to reflect newly loaded keys. + self.UseModifierLevel(self.modifier) + pass + + + + + +def main (argv=[]): + app = VegastrikeKeyBinderApp() + #crumb("MainLoop") + app.MainLoop() + + +if __name__ == "__main__": + main() +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/predefs.py Wed Jun 29 08:32:07 2011 -0700 @@ -0,0 +1,201 @@ +#!/usr/bin/env python + + +# Keybinder pre-defined values. + + +Commands = [ + # ( Display, Stored ) + ('(none)', None), + ('Netcomm', + [ + "ChangeCommStatus", + "UpFreq", + "DownFreq", + "SwitchWebcam", + "SwitchSecured", + ] ), + ('Communication', + [ + "Cockpit::SkipMusicTrack", + "Screenshot", + "CommFormup", + "CommBreakForm", + "CommHelpMeOut", + "CommAttackTarget", + ] ), + ('Chat', + [ + "Comm1Key", + "Comm2Key", + "Comm3Key", + "Comm4Key", + "Comm5Key", + "Comm6Key", + "Comm7Key", + "Comm8Key", + "Comm9Key", + ] ), + ('Target Memory - Save', + [ + "SaveTarget1", + "SaveTarget2", + "SaveTarget3", + "SaveTarget4", + "SaveTarget5", + "SaveTarget6", + "SaveTarget7", + "SaveTarget8", + "SaveTarget9", + ] ), + ('Target Memory - Recall', + [ + "RestoreTarget1", + "RestoreTarget2", + "RestoreTarget3", + "RestoreTarget4", + "RestoreTarget5", + "RestoreTarget6", + "RestoreTarget7", + "RestoreTarget8", + "RestoreTarget9", + ] ), + ('Flight', + [ + "UpKey", + "Downkey", + "LeftKey", + "RightKey", + "RollLeftKey", + "RollRightKey", + "Joystick::Mode::InertialXYToggle", + "Joystick::Mode::InertialXZToggle", + "Joystick::Mode::RollToggle", + "Joystick::Mode::BankToggle", + ] ), + ('Throttle', + [ + "SwitchCombatMode", + "JumpKey", + "AccelKey", + "DecelKey", + "StopKey", + "StartKey", + "ABKey", + "SetVelocityRefKey", + "SetVelocityNullKey", + "ToggleWarpDrive", + "ASAP", + #("InertialToggle", "Inertial Slide (Shelton Slide)"), + ("SheltonKey", "Inertial Slide (Shelton Slide)"), + ] ), + ('Mating', + [ + "EjectKey", + "EjectCargoKey", + "DockKey", + "UnDockKey" + "RequestClearenceKey", + ] ), + ('Combat', + [ + "FireKey", + "WeapSelKey", + "ReverseWeapSelKey", + "MissileKey", + "MisSelKey", + "ReverseMisSelKey", + "TurretTargetKey", + #"TurretAIKey", + "TurretAIOn", + "TurretAIOff", + "TurretAIFireAtWill", + #"SwitchControl", + "TurretControl", + "CloakKey", + "ECMKey", + ] ), + ('Targeting', + [ + "TargetKey", + "ReverseTargetKey", + "SigTargetKey", + "ReverseSigTargetKey", + "NearestTargetKey", + "ReverseNearestTargetKey", + "SubUnitTargetKey", + "UnitTargetKey", + "ReverseUnitTargetKey", + + "NearestHostileTargetKey", + "NearestDangerousHostileKey", + "NearestFriendlyKey", + "NearestBaseKey", + "NearestPlanetKey", + "NearestJumpKey", + + "PickTargetKey", + "LockTargetKey", + ] ), + ('Camera', + [ + "Cockpit::Inside", + "Cockpit::InsideLeft", + "Cockpit::InsideRight", + "Cockpit::InsideBack", + "Cockpit::OutsideTarget", + "Cockpit::ViewTarget", + "Cockpit::PanTarget", + "Cockpit::ZoomIn", + "Cockpit::Behind", + "Cockpit::Pan", + "Cockpit::ZoomOut", + ] ), + ('Cockpit', + [ + "Cockpit::MapKey", + "Cockpit::NavScreen", + "Cockpit::SwitchLVDU", + "Cockpit::SwitchRVDU", + "Cockpit::PitchDown", + "Cockpit::PitchUp", + "Cockpit::YawLeft", + "Cockpit::YawRight", + "Cockpit::ScrollDown", + "Cockpit::ScrollUp", + "Cockpit::ScrollDown", + "Cockpit::ScrollUp", + ] ), + ('Sound', + [ + "VolumeInc", + "VolumeDec", + "MusicVolumeInc", + "MusicVolumeDec", + ] ), + ('analog', + [ + "x", + "-x", + "y", + "-y", + "z", + "-z", + "throttle", + "-throttle", + ] ), + ('Meta', + [ + "Cockpit::BringConsole", + "TextMessage", + "PauseKey", + "TimeReset", + "SuicideKey", + "Respawn", + "Cockpit::Quit", + "TimeInc", + ] ), + ('Custom', + [ + ] ), +]