summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2022-12-02 14:48:14 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-12-05 23:04:19 +0000
commit3e3968d0a4153d4f08a1b748f47656a4362ce6bb (patch)
treea82c1422493b670a551dafd77edcd5593bb1317b
parentFix typo in documentation for QVariant::nameToType (diff)
downloadqtbase-3e3968d0a4153d4f08a1b748f47656a4362ce6bb.tar.xz
qtbase-3e3968d0a4153d4f08a1b748f47656a4362ce6bb.zip
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.mm34
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);