Coverage Report

Created: 2025-11-16 07:45

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