@@ -20,6 +20,10 @@ | |||
#include <gtk/gtk.h> | |||
#ifdef CARLA_OS_LINUX | |||
# include <gdk/gdkx.h> | |||
#endif | |||
CARLA_BRIDGE_START_NAMESPACE | |||
// ------------------------------------------------------------------------- | |||
@@ -47,13 +51,13 @@ public: | |||
~CarlaBridgeToolkitGtk() override | |||
{ | |||
CARLA_ASSERT(fWindow == nullptr); | |||
CARLA_SAFE_ASSERT(fWindow == nullptr); | |||
carla_debug("CarlaBridgeToolkitGtk::~CarlaBridgeToolkitGtk()"); | |||
} | |||
void init() override | |||
{ | |||
CARLA_ASSERT(fWindow == nullptr); | |||
CARLA_SAFE_ASSERT_RETURN(fWindow == nullptr,); | |||
carla_debug("CarlaBridgeToolkitGtk::init()"); | |||
gtk_init(&gargc, &gargv); | |||
@@ -65,8 +69,8 @@ public: | |||
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)); | |||
GtkWidget* const widget((GtkWidget*)kClient->getWidget()); | |||
@@ -76,6 +80,33 @@ public: | |||
gtk_window_set_resizable(GTK_WINDOW(fWindow), kClient->isResizable()); | |||
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) | |||
{ | |||
show(); | |||
@@ -101,8 +132,7 @@ public: | |||
gtk_widget_destroy(fWindow); | |||
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 | |||
{ | |||
CARLA_ASSERT(fWindow != nullptr); | |||
CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,); | |||
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(); | |||
return kClient->oscIdle(); | |||
if (! kClient->oscIdle()) | |||
{ | |||
gtk_main_quit_if_needed(); | |||
return false; | |||
} | |||
return true; | |||
} | |||
// --------------------------------------------------------------------- | |||
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) | |||
{ | |||
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) | |||
@@ -72,6 +72,12 @@ public: | |||
CARLA_SAFE_ASSERT_RETURN(fUI != nullptr,); | |||
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) | |||
fUI->show(); | |||
@@ -22,7 +22,7 @@ | |||
#include <QtCore/QThread> | |||
#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/QMainWindow> | |||
#else | |||
@@ -30,6 +30,11 @@ | |||
# include <QtGui/QMainWindow> | |||
#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 | |||
// ------------------------------------------------------------------------- | |||
@@ -61,17 +66,17 @@ public: | |||
~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()"); | |||
} | |||
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()"); | |||
fApp = new QApplication(qargc, qargv); | |||
@@ -83,9 +88,9 @@ public: | |||
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)); | |||
QWidget* const widget((QWidget*)kClient->getWidget()); | |||
@@ -99,7 +104,7 @@ public: | |||
if (! kClient->isResizable()) | |||
{ | |||
fWindow->setFixedSize(fWindow->width(), fWindow->height()); | |||
#ifdef Q_OS_WIN | |||
#ifdef CARLA_OS_WIN | |||
fWindow->setWindowFlags(fWindow->windowFlags() | Qt::MSWindowsFixedSizeDialogHint); | |||
#endif | |||
} | |||
@@ -107,6 +112,18 @@ public: | |||
fWindow->setWindowIcon(QIcon::fromTheme("carla", QIcon(":/scalable/carla.svg"))); | |||
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) | |||
{ | |||
show(); | |||
@@ -124,9 +141,9 @@ public: | |||
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()"); | |||
if (fMsgTimer != 0) | |||
@@ -175,16 +192,11 @@ public: | |||
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); | |||
if (width <= 0) | |||
return; | |||
if (height <= 0) | |||
return; | |||
emit setSizeSafeSignal(width, height); | |||
emit setSizeSafeSignal(static_cast<uint>(width), static_cast<uint>(height)); | |||
} | |||
protected: | |||
@@ -205,6 +217,7 @@ protected: | |||
{ | |||
killTimer(fMsgTimer); | |||
fMsgTimer = 0; | |||
fApp->quit(); | |||
} | |||
} | |||
@@ -221,13 +234,10 @@ signals: | |||
void setSizeSafeSignal(int, int); | |||
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()) | |||
fWindow->resize(width, height); | |||
@@ -263,7 +273,7 @@ CARLA_BRIDGE_END_NAMESPACE | |||
int qInitResources(); | |||
int qCleanupResources(); | |||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) | |||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) | |||
# include "resources.qt5.cpp" | |||
#else | |||
# 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) | |||
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) | |||