diff options
author | Lee Culver <leculver@microsoft.com> | 2022-02-05 00:33:20 +0300 |
---|---|---|
committer | Lee Culver <leculver@microsoft.com> | 2022-02-05 00:33:20 +0300 |
commit | 9886961dbc5d208650bad2907a43887e11490d00 (patch) | |
tree | 36878723f11375082179be402bdde4f42ee86b27 /Xwt.XamMac | |
parent | 4671fb8adf9f25d65eab95f9c39d23a9083e2f8d (diff) |
Fix fatal Obj-C callback issue due to delegate collection
VS for Mac is encountering a fatal error of: A callback was made on a garbage collected delegate of type 'Xwt.XamMac!Xwt.Mac.ViewBackend+DelegateIntPtrIntPtrBool::Invoke'.
The underlying root cause for this is that the delegates that are created and passed off to native code are not being kept alive. The GC has no way of knowing that delegates passed to native code need to be kept alive so a root must be established in some way.
Since these are all static methods, we can create a static variable to hold these delegates for the lifetime of the application.
Diffstat (limited to 'Xwt.XamMac')
-rw-r--r-- | Xwt.XamMac/Xwt.Mac/ViewBackend.cs | 27 |
1 files changed, 19 insertions, 8 deletions
diff --git a/Xwt.XamMac/Xwt.Mac/ViewBackend.cs b/Xwt.XamMac/Xwt.Mac/ViewBackend.cs index 26175b1e..f3864c67 100644 --- a/Xwt.XamMac/Xwt.Mac/ViewBackend.cs +++ b/Xwt.XamMac/Xwt.Mac/ViewBackend.cs @@ -535,6 +535,13 @@ namespace Xwt.Mac static Selector becomeFirstResponderSel = new Selector ("becomeFirstResponder"); static Selector resignFirstResponderSel = new Selector ("resignFirstResponder"); + static DelegateIntPtrIntPtrIntPtrNSDragOperation draggingEnteredDelegate = new DelegateIntPtrIntPtrIntPtrNSDragOperation(DraggingEntered); + static DelegateIntPtrIntPtrIntPtrNSDragOperation draggingUpdatedDelegate = new DelegateIntPtrIntPtrIntPtrNSDragOperation(DraggingUpdated); + static DelegateIntPtrIntPtrIntPtrVoid draggingExitedDelegate = new DelegateIntPtrIntPtrIntPtrVoid(DraggingExited); + static DelegateIntPtrIntPtrIntPtrBool prepareForDragOperationDelegate = new DelegateIntPtrIntPtrIntPtrBool(PrepareForDragOperation); + static DelegateIntPtrIntPtrIntPtrBool performDragOperationDelegate = new DelegateIntPtrIntPtrIntPtrBool(PerformDragOperation); + static DelegateIntPtrIntPtrIntPtrVoid delegateIntPtrIntPtrIntPtrVoid = new DelegateIntPtrIntPtrIntPtrVoid(ConcludeDragOperation); + static HashSet<Type> typesConfiguredForDragDrop = new HashSet<Type> (); static HashSet<Type> typesConfiguredForFocusEvents = new HashSet<Type> (); @@ -543,12 +550,13 @@ namespace Xwt.Mac lock (typesConfiguredForDragDrop) { if (typesConfiguredForDragDrop.Add (type)) { Class c = new Class (type); - c.AddMethod (draggingEnteredSel.Handle, new DelegateIntPtrIntPtrIntPtrNSDragOperation(DraggingEntered), "i@:@"); - c.AddMethod (draggingUpdatedSel.Handle, new DelegateIntPtrIntPtrIntPtrNSDragOperation(DraggingUpdated), "i@:@"); - c.AddMethod (draggingExitedSel.Handle, new DelegateIntPtrIntPtrIntPtrVoid(DraggingExited), "v@:@"); - c.AddMethod (prepareForDragOperationSel.Handle, new DelegateIntPtrIntPtrIntPtrBool(PrepareForDragOperation), "B@:@"); - c.AddMethod (performDragOperationSel.Handle, new DelegateIntPtrIntPtrIntPtrBool(PerformDragOperation), "B@:@"); - c.AddMethod (concludeDragOperationSel.Handle, new DelegateIntPtrIntPtrIntPtrVoid(ConcludeDragOperation), "v@:@"); + + c.AddMethod (draggingEnteredSel.Handle, draggingEnteredDelegate, "i@:@"); + c.AddMethod (draggingUpdatedSel.Handle, draggingUpdatedDelegate, "i@:@"); + c.AddMethod (draggingExitedSel.Handle, draggingExitedDelegate, "v@:@"); + c.AddMethod (prepareForDragOperationSel.Handle, prepareForDragOperationDelegate, "B@:@"); + c.AddMethod (performDragOperationSel.Handle, performDragOperationDelegate, "B@:@"); + c.AddMethod (concludeDragOperationSel.Handle, delegateIntPtrIntPtrIntPtrVoid, "v@:@"); } } } @@ -558,13 +566,16 @@ namespace Xwt.Mac delegate void DelegateIntPtrIntPtrIntPtrVoid(IntPtr p1, IntPtr p2, IntPtr p3); delegate bool DelegateIntPtrIntPtrIntPtrBool(IntPtr p1, IntPtr p2, IntPtr p3); + static DelegateIntPtrIntPtrBool onBecomeFirstResponderDelegate = new DelegateIntPtrIntPtrBool(OnBecomeFirstResponder); + static DelegateIntPtrIntPtrBool onResignFirstResponderDelegate = new DelegateIntPtrIntPtrBool(OnResignFirstResponder); + static void SetupFocusEvents (Type type) { lock (typesConfiguredForFocusEvents) { if (typesConfiguredForFocusEvents.Add (type)) { Class c = new Class (type); - c.AddMethod (becomeFirstResponderSel.Handle, new DelegateIntPtrIntPtrBool(OnBecomeFirstResponder), "B@:"); - c.AddMethod (resignFirstResponderSel.Handle, new DelegateIntPtrIntPtrBool(OnResignFirstResponder), "B@:"); + c.AddMethod (becomeFirstResponderSel.Handle, onBecomeFirstResponderDelegate, "B@:"); + c.AddMethod (resignFirstResponderSel.Handle, onResignFirstResponderDelegate, "B@:"); } } } |