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 <sal/config.h>
24 #include <osl/file.hxx>
25 #include <osl/signal.h>
27 #include "tools/debug.hxx"
28 #include "tools/resmgr.hxx"
30 #include "comphelper/processfactory.hxx"
32 #include "unotools/syslocaleoptions.hxx"
33 #include "vcl/svapp.hxx"
34 #include "vcl/wrkwin.hxx"
35 #include "vcl/cvtgrf.hxx"
36 #include "vcl/scheduler.hxx"
37 #include "vcl/image.hxx"
38 #include "vcl/implimagetree.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"
44 #include "vcl/debugevent.hxx"
53 #include <cppuhelper/bootstrap.hxx>
57 #include "salinst.hxx"
58 #include "salwtype.hxx"
60 #include "vcl/svmain.hxx"
63 #include "idlemgr.hxx"
65 #include "outfont.hxx"
66 #include "PhysicalFontCollection.hxx"
70 #include "saltimer.hxx"
71 #include "salimestatus.hxx"
72 #include "xconnection.hxx"
74 #include "vcl/opengl/OpenGLContext.hxx"
76 #include "osl/process.h"
77 #include "com/sun/star/lang/XMultiServiceFactory.hpp"
78 #include "com/sun/star/lang/XComponent.hpp"
79 #include "com/sun/star/frame/Desktop.hpp"
81 #include "cppuhelper/implbase1.hxx"
82 #include "uno/current_context.hxx"
84 #include "opengl/zone.hxx"
85 #include "opengl/watchdog.hxx"
87 #if OSL_DEBUG_LEVEL > 0
89 #include "rtl/strbuf.hxx"
92 using namespace ::com::sun::star
;
94 oslSignalAction SAL_CALL
VCLExceptionSignal_impl( void* /*pData*/, oslSignalInfo
* pInfo
)
96 static bool bIn
= false;
98 // if we crash again, bail out immediately
101 sal_uInt16 nVCLException
= 0;
104 if ( (pInfo
->Signal
== osl_Signal_AccessViolation
) ||
105 (pInfo
->Signal
== osl_Signal_IntegerDivideByZero
) ||
106 (pInfo
->Signal
== osl_Signal_FloatDivideByZero
) ||
107 (pInfo
->Signal
== osl_Signal_DebugBreak
) )
109 nVCLException
= EXC_SYSTEM
;
110 if (OpenGLZone::isInZone())
111 OpenGLZone::hardDisable();
115 if ((pInfo
->Signal
== osl_Signal_User
) &&
116 (pInfo
->UserSignal
== OSL_SIGNAL_USER_RESOURCEFAILURE
) )
117 nVCLException
= EXC_RSCNOTLOADED
;
120 if ((pInfo
->Signal
== osl_Signal_User
) &&
121 (pInfo
->UserSignal
== OSL_SIGNAL_USER_X11SUBSYSTEMERROR
) )
122 nVCLException
= EXC_DISPLAY
;
125 if ((pInfo
->Signal
== osl_Signal_User
) &&
126 (pInfo
->UserSignal
== OSL_SIGNAL_USER_RVPCONNECTIONERROR
) )
127 nVCLException
= EXC_REMOTE
;
133 SolarMutexGuard aLock
;
135 // do not stop timer because otherwise the UAE-Box will not be painted as well
136 ImplSVData
* pSVData
= ImplGetSVData();
137 if ( pSVData
->mpApp
)
139 SystemWindowFlags nOldMode
= Application::GetSystemWindowMode();
140 Application::SetSystemWindowMode( nOldMode
& ~SystemWindowFlags::NOAUTOMODE
);
141 pSVData
->mpApp
->Exception( nVCLException
);
142 Application::SetSystemWindowMode( nOldMode
);
146 return osl_Signal_ActCallNextHdl
;
150 return osl_Signal_ActCallNextHdl
;
156 // The 'real' SVMain()
157 ImplSVData
* pSVData
= ImplGetSVData();
159 DBG_ASSERT( pSVData
->mpApp
, "no instance of class Application" );
161 int nReturn
= EXIT_FAILURE
;
163 bool bInit
= InitVCL();
167 // call application main
168 pSVData
->maAppData
.mbInAppMain
= true;
169 nReturn
= pSVData
->mpApp
->Main();
170 pSVData
->maAppData
.mbInAppMain
= false;
173 if( pSVData
->mxDisplayConnection
.is() )
175 pSVData
->mxDisplayConnection
->terminate();
176 pSVData
->mxDisplayConnection
.clear();
179 // This is a hack to work around the problem of the asynchronous nature
180 // of bridging accessibility through Java: on shutdown there might still
181 // be some events in the AWT EventQueue, which need the SolarMutex which
182 // - on the other hand - is destroyed in DeInitVCL(). So empty the queue
184 if( pSVData
->mxAccessBridge
.is() )
187 SolarMutexReleaser aReleaser
;
188 pSVData
->mxAccessBridge
->dispose();
190 pSVData
->mxAccessBridge
.clear();
193 OpenGLWatchdogThread::stop();
203 if( !Application::IsConsoleOnly() && ImplSVMainHook( &nRet
) )
209 // This variable is set when no Application object has been instantiated
210 // before InitVCL is called
211 static Application
* pOwnSvApp
= NULL
;
213 // Exception handler. pExceptionHandler != NULL => VCL already inited
214 static oslSignalHandler pExceptionHandler
= NULL
;
216 class DesktopEnvironmentContext
: public cppu::WeakImplHelper1
< com::sun::star::uno::XCurrentContext
>
219 DesktopEnvironmentContext( const com::sun::star::uno::Reference
< com::sun::star::uno::XCurrentContext
> & ctx
)
220 : m_xNextContext( ctx
) {}
223 virtual com::sun::star::uno::Any SAL_CALL
getValueByName( const OUString
& Name
)
224 throw (com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
227 com::sun::star::uno::Reference
< com::sun::star::uno::XCurrentContext
> m_xNextContext
;
230 uno::Any SAL_CALL
DesktopEnvironmentContext::getValueByName( const OUString
& Name
) throw (uno::RuntimeException
, std::exception
)
234 if ( Name
== "system.desktop-environment" )
236 retVal
= uno::makeAny( Application::GetDesktopEnvironment() );
238 else if( m_xNextContext
.is() )
240 // Call next context in chain if found
241 retVal
= m_xNextContext
->getValueByName( Name
);
248 if( pExceptionHandler
!= NULL
)
251 EmbeddedFontsHelper::clearTemporaryFontFiles();
253 if( !ImplGetSVData()->mpApp
)
255 pOwnSvApp
= new Application();
259 ImplSVData
* pSVData
= ImplGetSVData();
261 // remember Main-Thread-Id
262 pSVData
->mnMainThreadId
= ::osl::Thread::getCurrentIdentifier();
265 pSVData
->mpDefInst
= CreateSalInstance();
266 if ( !pSVData
->mpDefInst
)
269 // Desktop Environment context (to be able to get value of "system.desktop-environment" as soon as possible)
270 com::sun::star::uno::setCurrentContext(
271 new DesktopEnvironmentContext( com::sun::star::uno::getCurrentContext() ) );
273 // Initialize application instance (should be done after initialization of VCL SAL part)
275 // call init to initialize application class
276 // soffice/sfx implementation creates the global service manager
277 pSVData
->mpApp
->Init();
279 pSVData
->mpDefInst
->AfterAppInit();
281 // Fetch AppFileName and make it absolute before the workdir changes...
282 OUString aExeFileName
;
283 osl_getExecutableFile( &aExeFileName
.pData
);
285 // convert path to native file format
286 OUString aNativeFileName
;
287 osl::FileBase::getSystemPathFromFileURL( aExeFileName
, aNativeFileName
);
288 pSVData
->maAppData
.mpAppFileName
= new OUString( aNativeFileName
);
290 // Initialize global data
291 pSVData
->maGDIData
.mpScreenFontList
= new PhysicalFontCollection
;
292 pSVData
->maGDIData
.mpScreenFontCache
= new ImplFontCache
;
293 pSVData
->maGDIData
.mpGrfConverter
= new GraphicConverter
;
295 // Set exception handler
296 pExceptionHandler
= osl_addSignalHandler(VCLExceptionSignal_impl
, NULL
);
298 DBGGUI_INIT_SOLARMUTEXCHECK();
300 #if OSL_DEBUG_LEVEL > 0
301 DebugEventInjector::getCreate();
310 /** Serves for destroying the VCL UNO wrapper as late as possible. This avoids
311 crash at exit in some special cases when a11y is enabled (e.g., when
312 a bundled extension is registered/deregistered during startup, forcing exit
313 while the app is still in splash screen.)
315 class VCLUnoWrapperDeleter
: public cppu::WeakImplHelper1
<com::sun::star::lang::XEventListener
>
317 virtual void SAL_CALL
disposing(lang::EventObject
const& rSource
) throw(uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
321 VCLUnoWrapperDeleter::disposing(lang::EventObject
const& /* rSource */)
322 throw(uno::RuntimeException
, std::exception
)
324 ImplSVData
* const pSVData
= ImplGetSVData();
325 if (pSVData
&& pSVData
->mpUnoWrapper
)
327 pSVData
->mpUnoWrapper
->Destroy();
328 pSVData
->mpUnoWrapper
= NULL
;
336 ImplSVData
* pSVData
= ImplGetSVData();
337 pSVData
->mbDeInit
= true;
339 vcl::DeleteOnDeinitBase::ImplDeleteOnDeInit();
341 // give ime status a chance to destroy its own windows
342 delete pSVData
->mpImeStatus
;
343 pSVData
->mpImeStatus
= NULL
;
345 #if OSL_DEBUG_LEVEL > 0
346 OStringBuffer
aBuf( 256 );
347 aBuf
.append( "DeInitVCL: some top Windows are still alive\n" );
348 long nTopWindowCount
= Application::GetTopWindowCount();
349 long nBadTopWindows
= nTopWindowCount
;
350 for( long i
= 0; i
< nTopWindowCount
; i
++ )
352 vcl::Window
* pWin
= Application::GetTopWindow( i
);
353 // default window will be destroyed further down
354 // but may still be useful during deinit up to that point
355 if( pWin
== pSVData
->mpDefaultWin
)
359 aBuf
.append( "text = \"" );
360 aBuf
.append( OUStringToOString( pWin
->GetText(), osl_getThreadTextEncoding() ) );
361 aBuf
.append( "\" type = \"" );
362 aBuf
.append( typeid(*pWin
).name() );
363 aBuf
.append( "\", ptr = 0x" );
364 aBuf
.append( sal_Int64( pWin
), 16 );
368 DBG_ASSERT( nBadTopWindows
==0, aBuf
.getStr() );
371 ImplImageTree::get().shutDown();
373 osl_removeSignalHandler( pExceptionHandler
);
374 pExceptionHandler
= NULL
;
377 delete pSVData
->maGDIData
.mpGrfConverter
;
379 if( pSVData
->mpSettingsConfigItem
)
380 delete pSVData
->mpSettingsConfigItem
, pSVData
->mpSettingsConfigItem
= NULL
;
382 if ( pSVData
->maAppData
.mpIdleMgr
)
383 delete pSVData
->maAppData
.mpIdleMgr
;
384 Scheduler::ImplDeInitScheduler();
386 if ( pSVData
->maWinData
.mpMsgBoxImgList
)
388 delete pSVData
->maWinData
.mpMsgBoxImgList
;
389 pSVData
->maWinData
.mpMsgBoxImgList
= NULL
;
391 if ( pSVData
->maCtrlData
.mpCheckImgList
)
393 delete pSVData
->maCtrlData
.mpCheckImgList
;
394 pSVData
->maCtrlData
.mpCheckImgList
= NULL
;
396 if ( pSVData
->maCtrlData
.mpRadioImgList
)
398 delete pSVData
->maCtrlData
.mpRadioImgList
;
399 pSVData
->maCtrlData
.mpRadioImgList
= NULL
;
401 if ( pSVData
->maCtrlData
.mpPinImgList
)
403 delete pSVData
->maCtrlData
.mpPinImgList
;
404 pSVData
->maCtrlData
.mpPinImgList
= NULL
;
406 if ( pSVData
->maCtrlData
.mpSplitHPinImgList
)
408 delete pSVData
->maCtrlData
.mpSplitHPinImgList
;
409 pSVData
->maCtrlData
.mpSplitHPinImgList
= NULL
;
411 if ( pSVData
->maCtrlData
.mpSplitVPinImgList
)
413 delete pSVData
->maCtrlData
.mpSplitVPinImgList
;
414 pSVData
->maCtrlData
.mpSplitVPinImgList
= NULL
;
416 if ( pSVData
->maCtrlData
.mpSplitHArwImgList
)
418 delete pSVData
->maCtrlData
.mpSplitHArwImgList
;
419 pSVData
->maCtrlData
.mpSplitHArwImgList
= NULL
;
421 if ( pSVData
->maCtrlData
.mpSplitVArwImgList
)
423 delete pSVData
->maCtrlData
.mpSplitVArwImgList
;
424 pSVData
->maCtrlData
.mpSplitVArwImgList
= NULL
;
426 if ( pSVData
->maCtrlData
.mpDisclosurePlus
)
428 delete pSVData
->maCtrlData
.mpDisclosurePlus
;
429 pSVData
->maCtrlData
.mpDisclosurePlus
= NULL
;
431 if ( pSVData
->maCtrlData
.mpDisclosureMinus
)
433 delete pSVData
->maCtrlData
.mpDisclosureMinus
;
434 pSVData
->maCtrlData
.mpDisclosureMinus
= NULL
;
436 pSVData
->mpDefaultWin
.disposeAndClear();
438 DBGGUI_DEINIT_SOLARMUTEXCHECK();
440 if ( pSVData
->mpUnoWrapper
)
444 uno::Reference
<frame::XDesktop2
> const xDesktop
= frame::Desktop::create(
445 comphelper::getProcessComponentContext() );
446 xDesktop
->addEventListener(new VCLUnoWrapperDeleter());
448 catch (uno::Exception
const&)
454 if( pSVData
->mpApp
|| pSVData
->maDeInitHook
.IsSet() )
456 SolarMutexReleaser aReleaser
;
457 // call deinit to deinitialize application class
458 // soffice/sfx implementation disposes the global service manager
459 // Warning: After this call you can't call uno services
462 pSVData
->mpApp
->DeInit();
464 if( pSVData
->maDeInitHook
.IsSet() )
466 pSVData
->maDeInitHook
.Call(0);
470 if ( pSVData
->maAppData
.mpSettings
)
472 if ( pSVData
->maAppData
.mpCfgListener
)
474 pSVData
->maAppData
.mpSettings
->GetSysLocale().GetOptions().RemoveListener( pSVData
->maAppData
.mpCfgListener
);
475 delete pSVData
->maAppData
.mpCfgListener
;
478 delete pSVData
->maAppData
.mpSettings
;
479 pSVData
->maAppData
.mpSettings
= NULL
;
481 if ( pSVData
->maAppData
.mpAccelMgr
)
483 delete pSVData
->maAppData
.mpAccelMgr
;
484 pSVData
->maAppData
.mpAccelMgr
= NULL
;
486 if ( pSVData
->maAppData
.mpAppFileName
)
488 delete pSVData
->maAppData
.mpAppFileName
;
489 pSVData
->maAppData
.mpAppFileName
= NULL
;
491 if ( pSVData
->maAppData
.mpAppName
)
493 delete pSVData
->maAppData
.mpAppName
;
494 pSVData
->maAppData
.mpAppName
= NULL
;
496 if ( pSVData
->maAppData
.mpDisplayName
)
498 delete pSVData
->maAppData
.mpDisplayName
;
499 pSVData
->maAppData
.mpDisplayName
= NULL
;
501 if ( pSVData
->maAppData
.mpEventListeners
)
503 delete pSVData
->maAppData
.mpEventListeners
;
504 pSVData
->maAppData
.mpEventListeners
= NULL
;
506 if ( pSVData
->maAppData
.mpKeyListeners
)
508 delete pSVData
->maAppData
.mpKeyListeners
;
509 pSVData
->maAppData
.mpKeyListeners
= NULL
;
511 if ( pSVData
->maAppData
.mpPostYieldListeners
)
513 delete pSVData
->maAppData
.mpPostYieldListeners
;
514 pSVData
->maAppData
.mpPostYieldListeners
= NULL
;
517 if ( pSVData
->maAppData
.mpFirstHotKey
)
518 ImplFreeHotKeyData();
519 if ( pSVData
->maAppData
.mpFirstEventHook
)
520 ImplFreeEventHookData();
522 if (pSVData
->mpBlendFrameCache
)
523 delete pSVData
->mpBlendFrameCache
, pSVData
->mpBlendFrameCache
= NULL
;
525 ImplDeletePrnQueueList();
526 delete pSVData
->maGDIData
.mpScreenFontList
;
527 pSVData
->maGDIData
.mpScreenFontList
= NULL
;
528 delete pSVData
->maGDIData
.mpScreenFontCache
;
529 pSVData
->maGDIData
.mpScreenFontCache
= NULL
;
531 if ( pSVData
->mpResMgr
)
533 delete pSVData
->mpResMgr
;
534 pSVData
->mpResMgr
= NULL
;
537 ResMgr::DestroyAllResMgr();
539 // destroy all Sal interfaces before destorying the instance
540 // and thereby unloading the plugin
541 delete pSVData
->mpSalSystem
;
542 pSVData
->mpSalSystem
= NULL
;
543 delete pSVData
->mpSalTimer
;
544 pSVData
->mpSalTimer
= NULL
;
547 DestroySalInstance( pSVData
->mpDefInst
);
555 EmbeddedFontsHelper::clearTemporaryFontFiles();
558 // only one call is allowed
559 struct WorkerThreadData
561 oslWorkerFunction pWorker
;
563 WorkerThreadData( oslWorkerFunction pWorker_
, void * pThreadData_
)
564 : pWorker( pWorker_
)
565 , pThreadData( pThreadData_
)
571 static HANDLE hThreadID
= 0;
572 static unsigned __stdcall
_threadmain( void *pArgs
)
574 OleInitialize( NULL
);
575 ((WorkerThreadData
*)pArgs
)->pWorker( ((WorkerThreadData
*)pArgs
)->pThreadData
);
576 delete (WorkerThreadData
*)pArgs
;
582 static oslThread hThreadID
= 0;
585 static void SAL_CALL
MainWorkerFunction( void* pArgs
)
587 static_cast<WorkerThreadData
*>(pArgs
)->pWorker( static_cast<WorkerThreadData
*>(pArgs
)->pThreadData
);
588 delete static_cast<WorkerThreadData
*>(pArgs
);
594 void CreateMainLoopThread( oslWorkerFunction pWorker
, void * pThreadData
)
597 // sal thread always call CoInitializeEx, so a sysdepen implementation is necessary
600 hThreadID
= (HANDLE
)_beginthreadex(
601 NULL
, // no security handle
602 0, // stacksize 0 means default
603 _threadmain
, // thread worker function
604 new WorkerThreadData( pWorker
, pThreadData
), // arguments for worker function
605 0, // 0 means: create immediately otherwise use CREATE_SUSPENDED
606 &uThreadID
); // thread id to fill
608 hThreadID
= osl_createThread( MainWorkerFunction
, new WorkerThreadData( pWorker
, pThreadData
) );
612 void JoinMainLoopThread()
617 WaitForSingleObject(hThreadID
, INFINITE
);
619 osl_joinWithThread(hThreadID
);
620 osl_destroyThread( hThreadID
);
625 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */