qmk / qmk_firmware

Open-source keyboard firmware for Atmel AVR and Arm USB families
https://qmk.fm
GNU General Public License v2.0
18.27k stars 39.35k forks source link

[Feature Request] Hold down Leader Key to hit the key sequence #19297

Closed oizehsgl closed 1 year ago

oizehsgl commented 1 year ago

Feature Request Type

Description

English is not my native language; please excuse typing errors.

what i want

  1. hold KC_LEAD,tap KC_F,release KC_LEAD --> SEND_STRING("QMK is awesome.")
  2. tap KC_LEAD --> tap_code(KC_ESC)

    why i need it

  3. Sometimes your leader key is not on a comfortable place as the rest of keys on your sequence
  4. define LEADER_NO_TIMEOUT is a good solution

  5. I choose another solution(move leader key to a comfortable place)
  6. But there will be some problems
    • The comfortable place cannot be used effectively, because leader key is a single action key, can’t be used for anything else
    • Can't set LEADER_TIMEOUT to the right value for me
  7. type KC_LEAD ~ type KC_F = 300ms
  8. type KC_LEAD ~ type KC_N = 200ms
  9. so i defined LEADER_TIMEOUT = 300ms
  10. I wasted 100ms when i type KC_LEAD,type KC_N
  11. if i defined LEADER_PER_KEY_TIMING,I will waste more time

    i tried

  12. Mod-Tap
  13. Tap-Dance
  14. change process_record_user()
  15. change leader_start() and leader_end() But i didn't solve my problem,maybe I don't know enough about these functions.Finally i try to change the source code to solve my problem,it seems to work fine.

    my question

  16. Does anyone have the same need?
  17. Is there a solution without changing the source code?
sigprof commented 1 year ago

You can call qk_leader_start(); from a custom keycode handler — this will do the same thing as the QK_LEAD keycode. If you do that in process_record_user(), you should probably have return false; after that (if you return true, your custom keycode will also be a part of the leader key sequence — but you can also use that feature to have multiple leader keys with different behavior).

And you can either use a tap dance or intercept a MT/LT keycode to implement different behavior for tap and hold.

oizehsgl commented 1 year ago

You can call qk_leader_start(); from a custom keycode handler — this will do the same thing as the QK_LEAD keycode. If you do that in process_record_user(), you should probably have return false; after that (if you return true, your custom keycode will also be a part of the leader key sequence — but you can also use that feature to have multiple leader keys with different behavior).

And you can either use a tap dance or intercept a MT/LT keycode to implement different behavior for tap and hold.

Thank you for your reply! I try it and qk_leader_start() work fine. here is my code

  1. config.h #define LEADER_TIMEOUT 10000
  2. keymap.c
    
    LEADER_EXTERNS();
    void matrix_scan_user(void) {
    LEADER_DICTIONARY() {
    leading = false;
    // demo
    SEQ_ONE_KEY(KC_F) {
      SEND_STRING("QMK is awesome.");
      did_leader_succeed = true;
    }
    leader_end();
    }
    };
    void leader_start(void) {
    did_leader_succeed = false;
    }
    void leader_end(void) {
    if (!did_leader_succeed) {
    tap_code(KC_ESC);
    }
    }

bool process_record_user(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case MY_LEAD_ESC: if(record->event.pressed) { qk_leader_start(); return false; } else { leader_time=0; return false; } return true; } return true; }

oizehsgl commented 1 year ago

The above code has a bug. When i hold leader and tap another key six times,it will send ESC.

drashna commented 1 year ago

The above code has a bug. When i hold leader and tap another key six times,it will send ESC.

Your code says to send escape if the sequence did not succeed:

void leader_end(void) {
  if (!did_leader_succeed) {
    tap_code(KC_ESC);
  }
}

And it looks like leader keys only supports 5 keys in the sequence, so when you hit the sixth, it ends.

zzzachzzz commented 1 year ago

Is there any way to pull this off, while still maintaining a low LEADER_TIMEOUT? The idea is that when the leader key is held the timeout would be bypassed, at least for the time between the leader key hold and the first key of the leader sequence, in the case that LEADER_PER_KEY_TIMING is set.

The use case I'm going after is binding Leader + j / k to Page Down / Page Up. Being a key useful for spamming, it would be ideal to be able to hold the leader key and then send multiple leader sequences while held.

Or if there's another feature that would be more appropriate to this use case let me know. I think of Leader as a custom modifier key.

github-actions[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had activity in the last 90 days. It will be closed in the next 30 days unless it is tagged properly or other activity occurs. For maintainers: Please label with bug, in progress, on hold, discussion or to do to prevent the issue from being re-flagged.

github-actions[bot] commented 1 year ago

This issue has been automatically closed because it has not had activity in the last 30 days. If this issue is still valid, re-open the issue and let us know. // [stale-action-closed]