Qmk_firmware: [Feature Request] LT(1, TG(1))

Created on 9 Jan 2020  Â·  15Comments  Â·  Source: qmk/qmk_firmware

make it work
please

as you can see main idea is to provide variability of switching layer,
you can press and hold or just tap

enhancement help wanted

Most helpful comment

This ability to tap to toggle or hold to temporarily activate a layer already exists in TT (tap toggle)

For it to work the way you want, with a single tap rather than the default 5, you'd need to add the following to your config.h:

#define TAPPING_TOGGLE 1

All 15 comments

This ability to tap to toggle or hold to temporarily activate a layer already exists in TT (tap toggle)

For it to work the way you want, with a single tap rather than the default 5, you'd need to add the following to your config.h:

#define TAPPING_TOGGLE 1

Oh wow, that's nice, thank you @ridingqwerty !

_Some one should add this tip into the docs_

But it would be even nicer to have not broking default behavior of TT()

but what if i want to assign different functions on the one button?

TT(1, KC_LSHIFT)

LT(layer, kc) - momentarily activates layer when held, and sends kc when tapped.

i need just opposite LT(held_kc, tappep_layer)

If I understand correctly, you want a particular keycode to be produced when the key is held for some time, and a layer to be activated on a quick tap?

There’s no baked in function for that, but you could create a custom keycode that utilizes a timer to determine tap or hold state against a specified threshold, produce the keycode if timer exceeds the threshold, or activates a one shot layer if it falls short of the threshold.

I don’t utilize one-shot layers so can’t give a complete solution at the moment, but the rest is pretty straightforward. If this is what you’re after and you need help, feel free to ping me.

yeah, that what i need

timer, mod key and MO(layer)

just make a timer logic and i do the rest

Here’s an example from my userspace:

https://github.com/qmk/qmk_firmware/blob/2d051d8de3787de889ff0f0301153dbb4e2e1272/users/ridingqwerty/process_records.c#L13-L33

I’ll post a skeleton with comments below.

uint16_t key_timer;
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
  switch(keycode) {
    case MACRO_NAME:
      if (record->event.pressed) {
        key_timer = timer_read();
        // key is depressed
        // start timer and initiate hold actions
      } else {
        // key is released
        // unregister hold actions, read timer
    if (timer_elapsed(key_timer)) < 200) {
          // short timer
          // do the tap thing
    }
        else {
          // long timer
          // possibly do a “hold” thing
        }
      }
      return false; break;
  }
  return true;
}

so this code won't compile

image

i guess i have to wrap keycodes into _register_code_ function right?

that's another way just a little confusing me, you know heh

found nice way SFT_T(KC_CAPS)

but i need SFT_T(KC_CAPS+TG(LAYER))

Yeah, you can’t just put TG (and other such functions like LT, MT, etc.) or normal keycodes into the macro directly like that.

I think you’d replace TG(RUS); with layer_invert(RUS);.

For KC_LSHIFT I’m not totally sure what you’re going for(IIRC kind of like TT, but able to do a mod instead of layer on hold), but just to clarify my example, the outer if statement is everything that happens when the key is pressed — so if you want hold to be a shift you need to register_mods(MOD_LSFT); in the same block where the key timer is set, and replace KC_SHIFT; with unregister_mods(MOD_LSFT); — you probably also want to unregister the mod before the layer command.

so much meh..

    case MACRO_NAME:
        if (record->event.pressed)
            {
                key_timer = timer_read();
                register_mods(MOD_LSFT);
            }
        else
            {
                if (timer_elapsed(key_timer) < 200)
                    {
                    layer_invert(RUS);  // change layer
                    register_mods(MOD_LALT(MOD_LSHIFT));  // change lang
                    unregister_mods(MOD_LALT(MOD_LSHIFT));
                    }
                else
                    {
                    unregister_mods(MOD_LSFT);
                    }
            }
        return false;
        break;

shift functionality works great, layer switching it seem ok too, but language is not switching(and won't compile)

possible solution

tap_code16(S(A(KC_NO)))
tap_code16(A(S(KC_NO)))

Working like a charm! =)

Thank you @ridingqwerty !!

uint16_t key_timer;
bool process_record_user(uint16_t keycode, keyrecord_t *record)
{
  switch (keycode)
  {

    case RUS_LAT:
        if (record->event.pressed)
            {
                key_timer = timer_read();
                register_mods(MOD_LSFT);
            }
        else
            {
                unregister_mods(MOD_LSFT);
                if (timer_elapsed(key_timer) < 200)
                    {
                    layer_invert(RUS);
                    tap_code16(S(A(KC_NO)));
                    }
                else
                    {
                    }
            }
        return false;
        break;
...

Oh excellent, I’m happy we could arrive at a solution that works for you.

but now i having issue with timer - it is too short, that any hotkey with Shift are also switching the lang

i need to define low threshold somehow

if (300 < timer_elapsed(key_timer) < 1500)

_this is not work_

You cannot do compound relations like that in C, you’d need to do something like

if (300 < timer_elapsed(key_timer) && timer_elapsed(key_timer) < 1500)

Note that this will trigger only when the key is held for more than 0.3s and less than 1.5s, so requires more precision than a quick tap.

Was this page helpful?
0 / 5 - 0 ratings