Recent

Author Topic: Getting the keys pressed in the Linux OS  (Read 6664 times)

ChPr

  • New Member
  • *
  • Posts: 48
Getting the keys pressed in the Linux OS
« on: May 21, 2018, 02:39:31 pm »
Hello everybody,

In a program, I would like to do some action when keys (like Ctrl, Alt, F1 ... F12) are pressed even if my program has not the focus.

In the Windows OS, I get this by cyclically testing the GetKeyState with a timer. It works fine.

Example :

Code: Pascal  [Select][+][-]
  1. function GetCursorState: TShiftState;
  2. begin
  3.   Result := [];
  4.   if (GetKeyState(VK_LBUTTON) and $8000) <> 0 then
  5.     Include(Result, ssLeft);
  6.   if (GetKeyState(VK_MBUTTON) and $8000) <> 0 then
  7.     Include(Result, ssMiddle);
  8.   if (GetKeyState(VK_RBUTTON) and $8000) <> 0 then
  9.     Include(Result, ssRight);
  10.   if (GetKeyState(VK_CONTROL) and $8000) <> 0 then
  11.     Include(Result, ssCtrl);
  12. end;
  13.  
  14. function GetFxKeysState: TFxKeysState;
  15. begin
  16.   Result := [];
  17.   if (GetKeyState(VK_F1) and $8000) <> 0 then
  18.     Include(Result, ssF1);
  19.   if (GetKeyState(VK_F2) and $8000) <> 0 then
  20.     Include(Result, ssF2);
  21.   if (GetKeyState(VK_F3) and $8000) <> 0 then
  22.     Include(Result, ssF3);
  23.   if (GetKeyState(VK_F4) and $8000) <> 0 then
  24.     Include(Result, ssF4);
  25. end;
  26.  
  27. procedure TFntrBase.ScruteClickTimer(Sender: TObject);
  28. var
  29.   State: TShiftState;
  30. begin
  31.   State:= GetCursorState;
  32.   if ssLeft in State) then
  33.     // do something
  34.   if ssCtrl in State then
  35.     // do something else
  36. end;
  37.  

In the Linux OS, the GetKeyState retrieve the key pressed only if my program has the focus.

Do you know if there is a way to retrieve the keys pressed in the Linux OS when the program has not the focus ?

Thank you for your help.

Pierre

Guva

  • Jr. Member
  • **
  • Posts: 82
Re: Getting the keys pressed in the Linux OS
« Reply #1 on: May 21, 2018, 06:30:44 pm »
uses Codebot.Input.hotkeys;
private
      procedure KeyNotify(Sender: TObject; Key: Word; Shift: TShiftState);

     HotkeyCapture.RegisterNotify(VK_A,[ssShift],KeyNotify)

dbannon

  • Hero Member
  • *****
  • Posts: 2786
    • tomboy-ng, a rewrite of the classic Tomboy
Re: Getting the keys pressed in the Linux OS
« Reply #2 on: May 22, 2018, 12:46:19 am »
......
In the Linux OS, the GetKeyState retrieve the key pressed only if my program has the focus.
Do you know if there is a way to retrieve the keys pressed in the Linux OS when the program has not the focus ?

Gee, I hope not. That would seem a very nasty security bug !

Davo
Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

Guva

  • Jr. Member
  • **
  • Posts: 82
Re: Getting the keys pressed in the Linux OS
« Reply #3 on: May 22, 2018, 06:11:30 am »
Everything works even if there is no focus. Does not work in daemons.

ChPr

  • New Member
  • *
  • Posts: 48
Re: Getting the keys pressed in the Linux OS
« Reply #4 on: May 22, 2018, 09:52:52 am »
... Gee, I hope not. That would seem a very nasty security bug ! ...

I am working with Ubuntu 12.04 and Lazarus 1.6 and I confirm that the problem exists.

Sincerely.

Pierre

ChPr

  • New Member
  • *
  • Posts: 48
Re: Getting the keys pressed in the Linux OS
« Reply #5 on: May 22, 2018, 09:55:22 am »
Everything works even if there is no focus ...

Not for me with Ubuntu 12.04 and Lazarus 1.6


... Does not work in daemons.

What does this mean ?

Sincerely.

Pierre

ChPr

  • New Member
  • *
  • Posts: 48
Re: Getting the keys pressed in the Linux OS
« Reply #6 on: May 22, 2018, 11:42:17 am »
uses Codebot.Input.hotkeys;
private
      procedure KeyNotify(Sender: TObject; Key: Word; Shift: TShiftState);

     HotkeyCapture.RegisterNotify(VK_A,[ssShift],KeyNotify)

Thank you for this way to get keys. It works fine even if my program has not the focus, but it does not work if I press Ctrl or Alt or Shift without any other key.

Sincerely.

Pierre

Guva

  • Jr. Member
  • **
  • Posts: 82
Re: Getting the keys pressed in the Linux OS
« Reply #7 on: May 22, 2018, 11:53:00 am »
Code: Pascal  [Select][+][-]
  1. unit mUnit;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, ExtCtrls, Process, LCLType, Dialogs,
  9.   Codebot.System,
  10.   Codebot.Graphics,
  11.   Codebot.Graphics.Types,
  12.   Codebot.Controls.Banner,
  13.   Codebot.Input.Hotkeys;
  14.  
  15. type
  16.   { TBannerForm1 }
  17.   TBannerForm1 = class(TBannerForm)
  18.     ApplProp: TApplicationProperties;
  19.     TrayIcon: TTrayIcon;
  20.     procedure FormCreate(Sender: TObject);
  21.     procedure FormDestroy(Sender: TObject);
  22.   private
  23.     LedState:Boolean;
  24.     procedure KeyNotify(Sender: TObject; Key: Word; Shift: TShiftState);
  25.   public
  26.  
  27.   end;
  28.  
  29. var
  30.   BannerForm1: TBannerForm1;
  31.   LedProcess: TProcess;
  32.  
  33. implementation
  34.  
  35. {$R *.lfm}
  36.  
  37. { TBannerForm1 }
  38.  
  39. procedure TBannerForm1.FormCreate(Sender: TObject);
  40. begin
  41.   LedState:=False;
  42.   //TrayIcon.Icon:=Application.Icon;
  43.   HotkeyCapture.RegisterNotify(VK_SCROLL,[],@KeyNotify);
  44. end;
  45.  
  46. procedure TBannerForm1.FormDestroy(Sender: TObject);
  47. begin
  48.   HotkeyCapture.UnRegisterNotify(VK_SCROLL,[]);
  49. end;
  50.  
  51. procedure TBannerForm1.KeyNotify(Sender: TObject; Key: Word; Shift: TShiftState);
  52. begin
  53.    LedProcess := TProcess.Create(nil);
  54.    LedProcess.Options:=[poWaitOnExit,poNoConsole];
  55.    LedProcess.Executable := 'xset';
  56.      If LedState then
  57.       begin
  58.        LedProcess.Parameters.Add('-led');
  59.        LedState:=false;
  60.       end else
  61.       begin
  62.       LedProcess.Parameters.Add('led');
  63.       LedState:=true;
  64.       end;
  65.     LedProcess.Parameters.Add('3');
  66.     LedProcess.Execute;
  67.     LedProcess.Free;
  68.  end;
  69.  
  70. end.
  71.  

Everything works fine only in codebot no VK_SCROLL change to your own.  Im write for hook my led keyboard.
sorry for my english. :)

Guva

  • Jr. Member
  • **
  • Posts: 82
Re: Getting the keys pressed in the Linux OS
« Reply #8 on: May 22, 2018, 12:02:44 pm »
TBannerForm1 can be changed to the usual-modal form. the main thing that would be a parent was TForm. in my example, I will use the form from the library and the form for settings ( adding automatic activation of the keyboard with sunset-sunrise)

ChPr

  • New Member
  • *
  • Posts: 48
Re: Getting the keys pressed in the Linux OS
« Reply #9 on: May 22, 2018, 12:15:40 pm »
... Everything works fine only in codebot no VK_SCROLL change to your own.  Im write for hook my led keyboard.
sorry for my english. :)

Don't worry for your english. Mine is not better (I am  french).

I tried also VK_PRINT, VK_SCROLL. they don't work alone.

Sincerely.

Pierre

Guva

  • Jr. Member
  • **
  • Posts: 82
Re: Getting the keys pressed in the Linux OS
« Reply #10 on: May 22, 2018, 12:35:34 pm »
they are not registered in Codebot.Input.Hotkeys
Code: Pascal  [Select][+][-]
  1.  VK_TAB: Result := XK_TAB;
  2.     VK_CLEAR: Result := XK_CLEAR;
  3.     VK_RETURN: Result := XK_RETURN;
  4.     VK_MENU: Result := XK_MENU;
  5.     VK_ESCAPE: Result := XK_ESCAPE;
  6.     VK_PAUSE: Result := XK_PAUSE;
  7.     VK_SPACE: Result := XK_SPACE;
  8.     VK_PRIOR: Result := XK_PRIOR;
  9.     VK_NEXT: Result := XK_NEXT;
  10.     VK_END: Result := XK_END;
  11.     VK_HOME: Result := XK_HOME;
  12.     VK_LEFT: Result := XK_LEFT;
  13.     VK_UP: Result := XK_UP;
  14.     VK_RIGHT: Result := XK_RIGHT;
  15.     VK_DOWN: Result := XK_DOWN;
  16.     VK_SELECT: Result := XK_SELECT;
  17.     VK_EXECUTE: Result := XK_EXECUTE;
  18.     VK_SNAPSHOT: Result := XK_PRINT;
  19.     VK_INSERT: Result := XK_INSERT;
  20.     VK_DELETE: Result := XK_DELETE;
  21.     VK_HELP: Result := XK_HELP;
  22.     VK_SCROLL: Result:=XK_Scroll_Lock;
  23.     VK_0: Result := XK_0;
  24.     VK_1: Result := XK_1;                          
if you need to just take from and add LCLType

here's my version with the addition of Scroll Lock
Code: Pascal  [Select][+][-]
  1. (********************************************************)
  2. (*                                                      *)
  3. (*  Codebot Pascal Library                              *)
  4. (*  http://cross.codebot.org                            *)
  5. (*  Modified October 2015                               *)
  6. (*                                                      *)
  7. (********************************************************)
  8.  
  9. { <include docs/codebot.input.hotkeys.txt> }
  10. unit Codebot.Input.Hotkeys;
  11.  
  12. {$i codebot.inc}
  13.  
  14. interface
  15.  
  16. {$if defined(linuxgtk)}
  17. uses
  18.   SysUtils, Classes, LCLType,
  19.   Codebot.System;
  20.  
  21. { THotkeyCapture }
  22.  
  23. type
  24.   TKeyNotifyEvent = procedure(Sender: TObject; Key: Word; Shift: TShiftState) of object;
  25.  
  26.   THotkeyNotify = record
  27.     Key: Word;
  28.     ShiftState: TShiftState;
  29.     Notify: TKeyNotifyEvent;
  30.   end;
  31.  
  32.   THotkeyList = TArrayList<THotkeyNotify>;
  33.  
  34.   THotkeyCapture = class
  35.   private
  36.     FList: THotkeyList;
  37.     function GetNotifier(Index: Integer): THotkeyNotify;
  38.     function GetCount: Integer;
  39.   protected
  40.     function FindHotkey(Key: Word; ShiftState: TShiftState): Integer;
  41.     procedure DoRegister(Key: Word; ShiftState: TShiftState); virtual; abstract;
  42.     procedure DoUnregister(Key: Word; ShiftState: TShiftState); virtual; abstract;
  43.     property Notifiers[Index: Integer]: THotkeyNotify read GetNotifier; default;
  44.     property Count: Integer read GetCount;
  45.   public
  46.     destructor Destroy; override;
  47.     function RegisterNotify(Key: Word; ShiftState: TShiftState; Notify: TKeyNotifyEvent): Boolean;
  48.     function UnregisterNotify(Key: Word; ShiftState: TShiftState): Boolean;
  49.   end;
  50.  
  51. { Used by THotkeyList }
  52. function HotkeyCompare(constref A, B: THotkeyNotify): Integer;
  53.  
  54. { Returns the global hotkey capture instance }
  55. function HotkeyCapture: THotkeyCapture;
  56. {$endif}
  57.  
  58. implementation
  59.  
  60. {$if defined(linuxgtk)}
  61. uses
  62.   X, XLib, Gdk2, Gdk2x, Gtk2Proc, KeySym;
  63.  
  64. { TGtk2X11HotkeyCapture
  65.  
  66.   X Key Modifiers:
  67.  
  68.   Mask        | Value | Key
  69.   ------------+-------+------------
  70.   ShiftMask   |     1 | Shift
  71.   LockMask    |     2 | Caps Lock
  72.   ControlMask |     4 | Ctrl
  73.   Mod1Mask    |     8 | Alt
  74.   Mod2Mask    |    16 | Num Lock
  75.   Mod3Mask    |    32 | Scroll Lock
  76.   Mod4Mask    |    64 | Windows }
  77.  
  78. type
  79.   TGtk2X11HotkeyCapture = class(THotkeyCapture)
  80.   private
  81.     FRoot: PGdkWindow;
  82.     FDisplay: PDisplay;
  83.   protected
  84.     procedure DoRegister(Key: Word; ShiftState: TShiftState); override;
  85.     procedure DoUnregister(Key: Word; ShiftState: TShiftState); override;
  86.   public
  87.     constructor Create;
  88.   end;
  89.  
  90.   THotkeyCaptureImpl = TGtk2X11HotkeyCapture;
  91.  
  92. const
  93.   AltMask = Mod1Mask;
  94.   SuperMask = Mod4Mask;
  95.   { TODO: Check on the reason for this mask }
  96.   // ModifiersMask = ShiftMask or AltMask or ControlMask or SuperMask;
  97.   CapLock = LockMask;
  98.   NumLock = Mod2Mask;
  99.   NotLock = Integer(not (CapLock or NumLock));
  100.  
  101. function ShiftToMod(ShiftState: TShiftState): Integer;
  102. begin
  103.   Result := 0;
  104.   if ssShift in ShiftState then
  105.     Result := Result or ShiftMask;
  106.   if ssAlt in ShiftState then
  107.     Result := Result or AltMask;
  108.   if ssCtrl in ShiftState then
  109.     Result := Result or ControlMask;
  110.   if ssSuper in ShiftState then
  111.     Result := Result or SuperMask;
  112. end;
  113.  
  114. function ModToShift(Modifiers: Integer): TShiftState;
  115. begin
  116.   Result := [];
  117.   if ShiftMask and Modifiers > 0 then
  118.     Include(Result, ssShift);
  119.   if AltMask and Modifiers > 0 then
  120.     Include(Result, ssAlt);
  121.   if ControlMask and Modifiers > 0 then
  122.     Include(Result, ssCtrl);
  123.   if SuperMask and Modifiers > 0 then
  124.     Include(Result, ssSuper);
  125. end;
  126.  
  127. function KeyToSym(Key: Word): TKeySym;
  128. begin
  129.   case Key of
  130.     VK_TAB: Result := XK_TAB;
  131.     VK_CLEAR: Result := XK_CLEAR;
  132.     VK_RETURN: Result := XK_RETURN;
  133.     VK_MENU: Result := XK_MENU;
  134.     VK_ESCAPE: Result := XK_ESCAPE;
  135.     VK_PAUSE: Result := XK_PAUSE;
  136.     VK_SPACE: Result := XK_SPACE;
  137.     VK_PRIOR: Result := XK_PRIOR;
  138.     VK_NEXT: Result := XK_NEXT;
  139.     VK_END: Result := XK_END;
  140.     VK_HOME: Result := XK_HOME;
  141.     VK_LEFT: Result := XK_LEFT;
  142.     VK_UP: Result := XK_UP;
  143.     VK_RIGHT: Result := XK_RIGHT;
  144.     VK_DOWN: Result := XK_DOWN;
  145.     VK_SELECT: Result := XK_SELECT;
  146.     VK_EXECUTE: Result := XK_EXECUTE;
  147.     VK_SNAPSHOT: Result := XK_PRINT;
  148.     VK_INSERT: Result := XK_INSERT;
  149.     VK_DELETE: Result := XK_DELETE;
  150.     VK_HELP: Result := XK_HELP;
  151.     VK_SCROLL: Result:=XK_Scroll_Lock; //addet
  152.     VK_0: Result := XK_0;
  153.     VK_1: Result := XK_1;
  154.     VK_2: Result := XK_2;
  155.     VK_3: Result := XK_3;
  156.     VK_4: Result := XK_4;
  157.     VK_5: Result := XK_5;
  158.     VK_6: Result := XK_6;
  159.     VK_7: Result := XK_7;
  160.     VK_8: Result := XK_8;
  161.     VK_9: Result := XK_9;
  162.     VK_A: Result := XK_A;
  163.     VK_B: Result := XK_B;
  164.     VK_C: Result := XK_C;
  165.     VK_D: Result := XK_D;
  166.     VK_E: Result := XK_E;
  167.     VK_F: Result := XK_F;
  168.     VK_G: Result := XK_G;
  169.     VK_H: Result := XK_H;
  170.     VK_I: Result := XK_I;
  171.     VK_J: Result := XK_J;
  172.     VK_K: Result := XK_K;
  173.     VK_L: Result := XK_L;
  174.     VK_M: Result := XK_M;
  175.     VK_N: Result := XK_N;
  176.     VK_O: Result := XK_O;
  177.     VK_P: Result := XK_P;
  178.     VK_Q: Result := XK_Q;
  179.     VK_R: Result := XK_R;
  180.     VK_S: Result := XK_S;
  181.     VK_T: Result := XK_T;
  182.     VK_U: Result := XK_U;
  183.     VK_V: Result := XK_V;
  184.     VK_W: Result := XK_W;
  185.     VK_X: Result := XK_X;
  186.     VK_Y: Result := XK_Y;
  187.     VK_Z: Result := XK_Z;
  188.     VK_NUMPAD0: Result := XK_KP_0;
  189.     VK_NUMPAD1: Result := XK_KP_1;
  190.     VK_NUMPAD2: Result := XK_KP_2;
  191.     VK_NUMPAD3: Result := XK_KP_3;
  192.     VK_NUMPAD4: Result := XK_KP_4;
  193.     VK_NUMPAD5: Result := XK_KP_5;
  194.     VK_NUMPAD6: Result := XK_KP_6;
  195.     VK_NUMPAD7: Result := XK_KP_7;
  196.     VK_NUMPAD8: Result := XK_KP_8;
  197.     VK_NUMPAD9: Result := XK_KP_9;
  198.     VK_MULTIPLY: Result := XK_KP_MULTIPLY;
  199.     VK_ADD: Result := XK_KP_ADD;
  200.     VK_SEPARATOR: Result := XK_KP_SEPARATOR;
  201.     VK_SUBTRACT: Result := XK_KP_SUBTRACT;
  202.     VK_DECIMAL: Result := XK_KP_DECIMAL;
  203.     VK_DIVIDE: Result := XK_KP_DIVIDE;
  204.     VK_F1: Result := XK_F1;
  205.     VK_F2: Result := XK_F2;
  206.     VK_F3: Result := XK_F3;
  207.     VK_F4: Result := XK_F4;
  208.     VK_F5: Result := XK_F5;
  209.     VK_F6: Result := XK_F6;
  210.     VK_F7: Result := XK_F7;
  211.     VK_F8: Result := XK_F8;
  212.     VK_F9: Result := XK_F9;
  213.     VK_F10: Result := XK_F10;
  214.     VK_F11: Result := XK_F11;
  215.     VK_F12: Result := XK_F12;
  216.     VK_LCL_EQUAL: Result := XK_EQUAL;
  217.     VK_LCL_COMMA: Result := XK_COMMA;
  218.     VK_LCL_POINT: Result := XK_PERIOD;
  219.     VK_LCL_SLASH: Result := XK_SLASH;
  220.     VK_LCL_SEMI_COMMA: Result := XK_SEMICOLON;
  221.     VK_LCL_MINUS: Result := XK_MINUS;
  222.     VK_LCL_OPEN_BRAKET: Result := XK_BRACKETLEFT;
  223.     VK_LCL_CLOSE_BRAKET: Result := XK_BRACKETRIGHT;
  224.     VK_LCL_BACKSLASH: Result := XK_BACKSLASH;
  225.     VK_LCL_TILDE: Result := XK_GRAVE;
  226.     VK_LCL_QUOTE: Result := XK_SINGLELOWQUOTEMARK;
  227.   else
  228.     Result := 0;
  229.   end;
  230. end;
  231.  
  232. function SymToKey(Sym: TKeySym): Word;
  233. begin
  234.   case Sym of
  235.     XK_TAB: Result := VK_TAB;
  236.     XK_CLEAR: Result := VK_CLEAR;
  237.     XK_RETURN: Result := VK_RETURN;
  238.     XK_MENU: Result := VK_MENU;
  239.     XK_ESCAPE: Result := VK_ESCAPE;
  240.     XK_PAUSE: Result := VK_PAUSE;
  241.     XK_SPACE: Result := VK_SPACE;
  242.     XK_PRIOR: Result := VK_PRIOR;
  243.     XK_NEXT: Result := VK_NEXT;
  244.     XK_END: Result := VK_END;
  245.     XK_HOME: Result := VK_HOME;
  246.     XK_LEFT: Result := VK_LEFT;
  247.     XK_UP: Result := VK_UP;
  248.     XK_RIGHT: Result := VK_RIGHT;
  249.     XK_DOWN: Result := VK_DOWN;
  250.     XK_SELECT: Result := VK_SELECT;
  251.     XK_EXECUTE: Result := VK_EXECUTE;
  252.     XK_PRINT: Result := VK_SNAPSHOT;
  253.     XK_INSERT: Result := VK_INSERT;
  254.     XK_DELETE: Result := VK_DELETE;
  255.     XK_HELP: Result := VK_HELP;
  256.     XK_Scroll_Lock: Result:=VK_SCROLL; //addet
  257.     XK_0: Result := VK_0;
  258.     XK_1: Result := VK_1;
  259.     XK_2: Result := VK_2;
  260.     XK_3: Result := VK_3;
  261.     XK_4: Result := VK_4;
  262.     XK_5: Result := VK_5;
  263.     XK_6: Result := VK_6;
  264.     XK_7: Result := VK_7;
  265.     XK_8: Result := VK_8;
  266.     XK_9: Result := VK_9;
  267.     XK_A: Result := VK_A;
  268.     XK_B: Result := VK_B;
  269.     XK_C: Result := VK_C;
  270.     XK_D: Result := VK_D;
  271.     XK_E: Result := VK_E;
  272.     XK_F: Result := VK_F;
  273.     XK_G: Result := VK_G;
  274.     XK_H: Result := VK_H;
  275.     XK_I: Result := VK_I;
  276.     XK_J: Result := VK_J;
  277.     XK_K: Result := VK_K;
  278.     XK_L: Result := VK_L;
  279.     XK_M: Result := VK_M;
  280.     XK_N: Result := VK_N;
  281.     XK_O: Result := VK_O;
  282.     XK_P: Result := VK_P;
  283.     XK_Q: Result := VK_Q;
  284.     XK_R: Result := VK_R;
  285.     XK_S: Result := VK_S;
  286.     XK_T: Result := VK_T;
  287.     XK_U: Result := VK_U;
  288.     XK_V: Result := VK_V;
  289.     XK_W: Result := VK_W;
  290.     XK_X: Result := VK_X;
  291.     XK_Y: Result := VK_Y;
  292.     XK_Z: Result := VK_Z;
  293.     XK_KP_0: Result := VK_NUMPAD0;
  294.     XK_KP_1: Result := VK_NUMPAD1;
  295.     XK_KP_2: Result := VK_NUMPAD2;
  296.     XK_KP_3: Result := VK_NUMPAD3;
  297.     XK_KP_4: Result := VK_NUMPAD4;
  298.     XK_KP_5: Result := VK_NUMPAD5;
  299.     XK_KP_6: Result := VK_NUMPAD6;
  300.     XK_KP_7: Result := VK_NUMPAD7;
  301.     XK_KP_8: Result := VK_NUMPAD8;
  302.     XK_KP_9: Result := VK_NUMPAD9;
  303.     XK_KP_MULTIPLY: Result := VK_MULTIPLY;
  304.     XK_KP_ADD: Result := VK_ADD;
  305.     XK_KP_SEPARATOR: Result := VK_SEPARATOR;
  306.     XK_KP_SUBTRACT: Result := VK_SUBTRACT;
  307.     XK_KP_DECIMAL: Result := VK_DECIMAL;
  308.     XK_KP_DIVIDE: Result := VK_DIVIDE;
  309.     XK_F1: Result := VK_F1;
  310.     XK_F2: Result := VK_F2;
  311.     XK_F3: Result := VK_F3;
  312.     XK_F4: Result := VK_F4;
  313.     XK_F5: Result := VK_F5;
  314.     XK_F6: Result := VK_F6;
  315.     XK_F7: Result := VK_F7;
  316.     XK_F8: Result := VK_F8;
  317.     XK_F9: Result := VK_F9;
  318.     XK_F10: Result := VK_F10;
  319.     XK_F11: Result := VK_F11;
  320.     XK_F12: Result := VK_F12;
  321.     XK_EQUAL: Result := VK_LCL_EQUAL;
  322.     XK_COMMA: Result := VK_LCL_COMMA;
  323.     XK_PERIOD: Result := VK_LCL_POINT;
  324.     XK_SLASH: Result := VK_LCL_SLASH;
  325.     XK_SEMICOLON: Result := VK_LCL_SEMI_COMMA;
  326.     XK_MINUS: Result := VK_LCL_MINUS;
  327.     XK_BRACKETLEFT: Result := VK_LCL_OPEN_BRAKET;
  328.     XK_BRACKETRIGHT: Result := VK_LCL_CLOSE_BRAKET;
  329.     XK_BACKSLASH: Result := VK_LCL_BACKSLASH;
  330.     XK_GRAVE: Result := VK_LCL_TILDE;
  331.     XK_SINGLELOWQUOTEMARK: Result := VK_LCL_QUOTE;
  332.   else
  333.     Result := 0;
  334.   end;
  335. end;
  336.  
  337. function FilterKeys(AnyEvent: PXAnyEvent; Event: PGdkEvent; Data: Pointer): TGdkFilterReturn; cdecl;
  338. var
  339.   Capture: TGtk2X11HotkeyCapture absolute Data;
  340.   KeyEvent: PXKeyEvent absolute AnyEvent;
  341.   Sym: TKeySym;
  342.   Key: Word;
  343.   ShiftState: TShiftState;
  344.   H: THotkeyNotify;
  345.   I: Integer;
  346. begin
  347.   if AnyEvent._type <> KeyPress then
  348.     Exit(GDK_FILTER_CONTINUE);
  349.   Sym := XKeycodeToKeysym(Capture.FDisplay, KeyEvent.keycode, 0);
  350.   Key := SymToKey(Sym);
  351.   ShiftState := ModToShift(KeyEvent.state);
  352.   I := Capture.FindHotkey(Key, ShiftState);
  353.   if I > -1 then
  354.   begin
  355.     H := Capture[I];
  356.     if Assigned(H.Notify) then
  357.       H.Notify(Capture, Key, ShiftState);
  358.     Result := GDK_FILTER_REMOVE;
  359.   end
  360.   else
  361.     Result := GDK_FILTER_CONTINUE;
  362. end;
  363.  
  364. constructor TGtk2X11HotkeyCapture.Create;
  365.  
  366. begin
  367.   inherited Create;
  368.   FRoot := gdk_get_default_root_window;
  369.   FDisplay := gdk_x11_get_default_xdisplay;
  370.   //GDK_WINDOW_XDISPLAY(FRoot);
  371. end;
  372.  
  373. procedure TGtk2X11HotkeyCapture.DoRegister(Key: Word; ShiftState: TShiftState);
  374.  
  375.   procedure CaptureKey(Display: PDisplay; KeyCode: LongWord; Modifier: LongWord; Window: TWindow);
  376.   begin
  377.     { Capture keys without cap or num lock }
  378.     XGrabKey(Display, KeyCode, Modifier and NotLock, Window, 1, GrabModeAsync, GrabModeAsync);
  379.     { Capture keys with cap lock }
  380.     XGrabKey(Display, KeyCode, Modifier or CapLock, Window, 1, GrabModeAsync, GrabModeAsync);
  381.     { Capture keys with num lock }
  382.     XGrabKey(Display, KeyCode, Modifier or NumLock, Window, 1, GrabModeAsync, GrabModeAsync);
  383.     { Capture keys with cap or num lock }
  384.     XGrabKey(Display, KeyCode, Modifier or CapLock or NumLock, Window, 1, GrabModeAsync, GrabModeAsync);
  385.   end;
  386.  
  387. var
  388.   Modifier: LongWord;
  389.   KeySym, ShiftSym: TKeySym;
  390.   KeyCode: LongWord;
  391.   Window: TWindow;
  392. begin
  393.   Modifier := ShiftToMod(ShiftState);
  394.   KeySym := KeyToSym(Key);
  395.   KeyCode := XKeysymToKeycode(FDisplay, KeySym);
  396.   Window := gdk_x11_drawable_get_xid(FRoot);
  397.   CaptureKey(FDisplay, KeyCode, Modifier, Window);
  398.   ShiftSym := XKeycodeToKeysym(FDisplay, KeyCode, 1);
  399.   if KeySym <> ShiftSym then
  400.   begin
  401.     KeyCode := XKeysymToKeycode(FDisplay, ShiftSym);
  402.     CaptureKey(FDisplay, KeyCode, Modifier, Window);
  403.   end;
  404.   if Count = 0 then
  405.     gdk_window_add_filter(FRoot, @FilterKeys, Self)
  406. end;
  407.  
  408. procedure TGtk2X11HotkeyCapture.DoUnregister(Key: Word; ShiftState: TShiftState);
  409.  
  410.   procedure ReleaseKey(Display: PDisplay; KeyCode: LongWord; Modifier: LongWord; Window: TWindow);
  411.   begin
  412.     { See comments in CaptureKey }
  413.     XUngrabKey(Display, KeyCode, Modifier and NotLock, Window);
  414.     XUngrabKey(Display, KeyCode, Modifier or CapLock, Window);
  415.     XUngrabKey(Display, KeyCode, Modifier or NumLock, Window);
  416.     XUngrabKey(Display, KeyCode, Modifier or CapLock or NumLock, Window);
  417.   end;
  418.  
  419. var
  420.   Modifier: LongWord;
  421.   KeySym, ShiftSym: TKeySym;
  422.   KeyCode: LongWord;
  423.   Window: TWindow;
  424. begin
  425.   Modifier := ShiftToMod(ShiftState);
  426.   KeySym := KeyToSym(Key);
  427.   KeyCode := XKeysymToKeycode(FDisplay, KeySym);
  428.   Window := gdk_x11_drawable_get_xid(FRoot);
  429.   ReleaseKey(FDisplay, KeyCode, Modifier, Window);
  430.   ShiftSym := XKeycodeToKeysym(FDisplay, KeyCode, 1);
  431.   if KeySym <> ShiftSym then
  432.   begin
  433.     KeyCode := XKeysymToKeycode(FDisplay, ShiftSym);
  434.     ReleaseKey(FDisplay, KeyCode, Modifier, Window);
  435.   end;
  436.   if Count = 0 then
  437.     gdk_window_remove_filter(FRoot, @FilterKeys, Self);
  438. end;
  439.  
  440. function IsKeyValid(Key: Word): Boolean;
  441. begin
  442.   case Key of
  443.     VK_TAB: Result := True;
  444.     VK_CLEAR: Result := True;
  445.     VK_RETURN: Result := True;
  446.     VK_MENU: Result := True;
  447.     VK_ESCAPE: Result := True;
  448.     VK_PAUSE: Result := True;
  449.     VK_SPACE: Result := True;
  450.     VK_PRIOR: Result := True;
  451.     VK_NEXT: Result := True;
  452.     VK_END: Result := True;
  453.     VK_HOME: Result := True;
  454.     VK_LEFT: Result := True;
  455.     VK_UP: Result := True;
  456.     VK_RIGHT: Result := True;
  457.     VK_DOWN: Result := True;
  458.     VK_SELECT: Result := True;
  459.     VK_EXECUTE: Result := True;
  460.     VK_SNAPSHOT: Result := True;
  461.     VK_INSERT: Result := True;
  462.     VK_DELETE: Result := True;
  463.     VK_HELP: Result := True;
  464.     VK_SCROLL: Result:=True;//addet
  465.     VK_0: Result := True;
  466.     VK_1: Result := True;
  467.     VK_2: Result := True;
  468.     VK_3: Result := True;
  469.     VK_4: Result := True;
  470.     VK_5: Result := True;
  471.     VK_6: Result := True;
  472.     VK_7: Result := True;
  473.     VK_8: Result := True;
  474.     VK_9: Result := True;
  475.     VK_A: Result := True;
  476.     VK_B: Result := True;
  477.     VK_C: Result := True;
  478.     VK_D: Result := True;
  479.     VK_E: Result := True;
  480.     VK_F: Result := True;
  481.     VK_G: Result := True;
  482.     VK_H: Result := True;
  483.     VK_I: Result := True;
  484.     VK_J: Result := True;
  485.     VK_K: Result := True;
  486.     VK_L: Result := True;
  487.     VK_M: Result := True;
  488.     VK_N: Result := True;
  489.     VK_O: Result := True;
  490.     VK_P: Result := True;
  491.     VK_Q: Result := True;
  492.     VK_R: Result := True;
  493.     VK_S: Result := True;
  494.     VK_T: Result := True;
  495.     VK_U: Result := True;
  496.     VK_V: Result := True;
  497.     VK_W: Result := True;
  498.     VK_X: Result := True;
  499.     VK_Y: Result := True;
  500.     VK_Z: Result := True;
  501.     VK_NUMPAD0: Result := True;
  502.     VK_NUMPAD1: Result := True;
  503.     VK_NUMPAD2: Result := True;
  504.     VK_NUMPAD3: Result := True;
  505.     VK_NUMPAD4: Result := True;
  506.     VK_NUMPAD5: Result := True;
  507.     VK_NUMPAD6: Result := True;
  508.     VK_NUMPAD7: Result := True;
  509.     VK_NUMPAD8: Result := True;
  510.     VK_NUMPAD9: Result := True;
  511.     VK_MULTIPLY: Result := True;
  512.     VK_ADD: Result := True;
  513.     VK_SEPARATOR: Result := True;
  514.     VK_SUBTRACT: Result := True;
  515.     VK_DECIMAL: Result := True;
  516.     VK_DIVIDE: Result := True;
  517.     VK_F1: Result := True;
  518.     VK_F2: Result := True;
  519.     VK_F3: Result := True;
  520.     VK_F4: Result := True;
  521.     VK_F5: Result := True;
  522.     VK_F6: Result := True;
  523.     VK_F7: Result := True;
  524.     VK_F8: Result := True;
  525.     VK_F9: Result := True;
  526.     VK_F10: Result := True;
  527.     VK_F11: Result := True;
  528.     VK_F12: Result := True;
  529.     VK_LCL_EQUAL: Result := True;
  530.     VK_LCL_COMMA: Result := True;
  531.     VK_LCL_POINT: Result := True;
  532.     VK_LCL_SLASH: Result := True;
  533.     VK_LCL_SEMI_COMMA: Result := True;
  534.     VK_LCL_MINUS: Result := True;
  535.     VK_LCL_OPEN_BRAKET: Result := True;
  536.     VK_LCL_CLOSE_BRAKET: Result := True;
  537.     VK_LCL_BACKSLASH: Result := True;
  538.     VK_LCL_TILDE: Result := True;
  539.     VK_LCL_QUOTE: Result := True;
  540.   else
  541.     Result := False;
  542.   end;
  543. end;
  544.  
  545. destructor THotkeyCapture.Destroy;
  546. var
  547.   H: THotkeyNotify;
  548. begin
  549.   while Count > 0 do
  550.   begin
  551.     H := Notifiers[Count - 1];
  552.     UnregisterNotify(H.Key, H.ShiftState);
  553.   end;
  554.   inherited Destroy;
  555. end;
  556.  
  557. function THotkeyCapture.GetNotifier(Index: Integer): THotkeyNotify;
  558. begin
  559.   Result := FList[Index];
  560. end;
  561.  
  562. function THotkeyCapture.GetCount: Integer;
  563. begin
  564.   Result := FList.Length;
  565. end;
  566.  
  567. function HotkeyCompare(constref A, B: THotkeyNotify): Integer;
  568. begin
  569.   Result := A.Key - B.Key;
  570.   if Result <> 0 then
  571.     Exit;
  572.   Result := LongInt(A.ShiftState) - LongInt(B.ShiftState);
  573. end;
  574.  
  575. function THotkeyCapture.FindHotkey(Key: Word; ShiftState: TShiftState): Integer;
  576. var
  577.   Item: THotkeyNotify;
  578. begin
  579.   Item.Key := Key;
  580.   Item.ShiftState := ShiftState;
  581.   Item.Notify := nil;
  582.   Result := FList.IndexOf(Item);
  583. end;
  584.  
  585. function THotkeyCapture.RegisterNotify(Key: Word; ShiftState: TShiftState; Notify: TKeyNotifyEvent): Boolean;
  586. var
  587.   H: THotkeyNotify;
  588.   I: Integer;
  589. begin
  590.   if not IsKeyValid(Key) then
  591.     Exit(False);
  592.   I := FindHotkey(Key, ShiftState);
  593.   Result := I < 0;
  594.   if Result then
  595.   begin
  596.     DoRegister(Key, ShiftState);
  597.     { Add items to the list of registered hotkeys after DoRegister }
  598.     H.Key := Key;
  599.     H.ShiftState := ShiftState;
  600.     H.Notify := Notify;
  601.     FList.Push(H);
  602.   end;
  603. end;
  604.  
  605. function THotkeyCapture.UnregisterNotify(Key: Word; ShiftState: TShiftState): Boolean;
  606. var
  607.   I: Integer;
  608. begin
  609.   if not IsKeyValid(Key) then
  610.     Exit(False);
  611.   I := FindHotkey(Key, ShiftState);
  612.   Result := I > -1;
  613.   if Result then
  614.   begin
  615.     { Remove items from the list of registered hotkeys before DoUnregister }
  616.     FList.Delete(I);
  617.     DoUnregister(Key, ShiftState);
  618.   end;
  619. end;
  620.  
  621. var
  622.   InternalCapture: TObject;
  623.  
  624.  
  625. function HotkeyCapture: THotkeyCapture;
  626. begin
  627.   if InternalCapture = nil then
  628.     InternalCapture := THotkeyCaptureImpl.Create;
  629.   Result := THotkeyCapture(InternalCapture);
  630. end;
  631.  
  632. initialization
  633.  
  634. InternalCapture := nil;
  635.   THotkeyList.DefaultCompare := HotkeyCompare;
  636.  
  637. finalization
  638.   InternalCapture.Free;
  639. {$endif}
  640. end.
  641.  
  642.  

Guva

  • Jr. Member
  • **
  • Posts: 82
Re: Getting the keys pressed in the Linux OS
« Reply #11 on: May 22, 2018, 12:45:19 pm »
Example of crosscodebot key hook

Guva

  • Jr. Member
  • **
  • Posts: 82
Re: Getting the keys pressed in the Linux OS
« Reply #12 on: May 22, 2018, 12:55:45 pm »
is it possible to implement it under daemon(service)???? let's think.

ChPr

  • New Member
  • *
  • Posts: 48
Re: Getting the keys pressed in the Linux OS
« Reply #13 on: May 22, 2018, 01:58:06 pm »
Example of crosscodebot key hook

In the Codebot.Input.HohKeys unit, I have added a line about CONTROL, each time you have added one about SCROLL and I have tested it : It works fine  :) . So I thank you very much for this solution.

Sincerely.

Pierre

 

TinyPortal © 2005-2018