Rotary Knob map to combination keypress

I’m brand new to this, and not a developer and looking for help configuring a rotary knob on a GMMK Pro to change Windows Desktops. The default key combination is Control-Windows-Left/Right Arrow. I’d like the rotary knob to take me to the right for clockwise turns and left desktop for counterclockwise.

I used the QMK CLI to get the rotary knob working as volume up / down before modifying and attempted to use the same syntax I used for a standard keymapping on rotary knob press (Control-Alt-Delete = RCTL(RALT(KC_DEL))). It doesn’t seem to like the nested KC options after the tap_code.

#ifdef ENCODER_ENABLE
bool encoder_update_user(uint8_t index, bool clockwise) {
if (clockwise) {
tap_code(KC_LCTL(KC_LGUI(KC_RGHT)));
} else {
tap_code(KC_LCTL(KC_LGUI(KC_LEFT)));
}
return true;
}
#endif // ENCODER_ENABLE

Here are the compiler errors -
Compiling: keyboards/gmmk/pro/ansi/keymaps/nyko/keymap.c In file included from quantum/action.h:23,
from quantum/keymap.h:22,
from quantum/quantum.h:21,
from keyboards/gmmk/pro/pro.h:19,
from keyboards/gmmk/pro/ansi/keymaps/nyko/keymap.c:1:
keyboards/gmmk/pro/ansi/keymaps/nyko/keymap.c: In function ‘encoder_update_user’:
quantum/keycode.h:175:17: error: called object is not a function or function pointer
175 | #define KC_LGUI KC_LEFT_GUI
| ^~~~~~~~~~~
keyboards/gmmk/pro/ansi/keymaps/nyko/keymap.c:18:24: note: in expansion of macro ‘KC_LGUI’
18 | tap_code(KC_LCTL(KC_LGUI(KC_RGHT)));
| ^~~~~~~
quantum/keycode.h:171:17: error: called object is not a function or function pointer
171 | #define KC_LCTL KC_LEFT_CTRL
| ^~~~~~~~~~~~
keyboards/gmmk/pro/ansi/keymaps/nyko/keymap.c:18:16: note: in expansion of macro ‘KC_LCTL’
18 | tap_code(KC_LCTL(KC_LGUI(KC_RGHT)));
| ^~~~~~~
quantum/keycode.h:175:17: error: called object is not a function or function pointer
175 | #define KC_LGUI KC_LEFT_GUI
| ^~~~~~~~~~~
keyboards/gmmk/pro/ansi/keymaps/nyko/keymap.c:20:24: note: in expansion of macro ‘KC_LGUI’
20 | tap_code(KC_LCTL(KC_LGUI(KC_LEFT)));
| ^~~~~~~
quantum/keycode.h:171:17: error: called object is not a function or function pointer
171 | #define KC_LCTL KC_LEFT_CTRL
| ^~~~~~~~~~~~
keyboards/gmmk/pro/ansi/keymaps/nyko/keymap.c:20:16: note: in expansion of macro ‘KC_LCTL’
20 | tap_code(KC_LCTL(KC_LGUI(KC_LEFT)));
| ^~~~~~~
[ERRORS]
|
|
|
make[1]: *** [tmk_core/rules.mk:457: .build/obj_gmmk_pro_ansi_nyko/keyboards/gmmk/pro/ansi/keymaps/nyko/keymap.o] Error 1
Make finished with errors
make: *** [Makefile:478: gmmk/pro/ansi:nyko] Error 1

So, I think you need to reformat your key code input. I have a couple possible solutions below.
The problem:

#ifdef ENCODER_ENABLE
bool encoder_update_user(uint8_t index, bool clockwise) {
    if (clockwise) {
        tap_code(KC_LCTL(KC_LGUI(KC_RGHT)));
        } else {
        tap_code(KC_LCTL(KC_LGUI(KC_LEFT)));
    }
    return true;
}
#endif // ENCODER_ENABLE

I believe the modifier shortcuts you’re using (eg: KC_LCTL(KC_LGUI(KC_RGHT))) aren’t meant to be nested.

Option 1 - Reformatting Your Macro

Referencing this Alt-Tab macro example might get you where you need to go.

I think the CW turn would look something like this:

#ifdef ENCODER_ENABLE
bool encoder_update_user(uint8_t index, bool clockwise) {
    if (clockwise) {
        register_code(KC_LCTL);
        register_code(KC_LALT);
        tap_code(KC_RGHT);
        unregister_code(KC_LCTL);
        unregister_code(KC_LALT);
    } else {
        <CCW Behavior here>
Option 2 - Use a different modifier keycode

Check out the Modifiers section of the key codes page. You might be able to use LCA(kc) to accomplish the modifiers you need and send it in a macro, simplifying things tremendously.

Give it a shot and let me know if you have any questions! :slight_smile:

Formatting note: You can use ``` at the beginning and end of a snippet of code to create a code block. EX:

```
Code block
```

Or you can wrap a section in single ` (ex: `code here`) to create an inline code block.

2 Likes

Thank you! It’s unclear to my why certain aliases work and others don’t, but your first solution worked once I updated ALT to KC_LWIN as here -

#ifdef ENCODER_ENABLE
bool encoder_update_user(uint8_t index, bool clockwise) {
if (clockwise) {
register_code(KC_LCTL);
register_code(KC_LWIN);
tap_code(KC_RGHT);
unregister_code(KC_LCTL);
unregister_code(KC_LWIN);
} else {
register_code(KC_LCTL);
register_code(KC_LWIN);
tap_code(KC_LEFT);
unregister_code(KC_LCTL);
unregister_code(KC_LWIN);
}
return true;
#endif // ENCODER_ENABLE

Doh! I did cntl-alt, not cntl-gui. I’m glad it worked!

I’d be curious if you could simplify the code block using the LCAG(kc) code.