event loop: Decouple state type from event handler

This commit is contained in:
Dorota Czaplejewicz
2022-11-28 14:39:21 +00:00
parent 23d6beee8e
commit e0b37d60c4
3 changed files with 28 additions and 12 deletions

View File

@ -75,8 +75,8 @@ impl Threaded {
self.thread.send(event) self.thread.send(event)
} }
fn handle_loop_event(loop_sender: &Sender, state: event_loop::State, event: Event, ui: &UISender) fn handle_loop_event(loop_sender: &Sender, state: event_loop::State<Application>, event: Event, ui: &UISender)
-> event_loop::State -> event_loop::State<Application>
{ {
let now = Instant::now(); let now = Instant::now();

View File

@ -49,20 +49,27 @@ use std::time::{ Duration, Instant };
pub trait Event: Clone { pub trait Event: Clone {
/// Returns the value of the reached timeout, if this event carries the timeout.
fn get_timeout_reached(&self) -> Option<Instant>; fn get_timeout_reached(&self) -> Option<Instant>;
} }
pub trait ActorState: Clone {
type Event: Event;
fn apply_event(self, e: Self::Event, time: Instant) -> Self;
fn get_outcome(&self, time: Instant) -> state::Outcome;
fn get_next_wake(&self, now: Instant) -> Option<Instant>;
}
/// This keeps the state of the tracker loop between iterations /// This keeps the state of the tracker loop between iterations
#[derive(Clone)] #[derive(Clone)]
struct State { struct State<S> {
state: state::Application, state: S,
scheduled_wakeup: Option<Instant>, scheduled_wakeup: Option<Instant>,
last_update: Instant, last_update: Instant,
} }
impl State { impl<S> State<S> {
fn new(initial_state: state::Application, now: Instant) -> Self { fn new(initial_state: S, now: Instant) -> Self {
Self { Self {
state: initial_state, state: initial_state,
scheduled_wakeup: None, scheduled_wakeup: None,
@ -77,11 +84,11 @@ impl State {
/// - determines next scheduled animation wakeup, /// - determines next scheduled animation wakeup,
/// and because this is a pure function, it's easily testable. /// and because this is a pure function, it's easily testable.
/// It returns the new state, and the message to send onwards. /// It returns the new state, and the message to send onwards.
fn handle_event( fn handle_event<S: ActorState<Event = state::Event>>(
mut loop_state: State, mut loop_state: State<S>,
event: state::Event, event: state::Event,
now: Instant, now: Instant,
) -> (State, Commands) { ) -> (State<S>, Commands) {
// Calculate changes to send to the consumer, // Calculate changes to send to the consumer,
// based on publicly visible state. // based on publicly visible state.
// The internal state may change more often than the publicly visible one, // The internal state may change more often than the publicly visible one,
@ -185,7 +192,7 @@ mod test {
now += animation::HIDING_TIMEOUT; now += animation::HIDING_TIMEOUT;
let (l, commands) = handle_event(l, Event::TimeoutReached(now), now); let (l, commands) = handle_event(l, state::Event::TimeoutReached(now), now);
assert_eq!(commands.panel_visibility, Some(panel::Command::Hide)); assert_eq!(commands.panel_visibility, Some(panel::Command::Hide));
assert_eq!(l.scheduled_wakeup, None); assert_eq!(l.scheduled_wakeup, None);
} }

View File

@ -8,6 +8,7 @@
use crate::animation; use crate::animation;
use crate::debug; use crate::debug;
use crate::event_loop; use crate::event_loop;
use crate::event_loop::ActorState;
use crate::imservice::{ ContentHint, ContentPurpose }; use crate::imservice::{ ContentHint, ContentPurpose };
use crate::layout::ArrangementKind; use crate::layout::ArrangementKind;
use crate::main; use crate::main;
@ -435,8 +436,16 @@ Outcome:
}, },
) )
} }
}
pub fn get_outcome(&self, now: Instant) -> Outcome { impl ActorState for Application {
type Event = Event;
fn apply_event(self, e: Self::Event, time: Instant) -> Self {
Self::apply_event(self, e, time)
}
fn get_outcome(&self, now: Instant) -> Outcome {
// FIXME: include physical keyboard presence // FIXME: include physical keyboard presence
Outcome { Outcome {
panel: match self.preferred_output { panel: match self.preferred_output {
@ -484,7 +493,7 @@ Outcome:
} }
/// Returns the next time to update the outcome. /// Returns the next time to update the outcome.
pub fn get_next_wake(&self, now: Instant) -> Option<Instant> { fn get_next_wake(&self, now: Instant) -> Option<Instant> {
match self { match self {
Self { Self {
visibility_override: visibility::State::NotForced, visibility_override: visibility::State::NotForced,