Rework ParentWindowHandle to be a sum type
So we can mix and match versions of baseview that target different versions of `raw_window_handle`.
This commit is contained in:
parent
4af581ba07
commit
b794cdeafe
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -19,6 +19,16 @@ state is to list breaking changes.
|
|||
may require small changes before they behave the same again. A summary of the
|
||||
most important changes can be found in Vizia PR
|
||||
[#291](https://github.com/vizia/vizia/pull/291).
|
||||
- The `raw_window_handle` version used by NIH-plug has been updated to version
|
||||
0.5.x.
|
||||
|
||||
### Changed
|
||||
|
||||
- `ParentWindowHandle` has changed to be a sum type of different parent window
|
||||
handle types, similar to `RawWindowHandle`. This makes it easier to use GUI
|
||||
libraries that link against a different version of `raw_window_handle` than
|
||||
the one used by NIH-plug itself by simply wrapping around
|
||||
`ParentWindowHandle`.
|
||||
|
||||
## [2023-12-30]
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
|
||||
use std::any::Any;
|
||||
use std::ffi::c_void;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::prelude::GuiContext;
|
||||
|
@ -75,13 +76,38 @@ pub trait Editor: Send {
|
|||
// TODO: Host->Plugin resizing
|
||||
}
|
||||
|
||||
/// A raw window handle for platform and GUI framework agnostic editors.
|
||||
pub struct ParentWindowHandle {
|
||||
pub handle: RawWindowHandle,
|
||||
/// A raw window handle for platform and GUI framework agnostic editors. This implements
|
||||
/// [`HasRawWindowHandle`] so it can be used directly with GUI libraries that use the same
|
||||
/// [`raw_window_handle`] version. If the library links against a different version of
|
||||
/// `raw_window_handle`, then you'll need to wrap around this type and implement the trait yourself.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum ParentWindowHandle {
|
||||
/// The ID of the host's parent window. Used with X11.
|
||||
X11Window(u32),
|
||||
/// A handle to the host's parent window. Used only on macOS.
|
||||
AppKitNsView(*mut c_void),
|
||||
/// A handle to the host's parent window. Used only on Windows.
|
||||
Win32Hwnd(*mut c_void),
|
||||
}
|
||||
|
||||
unsafe impl HasRawWindowHandle for ParentWindowHandle {
|
||||
fn raw_window_handle(&self) -> RawWindowHandle {
|
||||
self.handle
|
||||
match *self {
|
||||
ParentWindowHandle::X11Window(window) => {
|
||||
let mut handle = raw_window_handle::XcbWindowHandle::empty();
|
||||
handle.window = window;
|
||||
RawWindowHandle::Xcb(handle)
|
||||
}
|
||||
ParentWindowHandle::AppKitNsView(ns_view) => {
|
||||
let mut handle = raw_window_handle::AppKitWindowHandle::empty();
|
||||
handle.ns_view = ns_view;
|
||||
RawWindowHandle::AppKit(handle)
|
||||
}
|
||||
ParentWindowHandle::Win32Hwnd(hwnd) => {
|
||||
let mut handle = raw_window_handle::Win32WindowHandle::empty();
|
||||
handle.hwnd = hwnd;
|
||||
RawWindowHandle::Win32(handle)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,6 @@ use crossbeam::atomic::AtomicCell;
|
|||
use crossbeam::channel::{self, SendTimeoutError};
|
||||
use crossbeam::queue::ArrayQueue;
|
||||
use parking_lot::Mutex;
|
||||
use raw_window_handle::RawWindowHandle;
|
||||
use std::any::Any;
|
||||
use std::borrow::Borrow;
|
||||
use std::collections::{HashMap, HashSet, VecDeque};
|
||||
|
@ -2769,28 +2768,27 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
let mut editor_handle = wrapper.editor_handle.lock();
|
||||
if editor_handle.is_none() {
|
||||
let api = CStr::from_ptr(window.api);
|
||||
let handle = if api == CLAP_WINDOW_API_X11 {
|
||||
let mut handle = raw_window_handle::XcbHandle::empty();
|
||||
handle.window = window.specific.x11 as u32;
|
||||
RawWindowHandle::Xcb(handle)
|
||||
let parent_handle = if api == CLAP_WINDOW_API_X11 {
|
||||
ParentWindowHandle::X11Window(window.specific.x11 as u32)
|
||||
} else if api == CLAP_WINDOW_API_COCOA {
|
||||
let mut handle = raw_window_handle::AppKitHandle::empty();
|
||||
handle.ns_view = window.specific.cocoa;
|
||||
RawWindowHandle::AppKit(handle)
|
||||
ParentWindowHandle::AppKitNsView(window.specific.cocoa)
|
||||
} else if api == CLAP_WINDOW_API_WIN32 {
|
||||
let mut handle = raw_window_handle::Win32Handle::empty();
|
||||
handle.hwnd = window.specific.win32;
|
||||
RawWindowHandle::Win32(handle)
|
||||
ParentWindowHandle::AppKitNsView(window.specific.win32)
|
||||
} else {
|
||||
nih_debug_assert_failure!("Host passed an invalid API");
|
||||
return false;
|
||||
};
|
||||
|
||||
// This extension is only exposed when we have an editor
|
||||
*editor_handle = Some(wrapper.editor.borrow().as_ref().unwrap().lock().spawn(
|
||||
ParentWindowHandle { handle },
|
||||
wrapper.clone().make_gui_context(),
|
||||
));
|
||||
*editor_handle = Some(
|
||||
wrapper
|
||||
.editor
|
||||
.borrow()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.spawn(parent_handle, wrapper.clone().make_gui_context()),
|
||||
);
|
||||
|
||||
true
|
||||
} else {
|
||||
|
|
|
@ -345,16 +345,27 @@ impl<P: Plugin, B: Backend<P>> Wrapper<P, B> {
|
|||
gl_config: None,
|
||||
},
|
||||
move |window| {
|
||||
let parent_handle = match window.raw_window_handle() {
|
||||
raw_window_handle::RawWindowHandle::Xlib(handle) => {
|
||||
ParentWindowHandle::X11Window(handle.window as u32)
|
||||
}
|
||||
raw_window_handle::RawWindowHandle::Xcb(handle) => {
|
||||
ParentWindowHandle::X11Window(handle.window)
|
||||
}
|
||||
raw_window_handle::RawWindowHandle::AppKit(handle) => {
|
||||
ParentWindowHandle::AppKitNsView(handle.ns_view)
|
||||
}
|
||||
raw_window_handle::RawWindowHandle::Win32(handle) => {
|
||||
ParentWindowHandle::Win32Hwnd(handle.hwnd)
|
||||
}
|
||||
handle => unimplemented!("Unsupported window handle: {handle:?}"),
|
||||
};
|
||||
|
||||
// TODO: This spawn function should be able to fail and return an error, but
|
||||
// baseview does not support this yet. Once this is added, we should
|
||||
// immediately close the parent window when this happens so the loop
|
||||
// can exit.
|
||||
let editor_handle = editor.lock().spawn(
|
||||
ParentWindowHandle {
|
||||
handle: window.raw_window_handle(),
|
||||
},
|
||||
context,
|
||||
);
|
||||
let editor_handle = editor.lock().spawn(parent_handle, context);
|
||||
|
||||
WrapperWindowHandler {
|
||||
_editor_handle: editor_handle,
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use atomic_float::AtomicF32;
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use raw_window_handle::RawWindowHandle;
|
||||
use std::any::Any;
|
||||
use std::ffi::{c_void, CStr};
|
||||
use std::mem;
|
||||
|
@ -290,35 +289,25 @@ impl<P: Vst3Plugin> IPlugView for WrapperView<P> {
|
|||
let mut editor_handle = self.editor_handle.write();
|
||||
if editor_handle.is_none() {
|
||||
let type_ = CStr::from_ptr(type_);
|
||||
let handle = match type_.to_str() {
|
||||
#[cfg(all(target_family = "unix", not(target_os = "macos")))]
|
||||
let parent_handle = match type_.to_str() {
|
||||
Ok(type_) if type_ == VST3_PLATFORM_X11_WINDOW => {
|
||||
let mut handle = raw_window_handle::XcbHandle::empty();
|
||||
handle.window = parent as usize as u32;
|
||||
RawWindowHandle::Xcb(handle)
|
||||
ParentWindowHandle::X11Window(parent as usize as u32)
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
Ok(type_) if type_ == VST3_PLATFORM_NSVIEW => {
|
||||
let mut handle = raw_window_handle::AppKitHandle::empty();
|
||||
handle.ns_view = parent;
|
||||
RawWindowHandle::AppKit(handle)
|
||||
}
|
||||
#[cfg(target_os = "windows")]
|
||||
Ok(type_) if type_ == VST3_PLATFORM_HWND => {
|
||||
let mut handle = raw_window_handle::Win32Handle::empty();
|
||||
handle.hwnd = parent;
|
||||
RawWindowHandle::Win32(handle)
|
||||
ParentWindowHandle::AppKitNsView(parent)
|
||||
}
|
||||
Ok(type_) if type_ == VST3_PLATFORM_HWND => ParentWindowHandle::Win32Hwnd(parent),
|
||||
_ => {
|
||||
nih_debug_assert_failure!("Unknown window handle type: {:?}", type_);
|
||||
return kInvalidArgument;
|
||||
}
|
||||
};
|
||||
|
||||
*editor_handle = Some(self.editor.lock().spawn(
|
||||
ParentWindowHandle { handle },
|
||||
self.inner.clone().make_gui_context(),
|
||||
));
|
||||
*editor_handle = Some(
|
||||
self.editor
|
||||
.lock()
|
||||
.spawn(parent_handle, self.inner.clone().make_gui_context()),
|
||||
);
|
||||
*self.inner.plug_view.write() = Some(ObjectPtr::from(self));
|
||||
|
||||
kResultOk
|
||||
|
|
Loading…
Reference in a new issue