`FileDragAndDrop` events on wayland are WEIRD
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 16h
- Merged PRs (30d)
- 171
Description
## Bevy Version
Specify the release number or commit hash of the version you're using:
```toml
bevy = "0.14.2"
```
## [Optional] Relevant System Information
Provide relevant system information for context:
```plaintext
cargo 1.81.0 (2dbb1af80 2024-08-20)
rustc 1.81.0 (eeb90cda1 2024-09-04)
OS: Ubuntu 24.10
```
## What You Did
I created a minimal viable product (MVP) to demonstrate a bug. The repository can be found [here](https://github.com/metdxt/bevy_wayland_dnd). The app allows users to drop images onto a canvas, but it exhibits issues on Wayland.
The main.rs file of MVP
```rust
/// This is a bare-bones app that allows dropping images onto a canvas.
/// This is a minimal example of a bug with wayland DnD handling.
use bevy::input::mouse::MouseWheel;
use bevy::prelude::*;
use bevy::window::PrimaryWindow;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.init_resource::()
.add_systems(Startup, setup)
.add_systems(Update, (
handle_zoom,
global_cursor,
file_drop
.after(global_cursor) // Making extra sure we run file_drop after cursor pos update. Doesn't help at all.
))
.run();
}
#[derive(Component)]
struct CanvasCamera;
fn setup(mut commands: Commands) {
commands.spawn((Camera2dBundle::default(), CanvasCamera));
}
fn handle_zoom(
mut evr_scroll: EventReader,
mut query_camera: Query<&mut OrthographicProjection, With>,
) {
for ev in evr_scroll.read() {
let value = ev.y;
let mut p = query_camera.single_mut();
p.scale -= p.scale * 0.1 * value;
p.scale = p.scale.clamp(0.1, 400.0);
}
}
/// For storing world cursor position
#[derive(Default, Resource, Debug)]
struct CursorWorldPosition(Vec2);
/// This system updates the cursor position in the world.
fn global_cursor(
mut world_coords: ResMut,
q_window: Query<&Window, With>,
q_camera: Query<(&Camera, &GlobalTransform), With>,
) {
let (camera, camera_transform) = q_camera.single();
let window = q_window.single();
if let Some(world_position) = window
.cursor_position()
.and_then(|cursor| camera.viewport_to_world(camera_transform, cursor))
.map(|ray| ray.origin.truncate())
{
// this doesn't print anything when hovering a file over a window
log::info!("Cursor world position updated! {:?}", world_coords);
world_coords.0 = world_position;
}
}
fn file_drop(
mut evr_dnd: EventReader,
mut commands: Commands,
asset_server: Res,
world_cursor: Res, // world_cursor is not always updated when file is dropped
) {
for ev in evr_dnd.read() {
match ev {
FileDragAndDrop::DroppedFile { window, path_buf } => {
log::info!("Dropped file: {:?} at {:?}", path_buf, window);
let texture_handle = asset_server.load(path_buf.to_str().unwrap().to_string());
commands.spawn(
SpriteBundle {
texture: texture_handle,
transform: Transform::from_xyz(world_cursor.0.x, world_cursor.0.y, 0.0),
..default()
});
}
FileDragAndDrop::HoveredFile {
window: _,
path_buf: _,
} => {
// On wayland this sometimes prints multiple times for one drop
log::info!("Hovered file");
}
FileDragAndDrop::HoveredFileCanceled { window: _ } => {
log::info!("File canceled!");
}
}
}
}
```
## What Went Wrong
### Main Issue: Cursor World Position is Unreliable
Images are supposed to spawn at the current cursor position in world coordinates, as set by the `global_cursor` system. However, on Wayland, these coordinates are not always updated before a file drop occurs. This inconsistency leads to images spawning at the cursor's position when it previously exited the window. The issue doesn't happen every time but occurs frequently enough to be annoying — around 30-80% of the time.
> Testing on Xorg shows it works flawlessly.
### Secondary Issue: Multiple File Hover Events on Wayland
File hover events trigger multiple times for a single drop. Although not critical, this behavior is unusual.
> On Xorg, each drop results in a single event, which is expected behavior.
Contributor guide
Research direction
Start with the MVP's main.rs, especially global_cursor and file_drop, and reproduce the behavior on Wayland and Xorg using the linked example. Trace how FileDragAndDrop and cursor-position events are delivered when a file is dragged over and dropped. Done means dropped images consistently use the current cursor position and hover events do not repeat unexpectedly on Wayland.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- desktop, operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100