summaryrefslogtreecommitdiffstats
path: root/native
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2023-03-05 06:35:20 +0100
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2023-03-05 06:35:20 +0100
commit99e0a71504456976ba88040f5d1d3bbc347694ea (patch)
treea228c064fd3847831ff8072aa9375dc59db47f47 /native
parent8af69be47e88896b3c5f70174db609eee0c67971 (diff)
downloadiced-99e0a71504456976ba88040f5d1d3bbc347694ea.tar.gz
iced-99e0a71504456976ba88040f5d1d3bbc347694ea.tar.bz2
iced-99e0a71504456976ba88040f5d1d3bbc347694ea.zip
Rename `iced_native` to `iced_runtime`
Diffstat (limited to 'native')
-rw-r--r--native/Cargo.toml23
-rw-r--r--native/README.md37
-rw-r--r--native/src/clipboard.rs40
-rw-r--r--native/src/command.rs108
-rw-r--r--native/src/command/action.rs86
-rw-r--r--native/src/debug/basic.rs226
-rw-r--r--native/src/debug/null.rs47
-rw-r--r--native/src/font.rs19
-rw-r--r--native/src/keyboard.rs2
-rw-r--r--native/src/lib.rs71
-rw-r--r--native/src/program.rs33
-rw-r--r--native/src/program/state.rs194
-rw-r--r--native/src/system.rs6
-rw-r--r--native/src/system/action.rs39
-rw-r--r--native/src/system/information.rs29
-rw-r--r--native/src/user_interface.rs592
-rw-r--r--native/src/window.rs23
-rw-r--r--native/src/window/action.rs147
18 files changed, 0 insertions, 1722 deletions
diff --git a/native/Cargo.toml b/native/Cargo.toml
deleted file mode 100644
index bc4e7ca1..00000000
--- a/native/Cargo.toml
+++ /dev/null
@@ -1,23 +0,0 @@
-[package]
-name = "iced_native"
-version = "0.9.1"
-authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
-edition = "2021"
-description = "A renderer-agnostic library for native GUIs"
-license = "MIT"
-repository = "https://github.com/iced-rs/iced"
-
-[features]
-debug = []
-
-[dependencies]
-thiserror = "1"
-
-[dependencies.iced_core]
-version = "0.8"
-path = "../core"
-
-[dependencies.iced_futures]
-version = "0.6"
-path = "../futures"
-features = ["thread-pool"]
diff --git a/native/README.md b/native/README.md
deleted file mode 100644
index 996daa76..00000000
--- a/native/README.md
+++ /dev/null
@@ -1,37 +0,0 @@
-# `iced_native`
-[![Documentation](https://docs.rs/iced_native/badge.svg)][documentation]
-[![Crates.io](https://img.shields.io/crates/v/iced_native.svg)](https://crates.io/crates/iced_native)
-[![License](https://img.shields.io/crates/l/iced_native.svg)](https://github.com/iced-rs/iced/blob/master/LICENSE)
-[![Discord Server](https://img.shields.io/discord/628993209984614400?label=&labelColor=6A7EC2&logo=discord&logoColor=ffffff&color=7389D8)](https://discord.gg/3xZJ65GAhd)
-
-`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 bunch 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.
-- A `Windowed` trait, leveraging [`raw-window-handle`], which can be implemented by graphical renderers that target _windows_. Window-based shells (like [`iced_winit`]) can use this trait to stay renderer-agnostic.
-
-<p align="center">
- <img alt="The native target" src="../docs/graphs/native.png" width="80%">
-</p>
-
-[documentation]: https://docs.rs/iced_native
-[`iced_core`]: ../core
-[`iced_winit`]: ../winit
-[`druid`]: https://github.com/xi-editor/druid
-[`raw-window-handle`]: https://github.com/rust-windowing/raw-window-handle
-
-## Installation
-Add `iced_native` as a dependency in your `Cargo.toml`:
-
-```toml
-iced_native = "0.9"
-```
-
-__Iced moves fast and the `master` branch can contain breaking changes!__ If
-you want to learn about a specific release, check out [the release list].
-
-[the release list]: https://github.com/iced-rs/iced/releases
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.
-//!
-//! ![The native path of the Iced ecosystem](https://github.com/iced-rs/iced/raw/improvement/update-ecosystem-and-roadmap/docs/graphs/native.png)
-//!
-//! `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"),
- }
- }
-}