LearnNewsExamplesServices
Frontmatter
id9356
titleChrome Windows: Multi Window Drag & Drop
stateClosed
labels
bug
assigneestobiu
createdAtMar 6, 2026, 10:10 AM
updatedAtMar 15, 2026, 11:34 PM
githubUrlhttps://github.com/neomjs/neo/issues/9356
authorkmunk-klarso
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtMar 15, 2026, 11:29 PM

Chrome Windows: Multi Window Drag & Drop

Closed v12.1.0 bug
kmunk-klarso
kmunk-klarso commented on Mar 6, 2026, 10:10 AM
  • Open Docked Window -- auf weiterem fenster Position rechts und links macht keinen Unterschied -- Create Dialog lässt sich nicht zwischen Fenster hin und herziehen, Dialog verschwindet dabei
tobiu referenced in commit 231a645 - "bugfix: Fix cross-window Drag&Drop component coordinates (#9356) on Mar 15, 2026, 11:28 PM
tobiu
tobiu Mar 15, 2026, 11:28 PM

Input from Gemini 3.1 Pro:

✦ Hi @kmunk-klarso, thanks a lot for reporting this issue! It was an incredibly subtle bug involving a regression in the component styling system.

Here is an in-depth breakdown of what was happening and how we fixed it:

The Problem

  1. The Drop Calculation: In the multi-window SharedDialog app, when a dialog was dropped into the other window, the MainContainerController calculated the new left and top coordinates and applied them to dialog.wrapperStyle.
  2. The Merge Conflict: The base Component handles styling via two reactive configs: style_ and wrapperStyle_. When you modify either, it triggers updateStyle(), which merges them into the actual VDOM tree: vdom.style = {...me.wrapperStyle, ...me.style}.
  3. The Regression: Because ...me.style comes last in the merge, the old coordinates from the previous window (which were stored in me.style by the DragZone upon drag completion) completely overrode the newly calculated coordinates in me.wrapperStyle. This caused the dialog to render at its old coordinates in the new window, effectively vanishing from view (likely off-screen).

The Puzzling Part: Why did it work in older Neo.mjs versions?

The reason this used to work fine in older versions of the framework comes down to a side effect that was present in the wrapperStyle_ getter inside src/component/Base.mjs:

// Old buggy version
beforeGetWrapperStyle(value) {
    return {...Object.assign(this.vdom.style || {}, value)}
}

Object.assign() mutates its first argument in place! In older versions of Neo, this side effect accidentally masked the merge conflict. The timing of property accesses under the old config system meant this.vdom.style was mutated directly before the VDOM was mounted, effectively sneaking the correct coordinates into the tree.

With the introduction of the new core.Config reactivity system, the timing of these getters and setters became stricter and more predictable. The side effect was no longer triggered at the exact moment needed to mask the bug. Interestingly, while diagnosing this, we temporarily added console.log(dialog.wrapperStyle) which artificially triggered the getter. This caused the mutation to fire right when it was needed, "fixing" the bug locally and ultimately guiding us to the root cause!

The Fix

  1. Fixed the Side Effect: We removed the mutating Object.assign side effect from src/component/Base.mjs -> beforeGetWrapperStyle. It now safely returns a merged object without mutating the VDOM directly: return {...this.vdom.style, ...value}.
  2. Fixed the Controller: We updated the SharedDialog app's MainContainerController to correctly apply the new drop coordinates to dialog.style instead of dialog.wrapperStyle. Since Dialog.mjs uses style for its drag positioning, the controller must also use style when calculating new positions to prevent the old style from overriding the new coordinates.
  3. Cleaned up Routing: We also took the opportunity to clean up onDragStart, ensuring the windowId is correctly passed to the remote Neo.Main.getWindowData() call, adhering to the strict architectural constraints of our RemoteMethodAccess system.

The changes have been pushed to the dev branch. Thanks again for the report!

tobiu assigned to @tobiu on Mar 15, 2026, 11:29 PM
tobiu closed this issue on Mar 15, 2026, 11:29 PM