Resolve left and right combinations on deserialization

pull/56/head
Takashi Kokubun 3 years ago
parent 343204607c
commit c2204a4559
No known key found for this signature in database
GPG Key ID: 6FFC433B12EE23DD

@ -73,7 +73,7 @@ where
} }
// Used only for deserializing Vec<Action> // Used only for deserializing Vec<Action>
#[derive(Deserialize)] #[derive(Clone, Deserialize)]
#[serde(untagged)] #[serde(untagged)]
pub enum Actions { pub enum Actions {
Action(Action), Action(Action),

@ -6,10 +6,18 @@ use std::error;
#[derive(Clone, Debug, Eq, PartialEq, Hash)] #[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct KeyPress { pub struct KeyPress {
pub key: Key, pub key: Key,
pub shift: bool, pub shift: ModifierState,
pub control: bool, pub control: ModifierState,
pub alt: bool, pub alt: ModifierState,
pub windows: bool, pub windows: ModifierState,
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum ModifierState {
Left,
Right,
Either,
None,
} }
pub enum Modifier { pub enum Modifier {
@ -32,17 +40,17 @@ impl<'de> Deserialize<'de> for KeyPress {
fn parse_key_press(input: &str) -> Result<KeyPress, Box<dyn error::Error>> { fn parse_key_press(input: &str) -> Result<KeyPress, Box<dyn error::Error>> {
let keys: Vec<&str> = input.split("-").collect(); let keys: Vec<&str> = input.split("-").collect();
if let Some((key, modifiers)) = keys.split_last() { if let Some((key, modifiers)) = keys.split_last() {
let mut shift = false; let mut shift = ModifierState::None;
let mut control = false; let mut control = ModifierState::None;
let mut alt = false; let mut alt = ModifierState::None;
let mut windows = false; let mut windows = ModifierState::None;
for modifier in modifiers.iter() { for modifier in modifiers.iter() {
match parse_modifier(modifier) { match parse_modifier(modifier) {
Some(Modifier::Shift) => shift = true, Some((Modifier::Shift, state)) => shift = state,
Some(Modifier::Control) => control = true, Some((Modifier::Control, state)) => control = state,
Some(Modifier::Alt) => alt = true, Some((Modifier::Alt, state)) => alt = state,
Some(Modifier::Windows) => windows = true, Some((Modifier::Windows, state)) => windows = state,
None => return Err(format!("unknown modifier: {}", modifier).into()), None => return Err(format!("unknown modifier: {}", modifier).into()),
} }
} }
@ -60,22 +68,22 @@ fn parse_key_press(input: &str) -> Result<KeyPress, Box<dyn error::Error>> {
} }
} }
fn parse_modifier(modifier: &str) -> Option<Modifier> { fn parse_modifier(modifier: &str) -> Option<(Modifier, ModifierState)> {
// Everything is case-insensitive // Everything is case-insensitive
match &modifier.to_uppercase()[..] { match &modifier.to_uppercase()[..] {
// Shift // Shift
"SHIFT" => Some(Modifier::Shift), "SHIFT" => Some((Modifier::Shift, ModifierState::Either)),
// Control // Control
"C" => Some(Modifier::Control), "C" => Some((Modifier::Control, ModifierState::Either)),
"CTRL" => Some(Modifier::Control), "CTRL" => Some((Modifier::Control, ModifierState::Either)),
"CONTROL" => Some(Modifier::Control), "CONTROL" => Some((Modifier::Control, ModifierState::Either)),
// Alt // Alt
"M" => Some(Modifier::Alt), "M" => Some((Modifier::Alt, ModifierState::Either)),
"ALT" => Some(Modifier::Alt), "ALT" => Some((Modifier::Alt, ModifierState::Either)),
// Windows // Windows
"SUPER" => Some(Modifier::Windows), "SUPER" => Some((Modifier::Windows, ModifierState::Either)),
"WIN" => Some(Modifier::Windows), "WIN" => Some((Modifier::Windows, ModifierState::Either)),
"WINDOWS" => Some(Modifier::Windows), "WINDOWS" => Some((Modifier::Windows, ModifierState::Either)),
// else // else
_ => None, _ => None,
} }

@ -1,6 +1,6 @@
use crate::config::action::{Action, Actions}; use crate::config::action::{Action, Actions};
use crate::config::application::Application; use crate::config::application::Application;
use crate::config::key_press::KeyPress; use crate::config::key_press::{KeyPress, Modifier, ModifierState};
use serde::{Deserialize, Deserializer}; use serde::{Deserialize, Deserializer};
use std::collections::HashMap; use std::collections::HashMap;
@ -18,6 +18,62 @@ fn deserialize_remap<'de, D>(deserializer: D) -> Result<HashMap<KeyPress, Vec<Ac
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
let v = HashMap::<KeyPress, Actions>::deserialize(deserializer)?; let remap = HashMap::<KeyPress, Actions>::deserialize(deserializer)?;
Ok(v.into_iter().map(|(k, v)| (k, v.to_vec())).collect()) Ok(remap
.into_iter()
.flat_map(|(key_press, actions)| {
expand_modifiers(key_press)
.into_iter()
.map(|k| (k, actions.clone().to_vec()))
.collect::<Vec<(KeyPress, Vec<Action>)>>()
})
.collect())
}
// Expand ModifierState::Either to Left and Right. Not leaving Either to save some space and computation.
// Note that we currently don't have `Both`. Does anybody need it?
fn expand_modifiers(key_press: KeyPress) -> Vec<KeyPress> {
if key_press.shift == ModifierState::Either {
expand_modifier(key_press, &Modifier::Shift)
} else if key_press.control == ModifierState::Either {
expand_modifier(key_press, &Modifier::Control)
} else if key_press.alt == ModifierState::Either {
expand_modifier(key_press, &Modifier::Alt)
} else if key_press.windows == ModifierState::Either {
expand_modifier(key_press, &Modifier::Windows)
} else {
vec![key_press]
}
}
fn expand_modifier(key_press: KeyPress, modifier: &Modifier) -> Vec<KeyPress> {
vec![
change_modifier(key_press.clone(), modifier, ModifierState::Left),
change_modifier(key_press, modifier, ModifierState::Right),
]
.into_iter()
.flat_map(|key_press| expand_modifiers(key_press))
.collect()
}
fn change_modifier(key_press: KeyPress, modifier: &Modifier, state: ModifierState) -> KeyPress {
let mut shift = key_press.shift.clone();
let mut control = key_press.control.clone();
let mut alt = key_press.alt.clone();
let mut windows = key_press.windows.clone();
match modifier {
Modifier::Shift => shift = state,
Modifier::Control => control = state,
Modifier::Alt => alt = state,
Modifier::Windows => windows = state,
}
KeyPress {
key: key_press.key.clone(),
shift,
control,
alt,
windows,
}
} }

@ -2,7 +2,7 @@ use crate::client::{build_client, WMClient};
use crate::config::action::Action; use crate::config::action::Action;
use crate::config::application::Application; use crate::config::application::Application;
use crate::config::key_action::KeyAction; use crate::config::key_action::KeyAction;
use crate::config::key_press::{KeyPress, Modifier}; use crate::config::key_press::{KeyPress, Modifier, ModifierState};
use crate::Config; use crate::Config;
use evdev::uinput::VirtualDevice; use evdev::uinput::VirtualDevice;
use evdev::{EventType, InputEvent, Key}; use evdev::{EventType, InputEvent, Key};
@ -33,10 +33,10 @@ impl EventHandler {
pub fn new(device: VirtualDevice) -> EventHandler { pub fn new(device: VirtualDevice) -> EventHandler {
EventHandler { EventHandler {
device, device,
shift: PressState::new(false), shift: PressState::new(),
control: PressState::new(false), control: PressState::new(),
alt: PressState::new(false), alt: PressState::new(),
windows: PressState::new(false), windows: PressState::new(),
application_client: build_client(), application_client: build_client(),
application_cache: None, application_cache: None,
multi_purpose_keys: HashMap::new(), multi_purpose_keys: HashMap::new(),
@ -162,10 +162,10 @@ impl EventHandler {
let key_press = KeyPress { let key_press = KeyPress {
key: key.clone(), key: key.clone(),
shift: self.shift.left || self.shift.right, shift: self.shift.to_modifier_state(),
control: self.control.left || self.control.right, control: self.control.to_modifier_state(),
alt: self.alt.left || self.alt.right, alt: self.alt.to_modifier_state(),
windows: self.windows.left || self.windows.right, windows: self.windows.to_modifier_state(),
}; };
if let Some(override_remap) = &self.override_remap { if let Some(override_remap) = &self.override_remap {
let override_remap = override_remap.clone(); let override_remap = override_remap.clone();
@ -205,10 +205,10 @@ impl EventHandler {
} }
fn send_key_press(&mut self, key_press: &KeyPress) -> Result<(), Box<dyn Error>> { fn send_key_press(&mut self, key_press: &KeyPress) -> Result<(), Box<dyn Error>> {
let next_shift = self.build_state(Modifier::Shift, key_press.shift); let next_shift = self.build_state(Modifier::Shift, key_press.shift.clone());
let next_control = self.build_state(Modifier::Control, key_press.control); let next_control = self.build_state(Modifier::Control, key_press.control.clone());
let next_alt = self.build_state(Modifier::Alt, key_press.alt); let next_alt = self.build_state(Modifier::Alt, key_press.alt.clone());
let next_windows = self.build_state(Modifier::Windows, key_press.windows); let next_windows = self.build_state(Modifier::Windows, key_press.windows.clone());
let prev_shift = self.send_modifier(Modifier::Shift, &next_shift)?; let prev_shift = self.send_modifier(Modifier::Shift, &next_shift)?;
let prev_control = self.send_modifier(Modifier::Control, &next_control)?; let prev_control = self.send_modifier(Modifier::Control, &next_control)?;
@ -272,35 +272,54 @@ impl EventHandler {
Ok(original) Ok(original)
} }
// Choose a PressState closest to the current state fn build_state(&self, modifier: Modifier, modifier_state: ModifierState) -> PressState {
fn build_state(&self, modifier: Modifier, pressed: bool) -> PressState {
let press_state = match modifier { let press_state = match modifier {
Modifier::Shift => &self.shift, Modifier::Shift => &self.shift,
Modifier::Control => &self.control, Modifier::Control => &self.control,
Modifier::Alt => &self.alt, Modifier::Alt => &self.alt,
Modifier::Windows => &self.windows, Modifier::Windows => &self.windows,
}; };
if (press_state.left || press_state.right) == pressed {
press_state.clone() // no change is needed match modifier_state {
} else if pressed { ModifierState::Either => {
// just press left // Choose a PressState closest to the current PressState
PressState { if press_state.left || press_state.right {
press_state.clone() // no change is necessary
} else {
// Just press left
PressState {
left: true,
right: false,
}
}
}
ModifierState::Left => PressState {
left: true, left: true,
right: false, right: false,
} },
} else { ModifierState::Right => PressState {
// release all left: false,
PressState::new(false) right: true,
},
ModifierState::None => PressState {
left: false,
right: false,
},
} }
} }
fn with_mark(&self, key_press: &KeyPress) -> KeyPress { fn with_mark(&self, key_press: &KeyPress) -> KeyPress {
let mut shift = key_press.shift.clone();
if self.mark_set && shift == ModifierState::None {
// We don't leave Either in expand_modifiers(), so just using Left here.
shift = ModifierState::Left;
}
KeyPress { KeyPress {
key: key_press.key.clone(), key: key_press.key.clone(),
shift: key_press.shift || self.mark_set, shift,
control: key_press.control, control: key_press.control.clone(),
alt: key_press.alt, alt: key_press.alt.clone(),
windows: key_press.windows, windows: key_press.windows.clone(),
} }
} }
@ -413,10 +432,20 @@ struct PressState {
} }
impl PressState { impl PressState {
fn new(pressed: bool) -> PressState { fn new() -> PressState {
PressState { PressState {
left: pressed, left: false,
right: pressed, right: false,
}
}
fn to_modifier_state(&self) -> ModifierState {
if self.left {
ModifierState::Left
} else if self.right {
ModifierState::Right
} else {
ModifierState::None
} }
} }
} }

Loading…
Cancel
Save