Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <dispatch/closedispatcher.hxx>
30 : : #include <pattern/frame.hxx>
31 : : #include <threadhelp/readguard.hxx>
32 : : #include <threadhelp/writeguard.hxx>
33 : : #include <framework/framelistanalyzer.hxx>
34 : : #include <services.h>
35 : : #include <general.h>
36 : :
37 : : #include <com/sun/star/frame/XDesktop.hpp>
38 : : #include <com/sun/star/frame/XController.hpp>
39 : : #include <com/sun/star/frame/CommandGroup.hpp>
40 : : #include <com/sun/star/lang/DisposedException.hpp>
41 : : #include <com/sun/star/awt/XTopWindow.hpp>
42 : : #include <com/sun/star/document/XActionLockable.hpp>
43 : : #include "com/sun/star/beans/XFastPropertySet.hpp"
44 : : #include <toolkit/helper/vclunohelper.hxx>
45 : :
46 : : #include <vcl/window.hxx>
47 : : #include <vcl/svapp.hxx>
48 : : #include "vcl/syswin.hxx"
49 : : #include <osl/mutex.hxx>
50 : : #include <unotools/moduleoptions.hxx>
51 : :
52 : :
53 : : using namespace com::sun::star;
54 : :
55 : : namespace framework{
56 : :
57 : : #ifdef fpf
58 : : #error "Who uses \"fpf\" as define. It will overwrite my namespace alias ..."
59 : : #endif
60 : : namespace fpf = ::framework::pattern::frame;
61 : :
62 : : const char URL_CLOSEDOC[] = ".uno:CloseDoc";
63 : : const char URL_CLOSEWIN[] = ".uno:CloseWin";
64 : : const char URL_CLOSEFRAME[] = ".uno:CloseFrame";
65 : :
66 : :
67 [ + + ][ + - ]: 62 : DEFINE_XINTERFACE_4(CloseDispatcher ,
68 : : OWeakObject ,
69 : : DIRECT_INTERFACE(css::lang::XTypeProvider ),
70 : : DIRECT_INTERFACE(css::frame::XNotifyingDispatch ),
71 : : DIRECT_INTERFACE(css::frame::XDispatch ),
72 : : DIRECT_INTERFACE(css::frame::XDispatchInformationProvider))
73 : :
74 : : // Note: XStatusListener is an implementation detail. Hide it for scripting!
75 [ # # ][ # # ]: 0 : DEFINE_XTYPEPROVIDER_4(CloseDispatcher ,
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
76 : : css::lang::XTypeProvider ,
77 : : css::frame::XDispatchInformationProvider,
78 : : css::frame::XNotifyingDispatch ,
79 : : css::frame::XDispatch )
80 : :
81 : : //-----------------------------------------------
82 : 2 : CloseDispatcher::CloseDispatcher(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR ,
83 : : const css::uno::Reference< css::frame::XFrame >& xFrame ,
84 : : const ::rtl::OUString& sTarget)
85 [ + - ]: 2 : : ThreadHelpBase (&Application::GetSolarMutex() )
86 : : , ::cppu::OWeakObject( )
87 : : , m_xSMGR (xSMGR )
88 : : , m_aAsyncCallback (LINK( this, CloseDispatcher, impl_asyncCallback))
89 [ + - ]: 2 : , m_lStatusListener (m_aLock.getShareableOslMutex() )
90 [ + - ][ + - ]: 6 : , m_pSysWindow(NULL)
[ + - ][ + - ]
[ + - ]
91 : : {
92 [ + - ]: 2 : uno::Reference<frame::XFrame> xTarget = static_impl_searchRightTargetFrame(xFrame, sTarget);
93 [ + - ]: 2 : m_xCloseFrame = xTarget;
94 : :
95 : : // Try to retrieve the system window instance of the closing frame.
96 [ + - ][ + - ]: 2 : uno::Reference<awt::XWindow> xWindow = xTarget->getContainerWindow();
97 [ + - ]: 2 : if (xWindow.is())
98 : : {
99 [ + - ]: 2 : Window* pWindow = VCLUnoHelper::GetWindow(xWindow);
100 [ + - ][ + - ]: 2 : if (pWindow->IsSystemWindow())
101 [ - + ]: 2 : m_pSysWindow = dynamic_cast<SystemWindow*>(pWindow);
102 : 2 : }
103 : 2 : }
104 : :
105 : : //-----------------------------------------------
106 [ + - ][ + - ]: 2 : CloseDispatcher::~CloseDispatcher()
[ + - ][ + - ]
[ + - ]
107 : : {
108 [ - + ]: 4 : }
109 : :
110 : : //-----------------------------------------------
111 : 2 : void SAL_CALL CloseDispatcher::dispatch(const css::util::URL& aURL ,
112 : : const css::uno::Sequence< css::beans::PropertyValue >& lArguments)
113 : : throw(css::uno::RuntimeException)
114 : : {
115 [ + - ]: 2 : dispatchWithNotification(aURL, lArguments, css::uno::Reference< css::frame::XDispatchResultListener >());
116 : 2 : }
117 : :
118 : : //-----------------------------------------------
119 : 0 : css::uno::Sequence< sal_Int16 > SAL_CALL CloseDispatcher::getSupportedCommandGroups()
120 : : throw(css::uno::RuntimeException)
121 : : {
122 : 0 : css::uno::Sequence< sal_Int16 > lGroups(2);
123 [ # # ]: 0 : lGroups[0] = css::frame::CommandGroup::VIEW;
124 [ # # ]: 0 : lGroups[1] = css::frame::CommandGroup::DOCUMENT;
125 : 0 : return lGroups;
126 : : }
127 : :
128 : : //-----------------------------------------------
129 : 0 : css::uno::Sequence< css::frame::DispatchInformation > SAL_CALL CloseDispatcher::getConfigurableDispatchInformation(sal_Int16 nCommandGroup)
130 : : throw(css::uno::RuntimeException)
131 : : {
132 [ # # ]: 0 : if (nCommandGroup == css::frame::CommandGroup::VIEW)
133 : : {
134 : : /* Attention: Dont add .uno:CloseFrame here. Because its not realy
135 : : a configurable feature ... and further it does not have
136 : : a valid UIName entry inside the GenericCommands.xcu ... */
137 [ # # ]: 0 : css::uno::Sequence< css::frame::DispatchInformation > lViewInfos(1);
138 [ # # ]: 0 : lViewInfos[0].Command = rtl::OUString(URL_CLOSEWIN);
139 [ # # ]: 0 : lViewInfos[0].GroupId = css::frame::CommandGroup::VIEW;
140 [ # # ][ # # ]: 0 : return lViewInfos;
141 : : }
142 [ # # ]: 0 : else if (nCommandGroup == css::frame::CommandGroup::DOCUMENT)
143 : : {
144 [ # # ]: 0 : css::uno::Sequence< css::frame::DispatchInformation > lDocInfos(1);
145 [ # # ]: 0 : lDocInfos[0].Command = rtl::OUString(URL_CLOSEDOC);
146 [ # # ]: 0 : lDocInfos[0].GroupId = css::frame::CommandGroup::DOCUMENT;
147 [ # # ][ # # ]: 0 : return lDocInfos;
148 : : }
149 : :
150 : 0 : return css::uno::Sequence< css::frame::DispatchInformation >();
151 : : }
152 : :
153 : : //-----------------------------------------------
154 : 0 : void SAL_CALL CloseDispatcher::addStatusListener(const css::uno::Reference< css::frame::XStatusListener >& /*xListener*/,
155 : : const css::util::URL& /*aURL*/ )
156 : : throw(css::uno::RuntimeException)
157 : : {
158 : 0 : }
159 : :
160 : : //-----------------------------------------------
161 : 0 : void SAL_CALL CloseDispatcher::removeStatusListener(const css::uno::Reference< css::frame::XStatusListener >& /*xListener*/,
162 : : const css::util::URL& /*aURL*/ )
163 : : throw(css::uno::RuntimeException)
164 : : {
165 : 0 : }
166 : :
167 : : //-----------------------------------------------
168 : 2 : void SAL_CALL CloseDispatcher::dispatchWithNotification(const css::util::URL& aURL ,
169 : : const css::uno::Sequence< css::beans::PropertyValue >& lArguments,
170 : : const css::uno::Reference< css::frame::XDispatchResultListener >& xListener )
171 : : throw(css::uno::RuntimeException)
172 : : {
173 : : // SAFE -> ----------------------------------
174 [ + - ]: 2 : WriteGuard aWriteLock(m_aLock);
175 : :
176 : : // This reference indicates, that we was already called before and
177 : : // our asynchronous process was not finished yet.
178 : : // We have to reject double calls. Otherwhise we risk,
179 : : // that we try to close an already closed resource ...
180 : : // And its no problem to do nothing then. The UI user will try it again, if
181 : : // non of these jobs was successfully.
182 [ - + ]: 2 : if (m_xSelfHold.is())
183 : : {
184 [ # # ]: 0 : aWriteLock.unlock();
185 : : // <- SAFE ------------------------------
186 : :
187 : : implts_notifyResultListener(
188 : : xListener,
189 : : css::frame::DispatchResultState::DONTKNOW,
190 [ # # ]: 0 : css::uno::Any());
191 : : return;
192 : : }
193 : :
194 : : // First we have to check, if this dispatcher is used right. Means if valid URLs are used.
195 : : // If not - we have to break this operation. But an optional listener must be informed.
196 : : // BTW: We save the information about the requested operation. Because
197 : : // we need it later.
198 [ - + ]: 2 : if ( aURL.Complete == URL_CLOSEDOC )
199 : 0 : m_eOperation = E_CLOSE_DOC;
200 [ + - ]: 2 : else if ( aURL.Complete == URL_CLOSEWIN )
201 : 2 : m_eOperation = E_CLOSE_WIN;
202 [ # # ]: 0 : else if ( aURL.Complete == URL_CLOSEFRAME )
203 : 0 : m_eOperation = E_CLOSE_FRAME;
204 : : else
205 : : {
206 [ # # ]: 0 : aWriteLock.unlock();
207 : : // <- SAFE ------------------------------
208 : :
209 : : implts_notifyResultListener(
210 : : xListener,
211 : : css::frame::DispatchResultState::FAILURE,
212 [ # # ]: 0 : css::uno::Any());
213 : : return;
214 : : }
215 : :
216 [ + - ][ + - ]: 2 : if (m_pSysWindow && m_pSysWindow->GetCloseHdl().IsSet())
[ + - ][ - + ]
[ - + ]
217 : : {
218 : : // The closing frame has its own close handler. Call it instead.
219 [ # # ][ # # ]: 0 : m_pSysWindow->GetCloseHdl().Call(m_pSysWindow);
220 : : return;
221 : : }
222 : :
223 : : // OK - URLs are the right ones.
224 : : // But we cant execute synchronously :-)
225 : : // May we are called from a generic key-input handler,
226 : : // which isnt aware that this call kill its own environment ...
227 : : // Do it asynchronous everytimes!
228 : :
229 : : // But dont forget to hold usself alive.
230 : : // We are called back from an environment, which doesnt know an uno reference.
231 : : // They call us back by using our c++ interface.
232 : :
233 [ + - ]: 2 : m_xResultListener = xListener;
234 [ + - ][ + - ]: 2 : m_xSelfHold = css::uno::Reference< css::uno::XInterface >(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
235 : :
236 [ + - ]: 2 : aWriteLock.unlock();
237 : : // <- SAFE ----------------------------------
238 : :
239 : 2 : sal_Bool bIsSynchron = sal_False;
240 [ - + ]: 2 : for (sal_Int32 nArgs=0; nArgs<lArguments.getLength(); nArgs++ )
241 : : {
242 [ # # ]: 0 : if ( lArguments[nArgs].Name == "SynchronMode" )
243 : : {
244 : 0 : lArguments[nArgs].Value >>= bIsSynchron;
245 : 0 : break;
246 : : }
247 : : }
248 : :
249 [ - + ]: 2 : if ( bIsSynchron )
250 [ # # ]: 0 : impl_asyncCallback(0);
251 : : else
252 [ + - ][ + - ]: 2 : m_aAsyncCallback.Post(0);
[ + - ]
253 : : }
254 : :
255 : : //-----------------------------------------------
256 : : /**
257 : : @short asynchronous callback
258 : : @descr We start all actions inside this object asnychronoue.
259 : : (see comments there).
260 : : Now we do the following:
261 : : - close all views to the same document, if needed and possible
262 : : - make the current frame empty
263 : : ! This step is neccessary to handle errors during closing the
264 : : document inside the frame. May the document shows a dialog and
265 : : the user ignore it. Then the state of the office can be changed
266 : : during we try to close frame and document.
267 : : - check the environment (menas count open frames - exlcuding our
268 : : current one)
269 : : - decide then, if we must close this frame only, establish the backing mode
270 : : or shutdown the whole application.
271 : : */
272 : 2 : IMPL_LINK_NOARG(CloseDispatcher, impl_asyncCallback)
273 : : {
274 : : try
275 : : {
276 : :
277 : : // Allow calling of XController->suspend() everytimes.
278 : : // Dispatch is an UI functionality. We implement such dispatch object here.
279 : : // And further XController->suspend() was designed to bring an UI ...
280 : 2 : sal_Bool bAllowSuspend = sal_True;
281 : 2 : sal_Bool bControllerSuspended = sal_False;
282 : :
283 : : // SAFE -> ----------------------------------
284 [ + - ]: 2 : ReadGuard aReadLock(m_aLock);
285 : :
286 : : // Closing of all views, related to the same document, is allowed
287 : : // only if the dispatched URL was ".uno:CloseDoc"!
288 : 2 : sal_Bool bCloseAllViewsToo = (m_eOperation == E_CLOSE_DOC);
289 : :
290 : : // BTW: Make some copies, which are needed later ...
291 : 2 : EOperation eOperation = m_eOperation;
292 : 2 : css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
293 [ + - ][ + - ]: 2 : css::uno::Reference< css::frame::XFrame > xCloseFrame (m_xCloseFrame.get(), css::uno::UNO_QUERY);
294 : 2 : css::uno::Reference< css::frame::XDispatchResultListener > xListener = m_xResultListener;
295 : :
296 [ + - ]: 2 : aReadLock.unlock();
297 : : // <- SAFE ----------------------------------
298 : :
299 : : // frame already dead ?!
300 : : // Nothing to do !
301 [ - + ]: 2 : if (! xCloseFrame.is())
302 : 0 : return 0;
303 : :
304 : 2 : sal_Bool bCloseFrame = sal_False;
305 : 2 : sal_Bool bEstablishBackingMode = sal_False;
306 : 2 : sal_Bool bTerminateApp = sal_False;
307 : :
308 : : // Analyze the environment a first time.
309 : : // If we found some special cases, we can
310 : : // make some decisions erliar!
311 [ + - ][ + - ]: 2 : css::uno::Reference< css::frame::XFramesSupplier > xDesktop(xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY_THROW);
[ + - ][ + - ]
312 [ + - ]: 2 : FrameListAnalyzer aCheck1(xDesktop, xCloseFrame, FrameListAnalyzer::E_HELP | FrameListAnalyzer::E_BACKINGCOMPONENT);
313 : :
314 : : // a) If the curent frame (where the close dispatch was requested for) does not have
315 : : // any parent frame ... it will close this frame only. Such frame isnt part of the
316 : : // global desktop tree ... and such frames are used as "implementation details" only.
317 : : // E.g. the live previews of our wizards doing such things. And then the owner of the frame
318 : : // is responsible for closing the application or accepting closing of the application
319 : : // by others.
320 [ + - ][ + - ]: 2 : if ( ! xCloseFrame->getCreator().is())
[ - + ]
321 : 0 : bCloseFrame = sal_True;
322 : : else
323 : :
324 : : // b) The help window cant disagree with any request.
325 : : // Because it doesnt implement a controller - it uses a window only.
326 : : // Further t cant be the last open frame - if we do all other things
327 : : // right inside this CloseDispatcher implementation.
328 : : // => close it!
329 [ - + ]: 2 : if (aCheck1.m_bReferenceIsHelp)
330 : 0 : bCloseFrame = sal_True;
331 : : else
332 : :
333 : : // c) If we are already in "backing mode", we have to terminate
334 : : // the application, if this special frame is closed.
335 : : // It doesnt matter, how many other frames (can be the help or hidden frames only)
336 : : // are open then.
337 : : // => terminate the application!
338 [ - + ]: 2 : if (aCheck1.m_bReferenceIsBacking)
339 : 0 : bTerminateApp = sal_True;
340 : : else
341 : :
342 : : // d) Otherwhise we have to: close all views to the same document, close the
343 : : // document inside our own frame and decide then again, what has to be done!
344 : : {
345 [ + - ][ + - ]: 2 : if (implts_prepareFrameForClosing(m_xCloseFrame, bAllowSuspend, bCloseAllViewsToo, bControllerSuspended))
[ + - ]
346 : : {
347 : : // OK; this frame is empty now.
348 : : // Check the environment again to decide, what is the next step.
349 [ + - ]: 2 : FrameListAnalyzer aCheck2(xDesktop, xCloseFrame, FrameListAnalyzer::E_ALL);
350 : :
351 : : // c1) there is as minimum 1 frame open, which is visible and contains a document
352 : : // different from our one. And its not the help!
353 : : // => close our frame only - nothing else.
354 [ - + ]: 2 : if (aCheck2.m_lOtherVisibleFrames.getLength()>0)
355 : 0 : bCloseFrame = sal_True;
356 : : else
357 : :
358 : : // c2) if we close the current view ... but not all other views
359 : : // to the same document, we must close the current frame only!
360 : : // Because implts_closeView() suspended this view only - does not
361 : : // close the frame.
362 [ + - - + ]: 4 : if (
[ - + ]
363 : : (!bCloseAllViewsToo ) &&
364 : 2 : (aCheck2.m_lModelFrames.getLength() > 0)
365 : : )
366 : 0 : bCloseFrame = sal_True;
367 : :
368 : : else
369 : : // c3) there is no other (visible) frame open ...
370 : : // The help module will be ignored everytimes!
371 : : // But we have to decide if we must terminate the
372 : : // application or establish the backing mode now.
373 : : // And that depends from the dispatched URL ...
374 : : {
375 [ - + ]: 2 : if (eOperation == E_CLOSE_FRAME)
376 : 0 : bTerminateApp = sal_True;
377 [ + - ][ + - ]: 2 : else if( SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::E_SSTARTMODULE) )
[ + - ][ + - ]
378 : 2 : bEstablishBackingMode = sal_True;
379 : : else
380 : 0 : bTerminateApp = sal_True;
381 [ + - ]: 2 : }
382 : : }
383 : : }
384 : :
385 : : // Do it now ...
386 : 2 : sal_Bool bSuccess = sal_False;
387 [ - + ]: 2 : if (bCloseFrame)
388 [ # # ]: 0 : bSuccess = implts_closeFrame();
389 : : else
390 [ + - ]: 2 : if (bEstablishBackingMode)
391 : : #if defined QUARTZ
392 : : {
393 : : // on mac close down, quickstarter keeps the process alive
394 : : // however if someone has shut down the quickstarter
395 : : // behave as any other platform
396 : :
397 : : bool bQuickstarterRunning = false;
398 : : // get quickstart service
399 : : try
400 : : {
401 : : css::uno::Reference< css::beans::XFastPropertySet > xSet( xSMGR->createInstance(IMPLEMENTATIONNAME_QUICKLAUNCHER), css::uno::UNO_QUERY_THROW );
402 : : if( xSet.is() )
403 : : {
404 : : css::uno::Any aVal( xSet->getFastPropertyValue( 0 ) );
405 : : sal_Bool bState = sal_False;
406 : : if( aVal >>= bState )
407 : : bQuickstarterRunning = bState;
408 : : }
409 : : }
410 : : catch( const css::uno::Exception& )
411 : : {
412 : : }
413 : : bSuccess = bQuickstarterRunning ? implts_terminateApplication() : implts_establishBackingMode();
414 : : }
415 : : #else
416 [ + - ]: 2 : bSuccess = implts_establishBackingMode();
417 : : #endif
418 : : else
419 [ # # ]: 0 : if (bTerminateApp)
420 [ # # ]: 0 : bSuccess = implts_terminateApplication();
421 : :
422 [ - + ][ # # ]: 2 : if (
423 : : ( ! bSuccess ) &&
424 : : ( bControllerSuspended )
425 : : )
426 : : {
427 [ # # ][ # # ]: 0 : css::uno::Reference< css::frame::XController > xController = xCloseFrame->getController();
428 [ # # ]: 0 : if (xController.is())
429 [ # # ][ # # ]: 0 : xController->suspend(sal_False);
430 : : }
431 : :
432 : : // inform listener
433 : 2 : sal_Int16 nState = css::frame::DispatchResultState::FAILURE;
434 [ + - ]: 2 : if (bSuccess)
435 : 2 : nState = css::frame::DispatchResultState::SUCCESS;
436 [ + - ]: 2 : implts_notifyResultListener(xListener, nState, css::uno::Any());
437 : :
438 : : // SAFE -> ----------------------------------
439 [ + - ]: 2 : WriteGuard aWriteLock(m_aLock);
440 : :
441 : : // This method was called asynchronous from our main thread by using a pointer.
442 : : // We reached this method only, by using a reference to ourself :-)
443 : : // Further this member is used to detect still running and not yet finished
444 : : // ansynchronous operations. So its time now to release this reference.
445 : : // But hold it temp alive. Otherwhise we die before we can finish this method realy :-))
446 : 2 : css::uno::Reference< css::uno::XInterface > xTempHold = m_xSelfHold;
447 : 2 : m_xSelfHold.clear();
448 : 2 : m_xResultListener.clear();
449 : :
450 [ + - ][ + - ]: 2 : aWriteLock.unlock();
[ - + ][ - + ]
[ - + ][ + - ]
[ + - ][ # # ]
[ + - ]
451 : : // <- SAFE ----------------------------------
452 : :
453 : : }
454 : 0 : catch(const css::lang::DisposedException&)
455 : : {
456 : : }
457 : :
458 : 2 : return 0;
459 : : }
460 : :
461 : : //-----------------------------------------------
462 : 2 : sal_Bool CloseDispatcher::implts_prepareFrameForClosing(const css::uno::Reference< css::frame::XFrame >& xFrame ,
463 : : sal_Bool bAllowSuspend ,
464 : : sal_Bool bCloseAllOtherViewsToo,
465 : : sal_Bool& bControllerSuspended )
466 : : {
467 : : // Frame already dead ... so this view is closed ... is closed ... is ... .-)
468 [ - + ]: 2 : if (! xFrame.is())
469 : 0 : return sal_True;
470 : :
471 : : // Close all views to the same document ... if forced to do so.
472 : : // But dont touch our own frame here!
473 : : // We must do so ... because the may be following controller->suspend()
474 : : // will show the "save/discard/cancel" dialog for the last view only!
475 [ - + ]: 2 : if (bCloseAllOtherViewsToo)
476 : : {
477 : : // SAFE -> ----------------------------------
478 [ # # ]: 0 : ReadGuard aReadLock(m_aLock);
479 : 0 : css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
480 [ # # ]: 0 : aReadLock.unlock();
481 : : // <- SAFE ----------------------------------
482 : :
483 [ # # ][ # # ]: 0 : css::uno::Reference< css::frame::XFramesSupplier > xDesktop(xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY_THROW);
[ # # ][ # # ]
484 [ # # ]: 0 : FrameListAnalyzer aCheck(xDesktop, xFrame, FrameListAnalyzer::E_ALL);
485 : :
486 : 0 : sal_Int32 c = aCheck.m_lModelFrames.getLength();
487 : 0 : sal_Int32 i = 0;
488 [ # # ]: 0 : for (i=0; i<c; ++i)
489 : : {
490 [ # # ][ # # ]: 0 : if (!fpf::closeIt(aCheck.m_lModelFrames[i], sal_False))
[ # # ]
491 : 0 : return sal_False;
492 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
[ # # ][ # # ]
493 : : }
494 : :
495 : : // If allowed - inform user about modified documents or
496 : : // still running jobs (e.g. printing).
497 [ + - ]: 2 : if (bAllowSuspend)
498 : : {
499 [ + - ][ + - ]: 2 : css::uno::Reference< css::frame::XController > xController = xFrame->getController();
500 [ + - ]: 2 : if (xController.is()) // some views dont uses a controller .-( (e.g. the help window)
501 : : {
502 [ + - ][ + - ]: 2 : bControllerSuspended = xController->suspend(sal_True);
503 [ - + ]: 2 : if (! bControllerSuspended)
504 : 2 : return sal_False;
505 [ + - ]: 2 : }
506 : : }
507 : :
508 : : // dont remove the component realy by e.g. calling setComponent(null, null).
509 : : // It's enough to suspend the controller.
510 : : // If we close the frame later this controller doesnt show the same dialog again.
511 : 2 : return sal_True;
512 : : }
513 : :
514 : : //-----------------------------------------------
515 : 0 : sal_Bool CloseDispatcher::implts_closeFrame()
516 : : {
517 : : // SAFE -> ----------------------------------
518 [ # # ]: 0 : ReadGuard aReadLock(m_aLock);
519 [ # # ][ # # ]: 0 : css::uno::Reference< css::frame::XFrame > xFrame (m_xCloseFrame.get(), css::uno::UNO_QUERY);
520 [ # # ]: 0 : aReadLock.unlock();
521 : : // <- SAFE ----------------------------------
522 : :
523 : : // frame already dead ? => so it's closed ... it's closed ...
524 [ # # ]: 0 : if ( ! xFrame.is() )
525 : 0 : return sal_True;
526 : :
527 : : // dont deliver owner ship; our "UI user" will try it again if it failed.
528 : : // OK - he will get an empty frame then. But normaly an empty frame
529 : : // should be closeable always :-)
530 [ # # ][ # # ]: 0 : if (!fpf::closeIt(xFrame, sal_False))
531 : 0 : return sal_False;
532 : :
533 : : // SAFE -> ----------------------------------
534 [ # # ]: 0 : WriteGuard aWriteLock(m_aLock);
535 [ # # ][ # # ]: 0 : m_xCloseFrame = css::uno::WeakReference< css::frame::XFrame >();
[ # # ]
536 [ # # ]: 0 : aWriteLock.unlock();
537 : : // <- SAFE ----------------------------------
538 : :
539 [ # # ][ # # ]: 0 : return sal_True;
540 : : }
541 : :
542 : : //-----------------------------------------------
543 : 2 : sal_Bool CloseDispatcher::implts_establishBackingMode()
544 : : {
545 : : // SAFE -> ----------------------------------
546 [ + - ]: 2 : ReadGuard aReadLock(m_aLock);
547 : 2 : css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
548 [ + - ][ + - ]: 2 : css::uno::Reference< css::frame::XFrame > xFrame (m_xCloseFrame.get(), css::uno::UNO_QUERY);
549 [ + - ]: 2 : aReadLock.unlock();
550 : : // <- SAFE ----------------------------------
551 : :
552 [ - + ]: 2 : if (!xFrame.is())
553 : 0 : return sal_False;
554 : :
555 [ + - ]: 2 : css::uno::Reference < css::document::XActionLockable > xLock( xFrame, css::uno::UNO_QUERY );
556 [ + - ][ + - ]: 2 : if ( xLock.is() && xLock->isActionLocked() )
[ + - ][ - + ]
[ - + ]
557 : 0 : return sal_False;
558 : :
559 [ + - ][ + - ]: 2 : css::uno::Reference< css::awt::XWindow > xContainerWindow = xFrame->getContainerWindow();
560 [ + - ]: 2 : css::uno::Sequence< css::uno::Any > lArgs(1);
561 [ + - ][ + - ]: 2 : lArgs[0] <<= xContainerWindow;
562 : :
563 : : css::uno::Reference< css::frame::XController > xBackingComp(
564 [ + - ]: 2 : xSMGR->createInstanceWithArguments(SERVICENAME_STARTMODULE, lArgs),
565 [ + - ][ + - ]: 2 : css::uno::UNO_QUERY_THROW);
[ + - ]
566 : :
567 : : // Attention: You MUST(!) call setComponent() before you call attachFrame().
568 [ + - ]: 2 : css::uno::Reference< css::awt::XWindow > xBackingWin(xBackingComp, css::uno::UNO_QUERY);
569 [ + - ][ + - ]: 2 : xFrame->setComponent(xBackingWin, xBackingComp);
570 [ + - ][ + - ]: 2 : xBackingComp->attachFrame(xFrame);
571 [ + - ][ + - ]: 2 : xContainerWindow->setVisible(sal_True);
572 : :
573 [ + - ][ + - ]: 2 : return sal_True;
574 : : }
575 : :
576 : : //-----------------------------------------------
577 : 0 : sal_Bool CloseDispatcher::implts_terminateApplication()
578 : : {
579 : : // SAFE -> ----------------------------------
580 [ # # ]: 0 : ReadGuard aReadLock(m_aLock);
581 : 0 : css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
582 [ # # ]: 0 : aReadLock.unlock();
583 : : // <- SAFE ----------------------------------
584 : :
585 : : css::uno::Reference< css::frame::XDesktop > xDesktop(
586 [ # # ][ # # ]: 0 : xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY_THROW);
[ # # ][ # # ]
587 : :
588 [ # # ][ # # ]: 0 : return xDesktop->terminate();
[ # # ]
589 : : }
590 : :
591 : : //-----------------------------------------------
592 : 2 : void CloseDispatcher::implts_notifyResultListener(const css::uno::Reference< css::frame::XDispatchResultListener >& xListener,
593 : : sal_Int16 nState ,
594 : : const css::uno::Any& aResult )
595 : : {
596 [ - + ]: 2 : if (!xListener.is())
597 : 2 : return;
598 : :
599 : : css::frame::DispatchResultEvent aEvent(
600 : : css::uno::Reference< css::uno::XInterface >(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY),
601 : : nState,
602 [ # # ][ # # ]: 0 : aResult);
603 : :
604 [ # # ][ # # ]: 2 : xListener->dispatchFinished(aEvent);
[ # # ]
605 : : }
606 : :
607 : : //-----------------------------------------------
608 : 2 : css::uno::Reference< css::frame::XFrame > CloseDispatcher::static_impl_searchRightTargetFrame(const css::uno::Reference< css::frame::XFrame >& xFrame ,
609 : : const ::rtl::OUString& sTarget)
610 : : {
611 [ - + ]: 2 : if (sTarget.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("_self")))
612 : 0 : return xFrame;
613 : :
614 : : OSL_ENSURE(sTarget.isEmpty(), "CloseDispatch used for unexpected target. Magic things will happen now .-)");
615 : :
616 : 2 : css::uno::Reference< css::frame::XFrame > xTarget = xFrame;
617 : 0 : while(sal_True)
618 : : {
619 : : // a) top frames wil be closed
620 [ + - ][ + - ]: 2 : if (xTarget->isTop())
[ + - ]
621 : 2 : return xTarget;
622 : :
623 : : // b) even child frame containing top level windows (e.g. query designer of database) will be closed
624 [ # # ][ # # ]: 0 : css::uno::Reference< css::awt::XWindow > xWindow = xTarget->getContainerWindow();
625 [ # # ]: 0 : css::uno::Reference< css::awt::XTopWindow > xTopWindowCheck(xWindow, css::uno::UNO_QUERY);
626 [ # # ]: 0 : if (xTopWindowCheck.is())
627 : : {
628 : : // b1) Note: Toolkit interface XTopWindow sometimes is used by real VCL-child-windows also .-)
629 : : // Be sure that these window is realy a "top system window".
630 : : // Attention ! Checking Window->GetParent() isnt the right approach here.
631 : : // Because sometimes VCL create "implicit border windows" as parents even we created
632 : : // a simple XWindow using the toolkit only .-(
633 [ # # ]: 0 : SolarMutexGuard aSolarLock;
634 [ # # ]: 0 : Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
635 [ # # ][ # # ]: 0 : if (
[ # # ]
636 : : (pWindow ) &&
637 [ # # ]: 0 : (pWindow->IsSystemWindow())
638 : : )
639 [ # # ][ # # ]: 0 : return xTarget;
640 : : }
641 : :
642 : : // c) try to find better results on parent frame
643 : : // If no parent frame exists (because this frame is used outside the desktop tree)
644 : : // the given frame must be used directly.
645 [ # # ][ # # ]: 0 : css::uno::Reference< css::frame::XFrame > xParent(xTarget->getCreator(), css::uno::UNO_QUERY);
[ # # ]
646 [ # # ]: 0 : if ( ! xParent.is())
647 : 0 : return xTarget;
648 : :
649 : : // c1) check parent frame inside next loop ...
650 [ # # ][ # # ]: 0 : xTarget = xParent;
651 [ # # ][ # # ]: 2 : }
652 : : }
653 : :
654 : : } // namespace framework
655 : :
656 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|