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