//! A windowing shell for Iced, on top of [`winit`].
//!
//! 
//!
//! `iced_winit` offers some convenient abstractions on top of [`iced_runtime`]
//! to quickstart development when using [`winit`].
//!
//! It exposes a renderer-agnostic [`Program`] trait that can be implemented
//! and then run with a simple call. The use of this trait is optional.
//!
//! Additionally, a [`conversion`] module is available for users that decide to
//! implement a custom event loop.
//!
//! [`iced_runtime`]: https://github.com/iced-rs/iced/tree/0.13/runtime
//! [`winit`]: https://github.com/rust-windowing/winit
//! [`conversion`]: crate::conversion
#![doc(
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
pub use iced_program as program;
pub use program::core;
pub use program::graphics;
pub use program::runtime;
pub use runtime::debug;
pub use runtime::futures;
pub use winit;
pub mod clipboard;
pub mod conversion;
#[cfg(feature = "system")]
pub mod system;
mod error;
mod proxy;
mod window;
pub use clipboard::Clipboard;
pub use error::Error;
pub use proxy::Proxy;
use crate::core::mouse;
use crate::core::renderer;
use crate::core::theme;
use crate::core::time::Instant;
use crate::core::widget::operation;
use crate::core::{Point, Settings, Size};
use crate::futures::futures::channel::mpsc;
use crate::futures::futures::channel::oneshot;
use crate::futures::futures::task;
use crate::futures::futures::{Future, StreamExt};
use crate::futures::subscription;
use crate::futures::{Executor, Runtime};
use crate::graphics::{Compositor, compositor};
use crate::runtime::user_interface::{self, UserInterface};
use crate::runtime::{Action, Task};
use program::Program;
use window::WindowManager;
use rustc_hash::FxHashMap;
use std::borrow::Cow;
use std::mem::ManuallyDrop;
use std::sync::Arc;
/// Runs a [`Program`] with the provided settings.
pub fn run
(
program: P,
settings: Settings,
window_settings: Option,
) -> Result<(), Error>
where
P: Program + 'static,
P::Theme: theme::Base,
{
use winit::event_loop::EventLoop;
debug::init(P::name());
let boot_span = debug::boot();
let graphics_settings = settings.clone().into();
let event_loop = EventLoop::with_user_event()
.build()
.expect("Create event loop");
let (proxy, worker) = Proxy::new(event_loop.create_proxy());
let mut runtime = {
let executor =
P::Executor::new().map_err(Error::ExecutorCreationFailed)?;
executor.spawn(worker);
Runtime::new(executor, proxy.clone())
};
let (program, task) = runtime.enter(|| program::Instance::new(program));
let is_daemon = window_settings.is_none();
let task = if let Some(window_settings) = window_settings {
let mut task = Some(task);
let (_id, open) = runtime::window::open(window_settings);
open.then(move |_| task.take().unwrap_or(Task::none()))
} else {
task
};
if let Some(stream) = runtime::task::into_stream(task) {
runtime.run(stream);
}
runtime.track(subscription::into_recipes(
runtime.enter(|| program.subscription().map(Action::Output)),
));
let (event_sender, event_receiver) = mpsc::unbounded();
let (control_sender, control_receiver) = mpsc::unbounded();
let instance = Box::pin(run_instance::(
program,
runtime,
proxy.clone(),
event_receiver,
control_sender,
is_daemon,
graphics_settings,
settings.fonts,
));
let context = task::Context::from_waker(task::noop_waker_ref());
struct Runner {
instance: std::pin::Pin>,
context: task::Context<'static>,
id: Option,
sender: mpsc::UnboundedSender>>,
receiver: mpsc::UnboundedReceiver,
error: Option,
#[cfg(target_arch = "wasm32")]
canvas: Option,
}
let runner = Runner {
instance,
context,
id: settings.id,
sender: event_sender,
receiver: control_receiver,
error: None,
#[cfg(target_arch = "wasm32")]
canvas: None,
};
boot_span.finish();
impl winit::application::ApplicationHandler>
for Runner
where
Message: std::fmt::Debug,
F: Future