1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 /****************************************************************************
41 **
42 ** Copyright (c) 2007-2008, Apple, Inc.
43 **
44 ** All rights reserved.
45 **
46 ** Redistribution and use in source and binary forms, with or without
47 ** modification, are permitted provided that the following conditions are met:
48 **
49 **   * Redistributions of source code must retain the above copyright notice,
50 **     this list of conditions and the following disclaimer.
51 **
52 **   * Redistributions in binary form must reproduce the above copyright notice,
53 **     this list of conditions and the following disclaimer in the documentation
54 **     and/or other materials provided with the distribution.
55 **
56 **   * Neither the name of Apple, Inc. nor the names of its contributors
57 **     may be used to endorse or promote products derived from this software
58 **     without specific prior written permission.
59 **
60 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
61 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
62 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
63 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
64 ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
65 ** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
66 ** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
67 ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
68 ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
69 ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
70 ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
71 **
72 ****************************************************************************/
73 
74 #ifndef QEVENTDISPATCHER_MAC_P_H
75 #define QEVENTDISPATCHER_MAC_P_H
76 
77 //
78 //  W A R N I N G
79 //  -------------
80 //
81 // This file is not part of the Qt API.  It exists purely as an
82 // implementation detail.  This header file may change from version to
83 // version without notice, or even be removed.
84 //
85 // We mean it.
86 //
87 
88 #include <QtCore/qabstracteventdispatcher.h>
89 #include <QtCore/qstack.h>
90 #include <QtGui/qwindowdefs.h>
91 #include <QtCore/private/qabstracteventdispatcher_p.h>
92 #include <QtCore/private/qcfsocketnotifier_p.h>
93 #include <QtCore/private/qtimerinfo_unix_p.h>
94 
95 #include <CoreFoundation/CoreFoundation.h>
96 
97 QT_BEGIN_NAMESPACE
98 
99 typedef struct _NSModalSession *NSModalSession;
100 typedef struct _QCocoaModalSessionInfo {
101     QPointer<QWindow> window;
102     NSModalSession session;
103     void *nswindow;
104 } QCocoaModalSessionInfo;
105 
106 class QCocoaEventDispatcherPrivate;
107 class QCocoaEventDispatcher : public QAbstractEventDispatcher
108 {
109     Q_OBJECT
110     Q_DECLARE_PRIVATE(QCocoaEventDispatcher)
111 
112 public:
113     QCocoaEventDispatcher(QAbstractEventDispatcherPrivate &priv, QObject *parent = nullptr);
114     explicit QCocoaEventDispatcher(QObject *parent = nullptr);
115     ~QCocoaEventDispatcher();
116 
117     bool processEvents(QEventLoop::ProcessEventsFlags flags);
118     bool hasPendingEvents();
119 
120     void registerSocketNotifier(QSocketNotifier *notifier);
121     void unregisterSocketNotifier(QSocketNotifier *notifier);
122 
123     void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object);
124     bool unregisterTimer(int timerId);
125     bool unregisterTimers(QObject *object);
126     QList<TimerInfo> registeredTimers(QObject *object) const;
127 
128     int remainingTime(int timerId);
129 
130     void wakeUp();
131     void interrupt();
132     void flush();
133 
134     static void clearCurrentThreadCocoaEventDispatcherInterruptFlag();
135 
136     friend void qt_mac_maybeCancelWaitForMoreEventsForwarder(QAbstractEventDispatcher *eventDispatcher);
137 };
138 
139 class QCocoaEventDispatcherPrivate : public QAbstractEventDispatcherPrivate
140 {
141     Q_DECLARE_PUBLIC(QCocoaEventDispatcher)
142 
143 public:
144     QCocoaEventDispatcherPrivate();
145 
146     uint processEventsFlags;
147 
148     // timer handling
149     QTimerInfoList timerInfoList;
150     CFRunLoopTimerRef runLoopTimerRef;
151     CFRunLoopSourceRef activateTimersSourceRef;
152     void maybeStartCFRunLoopTimer();
153     void maybeStopCFRunLoopTimer();
154     static void runLoopTimerCallback(CFRunLoopTimerRef, void *info);
155     static void activateTimersSourceCallback(void *info);
156     bool processTimers();
157 
158     // Set 'blockSendPostedEvents' to true if you _really_ need
159     // to make sure that qt events are not posted while calling
160     // low-level cocoa functions (like beginModalForWindow). And
161     // use a QBoolBlocker to be safe:
162     bool blockSendPostedEvents;
163     // The following variables help organizing modal sessions:
164     QStack<QCocoaModalSessionInfo> cocoaModalSessionStack;
165     bool currentExecIsNSAppRun;
166     bool nsAppRunCalledByQt;
167     bool cleanupModalSessionsNeeded;
168     uint processEventsCalled;
169     NSModalSession currentModalSessionCached;
170     NSModalSession currentModalSession();
171     void temporarilyStopAllModalSessions();
172     void beginModalSession(QWindow *widget);
173     void endModalSession(QWindow *widget);
174     bool hasModalSession() const;
175     void cleanupModalSessions();
176 
177     void cancelWaitForMoreEvents();
178     void maybeCancelWaitForMoreEvents();
179     void ensureNSAppInitialized();
180 
181     QCFSocketNotifier cfSocketNotifier;
182     QList<void *> queuedUserInputEvents; // NSEvent *
183     CFRunLoopSourceRef postedEventsSource;
184     CFRunLoopObserverRef waitingObserver;
185     CFRunLoopObserverRef firstTimeObserver;
186     QAtomicInt serialNumber;
187     int lastSerial;
188     bool interrupt;
189     bool propagateInterrupt = false;
190 
191     static void postedEventsSourceCallback(void *info);
192     static void waitingObserverCallback(CFRunLoopObserverRef observer,
193                                         CFRunLoopActivity activity, void *info);
194     static void firstLoopEntry(CFRunLoopObserverRef ref, CFRunLoopActivity activity, void *info);
195     bool sendQueuedUserInputEvents();
196     void processPostedEvents();
197 };
198 
199 class QtCocoaInterruptDispatcher : public QObject
200 {
201     static QtCocoaInterruptDispatcher *instance;
202     bool cancelled;
203 
204     QtCocoaInterruptDispatcher();
205     ~QtCocoaInterruptDispatcher();
206 
207     public:
208     static void interruptLater();
209     static void cancelInterruptLater();
210 };
211 
212 QT_END_NAMESPACE
213 
214 #endif // QEVENTDISPATCHER_MAC_P_H
215