英文:
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
,它将使用wallutils
的SetWallpaperCustom
方法,该方法根据检测到的窗口管理器选择具体的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 <image file name>
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 (
"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)
}
}
(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
库,它包含以下功能:
XOpenDisplay()
,返回一个Display对象(C.Display
)XScreenCount
,用于获取屏幕数量XScreenOfDisplay
,根据给定的屏幕编号获取对应的Screen对象XWidthOfScreen
,获取屏幕的宽度XHeightOfScreen
,获取屏幕的高度
这些功能的灵感来自于C语言实现的"Obtaining List of all Xorg Displays"。
英文:
You might consider vbsw/xlib
, which includes:
XOpenDisplay()
, which returns a Display (C.Display
)XScreenCount
, for the number of "screens"XScreenOfDisplay
which gets a Screen for a given "screen number"XWidthOfScreen
XHeightOfScreen
That is inspired from the C implementation "Obtaining List of all Xorg Displays".
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论