macOS: Correctly implement attributedSubstringForProposedRange
The substring range refers to the entire text of the focus object, not just the selection. As there is no way to pull out the entire text via input method queries we do the best we can via ImTextBeforeCursor and ImTextAfterCursor. Returning the correct substring enables input method features such as backtracking into already committed text with the Hiragana IM, as well as the Keyboard Viewer's 'Current Text' toolbar. Pick-to: 6.2 Change-Id: I53286ef1e8e7c5fba37858dda7317ae74d95b528 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
parent
9e1875483c
commit
3de396590c
@ -435,17 +435,47 @@
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Returns an attributed string derived from the given range
|
||||
in the underlying focus object's text storage.
|
||||
|
||||
Input methods may call this with a proposed range that is
|
||||
out of bounds. For example, the InkWell text input service
|
||||
may ask for the contents of the text input client that extends
|
||||
beyond the document's range. To remedy this we always compute
|
||||
the intersection between the proposed range and the available
|
||||
text.
|
||||
|
||||
If the intersection is completely outside of the available text
|
||||
this method returns nil.
|
||||
*/
|
||||
- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)range actualRange:(NSRangePointer)actualRange
|
||||
{
|
||||
Q_UNUSED(actualRange);
|
||||
|
||||
QObject *focusObject = m_platformWindow->window()->focusObject();
|
||||
if (auto queryResult = queryInputMethod(focusObject, Qt::ImCurrentSelection)) {
|
||||
QString selectedText = queryResult.value(Qt::ImCurrentSelection).toString();
|
||||
if (selectedText.isEmpty())
|
||||
if (auto queryResult = queryInputMethod(focusObject,
|
||||
Qt::ImAbsolutePosition | Qt::ImTextBeforeCursor | Qt::ImTextAfterCursor)) {
|
||||
const int absoluteCursorPosition = queryResult.value(Qt::ImAbsolutePosition).toInt();
|
||||
const QString textBeforeCursor = queryResult.value(Qt::ImTextBeforeCursor).toString();
|
||||
const QString textAfterCursor = queryResult.value(Qt::ImTextAfterCursor).toString();
|
||||
|
||||
// The documentation doesn't say whether the marked text should be included
|
||||
// in the available text, but observing NSTextView shows that this is the
|
||||
// case, so we follow suit.
|
||||
const QString availableText = textBeforeCursor + m_composingText + textAfterCursor;
|
||||
const NSRange availableRange = NSMakeRange(absoluteCursorPosition - textBeforeCursor.length(),
|
||||
availableText.length());
|
||||
|
||||
const NSRange intersectedRange = NSIntersectionRange(range, availableRange);
|
||||
if (actualRange)
|
||||
*actualRange = intersectedRange;
|
||||
|
||||
if (!intersectedRange.length)
|
||||
return nil;
|
||||
|
||||
NSString *substring = QStringView(selectedText).mid(range.location, range.length).toNSString();
|
||||
NSString *substring = QStringView(availableText).mid(
|
||||
intersectedRange.location - availableRange.location,
|
||||
intersectedRange.length).toNSString();
|
||||
|
||||
return [[[NSAttributedString alloc] initWithString:substring] autorelease];
|
||||
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user