mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-24 06:11:30 +11:00
X11: Fix DND freezing the WM (#688)
Fixes #687 `XdndFinished` isn't supposed to be sent when rejecting a `XdndPosition`; it should only be sent in response to `XdndDrop`. https://freedesktop.org/wiki/Specifications/XDND/
This commit is contained in:
parent
6bec912961
commit
0fca8e8cb5
|
@ -23,6 +23,7 @@
|
||||||
- On Linux, if neither X11 nor Wayland manage to initialize, the corresponding panic now consists of a single line only.
|
- On Linux, if neither X11 nor Wayland manage to initialize, the corresponding panic now consists of a single line only.
|
||||||
- Add optional `serde` feature with implementations of `Serialize`/`Deserialize` for DPI types and various event types.
|
- Add optional `serde` feature with implementations of `Serialize`/`Deserialize` for DPI types and various event types.
|
||||||
- Add `PartialEq`, `Eq`, and `Hash` implementations on public types that could have them but were missing them.
|
- Add `PartialEq`, `Eq`, and `Hash` implementations on public types that could have them but were missing them.
|
||||||
|
- On X11, drag-and-drop receiving an unsupported drop type can no longer cause the WM to freeze.
|
||||||
|
|
||||||
# Version 0.17.2 (2018-08-19)
|
# Version 0.17.2 (2018-08-19)
|
||||||
|
|
||||||
|
|
|
@ -278,25 +278,25 @@ impl EventsLoop {
|
||||||
}
|
}
|
||||||
} else if client_msg.message_type == self.dnd.atoms.position {
|
} else if client_msg.message_type == self.dnd.atoms.position {
|
||||||
// This event occurs every time the mouse moves while a file's being dragged
|
// This event occurs every time the mouse moves while a file's being dragged
|
||||||
// over our window. We emit HoveredFile in response; while the Mac OS X backend
|
// over our window. We emit HoveredFile in response; while the macOS backend
|
||||||
// does that upon a drag entering, XDnD doesn't have access to the actual drop
|
// does that upon a drag entering, XDND doesn't have access to the actual drop
|
||||||
// data until this event. For parity with other platforms, we only emit
|
// data until this event. For parity with other platforms, we only emit
|
||||||
// HoveredFile the first time, though if winit's API is later extended to
|
// `HoveredFile` the first time, though if winit's API is later extended to
|
||||||
// supply position updates with HoveredFile or another event, implementing
|
// supply position updates with `HoveredFile` or another event, implementing
|
||||||
// that here would be trivial.
|
// that here would be trivial.
|
||||||
|
|
||||||
let source_window = client_msg.data.get_long(0) as c_ulong;
|
let source_window = client_msg.data.get_long(0) as c_ulong;
|
||||||
|
|
||||||
// Equivalent to (x << shift) | y
|
// Equivalent to `(x << shift) | y`
|
||||||
// where shift = mem::size_of::<c_short>() * 8
|
// where `shift = mem::size_of::<c_short>() * 8`
|
||||||
// Note that coordinates are in "desktop space", not "window space"
|
// Note that coordinates are in "desktop space", not "window space"
|
||||||
// (in x11 parlance, they're root window coordinates)
|
// (in X11 parlance, they're root window coordinates)
|
||||||
//let packed_coordinates = client_msg.data.get_long(2);
|
//let packed_coordinates = client_msg.data.get_long(2);
|
||||||
//let shift = mem::size_of::<libc::c_short>() * 8;
|
//let shift = mem::size_of::<libc::c_short>() * 8;
|
||||||
//let x = packed_coordinates >> shift;
|
//let x = packed_coordinates >> shift;
|
||||||
//let y = packed_coordinates & !(x << shift);
|
//let y = packed_coordinates & !(x << shift);
|
||||||
|
|
||||||
// By our own state flow, version should never be None at this point.
|
// By our own state flow, `version` should never be `None` at this point.
|
||||||
let version = self.dnd.version.unwrap_or(5);
|
let version = self.dnd.version.unwrap_or(5);
|
||||||
|
|
||||||
// Action is specified in versions 2 and up, though we don't need it anyway.
|
// Action is specified in versions 2 and up, though we don't need it anyway.
|
||||||
|
@ -318,23 +318,21 @@ impl EventsLoop {
|
||||||
// In version 0, time isn't specified
|
// In version 0, time isn't specified
|
||||||
ffi::CurrentTime
|
ffi::CurrentTime
|
||||||
};
|
};
|
||||||
// This results in the SelectionNotify event below
|
// This results in the `SelectionNotify` event below
|
||||||
self.dnd.convert_selection(window, time);
|
self.dnd.convert_selection(window, time);
|
||||||
}
|
}
|
||||||
self.dnd.send_status(window, source_window, DndState::Accepted)
|
self.dnd.send_status(window, source_window, DndState::Accepted)
|
||||||
.expect("Failed to send XDnD status message.");
|
.expect("Failed to send `XdndStatus` message.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.dnd.send_status(window, source_window, DndState::Rejected)
|
self.dnd.send_status(window, source_window, DndState::Rejected)
|
||||||
.expect("Failed to send XDnD status message.");
|
.expect("Failed to send `XdndStatus` message.");
|
||||||
self.dnd.send_finished(window, source_window, DndState::Rejected)
|
|
||||||
.expect("Failed to send XDnD finished message.");
|
|
||||||
}
|
}
|
||||||
self.dnd.reset();
|
self.dnd.reset();
|
||||||
}
|
}
|
||||||
} else if client_msg.message_type == self.dnd.atoms.drop {
|
} else if client_msg.message_type == self.dnd.atoms.drop {
|
||||||
if let Some(source_window) = self.dnd.source_window {
|
let (source_window, state) = if let Some(source_window) = self.dnd.source_window {
|
||||||
if let Some(Ok(ref path_list)) = self.dnd.result {
|
if let Some(Ok(ref path_list)) = self.dnd.result {
|
||||||
for path in path_list {
|
for path in path_list {
|
||||||
callback(Event::WindowEvent {
|
callback(Event::WindowEvent {
|
||||||
|
@ -343,10 +341,16 @@ impl EventsLoop {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(source_window, DndState::Accepted)
|
||||||
|
} else {
|
||||||
|
// `source_window` won't be part of our DND state if we already rejected the drop in our
|
||||||
|
// `XdndPosition` handler.
|
||||||
|
let source_window = client_msg.data.get_long(0) as c_ulong;
|
||||||
|
(source_window, DndState::Rejected)
|
||||||
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
self.dnd.send_finished(window, source_window, DndState::Accepted)
|
self.dnd.send_finished(window, source_window, state)
|
||||||
.expect("Failed to send XDnD finished message.");
|
.expect("Failed to send `XdndFinished` message.");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
self.dnd.reset();
|
self.dnd.reset();
|
||||||
} else if client_msg.message_type == self.dnd.atoms.leave {
|
} else if client_msg.message_type == self.dnd.atoms.leave {
|
||||||
|
|
Loading…
Reference in a new issue