aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/feature_advanced_keycodes.md75
-rw-r--r--tmk_core/common/action_util.c88
-rw-r--r--tmk_core/common/action_util.h11
3 files changed, 159 insertions, 15 deletions
diff --git a/docs/feature_advanced_keycodes.md b/docs/feature_advanced_keycodes.md
index 37a3d43fc..d23cb31d9 100644
--- a/docs/feature_advanced_keycodes.md
+++ b/docs/feature_advanced_keycodes.md
@@ -161,6 +161,81 @@ For one shot mods, you need to call `set_oneshot_mods(MOD)` to set it, or `clear
161 161
162!> If you're having issues with OSM translating over Remote Desktop Connection, this can be fixed by opening the settings, going to the "Local Resources" tap, and in the keyboard section, change the drop down to "On this Computer". This will fix the issue and allow OSM to function properly over Remote Desktop. 162!> If you're having issues with OSM translating over Remote Desktop Connection, this can be fixed by opening the settings, going to the "Local Resources" tap, and in the keyboard section, change the drop down to "On this Computer". This will fix the issue and allow OSM to function properly over Remote Desktop.
163 163
164## Callbacks
165
166When you'd like to perform custom logic when pressing a one shot key, there are several callbacks you can choose to implement. You could indicate changes in one shot keys by flashing an LED or making a sound, for example.
167
168There is a callback for `OSM(mod)`. It is called whenever the state of any one shot modifier key is changed: when it toggles on, but also when it is toggled off. You can use it like this:
169
170```c
171void oneshot_mods_changed_user(uint8_t mods) {
172 if (mods & MOD_MASK_SHIFT) {
173 println("Oneshot mods SHIFT");
174 }
175 if (mods & MOD_MASK_CTRL) {
176 println("Oneshot mods CTRL");
177 }
178 if (mods & MOD_MASK_ALT) {
179 println("Oneshot mods ALT");
180 }
181 if (mods & MOD_MASK_GUI) {
182 println("Oneshot mods GUI");
183 }
184 if (!mods) {
185 println("Oneshot mods off");
186 }
187}
188```
189
190The `mods` argument contains the active mods after the change, so it reflects the current state.
191
192When you use One Shot Tap Toggle (by adding `#define ONESHOT_TAP_TOGGLE 2` in your `config.h` file), you may lock a modifier key by pressing it the specified amount of times. There's a callback for that, too:
193
194```c
195void oneshot_locked_mods_changed_user(uint8_t mods) {
196 if (mods & MOD_MASK_SHIFT) {
197 println("Oneshot locked mods SHIFT");
198 }
199 if (mods & MOD_MASK_CTRL) {
200 println("Oneshot locked mods CTRL");
201 }
202 if (mods & MOD_MASK_ALT) {
203 println("Oneshot locked mods ALT");
204 }
205 if (mods & MOD_MASK_GUI) {
206 println("Oneshot locked mods GUI");
207 }
208 if (!mods) {
209 println("Oneshot locked mods off");
210 }
211}
212```
213
214Last, there is also a callback for the `OSL(layer)` one shot key:
215
216```c
217void oneshot_layer_changed_user(uint8_t layer) {
218 if (layer == 1) {
219 println("Oneshot layer 1 on");
220 }
221 if (!layer) {
222 println("Oneshot layer off");
223 }
224}
225```
226
227If any one shot layer is switched off, `layer` will be zero. When you're looking to do something on any layer change instead of one shot layer changes, `layer_state_set_user` is a better callback to use.
228
229If you are making your own keyboard, there are also `_kb` equivalent functions:
230
231```c
232void oneshot_locked_mods_changed_kb(uint8_t mods);
233void oneshot_mods_changed_kb(uint8_t mods);
234void oneshot_layer_changed_kb(uint8_t layer);
235```
236
237As with any callback, be sure to call the `_user` variant to allow for further customizability.
238
164# Tap-Hold Configuration Options 239# Tap-Hold Configuration Options
165 240
166While Tap-Hold options are fantastic, they are not without their issues. We have tried to configure them with reasonal defaults, but that may still cause issues for some people. 241While Tap-Hold options are fantastic, they are not without their issues. We have tried to configure them with reasonal defaults, but that may still cause issues for some people.
diff --git a/tmk_core/common/action_util.c b/tmk_core/common/action_util.c
index 58401ace5..365ed6a1d 100644
--- a/tmk_core/common/action_util.c
+++ b/tmk_core/common/action_util.c
@@ -48,11 +48,21 @@ extern inline void del_key(uint8_t key);
48extern inline void clear_keys(void); 48extern inline void clear_keys(void);
49 49
50#ifndef NO_ACTION_ONESHOT 50#ifndef NO_ACTION_ONESHOT
51static int8_t oneshot_mods = 0; 51static uint8_t oneshot_mods = 0;
52static int8_t oneshot_locked_mods = 0; 52static uint8_t oneshot_locked_mods = 0;
53int8_t get_oneshot_locked_mods(void) { return oneshot_locked_mods; } 53uint8_t get_oneshot_locked_mods(void) { return oneshot_locked_mods; }
54void set_oneshot_locked_mods(int8_t mods) { oneshot_locked_mods = mods; } 54void set_oneshot_locked_mods(uint8_t mods) {
55void clear_oneshot_locked_mods(void) { oneshot_locked_mods = 0; } 55 if (mods != oneshot_locked_mods) {
56 oneshot_locked_mods = mods;
57 oneshot_locked_mods_changed_kb(oneshot_locked_mods);
58 }
59}
60void clear_oneshot_locked_mods(void) {
61 if (oneshot_locked_mods) {
62 oneshot_locked_mods = 0;
63 oneshot_locked_mods_changed_kb(oneshot_locked_mods);
64 }
65}
56#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) 66#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
57static uint16_t oneshot_time = 0; 67static uint16_t oneshot_time = 0;
58bool has_oneshot_mods_timed_out(void) { 68bool has_oneshot_mods_timed_out(void) {
@@ -97,6 +107,7 @@ void set_oneshot_layer(uint8_t layer, uint8_t state)
97#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) 107#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
98 oneshot_layer_time = timer_read(); 108 oneshot_layer_time = timer_read();
99#endif 109#endif
110 oneshot_layer_changed_kb(get_oneshot_layer());
100} 111}
101/** \brief Reset oneshot layer 112/** \brief Reset oneshot layer
102 * 113 *
@@ -107,6 +118,7 @@ void reset_oneshot_layer(void) {
107#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) 118#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
108 oneshot_layer_time = 0; 119 oneshot_layer_time = 0;
109#endif 120#endif
121 oneshot_layer_changed_kb(get_oneshot_layer());
110} 122}
111/** \brief Clear oneshot layer 123/** \brief Clear oneshot layer
112 * 124 *
@@ -118,9 +130,7 @@ void clear_oneshot_layer_state(oneshot_fullfillment_t state)
118 oneshot_layer_data &= ~state; 130 oneshot_layer_data &= ~state;
119 if (!get_oneshot_layer_state() && start_state != oneshot_layer_data) { 131 if (!get_oneshot_layer_state() && start_state != oneshot_layer_data) {
120 layer_off(get_oneshot_layer()); 132 layer_off(get_oneshot_layer());
121#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) 133 reset_oneshot_layer();
122 oneshot_layer_time = 0;
123#endif
124 } 134 }
125} 135}
126/** \brief Is oneshot layer active 136/** \brief Is oneshot layer active
@@ -243,23 +253,27 @@ void clear_macro_mods(void) { macro_mods = 0; }
243 * 253 *
244 * FIXME: needs doc 254 * FIXME: needs doc
245 */ 255 */
246void set_oneshot_mods(uint8_t mods) 256void set_oneshot_mods(uint8_t mods) {
247{ 257 if (oneshot_mods != mods) {
248 oneshot_mods = mods;
249#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) 258#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
250 oneshot_time = timer_read(); 259 oneshot_time = timer_read();
251#endif 260#endif
261 oneshot_mods = mods;
262 oneshot_mods_changed_kb(mods);
263 }
252} 264}
253/** \brief clear oneshot mods 265/** \brief clear oneshot mods
254 * 266 *
255 * FIXME: needs doc 267 * FIXME: needs doc
256 */ 268 */
257void clear_oneshot_mods(void) 269void clear_oneshot_mods(void) {
258{ 270 if (oneshot_mods) {
259 oneshot_mods = 0; 271 oneshot_mods = 0;
260#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) 272#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
261 oneshot_time = 0; 273 oneshot_time = 0;
262#endif 274#endif
275 oneshot_mods_changed_kb(oneshot_mods);
276 }
263} 277}
264/** \brief get oneshot mods 278/** \brief get oneshot mods
265 * 279 *
@@ -271,6 +285,54 @@ uint8_t get_oneshot_mods(void)
271} 285}
272#endif 286#endif
273 287
288/** \brief Called when the one shot modifiers have been changed.
289 *
290 * \param mods Contains the active modifiers active after the change.
291 */
292__attribute__((weak))
293void oneshot_locked_mods_changed_user(uint8_t mods) { }
294
295/** \brief Called when the locked one shot modifiers have been changed.
296 *
297 * \param mods Contains the active modifiers active after the change.
298 */
299__attribute__((weak))
300void oneshot_locked_mods_changed_kb(uint8_t mods) {
301 oneshot_locked_mods_changed_user(mods);
302}
303
304/** \brief Called when the one shot modifiers have been changed.
305 *
306 * \param mods Contains the active modifiers active after the change.
307 */
308__attribute__((weak))
309void oneshot_mods_changed_user(uint8_t mods) { }
310
311/** \brief Called when the one shot modifiers have been changed.
312 *
313 * \param mods Contains the active modifiers active after the change.
314 */
315__attribute__((weak))
316void oneshot_mods_changed_kb(uint8_t mods) {
317 oneshot_mods_changed_user(mods);
318}
319
320/** \brief Called when the one shot layers have been changed.
321 *
322 * \param layer Contains the layer that is toggled on, or zero when toggled off.
323 */
324__attribute__((weak))
325void oneshot_layer_changed_user(uint8_t layer) { }
326
327/** \brief Called when the one shot layers have been changed.
328 *
329 * \param layer Contains the layer that is toggled on, or zero when toggled off.
330 */
331__attribute__((weak))
332void oneshot_layer_changed_kb(uint8_t layer) {
333 oneshot_layer_changed_user(layer);
334}
335
274/** \brief inspect keyboard state 336/** \brief inspect keyboard state
275 * 337 *
276 * FIXME: needs doc 338 * FIXME: needs doc
diff --git a/tmk_core/common/action_util.h b/tmk_core/common/action_util.h
index 345893151..d03f5682a 100644
--- a/tmk_core/common/action_util.h
+++ b/tmk_core/common/action_util.h
@@ -71,8 +71,8 @@ void oneshot_enable(void);
71void oneshot_disable(void); 71void oneshot_disable(void);
72bool has_oneshot_mods_timed_out(void); 72bool has_oneshot_mods_timed_out(void);
73 73
74int8_t get_oneshot_locked_mods(void); 74uint8_t get_oneshot_locked_mods(void);
75void set_oneshot_locked_mods(int8_t mods); 75void set_oneshot_locked_mods(uint8_t mods);
76void clear_oneshot_locked_mods(void); 76void clear_oneshot_locked_mods(void);
77 77
78typedef enum { 78typedef enum {
@@ -89,6 +89,13 @@ bool is_oneshot_layer_active(void);
89uint8_t get_oneshot_layer_state(void); 89uint8_t get_oneshot_layer_state(void);
90bool has_oneshot_layer_timed_out(void); 90bool has_oneshot_layer_timed_out(void);
91 91
92void oneshot_locked_mods_changed_user(uint8_t mods);
93void oneshot_locked_mods_changed_kb(uint8_t mods);
94void oneshot_mods_changed_user(uint8_t mods);
95void oneshot_mods_changed_kb(uint8_t mods);
96void oneshot_layer_changed_user(uint8_t layer);
97void oneshot_layer_changed_kb(uint8_t layer);
98
92/* inspect */ 99/* inspect */
93uint8_t has_anymod(void); 100uint8_t has_anymod(void);
94 101