tmk / tmk_keyboard

Keyboard firmwares for Atmel AVR and Cortex-M
3.98k stars 1.7k forks source link

Possible for "Simultaneous Key Presses" and when to use "add_weak_mods" #450

Closed dunkarooftop closed 7 years ago

dunkarooftop commented 7 years ago

I been using Karabiner on mac which is a awesome tool, one of the function is "Simultaneous Key Presses" which I use a lot. (it's like playing piano on your keyboard)

For example, when press "A" and "B" those 2 key together do event "Command + C" for copy

Is it possible code it in tmk? Karabiner is not working on the latest version of macOS, I am trying to move all the mod I have there to tmk when possible.

Also I don't use C so a lot of my function are hacks that I piece together and not fully understand why it work. My question is what is add_weak_mods and when to use send_keyboard_report();

Here is what I have for dual role key for LGUI

    case LGUI_LPAREN:
        if (record->event.pressed) {
            if (record->tap.count > 0 && !record->tap.interrupted) {
                if (record->tap.interrupted) {
                    dprint("tap interrupted\n");
                    register_mods(MOD_BIT(KC_LGUI));
                }
            } else {
                register_mods(MOD_BIT(KC_LGUI));
            }
        } else {
            if (record->tap.count > 0 && !(record->tap.interrupted)) {
                add_weak_mods(MOD_BIT(KC_LSHIFT));
                send_keyboard_report();
                register_code(KC_9);
                unregister_code(KC_9);
                del_weak_mods(MOD_BIT(KC_LSHIFT));
                send_keyboard_report();
                record->tap.count = 0;  // ad hoc: cancel tap
            } else {
                unregister_mods(MOD_BIT(KC_LGUI));
            }
        }
        break;

and last one more question for MARCO , is it possible to speed up the speed

Thanks !! God I love how I can customize my hhkb, thanks hasu

tmk commented 7 years ago

1) TMK doesn't support 'chording' or 'chorded' keys, you may kind of emulate them with tap key(dual role) but wont' be useful to define in current layer based keymap system.

2) you can use send_keyboard_report to control timing of sending keyboard report. In most cases it is not needed. Use register_* functions instead.

3) maybe. All other activity have to be stopped during macro is running in current imprement.

tmk commented 7 years ago

And I can't remember how weak_mods works :D I'll look into it if I get time.

dunkarooftop commented 7 years ago

Thanks for the reply hasu, if I replace send_keyboard_report with register_* functions would the fallowing code do the same thing?

add_weak_mods(MOD_BIT(KC_LSHIFT));
send_keyboard_report();
register_code(KC_9);
unregister_code(KC_9);
del_weak_mods(MOD_BIT(KC_LSHIFT));
send_keyboard_report();
register_code(MOD_BIT(KC_LSHIFT));
register_code(KC_9);
unregister_code(KC_9);
unregister_code(MOD_BIT(KC_LSHIFT));
tmk commented 7 years ago

In that case send_keyboard_report() is needed because add/del_weak_mods() doesn't send report to host(register). I should have said clearly:

Use [un]register_code() instead unless send_keyboard_report() is needed.

And I read code about weak_mods, I found it is used to keep current modifier state and not to change it by function or macro action. Assuming you hold LShift key and run the LGUI_LPAREN action somehow, unregister_code(KC_LSHFT) will remove LShift from keyboard report despite LShift is still depressed.

dunkarooftop commented 7 years ago

thank you for clear things up for me, hasu really appreciated.

One more stupid question, is it possible to have tmk send midi key to the os?

tmk commented 7 years ago

No, it doesn't support MIDI.

dunkarooftop commented 7 years ago

thanks for the reply, I will close this issues now :)

dunkarooftop commented 7 years ago

One more question on the LGUI_LPAREN

                if (record->tap.interrupted) {
                    dprint("tap interrupted\n");
                    register_mods(MOD_BIT(KC_LGUI));

What does that block of code really do ? Seems kinda strange that this block of if doesn't follow up with any else statement. I comment it out and compile and the keyboard works normal. But everywhere I see when people try doing dual role kind of stuff all included that block

    case DUALROLE_KEY:
        if (record->event.pressed) {
            if (record->tap.count > 0 && !record->tap.interrupted) {
                if (record->tap.interrupted) {
                   // I don't understand what happen here
                }
            } else {
                // When key is hold down do this
            }
        } else {
            if (record->tap.count > 0 && !(record->tap.interrupted)) {
                // When key is tap do this
            } else {
                // On key up if the key was held down before do this
            }
        }
        break;

Is my understanding correct thanks

tmk commented 7 years ago

In tmk dual role key(tap key) is recognized basically as 'tap' when the key is typed in TAPPNING_TERM(200ms) and as 'hold' when it is held beyond the term. But in real usage modifier key can be depressed only shorter time than the term, for example when user intends to input LGUI+d quickly, LGUI will be released probably under 200ms. In this case you get '(' and 'd' against the intention without the tap.interrupted block. The block becomes true and be executed when the case above occurs.

dunkarooftop commented 7 years ago

Understand now thanks !! :)