Code cleanup, clearer comments + removed some unnecessary dupe;

Removed `Frames` struct return for `window::frames()` since we are just redrawing every window anyways;
Interface dropping;
This commit is contained in:
Bingus 2023-03-13 14:16:45 -07:00
parent fa068b904a
commit 8ba1843080
No known key found for this signature in database
GPG key ID: 5F84D2AA40A9F170
11 changed files with 59 additions and 103 deletions

View file

@ -46,8 +46,8 @@ chrome-trace = [
"iced_wgpu?/tracing", "iced_wgpu?/tracing",
"iced_glow?/tracing", "iced_glow?/tracing",
] ]
# Enables experimental multi-window support for iced_winit # Enables experimental multi-window support for iced_winit + wgpu.
multi_window = ["iced_winit/multi_window"] multi-window = ["iced_winit/multi-window"]
[badges] [badges]
maintenance = { status = "actively-developed" } maintenance = { status = "actively-developed" }

View file

@ -7,7 +7,7 @@ publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
iced = { path = "../..", features = ["debug", "multi_window", "tokio"] } iced = { path = "../..", features = ["debug", "multi-window", "tokio"] }
env_logger = "0.10.0" env_logger = "0.10.0"
iced_native = { path = "../../native" } iced_native = { path = "../../native" }
iced_lazy = { path = "../../lazy" } iced_lazy = { path = "../../lazy" }

View file

@ -89,7 +89,7 @@ impl Application for SolarSystem {
} }
fn subscription(&self) -> Subscription<Message> { fn subscription(&self) -> Subscription<Message> {
window::frames().map(|frame| Message::Tick(frame.at)) window::frames().map(Message::Tick)
} }
} }

View file

@ -30,20 +30,9 @@ use crate::time::Instant;
/// ///
/// In any case, this [`Subscription`] is useful to smoothly draw application-driven /// In any case, this [`Subscription`] is useful to smoothly draw application-driven
/// animations without missing any frames. /// animations without missing any frames.
pub fn frames() -> Subscription<Frame> { pub fn frames() -> Subscription<Instant> {
subscription::raw_events(|event, _status| match event { subscription::raw_events(|event, _status| match event {
crate::Event::Window(id, Event::RedrawRequested(at)) => { crate::Event::Window(_, Event::RedrawRequested(at)) => Some(at),
Some(Frame { id, at })
}
_ => None, _ => None,
}) })
} }
/// The returned `Frame` for a framerate subscription.
#[derive(Debug)]
pub struct Frame {
/// The `window::Id` that the `Frame` was produced in.
pub id: Id,
/// The `Instant` at which the frame was produced.
pub at: Instant,
}

View file

@ -182,7 +182,7 @@ pub mod touch;
pub mod widget; pub mod widget;
pub mod window; pub mod window;
#[cfg(all(not(feature = "glow"), feature = "multi_window"))] #[cfg(all(not(feature = "glow"), feature = "multi-window"))]
pub mod multi_window; pub mod multi_window;
#[cfg(all(not(feature = "glow"), feature = "wgpu"))] #[cfg(all(not(feature = "glow"), feature = "wgpu"))]

View file

@ -139,7 +139,7 @@ pub trait Application: Sized {
window: window::Id, window: window::Id,
) -> Element<'_, Self::Message, crate::Renderer<Self::Theme>>; ) -> Element<'_, Self::Message, crate::Renderer<Self::Theme>>;
/// 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 /// It can be used to dynamically control the size of the UI at runtime
/// (i.e. zooming). /// (i.e. zooming).
@ -160,7 +160,8 @@ pub trait Application: Sized {
false false
} }
/// Requests that the [`window`] be closed. /// Returns the `Self::Message` that should be processed when a `window` is requested to
/// be closed.
fn close_requested(&self, window: window::Id) -> Self::Message; fn close_requested(&self, window: window::Id) -> Self::Message;
/// Runs the [`Application`]. /// Runs the [`Application`].

View file

@ -16,7 +16,7 @@ chrome-trace = ["trace", "tracing-chrome"]
debug = ["iced_native/debug"] debug = ["iced_native/debug"]
system = ["sysinfo"] system = ["sysinfo"]
application = [] application = []
multi_window = [] multi-window = []
[dependencies] [dependencies]
window_clipboard = "0.2" window_clipboard = "0.2"

View file

@ -743,7 +743,7 @@ pub fn run_command<A, E>(
} }
window::Action::Spawn { .. } => { window::Action::Spawn { .. } => {
log::info!( log::info!(
"This is only available on `multi_window::Application`" "Spawning a window is only available with `multi_window::Application`s."
) )
} }
window::Action::Resize { width, height } => { window::Action::Resize { width, height } => {

View file

@ -35,7 +35,7 @@
pub use iced_native::*; pub use iced_native::*;
pub use winit; pub use winit;
#[cfg(feature = "multi_window")] #[cfg(feature = "multi-window")]
pub mod multi_window; pub mod multi_window;
#[cfg(feature = "application")] #[cfg(feature = "application")]

View file

@ -33,7 +33,7 @@ use tracing::{info_span, instrument::Instrument};
/// This is a wrapper around the `Application::Message` associate type /// This is a wrapper around the `Application::Message` associate type
/// to allows the `shell` to create internal messages, while still having /// to allows the `shell` to create internal messages, while still having
/// the current user specified custom messages. /// the current user-specified custom messages.
#[derive(Debug)] #[derive(Debug)]
pub enum Event<Message> { pub enum Event<Message> {
/// An [`Application`] generated message /// An [`Application`] generated message
@ -53,9 +53,9 @@ pub enum Event<Message> {
WindowCreated(window::Id, winit::window::Window), WindowCreated(window::Id, winit::window::Window),
} }
/// An interactive, native cross-platform application. /// An interactive, native, cross-platform, multi-windowed application.
/// ///
/// This trait is the main entrypoint of Iced. Once implemented, you can run /// This trait is the main entrypoint of multi-window Iced. Once implemented, you can run
/// your GUI application by simply calling [`run`]. It will run in /// your GUI application by simply calling [`run`]. It will run in
/// its own window. /// its own window.
/// ///
@ -105,7 +105,7 @@ where
/// load state from a file, perform an initial HTTP request, etc. /// load state from a file, perform an initial HTTP request, etc.
fn new(flags: Self::Flags) -> (Self, Command<Self::Message>); fn new(flags: Self::Flags) -> (Self, Command<Self::Message>);
/// Returns the current title of each [`Application`] window. /// Returns the current title of each window of the [`Application`].
/// ///
/// This title can be dynamic! The runtime will automatically update the /// This title can be dynamic! The runtime will automatically update the
/// title of your application when necessary. /// title of your application when necessary.
@ -155,7 +155,8 @@ where
false false
} }
/// Requests that the [`window`] be closed. /// Returns the `Self::Message` that should be processed when a `window` is requested to
/// be closed.
fn close_requested(&self, window: window::Id) -> Self::Message; fn close_requested(&self, window: window::Id) -> Self::Message;
} }
@ -462,9 +463,9 @@ async fn run_instance<A, E, C>(
} }
debug.event_processing_finished(); debug.event_processing_finished();
// Update application with app message(s) // Update application with app messages
// Note: without tying an app message to a window ID, we must redraw all windows // Unless we implement some kind of diffing, we must redraw all windows as we
// as we cannot know what changed without some kind of damage tracking. // cannot know what changed.
if !messages.is_empty() if !messages.is_empty()
|| matches!( || matches!(
interface_state, interface_state,
@ -612,9 +613,7 @@ async fn run_instance<A, E, C>(
} }
Event::WindowCreated(id, window) => { Event::WindowCreated(id, window) => {
let mut surface = compositor.create_surface(&window); let mut surface = compositor.create_surface(&window);
let state = State::new(&application, id, &window); let state = State::new(&application, id, &window);
let physical_size = state.physical_size(); let physical_size = state.physical_size();
compositor.configure_surface( compositor.configure_surface(
@ -776,14 +775,12 @@ async fn run_instance<A, E, C>(
} }
_ => { _ => {
debug.render_finished(); debug.render_finished();
log::error!("Error {error:?} when presenting surface.");
// Try rendering again next frame. // Try rendering windows again next frame.
// TODO(derezzedex) for window in windows.values() {
windows window.request_redraw();
.values() }
.next()
.expect("No window found")
.request_redraw();
} }
}, },
} }
@ -792,80 +789,45 @@ async fn run_instance<A, E, C>(
event: window_event, event: window_event,
window_id, window_id,
} => { } => {
// dbg!(window_id); if let (Some(window), Some(state)) = (
if let Some(window) = window_ids.get(&window_id).and_then(|id| windows.get(id)),
window_ids.get(&window_id).and_then(|id| windows.get(id)) window_ids
{
if let Some(state) = window_ids
.get(&window_id) .get(&window_id)
.and_then(|id| states.get_mut(id)) .and_then(|id| states.get_mut(id)),
{ ) {
if requests_exit(&window_event, state.modifiers()) { if crate::application::requests_exit(&window_event, state.modifiers()) {
if let Some(id) = if let Some(id) = window_ids.get(&window_id).cloned() {
window_ids.get(&window_id).cloned() let message = application.close_requested(id);
{ messages.push(message);
let message = application.close_requested(id);
messages.push(message);
}
} }
}
state.update(window, &window_event, &mut debug); state.update(window, &window_event, &mut debug);
if let Some(event) = conversion::window_event( if let Some(event) = conversion::window_event(
*window_ids.get(&window_id).unwrap(), *window_ids.get(&window_id).unwrap(),
&window_event, &window_event,
state.scale_factor(), state.scale_factor(),
state.modifiers(), state.modifiers(),
) { ) {
events.push(( events
window_ids.get(&window_id).cloned(), .push((window_ids.get(&window_id).cloned(), event));
event,
));
}
} else {
log::error!(
"No window state found for id: {:?}",
window_id
);
} }
} else { } else {
log::error!("No window found with id: {:?}", window_id); log::error!(
"Could not find window or state for id: {window_id:?}"
);
} }
} }
_ => {} _ => {}
} }
} }
// Manually drop the user interface // Manually drop the user interfaces
// drop(ManuallyDrop::into_inner(user_interface)); drop(ManuallyDrop::into_inner(interfaces));
} }
/// Returns true if the provided event should cause an [`Application`] to /// Builds a window's [`UserInterface`] for the [`Application`].
/// exit.
pub fn requests_exit(
event: &winit::event::WindowEvent<'_>,
_modifiers: winit::event::ModifiersState,
) -> bool {
use winit::event::WindowEvent;
match event {
WindowEvent::CloseRequested => true,
#[cfg(target_os = "macos")]
WindowEvent::KeyboardInput {
input:
winit::event::KeyboardInput {
virtual_keycode: Some(winit::event::VirtualKeyCode::Q),
state: winit::event::ElementState::Pressed,
..
},
..
} if _modifiers.logo() => true,
_ => false,
}
}
/// Builds a [`UserInterface`] for the provided [`Application`], logging
/// [`struct@Debug`] information accordingly.
pub fn build_user_interface<'a, A: Application>( pub fn build_user_interface<'a, A: Application>(
application: &'a A, application: &'a A,
cache: user_interface::Cache, cache: user_interface::Cache,
@ -890,7 +852,9 @@ where
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
let layout_span = info_span!("Application", "LAYOUT").entered(); let layout_span = info_span!("Application", "LAYOUT").entered();
debug.layout_started(); debug.layout_started();
let user_interface = UserInterface::build(view, size, cache, renderer); let user_interface = UserInterface::build(view, size, cache, renderer);
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
let _ = layout_span.exit(); let _ = layout_span.exit();
debug.layout_finished(); debug.layout_finished();
@ -898,7 +862,7 @@ where
user_interface user_interface
} }
/// Updates an [`Application`] by feeding it the provided messages, spawning any /// Updates an [`Application`] by feeding it messages, spawning any
/// resulting [`Command`], and tracking its [`Subscription`]. /// resulting [`Command`], and tracking its [`Subscription`].
pub fn update<A: Application, E: Executor>( pub fn update<A: Application, E: Executor>(
application: &mut A, application: &mut A,
@ -923,7 +887,9 @@ pub fn update<A: Application, E: Executor>(
debug.log_message(&message); debug.log_message(&message);
debug.update_started(); debug.update_started();
let command = runtime.enter(|| application.update(message)); let command = runtime.enter(|| application.update(message));
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
let _ = update_span.exit(); let _ = update_span.exit();
debug.update_finished(); debug.update_finished();
@ -1023,7 +989,7 @@ pub fn run_command<A, E>(
let window = windows.get(&id).expect("No window found"); let window = windows.get(&id).expect("No window found");
window.set_visible(conversion::visible(mode)); window.set_visible(conversion::visible(mode));
window.set_fullscreen(conversion::fullscreen( window.set_fullscreen(conversion::fullscreen(
window.primary_monitor(), window.current_monitor(),
mode, mode,
)); ));
} }

View file

@ -179,7 +179,7 @@ where
/// Synchronizes the [`State`] with its [`Application`] and its respective /// Synchronizes the [`State`] with its [`Application`] and its respective
/// window. /// window.
/// ///
/// Normally an [`Application`] should be synchronized with its [`State`] /// Normally, an [`Application`] should be synchronized with its [`State`]
/// and window after calling [`Application::update`]. /// and window after calling [`Application::update`].
/// ///
/// [`Application::update`]: crate::Program::update /// [`Application::update`]: crate::Program::update