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)
131 newlineEvent.text = isEnter ?
QLatin1Char(kEnterCharCode)
133 newlineEvent.nativeVirtualKey = isEnter ?
quint32(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);
171 QList<QInputMethodEvent::Attribute> preeditAttributes;
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]) {
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(),
466 availableText.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 auto level = m_platformWindow ? m_platformWindow->nativeWindow().level
522 : NSNormalWindowLevel;
531 return qMax(
level, NSPopUpMenuWindowLevel);
547- (NSRange)sanitizeReplacementRange:(NSRange)range
549 if (
range.location != NSNotFound)
555 const auto markedRange = [
self markedRange];
556 if (markedRange.location != NSNotFound)
559 return [
self selectedRange];
568- (
std::pair<long long, long long>)inputMethodRangeForRange:(NSRange)range
570 long long replaceFrom =
range.location;
571 long long replaceLength =
range.length;
573 const auto markedRange = [
self markedRange];
574 const auto selectedRange = [
self selectedRange];
578 if (markedRange.location != NSNotFound)
579 replaceFrom -= markedRange.
location;
586 replaceLength -= selectedRange.
length;
591 replaceLength -= markedRange.
length;
595 replaceLength =
qMax(0ll, replaceLength);
597 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()
\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
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
void clear()
Clears the contents of the string and makes it null.
qsizetype length() const noexcept
Returns the number of characters in this string.
void setFontUnderline(bool underline)
If underline is true, sets the text format's font to be underlined; otherwise it is displayed non-und...
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 GLint level
GLenum GLuint GLenum GLsizei length
GLint GLsizei GLsizei GLenum format
QFileSelector selector
[1]
\inmodule QtCore \reentrant