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