Frontmatter
| id | 8118 |
| title | Support OffscreenCanvas node movement between windows (SharedWorkers) |
| state | Closed |
| labels | enhancementai |
| assignees | tobiu |
| createdAt | Dec 15, 2025, 11:13 PM |
| updatedAt | Dec 16, 2025, 12:25 AM |
| githubUrl | https://github.com/neomjs/neo/issues/8118 |
| author | tobiu |
| commentsCount | 1 |
| parentIssue | null |
| subIssues | [] |
| subIssuesCompleted | 0 |
| subIssuesTotal | 0 |
| blockedBy | [] |
| blocking | [] |
| closedAt | Dec 16, 2025, 12:25 AM |
Support OffscreenCanvas node movement between windows (SharedWorkers)
tobiu assigned to @tobiu on Dec 15, 2025, 11:14 PM

tobiu
Dec 15, 2025, 11:17 PM
Input from Gemini 2.5 pro:
✦ For additional context, these changes were driven by two specific use cases:
- Advanced Dashboard Drag & Drop: Supporting a scenario where a canvas node is effectively duplicated into a new popup window during a drag operation, and then potentially re-used (via the original node) if the popup is resolved back into an in-app drag proxy within the same drag operation. This requires the system to handle "already transferred" states gracefully when reusing the same DOM node.
- Standard Cross-Window Movement: Ensuring the logic remains robust for the standard pattern where a node is destroyed in Window A and a new node (with a new ID) is created in Window B, and potentially back again.
The refactored logic in
onRetrieveCanvasandDomAccessensures both the "hacky" reuse and the standard lifecycle work without errors.
tobiu cross-referenced by #8119 on Dec 16, 2025, 12:00 AM
tobiu closed this issue on Dec 16, 2025, 12:25 AM
This ticket covers the changes required to support moving
OffscreenCanvasnodes between windows when usingNeo.config.useSharedWorkers. This is critical for drag-and-drop scenarios where a canvas component is moved from a container to a popup window and back, preventing "ownership already transferred" errors.Changes
1.
src/worker/Canvas.mjscanvasWindowMapto track canvas instances by window ID.onRegisterCanvasnow populates this map.onRetrieveCanvasallows components to reclaim an existing canvas reference if it's already held by the worker for a specific window.2.
src/component/Canvas.mjsafterSetMountednow safely handles canvas transfer.transferred: true(indicating prior transfer) AND shared workers are enabled:retrieveCanvas.registerCanvas(now includingwindowId).3.
src/main/DomAccess.mjsonGetOffscreenCanvasnow wrapstransferControlToOffscreen()in atry-catchblock.{ transferred: true }if the transfer fails, instead of throwing an error.nodeto prevent runtime errors.4.
apps/agentos/view/ViewportController.mjswidget.mounted = trueinonDragBoundaryEntryto ensure correct component lifecycle state during re-integration.Goal
Enable seamless canvas reuse across windows without losing the
OffscreenCanvascontext or triggering DOM exceptions.