Bug 528491, combine nsFocusController and nsWindowRoot, r=jst,sr=smaug
authorNeil Deakin <neil@mozilla.com>
Sat, 20 Feb 2010 11:07:03 -0500
changeset 38336 7463ca240288ac138bf6766324a08e35e6131403
parent 38335 6b8dfb7407fd910e4209b2061d7f8de7bb9e494b
child 38337 505db0be4476fb2aea4647bcc2396f6bd85eb015
push idunknown
push userunknown
push dateunknown
reviewersjst, smaug
bugs528491
milestone1.9.3a2pre
Bug 528491, combine nsFocusController and nsWindowRoot, r=jst,sr=smaug
content/events/src/nsEventStateManager.cpp
content/xbl/src/nsXBLPrototypeHandler.cpp
content/xbl/src/nsXBLWindowKeyHandler.cpp
content/xul/document/src/nsXULCommandDispatcher.cpp
content/xul/document/src/nsXULCommandDispatcher.h
content/xul/document/src/nsXULDocument.cpp
content/xul/document/src/nsXULDocument.h
docshell/base/nsDocShell.cpp
dom/base/Makefile.in
dom/base/nsFocusController.cpp
dom/base/nsFocusController.h
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/base/nsIFocusController.h
dom/base/nsPIDOMWindow.h
dom/base/nsPIWindowRoot.h
dom/base/nsWindowRoot.cpp
dom/base/nsWindowRoot.h
embedding/browser/gtk/src/EmbedPrivate.cpp
embedding/browser/webBrowser/nsDocShellTreeOwner.cpp
embedding/components/commandhandler/src/nsCommandManager.cpp
layout/base/nsDocumentViewer.cpp
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -83,16 +83,17 @@
 #include "nsIView.h"
 #include "nsIViewManager.h"
 #include "nsISelection.h"
 #include "nsFrameSelection.h"
 #include "nsIDeviceContext.h"
 #include "nsIPrivateDOMEvent.h"
 #include "nsIDOMWindowInternal.h"
 #include "nsPIDOMWindow.h"
+#include "nsPIWindowRoot.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIEnumerator.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDocShellTreeNode.h"
 #include "nsIWebNavigation.h"
 #include "nsIContentViewer.h"
 #include "nsIPrefBranch2.h"
 #ifdef MOZ_XUL
@@ -145,17 +146,16 @@
 #include "nsIDOMXULDocument.h"
 #include "nsIDragService.h"
 #include "nsIDragSession.h"
 #include "nsDOMDataTransfer.h"
 #include "nsContentAreaDragDrop.h"
 #ifdef MOZ_XUL
 #include "nsTreeBodyFrame.h"
 #endif
-#include "nsIFocusController.h"
 #include "nsIController.h"
 #include "nsICommandParams.h"
 
 #ifdef XP_MACOSX
 #import <ApplicationServices/ApplicationServices.h>
 #endif
 
 //#define DEBUG_DOCSHELL_FOCUS
@@ -4355,20 +4355,21 @@ nsEventStateManager::IsShellVisible(nsID
   return isVisible;
 }
 
 nsresult
 nsEventStateManager::DoContentCommandEvent(nsContentCommandEvent* aEvent)
 {
   EnsureDocument(mPresContext);
   NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE);
-  nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mDocument->GetWindow()));
+  nsCOMPtr<nsPIDOMWindow> window(mDocument->GetWindow());
   NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
-  nsIFocusController* fc = window->GetRootFocusController();
-  NS_ENSURE_TRUE(fc, NS_ERROR_FAILURE);
+
+  nsCOMPtr<nsPIWindowRoot> root = window->GetTopWindowRoot();
+  NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
   const char* cmd;
   switch (aEvent->message) {
     case NS_CONTENT_COMMAND_CUT:
       cmd = "cmd_cut";
       break;
     case NS_CONTENT_COMMAND_COPY:
       cmd = "cmd_copy";
       break;
@@ -4386,17 +4387,17 @@ nsEventStateManager::DoContentCommandEve
       break;
     case NS_CONTENT_COMMAND_PASTE_TRANSFERABLE:
       cmd = "cmd_pasteTransferable";
       break;
     default:
       return NS_ERROR_NOT_IMPLEMENTED;
   }
   nsCOMPtr<nsIController> controller;
-  nsresult rv = fc->GetControllerForCommand(window, cmd, getter_AddRefs(controller));
+  nsresult rv = root->GetControllerForCommand(cmd, getter_AddRefs(controller));
   NS_ENSURE_SUCCESS(rv, rv);
   if (!controller) {
     // When GetControllerForCommand succeeded but there is no controller, the
     // command isn't supported.
     aEvent->mIsEnabled = PR_FALSE;
   } else {
     PRBool canDoIt;
     rv = controller->IsCommandEnabled(cmd, &canDoIt);
--- a/content/xbl/src/nsXBLPrototypeHandler.cpp
+++ b/content/xbl/src/nsXBLPrototypeHandler.cpp
@@ -52,17 +52,16 @@
 #include "nsIController.h"
 #include "nsIControllers.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDOMNSUIEvent.h"
 #include "nsIURI.h"
 #include "nsIDOMNSHTMLTextAreaElement.h"
 #include "nsIDOMNSHTMLInputElement.h"
 #include "nsIDOMText.h"
-#include "nsIFocusController.h"
 #include "nsFocusManager.h"
 #include "nsIEventListenerManager.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIDOMEventListener.h"
 #include "nsIPrivateDOMEvent.h"
 #include "nsIDOMNSEvent.h"
 #include "nsPIDOMWindow.h"
 #include "nsPIWindowRoot.h"
@@ -268,31 +267,27 @@ nsXBLPrototypeHandler::ExecuteHandler(ns
   nsCOMPtr<nsIAtom> onEventAtom = do_GetAtom(onEvent);
 
   // Compile the event handler.
   PRUint32 stID = nsIProgrammingLanguage::JAVASCRIPT;
 
   // Compile the handler and bind it to the element.
   nsCOMPtr<nsIScriptGlobalObject> boundGlobal;
   nsCOMPtr<nsPIWindowRoot> winRoot(do_QueryInterface(aTarget));
-  nsCOMPtr<nsIDOMWindow> window;
+  nsCOMPtr<nsPIDOMWindow> window;
 
   if (winRoot) {
     window = winRoot->GetWindow();
   }
 
   if (window) {
-    nsCOMPtr<nsPIDOMWindow> piWin(do_QueryInterface(window));
+    window = window->GetCurrentInnerWindow();
+    NS_ENSURE_TRUE(window, NS_ERROR_UNEXPECTED);
 
-    if (piWin) {
-      piWin = piWin->GetCurrentInnerWindow();
-      NS_ENSURE_TRUE(piWin, NS_ERROR_UNEXPECTED);
-    }
-
-    boundGlobal = do_QueryInterface(piWin->GetPrivateRoot());
+    boundGlobal = do_QueryInterface(window->GetPrivateRoot());
   }
   else boundGlobal = do_QueryInterface(aTarget);
 
   if (!boundGlobal) {
     nsCOMPtr<nsIDocument> boundDocument(do_QueryInterface(aTarget));
     if (!boundDocument) {
       // We must be an element.
       nsCOMPtr<nsIContent> content(do_QueryInterface(aTarget));
@@ -404,24 +399,21 @@ nsXBLPrototypeHandler::DispatchXBLComman
     PRBool dispatchStopped = privateEvent->IsDispatchStopped();
     if (dispatchStopped)
       return NS_OK;
   }
 
   // Instead of executing JS, let's get the controller for the bound
   // element and call doCommand on it.
   nsCOMPtr<nsIController> controller;
-  nsCOMPtr<nsIFocusController> focusController;
 
   nsCOMPtr<nsPIDOMWindow> privateWindow;
   nsCOMPtr<nsPIWindowRoot> windowRoot(do_QueryInterface(aTarget));
   if (windowRoot) {
-    windowRoot->GetFocusController(getter_AddRefs(focusController));
-    if (windowRoot)
-      privateWindow = do_QueryInterface(windowRoot->GetWindow());
+    privateWindow = windowRoot->GetWindow();
   }
   else {
     privateWindow = do_QueryInterface(aTarget);
     if (!privateWindow) {
       nsCOMPtr<nsIContent> elt(do_QueryInterface(aTarget));
       nsCOMPtr<nsIDocument> doc;
       // XXXbz sXBL/XBL2 issue -- this should be the "scope doc" or
       // something... whatever we use when wrapping DOM nodes
@@ -436,37 +428,37 @@ nsXBLPrototypeHandler::DispatchXBLComman
       if (!doc)
         return NS_ERROR_FAILURE;
 
       privateWindow = do_QueryInterface(doc->GetScriptGlobalObject());
       if (!privateWindow)
         return NS_ERROR_FAILURE;
     }
 
-    focusController = privateWindow->GetRootFocusController();
+    windowRoot = privateWindow->GetTopWindowRoot();
   }
 
   NS_LossyConvertUTF16toASCII command(mHandlerText);
-  if (focusController)
-    focusController->GetControllerForCommand(privateWindow, command.get(), getter_AddRefs(controller));
+  if (windowRoot)
+    windowRoot->GetControllerForCommand(command.get(), getter_AddRefs(controller));
   else
     controller = GetController(aTarget); // We're attached to the receiver possibly.
 
   nsAutoString type;
   mEventName->ToString(type);
 
   if (type.EqualsLiteral("keypress") &&
       mDetail == nsIDOMKeyEvent::DOM_VK_SPACE &&
       mMisc == 1) {
     // get the focused element so that we can pageDown only at
     // certain times.
 
     nsCOMPtr<nsPIDOMWindow> windowToCheck;
     if (windowRoot)
-      windowToCheck = do_QueryInterface(windowRoot->GetWindow());
+      windowToCheck = windowRoot->GetWindow();
     else
       windowToCheck = privateWindow->GetPrivateRoot();
 
     nsCOMPtr<nsIContent> focusedContent;
     if (windowToCheck) {
       nsCOMPtr<nsPIDOMWindow> focusedWindow;
       focusedContent =
         nsFocusManager::GetFocusedDescendant(windowToCheck, PR_TRUE, getter_AddRefs(focusedWindow));
--- a/content/xbl/src/nsXBLWindowKeyHandler.cpp
+++ b/content/xbl/src/nsXBLWindowKeyHandler.cpp
@@ -50,17 +50,16 @@
 #include "nsIServiceManager.h"
 #include "nsGkAtoms.h"
 #include "nsIXBLDocumentInfo.h"
 #include "nsIDOMElement.h"
 #include "nsINativeKeyBindings.h"
 #include "nsIController.h"
 #include "nsIControllers.h"
 #include "nsIDOMWindowInternal.h"
-#include "nsIFocusController.h"
 #include "nsFocusManager.h"
 #include "nsPIWindowRoot.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsContentUtils.h"
 #include "nsXBLPrototypeBinding.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMNSDocument.h"
@@ -361,22 +360,17 @@ nsXBLWindowKeyHandler::WalkHandlers(nsID
   WalkHandlersInternal(aKeyEvent, aEventType, mHandler);
 
   if (isEditor && GetEditorKeyBindings()) {
     nsNativeKeyEvent nativeEvent;
     // get the DOM window we're attached to
     nsCOMPtr<nsIControllers> controllers;
     nsCOMPtr<nsPIWindowRoot> root = do_QueryInterface(mTarget);
     if (root) {
-      nsCOMPtr<nsIFocusController> fc;
-      root->GetFocusController(getter_AddRefs(fc));
-      if (fc) {
-        nsCOMPtr<nsPIDOMWindow> piWindow = do_QueryInterface(root->GetWindow());
-        fc->GetControllers(piWindow, getter_AddRefs(controllers));
-      }
+      root->GetControllers(getter_AddRefs(controllers));
     }
 
     PRBool handled = PR_FALSE;
     if (aEventType == nsGkAtoms::keypress) {
       if (nsContentUtils::DOMEventToNativeKeyEvent(aKeyEvent, &nativeEvent, PR_TRUE))
         handled = sNativeEditorBindings->KeyPress(nativeEvent,
                                                   DoCommandCallback, controllers);
     } else if (aEventType == nsGkAtoms::keyup) {
--- a/content/xul/document/src/nsXULCommandDispatcher.cpp
+++ b/content/xul/document/src/nsXULCommandDispatcher.cpp
@@ -39,32 +39,32 @@
 
 /*
 
   This file provides the implementation for the XUL Command Dispatcher.
 
  */
 
 #include "nsIContent.h"
-#include "nsIFocusController.h"
 #include "nsFocusManager.h"
 #include "nsIControllers.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMXULDocument.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMNSHTMLInputElement.h"
 #include "nsIDOMNSHTMLTextAreaElement.h"
 #include "nsIDOMWindowInternal.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDocument.h"
 #include "nsPresContext.h"
 #include "nsIPresShell.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsPIDOMWindow.h"
+#include "nsPIWindowRoot.h"
 #include "nsRDFCID.h"
 #include "nsXULCommandDispatcher.h"
 #include "prlog.h"
 #include "nsIDOMEventTarget.h"
 #include "nsGUIEvent.h"
 #include "nsContentUtils.h"
 #include "nsReadableUtils.h"
 #include "nsCRT.h"
@@ -124,25 +124,27 @@ nsXULCommandDispatcher::Disconnect()
   while (mUpdaters) {
     Updater* doomed = mUpdaters;
     mUpdaters = mUpdaters->mNext;
     delete doomed;
   }
   mDocument = nsnull;
 }
 
-nsIFocusController*
-nsXULCommandDispatcher::GetFocusController()
+already_AddRefed<nsPIWindowRoot>
+nsXULCommandDispatcher::GetWindowRoot()
 {
-  if (!mDocument) {
-    return nsnull;
+  if (mDocument) {
+    nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mDocument->GetScriptGlobalObject()));
+    if (window) {
+      return window->GetTopWindowRoot();
+    }
   }
 
-  nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(mDocument->GetScriptGlobalObject()));
-  return win ? win->GetRootFocusController() : nsnull;
+  return nsnull;
 }
 
 nsIContent*
 nsXULCommandDispatcher::GetRootFocusedContentAndWindow(nsPIDOMWindow** aWindow)
 {
   *aWindow = nsnull;
 
   if (mDocument) {
@@ -386,19 +388,16 @@ nsXULCommandDispatcher::RemoveCommandUpd
 
   // Hmm. Not found. Oh well.
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULCommandDispatcher::UpdateCommands(const nsAString& aEventName)
 {
-  nsIFocusController* fc = GetFocusController();
-  NS_ENSURE_TRUE(fc, NS_ERROR_FAILURE);
-
   nsAutoString id;
   nsCOMPtr<nsIDOMElement> element;
   GetFocusedElement(getter_AddRefs(element));
   if (element) {
     nsresult rv = element->GetAttribute(NS_LITERAL_STRING("id"), id);
     NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get element's id");
     if (NS_FAILED(rv)) return rv;
   }
@@ -477,29 +476,29 @@ nsXULCommandDispatcher::Matches(const ns
   }
 
   return PR_TRUE;
 }
 
 NS_IMETHODIMP
 nsXULCommandDispatcher::GetControllers(nsIControllers** aResult)
 {
-  nsIFocusController* fc = GetFocusController();
-  NS_ENSURE_TRUE(fc, NS_ERROR_FAILURE);
+  nsCOMPtr<nsPIWindowRoot> root = GetWindowRoot();
+  NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
 
-  return fc->GetControllers(mDocument->GetWindow(), aResult);
+  return root->GetControllers(aResult);
 }
 
 NS_IMETHODIMP
 nsXULCommandDispatcher::GetControllerForCommand(const char *aCommand, nsIController** _retval)
 {
-  nsIFocusController* fc = GetFocusController();
-  NS_ENSURE_TRUE(fc, NS_ERROR_FAILURE);
+  nsCOMPtr<nsPIWindowRoot> root = GetWindowRoot();
+  NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
 
-  return fc->GetControllerForCommand(mDocument->GetWindow(), aCommand, _retval);
+  return root->GetControllerForCommand(aCommand, _retval);
 }
 
 NS_IMETHODIMP
 nsXULCommandDispatcher::GetSuppressFocusScroll(PRBool* aSuppressFocusScroll)
 {
   *aSuppressFocusScroll = PR_FALSE;
   return NS_OK;
 }
--- a/content/xul/document/src/nsXULCommandDispatcher.h
+++ b/content/xul/document/src/nsXULCommandDispatcher.h
@@ -50,17 +50,17 @@
 #include "nsIDOMXULCommandDispatcher.h"
 #include "nsIDOMFocusListener.h"
 #include "nsWeakReference.h"
 #include "nsIDOMNode.h"
 #include "nsString.h"
 #include "nsCycleCollectionParticipant.h"
 
 class nsIDOMElement;
-class nsIFocusController;
+class nsPIWindowRoot;
 
 class nsXULCommandDispatcher : public nsIDOMXULCommandDispatcher,
                                public nsSupportsWeakReference
 {
 public:
     nsXULCommandDispatcher(nsIDocument* aDocument);
     virtual ~nsXULCommandDispatcher();
 
@@ -69,17 +69,17 @@ public:
     NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXULCommandDispatcher,
                                              nsIDOMXULCommandDispatcher)
 
     // nsIDOMXULCommandDispatcher interface
     NS_DECL_NSIDOMXULCOMMANDDISPATCHER
 
     void Disconnect();
 protected:
-    nsIFocusController* GetFocusController();
+    already_AddRefed<nsPIWindowRoot> GetWindowRoot();
 
     nsIContent* GetRootFocusedContentAndWindow(nsPIDOMWindow** aWindow);
 
     nsCOMPtr<nsIDocument> mDocument;
 
     class Updater {
     public:
       Updater(nsIDOMElement* aElement,
--- a/content/xul/document/src/nsXULDocument.cpp
+++ b/content/xul/document/src/nsXULDocument.cpp
@@ -85,28 +85,28 @@
 #include "nsNetUtil.h"
 #include "nsParserUtils.h"
 #include "nsParserCIID.h"
 #include "nsPIBoxObject.h"
 #include "nsRDFCID.h"
 #include "nsILocalStore.h"
 #include "nsXPIDLString.h"
 #include "nsPIDOMWindow.h"
+#include "nsPIWindowRoot.h"
 #include "nsXULCommandDispatcher.h"
 #include "nsXULDocument.h"
 #include "nsXULElement.h"
 #include "prlog.h"
 #include "rdf.h"
 #include "nsIFrame.h"
 #include "nsIXBLService.h"
 #include "nsCExternalHandlerService.h"
 #include "nsMimeTypes.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
-#include "nsIFocusController.h"
 #include "nsContentList.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptGlobalObjectOwner.h"
 #include "nsIScriptRuntime.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsNodeInfoManager.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsContentUtils.h"
@@ -1548,38 +1548,39 @@ nsXULDocument::GetPopupNode(nsIDOMNode**
     }
 
     return rv;
 }
 
 NS_IMETHODIMP
 nsXULDocument::TrustedGetPopupNode(nsIDOMNode** aNode)
 {
-    // Get the focus controller.
-    nsCOMPtr<nsIFocusController> focusController;
-    GetFocusController(getter_AddRefs(focusController));
-    NS_ENSURE_TRUE(focusController, NS_ERROR_FAILURE);
-
-    // Get the popup node.
-    return focusController->GetPopupNode(aNode); // addref happens here
+    *aNode = nsnull;
+
+    nsCOMPtr<nsPIWindowRoot> rootWin = GetWindowRoot();
+    if (rootWin)
+        rootWin->GetPopupNode(aNode); // addref happens here
+
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULDocument::SetPopupNode(nsIDOMNode* aNode)
 {
-    nsresult rv;
-
-    // get focus controller
-    nsCOMPtr<nsIFocusController> focusController;
-    GetFocusController(getter_AddRefs(focusController));
-    NS_ENSURE_TRUE(focusController, NS_ERROR_FAILURE);
-    // set popup node
-    rv = focusController->SetPopupNode(aNode);
-
-    return rv;
+    if (aNode) {
+        // only allow real node objects
+        nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
+        NS_ENSURE_ARG(node);
+    }
+
+    nsCOMPtr<nsPIWindowRoot> rootWin = GetWindowRoot();
+    if (rootWin)
+        rootWin->SetPopupNode(aNode); // addref happens here
+
+    return NS_OK;
 }
 
 // Returns the rangeOffset element from the XUL Popup Manager. This is for
 // chrome callers only.
 NS_IMETHODIMP
 nsXULDocument::GetPopupRangeParent(nsIDOMNode** aRangeParent)
 {
     NS_ENSURE_ARG_POINTER(aRangeParent);
@@ -4605,25 +4606,23 @@ nsXULDocument::ParserObserver::OnStopReq
     // Drop the reference to the document to break cycle between the
     // document, the parser, the content sink, and the parser
     // observer.
     mDocument = nsnull;
 
     return rv;
 }
 
-void
-nsXULDocument::GetFocusController(nsIFocusController** aFocusController)
+already_AddRefed<nsPIWindowRoot>
+nsXULDocument::GetWindowRoot()
 {
     nsCOMPtr<nsIInterfaceRequestor> ir = do_QueryReferent(mDocumentContainer);
-    nsCOMPtr<nsPIDOMWindow> windowPrivate = do_GetInterface(ir);
-    if (windowPrivate) {
-        NS_IF_ADDREF(*aFocusController = windowPrivate->GetRootFocusController());
-    } else
-        *aFocusController = nsnull;
+    nsCOMPtr<nsIDOMWindow> window(do_GetInterface(ir));
+    nsCOMPtr<nsPIDOMWindow> piWin(do_QueryInterface(window));
+    return piWin ? piWin->GetTopWindowRoot() : nsnull;
 }
 
 PRBool
 nsXULDocument::IsDocumentRightToLeft()
 {
     if (mDocDirection == Direction_Uninitialized) {
         mDocDirection = Direction_LeftToRight; // default to ltr on failure
 
--- a/content/xul/document/src/nsXULDocument.h
+++ b/content/xul/document/src/nsXULDocument.h
@@ -56,17 +56,17 @@
 #include "nsIXULDocument.h"
 #include "nsScriptLoader.h"
 #include "nsIStreamListener.h"
 #include "nsICSSLoaderObserver.h"
 
 class nsIRDFResource;
 class nsIRDFService;
 class nsIXULPrototypeCache;
-class nsIFocusController;
+class nsPIWindowRoot;
 #if 0 // XXXbe save me, scc (need NSCAP_FORWARD_DECL(nsXULPrototypeScript))
 class nsIObjectInputStream;
 class nsIObjectOutputStream;
 class nsIXULPrototypeScript;
 #else
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsXULElement.h"
@@ -240,17 +240,17 @@ protected:
     nsresult
     AddElementToDocumentPost(nsIContent* aElement);
 
     nsresult
     ExecuteOnBroadcastHandlerFor(nsIContent* aBroadcaster,
                                  nsIDOMElement* aListener,
                                  nsIAtom* aAttr);
 
-    void GetFocusController(nsIFocusController** aFocusController);
+    already_AddRefed<nsPIWindowRoot> GetWindowRoot();
 
     PRInt32 GetDefaultNamespaceID() const
     {
         return kNameSpaceID_XUL;
     }
 
     static NS_HIDDEN_(int) DirectionChanged(const char* aPrefName, void* aData);
 
@@ -320,22 +320,16 @@ protected:
      * XXX dr
      * ------
      * We used to have two pointers into the content model: mPopupNode and
      * mTooltipNode, which were used to retrieve the objects triggering a
      * popup or tooltip. You need that access because your reference has
      * disappeared by the time you click on a popup item or do whatever
      * with a tooltip. These were owning references (no cycles, as pinkerton
      * pointed out, since we're still parent-child).
-     *
-     * We still have mTooltipNode, but mPopupNode has moved to the
-     * FocusController. The APIs (IDL attributes popupNode and tooltipNode)
-     * are still here for compatibility and ease of use, but we should
-     * probably move the mTooltipNode over to FocusController at some point
-     * as well, for consistency.
      */
 
     nsCOMPtr<nsIDOMNode>    mTooltipNode;          // [OWNER] element triggering the tooltip
 
     /**
      * document direction for use with the -moz-locale-dir property
      */
     enum DocumentDirection {
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -155,16 +155,17 @@
 #include "nsPICommandUpdater.h"
 #include "nsIDOMHTMLAnchorElement.h"
 #include "nsIWebBrowserChrome2.h"
 
 // Editor-related
 #include "nsIEditingSession.h"
 
 #include "nsPIDOMWindow.h"
+#include "nsPIWindowRoot.h"
 #include "nsIDOMDocument.h"
 #include "nsICachingChannel.h"
 #include "nsICacheVisitor.h"
 #include "nsICacheEntryDescriptor.h"
 #include "nsIMultiPartChannel.h"
 #include "nsIWyciwygChannel.h"
 
 // The following are for bug #13871: Prevent frameset spoofing
@@ -174,17 +175,16 @@
 // These can go away if error reporting is propagated up past nsDocShell.
 #include "nsIConsoleService.h"
 #include "nsIScriptError.h"
 
 // used to dispatch urls to default protocol handlers
 #include "nsCExternalHandlerService.h"
 #include "nsIExternalProtocolService.h"
 
-#include "nsIFocusController.h"
 #include "nsFocusManager.h"
 
 #include "nsITextToSubURI.h"
 
 #include "nsIJARChannel.h"
 
 #include "prlog.h"
 #include "prmem.h"
@@ -10965,28 +10965,26 @@ nsClassifierCallback::GetInterface(const
 // Routines for selection and clipboard
 //
 nsresult
 nsDocShell::GetControllerForCommand(const char * inCommand,
                                     nsIController** outController)
 {
   NS_ENSURE_ARG_POINTER(outController);
   *outController = nsnull;
-  
-  nsresult rv = NS_ERROR_FAILURE;
-  
-  nsCOMPtr<nsPIDOMWindow> window ( do_QueryInterface(mScriptGlobal) );
+
+  nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mScriptGlobal));
   if (window) {
-    nsIFocusController *focusController = window->GetRootFocusController();
-    if (focusController)
-      rv = focusController->GetControllerForCommand (window, inCommand, outController);
-  } // if window
-
-  return rv;
-  
+      nsCOMPtr<nsPIWindowRoot> root = window->GetTopWindowRoot();
+      if (root) {
+          return root->GetControllerForCommand(inCommand, outController);
+      }
+  }
+
+  return NS_ERROR_FAILURE;
 }
 
 nsresult
 nsDocShell::IsCommandEnabled(const char * inCommand, PRBool* outEnabled)
 {
   NS_ENSURE_ARG_POINTER(outEnabled);
   *outEnabled = PR_FALSE;
 
--- a/dom/base/Makefile.in
+++ b/dom/base/Makefile.in
@@ -57,17 +57,16 @@ EXPORTS = \
   nsDOMClassInfoID.h \
   nsDOMError.h \
   nsDOMJSUtils.h \
   nsDOMScriptObjectHolder.h \
   nsDOMString.h \
   nsIBaseDOMException.h \
   nsIDOMClassInfo.h \
   nsIDOMScriptObjectFactory.h \
-  nsIFocusController.h \
   nsIJSEventListener.h \
   nsIJSNativeInitializer.h \
   nsIScriptContext.h	\
   nsIScriptExternalNameSet.h \
   nsIScriptGlobalObject.h \
   nsIScriptGlobalObjectOwner.h \
   nsIScriptNameSpaceManager.h \
   nsIScriptObjectOwner.h \
@@ -81,17 +80,16 @@ EXPORTS = \
   $(NULL)
 
 CPPSRCS =			\
 	nsBarProps.cpp          \
 	nsDOMException.cpp 	\
 	nsDOMWindowUtils.cpp 	\
 	nsJSEnvironment.cpp	\
 	nsJSTimeoutHandler.cpp	\
-	nsFocusController.cpp	\
 	nsFocusManager.cpp \
 	nsGlobalWindow.cpp      \
 	nsGlobalWindowCommands.cpp \
 	nsLocation.cpp		\
 	nsDOMWindowList.cpp	\
 	nsJSUtils.cpp		\
 	nsScreen.cpp		\
 	nsHistory.cpp		\
deleted file mode 100644
--- a/dom/base/nsFocusController.cpp
+++ /dev/null
@@ -1,222 +0,0 @@
-/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla 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/MPL/
- *
- * 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 the Mozilla browser.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications, Inc.
- * Portions created by the Initial Developer are Copyright (C) 1999
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   David W. Hyatt <hyatt@netscape.com> (Original Author)
- *   Dan Rosen <dr@netscape.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsIContent.h"
-#include "nsIControllers.h"
-#include "nsIDOMDocument.h"
-#include "nsIDOMHTMLDocument.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMNSHTMLInputElement.h"
-#include "nsIDOMNSHTMLTextAreaElement.h"
-#include "nsIDOMNSEvent.h"
-#include "nsIDOMWindowInternal.h"
-#include "nsIDocument.h"
-#include "nsPIDOMWindow.h"
-#include "nsFocusController.h"
-#include "prlog.h"
-#include "nsGlobalWindow.h"
-#include "nsFocusManager.h"
-
-#ifdef MOZ_XUL
-#include "nsIDOMXULDocument.h"
-#include "nsIDOMXULElement.h"
-#endif
-
-////////////////////////////////////////////////////////////////////////
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsFocusController)
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsFocusController, nsIFocusController)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsFocusController,
-                                           nsIFocusController)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFocusController)
-  NS_INTERFACE_MAP_ENTRY(nsIFocusController)
-  NS_INTERFACE_MAP_ENTRY(nsSupportsWeakReference)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIFocusController)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsFocusController)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFocusController)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPopupNode)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-static nsIContent*
-GetRootFocusedContentAndWindow(nsPIDOMWindow* aContextWindow,
-                               nsPIDOMWindow** aWindow)
-{
-  *aWindow = nsnull;
-
-  if (aContextWindow) {
-    nsCOMPtr<nsPIDOMWindow> rootWindow = aContextWindow->GetPrivateRoot();
-    if (rootWindow) {
-      return nsFocusManager::GetFocusedDescendant(rootWindow, PR_TRUE, aWindow);
-    }
-  }
-
-  return nsnull;
-}
-
-NS_IMETHODIMP
-nsFocusController::Create(nsIFocusController** aResult)
-{
-  nsFocusController* controller = new nsFocusController();
-  if (!controller)
-    return NS_ERROR_OUT_OF_MEMORY;
-
-  *aResult = controller;
-  NS_ADDREF(*aResult);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsFocusController::GetControllers(nsPIDOMWindow* aContextWindow, nsIControllers** aResult)
-{
-  *aResult = nsnull;
-
-  // XXX: we should fix this so there's a generic interface that
-  // describes controllers, so this code would have no special
-  // knowledge of what object might have controllers.
-
-  nsCOMPtr<nsPIDOMWindow> focusedWindow;
-  nsIContent* focusedContent =
-    GetRootFocusedContentAndWindow(aContextWindow, getter_AddRefs(focusedWindow));
-  if (focusedContent) {
-#ifdef MOZ_XUL
-    nsCOMPtr<nsIDOMXULElement> xulElement(do_QueryInterface(focusedContent));
-    if (xulElement)
-      return xulElement->GetControllers(aResult);
-#endif
-
-    nsCOMPtr<nsIDOMNSHTMLTextAreaElement> htmlTextArea =
-      do_QueryInterface(focusedContent);
-    if (htmlTextArea)
-      return htmlTextArea->GetControllers(aResult);
-
-    nsCOMPtr<nsIDOMNSHTMLInputElement> htmlInputElement =
-      do_QueryInterface(focusedContent);
-    if (htmlInputElement)
-      return htmlInputElement->GetControllers(aResult);
-
-    if (focusedContent->IsEditable() && focusedWindow)
-      return focusedWindow->GetControllers(aResult);
-  }
-  else {
-    nsCOMPtr<nsIDOMWindowInternal> domWindow = do_QueryInterface(focusedWindow);
-    if (domWindow)
-      return domWindow->GetControllers(aResult);
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsFocusController::GetControllerForCommand(nsPIDOMWindow* aContextWindow,
-                                           const char * aCommand,
-                                           nsIController** _retval)
-{
-  NS_ENSURE_ARG_POINTER(_retval);
-  *_retval = nsnull;
-
-  nsCOMPtr<nsIControllers> controllers;
-  nsCOMPtr<nsIController> controller;
-
-  GetControllers(aContextWindow, getter_AddRefs(controllers));
-  if(controllers) {
-    controllers->GetControllerForCommand(aCommand, getter_AddRefs(controller));
-    if(controller) {
-      controller.swap(*_retval);
-      return NS_OK;
-    }
-  }
-
-  nsCOMPtr<nsPIDOMWindow> focusedWindow;
-  GetRootFocusedContentAndWindow(aContextWindow, getter_AddRefs(focusedWindow));
-  while (focusedWindow) {
-    nsCOMPtr<nsIDOMWindowInternal> domWindow(do_QueryInterface(focusedWindow));
-
-    nsCOMPtr<nsIControllers> controllers2;
-    domWindow->GetControllers(getter_AddRefs(controllers2));
-    if(controllers2) {
-      controllers2->GetControllerForCommand(aCommand,
-                                            getter_AddRefs(controller));
-      if(controller) {
-        controller.swap(*_retval);
-        return NS_OK;
-      }
-    }
-
-    // XXXndeakin P3 is this casting safe?
-    nsCOMPtr<nsPIDOMWindow> piWindow = do_QueryInterface(focusedWindow); 
-    nsGlobalWindow *win =
-      static_cast<nsGlobalWindow *>
-                 (static_cast<nsIDOMWindowInternal *>(piWindow));
-    focusedWindow = win->GetPrivateParent();
-  }
-  
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsFocusController::GetPopupNode(nsIDOMNode** aNode)
-{
-#ifdef DEBUG_dr
-  printf("dr :: nsFocusController::GetPopupNode\n");
-#endif
-
-  *aNode = mPopupNode;
-  NS_IF_ADDREF(*aNode);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsFocusController::SetPopupNode(nsIDOMNode* aNode)
-{
-#ifdef DEBUG_dr
-  printf("dr :: nsFocusController::SetPopupNode\n");
-#endif
-
-  if (aNode) {
-    nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
-    NS_ENSURE_ARG(node);
-  }
-  mPopupNode = aNode;
-  return NS_OK;
-}
deleted file mode 100644
--- a/dom/base/nsFocusController.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla 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/MPL/
- *
- * 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 the Mozilla browser.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications, Inc.
- * Portions created by the Initial Developer are Copyright (C) 1999
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   David W. Hyatt <hyatt@netscape.com> (Original Author)
- *   Dan Rosen <dr@netscape.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef nsFocusController_h__
-#define nsFocusController_h__
-
-#include "nsCOMPtr.h"
-#include "nsIFocusController.h"
-#include "nsIDOMFocusListener.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMWindow.h"
-#include "nsWeakReference.h"
-#include "nsCycleCollectionParticipant.h"
-
-class nsPIDOMWindow;
-class nsIController;
-class nsIControllers;
-
-class nsFocusController : public nsIFocusController,
-                          public nsSupportsWeakReference
-{
-public:
-  static NS_IMETHODIMP Create(nsIFocusController** aResult);
-
-public:
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-
-  NS_IMETHOD GetPopupNode(nsIDOMNode** aNode);
-  NS_IMETHOD SetPopupNode(nsIDOMNode* aNode);
-
-  NS_IMETHOD GetControllerForCommand(nsPIDOMWindow* aContextWindow,
-                                     const char *aCommand,
-                                     nsIController** aResult);
-  NS_IMETHOD GetControllers(nsPIDOMWindow* aContextWindow, nsIControllers** aResult);
-
-  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFocusController,
-                                           nsIFocusController)
-
-// Members
-protected:
-  nsCOMPtr<nsIDOMNode> mPopupNode; // [OWNER]
-};
-
-#endif // nsFocusController_h__
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -4768,30 +4768,30 @@ nsGlobalWindow::SizeToContent()
   NS_ENSURE_SUCCESS(markupViewer->SizeToContent(), NS_ERROR_FAILURE);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetWindowRoot(nsIDOMEventTarget **aWindowRoot)
 {
-  *aWindowRoot = nsnull;
-
-  nsIDOMWindowInternal *rootWindow = nsGlobalWindow::GetPrivateRoot();
+  nsCOMPtr<nsPIWindowRoot> root = GetTopWindowRoot();
+  return CallQueryInterface(root, aWindowRoot);
+}
+
+already_AddRefed<nsPIWindowRoot>
+nsGlobalWindow::GetTopWindowRoot()
+{
+  nsIDOMWindowInternal *rootWindow = GetPrivateRoot();
   nsCOMPtr<nsPIDOMWindow> piWin(do_QueryInterface(rootWindow));
-  if (!piWin) {
-    return NS_OK;
-  }
-
-  nsPIDOMEventTarget *chromeHandler = piWin->GetChromeEventHandler();
-  if (!chromeHandler) {
-    return NS_OK;
-  }
-
-  return CallQueryInterface(chromeHandler, aWindowRoot);
+  if (!piWin)
+    return nsnull;
+
+  nsCOMPtr<nsPIWindowRoot> window = do_QueryInterface(piWin->GetChromeEventHandler());
+  return window.forget();
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::Scroll(PRInt32 aXScroll, PRInt32 aYScroll)
 {
   return ScrollTo(aXScroll, aYScroll);
 }
 
@@ -6856,37 +6856,16 @@ nsGlobalWindow::SetChromeEventHandler(ns
     // Need the cast to be able to call the protected method on a
     // superclass. We could make the method public instead, but it's really
     // better this way.
     static_cast<nsGlobalWindow*>(mOuterWindow)->
       SetChromeEventHandlerInternal(aChromeEventHandler);
   }
 }
 
-nsIFocusController*
-nsGlobalWindow::GetRootFocusController()
-{
-  nsIDOMWindowInternal* rootWindow = nsGlobalWindow::GetPrivateRoot();
-  nsCOMPtr<nsIFocusController> fc;
-
-  nsCOMPtr<nsPIDOMWindow> piWin(do_QueryInterface(rootWindow));
-  if (piWin) {
-    // Obtain the chrome event handler.
-    nsPIDOMEventTarget* chromeHandler = piWin->GetChromeEventHandler();
-    nsCOMPtr<nsPIWindowRoot> windowRoot(do_QueryInterface(chromeHandler));
-    if (windowRoot) {
-      windowRoot->GetFocusController(getter_AddRefs(fc));
-    }
-  }
-
-  // this reference is going away, but the root (if found) holds onto
-  // it
-  return fc;
-}
-
 nsIContent*
 nsGlobalWindow::GetFocusedNode()
 {
   FORWARD_TO_INNER(GetFocusedNode, (), NS_OK);
 
   return mFocusedNode;
 }
 
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -284,17 +284,16 @@ public:
 
   // nsIDOMNSEventTarget
   NS_DECL_NSIDOMNSEVENTTARGET
 
   // nsPIDOMWindow
   virtual NS_HIDDEN_(nsPIDOMWindow*) GetPrivateRoot();
   virtual NS_HIDDEN_(void) ActivateOrDeactivate(PRBool aActivate);
   virtual NS_HIDDEN_(void) SetChromeEventHandler(nsPIDOMEventTarget* aChromeEventHandler);
-  virtual NS_HIDDEN_(nsIFocusController*) GetRootFocusController();
 
   virtual NS_HIDDEN_(void) SetOpenerScriptPrincipal(nsIPrincipal* aPrincipal);
   virtual NS_HIDDEN_(nsIPrincipal*) GetOpenerScriptPrincipal();
 
   virtual NS_HIDDEN_(PopupControlState) PushPopupControlState(PopupControlState state, PRBool aForce) const;
   virtual NS_HIDDEN_(void) PopPopupControlState(PopupControlState state) const;
   virtual NS_HIDDEN_(PopupControlState) GetPopupControlState() const;
 
@@ -658,16 +657,18 @@ protected:
   virtual void SetFocusedNode(nsIContent* aNode,
                               PRUint32 aFocusMethod = 0,
                               PRBool aNeedsFocus = PR_FALSE);
 
   virtual PRUint32 GetFocusMethod();
 
   void UpdateCanvasFocus(PRBool aFocusChanged, nsIContent* aNewContent);
 
+  already_AddRefed<nsPIWindowRoot> GetTopWindowRoot();
+
   static void NotifyDOMWindowDestroyed(nsGlobalWindow* aWindow);
 
   // When adding new member variables, be careful not to create cycles
   // through JavaScript.  If there is any chance that a member variable
   // could own objects that are implemented in JavaScript, then those
   // objects will keep the global object (this object) alive.  To prevent
   // these cycles, ownership of such members must be released in
   // |CleanUp| and |SetDocShell|.
deleted file mode 100644
--- a/dom/base/nsIFocusController.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * vim: set ts=3 sw=2 et tw=80:
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla 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/MPL/
- *
- * 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 the Mozilla browser.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications, Inc.
- * Portions created by the Initial Developer are Copyright (C) 1999
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   David W. Hyatt <hyatt@netscape.com> (Original Author)
- *   Dan Rosen <dr@netscape.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef nsIFocusController_h__
-#define nsIFocusController_h__
-
-#include "nsISupports.h"
-#include "nsCOMPtr.h"
-
-class nsPIDOMWindow;
-class nsIDOMNode;
-class nsIController;
-class nsIControllers;
-
-// 6D733829-8AE4-43BD-BEEE-35420FE3E932
-#define NS_IFOCUSCONTROLLER_IID \
-{ 0x6d733829, 0x8ae4, 0x43bd, \
-  { 0xbe, 0xee, 0x35, 0x42, 0x0f, 0xe3, 0xe9, 0x32 } }
-
-class nsIFocusController : public nsISupports {
-public:
-  NS_DECLARE_STATIC_IID_ACCESSOR(NS_IFOCUSCONTROLLER_IID)
-
-  NS_IMETHOD GetPopupNode(nsIDOMNode** aNode)=0;
-  NS_IMETHOD SetPopupNode(nsIDOMNode* aNode)=0;
-
-  NS_IMETHOD GetControllerForCommand(nsPIDOMWindow* aContextWindow,
-                                     const char * aCommand,
-                                     nsIController** aResult)=0;
-  NS_IMETHOD GetControllers(nsPIDOMWindow* aContextWindow, nsIControllers** aResult)=0;
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsIFocusController, NS_IFOCUSCONTROLLER_IID)
-
-#endif // nsIFocusController_h__
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -62,39 +62,42 @@ class nsIPrincipal;
 enum PopupControlState {
   openAllowed = 0,  // open that window without worries
   openControlled,   // it's a popup, but allow it
   openAbused,       // it's a popup. disallow it, but allow domain override.
   openOverridden    // disallow window open
 };
 
 class nsIDocShell;
-class nsIFocusController;
 class nsIContent;
 class nsIDocument;
 class nsIScriptTimeoutHandler;
 class nsPresContext;
 struct nsTimeout;
 class nsScriptObjectHolder;
 class nsXBLPrototypeHandler;
 class nsIArray;
+class nsPIWindowRoot;
 
 #define NS_PIDOMWINDOW_IID \
-{ 0xeee92d9a, 0xae9f, 0x41e5, \
-  { 0x95, 0x5f, 0xaf, 0x1c, 0xe7, 0x66, 0x42, 0xe6 } }
+{ 0x2962cfa4, 0x13f9, 0x4606, \
+  { 0x84, 0x64, 0xef, 0x4c, 0xfa, 0x33, 0xcc, 0xce } }
 
 class nsPIDOMWindow : public nsIDOMWindowInternal
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_PIDOMWINDOW_IID)
 
   virtual nsPIDOMWindow* GetPrivateRoot() = 0;
 
   virtual void ActivateOrDeactivate(PRBool aActivate) = 0;
 
+  // this is called GetTopWindowRoot to avoid conflicts with nsIDOMWindow2::GetWindowRoot
+  virtual already_AddRefed<nsPIWindowRoot> GetTopWindowRoot() = 0;
+
   nsPIDOMEventTarget* GetChromeEventHandler() const
   {
     return mChromeEventHandler;
   }
 
   virtual void SetChromeEventHandler(nsPIDOMEventTarget* aChromeEventHandler) = 0;
 
   PRBool HasMutationListeners(PRUint32 aMutationEventType) const
@@ -142,18 +145,16 @@ public:
       }
 
       win = this;
     }
 
     win->mMutationBits |= aType;
   }
 
-  virtual nsIFocusController* GetRootFocusController() = 0;
-
   // GetExtantDocument provides a backdoor to the DOM GetDocument accessor
   nsIDOMDocument* GetExtantDocument() const
   {
     return mDocument;
   }
 
   // Internal getter/setter for the frame element, this version of the
   // getter crosses chrome boundaries whereas the public scriptable
--- a/dom/base/nsPIWindowRoot.h
+++ b/dom/base/nsPIWindowRoot.h
@@ -38,28 +38,34 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsPIWindowRoot_h__
 #define nsPIWindowRoot_h__
 
 #include "nsISupports.h"
 #include "nsPIDOMEventTarget.h"
 
-class nsIDOMWindow;
-class nsIFocusController;
+class nsPIDOMWindow;
+class nsIControllers;
+class nsIController;
 
-// 440f8d32-818d-468a-ac75-5916fa1ea198
+// 313C1D52-88F1-46C7-B35C-4E71EC1B01F3
 #define NS_IWINDOWROOT_IID \
-{ 0x440f8d32, 0x818d, 0x468a, \
-  { 0xac, 0x75, 0x59, 0x16, 0xfa, 0x1e, 0xa1, 0x98 } }
+{ 0x313c1d52, 0x88f1, 0x46c7, \
+  { 0xb3, 0x5c, 0x4e, 0x71, 0xec, 0x1b, 0x01, 0xf3 } }
 
 class nsPIWindowRoot : public nsPIDOMEventTarget {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IWINDOWROOT_IID)
 
-  NS_IMETHOD GetFocusController(nsIFocusController** aResult)=0;
+  virtual nsPIDOMWindow* GetWindow()=0;
 
-  virtual nsIDOMWindow* GetWindow()=0;
+  virtual void GetPopupNode(nsIDOMNode** aNode) = 0;
+  virtual void SetPopupNode(nsIDOMNode* aNode) = 0;
+
+  virtual nsresult GetControllerForCommand(const char *aCommand,
+                                           nsIController** aResult) = 0;
+  virtual nsresult GetControllers(nsIControllers** aResult) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsPIWindowRoot, NS_IWINDOWROOT_IID)
 
 #endif // nsPIWindowRoot_h__
--- a/dom/base/nsWindowRoot.cpp
+++ b/dom/base/nsWindowRoot.cpp
@@ -34,53 +34,59 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsCOMPtr.h"
 #include "nsWindowRoot.h"
+#include "nsPIDOMWindow.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMDocument.h"
 #include "nsIDocument.h"
 #include "nsIEventListenerManager.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsLayoutCID.h"
 #include "nsContentCID.h"
 #include "nsIEventStateManager.h"
 #include "nsIPrivateDOMEvent.h"
 #include "nsIDOMWindowInternal.h"
-#include "nsFocusController.h"
 #include "nsString.h"
 #include "nsEventDispatcher.h"
 #include "nsIProgrammingLanguage.h"
 #include "nsGUIEvent.h"
+#include "nsGlobalWindow.h"
+#include "nsFocusManager.h"
+#include "nsIDOMNSHTMLInputElement.h"
+#include "nsIDOMNSHTMLTextAreaElement.h"
+#include "nsIControllers.h"
 
 #include "nsCycleCollectionParticipant.h"
 
+#ifdef MOZ_XUL
+#include "nsIDOMXULElement.h"
+#endif
+
 static NS_DEFINE_CID(kEventListenerManagerCID,    NS_EVENTLISTENERMANAGER_CID);
 
-nsWindowRoot::nsWindowRoot(nsIDOMWindow* aWindow)
+nsWindowRoot::nsWindowRoot(nsPIDOMWindow* aWindow)
 {
   mWindow = aWindow;
-
-  // Create and init our focus controller.
-  nsFocusController::Create(getter_AddRefs(mFocusController));
 }
 
 nsWindowRoot::~nsWindowRoot()
 {
   if (mListenerManager) {
     mListenerManager->Disconnect();
   }
 }
 
-NS_IMPL_CYCLE_COLLECTION_2(nsWindowRoot, mListenerManager, mFocusController)
+NS_IMPL_CYCLE_COLLECTION_2(nsWindowRoot, mListenerManager, mPopupNode)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsWindowRoot)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMEventTarget)
   NS_INTERFACE_MAP_ENTRY(nsPIDOMEventTarget)
   NS_INTERFACE_MAP_ENTRY(nsPIWindowRoot)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
   NS_INTERFACE_MAP_ENTRY(nsIDOM3EventTarget)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNSEventTarget)
@@ -226,35 +232,27 @@ nsWindowRoot::GetSystemEventGroup(nsIDOM
 
 
 nsresult
 nsWindowRoot::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
 {
   aVisitor.mCanHandle = PR_TRUE;
   aVisitor.mForceContentDispatch = PR_TRUE; //FIXME! Bug 329119
   // To keep mWindow alive
-  aVisitor.mItemData = mWindow;
+  aVisitor.mItemData = static_cast<nsISupports *>(mWindow);
   return NS_OK;
 }
 
 nsresult
 nsWindowRoot::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
 {
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsWindowRoot::GetFocusController(nsIFocusController** aResult)
-{
-  *aResult = mFocusController;
-  NS_IF_ADDREF(*aResult);
-  return NS_OK;
-}
-
-nsIDOMWindow*
+nsPIDOMWindow*
 nsWindowRoot::GetWindow()
 {
   return mWindow;
 }
 
 NS_IMETHODIMP
 nsWindowRoot::GetScriptTypeID(PRUint32 *aScriptType)
 {
@@ -264,19 +262,118 @@ nsWindowRoot::GetScriptTypeID(PRUint32 *
 
 NS_IMETHODIMP
 nsWindowRoot::SetScriptTypeID(PRUint32 aScriptType)
 {
     NS_ERROR("Can't change default script type for a document");
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
+nsresult
+nsWindowRoot::GetControllers(nsIControllers** aResult)
+{
+  *aResult = nsnull;
+
+  // XXX: we should fix this so there's a generic interface that
+  // describes controllers, so this code would have no special
+  // knowledge of what object might have controllers.
+
+  nsCOMPtr<nsPIDOMWindow> focusedWindow;
+  nsIContent* focusedContent =
+    nsFocusManager::GetFocusedDescendant(mWindow, PR_TRUE, getter_AddRefs(focusedWindow));
+  if (focusedContent) {
+#ifdef MOZ_XUL
+    nsCOMPtr<nsIDOMXULElement> xulElement(do_QueryInterface(focusedContent));
+    if (xulElement)
+      return xulElement->GetControllers(aResult);
+#endif
+
+    nsCOMPtr<nsIDOMNSHTMLTextAreaElement> htmlTextArea =
+      do_QueryInterface(focusedContent);
+    if (htmlTextArea)
+      return htmlTextArea->GetControllers(aResult);
+
+    nsCOMPtr<nsIDOMNSHTMLInputElement> htmlInputElement =
+      do_QueryInterface(focusedContent);
+    if (htmlInputElement)
+      return htmlInputElement->GetControllers(aResult);
+
+    if (focusedContent->IsEditable() && focusedWindow)
+      return focusedWindow->GetControllers(aResult);
+  }
+  else {
+    nsCOMPtr<nsIDOMWindowInternal> domWindow = do_QueryInterface(focusedWindow);
+    if (domWindow)
+      return domWindow->GetControllers(aResult);
+  }
+
+  return NS_OK;
+}
+
+nsresult
+nsWindowRoot::GetControllerForCommand(const char * aCommand,
+                                      nsIController** _retval)
+{
+  NS_ENSURE_ARG_POINTER(_retval);
+  *_retval = nsnull;
+
+  nsCOMPtr<nsIControllers> controllers;
+  nsCOMPtr<nsIController> controller;
+
+  GetControllers(getter_AddRefs(controllers));
+  if (controllers) {
+    controllers->GetControllerForCommand(aCommand, getter_AddRefs(controller));
+    if (controller) {
+      controller.swap(*_retval);
+      return NS_OK;
+    }
+  }
+
+  nsCOMPtr<nsPIDOMWindow> focusedWindow;
+  nsFocusManager::GetFocusedDescendant(mWindow, PR_TRUE, getter_AddRefs(focusedWindow));
+  while (focusedWindow) {
+    nsCOMPtr<nsIDOMWindowInternal> domWindow(do_QueryInterface(focusedWindow));
+
+    nsCOMPtr<nsIControllers> controllers2;
+    domWindow->GetControllers(getter_AddRefs(controllers2));
+    if (controllers2) {
+      controllers2->GetControllerForCommand(aCommand,
+                                            getter_AddRefs(controller));
+      if (controller) {
+        controller.swap(*_retval);
+        return NS_OK;
+      }
+    }
+
+    // XXXndeakin P3 is this casting safe?
+    nsCOMPtr<nsPIDOMWindow> piWindow = do_QueryInterface(focusedWindow); 
+    nsGlobalWindow *win =
+      static_cast<nsGlobalWindow *>
+                 (static_cast<nsIDOMWindowInternal *>(piWindow));
+    focusedWindow = win->GetPrivateParent();
+  }
+  
+  return NS_OK;
+}
+
+void
+nsWindowRoot::GetPopupNode(nsIDOMNode** aNode)
+{
+  NS_IF_ADDREF(*aNode = mPopupNode);
+}
+
+void
+nsWindowRoot::SetPopupNode(nsIDOMNode* aNode)
+{
+  mPopupNode = aNode;
+}
+
 ///////////////////////////////////////////////////////////////////////////////////
 
 nsresult
-NS_NewWindowRoot(nsIDOMWindow* aWindow, nsPIDOMEventTarget** aResult)
+NS_NewWindowRoot(nsPIDOMWindow* aWindow, nsPIDOMEventTarget** aResult)
 {
   *aResult = new nsWindowRoot(aWindow);
   if (!*aResult)
     return NS_ERROR_OUT_OF_MEMORY;
   NS_ADDREF(*aResult);
   return NS_OK;
 }
--- a/dom/base/nsWindowRoot.h
+++ b/dom/base/nsWindowRoot.h
@@ -35,39 +35,38 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsWindowRoot_h__
 #define nsWindowRoot_h__
 
-class nsIDOMWindow;
+class nsPIDOMWindow;
 class nsIDOMEventListener;
 class nsIEventListenerManager;
 class nsIDOMEvent;
 class nsEventChainPreVisitor;
 class nsEventChainPostVisitor;
 
 #include "nsIDOMEventTarget.h"
 #include "nsIDOM3EventTarget.h"
 #include "nsIDOMNSEventTarget.h"
 #include "nsIEventListenerManager.h"
 #include "nsPIWindowRoot.h"
-#include "nsIFocusController.h"
 #include "nsIDOMEventTarget.h"
 #include "nsCycleCollectionParticipant.h"
 
 class nsWindowRoot : public nsIDOMEventTarget,
                      public nsIDOM3EventTarget,
                      public nsIDOMNSEventTarget,
                      public nsPIWindowRoot
 {
 public:
-  nsWindowRoot(nsIDOMWindow* aWindow);
+  nsWindowRoot(nsPIDOMWindow* aWindow);
   virtual ~nsWindowRoot();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSIDOMEVENTTARGET
   NS_DECL_NSIDOM3EVENTTARGET
   NS_DECL_NSIDOMNSEVENTTARGET
 
   virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
@@ -84,27 +83,34 @@ public:
   virtual nsresult GetSystemEventGroup(nsIDOMEventGroup** aGroup);
   virtual nsIScriptContext* GetContextForEventHandlers(nsresult* aRv)
   {
     *aRv = NS_OK;
     return nsnull;
   }
 
   // nsPIWindowRoot
-  NS_IMETHOD GetFocusController(nsIFocusController** aResult);
+
+  virtual nsPIDOMWindow* GetWindow();
 
-  virtual nsIDOMWindow* GetWindow();
+  virtual nsresult GetControllers(nsIControllers** aResult);
+  virtual nsresult GetControllerForCommand(const char * aCommand,
+                                           nsIController** _retval);
+
+  virtual void GetPopupNode(nsIDOMNode** aNode);
+  virtual void SetPopupNode(nsIDOMNode* aNode);
 
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsWindowRoot, nsIDOMEventTarget)
 
 protected:
   // Members
-  nsIDOMWindow* mWindow; // [Weak]. The window will hold on to us and let go when it dies.
+  nsPIDOMWindow* mWindow; // [Weak]. The window will hold on to us and let go when it dies.
   nsCOMPtr<nsIEventListenerManager> mListenerManager; // [Strong]. We own the manager, which owns event listeners attached
                                                       // to us.
-  nsCOMPtr<nsIFocusController> mFocusController; // The focus controller for the root.
+
+  nsCOMPtr<nsIDOMNode> mPopupNode; // [OWNER]
 };
 
 extern nsresult
-NS_NewWindowRoot(nsIDOMWindow* aWindow,
+NS_NewWindowRoot(nsPIDOMWindow* aWindow,
                  nsPIDOMEventTarget** aResult);
 
 #endif
--- a/embedding/browser/gtk/src/EmbedPrivate.cpp
+++ b/embedding/browser/gtk/src/EmbedPrivate.cpp
@@ -62,19 +62,16 @@
 // and when chrome windows finish loading
 #include "nsIDOMWindow.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMWindowInternal.h"
 
 // For seting scrollbar visibilty
 #include "nsIDOMBarProp.h"
 
-// for the focus hacking we need to do
-#include "nsIFocusController.h"
-
 // app component registration
 #include "nsIGenericFactory.h"
 #include "nsIComponentRegistrar.h"
 
 // all of our local includes
 #include "EmbedPrivate.h"
 #include "EmbedWindow.h"
 #include "EmbedProgress.h"
--- a/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp
+++ b/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp
@@ -84,18 +84,18 @@
 #include "nsIDOMHTMLObjectElement.h"
 #include "nsIDOMHTMLEmbedElement.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIImageLoadingContent.h"
 #include "nsIWebNavigation.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIPresShell.h"
 #include "nsPIDOMWindow.h"
+#include "nsPIWindowRoot.h"
 #include "nsIDOMWindowCollection.h"
-#include "nsIFocusController.h"
 #include "nsIWindowWatcher.h"
 #include "nsPIWindowWatcher.h"
 #include "nsIPrompt.h"
 #include "nsRect.h"
 #include "nsIWebBrowserChromeFocus.h"
 #include "nsIContent.h"
 #include "imgIContainer.h"
 #include "nsContextMenuInfo.h"
@@ -1797,26 +1797,25 @@ ChromeContextMenuListener::ContextMenu(n
   // we need to cache the event target into the focus controller's popupNode
   // so we can get at it later from command code, etc.:
 
   // get the dom window
   nsCOMPtr<nsIDOMWindow> win;
   res = mWebBrowser->GetContentDOMWindow(getter_AddRefs(win));
   NS_ENSURE_SUCCESS(res, res);
   NS_ENSURE_TRUE(win, NS_ERROR_FAILURE);
-  // get the private dom window
-  nsCOMPtr<nsPIDOMWindow> privateWin(do_QueryInterface(win, &res));
-  NS_ENSURE_SUCCESS(res, res);
-  NS_ENSURE_TRUE(privateWin, NS_ERROR_FAILURE);
-  // get the focus controller
-  nsIFocusController *focusController = privateWin->GetRootFocusController();
-  NS_ENSURE_TRUE(focusController, NS_ERROR_FAILURE);
-  // set the focus controller's popup node to the event target
-  res = focusController->SetPopupNode(targetDOMnode);
-  NS_ENSURE_SUCCESS(res, res);
+
+  nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(win));
+  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
+  nsCOMPtr<nsPIWindowRoot> root = window->GetTopWindowRoot();
+  NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
+  if (root) {
+    // set the window root's popup node to the event target
+    root->SetPopupNode(targetDOMnode);
+  }
 
   // Tell the listener all about the event
   if ( menuListener2 ) {
     menuInfoImpl->SetMouseEvent(aMouseEvent);
     menuInfoImpl->SetDOMNode(targetDOMnode);
     menuListener2->OnShowContextMenu(flags2, menuInfo);
   }
   else {
--- a/embedding/components/commandhandler/src/nsCommandManager.cpp
+++ b/embedding/components/commandhandler/src/nsCommandManager.cpp
@@ -45,19 +45,20 @@
 #include "nsIComponentManager.h"
 
 #include "nsServiceManagerUtils.h"
 #include "nsIScriptSecurityManager.h"
 
 #include "nsIDOMDocument.h"
 #include "nsIDOMWindow.h"
 #include "nsPIDOMWindow.h"
+#include "nsPIWindowRoot.h"
 #include "nsIDOMWindowInternal.h"
-#include "nsIFocusController.h"
 #include "nsIFocusManager.h"
+#include "nsIDOMEventTarget.h"
 
 #include "nsCOMArray.h"
 
 #include "nsCommandManager.h"
 
 
 nsCommandManager::nsCommandManager()
 : mWindow(nsnull)
@@ -331,22 +332,17 @@ nsCommandManager::GetControllerForComman
       return rv;
     if (!controllers)
       return NS_ERROR_FAILURE;
 
     // dispatch the command
     return controllers->GetControllerForCommand(aCommand, outController);
   }
 
-
-  // else we're not targeted to a particular window so use focus
-  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mWindow);
-  if (!window)
-    return NS_ERROR_FAILURE;
-
-  nsIFocusController *focusController = window->GetRootFocusController();
-  if (!focusController)
-    return NS_ERROR_FAILURE;
+  nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mWindow));
+  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
+  nsCOMPtr<nsPIWindowRoot> root = window->GetTopWindowRoot();
+  NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
 
   // no target window; send command to focus controller
-  return focusController->GetControllerForCommand(window, aCommand, outController);
+  return root->GetControllerForCommand(aCommand, outController);
 }
 
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -112,18 +112,18 @@
 #include "nsIXULDocument.h"
 #include "nsXULPopupManager.h"
 #endif
 #include "nsPrintfCString.h"
 
 #include "nsIClipboardHelper.h"
 
 #include "nsPIDOMWindow.h"
+#include "nsPIWindowRoot.h"
 #include "nsJSEnvironment.h"
-#include "nsIFocusController.h"
 #include "nsFocusManager.h"
 
 #include "nsIScrollableFrame.h"
 #include "nsIHTMLDocument.h"
 #include "nsITimelineService.h"
 #include "nsGfxCIID.h"
 #include "nsStyleSheetService.h"
 #include "nsURILoader.h"
@@ -3351,27 +3351,26 @@ nsresult
 DocumentViewerImpl::GetPopupNode(nsIDOMNode** aNode)
 {
   NS_ENSURE_ARG_POINTER(aNode);
 
   // get the document
   nsIDocument* document = GetDocument();
   NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
 
-
   // get the private dom window
-  nsPIDOMWindow *privateWin = document->GetWindow();
-  NS_ENSURE_TRUE(privateWin, NS_ERROR_NOT_AVAILABLE);
-
-  // get the focus controller
-  nsIFocusController *focusController = privateWin->GetRootFocusController();
-  NS_ENSURE_TRUE(focusController, NS_ERROR_FAILURE);
-
-  // get the popup node
-  focusController->GetPopupNode(aNode); // addref happens here
+  nsCOMPtr<nsPIDOMWindow> window(document->GetWindow());
+  NS_ENSURE_TRUE(window, NS_ERROR_NOT_AVAILABLE);
+  if (window) {
+    nsCOMPtr<nsPIWindowRoot> root = window->GetTopWindowRoot();
+    NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
+
+    // get the popup node
+    root->GetPopupNode(aNode); // addref happens here
+  }
 
   return NS_OK;
 }
 
 // GetPopupLinkNode: return popup link node or fail
 nsresult
 DocumentViewerImpl::GetPopupLinkNode(nsIDOMNode** aNode)
 {