hooking up windowwatcher active window. bug 44809,76011 r=hyatt,saari

This commit is contained in:
danm%netscape.com 2001-04-16 20:35:46 +00:00
Родитель 269f5f62cd
Коммит 1b8441b75f
7 изменённых файлов: 149 добавлений и 40 удалений

Просмотреть файл

@ -298,7 +298,7 @@ void nsDocShellTreeOwner::AddToWatcher() {
if (domWindow) {
nsCOMPtr<nsPIWindowWatcher> wwatch(do_GetService(sWindowWatcherContractID));
if (wwatch)
wwatch->AddWindow(domWindow);
wwatch->AddWindow(domWindow, mWebBrowserChrome);
}
}
}

Просмотреть файл

@ -48,6 +48,7 @@ interface nsIObserver;
interface nsIPrompt;
interface nsIAuthPrompt;
interface nsISimpleEnumerator;
interface nsIWebBrowserChrome;
interface nsIWindowCreator;
[scriptable, uuid(002286a8-494b-43b3-8ddd-49e3fc50622b)]
@ -125,6 +126,16 @@ interface nsIWindowWatcher : nsISupports {
void setWindowCreator(in nsIWindowCreator creator);
/** Retrieve the chrome window mapped to the given DOM window. Window
Watcher keeps a list of all top-level DOM windows currently open,
along with their corresponding chrome interfaces. Since DOM Windows
lack a (public) means of retrieving their corresponding chrome,
this method will do that.
@param aWindow the DOM window whose chrome window the caller needs
@return the corresponding chrome window
*/
nsIWebBrowserChrome getChromeForWindow(in nsIDOMWindow aWindow);
/** The Watcher serves as a global storage facility for the current active
(frontmost non-floating-palette-type) window, storing and returning
it on demand. Users must keep this attribute current, including after

Просмотреть файл

@ -19,10 +19,15 @@
* Contributor(s):
*/
/* Private "control" methods on the Window Watcher. These are annoying
bookkeeping methods, not part of the public (embedding) interface.
*/
#include "nsISupports.idl"
interface nsIDOMWindow;
interface nsISimpleEnumerator;
interface nsIWebBrowserChrome;
[ptr] native jsvalptr(jsval);
@ -32,8 +37,13 @@ interface nsPIWindowWatcher : nsISupports
{
/** A window has been created. Add it to our list.
@param aWindow the window to add
@param aChrome the corresponding chrome window. The DOM window
and chrome will be mapped together, and the corresponding
chrome can be retrieved using the (not private)
method getChromeForWindow. If null, any extant mapping
will be cleared.
*/
void addWindow(in nsIDOMWindow aWindow);
void addWindow(in nsIDOMWindow aWindow, in nsIWebBrowserChrome aChrome);
/** A window has been closed. Remove it from our list.
@param aWindow the window to remove

Просмотреть файл

@ -75,12 +75,13 @@ class nsWindowWatcher;
struct WindowInfo {
WindowInfo(nsIDOMWindow* inWindow) {
WindowInfo(nsIDOMWindow *inWindow, nsIWebBrowserChrome *inChrome) {
#ifdef USEWEAKREFS
mWindow = getter_AddRefs(NS_GetWeakReference(inWindow));
#else
mWindow = inWindow;
#endif
mChrome = inChrome;
ReferenceSelf();
}
~WindowInfo() {}
@ -94,6 +95,7 @@ struct WindowInfo {
#else // still not an owning ref
nsIDOMWindow *mWindow;
#endif
nsIWebBrowserChrome *mChrome;
// each struct is in a circular, doubly-linked list
WindowInfo *mYounger, // next younger in sequence
*mOlder;
@ -742,19 +744,29 @@ nsWindowWatcher::SetActiveWindow(nsIDOMWindow *aActiveWindow)
}
NS_IMETHODIMP
nsWindowWatcher::AddWindow(nsIDOMWindow *aWindow)
nsWindowWatcher::AddWindow(nsIDOMWindow *aWindow, nsIWebBrowserChrome *aChrome)
{
nsresult rv;
if (!aWindow)
return NS_ERROR_INVALID_ARG;
WindowInfo *info;
nsAutoLock lock(mListLock);
// if we already have an entry for this window, adjust
// its chrome mapping and return
info = FindWindowInfo(aWindow);
if (info) {
info->mChrome = aChrome;
return NS_OK;
}
// create window info struct and add to list of windows
WindowInfo* info = new WindowInfo(aWindow);
// create a window info struct and add it to the list of windows
info = new WindowInfo(aWindow, aChrome);
if (!info)
return NS_ERROR_OUT_OF_MEMORY;
nsAutoLock lock(mListLock);
if (mOldestWindow)
info->InsertAfter(mOldestWindow->mOlder);
else
@ -775,6 +787,23 @@ NS_IMETHODIMP
nsWindowWatcher::RemoveWindow(nsIDOMWindow *aWindow)
{
// find the corresponding WindowInfo, remove it
if (!aWindow)
return NS_ERROR_INVALID_ARG;
WindowInfo *info = FindWindowInfo(aWindow);
if (info) {
RemoveWindow(info);
return NS_OK;
}
NS_WARNING("requested removal of nonexistent window\n");
return NS_ERROR_INVALID_ARG;
}
WindowInfo *
nsWindowWatcher::FindWindowInfo(nsIDOMWindow *aWindow)
{
// find the corresponding WindowInfo
WindowInfo *info,
*listEnd;
#ifdef USEWEAKREFS
@ -782,9 +811,6 @@ nsWindowWatcher::RemoveWindow(nsIDOMWindow *aWindow)
PRBool found;
#endif
if (!aWindow)
return NS_ERROR_INVALID_ARG;
info = mOldestWindow;
listEnd = 0;
#ifdef USEWEAKREFS
@ -792,25 +818,23 @@ nsWindowWatcher::RemoveWindow(nsIDOMWindow *aWindow)
found = PR_FALSE;
while (info != listEnd && NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIDOMWindow> infoWindow(do_QueryReferent(info->mWindow));
if (!infoWindow)
if (!infoWindow) // clean up dangling reference, while we're here
rv = RemoveWindow(info);
else if (infoWindow.get() == aWindow) {
found = PR_TRUE;
rv = RemoveWindow(info);
}
else if (infoWindow.get() == aWindow)
return info;
info = info->mYounger;
listEnd = mOldestWindow;
}
return found ? rv : NS_ERROR_INVALID_ARG;
return 0;
#else
while (info != listEnd) {
if (info->mWindow == aWindow)
return RemoveWindow(info);
return info;
info = info->mYounger;
listEnd = mOldestWindow;
}
NS_WARNING("requested removal of nonexistent window\n");
return NS_ERROR_INVALID_ARG;
return 0;
#endif
}
@ -830,6 +854,10 @@ nsresult nsWindowWatcher::RemoveWindow(WindowInfo *inInfo)
if (inInfo == mOldestWindow)
mOldestWindow = inInfo->mYounger == mOldestWindow ? 0 : inInfo->mYounger;
inInfo->Unlink();
// clear the active window, if they're the same
if (mActiveWindow == inInfo->mWindow)
mActiveWindow = 0;
}
// a window being removed from us signifies a newly closed window.
@ -851,6 +879,22 @@ nsresult nsWindowWatcher::RemoveWindow(WindowInfo *inInfo)
return NS_OK;
}
NS_IMETHODIMP
nsWindowWatcher::GetChromeForWindow(nsIDOMWindow *aWindow, nsIWebBrowserChrome **_retval)
{
if (!aWindow || !_retval)
return NS_ERROR_INVALID_ARG;
*_retval = 0;
nsAutoLock lock(mListLock);
WindowInfo *info = FindWindowInfo(aWindow);
if (info) {
*_retval = info->mChrome;
NS_IF_ADDREF(*_retval);
}
return NS_OK;
}
PRBool
nsWindowWatcher::AddEnumerator(nsWindowEnumerator* inEnumerator)
{

Просмотреть файл

@ -67,6 +67,7 @@ private:
PRBool AddEnumerator(nsWindowEnumerator* inEnumerator);
PRBool RemoveEnumerator(nsWindowEnumerator* inEnumerator);
WindowInfo *FindWindowInfo(nsIDOMWindow *aWindow);
nsresult RemoveWindow(WindowInfo *inInfo);
nsresult FindItemWithName(const PRUnichar *aName,

Просмотреть файл

@ -27,6 +27,7 @@
#include "nsVoidArray.h"
#include "rdf.h"
#include "nsIBaseWindow.h"
#include "nsIDOMWindow.h"
#include "nsIDOMWindowInternal.h"
#include "nsIDOMElement.h"
#include "nsIDocumentViewer.h"
@ -41,7 +42,6 @@
#include "nsIServiceManager.h"
#include "nsISimpleEnumerator.h"
#include "nsIWebShell.h"
#include "nsIWindowMediator.h"
#include "nsRDFCID.h"
#include "nsWindowMediator.h"
#include "nsXPIDLString.h"
@ -492,6 +492,18 @@ NS_IMETHODIMP nsWindowMediator::UnregisterWindow( nsWindowInfo *inInfo )
mTopmostWindow = 0;
delete inInfo;
// inform WindowWatcher
nsWindowInfo *info = MostRecentWindowInfo(0);
nsCOMPtr<nsIDOMWindow> domWindow;
if (info && info->mWindow) {
nsCOMPtr<nsIDOMWindowInternal> idomWindow;
GetDOMWindow(info->mWindow, idomWindow);
domWindow = do_QueryInterface(idomWindow);
}
// failure or no more windows sets it to 0, which is acceptable
mWatcher->SetActiveWindow(domWindow);
return NS_OK;
}
@ -539,34 +551,18 @@ PRInt32 nsWindowMediator::RemoveEnumerator( nsWindowEnumerator* inEnumerator)
*/
NS_IMETHODIMP nsWindowMediator::GetMostRecentWindow( const PRUnichar* inType, nsIDOMWindowInternal** outWindow ) {
NS_ENSURE_ARG_POINTER(outWindow);
*outWindow = NULL;
PRInt32 lastTimeStamp = -1;
nsIXULWindow* mostRecentWindow = NULL;
nsAutoString typeString( inType );
PRBool allWindows = !inType || typeString.Length() == 0;
// Find the most window with the highest time stamp that matches
// the requested type
nsWindowInfo *info,
*listEnd;
nsAutoLock lock(mListLock);
info = mOldestWindow;
listEnd = 0;
while (info != listEnd) {
if ((allWindows || info->GetType() == typeString) &&
info->mTimeStamp >= lastTimeStamp) {
nsWindowInfo *info = MostRecentWindowInfo(inType);
mostRecentWindow = info->mWindow;
lastTimeStamp = info->mTimeStamp;
}
info = info->mYounger;
listEnd = mOldestWindow;
}
if (mostRecentWindow) {
if (info && info->mWindow) {
nsCOMPtr <nsIDOMWindowInternal> DOMWindow;
if( NS_SUCCEEDED ( GetDOMWindow( mostRecentWindow, DOMWindow ) ) ) {
if(NS_SUCCEEDED(GetDOMWindow(info->mWindow, DOMWindow))) {
*outWindow = DOMWindow;
(*outWindow)->AddRef();
return NS_OK;
@ -578,6 +574,35 @@ NS_IMETHODIMP nsWindowMediator::GetMostRecentWindow( const PRUnichar* inType, ns
}
nsWindowInfo *
nsWindowMediator::MostRecentWindowInfo(const PRUnichar* inType)
{
PRInt32 lastTimeStamp = -1;
nsAutoString typeString(inType);
PRBool allWindows = !inType || typeString.Length() == 0;
// Find the most window with the highest time stamp that matches
// the requested type
nsWindowInfo *searchInfo,
*listEnd,
*foundInfo = 0;
searchInfo = mOldestWindow;
listEnd = 0;
while (searchInfo != listEnd) {
if ((allWindows || searchInfo->GetType() == typeString) &&
searchInfo->mTimeStamp >= lastTimeStamp) {
foundInfo = searchInfo;
lastTimeStamp = searchInfo->mTimeStamp;
}
searchInfo = searchInfo->mYounger;
listEnd = mOldestWindow;
}
return foundInfo;
}
NS_IMETHODIMP nsWindowMediator::UpdateWindowTimeStamp( nsIXULWindow* inWindow )
{
nsWindowInfo *info,
@ -588,7 +613,17 @@ NS_IMETHODIMP nsWindowMediator::UpdateWindowTimeStamp( nsIXULWindow* inWindow )
listEnd = 0;
while (info != listEnd) {
if (info->mWindow.get() == inWindow) {
// increment the window's time stamp
info->mTimeStamp = ++mTimeStamp;
// inform WindowWatcher
nsCOMPtr<nsIDOMWindowInternal> idomwindow;
GetDOMWindow(info->mWindow, idomwindow);
nsCOMPtr<nsIDOMWindow> domwindow(do_QueryInterface(idomwindow));
// if for some reason anything failed, it'll be set to 0, which is
// better than an invalid pointer.
mWatcher->SetActiveWindow(domwindow);
return NS_OK;
}
info = info->mYounger;
@ -958,6 +993,10 @@ nsWindowMediator::Init()
if ( gRDFService == NULL )
return NS_ERROR_NULL_POINTER;
mWatcher = do_GetService("@mozilla.org/embedcomp/window-watcher;1", &rv);
if (NS_FAILED(rv))
return rv;
// register this as a named data source with the RDF service
return gRDFService->RegisterDataSource(this, PR_FALSE);
}

Просмотреть файл

@ -23,7 +23,9 @@
#ifndef __nsWindowMediator_h
#define __nsWindowMediator_h
#include "nsCOMPtr.h"
#include "nsIWindowMediator.h"
#include "nsIWindowWatcher.h"
#include "nsXPIDLString.h"
class nsWindowEnumerator;
@ -171,6 +173,7 @@ private:
nsresult AddWindowToRDF( nsWindowInfo* ioWindowInfo );
PRInt32 AddEnumerator( nsWindowEnumerator* inEnumerator );
PRInt32 RemoveEnumerator( nsWindowEnumerator* inEnumerator);
nsWindowInfo *MostRecentWindowInfo(const PRUnichar* inType);
NS_IMETHOD UnregisterWindow( nsWindowInfo *inInfo );
@ -179,6 +182,7 @@ private:
*mTopmostWindow;
PRInt32 mTimeStamp;
PRLock *mListLock;
nsCOMPtr<nsIWindowWatcher> mWatcher;
// pseudo-constants for RDF
static nsIRDFResource* kNC_WindowMediatorRoot;