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 test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
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 General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include <QtTest/QtTest>
30
31#include <private/qguiapplication_p.h>
32#include <private/qinputmethod_p.h>
33#include <qpa/qplatforminputcontext.h>
34#include "../../../shared/platforminputcontext.h"
35
36class InputItem : public QObject
37{
38 Q_OBJECT
39public:
40 InputItem() : cursorRectangle(1, 2, 3, 4), m_enabled(true) {}
41
42 bool event(QEvent *event)
43 {
44 if (event->type() == QEvent::InputMethodQuery) {
45 QInputMethodQueryEvent *query = static_cast<QInputMethodQueryEvent *>(event);
46 if (query->queries() & Qt::ImEnabled)
47 query->setValue(query: Qt::ImEnabled, value: m_enabled);
48 if (query->queries() & Qt::ImCursorRectangle)
49 query->setValue(query: Qt::ImCursorRectangle, value: cursorRectangle);
50 if (query->queries() & Qt::ImPreferredLanguage)
51 query->setValue(query: Qt::ImPreferredLanguage, value: QString("English"));
52 m_lastQueries = query->queries();
53 query->accept();
54 return true;
55 }
56 return false;
57 }
58
59 void setEnabled(bool enabled) {
60 if (enabled != m_enabled) {
61 m_enabled = enabled;
62 qApp->inputMethod()->update(queries: Qt::ImEnabled);
63 }
64 }
65
66 QRectF cursorRectangle;
67 Qt::InputMethodQueries m_lastQueries;
68 bool m_enabled;
69};
70
71
72class DummyWindow : public QWindow
73{
74public:
75 DummyWindow() : m_focusObject(0) {}
76
77 virtual QObject *focusObject() const
78 {
79 return m_focusObject;
80 }
81
82 void setFocusObject(QObject *object)
83 {
84 m_focusObject = object;
85 emit focusObjectChanged(object);
86 }
87
88 QObject *m_focusObject;
89};
90
91
92class tst_qinputmethod : public QObject
93{
94 Q_OBJECT
95public:
96 tst_qinputmethod() {}
97 virtual ~tst_qinputmethod() {}
98private slots:
99 void initTestCase();
100 void isVisible();
101 void animating();
102 void keyboarRectangle();
103 void inputItemTransform();
104 void cursorRectangle();
105 void invokeAction();
106 void reset();
107 void commit();
108 void update();
109 void query();
110 void inputDirection();
111 void inputMethodAccepted();
112
113private:
114 InputItem m_inputItem;
115 PlatformInputContext m_platformInputContext;
116};
117
118void tst_qinputmethod::initTestCase()
119{
120 QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
121 inputMethodPrivate->testContext = &m_platformInputContext;
122}
123
124void tst_qinputmethod::isVisible()
125{
126 QCOMPARE(qApp->inputMethod()->isVisible(), false);
127 qApp->inputMethod()->show();
128 QCOMPARE(qApp->inputMethod()->isVisible(), true);
129
130 qApp->inputMethod()->hide();
131 QCOMPARE(qApp->inputMethod()->isVisible(), false);
132
133 qApp->inputMethod()->setVisible(true);
134 QCOMPARE(qApp->inputMethod()->isVisible(), true);
135
136 qApp->inputMethod()->setVisible(false);
137 QCOMPARE(qApp->inputMethod()->isVisible(), false);
138}
139
140void tst_qinputmethod::animating()
141{
142 QCOMPARE(qApp->inputMethod()->isAnimating(), false);
143
144 m_platformInputContext.m_animating = true;
145 QCOMPARE(qApp->inputMethod()->isAnimating(), true);
146
147 m_platformInputContext.m_animating = false;
148 QCOMPARE(qApp->inputMethod()->isAnimating(), false);
149
150 QSignalSpy spy(qApp->inputMethod(), SIGNAL(animatingChanged()));
151 m_platformInputContext.emitAnimatingChanged();
152 QCOMPARE(spy.count(), 1);
153}
154
155void tst_qinputmethod::keyboarRectangle()
156{
157 QCOMPARE(qApp->inputMethod()->keyboardRectangle(), QRectF());
158
159 m_platformInputContext.m_keyboardRect = QRectF(10, 20, 30, 40);
160 QCOMPARE(qApp->inputMethod()->keyboardRectangle(), QRectF(10, 20, 30, 40));
161
162 QSignalSpy spy(qApp->inputMethod(), SIGNAL(keyboardRectangleChanged()));
163 m_platformInputContext.emitKeyboardRectChanged();
164 QCOMPARE(spy.count(), 1);
165}
166
167void tst_qinputmethod::inputItemTransform()
168{
169 QCOMPARE(qApp->inputMethod()->inputItemTransform(), QTransform());
170 QSignalSpy spy(qApp->inputMethod(), SIGNAL(cursorRectangleChanged()));
171
172 QTransform transform;
173 transform.translate(dx: 10, dy: 10);
174 transform.scale(sx: 2, sy: 2);
175 transform.shear(sh: 2, sv: 2);
176 qApp->inputMethod()->setInputItemTransform(transform);
177
178 QCOMPARE(qApp->inputMethod()->inputItemTransform(), transform);
179 QCOMPARE(spy.count(), 1);
180
181 // reset
182 qApp->inputMethod()->setInputItemTransform(QTransform());
183}
184
185void tst_qinputmethod::cursorRectangle()
186{
187 QCOMPARE(qApp->inputMethod()->cursorRectangle(), QRectF());
188
189 if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(cap: QPlatformIntegration::WindowActivation))
190 QSKIP("QWindow::requestActivate() is not supported.");
191
192 DummyWindow window;
193 window.show();
194 QVERIFY(QTest::qWaitForWindowExposed(&window));
195 window.requestActivate();
196 QTRY_COMPARE(qApp->focusWindow(), &window);
197 window.setFocusObject(&m_inputItem);
198
199 QTransform transform;
200 transform.translate(dx: 10, dy: 10);
201 transform.scale(sx: 2, sy: 2);
202 transform.shear(sh: 2, sv: 2);
203 qApp->inputMethod()->setInputItemTransform(transform);
204 QCOMPARE(qApp->inputMethod()->cursorRectangle(), transform.mapRect(QRectF(1, 2, 3, 4)));
205
206 m_inputItem.cursorRectangle = QRectF(1.5, 2, 1, 8);
207 QCOMPARE(qApp->inputMethod()->cursorRectangle(), transform.mapRect(QRectF(1.5, 2, 1, 8)));
208
209 // reset
210 m_inputItem.cursorRectangle = QRectF(1, 2, 3, 4);
211 qApp->inputMethod()->setInputItemTransform(QTransform());
212}
213
214void tst_qinputmethod::invokeAction()
215{
216 QCOMPARE(m_platformInputContext.m_action, QInputMethod::Click);
217 QCOMPARE(m_platformInputContext.m_cursorPosition, 0);
218
219 qApp->inputMethod()->invokeAction(a: QInputMethod::ContextMenu, cursorPosition: 5);
220 QCOMPARE(m_platformInputContext.m_action, QInputMethod::ContextMenu);
221 QCOMPARE(m_platformInputContext.m_cursorPosition, 5);
222}
223
224void tst_qinputmethod::reset()
225{
226 QCOMPARE(m_platformInputContext.m_resetCallCount, 0);
227
228 qApp->inputMethod()->reset();
229 QCOMPARE(m_platformInputContext.m_resetCallCount, 1);
230
231 qApp->inputMethod()->reset();
232 QCOMPARE(m_platformInputContext.m_resetCallCount, 2);
233}
234
235void tst_qinputmethod::commit()
236{
237 QCOMPARE(m_platformInputContext.m_commitCallCount, 0);
238
239 qApp->inputMethod()->commit();
240 QCOMPARE(m_platformInputContext.m_commitCallCount, 1);
241
242 qApp->inputMethod()->commit();
243 QCOMPARE(m_platformInputContext.m_commitCallCount, 2);
244}
245
246void tst_qinputmethod::update()
247{
248 QCOMPARE(m_platformInputContext.m_updateCallCount, 0);
249 QCOMPARE(int(m_platformInputContext.m_lastQueries), int(Qt::ImhNone));
250
251 qApp->inputMethod()->update(queries: Qt::ImQueryInput);
252 QCOMPARE(m_platformInputContext.m_updateCallCount, 1);
253 QCOMPARE(int(m_platformInputContext.m_lastQueries), int(Qt::ImQueryInput));
254
255 qApp->inputMethod()->update(queries: Qt::ImQueryAll);
256 QCOMPARE(m_platformInputContext.m_updateCallCount, 2);
257 QCOMPARE(int(m_platformInputContext.m_lastQueries), int(Qt::ImQueryAll));
258
259 QCOMPARE(qApp->inputMethod()->keyboardRectangle(), QRectF(10, 20, 30, 40));
260}
261
262void tst_qinputmethod::query()
263{
264 QInputMethodQueryEvent query(Qt::InputMethodQueries(Qt::ImPreferredLanguage | Qt::ImCursorRectangle));
265 QGuiApplication::sendEvent(receiver: &m_inputItem, event: &query);
266
267 QString language = query.value(query: Qt::ImPreferredLanguage).toString();
268 QCOMPARE(language, QString("English"));
269
270 QRect cursorRectangle = query.value(query: Qt::ImCursorRectangle).toRect();
271 QCOMPARE(cursorRectangle, QRect(1,2,3,4));
272}
273
274void tst_qinputmethod::inputDirection()
275{
276 QCOMPARE(m_platformInputContext.m_inputDirectionCallCount, 0);
277 qApp->inputMethod()->inputDirection();
278 QCOMPARE(m_platformInputContext.m_inputDirectionCallCount, 1);
279
280 QCOMPARE(m_platformInputContext.m_localeCallCount, 0);
281 qApp->inputMethod()->locale();
282 QCOMPARE(m_platformInputContext.m_localeCallCount, 1);
283}
284
285void tst_qinputmethod::inputMethodAccepted()
286{
287 if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(cap: QPlatformIntegration::WindowActivation))
288 QSKIP("QWindow::requestActivate() is not supported.");
289
290 if (!QGuiApplication::platformName().compare(other: QLatin1String("minimal"), cs: Qt::CaseInsensitive)
291 || !QGuiApplication::platformName().compare(other: QLatin1String("offscreen"), cs: Qt::CaseInsensitive)) {
292 QSKIP("minimal/offscreen: This fails. Figure out why.");
293 }
294
295 if (!QGuiApplication::platformName().compare(other: QLatin1String("xcb"), cs: Qt::CaseInsensitive))
296 QSKIP("XCB: depends on dedicated platform context.");
297
298 InputItem disabledItem;
299 disabledItem.setEnabled(false);
300
301 DummyWindow window;
302 window.show();
303 QVERIFY(QTest::qWaitForWindowExposed(&window));
304 window.requestActivate();
305 QTRY_COMPARE(qApp->focusWindow(), &window);
306 window.setFocusObject(&disabledItem);
307
308 QCOMPARE(m_platformInputContext.inputMethodAccepted(), false);
309
310 window.setFocusObject(&m_inputItem);
311 QCOMPARE(m_platformInputContext.inputMethodAccepted(), true);
312}
313
314QTEST_MAIN(tst_qinputmethod)
315#include "tst_qinputmethod.moc"
316

source code of qtbase/tests/auto/gui/kernel/qinputmethod/tst_qinputmethod.cpp