diff options
author | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2022-12-02 14:48:14 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2022-12-05 23:04:19 +0000 |
commit | 3e3968d0a4153d4f08a1b748f47656a4362ce6bb (patch) | |
tree | a82c1422493b670a551dafd77edcd5593bb1317b | |
parent | e9c7d0c10a30a9b2bf23b30030aa93a45c50c7d7 (diff) | |
download | qtbase-3e3968d0a4153d4f08a1b748f47656a4362ce6bb.tar.gz |
macOS: Don't pass on key event text for function keys when IM is disabled
On macOS function keys such F1-F16 and the arrow keys result in NSEvents
with a character in the 0xF700-0xF8FF range of the private use area:
https://unicode.org/Public/MAPPINGS/VENDORS/APPLE/CORPCHAR.TXT
We used to filter these out for all key events sent from the platform
plugin (4dbce2a4696081), but this had the side effect of breaking the
Unicode Hex Input keyboard's ability to explicitly input these
characters.
As of 705665957baf16f9ec4d256dd4d2fad98788314b we started trusting the
macOS text input system on whether a key event should include text or
not, which fixed both the hex keyboard and Russian keyboard input when
the key included the ^⌥ modifiers.
Unfortunately this didn't account for the case of non-IM enabled input,
so we started sending key events with text for arrow and function keys.
And since Arial Unicode MS provides glyphs for these code points, we
would end up with confusing characters in input fields when pressing
the arrow keys.
In general a client can not assume that the text() of a QKeyEvent is
printable, and the logic to determine if a character should be filtered
out or not depends on the font matching, since all code points can in
theory have a font that provides a glyph for it, but since we know that
the function key range on macOS is not supposed to have associated
glyphs we filter them out explicitly.
Note that we only do this for non-IM enabled text input, and otherwise
leave it up to the macOS text input system to determine if a event
should result in text insertion or not.
Task-number: QTBUG-106393
Change-Id: I5498fbedee21b0720c56e99b26924959ade897bf
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit b2e5d547263f297a7a8f37e8ad5cded7e66f93c9)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | src/plugins/platforms/cocoa/qnsview_keys.mm | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/src/plugins/platforms/cocoa/qnsview_keys.mm b/src/plugins/platforms/cocoa/qnsview_keys.mm index 3eb8e2f4d6..7619ecbc4b 100644 --- a/src/plugins/platforms/cocoa/qnsview_keys.mm +++ b/src/plugins/platforms/cocoa/qnsview_keys.mm @@ -3,6 +3,33 @@ // This file is included from qnsview.mm, and only used to organize the code +/* + Determines if the text represents one of the "special keys" on macOS + + As a legacy from OpenStep, macOS reserves the range 0xF700-0xF8FF of the + Unicode private use area for representing function keys on the keyboard: + + http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/CORPCHAR.TXT + + https://developer.apple.com/documentation/appkit/nsevent/specialkey + + These code points are not supposed to have any glyphs associated with them, + but since we can't guarantee that the system doesn't have a font that does + provide glyphs for this range (Arial Unicode MS e.g.) we need to filter + the text of our key events up front. +*/ +static bool isSpecialKey(const QString &text) +{ + if (text.length() != 1) + return false; + + const char16_t unicode = text.at(0).unicode(); + if (unicode >= 0xF700 && unicode <= 0xF8FF) + return true; + + return false; +} + @implementation QNSView (Keys) - (bool)handleKeyEvent:(NSEvent *)nsevent @@ -20,6 +47,8 @@ // otherwise by doCommandBySelector. m_sendKeyEventWithoutText = false; + bool didInterpretKeyEvent = false; + if (keyEvent.type == QEvent::KeyPress) { if (m_composingText.isEmpty()) { @@ -67,6 +96,7 @@ m_currentlyInterpretedKeyEvent = nsevent; [self interpretKeyEvents:@[nsevent]]; m_currentlyInterpretedKeyEvent = 0; + didInterpretKeyEvent = true; // If the last key we sent was dead, then pass the next // key to the IM as well to complete composition. @@ -80,7 +110,9 @@ bool accepted = true; if (m_sendKeyEvent && m_composingText.isEmpty()) { KeyEvent keyEvent(nsevent); - if (m_sendKeyEventWithoutText) + // Trust text input system on whether to send the event with text or not, + // or otherwise apply heuristics to filter out private use symbols. + if (didInterpretKeyEvent ? m_sendKeyEventWithoutText : isSpecialKey(keyEvent.text)) keyEvent.text = {}; qCDebug(lcQpaKeys) << "Sending as" << keyEvent; accepted = keyEvent.sendWindowSystemEvent(window); |