Struggling with QMK modifier keys

2.3k Views Asked by At

I'm getting this error when I try to use modifier keys on my rotary encoder like so:

bool encoder_update_user(uint8_t index, bool clockwise) {
    if (index == 0) { /* First encoder */
        if (clockwise) {
            tap_code(QK_LCTL | KC_F24);
        } else {
            tap_code(QK_LCTL | KC_F23);
        }
    }
    return false;
}

This is the error:

Compiling: keyboards/planck/keymaps/dawz/keymap.c                                                  keyboards/planck/keymaps/dawz/keymap.c: In function 'encoder_update_user':
keyboards/planck/keymaps/dawz/keymap.c:68:22: error: unsigned conversion from 'int' to 'uint8_t' {aka 'unsigned char'} changes value from '371' to '115' [-Werror=overflow]
   68 |             tap_code(QK_LCTL | KC_F24);
      |                      ^~~~~~~~~~~~~~~~
keyboards/planck/keymaps/dawz/keymap.c:70:22: error: unsigned conversion from 'int' to 'uint8_t' {aka 'unsigned char'} changes value from '370' to '114' [-Werror=overflow]
   70 |             tap_code(QK_LCTL | KC_F23);
      |                      ^~~~~~~~~~~~~~~~
cc1.exe: all warnings being treated as errors
 [ERRORS]
 |
 |
 |
make[1]: *** [tmk_core/rules.mk:443: .build/obj_planck_rev6_drop_dawz/keyboards/planck/keymaps/dawz/keymap.o] Error 1
Make finished with errors
make: *** [Makefile:539: planck/rev6_drop:dawz] Error 1

The encoder works when I put in a regular keycode like KC_VOLUP or KC_VOLDOWN, but I’m trying to use Ctrl + F23, F24, so I can use the knob as a Voicemeeter macro buttons controller.

3

There are 3 best solutions below

2
SUB On

If you want to use modifier keys here with encoders, you should try using tap_code16() instead of tap_code().

Try this instead:

bool encoder_update_user(uint8_t index, bool clockwise) {
    if (index == 0) { /* First encoder */
        if (clockwise) {
            tap_code16(QK_LCTL | KC_F24);
        } else {
            tap_code16(QK_LCTL | KC_F23);
        }
    }
    return false;
}

QMK documentation for this

1
Leo On

You could break down how a key combination is pressed:

  1. Hold down the modifier key
  2. Press some key (usually a letter or number)
  3. Release the modifier key

Then you could represent the whole process:

bool encoder_update_user(uint8_t index, bool clockwise) {
    if (index == 0) { /* First encoder */
        if (clockwise) {
            register_code(QK_LCTL);   // Press and keep holding down
            tap_code(KC_F24);         // Press and release
            unregister_code(QK_LCTL); // Release
        } else {
            register_code(QK_LCTL);
            tap_code(KC_F23);
            unregister_code(QK_LCTL);
        }
    }
    return false;
}

This approach seems to be dumb, but you can achieve much more complicated cases, such as Ctrl + Alt + Shift + A or something that could hardly been done with keycodes.

I did this for one of my self-made keyboard, and it worked fine.

0
Pascal Getreuer On

You can represent "Ctrl + (basic key)" combinations using the macro LCTL(kc) (and similar macros for other mods), but the technicality is that this creates a 16-bit keycode. So rather than tap_code(), which is limited to 8-bit basic keycodes, use tap_code16() to tap it:

// Copyright 2022 Google LLC.
// SPDX-License-Identifier: Apache-2.0
bool encoder_update_user(uint8_t index, bool clockwise) {
  if (index == 0) {
    tap_code16(clockwise ? LCTL(KC_F24) : LCTL(KC_F23));
  } 
  return false;
}

See also the QMK encoders documentation.