diff options
author | 2019-12-05 06:10:13 +0100 | |
---|---|---|
committer | 2019-12-05 06:10:13 +0100 | |
commit | d575f4541126e2ab25908fe55c6805f16716b2a5 (patch) | |
tree | 9d5221fe201b64e2ec649228ebae26be819dbf58 /winit/src/application.rs | |
parent | e92ea48e8814b42fc566017db085ca9bdaf3c272 (diff) | |
download | iced-d575f4541126e2ab25908fe55c6805f16716b2a5.tar.gz iced-d575f4541126e2ab25908fe55c6805f16716b2a5.tar.bz2 iced-d575f4541126e2ab25908fe55c6805f16716b2a5.zip |
Draft first version of event subscriptions :tada:
Diffstat (limited to 'winit/src/application.rs')
-rw-r--r-- | winit/src/application.rs | 79 |
1 files changed, 77 insertions, 2 deletions
diff --git a/winit/src/application.rs b/winit/src/application.rs index 3772a667..959e142d 100644 --- a/winit/src/application.rs +++ b/winit/src/application.rs @@ -2,9 +2,10 @@ use crate::{ conversion, input::{keyboard, mouse}, renderer::{Target, Windowed}, - Cache, Command, Container, Debug, Element, Event, Length, MouseCursor, - Settings, UserInterface, + subscription, Cache, Command, Container, Debug, Element, Event, Length, + MouseCursor, Settings, Subscription, UserInterface, }; +use std::collections::HashMap; /// An interactive, native cross-platform application. /// @@ -57,6 +58,9 @@ pub trait Application: Sized { /// [`Command`]: struct.Command.html fn update(&mut self, message: Self::Message) -> Command<Self::Message>; + /// TODO + fn subscriptions(&self) -> Subscription<Self::Message>; + /// Returns the widgets to display in the [`Application`]. /// /// These widgets can produce __messages__ based on user interaction. @@ -89,11 +93,15 @@ pub trait Application: Sized { let proxy = event_loop.create_proxy(); let mut thread_pool = futures::executor::ThreadPool::new().expect("Create thread pool"); + let mut alive_subscriptions = Subscriptions::new(); let mut external_messages = Vec::new(); let (mut application, init_command) = Self::new(); spawn(init_command, &mut thread_pool, &proxy); + let subscriptions = application.subscriptions(); + alive_subscriptions.update(subscriptions, &mut thread_pool, &proxy); + let mut title = application.title(); let window = { @@ -204,6 +212,13 @@ pub trait Application: Sized { debug.update_finished(); } + let subscriptions = application.subscriptions(); + alive_subscriptions.update( + subscriptions, + &mut thread_pool, + &proxy, + ); + // Update window title let new_title = application.title(); @@ -404,6 +419,66 @@ fn spawn<Message: Send>( } } +pub struct Subscriptions { + alive: HashMap<u64, Box<dyn subscription::Handle>>, +} + +impl Subscriptions { + fn new() -> Self { + Self { + alive: HashMap::new(), + } + } + + fn update<Message: Send>( + &mut self, + subscriptions: Subscription<Message>, + thread_pool: &mut futures::executor::ThreadPool, + proxy: &winit::event_loop::EventLoopProxy<Message>, + ) { + use futures::stream::StreamExt; + + let definitions = subscriptions.definitions(); + let mut alive = std::collections::HashSet::new(); + + for definition in definitions { + let id = definition.id(); + let _ = alive.insert(id); + + if !self.alive.contains_key(&id) { + let (stream, handle) = definition.stream(); + + let proxy = + std::sync::Arc::new(std::sync::Mutex::new(proxy.clone())); + + let future = stream.for_each(move |message| { + proxy + .lock() + .expect("Acquire event loop proxy lock") + .send_event(message) + .expect("Send subscription result to event loop"); + + futures::future::ready(()) + }); + + thread_pool.spawn_ok(future); + + let _ = self.alive.insert(id, handle); + } + } + + self.alive.retain(|id, handle| { + let is_still_alive = alive.contains(&id); + + if !is_still_alive { + handle.cancel(); + } + + is_still_alive + }); + } +} + // As defined in: http://www.unicode.org/faq/private_use.html // TODO: Remove once https://github.com/rust-windowing/winit/pull/1254 lands fn is_private_use_character(c: char) -> bool { |