Global shortcut

Linux specific forum
User avatar
mk-soft
Always Here
Always Here
Posts: 5389
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Global shortcut

Post by mk-soft »

I use a globale shortcut for my program. (ALT-C)
Have any where a sample?

Thanks
Michael
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
Guimauve
Enthusiast
Enthusiast
Posts: 742
Joined: Wed Oct 22, 2003 2:51 am
Location: Canada

Re: Global shortcut

Post by Guimauve »

Hi,

To add a Shortcut inside a program you will have to do this :

Code: Select all

AddKeyboardShortcut(#Your_window, #PB_Shortcut_ALT | #PB_ShortCut_C, #Related_Menu_Event_ID)
Best regards.
Guimauve
User avatar
mk-soft
Always Here
Always Here
Posts: 5389
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Global shortcut

Post by mk-soft »

It´s only for active application...
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
Guimauve
Enthusiast
Enthusiast
Posts: 742
Joined: Wed Oct 22, 2003 2:51 am
Location: Canada

Re: Global shortcut

Post by Guimauve »

What do you mean ?

You would like to use a Global shortcut to call another program ?

Best regards.
Guimauve
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: Global shortcut

Post by ts-soft »

A hotkey that works on the system like

Code: Select all

RegisterHotKey_(WindowID(Window), HotkeyID, fsModifiers, Keys)
in windows.
http://msdn.microsoft.com/en-us/library ... 85%29.aspx
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
remi_meier
Enthusiast
Enthusiast
Posts: 468
Joined: Sat Dec 20, 2003 6:19 pm
Location: Switzerland

Re: Global shortcut

Post by remi_meier »

You can find an example in C for a global hotkey here:
http://lists.freedesktop.org/archives/x ... 51567.html
Athlon64 3700+, 1024MB Ram, Radeon X1600
User avatar
Shardik
Addict
Addict
Posts: 1989
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: Global shortcut

Post by Shardik »

Thank you Remi for your link. My first own Google searches only found global hotkey examples
which are bound to the desktop manager. So I thought the only way to realize a solution would
have been to write separate routines for the desktop managers KDE 3 + 4, Gnome 2 + 3 + Unity,
Xfce, LXDE...

But since all distributions are currently still using XWindow (until some of them will change to
Wayland) using XWindow API functions should be the most practical approach. Therefore I tried
to convert the posted C code to PB. Currently I have tested this code to detect the newly
established hotkey <Ctrl> + <Shift> + <K> successfully in Ubuntu 11.10, Kubuntu 11.10 and Linux
Mint 12. For non-Ubuntu based distributions (or pre 11.04 Ubuntu distributions) the path to the
Xlibs has to be changed!

Code: Select all

; Converted from cheshirekow's C-Code:
; http://lists.freedesktop.org/archives/xorg/2010-October/051373.html

EnableExplicit

#ControlMask = 1 << 2
#GrabModeAsync = 1
#KeyPress = 2
#KeyPressMask = 1
#ShiftMask = 1
#XK_K = $004B

ImportC "-lX11"
  XCloseDisplay(*Display)
  XDefaultRootWindow(*Display)
  XGrabKey(*Display, KeyCode.I, Modifiers.I, GrabWindow.I, OwnerEvents.i, PointerMode.I, KeyboardMode.I)
  XKeysymToKeycode(*Display, KeySym.I)
  XNextEvent(*Display, *XEvent)
  XOpenDisplay(*Display)
  XSelectInput(*Display, Window.I, EventMask.I)
  XUngrabKey(*Display, KeyCode.I, Modifiers.I, GrabWindow.I)
EndImport

ImportC "-lxcb" : EndImport
ImportC "-lXau" : EndImport
ImportC "-lXdmcp" : EndImport

Structure XEvent
  EventType.I
  SendEvent.I
  *Display
  EventWindow.I
  RootWindow.I
  ChildWindow.I
  Time.I
  x.I
  y.I
  x_root.I
  y_root.I
  Mask.I
  KeyCode.I
  SameScreen.I
EndStructure

Define *Display
Define Event.XEvent
Define KeyCode.I
Define RootWindow.I

*Display = XOpenDisplay(0)

If *Display
  RootWindow = XDefaultRootWindow(*Display)

  If RootWindow
    KeyCode = XKeysymToKeycode(*Display, #XK_K)
    XGrabKey(*Display, KeyCode, #ControlMask | #ShiftMask, RootWindow, #False, #GrabModeAsync, #GrabModeAsync)
    XSelectInput(*Display, RootWindow, #KeyPressMask)

    Repeat
      XNextEvent(*Display, @Event)

      If Event\EventType = #KeyPress
        MessageRequester("Info", "Global Hotkey <Ctrl> + <Shift> + <K> detected and removed!")
        XUngrabKey(*Display, KeyCode, #ControlMask | #ShiftMask, RootWindow)
        Break
      EndIf
    ForEver

    XCloseDisplay(*Display)
  EndIf
EndIf
Update: I have changed the ImportC statements so that the example code should run without modification on different Linux distributions. And keep in mind that during the test the NumLock key has to be switched off because otherwise the HotKey combination won't be recognized because the NumLock key will be recognized as "pressed"!
Furthermore I had to modify the link to the C source code of the original author.
Last edited by Shardik on Thu Aug 08, 2013 11:49 am, edited 1 time in total.
User avatar
mk-soft
Always Here
Always Here
Posts: 5389
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Global shortcut

Post by mk-soft »

Thanks to all

GT :wink:
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
nikoniko
User
User
Posts: 20
Joined: Fri Nov 11, 2011 7:58 am

Re: Global shortcut

Post by nikoniko »

Hello,

I tried this code on Ubuntu 12.04 LTS x64. It is not stable working. Sometimes works, sometimes show message debugger exception.

And How to install grab for all keys? Is it possible with this code?
nikoniko
User
User
Posts: 20
Joined: Fri Nov 11, 2011 7:58 am

Re: Global shortcut

Post by nikoniko »

Oopss. Sorry. It's working only MessageRequester is still invisible or doesn't call at all.
vwidmer
Enthusiast
Enthusiast
Posts: 282
Joined: Mon Jan 20, 2014 6:32 pm

Re: Global shortcut

Post by vwidmer »

Anyone have an updated version of this? Doesnt seem to work for me.
WARNING: I dont know what I am doing! I just put stuff here and there and sometimes like magic it works. So please improve on my code and post your changes so I can learn more. TIA
User avatar
Shardik
Addict
Addict
Posts: 1989
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: Global shortcut

Post by Shardik »

vwidmer wrote:Anyone have an updated version of this? Doesnt seem to work for me.
You should always report your Linux distribution, desktop environment and whether you are using a 32 bit (x86) or 64 bit (x64) distribution.

I have modified my example from above because of some variable declaration errors for 64 bit systems and posted it below. I have tested this example with PB 5.60 on these different distributions (a plus denotes it's working and a minus that the polling loop is hanging at XNextEvent() and doesn't detect the hot key):
+ Bodhi Linux 4.1.0 x86 with Moksha
+ Debian 8.9 x86 with Xfce
+ Elementary OS 0.3.2 x86 'Freya' with Pantheon
+ Fedora 25 x86 with Gnome
+ Kubuntu 16.04 x86 with KDE
+ Linux Mint 17.3 x64 'Rosa' with Cinnamon
- Linux Mint 18.0 x86 'Sarah' with Cinnamon
- Linux Mint 18.1 x64 'Serena' with Cinnamon
+ Lubuntu 14.04 x86 with LXDE
+ Lubuntu 16.04 x86 with LXDE
- OpenSuSE 13.2 x86 with KDE
- Ubuntu 12.04 x86 with Unity
- Ubuntu 16.04 x86 with Unity
+ Xubuntu 16.04 x86 with Xfce

As I already wrote more than 5 years ago this solution is only for distributions using XWindow as window server. In Fedora 25 you have to explicitly click onto the gear wheel beneath "Sign In" and choose "Gnome on Xorg" in order to not use the default Wayland. And in Fedora 25 you also have to install the X11 developer tools:
> su root
> dnf install "X Software Development"

In OpenSuSE 13.2 you have to additionally install libXdmcp-devel using Yast2.

I currently don't know why the hot key example doesn't work in some distributions. Very interesting is the difference between Linux Mint 17.3 x64 (hot key is working) and Linux Mint 18.1 x64 (hot key doesn't work).

Code: Select all

; Converted from cheshirekow's C-Code:
; http://lists.freedesktop.org/archives/xorg/2010-October/051373.html

EnableExplicit

#ControlMask = 1 << 2
#GrabModeAsync = 1
#KeyPress = 2
#KeyPressMask = 1
#ShiftMask = 1
#XK_K = $004B

ImportC "-lX11"
  XCloseDisplay(*Display)
  XDefaultRootWindow(*Display)
  XGrabKey(*Display, KeyCode.L, Modifiers.L, GrabWindow.I, OwnerEvents.L,
    PointerMode.L, KeyboardMode.L)
  XKeysymToKeycode(*Display, KeySym.L) ; KeySyms are 29-bit integer values
                                       ; identifying characters or functions
                                       ; associated with each key
  XNextEvent(*Display, *XEvent)
  XOpenDisplay(*Display)
  XSelectInput(*Display, Window.I, EventMask.I)
  XUngrabKey(*Display, KeyCode.L, Modifiers.L, GrabWindow.I)
EndImport

ImportC "-lxcb" : EndImport
ImportC "-lXau" : EndImport
ImportC "-lXdmcp" : EndImport

Structure XEvent
  StructureUnion
    type.L
    *XAnyEvent
    *XKeyEvent
    *XButtonEvent
    *XMotionEvent
    *XCrossingEvent
    *XFocusChangeEvent
    *XExposeEvent
    *XGraphicsExposeEvent
    *XNoExposeEvent
    *XVisibilityEvent
    *XCreateWindowEvent
    *XDestroyWindowEvent
    *XUnmapEvent
    *XMapEvent
    *XMapRequestEvent
    *XReparentEvent
    *XConfigureEvent
    *XGravityEvent
    *XResizeRequestEvent
    *XConfigureRequestEvent
    *XCirculateEvent
    *XCirculateRequestEvent
    *XPropertyEvent
    *XSelectionClearEvent
    *XSelectionRequestEvent
    *XSelectionEvent
    *XColormapEvent
    *XClientMessageEvent
    *XMappingEvent
    *XErrorEvent
    *XKeymapEvent
    *XGenericEvent
    *XGenericEventCookie
    pad.L[24]
  EndStructureUnion
EndStructure

Define *Display
Define Event.XEvent
Define KeyCode.L
Define RootWindow.I

*Display = XOpenDisplay(0)

If *Display
  RootWindow = XDefaultRootWindow(*Display)

  If RootWindow
    KeyCode = XKeysymToKeycode(*Display, #XK_K)
    XGrabKey(*Display, KeyCode, #ControlMask | #ShiftMask, RootWindow, #False,
      #GrabModeAsync, #GrabModeAsync)
    XSelectInput(*Display, RootWindow, #KeyPressMask)
    MessageRequester("Info", "Global Hotkey <Ctrl> + <Shift> + <K> is enabled!")

    Repeat
      XNextEvent(*Display, @Event)
 
      Select Event\type
        Case #KeyPress
          MessageRequester("Info", "Global Hotkey <Ctrl> + <Shift> + <K> detected and removed!")
          XUngrabKey(*Display, KeyCode, #ControlMask | #ShiftMask, RootWindow)
          Break
      EndSelect
    ForEver

    XCloseDisplay(*Display)
  EndIf
EndIf
vwidmer
Enthusiast
Enthusiast
Posts: 282
Joined: Mon Jan 20, 2014 6:32 pm

Re: Global shortcut

Post by vwidmer »

Thanks for the updated code it seems to work. I am using Manjaro Linux x64 "Linux 4.9.40-1-MANJARO #1 SMP PREEMPT Fri Jul 28 09:24:52 UTC 2017 x86_64 GNU/Linux"

When I just added the debug on the key as such:

Code: Select all

; Converted from cheshirekow's C-Code:
; http://lists.freedesktop.org/archives/xorg/2010-October/051373.html
;http://www.purebasic.fr/english/viewtopic.php?f=15&t=49107&hilit=global+shortcut

EnableExplicit

#ControlMask = 1 << 2
#GrabModeAsync = 1
#KeyPress = 2
#KeyPressMask = 1
#ShiftMask = 1
#XK_K = $004B

ImportC "-lX11"
  XCloseDisplay(*Display)
  XDefaultRootWindow(*Display)
  XGrabKey(*Display, KeyCode.I, Modifiers.I, GrabWindow.I, OwnerEvents.i, PointerMode.I, KeyboardMode.I)
  XKeysymToKeycode(*Display, KeySym.I)
  XNextEvent(*Display, *XEvent)
  XOpenDisplay(*Display)
  XSelectInput(*Display, Window.I, EventMask.I)
  XUngrabKey(*Display, KeyCode.I, Modifiers.I, GrabWindow.I)
EndImport

ImportC "-lxcb" : EndImport
ImportC "-lXau" : EndImport
ImportC "-lXdmcp" : EndImport

Structure XEvent
  EventType.I
  SendEvent.I
  *Display
  EventWindow.I
  RootWindow.I
  ChildWindow.I
  Time.I
  x.I
  y.I
  x_root.I
  y_root.I
  Mask.I
  KeyCode.I
  SameScreen.I
EndStructure

Define *Display
Define Event.XEvent
Define KeyCode.I
Define RootWindow.I

*Display = XOpenDisplay(0)

If *Display
  RootWindow = XDefaultRootWindow(*Display)
  
  If RootWindow
    KeyCode = XKeysymToKeycode(*Display, #XK_K)
    XGrabKey(*Display, KeyCode, #ControlMask | #ShiftMask, RootWindow, #False, #GrabModeAsync, #GrabModeAsync)
    XSelectInput(*Display, RootWindow, #KeyPressMask)
    
    Repeat
      XNextEvent(*Display, @Event)
      Debug Event\EventType
      If Event\EventType = #KeyPress
        MessageRequester("Info", "Global Hotkey <Ctrl> + <Shift> + <K> detected and removed!")
        XUngrabKey(*Display, KeyCode, #ControlMask | #ShiftMask, RootWindow)
        Break
      EndIf
    ForEver
    
    XCloseDisplay(*Display)
  EndIf
EndIf
if I press the key combo I get a number like:

Code: Select all

140454020513794
140454020513795
I dont get anything if I press anything else I think its trig on the up and down of the key though it seems to just keep going between the two if I hold it down. It also changes everytime it runs so I am guessing its a memory address. It never gets into the #KeyPress event.

The new one appears to work fine though.

Not sure if that helps diagnose anything for the other versions of linux not working.

Thanks
WARNING: I dont know what I am doing! I just put stuff here and there and sometimes like magic it works. So please improve on my code and post your changes so I can learn more. TIA
Post Reply