Use window instead of embedder application

This commit is contained in:
Javier Serrano Polo
2017-04-01 01:11:05 +02:00
committed by Lukas W
parent 12f6ea5566
commit f87f3638e1
10 changed files with 115 additions and 610 deletions

View File

@@ -1217,7 +1217,7 @@ RemotePluginClient::RemotePluginClient( const char * socketPath ) :
if( waitForMessage( IdBufferSizeInformation ).id
!= IdBufferSizeInformation )
{
fprintf( stderr, "Could not get buffer size information.\n" );
fprintf( stderr, "Could not get buffer size information\n" );
}
sendMessage( IdHostInfoGotten );
}

View File

@@ -219,7 +219,9 @@ VstEffectControlDialog::VstEffectControlDialog( VstEffectControls * _ctl ) :
l->addItem( new QSpacerItem( newSize - 20, 30, QSizePolicy::Fixed,
QSizePolicy::Fixed ), 1, 0 );
l->addWidget( resize, 2, 0, 1, 1, Qt::AlignCenter );
#if QT_VERSION < 0x050000
l->addWidget( m_pluginWidget, 3, 0, 1, 1, Qt::AlignCenter );
#endif
l->setRowStretch( 5, 1 );
l->setColumnStretch( 1, 1 );
@@ -273,11 +275,11 @@ void VstEffectControlDialog::togglePluginUI( bool checked )
{
if( checked )
{
m_plugin->showUI();
m_plugin->showEditor( NULL, true );
}
else
{
m_plugin->hideUI();
m_plugin->hideEditor();
}
}
}

View File

@@ -261,7 +261,7 @@ void vestigeInstrument::loadFile( const QString & _file )
return;
}
m_plugin->showUI();
m_plugin->showEditor( NULL, false );
if( set_ch_name )
{
@@ -735,7 +735,7 @@ void VestigeInstrumentView::toggleGUI( void )
{
return;
}
m_vi->m_plugin->toggleUI();
m_vi->m_plugin->toggleEditor();
}

View File

@@ -67,18 +67,6 @@ ADD_CUSTOM_COMMAND(
OUTPUTS ../RemoteVstPlugin
)
IF(QT5)
QT5_WRAP_CPP(embed-window_MOC_out EmbedderApplication.h)
ELSE()
QT4_WRAP_CPP(embed-window_MOC_out EmbedderApplication.h)
ENDIF()
ADD_EXECUTABLE(embed-window embed-window.cpp ${embed-window_MOC_out})
TARGET_LINK_LIBRARIES(embed-window ${QT_LIBRARIES})
IF(NOT QT5)
TARGET_LINK_LIBRARIES(embed-window ${X11_X11_LIB})
ENDIF()
SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ../RemoteVstPlugin.exe.so)
INSTALL(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/../RemoteVstPlugin" "${CMAKE_CURRENT_BINARY_DIR}/../RemoteVstPlugin.exe.so" DESTINATION "${PLUGIN_DIR}")
ENDIF(LMMS_BUILD_LINUX AND NOT WANT_VST_NOWINE)

View File

@@ -1,82 +0,0 @@
/*
* EmbedderApplication.h - simple application that embeds an external window
*
* Copyright (c) 2016 Javier Serrano Polo <javier@jasp.net>
*
* This file is part of LMMS - http://lmms.io
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#ifndef EMBEDDER_APPLICATION_H
#define EMBEDDER_APPLICATION_H
#include <QApplication>
#include <QMainWindow>
#if QT_VERSION < 0x050000
class QX11EmbedContainer;
#endif
class MainWindow : public QMainWindow
{
public:
void init( const char * title, unsigned int windowId, int width,
int height );
protected:
virtual void closeEvent( QCloseEvent *event );
private:
#if QT_VERSION < 0x050000
QX11EmbedContainer * m_window;
#else
QWindow * m_window;
#endif
} ;
class EmbedderApplication : public QApplication
{
Q_OBJECT
public:
EmbedderApplication( int & argc, char * * argv );
virtual ~EmbedderApplication();
void init( const char * title, unsigned int windowId, int width,
int height );
private:
MainWindow m_mainWindow;
private slots:
void applicationReady();
void readCommand();
} ;
#endif

View File

@@ -52,7 +52,6 @@
#include <sched.h>
#endif
#include <sys/wait.h>
#include <wine/exception.h>
#endif
@@ -67,7 +66,6 @@
#endif
#include <cinttypes>
#include <vector>
#include <string>
@@ -108,12 +106,6 @@ struct ERect
#include <sys/shm.h>
#endif
#define EMBEDDER_NAME "embed-window"
#ifdef LMMS_BUILD_LINUX
#define USE_LINUX_EMBEDDER
#endif
static VstHostLanguages hlang = LanguageEnglish;
@@ -123,10 +115,6 @@ RemoteVstPlugin * __plugin = NULL;
DWORD __GuiThreadID = 0;
#ifdef USE_LINUX_EMBEDDER
static char * s_embedderPath;
#endif
class RemoteVstPlugin : public RemotePluginClient
@@ -312,13 +300,6 @@ private:
intptr_t m_windowID;
int m_windowWidth;
int m_windowHeight;
#ifdef USE_LINUX_EMBEDDER
pid_t m_embedderPid;
int m_embedderStdin;
int m_embedderStdout;
#else
PROCESS_INFORMATION m_processInfo;
#endif
bool m_initialized;
bool m_registeredWindowClass;
@@ -478,47 +459,11 @@ RemoteVstPlugin::~RemoteVstPlugin()
#ifdef USE_LINUX_EMBEDDER
static void checkExitStatus( int status )
{
if( WIFEXITED( status ) && WEXITSTATUS( status ) == EXIT_SUCCESS )
{
return;
}
fprintf( stderr, "Child process did not exit properly\n" );
}
#endif
bool RemoteVstPlugin::processMessage( const message & _m )
{
switch( _m.id )
{
case IdShowUI:
#ifdef USE_LINUX_EMBEDDER
if( m_window )
{
int status;
pid_t pid = waitpid( m_embedderPid, &status,
WNOHANG );
switch( pid )
{
case -1:
perror( "waitpid" );
break;
case 0:
break;
default:
checkExitStatus( status );
m_embedderPid = -1;
destroyEditor();
}
}
#endif
initEditor();
break;
@@ -527,39 +472,6 @@ bool RemoteVstPlugin::processMessage( const message & _m )
break;
case IdToggleUI:
#ifdef USE_LINUX_EMBEDDER
if( m_window )
{
bool restart = false;
int status;
pid_t pid = waitpid( m_embedderPid, &status,
WNOHANG );
switch( pid )
{
case -1:
perror( "waitpid" );
break;
case 0:
break;
default:
checkExitStatus( status );
m_embedderPid = -1;
restart = true;
}
destroyEditor();
if( !restart )
{
break;
}
}
initEditor();
break;
#else
// Temporary implementation, not using an embedder
if( m_window )
{
destroyEditor();
@@ -569,12 +481,22 @@ bool RemoteVstPlugin::processMessage( const message & _m )
initEditor();
}
break;
#endif
case IdVstLoadPlugin:
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;
@@ -712,20 +634,6 @@ void RemoteVstPlugin::init( const std::string & _plugin_file )
#ifdef USE_LINUX_EMBEDDER
static void assert_dup2( int oldfd, int newfd )
{
if( dup2( oldfd, newfd ) == -1 )
{
perror( "dup2" );
exit( EXIT_FAILURE );
}
}
#endif
static void close_check( int fd )
{
if( close( fd ) )
@@ -775,11 +683,7 @@ void RemoteVstPlugin::initEditor()
}
m_window = CreateWindowEx( 0, "LVSL", m_shortName.c_str(),
#if QT_VERSION < 0x050000 && defined( LMMS_BUILD_LINUX )
WS_POPUP | WS_SYSMENU | WS_BORDER,
#else
( WS_OVERLAPPEDWINDOW | WS_THICKFRAME ) & ~WS_MAXIMIZEBOX,
#endif
0, 0, 10, 10, NULL, NULL, hInst, NULL );
if( m_window == NULL )
{
@@ -787,6 +691,7 @@ void RemoteVstPlugin::initEditor()
return;
}
pluginDispatch( effEditOpen, 0, 0, m_window );
ERect * er;
@@ -795,159 +700,17 @@ void RemoteVstPlugin::initEditor()
m_windowWidth = er->right - er->left;
m_windowHeight = er->bottom - er->top;
#ifdef USE_LINUX_EMBEDDER
m_windowID = (intptr_t) GetProp( m_window, "__wine_x11_whole_window" );
m_embedderPid = -1;
m_embedderStdin = -1;
m_embedderStdout = -1;
int infd[2];
int outfd[2];
if( pipe( infd ) )
{
perror( "pipe" );
destroyEditor();
return;
}
if( pipe( outfd ) )
{
perror( "pipe" );
close_check( infd[0] );
close_check( infd[1] );
destroyEditor();
return;
}
m_embedderPid = fork();
switch ( m_embedderPid )
{
case -1:
perror( "fork" );
close_check( infd[0] );
close_check( infd[1] );
close_check( outfd[0] );
close_check( outfd[1] );
destroyEditor();
return;
case 0:
assert_dup2( infd[0], STDIN_FILENO );
assert_dup2( outfd[1], STDOUT_FILENO );
close_check( infd[0] );
close_check( infd[1] );
close_check( outfd[0] );
close_check( outfd[1] );
char * widStr = new char[2 * sizeof m_windowID + 1];
sprintf( widStr, "%" PRIxPTR, m_windowID );
char * widthStr
= new char[2 * sizeof m_windowWidth + 1];
sprintf( widthStr, "%x", m_windowWidth );
char * heightStr
= new char[2 * sizeof m_windowHeight + 1];
sprintf( heightStr, "%x", m_windowHeight );
execl( s_embedderPath, s_embedderPath,
m_shortName.c_str(), widStr, widthStr,
heightStr, (char *) NULL );
perror( "execl" );
exit( EXIT_FAILURE );
}
close_check( infd[0] );
close_check( outfd[1] );
m_embedderStdin = infd[1];
m_embedderStdout = outfd[0];
#else
// Pending: Check that Qt 5 embedding works on Windows
// Should wait until Qt 4 support is dropped
// TODO: Set to native window ID
m_windowID = 1;
const char * name = m_shortName.c_str();
char * commandLine = new char[sizeof EMBEDDER_NAME " " + strlen( name )
+ 1 + 2 * sizeof m_windowID + 1 + 2 * sizeof m_windowWidth + 1
+ 2 * sizeof m_windowHeight];
sprintf( commandLine, EMBEDDER_NAME " %s %" PRIxPTR " %x %x", name,
m_windowID, m_windowWidth, m_windowHeight );
// Set up the pipes
/*
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
if ( !CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0) )
ErrorExit(TEXT("StdoutRd CreatePipe"));
if ( !SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) )
ErrorExit(TEXT("Stdout SetHandleInformation"));
if (! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0))
ErrorExit(TEXT("Stdin CreatePipe"));
if ( ! SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) )
ErrorExit(TEXT("Stdin SetHandleInformation"));
*/
STARTUPINFO si;
ZeroMemory( &si, sizeof si );
si.cb = sizeof si;
// si.hStdOutput = g_hChildStd_OUT_Wr;
// si.hStdInput = g_hChildStd_IN_Rd;
// si.dwFlags |= STARTF_USESTDHANDLES;
ZeroMemory( &m_processInfo, sizeof m_processInfo );
// Pending: Create new process when the embedder is ready
// bool ok = CreateProcess( NULL, commandLine, NULL, NULL, TRUE, 0, NULL,
// NULL, &si, &m_processInfo );
delete[] commandLine;
/*
if ( !ok )
{
fprintf( stderr, "CreateProcess failed (%d)\n",
GetLastError() );
destroyEditor();
return;
}
*/
// close unused pipe handles if possible
// if ( ! CloseHandle(g_hChildStd_IN_Rd) ) error
#endif
SetWindowPos( m_window, 0, 0, 0, m_windowWidth + 8,
m_windowHeight + 26, SWP_NOACTIVATE |
SWP_NOMOVE | SWP_NOZORDER );
pluginDispatch( effEditTop );
#ifdef USE_LINUX_EMBEDDER
char c;
if( ::read( m_embedderStdout, &c, 1 ) != 1 )
{
fprintf( stderr, "Could not read from embedder\n" );
destroyEditor();
return;
}
#else
// bSuccess = ReadFile(g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL);
// if ( ! bSuccess || dwRead == 0 ) break;
#endif
ShowWindow( m_window, SW_SHOWNORMAL );
#ifdef USE_LINUX_EMBEDDER
if( ::write( m_embedderStdin, "", 1 ) != 1 )
{
fprintf( stderr, "Could not write to embedder\n" );
destroyEditor();
return;
}
#ifdef LMMS_BUILD_LINUX
m_windowID = (intptr_t) GetProp( m_window, "__wine_x11_whole_window" );
#else
// bSuccess = WriteFile(g_hChildStd_IN_Wr, chBuf, dwRead, &dwWritten, NULL);
// if ( ! bSuccess ) break;
// 64-bit versions of Windows use 32-bit handles for interoperability
m_windowID = (intptr_t) m_window;
#endif
}
@@ -961,32 +724,6 @@ void RemoteVstPlugin::destroyEditor()
return;
}
#ifdef USE_LINUX_EMBEDDER
close_check( m_embedderStdin );
close_check( m_embedderStdout );
if( m_embedderPid != -1 )
{
int status;
pid_t pid = waitpid( m_embedderPid, &status, 0 );
if( pid == -1 )
{
perror( "waitpid" );
}
else
{
checkExitStatus( status );
}
}
#else
// Close pipes
// Wait until child process exits.
// WaitForSingleObject( m_processInfo.hProcess, INFINITE );
// Close process and thread handles.
// CloseHandle( m_processInfo.hProcess );
// CloseHandle( m_processInfo.hThread );
#endif
pluginDispatch( effEditClose );
// Destroying the window takes some time in Wine 1.8.5
DestroyWindow( m_window );
@@ -2105,13 +1842,6 @@ DWORD WINAPI RemoteVstPlugin::guiEventLoop( LPVOID _param )
while( quit == false && GetMessage( &msg, NULL, 0, 0 ) )
{
TranslateMessage( &msg );
if( msg.message == WM_SYSCOMMAND && msg.wParam == SC_CLOSE )
{
_this->destroyEditor();
continue;
}
DispatchMessage( &msg );
if( msg.message == WM_TIMER && _this->isInitialized() )
@@ -2151,63 +1881,6 @@ DWORD WINAPI RemoteVstPlugin::guiEventLoop( LPVOID _param )
#ifdef USE_LINUX_EMBEDDER
static char * findMyPath( const char * argv0 )
{
// TODO: escape ' or use execlp
std::string command = "winepath '";
command += argv0;
command += '\'';
FILE * stream = popen( command.c_str(), "r" );
if( !stream )
{
perror( "popen" );
return NULL;
}
char * unixPath = (char *) malloc( BUFSIZ );
char * s = fgets( unixPath, BUFSIZ, stream );
if( !s )
{
perror( "fgets" );
free( unixPath );
return NULL;
}
if( strlen( s ) == BUFSIZ - 1 )
{
//TODO: Read a longer line
fprintf( stderr, "findMyPath: Buffer too small\n" );
}
char * eol = strchr( unixPath, '\n' );
if( eol )
{
*eol = '\0';
}
if( pclose( stream ) == -1 )
{
perror( "pclose" );
}
return unixPath;
}
static char * findEmbedderPath( const char * argv0 )
{
char * myPath = findMyPath( argv0 );
const char * slash = myPath ? strrchr( myPath, '/' ) : NULL;
size_t prefixLength = slash ? slash - myPath + 1 : 0;
char * path = new char[prefixLength + sizeof EMBEDDER_NAME];
memcpy( path, myPath, prefixLength );
memcpy( path + prefixLength, EMBEDDER_NAME, sizeof EMBEDDER_NAME );
free( myPath );
return path;
}
#endif
int main( int _argc, char * * _argv )
{
#ifdef SYNC_WITH_SHM_FIFO
@@ -2245,10 +1918,6 @@ int main( int _argc, char * * _argv )
}
#endif
#ifdef USE_LINUX_EMBEDDER
s_embedderPath = findEmbedderPath( _argv[0] );
#endif
// constructor automatically will process messages until it receives
// a IdVstLoadPlugin message and processes it
#ifdef SYNC_WITH_SHM_FIFO
@@ -2273,10 +1942,6 @@ int main( int _argc, char * * _argv )
delete __plugin;
#ifdef USE_LINUX_EMBEDDER
delete[] s_embedderPath;
#endif
#ifdef LMMS_BUILD_WIN32
#ifndef __WINPTHREADS_VERSION

View File

@@ -31,6 +31,16 @@
#include <QCloseEvent>
#include <QMdiArea>
#include <QMdiSubWindow>
#ifdef LMMS_BUILD_LINUX
#if QT_VERSION < 0x050000
#include <QX11EmbedContainer>
#include <QX11Info>
#else
#include <QWindow>
#endif
#else
#include <QLayout>
#endif
#include <QDomDocument>
#ifdef LMMS_BUILD_WIN32
@@ -46,6 +56,33 @@
#include "FileDialog.h"
#if QT_VERSION < 0x050000
class vstSubWin : public QMdiSubWindow
{
public:
vstSubWin( QWidget * _parent ) :
QMdiSubWindow( _parent )
{
setAttribute( Qt::WA_DeleteOnClose, false );
}
virtual ~vstSubWin()
{
}
virtual void closeEvent( QCloseEvent * e )
{
// ignore close-events - for some reason otherwise the VST GUI
// remains hidden when re-opening
hide();
e->ignore();
}
} ;
#endif
VstPlugin::VstPlugin( const QString & _plugin ) :
RemotePlugin(),
JournallingObject(),
@@ -168,15 +205,49 @@ void VstPlugin::showEditor( QWidget * _parent, bool isEffect )
return;
}
#if QT_VERSION < 0x050000
m_pluginWidget = new QWidget( _parent );
m_pluginWidget->setFixedSize( m_pluginGeometry );
m_pluginWidget->setWindowTitle( name() );
if( _parent == NULL )
{
vstSubWin * sw = new vstSubWin(
gui->mainWindow()->workspace() );
if( isEffect )
{
sw->setAttribute( Qt::WA_TranslucentBackground );
sw->setWindowFlags( Qt::FramelessWindowHint );
sw->setWidget( m_pluginWidget );
QX11EmbedContainer * xe = new QX11EmbedContainer( sw );
xe->embedClient( m_pluginWindowID );
xe->setFixedSize( m_pluginGeometry );
xe->show();
}
else
{
sw->setWindowFlags( Qt::WindowCloseButtonHint );
sw->setWidget( m_pluginWidget );
QX11EmbedContainer * xe = new QX11EmbedContainer( sw );
xe->embedClient( m_pluginWindowID );
xe->setFixedSize( m_pluginGeometry );
xe->move( 4, 24 );
xe->show();
}
}
#else
QWindow * window = QWindow::fromWinId( m_pluginWindowID );
m_pluginWidget = QWidget::createWindowContainer( window, _parent,
Qt::Window );
m_pluginWidget->setFixedSize( m_pluginGeometry );
m_pluginWidget->setWindowTitle( name() );
// TODO: Synchronize show
// Tell remote that it is embedded
// Wait for remote reply
#endif
#endif
if( m_pluginWidget )
{
m_pluginWidget->show();
}
m_pluginWidget->show();
}
@@ -184,7 +255,6 @@ void VstPlugin::showEditor( QWidget * _parent, bool isEffect )
void VstPlugin::hideEditor()
{
//TODO: Drop m_pluginWidget, showEditor(), hideEditor()
QWidget * w = pluginWidget();
if( w )
{
@@ -195,6 +265,18 @@ void VstPlugin::hideEditor()
void VstPlugin::toggleEditor()
{
QWidget * w = m_pluginWidget;
if( w )
{
w->setVisible( !w->isVisible() );
}
}
void VstPlugin::loadSettings( const QDomElement & _this )
{
if( pluginWidget() != NULL )
@@ -240,7 +322,6 @@ void VstPlugin::loadSettings( const QDomElement & _this )
void VstPlugin::saveSettings( QDomDocument & _doc, QDomElement & _this )
{
//TODO: Replace with m_plugin->isVisible(), add IdIsUIVisble message
if( pluginWidget() != NULL )
{
_this.setAttribute( "guivisible", pluginWidget()->isVisible() );

View File

@@ -54,6 +54,7 @@ public:
void showEditor( QWidget * _parent = NULL, bool isEffect = false );
void hideEditor();
void toggleEditor();
inline const QString & name() const
{
@@ -93,6 +94,7 @@ public:
inline QWidget * pluginWidget( bool _top_widget = true )
{
#if QT_VERSION < 0x050000
if( _top_widget && m_pluginWidget )
{
if( m_pluginWidget->parentWidget() )
@@ -100,6 +102,7 @@ public:
return m_pluginWidget->parentWidget();
}
}
#endif
return m_pluginWidget;
}

View File

@@ -56,6 +56,8 @@ enum VstRemoteMessageIDs
{
// vstPlugin -> remoteVstPlugin
IdVstLoadPlugin = IdUserBase,
// TODO: Drop IdVstPluginWindowInformation, Windows hack for Qt 4
IdVstPluginWindowInformation,
IdVstClosePlugin,
IdVstSetTempo,
IdVstSetLanguage,
@@ -72,9 +74,6 @@ enum VstRemoteMessageIDs
// remoteVstPlugin -> vstPlugin
IdVstFailedLoadingPlugin,
IdVstBadDllFormat,
// Window ID and geometry are only useful if external windows can be
// embedded in LMMS, which is not the case in Qt 5 because there are
// glitches. If Qt is not fixed, then drop these messages.
IdVstPluginWindowID,
IdVstPluginEditorGeometry,
IdVstPluginName,

View File

@@ -1,151 +0,0 @@
/*
* embed-window.cpp - simple application that embeds an external window
*
* Copyright (c) 2016 Javier Serrano Polo <javier@jasp.net>
*
* This file is part of LMMS - http://lmms.io
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#include "EmbedderApplication.h"
#include <QSocketNotifier>
#include <QTimer>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#if QT_VERSION < 0x050000
#include <QX11EmbedContainer>
#include <QX11Info>
#include <X11/Xlib.h>
#else
#include <QWindow>
#endif
void MainWindow::init( const char * title, unsigned int windowId, int width,
int height )
{
setWindowTitle( title );
#if QT_VERSION < 0x050000
m_window = new QX11EmbedContainer( this );
QX11EmbedContainer * container = m_window;
container->embedClient( windowId );
#else
m_window = QWindow::fromWinId( windowId );
QWidget * container = QWidget::createWindowContainer( m_window, this );
#endif
container->setFixedSize( width, height );
container->show();
setFixedSize( width, height );
}
void MainWindow::closeEvent( QCloseEvent *event )
{
hide();
#if QT_VERSION < 0x050000
XUnmapWindow( QX11Info::display(), m_window->clientWinId() );
m_window->discardClient();
#else
m_window->setParent( 0 );
#endif
QMainWindow::closeEvent( event );
}
EmbedderApplication::EmbedderApplication( int & argc, char * * argv ) :
QApplication( argc, argv )
{
QSocketNotifier * notifier = new QSocketNotifier( STDIN_FILENO,
QSocketNotifier::Read );
connect( notifier, SIGNAL( activated( int ) ), SLOT( readCommand() ) );
}
EmbedderApplication::~EmbedderApplication()
{
}
void EmbedderApplication::init( const char * title, unsigned int windowId,
int width, int height )
{
m_mainWindow.init( title, windowId, width, height );
}
void EmbedderApplication::applicationReady()
{
putchar( 0 );
fflush( stdout );
}
void EmbedderApplication::readCommand()
{
int c = getchar();
if( c == EOF )
{
m_mainWindow.close();
quit();
return;
}
m_mainWindow.show();
}
int main( int argc, char * * argv )
{
if( argc < 5 )
{
fputs( "Missing arguments\n", stderr );
return EXIT_FAILURE;
}
EmbedderApplication * app = new EmbedderApplication( argc, argv );
const char * title = argv[1];
unsigned int windowId = strtol( argv[2], NULL, 16 );
int width = strtol( argv[3], NULL, 16 );
int height = strtol( argv[4], NULL, 16 );
app->init( title, windowId, width, height );
QTimer::singleShot( 0, app, SLOT( applicationReady() ) );
int ret = app->exec();
delete app;
return ret;
}