Skip to content
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

Remove Window::open_as_if_parented #153

Merged
merged 1 commit into from
Dec 12, 2023

Conversation

micahrj
Copy link
Member

@micahrj micahrj commented Dec 12, 2023

The open_as_if_parented method was intended to support the use case of Audio Unit plugin views. However, the Audio Unit API differs in important ways from other plugin APIs (such as VST 3 and CLAP) with regard to the lifetime management of the plugin's NSView, and trying to support both lifetime management patterns simultaneously has been the source of complexity and bugs. Thus, rather than implementing Audio Unit NSView management directly in Baseview, it will be the responsibility of plugin frameworks to implement a compatibility layer between the Audio Unit API and the Baseview API.

@micahrj micahrj requested review from robbert-vdh and Engid December 12, 2023 05:31
The open_as_if_parented method was intended to support the use case of Audio
Unit plugin views. However, the Audio Unit API differs in important ways from
other plugin APIs (such as VST 3 and CLAP) with regard to the lifetime
management of the plugin's NSView, and trying to support both lifetime
management patterns simultaneously has been the source of complexity and bugs.
Thus, rather than implementing Audio Unit NSView management directly in
Baseview, it will be the responsibility of plugin frameworks to implement a
compatibility layer between the Audio Unit API and the Baseview API.
@micahrj micahrj force-pushed the remove-as-if-parented branch from bb6e112 to 74272fb Compare December 12, 2023 16:42
@micahrj micahrj enabled auto-merge (squash) December 12, 2023 16:44
@micahrj micahrj merged commit df0e392 into RustAudio:master Dec 12, 2023
3 checks passed
micahrj added a commit that referenced this pull request Dec 18, 2023
Instead of trying to detect when to clean up the window based on the `NSView`'s retain count, require window cleanup to be initiated explicitly via `Window::close`, `WindowHandle::close`, or `[NSWindowDelegate windowShouldClose:]` (in non-parented mode; called when the user clicks the "X" button). This fixes the leaks and use-after-frees that can be caused by the inherent unreliability of the retain count logic.

As discussed in #153, this change essentially means that the `NSView` created by Baseview will not be suitable as the top-level view for an Audio Unit, since the Baseview API now requires that child windows be cleaned up by an explicit call to `WindowHandle::close`, and the only reliable signal for cleaning up an Audio Unit view is a call to `[NSView dealloc]`. However, this does not mean that Baseview cannot be used in the context of an Audio Unit; it just means that plugin frameworks must implement a compatibility layer with a wrapper `NSView` (which is the approach taken by JUCE).

In order to implement this change:

- `WindowState` is stored in an `Rc` rather than a `Box`.
- `WindowHandle` holds an `Rc<WindowState>` so that `WindowHandle::close` can directly invoke window cleanup logic.
- Since the window can be closed during an event handler, `WindowState::from_view` now returns a clone of the `Rc<WindowState>` held by the `NSView` to ensure that it lives until the end of an event handler.
- In the non-parented case, the `NSView` is set as the window delegate, which allows it to receive the `windowShouldClose:` call when the user clicks the "X" button, upon which it will dispatch the `WillClose` event and initiate window cleanup logic.
- `Window::open_parented` and `open_blocking` no longer `release` the `NSView` immediately after attaching it. Instead, the `NSView` is released as part of the cleanup logic in `WindowInner::close`.
- `Window::resize` now checks if the window is open to avoid using the `NSView` after releasing it.
- The overridden `release` method, the `retain_count_after_build` field, the `ParentHandle` struct, and the `close_requested` flag have all been removed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants