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 .
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"
52 #include <cppuhelper/bootstrap.hxx>
56 #include "salinst.hxx"
57 #include "salwtype.hxx"
61 #include "idlemgr.hxx"
63 #include "outfont.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
81 #include "rtl/strbuf.hxx"
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
95 sal_uInt16 nVCLException
= 0;
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
;
105 if ((pInfo
->Signal
== osl_Signal_User
) &&
106 (pInfo
->UserSignal
== OSL_SIGNAL_USER_RESOURCEFAILURE
) )
107 nVCLException
= EXC_RSCNOTLOADED
;
110 if ((pInfo
->Signal
== osl_Signal_User
) &&
111 (pInfo
->UserSignal
== OSL_SIGNAL_USER_X11SUBSYSTEMERROR
) )
112 nVCLException
= EXC_DISPLAY
;
115 if ((pInfo
->Signal
== osl_Signal_User
) &&
116 (pInfo
->UserSignal
== OSL_SIGNAL_USER_RVPCONNECTIONERROR
) )
117 nVCLException
= EXC_REMOTE
;
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
);
136 return osl_Signal_ActCallNextHdl
;
140 return osl_Signal_ActCallNextHdl
;
144 // =======================================================================
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();
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
177 if( pSVData
->mxAccessBridge
.is() )
179 sal_uLong nCount
= Application::ReleaseSolarMutex();
180 pSVData
->mxAccessBridge
->dispose();
181 Application::AcquireSolarMutex(nCount
);
182 pSVData
->mxAccessBridge
.clear();
191 // #i47888# allow for alternative initialization as required for e.g. MacOSX
192 extern sal_Bool
ImplSVMainHook( int* );
195 if( !Application::IsConsoleOnly() && ImplSVMainHook( &nRet
) )
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
209 int Main() { return EXIT_SUCCESS
; };
212 class DesktopEnvironmentContext
: public cppu::WeakImplHelper1
< com::sun::star::uno::XCurrentContext
>
215 DesktopEnvironmentContext( const com::sun::star::uno::Reference
< com::sun::star::uno::XCurrentContext
> & ctx
)
216 : m_xNextContext( ctx
) {}
219 virtual com::sun::star::uno::Any SAL_CALL
getValueByName( const OUString
& Name
)
220 throw (com::sun::star::uno::RuntimeException
);
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
)
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
);
244 SAL_INFO( "vcl.app", "vcl (ss112471) ::InitVCL" );
246 if( pExceptionHandler
!= NULL
)
249 EmbeddedFontsHelper::clearTemporaryFontFiles();
251 if( ! ImplGetSVData() )
254 if( !ImplGetSVData()->mpApp
)
256 pOwnSvApp
= new Application_Impl();
260 ImplSVData
* pSVData
= ImplGetSVData();
262 // register with tools
265 // remember Main-Thread-Id
266 pSVData
->mnMainThreadId
= ::osl::Thread::getCurrentIdentifier();
269 SAL_INFO( "vcl.app", "{ ::CreateSalInstance" );
270 pSVData
->mpDefInst
= CreateSalInstance();
271 if ( !pSVData
->mpDefInst
)
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)
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
312 extern "C" __attribute__ ((visibility("default"))) void
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
);
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
);
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
;
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
)
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 );
388 DBG_ASSERT( nBadTopWindows
==0, aBuf
.getStr() );
391 ImplImageTreeSingletonRef()->shutDown();
393 osl_removeSignalHandler( pExceptionHandler
);
394 pExceptionHandler
= NULL
;
396 // Debug Daten zuruecksetzen
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&)
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
;
570 DestroySalInstance( pSVData
->mpDefInst
);
580 EmbeddedFontsHelper::clearTemporaryFontFiles();
583 // only one call is allowed
584 struct WorkerThreadData
586 oslWorkerFunction pWorker
;
588 WorkerThreadData( oslWorkerFunction pWorker_
, void * pThreadData_
)
589 : pWorker( pWorker_
)
590 , pThreadData( pThreadData_
)
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
;
607 static oslThread hThreadID
= 0;
610 static void SAL_CALL
MainWorkerFunction( void* pArgs
)
612 ((WorkerThreadData
*)pArgs
)->pWorker( ((WorkerThreadData
*)pArgs
)->pThreadData
);
613 delete (WorkerThreadData
*)pArgs
;
619 void CreateMainLoopThread( oslWorkerFunction pWorker
, void * pThreadData
)
622 // sal thread always call CoInitializeEx, so a sysdepen implementation is necessary
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
633 hThreadID
= osl_createThread( MainWorkerFunction
, new WorkerThreadData( pWorker
, pThreadData
) );
637 void JoinMainLoopThread()
642 WaitForSingleObject(hThreadID
, INFINITE
);
644 osl_joinWithThread(hThreadID
);
645 osl_destroyThread( hThreadID
);
650 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */