diff --git a/plugins/Common/IldaeilUI.cpp b/plugins/Common/IldaeilUI.cpp index 3c77546..9caec13 100644 --- a/plugins/Common/IldaeilUI.cpp +++ b/plugins/Common/IldaeilUI.cpp @@ -21,6 +21,7 @@ #include "DistrhoUI.hpp" #include "DistrhoPlugin.hpp" +#include "PluginHostWindow.hpp" #include "SizeUtils.hpp" #include "extra/Thread.hpp" @@ -52,7 +53,9 @@ using namespace CarlaBackend; // shared resource pointer // carla_juce_init(); -class IldaeilUI : public UI, public Thread +class IldaeilUI : public UI, + public Thread, + public PluginHostWindow::Callbacks { static constexpr const uint kInitialWidth = 1220; static constexpr const uint kInitialHeight = 640; @@ -70,6 +73,7 @@ class IldaeilUI : public UI, public Thread } fDrawingState; IldaeilPlugin* const fPlugin; + PluginHostWindow fPluginHostWindow; uint fPluginCount; uint fPluginSelected; @@ -78,21 +82,17 @@ class IldaeilUI : public UI, public Thread bool fPluginSearchActive; char fPluginSearchString[0xff]; - bool fInitialSizeHasBeenSet; - const uintptr_t fOurWindowId; - public: IldaeilUI() : UI(kInitialWidth, kInitialHeight), Thread("IldaeilScanner"), fDrawingState(kDrawingInit), fPlugin((IldaeilPlugin*)getPluginInstancePointer()), + fPluginHostWindow(getWindow(), this), fPluginCount(0), fPluginSelected(0), fPlugins(nullptr), - fPluginSearchActive(false), - fInitialSizeHasBeenSet(false), - fOurWindowId(getWindow().getNativeWindowHandle()) + fPluginSearchActive(false) { if (fPlugin == nullptr || fPlugin->fCarlaHostHandle == nullptr) { @@ -107,10 +107,21 @@ public: const double scaleFactor = getScaleFactor(); if (d_isNotEqual(scaleFactor, 1.0)) + { setSize(kInitialWidth * scaleFactor, kInitialHeight * scaleFactor); + fPluginHostWindow.setPositionAndSize(0, kExtraHeight * scaleFactor, + kInitialWidth * scaleFactor, (kInitialHeight - kExtraHeight) * scaleFactor); + } + else + { + fPluginHostWindow.setPositionAndSize(0, kExtraHeight, kInitialWidth, kInitialHeight-kExtraHeight); + } const CarlaHostHandle handle = fPlugin->fCarlaHostHandle; + // carla_set_engine_option(handle, ENGINE_OPTION_FRONTEND_WIN_ID, 0, winIdStr); + carla_set_engine_option(handle, ENGINE_OPTION_FRONTEND_UI_SCALE, getScaleFactor()*1000, nullptr); + if (carla_get_current_plugin_count(handle) != 0) { showPluginUI(handle); @@ -128,9 +139,10 @@ public: fPlugin->fUI = nullptr; - if (fDrawingState == kDrawingPluginCustomUI) + if (fDrawingState == kDrawingPluginGenericUI || fDrawingState == kDrawingPluginCustomUI) carla_show_custom_ui(fPlugin->fCarlaHostHandle, 0, false); + fPluginHostWindow.detach(); delete[] fPlugins; } @@ -140,14 +152,8 @@ public: if (info->hints & PLUGIN_HAS_CUSTOM_EMBED_UI) { - // carla_set_engine_option(handle, ENGINE_OPTION_FRONTEND_WIN_ID, 0, winIdStr); - carla_set_engine_option(handle, ENGINE_OPTION_FRONTEND_UI_SCALE, getScaleFactor()*1000, nullptr); - - carla_embed_custom_ui(handle, 0, (void*)fOurWindowId); - fDrawingState = kDrawingPluginCustomUI; - fInitialSizeHasBeenSet = false; - tryResizingToChildWindowContent(); + carla_embed_custom_ui(handle, 0, fPluginHostWindow.attachAndGetWindowHandle()); } else { @@ -161,6 +167,11 @@ public: } protected: + void pluginWindowResized(uint width, uint height) override + { + setSize(width, height + kExtraHeight * getScaleFactor()); + } + void uiIdle() override { switch (fDrawingState) @@ -172,9 +183,9 @@ protected: break; case kDrawingPluginCustomUI: - if (! fInitialSizeHasBeenSet) - tryResizingToChildWindowContent(); - // fall-through + fPlugin->fCarlaPluginDescriptor->ui_idle(fPlugin->fCarlaPluginHandle); + fPluginHostWindow.idle(); + break; case kDrawingPluginGenericUI: fPlugin->fCarlaPluginDescriptor->ui_idle(fPlugin->fCarlaPluginHandle); @@ -225,14 +236,14 @@ protected: drawGenericUI(); // fall-through case kDrawingPluginCustomUI: - drawBottomBar(); + drawTopBar(); break; } } - void drawBottomBar() + void drawTopBar() { - ImGui::SetNextWindowPos(ImVec2(0, getHeight() - kExtraHeight * getScaleFactor())); + ImGui::SetNextWindowPos(ImVec2(0, 0)); ImGui::SetNextWindowSize(ImVec2(getWidth(), kExtraHeight * getScaleFactor())); if (ImGui::Begin("Current Plugin", nullptr, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize)) @@ -368,6 +379,7 @@ protected: { const CarlaCachedPluginInfo& info(fPlugins[i]); + /* #if DISTRHO_PLUGIN_IS_SYNTH if (info.midiIns != 1 || info.audioOuts != 2) continue; @@ -380,6 +392,7 @@ protected: if (info.audioIns != 2 || info.audioOuts != 2) continue; #endif + */ const char* const slash = std::strchr(info.label, DISTRHO_OS_SEP); DISTRHO_SAFE_ASSERT_CONTINUE(slash != nullptr); @@ -409,19 +422,6 @@ protected: ImGui::End(); } -private: - void tryResizingToChildWindowContent() - { - Size size(getChildWindowSize(fOurWindowId)); - - if (size.isValid()) - { - fInitialSizeHasBeenSet = true; - size.setHeight(size.getHeight() + kExtraHeight * getScaleFactor()); - setSize(size); - } - } - protected: /* -------------------------------------------------------------------------------------------------------- * DSP/Plugin Callbacks */ diff --git a/plugins/Common/PluginHostWindow.cpp b/plugins/Common/PluginHostWindow.cpp new file mode 100644 index 0000000..7b48cb6 --- /dev/null +++ b/plugins/Common/PluginHostWindow.cpp @@ -0,0 +1,200 @@ +/* + * DISTRHO Ildaeil Plugin + * Copyright (C) 2021 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * For a full copy of the GNU General Public License see the LICENSE file. + */ + +#include "src/DistrhoDefines.h" + +#if defined(DISTRHO_OS_HAIKU) +#elif defined(DISTRHO_OS_MAC) +# import +#elif defined(DISTRHO_OS_WINDOWS) +#else +# include +# include +#endif + +#include "PluginHostWindow.hpp" + +#ifdef DISTRHO_OS_MAC +@interface IldaeilPluginView : NSView +- (void)resizeWithOldSuperviewSize:(NSSize)oldSize; +@end +@implementation IldaeilPluginView +- (void)resizeWithOldSuperviewSize:(NSSize)oldSize +{ + [super resizeWithOldSuperviewSize:oldSize]; +} +@end +#endif + +START_NAMESPACE_DGL + +#if defined(DISTRHO_OS_HAIKU) +#elif defined(DISTRHO_OS_MAC) +#elif defined(DISTRHO_OS_WINDOWS) +#else +#endif + +struct PluginHostWindow::PrivateData +{ + Window& parentWindow; + const uintptr_t parentWindowId; + Callbacks* const pluginWindowCallbacks; + +#if defined(DISTRHO_OS_HAIKU) +#elif defined(DISTRHO_OS_MAC) + IldaeilPluginView* view; +#elif defined(DISTRHO_OS_WINDOWS) +#else +#endif + + bool lookingForChildren; + + PrivateData(Window& pw, Callbacks* const cbs) + : parentWindow(pw), + parentWindowId(pw.getNativeWindowHandle()), + pluginWindowCallbacks(cbs), +#if defined(DISTRHO_OS_HAIKU) +#elif defined(DISTRHO_OS_MAC) + view(nullptr), +#elif defined(DISTRHO_OS_WINDOWS) +#else +#endif + lookingForChildren(false) + { + view = [[IldaeilPluginView new]retain]; + DISTRHO_SAFE_ASSERT_RETURN(view != nullptr,) + + [view setAutoresizingMask:NSViewNotSizable]; + [view setAutoresizesSubviews:YES]; + [view setHidden:YES]; + [(NSView*)parentWindowId addSubview:view]; + } + + ~PrivateData() + { +#if defined(DISTRHO_OS_HAIKU) +#elif defined(DISTRHO_OS_MAC) + if (view != nullptr) + { + [view release]; + view = nullptr; + } +#elif defined(DISTRHO_OS_WINDOWS) +#else +#endif + } + + void* attachAndGetWindowHandle() + { + lookingForChildren = true; +#if defined(DISTRHO_OS_HAIKU) +#elif defined(DISTRHO_OS_MAC) + return view; +#elif defined(DISTRHO_OS_WINDOWS) +#else +#endif + } + + void detach() + { +#if defined(DISTRHO_OS_HAIKU) +#elif defined(DISTRHO_OS_MAC) + if (view != nullptr) + [view setHidden:YES]; +#elif defined(DISTRHO_OS_WINDOWS) +#else +#endif + } + + void idle() + { + if (lookingForChildren) + { +#if defined(DISTRHO_OS_HAIKU) +#elif defined(DISTRHO_OS_MAC) + if (view == nullptr) + return; + + for (NSView* subview in [view subviews]) + { + const double scaleFactor = [[[view window] screen] backingScaleFactor]; + const NSSize size = [subview frame].size; + const double width = size.width; + const double height = size.height; + + d_stdout("found subview %f %f", width, height); + + if (width <= 1 || height <= 1) + break; + + lookingForChildren = false; + [view setFrameSize:size]; + [view setHidden:NO]; + [view setNeedsDisplay:YES]; + pluginWindowCallbacks->pluginWindowResized(width * scaleFactor, height * scaleFactor); + break; + } +#elif defined(DISTRHO_OS_WINDOWS) +#else +#endif + } + } + + void setPositionAndSize(const uint x, const uint y, const uint width, const uint height) + { +#if defined(DISTRHO_OS_HAIKU) +#elif defined(DISTRHO_OS_MAC) + if (view != nullptr) + { + const double scaleFactor = [[[view window] screen] backingScaleFactor]; + [view setFrame:NSMakeRect(x / scaleFactor, y / scaleFactor, width / scaleFactor, height / scaleFactor)]; + } +#elif defined(DISTRHO_OS_WINDOWS) +#else +#endif + } +}; + +PluginHostWindow::PluginHostWindow(Window& parentWindow, Callbacks* const cbs) + : pData(new PrivateData(parentWindow, cbs)) {} + +PluginHostWindow::~PluginHostWindow() +{ + delete pData; +} + +void* PluginHostWindow::attachAndGetWindowHandle() +{ + return pData->attachAndGetWindowHandle(); +} + +void PluginHostWindow::detach() +{ + pData->detach(); +} + +void PluginHostWindow::idle() +{ + pData->idle(); +} + +void PluginHostWindow::setPositionAndSize(const uint x, const uint y, const uint width, const uint height) +{ + pData->setPositionAndSize(x, y, width, height); +} + +END_NAMESPACE_DGL diff --git a/plugins/Common/PluginHostWindow.hpp b/plugins/Common/PluginHostWindow.hpp new file mode 100644 index 0000000..b0c8bb9 --- /dev/null +++ b/plugins/Common/PluginHostWindow.hpp @@ -0,0 +1,42 @@ +/* + * DISTRHO Ildaeil Plugin + * Copyright (C) 2021 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * For a full copy of the GNU General Public License see the LICENSE file. + */ + +#include "Window.hpp" + +START_NAMESPACE_DGL + +class PluginHostWindow +{ + struct PrivateData; + PrivateData* const pData; + +public: + struct Callbacks { + virtual ~Callbacks() {} + virtual void pluginWindowResized(uint width, uint height) = 0; + }; + + explicit PluginHostWindow(Window& parentWindow, Callbacks* cbs); + ~PluginHostWindow(); + + void* attachAndGetWindowHandle(); + void detach(); + void idle(); + void setPositionAndSize(uint x, uint y, uint width, uint height); +}; + +END_NAMESPACE_DGL diff --git a/plugins/Common/SizeUtils.cpp b/plugins/Common/SizeUtils.cpp index 61261f3..be435ea 100644 --- a/plugins/Common/SizeUtils.cpp +++ b/plugins/Common/SizeUtils.cpp @@ -56,12 +56,14 @@ Size getChildWindowSize(const uintptr_t winId) { #if defined(DISTRHO_OS_HAIKU) #elif defined(DISTRHO_OS_MAC) + /* for (NSView* subview in [(NSView*)winId subviews]) { // [subview setFrame:NSMakeRect(0, 0, width, height)]; d_stdout("found subview"); return Size(subview.frame.size.width, subview.frame.size.height); } + */ #elif defined(DISTRHO_OS_WINDOWS) #else if (::Display* const display = XOpenDisplay(nullptr)) diff --git a/plugins/FX/Makefile b/plugins/FX/Makefile index 29643f6..185580f 100644 --- a/plugins/FX/Makefile +++ b/plugins/FX/Makefile @@ -17,6 +17,7 @@ FILES_DSP = \ FILES_UI = \ IldaeilUI.cpp \ + ../Common/PluginHostWindow.cpp \ ../Common/SizeUtils.cpp \ ../../dpf-widgets/opengl/DearImGui.cpp @@ -65,6 +66,7 @@ BUILD_CXX_FLAGS += -I../../carla/source/backend BUILD_CXX_FLAGS += -I../../carla/source/includes ifeq ($(MACOS),true) +$(BUILD_DIR)/../Common/PluginHostWindow.cpp.o: BUILD_CXX_FLAGS += -ObjC++ $(BUILD_DIR)/../Common/SizeUtils.cpp.o: BUILD_CXX_FLAGS += -ObjC++ LINK_FLAGS += -framework AppKit LINK_FLAGS += -framework Accelerate