My i3 monitor configurator project


#1

Setting up a “base station” for Leveno ideapad, with 24in monitor. Wanted a way to have i3 default to using only the HDMI-out when it is connected to that monitor, instead of having to open arandr each time, as well as fixing the Wallpaper each time.
The Leveno does connect to HDMI if present at Boot, but defaults to “duplicate screens”

Added this to my ~/.i3/config:

exec --no-startup-id /home/[user]/.screenlayout/setdisplay.sh

This needs to run before the line that runs nitrogen – restore, at least on my system, changing monitor configuration results in odd wallpaper effects, requiring nitrogen --restore. My ~/.config/nitrogen/bg-saved.cfg contains the correct image for both screens. Apparently there are no ill effects to nitrogen’s effort to restore 2 screens when one is NOT connected.

setdisplay.sh:
#!/usr/bin/bash
#
# Set preferred monitor config
# Designed for a Laptop with only one HDMI Port
# 
hdmi_ex=`xrandr --current | grep 'HDMI1 connected' | wc -l`
[ $hdmi_ex -eq 1 ] &&  $HOME/.screenlayout/LG24-Only.sh

To detect if the HDMI monitor is plugged in, if not, does nothing.

LG24-Only.sh is simply the xrandr script generated by arandr.

Works on startup as intended. Next I plan to add a utility to switch to other options, such as BOTH internal and external screens, or just to internal. I do not switch monitor set ups on the fly enough to bother with writing something to detect monitor changes and respond automatically (as far as I researched, one would need to add a script of service for that, not sure I need that level of magic…)

I am not new to programming but am new to bash, and welcome any input about my code or tactics… (I know this would have to have a good bit more in it to be portable…)


#2

That looks great and is a useful script. I suggest you also post it to the official i3 forum on reddit.


#3

Very useful script indeed.
.

I have 2 monitors connected on my PC, and sometimes I want to mirror the screens so that I can watch a video on one screen and turn the other facing the couch so that whoever’s sitting there can watch too.
I always wanted to make a keybind that does the switching for me and it was only after switching to i3 that it became so simple to do.

# Monitors layout. F12->spanned  F11->mirrored
bindsym $mod+Shift+F11 exec --no-startup-id xrandr --output DP-1 --mode 1920x1080 --primary --output HDMI-0 --mode 1920x1080 --same-as DP-1
bindsym $mod+Shift+F12 exec --no-startup-id xrandr --output DP-1 --mode 1920x1080 --primary --output HDMI-0 --mode 1920x1080 --left-of DP-1

Your solution to your problem is much cooler though :stuck_out_tongue:


#4

Thanks for the encouraging reviews :grinning:
@mynameisyiannis I like your idea also, actually that got me thinking I might build a “mode” in i3.conf, to switch between various set-ups when needed.


#5

Hey @CapnJak , I happen to know a tool that does exactly what you want to do - autorandr :slight_smile:
It allows you to save various monitor configurations and it’s smart enough to load the right one based on monitors that are currently connected.
I think you can also make use of udev rules to make it change the configuration dynamically as monitors are connected/disconnected.
It has tons of features, so I recommend reading the readme on Github.
Hope this helps :slight_smile:


#6

@bajolo Oh… yes that is a very comprehensive solution !
Thanks :sunglasses:


#7

Hey, one question. Im on a desktop, so I always have 2 monitors connected, but I switch from mirrored, to spanned. In a few hours 2 monitor arms will arrive :D:D so I will also have one of the 2 monitors vertical at some times. Is there a way to have 1 key-bind to toggle between the 3 modes using autorandr? I don’t know if I can make a script for that.


#8

Assuming you want to have single key that performs a cyclic toggle through three set-ups, say span, mirror, and one flipped (or any configs you want to save):
As far as I know, unless your monitor has a way of reporting to the OS which way it is turned, I know of no option to auto-detect if you turn your screen.
I have not installed autorandr to completely test this, but I took a stab at a bash script that would recall the last mode set, “increment” that and set the next mode in the cycle each time it is called.

# disptoggle.conf: List names of saved modes, one per line; eg:
mirror
span
flip
# dispset.conf: the named mode last set.  To begin, make a file with one mode listed

#!/bin/bash
# disptoggle.sh - cycle through saved display modes, once per call.  
# Bind this to a bindsym in i3.conf
# Read files for possible options, and current option.  Fill out complete paths to where these are
read activemode < dispset.conf
readarray -t modes < disptoggle.conf

# Relate current mode to available modes
modecount=${#modes[*]}
for mode in ${!modes[*]}
do
    [ "${modes[mode]}" = "$activemode" ] && break
done
# increment mode, adjust to "rollover" in sequence
mode=$((mode+1))
mode=$((mode%modecount))

# set the correct mode.  I did not test this line.
autorandr --load  ${modes[mode]}

# Update current saved mode
echo ${modes[mode]} > dispset.conf

The cycle-toggling logic appears to work at least. Hope this gives you a springboard to experiment. Pretty sure this could also be used with xrandr, rather an sending the mode to autorandr, you could have scripts fashioned by arandr, and modify the “autorandr” call line to call the appropriate .screenlayout script.

(Script above is not error-proofed - I may add some protection for missing files and other things next time I have time to play).


#9

Thanks for the script I think I may be able to make this work. I didn’t expect the script to identify the monitors orientations. I would manually toggle the mode. I was hoping to use 1 key-bind instead of 3.

This is my current solution. (The second monitor is upside down. I’m waiting for a longer HDMI cable :stuck_out_tongue: )
Edited:

# Monitors layout. F12 → spanned  F11 → mirrored F10 → horizontal+vertical screens
set $lgmonitor DP-1
set $samonitor HDMI-0
bindsym $mod+Shift+F10 exec --no-startup-id xrandr --output $lgmonitor --mode 1920x1080 --primary --output $samonitor --rotate left --mode 1920x1080 --right-of $lgmonitor
bindsym $mod+Shift+F11 exec --no-startup-id xrandr --output $lgmonitor --mode 1920x1080 --primary --output $samonitor --rotate inverted --mode 1920x1080 --same-as  $lgmonitor
bindsym $mod+Shift+F12 exec --no-startup-id xrandr --output $lgmonitor --mode 1920x1080 --primary --output $samonitor --rotate inverted --mode 1920x1080 --right-of $lgmonitor

Thank you for the script I think I can do it .


#10

Now that is an ingenious solution… way to think outside the box :+1:


#11

Hahahahaha thanks. Big desk, cable management and short cables don’t mix very well.


#12

I know you’ve already found a better solution, but I don’t think my idea is worth a new post so I want to add it here.

# Monitors layout.
set $lgmonitor DP-1
set $samonitor HDMI-0
bindsym $mod+Shift+F12 mode "$mode_display"
set $mode_display Monitor layout (m) mirrored, (d) dual, (Shift+d) dual-horrizontal+vertical
mode "$mode_display" {
    bindsym m exec --no-startup-id xrandr --output $lgmonitor --mode 1920x1080 --primary --output $samonitor --rotate inverted --mode 1920x1080 --same-as  $lgmonitor; exec feh --bg-center $wallpaper, mode "default"
    bindsym d exec --no-startup-id xrandr --output $lgmonitor --mode 1920x1080 --primary --output $samonitor --rotate inverted --mode 1920x1080 --right-of $lgmonitor; exec feh --bg-scale --no-xinerama $wallpaper, mode "default"
    bindsym Shift+d exec --no-startup-id xrandr --output $lgmonitor --mode 1920x1080 --primary --output $samonitor --rotate left --mode 1920x1080 --right-of $lgmonitor, mode "default"
    # back to normal: Enter or Escape
    bindsym Return mode "default"
    bindsym Escape mode "default"
}

$wallpaper must be set too, but I have it on a different section in my config, and I don’t think its necessary to add it here.
set $lgmonitor and set $samonitor are the names I gave to my monitors, so I can easily change the display port, if I have to.


#13

I like the implementation of the “mode” concept. Also this includes the wallpaper adjustments with no extra scripts. Nice.


#14

I don’t like using “external” scripts. I prefer to keep everything in the i3 config, .bash_profile, .xinitrc… you get the point. I’m trying to find what I’m going to do when the right screen is vertical. Maybe 2 different pictures? But the “mode” working great; I only have to use 1 key-bind, and I kept forgetting which key-bind did what :stuck_out_tongue:


#15

Oh… I had that problem too… if you use conky-short cuts, you could modify that to give yourself a list of favorites…

You mean Wallpapers for different orientations? When I had different aspect-ratio screens in my set up, I just saved instances of the WP at the needed resolutions and called the applicable ones. Granted this did not involve vertical screens.

If I had a vertical screen, I would find a giant version of my WP and then craft out a vertically oriented clip from it and use that.

That’s probably about where my experiments would stop… I just have one monitor output… for now.:wink:


#16

I remember all of the key-binds, but I don’t change the screen layout a lot, and I made the keybind 2 weeks ago, so the 2 times I had to use it I had to look it up