@@ -30,8 +30,9 @@ | |||||
class X11PluginUi : public CarlaPluginUi | class X11PluginUi : public CarlaPluginUi | ||||
{ | { | ||||
public: | public: | ||||
X11PluginUi() noexcept | |||||
: fDisplay(nullptr), | |||||
X11PluginUi(CloseCallback* cb) noexcept | |||||
: CarlaPluginUi(cb), | |||||
fDisplay(nullptr), | |||||
fWindow(0) | fWindow(0) | ||||
{ | { | ||||
fDisplay = XOpenDisplay(0); | fDisplay = XOpenDisplay(0); | ||||
@@ -90,6 +91,23 @@ public: | |||||
void idle() override | 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 | void focus() override | ||||
@@ -145,23 +163,23 @@ private: | |||||
// ----------------------------------------------------- | // ----------------------------------------------------- | ||||
#ifdef CARLA_OS_MAC | #ifdef CARLA_OS_MAC | ||||
CarlaPluginUi* CarlaPluginUi::newCocoa() | |||||
CarlaPluginUi* CarlaPluginUi::newCocoa(CloseCallback* cb) | |||||
{ | { | ||||
return new CocoaPluginUi(); | |||||
return new CocoaPluginUi(cb); | |||||
} | } | ||||
#endif | #endif | ||||
#ifdef CARLA_OS_WIN | #ifdef CARLA_OS_WIN | ||||
CarlaPluginUi* CarlaPluginUi::newWindows() | |||||
CarlaPluginUi* CarlaPluginUi::newWindows(CloseCallback* cb) | |||||
{ | { | ||||
return new WindowsPluginUi(); | |||||
return new WindowsPluginUi(cb); | |||||
} | } | ||||
#endif | #endif | ||||
#ifdef HAVE_X11 | #ifdef HAVE_X11 | ||||
CarlaPluginUi* CarlaPluginUi::newX11() | |||||
CarlaPluginUi* CarlaPluginUi::newX11(CloseCallback* cb) | |||||
{ | { | ||||
return new X11PluginUi(); | |||||
return new X11PluginUi(cb); | |||||
} | } | ||||
#endif | #endif | ||||
@@ -24,9 +24,13 @@ | |||||
class CarlaPluginUi | class CarlaPluginUi | ||||
{ | { | ||||
protected: | |||||
CarlaPluginUi() noexcept {} | |||||
public: | public: | ||||
class CloseCallback { | |||||
public: | |||||
virtual ~CloseCallback() {} | |||||
virtual void handlePluginUiClosed() = 0; | |||||
}; | |||||
virtual ~CarlaPluginUi() {} | virtual ~CarlaPluginUi() {} | ||||
virtual void show() = 0; | virtual void show() = 0; | ||||
virtual void hide() = 0; | virtual void hide() = 0; | ||||
@@ -37,14 +41,18 @@ public: | |||||
virtual void* getPtr() const noexcept = 0; | virtual void* getPtr() const noexcept = 0; | ||||
#ifdef CARLA_OS_MAC | #ifdef CARLA_OS_MAC | ||||
static CarlaPluginUi* newCocoa(); | |||||
static CarlaPluginUi* newCocoa(CloseCallback*); | |||||
#endif | #endif | ||||
#ifdef CARLA_OS_WIN | #ifdef CARLA_OS_WIN | ||||
static CarlaPluginUi* newWindows(); | |||||
static CarlaPluginUi* newWindows(CloseCallback*); | |||||
#endif | #endif | ||||
#ifdef HAVE_X11 | #ifdef HAVE_X11 | ||||
static CarlaPluginUi* newX11(); | |||||
static CarlaPluginUi* newX11(CloseCallback*); | |||||
#endif | #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: | public: | ||||
Lv2Plugin(CarlaEngine* const engine, const unsigned int id) | Lv2Plugin(CarlaEngine* const engine, const unsigned int id) | ||||
@@ -1127,7 +1128,7 @@ public: | |||||
case LV2_UI_COCOA: | case LV2_UI_COCOA: | ||||
#ifdef CARLA_OS_MAC | #ifdef CARLA_OS_MAC | ||||
fUi.window = CarlaPluginUi::newCocoa(); | |||||
fUi.window = CarlaPluginUi::newCocoa(this); | |||||
#else | #else | ||||
msg = "UI is for MacOS only"; | msg = "UI is for MacOS only"; | ||||
#endif | #endif | ||||
@@ -1135,7 +1136,7 @@ public: | |||||
case LV2_UI_WINDOWS: | case LV2_UI_WINDOWS: | ||||
#ifdef CARLA_OS_WIN | #ifdef CARLA_OS_WIN | ||||
fUi.window = CarlaPluginUi::newWindows(); | |||||
fUi.window = CarlaPluginUi::newWindows(this); | |||||
#else | #else | ||||
msg = "UI is for Windows only"; | msg = "UI is for Windows only"; | ||||
#endif | #endif | ||||
@@ -1143,7 +1144,7 @@ public: | |||||
case LV2_UI_X11: | case LV2_UI_X11: | ||||
#ifdef HAVE_X11 | #ifdef HAVE_X11 | ||||
fUi.window = CarlaPluginUi::newX11(); | |||||
fUi.window = CarlaPluginUi::newX11(this); | |||||
#else | #else | ||||
msg = "UI is only for systems with X11"; | msg = "UI is only for systems with X11"; | ||||
#endif | #endif | ||||
@@ -1262,7 +1263,9 @@ public: | |||||
if (fUi.handle != nullptr && fUi.descriptor != nullptr) | 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); | LV2_EXTERNAL_UI_RUN((LV2_External_UI_Widget*)fUi.widget); | ||||
if (fExt.uiidle != nullptr && fExt.uiidle->idle(fUi.handle) != 0) | 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); | 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 | uint32_t handleUiPortMap(const char* const symbol) const noexcept | ||||