2020 February 29 Breaking Changes Update (#8064)
[jackhill/qmk/firmware.git] / layouts / community / ergodox / townk_osx / keymap.c
1 #include QMK_KEYBOARD_H
2 #include "debug.h"
3 #include "action_layer.h"
4 #include "action_util.h"
5 #include "led.h"
6 #include "keymap.h"
7 #include "timer.h"
8
9 /*
10
11 # Why this Layout
12
13 This layout was based on Kinesis layout and other ErgoDox user layouts
14 available. It's target to be used on a MacOS but I'm pretty sure it can be
15 addapted to Windows and/or Linux easily.
16
17 ## Function Key
18
19 The `fn` key work almost like it would in any other keyboard with the exception
20 it has a semi-sticky behavior. What does that mean?
21
22 Well, if you press the `fn` and release it, the keyboard will be put on the
23 _function layout_ and the next key stroke will be processed as if the `fn` key
24 was pressed. Aftwards, the leyout get back to _normal_. If you hold `fn` and
25 press any other key, when you release them, the keyboard leyout is back to
26 _normal_.
27
28 While pressing the `fn` with the left hand and strikeing the other keys on the
29 right hand is farly easy, the same cannot being said for the other keys on the
30 left side. So, instead of trying to do contorcionism with my left hand, I
31 decided to do a semi-sticky version of `fn`. This way, I can press the `fn`
32 key with my pinky, release it and press the `1` key to issue an `F1` to the
33 operating system.
34
35 ## Key-Pad Key
36
37 The `key pad` key is a layout switch key. If pressed, it will put the keyboard
38 on the _key pad layout_ and stay there until key is pressed again.
39
40 This is used to make the keyboard behave mostly like a **num pad keyboard**.
41
42 ## Notes
43 - Regardless in which layout you are, keys from other layouts are not
44 accessible. This means that if you are on the _key pad layout_, the left hand
45 will be pretty much unusable.
46 Of course that like anything else, there are exceptions to this rule.
47 Modifiers should remain accessible throughout the layers.
48 - The _shift key_ is, like the _function key_, also configured to have a sticky
49 behavior.
50 - All sticky keys have a timeout of 3 seconds.
51
52 */
53 #define BASE 0
54 #define KEYPAD 1
55 #define FN 2
56
57 #define MACRO_TMUX_ESC 10
58 #define MACRO_TMUX_PASTE 11
59 #define MACRO_OSX_COPY 12
60 #define MACRO_OSX_PASTE 13
61
62 #define M_TESC M(MACRO_TMUX_ESC)
63 #define M_TPASTE M(MACRO_TMUX_PASTE)
64 #define M_OSXCPY M(MACRO_OSX_COPY)
65 #define M_OSXPST M(MACRO_OSX_PASTE)
66
67 const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
68 /* Keymap 0: Base Layer
69 *
70 * ,-----------------------------------------------------. ,-----------------------------------------------------.
71 * | `~ | 1 | 2 | 3 | 4 | 5 | ESC | | Pwr | 6 | 7 | 8 | 9 | 0 | - _ |
72 * |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
73 * | Tab | Q | W | E | R | T | F16 | | F17 | Y | U | I | O | P | = + |
74 * |-----------+------+------+------+------+------| Meh | | Meh |------+------+------+------+------+-----------|
75 * | \ (Ctrl) | A | S | D | F | G |------| |------| H | J | K | L | ; | ' " (Ctrl)|
76 * |-----------+------+------+------+------+------| F18 | | F19 |------+------+------+------+------+-----------|
77 * | LShift | Z | X | C | V | B | Hyper| | Hyper| N | M | , | . | / | RShift |
78 * `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
79 * | FN | KPAD |LCtrl | LAlt | LGui | | RGui | RAlt | RCtrl| KPAD | FN |
80 * `-----------------------------------' `-----------------------------------'
81 * ,-------------. ,-------------.
82 * | M(0) | M(1) | | M(2) | M(3) |
83 * ,------|------|------| |------+------+------.
84 * | | | Home | | PgUp | | |
85 * |Backsp| Del |------| |------| Enter| Space|
86 * | | | End | | PgDn | | |
87 * `--------------------' `--------------------'
88 *
89 * M(0) = Ctrk+A Esc
90 * (this is used to issue the Esc key to the Tmux application)
91 * M(1) = Ctrk+A P
92 * (this is used to issue the Paste key to the Tmux application)
93 * M(2) = Cmd+C
94 * M(3) = Cmd+V
95 */
96 [BASE]=LAYOUT_ergodox(//left half
97 KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_ESC,
98 KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, MEH_T(KC_F16),
99 CTL_T(KC_BSLS), KC_A, KC_S, KC_D, KC_F, KC_G,
100 KC_FN2, KC_Z, KC_X, KC_C, KC_V, KC_B, ALL_T(KC_F18),
101 KC_FN1, TG(KEYPAD), KC_LCTRL, KC_LALT, KC_LGUI,
102 M_TESC, M_TPASTE,
103 KC_HOME,
104 KC_BSPC, KC_DEL, KC_END,
105 //right half
106 KC_POWER, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
107 MEH_T(KC_F17), KC_Y, KC_U, KC_I, KC_O, KC_P, KC_EQL,
108 KC_H, KC_J, KC_K, KC_L, KC_SCLN, CTL_T(KC_QUOT),
109 ALL_T(KC_F19), KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_FN2,
110 KC_RGUI, KC_RALT, CTL_T(KC_LBRC), LT(KEYPAD, KC_RBRC), KC_FN1,
111 M_OSXCPY, M_OSXPST,
112 KC_PGUP,
113 KC_PGDN, KC_ENT, KC_SPC),
114
115 /* Keymap 1: KeyPad Layer
116 *
117 * ,-----------------------------------------------------. ,-----------------------------------------------------.
118 * | | | LClk | RClk | MClk | | | | BTab | Clear| / | * | ^ | ( | |
119 * |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
120 * | M.Accel 2 | |ScrlUp| U |ScrlDn| | | | Tab | 7 | 8 | 9 | + | ) | |
121 * |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------|
122 * | M.Accel 1 | | L | D | R | |------| |------| 4 | 5 | 6 | - | | |
123 * |-----------+------+------+------+------+------| | |Return|------+------+------+------+------+-----------|
124 * | M.Accel 0 | |ScrlL | |ScrlR | | | | | 1 | 2 | 3 | = | | |
125 * `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
126 * | | XXXX | | | | | 0 | . | , | XXXX | |
127 * `-----------------------------------' `-----------------------------------'
128 * ,-------------. ,-------------.
129 * | | | | | |
130 * ,------|------|------| |------+------+------.
131 * | | | | | | XXXX | |
132 * | | |------| |------| XXXX | |
133 * | | | | | | XXXX | |
134 * `--------------------' `--------------------'
135 */
136 [KEYPAD]=LAYOUT_ergodox(//left half
137 KC_NO, KC_NO, KC_MS_BTN1, KC_MS_BTN2, KC_MS_BTN3, KC_NO, KC_NO,
138 KC_MS_ACCEL2, KC_NO, KC_MS_WH_UP, KC_MS_U, KC_MS_WH_DOWN, KC_NO, KC_NO,
139 KC_MS_ACCEL1, KC_NO, KC_MS_L, KC_MS_D, KC_MS_R, KC_NO,
140 KC_MS_ACCEL0, KC_NO, KC_MS_WH_LEFT, KC_NO, KC_MS_WH_RIGHT, KC_NO, KC_NO,
141 KC_NO, KC_TRNS, KC_NO, KC_NO, KC_NO,
142 KC_NO, KC_NO,
143 KC_NO,
144 KC_NO, KC_NO, KC_NO,
145 //right half
146 LSFT(KC_TAB), KC_CLEAR, KC_KP_SLASH, KC_KP_ASTERISK, KC_CIRCUMFLEX, KC_LPRN, KC_NO,
147 KC_TAB, KC_KP_7, KC_KP_8, KC_KP_9, KC_KP_PLUS, KC_RPRN, KC_NO,
148 KC_KP_4, KC_KP_5, KC_KP_6, KC_KP_MINUS, KC_NO, KC_NO,
149 KC_KP_ENTER, KC_KP_1, KC_KP_2, KC_KP_3, KC_KP_EQUAL, KC_NO, KC_NO,
150 KC_KP_0, KC_KP_DOT, KC_KP_COMMA, KC_TRNS, KC_NO,
151 KC_NO, KC_NO,
152 KC_NO,
153 KC_NO, KC_TRNS, KC_NO),
154
155 /* Keymap 2: Functions Layer
156 *
157 * ,-----------------------------------------------------. ,-----------------------------------------------------.
158 * | | F1 | F2 | F3 | F4 | F5 | F6 | | F7 | F8 | F9 | F10 | F11 | F12 | Vol. Up |
159 * |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
160 * | | Stop | Rw | Rec | FF | | XXXX | | XXXX | | | | | | Vol. Down |
161 * |-----------+------+------+------+------+------| XXXX | | XXXX |------+------+------+------+------+-----------|
162 * | CapsLock | Eject| Prev | Play | Next | |------| |------| Left | Down | Up | Right| | Mute |
163 * |-----------+------+------+------+------+------| XXXX | | XXXX |------+------+------+------+------+-----------|
164 * | L Shift | | | | | | XXXX | | XXXX | | | | | | R Shift |
165 * `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
166 * | XXXXX | | XXXX | XXXX | XXXX | | XXXX | XXXX | XXXX | | XXXXX |
167 * `-----------------------------------' `-----------------------------------'
168 * ,-------------. ,-------------.
169 * | | | | | |
170 * ,------|------|------| |------+------+------.
171 * | | | | | | | |
172 * | | |------| |------| | |
173 * | | | | | | | |
174 * `--------------------' `--------------------'
175 *
176 * XXX = These keys are transparent keys that, when pressed, they issue the key from the previous layer.
177 */
178 [FN]=LAYOUT_ergodox(//left half
179 KC_NO, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6,
180 KC_NO, KC_MEDIA_STOP, KC_MEDIA_REWIND, KC_MEDIA_SELECT, KC_MEDIA_FAST_FORWARD, KC_NO, KC_TRNS,
181 KC_CAPS, KC_MEDIA_EJECT, KC_MEDIA_PREV_TRACK, KC_MEDIA_PLAY_PAUSE, KC_MEDIA_NEXT_TRACK, KC_NO,
182 KC_LSFT, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRNS,
183 KC_TRNS, KC_NO, KC_TRNS, KC_TRNS, KC_TRNS,
184 KC_NO, KC_NO,
185 KC_NO,
186 KC_NO, KC_NO, KC_NO,
187 //right half
188 KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_VOLU,
189 KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_VOLD,
190 KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT, KC_NO, KC_MUTE,
191 KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_RSFT,
192 KC_TRNS, KC_TRNS, KC_TRNS, KC_NO, KC_TRNS,
193 KC_NO, KC_NO,
194 KC_NO,
195 KC_NO, KC_NO, KC_NO)};
196
197 const uint16_t PROGMEM fn_actions[] = {
198 [1] = ACTION_LAYER_ONESHOT(FN),
199 [2] = ACTION_MODS_ONESHOT(MOD_LSFT), // Sticky shift light. Tap for the next keypress to be shifted. Hold for regular shift.
200 };
201
202 const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
203 // MACRODOWN only works in this function
204 switch(id) {
205 case MACRO_TMUX_ESC:
206 if (record->event.pressed) {
207 return MACRO(D(LCTRL), T(A), U(LCTRL), D(ESC), END);
208 }
209 return MACRO(U(ESC), END);
210 case MACRO_TMUX_PASTE:
211 if (record->event.pressed) {
212 return MACRO(D(LCTRL), T(A), U(LCTRL), D(P), END);
213 }
214 return MACRO(U(P), END);
215 case MACRO_OSX_COPY:
216 if (record->event.pressed) {
217 return MACRO(D(LGUI), D(C), END);
218 }
219 return MACRO(U(C), U(LGUI), END);
220 case MACRO_OSX_PASTE:
221 if (record->event.pressed) {
222 return MACRO(D(LGUI), D(V), END);
223 }
224 return MACRO(U(V), U(LGUI), END);
225 }
226 return MACRO_NONE;
227 };
228
229 // Runs just one time when the keyboard initializes.
230 void matrix_init_user(void) {
231 };
232
233 uint8_t current_layer = BASE;
234
235 // Runs constantly in the background, in a loop.
236 void matrix_scan_user(void) {
237 uint8_t layer = biton32(layer_state);
238
239 ergodox_led_all_off();
240 ergodox_led_all_set(LED_BRIGHTNESS_LO);
241
242 switch (layer) {
243 case BASE:
244 current_layer = BASE;
245 break;
246 case KEYPAD:
247 current_layer = KEYPAD;
248 break;
249 default:
250 // none
251 break;
252 }
253
254 // layer leds
255 if (current_layer == KEYPAD) {
256 ergodox_right_led_3_on();
257 }
258
259 // capslock
260 if (host_keyboard_leds() & (3<<USB_LED_CAPS_LOCK)) {
261 ergodox_right_led_1_on();
262 }
263
264 // Temporary leds
265
266 // The function layer takes over other layers and we need to reflect that on the leds.
267 // If the current layer is the BASE, we simply turn on the FN led, but if the current
268 // layer is the KEYPAD, than we must turn it off before turning on the FN led.
269 if (layer == FN && !has_oneshot_layer_timed_out()) {
270 ergodox_right_led_3_off();
271 ergodox_right_led_2_on();
272 }
273
274 // if the shifted is pressed I show the case led in a brighter color. This is nice to
275 // differenciate the shift from the capslock.
276 // Notice that I make sure that we're not using the shift on a chord shortcut (pressing
277 // shift togather with other modifiers).
278 if((keyboard_report->mods & (MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)) && // is shift pressed and there is no other
279 !(keyboard_report->mods & (~MOD_BIT(KC_LSFT) & ~MOD_BIT(KC_RSFT)))) || // modifier being pressed as well
280 (get_oneshot_mods() & (MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)) && !has_oneshot_mods_timed_out())) { // or the one shot shift didn't timed out
281 ergodox_right_led_1_set(LED_BRIGHTNESS_HI);
282 ergodox_right_led_1_on();
283 }
284 };