summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--Cargo.toml4
-rw-r--r--examples/integration_opengl/src/main.rs8
-rw-r--r--glutin/Cargo.toml10
-rw-r--r--glutin/src/application.rs364
-rw-r--r--glutin/src/lib.rs3
-rw-r--r--glutin/src/multi_window.rs1060
-rw-r--r--graphics/src/window/gl_compositor.rs2
-rw-r--r--native/src/window/id.rs4
-rw-r--r--src/lib.rs2
-rw-r--r--winit/src/application.rs2
-rw-r--r--winit/src/multi_window.rs25
-rw-r--r--winit/src/multi_window/state.rs7
-rw-r--r--winit/src/profiler.rs1
-rw-r--r--winit/src/settings.rs8
-rw-r--r--winit/src/settings/windows.rs4
15 files changed, 129 insertions, 1375 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 1a615da2..5276d921 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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(
- &current_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(
- &current_context,
- NonZeroU32::new(physical_size.width).unwrap_or(ONE),
- NonZeroU32::new(physical_size.height).unwrap_or(ONE),
- );
-
- if let Err(_) = surface.set_swap_interval(
- &current_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(&current_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.
diff --git a/src/lib.rs b/src/lib.rs
index 993e94b1..65fe3b93 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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,
}
}