diff options
Diffstat (limited to '')
| -rw-r--r-- | Cargo.toml | 4 | ||||
| -rw-r--r-- | examples/integration_opengl/src/main.rs | 8 | ||||
| -rw-r--r-- | glutin/Cargo.toml | 10 | ||||
| -rw-r--r-- | glutin/src/application.rs | 364 | ||||
| -rw-r--r-- | glutin/src/lib.rs | 3 | ||||
| -rw-r--r-- | glutin/src/multi_window.rs | 1060 | ||||
| -rw-r--r-- | graphics/src/window/gl_compositor.rs | 2 | ||||
| -rw-r--r-- | native/src/window/id.rs | 4 | ||||
| -rw-r--r-- | src/lib.rs | 2 | ||||
| -rw-r--r-- | winit/src/application.rs | 2 | ||||
| -rw-r--r-- | winit/src/multi_window.rs | 25 | ||||
| -rw-r--r-- | winit/src/multi_window/state.rs | 7 | ||||
| -rw-r--r-- | winit/src/profiler.rs | 1 | ||||
| -rw-r--r-- | winit/src/settings.rs | 8 | ||||
| -rw-r--r-- | winit/src/settings/windows.rs | 4 | 
15 files changed, 129 insertions, 1375 deletions
@@ -46,8 +46,8 @@ chrome-trace = [      "iced_wgpu?/tracing",      "iced_glow?/tracing",  ] -# Enables experimental multi-window support -multi_window = ["iced_winit/multi_window", "iced_glutin?/multi_window"] +# Enables experimental multi-window support for iced_winit +multi_window = ["iced_winit/multi_window"]  [badges]  maintenance = { status = "actively-developed" } diff --git a/examples/integration_opengl/src/main.rs b/examples/integration_opengl/src/main.rs index fdbd7369..4dd3a4a9 100644 --- a/examples/integration_opengl/src/main.rs +++ b/examples/integration_opengl/src/main.rs @@ -13,7 +13,6 @@ use iced_glow::{Backend, Renderer, Settings, Viewport};  use iced_glutin::conversion;  use iced_glutin::glutin;  use iced_glutin::renderer; -use iced_glutin::window;  use iced_glutin::{program, Clipboard, Color, Debug, Size};  pub fn main() { @@ -31,8 +30,7 @@ pub fn main() {              .unwrap();          unsafe { -            let windowed_context = -                windowed_context.make_current(todo!("derezzedex")).unwrap(); +            let windowed_context = windowed_context.make_current().unwrap();              let gl = glow::Context::from_loader_function(|s| {                  windowed_context.get_proc_address(s) as *const _ @@ -109,7 +107,7 @@ pub fn main() {                  // Map window event to iced event                  if let Some(event) = iced_winit::conversion::window_event( -                    window::Id::MAIN, +                    iced_winit::window::Id::MAIN,                      &event,                      windowed_context.window().scale_factor(),                      modifiers, @@ -182,7 +180,7 @@ pub fn main() {                      ),                  ); -                windowed_context.swap_buffers(todo!("derezzedex")).unwrap(); +                windowed_context.swap_buffers().unwrap();              }              _ => (),          } diff --git a/glutin/Cargo.toml b/glutin/Cargo.toml index 01dd3748..10d3778b 100644 --- a/glutin/Cargo.toml +++ b/glutin/Cargo.toml @@ -11,19 +11,17 @@ keywords = ["gui", "ui", "graphics", "interface", "widgets"]  categories = ["gui"]  [features] -trace = ["iced_winit/trace", "tracing"] +trace = ["iced_winit/trace"]  debug = ["iced_winit/debug"]  system = ["iced_winit/system"] -multi_window = ["iced_winit/multi_window"] - -[dependencies.raw-window-handle] -version = "0.5.0"  [dependencies]  log = "0.4"  [dependencies.glutin] -version = "0.30" +version = "0.29" +git = "https://github.com/iced-rs/glutin" +rev = "da8d291486b4c9bec12487a46c119c4b1d386abf"  [dependencies.iced_native]  version = "0.9" diff --git a/glutin/src/application.rs b/glutin/src/application.rs index c0a8cda4..24f38e7b 100644 --- a/glutin/src/application.rs +++ b/glutin/src/application.rs @@ -13,33 +13,14 @@ use iced_winit::futures::channel::mpsc;  use iced_winit::renderer;  use iced_winit::time::Instant;  use iced_winit::user_interface; -use iced_winit::winit;  use iced_winit::{Clipboard, Command, Debug, Event, Proxy, Settings}; -use glutin::config::{ -    Config, ConfigSurfaceTypes, ConfigTemplateBuilder, GlConfig, -}; -use glutin::context::{ -    ContextApi, ContextAttributesBuilder, NotCurrentContext, -    NotCurrentGlContextSurfaceAccessor, -    PossiblyCurrentContextGlSurfaceAccessor, PossiblyCurrentGlContext, -}; -use glutin::display::{Display, DisplayApiPreference, GlDisplay}; -use glutin::surface::{ -    GlSurface, Surface, SurfaceAttributesBuilder, WindowSurface, -}; -use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; - -use std::ffi::CString; +use glutin::window::Window;  use std::mem::ManuallyDrop; -use std::num::NonZeroU32; -#[cfg(feature = "trace")] +#[cfg(feature = "tracing")]  use tracing::{info_span, instrument::Instrument}; -#[allow(unsafe_code)] -const ONE: NonZeroU32 = unsafe { NonZeroU32::new_unchecked(1) }; -  /// Runs an [`Application`] with an executor, compositor, and the provided  /// settings.  pub fn run<A, E, C>( @@ -54,8 +35,9 @@ where  {      use futures::task;      use futures::Future; -    use winit::event_loop::EventLoopBuilder; -    use winit::platform::run_return::EventLoopExtRunReturn; +    use glutin::event_loop::EventLoopBuilder; +    use glutin::platform::run_return::EventLoopExtRunReturn; +    use glutin::ContextBuilder;      #[cfg(feature = "trace")]      let _guard = iced_winit::Profiler::init(); @@ -63,7 +45,7 @@ where      let mut debug = Debug::new();      debug.startup_started(); -    #[cfg(feature = "trace")] +    #[cfg(feature = "tracing")]      let _ = info_span!("Application::Glutin", "RUN").entered();      let mut event_loop = EventLoopBuilder::with_user_event().build(); @@ -82,205 +64,74 @@ where          runtime.enter(|| A::new(flags))      }; -    let builder = settings.window.into_builder( -        &application.title(), -        event_loop.primary_monitor(), -        settings.id, -    ); - -    log::debug!("Window builder: {:#?}", builder); - -    #[allow(unsafe_code)] -    let (display, window, surface, context) = unsafe { -        struct Configuration(Config); -        use std::fmt; -        impl fmt::Debug for Configuration { -            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -                let config = &self.0; - -                f.debug_struct("Configuration") -                    .field("raw", &config) -                    .field("samples", &config.num_samples()) -                    .field("buffer_type", &config.color_buffer_type()) -                    .field("surface_type", &config.config_surface_types()) -                    .field("depth", &config.depth_size()) -                    .field("alpha", &config.alpha_size()) -                    .field("stencil", &config.stencil_size()) -                    .field("float_pixels", &config.float_pixels()) -                    .field("srgb", &config.srgb_capable()) -                    .field("api", &config.api()) -                    .finish() -            } -        } - -        impl AsRef<Config> for Configuration { -            fn as_ref(&self) -> &Config { -                &self.0 -            } -        } - -        let display_handle = event_loop.raw_display_handle(); - -        #[cfg(all( -            any(windows, target_os = "macos"), -            not(target_arch = "wasm32") -        ))] -        let (window, window_handle) = { -            let window = builder -                .build(&event_loop) -                .map_err(Error::WindowCreationFailed)?; - -            let handle = window.raw_window_handle(); - -            (window, handle) -        }; - -        #[cfg(target_arch = "wasm32")] -        let preference = Err(Error::GraphicsCreationFailed( -            iced_graphics::Error::BackendError(format!( -                "target not supported by backend" -            )), -        ))?; - -        #[cfg(all(windows, not(target_arch = "wasm32")))] -        let preference = DisplayApiPreference::WglThenEgl(Some(window_handle)); - -        #[cfg(all(target_os = "macos", not(target_arch = "wasm32")))] -        let preference = DisplayApiPreference::Cgl; - -        #[cfg(all( -            unix, -            not(target_os = "macos"), -            not(target_arch = "wasm32") -        ))] -        let preference = DisplayApiPreference::GlxThenEgl(Box::new( -            winit::platform::unix::register_xlib_error_hook, -        )); - -        let display = -            Display::new(display_handle, preference).map_err(|error| { -                Error::GraphicsCreationFailed( -                    iced_graphics::Error::BackendError(format!( -                        "failed to create display: {error}" -                    )), -                ) -            })?; +    let context = { +        let builder = settings.window.into_builder( +            &application.title(), +            event_loop.primary_monitor(), +            settings.id, +        ); -        log::debug!("Display: {}", display.version_string()); +        log::debug!("Window builder: {:#?}", builder); -        let samples = C::sample_count(&compositor_settings) as u8; -        let mut template = ConfigTemplateBuilder::new() -            .with_surface_type(ConfigSurfaceTypes::WINDOW); +        let opengl_builder = ContextBuilder::new() +            .with_vsync(true) +            .with_multisampling(C::sample_count(&compositor_settings) as u16); -        if samples != 0 { -            template = template.with_multisampling(samples); -        } +        let opengles_builder = opengl_builder.clone().with_gl( +            glutin::GlRequest::Specific(glutin::Api::OpenGlEs, (2, 0)), +        ); -        #[cfg(all(windows, not(target_arch = "wasm32")))] -        let template = template.compatible_with_native_window(window_handle); - -        log::debug!("Searching for display configurations"); -        let configuration = display -            .find_configs(template.build()) -            .map_err(|_| { -                Error::GraphicsCreationFailed( -                    iced_graphics::Error::NoAvailablePixelFormat, -                ) -            })? -            .map(Configuration) -            .inspect(|config| { -                log::trace!("{config:#?}"); -            }) -            .min_by_key(|config| { -                config.as_ref().num_samples().saturating_sub(samples) -            }) -            .ok_or(Error::GraphicsCreationFailed( -                iced_graphics::Error::NoAvailablePixelFormat, -            ))?; - -        log::debug!("Selected: {configuration:#?}"); - -        #[cfg(all( -            unix, -            not(target_os = "macos"), -            not(target_arch = "wasm32") -        ))] -        let (window, window_handle) = { -            use glutin::platform::x11::X11GlConfigExt; -            let builder = -                if let Some(visual) = configuration.as_ref().x11_visual() { -                    use winit::platform::unix::WindowBuilderExtUnix; -                    builder.with_x11_visual(visual.into_raw()) -                } else { -                    builder -                }; - -            let window = builder -                .build(&event_loop) -                .map_err(Error::WindowCreationFailed)?; - -            let handle = window.raw_window_handle(); - -            (window, handle) +        let (first_builder, second_builder) = if settings.try_opengles_first { +            (opengles_builder, opengl_builder) +        } else { +            (opengl_builder, opengles_builder)          }; -        let attributes = -            ContextAttributesBuilder::new().build(Some(window_handle)); -        let fallback_attributes = ContextAttributesBuilder::new() -            .with_context_api(ContextApi::Gles(None)) -            .build(Some(window_handle)); +        log::info!("Trying first builder: {:#?}", first_builder); -        let context = display -            .create_context(configuration.as_ref(), &attributes) +        let context = first_builder +            .build_windowed(builder.clone(), &event_loop)              .or_else(|_| { -                display.create_context( -                    configuration.as_ref(), -                    &fallback_attributes, -                ) +                log::info!("Trying second builder: {:#?}", second_builder); +                second_builder.build_windowed(builder, &event_loop)              })              .map_err(|error| { -                Error::GraphicsCreationFailed( -                    iced_graphics::Error::BackendError(format!( -                        "failed to create context: {error}" -                    )), -                ) -            })?; +                use glutin::CreationError; +                use iced_graphics::Error as ContextError; -        let surface = gl_surface(&display, configuration.as_ref(), &window) -            .map_err(|error| { -                Error::GraphicsCreationFailed( -                    iced_graphics::Error::BackendError(format!( -                        "failed to create surface: {error}" -                    )), -                ) +                match error { +                    CreationError::Window(error) => { +                        Error::WindowCreationFailed(error) +                    } +                    CreationError::OpenGlVersionNotSupported => { +                        Error::GraphicsCreationFailed( +                            ContextError::VersionNotSupported, +                        ) +                    } +                    CreationError::NoAvailablePixelFormat => { +                        Error::GraphicsCreationFailed( +                            ContextError::NoAvailablePixelFormat, +                        ) +                    } +                    error => Error::GraphicsCreationFailed( +                        ContextError::BackendError(error.to_string()), +                    ), +                }              })?; -        let context = { -            context -                .make_current(&surface) -                .expect("make context current") -        }; - -        if let Err(error) = surface.set_swap_interval( -            &context, -            glutin::surface::SwapInterval::Wait(ONE), -        ) { -            log::error!("set swap interval failed: {}", error); +        #[allow(unsafe_code)] +        unsafe { +            context.make_current().expect("Make OpenGL context current")          } - -        (display, window, surface, context)      };      #[allow(unsafe_code)]      let (compositor, renderer) = unsafe {          C::new(compositor_settings, |address| { -            let address = CString::new(address).expect("address error"); -            display.get_proc_address(address.as_c_str()) +            context.get_proc_address(address)          })?      }; -    let context = { context.make_not_current().expect("make context current") }; -      let (mut event_sender, event_receiver) = mpsc::unbounded();      let (control_sender, mut control_receiver) = mpsc::unbounded(); @@ -294,14 +145,12 @@ where              debug,              event_receiver,              control_sender, -            window, -            surface,              context,              init_command,              settings.exit_on_close_request,          ); -        #[cfg(feature = "trace")] +        #[cfg(feature = "tracing")]          let run_instance =              run_instance.instrument(info_span!("Application", "LOOP")); @@ -311,22 +160,22 @@ where      let mut context = task::Context::from_waker(task::noop_waker_ref());      let _ = event_loop.run_return(move |event, _, control_flow| { -        use winit::event_loop::ControlFlow; +        use glutin::event_loop::ControlFlow;          if let ControlFlow::ExitWithCode(_) = control_flow {              return;          }          let event = match event { -            winit::event::Event::WindowEvent { +            glutin::event::Event::WindowEvent {                  event: -                    winit::event::WindowEvent::ScaleFactorChanged { +                    glutin::event::WindowEvent::ScaleFactorChanged {                          new_inner_size,                          ..                      },                  window_id, -            } => Some(winit::event::Event::WindowEvent { -                event: winit::event::WindowEvent::Resized(*new_inner_size), +            } => Some(glutin::event::Event::WindowEvent { +                event: glutin::event::WindowEvent::Resized(*new_inner_size),                  window_id,              }),              _ => event.to_static(), @@ -358,13 +207,13 @@ async fn run_instance<A, E, C>(      mut compositor: C,      mut renderer: A::Renderer,      mut runtime: Runtime<E, Proxy<A::Message>, A::Message>, -    mut proxy: winit::event_loop::EventLoopProxy<A::Message>, +    mut proxy: glutin::event_loop::EventLoopProxy<A::Message>,      mut debug: Debug, -    mut event_receiver: mpsc::UnboundedReceiver<winit::event::Event<'_, A::Message>, >, -    mut control_sender: mpsc::UnboundedSender<winit::event_loop::ControlFlow>, -    window: winit::window::Window, -    surface: Surface<WindowSurface>, -    context: NotCurrentContext, +    mut event_receiver: mpsc::UnboundedReceiver< +        glutin::event::Event<'_, A::Message>, +    >, +    mut control_sender: mpsc::UnboundedSender<glutin::event_loop::ControlFlow>, +    mut context: glutin::ContextWrapper<glutin::PossiblyCurrent, Window>,      init_command: Command<A::Message>,      exit_on_close_request: bool,  ) where @@ -373,19 +222,13 @@ async fn run_instance<A, E, C>(      C: window::GLCompositor<Renderer = A::Renderer> + 'static,      <A::Renderer as iced_native::Renderer>::Theme: StyleSheet,  { +    use glutin::event; +    use glutin::event_loop::ControlFlow;      use iced_winit::futures::stream::StreamExt; -    use winit::event_loop::ControlFlow; -    use winit::event; -    let context = { -        context -            .make_current(&surface) -            .expect("make context current") -    }; - -    let mut clipboard = Clipboard::connect(&window); +    let mut clipboard = Clipboard::connect(context.window());      let mut cache = user_interface::Cache::default(); -    let mut state = application::State::new(&application, &window); +    let mut state = application::State::new(&application, context.window());      let mut viewport_version = state.viewport_version();      let mut should_exit = false; @@ -400,7 +243,7 @@ async fn run_instance<A, E, C>(          &mut should_exit,          &mut proxy,          &mut debug, -        &window, +        context.window(),          || compositor.fetch_information(),      );      runtime.track(application.subscription()); @@ -473,12 +316,12 @@ async fn run_instance<A, E, C>(                          &mut proxy,                          &mut debug,                          &mut messages, -                        &window, +                        context.window(),                          || compositor.fetch_information(),                      );                      // Update window -                    state.synchronize(&application, &window); +                    state.synchronize(&application, context.window());                      user_interface =                          ManuallyDrop::new(application::build_user_interface( @@ -524,15 +367,16 @@ async fn run_instance<A, E, C>(                  debug.draw_finished();                  if new_mouse_interaction != mouse_interaction { -                    window.set_cursor_icon(conversion::mouse_interaction( -                        new_mouse_interaction, -                    )); +                    context.window().set_cursor_icon( +                        conversion::mouse_interaction(new_mouse_interaction), +                    );                      mouse_interaction = new_mouse_interaction;                  } -                window.request_redraw(); -                runtime.broadcast((redraw_event, crate::event::Status::Ignored)); +                context.window().request_redraw(); +                runtime +                    .broadcast((redraw_event, crate::event::Status::Ignored));                  let _ = control_sender.start_send(match interface_state {                      user_interface::State::Updated { @@ -564,15 +408,18 @@ async fn run_instance<A, E, C>(                  messages.push(message);              }              event::Event::RedrawRequested(_) => { -                #[cfg(feature = "trace")] +                #[cfg(feature = "tracing")]                  let _ = info_span!("Application", "FRAME").entered();                  debug.render_started(); -                if !context.is_current() { -                    context -                        .make_current(&surface) -                        .expect("Make OpenGL context current"); +                #[allow(unsafe_code)] +                unsafe { +                    if !context.is_current() { +                        context = context +                            .make_current() +                            .expect("Make OpenGL context current"); +                    }                  }                  let current_viewport_version = state.viewport_version(); @@ -600,18 +447,19 @@ async fn run_instance<A, E, C>(                      debug.draw_finished();                      if new_mouse_interaction != mouse_interaction { -                        window.set_cursor_icon(conversion::mouse_interaction( -                            new_mouse_interaction, -                        )); +                        context.window().set_cursor_icon( +                            conversion::mouse_interaction( +                                new_mouse_interaction, +                            ), +                        );                          mouse_interaction = new_mouse_interaction;                      } -                    surface.resize( -                        &context, -                        NonZeroU32::new(physical_size.width).unwrap_or(ONE), -                        NonZeroU32::new(physical_size.height).unwrap_or(ONE), -                    ); +                    context.resize(glutin::dpi::PhysicalSize::new( +                        physical_size.width, +                        physical_size.height, +                    ));                      compositor.resize_viewport(physical_size); @@ -625,7 +473,7 @@ async fn run_instance<A, E, C>(                      &debug.overlay(),                  ); -                surface.swap_buffers(&context).expect("Swap buffers"); +                context.swap_buffers().expect("Swap buffers");                  debug.render_finished(); @@ -642,7 +490,7 @@ async fn run_instance<A, E, C>(                      break;                  } -                state.update(&window, &window_event, &mut debug); +                state.update(context.window(), &window_event, &mut debug);                  if let Some(event) = conversion::window_event(                      crate::window::Id::MAIN, @@ -660,23 +508,3 @@ async fn run_instance<A, E, C>(      // Manually drop the user interface      drop(ManuallyDrop::into_inner(user_interface));  } - -#[allow(unsafe_code)] -/// Creates a new [`glutin::Surface<WindowSurface>`]. -pub fn gl_surface( -    display: &Display, -    gl_config: &Config, -    window: &winit::window::Window, -) -> Result<Surface<WindowSurface>, glutin::error::Error> { -    let (width, height) = window.inner_size().into(); - -    let surface_attributes = SurfaceAttributesBuilder::<WindowSurface>::new() -        .with_srgb(Some(true)) -        .build( -            window.raw_window_handle(), -            NonZeroU32::new(width).unwrap_or(ONE), -            NonZeroU32::new(height).unwrap_or(ONE), -        ); - -    unsafe { display.create_window_surface(gl_config, &surface_attributes) } -} diff --git a/glutin/src/lib.rs b/glutin/src/lib.rs index 45d6cb5b..33afd664 100644 --- a/glutin/src/lib.rs +++ b/glutin/src/lib.rs @@ -29,8 +29,5 @@ pub use iced_winit::*;  pub mod application; -#[cfg(feature = "multi_window")] -pub mod multi_window; -  #[doc(no_inline)]  pub use application::Application; diff --git a/glutin/src/multi_window.rs b/glutin/src/multi_window.rs deleted file mode 100644 index 620d01d8..00000000 --- a/glutin/src/multi_window.rs +++ /dev/null @@ -1,1060 +0,0 @@ -//! Create interactive, native cross-platform applications. -use crate::mouse; -use crate::{Error, Executor, Runtime}; - -pub use iced_winit::multi_window::{self, Application, StyleSheet}; - -use iced_winit::conversion; -use iced_winit::futures; -use iced_winit::futures::channel::mpsc; -use iced_winit::renderer; -use iced_winit::user_interface; -use iced_winit::window; -use iced_winit::winit; -use iced_winit::{Clipboard, Command, Debug, Proxy, Settings}; - -use glutin::config::{ -    Config, ConfigSurfaceTypes, ConfigTemplateBuilder, GlConfig, -}; -use glutin::context::{ -    ContextApi, ContextAttributesBuilder, NotCurrentContext, -    NotCurrentGlContextSurfaceAccessor, PossiblyCurrentGlContext, -}; -use glutin::display::{Display, DisplayApiPreference, GlDisplay}; -use glutin::surface::{GlSurface, SwapInterval}; -use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; - -use crate::application::gl_surface; -use iced_winit::multi_window::Event; -use std::collections::HashMap; -use std::ffi::CString; -use std::mem::ManuallyDrop; -use std::num::NonZeroU32; - -use iced_native::widget::operation; -#[cfg(feature = "tracing")] -use tracing::{info_span, instrument::Instrument}; - -#[allow(unsafe_code)] -const ONE: NonZeroU32 = unsafe { NonZeroU32::new_unchecked(1) }; - -/// Runs an [`Application`] with an executor, compositor, and the provided -/// settings. -pub fn run<A, E, C>( -    settings: Settings<A::Flags>, -    compositor_settings: C::Settings, -) -> Result<(), Error> -where -    A: Application + 'static, -    E: Executor + 'static, -    C: iced_graphics::window::GLCompositor<Renderer = A::Renderer> + 'static, -    <A::Renderer as iced_native::Renderer>::Theme: StyleSheet, -{ -    use futures::task; -    use futures::Future; -    use winit::event_loop::EventLoopBuilder; -    use winit::platform::run_return::EventLoopExtRunReturn; - -    #[cfg(feature = "trace")] -    let _guard = iced_winit::Profiler::init(); - -    let mut debug = Debug::new(); -    debug.startup_started(); - -    #[cfg(feature = "tracing")] -    let _ = info_span!("Application::Glutin", "RUN").entered(); - -    let mut event_loop = EventLoopBuilder::with_user_event().build(); -    let proxy = event_loop.create_proxy(); - -    let runtime = { -        let executor = E::new().map_err(Error::ExecutorCreationFailed)?; -        let proxy = Proxy::new(event_loop.create_proxy()); - -        Runtime::new(executor, proxy) -    }; - -    let (application, init_command) = { -        let flags = settings.flags; - -        runtime.enter(|| A::new(flags)) -    }; - -    let builder = settings.window.into_builder( -        &application.title(window::Id::MAIN), -        event_loop.primary_monitor(), -        settings.id, -    ); - -    log::info!("Window builder: {:#?}", builder); - -    #[allow(unsafe_code)] -    let (display, window, configuration, surface, context) = unsafe { -        struct Configuration(Config); -        use std::fmt; -        impl fmt::Debug for Configuration { -            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -                let config = &self.0; - -                f.debug_struct("Configuration") -                    .field("raw", &config) -                    .field("samples", &config.num_samples()) -                    .field("buffer_type", &config.color_buffer_type()) -                    .field("surface_type", &config.config_surface_types()) -                    .field("depth", &config.depth_size()) -                    .field("alpha", &config.alpha_size()) -                    .field("stencil", &config.stencil_size()) -                    .field("float_pixels", &config.float_pixels()) -                    .field("srgb", &config.srgb_capable()) -                    .field("api", &config.api()) -                    .finish() -            } -        } - -        impl AsRef<Config> for Configuration { -            fn as_ref(&self) -> &Config { -                &self.0 -            } -        } - -        let display_handle = event_loop.raw_display_handle(); - -        #[cfg(all( -            any(windows, target_os = "macos"), -            not(target_arch = "wasm32") -        ))] -        let (window, window_handle) = { -            let window = builder -                .build(&event_loop) -                .map_err(Error::WindowCreationFailed)?; - -            let handle = window.raw_window_handle(); - -            (window, handle) -        }; - -        #[cfg(target_arch = "wasm32")] -        let preference = Err(Error::GraphicsCreationFailed( -            iced_graphics::Error::BackendError(format!( -                "target not supported by backend" -            )), -        ))?; - -        #[cfg(all(windows, not(target_arch = "wasm32")))] -        let preference = DisplayApiPreference::WglThenEgl(Some(window_handle)); - -        #[cfg(all(target_os = "macos", not(target_arch = "wasm32")))] -        let preference = DisplayApiPreference::Cgl; - -        #[cfg(all( -            unix, -            not(target_os = "macos"), -            not(target_arch = "wasm32") -        ))] -        let preference = DisplayApiPreference::GlxThenEgl(Box::new( -            winit::platform::unix::register_xlib_error_hook, -        )); - -        let display = -            Display::new(display_handle, preference).map_err(|error| { -                Error::GraphicsCreationFailed( -                    iced_graphics::Error::BackendError(format!( -                        "failed to create display: {error}" -                    )), -                ) -            })?; - -        log::debug!("Display: {}", display.version_string()); - -        let samples = C::sample_count(&compositor_settings) as u8; -        let mut template = ConfigTemplateBuilder::new() -            .with_surface_type(ConfigSurfaceTypes::WINDOW); - -        if samples != 0 { -            template = template.with_multisampling(samples); -        } - -        #[cfg(all(windows, not(target_arch = "wasm32")))] -        let template = template.compatible_with_native_window(window_handle); - -        log::debug!("Searching for display configurations"); -        let configuration = display -            .find_configs(template.build()) -            .map_err(|_| { -                Error::GraphicsCreationFailed( -                    iced_graphics::Error::NoAvailablePixelFormat, -                ) -            })? -            .map(Configuration) -            .inspect(|config| { -                log::trace!("{config:#?}"); -            }) -            .min_by_key(|config| { -                config.as_ref().num_samples().saturating_sub(samples) -            }) -            .ok_or(Error::GraphicsCreationFailed( -                iced_graphics::Error::NoAvailablePixelFormat, -            ))?; - -        log::debug!("Selected: {configuration:#?}"); - -        #[cfg(all( -            unix, -            not(target_os = "macos"), -            not(target_arch = "wasm32") -        ))] -        let (window, window_handle) = { -            use glutin::platform::x11::X11GlConfigExt; -            let builder = -                if let Some(visual) = configuration.as_ref().x11_visual() { -                    use winit::platform::unix::WindowBuilderExtUnix; -                    builder.with_x11_visual(visual.into_raw()) -                } else { -                    builder -                }; - -            let window = builder -                .build(&event_loop) -                .map_err(Error::WindowCreationFailed)?; - -            let handle = window.raw_window_handle(); - -            (window, handle) -        }; - -        let attributes = -            ContextAttributesBuilder::new().build(Some(window_handle)); -        let fallback_attributes = ContextAttributesBuilder::new() -            .with_context_api(ContextApi::Gles(None)) -            .build(Some(window_handle)); - -        let context = display -            .create_context(configuration.as_ref(), &attributes) -            .or_else(|_| { -                display.create_context( -                    configuration.as_ref(), -                    &fallback_attributes, -                ) -            }) -            .map_err(|error| { -                Error::GraphicsCreationFailed( -                    iced_graphics::Error::BackendError(format!( -                        "failed to create context: {error}" -                    )), -                ) -            })?; - -        let surface = gl_surface(&display, configuration.as_ref(), &window) -            .map_err(|error| { -                Error::GraphicsCreationFailed( -                    iced_graphics::Error::BackendError(format!( -                        "failed to create surface: {error}" -                    )), -                ) -            })?; - -        (display, window, configuration.0, surface, context) -    }; - -    let windows: HashMap<window::Id, winit::window::Window> = -        HashMap::from([(window::Id::MAIN, window)]); - -    // need to make context current before trying to load GL functions -    let context = context -        .make_current(&surface) -        .expect("Make context current."); - -    #[allow(unsafe_code)] -    let (compositor, renderer) = unsafe { -        C::new(compositor_settings, |address| { -            let address = CString::new(address).expect("address error"); -            display.get_proc_address(address.as_c_str()) -        })? -    }; - -    let context = context.make_not_current().expect("Make not current."); - -    let (mut sender, receiver) = mpsc::unbounded(); - -    let mut instance = Box::pin({ -        let run_instance = run_instance::<A, E, C>( -            application, -            compositor, -            renderer, -            runtime, -            proxy, -            debug, -            receiver, -            display, -            windows, -            configuration, -            context, -            init_command, -            settings.exit_on_close_request, -        ); - -        #[cfg(feature = "tracing")] -        let run_instance = -            run_instance.instrument(info_span!("Application", "LOOP")); - -        run_instance -    }); - -    let mut context = task::Context::from_waker(task::noop_waker_ref()); - -    let _ = event_loop.run_return(move |event, event_loop, control_flow| { -        use winit::event_loop::ControlFlow; - -        if let ControlFlow::ExitWithCode(_) = control_flow { -            return; -        } - -        let event = match event { -            winit::event::Event::WindowEvent { -                event: -                    winit::event::WindowEvent::ScaleFactorChanged { -                        new_inner_size, -                        .. -                    }, -                window_id, -            } => Some(winit::event::Event::WindowEvent { -                event: winit::event::WindowEvent::Resized(*new_inner_size), -                window_id, -            }), -            winit::event::Event::UserEvent(Event::NewWindow { -                id, -                settings, -                title, -            }) => { -                let window = settings -                    .into_builder(&title, event_loop.primary_monitor(), None) -                    .build(event_loop) -                    .expect("Failed to build window"); - -                Some(winit::event::Event::UserEvent(Event::WindowCreated( -                    id, window, -                ))) -            } -            _ => event.to_static(), -        }; - -        if let Some(event) = event { -            sender.start_send(event).expect("Send event"); - -            let poll = instance.as_mut().poll(&mut context); - -            *control_flow = match poll { -                task::Poll::Pending => ControlFlow::Wait, -                task::Poll::Ready(_) => ControlFlow::Exit, -            }; -        } -    }); - -    Ok(()) -} - -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, -    mut receiver: mpsc::UnboundedReceiver< -        winit::event::Event<'_, Event<A::Message>>, -    >, -    display: Display, -    mut windows: HashMap<window::Id, winit::window::Window>, -    configuration: Config, -    mut context: NotCurrentContext, -    init_command: Command<A::Message>, -    _exit_on_close_request: bool, -) where -    A: Application + 'static, -    E: Executor + 'static, -    C: iced_graphics::window::GLCompositor<Renderer = A::Renderer> + 'static, -    <A::Renderer as iced_native::Renderer>::Theme: StyleSheet, -{ -    use iced_winit::futures::stream::StreamExt; -    use winit::event; - -    let mut clipboard = -        Clipboard::connect(windows.values().next().expect("No window found")); -    let mut caches = HashMap::new(); -    let mut current_context_window = None; -    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 surface = gl_surface(&display, &configuration, &window) -            .expect("Create surface."); -        let current_context = -            context.make_current(&surface).expect("Make current."); -        let state = multi_window::State::new(&application, id, &window); -        let physical_size = state.physical_size(); - -        surface.resize( -            ¤t_context, -            NonZeroU32::new(physical_size.width).unwrap_or(ONE), -            NonZeroU32::new(physical_size.height).unwrap_or(ONE), -        ); - -        let user_interface = multi_window::build_user_interface( -            &application, -            user_interface::Cache::default(), -            &mut renderer, -            state.logical_size(), -            &mut debug, -            id, -        ); - -        context = current_context -            .make_not_current() -            .expect("Make not current."); - -        let _ = states.insert(id, state); -        let _ = surfaces.insert(id, surface); -        let _ = interfaces.insert(id, user_interface); -    } - -    run_command( -        &application, -        &mut caches, -        &states, -        &mut renderer, -        init_command, -        &mut runtime, -        &mut clipboard, -        &mut proxy, -        &mut debug, -        &windows, -        || compositor.fetch_information(), -    ); - -    runtime.track(application.subscription().map(Event::Application)); - -    let mut mouse_interaction = mouse::Interaction::default(); -    let mut events = Vec::new(); -    let mut messages = Vec::new(); - -    debug.startup_finished(); - -    'main: while let Some(event) = receiver.next().await { -        match event { -            event::Event::MainEventsCleared => { -                for id in windows.keys().copied() { -                    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 -                            }, -                        ); - -                    events.retain(|el| remaining.contains(el)); -                    let filtered: Vec<_> = filtered -                        .into_iter() -                        .map(|(_id, event)| event) -                        .collect(); - -                    let cursor_position = -                        states.get(&id).unwrap().cursor_position(); -                    let window = windows.get(&id).unwrap(); - -                    if filtered.is_empty() && messages.is_empty() { -                        continue; -                    } - -                    debug.event_processing_started(); - -                    let (interface_state, statuses) = { -                        let user_interface = interfaces.get_mut(&id).unwrap(); -                        user_interface.update( -                            &filtered, -                            cursor_position, -                            &mut renderer, -                            &mut clipboard, -                            &mut messages, -                        ) -                    }; - -                    debug.event_processing_finished(); - -                    for event in filtered.into_iter().zip(statuses.into_iter()) -                    { -                        runtime.broadcast(event); -                    } - -                    if !messages.is_empty() -                        || matches!( -                            interface_state, -                            user_interface::State::Outdated -                        ) -                    { -                        let user_interfaces: HashMap<_, _> = -                            ManuallyDrop::into_inner(interfaces) -                                .drain() -                                .map(|(id, interface)| { -                                    (id, interface.into_cache()) -                                }) -                                .collect(); - -                        // Update application -                        update( -                            &mut application, -                            &mut caches, -                            &states, -                            &mut renderer, -                            &mut runtime, -                            &mut clipboard, -                            &mut proxy, -                            &mut debug, -                            &mut messages, -                            &windows, -                            || compositor.fetch_information(), -                        ); - -                        // Update window -                        states.get_mut(&id).unwrap().synchronize( -                            &application, -                            id, -                            windows.get(&id).expect("No window found with ID."), -                        ); - -                        let should_exit = application.should_exit(); - -                        interfaces = ManuallyDrop::new(build_user_interfaces( -                            &application, -                            &mut renderer, -                            &mut debug, -                            &states, -                            user_interfaces, -                        )); - -                        if should_exit { -                            break 'main; -                        } -                    } - -                    debug.draw_started(); -                    let new_mouse_interaction = { -                        let user_interface = interfaces.get_mut(&id).unwrap(); -                        let state = states.get(&id).unwrap(); - -                        user_interface.draw( -                            &mut renderer, -                            state.theme(), -                            &renderer::Style { -                                text_color: state.text_color(), -                            }, -                            state.cursor_position(), -                        ) -                    }; -                    debug.draw_finished(); - -                    if new_mouse_interaction != mouse_interaction { -                        window.set_cursor_icon(conversion::mouse_interaction( -                            new_mouse_interaction, -                        )); - -                        mouse_interaction = new_mouse_interaction; -                    } - -                    window.request_redraw(); -                } -            } -            event::Event::PlatformSpecific(event::PlatformSpecific::MacOS( -                event::MacOS::ReceivedUrl(url), -            )) => { -                use iced_native::event; -                events.push(( -                    None, -                    iced_native::Event::PlatformSpecific( -                        event::PlatformSpecific::MacOS( -                            event::MacOS::ReceivedUrl(url), -                        ), -                    ), -                )); -            } -            event::Event::UserEvent(event) => match event { -                Event::Application(message) => messages.push(message), -                Event::WindowCreated(id, window) => { -                    let state = -                        multi_window::State::new(&application, id, &window); -                    let user_interface = multi_window::build_user_interface( -                        &application, -                        user_interface::Cache::default(), -                        &mut renderer, -                        state.logical_size(), -                        &mut debug, -                        id, -                    ); - -                    let surface = gl_surface(&display, &configuration, &window) -                        .expect("Create surface."); - -                    let _ = states.insert(id, state); -                    let _ = interfaces.insert(id, user_interface); -                    let _ = window_ids.insert(window.id(), id); -                    let _ = windows.insert(id, window); -                    let _ = surfaces.insert(id, surface); -                } -                Event::CloseWindow(id) => { -                    // TODO(derezzedex): log errors -                    if let Some(window) = windows.get(&id) { -                        if window_ids.remove(&window.id()).is_none() { -                            println!("Failed to remove from `window_ids`!"); -                        } -                    } -                    if states.remove(&id).is_none() { -                        println!("Failed to remove from `states`!") -                    } -                    if interfaces.remove(&id).is_none() { -                        println!("Failed to remove from `interfaces`!"); -                    } -                    if surfaces.remove(&id).is_none() { -                        println!("Failed to remove from `surfaces`!") -                    } -                    if windows.remove(&id).is_none() { -                        println!("Failed to remove from `windows`!") -                    } - -                    if windows.is_empty() { -                        break 'main; -                    } -                } -                Event::NewWindow { .. } => unreachable!(), -            }, -            event::Event::RedrawRequested(id) => { -                #[cfg(feature = "tracing")] -                let _ = info_span!("Application", "FRAME").entered(); - -                let state = window_ids -                    .get(&id) -                    .and_then(|id| states.get_mut(id)) -                    .unwrap(); -                let window = -                    window_ids.get(&id).and_then(|id| windows.get(id)).unwrap(); - -                let surface = window_ids -                    .get(&id) -                    .and_then(|id| surfaces.get(id)) -                    .unwrap(); - -                debug.render_started(); - -                let current_context = -                    context.make_current(&surface).expect("Make current."); - -                if current_context_window != Some(id) { -                    current_context_window = Some(id); -                } - -                if state.viewport_changed() { -                    let physical_size = state.physical_size(); -                    let logical_size = state.logical_size(); - -                    let mut user_interface = window_ids -                        .get(&id) -                        .and_then(|id| interfaces.remove(id)) -                        .unwrap(); - -                    debug.layout_started(); -                    user_interface = -                        user_interface.relayout(logical_size, &mut renderer); -                    debug.layout_finished(); - -                    debug.draw_started(); -                    let new_mouse_interaction = user_interface.draw( -                        &mut renderer, -                        state.theme(), -                        &renderer::Style { -                            text_color: state.text_color(), -                        }, -                        state.cursor_position(), -                    ); -                    debug.draw_finished(); - -                    if new_mouse_interaction != mouse_interaction { -                        window.set_cursor_icon(conversion::mouse_interaction( -                            new_mouse_interaction, -                        )); - -                        mouse_interaction = new_mouse_interaction; -                    } - -                    surface.resize( -                        ¤t_context, -                        NonZeroU32::new(physical_size.width).unwrap_or(ONE), -                        NonZeroU32::new(physical_size.height).unwrap_or(ONE), -                    ); - -                    if let Err(_) = surface.set_swap_interval( -                        ¤t_context, -                        SwapInterval::Wait(ONE), -                    ) { -                        log::error!("Could not set swap interval for surface attached to window id: {:?}", id); -                    } - -                    compositor.resize_viewport(physical_size); - -                    let _ = interfaces -                        .insert(*window_ids.get(&id).unwrap(), user_interface); -                } - -                compositor.present( -                    &mut renderer, -                    state.viewport(), -                    state.background_color(), -                    &debug.overlay(), -                ); - -                surface -                    .swap_buffers(¤t_context) -                    .expect("Swap buffers"); - -                context = current_context -                    .make_not_current() -                    .expect("Make not current."); -                debug.render_finished(); -                // TODO: Handle animations! -                // Maybe we can use `ControlFlow::WaitUntil` for this. -            } -            event::Event::WindowEvent { -                event: window_event, -                window_id, -            } => { -                // dbg!(window_id); -                if let Some(window) = -                    window_ids.get(&window_id).and_then(|id| windows.get(id)) -                { -                    if let Some(state) = window_ids -                        .get(&window_id) -                        .and_then(|id| states.get_mut(id)) -                    { -                        if multi_window::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); -                            } -                        } - -                        state.update(window, &window_event, &mut debug); - -                        if let Some(event) = conversion::window_event( -                            *window_ids.get(&window_id).unwrap(), -                            &window_event, -                            state.scale_factor(), -                            state.modifiers(), -                        ) { -                            events.push(( -                                window_ids.get(&window_id).cloned(), -                                event, -                            )); -                        } -                    } else { -                        log::error!( -                            "Window state not found for id: {:?}", -                            window_id -                        ); -                    } -                } else { -                    log::error!("Window not found for id: {:?}", window_id); -                } -            } -            _ => {} -        } -    } - -    // Manually drop the user interface -    // drop(ManuallyDrop::into_inner(user_interface)); -} - -/// Updates an [`Application`] by feeding it the provided messages, spawning any -/// resulting [`Command`], and tracking its [`Subscription`]. -pub fn update<A: Application, E: Executor>( -    application: &mut A, -    caches: &mut HashMap<window::Id, user_interface::Cache>, -    states: &HashMap<window::Id, multi_window::State<A>>, -    renderer: &mut A::Renderer, -    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() -> iced_graphics::compositor::Information + Copy, -) where -    A: Application + 'static, -    <A::Renderer as crate::Renderer>::Theme: StyleSheet, -{ -    for message in messages.drain(..) { -        debug.log_message(&message); - -        debug.update_started(); -        let command = runtime.enter(|| application.update(message)); -        debug.update_finished(); - -        run_command( -            application, -            caches, -            &states, -            renderer, -            command, -            runtime, -            clipboard, -            proxy, -            debug, -            windows, -            graphics_info, -        ); -    } - -    let subscription = application.subscription().map(Event::Application); -    runtime.track(subscription); -} - -/// Runs the actions of a [`Command`]. -pub fn run_command<A, E>( -    application: &A, -    caches: &mut HashMap<window::Id, user_interface::Cache>, -    states: &HashMap<window::Id, multi_window::State<A>>, -    renderer: &mut A::Renderer, -    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() -> iced_graphics::compositor::Information + Copy, -) where -    A: Application + 'static, -    E: Executor, -    <A::Renderer as crate::Renderer>::Theme: StyleSheet, -{ -    use iced_native::command; -    use iced_native::system; -    use iced_native::window; -    use iced_winit::clipboard; -    use iced_winit::futures::FutureExt; - -    for action in command.actions() { -        match action { -            command::Action::Future(future) => { -                runtime.spawn(Box::pin(future.map(Event::Application))); -            } -            command::Action::Clipboard(action) => match action { -                clipboard::Action::Read(tag) => { -                    let message = tag(clipboard.read()); - -                    proxy -                        .send_event(Event::Application(message)) -                        .expect("Send message to event loop"); -                } -                clipboard::Action::Write(contents) => { -                    clipboard.write(contents); -                } -            }, -            command::Action::Window(id, action) => match action { -                window::Action::Spawn { settings } => { -                    proxy -                        .send_event(Event::NewWindow { -                            id, -                            settings: settings.into(), -                            title: application.title(id), -                        }) -                        .expect("Send message to event loop"); -                } -                window::Action::Close => { -                    proxy -                        .send_event(Event::CloseWindow(id)) -                        .expect("Send message to event loop"); -                } -                window::Action::Drag => { -                    let window = windows.get(&id).expect("No window found"); -                    let _res = window.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::Move { x, y } => { -                    let window = windows.get(&id).expect("No window found"); -                    window.set_outer_position(winit::dpi::LogicalPosition { -                        x, -                        y, -                    }); -                } -                window::Action::ChangeMode(mode) => { -                    let window = windows.get(&id).expect("No window found"); -                    window.set_visible(conversion::visible(mode)); -                    window.set_fullscreen(conversion::fullscreen( -                        window.primary_monitor(), -                        mode, -                    )); -                } -                window::Action::FetchMode(tag) => { -                    let window = windows.get(&id).expect("No window found"); -                    let mode = if window.is_visible().unwrap_or(true) { -                        conversion::mode(window.fullscreen()) -                    } else { -                        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); -                } -                window::Action::ToggleMaximize => { -                    let window = windows.get(&id).expect("No window found!"); -                    window.set_maximized(!window.is_maximized()); -                } -                window::Action::ToggleDecorations => { -                    let window = windows.get(&id).expect("No window found!"); -                    window.set_decorations(!window.is_decorated()); -                } -                window::Action::RequestUserAttention(attention_type) => { -                    let window = windows.get(&id).expect("No window found!"); -                    window.request_user_attention( -                        attention_type.map(conversion::user_attention), -                    ); -                } -                window::Action::GainFocus => { -                    let window = windows.get(&id).expect("No window found!"); -                    window.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::FetchId(tag) => { -                    let window = windows.get(&id).expect("No window found!"); - -                    proxy -                        .send_event(Event::Application(tag(window.id().into()))) -                        .expect("Send message to event loop.") -                } -            }, -            command::Action::System(action) => match action { -                system::Action::QueryInformation(_tag) => { -                    #[cfg(feature = "iced_winit/system")] -                    { -                        let graphics_info = _graphics_info(); -                        let proxy = proxy.clone(); - -                        let _ = std::thread::spawn(move || { -                            let information = -                                crate::system::information(graphics_info); - -                            let message = _tag(information); - -                            proxy -                                .send_event(Event::Application(message)) -                                .expect("Send message to event loop") -                        }); -                    } -                } -            }, -            command::Action::Widget(action) => { -                let mut current_caches = std::mem::take(caches); -                let mut current_operation = Some(action.into_operation()); - -                let mut user_interfaces = multi_window::build_user_interfaces( -                    application, -                    renderer, -                    debug, -                    states, -                    current_caches, -                ); - -                while let Some(mut operation) = current_operation.take() { -                    for user_interface in user_interfaces.values_mut() { -                        user_interface.operate(renderer, 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"); -                            } -                            operation::Outcome::Chain(next) => { -                                current_operation = Some(next); -                            } -                        } -                    } -                } - -                let user_interfaces: HashMap<_, _> = user_interfaces -                    .drain() -                    .map(|(id, interface)| (id, interface.into_cache())) -                    .collect(); - -                current_caches = user_interfaces; -                *caches = current_caches; -            } -        } -    } -} - -/// TODO(derezzedex) -pub fn build_user_interfaces<'a, A>( -    application: &'a A, -    renderer: &mut A::Renderer, -    debug: &mut Debug, -    states: &HashMap<window::Id, multi_window::State<A>>, -    mut user_interfaces: HashMap<window::Id, user_interface::Cache>, -) -> HashMap< -    window::Id, -    iced_winit::UserInterface< -        'a, -        <A as Application>::Message, -        <A as Application>::Renderer, -    >, -> -where -    A: Application + 'static, -    <A::Renderer as crate::Renderer>::Theme: StyleSheet, -{ -    let mut interfaces = HashMap::new(); - -    for (id, pure_state) in user_interfaces.drain() { -        let state = &states.get(&id).unwrap(); - -        let user_interface = multi_window::build_user_interface( -            application, -            pure_state, -            renderer, -            state.logical_size(), -            debug, -            id, -        ); - -        let _ = interfaces.insert(id, user_interface); -    } - -    interfaces -} diff --git a/graphics/src/window/gl_compositor.rs b/graphics/src/window/gl_compositor.rs index e6ae2364..a45a7ca1 100644 --- a/graphics/src/window/gl_compositor.rs +++ b/graphics/src/window/gl_compositor.rs @@ -30,7 +30,7 @@ pub trait GLCompositor: Sized {      /// The settings of the [`GLCompositor`].      ///      /// It's up to you to decide the configuration supported by your renderer! -    type Settings: Default + Clone; +    type Settings: Default;      /// Creates a new [`GLCompositor`] and [`Renderer`] with the given      /// [`Settings`] and an OpenGL address loader function. diff --git a/native/src/window/id.rs b/native/src/window/id.rs index fa9761f5..0c3e5272 100644 --- a/native/src/window/id.rs +++ b/native/src/window/id.rs @@ -4,12 +4,10 @@ use std::hash::{Hash, Hasher};  #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]  /// The ID of the window. -/// -/// This is not necessarily the same as the window ID fetched from `winit::window::Window`.  pub struct Id(u64);  impl Id { -    /// TODO(derezzedex): maybe change `u64` to an enum `Type::{Single, Multi(u64)}` +    /// The reserved window ID for the primary window in an Iced application.      pub const MAIN: Self = Id(0);      /// Creates a new unique window ID. @@ -182,7 +182,7 @@ pub mod touch;  pub mod widget;  pub mod window; -#[cfg(feature = "multi_window")] +#[cfg(all(not(feature = "glow"), feature = "multi_window"))]  pub mod multi_window;  #[cfg(all(not(feature = "glow"), feature = "wgpu"))] diff --git a/winit/src/application.rs b/winit/src/application.rs index 58556da4..1310ba1c 100644 --- a/winit/src/application.rs +++ b/winit/src/application.rs @@ -734,7 +734,7 @@ pub fn run_command<A, E>(                      clipboard.write(contents);                  }              }, -            command::Action::Window(_id, action) => match action { +            command::Action::Window(_, action) => match action {                  window::Action::Close => {                      *should_exit = true;                  } diff --git a/winit/src/multi_window.rs b/winit/src/multi_window.rs index 1a9d4a1c..eac8b260 100644 --- a/winit/src/multi_window.rs +++ b/winit/src/multi_window.rs @@ -1,4 +1,4 @@ -//! Create interactive, native cross-platform applications. +//! Create interactive, native cross-platform applications for WGPU.  mod state;  pub use state::State; @@ -31,17 +31,14 @@ pub use crate::Profiler;  #[cfg(feature = "trace")]  use tracing::{info_span, instrument::Instrument}; -/// TODO(derezzedex) -// This is the an wrapper around the `Application::Message` associate type -// to allows the `shell` to create internal messages, while still having -// the current user specified custom messages. +/// 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      Application(Message), -    /// TODO(derezzedex) -    // Create a wrapper variant of `window::Event` type instead -    // (maybe we should also allow users to listen/react to those internal messages?) +    /// A message which spawns a new window.      NewWindow {          /// The [window::Id] of the newly spawned [`Window`].          id: window::Id, @@ -50,9 +47,9 @@ pub enum Event<Message> {          /// The title of the newly spawned [`Window`].          title: String,      }, -    /// TODO(derezzedex) +    /// Close a window.      CloseWindow(window::Id), -    /// TODO(derezzedex) +    /// A message for when the window has finished being created.      WindowCreated(window::Id, winit::window::Window),  } @@ -90,7 +87,7 @@ where      /// background by shells.      fn update(&mut self, message: Self::Message) -> Command<Self::Message>; -    /// Returns the widgets to display in the [`Program`]. +    /// Returns the widgets to display for the `window` in the [`Program`].      ///      /// These widgets can produce __messages__ based on user interaction.      fn view( @@ -108,7 +105,7 @@ 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 the current [`Application`] window. +    /// Returns the current title of each [`Application`] window.      ///      /// This title can be dynamic! The runtime will automatically update the      /// title of your application when necessary. @@ -137,7 +134,7 @@ where          Subscription::none()      } -    /// Returns the scale factor of the [`Application`]. +    /// Returns the scale factor of the window of the [`Application`].      ///      /// It can be used to dynamically control the size of the UI at runtime      /// (i.e. zooming). @@ -1142,7 +1139,7 @@ pub fn run_command<A, E>(      }  } -/// TODO(derezzedex) +/// Build the user interfaces for every window.  pub fn build_user_interfaces<'a, A>(      application: &'a A,      renderer: &mut A::Renderer, diff --git a/winit/src/multi_window/state.rs b/winit/src/multi_window/state.rs index 35c69924..a7e65de7 100644 --- a/winit/src/multi_window/state.rs +++ b/winit/src/multi_window/state.rs @@ -8,7 +8,7 @@ use std::marker::PhantomData;  use winit::event::{Touch, WindowEvent};  use winit::window::Window; -/// The state of a windowed [`Application`]. +/// The state of a multi-windowed [`Application`].  #[allow(missing_debug_implementations)]  pub struct State<A: Application>  where @@ -29,7 +29,7 @@ impl<A: Application> State<A>  where      <A::Renderer as crate::Renderer>::Theme: application::StyleSheet,  { -    /// Creates a new [`State`] for the provided [`Application`]'s window. +    /// Creates a new [`State`] for the provided [`Application`]'s `window`.      pub fn new(          application: &A,          window_id: window::Id, @@ -116,8 +116,7 @@ where          self.appearance.text_color      } -    /// Processes the provided window event and updates the [`State`] -    /// accordingly. +    /// Processes the provided window event and updates the [`State`] accordingly.      pub fn update(          &mut self,          window: &Window, diff --git a/winit/src/profiler.rs b/winit/src/profiler.rs index ff9bbdc0..7031507a 100644 --- a/winit/src/profiler.rs +++ b/winit/src/profiler.rs @@ -21,7 +21,6 @@ pub struct Profiler {  impl Profiler {      /// Initializes the [`Profiler`].      pub fn init() -> Self { -        log::info!("Capturing trace..");          // Registry stores the spans & generates unique span IDs          let subscriber = Registry::default(); diff --git a/winit/src/settings.rs b/winit/src/settings.rs index b26de542..88d7c1de 100644 --- a/winit/src/settings.rs +++ b/winit/src/settings.rs @@ -179,9 +179,9 @@ impl Window {          {              use winit::platform::windows::WindowBuilderExtWindows; -            // if let Some(parent) = self.platform_specific.parent { -            //     window_builder = window_builder.with_parent_window(parent); -            // } +            if let Some(parent) = self.platform_specific.parent { +                window_builder = window_builder.with_parent_window(parent); +            }              window_builder = window_builder                  .with_drag_and_drop(self.platform_specific.drag_and_drop); @@ -227,7 +227,7 @@ impl From<iced_native::window::Settings> for Window {      fn from(settings: iced_native::window::Settings) -> Self {          Self {              size: settings.size, -            position: Position::from(settings.position), +            position: settings.position,              min_size: settings.min_size,              max_size: settings.max_size,              visible: settings.visible, diff --git a/winit/src/settings/windows.rs b/winit/src/settings/windows.rs index 0891ec2c..ff03a9c5 100644 --- a/winit/src/settings/windows.rs +++ b/winit/src/settings/windows.rs @@ -4,7 +4,7 @@  #[derive(Debug, Clone, Copy, PartialEq, Eq)]  pub struct PlatformSpecific {      /// Parent window -    // pub parent: Option<winit::platform::windows::HWND>, +    pub parent: Option<winit::platform::windows::HWND>,      /// Drag and drop support      pub drag_and_drop: bool, @@ -13,7 +13,7 @@ pub struct PlatformSpecific {  impl Default for PlatformSpecific {      fn default() -> Self {          Self { -            // parent: None, +            parent: None,              drag_and_drop: true,          }      }  | 
