Skip to content

Add host-to-guest file drag and drop - #751

Draft
zats wants to merge 1 commit into
insidegui:mainfrom
zats:feature/host-guest-file-drag-drop
Draft

Add host-to-guest file drag and drop#751
zats wants to merge 1 commit into
insidegui:mainfrom
zats:feature/host-guest-file-drag-drop

Conversation

@zats

@zats zats commented Aug 25, 2026

Copy link
Copy Markdown

This draft only documents my approach. I know the maintainer already plans this feature, so no code review is needed.

Goal

Support host-to-macOS-guest file drag and drop without shared folders.

Approaches tried

  • Forward the host drag directly: VZVirtualMachineView has no drag-session bridge.
  • Use shared folders: this requires VM configuration and does not meet the goal.
  • Start with a fabricated leftMouseDragged: Finder copied before host release.
  • Start with a fabricated leftMouseDown: the source panel blocked Finder.
  • Move the panel offscreen: AppKit still cancelled the drag without a held mouse button.
  • Queue mouseDown through AppKit: the inactive guest helper discarded it.
  • Dispatch mouseDown through the panel: the session started but ended immediately.
  • Inject mouseDown with Core Graphics: the panel was not yet ready for hit testing.
  • Delay Core Graphics injection until the panel is ready: this worked.

Final flow

  1. The host VM view accepts the file drag.
  2. The host sends file bytes through a virtio socket.
  3. Guest Buddy stages the files in its temporary directory.
  4. Guest Buddy puts an invisible 48×48 nonactivating panel under the guest pointer.
  5. It waits 50 ms for WindowServer hit testing.
  6. It injects a Core Graphics leftMouseDown.
  7. The panel starts a real NSDraggingSession from mouseDown(with:).
  8. The panel moves offscreen so the guest app becomes the target.
  9. Host pointer movement becomes guest leftMouseDragged events.
  10. Host release becomes a guest leftMouseUp.
  11. The guest app accepts or rejects the drop.
  12. Guest Buddy reports the real operation to the host.

Workarounds

  • Invisible panel: AppKit needs a local view to start the guest drag.
  • Core Graphics injection: AppKit has no supported API to start this drag without a local gesture.
  • Accessibility permission: Core Graphics input injection requires it.
  • 50 ms delay: WindowServer needs time to make the panel hit-testable.
  • Main-display mapping: the current coordinate conversion handles one guest display.
  • Brief click interception: the panel must receive the initial mouse-down before it moves offscreen.

@insidegui

Copy link
Copy Markdown
Owner

Thanks for sharing, this will definitely be useful as a reference!

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.

2 participants