In my last post I detailed how I turned one of my desktop Raspberry Pis into a digital sign that could automatically switch between multiple kiosk-mode web pages. The method that I presented works, but leaves the mouse cursor visible on the screen.
In this post I will continue that topic and show how I used ydotool to hide the mouse cursor when this solution is running.
Why ydotool?
I am by no means a Wayland expert, but my understanding is that Wayland based compositors are lean, mean and designed for security. The security model of Wayland prevents mouse input events from being generated by an end-user, and requires daemon level authorisation. This is a problem for anyone who actually wants to automate mouse movements from a user-space tool.
ydotool is an application that can enable user-space based automation on Wayland systems by creating a socket-based bridge that can transmit user requested events to an authorised daemon. I couldn't find detailed documentation of how to implement it, so what follows is my understanding:
There are three main components to this solution:
- A user space tool (ydotool), which enables command line requests for mouse and keyboard events
- A system level daemon (ydotoold) which processes automation requests and transmits them to Wayland
- A file-system socket, which act as a bridge between the two components
In essence, it seems to work like this,
The ydotoold daemon starts with system privileges, and creates a socket to listen to
The ydotool application transmits automation requests to this socket
The user-space requests from ydotool are turned into system level input events by ydotoold
The mouse moves!
Of course, this will only work if the user has sufficient rights to write to the socket!
Implementing ydotool
Here is a summary I added ydotool to my digital signage solution
- Download, build and install ydotool
- Create a startup script for the ydotoold daemon
- Create a systemd service for the ydotoold daemon
- Add a ydotool command to the digital sign launch script
I'll provide more detail for these steps below
Download, build and install ydotool
Here are the steps I used to build and install ydotool
(note - this step may be unnecessary. Apt packages for ydotool and ydotoold are available for Raspbian, BUT I wasn't able to get the solution to work with the packaged versions. Your mileage may vary).
Install cmake
> sudo apt install cmake
clone the ydotool repository
> git clone https://github.com/ReimuNotMoe/ydotool.git
change into the ydotool repository directory
>cd ydotool
run the ydotool build steps:
mkdir build
cd build
cmake ..
make -j `nproc`
install the solution (make install)
(see the ydotool github repository for more information)
If all goes well then you will have fresh copy of ydtool and ydotoold installed to /usr/local/bin
Create a startup script for the ydtoold daemon
The next step is to create a launch script for the ydotoold daemon. I called mine /usr/local/bin/run_ydotoold.sh
Edit this file and add the following:
#!/bin/sh
export YDOTOOL_SOCKET=/tmp/.ydotool_socket
/usr/local/bin/ydotoold &
sleep 1
chmod 777 /tmp/.ydotool_socket
while true; do
echo "ydotoold is running at $(date)" >> /var/log/ydotoold.log
sleep 300
done
This script starts the daemon, ensures that the ydotoold socket is user writeable and then sleeps to prevent the daemon from being terminated.
Make sure to make this script executable.
> sudo chmod u+x /usr/local/bin/run_ydotoold.sh
Enable ydotoold as a systemd service
To ensure that ydotoold is run as a system level service, we need to create a systemd service script.
Edit a new service script as the superuser:
> sudo nano /etc/systemd/service/ydotoold
Add and save the following contents:
[Unit]
Description=Run ydotoold
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/run_ydotoold.sh &
User=root
[Install]
WantedBy=multi-user.target
After creating the file, enable and start the service using systemctl:
>sudo systemctl enable /etc/systemd/service/ydotoold.service
>sudo systemctl start ydotool.service
>sudo systemctl status ydotoold.service
If all goes well you should see that the service is now active and running:
Test ydotool
It should now be possible to use ydtool to move the mouse.
Open a terminal in the GUI desktop (not SSH)
set the YDOTOOL_SOCKET environment variable (don't skip this step!)
> export YDOTOOL_SOCKET=/tmp/.ydotool_socket
run a test command
> /usr/local/bin/ydotool mousemove --absolute 100 100
If everything has worked, you should see the mouse cursor jump to coordinates 100,100 on the screen
Add ydotool to the digital sign launch script
The final step is to add the ydotool command to our digital signage launch script.
Edit pysign/pysign_launch.sh and change it to the following:
#!/bin/bash
#Move mouse
export YDOTOOL_SOCKET=/tmp/.ydotool_socket
/usr/local/bin/ydotool mousemove --absolute 1000 1000
#run chromium using playwright
cd /home/pi/dev/pysign
source ./pysign_env/bin/activate
python3 ./pysign.py
This inserts a command to move the mouse off screen before launching the browser.
Conclusion
..and with that we are done. Hiding the mouse cursor turned out to be just as complex as automating the browser window, but the end result is worth the effort!
Obviously, huge thanks are due to the people who maintain the ydotool repository. Once you understand how to make it work, it is a very useful tool for automating a Wayland desktop.