mirror of
https://github.com/k0kubun/xremap
synced 2024-11-02 03:40:25 +00:00
Implement launch action
This commit is contained in:
parent
a7e9b92bad
commit
dc5660754a
@ -1,10 +0,0 @@
|
||||
hotkeys:
|
||||
- name: hotkey_test
|
||||
keys:
|
||||
- KEY_GRAVE
|
||||
application:
|
||||
not: [Google-chrome, konsole]
|
||||
command:
|
||||
- "/bin/sh"
|
||||
- "-c"
|
||||
- "date > /tmp/hotkey_test"
|
@ -1,6 +1,6 @@
|
||||
use log::{debug, error};
|
||||
use std::process::{Command, Stdio};
|
||||
use std::thread;
|
||||
use log::{debug, error};
|
||||
|
||||
pub fn run_command(command: Vec<String>) {
|
||||
// To avoid defunct processes, spawn a thread to wait on the process.
|
||||
|
@ -12,6 +12,8 @@ pub enum Action {
|
||||
KeyPress(KeyPress),
|
||||
#[serde(deserialize_with = "deserialize_remap")]
|
||||
Remap(HashMap<KeyPress, Vec<Action>>),
|
||||
#[serde(deserialize_with = "deserialize_launch")]
|
||||
Launch(Vec<String>),
|
||||
}
|
||||
|
||||
fn deserialize_remap<'de, D>(deserializer: D) -> Result<HashMap<KeyPress, Vec<Action>>, D::Error>
|
||||
@ -27,6 +29,19 @@ where
|
||||
Err(de::Error::custom("not a map with a single \"remap\" key"))
|
||||
}
|
||||
|
||||
fn deserialize_launch<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let mut action = HashMap::<String, Vec<String>>::deserialize(deserializer)?;
|
||||
if let Some(launch) = action.remove("launch") {
|
||||
if action.is_empty() {
|
||||
return Ok(launch);
|
||||
}
|
||||
}
|
||||
Err(de::Error::custom("not a map with a single \"launch\" key"))
|
||||
}
|
||||
|
||||
// Used only for deserializing Vec<Action>
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
|
@ -1,13 +0,0 @@
|
||||
use crate::config::application::Application;
|
||||
use crate::config::key_press::KeyPress;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Hotkey {
|
||||
#[serde(default = "String::new")]
|
||||
pub name: String,
|
||||
pub keys: Vec<KeyPress>,
|
||||
pub command: Vec<String>,
|
||||
pub application: Option<Application>,
|
||||
}
|
@ -3,7 +3,6 @@ pub mod application;
|
||||
mod key;
|
||||
pub mod key_action;
|
||||
pub mod key_press;
|
||||
mod hotkey;
|
||||
mod keymap;
|
||||
mod modmap;
|
||||
|
||||
@ -14,7 +13,6 @@ extern crate serde_yaml;
|
||||
|
||||
use keymap::Keymap;
|
||||
use modmap::Modmap;
|
||||
use hotkey::Hotkey;
|
||||
use serde::Deserialize;
|
||||
use std::{error, fs};
|
||||
|
||||
@ -25,8 +23,6 @@ pub struct Config {
|
||||
pub modmap: Vec<Modmap>,
|
||||
#[serde(default = "Vec::new")]
|
||||
pub keymap: Vec<Keymap>,
|
||||
#[serde(default = "Vec::new")]
|
||||
pub hotkeys: Vec<Hotkey>,
|
||||
}
|
||||
|
||||
pub fn load_config(filename: &str) -> Result<Config, Box<dyn error::Error>> {
|
||||
|
@ -101,6 +101,19 @@ fn test_keymap_remap() {
|
||||
"})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keymap_launch() {
|
||||
assert_parse(indoc! {"
|
||||
keymap:
|
||||
- remap:
|
||||
KEY_GRAVE:
|
||||
launch:
|
||||
- '/bin/sh'
|
||||
- '-c'
|
||||
- 'date > /tmp/hotkey_test'
|
||||
"})
|
||||
}
|
||||
|
||||
fn assert_parse(yaml: &str) {
|
||||
let result: Result<Config, Error> = serde_yaml::from_str(&yaml);
|
||||
if let Err(e) = result {
|
||||
|
@ -58,13 +58,9 @@ impl EventHandler {
|
||||
|
||||
// Apply keymap
|
||||
for (key, value) in key_values.into_iter() {
|
||||
let key_press = self.key_to_key_press(&key);
|
||||
// Run hotkey commands
|
||||
if self.handle_hotkey(&key_press, value, &config) {
|
||||
return Ok(());
|
||||
} else if MODIFIER_KEYS.contains(&key.code()) {
|
||||
if MODIFIER_KEYS.contains(&key.code()) {
|
||||
self.update_modifier(key.code(), value);
|
||||
} else if let Some(actions) = self.find_keymap(config, &key_press, value) {
|
||||
} else if let Some(actions) = self.find_keymap(config, &key, value) {
|
||||
for action in &actions {
|
||||
self.dispatch_action(action)?;
|
||||
}
|
||||
@ -75,25 +71,6 @@ impl EventHandler {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_hotkey(&mut self, key_press: &KeyPress, value: i32, config: &Config) -> bool {
|
||||
let mut hotkey_used = false;
|
||||
'outer_hotkey: for hotkey in &config.hotkeys {
|
||||
for hotkey_key_press in &hotkey.keys {
|
||||
if hotkey_key_press == key_press && is_pressed(value) {
|
||||
if let Some(app) = &hotkey.application {
|
||||
if !self.match_application(app) {
|
||||
continue 'outer_hotkey;
|
||||
}
|
||||
}
|
||||
run_command(hotkey.command.clone());
|
||||
hotkey_used = true;
|
||||
break 'outer_hotkey;
|
||||
}
|
||||
}
|
||||
}
|
||||
return hotkey_used;
|
||||
}
|
||||
|
||||
pub fn send_event(&mut self, event: InputEvent) -> std::io::Result<()> {
|
||||
if event.event_type() == EventType::KEY {
|
||||
debug!("{}: {:?}", event.value(), Key::new(event.code()))
|
||||
@ -172,21 +149,18 @@ impl EventHandler {
|
||||
None
|
||||
}
|
||||
|
||||
fn key_to_key_press(&mut self, key: &Key) -> KeyPress {
|
||||
KeyPress {
|
||||
fn find_keymap(&mut self, config: &Config, key: &Key, value: i32) -> Option<Vec<Action>> {
|
||||
if !is_pressed(value) {
|
||||
return None;
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
fn find_keymap(&mut self, config: &Config, key_press: &KeyPress, value: i32) -> Option<Vec<Action>> {
|
||||
if !is_pressed(value) {
|
||||
return None;
|
||||
}
|
||||
|
||||
};
|
||||
if let Some(override_remap) = &self.override_remap {
|
||||
let override_remap = override_remap.clone();
|
||||
self.override_remap = None;
|
||||
@ -235,6 +209,7 @@ impl EventHandler {
|
||||
}
|
||||
self.override_remap = Some(override_remap)
|
||||
}
|
||||
Action::Launch(command) => run_command(command.clone()),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user