1
0
Fork 0

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:
Robbert van der Helm 2023-11-05 16:25:30 +01:00
parent 4af581ba07
commit b794cdeafe
5 changed files with 79 additions and 45 deletions

View file

@ -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]

View file

@ -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)
}
}
}
}

View file

@ -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 {

View file

@ -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,

View file

@ -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