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