xmchord is a productivity tool for Linux desktops, that binds custom
actions to chording*
events of mouse buttons and key presses: this way,
mouse buttons become additional modifier keys.
*Chording:
Chording generally means pushing several keys or buttons
simultaneously to achieve a result.
xmchord comes with a comprehensive set of shortcut actions to automate and speed-up user activities that are common on the Linux desktop.
- What does it do?
- Usage and arguments
- Included shortcut actions
- Build from source
- Code Convention
- Contributing
- Bug Reporting and Feature Requests
- Changelog
- Third Party References
- Author and License
- Addendum I: Linux trackball configuration snippets
- Addendum II: Action shell scripting tricks
xmchord listens for events of mouse buttons pressed together with keyboard keys.
When observing a chording event, xmchord generates an identifier code for the
given combination (and order) of button/key presses.
If there is a shell script file named by the current event code within
xmchord's actions
directory, it is executed.
Usage is: sudo xmchord
To ensure read-access to Linux device events, xmchord must be run with root
privileges (e.g. viasudo
).
Action shell scripts that perform user specific tasks, therefor must take care
of running on that user's behalf.
Running xmchord help
or xmchord h
, displays a list and explanation of
available commands.
Running xmchord debug
or xmchord d
, activates tracing of event codes.
While in debug mode, action shell script files can be added without having to
stop and restart xmchord.
In regular mode, xmchord reduces processing time by indexing which actions are available during startup.
Running xmchord actions
or xmchord a
, lists all recognized action shell
scripts, including their inlined description comments (which must be prefixed
with #:
).
xmchord by default installs its keyboard watcher upon the 1st keyboard device found (e.g. on laptops the built-in one). This optional argument allows setting a specific keyboard device to be used. xmchord stores this device preference, so once it is set, xmchord continues using that device when restarted later.
Running xmchord -k=/path/to/my/keyboard
or
xmchord --keyboard=/path/to/my/keyboard
selects the device at the given path
as the keyboard watcher's target.
Tip: xmchord's device detection is looking for a matching substring,
therefore the device-identifier can also be given w/o a path, e.g:
xmchord -k=Logitech
.
Running xmchord listDevices
or xmchord l
lists paths of available devices.
Running xmchord printPreferences
or xmchord p
outputs xmchord's preferences
if given, or a respective info if not.
Running xmchord reset
or xmchord r
unsets xmchord's keyboard device
preference.
Running xmchord version
or xmchord v
, tests whether xmchord is available
and displays it's version number.
See files under bin/actions
The included shortcut actions are scripted for use with a Kensington Expert Mouse trackball, tested on Linux Mint Cinnamon, but should be compatible or easily adjustable for other devices and Linux distributions and desktop environments.
The following third party dependencies must be installed for all included actions to work:
Application | Description |
---|---|
aosd-cat of libaosd | Display TEXT, or standard input, on top of display |
feh | Image viewer aimed mostly at console users to simply display images w/o fancy GUI |
sed | Stream editor for filtering and transforming text |
wmctrl | Command line tool to interact with an EWMH/NetWM compatible X Window Manager |
xdotool | Fake keyboard/mouse input, window management, and more |
xsrel | Manipulate the X selection (Clipboard) |
xclip | Interface to X selections ("the clipboard") from the command line. |
Install dependencies that are not included in Linux Mint distribution by default:
sudo apt install aosd-cat feh xclip xdotool xsel -y
Symbols are:
◤ ◥ = Top buttons left / right
◣ ◢ = Bottom buttons left / right
These actions launch applications, or bring re-focus their window, if already running (like the behavior on Mac OS).
Shortcut | Description |
---|---|
◤ + G | Summon default email client (like mail key on keyboard) |
◤ + M | Bring Mattermost desktop client to front, launch if not yet running |
◤ + O | Bring Orange-player to front, launch if not yet running |
◤ + W | Summon default web browser (like browser key on keyboard) |
◣ + C | Launch or bring Chromium to front |
◣ + D | Launch or bring DataGrip to front |
◣ + F | Launch or bring Firefox to front |
◣ + K | Launch or bring Kitematic to front |
◣ + M | Launch or bring Claws Mail to front |
◣ + Y | Bring CherryTree to front, launch if not yet running |
◣ + Esc | Launch or bring System Monitor to front |
Shortcut | Description |
---|---|
◤ + ← | Go to workspace left of current (Hit SUPER+SHIFT+Left) |
◤ + → | Go to workspace left of current (Hit SUPER+SHIFT+Right) |
◤ + ◣ | Jump to next workspace |
Right Shift + ◤ + ◣ | Jump to previous workspace |
◣ + ◢ | Touch bottom-right hot-corner (E.g. expose windows) |
◣ + I | Display public and private IP and wifi MAC address, copy public IP address |
◣ + L | Toggle keyboard backlight |
◣ + R | Toggle active window roll-up state |
◣ + S | Toggle active window "roll-sideways" state |
◣ + T | Toggle active window always-on-top state |
◣ + U | Type current UNIX timestamp |
◣ + V | Toggle active window always-on-visible-workspace state |
◣ + W | Hit CTRL+W (close window) |
◣ + Ä | Type large A-umlaut (helpful e.g. on swiss keyboards) |
◣ + Ö | Type large O-umlaut (helpful e.g. on swiss keyboards) |
◣ + Ü | Type large U-umlaut (helpful e.g. on swiss keyboards) |
◣ + 0 | Move active window to workspace 0 |
◣ + 1 | Move active window to workspace 1 |
◣ + 2 | Move active window to workspace 2 |
◣ + 3 | Move active window to workspace 3 |
◣ + 4 | Move active window to workspace 4 |
◣ + 8 | Move caret eight times to the right (helpful e.g. to crop git hashes quickly) |
◣ + ← | Focus previous tab |
◣ + → | Focus next tab |
◣ + ↑ | Scroll to top (same as home key) |
◣ + ↓ | Scroll to bottom (same as end key) |
◣ + Numpad "-" | Toggle play/pause audio |
◣ + Numpad 7 | Tile active window to top-left 50% of screen |
◣ + Numpad 8 | Tile active window to top 50% of screen |
◣ + Numpad 9 | Tile active window to top-right 50% of screen |
◣ + Numpad 6 | Tile active window to right 50% of screen |
◣ + Numpad 3 | Tile active window to bottom-right 50% of screen |
◣ + Numpad 2 | Tile active window to bottom 50% of screen |
◣ + Numpad 1 | Tile active window to bottom-left 50% of screen |
◣ + Numpad 4 | Tile active window to left 50% of screen |
◣ + Numpad 5 | Maximize active window |
◣ + ' | Output name of application of focused window (to terminal) |
◣ + $ | Convert selected text to all upper/lower case |
◣ + ENTER | Click left mouse button three times (select line) |
◢ + A | Select all (same as CTRL+A) |
◢ + C | Copy (same as CTRL+C) |
◢ + F | Find (same as CTRL+F) |
◢ + V | Paste (same as CTRL+V) |
◢ + X | Cut (same as CTRL+X) |
◢ + Y | Redo (same as CTRL+Y) |
◢ + Z | Undo (same as CTRL+Z) |
◢ + Numpad 4 | Move active window to screen left of current |
◢ + Numpad 6 | Move active window to screen right of current |
◢ + Numpad Plus | Zoom in (same as CTRL+Plus) |
◢ + Numpad Minus | Zoom out (same as CTRL+Minus) |
◢ + ↑ | Increase audio volume |
◢ + ↓ | Decrease audio volume |
For these actions to be triggered, a window of the respective application must be focussed when the shortcut is fired.
Shortcut | Description |
---|---|
◤ + D | Show downloads |
◤ + R | Reload |
◤ + L or ◤ + U | Focus URL field |
◣ + ← | Focus previous tab (browser and DevTools) |
◣ + → | Focus next tab (browser and DevTools) |
Right-CTRL + ◣ + ← | Focus previous tab, than reload it |
Right-CTRL + ◣ + → | Focus next tab, than reload it |
◣ + , | Decrement numeric ending of current URL by 1 |
◣ + . | Increment numeric ending of current URL by 1 |
◣ + Backspace | Remove trailing segment from current URL |
◣ + C | Copy trailing segment of current URL |
◣ + D | Duplicate active tab |
◣ + H | Toggle HTML "view-source" of current URL |
◣ + N | Move active tab to new window |
◣ + RETURN | Browse for selected text in new tab |
◢ + ← | Go URL backwards |
◢ + → | Go URL forward |
◢ + F4 | Close active tab |
Shortcut | Description |
---|---|
◣ + [-] | Toggle URL sub string |
When running this action while the current browser URL contains one of two sub strings, it is been replaced by the other and the browser reloaded.
The following environment variables must be set in your /etc/environment
:
sudo nano /etc/environment
PATH="/usr/local/sbin:..."
XMCHORD_URL_SUBSTR_1='http://localhost'
XMCHORD_URL_SUBSTR_2='https://yoururl.com'
For changes to take effect after editing /etc/environment
reload it and
restart xmchord.
Shortcut | Description |
---|---|
◣ + F | Open "Search Folder" popup |
◣ + H | Toggle "Hide read messages", precondition: "thread view" must be deactivated |
Shortcut | Description |
---|---|
◤ | Close active tab |
◣ + F | Open Find popup |
◣ + Numpad / | Insert 40 empty lines (helpful to separate sections of output) |
◣ + ← | Focus previous tab |
◣ + → | Focus next tab |
◣ + ↑ | Scroll to top |
◣ + ↓ | Scroll to bottom |
Shortcut | Description |
---|---|
◣ + C | Type and execute command to cd into a favorite local path |
◣ + D | Type scp command to recursively download remote directory |
◣ + L | Shortcut to wipe a cache directory: Type and execute command to clean a preferred path by executing rm -rf upon it. |
◣ + S | Type and execute command to connect to preferred SSH host and cd into preferred path |
◣ + SPACE | Type yes and hit ENTER |
◣ + U | Type scp command to recursively upload local directory to remote |
◣ + X | Type exit and hit ENTER |
For the cd
, rm -rf
, scp
and ssh
shortcut snippets, the following environment variables
must be set in your /etc/environment
:
sudo nano /etc/environment
PATH="/usr/local/sbin:..."
XMCHORD_CD_FAVORITE=/home/john/Projects/myProject
XMCHORD_RM_FAVORITE=/home/john/Projects/myProject/var/cache
XMCHORD_SCP_REMOTE=johndoe@yourhost:/var/www
XMCHORD_SCP_LOCAL=/home/john/yourhost_var_www
XMCHORD_SSH_REMOTE=johndoe@yourhost
XMCHORD_SSH_REMOTE_NEEDS_CONFIRMATION=1
XMCHORD_SSH_REMOTE_PATH_INITIAL=/var/www
For changes to take effect, restart xmchord after editing your
/etc/environment
.
These actions automate the steps for transferring screenshots made with
Gnome Screenshot into other applications.
For them to work, the mouse must be hovering Gnome Screenshot's
copy to clipboard
button when fired.
Shortcut | Description |
---|---|
◣ + AltGr | Click and hit [Esc] = Copy to clipboard and close Gnome Screenhot popup at once |
◣ + G | Click, hit [Esc], focus Gimp (if running) and paste image from clipboard as new image |
◢ + V | View as "sticky note:" Click, hit [Esc], store clipboard to temporary image file and open image file in feh Image Viewer, Set feh window always-on-top and always-on-visible-workspace. |
Shortcut | Description |
---|---|
◣ + M | Open "direct messages" popup |
◣ + U | Upload files |
◣ + W | Type ":wave:" |
◣ + . | Next unread channel |
◣ + 1 | Type ":+1:" (= thumbs-up icon) |
Shortcut | Description |
---|---|
◣ + B | Open address book |
◣ + F | Open "Search Messages" popup |
These actions differ from the basic global actions, in that they require some manual configuration, as described here.
This action adds text from a currently given text-selection to a preset URL, and loads the resulting URL in the web browser (chromium by default).
Shortcut | Description |
---|---|
◣ + O | Open generic URL in browser. Precondition: a text selection is given |
The following environment variable must be set in your /etc/environment
:
sudo nano /etc/environment
PATH="/usr/local/sbin:..."
XMCHORD_GENERIC_URL='https://www.your-domain.com/?id=SELECTED_TEXT'
When running this action, SELECTED_TEXT
will be replaced by your text
selection.
For changes to take effect after editing /etc/environment
reload it and
restart xmchord.
To use a different browser, edit script: 0220022-24.sh
Some additional actions that aren't active by default can be found within
the actions/inactive
directory.
cmake CMakeLists.txt; make
The source code of xmchord follows the Google C++ Style Guide, see:
https://google.github.io/styleguide/cppguide.html
The source code of action shell script files follows the Google Shell Style
Guide, see https://google.github.io/styleguide/shell.xml
See CONTRIBUTING.md
If you find a bug or have an enhancement request, please file an issue on the github repository.
See CHANGELOG.md
Expert Mouse® Trackball is a registered trademark of Kensington Computer Products Group, a division of ACCO Brands
The example action for window arrangement uses splitDesk.sh, based on the original script by Steve Simpson.
The following third party tools are used for building xmchord with automatic control over code quality and standards:
Tool or Service | Description | License |
---|---|---|
Clang | A C language family frontend for LLVM | Apache License |
Cmake | Family of tools designed to build, test and package software | New BSD License |
Cppcheck | Static analysis tool for C/C++ code | GNU General Public License version 3 |
cpplint | Static code checker for C++ | BSD-3 Clause |
GCC | GCC, the GNU Compiler Collection | GNU General Public License version 3 |
lgtm automated code review | Code analysis platform for finding zero-days and preventing critical vulnerabilities | lgtm Terms of Service |
ShellCheck | ShellCheck, a static analysis tool for shell scripts | GNU General Public License version 3 |
Tavis CI | Test and Deploy Your Code with Confidence | Travis CI Contact & Legal Inquiries |
Thanks a lot!
Written by Kay Stenschke. xmchord is licensed under the New BSD License
Copyright (c), Kay Stenschke All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Output list of devices: xinput --list
Output mouse buttons mapping: xinput get-button-map <device-ID>
Trace mouse button IDs: xev
Set speed and acceleration, buttons mapping and wheel emulation:
#!/bin/bash
for id in `xinput --list|grep 'Kensington Expert Wireless TB Mouse'|perl -ne 'while (m/id=(\d+)/g){print "$1\n";}'`; do
# set speed + accelleration
xinput set-ptr-feedback $id 0 34 12
# set top/left button to be middle-click
xinput set-button-map $id 3 2 1 4 5 6 7 8 9 10 11 12 # left-handed: bottom-right is left-click
# emulate mouse wheel on bottom/left (right-click) button + move
xinput set-prop "pointer:Kensington Expert Wireless TB Mouse" "libinput Scroll Method Enabled" 0, 0, 1
# on Kensington Expert Mouse, buttons are:
# 0 = no button needed
# 2 = top/left
# 8 = top/right
# 1 = bottom/left
# 8 1 = bottom buttons together
# 8 2 = bottom right + top/left together
# set bottom button to fire scroll-mode
xinput set-prop "pointer:Kensington Expert Wireless TB Mouse" "libinput Button Scrolling Button" 1
# map bottom-left button held to scroll
xinput set-prop $id "Evdev Wheel Emulation Timeout" 300
done
Problem: xmchord runs as root, but some actions need to be run for a specific logged-in user.
E.g. Cinnamon's D-Bus methods require being launched by a specific user. The following script switches from root to original user, before triggering the desired method:
#!/bin/bash
me=$SUDO_USER
sudo -u $me dbus-send --dest=org.Cinnamon --print-reply /org/Cinnamon org.Cinnamon.switchWorkspaceRight
Shell scripts can detect whether an application is running already and using e.g. wmctrl, bring a respective window onto the active workspace, or launch the application (similar to the behavior on Mac OS).
#!/bin/bash
if pidof -s evolution > /dev/null; then
wmctrl -a Evolution
else
me=$SUDO_USER
sudo -u $me nohup evolution > /dev/null &
fi
Using e.g. wmctrl, shell scripts can switch the active window's roll-up and always-on-top state:
#!/bin/bash
wmctrl -b toggle,shaded -r :ACTIVE:
#!/bin/bash
wmctrl -r :ACTIVE: -b toggle,above
Using e.g. xdotool, shell scripts can detect the currently focused window's application, and vary the triggered function accordingly. Xdotool also allows to trigger key-combinations for various shortcuts:
#!/bin/bash
focusApplication=\
`cat /proc/$(xdotool getwindowpid $(xdotool getwindowfocus))/comm`
if [[ "$focusApplication" =~ "gnome-terminal-" ]]; then
xdotool key Control_L+Page_Up
else
xdotool key shift+ctrl+Tab
fi