event loop: Decouple event handler from concrete state
This commit is contained in:
		@ -38,12 +38,6 @@
 | 
			
		||||
 | 
			
		||||
pub mod driver;
 | 
			
		||||
 | 
			
		||||
// This module is tightly coupled to the shape of data passed around in this project.
 | 
			
		||||
// That's not a problem as long as there's only one loop.
 | 
			
		||||
// They can still be abstracted into Traits,
 | 
			
		||||
// and the loop parametrized over them.
 | 
			
		||||
use crate::main::Commands;
 | 
			
		||||
use crate::state;
 | 
			
		||||
use std::cmp;
 | 
			
		||||
use std::time::{ Duration, Instant };
 | 
			
		||||
 | 
			
		||||
@ -55,13 +49,22 @@ pub trait Event: Clone {
 | 
			
		||||
    fn get_timeout_reached(&self) -> Option<Instant>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Contains and updates the intenal state of the actor.
 | 
			
		||||
/// The externally observable state of the actor.
 | 
			
		||||
pub trait Outcome {
 | 
			
		||||
    type Commands;
 | 
			
		||||
    
 | 
			
		||||
    /// Returns the instructions to emit in order to change the current visible state to the desired one.
 | 
			
		||||
    fn get_commands_to_reach(&self, desired: &Self) -> Self::Commands;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Contains and calculates the intenal state of the actor.
 | 
			
		||||
pub trait ActorState: Clone {
 | 
			
		||||
    type Event: Event;
 | 
			
		||||
    type Outcome: Outcome;
 | 
			
		||||
    /// Returns the new internal state after the event gets processed.
 | 
			
		||||
    fn apply_event(self, e: Self::Event, time: Instant) -> Self;
 | 
			
		||||
    /// Returns the observable state of the actor given this internal state.
 | 
			
		||||
    fn get_outcome(&self, time: Instant) -> state::Outcome;
 | 
			
		||||
    fn get_outcome(&self, time: Instant) -> Self::Outcome;
 | 
			
		||||
    /// Returns the next wake up to schedule if one is needed.
 | 
			
		||||
    /// This may be called at any time, so should always return the correct value.
 | 
			
		||||
    fn get_next_wake(&self, now: Instant) -> Option<Instant>;
 | 
			
		||||
@ -95,7 +98,7 @@ fn handle_event<S: ActorState>(
 | 
			
		||||
    mut loop_state: State<S>,
 | 
			
		||||
    event: S::Event,
 | 
			
		||||
    now: Instant,
 | 
			
		||||
) -> (State<S>, Commands) {
 | 
			
		||||
) -> (State<S>, <S::Outcome as Outcome>::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,
 | 
			
		||||
@ -170,6 +173,7 @@ mod test {
 | 
			
		||||
    use crate::animation;
 | 
			
		||||
    use crate::imservice::{ ContentHint, ContentPurpose };
 | 
			
		||||
    use crate::panel;
 | 
			
		||||
    use crate::state;
 | 
			
		||||
    use crate::state::{ Application, InputMethod, InputMethodDetails, Presence, visibility };
 | 
			
		||||
    use crate::state::test::application_with_fake_output;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -130,13 +130,14 @@ pub struct Outcome {
 | 
			
		||||
    pub im: InputMethod,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Outcome {
 | 
			
		||||
impl event_loop::Outcome for Outcome {
 | 
			
		||||
    type Commands = Commands;
 | 
			
		||||
    /// Returns the commands needed to apply changes as required by the new state.
 | 
			
		||||
    /// This implementation doesn't actually take the old state into account,
 | 
			
		||||
    /// instead issuing all the commands as needed to reach the new state.
 | 
			
		||||
    /// The receivers of the commands bear the burden
 | 
			
		||||
    /// of checking if the commands end up being no-ops.
 | 
			
		||||
    pub fn get_commands_to_reach(&self, new_state: &Self) -> Commands {
 | 
			
		||||
    fn get_commands_to_reach(&self, new_state: &Self) -> Commands {
 | 
			
		||||
// FIXME: handle switching outputs
 | 
			
		||||
        let (dbus_visible_set, panel_visibility) = match new_state.panel {
 | 
			
		||||
            animation::Outcome::Visible{output, height, ..}
 | 
			
		||||
@ -440,6 +441,7 @@ Outcome:
 | 
			
		||||
 | 
			
		||||
impl ActorState for Application {
 | 
			
		||||
    type Event = Event;
 | 
			
		||||
    type Outcome = Outcome;
 | 
			
		||||
    
 | 
			
		||||
    fn apply_event(self, e: Self::Event, time: Instant) -> Self {
 | 
			
		||||
        Self::apply_event(self, e, time)
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user