xpfe/appshell/src/nsAppShellWindowEnumerator.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:e65cf8cc6e3f
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "nsAppShellWindowEnumerator.h"
7
8 #include "nsIContentViewer.h"
9 #include "nsIDocShell.h"
10 #include "nsIDocument.h"
11 #include "nsIDOMDocument.h"
12 #include "nsIDOMElement.h"
13 #include "nsIDOMWindow.h"
14 #include "nsIFactory.h"
15 #include "nsIInterfaceRequestor.h"
16 #include "nsIInterfaceRequestorUtils.h"
17 #include "nsIXULWindow.h"
18
19 #include "nsWindowMediator.h"
20
21 //
22 // static helper functions
23 //
24
25 static nsCOMPtr<nsIDOMNode> GetDOMNodeFromDocShell(nsIDocShell *aShell);
26 static void GetAttribute(nsIXULWindow *inWindow, const nsAString &inAttribute,
27 nsAString &outValue);
28 static void GetWindowType(nsIXULWindow* inWindow, nsString &outType);
29
30 nsCOMPtr<nsIDOMNode> GetDOMNodeFromDocShell(nsIDocShell *aShell)
31 {
32 nsCOMPtr<nsIDOMNode> node;
33
34 nsCOMPtr<nsIContentViewer> cv;
35 aShell->GetContentViewer(getter_AddRefs(cv));
36 if (cv) {
37 nsCOMPtr<nsIDOMDocument> domdoc(do_QueryInterface(cv->GetDocument()));
38 if (domdoc) {
39 nsCOMPtr<nsIDOMElement> element;
40 domdoc->GetDocumentElement(getter_AddRefs(element));
41 if (element)
42 node = element;
43 }
44 }
45
46 return node;
47 }
48
49 // generic "retrieve the value of a XUL attribute" function
50 void GetAttribute(nsIXULWindow *inWindow, const nsAString &inAttribute,
51 nsAString &outValue)
52 {
53 nsCOMPtr<nsIDocShell> shell;
54 if (inWindow && NS_SUCCEEDED(inWindow->GetDocShell(getter_AddRefs(shell)))) {
55 nsCOMPtr<nsIDOMNode> node(GetDOMNodeFromDocShell(shell));
56 if (node) {
57 nsCOMPtr<nsIDOMElement> webshellElement(do_QueryInterface(node));
58 if (webshellElement)
59 webshellElement->GetAttribute(inAttribute, outValue);
60 }
61 }
62 }
63
64 // retrieve the window type, stored as the value of a particular
65 // attribute in its XUL window tag
66 void GetWindowType(nsIXULWindow* aWindow, nsString &outType)
67 {
68 GetAttribute(aWindow, NS_LITERAL_STRING("windowtype"), outType);
69 }
70
71 //
72 // nsWindowInfo
73 //
74
75 nsWindowInfo::nsWindowInfo(nsIXULWindow* inWindow, int32_t inTimeStamp) :
76 mWindow(inWindow),mTimeStamp(inTimeStamp),mZLevel(nsIXULWindow::normalZ)
77 {
78 ReferenceSelf(true, true);
79 }
80
81 nsWindowInfo::~nsWindowInfo()
82 {
83 }
84
85 // return true if the window described by this WindowInfo has a type
86 // equal to the given type
87 bool nsWindowInfo::TypeEquals(const nsAString &aType)
88 {
89 nsAutoString rtnString;
90 GetWindowType(mWindow, rtnString);
91 return rtnString == aType;
92 }
93
94 // insert the struct into their two linked lists, in position after the
95 // given (independent) method arguments
96 void nsWindowInfo::InsertAfter(nsWindowInfo *inOlder , nsWindowInfo *inHigher)
97 {
98 if (inOlder) {
99 mOlder = inOlder;
100 mYounger = inOlder->mYounger;
101 mOlder->mYounger = this;
102 if (mOlder->mOlder == mOlder)
103 mOlder->mOlder = this;
104 mYounger->mOlder = this;
105 if (mYounger->mYounger == mYounger)
106 mYounger->mYounger = this;
107 }
108 if (inHigher) {
109 mHigher = inHigher;
110 mLower = inHigher->mLower;
111 mHigher->mLower = this;
112 if (mHigher->mHigher == mHigher)
113 mHigher->mHigher = this;
114 mLower->mHigher = this;
115 if (mLower->mLower == mLower)
116 mLower->mLower = this;
117 }
118 }
119
120 // remove the struct from its linked lists
121 void nsWindowInfo::Unlink(bool inAge, bool inZ)
122 {
123 if (inAge) {
124 mOlder->mYounger = mYounger;
125 mYounger->mOlder = mOlder;
126 }
127 if (inZ) {
128 mLower->mHigher = mHigher;
129 mHigher->mLower = mLower;
130 }
131 ReferenceSelf(inAge, inZ);
132 }
133
134 // initialize the struct to be a valid linked list of one element
135 void nsWindowInfo::ReferenceSelf(bool inAge, bool inZ)
136 {
137 if (inAge) {
138 mYounger = this;
139 mOlder = this;
140 }
141 if (inZ) {
142 mLower = this;
143 mHigher = this;
144 }
145 }
146
147 //
148 // nsAppShellWindowEnumerator
149 //
150
151 NS_IMPL_ISUPPORTS(nsAppShellWindowEnumerator, nsISimpleEnumerator)
152
153 nsAppShellWindowEnumerator::nsAppShellWindowEnumerator(
154 const char16_t* aTypeString,
155 nsWindowMediator& aMediator) :
156 mWindowMediator(&aMediator), mType(aTypeString), mCurrentPosition(nullptr)
157 {
158 mWindowMediator->AddEnumerator(this);
159 NS_ADDREF(mWindowMediator);
160 }
161
162 nsAppShellWindowEnumerator::~nsAppShellWindowEnumerator()
163 {
164 mWindowMediator->RemoveEnumerator(this);
165 NS_RELEASE(mWindowMediator);
166 }
167
168 // after mCurrentPosition has been initialized to point to the beginning
169 // of the appropriate list, adjust it if necessary
170 void nsAppShellWindowEnumerator::AdjustInitialPosition()
171 {
172 if (!mType.IsEmpty() && mCurrentPosition && !mCurrentPosition->TypeEquals(mType))
173 mCurrentPosition = FindNext();
174 }
175
176 NS_IMETHODIMP nsAppShellWindowEnumerator::HasMoreElements(bool *retval)
177 {
178 if (!retval)
179 return NS_ERROR_INVALID_ARG;
180
181 *retval = mCurrentPosition ? true : false;
182 return NS_OK;
183 }
184
185 // if a window is being removed adjust the iterator's current position
186 void nsAppShellWindowEnumerator::WindowRemoved(nsWindowInfo *inInfo)
187 {
188 if (mCurrentPosition == inInfo)
189 mCurrentPosition = FindNext();
190 }
191
192 //
193 // nsASDOMWindowEnumerator
194 //
195
196 nsASDOMWindowEnumerator::nsASDOMWindowEnumerator(
197 const char16_t* aTypeString,
198 nsWindowMediator& aMediator) :
199 nsAppShellWindowEnumerator(aTypeString, aMediator)
200 {
201 }
202
203 nsASDOMWindowEnumerator::~nsASDOMWindowEnumerator()
204 {
205 }
206
207 NS_IMETHODIMP nsASDOMWindowEnumerator::GetNext(nsISupports **retval)
208 {
209 if (!retval)
210 return NS_ERROR_INVALID_ARG;
211
212 *retval = nullptr;
213 while (mCurrentPosition) {
214 nsCOMPtr<nsIDOMWindow> domWindow;
215 nsWindowMediator::GetDOMWindow(mCurrentPosition->mWindow, domWindow);
216 mCurrentPosition = FindNext();
217 if (domWindow)
218 return CallQueryInterface(domWindow, retval);
219 }
220 return NS_OK;
221 }
222
223 //
224 // nsASXULWindowEnumerator
225 //
226
227 nsASXULWindowEnumerator::nsASXULWindowEnumerator(
228 const char16_t* aTypeString,
229 nsWindowMediator& aMediator) :
230 nsAppShellWindowEnumerator(aTypeString, aMediator)
231 {
232 }
233
234 nsASXULWindowEnumerator::~nsASXULWindowEnumerator()
235 {
236 }
237
238 NS_IMETHODIMP nsASXULWindowEnumerator::GetNext(nsISupports **retval)
239 {
240 if (!retval)
241 return NS_ERROR_INVALID_ARG;
242
243 *retval = nullptr;
244 if (mCurrentPosition) {
245 CallQueryInterface(mCurrentPosition->mWindow, retval);
246 mCurrentPosition = FindNext();
247 }
248 return NS_OK;
249 }
250
251 //
252 // nsASDOMWindowEarlyToLateEnumerator
253 //
254
255 nsASDOMWindowEarlyToLateEnumerator::nsASDOMWindowEarlyToLateEnumerator(
256 const char16_t *aTypeString,
257 nsWindowMediator &aMediator) :
258 nsASDOMWindowEnumerator(aTypeString, aMediator)
259 {
260 mCurrentPosition = aMediator.mOldestWindow;
261 AdjustInitialPosition();
262 }
263
264 nsASDOMWindowEarlyToLateEnumerator::~nsASDOMWindowEarlyToLateEnumerator()
265 {
266 }
267
268 nsWindowInfo *nsASDOMWindowEarlyToLateEnumerator::FindNext()
269 {
270 nsWindowInfo *info,
271 *listEnd;
272 bool allWindows = mType.IsEmpty();
273
274 // see nsXULWindowEarlyToLateEnumerator::FindNext
275 if (!mCurrentPosition)
276 return nullptr;
277
278 info = mCurrentPosition->mYounger;
279 listEnd = mWindowMediator->mOldestWindow;
280
281 while (info != listEnd) {
282 if (allWindows || info->TypeEquals(mType))
283 return info;
284 info = info->mYounger;
285 }
286
287 return nullptr;
288 }
289
290 //
291 // nsASXULWindowEarlyToLateEnumerator
292 //
293
294 nsASXULWindowEarlyToLateEnumerator::nsASXULWindowEarlyToLateEnumerator(
295 const char16_t *aTypeString,
296 nsWindowMediator &aMediator) :
297 nsASXULWindowEnumerator(aTypeString, aMediator)
298 {
299 mCurrentPosition = aMediator.mOldestWindow;
300 AdjustInitialPosition();
301 }
302
303 nsASXULWindowEarlyToLateEnumerator::~nsASXULWindowEarlyToLateEnumerator()
304 {
305 }
306
307 nsWindowInfo *nsASXULWindowEarlyToLateEnumerator::FindNext()
308 {
309 nsWindowInfo *info,
310 *listEnd;
311 bool allWindows = mType.IsEmpty();
312
313 /* mCurrentPosition null is assumed to mean that the enumerator has run
314 its course and is now basically useless. It could also be interpreted
315 to mean that it was created at a time when there were no windows. In
316 that case it would probably be more appropriate to check to see whether
317 windows have subsequently been added. But it's not guaranteed that we'll
318 pick up newly added windows anyway (if they occurred previous to our
319 current position) so we just don't worry about that. */
320 if (!mCurrentPosition)
321 return nullptr;
322
323 info = mCurrentPosition->mYounger;
324 listEnd = mWindowMediator->mOldestWindow;
325
326 while (info != listEnd) {
327 if (allWindows || info->TypeEquals(mType))
328 return info;
329 info = info->mYounger;
330 }
331
332 return nullptr;
333 }
334
335 //
336 // nsASDOMWindowFrontToBackEnumerator
337 //
338
339 nsASDOMWindowFrontToBackEnumerator::nsASDOMWindowFrontToBackEnumerator(
340 const char16_t *aTypeString,
341 nsWindowMediator &aMediator) :
342 nsASDOMWindowEnumerator(aTypeString, aMediator)
343 {
344 mCurrentPosition = aMediator.mTopmostWindow;
345 AdjustInitialPosition();
346 }
347
348 nsASDOMWindowFrontToBackEnumerator::~nsASDOMWindowFrontToBackEnumerator()
349 {
350 }
351
352 nsWindowInfo *nsASDOMWindowFrontToBackEnumerator::FindNext()
353 {
354 nsWindowInfo *info,
355 *listEnd;
356 bool allWindows = mType.IsEmpty();
357
358 // see nsXULWindowEarlyToLateEnumerator::FindNext
359 if (!mCurrentPosition)
360 return nullptr;
361
362 info = mCurrentPosition->mLower;
363 listEnd = mWindowMediator->mTopmostWindow;
364
365 while (info != listEnd) {
366 if (allWindows || info->TypeEquals(mType))
367 return info;
368 info = info->mLower;
369 }
370
371 return nullptr;
372 }
373
374 //
375 // nsASXULWindowFrontToBackEnumerator
376 //
377
378 nsASXULWindowFrontToBackEnumerator::nsASXULWindowFrontToBackEnumerator(
379 const char16_t *aTypeString,
380 nsWindowMediator &aMediator) :
381 nsASXULWindowEnumerator(aTypeString, aMediator)
382 {
383 mCurrentPosition = aMediator.mTopmostWindow;
384 AdjustInitialPosition();
385 }
386
387 nsASXULWindowFrontToBackEnumerator::~nsASXULWindowFrontToBackEnumerator()
388 {
389 }
390
391 nsWindowInfo *nsASXULWindowFrontToBackEnumerator::FindNext()
392 {
393 nsWindowInfo *info,
394 *listEnd;
395 bool allWindows = mType.IsEmpty();
396
397 // see nsXULWindowEarlyToLateEnumerator::FindNext
398 if (!mCurrentPosition)
399 return nullptr;
400
401 info = mCurrentPosition->mLower;
402 listEnd = mWindowMediator->mTopmostWindow;
403
404 while (info != listEnd) {
405 if (allWindows || info->TypeEquals(mType))
406 return info;
407 info = info->mLower;
408 }
409
410 return nullptr;
411 }
412
413 //
414 // nsASDOMWindowBackToFrontEnumerator
415 //
416
417 nsASDOMWindowBackToFrontEnumerator::nsASDOMWindowBackToFrontEnumerator(
418 const char16_t *aTypeString,
419 nsWindowMediator &aMediator) :
420 nsASDOMWindowEnumerator(aTypeString, aMediator)
421 {
422 mCurrentPosition = aMediator.mTopmostWindow ?
423 aMediator.mTopmostWindow->mHigher : nullptr;
424 AdjustInitialPosition();
425 }
426
427 nsASDOMWindowBackToFrontEnumerator::~nsASDOMWindowBackToFrontEnumerator()
428 {
429 }
430
431 nsWindowInfo *nsASDOMWindowBackToFrontEnumerator::FindNext()
432 {
433 nsWindowInfo *info,
434 *listEnd;
435 bool allWindows = mType.IsEmpty();
436
437 // see nsXULWindowEarlyToLateEnumerator::FindNext
438 if (!mCurrentPosition)
439 return nullptr;
440
441 info = mCurrentPosition->mHigher;
442 listEnd = mWindowMediator->mTopmostWindow;
443 if (listEnd)
444 listEnd = listEnd->mHigher;
445
446 while (info != listEnd) {
447 if (allWindows || info->TypeEquals(mType))
448 return info;
449 info = info->mHigher;
450 }
451
452 return nullptr;
453 }
454
455 //
456 // nsASXULWindowBackToFrontEnumerator
457 //
458
459 nsASXULWindowBackToFrontEnumerator::nsASXULWindowBackToFrontEnumerator(
460 const char16_t *aTypeString,
461 nsWindowMediator &aMediator) :
462 nsASXULWindowEnumerator(aTypeString, aMediator)
463 {
464 mCurrentPosition = aMediator.mTopmostWindow ?
465 aMediator.mTopmostWindow->mHigher : nullptr;
466 AdjustInitialPosition();
467 }
468
469 nsASXULWindowBackToFrontEnumerator::~nsASXULWindowBackToFrontEnumerator()
470 {
471 }
472
473 nsWindowInfo *nsASXULWindowBackToFrontEnumerator::FindNext()
474 {
475 nsWindowInfo *info,
476 *listEnd;
477 bool allWindows = mType.IsEmpty();
478
479 // see nsXULWindowEarlyToLateEnumerator::FindNext
480 if (!mCurrentPosition)
481 return nullptr;
482
483 info = mCurrentPosition->mHigher;
484 listEnd = mWindowMediator->mTopmostWindow;
485 if (listEnd)
486 listEnd = listEnd->mHigher;
487
488 while (info != listEnd) {
489 if (allWindows || info->TypeEquals(mType))
490 return info;
491 info = info->mHigher;
492 }
493
494 return nullptr;
495 }

mercurial