One thing I like about the UHK is that, by default, 【Mod+d】 is an equivalent of 【Alt+Tab】.

UHK navigation schema

Moreover, it’s possible to keep mod key pressed, making it act just like 【Alt+Tab】. It seems that the mod layer remembers the last sent modifier key and keep sending this modifier key as long as Mod is being pressed.

Another way to see it is: let’s suppose 【Mod+d】 is a simple shortcut to 【Alt+Tab】. When releasing d, it would be equivalent to releasing Alt and Tab altogether. Since this is not what happens, something else is going on.

The way UHK behave is nice, since it lets us switch windows just like a regular 【Alt+Tab】 would do.

Switching windows with the M01

On the M01. There is no custom way to switching windows. You are expected to hit 【Alt+Tab】, however, Alt and Tab are on different halves of the keyboard. Thus, the default way to switch windows on the M01 requires both hands, which is quite frustrating. ( ͡° ͜ʖ ͡°)

M01 default layout

The naive way, Bind 【Alt+Tab】 to 【Fn+d

One would try to map 【Fn+d】 to 【Alt+Tab】 but this would not work. Actually the problem is already depicted in this thread here (along with a partial solution). In summary, mapping 【Fn+d】 to 【Alt+Tab】 would act like a simple shortcut: In 【Fn+d】 chord, releasing d key would be like releasing Alt and Tab altogether.

It’s complicated, let’s change the firmware

Let’s be honest, solving this issue is harder than it looks. One way to look at it is to imagine an abstract concept of transcient switching window session (basically a fancy term I came up with which represents the user inputing 【Alt+Tab+…+ Tab】 ).

Window switching transcient session This is a transcient window switching session

On the keyboard, we can try to represent a TWSS with these characteristics:

  • It will begin when the users hits 【Fn+d】.
  • It ends when user releases Fn key.
  • During it is active, it will simulates user hitting Alt
  • Will be accepting these keybindings
Key Bound to
Fn+d Alt+Tab
Fn+f
Fn+e
Fn+c
Fn+s

The key bindings mentionned above are purely suggestions, they override default mouse control on the M01 since I don’t use this function. You may find useful to bind them differently

We represent our TWSS session with this kaleidoscope plugin:

/** In charge of keeping alt pressed on during alt tab session
 * Alt tab session ends when stopping key release are detected */
class WindowsSwitcherTranscient : public kaleidoscope::Plugin {
  public:
    enum State { NOT_SWITCHING, SWITCHING };

    const static int stopping_array_s = 2;
    Key stopping_keys[stopping_array_s] = { Key_Escape, ShiftToLayer(FUNCTION) };

    WindowsSwitcherTranscient() { };
    void activate() { alt_press_on(); }

    kaleidoscope::EventHandlerResult onKeyswitchEvent(Key &mapped_key, KeyAddr key_addr, uint8_t keyState) {

      if (state == NOT_SWITCHING)
        return kaleidoscope::EventHandlerResult::OK;

      for (int i = 0; i < stopping_array_s; i++) {
        Key k = stopping_keys[i];
        if (mapped_key == k && keyToggledOff(keyState)) {
          alt_press_off();
          break;
        }
      }

      return kaleidoscope::EventHandlerResult::OK;
    }
    kaleidoscope::EventHandlerResult beforeReportingState() {
      if (state == NOT_SWITCHING)
        return kaleidoscope::EventHandlerResult::OK;

      handleKeyswitchEvent(Key_LeftAlt, UNKNOWN_KEYSWITCH_LOCATION, IS_PRESSED | INJECTED);
      return kaleidoscope::EventHandlerResult::OK;
    }
  private:
    void alt_press_on() { state = SWITCHING; };
    void alt_press_off() { state = NOT_SWITCHING; };
    State state = NOT_SWITCHING;
} WindowsSwitcherTranscient;

A macro is defined which is bound to 【Fn+d】, it calls

/** Macro used for enabling alt-tab transcient mode */
static void windowSwitch(uint8_t keyState) {
  kaleidoscope::hid::pressKey(Key_Tab, keyToggledOn(keyState));
  WindowsSwitcherTranscient.activate();
}

You can find a complete exemple firmware here with no dependencies on external plugin: complete example. Also, there is a third party plugin available here: https://github.com/Nimamoh/Kaleidoscope-TranscientWindowSwitchingState. The third party plugin is the more likely to be maintained

It is certainly not the best solution as I am sure we could find a nice usage of M01 layers to help us solve this problem but it get the job done without much hassle