|
diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk |
|
index 18f8b0bbfc..4ef3e230e4 100644 |
|
--- a/builddefs/common_features.mk |
|
+++ b/builddefs/common_features.mk |
|
@@ -878,6 +878,10 @@ ifeq ($(strip $(JOYSTICK_ENABLE)), yes) |
|
endif |
|
endif |
|
|
|
+ifeq ($(strip $(APPLE_FN_ENABLE)), yes) |
|
+ OPT_DEFS += -DAPPLE_FN_ENABLE |
|
+endif |
|
+ |
|
USBPD_ENABLE ?= no |
|
VALID_USBPD_DRIVER_TYPES = custom vendor |
|
USBPD_DRIVER ?= vendor |
|
diff --git a/data/constants/keycodes/keycodes_0.0.2_applefn.hjson b/data/constants/keycodes/keycodes_0.0.2_applefn.hjson |
|
new file mode 100644 |
|
index 0000000000..1378413a9e |
|
--- /dev/null |
|
+++ b/data/constants/keycodes/keycodes_0.0.2_applefn.hjson |
|
@@ -0,0 +1,11 @@ |
|
+{ |
|
+ "keycodes": { |
|
+ "0x5300": { |
|
+ "group": "apple_fn", |
|
+ "key": "QK_APPLE_FN", |
|
+ "aliases": [ |
|
+ "AP_FN" |
|
+ ] |
|
+ } |
|
+ } |
|
+} |
|
diff --git a/quantum/action.c b/quantum/action.c |
|
index 6368f7398c..d9bd34f681 100644 |
|
--- a/quantum/action.c |
|
+++ b/quantum/action.c |
|
@@ -555,6 +555,18 @@ void process_action(keyrecord_t *record, action_t action) { |
|
} |
|
break; |
|
#endif // EXTRAKEY_ENABLE |
|
+#ifdef APPLE_FN_ENABLE |
|
+ /* Apple Fn */ |
|
+ case ACT_APPLE_FN: |
|
+ if (event.pressed) { |
|
+ add_apple_fn(keyboard_report); |
|
+ send_keyboard_report(); |
|
+ } else { |
|
+ del_apple_fn(keyboard_report); |
|
+ send_keyboard_report(); |
|
+ } |
|
+ break; |
|
+#endif |
|
/* Mouse key */ |
|
case ACT_MOUSEKEY: |
|
register_mouse(action.key.code, event.pressed); |
|
@@ -1196,6 +1208,9 @@ void debug_action(action_t action) { |
|
case ACT_USAGE: |
|
ac_dprintf("ACT_USAGE"); |
|
break; |
|
+ case ACT_APPLE_FN: |
|
+ dprint("ACT_APPLE_FN"); |
|
+ break; |
|
case ACT_MOUSEKEY: |
|
ac_dprintf("ACT_MOUSEKEY"); |
|
break; |
|
diff --git a/quantum/action_code.h b/quantum/action_code.h |
|
index d9a575b518..f347010c8d 100644 |
|
--- a/quantum/action_code.h |
|
+++ b/quantum/action_code.h |
|
@@ -53,7 +53,8 @@ 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|xxxx xxxx xxxx (reserved) |
|
+ * ACT_APPLE_FN(0111): |
|
+ * 0111|0000|0000|0000 Apple Fn |
|
* |
|
* Layer Actions(10xx) |
|
* ------------------- |
|
@@ -95,6 +96,8 @@ enum action_kind_id { |
|
ACT_MOUSEKEY = 0b0101, |
|
/* One-hand Support */ |
|
ACT_SWAP_HANDS = 0b0110, |
|
+ /* Apple Fn */ |
|
+ ACT_APPLE_FN = 0b0111, |
|
/* Layer Actions */ |
|
ACT_LAYER = 0b1000, |
|
ACT_LAYER_MODS = 0b1001, |
|
@@ -182,6 +185,7 @@ enum usage_pages { |
|
|
|
#define ACTION_USAGE_SYSTEM(id) ACTION(ACT_USAGE, PAGE_SYSTEM << 10 | (id)) |
|
#define ACTION_USAGE_CONSUMER(id) ACTION(ACT_USAGE, PAGE_CONSUMER << 10 | (id)) |
|
+#define ACTION_APPLE_FN() ACTION(ACT_APPLE_FN, 0) |
|
#define ACTION_MOUSEKEY(key) ACTION(ACT_MOUSEKEY, key) |
|
|
|
/** \brief Layer Actions |
|
diff --git a/quantum/keycodes.h b/quantum/keycodes.h |
|
index bbf10da36d..b8e894a399 100644 |
|
--- a/quantum/keycodes.h |
|
+++ b/quantum/keycodes.h |
|
@@ -310,6 +310,7 @@ enum qk_keycode_defines { |
|
KC_RIGHT_SHIFT = 0x00E5, |
|
KC_RIGHT_ALT = 0x00E6, |
|
KC_RIGHT_GUI = 0x00E7, |
|
+ QK_APPLE_FN = 0x5300, |
|
QK_SWAP_HANDS_TOGGLE = 0x56F0, |
|
QK_SWAP_HANDS_TAP_TOGGLE = 0x56F1, |
|
QK_SWAP_HANDS_MOMENTARY_ON = 0x56F2, |
|
@@ -938,6 +939,7 @@ enum qk_keycode_defines { |
|
KC_RGUI = KC_RIGHT_GUI, |
|
KC_RCMD = KC_RIGHT_GUI, |
|
KC_RWIN = KC_RIGHT_GUI, |
|
+ AP_FN = QK_APPLE_FN, |
|
SH_TOGG = QK_SWAP_HANDS_TOGGLE, |
|
SH_TT = QK_SWAP_HANDS_TAP_TOGGLE, |
|
SH_MON = QK_SWAP_HANDS_MOMENTARY_ON, |
|
@@ -1406,6 +1408,7 @@ enum qk_keycode_defines { |
|
#define IS_CONSUMER_KEYCODE(code) ((code) >= KC_AUDIO_MUTE && (code) <= KC_LAUNCHPAD) |
|
#define IS_MOUSE_KEYCODE(code) ((code) >= KC_MS_UP && (code) <= KC_MS_ACCEL2) |
|
#define IS_MODIFIER_KEYCODE(code) ((code) >= KC_LEFT_CTRL && (code) <= KC_RIGHT_GUI) |
|
+#define IS_APPLE_FN_KEYCODE(code) ((code) >= QK_APPLE_FN && (code) <= QK_APPLE_FN) |
|
#define IS_SWAP_HANDS_KEYCODE(code) ((code) >= QK_SWAP_HANDS_TOGGLE && (code) <= QK_SWAP_HANDS_ONE_SHOT) |
|
#define IS_MAGIC_KEYCODE(code) ((code) >= QK_MAGIC_SWAP_CONTROL_CAPS_LOCK && (code) <= QK_MAGIC_TOGGLE_ESCAPE_CAPS_LOCK) |
|
#define IS_MIDI_KEYCODE(code) ((code) >= QK_MIDI_ON && (code) <= QK_MIDI_PITCH_BEND_UP) |
|
diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c |
|
index 9a67fad278..36a0b309be 100644 |
|
--- a/quantum/keymap_common.c |
|
+++ b/quantum/keymap_common.c |
|
@@ -70,6 +70,11 @@ action_t action_for_keycode(uint16_t keycode) { |
|
case KC_AUDIO_MUTE ... KC_LAUNCHPAD: |
|
action.code = ACTION_USAGE_CONSUMER(KEYCODE2CONSUMER(keycode)); |
|
break; |
|
+#endif |
|
+#ifdef APPLE_FN_ENABLE |
|
+ case QK_APPLE_FN: |
|
+ action.code = ACTION_APPLE_FN(); |
|
+ break; |
|
#endif |
|
case KC_MS_UP ... KC_MS_ACCEL2: |
|
action.code = ACTION_MOUSEKEY(keycode); |
|
diff --git a/tmk_core/protocol/report.c b/tmk_core/protocol/report.c |
|
index 1ba3be4604..b53d3f687b 100644 |
|
--- a/tmk_core/protocol/report.c |
|
+++ b/tmk_core/protocol/report.c |
|
@@ -299,3 +299,13 @@ __attribute__((weak)) bool has_mouse_report_changed(report_mouse_t* new_report, |
|
return changed; |
|
} |
|
#endif |
|
+ |
|
+#ifdef APPLE_FN_ENABLE |
|
+void add_apple_fn(report_keyboard_t* keyboard_report) { |
|
+ keyboard_report->reserved = 1; |
|
+} |
|
+ |
|
+void del_apple_fn(report_keyboard_t* keyboard_report) { |
|
+ keyboard_report->reserved = 0; |
|
+} |
|
+#endif |
|
diff --git a/tmk_core/protocol/report.h b/tmk_core/protocol/report.h |
|
index 9d415a3bfd..8c65b40386 100644 |
|
--- a/tmk_core/protocol/report.h |
|
+++ b/tmk_core/protocol/report.h |
|
@@ -348,6 +348,11 @@ void clear_keys_from_report(report_keyboard_t* keyboard_report); |
|
bool has_mouse_report_changed(report_mouse_t* new_report, report_mouse_t* old_report); |
|
#endif |
|
|
|
+#ifdef APPLE_FN_ENABLE |
|
+void add_apple_fn(report_keyboard_t* keyboard_report); |
|
+void del_apple_fn(report_keyboard_t* keyboard_report); |
|
+#endif |
|
+ |
|
#ifdef __cplusplus |
|
} |
|
#endif |
|
diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c |
|
index e215c90900..e38c0d37f7 100644 |
|
--- a/tmk_core/protocol/usb_descriptor.c |
|
+++ b/tmk_core/protocol/usb_descriptor.c |
|
@@ -75,10 +75,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), |
|
+ |
|
+#ifdef APPLE_FN_ENABLE |
|
+ 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), |
|
diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c |
|
index d74f375f66..2ade1350ad 100644 |
|
--- a/tmk_core/protocol/vusb/vusb.c |
|
+++ b/tmk_core/protocol/vusb/vusb.c |
|
@@ -417,10 +417,22 @@ const PROGMEM uchar keyboard_hid_report[] = { |
|
0x95, 0x08, // Report Count (8) |
|
0x75, 0x01, // Report Size (1) |
|
0x81, 0x02, // Input (Data, Variable, Absolute) |
|
+ |
|
+#ifdef APPLE_FN_ENABLE |
|
+ 0x05, 0xFF, // Usage Page (AppleVendor Top Case) |
|
+ 0x09, 0x03, // Usage (KeyboardFn) |
|
+ 0x15, 0x00, // Logical Minimum (0) |
|
+ 0x25, 0x01, // Logical Maximum (1) |
|
+ 0x95, 0x01, // Report Count (1) |
|
+ 0x75, 0x08, // Report Size (8) |
|
+ 0x81, 0x02, // Input (Data, Variable, Absolute) |
|
+#else |
|
// Reserved (1 byte) |
|
0x95, 0x01, // Report Count (1) |
|
0x75, 0x08, // Report Size (8) |
|
0x81, 0x03, // Input (Constant) |
|
+#endif |
|
+ |
|
// Keycodes (6 bytes) |
|
0x05, 0x07, // Usage Page (Keyboard/Keypad) |
|
0x19, 0x00, // Usage Minimum (0) |
We obviously have access to the same links but we're seeing different results and making different interpretations.
The functionality using 0x29D between ZMK and QMK is not the same. I don't know what ZMK are doing on the back end, but the result is different. On QMK that code simply never works as a modifier - it cannot be combined with any other key, whether you're using an Apple VID/PID or not. With ZMK it DOES work - and Apple VID/PID has no change (it's not needed).
But how does it send any other key while that key is being held? This is where the difference in behavior lies.
On QMK the only thing that works with modifiers is to use your original patch with VID/PID change or to use CAPS remapping. But see below - neither of these works with F1-12 like they do on a real Apple keyboard.
Absolutely F1-12 has to do with the keymap because the physical position of those keys on an MCU-powered keyboard has no meaning on what codes they produce, that's entirely defined by the keymap for qmk. So for instance as I mentioned, on my Keychron, those keys aren't set up with F-codes at all, so they will never work with any implementation of Globe/Fn - not 0x29D and not your patch.
Further, in my testing on this Q3, changing the F keys to F1-12 using VIA will still not let them do anything special when combined with Globe/Fn - neither the 0x29D nor your patch and not even with CAPS remapping (even using Apple VID/PID). Example: if I change the F4 key to send an actual F4, it does the plain F4 with or without the Globe/Fn. On a real Apple keyboard this works as expected an pressing the Globe/Fn does the special LAUNCH PAD feature.
If you're not seeing the behavior I'm describing above, then that's interesting in its own right.