Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework DnD #2615

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open

Conversation

amrbashir
Copy link
Contributor

@amrbashir amrbashir commented Jan 3, 2023

  • Tested on all platforms changed
    • Windows
    • macOS
    • X11
  • Added an entry to CHANGELOG.md if knowledge of this change could be valuable to users
  • Updated documentation to reflect any user-facing changes, including notes of platform-specific behavior
  • Created or updated an example program if it would help users understand this functionality
  • Updated feature matrix, if new features were added or implemented

@kchibisov
Copy link
Member

Could you elaborate why this is needed? Don't you get pointer motion events during DnD? It's just strange that we have 2 sources of pointer events during dnd with that.

@kchibisov
Copy link
Member

This is also a breaking change.

@amrbashir
Copy link
Contributor Author

Could you elaborate why this is needed? Don't you get pointer motion events during DnD? It's just strange that we have 2 sources of pointer events during dnd with that.

You get the cursor event only right before the DroppedFile event happens but not while HoveredFile, also there has been reports that it sometimes fire after the DroppedFile (Can't reproduce but see #1550 (comment)). Adding the cursor position to these events removes the need to sync with other events.

Copy link
Member

@kchibisov kchibisov left a comment

Choose a reason for hiding this comment

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

Just to ensure, have you tested the X11 part of it? (I just can't do that myself, but I guess that you can easily do that with any file manager)

src/event.rs Outdated Show resolved Hide resolved
src/event.rs Outdated Show resolved Hide resolved
@kchibisov kchibisov mentioned this pull request Jan 17, 2023
11 tasks
amrbashir and others added 3 commits January 17, 2023 13:58
Co-authored-by: Kirill Chibisov <contact@kchibisov.com>
Co-authored-by: Kirill Chibisov <contact@kchibisov.com>
@amrbashir
Copy link
Contributor Author

I haven't tested X11 nor macOS but I can test X11 later today.

@amrbashir
Copy link
Contributor Author

Alright, X11 should be fine now. The returned coordinates were root window coordinates so I had to translate them before dispatching the event.

Copy link
Member

@kchibisov kchibisov left a comment

Choose a reason for hiding this comment

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

I think it's a bit more clear which events.

CHANGELOG.md Outdated Show resolved Hide resolved
amrbashir and others added 2 commits January 18, 2023 19:33
Co-authored-by: Kirill Chibisov <contact@kchibisov.com>
Copy link
Member

@madsmtm madsmtm left a comment

Choose a reason for hiding this comment

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

I agree that it makes sense to have for DroppedFile, but not so sure about HoveredFile? It seems like, for that to be useful, you'd have to receive the event continuously (which you at least don't on macOS)

src/platform_impl/macos/window_delegate.rs Outdated Show resolved Hide resolved
@kchibisov
Copy link
Member

but not so sure about HoveredFile? It seems like, for that to be useful, you'd have to receive the event continuously (which you at least don't on macOS)

That would strange, I'd assume you can know that you're over some element while doing drag and drop? Maybe the event is sent via some side channel, so we should plumb it to hovered?

@amrbashir
Copy link
Contributor Author

but not so sure about HoveredFile? It seems like, for that to be useful, you'd have to receive the event continuously (which you at least don't on macOS)

It is the same behavior on Windows and Linux too, the event is emitted only once upon entering the window.

Copy link
Member

@madsmtm madsmtm left a comment

Choose a reason for hiding this comment

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

macOS impl tested and approved from my side.

It is the same behavior on Windows and Linux too, the event is emitted only once upon entering the window.

HoveredFile.position still doesn't really make sense to me, perhaps we should instead just emit two events CursorMoved { position } + HoveredFile { path } (or the other way around, if that's better)?

Adding the cursor position to these events removes the need to sync with other events.

(Though I do believe you when you say it's useful, I don't use the API myself, so it's not a blocker for me).

@madsmtm madsmtm added the S - enhancement Wouldn't this be the coolest? label Jan 21, 2023
@kchibisov
Copy link
Member

I think a better proposal would be to introduce new events, DragEnter, DragHover, DragDrop, DragCancel and/or maybe DragLeave? On Windows (and on macOS too, I think,) DragLeave and DragCancel are the same thing, so maybe only One of them should be added.

DragEnter, DragHover, DragDrop, and DrapLeave sounds good to me. It'll match the Wayland pretty match.

However, I think we might want to send CursorMotion events instead of DragHover and remove it? What's even the purpose of it anyway?

@madsmtm do you get any cursor events when moving drag and drop over the window, don't you get CurserMoved?

(Though I do believe you when you say it's useful, I don't use the API myself, so it's not a blocker for me).

I think what we should do is to plumb the current mouse position inside the DnD and suppress the mouse/touch events during dnd? That way the API for it will be unique among the input backend, since both touch and mouse could start DND.

Though, it could be hard to plumb the mouse/touch position inside the dnd, though you can broadcast on such platforms that you're doing DND and emit extra bits...

@amrbashir
Copy link
Contributor Author

However, I think we might want to send CursorMotion events instead of DragHover and remove it? What's even the purpose of it anyway?

using DragHover you can get the current hover position and then check if it is inside a drop zone or not, if it is, you may highlight the drop zone so the user have a visual indication where to drop the file.

@kchibisov
Copy link
Member

using DragHover you can get the current hover position and then check if it is inside a drop zone or not, if it is, you may highlight the drop zone so the user have a visual indication where to drop the file.

Ah, so it pairs with some API to set DND zones? On Wayland most of the time you should be fine with CursorMoved and DragEnter, so you know that you have DND with the cursor and can highlight drop areas yourself, but you don't define them on a display server level, it's up to you how to handle them.

The thing is that winit should send either CursorMoved or Hovered event, it shouldn't send both at the same time.

@amrbashir
Copy link
Contributor Author

The thing is that winit should send either CursorMoved or Hovered event, it shouldn't send both at the same time.

why not both? if the OS sends them both, I think winit should pass that through as well

@madsmtm
Copy link
Member

madsmtm commented Jan 29, 2023

do you get any cursor events when moving drag and drop over the window, don't you get CurserMoved?

Nope, you get neither WindowEvent::CursorMoved nor DeviceEvent::MouseMotion.

But it seems you can opt-in to getting updates about the current drag operation, so one could probably implement a DragHover event on macOS.


Should we consider postponing this PR to 0.29? It seems like there's still quite some work to do figuring out the desired design (and implementing it, and testing it).

@kchibisov
Copy link
Member

why not both? if the OS sends them both, I think winit should pass that through as well

I guess using both will also work, I'm just afraid of the potential collisions and such, since DND mouse movements shouldn't update mouse cursor. But I guess on most systems the event data is separate already.

I'm not sure I like Hovered as a name, maybe DragMoved will be better.

@kchibisov
Copy link
Member

Should we consider postponing this PR to 0.29? It seems like there's still quite some work to do figuring out the desired design (and implementing it, and testing it).

We may do so if it'll be the only PR left.

@amrbashir amrbashir changed the title Add cursor position to DroppedFile and HoveredFile events Rework DnD Feb 11, 2023
@amrbashir
Copy link
Contributor Author

I'm not sure I like Hovered as a name, maybe DragMoved will be better.

I went with DragOver since it could be triggered even if the mouse hasn't moved.

@dhardy
Copy link
Contributor

dhardy commented Feb 12, 2023

Use of CursorMotion sounds problematic: what happens if the event source is touch not mouse?

Ah, so it pairs with some API to set DND zones?

I much prefer the API in this PR (just send the coordinates).


The current API (i.e. this PR) seems fine except maybe one thing: it clones a Vec<PathBuf> on each cursor motion. Is this sensible over, maybe dyn AsRef<Path> or some such?

Also the API should be clear on whether CursorMotion, Touch etc. may still be received during DnD.


Edit: clarify that "current API = this PR"

@amrbashir
Copy link
Contributor Author

The current API seems fine except maybe one thing: it clones a Vec<PathBuf> on each cursor motion. Is this sensible over, maybe dyn AsRef<Path> or some such?

Using dyn AsRef<Path> would require manual implementation for the Debug trait and would need to either remove the PartialEq derive or implement it manually so I don't think it is worth it.

I initially had DragOver only emit the drag location without paths, since DragEnter emits the paths and it will be re emitted on DragDrop but I added just to show it is possible and if it is desired behavior or not.

@dhardy
Copy link
Contributor

dhardy commented Feb 13, 2023

Using dyn AsRef would require manual implementation ...

Rust doesn't support multi-trait objects (yet) but you can do this:

pub trait HasPath: Debug + PartialEq + Eq + AsRef<Path> {}

But this is somewhat irrelevant in my opinion. Do we want to lock winit into an API which copies a bunch of paths on every mouse movement? Or is it irrelevant since all platforms re-send those on each movement anyway?

@amrbashir
Copy link
Contributor Author

Do we want to lock winit into an API which copies a bunch of paths on every mouse movement? Or is it irrelevant since all platforms re-send those on each movement anyway?

Only Windows doesn't send it on each movement, x11 and macOS do.

@madsmtm
Copy link
Member

madsmtm commented Feb 19, 2023

I think I'd prefer to just leave paths out of DragOver - if you need to do something with the paths while they're being dragged you can just store it yourself from DragEnter.

And maybe even remove it from DragDrop? Can the dragged items change while they're being dragged? (Or should we leave it in for ease-of-use?)

@amrbashir
Copy link
Contributor Author

And maybe even remove it from DragDrop? Can the dragged items change while they're being dragged? (Or should we leave it in for ease-of-use?)

I doubt that it can change but I'd say keep it for ease-of-use

@amrbashir
Copy link
Contributor Author

@kchibisov It is been a while, and now that I have some time to work on this and fix conflicts, do you think this rework should land soon?

@geom3trik
Copy link

Is this PR still compatible with the recent winit API changes or does it need updating?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
I - BREAKING CHANGE S - api Design and usability S - enhancement Wouldn't this be the coolest?
Development

Successfully merging this pull request may close these issues.

5 participants