1

The xdotool command allows us to create scripts controlling the graphical user interface of the system very easily. I can e.g. open my Chrome browser in the following desktop by executing xdotool mousemove 26 146 click 1.

enter image description here

So, let's say that I create a new user to my system:

# adduser newuser

If I log with newuser in a different session and execute xdotool commands they work perfectly fine. But well, let's say that I've opened two different GUI sessions in different ttys, one with my regular user and other with newuser, and let's also say that I'm currently running a GUI session with my regular user and I create the following script:

#!/bin/bash

xdotool mousemove 31 61 click 1

Then I save it as macro.bash on my home folder and execute chmod 777 ~/macro.bash to set the right permissions for it. Finally, I open a new terminal and I log as newuser (while I'm currently using my regular user session):

$ su newuser

Now if I try to execute my script I get the following error (see EDIT):

newuser@myPC:~$ /home/myregularuser/macro.bash 
No protocol specified
Error: Can't open display: (null)
Failed creating new xdo instance

This script works fine if I try to execute it while running a GUI session logged as newuser, but my goal here is to have a macro tool that can control the graphical interface of the newuser session with scripts while I'm using my regular user session. Is it possible? Does anyone know a workaround to solve this error?


EDIT

As quixotic said in the comments and telcoM said on his answer I was missing setting the right values of the environment variables $DISPLAY and $XAUTHORITY. Although I didn't manage to solve my problem as described on telcoM's answer, I managed to solve it with the following process:

1- Logging into my newuser session.

2- Inserting the following commands as the last lines of the ~/.bashrc file:

if xhost >& /dev/null; then
   echo "export DISPLAY=\"$DISPLAY\"" > $HOME/.variableMemory
   echo "export XAUTHORITY=\"$XAUTHORITY\"" >> $HOME/.variableMemory
fi

3- Changing my script making it redefine the $DISPLAY and $XAUTHORITY variables to their right values while the script is executed:

#!/bin/bash

source $HOME/.variableMemory
xdotool mousemove 31 61 click 1

With this, I'm basically capturing and saving the values of the $DISPLAY and $AUTHORITY variables when I first log on the newuser session with the graphical interface, so I can use these values when I log with the shell later.

Now I don't see any errors and I can move the mouse around the other session with the xdotool commands perfectly when I execute the script, but I have a new problem: The Xorg that is in a different GUI session is frozen while it's not being used. To sum up, it queues all the clicks that I send to it and then it releases all of them at once when I manually switch to that particular GUI session (and that makes xdotool unusable)... So, the question still remains: Is it possible to control a GUI session with a macro tool while I'm running a different GUI session? Is there a Xorg configuration that disables this "freezing behavior" so it receives the click commands on real time even when I'm not using that session?


Additional information

  1. I'm running Ubuntu 18.04.
  2. The display server used is Xorg (with Wayland xdotool doesn't work at all but this question isn't related to Wayland).
  3. GNOME is the graphical user interface I'm currently using.
  4. My main goal is to use a macro tool to control a screen that I'm not physically using, so I can use the computer while the macro does its job. Although I chose xdotool, Ubuntu, Xorg and GNOME to solve this problem, I'm open to answers that solve this same problem with different tools, desktop environments or even different Linux distributions... Thanks!!
7
  • It can control any X server you're authorized to. Jun 18, 2018 at 1:49
  • @IgnacioVazquez-Abrams But how can I change the authorization of the X server in the context of my question? Jun 18, 2018 at 1:52
  • the error you see is because there's no $DISPLAY set in newuser's shell; xdotool uses that to determine which X server it should be talking to.
    – quixotic
    Jun 18, 2018 at 4:02
  • @quixotic Ah, yeah... That's true. I've edited my question now... Setting the $DISPLAY variable solved only part of the problem but my script still doesn't work completely. Jun 18, 2018 at 4:45
  • can you give details as to how the 2nd user gets logged in? via another VT? textmode console or graphical? if text how is the X session started? what do you normally do to switch between the 2 users?
    – quixotic
    Jun 20, 2018 at 2:29

1 Answer 1

1

The other component you're missing is the .Xauthority file. It contains a "session cookie" that is generated anew each time a X11 server restarts, and the client is required to have it in order to send any commands to the X11 server. This file is normally located in ~/.Xauthority, although you can use the $XAUTHORITY environment variable to specify an alternate location.

In order to control the GUI session that isn't yours, you'll need to gain access to the session cookie of that other session. If it has a different $DISPLAY value, you could simply copy that session cookie into your .Xauthority file using xauth extract and xauth merge commands:

su newuser -c "xauth extract /home/newuser/.Xauthority $newuserDISPLAY" | xauth merge

The .Xauthority file can hold multiple session cookies for different DISPLAYs at the same time.

Or if the session cookie is located in a file that is already accessible to you, you can use the $XAUTHORITY variable to point at it.


This is starting to seem like an XY problem: you have something you want to achieve, and may have fixated on xdotool as the assumed way to do it.

But when you are trying to automate something, going through the motions of the GUI using xdotool is usually the least convenient way to do it. For example, if you want to automate starting Google Chrome as a specific user, you don't need to simulate clicking an icon: you could just arrange for the right identity and environment, and just start the process you want.

For example, to start google-chrome as user newuser, you might do:

su -lc "DISPLAY=<whatever> google-chrome" newuser

As the su command has the -l option, the google-chrome process will have the right $HOME for newuser, and so it will look for .Xauthority in the default location, i.e. ~newuser/.Xauthority. You just need to supply the correct value for the $DISPLAY variable that matches the actual running GUI session of newuser. If you want Google Chrome to open a specific URL, you can specify it as an argument for google-chrome within the double quotes.

1
  • All users are supposed to have a .Xauthority file? In my case, I've realized that just my regular user has a .Xauthority file. There's no one located in /home/newuser/.Xauthority and the value of my $XAUTHORITY environment variable is /run/user/1000/gdm/Xauthority. Would the command still be the same in this case? I see an error when I run it. I'm going to append the results in my question... Jun 18, 2018 at 19:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .