6@implementation QNSView (ComplexText)
15 if (!m_platformWindow)
18 return m_platformWindow->window()->focusObject();
41- (
void)insertText:(
id)text replacementRange:(NSRange)replacementRange
43 qCDebug(lcQpaKeys).nospace() <<
"Inserting \"" <<
text <<
"\""
44 <<
", replacing range " << replacementRange;
52 auto *currentEvent = NSApp.currentEvent;
53 NSString *eventText = currentEvent.type == NSEventTypeKeyDown
54 || currentEvent.type == NSEventTypeKeyUp
55 ? currentEvent.characters : nil;
57 if ([
text isEqualToString:eventText]) {
60 qCDebug(lcQpaKeys) <<
"Ignoring text insertion for simple text";
69 const bool isAttributedString = [text isKindOfClass:NSAttributedString.class];
70 QString commitString = QString::fromNSString(isAttributedString ? [
text string] :
text);
73 replacementRange = [
self sanitizeReplacementRange:replacementRange];
77 auto [replaceFrom, replaceLength] = [
self inputMethodRangeForRange:replacementRange];
79 if (replaceFrom == NSNotFound) {
80 qCWarning(lcQpaKeys) <<
"Failed to compute valid replacement range for text insertion";
83 qCDebug(lcQpaKeys) <<
"Replacing from" << replaceFrom <<
"with length" << replaceLength
84 <<
"based on replacement range" << replacementRange;
85 inputMethodEvent.
setCommitString(commitString, replaceFrom, replaceLength);
95- (
void)insertNewline:(
id)sender
99 if (!m_platformWindow)
133 newlineEvent.nativeVirtualKey = isEnter ? kVK_ANSI_KeypadEnter
136 qCDebug(lcQpaKeys) <<
"Inserting newline via" << newlineEvent;
137 newlineEvent.sendWindowSystemEvent(m_platformWindow->window());
162- (
void)setMarkedText:(
id)text selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange
164 qCDebug(lcQpaKeys).nospace() <<
"Marking \"" <<
text <<
"\""
165 <<
" with selected range " << selectedRange
166 <<
", replacing range " << replacementRange;
168 const bool isAttributedString = [text isKindOfClass:NSAttributedString.class];
169 QString preeditString = QString::fromNSString(isAttributedString ? [
text string] :
text);
179 const bool showCursor = !selectedRange.
length;
191 auto *systemPalette = platformTheme->palette();
195 selectedRange.location, selectedRange.length,
199 int composingLength = preeditString.
length();
200 while (
index < composingLength) {
203 static NSDictionary *defaultMarkedTextAttributes = []{
204 NSTextView *textView = [[NSTextView new] autorelease];
205 return [textView.markedTextAttributes retain];
208 NSDictionary *attributes = isAttributedString
209 ? [text attributesAtIndex:index longestEffectiveRange:&range inRange:range]
210 : defaultMarkedTextAttributes;
212 qCDebug(lcQpaKeys) <<
"Decorating range" <<
range <<
"based on" << attributes;
215 if (NSNumber *underlineStyle = attributes[NSUnderlineStyleAttributeName]) {
216 format.setFontUnderline(
true);
217 NSUnderlineStyle style = underlineStyle.integerValue;
218 if (style & NSUnderlineStylePatternDot)
220 else if (style & NSUnderlineStylePatternDash)
222 else if (style & NSUnderlineStylePatternDashDot)
224 if (style & NSUnderlineStylePatternDashDotDot)
233 if (NSColor *underlineColor = attributes[NSUnderlineColorAttributeName])
235 if (NSColor *foregroundColor = attributes[NSForegroundColorAttributeName])
237 if (NSColor *backgroundColor = attributes[NSBackgroundColorAttributeName])
249 replacementRange = [
self sanitizeReplacementRange:replacementRange];
253 auto [replaceFrom, replaceLength] = [
self inputMethodRangeForRange:replacementRange];
262 if (replaceLength > 0) {
266 qCDebug(lcQpaKeys) <<
"Replacing from" << replaceFrom <<
"with length"
267 << replaceLength <<
"based on replacement range" << replacementRange;
268 event.setCommitString(
QString(), replaceFrom, replaceLength);
275- (NSArray<NSString *> *)validAttributesForMarkedText
278 NSUnderlineColorAttributeName,
279 NSUnderlineStyleAttributeName,
280 NSForegroundColorAttributeName,
281 NSBackgroundColorAttributeName
298- (NSRange)markedRange
315 return {NSNotFound, 0};
354- (
void)cancelComposingText
373- (
void)doCommandBySelector:(
SEL)selector
385 if (![NSStringFromSelector(
selector) hasPrefix:
@"insert"]) {
406- (NSRange)selectedRange
418 int absoluteOffset = absoluteCursorPosition - cursorPosition;
420 int anchorPosition = absoluteOffset + queryResult.
value(
Qt::ImAnchorPosition).toInt();
421 int selectionStart = anchorPosition >= absoluteCursorPosition ? absoluteCursorPosition : anchorPosition;
422 int selectionEnd = selectionStart == anchorPosition ? absoluteCursorPosition : anchorPosition;
423 int selectionLength = selectionEnd - selectionStart;
433 return NSMakeRange(selectionStart, selectionLength);
435 return {NSNotFound, 0};
453- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)range actualRange:(NSRangePointer)actualRange
465 const NSRange availableRange = NSMakeRange(absoluteCursorPosition - textBeforeCursor.
length(),
468 const NSRange intersectedRange = NSIntersectionRange(
range, availableRange);
470 *actualRange = intersectedRange;
472 if (!intersectedRange.length)
476 intersectedRange.location - availableRange.location,
477 intersectedRange.length).toNSString();
479 return [[[NSAttributedString alloc] initWithString:substring] autorelease];
486- (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(NSRangePointer)actualRange
491 QWindow *
window = m_platformWindow ? m_platformWindow->window() :
nullptr;
493 QRect cursorRect =
qApp->inputMethod()->cursorRectangle().toRect();
501- (
NSUInteger)characterIndexForPoint:(NSPoint)point
521- (NSRange)sanitizeReplacementRange:(NSRange)range
523 if (
range.location != NSNotFound)
529 const auto markedRange = [
self markedRange];
530 if (markedRange.location != NSNotFound)
533 return [
self selectedRange];
542- (
std::pair<long long, long long>)inputMethodRangeForRange:(NSRange)range
544 long long replaceFrom =
range.location;
545 long long replaceLength =
range.length;
547 const auto markedRange = [
self markedRange];
548 const auto selectedRange = [
self selectedRange];
552 if (markedRange.location != NSNotFound)
553 replaceFrom -= markedRange.
location;
560 replaceLength -= selectedRange.
length;
565 replaceLength -= markedRange.
length;
569 replaceLength =
qMax(0ll, replaceLength);
571 return {replaceFrom, replaceLength};
static CGPoint mapToNative(const QPointF &pos, QCocoaScreen *screen=QCocoaScreen::primaryScreen())
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
static QPlatformTheme * platformTheme()
qsizetype length() const noexcept
\inmodule QtCore\reentrant
constexpr QPoint bottomLeft() const noexcept
Returns the position of the rectangle's bottom-left corner.
constexpr void moveBottomLeft(const QPoint &p) noexcept
Moves the rectangle, leaving the bottom-left corner at the given position.
constexpr QStringView mid(qsizetype pos, qsizetype n=-1) const noexcept
Returns the substring of length length starting at position start in this object.
\macro QT_RESTRICTED_CAST_FROM_ASCII
void clear()
Clears the contents of the string and makes it null.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
qsizetype length() const
Returns the number of characters in this string.
void setBackground(const QBrush &brush)
Sets the brush use to paint the document's background to the brush specified.
InputMethodQueryResult queryInputMethod(QObject *object, Qt::InputMethodQueries queries)
QColor qt_mac_toQColor(CGColorRef color)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qCWarning(category,...)
#define qCDebug(category,...)
constexpr const T & qMax(const T &a, const T &b)
NSEvent * m_currentlyInterpretedKeyEvent
QPointer< QObject > m_composingFocusObject
bool m_sendKeyEventWithoutText
GLenum GLuint GLenum GLsizei length
GLint GLsizei GLsizei GLenum format
QFileSelector selector
[1]
QFlags< Qt::KeyboardModifier > modifiers
\inmodule QtCore \reentrant