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 "framework/framelistanalyzer.hxx"
21 :
22 : #include <threadhelp/writeguard.hxx>
23 : #include <threadhelp/readguard.hxx>
24 : #include <targets.h>
25 : #include <properties.h>
26 : #include <services.h>
27 :
28 : #include <com/sun/star/beans/XPropertySet.hpp>
29 : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
30 : #include <com/sun/star/frame/ModuleManager.hpp>
31 :
32 : #include <comphelper/processfactory.hxx>
33 : #include <vcl/svapp.hxx>
34 : #include <tools/diagnose_ex.h>
35 :
36 : namespace framework{
37 :
38 : /**
39 : */
40 :
41 1074 : FrameListAnalyzer::FrameListAnalyzer( const css::uno::Reference< css::frame::XFramesSupplier >& xSupplier ,
42 : const css::uno::Reference< css::frame::XFrame >& xReferenceFrame ,
43 : sal_uInt32 eDetectMode )
44 : : m_xSupplier (xSupplier )
45 : , m_xReferenceFrame(xReferenceFrame)
46 1074 : , m_eDetectMode (eDetectMode )
47 : {
48 1074 : impl_analyze();
49 1074 : }
50 :
51 : /**
52 : */
53 :
54 1074 : FrameListAnalyzer::~FrameListAnalyzer()
55 : {
56 1074 : }
57 :
58 : /** returns an analyzed list of all currently opened (top!) frames inside the desktop tree.
59 :
60 : We try to get a snapshot of all opened frames, which are part of the desktop frame container.
61 : Of course we can't access frames, which stands outside of this tree.
62 : But it's neccessary to collect top frames here only. Otherwhise we interpret closing of last
63 : frame wrong. Further we analyze this list and split into different parts.
64 : E.g. for "CloseDoc" we must know, which frames of the given list referr to the same model.
65 : These frames must be closed then. But all other frames must be untouched.
66 : In case the request was "CloseWin" these splitted lists can be used too, to decide if the last window
67 : or document was closed. Then we have to initialize the backing window ...
68 : Last but not least we must know something about our special help frame. It must be handled
69 : seperatly. And last but not least - the backing component frame must be detected too.
70 : */
71 :
72 1074 : void FrameListAnalyzer::impl_analyze()
73 : {
74 : // reset all members to get a consistent state
75 1074 : m_bReferenceIsHidden = sal_False;
76 1074 : m_bReferenceIsHelp = sal_False;
77 1074 : m_bReferenceIsBacking = sal_False;
78 1074 : m_xHelp = css::uno::Reference< css::frame::XFrame >();
79 1074 : m_xBackingComponent = css::uno::Reference< css::frame::XFrame >();
80 :
81 : // try to get the task container by using the given supplier
82 1074 : css::uno::Reference< css::container::XIndexAccess > xFrameContainer(m_xSupplier->getFrames(), css::uno::UNO_QUERY);
83 :
84 : // All return list get an initial size to include all possible frames.
85 : // They will be packed at the end of this method ... using the actual step positions then.
86 1074 : sal_Int32 nVisibleStep = 0;
87 1074 : sal_Int32 nHiddenStep = 0;
88 1074 : sal_Int32 nModelStep = 0;
89 1074 : sal_Int32 nCount = xFrameContainer->getCount();
90 :
91 1074 : m_lOtherVisibleFrames.realloc(nCount);
92 1074 : m_lOtherHiddenFrames.realloc(nCount);
93 1074 : m_lModelFrames.realloc(nCount);
94 :
95 : // ask for the model of the given reference frame.
96 : // It must be compared with the model of every frame of the container
97 : // to sort it into the list of frames with the same model.
98 : // Supress this step, if right detect mode isn't set.
99 1074 : css::uno::Reference< css::frame::XModel > xReferenceModel;
100 1074 : if ((m_eDetectMode & E_MODEL) == E_MODEL )
101 : {
102 0 : css::uno::Reference< css::frame::XController > xReferenceController;
103 0 : if (m_xReferenceFrame.is())
104 0 : xReferenceController = m_xReferenceFrame->getController();
105 0 : if (xReferenceController.is())
106 0 : xReferenceModel = xReferenceController->getModel();
107 : }
108 :
109 : // check, if the reference frame is in hidden mode.
110 : // But look, if this analyze step is realy needed.
111 1074 : css::uno::Reference< css::beans::XPropertySet > xSet(m_xReferenceFrame, css::uno::UNO_QUERY);
112 1912 : if (
113 : ((m_eDetectMode & E_HIDDEN) == E_HIDDEN) &&
114 838 : (xSet.is() )
115 : )
116 : {
117 838 : xSet->getPropertyValue(FRAME_PROPNAME_ISHIDDEN) >>= m_bReferenceIsHidden;
118 : }
119 :
120 : // check, if the reference frame includes the backing component.
121 : // But look, if this analyze step is realy needed.
122 1074 : if (((m_eDetectMode & E_BACKINGCOMPONENT) == E_BACKINGCOMPONENT) && m_xReferenceFrame.is() )
123 : {
124 : try
125 : {
126 838 : css::uno::Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
127 838 : css::uno::Reference< css::frame::XModuleManager2 > xModuleMgr = css::frame::ModuleManager::create(xContext);
128 838 : ::rtl::OUString sModule = xModuleMgr->identify(m_xReferenceFrame);
129 428 : m_bReferenceIsBacking = sModule.equals(SERVICENAME_STARTMODULE);
130 : }
131 410 : catch(const css::frame::UnknownModuleException&)
132 : {
133 : }
134 0 : catch(const css::uno::Exception&)
135 : {
136 : DBG_UNHANDLED_EXCEPTION();
137 : }
138 : }
139 :
140 : // check, if the reference frame includes the help module.
141 : // But look, if this analyze step is realy needed.
142 5500 : if (
143 : ((m_eDetectMode & E_HELP) == E_HELP ) &&
144 838 : (m_xReferenceFrame.is() ) &&
145 3588 : (m_xReferenceFrame->getName() == SPECIALTARGET_HELPTASK)
146 : )
147 : {
148 0 : m_bReferenceIsHelp = sal_True;
149 : }
150 :
151 : try
152 : {
153 : // Step over all frames of the desktop frame container and analyze it.
154 22226 : for (sal_Int32 i=0; i<nCount; ++i)
155 : {
156 : // Ignore invalid items ... and of course the reference frame.
157 : // It will be a member of the given frame list too - but it was already
158 : // analyzed before!
159 21152 : css::uno::Reference< css::frame::XFrame > xFrame;
160 126912 : if (
161 63456 : !(xFrameContainer->getByIndex(i) >>= xFrame) ||
162 21152 : !(xFrame.is() ) ||
163 21152 : (xFrame==m_xReferenceFrame )
164 : )
165 838 : continue;
166 :
167 : #ifdef ENABLE_WARNINGS
168 : if (
169 : ((m_eDetectMode & E_ZOMBIE) == E_ZOMBIE) &&
170 : (
171 : (!xFrame->getContainerWindow().is()) ||
172 : (!xFrame->getComponentWindow().is())
173 : )
174 : )
175 : {
176 : LOG_WARNING("FrameListAnalyzer::impl_analyze()", "ZOMBIE!")
177 : }
178 : #endif
179 :
180 : // -------------------------------------------------
181 : // a) Is it the special help task?
182 : // Return it seperated from any return list.
183 87623 : if (
184 : ((m_eDetectMode & E_HELP) == E_HELP ) &&
185 67309 : (xFrame->getName()==SPECIALTARGET_HELPTASK)
186 : )
187 : {
188 0 : m_xHelp = xFrame;
189 0 : continue;
190 : }
191 :
192 : // -------------------------------------------------
193 : // b) Or is includes this task the special backing component?
194 : // Return it seperated from any return list.
195 : // But check if the reference task itself is the backing frame.
196 : // Our user mst know it to decide right.
197 20314 : if ((m_eDetectMode & E_BACKINGCOMPONENT) == E_BACKINGCOMPONENT)
198 : {
199 : try
200 : {
201 20314 : css::uno::Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
202 20314 : css::uno::Reference< css::frame::XModuleManager2 > xModuleMgr = css::frame::ModuleManager::create(xContext);
203 20314 : ::rtl::OUString sModule = xModuleMgr->identify(xFrame);
204 20314 : if (sModule.equals(SERVICENAME_STARTMODULE))
205 : {
206 0 : m_xBackingComponent = xFrame;
207 0 : continue;
208 20314 : }
209 : }
210 0 : catch (const css::uno::Exception&)
211 : {
212 : }
213 : }
214 :
215 : // -------------------------------------------------
216 : // c) Or is it the a task, which uses the specified model?
217 : // Add it to the list of "model frames".
218 20314 : if ((m_eDetectMode & E_MODEL) == E_MODEL)
219 : {
220 0 : css::uno::Reference< css::frame::XController > xController = xFrame->getController();
221 0 : css::uno::Reference< css::frame::XModel > xModel ;
222 0 : if (xController.is())
223 0 : xModel = xController->getModel();
224 0 : if (xModel==xReferenceModel)
225 : {
226 0 : m_lModelFrames[nModelStep] = xFrame;
227 0 : ++nModelStep;
228 0 : continue;
229 0 : }
230 : }
231 :
232 : // -------------------------------------------------
233 : // d) Or is it the a task, which use another or no model at all?
234 : // Add it to the list of "other frames". But look for it's
235 : // visible state ... if it's allowed to do so.
236 : // -------------------------------------------------
237 20314 : sal_Bool bHidden = sal_False;
238 20314 : if ((m_eDetectMode & E_HIDDEN) == E_HIDDEN )
239 : {
240 15665 : xSet = css::uno::Reference< css::beans::XPropertySet >(xFrame, css::uno::UNO_QUERY);
241 15665 : if (xSet.is())
242 : {
243 15665 : xSet->getPropertyValue(FRAME_PROPNAME_ISHIDDEN) >>= bHidden;
244 : }
245 : }
246 :
247 20314 : if (bHidden)
248 : {
249 6 : m_lOtherHiddenFrames[nHiddenStep] = xFrame;
250 6 : ++nHiddenStep;
251 : }
252 : else
253 : {
254 20308 : m_lOtherVisibleFrames[nVisibleStep] = xFrame;
255 20308 : ++nVisibleStep;
256 : }
257 21152 : }
258 : }
259 0 : catch (const css::lang::IndexOutOfBoundsException&)
260 : {
261 : // stop copying if index seams to be wrong.
262 : // This interface can't realy guarantee its count for multithreaded
263 : // environments. So it can occure!
264 : }
265 :
266 : // Pack both lists by using the actual step positions.
267 : // All empty or ignorable items should exist at the end of these lists
268 : // behind the position pointers. So they will be removed by a reallocation.
269 1074 : m_lOtherVisibleFrames.realloc(nVisibleStep);
270 1074 : m_lOtherHiddenFrames.realloc(nHiddenStep);
271 1074 : m_lModelFrames.realloc(nModelStep);
272 1074 : }
273 :
274 : } // namespace framework
275 :
276 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|