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 XElementAccess are not supported!\n")
209                                                 LOG_ASSERT2( m_xDispatchHelper.is()==sal_False, "Desktop::Desktop()", "Dispatch helper is not valid. XDispatch will not work correctly!\n"                      )
210 
211                                                 // Enable object for real working!
212                                                 // Otherwise all calls will be rejected ...
213                                                 m_aTransactionManager.setWorkingMode( E_WORK );
214                                             }
215                                         )
216 
217 /*-************************************************************************************************************//**
218     @short      standard constructor to create instance by factory
219     @descr      This constructor initialize a new instance of this class by valid factory,
220                 and will be set valid values on his member and baseclasses.
221 
222     @attention  a)  Don't use your own reference during an UNO-Service-ctor! There is no guarantee, that you
223                     will get over this. (e.g. using of your reference as parameter to initialize some member)
224                     Do such things in DEFINE_INIT_SERVICE() method, which is called automatically after your ctor!!!
225                 b)  Baseclass OBroadcastHelper is a typedef in namespace cppu!
226                     The microsoft compiler has some problems to handle it right BY using namespace explicitly ::cppu::OBroadcastHelper.
227                     If we write it without a namespace or expand the typedef to OBrodcastHelperVar<...> -> it will be OK!?
228                     I don't know why! (other compiler not tested .. but it works!)
229 
230     @seealso    method DEFINE_INIT_SERVICE()
231 
232     @param      "xFactory" is the multi service manager, which create this instance.
233                 The value must be different from NULL!
234     @return     -
235 
236     @onerror    We throw an ASSERT in debug version or do nothing in relaese version.
237 *//*-*************************************************************************************************************/
238 Desktop::Desktop( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory )
239 		//	Init baseclasses first
240         //  Attention: Don't change order of initialization!
241         //      ThreadHelpBase is a struct with a lock as member. We can't use a lock as direct member!
242         //      We must garant right initialization and a valid value of this to initialize other baseclasses!
243         :   ThreadHelpBase          ( &Application::GetSolarMutex()                 )
244         ,   TransactionBase         (                                               )
245         ,   ::cppu::OBroadcastHelperVar< ::cppu::OMultiTypeInterfaceContainerHelper, ::cppu::OMultiTypeInterfaceContainerHelper::keyType >           ( m_aLock.getShareableOslMutex()         )
246         ,   ::cppu::OPropertySetHelper  ( *(static_cast< ::cppu::OBroadcastHelper* >(this)) )
247         ,   ::cppu::OWeakObject     (                                               )
248 		// Init member
249 		#ifdef ENABLE_ASSERTIONS
250         ,   m_bIsTerminated         ( sal_False                                     )   // see dispose() for further informations!
251 		#endif
252         ,   m_xFactory              ( xFactory                                      )
253         ,   m_aChildTaskContainer   (                                               )
254         ,   m_aListenerContainer    ( m_aLock.getShareableOslMutex()                )
255         ,   m_xFramesHelper         (                                               )
256         ,   m_xDispatchHelper       (                                               )
257         ,   m_eLoadState            ( E_NOTSET                                      )
258         ,   m_xLastFrame            (                                               )
259         ,   m_aInteractionRequest   (                                               )
260         ,   m_bSuspendQuickstartVeto( sal_False										)
261         ,   m_aCommandOptions       (                                               )
262         ,   m_sName                 (                                               )
263         ,   m_sTitle                (                                               )
264         ,   m_xDispatchRecorderSupplier(                                            )
265         ,   m_xPipeTerminator       (                                               )
266         ,   m_xQuickLauncher        (                                               )
267         ,   m_xSWThreadManager      (                                               )
268         ,   m_xSfxTerminator        (                                               )
269         ,   m_xTitleNumberGenerator (                                               )
270 {
271 	// Safe impossible cases
272 	// We don't accept all incoming parameter.
273     LOG_ASSERT2( implcp_ctor( xFactory ), "Desktop::Desktop()", "Invalid parameter detected!")
274 }
275 
276 /*-************************************************************************************************************//**
277 	@short		standard destructor
278 	@descr		This one do NOTHING! Use dispose() instaed of this.
279 
280 	@seealso	method dispose()
281 
282 	@param		-
283 	@return		-
284 
285 	@onerror	-
286 *//*-*************************************************************************************************************/
~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 really the last listener to be called.
420         // Because it shutdown the whole process asynchronous !
421         if ( xSfxTerminator.is() )
422             xSfxTerminator->notifyTermination( aEvent );
423     }
424 
425     return bTerminate;
426 }
427 
428 
429 //=============================================================================
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 paths in our frame hierarchy. But only one of them
583                 could be the most active frame (normal he has the focus).
584                 Don't mix it with getActiveFrame()! That will return our current active frame, which must be
585                 a direct child of us and should be a part(!) of an active path.
586 
587     @seealso    method getActiveFrame()
588 
589     @param      -
590     @return     A valid reference, if there is an active frame.
591                 A null reference , otherwise.
592 
593     @onerror    We return a null reference.
594     @threadsafe yes
595 *//*-*************************************************************************************************************/
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 our direct active frame (if it exists!).
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 our taskchilds
661     @descr      Direct childs of desktop are tasks every time.
662                 Call these method to could create enumerations of it.
663 
664 But; Don't forget - you will be the owner of returned object and must release it!
665                 We use a helper class to implement the access interface. They hold a weakreference to us.
666                 It can be, that the desktop is dead - but not your tasksaccess-object! Then they will do nothing!
667                 You can't create enumerations then.
668 
669     @attention  Normally 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 our 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 our 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 our 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 our 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 really provided by an internal helper, which is used inside the dispatch api too.
783     @param      xInterceptor
784                 the interceptor object, which wish to be (de)registered.
785 
786     @threadsafe yes
787 *//*-*************************************************************************************************************/
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 our 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 our 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 necessary for our FrameActionEvent listener on a frame!
861     css::uno::Reference< css::frame::XFrame > xLastActiveChild = m_aChildTaskContainer.getActive();
862     if( xLastActiveChild != xFrame )
863 	{
864         m_aChildTaskContainer.setActive( xFrame );
865         if( xLastActiveChild.is() == sal_True )
866         {
867             xLastActiveChild->deactivate();
868         }
869     }
870 }
871 
872 //*****************************************************************************************************************
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 occur!
1038     //-----------------------------------------------------------------------------------------------------
1039     if (
1040         (sTargetFrameName==SPECIALTARGET_DEFAULT  )   ||    // valid for dispatches - not for findFrame()!
1041         (sTargetFrameName==SPECIALTARGET_MENUBAR  )   ||    // valid for dispatches - not for findFrame()!
1042         (sTargetFrameName==SPECIALTARGET_HELPAGENT)   ||    // valid for dispatches - not for findFrame()!
1043         (sTargetFrameName==SPECIALTARGET_PARENT   )   ||    // we have no parent by definition
1044         (sTargetFrameName==SPECIALTARGET_BEAMER   )         // beamer frames are allowed as child of tasks only -
1045                                                             // and they exist more then ones. We have no idea which our sub tasks is the right one
1046        )
1047     {
1048         return NULL;
1049     }
1050 
1051     //-----------------------------------------------------------------------------------------------------
1052     // I) check for special defined targets first which must be handled exclusive.
1053     //    force using of "if() else if() ..."
1054     //-----------------------------------------------------------------------------------------------------
1055 
1056     // get threadsafe some necessary member which are necessary for following functionality
1057     /* SAFE { */
1058     ReadGuard aReadLock( m_aLock );
1059     css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory;
1060     aReadLock.unlock();
1061     /* } SAFE */
1062 
1063     //-----------------------------------------------------------------------------------------------------
1064     // I.I) "_blank"
1065     //  create a new task as child of this desktop instance
1066     //  Note: Used helper TaskCreator use us automatically ...
1067     //-----------------------------------------------------------------------------------------------------
1068     if ( sTargetFrameName==SPECIALTARGET_BLANK )
1069     {
1070         TaskCreator aCreator(xFactory);
1071         xTarget = aCreator.createTask(sTargetFrameName,sal_False);
1072     }
1073 
1074     //-----------------------------------------------------------------------------------------------------
1075     // I.II) "_top"
1076     //  We are top by definition
1077     //-----------------------------------------------------------------------------------------------------
1078     else
1079     if ( sTargetFrameName==SPECIALTARGET_TOP )
1080     {
1081         xTarget = this;
1082     }
1083 
1084     //-----------------------------------------------------------------------------------------------------
1085     // I.III) "_self", ""
1086     //  This mean this "frame" in every case.
1087     //-----------------------------------------------------------------------------------------------------
1088     else
1089     if (
1090         ( sTargetFrameName==SPECIALTARGET_SELF ) ||
1091         ( sTargetFrameName.getLength()<1       )
1092        )
1093     {
1094         xTarget = this;
1095     }
1096 
1097     else
1098     {
1099         //-------------------------------------------------------------------------------------------------
1100         // II) otherwise use optional given search flags
1101         //  force using of combinations of such flags. means no "else" part of use if() statements.
1102         //  But we must break further searches if target was already found.
1103         //  Order of using flags is fix: SELF - CHILDREN - SIBLINGS - PARENT
1104         //  TASK and CREATE are handled special.
1105         //  But note: Such flags are not valid for the desktop - especially SIBLINGS or PARENT.
1106         //-------------------------------------------------------------------------------------------------
1107 
1108         // get threadsafe some necessary member which are necessary for following functionality
1109         /* SAFE { */
1110         aReadLock.lock();
1111         ::rtl::OUString sOwnName = m_sName;
1112         aReadLock.unlock();
1113         /* } SAFE */
1114 
1115         //-------------------------------------------------------------------------------------------------
1116         // II.I) SELF
1117         //  Check for right name. If it's the searched one return ourself - otherwise
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. Normally it regulates search inside tasks and forbid access to parent trees.
1131         //  But the desktop exists outside such task trees. They are our sub trees. So the desktop implement
1132         //  a special feature: We use it to start search on our direct childrens only. That means we suppress
1133         //  search on ALL child frames. May that can be useful to get access on opened document tasks
1134         //  only without filter out all non really required sub frames ...
1135         //  Used helper method on our container doesn't create any frame - its a search only.
1136         //-------------------------------------------------------------------------------------------------
1137         if (
1138             ( ! xTarget.is()                                  ) &&
1139             (nSearchFlags & css::frame::FrameSearchFlag::TASKS)
1140            )
1141         {
1142             xTarget = m_aChildTaskContainer.searchOnDirectChildrens(sTargetFrameName);
1143         }
1144 
1145         //-------------------------------------------------------------------------------------------------
1146         // II.III) CHILDREN
1147         //  Search on all children for the given target name.
1148         //  An empty name value can't occur here - because it must be already handled as "_self"
1149         //  before. Used helper function of container doesn't create any frame.
1150         //  It makes a deep search only.
1151         //-------------------------------------------------------------------------------------------------
1152         if (
1153             ( ! xTarget.is()                                     ) &&
1154             (nSearchFlags & css::frame::FrameSearchFlag::CHILDREN)
1155            )
1156         {
1157             xTarget = m_aChildTaskContainer.searchOnAllChildrens(sTargetFrameName);
1158         }
1159 
1160         //-------------------------------------------------------------------------------------------------
1161         // II.IV) CREATE
1162         //  If we haven't found any valid target frame by using normal flags - but user allowed us to create
1163         //  a new one ... we should do that. Used TaskCreator use us automatically as parent!
1164         //-------------------------------------------------------------------------------------------------
1165         if (
1166             ( ! xTarget.is()                                   )    &&
1167             (nSearchFlags & css::frame::FrameSearchFlag::CREATE)
1168            )
1169         {
1170             TaskCreator aCreator(xFactory);
1171             xTarget = aCreator.createTask(sTargetFrameName,sal_False);
1172         }
1173     }
1174 
1175     return xTarget;
1176 }
1177 
1178 //=============================================================================
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 really!!!
1191         TransactionGuard aTransaction( m_aTransactionManager, E_HARDEXCEPTIONS );
1192 
1193         // Now - we are alone and its the first call of this method ...
1194         // otherwise call before had thrown a DisposedException / hopefully .-)
1195         // But we dont use the transaction object created before ... we reset it immediately ...
1196         // two lines of code ... for what ?
1197         // The answer: We wished to synchronize concurrent dispose() calls -> OK
1198         // But next line will wait for all currently running transaction (even if they
1199         // are running within the same thread!) So we would block ourself there if aTransaction
1200         // will stay registered .-)
1201         aTransaction.stop();
1202 
1203         // Disable this instance for further work.
1204         // This will wait for all current running transactions ...
1205         // and reject all new incoming requests!
1206         m_aTransactionManager.setWorkingMode( E_BEFORECLOSE );
1207 
1208         aWriteLock.unlock();
1209     SYNCHRONIZED_END
1210 
1211     // Following lines of code can be called outside a synchronized block ...
1212     // Because our transaction manager will block all new requests to this object.
1213     // So nobody can use us any longer.
1214     // Exception: Only removing of listener will work ... and this code can't be dangerous.
1215 
1216     // First we has to kill all listener connections.
1217     // They might rely on our member and can hinder us on releasing them.
1218     css::uno::Reference< css::uno::XInterface > xThis ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
1219     css::lang::EventObject                      aEvent( xThis );
1220     m_aListenerContainer.disposeAndClear( aEvent );
1221 
1222     // Clear our child task container and forget all task references hardly.
1223     // Normally all open document were already closed by our terminate() function before ...
1224     // New opened frames will have a problem now .-)
1225     m_aChildTaskContainer.clear();
1226 
1227     // Dispose our helper too.
1228     css::uno::Reference< css::lang::XEventListener > xFramesHelper( m_xFramesHelper, css::uno::UNO_QUERY );
1229     if( xFramesHelper.is() )
1230         xFramesHelper->disposing( aEvent );
1231 
1232     // At least clean up other member references.
1233     m_xDispatchHelper.clear();
1234     m_xFramesHelper.clear();
1235     m_xLastFrame.clear();
1236     m_xFactory.clear();
1237 
1238     m_xPipeTerminator.clear();
1239     m_xQuickLauncher.clear();
1240     m_xSWThreadManager.clear();
1241     m_xSfxTerminator.clear();
1242 
1243     // From this point nothing will work further on this object ...
1244     // excepting our dtor() .-)
1245     m_aTransactionManager.setWorkingMode( E_CLOSE );
1246 }
1247 
1248 /*-************************************************************************************************************//**
1249     @interface  XComponent
1250     @short      add/remove listener for dispose events
1251     @descr      Add an event listener to this object, if you whish to get informations
1252                 about our dying!
1253                 You must releas ethis listener reference during your own disposing() method.
1254 
1255     @attention  Our container is threadsafe himeslf. So we doesn't need any lock here.
1256 
1257     @seealso    -
1258 
1259     @param      "xListener", reference to valid listener. We don't accept invalid values!
1260     @return     -
1261 
1262     @onerror    -
1263     @threadsafe yes
1264 *//*-*************************************************************************************************************/
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 really!
1332                 We are a temp. listener only and our lifetime isn't smaller then of our temp. used dispatcher.
1333 
1334     @seealso    method loadComponentFromURL()
1335 
1336     @param      -
1337     @return     -
1338 
1339     @onerror    -
1340     @threadsafe -
1341 *//*-*************************************************************************************************************/
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! Normally desktop is temp. listener ... not all the time. So this method shouldn't be called." )
1345 }
1346 
1347 /*-************************************************************************************************************//**
1348     @interface  XInteractionHandler
1349     @short      callback for loadComponentFromURL for detected exceptions during load process
1350     @descr      In this case we must cancel loading and throw these detected exception again as result
1351                 of our own called method.
1352 
1353     @attention  a)
1354                 Normal loop in loadComponentFromURL() breaks on set member m_eLoadState during callback statusChanged().
1355                 But these interaction feature implements second way to do so! So we must look on different callbacks
1356                 for same operation ... and live with it.
1357                 b)
1358                 Search for given continuations too. If any XInteractionAbort exist ... use it to abort further operations
1359                 for currently running operation!
1360 
1361     @seealso    method loadComponentFromURL()
1362     @seealso    member m_eLoadState
1363 
1364     @param      "xRequest", request for interaction - normal a wrapped target exception from bottom services
1365     @return     -
1366 
1367     @onerror    -
1368     @threadsafe yes
1369 *//*-*************************************************************************************************************/
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 made something wrong.
1378     // loadComponentFromURL() waits for thjese event - otherwise it yield for ever!
1379 
1380     // get packed request and work on it first
1381     // Attention: Don't set it on internal member BEFORE interaction is finished - because
1382     // "loadComponentFromURL()" yield tills this member is changed. If we do it before
1383     // interaction finish we can't guarantee right functionality. May be we cancel load process to erliear ...
1384     css::uno::Any aRequest = xRequest->getRequest();
1385 
1386     // extract continuations from request
1387     css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > lContinuations = xRequest->getContinuations();
1388     css::uno::Reference< css::task::XInteractionAbort >                              xAbort         ;
1389     css::uno::Reference< css::task::XInteractionApprove >                            xApprove       ;
1390     css::uno::Reference< css::document::XInteractionFilterSelect >                   xFilterSelect  ;
1391     sal_Bool                                                                         bAbort         = sal_False;
1392 
1393     sal_Int32 nCount=lContinuations.getLength();
1394     for( sal_Int32 nStep=0; nStep<nCount; ++nStep )
1395     {
1396         if( ! xAbort.is() )
1397             xAbort  = css::uno::Reference< css::task::XInteractionAbort >( lContinuations[nStep], css::uno::UNO_QUERY );
1398 
1399         if( ! xApprove.is() )
1400             xApprove  = css::uno::Reference< css::task::XInteractionApprove >( lContinuations[nStep], css::uno::UNO_QUERY );
1401 
1402         if( ! xFilterSelect.is() )
1403             xFilterSelect = css::uno::Reference< css::document::XInteractionFilterSelect >( lContinuations[nStep], css::uno::UNO_QUERY );
1404     }
1405 
1406     // differ between abortable interactions (error, unknown filter ...)
1407     // and other ones (ambigous but not unknown filter ...)
1408     css::task::ErrorCodeRequest          aErrorCodeRequest     ;
1409     css::document::AmbigousFilterRequest aAmbigousFilterRequest;
1410     if( aRequest >>= aAmbigousFilterRequest )
1411     {
1412         if( xFilterSelect.is() )
1413         {
1414             xFilterSelect->setFilter( aAmbigousFilterRequest.SelectedFilter ); // user selected filter wins!
1415             xFilterSelect->select();
1416         }
1417     }
1418     else
1419     if( aRequest >>= aErrorCodeRequest )
1420     {
1421         sal_Bool bWarning = ((aErrorCodeRequest.ErrCode & ERRCODE_WARNING_MASK) == ERRCODE_WARNING_MASK);
1422         if (xApprove.is() && bWarning)
1423             xApprove->select();
1424         else
1425         if (xAbort.is())
1426         {
1427             xAbort->select();
1428             bAbort = sal_True;
1429         }
1430     }
1431     else
1432     if( xAbort.is() )
1433     {
1434         xAbort->select();
1435         bAbort = sal_True;
1436     }
1437 
1438     /* SAFE AREA ------------------------------------------------------------------------------------------- */
1439     // Ok now it's time to break yield loop of loadComponentFromURL().
1440     // But only for really aborted requests!
1441     // For example warnings will be approved and we wait for any success story ...
1442     if (bAbort)
1443     {
1444         WriteGuard aWriteLock( m_aLock );
1445         m_eLoadState          = E_INTERACTION;
1446         m_aInteractionRequest = aRequest     ;
1447         aWriteLock.unlock();
1448     }
1449     /* UNSAFE AREA ----------------------------------------------------------------------------------------- */
1450 }
1451 
1452 //-----------------------------------------------------------------------------
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 really!
1494                 ( in method setFastPropertyValue_NoBroadcast(...) )
1495 
1496     @attention  Methods of OPropertySethelper are safed by using our shared osl mutex! (see ctor!)
1497                 So we must use different locks to make our implementation threadsafe.
1498 
1499     @seealso    class OPropertySetHelper
1500     @seealso    method setFastPropertyValue_NoBroadcast()
1501 
1502     @param      "aConvertedValue"   new converted value of property
1503     @param      "aOldValue"         old value of property
1504     @param      "nHandle"           handle of property
1505     @param      "aValue"            new value of property
1506     @return     sal_True if value will be changed, sal_FALSE otherway
1507 
1508     @onerror    IllegalArgumentException, if you call this with an invalid argument
1509     @threadsafe yes
1510 *//*-*************************************************************************************************************/
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 automatically.
1559 
1560     @seealso    class OPropertySetHelper
1561 
1562     @param      "nHandle"   handle of property to change
1563     @param      "aValue"    new value of property
1564     @return     -
1565 
1566     @onerror    An exception is thrown.
1567     @threadsafe yes
1568 *//*-*************************************************************************************************************/
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 function, who will define a static propertytable.
1662 			// "sal_True" say: Table is sorted by name.
1663             static ::cppu::OPropertyArrayHelper aInfoHelper( impl_getStaticPropertyDescriptor(), sal_True );
1664 			pInfoHelper = &aInfoHelper;
1665 		}
1666 	}
1667 
1668     return(*pInfoHelper);
1669 }
1670 
1671 /*-************************************************************************************************************//**
1672     @short      return propertysetinfo
1673     @descr      You can call this method to get information about transient properties
1674                 of this object.
1675 
1676     @attention  You must use global lock (method use static variable) ... and it must be the shareable osl mutex of it.
1677                 Because; our baseclass use this mutex to make his code threadsafe. We use our lock!
1678                 So we could have two different mutex/lock mechanism at the same object.
1679 
1680     @seealso    class OPropertySetHelper
1681     @seealso    interface XPropertySet
1682     @seealso    interface XMultiPropertySet
1683 
1684     @param      -
1685     @return     reference to object with information [XPropertySetInfo]
1686 
1687     @onerror    -
1688     @threadsafe yes
1689 *//*-*************************************************************************************************************/
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 doesn't work any more.
1960                     if (
1961                         (bSuspended      ) &&
1962                         (xController.is())
1963                        )
1964                         xController->suspend(sal_False);
1965                 }
1966 
1967                 // If interface XClosable interface exists and was used ...
1968                 // it's not allowed to use XComponent->dispose() also !
1969                 continue;
1970             }
1971 
1972             // XClosable not supported ?
1973             // Then we have to dispose these frame hardly.
1974             css::uno::Reference< css::lang::XComponent > xDispose( xFrame, css::uno::UNO_QUERY );
1975             if ( xDispose.is() )
1976                 xDispose->dispose();
1977 
1978             // Don't remove these frame from our child container!
1979             // A frame do it by itself inside close()/dispose() method.
1980         }
1981         catch(const css::lang::DisposedException&)
1982         {
1983             // Dispose frames are closed frames.
1984             // So we can count it here .-)
1985         }
1986     }
1987 
1988     return (nNonClosedFrames < 1);
1989 }
1990 
1991 //_________________________________________________________________________________________________________________
1992 //	debug methods
1993 //_________________________________________________________________________________________________________________
1994 
1995 /*-----------------------------------------------------------------------------------------------------------------
1996 	The follow methods checks the parameter for other functions. If a parameter or his value is non valid,
1997     we return "sal_True". (otherwise sal_False) This mechanism is used to throw an ASSERT!
1998 -----------------------------------------------------------------------------------------------------------------*/
1999 
2000 #ifdef ENABLE_ASSERTIONS
2001 
2002 //*****************************************************************************************************************
2003 //	We work with valid servicemanager only.
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