Need to block Control (like ShiftBlocker)

So, I already use the ShiftBlocker plugin with great success. Now I need the equivalent to Control.

So I do the obvious:

class CtrlBlocker : public Plugin {
    EventHandlerResult onAddToReport(Key key) {
      if (active_ && key == Key_LeftControl) {
        return EventHandlerResult::ABORT;  
      return EventHandlerResult::OK;

    void enable() {
      active_ = true;
    void disable() {
      active_ = false;

    bool active_{false};

In ShiftBlocker the check is made with key.isKeyboardShift() but I can’t find anything similar to Ctrl. And I also found this: Can i modify ctrl behavior when it's pressed with j/l using Chrysalis? - #4 by merlin where the check is (key == Key_LeftControl || key == Key_RightControl).

I’m using CtrlBlocker in a macro function:

static void forceOnlyAltModifier(uint8_t key_state, Key key) {
  if (keyToggledOn(key_state)) {

Using some Serial.print statements (Serial.println(key == Key_LeftControl);) I found that the control key is recognized correctly in the onAddToReport. But only when it’s not activated through ML(LeftControl, SOME_LAYER_WHERE_I_NEED_CONTROL_HELD_BUT_NOT_FOR_ONE_PARTICULAR_KEY)

Why can’t I suppress Ctrl with my CtrlBlocker when used with ML()?

The reason is that your plugin is checking for the wrong Key value. In this case, you want the test to be:

if (key == ML(LeftControl, TARGET_LAYER)) {
  // ...

Unlike Qukeys (e.g. MT(LeftControl, X), which becomes either Key_LeftControl or Key_X before being passed to onAddToReport()), the ModLayer key doesn’t change its value when it’s used, so if you want to have your plugin suppress the modifier from it, you’ll need to explicitly match that value.

The function Key::isKeyboardShift() is special because, for some keys, shift changes the logical symbol of a key, not just its letter form (upper vs lower case), so there are more use cases for it.

Thanks Michael. I would never have figured that out. Is it something you know having worked a lot with Kaleidoscope, or is there some kind of hint I have missed?

You say that the test should be key == ML(LeftControl, TARGET_LAYER). Does that mean that if I have defined ML(LeftControl, LAYER1) and ML(LeftControl, LAYER2) I have to test specifically for both of those in addition to Key_LeftControl if I also have that defined somewhere?

I’m the one who wrote the ShiftBlocker example, as well as a large portion of Kaleidoscope’s current plugin API code, so I’m intimately familiar with the tricks for getting plugins to behave the way I want them to.

Yes, those are different Key values, so you’d need to test for both of them. Alternatively, you could construct a clever test that checks for any modifier key (including ModLayer keys) that includes the flag for a control key. If you think there’s enough utility in similar functions being added to the Kaleidoscope plugin API, please submit a GitHub issue (or, if you don’t have a GitHub account, or if you aren’t comfortable doing so, I could do it on your behalf).