Update documentation and example sketch

Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
pull/1024/head
Michael Richters 4 years ago
parent 682019493a
commit 1a63ade706
No known key found for this signature in database
GPG Key ID: 1288FD13E4EEF0C0

@ -12,6 +12,60 @@ See [UPGRADING.md](UPGRADING.md) for more detailed instructions about upgrading
## New features ## New features
### New OneShot features
#### Auto-OneShot modifiers & layers
OneShot can now treat modifiers and layer-shift keys as automatic OneShot
keys. This includes modifiers with other modifier flags applied, so it is now
very simple to turn `Key_Meh` or `Key_Hyper` into a OneShot key. The feature is
controlled by the following new functions:
- `OneShot.toggleAutoModifiers()`: Turn auto-OneShot modifiers on or off.
- `OneShot.toggleAutoLayers()`: Turn auto-OneShot layer shifts on or off.
- `OneShot.toggleAutoOneShot()`: Both of the above.
There are also `enable` and `disable` versions of these functions.
Note, it is still possible to define a modifier key in the keymap that will not
automatically become a OneShot key when pressed, by applying modifier flags to
`Key_NoKey` (e.g. `LSHIFT(Key_NoKey)`).
#### Two new special OneShot keys
OneShot can now also turn _any_ key into a sticky key, using either of two
special `Key` values that can be inserted in the keymap.
##### `OneShot_MetaStickyKey`
This is a special OneShot key (it behaves like other OneShot keys), but its
effect is to make any key pressed while it is active sticky. Press
`OneShot_MetaStickyKey`, then press `X`, and `X` will become sticky. Sticky
keys can be deactivated just like other OneShot keys, by pressing them
again. This works for any key value, so use it with caution.
##### `OneShot_ActiveStickyKey`
Like `OneShot_ActiveStickyKey`, this key makes other keys sticky, but rather than
affecting a subsequent key, it affects any keys already held when it is
pressed. Press `X`, press `OneShot_ActiveStickyKey`, and release `X`, and `X`
will be sticky until it is pressed again to deactivate it. Again, it works on
any key value, so use with caution.
#### LED-ActiveModColor highlighting
With the updates to OneShot, LED-ActiveModColor now recognizes and highlights
OneShot keys in three different states (along with normal modifiers):
- one-shot (a key that's active after release, but will time out)
- sticky (a key that will stay active indefinitely after release)
- normal (a key that will stay active only while physically held; also applies
to normal modifier keys)
The colors of theses three highlights are controlled by the properties
`ActiveModColorEffect.oneshot_color`, `ActiveModColorEffect.sticky_color`, and
`ActiveModColorEffect.highlight_color`, respectively.
### Better protection against unintended modifiers from Qukeys ### Better protection against unintended modifiers from Qukeys
Qukeys has two new configuration options for preventing unintended modifiers in Qukeys has two new configuration options for preventing unintended modifiers in

@ -18,6 +18,7 @@ If any of this does not make sense to you, or you have trouble updating your .in
- [The `RxCy` macros and peeking into the keyswitch state](#the-rxcy-macros-and-peeking-into-the-keyswitch-state) - [The `RxCy` macros and peeking into the keyswitch state](#the-rxcy-macros-and-peeking-into-the-keyswitch-state)
- [HostOS](#hostos) - [HostOS](#hostos)
- [MagicCombo](#magiccombo) - [MagicCombo](#magiccombo)
- [OneShot](#oneshot)
- [Qukeys](#qukeys) - [Qukeys](#qukeys)
- [TypingBreaks](#typingbreaks) - [TypingBreaks](#typingbreaks)
- [Redial](#redial) - [Redial](#redial)
@ -580,6 +581,44 @@ If your actions made use of the `left_hand` or `right_hand` arguments of
more involved to get to, out of scope for this simple migration guide. Please more involved to get to, out of scope for this simple migration guide. Please
open an issue, or ask for help on the forums, and we'll help you. open an issue, or ask for help on the forums, and we'll help you.
### OneShot
Older versions of the plugin were based on `Key` values; OneShot is now based on
`KeyAddr` coordinates instead, in order to improve reliability and
functionality.
The following deprecated functions and variables will be removed after
**2021-04-31**.
#### Deprecated functions
- `OneShot.inject(key, key_state)`: This `Key`-based function still works, but
because OneShot keys are now required to have a valid `KeyAddr`, it will now
look for an idle key, and use that, masking whatever value was mapped to that
key. Most of the reasons for using this function are better addressed by using
the newer features of the plugin, such as automatic one-shot modifiers. Use is
very strongly discouraged.
- `OneShot.isActive(key)`: This `Key`-based function no longer makes sense now
that OneShot is `KeyAddr`-based. There is a `OneShot.isActive(key_addr)`
function that should be used instead. The deprecated function still works, but
its use is discouraged.
- `OneShot.isSticky(key)`: This `Key`-based function no longer makes sense now
that OneShot is `KeyAddr`-based. There is a `OneShot.isSticky(key_addr)`
function that should be used instead. The deprecated function still works, but
its use is discouraged.
- `OneShot.isPressed()`: This function no longer has any reason for existing. In
older versions, the Escape-OneShot companion plugin used it to solve a problem
that no longer exists. It now always returns `false`.
- `OneShot.isModifierActive(key)`: This function still works, but is not
perfectly reliable, because it now returns positive results for keys other
than OneShot modifiers. It should not be used.
#### Deprecated variables
- `OneShot.time_out`: Use `OneShot.setTimeout()` instead.
- `OneShot.hold_time_out`: Use `OneShot.setHoldTimeout()` instead.
- `OneShot.double_tap_time_out`: Use `OneShot.setDoubleTapTimeout()` instead.
### Qukeys ### Qukeys
Older versions of the plugin used `row` and `col` indexing for defining `Qukey` Older versions of the plugin used `row` and `col` indexing for defining `Qukey`

@ -21,27 +21,27 @@
// Macros // Macros
enum { enum {
OSMALTCTRL, TOGGLE_ONESHOT,
}; };
// *INDENT-OFF* // *INDENT-OFF*
KEYMAPS( KEYMAPS(
[0] = KEYMAP_STACKED [0] = KEYMAP_STACKED
( (
Key_NoKey, Key_1, Key_2, Key_3, Key_4, Key_5, Key_NoKey, M(TOGGLE_ONESHOT), Key_1, Key_2, Key_3, Key_4, Key_5, OneShot_MetaStickyKey,
Key_Backtick, Key_Q, Key_W, Key_E, Key_R, Key_T, Key_Tab, Key_Backtick, Key_Q, Key_W, Key_E, Key_R, Key_T, Key_Tab,
Key_PageUp, Key_A, Key_S, Key_D, Key_F, Key_G, Key_PageUp, Key_A, Key_S, Key_D, Key_F, Key_G,
Key_PageDown, Key_Z, Key_X, Key_C, Key_V, Key_B, Key_Escape, Key_PageDown, Key_Z, Key_X, Key_C, Key_V, Key_B, Key_Escape,
OSM(LeftControl), Key_Backspace, OSM(LeftGui), OSM(LeftShift), OSM(LeftControl), Key_Backspace, OSM(LeftGui), OSM(LeftShift),
M(OSMALTCTRL), Key_Meh,
Key_skip, Key_6, Key_7, Key_8, Key_9, Key_0, Key_skip, OneShot_ActiveStickyKey, Key_6, Key_7, Key_8, Key_9, Key_0, ___,
Key_Enter, Key_Y, Key_U, Key_I, Key_O, Key_P, Key_Equals, Key_Enter, Key_Y, Key_U, Key_I, Key_O, Key_P, Key_Equals,
Key_H, Key_J, Key_K, Key_L, Key_Semicolon, Key_Quote, Key_H, Key_J, Key_K, Key_L, Key_Semicolon, Key_Quote,
Key_skip, Key_N, Key_M, Key_Comma, Key_Period, Key_Slash, Key_Minus, ___, Key_N, Key_M, Key_Comma, Key_Period, Key_Slash, Key_Minus,
OSM(RightShift), OSM(RightAlt), Key_Spacebar, OSM(RightControl), Key_RightShift, Key_RightAlt, Key_Spacebar, Key_RightControl,
OSL(1)), OSL(1)),
[1] = KEYMAP_STACKED [1] = KEYMAP_STACKED
@ -64,14 +64,13 @@ KEYMAPS(
) )
// *INDENT-ON* // *INDENT-ON*
void macroOneShotAltControl(uint8_t keyState) { void macroToggleOneShot() {
OneShot.inject(OSM(LeftAlt), keyState); OneShot.toggleAutoOneShot();
OneShot.inject(OSM(LeftControl), keyState);
} }
const macro_t *macroAction(uint8_t macroIndex, uint8_t keyState) { const macro_t *macroAction(uint8_t macroIndex, uint8_t keyState) {
if (macroIndex == OSMALTCTRL) { if (macroIndex == TOGGLE_ONESHOT) {
macroOneShotAltControl(keyState); macroToggleOneShot();
} }
return MACRO_NONE; return MACRO_NONE;

@ -2,9 +2,8 @@
With this plugin, any active modifier on the keyboard will have the LED under it With this plugin, any active modifier on the keyboard will have the LED under it
highlighted. No matter how the modifier got activated (a key press, a macro, highlighted. No matter how the modifier got activated (a key press, a macro,
anything else), the coloring will apply. Layer keys, be them layer toggles, anything else), the coloring will apply. Layer shift keys and OneShot layer keys
momentary switches, or one-shot layer keys count as modifiers as far as the count as modifiers as far as the plugin is concerned.
plugin is concerned.
## Using the plugin ## Using the plugin
@ -37,11 +36,20 @@ properties:
### `.highlight_color` ### `.highlight_color`
> The color to use for highlighting the modifiers. Defaults to a white color. > The color to use for highlighting normal modifier keys and
> layer-shift keys. Defaults to a white color.
### `.oneshot_color`
> The color to use for highlighting active one-shot keys. These are
> the keys that will time out or deactivate when a subsequent key is
> pressed. Defaults to a yellow color.
### `.sticky_color` ### `.sticky_color`
> The color to use for highlighting one-shot modifiers when they are sticky. Defaults to a red color. > The color to use for highlighting "sticky" one-shot keys. These keys
> will remain active until they are pressed again. Defaults to a red
> color.
## Plugin methods ## Plugin methods

@ -23,7 +23,7 @@ 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 `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. and other layer keys do not cancel the one-shot effect, either.
## Using One-Shot Keys ## Using One-Shot keys
To enter one-shot mode, tap _quickly_ on a one-shot key. The next 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, normal (non-one-shot) key you press will have the modifier applied,
@ -40,11 +40,30 @@ modifier will now stay on until you press it again. Continuing the
Shift, d, e, f` will give you `ABCdef`. Shift, d, e, f` will give you `ABCdef`.
This can be a bit tricky; combining this plugin with This can be a bit tricky; combining this plugin with
[LED-ActiveModColor](Kaleidoscope-LED-ActiveModColor.md) [LED-ActiveModColor](Kaleidoscope-LED-ActiveModColor.md) will help you
will help you understand what state your one-shot is in; when a understand what state your one-shot is in; when a one-shot key is active, it
one-shot key is active, it will have a white LED highlight; when will have a yellow LED highlight; when sticky, a red highlight. When it is in a
sticky, a red highlight. (These colors are configurable.) "held" state, but will be deactivated when released like any non-one-shot key,
it will have a white highlight. (These colors are configurable.)
## Special OneShot keys
OneShot also comes with two special keys that can make any key on your keyboard
sticky: `OneShot_MetaStickyKey` & `OneShot_ActiveStickyKey`. These are both
`Key` values that can be used as entries in your sketch's keymap.
### `OneShot_MetaStickyKey`
This special OneShot key behaves like other OneShot keys, but its affect is to
make the next key pressed sticky. Tap `OneShot_MetaStickyKey`, then tap `X`, and
`X` will become sticky. Tap `X` again to deactivate it.
### `OneShot_ActiveStickyKey`
This special key doesn't act like a OneShot key, but instead makes any key(s)
currently held (or otherwise active) sticky. Press (and hold) `X`, tap
`OneShot_ActiveStickyKey`, then release `X`, and `X` will stay active until it
is tapped again to deactivate it.
## Using the plugin ## Using the plugin
@ -69,13 +88,13 @@ void setup() {
There are two macros the plugin provides: There are two macros the plugin provides:
### `OSM(mod)` #### `OSM(mod)`
> A macro that takes a single argument, the name of the modifier: `LeftControl`, > A macro that takes a single argument, the name of the modifier: `LeftControl`,
> `LeftShift`, `LeftAlt`, `LeftGui` or their right-side variant. When marked up > `LeftShift`, `LeftAlt`, `LeftGui` or their right-side variant. When marked up
> with this macro, the modifier will act as a one-shot modifier. > with this macro, the modifier will act as a one-shot modifier.
### `OSL(layer)` #### `OSL(layer)`
> Takes a layer number as argument, and sets up the key to act as a one-shot > Takes a layer number as argument, and sets up the key to act as a one-shot
> layer key. > layer key.
@ -83,85 +102,203 @@ There are two macros the plugin provides:
> Please note that while `Kaleidoscope` supports more, one-shot layers are > Please note that while `Kaleidoscope` supports more, one-shot layers are
> limited to 8 layers only. > 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 ## Plugin methods
The plugin provides one object, `OneShot`, which implements both one-shot The plugin provides one object, `OneShot`, which implements both one-shot
modifiers and one-shot layer keys. It has the following methods: modifiers and one-shot layer keys. It has the following methods:
### `.isActive()` ### Configuration methods: Timeouts
> Returns if any one-shot key is in flight. This makes it possible to #### `.setTimeout(timeout)`
> differentiate between having a modifier or layer active, versus having them
> active only until after the next key getting pressed. And this, in turn, is
> useful for macros that need to fiddle with either modifier or layer state: if
> one-shots are not active, they need not restore the original state.
### `.isPressed()` > 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).
> Returns true if any one-shot key is still held. #### `.setHoldTimeout(timeout)`
### `.isSticky(key)` > 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).
> Returns if the key is currently sticky. #### `.setDoubleTapTimeout(timeout)`
### `.isModifierActive(key)` > 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()`.
> Returns if the modifier `key` has a one-shot state active. Use this together ### Configuration methods: Stickability
> with `Kaleidoscope.hid().keyboard().isModifierKeyActive` to catch cases where
> a one-shot modifier is active, but not registered yet.
### `.cancel([with_stickies])` #### `.enableStickability(key...)`
#### `.disableStickability(key...)`
> The `cancel()` method can be used to cancel any pending one-shot effects, > Enables/disables stickability for all keys listed. The keys should
> useful when one changed their minds, and does not wish to wait for the > all be OneShot keys, modifier keys, or layer-shift keys, as
> timeout. > specified on the keymap. For example:
> `OneShot.enableStickability(OSM(LeftShift), OSL(1), Key_RightGUI)`.
> `OneShot.disableStickability(OSM(RighttAlt), OSL(2), ShiftToLayer(4))`.
> >
> The optional `with_stickies` argument, if set to `true`, will also cancel > By default, all OneShot keys are stickable.
> sticky one-shot effects. If omitted, it defaults to `false`, and not canceling
> stickies.
### `.inject(key, keyState)` #### `.enableStickabilityForModifiers()`
#### `.enableStickabilityForLayers()`
#### `.disableStickabilityForModifiers()`
#### `.disableStickabilityForLayers()`
> Simulates a key event, specifically designed to inject one-shot keys into the > Enables/disables stickability for all modifiers and layers,
> event loop. The primary purpose of this method is to make it easier to trigger > respectively. These are convenience methods for cases where one
> multiple one-shots at the same time. > wants to enable stickability for a group of one-shot keys.
>
> See the example sketch for more information about its use.
### `.enableStickability(key...)` ### Configuration methods: Automatic one-shot keys
> Enables stickability for all keys listed. The keys should all be OneShot keys, #### `.enableAutoModifiers()`
> as if specified on the keymap. For example: #### `.disableAutoModifiers()`
> `OneShot.enableStickability(OSM(LeftShift), OSL(1))`. #### `.toggleAutoModifiers()`
>
> By default, all oneshot keys are stickable.
### `.enableStickabilityForModifiers()` > Enables/disables/toggles auto-oneshot functionality for modifier
### `.enableStickabilityForLayers()` > 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)`.
> Enables stickability for all modifiers and layers, respectively. These are #### `.enableAutoLayers()`
> convenience methods for cases where one wants to enable stickability for a #### `.disableAutoLayers()`
> group of one-shot keys. #### `.toggleAutoLayers()`
### `.disableStickability(key...)` > Enables/disables/toggles auto-oneshot functionality for layer shift
> keys (see above).
> Disables stickability for all keys listed. The keys should all be OneShot keys, #### `.enableAutoOneShot()`
> as if specified on the keymap. For example: #### `.disableAutoOneShot()`
> `OneShot.disableStickability(OSM(LeftShift), OSL(1))`. #### `.toggleAutoOneShot()`
>
> By default, all oneshot keys are stickable. > 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.
### `.disableStickabilityForModifiers()` #### `.isPressed()`
### `.disableStickabilityForLayers()`
> Disables stickability for all modifiers and layers, respectively. These are > Returns `false`. OneShot doesn't need to keep track of whether or
> convenience methods for cases where one wants to disable stickability for a > not a one-shot key is still pressed any more. This function was
> group of one-shot keys. > mainly used by LED-ActiveModColor, which no longer needs it.
## Plugin properties ## Plugin properties **[DEPRECATED]**
Along with the methods listed above, the `OneShot` object has the following Along with the methods listed above, the `OneShot` object has the
properties too: following properties, too. [Note: these have all been deprecated,
please use the `.set*Timeout()` methods above instead.]
### `.time_out` ### `.time_out`

Loading…
Cancel
Save