зеркало из https://github.com/mozilla/pjs.git
hooking up windowwatcher active window. bug 44809,76011 r=hyatt,saari
This commit is contained in:
Родитель
269f5f62cd
Коммит
1b8441b75f
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче