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