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