Skip to content

Drag & drop - #492

Open
Klemen2 wants to merge 2 commits into
DioxusLabs:mainfrom
Klemen2:dnd
Open

Drag & drop#492
Klemen2 wants to merge 2 commits into
DioxusLabs:mainfrom
Klemen2:dnd

Conversation

@Klemen2

@Klemen2 Klemen2 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Stacked on top of: #614

This PR adds the following

Drag events:

  • dragenter event
  • dragover event
  • dragleave event
  • drop event
  • dragstart event
  • drag event
  • dragend event

External drags:

  • dragging files
  • dragging text (plain/html/rtf)
  • ability to downcast data transfer to handle platform specific data types

Internal drags

  • dragging out of the window
  • dragging text (plain)

Shell

  • set_datatransfer

Not included in this pr: dragging text (html), dragging images, dragging links, dragging input/textbox text, dropping to input/textbox, cursor icon, drop effect based on target

WPT results

10 newly passing, 0 newly failing (net +10).

Full diff (10 changed tests)
+ Fail => Pass css/WOFF2/blocks-extraneous-data-003.xht
+ Fail => Pass css/WOFF2/blocks-extraneous-data-004.xht
+ Fail => Pass css/WOFF2/blocks-extraneous-data-005.xht
+ Fail => Pass css/WOFF2/blocks-extraneous-data-006.xht
+ Fail => Pass css/WOFF2/blocks-extraneous-data-007.xht
+ Fail => Pass css/WOFF2/blocks-extraneous-data-008.xht
+ Fail => Pass css/WOFF2/blocks-overlap-003.xht
+ Fail => Pass css/WOFF2/header-reserved-001.xht
+ Fail => Pass css/WOFF2/tabledata-extraneous-data-001.xht
+ Fail => Pass css/WOFF2/tabledata-recontruct-loca-001.xht

Generated by the WPT workflow.

@Klemen2
Klemen2 marked this pull request as draft July 6, 2026 11:29
Comment thread packages/blitz-traits/src/events.rs Outdated
@nicoburns

Copy link
Copy Markdown
Member

Will take a proper look but:

This is blocked on most likely next winit release as it's using the new dnd api

Just wanted to say that this seems like a very sensible choice. I'm anticipating that we'll probably get a new Winit beta once the DnD PR lands.

@Klemen2

Klemen2 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

No need to rush, I've only tested the incoming dnd events and not everything is implemented yet, but it's a great start.
I also think that I need to change how DataTransferReceived is handled since i believe it can come after the drop is handeled

@nicoburns nicoburns left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took a look because I was curious and have a left a couple of notes.

And a general comment that:

Drag and Drop actually has three distinct use cases: dragging elements within a page, dragging data out of a page, and dragging data into a page. They have subtly different requirements and implementations.

(https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API)

And this only currently only implements "dragging data into a page". We don't necessarily need an implementation of all 3 at once, but it's at least worth thinking about when designing the API (and I'd personally be kinda tempted to try to handle "dragging elements within a page" too, as I think that might end up changing the design somewhat).

Comment thread packages/dioxus-native/src/config.rs Outdated
Comment thread packages/blitz-traits/src/events.rs Outdated
@Klemen2

Klemen2 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

I think that the enter/over/leave/drop are now handled correctly (needs #496 to be fixed for bubbling)

I think that the structure can support "dragging elements within a page" but I haven't come to that part yet, also dragable=true needs to handle the event data automagically so yea fun stuff

@Klemen2

Klemen2 commented Jul 11, 2026

Copy link
Copy Markdown
Contributor Author

So I tried implementing dragstart/drag/dragend, but for whatever reason ondragstart is not even getting triggered... am I missing something somewhere? it gets to self.handler.handle_event in the driver, but not to the actual event, I don't think the implementation is correct yet, especially drag/dragend so thats still wip

@nicoburns

nicoburns commented Jul 11, 2026

Copy link
Copy Markdown
Member

@Klemen2 You need to detect and send dragstart (and set blitz-dom into a "dragging" state) yourself! See pointer.rs where we already detect drags for text selection and pan-to-scroll on mobile.

EDIT: well that's for dragging DOM elements with draggable=true. For external drags, you should probably be firing DragStart when first encountering a new DragEnter. Winit DragEvent(enter window) != web dragenter (enter droppable node).

@Klemen2

Klemen2 commented Jul 12, 2026

Copy link
Copy Markdown
Contributor Author

I did some changes and now you can d&d text within the app, haven't implemented the outgoing drags yet, but ondragstart is still not triggering on draggable (implementation is inside pointer.rs)

For external drags, you should probably be firing DragStart

as far as I can tell, dragstart only fires on elements with draggable=true / draggable types (text, images, link) from where the drag started, and doesn't fire at all for external drags

@nicoburns nicoburns added the B-winit Blocked a Winit release label Jul 13, 2026
@Klemen2
Klemen2 requested a review from nicoburns July 22, 2026 16:10
@Klemen2

Klemen2 commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

I think that this is mostly ready, (todo: cursor icon, dragging images, inputs, links)
I don't really know how should i be implementing get_datatransfer for the shell, std::mpsc? or futures oneshot?
Should internal drags be registered with OS (using event loop) when drag starts or when cursor leaves the window (the way its now)? - I think I answered this myself with just asking this question

@nicoburns

Copy link
Copy Markdown
Member

Testing this on macOS I'm getting two files when dropping a single file onto the drop zone

@Klemen2

Klemen2 commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

Testing this on macOS I'm getting two files when dropping a single file onto the drop zone

Interesting, I'm not experiencing this on windows

Comment thread packages/blitz-traits/src/events/datatransfer.rs Outdated
Comment thread packages/blitz-dom/src/events/driver.rs
Comment thread packages/blitz-dom/src/events/driver.rs
Comment thread packages/dioxus-native-dom/src/events.rs Outdated
Comment thread packages/blitz-shell/src/window.rs Outdated
@Klemen2
Klemen2 force-pushed the dnd branch 2 times, most recently from dc2795b to 9aadb39 Compare July 24, 2026 15:01
@Klemen2

Klemen2 commented Jul 26, 2026

Copy link
Copy Markdown
Contributor Author

@nicoburns how do I fix this returning 33 for drag start since the drag start event is 34?

let event_kind_idx = event.data.discriminant() as usize;

I don't think that doing this is the solution

let mut event_kind_idx = event.data.discriminant() as usize;
match event.data {
    DomEventData::DragStart(_) => event_kind_idx += 1,
    _ => {}
}

the custom draggable do work after doing this

Fixed it

@Klemen2
Klemen2 marked this pull request as ready for review July 26, 2026 13:06
@Klemen2
Klemen2 force-pushed the dnd branch 4 times, most recently from 30910f7 to b863f8d Compare July 29, 2026 08:24
Klemen2 added 2 commits August 5, 2026 15:03
- dragenter/dragover/drageave/drop
- dragstart/drag/dragend
- outgoing drags
- drop effect (not fully implemented)
- internal drags (not fully implemented)
- shell set_datatransfer (I don't think that get_datatransfer is
  necessary as drop will always be an ui event so custom widgets can use
  that)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

B-winit Blocked a Winit release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants