hhannine / superpaper

A cross-platform multi monitor wallpaper manager.
MIT License
1.12k stars 46 forks source link

only setting wallpaper on one display in kde plasma #6

Closed vyrus714 closed 4 years ago

vyrus714 commented 5 years ago

When using the cli or gui version it only changes the background on my main/primary display. It's also using the wrong image - the left one rather than the center one (3 displays horizontal).

I poked at the script at around line 1288 in kdeplasma_actions(), and printed out fname and idx, but they seem to be printing good values, so I think something in the plasmashell script isn't working quite right. The print statement inside it already doesn't show up though, so I'm not sure how to debug that.

hhannine commented 5 years ago

With what settings are you trying to set the wallpaper? Or with what command from cli?

Are there some temp images in the temp folder that have crop in their name? Are they something like you would expect?

hhannine commented 5 years ago

Have you tried running the script with the debug option to see if there's a hint of what's going wrong?

vyrus714 commented 5 years ago

Current command/settings:

DESKTOP_SESSION=/usr/share/xsessions/plasma python superpaper.pyw --debug --setimages /home/vyrus/.local/share/wallpapers/sptest/Wallpapers_Ultra_HD_8K_Janeiro_2017257680x4320.jpg --inches 24 27 18 --offsets 0 0 0 -400 0 55

And this is what I'm getting using it:

[vyrus@TNM-ARCH superpaper-portable-script]$ DESKTOP_SESSION=/usr/share/xsessions/plasma python superpaper.pyw --debug --setimages /home/vyrus/.local/share/wallpapers/sptest/Wallpapers_Ultra_HD_8K_Janeiro_2017257680x4320.jpg --inches 24 27 18 --offsets 0 0 0 -400 0 55 ['/home/vyrus/.local/share/wallpapers/sptest/Wallpapers_Ultra_HD_8K_Janeiro_2017257680x4320.jpg'] None [24.0, 27.0, 18.0] None ['0', '0', '0', '-400', '0', '55'] None True getDisplayData output: nDisplays = 3, [(2560, 1440), (1080, 1920), (1600, 1200)], [(1080, 0), (0, 0), (3640, 444)] SORTED getDisplayData output: nDisplays = 3, [(1080, 1920), (2560, 1440), (1600, 1200)], [(0, 0), (1080, 0), (3640, 444)] Computed PPIs: [91.7877987534291, 108.78553926332337, 111.11111111111111] relative pixel densities: [0.8260901887808618, 0.9790698533699103, 1.0] /home/vyrus/.local/share/wallpapers/sptest/Wallpapers_Ultra_HD_8K_Janeiro_2017257680x4320.jpg centers: [(654, 1162), (2615, 762), (4722, 1217)] crop_tuples: [(0, 0, 1307, 2324), (1307, 26, 3922, 1497), (3922, 617, 5522, 1817)] Canvas size: [5240, 1920] file:///home/vyrus/Desktop/superpaper-portable-script/temp/cli-a.png DESKTOP_SESSION is: '/usr/share/xsessions/plasma' cli-a -b cli-b-crop-2.png cli-b-crop-1.png cli-b-crop-0.png [vyrus@TNM-ARCH superpaper-portable-script]$

Without the --debug flag, all I see are the last few lines starting at cli-a. Nothing really indicating any kind of failure. Images show up just fine in the temp folder, and I can just set those manually (what I've done so far).

hhannine commented 5 years ago

Thanks. It's a bit hard to test in my KDE virtual machine since the multiple display support is really rough but at least with 2 displays it looks like it would be working. But I can't test it thoroughly since some display arrangements break it completely.

[(1080, 1920), (2560, 1440), (1600, 1200)]

Is this the actual order of your displays?

Let's look at your command step by step. Does it work if you run it with the --setimages command only? If the result is unexpected, what does it do?

If it works, what does the result look like if you add the --inches command?

EDIT: Also, are you running the latest version of the script from master?

vyrus714 commented 5 years ago

Yea, the display order is correct. Hopefully not any problem with my rotated display on the left. Running with just --setimages and no inches or offsets had the same behavior: only changed background on main screen, and used the component image for the left (vertical) monitor.

DESKTOP_SESSION=/usr/share/xsessions/plasma python superpaper.pyw --setimages /home/vyrus/.local/share/wallpapers/sptest/Wallpapers_Ultra_HD_8K_Janeiro_2017257680x4320.jpg

Have been running on the previous release version, but I grabbed a copy of the latest master & it behaves the same.

hhannine commented 5 years ago

No it shouldn't care about the monitor orientation at all. I was able to test on the virtual machine some more and there it sets both a single image across both monitors or two separate images as well. This is quite unfortunate as I have no clue what is the matter. I'll need to look into if I can extract some more useful debugging info from the process.

Would you mind verifying from the temp folder that the cli-*.png image has all 3 sections present?

hhannine commented 5 years ago

Given that the left most image piece goes onto the primary center display, it sounds like there's a disagreement of the monitor ordering between my bookkeeping and the way KDE arranges them. But even if this is the case, I can't see why only one image gets set and not all 3 in a wrong order..

hhannine commented 5 years ago

What version of KDE Plasma are you using?

hhannine commented 5 years ago

Are your widgets locked in KDE?

vyrus714 commented 5 years ago

temp folder contents:

[vyrus@TNM-ARCH temp]$ ls -ln total 8356 -rw-r--r-- 1 1000 1001 775066 May 26 21:49 cli-a-crop-0.png -rw-r--r-- 1 1000 1001 2125320 May 26 21:49 cli-a-crop-1.png -rw-r--r-- 1 1000 1001 941254 May 26 21:49 cli-a-crop-2.png -rw-r--r-- 1 1000 1001 4709374 May 26 21:49 cli-a.png -rw-r--r-- 1 1000 1001 0 May 26 08:42 running_profile [vyrus@TNM-ARCH temp]$

Seems like everything is there.

Plasma version 5.15.5 Yea, widgets locked, but it didn't change anything when i unlocked them. It does seem strange. When I printed out the index/file names they were right, so it should be running the command 3 times. It's like it only finds the primary/middle monitor in the kde desktops array, so it thinks that one is index 0, but doesn't find any monitors for index 1 or 2.

hhannine commented 5 years ago

I've read online that at least up until recent past of KDE Plasma, the scripting dbus interface that Superpaper uses needs to have the widgets unlocked to work. I don't know if this could've changed in recent versions given that you are running a cutting edge version on Arch.

Did you try restarting Superpaper after unlocking the widgets or maybe even logging out&in (or even rebooting)? I've no idea how finicky the scripting interface is. But it's really strange that it works partially even with the widgets locked.

vyrus714 commented 5 years ago

I'm not sure that's it, although I'll give it a shot. I did some digging trying to find out more about the interface, but it's really hard to find any documentation (or I'm not looking in the right places). I did come across this reddit thread where someone uses a similar method for setting the desktop backgrounds, however they're just looping over all of the desktops. By executing a loop like that I was seeing all of my desktops change their backgrounds (although to nothing, since I wasn't passing an image).

I dug a little further and found the desktop shell scripting console. It looks like my problem is the desktops array coming up with 5 screens somehow. Screenshot_20190527_012446 You can see that it's listing images for displays 0, 3, and 4, so when the images are set in superpaper, it only grabs the main display as index 0, then the 2 non-existing displays. I'm going to go try a restart and see if it still comes up with the extra displays, but it looks like the desktops() array isn't guaranteed to be ordered properly either, so you might need to find a way to get the correct screen order.

vyrus714 commented 5 years ago

Okay, I unlocked the widgets and restarted. Still shows 5 displays, and in the same order as before, so as expected there was no change when running superpaper.

I did finally find the plasmashell desktop scripting api. After some reading I might know what is going on. Since I've moved around a fair bit recently with this computer, I've had a few different monitors & configurations. Often enough when I move things around I lose my current desktop (panel, wallpaper, widgets, etc) and end up re-creating it fresh. So what I think happened is that I ended up with some spare desktops floating around not attached to any screens.

As for trying to figure out the current desktop arrangement, I did come across the function desktopForScreen, and was playing with the idea of passing the index of the wallpaper image from superpaper to that insead of the desktops array. Sadly whenever I passed any number besides 0 to the function it crashed plasmashell, so I don't know if it's usable (or if I was just using it wrong).

hhannine commented 5 years ago

Thanks a lot for the thorough research!

Yeah it might be that I need to figure out the screen geometry from the system. I've been planning some features that would need unique data from the monitors to be implementable. Would you mind trying what kind out output you get from the Screen Geometry methods outlined in the API you linked to? Did you happen to run any other functions that might return useful unique identifiers for the displays?

vyrus714 commented 5 years ago

Ok, did a bunch more poking at various functions and I think I've managed to find all the necessary bits to make things work. The desktops that aren't assigned to a screen can be filtered out easily since they have their screen property set to -1.

Here's what the output from the screen geometry object gives for my screen setup (with the invalid desktops filtered out):

Desktop 0:
   left:    1080
   top:     0
   bottom:  1440
   right:   3640
   height:  1440
   width:   2560
   x:       1080
   y:       0

Desktop 3:
   left:    0
   top:     0
   bottom:  1920
   right:   1080
   height:  1920
   width:   1080
   x:       0
   y:       0

Desktop 4:
   left:    3640
   top:     444
   bottom:  1644
   right:   5240
   height:  1200
   width:   1600
   x:       3640
   y:       444

Using this, you can pretty much figure out everything you need to know about the screen locations within the script.

Not perfect, but I wrote up a drop-in replacement for the script that works given a strictly horizontal screen arrangement:

script = """
    // make an array of all desktops with a valid screen
    var desktopArray = [];
    for(var desktopIndex in desktops()) {{
        var desktop = desktops()[desktopIndex];
        if(desktop.screen != -1) {{
            desktopArray.push(desktop);
        }}
    }}

    // sort the array based on the (horizontal) desktop position
    var i = 1;
    while(i < desktopArray.length) {{
        var j = i;
        while(j > 0 && screenGeometry(desktopArray[j-1].screen).left > screenGeometry(desktopArray[j].screen).left) {{
            var temp = desktopArray[j];
            desktopArray[j] = desktopArray[j-1];
            desktopArray[j-1] = temp;
            j = j-1;
        }}
        i = i+1;
    }}

    // set the desired wallpaper
    var desktop = desktopArray[{index}];
    desktop.wallpaperPlugin = "org.kde.image";
    desktop.currentConfigGroup = Array("Wallpaper", "org.kde.image", "General");
    desktop.writeConfig("Image", "file://{filename}");
"""

Can adapt something like this for use with more flexible configurations, just need to replace the sorting portion with something that can handle a 2D grid instead of just a horizontal row.

You also might be able to cut down the script calls to one by appending the index and filenames into a single string that initializes as an array in the plasmashell end of things. Haven't poked around with any of that though.

hhannine commented 5 years ago

Thank you so much for such thorough troubleshooting and even the script!

Did you happen to find out whether the primary display is always the 'Desktop 0'?

I've been trying to figure out a sorting algorithm for a 2D array of displays without really finding a solution that could handle an arbitrary arrangement of displays of any shape and size. One issue is how to figure out the sort correctly if a row has a display that is notably taller than the other displays in the same row. Think of a ~TV to the right of two vertically stacked rows, where depending on whether the top of the TV goes above the top most row or not seems to affect the row that it could be included in.

vyrus714 commented 5 years ago

I can't say for sure whether the primary display is always display 0, but across a few reboots here it has always been so for me. I'm not sure if that really helps sort the displays, but I haven't looked at how the image manipulation is being done.

For an arbitrary arrangement of displays my first thought would be to sort the desktops by a corner, say the top-left corner. Do a primary pass over the displays to count each unique x & y value at that corner, then sort them first by y value, then by x value, so they're arranged relatively like rows of text, from left to right.

I'm not exactly sure how you need the displays sorted, however this is one approach that would work if you just need a reliable ordering every time. For instance in your example if the TV goes over the top of the other 2 displays, it would be sorted first (row above), otherwise it would be sorted after them (row below).

If you're outputting your generated images indexed like this, then you could simply pass the file path for the output images to the plasmashell scrip and use the same sorting method there to match all the desktops to their respective images. Not sure if this works for other desktop platforms though, since I'm not as familiar with how they set their desktops.

hhannine commented 4 years ago

Finally sorted this out with 219f00aec.

I implemented your changes and also figured out the passing of the filenames into the script so it may only be called once. Thanks for that idea as well!