-
Notifications
You must be signed in to change notification settings - Fork 486
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[AppKit] Try to make NSWindow.ReleasedWhenClosed work. Fixes #8606. #17105
Conversation
…8606. NSWindow.ReleasedWhenClosed is a rather annoying API, because it interferes with reference counting. In effect it behaves kind of like autoreleasing does, except that the object (window) is released at a different time (when the window is closed, as opposed to when the autorelease pool drains). We've tried to fix this in the past in several ways: * Forcefully disable ReleasedWhenClosed in all the constructors, and if it's set in the Close method, then add an extra Retain call to offset the imminent extra release. The unfortunate side-effect is that we also call Dispose, which might be too early (see xamarin#8606). * Rewrite the code to correctly override the native 'close' method, so we get the supposedly correct semantics (our special Close code is called) when the window is closed by Objective-C (for instance when the user hits the red X to close the window). This doesn't really solve the previous problem (we're calling Dispose too early), and it doesn't work for non-subclassed NSWindows (see xamarin#8717). So I'm trying another approach: track the value of ReleasedWhenClosed, and call Retain/Release when the value switches between true/false. This way we don't need any special logic in the Close method. I've also: * Marked the ReleasedWhenClosed property as obsolete, and added a DangerousReleasedWhenClosed property, to match how we bind the other reference counting methods (retain -> DangerousRetain, release -> DangerousRelease, etc.). * Added a ReleaseWhenClosed(bool) method, to be called instead of the ReleasedWhenClosed property, and this method will call DangerousRetain/DangerousRelease as described above when the ReleasedWhenClosed property changes value. This new tracking behavior is opt-in for now, but will become opt-out in .NET 9, and hopefully we'll be able to make it the only behavior at some point (in .NET 10 maybe?). Fixes xamarin#8606. Ref: xamarin#8717.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
✅ API diff for current PR / commitLegacy Xamarin (No breaking changes).NET (No breaking changes)✅ API diff vs stableLegacy Xamarin (No breaking changes).NET (No breaking changes)ℹ️ Generator diffGenerator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes) Pipeline on Agent |
📚 [PR Build] Artifacts 📚Artifacts were not provided. Pipeline on Agent XAMBOT-1172.Monterey' |
💻 [PR Build] Tests on macOS M1 - Mac Big Sur (11.5) passed 💻✅ All tests on macOS M1 - Mac Big Sur (11.5) passed. Pipeline on Agent |
This comment has been minimized.
This comment has been minimized.
🚀 [CI Build] Test results 🚀Test results✅ All tests passed on VSTS: simulator tests. 🎉 All 223 tests passed 🎉 Tests counts✅ bcl: All 69 tests passed. Html Report (VSDrops) Download Pipeline on Agent |
NSWindow.ReleasedWhenClosed is a rather annoying API, because it interferes with
reference counting. In effect it behaves kind of like autoreleasing does, except
that the object (window) is released at a different time (when the window is closed,
as opposed to when the autorelease pool drains).
We've tried to fix this in the past in several ways:
Forcefully disable ReleasedWhenClosed in all the constructors, and if it's set
in the Close method, then add an extra Retain call to offset the imminent extra
release. The unfortunate side-effect is that we also call Dispose, which might
be too early (see IsKeyWindow called on disposed window & Releasing window w/wo default delegate #8606).
Rewrite the code to correctly override the native 'close' method, so we get the
supposedly correct semantics (our special Close code is called) when the window
is closed by Objective-C (for instance when the user hits the red X to close the
window). This doesn't really solve the previous problem (we're calling Dispose
too early), and it doesn't work for non-subclassed NSWindows (see [appkit] Allow ObjC calls into NSWindow.Close #8717).
So I'm trying another approach: track the value of ReleasedWhenClosed, and call Retain/Release
when the value switches between true/false. This way we don't need any special logic
in the Close method.
I've also:
Marked the ReleasedWhenClosed property as obsolete, and added a DangerousReleasedWhenClosed
property, to match how we bind the other reference counting methods (retain ->
DangerousRetain, release -> DangerousRelease, etc.).
Added a ReleaseWhenClosed(bool) method, to be called instead of the ReleasedWhenClosed
property, and this method will call DangerousRetain/DangerousRelease as described
above when the ReleasedWhenClosed property changes value.
This new tracking behavior is opt-in for now, but will become opt-out in .NET 9,
and hopefully we'll be able to make it the only behavior at some point (in .NET 10
maybe?).
Fixes #8606.
Fixes #8607.
Ref: #8717.