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>
#[derive(Deserialize)]
#[derive(Clone, Deserialize)]
#[serde(untagged)]
pub enum Actions {
Action(Action),

@ -6,10 +6,18 @@ use std::error;
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct KeyPress {
pub key: Key,
pub shift: bool,
pub control: bool,
pub alt: bool,
pub windows: bool,
pub shift: ModifierState,
pub control: ModifierState,
pub alt: ModifierState,
pub windows: ModifierState,
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum ModifierState {
Left,
Right,
Either,
None,
}
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>> {
let keys: Vec<&str> = input.split("-").collect();
if let Some((key, modifiers)) = keys.split_last() {
let mut shift = false;
let mut control = false;
let mut alt = false;
let mut windows = false;
let mut shift = ModifierState::None;
let mut control = ModifierState::None;
let mut alt = ModifierState::None;
let mut windows = ModifierState::None;
for modifier in modifiers.iter() {
match parse_modifier(modifier) {
Some(Modifier::Shift) => shift = true,
Some(Modifier::Control) => control = true,
Some(Modifier::Alt) => alt = true,
Some(Modifier::Windows) => windows = true,
Some((Modifier::Shift, state)) => shift = state,
Some((Modifier::Control, state)) => control = state,
Some((Modifier::Alt, state)) => alt = state,
Some((Modifier::Windows, state)) => windows = state,
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
match &modifier.to_uppercase()[..] {
// Shift
"SHIFT" => Some(Modifier::Shift),
"SHIFT" => Some((Modifier::Shift, ModifierState::Either)),
// Control
"C" => Some(Modifier::Control),
"CTRL" => Some(Modifier::Control),
"CONTROL" => Some(Modifier::Control),
"C" => Some((Modifier::Control, ModifierState::Either)),
"CTRL" => Some((Modifier::Control, ModifierState::Either)),
"CONTROL" => Some((Modifier::Control, ModifierState::Either)),
// Alt
"M" => Some(Modifier::Alt),
"ALT" => Some(Modifier::Alt),
"M" => Some((Modifier::Alt, ModifierState::Either)),
"ALT" => Some((Modifier::Alt, ModifierState::Either)),
// Windows
"SUPER" => Some(Modifier::Windows),
"WIN" => Some(Modifier::Windows),
"WINDOWS" => Some(Modifier::Windows),
"SUPER" => Some((Modifier::Windows, ModifierState::Either)),
"WIN" => Some((Modifier::Windows, ModifierState::Either)),
"WINDOWS" => Some((Modifier::Windows, ModifierState::Either)),
// else
_ => None,
}

@ -1,6 +1,6 @@
use crate::config::action::{Action, Actions};
use crate::config::application::Application;
use crate::config::key_press::KeyPress;
use crate::config::key_press::{KeyPress, Modifier, ModifierState};
use serde::{Deserialize, Deserializer};
use std::collections::HashMap;
@ -18,6 +18,62 @@ fn deserialize_remap<'de, D>(deserializer: D) -> Result<HashMap<KeyPress, Vec<Ac
where
D: Deserializer<'de>,
{
let v = HashMap::<KeyPress, Actions>::deserialize(deserializer)?;
Ok(v.into_iter().map(|(k, v)| (k, v.to_vec())).collect())
let remap = HashMap::<KeyPress, Actions>::deserialize(deserializer)?;
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::application::Application;
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 evdev::uinput::VirtualDevice;
use evdev::{EventType, InputEvent, Key};
@ -33,10 +33,10 @@ impl EventHandler {
pub fn new(device: VirtualDevice) -> EventHandler {
EventHandler {
device,
shift: PressState::new(false),
control: PressState::new(false),
alt: PressState::new(false),
windows: PressState::new(false),
shift: PressState::new(),
control: PressState::new(),
alt: PressState::new(),
windows: PressState::new(),
application_client: build_client(),
application_cache: None,
multi_purpose_keys: HashMap::new(),
@ -162,10 +162,10 @@ impl EventHandler {
let key_press = KeyPress {
key: key.clone(),
shift: self.shift.left || self.shift.right,
control: self.control.left || self.control.right,
alt: self.alt.left || self.alt.right,
windows: self.windows.left || self.windows.right,
shift: self.shift.to_modifier_state(),
control: self.control.to_modifier_state(),
alt: self.alt.to_modifier_state(),
windows: self.windows.to_modifier_state(),
};
if let Some(override_remap) = &self.override_remap {
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>> {
let next_shift = self.build_state(Modifier::Shift, key_press.shift);
let next_control = self.build_state(Modifier::Control, key_press.control);
let next_alt = self.build_state(Modifier::Alt, key_press.alt);
let next_windows = self.build_state(Modifier::Windows, key_press.windows);
let next_shift = self.build_state(Modifier::Shift, key_press.shift.clone());
let next_control = self.build_state(Modifier::Control, key_press.control.clone());
let next_alt = self.build_state(Modifier::Alt, key_press.alt.clone());
let next_windows = self.build_state(Modifier::Windows, key_press.windows.clone());
let prev_shift = self.send_modifier(Modifier::Shift, &next_shift)?;
let prev_control = self.send_modifier(Modifier::Control, &next_control)?;
@ -272,35 +272,54 @@ impl EventHandler {
Ok(original)
}
// Choose a PressState closest to the current state
fn build_state(&self, modifier: Modifier, pressed: bool) -> PressState {
fn build_state(&self, modifier: Modifier, modifier_state: ModifierState) -> PressState {
let press_state = match modifier {
Modifier::Shift => &self.shift,
Modifier::Control => &self.control,
Modifier::Alt => &self.alt,
Modifier::Windows => &self.windows,
};
if (press_state.left || press_state.right) == pressed {
press_state.clone() // no change is needed
} else if pressed {
// just press left
PressState {
match modifier_state {
ModifierState::Either => {
// Choose a PressState closest to the current 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,
right: false,
}
} else {
// release all
PressState::new(false)
},
ModifierState::Right => PressState {
left: false,
right: true,
},
ModifierState::None => PressState {
left: false,
right: false,
},
}
}
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 {
key: key_press.key.clone(),
shift: key_press.shift || self.mark_set,
control: key_press.control,
alt: key_press.alt,
windows: key_press.windows,
shift,
control: key_press.control.clone(),
alt: key_press.alt.clone(),
windows: key_press.windows.clone(),
}
}
@ -413,10 +432,20 @@ struct PressState {
}
impl PressState {
fn new(pressed: bool) -> PressState {
fn new() -> PressState {
PressState {
left: pressed,
right: pressed,
left: false,
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