Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to toggle One Shot functionality #4198

Merged
merged 10 commits into from
Mar 1, 2021
3 changes: 3 additions & 0 deletions docs/keycodes.md
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,9 @@ See also: [One Shot Keys](one_shot_keys.md)
|------------|----------------------------------|
|`OSM(mod)` |Hold `mod` for one keypress |
|`OSL(layer)`|Switch to `layer` for one keypress|
|`OS_ON` |Turns One Shot keys on |
|`OS_OFF` |Turns One Shot keys off |
|`OS_TOGG` |Toggles One Shot keys status |

## Space Cadet :id=space-cadet

Expand Down
3 changes: 3 additions & 0 deletions docs/one_shot_keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ You can control the behavior of one shot keys by defining these in `config.h`:
* `OSM(mod)` - Momentarily hold down *mod*. You must use the `MOD_*` keycodes as shown in [Mod Tap](mod_tap.md), not the `KC_*` codes.
* `OSL(layer)` - momentary switch to *layer*.
* `OS_ON` - Turns on One Shot keys.
* `OS_OFF` - Turns off One Shot keys. OSM act as regular mod keys, OSL act like `MO`.
* `ON_TOGG` - Toggles the one shot key status.
Sometimes, you want to activate a one-shot key as part of a macro or tap dance routine.
Expand Down
1 change: 1 addition & 0 deletions quantum/keycode_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ typedef union {
bool nkro : 1;
bool swap_lctl_lgui : 1;
bool swap_rctl_rgui : 1;
bool oneshot_disable : 1;
};
} keymap_config_t;

Expand Down
11 changes: 11 additions & 0 deletions quantum/quantum.c
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,17 @@ bool process_record_quantum(keyrecord_t *record) {
case OUT_BT:
set_output(OUTPUT_BLUETOOTH);
return false;
#endif
#ifndef NO_ACTION_ONESHOT
case ONESHOT_TOGGLE:
oneshot_toggle();
break;
case ONESHOT_ENABLE:
oneshot_enable();
break;
case ONESHOT_DISABLE:
oneshot_disable();
break;
#endif
}
}
Expand Down
9 changes: 9 additions & 0 deletions quantum/quantum_keycodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,10 @@ enum quantum_keycodes {

#endif

ONESHOT_ENABLE,
ONESHOT_DISABLE,
ONESHOT_TOGGLE,

// always leave at the end
SAFE_RANGE
};
Expand Down Expand Up @@ -885,3 +889,8 @@ enum quantum_keycodes {
#define DM_RSTP DYN_REC_STOP
#define DM_PLY1 DYN_MACRO_PLAY1
#define DM_PLY2 DYN_MACRO_PLAY2

// One Shot toggle
#define OS_TOGG ONESHOT_TOGGLE
#define OS_ON ONESHOT_ENABLE
#define OS_OFF ONESHOT_DISABLE
58 changes: 49 additions & 9 deletions tmk_core/common/action_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,16 @@ void clear_oneshot_swaphands(void) {
* FIXME: needs doc
*/
void set_oneshot_layer(uint8_t layer, uint8_t state) {
oneshot_layer_data = layer << 3 | state;
layer_on(layer);
if (!keymap_config.oneshot_disable) {
oneshot_layer_data = layer << 3 | state;
layer_on(layer);
# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
oneshot_layer_time = timer_read();
oneshot_layer_time = timer_read();
# endif
oneshot_layer_changed_kb(get_oneshot_layer());
oneshot_layer_changed_kb(get_oneshot_layer());
} else {
layer_on(layer);
}
}
/** \brief Reset oneshot layer
*
Expand All @@ -172,7 +176,7 @@ void reset_oneshot_layer(void) {
void clear_oneshot_layer_state(oneshot_fullfillment_t state) {
uint8_t start_state = oneshot_layer_data;
oneshot_layer_data &= ~state;
if (!get_oneshot_layer_state() && start_state != oneshot_layer_data) {
if ((!get_oneshot_layer_state() && start_state != oneshot_layer_data) || keymap_config.oneshot_disable) {
layer_off(get_oneshot_layer());
reset_oneshot_layer();
}
Expand All @@ -182,6 +186,39 @@ void clear_oneshot_layer_state(oneshot_fullfillment_t state) {
* FIXME: needs doc
*/
bool is_oneshot_layer_active(void) { return get_oneshot_layer_state(); }

drashna marked this conversation as resolved.
Show resolved Hide resolved
/** \brief set oneshot
*
* FIXME: needs doc
*/
void oneshot_set(bool active) {
if (keymap_config.oneshot_disable != active) {
keymap_config.oneshot_disable = active;
eeconfig_update_keymap(keymap_config.raw);
dprintf("Oneshot: active: %d\n", active);
}
}

/** \brief toggle oneshot
*
* FIXME: needs doc
*/
void oneshot_toggle(void) { oneshot_set(!keymap_config.oneshot_disable); }

/** \brief enable oneshot
*
* FIXME: needs doc
*/
void oneshot_enable(void) { oneshot_set(true); }

/** \brief disable oneshot
*
* FIXME: needs doc
*/
void oneshot_disable(void) { oneshot_set(false); }

bool is_oneshot_enabled(void) { return keymap_config.oneshot_disable; }

#endif

/** \brief Send keyboard report
Expand Down Expand Up @@ -321,14 +358,17 @@ void del_oneshot_mods(uint8_t mods) {
* FIXME: needs doc
*/
void set_oneshot_mods(uint8_t mods) {
if (oneshot_mods != mods) {
if (!keymap_config.oneshot_disable) {
if (oneshot_mods != mods) {
# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
oneshot_time = timer_read();
oneshot_time = timer_read();
# endif
oneshot_mods = mods;
oneshot_mods_changed_kb(mods);
oneshot_mods = mods;
oneshot_mods_changed_kb(mods);
}
}
}

/** \brief clear oneshot mods
*
* FIXME: needs doc
Expand Down
5 changes: 5 additions & 0 deletions tmk_core/common/action_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ void oneshot_mods_changed_kb(uint8_t mods);
void oneshot_layer_changed_user(uint8_t layer);
void oneshot_layer_changed_kb(uint8_t layer);

void oneshot_toggle(void);
void oneshot_enable(void);
void oneshot_disable(void);
bool is_oneshot_enabled(void);

/* inspect */
uint8_t has_anymod(void);

Expand Down