diff options
Diffstat (limited to 'winit/src/application.rs')
-rw-r--r-- | winit/src/application.rs | 208 |
1 files changed, 127 insertions, 81 deletions
diff --git a/winit/src/application.rs b/winit/src/application.rs index fe97486f..ab7b2495 100644 --- a/winit/src/application.rs +++ b/winit/src/application.rs @@ -3,25 +3,25 @@ mod state; pub use state::State; -use crate::clipboard::{self, Clipboard}; use crate::conversion; -use crate::mouse; -use crate::renderer; -use crate::widget::operation; -use crate::{ - Command, Debug, Error, Event, Executor, Proxy, Runtime, Settings, Size, - Subscription, -}; - -use iced_futures::futures; -use iced_futures::futures::channel::mpsc; -use iced_graphics::compositor; -use iced_graphics::window; -use iced_native::program::Program; -use iced_native::time::Instant; -use iced_native::user_interface::{self, UserInterface}; - -pub use iced_native::application::{Appearance, StyleSheet}; +use crate::core; +use crate::core::mouse; +use crate::core::renderer; +use crate::core::time::Instant; +use crate::core::widget::operation; +use crate::core::window; +use crate::core::{Event, Size}; +use crate::futures::futures; +use crate::futures::{Executor, Runtime, Subscription}; +use crate::graphics::compositor::{self, Compositor}; +use crate::runtime::clipboard; +use crate::runtime::program::Program; +use crate::runtime::user_interface::{self, UserInterface}; +use crate::runtime::{Command, Debug}; +use crate::style::application::{Appearance, StyleSheet}; +use crate::{Clipboard, Error, Proxy, Settings}; + +use futures::channel::mpsc; use std::mem::ManuallyDrop; @@ -43,7 +43,7 @@ use tracing::{info_span, instrument::Instrument}; /// can be toggled by pressing `F12`. pub trait Application: Program where - <Self::Renderer as crate::Renderer>::Theme: StyleSheet, + <Self::Renderer as core::Renderer>::Theme: StyleSheet, { /// The data needed to initialize your [`Application`]. type Flags; @@ -65,12 +65,12 @@ where fn title(&self) -> String; /// Returns the current `Theme` of the [`Application`]. - fn theme(&self) -> <Self::Renderer as crate::Renderer>::Theme; + fn theme(&self) -> <Self::Renderer as core::Renderer>::Theme; /// Returns the `Style` variation of the `Theme`. fn style( &self, - ) -> <<Self::Renderer as crate::Renderer>::Theme as StyleSheet>::Style { + ) -> <<Self::Renderer as core::Renderer>::Theme as StyleSheet>::Style { Default::default() } @@ -110,8 +110,8 @@ pub fn run<A, E, C>( where A: Application + 'static, E: Executor + 'static, - C: window::Compositor<Renderer = A::Renderer> + 'static, - <A::Renderer as crate::Renderer>::Theme: StyleSheet, + C: Compositor<Renderer = A::Renderer> + 'static, + <A::Renderer as core::Renderer>::Theme: StyleSheet, { use futures::task; use futures::Future; @@ -177,13 +177,17 @@ where .unwrap_or(None) }); - let _ = match target { - Some(node) => node - .replace_child(&canvas, &node) - .expect(&format!("Could not replace #{}", node.id())), - None => body - .append_child(&canvas) - .expect("Append canvas to HTML body"), + match target { + Some(node) => { + let _ = node + .replace_with_with_node_1(&canvas) + .expect(&format!("Could not replace #{}", node.id())); + } + None => { + let _ = body + .append_child(&canvas) + .expect("Append canvas to HTML body"); + } }; } @@ -276,28 +280,25 @@ async fn run_instance<A, E, C>( ) where A: Application + 'static, E: Executor + 'static, - C: window::Compositor<Renderer = A::Renderer> + 'static, - <A::Renderer as crate::Renderer>::Theme: StyleSheet, + C: Compositor<Renderer = A::Renderer> + 'static, + <A::Renderer as core::Renderer>::Theme: StyleSheet, { - use iced_futures::futures::stream::StreamExt; + use futures::stream::StreamExt; use winit::event; use winit::event_loop::ControlFlow; - let mut clipboard = Clipboard::connect(&window); - let mut cache = user_interface::Cache::default(); - let mut surface = compositor.create_surface(&window); - let mut should_exit = false; - let mut state = State::new(&application, &window); let mut viewport_version = state.viewport_version(); - let physical_size = state.physical_size(); - compositor.configure_surface( - &mut surface, + let mut clipboard = Clipboard::connect(&window); + let mut cache = user_interface::Cache::default(); + let mut surface = compositor.create_surface( + &window, physical_size.width, physical_size.height, ); + let mut should_exit = false; if should_be_visible { window.set_visible(true); @@ -305,6 +306,8 @@ async fn run_instance<A, E, C>( run_command( &application, + &mut compositor, + &mut surface, &mut cache, &state, &mut renderer, @@ -315,9 +318,8 @@ async fn run_instance<A, E, C>( &mut proxy, &mut debug, &window, - || compositor.fetch_information(), ); - runtime.track(application.subscription()); + runtime.track(application.subscription().into_recipes()); let mut user_interface = ManuallyDrop::new(build_user_interface( &application, @@ -353,7 +355,7 @@ async fn run_instance<A, E, C>( let (interface_state, statuses) = user_interface.update( &events, - state.cursor_position(), + state.cursor(), &mut renderer, &mut clipboard, &mut messages, @@ -361,8 +363,10 @@ async fn run_instance<A, E, C>( debug.event_processing_finished(); - for event in events.drain(..).zip(statuses.into_iter()) { - runtime.broadcast(event); + for (event, status) in + events.drain(..).zip(statuses.into_iter()) + { + runtime.broadcast(event, status); } if !messages.is_empty() @@ -377,6 +381,8 @@ async fn run_instance<A, E, C>( // Update application update( &mut application, + &mut compositor, + &mut surface, &mut cache, &state, &mut renderer, @@ -387,7 +393,6 @@ async fn run_instance<A, E, C>( &mut debug, &mut messages, &window, - || compositor.fetch_information(), ); // Update window @@ -412,13 +417,13 @@ async fn run_instance<A, E, C>( // Then, we can use the `interface_state` here to decide if a redraw // is needed right away, or simply wait until a specific time. let redraw_event = Event::Window( - crate::window::Id::MAIN, - crate::window::Event::RedrawRequested(Instant::now()), + window::Id::MAIN, + window::Event::RedrawRequested(Instant::now()), ); let (interface_state, _) = user_interface.update( &[redraw_event.clone()], - state.cursor_position(), + state.cursor(), &mut renderer, &mut clipboard, &mut messages, @@ -431,7 +436,7 @@ async fn run_instance<A, E, C>( &renderer::Style { text_color: state.text_color(), }, - state.cursor_position(), + state.cursor(), ); debug.draw_finished(); @@ -444,17 +449,14 @@ async fn run_instance<A, E, C>( } window.request_redraw(); - runtime - .broadcast((redraw_event, crate::event::Status::Ignored)); + runtime.broadcast(redraw_event, core::event::Status::Ignored); let _ = control_sender.start_send(match interface_state { user_interface::State::Updated { redraw_request: Some(redraw_request), } => match redraw_request { - crate::window::RedrawRequest::NextFrame => { - ControlFlow::Poll - } - crate::window::RedrawRequest::At(at) => { + window::RedrawRequest::NextFrame => ControlFlow::Poll, + window::RedrawRequest::At(at) => { ControlFlow::WaitUntil(at) } }, @@ -466,9 +468,9 @@ async fn run_instance<A, E, C>( event::Event::PlatformSpecific(event::PlatformSpecific::MacOS( event::MacOS::ReceivedUrl(url), )) => { - use iced_native::event; + use crate::core::event; - events.push(iced_native::Event::PlatformSpecific( + events.push(Event::PlatformSpecific( event::PlatformSpecific::MacOS(event::MacOS::ReceivedUrl( url, )), @@ -507,7 +509,7 @@ async fn run_instance<A, E, C>( &renderer::Style { text_color: state.text_color(), }, - state.cursor_position(), + state.cursor(), ); if new_mouse_interaction != mouse_interaction { @@ -568,7 +570,7 @@ async fn run_instance<A, E, C>( state.update(&window, &window_event, &mut debug); if let Some(event) = conversion::window_event( - crate::window::Id::MAIN, + window::Id::MAIN, &window_event, state.scale_factor(), state.modifiers(), @@ -618,7 +620,7 @@ pub fn build_user_interface<'a, A: Application>( debug: &mut Debug, ) -> UserInterface<'a, A::Message, A::Renderer> where - <A::Renderer as crate::Renderer>::Theme: StyleSheet, + <A::Renderer as core::Renderer>::Theme: StyleSheet, { #[cfg(feature = "trace")] let view_span = info_span!("Application", "VIEW").entered(); @@ -645,8 +647,10 @@ where /// Updates an [`Application`] by feeding it the provided messages, spawning any /// resulting [`Command`], and tracking its [`Subscription`]. -pub fn update<A: Application, E: Executor>( +pub fn update<A: Application, C, E: Executor>( application: &mut A, + compositor: &mut C, + surface: &mut C::Surface, cache: &mut user_interface::Cache, state: &State<A>, renderer: &mut A::Renderer, @@ -657,9 +661,9 @@ pub fn update<A: Application, E: Executor>( debug: &mut Debug, messages: &mut Vec<A::Message>, window: &winit::window::Window, - graphics_info: impl FnOnce() -> compositor::Information + Copy, ) where - <A::Renderer as crate::Renderer>::Theme: StyleSheet, + C: Compositor<Renderer = A::Renderer> + 'static, + <A::Renderer as core::Renderer>::Theme: StyleSheet, { for message in messages.drain(..) { #[cfg(feature = "trace")] @@ -676,6 +680,8 @@ pub fn update<A: Application, E: Executor>( run_command( application, + compositor, + surface, cache, state, renderer, @@ -686,17 +692,18 @@ pub fn update<A: Application, E: Executor>( proxy, debug, window, - graphics_info, ); } let subscription = application.subscription(); - runtime.track(subscription); + runtime.track(subscription.into_recipes()); } /// Runs the actions of a [`Command`]. -pub fn run_command<A, E>( +pub fn run_command<A, C, E>( application: &A, + compositor: &mut C, + surface: &mut C::Surface, cache: &mut user_interface::Cache, state: &State<A>, renderer: &mut A::Renderer, @@ -707,15 +714,15 @@ pub fn run_command<A, E>( proxy: &mut winit::event_loop::EventLoopProxy<A::Message>, debug: &mut Debug, window: &winit::window::Window, - _graphics_info: impl FnOnce() -> compositor::Information + Copy, ) where A: Application, E: Executor, - <A::Renderer as crate::Renderer>::Theme: StyleSheet, + C: Compositor<Renderer = A::Renderer> + 'static, + <A::Renderer as core::Renderer>::Theme: StyleSheet, { - use iced_native::command; - use iced_native::system; - use iced_native::window; + use crate::runtime::command; + use crate::runtime::system; + use crate::runtime::window; for action in command.actions() { match action { @@ -746,12 +753,22 @@ pub fn run_command<A, E>( "Spawning a window is only available with `multi_window::Application`s." ) } - window::Action::Resize { width, height } => { + window::Action::Resize(size) => { window.set_inner_size(winit::dpi::LogicalSize { - width, - height, + width: size.width, + height: size.height, }); } + window::Action::FetchSize(callback) => { + let size = window.inner_size(); + + proxy + .send_event(callback(Size::new( + size.width, + size.height, + ))) + .expect("Send message to event loop") + } window::Action::Maximize(maximized) => { window.set_maximized(maximized); } @@ -771,11 +788,14 @@ pub fn run_command<A, E>( mode, )); } + window::Action::ChangeIcon(icon) => { + window.set_window_icon(conversion::icon(icon)) + } window::Action::FetchMode(tag) => { let mode = if window.is_visible().unwrap_or(true) { conversion::mode(window.fullscreen()) } else { - window::Mode::Hidden + core::window::Mode::Hidden }; proxy @@ -796,20 +816,36 @@ pub fn run_command<A, E>( window::Action::GainFocus => { window.focus_window(); } - window::Action::ChangeAlwaysOnTop(on_top) => { - window.set_always_on_top(on_top); + window::Action::ChangeLevel(level) => { + window.set_window_level(conversion::window_level(level)); } window::Action::FetchId(tag) => { proxy .send_event(tag(window.id().into())) .expect("Send message to event loop"); } + window::Action::Screenshot(tag) => { + let bytes = compositor.screenshot( + renderer, + surface, + state.viewport(), + state.background_color(), + &debug.overlay(), + ); + + proxy + .send_event(tag(window::Screenshot::new( + bytes, + state.physical_size(), + ))) + .expect("Send message to event loop.") + } }, command::Action::System(action) => match action { system::Action::QueryInformation(_tag) => { #[cfg(feature = "system")] { - let graphics_info = _graphics_info(); + let graphics_info = compositor.fetch_information(); let proxy = proxy.clone(); let _ = std::thread::spawn(move || { @@ -827,7 +863,7 @@ pub fn run_command<A, E>( }, command::Action::Widget(action) => { let mut current_cache = std::mem::take(cache); - let mut current_operation = Some(action.into_operation()); + let mut current_operation = Some(action); let mut user_interface = build_user_interface( application, @@ -856,6 +892,16 @@ pub fn run_command<A, E>( current_cache = user_interface.into_cache(); *cache = current_cache; } + command::Action::LoadFont { bytes, tagger } => { + use crate::core::text::Renderer; + + // TODO: Error handling (?) + renderer.load_font(bytes); + + proxy + .send_event(tagger(Ok(()))) + .expect("Send message to event loop"); + } } } } |