1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <framework/desktop.hxx>
22 #include <loadenv/loadenv.hxx>
24 #include <helper/ocomponentaccess.hxx>
25 #include <helper/oframes.hxx>
26 #include <dispatch/dispatchprovider.hxx>
28 #include <dispatch/interceptionhelper.hxx>
29 #include <classes/taskcreator.hxx>
30 #include <threadhelp/transactionguard.hxx>
31 #include <properties.h>
34 #include <strings.hrc>
35 #include <classes/fwkresid.hxx>
37 #include <com/sun/star/beans/PropertyAttribute.hpp>
38 #include <com/sun/star/frame/FrameSearchFlag.hpp>
39 #include <com/sun/star/frame/TerminationVetoException.hpp>
40 #include <com/sun/star/task/XInteractionAbort.hpp>
41 #include <com/sun/star/task/XInteractionApprove.hpp>
42 #include <com/sun/star/document/XInteractionFilterSelect.hpp>
43 #include <com/sun/star/task/ErrorCodeRequest.hpp>
44 #include <com/sun/star/frame/DispatchResultState.hpp>
45 #include <com/sun/star/lang/DisposedException.hpp>
46 #include <com/sun/star/util/CloseVetoException.hpp>
47 #include <com/sun/star/util/XCloseable.hpp>
48 #include <com/sun/star/frame/XTerminateListener2.hpp>
50 #include <comphelper/numberedcollection.hxx>
51 #include <comphelper/sequence.hxx>
52 #include <comphelper/lok.hxx>
53 #include <cppuhelper/supportsservice.hxx>
55 #include <vcl/svapp.hxx>
56 #include <desktop/crashreport.hxx>
57 #include <vcl/scheduler.hxx>
58 #include <sal/log.hxx>
59 #include <comphelper/errcode.hxx>
60 #include <vcl/threadex.hxx>
61 #include <unotools/configmgr.hxx>
68 ActiveFrame
, DispatchRecorderSupplier
, IsPlugged
, SuspendQuickstartVeto
,
73 OUString SAL_CALL
Desktop::getImplementationName()
75 return "com.sun.star.comp.framework.Desktop";
78 sal_Bool SAL_CALL
Desktop::supportsService(OUString
const & ServiceName
)
80 return cppu::supportsService(this, ServiceName
);
83 css::uno::Sequence
<OUString
> SAL_CALL
Desktop::getSupportedServiceNames()
85 return { "com.sun.star.frame.Desktop" };
88 void Desktop::constructorInit()
90 // Initialize a new XFrames-helper-object to handle XIndexAccess and XElementAccess.
91 // We hold member as reference ... not as pointer too!
92 // Attention: We share our frame container with this helper. Container is threadsafe himself ... So I think we can do that.
93 // But look on dispose() for right order of deinitialization.
94 m_xFramesHelper
= new OFrames( this, &m_aChildTaskContainer
);
96 // Initialize a new dispatchhelper-object to handle dispatches.
97 // We use these helper as slave for our interceptor helper ... not directly!
98 // But he is event listener on THIS instance!
99 rtl::Reference
<DispatchProvider
> xDispatchProvider
= new DispatchProvider( m_xContext
, this );
101 // Initialize a new interception helper object to handle dispatches and implement an interceptor mechanism.
102 // Set created dispatch provider as slowest slave of it.
103 // Hold interception helper by reference only - not by pointer!
104 // So it's easier to destroy it.
105 m_xDispatchHelper
= new InterceptionHelper( this, xDispatchProvider
);
107 OUString sUntitledPrefix
= FwkResId(STR_UNTITLED_DOCUMENT
) + " ";
109 rtl::Reference
<::comphelper::NumberedCollection
> pNumbers
= new ::comphelper::NumberedCollection ();
110 m_xTitleNumberGenerator
= pNumbers
;
111 pNumbers
->setOwner ( static_cast< ::cppu::OWeakObject
* >(this) );
112 pNumbers
->setUntitledPrefix ( sUntitledPrefix
);
114 // Safe impossible cases
115 // We can't work without this helper!
116 SAL_WARN_IF( !m_xFramesHelper
.is(), "fwk.desktop", "Desktop::Desktop(): Frames helper is not valid. XFrames, XIndexAccess and XElementAccess are not supported!");
117 SAL_WARN_IF( !m_xDispatchHelper
.is(), "fwk.desktop", "Desktop::Desktop(): Dispatch helper is not valid. XDispatch will not work correctly!" );
119 // Enable object for real working!
120 // Otherwise all calls will be rejected ...
121 m_aTransactionManager
.setWorkingMode( E_WORK
);
124 /*-************************************************************************************************************
125 @short standard constructor to create instance by factory
126 @descr This constructor initialize a new instance of this class by valid factory,
127 and will be set valid values on his member and baseclasses.
129 @attention a) Don't use your own reference during a UNO-Service-ctor! There is no guarantee, that you
130 will get over this. (e.g. using of your reference as parameter to initialize some member)
131 Do such things in DEFINE_INIT_SERVICE() method, which is called automatically after your ctor!!!
132 b) Baseclass OBroadcastHelper is a typedef in namespace cppu!
133 The microsoft compiler has some problems to handle it right BY using namespace explicitly ::cppu::OBroadcastHelper.
134 If we write it without a namespace or expand the typedef to OBroadcastHelperVar<...> -> it will be OK!?
135 I don't know why! (other compiler not tested .. but it works!)
137 @seealso method DEFINE_INIT_SERVICE()
139 @param "xFactory" is the multi service manager, which create this instance.
140 The value must be different from NULL!
141 @onerror We throw an ASSERT in debug version or do nothing in release version.
142 *//*-*************************************************************************************************************/
143 Desktop::Desktop( css::uno::Reference
< css::uno::XComponentContext
> xContext
)
144 : Desktop_BASE ( m_aMutex
)
145 , cppu::OPropertySetHelper( cppu::WeakComponentImplHelperBase::rBHelper
)
147 , m_bIsTerminated(false)
148 , m_bIsShutdown(false) // see dispose() for further information!
149 , m_bSession ( false )
150 , m_xContext (std::move( xContext
))
151 , m_aListenerContainer ( m_aMutex
)
152 , m_eLoadState ( E_NOTSET
)
153 , m_bSuspendQuickstartVeto( false )
157 /*-************************************************************************************************************
158 @short standard destructor
159 @descr This one do NOTHING! Use dispose() instead of this.
161 @seealso method dispose()
162 *//*-*************************************************************************************************************/
165 SAL_WARN_IF(!m_bIsShutdown
, "fwk.desktop", "Desktop not terminated before being destructed");
166 SAL_WARN_IF( m_aTransactionManager
.getWorkingMode()!=E_CLOSE
, "fwk.desktop", "Desktop::~Desktop(): Who forgot to dispose this service?" );
169 css::uno::Any SAL_CALL
Desktop::queryInterface( const css::uno::Type
& _rType
)
171 css::uno::Any aRet
= Desktop_BASE::queryInterface( _rType
);
172 if ( !aRet
.hasValue() )
173 aRet
= OPropertySetHelper::queryInterface( _rType
);
177 css::uno::Sequence
< css::uno::Type
> SAL_CALL
Desktop::getTypes( )
179 return comphelper::concatSequences(
180 Desktop_BASE::getTypes(),
181 ::cppu::OPropertySetHelper::getTypes()
185 sal_Bool SAL_CALL
Desktop::terminate()
187 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
188 SolarMutexResettableGuard aGuard
;
193 css::uno::Reference
< css::frame::XTerminateListener
> xPipeTerminator
= m_xPipeTerminator
;
194 css::uno::Reference
< css::frame::XTerminateListener
> xQuickLauncher
= m_xQuickLauncher
;
195 css::uno::Reference
< css::frame::XTerminateListener
> xSWThreadManager
= m_xSWThreadManager
;
196 css::uno::Reference
< css::frame::XTerminateListener
> xSfxTerminator
= m_xSfxTerminator
;
198 css::lang::EventObject
aEvent ( static_cast< ::cppu::OWeakObject
* >(this) );
199 bool bAskQuickStart
= !m_bSuspendQuickstartVeto
;
200 const bool bRestartableMainLoop
= comphelper::LibreOfficeKit::isActive();
203 // Allow using of any UI ... because Desktop.terminate() was designed as UI functionality in the past.
205 // Ask normal terminate listener. They could veto terminating the process.
206 Desktop::TTerminateListenerList lCalledTerminationListener
;
207 if (!impl_sendQueryTerminationEvent(lCalledTerminationListener
))
209 impl_sendCancelTerminationEvent(lCalledTerminationListener
);
213 // try to close all open frames
214 if (!impl_closeFrames(!bRestartableMainLoop
))
216 impl_sendCancelTerminationEvent(lCalledTerminationListener
);
220 // Normal listener had no problem ...
221 // all frames was closed ...
222 // now it's time to ask our specialized listener.
223 // They are handled these way because they wish to hinder the office on termination
224 // but they wish also closing of all frames.
227 // We shouldn't ask quicklauncher in case it was allowed from outside only.
228 // This is special trick to "ignore existing quick starter" for debug purposes.
231 // Order of called listener is important!
232 // Some of them are harmless,-)
233 // but some can be dangerous. E.g. it would be dangerous if we close our pipe
234 // and don't terminate in real because another listener throws a veto exception .-)
238 if( bAskQuickStart
&& xQuickLauncher
.is() )
240 xQuickLauncher
->queryTermination( aEvent
);
241 lCalledTerminationListener
.push_back( xQuickLauncher
);
244 if ( xSWThreadManager
.is() )
246 xSWThreadManager
->queryTermination( aEvent
);
247 lCalledTerminationListener
.push_back( xSWThreadManager
);
250 if ( xPipeTerminator
.is() )
252 xPipeTerminator
->queryTermination( aEvent
);
253 lCalledTerminationListener
.push_back( xPipeTerminator
);
256 if ( xSfxTerminator
.is() )
258 xSfxTerminator
->queryTermination( aEvent
);
259 lCalledTerminationListener
.push_back( xSfxTerminator
);
262 catch(const css::frame::TerminationVetoException
&)
264 impl_sendCancelTerminationEvent(lCalledTerminationListener
);
271 m_bIsTerminated
= true;
273 if (!bRestartableMainLoop
)
275 CrashReporter::addKeyValue("ShutDown", OUString::boolean(true), CrashReporter::Write
);
277 // The clipboard listener needs to be the first. It can create copies of the
278 // existing document which needs basically all the available infrastructure.
279 impl_sendTerminateToClipboard();
281 SolarMutexReleaser aReleaser
;
282 impl_sendNotifyTerminationEvent();
284 Scheduler::ProcessEventsToIdle();
286 if( bAskQuickStart
&& xQuickLauncher
.is() )
287 xQuickLauncher
->notifyTermination( aEvent
);
289 if ( xSWThreadManager
.is() )
290 xSWThreadManager
->notifyTermination( aEvent
);
292 if ( xPipeTerminator
.is() )
293 xPipeTerminator
->notifyTermination( aEvent
);
295 // further termination is postponed to shutdown, if LO already runs the main loop
296 if (!Application::IsInExecute())
300 m_bIsShutdown
= true;
302 #ifndef IOS // or ANDROID?
304 // In the iOS app, posting the ImplQuitMsg user event will be too late, it will not be handled during the
305 // lifetime of the current document, but handled for the next document opened, which thus will break horribly.
312 void Desktop::shutdown()
314 TransactionGuard
aTransaction(m_aTransactionManager
, E_HARDEXCEPTIONS
);
315 SolarMutexGuard aGuard
;
319 m_bIsShutdown
= true;
321 css::uno::Reference
<css::frame::XTerminateListener
> xSfxTerminator
= m_xSfxTerminator
;
322 css::lang::EventObject
aEvent(static_cast<::cppu::OWeakObject
* >(this));
324 // we need a copy here as the notifyTermination call might cause a removeTerminateListener call
325 std::vector
< css::uno::Reference
<css::frame::XTerminateListener
> > xComponentDllListeners
;
326 xComponentDllListeners
.swap(m_xComponentDllListeners
);
327 for (auto& xListener
: xComponentDllListeners
)
328 xListener
->notifyTermination(aEvent
);
329 xComponentDllListeners
.clear();
331 // Must be really the last listener to be called.
332 // Because it shuts down the whole process asynchronous!
333 if (xSfxTerminator
.is())
334 xSfxTerminator
->notifyTermination(aEvent
);
339 class QuickstartSuppressor
341 Desktop
* const m_pDesktop
;
342 css::uno::Reference
< css::frame::XTerminateListener
> m_xQuickLauncher
;
344 QuickstartSuppressor(Desktop
* const pDesktop
, css::uno::Reference
< css::frame::XTerminateListener
> xQuickLauncher
)
345 : m_pDesktop(pDesktop
)
346 , m_xQuickLauncher(std::move(xQuickLauncher
))
348 SAL_INFO("fwk.desktop", "temporary removing Quickstarter");
349 if(m_xQuickLauncher
.is())
350 m_pDesktop
->removeTerminateListener(m_xQuickLauncher
);
352 ~QuickstartSuppressor()
354 SAL_INFO("fwk.desktop", "readding Quickstarter");
355 if(m_xQuickLauncher
.is())
356 m_pDesktop
->addTerminateListener(m_xQuickLauncher
);
361 bool Desktop::terminateQuickstarterToo()
363 QuickstartSuppressor
aQuickstartSuppressor(this, m_xQuickLauncher
);
368 void SAL_CALL
Desktop::addTerminateListener( const css::uno::Reference
< css::frame::XTerminateListener
>& xListener
)
370 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
372 css::uno::Reference
< css::lang::XServiceInfo
> xInfo( xListener
, css::uno::UNO_QUERY
);
375 OUString sImplementationName
= xInfo
->getImplementationName();
379 if( sImplementationName
== "com.sun.star.comp.sfx2.SfxTerminateListener" )
381 m_xSfxTerminator
= xListener
;
384 if( sImplementationName
== "com.sun.star.comp.RequestHandlerController" )
386 m_xPipeTerminator
= xListener
;
389 if( sImplementationName
== "com.sun.star.comp.desktop.QuickstartWrapper" )
391 m_xQuickLauncher
= xListener
;
394 if( sImplementationName
== "com.sun.star.util.comp.FinalThreadManager" )
396 m_xSWThreadManager
= xListener
;
399 else if ( sImplementationName
== "com.sun.star.comp.ComponentDLLListener" )
401 m_xComponentDllListeners
.push_back(xListener
);
406 // No lock required... container is threadsafe by itself.
407 m_aListenerContainer
.addInterface( cppu::UnoType
<css::frame::XTerminateListener
>::get(), xListener
);
410 void SAL_CALL
Desktop::removeTerminateListener( const css::uno::Reference
< css::frame::XTerminateListener
>& xListener
)
412 TransactionGuard
aTransaction( m_aTransactionManager
, E_SOFTEXCEPTIONS
);
414 css::uno::Reference
< css::lang::XServiceInfo
> xInfo( xListener
, css::uno::UNO_QUERY
);
417 OUString sImplementationName
= xInfo
->getImplementationName();
421 if( sImplementationName
== "com.sun.star.comp.sfx2.SfxTerminateListener" )
423 m_xSfxTerminator
.clear();
427 if( sImplementationName
== "com.sun.star.comp.RequestHandlerController" )
429 m_xPipeTerminator
.clear();
433 if( sImplementationName
== "com.sun.star.comp.desktop.QuickstartWrapper" )
435 m_xQuickLauncher
.clear();
439 if( sImplementationName
== "com.sun.star.util.comp.FinalThreadManager" )
441 m_xSWThreadManager
.clear();
444 else if (sImplementationName
== "com.sun.star.comp.ComponentDLLListener")
446 std::erase(m_xComponentDllListeners
, xListener
);
451 // No lock required ... container is threadsafe by itself.
452 m_aListenerContainer
.removeInterface( cppu::UnoType
<css::frame::XTerminateListener
>::get(), xListener
);
455 /*-************************************************************************************************************
457 @short get access to create enumerations of all current components
458 @descr You will be the owner of the returned object and must delete it if you don't use it again.
460 @seealso class TasksAccess
461 @seealso class TasksEnumeration
462 @return A reference to an XEnumerationAccess-object.
464 @onerror We return a null-reference.
466 *//*-*************************************************************************************************************/
467 css::uno::Reference
< css::container::XEnumerationAccess
> SAL_CALL
Desktop::getComponents()
469 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
470 // Register transaction and reject wrong calls.
471 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
473 // We use a helper class OComponentAccess to have access on all child components.
474 // Create it on demand and return it as a reference.
475 return new OComponentAccess( this );
478 /*-************************************************************************************************************
480 @short return the current active component
481 @descr The most current component is the window, model or the controller of the current active frame.
483 @seealso method getCurrentFrame()
484 @seealso method impl_getFrameComponent()
485 @return A reference to the component.
487 @onerror We return a null-reference.
489 *//*-*************************************************************************************************************/
490 css::uno::Reference
< css::lang::XComponent
> SAL_CALL
Desktop::getCurrentComponent()
492 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
493 // Register transaction and reject wrong calls.
494 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
496 // Set return value if method failed.
497 css::uno::Reference
< css::lang::XComponent
> xComponent
;
499 // Get reference to current frame ...
500 // ... get component of this frame ... (It can be the window, the model or the controller.)
501 // ... and return the result.
502 css::uno::Reference
< css::frame::XFrame
> xCurrentFrame
= getCurrentFrame();
503 if( xCurrentFrame
.is() )
505 xComponent
= impl_getFrameComponent( xCurrentFrame
);
510 /*-************************************************************************************************************
512 @short return the current active frame in hierarchy
513 @descr There can be more than one different active paths in our frame hierarchy. But only one of them
514 could be the most active frame (normal he has the focus).
515 Don't mix it with getActiveFrame()! That will return our current active frame, which must be
516 a direct child of us and should be a part(!) of an active path.
518 @seealso method getActiveFrame()
519 @return A valid reference, if there is an active frame.
520 A null reference , otherwise.
522 @onerror We return a null reference.
524 *//*-*************************************************************************************************************/
525 css::uno::Reference
< css::frame::XFrame
> SAL_CALL
Desktop::getCurrentFrame()
527 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
528 // Register transaction and reject wrong calls.
529 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
531 // Start search with our direct active frame (if it exist!).
532 // Search on his children for other active frames too.
533 // Stop if no one could be found and return last of found ones.
534 css::uno::Reference
< css::frame::XFramesSupplier
> xLast( getActiveFrame(), css::uno::UNO_QUERY
);
537 css::uno::Reference
< css::frame::XFramesSupplier
> xNext( xLast
->getActiveFrame(), css::uno::UNO_QUERY
);
541 xNext
.set( xNext
->getActiveFrame(), css::uno::UNO_QUERY
);
547 /*-************************************************************************************************************
548 @interface XComponentLoader
549 @short try to load given URL into a task
550 @descr You can give us some information about the content, which you will load into a frame.
551 We search or create this target for you, make a type detection of given URL and try to load it.
552 As result of this operation we return the new created component or nothing, if loading failed.
553 @param "sURL" , URL, which represent the content
554 @param "sTargetFrameName" , name of target frame or special value like "_self", "_blank" ...
555 @param "nSearchFlags" , optional arguments for frame search, if target isn't a special one
556 @param "lArguments" , optional arguments for loading
557 @return A valid component reference, if loading was successful.
558 A null reference otherwise.
560 @onerror We return a null reference.
562 *//*-*************************************************************************************************************/
563 css::uno::Reference
< css::lang::XComponent
> SAL_CALL
Desktop::loadComponentFromURL( const OUString
& sURL
,
564 const OUString
& sTargetFrameName
,
565 sal_Int32 nSearchFlags
,
566 const css::uno::Sequence
< css::beans::PropertyValue
>& lArguments
)
568 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
569 // Register transaction and reject wrong calls.
570 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
571 SAL_INFO( "fwk.desktop", "loadComponentFromURL" );
573 css::uno::Reference
< css::frame::XComponentLoader
> xThis(this);
575 utl::MediaDescriptor
aDescriptor(lArguments
);
576 bool bOnMainThread
= aDescriptor
.getUnpackedValueOrDefault("OnMainThread", false);
580 // Make sure that we own the solar mutex, otherwise later
581 // vcl::SolarThreadExecutor::execute() will release the solar mutex, even if it's owned by
582 // another thread, leading to an std::abort() at the end.
585 return vcl::solarthread::syncExecute(std::bind(&LoadEnv::loadComponentFromURL
, xThis
,
586 m_xContext
, sURL
, sTargetFrameName
,
587 nSearchFlags
, lArguments
));
591 return LoadEnv::loadComponentFromURL(xThis
, m_xContext
, sURL
, sTargetFrameName
,
592 nSearchFlags
, lArguments
);
596 /*-************************************************************************************************************
597 @interface XTasksSupplier
598 @short get access to create enumerations of our taskchildren
599 @descr Direct children of desktop are tasks every time.
600 Call these method to could create enumerations of it.
602 But; Don't forget - you will be the owner of returned object and must release it!
603 We use a helper class to implement the access interface. They hold a weakreference to us.
604 It can be, that the desktop is dead - but not your tasksaccess-object! Then they will do nothing!
605 You can't create enumerations then.
607 @attention Normally we don't need any lock here. We don't work on internal member!
609 @seealso class TasksAccess
610 @return A reference to an accessobject, which can create enumerations of our childtasks.
612 @onerror A null reference is returned.
614 *//*-*************************************************************************************************************/
615 css::uno::Reference
< css::container::XEnumerationAccess
> SAL_CALL
Desktop::getTasks()
617 SAL_INFO("fwk.desktop", "Desktop::getTasks(): Use of obsolete interface XTaskSupplier");
621 /*-************************************************************************************************************
622 @interface XTasksSupplier
623 @short return current active task of our direct children
624 @descr Desktop children are tasks only ! If we have an active path from desktop
625 as top to any frame on bottom, we must have an active direct child. His reference is returned here.
627 @attention a) Do not confuse it with getCurrentFrame()! The current frame don't must one of our direct children.
628 It can be every frame in subtree and must have the focus (Is the last one of an active path!).
629 b) We don't need any lock here. Our container is threadsafe himself and live, if we live!
631 @seealso method getCurrentFrame()
632 @return A reference to our current active taskchild.
634 @onerror A null reference is returned.
636 *//*-*************************************************************************************************************/
637 css::uno::Reference
< css::frame::XTask
> SAL_CALL
Desktop::getActiveTask()
639 SAL_INFO("fwk.desktop", "Desktop::getActiveTask(): Use of obsolete interface XTaskSupplier");
643 /*-************************************************************************************************************
644 @interface XDispatchProvider
645 @short search a dispatcher for given URL
646 @descr We use a helper implementation (class DispatchProvider) to do so.
647 So we don't must implement this algorithm twice!
649 @attention We don't need any lock here. Our helper is threadsafe himself and live, if we live!
651 @seealso class DispatchProvider
653 @param "aURL" , URL to dispatch
654 @param "sTargetFrameName" , name of target frame, who should dispatch these URL
655 @param "nSearchFlags" , flags to regulate the search
656 @param "lQueries" , list of queryDispatch() calls!
657 @return A reference or list of founded dispatch objects for these URL.
659 @onerror A null reference is returned.
661 *//*-*************************************************************************************************************/
662 css::uno::Reference
< css::frame::XDispatch
> SAL_CALL
Desktop::queryDispatch( const css::util::URL
& aURL
,
663 const OUString
& sTargetFrameName
,
664 sal_Int32 nSearchFlags
)
666 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
667 // Register transaction and reject wrong calls.
668 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
670 // Remove uno and cmd protocol part as we want to support both of them. We store only the command part
671 // in our hash map. All other protocols are stored with the protocol part.
672 OUString
aCommand( aURL
.Main
);
673 if ( aURL
.Protocol
.equalsIgnoreAsciiCase(".uno:") )
674 aCommand
= aURL
.Path
;
676 if (!m_xCommandOptions
&& !utl::ConfigManager::IsFuzzing())
677 m_xCommandOptions
.reset(new SvtCommandOptions
);
679 // Make std::unordered_map lookup if the current URL is in the disabled list
680 if (m_xCommandOptions
&& m_xCommandOptions
->LookupDisabled(aCommand
))
681 return css::uno::Reference
< css::frame::XDispatch
>();
684 // We use a helper to support these interface and an interceptor mechanism.
685 // Our helper is threadsafe by himself!
686 return m_xDispatchHelper
->queryDispatch( aURL
, sTargetFrameName
, nSearchFlags
);
690 css::uno::Sequence
< css::uno::Reference
< css::frame::XDispatch
> > SAL_CALL
Desktop::queryDispatches( const css::uno::Sequence
< css::frame::DispatchDescriptor
>& lQueries
)
692 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
693 // Register transaction and reject wrong calls.
694 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
696 return m_xDispatchHelper
->queryDispatches( lQueries
);
699 /*-************************************************************************************************************
700 @interface XDispatchProviderInterception
701 @short supports registration/deregistration of interception objects, which
702 are interested on special dispatches.
704 @descr It's really provided by an internal helper, which is used inside the dispatch API too.
706 the interceptor object, which wishes to be (de)registered.
709 *//*-*************************************************************************************************************/
710 void SAL_CALL
Desktop::registerDispatchProviderInterceptor( const css::uno::Reference
< css::frame::XDispatchProviderInterceptor
>& xInterceptor
)
712 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
714 css::uno::Reference
< css::frame::XDispatchProviderInterception
> xInterceptionHelper( m_xDispatchHelper
, css::uno::UNO_QUERY
);
715 xInterceptionHelper
->registerDispatchProviderInterceptor( xInterceptor
);
718 void SAL_CALL
Desktop::releaseDispatchProviderInterceptor ( const css::uno::Reference
< css::frame::XDispatchProviderInterceptor
>& xInterceptor
)
720 TransactionGuard
aTransaction( m_aTransactionManager
, E_SOFTEXCEPTIONS
);
722 css::uno::Reference
< css::frame::XDispatchProviderInterception
> xInterceptionHelper( m_xDispatchHelper
, css::uno::UNO_QUERY
);
723 xInterceptionHelper
->releaseDispatchProviderInterceptor( xInterceptor
);
726 /*-************************************************************************************************************
727 @interface XFramesSupplier
728 @short return access to append or remove children on desktop
729 @descr We don't implement these interface directly. We use a helper class to do this.
730 If you wish to add or delete children to/from the container, call these method to get
731 a reference to the helper.
733 @attention Helper is threadsafe himself. So we don't need any lock here.
735 @seealso class OFrames
736 @return A reference to the helper.
738 @onerror A null reference is returned.
740 *//*-*************************************************************************************************************/
741 css::uno::Reference
< css::frame::XFrames
> SAL_CALL
Desktop::getFrames()
743 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
744 // Register transaction and reject wrong calls.
745 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
747 return m_xFramesHelper
;
750 /*-************************************************************************************************************
751 @interface XFramesSupplier
752 @short set/get the current active child frame
753 @descr It must be a task. Direct children of desktop are tasks only! No frames are accepted.
754 We don't save this information directly in this class. We use our container-helper
757 @attention Helper is threadsafe himself. So we don't need any lock here.
759 @seealso class OFrameContainer
761 @param "xFrame", new active frame (must be valid!)
762 @return A reference to our current active childtask, if anyone exist.
764 @onerror A null reference is returned.
766 *//*-*************************************************************************************************************/
767 void SAL_CALL
Desktop::setActiveFrame( const css::uno::Reference
< css::frame::XFrame
>& xFrame
)
769 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
770 // Register transaction and reject wrong calls.
771 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
773 // Get old active frame first.
774 // If nothing will change - do nothing!
775 // Otherwise set new active frame ...
776 // and deactivate last frame.
777 // It's necessary for our FrameActionEvent listener on a frame!
778 css::uno::Reference
< css::frame::XFrame
> xLastActiveChild
= m_aChildTaskContainer
.getActive();
779 if( xLastActiveChild
!= xFrame
)
781 m_aChildTaskContainer
.setActive( xFrame
);
782 if( xLastActiveChild
.is() )
784 xLastActiveChild
->deactivate();
789 css::uno::Reference
< css::frame::XFrame
> SAL_CALL
Desktop::getActiveFrame()
791 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
792 // Register transaction and reject wrong calls.
793 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
795 return m_aChildTaskContainer
.getActive();
800 @short non implemented methods!
801 @descr Some method make no sense for our desktop! He has no window or parent or ...
802 So we should implement it empty and warn programmer, if he use it!
804 void SAL_CALL
Desktop::initialize( const css::uno::Reference
< css::awt::XWindow
>& )
808 css::uno::Reference
< css::awt::XWindow
> SAL_CALL
Desktop::getContainerWindow()
810 return css::uno::Reference
< css::awt::XWindow
>();
813 void SAL_CALL
Desktop::setCreator( const css::uno::Reference
< css::frame::XFramesSupplier
>& /*xCreator*/ )
817 css::uno::Reference
< css::frame::XFramesSupplier
> SAL_CALL
Desktop::getCreator()
819 return css::uno::Reference
< css::frame::XFramesSupplier
>();
822 OUString SAL_CALL
Desktop::getName()
828 void SAL_CALL
Desktop::setName( const OUString
& sName
)
834 sal_Bool SAL_CALL
Desktop::isTop()
839 void SAL_CALL
Desktop::activate()
841 // Desktop is active always... but sometimes our frames try to activate
842 // the complete path from bottom to top... And our desktop is the topest frame :-(
843 // So - please don't show any assertions here. Do nothing!
846 void SAL_CALL
Desktop::deactivate()
848 // Desktop is active always... but sometimes our frames try to deactivate
849 // the complete path from bottom to top... And our desktop is the topest frame :-(
850 // So - please don't show any assertions here. Do nothing!
853 sal_Bool SAL_CALL
Desktop::isActive()
858 sal_Bool SAL_CALL
Desktop::setComponent( const css::uno::Reference
< css::awt::XWindow
>& /*xComponentWindow*/ ,
859 const css::uno::Reference
< css::frame::XController
>& /*xController*/ )
864 css::uno::Reference
< css::awt::XWindow
> SAL_CALL
Desktop::getComponentWindow()
866 return css::uno::Reference
< css::awt::XWindow
>();
869 css::uno::Reference
< css::frame::XController
> SAL_CALL
Desktop::getController()
871 return css::uno::Reference
< css::frame::XController
>();
874 void SAL_CALL
Desktop::contextChanged()
878 void SAL_CALL
Desktop::addFrameActionListener( const css::uno::Reference
< css::frame::XFrameActionListener
>& )
882 // css::frame::XFrame
883 void SAL_CALL
Desktop::removeFrameActionListener( const css::uno::Reference
< css::frame::XFrameActionListener
>& )
887 /*-************************************************************************************************************
889 @short try to find a frame with special parameters
890 @descr This method searches for a frame with the specified name.
891 Frames may contain other frames (e.g. a frameset) and may
892 be contained in other frames. This hierarchy is searched by
894 First some special names are taken into account, i.e. "",
895 "_self", "_top", "_parent" etc. The FrameSearchFlags are ignored
896 when comparing these names with aTargetFrameName, further steps are
897 controlled by the FrameSearchFlags. If allowed, the name of the frame
898 itself is compared with the desired one, then ( again if allowed )
899 the method findFrame is called for all children of the frame.
900 If no Frame with the given name is found until the top frames container,
901 a new top Frame is created, if this is allowed by a special
902 FrameSearchFlag. The new Frame also gets the desired name.
903 We use a helper to get right search direction and react in a right manner.
905 @seealso class TargetFinder
907 @param "sTargetFrameName" , name of searched frame
908 @param "nSearchFlags" , flags to regulate search
909 @return A reference to an existing frame in hierarchy, if it exist.
911 @onerror A null reference is returned.
913 *//*-*************************************************************************************************************/
914 css::uno::Reference
< css::frame::XFrame
> SAL_CALL
Desktop::findFrame( const OUString
& sTargetFrameName
,
915 sal_Int32 nSearchFlags
)
917 css::uno::Reference
< css::frame::XFrame
> xTarget
;
919 // 0) Ignore wrong parameter!
920 // We don't support search for following special targets.
921 // If we reject these requests, we must not check for such names
922 // in following code again and again. If we do not, so wrong
923 // search results can occur!
926 (sTargetFrameName
==SPECIALTARGET_DEFAULT
) || // valid for dispatches - not for findFrame()!
927 (sTargetFrameName
==SPECIALTARGET_PARENT
) || // we have no parent by definition
928 (sTargetFrameName
==SPECIALTARGET_BEAMER
) // beamer frames are allowed as child of tasks only -
929 // and they exist more than ones. We have no idea which our sub tasks is the right one
935 // I) check for special defined targets first which must be handled exclusive.
936 // force using of "if() else if() ..."
939 // create a new task as child of this desktop instance
940 // Note: Used helper TaskCreator use us automatically ...
942 if ( sTargetFrameName
==SPECIALTARGET_BLANK
)
944 TaskCreator
aCreator( m_xContext
);
945 xTarget
= aCreator
.createTask(sTargetFrameName
, utl::MediaDescriptor());
949 // We are top by definition
951 else if ( sTargetFrameName
==SPECIALTARGET_TOP
)
956 // I.III) "_self", ""
957 // This mean this "frame" in every case.
960 ( sTargetFrameName
==SPECIALTARGET_SELF
) ||
961 ( sTargetFrameName
.isEmpty() )
970 // II) otherwise use optional given search flags
971 // force using of combinations of such flags. means no "else" part of use if() statements.
972 // But we ust break further searches if target was already found.
973 // Order of using flags is fix: SELF - CHILDREN - SIBLINGS - PARENT
974 // TASK and CREATE are handled special.
975 // But note: Such flags are not valid for the desktop - especially SIBLINGS or PARENT.
978 // Check for right name. If it's the searched one return ourself - otherwise
982 (nSearchFlags
& css::frame::FrameSearchFlag::SELF
) &&
983 (m_sName
== sTargetFrameName
)
990 // This is a special flag. Normally it regulate search inside tasks and forbid access to parent trees.
991 // But the desktop exists outside such task trees. They are our sub trees. So the desktop implement
992 // a special feature: We use it to start search on our direct children only. That means we suppress
993 // search on ALL child frames. May that can be useful to get access on opened document tasks
994 // only without filter out all non really required sub frames ...
995 // Used helper method on our container doesn't create any frame - it's a search only.
998 ( ! xTarget
.is() ) &&
999 (nSearchFlags
& css::frame::FrameSearchFlag::TASKS
)
1002 xTarget
= m_aChildTaskContainer
.searchOnDirectChildrens(sTargetFrameName
);
1006 // Search on all children for the given target name.
1007 // An empty name value can't occur here - because it must be already handled as "_self"
1008 // before. Used helper function of container doesn't create any frame.
1009 // It makes a deep search only.
1012 ( ! xTarget
.is() ) &&
1013 (nSearchFlags
& css::frame::FrameSearchFlag::CHILDREN
)
1016 xTarget
= m_aChildTaskContainer
.searchOnAllChildrens(sTargetFrameName
);
1020 // If we haven't found any valid target frame by using normal flags - but user allowed us to create
1021 // a new one ... we should do that. Used TaskCreator use us automatically as parent!
1024 ( ! xTarget
.is() ) &&
1025 (nSearchFlags
& css::frame::FrameSearchFlag::CREATE
)
1028 TaskCreator
aCreator( m_xContext
);
1029 xTarget
= aCreator
.createTask(sTargetFrameName
, utl::MediaDescriptor());
1036 void SAL_CALL
Desktop::disposing()
1038 // Safe impossible cases
1039 // It's a programming error if dispose is called before terminate!
1041 // But if you just ignore the assertion (which happens in unit
1042 // tests for instance in sc/qa/unit) nothing bad happens.
1043 assert(m_bIsShutdown
&& "Desktop disposed before terminating it");
1046 SolarMutexGuard aWriteLock
;
1049 TransactionGuard
aTransaction(m_aTransactionManager
, E_HARDEXCEPTIONS
);
1052 // Disable this instance for further work.
1053 // This will wait for all current running transactions ...
1054 // and reject all new incoming requests!
1055 m_aTransactionManager
.setWorkingMode(E_BEFORECLOSE
);
1058 // Following lines of code can be called outside a synchronized block ...
1059 // Because our transaction manager will block all new requests to this object.
1060 // So nobody can use us any longer.
1061 // Exception: Only removing of listener will work ... and this code can't be dangerous.
1063 // First we have to kill all listener connections.
1064 // They might rely on our member and can hinder us on releasing them.
1065 css::uno::Reference
< css::uno::XInterface
> xThis ( static_cast< ::cppu::OWeakObject
* >(this), css::uno::UNO_QUERY
);
1066 css::lang::EventObject
aEvent( xThis
);
1067 m_aListenerContainer
.disposeAndClear( aEvent
);
1069 // Clear our child task container and forget all task references hardly.
1070 // Normally all open document was already closed by our terminate() function before ...
1071 // New opened frames will have a problem now .-)
1072 m_aChildTaskContainer
.clear();
1074 // Dispose our helper too.
1075 css::uno::Reference
< css::lang::XEventListener
> xFramesHelper( m_xFramesHelper
, css::uno::UNO_QUERY
);
1076 if( xFramesHelper
.is() )
1077 xFramesHelper
->disposing( aEvent
);
1079 // At least clean up other member references.
1080 m_xDispatchHelper
.clear();
1081 m_xFramesHelper
.clear();
1084 m_xPipeTerminator
.clear();
1085 m_xQuickLauncher
.clear();
1086 m_xSWThreadManager
.clear();
1088 // we need a copy because the disposing might call the removeEventListener method
1089 std::vector
< css::uno::Reference
<css::frame::XTerminateListener
> > xComponentDllListeners
;
1090 xComponentDllListeners
.swap(m_xComponentDllListeners
);
1091 for (auto& xListener
: xComponentDllListeners
)
1093 xListener
->disposing(aEvent
);
1095 xComponentDllListeners
.clear();
1096 m_xSfxTerminator
.clear();
1097 m_xCommandOptions
.reset();
1099 // From this point nothing will work further on this object ...
1100 // excepting our dtor() .-)
1101 m_aTransactionManager
.setWorkingMode( E_CLOSE
);
1105 @interface XComponent
1106 @short add/remove listener for dispose events
1107 @descr Add an event listener to this object, if you wish to get information
1109 You must release this listener reference during your own disposing() method.
1111 @attention Our container is threadsafe himself. So we don't need any lock here.
1112 @param "xListener", reference to valid listener. We don't accept invalid values!
1115 void SAL_CALL
Desktop::addEventListener( const css::uno::Reference
< css::lang::XEventListener
>& xListener
)
1117 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
1118 // Safe impossible cases
1119 // Method not defined for all incoming parameter.
1120 SAL_WARN_IF( !xListener
.is(), "fwk.desktop", "Desktop::addEventListener(): Invalid parameter detected!" );
1121 // Register transaction and reject wrong calls.
1122 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
1124 m_aListenerContainer
.addInterface( cppu::UnoType
<css::lang::XEventListener
>::get(), xListener
);
1127 void SAL_CALL
Desktop::removeEventListener( const css::uno::Reference
< css::lang::XEventListener
>& xListener
)
1129 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
1130 // Safe impossible cases
1131 // Method not defined for all incoming parameter.
1132 SAL_WARN_IF( !xListener
.is(), "fwk.desktop", "Desktop::removeEventListener(): Invalid parameter detected!" );
1133 // Register transaction and reject wrong calls.
1134 TransactionGuard
aTransaction( m_aTransactionManager
, E_SOFTEXCEPTIONS
);
1136 m_aListenerContainer
.removeInterface( cppu::UnoType
<css::lang::XEventListener
>::get(), xListener
);
1139 /*-************************************************************************************************************
1140 @interface XDispatchResultListener
1141 @short callback for dispatches
1142 @descr To support our method "loadComponentFromURL()" we are listener on temp. created dispatcher.
1143 They call us back in this method "statusChanged()". As source of given state event, they give us a
1144 reference to the target frame, in which dispatch was loaded! So we can use it to return his component
1145 to caller! If no target exist ... ??!!
1147 @seealso method loadComponentFromURL()
1149 @param "aEvent", state event which (hopefully) valid information
1151 *//*-*************************************************************************************************************/
1152 void SAL_CALL
Desktop::dispatchFinished( const css::frame::DispatchResultEvent
& aEvent
)
1154 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
1155 // Register transaction and reject wrong calls.
1156 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
1159 if( m_eLoadState
!= E_INTERACTION
)
1161 m_eLoadState
= E_FAILED
;
1162 if( aEvent
.State
== css::frame::DispatchResultState::SUCCESS
)
1164 css::uno::Reference
< css::frame::XFrame
> xLastFrame
; /// last target of "loadComponentFromURL()"!
1165 if ( aEvent
.Result
>>= xLastFrame
)
1166 m_eLoadState
= E_SUCCESSFUL
;
1171 /*-************************************************************************************************************
1172 @interface XEventListener
1173 @short not implemented!
1174 @descr We are a status listener ... and so we must be an event listener too ... But we don't need it really!
1175 We are a temp. listener only and our lifetime isn't smaller then of our temp. used dispatcher.
1177 @seealso method loadComponentFromURL()
1178 *//*-*************************************************************************************************************/
1179 void SAL_CALL
Desktop::disposing( const css::lang::EventObject
& )
1181 SAL_WARN( "fwk.desktop", "Desktop::disposing(): Algorithm error! Normally desktop is temp. listener ... not all the time. So this method shouldn't be called." );
1184 /*-************************************************************************************************************
1185 @interface XInteractionHandler
1186 @short callback for loadComponentFromURL for detected exceptions during load process
1187 @descr In this case we must cancel loading and throw these detected exception again as result
1188 of our own called method.
1191 Normal loop in loadComponentFromURL() breaks on set member m_eLoadState during callback statusChanged().
1192 But these interaction feature implements second way to do so! So we must look on different callbacks
1193 for same operation ... and live with it.
1195 Search for given continuations too. If any XInteractionAbort exist ... use it to abort further operations
1196 for currently running operation!
1198 @seealso method loadComponentFromURL()
1199 @seealso member m_eLoadState
1201 @param "xRequest", request for interaction - normal a wrapped target exception from bottom services
1203 *//*-*************************************************************************************************************/
1204 void SAL_CALL
Desktop::handle( const css::uno::Reference
< css::task::XInteractionRequest
>& xRequest
)
1206 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
1207 // Register transaction and reject wrong calls.
1208 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
1210 // Don't check incoming request!
1211 // If somewhere starts interaction without right parameter - he made something wrong.
1212 // loadComponentFromURL() waits for these event - otherwise it yield for ever!
1214 // get packed request and work on it first
1215 // Attention: Don't set it on internal member BEFORE interaction is finished - because
1216 // "loadComponentFromURL()" yield tills this member is changed. If we do it before
1217 // interaction finish we can't guarantee right functionality. May be we cancel load process to earlier...
1218 css::uno::Any aRequest
= xRequest
->getRequest();
1220 // extract continuations from request
1221 css::uno::Sequence
< css::uno::Reference
< css::task::XInteractionContinuation
> > lContinuations
= xRequest
->getContinuations();
1222 css::uno::Reference
< css::task::XInteractionAbort
> xAbort
;
1223 css::uno::Reference
< css::task::XInteractionApprove
> xApprove
;
1224 css::uno::Reference
< css::document::XInteractionFilterSelect
> xFilterSelect
;
1225 bool bAbort
= false;
1227 sal_Int32 nCount
=lContinuations
.getLength();
1228 for( sal_Int32 nStep
=0; nStep
<nCount
; ++nStep
)
1231 xAbort
.set( lContinuations
[nStep
], css::uno::UNO_QUERY
);
1233 if( ! xApprove
.is() )
1234 xApprove
.set( lContinuations
[nStep
], css::uno::UNO_QUERY
);
1236 if( ! xFilterSelect
.is() )
1237 xFilterSelect
.set( lContinuations
[nStep
], css::uno::UNO_QUERY
);
1240 // differ between abortable interactions (error, unknown filter...)
1241 // and other ones (ambiguous but not unknown filter...)
1242 css::task::ErrorCodeRequest aErrorCodeRequest
;
1243 if( aRequest
>>= aErrorCodeRequest
)
1245 bool bWarning
= ErrCode(aErrorCodeRequest
.ErrCode
).IsWarning();
1246 if (xApprove
.is() && bWarning
)
1255 else if( xAbort
.is() )
1261 // Ok now it's time to break yield loop of loadComponentFromURL().
1262 // But only for really aborted requests!
1263 // For example warnings will be approved and we wait for any success story ...
1267 m_eLoadState
= E_INTERACTION
;
1271 ::sal_Int32 SAL_CALL
Desktop::leaseNumber( const css::uno::Reference
< css::uno::XInterface
>& xComponent
)
1273 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
1274 return m_xTitleNumberGenerator
->leaseNumber (xComponent
);
1277 void SAL_CALL
Desktop::releaseNumber( ::sal_Int32 nNumber
)
1279 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
1280 m_xTitleNumberGenerator
->releaseNumber (nNumber
);
1283 void SAL_CALL
Desktop::releaseNumberForComponent( const css::uno::Reference
< css::uno::XInterface
>& xComponent
)
1285 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
1286 m_xTitleNumberGenerator
->releaseNumberForComponent (xComponent
);
1289 OUString SAL_CALL
Desktop::getUntitledPrefix()
1291 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
1292 return m_xTitleNumberGenerator
->getUntitledPrefix ();
1295 /*-************************************************************************************************************
1296 @short try to convert a property value
1297 @descr This method is called from helperclass "OPropertySetHelper".
1298 Don't use this directly!
1299 You must try to convert the value of given PropHandle and
1300 return results of this operation. This will be used to ask vetoable
1301 listener. If no listener has a veto, we will change value really!
1302 ( in method setFastPropertyValue_NoBroadcast(...) )
1304 @attention Methods of OPropertySethelper are safed by using our shared osl mutex! (see ctor!)
1305 So we must use different locks to make our implementation threadsafe.
1307 @seealso class OPropertySetHelper
1308 @seealso method setFastPropertyValue_NoBroadcast()
1310 @param "aConvertedValue" new converted value of property
1311 @param "aOldValue" old value of property
1312 @param "nHandle" handle of property
1313 @param "aValue" new value of property
1314 @return sal_True if value will be changed, sal_FALSE otherway
1316 @onerror IllegalArgumentException, if you call this with an invalid argument
1318 *//*-*************************************************************************************************************/
1319 sal_Bool SAL_CALL
Desktop::convertFastPropertyValue( css::uno::Any
& aConvertedValue
,
1320 css::uno::Any
& aOldValue
,
1322 const css::uno::Any
& aValue
)
1324 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
1325 // Register transaction and reject wrong calls.
1326 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
1328 // Initialize state with sal_False !!!
1329 // (Handle can be invalid)
1330 bool bReturn
= false;
1334 case PropHandle::SuspendQuickstartVeto
:
1335 bReturn
= PropHelper::willPropertyBeChanged(
1336 css::uno::Any(m_bSuspendQuickstartVeto
),
1341 case PropHandle::DispatchRecorderSupplier
:
1342 bReturn
= PropHelper::willPropertyBeChanged(
1343 css::uno::Any(m_xDispatchRecorderSupplier
),
1348 case PropHandle::Title
:
1349 bReturn
= PropHelper::willPropertyBeChanged(
1350 css::uno::Any(m_sTitle
),
1357 // Return state of operation.
1361 /*-************************************************************************************************************
1362 @short set value of a transient property
1363 @descr This method is calling from helperclass "OPropertySetHelper".
1364 Don't use this directly!
1365 Handle and value are valid everyway! You must set the new value only.
1366 After this, baseclass send messages to all listener automatically.
1368 @seealso class OPropertySetHelper
1370 @param "nHandle" handle of property to change
1371 @param "aValue" new value of property
1372 @onerror An exception is thrown.
1374 *//*-*************************************************************************************************************/
1375 void SAL_CALL
Desktop::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle
,
1376 const css::uno::Any
& aValue
)
1378 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
1379 // Register transaction and reject wrong calls.
1380 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
1384 case PropHandle::SuspendQuickstartVeto
: aValue
>>= m_bSuspendQuickstartVeto
;
1386 case PropHandle::DispatchRecorderSupplier
: aValue
>>= m_xDispatchRecorderSupplier
;
1388 case PropHandle::Title
: aValue
>>= m_sTitle
;
1393 /*-************************************************************************************************************
1394 @short get value of a transient property
1395 @descr This method is calling from helperclass "OPropertySetHelper".
1396 Don't use this directly!
1398 @attention We don't need any mutex or lock here ... We use threadsafe container or methods here only!
1400 @seealso class OPropertySetHelper
1402 @param "nHandle" handle of property to change
1403 @param "aValue" current value of property
1405 *//*-*************************************************************************************************************/
1406 void SAL_CALL
Desktop::getFastPropertyValue( css::uno::Any
& aValue
,
1407 sal_Int32 nHandle
) const
1409 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
1410 // Register transaction and reject wrong calls.
1411 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
1415 case PropHandle::ActiveFrame
: aValue
<<= m_aChildTaskContainer
.getActive();
1417 case PropHandle::IsPlugged
: aValue
<<= false;
1419 case PropHandle::SuspendQuickstartVeto
: aValue
<<= m_bSuspendQuickstartVeto
;
1421 case PropHandle::DispatchRecorderSupplier
: aValue
<<= m_xDispatchRecorderSupplier
;
1423 case PropHandle::Title
: aValue
<<= m_sTitle
;
1428 ::cppu::IPropertyArrayHelper
& SAL_CALL
Desktop::getInfoHelper()
1430 static cppu::OPropertyArrayHelper HELPER
=
1432 return cppu::OPropertyArrayHelper
{
1433 {{"ActiveFrame", PropHandle::ActiveFrame
,
1434 cppu::UnoType
<css::lang::XComponent
>::get(),
1435 (css::beans::PropertyAttribute::TRANSIENT
1436 | css::beans::PropertyAttribute::READONLY
)},
1437 {"DispatchRecorderSupplier",
1438 PropHandle::DispatchRecorderSupplier
,
1439 cppu::UnoType
<css::frame::XDispatchRecorderSupplier
>::get(),
1440 css::beans::PropertyAttribute::TRANSIENT
},
1442 PropHandle::IsPlugged
, cppu::UnoType
<bool>::get(),
1443 (css::beans::PropertyAttribute::TRANSIENT
1444 | css::beans::PropertyAttribute::READONLY
)},
1445 {"SuspendQuickstartVeto", PropHandle::SuspendQuickstartVeto
,
1446 cppu::UnoType
<bool>::get(),
1447 css::beans::PropertyAttribute::TRANSIENT
},
1448 {"Title", PropHandle::Title
, cppu::UnoType
<OUString
>::get(),
1449 css::beans::PropertyAttribute::TRANSIENT
}},
1455 /*-************************************************************************************************************
1456 @short return propertysetinfo
1457 @descr You can call this method to get information about transient properties
1460 @attention You must use global lock (method use static variable) ... and it must be the shareable osl mutex of it.
1461 Because; our baseclass use this mutex to make his code threadsafe. We use our lock!
1462 So we could have two different mutex/lock mechanism at the same object.
1464 @seealso class OPropertySetHelper
1465 @seealso interface XPropertySet
1466 @seealso interface XMultiPropertySet
1467 @return reference to object with information [XPropertySetInfo]
1469 *//*-*************************************************************************************************************/
1470 css::uno::Reference
< css::beans::XPropertySetInfo
> SAL_CALL
Desktop::getPropertySetInfo()
1472 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
1473 // Register transaction and reject wrong calls.
1474 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
1476 // Create structure of propertysetinfo for baseclass "OPropertySetHelper".
1477 // (Use method "getInfoHelper()".)
1478 static css::uno::Reference
< css::beans::XPropertySetInfo
> xInfo(
1479 cppu::OPropertySetHelper::createPropertySetInfo( getInfoHelper() ) );
1484 /*-************************************************************************************************************
1485 @short return current component of current frame
1486 @descr The desktop himself has no component. But every frame in subtree.
1487 If somewhere call getCurrentComponent() at this class, we try to find the right frame and
1488 then we try to become his component. It can be a VCL-component, the model or the controller
1491 @attention We don't work on internal member ... so we don't need any lock here.
1493 @seealso method getCurrentComponent();
1495 @param "xFrame", reference to valid frame in hierarchy. Method is not defined for invalid values.
1496 But we don't check these. It's an IMPL-method and caller must use it right!
1497 @return A reference to found component.
1499 @onerror A null reference is returned.
1501 *//*-*************************************************************************************************************/
1502 css::uno::Reference
< css::lang::XComponent
> Desktop::impl_getFrameComponent( const css::uno::Reference
< css::frame::XFrame
>& xFrame
) const
1504 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
1505 // Register transaction and reject wrong calls.
1506 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
1508 // Set default return value, if method failed.
1509 css::uno::Reference
< css::lang::XComponent
> xComponent
;
1510 // Does no controller exists?
1511 css::uno::Reference
< css::frame::XController
> xController
= xFrame
->getController();
1512 if( !xController
.is() )
1514 // Controller not exist - use the VCL-component.
1515 xComponent
= xFrame
->getComponentWindow();
1519 // Does no model exists?
1520 css::uno::Reference
< css::frame::XModel
> xModel
= xController
->getModel();
1523 // Model exist - use the model as component.
1524 xComponent
= xModel
;
1528 // Model not exist - use the controller as component.
1529 xComponent
= xController
;
1536 bool Desktop::impl_sendQueryTerminationEvent(Desktop::TTerminateListenerList
& lCalledListener
)
1538 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
1540 comphelper::OInterfaceContainerHelper2
* pContainer
= m_aListenerContainer
.getContainer( cppu::UnoType
<css::frame::XTerminateListener
>::get());
1544 css::lang::EventObject
aEvent( static_cast< ::cppu::OWeakObject
* >(this) );
1546 comphelper::OInterfaceIteratorHelper2
aIterator( *pContainer
);
1547 while ( aIterator
.hasMoreElements() )
1551 css::uno::Reference
< css::frame::XTerminateListener
> xListener(aIterator
.next(), css::uno::UNO_QUERY
);
1552 if ( ! xListener
.is() )
1554 xListener
->queryTermination( aEvent
);
1555 lCalledListener
.push_back(xListener
);
1557 catch( const css::frame::TerminationVetoException
& )
1559 // first veto will stop the query loop.
1562 catch( const css::uno::Exception
& )
1564 // clean up container.
1565 // E.g. dead remote listener objects can make trouble otherwise.
1566 // Iterator implementation allows removing objects during it's used !
1574 void Desktop::impl_sendCancelTerminationEvent(const Desktop::TTerminateListenerList
& lCalledListener
)
1576 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
1578 css::lang::EventObject
aEvent( static_cast< ::cppu::OWeakObject
* >(this) );
1579 for (const css::uno::Reference
<css::frame::XTerminateListener
>& xListener
: lCalledListener
)
1583 // Note: cancelTermination() is a new and optional interface method !
1584 css::uno::Reference
< css::frame::XTerminateListener2
> xListenerGeneration2(xListener
, css::uno::UNO_QUERY
);
1585 if ( ! xListenerGeneration2
.is() )
1587 xListenerGeneration2
->cancelTermination( aEvent
);
1589 catch( const css::uno::Exception
& )
1594 void Desktop::impl_sendTerminateToClipboard()
1596 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
1598 comphelper::OInterfaceContainerHelper2
* pContainer
= m_aListenerContainer
.getContainer( cppu::UnoType
<css::frame::XTerminateListener
>::get());
1602 comphelper::OInterfaceIteratorHelper2
aIterator( *pContainer
);
1603 while ( aIterator
.hasMoreElements() )
1607 css::frame::XTerminateListener
* pTerminateListener
=
1608 static_cast< css::frame::XTerminateListener
* >(aIterator
.next());
1609 css::uno::Reference
< css::lang::XServiceInfo
> xInfo( pTerminateListener
, css::uno::UNO_QUERY
);
1613 if ( xInfo
->getImplementationName() != "com.sun.star.comp.svt.TransferableHelperTerminateListener" )
1616 css::lang::EventObject
aEvent( static_cast< ::cppu::OWeakObject
* >(this) );
1617 pTerminateListener
->notifyTermination( aEvent
);
1619 // don't notify twice
1622 catch( const css::uno::Exception
& )
1624 // clean up container.
1625 // E.g. dead remote listener objects can make trouble otherwise.
1626 // Iterator implementation allows removing objects during it's used !
1632 void Desktop::impl_sendNotifyTerminationEvent()
1634 TransactionGuard
aTransaction( m_aTransactionManager
, E_HARDEXCEPTIONS
);
1636 comphelper::OInterfaceContainerHelper2
* pContainer
= m_aListenerContainer
.getContainer( cppu::UnoType
<css::frame::XTerminateListener
>::get());
1640 css::lang::EventObject
aEvent( static_cast< ::cppu::OWeakObject
* >(this) );
1642 comphelper::OInterfaceIteratorHelper2
aIterator( *pContainer
);
1643 while ( aIterator
.hasMoreElements() )
1647 static_cast< css::frame::XTerminateListener
* >(aIterator
.next())->notifyTermination( aEvent
);
1649 catch( const css::uno::Exception
& )
1651 // clean up container.
1652 // E.g. dead remote listener objects can make trouble otherwise.
1653 // Iterator implementation allows removing objects during it's used !
1659 bool Desktop::impl_closeFrames(bool bAllowUI
)
1661 SolarMutexClearableGuard aReadLock
;
1662 css::uno::Sequence
< css::uno::Reference
< css::frame::XFrame
> > lFrames
= m_aChildTaskContainer
.getAllElements();
1665 ::sal_Int32 c
= lFrames
.getLength();
1667 ::sal_Int32 nNonClosedFrames
= 0;
1669 for( i
=0; i
<c
; ++i
)
1673 css::uno::Reference
< css::frame::XFrame
> xFrame
= lFrames
[i
];
1675 // XController.suspend() will show a UI ...
1676 // Use it in case it was allowed from outside only.
1677 bool bSuspended
= false;
1678 css::uno::Reference
< css::frame::XController
> xController
= xFrame
->getController();
1679 if ( bAllowUI
&& xController
.is() )
1681 bSuspended
= xController
->suspend( true );
1692 // Try to close frame (in case no UI was allowed without calling XController->suspend() before!)
1693 // But don't deliver ownership to any other one!
1694 // This method can be called again.
1695 css::uno::Reference
< css::util::XCloseable
> xClose( xFrame
, css::uno::UNO_QUERY
);
1700 xClose
->close(false);
1702 catch(const css::util::CloseVetoException
&)
1704 // Any internal process of this frame disagree with our request.
1705 // Safe this state but don't break these loop. Other frames has to be closed!
1708 // Reactivate controller.
1709 // It can happen that XController.suspend() returned true... but a registered close listener
1710 // threw these veto exception. Then the controller has to be reactivated. Otherwise
1711 // these document doesn't work any more.
1712 if ( bSuspended
&& xController
.is())
1713 xController
->suspend(false);
1716 // If interface XClosable interface exists and was used...
1717 // it's not allowed to use XComponent->dispose() also!
1721 // XClosable not supported ?
1722 // Then we have to dispose these frame hardly.
1726 // Don't remove these frame from our child container!
1727 // A frame do it by itself inside close()/dispose() method.
1729 catch(const css::lang::DisposedException
&)
1731 // Dispose frames are closed frames.
1732 // So we can count it here .-)
1736 // reset the session
1739 return (nNonClosedFrames
< 1);
1742 } // namespace framework
1746 rtl::Reference
<framework::Desktop
> createDesktop(
1747 css::uno::Reference
<css::uno::XComponentContext
> const & context
)
1749 SolarMutexGuard g
; // tdf#114025 init with SolarMutex to avoid deadlock
1750 rtl::Reference
<framework::Desktop
> desktop(new framework::Desktop(context
));
1751 desktop
->constructorInit();
1757 const rtl::Reference
<framework::Desktop
> & framework::getDesktop(
1758 css::uno::Reference
<css::uno::XComponentContext
> const & context
)
1760 static auto const instance
= createDesktop(context
);
1764 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1765 com_sun_star_comp_framework_Desktop_get_implementation(
1766 css::uno::XComponentContext
*context
,
1767 css::uno::Sequence
<css::uno::Any
> const &)
1769 return cppu::acquire(framework::getDesktop(context
).get());
1772 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */