From 079a60b8070521ec93a50335b5b491421d6c5f10 Mon Sep 17 00:00:00 2001 From: Stephen A Pohl Date: Tue, 21 Jan 2025 18:38:30 +0000 Subject: [PATCH] Bug 1833923: Start detecting when the Fn key is pressed on macOS, which allows for built-in macOS shortcuts (such as Fn+e for the emoji picker) to start working. r=masayuki, a=RyanVM Differential Revision: https://phabricator.services.mozilla.com/D235051 --- dom/events/KeyEventHandler.h | 2 -- widget/TextEvents.h | 2 +- widget/cocoa/TextInputHandler.mm | 14 ++++++++++++-- widget/cocoa/nsCocoaUtils.mm | 23 ++++++++++++++++------- 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/dom/events/KeyEventHandler.h b/dom/events/KeyEventHandler.h index 5d444cf32270..974c5c4c2f64 100644 --- a/dom/events/KeyEventHandler.h +++ b/dom/events/KeyEventHandler.h @@ -133,13 +133,11 @@ class KeyEventHandler final { static const int32_t cAlt; static const int32_t cControl; static const int32_t cMeta; - static const int32_t cOS; static const int32_t cShiftMask; static const int32_t cAltMask; static const int32_t cControlMask; static const int32_t cMetaMask; - static const int32_t cOSMask; static const int32_t cAllModifiers; diff --git a/widget/TextEvents.h b/widget/TextEvents.h index a775dd84c41a..41bb624c9d0d 100644 --- a/widget/TextEvents.h +++ b/widget/TextEvents.h @@ -238,7 +238,7 @@ class WidgetKeyboardEvent final : public WidgetInputEvent { // we don't have any bug reports that user cannot input proper // character with Alt and/or Ctrl key. // -- On macOS, IMEInputHandler::WillDispatchKeyboardEvent() clears - // MODIFIER_ALT and MDOFIEIR_CONTROL of eKeyPress event only when + // MODIFIER_ALT and MODIFIER_CONTROL of eKeyPress event only when // TextInputHandler::InsertText() has been called for the event. // I.e., they are cleared only when an editor has focus (even if IME // is disabled in password field or by |ime-mode: disabled;|) because diff --git a/widget/cocoa/TextInputHandler.mm b/widget/cocoa/TextInputHandler.mm index 046f1c46bedd..3a2ae103edae 100644 --- a/widget/cocoa/TextInputHandler.mm +++ b/widget/cocoa/TextInputHandler.mm @@ -533,9 +533,11 @@ bool TISInputSourceWrapper::IsDeadKey(NSEvent* aNativeKeyEvent) { return false; } - // Assmue that if control key or command key is pressed, it's not a dead key. + // Assume that if the control key, command key or Fn key is pressed, it's not + // a dead key. NSUInteger cocoaState = [aNativeKeyEvent modifierFlags]; - if (cocoaState & (NSEventModifierFlagControl | NSEventModifierFlagCommand)) { + if (cocoaState & (NSEventModifierFlagControl | NSEventModifierFlagCommand | + NSEventModifierFlagFunction)) { return false; } @@ -1838,6 +1840,14 @@ bool TextInputHandler::HandleKeyDownEvent(NSEvent* aNativeEvent, return false; } + // macOS supports shortcut keys using the `Fn` key. Check first if this key + // event is such a shortcut key. + if (nsCocoaUtils::ModifiersForEvent(aNativeEvent) & MODIFIER_FN) { + if (mWidget->SendEventToNativeMenuSystem(aNativeEvent)) { + return true; + } + } + // Let Cocoa interpret the key events, caching IsIMEComposing first. bool wasComposing = IsIMEComposing(); bool interpretKeyEventsCalled = false; diff --git a/widget/cocoa/nsCocoaUtils.mm b/widget/cocoa/nsCocoaUtils.mm index 8dd8f56ddc0d..bfb09be0d894 100644 --- a/widget/cocoa/nsCocoaUtils.mm +++ b/widget/cocoa/nsCocoaUtils.mm @@ -709,7 +709,8 @@ NSEvent* nsCocoaUtils::MakeNewCococaEventFromWidgetEvent( {MODIFIER_ALTGRAPH, NSEventModifierFlagOption}, {MODIFIER_META, NSEventModifierFlagCommand}, {MODIFIER_CAPSLOCK, NSEventModifierFlagCapsLock}, - {MODIFIER_NUMLOCK, NSEventModifierFlagNumericPad}}; + {MODIFIER_NUMLOCK, NSEventModifierFlagNumericPad}, + {MODIFIER_FN, NSEventModifierFlagFunction}}; NSUInteger modifierFlags = 0; for (uint32_t i = 0; i < ArrayLength(sModifierFlagMap); ++i) { @@ -794,9 +795,18 @@ Modifiers nsCocoaUtils::ModifiersForEvent(NSEvent* aNativeEvent) { result |= MODIFIER_NUMLOCK; } - // Be aware, NSEventModifierFlagFunction is included when arrow keys, home key - // or some other keys are pressed. We cannot check whether 'fn' key is pressed - // or not by the flag. + // Be aware, NSEventModifierFlagFunction is also set on the native event when + // arrow keys, the home key or some other keys are pressed. We cannot check + // whether the 'fn' key is pressed or not by the flag alone. We need to check + // that the event's keyCode falls outside the range of keys that will also set + // the function modifier. + if (!!(modifiers & NSEventModifierFlagFunction) && + (aNativeEvent.type == NSKeyDown || aNativeEvent.type == NSKeyUp || + aNativeEvent.type == NSFlagsChanged) && + !(kVK_Return <= aNativeEvent.keyCode && + aNativeEvent.keyCode <= NSModeSwitchFunctionKey)) { + result |= MODIFIER_FN; + } return result; } @@ -935,12 +945,11 @@ struct KeyConversionData { static const KeyConversionData gKeyConversions[] = { -#define KEYCODE_ENTRY(aStr, aCode) \ - { #aStr, sizeof(#aStr) - 1, NS_##aStr, aCode } +#define KEYCODE_ENTRY(aStr, aCode) {#aStr, sizeof(#aStr) - 1, NS_##aStr, aCode} // Some keycodes may have different name in KeyboardEvent from its key name. #define KEYCODE_ENTRY2(aStr, aNSName, aCode) \ - { #aStr, sizeof(#aStr) - 1, NS_##aNSName, aCode } + {#aStr, sizeof(#aStr) - 1, NS_##aNSName, aCode} KEYCODE_ENTRY(VK_CANCEL, 0x001B), KEYCODE_ENTRY(VK_DELETE, NSDeleteFunctionKey),