@@ -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 | |||