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