LearnNewsExamplesServices
Frontmatter
id8118
titleSupport OffscreenCanvas node movement between windows (SharedWorkers)
stateClosed
labels
enhancementai
assigneestobiu
createdAtDec 15, 2025, 11:13 PM
updatedAtDec 16, 2025, 12:25 AM
githubUrlhttps://github.com/neomjs/neo/issues/8118
authortobiu
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtDec 16, 2025, 12:25 AM

Support OffscreenCanvas node movement between windows (SharedWorkers)

Closed v11.17.0 enhancementai
tobiu
tobiu commented on Dec 15, 2025, 11:13 PM

This ticket covers the changes required to support moving OffscreenCanvas nodes between windows when using Neo.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.mjs

  • Feature: Introduced canvasWindowMap to track canvas instances by window ID.
  • Update: onRegisterCanvas now populates this map.
  • New Method: onRetrieveCanvas allows components to reclaim an existing canvas reference if it's already held by the worker for a specific window.

2. src/component/Canvas.mjs

  • Logic Update: afterSetMounted now safely handles canvas transfer.
  • Flow:
    1. Requests offscreen canvas from Main thread.
    2. If Main reports transferred: true (indicating prior transfer) AND shared workers are enabled:
      • Falls back to requesting the existing canvas from the worker via retrieveCanvas.
    3. If Main provides a new offscreen canvas:
      • Registers it normally via registerCanvas (now including windowId).

3. src/main/DomAccess.mjs

  • Robustness: onGetOffscreenCanvas now wraps transferControlToOffscreen() in a try-catch block.
  • Return Value: Returns { transferred: true } if the transfer fails, instead of throwing an error.
  • Safety: Added a check for undefined node to prevent runtime errors.

4. apps/agentos/view/ViewportController.mjs

  • Fix: Added widget.mounted = true in onDragBoundaryEntry to ensure correct component lifecycle state during re-integration.

Goal

Enable seamless canvas reuse across windows without losing the OffscreenCanvas context or triggering DOM exceptions.

tobiu added the enhancement label on Dec 15, 2025, 11:13 PM
tobiu added the ai label on Dec 15, 2025, 11:13 PM
tobiu assigned to @tobiu on Dec 15, 2025, 11:14 PM
tobiu referenced in commit 9a5c96c - "Support OffscreenCanvas node movement between windows (SharedWorkers) #8118" on Dec 15, 2025, 11:15 PM
tobiu
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:

  1. 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.
  2. 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 onRetrieveCanvas and DomAccess ensures 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