Adding a new monitor to my exwm setup

Table of Contents

img

I recently shuffled things with my office and found that I have hardware and ports for a third monitor to connect to my exwm setup. So, without further ado, how to get it going and registered with Linux/EXWM?

Edit [2022-01-02 Sun] an easier way with arandr

Downloading and installing arandr made this whole configuration much simpler than using the raw randr output. I finally made the jump when I was receiving an error at my attempts to load it manually: xrandr: Configure crtc 2 failed. I then just installed arandr from my repos (Tumbleweed z in arandr), lined up my monitors with the desired resolution, and hit “apply”. When I saw it worked I saved the generated configuration and loaded it into my auto-load locations instead of the below. At the end of the day, my localconfig.el (which I load at every startup) had an entry like this:

(defun tsa/trimon ()
  "Set up the three-monitor home setup to be used in an exwm hook. Output via arandr."
  (interactive)
  (setq exwm-randr-workspace-monitor-plist '(1 "DP-1-1"
                                               2 "DP-1-2"))
  (start-process-shell-command
   "xrandr" nil "xrandr --output eDP-1 --primary --mode 1600x900 --pos 1600x0 --rotate normal --output DP-1 --off --output HDMI-1 --off --output DP-2 --off --output HDMI-2 --off --output DP-1-1 --mode 1600x900 --pos 0x0 --rotate normal --output DP-1-2 --mode 1600x900 --pos 3200x0 --rotate normal --output DP-1-3 --off"))

One more Gotcha was that my dock, a Totu, was failing to handle two HDMI connections, despite having two ports. Turns out that is what that USBC-in on the dock is for; HDMI take more power to transmit operate the wire than do the SVGA I was using previously, and I needed to plug in some USB-C-provided power (an old phone charger) to get it to work with two HDMI plugged in. Note that this wasn’t powering the monitor, as I couldn’t understand. This is powering the HDMI connection itself. And now I wonder if the year of issues I have assumed were just EXWM failing to deal with three monitors was, in fact, the occasional slips from having just barely sufficient power to power all the monitor connections. I’ll be watching for this.

Discover the new monitor

First, I plug my 3rd monitor into my dock. It’s a vga connector, so I get it plugged in and powered up. Ok – upon starting it, I see it has power and that it has a blank black screen (ie without a “not connected” message): it’s physically set up but needs to have the computer send meaningful stuff to it.

Get xrandr set up

xrandr is the program to handle monitors. Here are several steps.

1. Locate the screen name/port

>$ xrandr -q
# ... a bunch of stuff about my other ports and monitors ELIDED. Below is the new one:
DP-1-3 connected 1920x1080+6400+0 (normal left inverted right x axis y axis) 509mm x 286mm
   1920x1080     60.00*+
   1280x1024     60.02  
   1440x900      59.89  
   1280x800      59.81  
   1152x864      75.00  
   1024x768      70.07    60.00  
   800x600       60.32    56.25  
   640x480       66.67    59.94  
   720x400       70.08  

2. Obtain the configuration line that xrandr needs

From the previous command I see that the desirable available resolution is 1920x1080 and the refresh rate is 60, so I put those into the gtf command to get the randr line I’ll need:

>$ gtf 1920 1080 60 | grep Modeline | cut -d' ' -f4-
"1920x1080_60.00"  172.80  1920 2040 2248 2576  1080 1081 1084 1118  -HSync +Vsync

3. Apply randr


# Create a new resolution mode
>$ xrandr --newmode "1920x1080_60.00"  172.80  1920 2040 2248 2576  1080 1081 1084 1118  -HSync +Vsync

# Add the new mode to the desired output we got from step 1 above
>$ xrandr --addmode DP-1-3 1920x1080_60.00
>$ xrandr --output DP-1-3 --mode 1920x1080_60.00

At this point our x window system should be all on-board with the new screen and is ready to use it. Now we just need exwm to utilize it.

4. Add screen to exwm

On my system I have a local-config.el that I reference for setup-specific situations, which is not under version control like my emacs.el is. For my laptop at home on the dock, I supplement it to look like this:

(setq exwm-randr-workspace-monitor-plist '(0 "eDP-1"
                                             1 "DP-1-1"
                                             2 "DP-1-3"))
  (add-hook 'exwm-randr-screen-change-hook
            (lambda ()
              (start-process-shell-command
               "xrandr" nil "xrandr --output DP-1-3 --right-of eDP-1 --output DP-1-1 --left-of eDP-1")))

With that elisp evaluated, then adding a new emacs workspace with C-x 5 2 and voila – I have my 3rd monitor reading and working! Once all is verified I make sure it’s persistent by adding those lines from step 3 to my ~/.xinitrc file, so it will configure the monitor (if present) on startup.

Cautions & Conclusion

Two words of caution I discovered from mishaps in my project.

First, when I didn’t like the resolution I saw on the “new” monitor (actually about a decade old), I tried it out in my non-exwm boot (KDE), where I fiddled with the display controls to see whether it was my xrandr setup causing the blurriness. Now, I found that a lower resolution made things much less blurry – good! However, when I went to switch to the lower resolution (mostly following the steps above), I found that use of KDE to change display settings had apparently deleted my .xinitrc file! Unforgivable! Fortunately I was able to recover it from a recent back up and supplement it appropriately. EDIT: false alarm. It was actually my exwm toggle script that had moved it safely out of the way since I was booting without exwm.

Then, when I started up with my shiny new xinitrc into exwm, I found that the third monitor was goofily showing half of my 2nd monitor on it and annoying clipping things were happening. I fixed this by explicitly setting the second monitor therein, and removing the “auto” keyword. When all was said and done we had peace, and my xinitrc looked as follows, and I also added a .bak copy of it just in case bad things happen again.

  1. xinitrc

    # My original HDMI extra monitor
    xrandr --newmode "1600x900_60.00"  118.25  1600 1696 1856 2112  900 903 908 934 -hsync +vsync
    xrandr --addmode eDP-1 1600x900_60.00
    xrandr --output eDP-1 --mode 1600x900_60.00
        
    # My laptop monitor, which can go all the way to 4k but it isn't usable that way
    xrandr --addmode DP-1-1 1600x900_60.00
    xrandr --output DP-1-1 --mode 1600x900_60.00
        
    # My new 3rd monitor from this post
    xrandr --newmode "1440x900_59.89"  106.28  1440 1520 1672 1904  900 901 904 932  -HSync +Vsync
    xrandr --addmode DP-1-3 1440x900_59.89
    xrandr --output DP-1-3 --mode  1440x900_59.89
        
    xscreensaver & # my screensaver
        
    dunst & # My notification system
        
    nm-applet & # I like to see the wifi settings in my taskbar
        
    syndaemon -i 0.5 -t -K -R -d
        
    # Java requirements below
    wmname LG3D
    export _JAVA_AWT_WM_NONREPARENTING=1
        
    # My cursors
    # Load cursor theme, etc
    # xrdb ~/.Xresources
    export XCURSOR_THEME=Scraft
        
    # So that the "locate" command is ready to go when necessary
    updatedb
        
    # and finally, start exwm! 
    exec emacsclient -a "" -c
    
  2. local-config.el

    This is the non-controlled file that emacs/exwm uses to start everything, including the xrandr command that aligns my screens.

    (setq exwm-randr-workspace-monitor-plist '(0 "eDP-1"
                                             1 "DP-1-1"
                                             2 "DP-1-3"))
      (add-hook 'exwm-randr-screen-change-hook
            (lambda ()
              (start-process-shell-command
               "xrandr" nil "xrandr --output DP-1-3 --right-of eDP-1 --output DP-1-1 --left-of eDP-1")))
    

Resources

Tory Anderson avatar
Tory Anderson
Full-time Web App Engineer, Digital Humanist, Researcher, Computer Psychologist