aboutsummaryrefslogtreecommitdiff
path: root/common/action.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/action.c')
-rw-r--r--common/action.c201
1 files changed, 132 insertions, 69 deletions
diff --git a/common/action.c b/common/action.c
index db31613bf..22f0bf0a0 100644
--- a/common/action.c
+++ b/common/action.c
@@ -97,6 +97,40 @@ static void waiting_buffer_process(void)
97{ 97{
98} 98}
99 99
100/* Oneshot modifier
101 *
102 * Problem: Want to capitalize like 'The' but the result tends to be 'THe'.
103 * Solution: Oneshot modifier have its effect on only one key coming next.
104 * Tap Shift, then type 't', 'h' and 'e'. Not need to hold Shift key.
105 *
106 * Hold: works as normal modifier.
107 * Tap: one shot modifier.
108 * 2 Tap: cancel one shot modifier.
109 * 5-Tap: toggles enable/disable oneshot feature.
110 */
111static struct {
112 uint8_t mods;
113 uint8_t time;
114 bool ready;
115 bool disabled;
116} oneshot_state;
117static void oneshot_start(uint8_t mods, uint16_t time)
118{
119 oneshot_state.mods = mods;
120 oneshot_state.time = time;
121 oneshot_state.ready = true;
122}
123static void oneshot_cancel(void)
124{
125 oneshot_state.mods = 0;
126 oneshot_state.time = 0;
127 oneshot_state.ready = false;
128}
129static void oneshot_toggle(void)
130{
131 oneshot_state.disabled = !oneshot_state.disabled;
132}
133
100 134
101/* 135/*
102 * Rule to judge tap: 136 * Rule to judge tap:
@@ -271,83 +305,102 @@ static void process(keyrecord_t *record)
271 switch (action.kind.id) { 305 switch (action.kind.id) {
272 /* Key and Mods */ 306 /* Key and Mods */
273 case ACT_LMODS: 307 case ACT_LMODS:
274 // |pressed |released
275 // --------------+---------------------------------+------------
276 // key |down(key) |up(key)
277 // mods |add(mods) |del(mods)
278 // key with mods |add(mods), down(key), unset(mods)|up(key)
279 if (event.pressed) {
280 uint8_t tmp_mods = host_get_mods();
281 if (action.key.mods) {
282 host_add_mods(action.key.mods);
283 host_send_keyboard_report();
284 }
285 register_code(action.key.code);
286 if (action.key.mods && action.key.code) {
287 host_set_mods(tmp_mods);
288 host_send_keyboard_report();
289 }
290 } else {
291 if (action.key.mods && !action.key.code) {
292 host_del_mods(action.key.mods);
293 host_send_keyboard_report();
294 }
295 unregister_code(action.key.code);
296 }
297 break;
298 case ACT_RMODS: 308 case ACT_RMODS:
299 // |pressed |released 309 {
300 // --------------+---------------------------------+------------ 310 uint8_t mods = (action.kind.id == ACT_LMODS) ? action.key.mods :
301 // key |down(key) |up(key) 311 action.key.mods<<4;
302 // mods |add(mods) |del(mods) 312 if (event.pressed) {
303 // key with mods |add(mods), down(key), unset(mods)|up(key) 313 uint8_t tmp_mods = host_get_mods();
304 if (event.pressed) { 314 if (mods) {
305 uint8_t tmp_mods = host_get_mods(); 315 host_add_mods(mods);
306 if (action.key.mods) { 316 host_send_keyboard_report();
307 host_add_mods(action.key.mods<<4); 317 }
308 host_send_keyboard_report(); 318 register_code(action.key.code);
309 } 319 if (mods && action.key.code) {
310 register_code(action.key.code); 320 host_set_mods(tmp_mods);
311 if (action.key.mods && action.key.code) { 321 host_send_keyboard_report();
312 host_set_mods(tmp_mods); 322 }
313 host_send_keyboard_report(); 323 } else {
314 } 324 if (mods && !action.key.code) {
315 } else { 325 host_del_mods(mods);
316 if (action.key.mods && !action.key.code) { 326 host_send_keyboard_report();
317 host_del_mods(action.key.mods<<4); 327 }
318 host_send_keyboard_report(); 328 unregister_code(action.key.code);
319 } 329 }
320 unregister_code(action.key.code);
321 } 330 }
322 break; 331 break;
323 case ACT_LMODS_TAP: 332 case ACT_LMODS_TAP:
324 case ACT_RMODS_TAP: 333 case ACT_RMODS_TAP:
325 { 334 {
326 uint8_t tmp_mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods : 335 uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods :
327 action.key.mods<<4; 336 action.key.mods<<4;
328 if (event.pressed) { 337 switch (action.layer.code) {
329 if (IS_TAPPING_KEY(event.key) && tap_count > 0) { 338 case 0x00:
330 if (waiting_buffer_has_anykey_pressed()) { 339 // Oneshot modifier
331 debug("MODS_TAP: Tap: Cancel: add_mods\n"); 340 if (event.pressed) {
332 // ad hoc: set 0 to cancel tap 341 if (tap_count == 0) {
333 record->tap_count = 0; 342 debug("MODS_TAP: Oneshot: add_mods\n");
334 add_mods(tmp_mods); 343 add_mods(mods);
344 }
345 else if (tap_count == 1) {
346 debug("MODS_TAP: Oneshot: start\n");
347 oneshot_start(mods, event.time);
348 }
349 else if (tap_count == 5) {
350 debug("MODS_TAP: Oneshot: toggle\n");
351 oneshot_toggle();
352 }
353 else {
354 debug("MODS_TAP: Oneshot: cancel&add_mods\n");
355 // double tap cancels oneshot and works as normal modifier.
356 oneshot_cancel();
357 add_mods(mods);
358 }
335 } else { 359 } else {
336 debug("MODS_TAP: Tap: register_code\n"); 360 if (tap_count == 0) {
337 register_code(action.key.code); 361 debug("MODS_TAP: Oneshot: cancel/del_mods\n");
362 // cancel oneshot by holding.
363 oneshot_cancel();
364 del_mods(mods);
365 }
366 else if (tap_count == 1) {
367 debug("MODS_TAP: Oneshot: del_mods\n");
368 // retain Oneshot
369 del_mods(mods);
370 }
371 else {
372 debug("MODS_TAP: Oneshot: del_mods\n");
373 // cancel Mods
374 del_mods(mods);
375 }
338 } 376 }
339 } else { 377 break;
340 debug("MODS_TAP: No tap: add_mods\n"); 378 default:
341 add_mods(tmp_mods); 379 if (event.pressed) {
342 } 380 if (tap_count > 0) {
343 } else { 381 if (waiting_buffer_has_anykey_pressed()) {
344 if (IS_TAPPING_KEY(event.key) && tap_count > 0) { 382 debug("MODS_TAP: Tap: Cancel: add_mods\n");
345 debug("MODS_TAP: Tap: unregister_code\n"); 383 // ad hoc: set 0 to cancel tap
346 unregister_code(action.key.code); 384 record->tap_count = 0;
347 } else { 385 add_mods(mods);
348 debug("MODS_TAP: No tap: add_mods\n"); 386 } else {
349 del_mods(tmp_mods); 387 debug("MODS_TAP: Tap: register_code\n");
350 } 388 register_code(action.key.code);
389 }
390 } else {
391 debug("MODS_TAP: No tap: add_mods\n");
392 add_mods(mods);
393 }
394 } else {
395 if (tap_count > 0) {
396 debug("MODS_TAP: Tap: unregister_code\n");
397 unregister_code(action.key.code);
398 } else {
399 debug("MODS_TAP: No tap: add_mods\n");
400 del_mods(mods);
401 }
402 }
403 break;
351 } 404 }
352 } 405 }
353 break; 406 break;
@@ -579,7 +632,17 @@ void register_code(uint8_t code)
579 } 632 }
580 else if IS_KEY(code) { 633 else if IS_KEY(code) {
581 // TODO: should push command_proc out of this block? 634 // TODO: should push command_proc out of this block?
582 if (!command_proc(code)) { 635 if (command_proc(code)) return;
636
637 if (oneshot_state.mods && oneshot_state.ready && !oneshot_state.disabled) {
638 uint8_t tmp_mods = host_get_mods();
639 host_add_mods(oneshot_state.mods);
640 host_add_key(code);
641 host_send_keyboard_report();
642
643 host_set_mods(tmp_mods);
644 oneshot_state.ready = false;
645 } else {
583 host_add_key(code); 646 host_add_key(code);
584 host_send_keyboard_report(); 647 host_send_keyboard_report();
585 } 648 }