mirror of
https://github.com/qmk/qmk_firmware.git
synced 2025-07-23 08:02:03 +00:00
Compare commits
10 Commits
6c01ab5b42
...
7faa82869c
Author | SHA1 | Date | |
---|---|---|---|
|
7faa82869c | ||
|
fe02abc479 | ||
|
cdf8ecd2c7 | ||
|
4002843797 | ||
|
21f4375393 | ||
|
98b0bcf545 | ||
|
90f3d6201a | ||
|
7a067c6127 | ||
|
0a9d06a505 | ||
|
f667821ed3 |
@ -624,6 +624,7 @@ ifeq ($(strip $(VIA_ENABLE)), yes)
|
||||
DYNAMIC_KEYMAP_ENABLE := yes
|
||||
RAW_ENABLE := yes
|
||||
BOOTMAGIC_ENABLE := yes
|
||||
TRI_LAYER_ENABLE := yes
|
||||
SRC += $(QUANTUM_DIR)/via.c
|
||||
OPT_DEFS += -DVIA_ENABLE
|
||||
endif
|
||||
|
@ -39,6 +39,7 @@ GENERIC_FEATURES = \
|
||||
VELOCIKEY \
|
||||
WPM \
|
||||
DYNAMIC_TAPPING_TERM \
|
||||
TRI_LAYER
|
||||
|
||||
define HANDLE_GENERIC_FEATURE
|
||||
# $$(info "Processing: $1_ENABLE $2.c")
|
||||
|
@ -84,7 +84,8 @@ OTHER_OPTION_NAMES = \
|
||||
PROGRAMMABLE_BUTTON_ENABLE \
|
||||
SECURE_ENABLE \
|
||||
CAPS_WORD_ENABLE \
|
||||
AUTOCORRECT_ENABLE
|
||||
AUTOCORRECT_ENABLE \
|
||||
TRI_LAYER_ENABLE
|
||||
|
||||
define NAME_ECHO
|
||||
@printf " %-30s = %-16s # %s\\n" "$1" "$($1)" "$(origin $1)"
|
||||
|
18
data/constants/keycodes/keycodes_0.0.2_quantum.hjson
Normal file
18
data/constants/keycodes/keycodes_0.0.2_quantum.hjson
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"keycodes": {
|
||||
"0x7C77": {
|
||||
"group": "quantum",
|
||||
"key": "QK_TRI_LAYER_LOWER",
|
||||
"aliases": [
|
||||
"TL_LOWR"
|
||||
]
|
||||
},
|
||||
"0x7C78": {
|
||||
"group": "quantum",
|
||||
"key": "QK_TRI_LAYER_UPPER",
|
||||
"aliases": [
|
||||
"TL_UPPR"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
@ -93,6 +93,7 @@
|
||||
* [Swap Hands](feature_swap_hands.md)
|
||||
* [Tap Dance](feature_tap_dance.md)
|
||||
* [Tap-Hold Configuration](tap_hold.md)
|
||||
* [Tri Layer](feature_tri_layer.md)
|
||||
* [Unicode](feature_unicode.md)
|
||||
* [Userspace](feature_userspace.md)
|
||||
* [WPM Calculation](feature_wpm.md)
|
||||
|
@ -10,7 +10,7 @@ These functions allow you to activate layers in various ways. Note that layers a
|
||||
|
||||
* `DF(layer)` - switches the default layer. The default layer is the always-active base layer that other layers stack on top of. See below for more about the default layer. This might be used to switch from QWERTY to Dvorak layout. (Note that this is a temporary switch that only persists until the keyboard loses power. To modify the default layer in a persistent way requires deeper customization, such as calling the `set_single_persistent_default_layer` function inside of [process_record_user](custom_quantum_functions.md#programming-the-behavior-of-any-keycode).)
|
||||
* `MO(layer)` - momentarily activates *layer*. As soon as you let go of the key, the layer is deactivated.
|
||||
* `LM(layer, mod)` - Momentarily activates *layer* (like `MO`), but with modifier(s) *mod* active. Only supports layers 0-15 and the left modifiers: `MOD_LCTL`, `MOD_LSFT`, `MOD_LALT`, `MOD_LGUI` (note the use of `MOD_` constants instead of `KC_`). These modifiers can be combined using bitwise OR, e.g. `LM(_RAISE, MOD_LCTL | MOD_LALT)`.
|
||||
* `LM(layer, mod)` - Momentarily activates *layer* (like `MO`), but with modifier(s) *mod* active. Only supports layers 0-15. The modifiers this keycode accept are prefixed with `MOD_`, not `KC_`. These modifiers can be combined using bitwise OR, e.g. `LM(_RAISE, MOD_LCTL | MOD_LALT)`.
|
||||
* `LT(layer, kc)` - momentarily activates *layer* when held, and sends *kc* when tapped. Only supports layers 0-15.
|
||||
* `OSL(layer)` - momentarily activates *layer* until the next key is pressed. See [One Shot Keys](one_shot_keys.md) for details and additional functionality.
|
||||
* `TG(layer)` - toggles *layer*, activating it if it's inactive and vice versa
|
||||
@ -21,6 +21,12 @@ These functions allow you to activate layers in various ways. Note that layers a
|
||||
|
||||
Currently, the `layer` argument of `LT()` is limited to layers 0-15, and the `kc` argument to the [Basic Keycode set](keycodes_basic.md), meaning you can't use keycodes like `LCTL()`, `KC_TILD`, or anything greater than `0xFF`. This is because QMK uses 16-bit keycodes, of which 4 bits are used for the function identifier and 4 bits for the layer, leaving only 8 bits for the keycode.
|
||||
|
||||
For a similar reason, the `layer` argument of `LM()` is also limited to layers 0-15 and the `mod` argument must fit within 5 bits. As a consequence, although left and right modifiers are supported by `LM()`, it is impossible to mix and match left and right modifiers. Specifying at least one right-hand modifier in a combination such as `MOD_RALT|MOD_LSFT` will convert *all* the listed modifiers to their right-hand counterpart. So, using the aforementionned mod-mask will actually send <kbd>Right Alt</kbd>+<kbd>Right Shift</kbd>. Make sure to use the `MOD_xxx` constants over alternative ways of specifying modifiers when defining your layer-mod key.
|
||||
|
||||
| `LM(1,KC_LSFT)` | `LM(1,MOD_MASK_SHIFT)` | `LM(1,MOD_BIT(KC_LSFT))` | `LM(1,MOD_LSFT)` |
|
||||
|:---------------:|:----------------------:|:------------------------:|:----------------:|
|
||||
| ❌ | ❌ | ❌ | ✅ |
|
||||
|
||||
Expanding this would be complicated, at best. Moving to a 32-bit keycode would solve a lot of this, but would double the amount of space that the keymap matrix uses. And it could potentially cause issues, too. If you need to apply modifiers to your tapped keycode, [Tap Dance](feature_tap_dance.md#example-5-using-tap-dance-for-advanced-mod-tap-and-layer-tap-keys) can be used to accomplish this.
|
||||
|
||||
## Working with Layers :id=working-with-layers
|
||||
|
48
docs/feature_tri_layer.md
Normal file
48
docs/feature_tri_layer.md
Normal file
@ -0,0 +1,48 @@
|
||||
# Tri Layers :id=tri-layers
|
||||
|
||||
This enables support for the OLKB style "Tri Layer" keycodes. These function similar to the `MO` (momentary) function key, but if both the "Lower" and "Upper" keys are pressed, it activates a third "Adjust" layer. To enable this functionality, add this line to your `rules.mk`:
|
||||
|
||||
```make
|
||||
TRI_LAYER_ENABLE = yes
|
||||
```
|
||||
|
||||
Note that the "upper", "lower" and "adjust" names don't have a particular significance, they are just used to identify and clarify the behavior. Layers are processed from highest numeric value to lowest, however the values are not required to be consecutive.
|
||||
|
||||
For a detailed explanation of how the layer stack works, check out [Keymap Overview](keymap.md#keymap-and-layers).
|
||||
|
||||
## Keycodes :id=keycodes
|
||||
|
||||
| Keycode | Alias | Description |
|
||||
|----------------------|-----------|---------------------------------------------------------------------------------------------------------|
|
||||
| `QK_TRI_LAYER_LOWER` | `TL_LOWR` | Momentarily enables the "lower" layer. Enables the "adjust" layer if the "upper" layer is also enabled" |
|
||||
| `QK_TRI_LAYER_UPPER` | `TL_UPPR` | Momentarily enables the "upper" layer. Enables the "adjust" layer if the "lower" layer is also enabled" |
|
||||
|
||||
## Configuration
|
||||
|
||||
To change the default values for the layers, you can change these defines, in your `config.h`
|
||||
|
||||
| Config name | Default | Description |
|
||||
|--------------------------|---------|------------------------------------------|
|
||||
| `TRI_LAYER_LOWER_LAYER` | `1` | Sets the default for the "lower" layer. |
|
||||
| `TRI_LAYER_UPPER_LAYER` | `2` | Sets the default for the "upper" layer. |
|
||||
| `TRI_LAYER_ADJUST_LAYER` | `3` | Sets the default for the "adjust" layer. |
|
||||
|
||||
Eg, if you wanted to set the "Adjust" layer to be layer 5, you'd add this to your `config.h`:
|
||||
|
||||
```c
|
||||
#define TRI_LAYER_ADJUST_LAYER 5
|
||||
```
|
||||
|
||||
## Functions
|
||||
|
||||
| Function name | Description |
|
||||
|----------------------------------------------|-------------------------------------------------|
|
||||
| `set_tri_layer_lower_layer(layer)` | Changes the "lower" layer*. |
|
||||
| `set_tri_layer_upper_layer(layer)` | Changes the "upper" layer*. |
|
||||
| `set_tri_layer_adjust_layer(layer)` | Changes the "adjust" layer*. |
|
||||
| `set_tri_layer_layers(lower, upper, adjust)` | Stes the "lower", "upper" and "adjust" layers*. |
|
||||
| `get_tri_layer_lower_layer()` | Gets the current "lower" layer. |
|
||||
| `get_tri_layer_upper_layer()` | Gets the current "upper" layer. |
|
||||
| `get_tri_layer_adjust_layer()` | Gets the current "adjust" layer. |
|
||||
|
||||
!> Note: these settings are not persisent, and will be reset to the default on power loss or power cycling of the controller.
|
@ -51,21 +51,21 @@ git remote set-url origin https://github.com/<your_username>/qmk_firmware.git
|
||||
Now that you have both remotes configured, you need to update the references for the upstream repository, which is QMK's, by running:
|
||||
|
||||
```
|
||||
git fetch upstream
|
||||
git fetch --recurse-submodules upstream
|
||||
```
|
||||
|
||||
At this point, resynchronize your branch to QMK's by running:
|
||||
|
||||
```
|
||||
git reset --hard upstream/master
|
||||
git reset --recurse-submodules --hard upstream/master
|
||||
```
|
||||
|
||||
These steps will update the repository on your computer, but your GitHub fork will still be out of sync. To resynchronize your fork on GitHub, you need to push to your fork, instructing Git to override any remote changes that are not reflected in your local repository. To do this, run:
|
||||
|
||||
```
|
||||
git push --force-with-lease
|
||||
git push --recurse-submodules=on-demand --force-with-lease
|
||||
```
|
||||
|
||||
!> **DO NOT** run `git push --force-with-lease` on a fork to which other users post commits. This will erase their commits.
|
||||
!> **DO NOT** run `git push --recurse-submodules=on-demand --force-with-lease` on a fork to which other users post commits. This will erase their commits.
|
||||
|
||||
Now your GitHub fork, your local files, and QMK's repository are all the same. From here you can make further needed changes ([use a branch!](newbs_git_using_your_master_branch.md#making-changes)) and post them as normal.
|
||||
|
@ -1,9 +1,10 @@
|
||||
"""Functions that help us generate and use info.json files.
|
||||
"""
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
import jsonschema
|
||||
from dotty_dict import dotty
|
||||
|
||||
from milc import cli
|
||||
|
||||
from qmk.constants import CHIBIOS_PROCESSORS, LUFA_PROCESSORS, VUSB_PROCESSORS
|
||||
@ -17,15 +18,30 @@ from qmk.math import compute
|
||||
true_values = ['1', 'on', 'yes']
|
||||
false_values = ['0', 'off', 'no']
|
||||
|
||||
# TODO: reduce this list down
|
||||
SAFE_LAYOUT_TOKENS = {
|
||||
'ansi',
|
||||
'iso',
|
||||
'wkl',
|
||||
'tkl',
|
||||
'preonic',
|
||||
'planck',
|
||||
}
|
||||
|
||||
def _keyboard_in_layout_name(keyboard, layout):
|
||||
"""Validate that a layout macro does not contain name of keyboard
|
||||
"""
|
||||
# TODO: reduce this list down
|
||||
safe_layout_tokens = {
|
||||
'ansi',
|
||||
'iso',
|
||||
'jp',
|
||||
'jis',
|
||||
'ortho',
|
||||
'wkl',
|
||||
'tkl',
|
||||
'preonic',
|
||||
'planck',
|
||||
}
|
||||
|
||||
# Ignore tokens like 'split_3x7_4' or just '2x4'
|
||||
layout = re.sub(r"_split_\d+x\d+_\d+", '', layout)
|
||||
layout = re.sub(r"_\d+x\d+", '', layout)
|
||||
|
||||
name_fragments = set(keyboard.split('/')) - safe_layout_tokens
|
||||
|
||||
return any(fragment in layout for fragment in name_fragments)
|
||||
|
||||
|
||||
def _valid_community_layout(layout):
|
||||
@ -60,10 +76,9 @@ def _validate(keyboard, info_data):
|
||||
_log_warning(info_data, '"LAYOUT_all" should be "LAYOUT" unless additional layouts are provided.')
|
||||
|
||||
# Extended layout name checks - ignoring community_layouts and "safe" values
|
||||
name_fragments = set(keyboard.split('/')) - SAFE_LAYOUT_TOKENS
|
||||
potential_layouts = set(layouts.keys()) - set(community_layouts_names)
|
||||
for layout in potential_layouts:
|
||||
if any(fragment in layout for fragment in name_fragments):
|
||||
if _keyboard_in_layout_name(keyboard, layout):
|
||||
_log_warning(info_data, f'Layout "{layout}" should not contain name of keyboard.')
|
||||
|
||||
# Filter out any non-existing community layouts
|
||||
|
@ -349,3 +349,13 @@ uint8_t layer_switch_get_layer(keypos_t key) {
|
||||
action_t layer_switch_get_action(keypos_t key) {
|
||||
return action_for_key(layer_switch_get_layer(key), key);
|
||||
}
|
||||
|
||||
layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_t layer2, uint8_t layer3) {
|
||||
layer_state_t mask12 = ((layer_state_t)1 << layer1) | ((layer_state_t)1 << layer2);
|
||||
layer_state_t mask3 = (layer_state_t)1 << layer3;
|
||||
return (state & mask12) == mask12 ? (state | mask3) : (state & ~mask3);
|
||||
}
|
||||
|
||||
void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) {
|
||||
layer_state_set(update_tri_layer_state(layer_state, layer1, layer2, layer3));
|
||||
}
|
||||
|
@ -113,6 +113,25 @@ void layer_and(layer_state_t state);
|
||||
void layer_xor(layer_state_t state);
|
||||
layer_state_t layer_state_set_user(layer_state_t state);
|
||||
layer_state_t layer_state_set_kb(layer_state_t state);
|
||||
|
||||
/**
|
||||
* @brief Applies the tri layer to global layer state. Not be used in layer_state_set_(kb|user) functions.
|
||||
*
|
||||
* @param layer1 First layer to check for tri layer
|
||||
* @param layer2 Second layer to check for tri layer
|
||||
* @param layer3 Layer to activate if both other layers are enabled
|
||||
*/
|
||||
void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3);
|
||||
/**
|
||||
* @brief Applies the tri layer behavior to supplied layer bitmask, without using layer functions.
|
||||
*
|
||||
* @param state Original layer bitmask to check and modify
|
||||
* @param layer1 First layer to check for tri layer
|
||||
* @param layer2 Second layer to check for tri layer
|
||||
* @param layer3 Layer to activate if both other layers are enabled
|
||||
* @return layer_state_t returns a modified layer bitmask with tri layer modifications applied
|
||||
*/
|
||||
layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_t layer2, uint8_t layer3);
|
||||
#else
|
||||
# define layer_state 0
|
||||
|
||||
@ -131,6 +150,8 @@ layer_state_t layer_state_set_kb(layer_state_t state);
|
||||
# define layer_xor(state) (void)state
|
||||
# define layer_state_set_kb(state) (void)state
|
||||
# define layer_state_set_user(state) (void)state
|
||||
# define update_tri_layer(layer1, layer2, layer3)
|
||||
# define update_tri_layer_state(state, layer1, layer2, layer3) (void)state
|
||||
#endif
|
||||
|
||||
/* pressed actions cache */
|
||||
|
@ -717,6 +717,8 @@ enum qk_keycode_defines {
|
||||
QK_AUTOCORRECT_ON = 0x7C74,
|
||||
QK_AUTOCORRECT_OFF = 0x7C75,
|
||||
QK_AUTOCORRECT_TOGGLE = 0x7C76,
|
||||
QK_TRI_LAYER_LOWER = 0x7C77,
|
||||
QK_TRI_LAYER_UPPER = 0x7C78,
|
||||
SAFE_RANGE = 0x7E00,
|
||||
|
||||
// Alias
|
||||
@ -1282,6 +1284,8 @@ enum qk_keycode_defines {
|
||||
AC_ON = QK_AUTOCORRECT_ON,
|
||||
AC_OFF = QK_AUTOCORRECT_OFF,
|
||||
AC_TOGG = QK_AUTOCORRECT_TOGGLE,
|
||||
TL_LOWR = QK_TRI_LAYER_LOWER,
|
||||
TL_UPPR = QK_TRI_LAYER_UPPER,
|
||||
};
|
||||
|
||||
// Range Helpers
|
||||
@ -1333,4 +1337,4 @@ enum qk_keycode_defines {
|
||||
#define IS_MACRO_KEYCODE(code) ((code) >= QK_MACRO_0 && (code) <= QK_MACRO_31)
|
||||
#define IS_BACKLIGHT_KEYCODE(code) ((code) >= QK_BACKLIGHT_ON && (code) <= QK_BACKLIGHT_TOGGLE_BREATHING)
|
||||
#define IS_RGB_KEYCODE(code) ((code) >= RGB_TOG && (code) <= RGB_MODE_TWINKLE)
|
||||
#define IS_QUANTUM_KEYCODE(code) ((code) >= QK_BOOTLOADER && (code) <= QK_AUTOCORRECT_TOGGLE)
|
||||
#define IS_QUANTUM_KEYCODE(code) ((code) >= QK_BOOTLOADER && (code) <= QK_TRI_LAYER_UPPER)
|
||||
|
30
quantum/process_keycode/process_tri_layer.c
Normal file
30
quantum/process_keycode/process_tri_layer.c
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2023 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "process_tri_layer.h"
|
||||
#include "tri_layer.h"
|
||||
#include "action_layer.h"
|
||||
|
||||
bool process_tri_layer(uint16_t keycode, keyrecord_t *record) {
|
||||
switch (keycode) {
|
||||
case QK_TRI_LAYER_LOWER:
|
||||
if (record->event.pressed) {
|
||||
layer_on(get_tri_layer_lower_layer());
|
||||
update_tri_layer(get_tri_layer_lower_layer(), get_tri_layer_upper_layer(), get_tri_layer_adjust_layer());
|
||||
} else {
|
||||
layer_off(get_tri_layer_lower_layer());
|
||||
update_tri_layer(get_tri_layer_lower_layer(), get_tri_layer_upper_layer(), get_tri_layer_adjust_layer());
|
||||
}
|
||||
return false;
|
||||
case QK_TRI_LAYER_UPPER:
|
||||
if (record->event.pressed) {
|
||||
layer_on(get_tri_layer_upper_layer());
|
||||
update_tri_layer(get_tri_layer_lower_layer(), get_tri_layer_upper_layer(), get_tri_layer_adjust_layer());
|
||||
} else {
|
||||
layer_off(get_tri_layer_upper_layer());
|
||||
update_tri_layer(get_tri_layer_lower_layer(), get_tri_layer_upper_layer(), get_tri_layer_adjust_layer());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
16
quantum/process_keycode/process_tri_layer.h
Normal file
16
quantum/process_keycode/process_tri_layer.h
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright 2023 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "action.h"
|
||||
|
||||
/**
|
||||
* @brief Handles tri layer behavior
|
||||
*
|
||||
* @param keycode the keycode
|
||||
* @param record the key record structure
|
||||
* @return true continue handling keycodes
|
||||
* @return false stop handling keycodes
|
||||
*/
|
||||
bool process_tri_layer(uint16_t keycode, keyrecord_t *record);
|
@ -342,6 +342,9 @@ bool process_record_quantum(keyrecord_t *record) {
|
||||
#endif
|
||||
#ifdef AUTOCORRECT_ENABLE
|
||||
process_autocorrect(keycode, record) &&
|
||||
#endif
|
||||
#ifdef TRI_LAYER_ENABLE
|
||||
process_tri_layer(keycode, record) &&
|
||||
#endif
|
||||
true)) {
|
||||
return false;
|
||||
@ -443,16 +446,6 @@ void set_single_persistent_default_layer(uint8_t default_layer) {
|
||||
default_layer_set((layer_state_t)1 << default_layer);
|
||||
}
|
||||
|
||||
layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_t layer2, uint8_t layer3) {
|
||||
layer_state_t mask12 = ((layer_state_t)1 << layer1) | ((layer_state_t)1 << layer2);
|
||||
layer_state_t mask3 = (layer_state_t)1 << layer3;
|
||||
return (state & mask12) == mask12 ? (state | mask3) : (state & ~mask3);
|
||||
}
|
||||
|
||||
void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) {
|
||||
layer_state_set(update_tri_layer_state(layer_state, layer1, layer2, layer3));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Override these functions in your keymap file to play different tunes on
|
||||
// different events such as startup and bootloader jump
|
||||
|
@ -244,9 +244,10 @@ extern layer_state_t layer_state;
|
||||
# include "process_autocorrect.h"
|
||||
#endif
|
||||
|
||||
// For tri-layer
|
||||
void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3);
|
||||
layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_t layer2, uint8_t layer3);
|
||||
#ifdef TRI_LAYER_ENABLE
|
||||
# include "tri_layer.h"
|
||||
# include "process_tri_layer.h"
|
||||
#endif
|
||||
|
||||
void set_single_persistent_default_layer(uint8_t default_layer);
|
||||
|
||||
|
39
quantum/tri_layer.c
Normal file
39
quantum/tri_layer.c
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright 2023 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "tri_layer.h"
|
||||
#include <stdint.h>
|
||||
|
||||
static uint8_t tri_layer_lower_layer = TRI_LAYER_LOWER_LAYER;
|
||||
static uint8_t tri_layer_upper_layer = TRI_LAYER_UPPER_LAYER;
|
||||
static uint8_t tri_layer_adjust_layer = TRI_LAYER_ADJUST_LAYER;
|
||||
|
||||
void set_tri_layer_lower_layer(uint8_t layer) {
|
||||
tri_layer_lower_layer = layer;
|
||||
}
|
||||
|
||||
void set_tri_layer_upper_layer(uint8_t layer) {
|
||||
tri_layer_upper_layer = layer;
|
||||
}
|
||||
|
||||
void set_tri_layer_adjust_layer(uint8_t layer) {
|
||||
tri_layer_adjust_layer = layer;
|
||||
}
|
||||
|
||||
void set_tri_layer_layers(uint8_t lower, uint8_t raise, uint8_t adjust) {
|
||||
tri_layer_lower_layer = lower;
|
||||
tri_layer_upper_layer = raise;
|
||||
tri_layer_adjust_layer = adjust;
|
||||
}
|
||||
|
||||
uint8_t get_tri_layer_lower_layer(void) {
|
||||
return tri_layer_lower_layer;
|
||||
}
|
||||
|
||||
uint8_t get_tri_layer_upper_layer(void) {
|
||||
return tri_layer_upper_layer;
|
||||
}
|
||||
|
||||
uint8_t get_tri_layer_adjust_layer(void) {
|
||||
return tri_layer_adjust_layer;
|
||||
}
|
59
quantum/tri_layer.h
Normal file
59
quantum/tri_layer.h
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright 2023 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef TRI_LAYER_LOWER_LAYER
|
||||
# define TRI_LAYER_LOWER_LAYER 1
|
||||
#endif
|
||||
#ifndef TRI_LAYER_UPPER_LAYER
|
||||
# define TRI_LAYER_UPPER_LAYER 2
|
||||
#endif
|
||||
#ifndef TRI_LAYER_ADJUST_LAYER
|
||||
# define TRI_LAYER_ADJUST_LAYER 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set the tri layer lower layer index
|
||||
*
|
||||
* @param layer
|
||||
*/
|
||||
void set_tri_layer_lower_layer(uint8_t layer);
|
||||
/**
|
||||
* @brief Set the tri layer upper layer index
|
||||
*
|
||||
* @param layer
|
||||
*/
|
||||
void set_tri_layer_upper_layer(uint8_t layer);
|
||||
/**
|
||||
* @brief Set the tri layer adjust layer index
|
||||
*
|
||||
* @param layer
|
||||
*/
|
||||
void set_tri_layer_adjust_layer(uint8_t layer);
|
||||
/**
|
||||
* @brief Set the tri layer indices
|
||||
*
|
||||
* @param lower
|
||||
* @param upper
|
||||
* @param adjust
|
||||
*/
|
||||
void set_tri_layer_layers(uint8_t lower, uint8_t upper, uint8_t adjust);
|
||||
/**
|
||||
* @brief Get the tri layer lower layer index
|
||||
*
|
||||
* @return uint8_t
|
||||
*/
|
||||
uint8_t get_tri_layer_lower_layer(void);
|
||||
/**
|
||||
* @brief Get the tri layer upper layer index
|
||||
*
|
||||
* @return uint8_t
|
||||
*/
|
||||
uint8_t get_tri_layer_upper_layer(void);
|
||||
/**
|
||||
* @brief Get the tri layer adjust layer index
|
||||
*
|
||||
* @return uint8_t
|
||||
*/
|
||||
uint8_t get_tri_layer_adjust_layer(void);
|
@ -659,5 +659,7 @@ std::map<uint16_t, std::string> KEYCODE_ID_TABLE = {
|
||||
{QK_AUTOCORRECT_ON, "QK_AUTOCORRECT_ON"},
|
||||
{QK_AUTOCORRECT_OFF, "QK_AUTOCORRECT_OFF"},
|
||||
{QK_AUTOCORRECT_TOGGLE, "QK_AUTOCORRECT_TOGGLE"},
|
||||
{QK_TRI_LAYER_LOWER, "QK_TRI_LAYER_LOWER"},
|
||||
{QK_TRI_LAYER_UPPER, "QK_TRI_LAYER_UPPER"},
|
||||
{SAFE_RANGE, "SAFE_RANGE"},
|
||||
};
|
||||
|
6
tests/tri_layer/config.h
Normal file
6
tests/tri_layer/config.h
Normal file
@ -0,0 +1,6 @@
|
||||
// Copyright 2021 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "test_common.h"
|
8
tests/tri_layer/test.mk
Normal file
8
tests/tri_layer/test.mk
Normal file
@ -0,0 +1,8 @@
|
||||
# Copyright 2021 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# --------------------------------------------------------------------------------
|
||||
# Keep this file, even if it is empty, as a marker that this folder contains tests
|
||||
# --------------------------------------------------------------------------------
|
||||
|
||||
TRI_LAYER_ENABLE = yes
|
103
tests/tri_layer/test_tri_layer.cpp
Normal file
103
tests/tri_layer/test_tri_layer.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
// Copyright 2021 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "test_common.hpp"
|
||||
|
||||
using testing::_;
|
||||
using testing::InSequence;
|
||||
|
||||
class TriLayer : public TestFixture {};
|
||||
|
||||
TEST_F(TriLayer, TriLayerLowerTest) {
|
||||
TestDriver driver;
|
||||
KeymapKey lower_layer_key = KeymapKey{0, 0, 0, QK_TRI_LAYER_LOWER};
|
||||
|
||||
set_keymap({lower_layer_key, KeymapKey{1, 0, 0, KC_TRNS}});
|
||||
|
||||
/* Press Lower. */
|
||||
EXPECT_NO_REPORT(driver);
|
||||
lower_layer_key.press();
|
||||
run_one_scan_loop();
|
||||
EXPECT_TRUE(layer_state_is(get_tri_layer_lower_layer()));
|
||||
EXPECT_FALSE(layer_state_is(get_tri_layer_upper_layer()));
|
||||
EXPECT_FALSE(layer_state_is(get_tri_layer_adjust_layer()));
|
||||
VERIFY_AND_CLEAR(driver);
|
||||
|
||||
/* Release Lower. */
|
||||
EXPECT_NO_REPORT(driver);
|
||||
lower_layer_key.release();
|
||||
run_one_scan_loop();
|
||||
EXPECT_FALSE(layer_state_is(get_tri_layer_lower_layer()));
|
||||
EXPECT_FALSE(layer_state_is(get_tri_layer_upper_layer()));
|
||||
EXPECT_FALSE(layer_state_is(get_tri_layer_adjust_layer()));
|
||||
VERIFY_AND_CLEAR(driver);
|
||||
}
|
||||
|
||||
TEST_F(TriLayer, TriLayerUpperTest) {
|
||||
TestDriver driver;
|
||||
KeymapKey upper_layer_key = KeymapKey{0, 0, 0, QK_TRI_LAYER_UPPER};
|
||||
|
||||
set_keymap({upper_layer_key, KeymapKey{2, 0, 0, KC_TRNS}});
|
||||
|
||||
/* Press Raise. */
|
||||
EXPECT_NO_REPORT(driver);
|
||||
upper_layer_key.press();
|
||||
run_one_scan_loop();
|
||||
EXPECT_FALSE(layer_state_is(get_tri_layer_lower_layer()));
|
||||
EXPECT_TRUE(layer_state_is(get_tri_layer_upper_layer()));
|
||||
EXPECT_FALSE(layer_state_is(get_tri_layer_adjust_layer()));
|
||||
VERIFY_AND_CLEAR(driver);
|
||||
|
||||
/* Release Raise. */
|
||||
EXPECT_NO_REPORT(driver);
|
||||
upper_layer_key.release();
|
||||
run_one_scan_loop();
|
||||
EXPECT_FALSE(layer_state_is(get_tri_layer_lower_layer()));
|
||||
EXPECT_FALSE(layer_state_is(get_tri_layer_upper_layer()));
|
||||
EXPECT_FALSE(layer_state_is(get_tri_layer_adjust_layer()));
|
||||
VERIFY_AND_CLEAR(driver);
|
||||
}
|
||||
|
||||
TEST_F(TriLayer, TriLayerAdjustTest) {
|
||||
TestDriver driver;
|
||||
KeymapKey lower_layer_key = KeymapKey{0, 0, 0, QK_TRI_LAYER_LOWER};
|
||||
KeymapKey upper_layer_key = KeymapKey{0, 1, 0, QK_TRI_LAYER_UPPER};
|
||||
|
||||
set_keymap({
|
||||
upper_layer_key,
|
||||
lower_layer_key,
|
||||
KeymapKey{1, 0, 0, KC_TRNS},
|
||||
KeymapKey{1, 1, 0, KC_TRNS},
|
||||
KeymapKey{2, 0, 0, KC_TRNS},
|
||||
KeymapKey{2, 1, 0, KC_TRNS},
|
||||
KeymapKey{3, 0, 0, KC_TRNS},
|
||||
KeymapKey{3, 1, 0, KC_TRNS},
|
||||
});
|
||||
|
||||
/* Press Lower, then upper, and release upper and then lower. */
|
||||
EXPECT_NO_REPORT(driver);
|
||||
lower_layer_key.press();
|
||||
run_one_scan_loop();
|
||||
EXPECT_TRUE(layer_state_is(get_tri_layer_lower_layer()));
|
||||
EXPECT_FALSE(layer_state_is(get_tri_layer_upper_layer()));
|
||||
EXPECT_FALSE(layer_state_is(get_tri_layer_adjust_layer()));
|
||||
|
||||
upper_layer_key.press();
|
||||
run_one_scan_loop();
|
||||
EXPECT_TRUE(layer_state_is(get_tri_layer_lower_layer()));
|
||||
EXPECT_TRUE(layer_state_is(get_tri_layer_upper_layer()));
|
||||
EXPECT_TRUE(layer_state_is(get_tri_layer_adjust_layer()));
|
||||
|
||||
lower_layer_key.release();
|
||||
run_one_scan_loop();
|
||||
EXPECT_FALSE(layer_state_is(get_tri_layer_lower_layer()));
|
||||
EXPECT_TRUE(layer_state_is(get_tri_layer_upper_layer()));
|
||||
EXPECT_FALSE(layer_state_is(get_tri_layer_adjust_layer()));
|
||||
|
||||
upper_layer_key.release();
|
||||
run_one_scan_loop();
|
||||
EXPECT_FALSE(layer_state_is(get_tri_layer_lower_layer()));
|
||||
EXPECT_FALSE(layer_state_is(get_tri_layer_upper_layer()));
|
||||
EXPECT_FALSE(layer_state_is(get_tri_layer_adjust_layer()));
|
||||
VERIFY_AND_CLEAR(driver);
|
||||
}
|
Loading…
Reference in New Issue
Block a user