summaryrefslogtreecommitdiff
path: root/users
diff options
context:
space:
mode:
authorJonas Avellana <14019120+ninjonas@users.noreply.github.com>2019-09-02 08:40:01 -0600
committerDrashna Jaelre <drashna@live.com>2019-09-02 07:40:01 -0700
commitf2ea65db6b8834dcb2a21462f43c1d89add6b101 (patch)
tree1620e9abc8bb455754ea50fd2d27a9c714e7ce03 /users
parent0e153781f035876771dd421ac92136ff2897c7d9 (diff)
[keymap] ninjonas userspace and keymaps for hotdox, lily58, & pinky3 (#6649)
* [keyboard] introducing ninjonas userspace & keymaps for hotdox, lily58, and pinky3 * [fix(#6649)] removed M_EPRM and used builtin EEP_RST keycode as-per review. * [chore(#6649)] forgot to update keymap legend on lily58
Diffstat (limited to 'users')
-rw-r--r--users/ninjonas/.gitignore1
-rw-r--r--users/ninjonas/README.md85
-rw-r--r--users/ninjonas/config.h14
-rw-r--r--users/ninjonas/ninjonas.c68
-rw-r--r--users/ninjonas/ninjonas.h112
-rw-r--r--users/ninjonas/process_records.c98
-rw-r--r--users/ninjonas/process_records.h24
-rw-r--r--users/ninjonas/rules.mk18
-rw-r--r--users/ninjonas/tap_dances.c12
-rw-r--r--users/ninjonas/tap_dances.h22
10 files changed, 454 insertions, 0 deletions
diff --git a/users/ninjonas/.gitignore b/users/ninjonas/.gitignore
new file mode 100644
index 0000000000..c6df8c0139
--- /dev/null
+++ b/users/ninjonas/.gitignore
@@ -0,0 +1 @@
+secrets.c
diff --git a/users/ninjonas/README.md b/users/ninjonas/README.md
new file mode 100644
index 0000000000..82bd5f09a0
--- /dev/null
+++ b/users/ninjonas/README.md
@@ -0,0 +1,85 @@
+# QMK User Configuration for [ninjonas](https://github.com/ninjonas/qmk-yonas)
+Tired of copying and pasting the same macros and tap dances for all my keymaps. Utilizing user keymaps functionality.
+See: https://docs.qmk.fm/#/feature_userspace
+
+## [ninjonas.c](ninjonas.c)
+- ninjonas [QMK user configuration](https://github.com/qmk/qmk_firmware/blob/master/docs/feature_userspace.md)
+- On `keymap.c` include `ninjonas.h`
+ ```c
+ #include "ninjonas.h"
+ ```
+
+## Features
+### [Keys](ninjonas.h#L44)
+|Code | Description |
+|---|---|
+|K_LOCK | MacOS shortcut to execute lock command  + ctrl + Q |
+|K_CSCN | MacOS shortcut to copy a portion of the screen to the clipboard |
+
+### [Layers](ninjonas.h#L48)
+|Code | Description |
+|---|---|
+|LT_LOW | Tap for ENTER, hold for RAISE |
+|LT_FUNC | Tap for ENTER, hold for FUNCTIONS |
+|LT_RAI | Tap for SPACE, hold for LOWER |
+|LT_NUM | Tap for SPACE, hold for NUMBERS |
+|LT_LOW + LT_RAI | Hold for ADJUST |
+|L_LOWER | Dedicated key to momentarily toggle to use LOWER layer |
+
+### [Layout Blocks](ninjonas.h#L57)
+Predefined keyboard layout templates to speed up configuring split keyboards
+
+|Code | Description |
+|---|---|
+|QWERTY | Qwerty Layout |
+|DVORAK | Dvorak Layout |
+|COLEMAK | Colemak Layout |
+|NUM | Number Rows |
+|FUNC | Function Rows |
+|SYM | Symbol Rows \(When holding shift on numbers\) |
+|NAV | Navigation Cluster |
+|MOUSE | Mouse Cluster |
+|MEDIA | Media Cluster |
+|MOD | Modifier Cluster |
+
+### [Macros](process_records.c)
+|Code | Description |
+|---|---|
+|M_PYNV | macro to activate pyenv with the name `jira` |
+|M_MAKE | macro to send QMK make command to compile keyboard |
+|M_FLSH | macro to send QMK make command to compile keyboard with the correct bootloader |
+|M_VRSN | macro to send QMK version |
+|M_SHFT | Sends  + alt + shift to a keycode to activate [ShiftIt](https://github.com/fikovnik/ShiftIt) |
+|M_CODE | Opens [Visual Studio Code](https://code.visualstudio.com/) on current directory |
+
+### [Tap-Dance](tap_dances.h)
+|Code | Description |
+|---|---|
+|T_ESC | Tap once for ESC, double tap for CAPS_LOCK |
+|T_LBRC | Tap once for [, double for back browser |
+|T_RBRC | Tap once for ], double for forward browser |
+|T_TAB | Tap once for TAB, double for CTRL + TAB |
+|T_GRV | Tap once for GRV, double for  + GRV |
+|T_GUI | Tap once for , double to open spotlight |
+|T_W | Tap for W, double tap for  + W |
+|T_Q | Tap for Q, double tap for  + Q |
+
+### Secrets
+There's times where you have macros you don't want to share like emails, passwords 😱, & and private strings. Based off [drashna's secret macros](https://github.com/qmk/qmk_firmware/blob/master/users/drashna/readme_secrets.md), it's now possible to do this. All you need to do is create a `secrets.c` file. Below is an example of how this is used.
+
+```c
+// secrets.c
+#include "ninjonas.h"
+
+bool process_record_secrets(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ // Sends zoom URL
+ case M_ZOOM:
+ if (record->event.pressed) {
+ SEND_STRING("SECRET_STRING_HERE" SS_TAP(X_ENTER));
+ }
+ break;
+ }
+ return true;
+}
+``` \ No newline at end of file
diff --git a/users/ninjonas/config.h b/users/ninjonas/config.h
new file mode 100644
index 0000000000..1166939c65
--- /dev/null
+++ b/users/ninjonas/config.h
@@ -0,0 +1,14 @@
+#ifdef TAPPING_TERM
+ #undef TAPPING_TERM
+ #define TAPPING_TERM 200
+#endif
+
+// Mouse Settings: Smoothing out mouse movement on keypress
+#ifndef MOUSEKEY_INTERVAL
+ #undef MOUSEKEY_INTERVAL
+ #define MOUSEKEY_INTERVAL 16
+#endif
+#define MOUSEKEY_DELAY 0
+#define MOUSEKEY_TIME_TO_MAX 60
+#define MOUSEKEY_MAX_SPEED 7
+#define MOUSEKEY_WHEEL_DELAY 0 \ No newline at end of file
diff --git a/users/ninjonas/ninjonas.c b/users/ninjonas/ninjonas.c
new file mode 100644
index 0000000000..6a77ecf8b0
--- /dev/null
+++ b/users/ninjonas/ninjonas.c
@@ -0,0 +1,68 @@
+/* Copyright 2019 @ninjonas
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "ninjonas.h"
+
+layer_state_t layer_state_set_user (layer_state_t state) {
+ return update_tri_layer_state(state, _LOWER, _RAISE, _ADJUST);
+}
+
+// BEGIN: SSD1306OLED
+// SSD1306 OLED update loop, make sure to add #define SSD1306OLED in config.h
+#if defined(KEYBOARD_lily58_rev1) & defined(PROTOCOL_LUFA)
+extern uint8_t is_master;
+
+void matrix_init_user(void) {
+ //SSD1306 OLED init, make sure to add #define SSD1306OLED in config.h
+ iota_gfx_init(!has_usb()); // turns on the display
+}
+
+// When add source files to SRC in rules.mk, you can use functions.
+const char *read_layer_state(void);
+const char *read_logo(void);
+//void set_keylog(uint16_t keycode, keyrecord_t *record); // Moved to process_records.h
+const char *read_keylog(void);
+const char *read_keylogs(void);
+
+void matrix_scan_user(void) {
+ iota_gfx_task();
+}
+
+void matrix_render_user(struct CharacterMatrix *matrix) {
+ if (is_master) {
+ // If you want to change the display of OLED, you need to change here
+ matrix_write_ln(matrix, read_layer_state());
+ matrix_write_ln(matrix, read_keylog());
+ matrix_write_ln(matrix, read_keylogs());
+ } else {
+ matrix_write(matrix, read_logo());
+ }
+}
+
+void matrix_update(struct CharacterMatrix *dest, const struct CharacterMatrix *source) {
+ if (memcmp(dest->display, source->display, sizeof(dest->display))) {
+ memcpy(dest->display, source->display, sizeof(dest->display));
+ dest->dirty = true;
+ }
+}
+
+void iota_gfx_task_user(void) {
+ struct CharacterMatrix matrix;
+ matrix_clear(&matrix);
+ matrix_render_user(&matrix);
+ matrix_update(&display, &matrix);
+}
+#endif
+// END: SSD1306OLED \ No newline at end of file
diff --git a/users/ninjonas/ninjonas.h b/users/ninjonas/ninjonas.h
new file mode 100644
index 0000000000..50d7c36802
--- /dev/null
+++ b/users/ninjonas/ninjonas.h
@@ -0,0 +1,112 @@
+/* Copyright 2019 @ninjonas
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+#include "quantum.h"
+#include "version.h"
+#include "eeprom.h"
+#include "process_records.h"
+
+#ifdef TAP_DANCE_ENABLE
+ #include "tap_dances.h"
+#endif
+#if defined(KEYBOARD_lily58_rev1) & defined(PROTOCOL_LUFA)
+ #include "lufa.h"
+ #include "split_util.h"
+#endif
+#ifdef SSD1306OLED
+ #include "ssd1306.h"
+#endif
+
+#define _QWERTY 0
+#define _DVORAK 1
+#define _COLEMAK 2
+#define _LOWER 3
+#define _RAISE 4
+#define _ADJUST 5
+#ifdef KEYBOARD_pinky_3
+ #define _NUMBERS 6
+ #define _FUNCTIONS 7
+#endif
+
+// Shortcut Keys
+#define K_LOCK LGUI(LCTL(KC_Q)) // Locks screen on MacOS
+#define K_CSCN LGUI(LCTL(LSFT(KC_4))) // Copy a portion of the screen to the clipboard
+
+// Layer Keys
+#define L_LOWER MO(_LOWER)
+#define LT_LOW LT(_LOWER, KC_ENT)
+#define LT_RAI LT(_RAISE, KC_SPC)
+#ifdef KEYBOARD_pinky_3
+ #define LT_NUM LT(_NUMBERS, KC_SPC)
+ #define LT_FUNC LT(_FUNCTIONS, KC_ENT)
+#endif
+
+// Layout blocks
+#define _____________________QWERTY_L1______________________ T_TAB, T_Q, T_W, KC_E, KC_R, KC_T
+#define _____________________QWERTY_L2______________________ T_ESC, KC_A, KC_S, KC_D, KC_F, KC_G
+#define _____________________QWERTY_L3______________________ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B
+
+#define _____________________QWERTY_R1______________________ KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS
+#define _____________________QWERTY_R2______________________ KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT
+#define _____________________QWERTY_R3______________________ KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_EQL
+
+#define _____________________DVORAK_L1______________________ T_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y
+#define _____________________DVORAK_L2______________________ T_ESC, KC_A, KC_O, KC_E, KC_U, KC_I
+#define _____________________DVORAK_L3______________________ KC_LSFT, KC_SCLN, T_Q, KC_J, KC_K, KC_X
+
+#define _____________________DVORAK_R1______________________ KC_F, KC_G, KC_C, KC_R, KC_L, KC_BSLS
+#define _____________________DVORAK_R2______________________ KC_D, KC_H, KC_T, KC_N, KC_S, KC_SLSH
+#define _____________________DVORAK_R3______________________ KC_B, KC_M, T_W, KC_V, KC_Z, KC_EQL
+
+#define _____________________COLEMAK_L1_____________________ T_TAB, T_Q, T_W, KC_F, KC_P, KC_G
+#define _____________________COLEMAK_L2_____________________ T_ESC, KC_A, KC_R, KC_S, KC_T, KC_D
+#define _____________________COLEMAK_L3_____________________ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B
+
+#define _____________________COLEMAK_R1_____________________ KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSLS
+#define _____________________COLEMAK_R2_____________________ KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT
+#define _____________________COLEMAK_R3_____________________ KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_EQL
+
+#define _____________________NUM_LEFT_______________________ T_GRV, KC_1, KC_2, KC_3, KC_4, KC_5
+#define _____________________NUM_RIGHT______________________ KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS
+
+#define _____________________FUNC_LEFT______________________ KC_F11, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5
+#define _____________________FUNC_RIGHT_____________________ KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F12
+
+#define _____________________SYM_LEFT_______________________ KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC
+#define _____________________SYM_RIGHT______________________ KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_UNDS
+
+#define ____________________________________________________ _______, _______, _______, _______, _______, _______
+#define _____________________XXXXXXX________________________ XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX
+
+#define _______________NAV_1______________ KC_PGUP, KC_HOME, KC_UP, KC_END
+#define _______________NAV_2______________ KC_PGDN, KC_LEFT, KC_DOWN, KC_RGHT
+
+#define _____________MOUSE_1______________ KC_BTN1, KC_MS_U, KC_BTN2, KC_WH_D
+#define _____________MOUSE_2______________ KC_MS_L, KC_MS_D, KC_MS_R, KC_WH_U
+
+#define __________________________________ _______, _______, _______, _______
+#define _____________XXXXXXX______________ XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX
+
+#define _________MEDIA_1_________ KC_BRIU, KC_MPLY, KC_MUTE
+#define _________MEDIA_2_________ KC_BRID, KC_MFFD, KC__VOLUP
+#define _________MEDIA_3_________ XXXXXXX, KC_MRWD, KC__VOLDOWN
+
+#define ________MOD_LEFT_________ KC_LALT, T_GUI, KC_LCTL
+#define ________MOD_RIGHT________ KC_BSPC, KC_DEL, L_LOWER
+
+// Layout wrappers
+#define LAYOUT_wrapper(...) LAYOUT(__VA_ARGS__)
+#define LAYOUT_ergodox_wrapper(...) LAYOUT_ergodox(__VA_ARGS__) \ No newline at end of file
diff --git a/users/ninjonas/process_records.c b/users/ninjonas/process_records.c
new file mode 100644
index 0000000000..1b7958abcd
--- /dev/null
+++ b/users/ninjonas/process_records.c
@@ -0,0 +1,98 @@
+#include "ninjonas.h"
+
+__attribute__((weak))
+bool process_record_keymap(uint16_t keycode, keyrecord_t *record) { return true; }
+
+__attribute__((weak))
+bool process_record_secrets(uint16_t keycode, keyrecord_t *record) { return true; }
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ if (record->event.pressed) {
+ #ifdef SSD1306OLED
+ set_keylog(keycode, record);
+ #endif
+ }
+
+ switch (keycode) {
+
+ // Sends pyenv to activate 'jira' environment
+ case M_PYNV:
+ if (record->event.pressed) {
+ SEND_STRING("pyenv activate jira" SS_TAP(X_ENTER));
+ }
+ break;
+
+ // Sends  + alt + shift to a keycode to activate shiftit. See: https://github.com/fikovnik/ShiftIt
+ case M_SHFT:
+ if (record->event.pressed) {
+ register_code(KC_LGUI);
+ register_code(KC_LALT);
+ register_code(KC_LCTL);
+ } else {
+ unregister_code(KC_LGUI);
+ unregister_code(KC_LALT);
+ unregister_code(KC_LCTL);
+ }
+ break;
+
+ // Sends QMK make command to compile keyboard
+ case M_MAKE:
+ if (record->event.pressed) {
+ SEND_STRING("rm -f *.hex && rm -rf .build/ && make " QMK_KEYBOARD ":" QMK_KEYMAP SS_TAP(X_ENTER));
+ }
+ break;
+
+ // Sends QMK make command with the correct bootloader
+ case M_FLSH:
+ if (!record->event.pressed) {
+ SEND_STRING("rm -f *.hex && rm -rf .build/ && make " QMK_KEYBOARD ":" QMK_KEYMAP
+ #if (defined(BOOTLOADER_DFU) || defined(BOOTLOADER_LUFA_DFU) || defined(BOOTLOADER_QMK_DFU))
+ ":dfu "
+ #elif defined(BOOTLOADER_CATERINA)
+ ":avrdude "
+ #endif
+ SS_TAP(X_ENTER)
+ );
+
+ // Send reset_keyboard command instead of pressing reset button
+ #if (defined(BOOTLOADER_DFU) || defined(BOOTLOADER_LUFA_DFU) || defined(BOOTLOADER_QMK_DFU))
+ reset_keyboard();
+ #endif
+ }
+ break;
+
+ // Sends QMK version
+ case M_VRSN:
+ if (record->event.pressed) {
+ SEND_STRING (QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION ", Built on: " QMK_BUILDDATE);
+ }
+ break;
+
+ // Opens Visual Studio Code on current directory
+ case M_CODE:
+ if (record->event.pressed) {
+ SEND_STRING("code ." SS_TAP(X_ENTER));
+ }
+ break;
+
+ // BEGIN: Layer macros
+ case QWERTY:
+ if (record->event.pressed) {
+ set_single_persistent_default_layer(_QWERTY);
+ }
+ break;
+ case DVORAK:
+ if (record->event.pressed) {
+ set_single_persistent_default_layer(_DVORAK);
+ }
+ break;
+ case COLEMAK:
+ if (record->event.pressed) {
+ set_single_persistent_default_layer(_COLEMAK);
+ }
+ break;
+ // END: Layer macros
+ }
+
+ return process_record_keymap(keycode, record) && process_record_secrets(keycode, record);
+}
diff --git a/users/ninjonas/process_records.h b/users/ninjonas/process_records.h
new file mode 100644
index 0000000000..6db1d91fb6
--- /dev/null
+++ b/users/ninjonas/process_records.h
@@ -0,0 +1,24 @@
+#pragma once
+#include "ninjonas.h"
+
+enum custom_keycodes {
+ // Layer Macros
+ QWERTY = SAFE_RANGE,
+ DVORAK,
+ COLEMAK,
+ // Custom Macros
+ M_ZOOM,
+ M_PYNV,
+ M_SHFT,
+ M_MAKE,
+ M_FLSH,
+ M_VRSN,
+ M_CODE,
+};
+
+#ifdef SSD1306OLED
+void set_keylog(uint16_t keycode, keyrecord_t *record);
+#endif
+
+bool process_record_secrets(uint16_t keycode, keyrecord_t *record);
+bool process_record_keymap(uint16_t keycode, keyrecord_t *record);
diff --git a/users/ninjonas/rules.mk b/users/ninjonas/rules.mk
new file mode 100644
index 0000000000..1f2697a0e4
--- /dev/null
+++ b/users/ninjonas/rules.mk
@@ -0,0 +1,18 @@
+BOOTMAGIC_ENABLE = no # Disable Boot Magic (https://beta.docs.qmk.fm/features/feature_bootmagic)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+TAP_DANCE_ENABLE = yes # Enable Tap Dance.
+
+Link_Time_Optimization = no # if firmware size over limit, try this option
+
+ifeq ($(strip $(Link_Time_Optimization)),yes)
+ EXTRAFLAGS += -flto -DUSE_Link_Time_Optimization
+endif
+
+SRC += ninjonas.c \
+ process_records.c \
+ tap_dances.c
+
+ifneq ("$(wildcard $(USER_PATH)/secrets.c)","")
+ SRC += secrets.c
+endif \ No newline at end of file
diff --git a/users/ninjonas/tap_dances.c b/users/ninjonas/tap_dances.c
new file mode 100644
index 0000000000..0665a1607d
--- /dev/null
+++ b/users/ninjonas/tap_dances.c
@@ -0,0 +1,12 @@
+#include "ninjonas.h"
+
+qk_tap_dance_action_t tap_dance_actions[] = {
+ [TD_ESC_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS),
+ [TD_LBRC_BACK] = ACTION_TAP_DANCE_DOUBLE(KC_LBRC, LGUI(KC_LBRC)),
+ [TD_RBRC_FWD] = ACTION_TAP_DANCE_DOUBLE(KC_RBRC, LGUI(KC_RBRC)),
+ [TD_TAB_CTRLTAB] = ACTION_TAP_DANCE_DOUBLE(KC_TAB, LCTL(KC_TAB)),
+ [TD_GRV_CTRLGRV] = ACTION_TAP_DANCE_DOUBLE(KC_GRV, LGUI(KC_GRV)),
+ [TD_GUI_GUISPC] = ACTION_TAP_DANCE_DOUBLE(KC_LGUI, LGUI(KC_SPC)),
+ [TD_W_CTRLW] = ACTION_TAP_DANCE_DOUBLE(KC_W, LGUI(KC_W)),
+ [TD_Q_GUIQ] = ACTION_TAP_DANCE_DOUBLE(KC_Q, LGUI(KC_Q)),
+}; \ No newline at end of file
diff --git a/users/ninjonas/tap_dances.h b/users/ninjonas/tap_dances.h
new file mode 100644
index 0000000000..0a781ce4ed
--- /dev/null
+++ b/users/ninjonas/tap_dances.h
@@ -0,0 +1,22 @@
+#pragma once
+#include "ninjonas.h"
+
+enum custom_tapdances{
+ TD_ESC_CAPS = 0,
+ TD_LBRC_BACK,
+ TD_RBRC_FWD,
+ TD_TAB_CTRLTAB,
+ TD_GRV_CTRLGRV,
+ TD_GUI_GUISPC,
+ TD_W_CTRLW,
+ TD_Q_GUIQ,
+};
+
+#define T_ESC TD(TD_ESC_CAPS) // Tap for ESC, double tap for CAPSLOCK
+#define T_LBRC TD(TD_LBRC_BACK) // Tap for [, double tap for back browser
+#define T_RBRC TD(TD_RBRC_FWD) // Tap for ], double tap for forward browser
+#define T_TAB TD(TD_TAB_CTRLTAB) // Tap for TAB, double tap for CTRL + TAB
+#define T_GRV TD(TD_GRV_CTRLGRV) // Tap for GRV, double tap for  + GRV
+#define T_GUI TD(TD_GUI_GUISPC) // Tap for , double tap for  + Space
+#define T_W TD(TD_W_CTRLW) // Tap for W, double tap for  + W
+#define T_Q TD(TD_Q_GUIQ) // Tap for Q, double tap for  + Q \ No newline at end of file