LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/framework/source/dispatch - closedispatcher.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 134 214 62.6 %
Date: 2013-07-09 Functions: 17 24 70.8 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10