From 2d05d3bd2815c220474b3c07bf3f2ef7417d3070 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Mon, 21 May 2012 11:26:12 +0200 Subject: Cocoa: don't send input method events for basic text input MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When receiving keyDown events on the Mac, we pass them to NSView's interpretKeyEvents method, which ends up calling our insertText method. This means we end up sending input method events for most text input (instead of normal key events). While this is not wrong, it is unexpected, and different form how Qt 4 works. Change insertText to do nothing if no preedit string has been set when handling a key event. For normal text input that does not need input method handling, we can simply return and let handleKeyEvent send key events instead. Our insertText implementation has to take care to not ignore calls from outside key event processing (such as the user input characters with the Character Viewer). As a result m_keyEventsAccepted changes to m_sendKeyEvent to let insertText know whether or not insertText was called via handleKeyEvent. Change-Id: Ie8c2eb67f6a8438f08442f9ff48f2027a041ca23 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qnsview.h | 2 +- src/plugins/platforms/cocoa/qnsview.mm | 36 ++++++++++++++++++++++++---------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index 16775621bf..2e8d9cebe9 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -59,7 +59,7 @@ QT_END_NAMESPACE Qt::MouseButtons m_buttons; QAccessibleInterface *m_accessibleRoot; QString m_composingText; - bool m_keyEventsAccepted; + bool m_sendKeyEvent; QStringList *currentCustomDragTypes; Qt::KeyboardModifiers currentWheelModifiers; } diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index a8372f754f..755b393af2 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -75,6 +75,7 @@ static QTouchDevice *touchDevice = 0; m_cgImage = 0; m_window = 0; m_buttons = Qt::NoButton; + m_sendKeyEvent = false; currentCustomDragTypes = 0; if (!touchDevice) { touchDevice = new QTouchDevice; @@ -95,7 +96,7 @@ static QTouchDevice *touchDevice = 0; m_window = window; m_platformWindow = platformWindow; m_accessibleRoot = 0; - m_keyEventsAccepted = false; + m_sendKeyEvent = false; #ifdef QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR // prevent rift in space-time continuum, disable @@ -614,6 +615,9 @@ static QTouchDevice *touchDevice = 0; QChar ch([charactersIgnoringModifiers characterAtIndex:0]); int keyCode = [self convertKeyCode:ch]; + // we will send a key event unless the input method sets m_sendKeyEvent to false + m_sendKeyEvent = true; + QString text; if (eventType == QEvent::KeyPress) { // ignore text for the U+F700-U+F8FF range. This is used by Cocoa when @@ -621,27 +625,31 @@ static QTouchDevice *touchDevice = 0; if ([charactersIgnoringModifiers length] == 1 && (ch.unicode() < 0xf700 || ch.unicode() > 0xf8ff)) text = QString::fromUtf8([[nsevent characters] UTF8String]); - if (!m_keyEventsAccepted && m_composingText.isEmpty()) - m_keyEventsAccepted = QWindowSystemInterface::tryHandleSynchronousShortcutEvent(m_window, timestamp, keyCode, modifiers, text); + if (m_composingText.isEmpty()) + m_sendKeyEvent = !QWindowSystemInterface::tryHandleSynchronousShortcutEvent(m_window, timestamp, keyCode, modifiers, text); QObject *fo = QGuiApplication::focusObject(); - if (!m_keyEventsAccepted && fo) { + if (m_sendKeyEvent && fo) { QInputMethodQueryEvent queryEvent(Qt::ImEnabled | Qt::ImHints); if (QCoreApplication::sendEvent(fo, &queryEvent)) { bool imEnabled = queryEvent.value(Qt::ImEnabled).toBool(); Qt::InputMethodHints hints = static_cast(queryEvent.value(Qt::ImHints).toUInt()); - if (imEnabled && !(hints & Qt::ImhDigitsOnly || hints & Qt::ImhFormattedNumbersOnly || hints & Qt::ImhHiddenText)) + if (imEnabled && !(hints & Qt::ImhDigitsOnly || hints & Qt::ImhFormattedNumbersOnly || hints & Qt::ImhHiddenText)) { + // pass the key event to the input method. note that m_sendKeyEvent may be set to false during this call [self interpretKeyEvents:[NSArray arrayWithObject:nsevent]]; + } } } } - if (!m_keyEventsAccepted && m_composingText.isEmpty()) + + if (m_sendKeyEvent && m_composingText.isEmpty()) QWindowSystemInterface::handleKeyEvent(m_window, timestamp, QEvent::Type(eventType), keyCode, modifiers, text); + + m_sendKeyEvent = false; } - (void)keyDown:(NSEvent *)nsevent { - m_keyEventsAccepted = false; [self handleKeyEvent:nsevent eventType:int(QEvent::KeyPress)]; } @@ -695,6 +703,12 @@ static QTouchDevice *touchDevice = 0; - (void) insertText:(id)aString replacementRange:(NSRange)replacementRange { Q_UNUSED(replacementRange) + + if (m_sendKeyEvent && m_composingText.isEmpty()) { + // don't send input method events for simple text input (let handleKeyEvent send key events instead) + return; + } + QString commitString; if ([aString length]) { if ([aString isKindOfClass:[NSAttributedString class]]) { @@ -711,13 +725,14 @@ static QTouchDevice *touchDevice = 0; QInputMethodEvent e; e.setCommitString(commitString); QCoreApplication::sendEvent(fo, &e); - m_keyEventsAccepted = true; + // prevent handleKeyEvent from sending a key event + m_sendKeyEvent = false; } } } m_composingText.clear(); - } +} - (void) setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange { @@ -777,7 +792,8 @@ static QTouchDevice *touchDevice = 0; if (queryEvent.value(Qt::ImEnabled).toBool()) { QInputMethodEvent e(preeditString, attrs); QCoreApplication::sendEvent(fo, &e); - m_keyEventsAccepted = true; + // prevent handleKeyEvent from sending a key event + m_sendKeyEvent = false; } } } -- cgit v1.2.3