event loop: Decouple state type from event handler
This commit is contained in:
@ -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();
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/state.rs
13
src/state.rs
@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user