Skip to content
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

Window intermittently crashes on Windows 10 & 11 on startup if setting a Window Icon using Winit #4010

Closed
samwatts98 opened this issue Feb 21, 2022 · 3 comments
Labels
C-Bug An unexpected or incorrect behavior O-Windows Specific to the Windows desktop operating system P-Crash A sudden unexpected crash

Comments

@samwatts98
Copy link

samwatts98 commented Feb 21, 2022

Bevy version

Bevy 0.6.1
Winit 0.26.1

Operating system & version

Tested on Windows 10 and 11

What you did

main.rs

use std::io::Cursor;

use bevy::{prelude::App, DefaultPlugins};
use image::{io::Reader as ImageReader, ImageFormat};
use winit::window::Icon;

use bevy::{prelude::Res, window::WindowId, winit::WinitWindows};

fn configure_icon(windows: Res<WinitWindows>) {
    let window = windows.get_window(WindowId::primary()).unwrap();

    let img_bytes = include_bytes!("..\\assets\\favicon.png");
    let mut img_reader = ImageReader::new(Cursor::new(img_bytes));
    img_reader.set_format(ImageFormat::Png);

    if let Ok(image) = img_reader.decode() {
        let image_data = image.into_rgba8();
        let (width, height) = image_data.dimensions();
        let rgba = image_data.into_raw();
        let icon =
            Icon::from_rgba(rgba, width, height).expect("Error creating icon from App Icon data");
        window.set_window_icon(Some(icon));
    }
}

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_startup_system(configure_icon)
        .run();
}

What you expected to happen

I expect the Window Icon at the top left hand corner of the application, and the window in the Task Bar to display the 16x16px png file located in the file assets/favicon.png. This should work 100% of the time.

What actually happened

This seems to work 50% of the time. Other times, the window opens with a blank white display, the default Windows window icon is shown, and the application is unresponsive. By clicking on the screen, Windows reports the application as (Not Responding).

The application never progresses after the call to window.set_window_icon(Some(icon)) .

Additional information

This isn't an issue with winit 0.26.1, as with the below code example just using Winit the issue doesn't occur, it works 100% of the time.


use std::io::Cursor;

use image::{io::Reader as ImageReader, ImageFormat};
use winit::{
    event::{Event, WindowEvent},
    event_loop::{ControlFlow, EventLoop},
    window::{Icon, WindowBuilder},
};

fn main() {
    let event_loop = EventLoop::new();
    let window = WindowBuilder::new().build(&event_loop).unwrap();

    let img_bytes = include_bytes!("..\\assets\\favicon.png");
    let mut img_reader = ImageReader::new(Cursor::new(img_bytes));
    img_reader.set_format(ImageFormat::Png);

    if let Ok(image) = img_reader.decode() {
        let image_data = image.into_rgba8();
        let (width, height) = image_data.dimensions();
        let rgba = image_data.into_raw();
        let icon =
            Icon::from_rgba(rgba, width, height).expect("Error creating icon from App Icon data");
        window.set_window_icon(Some(icon));
    }

    event_loop.run(move |event, _, control_flow| {
        *control_flow = ControlFlow::Wait;

        match event {
            Event::WindowEvent {
                event: WindowEvent::CloseRequested,
                window_id,
            } if window_id == window.id() => *control_flow = ControlFlow::Exit,
            _ => (),
        }
    });
}

Also worth noting, when doing the below via Bevy, as soon as the window is rendered the icon is immediately there. However, when using the Bevy example above, the default Windows application Icon flashes up for a second or so, before the rest of the game loads - but that could well just be overhead of the engine.

I'm aware this is the workaround, and talks / progress around setting the Window Icon via Bevy is being discussed under #2268 - however currently this workaround doesn't seem to be an option either.

Cheers! 😄

@samwatts98 samwatts98 added C-Bug An unexpected or incorrect behavior S-Needs-Triage This issue needs to be labelled labels Feb 21, 2022
@mockersf mockersf added P-Crash A sudden unexpected crash O-Windows Specific to the Windows desktop operating system and removed S-Needs-Triage This issue needs to be labelled labels Feb 21, 2022
@aevyrie
Copy link
Member

aevyrie commented Feb 23, 2022

This is caused by calling set_window_icon() outside of the main thread. You will need to ensure the configure_icon system is run on the main thread.

Solutions:

  1. Change Res<WinitWindows> to NonSend<WinitWindows>
    This works because systems with NonSend resources cannot be scheduled on another thread.
  2. Change .add_startup_system(configure_icon) to .add_startup_system(configure_icon.exclusive_system())
    This works because exclusive systems are scheduled on the main thread.

@samwatts98
Copy link
Author

@aevyrie Excellent, this works a charm! Thanks very much for your explanation 😄

I'll open a PR to get this added to this page of the unofficial Cookbook: https://bevy-cheatbook.github.io/cookbook/window-icon.html

@alice-i-cecile
Copy link
Member

Reopening because this is a problem we should fix directly :)

@bors bors bot closed this as completed in a2d49f4 Feb 24, 2022
kurtkuehnert pushed a commit to kurtkuehnert/bevy that referenced this issue Mar 6, 2022
# Objective

- Fixes bevyengine#4010, as well as any similar issues in this class.
- Winit functions used outside of the main thread can cause the application to unexpectedly hang.

## Solution

- Make the `WinitWindows` resource `!Send`.
- This ensures that any systems that use `WinitWindows` must either be exclusive (run on the main thread), or the resource is explicitly marked with the `NonSend` parameter in user systems.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-Bug An unexpected or incorrect behavior O-Windows Specific to the Windows desktop operating system P-Crash A sudden unexpected crash
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants