Unable to make my macro work with new firmware

Hello,

I just upgrade my atreus from kaleidoscope 1.99.3 to 1.99.5 and I struggled to update some macro.

I have macro that do different thing if modifier is pressed or not. A simple example :

  case KEY_COMMA:
    if (keyToggledOn(event.state)) {
      if (Kaleidoscope.hid().keyboard().wasModifierKeyActive(Key_LeftShift)) {
        return MACRO(I(15), U(LeftShift), T(Comma), D(LeftShift));
      } else {
        return MACRO(I(15), T(M));
      }
    }

I was using MACRODOWN method but just migrate to use new way.
My problem is when LeftShift is held I need a macro with no modifier active. I formerly solve this by begining Macro releasing the modifier key. But with the last version it does not work anymore.

I try unsuccessfully to use Kaleidoscope.hid().keyboard().clearModifier() or Runtime.handleKeyEvent() to do so.

Does anyone have an idea to solve this ?

Thanks

I have two solutions for you for the above macro:

  1. A special purpose “ShiftBlocker” plugin, submitted as a PR with example code.
  2. The existing CharShift plugin.

The problem you’re having is that MACRO() can’t release a key that wasn’t pressed by the Macros plugin. Since Kaleidoscope’s event-driven redesign, the Macros plugin works by pressing and releasing keys on a small supplemental virtual keyboard, and cannot effect keys held on the main keyboard by calling Macros.release(), which is what U(LeftShift) does, because that will only release that key on the supplemental keyboard.

I would be happy to look at the rest of your Macros code and see if there are any that need more complex adjustments, and I can also help you set up CharShift (or the custom ShiftBlocker plugin) if you want.

Thanks.

I just have a quick look at your solutions and believe the “ShiftBlocker” plugin is what I need.
The CharShift plugin would not do the job for some case where I use different macro depending on OS and alt codes for windows.

If you want to take a look to my code : https://github.com/rloic82/Kaleidoscope/blob/feature/fr_azerty/examples/Devices/Keyboardio/AtreusBepo/AtreusBepo.ino

I think I will be able to implement the ShiftBlocker. I will come back as soon as I did it.

I also recommend using the following instead of wasModifierKeyActive():

bool isShiftKeyHeld() {
  for (Key key : kaleidoscope::live_keys.all()) {
    if (key.isKeyboardShift())
      return true;
  }
  return false;
}

Unlike wasModifierKeyActive() (and isModifierKeyActive(), which is no longer problematic), you won’t get a false positive for a key with a modifier flag (e.g. LSHIFT(Key_1)).

[Edit: fixed typo in the code.]

1 Like

@merlin I implement your ShiftBlocker plugin which was exactly what I need. All my macros work as I want again.

Thanks a lot for helping me.

Just for those who will use your isShiftKeyHeld() function, I notice a little mistake on line

for (Key key : kaleidoscope:live_keys.all()) {

but it should be

for (Key key : kaleidoscope::live_keys.all()) {
1 Like

Thanks for catching my typo! Sorry about that.

@merlin thank you for your suggestions. It also helped me a lot. I managed to convert most of my macros to CharShift. I still have a few problems with tilde.

I’m trying to get the default layout so that the rightmost key of the left side is backtick when pressed normal and tilde when pressed with shift. On the finnish keyboard the tilde is achieved pressing MACRO(D(RightAlt), T(RightBracket, U(RightAlt), T(Space)).

I cannot figure out how to use the ShiftBlocker to achieve these combinations.

Any help is appreciated.

The repository is here finnish-atreus/MyAtreus.ino at master · nikkez/finnish-atreus · GitHub.

Your whole macroAction() function is the deprecated version, so it needs to be replaced with the newer KeyEvent version. I haven’t tested this code, so there may be some errors in it, but if I got it all right, it should serve as a replacement for your old macroAction() function:

const macro_t *macroAction(uint8_t macro_id, KeyEvent &event) {
  // All these macros only play when a key toggles on, so it's more efficient to
  // just test for that once.
  if (keyToggledOn(event.state)) {

    switch (macro_id) {

    case MACRO_VERSION_INFO:
      Macros.type(PSTR("Keyboardio Atreus - Kaleidoscope "));
      Macros.type(PSTR(BUILD_INFORMATION));
      break;

    case M_BACKTICK_AND_TILDE:
      // Check for any `shift` keys that are currently being held.
      bool shift_active = false;
      for (Key key : live_keys.all()) {
        if (key.isKeyboardShift())
          shift_active = true;
      }
      if (shift_active) {
        // If one or more `shift` keys are held, we can't use `MACRO()` because
        // we need to disable ShiftBlocker when we're done.
        ShiftBlocker.enable();
        Macros.tap(RALT(Key_RightBracket));
        Macros.tap(Key_Space);
        ShiftBlocker.disable();
      } else {
        // It's more efficient to use a single `Tr()` with a key value that
        // contains a modifier flag than to use separate commands for pressing
        // and releasing the modifier.
        return MACRO(Tr(LSHIFT(Key_Equals)), T(Space));
      }
      break;

    case M_CARET:
      return MACRO(Tr(LSHIFT(Key_RightBracket)), T(Space));

    case M_PARENTHESIS:
      return MACRO(D(LeftShift), T(8), T(9), U(LeftShift), T(LeftArrow));

    case M_ANGLES:
      return MACRO(T(NonUsBackslashAndPipe), Tr(LSHIFT(Key_NonUsBackslashAndPipe)), T(LeftArrow));

    case M_DOUBLE_EQUALS:
      return MACRO(D(LeftShift), T(0), T(0), U(LeftShift));

    case M_ALT_SHIFT_COMMA:
      // Modifier flags can be combined.
      return MACRO(Tr(LSHIFT(LALT(Key_Comma))));

    case M_ALT_SHIFT_X_T:
      // Modifier flag preprocessor macros are not sensitive to the order in
      // which they are applied to the key value.
      return MACRO(Tr(LALT(LSHIFT(Key_X))), T(T));

    default:
      break;
    }
  }
  return MACRO_NONE;
}

If you have any further questions, or if something doesn’t work properly, don’t hesitate to ask again!

Thank you for your help! Now it works.

There is still one problem but I’m not sure what causes it. For some reason sometimes the macro is not played or the resulting keypresses are not visible.

I added some printlines to serial to verify this. The execution is inside the macroAction function and I get the output to serial that certain key is pressed but nothing is output from the keyboard.

The code is here finnish-atreus/MyAtreus.ino at master · nikkez/finnish-atreus · GitHub.

It is just in the case where ShiftBlocker is getting activated, or is it happening for other macros, too?

It is happening for other macros too.

Thanks. I’ll try to reproduce this when I get a chance, but I don’t currently have a hypothesis that fits.

Whereas I use a lot of macro, I have no issues with them.
I see only 2 differences between our codes.

  • Your enum lists ended with a comma which, in my mind, means a continuation but there is not.
  • To avoid multiple repetition of the test if (keyToggledOn(event.state)) you put it before the switch code.

Perhaps one of this point is the cause of your problem but not sure at all.

Thank you @rloic and @merlin for your help! I was testing the keyboard only in Ubuntu in Gnome Terminal. For some reason Gnome Terminal seems to be the problem. The macros work fine for instance in vscode, gedit and xterm but Gnome Terminal “swallows” the macros maybe once in 10 presses.

2 Likes

Trailing commas are pretty common in lists with one item per line, and are especially nice for version control. If another item is added to the end of a list without a trailing comma, the diff will show three lines (two for adding a comma to one line, and one for the new line) instead of just one.

1 Like

Thanks for the information.
I didn’t know this usage and as the atreus customization is my only C++ code use case I have very limited skills.