elkowar / eww

ElKowars wacky widgets
https://elkowar.github.io/eww
MIT License
8.78k stars 366 forks source link

defwindow width 100% dont work when using scale factor on wayland monitors #1110

Open patrikha opened 1 month ago

patrikha commented 1 month ago

Checklist before submitting an issue

Description of the bug

Using a scale factor on a monitor cases the width to be incorrect:

Additionally the width of 100% cant be used on my two other attached screens that is not using any scale factor (total of three monitors)

Reproducing the issue

Set scale factor to 1.5 and try to show a windows using 100% width

(defwindow bar0
  :monitor 0
  :exclusive false
  :geometry (geometry
    :x "15px"
    :y "0px"
    :width "100%"
    :height "25px"
    :anchor "top center")
  :stacking "fg"
  (bar_layout_primary :monitor workspace0))

Dimensions:

hyprctl monitors
Monitor DP-1 (ID 0):
    3840x2160@59.99700 at 1200x240
    description: Samsung Electric Company LS27A80 HNMT600086
    make: Samsung Electric Company
    model: LS27A80
    serial: HNMT600086
    active workspace: 8 (8)
    special workspace: 0 ()
    reserved: 0 25 0 0
    scale: 1.50
    transform: 0
    focused: no
    dpmsStatus: 1
    vrr: 0
    activelyTearing: false
    disabled: false
    currentFormat: XRGB8888
    availableModes: 3840x2160@60.00Hz 3840x2160@30.00Hz 3840x2160@29.97Hz 2560x1440@59.95Hz 1920x1080@60.00Hz 1920x1080@59.94Hz 1920x1080@50.00Hz 1680x1050@59.95Hz 1600x900@60.00Hz 1280x1024@75.03Hz 1280x1024@60.02Hz 1440x900@59.89Hz 1280x800@59.81Hz 1152x864@75.00Hz 1280x720@60.00Hz 1280x720@59.94Hz 1280x720@50.00Hz 1024x768@75.03Hz 1024x768@70.07Hz 1024x768@60.00Hz 800x600@75.00Hz 800x600@72.19Hz 800x600@60.32Hz 800x600@56.25Hz 720x576@50.00Hz 720x480@59.94Hz 640x480@75.00Hz 640x480@72.81Hz 640x480@59.94Hz

This will render the bar using 75% of the screen width, if I set the width to 2560px (3840 / 1,5) then it will fill the entire screen. Displaying the same bar on one of the side monitors will overfill the screen with with 25% so some parts of the bar will not be visible. The left and right side monitors use:

(defwindow bar1
  :monitor 1
  :exclusive false
  :geometry (geometry
    :x "15px"
    :y "0px"
    :width "1200px"
    :height "25px"
    :anchor "top left")
  :stacking "fg"
  :windowtype "dock"
  (bar_layout_secondary :monitor workspace1))

Dimenstions:

Monitor DP-2 (ID 1):
    1920x1200@59.95000 at 3760x0
    description: Lenovo Group Limited LEN T2454pA 0x01010101
    make: Lenovo Group Limited
    model: LEN T2454pA
    serial: 0x01010101
    active workspace: 10 (10)
    special workspace: 0 ()
    reserved: 0 25 0 0
    scale: 1.00
    transform: 1
    focused: no
    dpmsStatus: 1
    vrr: 0
    activelyTearing: false
    disabled: false
    currentFormat: XRGB8888
    availableModes: 1920x1200@59.95Hz 1920x1080@60.00Hz 1920x1080@59.94Hz 1920x1080@59.93Hz 1920x1080@50.00Hz 1600x1200@60.00Hz 1680x1050@59.95Hz 1280x1024@75.03Hz 1280x1024@60.02Hz 1440x900@59.89Hz 1280x800@59.81Hz 1280x720@60.00Hz 1280x720@59.94Hz 1280x720@50.00Hz 1024x768@75.03Hz 1024x768@70.07Hz 1024x768@60.00Hz 800x600@75.00Hz 800x600@72.19Hz 800x600@60.32Hz 720x576@50.00Hz 720x480@59.94Hz 640x480@75.00Hz 640x480@72.81Hz 640x480@59.94Hz 640x480@59.93Hz

Expected behaviour

Setting width using percentage should take into account scale factors.

The issue came with the latest release, it has been working perfectly before.

eww --version
eww 0.5.0 d87c2fdbfdc012e76d229e4e9ea3325bc0f23e89

Additional context

No response

moxuze commented 3 weeks ago

Same here.

I added monitor = ,highres,auto,1.6 in my hyprland.conf so the scale factor is 1.6.

Dimensions:

$ hyprctl monitors
Monitor DP-1 (ID 0):
    2560x1440@144.00600 at 0x0
    description: ASUSTek COMPUTER INC VG27AQL1A MBLMQS211154
    make: ASUSTek COMPUTER INC
    model: VG27AQL1A
    serial: MBLMQS211154
    active workspace: 5 (5)
    special workspace: 0 ()
    reserved: 0 34 0 0
    scale: 1.60
    transform: 0
    focused: yes
    dpmsStatus: 1
    vrr: 0
    activelyTearing: false
    disabled: false
    currentFormat: XRGB8888
    availableModes: 2560x1440@59.95Hz 2560x1440@144.01Hz 2560x1440@120.00Hz 2560x1440@99.95Hz 1920x1080@119.88Hz 1920x1080@100.00Hz 1920x1080@60.00Hz 1920x1080@59.94Hz 1920x1080@50.00Hz 1280x1024@75.03Hz 1280x1024@60.02Hz 1440x900@59.89Hz 1152x864@75.00Hz 1280x720@59.94Hz 1280x720@50.00Hz 1440x576@50.00Hz 1024x768@75.03Hz 1024x768@70.07Hz 1024x768@60.00Hz 1440x480@59.94Hz 800x600@75.00Hz 800x600@72.19Hz 800x600@60.32Hz 800x600@56.25Hz 720x576@50.00Hz 640x480@75.00Hz 640x480@72.81Hz 640x480@59.94Hz

I followed the document and set the width to 100%:

(defwindow example
           :monitor 0
           :geometry (geometry :x "0%"
                               :y "0%"
                               :width "100%" ; <- !!! NOTE HERE
                               :height "5%"
                               :anchor "top center")
           :stacking "fg"
           :reserve (struts :distance "40px" :side "top")
           :windowtype "dock"
           :wm-ignore false
  "example content")

As you can see, the width is not real 100%:

240612_02h39m54s

If I set the width to "1600px" or "125%", the window can fill my screen properly: (I set the width to "1599px" or "124%" in the following pictures and there are little gaps on the both sides)

240612_02h47m18s 240612_02h47m57s

alexdaguy commented 2 weeks ago

I can confirm this also on hyprland, with 1.5 monitor scaling a width of about 133% seems to correct this. eww appears to round the scale factor to the next integer when calculating the width, so integer scaling works fine. With moxuze's example, eww would round 1.6 up to 2, and 2/1.6=1.25 so that explains why 125% width works fine, and with my example 2/1.5=1.33...

ovalkonia commented 2 weeks ago

I dug around a bit in the code and here's what I found. Eww appears to be using the gdk crate to handle monitors and stuff like that. If you take a look at the docs, it is stated that this crate provides bindings and wrappers for GDK3. I have a 1920x1080 monitor and 1.5 monitor scaling set in the Hyprland configuration. This is what I get when I run this simple program: 1718815324 As you can see, this is completely wrong, it says that scaling is 2 when in fact, it is 1.5 and the geometry is all wrong as well. Eww uses the .geometry() method to get the size of the monitor and I assume that wrong scaling value results in this method returning wrong geometry properties.

Now the reason for the scaling factor being wrong is that GDK3 literally does not provide a way to obtain it as a floating-point number. It stores the scale_factor field as an integer, so if the scaling value is not an integer, expect something to be wrong.

Starting from GDK 4.14 there's an additional scale field in the Monitor struct and it is stored as an f64. The corresponding method .scale() is also provided. Take a look at this program, which does the same thing as the one on the previous screenshot, but uses the gdk4 crate instead: 1718819378 With the use of this new field and the corresponding method, it all works just fine now.

I'm no expert and don't know how to resolve this issue right now as moving to gtk4 probably would be too much (and a pain in the ass). Besides, I don't know what consequences it would bring, so it'd be best to let people who are educated on this topic to deal with it.

P. S. It appears that there's a branch gtk4 of Eww, which in theory should handle the scaling correctly. Although, it seems to be long unmaintained, the last commit was 3 years ago. I can't even get it to compile(

jjduhamel commented 2 weeks ago

+1 Seeing this since updating to the latest hyprland

antoniocorbi commented 1 week ago

Hi! I'm using NixOS with eww 0.6.0 + sway 1.9 + scale 1.25.

I've started to observe this problem after upgrading to wlroots-0.17, with wlroots-0.16 it worked ok.

For the moment I've had to increase the %-width used on my windows to make it work as before.