summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Poulain <benjamin.poulain@nokia.com>2009-09-21 09:58:21 (GMT)
committerBenjamin Poulain <benjamin.poulain@nokia.com>2009-09-21 10:07:34 (GMT)
commitb0016ea9a6b225757e3ee06b50e8f7d05463ddf7 (patch)
tree7a4f640566155323bf900cc5fa7bb9fb2e93260a
parent74bd11b55388ca6a8e5cfdbdcfb044bb538fafa0 (diff)
downloadQt-b0016ea9a6b225757e3ee06b50e8f7d05463ddf7.zip
Qt-b0016ea9a6b225757e3ee06b50e8f7d05463ddf7.tar.gz
Qt-b0016ea9a6b225757e3ee06b50e8f7d05463ddf7.tar.bz2
On Mac, the posted events are processed on the first time in the loop
On Mac OS X, we use a custom source for posted events. The first time the event loop is entered, the custom source is added to the native event dispatcher but the events are not processed. In Qt, we expect those events to be processed. To work around the problem, a new observer is added to the event loop. This observer is only triggered the first time the event loop is entered. When the observer is triggered, the posted events are sent. Task-number: QTBUG-4521 Reviewed-by: Richard Moe Gustavsen Reviewed-by: João Abecasis
-rw-r--r--src/gui/kernel/qeventdispatcher_mac.mm33
-rw-r--r--src/gui/kernel/qeventdispatcher_mac_p.h1
-rw-r--r--tests/auto/qcoreapplication/tst_qcoreapplication.cpp45
3 files changed, 64 insertions, 15 deletions
diff --git a/src/gui/kernel/qeventdispatcher_mac.mm b/src/gui/kernel/qeventdispatcher_mac.mm
index f05d56f..7a3af86 100644
--- a/src/gui/kernel/qeventdispatcher_mac.mm
+++ b/src/gui/kernel/qeventdispatcher_mac.mm
@@ -909,6 +909,22 @@ QEventDispatcherMac::QEventDispatcherMac(QObject *parent)
QEventDispatcherMacPrivate::waitingObserverCallback,
&observerContext);
CFRunLoopAddObserver(mainRunLoop(), d->waitingObserver, kCFRunLoopCommonModes);
+
+ /* The first cycle in the loop adds the source and the events of the source
+ are not processed.
+ We use an observer to process the posted events for the first
+ execution of the loop. */
+ CFRunLoopObserverContext firstTimeObserverContext;
+ bzero(&firstTimeObserverContext, sizeof(CFRunLoopObserverContext));
+ firstTimeObserverContext.info = d;
+ CFRunLoopObserverRef firstTimeObserver = CFRunLoopObserverCreate(kCFAllocatorDefault,
+ kCFRunLoopEntry,
+ /* repeats = */ false,
+ 0,
+ QEventDispatcherMacPrivate::firstLoopEntry,
+ &firstTimeObserverContext);
+ CFRunLoopAddObserver(mainRunLoop(), firstTimeObserver, kCFRunLoopCommonModes);
+ CFRelease(firstTimeObserver);
}
void QEventDispatcherMacPrivate::waitingObserverCallback(CFRunLoopObserverRef,
@@ -925,9 +941,8 @@ Boolean QEventDispatcherMacPrivate::postedEventSourceEqualCallback(const void *i
return info1 == info2;
}
-void QEventDispatcherMacPrivate::postedEventsSourcePerformCallback(void *info)
+inline static void processPostedEvents(QEventDispatcherMacPrivate *const d, const bool blockSendPostedEvents)
{
- QEventDispatcherMacPrivate *d = static_cast<QEventDispatcherMacPrivate *>(info);
if (blockSendPostedEvents) {
CFRunLoopSourceSignal(d->postedEventsSource);
} else {
@@ -938,6 +953,20 @@ void QEventDispatcherMacPrivate::postedEventsSourcePerformCallback(void *info)
}
}
+void QEventDispatcherMacPrivate::firstLoopEntry(CFRunLoopObserverRef ref,
+ CFRunLoopActivity activity,
+ void *info)
+{
+ Q_UNUSED(ref);
+ Q_UNUSED(activity);
+ processPostedEvents(static_cast<QEventDispatcherMacPrivate *>(info), blockSendPostedEvents);
+}
+
+void QEventDispatcherMacPrivate::postedEventsSourcePerformCallback(void *info)
+{
+ processPostedEvents(static_cast<QEventDispatcherMacPrivate *>(info), blockSendPostedEvents);
+}
+
void QEventDispatcherMac::interrupt()
{
Q_D(QEventDispatcherMac);
diff --git a/src/gui/kernel/qeventdispatcher_mac_p.h b/src/gui/kernel/qeventdispatcher_mac_p.h
index e94d98a..15bc6f8 100644
--- a/src/gui/kernel/qeventdispatcher_mac_p.h
+++ b/src/gui/kernel/qeventdispatcher_mac_p.h
@@ -196,6 +196,7 @@ private:
static void activateTimer(CFRunLoopTimerRef, void *info);
static void waitingObserverCallback(CFRunLoopObserverRef observer,
CFRunLoopActivity activity, void *info);
+ static void firstLoopEntry(CFRunLoopObserverRef ref, CFRunLoopActivity activity, void *info);
};
#ifdef QT_MAC_USE_COCOA
diff --git a/tests/auto/qcoreapplication/tst_qcoreapplication.cpp b/tests/auto/qcoreapplication/tst_qcoreapplication.cpp
index 9ddd54a..4b38044 100644
--- a/tests/auto/qcoreapplication/tst_qcoreapplication.cpp
+++ b/tests/auto/qcoreapplication/tst_qcoreapplication.cpp
@@ -47,6 +47,7 @@ class tst_QCoreApplication: public QObject
{
Q_OBJECT
private slots:
+ void sendEventsOnProcessEvents(); // this must be the first test
void getSetCheck();
void qAppName();
void argc();
@@ -59,6 +60,35 @@ private slots:
void globalPostedEventsCount();
};
+class EventSpy : public QObject
+{
+ Q_OBJECT
+
+public:
+ QList<int> recordedEvents;
+ bool eventFilter(QObject *, QEvent *event)
+ {
+ recordedEvents.append(event->type());
+ return false;
+ }
+};
+
+void tst_QCoreApplication::sendEventsOnProcessEvents()
+{
+ int argc = 1;
+ char *argv[] = { "tst_qcoreapplication" };
+ QCoreApplication app(argc, argv);
+
+ EventSpy spy;
+ app.installEventFilter(&spy);
+
+ QCoreApplication::postEvent(&app, new QEvent(QEvent::Type(QEvent::User + 1)));
+ QCoreApplication::processEvents();
+ QList<int> expected;
+ expected << QEvent::User + 1;
+ QCOMPARE(expected, spy.recordedEvents);
+}
+
void tst_QCoreApplication::getSetCheck()
{
// do not crash
@@ -114,19 +144,6 @@ void tst_QCoreApplication::argc()
}
}
-class EventSpy : public QObject
-{
- Q_OBJECT
-
-public:
- QList<int> recordedEvents;
- bool eventFilter(QObject *, QEvent *event)
- {
- recordedEvents.append(event->type());
- return false;
- }
-};
-
class EventGenerator : public QObject
{
Q_OBJECT
@@ -394,6 +411,8 @@ public:
}
case QEvent::User + 1:
break;
+ default:
+ break;
}
return QObject::event(event);
}