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