no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / xpfe / appshell / nsAppShellWindowEnumerator.cpp
blobd140f8a90f62c5bec23b57105bb226f934f1aa23
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/. */
6 #include "nsAppShellWindowEnumerator.h"
8 #include "nsIDocumentViewer.h"
9 #include "nsIDocShell.h"
10 #include "mozilla/dom/Document.h"
11 #include "nsIInterfaceRequestor.h"
12 #include "nsIInterfaceRequestorUtils.h"
13 #include "nsIAppWindow.h"
14 #include "mozilla/dom/Element.h"
16 #include "nsWindowMediator.h"
18 using mozilla::dom::Document;
19 using mozilla::dom::Element;
22 // static helper functions
25 static void GetAttribute(nsIAppWindow* inWindow, const nsAString& inAttribute,
26 nsAString& outValue);
27 static void GetWindowType(nsIAppWindow* inWindow, nsString& outType);
29 static Element* GetElementFromDocShell(nsIDocShell* aShell) {
30 nsCOMPtr<nsIDocumentViewer> viewer;
31 aShell->GetDocViewer(getter_AddRefs(viewer));
32 if (viewer) {
33 RefPtr<Document> doc = viewer->GetDocument();
34 if (doc) {
35 return doc->GetDocumentElement();
39 return nullptr;
42 // generic "retrieve the value of a XUL attribute" function
43 void GetAttribute(nsIAppWindow* inWindow, const nsAString& inAttribute,
44 nsAString& outValue) {
45 nsCOMPtr<nsIDocShell> shell;
46 if (inWindow && NS_SUCCEEDED(inWindow->GetDocShell(getter_AddRefs(shell)))) {
47 RefPtr<Element> webshellElement = GetElementFromDocShell(shell);
48 if (webshellElement) {
49 webshellElement->GetAttribute(inAttribute, outValue);
54 // retrieve the window type, stored as the value of a particular
55 // attribute in its XUL window tag
56 void GetWindowType(nsIAppWindow* aWindow, nsString& outType) {
57 GetAttribute(aWindow, u"windowtype"_ns, outType);
61 // nsWindowInfo
64 nsWindowInfo::nsWindowInfo(nsIAppWindow* inWindow, int32_t inTimeStamp)
65 : mWindow(inWindow),
66 mTimeStamp(inTimeStamp),
67 mZLevel(nsIAppWindow::normalZ) {
68 ReferenceSelf(true, true);
71 nsWindowInfo::~nsWindowInfo() {}
73 // return true if the window described by this WindowInfo has a type
74 // equal to the given type
75 bool nsWindowInfo::TypeEquals(const nsAString& aType) {
76 nsAutoString rtnString;
77 GetWindowType(mWindow, rtnString);
78 return rtnString == aType;
81 // insert the struct into their two linked lists, in position after the
82 // given (independent) method arguments
83 void nsWindowInfo::InsertAfter(nsWindowInfo* inOlder, nsWindowInfo* inHigher) {
84 if (inOlder) {
85 mOlder = inOlder;
86 mYounger = inOlder->mYounger;
87 mOlder->mYounger = this;
88 if (mOlder->mOlder == mOlder) mOlder->mOlder = this;
89 mYounger->mOlder = this;
90 if (mYounger->mYounger == mYounger) mYounger->mYounger = this;
92 if (inHigher) {
93 mHigher = inHigher;
94 mLower = inHigher->mLower;
95 mHigher->mLower = this;
96 if (mHigher->mHigher == mHigher) mHigher->mHigher = this;
97 mLower->mHigher = this;
98 if (mLower->mLower == mLower) mLower->mLower = this;
102 // remove the struct from its linked lists
103 void nsWindowInfo::Unlink(bool inAge, bool inZ) {
104 if (inAge) {
105 mOlder->mYounger = mYounger;
106 mYounger->mOlder = mOlder;
108 if (inZ) {
109 mLower->mHigher = mHigher;
110 mHigher->mLower = mLower;
112 ReferenceSelf(inAge, inZ);
115 // initialize the struct to be a valid linked list of one element
116 void nsWindowInfo::ReferenceSelf(bool inAge, bool inZ) {
117 if (inAge) {
118 mYounger = this;
119 mOlder = this;
121 if (inZ) {
122 mLower = this;
123 mHigher = this;
128 // nsAppShellWindowEnumerator
131 nsAppShellWindowEnumerator::nsAppShellWindowEnumerator(
132 const char16_t* aTypeString, nsWindowMediator& aMediator)
133 : mWindowMediator(&aMediator),
134 mType(aTypeString),
135 mCurrentPosition(nullptr) {
136 mWindowMediator->AddEnumerator(this);
137 NS_ADDREF(mWindowMediator);
140 nsAppShellWindowEnumerator::~nsAppShellWindowEnumerator() {
141 mWindowMediator->RemoveEnumerator(this);
142 NS_RELEASE(mWindowMediator);
145 // after mCurrentPosition has been initialized to point to the beginning
146 // of the appropriate list, adjust it if necessary
147 void nsAppShellWindowEnumerator::AdjustInitialPosition() {
148 if (!mType.IsEmpty() && mCurrentPosition &&
149 !mCurrentPosition->TypeEquals(mType))
150 mCurrentPosition = FindNext();
153 NS_IMETHODIMP nsAppShellWindowEnumerator::HasMoreElements(bool* retval) {
154 if (!retval) return NS_ERROR_INVALID_ARG;
156 *retval = mCurrentPosition ? true : false;
157 return NS_OK;
160 // if a window is being removed adjust the iterator's current position
161 void nsAppShellWindowEnumerator::WindowRemoved(nsWindowInfo* inInfo) {
162 if (mCurrentPosition == inInfo) mCurrentPosition = FindNext();
166 // nsASDOMWindowEnumerator
169 nsASDOMWindowEnumerator::nsASDOMWindowEnumerator(const char16_t* aTypeString,
170 nsWindowMediator& aMediator)
171 : nsAppShellWindowEnumerator(aTypeString, aMediator) {}
173 nsASDOMWindowEnumerator::~nsASDOMWindowEnumerator() {}
175 NS_IMETHODIMP nsASDOMWindowEnumerator::GetNext(nsISupports** retval) {
176 if (!retval) return NS_ERROR_INVALID_ARG;
178 *retval = nullptr;
179 while (mCurrentPosition) {
180 nsCOMPtr<nsPIDOMWindowOuter> domWindow;
181 nsWindowMediator::GetDOMWindow(mCurrentPosition->mWindow, domWindow);
182 mCurrentPosition = FindNext();
183 if (domWindow) return CallQueryInterface(domWindow, retval);
185 return NS_ERROR_FAILURE;
189 // nsASAppWindowEnumerator
192 nsASAppWindowEnumerator::nsASAppWindowEnumerator(const char16_t* aTypeString,
193 nsWindowMediator& aMediator)
194 : nsAppShellWindowEnumerator(aTypeString, aMediator) {}
196 nsASAppWindowEnumerator::~nsASAppWindowEnumerator() {}
198 NS_IMETHODIMP nsASAppWindowEnumerator::GetNext(nsISupports** retval) {
199 if (!retval) return NS_ERROR_INVALID_ARG;
201 *retval = nullptr;
202 if (mCurrentPosition) {
203 CallQueryInterface(mCurrentPosition->mWindow, retval);
204 mCurrentPosition = FindNext();
205 return NS_OK;
207 return NS_ERROR_FAILURE;
211 // nsASDOMWindowEarlyToLateEnumerator
214 nsASDOMWindowEarlyToLateEnumerator::nsASDOMWindowEarlyToLateEnumerator(
215 const char16_t* aTypeString, nsWindowMediator& aMediator)
216 : nsASDOMWindowEnumerator(aTypeString, aMediator) {
217 mCurrentPosition = aMediator.mOldestWindow;
218 AdjustInitialPosition();
221 nsASDOMWindowEarlyToLateEnumerator::~nsASDOMWindowEarlyToLateEnumerator() {}
223 nsWindowInfo* nsASDOMWindowEarlyToLateEnumerator::FindNext() {
224 nsWindowInfo *info, *listEnd;
225 bool allWindows = mType.IsEmpty();
227 // see AppWindowEarlyToLateEnumerator::FindNext
228 if (!mCurrentPosition) return nullptr;
230 info = mCurrentPosition->mYounger;
231 listEnd = mWindowMediator->mOldestWindow;
233 while (info != listEnd) {
234 if (allWindows || info->TypeEquals(mType)) return info;
235 info = info->mYounger;
238 return nullptr;
242 // nsASAppWindowEarlyToLateEnumerator
245 nsASAppWindowEarlyToLateEnumerator::nsASAppWindowEarlyToLateEnumerator(
246 const char16_t* aTypeString, nsWindowMediator& aMediator)
247 : nsASAppWindowEnumerator(aTypeString, aMediator) {
248 mCurrentPosition = aMediator.mOldestWindow;
249 AdjustInitialPosition();
252 nsASAppWindowEarlyToLateEnumerator::~nsASAppWindowEarlyToLateEnumerator() {}
254 nsWindowInfo* nsASAppWindowEarlyToLateEnumerator::FindNext() {
255 nsWindowInfo *info, *listEnd;
256 bool allWindows = mType.IsEmpty();
258 /* mCurrentPosition null is assumed to mean that the enumerator has run
259 its course and is now basically useless. It could also be interpreted
260 to mean that it was created at a time when there were no windows. In
261 that case it would probably be more appropriate to check to see whether
262 windows have subsequently been added. But it's not guaranteed that we'll
263 pick up newly added windows anyway (if they occurred previous to our
264 current position) so we just don't worry about that. */
265 if (!mCurrentPosition) return nullptr;
267 info = mCurrentPosition->mYounger;
268 listEnd = mWindowMediator->mOldestWindow;
270 while (info != listEnd) {
271 if (allWindows || info->TypeEquals(mType)) return info;
272 info = info->mYounger;
275 return nullptr;
279 // nsASAppWindowFrontToBackEnumerator
282 nsASAppWindowFrontToBackEnumerator::nsASAppWindowFrontToBackEnumerator(
283 const char16_t* aTypeString, nsWindowMediator& aMediator)
284 : nsASAppWindowEnumerator(aTypeString, aMediator) {
285 mCurrentPosition = aMediator.mTopmostWindow;
286 AdjustInitialPosition();
289 nsASAppWindowFrontToBackEnumerator::~nsASAppWindowFrontToBackEnumerator() {}
291 nsWindowInfo* nsASAppWindowFrontToBackEnumerator::FindNext() {
292 nsWindowInfo *info, *listEnd;
293 bool allWindows = mType.IsEmpty();
295 // see AppWindowEarlyToLateEnumerator::FindNext
296 if (!mCurrentPosition) return nullptr;
298 info = mCurrentPosition->mLower;
299 listEnd = mWindowMediator->mTopmostWindow;
301 while (info != listEnd) {
302 if (allWindows || info->TypeEquals(mType)) return info;
303 info = info->mLower;
306 return nullptr;
310 // nsASAppWindowBackToFrontEnumerator
313 nsASAppWindowBackToFrontEnumerator::nsASAppWindowBackToFrontEnumerator(
314 const char16_t* aTypeString, nsWindowMediator& aMediator)
315 : nsASAppWindowEnumerator(aTypeString, aMediator) {
316 mCurrentPosition =
317 aMediator.mTopmostWindow ? aMediator.mTopmostWindow->mHigher : nullptr;
318 AdjustInitialPosition();
321 nsASAppWindowBackToFrontEnumerator::~nsASAppWindowBackToFrontEnumerator() {}
323 nsWindowInfo* nsASAppWindowBackToFrontEnumerator::FindNext() {
324 nsWindowInfo *info, *listEnd;
325 bool allWindows = mType.IsEmpty();
327 // see AppWindowEarlyToLateEnumerator::FindNext
328 if (!mCurrentPosition) return nullptr;
330 info = mCurrentPosition->mHigher;
331 listEnd = mWindowMediator->mTopmostWindow;
332 if (listEnd) listEnd = listEnd->mHigher;
334 while (info != listEnd) {
335 if (allWindows || info->TypeEquals(mType)) return info;
336 info = info->mHigher;
339 return nullptr;