44#include <QtGui/qevent.h>
45#include <QtGui/qguiapplication.h>
46#include <QtGui/private/qguiapplication_p.h>
48#include <QtCore/qmutex.h>
49#include <QtCore/qscopeguard.h>
50#include <QtCore/qsocketnotifier.h>
51#include <QtCore/private/qthread_p.h>
52#include <QtCore/private/qcore_mac_p.h>
54#include <qpa/qplatformwindow.h>
55#include <qpa/qplatformnativeinterface.h>
57#include <QtCore/qdebug.h>
65 return CFRunLoopGetMain();
70 return info1 == info2;
83 d->maybeCancelWaitForMoreEvents();
86 CFRunLoopSourceSignal(
d->activateTimersSourceRef);
92 if (
d->initializingNSApplication) {
93 qCDebug(lcEventDispatcher) <<
"Deferring" << __FUNCTION__ <<
"due to NSApp initialization";
96 CFRunLoopSourceSignal(
d->activateTimersSourceRef);
100 d->maybeCancelWaitForMoreEvents();
107 return activated > 0;
120 CFAbsoluteTime ttf = CFAbsoluteTimeGetCurrent();
121 CFTimeInterval interval;
122 CFTimeInterval oneyear = CFTimeInterval(3600. * 24. * 365.);
128 interval =
qMax(tv.tv_sec + tv.tv_nsec / 1000000000., 0.0000001);
135 CFRunLoopTimerContext
info = { 0,
this,
nullptr,
nullptr,
nullptr };
144 CFAbsoluteTime ttf = CFAbsoluteTimeGetCurrent();
145 CFTimeInterval interval;
151 interval =
qMax(tv.tv_sec + tv.tv_nsec / 1000000000., 0.0000001);
176 if (timerId < 1 || interval < 0 || !
obj) {
177 qWarning(
"QCocoaEventDispatcher::registerTimer: invalid arguments");
180 qWarning(
"QObject::startTimer: timers cannot be started from another thread");
186 d->timerInfoList.registerTimer(timerId, interval, timerType,
obj);
187 d->maybeStartCFRunLoopTimer();
194 qWarning(
"QCocoaEventDispatcher::unregisterTimer: invalid argument");
197 qWarning(
"QObject::killTimer: timers cannot be stopped from another thread");
203 bool returnValue =
d->timerInfoList.unregisterTimer(timerId);
204 if (!
d->timerInfoList.isEmpty())
205 d->maybeStartCFRunLoopTimer();
207 d->maybeStopCFRunLoopTimer();
215 qWarning(
"QCocoaEventDispatcher::unregisterTimers: invalid argument");
218 qWarning(
"QObject::killTimers: timers cannot be stopped from another thread");
224 bool returnValue =
d->timerInfoList.unregisterTimers(
obj);
225 if (!
d->timerInfoList.isEmpty())
226 d->maybeStartCFRunLoopTimer();
228 d->maybeStopCFRunLoopTimer();
237 qWarning(
"QCocoaEventDispatcher:registeredTimers: invalid argument");
243 return d->timerInfoList.registeredTimers(
object);
256 d->cfSocketNotifier.registerSocketNotifier(
notifier);
262 d->cfSocketNotifier.unregisterSocketNotifier(
notifier);
268 case NSEventTypeLeftMouseDown:
269 case NSEventTypeLeftMouseUp:
270 case NSEventTypeRightMouseDown:
271 case NSEventTypeRightMouseUp:
272 case NSEventTypeMouseMoved:
273 case NSEventTypeLeftMouseDragged:
274 case NSEventTypeRightMouseDragged:
275 case NSEventTypeMouseEntered:
276 case NSEventTypeMouseExited:
277 case NSEventTypeKeyDown:
278 case NSEventTypeKeyUp:
279 case NSEventTypeFlagsChanged:
280 case NSEventTypeCursorUpdate:
281 case NSEventTypeScrollWheel:
282 case NSEventTypeTabletPoint:
283 case NSEventTypeTabletProximity:
284 case NSEventTypeOtherMouseDown:
285 case NSEventTypeOtherMouseUp:
286 case NSEventTypeOtherMouseDragged:
287#ifndef QT_NO_GESTURES
288 case NSEventTypeGesture:
289 case NSEventTypeMagnify:
290 case NSEventTypeSwipe:
291 case NSEventTypeRotate:
292 case NSEventTypeBeginGesture:
293 case NSEventTypeEndGesture:
309 NSEvent*
event = [NSApp nextEventMatchingMask:NSEventMaskAny
310 untilDate:[NSDate distantFuture]
314 [NSApp postEvent:
event atStart:YES];
324 d->propagateInterrupt =
false;
326 if (
d->propagateInterrupt)
328 d->propagateInterrupt =
false;
332 bool interruptLater =
false;
337 uint oldflags =
d->processEventsFlags;
338 d->processEventsFlags =
flags;
343 ++
d->processEventsCalled;
352 NSEvent*
event = nil;
355 if (
d->sendQueuedUserInputEvents())
366 const bool canExec_3rdParty =
d->nsAppRunCalledByQt || ![NSApp
isRunning];
367 const bool canExec_Qt = (!excludeUserEvents
371 if (canExec_Qt && canExec_3rdParty) {
377 while ([NSApp runModalSession:session] == NSModalResponseContinue && !
d->interrupt) {
379 if (session !=
d->currentModalSessionCached) {
390 if (!
d->interrupt && session ==
d->currentModalSessionCached) {
394 d->temporarilyStopAllModalSessions();
398 if (
d->cleanupModalSessionsNeeded)
399 d->cleanupModalSessions();
402 d->nsAppRunCalledByQt =
true;
408 int lastSerialCopy =
d->lastSerial;
409 const bool hadModalSession =
d->currentModalSessionCached;
412 d->ensureNSAppInitialized();
415 if (!excludeUserEvents) {
420 NSInteger status = [NSApp runModalSession:session];
421 if (status != NSModalResponseContinue && session ==
d->currentModalSessionCached) {
425 d->temporarilyStopAllModalSessions();
429 if (
d->cleanupModalSessionsNeeded)
430 d->cleanupModalSessions();
437 event = [NSApp nextEventMatchingMask:NSEventMaskAny
439 inMode:NSModalPanelRunLoopMode
445 d->queuedUserInputEvents.append(
event);
449 [NSApp sendEvent:
event];
453 }
while (!
d->interrupt &&
event);
456 event = [NSApp nextEventMatchingMask:NSEventMaskAny
458 inMode:NSDefaultRunLoopMode
465 d->queuedUserInputEvents.append(
event);
470 [NSApp sendEvent:
event];
476 if (
d->cleanupModalSessionsNeeded)
477 d->cleanupModalSessions();
479 }
while (!
d->interrupt &&
event);
483 bool oldInterrupt =
d->interrupt;
484 d->processPostedEvents();
485 if (!oldInterrupt &&
d->interrupt && !
d->currentModalSession()) {
491 d->propagateInterrupt =
true;
493 retVal =
d->processTimers() || retVal;
497 retVal = retVal || lastSerialCopy !=
d->lastSerial;
504 if (hadModalSession && !
d->currentModalSessionCached)
505 interruptLater =
true;
507 bool canWait = (
d->threadData.loadRelaxed()->canWait
515 d->processEventsFlags &=
~QEventLoop::WaitForMoreEvents;
523 d->processEventsFlags = oldflags;
524 --
d->processEventsCalled;
544 qWarning(
"QCocoaEventDispatcher::remainingTime: invalid argument");
550 return d->timerInfoList.timerRemainingTime(timerId);
556 d->serialNumber.ref();
557 CFRunLoopSourceSignal(
d->postedEventsSource);
588 qCDebug(lcEventDispatcher) <<
"Ensuring NSApplication is initialized";
596 CFRunLoopPerformBlock(
mainRunLoop(), kCFRunLoopCommonModes, ^{
597 qCDebug(lcEventDispatcher) <<
"NSApplication has been initialized; Stopping NSApp";
602 qCDebug(lcEventDispatcher) <<
"Finished ensuring NSApplication is initialized";
617 for (
int i=0;
i<stackSize; ++
i) {
621 info.session =
nullptr;
639 for (
int i=0;
i<sessionCount; ++
i) {
655 info.nswindow = nswindow;
656 [(NSWindow*)
info.nswindow retain];
658 info.session = [NSApp beginModalSessionForWindow:nswindow];
694 for (
int i=stackSize-1;
i>=0; --
i) {
747 int endedSessions = 0;
748 for (
int i=stackSize-1;
i>=0; --
i) {
753 info.window =
nullptr;
754 if (
i + endedSessions == stackSize-1) {
766 : processEventsFlags(0),
768 blockSendPostedEvents(
false),
769 currentExecIsNSAppRun(
false),
770 nsAppRunCalledByQt(
false),
771 cleanupModalSessionsNeeded(
false),
772 processEventsCalled(0),
773 currentModalSessionCached(
nullptr),
789 d->cfSocketNotifier.setHostEventDispatcher(
this);
793 CFRunLoopAddCommonMode(
mainRunLoop(), (CFStringRef) NSModalPanelRunLoopMode);
795 CFRunLoopSourceContext
context;
796 bzero(&
context,
sizeof(CFRunLoopSourceContext));
802 d->activateTimersSourceRef = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &
context);
804 CFRunLoopAddSource(
mainRunLoop(),
d->activateTimersSourceRef, kCFRunLoopCommonModes);
808 d->postedEventsSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &
context);
810 CFRunLoopAddSource(
mainRunLoop(),
d->postedEventsSource, kCFRunLoopCommonModes);
813 CFRunLoopObserverContext observerContext;
814 bzero(&observerContext,
sizeof(CFRunLoopObserverContext));
815 observerContext.info =
this;
816 d->waitingObserver = CFRunLoopObserverCreate(kCFAllocatorDefault,
817 kCFRunLoopBeforeWaiting | kCFRunLoopAfterWaiting,
821 CFRunLoopAddObserver(
mainRunLoop(),
d->waitingObserver, kCFRunLoopCommonModes);
825 CFRunLoopActivity activity,
void *
info)
827 if (activity == kCFRunLoopBeforeWaiting)
838 bool didSendEvent =
false;
841 if (!
q->filterNativeEvent(
"NSEvent",
event,
nullptr)) {
842 [NSApp sendEvent:
event];
889 if (
d->initializingNSApplication) {
890 qCDebug(lcEventDispatcher) <<
"Deferring" << __FUNCTION__ <<
"due to NSApp initialization";
893 CFRunLoopSourceSignal(
d->postedEventsSource);
899 d->maybeCancelWaitForMoreEvents();
902 d->sendQueuedUserInputEvents();
903 d->processPostedEvents();
904 d->maybeCancelWaitForMoreEvents();
912 [NSApp postEvent:[NSEvent otherEventWithType:NSEventTypeApplicationDefined
location:NSZeroPoint
913 modifierFlags:0 timestamp:0. windowNumber:0
context:nil
914 subtype:QtCocoaEventSubTypeWakeup data1:0 data2:0] atStart:NO];
940 d->cancelWaitForMoreEvents();
949 if (!cocoaEventDispatcher)
953 cocoaEventDispatcherPrivate->
interrupt =
false;
961 d->maybeStopCFRunLoopTimer();
962 CFRunLoopRemoveSource(
mainRunLoop(),
d->activateTimersSourceRef, kCFRunLoopCommonModes);
963 CFRelease(
d->activateTimersSourceRef);
966 for (
int i = 0;
i <
d->cocoaModalSessionStack.count(); ++
i) {
969 [NSApp endModalSession:
info.session];
975 for (
int i = 0;
i <
d->queuedUserInputEvents.count(); ++
i) {
976 NSEvent *nsevent =
static_cast<NSEvent *
>(
d->queuedUserInputEvents.at(
i));
980 d->cfSocketNotifier.removeSocketNotifiers();
982 CFRunLoopRemoveSource(
mainRunLoop(),
d->postedEventsSource, kCFRunLoopCommonModes);
983 CFRelease(
d->postedEventsSource);
985 CFRunLoopObserverInvalidate(
d->waitingObserver);
986 CFRelease(
d->waitingObserver);
991QtCocoaInterruptDispatcher::QtCocoaInterruptDispatcher() :
cancelled(
false)
1002QtCocoaInterruptDispatcher::~QtCocoaInterruptDispatcher()
1014 instance->cancelled =
true;
DarwinBluetooth::LECBManagerNotifier * notifier
static QAbstractEventDispatcher * instance(QThread *thread=nullptr)
Returns a pointer to the event dispatcher object for the specified thread.
bool filterNativeEvent(const QByteArray &eventType, void *message, qintptr *result)
Sends message through the event filters that were set by installNativeEventFilter().
void awake()
This signal is emitted after the event loop returns from a function that could block.
virtual void interrupt()=0
Interrupts event dispatching.
T loadRelaxed() const noexcept
Type loadRelaxed() const noexcept
void beginModalSession(QWindow *widget)
void endModalSession(QWindow *widget)
NSModalSession currentModalSessionCached
bool sendQueuedUserInputEvents()
static void postedEventsSourceCallback(void *info)
bool blockSendPostedEvents
QCocoaEventDispatcherPrivate()
void temporarilyStopAllModalSessions()
CFRunLoopSourceRef postedEventsSource
static void runLoopTimerCallback(CFRunLoopTimerRef, void *info)
void processPostedEvents()
QList< void * > queuedUserInputEvents
CFRunLoopTimerRef runLoopTimerRef
void maybeCancelWaitForMoreEvents()
bool hasModalSession() const
static void activateTimersSourceCallback(void *info)
void maybeStopCFRunLoopTimer()
void cancelWaitForMoreEvents()
void cleanupModalSessions()
void ensureNSAppInitialized()
static void waitingObserverCallback(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info)
QTimerInfoList timerInfoList
NSModalSession currentModalSession()
bool initializingNSApplication
bool cleanupModalSessionsNeeded
void maybeStartCFRunLoopTimer()
QStack< QCocoaModalSessionInfo > cocoaModalSessionStack
bool currentExecIsNSAppRun
void registerTimer(int timerId, qint64 interval, Qt::TimerType timerType, QObject *object)
Register a timer with the specified timerId, interval, and timerType for the given object.
void interrupt()
Interrupts event dispatching.
void unregisterSocketNotifier(QSocketNotifier *notifier)
Unregisters notifier from the event dispatcher.
bool unregisterTimer(int timerId)
Unregisters the timer with the given timerId.
int remainingTime(int timerId)
Returns the remaining time in milliseconds with the given timerId.
void registerSocketNotifier(QSocketNotifier *notifier)
Registers notifier with the event loop.
QList< TimerInfo > registeredTimers(QObject *object) const
Returns a list of registered timers for object.
QCocoaEventDispatcher(QAbstractEventDispatcherPrivate &priv, QObject *parent=nullptr)
bool unregisterTimers(QObject *object)
Unregisters all the timers associated with the given object.
friend void qt_mac_maybeCancelWaitForMoreEventsForwarder(QAbstractEventDispatcher *eventDispatcher)
static void clearCurrentThreadCocoaEventDispatcherInterruptFlag()
bool processEvents(QEventLoop::ProcessEventsFlags flags)
Processes pending events that match flags until there are no more events to process.
QRect geometry() const override
Returns the current geometry of a window.
NSWindow * nativeWindow() const
void setGeometry(const QRect &rect) override
This function is called by Qt whenever a window is moved or resized using the QWindow API.
static void sendPostedEvents(QObject *receiver=nullptr, int event_type=0)
Immediately dispatches all events which have been previously queued with QCoreApplication::postEvent(...
bool isEmpty() const noexcept
static QObjectPrivate * get(QObject *o)
QAtomicPointer< QThreadData > threadData
QThread * thread() const
Returns the thread in which the object lives.
void deleteLater()
\threadsafe
\inmodule QtCore\reentrant
static QThread * currentThread()
bool timerWait(timespec &)
static bool sendWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)
static void cancelInterruptLater()
static void interruptLater()
qDeleteAll(list.begin(), list.end())
Combined button and popup list for selecting options.
struct _NSModalSession * NSModalSession
static CFRunLoopRef mainRunLoop()
static void qt_mac_waitForMoreEvents(NSString *runLoopMode=NSDefaultRunLoopMode)
static Boolean runLoopSourceEqualCallback(const void *info1, const void *info2)
void qt_mac_maybeCancelWaitForMoreEventsForwarder(QAbstractEventDispatcher *eventDispatcher)
static bool isUserInputEvent(NSEvent *event)
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
constexpr const T & qMax(const T &a, const T &b)
GLdouble GLdouble GLdouble GLdouble q
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
QFileInfo info(fileName)
[8]
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent