Monday, April 22, 2013

How To Bind Global HotKeys to a WINE Program under Linux


Have you ever installed a Windows program in Linux under WINE, only to discover that it doesn’t bind system wide hot-keys anymore? HTG has the work around you’ve been looking for.
Image by djeucalyptus

Overview

Every one who has even thought of the idea of switching to Linux, has probably very quickly encounter the problem that there is this one Windows app that you NEED to function. We’ve already shown you that you can accomplish this using WINE.
For this writer, the application was a Text-To-Speech application which utilizes the Microsoft SAPI4 engine. Installing the program under WINE was a breeze, however upon completion I’ve quickly found that the hot-keys used to trigger the various actions of the program (start reading, stop reading, etc’) did not function and that this is a known problem with WINE.
I’m glad to say that after eons of searching, I’ve finally found the solution in the form of a GNU utility which can manipulate the X.org interface using native functions. While not the only one of its kind, xdotool is the one which was the easiest to get working and was already in the Ubuntu/Mint repositories.

xdotool

The xdotool program can do many window related tasks from the CLI, with that said, the only two we are going to utilize are “search” and “key”. The “search” function does just that, searches for a window/s ID according to parameters you set for it. The “key” function enables you to simulate a key-stroke to a window ID.
Installation & configuration
It is assumed that you’ve already installed WINE and the program you need under it. In this example we will be using Balabolka as the “Windows” application because it is a good freeware replica of the original program I needed this solution for (2nd speech center).
If you’ve opted to use Balabolka as well, you need to activate its hotkeys ability.
Note: You may want to install either TTSReader or 2nd speech center even in demo mode, so that the SAPI voices will be installed. 
Open the program and go to settings (Shit+F6) under “Options” -> “Settings”.

Go to the hotkeys tab and check the checkbox for “Use global hotkeys”.

Click OK.
Leave it running in the background so that it can do its job when we hook the keystrokes to it.
Install xdotool by issuing:
sudo apt-get install xdotool

Global binding

The xdotool program on its own doesn’t help us bind globally to hotkeys, but we can use the already existing OS hotkey system. What we will do is create a simple script that utilizes xdotool to send the keystrokes we want to the Balabolka program and call it from the OSs hotkey system.
Create a script called “start_read.sh” with the following content:
xdotool key --window $( xdotool search --limit 1 --all --pid $( pgrep balabolka ) --name Balabolka ) "ctrl+alt+F9"
Create another script this time called “stop_read.sh” with the following content:
xdotool key --window $( xdotool search --limit 1 --all --pid $( pgrep balabolka ) --name Balabolka ) "ctrl+alt+F7"
Note: I know this is a one liner that doesn’t require a script, but the Mint/Ubuntu “Keyboard Shortcuts” program, wasn’t cooperating with just invoking it directly. If you know how to do it, please share in the comments below.
Braking this command to its components, what we see is:
  • The “–pid $( pgrep balabolka )” part, executes a “pgrep” on the program we want to use as to ascertain its process ID. This will narrow the xdotool filed of “search” to just that PID.
  • The “xdotool search –limit 1 –all … –name Balabolka” part, narrows the filed of search of xdotool even more and limits the returned answers to 1. As in our case it doesn’t matter which of the window IDs returned of the program, limiting the result acts as a formatter for the “key” command. You may find you need to massage this part more if it does matter for the program that you are using.
  • The “xdotool key –window %WINDOW_ID% “ctrl+alt+F7″” part, sends the desired keystroke to the windowID which was obtained by the previous parts.
Make the scripts executable.
Linux Mint Keyboard shortcuts
Under Linux Mint, the global hotkeys are set in the “Keyboard Shortcuts” program.

Once opened Click on “Add” to create a new custom shortcut:

Give it a name and under “Command” give the full path to one of the scripts we’ve created above. Repeat the process for the second script.
Now, on the “Shortcuts” Column, click on the “Disabled” word to get the option to set a new key combo.
Note: You may, if you wish, use something other then the program’s default. In a sense creating a “remap” to key bindings that, depending on the program you use, would otherwise be out of your control.

Hit the combo you’ve selected and hear the magic.
Ubuntu Keyboard
Under Ubuntu, the program that sets the global hotkeys is just called “Keyboard”.

Switch to the “Shortcuts” tab and select “Custom Shortcuts”.

Click the plus sign to add a shortcut. Give it a name and under “Command” give the full path to one of the scripts we’ve created above. Repeat the process for the second script.
Now click on the “Disabled” word to get the option to set a new key combo.
Note: Repeating on the note from the Mint section, you may, if you wish, use something other then the program’s default. In a sense creating a “remap” to key bindings that, depending on the program you use, would otherwise be out of your control.

Author’s Notes

Every time I’ve seriously considered moving to Linux, this issue was the first on my list of problems. Its not that Linux doesn’t have problems, but this was the real hurdle, for me. I’ve tried time and time again, asked friends/people in the field and even made it into a bounty… I am happy this saga is over and that my soul can finally rest.
It is my hope that I’ve helped someone out there to not have to go through the same ordeal.

Doc Brown: It’s taken me nearly thirty years and my entire family fortune to realize the vision of that day. My God, has it been that long?

No comments:

Post a Comment