diff options
| author | 2023-03-05 06:35:20 +0100 | |
|---|---|---|
| committer | 2023-03-05 06:35:20 +0100 | |
| commit | 99e0a71504456976ba88040f5d1d3bbc347694ea (patch) | |
| tree | a228c064fd3847831ff8072aa9375dc59db47f47 /native/src | |
| parent | 8af69be47e88896b3c5f70174db609eee0c67971 (diff) | |
| download | iced-99e0a71504456976ba88040f5d1d3bbc347694ea.tar.gz iced-99e0a71504456976ba88040f5d1d3bbc347694ea.tar.bz2 iced-99e0a71504456976ba88040f5d1d3bbc347694ea.zip | |
Rename `iced_native` to `iced_runtime`
Diffstat (limited to 'native/src')
| -rw-r--r-- | native/src/clipboard.rs | 40 | ||||
| -rw-r--r-- | native/src/command.rs | 108 | ||||
| -rw-r--r-- | native/src/command/action.rs | 86 | ||||
| -rw-r--r-- | native/src/debug/basic.rs | 226 | ||||
| -rw-r--r-- | native/src/debug/null.rs | 47 | ||||
| -rw-r--r-- | native/src/font.rs | 19 | ||||
| -rw-r--r-- | native/src/keyboard.rs | 2 | ||||
| -rw-r--r-- | native/src/lib.rs | 71 | ||||
| -rw-r--r-- | native/src/program.rs | 33 | ||||
| -rw-r--r-- | native/src/program/state.rs | 194 | ||||
| -rw-r--r-- | native/src/system.rs | 6 | ||||
| -rw-r--r-- | native/src/system/action.rs | 39 | ||||
| -rw-r--r-- | native/src/system/information.rs | 29 | ||||
| -rw-r--r-- | native/src/user_interface.rs | 592 | ||||
| -rw-r--r-- | native/src/window.rs | 23 | ||||
| -rw-r--r-- | native/src/window/action.rs | 147 | 
16 files changed, 0 insertions, 1662 deletions
| diff --git a/native/src/clipboard.rs b/native/src/clipboard.rs deleted file mode 100644 index e727c4a7..00000000 --- a/native/src/clipboard.rs +++ /dev/null @@ -1,40 +0,0 @@ -//! Access the clipboard. -use iced_futures::MaybeSend; - -use std::fmt; - -/// A clipboard action to be performed by some [`Command`]. -/// -/// [`Command`]: crate::Command -pub enum Action<T> { -    /// Read the clipboard and produce `T` with the result. -    Read(Box<dyn Fn(Option<String>) -> T>), - -    /// Write the given contents to the clipboard. -    Write(String), -} - -impl<T> Action<T> { -    /// Maps the output of a clipboard [`Action`] using the provided closure. -    pub fn map<A>( -        self, -        f: impl Fn(T) -> A + 'static + MaybeSend + Sync, -    ) -> Action<A> -    where -        T: 'static, -    { -        match self { -            Self::Read(o) => Action::Read(Box::new(move |s| f(o(s)))), -            Self::Write(content) => Action::Write(content), -        } -    } -} - -impl<T> fmt::Debug for Action<T> { -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -        match self { -            Self::Read(_) => write!(f, "Action::Read"), -            Self::Write(_) => write!(f, "Action::Write"), -        } -    } -} diff --git a/native/src/command.rs b/native/src/command.rs deleted file mode 100644 index cd4c51ff..00000000 --- a/native/src/command.rs +++ /dev/null @@ -1,108 +0,0 @@ -//! Run asynchronous actions. -mod action; - -pub use action::Action; - -use crate::core::widget; -use crate::futures::MaybeSend; - -use std::fmt; -use std::future::Future; - -/// A set of asynchronous actions to be performed by some runtime. -#[must_use = "`Command` must be returned to runtime to take effect"] -pub struct Command<T>(Internal<Action<T>>); - -#[derive(Debug)] -enum Internal<T> { -    None, -    Single(T), -    Batch(Vec<T>), -} - -impl<T> Command<T> { -    /// Creates an empty [`Command`]. -    /// -    /// In other words, a [`Command`] that does nothing. -    pub const fn none() -> Self { -        Self(Internal::None) -    } - -    /// Creates a [`Command`] that performs a single [`Action`]. -    pub const fn single(action: Action<T>) -> Self { -        Self(Internal::Single(action)) -    } - -    /// Creates a [`Command`] that performs a [`widget::Operation`]. -    pub fn widget(operation: impl widget::Operation<T> + 'static) -> Self { -        Self::single(Action::Widget(Box::new(operation))) -    } - -    /// Creates a [`Command`] that performs the action of the given future. -    pub fn perform<A>( -        future: impl Future<Output = T> + 'static + MaybeSend, -        f: impl FnOnce(T) -> A + 'static + MaybeSend, -    ) -> Command<A> { -        use iced_futures::futures::FutureExt; - -        Command::single(Action::Future(Box::pin(future.map(f)))) -    } - -    /// Creates a [`Command`] that performs the actions of all the given -    /// commands. -    /// -    /// Once this command is run, all the commands will be executed at once. -    pub fn batch(commands: impl IntoIterator<Item = Command<T>>) -> Self { -        let mut batch = Vec::new(); - -        for Command(command) in commands { -            match command { -                Internal::None => {} -                Internal::Single(command) => batch.push(command), -                Internal::Batch(commands) => batch.extend(commands), -            } -        } - -        Self(Internal::Batch(batch)) -    } - -    /// Applies a transformation to the result of a [`Command`]. -    pub fn map<A>( -        self, -        f: impl Fn(T) -> A + 'static + MaybeSend + Sync + Clone, -    ) -> Command<A> -    where -        T: 'static, -        A: 'static, -    { -        match self.0 { -            Internal::None => Command::none(), -            Internal::Single(action) => Command::single(action.map(f)), -            Internal::Batch(batch) => Command(Internal::Batch( -                batch -                    .into_iter() -                    .map(|action| action.map(f.clone())) -                    .collect(), -            )), -        } -    } - -    /// Returns all of the actions of the [`Command`]. -    pub fn actions(self) -> Vec<Action<T>> { -        let Command(command) = self; - -        match command { -            Internal::None => Vec::new(), -            Internal::Single(action) => vec![action], -            Internal::Batch(batch) => batch, -        } -    } -} - -impl<T> fmt::Debug for Command<T> { -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -        let Command(command) = self; - -        command.fmt(f) -    } -} diff --git a/native/src/command/action.rs b/native/src/command/action.rs deleted file mode 100644 index 6c74f0ef..00000000 --- a/native/src/command/action.rs +++ /dev/null @@ -1,86 +0,0 @@ -use crate::clipboard; -use crate::core::widget; -use crate::font; -use crate::system; -use crate::window; - -use iced_futures::MaybeSend; - -use std::borrow::Cow; -use std::fmt; - -/// An action that a [`Command`] can perform. -/// -/// [`Command`]: crate::Command -pub enum Action<T> { -    /// Run a [`Future`] to completion. -    /// -    /// [`Future`]: iced_futures::BoxFuture -    Future(iced_futures::BoxFuture<T>), - -    /// Run a clipboard action. -    Clipboard(clipboard::Action<T>), - -    /// Run a window action. -    Window(window::Action<T>), - -    /// Run a system action. -    System(system::Action<T>), - -    /// Run a widget action. -    Widget(Box<dyn widget::Operation<T>>), - -    /// Load a font from its bytes. -    LoadFont { -        /// The bytes of the font to load. -        bytes: Cow<'static, [u8]>, - -        /// The message to produce when the font has been loaded. -        tagger: Box<dyn Fn(Result<(), font::Error>) -> T>, -    }, -} - -impl<T> Action<T> { -    /// Applies a transformation to the result of a [`Command`]. -    /// -    /// [`Command`]: crate::Command -    pub fn map<A>( -        self, -        f: impl Fn(T) -> A + 'static + MaybeSend + Sync, -    ) -> Action<A> -    where -        A: 'static, -        T: 'static, -    { -        use iced_futures::futures::FutureExt; - -        match self { -            Self::Future(future) => Action::Future(Box::pin(future.map(f))), -            Self::Clipboard(action) => Action::Clipboard(action.map(f)), -            Self::Window(window) => Action::Window(window.map(f)), -            Self::System(system) => Action::System(system.map(f)), -            Self::Widget(operation) => { -                Action::Widget(Box::new(widget::operation::map(operation, f))) -            } -            Self::LoadFont { bytes, tagger } => Action::LoadFont { -                bytes, -                tagger: Box::new(move |result| f(tagger(result))), -            }, -        } -    } -} - -impl<T> fmt::Debug for Action<T> { -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -        match self { -            Self::Future(_) => write!(f, "Action::Future"), -            Self::Clipboard(action) => { -                write!(f, "Action::Clipboard({action:?})") -            } -            Self::Window(action) => write!(f, "Action::Window({action:?})"), -            Self::System(action) => write!(f, "Action::System({action:?})"), -            Self::Widget(_action) => write!(f, "Action::Widget"), -            Self::LoadFont { .. } => write!(f, "Action::LoadFont"), -        } -    } -} diff --git a/native/src/debug/basic.rs b/native/src/debug/basic.rs deleted file mode 100644 index 32f725a1..00000000 --- a/native/src/debug/basic.rs +++ /dev/null @@ -1,226 +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 = time::Instant::now() - self.startup_start; -    } - -    pub fn update_started(&mut self) { -        self.update_start = time::Instant::now(); -    } - -    pub fn update_finished(&mut self) { -        self.update_durations -            .push(time::Instant::now() - self.update_start); -    } - -    pub fn view_started(&mut self) { -        self.view_start = time::Instant::now(); -    } - -    pub fn view_finished(&mut self) { -        self.view_durations -            .push(time::Instant::now() - self.view_start); -    } - -    pub fn layout_started(&mut self) { -        self.layout_start = time::Instant::now(); -    } - -    pub fn layout_finished(&mut self) { -        self.layout_durations -            .push(time::Instant::now() - self.layout_start); -    } - -    pub fn event_processing_started(&mut self) { -        self.event_start = time::Instant::now(); -    } - -    pub fn event_processing_finished(&mut self) { -        self.event_durations -            .push(time::Instant::now() - self.event_start); -    } - -    pub fn draw_started(&mut self) { -        self.draw_start = time::Instant::now(); -    } - -    pub fn draw_finished(&mut self) { -        self.draw_durations -            .push(time::Instant::now() - self.draw_start); -    } - -    pub fn render_started(&mut self) { -        self.render_start = time::Instant::now(); -    } - -    pub fn render_finished(&mut self) { -        self.render_durations -            .push(time::Instant::now() - self.render_start); -    } - -    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 -    } -} diff --git a/native/src/debug/null.rs b/native/src/debug/null.rs deleted file mode 100644 index 2db0eebb..00000000 --- a/native/src/debug/null.rs +++ /dev/null @@ -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() -    } -} diff --git a/native/src/font.rs b/native/src/font.rs deleted file mode 100644 index 15359694..00000000 --- a/native/src/font.rs +++ /dev/null @@ -1,19 +0,0 @@ -//! Load and use fonts. -pub use iced_core::font::*; - -use crate::command::{self, Command}; -use std::borrow::Cow; - -/// An error while loading a font. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum Error {} - -/// Load a font from its bytes. -pub fn load( -    bytes: impl Into<Cow<'static, [u8]>>, -) -> Command<Result<(), Error>> { -    Command::single(command::Action::LoadFont { -        bytes: bytes.into(), -        tagger: Box::new(std::convert::identity), -    }) -} diff --git a/native/src/keyboard.rs b/native/src/keyboard.rs deleted file mode 100644 index 012538e3..00000000 --- a/native/src/keyboard.rs +++ /dev/null @@ -1,2 +0,0 @@ -//! Track keyboard events. -pub use iced_core::keyboard::*; diff --git a/native/src/lib.rs b/native/src/lib.rs deleted file mode 100644 index aa45e57a..00000000 --- a/native/src/lib.rs +++ /dev/null @@ -1,71 +0,0 @@ -//! A renderer-agnostic native GUI runtime. -//! -//!  -//! -//! `iced_native` takes [`iced_core`] and builds a native runtime on top of it, -//! featuring: -//! -//! - A custom layout engine, greatly inspired by [`druid`] -//! - Event handling for all the built-in widgets -//! - A renderer-agnostic API -//! -//! To achieve this, it introduces a couple of reusable interfaces: -//! -//! - A [`Widget`] trait, which is used to implement new widgets: from layout -//!   requirements to event and drawing logic. -//! - A bunch of `Renderer` traits, meant to keep the crate renderer-agnostic. -//! -//! # Usage -//! The strategy to use this crate depends on your particular use case. If you -//! want to: -//! - Implement a custom shell or integrate it in your own system, check out the -//! [`UserInterface`] type. -//! - Build a new renderer, see the [renderer] module. -//! - Build a custom widget, start at the [`Widget`] trait. -//! -//! [`iced_core`]: https://github.com/iced-rs/iced/tree/0.8/core -//! [`iced_winit`]: https://github.com/iced-rs/iced/tree/0.8/winit -//! [`druid`]: https://github.com/xi-editor/druid -//! [`raw-window-handle`]: https://github.com/rust-windowing/raw-window-handle -//! [renderer]: crate::renderer -#![doc( -    html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg" -)] -#![deny( -    missing_debug_implementations, -    //missing_docs, -    unused_results, -    clippy::extra_unused_lifetimes, -    clippy::from_over_into, -    clippy::needless_borrow, -    clippy::new_without_default, -    clippy::useless_conversion -)] -#![forbid(unsafe_code, rust_2018_idioms)] -#![cfg_attr(docsrs, feature(doc_cfg))] -pub mod clipboard; -pub mod command; -pub mod font; -pub mod keyboard; -pub mod program; -pub mod system; -pub mod user_interface; -pub mod 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_futures as futures; - -pub use command::Command; -pub use debug::Debug; -pub use font::Font; -pub use program::Program; -pub use user_interface::UserInterface; diff --git a/native/src/program.rs b/native/src/program.rs deleted file mode 100644 index 44585cc5..00000000 --- a/native/src/program.rs +++ /dev/null @@ -1,33 +0,0 @@ -//! Build interactive programs using The Elm Architecture. -use crate::Command; - -use iced_core::text; -use iced_core::{Element, Renderer}; - -mod state; - -pub use state::State; - -/// The core of a user interface application following The Elm Architecture. -pub trait Program: Sized { -    /// The graphics backend to use to draw the [`Program`]. -    type Renderer: Renderer + text::Renderer; - -    /// The type of __messages__ your [`Program`] will produce. -    type Message: std::fmt::Debug + Send; - -    /// Handles a __message__ and updates the state of the [`Program`]. -    /// -    /// This is where you define your __update logic__. All the __messages__, -    /// produced by either user interactions or commands, will be handled by -    /// this method. -    /// -    /// Any [`Command`] returned will be executed immediately in the -    /// background by shells. -    fn update(&mut self, message: Self::Message) -> Command<Self::Message>; - -    /// Returns the widgets to display in the [`Program`]. -    /// -    /// These widgets can produce __messages__ based on user interaction. -    fn view(&self) -> Element<'_, Self::Message, Self::Renderer>; -} diff --git a/native/src/program/state.rs b/native/src/program/state.rs deleted file mode 100644 index 2fa9934d..00000000 --- a/native/src/program/state.rs +++ /dev/null @@ -1,194 +0,0 @@ -use crate::core::event::{self, Event}; -use crate::core::mouse; -use crate::core::renderer; -use crate::core::{Clipboard, Point, Size}; -use crate::user_interface::{self, UserInterface}; -use crate::{Command, Debug, Program}; - -/// The execution state of a [`Program`]. It leverages caching, event -/// processing, and rendering primitive storage. -#[allow(missing_debug_implementations)] -pub struct State<P> -where -    P: Program + 'static, -{ -    program: P, -    cache: Option<user_interface::Cache>, -    queued_events: Vec<Event>, -    queued_messages: Vec<P::Message>, -    mouse_interaction: mouse::Interaction, -} - -impl<P> State<P> -where -    P: Program + 'static, -{ -    /// Creates a new [`State`] with the provided [`Program`], initializing its -    /// primitive with the given logical bounds and renderer. -    pub fn new( -        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()); - -        State { -            program, -            cache, -            queued_events: Vec::new(), -            queued_messages: Vec::new(), -            mouse_interaction: mouse::Interaction::Idle, -        } -    } - -    /// Returns a reference to the [`Program`] of the [`State`]. -    pub fn program(&self) -> &P { -        &self.program -    } - -    /// Queues an event in the [`State`] for processing during an [`update`]. -    /// -    /// [`update`]: Self::update -    pub fn queue_event(&mut self, event: Event) { -        self.queued_events.push(event); -    } - -    /// Queues a message in the [`State`] for processing during an [`update`]. -    /// -    /// [`update`]: Self::update -    pub fn queue_message(&mut self, message: P::Message) { -        self.queued_messages.push(message); -    } - -    /// Returns whether the event queue of the [`State`] is empty or not. -    pub fn is_queue_empty(&self) -> bool { -        self.queued_events.is_empty() && self.queued_messages.is_empty() -    } - -    /// Returns the current [`mouse::Interaction`] of the [`State`]. -    pub fn mouse_interaction(&self) -> mouse::Interaction { -        self.mouse_interaction -    } - -    /// Processes all the queued events and messages, rebuilding and redrawing -    /// the widgets of the linked [`Program`] if necessary. -    /// -    /// Returns a list containing the instances of [`Event`] that were not -    /// captured by any widget, and the [`Command`] obtained from [`Program`] -    /// after updating it, only if an update was necessary. -    pub fn update( -        &mut self, -        bounds: Size, -        cursor_position: Point, -        renderer: &mut P::Renderer, -        theme: &<P::Renderer as iced_core::Renderer>::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 mut messages = Vec::new(); - -        let (_, event_statuses) = user_interface.update( -            &self.queued_events, -            cursor_position, -            renderer, -            clipboard, -            &mut messages, -        ); - -        let uncaptured_events = self -            .queued_events -            .iter() -            .zip(event_statuses) -            .filter_map(|(event, status)| { -                matches!(status, event::Status::Ignored).then_some(event) -            }) -            .cloned() -            .collect(); - -        self.queued_events.clear(); -        messages.append(&mut self.queued_messages); -        debug.event_processing_finished(); - -        let command = if messages.is_empty() { -            debug.draw_started(); -            self.mouse_interaction = -                user_interface.draw(renderer, theme, style, cursor_position); -            debug.draw_finished(); - -            self.cache = Some(user_interface.into_cache()); - -            None -        } else { -            // When there are messages, we are forced to rebuild twice -            // for now :^) -            let temp_cache = user_interface.into_cache(); - -            let commands = -                Command::batch(messages.into_iter().map(|message| { -                    debug.log_message(&message); - -                    debug.update_started(); -                    let command = self.program.update(message); -                    debug.update_finished(); - -                    command -                })); - -            let mut user_interface = build_user_interface( -                &mut self.program, -                temp_cache, -                renderer, -                bounds, -                debug, -            ); - -            debug.draw_started(); -            self.mouse_interaction = -                user_interface.draw(renderer, theme, style, cursor_position); -            debug.draw_finished(); - -            self.cache = Some(user_interface.into_cache()); - -            Some(commands) -        }; - -        (uncaptured_events, command) -    } -} - -fn build_user_interface<'a, P: Program>( -    program: &'a mut P, -    cache: user_interface::Cache, -    renderer: &mut P::Renderer, -    size: Size, -    debug: &mut Debug, -) -> UserInterface<'a, P::Message, P::Renderer> { -    debug.view_started(); -    let view = program.view(); -    debug.view_finished(); - -    debug.layout_started(); -    let user_interface = UserInterface::build(view, size, cache, renderer); -    debug.layout_finished(); - -    user_interface -} diff --git a/native/src/system.rs b/native/src/system.rs deleted file mode 100644 index 61c8ff29..00000000 --- a/native/src/system.rs +++ /dev/null @@ -1,6 +0,0 @@ -//! Access the native system. -mod action; -mod information; - -pub use action::Action; -pub use information::Information; diff --git a/native/src/system/action.rs b/native/src/system/action.rs deleted file mode 100644 index dea9536f..00000000 --- a/native/src/system/action.rs +++ /dev/null @@ -1,39 +0,0 @@ -use crate::system; - -use iced_futures::MaybeSend; -use std::fmt; - -/// An operation to be performed on the system. -pub enum Action<T> { -    /// Query system information and produce `T` with the result. -    QueryInformation(Box<dyn Closure<T>>), -} - -pub trait Closure<T>: Fn(system::Information) -> T + MaybeSend {} - -impl<T, O> Closure<O> for T where T: Fn(system::Information) -> O + MaybeSend {} - -impl<T> Action<T> { -    /// Maps the output of a system [`Action`] using the provided closure. -    pub fn map<A>( -        self, -        f: impl Fn(T) -> A + 'static + MaybeSend + Sync, -    ) -> Action<A> -    where -        T: 'static, -    { -        match self { -            Self::QueryInformation(o) => { -                Action::QueryInformation(Box::new(move |s| f(o(s)))) -            } -        } -    } -} - -impl<T> fmt::Debug for Action<T> { -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -        match self { -            Self::QueryInformation(_) => write!(f, "Action::QueryInformation"), -        } -    } -} diff --git a/native/src/system/information.rs b/native/src/system/information.rs deleted file mode 100644 index 93e7a5a4..00000000 --- a/native/src/system/information.rs +++ /dev/null @@ -1,29 +0,0 @@ -/// Contains informations about the system (e.g. system name, processor, memory, graphics adapter). -#[derive(Clone, Debug)] -pub struct Information { -    /// The operating system name -    pub system_name: Option<String>, -    /// Operating system kernel version -    pub system_kernel: Option<String>, -    /// Long operating system version -    /// -    /// Examples: -    /// - MacOS 10.15 Catalina -    /// - Windows 10 Pro -    /// - Ubuntu 20.04 LTS (Focal Fossa) -    pub system_version: Option<String>, -    /// Short operating system version number -    pub system_short_version: Option<String>, -    /// Detailed processor model information -    pub cpu_brand: String, -    /// The number of physical cores on the processor -    pub cpu_cores: Option<usize>, -    /// Total RAM size, KB -    pub memory_total: u64, -    /// Memory used by this process, KB -    pub memory_used: Option<u64>, -    /// Underlying graphics backend for rendering -    pub graphics_backend: String, -    /// Model information for the active graphics adapter -    pub graphics_adapter: String, -} diff --git a/native/src/user_interface.rs b/native/src/user_interface.rs deleted file mode 100644 index 315027fa..00000000 --- a/native/src/user_interface.rs +++ /dev/null @@ -1,592 +0,0 @@ -//! Implement your own event loop to drive a user interface. -use crate::core::event::{self, Event}; -use crate::core::layout; -use crate::core::mouse; -use crate::core::renderer; -use crate::core::widget; -use crate::core::window; -use crate::core::{Clipboard, Point, Rectangle, Size, Vector}; -use crate::core::{Element, Layout, Shell}; - -/// A set of interactive graphical elements with a specific [`Layout`]. -/// -/// It can be updated and drawn. -/// -/// Iced tries to avoid dictating how to write your event loop. You are in -/// charge of using this type in your system in any way you want. -/// -/// # Example -/// The [`integration_opengl`] & [`integration_wgpu`] examples use a -/// [`UserInterface`] to integrate Iced in an existing graphical application. -/// -/// [`integration_opengl`]: https://github.com/iced-rs/iced/tree/0.8/examples/integration_opengl -/// [`integration_wgpu`]: https://github.com/iced-rs/iced/tree/0.8/examples/integration_wgpu -#[allow(missing_debug_implementations)] -pub struct UserInterface<'a, Message, Renderer> { -    root: Element<'a, Message, Renderer>, -    base: layout::Node, -    state: widget::Tree, -    overlay: Option<layout::Node>, -    bounds: Size, -} - -impl<'a, Message, Renderer> UserInterface<'a, Message, Renderer> -where -    Renderer: iced_core::Renderer, -{ -    /// Builds a user interface for an [`Element`]. -    /// -    /// It is able to avoid expensive computations when using a [`Cache`] -    /// obtained from a previous instance of a [`UserInterface`]. -    /// -    /// # Example -    /// Imagine we want to build a [`UserInterface`] for -    /// [the counter example that we previously wrote](index.html#usage). Here -    /// is naive way to set up our application loop: -    /// -    /// ```no_run -    /// # mod iced_wgpu { -    /// #     pub use iced_native::core::renderer::Null as Renderer; -    /// # } -    /// # -    /// # pub struct Counter; -    /// # -    /// # impl Counter { -    /// #     pub fn new() -> Self { Counter } -    /// #     pub fn view(&self) -> iced_core::Element<(), Renderer> { unimplemented!() } -    /// #     pub fn update(&mut self, _: ()) {} -    /// # } -    /// use iced_native::core::Size; -    /// use iced_native::user_interface::{self, UserInterface}; -    /// use iced_wgpu::Renderer; -    /// -    /// // Initialization -    /// let mut counter = Counter::new(); -    /// let mut cache = user_interface::Cache::new(); -    /// let mut renderer = Renderer::new(); -    /// let mut window_size = Size::new(1024.0, 768.0); -    /// -    /// // Application loop -    /// loop { -    ///     // Process system events here... -    /// -    ///     // Build the user interface -    ///     let user_interface = UserInterface::build( -    ///         counter.view(), -    ///         window_size, -    ///         cache, -    ///         &mut renderer, -    ///     ); -    /// -    ///     // Update and draw the user interface here... -    ///     // ... -    /// -    ///     // Obtain the cache for the next iteration -    ///     cache = user_interface.into_cache(); -    /// } -    /// ``` -    pub fn build<E: Into<Element<'a, Message, Renderer>>>( -        root: E, -        bounds: Size, -        cache: Cache, -        renderer: &mut Renderer, -    ) -> Self { -        let root = root.into(); - -        let Cache { mut state } = cache; -        state.diff(root.as_widget()); - -        let base = -            renderer.layout(&root, &layout::Limits::new(Size::ZERO, bounds)); - -        UserInterface { -            root, -            base, -            state, -            overlay: None, -            bounds, -        } -    } - -    /// Updates the [`UserInterface`] by processing each provided [`Event`]. -    /// -    /// It returns __messages__ that may have been produced as a result of user -    /// interactions. You should feed these to your __update logic__. -    /// -    /// # Example -    /// Let's allow our [counter](index.html#usage) to change state by -    /// completing [the previous example](#example): -    /// -    /// ```no_run -    /// # mod iced_wgpu { -    /// #     pub use iced_native::core::renderer::Null as Renderer; -    /// # } -    /// # -    /// # pub struct Counter; -    /// # -    /// # impl Counter { -    /// #     pub fn new() -> Self { Counter } -    /// #     pub fn view(&self) -> iced_core::Element<(), Renderer> { unimplemented!() } -    /// #     pub fn update(&mut self, _: ()) {} -    /// # } -    /// use iced_native::core::{clipboard, Size, Point}; -    /// use iced_native::user_interface::{self, UserInterface}; -    /// use iced_wgpu::Renderer; -    /// -    /// let mut counter = Counter::new(); -    /// let mut cache = user_interface::Cache::new(); -    /// let mut renderer = Renderer::new(); -    /// let mut window_size = Size::new(1024.0, 768.0); -    /// let mut cursor_position = Point::default(); -    /// let mut clipboard = clipboard::Null; -    /// -    /// // Initialize our event storage -    /// let mut events = Vec::new(); -    /// let mut messages = Vec::new(); -    /// -    /// loop { -    ///     // Obtain system events... -    /// -    ///     let mut user_interface = UserInterface::build( -    ///         counter.view(), -    ///         window_size, -    ///         cache, -    ///         &mut renderer, -    ///     ); -    /// -    ///     // Update the user interface -    ///     let (state, event_statuses) = user_interface.update( -    ///         &events, -    ///         cursor_position, -    ///         &mut renderer, -    ///         &mut clipboard, -    ///         &mut messages -    ///     ); -    /// -    ///     cache = user_interface.into_cache(); -    /// -    ///     // Process the produced messages -    ///     for message in messages.drain(..) { -    ///         counter.update(message); -    ///     } -    /// } -    /// ``` -    pub fn update( -        &mut self, -        events: &[Event], -        cursor_position: Point, -        renderer: &mut Renderer, -        clipboard: &mut dyn Clipboard, -        messages: &mut Vec<Message>, -    ) -> (State, Vec<event::Status>) { -        use std::mem::ManuallyDrop; - -        let mut outdated = false; -        let mut redraw_request = None; - -        let mut manual_overlay = -            ManuallyDrop::new(self.root.as_widget_mut().overlay( -                &mut self.state, -                Layout::new(&self.base), -                renderer, -            )); - -        let (base_cursor, overlay_statuses) = if manual_overlay.is_some() { -            let bounds = self.bounds; - -            let mut overlay = manual_overlay.as_mut().unwrap(); -            let mut layout = overlay.layout(renderer, bounds, Vector::ZERO); -            let mut event_statuses = Vec::new(); - -            for event in events.iter().cloned() { -                let mut shell = Shell::new(messages); - -                let event_status = overlay.on_event( -                    event, -                    Layout::new(&layout), -                    cursor_position, -                    renderer, -                    clipboard, -                    &mut shell, -                ); - -                event_statuses.push(event_status); - -                match (redraw_request, shell.redraw_request()) { -                    (None, Some(at)) => { -                        redraw_request = Some(at); -                    } -                    (Some(current), Some(new)) if new < current => { -                        redraw_request = Some(new); -                    } -                    _ => {} -                } - -                if shell.is_layout_invalid() { -                    let _ = ManuallyDrop::into_inner(manual_overlay); - -                    self.base = renderer.layout( -                        &self.root, -                        &layout::Limits::new(Size::ZERO, self.bounds), -                    ); - -                    manual_overlay = -                        ManuallyDrop::new(self.root.as_widget_mut().overlay( -                            &mut self.state, -                            Layout::new(&self.base), -                            renderer, -                        )); - -                    if manual_overlay.is_none() { -                        break; -                    } - -                    overlay = manual_overlay.as_mut().unwrap(); - -                    shell.revalidate_layout(|| { -                        layout = overlay.layout(renderer, bounds, Vector::ZERO); -                    }); -                } - -                if shell.are_widgets_invalid() { -                    outdated = true; -                } -            } - -            let base_cursor = manual_overlay -                .as_ref() -                .filter(|overlay| { -                    overlay.is_over(Layout::new(&layout), cursor_position) -                }) -                .map(|_| { -                    // TODO: Type-safe cursor availability -                    Point::new(-1.0, -1.0) -                }) -                .unwrap_or(cursor_position); - -            self.overlay = Some(layout); - -            (base_cursor, event_statuses) -        } else { -            (cursor_position, vec![event::Status::Ignored; events.len()]) -        }; - -        let _ = ManuallyDrop::into_inner(manual_overlay); - -        let event_statuses = events -            .iter() -            .cloned() -            .zip(overlay_statuses.into_iter()) -            .map(|(event, overlay_status)| { -                if matches!(overlay_status, event::Status::Captured) { -                    return overlay_status; -                } - -                let mut shell = Shell::new(messages); - -                let event_status = self.root.as_widget_mut().on_event( -                    &mut self.state, -                    event, -                    Layout::new(&self.base), -                    base_cursor, -                    renderer, -                    clipboard, -                    &mut shell, -                ); - -                if matches!(event_status, event::Status::Captured) { -                    self.overlay = None; -                } - -                match (redraw_request, shell.redraw_request()) { -                    (None, Some(at)) => { -                        redraw_request = Some(at); -                    } -                    (Some(current), Some(new)) if new < current => { -                        redraw_request = Some(new); -                    } -                    _ => {} -                } - -                shell.revalidate_layout(|| { -                    self.base = renderer.layout( -                        &self.root, -                        &layout::Limits::new(Size::ZERO, self.bounds), -                    ); - -                    self.overlay = None; -                }); - -                if shell.are_widgets_invalid() { -                    outdated = true; -                } - -                event_status.merge(overlay_status) -            }) -            .collect(); - -        ( -            if outdated { -                State::Outdated -            } else { -                State::Updated { redraw_request } -            }, -            event_statuses, -        ) -    } - -    /// Draws the [`UserInterface`] with the provided [`Renderer`]. -    /// -    /// It returns the current [`mouse::Interaction`]. You should update the -    /// icon of the mouse cursor accordingly in your system. -    /// -    /// [`Renderer`]: crate::Renderer -    /// -    /// # Example -    /// We can finally draw our [counter](index.html#usage) by -    /// [completing the last example](#example-1): -    /// -    /// ```no_run -    /// # mod iced_wgpu { -    /// #     pub use iced_native::core::renderer::Null as Renderer; -    /// #     pub type Theme = (); -    /// # } -    /// # -    /// # pub struct Counter; -    /// # -    /// # impl Counter { -    /// #     pub fn new() -> Self { Counter } -    /// #     pub fn view(&self) -> Element<(), Renderer> { unimplemented!() } -    /// #     pub fn update(&mut self, _: ()) {} -    /// # } -    /// use iced_native::core::clipboard; -    /// use iced_native::core::renderer; -    /// use iced_native::core::{Element, Size, Point}; -    /// use iced_native::user_interface::{self, UserInterface}; -    /// use iced_wgpu::{Renderer, Theme}; -    /// -    /// let mut counter = Counter::new(); -    /// let mut cache = user_interface::Cache::new(); -    /// let mut renderer = Renderer::new(); -    /// let mut window_size = Size::new(1024.0, 768.0); -    /// let mut cursor_position = Point::default(); -    /// let mut clipboard = clipboard::Null; -    /// let mut events = Vec::new(); -    /// let mut messages = Vec::new(); -    /// let mut theme = Theme::default(); -    /// -    /// loop { -    ///     // Obtain system events... -    /// -    ///     let mut user_interface = UserInterface::build( -    ///         counter.view(), -    ///         window_size, -    ///         cache, -    ///         &mut renderer, -    ///     ); -    /// -    ///     // Update the user interface -    ///     let event_statuses = user_interface.update( -    ///         &events, -    ///         cursor_position, -    ///         &mut renderer, -    ///         &mut clipboard, -    ///         &mut messages -    ///     ); -    /// -    ///     // Draw the user interface -    ///     let mouse_cursor = user_interface.draw(&mut renderer, &theme, &renderer::Style::default(), cursor_position); -    /// -    ///     cache = user_interface.into_cache(); -    /// -    ///     for message in messages.drain(..) { -    ///         counter.update(message); -    ///     } -    /// -    ///     // Update mouse cursor icon... -    ///     // Flush rendering operations... -    /// } -    /// ``` -    pub fn draw( -        &mut self, -        renderer: &mut Renderer, -        theme: &Renderer::Theme, -        style: &renderer::Style, -        cursor_position: Point, -    ) -> mouse::Interaction { -        // TODO: Move to shell level (?) -        renderer.clear(); - -        let viewport = Rectangle::with_size(self.bounds); - -        let base_cursor = if let Some(overlay) = self -            .root -            .as_widget_mut() -            .overlay(&mut self.state, Layout::new(&self.base), renderer) -        { -            let overlay_layout = self.overlay.take().unwrap_or_else(|| { -                overlay.layout(renderer, self.bounds, Vector::ZERO) -            }); - -            let new_cursor_position = if overlay -                .is_over(Layout::new(&overlay_layout), cursor_position) -            { -                Point::new(-1.0, -1.0) -            } else { -                cursor_position -            }; - -            self.overlay = Some(overlay_layout); - -            new_cursor_position -        } else { -            cursor_position -        }; - -        self.root.as_widget().draw( -            &self.state, -            renderer, -            theme, -            style, -            Layout::new(&self.base), -            base_cursor, -            &viewport, -        ); - -        let base_interaction = self.root.as_widget().mouse_interaction( -            &self.state, -            Layout::new(&self.base), -            cursor_position, -            &viewport, -            renderer, -        ); - -        let Self { -            overlay, -            root, -            base, -            .. -        } = self; - -        // TODO: Currently, we need to call Widget::overlay twice to -        // implement the painter's algorithm properly. -        // -        // Once we have a proper persistent widget tree, we should be able to -        // avoid this additional call. -        overlay -            .as_ref() -            .and_then(|layout| { -                root.as_widget_mut() -                    .overlay(&mut self.state, Layout::new(base), renderer) -                    .map(|overlay| { -                        let overlay_interaction = overlay.mouse_interaction( -                            Layout::new(layout), -                            cursor_position, -                            &viewport, -                            renderer, -                        ); - -                        let overlay_bounds = layout.bounds(); - -                        renderer.with_layer(overlay_bounds, |renderer| { -                            overlay.draw( -                                renderer, -                                theme, -                                style, -                                Layout::new(layout), -                                cursor_position, -                            ); -                        }); - -                        if overlay.is_over(Layout::new(layout), cursor_position) -                        { -                            overlay_interaction -                        } else { -                            base_interaction -                        } -                    }) -            }) -            .unwrap_or(base_interaction) -    } - -    /// Applies a [`widget::Operation`] to the [`UserInterface`]. -    pub fn operate( -        &mut self, -        renderer: &Renderer, -        operation: &mut dyn widget::Operation<Message>, -    ) { -        self.root.as_widget().operate( -            &mut self.state, -            Layout::new(&self.base), -            renderer, -            operation, -        ); - -        if let Some(mut overlay) = self.root.as_widget_mut().overlay( -            &mut self.state, -            Layout::new(&self.base), -            renderer, -        ) { -            if self.overlay.is_none() { -                self.overlay = -                    Some(overlay.layout(renderer, self.bounds, Vector::ZERO)); -            } - -            overlay.operate( -                Layout::new(self.overlay.as_ref().unwrap()), -                renderer, -                operation, -            ); -        } -    } - -    /// Relayouts and returns a new  [`UserInterface`] using the provided -    /// bounds. -    pub fn relayout(self, bounds: Size, renderer: &mut Renderer) -> Self { -        Self::build(self.root, bounds, Cache { state: self.state }, renderer) -    } - -    /// Extract the [`Cache`] of the [`UserInterface`], consuming it in the -    /// process. -    pub fn into_cache(self) -> Cache { -        Cache { state: self.state } -    } -} - -/// Reusable data of a specific [`UserInterface`]. -#[derive(Debug)] -pub struct Cache { -    state: widget::Tree, -} - -impl Cache { -    /// Creates an empty [`Cache`]. -    /// -    /// You should use this to initialize a [`Cache`] before building your first -    /// [`UserInterface`]. -    pub fn new() -> Cache { -        Cache { -            state: widget::Tree::empty(), -        } -    } -} - -impl Default for Cache { -    fn default() -> Cache { -        Cache::new() -    } -} - -/// The resulting state after updating a [`UserInterface`]. -#[derive(Debug, Clone, Copy)] -pub enum State { -    /// The [`UserInterface`] is outdated and needs to be rebuilt. -    Outdated, - -    /// The [`UserInterface`] is up-to-date and can be reused without -    /// rebuilding. -    Updated { -        /// The [`Instant`] when a redraw should be performed. -        redraw_request: Option<window::RedrawRequest>, -    }, -} diff --git a/native/src/window.rs b/native/src/window.rs deleted file mode 100644 index aa3f35c7..00000000 --- a/native/src/window.rs +++ /dev/null @@ -1,23 +0,0 @@ -//! Build window-based GUI applications. -mod action; - -pub use action::Action; - -use crate::core::time::Instant; -use crate::core::window::Event; -use crate::futures::subscription::{self, Subscription}; - -/// Subscribes to the frames of the window of the running application. -/// -/// The resulting [`Subscription`] will produce items at a rate equal to the -/// refresh rate of the window. Note that this rate may be variable, as it is -/// normally managed by the graphics driver and/or the OS. -/// -/// In any case, this [`Subscription`] is useful to smoothly draw application-driven -/// animations without missing any frames. -pub fn frames() -> Subscription<Instant> { -    subscription::raw_events(|event, _status| match event { -        iced_core::Event::Window(Event::RedrawRequested(at)) => Some(at), -        _ => None, -    }) -} diff --git a/native/src/window/action.rs b/native/src/window/action.rs deleted file mode 100644 index c1dbd84f..00000000 --- a/native/src/window/action.rs +++ /dev/null @@ -1,147 +0,0 @@ -use crate::core::window::{Mode, UserAttention}; -use crate::futures::MaybeSend; - -use std::fmt; - -/// An operation to be performed on some window. -pub enum Action<T> { -    /// Closes the current window and exits the application. -    Close, -    /// Moves the window with the left mouse button until the button is -    /// released. -    /// -    /// There’s no guarantee that this will work unless the left mouse -    /// button was pressed immediately before this function is called. -    Drag, -    /// Resize the window. -    Resize { -        /// The new logical width of the window -        width: u32, -        /// The new logical height of the window -        height: u32, -    }, -    /// Sets the window to maximized or back -    Maximize(bool), -    /// Set the window to minimized or back -    Minimize(bool), -    /// Move the window. -    /// -    /// Unsupported on Wayland. -    Move { -        /// The new logical x location of the window -        x: i32, -        /// The new logical y location of the window -        y: i32, -    }, -    /// Change the [`Mode`] of the window. -    ChangeMode(Mode), -    /// Fetch the current [`Mode`] of the window. -    FetchMode(Box<dyn FnOnce(Mode) -> T + 'static>), -    /// Toggle the window to maximized or back -    ToggleMaximize, -    /// Toggle whether window has decorations. -    /// -    /// ## Platform-specific -    /// - **X11:** Not implemented. -    /// - **Web:** Unsupported. -    ToggleDecorations, -    /// Request user attention to the window, this has no effect if the application -    /// is already focused. How requesting for user attention manifests is platform dependent, -    /// see [`UserAttention`] for details. -    /// -    /// Providing `None` will unset the request for user attention. Unsetting the request for -    /// user attention might not be done automatically by the WM when the window receives input. -    /// -    /// ## Platform-specific -    /// -    /// - **iOS / Android / Web:** Unsupported. -    /// - **macOS:** `None` has no effect. -    /// - **X11:** Requests for user attention must be manually cleared. -    /// - **Wayland:** Requires `xdg_activation_v1` protocol, `None` has no effect. -    RequestUserAttention(Option<UserAttention>), -    /// Bring the window to the front and sets input focus. Has no effect if the window is -    /// already in focus, minimized, or not visible. -    /// -    /// This method steals input focus from other applications. Do not use this method unless -    /// you are certain that's what the user wants. Focus stealing can cause an extremely disruptive -    /// user experience. -    /// -    /// ## Platform-specific -    /// -    /// - **Web / Wayland:** Unsupported. -    GainFocus, -    /// Change whether or not the window will always be on top of other windows. -    /// -    /// ## Platform-specific -    /// -    /// - **Web / Wayland:** Unsupported. -    ChangeAlwaysOnTop(bool), -    /// Fetch an identifier unique to the window. -    FetchId(Box<dyn FnOnce(u64) -> T + 'static>), -} - -impl<T> Action<T> { -    /// Maps the output of a window [`Action`] using the provided closure. -    pub fn map<A>( -        self, -        f: impl Fn(T) -> A + 'static + MaybeSend + Sync, -    ) -> Action<A> -    where -        T: 'static, -    { -        match self { -            Self::Close => Action::Close, -            Self::Drag => Action::Drag, -            Self::Resize { width, height } => Action::Resize { width, height }, -            Self::Maximize(maximized) => Action::Maximize(maximized), -            Self::Minimize(minimized) => Action::Minimize(minimized), -            Self::Move { x, y } => Action::Move { x, y }, -            Self::ChangeMode(mode) => Action::ChangeMode(mode), -            Self::FetchMode(o) => Action::FetchMode(Box::new(move |s| f(o(s)))), -            Self::ToggleMaximize => Action::ToggleMaximize, -            Self::ToggleDecorations => Action::ToggleDecorations, -            Self::RequestUserAttention(attention_type) => { -                Action::RequestUserAttention(attention_type) -            } -            Self::GainFocus => Action::GainFocus, -            Self::ChangeAlwaysOnTop(on_top) => { -                Action::ChangeAlwaysOnTop(on_top) -            } -            Self::FetchId(o) => Action::FetchId(Box::new(move |s| f(o(s)))), -        } -    } -} - -impl<T> fmt::Debug for Action<T> { -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -        match self { -            Self::Close => write!(f, "Action::Close"), -            Self::Drag => write!(f, "Action::Drag"), -            Self::Resize { width, height } => write!( -                f, -                "Action::Resize {{ widget: {width}, height: {height} }}" -            ), -            Self::Maximize(maximized) => { -                write!(f, "Action::Maximize({maximized})") -            } -            Self::Minimize(minimized) => { -                write!(f, "Action::Minimize({minimized}") -            } -            Self::Move { x, y } => { -                write!(f, "Action::Move {{ x: {x}, y: {y} }}") -            } -            Self::ChangeMode(mode) => write!(f, "Action::SetMode({mode:?})"), -            Self::FetchMode(_) => write!(f, "Action::FetchMode"), -            Self::ToggleMaximize => write!(f, "Action::ToggleMaximize"), -            Self::ToggleDecorations => write!(f, "Action::ToggleDecorations"), -            Self::RequestUserAttention(_) => { -                write!(f, "Action::RequestUserAttention") -            } -            Self::GainFocus => write!(f, "Action::GainFocus"), -            Self::ChangeAlwaysOnTop(on_top) => { -                write!(f, "Action::AlwaysOnTop({on_top})") -            } -            Self::FetchId(_) => write!(f, "Action::FetchId"), -        } -    } -} | 
