dip_desktop 0.2.0

Write cross-platform application with React-like declarative UI framework and scalable ECS architecture all in Rust.
Documentation
use crate::{converter, window::DioxusWindows};
use bevy::{
    ecs::{
        event::EventWriter,
        system::{NonSendMut, ResMut},
    },
    log::{error, warn},
    math::{UVec2, Vec2},
    window::{WindowClosed, WindowCommand, WindowMode, WindowScaleFactorChanged, Windows},
};
use wry::application::{
    dpi::{LogicalPosition, LogicalSize, PhysicalPosition},
    window::Fullscreen,
};

pub fn change_window(
    mut dioxus_windows: NonSendMut<DioxusWindows>,
    mut windows: ResMut<Windows>,
    mut window_dpi_changed_events: EventWriter<WindowScaleFactorChanged>,
    mut window_close_events: EventWriter<WindowClosed>,
) {
    let mut removed_windows = vec![];
    for bevy_window in windows.iter_mut() {
        let id = bevy_window.id();
        let window = dioxus_windows.get_tao_window(id).unwrap();

        for command in bevy_window.drain_commands() {
            match command {
                WindowCommand::SetWindowMode {
                    mode,
                    resolution: UVec2 { x, y },
                } => match mode {
                    WindowMode::BorderlessFullscreen => {
                        window.set_fullscreen(Some(Fullscreen::Borderless(None)));
                    }
                    WindowMode::Fullscreen => {
                        window.set_fullscreen(Some(Fullscreen::Exclusive(
                            DioxusWindows::get_best_videomode(&window.current_monitor().unwrap()),
                        )));
                    }
                    WindowMode::SizedFullscreen => window.set_fullscreen(Some(
                        Fullscreen::Exclusive(DioxusWindows::get_fitting_videomode(
                            &window.current_monitor().unwrap(),
                            x,
                            y,
                        )),
                    )),
                    WindowMode::Windowed => window.set_fullscreen(None),
                },
                WindowCommand::SetTitle { title } => {
                    window.set_title(&title);
                }
                WindowCommand::SetScaleFactor { scale_factor } => {
                    window_dpi_changed_events.send(WindowScaleFactorChanged { id, scale_factor });
                }
                WindowCommand::SetResolution {
                    logical_resolution:
                        Vec2 {
                            x: width,
                            y: height,
                        },
                    scale_factor,
                } => {
                    window.set_inner_size(
                        LogicalSize::new(width, height).to_physical::<f64>(scale_factor),
                    );
                }
                WindowCommand::SetPresentMode { .. } => (),
                WindowCommand::SetResizable { resizable } => {
                    window.set_resizable(resizable);
                }
                WindowCommand::SetDecorations { decorations } => {
                    window.set_decorations(decorations);
                }
                WindowCommand::SetCursorIcon { icon } => {
                    window.set_cursor_icon(converter::convert_cursor_icon(icon));
                }
                WindowCommand::SetCursorLockMode { locked } => {
                    window
                        .set_cursor_grab(locked)
                        .unwrap_or_else(|e| error!("Unable to un/grab cursor: {}", e));
                }
                WindowCommand::SetCursorVisibility { visible } => {
                    window.set_cursor_visible(visible);
                }
                WindowCommand::SetCursorPosition { position } => {
                    let inner_size = window.inner_size().to_logical::<f32>(window.scale_factor());
                    window
                        .set_cursor_position(LogicalPosition::new(
                            position.x,
                            inner_size.height - position.y,
                        ))
                        .unwrap_or_else(|e| error!("Unable to set cursor position: {}", e));
                }
                WindowCommand::SetMaximized { maximized } => {
                    window.set_maximized(maximized);
                }
                WindowCommand::SetMinimized { minimized } => {
                    window.set_minimized(minimized);
                }
                WindowCommand::SetPosition { position } => {
                    window.set_outer_position(PhysicalPosition {
                        x: position[0],
                        y: position[1],
                    });
                }
                WindowCommand::Center(monitor_selection) => {
                    use bevy::window::MonitorSelection::*;
                    let maybe_monitor = match monitor_selection {
                        Current => window.current_monitor(),
                        Primary => window.primary_monitor(),
                        Number(n) => window.available_monitors().nth(n),
                    };

                    if let Some(monitor) = maybe_monitor {
                        let screen_size = monitor.size();

                        let window_size = window.outer_size();

                        window.set_outer_position(PhysicalPosition {
                            x: screen_size.width.saturating_sub(window_size.width) as f64 / 2.
                                + monitor.position().x as f64,
                            y: screen_size.height.saturating_sub(window_size.height) as f64 / 2.
                                + monitor.position().y as f64,
                        });
                    } else {
                        warn!("Couldn't get monitor selected with: {monitor_selection:?}");
                    }
                }
                WindowCommand::SetResizeConstraints { resize_constraints } => {
                    let constraints = resize_constraints.check_constraints();
                    let min_inner_size = LogicalSize {
                        width: constraints.min_width,
                        height: constraints.min_height,
                    };
                    let max_inner_size = LogicalSize {
                        width: constraints.max_width,
                        height: constraints.max_height,
                    };

                    window.set_min_inner_size(Some(min_inner_size));
                    if constraints.max_width.is_finite() && constraints.max_height.is_finite() {
                        window.set_max_inner_size(Some(max_inner_size));
                    }
                }
                WindowCommand::Close => {
                    removed_windows.push(id);
                    break;
                }
            }
        }
    }

    if !removed_windows.is_empty() {
        for id in removed_windows {
            let _ = dioxus_windows.remove(id);
            windows.remove(id);
            window_close_events.send(WindowClosed { id });
        }
    }
}