diff --git a/mozilla/xpfe/appshell/src/nsAppShellWindowEnumerator.cpp b/mozilla/xpfe/appshell/src/nsAppShellWindowEnumerator.cpp new file mode 100644 index 00000000000..3f87fa8a972 --- /dev/null +++ b/mozilla/xpfe/appshell/src/nsAppShellWindowEnumerator.cpp @@ -0,0 +1,541 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 2001 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +#include "nsIContentViewer.h" +#include "nsIDocShell.h" +#include "nsIDocumentViewer.h" +#include "nsIDocument.h" +#include "nsIDOMDocument.h" +#include "nsIDOMElement.h" +#include "nsIDOMWindow.h" +#include "nsIDOMWindowInternal.h" +#include "nsIFactory.h" +#include "nsIInterfaceRequestor.h" +#include "nsIXULWindow.h" + +#include "nsAppShellWindowEnumerator.h" +#include "nsWindowMediator.h" + +/********************************************************************/ +/************************ static helper functions *******************/ +/********************************************************************/ + +static nsresult GetDOMWindow(nsIXULWindow* inWindow, + nsCOMPtr &outDOMWindow); +static nsCOMPtr GetDOMNodeFromDocShell(nsIDocShell *aShell); +static void GetAttribute( nsIXULWindow* inWindow, + const nsAutoString& inAttribute, nsAutoString& outValue); +static void GetWindowType(nsIXULWindow* inWindow, nsString &outType); + +// fetch the nsIDOMWindow(Internal) from a XUL Window +nsresult GetDOMWindow(nsIXULWindow *aWindow, nsCOMPtr &aDOMWindow) +{ + nsCOMPtr docShell; + + aWindow->GetDocShell(getter_AddRefs(docShell)); + aDOMWindow = do_GetInterface(docShell); + return aDOMWindow ? NS_OK : NS_ERROR_FAILURE; +} + + +// QueryInterface fu +nsCOMPtr GetDOMNodeFromDocShell(nsIDocShell *aShell) +{ + nsCOMPtr node; + + nsCOMPtr cv; + aShell->GetContentViewer(getter_AddRefs(cv)); + if (cv) { + nsCOMPtr docv(do_QueryInterface(cv)); + if (docv) { + nsCOMPtr doc; + docv->GetDocument(*getter_AddRefs(doc)); + if (doc) { + nsCOMPtr domdoc(do_QueryInterface(doc)); + if (domdoc) { + nsCOMPtr element; + domdoc->GetDocumentElement(getter_AddRefs(element)); + if (element) + node = do_QueryInterface(element); + } + } + } + } + + return node; +} + +// generic "retrieve the value of a XUL attribute" function +void GetAttribute(nsIXULWindow* aWindow, const nsAReadableString &anAttribute, + nsAWritableString &outValue) +{ + nsCOMPtr shell; + if (aWindow && + NS_SUCCEEDED(aWindow->GetDocShell(getter_AddRefs(shell)))) { + + nsCOMPtr node(GetDOMNodeFromDocShell(shell)); + + if (node) { + nsCOMPtr webshellElement(do_QueryInterface(node)); + if (webshellElement) + webshellElement->GetAttribute(anAttribute, outValue); + } + } +} + +// retrieve the window type, stored as the value of a particular +// attribute in its XUL window tag +void GetWindowType(nsIXULWindow* aWindow, nsString &outType) +{ + GetAttribute(aWindow, NS_LITERAL_STRING("windowtype"), outType); +} + +/********************************************************************/ +/**************************** nsWindowInfo **************************/ +/********************************************************************/ + +nsWindowInfo::nsWindowInfo(nsIXULWindow* inWindow, PRInt32 inTimeStamp) : + mWindow(inWindow),mTimeStamp(inTimeStamp) +{ + ReferenceSelf(PR_TRUE, PR_TRUE); +} + +nsWindowInfo::~nsWindowInfo() +{ +} + +// return true if the window described by this WindowInfo has a type +// equal to the given type +PRBool nsWindowInfo::TypeEquals(nsAReadableString &aType) +{ + nsAutoString rtnString; + GetWindowType(mWindow, rtnString); + return rtnString == aType; +} + +// insert the struct into their two linked lists, in position after the +// given (independent) method arguments +void nsWindowInfo::InsertAfter(nsWindowInfo *inOlder , nsWindowInfo *inHigher) { + if (inOlder) { + mOlder = inOlder; + mYounger = inOlder->mYounger; + mOlder->mYounger = this; + if (mOlder->mOlder == mOlder) + mOlder->mOlder = this; + mYounger->mOlder = this; + if (mYounger->mYounger == mYounger) + mYounger->mYounger = this; + } + if (inHigher) { + mHigher = inHigher; + mLower = inHigher->mLower; + mHigher->mLower = this; + if (mHigher->mHigher == mHigher) + mHigher->mHigher = this; + mLower->mHigher = this; + if (mLower->mLower == mLower) + mLower->mLower = this; + } +} + +// remove the struct from its linked lists +void nsWindowInfo::Unlink(PRBool inAge, PRBool inZ) { + + if (inAge) { + mOlder->mYounger = mYounger; + mYounger->mOlder = mOlder; + } + if (inZ) { + mLower->mHigher = mHigher; + mHigher->mLower = mLower; + } + ReferenceSelf( inAge, inZ ); +} + +// initialize the struct to be a valid linked list of one element +void nsWindowInfo::ReferenceSelf(PRBool inAge, PRBool inZ) { + + if (inAge) { + mYounger = this; + mOlder = this; + } + if (inZ) { + mLower = this; + mHigher = this; + } +} + +/********************************************************************/ +/*********************** nsAppShellWindowEnumerator *****************/ +/********************************************************************/ + +NS_IMPL_ISUPPORTS1(nsAppShellWindowEnumerator, nsISimpleEnumerator); + +nsAppShellWindowEnumerator::nsAppShellWindowEnumerator ( + const PRUnichar* aTypeString, + nsWindowMediator& aMediator) : + + mWindowMediator(&aMediator), mType(aTypeString), + mCurrentPosition(0) +{ + NS_INIT_REFCNT(); + + mWindowMediator->AddEnumerator(this); + mWindowMediator->AddRef(); +} + +nsAppShellWindowEnumerator::~nsAppShellWindowEnumerator() { + + mWindowMediator->RemoveEnumerator(this); + mWindowMediator->Release(); +} + +// after mCurrentPosition has been initialized to point to the beginning +// of the appropriate list, adjust it if necessary +void nsAppShellWindowEnumerator::AdjustInitialPosition() { + + if (!mType.IsEmpty() && mCurrentPosition && !mCurrentPosition->TypeEquals(mType)) + mCurrentPosition = FindNext(); +} + +NS_IMETHODIMP nsAppShellWindowEnumerator::HasMoreElements(PRBool *retval) +{ + if (!retval) + return NS_ERROR_INVALID_ARG; + + *retval = mCurrentPosition ? PR_TRUE : PR_FALSE; + return NS_OK; +} + +// if a window is being removed adjust the iterator's current position +void nsAppShellWindowEnumerator::WindowRemoved(nsWindowInfo *inInfo) { + + if (mCurrentPosition == inInfo) + mCurrentPosition = FindNext(); +} + +/********************************************************************/ +/*********************** nsASDOMWindowEnumerator ********************/ +/********************************************************************/ + +nsASDOMWindowEnumerator::nsASDOMWindowEnumerator( + const PRUnichar* aTypeString, + nsWindowMediator& aMediator) : + + nsAppShellWindowEnumerator(aTypeString, aMediator) { + +} + +nsASDOMWindowEnumerator::~nsASDOMWindowEnumerator() { +} + +NS_IMETHODIMP nsASDOMWindowEnumerator::GetNext(nsISupports **retval) { + + if (!retval) + return NS_ERROR_INVALID_ARG; + + *retval = NULL; + if (mCurrentPosition) { + nsCOMPtr domWindow; + GetDOMWindow(mCurrentPosition->mWindow, domWindow); + CallQueryInterface(domWindow, retval); + mCurrentPosition = FindNext(); + } + return NS_OK; +}; + +/********************************************************************/ +/*********************** nsASXULWindowEnumerator ********************/ +/********************************************************************/ + +nsASXULWindowEnumerator::nsASXULWindowEnumerator( + const PRUnichar* aTypeString, + nsWindowMediator& aMediator) : + + nsAppShellWindowEnumerator(aTypeString, aMediator) { + +} + +nsASXULWindowEnumerator::~nsASXULWindowEnumerator() { +} + +NS_IMETHODIMP nsASXULWindowEnumerator::GetNext(nsISupports **retval) { + + if (!retval) + return NS_ERROR_INVALID_ARG; + + *retval = NULL; + if (mCurrentPosition) { + CallQueryInterface(mCurrentPosition->mWindow, retval); + mCurrentPosition = FindNext(); + } + return NS_OK; +}; + +/********************************************************************/ +/****************** nsASDOMWindowEarlyToLateEnumerator **************/ +/********************************************************************/ + +nsASDOMWindowEarlyToLateEnumerator::nsASDOMWindowEarlyToLateEnumerator( + const PRUnichar *aTypeString, + nsWindowMediator &aMediator) : + + nsASDOMWindowEnumerator(aTypeString, aMediator) { + + mCurrentPosition = aMediator.mOldestWindow; + AdjustInitialPosition(); +} + +nsASDOMWindowEarlyToLateEnumerator::~nsASDOMWindowEarlyToLateEnumerator() { +} + +nsWindowInfo *nsASDOMWindowEarlyToLateEnumerator::FindNext() { + + nsWindowInfo *info, + *listEnd; + PRBool allWindows = mType.Length() == 0; + + // see nsXULWindowEarlyToLateEnumerator::FindNext + if (!mCurrentPosition) + return 0; + + info = mCurrentPosition->mYounger; + listEnd = mWindowMediator->mOldestWindow; + + while (info != listEnd) { + if (allWindows || info->TypeEquals(mType)) + return info; + info = info->mYounger; + } + + return 0; +} + +/********************************************************************/ +/****************** nsASXULWindowEarlyToLateEnumerator **************/ +/********************************************************************/ + +nsASXULWindowEarlyToLateEnumerator::nsASXULWindowEarlyToLateEnumerator( + const PRUnichar *aTypeString, + nsWindowMediator &aMediator) : + + nsASXULWindowEnumerator(aTypeString, aMediator) { + + mCurrentPosition = aMediator.mOldestWindow; + AdjustInitialPosition(); +} + +nsASXULWindowEarlyToLateEnumerator::~nsASXULWindowEarlyToLateEnumerator() { +} + +nsWindowInfo *nsASXULWindowEarlyToLateEnumerator::FindNext() { + + nsWindowInfo *info, + *listEnd; + PRBool allWindows = mType.Length() == 0; + + /* mCurrentPosition null is assumed to mean that the enumerator has run + its course and is now basically useless. It could also be interpreted + to mean that it was created at a time when there were no windows. In + that case it would probably be more appropriate to check to see whether + windows have subsequently been added. But it's not guaranteed that we'll + pick up newly added windows anyway (if they occurred previous to our + current position) so we just don't worry about that. */ + if (!mCurrentPosition) + return 0; + + info = mCurrentPosition->mYounger; + listEnd = mWindowMediator->mOldestWindow; + + while (info != listEnd) { + if (allWindows || info->TypeEquals(mType)) + return info; + info = info->mYounger; + } + + return 0; +} + +/********************************************************************/ +/****************** nsASDOMWindowFrontToBackEnumerator **************/ +/********************************************************************/ + +nsASDOMWindowFrontToBackEnumerator::nsASDOMWindowFrontToBackEnumerator( + const PRUnichar *aTypeString, + nsWindowMediator &aMediator) : + + nsASDOMWindowEnumerator(aTypeString, aMediator) { + + mCurrentPosition = aMediator.mTopmostWindow; + AdjustInitialPosition(); +} + +nsASDOMWindowFrontToBackEnumerator::~nsASDOMWindowFrontToBackEnumerator() { +} + +nsWindowInfo *nsASDOMWindowFrontToBackEnumerator::FindNext() { + + nsWindowInfo *info, + *listEnd; + PRBool allWindows = mType.Length() == 0; + + // see nsXULWindowEarlyToLateEnumerator::FindNext + if (!mCurrentPosition) + return 0; + + info = mCurrentPosition->mLower; + listEnd = mWindowMediator->mTopmostWindow; + + while (info != listEnd) { + if (allWindows || info->TypeEquals(mType)) + return info; + info = info->mLower; + } + + return 0; +} + +/********************************************************************/ +/****************** nsASXULWindowFrontToBackEnumerator **************/ +/********************************************************************/ + +nsASXULWindowFrontToBackEnumerator::nsASXULWindowFrontToBackEnumerator( + const PRUnichar *aTypeString, + nsWindowMediator &aMediator) : + + nsASXULWindowEnumerator(aTypeString, aMediator) { + + mCurrentPosition = aMediator.mTopmostWindow; + AdjustInitialPosition(); +} + +nsASXULWindowFrontToBackEnumerator::~nsASXULWindowFrontToBackEnumerator() +{ +} + +nsWindowInfo *nsASXULWindowFrontToBackEnumerator::FindNext() { + + nsWindowInfo *info, + *listEnd; + PRBool allWindows = mType.Length() == 0; + + // see nsXULWindowEarlyToLateEnumerator::FindNext + if (!mCurrentPosition) + return 0; + + info = mCurrentPosition->mLower; + listEnd = mWindowMediator->mTopmostWindow; + + while (info != listEnd) { + if (allWindows || info->TypeEquals(mType)) + return info; + info = info->mLower; + } + + return 0; +} + +/********************************************************************/ +/****************** nsASDOMWindowBackToFrontEnumerator **************/ +/********************************************************************/ + +nsASDOMWindowBackToFrontEnumerator::nsASDOMWindowBackToFrontEnumerator( + const PRUnichar *aTypeString, + nsWindowMediator &aMediator) : + + nsASDOMWindowEnumerator(aTypeString, aMediator) { + + mCurrentPosition = aMediator.mTopmostWindow ? + aMediator.mTopmostWindow->mHigher : 0; + AdjustInitialPosition(); +} + +nsASDOMWindowBackToFrontEnumerator::~nsASDOMWindowBackToFrontEnumerator() { +} + +nsWindowInfo *nsASDOMWindowBackToFrontEnumerator::FindNext() { + + nsWindowInfo *info, + *listEnd; + PRBool allWindows = mType.Length() == 0; + + // see nsXULWindowEarlyToLateEnumerator::FindNext + if (!mCurrentPosition) + return 0; + + info = mCurrentPosition->mHigher; + listEnd = mWindowMediator->mTopmostWindow; + if (listEnd) + listEnd = listEnd->mHigher; + + while (info != listEnd) { + if (allWindows || info->TypeEquals(mType)) + return info; + info = info->mHigher; + } + + return 0; +} + +/********************************************************************/ +/****************** nsASXULWindowBackToFrontEnumerator **************/ +/********************************************************************/ + +nsASXULWindowBackToFrontEnumerator::nsASXULWindowBackToFrontEnumerator( + const PRUnichar *aTypeString, + nsWindowMediator &aMediator) : + + nsASXULWindowEnumerator(aTypeString, aMediator) { + + mCurrentPosition = aMediator.mTopmostWindow ? + aMediator.mTopmostWindow->mHigher : 0; + AdjustInitialPosition(); +} + +nsASXULWindowBackToFrontEnumerator::~nsASXULWindowBackToFrontEnumerator() +{ +} + +nsWindowInfo *nsASXULWindowBackToFrontEnumerator::FindNext() { + + nsWindowInfo *info, + *listEnd; + PRBool allWindows = mType.Length() == 0; + + // see nsXULWindowEarlyToLateEnumerator::FindNext + if (!mCurrentPosition) + return 0; + + info = mCurrentPosition->mHigher; + listEnd = mWindowMediator->mTopmostWindow; + if (listEnd) + listEnd = listEnd->mHigher; + + while (info != listEnd) { + if (allWindows || info->TypeEquals(mType)) + return info; + info = info->mHigher; + } + + return 0; +} + diff --git a/mozilla/xpfe/appshell/src/nsAppShellWindowEnumerator.h b/mozilla/xpfe/appshell/src/nsAppShellWindowEnumerator.h new file mode 100644 index 00000000000..1491192b7fb --- /dev/null +++ b/mozilla/xpfe/appshell/src/nsAppShellWindowEnumerator.h @@ -0,0 +1,187 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 2001 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +#include "nsCOMPtr.h" +#include "nsString.h" + +#include "nsIRDFResource.h" +#include "nsISimpleEnumerator.h" +#include "nsIXULWindow.h" + +class nsWindowMediator; + +/********************************************************************/ +/**************************** nsWindowInfo **************************/ +/********************************************************************/ + +struct nsWindowInfo +{ + nsWindowInfo(nsIXULWindow* inWindow, PRInt32 inTimeStamp); + ~nsWindowInfo(); + + nsCOMPtr mRDFID; + nsCOMPtr mWindow; + PRInt32 mTimeStamp; + + // each struct is in two, independent, circular, doubly-linked lists + nsWindowInfo *mYounger, // next younger in sequence + *mOlder; + nsWindowInfo *mLower, // next lower in z-order + *mHigher; + + PRBool TypeEquals(nsAReadableString &aType); + void InsertAfter(nsWindowInfo *inOlder, nsWindowInfo *inHigher); + void Unlink(PRBool inAge, PRBool inZ); + void ReferenceSelf(PRBool inAge, PRBool inZ); +}; + + +/********************************************************************/ +/************************ virtual enumerators ***********************/ +/********************************************************************/ + +class nsAppShellWindowEnumerator : public nsISimpleEnumerator { + +friend class nsWindowMediator; + +public: + nsAppShellWindowEnumerator (const PRUnichar* aTypeString, + nsWindowMediator& inMediator); + virtual ~nsAppShellWindowEnumerator(); + NS_IMETHOD GetNext(nsISupports **retval) = 0; + NS_IMETHOD HasMoreElements(PRBool *retval); + + NS_DECL_ISUPPORTS + +protected: + + void AdjustInitialPosition(); + virtual nsWindowInfo *FindNext() = 0; + + void WindowRemoved(nsWindowInfo *inInfo); + + nsWindowMediator *mWindowMediator; + nsString mType; + nsWindowInfo *mCurrentPosition; +}; + +class nsASDOMWindowEnumerator : public nsAppShellWindowEnumerator { + +public: + nsASDOMWindowEnumerator (const PRUnichar* aTypeString, + nsWindowMediator& inMediator); + virtual ~nsASDOMWindowEnumerator(); + NS_IMETHOD GetNext(nsISupports **retval); +}; + +class nsASXULWindowEnumerator : public nsAppShellWindowEnumerator { + +public: + nsASXULWindowEnumerator (const PRUnichar* aTypeString, + nsWindowMediator& inMediator); + virtual ~nsASXULWindowEnumerator(); + NS_IMETHOD GetNext(nsISupports **retval); +}; + +/********************************************************************/ +/*********************** concrete enumerators ***********************/ +/********************************************************************/ + +class nsASDOMWindowEarlyToLateEnumerator : public nsASDOMWindowEnumerator { + +public: + nsASDOMWindowEarlyToLateEnumerator( + const PRUnichar* aTypeString, + nsWindowMediator& inMediator); + + virtual ~nsASDOMWindowEarlyToLateEnumerator(); + +protected: + virtual nsWindowInfo *FindNext(); +}; + +class nsASXULWindowEarlyToLateEnumerator : public nsASXULWindowEnumerator { + +public: + nsASXULWindowEarlyToLateEnumerator( + const PRUnichar* aTypeString, + nsWindowMediator& inMediator); + + virtual ~nsASXULWindowEarlyToLateEnumerator(); + +protected: + virtual nsWindowInfo *FindNext(); +}; + +class nsASDOMWindowFrontToBackEnumerator : public nsASDOMWindowEnumerator { + +public: + nsASDOMWindowFrontToBackEnumerator( + const PRUnichar* aTypeString, + nsWindowMediator& inMediator); + + virtual ~nsASDOMWindowFrontToBackEnumerator(); + +protected: + virtual nsWindowInfo *FindNext(); +}; + +class nsASXULWindowFrontToBackEnumerator : public nsASXULWindowEnumerator { + +public: + nsASXULWindowFrontToBackEnumerator( + const PRUnichar* aTypeString, + nsWindowMediator& inMediator); + + virtual ~nsASXULWindowFrontToBackEnumerator(); + +protected: + virtual nsWindowInfo *FindNext(); +}; + +class nsASDOMWindowBackToFrontEnumerator : public nsASDOMWindowEnumerator { + +public: + nsASDOMWindowBackToFrontEnumerator ( + const PRUnichar* aTypeString, + nsWindowMediator& inMediator); + + virtual ~nsASDOMWindowBackToFrontEnumerator(); + +protected: + virtual nsWindowInfo *FindNext(); +}; + +class nsASXULWindowBackToFrontEnumerator : public nsASXULWindowEnumerator { + +public: + nsASXULWindowBackToFrontEnumerator ( + const PRUnichar* aTypeString, + nsWindowMediator& inMediator); + + virtual ~nsASXULWindowBackToFrontEnumerator(); + +protected: + virtual nsWindowInfo *FindNext(); +}; + +