| @@ -30,8 +30,9 @@ | |||
| class X11PluginUi : public CarlaPluginUi | |||
| { | |||
| public: | |||
| X11PluginUi() noexcept | |||
| : fDisplay(nullptr), | |||
| X11PluginUi(CloseCallback* cb) noexcept | |||
| : CarlaPluginUi(cb), | |||
| fDisplay(nullptr), | |||
| fWindow(0) | |||
| { | |||
| fDisplay = XOpenDisplay(0); | |||
| @@ -90,6 +91,23 @@ public: | |||
| void idle() override | |||
| { | |||
| for (XEvent event; XPending(fDisplay) > 0;) | |||
| { | |||
| XNextEvent(fDisplay, &event); | |||
| switch (event.type) | |||
| { | |||
| case ClientMessage: | |||
| if (std::strcmp(XGetAtomName(fDisplay, event.xclient.message_type), "WM_PROTOCOLS") == 0) | |||
| { | |||
| CARLA_SAFE_ASSERT_BREAK(fCallback != nullptr); | |||
| fCallback->handlePluginUiClosed(); | |||
| } | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| void focus() override | |||
| @@ -145,23 +163,23 @@ private: | |||
| // ----------------------------------------------------- | |||
| #ifdef CARLA_OS_MAC | |||
| CarlaPluginUi* CarlaPluginUi::newCocoa() | |||
| CarlaPluginUi* CarlaPluginUi::newCocoa(CloseCallback* cb) | |||
| { | |||
| return new CocoaPluginUi(); | |||
| return new CocoaPluginUi(cb); | |||
| } | |||
| #endif | |||
| #ifdef CARLA_OS_WIN | |||
| CarlaPluginUi* CarlaPluginUi::newWindows() | |||
| CarlaPluginUi* CarlaPluginUi::newWindows(CloseCallback* cb) | |||
| { | |||
| return new WindowsPluginUi(); | |||
| return new WindowsPluginUi(cb); | |||
| } | |||
| #endif | |||
| #ifdef HAVE_X11 | |||
| CarlaPluginUi* CarlaPluginUi::newX11() | |||
| CarlaPluginUi* CarlaPluginUi::newX11(CloseCallback* cb) | |||
| { | |||
| return new X11PluginUi(); | |||
| return new X11PluginUi(cb); | |||
| } | |||
| #endif | |||
| @@ -24,9 +24,13 @@ | |||
| class CarlaPluginUi | |||
| { | |||
| protected: | |||
| CarlaPluginUi() noexcept {} | |||
| public: | |||
| class CloseCallback { | |||
| public: | |||
| virtual ~CloseCallback() {} | |||
| virtual void handlePluginUiClosed() = 0; | |||
| }; | |||
| virtual ~CarlaPluginUi() {} | |||
| virtual void show() = 0; | |||
| virtual void hide() = 0; | |||
| @@ -37,14 +41,18 @@ public: | |||
| virtual void* getPtr() const noexcept = 0; | |||
| #ifdef CARLA_OS_MAC | |||
| static CarlaPluginUi* newCocoa(); | |||
| static CarlaPluginUi* newCocoa(CloseCallback*); | |||
| #endif | |||
| #ifdef CARLA_OS_WIN | |||
| static CarlaPluginUi* newWindows(); | |||
| static CarlaPluginUi* newWindows(CloseCallback*); | |||
| #endif | |||
| #ifdef HAVE_X11 | |||
| static CarlaPluginUi* newX11(); | |||
| static CarlaPluginUi* newX11(CloseCallback*); | |||
| #endif | |||
| protected: | |||
| CloseCallback* fCallback; | |||
| CarlaPluginUi(CloseCallback* cb) noexcept : fCallback(cb) {} | |||
| }; | |||
| // ----------------------------------------------------- | |||
| @@ -331,7 +331,8 @@ struct Lv2PluginOptions { | |||
| // ----------------------------------------------------- | |||
| class Lv2Plugin : public CarlaPlugin | |||
| class Lv2Plugin : public CarlaPlugin, | |||
| CarlaPluginUi::CloseCallback | |||
| { | |||
| public: | |||
| Lv2Plugin(CarlaEngine* const engine, const unsigned int id) | |||
| @@ -1127,7 +1128,7 @@ public: | |||
| case LV2_UI_COCOA: | |||
| #ifdef CARLA_OS_MAC | |||
| fUi.window = CarlaPluginUi::newCocoa(); | |||
| fUi.window = CarlaPluginUi::newCocoa(this); | |||
| #else | |||
| msg = "UI is for MacOS only"; | |||
| #endif | |||
| @@ -1135,7 +1136,7 @@ public: | |||
| case LV2_UI_WINDOWS: | |||
| #ifdef CARLA_OS_WIN | |||
| fUi.window = CarlaPluginUi::newWindows(); | |||
| fUi.window = CarlaPluginUi::newWindows(this); | |||
| #else | |||
| msg = "UI is for Windows only"; | |||
| #endif | |||
| @@ -1143,7 +1144,7 @@ public: | |||
| case LV2_UI_X11: | |||
| #ifdef HAVE_X11 | |||
| fUi.window = CarlaPluginUi::newX11(); | |||
| fUi.window = CarlaPluginUi::newX11(this); | |||
| #else | |||
| msg = "UI is only for systems with X11"; | |||
| #endif | |||
| @@ -1262,7 +1263,9 @@ public: | |||
| if (fUi.handle != nullptr && fUi.descriptor != nullptr) | |||
| { | |||
| if (fUi.type == UI::TYPE_EXTERNAL && fUi.widget != nullptr) | |||
| if (fUi.type == UI::TYPE_EMBED && fUi.window != nullptr) | |||
| fUi.window->idle(); | |||
| else if (fUi.type == UI::TYPE_EXTERNAL && fUi.widget != nullptr) | |||
| LV2_EXTERNAL_UI_RUN((LV2_External_UI_Widget*)fUi.widget); | |||
| if (fExt.uiidle != nullptr && fExt.uiidle->idle(fUi.handle) != 0) | |||
| @@ -4034,6 +4037,22 @@ public: | |||
| pData->engine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0.0f, nullptr); | |||
| } | |||
| void handlePluginUiClosed() override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(fUi.type == UI::TYPE_EMBED,); | |||
| CARLA_SAFE_ASSERT_RETURN(fUi.window != nullptr,); | |||
| carla_debug("Lv2Plugin::handleExternalUiClosed()"); | |||
| fUi.window->hide(); | |||
| if (fUi.handle != nullptr && fUi.descriptor != nullptr && fUi.descriptor->cleanup != nullptr) | |||
| fUi.descriptor->cleanup(fUi.handle); | |||
| fUi.handle = nullptr; | |||
| fUi.widget = nullptr; | |||
| pData->engine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0.0f, nullptr); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| uint32_t handleUiPortMap(const char* const symbol) const noexcept | |||