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