diff options
Diffstat (limited to '')
| -rw-r--r-- | winit/src/application.rs | 4 | ||||
| -rw-r--r-- | winit/src/multi_window.rs | 148 | ||||
| -rw-r--r-- | winit/src/multi_window/windows.rs | 26 | ||||
| -rw-r--r-- | winit/src/settings.rs | 12 | 
4 files changed, 120 insertions, 70 deletions
diff --git a/winit/src/application.rs b/winit/src/application.rs index 5c45bbda..cffcb884 100644 --- a/winit/src/application.rs +++ b/winit/src/application.rs @@ -136,6 +136,8 @@ where      let target = settings.window.platform_specific.target.clone();      let should_be_visible = settings.window.visible; +    let exit_on_close_request = settings.window.exit_on_close_request; +      let builder = settings::window_builder(          settings.window,          &application.title(), @@ -197,7 +199,7 @@ where          init_command,          window,          should_be_visible, -        settings.exit_on_close_request, +        exit_on_close_request,      ));      let mut context = task::Context::from_waker(task::noop_waker_ref()); diff --git a/winit/src/multi_window.rs b/winit/src/multi_window.rs index e6f440bc..b67c0a48 100644 --- a/winit/src/multi_window.rs +++ b/winit/src/multi_window.rs @@ -46,7 +46,14 @@ pub enum Event<Message> {      /// An internal event for closing a window.      CloseWindow(window::Id),      /// An internal event for when the window has finished being created. -    WindowCreated(window::Id, winit::window::Window), +    WindowCreated { +        /// The internal ID of the window. +        id: window::Id, +        /// The raw window. +        window: winit::window::Window, +        /// Whether or not the window should close when a user requests it does. +        exit_on_close_request: bool, +    },  }  #[allow(unsafe_code)] @@ -161,6 +168,8 @@ where      };      let should_main_be_visible = settings.window.visible; +    let exit_on_close_request = settings.window.exit_on_close_request; +      let builder = window_builder(          settings.window,          &application.title(window::Id::MAIN), @@ -208,8 +217,13 @@ where      let (mut compositor, renderer) =          C::new(compositor_settings, Some(&main_window))?; -    let windows = -        Windows::new(&application, &mut compositor, renderer, main_window); +    let windows = Windows::new( +        &application, +        &mut compositor, +        renderer, +        main_window, +        exit_on_close_request, +    );      let (mut event_sender, event_receiver) = mpsc::unbounded();      let (control_sender, mut control_receiver) = mpsc::unbounded(); @@ -225,7 +239,6 @@ where          init_command,          windows,          should_main_be_visible, -        settings.exit_on_close_request,      ));      let mut context = task::Context::from_waker(task::noop_waker_ref()); @@ -255,14 +268,18 @@ where                  title,                  monitor,              }) => { +                let exit_on_close_request = settings.exit_on_close_request; +                  let window =                      settings::window_builder(settings, &title, monitor, None)                          .build(window_target)                          .expect("Failed to build window"); -                Some(winit::event::Event::UserEvent(Event::WindowCreated( -                    id, window, -                ))) +                Some(winit::event::Event::UserEvent(Event::WindowCreated { +                    id, +                    window, +                    exit_on_close_request, +                }))              }              _ => event.to_static(),          }; @@ -299,7 +316,6 @@ async fn run_instance<A, E, C>(      init_command: Command<A::Message>,      mut windows: Windows<A, C>,      should_main_window_be_visible: bool, -    exit_on_main_closed: bool,  ) where      A: Application + 'static,      E: Executor + 'static, @@ -548,11 +564,20 @@ async fn run_instance<A, E, C>(                  Event::Application(message) => {                      messages.push(message);                  } -                Event::WindowCreated(id, window) => { +                Event::WindowCreated { +                    id, +                    window, +                    exit_on_close_request, +                } => {                      let bounds = logical_bounds_of(&window); -                    let (inner_size, i) = -                        windows.add(&application, &mut compositor, id, window); +                    let (inner_size, i) = windows.add( +                        &application, +                        &mut compositor, +                        id, +                        window, +                        exit_on_close_request, +                    );                      user_interfaces.push(build_user_interface(                          &application, @@ -680,50 +705,61 @@ async fn run_instance<A, E, C>(                  event: window_event,                  window_id,              } => { -                let window_deleted = windows -                    .pending_destroy -                    .iter() -                    .any(|(_, w_id)| window_id == *w_id); +                let window_index = +                    windows.raw.iter().position(|w| w.id() == window_id); + +                match window_index { +                    Some(i) => { +                        let id = windows.ids[i]; +                        let raw = &windows.raw[i]; +                        let exit_on_close_request = +                            windows.exit_on_close_requested[i]; + +                        if matches!( +                            window_event, +                            winit::event::WindowEvent::CloseRequested +                        ) && exit_on_close_request +                        { +                            let i = windows.delete(id); +                            let _ = user_interfaces.remove(i); +                            let _ = ui_caches.remove(i); + +                            if windows.is_empty() { +                                break 'main; +                            } +                        } else { +                            let state = &mut windows.states[i]; +                            state.update(raw, &window_event, &mut debug); -                if matches!(window_event, winit::event::WindowEvent::Destroyed) -                { -                    // This is the only special case, since in order trigger the Destroyed event the -                    // window reference from winit must be dropped, but we still want to inform the -                    // user that the window was destroyed so they can clean up any specific window -                    // code for this window -                    let id = windows.get_pending_destroy(window_id); - -                    events.push(( -                        None, -                        core::Event::Window(id, window::Event::Destroyed), -                    )); -                } else if !window_deleted { -                    let i = windows.index_from_raw(window_id); -                    let id = windows.ids[i]; -                    let raw = &windows.raw[i]; -                    let state = &mut windows.states[i]; - -                    // first check if we need to just break the entire application -                    // e.g. a user does a force quit on MacOS, or if a user has set "exit on main closed" -                    // as an option in window settings and wants to close the main window -                    if requests_exit( -                        i, -                        exit_on_main_closed, -                        &window_event, -                        state.modifiers(), -                    ) { -                        break 'main; +                            if let Some(event) = conversion::window_event( +                                id, +                                &window_event, +                                state.scale_factor(), +                                state.modifiers(), +                            ) { +                                events.push((Some(id), event)); +                            } +                        }                      } - -                    state.update(raw, &window_event, &mut debug); - -                    if let Some(event) = conversion::window_event( -                        id, -                        &window_event, -                        state.scale_factor(), -                        state.modifiers(), -                    ) { -                        events.push((Some(id), event)); +                    None => { +                        // This is the only special case, since in order to trigger the Destroyed event the +                        // window reference from winit must be dropped, but we still want to inform the +                        // user that the window was destroyed so they can clean up any specific window +                        // code for this window +                        if matches!( +                            window_event, +                            winit::event::WindowEvent::Destroyed +                        ) { +                            let id = windows.get_pending_destroy(window_id); + +                            events.push(( +                                None, +                                core::Event::Window( +                                    id, +                                    window::Event::Destroyed, +                                ), +                            )); +                        }                      }                  }              } @@ -1068,17 +1104,13 @@ where  /// Returns true if the provided event should cause an [`Application`] to  /// exit. -pub fn requests_exit( -    window: usize, -    exit_on_main_closed: bool, +pub fn user_force_quit(      event: &winit::event::WindowEvent<'_>,      _modifiers: winit::event::ModifiersState,  ) -> bool {      use winit::event::WindowEvent; -    //TODO alt f4..?      match event { -        WindowEvent::CloseRequested => exit_on_main_closed && window == 0,          #[cfg(target_os = "macos")]          WindowEvent::KeyboardInput {              input: diff --git a/winit/src/multi_window/windows.rs b/winit/src/multi_window/windows.rs index 7b63defa..1f606b31 100644 --- a/winit/src/multi_window/windows.rs +++ b/winit/src/multi_window/windows.rs @@ -14,6 +14,7 @@ where      pub raw: Vec<winit::window::Window>,      pub states: Vec<State<A>>,      pub viewport_versions: Vec<usize>, +    pub exit_on_close_requested: Vec<bool>,      pub surfaces: Vec<C::Surface>,      pub renderers: Vec<A::Renderer>,      pub pending_destroy: Vec<(window::Id, winit::window::WindowId)>, @@ -52,6 +53,7 @@ where          compositor: &mut C,          renderer: A::Renderer,          main: winit::window::Window, +        exit_on_close_requested: bool,      ) -> Self {          let state = State::new(application, window::Id::MAIN, &main);          let viewport_version = state.viewport_version(); @@ -67,6 +69,7 @@ where              raw: vec![main],              states: vec![state],              viewport_versions: vec![viewport_version], +            exit_on_close_requested: vec![exit_on_close_requested],              surfaces: vec![surface],              renderers: vec![renderer],              pending_destroy: vec![], @@ -81,6 +84,7 @@ where          compositor: &mut C,          id: window::Id,          window: winit::window::Window, +        exit_on_close_requested: bool,      ) -> (Size, usize) {          let state = State::new(application, id, &window);          let window_size = state.logical_size(); @@ -96,6 +100,7 @@ where          self.ids.push(id);          self.raw.push(window);          self.states.push(state); +        self.exit_on_close_requested.push(exit_on_close_requested);          self.viewport_versions.push(viewport_version);          self.surfaces.push(surface);          self.renderers.push(renderer); @@ -145,6 +150,7 @@ where          let id = self.ids.remove(i);          let window = self.raw.remove(i);          let _ = self.states.remove(i); +        let _ = self.exit_on_close_requested.remove(i);          let _ = self.viewport_versions.remove(i);          let _ = self.surfaces.remove(i); @@ -167,4 +173,24 @@ where          let (id, _) = self.pending_destroy.remove(i);          id      } + +    /// Returns the windows that need to be requested to closed, and also the windows that can be +    /// closed immediately. +    pub fn partition_close_requests(&self) -> (Vec<window::Id>, Vec<window::Id>) { +        self.exit_on_close_requested.iter().enumerate().fold( +            (vec![], vec![]), +            |(mut close_immediately, mut needs_request_closed), +             (i, close)| { +                let id = self.ids[i]; + +                if *close { +                    close_immediately.push(id); +                } else { +                    needs_request_closed.push(id); +                } + +                (close_immediately, needs_request_closed) +            }, +        ) +    }  } diff --git a/winit/src/settings.rs b/winit/src/settings.rs index 2b846fbd..c0b3b047 100644 --- a/winit/src/settings.rs +++ b/winit/src/settings.rs @@ -1,6 +1,6 @@  //! Configure your application. -use crate::conversion;  use crate::core::window; +use crate::conversion;  use winit::monitor::MonitorHandle;  use winit::window::WindowBuilder; @@ -21,16 +21,6 @@ pub struct Settings<Flags> {      ///      /// [`Application`]: crate::Application      pub flags: Flags, - -    /// Whether the [`Application`] should exit when the user requests the -    /// window to close (e.g. the user presses the close button). -    /// -    /// With a [`multi_window::Application`] this will instead be used to determine whether the -    /// application should exit when the "main"" window is closed, i.e. the first window created on -    /// app launch. -    /// -    /// [`Application`]: crate::Application -    pub exit_on_close_request: bool,  }  /// Converts the window settings into a `WindowBuilder` from `winit`.  | 
