]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/common/action_layer.c
Add opensuse packages provided by @isolatedvirus
[qmk_firmware.git] / tmk_core / common / action_layer.c
1 #include <stdint.h>
2 #include "keyboard.h"
3 #include "action.h"
4 #include "util.h"
5 #include "action_layer.h"
6
7 #ifdef DEBUG_ACTION
8 #include "debug.h"
9 #else
10 #include "nodebug.h"
11 #endif
12
13
14 /** \brief Default Layer State
15  */
16 uint32_t default_layer_state = 0;
17
18 /** \brief Default Layer State Set At user Level
19  *
20  * FIXME: Needs docs
21  */
22 __attribute__((weak))
23 uint32_t default_layer_state_set_user(uint32_t state) {
24     return state;
25 }
26
27 /** \brief Default Layer State Set At Keyboard Level
28  *
29  * FIXME: Needs docs
30  */
31 __attribute__((weak))
32 uint32_t default_layer_state_set_kb(uint32_t state) {
33     return default_layer_state_set_user(state);
34 }
35
36 /** \brief Default Layer State Set
37  *
38  * FIXME: Needs docs
39  */
40 static void default_layer_state_set(uint32_t state)
41 {
42     state = default_layer_state_set_kb(state);
43     debug("default_layer_state: ");
44     default_layer_debug(); debug(" to ");
45     default_layer_state = state;
46     default_layer_debug(); debug("\n");
47     clear_keyboard_but_mods(); // To avoid stuck keys
48 }
49
50 /** \brief Default Layer Print
51  *
52  * FIXME: Needs docs
53  */
54 void default_layer_debug(void)
55 {
56     dprintf("%08lX(%u)", default_layer_state, biton32(default_layer_state));
57 }
58
59 /** \brief Default Layer Set
60  *
61  * FIXME: Needs docs
62  */
63 void default_layer_set(uint32_t state)
64 {
65     default_layer_state_set(state);
66 }
67
68 #ifndef NO_ACTION_LAYER
69 /** \brief Default Layer Or
70  *
71  * FIXME: Needs docs
72  */
73 void default_layer_or(uint32_t state)
74 {
75     default_layer_state_set(default_layer_state | state);
76 }
77 /** \brief Default Layer And
78  *
79  * FIXME: Needs docs
80  */
81 void default_layer_and(uint32_t state)
82 {
83     default_layer_state_set(default_layer_state & state);
84 }
85 /** \brief Default Layer Xor
86  *
87  * FIXME: Needs docs
88  */
89 void default_layer_xor(uint32_t state)
90 {
91     default_layer_state_set(default_layer_state ^ state);
92 }
93 #endif
94
95
96 #ifndef NO_ACTION_LAYER
97 /** \brief Keymap Layer State
98  */
99 uint32_t layer_state = 0;
100
101 /** \brief Layer state set user
102  *
103  * FIXME: Needs docs
104  */
105 __attribute__((weak))
106 uint32_t layer_state_set_user(uint32_t state) {
107     return state;
108 }
109
110 /** \brief Layer state set keyboard
111  *
112  * FIXME: Needs docs
113  */
114 __attribute__((weak))
115 uint32_t layer_state_set_kb(uint32_t state) {
116     return layer_state_set_user(state);
117 }
118
119 /** \brief Layer state set
120  *
121  * FIXME: Needs docs
122  */
123 void layer_state_set(uint32_t state)
124 {
125     state = layer_state_set_kb(state);
126     dprint("layer_state: ");
127     layer_debug(); dprint(" to ");
128     layer_state = state;
129     layer_debug(); dprintln();
130     clear_keyboard_but_mods(); // To avoid stuck keys
131 }
132
133 /** \brief Layer clear
134  *
135  * FIXME: Needs docs
136  */
137 void layer_clear(void)
138 {
139     layer_state_set(0);
140 }
141
142 /** \brief Layer state is
143  *
144  * FIXME: Needs docs
145  */
146 bool layer_state_is(uint8_t layer)
147 {
148     return layer_state_cmp(layer_state, layer);
149 }
150
151 /** \brief Layer state compare
152  *
153  * FIXME: Needs docs
154  */
155 bool layer_state_cmp(uint32_t cmp_layer_state, uint8_t layer) {
156     if (!cmp_layer_state) { return layer == 0; }
157     return (cmp_layer_state & (1UL<<layer)) != 0;
158 }
159
160 /** \brief Layer move
161  *
162  * FIXME: Needs docs
163  */
164 void layer_move(uint8_t layer)
165 {
166     layer_state_set(1UL<<layer);
167 }
168
169 /** \brief Layer on
170  *
171  * FIXME: Needs docs
172  */
173 void layer_on(uint8_t layer)
174 {
175     layer_state_set(layer_state | (1UL<<layer));
176 }
177
178 /** \brief Layer off
179  *
180  * FIXME: Needs docs
181  */
182 void layer_off(uint8_t layer)
183 {
184     layer_state_set(layer_state & ~(1UL<<layer));
185 }
186
187 /** \brief Layer invert
188  *
189  * FIXME: Needs docs
190  */
191 void layer_invert(uint8_t layer)
192 {
193     layer_state_set(layer_state ^ (1UL<<layer));
194 }
195
196 /** \brief Layer or
197  *
198  * FIXME: Needs docs
199  */
200 void layer_or(uint32_t state)
201 {
202     layer_state_set(layer_state | state);
203 }
204 /** \brief Layer and
205  *
206  * FIXME: Needs docs
207  */
208 void layer_and(uint32_t state)
209 {
210     layer_state_set(layer_state & state);
211 }
212 /** \brief Layer xor
213  *
214  * FIXME: Needs docs
215  */
216 void layer_xor(uint32_t state)
217 {
218     layer_state_set(layer_state ^ state);
219 }
220
221 /** \brief Layer debug printing
222  *
223  * FIXME: Needs docs
224  */
225 void layer_debug(void)
226 {
227     dprintf("%08lX(%u)", layer_state, biton32(layer_state));
228 }
229 #endif
230
231 #if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
232 uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS + 7) / 8][MAX_LAYER_BITS] = {{0}};
233
234 void update_source_layers_cache(keypos_t key, uint8_t layer)
235 {
236     const uint8_t key_number = key.col + (key.row * MATRIX_COLS);
237     const uint8_t storage_row = key_number / 8;
238     const uint8_t storage_bit = key_number % 8;
239
240     for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) {
241         source_layers_cache[storage_row][bit_number] ^=
242             (-((layer & (1U << bit_number)) != 0)
243              ^ source_layers_cache[storage_row][bit_number])
244             & (1U << storage_bit);
245     }
246 }
247
248 uint8_t read_source_layers_cache(keypos_t key)
249 {
250     const uint8_t key_number = key.col + (key.row * MATRIX_COLS);
251     const uint8_t storage_row = key_number / 8;
252     const uint8_t storage_bit = key_number % 8;
253     uint8_t layer = 0;
254
255     for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) {
256         layer |=
257             ((source_layers_cache[storage_row][bit_number]
258               & (1U << storage_bit)) != 0)
259             << bit_number;
260     }
261
262     return layer;
263 }
264 #endif
265
266 /** \brief Store or get action (FIXME: Needs better summary)
267  *
268  * Make sure the action triggered when the key is released is the same
269  * one as the one triggered on press. It's important for the mod keys
270  * when the layer is switched after the down event but before the up
271  * event as they may get stuck otherwise.
272  */
273 action_t store_or_get_action(bool pressed, keypos_t key)
274 {
275 #if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
276     if (disable_action_cache) {
277         return layer_switch_get_action(key);
278     }
279
280     uint8_t layer;
281
282     if (pressed) {
283         layer = layer_switch_get_layer(key);
284         update_source_layers_cache(key, layer);
285     }
286     else {
287         layer = read_source_layers_cache(key);
288     }
289     return action_for_key(layer, key);
290 #else
291     return layer_switch_get_action(key);
292 #endif
293 }
294
295
296 /** \brief Layer switch get layer
297  *
298  * FIXME: Needs docs
299  */
300 int8_t layer_switch_get_layer(keypos_t key)
301 {
302 #ifndef NO_ACTION_LAYER
303     action_t action;
304     action.code = ACTION_TRANSPARENT;
305
306     uint32_t layers = layer_state | default_layer_state;
307     /* check top layer first */
308     for (int8_t i = 31; i >= 0; i--) {
309         if (layers & (1UL<<i)) {
310             action = action_for_key(i, key);
311             if (action.code != ACTION_TRANSPARENT) {
312                 return i;
313             }
314         }
315     }
316     /* fall back to layer 0 */
317     return 0;
318 #else
319     return biton32(default_layer_state);
320 #endif
321 }
322
323 /** \brief Layer switch get layer
324  *
325  * FIXME: Needs docs
326  */
327 action_t layer_switch_get_action(keypos_t key)
328 {
329     return action_for_key(layer_switch_get_layer(key), key);
330 }