bevyengine / bevyengine/bevy

`FileDragAndDrop` events on wayland are WEIRD

Open
#16,101 0 comments 0 reactions 0 assignees View on GitHub
A-Input A-Windowing C-Bug O-Linux S-Needs-Design
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.