@@ -20,6 +20,10 @@ | |||||
#include <gtk/gtk.h> | #include <gtk/gtk.h> | ||||
#ifdef CARLA_OS_LINUX | |||||
# include <gdk/gdkx.h> | |||||
#endif | |||||
CARLA_BRIDGE_START_NAMESPACE | CARLA_BRIDGE_START_NAMESPACE | ||||
// ------------------------------------------------------------------------- | // ------------------------------------------------------------------------- | ||||
@@ -47,13 +51,13 @@ public: | |||||
~CarlaBridgeToolkitGtk() override | ~CarlaBridgeToolkitGtk() override | ||||
{ | { | ||||
CARLA_ASSERT(fWindow == nullptr); | |||||
CARLA_SAFE_ASSERT(fWindow == nullptr); | |||||
carla_debug("CarlaBridgeToolkitGtk::~CarlaBridgeToolkitGtk()"); | carla_debug("CarlaBridgeToolkitGtk::~CarlaBridgeToolkitGtk()"); | ||||
} | } | ||||
void init() override | void init() override | ||||
{ | { | ||||
CARLA_ASSERT(fWindow == nullptr); | |||||
CARLA_SAFE_ASSERT_RETURN(fWindow == nullptr,); | |||||
carla_debug("CarlaBridgeToolkitGtk::init()"); | carla_debug("CarlaBridgeToolkitGtk::init()"); | ||||
gtk_init(&gargc, &gargv); | gtk_init(&gargc, &gargv); | ||||
@@ -65,8 +69,8 @@ public: | |||||
void exec(const bool showUI) override | void exec(const bool showUI) override | ||||
{ | { | ||||
CARLA_ASSERT(kClient != nullptr); | |||||
CARLA_ASSERT(fWindow != nullptr); | |||||
CARLA_SAFE_ASSERT_RETURN(kClient != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,); | |||||
carla_debug("CarlaBridgeToolkitGtk::exec(%s)", bool2str(showUI)); | carla_debug("CarlaBridgeToolkitGtk::exec(%s)", bool2str(showUI)); | ||||
GtkWidget* const widget((GtkWidget*)kClient->getWidget()); | GtkWidget* const widget((GtkWidget*)kClient->getWidget()); | ||||
@@ -76,6 +80,33 @@ public: | |||||
gtk_window_set_resizable(GTK_WINDOW(fWindow), kClient->isResizable()); | gtk_window_set_resizable(GTK_WINDOW(fWindow), kClient->isResizable()); | ||||
gtk_window_set_title(GTK_WINDOW(fWindow), kWindowTitle); | gtk_window_set_title(GTK_WINDOW(fWindow), kWindowTitle); | ||||
if (const char* const winIdStr = std::getenv("ENGINE_OPTION_FRONTEND_WIN_ID")) | |||||
{ | |||||
if (const long long winId = std::strtoll(winIdStr, nullptr, 16)) | |||||
{ | |||||
#ifdef CARLA_OS_LINUX | |||||
if (GdkWindow* const gdkWindow = GDK_WINDOW(fWindow)) | |||||
{ | |||||
if (GdkDisplay* const gdkDisplay = gdk_window_get_display(gdkWindow)) | |||||
{ | |||||
::Display* const display(gdk_x11_display_get_xdisplay(gdkDisplay)); | |||||
# ifdef BRIDGE_GTK3 | |||||
::XID const xid(gdk_x11_window_get_xid(gdkWindow)); | |||||
# else | |||||
::XID xid = 0; | |||||
if (GdkDrawable* const gdkDrawable = GDK_DRAWABLE(fWindow)) | |||||
xid = gdk_x11_drawable_get_xid(gdkDrawable); | |||||
# endif | |||||
if (display != nullptr && xid != 0) | |||||
XSetTransientForHint(display, xid, static_cast<::Window>(winId)); | |||||
} | |||||
} | |||||
#else | |||||
(void)winId; | |||||
#endif | |||||
} | |||||
} | |||||
if (showUI || fNeedsShow) | if (showUI || fNeedsShow) | ||||
{ | { | ||||
show(); | show(); | ||||
@@ -101,8 +132,7 @@ public: | |||||
gtk_widget_destroy(fWindow); | gtk_widget_destroy(fWindow); | ||||
fWindow = nullptr; | fWindow = nullptr; | ||||
if (gtk_main_level() != 0) | |||||
gtk_main_quit(); | |||||
gtk_main_quit_if_needed(); | |||||
} | } | ||||
} | } | ||||
@@ -128,11 +158,10 @@ public: | |||||
void resize(int width, int height) override | void resize(int width, int height) override | ||||
{ | { | ||||
CARLA_ASSERT(fWindow != nullptr); | |||||
CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,); | |||||
carla_debug("CarlaBridgeToolkitGtk::resize(%i, %i)", width, height); | carla_debug("CarlaBridgeToolkitGtk::resize(%i, %i)", width, height); | ||||
if (fWindow != nullptr) | |||||
gtk_window_resize(GTK_WINDOW(fWindow), width, height); | |||||
gtk_window_resize(GTK_WINDOW(fWindow), width, height); | |||||
} | } | ||||
// --------------------------------------------------------------------- | // --------------------------------------------------------------------- | ||||
@@ -162,30 +191,38 @@ protected: | |||||
} | } | ||||
kClient->uiIdle(); | kClient->uiIdle(); | ||||
return kClient->oscIdle(); | |||||
if (! kClient->oscIdle()) | |||||
{ | |||||
gtk_main_quit_if_needed(); | |||||
return false; | |||||
} | |||||
return true; | |||||
} | } | ||||
// --------------------------------------------------------------------- | // --------------------------------------------------------------------- | ||||
private: | private: | ||||
static void gtk_ui_destroy(GtkWidget*, gpointer data) | |||||
static void gtk_main_quit_if_needed() | |||||
{ | { | ||||
CARLA_ASSERT(data != nullptr); | |||||
if (gtk_main_level() != 0) | |||||
gtk_main_quit(); | |||||
} | |||||
if (CarlaBridgeToolkitGtk* const _this_ = (CarlaBridgeToolkitGtk*)data) | |||||
_this_->handleDestroy(); | |||||
static void gtk_ui_destroy(GtkWidget*, gpointer data) | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(data != nullptr,); | |||||
gtk_main_quit(); | |||||
((CarlaBridgeToolkitGtk*)data)->handleDestroy(); | |||||
gtk_main_quit_if_needed(); | |||||
} | } | ||||
static gboolean gtk_ui_timeout(gpointer data) | static gboolean gtk_ui_timeout(gpointer data) | ||||
{ | { | ||||
CARLA_ASSERT(data != nullptr); | |||||
if (CarlaBridgeToolkitGtk* const _this_ = (CarlaBridgeToolkitGtk*)data) | |||||
return _this_->handleTimeout(); | |||||
CARLA_SAFE_ASSERT_RETURN(data != nullptr, false); | |||||
return false; | |||||
return ((CarlaBridgeToolkitGtk*)data)->handleTimeout(); | |||||
} | } | ||||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaBridgeToolkitGtk) | CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaBridgeToolkitGtk) | ||||
@@ -72,6 +72,12 @@ public: | |||||
CARLA_SAFE_ASSERT_RETURN(fUI != nullptr,); | CARLA_SAFE_ASSERT_RETURN(fUI != nullptr,); | ||||
carla_debug("CarlaBridgeToolkitPlugin::exec(%s)", bool2str(showUI)); | carla_debug("CarlaBridgeToolkitPlugin::exec(%s)", bool2str(showUI)); | ||||
if (const char* const winIdStr = std::getenv("ENGINE_OPTION_FRONTEND_WIN_ID")) | |||||
{ | |||||
if (const long long winId = std::strtoll(winIdStr, nullptr, 16)) | |||||
fUI->setTransientWinId(static_cast<uintptr_t>(winId)); | |||||
} | |||||
if (showUI) | if (showUI) | ||||
fUI->show(); | fUI->show(); | ||||
@@ -22,7 +22,7 @@ | |||||
#include <QtCore/QThread> | #include <QtCore/QThread> | ||||
#include <QtCore/QTimerEvent> | #include <QtCore/QTimerEvent> | ||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) | |||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) | |||||
# include <QtWidgets/QApplication> | # include <QtWidgets/QApplication> | ||||
# include <QtWidgets/QMainWindow> | # include <QtWidgets/QMainWindow> | ||||
#else | #else | ||||
@@ -30,6 +30,11 @@ | |||||
# include <QtGui/QMainWindow> | # include <QtGui/QMainWindow> | ||||
#endif | #endif | ||||
#if defined(CARLA_OS_LINUX) && QT_VERSION < QT_VERSION_CHECK(5, 0, 0) | |||||
# include <QtGui/QX11Info> | |||||
# include <X11/Xlib.h> | |||||
#endif | |||||
CARLA_BRIDGE_START_NAMESPACE | CARLA_BRIDGE_START_NAMESPACE | ||||
// ------------------------------------------------------------------------- | // ------------------------------------------------------------------------- | ||||
@@ -61,17 +66,17 @@ public: | |||||
~CarlaBridgeToolkitQt() override | ~CarlaBridgeToolkitQt() override | ||||
{ | { | ||||
CARLA_ASSERT(fApp == nullptr); | |||||
CARLA_ASSERT(fWindow == nullptr); | |||||
CARLA_ASSERT(fMsgTimer == 0); | |||||
CARLA_SAFE_ASSERT(fApp == nullptr); | |||||
CARLA_SAFE_ASSERT(fWindow == nullptr); | |||||
CARLA_SAFE_ASSERT(fMsgTimer == 0); | |||||
carla_debug("CarlaBridgeToolkitQt::~CarlaBridgeToolkitQt()"); | carla_debug("CarlaBridgeToolkitQt::~CarlaBridgeToolkitQt()"); | ||||
} | } | ||||
void init() override | void init() override | ||||
{ | { | ||||
CARLA_ASSERT(fApp == nullptr); | |||||
CARLA_ASSERT(fWindow == nullptr); | |||||
CARLA_ASSERT(fMsgTimer == 0); | |||||
CARLA_SAFE_ASSERT_RETURN(fApp == nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(fWindow == nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(fMsgTimer == 0,); | |||||
carla_debug("CarlaBridgeToolkitQt::init()"); | carla_debug("CarlaBridgeToolkitQt::init()"); | ||||
fApp = new QApplication(qargc, qargv); | fApp = new QApplication(qargc, qargv); | ||||
@@ -83,9 +88,9 @@ public: | |||||
void exec(const bool showUI) override | void exec(const bool showUI) override | ||||
{ | { | ||||
CARLA_ASSERT(kClient != nullptr); | |||||
CARLA_ASSERT(fApp != nullptr); | |||||
CARLA_ASSERT(fWindow != nullptr); | |||||
CARLA_SAFE_ASSERT_RETURN(kClient != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(fApp != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,); | |||||
carla_debug("CarlaBridgeToolkitQt::exec(%s)", bool2str(showUI)); | carla_debug("CarlaBridgeToolkitQt::exec(%s)", bool2str(showUI)); | ||||
QWidget* const widget((QWidget*)kClient->getWidget()); | QWidget* const widget((QWidget*)kClient->getWidget()); | ||||
@@ -99,7 +104,7 @@ public: | |||||
if (! kClient->isResizable()) | if (! kClient->isResizable()) | ||||
{ | { | ||||
fWindow->setFixedSize(fWindow->width(), fWindow->height()); | fWindow->setFixedSize(fWindow->width(), fWindow->height()); | ||||
#ifdef Q_OS_WIN | |||||
#ifdef CARLA_OS_WIN | |||||
fWindow->setWindowFlags(fWindow->windowFlags() | Qt::MSWindowsFixedSizeDialogHint); | fWindow->setWindowFlags(fWindow->windowFlags() | Qt::MSWindowsFixedSizeDialogHint); | ||||
#endif | #endif | ||||
} | } | ||||
@@ -107,6 +112,18 @@ public: | |||||
fWindow->setWindowIcon(QIcon::fromTheme("carla", QIcon(":/scalable/carla.svg"))); | fWindow->setWindowIcon(QIcon::fromTheme("carla", QIcon(":/scalable/carla.svg"))); | ||||
fWindow->setWindowTitle(kWindowTitle.buffer()); | fWindow->setWindowTitle(kWindowTitle.buffer()); | ||||
if (const char* const winIdStr = std::getenv("ENGINE_OPTION_FRONTEND_WIN_ID")) | |||||
{ | |||||
if (const long long winId = std::strtoll(winIdStr, nullptr, 16)) | |||||
{ | |||||
#if defined(CARLA_OS_LINUX) && QT_VERSION < QT_VERSION_CHECK(5, 0, 0) | |||||
XSetTransientForHint(QX11Info::display(), static_cast<::Window>(fWindow->winId()), static_cast<::Window>(winId)); | |||||
#else | |||||
(void)winId; | |||||
#endif | |||||
} | |||||
} | |||||
if (showUI || fNeedsShow) | if (showUI || fNeedsShow) | ||||
{ | { | ||||
show(); | show(); | ||||
@@ -124,9 +141,9 @@ public: | |||||
void quit() override | void quit() override | ||||
{ | { | ||||
CARLA_ASSERT(kClient != nullptr); | |||||
CARLA_ASSERT(fApp != nullptr); | |||||
CARLA_ASSERT(fWindow != nullptr); | |||||
CARLA_SAFE_ASSERT_RETURN(kClient != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(fApp != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,); | |||||
carla_debug("CarlaBridgeToolkitQt::quit()"); | carla_debug("CarlaBridgeToolkitQt::quit()"); | ||||
if (fMsgTimer != 0) | if (fMsgTimer != 0) | ||||
@@ -175,16 +192,11 @@ public: | |||||
void resize(const int width, const int height) override | void resize(const int width, const int height) override | ||||
{ | { | ||||
CARLA_ASSERT_INT(width > 0, width); | |||||
CARLA_ASSERT_INT(height > 0, height); | |||||
CARLA_SAFE_ASSERT_RETURN(width > 0,); | |||||
CARLA_SAFE_ASSERT_RETURN(height > 0,); | |||||
carla_debug("CarlaBridgeToolkitQt::resize(%i, %i)", width, height); | carla_debug("CarlaBridgeToolkitQt::resize(%i, %i)", width, height); | ||||
if (width <= 0) | |||||
return; | |||||
if (height <= 0) | |||||
return; | |||||
emit setSizeSafeSignal(width, height); | |||||
emit setSizeSafeSignal(static_cast<uint>(width), static_cast<uint>(height)); | |||||
} | } | ||||
protected: | protected: | ||||
@@ -205,6 +217,7 @@ protected: | |||||
{ | { | ||||
killTimer(fMsgTimer); | killTimer(fMsgTimer); | ||||
fMsgTimer = 0; | fMsgTimer = 0; | ||||
fApp->quit(); | |||||
} | } | ||||
} | } | ||||
@@ -221,13 +234,10 @@ signals: | |||||
void setSizeSafeSignal(int, int); | void setSizeSafeSignal(int, int); | ||||
private slots: | private slots: | ||||
void setSizeSafeSlot(int width, int height) | |||||
void setSizeSafeSlot(uint width, uint height) | |||||
{ | { | ||||
CARLA_ASSERT(kClient != nullptr && ! kClient->isResizable()); | |||||
CARLA_ASSERT(fWindow != nullptr); | |||||
if (kClient == nullptr || fWindow == nullptr) | |||||
return; | |||||
CARLA_SAFE_ASSERT_RETURN(kClient != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,); | |||||
if (kClient->isResizable()) | if (kClient->isResizable()) | ||||
fWindow->resize(width, height); | fWindow->resize(width, height); | ||||
@@ -263,7 +273,7 @@ CARLA_BRIDGE_END_NAMESPACE | |||||
int qInitResources(); | int qInitResources(); | ||||
int qCleanupResources(); | int qCleanupResources(); | ||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) | |||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) | |||||
# include "resources.qt5.cpp" | # include "resources.qt5.cpp" | ||||
#else | #else | ||||
# include "resources.qt4.cpp" | # include "resources.qt4.cpp" | ||||
@@ -61,6 +61,12 @@ LINK_LV2_WINDOWS_FLAGS = $(LINK_FLAGS) -static -mwindows | |||||
BUILD_VST2_X11_FLAGS = $(BUILD_VST2_FLAGS) -DBRIDGE_X11 -DBRIDGE_VST2_X11 $(X11_FLAGS) | BUILD_VST2_X11_FLAGS = $(BUILD_VST2_FLAGS) -DBRIDGE_X11 -DBRIDGE_VST2_X11 $(X11_FLAGS) | ||||
LINK_VST2_X11_FLAGS = $(LINK_FLAGS) $(X11_LIBS) -ldl | LINK_VST2_X11_FLAGS = $(LINK_FLAGS) $(X11_LIBS) -ldl | ||||
ifeq ($(LINUX),true) | |||||
LINK_LV2_GTK2_FLAGS += -lX11 | |||||
LINK_LV2_GTK3_FLAGS += -lX11 | |||||
LINK_LV2_QT4_FLAGS += -lX11 | |||||
endif | |||||
# ---------------------------------------------------------------------------------------------------------------------------- | # ---------------------------------------------------------------------------------------------------------------------------- | ||||
ifeq ($(MACOS_OR_WIN32),true) | ifeq ($(MACOS_OR_WIN32),true) | ||||