summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2021-08-17 14:56:15 +0200
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2021-08-19 19:10:58 +0200
commita5571ec8a0eee6a19d4533113f9ef2e74540cfe7 (patch)
treec24f088ed87fccf8e130b81fe71ce8887e014fea /src
parent60ca8ca5bc7dbe0c57bdc63282a277ac8c31b684 (diff)
macOS: Use helper method for querying input method parameters
Pick-to: 6.2 Change-Id: I379d4ca20101899db2dfbd8f0c5a22f423e40d6b Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.h9
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm22
-rw-r--r--src/plugins/platforms/cocoa/qnsview_complextext.mm144
-rw-r--r--src/plugins/platforms/cocoa/qnsview_keys.mm31
4 files changed, 101 insertions, 105 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h
index 713b19dad5..f97521fe02 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.h
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.h
@@ -361,6 +361,15 @@ QSendSuperHelper<Args...> qt_objcDynamicSuperHelper(id receiver, SEL selector, A
// -------------------------------------------------------------------------
+struct InputMethodQueryResult : public QHash<Qt::InputMethodQuery, QVariant>
+{
+ operator bool() { return !isEmpty(); }
+};
+
+InputMethodQueryResult queryInputMethod(QObject *object, Qt::InputMethodQueries queries = Qt::ImEnabled);
+
+// -------------------------------------------------------------------------
+
QDebug operator<<(QDebug, const NSRange &);
QDebug operator<<(QDebug, SEL);
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm
index 723cfcb952..102cf28452 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.mm
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm
@@ -511,6 +511,28 @@ void q_IOObjectRelease(io_object_t obj)
// -------------------------------------------------------------------------
+InputMethodQueryResult queryInputMethod(QObject *object, Qt::InputMethodQueries queries)
+{
+ if (object) {
+ QInputMethodQueryEvent queryEvent(queries | Qt::ImEnabled);
+ if (QCoreApplication::sendEvent(object, &queryEvent)) {
+ if (queryEvent.value(Qt::ImEnabled).toBool()) {
+ InputMethodQueryResult result;
+ static QMetaEnum queryEnum = QMetaEnum::fromType<Qt::InputMethodQuery>();
+ for (int i = 0; i < queryEnum.keyCount(); ++i) {
+ auto query = Qt::InputMethodQuery(queryEnum.value(i));
+ if (queries & query)
+ result.insert(query, queryEvent.value(query));
+ }
+ return result;
+ }
+ }
+ }
+ return {};
+}
+
+// -------------------------------------------------------------------------
+
QDebug operator<<(QDebug debug, const NSRange &range)
{
if (range.location == NSNotFound) {
diff --git a/src/plugins/platforms/cocoa/qnsview_complextext.mm b/src/plugins/platforms/cocoa/qnsview_complextext.mm
index fb19270017..1e5423ab0e 100644
--- a/src/plugins/platforms/cocoa/qnsview_complextext.mm
+++ b/src/plugins/platforms/cocoa/qnsview_complextext.mm
@@ -49,14 +49,9 @@
qCDebug(lcQpaKeys) << "Canceling composition" << m_composingText
<< "for focus object" << m_composingFocusObject;
- if (m_composingFocusObject) {
- QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
- if (QCoreApplication::sendEvent(m_composingFocusObject, &queryEvent)) {
- if (queryEvent.value(Qt::ImEnabled).toBool()) {
- QInputMethodEvent e;
- QCoreApplication::sendEvent(m_composingFocusObject, &e);
- }
- }
+ if (queryInputMethod(m_composingFocusObject)) {
+ QInputMethodEvent e;
+ QCoreApplication::sendEvent(m_composingFocusObject, &e);
}
m_composingText.clear();
@@ -71,17 +66,14 @@
<< "for focus object" << m_composingFocusObject;
if (!m_composingText.isEmpty()) {
- if (QObject *fo = m_platformWindow->window()->focusObject()) {
- QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
- if (QCoreApplication::sendEvent(fo, &queryEvent)) {
- if (queryEvent.value(Qt::ImEnabled).toBool()) {
- QInputMethodEvent e;
- e.setCommitString(m_composingText);
- QCoreApplication::sendEvent(fo, &e);
- }
- }
+ 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;
}
@@ -121,17 +113,14 @@
commitString = QString::fromCFString(reinterpret_cast<CFStringRef>(aString));
};
}
- if (QObject *fo = m_platformWindow->window()->focusObject()) {
- QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
- if (QCoreApplication::sendEvent(fo, &queryEvent)) {
- if (queryEvent.value(Qt::ImEnabled).toBool()) {
- QInputMethodEvent e;
- e.setCommitString(commitString);
- QCoreApplication::sendEvent(fo, &e);
- // prevent handleKeyEvent from sending a key event
- m_sendKeyEvent = false;
- }
- }
+
+ QObject *focusObject = m_platformWindow->window()->focusObject();
+ if (queryInputMethod(focusObject)) {
+ QInputMethodEvent e;
+ e.setCommitString(commitString);
+ QCoreApplication::sendEvent(focusObject, &e);
+ // prevent handleKeyEvent from sending a key event
+ m_sendKeyEvent = false;
}
m_composingText.clear();
@@ -192,16 +181,13 @@
m_composingText = preeditString;
- if (QObject *fo = m_platformWindow->window()->focusObject()) {
- m_composingFocusObject = fo;
- QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
- if (QCoreApplication::sendEvent(fo, &queryEvent)) {
- if (queryEvent.value(Qt::ImEnabled).toBool()) {
- QInputMethodEvent e(preeditString, attrs);
- QCoreApplication::sendEvent(fo, &e);
- // prevent handleKeyEvent from sending a key event
- m_sendKeyEvent = false;
- }
+ if (QObject *focusObject = m_platformWindow->window()->focusObject()) {
+ m_composingFocusObject = focusObject;
+ if (queryInputMethod(focusObject)) {
+ QInputMethodEvent e(preeditString, attrs);
+ QCoreApplication::sendEvent(focusObject, &e);
+ // prevent handleKeyEvent from sending a key event
+ m_sendKeyEvent = false;
}
}
}
@@ -214,22 +200,19 @@
- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
{
Q_UNUSED(actualRange);
- QObject *fo = m_platformWindow->window()->focusObject();
- if (!fo)
- return nil;
- QInputMethodQueryEvent queryEvent(Qt::ImEnabled | Qt::ImCurrentSelection);
- if (!QCoreApplication::sendEvent(fo, &queryEvent))
- return nil;
- if (!queryEvent.value(Qt::ImEnabled).toBool())
- return nil;
- QString selectedText = queryEvent.value(Qt::ImCurrentSelection).toString();
- if (selectedText.isEmpty())
- return nil;
+ QObject *focusObject = m_platformWindow->window()->focusObject();
+ if (auto queryResult = queryInputMethod(focusObject, Qt::ImCurrentSelection)) {
+ QString selectedText = queryResult.value(Qt::ImCurrentSelection).toString();
+ if (selectedText.isEmpty())
+ return nil;
- QCFString string(selectedText.mid(aRange.location, aRange.length));
- const NSString *tmpString = reinterpret_cast<const NSString *>((CFStringRef)string);
- return [[[NSAttributedString alloc] initWithString:const_cast<NSString *>(tmpString)] autorelease];
+ QCFString string(selectedText.mid(aRange.location, aRange.length));
+ const NSString *tmpString = reinterpret_cast<const NSString *>((CFStringRef)string);
+ return [[[NSAttributedString alloc] initWithString:const_cast<NSString *>(tmpString)] autorelease];
+ } else {
+ return nil;
+ }
}
- (NSRange)markedRange
@@ -247,24 +230,13 @@
- (NSRange)selectedRange
{
- NSRange selectedRange = {0, 0};
-
- QObject *fo = m_platformWindow->window()->focusObject();
- if (!fo)
- return selectedRange;
- QInputMethodQueryEvent queryEvent(Qt::ImEnabled | Qt::ImCurrentSelection);
- if (!QCoreApplication::sendEvent(fo, &queryEvent))
- return selectedRange;
- if (!queryEvent.value(Qt::ImEnabled).toBool())
- return selectedRange;
-
- QString selectedText = queryEvent.value(Qt::ImCurrentSelection).toString();
-
- if (!selectedText.isEmpty()) {
- selectedRange.location = 0;
- selectedRange.length = selectedText.length();
+ 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);
}
- return selectedRange;
}
- (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
@@ -272,20 +244,14 @@
Q_UNUSED(aRange);
Q_UNUSED(actualRange);
- QObject *fo = m_platformWindow->window()->focusObject();
- if (!fo)
- return NSZeroRect;
-
- QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
- if (!QCoreApplication::sendEvent(fo, &queryEvent))
- return NSZeroRect;
- if (!queryEvent.value(Qt::ImEnabled).toBool())
+ QWindow *window = m_platformWindow->window();
+ if (queryInputMethod(window->focusObject())) {
+ QRect cursorRect = qApp->inputMethod()->cursorRectangle().toRect();
+ cursorRect.moveBottomLeft(window->mapToGlobal(cursorRect.bottomLeft()));
+ return QCocoaScreen::mapToNative(cursorRect);
+ } else {
return NSZeroRect;
-
- // The returned rect is always based on the internal cursor.
- QRect mr = qApp->inputMethod()->cursorRectangle().toRect();
- mr.moveBottomLeft(m_platformWindow->window()->mapToGlobal(mr.bottomLeft()));
- return QCocoaScreen::mapToNative(mr);
+ }
}
- (NSUInteger)characterIndexForPoint:(NSPoint)aPoint
@@ -303,18 +269,10 @@
if (m_platformWindow->window() != QGuiApplication::focusWindow())
return nil;
- QObject *fo = m_platformWindow->window()->focusObject();
- if (!fo)
- return nil;
-
- QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
- if (!QCoreApplication::sendEvent(fo, &queryEvent))
- return nil;
- if (!queryEvent.value(Qt::ImEnabled).toBool())
+ if (queryInputMethod(m_platformWindow->window()->focusObject()))
+ return @[NSUnderlineColorAttributeName, NSUnderlineStyleAttributeName];
+ else
return nil;
-
- // Support only underline color/style.
- return @[NSUnderlineColorAttributeName, NSUnderlineStyleAttributeName];
}
- (void)textInputContextKeyboardSelectionDidChangeNotification:(NSNotification *)textInputContextKeyboardSelectionDidChangeNotification
diff --git a/src/plugins/platforms/cocoa/qnsview_keys.mm b/src/plugins/platforms/cocoa/qnsview_keys.mm
index 1975ac5f3a..3d339fe541 100644
--- a/src/plugins/platforms/cocoa/qnsview_keys.mm
+++ b/src/plugins/platforms/cocoa/qnsview_keys.mm
@@ -113,32 +113,39 @@
}
}
- QObject *fo = m_platformWindow->window()->focusObject();
- if (m_sendKeyEvent && fo) {
- QInputMethodQueryEvent queryEvent(Qt::ImEnabled | Qt::ImHints);
- if (QCoreApplication::sendEvent(fo, &queryEvent)) {
- bool imEnabled = queryEvent.value(Qt::ImEnabled).toBool();
- Qt::InputMethodHints hints = static_cast<Qt::InputMethodHints>(queryEvent.value(Qt::ImHints).toUInt());
- // make sure we send dead keys and the next key to the input method for composition
+ QObject *focusObject = m_platformWindow->window()->focusObject();
+ if (m_sendKeyEvent && focusObject) {
+ if (auto queryResult = queryInputMethod(focusObject, Qt::ImHints)) {
+ auto hints = static_cast<Qt::InputMethodHints>(queryResult.value(Qt::ImHints).toUInt());
+
+ // Make sure we send dead keys and the next key to the input method for composition
const bool ignoreHidden = (hints & Qt::ImhHiddenText) && !text.isEmpty() && !m_lastKeyDead;
- if (imEnabled && !(hints & Qt::ImhDigitsOnly || hints & Qt::ImhFormattedNumbersOnly || ignoreHidden)) {
- // pass the key event to the input method. note that m_sendKeyEvent may be set to false during this call
- qCDebug(lcQpaKeys) << "Interpreting key event for focus object" << fo;
+
+ if (!(hints & Qt::ImhDigitsOnly || hints & Qt::ImhFormattedNumbersOnly || ignoreHidden)) {
+ // Pass the key event to the input method. Note that m_sendKeyEvent may be set
+ // to false during this call
+ qCDebug(lcQpaKeys) << "Interpreting key event for focus object" << focusObject;
m_currentlyInterpretedKeyEvent = nsevent;
[self interpretKeyEvents:@[nsevent]];
+
// If the receiver opens an editor in response to a key press, then the focus will change, the input
// method will be reset, and the first key press will be gone. If the focus object changes, then we
// need to pass the key event to the input method once more.
- if (qApp->focusObject() != fo) {
+ if (qApp->focusObject() != focusObject) {
qCDebug(lcQpaKeys) << "Interpreting key event again for new focus object" << qApp->focusObject();
[self interpretKeyEvents:@[nsevent]];
}
+
m_currentlyInterpretedKeyEvent = 0;
- // if the last key we sent was dead, then pass the next key to the IM as well to complete composition
+
+ // If the last key we sent was dead, then pass the next
+ // key to the IM as well to complete composition.
m_lastKeyDead = text.isEmpty();
}
+
}
}
+
if (m_resendKeyEvent)
m_sendKeyEvent = true;
}