1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_framework.hxx" 30 31 //_________________________________________________________________________________________________________________ 32 // my own includes 33 //_________________________________________________________________________________________________________________ 34 #include <loadenv/loadenv.hxx> 35 36 #ifndef __FRAMEWORK_LOADENV_TARGETHELPER_HXX_ 37 #include <loadenv/targethelper.hxx> 38 #endif 39 40 #ifndef __FRAMEWORK_DESKTOP_HXX_ 41 #include <services/desktop.hxx> 42 #endif 43 #include <helper/ocomponentaccess.hxx> 44 #include <dispatch/dispatchprovider.hxx> 45 46 #ifndef __FRAMEWORK_DISPATCH_INTERCEPTIONHELPER_HXX_ 47 #include <dispatch/interceptionhelper.hxx> 48 #endif 49 #include <classes/taskcreator.hxx> 50 #include <threadhelp/transactionguard.hxx> 51 #include <threadhelp/writeguard.hxx> 52 #include <threadhelp/readguard.hxx> 53 #include <services.h> 54 #include <general.h> 55 #include <properties.h> 56 57 #include <classes/resource.hrc> 58 #include <classes/fwkresid.hxx> 59 60 //_________________________________________________________________________________________________________________ 61 // interface includes 62 //_________________________________________________________________________________________________________________ 63 #include <com/sun/star/beans/PropertyAttribute.hpp> 64 #include <com/sun/star/frame/FrameSearchFlag.hpp> 65 #include <com/sun/star/awt/XToolkit.hpp> 66 #include <com/sun/star/awt/XWindow.hpp> 67 #include <com/sun/star/awt/XWindowPeer.hpp> 68 #include <com/sun/star/awt/WindowDescriptor.hpp> 69 #include <com/sun/star/awt/WindowAttribute.hpp> 70 #include <com/sun/star/awt/PosSize.hpp> 71 #include <com/sun/star/util/XURLTransformer.hpp> 72 #include <com/sun/star/task/XInteractionAbort.hpp> 73 #include <com/sun/star/task/XInteractionApprove.hpp> 74 #include <com/sun/star/document/XInteractionFilterSelect.hpp> 75 #include <com/sun/star/document/AmbigousFilterRequest.hpp> 76 #include <com/sun/star/task/ErrorCodeRequest.hpp> 77 #include <com/sun/star/ucb/InteractiveIOException.hpp> 78 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> 79 #include <com/sun/star/frame/XNotifyingDispatch.hpp> 80 #include <com/sun/star/frame/DispatchResultState.hpp> 81 #include <com/sun/star/lang/IllegalArgumentException.hpp> 82 #include <com/sun/star/lang/DisposedException.hpp> 83 #include <com/sun/star/util/XCloseable.hpp> 84 #include <com/sun/star/document/MacroExecMode.hpp> 85 #include <com/sun/star/document/UpdateDocMode.hpp> 86 #include <com/sun/star/frame/XTerminateListener2.hpp> 87 88 //_________________________________________________________________________________________________________________ 89 // includes of other projects 90 //_________________________________________________________________________________________________________________ 91 #include <cppuhelper/queryinterface.hxx> 92 #include <cppuhelper/typeprovider.hxx> 93 #include <cppuhelper/factory.hxx> 94 #include <cppuhelper/proptypehlp.hxx> 95 #include <rtl/ustrbuf.hxx> 96 #include <rtl/logfile.hxx> 97 #include <vcl/svapp.hxx> 98 99 #ifndef __RSC 100 #include <tools/errinf.hxx> 101 #endif 102 #include <comphelper/extract.hxx> 103 104 #include <fwkdllapi.h> 105 106 //_________________________________________________________________________________________________________________ 107 // namespace 108 //_________________________________________________________________________________________________________________ 109 110 namespace framework{ 111 112 //_________________________________________________________________________________________________________________ 113 // non exported const 114 //_________________________________________________________________________________________________________________ 115 116 //_________________________________________________________________________________________________________________ 117 // non exported definitions 118 //_________________________________________________________________________________________________________________ 119 120 //_________________________________________________________________________________________________________________ 121 // declarations 122 //_________________________________________________________________________________________________________________ 123 124 //***************************************************************************************************************** 125 // XInterface, XTypeProvider, XServiceInfo 126 //***************************************************************************************************************** 127 DEFINE_XINTERFACE_15 ( Desktop , 128 OWeakObject , 129 DIRECT_INTERFACE( css::lang::XTypeProvider ), 130 DIRECT_INTERFACE( css::lang::XServiceInfo ), 131 DIRECT_INTERFACE( css::frame::XDesktop ), 132 DIRECT_INTERFACE( css::frame::XComponentLoader ), 133 DIRECT_INTERFACE( css::frame::XTasksSupplier ), 134 DIRECT_INTERFACE( css::frame::XDispatchProvider ), 135 DIRECT_INTERFACE( css::frame::XDispatchProviderInterception), 136 DIRECT_INTERFACE( css::frame::XFramesSupplier ), 137 DIRECT_INTERFACE( css::frame::XFrame ), 138 DIRECT_INTERFACE( css::lang::XComponent ), 139 DIRECT_INTERFACE( css::frame::XDispatchResultListener ), 140 DIRECT_INTERFACE( css::lang::XEventListener ), 141 DIRECT_INTERFACE( css::task::XInteractionHandler ), 142 DIRECT_INTERFACE( css::beans::XPropertySet ), 143 DIRECT_INTERFACE( css::frame::XUntitledNumbers ) 144 ) 145 146 DEFINE_XTYPEPROVIDER_15 ( Desktop , 147 css::lang::XTypeProvider , 148 css::lang::XServiceInfo , 149 css::frame::XDesktop , 150 css::frame::XComponentLoader , 151 css::frame::XTasksSupplier , 152 css::frame::XDispatchProvider , 153 css::frame::XDispatchProviderInterception , 154 css::frame::XFramesSupplier , 155 css::frame::XFrame , 156 css::lang::XComponent , 157 css::frame::XDispatchResultListener , 158 css::lang::XEventListener , 159 css::task::XInteractionHandler , 160 css::beans::XPropertySet , 161 css::frame::XUntitledNumbers 162 ) 163 164 DEFINE_XSERVICEINFO_ONEINSTANCESERVICE ( Desktop , 165 ::cppu::OWeakObject , 166 SERVICENAME_DESKTOP , 167 IMPLEMENTATIONNAME_DESKTOP 168 ) 169 170 DEFINE_INIT_SERVICE ( Desktop, 171 { 172 /*Attention 173 I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance() 174 to create a new instance of this class by our own supported service factory. 175 see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations! 176 */ 177 178 //------------------------------------------------------------------------------------------------------------- 179 // Initialize a new XFrames-helper-object to handle XIndexAccess and XElementAccess. 180 // We hold member as reference ... not as pointer too! 181 // Attention: We share our frame container with this helper. Container is threadsafe himself ... So I think we can do that. 182 // But look on dispose() for right order of deinitialization. 183 OFrames* pFramesHelper = new OFrames( m_xFactory, this, &m_aChildTaskContainer ); 184 m_xFramesHelper = css::uno::Reference< css::frame::XFrames >( static_cast< ::cppu::OWeakObject* >(pFramesHelper), css::uno::UNO_QUERY ); 185 186 //------------------------------------------------------------------------------------------------------------- 187 // Initialize a new dispatchhelper-object to handle dispatches. 188 // We use these helper as slave for our interceptor helper ... not directly! 189 // But he is event listener on THIS instance! 190 DispatchProvider* pDispatchHelper = new DispatchProvider( m_xFactory, this ); 191 css::uno::Reference< css::frame::XDispatchProvider > xDispatchProvider( static_cast< ::cppu::OWeakObject* >(pDispatchHelper), css::uno::UNO_QUERY ); 192 193 //------------------------------------------------------------------------------------------------------------- 194 // Initialize a new interception helper object to handle dispatches and implement an interceptor mechanism. 195 // Set created dispatch provider as slowest slave of it. 196 // Hold interception helper by reference only - not by pointer! 197 // So it's easiear to destroy it. 198 InterceptionHelper* pInterceptionHelper = new InterceptionHelper( this, xDispatchProvider ); 199 m_xDispatchHelper = css::uno::Reference< css::frame::XDispatchProvider >( static_cast< ::cppu::OWeakObject* >(pInterceptionHelper), css::uno::UNO_QUERY ); 200 201 ::rtl::OUStringBuffer sUntitledPrefix (256); 202 sUntitledPrefix.append (::rtl::OUString( String( FwkResId( STR_UNTITLED_DOCUMENT )))); 203 sUntitledPrefix.appendAscii (" "); 204 205 ::comphelper::NumberedCollection* pNumbers = new ::comphelper::NumberedCollection (); 206 m_xTitleNumberGenerator = css::uno::Reference< css::frame::XUntitledNumbers >(static_cast< ::cppu::OWeakObject* >(pNumbers), css::uno::UNO_QUERY_THROW); 207 pNumbers->setOwner ( static_cast< ::cppu::OWeakObject* >(this) ); 208 pNumbers->setUntitledPrefix ( sUntitledPrefix.makeStringAndClear () ); 209 210 // Safe impossible cases 211 // We can't work without this helper! 212 LOG_ASSERT2( m_xFramesHelper.is ()==sal_False, "Desktop::Desktop()", "Frames helper is not valid. XFrames, XIndexAccess and XElementAcces are not supported!\n") 213 LOG_ASSERT2( m_xDispatchHelper.is()==sal_False, "Desktop::Desktop()", "Dispatch helper is not valid. XDispatch will not work correctly!\n" ) 214 215 // Enable object for real working! 216 // Otherwise all calls will be rejected ... 217 m_aTransactionManager.setWorkingMode( E_WORK ); 218 } 219 ) 220 221 /*-************************************************************************************************************//** 222 @short standard constructor to create instance by factory 223 @descr This constructor initialize a new instance of this class by valid factory, 224 and will be set valid values on his member and baseclasses. 225 226 @attention a) Don't use your own reference during an UNO-Service-ctor! There is no guarantee, that you 227 will get over this. (e.g. using of your reference as parameter to initialize some member) 228 Do such things in DEFINE_INIT_SERVICE() method, which is called automaticly after your ctor!!! 229 b) Baseclass OBroadcastHelper is a typedef in namespace cppu! 230 The microsoft compiler has some problems to handle it right BY using namespace explicitly ::cppu::OBroadcastHelper. 231 If we write it without a namespace or expand the typedef to OBrodcastHelperVar<...> -> it will be OK!? 232 I don't know why! (other compiler not tested .. but it works!) 233 234 @seealso method DEFINE_INIT_SERVICE() 235 236 @param "xFactory" is the multi service manager, which create this instance. 237 The value must be different from NULL! 238 @return - 239 240 @onerror We throw an ASSERT in debug version or do nothing in relaese version. 241 *//*-*************************************************************************************************************/ 242 Desktop::Desktop( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory ) 243 // Init baseclasses first 244 // Attention: Don't change order of initialization! 245 // ThreadHelpBase is a struct with a lock as member. We can't use a lock as direct member! 246 // We must garant right initialization and a valid value of this to initialize other baseclasses! 247 : ThreadHelpBase ( &Application::GetSolarMutex() ) 248 , TransactionBase ( ) 249 , ::cppu::OBroadcastHelperVar< ::cppu::OMultiTypeInterfaceContainerHelper, ::cppu::OMultiTypeInterfaceContainerHelper::keyType > ( m_aLock.getShareableOslMutex() ) 250 , ::cppu::OPropertySetHelper ( *(static_cast< ::cppu::OBroadcastHelper* >(this)) ) 251 , ::cppu::OWeakObject ( ) 252 // Init member 253 #ifdef ENABLE_ASSERTIONS 254 , m_bIsTerminated ( sal_False ) // see dispose() for further informations! 255 #endif 256 , m_xFactory ( xFactory ) 257 , m_aChildTaskContainer ( ) 258 , m_aListenerContainer ( m_aLock.getShareableOslMutex() ) 259 , m_xFramesHelper ( ) 260 , m_xDispatchHelper ( ) 261 , m_eLoadState ( E_NOTSET ) 262 , m_xLastFrame ( ) 263 , m_aInteractionRequest ( ) 264 , m_bSuspendQuickstartVeto( sal_False ) 265 , m_aCommandOptions ( ) 266 , m_sName ( ) 267 , m_sTitle ( ) 268 , m_xDispatchRecorderSupplier( ) 269 , m_xPipeTerminator ( ) 270 , m_xQuickLauncher ( ) 271 , m_xSWThreadManager ( ) 272 , m_xSfxTerminator ( ) 273 , m_xTitleNumberGenerator ( ) 274 { 275 // Safe impossible cases 276 // We don't accept all incoming parameter. 277 LOG_ASSERT2( implcp_ctor( xFactory ), "Desktop::Desktop()", "Invalid parameter detected!") 278 } 279 280 /*-************************************************************************************************************//** 281 @short standard destructor 282 @descr This one do NOTHING! Use dispose() instaed of this. 283 284 @seealso method dispose() 285 286 @param - 287 @return - 288 289 @onerror - 290 *//*-*************************************************************************************************************/ 291 Desktop::~Desktop() 292 { 293 LOG_ASSERT2( m_bIsTerminated ==sal_False, "Desktop::~Desktop()", "Who forgot to terminate the desktop service?" ) 294 LOG_ASSERT2( m_aTransactionManager.getWorkingMode()!=E_CLOSE , "Desktop::~Desktop()", "Who forgot to dispose this service?" ) 295 } 296 297 //============================================================================= 298 sal_Bool SAL_CALL Desktop::terminate() 299 throw( css::uno::RuntimeException ) 300 { 301 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 302 303 SYNCHRONIZED_START 304 ReadGuard aReadLock( m_aLock ); 305 306 css::uno::Reference< css::frame::XTerminateListener > xPipeTerminator = m_xPipeTerminator; 307 css::uno::Reference< css::frame::XTerminateListener > xQuickLauncher = m_xQuickLauncher; 308 css::uno::Reference< css::frame::XTerminateListener > xSWThreadManager = m_xSWThreadManager; 309 css::uno::Reference< css::frame::XTerminateListener > xSfxTerminator = m_xSfxTerminator; 310 311 css::lang::EventObject aEvent ( static_cast< ::cppu::OWeakObject* >(this) ); 312 ::sal_Bool bAskQuickStart = !m_bSuspendQuickstartVeto ; 313 314 aReadLock.unlock(); 315 SYNCHRONIZED_END 316 317 //------------------------------------------------------------------------------------------------------------- 318 // Ask normal terminate listener. They could stop terminate without closing any open document. 319 Desktop::TTerminateListenerList lCalledTerminationListener; 320 ::sal_Bool bVeto = sal_False; 321 impl_sendQueryTerminationEvent(lCalledTerminationListener, bVeto); 322 if ( bVeto ) 323 { 324 impl_sendCancelTerminationEvent(lCalledTerminationListener); 325 return sal_False; 326 } 327 328 //------------------------------------------------------------------------------------------------------------- 329 // try to close all open frames. 330 // Allow using of any UI ... because Desktop.terminate() was designed as UI functionality in the past. 331 ::sal_Bool bAllowUI = sal_True; 332 ::sal_Bool bFramesClosed = impl_closeFrames(bAllowUI); 333 if ( ! bFramesClosed ) 334 { 335 impl_sendCancelTerminationEvent(lCalledTerminationListener); 336 return sal_False; 337 } 338 339 //------------------------------------------------------------------------------------------------------------- 340 // Normal listener had no problem ... 341 // all frames was closed ... 342 // now it's time to ask our specialized listener. 343 // They are handled these way because they wish to hinder the office on termination 344 // but they wish also closing of all frames. 345 346 // Note further: 347 // We shouldn't ask quicklauncher in case it was allowed from outside only. 348 // This is special trick to "ignore existing quick starter" for debug purposes. 349 350 // Attention: 351 // Order of alled listener is important ! 352 // some of them are harmless .-) 353 // But some of them can be dangerous. E.g. it would be dangerous if we close our pipe 354 // and dont terminate in real because another listener throws a veto exception .-) 355 356 ::sal_Bool bTerminate = sal_False; 357 try 358 { 359 if( 360 ( bAskQuickStart ) && 361 ( xQuickLauncher.is() ) 362 ) 363 { 364 xQuickLauncher->queryTermination( aEvent ); 365 lCalledTerminationListener.push_back( xQuickLauncher ); 366 } 367 368 if ( xSWThreadManager.is() ) 369 { 370 xSWThreadManager->queryTermination( aEvent ); 371 lCalledTerminationListener.push_back( xSWThreadManager ); 372 } 373 374 if ( xPipeTerminator.is() ) 375 { 376 xPipeTerminator->queryTermination( aEvent ); 377 lCalledTerminationListener.push_back( xPipeTerminator ); 378 } 379 380 if ( xSfxTerminator.is() ) 381 { 382 xSfxTerminator->queryTermination( aEvent ); 383 lCalledTerminationListener.push_back( xSfxTerminator ); 384 } 385 386 bTerminate = sal_True; 387 } 388 catch(const css::frame::TerminationVetoException&) 389 { 390 bTerminate = sal_False; 391 } 392 393 if ( ! bTerminate ) 394 impl_sendCancelTerminationEvent(lCalledTerminationListener); 395 else 396 { 397 #ifdef ENABLE_ASSERTIONS 398 // "Protect" us against dispose before terminate calls! 399 // see dispose() for further informations. 400 /* SAFE AREA --------------------------------------------------------------------------------------- */ 401 WriteGuard aWriteLock( m_aLock ); 402 m_bIsTerminated = sal_True; 403 aWriteLock.unlock(); 404 /* UNSAFE AREA ------------------------------------------------------------------------------------- */ 405 #endif 406 407 impl_sendNotifyTerminationEvent(); 408 409 if( 410 ( bAskQuickStart ) && 411 ( xQuickLauncher.is() ) 412 ) 413 { 414 xQuickLauncher->notifyTermination( aEvent ); 415 } 416 417 if ( xSWThreadManager.is() ) 418 xSWThreadManager->notifyTermination( aEvent ); 419 420 if ( xPipeTerminator.is() ) 421 xPipeTerminator->notifyTermination( aEvent ); 422 423 // Must be realy the last listener to be called. 424 // Because it shutdown the whole process asynchronous ! 425 if ( xSfxTerminator.is() ) 426 xSfxTerminator->notifyTermination( aEvent ); 427 } 428 429 return bTerminate; 430 } 431 432 433 //============================================================================= 434 void SAL_CALL Desktop::addTerminateListener( const css::uno::Reference< css::frame::XTerminateListener >& xListener ) 435 throw( css::uno::RuntimeException ) 436 { 437 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 438 439 css::uno::Reference< css::lang::XServiceInfo > xInfo( xListener, css::uno::UNO_QUERY ); 440 if ( xInfo.is() ) 441 { 442 ::rtl::OUString sImplementationName = xInfo->getImplementationName(); 443 444 // SYCNHRONIZED -> 445 WriteGuard aWriteLock( m_aLock ); 446 447 if( sImplementationName.equals(IMPLEMENTATIONNAME_SFXTERMINATOR) ) 448 { 449 m_xSfxTerminator = xListener; 450 return; 451 } 452 if( sImplementationName.equals(IMPLEMENTATIONNAME_PIPETERMINATOR) ) 453 { 454 m_xPipeTerminator = xListener; 455 return; 456 } 457 if( sImplementationName.equals(IMPLEMENTATIONNAME_QUICKLAUNCHER) ) 458 { 459 m_xQuickLauncher = xListener; 460 return; 461 } 462 if( sImplementationName.equals(IMPLEMENTATIONNAME_SWTHREADMANAGER) ) 463 { 464 m_xSWThreadManager = xListener; 465 return; 466 } 467 468 aWriteLock.unlock(); 469 // <- SYCNHRONIZED 470 } 471 472 // No lock required ... container is threadsafe by itself. 473 m_aListenerContainer.addInterface( ::getCppuType( ( const css::uno::Reference< css::frame::XTerminateListener >*) NULL ), xListener ); 474 } 475 476 //============================================================================= 477 void SAL_CALL Desktop::removeTerminateListener( const css::uno::Reference< css::frame::XTerminateListener >& xListener ) 478 throw( css::uno::RuntimeException ) 479 { 480 TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS ); 481 482 css::uno::Reference< css::lang::XServiceInfo > xInfo( xListener, css::uno::UNO_QUERY ); 483 if ( xInfo.is() ) 484 { 485 ::rtl::OUString sImplementationName = xInfo->getImplementationName(); 486 487 // SYCNHRONIZED -> 488 WriteGuard aWriteLock( m_aLock ); 489 490 if( sImplementationName.equals(IMPLEMENTATIONNAME_SFXTERMINATOR) ) 491 { 492 m_xSfxTerminator.clear(); 493 return; 494 } 495 496 if( sImplementationName.equals(IMPLEMENTATIONNAME_PIPETERMINATOR) ) 497 { 498 m_xPipeTerminator.clear(); 499 return; 500 } 501 502 if( sImplementationName.equals(IMPLEMENTATIONNAME_QUICKLAUNCHER) ) 503 { 504 m_xQuickLauncher.clear(); 505 return; 506 } 507 508 if( sImplementationName.equals(IMPLEMENTATIONNAME_SWTHREADMANAGER) ) 509 { 510 m_xSWThreadManager.clear(); 511 return; 512 } 513 514 aWriteLock.unlock(); 515 // <- SYCNHRONIZED 516 } 517 518 // No lock required ... container is threadsafe by itself. 519 m_aListenerContainer.removeInterface( ::getCppuType( ( const css::uno::Reference< css::frame::XTerminateListener >*) NULL ), xListener ); 520 } 521 522 /*-************************************************************************************************************//** 523 @interface XDesktop 524 @short get access to create enumerations of all current components 525 @descr You will be the owner of the returned object and must delete it if you don't use it again. 526 527 @seealso class TasksAccess 528 @seealso class TasksEnumeration 529 530 @param - 531 @return A reference to an XEnumerationAccess-object. 532 533 @onerror We return a null-reference. 534 @threadsafe yes 535 *//*-*************************************************************************************************************/ 536 css::uno::Reference< css::container::XEnumerationAccess > SAL_CALL Desktop::getComponents() throw( css::uno::RuntimeException ) 537 { 538 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ 539 // Register transaction and reject wrong calls. 540 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 541 542 // We use a helper class OComponentAccess to have access on all child components. 543 // Create it on demand and return it as a reference. 544 OComponentAccess* pAccess = new OComponentAccess( this ); 545 css::uno::Reference< css::container::XEnumerationAccess > xAccess( static_cast< ::cppu::OWeakObject* >(pAccess), css::uno::UNO_QUERY ); 546 return xAccess; 547 } 548 549 /*-************************************************************************************************************//** 550 @interface XDesktop 551 @short return the current active component 552 @descr The most current component is the window, model or the controller of the current active frame. 553 554 @seealso method getCurrentFrame() 555 @seealso method impl_getFrameComponent() 556 557 @param - 558 @return A reference to the component. 559 560 @onerror We return a null-reference. 561 @threadsafe yes 562 *//*-*************************************************************************************************************/ 563 css::uno::Reference< css::lang::XComponent > SAL_CALL Desktop::getCurrentComponent() throw( css::uno::RuntimeException ) 564 { 565 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ 566 // Register transaction and reject wrong calls. 567 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 568 569 // Set return value if method failed. 570 css::uno::Reference< css::lang::XComponent > xComponent; 571 572 // Get reference to current frame ... 573 // ... get component of this frame ... (It can be the window, the model or the controller.) 574 // ... and return the result. 575 css::uno::Reference< css::frame::XFrame > xCurrentFrame = getCurrentFrame(); 576 if( xCurrentFrame.is() == sal_True ) 577 { 578 xComponent = impl_getFrameComponent( xCurrentFrame ); 579 } 580 return xComponent; 581 } 582 583 /*-************************************************************************************************************//** 584 @interface XDesktop 585 @short return the current active frame in hierarchy 586 @descr There can be more then one different active pathes in our frame hierarchy. But only one of them 587 could be the most active frame (normal he has the focus). 588 Don't mix it with getActiveFrame()! That will return our current active frame, which must be 589 a direct child of us and should be a part(!) of an active path. 590 591 @seealso method getActiveFrame() 592 593 @param - 594 @return A valid reference, if there is an active frame. 595 A null reference , otherwise. 596 597 @onerror We return a null reference. 598 @threadsafe yes 599 *//*-*************************************************************************************************************/ 600 css::uno::Reference< css::frame::XFrame > SAL_CALL Desktop::getCurrentFrame() throw( css::uno::RuntimeException ) 601 { 602 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ 603 // Register transaction and reject wrong calls. 604 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 605 606 // Start search with ouer direct active frame (if it exist!). 607 // Search on his children for other active frames too. 608 // Stop if no one could be found and return last of found ones. 609 css::uno::Reference< css::frame::XFramesSupplier > xLast = css::uno::Reference< css::frame::XFramesSupplier >( getActiveFrame(), css::uno::UNO_QUERY ); 610 if( xLast.is() == sal_True ) 611 { 612 css::uno::Reference< css::frame::XFramesSupplier > xNext = css::uno::Reference< css::frame::XFramesSupplier >( xLast->getActiveFrame(), css::uno::UNO_QUERY ); 613 while( xNext.is() == sal_True ) 614 { 615 xLast = xNext; 616 xNext = css::uno::Reference< css::frame::XFramesSupplier >( xNext->getActiveFrame(), css::uno::UNO_QUERY ); 617 } 618 } 619 return css::uno::Reference< css::frame::XFrame >( xLast, css::uno::UNO_QUERY ); 620 } 621 622 /*-************************************************************************************************************//** 623 @interface XComponentLoader 624 @short try to load given URL into a task 625 @descr You can give us some informations about the content, which you will load into a frame. 626 We search or create this target for you, make a type detection of given URL and try to load it. 627 As result of this operation we return the new created component or nothing, if loading failed. 628 629 @seealso - 630 631 @param "sURL" , URL, which represant the content 632 @param "sTargetFrameName" , name of target frame or special value like "_self", "_blank" ... 633 @param "nSearchFlags" , optional arguments for frame search, if target isn't a special one 634 @param "lArguments" , optional arguments for loading 635 @return A valid component reference, if loading was successfully. 636 A null reference otherwise. 637 638 @onerror We return a null reference. 639 @threadsafe yes 640 *//*-*************************************************************************************************************/ 641 css::uno::Reference< css::lang::XComponent > SAL_CALL Desktop::loadComponentFromURL( const ::rtl::OUString& sURL , 642 const ::rtl::OUString& sTargetFrameName, 643 sal_Int32 nSearchFlags , 644 const css::uno::Sequence< css::beans::PropertyValue >& lArguments ) throw( css::io::IOException , 645 css::lang::IllegalArgumentException , 646 css::uno::RuntimeException ) 647 { 648 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ 649 // Register transaction and reject wrong calls. 650 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 651 RTL_LOGFILE_CONTEXT( aLog, "framework (as96863) ::Desktop::loadComponentFromURL" ); 652 653 ReadGuard aReadLock(m_aLock); 654 css::uno::Reference< css::frame::XComponentLoader > xThis(static_cast< css::frame::XComponentLoader* >(this), css::uno::UNO_QUERY); 655 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xFactory; 656 aReadLock.unlock(); 657 658 RTL_LOGFILE_PRODUCT_CONTEXT( aLog2, "PERFORMANCE - Desktop::loadComponentFromURL()" ); 659 return LoadEnv::loadComponentFromURL(xThis, xSMGR, sURL, sTargetFrameName, nSearchFlags, lArguments); 660 } 661 662 /*-************************************************************************************************************//** 663 @interface XTasksSupplier 664 @short get access to create enumerations of ouer taskchilds 665 @descr Direct childs of desktop are tasks everytime. 666 Call these method to could create enumerations of it. 667 668 But; Don't forget - you will be the owner of returned object and must release it! 669 We use a helper class to implement the access interface. They hold a weakreference to us. 670 It can be, that the desktop is dead - but not your tasksaccess-object! Then they will do nothing! 671 You can't create enumerations then. 672 673 @attention Normaly we don't need any lock here. We don't work on internal member! 674 675 @seealso class TasksAccess 676 677 @param - 678 @return A reference to an accessobject, which can create enumerations of ouer childtasks. 679 680 @onerror A null reference is returned. 681 @threadsafe yes 682 *//*-*************************************************************************************************************/ 683 css::uno::Reference< css::container::XEnumerationAccess > SAL_CALL Desktop::getTasks() throw( css::uno::RuntimeException ) 684 { 685 LOG_WARNING("Desktop::getTasks()", "Use of obsolete interface XTaskSupplier") 686 return NULL; 687 /* 688 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 689 690 OTasksAccess* pTasksAccess = new OTasksAccess( this, &m_aChildTaskContainer ); 691 css::uno::Reference< css::container::XEnumerationAccess > xAccess( static_cast< ::cppu::OWeakObject* >(pTasksAccess), css::uno::UNO_QUERY ); 692 return xAccess; 693 */ 694 } 695 696 /*-************************************************************************************************************//** 697 @interface XTasksSupplier 698 @short return current active task of ouer direct childs 699 @descr Desktop childs are tasks only ! If we have an active path from desktop 700 as top to any frame on bottom, we must have an active direct child. His reference is returned here. 701 702 @attention a) Do not confuse it with getCurrentFrame()! The current frame don't must one of ouer direct childs. 703 It can be every frame in subtree and must have the focus (Is the last one of an active path!). 704 b) We don't need any lock here. Our container is threadsafe himself and live, if we live! 705 706 @seealso method getCurrentFrame() 707 708 @param - 709 @return A reference to ouer current active taskchild. 710 711 @onerror A null reference is returned. 712 @threadsafe yes 713 *//*-*************************************************************************************************************/ 714 css::uno::Reference< css::frame::XTask > SAL_CALL Desktop::getActiveTask() throw( css::uno::RuntimeException ) 715 { 716 /* 717 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 718 719 return css::uno::Reference< css::frame::XTask >( m_aChildTaskContainer.getActive(), css::uno::UNO_QUERY ); 720 */ 721 LOG_WARNING("Desktop::getActiveTask()", "Use of obsolete interface XTaskSupplier") 722 return NULL; 723 } 724 725 /*-************************************************************************************************************//** 726 @interface XDispatchProvider 727 @short search a dispatcher for given URL 728 @descr We use a helper implementation (class DispatchProvider) to do so. 729 So we don't must implement this algorithm twice! 730 731 @attention We don't need any lock here. Our helper is threadsafe himself and live, if we live! 732 733 @seealso class DispatchProvider 734 735 @param "aURL" , URL to dispatch 736 @param "sTargetFrameName" , name of target frame, who should dispatch these URL 737 @param "nSearchFlags" , flags to regulate the search 738 @param "lQueries" , list of queryDispatch() calls! 739 @return A reference or list of founded dispatch objects for these URL. 740 741 @onerror A null reference is returned. 742 @threadsafe yes 743 *//*-*************************************************************************************************************/ 744 css::uno::Reference< css::frame::XDispatch > SAL_CALL Desktop::queryDispatch( const css::util::URL& aURL , 745 const ::rtl::OUString& sTargetFrameName , 746 sal_Int32 nSearchFlags ) throw( css::uno::RuntimeException ) 747 { 748 const char UNO_PROTOCOL[] = ".uno:"; 749 750 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ 751 // Register transaction and reject wrong calls. 752 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 753 754 // Remove uno and cmd protocol part as we want to support both of them. We store only the command part 755 // in our hash map. All other protocols are stored with the protocol part. 756 String aCommand( aURL.Main ); 757 if ( aURL.Protocol.equalsIgnoreAsciiCaseAsciiL( UNO_PROTOCOL, sizeof( UNO_PROTOCOL )-1 )) 758 aCommand = aURL.Path; 759 760 // Make hash_map lookup if the current URL is in the disabled list 761 if ( m_aCommandOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED, aCommand ) ) 762 return css::uno::Reference< css::frame::XDispatch >(); 763 else 764 { 765 // We use a helper to support these interface and an interceptor mechanism. 766 // Our helper is threadsafe by himself! 767 return m_xDispatchHelper->queryDispatch( aURL, sTargetFrameName, nSearchFlags ); 768 } 769 } 770 771 //***************************************************************************************************************** 772 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL Desktop::queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lQueries ) throw( css::uno::RuntimeException ) 773 { 774 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ 775 // Register transaction and reject wrong calls. 776 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 777 778 return m_xDispatchHelper->queryDispatches( lQueries ); 779 } 780 781 /*-************************************************************************************************************//** 782 @interface XDipsatchProviderInterception 783 @short supports registration/deregistration of interception objects, which 784 are interested on special dispatches. 785 786 @descr Its realy provided by an internal helper, which is used inside the dispatch api too. 787 @param xInterceptor 788 the interceptor object, which wish to be (de)registered. 789 790 @threadsafe yes 791 *//*-*************************************************************************************************************/ 792 void SAL_CALL Desktop::registerDispatchProviderInterceptor( const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor) 793 throw( css::uno::RuntimeException) 794 { 795 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 796 797 css::uno::Reference< css::frame::XDispatchProviderInterception > xInterceptionHelper( m_xDispatchHelper, css::uno::UNO_QUERY ); 798 xInterceptionHelper->registerDispatchProviderInterceptor( xInterceptor ); 799 } 800 801 //***************************************************************************************************************** 802 void SAL_CALL Desktop::releaseDispatchProviderInterceptor ( const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor) 803 throw( css::uno::RuntimeException) 804 { 805 TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS ); 806 807 css::uno::Reference< css::frame::XDispatchProviderInterception > xInterceptionHelper( m_xDispatchHelper, css::uno::UNO_QUERY ); 808 xInterceptionHelper->releaseDispatchProviderInterceptor( xInterceptor ); 809 } 810 811 /*-************************************************************************************************************//** 812 @interface XFramesSupplier 813 @short return access to append or remove childs on desktop 814 @descr We don't implement these interface directly. We use a helper class to do this. 815 If you wish to add or delete childs to/from the container, call these method to get 816 a reference to the helper. 817 818 @attention Helper is threadsafe himself. So we don't need any lock here. 819 820 @seealso class OFrames 821 822 @param - 823 @return A reference to the helper. 824 825 @onerror A null reference is returned. 826 @threadsafe yes 827 *//*-*************************************************************************************************************/ 828 css::uno::Reference< css::frame::XFrames > SAL_CALL Desktop::getFrames() throw( css::uno::RuntimeException ) 829 { 830 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ 831 // Register transaction and reject wrong calls. 832 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 833 834 return m_xFramesHelper; 835 } 836 837 /*-************************************************************************************************************//** 838 @interface XFramesSupplier 839 @short set/get the current active child frame 840 @descr It must be a task. Direct childs of desktop are tasks only! No frames are accepted. 841 We don't save this information directly in this class. We use ouer container-helper 842 to do that. 843 844 @attention Helper is threadsafe himself. So we don't need any lock here. 845 846 @seealso class OFrameContainer 847 848 @param "xFrame", new active frame (must be valid!) 849 @return A reference to ouer current active childtask, if anyone exist. 850 851 @onerror A null reference is returned. 852 @threadsafe yes 853 *//*-*************************************************************************************************************/ 854 void SAL_CALL Desktop::setActiveFrame( const css::uno::Reference< css::frame::XFrame >& xFrame ) throw( css::uno::RuntimeException ) 855 { 856 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ 857 // Register transaction and reject wrong calls. 858 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 859 860 // Get old active frame first. 861 // If nothing will change - do nothing! 862 // Otherwise set new active frame ... 863 // and deactivate last frame. 864 // It's neccessary for our FrameActionEvent listener on a frame! 865 css::uno::Reference< css::frame::XFrame > xLastActiveChild = m_aChildTaskContainer.getActive(); 866 if( xLastActiveChild != xFrame ) 867 { 868 m_aChildTaskContainer.setActive( xFrame ); 869 if( xLastActiveChild.is() == sal_True ) 870 { 871 xLastActiveChild->deactivate(); 872 } 873 } 874 } 875 876 //***************************************************************************************************************** 877 css::uno::Reference< css::frame::XFrame > SAL_CALL Desktop::getActiveFrame() throw( css::uno::RuntimeException ) 878 { 879 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ 880 // Register transaction and reject wrong calls. 881 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 882 883 return m_aChildTaskContainer.getActive(); 884 } 885 886 /*-************************************************************************************************************//** 887 @interface XFrame 888 @short non implemented methods! 889 @descr Some method make no sense for our desktop! He has no window or parent or ... 890 So we should implement it empty and warn programmer, if he use it! 891 892 @seealso - 893 894 @param - 895 @return - 896 897 @onerror - 898 @threadsafe - 899 *//*-*************************************************************************************************************/ 900 void SAL_CALL Desktop::initialize( const css::uno::Reference< css::awt::XWindow >& ) throw( css::uno::RuntimeException ) 901 { 902 } 903 904 //***************************************************************************************************************** 905 css::uno::Reference< css::awt::XWindow > SAL_CALL Desktop::getContainerWindow() throw( css::uno::RuntimeException ) 906 { 907 return css::uno::Reference< css::awt::XWindow >(); 908 } 909 910 //***************************************************************************************************************** 911 void SAL_CALL Desktop::setCreator( const css::uno::Reference< css::frame::XFramesSupplier >& /*xCreator*/ ) throw( css::uno::RuntimeException ) 912 { 913 } 914 915 //***************************************************************************************************************** 916 css::uno::Reference< css::frame::XFramesSupplier > SAL_CALL Desktop::getCreator() throw( css::uno::RuntimeException ) 917 { 918 return css::uno::Reference< css::frame::XFramesSupplier >(); 919 } 920 921 //***************************************************************************************************************** 922 ::rtl::OUString SAL_CALL Desktop::getName() throw( css::uno::RuntimeException ) 923 { 924 /* SAFE { */ 925 ReadGuard aReadLock( m_aLock ); 926 return m_sName; 927 /* } SAFE */ 928 } 929 930 //***************************************************************************************************************** 931 void SAL_CALL Desktop::setName( const ::rtl::OUString& sName ) throw( css::uno::RuntimeException ) 932 { 933 /* SAFE { */ 934 WriteGuard aWriteLock( m_aLock ); 935 m_sName = sName; 936 aWriteLock.unlock(); 937 /* } SAFE */ 938 } 939 940 //***************************************************************************************************************** 941 sal_Bool SAL_CALL Desktop::isTop() throw( css::uno::RuntimeException ) 942 { 943 return sal_True; 944 } 945 946 //***************************************************************************************************************** 947 void SAL_CALL Desktop::activate() throw( css::uno::RuntimeException ) 948 { 949 // Desktop is activae always ... but sometimes our frames try to activate 950 // the complete path from bottom to top ... And our desktop is the topest frame :-( 951 // So - please don't show any assertions here. Do nothing! 952 } 953 954 //***************************************************************************************************************** 955 void SAL_CALL Desktop::deactivate() throw( css::uno::RuntimeException ) 956 { 957 // Desktop is activae always ... but sometimes our frames try to deactivate 958 // the complete path from bottom to top ... And our desktop is the topest frame :-( 959 // So - please don't show any assertions here. Do nothing! 960 } 961 962 //***************************************************************************************************************** 963 sal_Bool SAL_CALL Desktop::isActive() throw( css::uno::RuntimeException ) 964 { 965 return sal_True; 966 } 967 968 //***************************************************************************************************************** 969 sal_Bool SAL_CALL Desktop::setComponent( const css::uno::Reference< css::awt::XWindow >& /*xComponentWindow*/ , 970 const css::uno::Reference< css::frame::XController >& /*xController*/ ) throw( css::uno::RuntimeException ) 971 { 972 return sal_False; 973 } 974 975 //***************************************************************************************************************** 976 css::uno::Reference< css::awt::XWindow > SAL_CALL Desktop::getComponentWindow() throw( css::uno::RuntimeException ) 977 { 978 return css::uno::Reference< css::awt::XWindow >(); 979 } 980 981 //***************************************************************************************************************** 982 css::uno::Reference< css::frame::XController > SAL_CALL Desktop::getController() throw( css::uno::RuntimeException ) 983 { 984 return css::uno::Reference< css::frame::XController >(); 985 } 986 987 //***************************************************************************************************************** 988 void SAL_CALL Desktop::contextChanged() throw( css::uno::RuntimeException ) 989 { 990 } 991 992 //***************************************************************************************************************** 993 void SAL_CALL Desktop::addFrameActionListener( const css::uno::Reference< css::frame::XFrameActionListener >& ) throw( css::uno::RuntimeException ) 994 { 995 } 996 997 //***************************************************************************************************************** 998 // css::frame::XFrame 999 //***************************************************************************************************************** 1000 void SAL_CALL Desktop::removeFrameActionListener( const css::uno::Reference< css::frame::XFrameActionListener >& ) throw( css::uno::RuntimeException ) 1001 { 1002 } 1003 1004 /*-************************************************************************************************************//** 1005 @interface XFrame 1006 @short try to find a frame with special parameters 1007 @descr This method searches for a frame with the specified name. 1008 Frames may contain other frames (e.g. a frameset) and may 1009 be contained in other frames. This hierarchie ist searched by 1010 this method. 1011 First some special names are taken into account, i.e. "", 1012 "_self", "_top", "_parent" etc. The FrameSearchFlags are ignored 1013 when comparing these names with aTargetFrameName, further steps are 1014 controlled by the FrameSearchFlags. If allowed, the name of the frame 1015 itself is compared with the desired one, then ( again if allowed ) 1016 the method findFrame is called for all children of the frame. 1017 If no Frame with the given name is found until the top frames container, 1018 a new top Frame is created, if this is allowed by a special 1019 FrameSearchFlag. The new Frame also gets the desired name. 1020 We use a helper to get right search direction and react in a right manner. 1021 1022 @seealso class TargetFinder 1023 1024 @param "sTargetFrameName" , name of searched frame 1025 @param "nSearchFlags" , flags to regulate search 1026 @return A reference to an existing frame in hierarchy, if it exist. 1027 1028 @onerror A null reference is returned. 1029 @threadsafe yes 1030 *//*-*************************************************************************************************************/ 1031 css::uno::Reference< css::frame::XFrame > SAL_CALL Desktop::findFrame( const ::rtl::OUString& sTargetFrameName , 1032 sal_Int32 nSearchFlags ) throw( css::uno::RuntimeException ) 1033 { 1034 css::uno::Reference< css::frame::XFrame > xTarget; 1035 1036 //----------------------------------------------------------------------------------------------------- 1037 // 0) Ignore wrong parameter! 1038 // We doesn't support search for following special targets. 1039 // If we reject this requests - we mustnt check for such names 1040 // in following code again and again. If we do not so -wrong 1041 // search results can occure! 1042 //----------------------------------------------------------------------------------------------------- 1043 if ( 1044 (sTargetFrameName==SPECIALTARGET_DEFAULT ) || // valid for dispatches - not for findFrame()! 1045 (sTargetFrameName==SPECIALTARGET_MENUBAR ) || // valid for dispatches - not for findFrame()! 1046 (sTargetFrameName==SPECIALTARGET_HELPAGENT) || // valid for dispatches - not for findFrame()! 1047 (sTargetFrameName==SPECIALTARGET_PARENT ) || // we have no parent by definition 1048 (sTargetFrameName==SPECIALTARGET_BEAMER ) // beamer frames are allowed as child of tasks only - 1049 // and they exist more then ones. We have no idea which our sub tasks is the right one 1050 ) 1051 { 1052 return NULL; 1053 } 1054 1055 //----------------------------------------------------------------------------------------------------- 1056 // I) check for special defined targets first which must be handled exclusive. 1057 // force using of "if() else if() ..." 1058 //----------------------------------------------------------------------------------------------------- 1059 1060 // get threadsafe some neccessary member which are neccessary for following functionality 1061 /* SAFE { */ 1062 ReadGuard aReadLock( m_aLock ); 1063 css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory; 1064 aReadLock.unlock(); 1065 /* } SAFE */ 1066 1067 //----------------------------------------------------------------------------------------------------- 1068 // I.I) "_blank" 1069 // create a new task as child of this desktop instance 1070 // Note: Used helper TaskCreator use us automaticly ... 1071 //----------------------------------------------------------------------------------------------------- 1072 if ( sTargetFrameName==SPECIALTARGET_BLANK ) 1073 { 1074 TaskCreator aCreator(xFactory); 1075 xTarget = aCreator.createTask(sTargetFrameName,sal_False); 1076 } 1077 1078 //----------------------------------------------------------------------------------------------------- 1079 // I.II) "_top" 1080 // We are top by definition 1081 //----------------------------------------------------------------------------------------------------- 1082 else 1083 if ( sTargetFrameName==SPECIALTARGET_TOP ) 1084 { 1085 xTarget = this; 1086 } 1087 1088 //----------------------------------------------------------------------------------------------------- 1089 // I.III) "_self", "" 1090 // This mean this "frame" in every case. 1091 //----------------------------------------------------------------------------------------------------- 1092 else 1093 if ( 1094 ( sTargetFrameName==SPECIALTARGET_SELF ) || 1095 ( sTargetFrameName.getLength()<1 ) 1096 ) 1097 { 1098 xTarget = this; 1099 } 1100 1101 else 1102 { 1103 //------------------------------------------------------------------------------------------------- 1104 // II) otherwhise use optional given search flags 1105 // force using of combinations of such flags. means no "else" part of use if() statements. 1106 // But we ust break further searches if target was already found. 1107 // Order of using flags is fix: SELF - CHILDREN - SIBLINGS - PARENT 1108 // TASK and CREATE are handled special. 1109 // But note: Such flags are not valid for the desktop - especialy SIBLINGS or PARENT. 1110 //------------------------------------------------------------------------------------------------- 1111 1112 // get threadsafe some neccessary member which are neccessary for following functionality 1113 /* SAFE { */ 1114 aReadLock.lock(); 1115 ::rtl::OUString sOwnName = m_sName; 1116 aReadLock.unlock(); 1117 /* } SAFE */ 1118 1119 //------------------------------------------------------------------------------------------------- 1120 // II.I) SELF 1121 // Check for right name. If it's the searched one return ourself - otherwhise 1122 // ignore this flag. 1123 //------------------------------------------------------------------------------------------------- 1124 if ( 1125 (nSearchFlags & css::frame::FrameSearchFlag::SELF) && 1126 (sOwnName == sTargetFrameName ) 1127 ) 1128 { 1129 xTarget = this; 1130 } 1131 1132 //------------------------------------------------------------------------------------------------- 1133 // II.II) TASKS 1134 // This is a special flag. Normaly it regulate search inside tasks and forbid access to parent trees. 1135 // But the desktop exists outside such task trees. They are our sub trees. So the desktop implement 1136 // a special feature: We use it to start search on our direct childrens only. That means we supress 1137 // search on ALL child frames. May that can be usefull to get access on opened document tasks 1138 // only without filter out all non realy required sub frames ... 1139 // Used helper method on our container doesn't create any frame - its a search only. 1140 //------------------------------------------------------------------------------------------------- 1141 if ( 1142 ( ! xTarget.is() ) && 1143 (nSearchFlags & css::frame::FrameSearchFlag::TASKS) 1144 ) 1145 { 1146 xTarget = m_aChildTaskContainer.searchOnDirectChildrens(sTargetFrameName); 1147 } 1148 1149 //------------------------------------------------------------------------------------------------- 1150 // II.III) CHILDREN 1151 // Search on all children for the given target name. 1152 // An empty name value can't occure here - because it must be already handled as "_self" 1153 // before. Used helper function of container doesn't create any frame. 1154 // It makes a deep search only. 1155 //------------------------------------------------------------------------------------------------- 1156 if ( 1157 ( ! xTarget.is() ) && 1158 (nSearchFlags & css::frame::FrameSearchFlag::CHILDREN) 1159 ) 1160 { 1161 xTarget = m_aChildTaskContainer.searchOnAllChildrens(sTargetFrameName); 1162 } 1163 1164 //------------------------------------------------------------------------------------------------- 1165 // II.IV) CREATE 1166 // If we haven't found any valid target frame by using normal flags - but user allowed us to create 1167 // a new one ... we should do that. Used TaskCreator use us automaticly as parent! 1168 //------------------------------------------------------------------------------------------------- 1169 if ( 1170 ( ! xTarget.is() ) && 1171 (nSearchFlags & css::frame::FrameSearchFlag::CREATE) 1172 ) 1173 { 1174 TaskCreator aCreator(xFactory); 1175 xTarget = aCreator.createTask(sTargetFrameName,sal_False); 1176 } 1177 } 1178 1179 return xTarget; 1180 } 1181 1182 //============================================================================= 1183 void SAL_CALL Desktop::dispose() 1184 throw( css::uno::RuntimeException ) 1185 { 1186 // Safe impossible cases 1187 // It's an programming error if dispose is called before terminate! 1188 LOG_ASSERT2( m_bIsTerminated==sal_False, "Desktop::dispose()", "It's not allowed to dispose the desktop before terminate() is called!" ) 1189 1190 SYNCHRONIZED_START 1191 WriteGuard aWriteLock( m_aLock ); 1192 1193 // Look for multiple calls of this method! 1194 // If somewhere call dispose() twice - he will be stopped here realy!!! 1195 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 1196 1197 // Now - we are alone and its the first call of this method ... 1198 // otherwise call before had thrown a DisposedException / hopefully .-) 1199 // But we dont use the transaction object created before ... we reset it immediatly ... 1200 // two lines of code ... for what ? 1201 // The answer: We wished to synchronize concurrent dispose() calls -> OK 1202 // But next line will wait for all currently running transaction (even if they 1203 // are running within the same thread!) So we would block ourself there if aTransaction 1204 // will stay registered .-) 1205 aTransaction.stop(); 1206 1207 // Disable this instance for further work. 1208 // This will wait for all current running transactions ... 1209 // and reject all new incoming requests! 1210 m_aTransactionManager.setWorkingMode( E_BEFORECLOSE ); 1211 1212 aWriteLock.unlock(); 1213 SYNCHRONIZED_END 1214 1215 // Following lines of code can be called outside a synchronized block ... 1216 // Because our transaction manager will block all new requests to this object. 1217 // So nobody can use us any longer. 1218 // Exception: Only removing of listener will work ... and this code cant be dangerous. 1219 1220 // First we has to kill all listener connections. 1221 // They might rely on our member and can hinder us on releasing them. 1222 css::uno::Reference< css::uno::XInterface > xThis ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY ); 1223 css::lang::EventObject aEvent( xThis ); 1224 m_aListenerContainer.disposeAndClear( aEvent ); 1225 1226 // Clear our child task container and forget all task references hardly. 1227 // Normaly all open document was already closed by our terminate() function before ... 1228 // New opened frames will have a problem now .-) 1229 m_aChildTaskContainer.clear(); 1230 1231 // Dispose our helper too. 1232 css::uno::Reference< css::lang::XEventListener > xFramesHelper( m_xFramesHelper, css::uno::UNO_QUERY ); 1233 if( xFramesHelper.is() ) 1234 xFramesHelper->disposing( aEvent ); 1235 1236 // At least clean up other member references. 1237 m_xDispatchHelper.clear(); 1238 m_xFramesHelper.clear(); 1239 m_xLastFrame.clear(); 1240 m_xFactory.clear(); 1241 1242 m_xPipeTerminator.clear(); 1243 m_xQuickLauncher.clear(); 1244 m_xSWThreadManager.clear(); 1245 m_xSfxTerminator.clear(); 1246 1247 // From this point nothing will work further on this object ... 1248 // excepting our dtor() .-) 1249 m_aTransactionManager.setWorkingMode( E_CLOSE ); 1250 } 1251 1252 /*-************************************************************************************************************//** 1253 @interface XComponent 1254 @short add/remove listener for dispose events 1255 @descr Add an event listener to this object, if you whish to get informations 1256 about our dieing! 1257 You must releas ethis listener reference during your own disposing() method. 1258 1259 @attention Our container is threadsafe himeslf. So we doesn't need any lock here. 1260 1261 @seealso - 1262 1263 @param "xListener", reference to valid listener. We don't accept invalid values! 1264 @return - 1265 1266 @onerror - 1267 @threadsafe yes 1268 *//*-*************************************************************************************************************/ 1269 void SAL_CALL Desktop::addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) throw( css::uno::RuntimeException ) 1270 { 1271 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ 1272 // Safe impossible cases 1273 // Method not defined for all incoming parameter. 1274 LOG_ASSERT2( implcp_addEventListener( xListener ), "Desktop::addEventListener()", "Invalid parameter detected!" ) 1275 // Register transaction and reject wrong calls. 1276 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 1277 1278 m_aListenerContainer.addInterface( ::getCppuType( ( const css::uno::Reference< css::lang::XEventListener >*) NULL ), xListener ); 1279 } 1280 1281 //***************************************************************************************************************** 1282 void SAL_CALL Desktop::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) throw( css::uno::RuntimeException ) 1283 { 1284 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ 1285 // Safe impossible cases 1286 // Method not defined for all incoming parameter. 1287 LOG_ASSERT2( implcp_removeEventListener( xListener ), "Desktop::removeEventListener()", "Invalid parameter detected!" ) 1288 // Register transaction and reject wrong calls. 1289 TransactionGuard aTransaction( m_aTransactionManager, E_SOFTEXCEPTIONS ); 1290 1291 m_aListenerContainer.removeInterface( ::getCppuType( ( const css::uno::Reference< css::lang::XEventListener >*) NULL ), xListener ); 1292 } 1293 1294 /*-************************************************************************************************************//** 1295 @interface XDispatchResultListener 1296 @short callback for dispatches 1297 @descr To support our method "loadComponentFromURL()" we are listener on temp. created dispatcher. 1298 They call us back in this method "statusChanged()". As source of given state event, they give us a 1299 reference to the target frame, in which dispatch was loaded! So we can use it to return his component 1300 to caller! If no target exist ... ??!! 1301 1302 @seealso method loadComponentFromURL() 1303 1304 @param "aEvent", state event which (hopefully) valid informations 1305 @return - 1306 1307 @onerror - 1308 @threadsafe yes 1309 *//*-*************************************************************************************************************/ 1310 void SAL_CALL Desktop::dispatchFinished( const css::frame::DispatchResultEvent& aEvent ) throw( css::uno::RuntimeException ) 1311 { 1312 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ 1313 // Register transaction and reject wrong calls. 1314 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 1315 1316 /* SAFE AREA ------------------------------------------------------------------------------------------- */ 1317 WriteGuard aWriteLock( m_aLock ); 1318 if( m_eLoadState != E_INTERACTION ) 1319 { 1320 m_xLastFrame = css::uno::Reference< css::frame::XFrame >(); 1321 m_eLoadState = E_FAILED ; 1322 if( aEvent.State == css::frame::DispatchResultState::SUCCESS ) 1323 { 1324 css::uno::Reference < css::frame::XFrame > xFrame; 1325 if ( aEvent.Result >>= m_xLastFrame ) 1326 m_eLoadState = E_SUCCESSFUL; 1327 } 1328 } 1329 /* UNSAFE AREA ----------------------------------------------------------------------------------------- */ 1330 } 1331 1332 /*-************************************************************************************************************//** 1333 @interface XEventListener 1334 @short not implemented! 1335 @descr We are a status listener ... and so we must be an event listener too ... But we doesn't need it realy! 1336 We are a temp. listener only and our lifetime isn't smaller then of our temp. used dispatcher. 1337 1338 @seealso method loadComponentFromURL() 1339 1340 @param - 1341 @return - 1342 1343 @onerror - 1344 @threadsafe - 1345 *//*-*************************************************************************************************************/ 1346 void SAL_CALL Desktop::disposing( const css::lang::EventObject& ) throw( css::uno::RuntimeException ) 1347 { 1348 LOG_ERROR( "Desktop::disposing()", "Algorithm error! Normaly desktop is temp. listener ... not all the time. So this method shouldn't be called." ) 1349 } 1350 1351 /*-************************************************************************************************************//** 1352 @interface XInteractionHandler 1353 @short callback for loadComponentFromURL for detected exceptions during load proccess 1354 @descr In this case we must cancel loading and throw these detected exception again as result 1355 of our own called method. 1356 1357 @attention a) 1358 Normal loop in loadComponentFromURL() breaks on setted member m_eLoadState during callback statusChanged(). 1359 But these interaction feature implements second way to do so! So we must look on different callbacks 1360 for same operation ... and live with it. 1361 b) 1362 Search for given continuations too. If any XInteractionAbort exist ... use it to abort further operations 1363 for currently running operation! 1364 1365 @seealso method loadComponentFromURL() 1366 @seealso member m_eLoadState 1367 1368 @param "xRequest", request for interaction - normal a wrapped target exception from bottom services 1369 @return - 1370 1371 @onerror - 1372 @threadsafe yes 1373 *//*-*************************************************************************************************************/ 1374 void SAL_CALL Desktop::handle( const css::uno::Reference< css::task::XInteractionRequest >& xRequest ) throw( css::uno::RuntimeException ) 1375 { 1376 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ 1377 // Register transaction and reject wrong calls. 1378 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 1379 1380 // Don't check incoming request! 1381 // If somewhere starts interaction without right parameter - he maked something wrong. 1382 // loadComponentFromURL() waits for thjese event - otherwise it yield for ever! 1383 1384 // get packed request and work on it first 1385 // Attention: Don't set it on internal member BEFORE interaction is finished - because 1386 // "loadComponentFromURL()" yield tills this member is changed. If we do it before 1387 // interaction finish we can't guarantee right functionality. May be we cancel load process to erliear ... 1388 css::uno::Any aRequest = xRequest->getRequest(); 1389 1390 // extract continuations from request 1391 css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > lContinuations = xRequest->getContinuations(); 1392 css::uno::Reference< css::task::XInteractionAbort > xAbort ; 1393 css::uno::Reference< css::task::XInteractionApprove > xApprove ; 1394 css::uno::Reference< css::document::XInteractionFilterSelect > xFilterSelect ; 1395 sal_Bool bAbort = sal_False; 1396 1397 sal_Int32 nCount=lContinuations.getLength(); 1398 for( sal_Int32 nStep=0; nStep<nCount; ++nStep ) 1399 { 1400 if( ! xAbort.is() ) 1401 xAbort = css::uno::Reference< css::task::XInteractionAbort >( lContinuations[nStep], css::uno::UNO_QUERY ); 1402 1403 if( ! xApprove.is() ) 1404 xApprove = css::uno::Reference< css::task::XInteractionApprove >( lContinuations[nStep], css::uno::UNO_QUERY ); 1405 1406 if( ! xFilterSelect.is() ) 1407 xFilterSelect = css::uno::Reference< css::document::XInteractionFilterSelect >( lContinuations[nStep], css::uno::UNO_QUERY ); 1408 } 1409 1410 // differ between abortable interactions (error, unknown filter ...) 1411 // and other ones (ambigous but not unknown filter ...) 1412 css::task::ErrorCodeRequest aErrorCodeRequest ; 1413 css::document::AmbigousFilterRequest aAmbigousFilterRequest; 1414 if( aRequest >>= aAmbigousFilterRequest ) 1415 { 1416 if( xFilterSelect.is() ) 1417 { 1418 xFilterSelect->setFilter( aAmbigousFilterRequest.SelectedFilter ); // user selected filter wins! 1419 xFilterSelect->select(); 1420 } 1421 } 1422 else 1423 if( aRequest >>= aErrorCodeRequest ) 1424 { 1425 sal_Bool bWarning = ((aErrorCodeRequest.ErrCode & ERRCODE_WARNING_MASK) == ERRCODE_WARNING_MASK); 1426 if (xApprove.is() && bWarning) 1427 xApprove->select(); 1428 else 1429 if (xAbort.is()) 1430 { 1431 xAbort->select(); 1432 bAbort = sal_True; 1433 } 1434 } 1435 else 1436 if( xAbort.is() ) 1437 { 1438 xAbort->select(); 1439 bAbort = sal_True; 1440 } 1441 1442 /* SAFE AREA ------------------------------------------------------------------------------------------- */ 1443 // Ok now it's time to break yield loop of loadComponentFromURL(). 1444 // But only for realy aborted requests! 1445 // For example warnings will be approved and we wait for any success story ... 1446 if (bAbort) 1447 { 1448 WriteGuard aWriteLock( m_aLock ); 1449 m_eLoadState = E_INTERACTION; 1450 m_aInteractionRequest = aRequest ; 1451 aWriteLock.unlock(); 1452 } 1453 /* UNSAFE AREA ----------------------------------------------------------------------------------------- */ 1454 } 1455 1456 //----------------------------------------------------------------------------- 1457 ::sal_Int32 SAL_CALL Desktop::leaseNumber( const css::uno::Reference< css::uno::XInterface >& xComponent ) 1458 throw (css::lang::IllegalArgumentException, 1459 css::uno::RuntimeException ) 1460 { 1461 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 1462 return m_xTitleNumberGenerator->leaseNumber (xComponent); 1463 } 1464 1465 //----------------------------------------------------------------------------- 1466 void SAL_CALL Desktop::releaseNumber( ::sal_Int32 nNumber ) 1467 throw (css::lang::IllegalArgumentException, 1468 css::uno::RuntimeException ) 1469 { 1470 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 1471 m_xTitleNumberGenerator->releaseNumber (nNumber); 1472 } 1473 1474 //----------------------------------------------------------------------------- 1475 void SAL_CALL Desktop::releaseNumberForComponent( const css::uno::Reference< css::uno::XInterface >& xComponent ) 1476 throw (css::lang::IllegalArgumentException, 1477 css::uno::RuntimeException ) 1478 { 1479 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 1480 m_xTitleNumberGenerator->releaseNumberForComponent (xComponent); 1481 } 1482 1483 //----------------------------------------------------------------------------- 1484 ::rtl::OUString SAL_CALL Desktop::getUntitledPrefix() 1485 throw (css::uno::RuntimeException) 1486 { 1487 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 1488 return m_xTitleNumberGenerator->getUntitledPrefix (); 1489 } 1490 1491 /*-************************************************************************************************************//** 1492 @short try to convert a property value 1493 @descr This method is called from helperclass "OPropertySetHelper". 1494 Don't use this directly! 1495 You must try to convert the value of given DESKTOP_PROPHANDLE and 1496 return results of this operation. This will be used to ask vetoable 1497 listener. If no listener has a veto, we will change value realy! 1498 ( in method setFastPropertyValue_NoBroadcast(...) ) 1499 1500 @attention Methods of OPropertySethelper are safed by using our shared osl mutex! (see ctor!) 1501 So we must use different locks to make our implementation threadsafe. 1502 1503 @seealso class OPropertySetHelper 1504 @seealso method setFastPropertyValue_NoBroadcast() 1505 1506 @param "aConvertedValue" new converted value of property 1507 @param "aOldValue" old value of property 1508 @param "nHandle" handle of property 1509 @param "aValue" new value of property 1510 @return sal_True if value will be changed, sal_FALSE otherway 1511 1512 @onerror IllegalArgumentException, if you call this with an invalid argument 1513 @threadsafe yes 1514 *//*-*************************************************************************************************************/ 1515 sal_Bool SAL_CALL Desktop::convertFastPropertyValue( css::uno::Any& aConvertedValue , 1516 css::uno::Any& aOldValue , 1517 sal_Int32 nHandle , 1518 const css::uno::Any& aValue ) throw( css::lang::IllegalArgumentException ) 1519 { 1520 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ 1521 // Register transaction and reject wrong calls. 1522 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 1523 1524 // Initialize state with sal_False !!! 1525 // (Handle can be invalid) 1526 sal_Bool bReturn = sal_False; 1527 1528 switch( nHandle ) 1529 { 1530 case DESKTOP_PROPHANDLE_SUSPENDQUICKSTARTVETO: 1531 bReturn = PropHelper::willPropertyBeChanged( 1532 css::uno::makeAny(m_bSuspendQuickstartVeto), 1533 aValue, 1534 aOldValue, 1535 aConvertedValue); 1536 break; 1537 case DESKTOP_PROPHANDLE_DISPATCHRECORDERSUPPLIER : 1538 bReturn = PropHelper::willPropertyBeChanged( 1539 css::uno::makeAny(m_xDispatchRecorderSupplier), 1540 aValue, 1541 aOldValue, 1542 aConvertedValue); 1543 break; 1544 case DESKTOP_PROPHANDLE_TITLE : 1545 bReturn = PropHelper::willPropertyBeChanged( 1546 css::uno::makeAny(m_sTitle), 1547 aValue, 1548 aOldValue, 1549 aConvertedValue); 1550 break; 1551 } 1552 1553 // Return state of operation. 1554 return bReturn ; 1555 } 1556 1557 /*-************************************************************************************************************//** 1558 @short set value of a transient property 1559 @descr This method is calling from helperclass "OPropertySetHelper". 1560 Don't use this directly! 1561 Handle and value are valid everyway! You must set the new value only. 1562 After this, baseclass send messages to all listener automaticly. 1563 1564 @seealso class OPropertySetHelper 1565 1566 @param "nHandle" handle of property to change 1567 @param "aValue" new value of property 1568 @return - 1569 1570 @onerror An exception is thrown. 1571 @threadsafe yes 1572 *//*-*************************************************************************************************************/ 1573 void SAL_CALL Desktop::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle , 1574 const css::uno::Any& aValue ) throw( css::uno::Exception ) 1575 { 1576 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ 1577 // Register transaction and reject wrong calls. 1578 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 1579 1580 switch( nHandle ) 1581 { 1582 case DESKTOP_PROPHANDLE_SUSPENDQUICKSTARTVETO: aValue >>= m_bSuspendQuickstartVeto; 1583 break; 1584 case DESKTOP_PROPHANDLE_DISPATCHRECORDERSUPPLIER: aValue >>= m_xDispatchRecorderSupplier; 1585 break; 1586 case DESKTOP_PROPHANDLE_TITLE: aValue >>= m_sTitle; 1587 break; 1588 } 1589 } 1590 1591 /*-************************************************************************************************************//** 1592 @short get value of a transient property 1593 @descr This method is calling from helperclass "OPropertySetHelper". 1594 Don't use this directly! 1595 1596 @attention We don't need any mutex or lock here ... We use threadsafe container or methods here only! 1597 1598 @seealso class OPropertySetHelper 1599 1600 @param "nHandle" handle of property to change 1601 @param "aValue" current value of property 1602 @return - 1603 1604 @onerror - 1605 @threadsafe yes 1606 *//*-*************************************************************************************************************/ 1607 void SAL_CALL Desktop::getFastPropertyValue( css::uno::Any& aValue , 1608 sal_Int32 nHandle ) const 1609 { 1610 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ 1611 // Register transaction and reject wrong calls. 1612 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 1613 1614 switch( nHandle ) 1615 { 1616 case DESKTOP_PROPHANDLE_ACTIVEFRAME : aValue <<= m_aChildTaskContainer.getActive(); 1617 break; 1618 case DESKTOP_PROPHANDLE_ISPLUGGED : aValue <<= sal_False; 1619 break; 1620 case DESKTOP_PROPHANDLE_SUSPENDQUICKSTARTVETO: aValue <<= m_bSuspendQuickstartVeto; 1621 break; 1622 case DESKTOP_PROPHANDLE_DISPATCHRECORDERSUPPLIER: aValue <<= m_xDispatchRecorderSupplier; 1623 break; 1624 case DESKTOP_PROPHANDLE_TITLE: aValue <<= m_sTitle; 1625 break; 1626 } 1627 } 1628 1629 /*-************************************************************************************************************//** 1630 @short return structure and information about transient properties 1631 @descr This method is calling from helperclass "OPropertySetHelper". 1632 Don't use this directly! 1633 1634 @attention You must use global lock (method use static variable) ... and it must be the shareable osl mutex of it. 1635 Because; our baseclass use this mutex to make his code threadsafe. We use our lock! 1636 So we could have two different mutex/lock mechanism at the same object. 1637 1638 @seealso class OPropertySetHelper 1639 1640 @param - 1641 @return structure with property-informations 1642 1643 @onerror - 1644 @threadsafe yes 1645 *//*-*************************************************************************************************************/ 1646 ::cppu::IPropertyArrayHelper& SAL_CALL Desktop::getInfoHelper() 1647 { 1648 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ 1649 // Register transaction and reject wrong calls. 1650 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 1651 1652 // Optimize this method ! 1653 // We initialize a static variable only one time. And we don't must use a mutex at every call! 1654 // For the first call; pInfoHelper is NULL - for the second call pInfoHelper is different from NULL! 1655 static ::cppu::OPropertyArrayHelper* pInfoHelper = NULL; 1656 1657 if( pInfoHelper == NULL ) 1658 { 1659 // Ready for multithreading 1660 ::osl::MutexGuard aGuard( LockHelper::getGlobalLock().getShareableOslMutex() ); 1661 // Control this pointer again, another instance can be faster then these! 1662 if( pInfoHelper == NULL ) 1663 { 1664 // Define static member to give structure of properties to baseclass "OPropertySetHelper". 1665 // "impl_getStaticPropertyDescriptor" is a non exported and static funtion, who will define a static propertytable. 1666 // "sal_True" say: Table is sorted by name. 1667 static ::cppu::OPropertyArrayHelper aInfoHelper( impl_getStaticPropertyDescriptor(), sal_True ); 1668 pInfoHelper = &aInfoHelper; 1669 } 1670 } 1671 1672 return(*pInfoHelper); 1673 } 1674 1675 /*-************************************************************************************************************//** 1676 @short return propertysetinfo 1677 @descr You can call this method to get information about transient properties 1678 of this object. 1679 1680 @attention You must use global lock (method use static variable) ... and it must be the shareable osl mutex of it. 1681 Because; our baseclass use this mutex to make his code threadsafe. We use our lock! 1682 So we could have two different mutex/lock mechanism at the same object. 1683 1684 @seealso class OPropertySetHelper 1685 @seealso interface XPropertySet 1686 @seealso interface XMultiPropertySet 1687 1688 @param - 1689 @return reference to object with information [XPropertySetInfo] 1690 1691 @onerror - 1692 @threadsafe yes 1693 *//*-*************************************************************************************************************/ 1694 css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL Desktop::getPropertySetInfo() throw (::com::sun::star::uno::RuntimeException) 1695 { 1696 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ 1697 // Register transaction and reject wrong calls. 1698 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 1699 1700 // Optimize this method ! 1701 // We initialize a static variable only one time. And we don't must use a mutex at every call! 1702 // For the first call; pInfo is NULL - for the second call pInfo is different from NULL! 1703 static css::uno::Reference< css::beans::XPropertySetInfo >* pInfo = NULL; 1704 1705 if( pInfo == NULL ) 1706 { 1707 // Ready for multithreading 1708 ::osl::MutexGuard aGuard( LockHelper::getGlobalLock().getShareableOslMutex() ); 1709 // Control this pointer again, another instance can be faster then these! 1710 if( pInfo == NULL ) 1711 { 1712 // Create structure of propertysetinfo for baseclass "OPropertySetHelper". 1713 // (Use method "getInfoHelper()".) 1714 static css::uno::Reference< css::beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); 1715 pInfo = &xInfo; 1716 } 1717 } 1718 1719 return (*pInfo); 1720 } 1721 1722 /*-************************************************************************************************************//** 1723 @short return current component of current frame 1724 @descr The desktop himself has no component. But every frame in subtree. 1725 If somewhere call getCurrentComponent() at this class, we try to find the right frame and 1726 then we try to become his component. It can be a VCL-component, the model or the controller 1727 of founded frame. 1728 1729 @attention We don't work on internal member ... so we doesn't need any lock here. 1730 1731 @seealso method getCurrentComponent(); 1732 1733 @param "xFrame", reference to valid frame in hierarchy. Method is not defined for invalid values. 1734 But we don't check these. Its an IMPL-method and caller must use it right! 1735 @return A reference to found component. 1736 1737 @onerror A null reference is returned. 1738 @threadsafe yes 1739 *//*-*************************************************************************************************************/ 1740 css::uno::Reference< css::lang::XComponent > Desktop::impl_getFrameComponent( const css::uno::Reference< css::frame::XFrame >& xFrame ) const 1741 { 1742 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */ 1743 // Register transaction and reject wrong calls. 1744 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 1745 1746 // Set default return value, if method failed. 1747 css::uno::Reference< css::lang::XComponent > xComponent; 1748 // Does no controller exists? 1749 css::uno::Reference< css::frame::XController > xController = xFrame->getController(); 1750 if( xController.is() == sal_False ) 1751 { 1752 // Controller not exist - use the VCL-component. 1753 xComponent = css::uno::Reference< css::lang::XComponent >( xFrame->getComponentWindow(), css::uno::UNO_QUERY ); 1754 } 1755 else 1756 { 1757 // Does no model exists? 1758 css::uno::Reference< css::frame::XModel > xModel( xController->getModel(), css::uno::UNO_QUERY ); 1759 if( xModel.is() == sal_True ) 1760 { 1761 // Model exist - use the model as component. 1762 xComponent = css::uno::Reference< css::lang::XComponent >( xModel, css::uno::UNO_QUERY ); 1763 } 1764 else 1765 { 1766 // Model not exist - use the controller as component. 1767 xComponent = css::uno::Reference< css::lang::XComponent >( xController, css::uno::UNO_QUERY ); 1768 } 1769 } 1770 1771 return xComponent; 1772 } 1773 1774 /*-************************************************************************************************************//** 1775 @short create table with information about properties 1776 @descr We use a helper class to support properties. These class need some information about this. 1777 These method create a new static description table with name, type, r/w-flags and so on ... 1778 1779 @seealso class OPropertySetHelper 1780 @seealso method getInfoHelper() 1781 1782 @param - 1783 @return Static table with information about properties. 1784 1785 @onerror - 1786 @threadsafe yes 1787 *//*-*************************************************************************************************************/ 1788 const css::uno::Sequence< css::beans::Property > Desktop::impl_getStaticPropertyDescriptor() 1789 { 1790 // Create a new static property array to initialize sequence! 1791 // Table of all predefined properties of this class. Its used from OPropertySetHelper-class! 1792 // Don't forget to change the defines (see begin of this file), if you add, change or delete a property in this list!!! 1793 // It's necessary for methods of OPropertySetHelper. 1794 // ATTENTION: 1795 // YOU MUST SORT FOLLOW TABLE BY NAME ALPHABETICAL !!! 1796 1797 static const css::beans::Property pProperties[] = 1798 { 1799 css::beans::Property( DESKTOP_PROPNAME_ACTIVEFRAME , DESKTOP_PROPHANDLE_ACTIVEFRAME , ::getCppuType((const css::uno::Reference< css::lang::XComponent >*)NULL) , css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY ), 1800 css::beans::Property( DESKTOP_PROPNAME_DISPATCHRECORDERSUPPLIER , DESKTOP_PROPHANDLE_DISPATCHRECORDERSUPPLIER, ::getCppuType((const css::uno::Reference< css::frame::XDispatchRecorderSupplier >*)NULL), css::beans::PropertyAttribute::TRANSIENT ), 1801 css::beans::Property( DESKTOP_PROPNAME_ISPLUGGED , DESKTOP_PROPHANDLE_ISPLUGGED , ::getBooleanCppuType() , css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY ), 1802 css::beans::Property( DESKTOP_PROPNAME_SUSPENDQUICKSTARTVETO , DESKTOP_PROPHANDLE_SUSPENDQUICKSTARTVETO , ::getBooleanCppuType() , css::beans::PropertyAttribute::TRANSIENT ), 1803 css::beans::Property( DESKTOP_PROPNAME_TITLE , DESKTOP_PROPHANDLE_TITLE , ::getCppuType((const ::rtl::OUString*)NULL) , css::beans::PropertyAttribute::TRANSIENT ), 1804 }; 1805 // Use it to initialize sequence! 1806 static const css::uno::Sequence< css::beans::Property > lPropertyDescriptor( pProperties, DESKTOP_PROPCOUNT ); 1807 // Return static "PropertyDescriptor" 1808 return lPropertyDescriptor; 1809 } 1810 1811 //============================================================================= 1812 void Desktop::impl_sendQueryTerminationEvent(Desktop::TTerminateListenerList& lCalledListener, 1813 ::sal_Bool& bVeto ) 1814 { 1815 bVeto = sal_False; 1816 1817 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 1818 1819 ::cppu::OInterfaceContainerHelper* pContainer = m_aListenerContainer.getContainer( ::getCppuType( ( const css::uno::Reference< css::frame::XTerminateListener >*) NULL ) ); 1820 if ( ! pContainer ) 1821 return; 1822 1823 css::lang::EventObject aEvent( static_cast< ::cppu::OWeakObject* >(this) ); 1824 1825 ::cppu::OInterfaceIteratorHelper aIterator( *pContainer ); 1826 while ( aIterator.hasMoreElements() ) 1827 { 1828 try 1829 { 1830 css::uno::Reference< css::frame::XTerminateListener > xListener(aIterator.next(), css::uno::UNO_QUERY); 1831 if ( ! xListener.is() ) 1832 continue; 1833 xListener->queryTermination( aEvent ); 1834 lCalledListener.push_back(xListener); 1835 } 1836 catch( const css::frame::TerminationVetoException& ) 1837 { 1838 // first veto will stop notification loop. 1839 bVeto = sal_True; 1840 return; 1841 } 1842 catch( const css::uno::Exception& ) 1843 { 1844 // clean up container. 1845 // E.g. dead remote listener objects can make trouble otherwise. 1846 // Iterator implementation allows removing objects during it's used ! 1847 aIterator.remove(); 1848 } 1849 } 1850 } 1851 1852 //============================================================================= 1853 void Desktop::impl_sendCancelTerminationEvent(const Desktop::TTerminateListenerList& lCalledListener) 1854 { 1855 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 1856 1857 css::lang::EventObject aEvent( static_cast< ::cppu::OWeakObject* >(this) ); 1858 Desktop::TTerminateListenerList::const_iterator pIt; 1859 for ( pIt = lCalledListener.begin(); 1860 pIt != lCalledListener.end (); 1861 ++pIt ) 1862 { 1863 try 1864 { 1865 // Note: cancelTermination() is a new and optional interface method ! 1866 css::uno::Reference< css::frame::XTerminateListener > xListener = *pIt; 1867 css::uno::Reference< css::frame::XTerminateListener2 > xListenerGeneration2(xListener, css::uno::UNO_QUERY); 1868 if ( ! xListenerGeneration2.is() ) 1869 continue; 1870 xListenerGeneration2->cancelTermination( aEvent ); 1871 } 1872 catch( const css::uno::Exception& ) 1873 {} 1874 } 1875 } 1876 1877 //============================================================================= 1878 void Desktop::impl_sendNotifyTerminationEvent() 1879 { 1880 TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS ); 1881 1882 ::cppu::OInterfaceContainerHelper* pContainer = m_aListenerContainer.getContainer( ::getCppuType( ( const css::uno::Reference< css::frame::XTerminateListener >*) NULL ) ); 1883 if ( ! pContainer ) 1884 return; 1885 1886 css::lang::EventObject aEvent( static_cast< ::cppu::OWeakObject* >(this) ); 1887 1888 ::cppu::OInterfaceIteratorHelper aIterator( *pContainer ); 1889 while ( aIterator.hasMoreElements() ) 1890 { 1891 try 1892 { 1893 css::uno::Reference< css::frame::XTerminateListener > xListener(aIterator.next(), css::uno::UNO_QUERY); 1894 if ( ! xListener.is() ) 1895 continue; 1896 xListener->notifyTermination( aEvent ); 1897 } 1898 catch( const css::uno::Exception& ) 1899 { 1900 // clean up container. 1901 // E.g. dead remote listener objects can make trouble otherwise. 1902 // Iterator implementation allows removing objects during it's used ! 1903 aIterator.remove(); 1904 } 1905 } 1906 } 1907 1908 //============================================================================= 1909 ::sal_Bool Desktop::impl_closeFrames(::sal_Bool bAllowUI) 1910 { 1911 SYNCHRONIZED_START 1912 ReadGuard aReadLock( m_aLock ); 1913 css::uno::Sequence< css::uno::Reference< css::frame::XFrame > > lFrames = m_aChildTaskContainer.getAllElements(); 1914 aReadLock.unlock(); 1915 SYNCHRONIZED_END 1916 1917 ::sal_Int32 c = lFrames.getLength(); 1918 ::sal_Int32 i = 0; 1919 ::sal_Int32 nNonClosedFrames = 0; 1920 1921 for( i=0; i<c; ++i ) 1922 { 1923 try 1924 { 1925 css::uno::Reference< css::frame::XFrame > xFrame = lFrames[i]; 1926 1927 // XController.suspend() will show an UI ... 1928 // Use it in case it was allowed from outside only. 1929 sal_Bool bSuspended = sal_False; 1930 css::uno::Reference< css::frame::XController > xController( xFrame->getController(), css::uno::UNO_QUERY ); 1931 if ( 1932 ( bAllowUI ) && 1933 ( xController.is() ) 1934 ) 1935 { 1936 bSuspended = xController->suspend( sal_True ); 1937 if ( ! bSuspended ) 1938 { 1939 ++nNonClosedFrames; 1940 continue; 1941 } 1942 } 1943 1944 // Try to close frame (in case no UI was allowed without calling XController->suspend() before!) 1945 // But don't deliver ownership to any other one! 1946 // This method can be called again. 1947 css::uno::Reference< css::util::XCloseable > xClose( xFrame, css::uno::UNO_QUERY ); 1948 if ( xClose.is() ) 1949 { 1950 try 1951 { 1952 xClose->close(sal_False); 1953 } 1954 catch(const css::util::CloseVetoException&) 1955 { 1956 // Any internal process of this frame disagree with our request. 1957 // Safe this state but dont break these loop. Other frames has to be closed! 1958 ++nNonClosedFrames; 1959 1960 // Reactivate controller. 1961 // It can happen that XController.suspend() returned true ... but a registered close listener 1962 // throwed these veto exception. Then the controller has to be reactivated. Otherwise 1963 // these document doesnt work any more. 1964 if ( 1965 (bSuspended ) && 1966 (xController.is()) 1967 ) 1968 xController->suspend(sal_False); 1969 } 1970 1971 // If interface XClosable interface exists and was used ... 1972 // it's not allowed to use XComponent->dispose() also ! 1973 continue; 1974 } 1975 1976 // XClosable not supported ? 1977 // Then we have to dispose these frame hardly. 1978 css::uno::Reference< css::lang::XComponent > xDispose( xFrame, css::uno::UNO_QUERY ); 1979 if ( xDispose.is() ) 1980 xDispose->dispose(); 1981 1982 // Don't remove these frame from our child container! 1983 // A frame do it by itself inside close()/dispose() method. 1984 } 1985 catch(const css::lang::DisposedException&) 1986 { 1987 // Dispose frames are closed frames. 1988 // So we can count it here .-) 1989 } 1990 } 1991 1992 return (nNonClosedFrames < 1); 1993 } 1994 1995 //_________________________________________________________________________________________________________________ 1996 // debug methods 1997 //_________________________________________________________________________________________________________________ 1998 1999 /*----------------------------------------------------------------------------------------------------------------- 2000 The follow methods checks the parameter for other functions. If a parameter or his value is non valid, 2001 we return "sal_True". (otherwise sal_False) This mechanism is used to throw an ASSERT! 2002 -----------------------------------------------------------------------------------------------------------------*/ 2003 2004 #ifdef ENABLE_ASSERTIONS 2005 2006 //***************************************************************************************************************** 2007 // We work with valid servicemanager only. 2008 sal_Bool Desktop::implcp_ctor( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory ) 2009 { 2010 return( 2011 ( &xFactory == NULL ) || 2012 ( xFactory.is() == sal_False ) 2013 ); 2014 } 2015 2016 //***************************************************************************************************************** 2017 // We work with valid listener only. 2018 sal_Bool Desktop::implcp_addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) 2019 { 2020 return( 2021 ( &xListener == NULL ) || 2022 ( xListener.is() == sal_False ) 2023 ); 2024 } 2025 2026 //***************************************************************************************************************** 2027 // We work with valid listener only. 2028 sal_Bool Desktop::implcp_removeEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) 2029 { 2030 return( 2031 ( &xListener == NULL ) || 2032 ( xListener.is() == sal_False ) 2033 ); 2034 } 2035 2036 #endif // #ifdef ENABLE_ASSERTIONS 2037 2038 } // namespace framework 2039