1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
43 #include <QtTest/QtTest>
44 #include <qapplication.h>
45 #include <qlineedit.h>
50 #include <qlineedit.h>
53 QT_FORWARD_DECLARE_CLASS(QWidget)
55 class FocusLineEdit : public QLineEdit
58 FocusLineEdit( QWidget* parent = 0, const char* name = 0 ) : QLineEdit(name, parent) {}
59 int focusInEventReason;
60 int focusOutEventReason;
61 bool focusInEventRecieved;
62 bool focusInEventGotFocus;
63 bool focusOutEventRecieved;
64 bool focusOutEventLostFocus;
66 virtual void keyPressEvent( QKeyEvent *e )
68 // qDebug( QString("keyPressEvent: %1").arg(e->key()) );
69 QLineEdit::keyPressEvent( e );
71 void focusInEvent( QFocusEvent* e )
73 QLineEdit::focusInEvent( e );
74 focusInEventReason = e->reason();
75 focusInEventGotFocus = e->gotFocus();
76 focusInEventRecieved = true;
78 void focusOutEvent( QFocusEvent* e )
80 QLineEdit::focusOutEvent( e );
81 focusOutEventReason = e->reason();
82 focusOutEventLostFocus = !e->gotFocus();
83 focusOutEventRecieved = true;
87 class tst_QFocusEvent : public QObject
93 virtual ~tst_QFocusEvent();
100 void cleanupTestCase();
104 void checkReason_Tab();
105 void checkReason_ShiftTab();
106 void checkReason_BackTab();
107 void checkReason_Popup();
108 void checkReason_focusWidget();
109 void checkReason_Shortcut();
110 void checkReason_ActiveWindow();
113 QWidget* testFocusWidget;
114 FocusLineEdit* childFocusWidgetOne;
115 FocusLineEdit* childFocusWidgetTwo;
118 tst_QFocusEvent::tst_QFocusEvent()
122 tst_QFocusEvent::~tst_QFocusEvent()
127 void tst_QFocusEvent::initTestCase()
129 testFocusWidget = new QWidget( 0 );
130 childFocusWidgetOne = new FocusLineEdit( testFocusWidget );
131 childFocusWidgetOne->setGeometry( 10, 10, 180, 20 );
132 childFocusWidgetTwo = new FocusLineEdit( testFocusWidget );
133 childFocusWidgetTwo->setGeometry( 10, 50, 180, 20 );
135 //qApp->setMainWidget( testFocusWidget ); Qt4
136 testFocusWidget->resize( 200,100 );
137 testFocusWidget->show();
138 QVERIFY(QTest::qWaitForWindowExposed(testFocusWidget));
139 // Applications don't get focus when launched from the command line on Mac.
141 testFocusWidget->raise();
145 void tst_QFocusEvent::cleanupTestCase()
147 delete testFocusWidget;
150 void tst_QFocusEvent::init()
154 void tst_QFocusEvent::cleanup()
156 childFocusWidgetTwo->setGeometry( 10, 50, 180, 20 );
159 void tst_QFocusEvent::initWidget()
161 // On X11 we have to ensure the event was processed before doing any checking, on Windows
162 // this is processed straight away.
163 QApplication::setActiveWindow(testFocusWidget);
164 childFocusWidgetOne->setFocus(); // The first lineedit should have focus
165 QVERIFY(QTest::qWaitForWindowActive(testFocusWidget));
166 QTRY_VERIFY(childFocusWidgetOne->hasFocus());
168 childFocusWidgetOne->focusInEventRecieved = false;
169 childFocusWidgetOne->focusInEventGotFocus = false;
170 childFocusWidgetOne->focusInEventReason = -1;
171 childFocusWidgetOne->focusOutEventRecieved = false;
172 childFocusWidgetOne->focusOutEventLostFocus = false;
173 childFocusWidgetOne->focusOutEventReason = -1;
174 childFocusWidgetTwo->focusInEventRecieved = false;
175 childFocusWidgetTwo->focusInEventGotFocus = false;
176 childFocusWidgetTwo->focusInEventReason = -1;
177 childFocusWidgetTwo->focusOutEventRecieved = false;
178 childFocusWidgetTwo->focusOutEventLostFocus = false;
179 childFocusWidgetTwo->focusOutEventReason = -1;
182 void tst_QFocusEvent::checkReason_Tab()
186 // Now test the tab key
187 QTest::keyClick( childFocusWidgetOne, Qt::Key_Tab );
189 QVERIFY(childFocusWidgetOne->focusOutEventRecieved);
190 QVERIFY(childFocusWidgetTwo->focusInEventRecieved);
191 QVERIFY(childFocusWidgetOne->focusOutEventLostFocus);
192 QVERIFY(childFocusWidgetTwo->focusInEventGotFocus);
194 QVERIFY( childFocusWidgetTwo->hasFocus() );
195 QCOMPARE( childFocusWidgetOne->focusOutEventReason, (int) Qt::TabFocusReason );
196 QCOMPARE( childFocusWidgetTwo->focusInEventReason, (int) Qt::TabFocusReason );
199 void tst_QFocusEvent::checkReason_ShiftTab()
203 // Now test the shift + tab key
204 QTest::keyClick( childFocusWidgetOne, Qt::Key_Tab, Qt::ShiftModifier );
206 QVERIFY(childFocusWidgetOne->focusOutEventRecieved);
207 QVERIFY(childFocusWidgetTwo->focusInEventRecieved);
208 QVERIFY(childFocusWidgetOne->focusOutEventLostFocus);
209 QVERIFY(childFocusWidgetTwo->focusInEventGotFocus);
211 QVERIFY( childFocusWidgetTwo->hasFocus() );
212 QCOMPARE( childFocusWidgetOne->focusOutEventReason, (int)Qt::BacktabFocusReason );
213 QCOMPARE( childFocusWidgetTwo->focusInEventReason, (int)Qt::BacktabFocusReason );
218 In this test we verify that the Qt::KeyBacktab key is handled in a qfocusevent
220 void tst_QFocusEvent::checkReason_BackTab()
222 #ifdef Q_OS_WIN32 // key is not supported on Windows
223 QSKIP( "Backtab is not supported on Windows");
226 QVERIFY( childFocusWidgetOne->hasFocus() );
228 // Now test the backtab key
229 QTest::keyClick( childFocusWidgetOne, Qt::Key_Backtab );
232 QTRY_VERIFY(childFocusWidgetOne->focusOutEventRecieved);
233 QVERIFY(childFocusWidgetTwo->focusInEventRecieved);
234 QVERIFY(childFocusWidgetOne->focusOutEventLostFocus);
235 QVERIFY(childFocusWidgetTwo->focusInEventGotFocus);
237 QVERIFY( childFocusWidgetTwo->hasFocus() );
238 QCOMPARE( childFocusWidgetOne->focusOutEventReason, int(Qt::BacktabFocusReason) );
239 QCOMPARE( childFocusWidgetTwo->focusInEventReason, int(Qt::BacktabFocusReason) );
243 void tst_QFocusEvent::checkReason_Popup()
247 // Now test the popup reason
248 QMenu* popupMenu = new QMenu( testFocusWidget );
249 popupMenu->addMenu( "Test" );
250 popupMenu->popup( QPoint(0,0) );
253 QTRY_VERIFY(childFocusWidgetOne->focusOutEventLostFocus);
255 QTRY_VERIFY( childFocusWidgetOne->hasFocus() );
256 QVERIFY( !childFocusWidgetOne->focusInEventRecieved );
257 QVERIFY( childFocusWidgetOne->focusOutEventRecieved );
258 QVERIFY( !childFocusWidgetTwo->focusInEventRecieved );
259 QVERIFY( !childFocusWidgetTwo->focusOutEventRecieved );
260 QCOMPARE( childFocusWidgetOne->focusOutEventReason, int(Qt::PopupFocusReason));
264 QVERIFY(childFocusWidgetOne->focusInEventRecieved);
265 QVERIFY(childFocusWidgetOne->focusInEventGotFocus);
267 QVERIFY( childFocusWidgetOne->hasFocus() );
268 QVERIFY( childFocusWidgetOne->focusInEventRecieved );
269 QVERIFY( childFocusWidgetOne->focusOutEventRecieved );
270 QVERIFY( !childFocusWidgetTwo->focusInEventRecieved );
271 QVERIFY( !childFocusWidgetTwo->focusOutEventRecieved );
276 extern void qt_set_sequence_auto_mnemonic(bool);
280 void tst_QFocusEvent::checkReason_Shortcut()
284 qt_set_sequence_auto_mnemonic(true);
286 QLabel* label = new QLabel( "&Test", testFocusWidget );
287 label->setBuddy( childFocusWidgetTwo );
288 label->setGeometry( 10, 50, 90, 20 );
289 childFocusWidgetTwo->setGeometry( 105, 50, 95, 20 );
292 QVERIFY( childFocusWidgetOne->hasFocus() );
293 QVERIFY( !childFocusWidgetTwo->hasFocus() );
295 QTest::keyClick( label, Qt::Key_T, Qt::AltModifier );
297 QVERIFY(childFocusWidgetOne->focusOutEventRecieved);
298 QVERIFY(childFocusWidgetTwo->focusInEventRecieved);
299 QVERIFY(childFocusWidgetOne->focusOutEventLostFocus);
300 QVERIFY(childFocusWidgetTwo->focusInEventGotFocus);
302 QVERIFY( childFocusWidgetTwo->hasFocus() );
303 QVERIFY( !childFocusWidgetOne->focusInEventRecieved );
304 QVERIFY( childFocusWidgetOne->focusOutEventRecieved );
305 QCOMPARE( childFocusWidgetOne->focusOutEventReason, (int)Qt::ShortcutFocusReason );
306 QVERIFY( childFocusWidgetTwo->focusInEventRecieved );
307 QCOMPARE( childFocusWidgetTwo->focusInEventReason, (int)Qt::ShortcutFocusReason );
308 QVERIFY( !childFocusWidgetTwo->focusOutEventRecieved );
311 QVERIFY( childFocusWidgetTwo->hasFocus() );
312 QVERIFY( !childFocusWidgetOne->hasFocus() );
314 qt_set_sequence_auto_mnemonic(false);
318 void tst_QFocusEvent::checkReason_focusWidget()
320 // This test checks that a widget doesn't loose
321 // its focuswidget just because the focuswidget looses focus.
328 QVBoxLayout outerLayout;
329 outerLayout.addWidget(&frame1);
330 outerLayout.addWidget(&frame2);
331 window1.setLayout(&outerLayout);
333 QVBoxLayout leftLayout;
334 QVBoxLayout rightLayout;
335 leftLayout.addWidget(&edit1);
336 rightLayout.addWidget(&edit2);
337 frame1.setLayout(&leftLayout);
338 frame2.setLayout(&rightLayout);
345 QVERIFY(frame1.focusWidget() != 0);
346 QVERIFY(frame2.focusWidget() != 0);
349 void tst_QFocusEvent::checkReason_ActiveWindow()
353 QDialog* d = new QDialog( testFocusWidget );
355 d->activateWindow(); // ### CDE
356 QApplication::setActiveWindow(d);
357 QVERIFY(QTest::qWaitForWindowActive(d));
359 QTRY_VERIFY(childFocusWidgetOne->focusOutEventRecieved);
360 QVERIFY(childFocusWidgetOne->focusOutEventLostFocus);
362 QVERIFY( !childFocusWidgetOne->focusInEventRecieved );
363 QVERIFY( childFocusWidgetOne->focusOutEventRecieved );
364 QCOMPARE( childFocusWidgetOne->focusOutEventReason, (int)Qt::ActiveWindowFocusReason);
365 QVERIFY( !childFocusWidgetOne->hasFocus() );
370 #if defined(Q_OS_IRIX)
371 QEXPECT_FAIL("", "IRIX requires explicit activateWindow(), so this test does not make any sense.", Abort);
374 QEXPECT_FAIL("", "QTBUG-22815", Abort);
376 if (QGuiApplication::platformName() == QStringLiteral("xcb"))
377 QSKIP("QTBUG-22815 - This test is unstable on this platform");
378 QTRY_VERIFY(childFocusWidgetOne->focusInEventRecieved);
379 QVERIFY(childFocusWidgetOne->focusInEventGotFocus);
381 QVERIFY( childFocusWidgetOne->hasFocus() );
382 QVERIFY( childFocusWidgetOne->focusInEventRecieved );
383 QCOMPARE( childFocusWidgetOne->focusInEventReason, (int)Qt::ActiveWindowFocusReason);
387 QTEST_MAIN(tst_QFocusEvent)
388 #include "tst_qfocusevent.moc"