如何使用Go为X11/Wayland的多个屏幕添加背景图像?

huangapple go评论93阅读模式
英文:

How to add a background images to several screens for X11/Wayland using Go?

问题

我为Go编写了一个自定义的窗口管理器壁纸设置器。目前我使用的是github.com/xyproto/wallutils项目,该项目依赖于feh

对于一个屏幕,我可以使用其尺寸创建精确大小的图像,一切都正常工作,但如果连接到计算机的多个屏幕具有不同的尺寸,这种方法就不适用了。

对于精确的图像,我使用feh的'fill'选项,但这只对其中一个监视器起作用。

我想要做的是为每个屏幕创建正确尺寸的图像,并将它们作为背景图像发送到相应的X11或Wayland屏幕。我该如何在Go中实现这一点?

英文:

I make a custom wallpaper setter for window managers in Go. Currently I use github.com/xyproto/wallutils project, which in turn depends on feh.

For one screen I can use its dimensions to create the image of exact size, and all works well, but if there are several screens with different dimensions connected to a computer, this approach does not work.

For the exact image I use feh's 'fill' option, which would work correctly only for one of the monitors.

What I want to do is to create images of correct dimensions for each screen and send them as background images to corresponding screens either in X11 or Wayland. How can I achieve this in Go?

答案1

得分: 3

要求:

  • 将不同的壁纸发送到不同的监视器
  • 从Go中调用
  • 在底层使用feh

muro和wallutils

wallutils指定了一个WM接口,其中包括SetWallpaper方法。对于许多不同的窗口管理器,都有相应的接口实现。

而Go包muro则使用了wallutils。根据标志WithAnyWindowManager,它将使用wallutilsSetWallpaperCustom方法,该方法根据检测到的窗口管理器选择具体的SetWallpaper实现,或者直接调用feh变体的SetWallpaper方法。

wallutils和feh

具体的显示模式取决于调用方式,但在wallutils的feh.go中,SetWallpaper基本上会像这样调用feh

	feh --bg-fill <image file name>

两个注意事项:

  • 这里的feh将所有屏幕的壁纸设置为完全相同的图像
  • 因此,不直接支持使用不同的图像

此外,wallutils的自述文件明确说明:
>为每个监视器设置壁纸

>目前不支持为每个监视器设置壁纸。目前,壁纸是为所有监视器设置的。

请参阅https://github.com/xyproto/wallutils#setting-a-wallpaper-per-monitor

可能的解决方案

由于您可以确定监视器和分辨率,我们将专注于以正确的顺序将预定义的图像作为背景图像发送到适当的屏幕,使用feh

feh本身支持为每个监视器设置不同的壁纸。只需使用不同分辨率的不同图像调用feh。顺序是由调用xrandr --listmonitors确定的。

在确定顺序并将其视为给定的情况下,最简单的GO程序如下所示(还可以参考wallutil的实用函数run):

package main

import (
	"os/exec"
)

func main() {
	args := []string{"--bg-fill", "1.png", "2.png"}
	cmd := exec.Command("feh", args...)
	if _, err := cmd.CombinedOutput(); err != nil {
		panic(err)
	}
}

(在FluxBox窗口管理器中测试通过)

只要feh与适当的窗口管理器配合使用,并且在go目录中有两个准备好的图像,这就是最简单的情况。当然,也可以以编程方式确定屏幕并动态调整对feh的调用。

由于feh并不适用于每个环境,wallutils为一些窗口管理器环境(Cinnamon、Deepin、Gnome、Mate、Pekwm、Plasma、Sway、Weston、Xfce4)提供了其WM接口的具体实现。这当然非常酷。但是,如果您想为wallutils创建一个MR(Merge Request),您可能需要在所有变体中这样做,至少是支持的变体。

英文:

Requirements:

  • send different wallpapers to different monitors
  • call from Go
  • use feh underneath

muro and wallutils

wallutils specifies a WM interface that provides, among other things, the SetWallpaper method. There are corresponding implementations of this interface for a number of different window managers.

The Go package muro in turn uses wallutils. Based on the flag WithAnyWindowManager it will either use wallutils' SetWallpaperCustom method which selects a concrete SetWallpaper implementation based on the detected window manager or just directly call SetWallpaper of the feh variant.

wallutils and feh

The specific display mode depends on how it is called, but SetWallpaper in wallutils feh.go would basically call feh in your case as follows:

	feh --bg-fill &lt;image file name&gt;

Two notes:

  • here feh sets the wallpaper on all screens to the very same image
  • therefore it's not directly supported to have different images

Also, wallutils' readme explicitly states:
>Setting a wallpaper per monitor

>Setting a wallpaper per monitor is not supported, yet. Currently, a wallpaper is set for all monitors.

see https://github.com/xyproto/wallutils#setting-a-wallpaper-per-monitor

Possible solution

Since you can determine monitors and resolution, we focus on sending the predefined images in the correct order as background images under use of feh to the appropriate screens.

feh itself supports setting different wallpapers per monitor. You just call feh with the different images having different resolutions. The order is guaranteed to be the same as determined by a call to xrandr --listmonitors.

After determining the order and taking it as a given, the simplest possible GO program would look something like this (see also wallutil's utility function run):

package main

import (
	&quot;os/exec&quot;
)

func main() {
	args := []string{&quot;--bg-fill&quot;, &quot;1.png&quot;, &quot;2.png&quot;}
	cmd := exec.Command(&quot;feh&quot;, args...)
	if _, err := cmd.CombinedOutput(); err != nil {
		panic(err)
	}
}

(tested with FluxBox window manager)

Provided feh works with the appropriate window manager and there are the two prepared images in the go directory, this is the simplest case. Of course, one could also programmatically determine the screens and dynamically adjust the call of feh.

Since feh does not work in every environment, wallutils provides concrete implementations of its WM interface for a number of window manager environments (Cinnamon, Deepin, Gnome, Mate, Pekwm, Plasma, Sway, Weston, Xfce4). This is of course very cool. However, if you wanted to create an MR for wallutils, you would probably have to do so in all variants, at least those that support it.

答案2

得分: 0

你可以考虑使用vbsw/xlib库,它包含以下功能:

这些功能的灵感来自于C语言实现的"Obtaining List of all Xorg Displays"。

英文:

You might consider vbsw/xlib, which includes:

That is inspired from the C implementation "Obtaining List of all Xorg Displays".

huangapple
  • 本文由 发表于 2022年12月7日 19:24:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/74715845.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定