~derf / interblag / entry / Automatic Screen Rotation on a Chuwi Minibook X

I recently got myself a new laptop (yes, in 2026, of all times – but at 360€, I'd say the price was quite acceptable): a Chuwi Minibook X. Performance-wise, it's nothing to write home about – it's slightly faster than the X270 I've been using since 2017, and I don't need any more than that. However, with a 10.5" Full HD touchscreen that supports 360° rotation, it's a really nifty netbook / tablet hybrid, and pretty much exactly the type of device that I've been looking for. Especially for hiking and related trips, I like having a laptop with me to pass the time on the train, but a 13.5" laptop was just too unwieldy for that.

When running the Minibook X with Gnome or similar environments, orientation-dependent screen rotation etc. should just happen automatically. In my case, I'm running i3, so I need to do that on my own. And, even if you don't want automatic rotation, you do need to make some changes at least once after booting: the netbook is using a tablet screen, and thus its native orientation is portrait mode.

Boot-Time Screen Orientation

Add the following parameter to the kernel command line (e.g., on Debian, by appending it to GRUB_CMDLINE_LINUX_DEFAULT in /etc/default/grub):

video=DSI-1:panel_orientation=right_side_up

Reading Out the Screen Angle

The netbook contains two identical accelerometers, one in the screen and one in the base. By default, Linux only exposes the one in the screen. There are ways around that, but in my case, a screen-only solution is sufficient.

So: /sys/bus/i2c/drivers/mxc4005/i2c-MDA6655:00/iio:device0/in_accel_?_raw contains raw readings in x, y, and z direction, depending on what you substitute for ?. You could do some fancy trigonometry now, or you could just use the simplest heuristic that you can come up with. I opted for the latter:

def get_accel(axis):
    with open(
        f"/sys/bus/i2c/drivers/mxc4005/i2c-MDA6655:00/iio:device0/in_accel_{axis}_raw",
        "r",
    ) as f:
        x = int(f.read())
    return x


if __name__ == "__main__":
    while True:
        x = get_accel("x")
        y = get_accel("y")
        if x < -500 and mode != "up":
            new_mode = "up"
            # The screen is in normal laptop orientation
        elif x > 500 and mode != "down":
            new_mode = "down"
            # The screen is in inverse laptop orientation ("tent mode")
        if y < -500 and mode != "normal":
            new_mode = "normal"
            # The screen is in its native orientation: it has been rotated into portrait mode so that the hinge is on the left when looking at the screen
        elif y > 500 and mode != "flip":
            new_mode = "flip"
            # The screen has been rotated into portrait mode so that the hinge is on the right when looking at the screen

        # ...

        time.sleep(1)

Changing Screen Orientation

Adjusting the screen orientation actually consists of two commands: one for output (xrandr, as usual), and one for touch input (xinput coordinate transformation matrix). Otherwise, touchscreen events will no longer map to the right display coordinates.

Laptop Configuration ("up")

  • xrandr --output DSI-1 --rotate right
  • xinput set-prop pointer:Goodix Capacitive TouchScreen --type=float Coordinate Transformation Matrix 0 1 0 -1 0 1 0 0 1

The second line sets the 3×3 coordinate transformation matrix to the following value:

 0  1  0
-1  0  1
 0  0  1

Tent Configuration ("down")

  • xrandr --output DSI-1 --rotate left
  • xinput set-prop pointer:Goodix Capacitive TouchScreen --type=float Coordinate Transformation Matrix 0 -1 1 1 0 0 0 0 1

The second line sets the 3×3 coordinate transformation matrix to the following value:

 0 -1  1
 1  0  0
 0  0  1

Tablet Configuration 1 ("normal")

  • xrandr --output DSI-1 --rotate normal
  • xinput set-prop pointer:Goodix Capacitive TouchScreen --type=float Coordinate Transformation Matrix 1 0 0 0 1 0 0 0 1

The second line sets the 3×3 coordinate transformation matrix to the following value:

 1  0  0
 0  1  0
 0  0  1

Tablet Configuration 2 ("flip")

  • xrandr --output DSI-1 --rotate inverted
  • xinput set-prop pointer:Goodix Capacitive TouchScreen --type=float Coordinate Transformation Matrix -1 0 1 0 -1 1 0 0 1

The second line sets the 3×3 coordinate transformation matrix to the following value:

-1  0  1
 0 -1  1
 0  0  1

Toggling Keyboard and Touchpad

Outside of laptop mode, I disable keyboard and touchpad so that I can actually use the device like a tablet.

Disabling Keyboard and Touchpad ("down", "normal", "flip")

  • xinput disable 'AT Translated Set 2 keyboard'
  • xinput disable 'XXXX0000:05 0911:5288 Touchpad'

Enabling Keyboard and Touchpad ("normal")

  • xinput enable 'AT Translated Set 2 keyboard'
  • xinput enable 'XXXX0000:05 0911:5288 Touchpad'

Setting the Wallpaper

After each rotation, you should set the wallpaper again to ensure that it is displayed correctly. How to do that depends on your setup – in my case, I'm using a simple wrapper around feh.

I have uploaded the full auto-rotate script at (sans custom wallpaper-setter) at chuwi-accel.py