1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_vcl.hxx" 26 27 #include "rtl/logfile.hxx" 28 29 #include "osl/file.hxx" 30 31 #include "vos/signal.hxx" 32 #include "vos/process.hxx" 33 34 #include "tools/tools.h" 35 #include "tools/debug.hxx" 36 #include "tools/unqid.hxx" 37 #include "tools/resmgr.hxx" 38 39 #include "comphelper/processfactory.hxx" 40 41 #include "unotools/syslocaleoptions.hxx" 42 #include "unotools/fontcfg.hxx" 43 44 #include "vcl/svapp.hxx" 45 #include "vcl/wrkwin.hxx" 46 #include "vcl/cvtgrf.hxx" 47 #include "vcl/image.hxx" 48 #include "vcl/settings.hxx" 49 #include "vcl/unowrap.hxx" 50 #include "vcl/configsettings.hxx" 51 #include "vcl/lazydelete.hxx" 52 53 #ifdef WNT 54 #include <tools/prewin.h> 55 #include <process.h> // for _beginthreadex 56 #include <ole2.h> // for _beginthreadex 57 #include <tools/postwin.h> 58 #endif 59 60 // [ed 5/14/02 Add in explicit check for quartz graphics. OS X will define 61 // unx for both quartz and X11 graphics, but we include svunx.h only if we're 62 // building X11 graphics layers. 63 64 #if defined UNX && ! defined QUARTZ 65 //#include "svunx.h" 66 #endif 67 68 //#include "svsys.h" 69 70 #include "salinst.hxx" 71 #include "salwtype.hxx" 72 #include "svdata.hxx" 73 #include "dbggui.hxx" 74 #include "accmgr.hxx" 75 #include "idlemgr.hxx" 76 #include "outdev.h" 77 #include "outfont.hxx" 78 #include "print.h" 79 #include "salsys.hxx" 80 #include "saltimer.hxx" 81 #include "salimestatus.hxx" 82 #include "impimagetree.hxx" 83 #include "xconnection.hxx" 84 85 #include "com/sun/star/lang/XMultiServiceFactory.hpp" 86 #include "com/sun/star/lang/XComponent.hpp" 87 88 #include "cppuhelper/implbase1.hxx" 89 #include "uno/current_context.hxx" 90 91 #if OSL_DEBUG_LEVEL > 0 92 #include <typeinfo> 93 #include "rtl/strbuf.hxx" 94 #endif 95 96 namespace { 97 98 namespace css = com::sun::star; 99 100 } 101 102 using namespace ::rtl; 103 using namespace ::com::sun::star::uno; 104 using namespace ::com::sun::star::lang; 105 106 107 108 // ======================================================================= 109 110 class ImplVCLExceptionHandler : public ::vos::OSignalHandler 111 { 112 public: 113 virtual ::vos::OSignalHandler::TSignalAction SAL_CALL signal( ::vos::OSignalHandler::TSignalInfo* pInfo ); 114 }; 115 116 // ----------------------------------------------------------------------- 117 118 ::vos::OSignalHandler::TSignalAction SAL_CALL ImplVCLExceptionHandler::signal( ::vos::OSignalHandler::TSignalInfo* pInfo ) 119 { 120 static sal_Bool bIn = sal_False; 121 122 // Wenn wir nocheinmal abstuerzen, verabschieden wir uns gleich 123 if ( !bIn ) 124 { 125 sal_uInt16 nVCLException = 0; 126 127 // UAE 128 if ( (pInfo->Signal == osl_Signal_AccessViolation) || 129 (pInfo->Signal == osl_Signal_IntegerDivideByZero) || 130 (pInfo->Signal == osl_Signal_FloatDivideByZero) || 131 (pInfo->Signal == osl_Signal_DebugBreak) ) 132 nVCLException = EXC_SYSTEM; 133 134 // RC 135 if ((pInfo->Signal == osl_Signal_User) && 136 (pInfo->UserSignal == OSL_SIGNAL_USER_RESOURCEFAILURE) ) 137 nVCLException = EXC_RSCNOTLOADED; 138 139 // DISPLAY-Unix 140 if ((pInfo->Signal == osl_Signal_User) && 141 (pInfo->UserSignal == OSL_SIGNAL_USER_X11SUBSYSTEMERROR) ) 142 nVCLException = EXC_DISPLAY; 143 144 // Remote-Client 145 if ((pInfo->Signal == osl_Signal_User) && 146 (pInfo->UserSignal == OSL_SIGNAL_USER_RVPCONNECTIONERROR) ) 147 nVCLException = EXC_REMOTE; 148 149 if ( nVCLException ) 150 { 151 bIn = sal_True; 152 153 ::vos::OGuard aLock(&Application::GetSolarMutex()); 154 155 // Timer nicht mehr anhalten, da ansonsten die UAE-Box 156 // auch nicht mehr gepaintet wird 157 ImplSVData* pSVData = ImplGetSVData(); 158 if ( pSVData->mpApp ) 159 { 160 sal_uInt16 nOldMode = Application::GetSystemWindowMode(); 161 Application::SetSystemWindowMode( nOldMode & ~SYSTEMWINDOW_MODE_NOAUTOMODE ); 162 pSVData->mpApp->Exception( nVCLException ); 163 Application::SetSystemWindowMode( nOldMode ); 164 } 165 bIn = sal_False; 166 167 return vos::OSignalHandler::TAction_CallNextHandler; 168 } 169 } 170 171 return vos::OSignalHandler::TAction_CallNextHandler; 172 } 173 174 // ======================================================================= 175 sal_Bool ImplSVMain() 176 { 177 // The 'real' SVMain() 178 RTL_LOGFILE_CONTEXT( aLog, "vcl (ss112471) ::SVMain" ); 179 180 ImplSVData* pSVData = ImplGetSVData(); 181 182 DBG_ASSERT( pSVData->mpApp, "no instance of class Application" ); 183 184 css::uno::Reference<XMultiServiceFactory> xMS; 185 186 187 sal_Bool bInit = InitVCL( xMS ); 188 189 if( bInit ) 190 { 191 // Application-Main rufen 192 pSVData->maAppData.mbInAppMain = sal_True; 193 pSVData->mpApp->Main(); 194 pSVData->maAppData.mbInAppMain = sal_False; 195 } 196 197 if( pSVData->mxDisplayConnection.is() ) 198 { 199 pSVData->mxDisplayConnection->terminate(); 200 pSVData->mxDisplayConnection.clear(); 201 } 202 203 // This is a hack to work around the problem of the asynchronous nature 204 // of bridging accessibility through Java: on shutdown there might still 205 // be some events in the AWT EventQueue, which need the SolarMutex which 206 // - on the other hand - is destroyed in DeInitVCL(). So empty the queue 207 // here .. 208 css::uno::Reference< XComponent > xComponent(pSVData->mxAccessBridge, UNO_QUERY); 209 if( xComponent.is() ) 210 { 211 sal_uLong nCount = Application::ReleaseSolarMutex(); 212 xComponent->dispose(); 213 Application::AcquireSolarMutex(nCount); 214 pSVData->mxAccessBridge.clear(); 215 } 216 217 DeInitVCL(); 218 return bInit; 219 } 220 221 sal_Bool SVMain() 222 { 223 // #i47888# allow for alternative initialization as required for e.g. MacOSX 224 extern sal_Bool ImplSVMainHook( sal_Bool* ); 225 226 sal_Bool bInit; 227 if( ImplSVMainHook( &bInit ) ) 228 return bInit; 229 else 230 return ImplSVMain(); 231 } 232 // This variable is set, when no Application object is instantiated 233 // before SVInit is called 234 static Application * pOwnSvApp = NULL; 235 // Exception handler. pExceptionHandler != NULL => VCL already inited 236 ImplVCLExceptionHandler * pExceptionHandler = NULL; 237 238 class Application_Impl : public Application 239 { 240 public: 241 void Main(){}; 242 }; 243 244 class DesktopEnvironmentContext: public cppu::WeakImplHelper1< com::sun::star::uno::XCurrentContext > 245 { 246 public: 247 DesktopEnvironmentContext( const com::sun::star::uno::Reference< com::sun::star::uno::XCurrentContext > & ctx) 248 : m_xNextContext( ctx ) {} 249 250 // XCurrentContext 251 virtual com::sun::star::uno::Any SAL_CALL getValueByName( const rtl::OUString& Name ) 252 throw (com::sun::star::uno::RuntimeException); 253 254 private: 255 com::sun::star::uno::Reference< com::sun::star::uno::XCurrentContext > m_xNextContext; 256 }; 257 258 Any SAL_CALL DesktopEnvironmentContext::getValueByName( const rtl::OUString& Name) throw (RuntimeException) 259 { 260 Any retVal; 261 262 if ( 0 == Name.compareToAscii( "system.desktop-environment" ) ) 263 { 264 retVal = makeAny( Application::GetDesktopEnvironment() ); 265 } 266 else if( m_xNextContext.is() ) 267 { 268 // Call next context in chain if found 269 retVal = m_xNextContext->getValueByName( Name ); 270 } 271 return retVal; 272 } 273 274 sal_Bool InitVCL( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & rSMgr ) 275 { 276 RTL_LOGFILE_CONTEXT( aLog, "vcl (ss112471) ::InitVCL" ); 277 278 if( pExceptionHandler != NULL ) 279 return sal_False; 280 281 if( ! ImplGetSVData() ) 282 ImplInitSVData(); 283 284 if( !ImplGetSVData()->mpApp ) 285 { 286 pOwnSvApp = new Application_Impl(); 287 } 288 InitSalMain(); 289 290 /*AllSettings aAS; 291 Application::SetSettings( aAS );// ??? 292 */ 293 ImplSVData* pSVData = ImplGetSVData(); 294 295 // SV bei den Tools anmelden 296 InitTools(); 297 298 DBG_ASSERT( !pSVData->maAppData.mxMSF.is(), "VCL service factory already set" ); 299 pSVData->maAppData.mxMSF = rSMgr; 300 301 // Main-Thread-Id merken 302 pSVData->mnMainThreadId = ::vos::OThread::getCurrentIdentifier(); 303 304 vos::OStartupInfo aStartInfo; 305 rtl::OUString aExeFileName; 306 307 308 // Sal initialisieren 309 RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ ::CreateSalInstance" ); 310 pSVData->mpDefInst = CreateSalInstance(); 311 if ( !pSVData->mpDefInst ) 312 return sal_False; 313 RTL_LOGFILE_CONTEXT_TRACE( aLog, "} ::CreateSalInstance" ); 314 315 // Desktop Environment context (to be able to get value of "system.desktop-environment" as soon as possible) 316 com::sun::star::uno::setCurrentContext( 317 new DesktopEnvironmentContext( com::sun::star::uno::getCurrentContext() ) ); 318 319 // Initialize application instance (should be done after initialization of VCL SAL part) 320 if( pSVData->mpApp ) 321 // call init to initialize application class 322 // soffice/sfx implementation creates the global service manager 323 pSVData->mpApp->Init(); 324 325 // Den AppFileName gleich holen und absolut machen, bevor das 326 // WorkingDirectory sich aendert... 327 aStartInfo.getExecutableFile( aExeFileName ); 328 329 // convert path to native file format 330 rtl::OUString aNativeFileName; 331 osl::FileBase::getSystemPathFromFileURL( aExeFileName, aNativeFileName ); 332 pSVData->maAppData.mpAppFileName = new String( aNativeFileName ); 333 334 // Initialize global data 335 pSVData->maGDIData.mpScreenFontList = new ImplDevFontList; 336 pSVData->maGDIData.mpScreenFontCache = new ImplFontCache( sal_False ); 337 pSVData->maGDIData.mpGrfConverter = new GraphicConverter; 338 339 // Exception-Handler setzen 340 pExceptionHandler = new ImplVCLExceptionHandler(); 341 342 // Debug-Daten initialisieren 343 DBGGUI_INIT(); 344 345 return sal_True; 346 } 347 348 void DeInitVCL() 349 { 350 ImplSVData* pSVData = ImplGetSVData(); 351 pSVData->mbDeInit = sal_True; 352 353 vcl::DeleteOnDeinitBase::ImplDeleteOnDeInit(); 354 355 // give ime status a chance to destroy its own windows 356 delete pSVData->mpImeStatus; 357 pSVData->mpImeStatus = NULL; 358 359 #if OSL_DEBUG_LEVEL > 0 360 rtl::OStringBuffer aBuf( 256 ); 361 aBuf.append( "DeInitVCL: some top Windows are still alive\n" ); 362 long nTopWindowCount = Application::GetTopWindowCount(); 363 long nBadTopWindows = nTopWindowCount; 364 for( long i = 0; i < nTopWindowCount; i++ ) 365 { 366 Window* pWin = Application::GetTopWindow( i ); 367 // default window will be destroyed further down 368 // but may still be useful during deinit up to that point 369 if( pWin == pSVData->mpDefaultWin ) 370 nBadTopWindows--; 371 else 372 { 373 aBuf.append( "text = \"" ); 374 aBuf.append( rtl::OUStringToOString( pWin->GetText(), osl_getThreadTextEncoding() ) ); 375 aBuf.append( "\" type = \"" ); 376 aBuf.append( typeid(*pWin).name() ); 377 aBuf.append( "\", ptr = 0x" ); 378 aBuf.append( sal_Int64( pWin ), 16 ); 379 aBuf.append( "\n" ); 380 } 381 } 382 DBG_ASSERT( nBadTopWindows==0, aBuf.getStr() ); 383 #endif 384 385 ImplImageTreeSingletonRef()->shutDown(); 386 387 delete pExceptionHandler; 388 pExceptionHandler = NULL; 389 390 // Debug Daten zuruecksetzen 391 DBGGUI_DEINIT(); 392 393 // free global data 394 delete pSVData->maGDIData.mpGrfConverter; 395 396 if( pSVData->mpSettingsConfigItem ) 397 delete pSVData->mpSettingsConfigItem, pSVData->mpSettingsConfigItem = NULL; 398 if( pSVData->maGDIData.mpDefaultFontConfiguration ) 399 delete pSVData->maGDIData.mpDefaultFontConfiguration, pSVData->maGDIData.mpDefaultFontConfiguration = NULL; 400 if( pSVData->maGDIData.mpFontSubstConfiguration ) 401 delete pSVData->maGDIData.mpFontSubstConfiguration, pSVData->maGDIData.mpFontSubstConfiguration = NULL; 402 403 if ( pSVData->maAppData.mpIdleMgr ) 404 delete pSVData->maAppData.mpIdleMgr; 405 Timer::ImplDeInitTimer(); 406 407 if ( pSVData->maWinData.mpMsgBoxImgList ) 408 { 409 delete pSVData->maWinData.mpMsgBoxImgList; 410 pSVData->maWinData.mpMsgBoxImgList = NULL; 411 } 412 if ( pSVData->maWinData.mpMsgBoxHCImgList ) 413 { 414 delete pSVData->maWinData.mpMsgBoxHCImgList; 415 pSVData->maWinData.mpMsgBoxHCImgList = NULL; 416 } 417 if ( pSVData->maCtrlData.mpCheckImgList ) 418 { 419 delete pSVData->maCtrlData.mpCheckImgList; 420 pSVData->maCtrlData.mpCheckImgList = NULL; 421 } 422 if ( pSVData->maCtrlData.mpRadioImgList ) 423 { 424 delete pSVData->maCtrlData.mpRadioImgList; 425 pSVData->maCtrlData.mpRadioImgList = NULL; 426 } 427 if ( pSVData->maCtrlData.mpPinImgList ) 428 { 429 delete pSVData->maCtrlData.mpPinImgList; 430 pSVData->maCtrlData.mpPinImgList = NULL; 431 } 432 if ( pSVData->maCtrlData.mpSplitHPinImgList ) 433 { 434 delete pSVData->maCtrlData.mpSplitHPinImgList; 435 pSVData->maCtrlData.mpSplitHPinImgList = NULL; 436 } 437 if ( pSVData->maCtrlData.mpSplitVPinImgList ) 438 { 439 delete pSVData->maCtrlData.mpSplitVPinImgList; 440 pSVData->maCtrlData.mpSplitVPinImgList = NULL; 441 } 442 if ( pSVData->maCtrlData.mpSplitHArwImgList ) 443 { 444 delete pSVData->maCtrlData.mpSplitHArwImgList; 445 pSVData->maCtrlData.mpSplitHArwImgList = NULL; 446 } 447 if ( pSVData->maCtrlData.mpSplitVArwImgList ) 448 { 449 delete pSVData->maCtrlData.mpSplitVArwImgList; 450 pSVData->maCtrlData.mpSplitVArwImgList = NULL; 451 } 452 if ( pSVData->maCtrlData.mpDisclosurePlus ) 453 { 454 delete pSVData->maCtrlData.mpDisclosurePlus; 455 pSVData->maCtrlData.mpDisclosurePlus = NULL; 456 } 457 if ( pSVData->maCtrlData.mpDisclosurePlusHC ) 458 { 459 delete pSVData->maCtrlData.mpDisclosurePlusHC; 460 pSVData->maCtrlData.mpDisclosurePlusHC = NULL; 461 } 462 if ( pSVData->maCtrlData.mpDisclosureMinus ) 463 { 464 delete pSVData->maCtrlData.mpDisclosureMinus; 465 pSVData->maCtrlData.mpDisclosureMinus = NULL; 466 } 467 if ( pSVData->maCtrlData.mpDisclosureMinusHC ) 468 { 469 delete pSVData->maCtrlData.mpDisclosureMinusHC; 470 pSVData->maCtrlData.mpDisclosureMinusHC = NULL; 471 } 472 if ( pSVData->mpDefaultWin ) 473 { 474 delete pSVData->mpDefaultWin; 475 pSVData->mpDefaultWin = NULL; 476 } 477 478 // #114285# Moved here from ImplDeInitSVData... 479 if ( pSVData->mpUnoWrapper ) 480 { 481 pSVData->mpUnoWrapper->Destroy(); 482 pSVData->mpUnoWrapper = NULL; 483 } 484 485 pSVData->maAppData.mxMSF.clear(); 486 487 if( pSVData->mpApp ) 488 // call deinit to deinitialize application class 489 // soffice/sfx implementation disposes the global service manager 490 // Warning: After this call you can't call uno services 491 pSVData->mpApp->DeInit(); 492 493 if ( pSVData->maAppData.mpSettings ) 494 { 495 if ( pSVData->maAppData.mpCfgListener ) 496 { 497 pSVData->maAppData.mpSettings->GetSysLocale().GetOptions().RemoveListener( pSVData->maAppData.mpCfgListener ); 498 delete pSVData->maAppData.mpCfgListener; 499 } 500 501 delete pSVData->maAppData.mpSettings; 502 pSVData->maAppData.mpSettings = NULL; 503 } 504 if ( pSVData->maAppData.mpAccelMgr ) 505 { 506 delete pSVData->maAppData.mpAccelMgr; 507 pSVData->maAppData.mpAccelMgr = NULL; 508 } 509 if ( pSVData->maAppData.mpUniqueIdCont ) 510 { 511 delete pSVData->maAppData.mpUniqueIdCont; 512 pSVData->maAppData.mpUniqueIdCont = NULL; 513 } 514 if ( pSVData->maAppData.mpAppFileName ) 515 { 516 delete pSVData->maAppData.mpAppFileName; 517 pSVData->maAppData.mpAppFileName = NULL; 518 } 519 if ( pSVData->maAppData.mpAppName ) 520 { 521 delete pSVData->maAppData.mpAppName; 522 pSVData->maAppData.mpAppName = NULL; 523 } 524 if ( pSVData->maAppData.mpDisplayName ) 525 { 526 delete pSVData->maAppData.mpDisplayName; 527 pSVData->maAppData.mpDisplayName = NULL; 528 } 529 if ( pSVData->maAppData.mpEventListeners ) 530 { 531 delete pSVData->maAppData.mpEventListeners; 532 pSVData->maAppData.mpEventListeners = NULL; 533 } 534 if ( pSVData->maAppData.mpKeyListeners ) 535 { 536 delete pSVData->maAppData.mpKeyListeners; 537 pSVData->maAppData.mpKeyListeners = NULL; 538 } 539 540 if ( pSVData->maAppData.mpFirstHotKey ) 541 ImplFreeHotKeyData(); 542 if ( pSVData->maAppData.mpFirstEventHook ) 543 ImplFreeEventHookData(); 544 545 ImplDeletePrnQueueList(); 546 delete pSVData->maGDIData.mpScreenFontList; 547 pSVData->maGDIData.mpScreenFontList = NULL; 548 delete pSVData->maGDIData.mpScreenFontCache; 549 pSVData->maGDIData.mpScreenFontCache = NULL; 550 ImplFreeOutDevFontData(); 551 552 if ( pSVData->mpResMgr ) 553 { 554 delete pSVData->mpResMgr; 555 pSVData->mpResMgr = NULL; 556 } 557 558 ResMgr::DestroyAllResMgr(); 559 560 // destroy all Sal interfaces before destorying the instance 561 // and thereby unloading the plugin 562 delete pSVData->mpSalSystem; 563 pSVData->mpSalSystem = NULL; 564 delete pSVData->mpSalTimer; 565 pSVData->mpSalTimer = NULL; 566 567 // Sal deinitialisieren 568 DestroySalInstance( pSVData->mpDefInst ); 569 570 DeInitTools(); 571 572 DeInitSalMain(); 573 574 if( pOwnSvApp ) 575 { 576 delete pOwnSvApp; 577 pOwnSvApp = NULL; 578 } 579 } 580 581 // only one call is allowed 582 struct WorkerThreadData 583 { 584 oslWorkerFunction pWorker; 585 void * pThreadData; 586 WorkerThreadData( oslWorkerFunction pWorker_, void * pThreadData_ ) 587 : pWorker( pWorker_ ) 588 , pThreadData( pThreadData_ ) 589 { 590 } 591 }; 592 593 #ifdef WNT 594 static HANDLE hThreadID = 0; 595 static unsigned __stdcall _threadmain( void *pArgs ) 596 { 597 OleInitialize( NULL ); 598 ((WorkerThreadData*)pArgs)->pWorker( ((WorkerThreadData*)pArgs)->pThreadData ); 599 delete (WorkerThreadData*)pArgs; 600 OleUninitialize(); 601 hThreadID = 0; 602 return 0; 603 } 604 #else 605 static oslThread hThreadID = 0; 606 extern "C" 607 { 608 static void SAL_CALL MainWorkerFunction( void* pArgs ) 609 { 610 ((WorkerThreadData*)pArgs)->pWorker( ((WorkerThreadData*)pArgs)->pThreadData ); 611 delete (WorkerThreadData*)pArgs; 612 hThreadID = 0; 613 } 614 } // extern "C" 615 #endif 616 617 void CreateMainLoopThread( oslWorkerFunction pWorker, void * pThreadData ) 618 { 619 #ifdef WNT 620 // sal thread alway call CoInitializeEx, so a sysdepen implementation is necessary 621 622 unsigned uThreadID; 623 hThreadID = (HANDLE)_beginthreadex( 624 NULL, // no security handle 625 0, // stacksize 0 means default 626 _threadmain, // thread worker function 627 new WorkerThreadData( pWorker, pThreadData ), // arguments for worker function 628 0, // 0 means: create immediatly otherwise use CREATE_SUSPENDED 629 &uThreadID ); // thread id to fill 630 #else 631 hThreadID = osl_createThread( MainWorkerFunction, new WorkerThreadData( pWorker, pThreadData ) ); 632 #endif 633 } 634 635 void JoinMainLoopThread() 636 { 637 if( hThreadID ) 638 { 639 #ifdef WNT 640 WaitForSingleObject(hThreadID, INFINITE); 641 #else 642 osl_joinWithThread(hThreadID); 643 osl_destroyThread( hThreadID ); 644 #endif 645 } 646 } 647