|
|
|
# OneShot
|
|
|
|
|
|
|
|
One-shots are a new kind of behaviour for your standard modifier and momentary
|
|
|
|
layer keys: instead of having to hold them while pressing other keys, they can
|
|
|
|
be tapped and released, and will remain active until any other key is pressed
|
|
|
|
subject to a time-out.
|
|
|
|
|
|
|
|
In short, they turn `Shift, A` into `Shift+A`, and `Fn, 1` to `Fn+1`. The main
|
|
|
|
advantage is that this allows us to place the modifiers and layer keys to
|
|
|
|
positions that would otherwise be awkward when chording. Nevertheless, they
|
|
|
|
still act as normal when held, that behaviour is not lost.
|
|
|
|
|
|
|
|
Furthermore, if a one-shot key is double-tapped ie tapped two times in quick
|
|
|
|
succession, it becomes sticky, and remains active until disabled with a third tap.
|
|
|
|
This can be useful when one needs to input a number of keys with the modifier or
|
|
|
|
layer active, and does not wish to hold the key down. If this "stickability"
|
|
|
|
feature is undesirable, it can be unset (and later again set) for individual
|
|
|
|
modifiers/layers. If stickability is unset, double-tapping a one-shot modifier
|
|
|
|
will just restart the timer.
|
|
|
|
|
|
|
|
To make multi-modifier, or multi-layer shortcuts possible, one-shot keys remain
|
|
|
|
active if another one-shot of the same type is tapped, so `Ctrl, Alt, b` becomes
|
|
|
|
`Ctrl+Alt+b`, and `L1, L2, c` is turned into `L1+L2+c`. Furthermore, modifiers
|
|
|
|
and other layer keys do not cancel the one-shot effect, either.
|
|
|
|
|
|
|
|
## Using One-Shot keys
|
|
|
|
|
|
|
|
To enter one-shot mode, tap _quickly_ on a one-shot key. The next
|
|
|
|
normal (non-one-shot) key you press will have the modifier applied,
|
|
|
|
and then the modifier will automatically turn off. If the Shift key is
|
|
|
|
a one-shot modifier, then hitting `Shift, a, b` will give you `Ab`,
|
|
|
|
_if you hit shift quickly._
|
|
|
|
|
|
|
|
Longish keypresses do not activate one-shot mode. If you press `Shift,
|
|
|
|
a, b`, as above, but hold the Shift key a bit longer, you'll get `ab`.
|
|
|
|
|
|
|
|
To enter sticky mode, _tap twice quickly_ on a one-shot key. The
|
|
|
|
modifier will now stay on until you press it again. Continuing the
|
|
|
|
`Shift` example, tapping `Shift, Shift` _quickly_ and then `a, b, c,
|
|
|
|
Shift, d, e, f` will give you `ABCdef`.
|
|
|
|
|
|
|
|
This can be a bit tricky; combining this plugin with
|
|
|
|
[LED-ActiveModColor](Kaleidoscope-LED-ActiveModColor.md) will help you
|
|
|
|
understand what state your one-shot is in; when a one-shot key is active, it
|
|
|
|
will have a yellow LED highlight; when sticky, a red highlight. When it is in a
|
|
|
|
"held" state, but will be deactivated when released like any non-one-shot key,
|
|
|
|
it will have a white highlight. (These colors are configurable.)
|
|
|
|
|
|
|
|
## Using the plugin
|
|
|
|
|
|
|
|
After adding one-shot keys to the keymap, all one needs to do, is enable the
|
|
|
|
plugin:
|
|
|
|
|
|
|
|
```c++
|
|
|
|
#include <Kaleidoscope.h>
|
|
|
|
#include <Kaleidoscope-OneShot.h>
|
|
|
|
|
|
|
|
// somewhere in the keymap...
|
|
|
|
OSM(LeftControl), OSL(_FN)
|
|
|
|
|
|
|
|
KALEIDOSCOPE_INIT_PLUGINS(OneShot);
|
|
|
|
|
|
|
|
void setup() {
|
|
|
|
Kaleidoscope.setup();
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
## Keymap markup
|
|
|
|
|
|
|
|
There are two macros the plugin provides:
|
|
|
|
|
|
|
|
#### `OSM(mod)`
|
|
|
|
|
|
|
|
> A macro that takes a single argument, the name of the modifier: `LeftControl`,
|
|
|
|
> `LeftShift`, `LeftAlt`, `LeftGui` or their right-side variant. When marked up
|
|
|
|
> with this macro, the modifier will act as a one-shot modifier.
|
|
|
|
|
|
|
|
#### `OSL(layer)`
|
|
|
|
|
|
|
|
> Takes a layer number as argument, and sets up the key to act as a one-shot
|
|
|
|
> layer key.
|
|
|
|
>
|
|
|
|
> Please note that while `Kaleidoscope` supports more, one-shot layers are
|
|
|
|
> limited to 8 layers only.
|
|
|
|
|
|
|
|
In addition, there is a special key:
|
|
|
|
|
|
|
|
#### `Key_MetaSticky`
|
|
|
|
|
|
|
|
> A key that behaves like a one-shot key, but while active, it makes
|
|
|
|
> other keys that are pressed become sticky, just like double-tapped
|
|
|
|
> one-shot keys.
|
|
|
|
|
|
|
|
## Plugin methods
|
|
|
|
|
|
|
|
The plugin provides one object, `OneShot`, which implements both one-shot
|
|
|
|
modifiers and one-shot layer keys. It has the following methods:
|
|
|
|
|
|
|
|
### Configuration methods: Timeouts
|
|
|
|
|
|
|
|
#### `.setTimeout(timeout)`
|
|
|
|
|
|
|
|
> OneShot keys will remain active after they're pressed for `timeout`
|
|
|
|
> milliseconds (or until a subsequent non-oneshot key is pressed). The
|
|
|
|
> default value is 2500 (2.5 seconds).
|
|
|
|
|
|
|
|
#### `.setHoldTimeout(timeout)`
|
|
|
|
|
|
|
|
> If a one-shot key is held for longer than `timeout` milliseconds, it
|
|
|
|
> will behave like a normal key, and won't remain active after it is
|
|
|
|
> released. The default value is 250 (1/4 seconds).
|
|
|
|
|
|
|
|
#### `.setDoubleTapTimeout(timeout)`
|
|
|
|
|
|
|
|
> If a one-shot key is double-tapped (pressed twice in a row) in less
|
|
|
|
> than `timeout` milliseconds, it wil become sticky, and will remain
|
|
|
|
> active until it is pressed a third time. The default value is -1,
|
|
|
|
> which indicates that it should use the same timeout as
|
|
|
|
> `.setTimeout()`.
|
|
|
|
|
|
|
|
### Configuration methods: Stickability
|
|
|
|
|
|
|
|
#### `.enableStickability(key...)`
|
|
|
|
#### `.disableStickability(key...)`
|
|
|
|
|
|
|
|
> Enables/disables stickability for all keys listed. The keys should
|
|
|
|
> all be OneShot keys, modifier keys, or layer-shift keys, as
|
|
|
|
> specified on the keymap. For example:
|
|
|
|
> `OneShot.enableStickability(OSM(LeftShift), OSL(1), Key_RightGUI)`.
|
|
|
|
> `OneShot.disableStickability(OSM(RighttAlt), OSL(2), ShiftToLayer(4))`.
|
|
|
|
>
|
|
|
|
> By default, all OneShot keys are stickable.
|
|
|
|
|
|
|
|
#### `.enableStickabilityForModifiers()`
|
|
|
|
#### `.enableStickabilityForLayers()`
|
|
|
|
#### `.disableStickabilityForModifiers()`
|
|
|
|
#### `.disableStickabilityForLayers()`
|
|
|
|
|
|
|
|
> Enables/disables stickability for all modifiers and layers,
|
|
|
|
> respectively. These are convenience methods for cases where one
|
|
|
|
> wants to enable stickability for a group of one-shot keys.
|
|
|
|
|
|
|
|
### Configuration methods: Automatic one-shot keys
|
|
|
|
|
|
|
|
#### `.enableAutoModifiers()`
|
|
|
|
#### `.disableAutoModifiers()`
|
|
|
|
#### `.toggleAutoModifiers()`
|
|
|
|
|
|
|
|
> Enables/disables/toggles auto-oneshot functionality for modifier
|
|
|
|
> keys. When enabled, all normal modifier keys, including those with
|
|
|
|
> other modifier flags added to them (e.g. `LSHIFT(Key_LeftAlt)`,
|
|
|
|
> `Key_Meh`) will be automatically treated as one-shot keys, in
|
|
|
|
> addition to dedicated ones like `OSM(LeftGui)`.
|
|
|
|
|
|
|
|
#### `.enableAutoLayers()`
|
|
|
|
#### `.disableAutoLayers()`
|
|
|
|
#### `.toggleAutoLayers()`
|
|
|
|
|
|
|
|
> Enables/disables/toggles auto-oneshot functionality for layer shift
|
|
|
|
> keys (see above).
|
|
|
|
|
|
|
|
#### `.enableAutoOneShot()`
|
|
|
|
#### `.disableAutoOneShot()`
|
|
|
|
#### `.toggleAutoOneShot()`
|
|
|
|
|
|
|
|
> Enables/disables/toggles auto-oneshot functionality for all
|
|
|
|
> modifiers and layer shift keys.
|
|
|
|
|
|
|
|
### Test methods
|
|
|
|
|
|
|
|
#### `.isActive(key_addr)`
|
|
|
|
|
|
|
|
> Returns `true` if the key at `key_addr` is in an active one-shot
|
|
|
|
> state. Note that if a key is still being held, but will be not
|
|
|
|
> remain active after it is released, it is not considered to be in a
|
|
|
|
> one-shot state, even if it had been earlier.
|
|
|
|
|
|
|
|
#### `.isTemporary(key_addr)`
|
|
|
|
|
|
|
|
> Returns `true` if the key at `key_addr` is in a temporary one-shot
|
|
|
|
> state. Such a key will eventually time out or get deactivated by a
|
|
|
|
> subsequent key press.
|
|
|
|
|
|
|
|
#### `.isSticky(key_addr)`
|
|
|
|
|
|
|
|
> Returns `true` if the key at `key_addr` is in a permanent one-shot
|
|
|
|
> state. Such a key will not be deactivated by subsequent keypresses,
|
|
|
|
> nor will it time out. It will only be deactivated by pressing it one
|
|
|
|
> more time, or by being cancelled by the `cancel()` method (see
|
|
|
|
> below).
|
|
|
|
|
|
|
|
#### `.isActive()`
|
|
|
|
|
|
|
|
> Returns `true` if there are any active one-shot keys. Note: it
|
|
|
|
> returns `false` if there are no currently active one-shot keys, but
|
|
|
|
> there are keys that were at one time in a one-shot state, but are
|
|
|
|
> still being held after that state has been cancelled.
|
|
|
|
|
|
|
|
#### `.isSticky()`
|
|
|
|
|
|
|
|
> Returns `true` if there are any sticky one-shot keys.
|
|
|
|
|
|
|
|
#### `.isStickable(key)`
|
|
|
|
|
|
|
|
> Returns `true` if a key of the specified value can be made sticky by
|
|
|
|
> double-tapping.
|
|
|
|
|
|
|
|
#### `.isModifier(key)`
|
|
|
|
|
|
|
|
> Returns `true` if the specified key is a modifier key. This does not
|
|
|
|
> include OneShot modifiers (e.g. `OSM(LeftShift)`), but it does
|
|
|
|
> include modifiers with additional modifier flags (e.g. `Key_Meh`,
|
|
|
|
> `LCTRL(Key_RightGui)`).
|
|
|
|
|
|
|
|
#### `.isLayerShift(key)`
|
|
|
|
|
|
|
|
> Returns `true` if the specified key is a layer-shift key
|
|
|
|
> (e.g. `ShiftToLayer(2)`). OneShot layer keys (e.g. `OSL(5)` are not
|
|
|
|
> included).
|
|
|
|
|
|
|
|
#### `.isOneShotKey(key)`
|
|
|
|
|
|
|
|
> Returns `true` if the specified key is a OneShot modifier or
|
|
|
|
> layer-shift key (e.g. `OSM(LeftAlt)`, `OSL(3)`).
|
|
|
|
|
|
|
|
### Other methods
|
|
|
|
|
|
|
|
#### `.cancel([with_stickies])`
|
|
|
|
|
|
|
|
> Immediately deactivates the one-shot status of any _temporary_
|
|
|
|
> one-shot keys. Any keys still being physically held will continue to
|
|
|
|
> function as normal modifier/layer-shift keys.
|
|
|
|
>
|
|
|
|
> If `with_stickies` is `true` (the default is `false`), _sticky_
|
|
|
|
> one-shot keys will also be deactivated, in the same way.
|
|
|
|
|
|
|
|
### Deprecated methods
|
|
|
|
|
|
|
|
The following methods have been deprecated, and should no longer be
|
|
|
|
used, if possible. These functions made more sense when OneShot was
|
|
|
|
based on `Key` values; it has since be rewritten to be based on
|
|
|
|
`KeyAddr` values.
|
|
|
|
|
|
|
|
#### `.inject(key, key_state)`
|
|
|
|
|
|
|
|
> Finds an idle key on the keyboard, and turns it into a one-shot
|
|
|
|
> key. When OneShot was based on `Key` values, this made more sense,
|
|
|
|
> as it didn't need a valid `KeyAddr` to work. Since the main purpose
|
|
|
|
> of this method was to enable the triggering of multiple one-shot
|
|
|
|
> modifiers with a single key, it is much better to use automatic
|
|
|
|
> one-shot modifiers, if possible, because then it's not necessary to
|
|
|
|
> use a Macro to configure.
|
|
|
|
|
|
|
|
#### `.isModifierActive(key)`
|
|
|
|
|
|
|
|
> Returns `true` if a keymap cache entry with the current value of
|
|
|
|
> `key` is active (one-shot, sticky, or held). This should be a
|
|
|
|
> function that is not specific to OneShot.
|
|
|
|
|
|
|
|
#### `.isActive(key)`
|
|
|
|
|
|
|
|
> Returns `true` if a keymap cache entry with the current value of
|
|
|
|
> `key` is in an active one-shot state. Please use
|
|
|
|
> `.isActive(key_addr)` instead.
|
|
|
|
|
|
|
|
#### `.isSticky(key)`
|
|
|
|
|
|
|
|
> Returns `true` if a keymap cache entry with the current value of
|
|
|
|
> `key` is in a sticky one-shot state. Please use
|
|
|
|
> `.isSticky(key_addr)` instead.
|
|
|
|
|
|
|
|
#### `.isPressed()`
|
|
|
|
|
|
|
|
> Returns `false`. OneShot doesn't need to keep track of whether or
|
|
|
|
> not a one-shot key is still pressed any more. This function was
|
|
|
|
> mainly used by LED-ActiveModColor, which no longer needs it.
|
|
|
|
|
|
|
|
## Dependencies
|
|
|
|
|
|
|
|
* [Kaleidoscope-Ranges](Kaleidoscope-Ranges.md)
|
|
|
|
|
|
|
|
## Further reading
|
|
|
|
|
|
|
|
Starting from the [example][plugin:example] is the recommended way of getting
|
|
|
|
started with the plugin.
|
|
|
|
|
|
|
|
[plugin:example]: /examples/Keystrokes/OneShot/OneShot.ino
|