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>
21 #include <config_folders.h>
23 #include "sal/config.h"
28 #include "desktop.hrc"
29 #include "cmdlineargs.hxx"
30 #include "cmdlinehelp.hxx"
31 #include "dispatchwatcher.hxx"
32 #include "configinit.hxx"
33 #include "lockfile.hxx"
34 #include "userinstall.hxx"
35 #include "desktopcontext.hxx"
36 #include "exithelper.h"
37 #include "migration.hxx"
39 #include <svl/languageoptions.hxx>
40 #include <svtools/javacontext.hxx>
41 #include <com/sun/star/beans/XPropertySet.hpp>
42 #include <com/sun/star/frame/AutoRecovery.hpp>
43 #include <com/sun/star/frame/GlobalEventBroadcaster.hpp>
44 #include <com/sun/star/frame/SessionListener.hpp>
45 #include <com/sun/star/frame/XSessionManagerListener.hpp>
46 #include <com/sun/star/frame/XSynchronousDispatch.hpp>
47 #include <com/sun/star/document/CorruptedFilterConfigurationException.hpp>
48 #include <com/sun/star/configuration/CorruptedConfigurationException.hpp>
49 #include <com/sun/star/configuration/theDefaultProvider.hpp>
50 #include <com/sun/star/util/XFlushable.hpp>
51 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
52 #include <com/sun/star/frame/Desktop.hpp>
53 #include <com/sun/star/frame/StartModule.hpp>
54 #include <com/sun/star/frame/XComponentLoader.hpp>
55 #include <com/sun/star/view/XPrintable.hpp>
56 #include <com/sun/star/awt/XTopWindow.hpp>
57 #include "com/sun/star/util/URLTransformer.hpp"
58 #include <com/sun/star/util/XURLTransformer.hpp>
59 #include <com/sun/star/util/XCloseable.hpp>
60 #include <com/sun/star/frame/XDispatchProvider.hpp>
61 #include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
62 #include <com/sun/star/configuration/MissingBootstrapFileException.hpp>
63 #include <com/sun/star/configuration/InvalidBootstrapFileException.hpp>
64 #include <com/sun/star/configuration/InstallationIncompleteException.hpp>
65 #include <com/sun/star/configuration/backend/BackendSetupException.hpp>
66 #include <com/sun/star/configuration/backend/BackendAccessException.hpp>
67 #include <com/sun/star/task/JobExecutor.hpp>
68 #include <com/sun/star/task/OfficeRestartManager.hpp>
69 #include <com/sun/star/task/XRestartManager.hpp>
70 #include <com/sun/star/document/XEventListener.hpp>
71 #include <com/sun/star/frame/UICommandDescription.hpp>
72 #include <com/sun/star/ui/UIElementFactoryManager.hpp>
73 #include <com/sun/star/ui/WindowStateConfiguration.hpp>
74 #include <com/sun/star/frame/XUIControllerRegistration.hpp>
75 #include <com/sun/star/frame/ToolbarControllerFactory.hpp>
76 #include <com/sun/star/frame/PopupMenuControllerFactory.hpp>
77 #include <com/sun/star/office/Quickstart.hpp>
79 #include <toolkit/helper/vclunohelper.hxx>
80 #include <comphelper/configuration.hxx>
81 #include <comphelper/processfactory.hxx>
82 #include <unotools/bootstrap.hxx>
83 #include <unotools/configmgr.hxx>
84 #include <unotools/moduleoptions.hxx>
85 #include <officecfg/Office/Common.hxx>
86 #include <officecfg/Office/Recovery.hxx>
87 #include <officecfg/Setup.hxx>
88 #include <osl/file.hxx>
89 #include <osl/process.h>
90 #include <rtl/uri.hxx>
91 #include <unotools/pathoptions.hxx>
92 #include <svtools/miscopt.hxx>
93 #include <svtools/menuoptions.hxx>
94 #include <rtl/bootstrap.hxx>
95 #include <vcl/help.hxx>
96 #include <vcl/msgbox.hxx>
97 #include <sfx2/sfx.hrc>
98 #include <sfx2/app.hxx>
99 #include <svl/itemset.hxx>
100 #include <svl/eitem.hxx>
102 #include <svtools/fontsubstconfig.hxx>
103 #include <svtools/accessibilityoptions.hxx>
104 #include <svtools/apearcfg.hxx>
105 #include <vcl/graphicfilter.hxx>
107 #include "langselect.hxx"
109 #include <config_telepathy.h>
112 #include <tubes/manager.hxx>
117 #include <sys/wait.h>
122 #pragma warning(push, 1) /* disable warnings within system headers */
123 #pragma warning (disable: 4005)
125 #define WIN32_LEAN_AND_MEAN
134 #define GETPID _getpid
137 #define GETPID getpid
140 using namespace ::com::sun::star::awt
;
141 using namespace ::com::sun::star::uno
;
142 using namespace ::com::sun::star::util
;
143 using namespace ::com::sun::star::lang
;
144 using namespace ::com::sun::star::beans
;
145 using namespace ::com::sun::star::frame
;
146 using namespace ::com::sun::star::document
;
147 using namespace ::com::sun::star::view
;
148 using namespace ::com::sun::star::task
;
149 using namespace ::com::sun::star::system
;
150 using namespace ::com::sun::star::ui
;
151 using namespace ::com::sun::star::ui::dialogs
;
152 using namespace ::com::sun::star::container
;
154 ResMgr
* desktop::Desktop::pResMgr
= 0;
159 static oslSignalHandler pSignalHandler
= 0;
160 static sal_Bool _bCrashReporterEnabled
= sal_True
;
164 void removeTree(OUString
const & url
) {
165 osl::Directory
dir(url
);
166 osl::FileBase::RC rc
= dir
.open();
168 case osl::FileBase::E_None
:
170 case osl::FileBase::E_NOENT
:
171 return; //TODO: SAL_WARN if recursive
173 SAL_WARN("desktop.app", "cannot open directory " << dir
.getURL() << ": " << +rc
);
177 osl::DirectoryItem i
;
178 rc
= dir
.getNextItem(i
, SAL_MAX_UINT32
);
179 if (rc
== osl::FileBase::E_NOENT
) {
182 if (rc
!= osl::FileBase::E_None
) {
183 SAL_WARN( "desktop.app", "cannot iterate directory " << dir
.getURL() << ": " << +rc
);
186 osl::FileStatus
stat(
187 osl_FileStatus_Mask_Type
| osl_FileStatus_Mask_FileName
|
188 osl_FileStatus_Mask_FileURL
);
189 rc
= i
.getFileStatus(stat
);
190 if (rc
!= osl::FileBase::E_None
) {
191 SAL_WARN( "desktop.app", "cannot stat in directory " << dir
.getURL() << ": " << +rc
);
194 if (stat
.getFileType() == osl::FileStatus::Directory
) { //TODO: symlinks
195 removeTree(stat
.getFileURL());
197 rc
= osl::File::remove(stat
.getFileURL());
199 rc
!= osl::FileBase::E_None
, "desktop.app",
200 "cannot remove file " << stat
.getFileURL() << ": " << +rc
);
206 rc
!= osl::FileBase::E_None
, "desktop.app",
207 "cannot close directory " << dir
.getURL() << ": " << +rc
);
209 rc
= osl::Directory::remove(url
);
211 rc
!= osl::FileBase::E_None
, "desktop.app",
212 "cannot remove directory " << url
<< ": " << +rc
);
215 // Remove any existing UserInstallation's extensions cache data remaining from
216 // old installations. This addresses at least two problems:
218 // For one, apparently due to the old share/prereg/bundled mechanism (disabled
219 // since 5c47e5f63a79a9e72ec4a100786b1bbf65137ed4 "fdo#51252 Disable copying
220 // share/prereg/bundled to avoid startup crashes"), the user/extensions/bundled
221 // cache could contain corrupted information (like a UNO component registered
222 // twice, which got changed from active to passive registration in one LO
223 // version, but the version of the corresponding bundled extension only
224 // incremented in a later LO version).
226 // For another, UserInstallations have been seen in the wild where no extensions
227 // were installed per-user (any longer), but user/uno_packages/cache/registry/
228 // com.sun.star.comp.deployment.component.PackageRegistryBackend/*.rdb files
229 // contained data nevertheless.
231 // When a LO upgrade is detected (i.e., no user/extensions/buildid or one
232 // containing an old build ID), then user/extensions and
233 // user/uno_packages/cache/registry/
234 // com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc are
235 // removed. That should prevent any problems starting the service manager due
236 // to old junk. Later on in Desktop::SynchronizeExtensionRepositories, the
237 // removed cache data is recreated.
239 // Multiple instances of soffice.bin can execute this code in parallel for a
240 // single UserInstallation, as it is called before OfficeIPCThread is set up.
241 // Therefore, any errors here only lead to SAL_WARNs.
243 // At least in theory, this function could be removed again once no
244 // UserInstallation can be poisoned by old junk any more.
245 bool cleanExtensionCache() {
247 "${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER
"/" SAL_CONFIGFILE("version") ":buildid}");
248 rtl::Bootstrap::expandMacros(buildId
); //TODO: detect failure
250 "${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER
"/" SAL_CONFIGFILE("bootstrap")
251 ":UserInstallation}/user/extensions");
252 rtl::Bootstrap::expandMacros(extDir
); //TODO: detect failure
253 OUString
buildIdFile(extDir
+ "/buildid");
254 osl::File
fr(buildIdFile
);
255 osl::FileBase::RC rc
= fr
.open(osl_File_OpenFlag_Read
);
257 case osl::FileBase::E_None
:
259 rtl::ByteSequence s1
;
260 rc
= fr
.readLine(s1
);
261 osl::FileBase::RC rc2
= fr
.close();
263 rc2
!= osl::FileBase::E_None
, "desktop.app",
264 "cannot close " << fr
.getURL() << " after reading: " << +rc2
);
265 if (rc
!= osl::FileBase::E_None
) {
266 SAL_WARN( "desktop.app", "cannot read from " << fr
.getURL() << ": " << +rc
);
270 reinterpret_cast< char const * >(s1
.getConstArray()),
271 s1
.getLength(), RTL_TEXTENCODING_ISO_8859_1
);
272 // using ISO 8859-1 avoids any and all conversion errors; the
273 // content should only be a subset of ASCII, anyway
279 case osl::FileBase::E_NOENT
:
282 SAL_WARN( "desktop.app", "cannot open " << fr
.getURL() << " for reading: " << +rc
);
287 "$UNO_USER_PACKAGES_CACHE/registry/"
288 "com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc");
289 rtl::Bootstrap::expandMacros(userRcFile
); //TODO: detect failure
290 rc
= osl::File::remove(userRcFile
);
292 rc
!= osl::FileBase::E_None
&& rc
!= osl::FileBase::E_NOENT
, "desktop.app",
293 "cannot remove file " << userRcFile
<< ": " << +rc
);
294 rc
= osl::Directory::createPath(extDir
);
296 rc
!= osl::FileBase::E_None
&& rc
!= osl::FileBase::E_EXIST
, "desktop.app",
297 "cannot create path " << extDir
<< ": " << +rc
);
298 osl::File
fw(buildIdFile
);
299 rc
= fw
.open(osl_File_OpenFlag_Write
| osl_File_OpenFlag_Create
);
300 if (rc
!= osl::FileBase::E_None
) {
301 SAL_WARN( "desktop.app", "cannot open " << fw
.getURL() << " for writing: " << +rc
);
304 OString
buf(OUStringToOString(buildId
, RTL_TEXTENCODING_UTF8
));
305 // using UTF-8 avoids almost all conversion errors (and buildid
306 // containing single surrogate halves should never happen, anyway); the
307 // content should only be a subset of ASCII, anyway
309 rc
= fw
.write(buf
.getStr(), buf
.getLength(), n
);
311 (rc
!= osl::FileBase::E_None
312 || n
!= static_cast< sal_uInt32
>(buf
.getLength())),
314 "cannot write to " << fw
.getURL() << ": " << +rc
<< ", " << n
);
317 rc
!= osl::FileBase::E_None
, "desktop.app",
318 "cannot close " << fw
.getURL() << " after writing: " << +rc
);
322 bool shouldLaunchQuickstart()
324 bool bQuickstart
= Desktop::GetCommandLineArgs().IsQuickstart();
327 const SfxPoolItem
* pItem
=0;
328 SfxItemSet
aQLSet(SFX_APP()->GetPool(), SID_ATTR_QUICKLAUNCHER
, SID_ATTR_QUICKLAUNCHER
);
329 SFX_APP()->GetOptions(aQLSet
);
330 SfxItemState eState
= aQLSet
.GetItemState(SID_ATTR_QUICKLAUNCHER
, sal_False
, &pItem
);
331 if (SFX_ITEM_SET
== eState
)
332 bQuickstart
= ((SfxBoolItem
*)pItem
)->GetValue();
337 void SetRestartState() {
339 boost::shared_ptr
< comphelper::ConfigurationChanges
> batch(
340 comphelper::ConfigurationChanges::create());
341 officecfg::Setup::Office::OfficeRestartInProgress::set(true, batch
);
343 } catch (css::uno::Exception
& e
) {
344 SAL_WARN("desktop.app", "ignoring Exception \"" << e
.Message
<< "\"");
348 void DoRestartActionsIfNecessary(bool quickstart
) {
351 if (officecfg::Setup::Office::OfficeRestartInProgress::get()) {
352 boost::shared_ptr
< comphelper::ConfigurationChanges
> batch(
353 comphelper::ConfigurationChanges::create());
354 officecfg::Setup::Office::OfficeRestartInProgress::set(
357 css::office::Quickstart::createStart(
358 comphelper::getProcessComponentContext(),
359 shouldLaunchQuickstart());
361 } catch (css::uno::Exception
& e
) {
363 "desktop.app", "ignoring Exception \"" << e
.Message
<< "\"");
370 // ----------------------------------------------------------------------------
372 ResMgr
* Desktop::GetDesktopResManager()
374 if ( !Desktop::pResMgr
)
376 // Create desktop resource manager and bootstrap process
377 // was successful. Use default way to get language specific message.
378 if ( Application::IsInExecute() )
379 Desktop::pResMgr
= ResMgr::CreateResMgr("dkt");
381 if ( !Desktop::pResMgr
)
383 // Use VCL to get the correct language specific message as we
384 // are in the bootstrap process and not able to get the installed
386 OUString aUILocaleString
= langselect::getEmergencyLocale();
387 LanguageTag
aLanguageTag( aUILocaleString
);
388 //! ResMgr may modify the Locale for fallback!
389 Desktop::pResMgr
= ResMgr::SearchCreateResMgr( "dkt", aLanguageTag
);
390 AllSettings as
= GetSettings();
391 as
.SetUILanguageTag(aLanguageTag
);
396 return Desktop::pResMgr
;
401 // ----------------------------------------------------------------------------
402 // Get a message string securely. There is a fallback string if the resource
405 OUString
GetMsgString(
406 sal_uInt16 nId
, const OUString
& aFallbackMsg
,
407 bool bAlwaysUseFallbackMsg
= false )
409 if ( !bAlwaysUseFallbackMsg
)
411 ResMgr
* resMgr
= Desktop::GetDesktopResManager();
413 return ResId(nId
, *resMgr
).toString();
418 OUString
MakeStartupErrorMessage(
419 OUString
const & aErrorMessage
, bool bAlwaysUseFallbackMsg
= false )
421 OUStringBuffer
aDiagnosticMessage( 100 );
423 aDiagnosticMessage
.append(
425 STR_BOOTSTRAP_ERR_CANNOT_START
, "The program cannot be started.",
426 bAlwaysUseFallbackMsg
) );
428 aDiagnosticMessage
.appendAscii( "\n" );
430 aDiagnosticMessage
.append( aErrorMessage
);
432 return aDiagnosticMessage
.makeStringAndClear();
435 OUString
MakeStartupConfigAccessErrorMessage( OUString
const & aInternalErrMsg
)
437 OUStringBuffer
aDiagnosticMessage( 200 );
439 ResMgr
* pResMgr
= Desktop::GetDesktopResManager();
441 aDiagnosticMessage
.append( ResId(STR_BOOTSTRAP_ERR_CFG_DATAACCESS
, *pResMgr
).toString() );
443 aDiagnosticMessage
.appendAscii( "The program cannot be started." );
445 if ( !aInternalErrMsg
.isEmpty() )
447 aDiagnosticMessage
.appendAscii( "\n\n" );
449 aDiagnosticMessage
.append( ResId(STR_INTERNAL_ERRMSG
, *pResMgr
).toString() );
451 aDiagnosticMessage
.appendAscii( "The following internal error has occurred:\n\n" );
452 aDiagnosticMessage
.append( aInternalErrMsg
);
455 return aDiagnosticMessage
.makeStringAndClear();
458 //=============================================================================
459 // shows a simple error box with the given message ... but exits from these process !
460 // Fatal errors cant be solved by the process ... nor any recovery can help.
461 // Mostly the installation was damaged and must be repaired manually .. or by calling
463 // On the other side we must make sure that no further actions will be possible within
464 // the current office process ! No pipe requests, no menu/toolbar/shortuct actions
465 // are allowed. Otherwise we will force a "crash inside a crash".
466 // Thats why we have to use a special native message box here which does not use yield :-)
467 //=============================================================================
468 void FatalError(const OUString
& sMessage
)
470 OUString sProductKey
= ::utl::Bootstrap::getProductKey();
471 if ( sProductKey
.isEmpty())
473 osl_getExecutableFile( &sProductKey
.pData
);
475 ::sal_uInt32 nLastIndex
= sProductKey
.lastIndexOf('/');
476 if ( nLastIndex
> 0 )
477 sProductKey
= sProductKey
.copy( nLastIndex
+1 );
480 OUStringBuffer
sTitle (128);
481 sTitle
.append (sProductKey
);
482 sTitle
.appendAscii (" - Fatal Error");
484 Application::ShowNativeErrorBox (sTitle
.makeStringAndClear (), sMessage
);
485 _exit(EXITHELPER_FATAL_ERROR
);
488 static bool ShouldSuppressUI(const CommandLineArgs
& rCmdLine
)
490 return rCmdLine
.IsInvisible() ||
491 rCmdLine
.IsHeadless() ||
492 rCmdLine
.IsQuickstart();
495 struct theCommandLineArgs
: public rtl::Static
< CommandLineArgs
, theCommandLineArgs
> {};
499 CommandLineArgs
& Desktop::GetCommandLineArgs()
501 return theCommandLineArgs::get();
507 : public rtl::Static
< OUString
, BrandName
> {};
509 : public rtl::Static
< OUString
, Version
> {};
510 struct AboutBoxVersion
511 : public rtl::Static
< OUString
, AboutBoxVersion
> {};
512 struct AboutBoxVersionSuffix
513 : public rtl::Static
< OUString
, AboutBoxVersionSuffix
> {};
515 : public rtl::Static
< OUString
, OOOVendor
> {};
517 : public rtl::Static
< OUString
, Extension
> {};
520 OUString
ReplaceStringHookProc( const OUString
& rStr
)
524 if (sRet
.indexOf("%PRODUCT") != -1 || sRet
.indexOf("%ABOUTBOX") != -1)
526 OUString sBrandName
= BrandName::get();
527 OUString sVersion
= Version::get();
528 OUString sBuildId
= utl::Bootstrap::getBuildIdData("development");
529 OUString sAboutBoxVersion
= AboutBoxVersion::get();
530 OUString sAboutBoxVersionSuffix
= AboutBoxVersionSuffix::get();
531 OUString sExtension
= Extension::get();
533 if ( sBrandName
.isEmpty() )
535 sBrandName
= utl::ConfigManager::getProductName();
536 sVersion
= utl::ConfigManager::getProductVersion();
537 sAboutBoxVersion
= utl::ConfigManager::getAboutBoxProductVersion();
538 sAboutBoxVersionSuffix
= utl::ConfigManager::getAboutBoxProductVersionSuffix();
539 if ( sExtension
.isEmpty() )
541 sExtension
= utl::ConfigManager::getProductExtension();
545 sRet
= sRet
.replaceAll( "%PRODUCTNAME", sBrandName
);
546 sRet
= sRet
.replaceAll( "%PRODUCTVERSION", sVersion
);
547 sRet
= sRet
.replaceAll( "%BUILDID", sBuildId
);
548 sRet
= sRet
.replaceAll( "%ABOUTBOXPRODUCTVERSIONSUFFIX", sAboutBoxVersionSuffix
);
549 sRet
= sRet
.replaceAll( "%ABOUTBOXPRODUCTVERSION", sAboutBoxVersion
);
550 sRet
= sRet
.replaceAll( "%PRODUCTEXTENSION", sExtension
);
553 if ( sRet
.indexOf( "%OOOVENDOR" ) != -1 )
555 OUString sOOOVendor
= OOOVendor::get();
557 if ( sOOOVendor
.isEmpty() )
559 sOOOVendor
= utl::ConfigManager::getVendor();
562 sRet
= sRet
.replaceAll( "%OOOVENDOR", sOOOVendor
);
569 : m_bCleanedExtensionCache( false )
570 , m_bServicesRegistered( false )
571 , m_aBootstrapError( BE_OK
)
573 SAL_INFO( "desktop.app", "desktop (cd100003) ::Desktop::Desktop" );
579 TeleManager::finalize();
585 SAL_INFO( "desktop.app", "desktop (cd100003) ::Desktop::Init" );
586 SetBootstrapStatus(BS_OK
);
588 m_bCleanedExtensionCache
= cleanExtensionCache();
590 // We need to have service factory before going further, but see fdo#37195.
591 // Doing this will mmap common.rdb, making it not overwritable on windows,
592 // so this can't happen before the synchronization above. Lets rework this
593 // so that the above is called *from* CreateApplicationServiceManager or
594 // something to enforce this gotcha
597 InitApplicationServiceManager();
599 catch (css::uno::Exception
& e
)
601 SetBootstrapError( BE_UNO_SERVICEMANAGER
, e
.Message
);
604 if ( m_aBootstrapError
== BE_OK
)
608 if (!langselect::prepareLocale())
610 SetBootstrapError( BE_LANGUAGE_MISSING
, OUString() );
613 catch (css::uno::Exception
& e
)
615 SetBootstrapError( BE_OFFICECONFIG_BROKEN
, e
.Message
);
621 const CommandLineArgs
& rCmdLineArgs
= GetCommandLineArgs();
623 // start ipc thread only for non-remote offices
624 SAL_INFO( "desktop.app", "desktop (cd100003) ::OfficeIPCThread::EnableOfficeIPCThread" );
625 OfficeIPCThread::Status aStatus
= OfficeIPCThread::EnableOfficeIPCThread();
626 if ( aStatus
== OfficeIPCThread::IPC_STATUS_PIPE_ERROR
)
628 #if HAVE_FEATURE_MACOSX_SANDBOX
629 // In a sandboxed LO, on 10.8.2 at least, creating the
630 // Unix domain socket fails. Ignore that as hopefully
631 // people running a sandboxed LO won't attempt starting it
632 // from the command-line or otherwise in tricky ways, so
633 // the normal OS X mechanism that prevents multiple
634 // instances of an app from being started should work
636 #elif defined ANDROID
637 // Ignore crack pipe errors on Android, too
639 // Keep using this oddly named BE_PATHINFO_MISSING value
640 // for pipe-related errors on other platforms. Of course
641 // this crack with two (if not more) levels of our own
642 // error codes hiding the actual system error code is
643 // broken, but that is done all over the code, let's leave
644 // re-enginering that to another year.
645 SetBootstrapError( BE_PATHINFO_MISSING
, OUString() );
648 else if ( aStatus
== OfficeIPCThread::IPC_STATUS_BOOTSTRAP_ERROR
)
650 SetBootstrapError( BE_PATHINFO_MISSING
, OUString() );
652 else if ( aStatus
== OfficeIPCThread::IPC_STATUS_2ND_OFFICE
)
654 // 2nd office startup should terminate after sending cmdlineargs through pipe
655 SetBootstrapStatus(BS_TERMINATE
);
657 else if ( !rCmdLineArgs
.GetUnknown().isEmpty()
658 || rCmdLineArgs
.IsHelp() || rCmdLineArgs
.IsVersion() )
660 // disable IPC thread in an instance that is just showing a help message
661 OfficeIPCThread::DisableOfficeIPCThread();
663 pSignalHandler
= osl_addSignalHandler(SalMainPipeExchangeSignal_impl
, NULL
);
667 void Desktop::InitFinished()
669 SAL_INFO( "desktop.app", "desktop (cd100003) ::Desktop::InitFinished" );
674 void Desktop::DeInit()
676 SAL_INFO( "desktop.app", "desktop (cd100003) ::Desktop::DeInit" );
679 // instead of removing of the configManager just let it commit all the changes
680 SAL_INFO( "desktop.app", "<- store config items" );
681 utl::ConfigManager::storeConfigItems();
682 FlushConfiguration();
683 SAL_INFO( "desktop.app", "<- store config items" );
685 // close splashscreen if it's still open
687 Reference
< XComponent
>(
688 comphelper::getProcessComponentContext(), UNO_QUERY_THROW
)->
690 // nobody should get a destroyed service factory...
691 ::comphelper::setProcessServiceFactory( NULL
);
696 OfficeIPCThread::DisableOfficeIPCThread();
698 osl_removeSignalHandler( pSignalHandler
);
699 } catch (const RuntimeException
&) {
700 // someone threw an exception during shutdown
701 // this will leave some garbage behind..
704 SAL_INFO( "desktop.app", "FINISHED WITH Destop::DeInit" );
707 sal_Bool
Desktop::QueryExit()
711 SAL_INFO( "desktop.app", "<- store config items" );
712 utl::ConfigManager::storeConfigItems();
713 SAL_INFO( "desktop.app", "<- store config items" );
715 catch ( const RuntimeException
& )
719 const sal_Char SUSPEND_QUICKSTARTVETO
[] = "SuspendQuickstartVeto";
721 Reference
< XDesktop2
> xDesktop
= css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
722 Reference
< XPropertySet
> xPropertySet(xDesktop
, UNO_QUERY_THROW
);
723 xPropertySet
->setPropertyValue( OUString(SUSPEND_QUICKSTARTVETO
), Any((sal_Bool
)sal_True
) );
725 sal_Bool bExit
= xDesktop
->terminate();
729 xPropertySet
->setPropertyValue( OUString(SUSPEND_QUICKSTARTVETO
), Any((sal_Bool
)sal_False
) );
733 FlushConfiguration();
736 // it is no problem to call DisableOfficeIPCThread() more than once
737 // it also looks to be threadsafe
738 OfficeIPCThread::DisableOfficeIPCThread();
740 catch ( const RuntimeException
& )
751 void Desktop::HandleBootstrapPathErrors( ::utl::Bootstrap::Status aBootstrapStatus
, const OUString
& aDiagnosticMessage
)
753 if ( aBootstrapStatus
!= ::utl::Bootstrap::DATA_OK
)
755 OUString aProductKey
;
758 osl_getExecutableFile( &aProductKey
.pData
);
759 sal_uInt32 lastIndex
= aProductKey
.lastIndexOf('/');
761 aProductKey
= aProductKey
.copy( lastIndex
+1 );
763 aTemp
= ::utl::Bootstrap::getProductKey( aProductKey
);
764 if ( !aTemp
.isEmpty() )
767 OUString
const aMessage(aDiagnosticMessage
+ "\n");
769 ErrorBox
aBootstrapFailedBox( NULL
, WB_OK
, aMessage
);
770 aBootstrapFailedBox
.SetText( aProductKey
);
771 aBootstrapFailedBox
.Execute();
775 // Create a error message depending on bootstrap failure code and an optional file url
776 OUString
Desktop::CreateErrorMsgString(
777 utl::Bootstrap::FailureCode nFailureCode
,
778 const OUString
& aFileURL
)
782 sal_Bool bFileInfo
= sal_True
;
784 switch ( nFailureCode
)
786 /// the shared installation directory could not be located
787 case ::utl::Bootstrap::MISSING_INSTALL_DIRECTORY
:
789 aMsg
= GetMsgString( STR_BOOTSTRAP_ERR_PATH_INVALID
,
790 OUString( "The installation path is not available." ) );
791 bFileInfo
= sal_False
;
795 /// the bootstrap INI file could not be found or read
796 case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE
:
798 aMsg
= GetMsgString( STR_BOOTSTRAP_ERR_FILE_MISSING
,
799 OUString( "The configuration file \"$1\" is missing." ) );
803 /// the bootstrap INI is missing a required entry
804 /// the bootstrap INI contains invalid data
805 case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE_ENTRY
:
806 case ::utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY
:
808 aMsg
= GetMsgString( STR_BOOTSTRAP_ERR_FILE_CORRUPT
,
809 OUString( "The configuration file \"$1\" is corrupt." ) );
813 /// the version locator INI file could not be found or read
814 case ::utl::Bootstrap::MISSING_VERSION_FILE
:
816 aMsg
= GetMsgString( STR_BOOTSTRAP_ERR_FILE_MISSING
,
817 OUString( "The configuration file \"$1\" is missing." ) );
821 /// the version locator INI has no entry for this version
822 case ::utl::Bootstrap::MISSING_VERSION_FILE_ENTRY
:
824 aMsg
= GetMsgString( STR_BOOTSTRAP_ERR_NO_SUPPORT
,
825 OUString( "The main configuration file \"$1\" does not support the current version." ) );
829 /// the user installation directory does not exist
830 case ::utl::Bootstrap::MISSING_USER_DIRECTORY
:
832 aMsg
= GetMsgString( STR_BOOTSTRAP_ERR_DIR_MISSING
,
833 OUString( "The configuration directory \"$1\" is missing." ) );
837 /// some bootstrap data was invalid in unexpected ways
838 case ::utl::Bootstrap::INVALID_BOOTSTRAP_DATA
:
840 aMsg
= GetMsgString( STR_BOOTSTRAP_ERR_INTERNAL
,
841 OUString( "An internal failure occurred." ) );
842 bFileInfo
= sal_False
;
846 case ::utl::Bootstrap::INVALID_VERSION_FILE_ENTRY
:
848 // This needs to be improved, see #i67575#:
849 aMsg
= "Invalid version file entry";
850 bFileInfo
= sal_False
;
854 case ::utl::Bootstrap::NO_FAILURE
:
863 OUString
aMsgString( aMsg
);
865 osl::File::getSystemPathFromFileURL( aFileURL
, aFilePath
);
867 aMsgString
= aMsgString
.replaceFirst( "$1", aFilePath
);
871 return MakeStartupErrorMessage( aMsg
);
874 void Desktop::HandleBootstrapErrors(
875 BootstrapError aBootstrapError
, OUString
const & aErrorMessage
)
877 if ( aBootstrapError
== BE_PATHINFO_MISSING
)
881 utl::Bootstrap::Status aBootstrapStatus
;
882 utl::Bootstrap::FailureCode nFailureCode
;
884 aBootstrapStatus
= ::utl::Bootstrap::checkBootstrapStatus( aBuffer
, nFailureCode
);
885 if ( aBootstrapStatus
!= ::utl::Bootstrap::DATA_OK
)
887 switch ( nFailureCode
)
889 case ::utl::Bootstrap::MISSING_INSTALL_DIRECTORY
:
890 case ::utl::Bootstrap::INVALID_BOOTSTRAP_DATA
:
892 aErrorMsg
= CreateErrorMsgString( nFailureCode
, OUString() );
896 /// the bootstrap INI file could not be found or read
897 /// the bootstrap INI is missing a required entry
898 /// the bootstrap INI contains invalid data
899 case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE_ENTRY
:
900 case ::utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY
:
901 case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE
:
903 OUString aBootstrapFileURL
;
905 utl::Bootstrap::locateBootstrapFile( aBootstrapFileURL
);
906 aErrorMsg
= CreateErrorMsgString( nFailureCode
, aBootstrapFileURL
);
910 /// the version locator INI file could not be found or read
911 /// the version locator INI has no entry for this version
912 /// the version locator INI entry is not a valid directory URL
913 case ::utl::Bootstrap::INVALID_VERSION_FILE_ENTRY
:
914 case ::utl::Bootstrap::MISSING_VERSION_FILE_ENTRY
:
915 case ::utl::Bootstrap::MISSING_VERSION_FILE
:
917 OUString aVersionFileURL
;
919 utl::Bootstrap::locateVersionFile( aVersionFileURL
);
920 aErrorMsg
= CreateErrorMsgString( nFailureCode
, aVersionFileURL
);
924 /// the user installation directory does not exist
925 case ::utl::Bootstrap::MISSING_USER_DIRECTORY
:
927 OUString aUserInstallationURL
;
929 utl::Bootstrap::locateUserInstallation( aUserInstallationURL
);
930 aErrorMsg
= CreateErrorMsgString( nFailureCode
, aUserInstallationURL
);
934 case ::utl::Bootstrap::NO_FAILURE
:
941 HandleBootstrapPathErrors( aBootstrapStatus
, aErrorMsg
);
944 else if ( aBootstrapError
== BE_UNO_SERVICEMANAGER
|| aBootstrapError
== BE_UNO_SERVICE_CONFIG_MISSING
)
946 // Uno service manager is not available. VCL needs a uno service manager to display a message box!!!
947 // Currently we are not able to display a message box with a service manager due to this limitations inside VCL.
949 // When UNO is not properly initialized, all kinds of things can fail
950 // and cause the process to crash (e.g., a call to GetMsgString may
951 // crash when somewhere deep within that call Any::operator <= is used
952 // with a PropertyValue, and no binary UNO type description for
953 // PropertyValue is available). To give the user a hint even if
954 // generating and displaying a message box below crashes, print a
955 // hard-coded message on stderr first:
957 << "The application cannot be started.\n"
958 // STR_BOOTSTRAP_ERR_CANNOT_START
959 << (aBootstrapError
== BE_UNO_SERVICEMANAGER
960 ? "The component manager is not available.\n"
961 // STR_BOOTSTRAP_ERR_NO_SERVICE
962 : "The configuration service is not available.\n");
963 // STR_BOOTSTRAP_ERR_NO_CFG_SERVICE
964 if ( !aErrorMessage
.isEmpty() )
966 std::cerr
<< "(\"" << aErrorMessage
<< "\")\n";
969 // First sentence. We cannot bootstrap office further!
971 OUStringBuffer
aDiagnosticMessage( 100 );
975 if ( aBootstrapError
== BE_UNO_SERVICEMANAGER
)
976 aErrorMsg
= "The service manager is not available.";
978 aErrorMsg
= GetMsgString( STR_BOOTSTRAP_ERR_NO_CFG_SERVICE
,
979 OUString( "The configuration service is not available." ) );
981 aDiagnosticMessage
.append( aErrorMsg
);
982 aDiagnosticMessage
.appendAscii( "\n" );
983 if ( !aErrorMessage
.isEmpty() )
985 aDiagnosticMessage
.appendAscii( "(\"" );
986 aDiagnosticMessage
.append( aErrorMessage
);
987 aDiagnosticMessage
.appendAscii( "\")\n" );
990 // Due to the fact the we haven't a backup applicat.rdb file anymore it is not possible to
991 // repair the installation with the setup executable besides the office executable. Now
992 // we have to ask the user to start the setup on CD/installation directory manually!!
993 OUString
aStartSetupManually( GetMsgString(
994 STR_ASK_START_SETUP_MANUALLY
,
995 OUString( "Start setup application to repair the installation from CD, or the folder containing the installation packages." ),
996 aBootstrapError
== BE_UNO_SERVICEMANAGER
) );
998 aDiagnosticMessage
.append( aStartSetupManually
);
999 aMessage
= MakeStartupErrorMessage(
1000 aDiagnosticMessage
.makeStringAndClear(),
1001 aBootstrapError
== BE_UNO_SERVICEMANAGER
);
1003 FatalError( aMessage
);
1005 else if ( aBootstrapError
== BE_OFFICECONFIG_BROKEN
)
1009 STR_CONFIG_ERR_ACCESS_GENERAL
,
1010 ("A general error occurred while accessing your central"
1011 " configuration.")));
1012 if (!aErrorMessage
.isEmpty()) {
1013 msg
+= "\n(\"" + aErrorMessage
+ "\")";
1015 FatalError(MakeStartupErrorMessage(msg
));
1017 else if ( aBootstrapError
== BE_USERINSTALL_FAILED
)
1020 OUStringBuffer
aDiagnosticMessage( 100 );
1022 aErrorMsg
= GetMsgString( STR_BOOTSTRAP_ERR_USERINSTALL_FAILED
,
1023 OUString( "User installation could not be completed" ) );
1024 aDiagnosticMessage
.append( aErrorMsg
);
1025 aMessage
= MakeStartupErrorMessage( aDiagnosticMessage
.makeStringAndClear() );
1026 FatalError(aMessage
);
1028 else if ( aBootstrapError
== BE_LANGUAGE_MISSING
)
1031 OUStringBuffer
aDiagnosticMessage( 100 );
1033 aErrorMsg
= GetMsgString(
1034 //@@@ FIXME: should use an own resource string => #i36213#
1035 STR_BOOTSTRAP_ERR_LANGUAGE_MISSING
,
1036 OUString( "Language could not be determined." ) );
1037 aDiagnosticMessage
.append( aErrorMsg
);
1038 aMessage
= MakeStartupErrorMessage(
1039 aDiagnosticMessage
.makeStringAndClear() );
1040 FatalError(aMessage
);
1042 else if (( aBootstrapError
== BE_USERINSTALL_NOTENOUGHDISKSPACE
) ||
1043 ( aBootstrapError
== BE_USERINSTALL_NOWRITEACCESS
))
1045 OUString aUserInstallationURL
;
1046 OUString aUserInstallationPath
;
1049 OUStringBuffer
aDiagnosticMessage( 100 );
1051 utl::Bootstrap::locateUserInstallation( aUserInstallationURL
);
1053 if ( aBootstrapError
== BE_USERINSTALL_NOTENOUGHDISKSPACE
)
1054 aErrorMsg
= GetMsgString(
1055 STR_BOOSTRAP_ERR_NOTENOUGHDISKSPACE
,
1056 OUString( "User installation could not be completed due to insufficient free disk space." ) );
1058 aErrorMsg
= GetMsgString(
1059 STR_BOOSTRAP_ERR_NOACCESSRIGHTS
,
1060 OUString( "User installation could not be processed due to missing access rights." ) );
1062 osl::File::getSystemPathFromFileURL( aUserInstallationURL
, aUserInstallationPath
);
1064 aDiagnosticMessage
.append( aErrorMsg
);
1065 aDiagnosticMessage
.append( aUserInstallationPath
);
1066 aMessage
= MakeStartupErrorMessage(
1067 aDiagnosticMessage
.makeStringAndClear() );
1068 FatalError(aMessage
);
1075 void Desktop::retrieveCrashReporterState()
1077 _bCrashReporterEnabled
1078 = officecfg::Office::Recovery::CrashReporter::Enabled::get();
1081 sal_Bool
Desktop::isUIOnSessionShutdownAllowed()
1083 return officecfg::Office::Recovery::SessionShutdown::DocumentStoreUIEnabled
1087 //-----------------------------------------------
1088 /** @short check if crash reporter feature is enabled or
1091 sal_Bool
Desktop::isCrashReporterEnabled()
1093 return _bCrashReporterEnabled
;
1096 //-----------------------------------------------
1097 /** @short check if recovery must be started or not.
1099 @param bCrashed [boolean ... out!]
1100 the office crashed last times.
1101 But may be there are no recovery data.
1102 Useful to trigger the error report tool without
1103 showing the recovery UI.
1105 @param bRecoveryDataExists [boolean ... out!]
1106 there exists some recovery data.
1108 @param bSessionDataExists [boolean ... out!]
1109 there exists some session data.
1110 Because the user may be logged out last time from it's
1113 void impl_checkRecoveryState(sal_Bool
& bCrashed
,
1114 sal_Bool
& bRecoveryDataExists
,
1115 sal_Bool
& bSessionDataExists
)
1117 bCrashed
= officecfg::Office::Recovery::RecoveryInfo::Crashed::get();
1118 bool elements
= officecfg::Office::Recovery::RecoveryList::get()->
1121 = officecfg::Office::Recovery::RecoveryInfo::SessionData::get();
1122 bRecoveryDataExists
= elements
&& !session
;
1123 bSessionDataExists
= elements
&& session
;
1126 //-----------------------------------------------
1127 /* @short start the recovery wizard.
1129 @param bEmergencySave
1130 differs between EMERGENCY_SAVE and RECOVERY
1132 sal_Bool
impl_callRecoveryUI(sal_Bool bEmergencySave
,
1134 sal_Bool bExistsRecoveryData
)
1136 static OUString
SERVICENAME_RECOVERYUI("com.sun.star.comp.svx.RecoveryUI");
1137 static OUString
COMMAND_EMERGENCYSAVE("vnd.sun.star.autorecovery:/doEmergencySave");
1138 static OUString
COMMAND_RECOVERY("vnd.sun.star.autorecovery:/doAutoRecovery");
1139 static OUString
COMMAND_CRASHREPORT("vnd.sun.star.autorecovery:/doCrashReport");
1141 css::uno::Reference
< css::uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
1143 Reference
< css::frame::XSynchronousDispatch
> xRecoveryUI(
1144 xContext
->getServiceManager()->createInstanceWithContext(SERVICENAME_RECOVERYUI
, xContext
),
1145 css::uno::UNO_QUERY_THROW
);
1147 Reference
< css::util::XURLTransformer
> xURLParser
=
1148 css::util::URLTransformer::create(::comphelper::getProcessComponentContext());
1150 css::util::URL aURL
;
1152 aURL
.Complete
= COMMAND_EMERGENCYSAVE
;
1153 else if (bExistsRecoveryData
)
1154 aURL
.Complete
= COMMAND_RECOVERY
;
1155 else if (bCrashed
&& Desktop::isCrashReporterEnabled() )
1156 aURL
.Complete
= COMMAND_CRASHREPORT
;
1160 xURLParser
->parseStrict(aURL
);
1162 css::uno::Any aRet
= xRecoveryUI
->dispatchWithReturnValue(aURL
, css::uno::Sequence
< css::beans::PropertyValue
>());
1163 sal_Bool bRet
= sal_False
;
1165 return !bEmergencySave
|| bRet
;
1169 * Save all open documents so they will be reopened
1170 * the next time the application is started
1172 * returns sal_True if at least one document could be saved...
1176 sal_Bool
Desktop::SaveTasks()
1178 return impl_callRecoveryUI(
1179 sal_True
, // sal_True => force emergency save
1180 sal_False
, // 2. and 3. param not used if 1. = true!
1186 void restartOnMac(bool passArguments
) {
1188 OfficeIPCThread::DisableOfficeIPCThread();
1189 #if HAVE_FEATURE_MACOSX_SANDBOX
1190 (void) passArguments
; // avoid warnings
1191 ResMgr
*resMgr
= Desktop::GetDesktopResManager();
1192 OUString aMessage
= ResId(STR_LO_MUST_BE_RESTARTED
, *resMgr
).toString();
1194 ErrorBox
aRestartBox( NULL
, WB_OK
, aMessage
);
1195 aRestartBox
.Execute();
1198 OSL_VERIFY(osl_getExecutableFile(&execUrl
.pData
) == osl_Process_E_None
);
1201 if ((osl::FileBase::getSystemPathFromFileURL(execUrl
, execPath
)
1202 != osl::FileBase::E_None
) ||
1203 !execPath
.convertToString(
1204 &execPath8
, osl_getThreadTextEncoding(),
1205 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
|
1206 RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
)))
1210 std::vector
< OString
> args
;
1211 args
.push_back(execPath8
);
1213 if (passArguments
) {
1214 sal_uInt32 n
= osl_getCommandArgCount();
1215 for (sal_uInt32 i
= 0; i
< n
; ++i
) {
1217 OSL_VERIFY(osl_getCommandArg(i
, &arg
.pData
) == osl_Process_E_None
);
1218 if (arg
.match("--accept=")) {
1222 if (!arg
.convertToString(
1223 &arg8
, osl_getThreadTextEncoding(),
1224 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
|
1225 RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
)))
1229 args
.push_back(arg8
);
1232 std::vector
< char const * > argPtrs
;
1233 for (std::vector
< OString
>::iterator
i(args
.begin()); i
!= args
.end();
1236 argPtrs
.push_back(i
->getStr());
1238 argPtrs
.push_back(0);
1239 execv(execPath8
.getStr(), const_cast< char ** >(&argPtrs
[0]));
1240 if (errno
== ENOTSUP
) { // happens when multithreaded on OS X < 10.6
1243 execv(execPath8
.getStr(), const_cast< char ** >(&argPtrs
[0]));
1244 } else if (pid
> 0) {
1245 // Two simultaneously running soffice processes lead to two dock
1246 // icons, so avoid waiting here unless it must be assumed that the
1247 // process invoking soffice itself wants to wait for soffice to
1253 if (waitpid(pid
, &stat
, 0) == pid
&& WIFEXITED(stat
)) {
1254 _exit(WEXITSTATUS(stat
));
1261 (void) passArguments
; // avoid warnings
1267 sal_uInt16
Desktop::Exception(sal_uInt16 nError
)
1269 // protect against recursive calls
1270 static sal_Bool bInException
= sal_False
;
1272 sal_uInt16 nOldMode
= Application::GetSystemWindowMode();
1273 Application::SetSystemWindowMode( nOldMode
& ~SYSTEMWINDOW_MODE_NOAUTOMODE
);
1274 Application::SetDefDialogParent( NULL
);
1278 OUString aDoubleExceptionString
;
1279 Application::Abort( aDoubleExceptionString
);
1282 bInException
= sal_True
;
1283 const CommandLineArgs
& rArgs
= GetCommandLineArgs();
1285 // save all modified documents ... if it's allowed doing so.
1286 sal_Bool bRestart
= sal_False
;
1287 sal_Bool bAllowRecoveryAndSessionManagement
= (
1288 ( !rArgs
.IsNoRestore() ) && // some use cases of office must work without recovery
1289 ( !rArgs
.IsHeadless() ) &&
1290 (( nError
& EXC_MAJORTYPE
) != EXC_DISPLAY
) && // recovery cant work without UI ... but UI layer seams to be the reason for this crash
1291 ( Application::IsInExecute() ) // crashes during startup and shutdown should be ignored (they indicates a corrupt installation ...)
1293 if ( bAllowRecoveryAndSessionManagement
)
1294 bRestart
= SaveTasks();
1296 FlushConfiguration();
1298 switch( nError
& EXC_MAJORTYPE
)
1300 case EXC_RSCNOTLOADED
:
1302 OUString aResExceptionString
;
1303 Application::Abort( aResExceptionString
);
1307 case EXC_SYSOBJNOTCREATED
:
1309 OUString aSysResExceptionString
;
1310 Application::Abort( aSysResExceptionString
);
1316 m_xLockfile
.reset();
1320 OfficeIPCThread::DisableOfficeIPCThread();
1321 if( pSignalHandler
)
1322 osl_removeSignalHandler( pSignalHandler
);
1324 restartOnMac(false);
1325 if ( m_rSplashScreen
.is() )
1326 m_rSplashScreen
->reset();
1328 _exit( EXITHELPER_CRASH_WITH_RESTART
);
1332 Application::Abort( OUString() );
1339 OSL_ASSERT(false); // unreachable
1343 void Desktop::AppEvent( const ApplicationEvent
& rAppEvent
)
1345 HandleAppEvent( rAppEvent
);
1349 struct ExecuteGlobals
1351 Reference
< css::document::XEventListener
> xGlobalBroadcaster
;
1352 sal_Bool bRestartRequested
;
1353 sal_Bool bUseSystemFileDialog
;
1354 std::auto_ptr
<SvtLanguageOptions
> pLanguageOptions
;
1355 std::auto_ptr
<SvtPathOptions
> pPathOptions
;
1358 : bRestartRequested( sal_False
)
1359 , bUseSystemFileDialog( sal_True
)
1363 static ExecuteGlobals
* pExecGlobals
= NULL
;
1367 pExecGlobals
= new ExecuteGlobals();
1369 SAL_INFO( "desktop.app", "desktop (cd100003) ::Desktop::Main" );
1371 // Remember current context object
1372 com::sun::star::uno::ContextLayer
layer(
1373 com::sun::star::uno::getCurrentContext() );
1375 if ( m_aBootstrapError
!= BE_OK
)
1377 HandleBootstrapErrors( m_aBootstrapError
, m_aBootstrapErrorMessage
);
1378 return EXIT_FAILURE
;
1381 BootstrapStatus eStatus
= GetBootstrapStatus();
1382 if (eStatus
== BS_TERMINATE
) {
1383 return EXIT_SUCCESS
;
1386 // Detect desktop environment - need to do this as early as possible
1387 com::sun::star::uno::setCurrentContext(
1388 new DesktopContext( com::sun::star::uno::getCurrentContext() ) );
1390 CommandLineArgs
& rCmdLineArgs
= GetCommandLineArgs();
1392 #if HAVE_FEATURE_DESKTOP
1393 OUString
aUnknown( rCmdLineArgs
.GetUnknown() );
1394 if ( !aUnknown
.isEmpty() )
1396 displayCmdlineHelp( aUnknown
);
1397 return EXIT_FAILURE
;
1399 if ( rCmdLineArgs
.IsHelp() )
1401 displayCmdlineHelp( OUString() );
1402 return EXIT_SUCCESS
;
1404 if ( rCmdLineArgs
.IsVersion() )
1407 return EXIT_SUCCESS
;
1410 // setup configuration error handling
1411 ConfigurationErrorHandler aConfigErrHandler
;
1412 if (!ShouldSuppressUI(rCmdLineArgs
))
1413 aConfigErrHandler
.activate();
1415 ResMgr::SetReadStringHook( ReplaceStringHookProc
);
1418 SAL_INFO( "desktop.app", "desktop (lo119109) Desktop::Main { OpenSplashScreen" );
1420 SAL_INFO( "desktop.app", "desktop (lo119109) Desktop::Main } OpenSplashScreen" );
1422 SetSplashScreenProgress(10);
1424 userinstall::Status inst_fin
= userinstall::finalize();
1425 if (inst_fin
!= userinstall::EXISTED
&& inst_fin
!= userinstall::CREATED
)
1427 SAL_WARN( "desktop.app", "userinstall failed");
1428 if ( inst_fin
== userinstall::ERROR_NO_SPACE
)
1429 HandleBootstrapErrors(
1430 BE_USERINSTALL_NOTENOUGHDISKSPACE
, OUString() );
1431 else if ( inst_fin
== userinstall::ERROR_CANT_WRITE
)
1432 HandleBootstrapErrors( BE_USERINSTALL_NOWRITEACCESS
, OUString() );
1434 HandleBootstrapErrors( BE_USERINSTALL_FAILED
, OUString() );
1435 return EXIT_FAILURE
;
1437 // refresh path information
1438 utl::Bootstrap::reloadData();
1439 SetSplashScreenProgress(20);
1441 Reference
< XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
1443 Reference
< XRestartManager
> xRestartManager( OfficeRestartManager::get(xContext
) );
1445 Reference
< XDesktop2
> xDesktop
;
1448 RegisterServices(xContext
);
1450 SetSplashScreenProgress(25);
1452 // check user installation directory for lockfile so we can be sure
1453 // there is no other instance using our data files from a remote host
1454 SAL_INFO( "desktop.app", "desktop (lo119109) Desktop::Main -> Lockfile" );
1455 m_xLockfile
.reset(new Lockfile
);
1457 #if HAVE_FEATURE_DESKTOP
1458 if ( !rCmdLineArgs
.IsHeadless() && !rCmdLineArgs
.IsInvisible() &&
1459 !rCmdLineArgs
.IsNoLockcheck() && !m_xLockfile
->check( Lockfile_execWarning
))
1461 // Lockfile exists, and user clicked 'no'
1462 return EXIT_FAILURE
;
1464 SAL_INFO( "desktop.app", "desktop (lo119109) Desktop::Main <- Lockfile" );
1466 // check if accessibility is enabled but not working and allow to quit
1467 SAL_INFO( "desktop.app", "{ GetEnableATToolSupport" );
1468 if( Application::GetSettings().GetMiscSettings().GetEnableATToolSupport() )
1472 if( !InitAccessBridge( true, bQuitApp
) )
1474 return EXIT_FAILURE
;
1476 SAL_INFO( "desktop.app", "} GetEnableATToolSupport" );
1479 // terminate if requested...
1480 if( rCmdLineArgs
.IsTerminateAfterInit() )
1481 return EXIT_SUCCESS
;
1483 // Read the common configuration items for optimization purpose
1484 if ( !InitializeConfiguration() )
1485 return EXIT_FAILURE
;
1487 SetSplashScreenProgress(30);
1489 // set static variable to enabled/disable crash reporter
1490 retrieveCrashReporterState();
1491 if ( !isCrashReporterEnabled() )
1493 osl_setErrorReporting( sal_False
);
1494 // disable stack trace feature
1497 // create title string
1498 LanguageTag
aLocale( LANGUAGE_SYSTEM
);
1499 ResMgr
* pLabelResMgr
= ResMgr::SearchCreateResMgr( "ofa", aLocale
);
1500 OUString aTitle
= pLabelResMgr
? ResId(RID_APPTITLE
, *pLabelResMgr
).toString() : OUString();
1501 delete pLabelResMgr
;
1504 //include buildid in non product builds
1505 OUString
aDefault("development");
1507 aTitle
+= utl::Bootstrap::getBuildIdData(aDefault
);
1511 SetDisplayName( aTitle
);
1512 SetSplashScreenProgress(35);
1513 SAL_INFO( "desktop.app", "{ create SvtPathOptions and SvtLanguageOptions" );
1514 pExecGlobals
->pPathOptions
.reset( new SvtPathOptions
);
1515 SetSplashScreenProgress(40);
1516 SAL_INFO( "desktop.app", "} create SvtPathOptions and SvtLanguageOptions" );
1518 xDesktop
= css::frame::Desktop::create( xContext
);
1520 // create service for loadin SFX (still needed in startup)
1521 pExecGlobals
->xGlobalBroadcaster
= Reference
< css::document::XEventListener
>
1522 ( css::frame::GlobalEventBroadcaster::create(xContext
), UNO_QUERY_THROW
);
1524 /* ensure existance of a default window that messages can be dispatched to
1525 This is for the benefit of testtool which uses PostUserEvent extensively
1526 and else can deadlock while creating this window from another tread while
1527 the main thread is not yet in the event loop.
1529 Application::GetDefaultDevice();
1531 #if HAVE_FEATURE_EXTENSIONS
1532 // Check if bundled or shared extensions were added /removed
1533 // and process those extensions (has to be done before checking
1534 // the extension dependencies!
1535 SynchronizeExtensionRepositories();
1536 bool bAbort
= CheckExtensionDependencies();
1538 return EXIT_FAILURE
;
1540 if (inst_fin
== userinstall::CREATED
)
1542 Migration::migrateSettingsIfNecessary();
1546 // keep a language options instance...
1547 pExecGlobals
->pLanguageOptions
.reset( new SvtLanguageOptions(sal_True
));
1549 css::document::EventObject aEvent
;
1550 aEvent
.EventName
= "OnStartApp";
1551 pExecGlobals
->xGlobalBroadcaster
->notifyEvent(aEvent
);
1553 SetSplashScreenProgress(50);
1555 // Backing Component
1556 sal_Bool bCrashed
= sal_False
;
1557 sal_Bool bExistsRecoveryData
= sal_False
;
1558 sal_Bool bExistsSessionData
= sal_False
;
1560 SAL_INFO( "desktop.app", "{ impl_checkRecoveryState" );
1561 impl_checkRecoveryState(bCrashed
, bExistsRecoveryData
, bExistsSessionData
);
1562 SAL_INFO( "desktop.app", "} impl_checkRecoveryState" );
1564 OUString pidfileName
= rCmdLineArgs
.GetPidfileName();
1565 if ( !pidfileName
.isEmpty() )
1567 OUString pidfileURL
;
1569 if ( osl_getFileURLFromSystemPath(pidfileName
.pData
, &pidfileURL
.pData
) == osl_File_E_None
)
1571 osl::File
pidfile( pidfileURL
);
1572 osl::FileBase::RC rc
;
1574 osl::File::remove( pidfileURL
);
1575 if ( (rc
= pidfile
.open( osl_File_OpenFlag_Write
| osl_File_OpenFlag_Create
) ) == osl::File::E_None
)
1577 OString
pid( OString::number( GETPID() ) );
1578 sal_uInt64 written
= 0;
1579 if ( pidfile
.write(pid
.getStr(), pid
.getLength(), written
) != osl::File::E_None
)
1581 SAL_WARN("desktop.app", "cannot write pidfile " << pidfile
.getURL());
1587 SAL_WARN("desktop.app", "cannot open pidfile " << pidfile
.getURL() << osl::FileBase::RC(rc
));
1592 SAL_WARN("desktop.app", "cannot get pidfile URL from path" << pidfileName
);
1596 if ( rCmdLineArgs
.IsHeadless() )
1598 // Ensure that we use not the system file dialogs as
1599 // headless mode relies on Application::EnableHeadlessMode()
1600 // which does only work for VCL dialogs!!
1601 SvtMiscOptions aMiscOptions
;
1602 pExecGlobals
->bUseSystemFileDialog
= aMiscOptions
.UseSystemFileDialog();
1603 aMiscOptions
.SetUseSystemFileDialog( sal_False
);
1606 pExecGlobals
->bRestartRequested
= xRestartManager
->isRestartRequested(
1608 if ( !pExecGlobals
->bRestartRequested
)
1610 if ((!rCmdLineArgs
.WantsToLoadDocument() && !rCmdLineArgs
.IsInvisible() && !rCmdLineArgs
.IsHeadless() && !rCmdLineArgs
.IsQuickstart()) &&
1611 (SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::E_SSTARTMODULE
)) &&
1612 (!bExistsRecoveryData
) &&
1613 (!bExistsSessionData
) &&
1614 (!Application::AnyInput( VCL_INPUT_APPEVENT
) ))
1616 SAL_INFO( "desktop.app", "{ create BackingComponent" );
1617 ShowBackingComponent(this);
1618 SAL_INFO( "desktop.app", "} create BackingComponent" );
1622 catch ( const com::sun::star::lang::WrappedTargetException
& wte
)
1624 com::sun::star::uno::Exception te
;
1625 wte
.TargetException
>>= te
;
1626 FatalError( MakeStartupConfigAccessErrorMessage(wte
.Message
+ te
.Message
) );
1628 catch ( const com::sun::star::uno::Exception
& e
)
1630 FatalError( MakeStartupErrorMessage(e
.Message
) );
1632 SetSplashScreenProgress(55);
1634 SvtFontSubstConfig().Apply();
1636 SvtTabAppearanceCfg aAppearanceCfg
;
1637 aAppearanceCfg
.SetInitialized();
1638 aAppearanceCfg
.SetApplicationDefaults( this );
1639 SvtAccessibilityOptions aOptions
;
1640 aOptions
.SetVCLSettings();
1641 SetSplashScreenProgress(60);
1643 #if ENABLE_TELEPATHY
1644 bool bListen
= rCmdLineArgs
.IsInvisible();
1645 TeleManager::init( bListen
);
1648 if ( !pExecGlobals
->bRestartRequested
)
1650 Application::SetFilterHdl( LINK( this, Desktop
, ImplInitFilterHdl
) );
1651 sal_Bool bTerminateRequested
= sal_False
;
1653 // Preload function depends on an initialized sfx application!
1654 SetSplashScreenProgress(75);
1656 // use system window dialogs
1657 Application::SetSystemWindowMode( SYSTEMWINDOW_MODE_DIALOG
);
1659 SetSplashScreenProgress(80);
1661 if ( !bTerminateRequested
&& !rCmdLineArgs
.IsInvisible() &&
1662 !rCmdLineArgs
.IsNoQuickstart() )
1663 InitializeQuickstartMode( xContext
);
1665 SAL_INFO( "desktop.app", "desktop (cd100003) createInstance com.sun.star.frame.Desktop" );
1668 if ( xDesktop
.is() )
1669 xDesktop
->addTerminateListener( new OfficeIPCThreadController
);
1670 SetSplashScreenProgress(100);
1672 catch ( const com::sun::star::uno::Exception
& e
)
1674 FatalError( MakeStartupErrorMessage(e
.Message
) );
1677 // Release solar mutex just before we wait for our client to connect
1678 int nAcquireCount
= Application::ReleaseSolarMutex();
1680 // Post user event to startup first application component window
1681 // We have to send this OpenClients message short before execute() to
1682 // minimize the risk that this message overtakes type detection contruction!!
1683 Application::PostUserEvent( LINK( this, Desktop
, OpenClients_Impl
) );
1685 // Post event to enable acceptors
1686 Application::PostUserEvent( LINK( this, Desktop
, EnableAcceptors_Impl
) );
1688 // The configuration error handler currently is only for startup
1689 aConfigErrHandler
.deactivate();
1691 // Acquire solar mutex just before we enter our message loop
1692 if ( nAcquireCount
)
1693 Application::AcquireSolarMutex( nAcquireCount
);
1695 // call Application::Execute to process messages in vcl message loop
1696 SAL_INFO( "desktop.app", "PERFORMANCE - enter Application::Execute()" );
1700 #if HAVE_FEATURE_JAVA
1701 // The JavaContext contains an interaction handler which is used when
1702 // the creation of a Java Virtual Machine fails
1703 com::sun::star::uno::ContextLayer
layer2(
1704 new svt::JavaContext( com::sun::star::uno::getCurrentContext() ) );
1706 // check whether the shutdown is caused by restart just before entering the Execute
1707 pExecGlobals
->bRestartRequested
= pExecGlobals
->bRestartRequested
||
1708 xRestartManager
->isRestartRequested(true);
1710 if ( !pExecGlobals
->bRestartRequested
)
1712 // if this run of the office is triggered by restart, some additional actions should be done
1713 DoRestartActionsIfNecessary( !rCmdLineArgs
.IsInvisible() && !rCmdLineArgs
.IsNoQuickstart() );
1718 catch(const com::sun::star::document::CorruptedFilterConfigurationException
& exFilterCfg
)
1720 OfficeIPCThread::SetDowning();
1721 FatalError( MakeStartupErrorMessage(exFilterCfg
.Message
) );
1723 catch(const com::sun::star::configuration::CorruptedConfigurationException
& exAnyCfg
)
1725 OfficeIPCThread::SetDowning();
1726 FatalError( MakeStartupErrorMessage(exAnyCfg
.Message
) );
1728 catch( const ::com::sun::star::uno::Exception
& exUNO
)
1730 OfficeIPCThread::SetDowning();
1731 FatalError( exUNO
.Message
);
1733 catch( const std::exception
& exSTD
)
1735 OfficeIPCThread::SetDowning();
1736 FatalError( OUString::createFromAscii( exSTD
.what()));
1740 OfficeIPCThread::SetDowning();
1741 FatalError( OUString( "Caught Unknown Exception: Aborting!"));
1747 xDesktop
->terminate();
1749 // CAUTION: you do not necessarily get here e.g. on the Mac.
1750 // please put all deinitialization code into doShutdown
1751 return doShutdown();
1754 int Desktop::doShutdown()
1756 if( ! pExecGlobals
)
1757 return EXIT_SUCCESS
;
1759 pExecGlobals
->bRestartRequested
= pExecGlobals
->bRestartRequested
||
1760 OfficeRestartManager::get(comphelper::getProcessComponentContext())->
1761 isRestartRequested(true);
1762 if ( pExecGlobals
->bRestartRequested
)
1765 if (pExecGlobals
->xGlobalBroadcaster
.is())
1767 css::document::EventObject aEvent
;
1768 aEvent
.EventName
= "OnCloseApp";
1769 pExecGlobals
->xGlobalBroadcaster
->notifyEvent(aEvent
);
1772 delete pResMgr
, pResMgr
= NULL
;
1773 // Restore old value
1774 const CommandLineArgs
& rCmdLineArgs
= GetCommandLineArgs();
1775 if ( rCmdLineArgs
.IsHeadless() )
1776 SvtMiscOptions().SetUseSystemFileDialog( pExecGlobals
->bUseSystemFileDialog
);
1778 OUString pidfileName
= rCmdLineArgs
.GetPidfileName();
1779 if ( !pidfileName
.isEmpty() )
1781 OUString pidfileURL
;
1783 if ( osl_getFileURLFromSystemPath(pidfileName
.pData
, &pidfileURL
.pData
) == osl_File_E_None
)
1785 if ( osl::File::remove( pidfileURL
) != osl::FileBase::E_None
)
1787 SAL_WARN("desktop.app", "shutdown: cannot remove pidfile " << pidfileURL
);
1792 SAL_WARN("desktop.app", "shutdown: cannot get pidfile URL from path" << pidfileName
);
1796 // remove temp directory
1797 RemoveTemporaryDirectory();
1798 FlushConfiguration();
1799 // The acceptors in the AcceptorMap must be released (in DeregisterServices)
1800 // with the solar mutex unlocked, to avoid deadlock:
1801 sal_uLong nAcquireCount
= Application::ReleaseSolarMutex();
1802 DeregisterServices();
1803 Application::AcquireSolarMutex(nAcquireCount
);
1804 // be sure that path/language options gets destroyed before
1805 // UCB is deinitialized
1806 SAL_INFO( "desktop.app", "-> dispose path/language options" );
1807 pExecGlobals
->pLanguageOptions
.reset( 0 );
1808 pExecGlobals
->pPathOptions
.reset( 0 );
1809 SAL_INFO( "desktop.app", "<- dispose path/language options" );
1811 sal_Bool bRR
= pExecGlobals
->bRestartRequested
;
1812 delete pExecGlobals
, pExecGlobals
= NULL
;
1814 SAL_INFO( "desktop.app", "FINISHED WITH Destop::Main" );
1818 if ( m_rSplashScreen
.is() )
1819 m_rSplashScreen
->reset();
1821 return EXITHELPER_NORMAL_RESTART
;
1823 return EXIT_SUCCESS
;
1826 IMPL_LINK( Desktop
, ImplInitFilterHdl
, ConvertData
*, pData
)
1828 return GraphicFilter::GetGraphicFilter().GetFilterCallback().Call( pData
);
1831 bool Desktop::InitializeConfiguration()
1833 SAL_INFO( "desktop.app", "desktop (jb99855) ::InitConfiguration" );
1836 css::configuration::theDefaultProvider::get(
1837 comphelper::getProcessComponentContext() );
1840 catch( ::com::sun::star::lang::ServiceNotRegisteredException
& e
)
1842 this->HandleBootstrapErrors(
1843 Desktop::BE_UNO_SERVICE_CONFIG_MISSING
, e
.Message
);
1845 catch( const ::com::sun::star::configuration::MissingBootstrapFileException
& e
)
1847 OUString
aMsg( CreateErrorMsgString( utl::Bootstrap::MISSING_BOOTSTRAP_FILE
,
1848 e
.BootstrapFileURL
));
1849 HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_USER_INSTALL
, aMsg
);
1851 catch( const ::com::sun::star::configuration::InvalidBootstrapFileException
& e
)
1853 OUString
aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY
,
1854 e
.BootstrapFileURL
));
1855 HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL
, aMsg
);
1857 catch( const ::com::sun::star::configuration::InstallationIncompleteException
& )
1859 OUString aVersionFileURL
;
1861 utl::Bootstrap::PathStatus aPathStatus
= utl::Bootstrap::locateVersionFile( aVersionFileURL
);
1862 if ( aPathStatus
== utl::Bootstrap::PATH_EXISTS
)
1863 aMsg
= CreateErrorMsgString( utl::Bootstrap::MISSING_VERSION_FILE_ENTRY
, aVersionFileURL
);
1865 aMsg
= CreateErrorMsgString( utl::Bootstrap::MISSING_VERSION_FILE
, aVersionFileURL
);
1867 HandleBootstrapPathErrors( ::utl::Bootstrap::MISSING_USER_INSTALL
, aMsg
);
1869 catch ( const com::sun::star::configuration::backend::BackendAccessException
& exception
)
1871 // [cm122549] It is assumed in this case that the message
1872 // coming from InitConfiguration (in fact CreateApplicationConf...)
1873 // is suitable for display directly.
1874 FatalError( MakeStartupErrorMessage( exception
.Message
) );
1876 catch ( const com::sun::star::configuration::backend::BackendSetupException
& exception
)
1878 // [cm122549] It is assumed in this case that the message
1879 // coming from InitConfiguration (in fact CreateApplicationConf...)
1880 // is suitable for display directly.
1881 FatalError( MakeStartupErrorMessage( exception
.Message
) );
1883 catch ( const ::com::sun::star::configuration::CannotLoadConfigurationException
& )
1885 OUString
aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_DATA
,
1887 HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL
, aMsg
);
1889 catch( const ::com::sun::star::uno::Exception
& )
1891 OUString
aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_DATA
,
1893 HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL
, aMsg
);
1898 void Desktop::FlushConfiguration()
1900 css::uno::Reference
< css::util::XFlushable
>(
1901 css::configuration::theDefaultProvider::get(
1902 comphelper::getProcessComponentContext()),
1903 css::uno::UNO_QUERY_THROW
)->flush();
1906 sal_Bool
Desktop::InitializeQuickstartMode( const Reference
< XComponentContext
>& rxContext
)
1910 // the shutdown icon sits in the systray and allows the user to keep
1911 // the office instance running for quicker restart
1912 // this will only be activated if --quickstart was specified on cmdline
1913 SAL_INFO( "desktop.app", "desktop (cd100003) createInstance com.sun.star.office.Quickstart" );
1915 sal_Bool bQuickstart
= shouldLaunchQuickstart();
1917 // Try to instantiate quickstart service. This service is not mandatory, so
1918 // do nothing if service is not available
1920 // #i105753# the following if was invented for performance
1921 // unfortunately this broke the Mac behavior which is to always run
1922 // in quickstart mode since Mac applications do not usually quit
1923 // when the last document closes.
1924 // Note that this claim that on OS X we "always run in quickstart mode"
1925 // has nothing to do with (quick) *starting* (i.e. starting automatically
1926 // when the user logs in), though, but with not quitting when no documents
1932 css::office::Quickstart::createStart(rxContext
, bQuickstart
);
1936 catch( const ::com::sun::star::uno::Exception
& )
1942 void Desktop::SystemSettingsChanging( AllSettings
& rSettings
, Window
* )
1944 if ( !SvtTabAppearanceCfg::IsInitialized () )
1947 # define DRAGFULL_OPTION_ALL \
1948 ( DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE \
1949 | DRAGFULL_OPTION_OBJECTMOVE | DRAGFULL_OPTION_OBJECTSIZE \
1950 | DRAGFULL_OPTION_DOCKING | DRAGFULL_OPTION_SPLIT \
1951 | DRAGFULL_OPTION_SCROLL )
1952 # define DRAGFULL_OPTION_NONE ((sal_uInt32)~DRAGFULL_OPTION_ALL)
1954 StyleSettings hStyleSettings
= rSettings
.GetStyleSettings();
1955 MouseSettings hMouseSettings
= rSettings
.GetMouseSettings();
1957 sal_uInt32 nDragFullOptions
= hStyleSettings
.GetDragFullOptions();
1959 SvtTabAppearanceCfg aAppearanceCfg
;
1960 sal_uInt16 nGet
= aAppearanceCfg
.GetDragMode();
1963 case DragFullWindow
:
1964 nDragFullOptions
|= DRAGFULL_OPTION_ALL
;
1967 nDragFullOptions
&= DRAGFULL_OPTION_NONE
;
1974 sal_uInt32 nFollow
= hMouseSettings
.GetFollow();
1975 hMouseSettings
.SetFollow( aAppearanceCfg
.IsMenuMouseFollow() ? (nFollow
|MOUSE_FOLLOW_MENU
) : (nFollow
&~MOUSE_FOLLOW_MENU
));
1976 rSettings
.SetMouseSettings(hMouseSettings
);
1978 SvtMenuOptions aMenuOpt
;
1979 hStyleSettings
.SetUseImagesInMenus(aMenuOpt
.GetMenuIconsState());
1980 hStyleSettings
.SetDragFullOptions( nDragFullOptions
);
1981 rSettings
.SetStyleSettings ( hStyleSettings
);
1984 // ========================================================================
1985 IMPL_LINK_NOARG(Desktop
, AsyncInitFirstRun
)
1987 DoFirstRunInitializations();
1991 // ========================================================================
1993 class ExitTimer
: public Timer
2001 virtual void Timeout()
2007 IMPL_LINK_NOARG(Desktop
, OpenClients_Impl
)
2009 SAL_INFO( "desktop.app", "PERFORMANCE - DesktopOpenClients_Impl()" );
2014 OfficeIPCThread::SetReady();
2016 CloseSplashScreen();
2018 EnableOleAutomation();
2020 if (getenv ("OOO_EXIT_POST_STARTUP"))
2022 } catch (const ::com::sun::star::uno::Exception
&e
) {
2023 OUString
a( "UNO exception during client open:\n" );
2024 Application::Abort( a
+ e
.Message
);
2030 IMPL_LINK_NOARG(Desktop
, EnableAcceptors_Impl
)
2037 // Registers a COM class factory of the service manager with the windows operating system.
2038 void Desktop::EnableOleAutomation()
2040 SAL_INFO( "desktop.app", "desktop (jl97489) ::Desktop::EnableOleAutomation" );
2042 Reference
< XMultiServiceFactory
> xSMgr
= comphelper::getProcessServiceFactory();
2043 xSMgr
->createInstance("com.sun.star.bridge.OleApplicationRegistration");
2044 xSMgr
->createInstance("com.sun.star.comp.ole.EmbedServer");
2048 void Desktop::PreloadModuleData( const CommandLineArgs
& rArgs
)
2050 Sequence
< com::sun::star::beans::PropertyValue
> args(1);
2051 args
[0].Name
= "Hidden";
2052 args
[0].Value
<<= sal_True
;
2053 Reference
< XDesktop2
> xDesktop
= css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
2055 if ( rArgs
.IsWriter() )
2059 Reference
< ::com::sun::star::util::XCloseable
> xDoc( xDesktop
->loadComponentFromURL( OUString("private:factory/swriter"),
2060 OUString("_blank"), 0, args
), UNO_QUERY_THROW
);
2061 xDoc
->close( sal_False
);
2063 catch ( const com::sun::star::uno::Exception
& )
2067 if ( rArgs
.IsCalc() )
2071 Reference
< ::com::sun::star::util::XCloseable
> xDoc( xDesktop
->loadComponentFromURL( OUString("private:factory/scalc"),
2072 OUString("_blank"), 0, args
), UNO_QUERY_THROW
);
2073 xDoc
->close( sal_False
);
2075 catch ( const com::sun::star::uno::Exception
& )
2079 if ( rArgs
.IsDraw() )
2083 Reference
< ::com::sun::star::util::XCloseable
> xDoc( xDesktop
->loadComponentFromURL( OUString("private:factory/sdraw"),
2084 OUString("_blank"), 0, args
), UNO_QUERY_THROW
);
2085 xDoc
->close( sal_False
);
2087 catch ( const com::sun::star::uno::Exception
& )
2091 if ( rArgs
.IsImpress() )
2095 Reference
< ::com::sun::star::util::XCloseable
> xDoc( xDesktop
->loadComponentFromURL( OUString("private:factory/simpress"),
2096 OUString("_blank"), 0, args
), UNO_QUERY_THROW
);
2097 xDoc
->close( sal_False
);
2099 catch ( const com::sun::star::uno::Exception
& )
2105 void Desktop::PreloadConfigurationData()
2107 Reference
< XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
2108 Reference
< XNameAccess
> xNameAccess
= css::frame::UICommandDescription::create(xContext
);
2110 OUString
aWriterDoc( "com.sun.star.text.TextDocument" );
2111 OUString
aCalcDoc( "com.sun.star.sheet.SpreadsheetDocument" );
2112 OUString
aDrawDoc( "com.sun.star.drawing.DrawingDocument" );
2113 OUString
aImpressDoc( "com.sun.star.presentation.PresentationDocument" );
2115 // preload commands configuration
2117 Reference
< XNameAccess
> xCmdAccess
;
2121 a
= xNameAccess
->getByName( aWriterDoc
);
2123 if ( xCmdAccess
.is() )
2125 xCmdAccess
->getByName(".uno:BasicShapes");
2126 xCmdAccess
->getByName(".uno:EditGlossary");
2129 catch ( const ::com::sun::star::uno::Exception
& )
2135 a
= xNameAccess
->getByName( aCalcDoc
);
2137 if ( xCmdAccess
.is() )
2138 xCmdAccess
->getByName(".uno:InsertObjectStarMath");
2140 catch ( const ::com::sun::star::uno::Exception
& )
2146 // draw and impress share the same configuration file (DrawImpressCommands.xcu)
2147 a
= xNameAccess
->getByName( aDrawDoc
);
2149 if ( xCmdAccess
.is() )
2150 xCmdAccess
->getByName(".uno:Polygon");
2152 catch ( const ::com::sun::star::uno::Exception
& )
2156 // preload window state configuration
2157 xNameAccess
= WindowStateConfiguration::create( xContext
);
2158 Reference
< XNameAccess
> xWindowAccess
;
2161 a
= xNameAccess
->getByName( aWriterDoc
);
2162 a
>>= xWindowAccess
;
2163 if ( xWindowAccess
.is() )
2164 xWindowAccess
->getByName("private:resource/toolbar/standardbar");
2166 catch ( const ::com::sun::star::uno::Exception
& )
2171 a
= xNameAccess
->getByName( aCalcDoc
);
2172 a
>>= xWindowAccess
;
2173 if ( xWindowAccess
.is() )
2174 xWindowAccess
->getByName("private:resource/toolbar/standardbar");
2176 catch ( const ::com::sun::star::uno::Exception
& )
2181 a
= xNameAccess
->getByName( aDrawDoc
);
2182 a
>>= xWindowAccess
;
2183 if ( xWindowAccess
.is() )
2184 xWindowAccess
->getByName("private:resource/toolbar/standardbar");
2186 catch ( const ::com::sun::star::uno::Exception
& )
2191 a
= xNameAccess
->getByName( aImpressDoc
);
2192 a
>>= xWindowAccess
;
2193 if ( xWindowAccess
.is() )
2194 xWindowAccess
->getByName("private:resource/toolbar/standardbar");
2196 catch ( const ::com::sun::star::uno::Exception
& )
2200 // preload user interface element factories
2201 Sequence
< Sequence
< css::beans::PropertyValue
> > aSeqSeqPropValue
;
2202 Reference
< XUIElementFactoryManager
> xUIElementFactory
= UIElementFactoryManager::create( xContext
);
2205 aSeqSeqPropValue
= xUIElementFactory
->getRegisteredFactories();
2207 catch ( const ::com::sun::star::uno::Exception
& )
2211 // preload popup menu controller factories. As all controllers are in the same
2212 // configuration file they also get preloaded!
2214 Reference
< css::frame::XUIControllerRegistration
> xPopupMenuControllerFactory
=
2215 css::frame::PopupMenuControllerFactory::create( xContext
);
2218 xPopupMenuControllerFactory
->hasController(
2219 OUString( ".uno:CharFontName" ),
2222 catch ( const ::com::sun::star::uno::Exception
& )
2226 // preload filter configuration
2227 Sequence
< OUString
> aSeq
;
2228 xNameAccess
= Reference
< XNameAccess
>(
2229 xContext
->getServiceManager()->createInstanceWithContext("com.sun.star.document.FilterFactory", xContext
),
2231 if ( xNameAccess
.is() )
2235 aSeq
= xNameAccess
->getElementNames();
2237 catch ( const ::com::sun::star::uno::Exception
& )
2242 // preload type detection configuration
2243 xNameAccess
= Reference
< XNameAccess
>(
2244 xContext
->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", xContext
),
2246 if ( xNameAccess
.is() )
2250 aSeq
= xNameAccess
->getElementNames();
2252 catch ( const ::com::sun::star::uno::Exception
& )
2258 void Desktop::OpenClients()
2261 // check if a document has been recovered - if there is one of if a document was loaded by cmdline, no default document
2262 // should be created
2263 Reference
< XComponent
> xFirst
;
2264 bool bRecovery
= false;
2266 const CommandLineArgs
& rArgs
= GetCommandLineArgs();
2268 if (!rArgs
.IsQuickstart())
2270 sal_Bool bShowHelp
= sal_False
;
2271 OUStringBuffer aHelpURLBuffer
;
2272 if (rArgs
.IsHelpWriter()) {
2273 bShowHelp
= sal_True
;
2274 aHelpURLBuffer
.appendAscii("vnd.sun.star.help://swriter/start");
2275 } else if (rArgs
.IsHelpCalc()) {
2276 bShowHelp
= sal_True
;
2277 aHelpURLBuffer
.appendAscii("vnd.sun.star.help://scalc/start");
2278 } else if (rArgs
.IsHelpDraw()) {
2279 bShowHelp
= sal_True
;
2280 aHelpURLBuffer
.appendAscii("vnd.sun.star.help://sdraw/start");
2281 } else if (rArgs
.IsHelpImpress()) {
2282 bShowHelp
= sal_True
;
2283 aHelpURLBuffer
.appendAscii("vnd.sun.star.help://simpress/start");
2284 } else if (rArgs
.IsHelpBase()) {
2285 bShowHelp
= sal_True
;
2286 aHelpURLBuffer
.appendAscii("vnd.sun.star.help://sdatabase/start");
2287 } else if (rArgs
.IsHelpBasic()) {
2288 bShowHelp
= sal_True
;
2289 aHelpURLBuffer
.appendAscii("vnd.sun.star.help://sbasic/start");
2290 } else if (rArgs
.IsHelpMath()) {
2291 bShowHelp
= sal_True
;
2292 aHelpURLBuffer
.appendAscii("vnd.sun.star.help://smath/start");
2295 aHelpURLBuffer
.appendAscii("?Language=");
2296 aHelpURLBuffer
.append(utl::ConfigManager::getLocale());
2298 aHelpURLBuffer
.appendAscii("&System=UNX");
2300 aHelpURLBuffer
.appendAscii("&System=WIN");
2302 Application::GetHelp()->Start(
2303 aHelpURLBuffer
.makeStringAndClear(), NULL
);
2311 osl_getExecutableFile( &aIniName
.pData
);
2312 sal_uInt32 lastIndex
= aIniName
.lastIndexOf('/');
2313 if ( lastIndex
> 0 )
2315 aIniName
= aIniName
.copy( 0, lastIndex
+1 );
2316 aIniName
+= "perftune";
2324 rtl::Bootstrap
aPerfTuneIniFile( aIniName
);
2326 OUString
aDefault( "0" );
2327 OUString aPreloadData
;
2329 aPerfTuneIniFile
.getFrom( OUString( "QuickstartPreloadConfiguration" ), aPreloadData
, aDefault
);
2330 if ( aPreloadData
== "1" )
2332 if ( rArgs
.IsWriter() ||
2337 PreloadModuleData( rArgs
);
2340 PreloadConfigurationData();
2344 // Disable AutoSave feature in case "--norestore" or a similar command line switch is set on the command line.
2345 // The reason behind: AutoSave/EmergencySave/AutoRecovery share the same data.
2346 // But the require that all documents, which are saved as backup should exists inside
2347 // memory. May be this mechanism will be inconsistent if the configuration exists ...
2348 // but no document inside memory corrspond to this data.
2349 // Furter it's not acceptable to recover such documents without any UI. It can
2350 // need some time, where the user wont see any results and wait for finishing the office startup ...
2351 sal_Bool bAllowRecoveryAndSessionManagement
= (
2352 ( !rArgs
.IsNoRestore() ) &&
2353 ( !rArgs
.IsHeadless() )
2356 if ( ! bAllowRecoveryAndSessionManagement
)
2360 Reference
< XDispatch
> xRecovery
= css::frame::AutoRecovery::create( ::comphelper::getProcessComponentContext() );
2361 Reference
< css::util::XURLTransformer
> xParser
= css::util::URLTransformer::create( ::comphelper::getProcessComponentContext() );
2363 css::util::URL aCmd
;
2364 aCmd
.Complete
= "vnd.sun.star.autorecovery:/disableRecovery";
2365 xParser
->parseStrict(aCmd
);
2367 xRecovery
->dispatch(aCmd
, css::uno::Sequence
< css::beans::PropertyValue
>());
2369 catch(const css::uno::Exception
& e
)
2371 SAL_WARN( "desktop.app", "Could not disable AutoRecovery." << e
.Message
);
2376 sal_Bool bCrashed
= sal_False
;
2377 sal_Bool bExistsRecoveryData
= sal_False
;
2378 sal_Bool bExistsSessionData
= sal_False
;
2380 impl_checkRecoveryState(bCrashed
, bExistsRecoveryData
, bExistsSessionData
);
2382 if ( !getenv ("OOO_DISABLE_RECOVERY") &&
2384 ( bExistsRecoveryData
) || // => crash with files => recovery
2385 ( bCrashed
) // => crash without files => error report
2391 bRecovery
= impl_callRecoveryUI(
2392 sal_False
, // false => force recovery instead of emergency save
2394 bExistsRecoveryData
);
2396 catch(const css::uno::Exception
& e
)
2398 SAL_WARN( "desktop.app", "Error during recovery" << e
.Message
);
2402 Reference
< XSessionManagerListener2
> xSessionListener
;
2405 // specifies whether the UI-interaction on Session shutdown is allowed
2406 sal_Bool bAllowUI
= isUIOnSessionShutdownAllowed();
2408 xSessionListener
= SessionListener::createWithOnQuitFlag(::comphelper::getProcessComponentContext(), bAllowUI
);
2410 // css::beans::NamedValue aProperty( OUString( "AllowUserInteractionOnQuit" ),
2411 // css::uno::makeAny( bAllowUI ) );
2412 // css::uno::Sequence< css::uno::Any > aArgs( 1 );
2413 // aArgs[0] <<= aProperty;
2415 // xSessionListener->initialize( aArgs );
2417 catch(const com::sun::star::uno::Exception
& e
)
2419 SAL_WARN( "desktop.app", "Registration of session listener failed" << e
.Message
);
2422 if ( !bExistsRecoveryData
)
2424 // session management
2427 xSessionListener
->doRestore();
2429 catch(const com::sun::star::uno::Exception
& e
)
2431 SAL_WARN( "desktop.app", "Error in session management" << e
.Message
);
2436 OfficeIPCThread::EnableRequests();
2438 ProcessDocumentsRequest
aRequest(rArgs
.getCwdUrl());
2439 aRequest
.pcProcessed
= NULL
;
2441 aRequest
.aOpenList
= rArgs
.GetOpenList();
2442 aRequest
.aViewList
= rArgs
.GetViewList();
2443 aRequest
.aStartList
= rArgs
.GetStartList();
2444 aRequest
.aPrintList
= rArgs
.GetPrintList();
2445 aRequest
.aPrintToList
= rArgs
.GetPrintToList();
2446 aRequest
.aPrinterName
= rArgs
.GetPrinterName();
2447 aRequest
.aForceOpenList
= rArgs
.GetForceOpenList();
2448 aRequest
.aForceNewList
= rArgs
.GetForceNewList();
2449 aRequest
.aConversionList
= rArgs
.GetConversionList();
2450 aRequest
.aConversionParams
= rArgs
.GetConversionParams();
2451 aRequest
.aConversionOut
= rArgs
.GetConversionOut();
2452 aRequest
.aInFilter
= rArgs
.GetInFilter();
2454 if ( !aRequest
.aOpenList
.empty() ||
2455 !aRequest
.aViewList
.empty() ||
2456 !aRequest
.aStartList
.empty() ||
2457 !aRequest
.aPrintList
.empty() ||
2458 !aRequest
.aForceOpenList
.empty() ||
2459 !aRequest
.aForceNewList
.empty() ||
2460 ( !aRequest
.aPrintToList
.empty() && !aRequest
.aPrinterName
.isEmpty() ) ||
2461 !aRequest
.aConversionList
.empty() )
2463 if ( rArgs
.HasModuleParam() )
2465 SvtModuleOptions aOpt
;
2467 // Support command line parameters to start a module (as preselection)
2468 if ( rArgs
.IsWriter() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SWRITER
) )
2469 aRequest
.aModule
= aOpt
.GetFactoryName( SvtModuleOptions::E_WRITER
);
2470 else if ( rArgs
.IsCalc() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SCALC
) )
2471 aRequest
.aModule
= aOpt
.GetFactoryName( SvtModuleOptions::E_CALC
);
2472 else if ( rArgs
.IsImpress() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS
) )
2473 aRequest
.aModule
= aOpt
.GetFactoryName( SvtModuleOptions::E_IMPRESS
);
2474 else if ( rArgs
.IsDraw() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SDRAW
) )
2475 aRequest
.aModule
= aOpt
.GetFactoryName( SvtModuleOptions::E_DRAW
);
2478 // check for printing disabled
2479 if( ( !(aRequest
.aPrintList
.empty() && aRequest
.aPrintToList
.empty()) )
2480 && Application::GetSettings().GetMiscSettings().GetDisablePrinting() )
2482 aRequest
.aPrintList
.clear();
2483 aRequest
.aPrintToList
.clear();
2484 ResMgr
* pDtResMgr
= GetDesktopResManager();
2487 ErrorBox
aBox( NULL
, ResId( EBX_ERR_PRINTDISABLED
, *pDtResMgr
) );
2493 if ( OfficeIPCThread::ExecuteCmdLineRequests( aRequest
) )
2495 // Don't do anything if we have successfully called terminate at desktop:
2500 // no default document if a document was loaded by recovery or by command line or if soffice is used as server
2501 Reference
< XDesktop2
> xDesktop
= css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
2502 Reference
< XElementAccess
> xList( xDesktop
->getFrames(), UNO_QUERY_THROW
);
2503 if ( xList
->hasElements() )
2506 if ( rArgs
.IsQuickstart() || rArgs
.IsInvisible() || Application::AnyInput( VCL_INPUT_APPEVENT
) )
2507 // soffice was started as tray icon ...
2512 ShowBackingComponent(0);
2520 void Desktop::OpenDefault()
2523 SAL_INFO( "desktop.app", "desktop (cd100003) ::Desktop::OpenDefault" );
2526 SvtModuleOptions aOpt
;
2528 const CommandLineArgs
& rArgs
= GetCommandLineArgs();
2529 if ( rArgs
.IsNoDefault() ) return;
2530 if ( rArgs
.HasModuleParam() )
2532 // Support new command line parameters to start a module
2533 if ( rArgs
.IsWriter() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SWRITER
) )
2534 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITER
);
2535 else if ( rArgs
.IsCalc() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SCALC
) )
2536 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_CALC
);
2537 else if ( rArgs
.IsImpress() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS
) )
2538 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_IMPRESS
);
2539 else if ( rArgs
.IsBase() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SDATABASE
) )
2540 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DATABASE
);
2541 else if ( rArgs
.IsDraw() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SDRAW
) )
2542 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DRAW
);
2543 else if ( rArgs
.IsMath() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SMATH
) )
2544 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_MATH
);
2545 else if ( rArgs
.IsGlobal() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SWRITER
) )
2546 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITERGLOBAL
);
2547 else if ( rArgs
.IsWeb() && aOpt
.IsModuleInstalled( SvtModuleOptions::E_SWRITER
) )
2548 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITERWEB
);
2551 if ( aName
.isEmpty() )
2553 // Old way to create a default document
2554 if ( aOpt
.IsModuleInstalled( SvtModuleOptions::E_SWRITER
) )
2555 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITER
);
2556 else if ( aOpt
.IsModuleInstalled( SvtModuleOptions::E_SCALC
) )
2557 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_CALC
);
2558 else if ( aOpt
.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS
) )
2559 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_IMPRESS
);
2560 else if ( aOpt
.IsModuleInstalled( SvtModuleOptions::E_SDATABASE
) )
2561 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DATABASE
);
2562 else if ( aOpt
.IsModuleInstalled( SvtModuleOptions::E_SDRAW
) )
2563 aName
= aOpt
.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DRAW
);
2568 ProcessDocumentsRequest
aRequest(rArgs
.getCwdUrl());
2569 aRequest
.pcProcessed
= NULL
;
2570 aRequest
.aOpenList
.push_back(aName
);
2571 OfficeIPCThread::ExecuteCmdLineRequests( aRequest
);
2575 OUString
GetURL_Impl(
2576 const OUString
& rName
, boost::optional
< OUString
> const & cwdUrl
)
2578 // if rName is a vnd.sun.star.script URL do not attempt to parse it
2579 // as INetURLObj does not handle handle there URLs
2580 if (rName
.startsWith("vnd.sun.star.script"))
2585 // dont touch file urls, those should already be in internal form
2586 // they won't get better here (#112849#)
2587 if (rName
.startsWith("file:"))
2592 if ( rName
.startsWith("service:"))
2597 // Add path separator to these directory and make given URL (rName) absolute by using of current working directory
2598 // Attention: "setFinalSlash()" is necessary for calling "smartRel2Abs()"!!!
2599 // Otherwhise last part will be ignored and wrong result will be returned!!!
2600 // "smartRel2Abs()" interpret given URL as file not as path. So he truncate last element to get the base path ...
2601 // But if we add a separator - he doesn't do it anymore.
2604 aObj
.SetURL(*cwdUrl
);
2605 aObj
.setFinalSlash();
2608 // Use the provided parameters for smartRel2Abs to support the usage of '%' in system paths.
2609 // Otherwise this char won't get encoded and we are not able to load such files later,
2611 INetURLObject aURL
= aObj
.smartRel2Abs( rName
, bWasAbsolute
, false, INetURLObject::WAS_ENCODED
,
2612 RTL_TEXTENCODING_UTF8
, true );
2613 OUString aFileURL
= aURL
.GetMainURL(INetURLObject::NO_DECODE
);
2615 ::osl::FileStatus
aStatus( osl_FileStatus_Mask_FileURL
);
2616 ::osl::DirectoryItem aItem
;
2617 if( ::osl::FileBase::E_None
== ::osl::DirectoryItem::get( aFileURL
, aItem
) &&
2618 ::osl::FileBase::E_None
== aItem
.getFileStatus( aStatus
) )
2619 aFileURL
= aStatus
.getFileURL();
2624 void Desktop::HandleAppEvent( const ApplicationEvent
& rAppEvent
)
2626 switch ( rAppEvent
.GetEvent() )
2628 case ApplicationEvent::TYPE_ACCEPT
:
2629 // every time an accept parameter is used we create an acceptor
2630 // with the corresponding accept-string
2631 createAcceptor(rAppEvent
.GetStringData());
2633 case ApplicationEvent::TYPE_APPEAR
:
2634 if ( !GetCommandLineArgs().IsInvisible() )
2636 Reference
< css::uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
2638 // find active task - the active task is always a visible task
2639 Reference
< css::frame::XDesktop2
> xDesktop
= css::frame::Desktop::create( xContext
);
2640 Reference
< css::frame::XFrame
> xTask
= xDesktop
->getActiveFrame();
2643 // get any task if there is no active one
2644 Reference
< css::container::XIndexAccess
> xList( xDesktop
->getFrames(), ::com::sun::star::uno::UNO_QUERY
);
2645 if ( xList
->getCount() > 0 )
2646 xList
->getByIndex(0) >>= xTask
;
2651 Reference
< com::sun::star::awt::XTopWindow
> xTop( xTask
->getContainerWindow(), UNO_QUERY
);
2656 // no visible task that could be activated found
2657 Reference
< ::com::sun::star::awt::XWindow
> xContainerWindow
;
2658 Reference
< XFrame
> xBackingFrame
= xDesktop
->findFrame(OUString( "_blank" ), 0);
2659 if (xBackingFrame
.is())
2660 xContainerWindow
= xBackingFrame
->getContainerWindow();
2661 if (xContainerWindow
.is())
2663 Reference
< XController
> xStartModule
= StartModule::createWithParentWindow(xContext
, xContainerWindow
);
2664 Reference
< ::com::sun::star::awt::XWindow
> xBackingWin(xStartModule
, UNO_QUERY
);
2665 // Attention: You MUST(!) call setComponent() before you call attachFrame().
2666 // Because the backing component set the property "IsBackingMode" of the frame
2667 // to true inside attachFrame(). But setComponent() reset this state every time ...
2668 xBackingFrame
->setComponent(xBackingWin
, xStartModule
);
2669 xStartModule
->attachFrame(xBackingFrame
);
2670 xContainerWindow
->setVisible(sal_True
);
2672 Window
* pCompWindow
= VCLUnoHelper::GetWindow(xBackingFrame
->getComponentWindow());
2674 pCompWindow
->Update();
2679 case ApplicationEvent::TYPE_HELP
:
2680 displayCmdlineHelp(rAppEvent
.GetStringData());
2682 case ApplicationEvent::TYPE_VERSION
:
2685 case ApplicationEvent::TYPE_OPEN
:
2687 const CommandLineArgs
& rCmdLine
= GetCommandLineArgs();
2688 if ( !rCmdLine
.IsInvisible() && !rCmdLine
.IsTerminateAfterInit() )
2690 ProcessDocumentsRequest
* pDocsRequest
= new ProcessDocumentsRequest(
2691 rCmdLine
.getCwdUrl());
2692 std::vector
<OUString
> const & data(rAppEvent
.GetStringsData());
2693 pDocsRequest
->aOpenList
.insert(
2694 pDocsRequest
->aOpenList
.end(), data
.begin(), data
.end());
2695 pDocsRequest
->pcProcessed
= NULL
;
2697 OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest
);
2698 delete pDocsRequest
;
2702 case ApplicationEvent::TYPE_OPENHELPURL
:
2703 // start help for a specific URL
2704 Application::GetHelp()->Start(rAppEvent
.GetStringData(), NULL
);
2706 case ApplicationEvent::TYPE_PRINT
:
2708 const CommandLineArgs
& rCmdLine
= GetCommandLineArgs();
2709 if ( !rCmdLine
.IsInvisible() && !rCmdLine
.IsTerminateAfterInit() )
2711 ProcessDocumentsRequest
* pDocsRequest
= new ProcessDocumentsRequest(
2712 rCmdLine
.getCwdUrl());
2713 std::vector
<OUString
> const & data(rAppEvent
.GetStringsData());
2714 pDocsRequest
->aPrintList
.insert(
2715 pDocsRequest
->aPrintList
.end(), data
.begin(), data
.end());
2716 pDocsRequest
->pcProcessed
= NULL
;
2718 OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest
);
2719 delete pDocsRequest
;
2723 case ApplicationEvent::TYPE_PRIVATE_DOSHUTDOWN
:
2725 Desktop
* pD
= dynamic_cast<Desktop
*>(GetpApp());
2726 OSL_ENSURE( pD
, "no desktop ?!?" );
2731 case ApplicationEvent::TYPE_QUICKSTART
:
2732 if ( !GetCommandLineArgs().IsInvisible() )
2734 // If the office has been started the second time its command line arguments are sent through a pipe
2735 // connection to the first office. We want to reuse the quickstart option for the first office.
2736 // NOTICE: The quickstart service must be initialized inside the "main thread", so we use the
2737 // application events to do this (they are executed inside main thread)!!!
2738 // Don't start quickstart service if the user specified "--invisible" on the command line!
2739 Reference
< css::uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
2740 css::office::Quickstart::createStart(xContext
, true/*Quickstart*/);
2743 case ApplicationEvent::TYPE_SHOWDIALOG
:
2744 // ignore all errors here. It's clicking a menu entry only ...
2745 // The user will try it again, in case nothing happens .-)
2748 Reference
< css::uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
2750 Reference
< css::frame::XDesktop2
> xDesktop
= css::frame::Desktop::create( xContext
);
2752 Reference
< css::util::XURLTransformer
> xParser
= css::util::URLTransformer::create(xContext
);
2753 css::util::URL aCommand
;
2754 if( rAppEvent
.GetStringData() == "PREFERENCES" )
2755 aCommand
.Complete
= ".uno:OptionsTreeDialog";
2756 else if( rAppEvent
.GetStringData() == "ABOUT" )
2757 aCommand
.Complete
= ".uno:About";
2758 if( !aCommand
.Complete
.isEmpty() )
2760 xParser
->parseStrict(aCommand
);
2762 css::uno::Reference
< css::frame::XDispatch
> xDispatch
= xDesktop
->queryDispatch(aCommand
, OUString(), 0);
2764 xDispatch
->dispatch(aCommand
, css::uno::Sequence
< css::beans::PropertyValue
>());
2767 catch(const css::uno::Exception
&)
2770 case ApplicationEvent::TYPE_UNACCEPT
:
2771 // try to remove corresponding acceptor
2772 destroyAcceptor(rAppEvent
.GetStringData());
2775 SAL_WARN( "desktop.app", "this cannot happen");
2780 void Desktop::OpenSplashScreen()
2782 const CommandLineArgs
&rCmdLine
= GetCommandLineArgs();
2783 sal_Bool bVisible
= sal_False
;
2784 // Show intro only if this is normal start (e.g. no server, no quickstart, no printing )
2785 if ( !rCmdLine
.IsInvisible() &&
2786 !rCmdLine
.IsHeadless() &&
2787 !rCmdLine
.IsQuickstart() &&
2788 !rCmdLine
.IsMinimized() &&
2789 !rCmdLine
.IsNoLogo() &&
2790 !rCmdLine
.IsTerminateAfterInit() &&
2791 rCmdLine
.GetPrintList().empty() &&
2792 rCmdLine
.GetPrintToList().empty() &&
2793 rCmdLine
.GetConversionList().empty() )
2795 // Determine application name from command line parameters
2797 if ( rCmdLine
.IsWriter() )
2798 aAppName
= "writer";
2799 else if ( rCmdLine
.IsCalc() )
2801 else if ( rCmdLine
.IsDraw() )
2803 else if ( rCmdLine
.IsImpress() )
2804 aAppName
= "impress";
2805 else if ( rCmdLine
.IsBase() )
2807 else if ( rCmdLine
.IsGlobal() )
2808 aAppName
= "global";
2809 else if ( rCmdLine
.IsMath() )
2811 else if ( rCmdLine
.IsWeb() )
2814 // Which splash to use
2815 OUString
aSplashService( "com.sun.star.office.SplashScreen" );
2816 if ( rCmdLine
.HasSplashPipe() )
2817 aSplashService
= "com.sun.star.office.PipeSplashScreen";
2819 bVisible
= sal_True
;
2820 Sequence
< Any
> aSeq( 2 );
2821 aSeq
[0] <<= bVisible
;
2822 aSeq
[1] <<= aAppName
;
2823 css::uno::Reference
< css::uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
2824 m_rSplashScreen
= Reference
<XStatusIndicator
>(
2825 xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(aSplashService
, aSeq
, xContext
),
2828 if(m_rSplashScreen
.is())
2829 m_rSplashScreen
->start(OUString("SplashScreen"), 100);
2834 void Desktop::SetSplashScreenProgress(sal_Int32 iProgress
)
2836 if(m_rSplashScreen
.is())
2838 m_rSplashScreen
->setValue(iProgress
);
2842 void Desktop::SetSplashScreenText( const OUString
& rText
)
2844 if( m_rSplashScreen
.is() )
2846 m_rSplashScreen
->setText( rText
);
2850 void Desktop::CloseSplashScreen()
2852 if(m_rSplashScreen
.is())
2854 m_rSplashScreen
->end();
2855 m_rSplashScreen
= NULL
;
2859 // ========================================================================
2860 void Desktop::DoFirstRunInitializations()
2864 Reference
< XJobExecutor
> xExecutor
= JobExecutor::create( ::comphelper::getProcessComponentContext() );
2865 xExecutor
->trigger( OUString("onFirstRunInitialization") );
2867 catch(const ::com::sun::star::uno::Exception
&)
2869 SAL_WARN( "desktop.app", "Desktop::DoFirstRunInitializations: caught an exception while trigger job executor ..." );
2873 void Desktop::ShowBackingComponent(Desktop
* progress
)
2875 if (GetCommandLineArgs().IsNoDefault())
2879 Reference
< XComponentContext
> xContext
= comphelper::getProcessComponentContext();
2880 Reference
< XDesktop2
> xDesktop
= css::frame::Desktop::create(xContext
);
2883 progress
->SetSplashScreenProgress(60);
2885 Reference
< XFrame
> xBackingFrame
= xDesktop
->findFrame(OUString( "_blank" ), 0);
2886 Reference
< ::com::sun::star::awt::XWindow
> xContainerWindow
;
2888 if (xBackingFrame
.is())
2889 xContainerWindow
= xBackingFrame
->getContainerWindow();
2890 if (xContainerWindow
.is())
2892 // set the WB_EXT_DOCUMENT style. Normally, this is done by the TaskCreator service when a "_blank"
2893 // frame/window is created. Since we do not use the TaskCreator here, we need to mimic its behavior,
2894 // otherwise documents loaded into this frame will later on miss functionality depending on the style.
2895 Window
* pContainerWindow
= VCLUnoHelper::GetWindow( xContainerWindow
);
2896 SAL_WARN_IF( !pContainerWindow
, "desktop.app", "Desktop::Main: no implementation access to the frame's container window!" );
2897 pContainerWindow
->SetExtendedStyle( pContainerWindow
->GetExtendedStyle() | WB_EXT_DOCUMENT
);
2900 progress
->SetSplashScreenProgress(75);
2903 Reference
< XController
> xStartModule
= StartModule::createWithParentWindow( xContext
, xContainerWindow
);
2904 // Attention: You MUST(!) call setComponent() before you call attachFrame().
2905 // Because the backing component set the property "IsBackingMode" of the frame
2906 // to true inside attachFrame(). But setComponent() reset this state everytimes ...
2907 xBackingFrame
->setComponent(Reference
< XWindow
>(xStartModule
, UNO_QUERY
), xStartModule
);
2910 progress
->SetSplashScreenProgress(100);
2912 xStartModule
->attachFrame(xBackingFrame
);
2915 progress
->CloseSplashScreen();
2917 xContainerWindow
->setVisible(sal_True
);
2921 // ========================================================================
2922 void Desktop::CheckFirstRun( )
2924 if (officecfg::Office::Common::Misc::FirstRun::get())
2926 // this has once been done using a vos timer. this could lead to problems when
2927 // the timer would trigger when the app is already going down again, since VCL would
2928 // no longer be available. Since the old handler would do a postUserEvent to the main
2929 // thread anyway, we can use a vcl timer here to prevent the race contition (#107197#)
2930 m_firstRunTimer
.SetTimeout(3000); // 3 sec.
2931 m_firstRunTimer
.SetTimeoutHdl(LINK(this, Desktop
, AsyncInitFirstRun
));
2932 m_firstRunTimer
.Start();
2935 // Check if Quckstarter should be started (on Windows only)
2936 TCHAR szValue
[8192];
2937 DWORD nValueSize
= sizeof(szValue
);
2939 if ( ERROR_SUCCESS
== RegOpenKey( HKEY_LOCAL_MACHINE
, "Software\\LibreOffice", &hKey
) )
2941 if ( ERROR_SUCCESS
== RegQueryValueEx( hKey
, TEXT("RunQuickstartAtFirstStart"), NULL
, NULL
, (LPBYTE
)szValue
, &nValueSize
) )
2943 css::uno::Reference
< css::uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
2944 css::office::Quickstart::createAutoStart(xContext
, true/*Quickstart*/, true/*bAutostart*/);
2945 RegCloseKey( hKey
);
2950 boost::shared_ptr
< comphelper::ConfigurationChanges
> batch(
2951 comphelper::ConfigurationChanges::create());
2952 officecfg::Office::Common::Misc::FirstRun::set(false, batch
);
2959 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */