diff options
author | Jan-Marek Glogowski <glogow@fbihome.de> | 2017-10-27 11:27:31 +0200 |
---|---|---|
committer | Thorsten Behrens <Thorsten.Behrens@CIB.de> | 2017-11-06 12:05:31 +0100 |
commit | c33b45c7e14bf47b857630ce05d38a09ffc7e886 (patch) | |
tree | d50bfca09f032d9b8bf6f9714b95bd977cfd6e82 /vcl | |
parent | 88945965d55192b3c1b3b62227d3e48f0bfd8da2 (diff) |
KF5 correctly initialize QApplication
This turned out more tricky then expected. Originally the
KAboutData was assigned to a non-existing QApplication object.
Somehow this was prevending the later crashes, if the QApplication
was initialized before KAboutData and we were creating QWidgets.
The problem turned out to be the referenced arguments to
QApplication. While we already passed the command arguments from
allocated / heap memory, the argc argument was just the local
stack variable!
The simple fix is to allocate an int to pass to QApplication and
the crashes are gone when assigning KAboutData after QApplication.
Also removes some Qt initialization warnings on startup.
Change-Id: Ic5b1eea578039fd5875097d23de587b970a6dfca
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/unx/kf5/Kf5Instance.cxx | 100 | ||||
-rw-r--r-- | vcl/unx/kf5/Kf5Instance.hxx | 7 |
2 files changed, 103 insertions, 4 deletions
diff --git a/vcl/unx/kf5/Kf5Instance.cxx b/vcl/unx/kf5/Kf5Instance.cxx index b913c79cf64c..4fb218b1ede1 100644 --- a/vcl/unx/kf5/Kf5Instance.cxx +++ b/vcl/unx/kf5/Kf5Instance.cxx @@ -20,21 +20,26 @@ #include "Kf5Instance.hxx" #include <Kf5Instance.moc> -#include <QtCore/QThread> -#include <QtWidgets/QApplication> -#include <QtCore/QAbstractEventDispatcher> - #include "Kf5Frame.hxx" #include "Kf5Data.hxx" #include "Kf5Timer.hxx" #include "Kf5VirtualDevice.hxx" +#include <QtCore/QThread> +#include <QtWidgets/QApplication> +#include <QtCore/QAbstractEventDispatcher> + #include <vclpluginapi.h> #include <sal/log.hxx> +#include <osl/process.h> #include <headless/svpdummies.hxx> #include <headless/svpbmp.hxx> +#include <KAboutData> +#include <KLocalizedString> +#include <KStartupInfo> + Kf5Instance::Kf5Instance( SalYieldMutex* pMutex ) : SalGenericInstance( pMutex ) , m_postUserEventId( -1 ) @@ -49,6 +54,11 @@ Kf5Instance::Kf5Instance( SalYieldMutex* pMutex ) Kf5Instance::~Kf5Instance() { + // force freeing the QApplication before freeing the arguments, + // as it uses references to the provided arguments! + m_pQApplication.reset(); + for( int i = 0; i < *m_pFakeArgc; i++ ) + free( m_pFakeArgvFreeable[i] ); } SalFrame* Kf5Instance::CreateChildFrame( SystemParentData* /*pParent*/, SalFrameStyleFlags nStyle ) @@ -190,11 +200,93 @@ extern "C" { OString aVersion( qVersion() ); SAL_INFO( "vcl.kf5", "qt version string is " << aVersion ); + QApplication *pQApplication; + char **pFakeArgvFreeable = nullptr; + + int nFakeArgc = 2; + const sal_uInt32 nParams = osl_getCommandArgCount(); + OString aDisplay; + OUString aParam, aBin; + + for ( sal_uInt32 nIdx = 0; nIdx < nParams; ++nIdx ) + { + osl_getCommandArg( nIdx, &aParam.pData ); + if ( aParam != "-display" ) + continue; + if ( !pFakeArgvFreeable ) + { + pFakeArgvFreeable = new char*[ nFakeArgc + 2 ]; + pFakeArgvFreeable[ nFakeArgc++ ] = strdup( "-display" ); + } + else + free( pFakeArgvFreeable[ nFakeArgc ] ); + + ++nIdx; + osl_getCommandArg( nIdx, &aParam.pData ); + aDisplay = OUStringToOString( aParam, osl_getThreadTextEncoding() ); + pFakeArgvFreeable[ nFakeArgc ] = strdup( aDisplay.getStr() ); + } + if ( !pFakeArgvFreeable ) + pFakeArgvFreeable = new char*[ nFakeArgc ]; + else + nFakeArgc++; + + osl_getExecutableFile( &aParam.pData ); + osl_getSystemPathFromFileURL( aParam.pData, &aBin.pData ); + OString aExec = OUStringToOString( aBin, osl_getThreadTextEncoding() ); + pFakeArgvFreeable[ 0 ] = strdup( aExec.getStr() ); + pFakeArgvFreeable[ 1 ] = strdup( "--nocrashhandler" ); + + char **pFakeArgv = new char*[ nFakeArgc ]; + for( int i = 0; i < nFakeArgc; i++ ) + pFakeArgv[ i ] = pFakeArgvFreeable[ i ]; + + char* session_manager = nullptr; + if( getenv( "SESSION_MANAGER" ) != nullptr ) + { + session_manager = strdup( getenv( "SESSION_MANAGER" )); + unsetenv( "SESSION_MANAGER" ); + } + + int * pFakeArgc = new int; + *pFakeArgc = nFakeArgc; + pQApplication = new QApplication( *pFakeArgc, pFakeArgv ); + + if( session_manager != nullptr ) + { + // coverity[tainted_string] - trusted source for setenv + setenv( "SESSION_MANAGER", session_manager, 1 ); + free( session_manager ); + } + + KAboutData *kAboutData = new KAboutData( I18N_NOOP("LibreOffice"), + i18n( "LibreOffice" ), + "6.0.0", + i18n( "LibreOffice with KF5 Native Widget Support." ), + KAboutLicense::File, + i18n("Copyright (c) 2017 LibreOffice contributors" ), + i18n( "LibreOffice is an office suite." ), + "http://libreoffice.org", + QLatin1String("libreoffice@lists.freedesktop.org") ); + + kAboutData->addAuthor( i18n( "Jan-Marek Glogowski" ), + i18n( "Original author and maintainer of the KF5 NWF." ), + "glogow@fbihome.de" ); + + KAboutData::setApplicationData( *kAboutData ); + + QApplication::setQuitOnLastWindowClosed(false); + Kf5Instance* pInstance = new Kf5Instance( new SalYieldMutex() ); // initialize SalData new Kf5Data( pInstance ); + pInstance->m_pQApplication.reset( pQApplication ); + pInstance->m_pFakeArgvFreeable.reset( pFakeArgvFreeable ); + pInstance->m_pFakeArgv.reset( pFakeArgv ); + pInstance->m_pFakeArgc.reset( pFakeArgc ); + return pInstance; } } diff --git a/vcl/unx/kf5/Kf5Instance.hxx b/vcl/unx/kf5/Kf5Instance.hxx index 6c1d846cfeb5..98cfa31c1579 100644 --- a/vcl/unx/kf5/Kf5Instance.hxx +++ b/vcl/unx/kf5/Kf5Instance.hxx @@ -26,6 +26,7 @@ #include <QtCore/QObject> +class QApplication; class SalYieldMutex; class SalFrame; @@ -39,6 +40,12 @@ class Kf5Instance osl::Condition m_aWaitingYieldCond; int m_postUserEventId; +public: + std::unique_ptr< QApplication > m_pQApplication; + std::unique_ptr< char*[] > m_pFakeArgvFreeable; + std::unique_ptr< char*[] > m_pFakeArgv; + std::unique_ptr< int > m_pFakeArgc; + private Q_SLOTS: bool ImplYield( bool bWait, bool bHandleAllCurrentEvents ); |