Browser block - how to swap input's axis?

the Browser block allows us to rotate the screen using env vars but I didn’t manage to correctly configure the touch inputs yet.

my setup:

  • I am using an Intel NUC, and portrait LG TV, and a touch film.
  • I am running the browser block with the ROTATE_DISPLAY set to right.

The touch film works but the axes were wrong and need to be swapped.
Any sugestions?

I think I was able to made some progress by myself, but I am not there yet.

I decided to install a full GUI OS (also X11 based) to do some more testing - based on this tututial.

With the OS configured in landscape mode (default) everything worked as expected, however when I configure the display settings to portrait mode the behavior was the same as the experienced on my setup using Browser Block.

Looking around for a while I was able to fix this:

  1. Install xinput : apt-get install xinput
  2. List the inputs: xinput list
  3. Collect the touch input ID
  4. Invert axis: xinput set-prop <ID> “Evdev Axis Inversion” 0, 1
  5. Swap axes: xinput set-prop <ID> “Evdev Axes Swap” 1

After this, the touch was working as respected.

:warning: Keep in mind the operations 4 and 5 are the ones that allow me to accomplish the right rotation and they are different for other rotations.

Then I back to my Browser Block setup. I SSH into the Browser container and installed xinput . However, I cannot run xinput commands.
I am getting: Unable to connect to X server.

Then I back to the GUI OS setup and try to run the same command using SSH and I get the same result: Unable to connect to X server.

Somehow I was not able to run the xinput commands over ssh.
I think I should use the -X flag in the SSH command but I don’t know how to use the flag with Balena.

Any thoughts on this?
Also, I was open to try other approaches as well :slight_smile:

Thanks a lot,


Hi @ngmartins_FF ,

I am getting: Unable to connect to X server

This is because (by default) when you SSH into a machine, you won’t have the DISPLAY variable set, so xinput commands don’t know which display you are trying to talk to. All you need to do after you SSH in, is run export DISPLAY=:0 (assuming you only have one display), and then all commands will run fine until you exit that SSH session. You will need to run that again the next time you connect.

On that note, if you reboot the device or the containers, you will have to run the xinput commands again, because xinput wont be persistent over reboots.

A good way to make it a permanent change in your full GUI app is to write a file to /etc/X11/xorg.conf.d/49-touch-rotate.conf with an InputClass xorg conf section: (you can change the file name if you need/want to)

Section "InputClass"
    Identifier "evdev touchscreen catchall"
    MatchDevicePath "/dev/input/event*"
    Option "TransformationMatrix" "0 -1 1 1 0 0 0 0 1"
    Driver "evdev"

That TransformMatrix line is the coordinate matrix for a right rotation of all input events. You can see how we do it in our xserver block here:

If that turns out to be the wrong touch rotation, try out the other coordinate matrix lines from that script. Let us know if this works!

– Flynn

Hello @nucleardreamer, I appreciate your help.

I was able to run the export DISPLAY=:0 command but the I keep getting the same output on xinput commands.
However, you mention a very relevant issue with persistence. As so, I move on and try the method you advice:
I was created the .conf file under the /etc/X11/xorg.conf.d directory: It simply worked. I just had to get the right transformation. so again: thank you so much for the guidance.

Meanwhile, there is something in this approach I cannot fully understand. If I hard reset the device, the config file is persisted on the next boot. On the other hand, if I just soft reset the browser service, the file is deleted.
At this stage and for test proposes only I am SSH into the container and create the file manually.

Once again. Thanks for the help,



instead of figuring out manually the right configuration, you can use xinput --map-to-output command, here is a part of a script we’re using:

    OUTPUT=$(xrandr -q | grep connected | sed 's/ connected.*//')
    echo "mapping touchscreen '$TOUCHSCREEN_NAME' to output '$OUTPUT'"
    xinput --map-to-output "$TOUCHSCREEN_NAME" "$OUTPUT"

in our case TOUCHSCREEN_NAME is set in an anv var in Balena Cloud but you could be able to figure it out automatically

@ngmartins_FF ,

I’m not sure about the inconsistency with hard vs. soft resetting the device. One thing I can say is that you will want to make sure you have a persistent data volume for your container, otherwise it’s expected that the file would definitely be gone when you stop/start the container. In the docker-compose.yml you can do this by setting a volume and a volume binding in the service:

       - 'mydata:/etc/X11/xorg.conf.d'  

After you do that, any file you write into the /etc/X11/xorg.conf.d directory will persist in your data volume.

@mathroc has a good suggestion as well! Any of those one-line xinput methods could be added to your entrypoint script before you start your application as well.