-
Notifications
You must be signed in to change notification settings - Fork 928
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 redux #4079
base: master
Are you sure you want to change the base?
Rework DnD redux #4079
Conversation
008f86a
to
aa18119
Compare
aa18119
to
4f0819f
Compare
b6eba6b
to
fe7132e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will leave macOS re-review up to @madsmtm .
src/event.rs
Outdated
}, | ||
/// The drag operation has been cancelled or left the window. On some platforms, this may occur | ||
/// even if no other drag events have occurred. | ||
DragLeave, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add a position: Option<PhysicalPosition<f64>>
to follow the pointer api.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added position
.
src/changelog/unreleased.md
Outdated
|
||
The `WindowEvent::DroppedFile`, `WindowEvent::HoveredFile` and `WindowEvent::HoveredFileCancelled` | ||
events have been removed, and replaced with `WindowEvent::DragEnter`, `WindowEvent::DragOver`, | ||
`WindowEvent::DragDrop` and `WindowEvent::DragLeave`. | ||
|
||
The old drag-and-drop events were emitted once per file. This occurred when files were *first* | ||
hovered over the window, dropped, or left the window. The new drag-and-drop events are emitted | ||
once per set of files dragged, and include a list of all dragged files. They also include the | ||
pointer position. | ||
|
||
The rough correspondence is: | ||
- `WindowEvent::HoveredFile` -> `WindowEvent::DragEnter` | ||
- `WindowEvent::DroppedFile` -> `WindowEvent::DragDrop` | ||
- `WindowEvent::HoveredFileCancelled` -> `WindowEvent::DragLeave` | ||
|
||
The `WindowEvent::DragOver` event is entirely new, and is emitted whenever the pointer moves | ||
whilst files are being dragged over the window. It doesn't contain any file paths, just the | ||
pointer position. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you write them the way e.g. Pointer
event above written?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed them to DragEntered
, DragDropped
, DragLeft
, and DragMoved
.
// https://www.freedesktop.org/wiki/Specifications/XDND/#xdndposition | ||
// "data.l[2] contains the coordinates of the mouse position relative to the root | ||
// window." | ||
// "data.l[2] = (x << 16) | y" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can keep the link, but what you wrote is already written in the next paragraph.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the redundant comment
let packed_coordinates = xev.data.get_long(2); | ||
let x = (packed_coordinates >> 16) as i16; | ||
let y = (packed_coordinates & 0xffff) as i16; | ||
self.dnd.position = (x, y); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe store translated position directly? I don't think there's a reason to use root coords?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed it to store the translated position.
@@ -502,21 +504,19 @@ impl EventProcessor { | |||
} | |||
|
|||
self.dnd.source_window = Some(source_window); | |||
if self.dnd.result.is_none() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why this got removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.dnd.result.is_none()
is only true
for the first DragEnter
event. Keeping this check means no DragOver
(aka DragMoved
) events will be fired.
if drop_handler.enter_is_valid { | ||
drop_handler.send_event(Event::WindowEvent { | ||
window_id: WindowId::from_raw(drop_handler.window as usize), | ||
event: HoveredFileCancelled, | ||
event: DragLeave, | ||
}); |
There was a problem hiding this 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 wrong, if you had Enter
you should have Leave
, and you send Enter
regardless. Sending Enter
and then not Leave
looks wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above; changed it so nothing is emitted if !enter_is_valid
.
window_id: WindowId::from_raw(drop_handler.window as usize), | ||
event: DragEnter { paths, position }, | ||
}); | ||
drop_handler.enter_is_valid = hdrop.is_some(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we want to utilize it, we should use it for sedening the Enter
as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed it so no events are emitted if !enter_is_valid
.
X11 has the opposite issue: if there are no valid files being dragged, it won't emit any drag start/position events but will emit DragLeave
. That's a pre-existing issue (in the current master branch, it will emit HoveredFileCancelled
without any prior HoveredFile
events), but I'll go ahead and fix that too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we stash whether the enter
was emitted for X11?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes; it's already stored as self.dnd.has_entered
(I'll push those changes)
src/event.rs
Outdated
/// A drag operation has entered the window. | ||
DragEnter { | ||
/// List of paths that are being dragged onto the window. | ||
paths: Vec<PathBuf>, | ||
/// Position of the drag operation. May be negative on some platforms if something is | ||
/// dragged over a window's decorations (title bar, frame, etc). | ||
position: PhysicalPosition<f64>, | ||
}, | ||
/// A drag operation is moving over the window. | ||
DragOver { | ||
/// Position of the drag operation. May be negative on some platforms if something is | ||
/// dragged over a window's decorations (title bar, frame, etc). | ||
position: PhysicalPosition<f64>, | ||
}, | ||
/// The drag operation has dropped file(s) on the window. | ||
DragDrop { | ||
/// List of paths that are being dragged onto the window. | ||
paths: Vec<PathBuf>, | ||
/// Position of the drag operation. May be negative on some platforms if something is | ||
/// dragged over a window's decorations (title bar, frame, etc). | ||
position: PhysicalPosition<f64>, | ||
}, | ||
/// The drag operation has been cancelled or left the window. On some platforms, this may occur | ||
/// even if no other drag events have occurred. | ||
DragLeave, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you reword things to how they are in pointer events?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed the events and reworded the documentation a bit; see above
src/event.rs
Outdated
position: PhysicalPosition<f64>, | ||
}, | ||
/// The drag operation has dropped file(s) on the window. | ||
DragDrop { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DragDrop { | |
DragMoved { |
so it looks like pointer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -426,9 +457,16 @@ declare_class!( | |||
|
|||
/// Invoked when the dragging operation is cancelled | |||
#[method(draggingExited:)] | |||
fn dragging_exited(&self, _sender: Option<&NSObject>) { | |||
fn dragging_exited(&self, info: Option<&ProtocolObject<dyn NSDraggingInfo>>) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For @madsmtm: is this the right way to represent a sender param that may be null? The Swift docs note that for this specific callback, this parameter is nullable.
(As a side node, kinda alarming how the Objective-C docs just don't mention its nullability at all, as far as I can tell. Any idea what's going on there?)
(Original work at rust-windowing#2615; rebased by @valadaptive)
Fixes GTK drag-and-drop coords being offset by (-100, -100). The relevant spec says: > data.l[2] contains the coordinates of the mouse position relative > to the root window. https://www.freedesktop.org/wiki/Specifications/XDND/#xdndposition
We also need to use `convertPoint_fromView` for coordinate conversion-- attempting to do it manually resulted in (0, 0) being the top-left of the window *including* decorations.
It's what translate_coords takes anyway, so the extra precision is misleading if we're going to cast it to i16 everywhere it's used. We can also simplify the "unpacking" from the XdndPosition message--we can and should use the value of 16 as the shift instead of size_of::<c_short> * 2 or something like that, because the specification gives us the constant 16.
ProtocolObject is new in objc2, and lets us use the generated AppKit bindings instead of roughing it with `msg_send!`.
Not yet implemented on macOS
The Swift docs say the dragging info may be nullable here specifically: https://developer.apple.com/documentation/appkit/nsdraggingdestination/draggingexited(_:)
Keep everything in past-tense
Make it clearer that drag events are for dragged *files*, and remove the outdated bit about spurious DragLeft events.
18849af
to
1084930
Compare
Made the requested review changes. |
Needed to display anything on Wayland. DnD still doesn't work on Wayland but the example should at least run.
This picks up from #2615, rebasing it atop the latest winit version and fixing a couple coordinate-space bugs. Part of #720.
Resolves #1550. Closes #2615.
changelog
module if knowledge of this change could be valuable to users