Commit 500c23be authored by Dorota Czaplejewicz's avatar Dorota Czaplejewicz
Browse files

locking: Lock keys statelessly

Locking is not determined by button state any more, but rather based on the view active at the moment. If pressing/locking a key results in the current view being active, the key is active. If locking a key results in the current view, the unlock view is activated.
parent 97d8dfe4
......@@ -38,3 +38,19 @@ pub enum Action {
},
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,
}
}
}
......@@ -392,7 +392,6 @@ impl Layout {
name.into(),
KeyState {
pressed: PressType::Released,
locked: false,
keycodes,
action,
}
......
......@@ -3,7 +3,6 @@
use cairo;
use std::cell::RefCell;
use ::action::Action;
use ::keyboard;
use ::layout::{ Button, Layout };
use ::layout::c::{ EekGtkKeyboard, Point };
......@@ -53,13 +52,7 @@ mod c {
for (row_offset, row) in &view.get_rows() {
for (x_offset, button) in &row.buttons {
let state = RefCell::borrow(&button.state).clone();
let locked = match state.action {
Action::SetView(name) => name == layout.current_view,
Action::LockView { lock, unlock: _ } => {
lock == layout.current_view
},
_ => false,
};
let locked = state.action.is_active(&layout.current_view);
if state.pressed == keyboard::PressType::Pressed || locked {
render_button_at_position(
renderer, &cr,
......
......@@ -23,7 +23,6 @@ pub type KeyCode = u32;
#[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<KeyCode>,
/// Static description of what the key does when pressed or released
......@@ -31,17 +30,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 {
......@@ -195,7 +183,6 @@ mod tests {
keys: vec!(KeySym("a".into()), KeySym("c".into())),
},
keycodes: vec!(9, 10),
locked: false,
pressed: PressType::Released,
},
}).unwrap();
......
......@@ -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<RefCell<KeyState>>>,
pub locked_keys: HashSet<::util::Pointer<RefCell<KeyState>>>,
}
/// 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<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 {
......@@ -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<RefCell<KeyState>> = 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 {
......@@ -899,10 +914,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 {
......@@ -918,13 +930,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(),
}
......@@ -966,11 +977,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);
}
......@@ -985,7 +991,6 @@ mod test {
pub fn make_state() -> Rc<RefCell<::keyboard::KeyState>> {
Rc::new(RefCell::new(::keyboard::KeyState {
pressed: PressType::Released,
locked: false,
keycodes: Vec::new(),
action: Action::SetView("default".into()),
}))
......@@ -1064,7 +1069,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 {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment