我怎样才能让 feh 根据每个显示器的大小设置壁纸?

我怎样才能让 feh 根据每个显示器的大小设置壁纸?

我有一个充满png文件的目录

$ tree ~/wallpaper/
~/wallpaper/
├── foo--1366x768.png
├── foo--1920x1080.png
├── foo--2048x1080.png
├── foo--3440x1440.png
└── foo--3840x2160.png

0 directories, 5 files

我经常更换显示器,有时会连接多个显示器。我想要一个脚本来检测连接到我的计算机的显示器的尺寸,并~/wallpaper根据显示器的尺寸设置壁纸。

因此,如果显示器具有分辨率1366x7683440x1440已连接,我希望脚本分别将壁纸设置为~/wallpaper/foo--1366x768.png~/wallpaper/foo--3440x1440.png。在这个特定的例子中,我知道发出命令

feh --bg-fill ~/wallpaper/foo--1366x768.png ~/wallpaper/foo--3440x1440.png

将正确设置壁纸。

为了解决一般问题,我知道我可以发出

xrandr | grep ' connected' | awk '{print $3}' | cut -f1 -d"+"

获取所连接显示器的尺寸。在我们的运行示例中,这里的输出是:

1366x768
3440x1440

我现在想以某种方式将其导入命令中,以便使用 来设置壁纸feh。我该怎么做?

答案1

您可以使用--no-xinerama,在这种情况下,您指定的任何图像都将出现在整个所有屏幕上。那么唯一的问题是,如何根据显示器的设置方式将所有图像组合在一起以制作一个桌面背景......

我唯一想到的是使用 ImageMagick,尽管这会非常奇怪且令人费解。所以,我决定无论如何都要做到……整个事情是这样的:

#!/bin/sh

AWK_XRANDR_PARSE='/ connected/ {
    split($3,sizePos,"+")
    split(sizePos[1],size,"x")
    print size[1] "," size[2] "," sizePos[2] "," sizePos[3]
}'

# Fetches a wallpaper for the monitor of size $1x$2. $1 is the required width,
# and $2 is the required height.
wallpaper_file() {
    # Use a case or string substitution to pick out any image files you fancy on
    # your system... They must be printf'd.
    printf "$HOME/.desktop"
}

# Writes any line whose $2nth column is equal to that of the first line.
# Columns are split by $1.
matching() {
    SENTINEL="$([ "$#" -gt 2 ] && printf '%s' "$3" || printf 'sentinel')"
    awk -F"$1" -v first="$SENTINEL" \
        "{if (first == \"$SENTINEL\") first = \$$2; if (\$$2 == first) print}"
}

# Writes the value within the variable named "$1".
cat() {
    printf '%s' "${!1}"
}

# Writes the $2nth column. Columns are split by $1.
nth() {
    awk -F"$1" "{print \$$2}"
}

# This one variable assignment takes xrandr's output, parses it via awk, runs
# the wallpaper_file, takes it's output, and combines all that information into
# a list of tuples. Each item in the list represents a monitor, and the tuple
# is roughly equivalent to 'W,H,X,Y,F', where W is width, H is height, X is the
# X position, Y is the Y position, and F is the file of the image.
DISPLAYS="$(while read X Y REST; do
    printf '%s,%s,%s,%s\n' "$X" "$Y" "$REST" "$(wallpaper_file "$X" "$Y")"
done < <(xrandr | awk "$AWK_XRANDR_PARSE" | \
    awk -F',' '{print $1 " " $2 " " $3 "," $4}'))"

# This simply finds the monitor that is the farthest out in the X direction,
# and is the widest. It then combines the X position and the width of the
# monitor to find the absolute width of your desktop.
PLACEMENT_WIDTH="$(cat DISPLAYS | sort -rnt, -k3 | matching , 3)"
SIZE_WIDTH="$(cat PLACEMENT_WIDTH | sort -rnt, -k1 | head -n1)"
WIDTH="$(("$(cat SIZE_WIDTH | nth , 1)" + "$(cat SIZE_WIDTH | nth , 3)"))"

# Same goes on as above, but with the height and Y direction.
PLACEMENT_HEIGHT="$(cat DISPLAYS | sort -rnt, -k4 | matching , 4)"
SIZE_HEIGHT="$(cat PLACEMENT_HEIGHT | sort -rnt, -k2 | head -n1)"
HEIGHT="$(("$(cat SIZE_HEIGHT | nth , 2)" + "$(cat SIZE_HEIGHT | nth , 4)"))"

# Take all that information, and make a wallpaper file from it via imagemagick.
magick -size $WIDTH'x'$HEIGHT canvas:black \
    $(cat DISPLAYS | awk -F',' '{print $5 " -geometry " $1 "x" $2 "+" $3 "+" $4 " -composite"}') \
    /tmp/wallpaper.png

# Then set it as the background.
feh --bg-fill --no-xinerama /tmp/wallpaper.png

我将整个脚本作为要点发布这里, 如果你更喜欢。

我知道我可能不应该这么做,但天哪我还是这么做了。

答案2

如果您总是连接 2 个显示器,那么使用 Bash 就很容易做到:

#!/usr/bin/env bash

screen_size=$(xrandr | grep ' connected' | awk '{print $3}' | cut -f1 -d"+")

IFS=$'\n'
readarray -t <<<"$screen_size"
feh --bg-fill ~/wallpaper/foo--"${MAPFILE[0]}".png ~/wallpaper/foo--"${MAPFILE[1]}".png

但是,如果连接的监视器数量可能会有所不同,这在实践中很可能是这种情况,您可以构建一个feh命令,然后eval像这样运行它:

#!/usr/bin/env bash

screen_size=$(xrandr | grep ' connected' | awk '{print $3}' | cut -f1 -d"+")

IFS=$'\n'
readarray -t <<<"$screen_size"
feh_command="feh --bg-fill"

for i in "${MAPFILE[@]}"
do
    echo size: "$i"
    feh_command="$feh_command ~/wallpaper/foo--$i.png"
done

eval "$feh_command"

相关内容