Setting environment variables before i3wm starts

I’m looking to vary some parts of my ~/.config/i3/config file based on how many output displays are connected to my computer. So far, I could only think of two ways to do this: 1) generating the ~/.config/i3/config with the use of a script 2) using the include mechanism in the i3 config.

I prefer the second option, but I cannot think of any way to implement it without using some kind of environment variable that is set before an i3 session starts.

The idea is to have, say two separate config files (~/.config/i3/three-monitor.conf and ~/.config/i3/single-monitor.conf), which will then be included inside the main config.

Selecting the config to be included can be done by setting an environmental variable, say, DISPLAY_MODE inside my monitor.sh script.

#monitor.sh
xrandr --output VGA1 --above eDP1
xrandr --output HDMI1 --right-of VGA1

output=$(xrandr --listactivemonitors)
#$output would be something like:
#Monitors: xx
#0: +*eDP1....
#1: +....
# etc. etc.

number_of_active_monitors=$(echo $output | awk '{print $1}'|cut -d -f 2)

#After this, set DISPLAY_MODE to either "single-monitor" or "three-monitor" with a case statement
#Inside ~/.config/i3/config

include ~/.config/i3/$DISPLAY_MODE.conf

#etc. etc.

Where do you guys recommend I define the DISPLAY_MODE environment variable? Is it better do it inside ~/.xprofile, ~/etc/xprofile, ~/.xsession, or ~/.xinitrc?

UPDATE:

I managed to create the environment variable by adding a line in /etc/environment

But now, I’m having trouble setting its value from within ~/.config/i3/config

I thought exec --no-startup-id source ~/.screenlayout/monitor.sh would do the trick, but it didn’t. The environment variable DISPLAY_MODE exists, but its value wasn’t changed.

The contents of ~/.screenlayout/monitor.sh look something like this:

#!/bin/sh
xrandr --output eDP1 --primary --mode 1920x1080 --pos 0x1080 --rotate normal --output DP1 --off --output DP2 --off --output HDMI1 --mode 1920x1080 --pos 1920x0 --rotate normal --output HDMI2 --off --output VGA1 --mode 1920x1080 --pos 0x0 --rotate normal --output VIRTUAL1 --off --output eDP-1-2 --off --output DVI-D-1-1 --off

output=$(xrandr --listactivemonitors)
number_of_monitors=$(echo $output | cut -d " " -f 2)

if [[ "$number_of_monitors" == "1" ]]; then
    DISPLAY_MODE="_single_monitor"
fi

if [[ "$numer_of_monitors" == "2" ]]; then
    DISPLAY_MODE="_dual_monitor"
fi

if [[ "$number_of_monitors" == "3" ]]; then
    DISPLAY_MODE="_three_monitor"
fi

I expected DISPLAY_MODE to be set to “_three_monitor” as I’m currently on a three monitor set-up, but it didn’t.

The only way I could set DISPLAY_MODE is by sourcing it directly in my terminal:

cd ~/.screenlayout
source ./monitor.sh

I don’t use i3 (I use LeftWM). But, I did something similar for my multi-monitor setup and use ~/.xprofile as it’s user profile specific. I don’t change the number of my monitors or their orientation very often, but maybe this script will give you some ideas for your setup.

outputs=($(xrandr --current | sed -n 's/\([^ ]*\) connected .*/\1/p'))
#xrandr --setprovideroutputsource modesetting NVIDIA-G0
#xrandr --setprovideroutputsource modesetting NVIDIA-0
for out in ${outputs[@]}; do
    if [[ $out == "DP-2" ]] ;  then
        xrandr --output DP-2 --mode 2560x1440 --pos 3440x0 --rotate left
    elif [[ $out == "DVI-D-1" ]] ; then
        xrandr --output DVI-D-1 --mode 2560x1440 --pos 3440x0 --rotate left
    elif [[ $out == "DVI-D-1-0" ]] ; then
        xrandr --output DVI-D-1-0 --mode 2560x1440 --pos 3440x0 --rotate left
    elif [[ $out == "DVI-D-0" ]] ; then
        xrandr --output DVI-D-0 --mode 2560x1440 --pos 3440x0 --rotate left
    elif [[ $out == "DP-1-0" ]] ; then
        xrandr --output DP-1-0 --mode 2560x1440 --pos 3440x0 --rotate left
    else
        xrandr --auto
    fi
done
for out in ${outputs[@]}; do
    if [[ $out == "DisplayPort-2" ]] ;  then
        xrandr --output DisplayPort-2 --primary --mode 3440x1440 --pos 0x900
    elif [[ $out == "DP-3" ]] ;  then
        xrandr --output DP-3 --primary --mode 3440x1440 --pos 0x900
    elif [[ $out == "DP-1-3" ]] ; then
        xrandr --output DP-1-3 --primary --mode 3440x1440 --pos 0x900
    elif [[ $out == "DP-1-2" ]] ; then
        xrandr --output DP-1-2 --primary --mode 3440x1440 --pos 0x900
    else
        xrandr --auto
    fi
done
2 Likes

How complex is your included config? This may help you if it is not extreamly complex.

@KDen

I just added this line into my ~/.xprofile:

export DISPLAY_MODE=""

It didn’t work. After rebooting and running printenv, the environment variable wasn’t set.

After poring through pages of documentation to figure out how to use systemd unit files to set environment variables, I suddenly realized that none of this was necessary. I’ve figured out a much simpler (and cleverer) way to solve this problem: using symbolic links.

Here is my solution:

#Inside ~/.screenlayout/monitor.sh

xrandr --output ..... #xrandr calls generated by arandr

output=$(xrandr --listactivemonitors)
number_of_monitors=$(echo $output | cut -d " " -f 2)
name_of_symlink="/home/anthony93/.config/i3/additional_monitor_config"
reset_symlink(){
    if [[ -L $1 ]]
    then
        rm $1
    fi
}

reset_symlink $name_of_symlink

if [[ "$numer_of_monitors" == "2" ]]
then
    ln -s "/home/anthony93/.config/i3/config_dual_monitor.conf" $name_of_symlink
elif [[ "$number_of_monitors" == "3" ]]
then
    ln -s "/home/anthony93/.config/i3/config_three_monitor.conf" $name_of_symlink
else 
    ln -s "/home/anthony93/.config/i3/config_single_monitor.conf" $name_of_symlink
fi

Now, all I have to do is organize my display configurations in three separate files ( ~/.config/i3/config_single_monitor.conf, ~/.config/i3/config_dual_monitor.conf, and ~/.config/i3/config_three_monitor.conf), and then point a symbolic link to the right file based on the output obtained in monitor.sh

The symbolic link would then be included inside i3’s main config file

include ~/.config/i3/additional_monitor_setup 

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.