Skip to content

Commit

Permalink
Merge pull request #2 from d86leader/develop
Browse files Browse the repository at this point in the history
Release 1.1.0
  • Loading branch information
maurges authored Jun 19, 2022
2 parents 83ed7c1 + 8ec256a commit 7c853a1
Show file tree
Hide file tree
Showing 14 changed files with 378 additions and 99 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "wzmach"
version = "1.0.0"
version = "1.1.0"
edition = "2021"

[profile.release]
Expand Down
119 changes: 110 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,81 @@ You can then edit that config file to add or replace your gestures. After
editing this file you need to restart wzmach.

The default config provides description of top-level fields. Below I describe
the available gestures.
the available gestures and actions.

#### UinputAction

Send keyboard events when a gesture is executed. First, it presses all the
modifier keys in the order they appear. Then, it clicks (presses and depresses)
all the sequence keys one after another. After that, all modifier keys get
depressed in the reverse order.

// Example: start omni-completion in vim
UinputAction (

// These keys are pressed for all the duration of the action
modifiers: ["RightControl"],

// There keys are pressed one at a time
sequence: ["X", "O"],

)

#### ShellCommandAction

Run a command in the `sh` shell. All wildcards and special symbols get
interpreted like the shell always does.

// Example: toggle a scroll lock LED (works in X11 only)
CommandAction (
command: r#"
on=$(xset -q | grep 'Scroll Lock:' | cut -d ":" -f 7)
echo $on
if [ $on == "off" ]; then
xset led named "Scroll Lock"
else
xset -led named "Scroll Lock"
fi
"#,
),

The example above features a raw string literal. It's delimited by `r###"` and
`"###` with any number of `#` symbols, and any symbol can appear inside this
string. You can use raw string literals anywhere a string is expected in
config, but it's most useful with this and the next action.

#### CommandAction

Like `ShellCommandAction`, but skip the shell and invoke the command literally.
The difference between this and that is like a difference between `system` and
`execv`.

// Example: unclutter desktop in KDE
CommandAction (
// Path can be absolute (/usr/bin/qdbus-qt5) or just a command name. In
// the second case it's looked up in $PATH
path: "qdbus-qt5",
args: [
"org.kde.KWin",
"/KWin",
"unclutterDesktop",
],
// Actually this example doesn't work because of
// https://bugs.freedesktop.org/show_bug.cgi?id=52202
),

Note that you can use this instead of the previous action. In fact, this is
what you should do if you want your command to run in bash or zsh instead of
sh.

CommandAction (
path: "/usr/bin/env",
args: [
"bash",
"-c",
r##" your command goes here "##,
],
),

#### Swipe

Expand All @@ -79,16 +153,10 @@ Example configuration:

),

// The action to execute upon trigger. Currently only UinputAction is
// supported
// The action to execute upon trigger. Use UinputAction, CommandAction
// or ShellCommandAction here
action: UinputAction (

// List of keys to be pressed for the whole action, and released
// after
modifiers: ["RightControl"],

// List of keys to be pressed and released one after another, while
// the modifier keys are pressed
sequence: ["T"],
)
),
Expand Down Expand Up @@ -152,6 +220,36 @@ Example:
)
),

#### Rotate

Rotate is when you rotate your fingers in one direction around a "center of
mass" of all your fingers; like rotating a map on your phone. It is extremely
easy to confuse shears and rotations, so you probably don't want to create
triggers for both.

Example:

(
trigger: Rotate (

// Amount of fingers, from 2 to infinity in theory, and from 2 to
// 4 or 5 in practice. 3 fingers means two digits + 1 thumb
fingers: 2,

// Direction of the fingers' rotation: Clockwise or Anticlockwise
direction: Anticlockwise,

// Can this gesture be repeated multiple times without lifting the
// fingers? true or false
repeated: true,

),
action: UinputAction (
modifiers: ["RightControl"],
sequence: ["PageUp"],
)
)

#### Hold

Holding several digits on touchpad without movement. In practice it works like
Expand Down Expand Up @@ -209,3 +307,6 @@ future I want to give the ability to interpret scrolling events as gestures.

It's called [RON](https://github.com/ron-rs/ron) and no, although the idea for
it lies on the surface.

##### A line for vim whitespace detection
vim: ts=4 sw=4 sts=4
10 changes: 10 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[1.1.0 2022-06-19]
- Add rotation gesture
- Add any-command action
- Can now specify config file to use
- Rework how sequential gestures are counted
This fixes the problem with diagonal swipes triggering a lot of stuff
simultaneously
- Make other gestures reversible, not just cardinals
So now you can rotate in one direction, in other, and then in the first
direction again, without lifting your fingers
5 changes: 5 additions & 0 deletions config.ron
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
// your pinch
pinch_distance: 1.4,

// Angle to rotate your fingers to trigger a /rotate/ gesture. Measured in
// degrees, but depending on your touchpad driver might not correspond to
// real degrees of rotation, or might be accelerated.
rotation_distance: 60,

// Triggers that execute in any window in any display environment
global_triggers: [

Expand Down
15 changes: 15 additions & 0 deletions src/action.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
mod command_action;
mod uinput_action;

use thiserror::Error;

#[derive(Error, Debug)]
#[error("Failure executing action: {0}")]
pub struct ActionError(pub String);

pub trait Action {
fn execute(&mut self) -> Result<(), ActionError>;
}

pub use uinput_action::UinputAction;
pub use command_action::{CommandAction, ShellCommandAction};
73 changes: 73 additions & 0 deletions src/action/command_action.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use std::os::unix::prelude::CommandExt;

use super::{Action, ActionError};

pub struct CommandAction {
pub path: String,
pub args: Vec<String>,
}

pub struct ShellCommandAction {
pub command: String,
}

impl Action for CommandAction {
fn execute(&mut self) -> Result<(), ActionError> {
log::debug!("Execute command {} {:?}", self.path, self.args);

std::process::Command::new(&self.path)
.args(self.args.iter())
.stdin(std::process::Stdio::null())
.stdout(std::process::Stdio::inherit())
.stderr(std::process::Stdio::inherit())
.detach()?;
log::trace!("Spawned the command");

Ok(())
}
}

impl Action for ShellCommandAction {
fn execute(&mut self) -> Result<(), ActionError> {
log::debug!("Execute command {:?}", self.command);

std::process::Command::new("/bin/sh")
.arg("-c")
.arg(&self.command)
.stdout(std::process::Stdio::inherit())
.stderr(std::process::Stdio::inherit())
.detach()?;
log::trace!("Spawned the command");

Ok(())
}
}

/// Extension to be able to detach child processes without creating zombies
trait DetachExt {
fn detach(&mut self) -> std::io::Result<()>;
}
impl DetachExt for std::process::Command {
fn detach(&mut self) -> std::io::Result<()> {
// Safety: usual daemonization stuff. Parent exits immediately before
// exec, child goes on to exec what it wants
use nix::unistd::ForkResult;
unsafe {
self.pre_exec(|| {
match nix::unistd::fork().unwrap() {
ForkResult::Parent { child: _ } => std::process::exit(0),
ForkResult::Child => (),
}
Ok(())
})
}
.status()
.map(|_| ())
}
}

impl From<std::io::Error> for ActionError {
fn from(err: std::io::Error) -> ActionError {
ActionError(format!("{}", err))
}
}
22 changes: 7 additions & 15 deletions src/action_sink.rs → src/action/uinput_action.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
use thiserror::Error;
use super::{Action, ActionError};
use uinput::event::keyboard::Key;

#[derive(Error, Debug)]
#[error("Failure executing action: {0}")]
pub struct ActionError(pub String);

pub trait Action {
fn execute(&mut self) -> Result<(), ActionError>;
}

pub struct UinputAction {
pub device: std::rc::Rc<std::cell::RefCell<uinput::Device>>,
pub modifiers: Vec<Key>,
Expand All @@ -30,12 +22,6 @@ impl UinputAction {
}
}

impl From<uinput::Error> for ActionError {
fn from(err: uinput::Error) -> ActionError {
ActionError(format!("{}", err))
}
}

impl Action for UinputAction {
fn execute(&mut self) -> Result<(), ActionError> {
let mut device = self.device.borrow_mut();
Expand All @@ -53,3 +39,9 @@ impl Action for UinputAction {
Ok(())
}
}

impl From<uinput::Error> for ActionError {
fn from(err: uinput::Error) -> ActionError {
ActionError(format!("{}", err))
}
}
15 changes: 14 additions & 1 deletion src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,24 @@ pub enum Direction {
Right,
}


/// In means scale goes 1.0 -> 1.5
/// Out means scale goes 1.0 -> 0.5
#[derive(PartialEq, Eq, Debug, Clone, Copy, Deserialize)]
pub enum PinchDirection {
In,
Out,
}

#[derive(PartialEq, Eq, Debug, Clone, Copy, Deserialize)]
pub enum RotateDirection {
Clockwise,
Anticlockwise,
}


#[derive(PartialEq, Eq, Debug, Clone, Copy, Deserialize)]
pub enum AnyDirection {
Cardinal(Direction),
Pinch(PinchDirection),
Rotate(RotateDirection),
}
Loading

0 comments on commit 7c853a1

Please sign in to comment.