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, } } |