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/. */
7 #include "nsEnumeratorUtils.h"
9 #include "nsReadableUtils.h"
10 #include "nsUnicharUtils.h"
12 #include "nsIBaseWindow.h"
13 #include "nsIWidget.h"
14 #include "nsIObserverService.h"
15 #include "nsISimpleEnumerator.h"
16 #include "nsAppShellWindowEnumerator.h"
17 #include "nsWindowMediator.h"
18 #include "nsIWindowMediatorListener.h"
19 #include "nsGlobalWindowInner.h"
20 #include "nsGlobalWindowOuter.h"
21 #include "nsServiceManagerUtils.h"
23 #include "nsIDocShell.h"
24 #include "nsIInterfaceRequestor.h"
25 #include "nsIInterfaceRequestorUtils.h"
26 #include "nsIAppWindow.h"
28 using namespace mozilla
;
30 nsresult
nsWindowMediator::GetDOMWindow(
31 nsIAppWindow
* inWindow
, nsCOMPtr
<nsPIDOMWindowOuter
>& outDOMWindow
) {
32 nsCOMPtr
<nsIDocShell
> docShell
;
34 outDOMWindow
= nullptr;
35 inWindow
->GetDocShell(getter_AddRefs(docShell
));
36 NS_ENSURE_TRUE(docShell
, NS_ERROR_FAILURE
);
38 outDOMWindow
= docShell
->GetWindow();
39 return outDOMWindow
? NS_OK
: NS_ERROR_FAILURE
;
42 nsWindowMediator::nsWindowMediator()
43 : mOldestWindow(nullptr),
44 mTopmostWindow(nullptr),
46 mSortingZOrder(false),
49 nsWindowMediator::~nsWindowMediator() {
50 while (mOldestWindow
) UnregisterWindow(mOldestWindow
);
53 nsresult
nsWindowMediator::Init() {
55 nsCOMPtr
<nsIObserverService
> obsSvc
=
56 do_GetService("@mozilla.org/observer-service;1", &rv
);
57 NS_ENSURE_SUCCESS(rv
, rv
);
58 rv
= obsSvc
->AddObserver(this, "xpcom-shutdown", true);
59 NS_ENSURE_SUCCESS(rv
, rv
);
65 NS_IMETHODIMP
nsWindowMediator::RegisterWindow(nsIAppWindow
* inWindow
) {
66 MOZ_RELEASE_ASSERT(NS_IsMainThread());
69 NS_ERROR("Mediator is not initialized or about to die.");
70 return NS_ERROR_FAILURE
;
73 if (GetInfoFor(inWindow
)) {
74 NS_ERROR("multiple window registration");
75 return NS_ERROR_FAILURE
;
80 // Create window info struct and add to list of windows
81 nsWindowInfo
* windowInfo
= new nsWindowInfo(inWindow
, mTimeStamp
);
83 for (const auto& listener
: mListeners
.ForwardRange()) {
84 listener
->OnOpenWindow(inWindow
);
88 windowInfo
->InsertAfter(mOldestWindow
->mOlder
, nullptr);
90 mOldestWindow
= windowInfo
;
96 nsWindowMediator::UnregisterWindow(nsIAppWindow
* inWindow
) {
97 MOZ_RELEASE_ASSERT(NS_IsMainThread());
99 NS_ENSURE_STATE(mReady
);
100 nsWindowInfo
* info
= GetInfoFor(inWindow
);
101 if (info
) return UnregisterWindow(info
);
102 return NS_ERROR_INVALID_ARG
;
105 nsresult
nsWindowMediator::UnregisterWindow(nsWindowInfo
* inInfo
) {
106 // Inform the iterators
108 while (index
< mEnumeratorList
.Length()) {
109 mEnumeratorList
[index
]->WindowRemoved(inInfo
);
113 nsIAppWindow
* window
= inInfo
->mWindow
.get();
114 for (const auto& listener
: mListeners
.ForwardRange()) {
115 listener
->OnCloseWindow(window
);
118 // Remove from the lists and free up
119 if (inInfo
== mOldestWindow
) mOldestWindow
= inInfo
->mYounger
;
120 if (inInfo
== mTopmostWindow
) mTopmostWindow
= inInfo
->mLower
;
121 inInfo
->Unlink(true, true);
122 if (inInfo
== mOldestWindow
) mOldestWindow
= nullptr;
123 if (inInfo
== mTopmostWindow
) mTopmostWindow
= nullptr;
129 nsWindowInfo
* nsWindowMediator::GetInfoFor(nsIAppWindow
* aWindow
) {
130 nsWindowInfo
*info
, *listEnd
;
132 if (!aWindow
) return nullptr;
134 info
= mOldestWindow
;
136 while (info
!= listEnd
) {
137 if (info
->mWindow
.get() == aWindow
) return info
;
138 info
= info
->mYounger
;
139 listEnd
= mOldestWindow
;
144 nsWindowInfo
* nsWindowMediator::GetInfoFor(nsIWidget
* aWindow
) {
145 nsWindowInfo
*info
, *listEnd
;
147 if (!aWindow
) return nullptr;
149 info
= mOldestWindow
;
152 nsCOMPtr
<nsIWidget
> scanWidget
;
153 while (info
!= listEnd
) {
154 nsCOMPtr
<nsIBaseWindow
> base(do_QueryInterface(info
->mWindow
));
155 if (base
) base
->GetMainWidget(getter_AddRefs(scanWidget
));
156 if (aWindow
== scanWidget
.get()) return info
;
157 info
= info
->mYounger
;
158 listEnd
= mOldestWindow
;
164 nsWindowMediator::GetEnumerator(const char16_t
* inType
,
165 nsISimpleEnumerator
** outEnumerator
) {
166 MOZ_RELEASE_ASSERT(NS_IsMainThread());
167 NS_ENSURE_ARG_POINTER(outEnumerator
);
169 // If we get here with mReady false, we most likely did observe
170 // xpcom-shutdown. We will return an empty enumerator such that
171 // we make happy Javascripts calling late without throwing.
172 return NS_NewEmptyEnumerator(outEnumerator
);
174 RefPtr
<nsAppShellWindowEnumerator
> enumerator
=
175 new nsASDOMWindowEarlyToLateEnumerator(inType
, *this);
176 enumerator
.forget(outEnumerator
);
181 nsWindowMediator::GetAppWindowEnumerator(const char16_t
* inType
,
182 nsISimpleEnumerator
** outEnumerator
) {
183 MOZ_RELEASE_ASSERT(NS_IsMainThread());
184 NS_ENSURE_ARG_POINTER(outEnumerator
);
186 // If we get here with mReady false, we most likely did observe
187 // xpcom-shutdown. We will return an empty enumerator such that
188 // we make happy Javascripts calling late without throwing.
189 return NS_NewEmptyEnumerator(outEnumerator
);
191 RefPtr
<nsAppShellWindowEnumerator
> enumerator
=
192 new nsASAppWindowEarlyToLateEnumerator(inType
, *this);
193 enumerator
.forget(outEnumerator
);
198 nsWindowMediator::GetZOrderAppWindowEnumerator(const char16_t
* aWindowType
,
200 nsISimpleEnumerator
** _retval
) {
201 MOZ_RELEASE_ASSERT(NS_IsMainThread());
202 NS_ENSURE_ARG_POINTER(_retval
);
204 // If we get here with mReady false, we most likely did observe
205 // xpcom-shutdown. We will return an empty enumerator such that
206 // we make happy Javascripts calling late without throwing.
207 return NS_NewEmptyEnumerator(_retval
);
209 RefPtr
<nsAppShellWindowEnumerator
> enumerator
;
211 enumerator
= new nsASAppWindowFrontToBackEnumerator(aWindowType
, *this);
213 enumerator
= new nsASAppWindowBackToFrontEnumerator(aWindowType
, *this);
215 enumerator
.forget(_retval
);
219 void nsWindowMediator::AddEnumerator(nsAppShellWindowEnumerator
* inEnumerator
) {
220 mEnumeratorList
.AppendElement(inEnumerator
);
223 int32_t nsWindowMediator::RemoveEnumerator(
224 nsAppShellWindowEnumerator
* inEnumerator
) {
225 return mEnumeratorList
.RemoveElement(inEnumerator
);
228 // Returns the window of type inType ( if null return any window type ) which
229 // has the most recent time stamp
231 nsWindowMediator::GetMostRecentWindow(const char16_t
* inType
,
232 mozIDOMWindowProxy
** outWindow
) {
233 MOZ_RELEASE_ASSERT(NS_IsMainThread());
234 NS_ENSURE_ARG_POINTER(outWindow
);
235 *outWindow
= nullptr;
236 if (!mReady
) return NS_OK
;
238 // Find the most window with the highest time stamp that matches
239 // the requested type
240 nsWindowInfo
* info
= MostRecentWindowInfo(inType
, false);
241 if (info
&& info
->mWindow
) {
242 nsCOMPtr
<nsPIDOMWindowOuter
> DOMWindow
;
243 if (NS_SUCCEEDED(GetDOMWindow(info
->mWindow
, DOMWindow
))) {
244 DOMWindow
.forget(outWindow
);
247 return NS_ERROR_FAILURE
;
254 nsWindowMediator::GetMostRecentBrowserWindow(mozIDOMWindowProxy
** outWindow
) {
255 nsresult rv
= GetMostRecentWindow(u
"navigator:browser", outWindow
);
256 NS_ENSURE_SUCCESS(rv
, rv
);
258 #ifdef MOZ_WIDGET_ANDROID
260 rv
= GetMostRecentWindow(u
"navigator:geckoview", outWindow
);
261 NS_ENSURE_SUCCESS(rv
, rv
);
265 #ifdef MOZ_THUNDERBIRD
267 rv
= GetMostRecentWindow(u
"mail:3pane", outWindow
);
268 NS_ENSURE_SUCCESS(rv
, rv
);
276 nsWindowMediator::GetMostRecentNonPBWindow(const char16_t
* aType
,
277 mozIDOMWindowProxy
** aWindow
) {
278 MOZ_RELEASE_ASSERT(NS_IsMainThread());
279 NS_ENSURE_ARG_POINTER(aWindow
);
282 nsWindowInfo
* info
= MostRecentWindowInfo(aType
, true);
283 nsCOMPtr
<nsPIDOMWindowOuter
> domWindow
;
284 if (info
&& info
->mWindow
) {
285 GetDOMWindow(info
->mWindow
, domWindow
);
289 return NS_ERROR_FAILURE
;
292 domWindow
.forget(aWindow
);
296 nsWindowInfo
* nsWindowMediator::MostRecentWindowInfo(
297 const char16_t
* inType
, bool aSkipPrivateBrowsingOrClosed
) {
298 int32_t lastTimeStamp
= -1;
299 nsAutoString
typeString(inType
);
300 bool allWindows
= !inType
|| typeString
.IsEmpty();
302 // Find the most recent window with the highest time stamp that matches
303 // the requested type and has the correct browsing mode.
304 nsWindowInfo
* searchInfo
= mOldestWindow
;
305 nsWindowInfo
* listEnd
= nullptr;
306 nsWindowInfo
* foundInfo
= nullptr;
307 for (; searchInfo
!= listEnd
; searchInfo
= searchInfo
->mYounger
) {
308 listEnd
= mOldestWindow
;
310 if (!allWindows
&& !searchInfo
->TypeEquals(typeString
)) {
313 if (searchInfo
->mTimeStamp
< lastTimeStamp
) {
316 if (!searchInfo
->mWindow
) {
319 if (aSkipPrivateBrowsingOrClosed
) {
320 nsCOMPtr
<nsIDocShell
> docShell
;
321 searchInfo
->mWindow
->GetDocShell(getter_AddRefs(docShell
));
322 nsCOMPtr
<nsILoadContext
> loadContext
= do_QueryInterface(docShell
);
323 if (!loadContext
|| loadContext
->UsePrivateBrowsing()) {
327 nsCOMPtr
<nsPIDOMWindowOuter
> piwindow
= docShell
->GetWindow();
328 if (!piwindow
|| piwindow
->Closed()) {
333 foundInfo
= searchInfo
;
334 lastTimeStamp
= searchInfo
->mTimeStamp
;
341 nsWindowMediator::GetOuterWindowWithId(uint64_t aWindowID
,
342 mozIDOMWindowProxy
** aWindow
) {
343 RefPtr
<nsGlobalWindowOuter
> window
=
344 nsGlobalWindowOuter::GetOuterWindowWithId(aWindowID
);
345 window
.forget(aWindow
);
350 nsWindowMediator::GetCurrentInnerWindowWithId(uint64_t aWindowID
,
351 mozIDOMWindow
** aWindow
) {
352 RefPtr
<nsGlobalWindowInner
> window
=
353 nsGlobalWindowInner::GetInnerWindowWithId(aWindowID
);
356 if (!window
) return NS_OK
;
358 nsCOMPtr
<nsPIDOMWindowOuter
> outer
= window
->GetOuterWindow();
359 NS_ENSURE_TRUE(outer
, NS_ERROR_UNEXPECTED
);
361 // outer is already using another inner, so it's same as not found
362 if (outer
->GetCurrentInnerWindow() != window
) return NS_OK
;
364 window
.forget(aWindow
);
369 nsWindowMediator::UpdateWindowTimeStamp(nsIAppWindow
* inWindow
) {
370 MOZ_RELEASE_ASSERT(NS_IsMainThread());
372 NS_ENSURE_STATE(mReady
);
373 nsWindowInfo
* info
= GetInfoFor(inWindow
);
375 // increment the window's time stamp
376 info
->mTimeStamp
= ++mTimeStamp
;
379 return NS_ERROR_FAILURE
;
382 /* This method's plan is to intervene only when absolutely necessary.
383 We will get requests to place our windows behind unknown windows.
384 For the most part, we need to leave those alone (turning them into
385 explicit requests to be on top breaks Windows.) So generally we
386 calculate a change as seldom as possible.
389 nsWindowMediator::CalculateZPosition(nsIAppWindow
* inWindow
,
390 uint32_t inPosition
, nsIWidget
* inBelow
,
391 uint32_t* outPosition
,
392 nsIWidget
** outBelow
, bool* outAltered
) {
393 MOZ_RELEASE_ASSERT(NS_IsMainThread());
394 NS_ENSURE_ARG_POINTER(outBelow
);
396 NS_ENSURE_STATE(mReady
);
400 if (!inWindow
|| !outPosition
|| !outAltered
) return NS_ERROR_NULL_POINTER
;
402 if (inPosition
!= nsIWindowMediator::zLevelTop
&&
403 inPosition
!= nsIWindowMediator::zLevelBottom
&&
404 inPosition
!= nsIWindowMediator::zLevelBelow
)
405 return NS_ERROR_INVALID_ARG
;
407 nsWindowInfo
* info
= mTopmostWindow
;
408 nsIAppWindow
* belowWindow
= nullptr;
410 nsresult result
= NS_OK
;
412 *outPosition
= inPosition
;
415 if (mSortingZOrder
) { // don't fight SortZOrder()
417 NS_IF_ADDREF(*outBelow
);
422 GetZLevel(inWindow
, &inZ
);
424 if (inPosition
== nsIWindowMediator::zLevelBelow
) {
425 // locate inBelow. use topmost if it can't be found or isn't in the
427 info
= GetInfoFor(inBelow
);
428 if (!info
|| (info
->mYounger
!= info
&& info
->mLower
== info
))
429 info
= mTopmostWindow
;
434 /* Treat unknown windows as a request to be on top.
435 Not as it should be, but that's what Windows gives us.
436 Note we change inPosition, but not *outPosition. This forces
437 us to go through the "on top" calculation just below, without
438 necessarily changing the output parameters. */
439 inPosition
= nsIWindowMediator::zLevelTop
;
443 if (inPosition
== nsIWindowMediator::zLevelTop
) {
444 if (mTopmostWindow
&& mTopmostWindow
->mZLevel
> inZ
) {
445 // asked for topmost, can't have it. locate highest allowed position.
447 if (info
->mZLevel
<= inZ
) break;
449 } while (info
!= mTopmostWindow
);
451 *outPosition
= nsIWindowMediator::zLevelBelow
;
452 belowWindow
= info
->mHigher
->mWindow
;
455 } else if (inPosition
== nsIWindowMediator::zLevelBottom
) {
456 if (mTopmostWindow
&& mTopmostWindow
->mHigher
->mZLevel
< inZ
) {
457 // asked for bottommost, can't have it. locate lowest allowed position.
459 info
= info
->mHigher
;
460 if (info
->mZLevel
>= inZ
) break;
461 } while (info
!= mTopmostWindow
);
463 *outPosition
= nsIWindowMediator::zLevelBelow
;
464 belowWindow
= info
->mWindow
;
468 unsigned long relativeZ
;
470 // check that we're in the right z-plane
472 belowWindow
= info
->mWindow
;
473 relativeZ
= info
->mZLevel
;
474 if (relativeZ
> inZ
) {
475 // might be OK. is lower window, if any, lower?
476 if (info
->mLower
!= info
&& info
->mLower
->mZLevel
> inZ
) {
478 if (info
->mZLevel
<= inZ
) break;
480 } while (info
!= mTopmostWindow
);
482 belowWindow
= info
->mHigher
->mWindow
;
485 } else if (relativeZ
< inZ
) {
486 // nope. look for a higher window to be behind.
488 info
= info
->mHigher
;
489 if (info
->mZLevel
>= inZ
) break;
490 } while (info
!= mTopmostWindow
);
492 if (info
->mZLevel
>= inZ
)
493 belowWindow
= info
->mWindow
;
495 *outPosition
= nsIWindowMediator::zLevelTop
;
497 } // else they're equal, so it's OK
501 if (NS_SUCCEEDED(result
) && belowWindow
) {
502 nsCOMPtr
<nsIBaseWindow
> base(do_QueryInterface(belowWindow
));
504 base
->GetMainWidget(outBelow
);
506 result
= NS_ERROR_NO_INTERFACE
;
513 nsWindowMediator::SetZPosition(nsIAppWindow
* inWindow
, uint32_t inPosition
,
514 nsIAppWindow
* inBelow
) {
515 MOZ_RELEASE_ASSERT(NS_IsMainThread());
516 nsWindowInfo
*inInfo
, *belowInfo
;
518 if ((inPosition
!= nsIWindowMediator::zLevelTop
&&
519 inPosition
!= nsIWindowMediator::zLevelBottom
&&
520 inPosition
!= nsIWindowMediator::zLevelBelow
) ||
522 return NS_ERROR_INVALID_ARG
;
525 if (mSortingZOrder
) // don't fight SortZOrder()
529 NS_ENSURE_STATE(mReady
);
531 /* Locate inWindow and unlink it from the z-order list.
532 It's important we look for it in the age list, not the z-order list.
533 This is because the former is guaranteed complete, while
534 now may be this window's first exposure to the latter. */
535 inInfo
= GetInfoFor(inWindow
);
536 if (!inInfo
) return NS_ERROR_INVALID_ARG
;
538 // locate inBelow, place inWindow behind it
539 if (inPosition
== nsIWindowMediator::zLevelBelow
) {
540 belowInfo
= GetInfoFor(inBelow
);
541 // it had better also be in the z-order list
542 if (belowInfo
&& belowInfo
->mYounger
!= belowInfo
&&
543 belowInfo
->mLower
== belowInfo
) {
548 return NS_ERROR_INVALID_ARG
;
550 inPosition
= nsIWindowMediator::zLevelTop
;
553 if (inPosition
== nsIWindowMediator::zLevelTop
||
554 inPosition
== nsIWindowMediator::zLevelBottom
)
555 belowInfo
= mTopmostWindow
? mTopmostWindow
->mHigher
: nullptr;
557 if (inInfo
!= belowInfo
) {
558 inInfo
->Unlink(false, true);
559 inInfo
->InsertAfter(nullptr, belowInfo
);
561 if (inPosition
== nsIWindowMediator::zLevelTop
) mTopmostWindow
= inInfo
;
567 nsWindowMediator::GetZLevel(nsIAppWindow
* aWindow
, uint32_t* _retval
) {
568 NS_ENSURE_ARG_POINTER(_retval
);
569 *_retval
= nsIAppWindow::normalZ
;
570 // This can fail during window destruction.
571 nsWindowInfo
* info
= GetInfoFor(aWindow
);
573 *_retval
= info
->mZLevel
;
579 nsWindowMediator::SetZLevel(nsIAppWindow
* aWindow
, uint32_t aZLevel
) {
580 MOZ_RELEASE_ASSERT(NS_IsMainThread());
582 NS_ENSURE_STATE(mReady
);
584 nsWindowInfo
* info
= GetInfoFor(aWindow
);
585 NS_ASSERTION(info
, "setting z level of unregistered window");
586 if (!info
) return NS_ERROR_FAILURE
;
588 if (info
->mZLevel
!= aZLevel
) {
589 bool lowered
= info
->mZLevel
> aZLevel
;
590 info
->mZLevel
= aZLevel
;
592 SortZOrderFrontToBack();
594 SortZOrderBackToFront();
599 /* Fix potentially out-of-order windows by performing an insertion sort
600 on the z-order list. The method will work no matter how broken the
601 list, but its assumed usage is immediately after one window's z level
602 has been changed, so one window is potentially out of place. Such a sort
603 is most efficiently done in a particular direction. Use this one
604 if a window's z level has just been reduced, so the sort is most efficiently
606 Note it's hardly worth going to all the trouble to write two versions
607 of this method except that if we choose the inefficient sorting direction,
608 on slow systems windows could visibly bubble around the window that
611 void nsWindowMediator::SortZOrderFrontToBack() {
612 nsWindowInfo
*scan
, // scans list looking for problems
613 *search
, // searches for correct placement for scan window
614 *prev
, // previous search element
615 *lowest
; // bottom-most window in list
618 if (!mTopmostWindow
) // early during program execution there's no z list yet
619 return; // there's also only one window, so this is not dangerous
621 mSortingZOrder
= true;
623 /* Step through the list from top to bottom. If we find a window which
624 should be moved down in the list, move it to its highest legal position. */
627 lowest
= mTopmostWindow
->mHigher
;
628 scan
= mTopmostWindow
;
629 while (scan
!= lowest
) {
630 uint32_t scanZ
= scan
->mZLevel
;
631 if (scanZ
< scan
->mLower
->mZLevel
) { // out of order
632 search
= scan
->mLower
;
635 search
= search
->mLower
;
636 } while (prev
!= lowest
&& scanZ
< search
->mZLevel
);
638 // reposition |scan| within the list
639 if (scan
== mTopmostWindow
) mTopmostWindow
= scan
->mLower
;
640 scan
->Unlink(false, true);
641 scan
->InsertAfter(nullptr, prev
);
643 // fix actual window order
644 nsCOMPtr
<nsIBaseWindow
> base
;
645 nsCOMPtr
<nsIWidget
> scanWidget
;
646 nsCOMPtr
<nsIWidget
> prevWidget
;
647 base
= do_QueryInterface(scan
->mWindow
);
648 if (base
) base
->GetMainWidget(getter_AddRefs(scanWidget
));
649 base
= do_QueryInterface(prev
->mWindow
);
650 if (base
) base
->GetMainWidget(getter_AddRefs(prevWidget
));
652 scanWidget
->PlaceBehind(eZPlacementBelow
, prevWidget
, false);
661 mSortingZOrder
= false;
664 // see comment for SortZOrderFrontToBack
665 void nsWindowMediator::SortZOrderBackToFront() {
666 nsWindowInfo
*scan
, // scans list looking for problems
667 *search
, // searches for correct placement for scan window
668 *lowest
; // bottom-most window in list
671 if (!mTopmostWindow
) // early during program execution there's no z list yet
672 return; // there's also only one window, so this is not dangerous
674 mSortingZOrder
= true;
676 /* Step through the list from bottom to top. If we find a window which
677 should be moved up in the list, move it to its lowest legal position. */
680 lowest
= mTopmostWindow
->mHigher
;
682 while (scan
!= mTopmostWindow
) {
683 uint32_t scanZ
= scan
->mZLevel
;
684 if (scanZ
> scan
->mHigher
->mZLevel
) { // out of order
687 search
= search
->mHigher
;
688 } while (search
!= lowest
&& scanZ
> search
->mZLevel
);
690 // reposition |scan| within the list
691 if (scan
!= search
&& scan
!= search
->mLower
) {
692 scan
->Unlink(false, true);
693 scan
->InsertAfter(nullptr, search
);
695 if (search
== lowest
) mTopmostWindow
= scan
;
697 // fix actual window order
698 nsCOMPtr
<nsIBaseWindow
> base
;
699 nsCOMPtr
<nsIWidget
> scanWidget
;
700 nsCOMPtr
<nsIWidget
> searchWidget
;
701 base
= do_QueryInterface(scan
->mWindow
);
702 if (base
) base
->GetMainWidget(getter_AddRefs(scanWidget
));
703 if (mTopmostWindow
!= scan
) {
704 base
= do_QueryInterface(search
->mWindow
);
705 if (base
) base
->GetMainWidget(getter_AddRefs(searchWidget
));
708 scanWidget
->PlaceBehind(eZPlacementBelow
, searchWidget
, false);
712 scan
= scan
->mHigher
;
716 mSortingZOrder
= false;
719 NS_IMPL_ISUPPORTS(nsWindowMediator
, nsIWindowMediator
, nsIObserver
,
720 nsISupportsWeakReference
)
723 nsWindowMediator::AddListener(nsIWindowMediatorListener
* aListener
) {
724 NS_ENSURE_ARG_POINTER(aListener
);
726 mListeners
.AppendElement(aListener
);
732 nsWindowMediator::RemoveListener(nsIWindowMediatorListener
* aListener
) {
733 NS_ENSURE_ARG_POINTER(aListener
);
735 mListeners
.RemoveElement(aListener
);
741 nsWindowMediator::Observe(nsISupports
* aSubject
, const char* aTopic
,
742 const char16_t
* aData
) {
743 if (!strcmp(aTopic
, "xpcom-shutdown") && mReady
) {
744 MOZ_RELEASE_ASSERT(NS_IsMainThread());
745 while (mOldestWindow
) UnregisterWindow(mOldestWindow
);