1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//! Plugins.

use crate::prelude::*;

/// Persistent windows plugin.
///
/// Responsible for restoring window states before the application is run
/// and synchronizing windows with their states during the run.
///
/// # Panics
///
/// - Panics if it's added to the [App]
/// before [WinitPlugin](bevy::winit::WinitPlugin),
/// which is in the [DefaultPlugins].
pub struct PersistentWindowsPlugin;

impl Plugin for PersistentWindowsPlugin {
    fn build(&self, app: &mut App) {
        let event_loop = app
            .world
            .get_non_send_resource::<EventLoop<RequestRedraw>>()
            .expect("persistent windows plugin is added before winit plugin");

        match utils::available_monitors(event_loop) {
            Some(available_monitors) => {
                let best_monitor = utils::best_monitor(&available_monitors);

                let mut persistent_windows =
                    app.world.query::<(&mut Window, &mut Persistent<WindowState>)>();

                for (mut window, mut state) in persistent_windows.iter_mut(&mut app.world) {
                    utils::adjust_to_monitor(
                        &available_monitors,
                        best_monitor,
                        &mut window,
                        &mut state,
                    );
                }
            },
            None => {
                log::error!("unable to persist windows as no monitors are available");
            },
        }

        let event_loop = app.world.remove_non_send_resource::<EventLoop<RequestRedraw>>().unwrap();

        let mut create_window = SystemState::<CreateWindowParams>::from_world(&mut app.world);
        create_windows(event_loop.deref(), create_window.get_mut(&mut app.world));
        create_window.apply(&mut app.world);

        app.insert_non_send_resource(event_loop);

        app.add_systems(
            PreUpdate,
            (
                on_persistent_window_moved,
                on_persistent_window_resized,
                on_persistent_window_scale_factor_changed,
            ),
        );
        app.add_systems(PostUpdate, on_persistent_window_state_changed);
    }
}