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
|
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]
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue