Introduce subscription::Event

... and remove `PlatformSpecific` from `Event`
This commit is contained in:
Héctor Ramón Jiménez 2024-06-11 19:41:05 +02:00
parent 83296a73eb
commit 5d7dcf417c
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
13 changed files with 156 additions and 129 deletions

View file

@ -32,11 +32,17 @@ where
#[derive(Hash)]
struct EventsWith;
subscription::filter_map((EventsWith, f), move |event, status, window| {
match event {
Event::Window(window::Event::RedrawRequested(_)) => None,
_ => f(event, status, window),
subscription::filter_map((EventsWith, f), move |event| match event {
subscription::Event::Interaction {
event: Event::Window(window::Event::RedrawRequested(_)),
..
}
| subscription::Event::PlatformSpecific(_) => None,
subscription::Event::Interaction {
window,
event,
status,
} => f(event, status, window),
})
}
@ -54,5 +60,32 @@ where
#[derive(Hash)]
struct RawEvents;
subscription::filter_map((RawEvents, f), f)
subscription::filter_map((RawEvents, f), move |event| match event {
subscription::Event::Interaction {
window,
event,
status,
} => f(event, status, window),
subscription::Event::PlatformSpecific(_) => None,
})
}
/// Creates a [`Subscription`] that notifies of custom application URL
/// received from the system.
///
/// _**Note:** Currently, it only triggers on macOS and the executable needs to be properly [bundled]!_
///
/// [bundled]: https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html#//apple_ref/doc/uid/10000123i-CH101-SW19
pub fn listen_url() -> Subscription<String> {
#[derive(Hash)]
struct ListenUrl;
subscription::filter_map(ListenUrl, move |event| match event {
subscription::Event::PlatformSpecific(
subscription::PlatformSpecific::MacOS(
subscription::MacOS::ReceivedUrl(url),
),
) => Some(url),
_ => None,
})
}

View file

@ -1,5 +1,6 @@
//! Listen to keyboard events.
use crate::core;
use crate::core::event;
use crate::core::keyboard::{Event, Key, Modifiers};
use crate::subscription::{self, Subscription};
use crate::MaybeSend;
@ -18,16 +19,14 @@ where
#[derive(Hash)]
struct OnKeyPress;
subscription::filter_map((OnKeyPress, f), move |event, status, _window| {
match (event, status) {
(
core::Event::Keyboard(Event::KeyPressed {
key, modifiers, ..
}),
core::event::Status::Ignored,
) => f(key, modifiers),
_ => None,
}
subscription::filter_map((OnKeyPress, f), move |event| match event {
subscription::Event::Interaction {
event:
core::Event::Keyboard(Event::KeyPressed { key, modifiers, .. }),
status: event::Status::Ignored,
..
} => f(key, modifiers),
_ => None,
})
}
@ -45,18 +44,13 @@ where
#[derive(Hash)]
struct OnKeyRelease;
subscription::filter_map(
(OnKeyRelease, f),
move |event, status, _window| match (event, status) {
(
core::Event::Keyboard(Event::KeyReleased {
key,
modifiers,
..
}),
core::event::Status::Ignored,
) => f(key, modifiers),
_ => None,
},
)
subscription::filter_map((OnKeyRelease, f), move |event| match event {
subscription::Event::Interaction {
event:
core::Event::Keyboard(Event::KeyReleased { key, modifiers, .. }),
status: event::Status::Ignored,
..
} => f(key, modifiers),
_ => None,
})
}

View file

@ -1,6 +1,4 @@
//! Run commands and keep track of subscriptions.
use crate::core::event::{self, Event};
use crate::core::window;
use crate::subscription;
use crate::{BoxFuture, BoxStream, Executor, MaybeSend};
@ -128,12 +126,7 @@ where
/// See [`Tracker::broadcast`] to learn more.
///
/// [`Tracker::broadcast`]: subscription::Tracker::broadcast
pub fn broadcast(
&mut self,
event: Event,
status: event::Status,
window: window::Id,
) {
self.subscriptions.broadcast(event, status, window);
pub fn broadcast(&mut self, event: subscription::Event) {
self.subscriptions.broadcast(event);
}
}

View file

@ -3,7 +3,7 @@ mod tracker;
pub use tracker::Tracker;
use crate::core::event::{self, Event};
use crate::core::event;
use crate::core::window;
use crate::futures::{Future, Stream};
use crate::{BoxStream, MaybeSend};
@ -13,10 +13,48 @@ use futures::never::Never;
use std::any::TypeId;
use std::hash::Hash;
/// A subscription event.
#[derive(Debug, Clone, PartialEq)]
pub enum Event {
/// A user interacted with a user interface in a window.
Interaction {
/// The window holding the interface of the interaction.
window: window::Id,
/// The [`Event`] describing the interaction.
///
/// [`Event`]: event::Event
event: event::Event,
/// The [`event::Status`] of the interaction.
status: event::Status,
},
/// A platform specific event.
PlatformSpecific(PlatformSpecific),
}
/// A platform specific event
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PlatformSpecific {
/// A MacOS specific event
MacOS(MacOS),
}
/// Describes an event specific to MacOS
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum MacOS {
/// Triggered when the app receives an URL from the system
///
/// _**Note:** For this event to be triggered, the executable needs to be properly [bundled]!_
///
/// [bundled]: https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html#//apple_ref/doc/uid/10000123i-CH101-SW19
ReceivedUrl(String),
}
/// A stream of runtime events.
///
/// It is the input of a [`Subscription`].
pub type EventStream = BoxStream<(Event, event::Status, window::Id)>;
pub type EventStream = BoxStream<Event>;
/// The hasher used for identifying subscriptions.
pub type Hasher = rustc_hash::FxHasher;
@ -290,9 +328,7 @@ where
pub(crate) fn filter_map<I, F, Message>(id: I, f: F) -> Subscription<Message>
where
I: Hash + 'static,
F: Fn(Event, event::Status, window::Id) -> Option<Message>
+ MaybeSend
+ 'static,
F: Fn(Event) -> Option<Message> + MaybeSend + 'static,
Message: 'static + MaybeSend,
{
Subscription::from_recipe(Runner {
@ -301,9 +337,7 @@ where
use futures::future;
use futures::stream::StreamExt;
events.filter_map(move |(event, status, window)| {
future::ready(f(event, status, window))
})
events.filter_map(move |event| future::ready(f(event)))
},
})
}

View file

@ -1,6 +1,4 @@
use crate::core::event::{self, Event};
use crate::core::window;
use crate::subscription::{Hasher, Recipe};
use crate::subscription::{Event, Hasher, Recipe};
use crate::{BoxFuture, MaybeSend};
use futures::channel::mpsc;
@ -24,9 +22,7 @@ pub struct Tracker {
#[derive(Debug)]
pub struct Execution {
_cancel: futures::channel::oneshot::Sender<()>,
listener: Option<
futures::channel::mpsc::Sender<(Event, event::Status, window::Id)>,
>,
listener: Option<futures::channel::mpsc::Sender<Event>>,
}
impl Tracker {
@ -142,19 +138,12 @@ impl Tracker {
/// currently open.
///
/// [`Recipe::stream`]: crate::subscription::Recipe::stream
pub fn broadcast(
&mut self,
event: Event,
status: event::Status,
window: window::Id,
) {
pub fn broadcast(&mut self, event: Event) {
self.subscriptions
.values_mut()
.filter_map(|connection| connection.listener.as_mut())
.for_each(|listener| {
if let Err(error) =
listener.try_send((event.clone(), status, window))
{
if let Err(error) = listener.try_send(event.clone()) {
log::warn!(
"Error sending event to subscription: {error:?}"
);