Skip to content

Commit

Permalink
feat: add toggle action for fake keys (#538)
Browse files Browse the repository at this point in the history
  • Loading branch information
jtroo committed Aug 20, 2023
1 parent c6fa1eb commit a0d8207
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 25 deletions.
1 change: 1 addition & 0 deletions cfg_samples/kanata.kbd
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,7 @@ If you need help, you are welcome to ask.
fsp (on-release-fakekey sft press)
fsr (on-release-fakekey sft release)
fst (on-release-fakekey sft tap)
fsg (on-release-fakekey sft toggle)
fmp (on-press-fakekey met press)
fap (on-press-fakekey alt press)
rma (multi
Expand Down
1 change: 1 addition & 0 deletions docs/config.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1761,6 +1761,7 @@ The aforementioned `+<key action>+` can be one of three values:
triggers a release or tap.
* `+release+`: Release the fake key. If it's not already pressed, this does nothing.
* `+tap+`: Press and release the fake key. If it's already pressed, this only releases it.
* `+toggle+`: Press the fake key if not already pressed, otherwise release it.

Expanding on the `on-idle-fakekey` action some more,
the wording that "kanata" has been idle is important.
Expand Down
3 changes: 2 additions & 1 deletion parser/src/cfg/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2238,7 +2238,7 @@ fn parse_fake_key_op_coord_action(
s: &ParsedState,
) -> Result<(Coord, FakeKeyAction)> {
const ERR_MSG: &str =
"on-(press|release)-fakekey expects two parameters: <fake key name> <(tap|press|release)>";
"on-(press|release)-fakekey expects two parameters: <fake key name> <(tap|press|release|toggle)>";
if ac_params.len() != 2 {
bail!("{ERR_MSG}");
}
Expand All @@ -2261,6 +2261,7 @@ fn parse_fake_key_op_coord_action(
"tap" => Some(FakeKeyAction::Tap),
"press" => Some(FakeKeyAction::Press),
"release" => Some(FakeKeyAction::Release),
"toggle" => Some(FakeKeyAction::Toggle),
_ => None,
})
.flatten()
Expand Down
1 change: 1 addition & 0 deletions parser/src/custom_action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ pub enum FakeKeyAction {
Press,
Release,
Tap,
Toggle,
}

/// An active waiting-for-idle state.
Expand Down
61 changes: 37 additions & 24 deletions src/kanata/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -605,14 +605,7 @@ impl Kanata {
// Process this and return false so that it is not retained.
let layout = self.layout.bm();
let Coord { x, y } = wfd.coord;
match wfd.action {
FakeKeyAction::Press => layout.event(Event::Press(x, y)),
FakeKeyAction::Release => layout.event(Event::Release(x, y)),
FakeKeyAction::Tap => {
layout.event(Event::Press(x, y));
layout.event(Event::Release(x, y));
}
};
handle_fakekey_action(wfd.action, layout, x, y);
false
} else {
true
Expand Down Expand Up @@ -991,14 +984,7 @@ impl Kanata {
layout.default_layer,
layout.layers[layout.default_layer][x as usize][y as usize]
);
match action {
FakeKeyAction::Press => layout.event(Event::Press(x, y)),
FakeKeyAction::Release => layout.event(Event::Release(x, y)),
FakeKeyAction::Tap => {
layout.event(Event::Press(x, y));
layout.event(Event::Release(x, y));
}
}
handle_fakekey_action(*action, layout, x, y);
}
CustomAction::Delay(delay) => {
log::debug!("on-press: sleeping for {delay} ms");
Expand Down Expand Up @@ -1263,14 +1249,7 @@ impl Kanata {
CustomAction::FakeKeyOnRelease { coord, action } => {
let (x, y) = (coord.x, coord.y);
log::debug!("fake key on release {action:?} {x:?},{y:?}");
match action {
FakeKeyAction::Press => layout.event(Event::Press(x, y)),
FakeKeyAction::Release => layout.event(Event::Release(x, y)),
FakeKeyAction::Tap => {
layout.event(Event::Press(x, y));
layout.event(Event::Release(x, y));
}
}
handle_fakekey_action(*action, layout, x, y);
pbtn
}
CustomAction::CancelMacroOnRelease => {
Expand Down Expand Up @@ -1785,3 +1764,37 @@ fn cancel_sequence(state: &SequenceState, kbd_out: &mut KbdOut) -> Result<()> {
}
Ok(())
}

fn handle_fakekey_action<'a, const C: usize, const R: usize, const L: usize, T>(
action: FakeKeyAction,
layout: &mut Layout<'a, C, R, L, T>,
x: u8,
y: u16,
) where
T: 'a + std::fmt::Debug + Copy,
{
match action {
FakeKeyAction::Press => layout.event(Event::Press(x, y)),
FakeKeyAction::Release => layout.event(Event::Release(x, y)),
FakeKeyAction::Tap => {
layout.event(Event::Press(x, y));
layout.event(Event::Release(x, y));
}
FakeKeyAction::Toggle => {
match states_has_coord(&layout.states, x, y) {
true => layout.event(Event::Release(x, y)),
false => layout.event(Event::Press(x, y)),
};
}
};
}

fn states_has_coord<T>(states: &[State<T>], x: u8, y: u16) -> bool {
states.iter().any(|s| match s {
State::NormalKey { coord, .. }
| State::LayerModifier { coord, .. }
| State::Custom { coord, .. }
| State::RepeatingSequence { coord, .. } => *coord == (x, y),
_ => false,
})
}

0 comments on commit a0d8207

Please sign in to comment.