Looking for a way to simulate keyboard and mouse input? The web is full of various guides and tutorials mentioning xdotool, a “command-line X11 automation tool.” xdotool simulates X11 input events; it can even move or resize the desktop windows.

Unfortunately, as its name implies, xdotool only works with the X11 window system. This means it cannot work in Wayland sessions due to the stricter security constraints defined by the Wayland protocol. The functionality provided by xdotool is still invaluable though. Fortunately, there is a set of utilities that provide very similar functionality as xdotool. Because it works by simulating input devices directly, evemu works in both Wayland sessions and X11 desktop sessions.

Evemu is not a drop-in replacement for xdotool, nor was it designed to be. For example, it does not have a feature similar to mousemove. Instead, evemu records device input events. Careful study of the output and modification of the sequence of events will yield the desired simulated event. This article will introduce evemu and demonstrate how it can be used to simulate input events much like xdotool does.

Installation

evemu is available in the Fedora repositories, so installation is straightforward:

sudo dnf install evemu

List devices

First, see what devices are present on the system by looking in /dev/input/by-id/ and /dev/input/by-path/. Alternatively, the evemu-describe command will enumerate events for each attached device:

$ sudo evemu-describe Available devices: /dev/input/event0: Power Button /dev/input/event1: Sleep Button /dev/input/event2: AT Translated Set 2 keyboard /dev/input/event3: ImExPS/2 Generic Explorer Mouse /dev/input/event4: VirtualBox USB Tablet /dev/input/event5: Video Bus /dev/input/event6: VirtualBox mouse integration Select the device event number [0-6]: 3 ... # Supported events: # Event type 0 (EV_SYN) # Event code 0 (SYN_REPORT) # Event code 1 (SYN_CONFIG) # Event code 2 (SYN_MT_REPORT) # Event code 3 (SYN_DROPPED) # Event code 4 ((null)) # Event code 5 ((null)) # Event code 6 ((null)) # Event code 7 ((null)) # Event code 8 ((null)) # Event code 9 ((null)) # Event code 10 ((null)) # Event code 11 ((null)) # Event code 12 ((null)) # Event code 13 ((null)) # Event code 14 ((null)) # Event code 15 (SYN_MAX) # Event type 1 (EV_KEY) # Event code 272 (BTN_LEFT) # Event code 273 (BTN_RIGHT) # Event code 274 (BTN_MIDDLE) # Event code 275 (BTN_SIDE) # Event code 276 (BTN_EXTRA) # Event type 2 (EV_REL) # Event code 0 (REL_X) # Event code 1 (REL_Y) # Event code 6 (REL_HWHEEL) # Event code 8 (REL_WHEEL) ...

Mouse

In this case, /dev/input/event3 is the mouse. Record its input events by running:

$ sudo evemu-record --autorestart=3 /dev/input/event3 /tmp/mouse ^C$

This command creates a file named /tmp/mouse.<timestamp>. After a period of 3 seconds of inactivity ( the autorestart option), a new file with a new timestamp suffix, is created. Press CTRL+C to stop the recording. Now run the recording by running evemu-play:

$ sudo evemu-play /tmp/mouse.<timestamp> ImExPS/2 Generic Explorer Mouse: /dev/input/event7 Hit enter to start replaying

The cursor should move around the screen in a pattern similar to the movement during the recording. Note that the coordinates are not relative to the desktop, instead they are relative to the input device. Movements will start from the current position of the cursor rather than the position the cursor was in during recording.

This example may seem superfluous. Using the keyboard results in more practical use cases. In fact, simulating keystrokes is easier; keyboards don’t have coordinate systems that make mouse emulation so challenging.

Keyboard

On this machine, the keyboard is /dev/input/event2. Remember that all its events can be listed out with evemu-describe /dev/input/event2. This example simulates pressing Super . In GNOME, this brings up the activities overview:

$ sudo -- bash -c 'evemu-event /dev/input/event2 --type EV_KEY --code KEY_LEFTMETA --value 1 --sync; evemu-event /dev/input/event2 --type EV_KEY --code KEY_LEFTMETA --value 0 --sync'

Notice the evemu-event command is repeated twice. The first time sets the value option set to 1. This emulates the key down event. The second time sets the value to 0. This emulates the key up event. Remember to release the key, otherwise it acts like the key is stuck pressing a key! Finally, the sync option guarantees that the keystrokes are executed in sequence.

Macro

Putting all this together, it’s fairly straightforward to create a simple bash script to launch LibreOffice Writer. The script presses the Super key, type “writer”, and press Enter . For the sake of demonstration, the script adds a pause between the keystrokes and event a typo that will be deleted using the backspace. Be sure to replace device with the keyboard device on your own machine.

#!/bin/bash device="/dev/input/event2" function press { evemu-event ${device} --type EV_KEY --code $1 --value 1 --sync evemu-event ${device} --type EV_KEY --code $1 --value 0 --sync sleep 0.2 } press KEY_LEFTMETA sleep 1 press KEY_W press KEY_R press KEY_I press KEY_T # Typo! press KEY_I press KEY_E # Let's fix that press KEY_BACKSPACE press KEY_BACKSPACE press KEY_E press KEY_R sleep 1 press KEY_ENTER

Set the execution bit with chmod and execute it (using sudo): sudo ./script.sh

Regardless of its original purpose, with some imagination, evemu can be put to some clever use: a kiosk or a live presentation, pranks on your roommates, or coupled with some hardware (like an Arduino or a micro:bit) a homemade remote control.