Cocoa integration - fix a crash in QMacPasteboard
QMacPasteboard's dtor skips LazyRequest promises and this leaves pasteboard manager in broken state, since we release the pasteboard itself of the next step in destructor. As a result, not only Qt's app doing D & D (and thus via QCocoaDrag creating a stack-allocated QMacPasteboard) can die suddenly when somebody inspects a pasteboard, this 'somebody' ... can also die amazingly. So now we DO resolve promises using PasteboardResolvePromises (but we also preserve the original intent of not providing or providing empty data for lazy requests). Task-number: QTBUG-54663 Task-number: QTBUG-54832 Change-Id: I3ce90bd0a012dd3cbb30c93b2b17dce9473acb28 Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
This commit is contained in:
parent
65cdffeaea
commit
ad0d2f463a
@ -69,6 +69,7 @@ private:
|
|||||||
uchar mime_type;
|
uchar mime_type;
|
||||||
mutable QPointer<QMimeData> mime;
|
mutable QPointer<QMimeData> mime;
|
||||||
mutable bool mac_mime_source;
|
mutable bool mac_mime_source;
|
||||||
|
bool resolvingBeforeDestruction;
|
||||||
static OSStatus promiseKeeper(PasteboardRef, PasteboardItemID, CFStringRef, void *);
|
static OSStatus promiseKeeper(PasteboardRef, PasteboardItemID, CFStringRef, void *);
|
||||||
void clear_helper();
|
void clear_helper();
|
||||||
public:
|
public:
|
||||||
|
@ -81,6 +81,7 @@ QMacPasteboard::QMacPasteboard(PasteboardRef p, uchar mt)
|
|||||||
mime_type = mt ? mt : uchar(QMacInternalPasteboardMime::MIME_ALL);
|
mime_type = mt ? mt : uchar(QMacInternalPasteboardMime::MIME_ALL);
|
||||||
paste = p;
|
paste = p;
|
||||||
CFRetain(paste);
|
CFRetain(paste);
|
||||||
|
resolvingBeforeDestruction = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QMacPasteboard::QMacPasteboard(uchar mt)
|
QMacPasteboard::QMacPasteboard(uchar mt)
|
||||||
@ -94,6 +95,7 @@ QMacPasteboard::QMacPasteboard(uchar mt)
|
|||||||
} else {
|
} else {
|
||||||
qDebug("PasteBoard: Error creating pasteboard: [%d]", (int)err);
|
qDebug("PasteBoard: Error creating pasteboard: [%d]", (int)err);
|
||||||
}
|
}
|
||||||
|
resolvingBeforeDestruction = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QMacPasteboard::QMacPasteboard(CFStringRef name, uchar mt)
|
QMacPasteboard::QMacPasteboard(CFStringRef name, uchar mt)
|
||||||
@ -107,23 +109,14 @@ QMacPasteboard::QMacPasteboard(CFStringRef name, uchar mt)
|
|||||||
} else {
|
} else {
|
||||||
qDebug("PasteBoard: Error creating pasteboard: %s [%d]", QCFString::toQString(name).toLatin1().constData(), (int)err);
|
qDebug("PasteBoard: Error creating pasteboard: %s [%d]", QCFString::toQString(name).toLatin1().constData(), (int)err);
|
||||||
}
|
}
|
||||||
|
resolvingBeforeDestruction = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QMacPasteboard::~QMacPasteboard()
|
QMacPasteboard::~QMacPasteboard()
|
||||||
{
|
{
|
||||||
// commit all promises for paste after exit close
|
// commit all promises for paste after exit close
|
||||||
for (int i = 0; i < promises.count(); ++i) {
|
resolvingBeforeDestruction = true;
|
||||||
const Promise &promise = promises.at(i);
|
PasteboardResolvePromises(paste);
|
||||||
// At this point app teardown has started and control is somewhere in the Q[Core]Application
|
|
||||||
// destructor. Skip "lazy" promises where the application has not provided data;
|
|
||||||
// the application will generally not be in a state to provide it.
|
|
||||||
if (promise.dataRequestType == LazyRequest)
|
|
||||||
continue;
|
|
||||||
QCFString flavor = QCFString(promise.convertor->flavorFor(promise.mime));
|
|
||||||
NSInteger pbItemId = promise.itemId;
|
|
||||||
promiseKeeper(paste, reinterpret_cast<PasteboardItemID>(pbItemId), flavor, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (paste)
|
if (paste)
|
||||||
CFRelease(paste);
|
CFRelease(paste);
|
||||||
}
|
}
|
||||||
@ -175,7 +168,7 @@ OSStatus QMacPasteboard::promiseKeeper(PasteboardRef paste, PasteboardItemID id,
|
|||||||
// to request the data from the application.
|
// to request the data from the application.
|
||||||
QVariant promiseData;
|
QVariant promiseData;
|
||||||
if (promise.dataRequestType == LazyRequest) {
|
if (promise.dataRequestType == LazyRequest) {
|
||||||
if (!promise.mimeData.isNull())
|
if (!qpaste->resolvingBeforeDestruction && !promise.mimeData.isNull())
|
||||||
promiseData = promise.mimeData->variantData(promise.mime);
|
promiseData = promise.mimeData->variantData(promise.mime);
|
||||||
} else {
|
} else {
|
||||||
promiseData = promise.variantData;
|
promiseData = promise.variantData;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user