]> git.donarmstrong.com Git - tmk_firmware.git/commitdiff
Fix tap key using delaying_layer and waiting_key.
authortmk <nobody@nowhere>
Sun, 13 Jan 2013 01:24:20 +0000 (10:24 +0900)
committertmk <nobody@nowhere>
Sun, 13 Jan 2013 01:24:20 +0000 (10:24 +0900)
common/action.c
common/host.c
common/host.h
common/keyboard.c
keyboard/hhkb/keymap.c

index 425a2b00ff17bc6a7e884fe2bf6774dbef5e16b2..1a86f16d316406926e3e7dce52bc1589f903dc0f 100644 (file)
@@ -115,29 +115,25 @@ uint8_t default_layer = 0;
 uint8_t current_layer = 0;
 keyrecord_t delaying_layer = {};
 
+keyrecord_t waiting_key = {};
 
-void action_exec(keyevent_t event)
+// TODO: ring buffer: waiting_keys[]
+/*
+#define WAITING_KEYS_BUFFER 3
+static keyrecord_t waiting_keys[WAITING_KEYS_BUFFER] = {};
+static uint8_t waiting_keys_head = 0;
+static uint8_t waiting_keys_tail = 0;
+static void waiting_key_queue(keyevent_t event)
 {
-    /* count tap when key is up */
-    if (KEYEQ(event.key, last_event.key) && timer_elapsed(last_event_time) < TAP_TIME) {
-        if (!event.pressed) tap_count++;
-    } else {
-        tap_count = 0;
-    }
+}
+static void waiting_key_dequeue(keyevent_t event)
+{
+}
+*/
 
-    /* layer switch after LAYER_DELAY */
-    if (delaying_layer.action.code && timer_elapsed(delaying_layer.event.time) > LAYER_DELAY) {
-        switch (delaying_layer.action.kind.id) {
-            case ACT_LAYER_PRESSED:
-                layer_switch(delaying_layer.action.layer.opt);
-                break;
-            case ACT_LAYER_BIT:
-                layer_switch(current_layer | delaying_layer.action.layer.opt);
-                break;
-        }
-        delaying_layer = (keyrecord_t){};
-    }
-    action_t action = keymap_get_action(current_layer, event.key.row, event.key.col);
+static void process(keyevent_t event, action_t action)
+{
+    //action_t action = keymap_get_action(current_layer, event.key.row, event.key.col);
 
     debug("action: "); debug_hex16(action.code); debug("\n");
     debug("kind.id: "); debug_hex(action.kind.id); debug("\n");
@@ -146,29 +142,54 @@ void action_exec(keyevent_t event)
     debug("key.mods: "); debug_hex(action.key.mods); debug("\n");
 
     switch (action.kind.id) {
+        /* Key and Mods */
         case ACT_LMODS:
             // normal key or key plus mods
             if (event.pressed) {
-                register_mods(action.key.mods);
+                uint8_t tmp_mods = host_get_mods();
+                if (action.key.mods) {
+                    host_add_mods(action.key.mods);
+                    host_send_keyboard_report();
+                }
                 register_code(action.key.code);
+                if (action.key.mods && action.key.code) {
+                    host_set_mods(tmp_mods);
+                    host_send_keyboard_report();
+                }
             } else {
+                if (action.key.mods && !action.key.code) {
+                    host_del_mods(action.key.mods);
+                    host_send_keyboard_report();
+                }
                 unregister_code(action.key.code);
-                unregister_mods(action.key.mods);
             }
             break;
         case ACT_RMODS:
             if (event.pressed) {
-                register_mods(action.key.mods<<4);
+                uint8_t tmp_mods = host_get_mods();
+                if (action.key.mods) {
+                    host_add_mods(action.key.mods<<4);
+                    host_send_keyboard_report();
+                }
                 register_code(action.key.code);
+                if (action.key.mods && action.key.code) {
+                    host_set_mods(tmp_mods);
+                    host_send_keyboard_report();
+                }
             } else {
+                if (action.key.mods && !action.key.code) {
+                    host_del_mods(action.key.mods<<4);
+                    host_send_keyboard_report();
+                }
                 unregister_code(action.key.code);
-                unregister_mods(action.key.mods<<4);
             }
             break;
         case ACT_LMOD_TAP:
             break;
         case ACT_RMOD_TAP:
             break;
+
+        /* other HID usage */
         case ACT_USAGE:
 #ifdef EXTRAKEY_ENABLE
             switch (action.usage.page) {
@@ -189,6 +210,8 @@ void action_exec(keyevent_t event)
             }
 #endif
             break;
+
+        /* Mouse key */
         case ACT_MOUSEKEY:
 #ifdef MOUSEKEY_ENABLE
             if (event.pressed) {
@@ -200,6 +223,8 @@ void action_exec(keyevent_t event)
             }
 #endif
             break;
+
+        /* Layer key */
         case ACT_LAYER_PRESSED:
             // layer action when pressed
             switch (action.layer.code) {
@@ -228,19 +253,25 @@ void action_exec(keyevent_t event)
                                 delaying_layer = (keyrecord_t){
                                     .event = event,
                                     .action = action,
-                                    .mods = keyboard_report->mods
+                                    .mods = host_get_mods()
                                 };
                             }
                         } else if (tap_count > 0) {
                             register_code(action.layer.code);
                         }
                     } else {
-                        // type key after tap
-                        if (tap_count == 1) {
-                            delaying_layer = (keyrecord_t){};
-                            register_code(action.layer.code);
+                        // tap key
+                        if (KEYEQ(event.key, delaying_layer.event.key) &&
+                                timer_elapsed(delaying_layer.event.time) < TAP_TIME) {
+                            uint8_t tmp_mods = host_get_mods();
+                            host_set_mods(delaying_layer.mods);
+                            register_code(delaying_layer.action.layer.code);
+                            host_set_mods(tmp_mods);
+                            unregister_code(delaying_layer.action.layer.code);
+                        } else {
+                            unregister_code(action.layer.code);
                         }
-                        unregister_code(action.layer.code);
+                        delaying_layer = (keyrecord_t){};
                     }
                     break;
             }
@@ -366,12 +397,87 @@ void action_exec(keyevent_t event)
                     break;
             }
             break;
+
+        /* Extentions */
         case ACT_MACRO:
         case ACT_COMMAND:
         case ACT_FUNCTION:
         default:
             break;
     }
+}
+
+void action_exec(keyevent_t event)
+{
+    /* count tap when key is up */
+    if (KEYEQ(event.key, last_event.key) && timer_elapsed(last_event_time) < TAP_TIME) {
+        if (!event.pressed) tap_count++;
+    } else {
+        tap_count = 0;
+    }
+
+    /* When delaying layer switch */
+    if (delaying_layer.action.code) {
+        /* Layer switch when delay time elapses or waiting key is released */
+        if ((timer_elapsed(delaying_layer.event.time) > LAYER_DELAY) ||
+            (!event.pressed && KEYEQ(event.key, waiting_key.event.key))) {
+            /* layer switch */
+            switch (delaying_layer.action.kind.id) {
+                case ACT_LAYER_PRESSED:
+                    layer_switch(delaying_layer.action.layer.opt);
+                    break;
+                case ACT_LAYER_BIT:
+                    layer_switch(current_layer | delaying_layer.action.layer.opt);
+                    break;
+            }
+            delaying_layer = (keyrecord_t){};
+
+            /* Process waiting keys in new layer */
+            if (waiting_key.event.time) {
+                uint8_t tmp_mods = host_get_mods();
+                host_set_mods(waiting_key.mods);
+                process(waiting_key.event, keymap_get_action(current_layer,
+                                                             waiting_key.event.key.row,
+                                                             waiting_key.event.key.col));
+                host_set_mods(tmp_mods);
+                waiting_key = (keyrecord_t){};
+            }
+        }
+        /* when delaying layer key is released within delay term */
+        else if (!event.pressed && KEYEQ(event.key, delaying_layer.event.key)) {
+            /* tap key down */
+            uint8_t tmp_mods = host_get_mods();
+            host_set_mods(delaying_layer.mods);
+            register_code(delaying_layer.action.layer.code);
+            delaying_layer = (keyrecord_t){};
+
+            /* process waiting keys */
+            if (waiting_key.event.time) {
+                host_set_mods(waiting_key.mods);
+                process(waiting_key.event, waiting_key.action);
+                waiting_key = (keyrecord_t){};
+            }
+            host_set_mods(tmp_mods);
+        }
+    }
+
+    action_t action = keymap_get_action(current_layer, event.key.row, event.key.col);
+
+    /* postpone key-down events while delaying layer */
+    if (delaying_layer.action.code) {
+        if (event.pressed) {
+            // TODO: waiting_keys[]
+            waiting_key = (keyrecord_t){
+                .event = event,
+                .action = action,
+                .mods = host_get_mods()
+            };
+        } else {
+            process(event, action);
+        }
+    } else {
+        process(event, action);
+    }
 
     /* last event */
     last_event = event;
@@ -451,5 +557,6 @@ static void layer_switch(uint8_t new_layer)
 
         current_layer = new_layer;
         clear_keyboard_but_mods(); // To avoid stuck keys
+        // TODO: update mods with full scan of matrix? if modifier changes between layers
     }
 }
index 28c8a819fd6a8a5280b7281b5ed26329dee0bdb5..6ed3d780f640affa88668ab11a303b40090200db 100644 (file)
@@ -127,6 +127,11 @@ void host_clear_keys(void)
     }
 }
 
+uint8_t host_get_mods(void)
+{
+    return keyboard_report->mods;
+}
+
 void host_add_mods(uint8_t mods)
 {
     keyboard_report->mods |= mods;
index 4f1f234a9685a621b64a2c0a103c9a9064c8ce1a..c59fbfee6a3ff5661a36c551cbaa3ffcf3413361 100644 (file)
@@ -51,10 +51,13 @@ void host_consumer_send(uint16_t data);
 void host_add_key(uint8_t key);
 void host_del_key(uint8_t key);
 void host_clear_keys(void);
+
+uint8_t host_get_mods(void);
 void host_add_mods(uint8_t mods);
 void host_del_mods(uint8_t mods);
 void host_set_mods(uint8_t mods);
 void host_clear_mods(void);
+
 uint8_t host_has_anykey(void);
 uint8_t host_has_anymod(void);
 uint8_t host_get_first_key(void);
index 1e0b8c3edbf65577beb2b30aec170952d52f3683..4e955e129b6fe9454d781df878ea5212e16ac918 100644 (file)
@@ -68,7 +68,7 @@ void keyboard_task(void)
                     action_exec((keyevent_t){
                         .key = (keypos_t){ .row = r, .col = c },
                         .pressed = (matrix_row & (1<<c)),
-                        .time = timer_read()
+                        .time = (timer_read() | 1) /* NOTE: 0 means no event */
                     });
                     // record a processed key
                     matrix_prev[r] ^= (1<<c);
index 3ea75f5bb700f8466acf83bb3b66f84b7eddb37f..9fe1237aa41f4fa14b3f0a998ce2fe6315c1ed88 100644 (file)
@@ -149,8 +149,8 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
      */
     KEYMAP(ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12, INS, DEL, \
            TAB, NO,  NO,  NO,  NO,  NO,  WH_L,WH_D,WH_U,WH_R,NO,  NO,  NO,  BSPC, \
-           LCTL,NO,  ACL0,ACL1,ACL2,NO,  MS_L,MS_D,MS_U,MS_R,FN0, NO,  ENT, \
-           LSFT,NO,  NO,  NO,  NO,  BTN3,BTN2,BTN1,BTN4,BTN5,NO,  RSFT,NO, \
+           LCTL,NO,  ACL0,ACL1,ACL2,NO,  MS_L,MS_D,MS_U,MS_R,FN0, QUOT,ENT, \
+           LSFT,NO,  NO,  NO,  NO,  BTN3,BTN2,BTN1,BTN4,BTN5,SLSH,RSFT,NO, \
                 LGUI,LALT,          BTN1,               RALT,FN0),
 
     /* Layer 4: Matias half keyboard style (Space)
@@ -195,6 +195,8 @@ action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col) {
     action_t action;
     switch (key) {
         case KC_A ... KC_EXSEL:
+        case KC_LCTRL ... KC_LGUI:
+        case KC_RCTRL ... KC_RGUI:
             action.code = ACTION_KEY(key);
             break;
         case KC_SYSTEM_POWER ... KC_SYSTEM_WAKE:
@@ -206,12 +208,14 @@ action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col) {
         case KC_MS_UP ... KC_MS_ACCEL2:
             action.code = ACTION_MOUSEKEY(key);
             break;
+/*
         case KC_LCTRL ... KC_LGUI:
             action.code = ACTION_LMODS(MOD_BIT(key));
             break;
         case KC_RCTRL ... KC_RGUI:
             action.code = ACTION_RMODS(MOD_BIT(key)>>4);
             break;
+*/
         case KC_FN0 ... KC_FN7:
             action.code = pgm_read_word(&fn_actions[FN_INDEX(key)]);
             break;