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

Wayland: support basic Drag&Drop #2429

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

Conversation

SludgePhD
Copy link
Contributor

  • Tested on all platforms changed
  • 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

Closes #1881

@SludgePhD
Copy link
Contributor Author

SludgePhD commented Aug 13, 2022

I've also pushed a commit that emits all appropriate cursor events, which should address #1550 at least on Wayland. Other platforms don't do this yet, so let me know if I should leave it out.

(though one issue I noticed is that some compositors send DnD events when the cursor is slightly outside the window (eg. hovering over its shadow only on KDE), which results in out-of-bounds cursor coordinates being sent to the app)

@kchibisov
Copy link
Member

kchibisov commented Aug 14, 2022

Could you test that it doesn't blow up in alacritty for example or when using https://github.com/smithay/smithay-clipboard ? I think gnome doesn't allow to have drag and drop and clipboard by using multiple data device managers. IIRC it uses just the last one, and that's the reason I haven't implemented drag and drop inside winit, since winit should support clipboard, otherwise registering clipboard via external crates will disable drag and drop from inside the winit.

The work to bring clipboard is #2156 , but I don't have that much time to work on it right now unfortunately, but I hope to go back to it soon...

@SludgePhD
Copy link
Contributor Author

I've tested with Alacritty on KDE Plasma, and both Drag&Drop and clipboard access work fine with this patch applied.

If GNOME doesn't support this properly, that does seem unfortunate, but this PR will at least make apps work on other compositors, and also make apps work everywhere that only need Drag&Drop and no clipboard access.

Do you happen to know if GNOME's behavior is correct here or does the Wayland specification require compositors to support multiple data device managers?

@kchibisov
Copy link
Member

Would suggest to test GNOME, since it's a major compositor and we can't break it even when it's a GNOME bug.

@SludgePhD
Copy link
Contributor Author

SludgePhD commented Aug 15, 2022

Alacritty built with this patch running in a nested GNOME session does not crash or break when dropping a file, but Drag&Drop doesn't do anything (so behavior matches winit master). Clipboard access still works fine.

Amusingly, Konsole in the same nested GNOME session does crash when dropping a file from a Dolphin window in the same session. Additionally, closing the nested GNOME shell window made it abort with several assertion failures, so it looks like winit is miles ahead of the typical Linux-on-the-desktop experience already... sadly

EDIT: also tested my drag&drop example app in the GNOME session and it works fine!

@kchibisov
Copy link
Member

The thing is that it'll work, but if you create another device manager the privious one (in winit here) would stop working. I do want to have drag and drop in winit Wayland, but I'm not sure whether I'll have time to look into it, given I think that clipboard issue should be resolved first, so we can have both at the same time without collapsing.

@SludgePhD
Copy link
Contributor Author

Yeah, I understand (unless Alacritty somehow does something differently?). As far as I can tell, this PR does not regress anything even if applications do use another data manager for accessing the clipboard. Drag&Drop simply won't work, just like it does now.

@kchibisov
Copy link
Member

I know what alacritty does and I know why the feature wasn't in winit, since I remember the GNOME bug given that it's quite easy to repro it. Besides that it's fair to assume that we can have drag and drop that way for now.

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.

See the clipboard PR I've linked to you before on how to handle pipe reading with calloop. It could also give an idea how to integrate dnd given that it has data device as well.

src/platform_impl/linux/wayland/seat/dnd/handlers.rs Outdated Show resolved Hide resolved
src/platform_impl/linux/wayland/seat/dnd/handlers.rs Outdated Show resolved Hide resolved
src/platform_impl/linux/wayland/seat/dnd/handlers.rs Outdated Show resolved Hide resolved
src/platform_impl/linux/wayland/seat/dnd/mod.rs Outdated Show resolved Hide resolved
}
}
DndEvent::Motion { x, y, .. } => {
if let Some(window_id) = inner.window_id {
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure why it generates that event, could you elaborate?

.event_sink
.push_window_event(WindowEvent::HoveredFileCancelled, window_id);
winit_state.event_sink.push_window_event(
WindowEvent::CursorLeft {
Copy link
Member

Choose a reason for hiding this comment

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

Also not sure how it's related, I'm pretty sure wl_pointer will send the right events anyway?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That doesn't seem to happen at least on KDE and GNOME. Only when no file is being dragged over.

Comment on lines +35 to +42
winit_state.event_sink.push_window_event(
WindowEvent::CursorEntered {
device_id: crate::event::DeviceId(
crate::platform_impl::DeviceId::Wayland(DeviceId),
),
},
window_id,
);
winit_state.event_sink.push_window_event(
WindowEvent::CursorMoved {
device_id: crate::event::DeviceId(
Copy link
Member

Choose a reason for hiding this comment

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

ditto.

src/platform_impl/linux/wayland/event_loop/state.rs Outdated Show resolved Hide resolved
@SludgePhD
Copy link
Contributor Author

Addressed your comments

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.

Unfortunatelly this doesn't work for me on sway and I think the reason is that serial we pass in accept is zero.

The issue with sway that there's no drop event. The mime types do match, etc.

Given that it's likely broken due to sctk bug I can't merge it, unless there's a way to make it work with e.g. thunar + alacritty on sway without patching gtk. Other applications do work here, but they pass normal serial.

let window_id = make_wid(&surface);
inner.window_id = Some(window_id);
offer.accept(Some(MIME_TYPE.into()));
let _ = parse_offer(&inner.loop_handle, offer, move |paths, winit_state| {
Copy link
Member

Choose a reason for hiding this comment

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

None of these is needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The callback emits the HoveredFile event though?

Copy link
Member

Choose a reason for hiding this comment

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

Hm, yeah. Sure. I'm not sure why anyone would need it. but ok.

@SludgePhD
Copy link
Contributor Author

sway appears to (correctly) send CRLF-delimited URI lists, while GNOME and KDE only use \n as a delimiter. I've pushed a fix for that, which makes things work correctly on sway for me.

@kchibisov
Copy link
Member

sway appears to (correctly) send CRLF-delimited URI lists, while GNOME and KDE only use \n as a delimiter. I've pushed a fix for that, which makes things work correctly on sway for me.

My problem that I don't see done event at all. It's not like something is crlf or anything. Also sway has nothing to do with crlf, that's what applications set. Could you try sway master branch?

@SludgePhD
Copy link
Contributor Author

Huh, right, that must be thunar's doing then. I'll check if I can repro with sway master.

@SludgePhD
Copy link
Contributor Author

Sorry for the confusion, it reproduces even with the release of sway that I was using, the \r issue just distracted me a bit.

I've patched sctk to pass the correct serial to the compositor but it still does not work (Smithay/client-toolkit@bef07ea). The sway debug log is also not very helpful, it only contains this when I try to drag&drop:

00:00:59.201 [wlr] [types/data_device/wlr_data_source.c:189] Offering additional MIME type after wl_data_device.set_selection
00:00:59.201 [wlr] [types/data_device/wlr_data_source.c:196] Ignoring duplicate MIME type offer text/uri-list
00:00:59.201 [wlr] [types/data_device/wlr_data_source.c:189] Offering additional MIME type after wl_data_device.set_selection

@SludgePhD
Copy link
Contributor Author

Sway also appears to send multiple hover enter events in sequence, which end up in the application as multiple HoveredFile events without any intervening HoveredFileCancelled or DroppedFile. I think this might be a sway or wlroots bug?

@kchibisov
Copy link
Member

But it works for me with any other application, so it's confusing.

TheNumerus added a commit to TheNumerus/black-hole that referenced this pull request Dec 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

Support drag and drop on wayland
3 participants