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 may require small changes before they behave the same again. A summary of the
most important changes can be found in Vizia PR most important changes can be found in Vizia PR
[#291](https://github.com/vizia/vizia/pull/291). [#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] ## [2023-12-30]

View file

@ -2,6 +2,7 @@
use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
use std::any::Any; use std::any::Any;
use std::ffi::c_void;
use std::sync::Arc; use std::sync::Arc;
use crate::prelude::GuiContext; use crate::prelude::GuiContext;
@ -75,13 +76,38 @@ pub trait Editor: Send {
// TODO: Host->Plugin resizing // TODO: Host->Plugin resizing
} }
/// A raw window handle for platform and GUI framework agnostic editors. /// A raw window handle for platform and GUI framework agnostic editors. This implements
pub struct ParentWindowHandle { /// [`HasRawWindowHandle`] so it can be used directly with GUI libraries that use the same
pub handle: RawWindowHandle, /// [`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 { unsafe impl HasRawWindowHandle for ParentWindowHandle {
fn raw_window_handle(&self) -> RawWindowHandle { 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::channel::{self, SendTimeoutError};
use crossbeam::queue::ArrayQueue; use crossbeam::queue::ArrayQueue;
use parking_lot::Mutex; use parking_lot::Mutex;
use raw_window_handle::RawWindowHandle;
use std::any::Any; use std::any::Any;
use std::borrow::Borrow; use std::borrow::Borrow;
use std::collections::{HashMap, HashSet, VecDeque}; use std::collections::{HashMap, HashSet, VecDeque};
@ -2769,28 +2768,27 @@ impl<P: ClapPlugin> Wrapper<P> {
let mut editor_handle = wrapper.editor_handle.lock(); let mut editor_handle = wrapper.editor_handle.lock();
if editor_handle.is_none() { if editor_handle.is_none() {
let api = CStr::from_ptr(window.api); let api = CStr::from_ptr(window.api);
let handle = if api == CLAP_WINDOW_API_X11 { let parent_handle = if api == CLAP_WINDOW_API_X11 {
let mut handle = raw_window_handle::XcbHandle::empty(); ParentWindowHandle::X11Window(window.specific.x11 as u32)
handle.window = window.specific.x11 as u32;
RawWindowHandle::Xcb(handle)
} else if api == CLAP_WINDOW_API_COCOA { } else if api == CLAP_WINDOW_API_COCOA {
let mut handle = raw_window_handle::AppKitHandle::empty(); ParentWindowHandle::AppKitNsView(window.specific.cocoa)
handle.ns_view = window.specific.cocoa;
RawWindowHandle::AppKit(handle)
} else if api == CLAP_WINDOW_API_WIN32 { } else if api == CLAP_WINDOW_API_WIN32 {
let mut handle = raw_window_handle::Win32Handle::empty(); ParentWindowHandle::AppKitNsView(window.specific.win32)
handle.hwnd = window.specific.win32;
RawWindowHandle::Win32(handle)
} else { } else {
nih_debug_assert_failure!("Host passed an invalid API"); nih_debug_assert_failure!("Host passed an invalid API");
return false; return false;
}; };
// This extension is only exposed when we have an editor // This extension is only exposed when we have an editor
*editor_handle = Some(wrapper.editor.borrow().as_ref().unwrap().lock().spawn( *editor_handle = Some(
ParentWindowHandle { handle }, wrapper
wrapper.clone().make_gui_context(), .editor
)); .borrow()
.as_ref()
.unwrap()
.lock()
.spawn(parent_handle, wrapper.clone().make_gui_context()),
);
true true
} else { } else {

View file

@ -345,16 +345,27 @@ impl<P: Plugin, B: Backend<P>> Wrapper<P, B> {
gl_config: None, gl_config: None,
}, },
move |window| { 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 // 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 // baseview does not support this yet. Once this is added, we should
// immediately close the parent window when this happens so the loop // immediately close the parent window when this happens so the loop
// can exit. // can exit.
let editor_handle = editor.lock().spawn( let editor_handle = editor.lock().spawn(parent_handle, context);
ParentWindowHandle {
handle: window.raw_window_handle(),
},
context,
);
WrapperWindowHandler { WrapperWindowHandler {
_editor_handle: editor_handle, _editor_handle: editor_handle,

View file

@ -1,6 +1,5 @@
use atomic_float::AtomicF32; use atomic_float::AtomicF32;
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use raw_window_handle::RawWindowHandle;
use std::any::Any; use std::any::Any;
use std::ffi::{c_void, CStr}; use std::ffi::{c_void, CStr};
use std::mem; use std::mem;
@ -290,35 +289,25 @@ impl<P: Vst3Plugin> IPlugView for WrapperView<P> {
let mut editor_handle = self.editor_handle.write(); let mut editor_handle = self.editor_handle.write();
if editor_handle.is_none() { if editor_handle.is_none() {
let type_ = CStr::from_ptr(type_); let type_ = CStr::from_ptr(type_);
let handle = match type_.to_str() { let parent_handle = match type_.to_str() {
#[cfg(all(target_family = "unix", not(target_os = "macos")))]
Ok(type_) if type_ == VST3_PLATFORM_X11_WINDOW => { Ok(type_) if type_ == VST3_PLATFORM_X11_WINDOW => {
let mut handle = raw_window_handle::XcbHandle::empty(); ParentWindowHandle::X11Window(parent as usize as u32)
handle.window = parent as usize as u32;
RawWindowHandle::Xcb(handle)
} }
#[cfg(target_os = "macos")]
Ok(type_) if type_ == VST3_PLATFORM_NSVIEW => { Ok(type_) if type_ == VST3_PLATFORM_NSVIEW => {
let mut handle = raw_window_handle::AppKitHandle::empty(); ParentWindowHandle::AppKitNsView(parent)
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)
} }
Ok(type_) if type_ == VST3_PLATFORM_HWND => ParentWindowHandle::Win32Hwnd(parent),
_ => { _ => {
nih_debug_assert_failure!("Unknown window handle type: {:?}", type_); nih_debug_assert_failure!("Unknown window handle type: {:?}", type_);
return kInvalidArgument; return kInvalidArgument;
} }
}; };
*editor_handle = Some(self.editor.lock().spawn( *editor_handle = Some(
ParentWindowHandle { handle }, self.editor
self.inner.clone().make_gui_context(), .lock()
)); .spawn(parent_handle, self.inner.clone().make_gui_context()),
);
*self.inner.plug_view.write() = Some(ObjectPtr::from(self)); *self.inner.plug_view.write() = Some(ObjectPtr::from(self));
kResultOk kResultOk