diff --git a/meson.build b/meson.build index a61a04e1..74b30398 100644 --- a/meson.build +++ b/meson.build @@ -57,6 +57,7 @@ executable( 'src/common/serialization.cpp', 'src/wine-host/plugin-bridge.cpp', 'src/wine-host/vst-host.cpp', + 'src/wine-host/win32-editor.cpp', ], native : false, include_directories : include_dir, diff --git a/src/wine-host/win32-editor.cpp b/src/wine-host/win32-editor.cpp new file mode 100644 index 00000000..35520668 --- /dev/null +++ b/src/wine-host/win32-editor.cpp @@ -0,0 +1,47 @@ +#include "win32-editor.h" + +ATOM register_window_class(std::string window_class_name); + +Win32Editor::Win32Editor(std::string window_class_name) + : window_class(register_window_class(window_class_name)) {} + +HWND Win32Editor::open() { + window_handle = + std::unique_ptr, decltype(&DestroyWindow)>( + CreateWindowEx(WS_EX_TOOLWINDOW, + reinterpret_cast(window_class), + "yabridge plugin", 0, 0, 0, 256, 256, nullptr, + nullptr, GetModuleHandle(nullptr), nullptr), + &DestroyWindow); + + return window_handle->get(); +} + +void Win32Editor::close() { + // RAII does the rest for us + window_handle = std::nullopt; +} + +std::optional Win32Editor::get_x11_handle() { + if (!window_handle.has_value()) { + return std::nullopt; + } + + return reinterpret_cast( + GetProp(window_handle.value().get(), "__wine_x11_whole_window")); +} + +ATOM register_window_class(std::string window_class_name) { + WNDCLASSEX window_class{}; + + window_class.cbSize = sizeof(WNDCLASSEX); + window_class.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; + // TODO: Probably do something here to handle resizes + window_class.lpfnWndProc = DefWindowProc; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.hbrBackground = CreateHatchBrush(HS_CROSS, RGB(255, 0, 255)); + window_class.lpszClassName = window_class_name.c_str(); + + return RegisterClassEx(&window_class); +} diff --git a/src/wine-host/win32-editor.h b/src/wine-host/win32-editor.h new file mode 100644 index 00000000..be5911dc --- /dev/null +++ b/src/wine-host/win32-editor.h @@ -0,0 +1,47 @@ +#define NOMINMAX +#define NOSERVICE +#define NOMCX +#define NOIMM +#define WIN32_LEAN_AND_MEAN +#include + +#include +#include +#include + +/** + * A wrapper around the win32 windowing API to create and destroy editor + * windows. A VST plugin can embed itself in that window, and we can then later + * embed the window in a VST host provided X11 window. + */ +class Win32Editor { + public: + /** + * @param window_class_name The name for the window class for editor + * windows. + */ + Win32Editor(std::string window_class_name); + + /** + * Open a window and return a handle to the new Win32 window that can be + * used by the hosted VST plugin. + */ + HWND open(); + void close(); + + /** + * Return the X11 window handle for the window if it's currently open. + */ + std::optional get_x11_handle(); + + private: + ATOM window_class; + + /** + * A pointer to the currently active window. Will be a null pointer if no + * window is active. + */ + std::optional< + std::unique_ptr, decltype(&DestroyWindow)>> + window_handle; +};