LCOV - code coverage report
Current view: top level - framework/source/dispatch - closedispatcher.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 115 211 54.5 %
Date: 2012-08-25 Functions: 14 22 63.6 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 132 502 26.3 %

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

Generated by: LCOV version 1.10