diff options
author | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> | 2017-08-29 09:56:36 +0200 |
---|---|---|
committer | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> | 2017-09-04 13:51:19 +0000 |
commit | 52bda430af2749da1a0467b71d9cca5208f22402 (patch) | |
tree | daa30b51a46f32cb3732b14ffe6e3cf321b1cf8b /src/plugins | |
parent | f9fea20c10ca7864cfa551fce23124d358c11b3a (diff) |
macOS: Reset composition when focus object changes inside window
When the focus object inside a window changes and we are
currently composing text, we have to cancel composition to avoid
getting into an inconsistent state. This is what already happens
if you switch to a different top level window.
Note: Because we limit the user's ability to change focus inside
a window when composing text, this would only happen under
certain circumstances, such as creating a new MDI window with
an editor while still composing text in a previous one.
[ChangeLog][macOS] Switching focus objects inside a top level window
while composing text using dead keys or input method events would
leave the application in an inconsistent state. The composition
now automatically cancels when the focus object changes.
Task-number: QTBUG-59222
Change-Id: I06792a7db1441dcc5c87e4bf0861b422a25f7f7c
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoainputcontext.mm | 17 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qnsview.h | 2 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qnsview.mm | 22 |
3 files changed, 40 insertions, 1 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoainputcontext.mm b/src/plugins/platforms/cocoa/qcocoainputcontext.mm index 9e3d747cd7..9221099a57 100644 --- a/src/plugins/platforms/cocoa/qcocoainputcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoainputcontext.mm @@ -124,7 +124,22 @@ void QCocoaInputContext::connectSignals() void QCocoaInputContext::focusObjectChanged(QObject *focusObject) { Q_UNUSED(focusObject); - mWindow = QGuiApplication::focusWindow(); + if (mWindow == QGuiApplication::focusWindow()) { + if (!mWindow) + return; + + QCocoaWindow *window = static_cast<QCocoaWindow *>(mWindow->handle()); + QNSView *view = qnsview_cast(window->view()); + if (!view) + return; + + if (NSTextInputContext *ctxt = [NSTextInputContext currentInputContext]) { + [ctxt discardMarkedText]; + [view cancelComposingText]; + } + } else { + mWindow = QGuiApplication::focusWindow(); + } } void QCocoaInputContext::updateLocale() diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index c37c45ce80..384f14ba3a 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -70,6 +70,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper)); Qt::MouseButtons m_acceptedMouseDowns; Qt::MouseButtons m_frameStrutButtons; QString m_composingText; + QPointer<QObject> m_composingFocusObject; bool m_sendKeyEvent; QStringList *currentCustomDragTypes; bool m_sendUpAsRightButton; @@ -104,6 +105,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper)); - (void)viewDidHide; - (void)viewDidUnhide; - (void)removeFromSuperview; +- (void)cancelComposingText; - (BOOL)isFlipped; - (BOOL)acceptsFirstResponder; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index a40bdfd314..ba5c0ea25d 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -1712,6 +1712,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) } m_composingText.clear(); + m_composingFocusObject = nullptr; } - (void) setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange @@ -1766,6 +1767,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) m_composingText = preeditString; if (QObject *fo = m_platformWindow->window()->focusObject()) { + m_composingFocusObject = fo; QInputMethodQueryEvent queryEvent(Qt::ImEnabled); if (QCoreApplication::sendEvent(fo, &queryEvent)) { if (queryEvent.value(Qt::ImEnabled).toBool()) { @@ -1778,6 +1780,25 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) } } +- (void)cancelComposingText +{ + if (m_composingText.isEmpty()) + return; + + if (m_composingFocusObject) { + QInputMethodQueryEvent queryEvent(Qt::ImEnabled); + if (QCoreApplication::sendEvent(m_composingFocusObject, &queryEvent)) { + if (queryEvent.value(Qt::ImEnabled).toBool()) { + QInputMethodEvent e; + QCoreApplication::sendEvent(m_composingFocusObject, &e); + } + } + } + + m_composingText.clear(); + m_composingFocusObject = nullptr; +} + - (void) unmarkText { if (!m_composingText.isEmpty()) { @@ -1793,6 +1814,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) } } m_composingText.clear(); + m_composingFocusObject = nullptr; } - (BOOL) hasMarkedText |