Qt 4.8
qeventdispatcher_mac.mm
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module 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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 /****************************************************************************
43 **
44 ** Copyright (c) 2007-2008, Apple, Inc.
45 **
46 ** All rights reserved.
47 **
48 ** Redistribution and use in source and binary forms, with or without
49 ** modification, are permitted provided that the following conditions are met:
50 **
51 ** * Redistributions of source code must retain the above copyright notice,
52 ** this list of conditions and the following disclaimer.
53 **
54 ** * Redistributions in binary form must reproduce the above copyright notice,
55 ** this list of conditions and the following disclaimer in the documentation
56 ** and/or other materials provided with the distribution.
57 **
58 ** * Neither the name of Apple, Inc. nor the names of its contributors
59 ** may be used to endorse or promote products derived from this software
60 ** without specific prior written permission.
61 **
62 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
63 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
64 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
65 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
66 ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
67 ** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
68 ** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
69 ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
70 ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
71 ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
72 ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73 **
74 ****************************************************************************/
75 
76 #include "qplatformdefs.h"
77 #include "private/qt_mac_p.h"
78 #include "qeventdispatcher_mac_p.h"
79 #include "qapplication.h"
80 #include "qevent.h"
81 #include "qdialog.h"
82 #include "qhash.h"
83 #include "qsocketnotifier.h"
84 #include "private/qwidget_p.h"
85 #include "private/qthread_p.h"
86 #include "private/qapplication_p.h"
87 
88 #include <private/qcocoaapplication_mac_p.h>
89 #include "private/qt_cocoa_helpers_mac_p.h"
90 
91 #ifndef QT_NO_THREAD
92 # include "qmutex.h"
93 #endif
94 
96 
98 
99 /*****************************************************************************
100  Externals
101  *****************************************************************************/
102 extern void qt_event_request_timer(MacTimerInfo *); //qapplication_mac.cpp
103 extern MacTimerInfo *qt_event_get_timer(EventRef); //qapplication_mac.cpp
104 extern void qt_event_request_select(QEventDispatcherMac *); //qapplication_mac.cpp
105 extern void qt_event_request_updates(); //qapplication_mac.cpp
106 extern OSWindowRef qt_mac_window_for(const QWidget *); //qwidget_mac.cpp
107 extern bool qt_is_gui_used; //qapplication.cpp
108 extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp
109 extern bool qt_mac_is_macsheet(const QWidget *); //qwidget_mac.cpp
110 
111 static inline CFRunLoopRef mainRunLoop()
112 {
113 #ifndef QT_MAC_USE_COCOA
114  return reinterpret_cast<CFRunLoopRef>(const_cast<void *>(GetCFRunLoopFromEventLoop(GetMainEventLoop())));
115 #else
116  return CFRunLoopGetMain();
117 #endif
118 }
119 
120 /*****************************************************************************
121  Timers stuff
122  *****************************************************************************/
123 
124 /* timer call back */
125 void QEventDispatcherMacPrivate::activateTimer(CFRunLoopTimerRef, void *info)
126 {
127  int timerID =
128 #ifdef Q_OS_MAC64
129  qint64(info);
130 #else
131  int(info);
132 #endif
133 
134  MacTimerInfo *tmr;
135  tmr = macTimerHash.value(timerID);
136  if (tmr == 0 || tmr->pending == true)
137  return; // Can't send another timer event if it's pending.
138 
139 
140  if (blockSendPostedEvents) {
142  } else {
143  tmr->pending = true;
144  QTimerEvent e(tmr->id);
145  qt_sendSpontaneousEvent(tmr->obj, &e);
146  // Get the value again in case the timer gets unregistered during the sendEvent.
147  tmr = macTimerHash.value(timerID);
148  if (tmr != 0)
149  tmr->pending = false;
150  }
151 
152 }
153 
154 void QEventDispatcherMac::registerTimer(int timerId, int interval, QObject *obj)
155 {
156 #ifndef QT_NO_DEBUG
157  if (timerId < 1 || interval < 0 || !obj) {
158  qWarning("QEventDispatcherMac::registerTimer: invalid arguments");
159  return;
160  } else if (obj->thread() != thread() || thread() != QThread::currentThread()) {
161  qWarning("QObject::startTimer: timers cannot be started from another thread");
162  return;
163  }
164 #endif
165 
166  MacTimerInfo *t = new MacTimerInfo();
167  t->id = timerId;
168  t->interval = interval;
169  t->obj = obj;
170  t->runLoopTimer = 0;
171  t->pending = false;
172 
173  CFAbsoluteTime fireDate = CFAbsoluteTimeGetCurrent();
174  CFTimeInterval cfinterval = qMax(CFTimeInterval(interval) / 1000, 0.0000001);
175  fireDate += cfinterval;
177  CFRunLoopTimerContext info = { 0, (void *)timerId, 0, 0, 0 };
178  t->runLoopTimer = CFRunLoopTimerCreate(0, fireDate, cfinterval, 0, 0,
180  if (t->runLoopTimer == 0) {
181  qFatal("QEventDispatcherMac::registerTimer: Cannot create timer");
182  }
183  CFRunLoopAddTimer(mainRunLoop(), t->runLoopTimer, kCFRunLoopCommonModes);
184 }
185 
187 {
188 #ifndef QT_NO_DEBUG
189  if (identifier < 1) {
190  qWarning("QEventDispatcherMac::unregisterTimer: invalid argument");
191  return false;
192  } else if (thread() != QThread::currentThread()) {
193  qWarning("QObject::killTimer: timers cannot be stopped from another thread");
194  return false;
195  }
196 #endif
197  if (identifier <= 0)
198  return false; // not init'd or invalid timer
199 
201  if (timerInfo == 0)
202  return false;
203 
204  if (!QObjectPrivate::get(timerInfo->obj)->inThreadChangeEvent)
206  CFRunLoopTimerInvalidate(timerInfo->runLoopTimer);
207  CFRelease(timerInfo->runLoopTimer);
208  delete timerInfo;
209 
210  return true;
211 }
212 
214 {
215 #ifndef QT_NO_DEBUG
216  if (!obj) {
217  qWarning("QEventDispatcherMac::unregisterTimers: invalid argument");
218  return false;
219  } else if (obj->thread() != thread() || thread() != QThread::currentThread()) {
220  qWarning("QObject::killTimers: timers cannot be stopped from another thread");
221  return false;
222  }
223 #endif
224 
227  MacTimerInfo *timerInfo = it.value();
228  if (timerInfo->obj != obj) {
229  ++it;
230  } else {
231  if (!QObjectPrivate::get(timerInfo->obj)->inThreadChangeEvent)
233  CFRunLoopTimerInvalidate(timerInfo->runLoopTimer);
234  CFRelease(timerInfo->runLoopTimer);
235  delete timerInfo;
237  }
238  }
239  return true;
240 }
241 
244 {
245  if (!object) {
246  qWarning("QEventDispatcherMac:registeredTimers: invalid argument");
247  return QList<TimerInfo>();
248  }
249 
250  QList<TimerInfo> list;
251 
253  while (it != QEventDispatcherMacPrivate::macTimerHash.constEnd()) {
254  MacTimerInfo *t = it.value();
255  if (t->obj == object)
256  list << TimerInfo(t->id, t->interval);
257  ++it;
258  }
259  return list;
260 }
261 
262 /**************************************************************************
263  Socket Notifiers
264  *************************************************************************/
265 void qt_mac_socket_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef,
266  const void *, void *info) {
267  QEventDispatcherMacPrivate *const eventDispatcher
268  = static_cast<QEventDispatcherMacPrivate *>(info);
269  int nativeSocket = CFSocketGetNative(s);
270  MacSocketInfo *socketInfo = eventDispatcher->macSockets.value(nativeSocket);
271  QEvent notifierEvent(QEvent::SockAct);
272 
273  // There is a race condition that happen where we disable the notifier and
274  // the kernel still has a notification to pass on. We then get this
275  // notification after we've successfully disabled the CFSocket, but our Qt
276  // notifier is now gone. The upshot is we have to check the notifier
277  // everytime.
278  if (callbackType == kCFSocketReadCallBack) {
279  if (socketInfo->readNotifier)
280  QApplication::sendEvent(socketInfo->readNotifier, &notifierEvent);
281  } else if (callbackType == kCFSocketWriteCallBack) {
282  if (socketInfo->writeNotifier)
283  QApplication::sendEvent(socketInfo->writeNotifier, &notifierEvent);
284  }
285 }
286 
287 /*
288  Adds a loop source for the given socket to the current run loop.
289 */
290 CFRunLoopSourceRef qt_mac_add_socket_to_runloop(const CFSocketRef socket)
291 {
292  CFRunLoopSourceRef loopSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0);
293  if (!loopSource)
294  return 0;
295 
296  CFRunLoopAddSource(mainRunLoop(), loopSource, kCFRunLoopCommonModes);
297  return loopSource;
298 }
299 
300 /*
301  Removes the loop source for the given socket from the current run loop.
302 */
303 void qt_mac_remove_socket_from_runloop(const CFSocketRef socket, CFRunLoopSourceRef runloop)
304 {
305  Q_ASSERT(runloop);
306  CFRunLoopRemoveSource(mainRunLoop(), runloop, kCFRunLoopCommonModes);
307  CFSocketDisableCallBacks(socket, kCFSocketReadCallBack);
308  CFSocketDisableCallBacks(socket, kCFSocketWriteCallBack);
309  CFRunLoopSourceInvalidate(runloop);
310 }
311 
312 /*
313  Register a QSocketNotifier with the mac event system by creating a CFSocket with
314  with a read/write callback.
315 
316  Qt has separate socket notifiers for reading and writing, but on the mac there is
317  a limitation of one CFSocket object for each native socket.
318 */
320 {
321  Q_ASSERT(notifier);
322  int nativeSocket = notifier->socket();
323  int type = notifier->type();
324 #ifndef QT_NO_DEBUG
325  if (nativeSocket < 0 || nativeSocket > FD_SETSIZE) {
326  qWarning("QSocketNotifier: Internal error");
327  return;
328  } else if (notifier->thread() != thread()
329  || thread() != QThread::currentThread()) {
330  qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread");
331  return;
332  }
333 #endif
334 
336 
337  if (type == QSocketNotifier::Exception) {
338  qWarning("QSocketNotifier::Exception is not supported on Mac OS X");
339  return;
340  }
341 
342  // Check if we have a CFSocket for the native socket, create one if not.
343  MacSocketInfo *socketInfo = d->macSockets.value(nativeSocket);
344  if (!socketInfo) {
345  socketInfo = new MacSocketInfo();
346 
347  // Create CFSocket, specify that we want both read and write callbacks (the callbacks
348  // are enabled/disabled later on).
349  const int callbackTypes = kCFSocketReadCallBack | kCFSocketWriteCallBack;
350  CFSocketContext context = {0, d, 0, 0, 0};
351  socketInfo->socket = CFSocketCreateWithNative(kCFAllocatorDefault, nativeSocket, callbackTypes, qt_mac_socket_callback, &context);
352  if (CFSocketIsValid(socketInfo->socket) == false) {
353  qWarning("QEventDispatcherMac::registerSocketNotifier: Failed to create CFSocket");
354  return;
355  }
356 
357  CFOptionFlags flags = CFSocketGetSocketFlags(socketInfo->socket);
358  flags |= kCFSocketAutomaticallyReenableWriteCallBack; //QSocketNotifier stays enabled after a write
359  flags &= ~kCFSocketCloseOnInvalidate; //QSocketNotifier doesn't close the socket upon destruction/invalidation
360  CFSocketSetSocketFlags(socketInfo->socket, flags);
361 
362  // Add CFSocket to runloop.
363  if(!(socketInfo->runloop = qt_mac_add_socket_to_runloop(socketInfo->socket))) {
364  qWarning("QEventDispatcherMac::registerSocketNotifier: Failed to add CFSocket to runloop");
365  CFSocketInvalidate(socketInfo->socket);
366  CFRelease(socketInfo->socket);
367  return;
368  }
369 
370  // Disable both callback types by default. This must be done after
371  // we add the CFSocket to the runloop, or else these calls will have
372  // no effect.
373  CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack);
374  CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack);
375 
376  d->macSockets.insert(nativeSocket, socketInfo);
377  }
378 
379  // Increment read/write counters and select enable callbacks if necessary.
380  if (type == QSocketNotifier::Read) {
381  Q_ASSERT(socketInfo->readNotifier == 0);
382  socketInfo->readNotifier = notifier;
383  CFSocketEnableCallBacks(socketInfo->socket, kCFSocketReadCallBack);
384  } else if (type == QSocketNotifier::Write) {
385  Q_ASSERT(socketInfo->writeNotifier == 0);
386  socketInfo->writeNotifier = notifier;
387  CFSocketEnableCallBacks(socketInfo->socket, kCFSocketWriteCallBack);
388  }
389 }
390 
391 /*
392  Unregister QSocketNotifer. The CFSocket correspoding to this notifier is
393  removed from the runloop of this is the last notifier that users
394  that CFSocket.
395 */
397 {
398  Q_ASSERT(notifier);
399  int nativeSocket = notifier->socket();
400  int type = notifier->type();
401 #ifndef QT_NO_DEBUG
402  if (nativeSocket < 0 || nativeSocket > FD_SETSIZE) {
403  qWarning("QSocketNotifier: Internal error");
404  return;
405  } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
406  qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread");
407  return;
408  }
409 #endif
410 
412 
413  if (type == QSocketNotifier::Exception) {
414  qWarning("QSocketNotifier::Exception is not supported on Mac OS X");
415  return;
416  }
417  MacSocketInfo *socketInfo = d->macSockets.value(nativeSocket);
418  if (!socketInfo) {
419  qWarning("QEventDispatcherMac::unregisterSocketNotifier: Tried to unregister a not registered notifier");
420  return;
421  }
422 
423  // Decrement read/write counters and disable callbacks if necessary.
424  if (type == QSocketNotifier::Read) {
425  Q_ASSERT(notifier == socketInfo->readNotifier);
426  socketInfo->readNotifier = 0;
427  CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack);
428  } else if (type == QSocketNotifier::Write) {
429  Q_ASSERT(notifier == socketInfo->writeNotifier);
430  socketInfo->writeNotifier = 0;
431  CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack);
432  }
433 
434  // Remove CFSocket from runloop if this was the last QSocketNotifier.
435  if (socketInfo->readNotifier == 0 && socketInfo->writeNotifier == 0) {
436  if (CFSocketIsValid(socketInfo->socket))
437  qt_mac_remove_socket_from_runloop(socketInfo->socket, socketInfo->runloop);
438  CFRunLoopSourceInvalidate(socketInfo->runloop);
439  CFRelease(socketInfo->runloop);
440  CFSocketInvalidate(socketInfo->socket);
441  CFRelease(socketInfo->socket);
442  delete socketInfo;
443  d->macSockets.remove(nativeSocket);
444  }
445 }
446 
448 {
450  return qGlobalPostedEventsCount() || (qt_is_gui_used && GetNumEventsInQueue(GetMainEventQueue()));
451 }
452 
453 
454 static bool qt_mac_send_event(QEventLoop::ProcessEventsFlags, OSEventRef event, OSWindowRef pt)
455 {
456 #ifndef QT_MAC_USE_COCOA
457  if(pt && SendEventToWindow(event, pt) != eventNotHandledErr)
458  return true;
459  return !SendEventToEventTarget(event, GetEventDispatcherTarget());
460 #else // QT_MAC_USE_COCOA
461  if (pt)
462  [pt sendEvent:event];
463  else
464  [NSApp sendEvent:event];
465  return true;
466 #endif
467 }
468 
469 #ifdef QT_MAC_USE_COCOA
470 static bool IsMouseOrKeyEvent( NSEvent* event )
471 {
472  bool result = false;
473 
474  switch( [event type] )
475  {
476  case NSLeftMouseDown:
477  case NSLeftMouseUp:
478  case NSRightMouseDown:
479  case NSRightMouseUp:
480  case NSMouseMoved: // ??
481  case NSLeftMouseDragged:
482  case NSRightMouseDragged:
483  case NSMouseEntered:
484  case NSMouseExited:
485  case NSKeyDown:
486  case NSKeyUp:
487  case NSFlagsChanged: // key modifiers changed?
488  case NSCursorUpdate: // ??
489  case NSScrollWheel:
490  case NSTabletPoint:
491  case NSTabletProximity:
492  case NSOtherMouseDown:
493  case NSOtherMouseUp:
494  case NSOtherMouseDragged:
495 #ifndef QT_NO_GESTURES
496 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
497  case NSEventTypeGesture: // touch events
498  case NSEventTypeMagnify:
499  case NSEventTypeSwipe:
500  case NSEventTypeRotate:
501  case NSEventTypeBeginGesture:
502  case NSEventTypeEndGesture:
503 #endif
504 #endif // QT_NO_GESTURES
505  result = true;
506  break;
507 
508  default:
509  break;
510  }
511  return result;
512 }
513 #endif
514 
515 static inline void qt_mac_waitForMoreEvents()
516 {
517 #ifndef QT_MAC_USE_COCOA
518  while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0e20, true) == kCFRunLoopRunTimedOut) ;
519 #else
520  // If no event exist in the cocoa event que, wait
521  // (and free up cpu time) until at least one event occur.
522  // This implementation is a bit on the edge, but seems to
523  // work fine:
524  NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
525  untilDate:[NSDate distantFuture]
526  inMode:NSDefaultRunLoopMode
527  dequeue:YES];
528  if (event)
529  [NSApp postEvent:event atStart:YES];
530 #endif
531 }
532 
533 #ifdef QT_MAC_USE_COCOA
534 static inline void qt_mac_waitForMoreModalSessionEvents()
535 {
536  // If no event exist in the cocoa event que, wait
537  // (and free up cpu time) until at least one event occur.
538  // This implementation is a bit on the edge, but seems to
539  // work fine:
540  NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
541  untilDate:[NSDate distantFuture]
542  inMode:NSModalPanelRunLoopMode
543  dequeue:YES];
544  if (event)
545  [NSApp postEvent:event atStart:YES];
546 }
547 #endif
548 
549 bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags)
550 {
552  d->interrupt = false;
553 
554 #ifdef QT_MAC_USE_COCOA
555  bool interruptLater = false;
556  QtMacInterruptDispatcherHelp::cancelInterruptLater();
557 #endif
558 
559  // In case we end up recursing while we now process events, make sure
560  // that we send remaining posted Qt events before this call returns:
561  wakeUp();
562  emit awake();
563 
564  bool excludeUserEvents = flags & QEventLoop::ExcludeUserInputEvents;
565  bool retVal = false;
566  forever {
567  if (d->interrupt)
568  break;
569 
570 #ifdef QT_MAC_USE_COCOA
572  NSEvent* event = 0;
573 
574  // First, send all previously excluded input events, if any:
575  if (!excludeUserEvents) {
576  while (!d->queuedUserInputEvents.isEmpty()) {
577  event = static_cast<NSEvent *>(d->queuedUserInputEvents.takeFirst());
578  if (!filterEvent(event)) {
579  qt_mac_send_event(flags, event, 0);
580  retVal = true;
581  }
582  [event release];
583  }
584  }
585 
586  // If Qt is used as a plugin, or as an extension in a native cocoa
587  // application, we should not run or stop NSApplication; This will be
588  // done from the application itself. And if processEvents is called
589  // manually (rather than from a QEventLoop), we cannot enter a tight
590  // loop and block this call, but instead we need to return after one flush.
591  // Finally, if we are to exclude user input events, we cannot call [NSApp run]
592  // as we then loose control over which events gets dispatched:
593  const bool canExec_3rdParty = d->nsAppRunCalledByQt || ![NSApp isRunning];
594  const bool canExec_Qt = !excludeUserEvents &&
596 
597  if (canExec_Qt && canExec_3rdParty) {
598  // We can use exec-mode, meaning that we can stay in a tight loop until
599  // interrupted. This is mostly an optimization, but it allow us to use
600  // [NSApp run], which is the normal code path for cocoa applications.
601  if (NSModalSession session = d->currentModalSession()) {
602  QBoolBlocker execGuard(d->currentExecIsNSAppRun, false);
603  while ([NSApp runModalSession:session] == NSRunContinuesResponse && !d->interrupt)
604  qt_mac_waitForMoreModalSessionEvents();
605 
606  if (!d->interrupt && session == d->currentModalSessionCached) {
607  // Someone called [NSApp stopModal:] from outside the event
608  // dispatcher (e.g to stop a native dialog). But that call wrongly stopped
609  // 'session' as well. As a result, we need to restart all internal sessions:
610  d->temporarilyStopAllModalSessions();
611  }
612  } else {
613  d->nsAppRunCalledByQt = true;
614  QBoolBlocker execGuard(d->currentExecIsNSAppRun, true);
615  [NSApp run];
616  }
617  retVal = true;
618  } else {
619  // We cannot block the thread (and run in a tight loop).
620  // Instead we will process all current pending events and return.
621  d->ensureNSAppInitialized();
622  if (NSModalSession session = d->currentModalSession()) {
623  // INVARIANT: a modal window is executing.
624  if (!excludeUserEvents) {
625  // Since we can dispatch all kinds of events, we choose
626  // to use cocoa's native way of running modal sessions:
627  if (flags & QEventLoop::WaitForMoreEvents)
628  qt_mac_waitForMoreModalSessionEvents();
629  NSInteger status = [NSApp runModalSession:session];
630  if (status != NSRunContinuesResponse && session == d->currentModalSessionCached) {
631  // INVARIANT: Someone called [NSApp stopModal:] from outside the event
632  // dispatcher (e.g to stop a native dialog). But that call wrongly stopped
633  // 'session' as well. As a result, we need to restart all internal sessions:
634  d->temporarilyStopAllModalSessions();
635  }
636  retVal = true;
637  } else do {
638  // Dispatch all non-user events (but que non-user events up for later). In
639  // this case, we need more control over which events gets dispatched, and
640  // cannot use [NSApp runModalSession:session]:
641  event = [NSApp nextEventMatchingMask:NSAnyEventMask
642  untilDate:nil
643  inMode:NSModalPanelRunLoopMode
644  dequeue: YES];
645 
646  if (event) {
647  if (IsMouseOrKeyEvent(event)) {
648  [event retain];
649  d->queuedUserInputEvents.append(event);
650  continue;
651  }
652  if (!filterEvent(event) && qt_mac_send_event(flags, event, 0))
653  retVal = true;
654  }
655  } while (!d->interrupt && event != nil);
656  } else do {
657  // INVARIANT: No modal window is executing.
658  event = [NSApp nextEventMatchingMask:NSAnyEventMask
659  untilDate:nil
660  inMode:NSDefaultRunLoopMode
661  dequeue: YES];
662 
663  if (event) {
664  if (flags & QEventLoop::ExcludeUserInputEvents) {
665  if (IsMouseOrKeyEvent(event)) {
666  [event retain];
667  d->queuedUserInputEvents.append(event);
668  continue;
669  }
670  }
671  if (!filterEvent(event) && qt_mac_send_event(flags, event, 0))
672  retVal = true;
673  }
674  } while (!d->interrupt && event != nil);
675 
676  // Be sure to flush the Qt posted events when not using exec mode
677  // (exec mode will always do this call from the event loop source):
678  if (!d->interrupt)
679  QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
680 
681  // Since the window that holds modality might have changed while processing
682  // events, we we need to interrupt when we return back the previous process
683  // event recursion to ensure that we spin the correct modal session.
684  // We do the interruptLater at the end of the function to ensure that we don't
685  // disturb the 'wait for more events' below (as deleteLater will post an event):
686  interruptLater = true;
687  }
688 #else
689  do {
690  EventRef event;
691  if (!(flags & QEventLoop::ExcludeUserInputEvents)
692  && !d->queuedUserInputEvents.isEmpty()) {
693  // process a pending user input event
694  event = static_cast<EventRef>(d->queuedUserInputEvents.takeFirst());
695  } else {
696  OSStatus err = ReceiveNextEvent(0,0, kEventDurationNoWait, true, &event);
697  if(err != noErr)
698  continue;
699  // else
700  if (flags & QEventLoop::ExcludeUserInputEvents) {
701  UInt32 ekind = GetEventKind(event),
702  eclass = GetEventClass(event);
703  switch(eclass) {
704  case kEventClassQt:
705  if(ekind != kEventQtRequestContext)
706  break;
707  // fall through
708  case kEventClassMouse:
709  case kEventClassKeyboard:
710  d->queuedUserInputEvents.append(event);
711  continue;
712  }
713  }
714  }
715 
716  if (!filterEvent(&event) && qt_mac_send_event(flags, event, 0))
717  retVal = true;
718  ReleaseEvent(event);
719  } while(!d->interrupt && GetNumEventsInQueue(GetMainEventQueue()) > 0);
720 
721 #endif
722 
723  bool canWait = (d->threadData->canWait
724  && !retVal
725  && !d->interrupt
726  && (flags & QEventLoop::WaitForMoreEvents));
727  if (canWait) {
728  // INVARIANT: We haven't processed any events yet. And we're told
729  // to stay inside this function until at least one event is processed.
731  flags &= ~QEventLoop::WaitForMoreEvents;
732  } else {
733  // Done with event processing for now.
734  // Leave the function:
735  break;
736  }
737  }
738 
739  // If we're interrupted, we need to interrupt the _current_
740  // recursion as well to check if it is still supposed to be
741  // executing. This way we wind down the stack until we land
742  // on a recursion that again calls processEvents (typically
743  // from QEventLoop), and set interrupt to false:
744  if (d->interrupt)
745  interrupt();
746 
747 #ifdef QT_MAC_USE_COCOA
748  if (interruptLater)
749  QtMacInterruptDispatcherHelp::interruptLater();
750 #endif
751 
752  return retVal;
753 }
754 
756 {
758  d->serialNumber.ref();
759  CFRunLoopSourceSignal(d->postedEventsSource);
760  CFRunLoopWakeUp(mainRunLoop());
761 }
762 
764 {
765  if(qApp) {
767  for(int i = 0; i < tlws.size(); i++) {
768  QWidget *tlw = tlws.at(i);
769  if(tlw->isVisible())
771  }
772  }
773 }
774 
775 /*****************************************************************************
776  QEventDispatcherMac Implementation
777  *****************************************************************************/
781 
782 #ifdef QT_MAC_USE_COCOA
783 QStack<QCocoaModalSessionInfo> QEventDispatcherMacPrivate::cocoaModalSessionStack;
784 bool QEventDispatcherMacPrivate::currentExecIsNSAppRun = false;
785 bool QEventDispatcherMacPrivate::nsAppRunCalledByQt = false;
786 bool QEventDispatcherMacPrivate::cleanupModalSessionsNeeded = false;
787 NSModalSession QEventDispatcherMacPrivate::currentModalSessionCached = 0;
788 
789 void QEventDispatcherMacPrivate::ensureNSAppInitialized()
790 {
791  // Some elements in Cocoa require NSApplication to be running before
792  // they get fully initialized, in particular the menu bar. This
793  // function is intended for cases where a dialog is told to execute before
794  // QApplication::exec is called, or the application spins the events loop
795  // manually rather than calling QApplication:exec.
796  // The function makes sure that NSApplication starts running, but stops
797  // it again as soon as the send posted events callback is called. That way
798  // we let Cocoa finish the initialization it seems to need. We'll only
799  // apply this trick at most once for any application, and we avoid doing it
800  // for the common case where main just starts QApplication::exec.
801  if (nsAppRunCalledByQt || [NSApp isRunning])
802  return;
803  nsAppRunCalledByQt = true;
804  QBoolBlocker block1(interrupt, true);
805  QBoolBlocker block2(currentExecIsNSAppRun, true);
806  [NSApp run];
807 }
808 
809 void QEventDispatcherMacPrivate::temporarilyStopAllModalSessions()
810 {
811  // Flush, and Stop, all created modal session, and as
812  // such, make them pending again. The next call to
813  // currentModalSession will recreate them again. The
814  // reason to stop all session like this is that otherwise
815  // a call [NSApp stop] would not stop NSApp, but rather
816  // the current modal session. So if we need to stop NSApp
817  // we need to stop all the modal session first. To avoid changing
818  // the stacking order of the windows while doing so, we put
819  // up a block that is used in QCocoaWindow and QCocoaPanel:
820  int stackSize = cocoaModalSessionStack.size();
821  for (int i=0; i<stackSize; ++i) {
822  QCocoaModalSessionInfo &info = cocoaModalSessionStack[i];
823  if (info.session) {
824  [NSApp endModalSession:info.session];
825  info.session = 0;
826  }
827  }
828  currentModalSessionCached = 0;
829 }
830 
831 NSModalSession QEventDispatcherMacPrivate::currentModalSession()
832 {
833  // If we have one or more modal windows, this function will create
834  // a session for each of those, and return the one for the top.
835  if (currentModalSessionCached)
836  return currentModalSessionCached;
837 
838  if (cocoaModalSessionStack.isEmpty())
839  return 0;
840 
841  int sessionCount = cocoaModalSessionStack.size();
842  for (int i=0; i<sessionCount; ++i) {
843  QCocoaModalSessionInfo &info = cocoaModalSessionStack[i];
844  if (!info.widget)
845  continue;
846  if (info.widget->testAttribute(Qt::WA_DontShowOnScreen))
847  continue;
848  if (!info.session) {
850  NSWindow *window = qt_mac_window_for(info.widget);
851  if (!window)
852  continue;
853 
854  ensureNSAppInitialized();
855  QBoolBlocker block1(blockSendPostedEvents, true);
856  info.nswindow = window;
857  [(NSWindow*) info.nswindow retain];
858  int levelBeforeEnterModal = [window level];
859  info.session = [NSApp beginModalSessionForWindow:window];
860  // Make sure we don't stack the window lower that it was before
861  // entering modal, in case it e.g. had the stays-on-top flag set:
862  if (levelBeforeEnterModal > [window level])
863  [window setLevel:levelBeforeEnterModal];
864  }
865  currentModalSessionCached = info.session;
866  cleanupModalSessionsNeeded = false;
867  }
868  return currentModalSessionCached;
869 }
870 
871 static void setChildrenWorksWhenModal(QWidget *widget, bool worksWhenModal)
872 {
873  // For NSPanels (but not NSWindows, sadly), we can set the flag
874  // worksWhenModal, so that they are active even when they are not modal.
875  QList<QDialog *> dialogs = widget->findChildren<QDialog *>();
876  for (int i=0; i<dialogs.size(); ++i){
877  NSWindow *window = qt_mac_window_for(dialogs[i]);
878  if (window && [window isKindOfClass:[NSPanel class]]) {
879  [static_cast<NSPanel *>(window) setWorksWhenModal:worksWhenModal];
880  if (worksWhenModal && [window isVisible]){
881  [window orderFront:window];
882  }
883  }
884  }
885 }
886 
887 void QEventDispatcherMacPrivate::updateChildrenWorksWhenModal()
888 {
889  // Make the dialog children of the widget
890  // active. And make the dialog children of
891  // the previous modal dialog unactive again:
893  int size = cocoaModalSessionStack.size();
894  if (size > 0){
895  if (QWidget *prevModal = cocoaModalSessionStack[size-1].widget)
896  setChildrenWorksWhenModal(prevModal, true);
897  if (size > 1){
898  if (QWidget *prevModal = cocoaModalSessionStack[size-2].widget)
899  setChildrenWorksWhenModal(prevModal, false);
900  }
901  }
902 }
903 
904 void QEventDispatcherMacPrivate::cleanupModalSessions()
905 {
906  // Go through the list of modal sessions, and end those
907  // that no longer has a widget assosiated; no widget means
908  // the the session has logically ended. The reason we wait like
909  // this to actually end the sessions for real (rather than at the
910  // point they were marked as stopped), is that ending a session
911  // when no other session runs below it on the stack will make cocoa
912  // drop some events on the floor.
914  int stackSize = cocoaModalSessionStack.size();
915 
916  for (int i=stackSize-1; i>=0; --i) {
917  QCocoaModalSessionInfo &info = cocoaModalSessionStack[i];
918  if (info.widget) {
919  // This session has a widget, and is therefore not marked
920  // as stopped. So just make it current. There might still be other
921  // stopped sessions on the stack, but those will be stopped on
922  // a later "cleanup" call.
923  currentModalSessionCached = info.session;
924  break;
925  }
926  cocoaModalSessionStack.remove(i);
927  currentModalSessionCached = 0;
928  if (info.session) {
929  [NSApp endModalSession:info.session];
930  [(NSWindow *)info.nswindow release];
931  }
932  }
933 
934  updateChildrenWorksWhenModal();
935  cleanupModalSessionsNeeded = false;
936 }
937 
938 void QEventDispatcherMacPrivate::beginModalSession(QWidget *widget)
939 {
940  // Add a new, empty (null), NSModalSession to the stack.
941  // It will become active the next time QEventDispatcher::processEvents is called.
942  // A QCocoaModalSessionInfo is considered pending to become active if the widget pointer
943  // is non-zero, and the session pointer is zero (it will become active upon a call to
944  // currentModalSession). A QCocoaModalSessionInfo is considered pending to be stopped if
945  // the widget pointer is zero, and the session pointer is non-zero (it will be fully
946  // stopped in cleanupModalSessions()).
947  QCocoaModalSessionInfo info = {widget, 0, 0};
948  cocoaModalSessionStack.push(info);
949  updateChildrenWorksWhenModal();
950  currentModalSessionCached = 0;
951 }
952 
953 void QEventDispatcherMacPrivate::endModalSession(QWidget *widget)
954 {
955  // Mark all sessions attached to widget as pending to be stopped. We do this
956  // by setting the widget pointer to zero, but leave the session pointer.
957  // We don't tell cocoa to stop any sessions just yet, because cocoa only understands
958  // when we stop the _current_ modal session (which is the session on top of
959  // the stack, and might not belong to 'widget').
960  int stackSize = cocoaModalSessionStack.size();
961  for (int i=stackSize-1; i>=0; --i) {
962  QCocoaModalSessionInfo &info = cocoaModalSessionStack[i];
963  if (info.widget == widget) {
964  info.widget = 0;
965  if (i == stackSize-1) {
966  // The top sessions ended. Interrupt the event dispatcher
967  // to start spinning the correct session immidiatly:
968  currentModalSessionCached = 0;
969  cleanupModalSessionsNeeded = true;
971  }
972  }
973  }
974 }
975 
976 #endif
977 
979 {
980 }
981 
984 {
986  CFRunLoopSourceContext context;
987  bzero(&context, sizeof(CFRunLoopSourceContext));
988  context.info = d;
991  d->postedEventsSource = CFRunLoopSourceCreate(0, 0, &context);
992  Q_ASSERT(d->postedEventsSource);
993  CFRunLoopAddSource(mainRunLoop(), d->postedEventsSource, kCFRunLoopCommonModes);
994 
995  CFRunLoopObserverContext observerContext;
996  bzero(&observerContext, sizeof(CFRunLoopObserverContext));
997  observerContext.info = this;
998  d->waitingObserver = CFRunLoopObserverCreate(kCFAllocatorDefault,
999  kCFRunLoopBeforeWaiting | kCFRunLoopAfterWaiting,
1000  true, 0,
1002  &observerContext);
1003  CFRunLoopAddObserver(mainRunLoop(), d->waitingObserver, kCFRunLoopCommonModes);
1004 
1005  /* The first cycle in the loop adds the source and the events of the source
1006  are not processed.
1007  We use an observer to process the posted events for the first
1008  execution of the loop. */
1009  CFRunLoopObserverContext firstTimeObserverContext;
1010  bzero(&firstTimeObserverContext, sizeof(CFRunLoopObserverContext));
1011  firstTimeObserverContext.info = d;
1012  d->firstTimeObserver = CFRunLoopObserverCreate(kCFAllocatorDefault,
1013  kCFRunLoopEntry,
1014  /* repeats = */ false,
1015  0,
1017  &firstTimeObserverContext);
1018  CFRunLoopAddObserver(mainRunLoop(), d->firstTimeObserver, kCFRunLoopCommonModes);
1019 }
1020 
1022  CFRunLoopActivity activity, void *info)
1023 {
1024  if (activity == kCFRunLoopBeforeWaiting)
1025  emit static_cast<QEventDispatcherMac*>(info)->aboutToBlock();
1026  else
1027  emit static_cast<QEventDispatcherMac*>(info)->awake();
1028 }
1029 
1031 {
1032  return info1 == info2;
1033 }
1034 
1035 inline static void processPostedEvents(QEventDispatcherMacPrivate *const d, const bool blockSendPostedEvents)
1036 {
1037  if (blockSendPostedEvents) {
1038  // We're told to not send posted events (because the event dispatcher
1039  // is currently working on setting up the correct session to run). But
1040  // we still need to make sure that we don't fall asleep until pending events
1041  // are sendt, so we just signal this need, and return:
1042  CFRunLoopSourceSignal(d->postedEventsSource);
1043  return;
1044  }
1045 
1046 #ifdef QT_MAC_USE_COCOA
1047  if (d->cleanupModalSessionsNeeded)
1048  d->cleanupModalSessions();
1049 #endif
1050 
1051  if (d->interrupt) {
1052 #ifdef QT_MAC_USE_COCOA
1053  if (d->currentExecIsNSAppRun) {
1054  // The event dispatcher has been interrupted. But since
1055  // [NSApplication run] is running the event loop, we
1056  // delayed stopping it until now (to let cocoa process
1057  // pending cocoa events first).
1058  if (d->currentModalSessionCached)
1059  d->temporarilyStopAllModalSessions();
1060  [NSApp stop:NSApp];
1061  d->cancelWaitForMoreEvents();
1062  }
1063 #endif
1064  return;
1065  }
1066 
1067  if (!d->threadData->canWait || (d->serialNumber != d->lastSerial)) {
1068  d->lastSerial = d->serialNumber;
1070  }
1071 }
1072 
1073 void QEventDispatcherMacPrivate::firstLoopEntry(CFRunLoopObserverRef ref,
1074  CFRunLoopActivity activity,
1075  void *info)
1076 {
1077  Q_UNUSED(ref);
1078  Q_UNUSED(activity);
1079 #ifdef QT_MAC_USE_COCOA
1080  QApplicationPrivate::qt_initAfterNSAppStarted();
1081 #endif
1082  processPostedEvents(static_cast<QEventDispatcherMacPrivate *>(info), blockSendPostedEvents);
1083 }
1084 
1086 {
1087  processPostedEvents(static_cast<QEventDispatcherMacPrivate *>(info), blockSendPostedEvents);
1088 }
1089 
1090 #ifdef QT_MAC_USE_COCOA
1091 void QEventDispatcherMacPrivate::cancelWaitForMoreEvents()
1092 {
1093  // In case the event dispatcher is waiting for more
1094  // events somewhere, we post a dummy event to wake it up:
1096  [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint
1097  modifierFlags:0 timestamp:0. windowNumber:0 context:0
1098  subtype:QtCocoaEventSubTypeWakeup data1:0 data2:0] atStart:NO];
1099 }
1100 #endif
1101 
1103 {
1105  d->interrupt = true;
1106  wakeUp();
1107 
1108 #ifndef QT_MAC_USE_COCOA
1109  CFRunLoopStop(mainRunLoop());
1110 #else
1111  // We do nothing more here than setting d->interrupt = true, and
1112  // poke the event loop if it is sleeping. Actually stopping
1113  // NSApp, or the current modal session, is done inside the send
1114  // posted events callback. We do this to ensure that all current pending
1115  // cocoa events gets delivered before we stop. Otherwise, if we now stop
1116  // the last event loop recursion, cocoa will just drop pending posted
1117  // events on the floor before we get a chance to reestablish a new session.
1118  d->cancelWaitForMoreEvents();
1119 #endif
1120 }
1121 
1123 {
1125  //timer cleanup
1126  MacTimerHash::iterator it = QEventDispatcherMacPrivate::macTimerHash.begin();
1127  while (it != QEventDispatcherMacPrivate::macTimerHash.end()) {
1128  MacTimerInfo *t = it.value();
1129  if (t->runLoopTimer) {
1130  CFRunLoopTimerInvalidate(t->runLoopTimer);
1131  CFRelease(t->runLoopTimer);
1132  }
1133  delete t;
1134  ++it;
1135  }
1136  QEventDispatcherMacPrivate::macTimerHash.clear();
1137 
1138  // Remove CFSockets from the runloop.
1139  for (MacSocketHash::ConstIterator it = d->macSockets.constBegin(); it != d->macSockets.constEnd(); ++it) {
1140  MacSocketInfo *socketInfo = (*it);
1141  if (CFSocketIsValid(socketInfo->socket)) {
1142  qt_mac_remove_socket_from_runloop(socketInfo->socket, socketInfo->runloop);
1143  CFRunLoopSourceInvalidate(socketInfo->runloop);
1144  CFRelease(socketInfo->runloop);
1145  CFSocketInvalidate(socketInfo->socket);
1146  CFRelease(socketInfo->socket);
1147  }
1148  }
1149  CFRunLoopRemoveSource(mainRunLoop(), d->postedEventsSource, kCFRunLoopCommonModes);
1150  CFRelease(d->postedEventsSource);
1151 
1152  CFRunLoopObserverInvalidate(d->waitingObserver);
1153  CFRelease(d->waitingObserver);
1154 
1155  CFRunLoopObserverInvalidate(d->firstTimeObserver);
1156  CFRelease(d->firstTimeObserver);
1157 }
1158 
1159 #ifdef QT_MAC_USE_COCOA
1160 
1161 QtMacInterruptDispatcherHelp* QtMacInterruptDispatcherHelp::instance = 0;
1162 
1163 QtMacInterruptDispatcherHelp::QtMacInterruptDispatcherHelp() : cancelled(false)
1164 {
1165  // The whole point of this class is that we enable a way to interrupt
1166  // the event dispatcher when returning back to a lower recursion level
1167  // than where interruptLater was called. This is needed to detect if
1168  // [NSApp run] should still be running at the recursion level it is at.
1169  // Since the interrupt is canceled if processEvents is called before
1170  // this object gets deleted, we also avoid interrupting unnecessary.
1171  deleteLater();
1172 }
1173 
1174 QtMacInterruptDispatcherHelp::~QtMacInterruptDispatcherHelp()
1175 {
1176  if (cancelled)
1177  return;
1178  instance = 0;
1180 }
1181 
1182 void QtMacInterruptDispatcherHelp::cancelInterruptLater()
1183 {
1184  if (!instance)
1185  return;
1186  instance->cancelled = true;
1187  delete instance;
1188  instance = 0;
1189 }
1190 
1191 void QtMacInterruptDispatcherHelp::interruptLater()
1192 {
1193  cancelInterruptLater();
1194  instance = new QtMacInterruptDispatcherHelp;
1195 }
1196 
1197 #endif
1198 
1200 
double d
Definition: qnumeric_p.h:62
static bool qt_mac_send_event(QEventLoop::ProcessEventsFlags, OSEventRef event, OSWindowRef pt)
static void sendPostedEvents(QObject *receiver, int event_type, QThreadData *data)
OSWindowRef qt_mac_window_for(const QWidget *)
Definition: qwidget_mac.mm:484
The QHash::const_iterator class provides an STL-style const iterator for QHash and QMultiHash...
Definition: qhash.h:395
virtual void interrupt()=0
Interrupts event dispatching; i.
int type
Definition: qmetatype.cpp:239
static mach_timebase_info_data_t info
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
EventRef event
QPointer< QWidget > widget
void clear()
Removes all items from the hash.
Definition: qhash.h:574
#define it(className, varName)
The QDialog class is the base class of dialog windows.
Definition: qdialog.h:56
CFRunLoopTimerRef runLoopTimer
static void postEvent(QObject *receiver, QEvent *event)
Adds the event event, with the object receiver as the receiver of the event, to an event queue and re...
void qt_mac_remove_socket_from_runloop(const CFSocketRef socket, CFRunLoopSourceRef runloop)
bool isVisible() const
Definition: qwidget.h:1005
static QAbstractEventDispatcher * instance(QThread *thread=0)
Returns a pointer to the event dispatcher object for the specified thread.
bool processEvents(QEventLoop::ProcessEventsFlags flags)
Processes pending events that match flags until there are no more events to process.
bool qt_is_gui_used
static void qt_mac_waitForMoreEvents()
void macWindowFlush(void *window)
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
void qt_event_request_select(QEventDispatcherMac *)
static LibLoadStatus status
Definition: qlocale_icu.cpp:69
The QStack class is a template class that provides a stack.
Definition: qcontainerfwd.h:63
bool canWait
Definition: qthread_p.h:267
T & value() const
Returns a modifiable reference to the current item&#39;s value.
Definition: qhash.h:348
bool hasPendingEvents()
Returns true if there is an event waiting; otherwise returns false.
T take(const Key &key)
Removes the item with the key from the hash and returns the value associated with it...
Definition: qhash.h:807
The QHash class is a template class that provides a hash-table-based dictionary.
Definition: qdatastream.h:66
bool qt_sendSpontaneousEvent(QObject *, QEvent *)
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
#define Q_D(Class)
Definition: qglobal.h:2482
static QObjectPrivate * get(QObject *o)
Definition: qobject_p.h:177
QThreadData * threadData
Definition: qobject_p.h:195
static void processPostedEvents(QEventDispatcherMacPrivate *const d, const bool blockSendPostedEvents)
const T value(const Key &key) const
Returns the value associated with the key.
Definition: qhash.h:606
Type type() const
Returns the socket event type specified to the constructor.
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition: qhash.h:753
The QSocketNotifier class provides support for monitoring activity on a file descriptor.
void registerTimer(int timerId, int interval, QObject *object)
Register a timer with the specified timerId and interval for the given object.
static void postedEventsSourcePerformCallback(void *info)
NSWindow * window
static QThread * currentThread()
Returns a pointer to a QThread which manages the currently executing thread.
Definition: qthread.cpp:419
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
void awake()
This signal is emitted after the event loop returns from a function that could block.
bool unregisterTimers(QObject *object)
Unregisters all the timers associated with the given object.
CFRunLoopSourceRef qt_mac_add_socket_to_runloop(const CFSocketRef socket)
The QEventLoop class provides a means of entering and leaving an event loop.
Definition: qeventloop.h:55
WindowRef OSWindowRef
QList< TimerInfo > registeredTimers(QObject *object) const
Returns a list of registered timers for object.
void qt_event_request_updates()
#define qApp
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
#define emit
Definition: qobjectdefs.h:76
CFRunLoopSourceRef runloop
const T & value() const
Returns the current item&#39;s value.
Definition: qhash.h:420
Q_CORE_EXPORT void qWarning(const char *,...)
uint inThreadChangeEvent
Definition: qobject.h:103
unsigned int uint
Definition: qglobal.h:996
static void activateTimer(CFRunLoopTimerRef, void *info)
static void waitingObserverCallback(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info)
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
__int64 qint64
Definition: qglobal.h:942
Q_CORE_EXPORT uint qGlobalPostedEventsCount()
signed long OSStatus
static QWidgetList topLevelWidgets()
Returns a list of the top-level widgets (windows) in the application.
QEventDispatcherMac(QObject *parent=0)
struct OpaqueEventRef * EventRef
void wakeUp()
Wakes up the event loop.
void qt_event_request_timer(MacTimerInfo *)
const_iterator constBegin() const
Returns a const STL-style iterator pointing to the first item in the hash.
Definition: qhash.h:466
Q_CORE_EXPORT void qFatal(const char *,...)
static CFRunLoopRef mainRunLoop()
void aboutToBlock()
This signal is emitted before the event loop calls a function that could block.
The QTimerEvent class contains parameters that describe a timer event.
Definition: qcoreevent.h:341
bool unregisterTimer(int timerId)
Unregisters the timer with the given timerId.
EventRef OSEventRef
void unregisterSocketNotifier(QSocketNotifier *notifier)
Unregisters notifier from the event dispatcher.
static QTestResult::TestLocation location
Definition: qtestresult.cpp:63
void qt_mac_socket_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef, const void *, void *info)
const UInt32 kEventClassQt
Definition: qt_mac_p.h:92
The QHash::iterator class provides an STL-style non-const iterator for QHash and QMultiHash.
Definition: qhash.h:330
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
if(void) toggleToolbarShown
iterator begin()
Returns an STL-style iterator pointing to the first item in the hash.
Definition: qhash.h:464
void interrupt()
Interrupts event dispatching; i.
#define QT_USE_NAMESPACE
This macro expands to using QT_NAMESPACE if QT_NAMESPACE is defined and nothing otherwise.
Definition: qglobal.h:88
QObject * parent
Definition: qobject.h:92
QFuture< T > run(Function function,...)
void registerSocketNotifier(QSocketNotifier *notifier)
Registers notifier with the event loop.
bool qt_mac_is_macsheet(const QWidget *)
Definition: qwidget_mac.mm:295
QThread * thread() const
Returns the thread in which the object lives.
Definition: qobject.cpp:1419
static const KeyPair *const end
The QEvent class is the base class of all event classes.
Definition: qcoreevent.h:56
MacTimerInfo * qt_event_get_timer(EventRef)
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
static void firstLoopEntry(CFRunLoopObserverRef ref, CFRunLoopActivity activity, void *info)
static Boolean postedEventSourceEqualCallback(const void *info1, const void *info2)
void deleteLater()
Schedules this object for deletion.
Definition: qobject.cpp:2145
QList< T > findChildren(const QString &aName=QString()) const
Returns all children of this object with the given name that can be cast to type T, or an empty list if there are no such objects.
Definition: qobject.h:162
iterator erase(iterator it)
Removes the (key, value) pair associated with the iterator pos from the hash, and returns an iterator...
Definition: qhash.h:827
void flush()
Flushes the event queue.
The QAbstractEventDispatcher class provides an interface to manage Qt&#39;s event queue.
int socket() const
Returns the socket identifier specified to the constructor.
The QList class is a template class that provides lists.
Definition: qdatastream.h:62
#define forever
This macro is provided for convenience for writing infinite loops.
Definition: qglobal.h:2452