aboutsummaryrefslogtreecommitdiff
path: root/tmk_core/common
diff options
context:
space:
mode:
authorIBNobody <ibnobody@gmail.com>2016-04-13 19:14:23 -0500
committerIBNobody <ibnobody@gmail.com>2016-04-13 19:14:23 -0500
commit01f5b35396e5558a39e6f35ef9128b96c289c05c (patch)
treef897786dddcd310f227ac157e79c7dd717e9b582 /tmk_core/common
parent390fd3107a84277151ceb63255c859307221a290 (diff)
parenta0194d7e5ff2f3d242a5c6508abf81b4ddf67a3e (diff)
downloadqmk_firmware-01f5b35396e5558a39e6f35ef9128b96c289c05c.tar.gz
qmk_firmware-01f5b35396e5558a39e6f35ef9128b96c289c05c.zip
Merge remote-tracking branch 'refs/remotes/jackhumbert/master' into pc_planck
Diffstat (limited to 'tmk_core/common')
-rw-r--r--tmk_core/common/action.c32
-rw-r--r--tmk_core/common/action.h4
-rw-r--r--tmk_core/common/action_layer.c77
-rw-r--r--tmk_core/common/action_layer.h11
4 files changed, 115 insertions, 9 deletions
diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c
index 2ccc0e0b9..f9e6c17dc 100644
--- a/tmk_core/common/action.c
+++ b/tmk_core/common/action.c
@@ -53,6 +53,22 @@ void action_exec(keyevent_t event)
53#endif 53#endif
54} 54}
55 55
56#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
57bool disable_action_cache = false;
58
59void process_action_nocache(keyrecord_t *record)
60{
61 disable_action_cache = true;
62 process_action(record);
63 disable_action_cache = false;
64}
65#else
66void process_action_nocache(keyrecord_t *record)
67{
68 process_action(record);
69}
70#endif
71
56__attribute__ ((weak)) 72__attribute__ ((weak))
57void process_action_kb(keyrecord_t *record) {} 73void process_action_kb(keyrecord_t *record) {}
58 74
@@ -67,7 +83,7 @@ void process_action(keyrecord_t *record)
67 83
68 process_action_kb(record); 84 process_action_kb(record);
69 85
70 action_t action = layer_switch_get_action(event.key); 86 action_t action = store_or_get_action(event.pressed, event.key);
71 dprint("ACTION: "); debug_action(action); 87 dprint("ACTION: "); debug_action(action);
72#ifndef NO_ACTION_LAYER 88#ifndef NO_ACTION_LAYER
73 dprint(" layer_state: "); layer_debug(); 89 dprint(" layer_state: "); layer_debug();
@@ -88,14 +104,24 @@ void process_action(keyrecord_t *record)
88 action.key.mods<<4; 104 action.key.mods<<4;
89 if (event.pressed) { 105 if (event.pressed) {
90 if (mods) { 106 if (mods) {
91 add_weak_mods(mods); 107 if (IS_MOD(action.key.code)) {
108 // e.g. LSFT(KC_LGUI): we don't want the LSFT to be weak as it would make it useless.
109 // this also makes LSFT(KC_LGUI) behave exactly the same as LGUI(KC_LSFT)
110 add_mods(mods);
111 } else {
112 add_weak_mods(mods);
113 }
92 send_keyboard_report(); 114 send_keyboard_report();
93 } 115 }
94 register_code(action.key.code); 116 register_code(action.key.code);
95 } else { 117 } else {
96 unregister_code(action.key.code); 118 unregister_code(action.key.code);
97 if (mods) { 119 if (mods) {
98 del_weak_mods(mods); 120 if (IS_MOD(action.key.code)) {
121 del_mods(mods);
122 } else {
123 del_weak_mods(mods);
124 }
99 send_keyboard_report(); 125 send_keyboard_report();
100 } 126 }
101 } 127 }
diff --git a/tmk_core/common/action.h b/tmk_core/common/action.h
index 9f528af4b..44ec3047b 100644
--- a/tmk_core/common/action.h
+++ b/tmk_core/common/action.h
@@ -62,6 +62,10 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt);
62void process_action_kb(keyrecord_t *record); 62void process_action_kb(keyrecord_t *record);
63 63
64/* Utilities for actions. */ 64/* Utilities for actions. */
65#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
66extern bool disable_action_cache;
67#endif
68void process_action_nocache(keyrecord_t *record);
65void process_action(keyrecord_t *record); 69void process_action(keyrecord_t *record);
66void register_code(uint8_t code); 70void register_code(uint8_t code);
67void unregister_code(uint8_t code); 71void unregister_code(uint8_t code);
diff --git a/tmk_core/common/action_layer.c b/tmk_core/common/action_layer.c
index c535615f4..fc721a732 100644
--- a/tmk_core/common/action_layer.c
+++ b/tmk_core/common/action_layer.c
@@ -110,9 +110,71 @@ void layer_debug(void)
110} 110}
111#endif 111#endif
112 112
113#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
114uint8_t source_layers_cache[MAX_LAYER_BITS][(MATRIX_ROWS * MATRIX_COLS + 7) / 8] = {0};
113 115
116void update_source_layers_cache(keypos_t key, uint8_t layer)
117{
118 const uint8_t key_number = key.col + (key.row * MATRIX_COLS);
119 const uint8_t storage_row = key_number / 8;
120 const uint8_t storage_bit = key_number % 8;
114 121
115action_t layer_switch_get_action(keypos_t key) 122 for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) {
123 source_layers_cache[bit_number][storage_row] ^=
124 (-((layer & (1U << bit_number)) != 0)
125 ^ source_layers_cache[bit_number][storage_row])
126 & (1U << storage_bit);
127 }
128}
129
130uint8_t read_source_layers_cache(keypos_t key)
131{
132 const uint8_t key_number = key.col + (key.row * MATRIX_COLS);
133 const uint8_t storage_row = key_number / 8;
134 const uint8_t storage_bit = key_number % 8;
135 uint8_t layer = 0;
136
137 for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) {
138 layer |=
139 ((source_layers_cache[bit_number][storage_row]
140 & (1U << storage_bit)) != 0)
141 << bit_number;
142 }
143
144 return layer;
145}
146#endif
147
148/*
149 * Make sure the action triggered when the key is released is the same
150 * one as the one triggered on press. It's important for the mod keys
151 * when the layer is switched after the down event but before the up
152 * event as they may get stuck otherwise.
153 */
154action_t store_or_get_action(bool pressed, keypos_t key)
155{
156#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
157 if (disable_action_cache) {
158 return layer_switch_get_action(key);
159 }
160
161 uint8_t layer;
162
163 if (pressed) {
164 layer = layer_switch_get_layer(key);
165 update_source_layers_cache(key, layer);
166 }
167 else {
168 layer = read_source_layers_cache(key);
169 }
170 return action_for_key(layer, key);
171#else
172 return layer_switch_get_action(key);
173#endif
174}
175
176
177int8_t layer_switch_get_layer(keypos_t key)
116{ 178{
117 action_t action; 179 action_t action;
118 action.code = ACTION_TRANSPARENT; 180 action.code = ACTION_TRANSPARENT;
@@ -124,15 +186,18 @@ action_t layer_switch_get_action(keypos_t key)
124 if (layers & (1UL<<i)) { 186 if (layers & (1UL<<i)) {
125 action = action_for_key(i, key); 187 action = action_for_key(i, key);
126 if (action.code != ACTION_TRANSPARENT) { 188 if (action.code != ACTION_TRANSPARENT) {
127 return action; 189 return i;
128 } 190 }
129 } 191 }
130 } 192 }
131 /* fall back to layer 0 */ 193 /* fall back to layer 0 */
132 action = action_for_key(0, key); 194 return 0;
133 return action;
134#else 195#else
135 action = action_for_key(biton32(default_layer_state), key); 196 return biton32(default_layer_state);
136 return action;
137#endif 197#endif
138} 198}
199
200action_t layer_switch_get_action(keypos_t key)
201{
202 return action_for_key(layer_switch_get_layer(key), key);
203}
diff --git a/tmk_core/common/action_layer.h b/tmk_core/common/action_layer.h
index b6da353cf..3a4b1e334 100644
--- a/tmk_core/common/action_layer.h
+++ b/tmk_core/common/action_layer.h
@@ -70,6 +70,17 @@ void layer_xor(uint32_t state);
70#define layer_debug() 70#define layer_debug()
71#endif 71#endif
72 72
73/* pressed actions cache */
74#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
75/* The number of bits needed to represent the layer number: log2(32). */
76#define MAX_LAYER_BITS 5
77void update_source_layers_cache(keypos_t key, uint8_t layer);
78uint8_t read_source_layers_cache(keypos_t key);
79#endif
80action_t store_or_get_action(bool pressed, keypos_t key);
81
82/* return the topmost non-transparent layer currently associated with key */
83int8_t layer_switch_get_layer(keypos_t key);
73 84
74/* return action depending on current layer status */ 85/* return action depending on current layer status */
75action_t layer_switch_get_action(keypos_t key); 86action_t layer_switch_get_action(keypos_t key);