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