From dcbd55c31e351ce0045840a9237755ca5b300c6a Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sat, 30 Nov 2019 12:15:55 +0000 Subject: [PATCH] layout: Eliminate locked and presed key lists The lists duplicated a source of truth, and were complicating the code, which can now be separated cleaner by effect areas. --- src/keyboard.rs | 17 +++++- src/layout.rs | 135 +++++++++++++++++++++++++++------------------- src/submission.rs | 12 ++--- 3 files changed, 101 insertions(+), 63 deletions(-) diff --git a/src/keyboard.rs b/src/keyboard.rs index 0ae163e6..411e47c2 100644 --- a/src/keyboard.rs +++ b/src/keyboard.rs @@ -41,16 +41,31 @@ pub enum PressType { Pressed = 1, } +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, + pub keycodes: Vec, /// Static description of what the key does when pressed or released pub action: Action, } +impl KeyState { + #[must_use] + pub fn activate(self) -> KeyState { + match self.action { + Action::LockLevel { lock: _, unlock: _ } => KeyState { + locked: self.locked ^ true, + ..self + }, + _ => self, + } + } +} + /// Generates a mapping where each key gets a keycode, starting from ~~8~~ /// HACK: starting from 9, because 8 results in keycode 0, /// which the compositor likes to discard diff --git a/src/layout.rs b/src/layout.rs index 27e32cd5..c465fec8 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -27,8 +27,10 @@ use ::action::Action; use ::float_ord::FloatOrd; use ::keyboard::{ KeyState, PressType }; use ::submission::{ Timestamp, VirtualKeyboard }; +use ::util; use std::borrow::Borrow; +use std::iter::FromIterator; /// Gathers stuff defined in C or called by C pub mod c { @@ -354,7 +356,8 @@ pub mod c { let virtual_keyboard = VirtualKeyboard(virtual_keyboard); // The list must be copied, // because it will be mutated in the loop - for key in layout.pressed_keys.clone() { + let keys = layout.get_pressed_keys(); + for key in keys { let key: &Rc> = key.borrow(); ui::release_key( layout, @@ -377,9 +380,8 @@ pub mod c { ) { let layout = unsafe { &mut *layout }; let virtual_keyboard = VirtualKeyboard(virtual_keyboard); - // The list must be copied, - // because it will be mutated in the loop - for key in layout.pressed_keys.clone() { + + for key in layout.get_pressed_keys() { let key: &Rc> = key.borrow(); layout.release_key( &virtual_keyboard, @@ -448,7 +450,7 @@ pub mod c { Point { x: x_widget, y: y_widget } ); - let pressed = layout.pressed_keys.clone(); + let pressed = layout.get_pressed_keys(); let state_place = { let view = layout.get_current_view(); let place = view.find_button_by_position(point); @@ -460,9 +462,8 @@ pub mod c { if let Some((mut state, c_place)) = state_place { let mut found = false; - for wrapped_key in pressed { - let key: &Rc> = wrapped_key.borrow(); - if Rc::ptr_eq(&state, &wrapped_key.0) { + for key in pressed { + if Rc::ptr_eq(&state, &key) { found = true; } else { ui::release_key( @@ -471,7 +472,7 @@ pub mod c { &widget_to_layout, time, ui_keyboard, - key, + &key, ); } } @@ -480,15 +481,14 @@ pub mod c { unsafe { eek_gtk_on_button_pressed(c_place, ui_keyboard) }; } } else { - for wrapped_key in pressed { - let key: &Rc> = wrapped_key.borrow(); + for key in pressed { ui::release_key( layout, &virtual_keyboard, &widget_to_layout, time, ui_keyboard, - key, + &key, ); } } @@ -755,15 +755,7 @@ pub struct Layout { /// xkb keymap applicable to the contained keys. Unchangeable pub keymap_str: CString, // Changeable state - // a Vec would be enough, but who cares, this will be small & fast enough - // TODO: turn those into per-input point *_buttons to track dragging. - // The renderer doesn't need the list of pressed keys any more, - // because it needs to iterate - // through all buttons of the current view anyway. - // 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>>, + // TODO: store clicked buttons per-input point to track dragging. } /// A builder structure for picking up layout data from storage @@ -785,14 +777,53 @@ impl Layout { current_view: "base".to_owned(), views: data.views, keymap_str: data.keymap_str, - pressed_keys: HashSet::new(), - locked_keys: HashSet::new(), } } fn get_current_view(&self) -> &Box { self.views.get(&self.current_view).expect("Selected nonexistent view") } + /// Returns all keys matching filter, without duplicates + fn get_filtered_keys(&self, pred: F) -> Vec>> + where F: Fn(&Box