himdel / hsetroot

yet another wallpaper application
GNU General Public License v2.0
124 stars 21 forks source link

Different images for different screens #14

Open himdel opened 5 years ago

himdel commented 5 years ago

Allow providing a list of images to be used in sequence across outputs (iterated over in TL->TR->BL->BR direction)

gavsiu commented 3 years ago

So what's the point of -screens option? I was looking for this capability as well and tried that option with no success or noticeable change.

himdel commented 3 years ago

-screens is for Xinerama .. unless you're running a multihead X setup, this is not for you.

Modern linux GUIs use xrandr for multiple desktops, not xinerama screens.

I would love to add better support for xrandr screens though, so far it only knows they are there and tries to put the wallpaper on each, but if you have any ideas on how you'd want to use hsetroot with multiple screens please share :)

lwilletts commented 3 years ago

I know it's more of a pain but you could write an imagemagick script to take two (or more) images provided and stitch them together with how your screens are positioned using the data from xrandr

himdel commented 3 years ago

@lwilletts That sounds perfectly reasonable (hsetroot already does pretty much call imagemagick anyway).

What I'm missing is a good way of specifying this...

hsetroot --output=eDP-1 image1.jpg --output=HDMI-2 image2.jpg sounds cumbersome, you'd have to always know how your outputs are called.

hsetroot image1.jpg image2.jpg would mean hsetroot has to magically figure out which image belongs on which screen.

I'm looking for something in between, something useable.. maybe going clockwise in a spiral matching the output positions or something like that :)

gavsiu commented 3 years ago

hsetroot --output=eDP-1 image1.jpg --output=HDMI-2 image2.jpg is exactly what I would like.

I used to use hsetroot cause for some reason, xsetroot -solid doesn't work for me for solid color background. Then I wrote a script to choose a random wallpaper and set it with hsetroot when I didn't have a second monitor.

I finally installed feh yesterday for multi monitor support, but you can only tell it to set first monitor and second. I have a feeling my first and second monitor changes because polybar system tray doesn't always load on the same monitor and I haven't quite figured out how to fix that.

himdel commented 3 years ago

Aah, well, in that case, it shouldn't be that hard to add, I'll take a look over the weekend :).

I have a feeling my first and second monitor changes because polybar system tray doesn't always load on the same monitor and I haven't quite figured out how to fix that.

That may have to do with what X considers the primary screen, you may be able to change that using xrandr --output=... --primary. (Idk about polybar, but i3 only notices the primary screen changes when I restart it.)

himdel commented 3 years ago

So.. one complication, there doesn't seem to be a nice way for a C program to tell which outputs are there by name. libXinerama doesn't return output names, while libxrandr doesn't seem to return the position/offset values.

Which would be more acceptable, depending on a ruby program using the xrandr gem to list the outputs (along the lines of https://github.com/himdel/hsetroot/pull/34), or having the C code call bash to run the xrandr command (https://github.com/himdel/hsetroot/blob/758a7c35a64e8a8573047c8b561b9b99beca9537/outputs_xrandr.c)? Any other ideas? (The ruby version depends on ruby and the xrandr gem, the C version on the xrandr command having consistent output, grep and sed.)

gavsiu commented 3 years ago

The C version would mean less dependencies?

himdel commented 3 years ago

Yes, the C version means less dependencies, the potential downside is that it will only work as long as xrandr outputs lines exactly like DP-2-3 connected 1920x2160+0+0 (...).

gavsiu commented 3 years ago

What differs for the xrandr output? The display name might change depending on load order or something right? I'm not too familiar. I think I remember reading it can change on some systems, but I don't think I've encountered it on my laptop's + 1 external monitor.

Whichever is easier for you.

vincentbernat commented 3 years ago

Have a look at the source code of xrandr. It's simple enough for you to steal the code. You have two different paths: one for getting outputs (physical screens) and one for monitors (virtual screens). Usually, there is a 1:1 mapping. For wallpapers, I think you should stick to outputs.

See https://gitlab.freedesktop.org/xorg/app/xrandr/-/blob/master/xrandr.c#L1815 and https://gitlab.freedesktop.org/xorg/app/xrandr/-/blob/master/xrandr.c#L1352. The code is a bit hard to read because xrandr is using global state. Basically, you do:

  1. XRRGetScreenResourcesCurrent() to get screen resources
  2. For each screen resource, XRRGetOutputInfo() to get the outputs
  3. For each output, also get the CRTC Info (which ontains offset and dimension) with XRRGetCrtcInfo()
vincentbernat commented 3 years ago

Here is what I use with Python. This should translate to C as is.

    d = display.Display()
    screen = d.screen()
    window = screen.root.create_window(0, 0, 1, 1, 1, screen.root_depth)
    background = Image.new("RGB", (screen.width_in_pixels, screen.height_in_pixels))

    # Query randr extension
    outputs = []
    screen_resources = randr.get_screen_resources_current(window)
    for output in screen_resources.outputs:
        output_info = randr.get_output_info(window, output, screen_resources.timestamp)
        if output_info.crtc == 0:
            continue
        crtc_info = randr.get_crtc_info(window, output_info.crtc, output_info.timestamp)
        outputs.append(
            Rectangle(crtc_info.x, crtc_info.y, crtc_info.width, crtc_info.height)
        )
Swivelgames commented 1 year ago

Hate to be that guy, but is there still any interest in implementing this? It's a bit out of my comfort zone to contribute, but I was bashing my head against a wall with -screens until I came here and realized it wasn't currently possible.

himdel commented 1 year ago

Fair :) I'm still planning to add it (though apparently you DO have to remind me every couple of years ;)), but .. if you rely on me, it probbbly won't happen before xmas.

So, contributions welcome, but if not, we'll get there eventually? :)