commit
1e9ebe4ece
|
@ -0,0 +1,297 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX layout : COLEMAK JC Sticky Keys Mod
|
||||
* created by Ryan Prince
|
||||
* Description: This layout is designed for programming with a focus on
|
||||
* minimizing/elimnating the need to take the hands out of home-row position
|
||||
* to reach other keys. Layer sticky keys are used to reduce the average
|
||||
* number of keystrokes required to access keys in other layers. Some
|
||||
* redundancy of navigation and spacing keys is added to the left hand to
|
||||
* allow for greater one-handed access when using a mouse with the right
|
||||
* hand.
|
||||
* The alpha key layout is COLEMAK with sticky layer keys on the thumb
|
||||
* switches for a symbol layer and a ten-key/function
|
||||
* layer.
|
||||
* Modifiers are symetric on each hand with the exception of the Alt
|
||||
* key because my primary machine is a Mac which utilizes command and ctrl
|
||||
* for chorded shortcuts more frequenty than ctrl and alt. The layer sticky
|
||||
* keys compliment standard modifier sticky keys (for shift, ctrl, command,
|
||||
* alt) to allow fast touch typing with minimal chording in favor of
|
||||
* sequential keying (preferably on alternate hands) for multi-key shortcuts
|
||||
* as chording introduces strain and fatigue and takes your hands out of
|
||||
* home row position increasing the likelihood of mistyping.
|
||||
* Sticky keys for standard modifiers are used as an operating system setting
|
||||
* for the benefit of key state visualization, though this can interfere
|
||||
* with the kbfun_shift_press_release() behavior which implicitly adds the
|
||||
* shift down modifier to output symbols that require it without knowledge
|
||||
* of the virtual sticky state maintained by the operating system.
|
||||
* The ErgoDox Layout Configurator layout that best approximates the layout
|
||||
* defined in this file is available here:
|
||||
* https://www.massdrop.com/ext/ergodox/?referer=EAZJPJ&hash=f26761358ba99e21ae937173da512849
|
||||
* The differences are mainly the use of layer toggles instead of sticky
|
||||
* layer keys and many of the symbols add the kbfun_shift_press_release()
|
||||
* which is not accessible for all keys in the cofigurator (as of
|
||||
* 2013-04-10).
|
||||
* -----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>,
|
||||
* 2013 Ryan Prince <judascleric@gmail.com>
|
||||
* Released under The MIT License (MIT) (see "license.md")
|
||||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* -------------------------------------------------------------------------- */
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "../../../lib/data-types/misc.h"
|
||||
#include "../../../lib/usb/usage-page/keyboard--short-names.h"
|
||||
#include "../../../lib/key-functions/public.h"
|
||||
#include "../matrix.h"
|
||||
#include "../layout.h"
|
||||
// FUNCTIONS ------------------------------------------------------------------
|
||||
void kbfun_layer_pop_all(void) {
|
||||
kbfun_layer_pop_1();
|
||||
kbfun_layer_pop_2();
|
||||
kbfun_layer_pop_3();
|
||||
kbfun_layer_pop_4();
|
||||
kbfun_layer_pop_5();
|
||||
kbfun_layer_pop_6();
|
||||
kbfun_layer_pop_7();
|
||||
kbfun_layer_pop_8();
|
||||
kbfun_layer_pop_9();
|
||||
kbfun_layer_pop_10();
|
||||
}
|
||||
|
||||
// DEFINITIONS ----------------------------------------------------------------
|
||||
#define kprrel &kbfun_press_release
|
||||
#define kprpst &kbfun_press_release_preserve_sticky
|
||||
#define ktrans &kbfun_transparent
|
||||
#define lpush1 &kbfun_layer_push_1
|
||||
#define lpush2 &kbfun_layer_push_2
|
||||
#define lsticky1 &kbfun_layer_sticky_1
|
||||
#define lsticky2 &kbfun_layer_sticky_2
|
||||
#define lpop &kbfun_layer_pop_all
|
||||
#define lpop1 &kbfun_layer_pop_1
|
||||
#define lpop2 &kbfun_layer_pop_2
|
||||
#define dbtldr &kbfun_jump_to_bootloader
|
||||
#define sshprre &kbfun_shift_press_release
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// LAYOUT ---------------------------------------------------------------------
|
||||
const uint8_t PROGMEM _kb_layout[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
|
||||
// LAYER 0
|
||||
KB_MATRIX_LAYER(
|
||||
// unused
|
||||
0,
|
||||
// left hand
|
||||
KEY_GraveAccent_Tilde, KEY_1_Exclamation, KEY_2_At, KEY_3_Pound, KEY_4_Dollar, KEY_5_Percent, KEY_LeftBracket_LeftBrace,
|
||||
KEY_LeftControl, KEY_q_Q, KEY_w_W, KEY_f_F, KEY_p_P, KEY_g_G, KEY_Equal_Plus,
|
||||
KEY_LeftShift, KEY_a_A, KEY_r_R, KEY_s_S, KEY_t_T, KEY_d_D,
|
||||
KEY_LeftGUI, KEY_z_Z, KEY_x_X, KEY_c_C, KEY_v_V, KEY_b_B, 0,
|
||||
KEY_Home, KEY_End, KEY_PageUp, KEY_PageDown, 1,
|
||||
KEY_Tab, KEY_Spacebar,
|
||||
0, 0, KEY_ReturnEnter,
|
||||
KEY_Escape, 2, KEY_LeftAlt,
|
||||
// right hand
|
||||
KEY_RightBracket_RightBrace, KEY_6_Caret, KEY_7_Ampersand, KEY_8_Asterisk, KEY_9_LeftParenthesis, KEY_0_RightParenthesis, KEY_Backslash_Pipe,
|
||||
KEY_Dash_Underscore, KEY_j_J, KEY_l_L, KEY_u_U, KEY_y_Y, KEY_Semicolon_Colon, KEY_RightControl,
|
||||
KEY_h_H, KEY_n_N, KEY_e_E, KEY_i_I, KEY_o_O, KEY_RightShift,
|
||||
2, KEY_k_K, KEY_m_M, KEY_Comma_LessThan, KEY_Period_GreaterThan, KEY_Slash_Question, KEY_RightGUI,
|
||||
1, KEY_DownArrow, KEY_UpArrow, KEY_LeftArrow, KEY_RightArrow,
|
||||
KEY_Insert, KEY_DeleteForward,
|
||||
0, 0, 0,
|
||||
KEY_DeleteBackspace, KEY_ReturnEnter, KEY_Spacebar
|
||||
),
|
||||
// LAYER 1
|
||||
KB_MATRIX_LAYER(
|
||||
// unused
|
||||
0,
|
||||
// left hand
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, KEY_1_Exclamation, KEY_2_At, KEY_3_Pound, KEY_4_Dollar, KEY_5_Percent, 0,
|
||||
0, KEY_SingleQuote_DoubleQuote, 0x34, 0x2F, 0x30, KEY_Equal_Plus,
|
||||
0, 0x31, KEY_Backslash_Pipe, KEY_Dash_Underscore, KEY_DeleteForward, KEY_DeleteBackspace, 0,
|
||||
KEY_LeftArrow, KEY_RightArrow, KEY_UpArrow, KEY_DownArrow, 0,
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0,
|
||||
// right hand
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, KEY_6_Caret, KEY_7_Ampersand, KEYPAD_Asterisk, KEYPAD_Minus, KEY_GraveAccent_Tilde, 0,
|
||||
KEYPAD_Plus, KEY_9_LeftParenthesis, KEY_0_RightParenthesis, KEY_LeftBracket_LeftBrace, KEY_RightBracket_RightBrace, 0,
|
||||
0, KEY_GraveAccent_Tilde, KEY_DownArrow, KEY_UpArrow, KEY_LeftArrow, KEY_RightArrow, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0
|
||||
),
|
||||
// LAYER 2
|
||||
KB_MATRIX_LAYER(
|
||||
// unused
|
||||
0,
|
||||
// left hand
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, KEY_F9, KEY_F10, KEY_F11, KEY_F12, KEY_VolumeUp, 0,
|
||||
0, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_VolumeDown,
|
||||
0, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_Mute, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0,
|
||||
// right hand
|
||||
0, 0, KEYPAD_NumLock_Clear, KEYPAD_Asterisk, KEYPAD_Slash, KEY_5_Percent, 0,
|
||||
0, KEYPAD_Minus, KEYPAD_7_Home, KEYPAD_8_UpArrow, KEYPAD_9_PageUp, KEYPAD_Plus, 0,
|
||||
KEYPAD_Equal, KEYPAD_4_LeftArrow, KEYPAD_5, KEYPAD_6_RightArrow, KEYPAD_0_Insert, 0,
|
||||
0, KEY_Comma_LessThan, KEYPAD_1_End, KEYPAD_2_DownArrow, KEYPAD_3_PageDown, KEYPAD_Period_Delete, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0
|
||||
),
|
||||
};
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// PRESS ----------------------------------------------------------------------
|
||||
const void_funptr_t PROGMEM _kb_layout_press[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
|
||||
// LAYER 0
|
||||
KB_MATRIX_LAYER(
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, lpop,
|
||||
kprrel, kprrel, kprrel, kprrel, lsticky1,
|
||||
kprrel, kprrel,
|
||||
NULL, NULL, kprrel,
|
||||
kprrel, lsticky2, kprrel,
|
||||
// right hand
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
lsticky2, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
lsticky1, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel,
|
||||
lpop, NULL, NULL,
|
||||
kprrel, kprrel, kprrel
|
||||
),
|
||||
// LAYER 1
|
||||
KB_MATRIX_LAYER(
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, sshprre, sshprre, sshprre, sshprre, sshprre, ktrans,
|
||||
ktrans, kprrel, sshprre, sshprre, sshprre, kprrel,
|
||||
ktrans, sshprre, kprrel, sshprre, kprrel, kprrel, ktrans,
|
||||
kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans,
|
||||
NULL, NULL, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
// right hand
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, sshprre, sshprre, kprrel, kprrel, kprrel, ktrans,
|
||||
kprrel, sshprre, sshprre, kprrel, kprrel, ktrans,
|
||||
ktrans, sshprre, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans,
|
||||
ktrans, NULL, NULL,
|
||||
ktrans, ktrans, ktrans
|
||||
),
|
||||
// LAYER 2
|
||||
KB_MATRIX_LAYER(
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans,
|
||||
NULL, NULL, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
// right hand
|
||||
dbtldr, kprrel, kprrel, kprrel, kprrel, sshprre, ktrans,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans,
|
||||
ktrans, NULL, NULL,
|
||||
ktrans, ktrans, ktrans
|
||||
),
|
||||
};
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// RELEASE --------------------------------------------------------------------
|
||||
const void_funptr_t PROGMEM _kb_layout_release[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
|
||||
// LAYER 0
|
||||
KB_MATRIX_LAYER(
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, NULL,
|
||||
kprrel, kprrel, kprrel, kprrel, lsticky1,
|
||||
kprrel, kprrel,
|
||||
NULL, NULL, kprrel,
|
||||
kprrel, lsticky2, kprrel,
|
||||
// right hand
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
lsticky2, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
lsticky1, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel,
|
||||
NULL, NULL, NULL,
|
||||
kprrel, kprrel, kprrel
|
||||
),
|
||||
// LAYER 1
|
||||
KB_MATRIX_LAYER(
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, sshprre, sshprre, sshprre, sshprre, sshprre, ktrans,
|
||||
ktrans, kprrel, sshprre, sshprre, sshprre, kprrel,
|
||||
kprrel, sshprre, kprrel, sshprre, kprrel, kprrel, ktrans,
|
||||
kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans,
|
||||
NULL, NULL, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
// right hand
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, sshprre, sshprre, kprrel, kprrel, kprrel, ktrans,
|
||||
kprrel, sshprre, sshprre, kprrel, kprrel, ktrans,
|
||||
ktrans, sshprre, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans,
|
||||
ktrans, NULL, NULL,
|
||||
ktrans, ktrans, ktrans
|
||||
),
|
||||
// LAYER 2
|
||||
KB_MATRIX_LAYER(
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans,
|
||||
NULL, NULL, ktrans,
|
||||
kprrel, ktrans, ktrans,
|
||||
// right hand
|
||||
NULL, kprrel, kprrel, kprrel, kprrel, sshprre, ktrans,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans,
|
||||
ktrans, NULL, NULL,
|
||||
ktrans, ktrans, ktrans
|
||||
),
|
||||
};
|
||||
// ----------------------------------------------------------------------------
|
|
@ -0,0 +1,30 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX : layout : DEFAULT : exports
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (MIT) (see "license.md")
|
||||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef KEYBOARD__ERGODOX__LAYOUT__DEFAULT_h
|
||||
#define KEYBOARD__ERGODOX__LAYOUT__DEFAULT_h
|
||||
|
||||
#include "../controller.h"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#define kb_led_num_on() _kb_led_1_on()
|
||||
#define kb_led_num_off() _kb_led_1_off()
|
||||
#define kb_led_caps_on() _kb_led_2_on()
|
||||
#define kb_led_caps_off() _kb_led_2_off()
|
||||
#define kb_led_scroll_on() _kb_led_3_on()
|
||||
#define kb_led_scroll_off() _kb_led_3_off()
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include "./default--led-control.h"
|
||||
#include "./default--matrix-control.h"
|
||||
|
||||
#endif
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
// basic
|
||||
void kbfun_press_release (void);
|
||||
void kbfun_press_release_preserve_sticky (void);
|
||||
void kbfun_toggle (void);
|
||||
void kbfun_transparent (void);
|
||||
// --- layer push/pop functions
|
||||
|
@ -30,6 +31,16 @@
|
|||
void kbfun_layer_push_8 (void);
|
||||
void kbfun_layer_push_9 (void);
|
||||
void kbfun_layer_push_10 (void);
|
||||
void kbfun_layer_sticky_1 (void);
|
||||
void kbfun_layer_sticky_2 (void);
|
||||
void kbfun_layer_sticky_3 (void);
|
||||
void kbfun_layer_sticky_4 (void);
|
||||
void kbfun_layer_sticky_5 (void);
|
||||
void kbfun_layer_sticky_6 (void);
|
||||
void kbfun_layer_sticky_7 (void);
|
||||
void kbfun_layer_sticky_8 (void);
|
||||
void kbfun_layer_sticky_9 (void);
|
||||
void kbfun_layer_sticky_10 (void);
|
||||
void kbfun_layer_pop_1 (void);
|
||||
void kbfun_layer_pop_2 (void);
|
||||
void kbfun_layer_pop_3 (void);
|
||||
|
|
|
@ -36,6 +36,27 @@
|
|||
* Generate a normal keypress or keyrelease
|
||||
*/
|
||||
void kbfun_press_release(void) {
|
||||
if (!main_arg_trans_key_pressed)
|
||||
main_arg_any_non_trans_key_pressed = true;
|
||||
kbfun_press_release_preserve_sticky();
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Press|Release and preserve top layer sticky key state
|
||||
*
|
||||
* [description]
|
||||
* Generate a normal keypress or keyrelease
|
||||
* While basing the sticky key state transition on whether
|
||||
* kbfun_press_release() was called after kbfun_transparent() generally
|
||||
* works in practice, it is not always the desired behavior. One of the
|
||||
* benefits of sticky keys is avoiding key chording, so we want to make sure
|
||||
* that standard modifiers do not interrupt the sticky key cycle. Use
|
||||
* kbfun_press_release_preserve_sticky() if you want to define a standard
|
||||
* modifier key (shift, control, alt, gui) on the sticky layer instead of
|
||||
* defining the key to be transparent for the layer.
|
||||
*/
|
||||
void kbfun_press_release_preserve_sticky(void) {
|
||||
uint8_t keycode = kb_layout_get(LAYER, ROW, COL);
|
||||
_kbfun_press_release(IS_PRESSED, keycode);
|
||||
}
|
||||
|
@ -65,6 +86,7 @@ void kbfun_toggle(void) {
|
|||
* active
|
||||
*/
|
||||
void kbfun_transparent(void) {
|
||||
main_arg_trans_key_pressed = true;
|
||||
LAYER_OFFSET++;
|
||||
LAYER = main_layers_peek(LAYER_OFFSET);
|
||||
main_layers_pressed[ROW][COL] = LAYER;
|
||||
|
@ -76,12 +98,61 @@ void kbfun_transparent(void) {
|
|||
* layer push/pop functions
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
static layer_ids[MAX_LAYER_PUSH_POP_FUNCTIONS];
|
||||
// While there are only MAX_LAYER_PUSH_POP_FUNCTIONS number of layer functions,
|
||||
// there are 1 + MAX_LAYER_PUSH_POP_FUNCTIONS layer ids because we still have
|
||||
// layer 0 even if we will never have a push or pop function for it
|
||||
static uint8_t layer_ids[1 + MAX_LAYER_PUSH_POP_FUNCTIONS];
|
||||
|
||||
static void layer_push(uint8_t local_id) {
|
||||
uint8_t keycode = kb_layout_get(LAYER, ROW, COL);
|
||||
main_layers_pop_id(layer_ids[local_id]);
|
||||
layer_ids[local_id] = main_layers_push(keycode);
|
||||
// Only the topmost layer on the stack should be in sticky once state, pop
|
||||
// the top layer if it is in sticky once state
|
||||
uint8_t topSticky = main_layers_peek_sticky(0);
|
||||
if (topSticky == eStickyOnceDown || topSticky == eStickyOnceUp) {
|
||||
main_layers_pop_id(main_layers_peek(0));
|
||||
}
|
||||
layer_ids[local_id] = main_layers_push(keycode, eStickyNone);
|
||||
}
|
||||
|
||||
static void layer_sticky(uint8_t local_id) {
|
||||
uint8_t keycode = kb_layout_get(LAYER, ROW, COL);
|
||||
if (IS_PRESSED) {
|
||||
uint8_t topLayer = main_layers_peek(0);
|
||||
uint8_t topSticky = main_layers_peek_sticky(0);
|
||||
main_layers_pop_id(layer_ids[local_id]);
|
||||
if (topLayer == local_id) {
|
||||
if (topSticky == eStickyOnceUp)
|
||||
layer_ids[local_id] = main_layers_push(keycode, eStickyLock);
|
||||
}
|
||||
else
|
||||
{
|
||||
// only the topmost layer on the stack should be in sticky once state
|
||||
if (topSticky == eStickyOnceDown || topSticky == eStickyOnceUp) {
|
||||
main_layers_pop_id(layer_ids[topLayer]);
|
||||
}
|
||||
layer_ids[local_id] = main_layers_push(keycode, eStickyOnceDown);
|
||||
// this should be the only place we care about this flag being cleared
|
||||
main_arg_any_non_trans_key_pressed = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t topLayer = main_layers_peek(0);
|
||||
uint8_t topSticky = main_layers_peek_sticky(0);
|
||||
if (topLayer == local_id) {
|
||||
if (topSticky == eStickyOnceDown) {
|
||||
// When releasing this sticky key, pop the layer always
|
||||
main_layers_pop_id(layer_ids[local_id]);
|
||||
if (!main_arg_any_non_trans_key_pressed) {
|
||||
// If no key defined for this layer (a non-transparent key)
|
||||
// was pressed, push the layer again, but in the
|
||||
// StickyOnceUp state
|
||||
layer_ids[local_id] = main_layers_push(keycode, eStickyOnceUp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void layer_pop(uint8_t local_id) {
|
||||
|
@ -101,6 +172,45 @@ void kbfun_layer_push_1(void) {
|
|||
layer_push(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer sticky cycle #1
|
||||
*
|
||||
* [description]
|
||||
* This function gives similar behavior to sticky keys for modifiers available
|
||||
* on most operating systems. It is considered an accessibility feature
|
||||
* because it alleviates the user from having to hold down modifiers while
|
||||
* pressing a key to produce the modified key function. It is useful for fast
|
||||
* touch typing because you can avoid chording motions which both strain your
|
||||
* hands and take your hands out of home-row position while pressing normal
|
||||
* alpha keys.
|
||||
* This function emulates the 3-state behavior which is default on OS X and
|
||||
* optional in Windows where the modifier cycles between Off->Once->Locked
|
||||
* states. This is particularly handy for symbol layers where you typically
|
||||
* only type one symbol before you want to return to unmodified typing (layer
|
||||
* 0), e.g. 'if (condition) { a = "b" + "c"; }'. If you assign a symbol layer
|
||||
* to a thumb key as a layer sticky cycle, you can type the entire line of
|
||||
* code without taking your hands out of home row position and you do not need
|
||||
* to toggle off the layer after each symbol is pressed, only immediately
|
||||
* before keying the symbol.
|
||||
* The exact behavior of the layer sticky cycle function is defined as follows
|
||||
* for each state:
|
||||
* 1) One time down (set on key press) - The layer was not active and the key
|
||||
* has been pressed but not yet released. The layer is pushed in the one
|
||||
* time down state.
|
||||
* 2) One time up (set on key release) - The layer was active when the layer
|
||||
* sticky key was released. If a key on this layer (not set to
|
||||
* transparent) was pressed before the key was released, the layer will be
|
||||
* popped. If a non-transparent key was not pressed, the layer is popped
|
||||
* and pushed again in the one time up state.
|
||||
* 3) Locked (set on key press) - The layer was active and in the one time up
|
||||
* state when the layer sticky key was pressed again. The layer will be
|
||||
* popped if the function is invoked on a subsequent keypress.
|
||||
*/
|
||||
void kbfun_layer_sticky_1 (void) {
|
||||
layer_sticky(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer pop #1
|
||||
|
@ -126,6 +236,17 @@ void kbfun_layer_push_2(void) {
|
|||
layer_push(2);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer sticky cycle #2
|
||||
*
|
||||
* [description]
|
||||
* See the description of kbfun_layer_sticky_1()
|
||||
*/
|
||||
void kbfun_layer_sticky_2 (void) {
|
||||
layer_sticky(2);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer pop #2
|
||||
|
@ -151,6 +272,17 @@ void kbfun_layer_push_3(void) {
|
|||
layer_push(3);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer sticky cycle #3
|
||||
*
|
||||
* [description]
|
||||
* See the description of kbfun_layer_sticky_1()
|
||||
*/
|
||||
void kbfun_layer_sticky_3 (void) {
|
||||
layer_sticky(3);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer pop #3
|
||||
|
@ -176,6 +308,17 @@ void kbfun_layer_push_4(void) {
|
|||
layer_push(4);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer sticky cycle #4
|
||||
*
|
||||
* [description]
|
||||
* See the description of kbfun_layer_sticky_1()
|
||||
*/
|
||||
void kbfun_layer_sticky_4 (void) {
|
||||
layer_sticky(4);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer pop #4
|
||||
|
@ -201,6 +344,17 @@ void kbfun_layer_push_5(void) {
|
|||
layer_push(5);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer sticky cycle #5
|
||||
*
|
||||
* [description]
|
||||
* See the description of kbfun_layer_sticky_1()
|
||||
*/
|
||||
void kbfun_layer_sticky_5 (void) {
|
||||
layer_sticky(5);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer pop #5
|
||||
|
@ -226,6 +380,17 @@ void kbfun_layer_push_6(void) {
|
|||
layer_push(6);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer sticky cycle #6
|
||||
*
|
||||
* [description]
|
||||
* See the description of kbfun_layer_sticky_1()
|
||||
*/
|
||||
void kbfun_layer_sticky_6 (void) {
|
||||
layer_sticky(6);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer pop #6
|
||||
|
@ -251,6 +416,17 @@ void kbfun_layer_push_7(void) {
|
|||
layer_push(7);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer sticky cycle #7
|
||||
*
|
||||
* [description]
|
||||
* See the description of kbfun_layer_sticky_1()
|
||||
*/
|
||||
void kbfun_layer_sticky_7 (void) {
|
||||
layer_sticky(7);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer pop #7
|
||||
|
@ -276,6 +452,17 @@ void kbfun_layer_push_8(void) {
|
|||
layer_push(8);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer sticky cycle #8
|
||||
*
|
||||
* [description]
|
||||
* See the description of kbfun_layer_sticky_1()
|
||||
*/
|
||||
void kbfun_layer_sticky_8 (void) {
|
||||
layer_sticky(8);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer pop #8
|
||||
|
@ -301,6 +488,17 @@ void kbfun_layer_push_9(void) {
|
|||
layer_push(9);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer sticky cycle #9
|
||||
*
|
||||
* [description]
|
||||
* See the description of kbfun_layer_sticky_1()
|
||||
*/
|
||||
void kbfun_layer_sticky_9 (void) {
|
||||
layer_sticky(9);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer pop #9
|
||||
|
@ -326,6 +524,17 @@ void kbfun_layer_push_10(void) {
|
|||
layer_push(10);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer sticky cycle #10
|
||||
*
|
||||
* [description]
|
||||
* See the description of kbfun_layer_sticky_1()
|
||||
*/
|
||||
void kbfun_layer_sticky_10 (void) {
|
||||
layer_sticky(10);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer pop #10
|
||||
|
@ -342,3 +551,4 @@ void kbfun_layer_pop_10(void) {
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ static inline void numpad_toggle_numlock(void) {
|
|||
void kbfun_layer_push_numpad(void) {
|
||||
uint8_t keycode = kb_layout_get(LAYER, ROW, COL);
|
||||
main_layers_pop_id(numpad_layer_id);
|
||||
numpad_layer_id = main_layers_push(keycode);
|
||||
numpad_layer_id = main_layers_push(keycode, eStickyNone);
|
||||
numpad_toggle_numlock();
|
||||
}
|
||||
|
||||
|
|
57
src/main.c
57
src/main.c
|
@ -30,6 +30,8 @@ bool (*main_kb_is_pressed)[KB_ROWS][KB_COLUMNS] = &_main_kb_is_pressed;
|
|||
static bool _main_kb_was_pressed[KB_ROWS][KB_COLUMNS];
|
||||
bool (*main_kb_was_pressed)[KB_ROWS][KB_COLUMNS] = &_main_kb_was_pressed;
|
||||
|
||||
static bool main_kb_was_transparent[KB_ROWS][KB_COLUMNS];
|
||||
|
||||
uint8_t main_layers_pressed[KB_ROWS][KB_COLUMNS];
|
||||
|
||||
uint8_t main_loop_row;
|
||||
|
@ -41,6 +43,8 @@ uint8_t main_arg_row;
|
|||
uint8_t main_arg_col;
|
||||
bool main_arg_is_pressed;
|
||||
bool main_arg_was_pressed;
|
||||
bool main_arg_any_non_trans_key_pressed;
|
||||
bool main_arg_trans_key_pressed;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
@ -90,8 +94,10 @@ int main(void) {
|
|||
if (is_pressed) {
|
||||
layer = main_layers_peek(0);
|
||||
main_layers_pressed[row][col] = layer;
|
||||
main_arg_trans_key_pressed = false;
|
||||
} else {
|
||||
layer = main_layers_pressed[row][col];
|
||||
main_arg_trans_key_pressed = main_kb_was_transparent[row][col];
|
||||
}
|
||||
|
||||
// set remaining vars, and "execute" key
|
||||
|
@ -99,6 +105,7 @@ int main(void) {
|
|||
main_arg_col = col;
|
||||
main_arg_layer_offset = 0;
|
||||
main_exec_key();
|
||||
main_kb_was_transparent[row][col] = main_arg_trans_key_pressed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -139,22 +146,6 @@ int main(void) {
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Exec key
|
||||
* - Execute the keypress or keyrelease function (if it exists) of the key at
|
||||
* the current possition.
|
||||
*/
|
||||
void main_exec_key(void) {
|
||||
void (*key_function)(void) =
|
||||
( (is_pressed)
|
||||
? kb_layout_press_get(layer, row, col)
|
||||
: kb_layout_release_get(layer, row, col) );
|
||||
|
||||
if (key_function)
|
||||
(*key_function)();
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Layer Functions
|
||||
* ----------------------------------------------------------------------------
|
||||
|
@ -170,6 +161,7 @@ void main_exec_key(void) {
|
|||
struct layers {
|
||||
uint8_t layer;
|
||||
uint8_t id;
|
||||
uint8_t sticky;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -178,6 +170,26 @@ struct layers layers[MAX_ACTIVE_LAYERS];
|
|||
uint8_t layers_head = 0;
|
||||
uint8_t layers_ids_in_use[MAX_ACTIVE_LAYERS] = {true};
|
||||
|
||||
/*
|
||||
* Exec key
|
||||
* - Execute the keypress or keyrelease function (if it exists) of the key at
|
||||
* the current possition.
|
||||
*/
|
||||
void main_exec_key(void) {
|
||||
void (*key_function)(void) =
|
||||
( (is_pressed)
|
||||
? kb_layout_press_get(layer, row, col)
|
||||
: kb_layout_release_get(layer, row, col) );
|
||||
|
||||
if (key_function)
|
||||
(*key_function)();
|
||||
|
||||
// If the current layer is in the sticky once up state and a key defined
|
||||
// for this layer (a non-transparent key) was pressed, pop the layer
|
||||
if (layers[layers_head].sticky == eStickyOnceUp && main_arg_any_non_trans_key_pressed)
|
||||
main_layers_pop_id(layers_head);
|
||||
}
|
||||
|
||||
/*
|
||||
* peek()
|
||||
*
|
||||
|
@ -195,6 +207,13 @@ uint8_t main_layers_peek(uint8_t offset) {
|
|||
return 0; // default, or error
|
||||
}
|
||||
|
||||
uint8_t main_layers_peek_sticky(uint8_t offset) {
|
||||
if (offset <= layers_head)
|
||||
return layers[layers_head - offset].sticky;
|
||||
|
||||
return 0; // default, or error
|
||||
}
|
||||
|
||||
/*
|
||||
* push()
|
||||
*
|
||||
|
@ -205,17 +224,19 @@ uint8_t main_layers_peek(uint8_t offset) {
|
|||
* - success: the id assigned to the newly added element
|
||||
* - failure: 0 (the stack was already full)
|
||||
*/
|
||||
uint8_t main_layers_push(uint8_t layer) {
|
||||
uint8_t main_layers_push(uint8_t layer, uint8_t sticky) {
|
||||
// look for an available id
|
||||
for (uint8_t id=1; id<MAX_ACTIVE_LAYERS; id++)
|
||||
for (uint8_t id=1; id<MAX_ACTIVE_LAYERS; id++) {
|
||||
// if one is found
|
||||
if (layers_ids_in_use[id] == false) {
|
||||
layers_ids_in_use[id] = true;
|
||||
layers_head++;
|
||||
layers[layers_head].layer = layer;
|
||||
layers[layers_head].id = id;
|
||||
layers[layers_head].sticky = sticky;
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
return 0; // default, or error
|
||||
}
|
||||
|
|
13
src/main.h
13
src/main.h
|
@ -16,6 +16,14 @@
|
|||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
typedef enum StickyState
|
||||
{
|
||||
eStickyNone,
|
||||
eStickyOnceDown,
|
||||
eStickyOnceUp,
|
||||
eStickyLock
|
||||
} StickyState;
|
||||
|
||||
extern bool (*main_kb_is_pressed)[KB_ROWS][KB_COLUMNS];
|
||||
extern bool (*main_kb_was_pressed)[KB_ROWS][KB_COLUMNS];
|
||||
|
||||
|
@ -30,13 +38,16 @@
|
|||
extern uint8_t main_arg_col;
|
||||
extern bool main_arg_is_pressed;
|
||||
extern bool main_arg_was_pressed;
|
||||
extern bool main_arg_any_non_trans_key_pressed;
|
||||
extern bool main_arg_trans_key_pressed;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
void main_exec_key (void);
|
||||
|
||||
uint8_t main_layers_peek (uint8_t offset);
|
||||
uint8_t main_layers_push (uint8_t layer);
|
||||
uint8_t main_layers_peek_sticky (uint8_t offset);
|
||||
uint8_t main_layers_push (uint8_t layer, uint8_t sticky);
|
||||
void main_layers_pop_id (uint8_t id);
|
||||
uint8_t main_layers_get_offset_id (uint8_t id);
|
||||
|
||||
|
|
Loading…
Reference in New Issue