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

Generated by: LCOV version 1.11