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