Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- unit X11Keyboard;
- {=============================================================================================]
- This (for some unknown reason) is unstable (at best) for me.
- Issue:
- 1.) It writes the expected text, but only some times... After a few test-runs it seems to
- stall/freeze the application for a half a minute, and once it "unfreezes" I see a few
- of the expected characters gets written.
- 2.) If keys are pressed with no wait between them some keys seems to be skipped.
- Testsystem:
- - Linux Mint Debian - x86-64
- - Simba - x86-64
- - Running inside Oracle VirtualBox
- The very similar Python program using python xlib works fine.
- Note:
- Not completed, lacks support for other modifiers than SHIFT, for example ALT_GR
- [=============================================================================================}
- {$mode objfpc}{$H+}
- {$linklib Xtst}
- interface
- uses
- SysUtils, ctypes, x, xlib;
- function XTestFakeKeyEvent(display:PDisplay; keycode: cuint; is_press: CBool; delay: CUInt): CInt; cdecl; external;
- procedure XKeyDown(display:PDisplay; key: Word);
- procedure XKeyUp(display:PDisplay; key: Word);
- procedure KeyDown(display:PDisplay; key: String);
- procedure KeyUp(display:PDisplay; key: String);
- (*
- More keycodes exits in the keysym unit. Only the important ones are declared here.
- *)
- var
- XK_SHIFT_L,
- XK_SHIFT,
- XK_SHIFT_R,
- XK_ALT_L,
- XK_ALT,
- XK_ALT_R,
- XK_ALT_GR,
- XK_CONTROL_L,
- XK_CONTROL_R,
- XK_CONTROL,
- XK_CAPITAL,
- XK_META_L,
- XK_META_R,
- XK_SUPER_L,
- XK_SUPER_R,
- XK_HYPER_L,
- XK_HYPER_R,
- XK_LWIN,
- XK_RWIN,
- XK_HOME,
- XK_BEGIN,
- XK_END,
- XK_UP,
- XK_DOWN,
- XK_LEFT,
- XK_RIGHT,
- XK_PRIOR,
- XK_NEXT,
- XK_PGUP,
- XK_PGDN,
- XK_BACK,
- XK_TAB,
- XK_LINEFEED,
- XK_CLEAR,
- XK_RETURN,
- XK_PAUSE,
- XK_SCROLL,
- XK_SYS_REQ,
- XK_ESCAPE,
- XK_SELECT,
- XK_PRINT,
- XK_EXECUTE,
- XK_SNAPSHOT,
- XK_INSERT,
- XK_DELETE,
- XK_UNDO,
- XK_REDO,
- XK_MENU,
- XK_APPS,
- XK_FIND,
- XK_CANCEL,
- XK_HELP,
- XK_BREAK,
- XK_NUMLOCK,
- XK_MODE_SWITCH,
- XK_MODECHANGE,
- XK_SCRIPT_SWITCH,
- XK_NUMPAD_SPACE,
- XK_NUMPAD_TAB,
- XK_NUMPAD_ENTER,
- XK_NUMPAD_F1,
- XK_NUMPAD_F2,
- XK_NUMPAD_F3,
- XK_NUMPAD_F4,
- XK_NUMPAD_HOME,
- XK_NUMPAD_LEFT,
- XK_NUMPAD_UP,
- XK_NUMPAD_RIGHT,
- XK_NUMPAD_DOWN,
- XK_NUMPAD_PRIOR,
- XK_NUMPAD_PAGE_UP,
- XK_NUMPAD_NEXT,
- XK_NUMPAD_PAGE_DOWN,
- XK_NUMPAD_END,
- XK_NUMPAD_BEGIN,
- XK_NUMPAD_INSERT,
- XK_NUMPAD_DELETE,
- XK_NUMPAD_EQUAL,
- XK_NUMPAD_MUL,
- XK_NUMPAD_ADD,
- XK_NUMPAD_SEPARATOR,
- XK_NUMPAD_SUBTRACT,
- XK_NUMPAD_DECIMAL,
- XK_NUMPAD_DIVIDE,
- XK_NUMPAD0,
- XK_NUMPAD1,
- XK_NUMPAD2,
- XK_NUMPAD3,
- XK_NUMPAD4,
- XK_NUMPAD5,
- XK_NUMPAD6,
- XK_NUMPAD7,
- XK_NUMPAD8,
- XK_NUMPAD9,
- XK_SPACE,
- XK_EXCLAM,
- XK_NUMSIGN,
- XK_PERCENT,
- XK_DOLLAR,
- XK_AMPERSAND,
- XK_QUOTE,
- XK_APOSTROPHE,
- XK_PAREN_L,
- XK_PAREN_R,
- XK_ASTERISK,
- XK_EQUAL,
- XK_PLUS,
- XK_COMMA,
- XK_MINUS,
- XK_PERIOD,
- XK_FRONTSLASH,
- XK_COLON,
- XK_SEMICOLON,
- XK_LESS,
- XK_GREATER,
- XK_QUESTION,
- XK_AT,
- XK_BRACKET_L,
- XK_BRACKET_R,
- XK_BACKSLASH,
- XK_CIRCUMFLEX,
- XK_UNDERSCORE,
- XK_GRAVE,
- XK_BRACE_L,
- XK_BRACE_R,
- XK_BAR,
- XK_TILDE,
- XK_F1,
- XK_F2,
- XK_F3,
- XK_F4,
- XK_F5,
- XK_F6,
- XK_F7,
- XK_F8,
- XK_F9,
- XK_F10,
- XK_F11,
- XK_F12,
- XK_F13,
- XK_F14,
- XK_F15,
- XK_F16,
- XK_F17,
- XK_F18,
- XK_F19,
- XK_F20,
- XK_F21,
- XK_F22,
- XK_F23,
- XK_F24,
- XK_0,
- XK_1,
- XK_2,
- XK_3,
- XK_4,
- XK_5,
- XK_6,
- XK_7,
- XK_8,
- XK_9,
- XK_A,
- XK_B,
- XK_C,
- XK_D,
- XK_E,
- XK_F,
- XK_G,
- XK_H,
- XK_I,
- XK_J,
- XK_K,
- XK_L,
- XK_M,
- XK_N,
- XK_O,
- XK_P,
- XK_Q,
- XK_R,
- XK_S,
- XK_T,
- XK_U,
- XK_V,
- XK_W,
- XK_X,
- XK_Y,
- XK_Z: Word;
- implementation
- uses Classes;
- var
- SpecialXKeys: TStringList;
- Display0: PDisplay;
- function IsShifted(k:Char): Boolean;
- const SHIFTKEYS:String = '<>?:"{}|~!@#$%^&*()_+=';
- begin
- Result := (k in ['A'..'Z']) or (Pos(k, SHIFTKEYS) > 0)
- end;
- function GetKeyCode(Key:AnsiString; display:PDisplay=nil): Word;
- var
- ks: TKeySym;
- begin
- if display = nil then display := display0;
- ks := XStringToKeysym(PChar(Key));
- if (ks = NoSymbol) then
- raise Exception.Create(Format('Undefined key: "%s"', [key]));
- Result := XKeysymToKeycode(display, ks);
- end;
- function GetKeyCode(keysym:Int32; display:PDisplay=nil): Word; overload;
- begin
- if display = nil then display := display0;
- if (KeySym = NoSymbol) then
- raise Exception.Create(Format('Undefined keysym: "%d"', [KeySym]));
- Result := XKeysymToKeycode(display, keysym);
- end;
- (*
- Note all keys loaded are case sensitive.
- *)
- procedure InitializeXKeys();
- begin
- //MODIFIER KEYS
- XK_SHIFT_L := GetKeyCode('Shift_L');
- XK_SHIFT := XK_SHIFT_L;
- XK_SHIFT_R := GetKeyCode('Shift_R');
- XK_ALT_L := GetKeyCode('Alt_L');
- XK_ALT := XK_ALT_L;
- XK_ALT_R := GetKeyCode('Alt_R');
- XK_ALT_GR := GetKeyCode($FE03); //GetKeyCode('ISO_Level3_Shift');
- XK_CONTROL_L := GetKeyCode('Control_L');
- XK_CONTROL_R := GetKeyCode('Control_R');
- XK_CONTROL := XK_CONTROL_L;
- XK_CAPITAL := GetKeyCode('Caps_Lock');
- XK_META_L := GetKeyCode('Meta_L');
- XK_META_R := GetKeyCode('Meta_R');
- XK_SUPER_L := GetKeyCode('Super_L');
- XK_SUPER_R := GetKeyCode('Super_R');
- XK_HYPER_L := GetKeyCode('Hyper_L');
- XK_HYPER_R := GetKeyCode('Hyper_R');
- XK_LWIN := XK_SUPER_L;
- XK_RWIN := XK_SUPER_R;
- //CURSOR CONTROL AND MOTION
- XK_HOME := GetKeyCode('Home');
- XK_BEGIN := GetKeyCode('Begin'); //^
- XK_END := GetKeyCode('End');
- XK_UP := GetKeyCode('Up');
- XK_DOWN := GetKeyCode('Down');
- XK_LEFT := GetKeyCode('Left');
- XK_RIGHT := GetKeyCode('Right');
- XK_PRIOR := GetKeyCode('Prior');
- XK_NEXT := GetKeyCode('Next');
- XK_PGUP := GetKeyCode('Page_Up'); //^
- XK_PGDN := GetKeyCode('Page_Down');
- //MISC FUNCTIONS & TTY FUNCTION KEYS
- XK_BACK := GetKeyCode('BackSpace');
- XK_TAB := GetKeyCode('Tab');
- XK_LINEFEED := GetKeyCode('Linefeed');
- XK_CLEAR := GetKeyCode('Clear');
- XK_RETURN := GetKeyCode('Return');
- XK_PAUSE := GetKeyCode('Pause');
- XK_SCROLL := GetKeyCode('Scroll_Lock');
- XK_SYS_REQ := GetKeyCode('Sys_Req');
- XK_ESCAPE := GetKeyCode('Escape');
- XK_SELECT := GetKeyCode('Select');
- XK_PRINT := GetKeyCode('Print');
- XK_EXECUTE := GetKeyCode('Execute');
- XK_SNAPSHOT := XK_PRINT;
- XK_INSERT := GetKeyCode('Insert');
- XK_DELETE := GetKeyCode('Delete');
- XK_UNDO := GetKeyCode('Undo');
- XK_REDO := GetKeyCode('Redo');
- XK_MENU := GetKeyCode('Menu');
- XK_APPS := XK_MENU;
- XK_FIND := GetKeyCode('Find');
- XK_CANCEL := GetKeyCode('Cancel');
- XK_HELP := GetKeyCode('Help');
- XK_BREAK := GetKeyCode('Break');
- XK_NUMLOCK := GetKeyCode('Num_Lock');
- XK_MODE_SWITCH := GetKeyCode('Mode_switch');
- XK_MODECHANGE := XK_MODE_SWITCH;
- XK_SCRIPT_SWITCH := GetKeyCode('script_switch');
- //KEYPAD | NUMPAD
- XK_NUMPAD_SPACE := GetKeyCode('KP_Space');
- XK_NUMPAD_TAB := GetKeyCode('KP_Tab');
- XK_NUMPAD_ENTER := GetKeyCode('KP_Enter');
- XK_NUMPAD_F1 := GetKeyCode('KP_F1');
- XK_NUMPAD_F2 := GetKeyCode('KP_F2');
- XK_NUMPAD_F3 := GetKeyCode('KP_F3');
- XK_NUMPAD_F4 := GetKeyCode('KP_F4');
- XK_NUMPAD_HOME := GetKeyCode('KP_Home');
- XK_NUMPAD_LEFT := GetKeyCode('KP_Left');
- XK_NUMPAD_UP := GetKeyCode('KP_Up');
- XK_NUMPAD_RIGHT := GetKeyCode('KP_Right');
- XK_NUMPAD_DOWN := GetKeyCode('KP_Down');
- XK_NUMPAD_PRIOR := GetKeyCode('KP_Prior');
- XK_NUMPAD_PAGE_UP := GetKeyCode('KP_Page_Up');
- XK_NUMPAD_NEXT := GetKeyCode('KP_Next');
- XK_NUMPAD_PAGE_DOWN := GetKeyCode('KP_Page_Down');
- XK_NUMPAD_END := GetKeyCode('KP_End');
- XK_NUMPAD_BEGIN := GetKeyCode('KP_Begin');
- XK_NUMPAD_INSERT := GetKeyCode('KP_Insert');
- XK_NUMPAD_DELETE := GetKeyCode('KP_Delete');
- XK_NUMPAD_EQUAL := GetKeyCode('KP_Equal');
- XK_NUMPAD_MUL := GetKeyCode('KP_Multiply');
- XK_NUMPAD_ADD := GetKeyCode('KP_Add');
- XK_NUMPAD_SEPARATOR := GetKeyCode('KP_Separator');
- XK_NUMPAD_SUBTRACT := GetKeyCode('KP_Subtract');
- XK_NUMPAD_DECIMAL := GetKeyCode('KP_Decimal');
- XK_NUMPAD_DIVIDE := GetKeyCode('KP_Divide');
- XK_NUMPAD0 := GetKeyCode('KP_0');
- XK_NUMPAD1 := GetKeyCode('KP_1');
- XK_NUMPAD2 := GetKeyCode('KP_2');
- XK_NUMPAD3 := GetKeyCode('KP_3');
- XK_NUMPAD4 := GetKeyCode('KP_4');
- XK_NUMPAD5 := GetKeyCode('KP_5');
- XK_NUMPAD6 := GetKeyCode('KP_6');
- XK_NUMPAD7 := GetKeyCode('KP_7');
- XK_NUMPAD8 := GetKeyCode('KP_8');
- XK_NUMPAD9 := GetKeyCode('KP_9');
- //SYMBOL KEYS
- XK_SPACE := GetKeyCode('space');
- XK_EXCLAM := GetKeyCode('exclam');
- XK_NUMSIGN := GetKeyCode('numbersign');
- XK_PERCENT := GetKeyCode('percent');
- XK_DOLLAR := GetKeyCode('dollar');
- XK_AMPERSAND := GetKeyCode('ampersand');
- XK_QUOTE := GetKeyCode('quotedbl');
- XK_APOSTROPHE := GetKeyCode('apostrophe');
- XK_PAREN_L := GetKeyCode('parenleft');
- XK_PAREN_R := GetKeyCode('parenright');
- XK_ASTERISK := GetKeyCode('asterisk');
- XK_EQUAL := GetKeyCode('equal');
- XK_PLUS := GetKeyCode('plus');
- XK_COMMA := GetKeyCode('comma');
- XK_MINUS := GetKeyCode('minus');
- XK_PERIOD := GetKeyCode('period');
- XK_FRONTSLASH := GetKeyCode('slash');
- XK_COLON := GetKeyCode('colon');
- XK_SEMICOLON := GetKeyCode('semicolon');
- XK_LESS := GetKeyCode('less');
- XK_GREATER := GetKeyCode('greater');
- XK_QUESTION := GetKeyCode('question');
- XK_AT := GetKeyCode('at');
- XK_BRACKET_L := GetKeyCode('bracketleft');
- XK_BRACKET_R := GetKeyCode('bracketright');
- XK_BACKSLASH := GetKeyCode('backslash');
- XK_CIRCUMFLEX := GetKeyCode('asciicircum');
- XK_UNDERSCORE := GetKeyCode('underscore');
- XK_GRAVE := GetKeyCode('grave');
- XK_BRACE_L := GetKeyCode('braceleft');
- XK_BRACE_R := GetKeyCode('braceright');
- XK_BAR := GetKeyCode('bar');
- XK_TILDE := GetKeyCode('asciitilde');
- //FUNCTION KEYS
- XK_F1 := GetKeyCode('F1');
- XK_F2 := GetKeyCode('F2');
- XK_F3 := GetKeyCode('F3');
- XK_F4 := GetKeyCode('F4');
- XK_F5 := GetKeyCode('F5');
- XK_F6 := GetKeyCode('F6');
- XK_F7 := GetKeyCode('F7');
- XK_F8 := GetKeyCode('F8');
- XK_F9 := GetKeyCode('F9');
- XK_F10 := GetKeyCode('F10');
- XK_F11 := GetKeyCode('F11');
- XK_F12 := GetKeyCode('F12');
- XK_F13 := GetKeyCode('F13');
- XK_F14 := GetKeyCode('F14');
- XK_F15 := GetKeyCode('F15');
- XK_F16 := GetKeyCode('F16');
- XK_F17 := GetKeyCode('F17');
- XK_F18 := GetKeyCode('F18');
- XK_F19 := GetKeyCode('F19');
- XK_F20 := GetKeyCode('F20');
- XK_F21 := GetKeyCode('F21');
- XK_F22 := GetKeyCode('F22');
- XK_F23 := GetKeyCode('F23');
- XK_F24 := GetKeyCode('F24');
- //NUMBER KEYS
- XK_0 := GetKeyCode('0');
- XK_1 := GetKeyCode('1');
- XK_2 := GetKeyCode('2');
- XK_3 := GetKeyCode('3');
- XK_4 := GetKeyCode('4');
- XK_5 := GetKeyCode('5');
- XK_6 := GetKeyCode('6');
- XK_7 := GetKeyCode('7');
- XK_8 := GetKeyCode('8');
- XK_9 := GetKeyCode('9');
- //CHARACTER KEYS
- XK_A := GetKeyCode('a');
- XK_B := GetKeyCode('b');
- XK_C := GetKeyCode('c');
- XK_D := GetKeyCode('d');
- XK_E := GetKeyCode('e');
- XK_F := GetKeyCode('f');
- XK_G := GetKeyCode('g');
- XK_H := GetKeyCode('h');
- XK_I := GetKeyCode('i');
- XK_J := GetKeyCode('j');
- XK_K := GetKeyCode('k');
- XK_L := GetKeyCode('l');
- XK_M := GetKeyCode('m');
- XK_N := GetKeyCode('n');
- XK_O := GetKeyCode('o');
- XK_P := GetKeyCode('p');
- XK_Q := GetKeyCode('q');
- XK_R := GetKeyCode('r');
- XK_S := GetKeyCode('s');
- XK_T := GetKeyCode('t');
- XK_U := GetKeyCode('u');
- XK_V := GetKeyCode('v');
- XK_W := GetKeyCode('w');
- XK_X := GetKeyCode('x');
- XK_Y := GetKeyCode('y');
- XK_Z := GetKeyCode('z');
- SpecialXKeys := TStringList.Create();
- SpecialXKeys.Values[#9 ] := IntToStr(XK_TAB);
- SpecialXKeys.Values[#10] := IntToStr(XK_RETURN);
- SpecialXKeys.Values[#32] := IntToStr(XK_SPACE);
- SpecialXKeys.Values[#34] := IntToStr(XK_QUOTE);
- SpecialXKeys.Values[#39] := IntToStr(XK_APOSTROPHE);
- SpecialXKeys.Values['!'] := IntToStr(XK_EXCLAM);
- SpecialXKeys.Values['#'] := IntToStr(XK_NUMSIGN);
- SpecialXKeys.Values['%'] := IntToStr(XK_PERCENT);
- SpecialXKeys.Values['$'] := IntToStr(XK_DOLLAR);
- SpecialXKeys.Values['&'] := IntToStr(XK_AMPERSAND);
- SpecialXKeys.Values['('] := IntToStr(XK_PAREN_L);
- SpecialXKeys.Values[')'] := IntToStr(XK_PAREN_R);
- SpecialXKeys.Values['*'] := IntToStr(XK_ASTERISK);
- SpecialXKeys.Values['='] := IntToStr(XK_EQUAL);
- SpecialXKeys.Values['+'] := IntToStr(XK_PLUS);
- SpecialXKeys.Values[','] := IntToStr(XK_COMMA);
- SpecialXKeys.Values['-'] := IntToStr(XK_MINUS);
- SpecialXKeys.Values['.'] := IntToStr(XK_PERIOD);
- SpecialXKeys.Values['/'] := IntToStr(XK_FRONTSLASH);
- SpecialXKeys.Values[':'] := IntToStr(XK_COLON);
- SpecialXKeys.Values[';'] := IntToStr(XK_SEMICOLON);
- SpecialXKeys.Values['<'] := IntToStr(XK_LESS);
- SpecialXKeys.Values['>'] := IntToStr(XK_GREATER);
- SpecialXKeys.Values['?'] := IntToStr(XK_QUESTION);
- SpecialXKeys.Values['@'] := IntToStr(XK_AT);
- SpecialXKeys.Values['['] := IntToStr(XK_BRACKET_L);
- SpecialXKeys.Values[']'] := IntToStr(XK_BRACKET_R);
- SpecialXKeys.Values['\'] := IntToStr(XK_BACKSLASH);
- SpecialXKeys.Values['^'] := IntToStr(XK_CIRCUMFLEX);
- SpecialXKeys.Values['_'] := IntToStr(XK_UNDERSCORE);
- SpecialXKeys.Values['`'] := IntToStr(XK_GRAVE);
- SpecialXKeys.Values['{'] := IntToStr(XK_BRACE_L);
- SpecialXKeys.Values['|'] := IntToStr(XK_BAR);
- SpecialXKeys.Values['}'] := IntToStr(XK_BRACE_R);
- SpecialXKeys.Values['~'] := IntToStr(XK_TILDE);
- end;
- procedure XKeyDown(display:PDisplay; key: Word);
- begin
- try
- XTestFakeKeyEvent(display, key, True, 0);
- XFlush(display);
- except
- end;
- end;
- procedure XKeyUp(display:PDisplay; key: Word);
- begin
- try
- XTestFakeKeyEvent(display, key, False, 0);
- XFlush(display);
- except
- end;
- end;
- procedure KeyDown(display:PDisplay; key: String);
- var
- xk:Int32;
- specialk:String;
- begin
- if key = '' then Exit;
- if IsShifted(key[1]) then XKeyDown(display, XK_SHIFT_L); //incomplete: ISO_Level3_Shift (AltGr)
- specialk := SpecialXKeys.Values[key];
- if specialk <> '' then
- xk := StrToInt(specialk)
- else
- xk := GetKeyCode(key, display);
- XKeyDown(display, xk);
- end;
- procedure KeyUp(display:PDisplay; key: String);
- var
- xk:Int32;
- specialk:String;
- begin
- if key = '' then Exit;
- specialk := SpecialXKeys.Values[key];
- if specialk <> '' then
- xk := StrToInt(specialk)
- else
- xk := GetKeyCode(key, display);
- XKeyUp(display, xk);
- if IsShifted(key[1]) then XKeyUp(display, XK_SHIFT_L); //incomplete: ISO_Level3_Shift (AltGr)
- end;
- initialization
- display0 := XOpenDisplay(nil);
- InitializeXKeys();
- finalization
- XCloseDisplay(display0);
- end.
Add Comment
Please, Sign In to add comment