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

Generated by: LCOV version 1.10