Version 4.2.0.1, tag libreoffice-4.2.0.1
[LibreOffice.git] / vcl / source / app / svmain.cxx
blob8203952fd9c41f88a0e13a22a239b5d018c8a982
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
21 #include "rtl/logfile.hxx"
23 #include <osl/file.hxx>
24 #include <osl/signal.h>
26 #include "tools/tools.h"
27 #include "tools/debug.hxx"
28 #include "tools/resmgr.hxx"
30 #include "comphelper/processfactory.hxx"
32 #include "unotools/syslocaleoptions.hxx"
33 #include "unotools/fontcfg.hxx"
35 #include "vcl/svapp.hxx"
36 #include "vcl/wrkwin.hxx"
37 #include "vcl/cvtgrf.hxx"
38 #include "vcl/image.hxx"
39 #include "vcl/settings.hxx"
40 #include "vcl/unowrap.hxx"
41 #include "vcl/configsettings.hxx"
42 #include "vcl/lazydelete.hxx"
43 #include "vcl/embeddedfontshelper.hxx"
45 #ifdef WNT
46 #include <svsys.h>
47 #include <process.h>
48 #include <ole2.h>
49 #endif
51 #ifdef ANDROID
52 #include <cppuhelper/bootstrap.hxx>
53 #include <jni.h>
54 #endif
56 #include "salinst.hxx"
57 #include "salwtype.hxx"
58 #include "svdata.hxx"
59 #include "dbggui.hxx"
60 #include "accmgr.hxx"
61 #include "idlemgr.hxx"
62 #include "outdev.h"
63 #include "outfont.hxx"
64 #include "print.h"
65 #include "salsys.hxx"
66 #include "saltimer.hxx"
67 #include "salimestatus.hxx"
68 #include "impimagetree.hxx"
69 #include "xconnection.hxx"
71 #include "osl/process.h"
72 #include "com/sun/star/lang/XMultiServiceFactory.hpp"
73 #include "com/sun/star/lang/XComponent.hpp"
74 #include "com/sun/star/frame/Desktop.hpp"
76 #include "cppuhelper/implbase1.hxx"
77 #include "uno/current_context.hxx"
79 #if OSL_DEBUG_LEVEL > 0
80 #include <typeinfo>
81 #include "rtl/strbuf.hxx"
82 #endif
84 using namespace ::com::sun::star;
86 // =======================================================================
88 oslSignalAction SAL_CALL VCLExceptionSignal_impl( void* /*pData*/, oslSignalInfo* pInfo)
90 static bool bIn = false;
92 // if we crash again, bail out immediately
93 if ( !bIn )
95 sal_uInt16 nVCLException = 0;
97 // UAE
98 if ( (pInfo->Signal == osl_Signal_AccessViolation) ||
99 (pInfo->Signal == osl_Signal_IntegerDivideByZero) ||
100 (pInfo->Signal == osl_Signal_FloatDivideByZero) ||
101 (pInfo->Signal == osl_Signal_DebugBreak) )
102 nVCLException = EXC_SYSTEM;
104 // RC
105 if ((pInfo->Signal == osl_Signal_User) &&
106 (pInfo->UserSignal == OSL_SIGNAL_USER_RESOURCEFAILURE) )
107 nVCLException = EXC_RSCNOTLOADED;
109 // DISPLAY-Unix
110 if ((pInfo->Signal == osl_Signal_User) &&
111 (pInfo->UserSignal == OSL_SIGNAL_USER_X11SUBSYSTEMERROR) )
112 nVCLException = EXC_DISPLAY;
114 // Remote-Client
115 if ((pInfo->Signal == osl_Signal_User) &&
116 (pInfo->UserSignal == OSL_SIGNAL_USER_RVPCONNECTIONERROR) )
117 nVCLException = EXC_REMOTE;
119 if ( nVCLException )
121 bIn = true;
123 SolarMutexGuard aLock;
125 // do not stop timer because otherwise the UAE-Box will not be painted as well
126 ImplSVData* pSVData = ImplGetSVData();
127 if ( pSVData->mpApp )
129 sal_uInt16 nOldMode = Application::GetSystemWindowMode();
130 Application::SetSystemWindowMode( nOldMode & ~SYSTEMWINDOW_MODE_NOAUTOMODE );
131 pSVData->mpApp->Exception( nVCLException );
132 Application::SetSystemWindowMode( nOldMode );
134 bIn = false;
136 return osl_Signal_ActCallNextHdl;
140 return osl_Signal_ActCallNextHdl;
144 // =======================================================================
145 int ImplSVMain()
147 // The 'real' SVMain()
148 SAL_INFO( "vcl.app", "vcl (ss112471) ::SVMain" );
150 ImplSVData* pSVData = ImplGetSVData();
152 DBG_ASSERT( pSVData->mpApp, "no instance of class Application" );
154 int nReturn = EXIT_FAILURE;
156 bool bInit = InitVCL();
158 if( bInit )
160 // call application main
161 pSVData->maAppData.mbInAppMain = sal_True;
162 nReturn = pSVData->mpApp->Main();
163 pSVData->maAppData.mbInAppMain = sal_False;
166 if( pSVData->mxDisplayConnection.is() )
168 pSVData->mxDisplayConnection->terminate();
169 pSVData->mxDisplayConnection.clear();
172 // This is a hack to work around the problem of the asynchronous nature
173 // of bridging accessibility through Java: on shutdown there might still
174 // be some events in the AWT EventQueue, which need the SolarMutex which
175 // - on the other hand - is destroyed in DeInitVCL(). So empty the queue
176 // here ..
177 if( pSVData->mxAccessBridge.is() )
179 sal_uLong nCount = Application::ReleaseSolarMutex();
180 pSVData->mxAccessBridge->dispose();
181 Application::AcquireSolarMutex(nCount);
182 pSVData->mxAccessBridge.clear();
185 DeInitVCL();
186 return nReturn;
189 int SVMain()
191 // #i47888# allow for alternative initialization as required for e.g. MacOSX
192 extern sal_Bool ImplSVMainHook( int* );
194 int nRet;
195 if( !Application::IsConsoleOnly() && ImplSVMainHook( &nRet ) )
196 return nRet;
197 else
198 return ImplSVMain();
200 // This variable is set, when no Application object is instantiated
201 // before SVInit is called
202 static Application * pOwnSvApp = NULL;
203 // Exception handler. pExceptionHandler != NULL => VCL already inited
204 oslSignalHandler pExceptionHandler = NULL;
206 class Application_Impl : public Application
208 public:
209 int Main() { return EXIT_SUCCESS; };
212 class DesktopEnvironmentContext: public cppu::WeakImplHelper1< com::sun::star::uno::XCurrentContext >
214 public:
215 DesktopEnvironmentContext( const com::sun::star::uno::Reference< com::sun::star::uno::XCurrentContext > & ctx)
216 : m_xNextContext( ctx ) {}
218 // XCurrentContext
219 virtual com::sun::star::uno::Any SAL_CALL getValueByName( const OUString& Name )
220 throw (com::sun::star::uno::RuntimeException);
222 private:
223 com::sun::star::uno::Reference< com::sun::star::uno::XCurrentContext > m_xNextContext;
226 uno::Any SAL_CALL DesktopEnvironmentContext::getValueByName( const OUString& Name) throw (uno::RuntimeException)
228 uno::Any retVal;
230 if ( Name == "system.desktop-environment" )
232 retVal = uno::makeAny( Application::GetDesktopEnvironment() );
234 else if( m_xNextContext.is() )
236 // Call next context in chain if found
237 retVal = m_xNextContext->getValueByName( Name );
239 return retVal;
242 bool InitVCL()
244 SAL_INFO( "vcl.app", "vcl (ss112471) ::InitVCL" );
246 if( pExceptionHandler != NULL )
247 return false;
249 EmbeddedFontsHelper::clearTemporaryFontFiles();
251 if( ! ImplGetSVData() )
252 ImplInitSVData();
254 if( !ImplGetSVData()->mpApp )
256 pOwnSvApp = new Application_Impl();
258 InitSalMain();
260 ImplSVData* pSVData = ImplGetSVData();
262 // register with tools
263 InitTools();
265 // remember Main-Thread-Id
266 pSVData->mnMainThreadId = ::osl::Thread::getCurrentIdentifier();
268 // Initialize Sal
269 SAL_INFO( "vcl.app", "{ ::CreateSalInstance" );
270 pSVData->mpDefInst = CreateSalInstance();
271 if ( !pSVData->mpDefInst )
272 return false;
273 SAL_INFO( "vcl.app", "} ::CreateSalInstance" );
275 // Desktop Environment context (to be able to get value of "system.desktop-environment" as soon as possible)
276 com::sun::star::uno::setCurrentContext(
277 new DesktopEnvironmentContext( com::sun::star::uno::getCurrentContext() ) );
279 // Initialize application instance (should be done after initialization of VCL SAL part)
280 if( pSVData->mpApp )
281 // call init to initialize application class
282 // soffice/sfx implementation creates the global service manager
283 pSVData->mpApp->Init();
285 pSVData->mpDefInst->AfterAppInit();
287 // Fetch AppFileName and make it absolute before the workdir changes...
288 OUString aExeFileName;
289 osl_getExecutableFile( &aExeFileName.pData );
291 // convert path to native file format
292 OUString aNativeFileName;
293 osl::FileBase::getSystemPathFromFileURL( aExeFileName, aNativeFileName );
294 pSVData->maAppData.mpAppFileName = new OUString( aNativeFileName );
296 // Initialize global data
297 pSVData->maGDIData.mpScreenFontList = new ImplDevFontList;
298 pSVData->maGDIData.mpScreenFontCache = new ImplFontCache( sal_False );
299 pSVData->maGDIData.mpGrfConverter = new GraphicConverter;
301 // Set exception handler
302 pExceptionHandler = osl_addSignalHandler(VCLExceptionSignal_impl, NULL);
304 // initialise debug data
305 DBGGUI_INIT();
307 return true;
310 #ifdef ANDROID
312 extern "C" __attribute__ ((visibility("default"))) void
313 InitVCLWrapper()
315 uno::Reference<uno::XComponentContext> xContext( cppu::defaultBootstrap_InitialComponentContext() );
316 uno::Reference<lang::XMultiComponentFactory> xFactory( xContext->getServiceManager() );
318 uno::Reference<lang::XMultiServiceFactory> xSM( xFactory, uno::UNO_QUERY_THROW );
320 comphelper::setProcessServiceFactory( xSM );
322 InitVCL();
325 #endif
327 namespace
330 /** Serves for destroying the VCL UNO wrapper as late as possible. This avoids
331 crash at exit in some special cases when a11y is enabled (e.g., when
332 a bundled extension is registered/deregistered during startup, forcing exit
333 while the app is still in splash screen.)
335 class VCLUnoWrapperDeleter : public cppu::WeakImplHelper1<com::sun::star::lang::XEventListener>
337 virtual void SAL_CALL disposing(lang::EventObject const& rSource) throw(uno::RuntimeException);
340 void
341 VCLUnoWrapperDeleter::disposing(lang::EventObject const& /* rSource */)
342 throw(uno::RuntimeException)
344 ImplSVData* const pSVData = ImplGetSVData();
345 if (pSVData && pSVData->mpUnoWrapper)
347 pSVData->mpUnoWrapper->Destroy();
348 pSVData->mpUnoWrapper = NULL;
354 void DeInitVCL()
356 ImplSVData* pSVData = ImplGetSVData();
357 pSVData->mbDeInit = sal_True;
359 vcl::DeleteOnDeinitBase::ImplDeleteOnDeInit();
361 // give ime status a chance to destroy its own windows
362 delete pSVData->mpImeStatus;
363 pSVData->mpImeStatus = NULL;
365 #if OSL_DEBUG_LEVEL > 0
366 OStringBuffer aBuf( 256 );
367 aBuf.append( "DeInitVCL: some top Windows are still alive\n" );
368 long nTopWindowCount = Application::GetTopWindowCount();
369 long nBadTopWindows = nTopWindowCount;
370 for( long i = 0; i < nTopWindowCount; i++ )
372 Window* pWin = Application::GetTopWindow( i );
373 // default window will be destroyed further down
374 // but may still be useful during deinit up to that point
375 if( pWin == pSVData->mpDefaultWin )
376 nBadTopWindows--;
377 else
379 aBuf.append( "text = \"" );
380 aBuf.append( OUStringToOString( pWin->GetText(), osl_getThreadTextEncoding() ) );
381 aBuf.append( "\" type = \"" );
382 aBuf.append( typeid(*pWin).name() );
383 aBuf.append( "\", ptr = 0x" );
384 aBuf.append( sal_Int64( pWin ), 16 );
385 aBuf.append( "\n" );
388 DBG_ASSERT( nBadTopWindows==0, aBuf.getStr() );
389 #endif
391 ImplImageTreeSingletonRef()->shutDown();
393 osl_removeSignalHandler( pExceptionHandler);
394 pExceptionHandler = NULL;
396 // Debug Daten zuruecksetzen
397 DBGGUI_DEINIT();
399 // free global data
400 delete pSVData->maGDIData.mpGrfConverter;
402 if( pSVData->mpSettingsConfigItem )
403 delete pSVData->mpSettingsConfigItem, pSVData->mpSettingsConfigItem = NULL;
404 if( pSVData->maGDIData.mpDefaultFontConfiguration )
405 delete pSVData->maGDIData.mpDefaultFontConfiguration, pSVData->maGDIData.mpDefaultFontConfiguration = NULL;
406 if( pSVData->maGDIData.mpFontSubstConfiguration )
407 delete pSVData->maGDIData.mpFontSubstConfiguration, pSVData->maGDIData.mpFontSubstConfiguration = NULL;
409 if ( pSVData->maAppData.mpIdleMgr )
410 delete pSVData->maAppData.mpIdleMgr;
411 Timer::ImplDeInitTimer();
413 if ( pSVData->maWinData.mpMsgBoxImgList )
415 delete pSVData->maWinData.mpMsgBoxImgList;
416 pSVData->maWinData.mpMsgBoxImgList = NULL;
418 if ( pSVData->maCtrlData.mpCheckImgList )
420 delete pSVData->maCtrlData.mpCheckImgList;
421 pSVData->maCtrlData.mpCheckImgList = NULL;
423 if ( pSVData->maCtrlData.mpRadioImgList )
425 delete pSVData->maCtrlData.mpRadioImgList;
426 pSVData->maCtrlData.mpRadioImgList = NULL;
428 if ( pSVData->maCtrlData.mpPinImgList )
430 delete pSVData->maCtrlData.mpPinImgList;
431 pSVData->maCtrlData.mpPinImgList = NULL;
433 if ( pSVData->maCtrlData.mpSplitHPinImgList )
435 delete pSVData->maCtrlData.mpSplitHPinImgList;
436 pSVData->maCtrlData.mpSplitHPinImgList = NULL;
438 if ( pSVData->maCtrlData.mpSplitVPinImgList )
440 delete pSVData->maCtrlData.mpSplitVPinImgList;
441 pSVData->maCtrlData.mpSplitVPinImgList = NULL;
443 if ( pSVData->maCtrlData.mpSplitHArwImgList )
445 delete pSVData->maCtrlData.mpSplitHArwImgList;
446 pSVData->maCtrlData.mpSplitHArwImgList = NULL;
448 if ( pSVData->maCtrlData.mpSplitVArwImgList )
450 delete pSVData->maCtrlData.mpSplitVArwImgList;
451 pSVData->maCtrlData.mpSplitVArwImgList = NULL;
453 if ( pSVData->maCtrlData.mpDisclosurePlus )
455 delete pSVData->maCtrlData.mpDisclosurePlus;
456 pSVData->maCtrlData.mpDisclosurePlus = NULL;
458 if ( pSVData->maCtrlData.mpDisclosureMinus )
460 delete pSVData->maCtrlData.mpDisclosureMinus;
461 pSVData->maCtrlData.mpDisclosureMinus = NULL;
463 if ( pSVData->mpDefaultWin )
465 delete pSVData->mpDefaultWin;
466 pSVData->mpDefaultWin = NULL;
469 if ( pSVData->mpUnoWrapper )
473 uno::Reference<frame::XDesktop2> const xDesktop = frame::Desktop::create(
474 comphelper::getProcessComponentContext() );
475 xDesktop->addEventListener(new VCLUnoWrapperDeleter());
477 catch (uno::Exception const&)
479 // ignore
483 if( pSVData->mpApp )
485 sal_uLong nCount = Application::ReleaseSolarMutex();
486 // call deinit to deinitialize application class
487 // soffice/sfx implementation disposes the global service manager
488 // Warning: After this call you can't call uno services
489 pSVData->mpApp->DeInit();
490 Application::AcquireSolarMutex(nCount);
493 if ( pSVData->maAppData.mpSettings )
495 if ( pSVData->maAppData.mpCfgListener )
497 pSVData->maAppData.mpSettings->GetSysLocale().GetOptions().RemoveListener( pSVData->maAppData.mpCfgListener );
498 delete pSVData->maAppData.mpCfgListener;
501 delete pSVData->maAppData.mpSettings;
502 pSVData->maAppData.mpSettings = NULL;
504 if ( pSVData->maAppData.mpAccelMgr )
506 delete pSVData->maAppData.mpAccelMgr;
507 pSVData->maAppData.mpAccelMgr = NULL;
509 if ( pSVData->maAppData.mpAppFileName )
511 delete pSVData->maAppData.mpAppFileName;
512 pSVData->maAppData.mpAppFileName = NULL;
514 if ( pSVData->maAppData.mpAppName )
516 delete pSVData->maAppData.mpAppName;
517 pSVData->maAppData.mpAppName = NULL;
519 if ( pSVData->maAppData.mpDisplayName )
521 delete pSVData->maAppData.mpDisplayName;
522 pSVData->maAppData.mpDisplayName = NULL;
524 if ( pSVData->maAppData.mpEventListeners )
526 delete pSVData->maAppData.mpEventListeners;
527 pSVData->maAppData.mpEventListeners = NULL;
529 if ( pSVData->maAppData.mpKeyListeners )
531 delete pSVData->maAppData.mpKeyListeners;
532 pSVData->maAppData.mpKeyListeners = NULL;
534 if ( pSVData->maAppData.mpPostYieldListeners )
536 delete pSVData->maAppData.mpPostYieldListeners;
537 pSVData->maAppData.mpPostYieldListeners = NULL;
540 if ( pSVData->maAppData.mpFirstHotKey )
541 ImplFreeHotKeyData();
542 if ( pSVData->maAppData.mpFirstEventHook )
543 ImplFreeEventHookData();
545 if (pSVData->mpBlendFrameCache)
546 delete pSVData->mpBlendFrameCache, pSVData->mpBlendFrameCache = NULL;
548 ImplDeletePrnQueueList();
549 delete pSVData->maGDIData.mpScreenFontList;
550 pSVData->maGDIData.mpScreenFontList = NULL;
551 delete pSVData->maGDIData.mpScreenFontCache;
552 pSVData->maGDIData.mpScreenFontCache = NULL;
554 if ( pSVData->mpResMgr )
556 delete pSVData->mpResMgr;
557 pSVData->mpResMgr = NULL;
560 ResMgr::DestroyAllResMgr();
562 // destroy all Sal interfaces before destorying the instance
563 // and thereby unloading the plugin
564 delete pSVData->mpSalSystem;
565 pSVData->mpSalSystem = NULL;
566 delete pSVData->mpSalTimer;
567 pSVData->mpSalTimer = NULL;
569 // Deinit Sal
570 DestroySalInstance( pSVData->mpDefInst );
572 DeInitTools();
574 if( pOwnSvApp )
576 delete pOwnSvApp;
577 pOwnSvApp = NULL;
580 EmbeddedFontsHelper::clearTemporaryFontFiles();
583 // only one call is allowed
584 struct WorkerThreadData
586 oslWorkerFunction pWorker;
587 void * pThreadData;
588 WorkerThreadData( oslWorkerFunction pWorker_, void * pThreadData_ )
589 : pWorker( pWorker_ )
590 , pThreadData( pThreadData_ )
595 #ifdef WNT
596 static HANDLE hThreadID = 0;
597 static unsigned __stdcall _threadmain( void *pArgs )
599 OleInitialize( NULL );
600 ((WorkerThreadData*)pArgs)->pWorker( ((WorkerThreadData*)pArgs)->pThreadData );
601 delete (WorkerThreadData*)pArgs;
602 OleUninitialize();
603 hThreadID = 0;
604 return 0;
606 #else
607 static oslThread hThreadID = 0;
608 extern "C"
610 static void SAL_CALL MainWorkerFunction( void* pArgs )
612 ((WorkerThreadData*)pArgs)->pWorker( ((WorkerThreadData*)pArgs)->pThreadData );
613 delete (WorkerThreadData*)pArgs;
614 hThreadID = 0;
616 } // extern "C"
617 #endif
619 void CreateMainLoopThread( oslWorkerFunction pWorker, void * pThreadData )
621 #ifdef WNT
622 // sal thread always call CoInitializeEx, so a sysdepen implementation is necessary
624 unsigned uThreadID;
625 hThreadID = (HANDLE)_beginthreadex(
626 NULL, // no security handle
627 0, // stacksize 0 means default
628 _threadmain, // thread worker function
629 new WorkerThreadData( pWorker, pThreadData ), // arguments for worker function
630 0, // 0 means: create immediately otherwise use CREATE_SUSPENDED
631 &uThreadID ); // thread id to fill
632 #else
633 hThreadID = osl_createThread( MainWorkerFunction, new WorkerThreadData( pWorker, pThreadData ) );
634 #endif
637 void JoinMainLoopThread()
639 if( hThreadID )
641 #ifdef WNT
642 WaitForSingleObject(hThreadID, INFINITE);
643 #else
644 osl_joinWithThread(hThreadID);
645 osl_destroyThread( hThreadID );
646 #endif
650 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */