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