Closed bug report

desktop_list_monitors misses secondary monitors and reports inconsistent units (blocks pup multi-monitor placement)

John Lauer · 26d ago ·closed by John Lauer

What

desktop_list_monitors reports only ONE monitor on a machine that has two. Chrome running on the same box sees both.

Repro (ADOMGPU, AD 1.9.116, 2026-07-15)

  • adom-desktop --target ADOMGPU desktop_list_monitors {} returns a single entry: Primary 1920x1080 at 0,0.
  • Ground truth from Chrome on the same box: screen.isExtended === true, and moving a window right of x=1440 lands it on a second display reporting availLeft=1440, width=1844, height=1152 (probe method: place a window at x=1500 and read its screen object).
  • So the real layout is: monitor 1 = 1440x900 logical at 0,0 (note: ALSO disagrees with the 1920x1080 AD reports for the primary), monitor 2 = 1844x1152 logical at 1440,0.

Two sub-bugs

  1. The second monitor is missing from the list entirely (enumeration likely stops at the primary, or queries a stale/session-scoped display set on this RDP-attached VM).
  2. The primary's reported size (1920x1080) matches neither the logical size Chrome sees (1440x900) nor an obvious physical size — units/DPI handling looks inconsistent. Related: desktop_set_window_bounds documents physical px; whichever unit list_monitors uses, the two verbs should agree so a caller can feed one into the other.

Why pup cares

pup 1.8.69 added multi-monitor window placement (open pup windows on a chosen monitor). It currently has to discover the monitor map empirically (move a probe window, read screen.availLeft/width back) because list_monitors is wrong. With a correct desktop_list_monitors (all monitors, logical+physical bounds, primary flag, per-monitor scale), pup deletes the probe.

Ask

  • Enumerate ALL monitors (EnumDisplayMonitors), not just the primary.
  • Per monitor: logical bounds, physical bounds, work area, scale factor, primary flag, index/name.
  • Make the units explicit in the response and consistent with desktop_set_window_bounds.

3 Replies

John Lauer · 26d ago

Fixed in AD 1.9.119 (live now on the wiki; the download box + auto-update carry it).

Root cause (both sub-bugs, one wrong route)

desktop_list_monitors was being routed to pup's own DPI-unaware JS handler, not to AD's Win32 enumeration. AD already had a correct EnumDisplayMonitors implementation in display.rs, but nothing was calling it for this verb, so you got whatever the JS path returned (primary only, and in a unit that did not match desktop_set_window_bounds).

Two changes:

  1. Routing: the CLI desktop_list_monitors now calls AD-core's list_monitors verb (a machine fact AD owns), not the bridge. AD enumerates every monitor via EnumDisplayMonitors.
  2. DPI: the enumeration is wrapped in SetThreadDpiAwarenessContext(PER_MONITOR_AWARE_V2) for the duration of the call (surgically, per-thread, so it does not change AD's process-wide GUI DPI mode). On an RDP-attached VM the process is otherwise handed virtualized/clamped bounds, which is the most likely reason the second display was invisible and the primary size was off.

New response shape (per monitor)

  • bounds and workArea: physical pixels (these are what desktop_set_window_bounds consumes, so the two verbs now agree).
  • logicalBounds and logicalWorkArea: DIPs (logical, what Chrome's screen object reports).
  • scale: the per-monitor scale factor (e.g. 1.5).
  • primary: bool.
  • plus index/name, and a top-level units object that spells out which field is physical vs logical so a caller never has to guess.

Feed bounds straight into desktop_set_window_bounds; use logicalBounds when you are matching against a screen.availLeft/width reading.

Honest caveat on the multi-monitor repro

I validated the all-monitors enumeration + the PMv2 hardening on the laptop, but with a single external monitor (it reported 2560x1600 at scale 1.5 with correct physical/logical split). I could not re-run your exact two-monitor ADOMGPU repro, because ADOMGPU is down right now. So: the "enumerate all monitors" + RDP-DPI fix is code-correct and PMv2-hardened, but the specific "second monitor was missing on the RDP VM" case has not been re-verified end to end on the failing box.

When ADOMGPU is back, please confirm desktop_list_monitors returns both displays with sane physical/logical bounds, and drop your probe. If the second monitor is STILL missing even with PMv2, that points at a session-scoped display set on that RDP session (the enumeration runs in AD's session, which may differ from the interactive RDP session's display set) and I will chase that specific angle next. Ping me either way.

John Lauer · 26d ago

Update: verified on ADOMGPU itself (now on 1.9.119). desktop_list_monitors returns count: 2, and it matches your ground truth to the pixel:

  • DISPLAY1 (primary): physical bounds 1440x900 at 0,0, logicalBounds 1440x900, scale 1.0, dpi 96.
  • DISPLAY2: physical bounds 2304x1440 at x=1440, logicalBounds 1843x1152 at x=1440, scale 1.25, dpi 120.

Your probe read the second display as availLeft=1440, width=1844, height=1152 — the logical bounds now report 1843x1152 at x=1440 (the 1844 vs 1843 is a single-pixel DIP rounding difference). So the earlier "second monitor was missing on the RDP VM" case is resolved: both displays enumerate, the per-thread PMv2 context gave correct physical bounds on the RDP session, and the physical/logical split lines up with what Chrome sees. The honest caveat from my last comment is now retired: it is verified end to end on the box that failed. Drop the probe whenever you like.

John Lauer · 19d ago

Closing: fixed in 1.9.119 and verified on ADOMGPU itself, per the replies above. This one was just never closed.

Recap for anyone finding this later. Both sub-bugs were one wrong route: desktop_list_monitors was being answered by pup's DPI-unaware JS handler instead of AD's Win32 EnumDisplayMonitors, which already existed in display.rs and nothing was calling. Fixed by routing the verb to AD core (a machine fact AD owns) and wrapping the enumeration in a per-thread SetThreadDpiAwarenessContext(PER_MONITOR_AWARE_V2), surgically, so AD's process-wide GUI DPI mode is untouched.

Verified again today on a single-display laptop: the verb reports physical bounds 2560x1600 at 0,0, logicalBounds 1707x1067, scale 1.5, dpi 144. So the physical/logical split and the DPI reporting you asked for are present, and bounds is in the same physical space desktop_set_window_bounds takes, which was your other ask.

Log in to reply.