tapper
— Keyboard layout switcher for X Window System and Wayland.
tapper
[option]… [assignment]…where assignment is (in EBNF notation):
=
", [ actions ];,
", action };@
", layout );Tapper runs in the background, when you tap an assigned key, Tapper activates the corresponding keyboard layout. The assigned key always activates the same layout: Tapper never toggles layouts, each layout must have its own dedicated key. Tapper key feature is using modifier keys (e. g.‍ Shift
s, Ctrl
s or Alt
s) to switch keyboard layouts without losing functionality of the modifier keys.
In addition to switching keyboard layouts, Tapper can emulate keystrokes. It allows some useful tricks.
Typically, Tapper is configured by using the --dconf-editor
option, and set up to start automatically with the --autostart
option. Alternatively, Tapper can be configured through the command line with the --save-settings
options, and set up for autostart using the desktop-specific apps, like GNOME “Tweaks” or KDE “System Settings”.
In order to detect taps, Tapper listens user input events (key press, key release, etc). The Tapper component that listens input events is called “listener”. Tapper has several listeners:
libinput is a low-level library to handle input devices. The libinput listener uses this library and works for both X Window System and Wayland, but requires extra permissions: the Tapper process must have the input
group identity. (It could be achieved if tapper
executable file is owned by the input
group and has the set-group-id
bit set. This is the reason why Tapper should be properly installed.)
See also “Security” below.
XRecord is an X Window System extension. The XRecord listener uses the extension and obviously requires X Window System and does not work in Wayland, but does not require extra permissions.
This is not a real listener but instruction for Tapper to select a suitable listener automatically. Tapper examines the XDG_SESSION_TYPE
environment variable: if the value is x11
, Tapper selects the XRecord listener, otherwise the libinput listener is selected.
Tapper has several listeners listed above, but only one selected listener is used in run time. A listener to use is specified by the listener
key in settings and/or by the --listener
command line option.
The Tapper component that manages (reports all available layouts, activates layouts, etc) keyboard layouts is called “layouter”. Tapper has several layouters:
This layouter requests Agism GNOME Shell extension to activate the layout, Agism calls appropriate GNOME Shell methods to do the work. Practically it means that the GNOME layouter works nicely in the GNOME desktop: it updates keyboard indicator and manages as many keyboard layouts as configured in the GNOME Shell.
Also, the GNOME layouter monitors the GNOME session. If the session becomes not active (e. g. when the user locks the current session and switches to the GNOME Display Manager screen or to another session), the GNOME layouter switches Tapper to passive mode: it continues to listen user input events, but does not execute any actions (does not activate layouts and does not simulate keystrokes). If the session becomes active, the GNOME layouter switches Tapper back to normal mode. Such behavior prevents one session from undesirably affecting another (this is possible in case of using the libinput listener and/or the libevdev enitter).
Important note: The GNOME layouter requires Agism GNOME Shell extension is installed and enabled.
This layouter calls KDE via D-Bus, KDE does the work.
Note: The KDE layouter cannot ring the bell, so the --bell
option does not have effect if the KDE layouter is selected.
Xkb is an X Window System extension. Note the Xkb limitation: Xkb allows you to load up to 4 keyboard layouts (they are called “groups” in the technical documentation) and then activate one of these preloaded layouts (they call it “to lock a group”).
The Xkb layouter uses Xkb to activate the layout. Obviously this layouter depends on X Window System and does not work in Wayland, but it works for non-GNOME desktops running on top of the X Window System session (Cinnamon, i3, KDE, LXDE, LXQt, Mate, Xfce to name a few).
This is a stub, dumb layouter, which does nothing. It reports no layouts and does not activate layouts. It does not ring the bell, too. It is used when no layout management is required.
This is not a real layouter but an instruction for Tapper to select a suitable layouter automatically. If no layout switching is required Tapper selects the dummy layouter; if layout switching is required Tapper checks the XDG_SESSION_DESKTOP
environment variable: if the value is gnome
, gnome-classic
, gnome-xorg
, ubuntu
, or ubuntu-wayland
, Tapper selects the GNOME layouter, if the value is KDE
, Tapper selects the KDE layouter, otherwise the Xkb layouter is selected.
Note: In the Ubuntu “native desktop” the environment variable XDG_SESSION_DESKTOP
has value ubuntu
, i. e. the Ubuntu distro pretends to runs the Ubuntu desktop. However, the Ubuntu desktop is actually the GNOME Shell with few Ubuntu-specific extensions, so the GNOME layouter works for Ubuntu desktop.
Tapper has several layouters listed above, but only one selected layouter is used in run time. A layouter to use is specified by layouter
key in settings and/or by --layouter
command line option.
The Tapper component that emulates keystrokes (emits input events) is called “emitter”. Tapper has several emitters:
libevdev is a low-level library that manages kernel input devices. The libevdev emitter uses this library to create a virtual keyboard, and later emulates keystrokes on that keyboard. It works for both X Window System and Wayland, but requires extra permissions: the Tapper process must have the root
user identity. (It could be achieved if tapper
executable file is owned by the root
user and has the set-user-id
bit set. This is the reason why Tapper should be properly installed.)
See also “Security” below.
XTest is an X Window System extension. The XTest emitter uses the extension and obviously requires X Window System and does not work in Wayland, but does not require extra permissions.
This is a stub, dumb emitter, which does nothing. It is used when keystroke emulation is not required.
This is not a real emitter but an instruction for Tapper to select a suitable emitter automatically. If no keystroke emulation is required Tapper selects the dummy emitter; if keystroke emulation is required Tapper checks the XDG_SESSION_TYPE
environment variable: if the value is x11
, Tapper selects the XTest emitter, otherwise the libevdev emitter is selected.
Tapper has several emitters listed above, but only one selected emitter is used in run time. An emitter to use is specified by emitter
key in settings and/or by --emitter
command line option.
Key can be specified by a key code (an unsigned integer number, e. g. 29
) or a symbolic key name (e. g. LCTL
or KEY_LEFTCTRL
).
Tapper uses the Linux kernel input event codes regardless of the selected listener and emitter.
Tapper converts key names to the corresponding key codes using the selected listener, and then operates only with key codes. If the specified symbolic key name is not known to the selected listener, it causes error.
Run Tapper with --list-keys
option to see the list of keys known to the selected listener. Use --list-keys
in combination with --listener
to see the list of keys for the specific listener. Alternatively, run Tapper with --show-taps
, then tap desired keys to discover their codes.
A “tap” means that a single key is pressed and quickly released, so:
Note: Both conditions must be met. If a key is pressed in a chord with other key(s), this is not a tap. If the key is released slowly (so that it was pressed for 0.5 seconds or more), this is not a tap.
Tapper relies on the selected layouter to get keyboard repeat delay value. GNOME layouter reads keyboard repeat delay from the GNOME settings in GSettings database; KDE layouter parses the KDE configuration files; Xkb layouter gets it from X Window System. Tapper reads keyboard repeat delay only once; if you change keyboard repeat delay after Tapper has started, Tapper will not use the new value until restarted.
Keyboard layout can be specified by a layout index (an unsigned integer number, e. g. 1
, 2
, 3
, etc) or name (e. g. English (US)
or Russian (typewriter)
).
Layouts are layouter-dependent. In case of GNOME layouter they are GNOME “input sources”, in case of Xkb layouter they are Xkb “groups”. Tapper enumerates layouts starting from the number 1.
Tapper converts layout names to corresponding layout indexes using the selected layouter and then operates only with layout indexes. If the specified layout name is not known to the selected layouter, it causes error.
Run Tapper with --list-layouts
option to see the list of currently configured layouts for the current layouter. Use --list-layouts
in combination with --layouter
to see the list of layouts known to the specific layouter.
An action is an elementary command that Tapper can execute. There are 2 types of actions:
@
layoutActivate the specified layout. Tapper does not load any keyboard layouts to GNOME, KDE or X Window System, Tapper just makes one of currently loaded layouts active. Technically speaking, the GNOME layouter invokes an Agism method via D-Bus, the KDE layouter invokes an KDE method via D-Bus, the Xkb layouter calls XkbLockGroup
function. (In turn, GNOME Shell working on top of X Window System session may (re)load keyboard layout(s) to lift the X Window System limit of 4 layouts).
Emulate the stroke on the specified key by emitting two input events: key press and key release.
Note that a layout used as an action must be prefixed with @
character to distinguish between layouts and keys: 1
is the command to emulate Esc
keystroke, while @1
is the command to activate the first layout. Layout names must be prefixed, too: @English (US)
.
An assignment dedicates the key for the series of actions.
Assignments are specified by assignments
key in the settings and/or by assignment arguments on the command line. Note the difference, though: in the settings, symbolic key names and layout names are not allowed, only key codes and layout indexes should be used. The command line is a little more flexible: it allows both codes and names.
The list of actions consists of a single keyboard layout activation command (e. g. LCTL=@1
). In such a case, assignment dedicates the key for the keyboard layout. When Tapper detects a tap on the assigned key, it activates the layout.
A key can be assigned only once, using the key for the second time (e. g. LCTL=@1 LCTL=@2
) causes an error. In constrast, the same layout may be assigned to multiple different keys (e. g. LCTL=@1 LFSH=@1
), in such a case the layout (the first layout in the example) is activated by tap on any of the keys assigned to the layout (either the left Ctrl
or the left Shift
).
Empty list of actions (e. g. LCTL=
) is allowed, too. Such assignment unassigns the key. It is useful to cancel key assignments made in settings.
The list of actions can be an arbitrary sequence of comma-separated actions (e. g. LCTL=@1,BTN1,BTN1,@2
). When Tapper detects a tap on the assigned key, it executes the associated actions sequentially.
List of actions can be an arbitrary mix of layout activation and keystroke emulation commands, but there are some limitations:
Tapper can not hide input events from other programs. For example, let us consider LCTL=BTN1
: when Tapper detects the left Ctrl
tap, it emulates Left button
click. But other programs will see the left Ctrl
press and release anyway.
The input events generated by Tapper are visible for all the programs, including Tapper itself. So assignments like LCTL=LCTL
or LCTL=RCTL RCTL=LCTL
will cause infinite loop as soon as the first tap on an assigned key is detected.
Tapper initiates keyboard layout change, but actual layout activation is done asynchronously by the GNOME Shell, KDE, or the X Window System. Similarly, Tapper emits input events, but they are routed asynchronously through the Linux kernel and/or the X Windows System. Because of this, result of commands of different type can be delivered out of order. For example, the result of @1,30,@2,31
may be the same as the result of @1,@2,30,31
or @1,30,31,@2
or 30,31,@1,@2
. However, result of commands of the same type should be delivered in order: in the previous example, programs will always see 30
keystroke followed by 31
keystroke.
Despite these limitations, keystroke emulation allows some useful tricks, see “Advanced usage” in “EXAMPLES”.
Tapper can ring the bell when it activates a layout. Actual bell sound depends on system configuration, bell may have no sound at all or have visual effect.
Bell mode is specified by bell
key in settings and/or by --bell
and --no-bell
command line options.
Note: The KDE layouter cannot ring the bell, so the --bell
option will not have effect if the KDE layouter is selected.
Tapper configuration includes:
Tapper can load configuration from the GSettings database and save it back.
By default, Tapper loads the settings; use --no-load-settings
option to avoid loading. Tapper merges the loaded settings and the configuration specified by the command line to get the effective configuration. In case of conflicts, command line options and assignments override the loaded settings. If --save-settings
option is specified, Tapper saves the effective configuration to the GSettings database and exits.
Thus, you can edit Tapper settings using the --save-settings
option. If you prefer a graphical interface, use the --dconf-editor
option — Tapper will open its settings in “dconf Editor” application. Alternatively, Tapper settings can be viewed or edited with command-line tools gsettings
and dconf
. Tapper’s settings schema is io.sourceforge.kbd-tapper
, path is /io/sourceforge/kbd-tapper/
.
Long option names can be abbreviated until they remain unique. For example, --save-options
can be types as just --save
or even --sa
(but --s
will be rejected because it is ambiguous: it could be either --save-settings
, --syslog
or --show-taps
).
Order of options does not matter. Even if you type --save-settings
--load-settings
--bell
, Tapper will load settings first, then enable bell, and then save settings.
--listener=
listenerListener to use, one of: libinput
, xrecord
, auto
(default).
--libinput
Same as --listener=libinput
.
--xrecord
Same as --listener=xrecord
.
--layouter=
layouterLayouter to use, one of: gnome
, kde
, xkb
, dummy
, or auto
(default).
--gnome
Same as --layouter=gnome
.
--kde
Same as --layouter=kde
.
--xkb
Same as --layouter=xkb
.
--emitter=
emitterLayouter to use, one of: libevdev
, xtest
, dummy
, or auto
(default).
--libevdev
Same as --emitter=libevdev
.
--xtest
Same as --emitter=xtest
.
--bell
Ring the bell when Tapper activates a layout.
--no-bell
Do not ring the bell when Tapper activates a layout (default).
--dconf-editor
Launch “dconf Editor” tool to edit Tapper settings and exit.
--load-settings
Load settings from GSettings database (default).
--no-load-settings
Do not load settings from GSettings database.
--reset-settings
Reset setting to default and exit.
--save-settings
Save effective configuration to GSettings database and exit.
--autostart
Set up Tapper to start automatically when you log in and exit. The option works for desktops, respecting the Desktop Application Autostart Specification.
--no-autostart
Disable Tapper autostart (by removing the link to the Tapper desktop file from your ~/.config/autostart/
directory) and exit.
--lay-off
Parse command line options and arguments, load settings (if not prohibited), print effective configuration and exit. The option exists for testing purposes.
--no-default-assignments
Do not use default assignments. Tapper uses default assignments if no assignments are made in settings (if settings loading is enabled) and command line. The option exists for testing purposes primarily.
--quiet
Do not print introductory messages (copyright and effective configuration).
--syslog
Copy run time errors and warnings to system log. (Command line errors are not copied to system log.)
--x
Same as --xrecord --xkb --xtest
.
--help
Print help message and exit.
--list-keys
List keys and exit. Key names are listener-dependent.
--list-layouts
List keyboard layouts and exit. Layouts are layouter-dependent.
--show-taps
Run Tapper in "show taps" mode: whenever a tap is detected, Tapper prints the code and name of the tapped key. The mode implies the --emitter=dummy
option and does not allow assignments in the command line; emitter selection and assignmnets in settings are ignored.
--usage
Print very short usage message and exit.
--version
Print short message containing version, copyright, license and exit.
0
if everything is ok,2
if usage (command-line) error detected,3
if run time error occurred.List keys known to the selected listener:
$ tapper --list-keys
List keys known to the libinput listener:
$ tapper --libinput --list-keys
Discover key codes (tap desired keys then press Ctrl
+C
to stop Tapper):
$ tapper --show-taps
List layouts known to the selected layouter:
$ tapper --list-layouts
List layouts known to the GNOME layouter:
$ tapper --gnome --list-layouts
List layouts known to the KDE layouter:
$ tapper --kde --list-layouts
By default, if tapper settings are not yet modified, the left Ctrl
tap activates the first keyboard layout and the right Ctrl
tap activates the second layout:
$ tapper
The same + enable bell:
$ tapper --bell
In addition to default left and right Ctrl
s, the left Shift
tap activates the third keyboard layout, the right Shift
— the fourth layout (X Window System session is assumed):
$ tapper LFSH=@3 RTSH=@4
Ditto but key codes are used instead of symbolic key names, so it works for both X Window System and Wayland sessions:
$ tapper 42=@3 54=@4
Unassign default Ctrl
s, use the left Shift
for the first layout and the right Shift
for the second layout:
$ tapper LCTL= RCTL= LFSH=@1 RTSH=@2
Completely ignore existing settings, if any, and specify new configuration: the left Shift
tap activates the first keyboard layout, the right Shift
tap — the second layout. Other settings are defaulted: listener, layouter and emitter are selected automatically, bell is disabled. The command below is suitable for X Window System session (due to used key names):
$ tapper --no-load-settings LFSH=@1 RTSH=@2 --save-settings
Ditto for Wayland session:
$ tapper --no-load-settings KEY_LEFTSHIFT=@1 KEY_RIGHTSHIFT=@2 --save-settings
Ditto (key codes used instead of symbolic key names, it is suitable for both X Window and Wayland sessions):
$ tapper --no-load-settings 42=@1 54=@2 --save-settings
Turn on the bell:
$ tapper --bell --save-settings
Reset settings to default:
$ tapper --reset-settings
Examine Tapper settings with gsettings
tool:
$ gsettings list-recursively io.sourceforge.kbd-tapper
Edit Tapper settings with “dconf Editor” graphical application:
$ tapper --dconf-editor
Start Tapper with the saved settings:
$ tapper
Start Tapper with the saved settings, but turn off the bell:
$ tapper --no-bell
Let Tapper start automatically when you log in:
$ tapper --autostart
A modifier key, like Ctrl
, does its function only in a chord with other key(s): pressing a modifier alone has no effect. Tapper gives a modifier key the second function: a tap on the assigned modifier is meaningful — it activates a keyboard layout.
Let us consider Alternate Characters Key and Compose Key. (“Alternate Characters Key” is GNOME Shell term, X Window System names it “a key to choose the 3rd level”.) Both Alternate Characters Key and Compose Key are functions, not physical keys. Alternate Character function is frequently assigned to the right Alt
key, Compose function — to the Menu
key. Alternate Characters Key is a modifier: it has effect only in a chord with other key(s), pressing Alternate Characters Key alone has no effect. Let us assign both functions, Alternate Characters Key and Compose Key to the Menu
key:
Configure your desktop to use the Menu
key as Alternate Characters Key.
Chose a key physically missing on your keyboard (e. g. F14
with code 184
), and configure your desktop to use it as Compose Key.
Run Tapper:
$ tapper 127=184 # 127 is the Menu key code
VoilĂ ! The Menu
key pressed in a chord with other key(s) does Alternate Characters function, the same Menu
key tapped alone does Compose function; the keyboard has two symmetric Alt
s (like Shift
s and Ctrl
s).
Alternatively, the right Alt
may be used for Alternate Characters/Compose, letting the Menu
key show the context menu.
(Or rather, for those vimers whose native language is not written in Latin-based script.)
Configure your desktop to disable Caps Lock
key first, then:
$ tapper 58=1,@1 # 58 is the Caps Lock key code, 1 — Esc key code
Now Caps Lock
emulates Esc
keystroke which activates Vim Normal mode, and activates the first layout (presumably English (US)
), since most of the Vim commands are Latin characters.
Note: This trick is obsolete now, since Tapper has the KDE layouter, but the idea of the trick is still worth to mention it.
KDE allows dedicated shortcuts for every keyboard layouts, but KDE does not accept single Ctrl
as a shortcut. Tapper can help:
$ tapper KEY_LEFTCTRL=KEY_F14 KEY_RIGHTCTRL=KEY_F15
Then start “System Settings”, navigate to “Input Devices” → “Keyboard” → “Layout” and add shortcuts for your layouts, using the left Ctrl
and the right Ctrl
— with a help from Tapper they will be recognized by KDE as “Launch (7)” and “Launch (8)”.
Important note: Using Tapper in multiuser environment may be insecure, see details below. Especially, avoid installing a debug build of Tapper, as its debug output can be used as a key logger.
The libinput listener reads device files in the /dev/input
directory. That files are not readable by regular users, only members of the input
group (and the root
user) can do that. The libevdev emitter is even more demanding: it writes the /dev/uinput
device file, which is writable only by the root
user.
So, to be fully functional, Tapper must be run with the root
user identity. Up to version 0.7.0, it was achieved by setting set-user-id
bit on the Tapper executable file owned by the root
user. Actually, Tapper does not need the all root
capabilities: only two capabilities cap_setuid
and cap_setgid
are sufficient. Capability-based approach was implemented in Tapper 0.7.1.
Anyway, Tapper still has the great power in the system: the libinput listener listens really all input events (key press and key releases, mouse movement, etc) in the system, even if these events are generated by another user. For example, one user may lock his session, another user may start its own session, but Tapper started by the first user will listen all that types the second user. Similarly, input events generated by the libevdev emitter affect all users.
However, Tapper strives to behave responsibly:
cap_setuid
and cap_setgid
capabilities in the very beginning to get the root
user and input
group identities, and drops all the capabilities.root
user identity permanently as soon as the libevdev emitter opens /dev/uinput
file, or as soon as Tapper learns that the libevdev emitter will not be used.input
group identity while the libinput listener is in use because new device files may appear in /dev/input
directory while Tapper is running (e. g. if the user plugs in an keyboard or mouse), and libinput will try to open them. However, Tapper drops input
group identity as soon as it learns that the libinput listener will not be used.Also, Tapper is free software, its source code is freely available. You can study it to make sure that Tapper does not cheat you.
The GNOME layouter in Tapper 0.5.0 (and earlier versions) uses the Eval
GNOME Shell method to manage keyboard layouts. In GNOME 41 the Eval
method is considered insecure and disabled: it is still present and callable, so Tapper does not throw any errors, but the method does nothing, so Tapper does not switch layouts.
As a temporary workaround for the problem, you may install one of these GNOME Shell extensions:
These extensions enable the “Unsafe Mode” of the GNOME Shell, so the Eval
method does actually work. Unfortunately, both extensions are considered unsafe and are missing from GNOME Shell Extensions, so you have to download and install them manually.
The GNOME layouter in Tapper 0.6.0 (and later versions) no longer uses the Eval
method. Instead, it uses Agism, a dedicated GNOME Shell extension that gives 3rd party applications the ability to manage keyboard layouts. Agism must be installed and enabled to let Tapper work. BTW, Agism works for any GNOME Shell version, starting from 3.28.
The Xkb layouter does not work in GNOME 3.18 running in Fedora 23. Strictly speaking, the layouter does work — it activates the required layout, but broken Mutter immediately switches the layout back. This behavior is introduced to Mutter to fix keyboard layout selection in Ubuntu… and break layout selection in Fedora. See details in:
The bug was fixed in Fedora 24, but later it was re-introduced back. Broken Mutter may appear in other GNU/Linux distros too.
Do not use the Xkb layouter in GNOME, use the GNOME layouter instead.
Even if Mutter is not broken (e. g. in Fedora 24), Xkb layouter may work weird in GNOME:
Since GNOME is not aware about the layout activated by Tapper behind GNOME’s back, keyboard indicator is not updated and may be out of sync.
If more than 4 input sources are configured in GNOME, GNOME (re)loads them dynamically to overcome X Window System limitations. The Xkb layouter always activates one of loaded keyboard layouts by an index, but in such conditions the index does not denote the same layout all the time.
Do not use the Xkb layouter in GNOME, use the GNOME layouter instead.
If you are a newbie, read Simon Tatham’s essay “How to Report Bugs Effectively”. The essay is available in several languages.
A bug report or help request must include:
Brief description of your system. Run the following commands and show me their exact output:
$ cat /etc/os-release
$ uname -m
How you installed Tapper:
rpm -q tapper
.In case of build problem: Exact build commands and their exact output.
In case of run time problem: Run the following commands and show me their exact output (omit the third command in case of non-GNOME desktop (Ubuntu is the GNOME desktop)):
$ echo $XDG_SESSION_TYPE
$ echo $XDG_SESSION_DESKTOP
$ gnome-extensions show agism@agism.sourceforge.io
$ gsettings list-recursively io.sourceforge.kbd-tapper
Then run Tapper from the terminal and show me exact command you type and its exact output; also describe your actions, the actual Tapper behavior, and your expectations.
Collect all the requested information and send the bug report to van.de.bugger@gmail.com.
Copyright 🄯 2014, 2016—2017, 2019—2023 Van de Bugger. License GPLv3+: GNU GPL version 3 or later https://gnu.org/licenses/gpl.html.
This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.