Key Chords

I'd like to define a Keyboard Maestro macro that I can trigger if I enter a certain key chord.

Key chords are sequences of two hot key presses. Many editors like Emacs, Visual Studio etc. support them and they can vastly expand the set of possible hot key combinations one can use to manage any action.

For example, I could bind Cmd+S Cmd+N to "next song in Spotify" (i.e. S => Spotify => N = Next Song).

Does Keyboard Maestro support chords?

In short: No.

But you might be able to do something similar using a Typed String trigger.

So with this you would NOT use a modifier key, but a sequence of normal keys.
Maybe something like:
;sp.ns𝍖
where "𝍖" is the SPACE key.

as the trigger for the spotify next song.

One important caution here is that you should use typed string triggers ONLY in a text field, and KM will (by default) delete what you typed before performing the Actions in your Macro.

You could also use a Macro Group Palettes. Trigger the palette with the first keystroke, and then the specific Macro with the second.

I realize that “try another app” might not be a solution that appeals to some folks, but Apptivate can do “chords”, and those chords can trigger scripts, which could include Keyboard Maestro macros.

It’s a free app (hasn’t been updated in awhile, unfortunately, but it worked OK last time I tried it) so you can download it and try it out.

3 Likes

See How do I use a multiple keystroke trigger? for a discussion of options.

Yes and no. Keyboard Maestro supports chords, but the keys will always be swallowed (ie, Command-S in your case will always be swallowed, which would be bad). The FAQ explains why this is necessary for proper behaviour.

So I read the FAQ carefully and if I'm not misunderstanding, there should be the possibility of doing more than what is currently possible given the system of constraints.

Logic dictates that the Option-F A should go through to the system unimpeded, but Option-F R should be swallowed entirely. But this is impossible. The only way to do it would be to swallow the Option-F key, and then swallow the second key and then resubmit the Option F and the second key unless it matches Option-F R.

However, that is fraught with peril and cannot work robustly in the presence of other applications placing things on the keyboard event queue (or even a sufficiently fast typist).

For example, suppose you quickly typed Option-F A B. Keyboard Maestro would have swallowed the Option F and then the A, and then resubmitted it to the event queue, resulting in the stream of characters B, Option-F, A. There is no way to avoid this race condition, and as such Keyboard Maestro does not support any such mechanism.

In particular, what if I reserve Option-F entirely for Keyboard Maestro. In other words, assume that no matter what it is swallowed —just as would be expected if I only mapped Option-F.

However, in this case, I also specify that afterward, if R (or Option-R) is typed, then that is also swallowed. I'm not sure I see any issue with the scenario. Of course I am giving up any possibility that the application can use for example Option-F R to mean something in particular (or anything else that follows Option-F). In fact, both keys would be swallowed if typed. Which is exactly what happens in Emacs.

At most, it just complains "Option-F R is undefined" and moves on. No need to put anything back on the event queue. No race condition.

Is there any flaw in this logic? This seems like it would enable me to use chords like Ctrl-C Ctrl-C, Ctrl-C Ctrl-K, etc. to take actions, just as in Emacs. Of course I am giving up not only Ctrl-C, but the next keystroke afterward.

But that's a price that any user of a chording keyboard app is willing to pay for more flexibility! (and Keyboard Maestro is incredibly flexible)

2 Likes

Yes, and given that restriction, you can do this easily.

Create a Macro Group, configure it to be active for one action when you press the Option-F key, and put your macros in there with whatever hot key you desire for the second key.

2 Likes

Confirmed this works, thanks... is there a way to nest macro groups? I would prefer not to pollute my top level groups with "AppX - Cmd+[A-Z] chord start" but I wouldn't at all mind if this were nested inside a top level "AppX" macro group.

No, there is only one level of groups. It has occasionally been requested but the additional complexity of nested groups is not worth the value for the vast majority of Keyboard Maestro users.

I started testing this out and it seems great.

It's essentially software based keyboard layers and can work similarly to how VS Code (and other editors) use command-k.

I was originally able to get it to work in its simplest form based on what @peternlewis wrote above. (Although now it doesn't work at all, and I just hear a system beep when I try my hot key: super-k. I'm not sure what that's about. But maybe the issue I mention below is related.)

But I've run into some issues around this.

I wanted to have some type of system-wide visual indication when option-f* was active/available.

*To use @peternlewis's example hot key.

The most obvious solution was to show the Macro Palette for that group via Shows a palette for one action when. I like this because not only would it be a pronounced visual indicator that the first key of the chord was pressed (and awaiting the second) but it would also show all of the available macros for this group/layer.

However I'm not sure if that will also work with/fulfill the Active for one action setting mentioned above.

But even worse than that, I can't seem to get a Macro Palette to show at all.

  • I setup a very simple macro group, set it up as noted (I think), but pressing the hot key does not show the macro palette.

Screen Shot 2024-06-19 at 4.01.47 PM

  • I tried check all of the checkboxes and different options for the dropdowns.

  • I downloaded @DanThomas's Ultra Claw Palette test group, just to make sure it wasn't something I was doing wrong. I imported it, enabled the group, and tried the macro and it too didn't show the macro palette. I tried different hot key triggers and none would show the macro palette.

  • I tried Show/Hide __ Palette actions in other macros outside of this group, but they didn't seem to work as expected either.

  • I've tried restarting the KM Engine.

I have a feeling I'm missing something really obvious or something else in my system is disrupting the display of a macro palette.

There are other related behaviors that don't seem to work (ie: None of the Display in menu bar options seem to do anything), but I won't go into detail about them for now. Since they may start working if someone knows what's happening with the issue above.


Assuming something weird (or dumb on my part) is happening above, there's still my general questions about Key Chords in Keyboard Maestro:

  1. What is the best system wide visual indication that chording has started via a hot key (ex: option-f) and the engine is waiting for the second key?

  2. Is it possible to both show the palette (that will list all of the macros in this group/layer) while still functioning as @peternlewis mentioned above re: Activate for one action when?

  3. Is there any visual indication within Keyboard Maestro (or its menu) that a macro group's state is Active/Inactive?

    • For example, an enabled/disabled group or macro has lowered opacity icon/text, checkbox for `Enabled macro group", etc.
    • I was often finding myself wondering if my tests were failing because I thought the group was active when it was actually inactive, because I couldn't find any visual indication of its state.

I've read through a bunch of documentation* and forum posts. But I have a feeling I must be missing something obvious. I'm sorry in advance :slight_smile:

Maybe someone could suggest some basic tests or point out the city-sized hole in my understanding.

Thank you!

*Related docs/posts

Try the simplest thing first: Does it work if you set your "_Chord Testing" hot key to, say, ⌥F?

People often report "interesting" issues when using the hyperkey modifier, and your screen shot suggests you are using that here.

Agreed.

tl;dr: It worked!

I switched to shift-a and then everything started working as expected.

But as I tested more, I noticed things. More below.

Definitely a good point. I was thinking that too. In fact, I tried that early on and I think maybe it worked at one point, but then stopped working again with this non-hyper key trigger.

fyi: My hyper key is mapped via Karabiner Elements and it's set to be either a hyper key or esc if no key is pressed directly after.

So I thought there might be some funniness there. However KM seemed to have no problem registering super-k when assigning it to the trigger. But who know. Maybe there's something different when assigning vs. using.

In any case, here's some observations I made:

  • Switching to shift-a made everything start to work as expected.
  • I found that there's a delay (maybe ~2s on my machine) between when you assign a trigger and when the KM Engine starts to use it. If you try to use the trigger before that time has elapsed, KM (or maybe the system) plays a warning sound.
  • I wonder if this was part of my initial issue because I was testing a lot of different triggers. I wonder if the KM Engine, or the frontend app, got into a state that was "confused" (for lack of a better term) about what, if any, trigger should be used for this macro group.
  • I write that because after setting shift-a as the trigger, waiting out that 2s period, confirm that it now works, then repeating with super-a (easier to type, less stretching) as the trigger, it continued to work!.
  • From then on, setting the macro group to any trigger continued to work as expect. The opposite of what I was experiencing before my initial reply above.
  • So maybe there is some bug somewhere. But one that has more to do with a race condition or setting a preference, than the fundamental functioning of the those options for a macro group.

So that's great.

I'm now able to use all of the options.


I tested my questions 1 and 2 above and see how that does work as I'd like.

So I guess the only questions remaining are:

  1. Is there any visual indication within Keyboard Maestro (or its menu) that a macro group's state is Active/Inactive? (#3 above)

  2. Any thoughts on the possible bug I encountered when setting the trigger and the macro group getting into a state where I wasn't able to trigger it?

Thanks!!