How to Use Hotkeys to Switch Between Two Keyboard Layouts

I know Keyboard Maestro can create "Set Keyboard Layout" Action, such as pressing shift+control+J to switch to Japanese input method, but I want to achieve pressing the same shortcut key to switch two specific input methods, such as pressing caps (F19)* key to switch between English and Japanese, how to achieve this?

*: I have installed Karabiner-Elements and map F19 key to caps key

There may be something more Maestronic, but this is what I do.

(Adjust the two languages in the conditional action to match your pattern)


Toggle keyboard layout between two languages.kmmacros (3.7 KB)


Expand disclosure triangle to view JS Source
(() => {
    "use strict";

    ObjC.import("Carbon");
    ObjC.bindFunction(
        "CFMakeCollectable",
        ["id", ["void *"]]
    );

    return ObjC.unwrap(
        $.CFMakeCollectable(
            $.TISGetInputSourceProperty(
                $.TISCopyCurrentKeyboardInputSource(),
                $.kTISPropertyInputSourceID
            )
        )
    );
})();
2 Likes

PS to get a localizedName property for the active keyboard layout, as well as (or instead of) an inputSourceID, you can obtain a JSON variable with the variant code below (in a JXA action), and extract the value of the key you want using Keyboard Maestro's JSONValue token.

token:JSONValue [Keyboard Maestro Wiki]


Expand disclosure triangle to view JS Source
(() => {
    "use strict";

    ObjC.import("Carbon");
    ObjC.bindFunction(
        "CFMakeCollectable",
        ["id", ["void *"]]
    );

    // keyboardLayout ::
    // () -> {source::String, localized::String}
    const keyboardLayout = () => {
        const source = $.TISCopyCurrentKeyboardInputSource();

        return [
                ["source", $.kTISPropertyInputSourceID],
                ["localized", $.kTISPropertyLocalizedName]
            ]
            .reduce((a, [k, v]) => Object.assign(a, {
                [k]: ObjC.unwrap(
                    $.CFMakeCollectable(
                        $.TISGetInputSourceProperty(
                            source, v
                        )
                    )
                )
            }), {});
    };

    return JSON.stringify(
        keyboardLayout(),
        null, 2
    );
})();

Which returns KM variable values like:

{
  "source": "com.apple.inputmethod.SCIM.ITABC",
  "localized": "Pinyin - Simplified"
}
2 Likes

Thank you ComplexPoint! It works for me!

1 Like

Hey Guys,

There's a text-token available for the keyboard layout:

%KeyboardLayout%

-Chris

4 Likes

Cool! I tried it, and compared to using the script, the response speed has been improved (it is more obvious when switching quickly).

1 Like

Thanks – I guessed there must be something by now.

That looks like a sensible choice – the LocalizedName rather than the InputSourceID.

1 Like