glyph / Pomodouroboros

Pomodoro timer that acknowledges the inexorable, infinite passage of time
MIT License
214 stars 16 forks source link

[GTK] Progress bar may be misaligned with vertical Ubuntu dock #81

Closed SnoopJ closed 2 weeks ago

SnoopJ commented 2 weeks ago

NOTE: Pomodouroboros on Linux is very much WIP at time of filing, this is an advisory issue on the WIP rather than an application bug

EDIT: This behavior is associated with the Ubuntu Dock, see discussion below. The computed width is off by an amount that seems equal to the width of the dock, and the alignment is wrong only when the Dock is on the right side of the screen in my local test.


When running python3 -m pomodouroboros.linux.gtk_progress_bar on a multi-display system (2x 1920x1080 displays of different physical sizes), I observe that the progress bar is displayed correctly on my secondary display, and has a horizontal offset on the primary display.

Image

In my (limited) personal usage of this demo as a reminder of the passage of time, I made an ad-hoc adjustment to the width computation that resolves the issue on my system, and might be useful to someone else who is poking at this demo code for similar assistive reasons. It is an ungraceful hack and I assume you will need to tweak that adjustment to match your own system. I also have no idea how this behaves on systems with more displays or a different display layout.

diff --git a/src/pomodouroboros/linux/gtk_progress_bar.py b/src/pomodouroboros/linux/gtk_progress_bar.py
index 24754bc..184f8cc 100644
--- a/src/pomodouroboros/linux/gtk_progress_bar.py
+++ b/src/pomodouroboros/linux/gtk_progress_bar.py
@@ -106,12 +106,15 @@ def makeOneProgressBar(
     xlibwin = display.create_resource_object("window", xid)

     # Always on top
-    print(f"moving to {monitor_geom.x} {monitor_geom.y} {monitor_geom.width}")
+    width_adjustment = 54 if monitor_geom.x > 0 else 0
+    target_width = monitor_geom.width - width_adjustment
+    print(f"moving to {monitor_geom.x} {monitor_geom.y} {target_width}")
+
     ewmh.setMoveResizeWindow(
         xlibwin,
         x=monitor_geom.x,
         y=monitor_geom.y + (monitor_geom.height - 150),
-        w=monitor_geom.width,
+        w=target_width,
         h=150,
     )
     ewmh.setWmState(xlibwin, 1, "_NET_WM_STATE_ABOVE")

Image

glyph commented 2 weeks ago

Huh. Do the two displays have different scale factors? (is that a thing that can be configured separately)

SnoopJ commented 2 weeks ago

Not sure if it's possible to have separate scale factors (the UI suggests this, but they change in lockstep), but I seem to have 100% on both displays

glyph commented 2 weeks ago

whew, okay, that makes it easier. this looks … ubuntu-y? what exact version?

SnoopJ commented 2 weeks ago

Ah yes sorry, this is Ubuntu 22.04.5 running GNOME 42.9

sigmavirus24 commented 2 weeks ago

Wayland does allow for different scale factors that can be configured per display. Pretty sure X11 also supports that although the ergonomics of configuring it is way worse

sigmavirus24 commented 2 weeks ago

Also, in my experience gnome on fedora defaults to 2.0 as the scale factors and can be brought down to 1.0 or lower and I've seen this be the default for other window managers on fedora. Might be fedora specific but I don't think they typically customize things like that

glyph commented 2 weeks ago

I should note that this does not happen on my Debian 12.6 / GNOME 43.9 system:

Image

Based on the width of the offset and the fact that it's horizontal, my suspicion is that this is a result of Ubuntu's weird dock thing that isn't in standard GNOME. I wonder what the display geometry API tells you about your displays, and whether it matches your expectations.

SnoopJ commented 2 weeks ago

ARGH, I had forgotten about the dock, but you are absolutely right, that is what the behavior is tied to. Moving my dock to the bottom of the screen resolves the issue.

I recall poking at this whenever I wrote up the bodge, trying my best to figure out how to query the size of the dock (I believe it is not predictable) and eventually giving up and going with the bodge. I'll edit the title/description of this issue accordingly.

SnoopJ commented 2 weeks ago

Dunno why this was so hard to unearth last time I thought about this, but the relevant setting to query for the width of the dock seems to be the dash-max-icon-size value under org.gnome.shell.extensions.dash-to-dock, which can be queried by the following:

    from .platspec import Gio

    dock_settings = Gio.Settings.new("org.gnome.shell.extensions.dash-to-dock")
    dock_adjustment = 2*11 + dock_settings.get_value("dash-max-icon-size").unpack()  # I am uncertain how safe this unpack is

The 2*11 there is my best fudge at the margins, I'm sure it can be pinned down more precisely but it wasn't obvious in a quick dive of the dash-to-dock source. The stylesheet may be the most relevant place to look.

This seemed to work well for a variety of icon size values. There are probably edge cases I'm not thinking about, but it's an improved bodge at least!

glyph commented 2 weeks ago

OK. Matching your exact OS version and desktop and monitor count, I … still can't reproduce it.

Image

But I notice your dock is on the right, whereas mine is on the left.

glyph commented 2 weeks ago

Also worth noting that for me, the compositor in 22.04 incorrectly makes the progress bar window take focus when clicked, and so it's just… kinda broken. 24.04 fixes that bug.

glyph commented 2 weeks ago

OK. I can reproduce the issue even on 24.04, if I put the dock on the right side of the rightmost display. It looks roughly the same as it does for you. I think this may have to do with the fact that Ubuntu seems to be using some custom logic to move and resize windows to respect its dock geometry, as well as … maybe reporting different geometry for the dock itself? And then something to do with the fact that resizing happens from the top left?

glyph commented 2 weeks ago

Yeah I think what's happening is that it's … pushing the window left, which would normally resize it against the left edge, but since there is room for it to expand, this only happens if the dock happens to be on the right and there is another monitor on the left into which the dock manipulated window can expand. It strikes me that this should probably be filed against Ubuntu's dock thing, since there's no "good" API for this?

glyph commented 2 weeks ago

OK. It's a bug in Ubuntu's "Dash to Dock", where it randomly resizes the window to squash it out of the way of the dock, but, like… implicitly. I think that this is because the dock is a "strut", per https://github.com/micheleg/dash-to-dock/blob/816d585207c2964225b33ab944766b0b62e65de4/docking.js#L452

glyph commented 2 weeks ago

Closer… https://wayland.app/protocols/xdg-shell#xdg_positioner:enum:constraint_adjustment

glyph commented 2 weeks ago

Note that the first element of this constraint repositioning algorithm enum is slide_x

SnoopJ commented 2 weeks ago

I can confirm that 9883c46 resolves the issue after the timer fires (i.e. it starts out wrong, then resolves itself). The business about strut is beyond my knowledge of the WM magick at play here, but I think I understand the sketch of the bug re: the dock moving a window

glyph commented 2 weeks ago

There is a way to properly ask the display for the information about what area is allowed (the "workarea" in X11 terms, or the "bounds" in Wayland terms), but, as you might imagine, it only exists in the X11 backend and it is deprecated. https://docs.gtk.org/gdk4-x11/method.X11Monitor.get_workarea.html

glyph commented 2 weeks ago

OK, using get_workarea should fix it For Real. Really need to get a move on making this app both A) real and B) popular so that GNOME can never remove these APIs.

SnoopJ commented 2 weeks ago

Confirmed that this does fix the issue! Seems to work right out of the gate without needing the timer to fire, too.

Thank you for the shockingly fast and thorough fix! 💙