diff --git a/.travis.yml b/.travis.yml index 773aed79f6e..fa331f58197 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,7 @@ matrix: - env: TARGET_OS=win64 - os: osx osx_image: xcode8.2 + - env: QT5= - env: QT5=True - env: QT5=True TARGET_OS=win32 - env: QT5=True TARGET_OS=win64 diff --git a/include/ConfigManager.h b/include/ConfigManager.h index 3e5c0578f0b..74cb29c17fc 100644 --- a/include/ConfigManager.h +++ b/include/ConfigManager.h @@ -210,6 +210,7 @@ class EXPORT ConfigManager : public QObject return m_recentlyOpenedProjects; } + static QStringList availabeVstEmbedMethods(); QString vstEmbedMethod() const; // returns true if the working dir (e.g. ~/lmms) exists on disk diff --git a/plugins/VstEffect/VstEffect.cpp b/plugins/VstEffect/VstEffect.cpp index 494613e26df..19d08c805b5 100644 --- a/plugins/VstEffect/VstEffect.cpp +++ b/plugins/VstEffect/VstEffect.cpp @@ -128,10 +128,21 @@ void VstEffect::openPlugin( const QString & _plugin ) PLUGIN_NAME::getIconPixmap( "logo", 24, 24 ), 0 ); QMutexLocker ml( &m_pluginMutex ); Q_UNUSED( ml ); +#if QT_VERSION > 0x050000 m_plugin.reset(new VstPlugin( _plugin )); +#else + { + QSharedPointer newPlugin(new VstPlugin( _plugin )); + std::swap(m_plugin, newPlugin); + } +#endif if( m_plugin->failed() ) { +#if QT_VERSION > 0x050000 m_plugin.reset(nullptr); +#else + m_plugin.clear(); +#endif delete tf; collectErrorForUI( VstPlugin::tr( "The VST plugin %1 could not be loaded." ).arg( _plugin ) ); return; diff --git a/plugins/vst_base/CMakeLists.txt b/plugins/vst_base/CMakeLists.txt index af58ffb1a98..ed956e2181a 100644 --- a/plugins/vst_base/CMakeLists.txt +++ b/plugins/vst_base/CMakeLists.txt @@ -29,7 +29,7 @@ SET(REMOTE_VST_PLUGIN_FILEPATH "RemoteVstPlugin" CACHE STRING "Relative file pat ADD_DEFINITIONS(-DREMOTE_VST_PLUGIN_FILEPATH="${REMOTE_VST_PLUGIN_FILEPATH}") BUILD_PLUGIN(vstbase vst_base.cpp VstPlugin.cpp VstPlugin.h communication.h MOCFILES VstPlugin.h) -IF(LMMS_BUILD_LINUX) +IF(LMMS_BUILD_LINUX AND WANT_QT5) TARGET_LINK_LIBRARIES(vstbase qx11embedcontainer) ENDIF() diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index 3a5eeed006a..f3a7ebc16b7 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -109,6 +109,7 @@ static VstHostLanguages hlang = LanguageEnglish; static bool EMBED = false; static bool EMBED_X11 = false; +static bool EMBED_WIN32 = false; class RemoteVstPlugin; @@ -567,17 +568,6 @@ bool RemoteVstPlugin::processMessage( const message & _m ) init( _m.getString() ); break; -// TODO: Drop Windows hack for Qt 4 -#ifdef LMMS_BUILD_WIN32 - case IdVstPluginWindowInformation: - { - HWND top = FindWindowEx( NULL, NULL, NULL, - _m.getString().c_str() ); - m_window = FindWindowEx( top, NULL, NULL, NULL ); - break; - } -#endif - case IdVstSetTempo: setBPM( _m.getInt() ); break; @@ -1977,13 +1967,6 @@ DWORD WINAPI RemoteVstPlugin::guiEventLoop() while( GetMessage( &msg, NULL, 0, 0 ) > 0 ) { TranslateMessage( &msg ); - - if( msg.message == WM_SYSCOMMAND && msg.wParam == SC_CLOSE ) - { - __plugin->destroyEditor(); - continue; - } - DispatchMessage( &msg ); } @@ -2030,6 +2013,12 @@ LRESULT CALLBACK RemoteVstPlugin::messageWndProc( HWND hwnd, UINT uMsg, break; } } + else if( uMsg == WM_SYSCOMMAND && wParam == SC_CLOSE ) + { + __plugin->destroyEditor(); + return 0; + } + return DefWindowProc( hwnd, uMsg, wParam, lParam ); } @@ -2084,21 +2073,27 @@ int main( int _argc, char * * _argv ) if ( embedMethod == "none" ) { cerr << "Starting detached." << endl; - EMBED = EMBED_X11 = false; + EMBED = EMBED_X11 = EMBED_WIN32 = false; + } + else if ( embedMethod == "win32" ) + { + cerr << "Starting using Win32-native embedding." << endl; + EMBED = EMBED_WIN32 = true; EMBED_X11= false; } else if ( embedMethod == "qt" ) { cerr << "Starting using Qt-native embedding." << endl; - EMBED = true; EMBED_X11 = false; + EMBED = true; EMBED_X11 = EMBED_WIN32 = false; } else if ( embedMethod == "xembed" ) { cerr << "Starting using X11Embed protocol." << endl; - EMBED = true; EMBED_X11 = true; + EMBED = EMBED_X11 = true; EMBED_WIN32 = false; } else { cerr << "Unknown embed method " << embedMethod << ". Starting detached instead." << endl; + EMBED = EMBED_X11 = EMBED_WIN32 = false; } } diff --git a/plugins/vst_base/VstPlugin.cpp b/plugins/vst_base/VstPlugin.cpp index 8b514770809..cada57293c3 100644 --- a/plugins/vst_base/VstPlugin.cpp +++ b/plugins/vst_base/VstPlugin.cpp @@ -51,6 +51,7 @@ #ifdef LMMS_BUILD_WIN32 # include +# include #endif #include "ConfigManager.h" @@ -659,6 +660,7 @@ void VstPlugin::createUI( QWidget * parent, bool isEffect ) m_pluginSubWindow = new vstSubWin( gui->mainWindow()->workspace() ); auto sw = m_pluginSubWindow.data(); +#if QT_VERSION >= 0x050100 if (m_embedMethod == "qt" ) { QWindow* vw = QWindow::fromWinId(m_pluginWindowID); @@ -667,17 +669,49 @@ void VstPlugin::createUI( QWidget * parent, bool isEffect ) // TODO: Synchronize show // Tell remote that it is embedded // Wait for remote reply - } + } else +#endif + +#ifdef LMMS_BUILD_WIN32 + if (m_embedMethod == "win32" ) + { + QWidget * helper = new QWidget; + QHBoxLayout * l = new QHBoxLayout( helper ); + QWidget * target = new QWidget( helper ); + l->setSpacing( 0 ); + l->setMargin( 0 ); + l->addWidget( target ); + + // we've to call that for making sure, Qt created the windows + helper->winId(); + HWND targetHandle = (HWND)target->winId(); + HWND pluginHandle = (HWND)(intptr_t)m_pluginWindowID; + + DWORD style = GetWindowLong(pluginHandle, GWL_STYLE); + style = style & ~(WS_POPUP); + style = style | WS_CHILD; + SetWindowLong(pluginHandle, GWL_STYLE, style); + SetParent(pluginHandle, targetHandle); + + DWORD threadId = GetWindowThreadProcessId(pluginHandle, NULL); + DWORD currentThreadId = GetCurrentThreadId(); + AttachThreadInput(currentThreadId, threadId, true); + + container = helper; + RemotePlugin::showUI(); + + } else +#endif + #ifdef LMMS_BUILD_LINUX - else if (m_embedMethod == "xembed" ) + if (m_embedMethod == "xembed" ) { QX11EmbedContainer * embedContainer = new QX11EmbedContainer( sw ); connect(embedContainer, SIGNAL(clientIsEmbedded()), this, SLOT(handleClientEmbed())); embedContainer->embedClient( m_pluginWindowID ); container = embedContainer; - } + } else #endif - else { qCritical() << "Unknown embed method" << m_embedMethod; delete m_pluginSubWindow; diff --git a/plugins/vst_base/communication.h b/plugins/vst_base/communication.h index 3e85007e711..bacf43c1edc 100644 --- a/plugins/vst_base/communication.h +++ b/plugins/vst_base/communication.h @@ -57,8 +57,6 @@ enum VstRemoteMessageIDs { // vstPlugin -> remoteVstPlugin IdVstLoadPlugin = IdUserBase, - // TODO: Drop IdVstPluginWindowInformation, Windows hack for Qt 4 - IdVstPluginWindowInformation, IdVstClosePlugin, IdVstSetTempo, IdVstSetLanguage, diff --git a/src/core/ConfigManager.cpp b/src/core/ConfigManager.cpp index 734c39c1f0f..985d5e08cd7 100644 --- a/src/core/ConfigManager.cpp +++ b/src/core/ConfigManager.cpp @@ -35,10 +35,6 @@ #include "lmmsversion.h" -#ifdef LMMS_BUILD_LINUX -#include -#endif - static inline QString ensureTrailingSlash( const QString & s ) { if( ! s.isEmpty() && !s.endsWith('/') && !s.endsWith('\\') ) @@ -190,16 +186,37 @@ QString ConfigManager::defaultVersion() const return LMMS_VERSION; } -QString ConfigManager::vstEmbedMethod() const +QStringList ConfigManager::availabeVstEmbedMethods() { - QString defaultMethod = "qt"; + QStringList methods; + methods.append("none"); +#if QT_VERSION >= 0x050100 + methods.append("qt"); +#endif +#ifdef LMMS_BUILD_WIN32 + methods.append("win32"); +#endif #ifdef LMMS_BUILD_LINUX - if (QX11Info::isPlatformX11()) { - defaultMethod = "xembed"; +#if QT_VERSION >= 0x050000 + if (static_cast(QApplication::instance())-> + platformName() == "xcb") +#else + if (qgetenv("QT_QPA_PLATFORM").isNull() + || qgetenv("QT_QPA_PLATFORM") == "xcb") +#endif + { + methods.append("xembed"); } #endif + return methods; +} - return value( "ui", "vstembedmethod", defaultMethod ); +QString ConfigManager::vstEmbedMethod() const +{ + QStringList methods = availabeVstEmbedMethods(); + QString defaultMethod = *(methods.end() - 1); + QString currentMethod = value( "ui", "vstembedmethod", defaultMethod ); + return methods.contains(currentMethod) ? currentMethod : defaultMethod; } bool ConfigManager::hasWorkingDir() const diff --git a/src/gui/SetupDialog.cpp b/src/gui/SetupDialog.cpp index 0d5f2c454a5..f88e1dcf6ce 100644 --- a/src/gui/SetupDialog.cpp +++ b/src/gui/SetupDialog.cpp @@ -67,10 +67,6 @@ #include "MidiApple.h" #include "MidiDummy.h" -#ifdef LMMS_BUILD_LINUX -#include -#endif - inline void labelWidget( QWidget * _w, const QString & _txt ) { QLabel * title = new QLabel( _txt, _w ); @@ -342,13 +338,21 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) : embed_tw->setFixedHeight( 48 ); m_vstEmbedComboBox = new QComboBox( embed_tw ); m_vstEmbedComboBox->move( XDelta, YDelta ); + + QStringList embedMethods = ConfigManager::availabeVstEmbedMethods(); m_vstEmbedComboBox->addItem( tr( "No embedding" ), "none" ); - m_vstEmbedComboBox->addItem( tr( "Embed using Qt API" ), "qt" ); -#ifdef LMMS_BUILD_LINUX - if ( QX11Info::isPlatformX11() ) { + if( embedMethods.contains("qt") ) + { + m_vstEmbedComboBox->addItem( tr( "Embed using Qt API" ), "qt" ); + } + if( embedMethods.contains("win32") ) + { + m_vstEmbedComboBox->addItem( tr( "Embed using native Win32 API" ), "win32" ); + } + if( embedMethods.contains("xembed") ) + { m_vstEmbedComboBox->addItem( tr( "Embed using XEmbed protocol" ), "xembed" ); } -#endif m_vstEmbedComboBox->setCurrentIndex( m_vstEmbedComboBox->findData( m_vstEmbedMethod ) ); TabWidget * lang_tw = new TabWidget( tr( "LANGUAGE" ), general ); @@ -1077,7 +1081,11 @@ void SetupDialog::accept() QString::number( m_disableAutoQuit ) ); ConfigManager::inst()->setValue( "app", "language", m_lang ); ConfigManager::inst()->setValue( "ui", "vstembedmethod", +#if QT_VERSION >= 0x050000 m_vstEmbedComboBox->currentData().toString() ); +#else + m_vstEmbedComboBox->itemData(m_vstEmbedComboBox->currentIndex()).toString() ); +#endif ConfigManager::inst()->setWorkingDir(QDir::fromNativeSeparators(m_workingDir));