Last active
March 3, 2024 14:22
-
-
Save arkku/95e661db1377342a7ce570a8d5bc9850 to your computer and use it in GitHub Desktop.
Patch for QMK firmware to add two keycodes for Apple Fn: KC_APFN simulates the key directly, whereas APFN_LAYER(x) works as MO(x) but also registers as holding down Apple Fn _when no other key is pressed_. APFN_KEY(x) is key x together with Apple Fn.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk | |
index c976b8296d..335b432e78 100644 | |
--- a/builddefs/common_features.mk | |
+++ b/builddefs/common_features.mk | |
@@ -108,6 +108,12 @@ ifeq ($(strip $(MOUSEKEY_ENABLE)), yes) | |
SRC += $(QUANTUM_DIR)/mousekey.c | |
endif | |
+ifeq ($(strip $(APPLE_FN_ENABLE)), yes) | |
+ OPT_DEFS += -DAPPLE_FN_ENABLE -DENABLE_APPLE_FN_KEY=1 | |
+else | |
+ OPT_DEFS += -DENABLE_APPLE_FN_KEY=0 | |
+endif | |
+ | |
VALID_POINTING_DEVICE_DRIVER_TYPES := adns5050 adns9800 analog_joystick cirque_pinnacle_i2c cirque_pinnacle_spi pmw3360 pmw3389 pimoroni_trackball custom | |
ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes) | |
ifeq ($(filter $(POINTING_DEVICE_DRIVER),$(VALID_POINTING_DEVICE_DRIVER_TYPES)),) | |
diff --git a/keyboards/gmmk/pro/config.h b/keyboards/gmmk/pro/config.h | |
index aba69c8872..aa1a262d90 100644 | |
--- a/keyboards/gmmk/pro/config.h | |
+++ b/keyboards/gmmk/pro/config.h | |
@@ -20,8 +20,13 @@ | |
/* USB Device descriptor parameter */ | |
#define DEVICE_VER 0x0001 | |
+#if ENABLE_APPLE_FN_KEY | |
+#define VENDOR_ID 0x05AC | |
+#define PRODUCT_ID 0x021E | |
+#else | |
#define VENDOR_ID 0x320F | |
#define PRODUCT_ID 0x5044 | |
+#endif | |
#define MANUFACTURER Glorious | |
#define PRODUCT GMMK Pro | |
diff --git a/keyboards/gmmk/pro/rev1/iso/rules.mk b/keyboards/gmmk/pro/rev1/iso/rules.mk | |
index d3afa4d432..fccc7035b6 100644 | |
--- a/keyboards/gmmk/pro/rev1/iso/rules.mk | |
+++ b/keyboards/gmmk/pro/rev1/iso/rules.mk | |
@@ -8,14 +8,15 @@ BOOTLOADER = stm32-dfu | |
# change yes to no to disable | |
# | |
BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite | |
-MOUSEKEY_ENABLE = yes # Mouse keys | |
+MOUSEKEY_ENABLE = no # Mouse keys | |
EXTRAKEY_ENABLE = yes # Audio control and System control | |
CONSOLE_ENABLE = no # Console for debug | |
COMMAND_ENABLE = no # Commands for debug and configuration | |
-NKRO_ENABLE = yes # Enable N-Key Rollover | |
+NKRO_ENABLE = no # Enable N-Key Rollover | |
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality | |
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow | |
AUDIO_ENABLE = no # Audio output | |
ENCODER_ENABLE = yes | |
RGB_MATRIX_ENABLE = yes | |
RGB_MATRIX_DRIVER = AW20216 | |
+APPLE_FN_ENABLE = yes | |
diff --git a/quantum/action.c b/quantum/action.c | |
index 4e81a5466f..cc6e53c102 100644 | |
--- a/quantum/action.c | |
+++ b/quantum/action.c | |
@@ -306,6 +306,10 @@ void register_button(bool pressed, enum mouse_buttons button) { | |
} | |
#endif | |
+#if ENABLE_APPLE_FN_KEY | |
+static bool virtual_apple_fn_on = false; | |
+#endif | |
+ | |
/** \brief Take an action and processes it. | |
* | |
* FIXME: Needs documentation. | |
@@ -585,6 +589,53 @@ void process_action(keyrecord_t *record, action_t action) { | |
layer_off(action.layer_mods.layer); | |
} | |
break; | |
+#if ENABLE_APPLE_FN_KEY | |
+ case ACT_APPLE_FN: | |
+ if (event.pressed) { | |
+ if (action.key.code) { | |
+ if (!virtual_apple_fn_on) { | |
+ add_key(KC_APPLE_FN); | |
+ send_keyboard_report(); | |
+ virtual_apple_fn_on = true; | |
+ } | |
+ add_key(action.key.code); | |
+ send_keyboard_report(); | |
+ } else { | |
+ virtual_apple_fn_on = false; | |
+ register_code(KC_APPLE_FN); | |
+ } | |
+ } else { | |
+ if (action.key.code) { | |
+ del_key(action.key.code); | |
+ if (virtual_apple_fn_on) { | |
+ del_key(KC_APPLE_FN); | |
+ virtual_apple_fn_on = false; | |
+ } | |
+ send_keyboard_report(); | |
+ } else { | |
+ unregister_code(KC_APPLE_FN); | |
+ } | |
+ } | |
+ break; | |
+#ifdef NO_ACTION_TAPPING | |
+ case ACT_LAYER_TAP: | |
+ case ACT_LAYER_TAP_EXT: | |
+ if (action.layer_tap.code == OP_APPLE_FN) { | |
+ if (event.pressed) { | |
+ layer_on(action.layer_tap.val); | |
+ register_code(KC_APPLE_FN); | |
+ virtual_apple_fn_on = true; | |
+ } else { | |
+ if (virtual_apple_fn_on) { | |
+ virtual_apple_fn_on = false; | |
+ unregister_code(KC_APPLE_FN); | |
+ } | |
+ layer_off(action.layer_tap.val); | |
+ } | |
+ } | |
+ break; | |
+#endif | |
+#endif | |
# ifndef NO_ACTION_TAPPING | |
case ACT_LAYER_TAP: | |
case ACT_LAYER_TAP_EXT: | |
@@ -653,6 +704,21 @@ void process_action(keyrecord_t *record, action_t action) { | |
} | |
break; | |
# endif | |
+#if ENABLE_APPLE_FN_KEY | |
+ case OP_APPLE_FN: | |
+ if (event.pressed) { | |
+ layer_on(action.layer_tap.val); | |
+ register_code(KC_APPLE_FN); | |
+ virtual_apple_fn_on = true; | |
+ } else { | |
+ if (virtual_apple_fn_on) { | |
+ virtual_apple_fn_on = false; | |
+ unregister_code(KC_APPLE_FN); | |
+ } | |
+ layer_off(action.layer_tap.val); | |
+ } | |
+ break; | |
+#endif | |
default: | |
/* tap key */ | |
if (event.pressed) { | |
@@ -892,6 +958,13 @@ __attribute__((weak)) void register_code(uint8_t code) { | |
*/ | |
#endif | |
{ | |
+#if ENABLE_APPLE_FN_KEY | |
+ if (virtual_apple_fn_on) { | |
+ del_key(KC_APPLE_FN); | |
+ send_keyboard_report(); | |
+ virtual_apple_fn_on = false; | |
+ } | |
+#endif | |
// Force a new key press if the key is already pressed | |
// without this, keys with the same keycode, but different | |
// modifiers will be reported incorrectly, see issue #1708 | |
@@ -919,6 +992,12 @@ __attribute__((weak)) void register_code(uint8_t code) { | |
mousekey_send(); | |
} | |
#endif | |
+#if ENABLE_APPLE_FN_KEY | |
+ else if (code == KC_APPLE_FN) { | |
+ add_key(code); | |
+ send_keyboard_report(); | |
+ } | |
+#endif | |
} | |
/** \brief Utilities for actions. (FIXME: Needs better description) | |
@@ -979,6 +1058,12 @@ __attribute__((weak)) void unregister_code(uint8_t code) { | |
mousekey_send(); | |
} | |
#endif | |
+#if ENABLE_APPLE_FN_KEY | |
+ else if (code == KC_APPLE_FN) { | |
+ del_key(code); | |
+ send_keyboard_report(); | |
+ } | |
+#endif | |
} | |
/** \brief Tap a keycode with a delay. | |
diff --git a/quantum/action_code.h b/quantum/action_code.h | |
index 20b3e459d2..4409ac4618 100644 | |
--- a/quantum/action_code.h | |
+++ b/quantum/action_code.h | |
@@ -51,6 +51,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |
* ACT_SWAP_HANDS(0110): | |
* 0110|xxxx| keycode Swap hands (keycode on tap, or options) | |
* | |
+ * 0111|0001 xxxx xxxx Apple Fn + key | |
* 0111|xxxx xxxx xxxx (reserved) | |
* | |
* Layer Actions(10xx) | |
@@ -77,8 +78,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |
* 101E|LLLL|1111 0010 Off/On (0xF2) [NOT TAP] | |
* 101E|LLLL|1111 0011 Set/Clear (0xF3) [NOT TAP] | |
* 101E|LLLL|1111 0100 One Shot Layer (0xF4) [TAP] | |
- * 101E|LLLL|1111 xxxx Reserved (0xF5-FF) | |
- * ELLLL: layer 0-31(E: extra bit for layer 16-31) | |
+ * 101E|LLLL|1111 0101 Apple Fn Layer (0xF5) | |
+ * 101E|LLLL|1111 xxxx Reserved (0xF6-FF) | |
*/ | |
enum action_kind_id { | |
/* Key Actions */ | |
@@ -98,6 +99,9 @@ enum action_kind_id { | |
ACT_LAYER_MODS = 0b1001, | |
ACT_LAYER_TAP = 0b1010, /* Layer 0-15 */ | |
ACT_LAYER_TAP_EXT = 0b1011, /* Layer 16-31 */ | |
+#if ENABLE_APPLE_FN_KEY | |
+ ACT_APPLE_FN = 0b0111 | |
+#endif | |
}; | |
/** \brief Action Code Struct | |
@@ -222,6 +226,9 @@ enum layer_param_tap_op { | |
OP_OFF_ON, | |
OP_SET_CLEAR, | |
OP_ONESHOT, | |
+#if ENABLE_APPLE_FN_KEY | |
+ OP_APPLE_FN | |
+#endif | |
}; | |
#define ACTION_LAYER_BITOP(op, part, bits, on) ACTION(ACT_LAYER, (op) << 10 | (on) << 8 | (part) << 5 | ((bits)&0x1f)) | |
#define ACTION_LAYER_TAP(layer, key) ACTION(ACT_LAYER_TAP, (layer) << 8 | (key)) | |
@@ -254,6 +261,12 @@ enum layer_param_tap_op { | |
#define ACTION_DEFAULT_LAYER_BIT_XOR(part, bits) ACTION_LAYER_BITOP(OP_BIT_XOR, (part), (bits), 0) | |
#define ACTION_DEFAULT_LAYER_BIT_SET(part, bits) ACTION_LAYER_BITOP(OP_BIT_SET, (part), (bits), 0) | |
+#if ENABLE_APPLE_FN_KEY | |
+#define ACTION_APPLE_FN_KEY(key) ACTION(ACT_APPLE_FN, (key)) | |
+#define ACTION_APPLE_FN() ACTION_APPLE_FN_KEY(0) | |
+#define ACTION_APPLE_FN_LAYER(layer) ACTION_LAYER_TAP((layer), OP_APPLE_FN) | |
+#endif | |
+ | |
/* OneHand Support */ | |
enum swap_hands_param_tap_op { | |
OP_SH_TOGGLE = 0xF0, | |
diff --git a/quantum/keycode.h b/quantum/keycode.h | |
index 3c80a386d1..762b1bf73f 100644 | |
--- a/quantum/keycode.h | |
+++ b/quantum/keycode.h | |
@@ -502,9 +502,17 @@ enum internal_special_keycodes { | |
KC_MEDIA_FAST_FORWARD, | |
KC_MEDIA_REWIND, | |
KC_BRIGHTNESS_UP, | |
- KC_BRIGHTNESS_DOWN | |
+ KC_BRIGHTNESS_DOWN, | |
+ | |
+#if ENABLE_APPLE_FN_KEY | |
+ KC_APFN, | |
+#endif | |
}; | |
+#if ENABLE_APPLE_FN_KEY | |
+#define KC_APPLE_FN KC_APFN | |
+#endif | |
+ | |
enum mouse_keys { | |
/* Mouse Buttons */ | |
#ifdef VIA_ENABLE | |
diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c | |
index c1940f0fd3..efda95d52c 100644 | |
--- a/quantum/keymap_common.c | |
+++ b/quantum/keymap_common.c | |
@@ -58,6 +58,17 @@ action_t action_for_keycode(uint16_t keycode) { | |
case KC_LEFT_CTRL ... KC_RIGHT_GUI: | |
action.code = ACTION_KEY(keycode); | |
break; | |
+#if ENABLE_APPLE_FN_KEY | |
+ case KC_APPLE_FN: | |
+ action.code = ACTION_APPLE_FN(); | |
+ break; | |
+ case QK_APPLE_FN_MOD ... QK_APPLE_FN_MOD_MAX: | |
+ action.code = ACTION_APPLE_FN_KEY(keycode & 0xFF); | |
+ break; | |
+ case QK_APPLE_FN ... QK_APPLE_FN_MAX: | |
+ action.code = ACTION_APPLE_FN_LAYER(keycode & 0x1F); | |
+ break; | |
+#endif | |
#ifdef EXTRAKEY_ENABLE | |
case KC_SYSTEM_POWER ... KC_SYSTEM_WAKE: | |
action.code = ACTION_USAGE_SYSTEM(KEYCODE2SYSTEM(keycode)); | |
diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h | |
index 40355d799a..c99a814cf6 100644 | |
--- a/quantum/quantum_keycodes.h | |
+++ b/quantum/quantum_keycodes.h | |
@@ -37,6 +37,12 @@ enum quantum_keycodes { | |
QK_RALT = 0x1400, | |
QK_RGUI = 0x1800, | |
QK_MODS_MAX = 0x1FFF, | |
+#if ENABLE_APPLE_FN_KEY | |
+ QK_APPLE_FN_MOD = 0x3E00, | |
+ QK_APPLE_FN_MOD_MAX = 0x3EFF, | |
+ QK_APPLE_FN = 0x3FE0, | |
+ QK_APPLE_FN_MAX = 0x3FFF, | |
+#endif | |
QK_LAYER_TAP = 0x4000, | |
QK_LAYER_TAP_MAX = 0x4FFF, | |
QK_TO = 0x5000, | |
@@ -823,6 +829,11 @@ enum quantum_keycodes { | |
// L-ayer, T-ap - 256 keycode max, 16 layer max | |
#define LT(layer, kc) (QK_LAYER_TAP | (((layer)&0xF) << 8) | ((kc)&0xFF)) | |
+#if ENABLE_APPLE_FN_KEY | |
+#define APFN_LAYER(layer) (QK_APPLE_FN | ((layer) & 0x1F)) | |
+#define APFN_KEY(key) (QK_APPLE_FN_MOD | ((key) & 0xFF)) | |
+#endif | |
+ | |
// M-od, T-ap - 256 keycode max | |
#define MT(mod, kc) (QK_MOD_TAP | (((mod)&0x1F) << 8) | ((kc)&0xFF)) | |
diff --git a/tmk_core/protocol/report.c b/tmk_core/protocol/report.c | |
index 5755098c60..ab596b603e 100644 | |
--- a/tmk_core/protocol/report.c | |
+++ b/tmk_core/protocol/report.c | |
@@ -241,6 +241,12 @@ void del_key_bit(report_keyboard_t* keyboard_report, uint8_t code) { | |
* FIXME: Needs doc | |
*/ | |
void add_key_to_report(report_keyboard_t* keyboard_report, uint8_t key) { | |
+#if ENABLE_APPLE_FN_KEY | |
+ if (key == KC_APPLE_FN) { | |
+ keyboard_report->reserved = 1; | |
+ return; | |
+ } | |
+#endif | |
#ifdef NKRO_ENABLE | |
if (keyboard_protocol && keymap_config.nkro) { | |
add_key_bit(keyboard_report, key); | |
@@ -255,6 +261,12 @@ void add_key_to_report(report_keyboard_t* keyboard_report, uint8_t key) { | |
* FIXME: Needs doc | |
*/ | |
void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key) { | |
+#if ENABLE_APPLE_FN_KEY | |
+ if (key == KC_APFN) { | |
+ keyboard_report->reserved = 0; | |
+ return; | |
+ } | |
+#endif | |
#ifdef NKRO_ENABLE | |
if (keyboard_protocol && keymap_config.nkro) { | |
del_key_bit(keyboard_report, key); | |
diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c | |
index 063bd2c3f1..a7fc5672b6 100644 | |
--- a/tmk_core/protocol/usb_descriptor.c | |
+++ b/tmk_core/protocol/usb_descriptor.c | |
@@ -71,10 +71,22 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] = { | |
HID_RI_REPORT_COUNT(8, 0x08), | |
HID_RI_REPORT_SIZE(8, 0x01), | |
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), | |
+ | |
+#if ENABLE_APPLE_FN_KEY | |
+ HID_RI_USAGE_PAGE(8, 0xFF), // AppleVendor Top Case | |
+ HID_RI_USAGE(8, 0x03), // KeyboardFn | |
+ HID_RI_LOGICAL_MINIMUM(8, 0x00), | |
+ HID_RI_LOGICAL_MAXIMUM(8, 0x01), | |
+ HID_RI_REPORT_COUNT(8, 0x01), | |
+ HID_RI_REPORT_SIZE(8, 0x08), | |
+ HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), | |
+#else | |
// Reserved (1 byte) | |
HID_RI_REPORT_COUNT(8, 0x01), | |
HID_RI_REPORT_SIZE(8, 0x08), | |
HID_RI_INPUT(8, HID_IOF_CONSTANT), | |
+#endif | |
+ | |
// Keycodes (6 bytes) | |
HID_RI_USAGE_PAGE(8, 0x07), // Keyboard/Keypad | |
HID_RI_USAGE_MINIMUM(8, 0x00), |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I just tried to merge qmk master into your apple_fn branch, there's only 3 files that conflict but they conflict in ways that I don't understand (something like 5k files changed,phew!). Like I can't find where:
This block of
keycode.h
is now gone? as well as a large chunk ofquantum_keycodes.h
has disappeared.