|
|
@ -31,6 +31,9 @@ struct Opts {
|
|
|
|
/// Ignore a device name or path
|
|
|
|
/// Ignore a device name or path
|
|
|
|
#[clap(long, use_delimiter = true)]
|
|
|
|
#[clap(long, use_delimiter = true)]
|
|
|
|
ignore: Vec<String>,
|
|
|
|
ignore: Vec<String>,
|
|
|
|
|
|
|
|
/// Match mice by default
|
|
|
|
|
|
|
|
#[clap(long)]
|
|
|
|
|
|
|
|
mouse: bool,
|
|
|
|
/// Targets to watch
|
|
|
|
/// Targets to watch
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// - device: add new devices automatically
|
|
|
|
/// - device: add new devices automatically
|
|
|
@ -80,6 +83,7 @@ fn main() -> anyhow::Result<()> {
|
|
|
|
let Opts {
|
|
|
|
let Opts {
|
|
|
|
device: device_filter,
|
|
|
|
device: device_filter,
|
|
|
|
ignore: ignore_filter,
|
|
|
|
ignore: ignore_filter,
|
|
|
|
|
|
|
|
mouse,
|
|
|
|
watch,
|
|
|
|
watch,
|
|
|
|
config,
|
|
|
|
config,
|
|
|
|
completions,
|
|
|
|
completions,
|
|
|
@ -107,7 +111,7 @@ fn main() -> anyhow::Result<()> {
|
|
|
|
let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty())?;
|
|
|
|
let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty())?;
|
|
|
|
let timer_fd = timer.as_raw_fd();
|
|
|
|
let timer_fd = timer.as_raw_fd();
|
|
|
|
let mut handler = EventHandler::new(output_device, timer, &config.default_mode);
|
|
|
|
let mut handler = EventHandler::new(output_device, timer, &config.default_mode);
|
|
|
|
let mut input_devices = match get_input_devices(&device_filter, &ignore_filter, watch_devices) {
|
|
|
|
let mut input_devices = match get_input_devices(&device_filter, &ignore_filter, mouse, watch_devices) {
|
|
|
|
Ok(input_devices) => input_devices,
|
|
|
|
Ok(input_devices) => input_devices,
|
|
|
|
Err(e) => bail!("Failed to prepare input devices: {}", e),
|
|
|
|
Err(e) => bail!("Failed to prepare input devices: {}", e),
|
|
|
|
};
|
|
|
|
};
|
|
|
@ -136,13 +140,19 @@ fn main() -> anyhow::Result<()> {
|
|
|
|
|
|
|
|
|
|
|
|
if let Some(inotify) = device_watcher {
|
|
|
|
if let Some(inotify) = device_watcher {
|
|
|
|
if let Ok(events) = inotify.read_events() {
|
|
|
|
if let Ok(events) = inotify.read_events() {
|
|
|
|
handle_device_changes(events, &mut input_devices, &device_filter, &ignore_filter)?;
|
|
|
|
handle_device_changes(events, &mut input_devices, &device_filter, &ignore_filter, mouse)?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if let Some(inotify) = config_watcher {
|
|
|
|
if let Some(inotify) = config_watcher {
|
|
|
|
if let Ok(events) = inotify.read_events() {
|
|
|
|
if let Ok(events) = inotify.read_events() {
|
|
|
|
if !handle_config_changes(events, &mut input_devices, &device_filter, &ignore_filter, &config_path)?
|
|
|
|
if !handle_config_changes(
|
|
|
|
{
|
|
|
|
events,
|
|
|
|
|
|
|
|
&mut input_devices,
|
|
|
|
|
|
|
|
&device_filter,
|
|
|
|
|
|
|
|
&ignore_filter,
|
|
|
|
|
|
|
|
mouse,
|
|
|
|
|
|
|
|
&config_path,
|
|
|
|
|
|
|
|
)? {
|
|
|
|
break 'event_loop Event::ReloadConfig;
|
|
|
|
break 'event_loop Event::ReloadConfig;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -152,7 +162,7 @@ fn main() -> anyhow::Result<()> {
|
|
|
|
for input_device in input_devices.values_mut() {
|
|
|
|
for input_device in input_devices.values_mut() {
|
|
|
|
input_device.ungrab();
|
|
|
|
input_device.ungrab();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
input_devices = match get_input_devices(&device_filter, &ignore_filter, watch_devices) {
|
|
|
|
input_devices = match get_input_devices(&device_filter, &ignore_filter, mouse, watch_devices) {
|
|
|
|
Ok(input_devices) => input_devices,
|
|
|
|
Ok(input_devices) => input_devices,
|
|
|
|
Err(e) => bail!("Failed to prepare input devices: {}", e),
|
|
|
|
Err(e) => bail!("Failed to prepare input devices: {}", e),
|
|
|
|
};
|
|
|
|
};
|
|
|
@ -217,12 +227,13 @@ fn handle_device_changes(
|
|
|
|
input_devices: &mut HashMap<PathBuf, InputDevice>,
|
|
|
|
input_devices: &mut HashMap<PathBuf, InputDevice>,
|
|
|
|
device_filter: &[String],
|
|
|
|
device_filter: &[String],
|
|
|
|
ignore_filter: &[String],
|
|
|
|
ignore_filter: &[String],
|
|
|
|
|
|
|
|
mouse: bool,
|
|
|
|
) -> anyhow::Result<()> {
|
|
|
|
) -> anyhow::Result<()> {
|
|
|
|
input_devices.extend(events.into_iter().filter_map(|event| {
|
|
|
|
input_devices.extend(events.into_iter().filter_map(|event| {
|
|
|
|
event.name.and_then(|name| {
|
|
|
|
event.name.and_then(|name| {
|
|
|
|
let path = PathBuf::from("/dev/input/").join(name);
|
|
|
|
let path = PathBuf::from("/dev/input/").join(name);
|
|
|
|
let mut device = InputDevice::try_from(path).ok()?;
|
|
|
|
let mut device = InputDevice::try_from(path).ok()?;
|
|
|
|
if device.is_input_device(device_filter, &ignore_filter) && device.grab() {
|
|
|
|
if device.is_input_device(device_filter, &ignore_filter, mouse) && device.grab() {
|
|
|
|
device.print();
|
|
|
|
device.print();
|
|
|
|
Some(device.into())
|
|
|
|
Some(device.into())
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -238,6 +249,7 @@ fn handle_config_changes(
|
|
|
|
input_devices: &mut HashMap<PathBuf, InputDevice>,
|
|
|
|
input_devices: &mut HashMap<PathBuf, InputDevice>,
|
|
|
|
device_filter: &[String],
|
|
|
|
device_filter: &[String],
|
|
|
|
ignore_filter: &[String],
|
|
|
|
ignore_filter: &[String],
|
|
|
|
|
|
|
|
mouse: bool,
|
|
|
|
config_path: &PathBuf,
|
|
|
|
config_path: &PathBuf,
|
|
|
|
) -> anyhow::Result<bool> {
|
|
|
|
) -> anyhow::Result<bool> {
|
|
|
|
for event in &events {
|
|
|
|
for event in &events {
|
|
|
@ -256,7 +268,7 @@ fn handle_config_changes(
|
|
|
|
event.name.and_then(|name| {
|
|
|
|
event.name.and_then(|name| {
|
|
|
|
let path = PathBuf::from("/dev/input/").join(name);
|
|
|
|
let path = PathBuf::from("/dev/input/").join(name);
|
|
|
|
let mut device = InputDevice::try_from(path).ok()?;
|
|
|
|
let mut device = InputDevice::try_from(path).ok()?;
|
|
|
|
if device.is_input_device(&device_filter, &ignore_filter) && device.grab() {
|
|
|
|
if device.is_input_device(&device_filter, &ignore_filter, mouse) && device.grab() {
|
|
|
|
device.print();
|
|
|
|
device.print();
|
|
|
|
Some(device.into())
|
|
|
|
Some(device.into())
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|