LCOV - code coverage report
Current view: top level - libreoffice/framework/source/dispatch - closedispatcher.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 211 0.0 %
Date: 2012-12-27 Functions: 0 22 0.0 %
Legend: Lines: hit not hit

          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: */

Generated by: LCOV version 1.10