From e0b37d60c4dbddb40e2be621166ca8c512ba37d9 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Mon, 28 Nov 2022 14:39:21 +0000 Subject: [PATCH] event loop: Decouple state type from event handler --- src/event_loop/driver.rs | 4 ++-- src/event_loop/mod.rs | 23 +++++++++++++++-------- src/state.rs | 13 +++++++++++-- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/event_loop/driver.rs b/src/event_loop/driver.rs index dcc22da5..6c313ad1 100644 --- a/src/event_loop/driver.rs +++ b/src/event_loop/driver.rs @@ -75,8 +75,8 @@ impl Threaded { self.thread.send(event) } - fn handle_loop_event(loop_sender: &Sender, state: event_loop::State, event: Event, ui: &UISender) - -> event_loop::State + fn handle_loop_event(loop_sender: &Sender, state: event_loop::State, event: Event, ui: &UISender) + -> event_loop::State { let now = Instant::now(); diff --git a/src/event_loop/mod.rs b/src/event_loop/mod.rs index e5581468..6771403f 100644 --- a/src/event_loop/mod.rs +++ b/src/event_loop/mod.rs @@ -49,20 +49,27 @@ use std::time::{ Duration, Instant }; pub trait Event: Clone { + /// Returns the value of the reached timeout, if this event carries the timeout. fn get_timeout_reached(&self) -> Option; } +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; +} /// This keeps the state of the tracker loop between iterations #[derive(Clone)] -struct State { - state: state::Application, +struct State { + state: S, scheduled_wakeup: Option, last_update: Instant, } -impl State { - fn new(initial_state: state::Application, now: Instant) -> Self { +impl State { + fn new(initial_state: S, now: Instant) -> Self { Self { state: initial_state, scheduled_wakeup: None, @@ -77,11 +84,11 @@ impl State { /// - determines next scheduled animation wakeup, /// and because this is a pure function, it's easily testable. /// It returns the new state, and the message to send onwards. -fn handle_event( - mut loop_state: State, +fn handle_event>( + mut loop_state: State, event: state::Event, now: Instant, -) -> (State, Commands) { +) -> (State, Commands) { // Calculate changes to send to the consumer, // based on publicly visible state. // The internal state may change more often than the publicly visible one, @@ -185,7 +192,7 @@ mod test { 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!(l.scheduled_wakeup, None); } diff --git a/src/state.rs b/src/state.rs index 84b91885..2ca45638 100644 --- a/src/state.rs +++ b/src/state.rs @@ -8,6 +8,7 @@ use crate::animation; use crate::debug; use crate::event_loop; +use crate::event_loop::ActorState; use crate::imservice::{ ContentHint, ContentPurpose }; use crate::layout::ArrangementKind; 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 Outcome { panel: match self.preferred_output { @@ -484,7 +493,7 @@ Outcome: } /// Returns the next time to update the outcome. - pub fn get_next_wake(&self, now: Instant) -> Option { + fn get_next_wake(&self, now: Instant) -> Option { match self { Self { visibility_override: visibility::State::NotForced,