Best library for sending multiple keys / switching from NicoHood?

Hi all,

A while back I built myself a media keyboard, powered with a Pro Micro. In it's first mode it just sends media commands as a HID device (PLAY_PAUSE, MEDIA_STOP, VOL_UP etc), but when you press the rotary encoder button it switches modes, and sends keyboard letters. The choice of command is defined in two arrays within the code. All of this is based on the NicoHood library, which supports both a Consumer keyboard mode (for the media keys) and a standard Keyboard mode for the shortcuts. Here's the code in full.

//setup USB
#include <HID-Project.h>

//keypad & encoder definitions
int colPins[] = {4, 5, 6, 7};  //select pins, driven LOW to select col => btn active LOW.
int rowPins[] = {10, 14, 15};      //signal pins, read LOW means btn pressed.
int encPins[] = {3, 2};          //encoder signal pins. Interrupts on Pro Micro
int const rows = sizeof(rowPins)/sizeof(int);
int const cols = sizeof(colPins)/sizeof(int);

//array for prev btn states to detect distinct presses and releases
int key_prev[rows][cols] = {
  { 1, 1, 1, 1},
  { 1, 1, 1, 1},
  { 1, 1, 1, 1}
};
//array for prev encoder A pin state to detect rotation direction
int enc_prev[cols] = {
  //1, 1, 1, 1
  1
};

//misc UI definitions
int const modes = 2;    //number of modes/different keysets
int mode = 1;           //curent mode
//btn to toggle through modes
int modeBtn = 16; //digital pin. Used to be 4.
int modeBtnPrev = 0;
//LEDs to indicate current mode
//int ledPins[] = {18, 19, 20};
//int leds = sizeof(ledPins)/sizeof(int);

//key sets for different modes
//usb codes for buttons (4x3) in different modes (3). each button can cause 5 keystrokes + optional modifier. see ProTrinketHidCombo.h for more information.
//see additional file for codes. for multiple modifiers combine them with bitwise or.
int usb_codes[modes][rows][cols][6] = {
  //multimedia
  {
    {{MEDIA_PREVIOUS},{MEDIA_STOP},{MEDIA_PLAY_PAUSE},{MEDIA_NEXT}}, //previous, stop, play/pause, next
    {{MEDIA_REWIND},{MEDIA_FAST_FORWARD},{MEDIA_VOL_DOWN},{MEDIA_VOL_UP}},  //rewind, fast forward, vol down, vol up
    {{CONSUMER_EXPLORER},{MEDIA_STOP},{MEDIA_PLAY_PAUSE},{MEDIA_VOL_MUTE}}  //open explorer, stop, play/pause, mute
  },
  //lightworks
  {
    {{'1'},{'3'},{'a'},{'s'}}, 
    //track 1, track 3, prev cut, next cut
    {{'h'},{';'},{'i'},{'o'}},
     //start, end, mark in, mark out
    {{'z'},{'x'},{'v'},{' '}}
    //clear, delete, cut, play/pause
    //others: p clear all marks, = zoom in, - zoom out
  }
};
//encoder actions. 1 enc per col, cw & ccw direction (2) plus optional modifier (2)
//1st is ccw, 2nd is cw
int usb_codes_enc[modes][cols][2][6] = {
  //multimedia encoders
  {
   // {{MEDIA_VOL_DOWN},{MEDIA_VOL_UP}},          //volume down, up
   // {{MEDIA_VOL_DOWN},{MEDIA_VOL_UP}},      //volume down, up
   // {{MEDIA_VOL_DOWN},{MEDIA_VOL_UP}},      //volume down, up
    {{MEDIA_VOL_DOWN},{MEDIA_VOL_UP}}   //volume down, up
  },
  //lightworks
  {
   // {{','},{'.'}},    //frame left, frame right
   // {{','},{'.'}},    //frame left, frame right
   // {{','},{'.'}},    //frame left, frame right
    {{','},{'.'}}     //frame left, frame right
  }
};

void setup(){
  //set data direction for keypad
  //cols: select, drive low to select
  for(int i=0; i<cols; i++){
    pinMode(colPins[i], OUTPUT);
    digitalWrite(colPins[i], HIGH);
  }
  //rows: sense/read, active low
  for(int i=0; i<rows; i++){
    pinMode(rowPins[i], INPUT_PULLUP);
  }
  //set up encoder inputs
  pinMode(encPins[0], INPUT_PULLUP);
  pinMode(encPins[1], INPUT_PULLUP);
  //mode btn
  pinMode(modeBtn, INPUT_PULLUP);
  //mode LEDs initialization & startup animation
  /*for(int i=0; i<leds; i++){
    pinMode(ledPins[i], OUTPUT);
    digitalWrite(ledPins[i], HIGH);
    delay(200);
    digitalWrite(ledPins[i], LOW);
  }*/

  //USB
  TIMSK0&=!(1<<TOIE0);
  Keyboard.begin();
  Consumer.begin();
  BootKeyboard.begin();
  /*while(!TrinketHidCombo.isConnected()){
    TrinketHidCombo.poll();
  }*/
  //turn on LED once USB connection is up
  //analogWrite(ledPins[mode], 64);
}

void loop(){

  //poll inputs

  //poll mode button
  if(digitalRead(modeBtn) == 0 && modeBtnPrev == 1){
    modeBtnPrev = 0;
    mode += 1;
    if(mode >= modes){
      mode = 0;
    }
    //change LEDs
    //turn off all LEDs
    /*for(int i=0; i<leds; i++){
      digitalWrite(ledPins[i], LOW);
    }*/
    //turn on current LED if USB is still connected. prevents LEDs being on if PC isn't
    /*if(TrinketHidCombo.isConnected()){
      analogWrite(ledPins[mode], 64);
    }*/
  }
  else if (digitalRead(modeBtn) == 1 && modeBtnPrev == 0){
    modeBtnPrev = 1;
  }

  //cycle through cols
  for(int i=0; i<cols; i++){
    //enable col (active low)
    digitalWrite(colPins[i], LOW);

    //poll rows
    for(int j=0; j<rows; j++){
      //read state of current btn
      int but = digitalRead(rowPins[j]);    //Button Under Test

      //btn was just pressed (0), which means prev state was 1 (unpressed)
      if(but == 0 && key_prev[j][i] == 1){
        //set new prev state
        key_prev[j][i] = 0;

        //execute keystroke
        executeKeystroke(usb_codes[mode][j][i]);
      }
      //key release
      else if(but == 1 && key_prev[j][i] == 0){
        //set new prev state
        key_prev[j][i] = 1;
      }
    }
    // /poll rows

    //poll encoder
    int A = digitalRead(encPins[0]);
    int B = digitalRead(encPins[1]);
    //detect rotation
    if(A == 0 && enc_prev[i] == 1){
      //change prev state
      enc_prev[i] = 0;

      //determine rotation direction (cw/ccw)
      if(B == 1){
        //ccw rotation

        //execute keystroke
        executeKeystroke(usb_codes_enc[mode][i][0]);
      }
      else if(B == 0){
        //cw rotation

        //execute keystroke
        executeKeystroke(usb_codes_enc[mode][i][1]);
      }
    }
    else if(A == 1 && B == 1){
      //no input on encoder pins
      enc_prev[i] = 1;
    }
    // /poll encoder

    //disable col
    digitalWrite(colPins[i], HIGH);

    delayMicroseconds(250);    //software debounce
  }

}

//differentiate between keycode and multimedia keycode
void executeKeystroke(int* keycombo){
  if(mode == 0){    
    Consumer.write(keycombo[0]);
  }
  else if(mode == 1){
    BootKeyboard.write(keycombo[0]);
  }
}

void delayMs(unsigned int ms){
  for (int i = 0; i < ms; i++) {
    delayMicroseconds(1000);
  }
}

As for my actual question: I want to convert the keyboard mapping to send multiple keystrokes at once: specifically CTRL+character, ALT+character, even CTRL+TAB if necessary. However, I can't work out how to make that work with my existing code. I've tried concatenating the values in the array with %%, or separating them with a pipe, and changing the keyboard type (from Consumer to Keyboard to BootKeyboard) but nothing seems to send 'standard' keyboard buttons like KEY_ENTER or KEY_F10, let alone compound commands.

Has anyone here got experience with the NicoHood library, or can recommend another library that might suit my purposes?