Open crsaracco opened 4 years ago
Note: raw_window_handle::RawWindowHandle
is what wgpu
uses, which allows binding to wgpu
. In that respect, choosing that handle type and exposing it would make things progress too for #891, although for that issue the workflow is reversed (embedding child window into druid, instead of embedding druid into parent window).
Raw window handle support for Windows and Mac has been merged, see #1586.
This is a tracking issue for supporting passing in a
parent
handle when creating a window. This functionality will enable users to use Druid as a child window for platform-native windows not created by Druid.Progress
See rest of issue for context.
General idea for implementation, might not be 100% accurate. Will update this section if needed.
c_void *
)Option<T>
field inWindowDesc
, and create a public function for the user to pass the window handle to.WindowDesc::build_native
should essentially end up passing the field through to the platform-specificWindowBuilder
.Option<T>
field inWindowBuilder
, and create a function forWindowDesc::build_native
to call to set it.create_window
inWindowBuilder::build
), pass the value if the new field isSome
, otherwise pass0
if the new field isNone
.Option<T>
field inWindowBuilder
, and create a function forWindowDesc::build_native
to call to set it.WindowBuilder::build
), attach to the given parent window if the new field isSome
, otherwise create a normal root window if the new field isNone
. See Raph'svst
branch for ideas.Option<T>
field inWindowBuilder
, and create a function forWindowDesc::build_native
to call to set it.Some
, otherwise create a normal root window if the new field isNone
. See this code for ideas.Background / Motivation
This functionality has been desired by many in the RustAudio group for a while now: it is a requirement for creating GUIs in the VST plugin format, one of the most popular plugin formats in modern Digital Audio Workstations (DAWs). Currently, no GUI crate in the Rust ecosystem fully meets all of the requirements to create GUIs for VST plugins, so this will be a step towards making Druid the first one.
(A "plugin", here, is basically a third-party musical "device" that the user can load into the DAW to synthesize or alter sounds. Plugins typically have a GUI that enables the user to change parameters for this device so that they can tweak the sounds/effects as they see fit, among other features.)
In DAWs following the VST specification, the DAW is responsible for handling the lifecycle of all plugin GUI windows: creation, opening, closing, etc. When the user loads a plugin into the DAW, the DAW probes the plugin to figure out if it supports having a GUI window. If so, the DAW creates the window for the plugin, then passes a handle to that window (the "parent window handle") to the plugin so that the plugin can attach to that window.
This parent handle is always a handle to a platform-native window (
HWND
on Windows,NSView
on Mac OS, or an X11 window ID on X11 systems), which can be used in the platform-native window creation function to "attach" to the parent window. (examples: Windows, Mac OS, Linux/X11)Therefore, the ideal workflow from a VST developer's perspective would be:
Discussion on impact to Druid's current project roadmap scope
Before I get too much farther into the weeds here, I should mention: while I would love to see some crate within the Rust ecosystem handle our use case, I still consider this to be pretty low priority as far as Druid is concerned. I know there's a lot of other stuff on your plate for the near-future, and I would like to disrupt that roadmap/timeline as little as possible.
I'm not specifically requesting the Druid core developers to implement this feature for us; some of us in the RustAudio group are willing to do the grunt work. That said, we might have some specific design questions as they relate to the architecture/vision of the crate, PRs take time to review, and all code in a codebase has some sort of maintenance cost.
This feature might be the first of a few for implementing VST support. I'm not sure what else will be needed afterwards, but I feel like parent window handle support is a self-contained enough feature to not be too disruptive, while allowing us to prove that Druid is a viable option for us, and also allowing us to dig in and identify future requirements.
If you feel like any aspect of us implementing VST support is too disruptive, please let us know and we can hold off. :) Similarly, if you feel like some aspect is completely out-of-scope for Druid as a whole, please let us know that as well.
Implementation details / proposal
Essentially, we have a handle to a parent window, and we want to pass that handle all the way down to
druid-shell
's platform-specific window creation functions (Windows, Mac OS).In
vst-rs
, the API currently gives you aparent: *mut c_void
. I don't find this to be a particularly good public API for use in Druid, so I propose using something likerust-windowing
'sraw-window-handle
instead to pass the parent handle around. Alternatively, we could make our own thing ifraw-window-handle
doesn't suit our needs, or if we want to reduce our dependencies. Either way, it would be up to the developer to transform this*mut c_void
(or whatever they have, for other use cases) into the correct handle type.I think the best place to expose this API to users would probably be in
WindowDesc
. We could make the function something like:If the user does not call this function, Druid should operate as normal (creating its own window instead of attaching to a parent window).
I think the rest of the implementation is basically just plumbing some data around, but let me know if there's some roadblocks I didn't foresee.
NOTE: X11 support needed to get VSTs working, see #475 for the tracking issue + context.
Unresolved issues and questions
window.open()
and have the control given back to the DAW when that function is done. Therefore, handling events inside a runloop, which never gives back control to the DAW, is problematic. It looks like we might be able to get around this by making anApplication
manually instead of launching anAppLauncher
, and just not creating thatRunLoop
. Would there be any issue doing it this way? Would events still be handled? (here's where my knowledge of how GUIs work drops off.)Update:
Not sure if there's an equivalent for GTK on other platforms.
Miscellaneous resources and links
vst-rs
crate, but this feature should work with anything that has a similar use case.vst
branch. While a lot has changed in the crate since then, it still might be a good reference (especially for Mac OS implementation specifically).rtb-rs
might also be a good reference.vst2-gui-research
.rutabaga
GUI toolkit (in C) is being used in a production VST (which he also made), so it might prove to be a valuable resource as well.