use crate::capability::{CapMatch, Capability};
use crate::domain;
use crate::domain::Domain;
use crate::ecodes;
use crate::error::ArgumentError;
use crate::error::Context;
use crate::event::{Channel, Event, EventCode, EventType, Namespace, VirtualEventType};
use crate::range::Range;
use crate::utils;
#[derive(Clone, Debug)]
pub struct Key {
properties: Vec<KeyProperty>,
}
impl Key {
fn new() -> Key {
Key {
properties: Vec::new(),
}
}
pub fn copy() -> Key {
Key::new()
}
pub fn from_domain_and_namespace(domain: Domain, namespace: Namespace) -> Key {
let mut result = Key::new();
result.add_property(KeyProperty::Namespace(namespace));
result.add_property(KeyProperty::Domain(domain));
result
}
pub fn matches(&self, event: &Event) -> bool {
self.properties.iter().all(|prop| prop.matches(event))
}
pub fn matches_channel(&self, channel: Channel) -> bool {
self.properties
.iter()
.all(|prop| prop.matches_channel(channel))
}
pub fn matches_cap(&self, cap: &Capability) -> CapMatch {
self.properties
.iter()
.map(|prop| prop.matches_cap(cap))
.min()
.unwrap_or(CapMatch::Yes)
}
pub fn merge(&self, mut event: Event) -> Event {
for prop in &self.properties {
event = prop.merge(event);
}
event
}
pub fn merge_cap(&self, mut cap: Capability) -> Capability {
for prop in &self.properties {
cap = prop.merge_cap(cap);
}
cap
}
pub fn pop_value(&mut self) -> Option<Range> {
let mut result: Option<Range> = None;
self.properties.retain(|&property| match property {
KeyProperty::Value(range) => {
result = Some(range);
false
}
_ => true,
});
result
}
fn add_property(&mut self, property: KeyProperty) {
self.properties.push(property);
}
pub fn requires_event_type(&self) -> Option<EventType> {
for property in &self.properties {
match property {
KeyProperty::Code(code) => return Some(code.ev_type()),
KeyProperty::VirtualType(v_type) => return Some(v_type.ev_type()),
KeyProperty::Domain(_)
| KeyProperty::Namespace(_)
| KeyProperty::Value(_)
| KeyProperty::PreviousValue(_)
| KeyProperty::DeltaFactor(_)
| KeyProperty::AbsoluteFactor(_) => (),
}
}
None
}
pub fn intersects_with(&self, other: &Key) -> bool {
for prop_1 in &self.properties {
for prop_2 in &other.properties {
let these_properties_may_intersect = match (prop_1, prop_2) {
(KeyProperty::Code(left), KeyProperty::Code(right)) => left == right,
(KeyProperty::Domain(left), KeyProperty::Domain(right)) => left == right,
(KeyProperty::Namespace(left), KeyProperty::Namespace(right)) => left == right,
(KeyProperty::VirtualType(left), KeyProperty::VirtualType(right)) => {
left == right
}
(KeyProperty::VirtualType(v_type), KeyProperty::Code(code))
| (KeyProperty::Code(code), KeyProperty::VirtualType(v_type)) => {
*v_type == code.virtual_ev_type()
}
(KeyProperty::Value(left), KeyProperty::Value(right))
| (KeyProperty::PreviousValue(left), KeyProperty::PreviousValue(right)) => {
left.intersects_with(right)
}
(KeyProperty::Code(_), _)
| (KeyProperty::Domain(_), _)
| (KeyProperty::Namespace(_), _)
| (KeyProperty::VirtualType(_), _)
| (KeyProperty::Value(_), _)
| (KeyProperty::PreviousValue(_), _)
| (KeyProperty::DeltaFactor(_), _)
| (KeyProperty::AbsoluteFactor(_), _) => true,
};
if !these_properties_may_intersect {
return false;
}
}
}
true
}
}
#[derive(Clone, Copy, Debug)]
enum KeyProperty {
Code(EventCode),
Domain(Domain),
Namespace(Namespace),
Value(Range),
PreviousValue(Range),
VirtualType(VirtualEventType),
AbsoluteFactor(f64),
DeltaFactor(f64),
}
impl KeyProperty {
pub fn matches(&self, event: &Event) -> bool {
match *self {
KeyProperty::Code(value) => event.code == value,
KeyProperty::Domain(value) => event.domain == value,
KeyProperty::VirtualType(value) => event.code.virtual_ev_type() == value,
KeyProperty::Namespace(value) => event.namespace == value,
KeyProperty::Value(range) => range.contains(event.value),
KeyProperty::PreviousValue(range) => range.contains(event.previous_value),
KeyProperty::AbsoluteFactor(_) | KeyProperty::DeltaFactor(_) => {
if cfg!(debug_assertions) {
panic!("Cannot filter events based on relative values. Panicked during event mapping.");
}
false
}
}
}
pub fn matches_channel(&self, channel: Channel) -> bool {
let (code, domain) = channel;
match *self {
KeyProperty::Code(value) => code == value,
KeyProperty::Domain(value) => domain == value,
KeyProperty::VirtualType(value) => value.ev_type() == code.ev_type(),
KeyProperty::Namespace(_)
| KeyProperty::Value(_)
| KeyProperty::PreviousValue(_)
| KeyProperty::AbsoluteFactor(_)
| KeyProperty::DeltaFactor(_) => true,
}
}
pub fn merge(&self, mut event: Event) -> Event {
match *self {
KeyProperty::Code(value) => event.code = value,
KeyProperty::Domain(value) => event.domain = value,
KeyProperty::Namespace(value) => event.namespace = value,
KeyProperty::Value(range) => event.value = range.bound(event.value),
KeyProperty::PreviousValue(range) => {
event.previous_value = range.bound(event.previous_value)
}
KeyProperty::AbsoluteFactor(factor) => {
event.value = ((event.value as f64 * factor).trunc()) as i32;
}
KeyProperty::DeltaFactor(factor) => {
event.value = ((event.value as f64 * factor).floor()
- (event.previous_value as f64 * factor).floor())
as i32;
}
KeyProperty::VirtualType(_) => {
if cfg!(debug_assertions) {
panic!(
"Cannot change the event type of an event. Panicked during event mapping."
);
} else {
}
}
};
event
}
pub fn matches_cap(&self, cap: &Capability) -> CapMatch {
match *self {
KeyProperty::Code(value) => (cap.code == value).into(),
KeyProperty::Domain(value) => (cap.domain == value).into(),
KeyProperty::VirtualType(value) => (cap.code.virtual_ev_type() == value).into(),
KeyProperty::Namespace(value) => (cap.namespace == value).into(),
KeyProperty::Value(range) => {
if cap.value_range.is_subset_of(&range) {
CapMatch::Yes
} else if range.is_disjoint_with(&cap.value_range) {
CapMatch::No
} else {
CapMatch::Maybe
}
}
KeyProperty::PreviousValue(_range) => CapMatch::Maybe,
KeyProperty::AbsoluteFactor(_) | KeyProperty::DeltaFactor(_) => {
panic!(
"Internal invariant violated: cannot filter events based on relative values."
);
}
}
}
pub fn merge_cap(&self, mut cap: Capability) -> Capability {
match *self {
KeyProperty::Code(value) => cap.code = value,
KeyProperty::Domain(value) => cap.domain = value,
KeyProperty::Namespace(value) => cap.namespace = value,
KeyProperty::Value(range) => cap.value_range = range.bound_range(&cap.value_range),
KeyProperty::PreviousValue(_range) => {}
KeyProperty::AbsoluteFactor(factor) => {
let bound_1 = cap.value_range.max.mul_f64_round(factor, f64::trunc);
let bound_2 = cap.value_range.min.mul_f64_round(factor, f64::trunc);
let max = std::cmp::max(bound_1, bound_2);
let min = std::cmp::min(bound_1, bound_2);
cap.value_range = Range { max, min };
}
KeyProperty::DeltaFactor(factor) => {
let bound_1 = cap.value_range.max.mul_f64_round(factor, f64::floor);
let bound_2 = cap.value_range.min.mul_f64_round(factor, f64::floor);
let max = std::cmp::max(bound_1, bound_2);
let min = std::cmp::min(bound_1, bound_2);
cap.value_range = Range { max, min };
}
KeyProperty::VirtualType(_) => {
if cfg!(debug_assertions) {
panic!("Cannot change the event type of an event. Panicked during capability propagation.");
} else {
utils::warn_once("Internal error: cannot change the event type of an event. If you see this message, this is a bug.");
}
}
};
cap
}
}
#[allow(non_snake_case)]
pub struct KeyParser<'a> {
pub default_value: &'a str,
pub allow_values: bool,
pub allow_transitions: bool,
pub allow_ranges: bool,
pub allow_types: bool,
pub allow_relative_values: bool,
pub forbid_non_EV_KEY: bool,
pub namespace: Namespace,
}
impl<'a> KeyParser<'a> {
pub fn default_filter() -> KeyParser<'static> {
KeyParser {
default_value: "",
allow_values: true,
allow_ranges: true,
allow_transitions: true,
allow_types: true,
allow_relative_values: false,
forbid_non_EV_KEY: false,
namespace: Namespace::User,
}
}
pub fn default_mask() -> KeyParser<'static> {
KeyParser {
default_value: "",
allow_values: true,
allow_ranges: false,
allow_transitions: false,
allow_types: false,
allow_relative_values: true,
forbid_non_EV_KEY: false,
namespace: Namespace::User,
}
}
pub fn pure() -> KeyParser<'static> {
KeyParser {
default_value: "",
allow_values: false,
allow_ranges: false,
allow_transitions: false,
allow_types: true,
allow_relative_values: false,
forbid_non_EV_KEY: false,
namespace: Namespace::User,
}
}
pub fn with_namespace(&mut self, namespace: Namespace) -> &mut Self {
self.namespace = namespace;
self
}
pub fn parse(&self, key_str: &str) -> Result<Key, ArgumentError> {
interpret_key_with_domain(key_str, self)
.with_context(format!("While parsing the key \"{}\":", key_str))
}
pub fn parse_all(&self, key_strs: &[String]) -> Result<Vec<Key>, ArgumentError> {
key_strs.iter().map(|key| self.parse(key)).collect()
}
}
pub fn resembles_key(key_str: &str) -> bool {
if key_str.starts_with('/') {
false
} else {
KeyParser {
default_value: "",
allow_values: true,
allow_ranges: true,
allow_transitions: true,
allow_types: true,
allow_relative_values: true,
forbid_non_EV_KEY: false,
namespace: Namespace::User,
}.parse(key_str).is_ok()
|| utils::split_once(key_str, "=").0.contains(':')
|| utils::split_once(key_str, "=").0.contains('@')
}
}
fn interpret_key_with_domain(key_str: &str, parser: &KeyParser) -> Result<Key, ArgumentError> {
let (event_str, domain_str_opt) = utils::split_once(key_str, "@");
let mut key = interpret_key(event_str, parser)?;
if let Some(domain_str) = domain_str_opt {
let domain = domain::resolve(domain_str)?;
key.properties.push(KeyProperty::Domain(domain));
}
Ok(key)
}
fn interpret_key(key_str: &str, parser: &KeyParser) -> Result<Key, ArgumentError> {
let mut key = Key::new();
key.add_property(KeyProperty::Namespace(parser.namespace));
if key_str == "" {
return Ok(key);
}
let mut parts = key_str.split(':');
let event_type_name = parts.next().unwrap();
let event_type = ecodes::event_type(event_type_name).ok_or_else(||
match event_type_name {
"" => ArgumentError::new("Cannot specify event code or value without specifying event type."),
_ => ArgumentError::new(format!(
"Unknown event type \"{}\".", event_type_name
)),
}
)?;
if event_type.is_syn() {
return Err(ArgumentError::new("Cannot use event type \"syn\": it is impossible to manipulate synchronisation events because synchronisation is automatically taken care of by evsieve."));
}
if parser.forbid_non_EV_KEY && event_type != EventType::KEY {
return Err(ArgumentError::new(
"Only events of type EV_KEY (i.e. \"key:something\" or \"btn:something\") can be specified in this position."
));
}
match parts.next() {
None | Some("") => {
if !parser.allow_types {
return Err(ArgumentError::new(format!(
"No event code provided for the key \"{}\".",
key_str
)));
}
let virtual_type = match event_type_name {
VirtualEventType::KEY => VirtualEventType::Key,
VirtualEventType::BUTTON => VirtualEventType::Button,
_ => VirtualEventType::Other(event_type),
};
key.add_property(KeyProperty::VirtualType(virtual_type));
}
Some(event_code_name) => {
let event_code =
ecodes::event_code(event_type_name, event_code_name).ok_or_else(|| {
ArgumentError::new(format!("Unknown event code \"{}\".", event_code_name))
})?;
key.add_property(KeyProperty::Code(event_code));
if ecodes::is_abs_mt(event_code) {
utils::warn_once("Warning: it seems you're trying to manipulate ABS_MT events. Keep in mind that evsieve's support for ABS_MT is considered unstable. Evsieve's behaviour with respect to ABS_MT events is subject to change in the future.");
}
}
};
let event_value_str = match parts.next() {
Some(value) => {
if parser.allow_values {
value
} else {
return Err(ArgumentError::new(format!(
"This argument does not allow you to specify values for its events. Try removing the \":{}\" part.",
value
)));
}
}
None => match parser.default_value {
"" => return Ok(key),
_ => &parser.default_value,
},
};
if let Some(property) = interpret_relative_value(event_value_str)? {
if parser.allow_relative_values {
key.add_property(property);
return Ok(key);
} else {
return Err(ArgumentError::new(format!(
"It is not possible to specify relative values for the key {}.",
key_str,
)));
}
}
let (val_1, val_2) = utils::split_once(event_value_str, "..");
let (previous_value_str_opt, current_value_str) = match val_2 {
Some(val) => (Some(val_1), val),
None => (None, val_1),
};
let current_value = interpret_event_value(current_value_str, parser)?;
key.add_property(KeyProperty::Value(current_value));
if let Some(previous_value_str) = previous_value_str_opt {
if !parser.allow_transitions {
return Err(ArgumentError::new(
"No transitions are allowed for keys in this position.",
));
}
let previous_value = interpret_event_value(previous_value_str, parser)?;
key.add_property(KeyProperty::PreviousValue(previous_value));
}
Ok(key)
}
fn interpret_event_value(value_str: &str, parser: &KeyParser) -> Result<Range, ArgumentError> {
if !parser.allow_ranges && value_str.contains('~') {
return Err(ArgumentError::new(format!(
"No ranges are allowed in the value \"{}\".",
value_str
)));
}
let (min_value_str, max_value_str_opt) = utils::split_once(value_str, "~");
let max_value_str = max_value_str_opt.unwrap_or(min_value_str);
let min = parse_int_or_wildcard(min_value_str)?;
let max = parse_int_or_wildcard(max_value_str)?;
if let (Some(min_value), Some(max_value)) = (min, max) {
if min_value > max_value {
return Err(ArgumentError::new(format!(
"The upper bound of a value range may not be smaller than its lower bound. Did you intend to use the range {}~{} instead?", max_value, min_value
)));
}
}
Ok(Range::new(min, max))
}
fn parse_int_or_wildcard(value_str: &str) -> Result<Option<i32>, ArgumentError> {
if value_str == "" {
Ok(None)
} else {
let value: i32 = value_str.parse().map_err(|err| {
ArgumentError::new(format!(
"Cannot interpret {} as an integer: {}.",
value_str, err
))
})?;
Ok(Some(value))
}
}
fn interpret_relative_value(value_str: &str) -> Result<Option<KeyProperty>, ArgumentError> {
let suffix_to_type: [(&str, &dyn Fn(f64) -> KeyProperty); 2] = [
("x", &KeyProperty::AbsoluteFactor),
("d", &KeyProperty::DeltaFactor),
];
for (suffix, property) in suffix_to_type {
match utils::strip_suffix(value_str, suffix) {
None => continue,
Some(factor_str) => {
let factor = match utils::parse_number(factor_str) {
Some(factor) => factor,
None => {
return Err(ArgumentError::new(format!(
"Cannot interpret {} as a float.",
factor_str
)))
}
};
return Ok(Some(property(factor)));
}
}
}
Ok(None)
}
#[test]
fn unittest_intersection() {
let parser = KeyParser::default_filter();
let expected_to_intersect = [
("key:a", "key:a"),
("key", "key:a"),
("key:a", "key"),
("key:a:1..2@foo", "key:a:1..2@foo"),
("key:a:1..2@foo", "@foo"),
("", ""),
("", "key:a:1..2@foo"),
];
let expected_not_to_intersect = [
("key:a", "key:b"),
("key:a", "btn"),
("btn", "key:a"),
("key:a@foo", "key:a@bar"),
("key:a@foo", "@bar"),
("key:a:1", "key:a:2"),
("key:a:1..2", "key:a:0..2"),
];
for (key_1, key_2) in expected_to_intersect {
assert!(parser
.parse(key_1)
.unwrap()
.intersects_with(&parser.parse(key_2).unwrap()));
}
for (key_1, key_2) in expected_not_to_intersect {
assert!(!parser
.parse(key_1)
.unwrap()
.intersects_with(&parser.parse(key_2).unwrap()));
}
}