mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2025-07-06 17:25:24 +08:00
qt 6.5.1 original
This commit is contained in:
39
tests/auto/other/macnativeevents/BLACKLIST
Normal file
39
tests/auto/other/macnativeevents/BLACKLIST
Normal file
@ -0,0 +1,39 @@
|
||||
# QTBUG-22775
|
||||
[testDragWindow]
|
||||
osx
|
||||
[testMouseEnter]
|
||||
osx
|
||||
[testChildDialogInFrontOfModalParent]
|
||||
osx
|
||||
[testChildWindowInFrontOfStaysOnTopParentWindow]
|
||||
osx
|
||||
[testMouseMoveLocation]
|
||||
osx
|
||||
[testMouseLeftDoubleClick]
|
||||
osx
|
||||
[stressTestMouseLeftDoubleClick]
|
||||
osx
|
||||
[testMouseDragInside]
|
||||
osx
|
||||
[testMouseDragOutside]
|
||||
osx
|
||||
[testMouseDragToNonClientArea]
|
||||
osx
|
||||
macos ci
|
||||
# The following key tests fail after switching to synchronous
|
||||
# expose events, and we don't know why yet. QTBUG-62042
|
||||
[testKeyPressOnToplevel]
|
||||
osx
|
||||
[testModifierShift]
|
||||
osx
|
||||
[testModifierAlt]
|
||||
osx
|
||||
[testModifierCtrl]
|
||||
osx
|
||||
# QTQAINFRA-1292
|
||||
[testPushButtonPressRelease]
|
||||
macos ci
|
||||
|
||||
# QTQAINFRA-1292
|
||||
[testModifierCtrlWithDontSwapCtrlAndMeta]
|
||||
macos ci
|
23
tests/auto/other/macnativeevents/CMakeLists.txt
Normal file
23
tests/auto/other/macnativeevents/CMakeLists.txt
Normal file
@ -0,0 +1,23 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
if(NOT APPLE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
#####################################################################
|
||||
## tst_macnativeevents Test:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_test(tst_macnativeevents
|
||||
SOURCES
|
||||
expectedeventlist.cpp expectedeventlist.h
|
||||
nativeeventlist.cpp nativeeventlist.h
|
||||
qnativeevents.cpp qnativeevents.h
|
||||
qnativeevents_mac.cpp
|
||||
tst_macnativeevents.cpp
|
||||
LIBRARIES
|
||||
${FWAppKit}
|
||||
Qt::Gui
|
||||
Qt::Widgets
|
||||
)
|
176
tests/auto/other/macnativeevents/expectedeventlist.cpp
Normal file
176
tests/auto/other/macnativeevents/expectedeventlist.cpp
Normal file
@ -0,0 +1,176 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "expectedeventlist.h"
|
||||
#include <QDebug>
|
||||
#include <QCoreApplication>
|
||||
#include <QAbstractEventDispatcher>
|
||||
#include <QTest>
|
||||
|
||||
ExpectedEventList::ExpectedEventList(QObject *target)
|
||||
: QObject(target), eventCount(0)
|
||||
{
|
||||
target->installEventFilter(this);
|
||||
debug = qgetenv("NATIVEDEBUG").toInt();
|
||||
if (debug > 0)
|
||||
qDebug() << "Debug level sat to:" << debug;
|
||||
}
|
||||
|
||||
ExpectedEventList::~ExpectedEventList()
|
||||
{
|
||||
qDeleteAll(eventList);
|
||||
}
|
||||
|
||||
void ExpectedEventList::append(QEvent *e)
|
||||
{
|
||||
eventList.append(e);
|
||||
++eventCount;
|
||||
}
|
||||
|
||||
void ExpectedEventList::timerEvent(QTimerEvent *)
|
||||
{
|
||||
timer.stop();
|
||||
QAbstractEventDispatcher::instance()->interrupt();
|
||||
}
|
||||
|
||||
bool ExpectedEventList::waitForAllEvents(int maxEventWaitTime)
|
||||
{
|
||||
if (eventList.isEmpty())
|
||||
return true;
|
||||
|
||||
int eventCount = eventList.size();
|
||||
timer.start(maxEventWaitTime, this);
|
||||
|
||||
while (timer.isActive()) {
|
||||
QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);
|
||||
if (eventList.isEmpty())
|
||||
return true;
|
||||
|
||||
if (eventCount < eventList.size()){
|
||||
eventCount = eventList.size();
|
||||
timer.start(maxEventWaitTime, this);
|
||||
}
|
||||
}
|
||||
|
||||
int eventListNr = eventCount - eventList.size() + 1;
|
||||
qWarning() << "Stopped waiting for expected event nr" << eventListNr;
|
||||
return false;
|
||||
}
|
||||
|
||||
void ExpectedEventList::compareMouseEvents(QEvent *received, QEvent *expected)
|
||||
{
|
||||
QMouseEvent *e1 = static_cast<QMouseEvent *>(received);
|
||||
QMouseEvent *e2 = static_cast<QMouseEvent *>(expected);
|
||||
|
||||
// Do a manual check first to be able to write more sensible
|
||||
// debug output if we know we're going to fail:
|
||||
if (e1->pos() == e2->pos()
|
||||
&& (e1->globalPos() == e2->globalPos())
|
||||
&& (e1->button() == e2->button())
|
||||
&& (e1->buttons() == e2->buttons())
|
||||
&& (e1->modifiers() == e2->modifiers())) {
|
||||
if (debug > 0)
|
||||
qDebug() << " Received (OK):" << e1 << e1->globalPos();
|
||||
return; // equal
|
||||
}
|
||||
|
||||
// INVARIANT: The two events are not equal. So we fail. Depending
|
||||
// on whether debug mode is no or not, we let QTest fail. Otherwise
|
||||
// we let the test continue for debugging puposes.
|
||||
int eventListNr = eventCount - eventList.size();
|
||||
if (debug == 0) {
|
||||
qWarning() << "Expected event" << eventListNr << "differs from received event:";
|
||||
QCOMPARE(e1->pos(), e2->pos());
|
||||
QCOMPARE(e1->globalPos(), e2->globalPos());
|
||||
QCOMPARE(e1->button(), e2->button());
|
||||
QCOMPARE(e1->buttons(), e2->buttons());
|
||||
QCOMPARE(e1->modifiers(), e2->modifiers());
|
||||
} else {
|
||||
qWarning() << "*** FAIL *** : Expected event" << eventListNr << "differs from received event:";
|
||||
qWarning() << "Received:" << e1 << e1->globalPos();
|
||||
qWarning() << "Expected:" << e2 << e2->globalPos();
|
||||
}
|
||||
}
|
||||
|
||||
void ExpectedEventList::compareKeyEvents(QEvent *received, QEvent *expected)
|
||||
{
|
||||
QKeyEvent *e1 = static_cast<QKeyEvent *>(received);
|
||||
QKeyEvent *e2 = static_cast<QKeyEvent *>(expected);
|
||||
|
||||
// Do a manual check first to be able to write more sensible
|
||||
// debug output if we know we're going to fail:
|
||||
if (e1->key() == e2->key()
|
||||
&& (e1->modifiers() == e2->modifiers())
|
||||
&& (e1->count() == e2->count())
|
||||
&& (e1->isAutoRepeat() == e2->isAutoRepeat())) {
|
||||
if (debug > 0)
|
||||
qDebug() << " Received (OK):" << e1 << QKeySequence(e1->key()).toString(QKeySequence::NativeText);
|
||||
return; // equal
|
||||
}
|
||||
|
||||
// INVARIANT: The two events are not equal. So we fail. Depending
|
||||
// on whether debug mode is no or not, we let QTest fail. Otherwise
|
||||
// we let the test continue for debugging puposes.
|
||||
int eventListNr = eventCount - eventList.size();
|
||||
if (debug == 0) {
|
||||
qWarning() << "Expected event" << eventListNr << "differs from received event:";
|
||||
QCOMPARE(e1->key(), e2->key());
|
||||
QCOMPARE(e1->modifiers(), e2->modifiers());
|
||||
QCOMPARE(e1->count(), e2->count());
|
||||
QCOMPARE(e1->isAutoRepeat(), e2->isAutoRepeat());
|
||||
} else {
|
||||
qWarning() << "*** FAIL *** : Expected event" << eventListNr << "differs from received event:";
|
||||
qWarning() << "Received:" << e1 << QKeySequence(e1->key()).toString(QKeySequence::NativeText);
|
||||
qWarning() << "Expected:" << e2 << QKeySequence(e2->key()).toString(QKeySequence::NativeText);
|
||||
}
|
||||
}
|
||||
|
||||
bool ExpectedEventList::eventFilter(QObject *, QEvent *received)
|
||||
{
|
||||
if (debug > 1)
|
||||
qDebug() << received;
|
||||
if (eventList.isEmpty())
|
||||
return false;
|
||||
|
||||
bool eat = false;
|
||||
QEvent *expected = eventList.first();
|
||||
if (expected->type() == received->type()) {
|
||||
eventList.removeFirst();
|
||||
switch (received->type()) {
|
||||
case QEvent::MouseButtonPress:
|
||||
case QEvent::MouseButtonRelease:
|
||||
case QEvent::MouseMove:
|
||||
case QEvent::MouseButtonDblClick:
|
||||
case QEvent::NonClientAreaMouseButtonPress:
|
||||
case QEvent::NonClientAreaMouseButtonRelease:
|
||||
case QEvent::NonClientAreaMouseButtonDblClick:
|
||||
case QEvent::NonClientAreaMouseMove: {
|
||||
compareMouseEvents(received, expected);
|
||||
eat = true;
|
||||
break;
|
||||
}
|
||||
case QEvent::KeyPress:
|
||||
case QEvent::KeyRelease: {
|
||||
compareKeyEvents(received, expected);
|
||||
eat = true;
|
||||
break;
|
||||
}
|
||||
case QEvent::Resize: {
|
||||
break;
|
||||
}
|
||||
case QEvent::WindowActivate: {
|
||||
break;
|
||||
}
|
||||
case QEvent::WindowDeactivate: {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (eventList.isEmpty())
|
||||
QAbstractEventDispatcher::instance()->interrupt();
|
||||
}
|
||||
|
||||
return eat;
|
||||
}
|
||||
|
33
tests/auto/other/macnativeevents/expectedeventlist.h
Normal file
33
tests/auto/other/macnativeevents/expectedeventlist.h
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#ifndef EVENTFILTER
|
||||
#define EVENTFILTER
|
||||
|
||||
#include <QWidget>
|
||||
#include <QList>
|
||||
#include <QEvent>
|
||||
#include <QBasicTimer>
|
||||
|
||||
class ExpectedEventList : public QObject
|
||||
{
|
||||
QList<QEvent *> eventList;
|
||||
QBasicTimer timer;
|
||||
int debug;
|
||||
int eventCount;
|
||||
void timerEvent(QTimerEvent *);
|
||||
|
||||
public:
|
||||
ExpectedEventList(QObject *target);
|
||||
~ExpectedEventList();
|
||||
void append(QEvent *e);
|
||||
bool waitForAllEvents(int timeoutPerEvent = 2000);
|
||||
bool eventFilter(QObject *obj, QEvent *event);
|
||||
|
||||
private:
|
||||
void compareMouseEvents(QEvent *event1, QEvent *event2);
|
||||
void compareKeyEvents(QEvent *event1, QEvent *event2);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
76
tests/auto/other/macnativeevents/nativeeventlist.cpp
Normal file
76
tests/auto/other/macnativeevents/nativeeventlist.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "nativeeventlist.h"
|
||||
|
||||
NativeEventList::NativeEventList(int defaultWaitMs)
|
||||
: playbackMultiplier(1.0)
|
||||
, currIndex(-1)
|
||||
, wait(false)
|
||||
, defaultWaitMs(defaultWaitMs)
|
||||
{
|
||||
debug = qgetenv("NATIVEDEBUG").toInt();
|
||||
QString multiplier = qgetenv("NATIVEDEBUGSPEED");
|
||||
if (!multiplier.isEmpty())
|
||||
setTimeMultiplier(multiplier.toFloat());
|
||||
}
|
||||
|
||||
NativeEventList::~NativeEventList()
|
||||
{
|
||||
for (int i=0; i<eventList.size(); i++)
|
||||
delete eventList.takeAt(i).second;
|
||||
}
|
||||
|
||||
void NativeEventList::sendNextEvent()
|
||||
{
|
||||
QNativeEvent *e = eventList.at(currIndex).second;
|
||||
if (e) {
|
||||
if (debug > 0)
|
||||
qDebug() << "Sending:" << *e;
|
||||
QNativeInput::sendNativeEvent(*e);
|
||||
}
|
||||
waitNextEvent();
|
||||
}
|
||||
|
||||
void NativeEventList::waitNextEvent()
|
||||
{
|
||||
if (++currIndex >= eventList.size()){
|
||||
emit done();
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
int interval = eventList.at(currIndex).first;
|
||||
QTimer::singleShot(interval * playbackMultiplier, this, SLOT(sendNextEvent()));
|
||||
}
|
||||
|
||||
void NativeEventList::append(QNativeEvent *event)
|
||||
{
|
||||
eventList.append(QPair<int, QNativeEvent *>(defaultWaitMs, event));
|
||||
}
|
||||
|
||||
void NativeEventList::append(int waitMs, QNativeEvent *event)
|
||||
{
|
||||
eventList.append(QPair<int, QNativeEvent *>(waitMs, event));
|
||||
}
|
||||
|
||||
void NativeEventList::play(Playback playback)
|
||||
{
|
||||
waitNextEvent();
|
||||
|
||||
wait = (playback == WaitUntilFinished);
|
||||
while (wait)
|
||||
QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);
|
||||
}
|
||||
|
||||
void NativeEventList::stop()
|
||||
{
|
||||
wait = false;
|
||||
QAbstractEventDispatcher::instance()->interrupt();
|
||||
}
|
||||
|
||||
void NativeEventList::setTimeMultiplier(float multiplier)
|
||||
{
|
||||
playbackMultiplier = multiplier;
|
||||
}
|
||||
|
44
tests/auto/other/macnativeevents/nativeeventlist.h
Normal file
44
tests/auto/other/macnativeevents/nativeeventlist.h
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#ifndef Q_NATIVE_PLAYBACK
|
||||
#define Q_NATIVE_PLAYBACK
|
||||
|
||||
#include <QtCore>
|
||||
#include "qnativeevents.h"
|
||||
|
||||
class NativeEventList : public QObject
|
||||
{
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
enum Playback {ReturnImmediately, WaitUntilFinished};
|
||||
|
||||
NativeEventList(int defaultWaitMs = 20);
|
||||
~NativeEventList();
|
||||
|
||||
void append(QNativeEvent *event);
|
||||
void append(int waitMs, QNativeEvent *event = nullptr);
|
||||
|
||||
void play(Playback playback = WaitUntilFinished);
|
||||
void stop();
|
||||
void setTimeMultiplier(float multiplier);
|
||||
|
||||
signals:
|
||||
void done();
|
||||
|
||||
private slots:
|
||||
void sendNextEvent();
|
||||
|
||||
private:
|
||||
void waitNextEvent();
|
||||
|
||||
QList<QPair<int, QNativeEvent *> > eventList;
|
||||
float playbackMultiplier;
|
||||
int currIndex;
|
||||
bool wait;
|
||||
int defaultWaitMs;
|
||||
int debug;
|
||||
};
|
||||
|
||||
#endif
|
340
tests/auto/other/macnativeevents/qnativeevents.cpp
Normal file
340
tests/auto/other/macnativeevents/qnativeevents.cpp
Normal file
@ -0,0 +1,340 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "qnativeevents.h"
|
||||
|
||||
QNativeInput::QNativeInput(bool subscribe)
|
||||
{
|
||||
if (subscribe)
|
||||
subscribeForNativeEvents();
|
||||
}
|
||||
|
||||
QNativeInput::~QNativeInput()
|
||||
{
|
||||
unsubscribeForNativeEvents();
|
||||
}
|
||||
|
||||
void QNativeInput::notify(QNativeEvent *event)
|
||||
{
|
||||
nativeEvent(event);
|
||||
}
|
||||
|
||||
void QNativeInput::nativeEvent(QNativeEvent *event)
|
||||
{
|
||||
switch (event->id()){
|
||||
case QNativeMouseButtonEvent::eventId:{
|
||||
QNativeMouseButtonEvent *e = static_cast<QNativeMouseButtonEvent *>(event);
|
||||
(e->clickCount > 0) ? nativeMousePressEvent(e) : nativeMouseReleaseEvent(e);
|
||||
break; }
|
||||
case QNativeMouseMoveEvent::eventId:
|
||||
nativeMouseMoveEvent(static_cast<QNativeMouseMoveEvent *>(event));
|
||||
break;
|
||||
case QNativeMouseDragEvent::eventId:
|
||||
nativeMouseDragEvent(static_cast<QNativeMouseDragEvent *>(event));
|
||||
break;
|
||||
case QNativeMouseWheelEvent::eventId:
|
||||
nativeMouseWheelEvent(static_cast<QNativeMouseWheelEvent *>(event));
|
||||
break;
|
||||
case QNativeKeyEvent::eventId:{
|
||||
QNativeKeyEvent *e = static_cast<QNativeKeyEvent *>(event);
|
||||
e->press ? nativeKeyPressEvent(e) : nativeKeyReleaseEvent(e);
|
||||
break; }
|
||||
case QNativeModifierEvent::eventId:
|
||||
nativeModifierEvent(static_cast<QNativeModifierEvent *>(event));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Qt::Native::Status QNativeInput::sendNativeEvent(const QNativeEvent &event)
|
||||
{
|
||||
switch (event.id()){
|
||||
case QNativeMouseMoveEvent::eventId:
|
||||
return sendNativeMouseMoveEvent(static_cast<const QNativeMouseMoveEvent &>(event));
|
||||
case QNativeMouseButtonEvent::eventId:
|
||||
return sendNativeMouseButtonEvent(static_cast<const QNativeMouseButtonEvent &>(event));
|
||||
case QNativeMouseDragEvent::eventId:
|
||||
return sendNativeMouseDragEvent(static_cast<const QNativeMouseDragEvent &>(event));
|
||||
case QNativeMouseWheelEvent::eventId:
|
||||
return sendNativeMouseWheelEvent(static_cast<const QNativeMouseWheelEvent &>(event));
|
||||
case QNativeKeyEvent::eventId:
|
||||
return sendNativeKeyEvent(static_cast<const QNativeKeyEvent &>(event));
|
||||
case QNativeModifierEvent::eventId:
|
||||
return sendNativeModifierEvent(static_cast<const QNativeModifierEvent &>(event));
|
||||
case QNativeEvent::eventId:
|
||||
qWarning() << "Warning: Cannot send a pure native event. Use a sub class.";
|
||||
default:
|
||||
return Qt::Native::Failure;
|
||||
}
|
||||
}
|
||||
|
||||
QNativeEvent::QNativeEvent(Qt::KeyboardModifiers modifiers)
|
||||
: modifiers(modifiers){}
|
||||
|
||||
QNativeMouseEvent::QNativeMouseEvent(QPoint pos, Qt::KeyboardModifiers modifiers)
|
||||
: QNativeEvent(modifiers), globalPos(pos){}
|
||||
|
||||
QNativeMouseMoveEvent::QNativeMouseMoveEvent(QPoint pos, Qt::KeyboardModifiers modifiers)
|
||||
: QNativeMouseEvent(pos, modifiers){}
|
||||
|
||||
QNativeMouseButtonEvent::QNativeMouseButtonEvent(QPoint globalPos, Qt::MouseButton button, int clickCount, Qt::KeyboardModifiers modifiers)
|
||||
: QNativeMouseEvent(globalPos, modifiers), button(button), clickCount(clickCount){}
|
||||
|
||||
QNativeMouseDragEvent::QNativeMouseDragEvent(QPoint globalPos, Qt::MouseButton button, Qt::KeyboardModifiers modifiers)
|
||||
: QNativeMouseButtonEvent(globalPos, button, true, modifiers){}
|
||||
|
||||
QNativeMouseWheelEvent::QNativeMouseWheelEvent(QPoint globalPos, int delta, Qt::KeyboardModifiers modifiers)
|
||||
: QNativeMouseEvent(globalPos, modifiers), delta(delta){}
|
||||
|
||||
QNativeKeyEvent::QNativeKeyEvent(int nativeKeyCode, bool press, Qt::KeyboardModifiers modifiers)
|
||||
: QNativeEvent(modifiers), nativeKeyCode(nativeKeyCode), press(press), character(QChar()){}
|
||||
|
||||
QNativeModifierEvent::QNativeModifierEvent(Qt::KeyboardModifiers modifiers, int nativeKeyCode)
|
||||
: QNativeEvent(modifiers), nativeKeyCode(nativeKeyCode){}
|
||||
|
||||
QNativeKeyEvent::QNativeKeyEvent(int nativeKeyCode, bool press, QChar character, Qt::KeyboardModifiers modifiers)
|
||||
: QNativeEvent(modifiers), nativeKeyCode(nativeKeyCode), press(press), character(character){}
|
||||
|
||||
static QString getButtonAsString(const QNativeMouseButtonEvent *e)
|
||||
{
|
||||
switch (e->button){
|
||||
case Qt::LeftButton:
|
||||
return "button = LeftButton";
|
||||
break;
|
||||
case Qt::RightButton:
|
||||
return "button = RightButton";
|
||||
break;
|
||||
case Qt::MiddleButton:
|
||||
return "button = MiddleButton";
|
||||
break;
|
||||
default:
|
||||
return "button = Other";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static QString getModifiersAsString(const QNativeEvent *e)
|
||||
{
|
||||
if (e->modifiers == 0)
|
||||
return "modifiers = none";
|
||||
|
||||
QString tmp = "modifiers = ";
|
||||
if (e->modifiers.testFlag(Qt::ShiftModifier))
|
||||
tmp += "Shift";
|
||||
if (e->modifiers.testFlag(Qt::ControlModifier))
|
||||
tmp += "Control";
|
||||
if (e->modifiers.testFlag(Qt::AltModifier))
|
||||
tmp += "Alt";
|
||||
if (e->modifiers.testFlag(Qt::MetaModifier))
|
||||
tmp += "Meta";
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static QString getPosAsString(QPoint pos)
|
||||
{
|
||||
return QString("QPoint(%1, %2)").arg(pos.x()).arg(pos.y());
|
||||
}
|
||||
|
||||
static QString getBoolAsString(bool b)
|
||||
{
|
||||
return b ? QString("true") : QString("false");
|
||||
}
|
||||
|
||||
QString QNativeMouseMoveEvent::toString() const
|
||||
{
|
||||
return QString("QNativeMouseMoveEvent(globalPos = %1 %2)").arg(getPosAsString(globalPos))
|
||||
.arg(getModifiersAsString(this));
|
||||
}
|
||||
|
||||
QString QNativeMouseButtonEvent::toString() const
|
||||
{
|
||||
return QString("QNativeMouseButtonEvent(globalPos = %1, %2, clickCount = %3, %4)").arg(getPosAsString(globalPos))
|
||||
.arg(getButtonAsString(this)).arg(clickCount).arg(getModifiersAsString(this));
|
||||
}
|
||||
|
||||
QString QNativeMouseDragEvent::toString() const
|
||||
{
|
||||
return QString("QNativeMouseDragEvent(globalPos = %1, %2, clickCount = %3, %4)").arg(getPosAsString(globalPos))
|
||||
.arg(getButtonAsString(this)).arg(clickCount).arg(getModifiersAsString(this));
|
||||
}
|
||||
|
||||
QString QNativeMouseWheelEvent::toString() const
|
||||
{
|
||||
return QString("QNativeMouseWheelEvent(globalPos = %1, delta = %2, %3)").arg(getPosAsString(globalPos))
|
||||
.arg(delta).arg(getModifiersAsString(this));
|
||||
}
|
||||
|
||||
QString QNativeKeyEvent::toString() const
|
||||
{
|
||||
return QString("QNativeKeyEvent(press = %1, native key code = %2, character = %3, %4)").arg(getBoolAsString(press))
|
||||
.arg(nativeKeyCode).arg(character.isPrint() ? character : QString("<no char>"))
|
||||
.arg(getModifiersAsString(this));
|
||||
}
|
||||
|
||||
QString QNativeModifierEvent::toString() const
|
||||
{
|
||||
return QString("QNativeModifierEvent(%1, native key code = %2)").arg(getModifiersAsString(this))
|
||||
.arg(nativeKeyCode);
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug d, QNativeEvent *e)
|
||||
{
|
||||
Q_UNUSED(e);
|
||||
return d << e->toString();
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug d, const QNativeEvent &e)
|
||||
{
|
||||
Q_UNUSED(e);
|
||||
return d << e.toString();
|
||||
}
|
||||
|
||||
QTextStream &operator<<(QTextStream &s, QNativeEvent *e)
|
||||
{
|
||||
return s << e->eventId << ' ' << e->modifiers << " QNativeEvent";
|
||||
}
|
||||
|
||||
QTextStream &operator<<(QTextStream &s, QNativeMouseEvent *e)
|
||||
{
|
||||
return s << e->eventId << ' ' << e->globalPos.x() << ' ' << e->globalPos.y() << ' ' << e->modifiers << ' ' << e->toString();
|
||||
}
|
||||
|
||||
QTextStream &operator<<(QTextStream &s, QNativeMouseMoveEvent *e)
|
||||
{
|
||||
return s << e->eventId << ' ' << e->globalPos.x() << ' ' << e->globalPos.y() << ' ' << e->modifiers << ' ' << e->toString();
|
||||
}
|
||||
|
||||
QTextStream &operator<<(QTextStream &s, QNativeMouseButtonEvent *e)
|
||||
{
|
||||
return s << e->eventId << ' ' << e->globalPos.x() << ' ' << e->globalPos.y() << ' ' << e->button
|
||||
<< ' ' << e->clickCount << ' ' << e->modifiers << ' ' << e->toString();
|
||||
}
|
||||
|
||||
QTextStream &operator<<(QTextStream &s, QNativeMouseDragEvent *e)
|
||||
{
|
||||
return s << e->eventId << ' ' << e->globalPos.x() << ' ' << e->globalPos.y() << ' ' << e->button << ' ' << e->clickCount
|
||||
<< ' ' << e->modifiers << ' ' << e->toString();
|
||||
}
|
||||
|
||||
QTextStream &operator<<(QTextStream &s, QNativeMouseWheelEvent *e)
|
||||
{
|
||||
return s << e->eventId << ' ' << e->globalPos.x() << ' ' << e->globalPos.y() << ' ' << e->delta
|
||||
<< ' ' << e->modifiers << ' ' << e->toString();
|
||||
}
|
||||
|
||||
QTextStream &operator<<(QTextStream &s, QNativeKeyEvent *e)
|
||||
{
|
||||
return s << e->eventId << ' ' << e->press << ' ' << e->nativeKeyCode << ' ' << e->character
|
||||
<< ' ' << e->modifiers << ' ' << e->toString();
|
||||
}
|
||||
|
||||
QTextStream &operator<<(QTextStream &s, QNativeModifierEvent *e)
|
||||
{
|
||||
return s << e->eventId << ' ' << e->modifiers << ' ' << e->nativeKeyCode << ' ' << e->toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QTextStream &operator>>(QTextStream &s, QNativeMouseMoveEvent *e)
|
||||
{
|
||||
// Skip reading eventId.
|
||||
QString humanReadable;
|
||||
int x, y, modifiers;
|
||||
s >> x >> y >> modifiers >> humanReadable;
|
||||
e->globalPos.setX(x);
|
||||
e->globalPos.setY(y);
|
||||
e->modifiers = Qt::KeyboardModifiers(modifiers);
|
||||
return s;
|
||||
}
|
||||
|
||||
QTextStream &operator>>(QTextStream &s, QNativeMouseButtonEvent *e)
|
||||
{
|
||||
// Skip reading eventId.
|
||||
QString humanReadable;
|
||||
int x, y, button, clickCount, modifiers;
|
||||
s >> x >> y >> button >> clickCount >> modifiers >> humanReadable;
|
||||
e->globalPos.setX(x);
|
||||
e->globalPos.setY(y);
|
||||
e->clickCount = clickCount;
|
||||
e->modifiers = Qt::KeyboardModifiers(modifiers);
|
||||
switch (button){
|
||||
case 1:
|
||||
e->button = Qt::LeftButton;
|
||||
break;
|
||||
case 2:
|
||||
e->button = Qt::RightButton;
|
||||
break;
|
||||
case 3:
|
||||
e->button = Qt::MiddleButton;
|
||||
break;
|
||||
default:
|
||||
e->button = Qt::NoButton;
|
||||
break;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
QTextStream &operator>>(QTextStream &s, QNativeMouseDragEvent *e)
|
||||
{
|
||||
// Skip reading eventId.
|
||||
QString humanReadable;
|
||||
int x, y, button, clickCount, modifiers;
|
||||
s >> x >> y >> button >> clickCount >> modifiers >> humanReadable;
|
||||
e->globalPos.setX(x);
|
||||
e->globalPos.setY(y);
|
||||
e->clickCount = clickCount;
|
||||
e->modifiers = Qt::KeyboardModifiers(modifiers);
|
||||
switch (button){
|
||||
case 1:
|
||||
e->button = Qt::LeftButton;
|
||||
break;
|
||||
case 2:
|
||||
e->button = Qt::RightButton;
|
||||
break;
|
||||
case 3:
|
||||
e->button = Qt::MiddleButton;
|
||||
break;
|
||||
default:
|
||||
e->button = Qt::NoButton;
|
||||
break;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
QTextStream &operator>>(QTextStream &s, QNativeMouseWheelEvent *e)
|
||||
{
|
||||
// Skip reading eventId.
|
||||
QString humanReadable;
|
||||
int x, y, modifiers;
|
||||
s >> x >> y >> e->delta >> modifiers >> humanReadable;
|
||||
e->globalPos.setX(x);
|
||||
e->globalPos.setY(y);
|
||||
e->modifiers = Qt::KeyboardModifiers(modifiers);
|
||||
return s;
|
||||
}
|
||||
|
||||
QTextStream &operator>>(QTextStream &s, QNativeKeyEvent *e)
|
||||
{
|
||||
// Skip reading eventId.
|
||||
QString humanReadable;
|
||||
int press, modifiers;
|
||||
QString character;
|
||||
s >> press >> e->nativeKeyCode >> character >> modifiers >> humanReadable;
|
||||
e->press = bool(press);
|
||||
e->character = character[0];
|
||||
e->modifiers = Qt::KeyboardModifiers(modifiers);
|
||||
return s;
|
||||
}
|
||||
|
||||
QTextStream &operator>>(QTextStream &s, QNativeModifierEvent *e)
|
||||
{
|
||||
// Skip reading eventId.
|
||||
QString humanReadable;
|
||||
int modifiers;
|
||||
s >> modifiers >> e->nativeKeyCode >> humanReadable;
|
||||
e->modifiers = Qt::KeyboardModifiers(modifiers);
|
||||
return s;
|
||||
}
|
||||
|
192
tests/auto/other/macnativeevents/qnativeevents.h
Normal file
192
tests/auto/other/macnativeevents/qnativeevents.h
Normal file
@ -0,0 +1,192 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#ifndef Q_NATIVE_INPUT
|
||||
#define Q_NATIVE_INPUT
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Qt {
|
||||
namespace Native {
|
||||
enum Status {Success, Failure};
|
||||
}}
|
||||
QT_END_NAMESPACE
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Declare a set of native events that can be used to communicate with
|
||||
// client applications in an platform independent way
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class QNativeEvent
|
||||
{
|
||||
public:
|
||||
static const int eventId = 1;
|
||||
|
||||
QNativeEvent(Qt::KeyboardModifiers modifiers = Qt::NoModifier);
|
||||
virtual ~QNativeEvent() {}
|
||||
virtual int id() const { return eventId; }
|
||||
virtual QString toString() const = 0;
|
||||
Qt::KeyboardModifiers modifiers; // Yields for mouse events too.
|
||||
};
|
||||
|
||||
class QNativeMouseEvent : public QNativeEvent {
|
||||
public:
|
||||
static const int eventId = 2;
|
||||
|
||||
QNativeMouseEvent() {}
|
||||
QNativeMouseEvent(QPoint globalPos, Qt::KeyboardModifiers modifiers = Qt::NoModifier);
|
||||
virtual ~QNativeMouseEvent() {}
|
||||
virtual int id() const { return eventId; }
|
||||
|
||||
QPoint globalPos;
|
||||
};
|
||||
|
||||
class QNativeMouseMoveEvent : public QNativeMouseEvent {
|
||||
public:
|
||||
static const int eventId = 4;
|
||||
|
||||
QNativeMouseMoveEvent() {}
|
||||
QNativeMouseMoveEvent(QPoint globalPos, Qt::KeyboardModifiers modifiers = Qt::NoModifier);
|
||||
virtual ~QNativeMouseMoveEvent() {}
|
||||
virtual int id() const { return eventId; }
|
||||
virtual QString toString() const;
|
||||
};
|
||||
|
||||
class QNativeMouseButtonEvent : public QNativeMouseEvent {
|
||||
public:
|
||||
static const int eventId = 8;
|
||||
|
||||
QNativeMouseButtonEvent() {}
|
||||
QNativeMouseButtonEvent(QPoint globalPos, Qt::MouseButton button, int clickCount, Qt::KeyboardModifiers modifiers = Qt::NoModifier);
|
||||
virtual ~QNativeMouseButtonEvent() {}
|
||||
virtual int id() const { return eventId; }
|
||||
virtual QString toString() const;
|
||||
|
||||
Qt::MouseButton button;
|
||||
int clickCount;
|
||||
};
|
||||
|
||||
class QNativeMouseDragEvent : public QNativeMouseButtonEvent {
|
||||
public:
|
||||
static const int eventId = 16;
|
||||
|
||||
QNativeMouseDragEvent() {}
|
||||
QNativeMouseDragEvent(QPoint globalPos, Qt::MouseButton button, Qt::KeyboardModifiers modifiers = Qt::NoModifier);
|
||||
virtual ~QNativeMouseDragEvent() {}
|
||||
virtual int id() const { return eventId; }
|
||||
virtual QString toString() const;
|
||||
};
|
||||
|
||||
class QNativeMouseWheelEvent : public QNativeMouseEvent {
|
||||
public:
|
||||
static const int eventId = 32;
|
||||
|
||||
QNativeMouseWheelEvent() {}
|
||||
QNativeMouseWheelEvent(QPoint globalPos, int delta, Qt::KeyboardModifiers modifiers = Qt::NoModifier);
|
||||
virtual ~QNativeMouseWheelEvent() {}
|
||||
virtual int id() const { return eventId; }
|
||||
virtual QString toString() const;
|
||||
|
||||
int delta;
|
||||
};
|
||||
|
||||
class QNativeKeyEvent : public QNativeEvent {
|
||||
public:
|
||||
static const int eventId = 64;
|
||||
|
||||
QNativeKeyEvent() {}
|
||||
QNativeKeyEvent(int nativeKeyCode, bool press, Qt::KeyboardModifiers modifiers = Qt::NoModifier);
|
||||
QNativeKeyEvent(int nativeKeyCode, bool press, QChar character, Qt::KeyboardModifiers modifiers);
|
||||
virtual ~QNativeKeyEvent() {}
|
||||
virtual int id() const { return eventId; }
|
||||
virtual QString toString() const;
|
||||
|
||||
int nativeKeyCode;
|
||||
bool press;
|
||||
QChar character;
|
||||
|
||||
// Some Qt to Native mappings:
|
||||
static int Key_A;
|
||||
static int Key_B;
|
||||
static int Key_C;
|
||||
static int Key_1;
|
||||
static int Key_Backspace;
|
||||
static int Key_Enter;
|
||||
static int Key_Del;
|
||||
};
|
||||
|
||||
class QNativeModifierEvent : public QNativeEvent {
|
||||
public:
|
||||
static const int eventId = 128;
|
||||
|
||||
QNativeModifierEvent(Qt::KeyboardModifiers modifiers = Qt::NoModifier, int nativeKeyCode = 0);
|
||||
virtual ~QNativeModifierEvent() {}
|
||||
virtual int id() const { return eventId; }
|
||||
virtual QString toString() const;
|
||||
|
||||
int nativeKeyCode;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Declare a set of related output / input functions for convenience:
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
QDebug operator<<(QDebug d, QNativeEvent *e);
|
||||
QDebug operator<<(QDebug d, const QNativeEvent &e);
|
||||
|
||||
QTextStream &operator<<(QTextStream &s, QNativeEvent *e);
|
||||
QTextStream &operator<<(QTextStream &s, QNativeMouseEvent *e);
|
||||
QTextStream &operator<<(QTextStream &s, QNativeMouseMoveEvent *e);
|
||||
QTextStream &operator<<(QTextStream &s, QNativeMouseButtonEvent *e);
|
||||
QTextStream &operator<<(QTextStream &s, QNativeMouseDragEvent *e);
|
||||
QTextStream &operator<<(QTextStream &s, QNativeMouseWheelEvent *e);
|
||||
QTextStream &operator<<(QTextStream &s, QNativeKeyEvent *e);
|
||||
QTextStream &operator<<(QTextStream &s, QNativeModifierEvent *e);
|
||||
|
||||
QTextStream &operator>>(QTextStream &s, QNativeMouseMoveEvent *e);
|
||||
QTextStream &operator>>(QTextStream &s, QNativeMouseButtonEvent *e);
|
||||
QTextStream &operator>>(QTextStream &s, QNativeMouseDragEvent *e);
|
||||
QTextStream &operator>>(QTextStream &s, QNativeMouseWheelEvent *e);
|
||||
QTextStream &operator>>(QTextStream &s, QNativeKeyEvent *e);
|
||||
QTextStream &operator>>(QTextStream &s, QNativeModifierEvent *e);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Declare the main class that is supposed to be sub-classed by components
|
||||
// that are to receive native events
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class QNativeInput
|
||||
{
|
||||
public:
|
||||
QNativeInput(bool subscribe = true);
|
||||
virtual ~QNativeInput();
|
||||
|
||||
// Callback methods. Should be implemented by interested sub-classes:
|
||||
void notify(QNativeEvent *event);
|
||||
virtual void nativeEvent(QNativeEvent *event);
|
||||
virtual void nativeMousePressEvent(QNativeMouseButtonEvent *) {}
|
||||
virtual void nativeMouseReleaseEvent(QNativeMouseButtonEvent *) {}
|
||||
virtual void nativeMouseMoveEvent(QNativeMouseMoveEvent *) {}
|
||||
virtual void nativeMouseDragEvent(QNativeMouseDragEvent *) {}
|
||||
virtual void nativeMouseWheelEvent(QNativeMouseWheelEvent *) {}
|
||||
virtual void nativeKeyPressEvent(QNativeKeyEvent *) {}
|
||||
virtual void nativeKeyReleaseEvent(QNativeKeyEvent *) {}
|
||||
virtual void nativeModifierEvent(QNativeModifierEvent *) {}
|
||||
|
||||
// The following methods will differ in implementation from OS to OS:
|
||||
static Qt::Native::Status sendNativeMouseButtonEvent(const QNativeMouseButtonEvent &event);
|
||||
static Qt::Native::Status sendNativeMouseMoveEvent(const QNativeMouseMoveEvent &event);
|
||||
static Qt::Native::Status sendNativeMouseDragEvent(const QNativeMouseDragEvent &event);
|
||||
static Qt::Native::Status sendNativeMouseWheelEvent(const QNativeMouseWheelEvent &event);
|
||||
static Qt::Native::Status sendNativeKeyEvent(const QNativeKeyEvent &event);
|
||||
static Qt::Native::Status sendNativeModifierEvent(const QNativeModifierEvent &event);
|
||||
// sendNativeEvent will NOT differ from OS to OS.
|
||||
static Qt::Native::Status sendNativeEvent(const QNativeEvent &event);
|
||||
|
||||
// The following methods will differ in implementation from OS to OS:
|
||||
Qt::Native::Status subscribeForNativeEvents();
|
||||
Qt::Native::Status unsubscribeForNativeEvents();
|
||||
};
|
||||
|
||||
#endif // Q_NATIVE_INPUT
|
327
tests/auto/other/macnativeevents/qnativeevents_mac.cpp
Normal file
327
tests/auto/other/macnativeevents/qnativeevents_mac.cpp
Normal file
@ -0,0 +1,327 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "qnativeevents.h"
|
||||
#include <CoreGraphics/CoreGraphics.h>
|
||||
#include <QtCore>
|
||||
|
||||
// ************************************************************
|
||||
// Quartz
|
||||
// ************************************************************
|
||||
|
||||
static Qt::KeyboardModifiers getModifiersFromQuartzEvent(CGEventRef inEvent)
|
||||
{
|
||||
Qt::KeyboardModifiers m;
|
||||
CGEventFlags flags = CGEventGetFlags(inEvent);
|
||||
if (flags & kCGEventFlagMaskShift || flags & kCGEventFlagMaskAlphaShift)
|
||||
m |= Qt::ShiftModifier;
|
||||
if (flags & kCGEventFlagMaskControl)
|
||||
m |= Qt::ControlModifier;
|
||||
if (flags & kCGEventFlagMaskAlternate)
|
||||
m |= Qt::AltModifier;
|
||||
if (flags & kCGEventFlagMaskCommand)
|
||||
m |= Qt::MetaModifier;
|
||||
return m;
|
||||
}
|
||||
|
||||
static void setModifiersFromQNativeEvent(CGEventRef inEvent, const QNativeEvent &event)
|
||||
{
|
||||
CGEventFlags flags = CGEventFlags(0);
|
||||
if (event.modifiers.testFlag(Qt::ShiftModifier))
|
||||
flags = CGEventFlags(flags | kCGEventFlagMaskShift);
|
||||
if (event.modifiers.testFlag(Qt::ControlModifier))
|
||||
flags = CGEventFlags(flags | kCGEventFlagMaskControl);
|
||||
if (event.modifiers.testFlag(Qt::AltModifier))
|
||||
flags = CGEventFlags(flags | kCGEventFlagMaskAlternate);
|
||||
if (event.modifiers.testFlag(Qt::MetaModifier))
|
||||
flags = CGEventFlags(flags | kCGEventFlagMaskCommand);
|
||||
CGEventSetFlags(inEvent, flags);
|
||||
}
|
||||
|
||||
static QPoint getMouseLocationFromQuartzEvent(CGEventRef inEvent)
|
||||
{
|
||||
CGPoint pos = CGEventGetLocation(inEvent);
|
||||
QPoint tmp;
|
||||
tmp.setX(pos.x);
|
||||
tmp.setY(pos.y);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static QChar getCharFromQuartzEvent(CGEventRef inEvent)
|
||||
{
|
||||
UniCharCount count = 0;
|
||||
UniChar c;
|
||||
CGEventKeyboardGetUnicodeString(inEvent, 1, &count, &c);
|
||||
return QChar(c);
|
||||
}
|
||||
|
||||
static CGEventRef EventHandler_Quartz(CGEventTapProxy proxy, CGEventType type, CGEventRef inEvent, void *refCon)
|
||||
{
|
||||
Q_UNUSED(proxy);
|
||||
QNativeInput *nativeInput = static_cast<QNativeInput *>(refCon);
|
||||
switch (type){
|
||||
case kCGEventKeyDown:{
|
||||
QNativeKeyEvent e;
|
||||
e.modifiers = getModifiersFromQuartzEvent(inEvent);
|
||||
e.nativeKeyCode = CGEventGetIntegerValueField(inEvent, kCGKeyboardEventKeycode);
|
||||
e.character = getCharFromQuartzEvent(inEvent);
|
||||
e.press = true;
|
||||
nativeInput->notify(&e);
|
||||
break;
|
||||
}
|
||||
case kCGEventKeyUp:{
|
||||
QNativeKeyEvent e;
|
||||
e.modifiers = getModifiersFromQuartzEvent(inEvent);
|
||||
e.nativeKeyCode = CGEventGetIntegerValueField(inEvent, kCGKeyboardEventKeycode);
|
||||
e.character = getCharFromQuartzEvent(inEvent);
|
||||
e.press = false;
|
||||
nativeInput->notify(&e);
|
||||
break;
|
||||
}
|
||||
case kCGEventLeftMouseDown:{
|
||||
QNativeMouseButtonEvent e;
|
||||
e.modifiers = getModifiersFromQuartzEvent(inEvent);
|
||||
e.globalPos = getMouseLocationFromQuartzEvent(inEvent);
|
||||
e.clickCount = CGEventGetIntegerValueField(inEvent, kCGMouseEventClickState);
|
||||
e.button = Qt::LeftButton;
|
||||
nativeInput->notify(&e);
|
||||
break;
|
||||
}
|
||||
case kCGEventLeftMouseUp:{
|
||||
QNativeMouseButtonEvent e;
|
||||
e.modifiers = getModifiersFromQuartzEvent(inEvent);
|
||||
e.globalPos = getMouseLocationFromQuartzEvent(inEvent);
|
||||
e.clickCount = 0;
|
||||
e.button = Qt::LeftButton;
|
||||
nativeInput->notify(&e);
|
||||
break;
|
||||
}
|
||||
case kCGEventRightMouseDown:{
|
||||
QNativeMouseButtonEvent e;
|
||||
e.modifiers = getModifiersFromQuartzEvent(inEvent);
|
||||
e.globalPos = getMouseLocationFromQuartzEvent(inEvent);
|
||||
e.clickCount = CGEventGetIntegerValueField(inEvent, kCGMouseEventClickState);
|
||||
e.button = Qt::RightButton;
|
||||
nativeInput->notify(&e);
|
||||
break;
|
||||
}
|
||||
case kCGEventRightMouseUp:{
|
||||
QNativeMouseButtonEvent e;
|
||||
e.modifiers = getModifiersFromQuartzEvent(inEvent);
|
||||
e.globalPos = getMouseLocationFromQuartzEvent(inEvent);
|
||||
e.clickCount = 0;
|
||||
e.button = Qt::RightButton;
|
||||
nativeInput->notify(&e);
|
||||
break;
|
||||
}
|
||||
case kCGEventMouseMoved:{
|
||||
QNativeMouseMoveEvent e;
|
||||
e.modifiers = getModifiersFromQuartzEvent(inEvent);
|
||||
e.globalPos = getMouseLocationFromQuartzEvent(inEvent);
|
||||
nativeInput->notify(&e);
|
||||
break;
|
||||
}
|
||||
case kCGEventLeftMouseDragged:{
|
||||
QNativeMouseDragEvent e;
|
||||
e.modifiers = getModifiersFromQuartzEvent(inEvent);
|
||||
e.globalPos = getMouseLocationFromQuartzEvent(inEvent);
|
||||
e.clickCount = CGEventGetIntegerValueField(inEvent, kCGMouseEventClickState);
|
||||
e.button = Qt::LeftButton;
|
||||
nativeInput->notify(&e);
|
||||
break;
|
||||
}
|
||||
case kCGEventScrollWheel:{
|
||||
QNativeMouseWheelEvent e;
|
||||
e.modifiers = getModifiersFromQuartzEvent(inEvent);
|
||||
e.delta = CGEventGetIntegerValueField(inEvent, kCGScrollWheelEventDeltaAxis1);
|
||||
e.globalPos = getMouseLocationFromQuartzEvent(inEvent);
|
||||
nativeInput->notify(&e);
|
||||
break;
|
||||
}
|
||||
case kCGEventFlagsChanged:{
|
||||
QNativeModifierEvent e;
|
||||
e.modifiers = getModifiersFromQuartzEvent(inEvent);
|
||||
e.nativeKeyCode = CGEventGetIntegerValueField(inEvent, kCGKeyboardEventKeycode);
|
||||
nativeInput->notify(&e);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return inEvent;
|
||||
}
|
||||
|
||||
Qt::Native::Status insertEventHandler_Quartz(QNativeInput *nativeInput)
|
||||
{
|
||||
uid_t uid = geteuid();
|
||||
if (uid != 0)
|
||||
qWarning("MacNativeEvents: You must be root to listen for key events!");
|
||||
|
||||
CFMachPortRef port = CGEventTapCreate(kCGHIDEventTap,
|
||||
kCGHeadInsertEventTap, kCGEventTapOptionListenOnly,
|
||||
kCGEventMaskForAllEvents, EventHandler_Quartz, nativeInput);
|
||||
|
||||
CFRunLoopSourceRef eventSrc = CFMachPortCreateRunLoopSource(NULL, port, 0);
|
||||
CFRunLoopAddSource(CFRunLoopGetMain(), eventSrc, kCFRunLoopCommonModes);
|
||||
|
||||
return Qt::Native::Success;
|
||||
}
|
||||
|
||||
Qt::Native::Status removeEventHandler_Quartz()
|
||||
{
|
||||
return Qt::Native::Success; // ToDo:
|
||||
}
|
||||
|
||||
Qt::Native::Status sendNativeKeyEvent_Quartz(const QNativeKeyEvent &event)
|
||||
{
|
||||
CGEventRef e = CGEventCreateKeyboardEvent(0, (uint)event.nativeKeyCode, event.press);
|
||||
setModifiersFromQNativeEvent(e, event);
|
||||
CGEventPost(kCGHIDEventTap, e);
|
||||
CFRelease(e);
|
||||
return Qt::Native::Success;
|
||||
}
|
||||
|
||||
Qt::Native::Status sendNativeMouseMoveEvent_Quartz(const QNativeMouseMoveEvent &event)
|
||||
{
|
||||
CGPoint pos;
|
||||
pos.x = event.globalPos.x();
|
||||
pos.y = event.globalPos.y();
|
||||
|
||||
CGEventRef e = CGEventCreateMouseEvent(0, kCGEventMouseMoved, pos, kCGMouseButtonLeft /* ignored */);
|
||||
setModifiersFromQNativeEvent(e, event);
|
||||
CGEventPost(kCGHIDEventTap, e);
|
||||
CFRelease(e);
|
||||
return Qt::Native::Success;
|
||||
}
|
||||
|
||||
Qt::Native::Status sendNativeMouseButtonEvent_Quartz(const QNativeMouseButtonEvent &event)
|
||||
{
|
||||
CGPoint pos;
|
||||
pos.x = event.globalPos.x();
|
||||
pos.y = event.globalPos.y();
|
||||
|
||||
CGEventType type = kCGEventNull;
|
||||
if (event.button == Qt::LeftButton)
|
||||
type = (event.clickCount > 0) ? kCGEventLeftMouseDown : kCGEventLeftMouseUp;
|
||||
else if (event.button == Qt::RightButton)
|
||||
type = (event.clickCount > 0) ? kCGEventRightMouseDown : kCGEventRightMouseUp;
|
||||
else
|
||||
type = (event.clickCount > 0) ? kCGEventOtherMouseDown : kCGEventOtherMouseUp;
|
||||
|
||||
// The mouseButton argument to CGEventCreateMouseEvent() is ignored unless the type
|
||||
// is kCGEventOtherSomething, so defaulting to kCGMouseButtonLeft is fine.
|
||||
CGMouseButton mouseButton = (type == kCGEventOtherMouseDown || type == kCGEventOtherMouseUp) ?
|
||||
kCGMouseButtonCenter : kCGMouseButtonLeft;
|
||||
|
||||
CGEventRef e = CGEventCreateMouseEvent(0, type, pos, mouseButton);
|
||||
setModifiersFromQNativeEvent(e, event);
|
||||
CGEventSetIntegerValueField(e, kCGMouseEventClickState, event.clickCount);
|
||||
CGEventPost(kCGHIDEventTap, e);
|
||||
CFRelease(e);
|
||||
return Qt::Native::Success;
|
||||
}
|
||||
|
||||
Qt::Native::Status sendNativeMouseDragEvent_Quartz(const QNativeMouseDragEvent &event)
|
||||
{
|
||||
CGPoint pos;
|
||||
pos.x = event.globalPos.x();
|
||||
pos.y = event.globalPos.y();
|
||||
|
||||
CGEventType type = kCGEventNull;
|
||||
if (event.button == Qt::LeftButton)
|
||||
type = kCGEventLeftMouseDragged;
|
||||
else if (event.button == Qt::RightButton)
|
||||
type = kCGEventRightMouseDragged;
|
||||
else
|
||||
type = kCGEventOtherMouseDragged;
|
||||
|
||||
// The mouseButton argument to CGEventCreateMouseEvent() is ignored unless the type
|
||||
// is kCGEventOtherSomething, so defaulting to kCGMouseButtonLeft is fine.
|
||||
CGMouseButton mouseButton = type == kCGEventOtherMouseDragged ? kCGMouseButtonCenter : kCGMouseButtonLeft;
|
||||
|
||||
CGEventRef e = CGEventCreateMouseEvent(0, type, pos, mouseButton);
|
||||
setModifiersFromQNativeEvent(e, event);
|
||||
CGEventPost(kCGHIDEventTap, e);
|
||||
CFRelease(e);
|
||||
return Qt::Native::Success;
|
||||
}
|
||||
|
||||
Qt::Native::Status sendNativeMouseWheelEvent_Quartz(const QNativeMouseWheelEvent &event)
|
||||
{
|
||||
CGPoint pos;
|
||||
pos.x = event.globalPos.x();
|
||||
pos.y = event.globalPos.y();
|
||||
|
||||
CGEventRef e = CGEventCreateScrollWheelEvent(0, kCGScrollEventUnitPixel, 1, 0);
|
||||
CGEventSetIntegerValueField(e, kCGScrollWheelEventDeltaAxis1, event.delta);
|
||||
CGEventSetLocation(e, pos);
|
||||
setModifiersFromQNativeEvent(e, event);
|
||||
CGEventPost(kCGHIDEventTap, e);
|
||||
CFRelease(e);
|
||||
|
||||
return Qt::Native::Success;
|
||||
}
|
||||
|
||||
Qt::Native::Status sendNativeModifierEvent_Quartz(const QNativeModifierEvent &event)
|
||||
{
|
||||
CGEventRef e = CGEventCreateKeyboardEvent(0, (uint)event.nativeKeyCode, 0);
|
||||
CGEventSetType(e, kCGEventFlagsChanged);
|
||||
setModifiersFromQNativeEvent(e, event);
|
||||
CGEventPost(kCGHIDEventTap, e);
|
||||
CFRelease(e);
|
||||
return Qt::Native::Success;
|
||||
}
|
||||
|
||||
// ************************************************************
|
||||
// QNativeInput methods:
|
||||
// ************************************************************
|
||||
|
||||
Qt::Native::Status QNativeInput::sendNativeMouseButtonEvent(const QNativeMouseButtonEvent &event)
|
||||
{
|
||||
return sendNativeMouseButtonEvent_Quartz(event);
|
||||
}
|
||||
|
||||
Qt::Native::Status QNativeInput::sendNativeMouseMoveEvent(const QNativeMouseMoveEvent &event)
|
||||
{
|
||||
return sendNativeMouseMoveEvent_Quartz(event);
|
||||
}
|
||||
|
||||
Qt::Native::Status QNativeInput::sendNativeMouseDragEvent(const QNativeMouseDragEvent &event)
|
||||
{
|
||||
return sendNativeMouseDragEvent_Quartz(event);
|
||||
}
|
||||
|
||||
Qt::Native::Status QNativeInput::sendNativeMouseWheelEvent(const QNativeMouseWheelEvent &event)
|
||||
{
|
||||
return sendNativeMouseWheelEvent_Quartz(event);
|
||||
}
|
||||
|
||||
Qt::Native::Status QNativeInput::sendNativeKeyEvent(const QNativeKeyEvent &event)
|
||||
{
|
||||
return sendNativeKeyEvent_Quartz(event);
|
||||
}
|
||||
|
||||
Qt::Native::Status QNativeInput::sendNativeModifierEvent(const QNativeModifierEvent &event)
|
||||
{
|
||||
return sendNativeModifierEvent_Quartz(event);
|
||||
}
|
||||
|
||||
Qt::Native::Status QNativeInput::subscribeForNativeEvents()
|
||||
{
|
||||
return insertEventHandler_Quartz(this);
|
||||
}
|
||||
|
||||
Qt::Native::Status QNativeInput::unsubscribeForNativeEvents()
|
||||
{
|
||||
return removeEventHandler_Quartz();
|
||||
}
|
||||
|
||||
// Some Qt to Mac mappings:
|
||||
int QNativeKeyEvent::Key_A = 0;
|
||||
int QNativeKeyEvent::Key_B = 11;
|
||||
int QNativeKeyEvent::Key_C = 8;
|
||||
int QNativeKeyEvent::Key_1 = 18;
|
||||
int QNativeKeyEvent::Key_Backspace = 51;
|
||||
int QNativeKeyEvent::Key_Enter = 36;
|
||||
int QNativeKeyEvent::Key_Del = 117;
|
||||
|
490
tests/auto/other/macnativeevents/tst_macnativeevents.cpp
Normal file
490
tests/auto/other/macnativeevents/tst_macnativeevents.cpp
Normal file
@ -0,0 +1,490 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include <QApplication>
|
||||
#include <QWidget>
|
||||
#include <QDialog>
|
||||
#include <QPushButton>
|
||||
#include <QTest>
|
||||
|
||||
#include "qnativeevents.h"
|
||||
#include "nativeeventlist.h"
|
||||
#include "expectedeventlist.h"
|
||||
|
||||
QT_USE_NAMESPACE
|
||||
|
||||
// Unicode code points for the glyphs associated with these keys
|
||||
// Defined by Carbon headers but not anywhere in Cocoa
|
||||
static const int kControlUnicode = 0x2303;
|
||||
static const int kCommandUnicode = 0x2318;
|
||||
|
||||
class tst_MacNativeEvents : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private slots:
|
||||
void testMouseMoveLocation();
|
||||
void testPushButtonPressRelease();
|
||||
void testMouseLeftDoubleClick();
|
||||
void stressTestMouseLeftDoubleClick();
|
||||
void testMouseDragInside();
|
||||
void testMouseDragOutside();
|
||||
void testMouseDragToNonClientArea();
|
||||
void testDragWindow();
|
||||
void testMouseEnter();
|
||||
void testChildDialogInFrontOfModalParent();
|
||||
// void testChildWindowInFrontOfParentWindow();
|
||||
// void testChildToolWindowInFrontOfChildNormalWindow();
|
||||
void testChildWindowInFrontOfStaysOnTopParentWindow();
|
||||
void testKeyPressOnToplevel();
|
||||
void testModifierShift();
|
||||
void testModifierAlt();
|
||||
void testModifierCtrl();
|
||||
void testModifierCtrlWithDontSwapCtrlAndMeta();
|
||||
};
|
||||
|
||||
void tst_MacNativeEvents::testMouseMoveLocation()
|
||||
{
|
||||
QWidget w;
|
||||
w.setMouseTracking(true);
|
||||
w.show();
|
||||
QPoint p = w.geometry().center();
|
||||
|
||||
NativeEventList native;
|
||||
native.append(new QNativeMouseMoveEvent(p, Qt::NoModifier));
|
||||
|
||||
ExpectedEventList expected(&w);
|
||||
expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(p), p, Qt::NoButton, Qt::NoButton, Qt::NoModifier));
|
||||
|
||||
native.play();
|
||||
QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
|
||||
}
|
||||
|
||||
void tst_MacNativeEvents::testPushButtonPressRelease()
|
||||
{
|
||||
// Check that a native mouse press and release generates the
|
||||
// same qevents on a pushbutton:
|
||||
QPushButton w("click me");
|
||||
w.show();
|
||||
QPoint p = w.geometry().center();
|
||||
|
||||
NativeEventList native;
|
||||
native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 1, Qt::NoModifier));
|
||||
native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 0, Qt::NoModifier));
|
||||
|
||||
ExpectedEventList expected(&w);
|
||||
expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier));
|
||||
expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::NoButton, Qt::NoModifier));
|
||||
|
||||
native.play();
|
||||
QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
|
||||
}
|
||||
|
||||
void tst_MacNativeEvents::testMouseLeftDoubleClick()
|
||||
{
|
||||
// Check that a native double click makes
|
||||
// the test widget receive a press-release-click-release:
|
||||
QWidget w;
|
||||
w.show();
|
||||
QPoint p = w.geometry().center();
|
||||
|
||||
NativeEventList native;
|
||||
native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 1, Qt::NoModifier));
|
||||
native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 0, Qt::NoModifier));
|
||||
native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 2, Qt::NoModifier));
|
||||
native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 0, Qt::NoModifier));
|
||||
|
||||
ExpectedEventList expected(&w);
|
||||
expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier));
|
||||
expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::NoButton, Qt::NoModifier));
|
||||
expected.append(new QMouseEvent(QEvent::MouseButtonDblClick, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier));
|
||||
expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::NoButton, Qt::NoModifier));
|
||||
|
||||
native.play();
|
||||
QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
|
||||
}
|
||||
|
||||
void tst_MacNativeEvents::stressTestMouseLeftDoubleClick()
|
||||
{
|
||||
// Check that multiple, fast, double clicks makes
|
||||
// the test widget receive correct click events
|
||||
QWidget w;
|
||||
w.show();
|
||||
QPoint p = w.geometry().center();
|
||||
|
||||
NativeEventList native;
|
||||
ExpectedEventList expected(&w);
|
||||
|
||||
for (int i=0; i<10; ++i){
|
||||
native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 1, Qt::NoModifier));
|
||||
native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 0, Qt::NoModifier));
|
||||
native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 2, Qt::NoModifier));
|
||||
native.append(new QNativeMouseButtonEvent(p, Qt::LeftButton, 0, Qt::NoModifier));
|
||||
|
||||
expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier));
|
||||
expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::NoButton, Qt::NoModifier));
|
||||
expected.append(new QMouseEvent(QEvent::MouseButtonDblClick, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier));
|
||||
expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p), p, Qt::LeftButton, Qt::NoButton, Qt::NoModifier));
|
||||
}
|
||||
|
||||
native.play();
|
||||
QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
|
||||
}
|
||||
|
||||
void tst_MacNativeEvents::testMouseDragInside()
|
||||
{
|
||||
// Check that a mouse drag inside a widget
|
||||
// will cause press-move-release events to be delivered
|
||||
QWidget w;
|
||||
w.show();
|
||||
QPoint p1 = w.geometry().center();
|
||||
QPoint p2 = p1 - QPoint(10, 0);
|
||||
QPoint p3 = p1 - QPoint(20, 0);
|
||||
QPoint p4 = p1 - QPoint(30, 0);
|
||||
|
||||
NativeEventList native;
|
||||
native.append(new QNativeMouseButtonEvent(p1, Qt::LeftButton, 1, Qt::NoModifier));
|
||||
native.append(new QNativeMouseDragEvent(p2, Qt::LeftButton, Qt::NoModifier));
|
||||
native.append(new QNativeMouseDragEvent(p3, Qt::LeftButton, Qt::NoModifier));
|
||||
native.append(new QNativeMouseButtonEvent(p4, Qt::LeftButton, 0, Qt::NoModifier));
|
||||
|
||||
ExpectedEventList expected(&w);
|
||||
expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(p1), p1, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier));
|
||||
expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(p2), p2, Qt::NoButton, Qt::LeftButton, Qt::NoModifier));
|
||||
expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(p3), p3, Qt::NoButton, Qt::LeftButton, Qt::NoModifier));
|
||||
expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(p4), p4, Qt::LeftButton, Qt::NoButton, Qt::NoModifier));
|
||||
|
||||
native.play();
|
||||
QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
|
||||
}
|
||||
|
||||
void tst_MacNativeEvents::testMouseDragOutside()
|
||||
{
|
||||
// Check that if we drag the mouse from inside the
|
||||
// widget, and release it outside, we still get mouse move
|
||||
// and release events when the mouse is outside the widget.
|
||||
QWidget w;
|
||||
w.show();
|
||||
QPoint inside1 = w.geometry().center();
|
||||
QPoint inside2 = inside1 - QPoint(10, 0);
|
||||
QPoint outside1 = w.geometry().topLeft() - QPoint(50, 0);
|
||||
QPoint outside2 = outside1 - QPoint(10, 0);
|
||||
|
||||
NativeEventList native;
|
||||
native.append(new QNativeMouseButtonEvent(inside1, Qt::LeftButton, 1, Qt::NoModifier));
|
||||
native.append(new QNativeMouseDragEvent(inside2, Qt::LeftButton, Qt::NoModifier));
|
||||
native.append(new QNativeMouseDragEvent(outside1, Qt::LeftButton, Qt::NoModifier));
|
||||
native.append(new QNativeMouseButtonEvent(outside2, Qt::LeftButton, 0, Qt::NoModifier));
|
||||
|
||||
ExpectedEventList expected(&w);
|
||||
expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(inside1), inside1, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier));
|
||||
expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(inside2), inside2, Qt::NoButton, Qt::LeftButton, Qt::NoModifier));
|
||||
expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(outside1), outside1, Qt::NoButton, Qt::LeftButton, Qt::NoModifier));
|
||||
expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(outside2), outside2, Qt::LeftButton, Qt::NoButton, Qt::NoModifier));
|
||||
|
||||
native.play();
|
||||
QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
|
||||
}
|
||||
|
||||
void tst_MacNativeEvents::testMouseDragToNonClientArea()
|
||||
{
|
||||
// Check that if we drag the mouse from inside the
|
||||
// widget, and release it on the title bar, we still get mouse move
|
||||
// and release events when the mouse is on the title bar
|
||||
QWidget w;
|
||||
w.show();
|
||||
QPoint inside1 = w.geometry().center();
|
||||
QPoint inside2 = inside1 - QPoint(10, 0);
|
||||
QPoint titlebar1 = w.geometry().topLeft() - QPoint(-100, 10);
|
||||
QPoint titlebar2 = titlebar1 - QPoint(10, 0);
|
||||
|
||||
NativeEventList native;
|
||||
native.append(new QNativeMouseButtonEvent(inside1, Qt::LeftButton, 1, Qt::NoModifier));
|
||||
native.append(new QNativeMouseDragEvent(inside2, Qt::LeftButton, Qt::NoModifier));
|
||||
native.append(new QNativeMouseDragEvent(titlebar1, Qt::LeftButton, Qt::NoModifier));
|
||||
native.append(new QNativeMouseButtonEvent(titlebar2, Qt::LeftButton, 0, Qt::NoModifier));
|
||||
|
||||
ExpectedEventList expected(&w);
|
||||
expected.append(new QMouseEvent(QEvent::MouseButtonPress, w.mapFromGlobal(inside1), inside1, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier));
|
||||
expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(inside2), inside2, Qt::NoButton, Qt::LeftButton, Qt::NoModifier));
|
||||
expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(titlebar1), titlebar1, Qt::NoButton, Qt::LeftButton, Qt::NoModifier));
|
||||
expected.append(new QMouseEvent(QEvent::MouseButtonRelease, w.mapFromGlobal(titlebar2), titlebar2, Qt::LeftButton, Qt::NoButton, Qt::NoModifier));
|
||||
|
||||
native.play();
|
||||
QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
|
||||
}
|
||||
|
||||
void tst_MacNativeEvents::testDragWindow()
|
||||
{
|
||||
// Check that if we drag the mouse from inside the
|
||||
// widgets title bar, we get a move event on the window
|
||||
QWidget w;
|
||||
w.show();
|
||||
QPoint titlebar = w.geometry().topLeft() - QPoint(-100, 10);
|
||||
QPoint moveTo = titlebar + QPoint(100, 0);
|
||||
|
||||
NativeEventList native;
|
||||
native.append(new QNativeMouseButtonEvent(titlebar, Qt::LeftButton, 1, Qt::NoModifier));
|
||||
native.append(new QNativeMouseDragEvent(moveTo, Qt::LeftButton, Qt::NoModifier));
|
||||
native.append(500, new QNativeMouseButtonEvent(moveTo, Qt::LeftButton, 0, Qt::NoModifier));
|
||||
|
||||
ExpectedEventList expected(&w);
|
||||
expected.append(new QMouseEvent(QEvent::NonClientAreaMouseButtonPress, w.mapFromGlobal(titlebar), titlebar, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier));
|
||||
expected.append(new QMouseEvent(QEvent::NonClientAreaMouseButtonRelease, w.mapFromGlobal(titlebar), moveTo, Qt::LeftButton, Qt::NoButton, Qt::NoModifier));
|
||||
|
||||
native.play();
|
||||
QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
|
||||
}
|
||||
|
||||
void tst_MacNativeEvents::testMouseEnter()
|
||||
{
|
||||
// When a mouse enters a widget, both a mouse enter events and a
|
||||
// mouse move event should be sent. Let's test this:
|
||||
QWidget w;
|
||||
w.setMouseTracking(true);
|
||||
w.show();
|
||||
QPoint outside = w.geometry().topLeft() - QPoint(50, 0);
|
||||
QPoint inside = w.geometry().center();
|
||||
|
||||
NativeEventList native;
|
||||
native.append(new QNativeMouseMoveEvent(outside, Qt::NoModifier));
|
||||
native.append(new QNativeMouseMoveEvent(inside, Qt::NoModifier));
|
||||
|
||||
ExpectedEventList expected(&w);
|
||||
expected.append(new QEvent(QEvent::Enter));
|
||||
expected.append(new QMouseEvent(QEvent::MouseMove, w.mapFromGlobal(inside), inside, Qt::NoButton, Qt::NoButton, Qt::NoModifier));
|
||||
|
||||
native.play();
|
||||
QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
|
||||
}
|
||||
|
||||
void tst_MacNativeEvents::testChildDialogInFrontOfModalParent()
|
||||
{
|
||||
QSKIP("Modal dialog causes later tests to fail, see QTBUG-58474");
|
||||
|
||||
// Test that a child dialog of a modal parent dialog is
|
||||
// in front of the parent, and active:
|
||||
QDialog parent;
|
||||
parent.setWindowModality(Qt::ApplicationModal);
|
||||
QDialog child(&parent);
|
||||
QPushButton button("close", &child);
|
||||
connect(&button, SIGNAL(clicked()), &child, SLOT(close()));
|
||||
parent.show();
|
||||
child.show();
|
||||
QPoint inside = button.mapToGlobal(button.geometry().center());
|
||||
|
||||
// Post a click on the button to close the child dialog:
|
||||
NativeEventList native;
|
||||
native.append(new QNativeMouseButtonEvent(inside, Qt::LeftButton, 1, Qt::NoModifier));
|
||||
native.append(new QNativeMouseButtonEvent(inside, Qt::LeftButton, 0, Qt::NoModifier));
|
||||
|
||||
native.play();
|
||||
QTest::qWait(100);
|
||||
QVERIFY(!child.isVisible());
|
||||
}
|
||||
|
||||
#if 0
|
||||
// This test is disabled as of Qt-4.7.4 because we cannot do it
|
||||
// unless we use the Cocoa sub window API. But using that opens up
|
||||
// a world of side effects that we cannot live with. So we rather
|
||||
// not support child-on-top-of-parent instead.
|
||||
void tst_MacNativeEvents::testChildWindowInFrontOfParentWindow()
|
||||
{
|
||||
// Test that a child window always stacks in front of its parent window.
|
||||
// Do this by first click on the parent, then on the child window button.
|
||||
QWidget parent;
|
||||
QPushButton child("a button", &parent);
|
||||
child.setWindowFlags(Qt::Window);
|
||||
connect(&child, SIGNAL(clicked()), &child, SLOT(close()));
|
||||
parent.show();
|
||||
child.show();
|
||||
|
||||
QPoint parent_p = parent.geometry().bottomLeft() + QPoint(20, -20);
|
||||
QPoint child_p = child.geometry().center();
|
||||
|
||||
NativeEventList native;
|
||||
native.append(new QNativeMouseButtonEvent(parent_p, Qt::LeftButton, 1, Qt::NoModifier));
|
||||
native.append(new QNativeMouseButtonEvent(parent_p, Qt::LeftButton, 0, Qt::NoModifier));
|
||||
native.append(new QNativeMouseButtonEvent(child_p, Qt::LeftButton, 1, Qt::NoModifier));
|
||||
native.append(new QNativeMouseButtonEvent(child_p, Qt::LeftButton, 0, Qt::NoModifier));
|
||||
|
||||
native.play();
|
||||
QTest::qWait(100);
|
||||
QVERIFY(!child.isVisible());
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This test can be enabled once setStackingOrder has been fixed in qwidget_mac.mm
|
||||
void tst_MacNativeEvents::testChildToolWindowInFrontOfChildNormalWindow()
|
||||
{
|
||||
// Test that a child tool window always stacks in front of normal sibling windows.
|
||||
// Do this by first click on the sibling, then on the tool window button.
|
||||
QWidget parent;
|
||||
QWidget normalChild(&parent, Qt::Window);
|
||||
QPushButton toolChild("a button", &parent);
|
||||
toolChild.setWindowFlags(Qt::Tool);
|
||||
connect(&toolChild, SIGNAL(clicked()), &toolChild, SLOT(close()));
|
||||
parent.show();
|
||||
normalChild.show();
|
||||
toolChild.show();
|
||||
|
||||
QPoint normalChild_p = normalChild.geometry().bottomLeft() + QPoint(20, -20);
|
||||
QPoint toolChild_p = toolChild.geometry().center();
|
||||
|
||||
NativeEventList native;
|
||||
native.append(new QNativeMouseButtonEvent(normalChild_p, Qt::LeftButton, 1, Qt::NoModifier));
|
||||
native.append(new QNativeMouseButtonEvent(normalChild_p, Qt::LeftButton, 0, Qt::NoModifier));
|
||||
native.append(new QNativeMouseButtonEvent(toolChild_p, Qt::LeftButton, 1, Qt::NoModifier));
|
||||
native.append(new QNativeMouseButtonEvent(toolChild_p, Qt::LeftButton, 0, Qt::NoModifier));
|
||||
|
||||
native.play();
|
||||
QTest::qWait(100);
|
||||
QVERIFY(!toolChild.isVisible());
|
||||
}
|
||||
*/
|
||||
void tst_MacNativeEvents::testChildWindowInFrontOfStaysOnTopParentWindow()
|
||||
{
|
||||
// Test that a child window stacks on top of a stays-on-top parent.
|
||||
QWidget parent(0, Qt::WindowStaysOnTopHint);
|
||||
QPushButton button("close", &parent);
|
||||
button.setWindowFlags(Qt::Window);
|
||||
connect(&button, SIGNAL(clicked()), &button, SLOT(close()));
|
||||
parent.show();
|
||||
button.show();
|
||||
QPoint inside = button.geometry().center();
|
||||
|
||||
// Post a click on the button to close the child dialog:
|
||||
NativeEventList native;
|
||||
native.append(new QNativeMouseButtonEvent(inside, Qt::LeftButton, 1, Qt::NoModifier));
|
||||
native.append(new QNativeMouseButtonEvent(inside, Qt::LeftButton, 0, Qt::NoModifier));
|
||||
|
||||
native.play();
|
||||
QTest::qWait(100);
|
||||
QVERIFY(!button.isVisible());
|
||||
}
|
||||
|
||||
void tst_MacNativeEvents::testKeyPressOnToplevel()
|
||||
{
|
||||
// Check that we receive keyevents for
|
||||
// toplevel widgets. For leagacy reasons, and according to Qt on
|
||||
// other platforms (carbon port + linux), we should get these events
|
||||
// even when the focus policy is set to Qt::NoFocus when there is no
|
||||
// other focus widget on screen:
|
||||
QWidget w;
|
||||
w.show();
|
||||
|
||||
NativeEventList native;
|
||||
native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::NoModifier));
|
||||
native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::NoModifier));
|
||||
|
||||
ExpectedEventList expected(&w);
|
||||
expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier));
|
||||
expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::NoModifier));
|
||||
|
||||
native.play();
|
||||
QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
|
||||
}
|
||||
|
||||
void tst_MacNativeEvents::testModifierShift()
|
||||
{
|
||||
QWidget w;
|
||||
w.show();
|
||||
|
||||
NativeEventList native;
|
||||
native.append(new QNativeModifierEvent(Qt::ShiftModifier));
|
||||
native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::ShiftModifier));
|
||||
native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::ShiftModifier));
|
||||
native.append(new QNativeModifierEvent(Qt::NoModifier));
|
||||
|
||||
ExpectedEventList expected(&w);
|
||||
expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_Shift, Qt::NoModifier));
|
||||
expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::ShiftModifier));
|
||||
expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::ShiftModifier));
|
||||
expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_Shift, Qt::ShiftModifier));
|
||||
|
||||
native.play();
|
||||
QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
|
||||
}
|
||||
|
||||
void tst_MacNativeEvents::testModifierAlt()
|
||||
{
|
||||
QWidget w;
|
||||
w.show();
|
||||
|
||||
NativeEventList native;
|
||||
native.append(new QNativeModifierEvent(Qt::AltModifier));
|
||||
native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::AltModifier));
|
||||
native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::AltModifier));
|
||||
native.append(new QNativeModifierEvent(Qt::NoModifier));
|
||||
|
||||
ExpectedEventList expected(&w);
|
||||
expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_Alt, Qt::NoModifier));
|
||||
expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::AltModifier));
|
||||
expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::AltModifier));
|
||||
expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_Alt, Qt::AltModifier));
|
||||
|
||||
native.play();
|
||||
QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
|
||||
}
|
||||
|
||||
void tst_MacNativeEvents::testModifierCtrl()
|
||||
{
|
||||
// On Mac, we switch the Command and Control modifier by default, so that Command
|
||||
// means Meta, and Control means Command. Lets check that this works:
|
||||
QWidget w;
|
||||
w.show();
|
||||
|
||||
QCOMPARE(ushort(kControlUnicode), QKeySequence(Qt::Key_Meta).toString(QKeySequence::NativeText).at(0).unicode());
|
||||
QCOMPARE(ushort(kCommandUnicode), QKeySequence(Qt::Key_Control).toString(QKeySequence::NativeText).at(0).unicode());
|
||||
|
||||
NativeEventList native;
|
||||
native.append(new QNativeModifierEvent(Qt::ControlModifier));
|
||||
native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::ControlModifier));
|
||||
native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::ControlModifier));
|
||||
native.append(new QNativeModifierEvent(Qt::NoModifier));
|
||||
|
||||
ExpectedEventList expected(&w);
|
||||
expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_Meta, Qt::NoModifier));
|
||||
expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::MetaModifier));
|
||||
expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::MetaModifier));
|
||||
expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_Meta, Qt::MetaModifier));
|
||||
|
||||
native.play();
|
||||
QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
|
||||
}
|
||||
|
||||
void tst_MacNativeEvents::testModifierCtrlWithDontSwapCtrlAndMeta()
|
||||
{
|
||||
// On Mac, we switch the Command and Control modifier by default, so that Command
|
||||
// means Meta, and Control means Command. Lets check that the flag to swith off
|
||||
// this behaviour works. While working on this test I realized that we actually
|
||||
// don't (and never have) respected this flag for raw key events. Only for
|
||||
// menus, through QKeySequence. I don't want to change this behaviour now, at
|
||||
// least not until someone complains. So I choose to let the test just stop
|
||||
// any unintended regressions instead. If we decide to resepect the flag at one
|
||||
// point, fix the test.
|
||||
QCoreApplication::setAttribute(Qt::AA_MacDontSwapCtrlAndMeta);
|
||||
QWidget w;
|
||||
w.show();
|
||||
|
||||
QCOMPARE(ushort(kCommandUnicode), QKeySequence(Qt::Key_Meta).toString(QKeySequence::NativeText).at(0).unicode());
|
||||
QCOMPARE(ushort(kControlUnicode), QKeySequence(Qt::Key_Control).toString(QKeySequence::NativeText).at(0).unicode());
|
||||
|
||||
NativeEventList native;
|
||||
native.append(new QNativeModifierEvent(Qt::ControlModifier));
|
||||
native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, true, Qt::ControlModifier));
|
||||
native.append(new QNativeKeyEvent(QNativeKeyEvent::Key_A, false, Qt::ControlModifier));
|
||||
native.append(new QNativeModifierEvent(Qt::NoModifier));
|
||||
|
||||
ExpectedEventList expected(&w);
|
||||
expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_Control, Qt::NoModifier));
|
||||
expected.append(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::ControlModifier));
|
||||
expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::ControlModifier));
|
||||
expected.append(new QKeyEvent(QEvent::KeyRelease, Qt::Key_Control, Qt::ControlModifier));
|
||||
|
||||
native.play();
|
||||
QVERIFY2(expected.waitForAllEvents(), "the test did not receive all expected events!");
|
||||
QCoreApplication::setAttribute(Qt::AA_MacDontSwapCtrlAndMeta, false);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_MacNativeEvents)
|
||||
#include "tst_macnativeevents.moc"
|
Reference in New Issue
Block a user