LearnNewsExamplesServices
Frontmatter
id16090
titleConverted vessel loses its dragged embodiment over the target popup
stateClosed
labels
bugaicore
assigneesneo-gpt-emmy
createdAtJul 28, 2026, 4:31 PM
updatedAtJul 28, 2026, 7:08 PM
githubUrlhttps://github.com/neomjs/neo/issues/16090
authorneo-gpt-emmy
commentsCount0
parentIssue15239
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJul 28, 2026, 7:08 PM

Converted vessel loses its dragged embodiment over the target popup

neo-gpt-emmy
neo-gpt-emmy commented on Jul 28, 2026, 4:31 PM

Context

Follow-up extracted from the #15252 Take 17 visual review. The popup-over-popup beat completes semantically, but its visual grammar is incomplete: when the dragged vessel converts over the target popup, the real popup parks/disappears and the target's docking zones illuminate, yet no in-app proxy embodies what is still being dragged.

This is not a new design request. #15395 explicitly contracted popup → semi-transparent drag proxy conversion, #15396 contracted park-not-close lifecycle, and #15906 composed the Workstation journey. The missing embodiment is therefore a contract-completion bug.

The Problem

The user sees the dragged popup vanish exactly when the drop zones become visible. The pointer and target preview continue, so the operation works, but the thing being dragged has no visual body. The result is weaker than both the Qt reference behavior (whole-window translucency during drag) and Neo's own infinite-canvas drag grammar.

Qt's native-window alpha is a reference, not an assumed browser capability. A Verify-Before-Assert sweep on macOS Chrome 150.0.7871.187 found:

  • the standard window.open() feature surface exposes popup selection and geometry, not top-level window alpha;
  • current chrome.windows exposes type, bounds, state, focus, and attention, not opacity;
  • current Chrome DevTools Protocol Browser exposes bounds/state, not opacity;
  • Chromium's historical Chrome-App alphaEnabled path is not a normal browser-popup API and the current source limits transparency to Aura (USE_AURA), falling back to opaque elsewhere: app_window_api.cc.

This does not claim that no private native hack can ever alter a Chrome window. It proves that the supported web/extension/CDP surfaces available to this app provide no macOS popup-alpha contract. Correctness must therefore come from Neo's in-app proxy. A future supported native-alpha capability may be an optional optimization, never the only embodiment.

The Architectural Reality

Current dev at ae6b87c907260e917e64357d801e814b3d9202f8 carries the intended ownership split but stops one layer early:

  • src/dashboard/DockVesselConversion.mjs says convert-in is suspendWindowDrag territory: “the popup yields, the proxy embodies over the target”.
  • apps/workstation/view/Workspace.mjs#parkTearOutVessel() correctly keeps the exact OS vessel alive behind the target.
  • src/dashboard/CrossWindowDragTarget.mjs#onRemoteDragMove() only calls previewFor(payload) and stores currentPreview; it owns no target-side drag proxy.
  • DockCrossWindowParticipation forwards the same preview-only surface.
  • Workspace#readCrossWindowGestureSnapshot() proves claim, preview, park, and source-vessel survival, but never proves proxy presence. The headed journey can therefore pass while the dragged embodiment is absent.
  • The reusable lineage already exists: src/draggable/dashboard/SortZone.mjs#startRemoteDrag() creates a target-window DragProxyContainer around the live dragged widget. DockTabSortZone#getDragProxyConfig() already carries dock ownership, theme, and preview-language classes onto body-mounted proxies.

The fix should compose or extract that owner rather than create another drag system.

The Fix

One PR: complete the popup-to-proxy conversion by giving the registered dock target an explicit target-window proxy lifecycle.

  1. On admitted convert-in, park the native vessel as today and create the in-app proxy in the winning target window.
  2. The proxy follows the pointer in target-local coordinates, visibly represents the dragged dock item/stack, and remains translucent enough for the existing drop-zone preview beneath it to stay legible.
  3. Reuse/factor the landed DragProxyContainer and dock proxy configuration; do not introduce a second drag coordinator, preview language, or model path.
  4. Convert-out restores the same parked vessel and retires the target proxy. Commit, cancel, target removal, disconnect, and stale-generation paths retire it exactly once.
  5. Extend semantic diagnostics/tests so “converted + parked + previewed” is not considered visually ready without the target proxy.

Acceptance Criteria

  • During popup-over-popup conversion, exactly one target-window in-app proxy visibly embodies the dragged dock item or stack; the native source vessel remains parked and connected.
  • The proxy follows the live pointer in target-local coordinates and the existing docking zones remain visible beneath it.
  • The proxy consumes the landed dock proxy styling/configuration (DragProxyContainer, ownership marker, active theme, preview language) or one factored equivalent; no parallel drag system is introduced.
  • Convert-out removes the proxy and re-shows the same OS vessel without window.open() re-acquisition; same-instance/store/heartbeat continuity remains green.
  • Commit, cancel, target unregister/disconnect, and stale-generation paths remove the proxy exactly once with no body-mounted residue.
  • A focused semantic witness fails on the current preview-only implementation and proves proxy identity/window/visibility across convert-in → move → convert-out/terminal. Pixel-only evidence is not sufficient.
  • A headed Workstation witness records the visual beat while retaining exactly-one claim, semantic/rendered preview equality, commit-before-close, and existing Scene 3–5 invariants.
  • No supported-browser alpha capability is required for correctness. If one is later discovered and feature-detected, it remains an optional platform optimization behind the in-app baseline.

Out of Scope

Workstation viewport sizing · the initial about:blank white flash · film recapture/composition · generic Chrome-native alpha R&D · Electron-shell materialization · changes to docking model operations or claim arbitration.

Decision Record impact

depends-on ADR 0029 §§2.3 and 2.8.2–2.8.3; no amendment expected because this completes the already-recorded DETACHED_MOVING ⇄ HOVERING_CLAIM embodiment and park lifecycle. If implementation discovers a new ownership state rather than a target-side rendering owner, stop and revalidate the ADR premise before coding.

Related

Parent #15239 · film #15252 · contract #15395 / PR #15567 · lifecycle #15396 · Workstation composition #15906 / PR #16035 · generic proxy lineage #7204.

Freshness evidence: semantic/local duplicate sweep plus latest 20 open issues and the latest 30 A2A messages checked immediately before filing; no current equivalent or competing claim.

Origin Session ID: 019f9e1e-2ef1-72c3-a04d-6bc67a531a8b

Retrieval Hint: "popup-to-proxy target-window DragProxyContainer missing dragged embodiment preview-only conversion"

tobiu referenced in commit 922ec30 - "fix(dashboard): embody converted vessels over target popups (#16090) (#16096)" on Jul 28, 2026, 7:08 PM
tobiu closed this issue on Jul 28, 2026, 7:08 PM