Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qnsview_complextext.mm
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4// This file is included from qnsview.mm, and only used to organize the code
5
6@implementation QNSView (ComplexText)
7
8// ------------- Text insertion -------------
9
11{
12 // The text input system may still hold a reference to our QNSView,
13 // even after QCocoaWindow has been destructed, delivering text input
14 // events to us, so we need to guard for this situation explicitly.
15 if (!m_platformWindow)
16 return nullptr;
17
18 return m_platformWindow->window()->focusObject();
19}
20
21/*
22 Inserts the given text, potentially replacing existing text.
23
24 The text input management system calls this as a result of:
25
26 - A normal key press, via [NSView interpretKeyEvents:] or
27 [NSInputContext handleEvent:]
28
29 - An input method finishing (confirming) composition
30
31 - Pressing a key in the Keyboard Viewer panel
32
33 - Confirming an inline input area (accent popup e.g.)
34
35 \a replacementRange refers to the existing text to replace.
36 Under normal circumstances this is {NSNotFound, 0}, and the
37 implementation should replace either the existing marked text,
38 the current selection, or just insert the text at the current
39 cursor location.
40*/
41- (void)insertText:(id)text replacementRange:(NSRange)replacementRange
42{
43 qCDebug(lcQpaKeys).nospace() << "Inserting \"" << text << "\""
44 << ", replacing range " << replacementRange;
45
47 // The input method may have transformed the incoming key event
48 // to text that doesn't match what the original key event would
49 // have produced, for example when 'Pinyin - Simplified' does smart
50 // replacement of quotes. If that's the case we can't rely on
51 // handleKeyEvent for sending the text.
52 auto *currentEvent = NSApp.currentEvent;
53 NSString *eventText = currentEvent.type == NSEventTypeKeyDown
54 || currentEvent.type == NSEventTypeKeyUp
55 ? currentEvent.characters : nil;
56
57 if ([text isEqualToString:eventText]) {
58 // We do not send input method events for simple text input,
59 // and instead let handleKeyEvent send the key event.
60 qCDebug(lcQpaKeys) << "Ignoring text insertion for simple text";
61 m_sendKeyEvent = true;
62 return;
63 }
64 }
65
66 if (queryInputMethod(self.focusObject)) {
67 QInputMethodEvent inputMethodEvent;
68
69 const bool isAttributedString = [text isKindOfClass:NSAttributedString.class];
70 QString commitString = QString::fromNSString(isAttributedString ? [text string] : text);
71
72 // Ensure we have a valid replacement range
73 replacementRange = [self sanitizeReplacementRange:replacementRange];
74
75 // Qt's QInputMethodEvent has different semantics for the replacement
76 // range than AppKit does, so we need to sanitize the range first.
77 auto [replaceFrom, replaceLength] = [self inputMethodRangeForRange:replacementRange];
78
79 if (replaceFrom == NSNotFound) {
80 qCWarning(lcQpaKeys) << "Failed to compute valid replacement range for text insertion";
81 inputMethodEvent.setCommitString(commitString);
82 } else {
83 qCDebug(lcQpaKeys) << "Replacing from" << replaceFrom << "with length" << replaceLength
84 << "based on replacement range" << replacementRange;
85 inputMethodEvent.setCommitString(commitString, replaceFrom, replaceLength);
86 }
87
88 QCoreApplication::sendEvent(self.focusObject, &inputMethodEvent);
89 }
90
92 m_composingFocusObject = nullptr;
93}
94
95- (void)insertNewline:(id)sender
96{
97 Q_UNUSED(sender);
98
99 if (!m_platformWindow)
100 return;
101
102 // Depending on the input method, pressing enter may
103 // result in simply dismissing the input method editor,
104 // without confirming the composition. In other cases
105 // it may confirm the composition as well. And in some
106 // cases the IME will produce an explicit new line, which
107 // brings us here.
108
109 // Semantically, the input method has asked us to insert
110 // a newline, and we should do so via an QInputMethodEvent,
111 // either directly or via [self insertText:@"\r"]. This is
112 // also how NSTextView handles the command. But, if we did,
113 // we would bypass all the code in Qt (and clients) that
114 // assume that pressing the return key results in a key
115 // event, for example the QLineEdit::returnPressed logic.
116 // To ensure that clients will still see the Qt::Key_Return
117 // key event, we send it as a normal key event.
118
119 // But, we can not fall back to handleKeyEvent for this,
120 // as the original key event may have text that reflects
121 // the combination of the inserted text and the newline,
122 // e.g. "~\r". We have already inserted the composition,
123 // so we need to follow up with a single newline event.
124
126 m_currentlyInterpretedKeyEvent : NSApp.currentEvent);
127 newlineEvent.type = QEvent::KeyPress;
128
129 const bool isEnter = newlineEvent.modifiers & Qt::KeypadModifier;
130 newlineEvent.key = isEnter ? Qt::Key_Enter : Qt::Key_Return;
131 newlineEvent.text = isEnter ? QLatin1Char(kEnterCharCode)
132 : QLatin1Char(kReturnCharCode);
133 newlineEvent.nativeVirtualKey = isEnter ? quint32(kVK_ANSI_KeypadEnter)
134 : quint32(kVK_Return);
135
136 qCDebug(lcQpaKeys) << "Inserting newline via" << newlineEvent;
137 newlineEvent.sendWindowSystemEvent(m_platformWindow->window());
138}
139
140// ------------- Text composition -------------
141
142/*
143 Updates the composed text, potentially replacing existing text.
144
145 The NSTextInputClient protocol refers to composed text as "marked",
146 since it is "marked differently from the selection, using temporary
147 attributes that affect only display, not layout or storage.""
148
149 The concept maps to the preeditString of our QInputMethodEvent.
150
151 \a selectedRange refers to the part of the marked text that
152 is considered selected, for example when composing text with
153 multiple clause segments (Hiragana - Kana e.g.).
154
155 \a replacementRange refers to the existing text to replace.
156 Under normal circumstances this is {NSNotFound, 0}, and the
157 implementation should replace either the existing marked text,
158 the current selection, or just insert the text at the current
159 cursor location. But when initiating composition of existing
160 committed text (Hiragana - Kana e.g.), the range will be valid.
161*/
162- (void)setMarkedText:(id)text selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange
163{
164 qCDebug(lcQpaKeys).nospace() << "Marking \"" << text << "\""
165 << " with selected range " << selectedRange
166 << ", replacing range " << replacementRange;
167
168 const bool isAttributedString = [text isKindOfClass:NSAttributedString.class];
169 QString preeditString = QString::fromNSString(isAttributedString ? [text string] : text);
170
171 QList<QInputMethodEvent::Attribute> preeditAttributes;
172
173 // The QInputMethodEvent::Cursor specifies that the length
174 // determines whether the cursor is visible or not, but uses
175 // logic opposite of that of native AppKit application, where
176 // the cursor is visible if there's no selection, and hidden
177 // if there's a selection. Instead of passing on the length
178 // directly we need to inverse the logic.
179 const bool showCursor = !selectedRange.length;
180 preeditAttributes << QInputMethodEvent::Attribute(
181 QInputMethodEvent::Cursor, selectedRange.location, showCursor);
182
183 // QInputMethodEvent::Selection unfortunately doesn't apply to the
184 // preedit text, and QInputMethodEvent::Cursor which does, doesn't
185 // support setting a selection. Until we've introduced attributes
186 // that allow us to propagate the preedit selection semantically
187 // we resort to styling the selection via the TextFormat attribute,
188 // so that the preedit selection is visible to the user.
189 QTextCharFormat selectionFormat;
190 auto *platformTheme = QGuiApplicationPrivate::platformTheme();
191 auto *systemPalette = platformTheme->palette();
192 selectionFormat.setBackground(systemPalette->color(QPalette::Highlight));
193 preeditAttributes << QInputMethodEvent::Attribute(
195 selectedRange.location, selectedRange.length,
196 selectionFormat);
197
198 int index = 0;
199 int composingLength = preeditString.length();
200 while (index < composingLength) {
201 NSRange range = NSMakeRange(index, composingLength - index);
202
203 static NSDictionary *defaultMarkedTextAttributes = []{
204 NSTextView *textView = [[NSTextView new] autorelease];
205 return [textView.markedTextAttributes retain];
206 }();
207
208 NSDictionary *attributes = isAttributedString
209 ? [text attributesAtIndex:index longestEffectiveRange:&range inRange:range]
210 : defaultMarkedTextAttributes;
211
212 qCDebug(lcQpaKeys) << "Decorating range" << range << "based on" << attributes;
214
215 if (NSNumber *underlineStyle = attributes[NSUnderlineStyleAttributeName]) {
217 NSUnderlineStyle style = underlineStyle.integerValue;
218 if (style & NSUnderlineStylePatternDot)
219 format.setUnderlineStyle(QTextCharFormat::DotLine);
220 else if (style & NSUnderlineStylePatternDash)
221 format.setUnderlineStyle(QTextCharFormat::DashUnderline);
222 else if (style & NSUnderlineStylePatternDashDot)
223 format.setUnderlineStyle(QTextCharFormat::DashDotLine);
224 if (style & NSUnderlineStylePatternDashDotDot)
225 format.setUnderlineStyle(QTextCharFormat::DashDotDotLine);
226 else
227 format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
228
229 // Unfortunately QTextCharFormat::UnderlineStyle does not distinguish
230 // between NSUnderlineStyle{Single,Thick,Double}, which is used by CJK
231 // input methods to highlight the selected clause segments.
232 }
233 if (NSColor *underlineColor = attributes[NSUnderlineColorAttributeName])
234 format.setUnderlineColor(qt_mac_toQColor(underlineColor));
235 if (NSColor *foregroundColor = attributes[NSForegroundColorAttributeName])
236 format.setForeground(qt_mac_toQColor(foregroundColor));
237 if (NSColor *backgroundColor = attributes[NSBackgroundColorAttributeName])
238 format.setBackground(qt_mac_toQColor(backgroundColor));
239
240 if (format != QTextCharFormat()) {
241 preeditAttributes << QInputMethodEvent::Attribute(
243 }
244
245 index = range.location + range.length;
246 }
247
248 // Ensure we have a valid replacement range
249 replacementRange = [self sanitizeReplacementRange:replacementRange];
250
251 // Qt's QInputMethodEvent has different semantics for the replacement
252 // range than AppKit does, so we need to sanitize the range first.
253 auto [replaceFrom, replaceLength] = [self inputMethodRangeForRange:replacementRange];
254
255 // Update the composition, now that we've computed the replacement range
256 m_composingText = preeditString;
257
258 if (QObject *focusObject = self.focusObject) {
261 QInputMethodEvent event(preeditString, preeditAttributes);
262 if (replaceLength > 0) {
263 // The input method may extend the preedit into already
264 // committed text. If so, we need to replace existing text
265 // by committing an empty string.
266 qCDebug(lcQpaKeys) << "Replacing from" << replaceFrom << "with length"
267 << replaceLength << "based on replacement range" << replacementRange;
268 event.setCommitString(QString(), replaceFrom, replaceLength);
269 }
271 }
272 }
273}
274
275- (NSArray<NSString *> *)validAttributesForMarkedText
276{
277 return @[
278 NSUnderlineColorAttributeName,
279 NSUnderlineStyleAttributeName,
280 NSForegroundColorAttributeName,
281 NSBackgroundColorAttributeName
282 ];
283}
284
285- (BOOL)hasMarkedText
286{
287 return !m_composingText.isEmpty();
288}
289
290/*
291 Returns the range of marked text or {cursorPosition, 0} if there's none.
292
293 This maps to the location and length of the current preedit (composited) string.
294
295 The returned range measures from the start of the receiver’s text storage,
296 that is, from 0 to the document length.
297*/
298- (NSRange)markedRange
299{
300 if (auto queryResult = queryInputMethod(self.focusObject, Qt::ImAbsolutePosition)) {
301 int absoluteCursorPosition = queryResult.value(Qt::ImAbsolutePosition).toInt();
302
303 // The cursor position as reflected by Qt::ImAbsolutePosition is not
304 // affected by the offset of the cursor in the preedit area. That means
305 // that when composing text, the cursor position stays the same, at the
306 // preedit insertion point, regardless of where the cursor is positioned within
307 // the preedit string by the QInputMethodEvent::Cursor attribute. This means
308 // we can use the cursor position to determine the range of the marked text.
309
310 // The NSTextInputClient documentation says {NSNotFound, 0} should be returned if there
311 // is no marked text, but in practice NSTextView seems to report {cursorPosition, 0},
312 // so we do the same.
313 return NSMakeRange(absoluteCursorPosition, m_composingText.length());
314 } else {
315 return {NSNotFound, 0};
316 }
317}
318
319/*
320 Confirms the marked (composed) text.
321
322 The marked text is accepted as if it had been inserted normally,
323 and the preedit string is cleared.
324
325 If there is no marked text this method has no effect.
326*/
327- (void)unmarkText
328{
329 // FIXME: Match cancelComposingText in early exit and focus object handling
330
331 qCDebug(lcQpaKeys) << "Unmarking" << m_composingText
332 << "for focus object" << m_composingFocusObject;
333
334 if (!m_composingText.isEmpty()) {
335 QObject *focusObject = self.focusObject;
340 }
341 }
342
344 m_composingFocusObject = nullptr;
345}
346
347/*
348 Cancels composition.
349
350 The marked text is discarded, and the preedit string is cleared.
351
352 If there is no marked text this method has no effect.
353*/
354- (void)cancelComposingText
355{
357 return;
358
359 qCDebug(lcQpaKeys) << "Canceling composition" << m_composingText
360 << "for focus object" << m_composingFocusObject;
361
365 }
366
368 m_composingFocusObject = nullptr;
369}
370
371// ------------- Key binding command handling -------------
372
373- (void)doCommandBySelector:(SEL)selector
374{
375 // Note: if the selector cannot be invoked, then doCommandBySelector:
376 // should not pass this message up the responder chain (nor should it
377 // call super, as the NSResponder base class would in that case pass
378 // the message up the responder chain, which we don't want). We will
379 // pass the originating key event up the responder chain if applicable.
380
381 qCDebug(lcQpaKeys) << "Trying to perform command" << selector;
382 if (![self tryToPerform:selector with:self]) {
383 m_sendKeyEvent = true;
384
385 if (![NSStringFromSelector(selector) hasPrefix:@"insert"]) {
386 // The text input system determined that the key event was not
387 // meant for text insertion, and instead asked us to treat it
388 // as a (possibly noop) command. This typically happens for key
389 // events with either ⌘ or ⌃, function keys such as F1-F35,
390 // arrow keys, etc. We reflect that when sending the key event
391 // later on, by removing the text from the event, so that the
392 // event does not result in text insertion on the client side.
394 }
395 }
396}
397
398// ------------- Various text properties -------------
399
400/*
401 Returns the range of selected text, or {cursorPosition, 0} if there's none.
402
403 The returned range measures from the start of the receiver’s text storage,
404 that is, from 0 to the document length.
405*/
406- (NSRange)selectedRange
407{
408 if (auto queryResult = queryInputMethod(self.focusObject,
410
411 // Unfortunately the Qt::InputMethodQuery values are all relative
412 // to the start of the current editing block (paragraph), but we
413 // need them in absolute values relative to the entire text.
414 // Luckily we have one property, Qt::ImAbsolutePosition, that
415 // we can use to compute the offset.
416 int cursorPosition = queryResult.value(Qt::ImCursorPosition).toInt();
417 int absoluteCursorPosition = queryResult.value(Qt::ImAbsolutePosition).toInt();
418 int absoluteOffset = absoluteCursorPosition - cursorPosition;
419
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;
424
425 // Note: The cursor position as reflected by these properties are not
426 // affected by the offset of the cursor in the preedit area. That means
427 // that when composing text, the cursor position stays the same, at the
428 // preedit insertion point, regardless of where the cursor is positioned within
429 // the preedit string by the QInputMethodEvent::Cursor attribute.
430
431 // The NSTextInputClient documentation says {NSNotFound, 0} should be returned if there is no
432 // selection, but in practice NSTextView seems to report {cursorPosition, 0}, so we do the same.
433 return NSMakeRange(selectionStart, selectionLength);
434 } else {
435 return {NSNotFound, 0};
436 }
437}
438
439/*
440 Returns an attributed string derived from the given range
441 in the underlying focus object's text storage.
442
443 Input methods may call this with a proposed range that is
444 out of bounds. For example, the InkWell text input service
445 may ask for the contents of the text input client that extends
446 beyond the document's range. To remedy this we always compute
447 the intersection between the proposed range and the available
448 text.
449
450 If the intersection is completely outside of the available text
451 this method returns nil.
452*/
453- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)range actualRange:(NSRangePointer)actualRange
454{
455 if (auto queryResult = queryInputMethod(self.focusObject,
457 const int absoluteCursorPosition = queryResult.value(Qt::ImAbsolutePosition).toInt();
458 const QString textBeforeCursor = queryResult.value(Qt::ImTextBeforeCursor).toString();
459 const QString textAfterCursor = queryResult.value(Qt::ImTextAfterCursor).toString();
460
461 // The documentation doesn't say whether the marked text should be included
462 // in the available text, but observing NSTextView shows that this is the
463 // case, so we follow suit.
464 const QString availableText = textBeforeCursor + m_composingText + textAfterCursor;
465 const NSRange availableRange = NSMakeRange(absoluteCursorPosition - textBeforeCursor.length(),
466 availableText.length());
467
468 const NSRange intersectedRange = NSIntersectionRange(range, availableRange);
469 if (actualRange)
470 *actualRange = intersectedRange;
471
472 if (!intersectedRange.length)
473 return nil;
474
475 NSString *substring = QStringView(availableText).mid(
476 intersectedRange.location - availableRange.location,
477 intersectedRange.length).toNSString();
478
479 return [[[NSAttributedString alloc] initWithString:substring] autorelease];
480
481 } else {
482 return nil;
483 }
484}
485
486- (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(NSRangePointer)actualRange
487{
489 Q_UNUSED(actualRange);
490
491 QWindow *window = m_platformWindow ? m_platformWindow->window() : nullptr;
492 if (window && queryInputMethod(window->focusObject())) {
493 QRect cursorRect = qApp->inputMethod()->cursorRectangle().toRect();
494 cursorRect.moveBottomLeft(window->mapToGlobal(cursorRect.bottomLeft()));
495 return QCocoaScreen::mapToNative(cursorRect);
496 } else {
497 return NSZeroRect;
498 }
499}
500
501- (NSUInteger)characterIndexForPoint:(NSPoint)point
502{
503 // We don't support cursor movements using mouse while composing.
504 Q_UNUSED(point);
505 return NSNotFound;
506}
507
508/*
509 Returns the window level of the text input.
510
511 This allows the input method to place its input panel
512 above the text input.
513*/
514- (NSInteger)windowLevel
515{
516 // The default level assumed by input methods is NSFloatingWindowLevel,
517 // but our NSWindow level could be higher than that for many reasons,
518 // including being set via QWindow::setFlags() or directly on the
519 // NSWindow, or because we're embedded into a native view hierarchy.
520 // Return the actual window level to account for this.
521 auto level = m_platformWindow ? m_platformWindow->nativeWindow().level
522 : NSNormalWindowLevel;
523
524 // The logic above only covers our own window though. In some cases,
525 // such as when a completer is active, the text input has a lower
526 // window level than another window that's also visible, and we don't
527 // want the input panel to be sandwiched between these two windows.
528 // Account for this by explicitly using NSPopUpMenuWindowLevel as
529 // the minimum window level, which corresponds to the highest level
530 // one can get via QWindow::setFlags(), except for Qt::ToolTip.
531 return qMax(level, NSPopUpMenuWindowLevel);
532}
533
534// ------------- Helper functions -------------
535
536/*
537 Sanitizes the replacement range, ensuring it's valid.
538
539 If \a range is not valid the range of the current
540 marked text will be used.
541
542 If there's no marked text the range of the current
543 selection will be used.
544
545 If there's no selection the range will be {cursorPosition, 0}.
546*/
547- (NSRange)sanitizeReplacementRange:(NSRange)range
548{
549 if (range.location != NSNotFound)
550 return range; // Use as is
551
552 // If the replacement range is not specified we are expected to compute
553 // the range ourselves, based on the current state of the input context.
554
555 const auto markedRange = [self markedRange];
556 if (markedRange.location != NSNotFound)
557 return markedRange;
558 else
559 return [self selectedRange];
560}
561
562/*
563 Computes the QInputMethodEvent commit string range,
564 based on the NSTextInputClient replacement range.
565
566 The two APIs have different semantics.
567*/
568- (std::pair<long long, long long>)inputMethodRangeForRange:(NSRange)range
569{
570 long long replaceFrom = range.location;
571 long long replaceLength = range.length;
572
573 const auto markedRange = [self markedRange];
574 const auto selectedRange = [self selectedRange];
575
576 // The QInputMethodEvent replacement start is relative to the start
577 // of the marked text (the location of the preedit string).
578 if (markedRange.location != NSNotFound)
579 replaceFrom -= markedRange.location;
580 else
581 replaceFrom = 0;
582
583 // The replacement length of QInputMethodEvent already includes
584 // the selection, as the documentation says that "If the widget
585 // has selected text, the selected text should get removed."
586 replaceLength -= selectedRange.length;
587
588 // The replacement length of QInputMethodEvent already includes
589 // the preedit string, as the documentation says that "When doing
590 // replacement, the area of the preedit string is ignored".
591 replaceLength -= markedRange.length;
592
593 // What we're left with is any _additional_ replacement.
594 // Make sure it's valid before passing it on.
595 replaceLength = qMax(0ll, replaceLength);
596
597 return {replaceFrom, replaceLength};
598}
599
600@end
QObject * focusObject
Definition qnsview.mm:80
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.
@ KeyPress
Definition qcoreevent.h:64
static QPlatformTheme * platformTheme()
The QInputMethodEvent class provides parameters for input method events.
Definition qevent.h:625
void setCommitString(const QString &commitString, int replaceFrom=0, int replaceLength=0)
Sets the commit string to commitString.
Definition qevent.cpp:2272
\inmodule QtCore
Definition qobject.h:103
@ Highlight
Definition qpalette.h:53
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr QPoint bottomLeft() const noexcept
Returns the position of the rectangle's bottom-left corner.
Definition qrect.h:230
constexpr void moveBottomLeft(const QPoint &p) noexcept
Moves the rectangle, leaving the bottom-left corner at the given position.
Definition qrect.h:322
\inmodule QtCore
Definition qstringview.h:78
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
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1252
qsizetype length() const noexcept
Returns the number of characters in this string.
Definition qstring.h:191
void setFontUnderline(bool underline)
If underline is true, sets the text format's font to be underlined; otherwise it is displayed non-und...
\inmodule QtGui
Definition qwindow.h:63
QString text
Definition qcompare.h:63
@ ImTextBeforeCursor
@ ImCursorPosition
@ ImAbsolutePosition
@ ImAnchorPosition
@ ImTextAfterCursor
@ Key_Return
Definition qnamespace.h:667
@ Key_Enter
Definition qnamespace.h:668
@ KeypadModifier
QString self
Definition language.cpp:58
InputMethodQueryResult queryInputMethod(QObject *object, Qt::InputMethodQueries queries)
long NSInteger
unsigned long NSUInteger
#define qApp
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)
Definition qminmax.h:42
bool m_sendKeyEvent
Definition qnsview.mm:113
NSEvent * m_currentlyInterpretedKeyEvent
Definition qnsview.mm:115
QPointer< QObject > m_composingFocusObject
Definition qnsview.mm:120
bool m_sendKeyEventWithoutText
Definition qnsview.mm:114
QString m_composingText
Definition qnsview.mm:119
GLint location
GLenum GLuint GLint level
GLuint index
[2]
GLenum GLuint GLenum GLsizei length
GLsizei range
GLint GLsizei GLsizei GLenum format
struct _cl_event * event
#define Q_UNUSED(x)
unsigned int quint32
Definition qtypes.h:50
QFileSelector selector
[1]
aWidget window() -> setWindowTitle("New Window Title")
[2]
EventType type
Definition qwasmevent.h:136
\inmodule QtCore \reentrant
Definition qchar.h:18