diff options
Diffstat (limited to '')
| -rw-r--r-- | core/src/window/settings/macos.rs (renamed from winit/src/settings/macos.rs) | 0 | ||||
| -rw-r--r-- | core/src/window/settings/other.rs (renamed from winit/src/settings/other.rs) | 0 | ||||
| -rw-r--r-- | core/src/window/settings/wasm.rs (renamed from winit/src/settings/wasm.rs) | 0 | ||||
| -rw-r--r-- | core/src/window/settings/windows.rs (renamed from winit/src/settings/windows.rs) | 0 | ||||
| -rw-r--r-- | src/window/icon.rs (renamed from winit/src/icon.rs) | 0 | ||||
| -rw-r--r-- | winit/src/application.rs | 86 | ||||
| -rw-r--r-- | winit/src/conversion.rs | 9 | ||||
| -rw-r--r-- | winit/src/lib.rs | 8 | ||||
| -rw-r--r-- | winit/src/multi_window.rs | 1078 | ||||
| -rw-r--r-- | winit/src/multi_window/state.rs | 96 | ||||
| -rw-r--r-- | winit/src/multi_window/windows.rs | 170 | ||||
| -rw-r--r-- | winit/src/profiler.rs | 101 | ||||
| -rw-r--r-- | winit/src/settings.rs | 246 | ||||
| -rw-r--r-- | winit/src/window.rs | 0 | 
14 files changed, 856 insertions, 938 deletions
diff --git a/winit/src/settings/macos.rs b/core/src/window/settings/macos.rs index f86e63ad..f86e63ad 100644 --- a/winit/src/settings/macos.rs +++ b/core/src/window/settings/macos.rs diff --git a/winit/src/settings/other.rs b/core/src/window/settings/other.rs index b1103f62..b1103f62 100644 --- a/winit/src/settings/other.rs +++ b/core/src/window/settings/other.rs diff --git a/winit/src/settings/wasm.rs b/core/src/window/settings/wasm.rs index 8e0f1bbc..8e0f1bbc 100644 --- a/winit/src/settings/wasm.rs +++ b/core/src/window/settings/wasm.rs diff --git a/winit/src/settings/windows.rs b/core/src/window/settings/windows.rs index 45d753bd..45d753bd 100644 --- a/winit/src/settings/windows.rs +++ b/core/src/window/settings/windows.rs diff --git a/winit/src/icon.rs b/src/window/icon.rs index 0fe010ca..0fe010ca 100644 --- a/winit/src/icon.rs +++ b/src/window/icon.rs diff --git a/winit/src/application.rs b/winit/src/application.rs index ab7b2495..5c45bbda 100644 --- a/winit/src/application.rs +++ b/winit/src/application.rs @@ -18,6 +18,7 @@ use crate::runtime::clipboard;  use crate::runtime::program::Program;  use crate::runtime::user_interface::{self, UserInterface};  use crate::runtime::{Command, Debug}; +use crate::settings;  use crate::style::application::{Appearance, StyleSheet};  use crate::{Clipboard, Error, Proxy, Settings}; @@ -25,11 +26,6 @@ use futures::channel::mpsc;  use std::mem::ManuallyDrop; -#[cfg(feature = "trace")] -pub use crate::Profiler; -#[cfg(feature = "trace")] -use tracing::{info_span, instrument::Instrument}; -  /// An interactive, native cross-platform application.  ///  /// This trait is the main entrypoint of Iced. Once implemented, you can run @@ -117,15 +113,9 @@ where      use futures::Future;      use winit::event_loop::EventLoopBuilder; -    #[cfg(feature = "trace")] -    let _guard = Profiler::init(); -      let mut debug = Debug::new();      debug.startup_started(); -    #[cfg(feature = "trace")] -    let _ = info_span!("Application", "RUN").entered(); -      let event_loop = EventLoopBuilder::with_user_event().build();      let proxy = event_loop.create_proxy(); @@ -146,14 +136,13 @@ where      let target = settings.window.platform_specific.target.clone();      let should_be_visible = settings.window.visible; -    let builder = settings -        .window -        .into_builder( -            &application.title(), -            event_loop.primary_monitor(), -            settings.id, -        ) -        .with_visible(false); +    let builder = settings::window_builder( +        settings.window, +        &application.title(), +        event_loop.primary_monitor(), +        settings.id, +    ) +    .with_visible(false);      log::debug!("Window builder: {:#?}", builder); @@ -196,28 +185,20 @@ where      let (mut event_sender, event_receiver) = mpsc::unbounded();      let (control_sender, mut control_receiver) = mpsc::unbounded(); -    let mut instance = Box::pin({ -        let run_instance = run_instance::<A, E, C>( -            application, -            compositor, -            renderer, -            runtime, -            proxy, -            debug, -            event_receiver, -            control_sender, -            init_command, -            window, -            should_be_visible, -            settings.exit_on_close_request, -        ); - -        #[cfg(feature = "trace")] -        let run_instance = -            run_instance.instrument(info_span!("Application", "LOOP")); - -        run_instance -    }); +    let mut instance = Box::pin(run_instance::<A, E, C>( +        application, +        compositor, +        renderer, +        runtime, +        proxy, +        debug, +        event_receiver, +        control_sender, +        init_command, +        window, +        should_be_visible, +        settings.exit_on_close_request, +    ));      let mut context = task::Context::from_waker(task::noop_waker_ref()); @@ -480,9 +461,6 @@ async fn run_instance<A, E, C>(                  messages.push(message);              }              event::Event::RedrawRequested(_) => { -                #[cfg(feature = "trace")] -                let _ = info_span!("Application", "FRAME").entered(); -                  let physical_size = state.physical_size();                  if physical_size.width == 0 || physical_size.height == 0 { @@ -622,24 +600,12 @@ pub fn build_user_interface<'a, A: Application>(  where      <A::Renderer as core::Renderer>::Theme: StyleSheet,  { -    #[cfg(feature = "trace")] -    let view_span = info_span!("Application", "VIEW").entered(); -      debug.view_started();      let view = application.view(); - -    #[cfg(feature = "trace")] -    let _ = view_span.exit();      debug.view_finished(); -    #[cfg(feature = "trace")] -    let layout_span = info_span!("Application", "LAYOUT").entered(); -      debug.layout_started();      let user_interface = UserInterface::build(view, size, cache, renderer); - -    #[cfg(feature = "trace")] -    let _ = layout_span.exit();      debug.layout_finished();      user_interface @@ -666,16 +632,10 @@ pub fn update<A: Application, C, E: Executor>(      <A::Renderer as core::Renderer>::Theme: StyleSheet,  {      for message in messages.drain(..) { -        #[cfg(feature = "trace")] -        let update_span = info_span!("Application", "UPDATE").entered(); -          debug.log_message(&message);          debug.update_started();          let command = runtime.enter(|| application.update(message)); - -        #[cfg(feature = "trace")] -        let _ = update_span.exit();          debug.update_finished();          run_command( @@ -750,7 +710,7 @@ pub fn run_command<A, C, E>(                  }                  window::Action::Spawn { .. } => {                      log::info!( -                        "Spawning a window is only available with `multi_window::Application`s." +                        "Spawning a window is only available with multi-window applications."                      )                  }                  window::Action::Resize(size) => { diff --git a/winit/src/conversion.rs b/winit/src/conversion.rs index fe0fce19..0625e74b 100644 --- a/winit/src/conversion.rs +++ b/winit/src/conversion.rs @@ -7,7 +7,6 @@ use crate::core::mouse;  use crate::core::touch;  use crate::core::window;  use crate::core::{Event, Point}; -use crate::Position;  /// Converts a winit window event into an iced event.  pub fn window_event( @@ -169,17 +168,17 @@ pub fn window_level(level: window::Level) -> winit::window::WindowLevel {  pub fn position(      monitor: Option<&winit::monitor::MonitorHandle>,      (width, height): (u32, u32), -    position: Position, +    position: window::Position,  ) -> Option<winit::dpi::Position> {      match position { -        Position::Default => None, -        Position::Specific(x, y) => { +        window::Position::Default => None, +        window::Position::Specific(x, y) => {              Some(winit::dpi::Position::Logical(winit::dpi::LogicalPosition {                  x: f64::from(x),                  y: f64::from(y),              }))          } -        Position::Centered => { +        window::Position::Centered => {              if let Some(monitor) = monitor {                  let start = monitor.position(); diff --git a/winit/src/lib.rs b/winit/src/lib.rs index dc163430..31002f51 100644 --- a/winit/src/lib.rs +++ b/winit/src/lib.rs @@ -51,20 +51,14 @@ pub mod settings;  pub mod system;  mod error; -mod icon;  mod proxy; -#[cfg(feature = "trace")] -mod profiler;  #[cfg(feature = "application")]  pub use application::Application; -#[cfg(feature = "trace")] -pub use profiler::Profiler;  pub use clipboard::Clipboard;  pub use error::Error; -pub use icon::Icon;  pub use proxy::Proxy;  pub use settings::Settings; +pub use crate::core::window::*;  pub use iced_graphics::Viewport; -pub use iced_native::window::Position; diff --git a/winit/src/multi_window.rs b/winit/src/multi_window.rs index 9b395c1d..e6f440bc 100644 --- a/winit/src/multi_window.rs +++ b/winit/src/multi_window.rs @@ -1,58 +1,57 @@  //! Create interactive, native cross-platform applications for WGPU.  mod state; +mod windows;  pub use state::State; -use crate::clipboard::{self, Clipboard}; -use crate::conversion; -use crate::mouse; -use crate::renderer; -use crate::settings; -use crate::widget::operation; -use crate::window; -use crate::{ -    Command, Debug, Element, Error, Executor, Proxy, Renderer, Runtime, -    Settings, Size, Subscription, -}; - -use iced_futures::futures::channel::mpsc; -use iced_futures::futures::{self, FutureExt}; -use iced_graphics::compositor; -use iced_native::user_interface::{self, UserInterface}; - -pub use iced_native::application::{Appearance, StyleSheet}; - -use std::collections::HashMap; +use crate::core::widget::operation; +use crate::core::{self, mouse, renderer, window, Size}; +use crate::futures::futures::channel::mpsc; +use crate::futures::futures::{task, Future, FutureExt, StreamExt}; +use crate::futures::{Executor, Runtime, Subscription}; +use crate::graphics::{compositor, Compositor}; +use crate::multi_window::windows::Windows; +use crate::runtime::command::{self, Command}; +use crate::runtime::multi_window::Program; +use crate::runtime::user_interface::{self, UserInterface}; +use crate::runtime::Debug; +use crate::settings::window_builder; +use crate::style::application::StyleSheet; +use crate::{conversion, settings, Clipboard, Error, Proxy, Settings}; + +use iced_runtime::user_interface::Cache;  use std::mem::ManuallyDrop;  use std::time::Instant; - -#[cfg(feature = "trace")] -pub use crate::Profiler; -#[cfg(feature = "trace")] -use tracing::{info_span, instrument::Instrument}; +use winit::monitor::MonitorHandle;  /// This is a wrapper around the `Application::Message` associate type  /// to allows the `shell` to create internal messages, while still having  /// the current user-specified custom messages.  #[derive(Debug)]  pub enum Event<Message> { -    /// An [`Application`] generated message +    /// An internal event which contains an [`Application`] generated message.      Application(Message), -    /// A message which spawns a new window. +    /// An internal event which spawns a new window.      NewWindow {          /// The [window::Id] of the newly spawned [`Window`].          id: window::Id,          /// The [settings::Window] of the newly spawned [`Window`]. -        settings: settings::Window, +        settings: window::Settings,          /// The title of the newly spawned [`Window`].          title: String, +        /// The monitor on which to spawn the window. If `None`, will use monitor of the last window +        /// spawned. +        monitor: Option<MonitorHandle>,      }, -    /// Close a window. +    /// An internal event for closing a window.      CloseWindow(window::Id), -    /// A message for when the window has finished being created. +    /// An internal event for when the window has finished being created.      WindowCreated(window::Id, winit::window::Window),  } +#[allow(unsafe_code)] +unsafe impl<Message> std::marker::Send for Event<Message> {} +  /// An interactive, native, cross-platform, multi-windowed application.  ///  /// This trait is the main entrypoint of multi-window Iced. Once implemented, you can run @@ -64,37 +63,13 @@ pub enum Event<Message> {  ///  /// When using an [`Application`] with the `debug` feature enabled, a debug view  /// can be toggled by pressing `F12`. -pub trait Application: Sized +pub trait Application: Program  where -    <Self::Renderer as crate::Renderer>::Theme: StyleSheet, +    <Self::Renderer as core::Renderer>::Theme: StyleSheet,  {      /// The data needed to initialize your [`Application`].      type Flags; -    /// The graphics backend to use to draw the [`Program`]. -    type Renderer: Renderer; - -    /// The type of __messages__ your [`Program`] will produce. -    type Message: std::fmt::Debug + Send; - -    /// Handles a __message__ and updates the state of the [`Program`]. -    /// -    /// This is where you define your __update logic__. All the __messages__, -    /// produced by either user interactions or commands, will be handled by -    /// this method. -    /// -    /// Any [`Command`] returned will be executed immediately in the -    /// background by shells. -    fn update(&mut self, message: Self::Message) -> Command<Self::Message>; - -    /// Returns the widgets to display for the `window` in the [`Program`]. -    /// -    /// These widgets can produce __messages__ based on user interaction. -    fn view( -        &self, -        window: window::Id, -    ) -> Element<'_, Self::Message, Self::Renderer>; -      /// Initializes the [`Application`] with the flags provided to      /// [`run`] as part of the [`Settings`].      /// @@ -105,19 +80,22 @@ where      /// load state from a file, perform an initial HTTP request, etc.      fn new(flags: Self::Flags) -> (Self, Command<Self::Message>); -    /// Returns the current title of each window of the [`Application`]. +    /// Returns the current title of the [`Application`].      ///      /// This title can be dynamic! The runtime will automatically update the      /// title of your application when necessary.      fn title(&self, window: window::Id) -> String; -    /// Returns the current [`Theme`] of the [`Application`]. -    fn theme(&self, window: window::Id) -> <Self::Renderer as crate::Renderer>::Theme; +    /// Returns the current `Theme` of the [`Application`]. +    fn theme( +        &self, +        window: window::Id, +    ) -> <Self::Renderer as core::Renderer>::Theme; -    /// Returns the [`Style`] variation of the [`Theme`]. +    /// Returns the `Style` variation of the `Theme`.      fn style(          &self, -    ) -> <<Self::Renderer as crate::Renderer>::Theme as StyleSheet>::Style { +    ) -> <<Self::Renderer as core::Renderer>::Theme as StyleSheet>::Style {          Default::default()      } @@ -147,17 +125,6 @@ where      fn scale_factor(&self, window: window::Id) -> f64 {          1.0      } - -    /// Returns whether the [`Application`] should be terminated. -    /// -    /// By default, it returns `false`. -    fn should_exit(&self) -> bool { -        false -    } - -    /// Returns the `Self::Message` that should be processed when a `window` is requested to -    /// be closed. -    fn close_requested(&self, window: window::Id) -> Self::Message;  }  /// Runs an [`Application`] with an executor, compositor, and the provided @@ -169,22 +136,14 @@ pub fn run<A, E, C>(  where      A: Application + 'static,      E: Executor + 'static, -    C: iced_graphics::window::Compositor<Renderer = A::Renderer> + 'static, -    <A::Renderer as crate::Renderer>::Theme: StyleSheet, +    C: Compositor<Renderer = A::Renderer> + 'static, +    <A::Renderer as core::Renderer>::Theme: StyleSheet,  { -    use futures::task; -    use futures::Future;      use winit::event_loop::EventLoopBuilder; -    #[cfg(feature = "trace")] -    let _guard = Profiler::init(); -      let mut debug = Debug::new();      debug.startup_started(); -    #[cfg(feature = "trace")] -    let _ = info_span!("Application", "RUN").entered(); -      let event_loop = EventLoopBuilder::with_user_event().build();      let proxy = event_loop.create_proxy(); @@ -201,68 +160,77 @@ where          runtime.enter(|| A::new(flags))      }; -    let builder = settings.window.into_builder( +    let should_main_be_visible = settings.window.visible; +    let builder = window_builder( +        settings.window,          &application.title(window::Id::MAIN),          event_loop.primary_monitor(),          settings.id, -    ); +    ) +    .with_visible(false);      log::info!("Window builder: {:#?}", builder); -    let window = builder +    let main_window = builder          .build(&event_loop)          .map_err(Error::WindowCreationFailed)?; -    let windows: HashMap<window::Id, winit::window::Window> = -        HashMap::from([(window::Id::MAIN, window)]); - -    let window = windows.values().next().expect("No window found"); -      #[cfg(target_arch = "wasm32")]      {          use winit::platform::web::WindowExtWebSys; -        let canvas = window.canvas(); +        let canvas = main_window.canvas();          let window = web_sys::window().unwrap();          let document = window.document().unwrap();          let body = document.body().unwrap(); -        let _ = body -            .append_child(&canvas) -            .expect("Append canvas to HTML body"); +        let target = target.and_then(|target| { +            body.query_selector(&format!("#{}", target)) +                .ok() +                .unwrap_or(None) +        }); + +        match target { +            Some(node) => { +                let _ = node +                    .replace_with_with_node_1(&canvas) +                    .expect(&format!("Could not replace #{}", node.id())); +            } +            None => { +                let _ = body +                    .append_child(&canvas) +                    .expect("Append canvas to HTML body"); +            } +        };      } -    let (compositor, renderer) = C::new(compositor_settings, Some(&window))?; +    let (mut compositor, renderer) = +        C::new(compositor_settings, Some(&main_window))?; + +    let windows = +        Windows::new(&application, &mut compositor, renderer, main_window);      let (mut event_sender, event_receiver) = mpsc::unbounded();      let (control_sender, mut control_receiver) = mpsc::unbounded(); -    let mut instance = Box::pin({ -        let run_instance = run_instance::<A, E, C>( -            application, -            compositor, -            renderer, -            runtime, -            proxy, -            debug, -            event_receiver, -            control_sender, -            init_command, -            windows, -            settings.exit_on_close_request, -        ); - -        #[cfg(feature = "trace")] -        let run_instance = -            run_instance.instrument(info_span!("Application", "LOOP")); - -        run_instance -    }); +    let mut instance = Box::pin(run_instance::<A, E, C>( +        application, +        compositor, +        runtime, +        proxy, +        debug, +        event_receiver, +        control_sender, +        init_command, +        windows, +        should_main_be_visible, +        settings.exit_on_close_request, +    ));      let mut context = task::Context::from_waker(task::noop_waker_ref()); -    platform::run(event_loop, move |event, event_loop, control_flow| { +    platform::run(event_loop, move |event, window_target, control_flow| {          use winit::event_loop::ControlFlow;          if let ControlFlow::ExitWithCode(_) = control_flow { @@ -285,11 +253,12 @@ where                  id,                  settings,                  title, +                monitor,              }) => { -                let window = settings -                    .into_builder(&title, event_loop.primary_monitor(), None) -                    .build(event_loop) -                    .expect("Failed to build window"); +                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, @@ -320,7 +289,6 @@ where  async fn run_instance<A, E, C>(      mut application: A,      mut compositor: C, -    mut renderer: A::Renderer,      mut runtime: Runtime<E, Proxy<Event<A::Message>>, Event<A::Message>>,      mut proxy: winit::event_loop::EventLoopProxy<Event<A::Message>>,      mut debug: Debug, @@ -329,74 +297,65 @@ async fn run_instance<A, E, C>(      >,      mut control_sender: mpsc::UnboundedSender<winit::event_loop::ControlFlow>,      init_command: Command<A::Message>, -    mut windows: HashMap<window::Id, winit::window::Window>, -    _exit_on_close_request: bool, +    mut windows: Windows<A, C>, +    should_main_window_be_visible: bool, +    exit_on_main_closed: bool,  ) where      A: Application + 'static,      E: Executor + 'static, -    C: iced_graphics::window::Compositor<Renderer = A::Renderer> + 'static, -    <A::Renderer as crate::Renderer>::Theme: StyleSheet, +    C: Compositor<Renderer = A::Renderer> + 'static, +    <A::Renderer as core::Renderer>::Theme: StyleSheet,  { -    use iced_futures::futures::stream::StreamExt;      use winit::event;      use winit::event_loop::ControlFlow; -    let mut clipboard = -        Clipboard::connect(windows.values().next().expect("No window found")); -    let mut caches = HashMap::new(); -    let mut window_ids: HashMap<_, _> = windows -        .iter() -        .map(|(&id, window)| (window.id(), id)) -        .collect(); - -    let mut states = HashMap::new(); -    let mut surfaces = HashMap::new(); -    let mut interfaces = ManuallyDrop::new(HashMap::new()); - -    for (&id, window) in windows.keys().zip(windows.values()) { -        let mut surface = compositor.create_surface(window); -        let state = State::new(&application, id, window); -        let physical_size = state.physical_size(); - -        compositor.configure_surface( -            &mut surface, -            physical_size.width, -            physical_size.height, -        ); +    let mut clipboard = Clipboard::connect(windows.main()); -        let user_interface = build_user_interface( -            &application, -            user_interface::Cache::default(), -            &mut renderer, -            state.logical_size(), -            &mut debug, -            id, -        ); +    let mut ui_caches = vec![user_interface::Cache::default()]; +    let mut user_interfaces = ManuallyDrop::new(build_user_interfaces( +        &application, +        &mut debug, +        &mut windows, +        vec![user_interface::Cache::default()], +    )); -        let _ = states.insert(id, state); -        let _ = surfaces.insert(id, surface); -        let _ = interfaces.insert(id, user_interface); -        let _ = caches.insert(id, user_interface::Cache::default()); +    if should_main_window_be_visible { +        windows.main().set_visible(true);      }      run_command(          &application, -        &mut caches, -        &states, -        &mut renderer, +        &mut compositor,          init_command,          &mut runtime,          &mut clipboard,          &mut proxy,          &mut debug, -        &windows, -        || compositor.fetch_information(), +        &mut windows, +        &mut ui_caches,      ); -    runtime.track(application.subscription().map(Event::Application)); +    runtime.track( +        application +            .subscription() +            .map(Event::Application) +            .into_recipes(), +    );      let mut mouse_interaction = mouse::Interaction::default(); -    let mut events = Vec::new(); + +    let mut events = +        if let Some((position, size)) = logical_bounds_of(windows.main()) { +            vec![( +                Some(window::Id::MAIN), +                core::Event::Window( +                    window::Id::MAIN, +                    window::Event::Created { position, size }, +                ), +            )] +        } else { +            Vec::new() +        };      let mut messages = Vec::new();      let mut redraw_pending = false; @@ -413,25 +372,20 @@ async fn run_instance<A, E, C>(                  );              }              event::Event::MainEventsCleared => { -                for id in states.keys().copied().collect::<Vec<_>>() { -                    // Partition events into only events for this window -                    let (filtered, remaining): (Vec<_>, Vec<_>) = -                        events.iter().cloned().partition( -                            |(window_id, _event): &( -                                Option<window::Id>, -                                iced_native::event::Event, -                            )| { -                                *window_id == Some(id) || *window_id == None -                            }, -                        ); - -                    // Only retain events which have not been processed for next iteration -                    events.retain(|el| remaining.contains(el)); - -                    let window_events: Vec<_> = filtered -                        .into_iter() -                        .map(|(_id, event)| event) -                        .collect(); +                debug.event_processing_started(); +                let mut uis_stale = false; + +                for (i, id) in windows.ids.iter().enumerate() { +                    let mut window_events = vec![]; + +                    events.retain(|(window_id, event)| { +                        if *window_id == Some(*id) || window_id.is_none() { +                            window_events.push(event.clone()); +                            false +                        } else { +                            true +                        } +                    });                      if !redraw_pending                          && window_events.is_empty() @@ -440,144 +394,124 @@ async fn run_instance<A, E, C>(                          continue;                      } -                    // Process winit events for window -                    debug.event_processing_started(); -                    let cursor_position = -                        states.get(&id).unwrap().cursor_position(); - -                    let (interface_state, statuses) = { -                        let user_interface = interfaces.get_mut(&id).unwrap(); -                        user_interface.update( -                            &window_events, -                            cursor_position, -                            &mut renderer, -                            &mut clipboard, -                            &mut messages, -                        ) -                    }; +                    let (ui_state, statuses) = user_interfaces[i].update( +                        &window_events, +                        windows.states[i].cursor(), +                        &mut windows.renderers[i], +                        &mut clipboard, +                        &mut messages, +                    ); + +                    if !uis_stale { +                        uis_stale = +                            matches!(ui_state, user_interface::State::Outdated); +                    } -                    for event in +                    for (event, status) in                          window_events.into_iter().zip(statuses.into_iter())                      { -                        runtime.broadcast(event); +                        runtime.broadcast(event, status);                      } -                    debug.event_processing_finished(); - -                    // Update application with app messages -                    // Unless we implement some kind of diffing, we must redraw all windows as we -                    // cannot know what changed. -                    if !messages.is_empty() -                        || matches!( -                            interface_state, -                            user_interface::State::Outdated, -                        ) -                    { -                        let mut cached_interfaces: HashMap<_, _> = -                            ManuallyDrop::into_inner(interfaces) -                                .drain() -                                .map( -                                    |(id, interface): ( -                                        window::Id, -                                        UserInterface<'_, _, _>, -                                    )| { -                                        (id, interface.into_cache()) -                                    }, -                                ) -                                .collect(); - -                        // Update application -                        update( -                            &mut application, -                            &mut cached_interfaces, -                            &states, -                            &mut renderer, -                            &mut runtime, -                            &mut clipboard, -                            &mut proxy, -                            &mut debug, -                            &mut messages, -                            &windows, -                            || compositor.fetch_information(), -                        ); - -                        // synchronize window states with application states. -                        for (id, state) in states.iter_mut() { -                            state.synchronize( -                                &application, -                                *id, -                                windows -                                    .get(id) -                                    .expect("No window found with ID."), -                            ); -                        } +                } -                        interfaces = ManuallyDrop::new(build_user_interfaces( -                            &application, -                            &mut renderer, -                            &mut debug, -                            &states, -                            cached_interfaces, -                        )); +                debug.event_processing_finished(); + +                // TODO mw application update returns which window IDs to update +                if !messages.is_empty() || uis_stale { +                    let mut cached_interfaces: Vec<Cache> = +                        ManuallyDrop::into_inner(user_interfaces) +                            .drain(..) +                            .map(UserInterface::into_cache) +                            .collect(); + +                    // Update application +                    update( +                        &mut application, +                        &mut compositor, +                        &mut runtime, +                        &mut clipboard, +                        &mut proxy, +                        &mut debug, +                        &mut messages, +                        &mut windows, +                        &mut cached_interfaces, +                    ); -                        if application.should_exit() { -                            break 'main; -                        } +                    // we must synchronize all window states with application state after an +                    // application update since we don't know what changed +                    for (state, (id, window)) in windows +                        .states +                        .iter_mut() +                        .zip(windows.ids.iter().zip(windows.raw.iter())) +                    { +                        state.synchronize(&application, *id, window);                      } +                    // rebuild UIs with the synchronized states +                    user_interfaces = ManuallyDrop::new(build_user_interfaces( +                        &application, +                        &mut debug, +                        &mut windows, +                        cached_interfaces, +                    )); +                } + +                debug.draw_started(); + +                for (i, id) in windows.ids.iter().enumerate() {                      // TODO: Avoid redrawing all the time by forcing widgets to -                    // request redraws on state changes +                    //  request redraws on state changes                      //                      // Then, we can use the `interface_state` here to decide if a redraw                      // is needed right away, or simply wait until a specific time. -                    let redraw_event = iced_native::Event::Window( -                        id, +                    let redraw_event = core::Event::Window( +                        *id,                          window::Event::RedrawRequested(Instant::now()),                      ); -                    let (interface_state, _) = -                        interfaces.get_mut(&id).unwrap().update( -                            &[redraw_event.clone()], -                            cursor_position, -                            &mut renderer, -                            &mut clipboard, -                            &mut messages, -                        ); +                    let cursor = windows.states[i].cursor(); + +                    let (ui_state, _) = user_interfaces[i].update( +                        &[redraw_event.clone()], +                        cursor, +                        &mut windows.renderers[i], +                        &mut clipboard, +                        &mut messages, +                    ); -                    debug.draw_started();                      let new_mouse_interaction = { -                        let state = states.get(&id).unwrap(); +                        let state = &windows.states[i]; -                        interfaces.get_mut(&id).unwrap().draw( -                            &mut renderer, +                        user_interfaces[i].draw( +                            &mut windows.renderers[i],                              state.theme(),                              &renderer::Style {                                  text_color: state.text_color(),                              }, -                            state.cursor_position(), +                            cursor,                          )                      }; -                    debug.draw_finished(); - -                    let window = windows.get(&id).unwrap();                      if new_mouse_interaction != mouse_interaction { -                        window.set_cursor_icon(conversion::mouse_interaction( -                            new_mouse_interaction, -                        )); +                        windows.raw[i].set_cursor_icon( +                            conversion::mouse_interaction( +                                new_mouse_interaction, +                            ), +                        );                          mouse_interaction = new_mouse_interaction;                      } -                    for window in windows.values() { -                        window.request_redraw(); -                    } +                    // TODO once widgets can request to be redrawn, we can avoid always requesting a +                    // redraw +                    windows.raw[i].request_redraw(); -                    runtime.broadcast(( +                    runtime.broadcast(                          redraw_event.clone(), -                        crate::event::Status::Ignored, -                    )); +                        core::event::Status::Ignored, +                    ); -                    let _ = control_sender.start_send(match interface_state { +                    let _ = control_sender.start_send(match ui_state {                          user_interface::State::Updated {                              redraw_request: Some(redraw_request),                          } => match redraw_request { @@ -590,17 +524,20 @@ async fn run_instance<A, E, C>(                          },                          _ => ControlFlow::Wait,                      }); - -                    redraw_pending = false;                  } + +                redraw_pending = false; + +                debug.draw_finished();              }              event::Event::PlatformSpecific(event::PlatformSpecific::MacOS(                  event::MacOS::ReceivedUrl(url),              )) => { -                use iced_native::event; +                use crate::core::event; +                  events.push((                      None, -                    iced_native::Event::PlatformSpecific( +                    event::Event::PlatformSpecific(                          event::PlatformSpecific::MacOS(                              event::MacOS::ReceivedUrl(url),                          ), @@ -612,91 +549,48 @@ async fn run_instance<A, E, C>(                      messages.push(message);                  }                  Event::WindowCreated(id, window) => { -                    let mut surface = compositor.create_surface(&window); -                    let state = State::new(&application, id, &window); -                    let physical_size = state.physical_size(); +                    let bounds = logical_bounds_of(&window); -                    compositor.configure_surface( -                        &mut surface, -                        physical_size.width, -                        physical_size.height, -                    ); +                    let (inner_size, i) = +                        windows.add(&application, &mut compositor, id, window); -                    let user_interface = build_user_interface( +                    user_interfaces.push(build_user_interface(                          &application,                          user_interface::Cache::default(), -                        &mut renderer, -                        state.logical_size(), +                        &mut windows.renderers[i], +                        inner_size,                          &mut debug,                          id, -                    ); - -                    let _ = states.insert(id, state); -                    let _ = surfaces.insert(id, surface); -                    let _ = interfaces.insert(id, user_interface); -                    let _ = window_ids.insert(window.id(), id); -                    let _ = windows.insert(id, window); -                    let _ = caches.insert(id, user_interface::Cache::default()); +                    )); +                    ui_caches.push(user_interface::Cache::default()); + +                    if let Some(bounds) = bounds { +                        events.push(( +                            Some(id), +                            core::Event::Window( +                                id, +                                window::Event::Created { +                                    position: bounds.0, +                                    size: bounds.1, +                                }, +                            ), +                        )); +                    }                  }                  Event::CloseWindow(id) => { -                    if let Some(window) = windows.get(&id) { -                        if window_ids.remove(&window.id()).is_none() { -                            log::error!("Failed to remove window with id {:?} from window_ids.", window.id()); -                        } -                    } else { -                        log::error!( -                            "Could not find window with id {:?} in windows.", -                            id -                        ); -                    } -                    if states.remove(&id).is_none() { -                        log::error!( -                            "Failed to remove window {:?} from states.", -                            id -                        ); -                    } -                    if interfaces.remove(&id).is_none() { -                        log::error!( -                            "Failed to remove window {:?} from interfaces.", -                            id -                        ); -                    } -                    if windows.remove(&id).is_none() { -                        log::error!( -                            "Failed to remove window {:?} from windows.", -                            id -                        ); -                    } -                    if surfaces.remove(&id).is_none() { -                        log::error!( -                            "Failed to remove window {:?} from surfaces.", -                            id -                        ); -                    } +                    let i = windows.delete(id); +                    let _ = user_interfaces.remove(i); +                    let _ = ui_caches.remove(i);                      if windows.is_empty() { -                        log::info!( -                            "All windows are closed. Terminating program." -                        );                          break 'main; -                    } else { -                        log::info!("Remaining windows: {:?}", windows.len());                      }                  }                  Event::NewWindow { .. } => unreachable!(),              },              event::Event::RedrawRequested(id) => { -                #[cfg(feature = "trace")] -                let _ = info_span!("Application", "FRAME").entered(); - -                let state = window_ids -                    .get(&id) -                    .and_then(|id| states.get_mut(id)) -                    .unwrap(); -                let surface = window_ids -                    .get(&id) -                    .and_then(|id| surfaces.get_mut(id)) -                    .unwrap(); +                let i = windows.index_from_raw(id); +                let state = &windows.states[i];                  let physical_size = state.physical_size();                  if physical_size.width == 0 || physical_size.height == 0 { @@ -704,60 +598,55 @@ async fn run_instance<A, E, C>(                  }                  debug.render_started(); +                let current_viewport_version = state.viewport_version(); +                let window_viewport_version = windows.viewport_versions[i]; -                if state.viewport_changed() { -                    let mut user_interface = window_ids -                        .get(&id) -                        .and_then(|id| interfaces.remove(id)) -                        .unwrap(); - +                if window_viewport_version != current_viewport_version {                      let logical_size = state.logical_size();                      debug.layout_started(); -                    user_interface = -                        user_interface.relayout(logical_size, &mut renderer); + +                    let renderer = &mut windows.renderers[i]; +                    let ui = user_interfaces.remove(i); + +                    user_interfaces +                        .insert(i, ui.relayout(logical_size, renderer)); +                      debug.layout_finished();                      debug.draw_started(); -                    let new_mouse_interaction = { -                        let state = &state; - -                        user_interface.draw( -                            &mut renderer, -                            state.theme(), -                            &renderer::Style { -                                text_color: state.text_color(), -                            }, -                            state.cursor_position(), -                        ) -                    }; +                    let new_mouse_interaction = user_interfaces[i].draw( +                        renderer, +                        state.theme(), +                        &renderer::Style { +                            text_color: state.text_color(), +                        }, +                        state.cursor(), +                    ); -                    let window = window_ids -                        .get(&id) -                        .and_then(|id| windows.get(id)) -                        .unwrap();                      if new_mouse_interaction != mouse_interaction { -                        window.set_cursor_icon(conversion::mouse_interaction( -                            new_mouse_interaction, -                        )); +                        windows.raw[i].set_cursor_icon( +                            conversion::mouse_interaction( +                                new_mouse_interaction, +                            ), +                        );                          mouse_interaction = new_mouse_interaction;                      }                      debug.draw_finished(); -                    let _ = interfaces -                        .insert(*window_ids.get(&id).unwrap(), user_interface); -                      compositor.configure_surface( -                        surface, +                        &mut windows.surfaces[i],                          physical_size.width,                          physical_size.height,                      ); + +                    windows.viewport_versions[i] = current_viewport_version;                  }                  match compositor.present( -                    &mut renderer, -                    surface, +                    &mut windows.renderers[i], +                    &mut windows.surfaces[i],                      state.viewport(),                      state.background_color(),                      &debug.overlay(), @@ -775,10 +664,12 @@ async fn run_instance<A, E, C>(                          }                          _ => {                              debug.render_finished(); -                            log::error!("Error {error:?} when presenting surface."); +                            log::error!( +                                "Error {error:?} when presenting surface." +                            ); -                            // Try rendering windows again next frame. -                            for window in windows.values() { +                            // Try rendering all windows again next frame. +                            for window in &windows.raw {                                  window.request_redraw();                              }                          } @@ -789,42 +680,58 @@ async fn run_instance<A, E, C>(                  event: window_event,                  window_id,              } => { -                if let (Some(window), Some(state)) = ( -                    window_ids.get(&window_id).and_then(|id| windows.get(id)), -                    window_ids -                        .get(&window_id) -                        .and_then(|id| states.get_mut(id)), -                ) { -                    if crate::application::requests_exit(&window_event, state.modifiers()) { -                        if let Some(id) = window_ids.get(&window_id).cloned() { -                            let message = application.close_requested(id); -                            messages.push(message); -                        } +                let window_deleted = windows +                    .pending_destroy +                    .iter() +                    .any(|(_, w_id)| window_id == *w_id); + +                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;                      } -                    state.update(window, &window_event, &mut debug); +                    state.update(raw, &window_event, &mut debug);                      if let Some(event) = conversion::window_event( -                        *window_ids.get(&window_id).unwrap(), +                        id,                          &window_event,                          state.scale_factor(),                          state.modifiers(),                      ) { -                        events -                            .push((window_ids.get(&window_id).cloned(), event)); +                        events.push((Some(id), event));                      } -                } else { -                    log::error!( -                        "Could not find window or state for id: {window_id:?}" -                    );                  }              }              _ => {}          }      } -    // Manually drop the user interfaces -    drop(ManuallyDrop::into_inner(interfaces)); +    let _ = ManuallyDrop::into_inner(user_interfaces);  }  /// Builds a window's [`UserInterface`] for the [`Application`]. @@ -837,103 +744,79 @@ pub fn build_user_interface<'a, A: Application>(      id: window::Id,  ) -> UserInterface<'a, A::Message, A::Renderer>  where -    <A::Renderer as crate::Renderer>::Theme: StyleSheet, +    <A::Renderer as core::Renderer>::Theme: StyleSheet,  { -    #[cfg(feature = "trace")] -    let view_span = info_span!("Application", "VIEW").entered(); -      debug.view_started();      let view = application.view(id); - -    #[cfg(feature = "trace")] -    let _ = view_span.exit();      debug.view_finished(); -    #[cfg(feature = "trace")] -    let layout_span = info_span!("Application", "LAYOUT").entered();      debug.layout_started(); -      let user_interface = UserInterface::build(view, size, cache, renderer); - -    #[cfg(feature = "trace")] -    let _ = layout_span.exit();      debug.layout_finished();      user_interface  } -/// Updates an [`Application`] by feeding it messages, spawning any +/// Updates a multi-window [`Application`] by feeding it messages, spawning any  /// resulting [`Command`], and tracking its [`Subscription`]. -pub fn update<A: Application, E: Executor>( +pub fn update<A: Application, C, E: Executor>(      application: &mut A, -    caches: &mut HashMap<window::Id, user_interface::Cache>, -    states: &HashMap<window::Id, State<A>>, -    renderer: &mut A::Renderer, +    compositor: &mut C,      runtime: &mut Runtime<E, Proxy<Event<A::Message>>, Event<A::Message>>,      clipboard: &mut Clipboard,      proxy: &mut winit::event_loop::EventLoopProxy<Event<A::Message>>,      debug: &mut Debug,      messages: &mut Vec<A::Message>, -    windows: &HashMap<window::Id, winit::window::Window>, -    graphics_info: impl FnOnce() -> compositor::Information + Copy, +    windows: &mut Windows<A, C>, +    ui_caches: &mut Vec<user_interface::Cache>,  ) where -    A: Application + 'static, -    <A::Renderer as crate::Renderer>::Theme: StyleSheet, +    C: Compositor<Renderer = A::Renderer> + 'static, +    <A::Renderer as core::Renderer>::Theme: StyleSheet,  {      for message in messages.drain(..) { -        #[cfg(feature = "trace")] -        let update_span = info_span!("Application", "UPDATE").entered(); -          debug.log_message(&message); -          debug.update_started();          let command = runtime.enter(|| application.update(message)); - -        #[cfg(feature = "trace")] -        let _ = update_span.exit();          debug.update_finished();          run_command(              application, -            caches, -            states, -            renderer, +            compositor,              command,              runtime,              clipboard,              proxy,              debug,              windows, -            graphics_info, +            ui_caches,          );      }      let subscription = application.subscription().map(Event::Application); -    runtime.track(subscription); +    runtime.track(subscription.into_recipes());  }  /// Runs the actions of a [`Command`]. -pub fn run_command<A, E>( +pub fn run_command<A, C, E>(      application: &A, -    caches: &mut HashMap<window::Id, user_interface::Cache>, -    states: &HashMap<window::Id, State<A>>, -    renderer: &mut A::Renderer, +    compositor: &mut C,      command: Command<A::Message>,      runtime: &mut Runtime<E, Proxy<Event<A::Message>>, Event<A::Message>>,      clipboard: &mut Clipboard,      proxy: &mut winit::event_loop::EventLoopProxy<Event<A::Message>>,      debug: &mut Debug, -    windows: &HashMap<window::Id, winit::window::Window>, -    _graphics_info: impl FnOnce() -> compositor::Information + Copy, +    windows: &mut Windows<A, C>, +    ui_caches: &mut Vec<user_interface::Cache>,  ) where -    A: Application + 'static, +    A: Application,      E: Executor, -    <A::Renderer as crate::Renderer>::Theme: StyleSheet, +    C: Compositor<Renderer = A::Renderer> + 'static, +    <A::Renderer as core::Renderer>::Theme: StyleSheet,  { -    use iced_native::command; -    use iced_native::system; -    use iced_native::window; +    use crate::runtime::clipboard; +    use crate::runtime::system; +    use crate::runtime::window;      for action in command.actions() {          match action { @@ -954,11 +837,14 @@ pub fn run_command<A, E>(              },              command::Action::Window(id, action) => match action {                  window::Action::Spawn { settings } => { +                    let monitor = windows.last_monitor(); +                      proxy                          .send_event(Event::NewWindow {                              id, -                            settings: settings.into(), +                            settings,                              title: application.title(id), +                            monitor,                          })                          .expect("Send message to event loop");                  } @@ -968,86 +854,117 @@ pub fn run_command<A, E>(                          .expect("Send message to event loop");                  }                  window::Action::Drag => { -                    let window = windows.get(&id).expect("No window found"); -                    let _res = window.drag_window(); +                    let _ = windows.with_raw(id).drag_window();                  } -                window::Action::Resize { width, height } => { -                    let window = windows.get(&id).expect("No window found"); -                    window.set_inner_size(winit::dpi::LogicalSize { -                        width, -                        height, -                    }); +                window::Action::Resize(size) => { +                    windows.with_raw(id).set_inner_size( +                        winit::dpi::LogicalSize { +                            width: size.width, +                            height: size.height, +                        }, +                    ); +                } +                window::Action::FetchSize(callback) => { +                    let window = windows.with_raw(id); +                    let size = window.inner_size(); + +                    proxy +                        .send_event(Event::Application(callback(Size::new( +                            size.width, +                            size.height, +                        )))) +                        .expect("Send message to event loop") +                } +                window::Action::Maximize(maximized) => { +                    windows.with_raw(id).set_maximized(maximized); +                } +                window::Action::Minimize(minimized) => { +                    windows.with_raw(id).set_minimized(minimized);                  }                  window::Action::Move { x, y } => { -                    let window = windows.get(&id).expect("No window found"); -                    window.set_outer_position(winit::dpi::LogicalPosition { -                        x, -                        y, -                    }); +                    windows.with_raw(id).set_outer_position( +                        winit::dpi::LogicalPosition { x, y }, +                    );                  }                  window::Action::ChangeMode(mode) => { -                    let window = windows.get(&id).expect("No window found"); +                    let window = windows.with_raw(id);                      window.set_visible(conversion::visible(mode));                      window.set_fullscreen(conversion::fullscreen(                          window.current_monitor(),                          mode,                      ));                  } +                window::Action::ChangeIcon(icon) => { +                    windows.with_raw(id).set_window_icon(conversion::icon(icon)) +                }                  window::Action::FetchMode(tag) => { -                    let window = windows.get(&id).expect("No window found"); +                    let window = windows.with_raw(id);                      let mode = if window.is_visible().unwrap_or(true) {                          conversion::mode(window.fullscreen())                      } else { -                        window::Mode::Hidden +                        core::window::Mode::Hidden                      };                      proxy                          .send_event(Event::Application(tag(mode))) -                        .expect("Send message to event loop"); -                } -                window::Action::Maximize(value) => { -                    let window = windows.get(&id).expect("No window found!"); -                    window.set_maximized(value); -                } -                window::Action::Minimize(value) => { -                    let window = windows.get(&id).expect("No window found!"); -                    window.set_minimized(value); +                        .expect("Event loop doesn't exist.");                  }                  window::Action::ToggleMaximize => { -                    let window = windows.get(&id).expect("No window found!"); +                    let window = windows.with_raw(id);                      window.set_maximized(!window.is_maximized());                  }                  window::Action::ToggleDecorations => { -                    let window = windows.get(&id).expect("No window found!"); +                    let window = windows.with_raw(id);                      window.set_decorations(!window.is_decorated());                  }                  window::Action::RequestUserAttention(attention_type) => { -                    let window = windows.get(&id).expect("No window found!"); -                    window.request_user_attention( +                    windows.with_raw(id).request_user_attention(                          attention_type.map(conversion::user_attention),                      );                  }                  window::Action::GainFocus => { -                    let window = windows.get(&id).expect("No window found!"); -                    window.focus_window(); +                    windows.with_raw(id).focus_window();                  } -                window::Action::ChangeAlwaysOnTop(on_top) => { -                    let window = windows.get(&id).expect("No window found!"); -                    window.set_always_on_top(on_top); +                window::Action::ChangeLevel(level) => { +                    windows +                        .with_raw(id) +                        .set_window_level(conversion::window_level(level));                  } -                window::Action::FetchId(tag) => { -                    let window = windows.get(&id).expect("No window found!"); +                window::Action::FetchId(tag) => proxy +                    .send_event(Event::Application(tag(windows +                        .with_raw(id) +                        .id() +                        .into()))) +                    .expect("Event loop doesn't exist."), +                window::Action::Screenshot(tag) => { +                    let i = windows.index_from_id(id); +                    let state = &windows.states[i]; +                    let surface = &mut windows.surfaces[i]; +                    let renderer = &mut windows.renderers[i]; + +                    let bytes = compositor.screenshot( +                        renderer, +                        surface, +                        state.viewport(), +                        state.background_color(), +                        &debug.overlay(), +                    );                      proxy -                        .send_event(Event::Application(tag(window.id().into()))) -                        .expect("Send message to event loop.") +                        .send_event(Event::Application(tag( +                            window::Screenshot::new( +                                bytes, +                                state.physical_size(), +                            ), +                        ))) +                        .expect("Event loop doesn't exist.")                  }              },              command::Action::System(action) => match action {                  system::Action::QueryInformation(_tag) => {                      #[cfg(feature = "system")]                      { -                        let graphics_info = _graphics_info(); +                        let graphics_info = compositor.fetch_information();                          let proxy = proxy.clone();                          let _ = std::thread::spawn(move || { @@ -1058,33 +975,36 @@ pub fn run_command<A, E>(                              proxy                                  .send_event(Event::Application(message)) -                                .expect("Send message to event loop") +                                .expect("Event loop doesn't exist.")                          });                      }                  }              },              command::Action::Widget(action) => { -                let mut current_caches = std::mem::take(caches); -                let mut current_operation = Some(action.into_operation()); +                let mut current_operation = Some(action); -                let mut user_interfaces = build_user_interfaces( +                let mut uis = build_user_interfaces(                      application, -                    renderer,                      debug, -                    states, -                    current_caches, +                    windows, +                    std::mem::take(ui_caches),                  ); -                while let Some(mut operation) = current_operation.take() { -                    for user_interface in user_interfaces.values_mut() { -                        user_interface.operate(renderer, operation.as_mut()); +                'operate: while let Some(mut operation) = +                    current_operation.take() +                { +                    for (i, ui) in uis.iter_mut().enumerate() { +                        ui.operate(&windows.renderers[i], operation.as_mut());                          match operation.finish() {                              operation::Outcome::None => {}                              operation::Outcome::Some(message) => {                                  proxy                                      .send_event(Event::Application(message)) -                                    .expect("Send message to event loop"); +                                    .expect("Event loop doesn't exist."); + +                                // operation completed, don't need to try to operate on rest of UIs +                                break 'operate;                              }                              operation::Outcome::Chain(next) => {                                  current_operation = Some(next); @@ -1093,55 +1013,105 @@ pub fn run_command<A, E>(                      }                  } -                let user_interfaces: HashMap<_, _> = user_interfaces -                    .drain() -                    .map(|(id, interface)| (id, interface.into_cache())) -                    .collect(); +                *ui_caches = +                    uis.drain(..).map(UserInterface::into_cache).collect(); +            } +            command::Action::LoadFont { bytes, tagger } => { +                use crate::core::text::Renderer; + +                // TODO change this once we change each renderer to having a single backend reference.. :pain: +                // TODO: Error handling (?) +                for renderer in &mut windows.renderers { +                    renderer.load_font(bytes.clone()); +                } -                current_caches = user_interfaces; -                *caches = current_caches; +                proxy +                    .send_event(Event::Application(tagger(Ok(())))) +                    .expect("Send message to event loop");              }          }      }  } -/// Build the user interfaces for every window. -pub fn build_user_interfaces<'a, A>( +/// Build the user interface for every window. +pub fn build_user_interfaces<'a, A: Application, C: Compositor>(      application: &'a A, -    renderer: &mut A::Renderer,      debug: &mut Debug, -    states: &HashMap<window::Id, State<A>>, -    mut cached_user_interfaces: HashMap<window::Id, user_interface::Cache>, -) -> HashMap< -    window::Id, -    UserInterface< -        'a, -        <A as Application>::Message, -        <A as Application>::Renderer, -    >, -> +    windows: &mut Windows<A, C>, +    mut cached_user_interfaces: Vec<user_interface::Cache>, +) -> Vec<UserInterface<'a, A::Message, A::Renderer>>  where -    A: Application + 'static, -    <A::Renderer as crate::Renderer>::Theme: StyleSheet, +    <A::Renderer as core::Renderer>::Theme: StyleSheet, +    C: Compositor<Renderer = A::Renderer>,  { -    let mut interfaces = HashMap::new(); - -    for (id, cache) in cached_user_interfaces.drain() { -        let state = &states.get(&id).unwrap(); - -        let user_interface = build_user_interface( -            application, -            cache, -            renderer, -            state.logical_size(), -            debug, -            id, -        ); +    cached_user_interfaces +        .drain(..) +        .zip( +            windows +                .ids +                .iter() +                .zip(windows.states.iter().zip(windows.renderers.iter_mut())), +        ) +        .fold(vec![], |mut uis, (cache, (id, (state, renderer)))| { +            uis.push(build_user_interface( +                application, +                cache, +                renderer, +                state.logical_size(), +                debug, +                *id, +            )); + +            uis +        }) +} -        let _ = interfaces.insert(id, user_interface); +/// Returns true if the provided event should cause an [`Application`] to +/// exit. +pub fn requests_exit( +    window: usize, +    exit_on_main_closed: bool, +    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: +                winit::event::KeyboardInput { +                    virtual_keycode: Some(winit::event::VirtualKeyCode::Q), +                    state: winit::event::ElementState::Pressed, +                    .. +                }, +            .. +        } if _modifiers.logo() => true, +        _ => false,      } +} + +fn logical_bounds_of( +    window: &winit::window::Window, +) -> Option<((i32, i32), Size<u32>)> { +    let scale = window.scale_factor(); +    let pos = window +        .inner_position() +        .map(|pos| { +            ((pos.x as f64 / scale) as i32, (pos.y as f64 / scale) as i32) +        }) +        .ok()?; +    let size = { +        let size = window.inner_size(); +        Size::new( +            (size.width as f64 / scale) as u32, +            (size.height as f64 / scale) as u32, +        ) +    }; -    interfaces +    Some((pos, size))  }  #[cfg(not(target_arch = "wasm32"))] diff --git a/winit/src/multi_window/state.rs b/winit/src/multi_window/state.rs index 54a114ad..f2741c3c 100644 --- a/winit/src/multi_window/state.rs +++ b/winit/src/multi_window/state.rs @@ -1,33 +1,50 @@ -use crate::application::{self, StyleSheet as _};  use crate::conversion; +use crate::core; +use crate::core::{mouse, window}; +use crate::core::{Color, Size}; +use crate::graphics::Viewport;  use crate::multi_window::Application; -use crate::window; -use crate::{Color, Debug, Point, Size, Viewport}; +use crate::style::application; +use std::fmt::{Debug, Formatter}; -use std::marker::PhantomData; +use iced_style::application::StyleSheet;  use winit::event::{Touch, WindowEvent};  use winit::window::Window;  /// The state of a multi-windowed [`Application`]. -#[allow(missing_debug_implementations)]  pub struct State<A: Application>  where -    <A::Renderer as crate::Renderer>::Theme: application::StyleSheet, +    <A::Renderer as core::Renderer>::Theme: application::StyleSheet,  {      title: String,      scale_factor: f64,      viewport: Viewport, -    viewport_changed: bool, -    cursor_position: winit::dpi::PhysicalPosition<f64>, +    viewport_version: usize, +    cursor_position: Option<winit::dpi::PhysicalPosition<f64>>,      modifiers: winit::event::ModifiersState, -    theme: <A::Renderer as crate::Renderer>::Theme, +    theme: <A::Renderer as core::Renderer>::Theme,      appearance: application::Appearance, -    application: PhantomData<A>, +} + +impl<A: Application> Debug for State<A> +where +    <A::Renderer as core::Renderer>::Theme: application::StyleSheet, +{ +    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { +        f.debug_struct("multi_window::State") +            .field("title", &self.title) +            .field("scale_factor", &self.scale_factor) +            .field("viewport", &self.viewport) +            .field("viewport_version", &self.viewport_version) +            .field("cursor_position", &self.cursor_position) +            .field("appearance", &self.appearance) +            .finish() +    }  }  impl<A: Application> State<A>  where -    <A::Renderer as crate::Renderer>::Theme: application::StyleSheet, +    <A::Renderer as core::Renderer>::Theme: application::StyleSheet,  {      /// Creates a new [`State`] for the provided [`Application`]'s `window`.      pub fn new( @@ -53,13 +70,11 @@ where              title,              scale_factor,              viewport, -            viewport_changed: false, -            // TODO: Encode cursor availability in the type-system -            cursor_position: winit::dpi::PhysicalPosition::new(-1.0, -1.0), +            viewport_version: 0, +            cursor_position: None,              modifiers: winit::event::ModifiersState::default(),              theme,              appearance, -            application: PhantomData,          }      } @@ -68,9 +83,11 @@ where          &self.viewport      } -    /// Returns whether or not the viewport changed. -    pub fn viewport_changed(&self) -> bool { -        self.viewport_changed +    /// Returns the version of the [`Viewport`] of the [`State`]. +    /// +    /// The version is incremented every time the [`Viewport`] changes. +    pub fn viewport_version(&self) -> usize { +        self.viewport_version      }      /// Returns the physical [`Size`] of the [`Viewport`] of the [`State`]. @@ -89,11 +106,16 @@ where      }      /// Returns the current cursor position of the [`State`]. -    pub fn cursor_position(&self) -> Point { -        conversion::cursor_position( -            self.cursor_position, -            self.viewport.scale_factor(), -        ) +    pub fn cursor(&self) -> mouse::Cursor { +        self.cursor_position +            .map(|cursor_position| { +                conversion::cursor_position( +                    cursor_position, +                    self.viewport.scale_factor(), +                ) +            }) +            .map(mouse::Cursor::Available) +            .unwrap_or(mouse::Cursor::Unavailable)      }      /// Returns the current keyboard modifiers of the [`State`]. @@ -102,7 +124,7 @@ where      }      /// Returns the current theme of the [`State`]. -    pub fn theme(&self) -> &<A::Renderer as crate::Renderer>::Theme { +    pub fn theme(&self) -> &<A::Renderer as core::Renderer>::Theme {          &self.theme      } @@ -121,7 +143,7 @@ where          &mut self,          window: &Window,          event: &WindowEvent<'_>, -        _debug: &mut Debug, +        _debug: &mut crate::runtime::Debug,      ) {          match event {              WindowEvent::Resized(new_size) => { @@ -132,7 +154,7 @@ where                      window.scale_factor() * self.scale_factor,                  ); -                self.viewport_changed = true; +                self.viewport_version = self.viewport_version.wrapping_add(1);              }              WindowEvent::ScaleFactorChanged {                  scale_factor: new_scale_factor, @@ -146,18 +168,16 @@ where                      new_scale_factor * self.scale_factor,                  ); -                self.viewport_changed = true; +                self.viewport_version = self.viewport_version.wrapping_add(1);              }              WindowEvent::CursorMoved { position, .. }              | WindowEvent::Touch(Touch {                  location: position, ..              }) => { -                self.cursor_position = *position; +                self.cursor_position = Some(*position);              }              WindowEvent::CursorLeft { .. } => { -                // TODO: Encode cursor availability in the type-system -                self.cursor_position = -                    winit::dpi::PhysicalPosition::new(-1.0, -1.0); +                self.cursor_position = None;              }              WindowEvent::ModifiersChanged(new_modifiers) => {                  self.modifiers = *new_modifiers; @@ -197,16 +217,20 @@ where              self.title = new_title;          } -        // Update scale factor +        // Update scale factor and size          let new_scale_factor = application.scale_factor(window_id); +        let new_size = window.inner_size(); +        let current_size = self.viewport.physical_size(); -        if self.scale_factor != new_scale_factor { -            let size = window.inner_size(); - +        if self.scale_factor != new_scale_factor +            || (current_size.width, current_size.height) +                != (new_size.width, new_size.height) +        {              self.viewport = Viewport::with_physical_size( -                Size::new(size.width, size.height), +                Size::new(new_size.width, new_size.height),                  window.scale_factor() * new_scale_factor,              ); +            self.viewport_version = self.viewport_version.wrapping_add(1);              self.scale_factor = new_scale_factor;          } diff --git a/winit/src/multi_window/windows.rs b/winit/src/multi_window/windows.rs new file mode 100644 index 00000000..7b63defa --- /dev/null +++ b/winit/src/multi_window/windows.rs @@ -0,0 +1,170 @@ +use crate::core::{window, Size}; +use crate::multi_window::{Application, State}; +use iced_graphics::Compositor; +use iced_style::application::StyleSheet; +use std::fmt::{Debug, Formatter}; +use winit::monitor::MonitorHandle; + +pub struct Windows<A: Application, C: Compositor> +where +    <A::Renderer as crate::core::Renderer>::Theme: StyleSheet, +    C: Compositor<Renderer = A::Renderer>, +{ +    pub ids: Vec<window::Id>, +    pub raw: Vec<winit::window::Window>, +    pub states: Vec<State<A>>, +    pub viewport_versions: Vec<usize>, +    pub surfaces: Vec<C::Surface>, +    pub renderers: Vec<A::Renderer>, +    pub pending_destroy: Vec<(window::Id, winit::window::WindowId)>, +} + +impl<A: Application, C: Compositor> Debug for Windows<A, C> +where +    <A::Renderer as crate::core::Renderer>::Theme: StyleSheet, +    C: Compositor<Renderer = A::Renderer>, +{ +    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { +        f.debug_struct("Windows") +            .field("ids", &self.ids) +            .field( +                "raw", +                &self +                    .raw +                    .iter() +                    .map(|raw| raw.id()) +                    .collect::<Vec<winit::window::WindowId>>(), +            ) +            .field("states", &self.states) +            .field("viewport_versions", &self.viewport_versions) +            .finish() +    } +} + +impl<A: Application, C: Compositor> Windows<A, C> +where +    <A::Renderer as crate::core::Renderer>::Theme: StyleSheet, +    C: Compositor<Renderer = A::Renderer>, +{ +    /// Creates a new [`Windows`] with a single `window::Id::MAIN` window. +    pub fn new( +        application: &A, +        compositor: &mut C, +        renderer: A::Renderer, +        main: winit::window::Window, +    ) -> Self { +        let state = State::new(application, window::Id::MAIN, &main); +        let viewport_version = state.viewport_version(); +        let physical_size = state.physical_size(); +        let surface = compositor.create_surface( +            &main, +            physical_size.width, +            physical_size.height, +        ); + +        Self { +            ids: vec![window::Id::MAIN], +            raw: vec![main], +            states: vec![state], +            viewport_versions: vec![viewport_version], +            surfaces: vec![surface], +            renderers: vec![renderer], +            pending_destroy: vec![], +        } +    } + +    /// Adds a new window to [`Windows`]. Returns the size of the newly created window in logical +    /// pixels & the index of the window within [`Windows`]. +    pub fn add( +        &mut self, +        application: &A, +        compositor: &mut C, +        id: window::Id, +        window: winit::window::Window, +    ) -> (Size, usize) { +        let state = State::new(application, id, &window); +        let window_size = state.logical_size(); +        let viewport_version = state.viewport_version(); +        let physical_size = state.physical_size(); +        let surface = compositor.create_surface( +            &window, +            physical_size.width, +            physical_size.height, +        ); +        let renderer = compositor.renderer(); + +        self.ids.push(id); +        self.raw.push(window); +        self.states.push(state); +        self.viewport_versions.push(viewport_version); +        self.surfaces.push(surface); +        self.renderers.push(renderer); + +        (window_size, self.ids.len() - 1) +    } + +    pub fn is_empty(&self) -> bool { +        self.ids.is_empty() +    } + +    pub fn main(&self) -> &winit::window::Window { +        &self.raw[0] +    } + +    pub fn index_from_raw(&self, id: winit::window::WindowId) -> usize { +        self.raw +            .iter() +            .position(|window| window.id() == id) +            .expect("No raw window in multi_window::Windows") +    } + +    pub fn index_from_id(&self, id: window::Id) -> usize { +        self.ids +            .iter() +            .position(|window_id| *window_id == id) +            .expect("No window in multi_window::Windows") +    } + +    pub fn last_monitor(&self) -> Option<MonitorHandle> { +        self.raw.last().and_then(|w| w.current_monitor()) +    } + +    pub fn last(&self) -> usize { +        self.ids.len() - 1 +    } + +    pub fn with_raw(&self, id: window::Id) -> &winit::window::Window { +        let i = self.index_from_id(id); +        &self.raw[i] +    } + +    /// Deletes the window with `id` from [`Windows`]. Returns the index that the window had. +    pub fn delete(&mut self, id: window::Id) -> usize { +        let i = self.index_from_id(id); + +        let id = self.ids.remove(i); +        let window = self.raw.remove(i); +        let _ = self.states.remove(i); +        let _ = self.viewport_versions.remove(i); +        let _ = self.surfaces.remove(i); + +        self.pending_destroy.push((id, window.id())); + +        i +    } + +    /// Gets the winit `window` that is pending to be destroyed if it exists. +    pub fn get_pending_destroy( +        &mut self, +        window: winit::window::WindowId, +    ) -> window::Id { +        let i = self +            .pending_destroy +            .iter() +            .position(|(_, window_id)| window == *window_id) +            .unwrap(); + +        let (id, _) = self.pending_destroy.remove(i); +        id +    } +} diff --git a/winit/src/profiler.rs b/winit/src/profiler.rs deleted file mode 100644 index 7031507a..00000000 --- a/winit/src/profiler.rs +++ /dev/null @@ -1,101 +0,0 @@ -//! A simple profiler for Iced. -use std::ffi::OsStr; -use std::path::Path; -use std::time::Duration; -use tracing_subscriber::prelude::*; -use tracing_subscriber::Registry; -#[cfg(feature = "chrome-trace")] -use { -    tracing_chrome::FlushGuard, -    tracing_subscriber::fmt::{format::DefaultFields, FormattedFields}, -}; - -/// Profiler state. This will likely need to be updated or reworked when adding new tracing backends. -#[allow(missing_debug_implementations)] -pub struct Profiler { -    #[cfg(feature = "chrome-trace")] -    /// [`FlushGuard`] must not be dropped until the application scope is dropped for accurate tracing. -    _guard: FlushGuard, -} - -impl Profiler { -    /// Initializes the [`Profiler`]. -    pub fn init() -> Self { -        // Registry stores the spans & generates unique span IDs -        let subscriber = Registry::default(); - -        let default_path = Path::new(env!("CARGO_MANIFEST_DIR")); -        let curr_exe = std::env::current_exe() -            .unwrap_or_else(|_| default_path.to_path_buf()); -        let out_dir = curr_exe.parent().unwrap_or(default_path).join("traces"); - -        #[cfg(feature = "chrome-trace")] -        let (chrome_layer, guard) = { -            let mut layer = tracing_chrome::ChromeLayerBuilder::new(); - -            // Optional configurable env var: CHROME_TRACE_FILE=/path/to/trace_file/file.json, -            // for uploading to chrome://tracing (old) or ui.perfetto.dev (new). -            if let Ok(path) = std::env::var("CHROME_TRACE_FILE") { -                layer = layer.file(path); -            } else if std::fs::create_dir_all(&out_dir).is_ok() { -                let time = std::time::SystemTime::now() -                    .duration_since(std::time::UNIX_EPOCH) -                    .unwrap_or(Duration::from_millis(0)) -                    .as_millis(); - -                let curr_exe_name = curr_exe -                    .file_name() -                    .unwrap_or_else(|| OsStr::new("trace")) -                    .to_str() -                    .unwrap_or("trace"); - -                let path = -                    out_dir.join(format!("{curr_exe_name}_trace_{time}.json")); - -                layer = layer.file(path); -            } else { -                layer = layer.file(env!("CARGO_MANIFEST_DIR")) -            } - -            let (chrome_layer, guard) = layer -                .name_fn(Box::new(|event_or_span| match event_or_span { -                    tracing_chrome::EventOrSpan::Event(event) => { -                        event.metadata().name().into() -                    } -                    tracing_chrome::EventOrSpan::Span(span) => { -                        if let Some(fields) = span -                            .extensions() -                            .get::<FormattedFields<DefaultFields>>() -                        { -                            format!( -                                "{}: {}", -                                span.metadata().name(), -                                fields.fields.as_str() -                            ) -                        } else { -                            span.metadata().name().into() -                        } -                    } -                })) -                .build(); - -            (chrome_layer, guard) -        }; - -        let fmt_layer = tracing_subscriber::fmt::Layer::default(); -        let subscriber = subscriber.with(fmt_layer); - -        #[cfg(feature = "chrome-trace")] -        let subscriber = subscriber.with(chrome_layer); - -        // create dispatcher which will forward span events to the subscriber -        // this can only be set once or will panic -        tracing::subscriber::set_global_default(subscriber) -            .expect("Tracer could not set the global default subscriber."); - -        Profiler { -            #[cfg(feature = "chrome-trace")] -            _guard: guard, -        } -    } -} diff --git a/winit/src/settings.rs b/winit/src/settings.rs index 40b3d487..2b846fbd 100644 --- a/winit/src/settings.rs +++ b/winit/src/settings.rs @@ -1,35 +1,10 @@  //! Configure your application. -#[cfg(target_os = "windows")] -#[path = "settings/windows.rs"] -mod platform; - -#[cfg(target_os = "macos")] -#[path = "settings/macos.rs"] -mod platform; - -#[cfg(target_arch = "wasm32")] -#[path = "settings/wasm.rs"] -mod platform; - -#[cfg(not(any( -    target_os = "windows", -    target_os = "macos", -    target_arch = "wasm32" -)))] -#[path = "settings/other.rs"] -mod platform; - -pub use platform::PlatformSpecific; -  use crate::conversion; -use crate::core::window::{Icon, Level}; -use crate::Position; +use crate::core::window;  use winit::monitor::MonitorHandle;  use winit::window::WindowBuilder; -use std::fmt; -  /// The settings of an application.  #[derive(Debug, Clone, Default)]  pub struct Settings<Flags> { @@ -40,7 +15,7 @@ pub struct Settings<Flags> {      pub id: Option<String>,      /// The [`Window`] settings. -    pub window: Window, +    pub window: window::Settings,      /// The data needed to initialize an [`Application`].      /// @@ -50,166 +25,93 @@ pub struct Settings<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,  } -/// The window settings of an application. -#[derive(Clone)] -pub struct Window { -    /// The size of the window. -    pub size: (u32, u32), - -    /// The position of the window. -    pub position: Position, - -    /// The minimum size of the window. -    pub min_size: Option<(u32, u32)>, - -    /// The maximum size of the window. -    pub max_size: Option<(u32, u32)>, - -    /// Whether the window should be visible or not. -    pub visible: bool, - -    /// Whether the window should be resizable or not. -    pub resizable: bool, - -    /// Whether the window should have a border, a title bar, etc. -    pub decorations: bool, - -    /// Whether the window should be transparent. -    pub transparent: bool, - -    /// The window [`Level`]. -    pub level: Level, - -    /// The window icon, which is also usually used in the taskbar -    pub icon: Option<Icon>, - -    /// Platform specific settings. -    pub platform_specific: platform::PlatformSpecific, -} - -impl fmt::Debug for Window { -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -        f.debug_struct("Window") -            .field("size", &self.size) -            .field("position", &self.position) -            .field("min_size", &self.min_size) -            .field("max_size", &self.max_size) -            .field("visible", &self.visible) -            .field("resizable", &self.resizable) -            .field("decorations", &self.decorations) -            .field("transparent", &self.transparent) -            .field("level", &self.level) -            .field("icon", &self.icon.is_some()) -            .field("platform_specific", &self.platform_specific) -            .finish() +/// Converts the window settings into a `WindowBuilder` from `winit`. +pub fn window_builder( +    settings: window::Settings, +    title: &str, +    monitor: Option<MonitorHandle>, +    _id: Option<String>, +) -> WindowBuilder { +    let mut window_builder = WindowBuilder::new(); + +    let (width, height) = settings.size; + +    window_builder = window_builder +        .with_title(title) +        .with_inner_size(winit::dpi::LogicalSize { width, height }) +        .with_resizable(settings.resizable) +        .with_decorations(settings.decorations) +        .with_transparent(settings.transparent) +        .with_window_icon(settings.icon.and_then(conversion::icon)) +        .with_window_level(conversion::window_level(settings.level)) +        .with_visible(settings.visible); + +    if let Some(position) = +        conversion::position(monitor.as_ref(), settings.size, settings.position) +    { +        window_builder = window_builder.with_position(position);      } -} - -impl Window { -    /// Converts the window settings into a `WindowBuilder` from `winit`. -    pub fn into_builder( -        self, -        title: &str, -        primary_monitor: Option<MonitorHandle>, -        _id: Option<String>, -    ) -> WindowBuilder { -        let mut window_builder = WindowBuilder::new(); - -        let (width, height) = self.size; +    if let Some((width, height)) = settings.min_size {          window_builder = window_builder -            .with_title(title) -            .with_inner_size(winit::dpi::LogicalSize { width, height }) -            .with_resizable(self.resizable) -            .with_decorations(self.decorations) -            .with_transparent(self.transparent) -            .with_window_icon(self.icon.and_then(conversion::icon)) -            .with_window_level(conversion::window_level(self.level)) -            .with_visible(self.visible); - -        if let Some(position) = conversion::position( -            primary_monitor.as_ref(), -            self.size, -            self.position, -        ) { -            window_builder = window_builder.with_position(position); -        } - -        if let Some((width, height)) = self.min_size { -            window_builder = window_builder -                .with_min_inner_size(winit::dpi::LogicalSize { width, height }); -        } +            .with_min_inner_size(winit::dpi::LogicalSize { width, height }); +    } -        if let Some((width, height)) = self.max_size { -            window_builder = window_builder -                .with_max_inner_size(winit::dpi::LogicalSize { width, height }); -        } +    if let Some((width, height)) = settings.max_size { +        window_builder = window_builder +            .with_max_inner_size(winit::dpi::LogicalSize { width, height }); +    } -        #[cfg(any( -            target_os = "linux", -            target_os = "dragonfly", -            target_os = "freebsd", -            target_os = "netbsd", -            target_os = "openbsd" -        ))] -        { -            // `with_name` is available on both `WindowBuilderExtWayland` and `WindowBuilderExtX11` and they do -            // exactly the same thing. We arbitrarily choose `WindowBuilderExtWayland` here. -            use ::winit::platform::wayland::WindowBuilderExtWayland; - -            if let Some(id) = _id { -                window_builder = window_builder.with_name(id.clone(), id); -            } +    #[cfg(any( +        target_os = "linux", +        target_os = "dragonfly", +        target_os = "freebsd", +        target_os = "netbsd", +        target_os = "openbsd" +    ))] +    { +        // `with_name` is available on both `WindowBuilderExtWayland` and `WindowBuilderExtX11` and they do +        // exactly the same thing. We arbitrarily choose `WindowBuilderExtWayland` here. +        use ::winit::platform::wayland::WindowBuilderExtWayland; + +        if let Some(id) = _id { +            window_builder = window_builder.with_name(id.clone(), id);          } +    } -        #[cfg(target_os = "windows")] -        { -            use winit::platform::windows::WindowBuilderExtWindows; -            #[allow(unsafe_code)] -            unsafe { -                window_builder = window_builder -                    .with_parent_window(self.platform_specific.parent); -            } +    #[cfg(target_os = "windows")] +    { +        use winit::platform::windows::WindowBuilderExtWindows; +        #[allow(unsafe_code)] +        unsafe {              window_builder = window_builder -                .with_drag_and_drop(self.platform_specific.drag_and_drop); +                .with_parent_window(settings.platform_specific.parent);          } +        window_builder = window_builder +            .with_drag_and_drop(settings.platform_specific.drag_and_drop); +    } -        #[cfg(target_os = "macos")] -        { -            use winit::platform::macos::WindowBuilderExtMacOS; - -            window_builder = window_builder -                .with_title_hidden(self.platform_specific.title_hidden) -                .with_titlebar_transparent( -                    self.platform_specific.titlebar_transparent, -                ) -                .with_fullsize_content_view( -                    self.platform_specific.fullsize_content_view, -                ); -        } +    #[cfg(target_os = "macos")] +    { +        use winit::platform::macos::WindowBuilderExtMacOS; -        window_builder +        window_builder = window_builder +            .with_title_hidden(settings.platform_specific.title_hidden) +            .with_titlebar_transparent( +                settings.platform_specific.titlebar_transparent, +            ) +            .with_fullsize_content_view( +                settings.platform_specific.fullsize_content_view, +            );      } -} -impl Default for Window { -    fn default() -> Window { -        Window { -            size: (1024, 768), -            position: Position::default(), -            min_size: None, -            max_size: None, -            visible: true, -            resizable: true, -            decorations: true, -            transparent: false, -            level: Level::default(), -            icon: None, -            platform_specific: Default::default(), -        } -    } +    window_builder  } diff --git a/winit/src/window.rs b/winit/src/window.rs deleted file mode 100644 index e69de29b..00000000 --- a/winit/src/window.rs +++ /dev/null  | 
