1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
22 #include "sal/config.h"
27 #include "desktop.hrc"
28 #include "cmdlineargs.hxx"
29 #include "cmdlinehelp.hxx"
30 #include "dispatchwatcher.hxx"
31 #include "configinit.hxx"
32 #include "lockfile.hxx"
33 #include "userinstall.hxx"
34 #include "desktopcontext.hxx"
35 #include "exithelper.h"
36 #include "migration.hxx"
38 #include <svtools/javacontext.hxx>
39 #include <com/sun/star/frame/AutoRecovery.hpp>
40 #include <com/sun/star/frame/GlobalEventBroadcaster.hpp>
41 #include <com/sun/star/frame/SessionListener.hpp>
42 #include <com/sun/star/frame/XSessionManagerListener.hpp>
43 #include <com/sun/star/frame/XSynchronousDispatch.hpp>
44 #include <com/sun/star/document/CorruptedFilterConfigurationException.hpp>
45 #include <com/sun/star/configuration/CorruptedConfigurationException.hpp>
46 #include <com/sun/star/configuration/theDefaultProvider.hpp>
47 #include <com/sun/star/util/XFlushable.hpp>
48 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
49 #include <com/sun/star/frame/Desktop.hpp>
50 #include <com/sun/star/frame/StartModule.hpp>
51 #include <com/sun/star/frame/XComponentLoader.hpp>
52 #include <com/sun/star/view/XPrintable.hpp>
53 #include <com/sun/star/awt/XTopWindow.hpp>
54 #include "com/sun/star/util/URLTransformer.hpp"
55 #include <com/sun/star/util/XURLTransformer.hpp>
56 #include <com/sun/star/util/XCloseable.hpp>
57 #include <com/sun/star/frame/XDispatchProvider.hpp>
58 #include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
59 #include <com/sun/star/configuration/MissingBootstrapFileException.hpp>
60 #include <com/sun/star/configuration/InvalidBootstrapFileException.hpp>
61 #include <com/sun/star/configuration/InstallationIncompleteException.hpp>
62 #include <com/sun/star/configuration/backend/BackendSetupException.hpp>
63 #include <com/sun/star/configuration/backend/BackendAccessException.hpp>
64 #include <com/sun/star/task/JobExecutor.hpp>
65 #include <com/sun/star/task/OfficeRestartManager.hpp>
66 #include <com/sun/star/task/XRestartManager.hpp>
67 #include <com/sun/star/document/XEventListener.hpp>
68 #include <com/sun/star/frame/UICommandDescription.hpp>
69 #include <com/sun/star/ui/UIElementFactoryManager.hpp>
70 #include <com/sun/star/ui/WindowStateConfiguration.hpp>
71 #include <com/sun/star/frame/XUIControllerRegistration.hpp>
72 #include <com/sun/star/frame/ToolbarControllerFactory.hpp>
73 #include <com/sun/star/frame/PopupMenuControllerFactory.hpp>
75 #include <toolkit/unohlp.hxx>
76 #include <comphelper/configuration.hxx>
77 #include <comphelper/processfactory.hxx>
78 #include <unotools/bootstrap.hxx>
79 #include <unotools/configmgr.hxx>
80 #include <unotools/moduleoptions.hxx>
81 #include <officecfg/Office/Common.hxx>
82 #include <officecfg/Office/Recovery.hxx>
83 #include <osl/file.hxx>
84 #include <osl/process.h>
85 #include <rtl/uri.hxx>
86 #include <unotools/pathoptions.hxx>
87 #include <svtools/miscopt.hxx>
88 #include <svtools/menuoptions.hxx>
89 #include <rtl/logfile.hxx>
90 #include <rtl/bootstrap.hxx>
91 #include <vcl/help.hxx>
92 #include <vcl/msgbox.hxx>
93 #include <sfx2/sfx.hrc>
94 #include <sfx2/app.hxx>
95 #include <svl/itemset.hxx>
96 #include <svl/eitem.hxx>
98 #include <svtools/fontsubstconfig.hxx>
99 #include <svtools/accessibilityoptions.hxx>
100 #include <svtools/apearcfg.hxx>
101 #include <vcl/graphicfilter.hxx>
103 #include "langselect.hxx"
105 #include <config_telepathy.h>
108 #include <tubes/manager.hxx>
113 #include <sys/wait.h>
118 #pragma warning(push, 1) /* disable warnings within system headers */
119 #pragma warning (disable: 4005)
121 #define WIN32_LEAN_AND_MEAN
130 #define GETPID _getpid
133 #define GETPID getpid
136 using namespace ::com::sun::star::awt
;
137 using namespace ::com::sun::star::uno
;
138 using namespace ::com::sun::star::util
;
139 using namespace ::com::sun::star::lang
;
140 using namespace ::com::sun::star::beans
;
141 using namespace ::com::sun::star::frame
;
142 using namespace ::com::sun::star::document
;
143 using namespace ::com::sun::star::view
;
144 using namespace ::com::sun::star::task
;
145 using namespace ::com::sun::star::system
;
146 using namespace ::com::sun::star::ui
;
147 using namespace ::com::sun::star::ui::dialogs
;
148 using namespace ::com::sun::star::container
;
150 ResMgr
* desktop::Desktop::pResMgr
= 0;
155 static oslSignalHandler pSignalHandler
= 0;
156 static sal_Bool _bCrashReporterEnabled
= sal_True
;
160 void removeTree(OUString
const & url
) {
161 osl::Directory
dir(url
);
162 osl::FileBase::RC rc
= dir
.open();
164 case osl::FileBase::E_None
:
166 case osl::FileBase::E_NOENT
:
167 return; //TODO: SAL_WARN if recursive
170 "desktop", "cannot open directory " << dir
.getURL() << ": " << +rc
);
174 osl::DirectoryItem i
;
175 rc
= dir
.getNextItem(i
, SAL_MAX_UINT32
);
176 if (rc
== osl::FileBase::E_NOENT
) {
179 if (rc
!= osl::FileBase::E_None
) {
182 "cannot iterate directory " << dir
.getURL() << ": " << +rc
);
185 osl::FileStatus
stat(
186 osl_FileStatus_Mask_Type
| osl_FileStatus_Mask_FileName
|
187 osl_FileStatus_Mask_FileURL
);
188 rc
= i
.getFileStatus(stat
);
189 if (rc
!= osl::FileBase::E_None
) {
192 "cannot stat in directory " << dir
.getURL() << ": " << +rc
);
195 if (stat
.getFileType() == osl::FileStatus::Directory
) { //TODO: symlinks
196 removeTree(stat
.getFileURL());
198 rc
= osl::File::remove(stat
.getFileURL());
200 rc
!= osl::FileBase::E_None
, "desktop",
201 "cannot remove file " << stat
.getFileURL() << ": " << +rc
);
207 rc
!= osl::FileBase::E_None
, "desktop",
208 "cannot close directory " << dir
.getURL() << ": " << +rc
);
210 rc
= osl::Directory::remove(url
);
212 rc
!= osl::FileBase::E_None
, "desktop",
213 "cannot remove directory " << url
<< ": " << +rc
);
216 // Remove any existing UserInstallation's extensions cache data remaining from
217 // old installations. This addresses at least two problems:
219 // For one, apparently due to the old share/prereg/bundled mechanism (disabled
220 // since 5c47e5f63a79a9e72ec4a100786b1bbf65137ed4 "fdo#51252 Disable copying
221 // share/prereg/bundled to avoid startup crashes"), the user/extensions/bundled
222 // cache could contain corrupted information (like a UNO component registered
223 // twice, which got changed from active to passive registration in one LO
224 // version, but the version of the corresponding bundled extension only
225 // incremented in a later LO version).
227 // For another, UserInstallations have been seen in the wild where no extensions
228 // were installed per-user (any longer), but user/uno_packages/cache/registry/
229 // com.sun.star.comp.deployment.component.PackageRegistryBackend/*.rdb files
230 // contained data nevertheless.
232 // When a LO upgrade is detected (i.e., no user/extensions/buildid or one
233 // containing an old build ID), then user/extensions and
234 // user/uno_packages/cache/registry/
235 // com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc are
236 // removed. That should prevent any problems starting the service manager due
237 // to old junk. Later on in Desktop::SynchronizeExtensionRepositories, the
238 // removed cache data is recreated.
240 // Multiple instances of soffice.bin can execute this code in parallel for a
241 // single UserInstallation, as it is called before OfficeIPCThread is set up.
242 // Therefore, any errors here only lead to SAL_WARNs.
244 // At least in theory, this function could be removed again once no
245 // UserInstallation can be poisoned by old junk any more.
246 bool cleanExtensionCache() {
248 "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") ":buildid}");
249 rtl::Bootstrap::expandMacros(buildId
); //TODO: detect failure
251 "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("bootstrap")
252 ":UserInstallation}/user/extensions");
253 rtl::Bootstrap::expandMacros(extDir
); //TODO: detect failure
254 OUString
buildIdFile(extDir
+ "/buildid");
255 osl::File
fr(buildIdFile
);
256 osl::FileBase::RC rc
= fr
.open(osl_File_OpenFlag_Read
);
258 case osl::FileBase::E_None
:
260 rtl::ByteSequence s1
;
261 rc
= fr
.readLine(s1
);
262 osl::FileBase::RC rc2
= fr
.close();
264 rc2
!= osl::FileBase::E_None
, "desktop",
265 "cannot close " << fr
.getURL() << " after reading: " << +rc2
);
266 if (rc
!= osl::FileBase::E_None
) {
269 "cannot read from " << fr
.getURL() << ": " << +rc
);
273 reinterpret_cast< char const * >(s1
.getConstArray()),
274 s1
.getLength(), RTL_TEXTENCODING_ISO_8859_1
);
275 // using ISO 8859-1 avoids any and all conversion errors; the
276 // content should only be a subset of ASCII, anyway
282 case osl::FileBase::E_NOENT
:
287 "cannot open " << fr
.getURL() << " for reading: " << +rc
);
292 "$UNO_USER_PACKAGES_CACHE/registry/"
293 "com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc");
294 rtl::Bootstrap::expandMacros(userRcFile
); //TODO: detect failure
295 rc
= osl::File::remove(userRcFile
);
297 rc
!= osl::FileBase::E_None
&& rc
!= osl::FileBase::E_NOENT
, "desktop",
298 "cannot remove file " << userRcFile
<< ": " << +rc
);
299 rc
= osl::Directory::createPath(extDir
);
301 rc
!= osl::FileBase::E_None
&& rc
!= osl::FileBase::E_EXIST
, "desktop",
302 "cannot create path " << extDir
<< ": " << +rc
);
303 osl::File
fw(buildIdFile
);
304 rc
= fw
.open(osl_File_OpenFlag_Write
| osl_File_OpenFlag_Create
);
305 if (rc
!= osl::FileBase::E_None
) {
308 "cannot open " << fw
.getURL() << " for writing: " << +rc
);
311 OString
buf(OUStringToOString(buildId
, RTL_TEXTENCODING_UTF8
));
312 // using UTF-8 avoids almost all conversion errors (and buildid
313 // containing single surrogate halves should never happen, anyway); the
314 // content should only be a subset of ASCII, anyway
316 rc
= fw
.write(buf
.getStr(), buf
.getLength(), n
);
318 (rc
!= osl::FileBase::E_None
319 || n
!= static_cast< sal_uInt32
>(buf
.getLength())),
321 "cannot write to " << fw
.getURL() << ": " << +rc
<< ", " << n
);
324 rc
!= osl::FileBase::E_None
, "desktop",
325 "cannot close " << fw
.getURL() << " after writing: " << +rc
);
331 // ----------------------------------------------------------------------------
333 ResMgr
* Desktop::GetDesktopResManager()
335 if ( !Desktop::pResMgr
)
337 // Create desktop resource manager and bootstrap process
338 // was successful. Use default way to get language specific message.
339 if ( Application::IsInExecute() )
340 Desktop::pResMgr
= ResMgr::CreateResMgr("dkt");
342 if ( !Desktop::pResMgr
)
344 // Use VCL to get the correct language specific message as we
345 // are in the bootstrap process and not able to get the installed
347 OUString aUILocaleString
= LanguageSelection::getLanguageString();
348 LanguageTag
aLanguageTag( aUILocaleString
);
349 //! ResMgr may modify the Locale for fallback!
350 Desktop::pResMgr
= ResMgr::SearchCreateResMgr( "dkt", aLanguageTag
);
351 AllSettings as
= GetSettings();
352 as
.SetUILanguageTag(aLanguageTag
);
357 return Desktop::pResMgr
;
362 // ----------------------------------------------------------------------------
363 // Get a message string securely. There is a fallback string if the resource
366 OUString
GetMsgString(
367 sal_uInt16 nId
, const OUString
& aFallbackMsg
,
368 bool bAlwaysUseFallbackMsg
= false )
370 if ( !bAlwaysUseFallbackMsg
)
372 ResMgr
* resMgr
= Desktop::GetDesktopResManager();
374 return OUString( String( ResId( nId
, *resMgr
)));
379 OUString
MakeStartupErrorMessage(
380 OUString
const & aErrorMessage
, bool bAlwaysUseFallbackMsg
= false )
382 OUStringBuffer
aDiagnosticMessage( 100 );
384 aDiagnosticMessage
.append(
386 STR_BOOTSTRAP_ERR_CANNOT_START
, "The program cannot be started.",
387 bAlwaysUseFallbackMsg
) );
389 aDiagnosticMessage
.appendAscii( "\n" );
391 aDiagnosticMessage
.append( aErrorMessage
);
393 return aDiagnosticMessage
.makeStringAndClear();
396 OUString
MakeStartupConfigAccessErrorMessage( OUString
const & aInternalErrMsg
)
398 OUStringBuffer
aDiagnosticMessage( 200 );
400 ResMgr
* pResMgr
= Desktop::GetDesktopResManager();
402 aDiagnosticMessage
.append( OUString(String(ResId(STR_BOOTSTRAP_ERR_CFG_DATAACCESS
, *pResMgr
))) );
404 aDiagnosticMessage
.appendAscii( "The program cannot be started." );
406 if ( !aInternalErrMsg
.isEmpty() )
408 aDiagnosticMessage
.appendAscii( "\n\n" );
410 aDiagnosticMessage
.append( OUString(String(ResId(STR_INTERNAL_ERRMSG
, *pResMgr
))) );
412 aDiagnosticMessage
.appendAscii( "The following internal error has occurred:\n\n" );
413 aDiagnosticMessage
.append( aInternalErrMsg
);
416 return aDiagnosticMessage
.makeStringAndClear();
419 //=============================================================================
420 // shows a simple error box with the given message ... but exits from these process !
421 // Fatal errors cant be solved by the process ... nor any recovery can help.
422 // Mostly the installation was damaged and must be repaired manually .. or by calling
424 // On the other side we must make sure that no further actions will be possible within
425 // the current office process ! No pipe requests, no menu/toolbar/shortuct actions
426 // are allowed. Otherwise we will force a "crash inside a crash".
427 // Thats why we have to use a special native message box here which does not use yield :-)
428 //=============================================================================
429 void FatalError(const OUString
& sMessage
)
431 OUString sProductKey
= ::utl::Bootstrap::getProductKey();
432 if ( sProductKey
.isEmpty())
434 osl_getExecutableFile( &sProductKey
.pData
);
436 ::sal_uInt32 nLastIndex
= sProductKey
.lastIndexOf('/');
437 if ( nLastIndex
> 0 )
438 sProductKey
= sProductKey
.copy( nLastIndex
+1 );
441 OUStringBuffer
sTitle (128);
442 sTitle
.append (sProductKey
);
443 sTitle
.appendAscii (" - Fatal Error");
445 Application::ShowNativeErrorBox (sTitle
.makeStringAndClear (), sMessage
);
446 _exit(EXITHELPER_FATAL_ERROR
);
449 static bool ShouldSuppressUI(const CommandLineArgs
& rCmdLine
)
451 return rCmdLine
.IsInvisible() ||
452 rCmdLine
.IsHeadless() ||
453 rCmdLine
.IsQuickstart();
456 struct theCommandLineArgs
: public rtl::Static
< CommandLineArgs
, theCommandLineArgs
> {};
460 CommandLineArgs
& Desktop::GetCommandLineArgs()
462 return theCommandLineArgs::get();
468 : public rtl::Static
< String
, BrandName
> {};
470 : public rtl::Static
< String
, Version
> {};
471 struct AboutBoxVersion
472 : public rtl::Static
< String
, AboutBoxVersion
> {};
473 struct AboutBoxVersionSuffix
474 : public rtl::Static
< String
, AboutBoxVersionSuffix
> {};
476 : public rtl::Static
< String
, OOOVendor
> {};
478 : public rtl::Static
< String
, Extension
> {};
479 struct XMLFileFormatName
480 : public rtl::Static
< String
, XMLFileFormatName
> {};
481 struct XMLFileFormatVersion
482 : public rtl::Static
< String
, XMLFileFormatVersion
> {};
483 struct WriterCompatibilityVersionOOo11
484 : public rtl::Static
< String
, WriterCompatibilityVersionOOo11
> {};
487 OUString
ReplaceStringHookProc( const OUString
& rStr
)
491 if (sRet
.indexOf("%PRODUCT") != -1 || sRet
.indexOf("%ABOUTBOX") != -1)
493 OUString sBrandName
= BrandName::get();
494 OUString sVersion
= Version::get();
495 OUString sBuildId
= utl::Bootstrap::getBuildIdData("development");
496 OUString sAboutBoxVersion
= AboutBoxVersion::get();
497 OUString sAboutBoxVersionSuffix
= AboutBoxVersionSuffix::get();
498 OUString sExtension
= Extension::get();
499 OUString sXMLFileFormatName
= XMLFileFormatName::get();
500 OUString sXMLFileFormatVersion
= XMLFileFormatVersion::get();
502 if ( sBrandName
.isEmpty() )
504 sBrandName
= utl::ConfigManager::getProductName();
505 sXMLFileFormatName
= utl::ConfigManager::getProductXmlFileFormat();
506 sXMLFileFormatVersion
=
507 utl::ConfigManager::getProductXmlFileFormatVersion();
508 sVersion
= utl::ConfigManager::getProductVersion();
509 sAboutBoxVersion
= utl::ConfigManager::getAboutBoxProductVersion();
510 sAboutBoxVersionSuffix
= utl::ConfigManager::getAboutBoxProductVersionSuffix();
511 if ( sExtension
.isEmpty() )
513 sExtension
= utl::ConfigManager::getProductExtension();
517 sRet
= sRet
.replaceAll( "%PRODUCTNAME", sBrandName
);
518 sRet
= sRet
.replaceAll( "%PRODUCTVERSION", sVersion
);
519 sRet
= sRet
.replaceAll( "%BUILDID", sBuildId
);
520 sRet
= sRet
.replaceAll( "%ABOUTBOXPRODUCTVERSIONSUFFIX", sAboutBoxVersionSuffix
);
521 sRet
= sRet
.replaceAll( "%ABOUTBOXPRODUCTVERSION", sAboutBoxVersion
);
522 sRet
= sRet
.replaceAll( "%PRODUCTEXTENSION", sExtension
);
523 sRet
= sRet
.replaceAll( "%PRODUCTXMLFILEFORMATNAME", sXMLFileFormatName
);
524 sRet
= sRet
.replaceAll( "%PRODUCTXMLFILEFORMATVERSION", sXMLFileFormatVersion
);
527 if ( sRet
.indexOf( "%OOOVENDOR" ) != -1 )
529 OUString sOOOVendor
= OOOVendor::get();
531 if ( sOOOVendor
.isEmpty() )
533 sOOOVendor
= utl::ConfigManager::getVendor();
536 sRet
= sRet
.replaceAll( "%OOOVENDOR", sOOOVendor
);
539 if ( sRet
.indexOf( "%WRITERCOMPATIBILITYVERSIONOOO11" ) != -1 )
541 OUString sWriterCompatibilityVersionOOo11
= WriterCompatibilityVersionOOo11::get();
542 if ( sWriterCompatibilityVersionOOo11
.isEmpty() )
544 sWriterCompatibilityVersionOOo11
=
545 utl::ConfigManager::getWriterCompatibilityVersionOOo_1_1();
548 sRet
= sRet
.replaceAll( "%WRITERCOMPATIBILITYVERSIONOOO11",
549 sWriterCompatibilityVersionOOo11
);
556 : m_bCleanedExtensionCache( false )
557 , m_bServicesRegistered( false )
558 , m_aBootstrapError( BE_OK
)
560 RTL_LOGFILE_TRACE( "desktop (cd100003) ::Desktop::Desktop" );
566 TeleManager::finalize();
572 RTL_LOGFILE_CONTEXT( aLog
, "desktop (cd100003) ::Desktop::Init" );
573 SetBootstrapStatus(BS_OK
);
575 m_bCleanedExtensionCache
= cleanExtensionCache();
577 // We need to have service factory before going further, but see fdo#37195.
578 // Doing this will mmap common.rdb, making it not overwritable on windows,
579 // so this can't happen before the synchronization above. Lets rework this
580 // so that the above is called *from* CreateApplicationServiceManager or
581 // something to enforce this gotcha
584 InitApplicationServiceManager();
586 catch (css::uno::Exception
& e
)
588 SetBootstrapError( BE_UNO_SERVICEMANAGER
, e
.Message
);
591 if ( m_aBootstrapError
== BE_OK
)
594 if ( !LanguageSelection::prepareLanguage() )
596 if ( LanguageSelection::getStatus() == LanguageSelection::LS_STATUS_CANNOT_DETERMINE_LANGUAGE
)
597 SetBootstrapError( BE_LANGUAGE_MISSING
, OUString() );
599 SetBootstrapError( BE_OFFICECONFIG_BROKEN
, OUString() );
605 const CommandLineArgs
& rCmdLineArgs
= GetCommandLineArgs();
607 // start ipc thread only for non-remote offices
608 RTL_LOGFILE_CONTEXT( aLog2
, "desktop (cd100003) ::OfficeIPCThread::EnableOfficeIPCThread" );
609 OfficeIPCThread::Status aStatus
= OfficeIPCThread::EnableOfficeIPCThread();
610 if ( aStatus
== OfficeIPCThread::IPC_STATUS_PIPE_ERROR
)
613 // In a sandboxed LO, on 10.8.2 at least, creating the
614 // Unix domain socket fails. Ignore that as hopefully
615 // people running a sandboxed LO won't attempt starting it
616 // from the command-line or otherwise in tricky ways, so
617 // the normal OS X mechanism that prevents multiple
618 // instances of an app from being started should work
620 #elif defined ANDROID
621 // Ignore crack pipe errors on Android, too
623 // Keep using this oddly named BE_PATHINFO_MISSING value
624 // for pipe-related errors on other platforms. Of course
625 // this crack with two (if not more) levels of our own
626 // error codes hiding the actual system error code is
627 // broken, but that is done all over the code, let's leave
628 // re-enginering that to another year.
629 SetBootstrapError( BE_PATHINFO_MISSING
, OUString() );
632 else if ( aStatus
== OfficeIPCThread::IPC_STATUS_BOOTSTRAP_ERROR
)
634 SetBootstrapError( BE_PATHINFO_MISSING
, OUString() );
636 else if ( aStatus
== OfficeIPCThread::IPC_STATUS_2ND_OFFICE
)
638 // 2nd office startup should terminate after sending cmdlineargs through pipe
639 SetBootstrapStatus(BS_TERMINATE
);
641 else if ( !rCmdLineArgs
.GetUnknown().isEmpty()
642 || rCmdLineArgs
.IsHelp() || rCmdLineArgs
.IsVersion() )
644 // disable IPC thread in an instance that is just showing a help message
645 OfficeIPCThread::DisableOfficeIPCThread();
647 pSignalHandler
= osl_addSignalHandler(SalMainPipeExchangeSignal_impl
, NULL
);
651 void Desktop::InitFinished()
653 RTL_LOGFILE_CONTEXT( aLog
, "desktop (cd100003) ::Desktop::InitFinished" );
658 void Desktop::DeInit()
660 RTL_LOGFILE_CONTEXT( aLog
, "desktop (cd100003) ::Desktop::DeInit" );
663 // instead of removing of the configManager just let it commit all the changes
664 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "<- store config items" );
665 utl::ConfigManager::storeConfigItems();
666 FlushConfiguration();
667 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "<- store config items" );
669 // close splashscreen if it's still open
671 Reference
< XComponent
>(
672 comphelper::getProcessComponentContext(), UNO_QUERY_THROW
)->
674 // nobody should get a destroyed service factory...
675 ::comphelper::setProcessServiceFactory( NULL
);
680 OfficeIPCThread::DisableOfficeIPCThread();
682 osl_removeSignalHandler( pSignalHandler
);
683 } catch (const RuntimeException
&) {
684 // someone threw an exception during shutdown
685 // this will leave some garbage behind..
688 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "FINISHED WITH Destop::DeInit" );
691 sal_Bool
Desktop::QueryExit()
695 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "<- store config items" );
696 utl::ConfigManager::storeConfigItems();
697 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "<- store config items" );
699 catch ( const RuntimeException
& )
703 const sal_Char SUSPEND_QUICKSTARTVETO
[] = "SuspendQuickstartVeto";
705 Reference
< XDesktop2
> xDesktop
= css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
706 Reference
< XPropertySet
> xPropertySet(xDesktop
, UNO_QUERY_THROW
);
707 xPropertySet
->setPropertyValue( OUString(SUSPEND_QUICKSTARTVETO
), Any((sal_Bool
)sal_True
) );
709 sal_Bool bExit
= xDesktop
->terminate();
713 xPropertySet
->setPropertyValue( OUString(SUSPEND_QUICKSTARTVETO
), Any((sal_Bool
)sal_False
) );
717 FlushConfiguration();
720 // it is no problem to call DisableOfficeIPCThread() more than once
721 // it also looks to be threadsafe
722 OfficeIPCThread::DisableOfficeIPCThread();
724 catch ( const RuntimeException
& )
735 void Desktop::HandleBootstrapPathErrors( ::utl::Bootstrap::Status aBootstrapStatus
, const OUString
& aDiagnosticMessage
)
737 if ( aBootstrapStatus
!= ::utl::Bootstrap::DATA_OK
)
739 OUString aProductKey
;
742 osl_getExecutableFile( &aProductKey
.pData
);
743 sal_uInt32 lastIndex
= aProductKey
.lastIndexOf('/');
745 aProductKey
= aProductKey
.copy( lastIndex
+1 );
747 aTemp
= ::utl::Bootstrap::getProductKey( aProductKey
);
748 if ( !aTemp
.isEmpty() )
751 OUString
const aMessage(aDiagnosticMessage
+ "\n");
753 ErrorBox
aBootstrapFailedBox( NULL
, WB_OK
, aMessage
);
754 aBootstrapFailedBox
.SetText( aProductKey
);
755 aBootstrapFailedBox
.Execute();
759 // Create a error message depending on bootstrap failure code and an optional file url
760 OUString
Desktop::CreateErrorMsgString(
761 utl::Bootstrap::FailureCode nFailureCode
,
762 const OUString
& aFileURL
)
766 sal_Bool bFileInfo
= sal_True
;
768 switch ( nFailureCode
)
770 /// the shared installation directory could not be located
771 case ::utl::Bootstrap::MISSING_INSTALL_DIRECTORY
:
773 aMsg
= GetMsgString( STR_BOOTSTRAP_ERR_PATH_INVALID
,
774 OUString( "The installation path is not available." ) );
775 bFileInfo
= sal_False
;
779 /// the bootstrap INI file could not be found or read
780 case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE
:
782 aMsg
= GetMsgString( STR_BOOTSTRAP_ERR_FILE_MISSING
,
783 OUString( "The configuration file \"$1\" is missing." ) );
787 /// the bootstrap INI is missing a required entry
788 /// the bootstrap INI contains invalid data
789 case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE_ENTRY
:
790 case ::utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY
:
792 aMsg
= GetMsgString( STR_BOOTSTRAP_ERR_FILE_CORRUPT
,
793 OUString( "The configuration file \"$1\" is corrupt." ) );
797 /// the version locator INI file could not be found or read
798 case ::utl::Bootstrap::MISSING_VERSION_FILE
:
800 aMsg
= GetMsgString( STR_BOOTSTRAP_ERR_FILE_MISSING
,
801 OUString( "The configuration file \"$1\" is missing." ) );
805 /// the version locator INI has no entry for this version
806 case ::utl::Bootstrap::MISSING_VERSION_FILE_ENTRY
:
808 aMsg
= GetMsgString( STR_BOOTSTRAP_ERR_NO_SUPPORT
,
809 OUString( "The main configuration file \"$1\" does not support the current version." ) );
813 /// the user installation directory does not exist
814 case ::utl::Bootstrap::MISSING_USER_DIRECTORY
:
816 aMsg
= GetMsgString( STR_BOOTSTRAP_ERR_DIR_MISSING
,
817 OUString( "The configuration directory \"$1\" is missing." ) );
821 /// some bootstrap data was invalid in unexpected ways
822 case ::utl::Bootstrap::INVALID_BOOTSTRAP_DATA
:
824 aMsg
= GetMsgString( STR_BOOTSTRAP_ERR_INTERNAL
,
825 OUString( "An internal failure occurred." ) );
826 bFileInfo
= sal_False
;
830 case ::utl::Bootstrap::INVALID_VERSION_FILE_ENTRY
:
832 // This needs to be improved, see #i67575#:
834 "Invalid version file entry" );
835 bFileInfo
= sal_False
;
839 case ::utl::Bootstrap::NO_FAILURE
:
848 String
aMsgString( aMsg
);
850 osl::File::getSystemPathFromFileURL( aFileURL
, aFilePath
);
852 aMsgString
.SearchAndReplaceAscii( "$1", aFilePath
);
856 return MakeStartupErrorMessage( aMsg
);
859 void Desktop::HandleBootstrapErrors(
860 BootstrapError aBootstrapError
, OUString
const & aErrorMessage
)
862 if ( aBootstrapError
== BE_PATHINFO_MISSING
)
866 utl::Bootstrap::Status aBootstrapStatus
;
867 utl::Bootstrap::FailureCode nFailureCode
;
869 aBootstrapStatus
= ::utl::Bootstrap::checkBootstrapStatus( aBuffer
, nFailureCode
);
870 if ( aBootstrapStatus
!= ::utl::Bootstrap::DATA_OK
)
872 switch ( nFailureCode
)
874 case ::utl::Bootstrap::MISSING_INSTALL_DIRECTORY
:
875 case ::utl::Bootstrap::INVALID_BOOTSTRAP_DATA
:
877 aErrorMsg
= CreateErrorMsgString( nFailureCode
, OUString() );
881 /// the bootstrap INI file could not be found or read
882 /// the bootstrap INI is missing a required entry
883 /// the bootstrap INI contains invalid data
884 case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE_ENTRY
:
885 case ::utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY
:
886 case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE
:
888 OUString aBootstrapFileURL
;
890 utl::Bootstrap::locateBootstrapFile( aBootstrapFileURL
);
891 aErrorMsg
= CreateErrorMsgString( nFailureCode
, aBootstrapFileURL
);
895 /// the version locator INI file could not be found or read
896 /// the version locator INI has no entry for this version
897 /// the version locator INI entry is not a valid directory URL
898 case ::utl::Bootstrap::INVALID_VERSION_FILE_ENTRY
:
899 case ::utl::Bootstrap::MISSING_VERSION_FILE_ENTRY
:
900 case ::utl::Bootstrap::MISSING_VERSION_FILE
:
902 OUString aVersionFileURL
;
904 utl::Bootstrap::locateVersionFile( aVersionFileURL
);
905 aErrorMsg
= CreateErrorMsgString( nFailureCode
, aVersionFileURL
);
909 /// the user installation directory does not exist
910 case ::utl::Bootstrap::MISSING_USER_DIRECTORY
:
912 OUString aUserInstallationURL
;
914 utl::Bootstrap::locateUserInstallation( aUserInstallationURL
);
915 aErrorMsg
= CreateErrorMsgString( nFailureCode
, aUserInstallationURL
);
919 case ::utl::Bootstrap::NO_FAILURE
:
926 HandleBootstrapPathErrors( aBootstrapStatus
, aErrorMsg
);
929 else if ( aBootstrapError
== BE_UNO_SERVICEMANAGER
|| aBootstrapError
== BE_UNO_SERVICE_CONFIG_MISSING
)
931 // Uno service manager is not available. VCL needs a uno service manager to display a message box!!!
932 // Currently we are not able to display a message box with a service manager due to this limitations inside VCL.
934 // When UNO is not properly initialized, all kinds of things can fail
935 // and cause the process to crash (e.g., a call to GetMsgString may
936 // crash when somewhere deep within that call Any::operator <= is used
937 // with a PropertyValue, and no binary UNO type description for
938 // PropertyValue is available). To give the user a hint even if
939 // generating and displaying a message box below crashes, print a
940 // hard-coded message on stderr first:
942 << "The application cannot be started.\n"
943 // STR_BOOTSTRAP_ERR_CANNOT_START
944 << (aBootstrapError
== BE_UNO_SERVICEMANAGER
945 ? "The component manager is not available.\n"
946 // STR_BOOTSTRAP_ERR_NO_SERVICE
947 : "The configuration service is not available.\n");
948 // STR_BOOTSTRAP_ERR_NO_CFG_SERVICE
949 if ( !aErrorMessage
.isEmpty() )
951 std::cerr
<< "(\"" << aErrorMessage
<< "\")\n";
954 // First sentence. We cannot bootstrap office further!
956 OUStringBuffer
aDiagnosticMessage( 100 );
960 if ( aBootstrapError
== BE_UNO_SERVICEMANAGER
)
961 aErrorMsg
= "The service manager is not available.";
963 aErrorMsg
= GetMsgString( STR_BOOTSTRAP_ERR_NO_CFG_SERVICE
,
964 OUString( "The configuration service is not available." ) );
966 aDiagnosticMessage
.append( aErrorMsg
);
967 aDiagnosticMessage
.appendAscii( "\n" );
968 if ( !aErrorMessage
.isEmpty() )
970 aDiagnosticMessage
.appendAscii( "(\"" );
971 aDiagnosticMessage
.append( aErrorMessage
);
972 aDiagnosticMessage
.appendAscii( "\")\n" );
975 // Due to the fact the we haven't a backup applicat.rdb file anymore it is not possible to
976 // repair the installation with the setup executable besides the office executable. Now
977 // we have to ask the user to start the setup on CD/installation directory manually!!
978 OUString
aStartSetupManually( GetMsgString(
979 STR_ASK_START_SETUP_MANUALLY
,
980 OUString( "Start setup application to repair the installation from CD, or the folder containing the installation packages." ),
981 aBootstrapError
== BE_UNO_SERVICEMANAGER
) );
983 aDiagnosticMessage
.append( aStartSetupManually
);
984 aMessage
= MakeStartupErrorMessage(
985 aDiagnosticMessage
.makeStringAndClear(),
986 aBootstrapError
== BE_UNO_SERVICEMANAGER
);
988 FatalError( aMessage
);
990 else if ( aBootstrapError
== BE_OFFICECONFIG_BROKEN
)
993 OUStringBuffer
aDiagnosticMessage( 100 );
995 aErrorMsg
= GetMsgString( STR_CONFIG_ERR_ACCESS_GENERAL
,
996 OUString( "A general error occurred while accessing your central configuration." ) );
997 aDiagnosticMessage
.append( aErrorMsg
);
998 aMessage
= MakeStartupErrorMessage( aDiagnosticMessage
.makeStringAndClear() );
999 FatalError(aMessage
);
1001 else if ( aBootstrapError
== BE_USERINSTALL_FAILED
)
1004 OUStringBuffer
aDiagnosticMessage( 100 );
1006 aErrorMsg
= GetMsgString( STR_BOOTSTRAP_ERR_USERINSTALL_FAILED
,
1007 OUString( "User installation could not be completed" ) );
1008 aDiagnosticMessage
.append( aErrorMsg
);
1009 aMessage
= MakeStartupErrorMessage( aDiagnosticMessage
.makeStringAndClear() );
1010 FatalError(aMessage
);
1012 else if ( aBootstrapError
== BE_LANGUAGE_MISSING
)
1015 OUStringBuffer
aDiagnosticMessage( 100 );
1017 aErrorMsg
= GetMsgString(
1018 //@@@ FIXME: should use an own resource string => #i36213#
1019 STR_BOOTSTRAP_ERR_LANGUAGE_MISSING
,
1020 OUString( "Language could not be determined." ) );
1021 aDiagnosticMessage
.append( aErrorMsg
);
1022 aMessage
= MakeStartupErrorMessage(
1023 aDiagnosticMessage
.makeStringAndClear() );
1024 FatalError(aMessage
);
1026 else if (( aBootstrapError
== BE_USERINSTALL_NOTENOUGHDISKSPACE
) ||
1027 ( aBootstrapError
== BE_USERINSTALL_NOWRITEACCESS
))
1029 OUString aUserInstallationURL
;
1030 OUString aUserInstallationPath
;
1033 OUStringBuffer
aDiagnosticMessage( 100 );
1035 utl::Bootstrap::locateUserInstallation( aUserInstallationURL
);
1037 if ( aBootstrapError
== BE_USERINSTALL_NOTENOUGHDISKSPACE
)
1038 aErrorMsg
= GetMsgString(
1039 STR_BOOSTRAP_ERR_NOTENOUGHDISKSPACE
,
1040 OUString( "User installation could not be completed due to insufficient free disk space." ) );
1042 aErrorMsg
= GetMsgString(
1043 STR_BOOSTRAP_ERR_NOACCESSRIGHTS
,
1044 OUString( "User installation could not be processed due to missing access rights." ) );
1046 osl::File::getSystemPathFromFileURL( aUserInstallationURL
, aUserInstallationPath
);
1048 aDiagnosticMessage
.append( aErrorMsg
);
1049 aDiagnosticMessage
.append( aUserInstallationPath
);
1050 aMessage
= MakeStartupErrorMessage(
1051 aDiagnosticMessage
.makeStringAndClear() );
1052 FatalError(aMessage
);
1059 void Desktop::retrieveCrashReporterState()
1061 _bCrashReporterEnabled
1062 = officecfg::Office::Recovery::CrashReporter::Enabled::get();
1065 sal_Bool
Desktop::isUIOnSessionShutdownAllowed()
1067 return officecfg::Office::Recovery::SessionShutdown::DocumentStoreUIEnabled
1071 //-----------------------------------------------
1072 /** @short check if crash reporter feature is enabled or
1075 sal_Bool
Desktop::isCrashReporterEnabled()
1077 return _bCrashReporterEnabled
;
1080 //-----------------------------------------------
1081 /** @short check if recovery must be started or not.
1083 @param bCrashed [boolean ... out!]
1084 the office crashed last times.
1085 But may be there are no recovery data.
1086 Useful to trigger the error report tool without
1087 showing the recovery UI.
1089 @param bRecoveryDataExists [boolean ... out!]
1090 there exists some recovery data.
1092 @param bSessionDataExists [boolean ... out!]
1093 there exists some session data.
1094 Because the user may be logged out last time from it's
1097 void impl_checkRecoveryState(sal_Bool
& bCrashed
,
1098 sal_Bool
& bRecoveryDataExists
,
1099 sal_Bool
& bSessionDataExists
)
1101 bCrashed
= officecfg::Office::Recovery::RecoveryInfo::Crashed::get();
1102 bool elements
= officecfg::Office::Recovery::RecoveryList::get()->
1105 = officecfg::Office::Recovery::RecoveryInfo::SessionData::get();
1106 bRecoveryDataExists
= elements
&& !session
;
1107 bSessionDataExists
= elements
&& session
;
1110 //-----------------------------------------------
1111 /* @short start the recovery wizard.
1113 @param bEmergencySave
1114 differs between EMERGENCY_SAVE and RECOVERY
1116 sal_Bool
impl_callRecoveryUI(sal_Bool bEmergencySave
,
1118 sal_Bool bExistsRecoveryData
)
1120 static OUString
SERVICENAME_RECOVERYUI("com.sun.star.comp.svx.RecoveryUI");
1121 static OUString
COMMAND_EMERGENCYSAVE("vnd.sun.star.autorecovery:/doEmergencySave");
1122 static OUString
COMMAND_RECOVERY("vnd.sun.star.autorecovery:/doAutoRecovery");
1123 static OUString
COMMAND_CRASHREPORT("vnd.sun.star.autorecovery:/doCrashReport");
1125 css::uno::Reference
< css::uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
1127 Reference
< css::frame::XSynchronousDispatch
> xRecoveryUI(
1128 xContext
->getServiceManager()->createInstanceWithContext(SERVICENAME_RECOVERYUI
, xContext
),
1129 css::uno::UNO_QUERY_THROW
);
1131 Reference
< css::util::XURLTransformer
> xURLParser
=
1132 css::util::URLTransformer::create(::comphelper::getProcessComponentContext());
1134 css::util::URL aURL
;
1136 aURL
.Complete
= COMMAND_EMERGENCYSAVE
;
1137 else if (bExistsRecoveryData
)
1138 aURL
.Complete
= COMMAND_RECOVERY
;
1139 else if (bCrashed
&& Desktop::isCrashReporterEnabled() )
1140 aURL
.Complete
= COMMAND_CRASHREPORT
;
1144 xURLParser
->parseStrict(aURL
);
1146 css::uno::Any aRet
= xRecoveryUI
->dispatchWithReturnValue(aURL
, css::uno::Sequence
< css::beans::PropertyValue
>());
1147 sal_Bool bRet
= sal_False
;
1149 return !bEmergencySave
|| bRet
;
1153 * Save all open documents so they will be reopened
1154 * the next time the application ist started
1156 * returns sal_True if at least one document could be saved...
1160 sal_Bool
Desktop::SaveTasks()
1162 return impl_callRecoveryUI(
1163 sal_True
, // sal_True => force emergency save
1164 sal_False
, // 2. and 3. param not used if 1. = true!
1170 void restartOnMac(bool passArguments
) {
1172 OfficeIPCThread::DisableOfficeIPCThread();
1173 #ifdef ENABLE_MACOSX_SANDBOX
1174 (void) passArguments
; // avoid warnings
1175 ResMgr
*resMgr
= Desktop::GetDesktopResManager();
1176 OUString aMessage
= OUString( String( ResId( STR_LO_MUST_BE_RESTARTED
, *resMgr
)));
1178 ErrorBox
aRestartBox( NULL
, WB_OK
, aMessage
);
1179 aRestartBox
.Execute();
1182 OSL_VERIFY(osl_getExecutableFile(&execUrl
.pData
) == osl_Process_E_None
);
1185 if ((osl::FileBase::getSystemPathFromFileURL(execUrl
, execPath
)
1186 != osl::FileBase::E_None
) ||
1187 !execPath
.convertToString(
1188 &execPath8
, osl_getThreadTextEncoding(),
1189 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
|
1190 RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
)))
1194 std::vector
< OString
> args
;
1195 args
.push_back(execPath8
);
1197 if (passArguments
) {
1198 sal_uInt32 n
= osl_getCommandArgCount();
1199 for (sal_uInt32 i
= 0; i
< n
; ++i
) {
1201 OSL_VERIFY(osl_getCommandArg(i
, &arg
.pData
) == osl_Process_E_None
);
1202 if (arg
.match("--accept=")) {
1206 if (!arg
.convertToString(
1207 &arg8
, osl_getThreadTextEncoding(),
1208 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
|
1209 RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
)))
1213 args
.push_back(arg8
);
1216 std::vector
< char const * > argPtrs
;
1217 for (std::vector
< OString
>::iterator
i(args
.begin()); i
!= args
.end();
1220 argPtrs
.push_back(i
->getStr());
1222 argPtrs
.push_back(0);
1223 execv(execPath8
.getStr(), const_cast< char ** >(&argPtrs
[0]));
1224 if (errno
== ENOTSUP
) { // happens when multithreaded on OS X < 10.6
1227 execv(execPath8
.getStr(), const_cast< char ** >(&argPtrs
[0]));
1228 } else if (pid
> 0) {
1229 // Two simultaneously running soffice processes lead to two dock
1230 // icons, so avoid waiting here unless it must be assumed that the
1231 // process invoking soffice itself wants to wait for soffice to
1237 if (waitpid(pid
, &stat
, 0) == pid
&& WIFEXITED(stat
)) {
1238 _exit(WEXITSTATUS(stat
));
1245 (void) passArguments
; // avoid warnings
1251 sal_uInt16
Desktop::Exception(sal_uInt16 nError
)
1253 // protect against recursive calls
1254 static sal_Bool bInException
= sal_False
;
1256 sal_uInt16 nOldMode
= Application::GetSystemWindowMode();
1257 Application::SetSystemWindowMode( nOldMode
& ~SYSTEMWINDOW_MODE_NOAUTOMODE
);
1258 Application::SetDefDialogParent( NULL
);
1262 String aDoubleExceptionString
;
1263 Application::Abort( aDoubleExceptionString
);
1266 bInException
= sal_True
;
1267 const CommandLineArgs
& rArgs
= GetCommandLineArgs();
1269 // save all modified documents ... if it's allowed doing so.
1270 sal_Bool bRestart
= sal_False
;
1271 sal_Bool bAllowRecoveryAndSessionManagement
= (
1272 ( !rArgs
.IsNoRestore() ) && // some use cases of office must work without recovery
1273 ( !rArgs
.IsHeadless() ) &&
1274 (( nError
& EXC_MAJORTYPE
) != EXC_DISPLAY
) && // recovery cant work without UI ... but UI layer seams to be the reason for this crash
1275 ( Application::IsInExecute() ) // crashes during startup and shutdown should be ignored (they indicates a corrupt installation ...)
1277 if ( bAllowRecoveryAndSessionManagement
)
1278 bRestart
= SaveTasks();
1280 FlushConfiguration();
1282 switch( nError
& EXC_MAJORTYPE
)
1284 case EXC_RSCNOTLOADED
:
1286 String aResExceptionString
;
1287 Application::Abort( aResExceptionString
);
1291 case EXC_SYSOBJNOTCREATED
:
1293 String aSysResExceptionString
;
1294 Application::Abort( aSysResExceptionString
);
1300 m_xLockfile
.reset();
1304 OfficeIPCThread::DisableOfficeIPCThread();
1305 if( pSignalHandler
)
1306 osl_removeSignalHandler( pSignalHandler
);
1308 restartOnMac(false);
1309 if ( m_rSplashScreen
.is() )
1310 m_rSplashScreen
->reset();
1312 _exit( EXITHELPER_CRASH_WITH_RESTART
);
1316 Application::Abort( String() );
1323 OSL_ASSERT(false); // unreachable
1327 void Desktop::AppEvent( const ApplicationEvent
& rAppEvent
)
1329 HandleAppEvent( rAppEvent
);
1333 void SetDocumentExtendedStyle( const Reference
< ::com::sun::star::awt::XWindow
> &xContainerWindow
)
1335 // set the WB_EXT_DOCUMENT style. Normally, this is done by the TaskCreator service when a "_blank"
1336 // frame/window is created. Since we do not use the TaskCreator here, we need to mimic its behavior,
1337 // otherwise documents loaded into this frame will later on miss functionality depending on the style.
1338 Window
* pContainerWindow
= VCLUnoHelper::GetWindow( xContainerWindow
);
1339 OSL_ENSURE( pContainerWindow
, "Desktop::Main: no implementation access to the frame's container window!" );
1340 if (!pContainerWindow
) {
1341 fprintf (stderr
, "Error: It very much looks as if you have used 'linkoo' (or bin/ooinstall -l)\n"
1342 "but have then forgotten to source 'ooenv' into your shell before running !\n"
1343 "to save a crash, we will exit now with an error - please '. ./ooenv' first.\n");
1346 pContainerWindow
->SetExtendedStyle( pContainerWindow
->GetExtendedStyle() | WB_EXT_DOCUMENT
);
1350 struct ExecuteGlobals
1352 Reference
< css::document::XEventListener
> xGlobalBroadcaster
;
1353 sal_Bool bRestartRequested
;
1354 sal_Bool bUseSystemFileDialog
;
1355 std::auto_ptr
<SvtLanguageOptions
> pLanguageOptions
;
1356 std::auto_ptr
<SvtPathOptions
> pPathOptions
;
1359 : bRestartRequested( sal_False
)
1360 , bUseSystemFileDialog( sal_True
)
1364 static ExecuteGlobals
* pExecGlobals
= NULL
;
1368 pExecGlobals
= new ExecuteGlobals();
1370 RTL_LOGFILE_CONTEXT( aLog
, "desktop (cd100003) ::Desktop::Main" );
1372 // Remember current context object
1373 com::sun::star::uno::ContextLayer
layer(
1374 com::sun::star::uno::getCurrentContext() );
1376 if ( m_aBootstrapError
!= BE_OK
)
1378 HandleBootstrapErrors( m_aBootstrapError
, m_aBootstrapErrorMessage
);
1379 return EXIT_FAILURE
;
1382 BootstrapStatus eStatus
= GetBootstrapStatus();
1383 if (eStatus
== BS_TERMINATE
) {
1384 return EXIT_SUCCESS
;
1387 // Detect desktop environment - need to do this as early as possible
1388 com::sun::star::uno::setCurrentContext(
1389 new DesktopContext( com::sun::star::uno::getCurrentContext() ) );
1391 CommandLineArgs
& rCmdLineArgs
= GetCommandLineArgs();
1393 #if HAVE_FEATURE_DESKTOP
1394 OUString
aUnknown( rCmdLineArgs
.GetUnknown() );
1395 if ( !aUnknown
.isEmpty() )
1397 displayCmdlineHelp( aUnknown
);
1398 return EXIT_FAILURE
;
1400 if ( rCmdLineArgs
.IsHelp() )
1402 displayCmdlineHelp( OUString() );
1403 return EXIT_SUCCESS
;
1405 if ( rCmdLineArgs
.IsVersion() )
1408 return EXIT_SUCCESS
;
1411 // setup configuration error handling
1412 ConfigurationErrorHandler aConfigErrHandler
;
1413 if (!ShouldSuppressUI(rCmdLineArgs
))
1414 aConfigErrHandler
.activate();
1416 ResMgr::SetReadStringHook( ReplaceStringHookProc
);
1419 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "desktop (lo119109) Desktop::Main { OpenSplashScreen" );
1421 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "desktop (lo119109) Desktop::Main } OpenSplashScreen" );
1423 SetSplashScreenProgress(10);
1425 UserInstall::UserInstallStatus inst_fin
= UserInstall::finalize();
1426 if (inst_fin
!= UserInstall::Ok
&& inst_fin
!= UserInstall::Created
)
1428 OSL_FAIL("userinstall failed");
1429 if ( inst_fin
== UserInstall::E_NoDiskSpace
)
1430 HandleBootstrapErrors(
1431 BE_USERINSTALL_NOTENOUGHDISKSPACE
, OUString() );
1432 else if ( inst_fin
== UserInstall::E_NoWriteAccess
)
1433 HandleBootstrapErrors( BE_USERINSTALL_NOWRITEACCESS
, OUString() );
1435 HandleBootstrapErrors( BE_USERINSTALL_FAILED
, OUString() );
1436 return EXIT_FAILURE
;
1438 // refresh path information
1439 utl::Bootstrap::reloadData();
1440 SetSplashScreenProgress(20);
1442 Reference
< XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
1444 Reference
< XRestartManager
> xRestartManager( OfficeRestartManager::get(xContext
) );
1446 Reference
< XDesktop2
> xDesktop
;
1449 RegisterServices(xContext
);
1451 SetSplashScreenProgress(25);
1453 // check user installation directory for lockfile so we can be sure
1454 // there is no other instance using our data files from a remote host
1455 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "desktop (lo119109) Desktop::Main -> Lockfile" );
1456 m_xLockfile
.reset(new Lockfile
);
1458 #if HAVE_FEATURE_DESKTOP
1459 if ( !rCmdLineArgs
.IsHeadless() && !rCmdLineArgs
.IsInvisible() &&
1460 !rCmdLineArgs
.IsNoLockcheck() && !m_xLockfile
->check( Lockfile_execWarning
))
1462 // Lockfile exists, and user clicked 'no'
1463 return EXIT_FAILURE
;
1465 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "desktop (lo119109) Desktop::Main <- Lockfile" );
1467 // check if accessibility is enabled but not working and allow to quit
1468 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "{ GetEnableATToolSupport" );
1469 if( Application::GetSettings().GetMiscSettings().GetEnableATToolSupport() )
1473 if( !InitAccessBridge( true, bQuitApp
) )
1475 return EXIT_FAILURE
;
1477 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "} GetEnableATToolSupport" );
1480 // terminate if requested...
1481 if( rCmdLineArgs
.IsTerminateAfterInit() )
1482 return EXIT_SUCCESS
;
1484 // Read the common configuration items for optimization purpose
1485 if ( !InitializeConfiguration() )
1486 return EXIT_FAILURE
;
1488 SetSplashScreenProgress(30);
1490 // set static variable to enabled/disable crash reporter
1491 retrieveCrashReporterState();
1492 if ( !isCrashReporterEnabled() )
1494 osl_setErrorReporting( sal_False
);
1495 // disable stack trace feature
1498 // create title string
1499 LanguageTag
aLocale( LANGUAGE_SYSTEM
);
1500 ResMgr
* pLabelResMgr
= ResMgr::SearchCreateResMgr( "ofa", aLocale
);
1501 String aTitle
= pLabelResMgr
? String( ResId( RID_APPTITLE
, *pLabelResMgr
) ) : String();
1502 delete pLabelResMgr
;
1505 //include buildid in non product builds
1506 OUString
aDefault("development");
1507 aTitle
+= OUString(" [");
1508 String
aVerId( utl::Bootstrap::getBuildIdData(aDefault
));
1513 SetDisplayName( aTitle
);
1514 SetSplashScreenProgress(35);
1515 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "{ create SvtPathOptions and SvtLanguageOptions" );
1516 pExecGlobals
->pPathOptions
.reset( new SvtPathOptions
);
1517 SetSplashScreenProgress(40);
1518 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "} create SvtPathOptions and SvtLanguageOptions" );
1520 xDesktop
= css::frame::Desktop::create( xContext
);
1522 // create service for loadin SFX (still needed in startup)
1523 pExecGlobals
->xGlobalBroadcaster
= Reference
< css::document::XEventListener
>
1524 ( css::frame::GlobalEventBroadcaster::create(xContext
), UNO_QUERY_THROW
);
1526 /* ensure existance of a default window that messages can be dispatched to
1527 This is for the benefit of testtool which uses PostUserEvent extensively
1528 and else can deadlock while creating this window from another tread while
1529 the main thread is not yet in the event loop.
1531 Application::GetDefaultDevice();
1533 #if HAVE_FEATURE_EXTENSIONS
1534 // Check if bundled or shared extensions were added /removed
1535 // and process those extensions (has to be done before checking
1536 // the extension dependencies!
1537 SynchronizeExtensionRepositories();
1538 bool bAbort
= CheckExtensionDependencies();
1540 return EXIT_FAILURE
;
1542 if (inst_fin
== UserInstall::Created
)
1544 Migration::migrateSettingsIfNecessary();
1548 // keep a language options instance...
1549 pExecGlobals
->pLanguageOptions
.reset( new SvtLanguageOptions(sal_True
));
1551 css::document::EventObject aEvent
;
1552 aEvent
.EventName
= OUString("OnStartApp");
1553 pExecGlobals
->xGlobalBroadcaster
->notifyEvent(aEvent
);
1555 SetSplashScreenProgress(50);
1557 // Backing Component
1558 sal_Bool bCrashed
= sal_False
;
1559 sal_Bool bExistsRecoveryData
= sal_False
;
1560 sal_Bool bExistsSessionData
= sal_False
;
1562 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "{ impl_checkRecoveryState" );
1563 impl_checkRecoveryState(bCrashed
, bExistsRecoveryData
, bExistsSessionData
);
1564 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "} impl_checkRecoveryState" );
1566 OUString pidfileName
= rCmdLineArgs
.GetPidfileName();
1567 if ( !pidfileName
.isEmpty() )
1569 OUString pidfileURL
;
1571 if ( osl_getFileURLFromSystemPath(pidfileName
.pData
, &pidfileURL
.pData
) == osl_File_E_None
)
1573 osl::File
pidfile( pidfileURL
);
1574 osl::FileBase::RC rc
;
1576 osl::File::remove( pidfileURL
);
1577 if ( (rc
= pidfile
.open( osl_File_OpenFlag_Write
| osl_File_OpenFlag_Create
) ) == osl::File::E_None
)
1579 OString
pid( OString::valueOf( static_cast<sal_Int32
>( GETPID() ) ) );
1580 sal_uInt64 written
= 0;
1581 if ( pidfile
.write(pid
.getStr(), pid
.getLength(), written
) != osl::File::E_None
)
1583 SAL_WARN("desktop", "cannot write pidfile " << pidfile
.getURL());
1589 SAL_WARN("desktop", "cannot open pidfile " << pidfile
.getURL() << osl::FileBase::RC(rc
));
1594 SAL_WARN("desktop", "cannot get pidfile URL from path" << pidfileName
);
1598 if ( rCmdLineArgs
.IsHeadless() )
1600 // Ensure that we use not the system file dialogs as
1601 // headless mode relies on Application::EnableHeadlessMode()
1602 // which does only work for VCL dialogs!!
1603 SvtMiscOptions aMiscOptions
;
1604 pExecGlobals
->bUseSystemFileDialog
= aMiscOptions
.UseSystemFileDialog();
1605 aMiscOptions
.SetUseSystemFileDialog( sal_False
);
1608 pExecGlobals
->bRestartRequested
= xRestartManager
->isRestartRequested(
1610 if ( !pExecGlobals
->bRestartRequested
)
1612 if ((!rCmdLineArgs
.WantsToLoadDocument() && !rCmdLineArgs
.IsInvisible() && !rCmdLineArgs
.IsHeadless() && !rCmdLineArgs
.IsQuickstart()) &&
1613 (SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::E_SSTARTMODULE
)) &&
1614 (!bExistsRecoveryData
) &&
1615 (!bExistsSessionData
) &&
1616 (!Application::AnyInput( VCL_INPUT_APPEVENT
) ))
1618 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "{ create BackingComponent" );
1619 ShowBackingComponent(this);
1620 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "} create BackingComponent" );
1624 catch ( const com::sun::star::lang::WrappedTargetException
& wte
)
1626 com::sun::star::uno::Exception te
;
1627 wte
.TargetException
>>= te
;
1628 FatalError( MakeStartupConfigAccessErrorMessage(wte
.Message
+ te
.Message
) );
1629 return EXIT_FAILURE
;
1631 catch ( const com::sun::star::uno::Exception
& e
)
1633 FatalError( MakeStartupErrorMessage(e
.Message
) );
1634 return EXIT_FAILURE
;
1636 SetSplashScreenProgress(55);
1638 SvtFontSubstConfig().Apply();
1640 SvtTabAppearanceCfg aAppearanceCfg
;
1641 aAppearanceCfg
.SetInitialized();
1642 aAppearanceCfg
.SetApplicationDefaults( this );
1643 SvtAccessibilityOptions aOptions
;
1644 aOptions
.SetVCLSettings();
1645 SetSplashScreenProgress(60);
1647 #if ENABLE_TELEPATHY
1648 bool bListen
= rCmdLineArgs
.IsInvisible();
1649 TeleManager::init( bListen
);
1652 if ( !pExecGlobals
->bRestartRequested
)
1654 Application::SetFilterHdl( LINK( this, Desktop
, ImplInitFilterHdl
) );
1655 sal_Bool bTerminateRequested
= sal_False
;
1657 // Preload function depends on an initialized sfx application!
1658 SetSplashScreenProgress(75);
1660 // use system window dialogs
1661 Application::SetSystemWindowMode( SYSTEMWINDOW_MODE_DIALOG
);
1663 SetSplashScreenProgress(80);
1665 if ( !bTerminateRequested
&& !rCmdLineArgs
.IsInvisible() &&
1666 !rCmdLineArgs
.IsNoQuickstart() )
1667 InitializeQuickstartMode( xContext
);
1669 RTL_LOGFILE_CONTEXT( aLog2
, "desktop (cd100003) createInstance com.sun.star.frame.Desktop" );
1672 if ( xDesktop
.is() )
1673 xDesktop
->addTerminateListener( new OfficeIPCThreadController
);
1674 SetSplashScreenProgress(100);
1676 catch ( const com::sun::star::uno::Exception
& e
)
1678 FatalError( MakeStartupErrorMessage(e
.Message
) );
1679 return EXIT_FAILURE
;
1682 // Release solar mutex just before we wait for our client to connect
1683 int nAcquireCount
= Application::ReleaseSolarMutex();
1685 // Post user event to startup first application component window
1686 // We have to send this OpenClients message short before execute() to
1687 // minimize the risk that this message overtakes type detection contruction!!
1688 Application::PostUserEvent( LINK( this, Desktop
, OpenClients_Impl
) );
1690 // Post event to enable acceptors
1691 Application::PostUserEvent( LINK( this, Desktop
, EnableAcceptors_Impl
) );
1693 // The configuration error handler currently is only for startup
1694 aConfigErrHandler
.deactivate();
1696 // Acquire solar mutex just before we enter our message loop
1697 if ( nAcquireCount
)
1698 Application::AcquireSolarMutex( nAcquireCount
);
1700 // call Application::Execute to process messages in vcl message loop
1701 RTL_LOGFILE_PRODUCT_TRACE( "PERFORMANCE - enter Application::Execute()" );
1706 // The JavaContext contains an interaction handler which is used when
1707 // the creation of a Java Virtual Machine fails
1708 com::sun::star::uno::ContextLayer
layer2(
1709 new svt::JavaContext( com::sun::star::uno::getCurrentContext() ) );
1711 // check whether the shutdown is caused by restart just before entering the Execute
1712 pExecGlobals
->bRestartRequested
= pExecGlobals
->bRestartRequested
||
1713 xRestartManager
->isRestartRequested(true);
1715 if ( !pExecGlobals
->bRestartRequested
)
1717 // if this run of the office is triggered by restart, some additional actions should be done
1718 DoRestartActionsIfNecessary( !rCmdLineArgs
.IsInvisible() && !rCmdLineArgs
.IsNoQuickstart() );
1723 catch(const com::sun::star::document::CorruptedFilterConfigurationException
& exFilterCfg
)
1725 OfficeIPCThread::SetDowning();
1726 FatalError( MakeStartupErrorMessage(exFilterCfg
.Message
) );
1728 catch(const com::sun::star::configuration::CorruptedConfigurationException
& exAnyCfg
)
1730 OfficeIPCThread::SetDowning();
1731 FatalError( MakeStartupErrorMessage(exAnyCfg
.Message
) );
1737 xDesktop
->terminate();
1739 // CAUTION: you do not necessarily get here e.g. on the Mac.
1740 // please put all deinitialization code into doShutdown
1741 return doShutdown();
1744 int Desktop::doShutdown()
1746 if( ! pExecGlobals
)
1747 return EXIT_SUCCESS
;
1749 pExecGlobals
->bRestartRequested
= pExecGlobals
->bRestartRequested
||
1750 OfficeRestartManager::get(comphelper::getProcessComponentContext())->
1751 isRestartRequested(true);
1752 if ( pExecGlobals
->bRestartRequested
)
1755 if (pExecGlobals
->xGlobalBroadcaster
.is())
1757 css::document::EventObject aEvent
;
1758 aEvent
.EventName
= OUString("OnCloseApp");
1759 pExecGlobals
->xGlobalBroadcaster
->notifyEvent(aEvent
);
1762 delete pResMgr
, pResMgr
= NULL
;
1763 // Restore old value
1764 const CommandLineArgs
& rCmdLineArgs
= GetCommandLineArgs();
1765 if ( rCmdLineArgs
.IsHeadless() )
1766 SvtMiscOptions().SetUseSystemFileDialog( pExecGlobals
->bUseSystemFileDialog
);
1768 OUString pidfileName
= rCmdLineArgs
.GetPidfileName();
1769 if ( !pidfileName
.isEmpty() )
1771 OUString pidfileURL
;
1773 if ( osl_getFileURLFromSystemPath(pidfileName
.pData
, &pidfileURL
.pData
) == osl_File_E_None
)
1775 if ( osl::File::remove( pidfileURL
) != osl::FileBase::E_None
)
1777 SAL_WARN("desktop", "shutdown: cannot remove pidfile " << pidfileURL
);
1782 SAL_WARN("desktop", "shutdown: cannot get pidfile URL from path" << pidfileName
);
1786 // remove temp directory
1787 RemoveTemporaryDirectory();
1788 FlushConfiguration();
1789 // The acceptors in the AcceptorMap must be released (in DeregisterServices)
1790 // with the solar mutex unlocked, to avoid deadlock:
1791 sal_uLong nAcquireCount
= Application::ReleaseSolarMutex();
1792 DeregisterServices();
1793 Application::AcquireSolarMutex(nAcquireCount
);
1794 // be sure that path/language options gets destroyed before
1795 // UCB is deinitialized
1796 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "-> dispose path/language options" );
1797 pExecGlobals
->pLanguageOptions
.reset( 0 );
1798 pExecGlobals
->pPathOptions
.reset( 0 );
1799 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "<- dispose path/language options" );
1801 sal_Bool bRR
= pExecGlobals
->bRestartRequested
;
1802 delete pExecGlobals
, pExecGlobals
= NULL
;
1804 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "FINISHED WITH Destop::Main" );
1808 if ( m_rSplashScreen
.is() )
1809 m_rSplashScreen
->reset();
1811 return EXITHELPER_NORMAL_RESTART
;
1813 return EXIT_SUCCESS
;
1816 IMPL_LINK( Desktop
, ImplInitFilterHdl
, ConvertData
*, pData
)
1818 return GraphicFilter::GetGraphicFilter().GetFilterCallback().Call( pData
);
1821 bool Desktop::InitializeConfiguration()
1823 RTL_LOGFILE_CONTEXT( aLog
, "desktop (jb99855) ::InitConfiguration" );
1826 css::configuration::theDefaultProvider::get(
1827 comphelper::getProcessComponentContext() );
1830 catch( ::com::sun::star::lang::ServiceNotRegisteredException
& e
)
1832 this->HandleBootstrapErrors(
1833 Desktop::BE_UNO_SERVICE_CONFIG_MISSING
, e
.Message
);
1835 catch( const ::com::sun::star::configuration::MissingBootstrapFileException
& e
)
1837 OUString
aMsg( CreateErrorMsgString( utl::Bootstrap::MISSING_BOOTSTRAP_FILE
,
1838 e
.BootstrapFileURL
));
1839 HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_USER_INSTALL
, aMsg
);
1841 catch( const ::com::sun::star::configuration::InvalidBootstrapFileException
& e
)
1843 OUString
aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY
,
1844 e
.BootstrapFileURL
));
1845 HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL
, aMsg
);
1847 catch( const ::com::sun::star::configuration::InstallationIncompleteException
& )
1849 OUString aVersionFileURL
;
1851 utl::Bootstrap::PathStatus aPathStatus
= utl::Bootstrap::locateVersionFile( aVersionFileURL
);
1852 if ( aPathStatus
== utl::Bootstrap::PATH_EXISTS
)
1853 aMsg
= CreateErrorMsgString( utl::Bootstrap::MISSING_VERSION_FILE_ENTRY
, aVersionFileURL
);
1855 aMsg
= CreateErrorMsgString( utl::Bootstrap::MISSING_VERSION_FILE
, aVersionFileURL
);
1857 HandleBootstrapPathErrors( ::utl::Bootstrap::MISSING_USER_INSTALL
, aMsg
);
1859 catch ( const com::sun::star::configuration::backend::BackendAccessException
& exception
)
1861 // [cm122549] It is assumed in this case that the message
1862 // coming from InitConfiguration (in fact CreateApplicationConf...)
1863 // is suitable for display directly.
1864 FatalError( MakeStartupErrorMessage( exception
.Message
) );
1866 catch ( const com::sun::star::configuration::backend::BackendSetupException
& exception
)
1868 // [cm122549] It is assumed in this case that the message
1869 // coming from InitConfiguration (in fact CreateApplicationConf...)
1870 // is suitable for display directly.
1871 FatalError( MakeStartupErrorMessage( exception
.Message
) );
1873 catch ( const ::com::sun::star::configuration::CannotLoadConfigurationException
& )
1875 OUString
aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_DATA
,
1877 HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL
, aMsg
);
1879 catch( const ::com::sun::star::uno::Exception
& )
1881 OUString
aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_DATA
,
1883 HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL
, aMsg
);
1888 void Desktop::FlushConfiguration()
1890 css::uno::Reference
< css::util::XFlushable
>(
1891 css::configuration::theDefaultProvider::get(
1892 comphelper::getProcessComponentContext()),
1893 css::uno::UNO_QUERY_THROW
)->flush();
1896 sal_Bool
Desktop::shouldLaunchQuickstart()
1898 sal_Bool bQuickstart
= GetCommandLineArgs().IsQuickstart();
1901 const SfxPoolItem
* pItem
=0;
1902 SfxItemSet
aQLSet(SFX_APP()->GetPool(), SID_ATTR_QUICKLAUNCHER
, SID_ATTR_QUICKLAUNCHER
);
1903 SFX_APP()->GetOptions(aQLSet
);
1904 SfxItemState eState
= aQLSet
.GetItemState(SID_ATTR_QUICKLAUNCHER
, sal_False
, &pItem
);
1905 if (SFX_ITEM_SET
== eState
)
1906 bQuickstart
= ((SfxBoolItem
*)pItem
)->GetValue();
1912 sal_Bool
Desktop::InitializeQuickstartMode( const Reference
< XComponentContext
>& rxContext
)
1916 // the shutdown icon sits in the systray and allows the user to keep
1917 // the office instance running for quicker restart
1918 // this will only be activated if --quickstart was specified on cmdline
1919 RTL_LOGFILE_CONTEXT( aLog
, "desktop (cd100003) createInstance com.sun.star.office.Quickstart" );
1921 sal_Bool bQuickstart
= shouldLaunchQuickstart();
1923 // Try to instantiate quickstart service. This service is not mandatory, so
1924 // do nothing if service is not available
1926 // #i105753# the following if was invented for performance
1927 // unfortunately this broke the Mac behavior which is to always run
1928 // in quickstart mode since Mac applications do not usually quit
1929 // when the last document closes
1934 Sequence
< Any
> aSeq( 1 );
1935 aSeq
[0] <<= bQuickstart
;
1936 Reference
< XComponent
> xQuickstart(
1937 rxContext
->getServiceManager()->createInstanceWithArgumentsAndContext("com.sun.star.office.Quickstart", aSeq
, rxContext
),
1942 catch( const ::com::sun::star::uno::Exception
& )
1948 void Desktop::SystemSettingsChanging( AllSettings
& rSettings
, Window
* )
1950 if ( !SvtTabAppearanceCfg::IsInitialized () )
1953 # define DRAGFULL_OPTION_ALL \
1954 ( DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE \
1955 | DRAGFULL_OPTION_OBJECTMOVE | DRAGFULL_OPTION_OBJECTSIZE \
1956 | DRAGFULL_OPTION_DOCKING | DRAGFULL_OPTION_SPLIT \
1957 | DRAGFULL_OPTION_SCROLL )
1958 # define DRAGFULL_OPTION_NONE ((sal_uInt32)~DRAGFULL_OPTION_ALL)
1960 StyleSettings hStyleSettings
= rSettings
.GetStyleSettings();
1961 MouseSettings hMouseSettings
= rSettings
.GetMouseSettings();
1963 sal_uInt32 nDragFullOptions
= hStyleSettings
.GetDragFullOptions();
1965 SvtTabAppearanceCfg aAppearanceCfg
;
1966 sal_uInt16 nGet
= aAppearanceCfg
.GetDragMode();
1969 case DragFullWindow
:
1970 nDragFullOptions
|= DRAGFULL_OPTION_ALL
;
1973 nDragFullOptions
&= DRAGFULL_OPTION_NONE
;
1980 sal_uInt32 nFollow
= hMouseSettings
.GetFollow();
1981 hMouseSettings
.SetFollow( aAppearanceCfg
.IsMenuMouseFollow() ? (nFollow
|MOUSE_FOLLOW_MENU
) : (nFollow
&~MOUSE_FOLLOW_MENU
));
1982 rSettings
.SetMouseSettings(hMouseSettings
);
1984 SvtMenuOptions aMenuOpt
;
1985 hStyleSettings
.SetUseImagesInMenus(aMenuOpt
.GetMenuIconsState());
1986 hStyleSettings
.SetDragFullOptions( nDragFullOptions
);
1987 rSettings
.SetStyleSettings ( hStyleSettings
);
1990 // ========================================================================
1991 IMPL_LINK_NOARG(Desktop
, AsyncInitFirstRun
)
1993 DoFirstRunInitializations();
1997 // ========================================================================
1999 class ExitTimer
: public Timer
2007 virtual void Timeout()
2013 IMPL_LINK_NOARG(Desktop
, OpenClients_Impl
)
2015 RTL_LOGFILE_PRODUCT_CONTEXT( aLog
, "PERFORMANCE - DesktopOpenClients_Impl()" );
2020 OfficeIPCThread::SetReady();
2022 CloseSplashScreen();
2024 EnableOleAutomation();
2026 if (getenv ("OOO_EXIT_POST_STARTUP"))
2028 } catch (const ::com::sun::star::uno::Exception
&e
) {
2029 String
a( "UNO exception during client open:\n" );
2030 Application::Abort( a
+ e
.Message
);
2036 IMPL_LINK_NOARG(Desktop
, EnableAcceptors_Impl
)
2043 // Registers a COM class factory of the service manager with the windows operating system.
2044 void Desktop::EnableOleAutomation()
2046 RTL_LOGFILE_CONTEXT( aLog
, "desktop (jl97489) ::Desktop::EnableOleAutomation" );
2048 Reference
< XMultiServiceFactory
> xSMgr
= comphelper::getProcessServiceFactory();
2049 xSMgr
->createInstance(OUString("com.sun.star.bridge.OleApplicationRegistration"));
2050 xSMgr
->createInstance(OUString("com.sun.star.comp.ole.EmbedServer"));
2054 void Desktop::PreloadModuleData( const CommandLineArgs
& rArgs
)
2056 Sequence
< com::sun::star::beans::PropertyValue
> args(1);
2057 args
[0].Name
= OUString("Hidden");
2058 args
[0].Value
<<= sal_True
;
2059 Reference
< XDesktop2
> xDesktop
= css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
2061 if ( rArgs
.IsWriter() )
2065 Reference
< ::com::sun::star::util::XCloseable
> xDoc( xDesktop
->loadComponentFromURL( OUString("private:factory/swriter"),
2066 OUString("_blank"), 0, args
), UNO_QUERY_THROW
);
2067 xDoc
->close( sal_False
);
2069 catch ( const com::sun::star::uno::Exception
& )
2073 if ( rArgs
.IsCalc() )
2077 Reference
< ::com::sun::star::util::XCloseable
> xDoc( xDesktop
->loadComponentFromURL( OUString("private:factory/scalc"),
2078 OUString("_blank"), 0, args
), UNO_QUERY_THROW
);
2079 xDoc
->close( sal_False
);
2081 catch ( const com::sun::star::uno::Exception
& )
2085 if ( rArgs
.IsDraw() )
2089 Reference
< ::com::sun::star::util::XCloseable
> xDoc( xDesktop
->loadComponentFromURL( OUString("private:factory/sdraw"),
2090 OUString("_blank"), 0, args
), UNO_QUERY_THROW
);
2091 xDoc
->close( sal_False
);
2093 catch ( const com::sun::star::uno::Exception
& )
2097 if ( rArgs
.IsImpress() )
2101 Reference
< ::com::sun::star::util::XCloseable
> xDoc( xDesktop
->loadComponentFromURL( OUString("private:factory/simpress"),
2102 OUString("_blank"), 0, args
), UNO_QUERY_THROW
);
2103 xDoc
->close( sal_False
);
2105 catch ( const com::sun::star::uno::Exception
& )
2111 void Desktop::PreloadConfigurationData()
2113 Reference
< XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
2114 Reference
< XNameAccess
> xNameAccess
= css::frame::UICommandDescription::create(xContext
);
2116 OUString
aWriterDoc( "com.sun.star.text.TextDocument" );
2117 OUString
aCalcDoc( "com.sun.star.sheet.SpreadsheetDocument" );
2118 OUString
aDrawDoc( "com.sun.star.drawing.DrawingDocument" );
2119 OUString
aImpressDoc( "com.sun.star.presentation.PresentationDocument" );
2121 // preload commands configuration
2123 Reference
< XNameAccess
> xCmdAccess
;
2127 a
= xNameAccess
->getByName( aWriterDoc
);
2129 if ( xCmdAccess
.is() )
2131 xCmdAccess
->getByName( OUString( ".uno:BasicShapes" ));
2132 xCmdAccess
->getByName( OUString( ".uno:EditGlossary" ));
2135 catch ( const ::com::sun::star::uno::Exception
& )
2141 a
= xNameAccess
->getByName( aCalcDoc
);
2143 if ( xCmdAccess
.is() )
2144 xCmdAccess
->getByName( OUString( ".uno:InsertObjectStarMath" ));
2146 catch ( const ::com::sun::star::uno::Exception
& )
2152 // draw and impress share the same configuration file (DrawImpressCommands.xcu)
2153 a
= xNameAccess
->getByName( aDrawDoc
);
2155 if ( xCmdAccess
.is() )
2156 xCmdAccess
->getByName( OUString( ".uno:Polygon" ));
2158 catch ( const ::com::sun::star::uno::Exception
& )
2162 // preload window state configuration
2163 xNameAccess
= WindowStateConfiguration::create( xContext
);
2164 Reference
< XNameAccess
> xWindowAccess
;
2167 a
= xNameAccess
->getByName( aWriterDoc
);
2168 a
>>= xWindowAccess
;
2169 if ( xWindowAccess
.is() )
2170 xWindowAccess
->getByName( OUString( "private:resource/toolbar/standardbar" ));
2172 catch ( const ::com::sun::star::uno::Exception
& )
2177 a
= xNameAccess
->getByName( aCalcDoc
);
2178 a
>>= xWindowAccess
;
2179 if ( xWindowAccess
.is() )
2180 xWindowAccess
->getByName( OUString( "private:resource/toolbar/standardbar" ));
2182 catch ( const ::com::sun::star::uno::Exception
& )
2187 a
= xNameAccess
->getByName( aDrawDoc
);
2188 a
>>= xWindowAccess
;
2189 if ( xWindowAccess
.is() )
2190 xWindowAccess
->getByName( OUString( "private:resource/toolbar/standardbar" ));
2192 catch ( const ::com::sun::star::uno::Exception
& )
2197 a
= xNameAccess
->getByName( aImpressDoc
);
2198 a
>>= xWindowAccess
;
2199 if ( xWindowAccess
.is() )
2200 xWindowAccess
->getByName( OUString( "private:resource/toolbar/standardbar" ));
2202 catch ( const ::com::sun::star::uno::Exception
& )
2206 // preload user interface element factories
2207 Sequence
< Sequence
< css::beans::PropertyValue
> > aSeqSeqPropValue
;
2208 Reference
< XUIElementFactoryManager
> xUIElementFactory
= UIElementFactoryManager::create( xContext
);
2211 aSeqSeqPropValue
= xUIElementFactory
->getRegisteredFactories();
2213 catch ( const ::com::sun::star::uno::Exception
& )
2217 // preload popup menu controller factories. As all controllers are in the same
2218 // configuration file they also get preloaded!
2220 Reference
< css::frame::XUIControllerRegistration
> xPopupMenuControllerFactory
=
2221 css::frame::PopupMenuControllerFactory::create( xContext
);
2224 xPopupMenuControllerFactory
->hasController(
2225 OUString( ".uno:CharFontName" ),
2228 catch ( const ::com::sun::star::uno::Exception
& )
2232 // preload filter configuration
2233 Sequence
< OUString
> aSeq
;
2234 xNameAccess
= Reference
< XNameAccess
>(
2235 xContext
->getServiceManager()->createInstanceWithContext("com.sun.star.document.FilterFactory", xContext
),
2237 if ( xNameAccess
.is() )
2241 aSeq
= xNameAccess
->getElementNames();
2243 catch ( const ::com::sun::star::uno::Exception
& )
2248 // preload type detection configuration
2249 xNameAccess
= Reference
< XNameAccess
>(
2250 xContext
->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", xContext
),
2252 if ( xNameAccess
.is() )
2256 aSeq
= xNameAccess
->getElementNames();
2258 catch ( const ::com::sun::star::uno::Exception
& )
2264 void Desktop::OpenClients()
2267 // check if a document has been recovered - if there is one of if a document was loaded by cmdline, no default document
2268 // should be created
2269 Reference
< XComponent
> xFirst
;
2270 bool bRecovery
= false;
2272 const CommandLineArgs
& rArgs
= GetCommandLineArgs();
2274 Reference
<XMultiServiceFactory
> rFactory
= ::comphelper::getProcessServiceFactory();
2276 if (!rArgs
.IsQuickstart())
2278 sal_Bool bShowHelp
= sal_False
;
2279 OUStringBuffer aHelpURLBuffer
;
2280 if (rArgs
.IsHelpWriter()) {
2281 bShowHelp
= sal_True
;
2282 aHelpURLBuffer
.appendAscii("vnd.sun.star.help://swriter/start");
2283 } else if (rArgs
.IsHelpCalc()) {
2284 bShowHelp
= sal_True
;
2285 aHelpURLBuffer
.appendAscii("vnd.sun.star.help://scalc/start");
2286 } else if (rArgs
.IsHelpDraw()) {
2287 bShowHelp
= sal_True
;
2288 aHelpURLBuffer
.appendAscii("vnd.sun.star.help://sdraw/start");
2289 } else if (rArgs
.IsHelpImpress()) {
2290 bShowHelp
= sal_True
;
2291 aHelpURLBuffer
.appendAscii("vnd.sun.star.help://simpress/start");
2292 } else if (rArgs
.IsHelpBase()) {
2293 bShowHelp
= sal_True
;
2294 aHelpURLBuffer
.appendAscii("vnd.sun.star.help://sdatabase/start");
2295 } else if (rArgs
.IsHelpBasic()) {
2296 bShowHelp
= sal_True
;
2297 aHelpURLBuffer
.appendAscii("vnd.sun.star.help://sbasic/start");
2298 } else if (rArgs
.IsHelpMath()) {
2299 bShowHelp
= sal_True
;
2300 aHelpURLBuffer
.appendAscii("vnd.sun.star.help://smath/start");
2303 aHelpURLBuffer
.appendAscii("?Language=");
2304 aHelpURLBuffer
.append(utl::ConfigManager::getLocale());
2306 aHelpURLBuffer
.appendAscii("&System=UNX");
2308 aHelpURLBuffer
.appendAscii("&System=WIN");
2310 Application::GetHelp()->Start(
2311 aHelpURLBuffer
.makeStringAndClear(), NULL
);
2319 osl_getExecutableFile( &aIniName
.pData
);
2320 sal_uInt32 lastIndex
= aIniName
.lastIndexOf('/');
2321 if ( lastIndex
> 0 )
2323 aIniName
= aIniName
.copy( 0, lastIndex
+1 );
2324 aIniName
+= "perftune";
2332 rtl::Bootstrap
aPerfTuneIniFile( aIniName
);
2334 OUString
aDefault( "0" );
2335 OUString aPreloadData
;
2337 aPerfTuneIniFile
.getFrom( OUString( "QuickstartPreloadConfiguration" ), aPreloadData
, aDefault
);
2338 if ( aPreloadData
== "1" )
2340 if ( rArgs
.IsWriter() ||
2345 PreloadModuleData( rArgs
);
2348 PreloadConfigurationData();
2352 // Disable AutoSave feature in case "--norestore" or a similar command line switch is set on the command line.
2353 // The reason behind: AutoSave/EmergencySave/AutoRecovery share the same data.
2354 // But the require that all documents, which are saved as backup should exists inside
2355 // memory. May be this mechanism will be inconsistent if the configuration exists ...
2356 // but no document inside memory corrspond to this data.
2357 // Furter it's not acceptable to recover such documents without any UI. It can
2358 // need some time, where the user wont see any results and wait for finishing the office startup ...
2359 sal_Bool bAllowRecoveryAndSessionManagement
= (
2360 ( !rArgs
.IsNoRestore() ) &&
2361 ( !rArgs
.IsHeadless() )
2364 if ( ! bAllowRecoveryAndSessionManagement
)
2368 Reference
< XDispatch
> xRecovery
= css::frame::AutoRecovery::create( ::comphelper::getProcessComponentContext() );
2369 Reference
< css::util::XURLTransformer
> xParser
= css::util::URLTransformer::create( ::comphelper::getProcessComponentContext() );
2371 css::util::URL aCmd
;
2372 aCmd
.Complete
= OUString("vnd.sun.star.autorecovery:/disableRecovery");
2373 xParser
->parseStrict(aCmd
);
2375 xRecovery
->dispatch(aCmd
, css::uno::Sequence
< css::beans::PropertyValue
>());
2377 catch(const css::uno::Exception
& e
)
2379 OUString aMessage
= OUString("Could not disable AutoRecovery.\n")
2381 OSL_FAIL(OUStringToOString(aMessage
, RTL_TEXTENCODING_ASCII_US
).getStr());
2386 sal_Bool bCrashed
= sal_False
;
2387 sal_Bool bExistsRecoveryData
= sal_False
;
2388 sal_Bool bExistsSessionData
= sal_False
;
2390 impl_checkRecoveryState(bCrashed
, bExistsRecoveryData
, bExistsSessionData
);
2392 if ( !getenv ("OOO_DISABLE_RECOVERY") &&
2394 ( bExistsRecoveryData
) || // => crash with files => recovery
2395 ( bCrashed
) // => crash without files => error report
2401 bRecovery
= impl_callRecoveryUI(
2402 sal_False
, // false => force recovery instead of emergency save
2404 bExistsRecoveryData
);
2406 catch(const css::uno::Exception
& e
)
2408 OUString aMessage
= OUString("Error during recovery\n")
2410 OSL_FAIL(OUStringToOString(aMessage
, RTL_TEXTENCODING_ASCII_US
).getStr());
2414 Reference
< XSessionManagerListener2
> xSessionListener
;
2417 // specifies whether the UI-interaction on Session shutdown is allowed
2418 sal_Bool bAllowUI
= isUIOnSessionShutdownAllowed();
2420 xSessionListener
= SessionListener::createWithOnQuitFlag(::comphelper::getProcessComponentContext(), bAllowUI
);
2422 // css::beans::NamedValue aProperty( OUString( "AllowUserInteractionOnQuit" ),
2423 // css::uno::makeAny( bAllowUI ) );
2424 // css::uno::Sequence< css::uno::Any > aArgs( 1 );
2425 // aArgs[0] <<= aProperty;
2427 // xSessionListener->initialize( aArgs );
2429 catch(const com::sun::star::uno::Exception
& e
)
2431 OUString aMessage
= OUString("Registration of session listener failed\n")
2433 OSL_FAIL(OUStringToOString(aMessage
, RTL_TEXTENCODING_ASCII_US
).getStr());
2436 if ( !bExistsRecoveryData
)
2438 // session management
2441 Reference
< XSessionManagerListener
> r(xSessionListener
, UNO_QUERY_THROW
);
2444 catch(const com::sun::star::uno::Exception
& e
)
2446 OUString aMessage
= OUString("Error in session management\n")
2448 OSL_FAIL(OUStringToOString(aMessage
, RTL_TEXTENCODING_ASCII_US
).getStr());
2453 OfficeIPCThread::EnableRequests();
2455 ProcessDocumentsRequest
aRequest(rArgs
.getCwdUrl());
2456 aRequest
.pcProcessed
= NULL
;
2458 aRequest
.aOpenList
= rArgs
.GetOpenList();
2459 aRequest
.aViewList
= rArgs
.GetViewList();
2460 aRequest
.aStartList
= rArgs
.GetStartList();
2461 aRequest
.aPrintList
= rArgs
.GetPrintList();
2462 aRequest
.aPrintToList
= rArgs
.GetPrintToList();
2463 aRequest
.aPrinterName
= rArgs
.GetPrinterName();
2464 aRequest
.aForceOpenList
= rArgs
.GetForceOpenList();
2465 aRequest
.aForceNewList
= rArgs
.GetForceNewList();
2466 aRequest
.aConversionList
= rArgs
.GetConversionList();
2467 aRequest
.aConversionParams
= rArgs
.GetConversionParams();
2468 aRequest
.aConversionOut
= rArgs
.GetConversionOut();
2469 aRequest
.aInFilter
= rArgs
.GetInFilter();
2471 if ( !aRequest
.aOpenList
.empty() ||
2472 !aRequest
.aViewList
.empty() ||
2473 !aRequest
.aStartList
.empty() ||
2474 !aRequest
.aPrintList
.empty() ||
2475 !aRequest
.aForceOpenList
.empty() ||
2476 !aRequest
.aForceNewList
.empty() ||
2477 ( !aRequest
.aPrintToList
.empty() && !aRequest
.aPrinterName
.isEmpty() ) ||
2478 !aRequest
.aConversionList
.empty() )
2480 if ( rArgs
.HasModuleParam() )
2482 SvtModuleOptions aOpt
;
2484 // Support command line parameters to start a module (as preselection)
2485 if ( rArgs
.IsWriter() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SWRITER
) )
2486 aRequest
.aModule
= aOpt
.GetFactoryName( SvtModuleOptions::E_WRITER
);
2487 else if ( rArgs
.IsCalc() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SCALC
) )
2488 aRequest
.aModule
= aOpt
.GetFactoryName( SvtModuleOptions::E_CALC
);
2489 else if ( rArgs
.IsImpress() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS
) )
2490 aRequest
.aModule
= aOpt
.GetFactoryName( SvtModuleOptions::E_IMPRESS
);
2491 else if ( rArgs
.IsDraw() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SDRAW
) )
2492 aRequest
.aModule
= aOpt
.GetFactoryName( SvtModuleOptions::E_DRAW
);
2495 // check for printing disabled
2496 if( ( !(aRequest
.aPrintList
.empty() && aRequest
.aPrintToList
.empty()) )
2497 && Application::GetSettings().GetMiscSettings().GetDisablePrinting() )
2499 aRequest
.aPrintList
.clear();
2500 aRequest
.aPrintToList
.clear();
2501 ResMgr
* pDtResMgr
= GetDesktopResManager();
2504 ErrorBox
aBox( NULL
, ResId( EBX_ERR_PRINTDISABLED
, *pDtResMgr
) );
2510 if ( OfficeIPCThread::ExecuteCmdLineRequests( aRequest
) )
2512 // Don't do anything if we have successfully called terminate at desktop:
2517 // no default document if a document was loaded by recovery or by command line or if soffice is used as server
2518 Reference
< XDesktop2
> xDesktop
= css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
2519 Reference
< XElementAccess
> xList( xDesktop
->getFrames(), UNO_QUERY_THROW
);
2520 if ( xList
->hasElements() )
2523 if ( rArgs
.IsQuickstart() || rArgs
.IsInvisible() || Application::AnyInput( VCL_INPUT_APPEVENT
) )
2524 // soffice was started as tray icon ...
2529 ShowBackingComponent(0);
2537 void Desktop::OpenDefault()
2540 RTL_LOGFILE_CONTEXT( aLog
, "desktop (cd100003) ::Desktop::OpenDefault" );
2543 SvtModuleOptions aOpt
;
2545 const CommandLineArgs
& rArgs
= GetCommandLineArgs();
2546 if ( rArgs
.IsNoDefault() ) return;
2547 if ( rArgs
.HasModuleParam() )
2549 // Support new command line parameters to start a module
2550 if ( rArgs
.IsWriter() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SWRITER
) )
2551 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITER
);
2552 else if ( rArgs
.IsCalc() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SCALC
) )
2553 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_CALC
);
2554 else if ( rArgs
.IsImpress() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS
) )
2555 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_IMPRESS
);
2556 else if ( rArgs
.IsBase() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SDATABASE
) )
2557 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DATABASE
);
2558 else if ( rArgs
.IsDraw() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SDRAW
) )
2559 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DRAW
);
2560 else if ( rArgs
.IsMath() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SMATH
) )
2561 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_MATH
);
2562 else if ( rArgs
.IsGlobal() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SWRITER
) )
2563 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITERGLOBAL
);
2564 else if ( rArgs
.IsWeb() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SWRITER
) )
2565 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITERWEB
);
2568 if ( aName
.isEmpty() )
2570 // Old way to create a default document
2571 if ( aOpt
.IsModuleInstalled( SvtModuleOptions::E_SWRITER
) )
2572 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITER
);
2573 else if ( aOpt
.IsModuleInstalled( SvtModuleOptions::E_SCALC
) )
2574 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_CALC
);
2575 else if ( aOpt
.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS
) )
2576 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_IMPRESS
);
2577 else if ( aOpt
.IsModuleInstalled( SvtModuleOptions::E_SDATABASE
) )
2578 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DATABASE
);
2579 else if ( aOpt
.IsModuleInstalled( SvtModuleOptions::E_SDRAW
) )
2580 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DRAW
);
2585 ProcessDocumentsRequest
aRequest(rArgs
.getCwdUrl());
2586 aRequest
.pcProcessed
= NULL
;
2587 aRequest
.aOpenList
.push_back(aName
);
2588 OfficeIPCThread::ExecuteCmdLineRequests( aRequest
);
2593 const String
& rName
, boost::optional
< OUString
> const & cwdUrl
)
2595 // if rName is a vnd.sun.star.script URL do not attempt to parse it
2596 // as INetURLObj does not handle handle there URLs
2597 if (rName
.CompareToAscii("vnd.sun.star.script" , 19) == COMPARE_EQUAL
)
2602 // dont touch file urls, those should already be in internal form
2603 // they won't get better here (#112849#)
2604 if (rName
.CompareToAscii("file:" , 5) == COMPARE_EQUAL
)
2609 if ( rName
.CompareToAscii("service:" , 8) == COMPARE_EQUAL
)
2614 // Add path separator to these directory and make given URL (rName) absolute by using of current working directory
2615 // Attention: "setFinalSlash()" is necessary for calling "smartRel2Abs()"!!!
2616 // Otherwhise last part will be ignored and wrong result will be returned!!!
2617 // "smartRel2Abs()" interpret given URL as file not as path. So he truncate last element to get the base path ...
2618 // But if we add a separator - he doesn't do it anymore.
2621 aObj
.SetURL(*cwdUrl
);
2622 aObj
.setFinalSlash();
2625 // Use the provided parameters for smartRel2Abs to support the usage of '%' in system paths.
2626 // Otherwise this char won't get encoded and we are not able to load such files later,
2628 INetURLObject aURL
= aObj
.smartRel2Abs( rName
, bWasAbsolute
, false, INetURLObject::WAS_ENCODED
,
2629 RTL_TEXTENCODING_UTF8
, true );
2630 String aFileURL
= aURL
.GetMainURL(INetURLObject::NO_DECODE
);
2632 ::osl::FileStatus
aStatus( osl_FileStatus_Mask_FileURL
);
2633 ::osl::DirectoryItem aItem
;
2634 if( ::osl::FileBase::E_None
== ::osl::DirectoryItem::get( aFileURL
, aItem
) &&
2635 ::osl::FileBase::E_None
== aItem
.getFileStatus( aStatus
) )
2636 aFileURL
= aStatus
.getFileURL();
2641 void Desktop::HandleAppEvent( const ApplicationEvent
& rAppEvent
)
2643 switch ( rAppEvent
.GetEvent() )
2645 case ApplicationEvent::TYPE_ACCEPT
:
2646 // every time an accept parameter is used we create an acceptor
2647 // with the corresponding accept-string
2648 createAcceptor(rAppEvent
.GetStringData());
2650 case ApplicationEvent::TYPE_APPEAR
:
2651 if ( !GetCommandLineArgs().IsInvisible() )
2653 Reference
< css::uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
2655 // find active task - the active task is always a visible task
2656 Reference
< css::frame::XDesktop2
> xDesktop
= css::frame::Desktop::create( xContext
);
2657 Reference
< css::frame::XFrame
> xTask
= xDesktop
->getActiveFrame();
2660 // get any task if there is no active one
2661 Reference
< css::container::XIndexAccess
> xList( xDesktop
->getFrames(), ::com::sun::star::uno::UNO_QUERY
);
2662 if ( xList
->getCount() > 0 )
2663 xList
->getByIndex(0) >>= xTask
;
2668 Reference
< com::sun::star::awt::XTopWindow
> xTop( xTask
->getContainerWindow(), UNO_QUERY
);
2673 // no visible task that could be activated found
2674 Reference
< ::com::sun::star::awt::XWindow
> xContainerWindow
;
2675 Reference
< XFrame
> xBackingFrame
= xDesktop
->findFrame(OUString( "_blank" ), 0);
2676 if (xBackingFrame
.is())
2677 xContainerWindow
= xBackingFrame
->getContainerWindow();
2678 if (xContainerWindow
.is())
2680 Reference
< XController
> xStartModule
= StartModule::createWithParentWindow(xContext
, xContainerWindow
);
2681 Reference
< ::com::sun::star::awt::XWindow
> xBackingWin(xStartModule
, UNO_QUERY
);
2682 // Attention: You MUST(!) call setComponent() before you call attachFrame().
2683 // Because the backing component set the property "IsBackingMode" of the frame
2684 // to true inside attachFrame(). But setComponent() reset this state every time ...
2685 xBackingFrame
->setComponent(xBackingWin
, xStartModule
);
2686 xStartModule
->attachFrame(xBackingFrame
);
2687 xContainerWindow
->setVisible(sal_True
);
2689 Window
* pCompWindow
= VCLUnoHelper::GetWindow(xBackingFrame
->getComponentWindow());
2691 pCompWindow
->Update();
2696 case ApplicationEvent::TYPE_HELP
:
2697 displayCmdlineHelp(rAppEvent
.GetStringData());
2699 case ApplicationEvent::TYPE_VERSION
:
2702 case ApplicationEvent::TYPE_OPEN
:
2704 const CommandLineArgs
& rCmdLine
= GetCommandLineArgs();
2705 if ( !rCmdLine
.IsInvisible() && !rCmdLine
.IsTerminateAfterInit() )
2707 ProcessDocumentsRequest
* pDocsRequest
= new ProcessDocumentsRequest(
2708 rCmdLine
.getCwdUrl());
2709 std::vector
<OUString
> const & data(rAppEvent
.GetStringsData());
2710 pDocsRequest
->aOpenList
.insert(
2711 pDocsRequest
->aOpenList
.end(), data
.begin(), data
.end());
2712 pDocsRequest
->pcProcessed
= NULL
;
2714 OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest
);
2715 delete pDocsRequest
;
2719 case ApplicationEvent::TYPE_OPENHELPURL
:
2720 // start help for a specific URL
2721 Application::GetHelp()->Start(rAppEvent
.GetStringData(), NULL
);
2723 case ApplicationEvent::TYPE_PRINT
:
2725 const CommandLineArgs
& rCmdLine
= GetCommandLineArgs();
2726 if ( !rCmdLine
.IsInvisible() && !rCmdLine
.IsTerminateAfterInit() )
2728 ProcessDocumentsRequest
* pDocsRequest
= new ProcessDocumentsRequest(
2729 rCmdLine
.getCwdUrl());
2730 std::vector
<OUString
> const & data(rAppEvent
.GetStringsData());
2731 pDocsRequest
->aPrintList
.insert(
2732 pDocsRequest
->aPrintList
.end(), data
.begin(), data
.end());
2733 pDocsRequest
->pcProcessed
= NULL
;
2735 OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest
);
2736 delete pDocsRequest
;
2740 case ApplicationEvent::TYPE_PRIVATE_DOSHUTDOWN
:
2742 Desktop
* pD
= dynamic_cast<Desktop
*>(GetpApp());
2743 OSL_ENSURE( pD
, "no desktop ?!?" );
2748 case ApplicationEvent::TYPE_QUICKSTART
:
2749 if ( !GetCommandLineArgs().IsInvisible() )
2751 // If the office has been started the second time its command line arguments are sent through a pipe
2752 // connection to the first office. We want to reuse the quickstart option for the first office.
2753 // NOTICE: The quickstart service must be initialized inside the "main thread", so we use the
2754 // application events to do this (they are executed inside main thread)!!!
2755 // Don't start quickstart service if the user specified "--invisible" on the command line!
2756 sal_Bool
bQuickstart( sal_True
);
2757 Sequence
< Any
> aSeq( 1 );
2758 aSeq
[0] <<= bQuickstart
;
2760 Reference
< css::uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
2761 Reference
< XInitialization
> xQuickstart( xContext
->getServiceManager()->createInstanceWithContext("com.sun.star.office.Quickstart", xContext
),
2763 if ( xQuickstart
.is() )
2764 xQuickstart
->initialize( aSeq
);
2767 case ApplicationEvent::TYPE_SHOWDIALOG
:
2768 // ignore all errors here. It's clicking a menu entry only ...
2769 // The user will try it again, in case nothing happens .-)
2772 Reference
< css::uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
2774 Reference
< css::frame::XDesktop2
> xDesktop
= css::frame::Desktop::create( xContext
);
2776 Reference
< css::util::XURLTransformer
> xParser
= css::util::URLTransformer::create(xContext
);
2777 css::util::URL aCommand
;
2778 if( rAppEvent
.GetStringData() == "PREFERENCES" )
2779 aCommand
.Complete
= ".uno:OptionsTreeDialog";
2780 else if( rAppEvent
.GetStringData() == "ABOUT" )
2781 aCommand
.Complete
= ".uno:About";
2782 if( !aCommand
.Complete
.isEmpty() )
2784 xParser
->parseStrict(aCommand
);
2786 css::uno::Reference
< css::frame::XDispatch
> xDispatch
= xDesktop
->queryDispatch(aCommand
, OUString(), 0);
2788 xDispatch
->dispatch(aCommand
, css::uno::Sequence
< css::beans::PropertyValue
>());
2791 catch(const css::uno::Exception
&)
2794 case ApplicationEvent::TYPE_UNACCEPT
:
2795 // try to remove corresponding acceptor
2796 destroyAcceptor(rAppEvent
.GetStringData());
2799 OSL_FAIL("this cannot happen");
2804 void Desktop::OpenSplashScreen()
2806 const CommandLineArgs
&rCmdLine
= GetCommandLineArgs();
2807 sal_Bool bVisible
= sal_False
;
2808 // Show intro only if this is normal start (e.g. no server, no quickstart, no printing )
2809 if ( !rCmdLine
.IsInvisible() &&
2810 !rCmdLine
.IsHeadless() &&
2811 !rCmdLine
.IsQuickstart() &&
2812 !rCmdLine
.IsMinimized() &&
2813 !rCmdLine
.IsNoLogo() &&
2814 !rCmdLine
.IsTerminateAfterInit() &&
2815 rCmdLine
.GetPrintList().empty() &&
2816 rCmdLine
.GetPrintToList().empty() &&
2817 rCmdLine
.GetConversionList().empty() )
2819 // Determine application name from command line parameters
2821 if ( rCmdLine
.IsWriter() )
2822 aAppName
= OUString( "writer" );
2823 else if ( rCmdLine
.IsCalc() )
2824 aAppName
= OUString( "calc" );
2825 else if ( rCmdLine
.IsDraw() )
2826 aAppName
= OUString( "draw" );
2827 else if ( rCmdLine
.IsImpress() )
2828 aAppName
= OUString( "impress" );
2829 else if ( rCmdLine
.IsBase() )
2830 aAppName
= OUString( "base" );
2831 else if ( rCmdLine
.IsGlobal() )
2832 aAppName
= OUString( "global" );
2833 else if ( rCmdLine
.IsMath() )
2834 aAppName
= OUString( "math" );
2835 else if ( rCmdLine
.IsWeb() )
2836 aAppName
= OUString( "web" );
2838 // Which splash to use
2839 OUString
aSplashService( "com.sun.star.office.SplashScreen" );
2840 if ( rCmdLine
.HasSplashPipe() )
2841 aSplashService
= OUString("com.sun.star.office.PipeSplashScreen");
2843 bVisible
= sal_True
;
2844 Sequence
< Any
> aSeq( 2 );
2845 aSeq
[0] <<= bVisible
;
2846 aSeq
[1] <<= aAppName
;
2847 css::uno::Reference
< css::uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
2848 m_rSplashScreen
= Reference
<XStatusIndicator
>(
2849 xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(aSplashService
, aSeq
, xContext
),
2852 if(m_rSplashScreen
.is())
2853 m_rSplashScreen
->start(OUString("SplashScreen"), 100);
2858 void Desktop::SetSplashScreenProgress(sal_Int32 iProgress
)
2860 if(m_rSplashScreen
.is())
2862 m_rSplashScreen
->setValue(iProgress
);
2866 void Desktop::SetSplashScreenText( const OUString
& rText
)
2868 if( m_rSplashScreen
.is() )
2870 m_rSplashScreen
->setText( rText
);
2874 void Desktop::CloseSplashScreen()
2876 if(m_rSplashScreen
.is())
2878 m_rSplashScreen
->end();
2879 m_rSplashScreen
= NULL
;
2883 // ========================================================================
2884 void Desktop::DoFirstRunInitializations()
2888 Reference
< XJobExecutor
> xExecutor
= JobExecutor::create( ::comphelper::getProcessComponentContext() );
2889 xExecutor
->trigger( OUString("onFirstRunInitialization") );
2891 catch(const ::com::sun::star::uno::Exception
&)
2893 OSL_FAIL( "Desktop::DoFirstRunInitializations: caught an exception while trigger job executor ..." );
2897 void Desktop::ShowBackingComponent(Desktop
* progress
)
2899 if (GetCommandLineArgs().IsNoDefault())
2903 Reference
< XComponentContext
> xContext
= comphelper::getProcessComponentContext();
2904 Reference
< XDesktop2
> xDesktop
= css::frame::Desktop::create(xContext
);
2907 progress
->SetSplashScreenProgress(60);
2909 Reference
< XFrame
> xBackingFrame
= xDesktop
->findFrame(OUString( "_blank" ), 0);
2910 Reference
< ::com::sun::star::awt::XWindow
> xContainerWindow
;
2912 if (xBackingFrame
.is())
2913 xContainerWindow
= xBackingFrame
->getContainerWindow();
2914 if (xContainerWindow
.is())
2916 SetDocumentExtendedStyle(xContainerWindow
);
2919 progress
->SetSplashScreenProgress(75);
2922 Reference
< XController
> xStartModule
= StartModule::createWithParentWindow( xContext
, xContainerWindow
);
2923 // Attention: You MUST(!) call setComponent() before you call attachFrame().
2924 // Because the backing component set the property "IsBackingMode" of the frame
2925 // to true inside attachFrame(). But setComponent() reset this state everytimes ...
2926 xBackingFrame
->setComponent(Reference
< XWindow
>(xStartModule
, UNO_QUERY
), xStartModule
);
2929 progress
->SetSplashScreenProgress(100);
2931 xStartModule
->attachFrame(xBackingFrame
);
2934 progress
->CloseSplashScreen();
2936 xContainerWindow
->setVisible(sal_True
);
2940 // ========================================================================
2941 void Desktop::CheckFirstRun( )
2943 if (officecfg::Office::Common::Misc::FirstRun::get())
2945 // this has once been done using a vos timer. this could lead to problems when
2946 // the timer would trigger when the app is already going down again, since VCL would
2947 // no longer be available. Since the old handler would do a postUserEvent to the main
2948 // thread anyway, we can use a vcl timer here to prevent the race contition (#107197#)
2949 m_firstRunTimer
.SetTimeout(3000); // 3 sec.
2950 m_firstRunTimer
.SetTimeoutHdl(LINK(this, Desktop
, AsyncInitFirstRun
));
2951 m_firstRunTimer
.Start();
2954 // Check if Quckstarter should be started (on Windows only)
2955 TCHAR szValue
[8192];
2956 DWORD nValueSize
= sizeof(szValue
);
2958 if ( ERROR_SUCCESS
== RegOpenKey( HKEY_LOCAL_MACHINE
, "Software\\LibreOffice", &hKey
) )
2960 if ( ERROR_SUCCESS
== RegQueryValueEx( hKey
, TEXT("RunQuickstartAtFirstStart"), NULL
, NULL
, (LPBYTE
)szValue
, &nValueSize
) )
2962 sal_Bool
bQuickstart( sal_True
);
2963 sal_Bool
bAutostart( sal_True
);
2964 Sequence
< Any
> aSeq( 2 );
2965 aSeq
[0] <<= bQuickstart
;
2966 aSeq
[1] <<= bAutostart
;
2968 css::uno::Reference
< css::uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
2969 Reference
< XInitialization
> xQuickstart(
2970 xContext
->getServiceManager()->createInstanceWithContext("com.sun.star.office.Quickstart", xContext
),
2972 if ( xQuickstart
.is() )
2973 xQuickstart
->initialize( aSeq
);
2974 RegCloseKey( hKey
);
2979 boost::shared_ptr
< comphelper::ConfigurationChanges
> batch(
2980 comphelper::ConfigurationChanges::create());
2981 officecfg::Office::Common::Misc::FirstRun::set(false, batch
);
2988 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */