elkowar/eww

[BUG] Screen enumeration is inconsistent with my Wayland compositor

Closed this issue · 7 comments

Checklist before submitting an issue

  • I have searched through the existing closed and open issues for eww and made sure this is not a duplicate
  • I have specifically verified that this bug is not a common user error
  • I am providing as much relevant information as I am able to in this bug report (Minimal config to reproduce the issue for example, if applicable)

Description of the bug

I have created a simple widget.

(defwidget power-menu-buttons []
  (box :class "button-container"
       :orientation "vertical"
       :halign "left"
       :spacing 4
    (button :onclick "systemctl suspend" "Suspend")
    (button :onclick "systemctl poweroff" "Shut down")
    (button :onclick "systemctl reboot" "Reboot")
))

(defwindow power-menu [screen]
           :id "power-menu"
           :monitor screen
           :geometry (geometry :x "3px"
                               :y "3px"
                               :width "15%"
                               :height "10%"
                               :anchor "top left")
           :stacking "overlay"
           :exclusive false
           :focusable false
           :wm-ignore false
           (power-menu-buttons)
)

I want to be able to pass the screen that the widget is shown on as a parameter so that I may show it on any of my monitors.

I have 2 monitors, and I'm currently passing the ID of whichever one Hyprland reports as the active monitor to the widget's window. The full invocation looks like this.

eww active-windows | grep "power-menu"
if [ $? -eq 0 ]; then 
    eww close power-menu 
else
    scr=$(hyprctl activewindow | grep monitor | head -n 1 | awk '{print $2}')
    eww open power-menu --screen $scr
    notify-send $scr
fi

The widget is consistently shown on the other monitor.

In my case I could just use the process of elimination to get the correct monitor, but for 3 or more there's no way to do it reliably and (as far as I can tell) eww provides no way to query screen information.

Reproducing the issue

No response

Expected behaviour

I expect the widget to be shown on the screen that Hyprland reports as active.

Additional context

No response

i ran into a similar issue, and i'm really not sure whether this is hyprland's or eww's fault.
the issue i was facing was the fact that hyprland's monitor ids are inconsistent and sometimes even changed on my 2 monitor setup, this might be similar for you, so i'd recommend maybe logging for a bit which of your monitors gets assigned which id.
my fix for launching 2 bars, one on each monitor, consists of a very ugly hack in which i basically look for the order in which hyprland reports the monitors iirc.

a different approach you might want to look into could be getting the monitor's model from hyprctl monitors and then passing that via the --screen flag.

#1086 might be of interest to you as well.

I did find that you can pass the model when I was looking around online. It does seem like a decent fix, I just wish Hyprland had a more robust way of querying screen info. The output filtering stuff I'm doing to get the ID is already pretty gross.

hyprland's monitor ids are inconsistent and sometimes even changed on my 2 monitor setup

I've experienced the same thing when switching video drivers/configurations, and even sometimes just on rebooting (iirc). Another reason I can't hardcode the monitor ID...

Having looked at that issue I'm just convinced this is another fundamental Wayland shortcoming. It makes no sense that 2 clients working together in this regard have no consistent way of querying the physical device they should be displayed on.

As far as this issue goes, I think it should stay open until there is a "real" solution to this issue. Do you deprecate monitor IDs? Add a communication mechanism for every possible compositor? Wait until compositors have a way to query a monitor's ID under GDK? What a proper fix really entails, I have no idea.

Edit:
realSaltyFish proposed something of a solution on Aylur/ags#363 (I found this issue at the bottom of #1086):

GDK 3 does not provide a way to uniquely identify a monitor. GDK 4 provides a get_connector() function and a get_description() function that can be used to precisely map a GDK monitor to a Hyprland monitor. Is it possible to upgrade AGS to use GDK 4?

I don't know if this is currently possible for eww to implement but it would theoretically fix the issue.

@ovalkonia has found a nice and tidy way to get the active monitor in 1 query.

hyprctl -j monitors | jq -r 'first(.[] | select(.focused)) | .model'

My script now looks like this.

#!/usr/bin/env bash
# eww-toggle-window
# $1 = window name, $2 = monitor id (or none for current)

eww active-windows | grep "$1"
if [ $? -eq 0 ]; then 
    eww close "$1"
else
    eww open "$1" --screen="${2:-$(hyprctl -j monitors | gojq -r 'first(.[] | select(.focused)) | .model')}"
fi

if you now have a solution that works i'd suggest closing this issue, a pr trying to make display adapters work has been opened already

@ewancg Won't something like hyprctl -j monitors | jq -r 'first(.[] | select(.focused)) | .model' work?

@ovalkonia Yes it would! Thanks

510b824 made it to master, this might be of interest to you