Merge branch 'lock' into 'master'
Turn locking stateless See merge request Librem5/squeekboard!322
This commit is contained in:
		@ -41,3 +41,19 @@ pub enum Action {
 | 
				
			|||||||
    Erase,
 | 
					    Erase,
 | 
				
			||||||
    ShowPreferences,
 | 
					    ShowPreferences,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Action {
 | 
				
			||||||
 | 
					    pub fn is_locked(&self, view_name: &str) -> bool {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            Action::LockView { lock, unlock: _ } => lock == view_name,
 | 
				
			||||||
 | 
					            _ => false,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub fn is_active(&self, view_name: &str) -> bool {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            Action::SetView(view) => view == view_name,
 | 
				
			||||||
 | 
					            Action::LockView { lock, unlock: _ } => lock == view_name,
 | 
				
			||||||
 | 
					            _ => false,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -400,7 +400,6 @@ impl Layout {
 | 
				
			|||||||
                name.into(),
 | 
					                name.into(),
 | 
				
			||||||
                KeyState {
 | 
					                KeyState {
 | 
				
			||||||
                    pressed: PressType::Released,
 | 
					                    pressed: PressType::Released,
 | 
				
			||||||
                    locked: false,
 | 
					 | 
				
			||||||
                    keycodes,
 | 
					                    keycodes,
 | 
				
			||||||
                    action,
 | 
					                    action,
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
				
			|||||||
@ -37,6 +37,7 @@ mod c {
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Draws all buttons that are not in the base state
 | 
				
			||||||
    #[no_mangle]
 | 
					    #[no_mangle]
 | 
				
			||||||
    pub extern "C"
 | 
					    pub extern "C"
 | 
				
			||||||
    fn squeek_layout_draw_all_changed(
 | 
					    fn squeek_layout_draw_all_changed(
 | 
				
			||||||
@ -51,12 +52,13 @@ mod c {
 | 
				
			|||||||
        for (row_offset, row) in &view.get_rows() {
 | 
					        for (row_offset, row) in &view.get_rows() {
 | 
				
			||||||
            for (x_offset, button) in &row.buttons {
 | 
					            for (x_offset, button) in &row.buttons {
 | 
				
			||||||
                let state = RefCell::borrow(&button.state).clone();
 | 
					                let state = RefCell::borrow(&button.state).clone();
 | 
				
			||||||
                if state.pressed == keyboard::PressType::Pressed || state.locked {
 | 
					                let locked = state.action.is_active(&layout.current_view);
 | 
				
			||||||
 | 
					                if state.pressed == keyboard::PressType::Pressed || locked {
 | 
				
			||||||
                    render_button_at_position(
 | 
					                    render_button_at_position(
 | 
				
			||||||
                        renderer, &cr,
 | 
					                        renderer, &cr,
 | 
				
			||||||
                        row_offset + Point { x: *x_offset, y: 0.0 },
 | 
					                        row_offset + Point { x: *x_offset, y: 0.0 },
 | 
				
			||||||
                        button.as_ref(),
 | 
					                        button.as_ref(),
 | 
				
			||||||
                        state.pressed, state.locked,
 | 
					                        state.pressed, locked,
 | 
				
			||||||
                    );
 | 
					                    );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -31,7 +31,6 @@ pub struct KeyStateId(*const KeyState);
 | 
				
			|||||||
#[derive(Debug, Clone)]
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
pub struct KeyState {
 | 
					pub struct KeyState {
 | 
				
			||||||
    pub pressed: PressType,
 | 
					    pub pressed: PressType,
 | 
				
			||||||
    pub locked: bool,
 | 
					 | 
				
			||||||
    /// A cache of raw keycodes derived from Action::Sumbit given a keymap
 | 
					    /// A cache of raw keycodes derived from Action::Sumbit given a keymap
 | 
				
			||||||
    pub keycodes: Vec<KeyCode>,
 | 
					    pub keycodes: Vec<KeyCode>,
 | 
				
			||||||
    /// Static description of what the key does when pressed or released
 | 
					    /// Static description of what the key does when pressed or released
 | 
				
			||||||
@ -39,17 +38,6 @@ pub struct KeyState {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl KeyState {
 | 
					impl KeyState {
 | 
				
			||||||
    #[must_use]
 | 
					 | 
				
			||||||
    pub fn into_activated(self) -> KeyState {
 | 
					 | 
				
			||||||
        match self.action {
 | 
					 | 
				
			||||||
            Action::LockView { lock: _, unlock: _ } => KeyState {
 | 
					 | 
				
			||||||
                locked: self.locked ^ true,
 | 
					 | 
				
			||||||
                ..self
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            _ => self,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[must_use]
 | 
					    #[must_use]
 | 
				
			||||||
    pub fn into_released(self) -> KeyState {
 | 
					    pub fn into_released(self) -> KeyState {
 | 
				
			||||||
        KeyState {
 | 
					        KeyState {
 | 
				
			||||||
@ -233,7 +221,6 @@ mod tests {
 | 
				
			|||||||
                    keys: vec!(KeySym("a".into()), KeySym("c".into())),
 | 
					                    keys: vec!(KeySym("a".into()), KeySym("c".into())),
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                keycodes: vec!(9, 10),
 | 
					                keycodes: vec!(9, 10),
 | 
				
			||||||
                locked: false,
 | 
					 | 
				
			||||||
                pressed: PressType::Released,
 | 
					                pressed: PressType::Released,
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
        }).unwrap();
 | 
					        }).unwrap();
 | 
				
			||||||
 | 
				
			|||||||
@ -619,7 +619,6 @@ pub struct Layout {
 | 
				
			|||||||
    // When the list tracks actual location,
 | 
					    // When the list tracks actual location,
 | 
				
			||||||
    // it becomes possible to place popovers and other UI accurately.
 | 
					    // it becomes possible to place popovers and other UI accurately.
 | 
				
			||||||
    pub pressed_keys: HashSet<::util::Pointer<RefCell<KeyState>>>,
 | 
					    pub pressed_keys: HashSet<::util::Pointer<RefCell<KeyState>>>,
 | 
				
			||||||
    pub locked_keys: HashSet<::util::Pointer<RefCell<KeyState>>>,
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// A builder structure for picking up layout data from storage
 | 
					/// A builder structure for picking up layout data from storage
 | 
				
			||||||
@ -650,7 +649,6 @@ impl Layout {
 | 
				
			|||||||
            views: data.views,
 | 
					            views: data.views,
 | 
				
			||||||
            keymap_str: data.keymap_str,
 | 
					            keymap_str: data.keymap_str,
 | 
				
			||||||
            pressed_keys: HashSet::new(),
 | 
					            pressed_keys: HashSet::new(),
 | 
				
			||||||
            locked_keys: HashSet::new(),
 | 
					 | 
				
			||||||
            margins: data.margins,
 | 
					            margins: data.margins,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -714,6 +712,23 @@ impl Layout {
 | 
				
			|||||||
            scale: 1.0,
 | 
					            scale: 1.0,
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn get_locked_keys(&self) -> Vec<Rc<RefCell<KeyState>>> {
 | 
				
			||||||
 | 
					        let mut out = Vec::new();
 | 
				
			||||||
 | 
					        let view = self.get_current_view();
 | 
				
			||||||
 | 
					        for (_, row) in &view.get_rows() {
 | 
				
			||||||
 | 
					            for (_, button) in &row.buttons {
 | 
				
			||||||
 | 
					                let locked = {
 | 
				
			||||||
 | 
					                    let state = RefCell::borrow(&button.state).clone();
 | 
				
			||||||
 | 
					                    state.action.is_locked(&self.current_view)
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					                if locked {
 | 
				
			||||||
 | 
					                    out.push(button.state.clone());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        out
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod procedures {
 | 
					mod procedures {
 | 
				
			||||||
@ -838,12 +853,13 @@ mod seat {
 | 
				
			|||||||
    // This is guaranteed because pressing a lock button unlocks all others.
 | 
					    // This is guaranteed because pressing a lock button unlocks all others.
 | 
				
			||||||
    // TODO: Make some broader guarantee about the resulting view,
 | 
					    // TODO: Make some broader guarantee about the resulting view,
 | 
				
			||||||
    // e.g. by maintaining a stack of stuck keys.
 | 
					    // e.g. by maintaining a stack of stuck keys.
 | 
				
			||||||
 | 
					    // FIXME: This doesn't record changes in layout.locked_keys
 | 
				
			||||||
    #[must_use]
 | 
					    #[must_use]
 | 
				
			||||||
    fn unstick_locks(layout: &mut Layout) -> ViewChange {
 | 
					    fn unstick_locks(layout: &mut Layout) -> ViewChange {
 | 
				
			||||||
        let mut new_view = None;
 | 
					        let mut new_view = None;
 | 
				
			||||||
        for key in layout.locked_keys.clone() {
 | 
					        for key in layout.get_locked_keys().clone() {
 | 
				
			||||||
            let key: &Rc<RefCell<KeyState>> = key.borrow();
 | 
					            let key: &Rc<RefCell<KeyState>> = key.borrow();
 | 
				
			||||||
            let mut key = RefCell::borrow_mut(key);
 | 
					            let key = RefCell::borrow(key);
 | 
				
			||||||
            match &key.action {
 | 
					            match &key.action {
 | 
				
			||||||
                Action::LockView { lock: _, unlock: view } => {
 | 
					                Action::LockView { lock: _, unlock: view } => {
 | 
				
			||||||
                    new_view = Some(view.clone());
 | 
					                    new_view = Some(view.clone());
 | 
				
			||||||
@ -854,7 +870,6 @@ mod seat {
 | 
				
			|||||||
                    a,
 | 
					                    a,
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            key.locked = false;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        ViewChange {
 | 
					        ViewChange {
 | 
				
			||||||
@ -895,10 +910,7 @@ mod seat {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // update
 | 
					        // update
 | 
				
			||||||
        let key = key.into_released();
 | 
					        let key = key.into_released();
 | 
				
			||||||
        let key = match action {
 | 
					        let mut locked = key.action.is_locked(&layout.current_view);
 | 
				
			||||||
            Action::LockView { lock: _, unlock: _ } => key.into_activated(),
 | 
					 | 
				
			||||||
            _ => key,
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // process changes
 | 
					        // process changes
 | 
				
			||||||
        match action {
 | 
					        match action {
 | 
				
			||||||
@ -912,13 +924,12 @@ mod seat {
 | 
				
			|||||||
                try_set_view(layout, view)
 | 
					                try_set_view(layout, view)
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            Action::LockView { lock, unlock } => {
 | 
					            Action::LockView { lock, unlock } => {
 | 
				
			||||||
                // The button that triggered this will be in the right state
 | 
					                locked ^= true;
 | 
				
			||||||
                // due to commit at the end.
 | 
					 | 
				
			||||||
                unstick_locks(layout)
 | 
					                unstick_locks(layout)
 | 
				
			||||||
                    // It doesn't matter what the resulting view should be,
 | 
					                    // It doesn't matter what the resulting view should be,
 | 
				
			||||||
                    // it's getting changed anyway.
 | 
					                    // it's getting changed anyway.
 | 
				
			||||||
                    .choose_view(
 | 
					                    .choose_view(
 | 
				
			||||||
                        match key.locked {
 | 
					                        match locked {
 | 
				
			||||||
                            true => lock.clone(),
 | 
					                            true => lock.clone(),
 | 
				
			||||||
                            false => unlock.clone(),
 | 
					                            false => unlock.clone(),
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
@ -960,11 +971,6 @@ mod seat {
 | 
				
			|||||||
        let pointer = ::util::Pointer(rckey.clone());
 | 
					        let pointer = ::util::Pointer(rckey.clone());
 | 
				
			||||||
        // Apply state changes
 | 
					        // Apply state changes
 | 
				
			||||||
        layout.pressed_keys.remove(&pointer);
 | 
					        layout.pressed_keys.remove(&pointer);
 | 
				
			||||||
        if key.locked {
 | 
					 | 
				
			||||||
            layout.locked_keys.insert(pointer);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            layout.locked_keys.remove(&pointer);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        // Commit activated button state changes
 | 
					        // Commit activated button state changes
 | 
				
			||||||
        RefCell::replace(rckey, key);
 | 
					        RefCell::replace(rckey, key);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -979,7 +985,6 @@ mod test {
 | 
				
			|||||||
    pub fn make_state() -> Rc<RefCell<::keyboard::KeyState>> {
 | 
					    pub fn make_state() -> Rc<RefCell<::keyboard::KeyState>> {
 | 
				
			||||||
        Rc::new(RefCell::new(::keyboard::KeyState {
 | 
					        Rc::new(RefCell::new(::keyboard::KeyState {
 | 
				
			||||||
            pressed: PressType::Released,
 | 
					            pressed: PressType::Released,
 | 
				
			||||||
            locked: false,
 | 
					 | 
				
			||||||
            keycodes: Vec::new(),
 | 
					            keycodes: Vec::new(),
 | 
				
			||||||
            action: Action::SetView("default".into()),
 | 
					            action: Action::SetView("default".into()),
 | 
				
			||||||
        }))
 | 
					        }))
 | 
				
			||||||
@ -1058,7 +1063,6 @@ mod test {
 | 
				
			|||||||
            current_view: String::new(),
 | 
					            current_view: String::new(),
 | 
				
			||||||
            keymap_str: CString::new("").unwrap(),
 | 
					            keymap_str: CString::new("").unwrap(),
 | 
				
			||||||
            kind: ArrangementKind::Base,
 | 
					            kind: ArrangementKind::Base,
 | 
				
			||||||
            locked_keys: HashSet::new(),
 | 
					 | 
				
			||||||
            pressed_keys: HashSet::new(),
 | 
					            pressed_keys: HashSet::new(),
 | 
				
			||||||
            // Lots of bottom margin
 | 
					            // Lots of bottom margin
 | 
				
			||||||
            margins: Margins {
 | 
					            margins: Margins {
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user