Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qinputmethod.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 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// Qt-Security score:significant reason:default
4
5#include <qinputmethod.h>
6#include <private/qinputmethod_p.h>
7#include <qguiapplication.h>
8#include <qpa/qplatforminputcontext_p.h>
9
10#include <QDebug>
11
13
14/*!
15 \internal
16*/
17QInputMethod::QInputMethod()
18 : QObject(*new QInputMethodPrivate)
19{
20}
21
22/*!
23 \internal
24*/
25QInputMethod::~QInputMethod()
26{
27}
28
29/*!
30 \class QInputMethod
31 \brief The QInputMethod class provides access to the active text input method.
32 \inmodule QtGui
33
34 QInputMethod is used by the text editors for integrating to the platform text input
35 methods and more commonly by application views for querying various text input method-related
36 information like virtual keyboard visibility and keyboard dimensions.
37
38 Qt Quick also provides access to QInputMethod in QML through \l{QmlGlobalQtObject}{Qt global object}
39 as \c Qt.inputMethod property.
40
41 Text editors receive input from the input method through QInputMethodEvent,
42 and the input method queries their state through QInputMethodQueryEvent.
43 For information about supporting input methods in a custom text editor, see
44 QInputMethodEvent.
45*/
46
47/*!
48 Returns the transformation from input item coordinates to the window coordinates.
49*/
50QTransform QInputMethod::inputItemTransform() const
51{
52 Q_D(const QInputMethod);
53 return d->inputItemTransform;
54}
55
56/*!
57 Sets the transformation from input item coordinates to window coordinates to be \a transform.
58 Item transform needs to be updated by the focused window like QQuickCanvas whenever
59 item is moved inside the scene.
60*/
61void QInputMethod::setInputItemTransform(const QTransform &transform)
62{
63 Q_D(QInputMethod);
64 if (d->inputItemTransform == transform)
65 return;
66
67 d->inputItemTransform = transform;
68 emit cursorRectangleChanged();
69 emit anchorRectangleChanged();
70}
71
72
73/*!
74 \since 5.1
75
76 Returns the input item's geometry in input item coordinates.
77
78 \sa setInputItemRectangle()
79*/
80QRectF QInputMethod::inputItemRectangle() const
81{
82 Q_D(const QInputMethod);
83 return d->inputRectangle;
84}
85
86/*!
87 \since 5.1
88
89 Sets the input item's geometry to be \a rect, in input item coordinates.
90 This needs to be updated by the focused window like QQuickCanvas whenever
91 item is moved inside the scene, or focus is changed.
92*/
93void QInputMethod::setInputItemRectangle(const QRectF &rect)
94{
95 Q_D(QInputMethod);
96 d->inputRectangle = rect;
97}
98
99static QRectF inputMethodQueryRectangle_helper(Qt::InputMethodQuery imquery, const QTransform &xform)
100{
101 QRectF r;
102 if (QObject *focusObject = qGuiApp->focusObject()) {
103 QInputMethodQueryEvent query(imquery);
104 QGuiApplication::sendEvent(focusObject, &query);
105 r = query.value(imquery).toRectF();
106 if (r.isValid())
107 r = xform.mapRect(r);
108 }
109 return r;
110}
111
112/*!
113 \property QInputMethod::cursorRectangle
114 \brief Input item's cursor rectangle in window coordinates.
115
116 Cursor rectangle is often used by various text editing controls
117 like text prediction popups for following the text being typed.
118*/
119QRectF QInputMethod::cursorRectangle() const
120{
121 Q_D(const QInputMethod);
122 return inputMethodQueryRectangle_helper(Qt::ImCursorRectangle, d->inputItemTransform);
123}
124
125/*!
126 \property QInputMethod::anchorRectangle
127 \brief Input item's anchor rectangle in window coordinates.
128
129 Anchor rectangle is often used by various text editing controls
130 like text prediction popups for following the text selection.
131*/
132QRectF QInputMethod::anchorRectangle() const
133{
134 Q_D(const QInputMethod);
135 return inputMethodQueryRectangle_helper(Qt::ImAnchorRectangle, d->inputItemTransform);
136}
137
138/*!
139 \property QInputMethod::keyboardRectangle
140 \brief Virtual keyboard's geometry in window coordinates.
141
142 This might be an empty rectangle if it is not possible to know the geometry
143 of the keyboard. This is the case for a floating keyboard on android.
144*/
145QRectF QInputMethod::keyboardRectangle() const
146{
147 Q_D(const QInputMethod);
148 QPlatformInputContext *ic = d->platformInputContext();
149 if (ic)
150 return ic->keyboardRect();
151 return QRectF();
152}
153
154/*!
155 \property QInputMethod::inputItemClipRectangle
156 \brief Input item's clipped rectangle in window coordinates.
157
158 The clipped input rectangle is often used by various input methods to determine
159 how much screen real estate is available for the input method (e.g. Virtual Keyboard).
160*/
161QRectF QInputMethod::inputItemClipRectangle() const
162{
163 Q_D(const QInputMethod);
164 return inputMethodQueryRectangle_helper(Qt::ImInputItemClipRectangle, d->inputItemTransform);
165}
166/*!
167 Requests virtual keyboard to open. If the platform
168 doesn't provide virtual keyboard the visibility
169 remains false.
170
171 Normally applications should not need to call this
172 function, keyboard should automatically open when
173 the text editor gains focus.
174*/
175void QInputMethod::show()
176{
177 Q_D(QInputMethod);
178 QPlatformInputContext *ic = d->platformInputContext();
179 if (ic)
180 ic->showInputPanel();
181}
182
183/*!
184 Requests virtual keyboard to close.
185
186 Normally applications should not need to call this function,
187 keyboard should automatically close when the text editor loses
188 focus, for example when the parent view is closed.
189*/
190void QInputMethod::hide()
191{
192 Q_D(QInputMethod);
193 QPlatformInputContext *ic = d->platformInputContext();
194 if (ic)
195 ic->hideInputPanel();
196}
197
198/*!
199 \property QInputMethod::visible
200 \brief Virtual keyboard's visibility on the screen
201
202 Input method visibility remains false for devices
203 with no virtual keyboards.
204
205 \sa show(), hide()
206*/
207bool QInputMethod::isVisible() const
208{
209 Q_D(const QInputMethod);
210 QPlatformInputContext *ic = d->platformInputContext();
211 if (ic)
212 return ic->isInputPanelVisible();
213 return false;
214}
215
216/*!
217 Controls the keyboard visibility. Equivalent
218 to calling show() (if \a visible is \c true)
219 or hide() (if \a visible is \c false).
220
221 \sa show(), hide()
222*/
223void QInputMethod::setVisible(bool visible)
224{
225 visible ? show() : hide();
226}
227
228/*!
229 \property QInputMethod::animating
230 \brief True when the virtual keyboard is being opened or closed.
231
232 Animating is false when keyboard is fully open or closed.
233 When \c animating is \c true and \c visibility is \c true keyboard
234 is being opened. When \c animating is \c true and \c visibility is
235 false keyboard is being closed.
236*/
237
238bool QInputMethod::isAnimating() const
239{
240 Q_D(const QInputMethod);
241 QPlatformInputContext *ic = d->platformInputContext();
242 if (ic)
243 return ic->isAnimating();
244 return false;
245}
246
247/*!
248 \property QInputMethod::locale
249 \brief Current input locale.
250*/
251QLocale QInputMethod::locale() const
252{
253 Q_D(const QInputMethod);
254 QPlatformInputContext *ic = d->platformInputContext();
255 if (ic)
256 return ic->locale();
257 return QLocale::c();
258}
259
260/*!
261 \property QInputMethod::inputDirection
262 \brief Current input direction.
263*/
264Qt::LayoutDirection QInputMethod::inputDirection() const
265{
266 Q_D(const QInputMethod);
267 QPlatformInputContext *ic = d->platformInputContext();
268 if (ic)
269 return ic->inputDirection();
270 return Qt::LeftToRight;
271}
272
273/*!
274 Called by the input item to inform the platform input methods when there has been
275 state changes in editor's input method query attributes. When calling the function
276 \a queries parameter has to be used to tell what has changes, which input method
277 can use to make queries for attributes it's interested with QInputMethodQueryEvent.
278
279 In particular calling update whenever the cursor position changes is important as
280 that often causes other query attributes like surrounding text and text selection
281 to change as well. The attributes that often change together with cursor position
282 have been grouped in Qt::ImQueryInput value for convenience.
283*/
284void QInputMethod::update(Qt::InputMethodQueries queries)
285{
286 Q_D(QInputMethod);
287
288 if (queries & Qt::ImEnabled) {
289 QObject *focus = qApp->focusObject();
290 bool enabled = d->objectAcceptsInputMethod(focus);
291 QPlatformInputContextPrivate::setInputMethodAccepted(enabled);
292 }
293
294 QPlatformInputContext *ic = d->platformInputContext();
295 if (ic)
296 ic->update(queries);
297
298 if (queries & Qt::ImCursorRectangle)
299 emit cursorRectangleChanged();
300
301 if (queries & (Qt::ImAnchorRectangle))
302 emit anchorRectangleChanged();
303
304 if (queries & (Qt::ImInputItemClipRectangle))
305 emit inputItemClipRectangleChanged();
306}
307
308/*!
309 Resets the input method state. For example, a text editor normally calls
310 this method before inserting a text to make widget ready to accept a text.
311
312 Input method resets automatically when the focused editor changes.
313*/
314void QInputMethod::reset()
315{
316 Q_D(QInputMethod);
317 QPlatformInputContext *ic = d->platformInputContext();
318 if (ic)
319 ic->reset();
320}
321
322/*!
323 Commits the word user is currently composing to the editor. The function is
324 mostly needed by the input methods with text prediction features and by the
325 methods where the script used for typing characters is different from the
326 script that actually gets appended to the editor. Any kind of action that
327 interrupts the text composing needs to flush the composing state by calling the
328 commit() function, for example when the cursor is moved elsewhere.
329*/
330void QInputMethod::commit()
331{
332 Q_D(QInputMethod);
333 QPlatformInputContext *ic = d->platformInputContext();
334 if (ic)
335 ic->commit();
336}
337
338/*!
339 \enum QInputMethod::Action
340
341 Indicates the kind of action performed by the user.
342
343 \value Click A normal click/tap
344 \value ContextMenu A context menu click/tap (e.g. right-button or tap-and-hold)
345
346 \sa invokeAction()
347*/
348
349/*!
350 Called by the input item when the word currently being composed is tapped by
351 the user, as indicated by the action \a a and the given \a cursorPosition.
352 Input methods often use this information to offer more word suggestions to the user.
353*/
354void QInputMethod::invokeAction(Action a, int cursorPosition)
355{
356 Q_D(QInputMethod);
357 QPlatformInputContext *ic = d->platformInputContext();
358 if (ic)
359 ic->invokeAction(a, cursorPosition);
360}
361
362static inline bool platformSupportsHiddenText()
363{
364 const QPlatformInputContext *inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext();
365 return inputContext && inputContext->hasCapability(QPlatformInputContext::HiddenTextCapability);
366}
367
368bool QInputMethodPrivate::objectAcceptsInputMethod(QObject *object)
369{
370 bool enabled = false;
371 if (object) {
372 // If the platform does not support hidden text, query the hints
373 // in addition and disable in case of ImhHiddenText.
374 static const bool supportsHiddenText = platformSupportsHiddenText();
375 QInputMethodQueryEvent query(supportsHiddenText
376 ? Qt::InputMethodQueries(Qt::ImEnabled)
377 : Qt::InputMethodQueries(Qt::ImEnabled | Qt::ImHints));
378 QGuiApplication::sendEvent(object, &query);
379 enabled = query.value(Qt::ImEnabled).toBool();
380 if (enabled && !supportsHiddenText
381 && Qt::InputMethodHints(query.value(Qt::ImHints).toInt()).testFlag(Qt::ImhHiddenText)) {
382 enabled = false;
383 }
384 }
385 return enabled;
386}
387
388/*!
389 Sends \a query to the current focus object with parameters \a argument and
390 returns the result.
391
392 If the focus object has an invokable method with the signature
393 \c{inputMethodQuery(Qt::InputMethodQuery, QVariant)}, that method is called
394 with \a query and \a argument. If the focus object has no such method, or
395 the method returns an invalid QVariant, a QInputMethodQueryEvent for \a query
396 is sent to the focus object instead, and \a argument is ignored.
397 */
398QVariant QInputMethod::queryFocusObject(Qt::InputMethodQuery query, const QVariant &argument)
399{
400 QVariant retval;
401 QObject *focusObject = qGuiApp->focusObject();
402 if (!focusObject)
403 return retval;
404
405 static const char *signature = "inputMethodQuery(Qt::InputMethodQuery,QVariant)";
406 const bool newMethodSupported = focusObject->metaObject()->indexOfMethod(signature) != -1;
407 if (newMethodSupported) {
408 const bool ok = QMetaObject::invokeMethod(focusObject, "inputMethodQuery",
409 Qt::DirectConnection,
410 Q_RETURN_ARG(QVariant, retval),
411 Q_ARG(Qt::InputMethodQuery, query),
412 Q_ARG(QVariant, argument));
413 Q_ASSERT(ok);
414 if (retval.isValid())
415 return retval;
416
417 // If the new API didn't have an answer to the query, we fall
418 // back to use the old event-based API.
419 }
420
421 QInputMethodQueryEvent queryEvent(query);
422 QCoreApplication::sendEvent(focusObject, &queryEvent);
423 return queryEvent.value(query);
424}
425
426QT_END_NAMESPACE
427
428#include "moc_qinputmethod.cpp"
Combined button and popup list for selecting options.
#define qApp
#define qGuiApp
static bool platformSupportsHiddenText()
static QRectF inputMethodQueryRectangle_helper(Qt::InputMethodQuery imquery, const QTransform &xform)