From 7132f773ba2a1dc440e39fa8ab364505f1dc61c9 Mon Sep 17 00:00:00 2001 From: Stephen A Pohl Date: Sat, 2 Nov 2024 02:13:06 +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 Depends on D195016 Differential Revision: https://phabricator.services.mozilla.com/D223630 --- dom/events/KeyEventHandler.h | 2 -- widget/TextEvents.h | 2 +- widget/cocoa/TextInputHandler.mm | 14 ++++++++++++-- widget/cocoa/nsCocoaUtils.mm | 18 ++++++++++++++---- 4 files changed, 27 insertions(+), 9 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 e25acef5d738..a7fba34f94c0 100644 --- a/widget/cocoa/TextInputHandler.mm +++ b/widget/cocoa/TextInputHandler.mm @@ -545,9 +545,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; } @@ -1849,6 +1851,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 5ecca19e3b17..e0b3e1d79353 100644 --- a/widget/cocoa/nsCocoaUtils.mm +++ b/widget/cocoa/nsCocoaUtils.mm @@ -701,7 +701,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 < std::size(sModifierFlagMap); ++i) { @@ -786,9 +787,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; }