randrctl — profile-based screen manager for X

3 minutes read

While having some free time, decided to automate one of my daily routines — setting up external display.

Idea appeared long before I was told about famous (or not?) autorandr project. So if you are familiar with autorandr, you are already familiar with randrctl idea.

Idea

How often have you to plug external display to your laptop, how many different setups do you have? I have 3: no external display, office setup, where laptop stands below old 19" external display and home setup, where laptop stands beside of my shiny 23" fullhd display. To set them all up, I created 3 scripts in my home directory: lvds.sh, office.sh, home.sh.

That couldn’t be good. So I decided to develop an utility to manage my screen setup in the same way networks are managed in archlinux. So instead of calling custom shell script, it would be possible to do something like

$ randrctl switch-to office

randrctl

And here it is: https://github.com/edio/randrctl) (tah-dam!). Project has a descriptive readme (I believe[randrctl on github], but here is a brief list of what is done already

  • support for display mode (resolution), position, rotation and panning (the latter is not supported in autorandr afaik)
  • switching between profiles
  • executing custom commands before and after the switch or in the case randrctl fails
  • profile creation from current screen setup

Under the hood it performs calls to xrandr utility to get info about current setup and to apply new settings.

Installation

Installation instructions are on github. Basic idea is that you clone a git repo and allow python to install the module. And then you copy exemplary configs to specific locations and copy completion functions for bash and zsh if you need them.

For archers there is a package on AUR.

Configuration

All configuration is currently stored under /etc/randrctl/ (which may be not such a good idea, because screen setup usually do not require root privileges, I know. I’m working on it).

/etc/randrctl/config.ini allows to declare custom commands on profile switch or failure. The whole property value gets executed in a shell, so all these &&`s, `||`s, pipes and redirections are supported. While composing your custom commands, you can get profile name from `$randr_profile environment variable. Error, if it happens, is stored to $randr_error.

Profiles are stored under /etc/randrctl/profiles/ as plain text files in json format. Profile structure and property names are self-descriptive, I believe:

{
    "outputs": {
        "LVDS1": {
            "mode": "1366x768",
            "panning": "1366x1080"
        },
        "DP1": {
            "mode": "1920x1080",
            "pos": "1366x0".
            "rotate": "inverted"
        }
    },
    "primary": "DP1"
}

Usage

Running randrctl without parameters (or with canonical -h or --help) will tell you all you can do with it. And you can:

  • check your current screen setup

    $ randrctl show

  • dump it to file (note that root is required here)

    # randrctl dump my_setup

  • check stored profiles

    $ randrctl show my_setup

  • list your profiles

    $ randrctl list

  • and finally, apply profile settings

    $ randrctl switch-to my_setup

Planned features

Right now I’m thinking about 2 things:

  1. autodetecting when display is plugged via udev and applying profile, that matches display EDID (I come with this idea before knowing about autorandr, I swear ;))
  2. support for user profiles and configurations. This will allow to run randrctl without root

Of course there is always a room for code and experience improvements, so these will take place also.