Introduce window::Id to timing::Stage in iced_sentinel

This commit is contained in:
Héctor Ramón Jiménez 2024-02-28 15:25:45 +01:00
parent caecbf20ef
commit 8591e5a148
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
8 changed files with 97 additions and 62 deletions

View file

@ -2,10 +2,11 @@ use std::hash::Hash;
use std::sync::atomic::{self, AtomicU64}; use std::sync::atomic::{self, AtomicU64};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
/// The id of the window. /// The id of the window.
/// ///
/// Internally Iced reserves `window::Id::MAIN` for the first window spawned. /// Internally Iced reserves `window::Id::MAIN` for the first window spawned.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Id(u64); pub struct Id(u64);
static COUNT: AtomicU64 = AtomicU64::new(1); static COUNT: AtomicU64 = AtomicU64::new(1);

View file

@ -1,6 +1,7 @@
pub use iced_core as core; pub use iced_core as core;
pub use iced_style as style; pub use iced_style as style;
use crate::core::window;
use crate::style::theme; use crate::style::theme;
pub use internal::Timer; pub use internal::Timer;
@ -21,33 +22,34 @@ pub fn update_time() -> Timer {
internal::update_time() internal::update_time()
} }
pub fn view_time() -> Timer { pub fn view_time(window: window::Id) -> Timer {
internal::view_time() internal::view_time(window)
} }
pub fn layout_time() -> Timer { pub fn layout_time(window: window::Id) -> Timer {
internal::layout_time() internal::layout_time(window)
} }
pub fn interact_time() -> Timer { pub fn interact_time(window: window::Id) -> Timer {
internal::interact_time() internal::interact_time(window)
} }
pub fn draw_time() -> Timer { pub fn draw_time(window: window::Id) -> Timer {
internal::draw_time() internal::draw_time(window)
} }
pub fn render_time() -> Timer { pub fn render_time(window: window::Id) -> Timer {
internal::render_time() internal::render_time(window)
} }
pub fn time(name: impl AsRef<str>) -> Timer { pub fn time(window: window::Id, name: impl AsRef<str>) -> Timer {
internal::time(name) internal::time(window, name)
} }
#[cfg(feature = "enable")] #[cfg(feature = "enable")]
mod internal { mod internal {
use crate::core::time::Instant; use crate::core::time::Instant;
use crate::core::window;
use crate::style::theme; use crate::style::theme;
use iced_sentinel::client::{self, Client}; use iced_sentinel::client::{self, Client};
@ -74,28 +76,28 @@ mod internal {
timer(timing::Stage::Update) timer(timing::Stage::Update)
} }
pub fn view_time() -> Timer { pub fn view_time(window: window::Id) -> Timer {
timer(timing::Stage::View) timer(timing::Stage::View(window))
} }
pub fn layout_time() -> Timer { pub fn layout_time(window: window::Id) -> Timer {
timer(timing::Stage::Layout) timer(timing::Stage::Layout(window))
} }
pub fn interact_time() -> Timer { pub fn interact_time(window: window::Id) -> Timer {
timer(timing::Stage::Interact) timer(timing::Stage::Interact(window))
} }
pub fn draw_time() -> Timer { pub fn draw_time(window: window::Id) -> Timer {
timer(timing::Stage::Draw) timer(timing::Stage::Draw(window))
} }
pub fn render_time() -> Timer { pub fn render_time(window: window::Id) -> Timer {
timer(timing::Stage::Render) timer(timing::Stage::Render(window))
} }
pub fn time(name: impl AsRef<str>) -> Timer { pub fn time(window: window::Id, name: impl AsRef<str>) -> Timer {
timer(timing::Stage::Custom(name.as_ref().to_owned())) timer(timing::Stage::Custom(window, name.as_ref().to_owned()))
} }
fn timer(stage: timing::Stage) -> Timer { fn timer(stage: timing::Stage) -> Timer {
@ -140,6 +142,7 @@ mod internal {
#[cfg(not(feature = "enable"))] #[cfg(not(feature = "enable"))]
mod internal { mod internal {
use crate::core::window;
use crate::style::theme; use crate::style::theme;
pub fn theme_changed(_palette: theme::Palette) {} pub fn theme_changed(_palette: theme::Palette) {}
@ -152,27 +155,27 @@ mod internal {
Timer Timer
} }
pub fn view_time() -> Timer { pub fn view_time(_window: window::Id) -> Timer {
Timer Timer
} }
pub fn layout_time() -> Timer { pub fn layout_time(_window: window::Id) -> Timer {
Timer Timer
} }
pub fn interact_time() -> Timer { pub fn interact_time(_window: window::Id) -> Timer {
Timer Timer
} }
pub fn draw_time() -> Timer { pub fn draw_time(_window: window::Id) -> Timer {
Timer Timer
} }
pub fn render_time() -> Timer { pub fn render_time(_window: window::Id) -> Timer {
Timer Timer
} }
pub fn time(_name: impl AsRef<str>) -> Timer { pub fn time(_window: window::Id, _name: impl AsRef<str>) -> Timer {
Timer Timer
} }

View file

@ -1,6 +1,35 @@
//! A multi-window application. //! A multi-window application.
pub mod program; use crate::core::text;
pub mod state; use crate::core::window;
use crate::core::{Element, Renderer};
use crate::Command;
pub use program::Program; /// The core of a user interface for a multi-window application following The Elm Architecture.
pub use state::State; pub trait Program: Sized {
/// The graphics backend to use to draw the [`Program`].
type Renderer: Renderer + text::Renderer;
/// The type of __messages__ your [`Program`] will produce.
type Message: std::fmt::Debug + Send;
/// The theme used to draw the [`Program`].
type Theme;
/// Handles a __message__ and updates the state of the [`Program`].
///
/// This is where you define your __update logic__. All the __messages__,
/// produced by either user interactions or commands, will be handled by
/// this method.
///
/// Any [`Command`] returned will be executed immediately in the
/// background by shells.
fn update(&mut self, message: Self::Message) -> Command<Self::Message>;
/// Returns the widgets to display in the [`Program`] for the `window`.
///
/// These widgets can produce __messages__ based on user interaction.
fn view(
&self,
window: window::Id,
) -> Element<'_, Self::Message, Self::Theme, Self::Renderer>;
}

View file

@ -98,12 +98,12 @@ where
bounds, bounds,
); );
let interact_timer = debug::interact_time();
let mut messages = Vec::new(); let mut messages = Vec::new();
let uncaptured_events = user_interfaces.iter_mut().fold( let uncaptured_events = user_interfaces.iter_mut().fold(
vec![], vec![],
|mut uncaptured_events, ui| { |mut uncaptured_events, ui| {
let interact_timer = debug::interact_time();
let (_, event_statuses) = ui.update( let (_, event_statuses) = ui.update(
&self.queued_events, &self.queued_events,
cursor, cursor,
@ -111,6 +111,7 @@ where
clipboard, clipboard,
&mut messages, &mut messages,
); );
interact_timer.finish();
uncaptured_events.extend( uncaptured_events.extend(
self.queued_events self.queued_events
@ -128,7 +129,6 @@ where
self.queued_events.clear(); self.queued_events.clear();
messages.append(&mut self.queued_messages); messages.append(&mut self.queued_messages);
drop(interact_timer);
let commands = if messages.is_empty() { let commands = if messages.is_empty() {
let draw_timer = debug::draw_time(); let draw_timer = debug::draw_time();

View file

@ -2,6 +2,7 @@ use crate::core::event::{self, Event};
use crate::core::mouse; use crate::core::mouse;
use crate::core::renderer; use crate::core::renderer;
use crate::core::widget::operation::{self, Operation}; use crate::core::widget::operation::{self, Operation};
use crate::core::window;
use crate::core::{Clipboard, Size}; use crate::core::{Clipboard, Size};
use crate::debug; use crate::debug;
use crate::user_interface::{self, UserInterface}; use crate::user_interface::{self, UserInterface};
@ -101,7 +102,7 @@ where
bounds, bounds,
); );
let interact_timer = debug::interact_time(); let interact_timer = debug::interact_time(window::Id::MAIN);
let mut messages = Vec::new(); let mut messages = Vec::new();
let (_, event_statuses) = user_interface.update( let (_, event_statuses) = user_interface.update(
@ -127,7 +128,7 @@ where
drop(interact_timer); drop(interact_timer);
let command = if messages.is_empty() { let command = if messages.is_empty() {
let draw_timer = debug::draw_time(); let draw_timer = debug::draw_time(window::Id::MAIN);
self.mouse_interaction = self.mouse_interaction =
user_interface.draw(renderer, theme, style, cursor); user_interface.draw(renderer, theme, style, cursor);
drop(draw_timer); drop(draw_timer);
@ -158,7 +159,7 @@ where
bounds, bounds,
); );
let draw_timer = debug::draw_time(); let draw_timer = debug::draw_time(window::Id::MAIN);
self.mouse_interaction = self.mouse_interaction =
user_interface.draw(renderer, theme, style, cursor); user_interface.draw(renderer, theme, style, cursor);
drop(draw_timer); drop(draw_timer);
@ -213,11 +214,11 @@ fn build_user_interface<'a, P: Program>(
renderer: &mut P::Renderer, renderer: &mut P::Renderer,
size: Size, size: Size,
) -> UserInterface<'a, P::Message, P::Theme, P::Renderer> { ) -> UserInterface<'a, P::Message, P::Theme, P::Renderer> {
let view_timer = debug::view_time(); let view_timer = debug::view_time(window::Id::MAIN);
let view = program.view(); let view = program.view();
drop(view_timer); drop(view_timer);
let layout_timer = debug::layout_time(); let layout_timer = debug::layout_time(window::Id::MAIN);
let user_interface = UserInterface::build(view, size, cache, renderer); let user_interface = UserInterface::build(view, size, cache, renderer);
drop(layout_timer); drop(layout_timer);

View file

@ -1,4 +1,5 @@
use crate::core::time::Duration; use crate::core::time::Duration;
use crate::core::window;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -16,10 +17,10 @@ pub struct Timing {
pub enum Stage { pub enum Stage {
Boot, Boot,
Update, Update,
View, View(window::Id),
Layout, Layout(window::Id),
Interact, Interact(window::Id),
Draw, Draw(window::Id),
Render, Render(window::Id),
Custom(String), Custom(window::Id, String),
} }

View file

@ -379,7 +379,7 @@ async fn run_instance<A, E, C>(
if viewport_version != current_viewport_version { if viewport_version != current_viewport_version {
let logical_size = state.logical_size(); let logical_size = state.logical_size();
let layout_timer = debug::layout_time(); let layout_timer = debug::layout_time(window::Id::MAIN);
user_interface = ManuallyDrop::new( user_interface = ManuallyDrop::new(
ManuallyDrop::into_inner(user_interface) ManuallyDrop::into_inner(user_interface)
.relayout(logical_size, &mut renderer), .relayout(logical_size, &mut renderer),
@ -431,7 +431,7 @@ async fn run_instance<A, E, C>(
runtime.broadcast(redraw_event, core::event::Status::Ignored); runtime.broadcast(redraw_event, core::event::Status::Ignored);
let draw_timer = debug::draw_time(); let draw_timer = debug::draw_time(window::Id::MAIN);
let new_mouse_interaction = user_interface.draw( let new_mouse_interaction = user_interface.draw(
&mut renderer, &mut renderer,
state.theme(), state.theme(),
@ -451,7 +451,7 @@ async fn run_instance<A, E, C>(
mouse_interaction = new_mouse_interaction; mouse_interaction = new_mouse_interaction;
} }
let render_timer = debug::render_time(); let render_timer = debug::render_time(window::Id::MAIN);
match compositor.present( match compositor.present(
&mut renderer, &mut renderer,
&mut surface, &mut surface,
@ -499,7 +499,7 @@ async fn run_instance<A, E, C>(
continue; continue;
} }
let interact_timer = debug::interact_time(); let interact_timer = debug::interact_time(window::Id::MAIN);
let (interface_state, statuses) = user_interface.update( let (interface_state, statuses) = user_interface.update(
&events, &events,
state.cursor(), state.cursor(),
@ -600,11 +600,11 @@ pub fn build_user_interface<'a, A: Application>(
where where
A::Theme: StyleSheet, A::Theme: StyleSheet,
{ {
let view_timer = debug::view_time(); let view_timer = debug::view_time(window::Id::MAIN);
let view = application.view(); let view = application.view();
view_timer.finish(); view_timer.finish();
let layout_timer = debug::layout_time(); let layout_timer = debug::layout_time(window::Id::MAIN);
let user_interface = UserInterface::build(view, size, cache, renderer); let user_interface = UserInterface::build(view, size, cache, renderer);
layout_timer.finish(); layout_timer.finish();

View file

@ -509,7 +509,7 @@ async fn run_instance<A, E, C>(
&mut messages, &mut messages,
); );
let draw_timer = debug::draw_time(); let draw_timer = debug::draw_time(id);
let new_mouse_interaction = ui.draw( let new_mouse_interaction = ui.draw(
&mut window.renderer, &mut window.renderer,
window.state.theme(), window.state.theme(),
@ -565,7 +565,7 @@ async fn run_instance<A, E, C>(
{ {
let logical_size = window.state.logical_size(); let logical_size = window.state.logical_size();
let layout_time = debug::layout_time(); let layout_time = debug::layout_time(id);
let ui = user_interfaces let ui = user_interfaces
.remove(&id) .remove(&id)
.expect("Remove user interface"); .expect("Remove user interface");
@ -576,7 +576,7 @@ async fn run_instance<A, E, C>(
); );
layout_time.finish(); layout_time.finish();
let draw_time = debug::draw_time(); let draw_time = debug::draw_time(id);
let new_mouse_interaction = user_interfaces let new_mouse_interaction = user_interfaces
.get_mut(&id) .get_mut(&id)
.expect("Get user interface") .expect("Get user interface")
@ -612,7 +612,7 @@ async fn run_instance<A, E, C>(
window.state.viewport_version(); window.state.viewport_version();
} }
let render_time = debug::render_time(); let render_time = debug::render_time(id);
match compositor.present( match compositor.present(
&mut window.renderer, &mut window.renderer,
&mut window.surface, &mut window.surface,
@ -691,10 +691,10 @@ async fn run_instance<A, E, C>(
continue; continue;
} }
let interact_time = debug::interact_time();
let mut uis_stale = false; let mut uis_stale = false;
for (id, window) in window_manager.iter_mut() { for (id, window) in window_manager.iter_mut() {
let interact_time = debug::interact_time(id);
let mut window_events = vec![]; let mut window_events = vec![];
events.retain(|(window_id, event)| { events.retain(|(window_id, event)| {
@ -737,8 +737,8 @@ async fn run_instance<A, E, C>(
{ {
runtime.broadcast(event, status); runtime.broadcast(event, status);
} }
}
interact_time.finish(); interact_time.finish();
}
// TODO mw application update returns which window IDs to update // TODO mw application update returns which window IDs to update
if !messages.is_empty() || uis_stale { if !messages.is_empty() || uis_stale {
@ -806,11 +806,11 @@ fn build_user_interface<'a, A: Application>(
where where
A::Theme: StyleSheet, A::Theme: StyleSheet,
{ {
let view_timer = debug::view_time(); let view_timer = debug::view_time(id);
let view = application.view(id); let view = application.view(id);
view_timer.finish(); view_timer.finish();
let layout_timer = debug::layout_time(); let layout_timer = debug::layout_time(id);
let user_interface = UserInterface::build(view, size, cache, renderer); let user_interface = UserInterface::build(view, size, cache, renderer);
layout_timer.finish(); layout_timer.finish();