diff options
Diffstat (limited to 'src/plugins/platforms/cocoa')
-rw-r--r-- | src/plugins/platforms/cocoa/cocoa.pro | 5 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm | 20 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaclipboard.mm | 2 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaeventdispatcher.h | 1 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm | 94 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaintegration.h | 4 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaintegration.mm | 10 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoasessionmanager.cpp | 88 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoasessionmanager.h | 81 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoasystemtrayicon.h | 2 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm | 9 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoatheme.h | 2 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qmacclipboard.mm | 8 |
13 files changed, 275 insertions, 51 deletions
diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index 4cf9e64447..8f2956e7d4 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -87,6 +87,11 @@ qtConfig(accessibility) { qcocoaaccessibility.h } +qtConfig(sessionmanager) { + SOURCES += qcocoasessionmanager.cpp + HEADERS += qcocoasessionmanager.h +} + RESOURCES += qcocoaresources.qrc LIBS += -framework AppKit -framework CoreServices -framework Carbon -framework IOKit -framework QuartzCore -framework CoreVideo -framework Metal -framework IOSurface -lcups diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm index 9b0a6b1b86..3fb9e83d35 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm @@ -79,11 +79,14 @@ #include "qcocoamenuitem.h" #include "qcocoansmenu.h" +#if QT_CONFIG(sessionmanager) +# include "qcocoasessionmanager.h" +#endif + #include <qevent.h> #include <qurl.h> #include <qdebug.h> #include <qguiapplication.h> -#include <private/qguiapplication_p.h> #include "qt_mac_p.h" #include <qpa/qwindowsysteminterface.h> #include <qwindowdefs.h> @@ -149,7 +152,7 @@ QT_USE_NAMESPACE if ([reflectionDelegate respondsToSelector:_cmd]) return [reflectionDelegate applicationShouldTerminate:sender]; - if (QGuiApplicationPrivate::instance()->threadData->eventLoops.isEmpty()) { + if (QGuiApplicationPrivate::instance()->threadData.loadRelaxed()->eventLoops.isEmpty()) { // No event loop is executing. This probably means that Qt is used as a plugin, // or as a part of a native Cocoa application. In any case it should be fine to // terminate now. @@ -157,6 +160,17 @@ QT_USE_NAMESPACE return NSTerminateNow; } +#if QT_CONFIG(sessionmanager) + QCocoaSessionManager *cocoaSessionManager = QCocoaSessionManager::instance(); + cocoaSessionManager->resetCancellation(); + cocoaSessionManager->appCommitData(); + + if (cocoaSessionManager->wasCanceled()) { + qCDebug(lcQpaApplication) << "Session management canceled application termination"; + return NSTerminateCancel; + } +#endif + if (!QWindowSystemInterface::handleApplicationTermination<QWindowSystemInterface::SynchronousDelivery>()) { qCDebug(lcQpaApplication) << "Application termination canceled"; return NSTerminateCancel; @@ -359,7 +373,7 @@ QT_USE_NAMESPACE if (!platformItem || platformItem->menu()) return; - QScopedScopeLevelCounter scopeLevelCounter(QGuiApplicationPrivate::instance()->threadData); + QScopedScopeLevelCounter scopeLevelCounter(QGuiApplicationPrivate::instance()->threadData.loadRelaxed()); QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers:[NSEvent modifierFlags]]; static QMetaMethod activatedSignal = QMetaMethod::fromSignal(&QCocoaMenuItem::activated); diff --git a/src/plugins/platforms/cocoa/qcocoaclipboard.mm b/src/plugins/platforms/cocoa/qcocoaclipboard.mm index a35c153084..141940cc50 100644 --- a/src/plugins/platforms/cocoa/qcocoaclipboard.mm +++ b/src/plugins/platforms/cocoa/qcocoaclipboard.mm @@ -67,7 +67,7 @@ void QCocoaClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) } pasteBoard->sync(); - pasteBoard->setMimeData(data); + pasteBoard->setMimeData(data, QMacPasteboard::LazyRequest); emitChanged(mode); } } diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h index 69587a24be..b8d2532b8e 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h @@ -186,6 +186,7 @@ public: QAtomicInt serialNumber; int lastSerial; bool interrupt; + bool propagateInterrupt = false; static void postedEventsSourceCallback(void *info); static void waitingObserverCallback(CFRunLoopObserverRef observer, diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index e87fc39c42..94b9e62eab 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -84,13 +84,12 @@ #include "private/qthread_p.h" #include "private/qguiapplication_p.h" #include <qdebug.h> +#include <qscopeguard.h> #include <AppKit/AppKit.h> QT_BEGIN_NAMESPACE -QT_USE_NAMESPACE - static inline CFRunLoopRef mainRunLoop() { return CFRunLoopGetMain(); @@ -293,46 +292,42 @@ bool QCocoaEventDispatcher::hasPendingEvents() return qGlobalPostedEventsCount() || (qt_is_gui_used && !CFRunLoopIsWaiting(CFRunLoopGetMain())); } -static bool IsMouseOrKeyEvent( NSEvent* event ) +static bool isUserInputEvent(NSEvent* event) { - bool result = false; - - switch( [event type] ) - { - case NSEventTypeLeftMouseDown: - case NSEventTypeLeftMouseUp: - case NSEventTypeRightMouseDown: - case NSEventTypeRightMouseUp: - case NSEventTypeMouseMoved: // ?? - case NSEventTypeLeftMouseDragged: - case NSEventTypeRightMouseDragged: - case NSEventTypeMouseEntered: - case NSEventTypeMouseExited: - case NSEventTypeKeyDown: - case NSEventTypeKeyUp: - case NSEventTypeFlagsChanged: // key modifiers changed? - case NSEventTypeCursorUpdate: // ?? - case NSEventTypeScrollWheel: - case NSEventTypeTabletPoint: - case NSEventTypeTabletProximity: - case NSEventTypeOtherMouseDown: - case NSEventTypeOtherMouseUp: - case NSEventTypeOtherMouseDragged: + switch ([event type]) { + case NSEventTypeLeftMouseDown: + case NSEventTypeLeftMouseUp: + case NSEventTypeRightMouseDown: + case NSEventTypeRightMouseUp: + case NSEventTypeMouseMoved: // ?? + case NSEventTypeLeftMouseDragged: + case NSEventTypeRightMouseDragged: + case NSEventTypeMouseEntered: + case NSEventTypeMouseExited: + case NSEventTypeKeyDown: + case NSEventTypeKeyUp: + case NSEventTypeFlagsChanged: // key modifiers changed? + case NSEventTypeCursorUpdate: // ?? + case NSEventTypeScrollWheel: + case NSEventTypeTabletPoint: + case NSEventTypeTabletProximity: + case NSEventTypeOtherMouseDown: + case NSEventTypeOtherMouseUp: + case NSEventTypeOtherMouseDragged: #ifndef QT_NO_GESTURES - case NSEventTypeGesture: // touch events - case NSEventTypeMagnify: - case NSEventTypeSwipe: - case NSEventTypeRotate: - case NSEventTypeBeginGesture: - case NSEventTypeEndGesture: + case NSEventTypeGesture: // touch events + case NSEventTypeMagnify: + case NSEventTypeSwipe: + case NSEventTypeRotate: + case NSEventTypeBeginGesture: + case NSEventTypeEndGesture: #endif // QT_NO_GESTURES - result = true; + return true; break; - - default: + default: break; } - return result; + return false; } static inline void qt_mac_waitForMoreEvents(NSString *runLoopMode = NSDefaultRunLoopMode) @@ -352,6 +347,16 @@ static inline void qt_mac_waitForMoreEvents(NSString *runLoopMode = NSDefaultRun bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) { Q_D(QCocoaEventDispatcher); + + // In rare rather corner cases a user's application messes with + // QEventLoop::exec()/exit() and QCoreApplication::processEvents(), + // we have to undo what bool blocker normally does. + d->propagateInterrupt = false; + const auto boolBlockerUndo = qScopeGuard([d](){ + if (d->propagateInterrupt) + d->interrupt = true; + d->propagateInterrupt = false; + }); QBoolBlocker interruptBlocker(d->interrupt, false); bool interruptLater = false; @@ -465,7 +470,7 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) dequeue: YES]; if (event) { - if (IsMouseOrKeyEvent(event)) { + if (isUserInputEvent(event)) { [event retain]; d->queuedUserInputEvents.append(event); continue; @@ -485,7 +490,7 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) if (event) { if (flags & QEventLoop::ExcludeUserInputEvents) { - if (IsMouseOrKeyEvent(event)) { + if (isUserInputEvent(event)) { [event retain]; d->queuedUserInputEvents.append(event); continue; @@ -500,7 +505,16 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) if ((d->processEventsFlags & QEventLoop::EventLoopExec) == 0) { // When called "manually", always process posted events and timers + bool oldInterrupt = d->interrupt; d->processPostedEvents(); + if (!oldInterrupt && d->interrupt && !d->currentModalSession()) { + // We had direct processEvent call, coming not from QEventLoop::exec(). + // One of the posted events triggered an application to interrupt the loop. + // But bool blocker will reset d->interrupt to false, so the real event + // loop will never notice it was interrupted. Now we'll have to fix it by + // enforcing the value of d->interrupt. + d->propagateInterrupt = true; + } retVal = d->processTimers() || retVal; } @@ -515,7 +529,7 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) if (hadModalSession && !d->currentModalSessionCached) interruptLater = true; } - bool canWait = (d->threadData->canWait + bool canWait = (d->threadData.loadRelaxed()->canWait && !retVal && !d->interrupt && (d->processEventsFlags & QEventLoop::WaitForMoreEvents)); @@ -882,7 +896,7 @@ void QCocoaEventDispatcherPrivate::processPostedEvents() } int serial = serialNumber.loadRelaxed(); - if (!threadData->canWait || (serial != lastSerial)) { + if (!threadData.loadRelaxed()->canWait || (serial != lastSerial)) { lastSerial = serial; QCoreApplication::sendPostedEvents(); QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::AllEvents); diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index bfc3bfe9de..0c14e07551 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -92,6 +92,10 @@ public: QCocoaVulkanInstance *getCocoaVulkanInstance() const; #endif +#if QT_CONFIG(sessionmanager) + QPlatformSessionManager *createPlatformSessionManager(const QString &id, const QString &key) const override; +#endif + QCoreTextFontDatabase *fontDatabase() const override; QCocoaNativeInterface *nativeInterface() const override; QPlatformInputContext *inputContext() const override; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index d8c931e9a1..daece10e79 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -52,6 +52,9 @@ #include "qcocoamimetypes.h" #include "qcocoaaccessibility.h" #include "qcocoascreen.h" +#if QT_CONFIG(sessionmanager) +# include "qcocoasessionmanager.h" +#endif #include <qpa/qplatforminputcontextfactory_p.h> #include <qpa/qplatformaccessibility.h> @@ -245,6 +248,13 @@ QCocoaIntegration::Options QCocoaIntegration::options() const return mOptions; } +#if QT_CONFIG(sessionmanager) +QPlatformSessionManager *QCocoaIntegration::createPlatformSessionManager(const QString &id, const QString &key) const +{ + return new QCocoaSessionManager(id, key); +} +#endif + bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) const { switch (cap) { diff --git a/src/plugins/platforms/cocoa/qcocoasessionmanager.cpp b/src/plugins/platforms/cocoa/qcocoasessionmanager.cpp new file mode 100644 index 0000000000..74e318b5be --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoasessionmanager.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Samuel Gaist <samuel.gaist@idiap.ch> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT_NO_SESSIONMANAGER +#include <private/qsessionmanager_p.h> +#include <private/qguiapplication_p.h> + +#include <qcocoasessionmanager.h> +#include <qstring.h> + +QT_BEGIN_NAMESPACE + +QCocoaSessionManager::QCocoaSessionManager(const QString &id, const QString &key) + : QPlatformSessionManager(id, key), + m_canceled(false) +{ +} + +QCocoaSessionManager::~QCocoaSessionManager() +{ +} + +bool QCocoaSessionManager::allowsInteraction() +{ + return false; +} + +void QCocoaSessionManager::resetCancellation() +{ + m_canceled = false; +} + +void QCocoaSessionManager::cancel() +{ + m_canceled = true; +} + +bool QCocoaSessionManager::wasCanceled() const +{ + return m_canceled; +} + +QCocoaSessionManager *QCocoaSessionManager::instance() +{ + auto *qGuiAppPriv = QGuiApplicationPrivate::instance(); + auto *managerPrivate = static_cast<QSessionManagerPrivate*>(QObjectPrivate::get(qGuiAppPriv->session_manager)); + return static_cast<QCocoaSessionManager *>(managerPrivate->platformSessionManager); +} + +QT_END_NAMESPACE + +#endif // QT_NO_SESSIONMANAGER diff --git a/src/plugins/platforms/cocoa/qcocoasessionmanager.h b/src/plugins/platforms/cocoa/qcocoasessionmanager.h new file mode 100644 index 0000000000..89ab7bd157 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoasessionmanager.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Samuel Gaist <samuel.gaist@idiap.ch> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCOCOASESSIONMANAGER_H +#define QCOCOASESSIONMANAGER_H + +// +// W A R N I N G +// ------------- +// +// This file is part of the QPA API and is not meant to be used +// in applications. Usage of this API may make your code +// source and binary incompatible with future versions of Qt. +// + +#ifndef QT_NO_SESSIONMANAGER + +#include <qpa/qplatformsessionmanager.h> + +QT_BEGIN_NAMESPACE + +class QCocoaSessionManager : public QPlatformSessionManager +{ +public: + QCocoaSessionManager(const QString &id, const QString &key); + virtual ~QCocoaSessionManager(); + + bool allowsInteraction() override; + void cancel() override; + void resetCancellation(); + bool wasCanceled() const; + + static QCocoaSessionManager *instance(); + +private: + bool m_canceled; + + Q_DISABLE_COPY(QCocoaSessionManager) +}; + +QT_END_NAMESPACE + +#endif // QT_NO_SESSIONMANAGER + +#endif // QCOCOASESSIONMANAGER_H diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h index 6779bda491..738c40aba6 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h +++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h @@ -65,7 +65,7 @@ public: void updateMenu(QPlatformMenu *menu) override; QRect geometry() const override; void showMessage(const QString &title, const QString &msg, - const QIcon& icon, MessageIcon iconType, int secs) override; + const QIcon& icon, MessageIcon iconType, int msecs) override; bool isSystemTrayAvailable() const override; bool supportsMessages() const override; diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm index a5b42ac4e3..559188aa5f 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm @@ -265,7 +265,7 @@ bool QCocoaSystemTrayIcon::supportsMessages() const } void QCocoaSystemTrayIcon::showMessage(const QString &title, const QString &message, - const QIcon& icon, MessageIcon, int) + const QIcon& icon, MessageIcon, int msecs) { if (!m_sys) return; @@ -283,6 +283,10 @@ void QCocoaSystemTrayIcon::showMessage(const QString &title, const QString &mess NSUserNotificationCenter *center = NSUserNotificationCenter.defaultUserNotificationCenter; center.delegate = m_sys->item; [center deliverNotification:notification]; + if (msecs) { + NSTimeInterval timeout = msecs / 1000.0; + [center performSelector:@selector(removeDeliveredNotification:) withObject:notification afterDelay:timeout]; + } [notification release]; } QT_END_NAMESPACE @@ -435,8 +439,7 @@ QT_END_NAMESPACE } - (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification { - Q_UNUSED(center); - Q_UNUSED(notification); + [center removeDeliveredNotification:notification]; emit systray->messageClicked(); } diff --git a/src/plugins/platforms/cocoa/qcocoatheme.h b/src/plugins/platforms/cocoa/qcocoatheme.h index a00cbdfea3..50e56ef1bf 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.h +++ b/src/plugins/platforms/cocoa/qcocoatheme.h @@ -70,7 +70,7 @@ public: const QPalette *palette(Palette type = SystemPalette) const override; const QFont *font(Font type = SystemFont) const override; QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const override; - QIcon fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions options = 0) const override; + QIcon fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions options = {}) const override; QVariant themeHint(ThemeHint hint) const override; QString standardButtonText(int button) const override; diff --git a/src/plugins/platforms/cocoa/qmacclipboard.mm b/src/plugins/platforms/cocoa/qmacclipboard.mm index 358a6b49fd..654647b35a 100644 --- a/src/plugins/platforms/cocoa/qmacclipboard.mm +++ b/src/plugins/platforms/cocoa/qmacclipboard.mm @@ -138,8 +138,12 @@ QMacPasteboard::QMacPasteboard(CFStringRef name, uchar mt) QMacPasteboard::~QMacPasteboard() { - // commit all promises for paste after exit close - resolvingBeforeDestruction = true; + /* + Commit all promises for paste when shutting down, + unless we are the stack-allocated clipboard used by QCocoaDrag. + */ + if (mime_type == QMacInternalPasteboardMime::MIME_DND) + resolvingBeforeDestruction = true; PasteboardResolvePromises(paste); if (paste) CFRelease(paste); |