Skip to content

WakeUp doesn't unfreeze systems when dragging #17488

@chlobes

Description

@chlobes

Bevy version

0.15.1

Relevant system information

Windows 11

`AdapterInfo { name: "NVIDIA GeForce RTX 2070", vendor: 4318, device: 7938, device_type: DiscreteGpu, backend: Vulkan }`

What you did

We stuff the EventLoopProxy into a static, so that we can wake the app remotely from a seperate thread

What went wrong

The systems do not wake under some conditions, such as dragging the window, or winit's drag_resize_window.

Additional information

Appears to work ok on Linux.
I am not entirely sure if this is a bevy issue, a winit issue, or a Win11 issue.
Originally reproduced for 14.2, updated to 15.1 and it is still possible to reproduce.

Minimal Repro

/*
[dependencies]
bevy = "0.15.1"
bevy_winit = "0.15.1"
once_cell = "1.19.0"
*/

use std::sync::{Mutex, OnceLock};
use std::time::{Duration, Instant};

use bevy::{prelude::*, sprite::Sprite, window::RequestRedraw};
use bevy_winit::{EventLoopProxy, EventLoopProxyWrapper, UpdateMode, WakeUp, WinitSettings};
use once_cell::sync::Lazy;

static START: Lazy<Instant> = Lazy::new(Instant::now);

fn redraw(
    mut redraw: EventWriter<RequestRedraw>,
) {
    println!("redrawing {}", START.elapsed().subsec_millis());
    redraw.send(RequestRedraw);
}

//bobbing square so that we can see if the window is still responsive
#[derive(Component)]
struct Square;

fn spawn_square(mut commands: Commands) {
    // Spawn camera
    commands.spawn(Camera2d);
    commands.spawn((
        Sprite {
            color: Color::WHITE,
            custom_size: Some(Vec2::new(100.0, 100.0)),
            ..Default::default()
        },
        Square,
    ));
}

fn bob_square(mut query: Query<&mut Transform, With<Square>>) {
    if let Ok(mut transform) = query.get_single_mut() {
        let elapsed = START.elapsed().as_secs_f32();
        transform.translation.y = (elapsed * 1.5).sin() * 50.0;
    }
}

fn setup_wake_thread() {
    std::thread::spawn(move || {
        loop {
            EVENT_LOOP_PROXY.wake_event_loop();
            println!("waking {}", START.elapsed().subsec_millis());
            std::thread::sleep(Duration::from_millis(50));
        }
    });
}

pub struct AppWinitPlugin;
impl Plugin for AppWinitPlugin {
    fn build(&self, app: &mut App) {
        app.insert_resource(WinitSettings {
            focused_mode: UpdateMode::reactive(Duration::from_secs(1)),
            unfocused_mode: UpdateMode::reactive_low_power(Duration::from_secs(5)),
        })
        .add_systems(Startup, EventLoopWaker::init);
    }
}

pub static EVENT_LOOP_PROXY: EventLoopWaker = EventLoopWaker(OnceLock::new());
pub struct EventLoopWaker(OnceLock<Mutex<EventLoopProxy<WakeUp>>>);

impl EventLoopWaker {
    pub fn wake_event_loop(&self) {
        if self
            .0
            .get()
            .and_then(|mutex| mutex.lock().ok())
            .and_then(|proxy| proxy.send_event(WakeUp).ok())
            .is_none()
        {
            println!("Failed to wake the event loop.")
        }
    }

    fn init(proxy: Res<EventLoopProxyWrapper<WakeUp>>) {
        let proxy: &EventLoopProxy<WakeUp> = &proxy;
        EVENT_LOOP_PROXY
            .0
            .get_or_init(|| std::sync::Mutex::new(proxy.clone()));
    }
}

fn main() {
    App::new()
        .add_plugins((
            DefaultPlugins,
            AppWinitPlugin,
        ))
        .add_systems(Startup, (spawn_square, setup_wake_thread))
        .add_systems(Update, (redraw, bob_square))
        .run();
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-WindowingPlatform-agnostic interface layer to run your app inC-BugAn unexpected or incorrect behaviorD-StraightforwardSimple bug fixes and API improvements, docs, test and examplesO-WindowsSpecific to the Windows desktop operating systemP-RegressionFunctionality that used to work but no longer does. Add a test for this!S-Needs-InvestigationThis issue requires detective work to figure out what's going wrong

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions