config: allow handling switch events
This commit is contained in:
parent
55d55bf161
commit
cf233abb5a
21 changed files with 443 additions and 27 deletions
|
|
@ -15,8 +15,9 @@ use {
|
|||
},
|
||||
toml::{self},
|
||||
},
|
||||
ahash::AHashMap,
|
||||
jay_config::{
|
||||
input::acceleration::AccelProfile,
|
||||
input::{acceleration::AccelProfile, SwitchEvent},
|
||||
keyboard::{mods::Modifiers, Keymap, ModifiedKeySym},
|
||||
logging::LogLevel,
|
||||
status::MessageFormat,
|
||||
|
|
@ -244,6 +245,7 @@ pub struct Input {
|
|||
pub px_per_wheel_scroll: Option<f64>,
|
||||
pub transform_matrix: Option<[[f64; 2]; 2]>,
|
||||
pub keymap: Option<ConfigKeymap>,
|
||||
pub switch_actions: AHashMap<SwitchEvent, Action>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use {
|
|||
extractor::{bol, fltorint, opt, recover, str, val, Extractor, ExtractorError},
|
||||
parser::{DataType, ParseResult, Parser, UnexpectedDataType},
|
||||
parsers::{
|
||||
action::ActionParser,
|
||||
input_match::{InputMatchParser, InputMatchParserError},
|
||||
keymap::KeymapParser,
|
||||
},
|
||||
|
|
@ -15,8 +16,12 @@ use {
|
|||
toml_value::Value,
|
||||
},
|
||||
},
|
||||
ahash::AHashMap,
|
||||
indexmap::IndexMap,
|
||||
jay_config::input::acceleration::{ACCEL_PROFILE_ADAPTIVE, ACCEL_PROFILE_FLAT},
|
||||
jay_config::input::{
|
||||
acceleration::{ACCEL_PROFILE_ADAPTIVE, ACCEL_PROFILE_FLAT},
|
||||
SwitchEvent,
|
||||
},
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
|
|
@ -65,7 +70,14 @@ impl<'a> Parser for InputParser<'a> {
|
|||
natural_scrolling,
|
||||
px_per_wheel_scroll,
|
||||
),
|
||||
(transform_matrix, keymap),
|
||||
(
|
||||
transform_matrix,
|
||||
keymap,
|
||||
on_lid_opened_val,
|
||||
on_lid_closed_val,
|
||||
on_converted_to_laptop_val,
|
||||
on_converted_to_tablet_val,
|
||||
),
|
||||
) = ext.extract((
|
||||
(
|
||||
opt(str("tag")),
|
||||
|
|
@ -79,7 +91,14 @@ impl<'a> Parser for InputParser<'a> {
|
|||
recover(opt(bol("natural-scrolling"))),
|
||||
recover(opt(fltorint("px-per-wheel-scroll"))),
|
||||
),
|
||||
(recover(opt(val("transform-matrix"))), opt(val("keymap"))),
|
||||
(
|
||||
recover(opt(val("transform-matrix"))),
|
||||
opt(val("keymap")),
|
||||
opt(val("on-lid-opened")),
|
||||
opt(val("on-lid-closed")),
|
||||
opt(val("on-converted-to-laptop")),
|
||||
opt(val("on-converted-to-tablet")),
|
||||
),
|
||||
))?;
|
||||
let accel_profile = match accel_profile {
|
||||
None => None,
|
||||
|
|
@ -125,6 +144,38 @@ impl<'a> Parser for InputParser<'a> {
|
|||
}
|
||||
},
|
||||
};
|
||||
let mut switch_actions = AHashMap::new();
|
||||
let mut parse_action = |val: Option<Spanned<&Value>>, name, event| {
|
||||
if let Some(val) = val {
|
||||
if !self.tag_ok {
|
||||
log::warn!(
|
||||
"{name} has no effect in this position: {}",
|
||||
self.cx.error3(val.span)
|
||||
);
|
||||
return;
|
||||
}
|
||||
match val.parse(&mut ActionParser(self.cx)) {
|
||||
Ok(a) => {
|
||||
switch_actions.insert(event, a);
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("Could not parse {name} action: {}", self.cx.error(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
parse_action(on_lid_opened_val, "on-lid-opened", SwitchEvent::LidOpened);
|
||||
parse_action(on_lid_closed_val, "on-lid-closed", SwitchEvent::LidClosed);
|
||||
parse_action(
|
||||
on_converted_to_laptop_val,
|
||||
"on-converted-to-laptop",
|
||||
SwitchEvent::ConvertedToLaptop,
|
||||
);
|
||||
parse_action(
|
||||
on_converted_to_tablet_val,
|
||||
"on-converted-to-tablet",
|
||||
SwitchEvent::ConvertedToTablet,
|
||||
);
|
||||
Ok(Input {
|
||||
tag: tag.despan_into(),
|
||||
match_: match_val.parse_map(&mut InputMatchParser(self.cx))?,
|
||||
|
|
@ -138,6 +189,7 @@ impl<'a> Parser for InputParser<'a> {
|
|||
px_per_wheel_scroll: px_per_wheel_scroll.despan(),
|
||||
transform_matrix,
|
||||
keymap,
|
||||
switch_actions,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ use {
|
|||
exec::{set_env, unset_env, Command},
|
||||
get_workspace,
|
||||
input::{
|
||||
get_seat, input_devices, on_new_input_device, FocusFollowsMouseMode, InputDevice, Seat,
|
||||
capability::CAP_SWITCH, get_seat, input_devices, on_new_input_device,
|
||||
FocusFollowsMouseMode, InputDevice, Seat, SwitchEvent,
|
||||
},
|
||||
is_reload,
|
||||
keyboard::{Keymap, ModifiedKeySym},
|
||||
|
|
@ -559,6 +560,8 @@ impl Drop for State {
|
|||
}
|
||||
}
|
||||
|
||||
type SwitchActions = Vec<(InputMatch, AHashMap<SwitchEvent, Box<dyn Fn()>>)>;
|
||||
|
||||
impl State {
|
||||
fn unbind_all(&self) {
|
||||
let mut binds = self.persistent.binds.borrow_mut();
|
||||
|
|
@ -681,6 +684,23 @@ impl State {
|
|||
set_font(font);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_switch_device(self: &Rc<Self>, dev: InputDevice, actions: &Rc<SwitchActions>) {
|
||||
if !dev.has_capability(CAP_SWITCH) {
|
||||
return;
|
||||
}
|
||||
let state = self.clone();
|
||||
let actions = actions.clone();
|
||||
dev.on_switch_event(move |ev| {
|
||||
for (match_, actions) in &*actions {
|
||||
if match_.matches(dev, &state) {
|
||||
if let Some(action) = actions.get(&ev) {
|
||||
action();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Hash)]
|
||||
|
|
@ -700,7 +720,7 @@ struct PersistentState {
|
|||
fn load_config(initial_load: bool, persistent: &Rc<PersistentState>) {
|
||||
let mut path = PathBuf::from(config_dir());
|
||||
path.push("config.toml");
|
||||
let config = match std::fs::read(&path) {
|
||||
let mut config = match std::fs::read(&path) {
|
||||
Ok(input) => match parse_config(&input, |e| {
|
||||
log::warn!("Error while parsing {}: {}", path.display(), Report::new(e))
|
||||
}) {
|
||||
|
|
@ -768,6 +788,17 @@ fn load_config(initial_load: bool, persistent: &Rc<PersistentState>) {
|
|||
keymaps,
|
||||
});
|
||||
state.set_status(&config.status);
|
||||
let mut switch_actions = vec![];
|
||||
for input in &mut config.inputs {
|
||||
let mut actions = AHashMap::new();
|
||||
for (event, action) in input.switch_actions.drain() {
|
||||
actions.insert(event, action.into_fn(&state));
|
||||
}
|
||||
if actions.len() > 0 {
|
||||
switch_actions.push((input.match_.clone(), actions));
|
||||
}
|
||||
}
|
||||
let switch_actions = Rc::new(switch_actions);
|
||||
match config.on_graphics_initialized {
|
||||
None => on_graphics_initialized(|| ()),
|
||||
Some(a) => on_graphics_initialized(a.into_fn(&state)),
|
||||
|
|
@ -863,14 +894,19 @@ fn load_config(initial_load: bool, persistent: &Rc<PersistentState>) {
|
|||
});
|
||||
on_new_input_device({
|
||||
let state = state.clone();
|
||||
let switch_actions = switch_actions.clone();
|
||||
move |c| {
|
||||
for input in &config.inputs {
|
||||
if input.match_.matches(c, &state) {
|
||||
input.apply(c, &state);
|
||||
}
|
||||
}
|
||||
state.handle_switch_device(c, &switch_actions);
|
||||
}
|
||||
});
|
||||
for c in jay_config::input::input_devices() {
|
||||
state.handle_switch_device(c, &switch_actions);
|
||||
}
|
||||
persistent
|
||||
.seat
|
||||
.set_focus_follows_mouse_mode(match config.focus_follows_mouse {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue