qmk / qmk_firmware

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

A better implementation of Grave Escape under macOS? #6006

Closed Morid1n closed 2 years ago

Morid1n commented 5 years ago

Under macOS, Grave Escape (KC_GESC) currently makes accessing the backtick character impossible. I might have a possible solution.

Feature Request Type

Description

KC_GESC under macOS currently works as follows:

Since the Option/Alt + ESC and Control + ESC shortcuts are "free to use", I would like one or both of them to generate the backtick character (which I can't live without). This would basically solve the whole problem.

fauxpark commented 5 years ago

So, unfortunately Control+` does not produce `, and since the way Grave Escape works is by simply sending a KC_GRV or KC_ESC without tweaking the held modifiers, it's a no-go. I got macOS to type a backtick with Alt+`, but this appears to be a dead key in certain circumstances so may not be 100% what you need.

// placed underneath the GRAVE_ESC_SHIFT_OVERRIDE block in quantum.c
#ifdef GRAVE_ESC_ALT_FORCE
      // if ALT is pressed, KC_GRV is always sent
      if (get_mods() & MOD_MASK_ALT) {
        shifted = 1;
      }
#endif

Making this feature work properly will likely require a little bit of a rewrite to keep track of the held mods and disable/enable them when it comes time to send the Grave or Escape.

Morid1n commented 5 years ago

Funny thing. If I hold Shift + Alt + KC_GESC, I get a Ŕ character, but if I add Control after pressing those three, I get a backtick! Proof: ````````````. Spams the character though. 🙂

How much work would it be to do an #ifdef for Control?

Morid1n commented 5 years ago

Another idea: since LShift + ESC are used to generate ~, then LShift + LControl + ESC could be used for backtick `.

drashna commented 5 years ago

Do none of these help?

https://docs.qmk.fm/#/feature_grave_esc?id=configuration

Also, there is: https://docs.qmk.fm/#/feature_grave_esc?id=caveats

fauxpark commented 5 years ago

@drashna - the issue is that the modifiers controlling Grave/Esc aren't removed before sending it, which presents problems when there is a key combination mapped to it. Thus as I mentioned above, we need to unset the mods first and put them back afterwards. (I can see this being an issue for Alt and GUI on Windows)

drashna commented 5 years ago

Ah, okay.

And actually, looking at it, that shouldn't bee too difficult to fix.

Morid1n commented 5 years ago

Any news on this? Tell me what I can do to help, if needed.

This function (e.g LShift + LGUI + KC_GESC to generate backtick and LShift + KC_GESC for tilde) would free up 1 key on my 65s under MacOS and make life so much easier.

fauxpark commented 5 years ago

Honestly, I'm not convinced this is fixable, at least not without some serious side effects that would basically render it useless. The problem is that when KC_GESC is pressed with Alt or GUI, we first have to unset those modifiers in order to send the proper key combination. This will complete a "tap" event from the perspective of the OS, and on Windows (maybe Linux too) will change the focus, to the menu bar or the start menu respectively.

Morid1n commented 5 years ago

What if another modifier was used for the backtick? E.g. Shift + Alt + KC_GESC?

fauxpark commented 5 years ago

Same deal, you have to release that Alt before sending either KC_GRV or S(KC_GRV).

Morid1n commented 5 years ago

Oh boy. I’m currently duplicating a key. GESC top left and a regular backtick+tilde top right, just for that backtick... such a waste.

noroadsleft commented 5 years ago

I used to split time between macOS and Windows, and at the time, I had my top left key (60%) as a dedicated Escape key, and I modded my Left Ctrl key so it was KC_LCTL when held, but KC_GRV when tapped.

yanfali commented 5 years ago

I used to split time between macOS and Windows, and at the time, I had my top left key (60%) as a dedicated Escape key, and I modded my Left Ctrl key so it was KC_LCTL when held, but KC_GRV when tapped.

I do the inverse. LCTL_T(KC_ESC) on capslock and KC_GRV on the grave

Morid1n commented 5 years ago

Seems like I’ll have to do something similar. Siding towards Caps Lock (which is CTRL for me) tap for ESC.

masterzen commented 5 years ago

My issue specifically is the dead key backtick which is very helpful for international users. On a classic macos keyboard you get it with ALT+`, but it isn't possible to get it with KC_GESC. I still haven't found a good solution to combine all usage in a key. In retrospect, I think what I'd like to have is (based on my usage):

I might as well use a LCTL_T(KC_ESC) on caps-lock (which is CTRL on my keyboards)...

etchnsketch commented 3 years ago
* normal ` on single press

* dead key ` on ALT+`

* normal ~ on SHIFT+`

* ESC on CTRL/GUI+`

@masterzen this is exactly what I'm trying to do as well:

masterzen commented 3 years ago

@20four80five I made an implementation that works as you wish:

https://github.com/masterzen/qmk_firmware/blob/07159c2c1c651d7ae47b54182503c73b7b9d173e/keyboards/exclusive/e65/keymaps/masterzen/keymap.c#L113-L125

etchnsketch commented 3 years ago

@masterzen - Happy holidays!

I finally managed to get this working! Let me know your thoughts.

Aside from what I mentioned earlier above:

  • ESC key = back-tick `
  • LeftGUI + ESC key produces Escape
  • SHIFT + ESC key produces ~

...I also wanted to be able to Command + Shift + Escape to cycle through windows of the same application.

I hope this helps other folks looking to do the same thing on macOS 🤞🏼


I'm still new to QMK - this is what I added to my keymap.c:

#include QMK_KEYBOARD_H

// ADDED THIS
enum my_keycodes {
    BACK_TICK = SAFE_RANGE,
};

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
    [0] = LAYOUT_66_ansi(
        BACK_TICK, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_INS, KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_DEL, KC_ENT, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_LCTL, KC_LALT, KC_LGUI, KC_SPC, KC_RGUI, KC_RCTL, MO(1), KC_LEFT, KC_DOWN, KC_RGHT),
    [1] = LAYOUT_66_ansi(
        KC_TRNS, KC_BRID, KC_BRIU, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_MUTE, KC_VOLD, KC_VOLU, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_CAPS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS)
};

// ADDED THIS
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
  switch (keycode) {
    case BACK_TICK: {
      static uint8_t kc;
            static bool leftGui;
            static bool leftShift;

      if (record->event.pressed) {
        leftGui = get_mods() & (MOD_BIT(KC_LGUI));
                leftShift = get_mods() & (MOD_BIT(KC_LSFT));

        if ((leftGui) & !(leftGui && leftShift)) {
          del_mods(MOD_BIT(KC_LGUI));
          kc = KC_ESC;
        } else {
          kc = KC_GRV;
        }

                register_code(kc);

                if ((leftGui) & !(leftGui && leftShift)) {
                    register_code(KC_LGUI);
                }

      } else {
        unregister_code(kc);
      }
    }
  }
  return true;
}
Soundtoxin commented 3 years ago

I noticed that right shift + esc still makes a ~ with this key configuration (KC_GESC), contrasting with how the same feature works on the Pok3r's factory firmware. It would be nice if only left shift did it. My work-around in the meantime was to: 1) put ` on another layer or two where esc is so I can hit it when needed (same as Pok3r) 2) on a different layer put a shift + escape combo press where the escape key is, because it's otherwise impossible to use shift-escape, which is needed to leave the "passthrough" mode in qutebrowser.

On my Pok3r I used to just hit right shift and escape for those situations. I was gonna open an issue about this, but this one seems close enough. I'm not on macOS, fyi. edit: did not realize GUI + ESC would make a ` with the default config... but I still would like it if right shift didn't make a ~ like left shift does.

alanhoyle commented 3 years ago

I am noticing this because a system-wide macOS keystroke is getting suppressed/redirected.

On macOS/OSX going back at least as long as I've used it, option+command+Esc (⌥⌘ Esc) should bring up the Force Quit... dialog box, however, it's sending option+command+` (⌥⌘`) instead.

kbrock commented 2 years ago

I'm pretty sure you want to define GRAVE_ESC_ALT_OVERRIDE. So command back tick and command alt escape both work.

There are a ton of these options, google/grep for GRAVE_ESC_ALT_OVERRIDE and you should find behavior that works for you.

But I'm using VIAL right now and don't know how to get that option into my firmware (may need to compile myself)

EDIT: the latest version of VIAL lets you set the GRAV/ESC behavior.

Be aware that qmk has some wonderful features and flexibility that VIA/VIAL will never be able to touch. Lets just hope that qmk and vial converge rather than split like tmk/qmk did.

alanhoyle commented 2 years ago

@kbrock, I'd been unaware of VIAL before. Thanks for pointing it out. Perhaps since it's open source (unlike VIA), there would be a way to get it implemented there? I recently bought a VIA-compatible keyboard and it's much easier than recompiling/flashing with regular QMK, albeit not as flexible.

zvecr commented 2 years ago

This issue has been automatically closed because it has not had any recent activity. If this issue is still valid, re-open the issue and let us know.