1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the test suite 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 http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://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 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <QApplication>
43 #include <QWidget>
44 #include <QDialog>
45 #include <QPushButton>
46 #include <QtTest/QtTest>
47
48 #include "qnativeevents.h"
49 #include "nativeeventlist.h"
50 #include "expectedeventlist.h"
51 #include <Carbon/Carbon.h>
52
53 #ifdef Q_OS_MAC
54
55 QT_USE_NAMESPACE
56
57 class tst_MacNativeEvents : public QObject
58 {
59 Q_OBJECT
60 private slots:
61 void testMouseMoveLocation();
62 void testPushButtonPressRelease();
63 void testMouseLeftDoubleClick();
64 void stressTestMouseLeftDoubleClick();
65 void testMouseDragInside();
66 void testMouseDragOutside();
67 void testMouseDragToNonClientArea();
68 void testDragWindow();
69 void testMouseEnter();
70 void testChildDialogInFrontOfModalParent();
71 #ifdef QT_MAC_USE_COCOA
72 // void testChildWindowInFrontOfParentWindow();
73 // void testChildToolWindowInFrontOfChildNormalWindow();
74 void testChildWindowInFrontOfStaysOnTopParentWindow();
75 #endif
76 void testKeyPressOnToplevel();
77 void testModifierShift();
78 void testModifierAlt();
79 void testModifierCtrl();
80 void testModifierCtrlWithDontSwapCtrlAndMeta();
81 };
82
testMouseMoveLocation()83 void tst_MacNativeEvents::testMouseMoveLocation()
84 {
85 QWidget w;
86 w.setMouseTracking(true);
87 w.show();
88 QPoint p = w.geometry().center();
89
90 NativeEventList native;
91 native.append(new QNativeMouseMoveEvent(p, Qt::NoModifier));
92
93 ExpectedEventList expected(&w);
94 expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(p), p, Qt::NoButton, Qt::NoButton, Qt::NoModifier));
95
96 native.play();
97 QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
98 }
99
testPushButtonPressRelease()100 void tst_MacNativeEvents::testPushButtonPressRelease()
101 {
102 // Check that a native mouse press and release generates the
103 // same qevents on a pushbutton:
104 QPushButton w("click me");
105 w.show();
106 QPoint p = w.geometry().center();
107
108 NativeEventList native;
109 native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 1, Qt::NoModifier));
110 native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 0, Qt::NoModifier));
111
112 ExpectedEventList expected(&w);
113 expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier));
114 expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::NoButton, Qt::NoModifier));
115
116 native.play();
117 QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
118 }
119
testMouseLeftDoubleClick()120 void tst_MacNativeEvents::testMouseLeftDoubleClick()
121 {
122 // Check that a native double click makes
123 // the test widget receive a press-release-click-release:
124 QWidget w;
125 w.show();
126 QPoint p = w.geometry().center();
127
128 NativeEventList native;
129 native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 1, Qt::NoModifier));
130 native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 0, Qt::NoModifier));
131 native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 2, Qt::NoModifier));
132 native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 0, Qt::NoModifier));
133
134 ExpectedEventList expected(&w);
135 expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier));
136 expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::NoButton, Qt::NoModifier));
137 expected.append(new QMouseEvent(QEvent::MouseButtonDblClick, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier));
138 expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::NoButton, Qt::NoModifier));
139
140 native.play();
141 QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
142 }
143
stressTestMouseLeftDoubleClick()144 void tst_MacNativeEvents::stressTestMouseLeftDoubleClick()
145 {
146 // Check that multiple, fast, double clicks makes
147 // the test widget receive correct click events
148 QWidget w;
149 w.show();
150 QPoint p = w.geometry().center();
151
152 NativeEventList native;
153 ExpectedEventList expected(&w);
154
155 for (int i=0; i<10; ++i){
156 native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 1, Qt::NoModifier));
157 native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 0, Qt::NoModifier));
158 native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 2, Qt::NoModifier));
159 native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 0, Qt::NoModifier));
160
161 expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier));
162 expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::NoButton, Qt::NoModifier));
163 expected.append(new QMouseEvent(QEvent::MouseButtonDblClick, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier));
164 expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::NoButton, Qt::NoModifier));
165 }
166
167 native.play();
168 QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
169 }
170
testMouseDragInside()171 void tst_MacNativeEvents::testMouseDragInside()
172 {
173 // Check that a mouse drag inside a widget
174 // will cause press-move-release events to be delivered
175 QWidget w;
176 w.show();
177 QPoint p1 = w.geometry().center();
178 QPoint p2 = p1 - QPoint(10, 0);
179 QPoint p3 = p1 - QPoint(20, 0);
180 QPoint p4 = p1 - QPoint(30, 0);
181
182 NativeEventList native;
183 native.append(new QNativeMouseButtonEvent(p1, Qt::LeftButton, 1, Qt::NoModifier));
184 native.append(new QNativeMouseDragEvent(p2, Qt::LeftButton, Qt::NoModifier));
185 native.append(new QNativeMouseDragEvent(p3, Qt::LeftButton, Qt::NoModifier));
186 native.append(new QNativeMouseButtonEvent(p4, Qt::LeftButton, 0, Qt::NoModifier));
187
188 ExpectedEventList expected(&w);
189 expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(p1), p1, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier));
190 expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(p2), p2, Qt::NoButton, Qt::LeftButton, Qt::NoModifier));
191 expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(p3), p3, Qt::NoButton, Qt::LeftButton, Qt::NoModifier));
192 expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p4), p4, Qt::LeftButton, Qt::NoButton, Qt::NoModifier));
193
194 native.play();
195 QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
196 }
197
testMouseDragOutside()198 void tst_MacNativeEvents::testMouseDragOutside()
199 {
200 // Check that if we drag the mouse from inside the
201 // widget, and release it outside, we still get mouse move
202 // and release events when the mouse is outside the widget.
203 QWidget w;
204 w.show();
205 QPoint inside1 = w.geometry().center();
206 QPoint inside2 = inside1 - QPoint(10, 0);
207 QPoint outside1 = w.geometry().topLeft() - QPoint(50, 0);
208 QPoint outside2 = outside1 - QPoint(10, 0);
209
210 NativeEventList native;
211 native.append(new QNativeMouseButtonEvent(inside1, Qt::LeftButton, 1, Qt::NoModifier));
212 native.append(new QNativeMouseDragEvent(inside2, Qt::LeftButton, Qt::NoModifier));
213 native.append(new QNativeMouseDragEvent(outside1, Qt::LeftButton, Qt::NoModifier));
214 native.append(new QNativeMouseButtonEvent(outside2, Qt::LeftButton, 0, Qt::NoModifier));
215
216 ExpectedEventList expected(&w);
217 expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(inside1), inside1, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier));
218 expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(inside2), inside2, Qt::NoButton, Qt::LeftButton, Qt::NoModifier));
219 expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(outside1), outside1, Qt::NoButton, Qt::LeftButton, Qt::NoModifier));
220 expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(outside2), outside2, Qt::LeftButton, Qt::NoButton, Qt::NoModifier));
221
222 native.play();
223 QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
224 }
225
testMouseDragToNonClientArea()226 void tst_MacNativeEvents::testMouseDragToNonClientArea()
227 {
228 // Check that if we drag the mouse from inside the
229 // widget, and release it on the title bar, we still get mouse move
230 // and release events when the mouse is on the title bar
231 QWidget w;
232 w.show();
233 QPoint inside1 = w.geometry().center();
234 QPoint inside2 = inside1 - QPoint(10, 0);
235 QPoint titlebar1 = w.geometry().topLeft() - QPoint(-100, 10);
236 QPoint titlebar2 = titlebar1 - QPoint(10, 0);
237
238 NativeEventList native;
239 native.append(new QNativeMouseButtonEvent(inside1, Qt::LeftButton, 1, Qt::NoModifier));
240 native.append(new QNativeMouseDragEvent(inside2, Qt::LeftButton, Qt::NoModifier));
241 native.append(new QNativeMouseDragEvent(titlebar1, Qt::LeftButton, Qt::NoModifier));
242 native.append(new QNativeMouseButtonEvent(titlebar2, Qt::LeftButton, 0, Qt::NoModifier));
243
244 ExpectedEventList expected(&w);
245 expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(inside1), inside1, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier));
246 expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(inside2), inside2, Qt::NoButton, Qt::LeftButton, Qt::NoModifier));
247 expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(titlebar1), titlebar1, Qt::NoButton, Qt::LeftButton, Qt::NoModifier));
248 expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(titlebar2), titlebar2, Qt::LeftButton, Qt::NoButton, Qt::NoModifier));
249
250 native.play();
251 QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
252 }
253
testDragWindow()254 void tst_MacNativeEvents::testDragWindow()
255 {
256 // Check that if we drag the mouse from inside the
257 // widgets title bar, we get a move event on the window
258 QWidget w;
259 w.show();
260 QPoint titlebar = w.geometry().topLeft() - QPoint(-100, 10);
261 QPoint moveTo = titlebar + QPoint(100, 0);
262
263 NativeEventList native;
264 native.append(new QNativeMouseButtonEvent(titlebar, Qt::LeftButton, 1, Qt::NoModifier));
265 native.append(new QNativeMouseDragEvent(moveTo, Qt::LeftButton, Qt::NoModifier));
266 native.append(500, new QNativeMouseButtonEvent(moveTo, Qt::LeftButton, 0, Qt::NoModifier));
267
268 ExpectedEventList expected(&w);
269 expected.append(new QMouseEvent(QEvent::NonClientAreaMouseButtonPress, w.mapFromGlobal(titlebar), titlebar, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier));
270 expected.append(new QMouseEvent(QEvent::NonClientAreaMouseButtonRelease, w.mapFromGlobal(titlebar), moveTo, Qt::LeftButton, Qt::NoButton, Qt::NoModifier));
271
272 native.play();
273 bool waited = expected.waitForAllEvents();
274 if (!waited) {
275 QEXPECT_FAIL("", "QTBUG-26804", Continue);
276 }
277 QVERIFY2(waited, "the test did not receive all expected events!");
278 }
279
testMouseEnter()280 void tst_MacNativeEvents::testMouseEnter()
281 {
282 // When a mouse enters a widget, both a mouse enter events and a
283 // mouse move event should be sendt. Lets test this:
284 QWidget w;
285 w.setMouseTracking(true);
286 w.show();
287 QPoint outside = w.geometry().topLeft() - QPoint(50, 0);
288 QPoint inside = w.geometry().center();
289
290 NativeEventList native;
291 native.append(new QNativeMouseMoveEvent(outside, Qt::NoModifier));
292 native.append(new QNativeMouseMoveEvent(inside, Qt::NoModifier));
293
294 ExpectedEventList expected(&w);
295 expected.append(new QEvent(QEvent::Enter));
296 expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(inside), inside, Qt::NoButton, Qt::NoButton, Qt::NoModifier));
297
298 native.play();
299 QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
300 }
301
testChildDialogInFrontOfModalParent()302 void tst_MacNativeEvents::testChildDialogInFrontOfModalParent()
303 {
304 // Test that a child dialog of a modal parent dialog is
305 // in front of the parent, and active:
306 QDialog parent;
307 parent.setWindowModality(Qt::ApplicationModal);
308 QDialog child(&parent);
309 QPushButton button("close", &child);
310 connect(&button, SIGNAL(clicked()), &child, SLOT(close()));
311 parent.show();
312 child.show();
313 QPoint inside = button.mapToGlobal(button.geometry().center());
314
315 // Post a click on the button to close the child dialog:
316 NativeEventList native;
317 native.append(new QNativeMouseButtonEvent(inside, Qt::LeftButton, 1, Qt::NoModifier));
318 native.append(new QNativeMouseButtonEvent(inside, Qt::LeftButton, 0, Qt::NoModifier));
319
320 native.play();
321 QTest::qWait(100);
322 QVERIFY(!child.isVisible());
323 }
324
325 #ifdef QT_MAC_USE_COCOA
326 #if 0
327 // This test is disabled as of Qt-4.7.4 because we cannot do it
328 // unless we use the Cocoa sub window API. But using that opens up
329 // a world of side effects that we cannot live with. So we rather
330 // not support child-on-top-of-parent instead.
331 void tst_MacNativeEvents::testChildWindowInFrontOfParentWindow()
332 {
333 // Test that a child window always stacks in front of its parent window.
334 // Do this by first click on the parent, then on the child window button.
335 QWidget parent;
336 QPushButton child("a button", &parent);
337 child.setWindowFlags(Qt::Window);
338 connect(&child, SIGNAL(clicked()), &child, SLOT(close()));
339 parent.show();
340 child.show();
341
342 QPoint parent_p = parent.geometry().bottomLeft() + QPoint(20, -20);
343 QPoint child_p = child.geometry().center();
344
345 NativeEventList native;
346 native.append(new QNativeMouseButtonEvent(parent_p, Qt::LeftButton, 1, Qt::NoModifier));
347 native.append(new QNativeMouseButtonEvent(parent_p, Qt::LeftButton, 0, Qt::NoModifier));
348 native.append(new QNativeMouseButtonEvent(child_p, Qt::LeftButton, 1, Qt::NoModifier));
349 native.append(new QNativeMouseButtonEvent(child_p, Qt::LeftButton, 0, Qt::NoModifier));
350
351 native.play();
352 QTest::qWait(100);
353 QVERIFY(!child.isVisible());
354 }
355 #endif
356
357 /* This test can be enabled once setStackingOrder has been fixed in qwidget_mac.mm
358 void tst_MacNativeEvents::testChildToolWindowInFrontOfChildNormalWindow()
359 {
360 // Test that a child tool window always stacks in front of normal sibling windows.
361 // Do this by first click on the sibling, then on the tool window button.
362 QWidget parent;
363 QWidget normalChild(&parent, Qt::Window);
364 QPushButton toolChild("a button", &parent);
365 toolChild.setWindowFlags(Qt::Tool);
366 connect(&toolChild, SIGNAL(clicked()), &toolChild, SLOT(close()));
367 parent.show();
368 normalChild.show();
369 toolChild.show();
370
371 QPoint normalChild_p = normalChild.geometry().bottomLeft() + QPoint(20, -20);
372 QPoint toolChild_p = toolChild.geometry().center();
373
374 NativeEventList native;
375 native.append(new QNativeMouseButtonEvent(normalChild_p, Qt::LeftButton, 1, Qt::NoModifier));
376 native.append(new QNativeMouseButtonEvent(normalChild_p, Qt::LeftButton, 0, Qt::NoModifier));
377 native.append(new QNativeMouseButtonEvent(toolChild_p, Qt::LeftButton, 1, Qt::NoModifier));
378 native.append(new QNativeMouseButtonEvent(toolChild_p, Qt::LeftButton, 0, Qt::NoModifier));
379
380 native.play();
381 QTest::qWait(100);
382 QVERIFY(!toolChild.isVisible());
383 }
384 */
testChildWindowInFrontOfStaysOnTopParentWindow()385 void tst_MacNativeEvents::testChildWindowInFrontOfStaysOnTopParentWindow()
386 {
387 // Test that a child window stacks on top of a stays-on-top parent.
388 QWidget parent(0, Qt::WindowStaysOnTopHint);
389 QPushButton button("close", &parent);
390 button.setWindowFlags(Qt::Window);
391 connect(&button, SIGNAL(clicked()), &button, SLOT(close()));
392 parent.show();
393 button.show();
394 QPoint inside = button.geometry().center();
395
396 // Post a click on the button to close the child dialog:
397 NativeEventList native;
398 native.append(new QNativeMouseButtonEvent(inside, Qt::LeftButton, 1, Qt::NoModifier));
399 native.append(new QNativeMouseButtonEvent(inside, Qt::LeftButton, 0, Qt::NoModifier));
400
401 native.play();
402 QTest::qWait(100);
403 QVERIFY(!button.isVisible());
404 }
405 #endif
406
testKeyPressOnToplevel()407 void tst_MacNativeEvents::testKeyPressOnToplevel()
408 {
409 // Check that we receive keyevents for
410 // toplevel widgets. For leagacy reasons, and according to Qt on
411 // other platforms (carbon port + linux), we should get these events
412 // even when the focus policy is set to Qt::NoFocus when there is no
413 // other focus widget on screen:
414 QWidget w;
415 w.show();
416
417 NativeEventList native;
418 native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::NoModifier));
419 native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::NoModifier));
420
421 ExpectedEventList expected(&w);
422 expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier));
423 expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::NoModifier));
424
425 native.play();
426 QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
427 }
428
testModifierShift()429 void tst_MacNativeEvents::testModifierShift()
430 {
431 QWidget w;
432 w.show();
433
434 NativeEventList native;
435 native.append(new QNativeModifierEvent(Qt::ShiftModifier));
436 native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::ShiftModifier));
437 native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::ShiftModifier));
438 native.append(new QNativeModifierEvent(Qt::NoModifier));
439
440 ExpectedEventList expected(&w);
441 expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_Shift, Qt::NoModifier));
442 expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::ShiftModifier));
443 expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::ShiftModifier));
444 expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_Shift, Qt::ShiftModifier));
445
446 native.play();
447 QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
448 }
449
testModifierAlt()450 void tst_MacNativeEvents::testModifierAlt()
451 {
452 QWidget w;
453 w.show();
454
455 NativeEventList native;
456 native.append(new QNativeModifierEvent(Qt::AltModifier));
457 native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::AltModifier));
458 native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::AltModifier));
459 native.append(new QNativeModifierEvent(Qt::NoModifier));
460
461 ExpectedEventList expected(&w);
462 expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_Alt, Qt::NoModifier));
463 expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::AltModifier));
464 expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::AltModifier));
465 expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_Alt, Qt::AltModifier));
466
467 native.play();
468 QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
469 }
470
testModifierCtrl()471 void tst_MacNativeEvents::testModifierCtrl()
472 {
473 // On Mac, we switch the Command and Control modifier by default, so that Command
474 // means Meta, and Control means Command. Lets check that this works:
475 QWidget w;
476 w.show();
477
478 QVERIFY(kControlUnicode == QKeySequence(Qt::Key_Meta).toString(QKeySequence::NativeText)[0]);
479 QVERIFY(kCommandUnicode == QKeySequence(Qt::Key_Control).toString(QKeySequence::NativeText)[0]);
480
481 NativeEventList native;
482 native.append(new QNativeModifierEvent(Qt::ControlModifier));
483 native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::ControlModifier));
484 native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::ControlModifier));
485 native.append(new QNativeModifierEvent(Qt::NoModifier));
486
487 ExpectedEventList expected(&w);
488 expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_Meta, Qt::NoModifier));
489 expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::MetaModifier));
490 expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::MetaModifier));
491 expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_Meta, Qt::MetaModifier));
492
493 native.play();
494 QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
495 }
496
testModifierCtrlWithDontSwapCtrlAndMeta()497 void tst_MacNativeEvents::testModifierCtrlWithDontSwapCtrlAndMeta()
498 {
499 // On Mac, we switch the Command and Control modifier by default, so that Command
500 // means Meta, and Control means Command. Lets check that the flag to swith off
501 // this behaviour works. While working on this test I realized that we actually
502 // don't (and never have) respected this flag for raw key events. Only for
503 // menus, through QKeySequence. I don't want to change this behaviour now, at
504 // least not until someone complains. So I choose to let the test just stop
505 // any unintended regressions instead. If we decide to resepect the the flag at one
506 // point, fix the test.
507 QCoreApplication::setAttribute(Qt::AA_MacDontSwapCtrlAndMeta);
508 QWidget w;
509 w.show();
510
511 QVERIFY(kCommandUnicode == QKeySequence(Qt::Key_Meta).toString(QKeySequence::NativeText)[0]);
512 QVERIFY(kControlUnicode == QKeySequence(Qt::Key_Control).toString(QKeySequence::NativeText)[0]);
513
514 NativeEventList native;
515 native.append(new QNativeModifierEvent(Qt::ControlModifier));
516 native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::ControlModifier));
517 native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::ControlModifier));
518 native.append(new QNativeModifierEvent(Qt::NoModifier));
519
520 ExpectedEventList expected(&w);
521 expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_Meta, Qt::NoModifier));
522 expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::ControlModifier));
523 expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::ControlModifier));
524 expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_Meta, Qt::ControlModifier));
525
526 native.play();
527 QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
528 QCoreApplication::setAttribute(Qt::AA_MacDontSwapCtrlAndMeta, false);
529 }
530
531 #include "tst_macnativeevents.moc"
532
533 QTEST_MAIN(tst_MacNativeEvents)
534
535 #else
536
537 QTEST_NOOP_MAIN
538
539 #endif
540