From 42573d9496dc44847ad995e2b79fe5e197ce1a05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 18 Aug 2021 21:54:51 +0200 Subject: [PATCH] macOS: Restructure QNSView complex text implementation For better overview of the flow and functionality of the NSTextInputClient protocol. Pick-to: 6.2 Change-Id: I8658405c7ff4ae762bfe3e4c11f9a157ae2b9a09 Reviewed-by: Volker Hilsheimer --- .../platforms/cocoa/qnsview_complextext.mm | 190 +++++++++--------- 1 file changed, 97 insertions(+), 93 deletions(-) diff --git a/src/plugins/platforms/cocoa/qnsview_complextext.mm b/src/plugins/platforms/cocoa/qnsview_complextext.mm index a7c08e53ed..4b00a8a54f 100644 --- a/src/plugins/platforms/cocoa/qnsview_complextext.mm +++ b/src/plugins/platforms/cocoa/qnsview_complextext.mm @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -39,61 +39,9 @@ // This file is included from qnsview.mm, and only used to organize the code -@implementation QNSView (ComplexTextAPI) - -- (void)cancelComposingText -{ - if (m_composingText.isEmpty()) - return; - - qCDebug(lcQpaKeys) << "Canceling composition" << m_composingText - << "for focus object" << m_composingFocusObject; - - if (queryInputMethod(m_composingFocusObject)) { - QInputMethodEvent e; - QCoreApplication::sendEvent(m_composingFocusObject, &e); - } - - m_composingText.clear(); - m_composingFocusObject = nullptr; -} - -- (void)unmarkText -{ - // FIXME: Match cancelComposingText in early exit and focus object handling - - qCDebug(lcQpaKeys) << "Unmarking" << m_composingText - << "for focus object" << m_composingFocusObject; - - if (!m_composingText.isEmpty()) { - QObject *focusObject = m_platformWindow->window()->focusObject(); - if (queryInputMethod(focusObject)) { - QInputMethodEvent e; - e.setCommitString(m_composingText); - QCoreApplication::sendEvent(focusObject, &e); - } - } - - m_composingText.clear(); - m_composingFocusObject = nullptr; -} - -@end - @implementation QNSView (ComplexText) -- (void)insertNewline:(id)sender -{ - Q_UNUSED(sender); - qCDebug(lcQpaKeys) << "Inserting newline"; - m_resendKeyEvent = true; -} - -- (void)doCommandBySelector:(SEL)aSelector -{ - qCDebug(lcQpaKeys) << "Trying to perform command" << aSelector; - [self tryToPerform:aSelector with:self]; -} +// ------------- Text insertion ------------- - (void)insertText:(id)aString replacementRange:(NSRange)replacementRange { @@ -121,6 +69,15 @@ m_composingFocusObject = nullptr; } +- (void)insertNewline:(id)sender +{ + Q_UNUSED(sender); + qCDebug(lcQpaKeys) << "Inserting newline"; + m_resendKeyEvent = true; +} + +// ------------- Text composition ------------- + - (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange { qCDebug(lcQpaKeys).nospace() << "Marking \"" << aString << "\"" @@ -182,9 +139,94 @@ } } +- (NSArray *)validAttributesForMarkedText +{ + if (!m_platformWindow) + return nil; + + if (m_platformWindow->window() != QGuiApplication::focusWindow()) + return nil; + + if (queryInputMethod(m_platformWindow->window()->focusObject())) + return @[NSUnderlineColorAttributeName, NSUnderlineStyleAttributeName]; + else + return nil; +} + - (BOOL)hasMarkedText { - return (m_composingText.isEmpty() ? NO: YES); + return !m_composingText.isEmpty(); +} + +- (NSRange)markedRange +{ + NSRange range; + if (!m_composingText.isEmpty()) { + range.location = 0; + range.length = m_composingText.length(); + } else { + range.location = NSNotFound; + range.length = 0; + } + return range; +} + +- (void)unmarkText +{ + // FIXME: Match cancelComposingText in early exit and focus object handling + + qCDebug(lcQpaKeys) << "Unmarking" << m_composingText + << "for focus object" << m_composingFocusObject; + + if (!m_composingText.isEmpty()) { + QObject *focusObject = m_platformWindow->window()->focusObject(); + if (queryInputMethod(focusObject)) { + QInputMethodEvent e; + e.setCommitString(m_composingText); + QCoreApplication::sendEvent(focusObject, &e); + } + } + + m_composingText.clear(); + m_composingFocusObject = nullptr; +} + +- (void)cancelComposingText +{ + if (m_composingText.isEmpty()) + return; + + qCDebug(lcQpaKeys) << "Canceling composition" << m_composingText + << "for focus object" << m_composingFocusObject; + + if (queryInputMethod(m_composingFocusObject)) { + QInputMethodEvent e; + QCoreApplication::sendEvent(m_composingFocusObject, &e); + } + + m_composingText.clear(); + m_composingFocusObject = nullptr; +} + +// ------------- Key binding command handling ------------- + +- (void)doCommandBySelector:(SEL)aSelector +{ + qCDebug(lcQpaKeys) << "Trying to perform command" << aSelector; + [self tryToPerform:aSelector with:self]; +} + +// ------------- Various text properties ------------- + +- (NSRange)selectedRange +{ + QObject *focusObject = m_platformWindow->window()->focusObject(); + if (auto queryResult = queryInputMethod(focusObject, Qt::ImCurrentSelection)) { + QString selectedText = queryResult.value(Qt::ImCurrentSelection).toString(); + return selectedText.isEmpty() ? NSMakeRange(0, 0) : NSMakeRange(0, selectedText.length()); + } else { + return NSMakeRange(0, 0); + } } - (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange @@ -205,30 +247,6 @@ } } -- (NSRange)markedRange -{ - NSRange range; - if (!m_composingText.isEmpty()) { - range.location = 0; - range.length = m_composingText.length(); - } else { - range.location = NSNotFound; - range.length = 0; - } - return range; -} - -- (NSRange)selectedRange -{ - QObject *focusObject = m_platformWindow->window()->focusObject(); - if (auto queryResult = queryInputMethod(focusObject, Qt::ImCurrentSelection)) { - QString selectedText = queryResult.value(Qt::ImCurrentSelection).toString(); - return selectedText.isEmpty() ? NSMakeRange(0, 0) : NSMakeRange(0, selectedText.length()); - } else { - return NSMakeRange(0, 0); - } -} - - (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange { Q_UNUSED(aRange); @@ -251,18 +269,4 @@ return NSNotFound; } -- (NSArray *)validAttributesForMarkedText -{ - if (!m_platformWindow) - return nil; - - if (m_platformWindow->window() != QGuiApplication::focusWindow()) - return nil; - - if (queryInputMethod(m_platformWindow->window()->focusObject())) - return @[NSUnderlineColorAttributeName, NSUnderlineStyleAttributeName]; - else - return nil; -} - @end