Skip to content

owned_window_over: an owned dialog over part of the region counts - #1735

Merged
abrichr merged 2 commits into
mainfrom
claude/owned-window-intersects
Nov 3, 2026
Merged

abrichr merged 2 commits into
mainfrom
claude/owned-window-intersects

Conversation

@abrichr

@abrichr abrichr commented Nov 3, 2026

Copy link
Copy Markdown
Member

Follow-up to #1727, from agnostic-repair's live run on the UTM Windows lab. The app's "Session notice" dialog covers the right part of the identity band but not its center, so the center rule returned None and the repair never applied.

What changed

  • Intersects, not covers the center. The topmost window of the app's own process whose owner chain reaches the captured window, and which meets the region, is now reported. The "covers the region's center" rule is gone.
  • Unchanged: any other process's window, or an app window not owned by the captured one, that meets the region anywhere above the captured window means None.
  • Foreign windows measured by everything they may paint. That's the union of GetWindowRect and the DWM visible frame, because a self-drawn frame (Electron, Chromium) paints into the border DWM leaves out. The app's own windows keep the visible frame.

Safety for the repair doesn't depend on the center: the caller matches the uncovered part of the band word for word against the recorded identity, refuses parameterised bands, and re-runs the full identity check after the dialog is dismissed.

Adversarial review (independent; it also traced the caller on claude/repair-windows-qualify)

No blockers.

Finding Severity Outcome
(a) A foreign window partly over the band next to an owned dialog: None in either z-order; layered overlays and cross-process owner tricks are refused on process ID — Holds; tested
A foreign self-drawn frame paints into the border the DWM frame leaves out Should-fix Fixed here; tested
(b) A dialog on the right of the band can hide the part that tells two patients apart (a prefix read covering about 57% of the band is accepted) — Not a blocker: the full identity check after dismissal protects. It's the caller's prefix rule, in agnostic-repair.
The caller's dismiss click isn't tied to the reported window, and its label gate lets "OK" or "Yes" through on dialogs like "Discard unsaved changes?" Should-fix (caller) Passed to agnostic-repair
Any owned popup touching the band, such as a tooltip, now counts as the cause; the caller should require the covered rectangle to span the band from where the read is cut Should-fix (caller, plus an API change) Passed to agnostic-repair; returning the intersecting rectangle would change this contract, so it's left for them to ask for
A foreign window reparented with SetParent inside the captured window isn't enumerated Nit (predates this) Open

Testing

tests/test_win_agent_server.py and tests/test_windows_backend.py: 171 passed. New tests:

  • an owned dialog over part of the region is reported;
  • the topmost owned window is reported;
  • a foreign window beside an owned dialog gives None in either order;
  • a foreign self-drawn frame reaching the band gives None.

The real-VM probe from #1727 still applies: it showed an owned dialog reported and a foreign Notepad refused.

agnostic-repair's live run: the Session notice dialog covers the right
part of the identity band, not its center, so the center rule answered
None and the repair never applied. The topmost owned window that meets
the region is now reported. Unchanged: any other process's window, or an
app window not owned by the capture, meeting the region anywhere above
the captured window answers None; the caller matches the uncovered part
of the band and rechecks identity after the dialog is dismissed.
…may paint

Review should-fix: a self-drawn frame (Electron, Chromium) paints into the
~7 px border DWM leaves out of the visible frame, so a strip of a foreign
window at the band's edge went unseen. Foreign windows are now measured
by the union of GetWindowRect and the visible frame; the app's own keep
the visible frame.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant