Introduce iced_sentinel and iced_debug crates
This commit is contained in:
parent
58a7007ac1
commit
dd36893f7a
26 changed files with 543 additions and 567 deletions
10
Cargo.toml
10
Cargo.toml
|
|
@ -32,7 +32,7 @@ qr_code = ["iced_widget/qr_code"]
|
|||
# Enables lazy widgets
|
||||
lazy = ["iced_widget/lazy"]
|
||||
# Enables a debug view in native platforms (press F12)
|
||||
debug = ["iced_winit/debug"]
|
||||
debug = ["iced_debug/enable"]
|
||||
# Enables `tokio` as the `executor::Default` on native platforms
|
||||
tokio = ["iced_futures/tokio"]
|
||||
# Enables `async-std` as the `executor::Default` on native platforms
|
||||
|
|
@ -58,6 +58,7 @@ fira-sans = ["iced_renderer/fira-sans"]
|
|||
|
||||
[dependencies]
|
||||
iced_core.workspace = true
|
||||
iced_debug.workspace = true
|
||||
iced_futures.workspace = true
|
||||
iced_renderer.workspace = true
|
||||
iced_widget.workspace = true
|
||||
|
|
@ -85,11 +86,13 @@ strip = "debuginfo"
|
|||
[workspace]
|
||||
members = [
|
||||
"core",
|
||||
"debug",
|
||||
"futures",
|
||||
"graphics",
|
||||
"highlighter",
|
||||
"renderer",
|
||||
"runtime",
|
||||
"sentinel",
|
||||
"style",
|
||||
"tiny_skia",
|
||||
"wgpu",
|
||||
|
|
@ -111,11 +114,13 @@ keywords = ["gui", "ui", "graphics", "interface", "widgets"]
|
|||
[workspace.dependencies]
|
||||
iced = { version = "0.13.0-dev", path = "." }
|
||||
iced_core = { version = "0.13.0-dev", path = "core" }
|
||||
iced_debug = { version = "0.13.0-dev", path = "debug" }
|
||||
iced_futures = { version = "0.13.0-dev", path = "futures" }
|
||||
iced_graphics = { version = "0.13.0-dev", path = "graphics" }
|
||||
iced_highlighter = { version = "0.13.0-dev", path = "highlighter" }
|
||||
iced_renderer = { version = "0.13.0-dev", path = "renderer" }
|
||||
iced_runtime = { version = "0.13.0-dev", path = "runtime" }
|
||||
iced_sentinel = { version = "0.13.0-dev", path = "sentinel" }
|
||||
iced_style = { version = "0.13.0-dev", path = "style" }
|
||||
iced_tiny_skia = { version = "0.13.0-dev", path = "tiny_skia" }
|
||||
iced_wgpu = { version = "0.13.0-dev", path = "wgpu" }
|
||||
|
|
@ -145,6 +150,9 @@ qrcode = { version = "0.13", default-features = false }
|
|||
raw-window-handle = "0.6"
|
||||
resvg = "0.36"
|
||||
rustc-hash = "1.0"
|
||||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
semver = "1.0"
|
||||
smol = "1.0"
|
||||
smol_str = "0.2"
|
||||
softbuffer = "0.4"
|
||||
|
|
|
|||
23
debug/Cargo.toml
Normal file
23
debug/Cargo.toml
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
[package]
|
||||
name = "iced_debug"
|
||||
description = "A pluggable API for debugging iced applications"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
authors.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
categories.workspace = true
|
||||
keywords.workspace = true
|
||||
|
||||
[features]
|
||||
enable = ["iced_sentinel", "once_cell"]
|
||||
|
||||
[dependencies]
|
||||
iced_core.workspace = true
|
||||
|
||||
iced_sentinel.workspace = true
|
||||
iced_sentinel.optional = true
|
||||
|
||||
once_cell.workspace = true
|
||||
once_cell.optional = true
|
||||
162
debug/src/lib.rs
Normal file
162
debug/src/lib.rs
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
pub use iced_core as core;
|
||||
|
||||
pub use internal::Timer;
|
||||
|
||||
pub fn open_axe() {}
|
||||
|
||||
pub fn log_message(_message: &impl std::fmt::Debug) {}
|
||||
|
||||
pub fn boot_time() -> Timer {
|
||||
internal::boot_time()
|
||||
}
|
||||
|
||||
pub fn update_time() -> Timer {
|
||||
internal::update_time()
|
||||
}
|
||||
|
||||
pub fn view_time() -> Timer {
|
||||
internal::view_time()
|
||||
}
|
||||
|
||||
pub fn layout_time() -> Timer {
|
||||
internal::layout_time()
|
||||
}
|
||||
|
||||
pub fn interact_time() -> Timer {
|
||||
internal::interact_time()
|
||||
}
|
||||
|
||||
pub fn draw_time() -> Timer {
|
||||
internal::draw_time()
|
||||
}
|
||||
|
||||
pub fn render_time() -> Timer {
|
||||
internal::render_time()
|
||||
}
|
||||
|
||||
pub fn time(name: impl AsRef<str>) -> Timer {
|
||||
internal::time(name)
|
||||
}
|
||||
|
||||
#[cfg(feature = "enable")]
|
||||
mod internal {
|
||||
use crate::core::time::Instant;
|
||||
|
||||
use iced_sentinel::client::{self, Client};
|
||||
use iced_sentinel::timing::{self, Timing};
|
||||
use iced_sentinel::Report;
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
use std::sync::{Mutex, MutexGuard};
|
||||
|
||||
pub fn boot_time() -> Timer {
|
||||
timer(timing::Stage::Boot)
|
||||
}
|
||||
|
||||
pub fn update_time() -> Timer {
|
||||
timer(timing::Stage::Update)
|
||||
}
|
||||
|
||||
pub fn view_time() -> Timer {
|
||||
timer(timing::Stage::View)
|
||||
}
|
||||
|
||||
pub fn layout_time() -> Timer {
|
||||
timer(timing::Stage::Layout)
|
||||
}
|
||||
|
||||
pub fn interact_time() -> Timer {
|
||||
timer(timing::Stage::Interact)
|
||||
}
|
||||
|
||||
pub fn draw_time() -> Timer {
|
||||
timer(timing::Stage::Draw)
|
||||
}
|
||||
|
||||
pub fn render_time() -> Timer {
|
||||
timer(timing::Stage::Render)
|
||||
}
|
||||
|
||||
pub fn time(name: impl AsRef<str>) -> Timer {
|
||||
timer(timing::Stage::Custom(name.as_ref().to_owned()))
|
||||
}
|
||||
|
||||
fn timer(stage: timing::Stage) -> Timer {
|
||||
Timer {
|
||||
stage,
|
||||
start: Instant::now(),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Timer {
|
||||
stage: timing::Stage,
|
||||
start: Instant,
|
||||
}
|
||||
|
||||
impl Timer {
|
||||
pub fn finish(self) {
|
||||
lock().sentinel.report(Report::Timing(Timing {
|
||||
stage: self.stage,
|
||||
duration: self.start.elapsed(),
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Debug {
|
||||
sentinel: Client,
|
||||
}
|
||||
|
||||
fn lock() -> MutexGuard<'static, Debug> {
|
||||
static DEBUG: Lazy<Mutex<Debug>> = Lazy::new(|| {
|
||||
Mutex::new(Debug {
|
||||
sentinel: client::connect(),
|
||||
})
|
||||
});
|
||||
|
||||
DEBUG.lock().expect("Acquire debug lock")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "enable"))]
|
||||
mod internal {
|
||||
pub fn boot_time() -> Timer {
|
||||
Timer
|
||||
}
|
||||
|
||||
pub fn update_time() -> Timer {
|
||||
Timer
|
||||
}
|
||||
|
||||
pub fn view_time() -> Timer {
|
||||
Timer
|
||||
}
|
||||
|
||||
pub fn layout_time() -> Timer {
|
||||
Timer
|
||||
}
|
||||
|
||||
pub fn interact_time() -> Timer {
|
||||
Timer
|
||||
}
|
||||
|
||||
pub fn draw_time() -> Timer {
|
||||
Timer
|
||||
}
|
||||
|
||||
pub fn render_time() -> Timer {
|
||||
Timer
|
||||
}
|
||||
|
||||
pub fn time(_name: impl AsRef<str>) -> Timer {
|
||||
Timer
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Timer;
|
||||
|
||||
impl Timer {
|
||||
pub fn finish(self) {}
|
||||
}
|
||||
}
|
||||
|
|
@ -13,7 +13,6 @@ use iced_winit::core::window;
|
|||
use iced_winit::core::{Color, Font, Pixels, Size};
|
||||
use iced_winit::futures;
|
||||
use iced_winit::runtime::program;
|
||||
use iced_winit::runtime::Debug;
|
||||
use iced_winit::style::Theme;
|
||||
use iced_winit::winit;
|
||||
use iced_winit::Clipboard;
|
||||
|
|
@ -155,19 +154,14 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
let controls = Controls::new();
|
||||
|
||||
// Initialize iced
|
||||
let mut debug = Debug::new();
|
||||
let mut renderer = Renderer::new(
|
||||
Backend::new(&adapter, &device, &queue, Settings::default(), format),
|
||||
Font::default(),
|
||||
Pixels(16.0),
|
||||
);
|
||||
|
||||
let mut state = program::State::new(
|
||||
controls,
|
||||
viewport.logical_size(),
|
||||
&mut renderer,
|
||||
&mut debug,
|
||||
);
|
||||
let mut state =
|
||||
program::State::new(controls, viewport.logical_size(), &mut renderer);
|
||||
|
||||
// Run event loop
|
||||
event_loop.run(move |event, window_target| {
|
||||
|
|
@ -239,7 +233,6 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
&view,
|
||||
primitive,
|
||||
&viewport,
|
||||
&debug.overlay(),
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -315,7 +308,6 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
text_color: Color::WHITE,
|
||||
},
|
||||
&mut clipboard,
|
||||
&mut debug,
|
||||
);
|
||||
|
||||
// and request a redraw
|
||||
|
|
|
|||
|
|
@ -55,26 +55,24 @@ pub trait Compositor: Sized {
|
|||
///
|
||||
/// [`Renderer`]: Self::Renderer
|
||||
/// [`Surface`]: Self::Surface
|
||||
fn present<T: AsRef<str>>(
|
||||
fn present(
|
||||
&mut self,
|
||||
renderer: &mut Self::Renderer,
|
||||
surface: &mut Self::Surface,
|
||||
viewport: &Viewport,
|
||||
background_color: Color,
|
||||
overlay: &[T],
|
||||
) -> Result<(), SurfaceError>;
|
||||
|
||||
/// Screenshots the current [`Renderer`] primitives to an offscreen texture, and returns the bytes of
|
||||
/// the texture ordered as `RGBA` in the `sRGB` color space.
|
||||
///
|
||||
/// [`Renderer`]: Self::Renderer
|
||||
fn screenshot<T: AsRef<str>>(
|
||||
fn screenshot(
|
||||
&mut self,
|
||||
renderer: &mut Self::Renderer,
|
||||
surface: &mut Self::Surface,
|
||||
viewport: &Viewport,
|
||||
background_color: Color,
|
||||
overlay: &[T],
|
||||
) -> Vec<u8>;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -101,13 +101,12 @@ impl crate::graphics::Compositor for Compositor {
|
|||
}
|
||||
}
|
||||
|
||||
fn present<T: AsRef<str>>(
|
||||
fn present(
|
||||
&mut self,
|
||||
renderer: &mut Self::Renderer,
|
||||
surface: &mut Self::Surface,
|
||||
viewport: &Viewport,
|
||||
background_color: Color,
|
||||
overlay: &[T],
|
||||
) -> Result<(), SurfaceError> {
|
||||
match (self, renderer, surface) {
|
||||
(
|
||||
|
|
@ -121,7 +120,6 @@ impl crate::graphics::Compositor for Compositor {
|
|||
primitives,
|
||||
viewport,
|
||||
background_color,
|
||||
overlay,
|
||||
)
|
||||
}),
|
||||
#[cfg(feature = "wgpu")]
|
||||
|
|
@ -137,7 +135,6 @@ impl crate::graphics::Compositor for Compositor {
|
|||
primitives,
|
||||
viewport,
|
||||
background_color,
|
||||
overlay,
|
||||
)
|
||||
}),
|
||||
#[allow(unreachable_patterns)]
|
||||
|
|
@ -148,13 +145,12 @@ impl crate::graphics::Compositor for Compositor {
|
|||
}
|
||||
}
|
||||
|
||||
fn screenshot<T: AsRef<str>>(
|
||||
fn screenshot(
|
||||
&mut self,
|
||||
renderer: &mut Self::Renderer,
|
||||
surface: &mut Self::Surface,
|
||||
viewport: &Viewport,
|
||||
background_color: Color,
|
||||
overlay: &[T],
|
||||
) -> Vec<u8> {
|
||||
match (self, renderer, surface) {
|
||||
(
|
||||
|
|
@ -168,7 +164,6 @@ impl crate::graphics::Compositor for Compositor {
|
|||
primitives,
|
||||
viewport,
|
||||
background_color,
|
||||
overlay,
|
||||
)
|
||||
}),
|
||||
#[cfg(feature = "wgpu")]
|
||||
|
|
@ -183,7 +178,6 @@ impl crate::graphics::Compositor for Compositor {
|
|||
primitives,
|
||||
viewport,
|
||||
background_color,
|
||||
overlay,
|
||||
)
|
||||
}),
|
||||
#[allow(unreachable_patterns)]
|
||||
|
|
|
|||
|
|
@ -11,11 +11,12 @@ categories.workspace = true
|
|||
keywords.workspace = true
|
||||
|
||||
[features]
|
||||
debug = []
|
||||
multi-window = []
|
||||
|
||||
[dependencies]
|
||||
iced_core.workspace = true
|
||||
iced_debug.workspace = true
|
||||
|
||||
iced_futures.workspace = true
|
||||
iced_futures.features = ["thread-pool"]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,220 +0,0 @@
|
|||
#![allow(missing_docs)]
|
||||
use crate::core::time;
|
||||
|
||||
use std::collections::VecDeque;
|
||||
|
||||
/// A bunch of time measurements for debugging purposes.
|
||||
#[derive(Debug)]
|
||||
pub struct Debug {
|
||||
is_enabled: bool,
|
||||
|
||||
startup_start: time::Instant,
|
||||
startup_duration: time::Duration,
|
||||
|
||||
update_start: time::Instant,
|
||||
update_durations: TimeBuffer,
|
||||
|
||||
view_start: time::Instant,
|
||||
view_durations: TimeBuffer,
|
||||
|
||||
layout_start: time::Instant,
|
||||
layout_durations: TimeBuffer,
|
||||
|
||||
event_start: time::Instant,
|
||||
event_durations: TimeBuffer,
|
||||
|
||||
draw_start: time::Instant,
|
||||
draw_durations: TimeBuffer,
|
||||
|
||||
render_start: time::Instant,
|
||||
render_durations: TimeBuffer,
|
||||
|
||||
message_count: usize,
|
||||
last_messages: VecDeque<String>,
|
||||
}
|
||||
|
||||
impl Debug {
|
||||
/// Creates a new [`struct@Debug`].
|
||||
pub fn new() -> Self {
|
||||
let now = time::Instant::now();
|
||||
|
||||
Self {
|
||||
is_enabled: false,
|
||||
startup_start: now,
|
||||
startup_duration: time::Duration::from_secs(0),
|
||||
|
||||
update_start: now,
|
||||
update_durations: TimeBuffer::new(200),
|
||||
|
||||
view_start: now,
|
||||
view_durations: TimeBuffer::new(200),
|
||||
|
||||
layout_start: now,
|
||||
layout_durations: TimeBuffer::new(200),
|
||||
|
||||
event_start: now,
|
||||
event_durations: TimeBuffer::new(200),
|
||||
|
||||
draw_start: now,
|
||||
draw_durations: TimeBuffer::new(200),
|
||||
|
||||
render_start: now,
|
||||
render_durations: TimeBuffer::new(50),
|
||||
|
||||
message_count: 0,
|
||||
last_messages: VecDeque::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toggle(&mut self) {
|
||||
self.is_enabled = !self.is_enabled;
|
||||
}
|
||||
|
||||
pub fn startup_started(&mut self) {
|
||||
self.startup_start = time::Instant::now();
|
||||
}
|
||||
|
||||
pub fn startup_finished(&mut self) {
|
||||
self.startup_duration = self.startup_start.elapsed();
|
||||
}
|
||||
|
||||
pub fn update_started(&mut self) {
|
||||
self.update_start = time::Instant::now();
|
||||
}
|
||||
|
||||
pub fn update_finished(&mut self) {
|
||||
self.update_durations.push(self.update_start.elapsed());
|
||||
}
|
||||
|
||||
pub fn view_started(&mut self) {
|
||||
self.view_start = time::Instant::now();
|
||||
}
|
||||
|
||||
pub fn view_finished(&mut self) {
|
||||
self.view_durations.push(self.view_start.elapsed());
|
||||
}
|
||||
|
||||
pub fn layout_started(&mut self) {
|
||||
self.layout_start = time::Instant::now();
|
||||
}
|
||||
|
||||
pub fn layout_finished(&mut self) {
|
||||
self.layout_durations.push(self.layout_start.elapsed());
|
||||
}
|
||||
|
||||
pub fn event_processing_started(&mut self) {
|
||||
self.event_start = time::Instant::now();
|
||||
}
|
||||
|
||||
pub fn event_processing_finished(&mut self) {
|
||||
self.event_durations.push(self.event_start.elapsed());
|
||||
}
|
||||
|
||||
pub fn draw_started(&mut self) {
|
||||
self.draw_start = time::Instant::now();
|
||||
}
|
||||
|
||||
pub fn draw_finished(&mut self) {
|
||||
self.draw_durations.push(self.draw_start.elapsed());
|
||||
}
|
||||
|
||||
pub fn render_started(&mut self) {
|
||||
self.render_start = time::Instant::now();
|
||||
}
|
||||
|
||||
pub fn render_finished(&mut self) {
|
||||
self.render_durations.push(self.render_start.elapsed());
|
||||
}
|
||||
|
||||
pub fn log_message<Message: std::fmt::Debug>(&mut self, message: &Message) {
|
||||
self.last_messages.push_back(format!("{message:?}"));
|
||||
|
||||
if self.last_messages.len() > 10 {
|
||||
let _ = self.last_messages.pop_front();
|
||||
}
|
||||
|
||||
self.message_count += 1;
|
||||
}
|
||||
|
||||
pub fn overlay(&self) -> Vec<String> {
|
||||
if !self.is_enabled {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let mut lines = Vec::new();
|
||||
|
||||
fn key_value<T: std::fmt::Debug>(key: &str, value: T) -> String {
|
||||
format!("{key} {value:?}")
|
||||
}
|
||||
|
||||
lines.push(format!(
|
||||
"{} {} - {}",
|
||||
env!("CARGO_PKG_NAME"),
|
||||
env!("CARGO_PKG_VERSION"),
|
||||
env!("CARGO_PKG_REPOSITORY"),
|
||||
));
|
||||
lines.push(key_value("Startup:", self.startup_duration));
|
||||
lines.push(key_value("Update:", self.update_durations.average()));
|
||||
lines.push(key_value("View:", self.view_durations.average()));
|
||||
lines.push(key_value("Layout:", self.layout_durations.average()));
|
||||
lines.push(key_value(
|
||||
"Event processing:",
|
||||
self.event_durations.average(),
|
||||
));
|
||||
lines.push(key_value(
|
||||
"Primitive generation:",
|
||||
self.draw_durations.average(),
|
||||
));
|
||||
lines.push(key_value("Render:", self.render_durations.average()));
|
||||
lines.push(key_value("Message count:", self.message_count));
|
||||
lines.push(String::from("Last messages:"));
|
||||
lines.extend(self.last_messages.iter().map(|msg| {
|
||||
if msg.len() <= 100 {
|
||||
format!(" {msg}")
|
||||
} else {
|
||||
format!(" {msg:.100}...")
|
||||
}
|
||||
}));
|
||||
|
||||
lines
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Debug {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TimeBuffer {
|
||||
head: usize,
|
||||
size: usize,
|
||||
contents: Vec<time::Duration>,
|
||||
}
|
||||
|
||||
impl TimeBuffer {
|
||||
fn new(capacity: usize) -> TimeBuffer {
|
||||
TimeBuffer {
|
||||
head: 0,
|
||||
size: 0,
|
||||
contents: vec![time::Duration::from_secs(0); capacity],
|
||||
}
|
||||
}
|
||||
|
||||
fn push(&mut self, duration: time::Duration) {
|
||||
self.head = (self.head + 1) % self.contents.len();
|
||||
self.contents[self.head] = duration;
|
||||
self.size = (self.size + 1).min(self.contents.len());
|
||||
}
|
||||
|
||||
fn average(&self) -> time::Duration {
|
||||
let sum: time::Duration = if self.size == self.contents.len() {
|
||||
self.contents[..].iter().sum()
|
||||
} else {
|
||||
self.contents[..self.size].iter().sum()
|
||||
};
|
||||
|
||||
sum / self.size.max(1) as u32
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
#![allow(missing_docs)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Debug;
|
||||
|
||||
impl Debug {
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
|
||||
pub fn startup_started(&mut self) {}
|
||||
|
||||
pub fn startup_finished(&mut self) {}
|
||||
|
||||
pub fn update_started(&mut self) {}
|
||||
|
||||
pub fn update_finished(&mut self) {}
|
||||
|
||||
pub fn view_started(&mut self) {}
|
||||
|
||||
pub fn view_finished(&mut self) {}
|
||||
|
||||
pub fn layout_started(&mut self) {}
|
||||
|
||||
pub fn layout_finished(&mut self) {}
|
||||
|
||||
pub fn event_processing_started(&mut self) {}
|
||||
|
||||
pub fn event_processing_finished(&mut self) {}
|
||||
|
||||
pub fn draw_started(&mut self) {}
|
||||
|
||||
pub fn draw_finished(&mut self) {}
|
||||
|
||||
pub fn render_started(&mut self) {}
|
||||
|
||||
pub fn render_finished(&mut self) {}
|
||||
|
||||
pub fn log_message<Message: std::fmt::Debug>(
|
||||
&mut self,
|
||||
_message: &Message,
|
||||
) {
|
||||
}
|
||||
|
||||
pub fn overlay(&self) -> Vec<String> {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
|
@ -29,20 +29,11 @@ pub mod window;
|
|||
#[cfg(feature = "multi-window")]
|
||||
pub mod multi_window;
|
||||
|
||||
// We disable debug capabilities on release builds unless the `debug` feature
|
||||
// is explicitly enabled.
|
||||
#[cfg(feature = "debug")]
|
||||
#[path = "debug/basic.rs"]
|
||||
mod debug;
|
||||
#[cfg(not(feature = "debug"))]
|
||||
#[path = "debug/null.rs"]
|
||||
mod debug;
|
||||
|
||||
pub use iced_core as core;
|
||||
pub use iced_debug as debug;
|
||||
pub use iced_futures as futures;
|
||||
|
||||
pub use command::Command;
|
||||
pub use debug::Debug;
|
||||
pub use font::Font;
|
||||
pub use program::Program;
|
||||
pub use user_interface::UserInterface;
|
||||
|
|
|
|||
|
|
@ -4,8 +4,9 @@ use crate::core::mouse;
|
|||
use crate::core::renderer;
|
||||
use crate::core::widget::operation::{self, Operation};
|
||||
use crate::core::{Clipboard, Size};
|
||||
use crate::debug;
|
||||
use crate::user_interface::{self, UserInterface};
|
||||
use crate::{Command, Debug, Program};
|
||||
use crate::{Command, Program};
|
||||
|
||||
/// The execution state of a multi-window [`Program`]. It leverages caching, event
|
||||
/// processing, and rendering primitive storage.
|
||||
|
|
@ -27,18 +28,12 @@ where
|
|||
{
|
||||
/// Creates a new [`State`] with the provided [`Program`], initializing its
|
||||
/// primitive with the given logical bounds and renderer.
|
||||
pub fn new(
|
||||
program: P,
|
||||
bounds: Size,
|
||||
renderer: &mut P::Renderer,
|
||||
debug: &mut Debug,
|
||||
) -> Self {
|
||||
pub fn new(program: P, bounds: Size, renderer: &mut P::Renderer) -> Self {
|
||||
let user_interface = build_user_interface(
|
||||
&program,
|
||||
user_interface::Cache::default(),
|
||||
renderer,
|
||||
bounds,
|
||||
debug,
|
||||
);
|
||||
|
||||
let caches = Some(vec![user_interface.into_cache()]);
|
||||
|
|
@ -95,17 +90,15 @@ where
|
|||
theme: &P::Theme,
|
||||
style: &renderer::Style,
|
||||
clipboard: &mut dyn Clipboard,
|
||||
debug: &mut Debug,
|
||||
) -> (Vec<Event>, Option<Command<P::Message>>) {
|
||||
let mut user_interfaces = build_user_interfaces(
|
||||
&self.program,
|
||||
self.caches.take().unwrap(),
|
||||
renderer,
|
||||
bounds,
|
||||
debug,
|
||||
);
|
||||
|
||||
debug.event_processing_started();
|
||||
let interact_timer = debug::interact_time();
|
||||
let mut messages = Vec::new();
|
||||
|
||||
let uncaptured_events = user_interfaces.iter_mut().fold(
|
||||
|
|
@ -135,17 +128,15 @@ where
|
|||
|
||||
self.queued_events.clear();
|
||||
messages.append(&mut self.queued_messages);
|
||||
debug.event_processing_finished();
|
||||
drop(interact_timer);
|
||||
|
||||
let commands = if messages.is_empty() {
|
||||
debug.draw_started();
|
||||
|
||||
let draw_timer = debug::draw_time();
|
||||
for ui in &mut user_interfaces {
|
||||
self.mouse_interaction =
|
||||
ui.draw(renderer, theme, style, cursor);
|
||||
}
|
||||
|
||||
debug.draw_finished();
|
||||
drop(draw_timer);
|
||||
|
||||
self.caches = Some(
|
||||
user_interfaces
|
||||
|
|
@ -164,11 +155,11 @@ where
|
|||
drop(user_interfaces);
|
||||
|
||||
let commands = Command::batch(messages.into_iter().map(|msg| {
|
||||
debug.log_message(&msg);
|
||||
debug::log_message(&msg);
|
||||
|
||||
debug.update_started();
|
||||
let update_timer = debug::update_time();
|
||||
let command = self.program.update(msg);
|
||||
debug.update_finished();
|
||||
drop(update_timer);
|
||||
|
||||
command
|
||||
}));
|
||||
|
|
@ -178,15 +169,14 @@ where
|
|||
temp_caches,
|
||||
renderer,
|
||||
bounds,
|
||||
debug,
|
||||
);
|
||||
|
||||
debug.draw_started();
|
||||
let draw_timer = debug::draw_time();
|
||||
for ui in &mut user_interfaces {
|
||||
self.mouse_interaction =
|
||||
ui.draw(renderer, theme, style, cursor);
|
||||
}
|
||||
debug.draw_finished();
|
||||
drop(draw_timer);
|
||||
|
||||
self.caches = Some(
|
||||
user_interfaces
|
||||
|
|
@ -207,14 +197,12 @@ where
|
|||
renderer: &mut P::Renderer,
|
||||
operations: impl Iterator<Item = Box<dyn Operation<P::Message>>>,
|
||||
bounds: Size,
|
||||
debug: &mut Debug,
|
||||
) {
|
||||
let mut user_interfaces = build_user_interfaces(
|
||||
&self.program,
|
||||
self.caches.take().unwrap(),
|
||||
renderer,
|
||||
bounds,
|
||||
debug,
|
||||
);
|
||||
|
||||
for operation in operations {
|
||||
|
|
@ -251,13 +239,10 @@ fn build_user_interfaces<'a, P: Program>(
|
|||
mut caches: Vec<user_interface::Cache>,
|
||||
renderer: &mut P::Renderer,
|
||||
size: Size,
|
||||
debug: &mut Debug,
|
||||
) -> Vec<UserInterface<'a, P::Message, P::Theme, P::Renderer>> {
|
||||
caches
|
||||
.drain(..)
|
||||
.map(|cache| {
|
||||
build_user_interface(program, cache, renderer, size, debug)
|
||||
})
|
||||
.map(|cache| build_user_interface(program, cache, renderer, size))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
|
@ -266,15 +251,14 @@ fn build_user_interface<'a, P: Program>(
|
|||
cache: user_interface::Cache,
|
||||
renderer: &mut P::Renderer,
|
||||
size: Size,
|
||||
debug: &mut Debug,
|
||||
) -> UserInterface<'a, P::Message, P::Theme, P::Renderer> {
|
||||
debug.view_started();
|
||||
let view_timer = debug::view_time();
|
||||
let view = program.view();
|
||||
debug.view_finished();
|
||||
drop(view_timer);
|
||||
|
||||
debug.layout_started();
|
||||
let layout_timer = debug::layout_time();
|
||||
let user_interface = UserInterface::build(view, size, cache, renderer);
|
||||
debug.layout_finished();
|
||||
drop(layout_timer);
|
||||
|
||||
user_interface
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@ use crate::core::mouse;
|
|||
use crate::core::renderer;
|
||||
use crate::core::widget::operation::{self, Operation};
|
||||
use crate::core::{Clipboard, Size};
|
||||
use crate::debug;
|
||||
use crate::user_interface::{self, UserInterface};
|
||||
use crate::{Command, Debug, Program};
|
||||
use crate::{Command, Program};
|
||||
|
||||
/// The execution state of a [`Program`]. It leverages caching, event
|
||||
/// processing, and rendering primitive storage.
|
||||
|
|
@ -30,14 +31,12 @@ where
|
|||
mut program: P,
|
||||
bounds: Size,
|
||||
renderer: &mut P::Renderer,
|
||||
debug: &mut Debug,
|
||||
) -> Self {
|
||||
let user_interface = build_user_interface(
|
||||
&mut program,
|
||||
user_interface::Cache::default(),
|
||||
renderer,
|
||||
bounds,
|
||||
debug,
|
||||
);
|
||||
|
||||
let cache = Some(user_interface.into_cache());
|
||||
|
|
@ -94,17 +93,15 @@ where
|
|||
theme: &P::Theme,
|
||||
style: &renderer::Style,
|
||||
clipboard: &mut dyn Clipboard,
|
||||
debug: &mut Debug,
|
||||
) -> (Vec<Event>, Option<Command<P::Message>>) {
|
||||
let mut user_interface = build_user_interface(
|
||||
&mut self.program,
|
||||
self.cache.take().unwrap(),
|
||||
renderer,
|
||||
bounds,
|
||||
debug,
|
||||
);
|
||||
|
||||
debug.event_processing_started();
|
||||
let interact_timer = debug::interact_time();
|
||||
let mut messages = Vec::new();
|
||||
|
||||
let (_, event_statuses) = user_interface.update(
|
||||
|
|
@ -127,13 +124,13 @@ where
|
|||
|
||||
self.queued_events.clear();
|
||||
messages.append(&mut self.queued_messages);
|
||||
debug.event_processing_finished();
|
||||
drop(interact_timer);
|
||||
|
||||
let command = if messages.is_empty() {
|
||||
debug.draw_started();
|
||||
let draw_timer = debug::draw_time();
|
||||
self.mouse_interaction =
|
||||
user_interface.draw(renderer, theme, style, cursor);
|
||||
debug.draw_finished();
|
||||
drop(draw_timer);
|
||||
|
||||
self.cache = Some(user_interface.into_cache());
|
||||
|
||||
|
|
@ -145,11 +142,11 @@ where
|
|||
|
||||
let commands =
|
||||
Command::batch(messages.into_iter().map(|message| {
|
||||
debug.log_message(&message);
|
||||
debug::log_message(&message);
|
||||
|
||||
debug.update_started();
|
||||
let update_timer = debug::update_time();
|
||||
let command = self.program.update(message);
|
||||
debug.update_finished();
|
||||
drop(update_timer);
|
||||
|
||||
command
|
||||
}));
|
||||
|
|
@ -159,13 +156,12 @@ where
|
|||
temp_cache,
|
||||
renderer,
|
||||
bounds,
|
||||
debug,
|
||||
);
|
||||
|
||||
debug.draw_started();
|
||||
let draw_timer = debug::draw_time();
|
||||
self.mouse_interaction =
|
||||
user_interface.draw(renderer, theme, style, cursor);
|
||||
debug.draw_finished();
|
||||
drop(draw_timer);
|
||||
|
||||
self.cache = Some(user_interface.into_cache());
|
||||
|
||||
|
|
@ -181,14 +177,12 @@ where
|
|||
renderer: &mut P::Renderer,
|
||||
operations: impl Iterator<Item = Box<dyn Operation<P::Message>>>,
|
||||
bounds: Size,
|
||||
debug: &mut Debug,
|
||||
) {
|
||||
let mut user_interface = build_user_interface(
|
||||
&mut self.program,
|
||||
self.cache.take().unwrap(),
|
||||
renderer,
|
||||
bounds,
|
||||
debug,
|
||||
);
|
||||
|
||||
for operation in operations {
|
||||
|
|
@ -218,15 +212,14 @@ fn build_user_interface<'a, P: Program>(
|
|||
cache: user_interface::Cache,
|
||||
renderer: &mut P::Renderer,
|
||||
size: Size,
|
||||
debug: &mut Debug,
|
||||
) -> UserInterface<'a, P::Message, P::Theme, P::Renderer> {
|
||||
debug.view_started();
|
||||
let view_timer = debug::view_time();
|
||||
let view = program.view();
|
||||
debug.view_finished();
|
||||
drop(view_timer);
|
||||
|
||||
debug.layout_started();
|
||||
let layout_timer = debug::layout_time();
|
||||
let user_interface = UserInterface::build(view, size, cache, renderer);
|
||||
debug.layout_finished();
|
||||
drop(layout_timer);
|
||||
|
||||
user_interface
|
||||
}
|
||||
|
|
|
|||
26
sentinel/Cargo.toml
Normal file
26
sentinel/Cargo.toml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
[package]
|
||||
name = "iced_sentinel"
|
||||
description = "A client/server protocol to monitor and supervise iced applications"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
authors.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
categories.workspace = true
|
||||
keywords.workspace = true
|
||||
|
||||
[dependencies]
|
||||
iced_core.workspace = true
|
||||
serde_json.workspace = true
|
||||
futures.workspace = true
|
||||
log.workspace = true
|
||||
|
||||
tokio.workspace = true
|
||||
tokio.features = ["rt", "rt-multi-thread", "net", "sync", "time", "io-util", "macros"]
|
||||
|
||||
serde.workspace = true
|
||||
serde.features = ["derive"]
|
||||
|
||||
semver.workspace = true
|
||||
semver.features = ["serde"]
|
||||
80
sentinel/src/client.rs
Normal file
80
sentinel/src/client.rs
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
use crate::{Input, Report, SOCKET_ADDRESS};
|
||||
|
||||
use tokio::io::{self, AsyncWriteExt};
|
||||
use tokio::net;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::time;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Client {
|
||||
sender: mpsc::Sender<Input>,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub fn report(&mut self, report: Report) {
|
||||
let _ = self.sender.try_send(Input::Reported(report));
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn connect() -> Client {
|
||||
let (sender, receiver) = mpsc::channel(1_000);
|
||||
|
||||
std::thread::spawn(move || run(receiver));
|
||||
|
||||
Client { sender }
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn run(mut receiver: mpsc::Receiver<Input>) {
|
||||
let version = semver::Version::parse(env!("CARGO_PKG_VERSION"))
|
||||
.expect("Parse package version");
|
||||
|
||||
loop {
|
||||
match _connect().await {
|
||||
Ok(mut stream) => {
|
||||
let _ = send(&mut stream, Input::Connected(version)).await;
|
||||
|
||||
while let Some(input) = receiver.recv().await {
|
||||
if send(&mut stream, input).await.is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
Err(_) => {
|
||||
time::sleep(time::Duration::from_secs(2)).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn _connect() -> Result<io::BufStream<net::TcpStream>, io::Error> {
|
||||
log::debug!("Attempting to connect sentinel to server...");
|
||||
let stream = net::TcpStream::connect(SOCKET_ADDRESS).await?;
|
||||
|
||||
stream.set_nodelay(true)?;
|
||||
stream.writable().await?;
|
||||
|
||||
Ok(io::BufStream::new(stream))
|
||||
}
|
||||
|
||||
async fn send(
|
||||
stream: &mut io::BufStream<net::TcpStream>,
|
||||
input: Input,
|
||||
) -> Result<(), io::Error> {
|
||||
stream
|
||||
.write_all(
|
||||
format!(
|
||||
"{}\n",
|
||||
serde_json::to_string(&input).expect("Serialize input message")
|
||||
)
|
||||
.as_bytes(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
stream.flush().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
105
sentinel/src/lib.rs
Normal file
105
sentinel/src/lib.rs
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
pub use iced_core as core;
|
||||
|
||||
pub mod client;
|
||||
pub mod timing;
|
||||
|
||||
use crate::timing::Timing;
|
||||
|
||||
use futures::future;
|
||||
use futures::stream::{self, Stream, StreamExt};
|
||||
use semver::Version;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokio::io::{self, AsyncBufReadExt, BufStream};
|
||||
use tokio::net;
|
||||
|
||||
pub const SOCKET_ADDRESS: &str = "127.0.0.1:9167";
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum Input {
|
||||
Connected(Version),
|
||||
Reported(Report),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Event {
|
||||
Connected(Version),
|
||||
Disconnected,
|
||||
Reported(Report),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum Report {
|
||||
Timing(Timing),
|
||||
}
|
||||
|
||||
pub fn run() -> impl Stream<Item = Event> {
|
||||
enum State {
|
||||
Disconnected,
|
||||
Connected(BufStream<net::TcpStream>),
|
||||
}
|
||||
|
||||
stream::unfold(State::Disconnected, |state| async {
|
||||
match state {
|
||||
State::Disconnected => match connect().await {
|
||||
Ok(stream) => {
|
||||
let stream = BufStream::new(stream);
|
||||
|
||||
Some((None, State::Connected(stream)))
|
||||
}
|
||||
Err(_error) => Some((None, State::Disconnected)),
|
||||
},
|
||||
State::Connected(stream) => match receive(stream).await {
|
||||
Ok((_, Event::Disconnected)) | Err(_) => {
|
||||
Some((Some(Event::Disconnected), State::Disconnected))
|
||||
}
|
||||
Ok((stream, message)) => {
|
||||
Some((Some(message), State::Connected(stream)))
|
||||
}
|
||||
},
|
||||
}
|
||||
})
|
||||
.filter_map(future::ready)
|
||||
}
|
||||
|
||||
async fn connect() -> Result<net::TcpStream, io::Error> {
|
||||
let listener = net::TcpListener::bind(SOCKET_ADDRESS).await?;
|
||||
|
||||
let (stream, _) = listener.accept().await?;
|
||||
|
||||
stream.set_nodelay(true)?;
|
||||
stream.readable().await?;
|
||||
|
||||
Ok(stream)
|
||||
}
|
||||
|
||||
async fn receive(
|
||||
mut stream: BufStream<net::TcpStream>,
|
||||
) -> Result<(BufStream<net::TcpStream>, Event), io::Error> {
|
||||
let mut input = String::new();
|
||||
|
||||
loop {
|
||||
match stream.read_line(&mut input).await? {
|
||||
0 => return Ok((stream, Event::Disconnected)),
|
||||
n => {
|
||||
match serde_json::from_str(&input[..n]) {
|
||||
Ok(input) => {
|
||||
return Ok((
|
||||
stream,
|
||||
match dbg!(input) {
|
||||
Input::Connected(version) => {
|
||||
Event::Connected(version)
|
||||
}
|
||||
Input::Reported(report) => {
|
||||
Event::Reported(report)
|
||||
}
|
||||
},
|
||||
))
|
||||
}
|
||||
Err(_) => {
|
||||
// TODO: Log decoding error
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
25
sentinel/src/timing.rs
Normal file
25
sentinel/src/timing.rs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
use crate::core::time::Duration;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(
|
||||
Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
|
||||
)]
|
||||
pub struct Timing {
|
||||
pub stage: Stage,
|
||||
pub duration: Duration,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
|
||||
)]
|
||||
pub enum Stage {
|
||||
Boot,
|
||||
Update,
|
||||
View,
|
||||
Layout,
|
||||
Interact,
|
||||
Draw,
|
||||
Render,
|
||||
Custom(String),
|
||||
}
|
||||
|
|
@ -31,7 +31,7 @@ impl Backend {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn draw<T: AsRef<str>>(
|
||||
pub fn draw(
|
||||
&mut self,
|
||||
pixels: &mut tiny_skia::PixmapMut<'_>,
|
||||
clip_mask: &mut tiny_skia::Mask,
|
||||
|
|
@ -39,38 +39,9 @@ impl Backend {
|
|||
viewport: &Viewport,
|
||||
damage: &[Rectangle],
|
||||
background_color: Color,
|
||||
overlay: &[T],
|
||||
) {
|
||||
let physical_size = viewport.physical_size();
|
||||
let scale_factor = viewport.scale_factor() as f32;
|
||||
|
||||
if !overlay.is_empty() {
|
||||
let path = tiny_skia::PathBuilder::from_rect(
|
||||
tiny_skia::Rect::from_xywh(
|
||||
0.0,
|
||||
0.0,
|
||||
physical_size.width as f32,
|
||||
physical_size.height as f32,
|
||||
)
|
||||
.expect("Create damage rectangle"),
|
||||
);
|
||||
|
||||
pixels.fill_path(
|
||||
&path,
|
||||
&tiny_skia::Paint {
|
||||
shader: tiny_skia::Shader::SolidColor(into_color(Color {
|
||||
a: 0.1,
|
||||
..background_color
|
||||
})),
|
||||
anti_alias: false,
|
||||
..Default::default()
|
||||
},
|
||||
tiny_skia::FillRule::default(),
|
||||
tiny_skia::Transform::identity(),
|
||||
None,
|
||||
);
|
||||
}
|
||||
|
||||
for ®ion in damage {
|
||||
let path = tiny_skia::PathBuilder::from_rect(
|
||||
tiny_skia::Rect::from_xywh(
|
||||
|
|
@ -109,25 +80,6 @@ impl Backend {
|
|||
Transformation::IDENTITY,
|
||||
);
|
||||
}
|
||||
|
||||
if !overlay.is_empty() {
|
||||
pixels.stroke_path(
|
||||
&path,
|
||||
&tiny_skia::Paint {
|
||||
shader: tiny_skia::Shader::SolidColor(into_color(
|
||||
Color::from_rgb(1.0, 0.0, 0.0),
|
||||
)),
|
||||
anti_alias: false,
|
||||
..tiny_skia::Paint::default()
|
||||
},
|
||||
&tiny_skia::Stroke {
|
||||
width: 1.0,
|
||||
..tiny_skia::Stroke::default()
|
||||
},
|
||||
tiny_skia::Transform::identity(),
|
||||
None,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
self.text_pipeline.trim_cache();
|
||||
|
|
|
|||
|
|
@ -95,43 +95,27 @@ impl crate::graphics::Compositor for Compositor {
|
|||
}
|
||||
}
|
||||
|
||||
fn present<T: AsRef<str>>(
|
||||
fn present(
|
||||
&mut self,
|
||||
renderer: &mut Self::Renderer,
|
||||
surface: &mut Self::Surface,
|
||||
viewport: &Viewport,
|
||||
background_color: Color,
|
||||
overlay: &[T],
|
||||
) -> Result<(), compositor::SurfaceError> {
|
||||
renderer.with_primitives(|backend, primitives| {
|
||||
present(
|
||||
backend,
|
||||
surface,
|
||||
primitives,
|
||||
viewport,
|
||||
background_color,
|
||||
overlay,
|
||||
)
|
||||
present(backend, surface, primitives, viewport, background_color)
|
||||
})
|
||||
}
|
||||
|
||||
fn screenshot<T: AsRef<str>>(
|
||||
fn screenshot(
|
||||
&mut self,
|
||||
renderer: &mut Self::Renderer,
|
||||
surface: &mut Self::Surface,
|
||||
viewport: &Viewport,
|
||||
background_color: Color,
|
||||
overlay: &[T],
|
||||
) -> Vec<u8> {
|
||||
renderer.with_primitives(|backend, primitives| {
|
||||
screenshot(
|
||||
surface,
|
||||
backend,
|
||||
primitives,
|
||||
viewport,
|
||||
background_color,
|
||||
overlay,
|
||||
)
|
||||
screenshot(surface, backend, primitives, viewport, background_color)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -147,13 +131,12 @@ pub fn new<W: compositor::Window>(
|
|||
Compositor { context, settings }
|
||||
}
|
||||
|
||||
pub fn present<T: AsRef<str>>(
|
||||
pub fn present(
|
||||
backend: &mut Backend,
|
||||
surface: &mut Surface,
|
||||
primitives: &[Primitive],
|
||||
viewport: &Viewport,
|
||||
background_color: Color,
|
||||
overlay: &[T],
|
||||
) -> Result<(), compositor::SurfaceError> {
|
||||
let physical_size = viewport.physical_size();
|
||||
let scale_factor = viewport.scale_factor() as f32;
|
||||
|
|
@ -206,19 +189,17 @@ pub fn present<T: AsRef<str>>(
|
|||
viewport,
|
||||
&damage,
|
||||
background_color,
|
||||
overlay,
|
||||
);
|
||||
|
||||
buffer.present().map_err(|_| compositor::SurfaceError::Lost)
|
||||
}
|
||||
|
||||
pub fn screenshot<T: AsRef<str>>(
|
||||
pub fn screenshot(
|
||||
surface: &mut Surface,
|
||||
backend: &mut Backend,
|
||||
primitives: &[Primitive],
|
||||
viewport: &Viewport,
|
||||
background_color: Color,
|
||||
overlay: &[T],
|
||||
) -> Vec<u8> {
|
||||
let size = viewport.physical_size();
|
||||
|
||||
|
|
@ -240,7 +221,6 @@ pub fn screenshot<T: AsRef<str>>(
|
|||
size.height as f32,
|
||||
))],
|
||||
background_color,
|
||||
overlay,
|
||||
);
|
||||
|
||||
offscreen_buffer.iter().fold(
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ impl Backend {
|
|||
///
|
||||
/// The text provided as overlay will be rendered on top of the primitives.
|
||||
/// This is useful for rendering debug information.
|
||||
pub fn present<T: AsRef<str>>(
|
||||
pub fn present(
|
||||
&mut self,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
|
|
@ -77,7 +77,6 @@ impl Backend {
|
|||
frame: &wgpu::TextureView,
|
||||
primitives: &[Primitive],
|
||||
viewport: &Viewport,
|
||||
overlay_text: &[T],
|
||||
) {
|
||||
log::debug!("Drawing");
|
||||
#[cfg(feature = "tracing")]
|
||||
|
|
@ -87,11 +86,7 @@ impl Backend {
|
|||
let scale_factor = viewport.scale_factor() as f32;
|
||||
let transformation = viewport.projection();
|
||||
|
||||
let mut layers = Layer::generate(primitives, viewport);
|
||||
|
||||
if !overlay_text.is_empty() {
|
||||
layers.push(Layer::overlay(overlay_text, viewport));
|
||||
}
|
||||
let layers = Layer::generate(primitives, viewport);
|
||||
|
||||
self.prepare(
|
||||
device,
|
||||
|
|
|
|||
|
|
@ -172,14 +172,13 @@ pub fn new<W: compositor::Window>(
|
|||
}
|
||||
|
||||
/// Presents the given primitives with the given [`Compositor`] and [`Backend`].
|
||||
pub fn present<T: AsRef<str>>(
|
||||
pub fn present(
|
||||
compositor: &mut Compositor,
|
||||
backend: &mut Backend,
|
||||
surface: &mut wgpu::Surface<'static>,
|
||||
primitives: &[Primitive],
|
||||
viewport: &Viewport,
|
||||
background_color: Color,
|
||||
overlay: &[T],
|
||||
) -> Result<(), compositor::SurfaceError> {
|
||||
match surface.get_current_texture() {
|
||||
Ok(frame) => {
|
||||
|
|
@ -202,7 +201,6 @@ pub fn present<T: AsRef<str>>(
|
|||
view,
|
||||
primitives,
|
||||
viewport,
|
||||
overlay,
|
||||
);
|
||||
|
||||
// Submit work
|
||||
|
|
@ -294,13 +292,12 @@ impl graphics::Compositor for Compositor {
|
|||
}
|
||||
}
|
||||
|
||||
fn present<T: AsRef<str>>(
|
||||
fn present(
|
||||
&mut self,
|
||||
renderer: &mut Self::Renderer,
|
||||
surface: &mut Self::Surface,
|
||||
viewport: &Viewport,
|
||||
background_color: Color,
|
||||
overlay: &[T],
|
||||
) -> Result<(), compositor::SurfaceError> {
|
||||
renderer.with_primitives(|backend, primitives| {
|
||||
present(
|
||||
|
|
@ -310,28 +307,19 @@ impl graphics::Compositor for Compositor {
|
|||
primitives,
|
||||
viewport,
|
||||
background_color,
|
||||
overlay,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn screenshot<T: AsRef<str>>(
|
||||
fn screenshot(
|
||||
&mut self,
|
||||
renderer: &mut Self::Renderer,
|
||||
_surface: &mut Self::Surface,
|
||||
viewport: &Viewport,
|
||||
background_color: Color,
|
||||
overlay: &[T],
|
||||
) -> Vec<u8> {
|
||||
renderer.with_primitives(|backend, primitives| {
|
||||
screenshot(
|
||||
self,
|
||||
backend,
|
||||
primitives,
|
||||
viewport,
|
||||
background_color,
|
||||
overlay,
|
||||
)
|
||||
screenshot(self, backend, primitives, viewport, background_color)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -339,13 +327,12 @@ impl graphics::Compositor for Compositor {
|
|||
/// Renders the current surface to an offscreen buffer.
|
||||
///
|
||||
/// Returns RGBA bytes of the texture data.
|
||||
pub fn screenshot<T: AsRef<str>>(
|
||||
pub fn screenshot(
|
||||
compositor: &Compositor,
|
||||
backend: &mut Backend,
|
||||
primitives: &[Primitive],
|
||||
viewport: &Viewport,
|
||||
background_color: Color,
|
||||
overlay: &[T],
|
||||
) -> Vec<u8> {
|
||||
let mut encoder = compositor.device.create_command_encoder(
|
||||
&wgpu::CommandEncoderDescriptor {
|
||||
|
|
@ -385,7 +372,6 @@ pub fn screenshot<T: AsRef<str>>(
|
|||
&view,
|
||||
primitives,
|
||||
viewport,
|
||||
overlay,
|
||||
);
|
||||
|
||||
let texture = crate::color::convert(
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ keywords.workspace = true
|
|||
|
||||
[features]
|
||||
default = ["x11", "wayland", "wayland-dlopen", "wayland-csd-adwaita"]
|
||||
debug = ["iced_runtime/debug"]
|
||||
system = ["sysinfo"]
|
||||
application = []
|
||||
x11 = ["winit/x11"]
|
||||
|
|
|
|||
|
|
@ -11,13 +11,14 @@ use crate::core::time::Instant;
|
|||
use crate::core::widget::operation;
|
||||
use crate::core::window;
|
||||
use crate::core::{Event, Point, Size};
|
||||
use crate::debug;
|
||||
use crate::futures::futures;
|
||||
use crate::futures::{Executor, Runtime, Subscription};
|
||||
use crate::graphics::compositor::{self, Compositor};
|
||||
use crate::runtime::clipboard;
|
||||
use crate::runtime::program::Program;
|
||||
use crate::runtime::user_interface::{self, UserInterface};
|
||||
use crate::runtime::{Command, Debug};
|
||||
use crate::runtime::Command;
|
||||
use crate::style::application::{Appearance, StyleSheet};
|
||||
use crate::{Clipboard, Error, Proxy, Settings};
|
||||
|
||||
|
|
@ -111,8 +112,7 @@ where
|
|||
use futures::Future;
|
||||
use winit::event_loop::EventLoopBuilder;
|
||||
|
||||
let mut debug = Debug::new();
|
||||
debug.startup_started();
|
||||
let boot_timer = debug::boot_time();
|
||||
|
||||
let event_loop = EventLoopBuilder::with_user_event()
|
||||
.build()
|
||||
|
|
@ -206,13 +206,13 @@ where
|
|||
renderer,
|
||||
runtime,
|
||||
proxy,
|
||||
debug,
|
||||
event_receiver,
|
||||
control_sender,
|
||||
init_command,
|
||||
window,
|
||||
should_be_visible,
|
||||
exit_on_close_request,
|
||||
boot_timer,
|
||||
));
|
||||
|
||||
let mut context = task::Context::from_waker(task::noop_waker_ref());
|
||||
|
|
@ -276,7 +276,6 @@ async fn run_instance<A, E, C>(
|
|||
mut renderer: A::Renderer,
|
||||
mut runtime: Runtime<E, Proxy<A::Message>, A::Message>,
|
||||
mut proxy: winit::event_loop::EventLoopProxy<A::Message>,
|
||||
mut debug: Debug,
|
||||
mut event_receiver: mpsc::UnboundedReceiver<
|
||||
winit::event::Event<A::Message>,
|
||||
>,
|
||||
|
|
@ -285,6 +284,7 @@ async fn run_instance<A, E, C>(
|
|||
window: Arc<winit::window::Window>,
|
||||
should_be_visible: bool,
|
||||
exit_on_close_request: bool,
|
||||
boot_timer: debug::Timer,
|
||||
) where
|
||||
A: Application + 'static,
|
||||
E: Executor + 'static,
|
||||
|
|
@ -324,17 +324,16 @@ async fn run_instance<A, E, C>(
|
|||
&mut clipboard,
|
||||
&mut should_exit,
|
||||
&mut proxy,
|
||||
&mut debug,
|
||||
&window,
|
||||
);
|
||||
runtime.track(application.subscription().into_recipes());
|
||||
boot_timer.finish();
|
||||
|
||||
let mut user_interface = ManuallyDrop::new(build_user_interface(
|
||||
&application,
|
||||
cache,
|
||||
&mut renderer,
|
||||
state.logical_size(),
|
||||
&mut debug,
|
||||
));
|
||||
|
||||
let mut mouse_interaction = mouse::Interaction::default();
|
||||
|
|
@ -342,8 +341,6 @@ async fn run_instance<A, E, C>(
|
|||
let mut messages = Vec::new();
|
||||
let mut redraw_pending = false;
|
||||
|
||||
debug.startup_finished();
|
||||
|
||||
while let Some(event) = event_receiver.next().await {
|
||||
match event {
|
||||
event::Event::NewEvents(
|
||||
|
|
@ -382,12 +379,12 @@ async fn run_instance<A, E, C>(
|
|||
if viewport_version != current_viewport_version {
|
||||
let logical_size = state.logical_size();
|
||||
|
||||
debug.layout_started();
|
||||
let layout_timer = debug::layout_time();
|
||||
user_interface = ManuallyDrop::new(
|
||||
ManuallyDrop::into_inner(user_interface)
|
||||
.relayout(logical_size, &mut renderer),
|
||||
);
|
||||
debug.layout_finished();
|
||||
layout_timer.finish();
|
||||
|
||||
compositor.configure_surface(
|
||||
&mut surface,
|
||||
|
|
@ -434,7 +431,7 @@ async fn run_instance<A, E, C>(
|
|||
|
||||
runtime.broadcast(redraw_event, core::event::Status::Ignored);
|
||||
|
||||
debug.draw_started();
|
||||
let draw_timer = debug::draw_time();
|
||||
let new_mouse_interaction = user_interface.draw(
|
||||
&mut renderer,
|
||||
state.theme(),
|
||||
|
|
@ -444,7 +441,7 @@ async fn run_instance<A, E, C>(
|
|||
state.cursor(),
|
||||
);
|
||||
redraw_pending = false;
|
||||
debug.draw_finished();
|
||||
draw_timer.finish();
|
||||
|
||||
if new_mouse_interaction != mouse_interaction {
|
||||
window.set_cursor_icon(conversion::mouse_interaction(
|
||||
|
|
@ -454,19 +451,15 @@ async fn run_instance<A, E, C>(
|
|||
mouse_interaction = new_mouse_interaction;
|
||||
}
|
||||
|
||||
debug.render_started();
|
||||
let render_timer = debug::render_time();
|
||||
match compositor.present(
|
||||
&mut renderer,
|
||||
&mut surface,
|
||||
state.viewport(),
|
||||
state.background_color(),
|
||||
&debug.overlay(),
|
||||
) {
|
||||
Ok(()) => {
|
||||
debug.render_finished();
|
||||
|
||||
// TODO: Handle animations!
|
||||
// Maybe we can use `ControlFlow::WaitUntil` for this.
|
||||
render_timer.finish();
|
||||
}
|
||||
Err(error) => match error {
|
||||
// This is an unrecoverable error.
|
||||
|
|
@ -474,8 +467,6 @@ async fn run_instance<A, E, C>(
|
|||
panic!("{error:?}");
|
||||
}
|
||||
_ => {
|
||||
debug.render_finished();
|
||||
|
||||
// Try rendering again next frame.
|
||||
window.request_redraw();
|
||||
}
|
||||
|
|
@ -492,7 +483,7 @@ async fn run_instance<A, E, C>(
|
|||
break;
|
||||
}
|
||||
|
||||
state.update(&window, &window_event, &mut debug);
|
||||
state.update(&window, &window_event);
|
||||
|
||||
if let Some(event) = conversion::window_event(
|
||||
window::Id::MAIN,
|
||||
|
|
@ -508,8 +499,7 @@ async fn run_instance<A, E, C>(
|
|||
continue;
|
||||
}
|
||||
|
||||
debug.event_processing_started();
|
||||
|
||||
let interact_timer = debug::interact_time();
|
||||
let (interface_state, statuses) = user_interface.update(
|
||||
&events,
|
||||
state.cursor(),
|
||||
|
|
@ -517,8 +507,7 @@ async fn run_instance<A, E, C>(
|
|||
&mut clipboard,
|
||||
&mut messages,
|
||||
);
|
||||
|
||||
debug.event_processing_finished();
|
||||
interact_timer.finish();
|
||||
|
||||
for (event, status) in
|
||||
events.drain(..).zip(statuses.into_iter())
|
||||
|
|
@ -547,7 +536,6 @@ async fn run_instance<A, E, C>(
|
|||
&mut clipboard,
|
||||
&mut should_exit,
|
||||
&mut proxy,
|
||||
&mut debug,
|
||||
&mut messages,
|
||||
&window,
|
||||
);
|
||||
|
|
@ -557,7 +545,6 @@ async fn run_instance<A, E, C>(
|
|||
cache,
|
||||
&mut renderer,
|
||||
state.logical_size(),
|
||||
&mut debug,
|
||||
));
|
||||
|
||||
if should_exit {
|
||||
|
|
@ -609,18 +596,17 @@ pub fn build_user_interface<'a, A: Application>(
|
|||
cache: user_interface::Cache,
|
||||
renderer: &mut A::Renderer,
|
||||
size: Size,
|
||||
debug: &mut Debug,
|
||||
) -> UserInterface<'a, A::Message, A::Theme, A::Renderer>
|
||||
where
|
||||
A::Theme: StyleSheet,
|
||||
{
|
||||
debug.view_started();
|
||||
let view_timer = debug::view_time();
|
||||
let view = application.view();
|
||||
debug.view_finished();
|
||||
view_timer.finish();
|
||||
|
||||
debug.layout_started();
|
||||
let layout_timer = debug::layout_time();
|
||||
let user_interface = UserInterface::build(view, size, cache, renderer);
|
||||
debug.layout_finished();
|
||||
layout_timer.finish();
|
||||
|
||||
user_interface
|
||||
}
|
||||
|
|
@ -638,7 +624,6 @@ pub fn update<A: Application, C, E: Executor>(
|
|||
clipboard: &mut Clipboard,
|
||||
should_exit: &mut bool,
|
||||
proxy: &mut winit::event_loop::EventLoopProxy<A::Message>,
|
||||
debug: &mut Debug,
|
||||
messages: &mut Vec<A::Message>,
|
||||
window: &winit::window::Window,
|
||||
) where
|
||||
|
|
@ -646,11 +631,11 @@ pub fn update<A: Application, C, E: Executor>(
|
|||
A::Theme: StyleSheet,
|
||||
{
|
||||
for message in messages.drain(..) {
|
||||
debug.log_message(&message);
|
||||
debug::log_message(&message);
|
||||
|
||||
debug.update_started();
|
||||
let update_timer = debug::update_time();
|
||||
let command = runtime.enter(|| application.update(message));
|
||||
debug.update_finished();
|
||||
update_timer.finish();
|
||||
|
||||
run_command(
|
||||
application,
|
||||
|
|
@ -664,7 +649,6 @@ pub fn update<A: Application, C, E: Executor>(
|
|||
clipboard,
|
||||
should_exit,
|
||||
proxy,
|
||||
debug,
|
||||
window,
|
||||
);
|
||||
}
|
||||
|
|
@ -688,7 +672,6 @@ pub fn run_command<A, C, E>(
|
|||
clipboard: &mut Clipboard,
|
||||
should_exit: &mut bool,
|
||||
proxy: &mut winit::event_loop::EventLoopProxy<A::Message>,
|
||||
debug: &mut Debug,
|
||||
window: &winit::window::Window,
|
||||
) where
|
||||
A: Application,
|
||||
|
|
@ -855,7 +838,6 @@ pub fn run_command<A, C, E>(
|
|||
surface,
|
||||
state.viewport(),
|
||||
state.background_color(),
|
||||
&debug.overlay(),
|
||||
);
|
||||
|
||||
proxy
|
||||
|
|
@ -895,7 +877,6 @@ pub fn run_command<A, C, E>(
|
|||
current_cache,
|
||||
renderer,
|
||||
state.logical_size(),
|
||||
debug,
|
||||
);
|
||||
|
||||
while let Some(mut operation) = current_operation.take() {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ use crate::conversion;
|
|||
use crate::core::mouse;
|
||||
use crate::core::{Color, Size};
|
||||
use crate::graphics::Viewport;
|
||||
use crate::runtime::Debug;
|
||||
use crate::Application;
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
|
@ -122,12 +121,7 @@ where
|
|||
|
||||
/// Processes the provided window event and updates the [`State`]
|
||||
/// accordingly.
|
||||
pub fn update(
|
||||
&mut self,
|
||||
window: &Window,
|
||||
event: &WindowEvent,
|
||||
_debug: &mut Debug,
|
||||
) {
|
||||
pub fn update(&mut self, window: &Window, event: &WindowEvent) {
|
||||
match event {
|
||||
WindowEvent::Resized(new_size) => {
|
||||
let size = Size::new(new_size.width, new_size.height);
|
||||
|
|
@ -176,7 +170,7 @@ where
|
|||
..
|
||||
},
|
||||
..
|
||||
} => _debug.toggle(),
|
||||
} => crate::debug::open_axe(),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
pub use iced_graphics as graphics;
|
||||
pub use iced_runtime as runtime;
|
||||
pub use iced_runtime::core;
|
||||
pub use iced_runtime::debug;
|
||||
pub use iced_runtime::futures;
|
||||
pub use iced_style as style;
|
||||
pub use winit;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use crate::core::renderer;
|
|||
use crate::core::widget::operation;
|
||||
use crate::core::window;
|
||||
use crate::core::{Point, Size};
|
||||
use crate::debug;
|
||||
use crate::futures::futures::channel::mpsc;
|
||||
use crate::futures::futures::{task, Future, StreamExt};
|
||||
use crate::futures::{Executor, Runtime, Subscription};
|
||||
|
|
@ -19,7 +20,6 @@ use crate::multi_window::window_manager::WindowManager;
|
|||
use crate::runtime::command::{self, Command};
|
||||
use crate::runtime::multi_window::Program;
|
||||
use crate::runtime::user_interface::{self, UserInterface};
|
||||
use crate::runtime::Debug;
|
||||
use crate::style::application::StyleSheet;
|
||||
use crate::{Clipboard, Error, Proxy, Settings};
|
||||
|
||||
|
|
@ -112,8 +112,7 @@ where
|
|||
{
|
||||
use winit::event_loop::EventLoopBuilder;
|
||||
|
||||
let mut debug = Debug::new();
|
||||
debug.startup_started();
|
||||
let boot_timer = debug::boot_time();
|
||||
|
||||
let event_loop = EventLoopBuilder::with_user_event()
|
||||
.build()
|
||||
|
|
@ -202,12 +201,12 @@ where
|
|||
compositor,
|
||||
runtime,
|
||||
proxy,
|
||||
debug,
|
||||
event_receiver,
|
||||
control_sender,
|
||||
init_command,
|
||||
window_manager,
|
||||
should_main_be_visible,
|
||||
boot_timer,
|
||||
));
|
||||
|
||||
let mut context = task::Context::from_waker(task::noop_waker_ref());
|
||||
|
|
@ -339,12 +338,12 @@ async fn run_instance<A, E, C>(
|
|||
mut compositor: C,
|
||||
mut runtime: Runtime<E, Proxy<A::Message>, A::Message>,
|
||||
mut proxy: winit::event_loop::EventLoopProxy<A::Message>,
|
||||
mut debug: Debug,
|
||||
mut event_receiver: mpsc::UnboundedReceiver<Event<A::Message>>,
|
||||
mut control_sender: mpsc::UnboundedSender<Control>,
|
||||
init_command: Command<A::Message>,
|
||||
mut window_manager: WindowManager<A, C>,
|
||||
should_main_window_be_visible: bool,
|
||||
boot_timer: debug::Timer,
|
||||
) where
|
||||
A: Application + 'static,
|
||||
E: Executor + 'static,
|
||||
|
|
@ -377,15 +376,6 @@ async fn run_instance<A, E, C>(
|
|||
};
|
||||
|
||||
let mut ui_caches = HashMap::new();
|
||||
let mut user_interfaces = ManuallyDrop::new(build_user_interfaces(
|
||||
&application,
|
||||
&mut debug,
|
||||
&mut window_manager,
|
||||
HashMap::from_iter([(
|
||||
window::Id::MAIN,
|
||||
user_interface::Cache::default(),
|
||||
)]),
|
||||
));
|
||||
|
||||
run_command(
|
||||
&application,
|
||||
|
|
@ -395,17 +385,24 @@ async fn run_instance<A, E, C>(
|
|||
&mut clipboard,
|
||||
&mut control_sender,
|
||||
&mut proxy,
|
||||
&mut debug,
|
||||
&mut window_manager,
|
||||
&mut ui_caches,
|
||||
);
|
||||
|
||||
runtime.track(application.subscription().into_recipes());
|
||||
boot_timer.finish();
|
||||
|
||||
let mut user_interfaces = ManuallyDrop::new(build_user_interfaces(
|
||||
&application,
|
||||
&mut window_manager,
|
||||
HashMap::from_iter([(
|
||||
window::Id::MAIN,
|
||||
user_interface::Cache::default(),
|
||||
)]),
|
||||
));
|
||||
|
||||
let mut messages = Vec::new();
|
||||
|
||||
debug.startup_finished();
|
||||
|
||||
'main: while let Some(event) = event_receiver.next().await {
|
||||
match event {
|
||||
Event::WindowCreated {
|
||||
|
|
@ -430,7 +427,6 @@ async fn run_instance<A, E, C>(
|
|||
user_interface::Cache::default(),
|
||||
&mut window.renderer,
|
||||
logical_size,
|
||||
&mut debug,
|
||||
id,
|
||||
),
|
||||
);
|
||||
|
|
@ -513,7 +509,7 @@ async fn run_instance<A, E, C>(
|
|||
&mut messages,
|
||||
);
|
||||
|
||||
debug.draw_started();
|
||||
let draw_timer = debug::draw_time();
|
||||
let new_mouse_interaction = ui.draw(
|
||||
&mut window.renderer,
|
||||
window.state.theme(),
|
||||
|
|
@ -522,7 +518,7 @@ async fn run_instance<A, E, C>(
|
|||
},
|
||||
cursor,
|
||||
);
|
||||
debug.draw_finished();
|
||||
draw_timer.finish();
|
||||
|
||||
if new_mouse_interaction != window.mouse_interaction {
|
||||
window.raw.set_cursor_icon(
|
||||
|
|
@ -569,7 +565,7 @@ async fn run_instance<A, E, C>(
|
|||
{
|
||||
let logical_size = window.state.logical_size();
|
||||
|
||||
debug.layout_started();
|
||||
let layout_time = debug::layout_time();
|
||||
let ui = user_interfaces
|
||||
.remove(&id)
|
||||
.expect("Remove user interface");
|
||||
|
|
@ -578,9 +574,9 @@ async fn run_instance<A, E, C>(
|
|||
id,
|
||||
ui.relayout(logical_size, &mut window.renderer),
|
||||
);
|
||||
debug.layout_finished();
|
||||
layout_time.finish();
|
||||
|
||||
debug.draw_started();
|
||||
let draw_time = debug::draw_time();
|
||||
let new_mouse_interaction = user_interfaces
|
||||
.get_mut(&id)
|
||||
.expect("Get user interface")
|
||||
|
|
@ -592,7 +588,7 @@ async fn run_instance<A, E, C>(
|
|||
},
|
||||
window.state.cursor(),
|
||||
);
|
||||
debug.draw_finished();
|
||||
draw_time.finish();
|
||||
|
||||
if new_mouse_interaction != window.mouse_interaction
|
||||
{
|
||||
|
|
@ -616,16 +612,15 @@ async fn run_instance<A, E, C>(
|
|||
window.state.viewport_version();
|
||||
}
|
||||
|
||||
debug.render_started();
|
||||
let render_time = debug::render_time();
|
||||
match compositor.present(
|
||||
&mut window.renderer,
|
||||
&mut window.surface,
|
||||
window.state.viewport(),
|
||||
window.state.background_color(),
|
||||
&debug.overlay(),
|
||||
) {
|
||||
Ok(()) => {
|
||||
debug.render_finished();
|
||||
render_time.finish();
|
||||
|
||||
// TODO: Handle animations!
|
||||
// Maybe we can use `ControlFlow::WaitUntil` for this.
|
||||
|
|
@ -636,8 +631,6 @@ async fn run_instance<A, E, C>(
|
|||
panic!("{:?}", error);
|
||||
}
|
||||
_ => {
|
||||
debug.render_finished();
|
||||
|
||||
log::error!(
|
||||
"Error {error:?} when \
|
||||
presenting surface."
|
||||
|
|
@ -681,11 +674,7 @@ async fn run_instance<A, E, C>(
|
|||
break 'main;
|
||||
}
|
||||
} else {
|
||||
window.state.update(
|
||||
&window.raw,
|
||||
&window_event,
|
||||
&mut debug,
|
||||
);
|
||||
window.state.update(&window.raw, &window_event);
|
||||
|
||||
if let Some(event) = conversion::window_event(
|
||||
id,
|
||||
|
|
@ -702,7 +691,7 @@ async fn run_instance<A, E, C>(
|
|||
continue;
|
||||
}
|
||||
|
||||
debug.event_processing_started();
|
||||
let interact_time = debug::interact_time();
|
||||
let mut uis_stale = false;
|
||||
|
||||
for (id, window) in window_manager.iter_mut() {
|
||||
|
|
@ -749,8 +738,7 @@ async fn run_instance<A, E, C>(
|
|||
runtime.broadcast(event, status);
|
||||
}
|
||||
}
|
||||
|
||||
debug.event_processing_finished();
|
||||
interact_time.finish();
|
||||
|
||||
// TODO mw application update returns which window IDs to update
|
||||
if !messages.is_empty() || uis_stale {
|
||||
|
|
@ -770,7 +758,6 @@ async fn run_instance<A, E, C>(
|
|||
&mut clipboard,
|
||||
&mut control_sender,
|
||||
&mut proxy,
|
||||
&mut debug,
|
||||
&mut messages,
|
||||
&mut window_manager,
|
||||
&mut cached_interfaces,
|
||||
|
|
@ -794,7 +781,6 @@ async fn run_instance<A, E, C>(
|
|||
user_interfaces =
|
||||
ManuallyDrop::new(build_user_interfaces(
|
||||
&application,
|
||||
&mut debug,
|
||||
&mut window_manager,
|
||||
cached_interfaces,
|
||||
));
|
||||
|
|
@ -815,19 +801,18 @@ fn build_user_interface<'a, A: Application>(
|
|||
cache: user_interface::Cache,
|
||||
renderer: &mut A::Renderer,
|
||||
size: Size,
|
||||
debug: &mut Debug,
|
||||
id: window::Id,
|
||||
) -> UserInterface<'a, A::Message, A::Theme, A::Renderer>
|
||||
where
|
||||
A::Theme: StyleSheet,
|
||||
{
|
||||
debug.view_started();
|
||||
let view_timer = debug::view_time();
|
||||
let view = application.view(id);
|
||||
debug.view_finished();
|
||||
view_timer.finish();
|
||||
|
||||
debug.layout_started();
|
||||
let layout_timer = debug::layout_time();
|
||||
let user_interface = UserInterface::build(view, size, cache, renderer);
|
||||
debug.layout_finished();
|
||||
layout_timer.finish();
|
||||
|
||||
user_interface
|
||||
}
|
||||
|
|
@ -841,7 +826,6 @@ fn update<A: Application, C, E: Executor>(
|
|||
clipboard: &mut Clipboard,
|
||||
control_sender: &mut mpsc::UnboundedSender<Control>,
|
||||
proxy: &mut winit::event_loop::EventLoopProxy<A::Message>,
|
||||
debug: &mut Debug,
|
||||
messages: &mut Vec<A::Message>,
|
||||
window_manager: &mut WindowManager<A, C>,
|
||||
ui_caches: &mut HashMap<window::Id, user_interface::Cache>,
|
||||
|
|
@ -850,11 +834,11 @@ fn update<A: Application, C, E: Executor>(
|
|||
A::Theme: StyleSheet,
|
||||
{
|
||||
for message in messages.drain(..) {
|
||||
debug.log_message(&message);
|
||||
debug.update_started();
|
||||
debug::log_message(&message);
|
||||
|
||||
let update_timer = debug::update_time();
|
||||
let command = runtime.enter(|| application.update(message));
|
||||
debug.update_finished();
|
||||
update_timer.finish();
|
||||
|
||||
run_command(
|
||||
application,
|
||||
|
|
@ -864,7 +848,6 @@ fn update<A: Application, C, E: Executor>(
|
|||
clipboard,
|
||||
control_sender,
|
||||
proxy,
|
||||
debug,
|
||||
window_manager,
|
||||
ui_caches,
|
||||
);
|
||||
|
|
@ -883,7 +866,6 @@ fn run_command<A, C, E>(
|
|||
clipboard: &mut Clipboard,
|
||||
control_sender: &mut mpsc::UnboundedSender<Control>,
|
||||
proxy: &mut winit::event_loop::EventLoopProxy<A::Message>,
|
||||
debug: &mut Debug,
|
||||
window_manager: &mut WindowManager<A, C>,
|
||||
ui_caches: &mut HashMap<window::Id, user_interface::Cache>,
|
||||
) where
|
||||
|
|
@ -1118,7 +1100,6 @@ fn run_command<A, C, E>(
|
|||
&mut window.surface,
|
||||
window.state.viewport(),
|
||||
window.state.background_color(),
|
||||
&debug.overlay(),
|
||||
);
|
||||
|
||||
proxy
|
||||
|
|
@ -1155,7 +1136,6 @@ fn run_command<A, C, E>(
|
|||
|
||||
let mut uis = build_user_interfaces(
|
||||
application,
|
||||
debug,
|
||||
window_manager,
|
||||
std::mem::take(ui_caches),
|
||||
);
|
||||
|
|
@ -1211,7 +1191,6 @@ fn run_command<A, C, E>(
|
|||
/// Build the user interface for every window.
|
||||
pub fn build_user_interfaces<'a, A: Application, C: Compositor>(
|
||||
application: &'a A,
|
||||
debug: &mut Debug,
|
||||
window_manager: &mut WindowManager<A, C>,
|
||||
mut cached_user_interfaces: HashMap<window::Id, user_interface::Cache>,
|
||||
) -> HashMap<window::Id, UserInterface<'a, A::Message, A::Theme, A::Renderer>>
|
||||
|
|
@ -1231,7 +1210,6 @@ where
|
|||
cache,
|
||||
&mut window.renderer,
|
||||
window.state.logical_size(),
|
||||
debug,
|
||||
id,
|
||||
),
|
||||
))
|
||||
|
|
|
|||
|
|
@ -138,12 +138,7 @@ where
|
|||
}
|
||||
|
||||
/// Processes the provided window event and updates the [`State`] accordingly.
|
||||
pub fn update(
|
||||
&mut self,
|
||||
window: &Window,
|
||||
event: &WindowEvent,
|
||||
_debug: &mut crate::runtime::Debug,
|
||||
) {
|
||||
pub fn update(&mut self, window: &Window, event: &WindowEvent) {
|
||||
match event {
|
||||
WindowEvent::Resized(new_size) => {
|
||||
let size = Size::new(new_size.width, new_size.height);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue