1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: svmain.cxx,v $
10 * $Revision: 1.73.92.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
35 #include <tools/prewin.h>
36 #include <process.h> // for _beginthreadex
37 #include <ole2.h> // for _beginthreadex
38 #include <tools/postwin.h>
41 // [ed 5/14/02 Add in explicit check for quartz graphics. OS X will define
42 // unx for both quartz and X11 graphics, but we include svunx.h only if we're
43 // building X11 graphics layers.
45 #if defined UNX && ! defined QUARTZ
50 #include "vcl/salinst.hxx"
51 #include "vcl/salwtype.hxx"
52 #include "vos/signal.hxx"
53 #include "tools/tools.h"
54 #include "tools/debug.hxx"
55 #include "tools/unqid.hxx"
56 #include "vcl/svdata.hxx"
57 #include "vcl/dbggui.hxx"
58 #include "vcl/svapp.hxx"
59 #include "vcl/wrkwin.hxx"
60 #include "vcl/cvtgrf.hxx"
61 #include "vcl/image.hxx"
62 #include "tools/resmgr.hxx"
63 #include "vcl/accmgr.hxx"
64 #include "vcl/idlemgr.hxx"
65 #include "vcl/outdev.h"
66 #include "vcl/outfont.hxx"
67 #include "vcl/print.h"
68 #include "vcl/settings.hxx"
69 #include "vcl/unowrap.hxx"
70 #include "vcl/salsys.hxx"
71 #include "vcl/saltimer.hxx"
72 #include "vcl/salimestatus.hxx"
73 #include "vcl/impimagetree.hxx"
74 #include "vcl/xconnection.hxx"
76 #include "vos/process.hxx"
77 #include "osl/file.hxx"
78 #include "comphelper/processfactory.hxx"
79 #include "com/sun/star/lang/XMultiServiceFactory.hpp"
80 #include "com/sun/star/lang/XComponent.hpp"
81 #include "rtl/logfile.hxx"
83 #include "vcl/fontcfg.hxx"
84 #include "vcl/configsettings.hxx"
85 #include "vcl/lazydelete.hxx"
87 #include "cppuhelper/implbase1.hxx"
88 #include "uno/current_context.hxx"
90 #if OSL_DEBUG_LEVEL > 0
92 #include "rtl/strbuf.hxx"
95 using namespace ::rtl
;
96 using namespace ::com::sun::star::uno
;
97 using namespace ::com::sun::star::lang
;
101 // =======================================================================
103 class ImplVCLExceptionHandler
: public ::vos::OSignalHandler
106 virtual ::vos::OSignalHandler::TSignalAction SAL_CALL
signal( ::vos::OSignalHandler::TSignalInfo
* pInfo
);
109 // -----------------------------------------------------------------------
111 ::vos::OSignalHandler::TSignalAction SAL_CALL
ImplVCLExceptionHandler::signal( ::vos::OSignalHandler::TSignalInfo
* pInfo
)
113 static BOOL bIn
= FALSE
;
115 // Wenn wir nocheinmal abstuerzen, verabschieden wir uns gleich
118 USHORT nVCLException
= 0;
121 if ( (pInfo
->Signal
== osl_Signal_AccessViolation
) ||
122 (pInfo
->Signal
== osl_Signal_IntegerDivideByZero
) ||
123 (pInfo
->Signal
== osl_Signal_FloatDivideByZero
) ||
124 (pInfo
->Signal
== osl_Signal_DebugBreak
) )
125 nVCLException
= EXC_SYSTEM
;
128 if ((pInfo
->Signal
== osl_Signal_User
) &&
129 (pInfo
->UserSignal
== OSL_SIGNAL_USER_RESOURCEFAILURE
) )
130 nVCLException
= EXC_RSCNOTLOADED
;
133 if ((pInfo
->Signal
== osl_Signal_User
) &&
134 (pInfo
->UserSignal
== OSL_SIGNAL_USER_X11SUBSYSTEMERROR
) )
135 nVCLException
= EXC_DISPLAY
;
138 if ((pInfo
->Signal
== osl_Signal_User
) &&
139 (pInfo
->UserSignal
== OSL_SIGNAL_USER_RVPCONNECTIONERROR
) )
140 nVCLException
= EXC_REMOTE
;
146 ::vos::OGuard
aLock(&Application::GetSolarMutex());
148 // Timer nicht mehr anhalten, da ansonsten die UAE-Box
149 // auch nicht mehr gepaintet wird
150 ImplSVData
* pSVData
= ImplGetSVData();
151 if ( pSVData
->mpApp
)
153 USHORT nOldMode
= Application::GetSystemWindowMode();
154 Application::SetSystemWindowMode( nOldMode
& ~SYSTEMWINDOW_MODE_NOAUTOMODE
);
155 pSVData
->mpApp
->Exception( nVCLException
);
156 Application::SetSystemWindowMode( nOldMode
);
160 return vos::OSignalHandler::TAction_CallNextHandler
;
164 return vos::OSignalHandler::TAction_CallNextHandler
;
167 // =======================================================================
170 // The 'real' SVMain()
171 RTL_LOGFILE_CONTEXT( aLog
, "vcl (ss112471) ::SVMain" );
173 ImplSVData
* pSVData
= ImplGetSVData();
175 DBG_ASSERT( pSVData
->mpApp
, "no instance of class Application" );
177 Reference
<XMultiServiceFactory
> xMS
;
180 BOOL bInit
= InitVCL( xMS
);
184 // Application-Main rufen
185 pSVData
->maAppData
.mbInAppMain
= TRUE
;
186 pSVData
->mpApp
->Main();
187 pSVData
->maAppData
.mbInAppMain
= FALSE
;
190 if( pSVData
->mxDisplayConnection
.is() )
192 vcl::DisplayConnection
* pConnection
=
193 dynamic_cast<vcl::DisplayConnection
*>(pSVData
->mxDisplayConnection
.get());
196 pConnection
->dispatchDowningEvent();
197 pSVData
->mxDisplayConnection
.clear();
200 // This is a hack to work around the problem of the asynchronous nature
201 // of bridging accessibility through Java: on shutdown there might still
202 // be some events in the AWT EventQueue, which need the SolarMutex which
203 // - on the other hand - is destroyed in DeInitVCL(). So empty the queue
205 Reference
< XComponent
> xComponent(pSVData
->mxAccessBridge
, UNO_QUERY
);
206 if( xComponent
.is() )
208 ULONG nCount
= Application::ReleaseSolarMutex();
209 xComponent
->dispose();
210 Application::AcquireSolarMutex(nCount
);
211 pSVData
->mxAccessBridge
.clear();
220 // #i47888# allow for alternative initialization as required for e.g. MacOSX
221 extern BOOL
ImplSVMainHook( BOOL
* );
224 if( ImplSVMainHook( &bInit
) )
229 // This variable is set, when no Application object is instantiated
230 // before SVInit is called
231 static Application
* pOwnSvApp
= NULL
;
232 // Exception handler. pExceptionHandler != NULL => VCL already inited
233 ImplVCLExceptionHandler
* pExceptionHandler
= NULL
;
235 class Application_Impl
: public Application
241 class DesktopEnvironmentContext
: public cppu::WeakImplHelper1
< com::sun::star::uno::XCurrentContext
>
244 DesktopEnvironmentContext( const com::sun::star::uno::Reference
< com::sun::star::uno::XCurrentContext
> & ctx
)
245 : m_xNextContext( ctx
) {}
248 virtual com::sun::star::uno::Any SAL_CALL
getValueByName( const rtl::OUString
& Name
)
249 throw (com::sun::star::uno::RuntimeException
);
252 com::sun::star::uno::Reference
< com::sun::star::uno::XCurrentContext
> m_xNextContext
;
255 Any SAL_CALL
DesktopEnvironmentContext::getValueByName( const rtl::OUString
& Name
) throw (RuntimeException
)
259 if ( 0 == Name
.compareToAscii( "system.desktop-environment" ) )
261 retVal
= makeAny( Application::GetDesktopEnvironment() );
263 else if( m_xNextContext
.is() )
265 // Call next context in chain if found
266 retVal
= m_xNextContext
->getValueByName( Name
);
271 BOOL
InitVCL( const ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XMultiServiceFactory
> & rSMgr
)
273 RTL_LOGFILE_CONTEXT( aLog
, "vcl (ss112471) ::InitVCL" );
275 if( pExceptionHandler
!= NULL
)
278 if( ! ImplGetSVData() )
281 if( !ImplGetSVData()->mpApp
)
283 pOwnSvApp
= new Application_Impl();
288 Application::SetSettings( aAS );// ???
290 ImplSVData
* pSVData
= ImplGetSVData();
292 // SV bei den Tools anmelden
295 DBG_ASSERT( !pSVData
->maAppData
.mxMSF
.is(), "VCL service factory already set" );
296 pSVData
->maAppData
.mxMSF
= rSMgr
;
298 // Main-Thread-Id merken
299 pSVData
->mnMainThreadId
= ::vos::OThread::getCurrentIdentifier();
301 vos::OStartupInfo aStartInfo
;
302 rtl::OUString aExeFileName
;
305 // Sal initialisieren
306 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "{ ::CreateSalInstance" );
307 pSVData
->mpDefInst
= CreateSalInstance();
308 if ( !pSVData
->mpDefInst
)
310 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "} ::CreateSalInstance" );
312 // Desktop Environment context (to be able to get value of "system.desktop-environment" as soon as possible)
313 com::sun::star::uno::setCurrentContext(
314 new DesktopEnvironmentContext( com::sun::star::uno::getCurrentContext() ) );
316 // Initialize application instance (should be done after initialization of VCL SAL part)
318 // call init to initialize application class
319 // soffice/sfx implementation creates the global service manager
320 pSVData
->mpApp
->Init();
322 // Den AppFileName gleich holen und absolut machen, bevor das
323 // WorkingDirectory sich aendert...
324 aStartInfo
.getExecutableFile( aExeFileName
);
326 // convert path to native file format
327 rtl::OUString aNativeFileName
;
328 osl::FileBase::getSystemPathFromFileURL( aExeFileName
, aNativeFileName
);
329 pSVData
->maAppData
.mpAppFileName
= new String( aNativeFileName
);
331 // Initialize global data
332 pSVData
->maGDIData
.mpScreenFontList
= new ImplDevFontList
;
333 pSVData
->maGDIData
.mpScreenFontCache
= new ImplFontCache( FALSE
);
334 pSVData
->maGDIData
.mpGrfConverter
= new GraphicConverter
;
336 // Exception-Handler setzen
337 pExceptionHandler
= new ImplVCLExceptionHandler();
339 // Debug-Daten initialisieren
347 ImplSVData
* pSVData
= ImplGetSVData();
348 pSVData
->mbDeInit
= TRUE
;
350 vcl::DeleteOnDeinitBase::ImplDeleteOnDeInit();
352 // give ime status a chance to destroy its own windows
353 delete pSVData
->mpImeStatus
;
354 pSVData
->mpImeStatus
= NULL
;
356 #if OSL_DEBUG_LEVEL > 0
357 rtl::OStringBuffer
aBuf( 256 );
358 aBuf
.append( "DeInitVCL: some top Windows are still alive\n" );
359 long nTopWindowCount
= Application::GetTopWindowCount();
360 long nBadTopWindows
= nTopWindowCount
;
361 for( long i
= 0; i
< nTopWindowCount
; i
++ )
363 Window
* pWin
= Application::GetTopWindow( i
);
364 // default window will be destroyed further down
365 // but may still be useful during deinit up to that point
366 if( pWin
== pSVData
->mpDefaultWin
)
370 aBuf
.append( "text = \"" );
371 aBuf
.append( rtl::OUStringToOString( pWin
->GetText(), osl_getThreadTextEncoding() ) );
372 aBuf
.append( "\" type = \"" );
373 aBuf
.append( typeid(*pWin
).name() );
374 aBuf
.append( "\"\n" );
377 DBG_ASSERT( nBadTopWindows
==0, aBuf
.getStr() );
380 ImplImageTreeSingletonRef()->shutDown();
382 delete pExceptionHandler
;
383 pExceptionHandler
= NULL
;
385 // Debug Daten zuruecksetzen
389 delete pSVData
->maGDIData
.mpGrfConverter
;
391 if( pSVData
->mpSettingsConfigItem
)
392 delete pSVData
->mpSettingsConfigItem
, pSVData
->mpSettingsConfigItem
= NULL
;
393 if( pSVData
->maGDIData
.mpDefaultFontConfiguration
)
394 delete pSVData
->maGDIData
.mpDefaultFontConfiguration
, pSVData
->maGDIData
.mpDefaultFontConfiguration
= NULL
;
395 if( pSVData
->maGDIData
.mpFontSubstConfiguration
)
396 delete pSVData
->maGDIData
.mpFontSubstConfiguration
, pSVData
->maGDIData
.mpFontSubstConfiguration
= NULL
;
398 if ( pSVData
->maAppData
.mpIdleMgr
)
399 delete pSVData
->maAppData
.mpIdleMgr
;
400 Timer::ImplDeInitTimer();
402 if ( pSVData
->maWinData
.mpMsgBoxImgList
)
404 delete pSVData
->maWinData
.mpMsgBoxImgList
;
405 pSVData
->maWinData
.mpMsgBoxImgList
= NULL
;
407 if ( pSVData
->maWinData
.mpMsgBoxHCImgList
)
409 delete pSVData
->maWinData
.mpMsgBoxHCImgList
;
410 pSVData
->maWinData
.mpMsgBoxHCImgList
= NULL
;
412 if ( pSVData
->maCtrlData
.mpCheckImgList
)
414 delete pSVData
->maCtrlData
.mpCheckImgList
;
415 pSVData
->maCtrlData
.mpCheckImgList
= NULL
;
417 if ( pSVData
->maCtrlData
.mpRadioImgList
)
419 delete pSVData
->maCtrlData
.mpRadioImgList
;
420 pSVData
->maCtrlData
.mpRadioImgList
= NULL
;
422 if ( pSVData
->maCtrlData
.mpPinImgList
)
424 delete pSVData
->maCtrlData
.mpPinImgList
;
425 pSVData
->maCtrlData
.mpPinImgList
= NULL
;
427 if ( pSVData
->maCtrlData
.mpSplitHPinImgList
)
429 delete pSVData
->maCtrlData
.mpSplitHPinImgList
;
430 pSVData
->maCtrlData
.mpSplitHPinImgList
= NULL
;
432 if ( pSVData
->maCtrlData
.mpSplitVPinImgList
)
434 delete pSVData
->maCtrlData
.mpSplitVPinImgList
;
435 pSVData
->maCtrlData
.mpSplitVPinImgList
= NULL
;
437 if ( pSVData
->maCtrlData
.mpSplitHArwImgList
)
439 delete pSVData
->maCtrlData
.mpSplitHArwImgList
;
440 pSVData
->maCtrlData
.mpSplitHArwImgList
= NULL
;
442 if ( pSVData
->maCtrlData
.mpSplitVArwImgList
)
444 delete pSVData
->maCtrlData
.mpSplitVArwImgList
;
445 pSVData
->maCtrlData
.mpSplitVArwImgList
= NULL
;
447 if ( pSVData
->mpDefaultWin
)
449 delete pSVData
->mpDefaultWin
;
450 pSVData
->mpDefaultWin
= NULL
;
453 // #114285# Moved here from ImplDeInitSVData...
454 if ( pSVData
->mpUnoWrapper
)
456 pSVData
->mpUnoWrapper
->Destroy();
457 pSVData
->mpUnoWrapper
= NULL
;
460 pSVData
->maAppData
.mxMSF
.clear();
463 // call deinit to deinitialize application class
464 // soffice/sfx implementation disposes the global service manager
465 // Warning: After this call you can't call uno services
466 pSVData
->mpApp
->DeInit();
468 if ( pSVData
->maAppData
.mpSettings
)
470 delete pSVData
->maAppData
.mpSettings
;
471 pSVData
->maAppData
.mpSettings
= NULL
;
473 if ( pSVData
->maAppData
.mpAccelMgr
)
475 delete pSVData
->maAppData
.mpAccelMgr
;
476 pSVData
->maAppData
.mpAccelMgr
= NULL
;
478 if ( pSVData
->maAppData
.mpUniqueIdCont
)
480 delete pSVData
->maAppData
.mpUniqueIdCont
;
481 pSVData
->maAppData
.mpUniqueIdCont
= NULL
;
483 if ( pSVData
->maAppData
.mpAppFileName
)
485 delete pSVData
->maAppData
.mpAppFileName
;
486 pSVData
->maAppData
.mpAppFileName
= NULL
;
488 if ( pSVData
->maAppData
.mpAppName
)
490 delete pSVData
->maAppData
.mpAppName
;
491 pSVData
->maAppData
.mpAppName
= NULL
;
493 if ( pSVData
->maAppData
.mpDisplayName
)
495 delete pSVData
->maAppData
.mpDisplayName
;
496 pSVData
->maAppData
.mpDisplayName
= NULL
;
498 if ( pSVData
->maAppData
.mpEventListeners
)
500 delete pSVData
->maAppData
.mpEventListeners
;
501 pSVData
->maAppData
.mpEventListeners
= NULL
;
503 if ( pSVData
->maAppData
.mpKeyListeners
)
505 delete pSVData
->maAppData
.mpKeyListeners
;
506 pSVData
->maAppData
.mpKeyListeners
= NULL
;
509 if ( pSVData
->maAppData
.mpFirstHotKey
)
510 ImplFreeHotKeyData();
511 if ( pSVData
->maAppData
.mpFirstEventHook
)
512 ImplFreeEventHookData();
514 ImplDeletePrnQueueList();
515 delete pSVData
->maGDIData
.mpScreenFontList
;
516 pSVData
->maGDIData
.mpScreenFontList
= NULL
;
517 delete pSVData
->maGDIData
.mpScreenFontCache
;
518 pSVData
->maGDIData
.mpScreenFontCache
= NULL
;
519 ImplFreeOutDevFontData();
521 if ( pSVData
->mpResMgr
)
523 delete pSVData
->mpResMgr
;
524 pSVData
->mpResMgr
= NULL
;
527 ResMgr::DestroyAllResMgr();
529 // destroy all Sal interfaces before destorying the instance
530 // and thereby unloading the plugin
531 delete pSVData
->mpSalSystem
;
532 pSVData
->mpSalSystem
= NULL
;
533 delete pSVData
->mpSalTimer
;
534 pSVData
->mpSalTimer
= NULL
;
536 // Sal deinitialisieren
537 DestroySalInstance( pSVData
->mpDefInst
);
550 // only one call is allowed
551 struct WorkerThreadData
553 oslWorkerFunction pWorker
;
555 WorkerThreadData( oslWorkerFunction pWorker_
, void * pThreadData_
)
556 : pWorker( pWorker_
)
557 , pThreadData( pThreadData_
)
563 static HANDLE hThreadID
= 0;
564 static unsigned __stdcall
_threadmain( void *pArgs
)
566 OleInitialize( NULL
);
567 ((WorkerThreadData
*)pArgs
)->pWorker( ((WorkerThreadData
*)pArgs
)->pThreadData
);
568 delete (WorkerThreadData
*)pArgs
;
574 static oslThread hThreadID
= 0;
577 static void SAL_CALL
MainWorkerFunction( void* pArgs
)
579 ((WorkerThreadData
*)pArgs
)->pWorker( ((WorkerThreadData
*)pArgs
)->pThreadData
);
580 delete (WorkerThreadData
*)pArgs
;
586 void CreateMainLoopThread( oslWorkerFunction pWorker
, void * pThreadData
)
589 // sal thread alway call CoInitializeEx, so a sysdepen implementation is necessary
592 hThreadID
= (HANDLE
)_beginthreadex(
593 NULL
, // no security handle
594 0, // stacksize 0 means default
595 _threadmain
, // thread worker function
596 new WorkerThreadData( pWorker
, pThreadData
), // arguments for worker function
597 0, // 0 means: create immediatly otherwise use CREATE_SUSPENDED
598 &uThreadID
); // thread id to fill
600 hThreadID
= osl_createThread( MainWorkerFunction
, new WorkerThreadData( pWorker
, pThreadData
) );
604 void JoinMainLoopThread()
609 WaitForSingleObject(hThreadID
, INFINITE
);
611 osl_joinWithThread(hThreadID
);
612 osl_destroyThread( hThreadID
);