Knowledge Base

Preserving for the future: Shell scripts, AoC, and more

Found! Oneliner for nvidia display settings

tl;dr

I finally found a oneliner method for controlling which monitors are actively used for my NVIDIA graphics card after using it for years. Xrandr doesn't cut it when using nvidia.

nvidia-settings --assign "CurrentMetaMode=DPY-4: nvidia-auto-select @1920x1080 +1920+0 {ViewPortIn=1920x1080, ViewPortOut=1920x1080+0+0}, DPY-1: nvidia-auto-select @1920x1080 +0+0 {ViewPortIn=1920x1080, ViewPortOut=1920x1080+0+0}"

Of course the exact settings depend on your setup. You need all the contents after the colons, ::, from this command:

$ nvidia-settings -q CurrentMetaMode

  Attribute 'CurrentMetaMode' (pcb-009:0.0): id=50, switchable=no, source=nv-control :: DPY-4: nvidia-auto-select @1920x1080 +1920+0 {ViewPortIn=1920x1080, ViewPortOut=1920x1080+0+0}, DPY-1: nvidia-auto-select @1920x1080 +0+0 {ViewPortIn=1920x1080, ViewPortOut=1920x1080+0+0}

That's it. I've pondered this ease of use for years, and had actually started an xdotool wrapper but one final Internet search led to this great discovery.

File listings

I of course wrote a script that takes a limited input, "both" or "right" to use those monitors.

files/2023/12/listings/switch-monitors.sh (Source)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/bin/sh
# File: switch-monitors.sh
# Location: /usr/local/bin
# Author: bgstack15
# SPDX-License-Identifier: GPL-3.0
# Startdate: 2023-12-05-3 16:15
# Title: Switch monitor config for NVIDIA graphics card
# Purpose: easily switch between 1 monitor and 2 monitors on pcb-009.
# History: attempt 2. The first was attemping to read nvidia-settings -q dpys and parsing enabled/connected, but I didn't know how to use the derived values
# Usage: Called by tray icon
# Reference:
#    https://wiki.archlinux.org/title/NVIDIA#Using_nvidia-settings
# Improve:
# Documentation:
#    Configure `nvidia-settings` as desired. Print metamode value with following command.
#    nvidia-settings -q CurrentMetaMode
#    Use everything after the `::`

test -z "${DESIRED}" && test -n "${1}" && DESIRED="${1}"
desired="$( echo "${DESIRED}" | tr 'A-Z' 'a-z' )"
case "${desired}" in
   "both"|"left+right"|"left,right","double")
      echo "Using both monitors."
      nvidia-settings --assign "CurrentMetaMode=DPY-4: nvidia-auto-select @1920x1080 +1920+0 {ViewPortIn=1920x1080, ViewPortOut=1920x1080+0+0}, DPY-1: nvidia-auto-select @1920x1080 +0+0 {ViewPortIn=1920x1080, ViewPortOut=1920x1080+0+0}"
      ;;
   "one"|"right"|"single")
      nvidia-settings --assign "CurrentMetaMode=DPY-4: nvidia-auto-select @1920x1080 +0+0 {ViewPortIn=1920x1080, ViewPortOut=1920x1080+0+0}"
      ;;
   *) echo "Unknown option: ${desired}. Aborted." ;
      exit 1 ;
      ;;
esac

And then I wrote a tray icon so it's easy to get to these.

files/2023/12/listings/switch-monitors-trayicon.sh (Source)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#!/usr/bin/env sh
# File: switch-monitors-trayicon.sh
# Location: /usr/local/bin
# Author: bgstack15
# SPDX-License-Identifier: GPL-3.0
# Startdate: 2023-12-05-3 16:29
# Title: Trayicon for switching monitor config
# Purpose: Provide easy drop-down for pcb-009 for monitor control
# History:
# Usage:
# Reference:
#    Heavily ripped keyboard-leds-trayicons
# Improve:
#    There is no loop, so manually touching the kill file does not stop the process like it should.
# Dependencies:
#    raw: mktrayicon, awk, switch-monitors.sh
#    devuan: mktrayicon, mawk | gawk, x11-xserver-utils

# CONFIG FILES
test -z "${SWITCH_MONITORS_CONF}" && SWITCH_MONITORS_CONF="${HOME}/.config/switch-monitors.conf"

# FUNCTIONS

get_conf() {
   # Ripped from framework.sh
   # call: get_conf "${conffile}"
   local _infile="$1"
   local _tmpfile1="$( mktemp )"
   sed -e 's/^\s*//;s/\s*$//;/^[#$]/d;s/\s*[^\]#.*$//;' "${_infile}" | grep -viE "^$" | while read _line ;
   do
      local _left="$( echo "${_line}" | cut -d'=' -f1 )"
      eval "_thisval=\"\${${_left}}\""
      test -z "${_thisval}" && echo "${_line}" >> "${_tmpfile1}"
   done
   test -f "${_tmpfile1}" && { . "${_tmpfile1}" 1>/dev/null 2>&1 ; }
   /bin/rm -rf "${_tmpfile1}" 1>/dev/null 2>&1
}

clean_switch_monitors_trayicon() {
   { test -e "${switch_monitors_icon}" && echo "q" > "${switch_monitors_icon}" ; } 1>/dev/null 2>&1 &
   sleep 1 && rm -f "${switch_monitors_icon}" "${SMT_KILLFILE}"
}

# LOAD CONFIGS
# order is important! The last one called gets precedence.
# instead of simply dot-sourcing the conf file, pass it to get_conf which only applies new values, so this process's environment is preserved
for thisconf in "${SMT_CONF}" "${SMT_USER_CONF}" "${SMT_GLOBAL_CONF}" ;
do
   test -r "${thisconf}" && get_conf "${thisconf}"
done

# DEFAULTS in case configs did not have these values
test -z "${SMT_ICON}" && SMT_ICON=display
test -z "${SMT_KILLFILE}" && SMT_KILLFILE="/tmp/kill-all-switch-monitors-trayicons"

# INITIALIZATION

switch_monitors_icon="/var/run/user/$( id -u )/${$}.switch_monitors.icon"

mkfifo "${switch_monitors_icon}"
mktrayicon "${switch_monitors_icon}" &
{
   echo "i ${SMT_ICON}"
   echo "t pcb-009 easy display settings"
   echo "m right,switch-monitors.sh right|both,switch-monitors.sh both|-----|quit,echo 'q' > ${switch_monitors_icon} ; touch "${SMT_KILLFILE}""
} > "${switch_monitors_icon}"

rm -f "${SMT_KILLFILE}"

trap 'trap "" 2 ; touch "${SMT_KILLFILE}" '  2 # CTRL-C
wait %1

# safety shutoff
clean_switch_monitors_trayicon

References

Weblinks

  1. NVIDIA - ArchWiki#Using_nvidia-settings

Comments