Rename iced_sentinel to iced_beacon and refactor its API
This commit is contained in:
parent
aaf396256e
commit
57033dc4d0
19 changed files with 596 additions and 438 deletions
|
|
@ -106,7 +106,7 @@ members = [
|
||||||
"highlighter",
|
"highlighter",
|
||||||
"renderer",
|
"renderer",
|
||||||
"runtime",
|
"runtime",
|
||||||
"sentinel",
|
"beacon",
|
||||||
"tiny_skia",
|
"tiny_skia",
|
||||||
"wgpu",
|
"wgpu",
|
||||||
"widget",
|
"widget",
|
||||||
|
|
@ -126,6 +126,7 @@ keywords = ["gui", "ui", "graphics", "interface", "widgets"]
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
iced = { version = "0.13.0-dev", path = "." }
|
iced = { version = "0.13.0-dev", path = "." }
|
||||||
|
iced_beacon = { version = "0.13.0-dev", path = "beacon" }
|
||||||
iced_core = { version = "0.13.0-dev", path = "core" }
|
iced_core = { version = "0.13.0-dev", path = "core" }
|
||||||
iced_debug = { version = "0.13.0-dev", path = "debug" }
|
iced_debug = { version = "0.13.0-dev", path = "debug" }
|
||||||
iced_futures = { version = "0.13.0-dev", path = "futures" }
|
iced_futures = { version = "0.13.0-dev", path = "futures" }
|
||||||
|
|
@ -133,7 +134,6 @@ iced_graphics = { version = "0.13.0-dev", path = "graphics" }
|
||||||
iced_highlighter = { version = "0.13.0-dev", path = "highlighter" }
|
iced_highlighter = { version = "0.13.0-dev", path = "highlighter" }
|
||||||
iced_renderer = { version = "0.13.0-dev", path = "renderer" }
|
iced_renderer = { version = "0.13.0-dev", path = "renderer" }
|
||||||
iced_runtime = { version = "0.13.0-dev", path = "runtime" }
|
iced_runtime = { version = "0.13.0-dev", path = "runtime" }
|
||||||
iced_sentinel = { version = "0.13.0-dev", path = "sentinel" }
|
|
||||||
iced_tiny_skia = { version = "0.13.0-dev", path = "tiny_skia" }
|
iced_tiny_skia = { version = "0.13.0-dev", path = "tiny_skia" }
|
||||||
iced_wgpu = { version = "0.13.0-dev", path = "wgpu" }
|
iced_wgpu = { version = "0.13.0-dev", path = "wgpu" }
|
||||||
iced_widget = { version = "0.13.0-dev", path = "widget" }
|
iced_widget = { version = "0.13.0-dev", path = "widget" }
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "iced_sentinel"
|
name = "iced_beacon"
|
||||||
description = "A client/server protocol to monitor and supervise iced applications"
|
description = "A client/server protocol to monitor and supervise iced applications"
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
|
|
@ -17,6 +17,7 @@ iced_core.features = ["serde"]
|
||||||
bincode.workspace = true
|
bincode.workspace = true
|
||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
|
thiserror.workspace = true
|
||||||
|
|
||||||
tokio.workspace = true
|
tokio.workspace = true
|
||||||
tokio.features = ["rt", "rt-multi-thread", "net", "sync", "time", "io-util", "macros"]
|
tokio.features = ["rt", "rt-multi-thread", "net", "sync", "time", "io-util", "macros"]
|
||||||
123
beacon/src/client.rs
Normal file
123
beacon/src/client.rs
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
use crate::core::time::{Duration, SystemTime};
|
||||||
|
use crate::span;
|
||||||
|
use crate::theme;
|
||||||
|
|
||||||
|
use semver::Version;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use tokio::io::{self, AsyncWriteExt};
|
||||||
|
use tokio::net;
|
||||||
|
use tokio::sync::mpsc;
|
||||||
|
use tokio::time;
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::thread;
|
||||||
|
|
||||||
|
pub const SERVER_ADDRESS: &str = "127.0.0.1:9167";
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Client {
|
||||||
|
sender: mpsc::Sender<Message>,
|
||||||
|
_handle: Arc<thread::JoinHandle<()>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub enum Message {
|
||||||
|
Connected {
|
||||||
|
at: SystemTime,
|
||||||
|
name: String,
|
||||||
|
version: Version,
|
||||||
|
},
|
||||||
|
EventLogged {
|
||||||
|
at: SystemTime,
|
||||||
|
event: Event,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub enum Event {
|
||||||
|
ThemeChanged(theme::Palette),
|
||||||
|
SpanStarted(span::Stage),
|
||||||
|
SpanFinished(span::Stage, Duration),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Client {
|
||||||
|
pub fn log(&self, event: Event) {
|
||||||
|
let _ = self.sender.try_send(Message::EventLogged {
|
||||||
|
at: SystemTime::now(),
|
||||||
|
event,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn connect(name: String) -> Client {
|
||||||
|
let (sender, receiver) = mpsc::channel(100);
|
||||||
|
|
||||||
|
let handle = std::thread::spawn(move || run(name, receiver));
|
||||||
|
|
||||||
|
Client {
|
||||||
|
sender,
|
||||||
|
_handle: Arc::new(handle),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn run(name: String, mut receiver: mpsc::Receiver<Message>) {
|
||||||
|
let version = semver::Version::parse(env!("CARGO_PKG_VERSION"))
|
||||||
|
.expect("Parse package version");
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match _connect().await {
|
||||||
|
Ok(mut stream) => {
|
||||||
|
let _ = send(
|
||||||
|
&mut stream,
|
||||||
|
Message::Connected {
|
||||||
|
at: SystemTime::now(),
|
||||||
|
name: name.clone(),
|
||||||
|
version: version.clone(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
while let Some(output) = receiver.recv().await {
|
||||||
|
match send(&mut stream, output).await {
|
||||||
|
Ok(()) => {}
|
||||||
|
Err(error) => {
|
||||||
|
log::warn!(
|
||||||
|
"Error sending message to server: {error}"
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
time::sleep(time::Duration::from_secs(2)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn _connect() -> Result<net::TcpStream, io::Error> {
|
||||||
|
log::debug!("Attempting to connect to server...");
|
||||||
|
let stream = net::TcpStream::connect(SERVER_ADDRESS).await?;
|
||||||
|
|
||||||
|
stream.set_nodelay(true)?;
|
||||||
|
stream.writable().await?;
|
||||||
|
|
||||||
|
Ok(stream)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn send(
|
||||||
|
stream: &mut net::TcpStream,
|
||||||
|
message: Message,
|
||||||
|
) -> Result<(), io::Error> {
|
||||||
|
let bytes = bincode::serialize(&message).expect("Encode input message");
|
||||||
|
let size = bytes.len() as u64;
|
||||||
|
|
||||||
|
stream.write_all(&size.to_be_bytes()).await?;
|
||||||
|
stream.write_all(&bytes).await?;
|
||||||
|
stream.flush().await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
184
beacon/src/lib.rs
Normal file
184
beacon/src/lib.rs
Normal file
|
|
@ -0,0 +1,184 @@
|
||||||
|
pub use iced_core as core;
|
||||||
|
pub use semver::Version;
|
||||||
|
|
||||||
|
pub mod client;
|
||||||
|
pub mod span;
|
||||||
|
|
||||||
|
mod stream;
|
||||||
|
|
||||||
|
pub use client::Client;
|
||||||
|
pub use span::Span;
|
||||||
|
|
||||||
|
use crate::core::theme;
|
||||||
|
use crate::core::time::{Duration, SystemTime};
|
||||||
|
|
||||||
|
use futures::{SinkExt, Stream};
|
||||||
|
use tokio::io::{self, AsyncReadExt};
|
||||||
|
use tokio::net;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Event {
|
||||||
|
Connected {
|
||||||
|
at: SystemTime,
|
||||||
|
name: String,
|
||||||
|
version: Version,
|
||||||
|
},
|
||||||
|
Disconnected {
|
||||||
|
at: SystemTime,
|
||||||
|
},
|
||||||
|
ThemeChanged {
|
||||||
|
at: SystemTime,
|
||||||
|
palette: theme::Palette,
|
||||||
|
},
|
||||||
|
SpanFinished {
|
||||||
|
at: SystemTime,
|
||||||
|
duration: Duration,
|
||||||
|
span: Span,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Event {
|
||||||
|
pub fn at(&self) -> SystemTime {
|
||||||
|
match self {
|
||||||
|
Self::Connected { at, .. }
|
||||||
|
| Self::Disconnected { at, .. }
|
||||||
|
| Self::ThemeChanged { at, .. }
|
||||||
|
| Self::SpanFinished { at, .. } => *at,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run() -> impl Stream<Item = Event> {
|
||||||
|
stream::channel(|mut output| async move {
|
||||||
|
let mut buffer = Vec::new();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let Ok(mut stream) = connect().await else {
|
||||||
|
delay().await;
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match receive(&mut stream, &mut buffer).await {
|
||||||
|
Ok(message) => {
|
||||||
|
match message {
|
||||||
|
client::Message::Connected {
|
||||||
|
at,
|
||||||
|
name,
|
||||||
|
version,
|
||||||
|
} => {
|
||||||
|
let _ = output
|
||||||
|
.send(Event::Connected {
|
||||||
|
at,
|
||||||
|
name,
|
||||||
|
version,
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
client::Message::EventLogged { at, event } => {
|
||||||
|
match event {
|
||||||
|
client::Event::ThemeChanged(palette) => {
|
||||||
|
let _ = output
|
||||||
|
.send(Event::ThemeChanged {
|
||||||
|
at,
|
||||||
|
palette,
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
client::Event::SpanStarted(_) => {}
|
||||||
|
client::Event::SpanFinished(
|
||||||
|
stage,
|
||||||
|
duration,
|
||||||
|
) => {
|
||||||
|
let span = match stage {
|
||||||
|
span::Stage::Boot => Span::Boot,
|
||||||
|
span::Stage::Update => Span::Update,
|
||||||
|
span::Stage::View(window) => {
|
||||||
|
Span::View { window }
|
||||||
|
}
|
||||||
|
span::Stage::Layout(window) => {
|
||||||
|
Span::Layout { window }
|
||||||
|
}
|
||||||
|
span::Stage::Interact(window) => {
|
||||||
|
Span::Interact { window }
|
||||||
|
}
|
||||||
|
span::Stage::Draw(window) => {
|
||||||
|
Span::Draw { window }
|
||||||
|
}
|
||||||
|
span::Stage::Present(window) => {
|
||||||
|
Span::Present { window }
|
||||||
|
}
|
||||||
|
span::Stage::Custom(
|
||||||
|
window,
|
||||||
|
name,
|
||||||
|
) => Span::Custom { window, name },
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = output
|
||||||
|
.send(Event::SpanFinished {
|
||||||
|
at,
|
||||||
|
duration,
|
||||||
|
span,
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Err(Error::IOFailed(_)) => {
|
||||||
|
let _ = output
|
||||||
|
.send(Event::Disconnected {
|
||||||
|
at: SystemTime::now(),
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
delay().await;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Err(Error::DecodingFailed(error)) => {
|
||||||
|
log::warn!("Error decoding beacon output: {error}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn connect() -> Result<net::TcpStream, io::Error> {
|
||||||
|
let listener = net::TcpListener::bind(client::SERVER_ADDRESS).await?;
|
||||||
|
|
||||||
|
let (stream, _) = listener.accept().await?;
|
||||||
|
|
||||||
|
stream.set_nodelay(true)?;
|
||||||
|
stream.readable().await?;
|
||||||
|
|
||||||
|
Ok(stream)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn receive(
|
||||||
|
stream: &mut net::TcpStream,
|
||||||
|
buffer: &mut Vec<u8>,
|
||||||
|
) -> Result<client::Message, Error> {
|
||||||
|
let size = stream.read_u64().await? as usize;
|
||||||
|
|
||||||
|
if buffer.len() < size {
|
||||||
|
buffer.resize(size, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let _n = stream.read_exact(&mut buffer[..size]).await?;
|
||||||
|
|
||||||
|
Ok(bincode::deserialize(buffer)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delay() {
|
||||||
|
tokio::time::sleep(Duration::from_secs(2)).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
enum Error {
|
||||||
|
#[error("input/output operation failed: {0}")]
|
||||||
|
IOFailed(#[from] io::Error),
|
||||||
|
#[error("decoding failed: {0}")]
|
||||||
|
DecodingFailed(#[from] Box<bincode::ErrorKind>),
|
||||||
|
}
|
||||||
61
beacon/src/span.rs
Normal file
61
beacon/src/span.rs
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
use crate::core::window;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub enum Span {
|
||||||
|
Boot,
|
||||||
|
Update,
|
||||||
|
View { window: window::Id },
|
||||||
|
Layout { window: window::Id },
|
||||||
|
Interact { window: window::Id },
|
||||||
|
Draw { window: window::Id },
|
||||||
|
Present { window: window::Id },
|
||||||
|
Custom { window: window::Id, name: String },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Span {
|
||||||
|
pub fn stage(&self) -> Stage {
|
||||||
|
match self {
|
||||||
|
Span::Boot => Stage::Boot,
|
||||||
|
Span::Update => Stage::Update,
|
||||||
|
Span::View { window } => Stage::View(*window),
|
||||||
|
Span::Layout { window } => Stage::Layout(*window),
|
||||||
|
Span::Interact { window } => Stage::Interact(*window),
|
||||||
|
Span::Draw { window } => Stage::Draw(*window),
|
||||||
|
Span::Present { window } => Stage::Present(*window),
|
||||||
|
Span::Custom { window, name } => {
|
||||||
|
Stage::Custom(*window, name.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
|
||||||
|
)]
|
||||||
|
pub enum Stage {
|
||||||
|
Boot,
|
||||||
|
Update,
|
||||||
|
View(window::Id),
|
||||||
|
Layout(window::Id),
|
||||||
|
Interact(window::Id),
|
||||||
|
Draw(window::Id),
|
||||||
|
Present(window::Id),
|
||||||
|
Custom(window::Id, String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Stage {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.write_str(match self {
|
||||||
|
Stage::Boot => "Boot",
|
||||||
|
Stage::Update => "Update",
|
||||||
|
Stage::View(_) => "View",
|
||||||
|
Stage::Layout(_) => "Layout",
|
||||||
|
Stage::Interact(_) => "Interact",
|
||||||
|
Stage::Draw(_) => "Draw",
|
||||||
|
Stage::Present(_) => "Present",
|
||||||
|
Stage::Custom(_, name) => name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
15
beacon/src/stream.rs
Normal file
15
beacon/src/stream.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
use futures::channel::mpsc;
|
||||||
|
use futures::stream::{self, Stream, StreamExt};
|
||||||
|
use futures::Future;
|
||||||
|
|
||||||
|
pub fn channel<T, F>(f: impl Fn(mpsc::Sender<T>) -> F) -> impl Stream<Item = T>
|
||||||
|
where
|
||||||
|
F: Future<Output = ()>,
|
||||||
|
{
|
||||||
|
let (sender, receiver) = mpsc::channel(1);
|
||||||
|
|
||||||
|
stream::select(
|
||||||
|
receiver,
|
||||||
|
stream::once(f(sender)).filter_map(|_| async { None }),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -11,13 +11,13 @@ categories.workspace = true
|
||||||
keywords.workspace = true
|
keywords.workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
enable = ["dep:iced_sentinel", "dep:once_cell"]
|
enable = ["dep:iced_beacon", "dep:once_cell"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
iced_core.workspace = true
|
iced_core.workspace = true
|
||||||
|
|
||||||
iced_sentinel.workspace = true
|
iced_beacon.workspace = true
|
||||||
iced_sentinel.optional = true
|
iced_beacon.optional = true
|
||||||
|
|
||||||
once_cell.workspace = true
|
once_cell.workspace = true
|
||||||
once_cell.optional = true
|
once_cell.optional = true
|
||||||
|
|
|
||||||
198
debug/src/lib.rs
198
debug/src/lib.rs
|
|
@ -3,45 +3,49 @@ pub use iced_core as core;
|
||||||
use crate::core::theme;
|
use crate::core::theme;
|
||||||
use crate::core::window;
|
use crate::core::window;
|
||||||
|
|
||||||
pub use internal::Timer;
|
pub use internal::Span;
|
||||||
|
|
||||||
pub fn open_axe() {}
|
pub fn init(name: &str) {
|
||||||
|
internal::init(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn open_comet() {}
|
||||||
|
|
||||||
pub fn log_message(_message: &impl std::fmt::Debug) {}
|
pub fn log_message(_message: &impl std::fmt::Debug) {}
|
||||||
|
|
||||||
pub fn theme_changed(palette: theme::Palette) {
|
pub fn theme_changed(f: impl FnOnce() -> Option<theme::Palette>) {
|
||||||
internal::theme_changed(palette);
|
internal::theme_changed(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn boot_time() -> Timer {
|
pub fn boot() -> Span {
|
||||||
internal::boot_time()
|
internal::boot()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_time() -> Timer {
|
pub fn update() -> Span {
|
||||||
internal::update_time()
|
internal::update()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view_time(window: window::Id) -> Timer {
|
pub fn view(window: window::Id) -> Span {
|
||||||
internal::view_time(window)
|
internal::view(window)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn layout_time(window: window::Id) -> Timer {
|
pub fn layout(window: window::Id) -> Span {
|
||||||
internal::layout_time(window)
|
internal::layout(window)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn interact_time(window: window::Id) -> Timer {
|
pub fn interact(window: window::Id) -> Span {
|
||||||
internal::interact_time(window)
|
internal::interact(window)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_time(window: window::Id) -> Timer {
|
pub fn draw(window: window::Id) -> Span {
|
||||||
internal::draw_time(window)
|
internal::draw(window)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_time(window: window::Id) -> Timer {
|
pub fn present(window: window::Id) -> Span {
|
||||||
internal::render_time(window)
|
internal::present(window)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn time(window: window::Id, name: impl AsRef<str>) -> Timer {
|
pub fn time(window: window::Id, name: impl AsRef<str>) -> Span {
|
||||||
internal::time(window, name)
|
internal::time(window, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -52,158 +56,156 @@ pub fn skip_next_timing() {
|
||||||
#[cfg(feature = "enable")]
|
#[cfg(feature = "enable")]
|
||||||
mod internal {
|
mod internal {
|
||||||
use crate::core::theme;
|
use crate::core::theme;
|
||||||
use crate::core::time::{Instant, SystemTime};
|
use crate::core::time::Instant;
|
||||||
use crate::core::window;
|
use crate::core::window;
|
||||||
|
|
||||||
use iced_sentinel::client::{self, Client};
|
use iced_beacon as beacon;
|
||||||
use iced_sentinel::timing::{self, Timing};
|
|
||||||
|
use beacon::client::{self, Client};
|
||||||
|
use beacon::span;
|
||||||
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use std::sync::{Mutex, MutexGuard};
|
use std::sync::atomic::{self, AtomicBool};
|
||||||
|
use std::sync::RwLock;
|
||||||
|
|
||||||
pub fn theme_changed(palette: theme::Palette) {
|
pub fn init(name: &str) {
|
||||||
let mut debug = lock();
|
name.clone_into(&mut NAME.write().expect("Write application name"));
|
||||||
|
}
|
||||||
|
|
||||||
if debug.last_palette.as_ref() != Some(&palette) {
|
pub fn theme_changed(f: impl FnOnce() -> Option<theme::Palette>) {
|
||||||
debug.sentinel.report_theme_change(palette);
|
let Some(palette) = f() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
debug.last_palette = Some(palette);
|
if LAST_PALETTE.read().expect("Read last palette").as_ref()
|
||||||
|
!= Some(&palette)
|
||||||
|
{
|
||||||
|
BEACON.log(client::Event::ThemeChanged(palette));
|
||||||
|
|
||||||
|
*LAST_PALETTE.write().expect("Write last palette") = Some(palette);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn boot_time() -> Timer {
|
pub fn boot() -> Span {
|
||||||
timer(timing::Stage::Boot)
|
span(span::Stage::Boot)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_time() -> Timer {
|
pub fn update() -> Span {
|
||||||
timer(timing::Stage::Update)
|
span(span::Stage::Update)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view_time(window: window::Id) -> Timer {
|
pub fn view(window: window::Id) -> Span {
|
||||||
timer(timing::Stage::View(window))
|
span(span::Stage::View(window))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn layout_time(window: window::Id) -> Timer {
|
pub fn layout(window: window::Id) -> Span {
|
||||||
timer(timing::Stage::Layout(window))
|
span(span::Stage::Layout(window))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn interact_time(window: window::Id) -> Timer {
|
pub fn interact(window: window::Id) -> Span {
|
||||||
timer(timing::Stage::Interact(window))
|
span(span::Stage::Interact(window))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_time(window: window::Id) -> Timer {
|
pub fn draw(window: window::Id) -> Span {
|
||||||
timer(timing::Stage::Draw(window))
|
span(span::Stage::Draw(window))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_time(window: window::Id) -> Timer {
|
pub fn present(window: window::Id) -> Span {
|
||||||
timer(timing::Stage::Render(window))
|
span(span::Stage::Present(window))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn time(window: window::Id, name: impl AsRef<str>) -> Timer {
|
pub fn time(window: window::Id, name: impl AsRef<str>) -> Span {
|
||||||
timer(timing::Stage::Custom(window, name.as_ref().to_owned()))
|
span(span::Stage::Custom(window, name.as_ref().to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn skip_next_timing() {
|
pub fn skip_next_timing() {
|
||||||
lock().skip_next_timing = true;
|
SKIP_NEXT_SPAN.store(true, atomic::Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn timer(stage: timing::Stage) -> Timer {
|
fn span(span: span::Stage) -> Span {
|
||||||
Timer {
|
BEACON.log(client::Event::SpanStarted(span.clone()));
|
||||||
stage,
|
|
||||||
|
Span {
|
||||||
|
span,
|
||||||
start: Instant::now(),
|
start: Instant::now(),
|
||||||
start_system_time: SystemTime::now(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Timer {
|
pub struct Span {
|
||||||
stage: timing::Stage,
|
span: span::Stage,
|
||||||
start: Instant,
|
start: Instant,
|
||||||
start_system_time: SystemTime,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Timer {
|
impl Span {
|
||||||
pub fn finish(self) {
|
pub fn finish(self) {
|
||||||
let mut debug = lock();
|
if SKIP_NEXT_SPAN.fetch_and(false, atomic::Ordering::Relaxed) {
|
||||||
|
|
||||||
if debug.skip_next_timing {
|
|
||||||
debug.skip_next_timing = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug.sentinel.report_timing(Timing {
|
BEACON.log(client::Event::SpanFinished(
|
||||||
stage: self.stage,
|
self.span,
|
||||||
start: self.start_system_time,
|
self.start.elapsed(),
|
||||||
duration: self.start.elapsed(),
|
));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
static BEACON: Lazy<Client> = Lazy::new(|| {
|
||||||
struct Debug {
|
client::connect(NAME.read().expect("Read application name").to_owned())
|
||||||
sentinel: Client,
|
|
||||||
last_palette: Option<theme::Palette>,
|
|
||||||
skip_next_timing: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lock() -> MutexGuard<'static, Debug> {
|
|
||||||
static DEBUG: Lazy<Mutex<Debug>> = Lazy::new(|| {
|
|
||||||
Mutex::new(Debug {
|
|
||||||
sentinel: client::connect(),
|
|
||||||
last_palette: None,
|
|
||||||
skip_next_timing: false,
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
DEBUG.lock().expect("Acquire debug lock")
|
static NAME: RwLock<String> = RwLock::new(String::new());
|
||||||
}
|
static LAST_PALETTE: RwLock<Option<theme::Palette>> = RwLock::new(None);
|
||||||
|
static SKIP_NEXT_SPAN: AtomicBool = AtomicBool::new(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "enable"))]
|
#[cfg(not(feature = "enable"))]
|
||||||
mod internal {
|
mod internal {
|
||||||
|
use crate::core::theme;
|
||||||
use crate::core::window;
|
use crate::core::window;
|
||||||
use crate::style::theme;
|
|
||||||
|
|
||||||
pub fn theme_changed(_palette: theme::Palette) {}
|
pub fn init(_name: &str) {}
|
||||||
|
|
||||||
pub fn boot_time() -> Timer {
|
pub fn theme_changed(_f: impl FnOnce() -> Option<theme::Palette>) {}
|
||||||
Timer
|
|
||||||
|
pub fn boot() -> Span {
|
||||||
|
Span
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_time() -> Timer {
|
pub fn update() -> Span {
|
||||||
Timer
|
Span
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view_time(_window: window::Id) -> Timer {
|
pub fn view(_window: window::Id) -> Span {
|
||||||
Timer
|
Span
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn layout_time(_window: window::Id) -> Timer {
|
pub fn layout(_window: window::Id) -> Span {
|
||||||
Timer
|
Span
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn interact_time(_window: window::Id) -> Timer {
|
pub fn interact(_window: window::Id) -> Span {
|
||||||
Timer
|
Span
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_time(_window: window::Id) -> Timer {
|
pub fn draw(_window: window::Id) -> Span {
|
||||||
Timer
|
Span
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_time(_window: window::Id) -> Timer {
|
pub fn present(_window: window::Id) -> Span {
|
||||||
Timer
|
Span
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn time(_window: window::Id, _name: impl AsRef<str>) -> Timer {
|
pub fn time(_window: window::Id, _name: impl AsRef<str>) -> Span {
|
||||||
Timer
|
Span
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn skip_next_timing() {}
|
pub fn skip_next_timing() {}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Timer;
|
pub struct Span;
|
||||||
|
|
||||||
impl Timer {
|
impl Span {
|
||||||
pub fn finish(self) {}
|
pub fn finish(self) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
docs/logo-no-shadow.svg
Normal file
2
docs/logo-no-shadow.svg
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="140" height="140" fill="none" version="1.1" viewBox="35 31 179 171"><rect x="42" y="31.001" width="169.9" height="169.9" rx="49.815" fill="url(#paint1_linear)"/><path d="m182.62 65.747-28.136 28.606-6.13-6.0291 28.136-28.606 6.13 6.0291zm-26.344 0.218-42.204 42.909-6.13-6.029 42.204-42.909 6.13 6.0291zm-61.648 23.913c5.3254-5.3831 10.65-10.765 21.569-21.867l6.13 6.0291c-10.927 11.11-16.258 16.498-21.587 21.885-4.4007 4.4488-8.8009 8.8968-16.359 16.573l31.977 8.358 25.968-26.402 6.13 6.0292-25.968 26.402 8.907 31.908 42.138-42.087 6.076 6.083-49.109 49.05-45.837-12.628-13.394-45.646 1.7714-1.801c10.928-11.111 16.258-16.499 21.588-21.886zm28.419 70.99-8.846-31.689-31.831-8.32 9.1945 31.335 31.482 8.674zm47.734-56.517 7.122-7.1221-6.08-6.0797-7.147 7.1474-30.171 30.674 6.13 6.029 30.146-30.649z" clip-rule="evenodd" fill="url(#paint2_linear)" fill-rule="evenodd"/><defs><filter id="filter0_f" x="55" y="47.001" width="144" height="168" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur" stdDeviation="2"/></filter><linearGradient id="paint0_linear" x1="127" x2="127" y1="51.001" y2="211" gradientUnits="userSpaceOnUse"><stop offset=".052083"/><stop stop-opacity=".08" offset="1"/></linearGradient><linearGradient id="paint1_linear" x1="212" x2="57.5" y1="31.001" y2="189" gradientUnits="userSpaceOnUse"><stop stop-color="#00A3FF" offset="0"/><stop stop-color="#30f" offset="1"/></linearGradient><linearGradient id="paint2_linear" x1="86.098" x2="206.01" y1="158.28" y2="35.327" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient></defs></svg>
|
||||||
|
After Width: | Height: | Size: 1.8 KiB |
|
|
@ -102,7 +102,7 @@ where
|
||||||
bounds,
|
bounds,
|
||||||
);
|
);
|
||||||
|
|
||||||
let interact_timer = debug::interact_time(window::Id::MAIN);
|
let interact_span = debug::interact(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(
|
||||||
|
|
@ -125,13 +125,13 @@ where
|
||||||
|
|
||||||
self.queued_events.clear();
|
self.queued_events.clear();
|
||||||
messages.append(&mut self.queued_messages);
|
messages.append(&mut self.queued_messages);
|
||||||
drop(interact_timer);
|
interact_span.finish();
|
||||||
|
|
||||||
let command = if messages.is_empty() {
|
let command = if messages.is_empty() {
|
||||||
let draw_timer = debug::draw_time(window::Id::MAIN);
|
let draw_span = debug::draw(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);
|
draw_span.finish();
|
||||||
|
|
||||||
self.cache = Some(user_interface.into_cache());
|
self.cache = Some(user_interface.into_cache());
|
||||||
|
|
||||||
|
|
@ -145,9 +145,9 @@ where
|
||||||
Command::batch(messages.into_iter().map(|message| {
|
Command::batch(messages.into_iter().map(|message| {
|
||||||
debug::log_message(&message);
|
debug::log_message(&message);
|
||||||
|
|
||||||
let update_timer = debug::update_time();
|
let update_span = debug::update();
|
||||||
let command = self.program.update(message);
|
let command = self.program.update(message);
|
||||||
drop(update_timer);
|
update_span.finish();
|
||||||
|
|
||||||
command
|
command
|
||||||
}));
|
}));
|
||||||
|
|
@ -159,10 +159,10 @@ where
|
||||||
bounds,
|
bounds,
|
||||||
);
|
);
|
||||||
|
|
||||||
let draw_timer = debug::draw_time(window::Id::MAIN);
|
let draw_spawn = debug::draw(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);
|
draw_spawn.finish();
|
||||||
|
|
||||||
self.cache = Some(user_interface.into_cache());
|
self.cache = Some(user_interface.into_cache());
|
||||||
|
|
||||||
|
|
@ -214,13 +214,13 @@ 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(window::Id::MAIN);
|
let view_span = debug::view(window::Id::MAIN);
|
||||||
let view = program.view();
|
let view = program.view();
|
||||||
drop(view_timer);
|
view_span.finish();
|
||||||
|
|
||||||
let layout_timer = debug::layout_time(window::Id::MAIN);
|
let layout_span = debug::layout(window::Id::MAIN);
|
||||||
let user_interface = UserInterface::build(view, size, cache, renderer);
|
let user_interface = UserInterface::build(view, size, cache, renderer);
|
||||||
drop(layout_timer);
|
layout_span.finish();
|
||||||
|
|
||||||
user_interface
|
user_interface
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,93 +0,0 @@
|
||||||
use crate::core::time::SystemTime;
|
|
||||||
use crate::theme;
|
|
||||||
use crate::{Input, Timing, 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_theme_change(&mut self, palette: theme::Palette) {
|
|
||||||
let _ = self.sender.try_send(Input::ThemeChanged {
|
|
||||||
at: SystemTime::now(),
|
|
||||||
palette,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn report_timing(&mut self, timing: Timing) {
|
|
||||||
let _ = self.sender.try_send(Input::TimingMeasured(timing));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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 {
|
|
||||||
at: SystemTime::now(),
|
|
||||||
version: version.clone(),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
while let Some(input) = receiver.recv().await {
|
|
||||||
match send(&mut stream, input).await {
|
|
||||||
Ok(()) => {}
|
|
||||||
Err(error) => {
|
|
||||||
log::warn!("Error sending message to sentinel server: {error}");
|
|
||||||
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> {
|
|
||||||
let bytes = bincode::serialize(&input).expect("Encode input message");
|
|
||||||
let size = bytes.len() as u64;
|
|
||||||
|
|
||||||
stream.write_all(&size.to_be_bytes()).await?;
|
|
||||||
stream.write_all(&bytes).await?;
|
|
||||||
stream.flush().await?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
@ -1,137 +0,0 @@
|
||||||
pub use iced_core as core;
|
|
||||||
pub use semver::Version;
|
|
||||||
|
|
||||||
pub mod client;
|
|
||||||
pub mod timing;
|
|
||||||
|
|
||||||
use crate::core::theme;
|
|
||||||
use crate::core::time::SystemTime;
|
|
||||||
use crate::timing::Timing;
|
|
||||||
|
|
||||||
use futures::future;
|
|
||||||
use futures::stream::{self, Stream, StreamExt};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use tokio::io::{self, AsyncReadExt, BufStream};
|
|
||||||
use tokio::net;
|
|
||||||
|
|
||||||
pub const SOCKET_ADDRESS: &str = "127.0.0.1:9167";
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub enum Input {
|
|
||||||
Connected {
|
|
||||||
at: SystemTime,
|
|
||||||
version: Version,
|
|
||||||
},
|
|
||||||
ThemeChanged {
|
|
||||||
at: SystemTime,
|
|
||||||
palette: theme::Palette,
|
|
||||||
},
|
|
||||||
TimingMeasured(Timing),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum Event {
|
|
||||||
Connected {
|
|
||||||
at: SystemTime,
|
|
||||||
version: Version,
|
|
||||||
},
|
|
||||||
Disconnected {
|
|
||||||
at: SystemTime,
|
|
||||||
},
|
|
||||||
ThemeChanged {
|
|
||||||
at: SystemTime,
|
|
||||||
palette: theme::Palette,
|
|
||||||
},
|
|
||||||
TimingMeasured(Timing),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Event {
|
|
||||||
pub fn at(&self) -> SystemTime {
|
|
||||||
match self {
|
|
||||||
Self::Connected { at, .. }
|
|
||||||
| Self::Disconnected { at }
|
|
||||||
| Self::ThemeChanged { at, .. } => *at,
|
|
||||||
Self::TimingMeasured(timing) => timing.start,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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((stream, input)) => {
|
|
||||||
let event = match input {
|
|
||||||
Input::Connected { at, version } => {
|
|
||||||
Event::Connected { at, version }
|
|
||||||
}
|
|
||||||
Input::TimingMeasured(timing) => {
|
|
||||||
Event::TimingMeasured(timing)
|
|
||||||
}
|
|
||||||
Input::ThemeChanged { at, palette } => {
|
|
||||||
Event::ThemeChanged { at, palette }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Some((Some(event), State::Connected(stream)))
|
|
||||||
}
|
|
||||||
Err(_) => Some((
|
|
||||||
Some(Event::Disconnected {
|
|
||||||
at: SystemTime::now(),
|
|
||||||
}),
|
|
||||||
State::Disconnected,
|
|
||||||
)),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.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>, Input), io::Error> {
|
|
||||||
let mut bytes = Vec::new();
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let size = stream.read_u64().await? as usize;
|
|
||||||
|
|
||||||
if bytes.len() < size {
|
|
||||||
bytes.resize(size, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
let _n = stream.read_exact(&mut bytes[..size]).await?;
|
|
||||||
|
|
||||||
match bincode::deserialize(&bytes) {
|
|
||||||
Ok(input) => {
|
|
||||||
return Ok((stream, input));
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
log::warn!("Error decoding sentinel message");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
use crate::core::time::{Duration, SystemTime};
|
|
||||||
use crate::core::window;
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
#[derive(
|
|
||||||
Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
|
|
||||||
)]
|
|
||||||
pub struct Timing {
|
|
||||||
pub stage: Stage,
|
|
||||||
pub start: SystemTime,
|
|
||||||
pub duration: Duration,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(
|
|
||||||
Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
|
|
||||||
)]
|
|
||||||
pub enum Stage {
|
|
||||||
Boot,
|
|
||||||
Update,
|
|
||||||
View(window::Id),
|
|
||||||
Layout(window::Id),
|
|
||||||
Interact(window::Id),
|
|
||||||
Draw(window::Id),
|
|
||||||
Render(window::Id),
|
|
||||||
Custom(window::Id, String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for Stage {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::Boot => write!(f, "Boot"),
|
|
||||||
Self::Update => write!(f, "Update"),
|
|
||||||
Self::View(_) => write!(f, "View"),
|
|
||||||
Self::Layout(_) => write!(f, "Layout"),
|
|
||||||
Self::Interact(_) => write!(f, "Interact"),
|
|
||||||
Self::Draw(_) => write!(f, "Draw"),
|
|
||||||
Self::Render(_) => write!(f, "Render"),
|
|
||||||
Self::Custom(_, name) => f.write_str(name),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -118,6 +118,9 @@ where
|
||||||
/// The data needed to initialize your [`Application`].
|
/// The data needed to initialize your [`Application`].
|
||||||
type Flags;
|
type Flags;
|
||||||
|
|
||||||
|
/// Returns the unique name of the [`Application`].
|
||||||
|
fn name() -> &'static str;
|
||||||
|
|
||||||
/// Initializes the [`Application`] with the flags provided to
|
/// Initializes the [`Application`] with the flags provided to
|
||||||
/// [`run`] as part of the [`Settings`].
|
/// [`run`] as part of the [`Settings`].
|
||||||
///
|
///
|
||||||
|
|
@ -250,6 +253,10 @@ where
|
||||||
{
|
{
|
||||||
type Flags = A::Flags;
|
type Flags = A::Flags;
|
||||||
|
|
||||||
|
fn name() -> &'static str {
|
||||||
|
A::name()
|
||||||
|
}
|
||||||
|
|
||||||
fn new(flags: Self::Flags) -> (Self, Command<A::Message>) {
|
fn new(flags: Self::Flags) -> (Self, Command<A::Message>) {
|
||||||
let (app, command) = A::new(flags);
|
let (app, command) = A::new(flags);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,12 @@ where
|
||||||
type Renderer = Renderer;
|
type Renderer = Renderer;
|
||||||
type Executor = executor::Default;
|
type Executor = executor::Default;
|
||||||
|
|
||||||
|
fn name() -> &'static str {
|
||||||
|
let type_name = std::any::type_name::<State>();
|
||||||
|
|
||||||
|
type_name.split("::").next().unwrap_or(type_name)
|
||||||
|
}
|
||||||
|
|
||||||
fn load(&self) -> Command<Self::Message> {
|
fn load(&self) -> Command<Self::Message> {
|
||||||
Command::none()
|
Command::none()
|
||||||
}
|
}
|
||||||
|
|
@ -211,6 +217,10 @@ impl<P: Definition> Program<P> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn name() -> &'static str {
|
||||||
|
P::name()
|
||||||
|
}
|
||||||
|
|
||||||
fn title(&self) -> String {
|
fn title(&self) -> String {
|
||||||
self.program.title(&self.state)
|
self.program.title(&self.state)
|
||||||
}
|
}
|
||||||
|
|
@ -431,6 +441,8 @@ pub trait Definition: Sized {
|
||||||
/// The executor of the program.
|
/// The executor of the program.
|
||||||
type Executor: Executor;
|
type Executor: Executor;
|
||||||
|
|
||||||
|
fn name() -> &'static str;
|
||||||
|
|
||||||
fn load(&self) -> Command<Self::Message>;
|
fn load(&self) -> Command<Self::Message>;
|
||||||
|
|
||||||
fn update(
|
fn update(
|
||||||
|
|
@ -484,12 +496,16 @@ fn with_title<P: Definition>(
|
||||||
type Renderer = P::Renderer;
|
type Renderer = P::Renderer;
|
||||||
type Executor = P::Executor;
|
type Executor = P::Executor;
|
||||||
|
|
||||||
|
fn title(&self, state: &Self::State) -> String {
|
||||||
|
self.title.title(state)
|
||||||
|
}
|
||||||
|
|
||||||
fn load(&self) -> Command<Self::Message> {
|
fn load(&self) -> Command<Self::Message> {
|
||||||
self.program.load()
|
self.program.load()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self, state: &Self::State) -> String {
|
fn name() -> &'static str {
|
||||||
self.title.title(state)
|
P::name()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(
|
fn update(
|
||||||
|
|
@ -553,6 +569,10 @@ fn with_load<P: Definition>(
|
||||||
Command::batch([self.program.load(), (self.load)()])
|
Command::batch([self.program.load(), (self.load)()])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn name() -> &'static str {
|
||||||
|
P::name()
|
||||||
|
}
|
||||||
|
|
||||||
fn update(
|
fn update(
|
||||||
&self,
|
&self,
|
||||||
state: &mut Self::State,
|
state: &mut Self::State,
|
||||||
|
|
@ -621,6 +641,10 @@ fn with_subscription<P: Definition>(
|
||||||
(self.subscription)(state)
|
(self.subscription)(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn name() -> &'static str {
|
||||||
|
P::name()
|
||||||
|
}
|
||||||
|
|
||||||
fn load(&self) -> Command<Self::Message> {
|
fn load(&self) -> Command<Self::Message> {
|
||||||
self.program.load()
|
self.program.load()
|
||||||
}
|
}
|
||||||
|
|
@ -686,6 +710,10 @@ fn with_theme<P: Definition>(
|
||||||
(self.theme)(state)
|
(self.theme)(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn name() -> &'static str {
|
||||||
|
P::name()
|
||||||
|
}
|
||||||
|
|
||||||
fn load(&self) -> Command<Self::Message> {
|
fn load(&self) -> Command<Self::Message> {
|
||||||
self.program.load()
|
self.program.load()
|
||||||
}
|
}
|
||||||
|
|
@ -755,6 +783,10 @@ fn with_style<P: Definition>(
|
||||||
(self.style)(state, theme)
|
(self.style)(state, theme)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn name() -> &'static str {
|
||||||
|
P::name()
|
||||||
|
}
|
||||||
|
|
||||||
fn load(&self) -> Command<Self::Message> {
|
fn load(&self) -> Command<Self::Message> {
|
||||||
self.program.load()
|
self.program.load()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ pub use settings::Settings;
|
||||||
pub use geometry::Geometry;
|
pub use geometry::Geometry;
|
||||||
|
|
||||||
use crate::core::{
|
use crate::core::{
|
||||||
Background, Color, Font, Pixels, Point, Rectangle, Size, Transformation,
|
Background, Color, Font, Pixels, Point, Rectangle, Transformation,
|
||||||
};
|
};
|
||||||
use crate::graphics::text::{Editor, Paragraph};
|
use crate::graphics::text::{Editor, Paragraph};
|
||||||
use crate::graphics::Viewport;
|
use crate::graphics::Viewport;
|
||||||
|
|
@ -477,7 +477,7 @@ impl core::text::Renderer for Renderer {
|
||||||
impl core::image::Renderer for Renderer {
|
impl core::image::Renderer for Renderer {
|
||||||
type Handle = core::image::Handle;
|
type Handle = core::image::Handle;
|
||||||
|
|
||||||
fn measure_image(&self, handle: &Self::Handle) -> Size<u32> {
|
fn measure_image(&self, handle: &Self::Handle) -> core::Size<u32> {
|
||||||
self.image_cache.borrow_mut().measure_image(handle)
|
self.image_cache.borrow_mut().measure_image(handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -503,7 +503,7 @@ impl core::image::Renderer for Renderer {
|
||||||
|
|
||||||
#[cfg(feature = "svg")]
|
#[cfg(feature = "svg")]
|
||||||
impl core::svg::Renderer for Renderer {
|
impl core::svg::Renderer for Renderer {
|
||||||
fn measure_svg(&self, handle: &core::svg::Handle) -> Size<u32> {
|
fn measure_svg(&self, handle: &core::svg::Handle) -> core::Size<u32> {
|
||||||
self.image_cache.borrow_mut().measure_svg(handle)
|
self.image_cache.borrow_mut().measure_svg(handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -539,7 +539,7 @@ impl graphics::geometry::Renderer for Renderer {
|
||||||
type Geometry = Geometry;
|
type Geometry = Geometry;
|
||||||
type Frame = geometry::Frame;
|
type Frame = geometry::Frame;
|
||||||
|
|
||||||
fn new_frame(&self, size: Size) -> Self::Frame {
|
fn new_frame(&self, size: core::Size) -> Self::Frame {
|
||||||
geometry::Frame::new(size)
|
geometry::Frame::new(size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,9 @@ where
|
||||||
/// The data needed to initialize your [`Application`].
|
/// The data needed to initialize your [`Application`].
|
||||||
type Flags;
|
type Flags;
|
||||||
|
|
||||||
|
/// Returns the unique name of the [`Application`].
|
||||||
|
fn name() -> &'static str;
|
||||||
|
|
||||||
/// Initializes the [`Application`] with the flags provided to
|
/// Initializes the [`Application`] with the flags provided to
|
||||||
/// [`run`] as part of the [`Settings`].
|
/// [`run`] as part of the [`Settings`].
|
||||||
///
|
///
|
||||||
|
|
@ -156,7 +159,8 @@ where
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
use winit::event_loop::EventLoop;
|
use winit::event_loop::EventLoop;
|
||||||
|
|
||||||
let boot_timer = debug::boot_time();
|
debug::init(A::name());
|
||||||
|
let boot_span = debug::boot();
|
||||||
|
|
||||||
let event_loop = EventLoop::with_user_event()
|
let event_loop = EventLoop::with_user_event()
|
||||||
.build()
|
.build()
|
||||||
|
|
@ -193,7 +197,7 @@ where
|
||||||
control_sender,
|
control_sender,
|
||||||
init_command,
|
init_command,
|
||||||
settings.fonts,
|
settings.fonts,
|
||||||
boot_timer,
|
boot_span,
|
||||||
));
|
));
|
||||||
|
|
||||||
let context = task::Context::from_waker(task::noop_waker_ref());
|
let context = task::Context::from_waker(task::noop_waker_ref());
|
||||||
|
|
@ -498,7 +502,7 @@ async fn run_instance<A, E, C>(
|
||||||
mut control_sender: mpsc::UnboundedSender<winit::event_loop::ControlFlow>,
|
mut control_sender: mpsc::UnboundedSender<winit::event_loop::ControlFlow>,
|
||||||
init_command: Command<A::Message>,
|
init_command: Command<A::Message>,
|
||||||
fonts: Vec<Cow<'static, [u8]>>,
|
fonts: Vec<Cow<'static, [u8]>>,
|
||||||
boot_timer: debug::Timer,
|
boot_span: debug::Span,
|
||||||
) where
|
) where
|
||||||
A: Application + 'static,
|
A: Application + 'static,
|
||||||
E: Executor + 'static,
|
E: Executor + 'static,
|
||||||
|
|
@ -554,7 +558,7 @@ async fn run_instance<A, E, C>(
|
||||||
&window,
|
&window,
|
||||||
);
|
);
|
||||||
runtime.track(application.subscription().into_recipes());
|
runtime.track(application.subscription().into_recipes());
|
||||||
boot_timer.finish();
|
boot_span.finish();
|
||||||
|
|
||||||
let mut user_interface = ManuallyDrop::new(build_user_interface(
|
let mut user_interface = ManuallyDrop::new(build_user_interface(
|
||||||
&application,
|
&application,
|
||||||
|
|
@ -608,12 +612,12 @@ 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(window::Id::MAIN);
|
let layout_span = debug::layout(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),
|
||||||
);
|
);
|
||||||
layout_timer.finish();
|
layout_span.finish();
|
||||||
|
|
||||||
compositor.configure_surface(
|
compositor.configure_surface(
|
||||||
&mut surface,
|
&mut surface,
|
||||||
|
|
@ -660,7 +664,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(window::Id::MAIN);
|
let draw_span = debug::draw(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(),
|
||||||
|
|
@ -670,7 +674,7 @@ async fn run_instance<A, E, C>(
|
||||||
state.cursor(),
|
state.cursor(),
|
||||||
);
|
);
|
||||||
redraw_pending = false;
|
redraw_pending = false;
|
||||||
draw_timer.finish();
|
draw_span.finish();
|
||||||
|
|
||||||
if new_mouse_interaction != mouse_interaction {
|
if new_mouse_interaction != mouse_interaction {
|
||||||
window.set_cursor(conversion::mouse_interaction(
|
window.set_cursor(conversion::mouse_interaction(
|
||||||
|
|
@ -680,7 +684,7 @@ async fn run_instance<A, E, C>(
|
||||||
mouse_interaction = new_mouse_interaction;
|
mouse_interaction = new_mouse_interaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
let render_timer = debug::render_time(window::Id::MAIN);
|
let present_span = debug::present(window::Id::MAIN);
|
||||||
match compositor.present(
|
match compositor.present(
|
||||||
&mut renderer,
|
&mut renderer,
|
||||||
&mut surface,
|
&mut surface,
|
||||||
|
|
@ -688,7 +692,7 @@ async fn run_instance<A, E, C>(
|
||||||
state.background_color(),
|
state.background_color(),
|
||||||
) {
|
) {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
render_timer.finish();
|
present_span.finish();
|
||||||
}
|
}
|
||||||
Err(error) => match error {
|
Err(error) => match error {
|
||||||
// This is an unrecoverable error.
|
// This is an unrecoverable error.
|
||||||
|
|
@ -733,7 +737,7 @@ async fn run_instance<A, E, C>(
|
||||||
redraw_request: None,
|
redraw_request: None,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let interact_timer = debug::interact_time(window::Id::MAIN);
|
let interact_span = debug::interact(window::Id::MAIN);
|
||||||
let (interface_state, statuses) = user_interface.update(
|
let (interface_state, statuses) = user_interface.update(
|
||||||
&events,
|
&events,
|
||||||
state.cursor(),
|
state.cursor(),
|
||||||
|
|
@ -747,7 +751,7 @@ async fn run_instance<A, E, C>(
|
||||||
{
|
{
|
||||||
runtime.broadcast(event, status);
|
runtime.broadcast(event, status);
|
||||||
}
|
}
|
||||||
interact_timer.finish();
|
interact_span.finish();
|
||||||
|
|
||||||
interface_state
|
interface_state
|
||||||
};
|
};
|
||||||
|
|
@ -842,13 +846,13 @@ pub fn build_user_interface<'a, A: Application>(
|
||||||
where
|
where
|
||||||
A::Theme: DefaultStyle,
|
A::Theme: DefaultStyle,
|
||||||
{
|
{
|
||||||
let view_timer = debug::view_time(window::Id::MAIN);
|
let view_span = debug::view(window::Id::MAIN);
|
||||||
let view = application.view();
|
let view = application.view();
|
||||||
view_timer.finish();
|
view_span.finish();
|
||||||
|
|
||||||
let layout_timer = debug::layout_time(window::Id::MAIN);
|
let layout_span = debug::layout(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_span.finish();
|
||||||
|
|
||||||
user_interface
|
user_interface
|
||||||
}
|
}
|
||||||
|
|
@ -875,9 +879,9 @@ pub fn update<A: Application, C, E: Executor>(
|
||||||
for message in messages.drain(..) {
|
for message in messages.drain(..) {
|
||||||
debug::log_message(&message);
|
debug::log_message(&message);
|
||||||
|
|
||||||
let update_timer = debug::update_time();
|
let update_span = debug::update();
|
||||||
let command = runtime.enter(|| application.update(message));
|
let command = runtime.enter(|| application.update(message));
|
||||||
update_timer.finish();
|
update_span.finish();
|
||||||
|
|
||||||
run_command(
|
run_command(
|
||||||
application,
|
application,
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,7 @@ where
|
||||||
let theme = application.theme();
|
let theme = application.theme();
|
||||||
let appearance = application.style(&theme);
|
let appearance = application.style(&theme);
|
||||||
|
|
||||||
let _ = application::DefaultStyle::palette(&theme)
|
debug::theme_changed(|| application::DefaultStyle::palette(&theme));
|
||||||
.map(debug::theme_changed);
|
|
||||||
|
|
||||||
let viewport = {
|
let viewport = {
|
||||||
let physical_size = window.inner_size();
|
let physical_size = window.inner_size();
|
||||||
|
|
@ -216,7 +215,8 @@ where
|
||||||
self.theme = application.theme();
|
self.theme = application.theme();
|
||||||
self.appearance = application.style(&self.theme);
|
self.appearance = application.style(&self.theme);
|
||||||
|
|
||||||
let _ = application::DefaultStyle::palette(&self.theme)
|
debug::theme_changed(|| {
|
||||||
.map(debug::theme_changed);
|
application::DefaultStyle::palette(&self.theme)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ where
|
||||||
{
|
{
|
||||||
use winit::event_loop::EventLoop;
|
use winit::event_loop::EventLoop;
|
||||||
|
|
||||||
let boot_timer = debug::boot_time();
|
let boot_span = debug::boot();
|
||||||
|
|
||||||
let event_loop = EventLoop::with_user_event()
|
let event_loop = EventLoop::with_user_event()
|
||||||
.build()
|
.build()
|
||||||
|
|
@ -153,7 +153,7 @@ where
|
||||||
event_receiver,
|
event_receiver,
|
||||||
control_sender,
|
control_sender,
|
||||||
init_command,
|
init_command,
|
||||||
boot_timer,
|
boot_span,
|
||||||
));
|
));
|
||||||
|
|
||||||
let context = task::Context::from_waker(task::noop_waker_ref());
|
let context = task::Context::from_waker(task::noop_waker_ref());
|
||||||
|
|
@ -452,7 +452,7 @@ async fn run_instance<A, E, C>(
|
||||||
mut event_receiver: mpsc::UnboundedReceiver<Event<A::Message>>,
|
mut event_receiver: mpsc::UnboundedReceiver<Event<A::Message>>,
|
||||||
mut control_sender: mpsc::UnboundedSender<Control>,
|
mut control_sender: mpsc::UnboundedSender<Control>,
|
||||||
init_command: Command<A::Message>,
|
init_command: Command<A::Message>,
|
||||||
boot_timer: debug::Timer,
|
boot_span: debug::Span,
|
||||||
) where
|
) where
|
||||||
A: Application + 'static,
|
A: Application + 'static,
|
||||||
E: Executor + 'static,
|
E: Executor + 'static,
|
||||||
|
|
@ -524,7 +524,7 @@ async fn run_instance<A, E, C>(
|
||||||
);
|
);
|
||||||
|
|
||||||
runtime.track(application.subscription().into_recipes());
|
runtime.track(application.subscription().into_recipes());
|
||||||
boot_timer.finish();
|
boot_span.finish();
|
||||||
|
|
||||||
let mut messages = Vec::new();
|
let mut messages = Vec::new();
|
||||||
let mut user_events = 0;
|
let mut user_events = 0;
|
||||||
|
|
@ -636,7 +636,7 @@ async fn run_instance<A, E, C>(
|
||||||
&mut messages,
|
&mut messages,
|
||||||
);
|
);
|
||||||
|
|
||||||
let draw_timer = debug::draw_time(id);
|
let draw_span = debug::draw(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(),
|
||||||
|
|
@ -645,7 +645,7 @@ async fn run_instance<A, E, C>(
|
||||||
},
|
},
|
||||||
cursor,
|
cursor,
|
||||||
);
|
);
|
||||||
draw_timer.finish();
|
draw_span.finish();
|
||||||
|
|
||||||
if new_mouse_interaction != window.mouse_interaction {
|
if new_mouse_interaction != window.mouse_interaction {
|
||||||
window.raw.set_cursor(
|
window.raw.set_cursor(
|
||||||
|
|
@ -692,7 +692,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(id);
|
let layout = debug::layout(id);
|
||||||
let ui = user_interfaces
|
let ui = user_interfaces
|
||||||
.remove(&id)
|
.remove(&id)
|
||||||
.expect("Remove user interface");
|
.expect("Remove user interface");
|
||||||
|
|
@ -701,9 +701,9 @@ async fn run_instance<A, E, C>(
|
||||||
id,
|
id,
|
||||||
ui.relayout(logical_size, &mut window.renderer),
|
ui.relayout(logical_size, &mut window.renderer),
|
||||||
);
|
);
|
||||||
layout_time.finish();
|
layout.finish();
|
||||||
|
|
||||||
let draw_time = debug::draw_time(id);
|
let draw = debug::draw(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")
|
||||||
|
|
@ -715,7 +715,7 @@ async fn run_instance<A, E, C>(
|
||||||
},
|
},
|
||||||
window.state.cursor(),
|
window.state.cursor(),
|
||||||
);
|
);
|
||||||
draw_time.finish();
|
draw.finish();
|
||||||
|
|
||||||
if new_mouse_interaction != window.mouse_interaction
|
if new_mouse_interaction != window.mouse_interaction
|
||||||
{
|
{
|
||||||
|
|
@ -739,7 +739,7 @@ async fn run_instance<A, E, C>(
|
||||||
window.state.viewport_version();
|
window.state.viewport_version();
|
||||||
}
|
}
|
||||||
|
|
||||||
let render_time = debug::render_time(id);
|
let present_span = debug::present(id);
|
||||||
match compositor.present(
|
match compositor.present(
|
||||||
&mut window.renderer,
|
&mut window.renderer,
|
||||||
&mut window.surface,
|
&mut window.surface,
|
||||||
|
|
@ -747,7 +747,7 @@ async fn run_instance<A, E, C>(
|
||||||
window.state.background_color(),
|
window.state.background_color(),
|
||||||
) {
|
) {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
render_time.finish();
|
present_span.finish();
|
||||||
|
|
||||||
// TODO: Handle animations!
|
// TODO: Handle animations!
|
||||||
// Maybe we can use `ControlFlow::WaitUntil` for this.
|
// Maybe we can use `ControlFlow::WaitUntil` for this.
|
||||||
|
|
@ -821,7 +821,7 @@ async fn run_instance<A, E, C>(
|
||||||
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 interact = debug::interact(id);
|
||||||
let mut window_events = vec![];
|
let mut window_events = vec![];
|
||||||
|
|
||||||
events.retain(|(window_id, event)| {
|
events.retain(|(window_id, event)| {
|
||||||
|
|
@ -864,7 +864,7 @@ async fn run_instance<A, E, C>(
|
||||||
{
|
{
|
||||||
runtime.broadcast(event, status);
|
runtime.broadcast(event, status);
|
||||||
}
|
}
|
||||||
interact_time.finish();
|
interact.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO mw application update returns which window IDs to update
|
// TODO mw application update returns which window IDs to update
|
||||||
|
|
@ -938,13 +938,13 @@ fn build_user_interface<'a, A: Application>(
|
||||||
where
|
where
|
||||||
A::Theme: DefaultStyle,
|
A::Theme: DefaultStyle,
|
||||||
{
|
{
|
||||||
let view_timer = debug::view_time(id);
|
let view_span = debug::view(id);
|
||||||
let view = application.view(id);
|
let view = application.view(id);
|
||||||
view_timer.finish();
|
view_span.finish();
|
||||||
|
|
||||||
let layout_timer = debug::layout_time(id);
|
let layout_span = debug::layout(id);
|
||||||
let user_interface = UserInterface::build(view, size, cache, renderer);
|
let user_interface = UserInterface::build(view, size, cache, renderer);
|
||||||
layout_timer.finish();
|
layout_span.finish();
|
||||||
|
|
||||||
user_interface
|
user_interface
|
||||||
}
|
}
|
||||||
|
|
@ -968,9 +968,9 @@ fn update<A: Application, C, E: Executor>(
|
||||||
for message in messages.drain(..) {
|
for message in messages.drain(..) {
|
||||||
debug::log_message(&message);
|
debug::log_message(&message);
|
||||||
|
|
||||||
let update_timer = debug::update_time();
|
let update_span = debug::update();
|
||||||
let command = runtime.enter(|| application.update(message));
|
let command = runtime.enter(|| application.update(message));
|
||||||
update_timer.finish();
|
update_span.finish();
|
||||||
|
|
||||||
run_command(
|
run_command(
|
||||||
application,
|
application,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue