Closed NsCDE closed 3 years ago
Hi,
This is difficult to do. FvwmBacker
uses XSetWindowBackground()
to set the root window. This works fine in fvwm2
or when using DesktopConfiguration global
because the desks and pages are the same for all monitors.
But when per-monitor
is used, the root window is still common across both monitors, even though they could be on different desks and pages, so setting a different colour per monitor is tricky.
The only way to do this would be to render separate pixmaps and stitch them together via XCopyArea()
-- but that would mean drawing over the root window.
I'll give this some further thought.
I'm reading now about X functions you mentioned. From your wording that XCopyArea() means drwaing over root window, I can assume that this brings some concerns or maybe unknown obstacles.
One (pretty much dummy) approach would be to take pixmaps stored in FvwmBacker's Colorset or -solid, pick data about where are the left, right, top or bottom monitors, and compose joined pixmap when desks and pages are different on monitors. Of course, this is probably easier to say then do, I don't know if existing libraries used by FVWM (Xlib, Xpm, Png ...) contains something usable for this.
By googling around, I have downloaded source from program "feh". This program can set different background on different monitors with simple feh [ --bg-fill | --bg-max | --bg-center | --bg-tile ] pict1 pict2
. Only in --bg-tile mode it lacks multi monitor feature - which is for my CDE backdrops essential ARGH! :) Watching it's src/wallpaper.c feh_wm_set_bg. This program uses Imlib for many actions obviously, but that part of code looks like it is messing something with XCreateGC, XFillRectangle etc.
In other words, finding some examples from different X programs or WMs may bring some hint, idea or direction here. I will investigate this further when I catch the time during the day.
@NsCDE Do you think this is something that could be offloaded to a script/third party software (like feh). What if fvwm reports current desk/page information and some script uses this info to set the wallpapers appropriately based on which desk/page each monitor is on.
My thought was something like ta/more-monitor-vars could work, so now you can put $[monitor.<n1>.desk]
and $[monitor.<n2>.desk]
in a function and have FvwmEvent run that function on desk changes which could export the current desk to a script to set the wallpaper appropriately. There is also $[monitor.<n>.pagex]
and $[monitor.<n>.pagey]
if you want to get the current page.
Using the mentioned branch this seems to work for me, and my wallpapers now change per-monitor. First my basic shell script.
#!/bin/bash
MONITOR1=(Castle_Peak_at_Sunset.png Goat_Lake.png Mount_Regan.png Hyndman_Peak.png)
MONITOR2=(Sawtooths.png Dolomites.png Sawtooth_Sunset.png Barking_Fox_Lake.png)
feh --bg-fill $FVWM_USERDIR/wallpaper/${MONITOR1[$1]} $FVWM_USERDIR/wallpaper/${MONITOR2[$2]}
Next my fvwm configuration.
DestroyFunc MyBacker
AddToFunc MyBacker
+ I Exec exec $[FVWM_USERDIR]/scripts/backer.sh $[monitor.DP-4.desk] $[monitor.DP-3.desk]
DestroyModuleConfig FE-Backer: *
*FE-Backer: Cmd
*FE-Backer: new_desk MyBacker
Module FvwmEvent FE-Backer
As for your issue with --bg-tile
, maybe use imagemagick to tile the images for you into the screens resolution, then set the resulting image as the background (you could even use RandRFunc or FvwmEvent to rebuild these on resolution changes).
Hi @somiaj
While reading what you write for FvwmEvent and FvwmBacker, I'm fully aware that functionality of this modules is sometimes overlapping, and that FvwmEvent can (sometimes) serve as Backer. But I think that FvwmBacker, that is, dedicated module for setting root window background or running a command on change desk, page (RandR screen?) is something which should survive in Fvwm3. Specially with RetainPixmap, which is crucial if somebody is using X compositor together with FVWM.
That said, there is another problem with external scripts and programs: not all of them are aware of RandR screens. Feh has this support, but as a curse it lacks tiling support exactly in this operation mode, and for me, this is crucial feature. There is another one called "nitrogen" but it has it's own bugs, it is buggy and if it doesn't core dump, it sometimes forgets to set background. The feeling is noticable: this external program is not FvwmBacker - reliable configure-and-forget module.
Here is one possible hack for NsCDE on per-monitor setup of FVWM3. It is not really reliable in "production" sense: https://github.com/NsCDE/NsCDE/tree/master/NsCDE/share/doc/examples/fvwm3-per-monitor
Because in DesktopConfiguration "per-monitor" (probably "shared" too) mixing backgrounds which "belong" to one desk with other desk is very confusing and misleading. So I think FvwmBacker should really address this issue in FVWM3 internally. More precisely, addressing RandR monitor as desk and page are addressed where monitor is that part where pointer is current looks to me as most normal thing to expect to happen when navigating visual apstractions (desk, page, monitor) in FVWM3.
Sorry for longer post, I just wanted to share my thoughts and observations on this topic ...
@NsCDE seems my edit overlapped your post, anyways I have a working solution above using feh (though haven't experimented with tiling wallpapers).
It could be possible to extend FvwmBacker to run the commands with the new monitor variables, and just configure FvwmBacker to send functions with those commands. As for using it to set the backgrounds, this gets more complicated. I think the reason feh is able to do this is feh is already an image viewer that can scale/stretch/do basic image manipulation and what I believe it is doing is just combing two images into one and then setting that single image as the background (since if you use their feh --xinerama-index
option it sets the other monitor(s) to a gray background as opposed to leaving it alone, so in either case it is setting a single image as the background, just modifying it first.
I think in order to achieve what you want using fvwm, fvwm would have to introduce more image manipulation capabilities (consider fvwm-root
can't even scale .png images to fit), and the combine multiple images together into a single pixmap that can be set as the background so RetainPixmap works. I have personally switched to using feh over fvwm-root so I don't have to manually resize my images (and since I use it anyways as my image viewer).
So I think in order to achieve this through FvwmBacker it would require improving fvwm to have more image manipulation abilities, and at some point certain things might just be better suited for external tools.
Hey,
Indeed. This is tricky because although we could support this in fvwm
directly, it would require me to depend on something like imlib
which I am not really willing to do for a module which isn't going to see much use. Given there's already external tools which can do this -- we should use them, and take the time to fix them so they operate well with RandR-aware monitors better.
I did spend time looking at this -- and FvwmBacker
isn't going to go anywhere just yet -- and it'll work fine when in global mode, but less so now we support other modes.
That being said, you could also script something using imagemagick and do some maths to work out the size of an image per monitor, and stitch them together using mogrify
.
But for now, this is a WONTFIX for me, I'm afraid.
@NsCDE here is a solution that seems to work for me using tiled images with fvwm functions. I do use both imagemagick and feh (though this could proabbably all be done with imagemagick, but then you would have to manually combine the images together into a bigger image, and either do this each time a desk is changed or at the startup and generate all the images you'll use), so feh just makes things easier for me. I was experimenting with the three tiled images from the default-config.
# Background Image Functions
# TileImg <monitor> <src img> <desk>
DestroyFunc TileImg
AddToFunc TileImg
+ I Exec exec convert -size $[monitor.$[0].width]x$[monitor.$[0].height] tile:$[FVWM_USERDIR]/bg/$1.png $[FVWM_USERDIR]/bg/bg-$0-$2.png
# SetBack <monitor1> <monitor2>
DestroyFunc SetBack
AddToFunc SetBack
+ I Exec exec feh --bg-fill $[FVWM_USERDIR]/bg/bg-$0-$[monitor.$[0].desk].png $[FVWM_USERDIR]/bg/bg-$1-$[monitor.$[1].desk].png
# BuildBack <monitor>
DestroyFunc BuildBack
AddToFunc BuildBack
+ I TileImg $0 bg1 0
+ I TileImg $0 bg2 1
+ I TileImg $0 bg3 2
# FvwmEvent to trigger changes
DestroyModuleConfig FE-Backer: *
*FE-Backer: Cmd
*FE-Backer: new_desk "SetBack DP-4 DP-3"
#Start Up Functions (give it my two monitor names)
BuildBack DP-4
BuildBack DP-3
Module FvwmEvent FE-Backer
Hi @ThomasAdam and @somiaj
Until now, it was a lot easier and elegant to "swallow" backgrounds for 2-8 NsCDE desks in colorsets 31-38 and have it in FvwmBacker configuration statically and have it filled with contents of the xpm or png files. This is how things are presently working (I don't use fvwm-root).
As I understand, it is not easy to draw in the root window half of it, or only on one monitor without using extended graphical libraries and APIs. Out of curiotity, @ThomasAdam you have tried some drawing in the root window last year, but that was put aside. Is this hard to achieve with standard X features or unreliable? I must admit I don't know, but want to know more.
If things are really such difficult with X and FvwmBacker in the context of per-monitor and shared desktop configuration modes, then a solution with ImageMagick tools (which are already existing NsCDE dependency) seems to be less painful path then introducing feh. But thanks @somiaj for your example.
My current idea for (re)implementing things is: any desk change should trigger an action which will:
This means 16 xpms in cache in standard 4-desks setup, and 64 in maximal 8 desks setup.
This also means rewrite of Preview mode of Color Style Manager and Backdrop Style Manager. Lot of work for which I will keep existing model for FVWM2 and global mode of FVWM3 and "ifdef" FVWM3 model when DesktopConfiguration is not global. I just hope ImageMagick and FVWM colorset code will behave reasonable in case of two monitors with different resolutions and sizes. I will try @somiaj example from the above immediately ...
P. S. If you have any good idea on this, please enlighten me. Thanks.
Edit: it may work ... sort of. It seems that I cannot convert resize, tile and append in one step.
@NsCDE I just used feh as proof of concept and that it does all the math for you (though there isn't much math to do) and doesn't requiring creating an image for each and every desk combination. I have found a single line solution to create the image with imagemagick (though I do notice that even on my fast machine on nvme there is a noticeable, but short, time to do the image processing -- I think feh is faster).
I created a very complicated setup to test. I have three monitors, primary is 2560x1440+0+0
with two attached (one is rotated) 900x1600+2560+0
and 1366x768+1194+1440
. Using this info I can combine the three tiled back ground images from the default-config (if you run this command in a directory containing the three images you'll see it work in practice). Here is my one liner (split into multiple lines for readability)
convert \( -size 2560x1440 tile:bg1.png -repage +0+0 \) \
\( -size 900x1600 tile:bg2.png -repage +2560+0 \) \
\( -size 1366x768 tile:bg3.png -repage +1194+1440 \) \
-layers merge out.png
# Set the background
fvwm-root out.png
@NsCDE I also had another thought. Maybe use two different methods for global vs per-monitor. Might make things easier to maintain for compatibility. Use FvwmBacker for fvwm2 and fvwm3 in global since it works fine in this case, and then FvwmEvent and some more elegant custom scripts for per-monitor. This way you can just load the appropriate set of tools depending on mode / fvwm version.
FvwmBacker in per-monitor mode should operate only on screen where pointer is located, and not applying background on other screen(s), where desk and page are not in sync across screens like in global mode.
At least when using Colorset or "-solid" as internal commands, or even possibly fvwm-root. It cannot be responsible for other program's handling of virtual screen geometry and coordinates of course.