1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_framework.hxx"
26
27 #include "framework/framelistanalyzer.hxx"
28
29 //_______________________________________________
30 // my own includes
31 #include <threadhelp/writeguard.hxx>
32 #include <threadhelp/readguard.hxx>
33 #include <targets.h>
34 #include <properties.h>
35 #include <services.h>
36
37 //_______________________________________________
38 // interface includes
39 #include <com/sun/star/beans/XPropertySet.hpp>
40 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
41 #include <com/sun/star/frame/XModuleManager.hpp>
42
43 //_______________________________________________
44 // includes of other projects
45 #include <unotools/processfactory.hxx>
46 #include <vcl/svapp.hxx>
47 #include <tools/diagnose_ex.h>
48
49 //_______________________________________________
50 // namespace
51
52 namespace framework{
53
54 //_______________________________________________
55 // non exported const
56
57 //_______________________________________________
58 // non exported definitions
59
60 //_______________________________________________
61 // declarations
62
63 //_______________________________________________
64
65 /**
66 */
67
FrameListAnalyzer(const css::uno::Reference<css::frame::XFramesSupplier> & xSupplier,const css::uno::Reference<css::frame::XFrame> & xReferenceFrame,sal_uInt32 eDetectMode)68 FrameListAnalyzer::FrameListAnalyzer( const css::uno::Reference< css::frame::XFramesSupplier >& xSupplier ,
69 const css::uno::Reference< css::frame::XFrame >& xReferenceFrame ,
70 sal_uInt32 eDetectMode )
71 : m_xSupplier (xSupplier )
72 , m_xReferenceFrame(xReferenceFrame)
73 , m_eDetectMode (eDetectMode )
74 {
75 impl_analyze();
76 }
77
78 //_______________________________________________
79
80 /**
81 */
82
~FrameListAnalyzer()83 FrameListAnalyzer::~FrameListAnalyzer()
84 {
85 }
86
87 //_______________________________________________
88
89 /** returns an analyzed list of all currently opened (top!) frames inside the desktop tree.
90
91 We try to get a snapshot of all opened frames, which are part of the desktop frame container.
92 Of course we can't access frames, which stands outside of this tree.
93 But it's necessary to collect top frames here only. Otherwise we interpret closing of last
94 frame wrong. Further we analyze this list and split into different parts.
95 E.g. for "CloseDoc" we must know, which frames of the given list referr to the same model.
96 These frames must be closed then. But all other frames must be untouched.
97 In case the request was "CloseWin" these splitted lists can be used too, to decide if the last window
98 or document was closed. Then we have to initialize the backing window ...
99 Last but not least we must know something about our special help frame. It must be handled
100 seperatly. And last but not least - the backing component frame must be detected too.
101 */
102
impl_analyze()103 void FrameListAnalyzer::impl_analyze()
104 {
105 // reset all members to get a consistent state
106 m_bReferenceIsHidden = sal_False;
107 m_bReferenceIsHelp = sal_False;
108 m_bReferenceIsBacking = sal_False;
109 m_xHelp = css::uno::Reference< css::frame::XFrame >();
110 m_xBackingComponent = css::uno::Reference< css::frame::XFrame >();
111
112 // try to get the task container by using the given supplier
113 css::uno::Reference< css::container::XIndexAccess > xFrameContainer(m_xSupplier->getFrames(), css::uno::UNO_QUERY);
114
115 // All return list get an initial size to include all possible frames.
116 // They will be packed at the end of this method ... using the actual step positions then.
117 sal_Int32 nVisibleStep = 0;
118 sal_Int32 nHiddenStep = 0;
119 sal_Int32 nModelStep = 0;
120 sal_Int32 nCount = xFrameContainer->getCount();
121
122 m_lOtherVisibleFrames.realloc(nCount);
123 m_lOtherHiddenFrames.realloc(nCount);
124 m_lModelFrames.realloc(nCount);
125
126 // ask for the model of the given reference frame.
127 // It must be compared with the model of every frame of the container
128 // to sort it into the list of frames with the same model.
129 // Suppress this step, if right detect mode isn't set.
130 css::uno::Reference< css::frame::XModel > xReferenceModel;
131 if ((m_eDetectMode & E_MODEL) == E_MODEL )
132 {
133 css::uno::Reference< css::frame::XController > xReferenceController;
134 if (m_xReferenceFrame.is())
135 xReferenceController = m_xReferenceFrame->getController();
136 if (xReferenceController.is())
137 xReferenceModel = xReferenceController->getModel();
138 }
139
140 // check, if the reference frame is in hidden mode.
141 // But look, if this analyze step is really needed.
142 css::uno::Reference< css::beans::XPropertySet > xSet(m_xReferenceFrame, css::uno::UNO_QUERY);
143 if (
144 ((m_eDetectMode & E_HIDDEN) == E_HIDDEN) &&
145 (xSet.is() )
146 )
147 {
148 xSet->getPropertyValue(FRAME_PROPNAME_ISHIDDEN) >>= m_bReferenceIsHidden;
149 }
150
151 // check, if the reference frame includes the backing component.
152 // But look, if this analyze step is really needed.
153 if (((m_eDetectMode & E_BACKINGCOMPONENT) == E_BACKINGCOMPONENT) && m_xReferenceFrame.is() )
154 {
155 try
156 {
157 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::utl::getProcessServiceFactory();
158 css::uno::Reference< css::frame::XModuleManager > xModuleMgr(xSMGR->createInstance(SERVICENAME_MODULEMANAGER), css::uno::UNO_QUERY_THROW);
159 ::rtl::OUString sModule = xModuleMgr->identify(m_xReferenceFrame);
160 m_bReferenceIsBacking = (sModule.equals(SERVICENAME_STARTMODULE));
161 }
162 catch(const css::frame::UnknownModuleException&)
163 {
164 }
165 catch(const css::uno::Exception&)
166 {
167 DBG_UNHANDLED_EXCEPTION();
168 }
169 }
170
171 // check, if the reference frame includes the help module.
172 // But look, if this analyze step is really needed.
173 if (
174 ((m_eDetectMode & E_HELP) == E_HELP ) &&
175 (m_xReferenceFrame.is() ) &&
176 (m_xReferenceFrame->getName() == SPECIALTARGET_HELPTASK)
177 )
178 {
179 m_bReferenceIsHelp = sal_True;
180 }
181
182 try
183 {
184 // Step over all frames of the desktop frame container and analyze it.
185 for (sal_Int32 i=0; i<nCount; ++i)
186 {
187 // Ignore invalid items ... and of course the reference frame.
188 // It will be a member of the given frame list too - but it was already
189 // analyzed before!
190 css::uno::Reference< css::frame::XFrame > xFrame;
191 if (
192 !(xFrameContainer->getByIndex(i) >>= xFrame) ||
193 !(xFrame.is() ) ||
194 (xFrame==m_xReferenceFrame )
195 )
196 continue;
197
198 #ifdef ENABLE_WARNINGS
199 if (
200 ((m_eDetectMode & E_ZOMBIE) == E_ZOMBIE) &&
201 (
202 (!xFrame->getContainerWindow().is()) ||
203 (!xFrame->getComponentWindow().is())
204 )
205 )
206 {
207 LOG_WARNING("FrameListAnalyzer::impl_analyze()", "ZOMBIE!")
208 }
209 #endif
210
211 // -------------------------------------------------
212 // a) Is it the special help task?
213 // Return it separated from any return list.
214 if (
215 ((m_eDetectMode & E_HELP) == E_HELP ) &&
216 (xFrame->getName()==SPECIALTARGET_HELPTASK)
217 )
218 {
219 m_xHelp = xFrame;
220 continue;
221 }
222
223 // -------------------------------------------------
224 // b) Or is includes this task the special backing component?
225 // Return it separated from any return list.
226 // But check if the reference task itself is the backing frame.
227 // Our user mst know it to decide right.
228 if ((m_eDetectMode & E_BACKINGCOMPONENT) == E_BACKINGCOMPONENT)
229 {
230 try
231 {
232 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::utl::getProcessServiceFactory();
233 css::uno::Reference< css::frame::XModuleManager > xModuleMgr(xSMGR->createInstance(SERVICENAME_MODULEMANAGER), css::uno::UNO_QUERY);
234 ::rtl::OUString sModule = xModuleMgr->identify(xFrame);
235 if (sModule.equals(SERVICENAME_STARTMODULE))
236 {
237 m_xBackingComponent = xFrame;
238 continue;
239 }
240 }
241 catch(const css::uno::Exception&)
242 {}
243 }
244
245 // -------------------------------------------------
246 // c) Or is it the a task, which uses the specified model?
247 // Add it to the list of "model frames".
248 if ((m_eDetectMode & E_MODEL) == E_MODEL)
249 {
250 css::uno::Reference< css::frame::XController > xController = xFrame->getController();
251 css::uno::Reference< css::frame::XModel > xModel ;
252 if (xController.is())
253 xModel = xController->getModel();
254 if (xModel==xReferenceModel)
255 {
256 m_lModelFrames[nModelStep] = xFrame;
257 ++nModelStep;
258 continue;
259 }
260 }
261
262 // -------------------------------------------------
263 // d) Or is it the a task, which use another or no model at all?
264 // Add it to the list of "other frames". But look for it's
265 // visible state ... if it's allowed to do so.
266 // -------------------------------------------------
267 sal_Bool bHidden = sal_False;
268 if ((m_eDetectMode & E_HIDDEN) == E_HIDDEN )
269 {
270 xSet = css::uno::Reference< css::beans::XPropertySet >(xFrame, css::uno::UNO_QUERY);
271 if (xSet.is())
272 {
273 xSet->getPropertyValue(FRAME_PROPNAME_ISHIDDEN) >>= bHidden;
274 }
275 }
276
277 if (bHidden)
278 {
279 m_lOtherHiddenFrames[nHiddenStep] = xFrame;
280 ++nHiddenStep;
281 }
282 else
283 {
284 m_lOtherVisibleFrames[nVisibleStep] = xFrame;
285 ++nVisibleStep;
286 }
287 }
288 }
289 catch(css::lang::IndexOutOfBoundsException)
290 {
291 // stop copying if index seems to be wrong.
292 // This interface can't really guarantee its count for multithreaded
293 // environments. So it can occur!
294 }
295
296 // Pack both lists by using the actual step positions.
297 // All empty or ignorable items should exist at the end of these lists
298 // behind the position pointers. So they will be removed by a reallocation.
299 m_lOtherVisibleFrames.realloc(nVisibleStep);
300 m_lOtherHiddenFrames.realloc(nHiddenStep);
301 m_lModelFrames.realloc(nModelStep);
302 }
303
304 } // namespace framework
305