diff --git a/source/backend/CarlaUtils.cpp b/source/backend/CarlaUtils.cpp index c6c315177..1d2397bac 100644 --- a/source/backend/CarlaUtils.cpp +++ b/source/backend/CarlaUtils.cpp @@ -27,6 +27,10 @@ #include "water/files/File.h" +#ifdef CARLA_OS_MAC +# import +#endif + #ifndef CARLA_UTILS_CACHED_PLUGINS_ONLY # include "rtaudio/RtAudio.h" # include "rtmidi/RtMidi.h" @@ -711,7 +715,8 @@ const char* carla_get_library_folder() void carla_x11_reparent_window(uintptr_t winId1, uintptr_t winId2) { - carla_debug("carla_x11_reparent_window()"); + CARLA_SAFE_ASSERT_RETURN(winId1 != 0,); + CARLA_SAFE_ASSERT_RETURN(winId2 != 0,); #ifdef HAVE_X11 if (::Display* const disp = XOpenDisplay(nullptr)) @@ -725,6 +730,8 @@ void carla_x11_reparent_window(uintptr_t winId1, uintptr_t winId2) void carla_x11_move_window(uintptr_t winId, int x, int y) { + CARLA_SAFE_ASSERT_RETURN(winId != 0,); + #ifdef HAVE_X11 if (::Display* const disp = XOpenDisplay(nullptr)) { @@ -736,12 +743,15 @@ void carla_x11_move_window(uintptr_t winId, int x, int y) int* carla_x11_get_window_pos(uintptr_t winId) { - carla_debug("carla_x11_get_window_pos()"); - static int pos[2]; + if (winId == 0) + { + pos[0] = 0; + pos[1] = 0; + } #ifdef HAVE_X11 - if (::Display* const disp = XOpenDisplay(nullptr)) + else if (::Display* const disp = XOpenDisplay(nullptr)) { int x, y; Window child; @@ -752,8 +762,8 @@ int* carla_x11_get_window_pos(uintptr_t winId) pos[0] = x - xwa.x; pos[1] = y - xwa.y; } - else #endif + else { pos[0] = 0; pos[1] = 0; @@ -762,6 +772,18 @@ int* carla_x11_get_window_pos(uintptr_t winId) return pos; } +int carla_cocoa_get_window(void* nsViewPtr) +{ + CARLA_SAFE_ASSERT_RETURN(nsViewPtr != nullptr, 0); + +#ifdef CARLA_OS_MAC + NSView* nsView = (NSView*)nsViewPtr; + return [[nsView window] windowNumber]; +#else + return 0; +#endif +} + // ------------------------------------------------------------------------------------------------------------------- #include "CarlaPipeUtils.cpp" diff --git a/source/backend/CarlaUtils.h b/source/backend/CarlaUtils.h index d3396cf9a..0ce4f613f 100644 --- a/source/backend/CarlaUtils.h +++ b/source/backend/CarlaUtils.h @@ -248,6 +248,8 @@ CARLA_EXPORT void carla_x11_move_window(uintptr_t winId, int x, int y); CARLA_EXPORT int* carla_x11_get_window_pos(uintptr_t winId); +CARLA_EXPORT int carla_cocoa_get_window(void* nsViewPtr); + // ------------------------------------------------------------------------------------------------------------------- /** @} */ diff --git a/source/backend/Makefile b/source/backend/Makefile index cb8953163..767e8401a 100644 --- a/source/backend/Makefile +++ b/source/backend/Makefile @@ -110,6 +110,11 @@ $(OBJDIR)/CarlaStandalone.cpp.o: CarlaStandalone.cpp -@mkdir -p $(OBJDIR) @echo "Compiling $<" @$(CXX) $< $(BUILD_CXX_FLAGS) -ObjC++ -c -o $@ + +$(OBJDIR)/CarlaUtils.cpp.o: CarlaUtils.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling $<" + @$(CXX) $< $(BUILD_CXX_FLAGS) -ObjC++ -c -o $@ endif $(OBJDIR)/%.cpp.o: %.cpp diff --git a/source/backend/plugin/CarlaPluginLV2.cpp b/source/backend/plugin/CarlaPluginLV2.cpp index 184fc9cde..5d11d5340 100644 --- a/source/backend/plugin/CarlaPluginLV2.cpp +++ b/source/backend/plugin/CarlaPluginLV2.cpp @@ -496,7 +496,7 @@ private: // ------------------------------------------------------------------------------------------------------------------- class CarlaPluginLV2 : public CarlaPlugin, - private CarlaPluginUI::CloseCallback + private CarlaPluginUI::Callback { public: CarlaPluginLV2(CarlaEngine* const engine, const uint id) diff --git a/source/backend/plugin/CarlaPluginVST2.cpp b/source/backend/plugin/CarlaPluginVST2.cpp index 3054b410d..379f22803 100644 --- a/source/backend/plugin/CarlaPluginVST2.cpp +++ b/source/backend/plugin/CarlaPluginVST2.cpp @@ -49,7 +49,7 @@ static const int32_t kVstMidiEventSize = static_cast(sizeof(VstMidiEven // ----------------------------------------------------- class CarlaPluginVST2 : public CarlaPlugin, - private CarlaPluginUI::CloseCallback + private CarlaPluginUI::Callback { public: CarlaPluginVST2(CarlaEngine* const engine, const uint id) @@ -435,7 +435,7 @@ public: const char* msg = nullptr; const uintptr_t frontendWinId(pData->engine->getOptions().frontendWinId); -#if defined(CARLA_OS_MAC) && defined(__LP64__) +#if defined(CARLA_OS_MAC) && defined(CARLA_OS_64BIT) fUI.window = CarlaPluginUI::newCocoa(this, frontendWinId, false); #elif defined(CARLA_OS_WIN) fUI.window = CarlaPluginUI::newWindows(this, frontendWinId, false); diff --git a/source/bridges-plugin/CarlaBridgePlugin.cpp b/source/bridges-plugin/CarlaBridgePlugin.cpp index acb756a30..a93ec7002 100644 --- a/source/bridges-plugin/CarlaBridgePlugin.cpp +++ b/source/bridges-plugin/CarlaBridgePlugin.cpp @@ -178,7 +178,12 @@ public: for (; runMainLoopOnce() && ! gCloseNow;) { gIdle(); +#if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN) + // MacOS and Win32 have event-loops to run, so minimize sleep time carla_msleep(1); +#else + carla_msleep(5); +#endif } carla_set_engine_about_to_close(); diff --git a/source/bridges-ui/CarlaBridgeToolkitPlugin.cpp b/source/bridges-ui/CarlaBridgeToolkitPlugin.cpp index 59b86c5ee..ae58831c2 100644 --- a/source/bridges-ui/CarlaBridgeToolkitPlugin.cpp +++ b/source/bridges-ui/CarlaBridgeToolkitPlugin.cpp @@ -17,15 +17,17 @@ #include "CarlaBridgeUI.hpp" #include "CarlaBridgeToolkit.hpp" - +#include "CarlaMainLoop.hpp" #include "CarlaPluginUI.hpp" CARLA_BRIDGE_START_NAMESPACE +using CarlaBackend::runMainLoopOnce; + // ------------------------------------------------------------------------- class CarlaBridgeToolkitPlugin : public CarlaBridgeToolkit, - private CarlaPluginUI::CloseCallback + private CarlaPluginUI::Callback { public: CarlaBridgeToolkitPlugin(CarlaBridgeUI* const u) @@ -50,9 +52,9 @@ public: const CarlaBridgeUI::Options& options(ui->getOptions()); #if defined(CARLA_OS_MAC) && defined(BRIDGE_COCOA) - fUI = nullptr; + fUI = CarlaPluginUI::newCocoa(this, 0, options.isResizable); #elif defined(CARLA_OS_WIN) && defined(BRIDGE_HWND) - fUI = nullptr; + fUI = CarlaPluginUI::newWindows(this, 0, options.isResizable); #elif defined(HAVE_X11) && defined(BRIDGE_X11) fUI = CarlaPluginUI::newX11(this, 0, options.isResizable); #endif @@ -60,8 +62,11 @@ public: fUI->setTitle(options.windowTitle.buffer()); +#ifdef HAVE_X11 + // Out-of-process reparenting only possible on X11 if (options.transientWindowId != 0) fUI->setTransientWinId(options.transientWindowId); +#endif return true; } @@ -83,14 +88,19 @@ public: fIdling = true; - for (; fIdling;) + for (; runMainLoopOnce() && fIdling;) { if (ui->isPipeRunning()) ui->idlePipe(); ui->idleUI(); fUI->idle(); +#if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN) + // MacOS and Win32 have event-loops to run, so minimize sleep time + carla_msleep(1); +#else carla_msleep(20); +#endif } } diff --git a/source/carla_host.py b/source/carla_host.py index 0223aae16..91fbae39d 100644 --- a/source/carla_host.py +++ b/source/carla_host.py @@ -2129,7 +2129,11 @@ class HostWindow(QMainWindow): # set our gui as parent for all plugins UIs if self.host.manageUIs and not (self.host.isControl or self.host.isPlugin): - winIdStr = "%x" % int(self.winId()) + if MACOS: + nsViewPtr = int(self.winId()) + winIdStr = "%x" % gCarla.utils.cocoa_get_window(nsViewPtr) + else: + winIdStr = "%x" % int(self.winId()) self.host.set_engine_option(ENGINE_OPTION_FRONTEND_WIN_ID, 0, winIdStr) def hideEvent(self, event): diff --git a/source/carla_settings.py b/source/carla_settings.py index 321da044a..96dfa826a 100755 --- a/source/carla_settings.py +++ b/source/carla_settings.py @@ -243,7 +243,7 @@ class CarlaSettingsW(QDialog): self.ui.ch_main_show_logs.setEnabled(False) self.ui.ch_main_show_logs.setVisible(False) - if MACOS or WINDOWS: + if WINDOWS: self.ui.ch_engine_manage_uis.setEnabled(False) self.ui.ch_engine_manage_uis.setVisible(False) diff --git a/source/carla_utils.py b/source/carla_utils.py index 6b3478fab..9dd7a98a1 100644 --- a/source/carla_utils.py +++ b/source/carla_utils.py @@ -224,6 +224,9 @@ class CarlaUtils(object): self.lib.carla_x11_get_window_pos.argtypes = [c_uintptr] self.lib.carla_x11_get_window_pos.restype = POINTER(c_int) + self.lib.carla_cocoa_get_window.argtypes = [c_uintptr] + self.lib.carla_cocoa_get_window.restype = c_int + # use _putenv on windows if not WINDOWS: self.msvcrt = None @@ -338,4 +341,7 @@ class CarlaUtils(object): data = self.lib.carla_x11_get_window_pos(winId) return (int(data[0]), int(data[1])) + def cocoa_get_window(self, winId): + return self.lib.carla_cocoa_get_window(winId) + # ------------------------------------------------------------------------------------------------------------ diff --git a/source/modules/dgl/src/Window.cpp b/source/modules/dgl/src/Window.cpp index a3cdea3e7..2855a2c10 100644 --- a/source/modules/dgl/src/Window.cpp +++ b/source/modules/dgl/src/Window.cpp @@ -403,11 +403,7 @@ struct Window::PrivateData { SetFocus(hwnd); #elif defined(DISTRHO_OS_MAC) if (mWindow != nullptr) - { - // TODO - //[NSApp activateIgnoringOtherApps:YES]; - //[mWindow makeKeyAndOrderFront:mWindow]; - } + [mWindow makeKeyWindow]; #elif defined(DISTRHO_OS_LINUX) XRaiseWindow(xDisplay, xWindow); XSetInputFocus(xDisplay, xWindow, RevertToPointerRoot, CurrentTime); @@ -626,12 +622,17 @@ struct Window::PrivateData { void setTransientWinId(const uintptr_t winId) { -#if defined(DISTRHO_OS_LINUX) + DISTRHO_SAFE_ASSERT_RETURN(winId != 0,); + +#if defined(DISTRHO_OS_MAC) + NSWindow* window = [NSApp windowWithWindowNumber:winId]; + DISTRHO_SAFE_ASSERT_RETURN(window != nullptr,); + + [window addChildWindow:mWindow + ordered:NSWindowAbove]; + [mWindow makeKeyWindow]; +#elif defined(DISTRHO_OS_LINUX) XSetTransientForHint(xDisplay, xWindow, static_cast< ::Window>(winId)); -#else - return; - // unused - (void)winId; #endif } diff --git a/source/utils/CarlaPluginUI.cpp b/source/utils/CarlaPluginUI.cpp index 50bdbbe33..d509923ea 100644 --- a/source/utils/CarlaPluginUI.cpp +++ b/source/utils/CarlaPluginUI.cpp @@ -53,7 +53,7 @@ static int temporaryErrorHandler(Display*, XErrorEvent*) class X11PluginUI : public CarlaPluginUI { public: - X11PluginUI(CloseCallback* const cb, const uintptr_t parentId, const bool isResizable) noexcept + X11PluginUI(Callback* const cb, const uintptr_t parentId, const bool isResizable) noexcept : CarlaPluginUI(cb, isResizable), fDisplay(nullptr), fWindow(0), @@ -330,16 +330,18 @@ private: @interface CarlaPluginWindow : NSWindow { @public - CarlaPluginUI::CloseCallback* callback; + CarlaPluginUI::Callback* callback; + NSView* view; } - (id) initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag; -- (void) setCloseCallback:(CarlaPluginUI::CloseCallback*)cb; +- (void) setup:(CarlaPluginUI::Callback*)cb view:(NSView*)v; - (BOOL) canBecomeKeyWindow; - (BOOL) windowShouldClose:(id)sender; +- (NSSize) windowWillResize:(NSWindow*)sender toSize:(NSSize)frameSize; @end @implementation CarlaPluginWindow @@ -350,6 +352,7 @@ private: defer:(BOOL)flag { callback = nil; + view = nil; NSWindow* result = [super initWithContentRect:contentRect styleMask:(NSClosableWindowMask | @@ -367,9 +370,10 @@ private: (void)aStyle; (void)bufferingType; (void)flag; } -- (void)setCloseCallback:(CarlaPluginUI::CloseCallback*)cb +- (void)setup:(CarlaPluginUI::Callback*)cb view:(NSView*)v { callback = cb; + view = v; } - (BOOL)canBecomeKeyWindow @@ -379,23 +383,36 @@ private: - (BOOL)windowShouldClose:(id)sender { - if (callback) + if (callback != nil) callback->handlePluginUIClosed(); + return NO; // unused (void)sender; } +- (NSSize) windowWillResize:(NSWindow*)sender toSize:(NSSize)frameSize +{ + if (callback != nil) + callback->handlePluginUIResized(frameSize.width, frameSize.height); + + return frameSize; + + // unused + (void)sender; +} + @end class CocoaPluginUI : public CarlaPluginUI { public: - CocoaPluginUI(CloseCallback* const cb, const uintptr_t parentId, const bool isResizable) noexcept + CocoaPluginUI(Callback* const cb, const uintptr_t parentId, const bool isResizable) noexcept : CarlaPluginUI(cb, isResizable), fView(nullptr), - fWindow(0) + fWindow(0), + fParentId(parentId) { [NSAutoreleasePool new]; [NSApplication sharedApplication]; @@ -418,13 +435,16 @@ public: if (! isResizable) [[fWindow standardWindowButton:NSWindowZoomButton] setHidden:YES]; - [fWindow setCloseCallback:cb]; + [fWindow setup:cb view:fView]; [fWindow setContentView:fView]; [fWindow makeFirstResponder:fView]; [fWindow makeKeyAndOrderFront:fWindow]; [NSApp activateIgnoringOtherApps:YES]; [fWindow center]; + + if (parentId != 0) + setTransientWinId(parentId); } ~CocoaPluginUI() override @@ -443,6 +463,9 @@ public: [fView setHidden:NO]; [fWindow setIsVisible:YES]; + + if (fParentId != 0) + setTransientWinId(fParentId); } void hide() override @@ -459,14 +482,14 @@ public: void focus() override { - CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,); + CARLA_SAFE_ASSERT_RETURN(fWindow != 0,); - // TODO + [fWindow makeKeyWindow]; } void setSize(const uint width, const uint height, const bool forceUpdate) override { - CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,); + CARLA_SAFE_ASSERT_RETURN(fWindow != 0,); CARLA_SAFE_ASSERT_RETURN(fView != nullptr,); [fView setFrame:NSMakeRect(0, 0, width, height)]; @@ -504,7 +527,12 @@ public: { CARLA_SAFE_ASSERT_RETURN(fWindow != 0,); - // TODO + NSWindow* window = [NSApp windowWithWindowNumber:winId]; + CARLA_SAFE_ASSERT_RETURN(window != nullptr,); + + [window addChildWindow:fWindow + ordered:NSWindowAbove]; + [fWindow makeKeyWindow]; } void* getPtr() const noexcept override @@ -520,6 +548,7 @@ public: private: NSView* fView; id fWindow; + uintptr_t fParentId; CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CocoaPluginUI) }; @@ -538,7 +567,7 @@ static LRESULT CALLBACK wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM l class WindowsPluginUI : public CarlaPluginUI { public: - WindowsPluginUI(CloseCallback* const cb, const uintptr_t parentId, const bool isResizable) noexcept + WindowsPluginUI(Callback* const cb, const uintptr_t parentId, const bool isResizable) noexcept : CarlaPluginUI(cb, isResizable), fWindow(0), fIsVisible(false), @@ -582,6 +611,9 @@ public: } SetWindowLongPtr(fWindow, GWLP_USERDATA, (LONG_PTR)this); + + if (parentId != 0) + setTransientWinId(parentId); } ~WindowsPluginUI() override @@ -963,21 +995,21 @@ bool CarlaPluginUI::tryTransientWinIdMatch(const uintptr_t pid, const char* cons // ----------------------------------------------------- #ifdef HAVE_X11 -CarlaPluginUI* CarlaPluginUI::newX11(CloseCallback* cb, uintptr_t parentId, bool isResizable) +CarlaPluginUI* CarlaPluginUI::newX11(Callback* cb, uintptr_t parentId, bool isResizable) { return new X11PluginUI(cb, parentId, isResizable); } #endif #ifdef CARLA_OS_MAC -CarlaPluginUI* CarlaPluginUI::newCocoa(CloseCallback* cb, uintptr_t parentId, bool isResizable) +CarlaPluginUI* CarlaPluginUI::newCocoa(Callback* cb, uintptr_t parentId, bool isResizable) { return new CocoaPluginUI(cb, parentId, isResizable); } #endif #ifdef CARLA_OS_WIN -CarlaPluginUI* CarlaPluginUI::newWindows(CloseCallback* cb, uintptr_t parentId, bool isResizable) +CarlaPluginUI* CarlaPluginUI::newWindows(Callback* cb, uintptr_t parentId, bool isResizable) { return new WindowsPluginUI(cb, parentId, isResizable); } diff --git a/source/utils/CarlaPluginUI.hpp b/source/utils/CarlaPluginUI.hpp index e9401ef43..46cdc845d 100644 --- a/source/utils/CarlaPluginUI.hpp +++ b/source/utils/CarlaPluginUI.hpp @@ -25,9 +25,9 @@ class CarlaPluginUI { public: - class CloseCallback { + class Callback { public: - virtual ~CloseCallback() {} + virtual ~Callback() {} virtual void handlePluginUIClosed() = 0; virtual void handlePluginUIResized(const uint width, const uint height) = 0; }; @@ -48,21 +48,21 @@ public: static bool tryTransientWinIdMatch(const uintptr_t pid, const char* const uiTitle, const uintptr_t winId, const bool centerUI); #ifdef CARLA_OS_MAC - static CarlaPluginUI* newCocoa(CloseCallback*, uintptr_t, bool); + static CarlaPluginUI* newCocoa(Callback*, uintptr_t, bool); #endif #ifdef CARLA_OS_WIN - static CarlaPluginUI* newWindows(CloseCallback*, uintptr_t, bool); + static CarlaPluginUI* newWindows(Callback*, uintptr_t, bool); #endif #ifdef HAVE_X11 - static CarlaPluginUI* newX11(CloseCallback*, uintptr_t, bool); + static CarlaPluginUI* newX11(Callback*, uintptr_t, bool); #endif protected: bool fIsIdling; bool fIsResizable; - CloseCallback* fCallback; + Callback* fCallback; - CarlaPluginUI(CloseCallback* const cb, const bool isResizable) noexcept + CarlaPluginUI(Callback* const cb, const bool isResizable) noexcept : fIsIdling(false), fIsResizable(isResizable), fCallback(cb) {}