Add private QObjCWeakPointer for tracking Objective-C object lifetime
Uses __weak if possible, and otherwise falls back to associated objects. Replaces manual tracking of QNSView lifetime for QCocoaDrag. Task-number: QTBUG-116554 Change-Id: I56f2707bbf5aa14a9efd0ec29e37b157e97cfc3e Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> (cherry picked from commit fa9449bbe8fb20cbdfc5b1e81181a30e4a7c358a) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
ef8fc89355
commit
059cbd17ba
@ -774,5 +774,19 @@ QMacVersion::VersionTuple QMacVersion::libraryVersion()
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
#if !(__has_feature(objc_arc_weak) && __has_feature(objc_arc_fields))
|
||||
QT_END_NAMESPACE
|
||||
@implementation QT_MANGLE_NAMESPACE(WeakPointerLifetimeTracker)
|
||||
- (void)dealloc
|
||||
{
|
||||
*self.pointer = {};
|
||||
[super dealloc];
|
||||
}
|
||||
@end
|
||||
QT_BEGIN_NAMESPACE
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
@ -462,6 +462,89 @@ qt_objc_cast(id object)
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
#if defined( __OBJC__)
|
||||
|
||||
template <typename T = NSObject>
|
||||
class QObjCWeakPointer;
|
||||
|
||||
#if __has_feature(objc_arc_weak) && __has_feature(objc_arc_fields)
|
||||
# define USE_OBJC_WEAK 1
|
||||
#endif
|
||||
|
||||
#if !USE_OBJC_WEAK
|
||||
QT_END_NAMESPACE
|
||||
#include <objc/runtime.h>
|
||||
Q_CORE_EXPORT
|
||||
QT_DECLARE_NAMESPACED_OBJC_INTERFACE(WeakPointerLifetimeTracker, NSObject
|
||||
@property (atomic, assign) QT_PREPEND_NAMESPACE(QObjCWeakPointer)<NSObject> *pointer;
|
||||
)
|
||||
QT_BEGIN_NAMESPACE
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
class QObjCWeakPointer
|
||||
{
|
||||
public:
|
||||
QObjCWeakPointer(T *object = nil) : m_object(object)
|
||||
{
|
||||
#if !USE_OBJC_WEAK
|
||||
trackObjectLifetime();
|
||||
#endif
|
||||
}
|
||||
|
||||
QObjCWeakPointer(const QObjCWeakPointer &other)
|
||||
{
|
||||
QMacAutoReleasePool pool;
|
||||
m_object = other.m_object;
|
||||
#if !USE_OBJC_WEAK
|
||||
trackObjectLifetime();
|
||||
#endif
|
||||
}
|
||||
|
||||
QObjCWeakPointer &operator=(const QObjCWeakPointer &other)
|
||||
{
|
||||
QMacAutoReleasePool pool;
|
||||
m_object = other.m_object;
|
||||
#if !USE_OBJC_WEAK
|
||||
trackObjectLifetime();
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
~QObjCWeakPointer()
|
||||
{
|
||||
#if !USE_OBJC_WEAK
|
||||
if (m_object)
|
||||
objc_setAssociatedObject(m_object, this, nil, OBJC_ASSOCIATION_RETAIN);
|
||||
#endif
|
||||
}
|
||||
|
||||
operator T*() const { return static_cast<T*>([[m_object retain] autorelease]); }
|
||||
|
||||
private:
|
||||
#if USE_OBJC_WEAK
|
||||
__weak
|
||||
#else
|
||||
void trackObjectLifetime()
|
||||
{
|
||||
if (!m_object)
|
||||
return;
|
||||
|
||||
auto *lifetimeTracker = [WeakPointerLifetimeTracker new];
|
||||
lifetimeTracker.pointer = reinterpret_cast<QObjCWeakPointer<NSObject>*>(this);
|
||||
objc_setAssociatedObject(m_object, this, lifetimeTracker, OBJC_ASSOCIATION_RETAIN);
|
||||
[lifetimeTracker release];
|
||||
}
|
||||
#endif
|
||||
NSObject *m_object = nil;
|
||||
};
|
||||
|
||||
#undef USE_OBJC_WEAK
|
||||
|
||||
#endif // __OBJC__
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QCORE_MAC_P_H
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include <qpa/qplatformdrag.h>
|
||||
#include <private/qsimpledrag_p.h>
|
||||
|
||||
#include <QtCore/private/qcore_mac_p.h>
|
||||
|
||||
#include <QtGui/private/qdnd_p.h>
|
||||
#include <QtGui/private/qinternalmimedata_p.h>
|
||||
|
||||
@ -36,14 +38,13 @@ public:
|
||||
* event and view when handling an event in QNSView
|
||||
*/
|
||||
void setLastInputEvent(NSEvent *event, NSView *view);
|
||||
void viewDestroyed(NSView *view);
|
||||
|
||||
void setAcceptedAction(Qt::DropAction act);
|
||||
void exitDragLoop();
|
||||
private:
|
||||
QDrag *m_drag;
|
||||
NSEvent *m_lastEvent;
|
||||
NSView *m_lastView;
|
||||
QObjCWeakPointer<NSView> m_lastView;
|
||||
Qt::DropAction m_executed_drop_action;
|
||||
QEventLoop *m_internalDragLoop = nullptr;
|
||||
|
||||
|
@ -38,17 +38,6 @@ void QCocoaDrag::setLastInputEvent(NSEvent *event, NSView *view)
|
||||
m_lastView = view;
|
||||
}
|
||||
|
||||
void QCocoaDrag::viewDestroyed(NSView *view)
|
||||
{
|
||||
if (view == m_lastView) {
|
||||
if (m_lastEvent.window.contentView == view) {
|
||||
[m_lastEvent release];
|
||||
m_lastEvent = nil;
|
||||
}
|
||||
m_lastView = nil;
|
||||
}
|
||||
}
|
||||
|
||||
QMimeData *QCocoaDrag::dragMimeData()
|
||||
{
|
||||
if (m_drag)
|
||||
@ -107,8 +96,11 @@ Qt::DropAction QCocoaDrag::defaultAction(Qt::DropActions possibleActions,
|
||||
Qt::DropAction QCocoaDrag::drag(QDrag *o)
|
||||
{
|
||||
m_executed_drop_action = Qt::IgnoreAction;
|
||||
if (!m_lastEvent)
|
||||
if (!m_lastView) {
|
||||
[m_lastEvent release];
|
||||
m_lastEvent = nil;
|
||||
return m_executed_drop_action;
|
||||
}
|
||||
|
||||
m_drag = o;
|
||||
QMacPasteboard dragBoard(CFStringRef(NSPasteboardNameDrag), QUtiMimeConverter::HandlerScopeFlag::DnD);
|
||||
@ -151,7 +143,7 @@ bool QCocoaDrag::maybeDragMultipleItems()
|
||||
|
||||
const QMacAutoReleasePool pool;
|
||||
|
||||
NSView *view = m_lastView ? m_lastView : m_lastEvent.window.contentView;
|
||||
NSView *view = m_lastView ? static_cast<NSView*>(m_lastView) : m_lastEvent.window.contentView;
|
||||
if (![view respondsToSelector:@selector(draggingSession:sourceOperationMaskForDraggingContext:)])
|
||||
return false;
|
||||
|
||||
|
@ -173,10 +173,6 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSViewMenuHelper);
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
[m_mouseMoveHelper release];
|
||||
|
||||
// FIXME: Replace with __weak or someting equivalent
|
||||
QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
|
||||
nativeDrag->viewDestroyed(self);
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user