winit 0.14.0

Cross-platform window creation library.
Documentation
// Heads up: you need to compile this example with `--features icon_loading`.
// `Icon::from_path` won't be available otherwise, though for your own applications, you could use
// `Icon::from_rgba` if you don't want to depend on the `image` crate.

extern crate winit;
#[cfg(feature = "icon_loading")]
extern crate image;

use winit::Icon;

#[cfg(feature = "icon_loading")]
fn main() {
    // You'll have to choose an icon size at your own discretion. On X11, the desired size varies
    // by WM, and on Windows, you still have to account for screen scaling. Here we use 32px,
    // since it seems to work well enough in most cases. Be careful about going too high, or
    // you'll be bitten by the low-quality downscaling built into the WM.
    let path = concat!(env!("CARGO_MANIFEST_DIR"), "/examples/icon.png");
    // While `Icon::from_path` is the most straightforward, you have a few other options. If you
    // want to use the `include_bytes` macro, then pass the result to `Icon::from_bytes`. See the
    // docs for the full list of options (you'll have to generate the docs with the `icon_loading`
    // feature enabled).
    let icon = Icon::from_path(path).expect("Failed to open icon");

    let mut events_loop = winit::EventsLoop::new();

    let window = winit::WindowBuilder::new()
        .with_title("An iconic window!")
        // At present, this only does anything on Windows and X11, so if you want to save load
        // time, you can put icon loading behind a function that returns `None` on other platforms.
        .with_window_icon(Some(icon))
        .build(&events_loop)
        .unwrap();

    events_loop.run_forever(|event| {
        if let winit::Event::WindowEvent { event, .. } = event {
            use winit::WindowEvent::*;
            match event {
                CloseRequested => return winit::ControlFlow::Break,
                DroppedFile(path) => {
                    use image::GenericImage;

                    let icon_image = image::open(path).expect("Failed to open window icon");

                    let (width, height) = icon_image.dimensions();
                    const DESIRED_SIZE: u32 = 32;
                    let (new_width, new_height) = if width == height {
                        (DESIRED_SIZE, DESIRED_SIZE)
                    } else {
                        // Note that this will never divide by zero, due to the previous condition.
                        let aspect_adjustment = DESIRED_SIZE as f64
                            / std::cmp::max(width, height) as f64;
                        (
                            (width as f64 * aspect_adjustment) as u32,
                            (height as f64 * aspect_adjustment) as u32,
                        )
                    };

                    // By scaling the icon ourselves, we get higher-quality filtering and save
                    // some memory.
                    let icon = image::imageops::resize(
                        &icon_image,
                        new_width,
                        new_height,
                        image::FilterType::Lanczos3,
                    );

                    let (offset_x, offset_y) = (
                        (DESIRED_SIZE - new_width) / 2,
                        (DESIRED_SIZE - new_height) / 2,
                    );

                    let mut canvas = image::ImageBuffer::new(DESIRED_SIZE, DESIRED_SIZE);
                    image::imageops::replace(
                        &mut canvas,
                        &icon,
                        offset_x,
                        offset_y,
                    );

                    window.set_window_icon(Some(canvas.into()));
                },
                _ => (),
            }
        }
        winit::ControlFlow::Continue
    });
}

#[cfg(not(feature = "icon_loading"))]
fn main() {
    print!(
r#"This example requires the `icon_loading` feature:
    cargo run --example window_icon --features icon_loading
"#);
}