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