khanshoaib3 / minecraft-access

A mod for minecraft java (fabric/neoforge) that adds accessibility feature
GNU General Public License v3.0
45 stars 10 forks source link

[Linux] Replace `xdotool` with an alternate to better support wayland #302

Open khanshoaib3 opened 1 month ago

khanshoaib3 commented 1 month ago

ydotool is an alternative to xdotool which not only supports wayland but also x11 and others. A much better choice than xdotool.

boholder commented 3 weeks ago

This info might be helpful to this issue, posted by @Aya-Komichi in https://github.com/khanshoaib3/minecraft-access/issues/310#issuecomment-2304359402_

Aya-Komichi commented 3 weeks ago

In addition to what I mentioned in #310 (comment), I will add here the information I gathered about ydotool.

The tool itself is rather finicky imo, at least on my arch linux based OS installing it is not enough to get things running. This tool relies on a daemon that ideally should run in the background since it doesn't just send things directly to x11 or wayland. In my experience the installation of ydotool comes with a user level systemd service file to automatically start the ydotoold daemon.

From my research, different linux distributions may bring in different service files for this daemon or none at all. The file I got in arch is actually nearly useless since not only it does not start the command with the necessary flags, but at least for the mouse movement to work correctly with ydotool, the service started needs to be a system level service and not a user level one, because the daemon works better with root permissions. Additionally, the socket path and socket ownership flags need to be set appropriately.

I had to create a system level service file based on the user level service file I was provided. After the necessary edits, the file looks like this:

[Unit]
Description=Starts ydotoold service

[Service]
Type=simple
Restart=always
ExecStart=/usr/bin/ydotoold -p <home-path>/.ydotool_socket -o 1000:1000
ExecReload=/usr/bin/kill -HUP $MAINPID
KillMode=process
TimeoutSec=180

[Install]
WantedBy=default.target

The needs to be replaced by the path to the home directory of the user. The numbers next to the -o flag are the user id and the user group id which respectively, both are 1000 by default. The home path and ids need to be hardcoded since otherwise trying to use the systemd unit specifiers on a system level service will result in the root home directory and ids being used on the command instead. This is probably the reason why the user service included in the package installation isn't that useful by default.

Alternatively, a user can also just run the following command whenever they login: sudo -b ydotoold -p "$HOME/.ydotool_socket" -o "$(id -u):$(id -g)"

Problem is, by default the acceleration profile of the ydotoold pointer might be set to adaptive, which leads to the weird unexpected behaviour I commented in the issue I had opened. With the adaptive profile, trying to move the cursor to x 10 y 10 for example will end up with the mouse going to x 20 y 20, as described here. On the comment I linked, the solution works for x11. For a wayland environment the command itself might depend on the desktop environment or window manager used, since wayland is just a display protocol unlike x11.

With the daemon running in the background, an additional thing should be done. The environment variable YDOTOOL_SOCKET should be set in the ~/.profile file to be equal to the socket path set in the service file example. The home path here does not need to be hardcoded and so one can just write export YDOTOOL_SOCKET=$HOME/.ydotool_socket in the file.

The reason why the socket path should be specified is because ydotool and ydotoold with user permissions set the socket to /run/user/1000/.ydotool_socket and with root permissions they set it to /tmp/.ydotool_socket. The socket path should remain consistent between the system level service of the daemon and the ydotool commands sent in the terminal by the user and should ideally be a path easily accessible by both the service and user commands.

So in summary, for a hassle free ydotool setup, one needs to create a system level systemd service file similar to my example, enable the service to autostart the ydotoold daemon every time the system is booted up and set the environmental variable in the ~/.profile file in order for any and all ydotool commands sent to use the same socket as the daemon.

I may test my own jar of this mod with my setup complete. So far I know the mouse clicking simulation worked with the ydotool command strings I set in the code, but I don't know yet if the mouse movement for the inventory controls work.

Update: well the inventory controls don't seem to work yet for me, I don't know if version 1.4.3 of the mod had a bug with these, I didn't test the jar with the xdotool command strings. I guess someone will really have to test them on a newer version.

khanshoaib3 commented 2 weeks ago

@Aya-Komichi Yeah, ydotool did not worked for me either. I dislike the idea of having a systemd service either. The reason why this issue hasn't been closed yet although it should've been re-titled.

We should look for more alternatives.