Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
authorNeil Deakin <neil@mozilla.com>
Wed, 10 Jun 2009 14:00:39 -0400
changeset 29018 cabb8925dcd3d831a244b01e0a37c29b8793c77b
parent 29017 771509552a2ed09a31a27b3983bbe68df1393296
child 29019 524477378eb1639b10f545d80ed47c6f84380cf7
push idunknown
push userunknown
push dateunknown
reviewersjosh, smichaud, ere, dbaron, marco, neil, gavin, smaug, smaug
bugs178324
milestone1.9.2a1pre
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
accessible/src/base/nsAccessNode.cpp
accessible/src/base/nsAccessible.cpp
accessible/src/base/nsDocAccessible.cpp
accessible/src/base/nsRootAccessible.cpp
browser/base/content/browser.xul
browser/base/content/tabbrowser.xml
browser/base/content/test/Makefile.in
browser/base/content/test/browser_bug481560.js
browser/base/content/test/browser_tabfocus.js
browser/base/content/utilityOverlay.js
content/base/public/nsIContent.h
content/base/src/nsDocument.cpp
content/base/src/nsGenericElement.cpp
content/base/src/nsGenericElement.h
content/events/public/nsIEventStateManager.h
content/events/src/nsDOMEvent.cpp
content/events/src/nsEventListenerManager.cpp
content/events/src/nsEventStateManager.cpp
content/events/src/nsEventStateManager.h
content/events/src/nsIMEStateManager.cpp
content/events/src/nsIMEStateManager.h
content/events/test/test_bug450876.html
content/html/content/src/nsGenericHTMLElement.cpp
content/html/content/src/nsGenericHTMLElement.h
content/html/content/src/nsHTMLAnchorElement.cpp
content/html/content/src/nsHTMLAreaElement.cpp
content/html/content/src/nsHTMLButtonElement.cpp
content/html/content/src/nsHTMLInputElement.cpp
content/html/content/src/nsHTMLLabelElement.cpp
content/html/content/src/nsHTMLLegendElement.cpp
content/html/content/src/nsHTMLSelectElement.cpp
content/html/content/src/nsHTMLSelectElement.h
content/html/content/src/nsHTMLTextAreaElement.cpp
content/xbl/src/nsXBLPrototypeHandler.cpp
content/xbl/src/nsXBLWindowKeyHandler.cpp
content/xtf/src/nsXTFElementWrapper.cpp
content/xul/content/src/Makefile.in
content/xul/content/src/nsXULElement.cpp
content/xul/content/src/nsXULElement.h
content/xul/content/src/nsXULPopupListener.cpp
content/xul/content/test/test_bug398289.html
content/xul/document/src/nsXULCommandDispatcher.cpp
content/xul/document/src/nsXULCommandDispatcher.h
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
docshell/base/nsIDocShell.idl
docshell/test/chrome/test_bug454235.xul
dom/base/Makefile.in
dom/base/crashtests/473284.xul
dom/base/nsDOMWindowUtils.cpp
dom/base/nsFocusController.cpp
dom/base/nsFocusController.h
dom/base/nsFocusManager.cpp
dom/base/nsFocusManager.h
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/base/nsGlobalWindowCommands.cpp
dom/base/nsIFocusController.h
dom/base/nsPIDOMWindow.h
dom/base/nsWindowRoot.cpp
dom/dom-config.mk
dom/interfaces/base/Makefile.in
dom/interfaces/base/nsIDOMWindowUtils.idl
dom/interfaces/base/nsIFocusManager.idl
dom/tests/mochitest/chrome/Makefile.in
dom/tests/mochitest/chrome/child_focus_frame.html
dom/tests/mochitest/chrome/focus_frameset.html
dom/tests/mochitest/chrome/focus_window2.xul
dom/tests/mochitest/chrome/test_focus.xul
dom/tests/mochitest/chrome/window_focus.xul
editor/libeditor/text/nsEditorEventListeners.cpp
editor/libeditor/text/nsEditorEventListeners.h
embedding/browser/webBrowser/nsWebBrowser.cpp
embedding/components/commandhandler/src/nsCommandManager.cpp
embedding/components/find/src/nsWebBrowserFind.cpp
embedding/components/windowwatcher/src/nsWindowWatcher.cpp
embedding/components/windowwatcher/src/nsWindowWatcher.h
layout/base/Makefile.in
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSFrameConstructor.h
layout/base/nsDocumentViewer.cpp
layout/base/nsFocusEventSuppressor.cpp
layout/base/nsIFocusEventSuppressor.h
layout/base/nsIPresShell.h
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
layout/base/nsPresShell.cpp
layout/build/nsLayoutCID.h
layout/build/nsLayoutModule.cpp
layout/build/nsLayoutStatics.cpp
layout/forms/nsFileControlFrame.cpp
layout/forms/nsTextControlFrame.cpp
layout/generic/nsContainerFrame.cpp
layout/generic/nsHTMLFrame.cpp
layout/generic/nsObjectFrame.cpp
layout/printing/Makefile.in
layout/printing/nsPrintEngine.cpp
layout/printing/nsPrintPreviewListener.cpp
layout/xul/base/src/Makefile.in
layout/xul/base/src/nsXULPopupManager.cpp
modules/plugin/base/src/nsPluginNativeWindowWin.cpp
toolkit/components/passwordmgr/test/browser/browser_passwordmgrdlg.js
toolkit/components/printing/content/printUtils.js
toolkit/components/typeaheadfind/src/nsTypeAheadFind.cpp
toolkit/content/tests/chrome/test_autocomplete2.xul
toolkit/content/tests/widgets/Makefile.in
toolkit/content/tests/widgets/test_focus_anons.xul
toolkit/content/tests/widgets/test_tabindex.xul
toolkit/content/widgets/browser.xml
toolkit/content/widgets/findbar.xml
toolkit/content/widgets/menulist.xml
toolkit/content/widgets/scale.xml
toolkit/mozapps/downloads/tests/chrome/test_select_all.xul
toolkit/themes/pinstripe/global/menulist.css
view/src/nsView.cpp
view/src/nsViewManager.cpp
view/src/nsViewManager.h
widget/public/nsGUIEvent.h
widget/src/beos/nsWindow.cpp
widget/src/cocoa/nsChildView.h
widget/src/cocoa/nsChildView.mm
widget/src/cocoa/nsCocoaWindow.h
widget/src/cocoa/nsCocoaWindow.mm
widget/src/cocoa/nsWindowMap.h
widget/src/cocoa/nsWindowMap.mm
widget/src/gtk2/nsWindow.cpp
widget/src/gtk2/nsWindow.h
widget/src/os2/nsFrameWindow.cpp
widget/src/os2/nsWindow.cpp
widget/src/os2/nsWindow.h
widget/src/photon/nsWidget.cpp
widget/src/qt/nsWindow.cpp
widget/src/qt/nsWindow.h
widget/src/windows/nsWindow.cpp
widget/src/windows/nsWindow.h
widget/src/xpwidgets/nsBaseWidget.cpp
widget/tests/test_imestate.html
xpfe/appshell/src/nsWebShellWindow.cpp
xpfe/appshell/src/nsWebShellWindow.h
--- a/accessible/src/base/nsAccessNode.cpp
+++ b/accessible/src/base/nsAccessNode.cpp
@@ -61,17 +61,17 @@
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsPresContext.h"
 #include "nsIPresShell.h"
 #include "nsIServiceManager.h"
 #include "nsIStringBundle.h"
 #include "nsITimer.h"
 #include "nsRootAccessible.h"
-#include "nsIFocusController.h"
+#include "nsFocusManager.h"
 #include "nsIObserverService.h"
 
 #ifdef MOZ_ACCESSIBILITY_ATK
 #include "nsAppRootAccessible.h"
 #else
 #include "nsApplicationAccessibleWrap.h"
 #endif
 
@@ -771,43 +771,34 @@ nsAccessNode::ClearCache(nsAccessNodeHas
 
 already_AddRefed<nsIDOMNode> nsAccessNode::GetCurrentFocus()
 {
   nsCOMPtr<nsIPresShell> shell = nsCoreUtils::GetPresShellFor(mDOMNode);
   NS_ENSURE_TRUE(shell, nsnull);
   nsCOMPtr<nsIDocument> doc = shell->GetDocument();
   NS_ENSURE_TRUE(doc, nsnull);
 
-  nsCOMPtr<nsPIDOMWindow> privateDOMWindow(do_QueryInterface(doc->GetWindow()));
-  if (!privateDOMWindow) {
-    return nsnull;
-  }
-  nsIFocusController *focusController = privateDOMWindow->GetRootFocusController();
-  if (!focusController) {
-    return nsnull;
-  }
+  nsIDOMWindow* win = doc->GetWindow();
+
+  nsCOMPtr<nsIDOMWindow> focusedWindow;
   nsCOMPtr<nsIDOMElement> focusedElement;
-  focusController->GetFocusedElement(getter_AddRefs(focusedElement));
+  nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
+  if (fm)
+    fm->GetFocusedElementForWindow(win, PR_TRUE, getter_AddRefs(focusedWindow),
+                                   getter_AddRefs(focusedElement));
+
   nsIDOMNode *focusedNode = nsnull;
-  if (!focusedElement) {
-    // Document itself has focus
-    nsCOMPtr<nsIDOMWindowInternal> focusedWinInternal;
-    focusController->GetFocusedWindow(getter_AddRefs(focusedWinInternal));
-    if (!focusedWinInternal) {
-      return nsnull;
-    }
-    nsCOMPtr<nsIDOMDocument> focusedDOMDocument;
-    focusedWinInternal->GetDocument(getter_AddRefs(focusedDOMDocument));
-    if (!focusedDOMDocument) {
-      return nsnull;
-    }
-    focusedDOMDocument->QueryInterface(NS_GET_IID(nsIDOMNode), (void**)&focusedNode);
+  if (focusedElement) {
+    CallQueryInterface(focusedElement, &focusedNode);
   }
-  else {
-    focusedElement->QueryInterface(NS_GET_IID(nsIDOMNode), (void**)&focusedNode);
+  else if (focusedWindow) {
+    nsCOMPtr<nsIDOMDocument> doc;
+    focusedWindow->GetDocument(getter_AddRefs(doc));
+    if (doc)
+      CallQueryInterface(doc, &focusedNode);
   }
 
   return focusedNode;
 }
 
 NS_IMETHODIMP
 nsAccessNode::GetLanguage(nsAString& aLanguage)
 {
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -69,16 +69,17 @@
 #include "nsIFormControl.h"
 
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsIFrame.h"
 #include "nsIViewManager.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIScrollableFrame.h"
+#include "nsFocusManager.h"
 
 #include "nsXPIDLString.h"
 #include "nsUnicharUtils.h"
 #include "nsReadableUtils.h"
 #include "prdtoa.h"
 #include "nsIAtom.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
@@ -1464,24 +1465,21 @@ nsAccessible::TakeFocus()
                              nsAccessibilityAtoms::aria_activedescendant,
                              id, PR_TRUE);
           }
         }
       }
     }
   }
 
-  nsCOMPtr<nsIDOMNSHTMLElement> htmlElement(do_QueryInterface(content));
-  if (htmlElement) {
-    // HTML Elements also set the caret position
-    // in order to affect tabbing order
-    return htmlElement->Focus();
-  }
-
-  content->SetFocus(GetPresContext());
+  nsCOMPtr<nsIDOMElement> element(do_QueryInterface(content));
+  nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
+  if (fm)
+    fm->SetFocus(element, 0);
+
   return NS_OK;
 }
 
 nsresult
 nsAccessible::GetHTMLName(nsAString& aLabel)
 {
   nsCOMPtr<nsIContent> content = nsCoreUtils::GetRoleContent(mDOMNode);
   if (!content) {
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -63,17 +63,17 @@
 #include "nsIPresShell.h"
 #include "nsIServiceManager.h"
 #include "nsIScrollableView.h"
 #include "nsIViewManager.h"
 #include "nsIView.h"
 #include "nsUnicharUtils.h"
 #include "nsIURI.h"
 #include "nsIWebNavigation.h"
-#include "nsIFocusController.h"
+#include "nsFocusManager.h"
 #ifdef MOZ_XUL
 #include "nsIXULDocument.h"
 #endif
 
 //=============================//
 // nsDocAccessible  //
 //=============================//
 
@@ -345,16 +345,17 @@ nsDocAccessible::GetAttributes(nsIPersis
   if (mParent) {
     mParent->GetAttributes(aAttributes); // Add parent attributes (override inner)
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP nsDocAccessible::GetFocusedChild(nsIAccessible **aFocusedChild)
 {
+  // XXXndeakin P3 accessibility shouldn't be caching the focus
   if (!gLastFocusedNode) {
     *aFocusedChild = nsnull;
     return NS_OK;
   }
 
   // Return an accessible for the current global focus, which does not have to
   // be contained within the current document.
   nsCOMPtr<nsIAccessibilityService> accService =
@@ -366,35 +367,28 @@ NS_IMETHODIMP nsDocAccessible::TakeFocus
 {
   NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE);
   PRUint32 state;
   GetStateInternal(&state, nsnull);
   if (0 == (state & nsIAccessibleStates::STATE_FOCUSABLE)) {
     return NS_ERROR_FAILURE; // Not focusable
   }
 
-  nsCOMPtr<nsIDocShellTreeItem> treeItem =
-    nsCoreUtils::GetDocShellTreeItemFor(mDOMNode);
-  nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(treeItem);
-  NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
-
-  nsCOMPtr<nsIPresShell> shell(GetPresShell());
-  if (!shell) {
-    NS_WARNING("Was not shutdown properly via InvalidateCacheSubtree()");
-    return NS_ERROR_FAILURE;
+  nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
+  if (fm) {
+    nsCOMPtr<nsIDOMDocument> domDocument;
+    mDOMNode->GetOwnerDocument(getter_AddRefs(domDocument));
+    nsCOMPtr<nsIDocument> document(do_QueryInterface(domDocument));
+    if (document) {
+      // focus the document
+      nsCOMPtr<nsIDOMElement> newFocus;
+      fm->MoveFocus(document->GetWindow(), nsnull, nsIFocusManager::MOVEFOCUS_ROOT, 0,
+                    getter_AddRefs(newFocus));
+    }
   }
-  nsIEventStateManager *esm = shell->GetPresContext()->EventStateManager();
-  NS_ENSURE_TRUE(esm, NS_ERROR_FAILURE);
-
-  // Focus the document
-  nsresult rv = docShell->SetHasFocus(PR_TRUE);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Clear out any existing focus state
-  return esm->SetContentState(nsnull, NS_EVENT_STATE_FOCUS);
 }
 
 // ------- nsIAccessibleDocument Methods (5) ---------------
 
 NS_IMETHODIMP nsDocAccessible::GetURL(nsAString& aURL)
 {
   if (!mDocument) {
     return NS_ERROR_FAILURE; // Document has been shut down
--- a/accessible/src/base/nsRootAccessible.cpp
+++ b/accessible/src/base/nsRootAccessible.cpp
@@ -55,31 +55,31 @@
 #include "nsIDOMDataContainerEvent.h"
 #include "nsIDOMNSEvent.h"
 #include "nsIDOMXULMenuListElement.h"
 #include "nsIDOMXULMultSelectCntrlEl.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
 #include "nsIDOMXULPopupElement.h"
 #include "nsIDocument.h"
 #include "nsIEventListenerManager.h"
-#include "nsIFocusController.h"
 #include "nsIFrame.h"
 #include "nsIMenuFrame.h"
 #include "nsIHTMLDocument.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIScrollableView.h"
 #include "nsISelectionPrivate.h"
 #include "nsIServiceManager.h"
 #include "nsIViewManager.h"
 #include "nsPIDOMWindow.h"
 #include "nsIWebBrowserChrome.h"
 #include "nsReadableUtils.h"
 #include "nsRootAccessible.h"
 #include "nsIDOMNSEventTarget.h"
 #include "nsIDOMDocumentEvent.h"
+#include "nsFocusManager.h"
 
 #ifdef MOZ_XUL
 #include "nsXULTreeAccessible.h"
 #include "nsIXULDocument.h"
 #include "nsIXULWindow.h"
 #endif
 
 #ifdef MOZ_ACCESSIBILITY_ATK
@@ -229,26 +229,28 @@ nsRootAccessible::GetStateInternal(PRUin
   }
 #endif
 
   if (!aExtraState)
     return NS_OK;
 
   nsCOMPtr<nsIDOMWindow> domWin;
   GetWindow(getter_AddRefs(domWin));
-  nsCOMPtr<nsPIDOMWindow> privateDOMWindow(do_QueryInterface(domWin));
-  if (privateDOMWindow) {
-    nsIFocusController *focusController =
-      privateDOMWindow->GetRootFocusController();
-    if (focusController) {
-      PRBool isActive = PR_FALSE;
-      focusController->GetActive(&isActive);
-      if (isActive) {
+  nsCOMPtr<nsIDocShellTreeItem> dsti = do_GetInterface(domWin);
+  if (dsti) {
+    nsCOMPtr<nsIDocShellTreeItem> root;
+    dsti->GetRootTreeItem(getter_AddRefs(root));
+    nsCOMPtr<nsIDOMWindow> rootWindow = do_GetInterface(root);
+
+    nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
+    if (fm && rootWindow) {
+      nsCOMPtr<nsIDOMWindow> activeWindow;
+      fm->GetActiveWindow(getter_AddRefs(activeWindow));
+      if (activeWindow == rootWindow)
         *aExtraState |= nsIAccessibleStates::EXT_STATE_ACTIVE;
-      }
     }
   }
 #ifdef MOZ_XUL
   if (GetChromeFlags() & nsIWebBrowserChrome::CHROME_MODAL) {
     *aExtraState |= nsIAccessibleStates::EXT_STATE_MODAL;
   }
 #endif
 
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -365,17 +365,17 @@
                  newlines="stripsurroundingwhitespace"
                  oninput="gBrowser.userTypedValue = this.value;"
                  ontextentered="this.handleCommand(param);"
                  ontextreverted="return this.handleRevert();"
                  pageproxystate="invalid"
                  onsearchbegin="LocationBarHelpers._searchBegin();"
                  onsearchcomplete="LocationBarHelpers._searchComplete();"
                  onfocus="document.getElementById('identity-box').style.MozUserFocus= 'normal'"
-                 onblur="document.getElementById('identity-box').style.MozUserFocus = 'ignore';">
+                 onblur="setTimeout(function() document.getElementById('identity-box').style.MozUserFocus = '', 0);">
           <!-- Use onclick instead of normal popup= syntax since the popup
                code fires onmousedown, and hence eats our favicon drag events.
                We only add the identity-box button to the tab order when the location bar
                has focus, otherwise pressing F6 focuses it instead of the location bar -->
           <box id="identity-box" role="button"
                chromedir="&locale.dir;"
                onclick="gIdentityHandler.handleIdentityButtonEvent(event);"
                onkeypress="gIdentityHandler.handleIdentityButtonEvent(event);">
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -808,72 +808,28 @@
           <![CDATA[
             var newBrowser = this.getBrowserAtIndex(this.mTabContainer.selectedIndex);
             if (this.mCurrentBrowser == newBrowser && !aForceUpdate)
               return;
 
             if (this.mCurrentTab != this.selectedTab)
               this.mCurrentTab.owner = null;
 
-            if (this.mCurrentBrowser) {
-              // Only save the focused element if it is in our content window
-              // or in an ancestor window.
-              var focusedWindow = document.commandDispatcher.focusedWindow;
-              var saveFocus = false;
-
-              if (focusedWindow && focusedWindow.top == window.content) {
-                saveFocus = true;
-              } else {
-                var contentWindow = window;
-
-                while (contentWindow) {
-                  if (contentWindow == focusedWindow) {
-                    saveFocus = true;
-                    break;
-                  }
-
-                  if (contentWindow.parent == contentWindow) {
-                    break;
-                  }
-
-                  contentWindow = contentWindow.parent;
-                }
-              }
-
-              if (saveFocus) {
-                // Preserve the currently-focused element or DOM window for
-                // this tab.
-
-                this.mCurrentBrowser.focusedWindow = focusedWindow;
-                this.mCurrentBrowser.focusedElement = document.commandDispatcher.focusedElement;
-              }
-
-              if (this.mCurrentBrowser.focusedElement &&
-                  this.mCurrentBrowser.focusedElement.parentNode !=
-                  this.mCurrentTab.parentNode) {
-                // Clear focus outline before we draw on top of it.
-                // Only blur the focused element if it isn't a tab, 
-                // to avoid breaking keyboard tab navigation
-                var elem = this.mCurrentBrowser.focusedElement;
-                if (elem instanceof HTMLElement || elem instanceof XULElement) {
-                  elem.blur();
-                }
-                else {
-                  var content = elem.ownerDocument.defaultView;
-                  if (content instanceof Components.interfaces.nsIInterfaceRequestor)
-                    content.getInterface(Components.interfaces.nsIDOMWindowUtils).focus(null);
-                }
-              }
-              this.mCurrentBrowser.setAttribute("type", "content-targetable");
-            }
+            var fm = Components.classes["@mozilla.org/focus-manager;1"].
+                       getService(Components.interfaces.nsIFocusManager);
+            var focusedChromeElement = fm.getFocusedElementForWindow(window, false, {});
+
+            var oldBrowser = this.mCurrentBrowser;
+            if (oldBrowser)
+              oldBrowser.setAttribute("type", "content-targetable");
 
             var updatePageReport = false;
-            if (!this.mCurrentBrowser ||
-                (this.mCurrentBrowser.pageReport && !newBrowser.pageReport) ||
-                (!this.mCurrentBrowser.pageReport && newBrowser.pageReport))
+            if (!oldBrowser ||
+                (oldBrowser.pageReport && !newBrowser.pageReport) ||
+                (!oldBrowser.pageReport && newBrowser.pageReport))
               updatePageReport = true;
 
             newBrowser.setAttribute("type", "content-primary");
             this.mCurrentBrowser = newBrowser;
             this.mCurrentTab = this.selectedTab;
 
             if (updatePageReport)
               this.mCurrentBrowser.updatePageReport();
@@ -946,74 +902,23 @@
               }
             }
 
             // We've selected the new tab, so go ahead and notify listeners.
             var event = document.createEvent("Events");
             event.initEvent("TabSelect", true, false);
             this.mCurrentTab.dispatchEvent(event);
 
-            if (document.commandDispatcher.focusedElement &&
-                document.commandDispatcher.focusedElement.parentNode ==
-                this.mCurrentTab.parentNode) {
-              // The focus is on a tab in the same tab panel
-              return;  // If focus was on a tab, switching tabs focuses the new tab
-            }
-
-            var whatToFocus = window.content;
-
-            // Focus the previously focused element or window, but make sure
-            // the focused element is still part of the document
-            let focusedElem = newBrowser.focusedElement;
-            if (focusedElem && focusedElem.ownerDocument &&
-                !(focusedElem.ownerDocument.compareDocumentPosition(focusedElem) &
-                  Node.DOCUMENT_POSITION_DISCONNECTED)) {
-              if (newBrowser.focusedElement.parentNode !=
-                  this.mCurrentTab.parentNode) {
-                // Focus the remembered element unless it's in the current tab panel
-                whatToFocus = newBrowser.focusedElement;
-              }
-            }
-            else if (newBrowser.focusedWindow) {
-              whatToFocus = newBrowser.focusedWindow;
-            }
- 
-            // Change focus for this window to |whatToFocus|, without
-            // focusing the window itself.
-            var cmdDispatcher = document.commandDispatcher;
-
-            var ww =
-              Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
-                        .getService(Components.interfaces.nsIWindowWatcher);
-            if (ww.activeWindow == window) {
-              cmdDispatcher.suppressFocusScroll = true;
-              if (whatToFocus instanceof HTMLElement ||
-                  whatToFocus instanceof XULElement ||
-                  whatToFocus instanceof Window) {
-                whatToFocus.focus();
-              }
-              else if (whatToFocus instanceof Node) {
-                var content = window.content;
-                if (content instanceof Components.interfaces.nsIInterfaceRequestor)
-                  content.getInterface(Components.interfaces.nsIDOMWindowUtils).focus(whatToFocus);
-              }
-              cmdDispatcher.suppressFocusScroll = false;
-            }
-            else {
-              // set the element in command dispatcher so focus will restore
-              // properly when the window does become active
-              if (whatToFocus instanceof Window) {
-                cmdDispatcher.focusedWindow = whatToFocus;
-                cmdDispatcher.focusedElement = null;
-              }
-              else {
-                cmdDispatcher.focusedWindow = whatToFocus.ownerDocument.defaultView;
-                cmdDispatcher.focusedElement = whatToFocus;
-              }
-            }
+            // change focus to the new tab if nothing is focused, the old tab
+            // is focused or there is something in the new tab to focus. One
+            // specific case where focus is not changed is when the new tab
+            // has no focused element and a chrome element is focused.
+            if (!focusedChromeElement || focusedChromeElement == oldBrowser ||
+                fm.getFocusedElementForWindow(window.content, true, {}))
+              fm.setFocus(newBrowser, fm.FLAG_NOSCROLL);
           ]]>
         </body>
       </method>
 
       <method name="onTabClick">
         <parameter name="event"/>
         <body>
           <![CDATA[
@@ -1622,19 +1527,17 @@
 
             // Because of the way XBL works (fields just set JS
             // properties on the element) and the code we have in place
             // to preserve the JS objects for any elements that have
             // JS properties set on them, the browser element won't be
             // destroyed until the document goes away.  So we force a
             // cleanup ourselves.
             // This has to happen before we remove the child so that the
-            // XBL implementation of nsIObserver still works.  But
-            // clearing focusedWindow happens below because it gets
-            // reset by updateCurrentBrowser.
+            // XBL implementation of nsIObserver still works.
             browser.destroy();
 
             if (browser == this.mCurrentBrowser)
               this.mCurrentBrowser = null;
 
             // Invalidate browsers cache, as the tab is removed from the
             // tab container.
             this._browsers = null;
@@ -1657,20 +1560,16 @@
             this.mPanelContainer.removeChild(browser.parentNode);
 
             // As the panel is removed, the removal of a dependent document can
             // cause the whole window to close. So at this point, it's possible
             // that the binding is destructed.
             if (this.mTabBox)
               this.mTabBox.selectedPanel = this.getBrowserForTab(this.mCurrentTab).parentNode;
 
-            // see comment about destroy above
-            browser.focusedWindow = null;
-            browser.focusedElement = null;
-
             if (aCloseWindow)
               this._windowIsClosing = closeWindow(true);
           ]]>
         </body>
       </method>
 
       <method name="_blurTab">
         <parameter name="aTab"/>
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -79,16 +79,17 @@ include $(topsrcdir)/config/rules.mk
                  browser_bug432599.js \
                  browser_bug441778.js \
                  browser_bug455852.js \
                  browser_bug462673.js \
                  browser_bug481560.js \
                  browser_bug477014.js \
                  browser_bug495058.js \
                  browser_discovery.js \
+                 browser_tabfocus.js \
                  discovery.html \
                  moz.png \
                  test_bug462673.html \
                  browser_getshortcutoruri.js \
                  browser_page_style_menu.js \
                  page_style_sample.html \
                  browser_ctrlTab.js \
                  browser_selectTabAtIndex.js \
--- a/browser/base/content/test/browser_bug481560.js
+++ b/browser/base/content/test/browser_bug481560.js
@@ -1,19 +1,30 @@
 function test() {
   waitForExplicitFinish();
 
+  // focus the url field so that it will can ensure the focus is there when
+  // the window is refocused after the dialog closes
+  gURLBar.focus();
+
+  window.addEventListener("focus", function () {
+    window.removeEventListener("focus", arguments.callee, false);
+    finish();
+  }, false);
+
   var win = openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no");
 
   win.addEventListener("load", function () {
     win.removeEventListener("load", arguments.callee, false);
 
+    win.content.addEventListener("focus", function () {
+      win.content.removeEventListener("focus", arguments.callee, false);
+
+      EventUtils.synthesizeKey("w", { accelKey: true }, win);
+      ok(win.closed, "accel+w closed the window immediately");
+    }, false);
+
     win.gBrowser.selectedTab.addEventListener("TabClose", function () {
       ok(false, "shouldn't have gotten the TabClose event for the last tab");
     }, false);
 
-    EventUtils.synthesizeKey("w", { accelKey: true }, win);
-
-    ok(win.closed, "accel+w closed the window immediately");
-
-    finish();
   }, false);
 }
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_tabfocus.js
@@ -0,0 +1,216 @@
+/*
+ * This test checks that focus is adjusted properly when switching tabs.
+ */
+
+let testPage1 = "data:text/html,<html id='tab1'><body><button id='button1'>Tab 1</button></body></html>";
+let testPage2 = "data:text/html,<html id='tab2'><body><button id='button2'>Tab 2</button></body></html>";
+
+function test() {
+  waitForExplicitFinish();
+
+  var tab1 = gBrowser.addTab();
+  var tab2 = gBrowser.addTab();
+  var browser1 = gBrowser.getBrowserForTab(tab1);
+  var browser2 = gBrowser.getBrowserForTab(tab2);
+
+  gURLBar.focus();
+
+  var loadCount = 0;
+  function check()
+  {
+    // wait for both tabs to load
+    if (++loadCount != 2)
+      return;
+
+    window.focus();
+
+    _browser_tabfocus_test_lastfocus = gURLBar;
+    _browser_tabfocus_test_lastfocuswindow = window;
+
+    window.addEventListener("focus", _browser_tabfocus_test_eventOccured, true);
+    window.addEventListener("blur", _browser_tabfocus_test_eventOccured, true);
+
+    gBrowser.selectedTab = tab2;
+
+    var fm = Components.classes["@mozilla.org/focus-manager;1"].
+               getService(Components.interfaces.nsIFocusManager);
+    is(fm.focusedWindow, window, "focusedWindow after tab load");
+    is(fm.focusedElement, gURLBar.inputField, "focusedElement after tab load");
+
+    // make sure that the focus initially starts out blank
+    var focusedWindow = {};
+    is(fm.getFocusedElementForWindow(browser1.contentWindow, false, focusedWindow), null, "initial focus in tab 1");
+    is(focusedWindow.value, browser1.contentWindow, "initial frame focus in tab 1");
+    is(fm.getFocusedElementForWindow(browser2.contentWindow, false, focusedWindow), null, "initial focus in tab 2");
+    is(focusedWindow.value, browser2.contentWindow, "initial frame focus in tab 2");
+
+    // switching tabs when the urlbar is focused and nothing in the new tab is focused
+    // should keep focus in the urlbar
+    expectFocusShift(function () gBrowser.selectedTab = tab1,
+                     window, gURLBar.inputField, false,
+                     "focusedElement after tab change, focus in url field, no focus in new tab");
+
+    // focusing a button in the current tab should focus it
+    var button1 = browser1.contentWindow.document.getElementById("button1");
+    expectFocusShift(function () button1.focus(),
+                     browser1.contentWindow, button1, true,
+                     "focusedWindow after focus in focused tab");
+
+    // focusing a button in a background tab should not change the actual
+    // focus, but should set the focus that would be in that background tab to
+    // that button.
+    var button2 = browser2.contentWindow.document.getElementById("button2");
+    button2.focus();
+
+    expectFocusShift(function () button2.focus(),
+                     browser1.contentWindow, button1, false,
+                     "focusedWindow after focus in unfocused tab");
+    is(fm.getFocusedElementForWindow(browser2.contentWindow, false, {}), button2, "focus in unfocused tab");
+
+    // switching tabs should now make the button in the other tab focused
+    expectFocusShift(function () gBrowser.selectedTab = tab2,
+                     browser2.contentWindow, button2, true,
+                     "focusedWindow after tab change");
+
+    // blurring an element in a background tab should not change the active
+    // focus, but should clear the focus in that tab.
+    expectFocusShift(function () button1.blur(),
+                     browser2.contentWindow, button2, false,
+                     "focusedWindow after blur in unfocused tab");
+    is(fm.getFocusedElementForWindow(browser1.contentWindow, false, {}), null, "blur in unfocused tab");
+
+    // focusing the url field should switch active focus away from the tab but
+    // not clear what would be the focus in the tab 
+    button1.focus();
+    expectFocusShift(function () gURLBar.focus(),
+                     window, gURLBar.inputField, true,
+                     "focusedWindow after url field focused");
+    is(fm.getFocusedElementForWindow(browser2.contentWindow, false, {}), button2, "url field focused, button in tab");
+
+    // when a chrome element is focused, switching tabs to a tab with a button
+    // with the current focus should focus the button
+    expectFocusShift(function () gBrowser.selectedTab = tab1,
+                     browser1.contentWindow, button1, true,
+                     "focusedWindow after tab change, focus in url field, button focused in new tab");
+    is(fm.getFocusedElementForWindow(browser2.contentWindow, false, {}), button2, "after switch tab, focus in unfocused tab");
+
+    // blurring an element in the current tab should clear the active focus
+    expectFocusShift(function () button1.blur(),
+                     browser1.contentWindow, null, true,
+                     "focusedWindow after blur in focused tab");
+
+    // blurring an non-focused url field should have no effect
+    expectFocusShift(function () gURLBar.blur(),
+                     browser1.contentWindow, null, false,
+                     "focusedWindow after blur in unfocused url field");
+
+    // switch focus to a tab with a currently focused element
+    expectFocusShift(function () gBrowser.selectedTab = tab2,
+                     browser2.contentWindow, button2, true,
+                     "focusedWindow after switch from unfocused to focused tab");
+
+    // clearing focus on the chrome window should switch the focus to the
+    // chrome window
+    expectFocusShift(function () fm.clearFocus(window),
+                     window, null, true,
+                     "focusedWindow after switch to chrome with no focused element");
+
+    // switch focus to another tab when neither have an active focus
+    expectFocusShift(function () gBrowser.selectedTab = tab1,
+                     browser1.contentWindow, null, true,
+                     "focusedWindow after tab switch from no focus to no focus");
+    
+    gBrowser.removeCurrentTab();
+    gBrowser.removeCurrentTab();
+    finish();
+  }
+
+  browser1.addEventListener("load", check, true);
+  browser2.addEventListener("load", check, true);
+  browser1.contentWindow.location = testPage1;
+  browser2.contentWindow.location = testPage2;
+}
+
+var _browser_tabfocus_test_lastfocus;
+var _browser_tabfocus_test_lastfocuswindow = null;
+var _browser_tabfocus_test_events = "";
+
+function _browser_tabfocus_test_eventOccured(event)
+{
+  var id;
+  if (event.target instanceof Window)
+    id = event.originalTarget.document.documentElement.id + "-window";
+  else if (event.target instanceof Document)
+    id = event.originalTarget.documentElement.id + "-document";
+  else if (event.target.id == "urlbar" && event.originalTarget.localName == "input")
+    id = "urlbar";
+  else
+    id = event.originalTarget.id;
+
+  if (_browser_tabfocus_test_events)
+    _browser_tabfocus_test_events += " ";
+  _browser_tabfocus_test_events += event.type + ": " + id;
+}
+
+function getId(element)
+{
+  return (element.localName == "input") ? "urlbar" : element.id;
+}
+
+function expectFocusShift(callback, expectedWindow, expectedElement, focusChanged, testid)
+{
+  var expectedEvents = "";
+  if (focusChanged) {
+    if (_browser_tabfocus_test_lastfocus)
+      expectedEvents += "blur: " + getId(_browser_tabfocus_test_lastfocus);
+
+    if (_browser_tabfocus_test_lastfocuswindow &&
+        _browser_tabfocus_test_lastfocuswindow != expectedWindow) {
+      if (expectedEvents)
+        expectedEvents += " ";
+      var windowid = _browser_tabfocus_test_lastfocuswindow.document.documentElement.id;
+      expectedEvents += "blur: " + windowid + "-document " +
+                        "blur: " + windowid + "-window";
+    }
+
+    if (expectedWindow && _browser_tabfocus_test_lastfocuswindow != expectedWindow) {
+      if (expectedEvents)
+        expectedEvents += " ";
+      var windowid = expectedWindow.document.documentElement.id;
+      expectedEvents += "focus: " + windowid + "-document " +
+                        "focus: " + windowid + "-window";
+    }
+
+    if (expectedElement) {
+      if (expectedEvents)
+        expectedEvents += " ";
+      expectedEvents += "focus: " + getId(expectedElement);
+    }
+
+    _browser_tabfocus_test_lastfocus = expectedElement;
+    _browser_tabfocus_test_lastfocuswindow = expectedWindow;
+  }
+
+  callback();
+
+  is(_browser_tabfocus_test_events, expectedEvents, testid + " events");
+  _browser_tabfocus_test_events = "";
+
+  var fm = Components.classes["@mozilla.org/focus-manager;1"].
+             getService(Components.interfaces.nsIFocusManager);
+
+  var focusedElement = fm.focusedElement;
+  is(focusedElement ? getId(focusedElement) : "none",
+     expectedElement ? getId(expectedElement) : "none", testid + " focusedElement");
+  is(fm.focusedWindow, expectedWindow, testid + " focusedWindow");
+  var focusedWindow = {};
+  is(fm.getFocusedElementForWindow(expectedWindow, false, focusedWindow),
+     expectedElement, testid + " getFocusedElementForWindow");
+  is(focusedWindow.value, expectedWindow, testid + " getFocusedElementForWindow frame");
+  is(expectedWindow.document.hasFocus(), true, testid + " hasFocus");
+  var expectedActive = expectedElement;
+  if (!expectedActive)
+    expectedActive = expectedWindow.document instanceof XULDocument ?
+                     expectedWindow.document.documentElement : expectedWindow.document.body;
+  is(expectedWindow.document.activeElement, expectedActive, testid + " activeElement");
+}
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -88,34 +88,27 @@ function getBoolPref ( prefname, def )
   }
   catch(er) {
     return def;
   }
 }
 
 // Change focus for this browser window to |aElement|, without focusing the
 // window itself.
-function focusElement(aElement) {
-  // This is a redo of the fix for jag bug 91884
-  var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
-                     .getService(Components.interfaces.nsIWindowWatcher);
-  if (window == ww.activeWindow)
-    aElement.focus();
+function focusElement(aElement)
+{
+  // if a content window, focus the <browser> instead as window.focus()
+  // raises the window
+  if (aElement instanceof Window) {
+    var browser = getBrowserFromContentWindow(aElement);
+    if (browser)
+      browser.focus();
+  }
   else {
-    // set the element in command dispatcher so focus will restore properly
-    // when the window does become active
-    var cmdDispatcher = document.commandDispatcher;
-    if (aElement instanceof Window) {
-      cmdDispatcher.focusedWindow = aElement;
-      cmdDispatcher.focusedElement = null;
-    }
-    else if (aElement instanceof Element) {
-      cmdDispatcher.focusedWindow = aElement.ownerDocument.defaultView;
-      cmdDispatcher.focusedElement = aElement;
-    }
+    aElement.focus();
   }
 }
 
 // openUILink handles clicks on UI elements that cause URLs to load.
 function openUILink( url, e, ignoreButton, ignoreAlt, allowKeywordFixup, postData, referrerUrl )
 {
   var where = whereToOpenLink(e, ignoreButton, ignoreAlt);
   openUILinkIn(url, where, allowKeywordFixup, postData, referrerUrl);
@@ -250,20 +243,21 @@ function openUILinkIn( url, where, allow
     // fall through
   case "tab":
     var browser = w.getBrowser();
     browser.loadOneTab(url, referrerUrl, null, postData, loadInBackground,
                        allowThirdPartyFixup || false);
     break;
   }
 
-  // Call focusElement(w.content) instead of w.content.focus() to make sure
-  // that we don't raise the old window, since the URI we just loaded may have
-  // resulted in a new frontmost window (e.g. "javascript:window.open('');").
-  focusElement(w.content);
+  // Focus the content but don't raise the window, since the URI we just loaded
+  // may have resulted in a new frontmost window (e.g. "javascript:window.open('');").
+  var browser = w.getBrowserFromContentWindow(w.content);
+  if (browser)
+    browser.focus();
 }
 
 // Used as an onclick handler for UI elements with link-like behavior.
 // e.g. onclick="checkForMiddleClick(this, event);"
 function checkForMiddleClick(node, event) {
   // We should be using the disabled property here instead of the attribute,
   // but some elements that this function is used with don't support it (e.g.
   // menuitem).
--- a/content/base/public/nsIContent.h
+++ b/content/base/public/nsIContent.h
@@ -58,18 +58,18 @@ class nsAttrName;
 class nsTextFragment;
 class nsIDocShell;
 #ifdef MOZ_SMIL
 class nsISMILAttr;
 #endif // MOZ_SMIL
 
 // IID for the nsIContent interface
 #define NS_ICONTENT_IID       \
-{ 0x3ca5afbe, 0x1052, 0x4682, \
-  { 0x9f, 0xa0, 0x0e, 0x39, 0xe4, 0xf8, 0xef, 0x9d } }
+{ 0x08dadcc4, 0x057a, 0x4b8d, \
+  { 0x89, 0x43, 0x30, 0x0e, 0x61, 0xc6, 0x9d, 0x36 } }
 
 /**
  * A node of content in a document's content model. This interface
  * is supported by all content objects.
  */
 class nsIContent : public nsINode {
 public:
 #ifdef MOZILLA_INTERNAL_API
@@ -463,46 +463,16 @@ public:
 
   /**
    * Append the text content to aResult.
    * NOTE: This asserts and returns for elements
    */
   virtual void AppendTextTo(nsAString& aResult) = 0;
 
   /**
-   * Set the focus on this content.  This is generally something for the event
-   * state manager to do, not ordinary people.  Ordinary people should do
-   * something like nsGenericHTMLElement::SetElementFocus().  This method is
-   * the end result, the point where the content finds out it has been focused.
-   * 
-   * All content elements are potentially focusable.
-   *
-   * @param aPresContext the pres context
-   * @see nsGenericHTMLElement::SetElementFocus()
-   */
-  virtual void SetFocus(nsPresContext* aPresContext)
-  {
-  }
-
-  /**
-   * Remove the focus on this content.  This is generally something for the
-   * event state manager to do, not ordinary people.  Ordinary people should do
-   * something like nsGenericHTMLElement::SetElementFocus().  This method is
-   * the end result, the point where the content finds out it has been focused.
-   * 
-   * All content elements are potentially focusable.
-   *
-   * @param aPresContext the pres context
-   * @see nsGenericHTMLElement::SetElementFocus()
-   */
-  virtual void RemoveFocus(nsPresContext* aPresContext)
-  {
-  }
-
-  /**
    * Check if this content is focusable and in the current tab order.
    * Note: most callers should use nsIFrame::IsFocusable() instead as it 
    *       checks visibility and other layout factors as well.
    * Tabbable is indicated by a nonnegative tabindex & is a subset of focusable.
    * For example, only the selected radio button in a group is in the 
    * tab order, unless the radio group has no selection in which case
    * all of the visible, non-disabled radio buttons in the group are 
    * in the tab order. On the other hand, all of the visible, non-disabled 
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -110,16 +110,17 @@
 
 #include "nsIScriptSecurityManager.h"
 #include "nsIPrincipal.h"
 #include "nsIPrivateDOMImplementation.h"
 
 #include "nsIDOMWindowInternal.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMElement.h"
+#include "nsFocusManager.h"
 
 // for radio group stuff
 #include "nsIDOMHTMLInputElement.h"
 #include "nsIRadioVisitor.h"
 #include "nsIFormControl.h"
 
 #include "nsXMLEventsManager.h"
 
@@ -2488,38 +2489,25 @@ nsDocument::SetContentType(const nsAStri
 
 /* Return true if the document is in the focused top-level window, and is an
  * ancestor of the focused DOMWindow. */
 NS_IMETHODIMP
 nsDocument::HasFocus(PRBool* aResult)
 {
   *aResult = PR_FALSE;
 
-  nsPIDOMWindow* window = GetWindow();
-  nsIFocusController* focusController = window ?
-    window->GetRootFocusController() : nsnull;
-  if (!focusController) {
-    return NS_OK;
-  }
-
-  // Does the top-level window have focus?
-  PRBool active;
-  nsresult rv = focusController->GetActive(&active);
-  NS_ENSURE_SUCCESS(rv, rv);
-  if (!active){
-    return NS_OK;
-  }
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+  if (!fm)
+    return NS_ERROR_NOT_AVAILABLE;
 
   // Is there a focused DOMWindow?
-  nsCOMPtr<nsIDOMWindowInternal> focusedWindow;
-  rv = focusController->GetFocusedWindow(getter_AddRefs(focusedWindow));
-  NS_ENSURE_SUCCESS(rv, rv);
-  if (!focusedWindow) {
-    return NS_ERROR_FAILURE;
-  }
+  nsCOMPtr<nsIDOMWindow> focusedWindow;
+  fm->GetFocusedWindow(getter_AddRefs(focusedWindow));
+  if (!focusedWindow)
+    return NS_OK;
 
   // Are we an ancestor of the focused DOMWindow?
   nsCOMPtr<nsIDOMDocument> domDocument;
   focusedWindow->GetDocument(getter_AddRefs(domDocument));
   nsCOMPtr<nsIDocument> document = do_QueryInterface(domDocument);
 
   for (nsIDocument* currentDoc = document; currentDoc;
        currentDoc = currentDoc->GetParentDocument()) {
@@ -2541,66 +2529,39 @@ nsDocument::GetReferrer(nsAString& aRefe
 }
 
 NS_IMETHODIMP
 nsDocument::GetActiveElement(nsIDOMElement **aElement)
 {
   *aElement = nsnull;
 
   // Get the focused element.
-  nsPIDOMWindow* window = GetWindow();
+  nsCOMPtr<nsPIDOMWindow> window = GetWindow();
   if (!window) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
-  nsIFocusController* focusController = window->GetRootFocusController();
-  if (!focusController) {
-    return NS_ERROR_FAILURE;
-  }
-
-  nsCOMPtr<nsIDOMElement> focusedElement;
-  focusController->GetFocusedElement(getter_AddRefs(focusedElement));
-  nsCOMPtr<nsIContent> content = do_QueryInterface(focusedElement);
-  if (content) {
-    // Found a focused element.  See if it's in this document.
-    nsIDocument* currentDoc = content->GetCurrentDoc();
-    if (currentDoc == this) {
-      focusedElement.swap(*aElement);
-      return NS_OK;
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+  if (!fm)
+    return NS_ERROR_NOT_AVAILABLE;
+
+  nsCOMPtr<nsPIDOMWindow> focusedWindow;
+  nsIContent* focusedContent =
+    nsFocusManager::GetFocusedDescendant(window, PR_FALSE, getter_AddRefs(focusedWindow));
+
+  // an element in this document is focused, so return it
+  if (focusedContent) {
+    // be safe and make sure the element is from this document
+    if (focusedContent->GetOwnerDoc() != this) {
+      NS_WARNING("Focused element found from another document");
+      return NS_ERROR_FAILURE;
     }
 
-    // Not in this document.  If it's in a child document, return the iframe in
-    // this document that's an ancestor of the child.
-    if (currentDoc) {
-      *aElement = CheckAncestryAndGetFrame(currentDoc).get();
-      if (*aElement) {
-        return NS_OK;
-      }
-    }
-  }
-
-  // Couldn't find a focused element.  Check if something like an IFRAME is
-  // focused, which will give us a focused window rather than a focused
-  // element.
-  nsCOMPtr<nsIDOMWindowInternal> focusedWindow;
-  focusController->GetFocusedWindow(getter_AddRefs(focusedWindow));
-  if (focusedWindow) {
-    // Found a focused window.  See if it's in a child of this document.  (If
-    // the window's document is this, then we should just fall through to
-    // returning the BODY below).
-    nsCOMPtr<nsIDOMDocument> domDocument;
-    focusedWindow->GetDocument(getter_AddRefs(domDocument));
-    nsCOMPtr<nsIDocument> document = do_QueryInterface(domDocument);
-
-    if (document && (document != this)) {
-      *aElement = CheckAncestryAndGetFrame(document).get();
-      if (*aElement) {
-        return NS_OK;
-      }
-    }
+    CallQueryInterface(focusedContent, aElement);
+    return NS_OK;
   }
 
   // No focused element anywhere in this document.  Try to get the BODY.
   nsCOMPtr<nsIDOMHTMLDocument> htmlDoc =
     do_QueryInterface(static_cast<nsIDocument*>(this));
   if (htmlDoc) {
     nsCOMPtr<nsIDOMHTMLElement> bodyElement;
     htmlDoc->GetBody(getter_AddRefs(bodyElement));
@@ -7495,18 +7456,23 @@ nsDocument::SuppressEventHandling(PRUint
   mEventsSuppressed += aIncrease;
   EnumerateSubDocuments(SuppressEventHandlingInDocument, &aIncrease);
 }
 
 static void
 FireOrClearDelayedEvents(nsTArray<nsCOMPtr<nsIDocument> >& aDocuments,
                          PRBool aFireEvents)
 {
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+  if (!fm)
+    return;
+
   for (PRUint32 i = 0; i < aDocuments.Length(); ++i) {
     if (!aDocuments[i]->EventHandlingSuppressed()) {
+      fm->FireDelayedEvents(aDocuments[i]);
       nsPresShellIterator iter(aDocuments[i]);
       nsCOMPtr<nsIPresShell> shell;
       while ((shell = iter.GetNextShell())) {
         shell->FireOrClearDelayedEvents(aFireEvents);
       }
     }
   }
 }
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -49,17 +49,17 @@
 #include "nsIAtom.h"
 #include "nsINodeInfo.h"
 #include "nsIDocument.h"
 #include "nsIDOMNodeList.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMText.h"
 #include "nsIContentIterator.h"
 #include "nsIEventListenerManager.h"
-#include "nsIFocusController.h"
+#include "nsFocusManager.h"
 #include "nsILinkHandler.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIURL.h"
 #include "nsNetUtil.h"
 #include "nsIFrame.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsStyleConsts.h"
@@ -119,17 +119,16 @@
 #include "nsIDOMNSFeatureFactory.h"
 #include "nsIDOMDocumentType.h"
 #include "nsIDOMUserDataHandler.h"
 #include "nsGenericHTMLElement.h"
 #include "nsIEditor.h"
 #include "nsIEditorDocShell.h"
 #include "nsEventDispatcher.h"
 #include "nsContentCreatorFunctions.h"
-#include "nsIFocusController.h"
 #include "nsIControllers.h"
 #include "nsLayoutUtils.h"
 #include "nsIView.h"
 #include "nsIViewManager.h"
 #include "nsIScrollableFrame.h"
 #include "nsIScrollableView.h"
 #include "nsIScrollableViewProvider.h"
 #include "nsXBLInsertionPoint.h"
@@ -3067,94 +3066,39 @@ nsGenericElement::GetBaseURI() const
 
 PRBool
 nsGenericElement::IsLink(nsIURI** aURI) const
 {
   *aURI = nsnull;
   return PR_FALSE;
 }
 
-void
-nsGenericElement::SetFocus(nsPresContext* aPresContext)
-{
-  // Traditionally focusable elements can take focus as long as they don't set
-  // the disabled attribute
-
-  nsCOMPtr<nsIPresShell> presShell = aPresContext->PresShell();
-  if (!presShell) {
-    return;
-  }
-  nsIFrame* frame = presShell->GetPrimaryFrameFor(this);
-  if (frame && frame->IsFocusable() &&
-      aPresContext->EventStateManager()->SetContentState(this,
-                                                         NS_EVENT_STATE_FOCUS)) {
-    presShell->ScrollContentIntoView(this, NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,
-                                     NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE);
-  }
-}
-
-// static
-PRBool
-nsGenericElement::ShouldFocus(nsIContent *aContent)
-{
-  // Default to false, since if the document is not attached to a window,
-  // we should not focus any of its content.
-  PRBool visible = PR_FALSE;
-
-  // Figure out if we're focusing an element in an inactive (hidden)
-  // tab (whose docshell is not visible), if so, drop this focus
-  // request on the floor
-
-  nsIDocument *document = aContent->GetDocument();
-
-  if (document) {
-    nsIScriptGlobalObject *sgo = document->GetScriptGlobalObject();
-
-    if (sgo) {
-      nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(sgo));
-      nsCOMPtr<nsIBaseWindow> baseWin(do_QueryInterface(webNav));
-
-      if (baseWin) {
-        baseWin->GetVisibility(&visible);
-      }
-    }
-  }
-
-  return visible;
-}
-
 // static
 PRBool
 nsGenericElement::ShouldBlur(nsIContent *aContent)
 {
   // Determine if the current element is focused, if it is not focused
   // then we should not try to blur
-  PRBool isFocused = PR_FALSE;
-
   nsIDocument *document = aContent->GetDocument();
-
-  if (document) {
-    nsPIDOMWindow *win = document->GetWindow();
-
-    if (win) {
-      nsCOMPtr<nsIFocusController> focusController =
-           win->GetRootFocusController();
-
-      if (focusController) {
-        nsCOMPtr<nsIDOMElement> focusedElement;
-        focusController->GetFocusedElement(getter_AddRefs(focusedElement));    
-        nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(aContent);
-        //when the element is the same as the focused element, blur it
-        if (domElement == focusedElement)
-          isFocused = PR_TRUE;
-      }
-    }
-  }
-
-  return isFocused;
+  if (!document)
+    return PR_FALSE;
+
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(document->GetWindow());
+  if (!window)
+    return PR_FALSE;
+
+  nsCOMPtr<nsPIDOMWindow> focusedFrame;
+  nsIContent* contentToBlur =
+    nsFocusManager::GetFocusedDescendant(window, PR_FALSE, getter_AddRefs(focusedFrame));
+  if (contentToBlur == aContent)
+    return PR_TRUE;
+
+  // if focus on this element would get redirected, then check the redirected
+  // content as well when blurring.
+  return (contentToBlur && nsFocusManager::GetRedirectedFocus(aContent) == contentToBlur);
 }
 
 nsIContent*
 nsGenericElement::GetBindingParent() const
 {
   nsDOMSlots *slots = GetExistingDOMSlots();
 
   if (slots) {
@@ -4992,38 +4936,25 @@ nsGenericElement::PostHandleEventForLink
   case NS_MOUSE_BUTTON_DOWN:
     {
       if (aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT &&
           static_cast<nsMouseEvent*>(aVisitor.mEvent)->button ==
           nsMouseEvent::eLeftButton) {
         // don't make the link grab the focus if there is no link handler
         nsILinkHandler *handler = aVisitor.mPresContext->GetLinkHandler();
         nsIDocument *document = GetCurrentDoc();
-        if (handler && document && ShouldFocus(this)) {
-          // If the window is not active, do not allow the focus to bring the
-          // window to the front. We update the focus controller, but do nothing
-          // else.
-          nsPIDOMWindow *win = document->GetWindow();
-          if (win) {
-            nsIFocusController *focusController =
-              win->GetRootFocusController();
-            if (focusController) {
-              PRBool isActive = PR_FALSE;
-              focusController->GetActive(&isActive);
-              if (!isActive) {
-                nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(this);
-                if(domElement)
-                  focusController->SetFocusedElement(domElement);
-                break;
-              }
-            }
+        if (handler && document) {
+          nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+          if (fm) {
+            nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(this);
+            fm->SetFocus(elem, nsIFocusManager::FLAG_BYMOUSE);
           }
-  
+
           aVisitor.mPresContext->EventStateManager()->
-            SetContentState(this, NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS);
+            SetContentState(this, NS_EVENT_STATE_ACTIVE);
         }
       }
     }
     break;
 
   case NS_MOUSE_CLICK:
     if (NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent)) {
       nsInputEvent* inputEvent = static_cast<nsInputEvent*>(aVisitor.mEvent);
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -412,17 +412,16 @@ public:
   nsresult SetText(const nsAString& aStr, PRBool aNotify)
   {
     return SetText(aStr.BeginReading(), aStr.Length(), aNotify);
   }
   virtual nsresult AppendText(const PRUnichar* aBuffer, PRUint32 aLength,
                               PRBool aNotify);
   virtual PRBool TextIsOnlyWhitespace();
   virtual void AppendTextTo(nsAString& aResult);
-  virtual void SetFocus(nsPresContext* aContext);
   virtual nsIContent *GetBindingParent() const;
   virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
   virtual already_AddRefed<nsIURI> GetBaseURI() const;
   virtual PRBool IsLink(nsIURI** aURI) const;
   virtual void SetMayHaveFrame(PRBool aMayHaveFrame);
   virtual PRBool MayHaveFrame() const;
 
   virtual PRUint32 GetScriptTypeID() const;
@@ -579,18 +578,16 @@ public:
   static nsresult InternalGetFeature(nsISupports* aObject,
                                      const nsAString& aFeature,
                                      const nsAString& aVersion,
                                      nsISupports** aReturn);
   
   static already_AddRefed<nsIDOMNSFeatureFactory>
     GetDOMFeatureFactory(const nsAString& aFeature, const nsAString& aVersion);
 
-  static PRBool ShouldFocus(nsIContent *aContent);
-
   static PRBool ShouldBlur(nsIContent *aContent);
 
   /**
    * Actual implementation of the DOM InsertBefore and ReplaceChild methods.
    * Shared by nsDocument. When called from nsDocument, aParent will be null.
    *
    * @param aReplace  True if aNewChild should replace aRefChild. False if
    *                  aNewChild should be inserted before aRefChild.
--- a/content/events/public/nsIEventStateManager.h
+++ b/content/events/public/nsIEventStateManager.h
@@ -37,44 +37,37 @@
 
 #ifndef nsIEventStateManager_h__
 #define nsIEventStateManager_h__
 
 #include "nsEvent.h"
 #include "nsISupports.h"
 
 class nsIContent;
+class nsIDocument;
 class nsPresContext;
 class nsIDOMEvent;
 class nsIFrame;
 class nsIView;
 class nsIWidget;
 class imgIContainer;
 
 /*
  * Event state manager interface.
  */
-// {fb7516ff-2f01-4893-84e8-e4b282813023}
+// {C224A806-A99F-4056-85C2-3B1970F94DB2}
 #define NS_IEVENTSTATEMANAGER_IID \
-{ 0x522d12ec, 0xde51, 0x4635, \
-  { 0xb0, 0x10, 0x4, 0x2a, 0x6d, 0x5, 0xa0, 0x3e } }
+{ 0xc224a806, 0xa99f, 0x4056, \
+  { 0x85, 0xc2, 0x3b, 0x19, 0x70, 0xf9, 0x4d, 0xb2 } }
 
 #define NS_EVENT_NEEDS_FRAME(event) (!NS_IS_FOCUS_EVENT(event))
 
 class nsIEventStateManager : public nsISupports {
 
 public:
-  enum EFocusedWithType {
-    eEventFocusedByUnknown,     // focus gained via unknown method
-    eEventFocusedByMouse,       // focus gained via mouse
-    eEventFocusedByKey,         // focus gained via key press (like tab)
-    eEventFocusedByContextMenu, // focus gained via context menu
-    eEventFocusedByApplication  // focus gained via Application (like script)
-  };
-
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IEVENTSTATEMANAGER_IID)
 
   NS_IMETHOD Init() = 0;
 
   NS_IMETHOD PreHandleEvent(nsPresContext* aPresContext, 
                             nsEvent *aEvent, 
                             nsIFrame* aTargetFrame,
                             nsEventStatus* aStatus,
@@ -103,39 +96,19 @@ public:
    *                  if a resulting DOM event causes the content node passed in
    *                  to not change states. Note, the frame for the content may
    *                  change as a result of the content state change, because of
    *                  frame reconstructions that may occur, but this does not
    *                  affect the return value.
    */
   virtual PRBool SetContentState(nsIContent *aContent, PRInt32 aState) = 0;
 
-  NS_IMETHOD GetFocusedContent(nsIContent **aContent) = 0;
-  NS_IMETHOD SetFocusedContent(nsIContent* aContent) = 0;
-
-  // Get the previously-focused content node for this document
-  NS_IMETHOD GetLastFocusedContent(nsIContent **aContent) = 0;
-
-  NS_IMETHOD GetFocusedFrame(nsIFrame **aFrame) = 0;
-
-  NS_IMETHOD ContentRemoved(nsIContent* aContent) = 0;
+  NS_IMETHOD ContentRemoved(nsIDocument* aDocument, nsIContent* aContent) = 0;
   NS_IMETHOD EventStatusOK(nsGUIEvent* aEvent, PRBool *aOK) = 0;
 
-  // Return whether browse with caret is enabled or not
-  virtual PRBool GetBrowseWithCaret() = 0;
-
-  // This is called after find text or when a cursor movement key is pressed
-  // If aCanFocusDoc == PR_TRUE, the current document will be focused if caret is not on a focusable element
-  NS_IMETHOD MoveFocusToCaret(PRBool aCanFocusDoc, PRBool *aIsSelectionWithFocus) = 0;
-  NS_IMETHOD MoveCaretToFocus() = 0;
-
-  // Set focus on any element that can receive focus, or on document via aFocusContent == nsnull
-  // Must supply method that focus is being set with
-  NS_IMETHOD ChangeFocusWith(nsIContent *aFocusContent, EFocusedWithType aFocusedWith) = 0;
-
   // Access Key Registration
 
   /**
    * Register accesskey on the given element. When accesskey is activated then
    * the element will be notified via nsIContent::PerformAccesskey() method.
    *
    * @param  aContent  the given element
    * @param  aKey      accesskey
@@ -158,19 +131,16 @@ public:
    * @return           NS_OK
    */
   NS_IMETHOD GetRegisteredAccessKey(nsIContent* aContent, PRUint32* aKey) = 0;
 
   NS_IMETHOD SetCursor(PRInt32 aCursor, imgIContainer* aContainer,
                        PRBool aHaveHotspot, float aHotspotX, float aHotspotY,
                        nsIWidget* aWidget, PRBool aLockCursor) = 0;
 
-  // Method for moving the focus forward/back.
-  NS_IMETHOD ShiftFocus(PRBool aDirection, nsIContent* aStart)=0;
-
   NS_IMETHOD NotifyDestroyPresContext(nsPresContext* aPresContext) = 0;
   
   /**
    * Returns true if the current code is being executed as a result of user input.
    * This includes timers or anything else that is initiated from user input.
    * However, mouse hover events are not counted as user input, nor are
    * page load events. If this method is called from asynchronously executed code,
    * such as during layout reflows, it will return false.
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -923,24 +923,16 @@ NS_METHOD nsDOMEvent::DuplicatePrivateDa
       isInputEvent = PR_TRUE;
       break;
     }
     case NS_FORM_EVENT:
     {
       newEvent = new nsFormEvent(PR_FALSE, msg);
       break;
     }
-    case NS_FOCUS_EVENT:
-    {
-      newEvent = new nsFocusEvent(PR_FALSE, msg, nsnull);
-      NS_ENSURE_TRUE(newEvent, NS_ERROR_OUT_OF_MEMORY);
-      static_cast<nsFocusEvent*>(newEvent)->isMozWindowTakingFocus =
-        static_cast<nsFocusEvent*>(mEvent)->isMozWindowTakingFocus;
-      break;
-    }
     case NS_POPUP_EVENT:
     {
       newEvent = new nsInputEvent(PR_FALSE, msg, nsnull);
       NS_ENSURE_TRUE(newEvent, NS_ERROR_OUT_OF_MEMORY);
       isInputEvent = PR_TRUE;
       newEvent->eventStructType = NS_POPUP_EVENT;
       break;
     }
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -80,17 +80,17 @@
 #include "nsDOMError.h"
 #include "nsIJSContextStack.h"
 #include "nsIDocument.h"
 #include "nsIPresShell.h"
 #include "nsMutationEvent.h"
 #include "nsIXPConnect.h"
 #include "nsDOMCID.h"
 #include "nsIScriptObjectOwner.h" // for nsIScriptEventHandlerOwner
-#include "nsIFocusController.h"
+#include "nsFocusManager.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMNSDocument.h"
 #include "nsContentUtils.h"
 #include "nsJSUtils.h"
 #include "nsIDOMEventGroup.h"
 #include "nsContentCID.h"
 #include "nsEventDispatcher.h"
 #include "nsDOMJSUtils.h"
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -98,17 +98,17 @@
 #include "nsIObjectFrame.h"
 #ifdef MOZ_XUL
 #include "nsXULPopupManager.h"
 #endif
 
 #include "nsIServiceManager.h"
 #include "nsIScriptSecurityManager.h"
 
-#include "nsIFocusController.h"
+#include "nsFocusManager.h"
 
 #include "nsIDOMXULElement.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMKeyEvent.h"
 #include "nsIObserverService.h"
 #include "nsIDocShell.h"
 #include "nsIMarkupDocumentViewer.h"
 #include "nsIScrollableViewProvider.h"
@@ -163,29 +163,16 @@
 
 static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID);
 
 //we will use key binding by default now. this wil lbreak viewer for now
 #define NON_KEYBINDING 0
 
 static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
 
-nsIContent * gLastFocusedContent = 0; // Strong reference
-nsIDocument * gLastFocusedDocument = 0; // Strong reference
-nsPresContext* gLastFocusedPresContextWeak = 0; // Weak reference
-
-enum nsTextfieldSelectModel {
-  eTextfieldSelect_unset = -1,
-  eTextfieldSelect_manual = 0,
-  eTextfieldSelect_auto = 1   // select textfields when focused with keyboard
-};
-
-// Tab focus policy (static, constant across the app):
-// Which types of elements are in the tab order?
-static PRInt8 sTextfieldSelectModel = eTextfieldSelect_unset;
 static PRBool sLeftClickOnly = PR_TRUE;
 static PRBool sKeyCausesActivation = PR_TRUE;
 static PRUint32 sESMInstanceCount = 0;
 static PRInt32 sChromeAccessModifier = 0, sContentAccessModifier = 0;
 PRInt32 nsEventStateManager::sUserInputEventDepth = 0;
 
 static PRUint32 gMouseOrKeyboardEventCounter = 0;
 static nsITimer* gUserInteractionTimer = nsnull;
@@ -262,79 +249,16 @@ PrintDocTreeAll(nsIDocShellTreeItem* aIt
       break;
     item = parent;
   }
 
   PrintDocTree(item, 0);
 }
 #endif
 
-static PRUint32 gMayNeedFocusSuppression = 0;
-
-class nsSuppressUserFocus
-{
-public:
-  nsSuppressUserFocus() : mActive(PR_FALSE) {}
-  ~nsSuppressUserFocus() {
-    if (mActive) {
-      NS_ASSERTION(gMayNeedFocusSuppression,
-                   "Trying to unsuppress too much!");
-      --gMayNeedFocusSuppression;
-    }
-  }
-  void MaybeSuppress()
-  {
-    if (!mActive) {
-      mActive = PR_TRUE;
-      ++gMayNeedFocusSuppression;
-    }
-  }
-private:
-  PRBool mActive;
-};
-
-static nsIDocument*
-EventHandlingSuppressed(nsPIDOMEventTarget* aTarget)
-{
-  if (!gMayNeedFocusSuppression) {
-    return nsnull;
-  }
-  nsCOMPtr<nsINode> node = do_QueryInterface(aTarget);
-  nsCOMPtr<nsIDocument> doc;
-  if (node) {
-    doc = node->GetOwnerDoc();
-  } else {
-    nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aTarget);
-    if (window) {
-      doc = do_QueryInterface(window->GetExtantDocument());
-    }
-  }
-
-  return (doc && doc->EventHandlingSuppressed()) ? doc.get() : nsnull;
-}
-
-static void
-FireFocusOrBlurEvent(nsPIDOMEventTarget* aTarget, nsEvent* aEvent, nsPresContext* aContext)
-{
-  NS_ASSERTION(aEvent->message == NS_BLUR_CONTENT ||
-               aEvent->message == NS_FOCUS_CONTENT,
-               "Wrong event!");
-  nsIDocument* doc = EventHandlingSuppressed(aTarget);
-  if (doc) {
-    if (aContext) {
-      nsIPresShell* shell = aContext->GetPresShell();
-      if (shell) {
-        shell->NeedsFocusOrBlurAfterSuppression(aTarget, aEvent->message);
-      }
-    }
-  } else if (aTarget) {
-    nsEventDispatcher::Dispatch(aTarget, aContext, aEvent);
-  }
-}
-
 class nsUITimerCallback : public nsITimerCallback
 {
 public:
   nsUITimerCallback() : mPreviousCount(0) {}
   NS_DECL_ISUPPORTS
   NS_DECL_NSITIMERCALLBACK
 private:
   PRUint32 mPreviousCount;
@@ -370,18 +294,16 @@ enum {
 };
 
 // mask values for ui.key.chromeAccess and ui.key.contentAccess
 #define NS_MODIFIER_SHIFT    1
 #define NS_MODIFIER_CONTROL  2
 #define NS_MODIFIER_ALT      4
 #define NS_MODIFIER_META     8
 
-static PRBool GetWindowShowCaret(nsIDocument *aDocument);
-
 static nsIDocument *
 GetDocumentFromWindow(nsIDOMWindow *aWindow)
 {
   nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(aWindow);
   nsCOMPtr<nsIDocument> doc;
 
   if (win) {
     doc = do_QueryInterface(win->GetExtantDocument());
@@ -692,27 +614,22 @@ nsMouseWheelTransaction::GetIgnoreMoveDe
 
 nsEventStateManager::nsEventStateManager()
   : mLockCursor(0),
     mCurrentTarget(nsnull),
     mLastMouseOverFrame(nsnull),
     mLastDragOverFrame(nsnull),
     // init d&d gesture state machine variables
     mGestureDownPoint(0,0),
-    mCurrentFocusFrame(nsnull),
-    mCurrentTabIndex(0),
-    mLastFocusedWith(eEventFocusedByUnknown),
     mPresContext(nsnull),
     mLClickCount(0),
     mMClickCount(0),
     mRClickCount(0),
     mNormalLMouseEventInProcess(PR_FALSE),
     m_haveShutdown(PR_FALSE),
-    mBrowseWithCaret(PR_FALSE),
-    mTabbedThroughDocument(PR_FALSE),
     mLastLineScrollConsumedX(PR_FALSE),
     mLastLineScrollConsumedY(PR_FALSE)
 {
   if (sESMInstanceCount == 0) {
     gUserInteractionTimerCallback = new nsUITimerCallback();
     if (gUserInteractionTimerCallback) {
       NS_ADDREF(gUserInteractionTimerCallback);
       CallCreateInstance("@mozilla.org/timer;1", &gUserInteractionTimer);
@@ -744,24 +661,18 @@ nsEventStateManager::Init()
       sLeftClickOnly =
         nsContentUtils::GetBoolPref("nglayout.events.dispatchLeftClickOnly",
                                     sLeftClickOnly);
 
       sChromeAccessModifier =
         GetAccessModifierMaskFromPref(nsIDocShellTreeItem::typeChrome);
       sContentAccessModifier =
         GetAccessModifierMaskFromPref(nsIDocShellTreeItem::typeContent);
-
-      nsIContent::sTabFocusModelAppliesToXUL =
-        nsContentUtils::GetBoolPref("accessibility.tabfocus_applies_to_xul",
-                                    nsIContent::sTabFocusModelAppliesToXUL);
     }
     prefBranch->AddObserver("accessibility.accesskeycausesactivation", this, PR_TRUE);
-    prefBranch->AddObserver("accessibility.browsewithcaret", this, PR_TRUE);
-    prefBranch->AddObserver("accessibility.tabfocus_applies_to_xul", this, PR_TRUE);
     prefBranch->AddObserver("nglayout.events.dispatchLeftClickOnly", this, PR_TRUE);
     prefBranch->AddObserver("ui.key.generalAccessKey", this, PR_TRUE);
     prefBranch->AddObserver("ui.key.chromeAccess", this, PR_TRUE);
     prefBranch->AddObserver("ui.key.contentAccess", this, PR_TRUE);
 #if 0
     prefBranch->AddObserver("mousewheel.withaltkey.action", this, PR_TRUE);
     prefBranch->AddObserver("mousewheel.withaltkey.numlines", this, PR_TRUE);
     prefBranch->AddObserver("mousewheel.withaltkey.sysnumlines", this, PR_TRUE);
@@ -774,39 +685,28 @@ nsEventStateManager::Init()
     prefBranch->AddObserver("mousewheel.withshiftkey.action", this, PR_TRUE);
     prefBranch->AddObserver("mousewheel.withshiftkey.numlines", this, PR_TRUE);
     prefBranch->AddObserver("mousewheel.withshiftkey.sysnumlines", this, PR_TRUE);
 #endif
 
     prefBranch->AddObserver("dom.popup_allowed_events", this, PR_TRUE);
   }
 
-  if (sTextfieldSelectModel == eTextfieldSelect_unset) {
-    nsCOMPtr<nsILookAndFeel> lookNFeel(do_GetService(kLookAndFeelCID));
-    PRInt32 selectTextfieldsOnKeyFocus = 0;
-    lookNFeel->GetMetric(nsILookAndFeel::eMetric_SelectTextfieldsOnKeyFocus,
-                         selectTextfieldsOnKeyFocus);
-    sTextfieldSelectModel = selectTextfieldsOnKeyFocus ? eTextfieldSelect_auto:
-                                                         eTextfieldSelect_manual;
-  }
-
   return rv;
 }
 
 nsEventStateManager::~nsEventStateManager()
 {
 #if CLICK_HOLD_CONTEXT_MENUS
   KillClickHoldTimer();
 #endif
 
   --sESMInstanceCount;
   if(sESMInstanceCount == 0) {
     nsMouseWheelTransaction::Shutdown();
-    NS_IF_RELEASE(gLastFocusedContent);
-    NS_IF_RELEASE(gLastFocusedDocument);
     if (gUserInteractionTimerCallback) {
       gUserInteractionTimerCallback->Notify(nsnull);
       NS_RELEASE(gUserInteractionTimerCallback);
     }
     if (gUserInteractionTimer) {
       gUserInteractionTimer->Cancel();
       NS_RELEASE(gUserInteractionTimer);
     }
@@ -833,18 +733,16 @@ nsEventStateManager::~nsEventStateManage
 nsresult
 nsEventStateManager::Shutdown()
 {
   nsCOMPtr<nsIPrefBranch2> prefBranch =
     do_QueryInterface(nsContentUtils::GetPrefBranch());
 
   if (prefBranch) {
     prefBranch->RemoveObserver("accessibility.accesskeycausesactivation", this);
-    prefBranch->RemoveObserver("accessibility.browsewithcaret", this);
-    prefBranch->RemoveObserver("accessibility.tabfocus_applies_to_xul", this);
     prefBranch->RemoveObserver("nglayout.events.dispatchLeftClickOnly", this);
     prefBranch->RemoveObserver("ui.key.generalAccessKey", this);
     prefBranch->RemoveObserver("ui.key.chromeAccess", this);
     prefBranch->RemoveObserver("ui.key.contentAccess", this);
 #if 0
     prefBranch->RemoveObserver("mousewheel.withshiftkey.action", this);
     prefBranch->RemoveObserver("mousewheel.withshiftkey.numlines", this);
     prefBranch->RemoveObserver("mousewheel.withshiftkey.sysnumlines", this);
@@ -877,22 +775,16 @@ nsEventStateManager::Observe(nsISupports
     if (!someData)
       return NS_OK;
 
     nsDependentString data(someData);
     if (data.EqualsLiteral("accessibility.accesskeycausesactivation")) {
       sKeyCausesActivation =
         nsContentUtils::GetBoolPref("accessibility.accesskeycausesactivation",
                                     sKeyCausesActivation);
-    } else if (data.EqualsLiteral("accessibility.browsewithcaret")) {
-      ResetBrowseWithCaret();
-    } else if (data.EqualsLiteral("accessibility.tabfocus_applies_to_xul")) {
-      nsIContent::sTabFocusModelAppliesToXUL =
-        nsContentUtils::GetBoolPref("accessibility.tabfocus_applies_to_xul",
-                                    nsIContent::sTabFocusModelAppliesToXUL);
     } else if (data.EqualsLiteral("nglayout.events.dispatchLeftClickOnly")) {
       sLeftClickOnly =
         nsContentUtils::GetBoolPref("nglayout.events.dispatchLeftClickOnly",
                                     sLeftClickOnly);
     } else if (data.EqualsLiteral("ui.key.generalAccessKey")) {
       sChromeAccessModifier =
         GetAccessModifierMaskFromPref(nsIDocShellTreeItem::typeChrome);
       sContentAccessModifier =
@@ -944,22 +836,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mGestureDownFrameOwner);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLastLeftMouseDownContent);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLastMiddleMouseDownContent);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLastRightMouseDownContent);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mActiveContent);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mHoverContent);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDragOverContent);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mURLTargetContent);
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCurrentFocus);
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLastFocus);
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLastContentFocus);
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFirstBlurEvent);
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFirstDocumentBlurEvent);
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFirstFocusEvent);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFirstMouseOverEventElement);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFirstMouseOutEventElement);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocument);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mAccessKeys);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsEventStateManager)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCurrentTargetContent);
@@ -968,22 +854,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mGestureDownFrameOwner);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLastLeftMouseDownContent);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLastMiddleMouseDownContent);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLastRightMouseDownContent);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mActiveContent);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mHoverContent);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDragOverContent);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mURLTargetContent);
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCurrentFocus);
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLastFocus);
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLastContentFocus);
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstBlurEvent);
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstDocumentBlurEvent);
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstFocusEvent);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstMouseOverEventElement);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstMouseOutEventElement);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocument);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mAccessKeys);
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 
 NS_IMETHODIMP
@@ -1027,18 +907,16 @@ nsEventStateManager::PreHandleEvent(nsPr
     }
     ++gMouseOrKeyboardEventCounter;
   }
 
   *aStatus = nsEventStatus_eIgnore;
 
   nsMouseWheelTransaction::OnEvent(aEvent);
 
-  nsSuppressUserFocus userFocus;
-
   switch (aEvent->message) {
   case NS_MOUSE_BUTTON_DOWN:
     switch (static_cast<nsMouseEvent*>(aEvent)->button) {
     case nsMouseEvent::eLeftButton:
 #ifndef XP_OS2
       BeginTrackingDragGesture ( aPresContext, (nsMouseEvent*)aEvent, aTargetFrame );
 #endif
       mLClickCount = ((nsMouseEvent*)aEvent)->clickCount;
@@ -1116,462 +994,16 @@ nsEventStateManager::PreHandleEvent(nsPr
     break;
 #endif
   case NS_DRAGDROP_DROP:
   case NS_DRAGDROP_OVER:
     // NS_DRAGDROP_DROP is fired before NS_DRAGDROP_DRAGDROP so send
     // the enter/exit events before NS_DRAGDROP_DROP.
     GenerateDragDropEnterExit(aPresContext, (nsGUIEvent*)aEvent);
     break;
-  case NS_GOTFOCUS:
-    {
-#ifdef DEBUG_smaug
-      printf("nsEventStateManager::PreHandleEvent, NS_GOTFOCUS \n");
-#endif
-      userFocus.MaybeSuppress();
-      // This is called when a child widget has received focus.
-      // We need to take care of sending a blur event for the previously
-      // focused content and document, then dispatching a focus
-      // event to the target content, its document, and its window.
-
-      EnsureDocument(aPresContext);
-
-      // If the document didn't change, then the only thing that could have
-      // changed is the focused content node.  That's handled elsewhere
-      // (SetContentState and SendFocusBlur).
-
-      if (gLastFocusedDocument == mDocument)
-        break;
-
-      if (mDocument) {
-        nsIMEStateManager::OnTextStateBlur(mPresContext, mCurrentFocus);
-
-        if (gLastFocusedDocument && gLastFocusedPresContextWeak) {
-          nsCOMPtr<nsPIDOMWindow> ourWindow =
-            gLastFocusedDocument->GetWindow();
-
-          // If the focus controller is already suppressed, it means that we
-          // are in the middle of an activate sequence. In this case, we do
-          // _not_ want to fire a blur on the previously focused content, since
-          // we will be focusing it again later when we receive the NS_ACTIVATE
-          // event.  See bug 120209.
-
-          // Hold a strong ref to the focus controller, since we need
-          // it after event dispatch.
-          nsCOMPtr<nsIFocusController> focusController;
-          PRBool isAlreadySuppressed = PR_FALSE;
-
-          if (ourWindow) {
-            focusController = ourWindow->GetRootFocusController();
-            if (focusController) {
-              focusController->GetSuppressFocus(&isAlreadySuppressed);
-              focusController->SetSuppressFocus(PR_TRUE,
-                                                "NS_GOTFOCUS ESM Suppression");
-            }
-          }
-
-          if (!isAlreadySuppressed) {
-
-            // Fire the blur event on the previously focused document.
-            nsEvent blurEvent(PR_TRUE, NS_BLUR_CONTENT);
-            blurEvent.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
-
-            FireFocusOrBlurEvent(gLastFocusedDocument, &blurEvent,
-                                 gLastFocusedPresContextWeak);
-
-            nsCOMPtr<nsIEventStateManager> esm;
-            if (!mCurrentFocus && gLastFocusedContent) {
-              // We also need to blur the previously focused content node here,
-              // if we don't have a focused content node in this document.
-              // (SendFocusBlur isn't called in this case).
-              if (gLastFocusedContent) {
-                nsCOMPtr<nsIDocument> doc = gLastFocusedContent->GetCurrentDoc();
-                if (doc) {
-                  nsIPresShell *shell = doc->GetPrimaryShell();
-                  if (shell) {
-                    nsCOMPtr<nsPresContext> oldPresContext = shell->GetPresContext();
-                    esm = oldPresContext->EventStateManager();
-                    if (esm) {
-                      esm->SetFocusedContent(gLastFocusedContent);
-                    }
-                  }
-                }
-              }
-              nsCOMPtr<nsIContent> blurContent = gLastFocusedContent;
-              blurEvent.target = nsnull;
-              FireFocusOrBlurEvent(gLastFocusedContent, &blurEvent,
-                                   gLastFocusedPresContextWeak);
-            }
-            if (ourWindow) {
-              // Clear the target so that Dispatch can set it back correctly.
-              blurEvent.target = nsnull;
-              nsCOMPtr<nsPIDOMEventTarget> win = do_QueryInterface(ourWindow);
-              FireFocusOrBlurEvent(win, &blurEvent, gLastFocusedPresContextWeak);
-            }
-
-            if (esm) {
-              esm->SetFocusedContent(nsnull);
-            }
-            NS_IF_RELEASE(gLastFocusedContent);
-          }
-
-          if (focusController)
-            focusController->SetSuppressFocus(PR_FALSE,
-                                              "NS_GOTFOCUS ESM Suppression");
-        }
-
-        // Now we should fire the focus event.  We fire it on the document,
-        // then the content node, then the window.
-
-        nsCOMPtr<nsPIDOMWindow> window(mDocument->GetWindow());
-
-        if (window) {
-          // We don't want there to be a focused content node while we're
-          // dispatching the focus event.
-
-          nsCOMPtr<nsIContent> currentFocus = mCurrentFocus;
-          // "leak" this reference, but we take it back later
-          SetFocusedContent(nsnull);
-
-          nsIMEStateManager::OnChangeFocus(mPresContext, currentFocus);
-
-          nsEvent focusEvent(PR_TRUE, NS_FOCUS_CONTENT);
-          focusEvent.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
-
-          if (gLastFocusedDocument != mDocument) {
-            FireFocusOrBlurEvent(mDocument, &focusEvent, aPresContext);
-            if (currentFocus && currentFocus != gLastFocusedContent) {
-              // Clear the target so that Dispatch can set it back correctly.
-              focusEvent.target = nsnull;
-              FireFocusOrBlurEvent(currentFocus, &focusEvent, aPresContext);
-            }
-          }
-
-          // Clear the target so that Dispatch can set it back correctly.
-          focusEvent.target = nsnull;
-          nsCOMPtr<nsPIDOMEventTarget> win = do_QueryInterface(window);
-          FireFocusOrBlurEvent(win, &focusEvent, aPresContext);
-
-          SetFocusedContent(currentFocus); // we kept this reference above
-          NS_IF_RELEASE(gLastFocusedContent);
-          gLastFocusedContent = mCurrentFocus;
-          NS_IF_ADDREF(gLastFocusedContent);
-
-          nsIMEStateManager::OnTextStateFocus(mPresContext, mCurrentFocus);
-        }
-
-        // Try to keep the focus controllers and the globals in synch
-        if (gLastFocusedDocument && gLastFocusedDocument != mDocument) {
-
-          nsIFocusController *lastController = nsnull;
-          nsPIDOMWindow* lastWindow = gLastFocusedDocument->GetWindow();
-          if (lastWindow)
-            lastController = lastWindow->GetRootFocusController();
-
-          nsIFocusController *nextController = nsnull;
-          nsPIDOMWindow* nextWindow = mDocument->GetWindow();
-          if (nextWindow)
-            nextController = nextWindow->GetRootFocusController();
-
-          if (lastController != nextController && lastController && nextController)
-            lastController->SetActive(PR_FALSE);
-        }
-
-        NS_IF_RELEASE(gLastFocusedDocument);
-        gLastFocusedDocument = mDocument;
-        gLastFocusedPresContextWeak = aPresContext;
-        NS_IF_ADDREF(gLastFocusedDocument);
-      }
-
-      ResetBrowseWithCaret();
-    }
-
-    break;
-
-  case NS_LOSTFOCUS:
-    {
-#ifdef DEBUG_smaug
-      printf("nsEventStateManager::PreHandleEvent, NS_LOSTFOCUS \n");
-#endif
-      userFocus.MaybeSuppress();
-      // Hide the caret if it's visible.
-      if (mPresContext) {
-        nsIPresShell *presShell = mPresContext->GetPresShell();
-        if (presShell) {
-           nsRefPtr<nsCaret> caret;
-           presShell->GetCaret(getter_AddRefs(caret));
-           if (caret) {
-             PRBool caretVisible = PR_FALSE;
-             caret->GetCaretVisible(&caretVisible);
-             if (caretVisible) {
-               SetContentCaretVisible(presShell, mCurrentFocus, PR_FALSE);
-             }
-           }
-        }
-      }
-
-      // If focus is going to another mozilla window, we wait for the
-      // focus event and fire a blur on the old focused content at that time.
-      // This allows "-moz-user-focus: ignore" to work.
-
-#if defined(XP_WIN) || defined(XP_OS2)
-      //XXXsmaug Change all the NS_LOSTFOCUS/GOTFOCUS events to use
-      //         the same event struct type!
-      if (aEvent->eventStructType == NS_FOCUS_EVENT &&
-          !static_cast<nsFocusEvent*>(aEvent)->isMozWindowTakingFocus) {
-
-        // This situation occurs when focus goes to a non-gecko child window
-        // in an embedding application.  In this case we do fire a blur
-        // immediately.
-
-        EnsureDocument(aPresContext);
-
-        if (gLastFocusedContent && !gLastFocusedContent->IsInDoc()) {
-          NS_RELEASE(gLastFocusedContent);
-        }
-
-        nsIMEStateManager::OnTextStateBlur(nsnull, nsnull);
-
-        // Now fire blurs.  We fire a blur on the focused document, element,
-        // and window.
-        nsEvent blurEvent(PR_TRUE, NS_BLUR_CONTENT);
-        blurEvent.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
-
-        if (gLastFocusedDocument && gLastFocusedPresContextWeak) {
-          if (gLastFocusedContent) {
-            // Retrieve this content node's pres context. it can be out of sync
-            // in the Ender widget case.
-            nsCOMPtr<nsIDocument> doc = gLastFocusedContent->GetDocument();
-            if (doc) {
-              nsIPresShell *shell = doc->GetPrimaryShell();
-              if (shell) {
-                nsCOMPtr<nsPresContext> oldPresContext =
-                  shell->GetPresContext();
-
-                nsCOMPtr<nsIEventStateManager> esm =
-                  oldPresContext->EventStateManager();
-                esm->SetFocusedContent(gLastFocusedContent);
-                FireFocusOrBlurEvent(gLastFocusedContent, &blurEvent, oldPresContext);
-                esm->SetFocusedContent(nsnull);
-                NS_IF_RELEASE(gLastFocusedContent);
-              }
-            }
-          }
-
-          // Clear our global variables before firing the event to prevent
-          // duplicate blur events (bug 112294).
-          nsCOMPtr<nsIDocument> lastFocusedDocument;
-          lastFocusedDocument.swap(gLastFocusedDocument);
-          nsCOMPtr<nsPresContext> lastFocusedPresContext = gLastFocusedPresContextWeak;
-          gLastFocusedPresContextWeak = nsnull;
-          mCurrentTarget = nsnull;
-
-          // fire blur on document and window
-          if (lastFocusedDocument) {
-            // get the window here, in case the event causes
-            // gLastFocusedDocument to change.
-
-            nsCOMPtr<nsPIDOMWindow> window(lastFocusedDocument->GetWindow());
-
-            blurEvent.target = nsnull;
-            FireFocusOrBlurEvent(lastFocusedDocument, &blurEvent, lastFocusedPresContext);
-
-            if (window) {
-              blurEvent.target = nsnull;
-              nsCOMPtr<nsPIDOMEventTarget> win = do_QueryInterface(window);
-              FireFocusOrBlurEvent(win, &blurEvent ,lastFocusedPresContext);
-            }
-          }
-        }
-      }
-#endif
-    }
-    break;
-
- case NS_ACTIVATE:
-    {
-#ifdef DEBUG_smaug
-      printf("nsEventStateManager::PreHandleEvent, NS_ACTIVATE \n");
-#endif
-      userFocus.MaybeSuppress();
-      // If we have a focus controller, and if it has a focused window and a
-      // focused element in its focus memory, then restore the focus to those
-      // objects.
-
-      EnsureDocument(aPresContext);
-
-      nsCOMPtr<nsPIDOMWindow> win = mDocument->GetWindow();
-
-      if (!win) {
-        // NS_ERROR("win is null.  this happens [often on xlib builds].  see bug #79213");
-        return NS_ERROR_NULL_POINTER;
-      }
-
-      // Hold a strong ref to the focus controller, since we need
-      // it after event dispatch.
-      nsCOMPtr<nsIFocusController> focusController =
-        win->GetRootFocusController();
-      nsCOMPtr<nsIDOMElement> focusedElement;
-      nsCOMPtr<nsIDOMWindowInternal> focusedWindow;
-      nsFocusScrollSuppressor scrollSuppressor;
-
-      if (focusController) {
-        // Obtain focus info from the focus controller.
-        focusController->GetFocusedWindow(getter_AddRefs(focusedWindow));
-        focusController->GetFocusedElement(getter_AddRefs(focusedElement));
-
-        scrollSuppressor.Init(focusController);
-        focusController->SetActive(PR_TRUE);
-      }
-
-      if (!focusedWindow)
-        focusedWindow = win;
-
-      NS_ASSERTION(focusedWindow,"check why focusedWindow is null!!!");
-
-      // Focus the DOM window.
-      if (focusedWindow) {
-        focusedWindow->Focus();
-
-        nsCOMPtr<nsIDocument> document = GetDocumentFromWindow(focusedWindow);
-
-        if (document) {
-          // Use a strong ref to make sure that the shell is alive still
-          // when calling FrameSelection().
-          nsCOMPtr<nsIPresShell> shell = document->GetPrimaryShell();
-          NS_ASSERTION(shell, "Focus events should not be getting thru when this is null!");
-          if (shell) {
-            nsPresContext* context = shell->GetPresContext();
-            nsIMEStateManager::OnActivate(context);
-            if (focusedElement) {
-              nsCOMPtr<nsIContent> focusContent = do_QueryInterface(focusedElement);
-              focusContent->SetFocus(context);
-            } else {
-              nsIMEStateManager::OnChangeFocus(context, nsnull);
-            }
-
-            // disable selection mousedown state on activation
-            nsCOMPtr<nsFrameSelection> frameSelection = shell->FrameSelection();
-            frameSelection->SetMouseDownState(PR_FALSE);
-          }
-        }
-      }
-
-      if (focusController) {
-        // Make sure the focus controller is up-to-date, since restoring
-        // focus memory may have caused focus to go elsewhere.
-
-        if (gLastFocusedDocument && gLastFocusedDocument == mDocument) {
-          nsCOMPtr<nsIDOMElement> focusElement = do_QueryInterface(mCurrentFocus);
-          focusController->SetFocusedElement(focusElement);
-        }
-
-        PRBool isSuppressed;
-        focusController->GetSuppressFocus(&isSuppressed);
-        while (isSuppressed) {
-          // Unsuppress and let the focus controller listen again.
-          focusController->SetSuppressFocus(PR_FALSE,
-                                            "Activation Suppression");
-
-          focusController->GetSuppressFocus(&isSuppressed);
-        }
-      }
-    }
-    break;
-
- case NS_DEACTIVATE:
-    {
-#ifdef DEBUG_smaug
-      printf("nsEventStateManager::PreHandleEvent, NS_DEACTIVATE \n");
-#endif
-      userFocus.MaybeSuppress();
-      EnsureDocument(aPresContext);
-
-      nsIMEStateManager::OnDeactivate(aPresContext);
-
-      nsCOMPtr<nsPIDOMWindow> ourWindow(mDocument->GetWindow());
-
-      // Suppress the focus controller for the duration of the
-      // de-activation.  This will cause it to remember the last
-      // focused sub-window and sub-element for this top-level
-      // window.
-
-      nsCOMPtr<nsIFocusController> focusController =
-        GetFocusControllerForDocument(mDocument);
-
-      if (focusController)
-        focusController->SetSuppressFocus(PR_TRUE, "Deactivate Suppression");
-
-      nsIMEStateManager::OnTextStateBlur(nsnull, nsnull);
-
-      // Now fire blurs.  Blur the content, then the document, then the window.
-
-      if (gLastFocusedDocument && gLastFocusedDocument == mDocument &&
-          gLastFocusedDocument != mFirstDocumentBlurEvent) {
-
-        PRBool clearFirstDocumentBlurEvent = PR_FALSE;
-        if (!mFirstDocumentBlurEvent) {
-          mFirstDocumentBlurEvent = gLastFocusedDocument;
-          clearFirstDocumentBlurEvent = PR_TRUE;
-        }
-
-        nsEvent blurEvent(PR_TRUE, NS_BLUR_CONTENT);
-        blurEvent.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
-
-        if (gLastFocusedContent) {
-          nsIPresShell *shell = gLastFocusedDocument->GetPrimaryShell();
-          if (shell) {
-            nsCOMPtr<nsPresContext> oldPresContext = shell->GetPresContext();
-
-            nsCOMPtr<nsIDOMElement> focusedElement;
-            if (focusController)
-              focusController->GetFocusedElement(getter_AddRefs(focusedElement));
-
-            nsCOMPtr<nsIEventStateManager> esm;
-            esm = oldPresContext->EventStateManager();
-            esm->SetFocusedContent(gLastFocusedContent);
-
-            nsCOMPtr<nsIContent> focusedContent = do_QueryInterface(focusedElement);
-            if (focusedContent) {
-              // Blur the element.
-              FireFocusOrBlurEvent(focusedContent, &blurEvent, oldPresContext);
-            }
-
-            esm->SetFocusedContent(nsnull);
-            NS_IF_RELEASE(gLastFocusedContent);
-          }
-        }
-
-        // Clear our global variables before firing the event to prevent
-        // duplicate blur events (bug 112294).
-        mCurrentTarget = nsnull;
-        NS_IF_RELEASE(gLastFocusedDocument);
-        gLastFocusedPresContextWeak = nsnull;
-
-        // fire blur on document and window
-        blurEvent.target = nsnull;
-        FireFocusOrBlurEvent(mDocument, &blurEvent, aPresContext);
-
-        if (ourWindow) {
-          blurEvent.target = nsnull;
-          nsCOMPtr<nsPIDOMEventTarget> win = do_QueryInterface(ourWindow);
-          FireFocusOrBlurEvent(win, &blurEvent, aPresContext);
-        }
-        if (clearFirstDocumentBlurEvent) {
-          mFirstDocumentBlurEvent = nsnull;
-        }
-      }
-
-      if (focusController) {
-        focusController->SetActive(PR_FALSE);
-        focusController->SetSuppressFocus(PR_FALSE, "Deactivate Suppression");
-      }
-    }
-
-    break;
 
   case NS_KEY_PRESS:
     {
 
       nsKeyEvent* keyEvent = (nsKeyEvent*)aEvent;
 
       PRInt32 modifierMask = 0;
       if (keyEvent->isShift)
@@ -1587,26 +1019,26 @@ nsEventStateManager::PreHandleEvent(nsPr
       if (modifierMask && (modifierMask == sChromeAccessModifier ||
                            modifierMask == sContentAccessModifier))
         HandleAccessKey(aPresContext, keyEvent, aStatus, nsnull,
                         eAccessKeyProcessingNormal, modifierMask);
     }
   case NS_KEY_DOWN:
   case NS_KEY_UP:
     {
-      if (mCurrentFocus) {
-        mCurrentTargetContent = mCurrentFocus;
-      }
+      nsIContent* content = GetFocusedContent();
+      if (content)
+        mCurrentTargetContent = content;
     }
     break;
   case NS_MOUSE_SCROLL:
     {
-      if (mCurrentFocus) {
-        mCurrentTargetContent = mCurrentFocus;
-      }
+      nsIContent* content = GetFocusedContent();
+      if (content)
+        mCurrentTargetContent = content;
 
       nsMouseScrollEvent* msEvent = static_cast<nsMouseScrollEvent*>(aEvent);
 
       NS_NAMED_LITERAL_CSTRING(actionslot,      ".action");
       NS_NAMED_LITERAL_CSTRING(numlinesslot,    ".numlines");
       NS_NAMED_LITERAL_CSTRING(sysnumlinesslot, ".sysnumlines");
 
       nsCAutoString baseKey;
@@ -1654,19 +1086,19 @@ nsEventStateManager::PreHandleEvent(nsPr
           msEvent->delta = (msEvent->delta > 0)
             ? PRInt32(nsIDOMNSUIEvent::SCROLL_PAGE_DOWN)
             : PRInt32(nsIDOMNSUIEvent::SCROLL_PAGE_UP);
       }
     }
     break;
   case NS_MOUSE_PIXEL_SCROLL:
     {
-      if (mCurrentFocus) {
-        mCurrentTargetContent = mCurrentFocus;
-      }
+      nsIContent* content = GetFocusedContent();
+      if (content)
+        mCurrentTargetContent = content;
 
       nsMouseScrollEvent *msEvent = static_cast<nsMouseScrollEvent*>(aEvent);
 
       // Clear old deltas after a period of non action
       if (OutOfTime(gPixelScrollDeltaTimeout, nsMouseWheelTransaction::GetTimeoutTime())) {
         gPixelScrollDeltaX = gPixelScrollDeltaY = 0;
       }
       gPixelScrollDeltaTimeout = PR_IntervalToMilliseconds(PR_IntervalNow());
@@ -1840,20 +1272,21 @@ IsAccessKeyTarget(nsIContent* aContent, 
   return PR_FALSE;
 }
 
 PRBool
 nsEventStateManager::ExecuteAccessKey(nsTArray<PRUint32>& aAccessCharCodes,
                                       PRBool aIsTrustedEvent)
 {
   PRInt32 count, start = -1;
-  if (mCurrentFocus) {
-    start = mAccessKeys.IndexOf(mCurrentFocus);
-    if (start == -1 && mCurrentFocus->GetBindingParent())
-      start = mAccessKeys.IndexOf(mCurrentFocus->GetBindingParent());
+  nsIContent* focusedContent = GetFocusedContent();
+  if (focusedContent) {
+    start = mAccessKeys.IndexOf(focusedContent);
+    if (start == -1 && focusedContent->GetBindingParent())
+      start = mAccessKeys.IndexOf(focusedContent->GetBindingParent());
   }
   nsIContent *content;
   nsIFrame *frame;
   PRInt32 length = mAccessKeys.Count();
   for (PRUint32 i = 0; i < aAccessCharCodes.Length(); ++i) {
     PRUint32 ch = aAccessCharCodes[i];
     nsAutoString accessKey;
     AppendUCS4ToUTF16(ch, accessKey);
@@ -1865,18 +1298,23 @@ nsEventStateManager::ExecuteAccessKey(ns
         while (shouldActivate && ++count <= length) {
           nsIContent *oc = mAccessKeys[(start + count) % length];
           nsIFrame *of = mPresContext->PresShell()->GetPrimaryFrameFor(oc);
           if (IsAccessKeyTarget(oc, of, accessKey))
             shouldActivate = PR_FALSE;
         }
         if (shouldActivate)
           content->PerformAccesskey(shouldActivate, aIsTrustedEvent);
-        else if (frame && frame->IsFocusable())
-          ChangeFocusWith(content, eEventFocusedByKey);
+        else {
+          nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+          if (fm) {
+            nsCOMPtr<nsIDOMElement> element = do_QueryInterface(content);
+            fm->SetFocus(element, nsIFocusManager::FLAG_BYKEY);
+          }
+        }
         return PR_TRUE;
       }
     }
   }
   return PR_FALSE;
 }
 
 void
@@ -2643,19 +2081,23 @@ nsEventStateManager::DoDefaultDragStart(
   }
 }
 
 nsresult
 nsEventStateManager::GetMarkupDocumentViewer(nsIMarkupDocumentViewer** aMv)
 {
   *aMv = nsnull;
 
-  if(!gLastFocusedDocument) return NS_ERROR_FAILURE;
-
-  nsPIDOMWindow* ourWindow = gLastFocusedDocument->GetWindow();
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+  if(!fm) return NS_ERROR_FAILURE;
+
+  nsCOMPtr<nsIDOMWindow> focusedWindow;
+  fm->GetFocusedWindow(getter_AddRefs(focusedWindow));
+
+  nsCOMPtr<nsPIDOMWindow> ourWindow = do_QueryInterface(focusedWindow);
   if(!ourWindow) return NS_ERROR_FAILURE;
 
   nsIDOMWindowInternal *rootWindow = ourWindow->GetPrivateRoot();
   if(!rootWindow) return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsIDOMWindow> contentWindow;
   rootWindow->GetContent(getter_AddRefs(contentWindow));
   if(!contentWindow) return NS_ERROR_FAILURE;
@@ -2815,17 +2257,17 @@ void
 nsEventStateManager::SendLineScrollEvent(nsIFrame* aTargetFrame,
                                          nsMouseScrollEvent* aEvent,
                                          nsPresContext* aPresContext,
                                          nsEventStatus* aStatus,
                                          PRInt32 aNumLines)
 {
   nsCOMPtr<nsIContent> targetContent = aTargetFrame->GetContent();
   if (!targetContent)
-    GetFocusedContent(getter_AddRefs(targetContent));
+    targetContent = GetFocusedContent();
   if (!targetContent)
     return;
 
   while (targetContent->IsNodeOfType(nsINode::eTEXT)) {
     targetContent = targetContent->GetParent();
   }
 
   PRBool isTrusted = (aEvent->flags & NS_EVENT_FLAG_TRUSTED) != 0;
@@ -2845,20 +2287,21 @@ nsEventStateManager::SendLineScrollEvent
 
 void
 nsEventStateManager::SendPixelScrollEvent(nsIFrame* aTargetFrame,
                                           nsMouseScrollEvent* aEvent,
                                           nsPresContext* aPresContext,
                                           nsEventStatus* aStatus)
 {
   nsCOMPtr<nsIContent> targetContent = aTargetFrame->GetContent();
-  if (!targetContent)
-    GetFocusedContent(getter_AddRefs(targetContent));
-  if (!targetContent)
-    return;
+  if (!targetContent) {
+    targetContent = GetFocusedContent();
+    if (!targetContent)
+      return;
+  }
 
   while (targetContent->IsNodeOfType(nsINode::eTEXT)) {
     targetContent = targetContent->GetParent();
   }
 
   nscoord lineHeight = GetScrollableViewLineHeight(aPresContext, aTargetFrame);
 
   PRBool isTrusted = (aEvent->flags & NS_EVENT_FLAG_TRUSTED) != 0;
@@ -3135,29 +2578,28 @@ nsEventStateManager::PostHandleEvent(nsP
             }
           }
         }
         break;
       }
 
       if (nsEventStatus_eConsumeNoDefault != *aStatus) {
         nsCOMPtr<nsIContent> newFocus;
+        nsIContent* activeContent = nsnull;
         PRBool suppressBlur = PR_FALSE;
         if (mCurrentTarget) {
           mCurrentTarget->GetContentForEvent(mPresContext, aEvent, getter_AddRefs(newFocus));
           const nsStyleUserInterface* ui = mCurrentTarget->GetStyleUserInterface();
           suppressBlur = (ui->mUserFocus == NS_STYLE_USER_FOCUS_IGNORE);
+          activeContent = mCurrentTarget->GetContent();
         }
 
+        // When the mouse is pressed, the default action is to focus the
+        // target. Look for the nearest enclosing focusable frame.
         nsIFrame* currFrame = mCurrentTarget;
-        nsIContent* activeContent = nsnull;
-        if (mCurrentTarget)
-          activeContent = mCurrentTarget->GetContent();
-
-        // Look for the nearest enclosing focusable frame.
         while (currFrame) {
           // If the mousedown happened inside a popup, don't
           // try to set focus on one of its containing elements
           const nsStyleDisplay* display = currFrame->GetStyleDisplay();
           if (display->mDisplay == NS_STYLE_DISPLAY_POPUP) {
             newFocus = nsnull;
             break;
           }
@@ -3167,20 +2609,44 @@ nsEventStateManager::PostHandleEvent(nsP
             newFocus = currFrame->GetContent();
             nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(newFocus));
             if (domElement)
               break;
           }
           currFrame = currFrame->GetParent();
         }
 
-        if (newFocus && currFrame)
-          ChangeFocusWith(newFocus, eEventFocusedByMouse);
-        else if (!suppressBlur) {
-          SetContentState(nsnull, NS_EVENT_STATE_FOCUS);
+        nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+        if (fm) {
+          // if something was found to focus, focus it. Otherwise, if the
+          // element that was clicked doesn't have -moz-user-focus: ignore,
+          // clear the existing focus. For -moz-user-focus: ignore, the focus
+          // is just left as is.
+          // Another effect of mouse clicking, handled in nsSelection, is that
+          // it should update the caret position to where the mouse was
+          // clicked. Because the focus is cleared when clicking on a
+          // non-focusable node, the next press of the tab key will cause
+          // focus to be shifted from the caret position instead of the root.
+          if (newFocus && currFrame) {
+            // use the mouse flag and the noscroll flag so that the content
+            // doesn't unexpectedly scroll when clicking an element that is
+            // only hald visible
+            nsCOMPtr<nsIDOMElement> newFocusElement = do_QueryInterface(newFocus);
+            fm->SetFocus(newFocusElement, nsIFocusManager::FLAG_BYMOUSE |
+                                          nsIFocusManager::FLAG_NOSCROLL);
+          }
+          else if (!suppressBlur) {
+            // clear the focus within the frame and then set it as the
+            // focused frame
+            EnsureDocument(mPresContext);
+            if (mDocument) {
+              fm->ClearFocus(mDocument->GetWindow());
+              fm->SetFocusedWindow(mDocument->GetWindow());
+            }
+          }
         }
 
         // The rest is left button-specific.
         if (static_cast<nsMouseEvent*>(aEvent)->button !=
             nsMouseEvent::eLeftButton)
           break;
 
         if (activeContent) {
@@ -3447,57 +2913,62 @@ nsEventStateManager::PostHandleEvent(nsP
 
   case NS_KEY_PRESS:
     if (nsEventStatus_eConsumeNoDefault != *aStatus) {
       nsKeyEvent* keyEvent = (nsKeyEvent*)aEvent;
       //This is to prevent keyboard scrolling while alt modifier in use.
       if (!keyEvent->isAlt) {
         switch(keyEvent->keyCode) {
           case NS_VK_TAB:
-            if (!((nsInputEvent*)aEvent)->isControl) {
-              //Shift focus forward or back depending on shift key
-              ShiftFocus(!((nsInputEvent*)aEvent)->isShift);
-            } else {
-              ShiftFocusByDoc(!((nsInputEvent*)aEvent)->isShift);
+          case NS_VK_F6:
+            EnsureDocument(mPresContext);
+            nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+            if (fm && mDocument) {
+              // Shift focus forward or back depending on shift key
+              PRBool isDocMove = ((nsInputEvent*)aEvent)->isControl ||
+                                 (keyEvent->keyCode == NS_VK_F6);
+              PRUint32 dir = ((nsInputEvent*)aEvent)->isShift ?
+                             (isDocMove ? nsIFocusManager::MOVEFOCUS_BACKWARDDOC :
+                                          nsIFocusManager::MOVEFOCUS_BACKWARD) :
+                             (isDocMove ? nsIFocusManager::MOVEFOCUS_FORWARDDOC :
+                                          nsIFocusManager::MOVEFOCUS_FORWARD);
+              nsCOMPtr<nsIDOMElement> result;
+              fm->MoveFocus(mDocument->GetWindow(), nsnull, dir,
+                            nsIFocusManager::FLAG_BYKEY,
+                            getter_AddRefs(result));
             }
             *aStatus = nsEventStatus_eConsumeNoDefault;
             break;
 
-          case NS_VK_F6:
-            //Shift focus forward or back depending on shift key
-            ShiftFocusByDoc(!((nsInputEvent*)aEvent)->isShift);
-            *aStatus = nsEventStatus_eConsumeNoDefault;
-            break;
-
 //the problem is that viewer does not have xul so we cannot completely eliminate these
 #if NON_KEYBINDING
           case NS_VK_PAGE_DOWN:
           case NS_VK_PAGE_UP:
-            if (!mCurrentFocus) {
+            if (!focusedContent) {
               nsIScrollableView* sv = nsLayoutUtils::GetNearestScrollingView(aView, nsLayoutUtils::eVertical);
               if (sv) {
                 nsKeyEvent * keyEvent = (nsKeyEvent *)aEvent;
                 sv->ScrollByPages(0, (keyEvent->keyCode != NS_VK_PAGE_UP) ? 1 : -1,
                                   NS_VMREFRESH_SMOOTHSCROLL);
               }
             }
             break;
           case NS_VK_HOME:
           case NS_VK_END:
-            if (!mCurrentFocus) {
+            if (!focusedContent) {
               nsIScrollableView* sv = nsLayoutUtils::GetNearestScrollingView(aView, nsLayoutUtils::eVertical);
               if (sv) {
                 nsKeyEvent * keyEvent = (nsKeyEvent *)aEvent;
                 sv->ScrollByWhole((keyEvent->keyCode != NS_VK_HOME) ? PR_FALSE : PR_TRUE);
               }
             }
             break;
           case NS_VK_DOWN:
           case NS_VK_UP:
-            if (!mCurrentFocus) {
+            if (!focusedContent) {
               nsIScrollableView* sv = nsLayoutUtils::GetNearestScrollingView(aView, nsLayoutUtils::eVertical);
               if (sv) {
                 nsKeyEvent * keyEvent = (nsKeyEvent *)aEvent;
                 sv->ScrollByLines(0, (keyEvent->keyCode == NS_VK_DOWN) ? 1 : -1,
                                   NS_VMREFRESH_SMOOTHSCROLL);
 
                 // force the update to happen now, otherwise multiple scrolls can
                 // occur before the update is processed. (bug #7354)
@@ -3507,17 +2978,17 @@ nsEventStateManager::PostHandleEvent(nsP
                   // vm->Composite();
                   vm->ForceUpdate();
                 }
               }
             }
             break;
           case NS_VK_LEFT:
           case NS_VK_RIGHT:
-            if (!mCurrentFocus) {
+            if (!focusedContent) {
               nsIScrollableView* sv = nsLayoutUtils::GetNearestScrollingView(aView, nsLayoutUtils::eHorizontal);
               if (sv) {
                 nsKeyEvent * keyEvent = (nsKeyEvent *)aEvent;
                 sv->ScrollByLines((keyEvent->keyCode == NS_VK_RIGHT) ? 1 : -1, 0,
                                   NS_VMREFRESH_SMOOTHSCROLL);
 
                 // force the update to happen now, otherwise multiple scrolls can
                 // occur before the update is processed. (bug #7354)
@@ -3530,17 +3001,17 @@ nsEventStateManager::PostHandleEvent(nsP
               }
             }
             break;
         case 0: /* check charcode since keycode is 0 */
           {
           //Spacebar
             nsKeyEvent * keyEvent = (nsKeyEvent *)aEvent;
             if (keyEvent->charCode == 0x20) {
-              if (!mCurrentFocus) {
+              if (!focusedContent) {
                 nsIScrollableView* sv = nsLayoutUtils::GetNearestScrollingView(aView, nsLayoutUtils::eVertical);
                 if (sv) {
                   sv->ScrollByPages(0, 1, NS_VMREFRESH_SMOOTHSCROLL);
                 }
               }
             }
           }
           break;
@@ -3571,26 +3042,16 @@ nsEventStateManager::NotifyDestroyPresCo
 {
   nsIMEStateManager::OnDestroyPresContext(aPresContext);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsEventStateManager::SetPresContext(nsPresContext* aPresContext)
 {
-  if (aPresContext == nsnull) {
-    // XXX should we move this block to |NotifyDestroyPresContext|?
-    // A pres context is going away. Make sure we do cleanup.
-    if (mPresContext == gLastFocusedPresContextWeak) {
-      gLastFocusedPresContextWeak = nsnull;
-      NS_IF_RELEASE(gLastFocusedDocument);
-      NS_IF_RELEASE(gLastFocusedContent);
-    }
-  }
-
   mPresContext = aPresContext;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsEventStateManager::ClearFrameRefs(nsIFrame* aFrame)
 {
   if (aFrame && aFrame == mCurrentTarget) {
@@ -4252,635 +3713,16 @@ nsEventStateManager::CheckForAndDispatch
                                                mouseContent, aStatus);
       }
     }
   }
   return ret;
 }
 
 NS_IMETHODIMP
-nsEventStateManager::ChangeFocusWith(nsIContent* aFocusContent,
-                                     EFocusedWithType aFocusedWith)
-{
-  mLastFocusedWith = aFocusedWith;
-  if (!aFocusContent) {
-    SetContentState(nsnull, NS_EVENT_STATE_FOCUS);
-    return NS_OK;
-  }
-
-  // Get focus controller.
-  EnsureDocument(mPresContext);
-  nsCOMPtr<nsIFocusController> focusController = nsnull;
-  nsCOMPtr<nsPIDOMWindow> window(mDocument->GetWindow());
-  if (window)
-    focusController = window->GetRootFocusController();
-
-  // If this is called from mouse event, we lock to scroll.
-  // Because the part of element is always in view. See bug 105894.
-  nsFocusScrollSuppressor scrollSuppressor;
-  if (aFocusedWith == eEventFocusedByMouse) {
-    scrollSuppressor.Init(focusController);
-  }
-
-  aFocusContent->SetFocus(mPresContext);
-  if (aFocusedWith != eEventFocusedByMouse) {
-    MoveCaretToFocus();
-    // Select text fields when focused via keyboard (tab or accesskey)
-    if (sTextfieldSelectModel == eTextfieldSelect_auto &&
-        mCurrentFocus &&
-        mCurrentFocus->IsNodeOfType(nsINode::eHTML_FORM_CONTROL)) {
-      nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(mCurrentFocus));
-      PRInt32 controlType = formControl->GetType();
-      if (controlType == NS_FORM_INPUT_TEXT ||
-          controlType == NS_FORM_INPUT_PASSWORD) {
-        nsCOMPtr<nsIDOMHTMLInputElement> inputElement =
-          do_QueryInterface(mCurrentFocus);
-        if (inputElement) {
-          inputElement->Select();
-        }
-      }
-    }
-  }
-  return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsEventStateManager::ShiftFocus(PRBool aForward, nsIContent* aStart)
-{
-  nsCOMPtr<nsILookAndFeel> lookNFeel(do_GetService(kLookAndFeelCID));
-  lookNFeel->GetMetric(nsILookAndFeel::eMetric_TabFocusModel,
-                       nsIContent::sTabFocusModel);
-
-  // We use mTabbedThroughDocument to indicate that we have passed
-  // the end (or beginning) of the document we started tabbing from,
-  // without finding anything else to focus.  If we pass the end of
-  // the same document again (and the flag is set), we know that there
-  // is no focusable content anywhere in the tree, and should stop.
-
-  mTabbedThroughDocument = PR_FALSE;
-  return ShiftFocusInternal(aForward, aStart);
-}
-
-nsresult
-nsEventStateManager::ShiftFocusInternal(PRBool aForward, nsIContent* aStart)
-{
-#ifdef DEBUG_DOCSHELL_FOCUS
-  printf("[%p] ShiftFocusInternal: aForward=%d, aStart=%p, mCurrentFocus=%p\n",
-         static_cast<void*>(this), aForward, static_cast<void*>(aStart),
-         static_cast<void*>(mCurrentFocus.get()));
-#endif
-  NS_ASSERTION(mPresContext, "no pres context");
-  EnsureDocument(mPresContext);
-  NS_ASSERTION(mDocument, "no document");
-
-  nsCOMPtr<nsIContent> rootContent = mDocument->GetRootContent();
-
-  nsCOMPtr<nsISupports> pcContainer = mPresContext->GetContainer();
-  nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(pcContainer));
-  NS_ENSURE_STATE(docShell);
-  PRBool docHasFocus = PR_FALSE;
-
-  // ignoreTabIndex allows the user to tab to the next link after clicking before it link in the page
-  // or using find text to get to the link. Without ignoreTabIndex in those cases, pages that
-  // use tabindex would still enforce that order in those situations.
-  PRBool ignoreTabIndex = PR_FALSE;
-
-  if (!aStart && !mCurrentFocus) {
-    // mCurrentFocus is ambiguous for determining whether
-    // we're in document-focus mode, because it's nulled out
-    // when the document is blurred, and it's also nulled out
-    // when the document/canvas has focus.
-    //
-    // So, use the docshell focus state to disambiguate.
-
-    docShell->GetHasFocus(&docHasFocus);
-  }
-
-  nsIFrame* selectionFrame = nsnull;
-  nsIFrame* curFocusFrame = nsnull;   // This will hold the location we're moving away from
-
-  // If in content, navigate from last cursor position rather than last focus
-  // If we're in UI, selection location will return null
-  nsCOMPtr<nsIPresShell> presShell = mPresContext->PresShell();
-
-  // We might use the selection position, rather than mCurrentFocus, as our position to shift focus from
-  PRInt32 itemType;
-  nsCOMPtr<nsIDocShellTreeItem> shellItem(do_QueryInterface(docShell));
-  shellItem->GetItemType(&itemType);
-
-  // Tab from the selection if it exists, but not if we're in chrome or an explicit starting
-  // point was given.
-  if (!aStart && itemType != nsIDocShellTreeItem::typeChrome) {
-    // We're going to tab from the selection position
-    if (!mCurrentFocus || (mLastFocusedWith != eEventFocusedByMouse && mCurrentFocus->Tag() != nsGkAtoms::area)) {
-      nsCOMPtr<nsIContent> selectionContent, endSelectionContent;  // We won't be using this, need arg for method call
-      PRUint32 selectionOffset; // We won't be using this either, need arg for method call
-      GetDocSelectionLocation(getter_AddRefs(selectionContent), getter_AddRefs(endSelectionContent), &selectionFrame, &selectionOffset);
-      if (selectionContent == rootContent)  // If selection on rootContent, same as null -- we have no selection yet
-        selectionFrame = nsnull;
-      // Don't start from the selection if the selection is in a contentEditable
-      // region.
-      nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(mDocument);
-      if (htmlDoc &&
-          htmlDoc->GetEditingState() == nsIHTMLDocument::eContentEditable &&
-          selectionContent && selectionContent->HasFlag(NODE_IS_EDITABLE))
-        selectionFrame = nsnull;
-      // Only use tabindex if selection is synchronized with focus
-      // That way, if the user clicks in content, or does a find text that lands between focusable elements,
-      // they can then tab relative to that selection
-      if (selectionFrame) {
-        PRBool selectionWithFocus;
-        MoveFocusToCaret(PR_FALSE, &selectionWithFocus);
-        ignoreTabIndex = !selectionWithFocus;
-        // Refresh |selectionFrame| since MoveFocusToCaret() could have
-        // destroyed it. (bug 308086)
-        GetDocSelectionLocation(getter_AddRefs(selectionContent),
-                                getter_AddRefs(endSelectionContent),
-                                &selectionFrame, &selectionOffset);
-      }
-    }
-  }
-
-  nsIContent *startContent = nsnull;
-
-  if (aStart) {
-    curFocusFrame = presShell->GetPrimaryFrameFor(aStart);
-
-    // If there is no frame, we can't navigate from this content node, and we
-    // fall back to navigating from the document root.
-    if (curFocusFrame)
-      startContent = aStart;
-  } else if (selectionFrame) {
-    // We moved focus to the caret location above, so mCurrentFocus
-    // reflects the starting content node.
-    startContent = mCurrentFocus;
-    curFocusFrame = selectionFrame;
-  } else if (!docHasFocus) {
-    startContent = mCurrentFocus;
-    GetFocusedFrame(&curFocusFrame);
-  }
-
-  if (aStart) {
-    if (aStart->HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)) {
-      aStart->IsFocusable(&mCurrentTabIndex);
-    } else {
-      ignoreTabIndex = PR_TRUE; // ignore current tabindex, bug 81481
-    }
-  } else if (!mCurrentFocus) {  // Get tabindex ready
-    if (aForward) {
-      mCurrentTabIndex = docHasFocus && selectionFrame ? 0 : 1;
-    } else if (!docHasFocus) {
-      mCurrentTabIndex = 0;
-    } else if (selectionFrame) {
-      mCurrentTabIndex = 1;   // will keep it from wrapping around to end
-    }
-  }
-
-  // when a popup is open, we want to ensure that tab navigation occurs only
-  // within the most recently opened panel. If a popup is open, its frame will
-  // be stored in popupFrame.
-  nsIFrame* popupFrame = nsnull;
-  if (curFocusFrame) {
-    // check if the focus is currently inside a popup. Elements such as the
-    // autocomplete widget use the noautofocus attribute to allow the focus to
-    // remain outside the popup when it is opened.
-    popupFrame = nsLayoutUtils::GetClosestFrameOfType(curFocusFrame,
-                                                      nsGkAtoms::menuPopupFrame);
-  }
-#ifdef MOZ_XUL
-  else {
-    // if there is no focus, yet a panel is open, focus the
-    // first item in the popup
-    nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
-    if (pm) {
-      popupFrame = pm->GetTopPopup(ePopupTypePanel);
-    }
-  }
-#endif
-
-  if (popupFrame) {
-    // Don't navigate outside of a popup, so pretend that the
-    // root content is the popup itself
-    rootContent = popupFrame->GetContent();
-    NS_ASSERTION(rootContent, "Popup frame doesn't have a content node");
-  }
-
-  nsCOMPtr<nsIContent> nextFocus;
-  nsIFrame* nextFocusFrame;
-  if (aForward || !docHasFocus || selectionFrame)
-    GetNextTabbableContent(rootContent, startContent, curFocusFrame,
-                           aForward, ignoreTabIndex || mCurrentTabIndex < 0,
-                           getter_AddRefs(nextFocus), &nextFocusFrame);
-
-  if (popupFrame && !nextFocus) {
-    // if no content was found to focus, yet we are inside a popup, try again
-    // from the beginning or end of the popup. Set the current tab index to
-    // the beginning or end.
-    mCurrentTabIndex = aForward ? 1 : 0;
-    GetNextTabbableContent(rootContent, rootContent, nsnull,
-                           aForward, ignoreTabIndex,
-                           getter_AddRefs(nextFocus), &nextFocusFrame);
-    // if the same node was found, don't change the focus
-    if (startContent == nextFocus) {
-      nextFocus = nsnull;
-    }
-  }
-
-  // Clear out mCurrentTabIndex. It has a garbage value because of GetNextTabbableContent()'s side effects
-  // It will be set correctly when focus is changed via ChangeFocusWith()
-  mCurrentTabIndex = 0;
-
-  if (nextFocus) {
-    // Check to see if the next focused element has a subshell.
-    // This is the case for an IFRAME or FRAME element.  If it
-    // does, we send focus into the subshell.
-
-    nsCOMPtr<nsIDocShell> sub_shell;
-    nsCOMPtr<nsIDocument> doc = nextFocus->GetDocument();
-
-    if (doc) {
-      nsIDocument *sub_doc = doc->GetSubDocumentFor(nextFocus);
-
-      if (sub_doc && !sub_doc->EventHandlingSuppressed()) {
-        nsCOMPtr<nsISupports> container = sub_doc->GetContainer();
-        sub_shell = do_QueryInterface(container);
-      }
-    }
-
-    if (sub_shell) {
-      // Make sure to scroll before possibly dispatching focus/blur events.
-      presShell->ScrollContentIntoView(nextFocus,
-                                       NS_PRESSHELL_SCROLL_ANYWHERE,
-                                       NS_PRESSHELL_SCROLL_ANYWHERE);
-
-      SetContentState(nsnull, NS_EVENT_STATE_FOCUS);
-
-      // if we are in the middle of tabbing into
-      // sub_shell, bail out, to avoid recursion
-      // see bug #195011 and bug #137191
-      if (mTabbingFromDocShells.IndexOf(sub_shell) != -1)
-        return NS_OK;
-
-      TabIntoDocument(sub_shell, aForward);
-    } else {
-      // there is no subshell, so just focus nextFocus
-#ifdef DEBUG_DOCSHELL_FOCUS
-      printf("focusing next focusable content: %p\n",
-             static_cast<void*>(nextFocus.get()));
-#endif
-      mCurrentTarget = nextFocusFrame;
-
-      nsCOMPtr<nsIContent> oldFocus(mCurrentFocus);
-      ChangeFocusWith(nextFocus, eEventFocusedByKey);
-      if (!mCurrentFocus && oldFocus) {
-        // ChangeFocusWith failed to move focus to nextFocus because a blur handler
-        // made it unfocusable. (bug #118685)
-        // Try again unless it's from the same point, bug 232368.
-        if (oldFocus != aStart && oldFocus->GetDocument()) {
-          mCurrentTarget = nsnull;
-          return ShiftFocusInternal(aForward, oldFocus);
-        } else {
-          return NS_OK;
-        }
-      } else {
-        if (mCurrentFocus != nextFocus) {
-          // A focus or blur handler switched the focus from one of
-          // its focus/blur/change handlers, don't mess with what the
-          // page wanted...
-
-          return NS_OK;
-        }
-        nsIFrame* focusedFrame = nsnull;
-        GetFocusedFrame(&focusedFrame);
-        mCurrentTarget = focusedFrame;
-      }
-
-      // It's possible that the act of removing focus from our previously
-      // focused element caused nextFocus to be removed from the document.
-      // In this case, we can restart the frame traversal from our previously
-      // focused content.
-
-      if (oldFocus && doc != nextFocus->GetDocument()) {
-        mCurrentTarget = nsnull;
-        return ShiftFocusInternal(aForward, oldFocus);
-      }
-
-      if (!docHasFocus)
-        docShell->SetHasFocus(PR_TRUE);
-    }
-  } else {
-
-    // If we're going backwards past the first content,
-    // focus the document.
-
-    PRBool focusDocument;
-    if (itemType == nsIDocShellTreeItem::typeChrome)
-      focusDocument = PR_FALSE;
-    else {
-      // Check for a frameset document
-      focusDocument = !(IsFrameSetDoc(docShell));
-    }
-
-    if (!aForward && !docHasFocus && focusDocument) {
-#ifdef DEBUG_DOCSHELL_FOCUS
-      printf("Focusing document\n");
-#endif
-      SetContentState(nsnull, NS_EVENT_STATE_FOCUS);
-      docShell->SetHasFocus(PR_TRUE);
-      docShell->SetCanvasHasFocus(PR_TRUE);
-      // Next time forward we start at the beginning of the document
-      // Next time backward we go to URL bar
-      // We need to move the caret to the document root, so that we don't
-      // tab from the most recently focused element next time around
-      SetFocusedContent(rootContent);
-      MoveCaretToFocus();
-      SetFocusedContent(nsnull);
-
-    } else {
-      // If there's nothing left to focus in this document,
-      // pop out to our parent document, and have it shift focus
-      // in the same direction starting at the content element
-      // corresponding to our docshell.
-      // Guard against infinite recursion (see explanation in ShiftFocus)
-
-      if (mTabbedThroughDocument)
-        return NS_OK;
-
-      SetFocusedContent(rootContent);
-      mCurrentTabIndex = 0;
-      MoveCaretToFocus();
-      SetFocusedContent(nsnull);
-
-      mTabbedThroughDocument = PR_TRUE;
-
-      nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(pcContainer);
-      nsCOMPtr<nsIDocShellTreeItem> treeParent;
-      treeItem->GetParent(getter_AddRefs(treeParent));
-      if (treeParent) {
-        nsCOMPtr<nsIDocShell> parentDS = do_QueryInterface(treeParent);
-        if (parentDS) {
-          nsCOMPtr<nsIPresShell> parentShell;
-          parentDS->GetPresShell(getter_AddRefs(parentShell));
-
-          nsCOMPtr<nsIDocument> parent_doc = parentShell->GetDocument();
-          nsCOMPtr<nsIContent> docContent = parent_doc->FindContentForSubDocument(mDocument);
-
-          nsCOMPtr<nsPresContext> parentPC = parentShell->GetPresContext();
-          nsIEventStateManager *parentESM = parentPC->EventStateManager();
-
-          SetContentState(nsnull, NS_EVENT_STATE_FOCUS);
-
-          nsCOMPtr<nsISupports> parentContainer = parentPC->GetContainer();
-          if (parentContainer && docContent && docContent->GetCurrentDoc() == parent_doc) {
-#ifdef DEBUG_DOCSHELL_FOCUS
-            printf("popping out focus to parent docshell\n");
-#endif
-            parentESM->MoveCaretToFocus();
-            parentESM->ShiftFocus(aForward, docContent);
-#ifdef DEBUG_DOCSHELL_FOCUS
-          } else {
-            printf("can't pop out focus to parent docshell\n"); // bug 308025
-#endif
-          }
-        }
-      } else {
-        PRBool tookFocus = PR_FALSE;
-        nsCOMPtr<nsIDocShell> subShell = do_QueryInterface(pcContainer);
-        if (subShell) {
-          subShell->TabToTreeOwner(aForward, &tookFocus);
-        }
-
-#ifdef DEBUG_DOCSHEL_FOCUS
-        printf("offered focus to tree owner, tookFocus=%d\n",
-               tookFocus);
-#endif
-
-        if (tookFocus) {
-          SetContentState(nsnull, NS_EVENT_STATE_FOCUS);
-          docShell->SetHasFocus(PR_FALSE);
-        } else {
-          // there is nowhere else to send the focus, so
-          // refocus ourself.
-          // Next time forward we start at the beginning of the document
-
-#ifdef DEBUG_DOCSHELL_FOCUS
-          printf("wrapping around within this document\n");
-#endif
-
-          SetFocusedContent(nsnull);
-          docShell->SetHasFocus(PR_FALSE);
-          ShiftFocusInternal(aForward);
-        }
-      }
-    }
-  }
-
-  return NS_OK;
-}
-
-nsresult
-nsEventStateManager::GetNextTabbableContent(nsIContent* aRootContent,
-                                            nsIContent* aStartContent,
-                                            nsIFrame* aStartFrame,
-                                            PRBool forward,
-                                            PRBool aIgnoreTabIndex,
-                                            nsIContent** aResultNode,
-                                            nsIFrame** aResultFrame)
-{
-  *aResultNode = nsnull;
-  *aResultFrame = nsnull;
-
-  nsresult rv;
-  nsCOMPtr<nsIFrameTraversal> trav(do_CreateInstance(kFrameTraversalCID, &rv));
-  NS_ENSURE_SUCCESS(rv, rv);
-  nsCOMPtr<nsIFrameEnumerator> frameTraversal;
-
-  // --- Get frame to start with ---
-  if (!aStartFrame) {
-    // No frame means we need to start with the root content again.
-    NS_ENSURE_TRUE(mPresContext, NS_ERROR_FAILURE);
-    nsIPresShell *presShell = mPresContext->GetPresShell();
-    NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
-    aStartFrame = presShell->GetPrimaryFrameFor(aRootContent);
-    NS_ENSURE_TRUE(aStartFrame, NS_ERROR_FAILURE);
-    rv = trav->NewFrameTraversal(getter_AddRefs(frameTraversal),
-                                mPresContext, aStartFrame,
-                                ePreOrder,
-                                PR_FALSE, // aVisual
-                                PR_FALSE, // aLockInScrollView
-                                PR_TRUE   // aFollowOOFs
-                                );
-    NS_ENSURE_SUCCESS(rv, rv);
-    if (!forward) {
-      frameTraversal->Last();
-    }
-  }
-  else {
-    rv = trav->NewFrameTraversal(getter_AddRefs(frameTraversal),
-                                 mPresContext, aStartFrame,
-                                 ePreOrder,
-                                 PR_FALSE, // aVisual
-                                 PR_FALSE, // aLockInScrollView
-                                 PR_TRUE   // aFollowOOFs
-                                 );
-    NS_ENSURE_SUCCESS(rv, rv);
-    if (!aStartContent || aStartContent->Tag() != nsGkAtoms::area ||
-        !aStartContent->IsNodeOfType(nsINode::eHTML)) {
-      // Need to do special check in case we're in an imagemap which has multiple
-      // content per frame, so don't skip over the starting frame.
-      if (forward)
-        frameTraversal->Next();
-      else
-        frameTraversal->Prev();
-    }
-  }
-
-  // -- Walk frames to find something tabbable matching mCurrentTabIndex --
-  while (1) {
-    *aResultFrame = frameTraversal->CurrentItem();
-    if (!*aResultFrame) {
-      break;
-    }
-
-    // TabIndex not set defaults to 0 for form elements, anchors and other
-    // elements that are normally focusable. Tabindex defaults to -1
-    // for elements that are not normally focusable.
-    // The returned computed tabindex from IsFocusable() is as follows:
-    //          < 0 not tabbable at all
-    //          == 0 in normal tab order (last after positive tabindex'd items)
-    //          > 0 can be tabbed to in the order specified by this value
-    PRInt32 tabIndex;
-    nsIContent* currentContent = (*aResultFrame)->GetContent();
-    (*aResultFrame)->IsFocusable(&tabIndex);
-    if (tabIndex >= 0) {
-      if (currentContent->Tag() == nsGkAtoms::img &&
-          currentContent->HasAttr(kNameSpaceID_None, nsGkAtoms::usemap)) {
-        // Must be an image w/ a map -- it's tabbable but no tabindex is specified
-        // Special case for image maps: they don't get walked by nsIFrameTraversal
-        nsIContent *areaContent = GetNextTabbableMapArea(forward, currentContent);
-        if (areaContent) {
-          NS_ADDREF(*aResultNode = areaContent);
-          return NS_OK;
-        }
-      }
-      else if ((aIgnoreTabIndex || mCurrentTabIndex == tabIndex) &&
-          currentContent != aStartContent) {
-        NS_ADDREF(*aResultNode = currentContent);
-        return NS_OK;
-      }
-    }
-    if (forward)
-      frameTraversal->Next();
-    else
-      frameTraversal->Prev();
-  }
-
-  // -- Reached end or beginning of document --
-
-  // If already at lowest priority tab (0), end search completely.
-  // A bit counterintuitive but true, tabindex order goes 1, 2, ... 32767, 0
-  if (mCurrentTabIndex == (forward? 0: 1)) {
-    return NS_OK;
-  }
-
-  // else continue looking for next highest priority tabindex
-  mCurrentTabIndex = GetNextTabIndex(aRootContent, forward);
-  return GetNextTabbableContent(aRootContent, aStartContent, nsnull, forward,
-                                aIgnoreTabIndex, aResultNode, aResultFrame);
-}
-
-nsIContent*
-nsEventStateManager::GetNextTabbableMapArea(PRBool aForward,
-                                            nsIContent *aImageContent)
-{
-  nsAutoString useMap;
-  aImageContent->GetAttr(kNameSpaceID_None, nsGkAtoms::usemap, useMap);
-
-  nsCOMPtr<nsIDocument> doc = aImageContent->GetDocument();
-  if (doc) {
-    nsCOMPtr<nsIDOMHTMLMapElement> imageMap = nsImageMapUtils::FindImageMap(doc, useMap);
-    if (!imageMap)
-      return nsnull;
-    nsCOMPtr<nsIContent> mapContent = do_QueryInterface(imageMap);
-    PRUint32 count = mapContent->GetChildCount();
-    // First see if mCurrentFocus is in this map
-    PRInt32 index = mapContent->IndexOf(mCurrentFocus);
-    PRInt32 tabIndex;
-    if (index < 0 || (mCurrentFocus->IsFocusable(&tabIndex) &&
-                      tabIndex != mCurrentTabIndex)) {
-      // If mCurrentFocus is in this map we must start iterating past it.
-      // We skip the case where mCurrentFocus has tabindex == mCurrentTabIndex
-      // since the next tab ordered element might be before it
-      // (or after for backwards) in the child list.
-      index = aForward ? -1 : (PRInt32)count;
-    }
-
-    // GetChildAt will return nsnull if our index < 0 or index >= count
-    nsCOMPtr<nsIContent> areaContent;
-    while ((areaContent = mapContent->GetChildAt(aForward? ++index : --index)) != nsnull) {
-      if (areaContent->IsFocusable(&tabIndex) && tabIndex == mCurrentTabIndex) {
-        return areaContent;
-      }
-    }
-  }
-
-  return nsnull;
-}
-
-PRInt32
-nsEventStateManager::GetNextTabIndex(nsIContent* aParent, PRBool forward)
-{
-  PRInt32 tabIndex, childTabIndex;
-  nsIContent *child;
-
-  PRUint32 count = aParent->GetChildCount();
-
-  if (forward) {
-    tabIndex = 0;
-    for (PRUint32 index = 0; index < count; index++) {
-      child = aParent->GetChildAt(index);
-      childTabIndex = GetNextTabIndex(child, forward);
-      if (childTabIndex > mCurrentTabIndex && childTabIndex != tabIndex) {
-        tabIndex = (tabIndex == 0 || childTabIndex < tabIndex) ? childTabIndex : tabIndex;
-      }
-
-      nsAutoString tabIndexStr;
-      child->GetAttr(kNameSpaceID_None, nsGkAtoms::tabindex, tabIndexStr);
-      PRInt32 ec, val = tabIndexStr.ToInteger(&ec);
-      if (NS_SUCCEEDED (ec) && val > mCurrentTabIndex && val != tabIndex) {
-        tabIndex = (tabIndex == 0 || val < tabIndex) ? val : tabIndex;
-      }
-    }
-  }
-  else { /* !forward */
-    tabIndex = 1;
-    for (PRUint32 index = 0; index < count; index++) {
-      child = aParent->GetChildAt(index);
-      childTabIndex = GetNextTabIndex(child, forward);
-      if ((mCurrentTabIndex == 0 && childTabIndex > tabIndex) ||
-          (childTabIndex < mCurrentTabIndex && childTabIndex > tabIndex)) {
-        tabIndex = childTabIndex;
-      }
-
-      nsAutoString tabIndexStr;
-      child->GetAttr(kNameSpaceID_None, nsGkAtoms::tabindex, tabIndexStr);
-      PRInt32 ec, val = tabIndexStr.ToInteger(&ec);
-      if (NS_SUCCEEDED (ec)) {
-        if ((mCurrentTabIndex == 0 && val > tabIndex) ||
-            (val < mCurrentTabIndex && val > tabIndex) ) {
-          tabIndex = val;
-        }
-      }
-    }
-  }
-  return tabIndex;
-}
-
-NS_IMETHODIMP
 nsEventStateManager::GetEventTarget(nsIFrame **aFrame)
 {
   if (!mCurrentTarget && mCurrentTargetContent) {
     if (mPresContext) {
       nsIPresShell *shell = mPresContext->GetPresShell();
       if (shell) {
         mCurrentTarget = shell->GetPrimaryFrameFor(mCurrentTargetContent);
       }
@@ -4902,18 +3744,17 @@ nsEventStateManager::GetEventTarget(nsIF
 
 NS_IMETHODIMP
 nsEventStateManager::GetEventTargetContent(nsEvent* aEvent,
                                            nsIContent** aContent)
 {
   if (aEvent &&
       (aEvent->message == NS_FOCUS_CONTENT ||
        aEvent->message == NS_BLUR_CONTENT)) {
-    *aContent = mCurrentFocus;
-    NS_IF_ADDREF(*aContent);
+    NS_IF_ADDREF(*aContent = GetFocusedContent());
     return NS_OK;
   }
 
   if (mCurrentTargetContent) {
     *aContent = mCurrentTargetContent;
     NS_IF_ADDREF(*aContent);
     return NS_OK;
   }
@@ -4953,18 +3794,25 @@ nsEventStateManager::GetContentState(nsI
   for (nsIContent* hoverContent = mHoverContent; hoverContent;
        hoverContent = hoverContent->GetParent()) {
     if (aContent == hoverContent) {
       aState |= NS_EVENT_STATE_HOVER;
       break;
     }
   }
 
-  if (aContent == mCurrentFocus) {
-    aState |= NS_EVENT_STATE_FOCUS;
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+  if (fm) {
+    nsCOMPtr<nsIDOMElement> focusedElement;
+    fm->GetFocusedElement(getter_AddRefs(focusedElement));
+
+    nsCOMPtr<nsIContent> focusedContent = do_QueryInterface(focusedElement);
+    if (aContent == focusedContent) {
+      aState |= NS_EVENT_STATE_FOCUS;
+    }
   }
   if (aContent == mDragOverContent) {
     aState |= NS_EVENT_STATE_DRAGOVER;
   }
   if (aContent == mURLTargetContent) {
     aState |= NS_EVENT_STATE_URLTARGET;
   }
   return NS_OK;
@@ -5028,18 +3876,16 @@ nsEventStateManager::SetContentState(nsI
   // XXX Is this even what we want?
   if (mCurrentTarget && (aState == NS_EVENT_STATE_ACTIVE || aState == NS_EVENT_STATE_HOVER))
   {
     const nsStyleUserInterface* ui = mCurrentTarget->GetStyleUserInterface();
     if (ui->mUserInput == NS_STYLE_USER_INPUT_NONE)
       return PR_FALSE;
   }
 
-  PRBool didContentChangeAllStates = PR_TRUE;
-
   if ((aState & NS_EVENT_STATE_DRAGOVER) && (aContent != mDragOverContent)) {
     notifyContent[3] = mDragOverContent; // notify dragover first, since more common case
     NS_IF_ADDREF(notifyContent[3]);
     mDragOverContent = aContent;
   }
 
   if ((aState & NS_EVENT_STATE_URLTARGET) && (aContent != mURLTargetContent)) {
     notifyContent[4] = mURLTargetContent;
@@ -5074,68 +3920,18 @@ nsEventStateManager::SetContentState(nsI
       }
     }
 
     commonHoverAncestor = FindCommonAncestor(mHoverContent, aContent);
     mHoverContent = aContent;
   }
 
   if ((aState & NS_EVENT_STATE_FOCUS)) {
-    EnsureDocument(mPresContext);
-    nsIMEStateManager::OnChangeFocus(mPresContext, aContent);
-    if (aContent && (aContent == mCurrentFocus) && gLastFocusedDocument == mDocument) {
-      // gLastFocusedDocument appears to always be correct, that is why
-      // I'm not setting it here. This is to catch an edge case.
-      NS_IF_RELEASE(gLastFocusedContent);
-      gLastFocusedContent = mCurrentFocus;
-      NS_IF_ADDREF(gLastFocusedContent);
-      //If this notification was for focus alone then get rid of aContent
-      //ref to avoid unnecessary notification.
-      if (!(aState & ~NS_EVENT_STATE_FOCUS)) {
-        aContent = nsnull;
-      }
-    } else {
-      // see comments in ShiftFocusInternal on mCurrentFocus overloading
-      PRBool fcActive = PR_FALSE;
-      if (mDocument) {
-        nsIFocusController *fc = GetFocusControllerForDocument(mDocument);
-        if (fc)
-          fc->GetActive(&fcActive);
-      }
-      notifyContent[2] = gLastFocusedContent;
-      NS_IF_ADDREF(gLastFocusedContent);
-      // only raise window if the the focus controller is active
-      SendFocusBlur(mPresContext, aContent, fcActive);
-      if (mCurrentFocus != aContent) {
-        didContentChangeAllStates = PR_FALSE;
-      }
-
-#ifdef DEBUG_aleventhal
-      nsPIDOMWindow *currentWindow = mDocument->GetWindow();
-      if (currentWindow) {
-        nsIFocusController *fc = currentWindow->GetRootFocusController();
-        if (fc) {
-          nsCOMPtr<nsIDOMElement> focusedElement;
-          fc->GetFocusedElement(getter_AddRefs(focusedElement));
-          if (!SameCOMIdentity(mCurrentFocus, focusedElement)) {
-            printf("\n\nFocus out of whack!!!\n\n");
-          }
-        }
-      }
-#endif
-      // If we now have focused content, ensure that the canvas focus ring
-      // is removed.
-      if (mDocument) {
-        nsCOMPtr<nsIDocShell> docShell =
-          do_QueryInterface(nsCOMPtr<nsISupports>(mDocument->GetContainer()));
-
-        if (docShell && mCurrentFocus)
-          docShell->SetCanvasHasFocus(PR_FALSE);
-      }
-    }
+    notifyContent[2] = aContent;
+    NS_IF_ADDREF(notifyContent[2]);
   }
 
   PRInt32 simpleStates = aState & ~(NS_EVENT_STATE_ACTIVE|NS_EVENT_STATE_HOVER);
 
   if (aContent && simpleStates != 0) {
     // notify about new content too
     notifyContent[0] = aContent;
     NS_ADDREF(aContent);  // everything in notify array has a ref
@@ -5265,410 +4061,27 @@ nsEventStateManager::SetContentState(nsI
 
     from = &(notifyContent[0]);
     while (from < to) {  // release old refs now that we are through
       nsIContent* notify = *from++;
       NS_RELEASE(notify);
     }
   }
 
-  return didContentChangeAllStates;
-}
-
-static PRBool
-IsFocusable(nsIPresShell* aPresShell, nsIContent* aContent)
-{
-  // Flush pending updates to the frame tree first (bug 305840).
-  aPresShell->FlushPendingNotifications(Flush_Frames);
-
-  nsIFrame* focusFrame = aPresShell->GetPrimaryFrameFor(aContent);
-  if (!focusFrame) {
-    return PR_FALSE;
-  }
-
-  // XUL frames in general have a somewhat confusing notion of
-  // focusability so we only require a visible frame and that
-  // the content is focusable (not disabled).
-  // We don't use nsIFrame::IsFocusable() because it defaults
-  // tabindex to -1 for -moz-user-focus:ignore (bug 305840).
-  if (aContent->IsNodeOfType(nsINode::eXUL)) {
-    // XXX Eventually we should have a better check, but for
-    // now checking for style visibility and focusability caused
-    // too many regressions.
-    return focusFrame->AreAncestorViewsVisible();
-  }
-
-  if (aContent->Tag() != nsGkAtoms::area) {
-    return focusFrame->IsFocusable();
-  }
-  // HTML areas do not have their own frame, and the img frame we get from
-  // GetPrimaryFrameFor() is not relevant to whether it is focusable or not,
-  // so we have to do all the relevant checks manually for them.
-  return focusFrame->AreAncestorViewsVisible() &&
-         focusFrame->GetStyleVisibility()->IsVisible() &&
-         aContent->IsFocusable();
-}
-
-nsresult
-nsEventStateManager::SendFocusBlur(nsPresContext* aPresContext,
-                                   nsIContent *aContent,
-                                   PRBool aEnsureWindowHasFocus)
-{
-  // Keep a ref to presShell since dispatching the DOM event may cause
-  // the document to be destroyed.
-  nsCOMPtr<nsIPresShell> presShell = aPresContext->GetPresShell();
-  if (!presShell)
-    return NS_OK;
-
-  nsCOMPtr<nsIContent> previousFocus = mCurrentFocus;
-
-  // Make sure previousFocus is in a document.  If it's not, then
-  // we should never abort firing events based on what happens when we
-  // send it a blur.
-
-  if (previousFocus && !previousFocus->GetDocument())
-    previousFocus = nsnull;
-
-  // Track the old focus controller if any focus suppressions is used on it.
-  nsFocusSuppressor oldFocusSuppressor;
-  
-  nsIMEStateManager::OnTextStateBlur(aPresContext, aContent);
-
-  if (nsnull != gLastFocusedPresContextWeak) {
-
-    nsCOMPtr<nsIContent> focusAfterBlur;
-
-    if (gLastFocusedContent && gLastFocusedContent != mFirstBlurEvent) {
-
-      //Store the first blur event we fire and don't refire blur
-      //to that element while the first blur is still ongoing.
-      PRBool clearFirstBlurEvent = PR_FALSE;
-      if (!mFirstBlurEvent) {
-        mFirstBlurEvent = gLastFocusedContent;
-        clearFirstBlurEvent = PR_TRUE;
-      }
-
-      // Retrieve this content node's pres context. it can be out of sync in
-      // the Ender widget case.
-      nsCOMPtr<nsIDocument> doc = gLastFocusedContent->GetDocument();
-      if (doc) {
-        // The order of the nsIViewManager and nsIPresShell COM pointers is
-        // important below.  We want the pres shell to get released before the
-        // associated view manager on exit from this function.
-        // See bug 53763.
-        nsCOMPtr<nsIViewManager> kungFuDeathGrip;
-        nsIPresShell *shell = doc->GetPrimaryShell();
-        if (shell) {
-          kungFuDeathGrip = shell->GetViewManager();
-
-          nsCOMPtr<nsPresContext> oldPresContext = shell->GetPresContext();
-
-          //fire blur
-          nsEvent blurEvent(PR_TRUE, NS_BLUR_CONTENT);
-          blurEvent.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
-
-          EnsureDocument(presShell);
-
-          // Make sure we're not switching command dispatchers, if so,
-          // surpress the blurred one
-          if(gLastFocusedDocument && mDocument) {
-            nsPIDOMWindow *newWindow = mDocument->GetWindow();
-            if (newWindow) {
-              nsIFocusController *newFocusController =
-                newWindow->GetRootFocusController();
-              nsPIDOMWindow *oldWindow = gLastFocusedDocument->GetWindow();
-              if (oldWindow) {
-                nsIFocusController *suppressed =
-                  oldWindow->GetRootFocusController();
-
-                if (suppressed != newFocusController) {
-                  oldFocusSuppressor.Suppress(suppressed, "SendFocusBlur Window Switch #1");
-                }
-              }
-            }
-          }
-
-          nsCOMPtr<nsIEventStateManager> esm;
-          esm = oldPresContext->EventStateManager();
-          esm->SetFocusedContent(gLastFocusedContent);
-          nsCOMPtr<nsIContent> temp = gLastFocusedContent;
-          NS_RELEASE(gLastFocusedContent); // nulls out gLastFocusedContent
-
-          nsCxPusher pusher;
-          if (pusher.Push(temp)) {
-            FireFocusOrBlurEvent(temp, &blurEvent, oldPresContext);
-            pusher.Pop();
-          }
-
-          focusAfterBlur = mCurrentFocus;
-          if (!previousFocus || previousFocus == focusAfterBlur)
-            esm->SetFocusedContent(nsnull);
-        }
-      }
-
-      if (clearFirstBlurEvent) {
-        mFirstBlurEvent = nsnull;
-      }
-
-      if (previousFocus && previousFocus != focusAfterBlur) {
-        // The content node's blur handler focused something else.
-        // In this case, abort firing any more blur or focus events.
-        EnsureFocusSynchronization();
-        return NS_OK;
-      }
-    }
-
-    // Go ahead and fire a blur on the window.
-    nsCOMPtr<nsPIDOMWindow> window;
-
-    if(gLastFocusedDocument)
-      window = gLastFocusedDocument->GetWindow();
-
-    EnsureDocument(presShell);
-
-    if (gLastFocusedDocument && (gLastFocusedDocument != mDocument) &&
-        window) {
-      nsEvent blurEvent(PR_TRUE, NS_BLUR_CONTENT);
-      blurEvent.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
-
-      // Make sure we're not switching command dispatchers, if so,
-      // suppress the blurred one if it isn't already suppressed
-      if (mDocument && !oldFocusSuppressor.Suppressing()) {
-        nsCOMPtr<nsPIDOMWindow> newWindow(mDocument->GetWindow());
-
-        if (newWindow) {
-          nsCOMPtr<nsPIDOMWindow> oldWindow(gLastFocusedDocument->GetWindow());
-          nsIFocusController *newFocusController =
-            newWindow->GetRootFocusController();
-          if (oldWindow) {
-            nsIFocusController *suppressed =
-              oldWindow->GetRootFocusController();
-            if (suppressed != newFocusController) {
-              oldFocusSuppressor.Suppress(suppressed, "SendFocusBlur Window Switch #2");
-            }
-          }
-        }
-      }
-
-      gLastFocusedPresContextWeak->EventStateManager()->SetFocusedContent(nsnull);
-      nsCOMPtr<nsIDocument> temp = gLastFocusedDocument;
-      NS_RELEASE(gLastFocusedDocument);
-      gLastFocusedDocument = nsnull;
-
-      nsCxPusher pusher;
-      if (pusher.Push(temp)) {
-        FireFocusOrBlurEvent(temp, &blurEvent, gLastFocusedPresContextWeak);
-        pusher.Pop();
-      }
-
-      if (previousFocus && mCurrentFocus != previousFocus) {
-        // The document's blur handler focused something else.
-        // Abort firing any additional blur or focus events, and make sure
-        // nsFocusController:mFocusedElement is not nulled out, but agrees
-        // with our current concept of focus.
-        EnsureFocusSynchronization();
-        return NS_OK;
-      }
-
-      nsCOMPtr<nsPIDOMEventTarget> target = do_QueryInterface(window);
-      if (pusher.Push(target)) {
-        blurEvent.target = nsnull;
-        FireFocusOrBlurEvent(target, &blurEvent, gLastFocusedPresContextWeak);
-  
-        if (previousFocus && mCurrentFocus != previousFocus) {
-          // The window's blur handler focused something else.
-          // Abort firing any additional blur or focus events.
-          EnsureFocusSynchronization();
-          return NS_OK;
-        }
-      }
-    }
-  }
-
-  // Check if the nsEventDispatcher::Dispatch calls above destroyed our frame
-  // (bug #118685) or made it not focusable in any way.
-  if (aContent && !::IsFocusable(presShell, aContent)) {
-    aContent = nsnull;
-  }
-
-  NS_IF_RELEASE(gLastFocusedContent);
-  gLastFocusedContent = aContent;
-  NS_IF_ADDREF(gLastFocusedContent);
-  SetFocusedContent(aContent);
-  EnsureFocusSynchronization();
-
-  // Moved widget focusing code here, from end of SendFocusBlur
-  // This fixes the order of accessibility focus events, so that
-  // the window focus event goes first, and then the focus event for the control
-  if (aEnsureWindowHasFocus) {
-    nsCOMPtr<nsIWidget> widget;
-    // Plug-ins with native widget need a special handling
-    nsIFrame* currentFocusFrame = nsnull;
-    if (mCurrentFocus)
-      currentFocusFrame = presShell->GetPrimaryFrameFor(mCurrentFocus);
-    if (!currentFocusFrame)
-      currentFocusFrame = mCurrentTarget;
-    nsIObjectFrame* objFrame = do_QueryFrame(currentFocusFrame);
-    if (objFrame) {
-      nsIView* view = currentFocusFrame->GetViewExternal();
-      NS_ASSERTION(view, "Object frames must have views");
-      widget = view->GetWidget();
-    }
-    if (!widget) {
-      // This raises the window that has both content and scroll bars in it
-      // instead of the child window just below it that contains only the content
-      // That way we focus the same window that gets focused by a mouse click
-      nsIViewManager* vm = presShell->GetViewManager();
-      if (vm) {
-        vm->GetWidget(getter_AddRefs(widget));
-      }
-    }
-    if (widget)
-      widget->SetFocus(PR_TRUE);
-  }
-
-  if (nsnull != aContent && aContent != mFirstFocusEvent &&
-      !EventHandlingSuppressed(aContent)) {
-
-    //Store the first focus event we fire and don't refire focus
-    //to that element while the first focus is still ongoing.
-    PRBool clearFirstFocusEvent = PR_FALSE;
-    if (!mFirstFocusEvent) {
-      mFirstFocusEvent = aContent;
-      clearFirstFocusEvent = PR_TRUE;
-    }
-
-    //fire focus
-    nsEvent focusEvent(PR_TRUE, NS_FOCUS_CONTENT);
-    focusEvent.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
-
-    if (nsnull != mPresContext) {
-      nsCxPusher pusher;
-      if (pusher.Push(aContent)) {
-        FireFocusOrBlurEvent(aContent, &focusEvent, mPresContext);
-      }
-    }
-
-    nsAutoString tabIndex;
-    aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::tabindex, tabIndex);
-    PRInt32 ec, val = tabIndex.ToInteger(&ec);
-    if (NS_SUCCEEDED (ec)) {
-      mCurrentTabIndex = val;
-    }
-
-    if (clearFirstFocusEvent) {
-      mFirstFocusEvent = nsnull;
-    }
-
-    nsIMEStateManager::OnTextStateFocus(mPresContext, mCurrentFocus);
-  } else if (!aContent && !EventHandlingSuppressed(mDocument)) {
-    //fire focus on document even if the content isn't focusable (ie. text)
-    //see bugzilla bug 93521
-    nsEvent focusEvent(PR_TRUE, NS_FOCUS_CONTENT);
-    focusEvent.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
-
-    if (nsnull != mPresContext && mDocument) {
-      nsCxPusher pusher;
-      if (pusher.Push(mDocument)) {
-        FireFocusOrBlurEvent(mDocument, &focusEvent, mPresContext);
-      }
-    }
-  }
-
-  if (mBrowseWithCaret || GetWindowShowCaret(mDocument))
-    SetContentCaretVisible(presShell, aContent, PR_TRUE);
-
-  return NS_OK;
+  return PR_TRUE;
 }
 
 NS_IMETHODIMP
-nsEventStateManager::GetFocusedContent(nsIContent** aContent)
-{
-  *aContent = mCurrentFocus;
-  NS_IF_ADDREF(*aContent);
-  return NS_OK;
-}
-
-void nsEventStateManager::EnsureFocusSynchronization()
-{
-  // Sometimes the focus can get out of whack due to a blur handler
-  // resetting focus. In addition, we fire onchange from the blur handler
-  // for some controls, which is another place where focus can be changed.
-  // XXX Ideally we will eventually store focus in one place instead of
-  // the focus controller, esm, tabbrowser and some frames, so that it
-  // cannot get out of sync.
-  // See Bug 304751, calling FireOnChange() inside
-  //                 nsComboboxControlFrame::SetFocus() is bad
-  nsPIDOMWindow *currentWindow = mDocument->GetWindow();
-  if (currentWindow) {
-    nsIFocusController *fc = currentWindow->GetRootFocusController();
-    if (fc) {
-      nsCOMPtr<nsIDOMElement> focusedElement = do_QueryInterface(mCurrentFocus);
-      fc->SetFocusedElement(focusedElement);
-    }
-  }
-}
-
-NS_IMETHODIMP
-nsEventStateManager::SetFocusedContent(nsIContent* aContent)
+nsEventStateManager::ContentRemoved(nsIDocument* aDocument, nsIContent* aContent)
 {
-
-  if (aContent &&
-      (!mPresContext || mPresContext->Type() == nsPresContext::eContext_PrintPreview)) {
-    return NS_OK;
-  }
-
-  mCurrentFocus = aContent;
-  if (mCurrentFocus)
-    mLastFocus = mCurrentFocus;
-  mCurrentFocusFrame = nsnull;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsEventStateManager::GetLastFocusedContent(nsIContent** aContent)
-{
-  *aContent = mLastFocus;
-  NS_IF_ADDREF(*aContent);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsEventStateManager::GetFocusedFrame(nsIFrame** aFrame)
-{
-  if (!mCurrentFocusFrame && mCurrentFocus) {
-    nsIDocument* doc = mCurrentFocus->GetDocument();
-    if (doc) {
-      nsIPresShell *shell = doc->GetPrimaryShell();
-      if (shell) {
-        mCurrentFocusFrame = shell->GetPrimaryFrameFor(mCurrentFocus);
-      }
-    }
-  }
-
-  *aFrame = mCurrentFocusFrame;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsEventStateManager::ContentRemoved(nsIContent* aContent)
-{
-  if (mCurrentFocus &&
-      nsContentUtils::ContentIsDescendantOf(mCurrentFocus, aContent)) {
-    // Note that we don't use SetContentState() here because
-    // we don't want to fire a blur.  Blurs should only be fired
-    // in response to clicks or tabbing.
-    nsIMEStateManager::OnRemoveContent(mPresContext, mCurrentFocus);
-    SetFocusedContent(nsnull);
-  }
-
-  if (mLastFocus &&
-      nsContentUtils::ContentIsDescendantOf(mLastFocus, aContent)) {
-    mLastFocus = nsnull;
-  }
+  // inform the focus manager that the content is being removed. If this
+  // content is focused, the focus will be removed without firing events.
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+  if (fm)
+    fm->ContentRemoved(aDocument, aContent);
 
   if (mHoverContent &&
       nsContentUtils::ContentIsDescendantOf(mHoverContent, aContent)) {
     // Since hover is hierarchical, set the current hover to the
     // content's parent node.
     mHoverContent = aContent->GetParent();
   }
 
@@ -5747,636 +4160,35 @@ nsEventStateManager::GetRegisteredAccess
 void
 nsEventStateManager::EnsureDocument(nsPresContext* aPresContext)
 {
   if (!mDocument)
     mDocument = aPresContext->Document();
 }
 
 void
-nsEventStateManager::EnsureDocument(nsIPresShell* aPresShell)
-{
-  if (!mDocument && aPresShell)
-    mDocument = aPresShell->GetDocument();
-}
-
-void
 nsEventStateManager::FlushPendingEvents(nsPresContext* aPresContext)
 {
   NS_PRECONDITION(nsnull != aPresContext, "nsnull ptr");
   nsIPresShell *shell = aPresContext->GetPresShell();
   if (shell) {
     shell->FlushPendingNotifications(Flush_InterruptibleLayout);
   }
 }
 
-nsresult
-nsEventStateManager::GetDocSelectionLocation(nsIContent **aStartContent,
-                                             nsIContent **aEndContent,
-                                             nsIFrame **aStartFrame,
-                                             PRUint32* aStartOffset)
-{
-  // In order to return the nsIContent and nsIFrame of the caret's position,
-  // we need to get a pres shell, and then get the selection from it
-
-  *aStartOffset = 0;
-  *aStartFrame = nsnull;
-  *aStartContent = *aEndContent = nsnull;
-  nsresult rv = NS_ERROR_FAILURE;
-
-  NS_ASSERTION(mPresContext, "mPresContent is null!!");
-  EnsureDocument(mPresContext);
-  if (!mDocument)
-    return rv;
-  nsIPresShell *shell;
-  shell = mPresContext->GetPresShell();
-
-  nsCOMPtr<nsFrameSelection> frameSelection;
-  if (shell)
-    frameSelection = shell->FrameSelection();
-
-  nsCOMPtr<nsISelection> domSelection;
-  if (frameSelection) {
-    domSelection = frameSelection->
-      GetSelection(nsISelectionController::SELECTION_NORMAL);
-  }
-
-  nsCOMPtr<nsIDOMNode> startNode, endNode;
-  PRBool isCollapsed = PR_FALSE;
-  nsCOMPtr<nsIContent> startContent, endContent;
-  if (domSelection) {
-    domSelection->GetIsCollapsed(&isCollapsed);
-    nsCOMPtr<nsIDOMRange> domRange;
-    rv = domSelection->GetRangeAt(0, getter_AddRefs(domRange));
-    if (domRange) {
-      domRange->GetStartContainer(getter_AddRefs(startNode));
-      domRange->GetEndContainer(getter_AddRefs(endNode));
-      domRange->GetStartOffset(reinterpret_cast<PRInt32 *>(aStartOffset));
-
-      nsIContent *childContent = nsnull;
-
-      startContent = do_QueryInterface(startNode);
-      if (startContent && startContent->IsNodeOfType(nsINode::eELEMENT)) {
-        NS_ASSERTION(*aStartOffset >= 0, "Start offset cannot be negative");  
-        childContent = startContent->GetChildAt(*aStartOffset);
-        if (childContent) {
-          startContent = childContent;
-        }
-      }
-
-      endContent = do_QueryInterface(endNode);
-      if (endContent && endContent->IsNodeOfType(nsINode::eELEMENT)) {
-        PRInt32 endOffset = 0;
-        domRange->GetEndOffset(&endOffset);
-        NS_ASSERTION(endOffset >= 0, "End offset cannot be negative");
-        childContent = endContent->GetChildAt(endOffset);
-        if (childContent) {
-          endContent = childContent;
-        }
-      }
-    }
-  }
-  else {
-    rv = NS_ERROR_INVALID_ARG;
-  }
-
-  nsIFrame *startFrame = nsnull;
-  if (startContent) {
-    startFrame = shell->GetPrimaryFrameFor(startContent);
-    if (isCollapsed) {
-      // Next check to see if our caret is at the very end of a node
-      // If so, the caret is actually sitting in front of the next
-      // logical frame's primary node - so for this case we need to
-      // change caretContent to that node.
-
-      nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(startContent));
-      PRUint16 nodeType;
-      domNode->GetNodeType(&nodeType);
-
-      if (nodeType == nsIDOMNode::TEXT_NODE) {
-        nsAutoString nodeValue;
-        domNode->GetNodeValue(nodeValue);
-
-        PRBool isFormControl =
-          startContent->IsNodeOfType(nsINode::eHTML_FORM_CONTROL);
-
-        if (nodeValue.Length() == *aStartOffset && !isFormControl &&
-            startContent != mDocument->GetRootContent()) {
-          // Yes, indeed we were at the end of the last node
-          nsCOMPtr<nsIFrameEnumerator> frameTraversal;
-
-          nsCOMPtr<nsIFrameTraversal> trav(do_CreateInstance(kFrameTraversalCID,
-                                                             &rv));
-          NS_ENSURE_SUCCESS(rv, rv);
-
-          rv = trav->NewFrameTraversal(getter_AddRefs(frameTraversal),
-                                       mPresContext, startFrame,
-                                       eLeaf,
-                                       PR_FALSE, // aVisual
-                                       PR_FALSE, // aLockInScrollView
-                                       PR_FALSE  // aFollowOOFs
-                                       );
-          NS_ENSURE_SUCCESS(rv, rv);
-
-          nsIFrame *newCaretFrame = nsnull;
-          nsCOMPtr<nsIContent> newCaretContent = startContent;
-          PRBool endOfSelectionInStartNode(startContent == endContent);
-          do {
-            // Continue getting the next frame until the primary content for the frame
-            // we are on changes - we don't want to be stuck in the same place
-            frameTraversal->Next();
-            newCaretFrame = frameTraversal->CurrentItem();
-            if (nsnull == newCaretFrame) {
-              break;
-            }
-            newCaretContent = newCaretFrame->GetContent();            
-          } while (!newCaretContent || newCaretContent == startContent);
-
-          if (newCaretFrame && newCaretContent) {
-            // If the caret is exactly at the same position of the new frame,
-            // then we can use the newCaretFrame and newCaretContent for our position
-            nsRefPtr<nsCaret> caret;
-            shell->GetCaret(getter_AddRefs(caret));
-            nsRect caretRect;
-            nsIView *caretView;
-            caret->GetCaretCoordinates(nsCaret::eClosestViewCoordinates, 
-                                       domSelection, &caretRect,
-                                       &isCollapsed, &caretView);
-            nsPoint framePt;
-            nsIView *frameClosestView = newCaretFrame->GetClosestView(&framePt);
-            if (caretView == frameClosestView && caretRect.y == framePt.y &&
-                caretRect.x == framePt.x) {
-              // The caret is at the start of the new element.
-              startFrame = newCaretFrame;
-              startContent = newCaretContent;
-              if (endOfSelectionInStartNode) {
-                endContent = newCaretContent; // Ensure end of selection is not before start
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-
-  *aStartFrame = startFrame;
-  *aStartContent = startContent;
-  *aEndContent = endContent;
-  NS_IF_ADDREF(*aStartContent);
-  NS_IF_ADDREF(*aEndContent);
-
-  return rv;
-}
-
-void
-nsEventStateManager::FocusElementButNotDocument(nsIContent *aContent)
-{
-  // Focus an element in the current document, but don't switch document/window focus!
-
-  if (gLastFocusedDocument == mDocument) {
-    // If we're already focused in this document,
-    // use normal focus method
-    if (mCurrentFocus != aContent) {
-      if (aContent)
-        aContent->SetFocus(mPresContext);
-      else
-        SetContentState(nsnull, NS_EVENT_STATE_FOCUS);
-    }
-    return;
-  }
-
-  /**
-   * The last focus wasn't in this document, so we may be getting our position from the selection
-   * while the window focus is currently somewhere else such as the find dialog
-   */
-
-  nsIFocusController *focusController =
-    GetFocusControllerForDocument(mDocument);
-  if (!focusController)
-      return;
-
-  // Get previous focus
-  nsCOMPtr<nsIDOMElement> oldFocusedElement;
-  focusController->GetFocusedElement(getter_AddRefs(oldFocusedElement));
-  nsCOMPtr<nsIContent> oldFocusedContent(do_QueryInterface(oldFocusedElement));
-
-  // Temporarily set mCurrentFocus so that esm::GetContentState() tells
-  // layout system to show focus on this element.
-  SetFocusedContent(aContent);  // Reset back to null at the end of this method.
-  mDocument->BeginUpdate(UPDATE_CONTENT_STATE);
-  mDocument->ContentStatesChanged(oldFocusedContent, aContent,
-                                  NS_EVENT_STATE_FOCUS);
-  mDocument->EndUpdate(UPDATE_CONTENT_STATE);
-
-  // Reset mCurrentFocus = nsnull for this doc, so when this document
-  // does get focus next time via preHandleEvent() NS_GOTFOCUS,
-  // the old document gets blurred
-  SetFocusedContent(nsnull);
-
-}
-
-NS_IMETHODIMP
-nsEventStateManager::MoveFocusToCaret(PRBool aCanFocusDoc,
-                                      PRBool *aIsSelectionWithFocus)
+nsIContent*
+nsEventStateManager::GetFocusedContent()
 {
-  // mBrowseWithCaret equals the pref accessibility.browsewithcaret
-  // When it's true, the user can arrow around the browser as if it's a
-  // read only text editor.
-
-  // If the user cursors over a focusable element or gets there with find text, then send focus to it
-
-  *aIsSelectionWithFocus= PR_FALSE;
-  nsCOMPtr<nsIContent> selectionContent, endSelectionContent;
-  nsIFrame *selectionFrame;
-  PRUint32 selectionOffset;
-  GetDocSelectionLocation(getter_AddRefs(selectionContent), getter_AddRefs(endSelectionContent),
-    &selectionFrame, &selectionOffset);
-
-  if (!selectionContent)
-    return NS_ERROR_FAILURE;
-
-  nsCOMPtr<nsIContent> testContent(selectionContent);
-  nsCOMPtr<nsIContent> nextTestContent(endSelectionContent);
-
-  // We now have the correct start node in selectionContent!
-  // Search for focusable elements, starting with selectionContent
-
-  // Method #1: Keep going up while we look - an ancestor might be focusable
-  // We could end the loop earlier, such as when we're no longer
-  // in the same frame, by comparing getPrimaryFrameFor(selectionContent)
-  // with a variable holding the starting selectionContent
-  while (testContent) {
-    // Keep testing while selectionContent is equal to something,
-    // eventually we'll run out of ancestors
-
-    if (testContent == mCurrentFocus) {
-      *aIsSelectionWithFocus = PR_TRUE;
-      return NS_OK;  // already focused on this node, this whole thing's moot
-    }
-
-    nsIAtom *tag = testContent->Tag();
-
-    // Add better focusable test here later if necessary ...
-    if (tag == nsGkAtoms::a &&
-        testContent->IsNodeOfType(nsINode::eHTML)) {
-      *aIsSelectionWithFocus = PR_TRUE;
-    }
-    else {
-      // Xlink must be type="simple"
-      *aIsSelectionWithFocus =
-        testContent->HasAttr(kNameSpaceID_XLink, nsGkAtoms::href) &&
-        testContent->AttrValueIs(kNameSpaceID_XLink, nsGkAtoms::type,
-                                 nsGkAtoms::simple, eCaseMatters);
-    }
-
-    if (*aIsSelectionWithFocus) {
-      FocusElementButNotDocument(testContent);
-      return NS_OK;
-    }
-
-    // Get the parent
-    testContent = testContent->GetParent();
-
-    if (!testContent) {
-      // We run this loop again, checking the ancestor chain of the selection's end point
-      testContent = nextTestContent;
-      nextTestContent = nsnull;
-    }
-  }
-
-  // We couldn't find an anchor that was an ancestor of the selection start
-  // Method #2: look for anchor in selection's primary range (depth first search)
-
-  // Turn into nodes so that we can use GetNextSibling() and GetFirstChild()
-  nsCOMPtr<nsIDOMNode> selectionNode(do_QueryInterface(selectionContent));
-  nsCOMPtr<nsIDOMNode> endSelectionNode(do_QueryInterface(endSelectionContent));
-  nsCOMPtr<nsIDOMNode> testNode;
-
-  do {
-    testContent = do_QueryInterface(selectionNode);
-
-    // We're looking for any focusable item that could be part of the
-    // main document's selection.
-    // Right now we only look for elements with the <a> tag.
-    // Add better focusable test here later if necessary ...
-    if (testContent) {
-      if (testContent->Tag() == nsGkAtoms::a &&
-          testContent->IsNodeOfType(nsINode::eHTML)) {
-        *aIsSelectionWithFocus = PR_TRUE;
-        FocusElementButNotDocument(testContent);
-        return NS_OK;
-      }
-    }
-
-    selectionNode->GetFirstChild(getter_AddRefs(testNode));
-    if (testNode) {
-      selectionNode = testNode;
-      continue;
-    }
-
-    if (selectionNode == endSelectionNode)
-      break;
-    selectionNode->GetNextSibling(getter_AddRefs(testNode));
-    if (testNode) {
-      selectionNode = testNode;
-      continue;
-    }
-
-    do {
-      selectionNode->GetParentNode(getter_AddRefs(testNode));
-      if (!testNode || testNode == endSelectionNode) {
-        selectionNode = nsnull;
-        break;
-      }
-      testNode->GetNextSibling(getter_AddRefs(selectionNode));
-      if (selectionNode)
-        break;
-      selectionNode = testNode;
-    } while (PR_TRUE);
-  }
-  while (selectionNode && selectionNode != endSelectionNode);
-
-  if (aCanFocusDoc)
-    FocusElementButNotDocument(nsnull);
-
-  return NS_OK; // no errors, but caret not inside focusable element other than doc itself
-}
-
-
-
-NS_IMETHODIMP
-nsEventStateManager::MoveCaretToFocus()
-{
-  // If in HTML content and the pref accessibility.browsewithcaret is TRUE,
-  // then always move the caret to beginning of a new focus
-
-  PRInt32 itemType = nsIDocShellTreeItem::typeChrome;
-
-  if (mPresContext) {
-    nsCOMPtr<nsISupports> pcContainer = mPresContext->GetContainer();
-    nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(pcContainer));
-    if (treeItem)
-      treeItem->GetItemType(&itemType);
-    nsCOMPtr<nsIEditorDocShell> editorDocShell(do_QueryInterface(treeItem));
-    if (editorDocShell) {
-      PRBool isEditable;
-      editorDocShell->GetEditable(&isEditable);
-      if (isEditable) {
-        return NS_OK;  // Move focus to caret only if browsing, not editing
-      }
-    }
-  }
-
-  if (itemType != nsIDocShellTreeItem::typeChrome) {
-    nsIPresShell *shell = mPresContext->GetPresShell();
-    if (shell) {
-      // rangeDoc is a document interface we can create a range with
-      nsCOMPtr<nsIDOMDocumentRange> rangeDoc(do_QueryInterface(mDocument));
-
-      if (rangeDoc) {
-        nsCOMPtr<nsFrameSelection> frameSelection = shell->FrameSelection();
-        nsCOMPtr<nsISelection> domSelection = frameSelection->
-          GetSelection(nsISelectionController::SELECTION_NORMAL);
-        if (domSelection) {
-          nsCOMPtr<nsIDOMNode> currentFocusNode(do_QueryInterface(mCurrentFocus));
-          // First clear the selection
-          domSelection->RemoveAllRanges();
-          if (currentFocusNode && !mCurrentFocus->IsNodeOfType(nsINode::eXUL)) {
-            nsCOMPtr<nsIDOMRange> newRange;
-            nsresult rv = rangeDoc->CreateRange(getter_AddRefs(newRange));
-            if (NS_SUCCEEDED(rv)) {
-              // Set the range to the start of the currently focused node
-              // Make sure it's collapsed
-              newRange->SelectNodeContents(currentFocusNode);
-              nsCOMPtr<nsIDOMNode> firstChild;
-              currentFocusNode->GetFirstChild(getter_AddRefs(firstChild));
-              if (!firstChild ||
-                  mCurrentFocus->IsNodeOfType(nsINode::eHTML_FORM_CONTROL)) {
-                // If current focus node is a leaf, set range to before the
-                // node by using the parent as a container.
-                // This prevents it from appearing as selected.
-                newRange->SetStartBefore(currentFocusNode);
-                newRange->SetEndBefore(currentFocusNode);
-              }
-              domSelection->AddRange(newRange);
-              domSelection->CollapseToStart();
-            }
-          }
-        }
-      }
-    }
-  }
-  return NS_OK;
-}
-
-nsresult
-nsEventStateManager::SetCaretEnabled(nsIPresShell *aPresShell, PRBool aEnabled)
-{
-  nsRefPtr<nsCaret> caret;
-  aPresShell->GetCaret(getter_AddRefs(caret));
-
-  nsCOMPtr<nsISelectionController> selCon(do_QueryInterface(aPresShell));
-  if (!selCon || !caret)
-    return NS_ERROR_FAILURE;
-
-  selCon->SetCaretEnabled(aEnabled);
-  caret->SetCaretVisible(aEnabled);
-  caret->SetIgnoreUserModify(aEnabled);
-
-  return NS_OK;
-}
-
-nsresult
-nsEventStateManager::SetContentCaretVisible(nsIPresShell* aPresShell,
-                                            nsIContent *aFocusedContent,
-                                            PRBool aVisible)
-{
-  // When browsing with caret, make sure caret is visible after new focus
-  nsRefPtr<nsCaret> caret;
-  aPresShell->GetCaret(getter_AddRefs(caret));
-
-  nsCOMPtr<nsFrameSelection> frameSelection;
-  if (aFocusedContent) {
-    nsIFrame *focusFrame = aPresShell->GetPrimaryFrameFor(aFocusedContent);
-    
-    if (focusFrame)
-      frameSelection = focusFrame->GetFrameSelection();
-  }
-
-  nsCOMPtr<nsFrameSelection> docFrameSelection = aPresShell->FrameSelection();
-
-  if (docFrameSelection && caret &&
-     (frameSelection == docFrameSelection || !aFocusedContent)) {
-    nsISelection* domSelection = docFrameSelection->
-      GetSelection(nsISelectionController::SELECTION_NORMAL);
-    if (domSelection) {
-      // First, tell the caret which selection to use
-      caret->SetCaretDOMSelection(domSelection);
-
-      // In content, we need to set the caret
-      // the only other case is edit fields, where they have a different frame selection from the doc's
-      // in that case they'll take care of making the caret visible themselves
-
-      // Then make sure it's visible
-      return SetCaretEnabled(aPresShell, aVisible);
-    }
-  }
-
-  return NS_OK;
-}
-
-PRBool
-nsEventStateManager::GetBrowseWithCaret()
-{
-  return mBrowseWithCaret;
-}
-
-// Checks if the window corresponding to |aDocument| has the 
-// showcaret="true" attribute set.
-static PRBool
-GetWindowShowCaret(nsIDocument *aDocument)
-{
-  if (!aDocument) return PR_FALSE;
-
-  nsPIDOMWindow* window = aDocument->GetWindow();
-  if (!window) return PR_FALSE;
-
-  nsCOMPtr<nsIContent> docContent =
-    do_QueryInterface(window->GetFrameElementInternal());
-  if (!docContent) return PR_FALSE;
-
-  return docContent->AttrValueIs(kNameSpaceID_None,
-                                 nsGkAtoms::showcaret,
-                                 NS_LITERAL_STRING("true"),
-                                 eCaseMatters);
-}
-
-void
-nsEventStateManager::ResetBrowseWithCaret()
-{
-  // This is called when browse with caret changes on the fly
-  // or when a document gets focused
-
-  if (!mPresContext)
-    return;
-
-  nsCOMPtr<nsISupports> pcContainer = mPresContext->GetContainer();
-  PRInt32 itemType;
-  nsCOMPtr<nsIDocShellTreeItem> shellItem(do_QueryInterface(pcContainer));
-  if (!shellItem)
-    return;
-
-  shellItem->GetItemType(&itemType);
-
-  if (itemType == nsIDocShellTreeItem::typeChrome)
-    return;  // Never browse with caret in chrome
-
-  PRPackedBool browseWithCaret =
-    nsContentUtils::GetBoolPref("accessibility.browsewithcaret");
-  mBrowseWithCaret = browseWithCaret;
-
-  nsIPresShell *presShell = mPresContext->GetPresShell();
-
-  // If we're in an editable document which isn't contentEditable, or we're
-  // in a contentEditable document which whose focus is contentEditable,
-  // return, so that we don't mess with caret visibility.
-  nsCOMPtr<nsIEditorDocShell> editorDocShell(do_QueryInterface(shellItem));
-  if (editorDocShell) {
-    PRBool isEditable;
-    editorDocShell->GetEditable(&isEditable);
-    if (presShell && isEditable) {
-      nsCOMPtr<nsIHTMLDocument> doc =
-        do_QueryInterface(presShell->GetDocument());
-
-      PRBool isContentEditableDoc =
-        doc && doc->GetEditingState() == nsIHTMLDocument::eContentEditable;
-
-      PRBool isFocusEditable =
-        mCurrentFocus && mCurrentFocus->HasFlag(NODE_IS_EDITABLE);
-
-      if (!isContentEditableDoc || isFocusEditable)
-        return;
-    }
-  }
-
-  // Make caret visible or not, depending on what's appropriate.
-  // Set caret visibility for focused document only,
-  // others will be set when they get focused again
-  if (presShell && gLastFocusedDocument && gLastFocusedDocument == mDocument) {
-
-    PRBool caretShouldBeVisible = browseWithCaret ||
-                                  GetWindowShowCaret(mDocument);
-
-    SetContentCaretVisible(presShell, mCurrentFocus, caretShouldBeVisible);
-  }
-}
-
-//--------------------------------------------------------------------------------
-//-- DocShell Focus Traversal Methods
-//--------------------------------------------------------------------------------
-
-//----------------------------------------
-// Returns PR_TRUE if this doc contains a frameset
-PRBool
-nsEventStateManager::IsFrameSetDoc(nsIDocShell* aDocShell)
-{
-  NS_ASSERTION(aDocShell, "docshell is null");
-  PRBool isFrameSet = PR_FALSE;
-
-  // a frameset element will always be the immediate child
-  // of the root content (the HTML tag)
-  nsCOMPtr<nsIPresShell> presShell;
-  aDocShell->GetPresShell(getter_AddRefs(presShell));
-  if (presShell) {
-    nsIDocument *doc = presShell->GetDocument();
-    nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(doc);
-    if (htmlDoc) {
-      nsIContent *rootContent = doc->GetRootContent();
-      if (rootContent) {
-        PRUint32 childCount = rootContent->GetChildCount();
-        for (PRUint32 i = 0; i < childCount; ++i) {
-          nsIContent *childContent = rootContent->GetChildAt(i);
-
-          nsINodeInfo *ni = childContent->NodeInfo();
-
-          if (childContent->IsNodeOfType(nsINode::eHTML) &&
-              ni->Equals(nsGkAtoms::frameset)) {
-            isFrameSet = PR_TRUE;
-            break;
-          }
-        }
-      }
-    }
-  }
-
-  return isFrameSet;
-}
-
-//----------------------------------------
-// Returns PR_TRUE if this doc is an IFRAME
-
-PRBool
-nsEventStateManager::IsIFrameDoc(nsIDocShell* aDocShell)
-{
-  NS_ASSERTION(aDocShell, "docshell is null");
-
-  nsCOMPtr<nsPIDOMWindow> domWindow(do_GetInterface(aDocShell));
-  if (!domWindow) {
-    NS_ERROR("We're a child of a docshell without a window?");
-    return PR_FALSE;
-  }
-
-  nsCOMPtr<nsIContent> docContent =
-    do_QueryInterface(domWindow->GetFrameElementInternal());
-
-  if (!docContent) {
-    return PR_FALSE;
-  }
-
-  return docContent->Tag() == nsGkAtoms::iframe;
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+  if (!fm || !mDocument)
+    return nsnull;
+
+  nsCOMPtr<nsPIDOMWindow> focusedWindow;
+  return nsFocusManager::GetFocusedDescendant(mDocument->GetWindow(), PR_FALSE,
+                                              getter_AddRefs(focusedWindow));
 }
 
 //-------------------------------------------------------
 // Return PR_TRUE if the docshell is visible
 
 PRBool
 nsEventStateManager::IsShellVisible(nsIDocShell* aShell)
 {
@@ -6389,263 +4201,8 @@ nsEventStateManager::IsShellVisible(nsID
   PRBool isVisible = PR_TRUE;
   basewin->GetVisibility(&isVisible);
 
   // We should be doing some additional checks here so that
   // we don't tab into hidden tabs of tabbrowser.  -bryner
 
   return isVisible;
 }
-
-//------------------------------------------------
-// This method should be called when tab or F6/ctrl-tab
-// traversal wants to focus a new document.  It will focus
-// the docshell, traverse into the document if this type
-// of document does not get document focus (i.e. framsets
-// and chrome), and update the canvas focus state on the docshell.
-
-void
-nsEventStateManager::TabIntoDocument(nsIDocShell* aDocShell,
-                                     PRBool aForward)
-{
-  NS_ASSERTION(aDocShell, "null docshell");
-  nsCOMPtr<nsIDOMWindowInternal> domwin = do_GetInterface(aDocShell);
-  if (domwin)
-    domwin->Focus();
-
-  PRInt32 itemType;
-  nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(aDocShell);
-  treeItem->GetItemType(&itemType);
-
-  nsCOMPtr<nsPresContext> presContext;
-  aDocShell->GetPresContext(getter_AddRefs(presContext));
-  PRBool focusDocument;
-  if (presContext &&
-      presContext->Type() == nsPresContext::eContext_PrintPreview) {
-    // Don't focus any content in print preview mode, bug 244128.
-    focusDocument = PR_TRUE;
-  } else {
-    if (!aForward || (itemType == nsIDocShellTreeItem::typeChrome))
-      focusDocument = PR_FALSE;
-    else {
-      // Check for a frameset document
-      focusDocument = !(IsFrameSetDoc(aDocShell));
-    }
-  }
-
-  if (focusDocument) {
-    // make sure we're in view
-    aDocShell->SetCanvasHasFocus(PR_TRUE);
-  }
-  else {
-    aDocShell->SetHasFocus(PR_FALSE);
-
-    if (presContext) {
-      nsIEventStateManager *docESM = presContext->EventStateManager();
-
-      // we are about to shift focus to aDocShell
-      // keep track of the document, so we don't try to go back into it.
-      mTabbingFromDocShells.AppendObject(aDocShell);
-
-      // clear out any existing focus state
-      docESM->SetContentState(nsnull, NS_EVENT_STATE_FOCUS);
-      // now focus the first (or last) focusable content
-      docESM->ShiftFocus(aForward, nsnull);
-
-      // remove the document from the list
-      mTabbingFromDocShells.RemoveObject(aDocShell);
-    }
-  }
-}
-
-void
-nsEventStateManager::GetLastChildDocShell(nsIDocShellTreeItem* aItem,
-                                          nsIDocShellTreeItem** aResult)
-{
-  NS_ASSERTION(aItem, "null docshell");
-  NS_ASSERTION(aResult, "null out pointer");
-
-  nsCOMPtr<nsIDocShellTreeItem> curItem = do_QueryInterface(aItem);
-  while (1) {
-    nsCOMPtr<nsIDocShellTreeNode> curNode = do_QueryInterface(curItem);
-    PRInt32 childCount = 0;
-    curNode->GetChildCount(&childCount);
-    if (!childCount) {
-      *aResult = curItem;
-      NS_ADDREF(*aResult);
-      return;
-    }
-
-    curNode->GetChildAt(childCount - 1, getter_AddRefs(curItem));
-  }
-}
-
-void
-nsEventStateManager::GetNextDocShell(nsIDocShellTreeNode* aNode,
-                                     nsIDocShellTreeItem** aResult)
-{
-  NS_ASSERTION(aNode, "null docshell");
-  NS_ASSERTION(aResult, "null out pointer");
-
-  *aResult = nsnull;
-
-  PRInt32 childCount = 0;
-  aNode->GetChildCount(&childCount);
-  if (childCount) {
-    aNode->GetChildAt(0, aResult);
-    if (*aResult)
-      return;
-  }
-
-  nsCOMPtr<nsIDocShellTreeNode> curNode = aNode;
-  while (curNode) {
-    nsCOMPtr<nsIDocShellTreeItem> curItem = do_QueryInterface(curNode);
-    nsCOMPtr<nsIDocShellTreeItem> parentItem;
-    curItem->GetParent(getter_AddRefs(parentItem));
-    if (!parentItem) {
-      *aResult = nsnull;
-      return;
-    }
-
-    // Note that we avoid using GetChildOffset() here because docshell
-    // child offsets can't be trusted to be correct. bug 162283.
-    nsCOMPtr<nsIDocShellTreeNode> parentNode = do_QueryInterface(parentItem);
-    nsCOMPtr<nsIDocShellTreeItem> iterItem;
-    childCount = 0;
-    parentNode->GetChildCount(&childCount);
-    for (PRInt32 index = 0; index < childCount; ++index) {
-      parentNode->GetChildAt(index, getter_AddRefs(iterItem));
-      if (iterItem == curItem) {
-        ++index;
-        if (index < childCount) {
-          parentNode->GetChildAt(index, aResult);
-          if (*aResult)
-            return;
-        }
-        break;
-      }
-    }
-
-    curNode = do_QueryInterface(parentItem);
-  }
-}
-
-void
-nsEventStateManager::GetPrevDocShell(nsIDocShellTreeNode* aNode,
-                                     nsIDocShellTreeItem** aResult)
-{
-  NS_ASSERTION(aNode, "null docshell");
-  NS_ASSERTION(aResult, "null out pointer");
-
-  nsCOMPtr<nsIDocShellTreeItem> curItem = do_QueryInterface(aNode);
-  nsCOMPtr<nsIDocShellTreeItem> parentItem;
-
-  curItem->GetParent(getter_AddRefs(parentItem));
-  if (!parentItem) {
-    *aResult = nsnull;
-    return;
-  }
-
-  // Note that we avoid using GetChildOffset() here because docshell
-  // child offsets can't be trusted to be correct. bug 162283.
-  nsCOMPtr<nsIDocShellTreeNode> parentNode = do_QueryInterface(parentItem);
-  PRInt32 childCount = 0;
-  parentNode->GetChildCount(&childCount);
-  nsCOMPtr<nsIDocShellTreeItem> prevItem, iterItem;
-  for (PRInt32 index = 0; index < childCount; ++index) {
-    parentNode->GetChildAt(index, getter_AddRefs(iterItem));
-    if (iterItem == curItem)
-      break;
-    prevItem = iterItem;
-  }
-
-  if (prevItem) {
-    curItem = prevItem;
-    nsCOMPtr<nsIDocShellTreeNode> curNode;
-    // Get the last child recursively of this node.
-    while (1) {
-      curNode = do_QueryInterface(curItem);
-      childCount = 0;
-      curNode->GetChildCount(&childCount);
-      if (!childCount)
-        break;
-
-      curNode->GetChildAt(childCount - 1, getter_AddRefs(curItem));
-    }
-
-    *aResult = curItem;
-    NS_ADDREF(*aResult);
-    return;
-  }
-
-  *aResult = parentItem;
-  NS_ADDREF(*aResult);
-  return;
-}
-
-//-------------------------------------------------
-// Traversal by document/DocShell only
-// this does not include any content inside the doc
-// or IFrames
-void
-nsEventStateManager::ShiftFocusByDoc(PRBool aForward)
-{
-  // Note that we use the docshell tree here instead of iteratively calling
-  // ShiftFocus.  The docshell tree should be kept in depth-first frame tree
-  // order, the same as we use for tabbing, so the effect should be the same,
-  // but this is much faster.
-
-  NS_ASSERTION(mPresContext, "no prescontext");
-
-  nsCOMPtr<nsISupports> pcContainer = mPresContext->GetContainer();
-  nsCOMPtr<nsIDocShellTreeNode> curNode = do_QueryInterface(pcContainer);
-  if (!curNode) {
-    return;
-  }
-
-  // perform a depth first search (preorder) of the docshell tree
-  // looking for an HTML Frame or a chrome document
-
-  nsCOMPtr<nsIDocShellTreeItem> nextItem;
-  nsCOMPtr<nsIDocShell> nextShell;
-  do {
-    if (aForward) {
-      GetNextDocShell(curNode, getter_AddRefs(nextItem));
-      if (!nextItem) {
-        nsCOMPtr<nsIDocShellTreeItem> curItem = do_QueryInterface(pcContainer);
-        // wrap around to the beginning, which is the top of the tree
-        curItem->GetRootTreeItem(getter_AddRefs(nextItem));
-      }
-    }
-    else {
-      GetPrevDocShell(curNode, getter_AddRefs(nextItem));
-      if (!nextItem) {
-        nsCOMPtr<nsIDocShellTreeItem> curItem = do_QueryInterface(pcContainer);
-        // wrap around to the end, which is the last node in the tree
-        nsCOMPtr<nsIDocShellTreeItem> rootItem;
-        curItem->GetRootTreeItem(getter_AddRefs(rootItem));
-        GetLastChildDocShell(rootItem, getter_AddRefs(nextItem));
-      }
-    }
-
-    curNode = do_QueryInterface(nextItem);
-    nextShell = do_QueryInterface(nextItem);
-  } while (IsFrameSetDoc(nextShell) || IsIFrameDoc(nextShell) || !IsShellVisible(nextShell));
-
-  if (nextShell) {
-    // NOTE: always tab forward into the document, this ensures that we
-    // focus the document itself, not its last focusable content.
-    // chrome documents will get their first focusable content focused.
-    SetContentState(nsnull, NS_EVENT_STATE_FOCUS);
-    TabIntoDocument(nextShell, PR_TRUE);
-  }
-}
-
-// Get the FocusController given an nsIDocument
-nsIFocusController*
-nsEventStateManager::GetFocusControllerForDocument(nsIDocument* aDocument)
-{
-  nsCOMPtr<nsISupports> container = aDocument->GetContainer();
-  nsCOMPtr<nsPIDOMWindow> windowPrivate = do_GetInterface(container);
-
-  return windowPrivate ? windowPrivate->GetRootFocusController() : nsnull;
-}
-
--- a/content/events/src/nsEventStateManager.h
+++ b/content/events/src/nsEventStateManager.h
@@ -116,41 +116,28 @@ public:
   NS_IMETHOD SetPresContext(nsPresContext* aPresContext);
   NS_IMETHOD ClearFrameRefs(nsIFrame* aFrame);
 
   NS_IMETHOD GetEventTarget(nsIFrame **aFrame);
   NS_IMETHOD GetEventTargetContent(nsEvent* aEvent, nsIContent** aContent);
 
   NS_IMETHOD GetContentState(nsIContent *aContent, PRInt32& aState);
   virtual PRBool SetContentState(nsIContent *aContent, PRInt32 aState);
-  NS_IMETHOD GetFocusedContent(nsIContent **aContent);
-  NS_IMETHOD SetFocusedContent(nsIContent* aContent);
-  NS_IMETHOD GetLastFocusedContent(nsIContent **aContent);
-  NS_IMETHOD GetFocusedFrame(nsIFrame **aFrame);
-  NS_IMETHOD ContentRemoved(nsIContent* aContent);
+  NS_IMETHOD ContentRemoved(nsIDocument* aDocument, nsIContent* aContent);
   NS_IMETHOD EventStatusOK(nsGUIEvent* aEvent, PRBool *aOK);
 
   // Access Key Registration
   NS_IMETHOD RegisterAccessKey(nsIContent* aContent, PRUint32 aKey);
   NS_IMETHOD UnregisterAccessKey(nsIContent* aContent, PRUint32 aKey);
   NS_IMETHOD GetRegisteredAccessKey(nsIContent* aContent, PRUint32* aKey);
 
   NS_IMETHOD SetCursor(PRInt32 aCursor, imgIContainer* aContainer,
                        PRBool aHaveHotspot, float aHotspotX, float aHotspotY,
                        nsIWidget* aWidget, PRBool aLockCursor);
 
-  NS_IMETHOD ShiftFocus(PRBool aForward, nsIContent* aStart=nsnull);
-
-  virtual PRBool GetBrowseWithCaret();
-  void ResetBrowseWithCaret();
-
-  NS_IMETHOD MoveFocusToCaret(PRBool aCanFocusDoc, PRBool *aIsSelectionWithFocus);
-  NS_IMETHOD MoveCaretToFocus();
-  NS_IMETHOD ChangeFocusWith(nsIContent* aFocus, EFocusedWithType aFocusedWith);
-
   static void StartHandlingUserInput()
   {
     ++sUserInputEventDepth;
   }
 
   static void StopHandlingUserInput()
   {
     --sUserInputEventDepth;
@@ -162,24 +149,16 @@ public:
   }
 
   NS_IMETHOD_(PRBool) IsHandlingUserInputExternal() { return IsHandlingUserInput(); }
   
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsEventStateManager,
                                            nsIEventStateManager)
 
 protected:
-  /**
-   * In certain situations the focus controller's concept of focus gets out of
-   * whack with mCurrentFocus. This is used in known cases to reset the focus
-   * controller's focus. At some point we should probably move to a single
-   * focus storage mechanism because tracking it in several places is error-prone.
-   */
-  void EnsureFocusSynchronization();
-
   void UpdateCursor(nsPresContext* aPresContext, nsEvent* aEvent, nsIFrame* aTargetFrame, nsEventStatus* aStatus);
   /**
    * Turn a GUI mouse event into a mouse event targeted at the specified
    * content.  This returns the primary frame for the content (or null
    * if it goes away during the event).
    */
   nsIFrame* DispatchMouseEvent(nsGUIEvent* aEvent, PRUint32 aMessage,
                                nsIContent* aTargetContent,
@@ -216,30 +195,18 @@ protected:
   void FireDragEnterOrExit(nsPresContext* aPresContext,
                            nsGUIEvent* aEvent,
                            PRUint32 aMsg,
                            nsIContent* aRelatedTarget,
                            nsIContent* aTargetContent,
                            nsWeakFrame& aTargetFrame);
   nsresult SetClickCount(nsPresContext* aPresContext, nsMouseEvent *aEvent, nsEventStatus* aStatus);
   nsresult CheckForAndDispatchClick(nsPresContext* aPresContext, nsMouseEvent *aEvent, nsEventStatus* aStatus);
-  nsresult GetNextTabbableContent(nsIContent* aRootContent,
-                                  nsIContent* aStartContent,
-                                  nsIFrame* aStartFrame,
-                                  PRBool forward, PRBool ignoreTabIndex,
-                                  nsIContent** aResultNode,
-                                  nsIFrame** aResultFrame);
-  nsIContent *GetNextTabbableMapArea(PRBool aForward, nsIContent *imageContent);
-
-  PRInt32 GetNextTabIndex(nsIContent* aParent, PRBool foward);
-  nsresult SendFocusBlur(nsPresContext* aPresContext, nsIContent *aContent, PRBool aEnsureWindowHasFocus);
-  void EnsureDocument(nsIPresShell* aPresShell);
   void EnsureDocument(nsPresContext* aPresContext);
   void FlushPendingEvents(nsPresContext* aPresContext);
-  nsIFocusController* GetFocusControllerForDocument(nsIDocument* aDocument);
 
   /**
    * The phases of HandleAccessKey processing. See below.
    */
   typedef enum {
     eAccessKeyProcessingNormal = 0,
     eAccessKeyProcessingUp,
     eAccessKeyProcessingDown
@@ -273,28 +240,18 @@ protected:
 
   PRBool ExecuteAccessKey(nsTArray<PRUint32>& aAccessCharCodes,
                           PRBool aIsTrustedEvent);
 
   //---------------------------------------------
   // DocShell Focus Traversal Methods
   //---------------------------------------------
 
-  nsresult ShiftFocusInternal(PRBool aForward, nsIContent* aStart = nsnull);
-  void TabIntoDocument(nsIDocShell* aDocShell, PRBool aForward);
-  void ShiftFocusByDoc(PRBool forward);
-  PRBool IsFrameSetDoc(nsIDocShell* aDocShell);
-  PRBool IsIFrameDoc(nsIDocShell* aDocShell);
+  nsIContent* GetFocusedContent();
   PRBool IsShellVisible(nsIDocShell* aShell);
-  void GetLastChildDocShell(nsIDocShellTreeItem* aItem,
-                            nsIDocShellTreeItem** aResult);
-  void GetNextDocShell(nsIDocShellTreeNode* aNode,
-                       nsIDocShellTreeItem** aResult);
-  void GetPrevDocShell(nsIDocShellTreeNode* aNode,
-                       nsIDocShellTreeItem** aResult);
 
   // These functions are for mousewheel and pixel scrolling
   nsresult GetParentScrollingView(nsInputEvent* aEvent,
                                   nsPresContext* aPresContext,
                                   nsIFrame* &targetOuterFrame,
                                   nsPresContext* &presCtxOuter);
   void SendLineScrollEvent(nsIFrame* aTargetFrame,
                            nsMouseScrollEvent* aEvent,
@@ -364,26 +321,16 @@ protected:
   /**
    * Set the fields of aEvent to reflect the mouse position and modifier keys
    * that were set when the user first pressed the mouse button (stored by
    * BeginTrackingDragGesture). aEvent->widget must be
    * mCurrentTarget->GetWindow().
    */
   void FillInEventFromGestureDown(nsMouseEvent* aEvent);
 
-  PRBool mSuppressFocusChange; // Used only for Ender text fields to suppress a focus firing on mouse down
-
-  nsresult SetCaretEnabled(nsIPresShell *aPresShell, PRBool aVisibility);
-  nsresult SetContentCaretVisible(nsIPresShell* aPresShell, nsIContent *aContent, PRBool aVisible);
-  void FocusElementButNotDocument(nsIContent *aElement);
-
-  // Return the location of the caret
-  nsresult GetDocSelectionLocation(nsIContent **start, nsIContent **end, 
-                                   nsIFrame **startFrame, PRUint32 *startOffset);
-
   PRInt32     mLockCursor;
 
   nsWeakFrame mCurrentTarget;
   nsCOMPtr<nsIContent> mCurrentTargetContent;
   nsWeakFrame mLastMouseOverFrame;
   nsCOMPtr<nsIContent> mLastMouseOverElement;
   nsWeakFrame mLastDragOverFrame;
 
@@ -404,30 +351,16 @@ protected:
   nsCOMPtr<nsIContent> mLastLeftMouseDownContent;
   nsCOMPtr<nsIContent> mLastMiddleMouseDownContent;
   nsCOMPtr<nsIContent> mLastRightMouseDownContent;
 
   nsCOMPtr<nsIContent> mActiveContent;
   nsCOMPtr<nsIContent> mHoverContent;
   nsCOMPtr<nsIContent> mDragOverContent;
   nsCOMPtr<nsIContent> mURLTargetContent;
-  nsCOMPtr<nsIContent> mCurrentFocus;
-  nsCOMPtr<nsIContent> mLastFocus;
-  nsWeakFrame mCurrentFocusFrame;
-  PRInt32 mCurrentTabIndex;
-  EFocusedWithType mLastFocusedWith;
-
-  // DocShell Traversal Data Memebers
-  nsCOMPtr<nsIContent> mLastContentFocus;
-
-  //Anti-recursive stack controls
-
-  nsCOMPtr<nsIContent> mFirstBlurEvent;
-  nsCOMPtr<nsIDocument> mFirstDocumentBlurEvent;
-  nsCOMPtr<nsIContent> mFirstFocusEvent;
 
   // The last element on which we fired a mouseover event, or null if
   // the last mouseover event we fired has finished processing.
   nsCOMPtr<nsIContent> mFirstMouseOverEventElement;
 
   // The last element on which we fired a mouseout event, or null if
   // the last mouseout event we fired has finished processing.
   nsCOMPtr<nsIContent> mFirstMouseOutEventElement;
@@ -438,27 +371,19 @@ protected:
   PRUint32 mLClickCount;
   PRUint32 mMClickCount;
   PRUint32 mRClickCount;
 
   PRPackedBool mNormalLMouseEventInProcess;
 
   PRPackedBool m_haveShutdown;
 
-  // So we don't have to keep checking accessibility.browsewithcaret pref
-  PRPackedBool mBrowseWithCaret;
-
-  // Recursion guard for tabbing
-  PRPackedBool mTabbedThroughDocument;
-
   // Array for accesskey support
   nsCOMArray<nsIContent> mAccessKeys;
 
-  nsCOMArray<nsIDocShell> mTabbingFromDocShells;
-
   // Unlocks pixel scrolling
   PRPackedBool mLastLineScrollConsumedX;
   PRPackedBool mLastLineScrollConsumedY;
 
 #ifdef CLICK_HOLD_CONTEXT_MENUS
   enum { kClickHoldDelay = 500 } ;        // 500ms == 1/2 second
 
   void CreateClickHoldTimer ( nsPresContext* aPresContext, nsIFrame* inDownFrame,
--- a/content/events/src/nsIMEStateManager.cpp
+++ b/content/events/src/nsIMEStateManager.cpp
@@ -46,17 +46,16 @@
 #include "nsIPresShell.h"
 #include "nsISupports.h"
 #include "nsPIDOMWindow.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIEditorDocShell.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
 #include "nsPresContext.h"
-#include "nsIFocusController.h"
 #include "nsIDOMWindow.h"
 #include "nsContentUtils.h"
 #include "nsINode.h"
 #include "nsIFrame.h"
 #include "nsRange.h"
 #include "nsIDOMRange.h"
 #include "nsISelection.h"
 #include "nsISelectionPrivate.h"
@@ -66,17 +65,16 @@
 #include "nsContentEventHandler.h"
 
 /******************************************************************/
 /* nsIMEStateManager                                              */
 /******************************************************************/
 
 nsIContent*    nsIMEStateManager::sContent      = nsnull;
 nsPresContext* nsIMEStateManager::sPresContext  = nsnull;
-nsPIDOMWindow* nsIMEStateManager::sActiveWindow = nsnull;
 PRBool         nsIMEStateManager::sInstalledMenuKeyboardListener = PR_FALSE;
 
 nsTextStateManager* nsIMEStateManager::sTextStateObserver = nsnull;
 
 nsresult
 nsIMEStateManager::OnDestroyPresContext(nsPresContext* aPresContext)
 {
   NS_ENSURE_ARG_POINTER(aPresContext);
@@ -113,21 +111,16 @@ nsIMEStateManager::OnRemoveContent(nsPre
 }
 
 nsresult
 nsIMEStateManager::OnChangeFocus(nsPresContext* aPresContext,
                                  nsIContent* aContent)
 {
   NS_ENSURE_ARG_POINTER(aPresContext);
 
-  if (!IsActive(aPresContext)) {
-    // The actual focus isn't changing, because this presContext isn't active.
-    return NS_OK;
-  }
-
   nsCOMPtr<nsIWidget> widget = GetWidget(aPresContext);
   if (!widget) {
     return NS_OK;
   }
 
   PRUint32 newState = GetNewIMEState(aPresContext, aContent);
   if (aPresContext == sPresContext && aContent == sContent) {
     // actual focus isn't changing, but if IME enabled state is changing,
@@ -166,77 +159,23 @@ nsIMEStateManager::OnChangeFocus(nsPresC
   }
 
   sPresContext = aPresContext;
   sContent = aContent;
 
   return NS_OK;
 }
 
-nsresult
-nsIMEStateManager::OnActivate(nsPresContext* aPresContext)
-{
-  NS_ENSURE_ARG_POINTER(aPresContext);
-  sActiveWindow = aPresContext->Document()->GetWindow();
-  NS_ENSURE_TRUE(sActiveWindow, NS_ERROR_FAILURE);
-  sActiveWindow = sActiveWindow->GetPrivateRoot();
-  return NS_OK;
-}
-
-nsresult
-nsIMEStateManager::OnDeactivate(nsPresContext* aPresContext)
-{
-  NS_ENSURE_ARG_POINTER(aPresContext);
-  NS_ENSURE_TRUE(aPresContext->Document()->GetWindow(), NS_ERROR_FAILURE);
-  if (sActiveWindow !=
-      aPresContext->Document()->GetWindow()->GetPrivateRoot())
-    return NS_OK;
-
-  sActiveWindow = nsnull;
-  return NS_OK;
-}
-
 void
 nsIMEStateManager::OnInstalledMenuKeyboardListener(PRBool aInstalling)
 {
   sInstalledMenuKeyboardListener = aInstalling;
   OnChangeFocus(sPresContext, sContent);
 }
 
-PRBool
-nsIMEStateManager::IsActive(nsPresContext* aPresContext)
-{
-  NS_ENSURE_TRUE(aPresContext, PR_FALSE);
-  nsPIDOMWindow* window = aPresContext->Document()->GetWindow();
-  NS_ENSURE_TRUE(window, PR_FALSE);
-  if (!sActiveWindow || sActiveWindow != window->GetPrivateRoot()) {
-    // This root window is not active.
-    return PR_FALSE;
-  }
-
-  nsIPresShell* shell = aPresContext->GetPresShell();
-  NS_ENSURE_TRUE(shell, PR_FALSE);
-  nsIViewManager* vm = shell->GetViewManager();
-  NS_ENSURE_TRUE(vm, PR_FALSE);
-  nsCOMPtr<nsIViewObserver> observer;
-  vm->GetViewObserver(*getter_AddRefs(observer));
-  NS_ENSURE_TRUE(observer, PR_FALSE);
-  return observer->IsVisible();
-}
-
-nsIFocusController*
-nsIMEStateManager::GetFocusController(nsPresContext* aPresContext)
-{
-  nsCOMPtr<nsISupports> container =
-    aPresContext->Document()->GetContainer();
-  nsCOMPtr<nsPIDOMWindow> windowPrivate = do_GetInterface(container);
-
-  return windowPrivate ? windowPrivate->GetRootFocusController() : nsnull;
-}
-
 PRUint32
 nsIMEStateManager::GetNewIMEState(nsPresContext* aPresContext,
                                   nsIContent*    aContent)
 {
   // On Printing or Print Preview, we don't need IME.
   if (aPresContext->Type() == nsPresContext::eContext_PrintPreview ||
       aPresContext->Type() == nsPresContext::eContext_Print) {
     return nsIContent::IME_STATUS_DISABLE;
--- a/content/events/src/nsIMEStateManager.h
+++ b/content/events/src/nsIMEStateManager.h
@@ -56,18 +56,16 @@ class nsISelection;
 class nsIMEStateManager
 {
 public:
   static nsresult OnDestroyPresContext(nsPresContext* aPresContext);
   static nsresult OnRemoveContent(nsPresContext* aPresContext,
                                   nsIContent* aContent);
   static nsresult OnChangeFocus(nsPresContext* aPresContext,
                                 nsIContent* aContent);
-  static nsresult OnActivate(nsPresContext* aPresContext);
-  static nsresult OnDeactivate(nsPresContext* aPresContext);
   static void OnInstalledMenuKeyboardListener(PRBool aInstalling);
 
   // These two methods manage focus and selection/text observers.
   // They are separate from OnChangeFocus above because this offers finer
   // control compared to having the two methods incorporated into OnChangeFocus
 
   // OnTextStateBlur should be called *before* NS_BLUR_CONTENT fires
   // aPresContext is the nsPresContext receiving focus (not lost focus)
@@ -85,22 +83,18 @@ public:
                                            nsIContent** aRoot);
 protected:
   static void SetIMEState(nsPresContext* aPresContext,
                           PRUint32 aState,
                           nsIWidget* aKB);
   static PRUint32 GetNewIMEState(nsPresContext* aPresContext,
                                  nsIContent* aContent);
 
-  static PRBool IsActive(nsPresContext* aPresContext);
-
-  static nsIFocusController* GetFocusController(nsPresContext* aPresContext);
   static nsIWidget* GetWidget(nsPresContext* aPresContext);
 
   static nsIContent*    sContent;
   static nsPresContext* sPresContext;
-  static nsPIDOMWindow* sActiveWindow;
   static PRBool         sInstalledMenuKeyboardListener;
 
   static nsTextStateManager* sTextStateObserver;
 };
 
 #endif // nsIMEStateManager_h__
--- a/content/events/test/test_bug450876.html
+++ b/content/events/test/test_bug450876.html
@@ -22,18 +22,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 
 function doTest() {
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   is(document.activeElement, document.body, "body element should be focused");
   document.getElementById('a').focus();
   is(document.activeElement, document.getElementById('a'), "link should have focus");
   var wu =  window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                 .getInterface(Components.interfaces.nsIDOMWindowUtils);
+  is(document.hasFocus(), true, "document should be focused");
   wu.sendKeyEvent('keypress',  9, 0, 0);
-  is(document.activeElement, document.body, "body element should be focused");
+  is(document.activeElement, document.getElementById('a'), "body element should be focused");
+  is(document.hasFocus(), false, "document should not be focused");
 
   SimpleTest.finish();
 }
 
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(doTest);
 
 </script>
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -71,16 +71,17 @@
 #include "nsIScrollableView.h"
 #include "nsIScrollableViewProvider.h"
 #include "nsIView.h"
 #include "nsIViewManager.h"
 #include "nsRange.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsIDocShell.h"
+#include "nsIDocShellTreeItem.h"
 #include "nsINameSpaceManager.h"
 #include "nsDOMError.h"
 #include "nsScriptLoader.h"
 #include "nsRuleData.h"
 
 #include "nsPresState.h"
 #include "nsILayoutHistoryState.h"
 
@@ -92,16 +93,17 @@
 #include "nsIEventStateManager.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMNSEvent.h"
 #include "nsDOMCSSDeclaration.h"
 #include "nsITextControlFrame.h"
 #include "nsIForm.h"
 #include "nsIFormControl.h"
 #include "nsIDOMHTMLFormElement.h"
+#include "nsFocusManager.h"
 
 #include "nsMutationEvent.h"
 
 #include "nsContentCID.h"
 
 #include "nsIDOMText.h"
 
 #include "nsIEditor.h"
@@ -2591,16 +2593,45 @@ nsGenericHTMLFormElement::AfterSetAttr(P
       }
     }
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
                                             aValue, aNotify);
 }
 
+nsresult
+nsGenericHTMLFormElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
+{
+  if (NS_IS_TRUSTED_EVENT(aVisitor.mEvent)) {
+    switch (aVisitor.mEvent->message) {
+      case NS_FOCUS_CONTENT:
+      {
+        // Check to see if focus has bubbled up from a form control's
+        // child textfield or button.  If that's the case, don't focus
+        // this parent file control -- leave focus on the child.
+        nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
+        if (formControlFrame &&
+            aVisitor.mEvent->originalTarget == static_cast<nsINode*>(this))
+          formControlFrame->SetFocus(PR_TRUE, PR_TRUE);
+        break;
+      }
+      case NS_BLUR_CONTENT:
+      {
+        nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
+        if (formControlFrame)
+          formControlFrame->SetFocus(PR_FALSE, PR_FALSE);
+        break;
+      }
+    }
+  }
+
+  return nsGenericHTMLElement::PreHandleEvent(aVisitor);
+}
+
 PRBool
 nsGenericHTMLFormElement::CanBeDisabled() const
 {
   PRInt32 type = GetType();
   // It's easier to test the types that _cannot_ be disabled
   return
     type != NS_FORM_LABEL &&
     type != NS_FORM_LEGEND &&
@@ -2646,81 +2677,49 @@ nsGenericHTMLFormElement::IntrinsicState
                    "Default submit element that isn't a submit control.");
       // We are the default submit element (:default)
       state |= NS_EVENT_STATE_DEFAULT;
   }
 
   return state;
 }
 
-void
-nsGenericHTMLFormElement::SetFocusAndScrollIntoView(nsPresContext* aPresContext)
-{
-  nsIEventStateManager *esm = aPresContext->EventStateManager();
-  if (esm->SetContentState(this, NS_EVENT_STATE_FOCUS)) {
-    // XXXldb once bug 43114 is fixed, we don't need to flush here.
-    aPresContext->Document()->
-      FlushPendingNotifications(Flush_InterruptibleLayout);
-    nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE);
-    if (formControlFrame) {
-      formControlFrame->SetFocus(PR_TRUE, PR_TRUE);
-      nsCOMPtr<nsIPresShell> presShell = aPresContext->GetPresShell();
-      if (presShell) {
-        presShell->ScrollContentIntoView(this, NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,
-                                         NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE);
-      }
-    }
-  }
-}
-
-void
-nsGenericHTMLFormElement::DoSetFocus(nsPresContext* aPresContext)
-{
-  if (!aPresContext)
-    return;
-
-  if (FocusState() == eActiveWindow) {
-    SetFocusAndScrollIntoView(aPresContext);
-  }
-}
-
 nsGenericHTMLFormElement::FocusTristate
 nsGenericHTMLFormElement::FocusState()
 {
   // We can't be focused if we aren't in a document
   nsIDocument* doc = GetCurrentDoc();
   if (!doc)
     return eUnfocusable;
 
   // first see if we are disabled or not. If disabled then do nothing.
   if (HasAttr(kNameSpaceID_None, nsGkAtoms::disabled)) {
     return eUnfocusable;
   }
 
   // If the window is not active, do not allow the focus to bring the
   // window to the front.  We update the focus controller, but do
   // nothing else.
-  nsCOMPtr<nsPIDOMWindow> win = doc->GetWindow();
-  if (win) {
-    nsIFocusController *focusController = win->GetRootFocusController();
-    if (focusController) {
-      PRBool isActive = PR_FALSE;
-      focusController->GetActive(&isActive);
-      if (!isActive) {
-        focusController->SetFocusedWindow(win);
-        nsCOMPtr<nsIDOMElement> el =
-          do_QueryInterface(static_cast<nsGenericHTMLElement*>(this));
-        focusController->SetFocusedElement(el);
-
-        return eInactiveWindow;
+  nsCOMPtr<nsIDocShellTreeItem> dsti = do_GetInterface(doc->GetWindow());
+  if (dsti) {
+    nsCOMPtr<nsIDocShellTreeItem> root;
+    dsti->GetRootTreeItem(getter_AddRefs(root));
+    nsCOMPtr<nsIDOMWindow> rootWindow = do_GetInterface(root);
+
+    nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
+    if (fm && rootWindow) {
+      nsCOMPtr<nsIDOMWindow> activeWindow;
+      fm->GetActiveWindow(getter_AddRefs(activeWindow));
+      if (activeWindow == rootWindow) {
+        return eActiveWindow;
       }
     }
   }
 
-  return eActiveWindow;
+  return eInactiveWindow;
 }
 
 //----------------------------------------------------------------------
 
 nsGenericHTMLFrameElement::~nsGenericHTMLFrameElement()
 {
   if (mFrameLoader) {
     mFrameLoader->Destroy();
@@ -2902,78 +2901,39 @@ nsGenericHTMLFrameElement::DestroyConten
     mFrameLoader = nsnull;
   }
 
   nsGenericHTMLElement::DestroyContent();
 }
 
 //----------------------------------------------------------------------
 
-void
-nsGenericHTMLElement::SetElementFocus(PRBool aDoFocus)
-{
-  nsCOMPtr<nsPresContext> presContext = GetPresContext();
-  if (!presContext)
-    return;
-
-  if (aDoFocus) {
-    if (IsInDoc()) {
-      // Make sure that our frames are up to date so we focus the right thing.
-      GetCurrentDoc()->FlushPendingNotifications(Flush_Frames);
-    }
-
-    SetFocus(presContext);
-
-    presContext->EventStateManager()->MoveCaretToFocus();
-    return;
-  }
-
-  RemoveFocus(presContext);
-}
-
 nsresult
 nsGenericHTMLElement::Blur()
 {
-  if (ShouldBlur(this)) {
-    SetElementFocus(PR_FALSE);
-  }
+  if (!ShouldBlur(this))
+    return NS_OK;
+
+  nsIDocument* doc = GetCurrentDoc();
+  if (!doc)
+    return NS_OK;
+
+  nsIDOMWindow* win = doc->GetWindow();
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+  return (win && fm) ? fm->ClearFocus(win) : NS_OK;
 
   return NS_OK;
 }
 
 nsresult
 nsGenericHTMLElement::Focus()
 {
-  // Generic HTML elements are focusable only if tabindex explicitly set.
-  // SetFocus() will check to see if we're focusable and then
-  // call into esm to do the work of focusing.
-  if (ShouldFocus(this)) {
-    SetElementFocus(PR_TRUE);
-  }
-
-  return NS_OK;
-}
-
-void
-nsGenericHTMLElement::RemoveFocus(nsPresContext *aPresContext)
-{
-  if (!aPresContext) 
-    return;
-
-  if (IsNodeOfType(eHTML_FORM_CONTROL)) {
-    nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
-    if (formControlFrame) {
-      formControlFrame->SetFocus(PR_FALSE, PR_FALSE);
-    }
-  }
-  
-  if (IsInDoc()) {
-    aPresContext->EventStateManager()->SetContentState(nsnull,
-                                                       NS_EVENT_STATE_FOCUS);
-  }
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+  nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(this);
+  return fm ? fm->SetFocus(elem, 0) : NS_OK;
 }
 
 PRBool
 nsGenericHTMLElement::IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex)
 {
   nsIDocument *doc = GetCurrentDoc();
   if (!doc || doc->HasFlag(NODE_IS_EDITABLE)) {
     // In designMode documents we only allow focusing the document.
@@ -2984,34 +2944,33 @@ nsGenericHTMLElement::IsHTMLFocusable(PR
     *aIsFocusable = PR_FALSE;
 
     return PR_TRUE;
   }
 
   PRInt32 tabIndex = 0;   // Default value for non HTML elements with -moz-user-focus
   GetTabIndex(&tabIndex);
 
-  PRBool override, disabled;
+  PRBool override, disabled = PR_FALSE;
   if (IsEditableRoot()) {
     // Editable roots should always be focusable.
     override = PR_TRUE;
 
     // Ignore the disabled attribute in editable contentEditable/designMode
     // roots.
-    disabled = PR_FALSE;
     if (!HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)) {
       // The default value for tabindex should be 0 for editable
       // contentEditable roots.
       tabIndex = 0;
     }
   }
   else {
     override = PR_FALSE;
 
-    // Just check for disabled attribute on all HTML elements
+    // Just check for disabled attribute on form controls
     disabled = HasAttr(kNameSpaceID_None, nsGkAtoms::disabled);
     if (disabled) {
       tabIndex = -1;
     }
   }
 
   if (aTabIndex) {
     *aTabIndex = tabIndex;
@@ -3052,22 +3011,22 @@ nsGenericHTMLElement::RegUnRegAccessKey(
 void
 nsGenericHTMLElement::PerformAccesskey(PRBool aKeyCausesActivation,
                                        PRBool aIsTrustedEvent)
 {
   nsPresContext *presContext = GetPresContext();
   if (!presContext)
     return;
 
-  nsIEventStateManager *esm = presContext->EventStateManager();
-  if (!esm)
-    return;
-
   // It's hard to say what HTML4 wants us to do in all cases.
-  esm->ChangeFocusWith(this, nsIEventStateManager::eEventFocusedByKey);
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+  if (fm) {
+    nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(this);
+    fm->SetFocus(elem, nsIFocusManager::FLAG_BYKEY);
+  }
 
   if (aKeyCausesActivation) {
     // Click on it if the users prefs indicate to do so.
     nsMouseEvent event(aIsTrustedEvent, NS_MOUSE_CLICK,
                        nsnull, nsMouseEvent::eReal);
 
     nsAutoPopupStatePusher popupStatePusher(aIsTrustedEvent ?
                                             openAllowed : openAbused);
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -167,17 +167,16 @@ public:
     return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
   }
   virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                            nsIAtom* aPrefix, const nsAString& aValue,
                            PRBool aNotify);
   virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                              PRBool aNotify);
   virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
-  virtual void RemoveFocus(nsPresContext *aPresContext);
   virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull)
   {
     PRBool isFocusable = PR_FALSE;
     IsHTMLFocusable(&isFocusable, aTabIndex);
     return isFocusable;
   }
   /**
    * Returns PR_TRUE if a subclass is not allowed to override the value returned
@@ -540,23 +539,16 @@ public:
   /**
    * Locate an nsIEditor rooted at this content node, if there is one.
    */
   NS_HIDDEN_(nsresult) GetEditor(nsIEditor** aEditor);
   NS_HIDDEN_(nsresult) GetEditorInternal(nsIEditor** aEditor);
 
 protected:
   /**
-   * Focus or blur the element.  This is what you should call if you want to
-   * *cause* a focus or blur on your element.  SetFocus / SetBlur are the
-   * methods where you want to catch what occurs on your element.
-   * @param aDoFocus true to focus, false to blur
-   */
-  void SetElementFocus(PRBool aDoFocus);
-  /**
    * Register or unregister an access key to this element based on the
    * accesskey attribute.
    * @param aDoReg true to register, false to unregister
    */
   void RegUnRegAccessKey(PRBool aDoReg);
 
   /**
    * Determine whether an attribute is an event (onclick, etc.)
@@ -827,35 +819,32 @@ public:
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               PRBool aCompileEventHandlers);
   virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
                               PRBool aNullParent = PR_TRUE);
   virtual PRUint32 GetDesiredIMEState();
   virtual PRInt32 IntrinsicState() const;
 
+  virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
+
 protected:
   virtual nsresult BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                                  const nsAString* aValue, PRBool aNotify);
 
   virtual nsresult AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                                 const nsAString* aValue, PRBool aNotify);
 
   /**
    * Returns true if the control can be disabled
    */
   PRBool CanBeDisabled() const;
 
   void UpdateEditableFormControlState();
 
-  void SetFocusAndScrollIntoView(nsPresContext* aPresContext);
-
-  // A sane SetFocus implementation for focusable form controls
-  void DoSetFocus(nsPresContext* aPresContext);
-
   // The focusability state of this form control.  eUnfocusable means that it
   // shouldn't be focused at all, eInactiveWindow means it's in an inactive
   // window, eActiveWindow means it's in an active window.
   enum FocusTristate {
     eUnfocusable,
     eInactiveWindow,
     eActiveWindow
   };
--- a/content/html/content/src/nsHTMLAnchorElement.cpp
+++ b/content/html/content/src/nsHTMLAnchorElement.cpp
@@ -108,17 +108,16 @@ public:
   // override from nsGenericHTMLElement
   NS_IMETHOD GetDraggable(PRBool* aDraggable);
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               PRBool aCompileEventHandlers);
   virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
                               PRBool aNullParent = PR_TRUE);
-  virtual void SetFocus(nsPresContext* aPresContext);
   virtual PRBool IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex);
 
   virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
   virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
   virtual PRBool IsLink(nsIURI** aURI) const;
   virtual void GetLinkTarget(nsAString& aTarget);
 
   nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
@@ -235,59 +234,45 @@ nsHTMLAnchorElement::UnbindFromTree(PRBo
   }
     
   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
 }
 
 NS_IMETHODIMP
 nsHTMLAnchorElement::Blur()
 {
-  if (ShouldBlur(this)) {
-    SetElementFocus(PR_FALSE);
-  }
-
-  return NS_OK;
+  return nsGenericHTMLElement::Blur();
 }
 
 NS_IMETHODIMP
 nsHTMLAnchorElement::Focus()
 {
-  if (ShouldFocus(this)) {
-    SetElementFocus(PR_TRUE);
-  }
-
-  return NS_OK;
-}
-
-void
-nsHTMLAnchorElement::SetFocus(nsPresContext* aPresContext)
-{
-  if (!aPresContext) {
-    return;
-  }
-
-  // don't make the link grab the focus if there is no link handler
-  nsILinkHandler *handler = aPresContext->GetLinkHandler();
-  if (handler && aPresContext->EventStateManager()->
-                               SetContentState(this, NS_EVENT_STATE_FOCUS)) {
-    nsCOMPtr<nsIPresShell> presShell = aPresContext->GetPresShell();
-    if (presShell) {
-      presShell->ScrollContentIntoView(this, NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,
-                                       NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE);
-    }
-  }
+  return nsGenericHTMLElement::Focus();
 }
 
 PRBool
 nsHTMLAnchorElement::IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex)
 {
   if (nsGenericHTMLElement::IsHTMLFocusable(aIsFocusable, aTabIndex)) {
     return PR_TRUE;
   }
 
+  // cannot focus links if there is no link handler
+  nsIDocument* doc = GetCurrentDoc();
+  if (doc) {
+    nsIPresShell* presShell = doc->GetPrimaryShell();
+    if (presShell) {
+      nsPresContext* presContext = presShell->GetPresContext();
+      if (presContext && !presContext->GetLinkHandler()) {
+        *aIsFocusable = PR_FALSE;
+        return PR_FALSE;
+      }
+    }
+  }
+
   if (IsEditable()) {
     if (aTabIndex) {
       *aTabIndex = -1;
     }
 
     *aIsFocusable = PR_FALSE;
 
     return PR_TRUE;
--- a/content/html/content/src/nsHTMLAreaElement.cpp
+++ b/content/html/content/src/nsHTMLAreaElement.cpp
@@ -87,18 +87,16 @@ public:
   NS_IMETHOD LinkAdded() { return NS_OK; }
   NS_IMETHOD LinkRemoved() { return NS_OK; }
 
   virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
   virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
   virtual PRBool IsLink(nsIURI** aURI) const;
   virtual void GetLinkTarget(nsAString& aTarget);
 
-  virtual void SetFocus(nsPresContext* aPresContext);
-
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               PRBool aCompileEventHandlers);
   virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
                               PRBool aNullParent = PR_TRUE);
   nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                    const nsAString& aValue, PRBool aNotify)
   {
@@ -195,31 +193,16 @@ void
 nsHTMLAreaElement::GetLinkTarget(nsAString& aTarget)
 {
   GetAttr(kNameSpaceID_None, nsGkAtoms::target, aTarget);
   if (aTarget.IsEmpty()) {
     GetBaseTarget(aTarget);
   }
 }
 
-void
-nsHTMLAreaElement::SetFocus(nsPresContext* aPresContext)
-{
-  if (!aPresContext ||
-      !aPresContext->EventStateManager()->SetContentState(this, 
-                                                          NS_EVENT_STATE_FOCUS)) {
-    return;
-  }
-  nsCOMPtr<nsIPresShell> presShell = aPresContext->GetPresShell();
-  if (presShell) {
-    presShell->ScrollContentIntoView(this, NS_PRESSHELL_SCROLL_ANYWHERE,
-                                     NS_PRESSHELL_SCROLL_ANYWHERE);
-  }
-}
-
 nsresult
 nsHTMLAreaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               PRBool aCompileEventHandlers)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
                                                  aBindingParent,
                                                  aCompileEventHandlers);
--- a/content/html/content/src/nsHTMLButtonElement.cpp
+++ b/content/html/content/src/nsHTMLButtonElement.cpp
@@ -55,16 +55,17 @@
 #include "nsIDOMNSEvent.h"
 #include "nsIDocument.h"
 #include "nsGUIEvent.h"
 #include "nsUnicharUtils.h"
 #include "nsLayoutUtils.h"
 #include "nsEventDispatcher.h"
 #include "nsPresState.h"
 #include "nsLayoutErrors.h"
+#include "nsFocusManager.h"
 
 #define NS_IN_SUBMIT_CLICK      (1 << 0)
 #define NS_OUTER_ACTIVATE_EVENT (1 << 1)
 
 class nsHTMLButtonElement : public nsGenericHTMLFormElement,
                             public nsIDOMHTMLButtonElement,
                             public nsIDOMNSHTMLButtonElement
 {
@@ -105,17 +106,16 @@ public:
 
   /**
    * Called when an attribute is about to be changed
    */
   virtual nsresult BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                                  const nsAString* aValue, PRBool aNotify);
   
   // nsIContent overrides...
-  virtual void SetFocus(nsPresContext* aPresContext);
   virtual PRBool IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex);
   virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult);
   virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
   virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
 
@@ -188,31 +188,23 @@ NS_IMPL_BOOL_ATTR(nsHTMLButtonElement, D
 NS_IMPL_STRING_ATTR(nsHTMLButtonElement, Name, name)
 NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLButtonElement, TabIndex, tabindex, 0)
 NS_IMPL_STRING_ATTR(nsHTMLButtonElement, Value, value)
 NS_IMPL_STRING_ATTR_DEFAULT_VALUE(nsHTMLButtonElement, Type, type, "submit")
 
 NS_IMETHODIMP
 nsHTMLButtonElement::Blur()
 {
-  if (ShouldBlur(this)) {
-    SetElementFocus(PR_FALSE);
-  }
-
-  return NS_OK;
+  return nsGenericHTMLElement::Blur();
 }
 
 NS_IMETHODIMP
 nsHTMLButtonElement::Focus()
 {
-  if (ShouldFocus(this)) {
-    SetElementFocus(PR_TRUE);
-  }
-
-  return NS_OK;
+  return nsGenericHTMLElement::Focus();
 }
 
 NS_IMETHODIMP
 nsHTMLButtonElement::Click()
 {
   if (mHandlingClick)
     return NS_OK;
 
@@ -249,27 +241,21 @@ nsHTMLButtonElement::IsHTMLFocusable(PRB
 {
   if (nsGenericHTMLElement::IsHTMLFocusable(aIsFocusable, aTabIndex)) {
     return PR_TRUE;
   }
   if (aTabIndex && (sTabFocusModel & eTabFocus_formElementsMask) == 0) {
     *aTabIndex = -1;
   }
 
-  *aIsFocusable = PR_TRUE;
+  *aIsFocusable = !HasAttr(kNameSpaceID_None, nsGkAtoms::disabled);
 
   return PR_FALSE;
 }
 
-void
-nsHTMLButtonElement::SetFocus(nsPresContext* aPresContext)
-{
-  DoSetFocus(aPresContext);
-}
-
 static const nsAttrValue::EnumTable kButtonTypeTable[] = {
   { "button", NS_FORM_BUTTON_BUTTON },
   { "reset", NS_FORM_BUTTON_RESET },
   { "submit", NS_FORM_BUTTON_SUBMIT },
   { 0 }
 };
 
 PRBool
@@ -399,17 +385,21 @@ nsHTMLButtonElement::PostHandleEvent(nsE
         break;// NS_KEY_PRESS
 
       case NS_MOUSE_BUTTON_DOWN:
         {
           if (aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT) {
             if (static_cast<nsMouseEvent*>(aVisitor.mEvent)->button ==
                   nsMouseEvent::eLeftButton) {
               aVisitor.mPresContext->EventStateManager()->
-                SetContentState(this, NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS);
+                SetContentState(this, NS_EVENT_STATE_ACTIVE);
+              nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+              if (fm)
+                fm->SetFocus(this, nsIFocusManager::FLAG_BYMOUSE |
+                                   nsIFocusManager::FLAG_NOSCROLL);
               aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
             } else if (static_cast<nsMouseEvent*>(aVisitor.mEvent)->button ==
                          nsMouseEvent::eMiddleButton ||
                        static_cast<nsMouseEvent*>(aVisitor.mEvent)->button ==
                          nsMouseEvent::eRightButton) {
               // cancel all of these events for buttons
               //XXXsmaug What to do with these events? Why these should be cancelled?
               if (aVisitor.mDOMEvent) {
--- a/content/html/content/src/nsHTMLInputElement.cpp
+++ b/content/html/content/src/nsHTMLInputElement.cpp
@@ -41,16 +41,17 @@
 #include "nsITextControlElement.h"
 #include "nsIFileControlElement.h"
 #include "nsIDOMNSEditableElement.h"
 #include "nsIRadioControlElement.h"
 #include "nsIRadioVisitor.h"
 #include "nsIPhonetic.h"
 
 #include "nsIControllers.h"
+#include "nsFocusManager.h"
 #include "nsPIDOMWindow.h"
 #include "nsContentCID.h"
 #include "nsIComponentManager.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsIDOMEventTarget.h"
 #include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
@@ -81,16 +82,18 @@
 #include "nsIDOMNodeList.h"
 #include "nsIDOMHTMLCollection.h"
 #include "nsICheckboxControlFrame.h"
 #include "nsLinebreakConverter.h" //to strip out carriage returns
 #include "nsReadableUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsEventDispatcher.h"
 #include "nsLayoutUtils.h"
+#include "nsWidgetsCID.h"
+#include "nsILookAndFeel.h"
 
 #include "nsIDOMMutationEvent.h"
 #include "nsIDOMEventTarget.h"
 #include "nsMutationEvent.h"
 #include "nsIEventListenerManager.h"
 
 #include "nsRuleData.h"
 
@@ -111,16 +114,18 @@
 #include "nsImageLoadingContent.h"
 #include "nsIDOMWindowInternal.h"
 
 #include "mozAutoDocUpdate.h"
 
 // XXX align=left, hspace, vspace, border? other nav4 attrs
 
 static NS_DEFINE_CID(kXULControllersCID,  NS_XULCONTROLLERS_CID);
+static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
+
 //
 // Accessors for mBitField
 //
 #define BF_DISABLED_CHANGED 0
 #define BF_HANDLING_CLICK 1
 #define BF_VALUE_CHANGED 2
 #define BF_CHECKED_CHANGED 3
 #define BF_CHECKED 4
@@ -143,16 +148,20 @@ static NS_DEFINE_CID(kXULControllersCID,
 #define NS_NO_CONTENT_DISPATCH    (1 << 11)
 #define NS_ORIGINAL_INDETERMINATE_VALUE (1 << 12)
 #define NS_CONTROL_TYPE(bits)  ((bits) & ~( \
   NS_OUTER_ACTIVATE_EVENT | NS_ORIGINAL_CHECKED_VALUE | NS_NO_CONTENT_DISPATCH | \
   NS_ORIGINAL_INDETERMINATE_VALUE))
 
 static const char kWhitespace[] = "\n\r\t\b";
 
+// whether textfields should be selected once focused:
+//  -1: no, 1: yes, 0: uninitialized
+static PRInt32 gSelectTextFieldOnFocus;
+
 #define NS_INPUT_ELEMENT_STATE_IID                 \
 { /* dc3b3d14-23e2-4479-b513-7b369343e3a0 */       \
   0xdc3b3d14,                                      \
   0x23e2,                                          \
   0x4479,                                          \
   {0xb5, 0x13, 0x7b, 0x36, 0x93, 0x43, 0xe3, 0xa0} \
 }
 
@@ -255,17 +264,16 @@ public:
   NS_IMETHOD Reset();
   NS_IMETHOD SubmitNamesValues(nsIFormSubmission* aFormSubmission,
                                nsIContent* aSubmitElement);
   NS_IMETHOD SaveState();
   virtual PRBool RestoreState(nsPresState* aState);
   virtual PRBool AllowDrop();
 
   // nsIContent
-  virtual void SetFocus(nsPresContext* aPresContext);
   virtual PRBool IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex);
 
   virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult);
   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                               PRInt32 aModType) const;
@@ -275,17 +283,17 @@ public:
   virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
   virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               PRBool aCompileEventHandlers);
   virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
                               PRBool aNullParent = PR_TRUE);
-  
+
   virtual void DoneCreatingElement();
 
   virtual PRInt32 IntrinsicState() const;
 
   // nsITextControlElement
   NS_IMETHOD TakeTextFrameValue(const nsAString& aValue);
   NS_IMETHOD SetValueChanged(PRBool aValueChanged);
   
@@ -343,16 +351,21 @@ protected:
   virtual nsresult BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                                  const nsAString* aValue, PRBool aNotify);
   /**
    * Called when an attribute has just been changed
    */
   virtual nsresult AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                                 const nsAString* aValue, PRBool aNotify);
 
+  /**
+   * Dispatch a select event. Returns true if the event was not cancelled.
+   */
+  PRBool DispatchSelectEvent(nsPresContext* aPresContext);
+
   void SelectAll(nsPresContext* aPresContext);
   PRBool IsImage() const
   {
     return AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
                        nsGkAtoms::image, eIgnoreCase);
   }
 
   /**
@@ -1330,37 +1343,46 @@ nsHTMLInputElement::FireOnChange()
   nsCOMPtr<nsPresContext> presContext = GetPresContext();
   nsEventDispatcher::Dispatch(static_cast<nsIContent*>(this), presContext,
                               &event, nsnull, &status);
 }
 
 NS_IMETHODIMP
 nsHTMLInputElement::Blur()
 {
-  if (ShouldFocus(this)) {
-    SetElementFocus(PR_FALSE);
-  }
-
-  return NS_OK;
+  return nsGenericHTMLElement::Blur();
 }
 
 NS_IMETHODIMP
 nsHTMLInputElement::Focus()
 {
-  if (ShouldFocus(this)) {
-    SetElementFocus(PR_TRUE);
+  if (mType == NS_FORM_INPUT_FILE) {
+    // for file inputs, focus the button instead
+    nsIFrame* frame = GetPrimaryFrame();
+    if (frame) {
+      nsIFrame* childFrame = frame->GetFirstChild(nsnull);
+      while (childFrame) {
+        // see if the child is a button control
+        nsCOMPtr<nsIFormControl> formCtrl =
+          do_QueryInterface(childFrame->GetContent());
+        if (formCtrl && formCtrl->GetType() == NS_FORM_INPUT_BUTTON) {
+          nsCOMPtr<nsIDOMElement> element(do_QueryInterface(formCtrl));
+          nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+          if (fm && element)
+            fm->SetFocus(element, 0);
+        }
+
+        childFrame = childFrame->GetNextSibling();
+      }
+    }
+
+    return NS_OK;
   }
 
-  return NS_OK;
-}
-
-void
-nsHTMLInputElement::SetFocus(nsPresContext* aPresContext)
-{
-  DoSetFocus(aPresContext);
+  return nsGenericHTMLElement::Focus();
 }
 
 NS_IMETHODIMP
 nsHTMLInputElement::Select()
 {
   if (mType != NS_FORM_INPUT_PASSWORD && mType != NS_FORM_INPUT_TEXT) {
     return NS_OK;
   }
@@ -1368,69 +1390,61 @@ nsHTMLInputElement::Select()
   // XXX Bug?  We have to give the input focus before contents can be
   // selected
 
   FocusTristate state = FocusState();
   if (state == eUnfocusable) {
     return NS_OK;
   }
 
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+
   nsCOMPtr<nsPresContext> presContext = GetPresContext();
   if (state == eInactiveWindow) {
+    if (fm)
+      fm->SetFocus(this, nsIFocusManager::FLAG_NOSCROLL);
     SelectAll(presContext);
     return NS_OK;
   }
 
-  // Just like SetFocus() but without the ScrollIntoView()!
-  nsEventStatus status = nsEventStatus_eIgnore;
-    
-  //If already handling select event, don't dispatch a second.
-  if (!GET_BOOLBIT(mBitField, BF_HANDLING_SELECT_EVENT)) {
-    nsEvent event(nsContentUtils::IsCallerChrome(), NS_FORM_SELECTED);
-
-    SET_BOOLBIT(mBitField, BF_HANDLING_SELECT_EVENT, PR_TRUE);
-    nsEventDispatcher::Dispatch(static_cast<nsIContent*>(this),
-                                presContext, &event, nsnull, &status);
-    SET_BOOLBIT(mBitField, BF_HANDLING_SELECT_EVENT, PR_FALSE);
-  }
-
-  // If the DOM event was not canceled (e.g. by a JS event handler
-  // returning false)
-  if (status == nsEventStatus_eIgnore) {
-    PRBool shouldFocus = ShouldFocus(this);
-
-    if (presContext && shouldFocus) {
-      nsIEventStateManager *esm = presContext->EventStateManager();
-      // XXX Fix for bug 135345 - ESM currently does not check to see if we
-      // have focus before attempting to set focus again and may cause
-      // infinite recursion.  For now check if we have focus and do not set
-      // focus again if already focused.
-      PRInt32 currentState;
-      esm->GetContentState(this, currentState);
-      if (!(currentState & NS_EVENT_STATE_FOCUS) &&
-          !esm->SetContentState(this, NS_EVENT_STATE_FOCUS)) {
-        return NS_OK; // We ended up unfocused, e.g. due to a DOM event handler.
-      }
-    }
-
-    nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
-
-    if (formControlFrame) {
-      if (shouldFocus) {
-        formControlFrame->SetFocus(PR_TRUE, PR_TRUE);
-      }
-
+  if (DispatchSelectEvent(presContext) && fm) {
+    fm->SetFocus(this, nsIFocusManager::FLAG_NOSCROLL);
+
+    // ensure that the element is actually focused
+    nsCOMPtr<nsIDOMElement> focusedElement;
+    fm->GetFocusedElement(getter_AddRefs(focusedElement));
+    if (SameCOMIdentity(static_cast<nsIDOMNode *>(this), focusedElement)) {
       // Now Select all the text!
       SelectAll(presContext);
     }
   }
 
   return NS_OK;
 }
 
+PRBool
+nsHTMLInputElement::DispatchSelectEvent(nsPresContext* aPresContext)
+{
+  nsEventStatus status = nsEventStatus_eIgnore;
+
+  // If already handling select event, don't dispatch a second.
+  if (!GET_BOOLBIT(mBitField, BF_HANDLING_SELECT_EVENT)) {
+    nsEvent event(nsContentUtils::IsCallerChrome(), NS_FORM_SELECTED);
+
+    SET_BOOLBIT(mBitField, BF_HANDLING_SELECT_EVENT, PR_TRUE);
+    nsEventDispatcher::Dispatch(static_cast<nsIContent*>(this),
+                                aPresContext, &event, nsnull, &status);
+    SET_BOOLBIT(mBitField, BF_HANDLING_SELECT_EVENT, PR_FALSE);
+  }
+
+  // If the DOM event was not canceled (e.g. by a JS event handler
+  // returning false)
+  return (status == nsEventStatus_eIgnore);
+}
+    
 void
 nsHTMLInputElement::SelectAll(nsPresContext* aPresContext)
 {
   nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
 
   if (formControlFrame) {
     formControlFrame->SetFormProperty(nsGkAtoms::select, EmptyString());
   }
@@ -1633,17 +1647,36 @@ nsHTMLInputElement::PreHandleEvent(nsEve
     if (primaryFrame) {
       nsITextControlFrame* textFrame = do_QueryFrame(primaryFrame);
       if (textFrame) {
         textFrame->CheckFireOnChange();
       }
     }
   }
 
-  return nsGenericHTMLElement::PreHandleEvent(aVisitor);
+  return nsGenericHTMLFormElement::PreHandleEvent(aVisitor);
+}
+
+static PRBool
+SelectTextFieldOnFocus()
+{
+  if (!gSelectTextFieldOnFocus) {
+    nsCOMPtr<nsILookAndFeel> lookNFeel(do_GetService(kLookAndFeelCID));
+    if (lookNFeel) {
+      PRInt32 selectTextfieldsOnKeyFocus = -1;
+      lookNFeel->GetMetric(nsILookAndFeel::eMetric_SelectTextfieldsOnKeyFocus,
+                           selectTextfieldsOnKeyFocus);
+      gSelectTextFieldOnFocus = selectTextfieldsOnKeyFocus != 0 ? 1 : -1;
+    }
+    else {
+      gSelectTextFieldOnFocus = -1;
+    }
+  }
+
+  return gSelectTextFieldOnFocus == 1;
 }
 
 nsresult
 nsHTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
 {
   if (!aVisitor.mPresContext) {
     return NS_OK;
   }
@@ -1742,25 +1775,34 @@ nsHTMLInputElement::PostHandleEvent(nsEv
   }
 
   if (NS_SUCCEEDED(rv)) {
     if (nsEventStatus_eIgnore == aVisitor.mEventStatus) {
       switch (aVisitor.mEvent->message) {
 
         case NS_FOCUS_CONTENT:
         {
-          // Check to see if focus has bubbled up from a form control's
-          // child textfield or button.  If that's the case, don't focus
-          // this parent file control -- leave focus on the child.
-          nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE);
-          if (formControlFrame && ShouldFocus(this) &&
-              aVisitor.mEvent->originalTarget == static_cast<nsINode*>(this))
-            formControlFrame->SetFocus(PR_TRUE, PR_TRUE);
+          nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+          if (fm && (mType == NS_FORM_INPUT_TEXT || mType == NS_FORM_INPUT_PASSWORD) &&
+              SelectTextFieldOnFocus()) {
+            // select the text if the field was focused by the keyboard.
+            nsIDocument* document = GetCurrentDoc();
+            if (document) {
+              PRUint32 lastFocusMethod;
+              fm->GetLastFocusMethod(document->GetWindow(), &lastFocusMethod);
+              if (lastFocusMethod & nsIFocusManager::FLAG_BYKEY) {
+                nsCOMPtr<nsPresContext> presContext = GetPresContext();
+                if (DispatchSelectEvent(presContext)) {
+                  SelectAll(presContext);
+                }
+              }
+            }
+          }
+          break;
         }
-        break; // NS_FOCUS_CONTENT
 
         case NS_KEY_PRESS:
         case NS_KEY_UP:
         {
           // For backwards compat, trigger checks/radios/buttons with
           // space or enter (bug 25300)
           nsKeyEvent * keyEvent = (nsKeyEvent *)aVisitor.mEvent;
 
@@ -2950,23 +2992,35 @@ nsHTMLInputElement::WillRemoveFromRadioG
 
 PRBool
 nsHTMLInputElement::IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex)
 {
   if (nsGenericHTMLElement::IsHTMLFocusable(aIsFocusable, aTabIndex)) {
     return PR_TRUE;
   }
 
+  if (HasAttr(kNameSpaceID_None, nsGkAtoms::disabled)) {
+    *aIsFocusable = PR_FALSE;
+    return PR_TRUE;
+  }
+
   if (mType == NS_FORM_INPUT_TEXT || mType == NS_FORM_INPUT_PASSWORD) {
     *aIsFocusable = PR_TRUE;
     return PR_FALSE;
   }
 
-  if (mType == NS_FORM_INPUT_HIDDEN || mType == NS_FORM_INPUT_FILE) {
-    // Sub controls of file input are tabbable, not the file input itself.
+  if (mType == NS_FORM_INPUT_FILE) {
+    if (aTabIndex) {
+      *aTabIndex = -1;
+    }
+    *aIsFocusable = PR_TRUE;
+    return PR_TRUE;
+  }
+
+  if (mType == NS_FORM_INPUT_HIDDEN) {
     if (aTabIndex) {
       *aTabIndex = -1;
     }
     *aIsFocusable = PR_FALSE;
     return PR_FALSE;
   }
 
   if (!aTabIndex) {
--- a/content/html/content/src/nsHTMLLabelElement.cpp
+++ b/content/html/content/src/nsHTMLLabelElement.cpp
@@ -46,16 +46,17 @@
 #include "nsIForm.h"
 #include "nsIDOMDocument.h"
 #include "nsIDocument.h"
 #include "nsIPresShell.h"
 #include "nsGUIEvent.h"
 #include "nsIEventStateManager.h"
 #include "nsEventDispatcher.h"
 #include "nsPIDOMWindow.h"
+#include "nsFocusManager.h"
 
 class nsHTMLLabelElement : public nsGenericHTMLFormElement,
                            public nsIDOMHTMLLabelElement
 {
 public:
   nsHTMLLabelElement(nsINodeInfo *aNodeInfo);
   virtual ~nsHTMLLabelElement();
 
@@ -75,26 +76,27 @@ public:
   NS_DECL_NSIDOMHTMLLABELELEMENT
 
   // nsIFormControl
   NS_IMETHOD_(PRInt32) GetType() const { return NS_FORM_LABEL; }
   NS_IMETHOD Reset();
   NS_IMETHOD SubmitNamesValues(nsIFormSubmission* aFormSubmission,
                                nsIContent* aSubmitElement);
 
+  NS_IMETHOD Focus();
+
   // nsIContent
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               PRBool aCompileEventHandlers);
   virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
                               PRBool aNullParent = PR_TRUE);
 
   virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
 
-  virtual void SetFocus(nsPresContext* aContext);
   nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                    const nsAString& aValue, PRBool aNotify)
   {
     return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
   }
   virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                            nsIAtom* aPrefix, const nsAString& aValue,
                            PRBool aNotify);
@@ -105,29 +107,27 @@ public:
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
 protected:
   already_AddRefed<nsIContent> GetForContent();
   already_AddRefed<nsIContent> GetFirstFormControl(nsIContent *current);
 
   // XXX It would be nice if we could use an event flag instead.
   PRPackedBool mHandlingEvent;
-  PRPackedBool mInSetFocus;
 };
 
 // construction, destruction
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Label)
 
 
 nsHTMLLabelElement::nsHTMLLabelElement(nsINodeInfo *aNodeInfo)
   : nsGenericHTMLFormElement(aNodeInfo)
   , mHandlingEvent(PR_FALSE)
-  , mInSetFocus(PR_FALSE)
 {
 }
 
 nsHTMLLabelElement::~nsHTMLLabelElement()
 {
 }
 
 // nsISupports 
@@ -156,16 +156,31 @@ nsHTMLLabelElement::GetForm(nsIDOMHTMLFo
 {
   return nsGenericHTMLFormElement::GetForm(aForm);
 }
 
 
 NS_IMPL_STRING_ATTR(nsHTMLLabelElement, AccessKey, accesskey)
 NS_IMPL_STRING_ATTR(nsHTMLLabelElement, HtmlFor, _for)
 
+NS_IMETHODIMP
+nsHTMLLabelElement::Focus()
+{
+  // retarget the focus method at the for content
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+  if (fm) {
+    nsCOMPtr<nsIContent> content = GetForContent();
+    nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(content);
+    if (elem)
+      fm->SetFocus(elem, 0);
+  }
+
+  return NS_OK;
+}
+
 nsresult
 nsHTMLLabelElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                                nsIContent* aBindingParent,
                                PRBool aCompileEventHandlers)
 {
   nsresult rv = nsGenericHTMLFormElement::BindToTree(aDocument, aParent,
                                                      aBindingParent,
                                                      aCompileEventHandlers);
@@ -217,17 +232,16 @@ DestroyMouseDownPoint(void *    /*aObjec
   delete pt;
 }
 
 nsresult
 nsHTMLLabelElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
 {
   if (mHandlingEvent ||
       (!NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent) &&
-       aVisitor.mEvent->message != NS_FOCUS_CONTENT &&
        aVisitor.mEvent->message != NS_MOUSE_BUTTON_DOWN) ||
       aVisitor.mEventStatus == nsEventStatus_eConsumeNoDefault ||
       !aVisitor.mPresContext) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIContent> content = GetForContent();
   if (content && !EventTargetIn(aVisitor.mEvent, content, this)) {
@@ -271,20 +285,24 @@ nsHTMLLabelElement::PostHandleEvent(nsEv
           // have a kbd modifier (which adjusts a selection), or if it's a
           // double click (we already forwarded the first click event).
           if (dragSelect || event->clickCount > 1 ||
               event->isShift || event->isControl || event->isAlt ||
               event->isMeta) {
             break;
           }
 
-          if (ShouldFocus(this)) {
-            // Focus the for content.
-            aVisitor.mPresContext->EventStateManager()->
-              ChangeFocusWith(content, nsIEventStateManager::eEventFocusedByKey);
+          nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+          if (fm) {
+            // Use FLAG_BYKEY here so that the label is scrolled to. Also,
+            // within nsHTMLInputElement::PostHandleEvent, inputs will be
+            // selected only when focused via a key and we want to select
+            // the text on label clicks as well.
+            nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(content);
+            fm->SetFocus(elem, nsIFocusManager::FLAG_BYKEY);
           }
 
           // Dispatch a new click event to |content|
           //    (For compatibility with IE, we do only left click.  If
           //    we wanted to interpret the HTML spec very narrowly, we
           //    would do nothing.  If we wanted to do something
           //    sensible, we might send more events through like
           //    this.)  See bug 7554, bug 49897, and bug 96813.
@@ -292,50 +310,22 @@ nsHTMLLabelElement::PostHandleEvent(nsEv
           // Ok to use aVisitor.mEvent as parameter because DispatchClickEvent
           // will actually create a new event.
           DispatchClickEvent(aVisitor.mPresContext,
                              static_cast<nsInputEvent*>(aVisitor.mEvent),
                              content, PR_FALSE, &status);
           // Do we care about the status this returned?  I don't think we do...
         }
         break;
-      case NS_FOCUS_CONTENT:
-        // Since we don't have '-moz-user-focus: normal', the only time
-        // the event type will be NS_FOCUS_CONTENT will be when the accesskey
-        // is activated.  We've already redirected the |SetFocus| call in that
-        // case.
-        // Since focus doesn't bubble, this is basically the second part
-        // of redirecting |SetFocus|.
-        {
-          nsEvent event(NS_IS_TRUSTED_EVENT(aVisitor.mEvent), NS_FOCUS_CONTENT);
-          event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
-          nsEventStatus status = aVisitor.mEventStatus;
-          DispatchEvent(aVisitor.mPresContext, &event,
-                        content, PR_TRUE, &status);
-          // Do we care about the status this returned?  I don't think we do...
-        }
-        break;
     }
     mHandlingEvent = PR_FALSE;
   }
   return NS_OK;
 }
 
-void
-nsHTMLLabelElement::SetFocus(nsPresContext* aContext)
-{
-  if (mInSetFocus)
-    return;
-  mInSetFocus = PR_TRUE;
-  nsCOMPtr<nsIContent> content = GetForContent();
-  if (content)
-    content->SetFocus(aContext);
-  mInSetFocus = PR_FALSE;
-}
-
 nsresult
 nsHTMLLabelElement::Reset()
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLLabelElement::SubmitNamesValues(nsIFormSubmission* aFormSubmission,
--- a/content/html/content/src/nsHTMLLegendElement.cpp
+++ b/content/html/content/src/nsHTMLLegendElement.cpp
@@ -40,20 +40,20 @@
 #include "nsIDOMEventTarget.h"
 #include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsPresContext.h"
 #include "nsIForm.h"
 #include "nsIFormControl.h"
 #include "nsIEventStateManager.h"
-#include "nsIFocusController.h"
 #include "nsIDocument.h"
 #include "nsPIDOMWindow.h"
-
+#include "nsFocusManager.h"
+#include "nsIFrame.h"
 
 class nsHTMLLegendElement : public nsGenericHTMLFormElement,
                             public nsIDOMHTMLLegendElement
 {
 public:
   nsHTMLLegendElement(nsINodeInfo *aNodeInfo);
   virtual ~nsHTMLLegendElement();
 
@@ -73,23 +73,27 @@ public:
   NS_DECL_NSIDOMHTMLLEGENDELEMENT
 
   // nsIFormControl
   NS_IMETHOD_(PRInt32) GetType() const { return NS_FORM_LEGEND; }
   NS_IMETHOD Reset();
   NS_IMETHOD SubmitNamesValues(nsIFormSubmission* aFormSubmission,
                                nsIContent* aSubmitElement);
 
+  NS_IMETHODIMP Focus();
+
+  virtual void PerformAccesskey(PRBool aKeyCausesActivation,
+                                PRBool aIsTrustedEvent);
+
   // nsIContent
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               PRBool aCompileEventHandlers);
   virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
                               PRBool aNullParent = PR_TRUE);
-  virtual void SetFocus(nsPresContext* aPresContext);
   virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult);
   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                               PRInt32 aModType) const;
   nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                    const nsAString& aValue, PRBool aNotify)
@@ -98,28 +102,24 @@ public:
   }
   virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                            nsIAtom* aPrefix, const nsAString& aValue,
                            PRBool aNotify);
   virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
                              PRBool aNotify);
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
-
-protected:
-  PRPackedBool mInSetFocus;
 };
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Legend)
 
 
 nsHTMLLegendElement::nsHTMLLegendElement(nsINodeInfo *aNodeInfo)
   : nsGenericHTMLFormElement(aNodeInfo)
-  , mInSetFocus(PR_FALSE)
 {
 }
 
 nsHTMLLegendElement::~nsHTMLLegendElement()
 {
 }
 
 
@@ -248,42 +248,44 @@ nsHTMLLegendElement::UnbindFromTree(PRBo
 {
   if (IsInDoc()) {
     RegUnRegAccessKey(PR_FALSE);
   }
 
   nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent);
 }
 
-void
-nsHTMLLegendElement::SetFocus(nsPresContext* aPresContext)
+NS_IMETHODIMP
+nsHTMLLegendElement::Focus()
 {
-  nsIDocument *document = GetCurrentDoc();
-  if (!aPresContext || !document || mInSetFocus) {
-    return;
-  }
+  nsIFrame* frame = GetPrimaryFrame();
+  if (!frame)
+    return NS_OK;
+
+  PRInt32 tabIndex;
+  if (frame->IsFocusable(&tabIndex))
+    return nsGenericHTMLElement::Focus();
 
-  mInSetFocus = PR_TRUE;
-  if (IsFocusable()) {
-    nsGenericHTMLFormElement::SetFocus(aPresContext);
-  } else {
-    // If the legend isn't focusable (no tabindex) we focus whatever is
-    // focusable following the legend instead, bug 81481.
-    nsCOMPtr<nsPIDOMWindow> ourWindow = document->GetWindow();
-    if (ourWindow) {
-      nsIFocusController* focusController =
-        ourWindow->GetRootFocusController();
-      nsCOMPtr<nsIDOMElement> domElement =
-        do_QueryInterface(static_cast<nsIContent *>(this));
-      if (focusController && domElement) {
-        focusController->MoveFocus(PR_TRUE, domElement);
-      }
-    }
-  }
-  mInSetFocus = PR_FALSE;
+  // If the legend isn't focusable, focus whatever is focusable following
+  // the legend instead, bug 81481.
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+  if (!fm)
+    return NS_OK;
+
+  nsCOMPtr<nsIDOMElement> result;
+  return fm->MoveFocus(nsnull, this, nsIFocusManager::MOVEFOCUS_FORWARD, 0,
+                       getter_AddRefs(result));
+}
+
+void
+nsHTMLLegendElement::PerformAccesskey(PRBool aKeyCausesActivation,
+                                      PRBool aIsTrustedEvent)
+{
+  // just use the same behaviour as the focus method
+  Focus();
 }
 
 NS_IMETHODIMP
 nsHTMLLegendElement::SubmitNamesValues(nsIFormSubmission* aFormSubmission,
                                        nsIContent* aSubmitElement)
 {
   return NS_OK;
 }
--- a/content/html/content/src/nsHTMLSelectElement.cpp
+++ b/content/html/content/src/nsHTMLSelectElement.cpp
@@ -1203,49 +1203,35 @@ NS_IMPL_BOOL_ATTR(nsHTMLSelectElement, D
 NS_IMPL_BOOL_ATTR(nsHTMLSelectElement, Multiple, multiple)
 NS_IMPL_STRING_ATTR(nsHTMLSelectElement, Name, name)
 NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLSelectElement, Size, size, 0)
 NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLSelectElement, TabIndex, tabindex, 0)
 
 NS_IMETHODIMP
 nsHTMLSelectElement::Blur()
 {
-  if (ShouldBlur(this)) {
-    SetElementFocus(PR_FALSE);
-  }
-
-  return NS_OK;
+  return nsGenericHTMLElement::Blur();
 }
 
 NS_IMETHODIMP
 nsHTMLSelectElement::Focus()
 {
-  if (ShouldFocus(this)) {
-    SetElementFocus(PR_TRUE);
-  }
-
-  return NS_OK;
-}
-
-void
-nsHTMLSelectElement::SetFocus(nsPresContext* aPresContext)
-{
-  DoSetFocus(aPresContext);
+  return nsGenericHTMLElement::Focus();
 }
 
 PRBool
 nsHTMLSelectElement::IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex)
 {
   if (nsGenericHTMLElement::IsHTMLFocusable(aIsFocusable, aTabIndex)) {
     return PR_TRUE;
   }
   if (aTabIndex && (sTabFocusModel & eTabFocus_formElementsMask) == 0) {
     *aTabIndex = -1;
   }
-  *aIsFocusable = PR_TRUE;
+  *aIsFocusable = !HasAttr(kNameSpaceID_None, nsGkAtoms::disabled);
   return PR_FALSE;
 }
 
 NS_IMETHODIMP
 nsHTMLSelectElement::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
 {
   return mOptions->Item(aIndex, aReturn);
 }
@@ -1443,27 +1429,17 @@ nsHTMLSelectElement::PreHandleEvent(nsEv
     const nsStyleUserInterface* uiStyle = formFrame->GetStyleUserInterface();
 
     if (uiStyle->mUserInput == NS_STYLE_USER_INPUT_NONE ||
         uiStyle->mUserInput == NS_STYLE_USER_INPUT_DISABLED) {
       return NS_OK;
     }
   }
 
-  // Must notify the frame that the blur event occurred
-  // NOTE: At this point EventStateManager has not yet set the
-  // new content as having focus so this content is still considered
-  // the focused element. So the ComboboxControlFrame tracks the focus
-  // at a class level (Bug 32920)
-  if (nsEventStatus_eIgnore == aVisitor.mEventStatus &&
-      (aVisitor.mEvent->message == NS_BLUR_CONTENT) && formControlFrame) {
-    formControlFrame->SetFocus(PR_FALSE, PR_TRUE);
-  }
-
-  return nsGenericHTMLElement::PreHandleEvent(aVisitor);
+  return nsGenericHTMLFormElement::PreHandleEvent(aVisitor);
 }
 
 // nsIFormControl
 
 NS_IMETHODIMP
 nsHTMLSelectElement::SaveState()
 {
   nsRefPtr<nsSelectState> state = new nsSelectState();
--- a/content/html/content/src/nsHTMLSelectElement.h
+++ b/content/html/content/src/nsHTMLSelectElement.h
@@ -263,17 +263,16 @@ public:
   NS_DECL_NSIDOMHTMLSELECTELEMENT
 
   // nsIDOMNSHTMLSelectElement
   NS_DECL_NSIDOMNSHTMLSELECTELEMENT
 
   // nsIContent
   virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
 
-  virtual void SetFocus(nsPresContext* aPresContext);
   virtual PRBool IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex);
   virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
                                  PRBool aNotify);
   virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
 
   // Overriden nsIFormControl methods
   NS_IMETHOD_(PRInt32) GetType() const { return NS_FORM_SELECT; }
   NS_IMETHOD Reset();
--- a/content/html/content/src/nsHTMLTextAreaElement.cpp
+++ b/content/html/content/src/nsHTMLTextAreaElement.cpp
@@ -36,16 +36,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #include "nsIDOMHTMLTextAreaElement.h"
 #include "nsIDOMNSHTMLTextAreaElement.h"
 #include "nsITextControlElement.h"
 #include "nsIDOMNSEditableElement.h"
 #include "nsIControllers.h"
+#include "nsFocusManager.h"
 #include "nsPIDOMWindow.h"
 #include "nsContentCID.h"
 #include "nsCOMPtr.h"
 #include "nsIComponentManager.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsIFormControl.h"
 #include "nsIForm.h"
 #include "nsIFormSubmission.h"
@@ -137,17 +138,17 @@ public:
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                               PRInt32 aModType) const;
   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
   virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
   virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
 
-  virtual void SetFocus(nsPresContext* aPresContext);
+  virtual PRBool IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex);
 
   virtual nsresult DoneAddingChildren(PRBool aHaveNotified);
   virtual PRBool IsDoneAddingChildren();
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   /**
    * Called when an attribute is about to be changed
@@ -283,104 +284,95 @@ nsHTMLTextAreaElement::GetForm(nsIDOMHTM
 }
 
 
 // nsIContent
 
 NS_IMETHODIMP
 nsHTMLTextAreaElement::Blur()
 {
-  if (ShouldBlur(this)) {
-    SetElementFocus(PR_FALSE);
-  }
-
-  return NS_OK;
+  return nsGenericHTMLElement::Blur();
 }
 
 NS_IMETHODIMP
-nsHTMLTextAreaElement::Focus() 
+nsHTMLTextAreaElement::Focus()
 {
-  if (ShouldFocus(this)) {
-    SetElementFocus(PR_TRUE);
-  }
-
-  return NS_OK;
-}
-
-void
-nsHTMLTextAreaElement::SetFocus(nsPresContext* aPresContext)
-{
-  DoSetFocus(aPresContext);
+  return nsGenericHTMLElement::Focus();
 }
 
 NS_IMETHODIMP
 nsHTMLTextAreaElement::Select()
 {
-  nsresult rv = NS_OK;
-
   // XXX Bug?  We have to give the input focus before contents can be
   // selected
 
   FocusTristate state = FocusState();
   if (state == eUnfocusable) {
     return NS_OK;
   }
 
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+
   nsCOMPtr<nsPresContext> presContext = GetPresContext();
   if (state == eInactiveWindow) {
+    if (fm)
+      fm->SetFocus(this, nsIFocusManager::FLAG_NOSCROLL);
     SelectAll(presContext);
     return NS_OK;
   }
 
-  // Just like SetFocus() but without the ScrollIntoView()!
-
   nsEventStatus status = nsEventStatus_eIgnore;
   nsGUIEvent event(PR_TRUE, NS_FORM_SELECTED, nsnull);
   // XXXbz nsHTMLInputElement guards against this reentering; shouldn't we?
   nsEventDispatcher::Dispatch(static_cast<nsIContent*>(this), presContext,
                               &event, nsnull, &status);
 
   // If the DOM event was not canceled (e.g. by a JS event handler
   // returning false)
   if (status == nsEventStatus_eIgnore) {
-    PRBool shouldFocus = ShouldFocus(this);
-
-    if (shouldFocus &&
-        !presContext->EventStateManager()->SetContentState(this,
-                                                           NS_EVENT_STATE_FOCUS)) {
-      return rv; // We ended up unfocused, e.g. due to a DOM event handler.
-    }
+    if (fm) {
+      fm->SetFocus(this, nsIFocusManager::FLAG_NOSCROLL);
 
-    nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
-
-    if (formControlFrame) {
-      if (shouldFocus) {
-        formControlFrame->SetFocus(PR_TRUE, PR_TRUE);
+      // ensure that the element is actually focused
+      nsCOMPtr<nsIDOMElement> focusedElement;
+      fm->GetFocusedElement(getter_AddRefs(focusedElement));
+      if (SameCOMIdentity(static_cast<nsIDOMNode*>(this), focusedElement)) {
+        // Now Select all the text!
+        SelectAll(presContext);
       }
-
-      // Now Select all the text!
-      SelectAll(presContext);
     }
   }
 
-  return rv;
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLTextAreaElement::SelectAll(nsPresContext* aPresContext)
 {
   nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
 
   if (formControlFrame) {
     formControlFrame->SetFormProperty(nsGkAtoms::select, EmptyString());
   }
 
   return NS_OK;
 }
 
+PRBool
+nsHTMLTextAreaElement::IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex)
+{
+  if (nsGenericHTMLElement::IsHTMLFocusable(aIsFocusable, aTabIndex)) {
+    return PR_TRUE;
+  }
+
+  // disabled textareas are not focusable
+  *aIsFocusable = !HasAttr(kNameSpaceID_None, nsGkAtoms::disabled);
+  return PR_FALSE;
+}
+
 NS_IMPL_STRING_ATTR(nsHTMLTextAreaElement, AccessKey, accesskey)
 NS_IMPL_INT_ATTR(nsHTMLTextAreaElement, Cols, cols)
 NS_IMPL_BOOL_ATTR(nsHTMLTextAreaElement, Disabled, disabled)
 NS_IMPL_STRING_ATTR(nsHTMLTextAreaElement, Name, name)
 NS_IMPL_BOOL_ATTR(nsHTMLTextAreaElement, ReadOnly, readonly)
 NS_IMPL_INT_ATTR(nsHTMLTextAreaElement, Rows, rows)
 NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLTextAreaElement, TabIndex, tabindex, 0)
   
@@ -629,17 +621,17 @@ nsHTMLTextAreaElement::PreHandleEvent(ns
     if (primaryFrame) {
       nsITextControlFrame* textFrame = do_QueryFrame(primaryFrame);
       if (textFrame) {
         textFrame->CheckFireOnChange();
       }
     }
   }
 
-  return nsGenericHTMLElement::PreHandleEvent(aVisitor);
+  return nsGenericHTMLFormElement::PreHandleEvent(aVisitor);
 }
 
 nsresult
 nsHTMLTextAreaElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
 {
   if (aVisitor.mEvent->message == NS_FORM_SELECTED) {
     mHandlingSelect = PR_FALSE;
   }
--- a/content/xbl/src/nsXBLPrototypeHandler.cpp
+++ b/content/xbl/src/nsXBLPrototypeHandler.cpp
@@ -53,16 +53,17 @@
 #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"
 #include "nsIDOMWindowInternal.h"
@@ -406,22 +407,23 @@ nsXBLPrototypeHandler::DispatchXBLComman
       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));
   }
   else {
-    nsCOMPtr<nsPIDOMWindow> privateWindow(do_QueryInterface(aTarget));
+    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
       // normally.  It's not clear that the owner doc is the right
       // thing.
       if (elt)
@@ -450,26 +452,38 @@ nsXBLPrototypeHandler::DispatchXBLComman
   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<nsIDOMElement> focusedElement;
-    focusController->GetFocusedElement(getter_AddRefs(focusedElement));
+
+    nsCOMPtr<nsPIDOMWindow> windowToCheck;
+    if (windowRoot)
+      windowToCheck = do_QueryInterface(windowRoot->GetWindow());
+    else
+      windowToCheck = privateWindow->GetPrivateRoot();
+
+    nsCOMPtr<nsIContent> focusedContent;
+    if (windowToCheck) {
+      nsCOMPtr<nsPIDOMWindow> focusedWindow;
+      focusedContent =
+        nsFocusManager::GetFocusedDescendant(windowToCheck, PR_TRUE, getter_AddRefs(focusedWindow));
+    }
+
     PRBool isLink = PR_FALSE;
-    nsCOMPtr<nsIContent> focusedContent = do_QueryInterface(focusedElement);
     nsIContent *content = focusedContent;
 
     // if the focused element is a link then we do want space to 
-    // scroll down. focused element may be an element in a link,
-    // we need to check the parent node too.
-    if (focusedContent) {
+    // scroll down. The focused element may be an element in a link,
+    // we need to check the parent node too. Only do this check if an
+    // element is focused and has a parent.
+    if (focusedContent && focusedContent->GetParent()) {
       while (content) {
         if (content->Tag() == nsGkAtoms::a &&
             content->IsNodeOfType(nsINode::eHTML)) {
           isLink = PR_TRUE;
           break;
         }
 
         if (content->HasAttr(kNameSpaceID_XLink, nsGkAtoms::type)) {
--- a/content/xbl/src/nsXBLWindowKeyHandler.cpp
+++ b/content/xbl/src/nsXBLWindowKeyHandler.cpp
@@ -51,26 +51,26 @@
 #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"
 #include "nsPIWindowRoot.h"
 #include "nsPIDOMWindow.h"
-#include "nsIFocusController.h"
 #include "nsIDocShell.h"
 #include "nsIPresShell.h"
 #include "nsIPrivateDOMEvent.h"
 #include "nsISelectionController.h"
 #include "nsGUIEvent.h"
 
 static nsINativeKeyBindings *sNativeEditorBindings = nsnull;
 
@@ -444,30 +444,28 @@ nsXBLWindowKeyHandler::ShutDown()
 //
 // IsEditor
 //
 // Determine if the document we're working with is Editor or Browser
 //
 PRBool
 nsXBLWindowKeyHandler::IsEditor()
 {
-  nsCOMPtr<nsPIWindowRoot> windowRoot(do_QueryInterface(mTarget));
-  NS_ENSURE_TRUE(windowRoot, PR_FALSE);
-  nsCOMPtr<nsIFocusController> focusController;
-  windowRoot->GetFocusController(getter_AddRefs(focusController));
-  if (!focusController) {
-    NS_WARNING("********* Something went wrong! No focus controller on the root!!!\n");
+  // XXXndeakin even though this is only used for key events which should be
+  // going to the focused frame anyway, this doesn't seem like the right way
+  // to determine if something is an editor.
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+  if (!fm)
     return PR_FALSE;
-  }
 
-  nsCOMPtr<nsIDOMWindowInternal> focusedWindow;
-  focusController->GetFocusedWindow(getter_AddRefs(focusedWindow));
+  nsCOMPtr<nsIDOMWindow> focusedWindow;
+  fm->GetFocusedWindow(getter_AddRefs(focusedWindow));
   if (!focusedWindow)
     return PR_FALSE;
-  
+
   nsCOMPtr<nsPIDOMWindow> piwin(do_QueryInterface(focusedWindow));
   nsIDocShell *docShell = piwin->GetDocShell();
   nsCOMPtr<nsIPresShell> presShell;
   if (docShell)
     docShell->GetPresShell(getter_AddRefs(presShell));
 
   if (presShell) {
     PRInt16 isEditor;
--- a/content/xtf/src/nsXTFElementWrapper.cpp
+++ b/content/xtf/src/nsXTFElementWrapper.cpp
@@ -58,16 +58,17 @@
 #include "nsIAttribute.h"
 #include "nsDOMAttributeMap.h"
 #include "nsUnicharUtils.h"
 #include "nsEventDispatcher.h"
 #include "nsIProgrammingLanguage.h"
 #include "nsIXPConnect.h"
 #include "nsXTFWeakTearoff.h"
 #include "mozAutoDocUpdate.h"
+#include "nsFocusManager.h"
 
 nsXTFElementWrapper::nsXTFElementWrapper(nsINodeInfo* aNodeInfo,
                                          nsIXTFElement* aXTFElement)
     : nsXTFElementWrapperBase(aNodeInfo),
       mXTFElement(aXTFElement),
       mNotificationMask(0),
       mIntrinsicState(0),
       mTmpAttrName(nsGkAtoms::_asterix) // XXX this is a hack, but names
@@ -548,32 +549,19 @@ nsXTFElementWrapper::IntrinsicState() co
   return  retState | mIntrinsicState;
 }
 
 void
 nsXTFElementWrapper::PerformAccesskey(PRBool aKeyCausesActivation,
                                       PRBool aIsTrustedEvent)
 {
   if (mNotificationMask & nsIXTFElement::NOTIFY_PERFORM_ACCESSKEY) {
-    nsIDocument* doc = GetCurrentDoc();
-    if (!doc)
-      return;
-
-    // Get presentation shell 0
-    nsIPresShell *presShell = doc->GetPrimaryShell();
-    if (!presShell)
-      return;
-
-    nsPresContext *presContext = presShell->GetPresContext();
-    if (!presContext)
-      return;
-
-    nsIEventStateManager *esm = presContext->EventStateManager();
-    if (esm)
-      esm->ChangeFocusWith(this, nsIEventStateManager::eEventFocusedByKey);
+    nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+    if (fm)
+      fm->SetFocus(this, nsIFocusManager::FLAG_BYKEY);
 
     if (aKeyCausesActivation)
       GetXTFElement()->PerformAccesskey();
   }
 }
 
 nsresult
 nsXTFElementWrapper::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
--- a/content/xul/content/src/Makefile.in
+++ b/content/xul/content/src/Makefile.in
@@ -81,17 +81,16 @@ endif
 
 # we don't want the shared lib, but we want to force the creation of a
 # static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES	= \
-	-I$(srcdir) \
 	-I$(srcdir)/../../document/src \
 	-I$(srcdir)/../../templates/src \
 	-I$(srcdir)/../../../xml/content/src \
 	-I$(srcdir)/../../../base/src \
 	-I$(srcdir)/../../../xml/document/src \
 	-I$(srcdir)/../../../../layout/style \
 	-I$(srcdir)/../../../html/content/src \
 	-I$(srcdir)/../../../events/src \
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -81,16 +81,17 @@
 #include "nsIDOMNodeList.h"
 #include "nsIDOMXULCommandDispatcher.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDOMElementCSSInlineStyle.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
 #include "nsIDocument.h"
 #include "nsIEventListenerManager.h"
 #include "nsIEventStateManager.h"
+#include "nsFocusManager.h"
 #include "nsIFastLoadService.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsINameSpaceManager.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsIPresShell.h"
 #include "nsIPrincipal.h"
 #include "nsIRDFCompositeDataSource.h"
@@ -648,18 +649,22 @@ nsXULElement::PerformAccesskey(PRBool aK
         vis->mVisible == NS_STYLE_VISIBILITY_HIDDEN ||
         !frame->AreAncestorViewsVisible())
         return;
 
     nsCOMPtr<nsIDOMXULElement> elm(do_QueryInterface(content));
     if (elm) {
         // Define behavior for each type of XUL element.
         nsIAtom *tag = content->Tag();
-        if (tag != nsGkAtoms::toolbarbutton)
-            elm->Focus();
+        if (tag != nsGkAtoms::toolbarbutton) {
+          nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+          nsCOMPtr<nsIDOMElement> element = do_QueryInterface(content);
+          if (fm)
+            fm->SetFocus(element, nsIFocusManager::FLAG_BYKEY);
+        }
         if (aKeyCausesActivation && tag != nsGkAtoms::textbox && tag != nsGkAtoms::menulist)
             elm->Click();
     }
     else {
         content->PerformAccesskey(aKeyCausesActivation, aIsTrustedEvent);
     }
 }
 
@@ -2022,56 +2027,35 @@ nsXULElement::GetParentTree(nsIDOMXULMul
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULElement::Focus()
 {
-    if (!nsGenericElement::ShouldFocus(this)) {
-        return NS_OK;
-    }
-
-    nsIDocument* doc = GetCurrentDoc();
-    // What kind of crazy tries to focus an element without a doc?
-    if (!doc)
-        return NS_OK;
-
-    // Obtain a presentation context and then call SetFocus.
-
-    nsIPresShell *shell = doc->GetPrimaryShell();
-    if (!shell)
-        return NS_OK;
-
-    // Set focus
-    nsCOMPtr<nsPresContext> context = shell->GetPresContext();
-    SetFocus(context);
-
-    return NS_OK;
+    nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+    nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(static_cast<nsIContent*>(this));
+    return fm ? fm->SetFocus(this, 0) : NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULElement::Blur()
 {
+    if (!ShouldBlur(this))
+      return NS_OK;
+
     nsIDocument* doc = GetCurrentDoc();
-    // What kind of crazy tries to blur an element without a doc?
     if (!doc)
-        return NS_OK;
-
-    // Obtain a presentation context and then call SetFocus.
-    nsIPresShell *shell = doc->GetPrimaryShell();
-    if (!shell)
-        return NS_OK;
-
-    // Set focus
-    nsCOMPtr<nsPresContext> context = shell->GetPresContext();
-    if (ShouldBlur(this))
-      RemoveFocus(context);
-
+      return NS_OK;
+
+    nsIDOMWindow* win = doc->GetWindow();
+    nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+    if (win && fm)
+      return fm->ClearFocus(win);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULElement::Click()
 {
     if (BoolAttrIsTrue(nsGkAtoms::disabled))
         return NS_OK;
@@ -2128,39 +2112,16 @@ nsXULElement::DoCommand()
             nsEventDispatcher::Dispatch(static_cast<nsIContent*>(this),
                                         context, &event, nsnull, &status);
         }
     }
 
     return NS_OK;
 }
 
-// nsIFocusableContent interface and helpers
-void
-nsXULElement::SetFocus(nsPresContext* aPresContext)
-{
-    if (BoolAttrIsTrue(nsGkAtoms::disabled))
-        return;
-
-    aPresContext->EventStateManager()->SetContentState(this,
-                                                       NS_EVENT_STATE_FOCUS);
-}
-
-void
-nsXULElement::RemoveFocus(nsPresContext* aPresContext)
-{
-  if (!aPresContext) 
-    return;
-  
-  if (IsInDoc()) {
-    aPresContext->EventStateManager()->SetContentState(nsnull,
-                                                       NS_EVENT_STATE_FOCUS);
-  }
-}
-
 nsIContent *
 nsXULElement::GetBindingParent() const
 {
     return mBindingParent;
 }
 
 PRBool
 nsXULElement::IsNodeOfType(PRUint32 aFlags) const
--- a/content/xul/content/src/nsXULElement.h
+++ b/content/xul/content/src/nsXULElement.h
@@ -537,18 +537,16 @@ public:
 
 #ifdef DEBUG
     virtual void List(FILE* out, PRInt32 aIndent) const;
     virtual void DumpContent(FILE* out, PRInt32 aIndent,PRBool aDumpAll) const
     {
     }
 #endif
 
-    virtual void SetFocus(nsPresContext* aPresContext);
-    virtual void RemoveFocus(nsPresContext* aPresContext);
     virtual void PerformAccesskey(PRBool aKeyCausesActivation,
                                   PRBool aIsTrustedEvent);
 
     virtual nsIContent *GetBindingParent() const;
     virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
     virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
     virtual nsIAtom* GetID() const;
     virtual const nsAttrValue* DoGetClasses() const;
--- a/content/xul/content/src/nsXULPopupListener.cpp
+++ b/content/xul/content/src/nsXULPopupListener.cpp
@@ -70,17 +70,17 @@
 #include "nsFrameManager.h"
 #include "nsHTMLReflowState.h"
 #include "nsIObjectLoadingContent.h"
 
 // for event firing in context menus
 #include "nsPresContext.h"
 #include "nsIPresShell.h"
 #include "nsIEventStateManager.h"
-#include "nsIFocusController.h"
+#include "nsFocusManager.h"
 #include "nsPIDOMWindow.h"
 #include "nsIViewManager.h"
 #include "nsDOMError.h"
 #include "nsIMenuFrame.h"
 
 // on win32 and os/2, context menus come up on mouse up. On other platforms,
 // they appear on mouse down. Certain bits of code care about this difference.
 #if !defined(XP_WIN) && !defined(XP_OS2)
@@ -274,20 +274,19 @@ nsXULPopupListener::FireFocusOnTargetCon
       return NS_ERROR_FAILURE;
 
     // strong reference to keep this from going away between events
     nsCOMPtr<nsPresContext> context = shell->GetPresContext();
  
     nsCOMPtr<nsIContent> content = do_QueryInterface(aTargetNode);
     nsIFrame* targetFrame = shell->GetPrimaryFrameFor(content);
     if (!targetFrame) return NS_ERROR_FAILURE;
-      
-    PRBool suppressBlur = PR_FALSE;
+
     const nsStyleUserInterface* ui = targetFrame->GetStyleUserInterface();
-    suppressBlur = (ui->mUserFocus == NS_STYLE_USER_FOCUS_IGNORE);
+    PRBool suppressBlur = (ui->mUserFocus == NS_STYLE_USER_FOCUS_IGNORE);
 
     nsCOMPtr<nsIDOMElement> element;
     nsCOMPtr<nsIContent> newFocus = do_QueryInterface(content);
 
     nsIFrame* currFrame = targetFrame;
     // Look for the nearest enclosing focusable frame.
     while (currFrame) {
         PRInt32 tabIndexUnused;
@@ -296,31 +295,30 @@ nsXULPopupListener::FireFocusOnTargetCon
           nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(newFocus));
           if (domElement) {
             element = domElement;
             break;
           }
         }
         currFrame = currFrame->GetParent();
     } 
-    nsCOMPtr<nsIContent> focusableContent = do_QueryInterface(element);
-    nsIEventStateManager *esm = context->EventStateManager();
 
-    if (focusableContent) {
-      // Lock to scroll by SetFocus. See bug 309075.
-      nsFocusScrollSuppressor scrollSuppressor;
-      nsPIDOMWindow *ourWindow = doc->GetWindow();
-      if (ourWindow) {
-        scrollSuppressor.Init(ourWindow->GetRootFocusController());
+    nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+    if (fm) {
+      if (element) {
+        fm->SetFocus(element, nsIFocusManager::FLAG_BYMOUSE |
+                              nsIFocusManager::FLAG_NOSCROLL);
+      } else if (!suppressBlur) {
+        nsPIDOMWindow *window = doc->GetWindow();
+        fm->ClearFocus(window);
       }
+    }
 
-      focusableContent->SetFocus(context);
-    } else if (!suppressBlur)
-      esm->SetContentState(nsnull, NS_EVENT_STATE_FOCUS);
-
+    nsIEventStateManager *esm = context->EventStateManager();
+    nsCOMPtr<nsIContent> focusableContent = do_QueryInterface(element);
     esm->SetContentState(focusableContent, NS_EVENT_STATE_ACTIVE);
   }
   return rv;
 }
 #endif
 
 // ClosePopup
 //
--- a/content/xul/content/test/test_bug398289.html
+++ b/content/xul/content/test/test_bug398289.html
@@ -2,17 +2,17 @@
 <html style="height: 100%">
 <head>
   <title>Test for bug 398289</title>
   <script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 </head>
-<body style="height: 100%" onload="onBodyLoad();">
+<body style="height: 100%" onload="setTimeout(onBodyLoad, 0);">
   <iframe id="test" src="chrome://mochikit/content/chrome/content/xul/content/test/398289-resource.xul" width="100%" height="100%">
   </iframe>
 
   <script class="testbody" type="text/javascript">
     var snap1, snap2;
   
     SimpleTest.waitForExplicitFinish();
   
--- a/content/xul/document/src/nsXULCommandDispatcher.cpp
+++ b/content/xul/document/src/nsXULCommandDispatcher.cpp
@@ -40,16 +40,17 @@
 /*
 
   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"
@@ -135,108 +136,152 @@ nsXULCommandDispatcher::GetFocusControll
   if (!mDocument) {
     return nsnull;
   }
 
   nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(mDocument->GetScriptGlobalObject()));
   return win ? win->GetRootFocusController() : nsnull;
 }
 
-////////////////////////////////////////////////////////////////
-// nsIDOMXULTracker Interface
+nsIContent*
+nsXULCommandDispatcher::GetRootFocusedContentAndWindow(nsPIDOMWindow** aWindow)
+{
+  *aWindow = nsnull;
+
+  if (mDocument) {
+    nsCOMPtr<nsPIDOMWindow> win = mDocument->GetWindow();
+    if (win) {
+      nsCOMPtr<nsPIDOMWindow> rootWindow = win->GetPrivateRoot();
+      if (rootWindow) {
+        return nsFocusManager::GetFocusedDescendant(rootWindow, PR_TRUE, aWindow);
+      }
+    }
+  }
+
+  return nsnull;
+}
 
 NS_IMETHODIMP
 nsXULCommandDispatcher::GetFocusedElement(nsIDOMElement** aElement)
 {
-  nsIFocusController* fc = GetFocusController();
-  NS_ENSURE_TRUE(fc, NS_ERROR_FAILURE);
+  *aElement = nsnull;
 
-  nsresult rv = fc->GetFocusedElement(aElement);
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsPIDOMWindow> focusedWindow;
+  nsIContent* focusedContent =
+    GetRootFocusedContentAndWindow(getter_AddRefs(focusedWindow));
+  if (focusedContent) {
+    CallQueryInterface(focusedContent, aElement);
 
-  // Make sure the caller can access the focused element.
-  if (*aElement && !nsContentUtils::CanCallerAccess(*aElement)) {
-    // XXX This might want to return null, but we use that return value
-    // to mean "there is no focused element," so to be clear, throw an
-    // exception.
-    NS_RELEASE(*aElement);
-    return NS_ERROR_DOM_SECURITY_ERR;
+    // Make sure the caller can access the focused element.
+    if (!nsContentUtils::CanCallerAccess(*aElement)) {
+      // XXX This might want to return null, but we use that return value
+      // to mean "there is no focused element," so to be clear, throw an
+      // exception.
+      NS_RELEASE(*aElement);
+      return NS_ERROR_DOM_SECURITY_ERR;
+    }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULCommandDispatcher::GetFocusedWindow(nsIDOMWindow** aWindow)
 {
-  nsIFocusController* fc = GetFocusController();
-  NS_ENSURE_TRUE(fc, NS_ERROR_FAILURE);
+  *aWindow = nsnull;
 
-  nsCOMPtr<nsIDOMWindowInternal> window;
-  nsresult rv = fc->GetFocusedWindow(getter_AddRefs(window));
-  NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && window, rv);
-
-  rv = CallQueryInterface(window, aWindow);
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsPIDOMWindow> window;
+  GetRootFocusedContentAndWindow(getter_AddRefs(window));
+  if (!window)
+    return NS_OK;
 
   // Make sure the caller can access this window. The caller can access this
   // window iff it can access the document.
   nsCOMPtr<nsIDOMDocument> domdoc;
-  rv = (*aWindow)->GetDocument(getter_AddRefs(domdoc));
+  nsresult rv = window->GetDocument(getter_AddRefs(domdoc));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Note: If there is no document, then this window has been cleared and
   // there's nothing left to protect, so let the window pass through.
-  if (domdoc && !nsContentUtils::CanCallerAccess(domdoc)) {
-    NS_RELEASE(*aWindow);
+  if (domdoc && !nsContentUtils::CanCallerAccess(domdoc))
     return NS_ERROR_DOM_SECURITY_ERR;
-  }
 
+  CallQueryInterface(window, aWindow);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULCommandDispatcher::SetFocusedElement(nsIDOMElement* aElement)
 {
-  nsIFocusController* fc = GetFocusController();
-  NS_ENSURE_TRUE(fc, NS_ERROR_FAILURE);
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+  NS_ENSURE_TRUE(fm, NS_ERROR_FAILURE);
 
-  return fc->SetFocusedElement(aElement);
+  if (aElement)
+    return fm->SetFocus(aElement, 0);
+
+  // if aElement is null, clear the focus in the currently focused child window
+  nsCOMPtr<nsPIDOMWindow> focusedWindow;
+  GetRootFocusedContentAndWindow(getter_AddRefs(focusedWindow));
+  return fm->ClearFocus(focusedWindow);
 }
 
 NS_IMETHODIMP
 nsXULCommandDispatcher::SetFocusedWindow(nsIDOMWindow* aWindow)
 {
-  nsIFocusController* fc = GetFocusController();
-  NS_ENSURE_TRUE(fc, NS_ERROR_FAILURE);
+  NS_ENSURE_TRUE(aWindow, NS_OK); // do nothing if set to null
+
+  nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(aWindow));
+  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
+
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+  NS_ENSURE_TRUE(fm, NS_ERROR_FAILURE);
 
-  nsCOMPtr<nsIDOMWindowInternal> window(do_QueryInterface(aWindow));
+  // get the containing frame for the window, and set it as focused. This will
+  // end up focusing whatever is currently focused inside the frame. Since
+  // setting the command dispatcher's focused window doesn't raise the window,
+  // setting it to a top-level window doesn't need to do anything.
+  nsCOMPtr<nsIDOMElement> frameElement = window->GetFrameElementInternal();
+  if (frameElement)
+    return fm->SetFocus(frameElement, 0);
 
-  return fc->SetFocusedWindow(window);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULCommandDispatcher::AdvanceFocus()
 {
-  nsIFocusController* fc = GetFocusController();
-  return fc ? fc->MoveFocus(PR_TRUE, nsnull) : NS_OK;
+  return AdvanceFocusIntoSubtree(nsnull);
 }
 
 NS_IMETHODIMP
 nsXULCommandDispatcher::RewindFocus()
 {
-  nsIFocusController* fc = GetFocusController();
-  return fc ? fc->MoveFocus(PR_FALSE, nsnull) : NS_OK;
+  nsCOMPtr<nsPIDOMWindow> win;
+  GetRootFocusedContentAndWindow(getter_AddRefs(win));
+
+  nsCOMPtr<nsIDOMElement> result;
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+  if (fm)
+    return fm->MoveFocus(win, nsnull, nsIFocusManager::MOVEFOCUS_BACKWARD,
+                         0, getter_AddRefs(result));
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULCommandDispatcher::AdvanceFocusIntoSubtree(nsIDOMElement* aElt)
 {
-  nsIFocusController* fc = GetFocusController();
-  return fc ? fc->MoveFocus(PR_TRUE, aElt) : NS_OK;
+  nsCOMPtr<nsPIDOMWindow> win;
+  GetRootFocusedContentAndWindow(getter_AddRefs(win));
+
+  nsCOMPtr<nsIDOMElement> result;
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+  if (fm)
+    return fm->MoveFocus(win, aElt, nsIFocusManager::MOVEFOCUS_FORWARD,
+                         0, getter_AddRefs(result));
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULCommandDispatcher::AddCommandUpdater(nsIDOMElement* aElement,
                                           const nsAString& aEvents,
                                           const nsAString& aTargets)
 {
   NS_PRECONDITION(aElement != nsnull, "null ptr");
@@ -349,17 +394,17 @@ nsXULCommandDispatcher::RemoveCommandUpd
 NS_IMETHODIMP
 nsXULCommandDispatcher::UpdateCommands(const nsAString& aEventName)
 {
   nsIFocusController* fc = GetFocusController();
   NS_ENSURE_TRUE(fc, NS_ERROR_FAILURE);
 
   nsAutoString id;
   nsCOMPtr<nsIDOMElement> element;
-  fc->GetFocusedElement(getter_AddRefs(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;
   }
 
   for (Updater* updater = mUpdaters; updater != nsnull; updater = updater->mNext) {
     // Skip any nodes that don't match our 'events' or 'targets'
@@ -454,23 +499,18 @@ nsXULCommandDispatcher::GetControllerFor
   NS_ENSURE_TRUE(fc, NS_ERROR_FAILURE);
 
   return fc->GetControllerForCommand(aCommand, _retval);
 }
 
 NS_IMETHODIMP
 nsXULCommandDispatcher::GetSuppressFocusScroll(PRBool* aSuppressFocusScroll)
 {
-  nsIFocusController* fc = GetFocusController();
-  NS_ENSURE_TRUE(fc, NS_ERROR_FAILURE);
-
-  return fc->GetSuppressFocusScroll(aSuppressFocusScroll);
+  *aSuppressFocusScroll = PR_FALSE;
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULCommandDispatcher::SetSuppressFocusScroll(PRBool aSuppressFocusScroll)
 {
-  nsIFocusController* fc = GetFocusController();
-  NS_ENSURE_TRUE(fc, NS_ERROR_FAILURE);
-
-  return fc->SetSuppressFocusScroll(aSuppressFocusScroll);
+  return NS_OK;
 }
 
--- a/content/xul/document/src/nsXULCommandDispatcher.h
+++ b/content/xul/document/src/nsXULCommandDispatcher.h
@@ -71,16 +71,18 @@ public:
 
     // nsIDOMXULCommandDispatcher interface
     NS_DECL_NSIDOMXULCOMMANDDISPATCHER
 
     void Disconnect();
 protected:
     nsIFocusController* GetFocusController();
 
+    nsIContent* GetRootFocusedContentAndWindow(nsPIDOMWindow** aWindow);
+
     nsCOMPtr<nsIDocument> mDocument;
 
     class Updater {
     public:
       Updater(nsIDOMElement* aElement,
               const nsAString& aEvents,
               const nsAString& aTargets)
           : mElement(aElement),
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -175,16 +175,17 @@
 #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"
 
@@ -209,17 +210,16 @@ static NS_DEFINE_CID(kDOMScriptObjectFac
 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
 #if defined(DEBUG_bryner) || defined(DEBUG_chb)
 //#define DEBUG_DOCSHELL_FOCUS
 #define DEBUG_PAGE_CACHE
 #endif
 
 #include "nsContentErrors.h"
-#include "nsIFocusEventSuppressor.h"
 
 // Number of documents currently loading
 static PRInt32 gNumberOfDocumentsLoading = 0;
 
 // Global count of existing docshells.
 static PRInt32 gDocShellCount = 0;
 
 // Global reference to the URI fixup service.
@@ -255,41 +255,16 @@ static void
 FavorPerformanceHint(PRBool perfOverStarvation, PRUint32 starvationDelay)
 {
     nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
     if (appShell)
         appShell->FavorPerformanceHint(perfOverStarvation, starvationDelay);
 }
 
 //*****************************************************************************
-//***    nsDocShellFocusController
-//*****************************************************************************
-
-class nsDocShellFocusController
-{
-
-public:
-  static nsDocShellFocusController* GetInstance() { return &mDocShellFocusControllerSingleton; }
-  virtual ~nsDocShellFocusController(){}
-
-  void Focus(nsIDocShell* aDS);
-  void ClosingDown(nsIDocShell* aDS);
-
-protected:
-  nsDocShellFocusController(){}
-
-  nsIDocShell* mFocusedDocShell; // very weak reference
-
-private:
-  static nsDocShellFocusController mDocShellFocusControllerSingleton;
-};
-
-nsDocShellFocusController nsDocShellFocusController::mDocShellFocusControllerSingleton;
-
-//*****************************************************************************
 // <a ping> support
 //*****************************************************************************
 
 #define PREF_PINGS_ENABLED           "browser.send_pings"
 #define PREF_PINGS_MAX_PER_LINK      "browser.send_pings.max_per_link"
 #define PREF_PINGS_REQUIRE_SAME_HOST "browser.send_pings.require_same_host"
 
 // Check prefs to see if pings are enabled and if so what restrictions might
@@ -696,18 +671,16 @@ nsDocShell::nsDocShell():
     mPreviousTransIndex(-1),
     mLoadedTransIndex(-1),
     mAllowSubframes(PR_TRUE),
     mAllowPlugins(PR_TRUE),
     mAllowJavascript(PR_TRUE),
     mAllowMetaRedirects(PR_TRUE),
     mAllowImages(PR_TRUE),
     mAllowDNSPrefetch(PR_TRUE),
-    mFocusDocFirst(PR_FALSE),
-    mHasFocus(PR_FALSE),
     mCreatingDocument(PR_FALSE),
     mUseErrorPages(PR_FALSE),
     mObserveErrorPages(PR_TRUE),
     mAllowAuth(PR_TRUE),
     mAllowKeywordFixup(PR_FALSE),
     mIsOffScreenBrowser(PR_FALSE),
     mFiredUnloadEvent(PR_FALSE),
     mEODForCurrentDocument(PR_FALSE),
@@ -744,20 +717,16 @@ nsDocShell::nsDocShell():
 #endif
 #ifdef DEBUG
   printf("++DOCSHELL %p == %ld\n", (void*) this, gNumberOfDocShells);
 #endif
 }
 
 nsDocShell::~nsDocShell()
 {
-    nsDocShellFocusController* dsfc = nsDocShellFocusController::GetInstance();
-    if (dsfc) {
-      dsfc->ClosingDown(this);
-    }
     Destroy();
 
     if (--gDocShellCount == 0) {
         NS_IF_RELEASE(sURIFixup);
     }
 
 #ifdef PR_LOGGING
     if (gDocShellLeakLog)
@@ -4253,17 +4222,17 @@ nsDocShell::Destroy()
             prefs->RemoveObserver("browser.xul.error_pages.enabled", this);
             mObserveErrorPages = PR_FALSE;
         }
     }
 
     // Make sure to blow away our mLoadingURI just in case.  No loads
     // from inside this pagehide.
     mLoadingURI = nsnull;
-    
+
     // Fire unload event before we blow anything away.
     (void) FirePageHideNotification(PR_TRUE);
 
     // Clear pointers to any detached nsEditorData that's lying
     // around in shistory entries. Breaks cycle. See bug 430921.
     if (mOSHE)
       mOSHE->SetEditorData(nsnull);
     if (mLSHE)
@@ -4294,22 +4263,17 @@ nsDocShell::Destroy()
     PersistLayoutHistoryState();
 
     // Remove this docshell from its parent's child list
     nsCOMPtr<nsIDocShellTreeItem> docShellParentAsItem =
         do_QueryInterface(GetAsSupports(mParent));
     if (docShellParentAsItem)
         docShellParentAsItem->RemoveChild(this);
 
-    nsCOMPtr<nsIFocusEventSuppressorService> suppressor;
     if (mContentViewer) {
-        suppressor =
-          do_GetService(NS_NSIFOCUSEVENTSUPPRESSORSERVICE_CONTRACTID);
-        NS_ENSURE_STATE(suppressor);
-        suppressor->Suppress();
         mContentViewer->Close(nsnull);
         mContentViewer->Destroy();
         mContentViewer = nsnull;
     }
 
     nsDocLoader::Destroy();
     
     mParentWidget = nsnull;
@@ -4337,19 +4301,16 @@ nsDocShell::Destroy()
     SetTreeOwner(nsnull);
 
     // required to break ref cycle
     mSecurityUI = nsnull;
 
     // Cancel any timers that were set for this docshell; this is needed
     // to break the cycle between us and the timers.
     CancelRefreshURITimers();
-    if (suppressor) {
-      suppressor->Unsuppress();
-    }
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShell::SetPosition(PRInt32 x, PRInt32 y)
 {
     mBounds.x = x;
     mBounds.y = y;
@@ -4611,38 +4572,29 @@ nsDocShell::GetBlurSuppression(PRBool *a
 
 NS_IMETHODIMP
 nsDocShell::SetBlurSuppression(PRBool aBlurSuppression)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
+nsDocShell::SetFocus()
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDocShell::GetMainWidget(nsIWidget ** aMainWidget)
 {
     // We don't create our own widget, so simply return the parent one. 
     return GetParentWidget(aMainWidget);
 }
 
 NS_IMETHODIMP
-nsDocShell::SetFocus()
-{
-#ifdef DEBUG_DOCSHELL_FOCUS
-  printf("nsDocShell::SetFocus %p\n", (void*)this);
-#endif
-
-  // Tell itself (and the DocShellFocusController) who has focus
-  // this way focus gets removed from the currently focused DocShell
-
-  SetHasFocus(PR_TRUE);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 nsDocShell::GetTitle(PRUnichar ** aTitle)
 {
     NS_ENSURE_ARG_POINTER(aTitle);
 
     *aTitle = ToNewUnicode(mTitle);
     return NS_OK;
 }
 
@@ -7276,71 +7228,16 @@ nsDocShell::SetupNewViewer(nsIContentVie
                                   NS_ERROR_FAILURE);
                 NS_ENSURE_SUCCESS(oldMUDV->
                                   GetPrevDocCharacterSet(prevDocCharset),
                                   NS_ERROR_FAILURE);
             }
         }
     }
 
-    // It is necessary to obtain the focus controller to utilize its ability
-    // to suppress focus.  This is necessary to fix Win32-only bugs related to
-    // a loss of focus when mContentViewer is set to null.  The internal window
-    // is destroyed, and the OS focuses the parent window.  This call ends up
-    // notifying the focus controller that the outer window should focus
-    // and this hoses us on any link traversal.
-    //
-    // Please do not touch any of the focus controller code here without
-    // testing bugs #28580 and 50509.  These are immensely important bugs,
-    // so PLEASE take care not to regress them if you decide to alter this 
-    // code later              -- hyatt
-    nsIFocusController *focusController = nsnull;
-    if (mScriptGlobal) {
-        nsCOMPtr<nsPIDOMWindow> ourWindow = do_QueryInterface(mScriptGlobal);
-        focusController = ourWindow->GetRootFocusController();
-        if (focusController) {
-            // Suppress the command dispatcher.
-            focusController->SetSuppressFocus(PR_TRUE,
-                                              "Win32-Only Link Traversal Issue");
-            // Remove focus from the element that has it
-            nsCOMPtr<nsIDOMWindowInternal> focusedWindow;
-            focusController->GetFocusedWindow(getter_AddRefs(focusedWindow));
-
-            // We want to null out the last focused element if the document containing
-            // it is going away.  If the last focused element is in a descendent
-            // window of our domwindow, its document will be destroyed when we
-            // destroy our children.  So, check for this case and null out the
-            // last focused element.  See bug 70484.
-
-            PRBool isSubWindow = PR_FALSE;
-            nsCOMPtr<nsIDOMWindow> curwin;
-            if (focusedWindow)
-              focusedWindow->GetParent(getter_AddRefs(curwin));
-            while (curwin) {
-              if (curwin == ourWindow) {
-                isSubWindow = PR_TRUE;
-                break;
-              }
-
-              // don't use nsCOMPtr here to avoid extra addref
-              // when assigning to curwin
-              nsIDOMWindow* temp;
-              curwin->GetParent(&temp);
-              if (curwin == temp) {
-                NS_RELEASE(temp);
-                break;
-              }
-              curwin = dont_AddRef(temp);
-            }
-
-            if (ourWindow == focusedWindow || isSubWindow)
-              focusController->ResetElementFocus();
-        }
-    }
-
     nscolor bgcolor = NS_RGBA(0, 0, 0, 0);
     // Ensure that the content viewer is destroyed *after* the GC - bug 71515
     nsCOMPtr<nsIContentViewer> kungfuDeathGrip = mContentViewer;
     if (mContentViewer) {
         // Stop any activity that may be happening in the old document before
         // releasing it...
         mContentViewer->Stop();
 
@@ -7394,33 +7291,16 @@ nsDocShell::SetupNewViewer(nsIContentVie
         NS_ENSURE_SUCCESS(newMUDV->SetTextZoom(textZoom),
                           NS_ERROR_FAILURE);
         NS_ENSURE_SUCCESS(newMUDV->SetFullZoom(pageZoom),
                           NS_ERROR_FAILURE);
         NS_ENSURE_SUCCESS(newMUDV->SetAuthorStyleDisabled(styleDisabled),
                           NS_ERROR_FAILURE);
     }
 
-    // End copying block (Don't mess with the old content/document viewer
-    // beyond here!!)
-
-    // See the book I wrote above regarding why the focus controller is 
-    // being used here.  -- hyatt
-
-    /* Note it's important that focus suppression be turned off no earlier
-       because in cases where the docshell is lazily creating an about:blank
-       document, mContentViewer->Init finally puts a reference to that
-       document into the DOM window, which prevents an infinite recursion
-       attempting to lazily create the document as focus is unsuppressed
-       (bug 110856). */
-    if (focusController)
-        focusController->SetSuppressFocus(PR_FALSE,
-                                          "Win32-Only Link Traversal Issue");
-
-
     // Stuff the bgcolor from the old pres shell into the new
     // pres shell. This improves page load continuity.
     nsCOMPtr<nsIDocumentViewer> docviewer =
         do_QueryInterface(mContentViewer);
 
     if (docviewer) {
         nsCOMPtr<nsIPresShell> shell;
         docviewer->GetPresShell(getter_AddRefs(shell));
@@ -10025,30 +9905,30 @@ NS_IMETHODIMP nsDocShell::EnsureFind()
     // we promise that the nsIWebBrowserFind that we return has been set
     // up to point to the focused, or content window, so we have to
     // set that up each time.
 
     nsIScriptGlobalObject* scriptGO = GetScriptGlobalObject();
     NS_ENSURE_TRUE(scriptGO, NS_ERROR_UNEXPECTED);
 
     // default to our window
-    nsCOMPtr<nsIDOMWindow> rootWindow = do_QueryInterface(scriptGO);
-    nsCOMPtr<nsIDOMWindow> windowToSearch = rootWindow;
-
-    // if we can, search the focused window
-    nsCOMPtr<nsPIDOMWindow> ourWindow = do_QueryInterface(scriptGO);
-    nsIFocusController *focusController = nsnull;
-    if (ourWindow)
-        focusController = ourWindow->GetRootFocusController();
-    if (focusController)
-    {
-        nsCOMPtr<nsIDOMWindowInternal> focusedWindow;
-        focusController->GetFocusedWindow(getter_AddRefs(focusedWindow));
-        if (focusedWindow)
-            windowToSearch = focusedWindow;
+    nsCOMPtr<nsIDOMWindow> windowToSearch(do_QueryInterface(mScriptGlobal));
+
+    nsCOMPtr<nsIDocShellTreeItem> root;
+    GetRootTreeItem(getter_AddRefs(root));
+
+    // if the active window is the same window that this docshell is in,
+    // use the currently focused frame
+    nsCOMPtr<nsIDOMWindow> rootWindow = do_GetInterface(root);
+    nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
+    if (fm) {
+      nsCOMPtr<nsIDOMWindow> activeWindow;
+      fm->GetActiveWindow(getter_AddRefs(activeWindow));
+      if (activeWindow == rootWindow)
+        fm->GetFocusedWindow(getter_AddRefs(windowToSearch));
     }
 
     nsCOMPtr<nsIWebBrowserFindInFrames> findInFrames = do_QueryInterface(mFind);
     if (!findInFrames) return NS_ERROR_NO_INTERFACE;
     
     rv = findInFrames->SetRootSearchFrame(rootWindow);
     if (NS_FAILED(rv)) return rv;
     rv = findInFrames->SetCurrentSearchFrame(windowToSearch);
@@ -10067,117 +9947,16 @@ nsDocShell::IsFrame()
         parent->GetItemType(&parentType);
         if (parentType == mItemType)    // This is a frame
             return PR_TRUE;
     }
 
     return PR_FALSE;
 }
 
-NS_IMETHODIMP
-nsDocShell::GetHasFocus(PRBool *aHasFocus)
-{
-  *aHasFocus = mHasFocus;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDocShell::SetHasFocus(PRBool aHasFocus)
-{
-#ifdef DEBUG_DOCSHELL_FOCUS
-    printf(">>>>>>>>>> nsDocShell::SetHasFocus: %p  %s\n", (void*)this,
-           aHasFocus?"Yes":"No");
-#endif
-
-  mHasFocus = aHasFocus;
-
-  nsDocShellFocusController* dsfc = nsDocShellFocusController::GetInstance();
-  if (dsfc && aHasFocus) {
-    dsfc->Focus(this);
-  }
-
-  if (!aHasFocus) {
-      // We may be in a situation where the focus outline was shown
-      // on this document because the user tabbed into it, but the focus
-      // is now switching to another document via a click.  In this case,
-      // we need to make sure the focus outline is removed from this document.
-      SetCanvasHasFocus(PR_FALSE);
-  }
-
-  return NS_OK;
-}
-
-// Find an nsICanvasFrame under aFrame.  Only search the principal
-// child lists.  aFrame must be non-null.
-static nsICanvasFrame* FindCanvasFrame(nsIFrame* aFrame)
-{
-    nsICanvasFrame* canvasFrame = do_QueryFrame(aFrame);
-    if (canvasFrame) {
-        return canvasFrame;
-    }
-
-    nsIFrame* kid = aFrame->GetFirstChild(nsnull);
-    while (kid) {
-        canvasFrame = FindCanvasFrame(kid);
-        if (canvasFrame) {
-            return canvasFrame;
-        }
-        kid = kid->GetNextSibling();
-    }
-
-    return nsnull;
-}
-
-//-------------------------------------------------------
-// Tells the HTMLFrame/CanvasFrame that is now has focus
-NS_IMETHODIMP
-nsDocShell::SetCanvasHasFocus(PRBool aCanvasHasFocus)
-{
-  if (mEditorData && mEditorData->GetEditable())
-    return NS_ERROR_NOT_AVAILABLE;
-
-  nsCOMPtr<nsIPresShell> presShell;
-  GetPresShell(getter_AddRefs(presShell));
-  if (!presShell) return NS_ERROR_FAILURE;
-
-  nsIDocument *doc = presShell->GetDocument();
-  if (!doc) return NS_ERROR_FAILURE;
-
-  nsIContent *rootContent = doc->GetRootContent();
-  if (rootContent) {
-      nsIFrame* frame = presShell->GetPrimaryFrameFor(rootContent);
-      if (frame) {
-          frame = frame->GetParent();
-          if (frame) {
-              nsICanvasFrame* canvasFrame = do_QueryFrame(frame);
-              if (canvasFrame) {
-                  return canvasFrame->SetHasFocus(aCanvasHasFocus);
-              }
-          }
-      }
-  } else {
-      // Look for the frame the hard way
-      nsIFrame* frame = presShell->GetRootFrame();
-      if (frame) {
-          nsICanvasFrame* canvasFrame = FindCanvasFrame(frame);
-          if (canvasFrame) {
-              return canvasFrame->SetHasFocus(aCanvasHasFocus);
-          }
-      }      
-  }
-  
-  return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-nsDocShell::GetCanvasHasFocus(PRBool *aCanvasHasFocus)
-{
-  return NS_ERROR_FAILURE;
-}
-
 /* boolean IsBeingDestroyed (); */
 NS_IMETHODIMP 
 nsDocShell::IsBeingDestroyed(PRBool *aDoomed)
 {
   NS_ENSURE_ARG(aDoomed);
   *aDoomed = mIsBeingDestroyed;
   return NS_OK;
 }
@@ -10245,46 +10024,16 @@ nsRefreshTimer::Notify(nsITimer * aTimer
         PRUint32 delay = 0;
         aTimer->GetDelay(&delay);
         mDocShell->ForceRefreshURIFromTimer(mURI, delay, mMetaRefresh, aTimer);
     }
     return NS_OK;
 }
 
 //*****************************************************************************
-//***    nsDocShellFocusController: Object Management
-//*****************************************************************************
-void 
-nsDocShellFocusController::Focus(nsIDocShell* aDocShell)
-{
-#ifdef DEBUG_DOCSHELL_FOCUS
-  printf("****** nsDocShellFocusController Focus To: %p  Blur To: %p\n",
-         (void*)aDocShell, (void*)mFocusedDocShell);
-#endif
-
-  if (aDocShell != mFocusedDocShell) {
-    if (mFocusedDocShell) {
-      mFocusedDocShell->SetHasFocus(PR_FALSE);
-    }
-    mFocusedDocShell = aDocShell;
-  }
-
-}
-
-//--------------------------------------------------
-// This is need for when the document with focus goes away
-void 
-nsDocShellFocusController::ClosingDown(nsIDocShell* aDocShell)
-{
-  if (aDocShell == mFocusedDocShell) {
-    mFocusedDocShell = nsnull;
-  }
-}
-
-//*****************************************************************************
 // nsDocShell::InterfaceRequestorProxy
 //*****************************************************************************
 nsDocShell::InterfaceRequestorProxy::InterfaceRequestorProxy(nsIInterfaceRequestor* p)
 {
     if (p) {
         mWeakPtr = do_GetWeakReference(p);
     }
 }
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -723,18 +723,16 @@ protected:
     PRInt32                    mLoadedTransIndex;
 
     PRPackedBool               mAllowSubframes;
     PRPackedBool               mAllowPlugins;
     PRPackedBool               mAllowJavascript;
     PRPackedBool               mAllowMetaRedirects;
     PRPackedBool               mAllowImages;
     PRPackedBool               mAllowDNSPrefetch;
-    PRPackedBool               mFocusDocFirst;
-    PRPackedBool               mHasFocus;
     PRPackedBool               mCreatingDocument; // (should be) debugging only
     PRPackedBool               mUseErrorPages;
     PRPackedBool               mObserveErrorPages;
     PRPackedBool               mAllowAuth;
     PRPackedBool               mAllowKeywordFixup;
     PRPackedBool               mIsOffScreenBrowser;
 
     // This boolean is set to true right before we fire pagehide and generally
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -64,17 +64,17 @@ interface nsISimpleEnumerator;
 interface nsIInputStream;
 interface nsIRequest;
 interface nsISHEntry;
 interface nsILayoutHistoryState;
 interface nsISecureBrowserUI;
 interface nsIDOMStorage;
 interface nsIPrincipal;
 
-[scriptable, uuid(3156f677-f444-4c3e-a47f-b47e568eafd6)]
+[scriptable, uuid(8ADFB831-1053-4A19-884D-BCDAD7277B4B)]
 interface nsIDocShell : nsISupports
 {
   /**
    * Loads a given URI.  This will give priority to loading the requested URI
    * in the object implementing	this interface.  If it can't be loaded here
    * however, the URL dispatcher will go through its normal process of content
    * loading.
    *
@@ -315,26 +315,16 @@ interface nsIDocShell : nsISupports
    * The size, in CSS pixels, of the vertical margins for the <body> of an HTML
    * document in this docshel; used to implement the marginheight attribute on
    * HTML <frame>/<iframe> elements.  A value smaller than zero indicates that
    * the attribute was not set.
    */
   attribute long marginHeight;
 
   /*
-   * Tells the DocShell that it now has focus or has lost focus
-   */
-  attribute boolean hasFocus;
-
-  /*
-   * Tells the docshell whether the canvas should have focus
-   */
-  attribute boolean canvasHasFocus;
-
-  /*
    * Tells the docshell to offer focus to its tree owner.
    * This is currently only necessary for embedding chrome.
    */
   void tabToTreeOwner(in boolean forward,
                       out boolean tookFocus);
 
   /**
    * Current busy state for DocShell
--- a/docshell/test/chrome/test_bug454235.xul
+++ b/docshell/test/chrome/test_bug454235.xul
@@ -27,19 +27,16 @@ addLoadEvent(doTest);
 
 function doTest() {
   var shownBrowser = document.getElementById("shownBrowser");
   var hiddenBrowser = document.getElementById("hiddenBrowser");
   var offScreenBrowser = document.getElementById("offScreenBrowser");
   var offScreenSubBrowser = offScreenBrowser.contentDocument.getElementById("topBrowser");
   var offScreenBurriedBrowser = offScreenBrowser.contentDocument.getElementById("burriedBrowser");
   
-  shownBrowser.contentWindow.focus();
-  ok(shownBrowser.contentDocument.hasFocus(), "visible browser is not visible");  
-
   hiddenBrowser.contentWindow.focus();
   ok(!hiddenBrowser.contentDocument.hasFocus(),"hidden browser is visible");
 
   offScreenBrowser.docShell.isOffScreenBrowser = true;
   offScreenBrowser.contentWindow.focus();
   ok(offScreenBrowser.contentDocument.hasFocus(),"offscreen browser is not visible");
 
   offScreenSubBrowser.wrappedJSObject.contentWindow.focus();
@@ -49,14 +46,13 @@ function doTest() {
   ok(!offScreenBurriedBrowser.wrappedJSObject.contentDocument.hasFocus(),"hidden browser in offscreen browser is visible");
 
   SimpleTest.finish();
 }
 
 
 
   ]]></script>
-  <deck flex="1" style="border:5px black solid">
-    <browser style="border:5px green solid" id="shownBrowser" src="bug454235-subframe.xul"/>
+  <box flex="1" style="visibility: hidden; border:5px black solid">
     <browser style="border:5px blue solid" id="hiddenBrowser" src="bug454235-subframe.xul"/>
     <browser style="border:5px yellow solid" id="offScreenBrowser" src="bug454235-subframe.xul"/>
-  </deck>
+  </box>
 </window>
--- a/dom/base/Makefile.in
+++ b/dom/base/Makefile.in
@@ -71,26 +71,28 @@ EXPORTS = \
   nsIScriptGlobalObjectOwner.h \
   nsIScriptNameSpaceManager.h \
   nsIScriptObjectOwner.h \
   nsIScriptObjectPrincipal.h \
   nsIScriptRuntime.h \
   nsIScriptTimeoutHandler.h \
   nsPIDOMWindow.h \
   nsPIWindowRoot.h \
+  nsFocusManager.h \
   nsWrapperCache.h \
   $(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		\
 	nsMimeTypeArray.cpp	\
--- a/dom/base/crashtests/473284.xul
+++ b/dom/base/crashtests/473284.xul
@@ -81,13 +81,13 @@ try {
 
 try {
   document.commandDispatcher.focusedWindow = window;
   result += 'c';
 } catch (ex) {
   result += '.';
 }
 
-document.documentElement.textContent = result == '.23.56.89abc' ? 'PASSED' : 'FAILED';
+document.documentElement.textContent = result == '.23.56.89.bc' ? 'PASSED' : 'FAILED';
 if (document.documentElement.textContent == 'PASSED') {
   document.documentElement.removeAttribute('class');
 }
 "/>
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -39,17 +39,17 @@
 #include "nsPresContext.h"
 #include "nsDOMClassInfo.h"
 #include "nsDOMError.h"
 #include "nsIDOMNSEvent.h"
 
 #include "nsDOMWindowUtils.h"
 #include "nsGlobalWindow.h"
 #include "nsIDocument.h"
-#include "nsIFocusController.h"
+#include "nsFocusManager.h"
 #include "nsIEventStateManager.h"
 
 #include "nsIScrollableView.h"
 
 #include "nsContentUtils.h"
 
 #include "nsIFrame.h"
 #include "nsIWidget.h"
@@ -445,27 +445,22 @@ nsDOMWindowUtils::GetWidget(nsPoint* aOf
 NS_IMETHODIMP
 nsDOMWindowUtils::Focus(nsIDOMElement* aElement)
 {
   PRBool hasCap = PR_FALSE;
   if (NS_FAILED(nsContentUtils::GetSecurityManager()->IsCapabilityEnabled(
     "UniversalXPConnect", &hasCap)) || !hasCap)
     return NS_ERROR_DOM_SECURITY_ERR;
 
-  nsPresContext* pc = GetPresContext();
-  if (pc) {
-    nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
-    if (content) {
-      nsCOMPtr<nsIDocument> doc(do_QueryInterface(mWindow->GetExtantDocument()));
-      if (!doc || content->GetCurrentDoc() != doc)
-        return NS_ERROR_FAILURE;
-    }
-
-    pc->EventStateManager()->ChangeFocusWith(content,
-        nsIEventStateManager::eEventFocusedByApplication);
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+  if (fm) {
+    if (aElement)
+      fm->SetFocus(aElement, 0);
+    else
+      fm->ClearFocus(mWindow);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GarbageCollect()
 {
--- a/dom/base/nsFocusController.cpp
+++ b/dom/base/nsFocusController.cpp
@@ -43,390 +43,109 @@
 #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 "nsPresContext.h"
-#include "nsIPresShell.h"
-#include "nsIScriptGlobalObject.h"
 #include "nsPIDOMWindow.h"
 #include "nsFocusController.h"
 #include "prlog.h"
-#include "nsIDOMEventTarget.h"
-#include "nsIEventStateManager.h"
-#include "nsIDocShell.h"
-#include "nsIBaseWindow.h"
-#include "nsIWindowWatcher.h"
-#include "nsIDocShellTreeItem.h"
-#include "nsIDocShellTreeOwner.h"
-#include "nsIInterfaceRequestorUtils.h"
-#include "nsServiceManagerUtils.h"
 #include "nsGlobalWindow.h"
+#include "nsFocusManager.h"
 
 #ifdef MOZ_XUL
 #include "nsIDOMXULDocument.h"
 #include "nsIDOMXULElement.h"
 #endif
 
 ////////////////////////////////////////////////////////////////////////
 
-nsFocusController::nsFocusController(void)
-: mSuppressFocus(0), 
-  mSuppressFocusScroll(PR_FALSE), 
-  mActive(PR_FALSE),
-  mUpdateWindowWatcher(PR_FALSE),
-  mNeedUpdateCommands(PR_FALSE)
-{
-}
-
-nsFocusController::~nsFocusController(void)
-{
-}
-
 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(nsIDOMFocusListener)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
   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(mCurrentElement)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPreviousElement)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCurrentWindow)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPreviousWindow)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPopupNode)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 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;
 }
 
-
-////////////////////////////////////////////////////////////////
-// nsIFocusController Interface
-
-NS_IMETHODIMP
-nsFocusController::GetFocusedElement(nsIDOMElement** aElement)
-{
-  *aElement = mCurrentElement;
-  NS_IF_ADDREF(*aElement);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsFocusController::GetFocusedWindow(nsIDOMWindowInternal** aWindow)
-{
-  *aWindow = mCurrentWindow;
-  NS_IF_ADDREF(*aWindow);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsFocusController::SetFocusedElement(nsIDOMElement* aElement)
-{
-  if (aElement) {
-    nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
-    NS_ENSURE_ARG(content);
-  }
-  if (mCurrentElement) 
-    mPreviousElement = mCurrentElement;
-  else if (aElement) 
-    mPreviousElement = aElement;
-
-  mNeedUpdateCommands = mNeedUpdateCommands || mCurrentElement != aElement;
-  mCurrentElement = aElement;
-
-  if (!mSuppressFocus) {
-    // Need to update focus commands when focus switches from
-    // an element to no element, so don't test mCurrentElement
-    // before updating.
-    UpdateCommands();
-  }
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsFocusController::RewindFocusState()
-{
-  mCurrentElement = mPreviousElement;
-  mCurrentWindow = mPreviousWindow;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsFocusController::SetFocusedWindow(nsIDOMWindowInternal* aWindow)
-{
-  nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(aWindow);
-
-  if (win) {
-    win = win->GetOuterWindow();
-  }
-
-  NS_ASSERTION(!win || !win->IsInnerWindow(),
-               "Uh, inner window can't have focus!");
-
-  if (win && (mCurrentWindow != win)) {
-    nsCOMPtr<nsIBaseWindow> basewin = do_QueryInterface(win->GetDocShell());
-    if (basewin)
-      basewin->SetFocus();
-  }
-
-  if (mCurrentWindow) {
-    mPreviousWindow = mCurrentWindow;
-  } else if (win) {
-    mPreviousWindow = win;
-  }
-
-  mNeedUpdateCommands = mNeedUpdateCommands || mCurrentWindow != win;
-  mCurrentWindow = win;
-
-  if (mUpdateWindowWatcher) {
-    NS_ASSERTION(mActive, "This shouldn't happen");
-    if (mCurrentWindow)
-      UpdateWWActiveWindow();
-    mUpdateWindowWatcher = PR_FALSE;
-  }
-
-  return NS_OK;
-}
-
-
-void
-nsFocusController::UpdateCommands()
-{
-  if (!mNeedUpdateCommands) {
-    return;
-  }
-  nsCOMPtr<nsIDOMWindowInternal> window;
-  nsCOMPtr<nsIDocument> doc;
-  if (mCurrentWindow) {
-    window = mCurrentWindow;
-    nsCOMPtr<nsIDOMWindow> domWin(do_QueryInterface(window));
-    nsCOMPtr<nsIDOMDocument> domDoc;
-    domWin->GetDocument(getter_AddRefs(domDoc));
-    doc = do_QueryInterface(domDoc);
-  }
-  else if (mCurrentElement) {
-    nsCOMPtr<nsIDOMDocument> domDoc;
-    mCurrentElement->GetOwnerDocument(getter_AddRefs(domDoc));
-    if (domDoc) {
-      doc = do_QueryInterface(domDoc);
-      window = do_QueryInterface(doc->GetScriptGlobalObject());
-    }
-  }
-
-  // If there is no presshell, it's a zombie document which can't handle the command updates
-  if (window && doc && doc->GetPrimaryShell()) {
-    // Not a zombie document, so we can handle the command update
-    window->UpdateCommands(NS_LITERAL_STRING("focus"));
-    mNeedUpdateCommands = PR_FALSE;
-  }
-}
-
-  
 NS_IMETHODIMP
 nsFocusController::GetControllers(nsIControllers** aResult)
 {
   // 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.
-  if (mCurrentElement) {
+  nsCOMPtr<nsIDOMElement> focusedElement;
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+  if (fm)
+    fm->GetFocusedElement(getter_AddRefs(focusedElement));
 
+  if (focusedElement) {
 #ifdef MOZ_XUL
-    nsCOMPtr<nsIDOMXULElement> xulElement(do_QueryInterface(mCurrentElement));
+    nsCOMPtr<nsIDOMXULElement> xulElement(do_QueryInterface(focusedElement));
     if (xulElement)
       return xulElement->GetControllers(aResult);
 #endif
 
     nsCOMPtr<nsIDOMNSHTMLTextAreaElement> htmlTextArea =
-      do_QueryInterface(mCurrentElement);
+      do_QueryInterface(focusedElement);
     if (htmlTextArea)
       return htmlTextArea->GetControllers(aResult);
 
     nsCOMPtr<nsIDOMNSHTMLInputElement> htmlInputElement =
-      do_QueryInterface(mCurrentElement);
+      do_QueryInterface(focusedElement);
     if (htmlInputElement)
       return htmlInputElement->GetControllers(aResult);
 
-    nsCOMPtr<nsIContent> content = do_QueryInterface(mCurrentElement);
+    nsCOMPtr<nsIContent> content = do_QueryInterface(focusedElement);
     if (content && content->IsEditable()) {
       // Move up to the window.
       nsCOMPtr<nsIDOMDocument> domDoc;
-      mCurrentElement->GetOwnerDocument(getter_AddRefs(domDoc));
+      focusedElement->GetOwnerDocument(getter_AddRefs(domDoc));
       nsCOMPtr<nsIDOMWindowInternal> domWindow =
         do_QueryInterface(GetWindowFromDocument(domDoc));
       if (domWindow)
         return domWindow->GetControllers(aResult);
     }
   }
-  else if (mCurrentWindow) {
-    nsCOMPtr<nsIDOMWindowInternal> domWindow =
-      do_QueryInterface(mCurrentWindow);
+  else {
+    nsCOMPtr<nsIDOMWindow> focusedWindow;
+    fm->GetFocusedWindow(getter_AddRefs(focusedWindow));
+    nsCOMPtr<nsIDOMWindowInternal> domWindow = do_QueryInterface(focusedWindow);
     if (domWindow)
       return domWindow->GetControllers(aResult);
   }
 
   *aResult = nsnull;
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsFocusController::MoveFocus(PRBool aForward, nsIDOMElement* aElt)
-{
-  // Obtain the doc that we'll be shifting focus inside.
-  nsCOMPtr<nsIDocument> doc;
-  nsCOMPtr<nsIContent> content;
-  if (aElt) {
-    content = do_QueryInterface(aElt);
-    NS_ENSURE_ARG(content);
-    doc = content->GetDocument();
-  }
-  else {
-    if (mCurrentElement) {
-      content = do_QueryInterface(mCurrentElement);
-      doc = content->GetDocument();
-      content = nsnull;
-    }
-    else if (mCurrentWindow) {
-      nsCOMPtr<nsIDOMDocument> domDoc;
-      mCurrentWindow->GetDocument(getter_AddRefs(domDoc));
-      doc = do_QueryInterface(domDoc);
-    }
-  }
-
-  if (!doc) {
-    // No way to obtain an event state manager.  Give up.
-    return NS_ERROR_FAILURE;
-  }
-
-  nsIPresShell *shell = doc->GetPrimaryShell();
-  if (!shell)
-    return NS_ERROR_FAILURE;
-
-  // Make sure frames have been constructed before shifting focus, bug 273092.
-  shell->FlushPendingNotifications(Flush_Frames);
-
-  // Retrieve the context
-  nsCOMPtr<nsPresContext> presContext = shell->GetPresContext();
-
-  // Make this ESM shift the focus per our instructions.
-  return presContext->EventStateManager()->ShiftFocus(aForward, content);
-}
-
-/////
-// nsIDOMFocusListener
-/////
-
-nsresult 
-nsFocusController::Focus(nsIDOMEvent* aEvent)
-{
-  if (mSuppressFocus)
-    return NS_OK;
-
-  nsCOMPtr<nsIDOMEventTarget> t;
-
-  nsCOMPtr<nsIDOMNSEvent> nsevent(do_QueryInterface(aEvent));
-  if (nsevent) {
-    nsevent->GetOriginalTarget(getter_AddRefs(t));
-  }
-
-  nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(t);
-  if (domElement && (domElement != mCurrentElement)) {
-    SetFocusedElement(domElement);
-
-    // Also set focus to our innermost window.
-    // XXX Must be done for the Ender case, since ender causes a blur,
-    // but we don't hear the subsequent focus to the Ender window.
-    nsCOMPtr<nsIDOMDocument> ownerDoc;
-    domElement->GetOwnerDocument(getter_AddRefs(ownerDoc));
-    nsCOMPtr<nsIDOMWindowInternal> domWindow = GetWindowFromDocument(ownerDoc);
-    if (domWindow)
-      SetFocusedWindow(domWindow);
-  }
-  else {
-    // We're focusing a window.  We only want to do an update commands
-    // if no element is focused.
-    nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(t);
-    if (domDoc) {
-      nsCOMPtr<nsIDOMWindowInternal> domWindow = GetWindowFromDocument(domDoc);
-      if (domWindow) {
-        SetFocusedWindow(domWindow);
-        if (mCurrentElement) {
-          // Make sure this element is in our window. If not, we
-          // should clear this field.
-          nsCOMPtr<nsIDOMDocument> ownerDoc;
-          mCurrentElement->GetOwnerDocument(getter_AddRefs(ownerDoc));
-          nsCOMPtr<nsIDOMDocument> windowDoc;
-          mCurrentWindow->GetDocument(getter_AddRefs(windowDoc));
-          if (ownerDoc != windowDoc)
-            mCurrentElement = mPreviousElement = nsnull;
-        }
-        else
-          mPreviousElement = nsnull;
-
-        if (!mCurrentElement) {
-          UpdateCommands();
-        }
-      }
-    }
-  }
-
-  return NS_OK;
-}
-
-nsresult 
-nsFocusController::Blur(nsIDOMEvent* aEvent)
-{
-  if (mSuppressFocus)
-    return NS_OK;
-
-  nsCOMPtr<nsIDOMEventTarget> t;
-
-  nsCOMPtr<nsIDOMNSEvent> nsevent(do_QueryInterface(aEvent));
-
-  if (nsevent) {
-    nsevent->GetOriginalTarget(getter_AddRefs(t));
-  }
-
-  nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(t);
-  if (domElement) {
-    SetFocusedElement(nsnull);
-  }
-  
-  nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(t);
-  if (domDoc) {
-    nsCOMPtr<nsIDOMWindowInternal> domWindow = GetWindowFromDocument(domDoc);
-    if (domWindow)
-      SetFocusedWindow(nsnull);
-  }
-
-  return NS_OK;
-}
 
 nsPIDOMWindow *
 nsFocusController::GetWindowFromDocument(nsIDOMDocument* aDocument)
 {
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDocument);
   if (!doc)
     return nsnull;
 
@@ -446,165 +165,51 @@ nsFocusController::GetControllerForComma
   GetControllers(getter_AddRefs(controllers));
   if(controllers) {
     controllers->GetControllerForCommand(aCommand, getter_AddRefs(controller));
     if(controller) {
       controller.swap(*_retval);
       return NS_OK;
     }
   }
-  
-  nsCOMPtr<nsPIDOMWindow> currentWindow;
-  if (mCurrentElement) {
-    // Move up to the window.
-    nsCOMPtr<nsIDOMDocument> domDoc;
-    mCurrentElement->GetOwnerDocument(getter_AddRefs(domDoc));
-    currentWindow = do_QueryInterface(GetWindowFromDocument(domDoc));
+
+  nsCOMPtr<nsIDOMElement> focusedElement;
+  nsCOMPtr<nsIDOMWindow> focusedWindow;
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+  if (fm) {
+    fm->GetFocusedElement(getter_AddRefs(focusedElement));
+    fm->GetFocusedWindow(getter_AddRefs(focusedWindow));
   }
-  else if (mCurrentWindow) {
-    nsGlobalWindow *win =
-      static_cast<nsGlobalWindow *>
-                 (static_cast<nsIDOMWindowInternal *>(mCurrentWindow));
-    currentWindow = win->GetPrivateParent();
-  }
-  else return NS_OK;
 
-  while(currentWindow) {
-    nsCOMPtr<nsIDOMWindowInternal> domWindow(do_QueryInterface(currentWindow));
+  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 *>(currentWindow));
-    currentWindow = win->GetPrivateParent();
+                 (static_cast<nsIDOMWindowInternal *>(piWindow));
+    focusedWindow = win->GetPrivateParent();
   }
   
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsFocusController::GetSuppressFocusScroll(PRBool* aSuppressFocusScroll)
-{
-  *aSuppressFocusScroll = mSuppressFocusScroll;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsFocusController::SetSuppressFocusScroll(PRBool aSuppressFocusScroll)
-{
-  mSuppressFocusScroll = aSuppressFocusScroll;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsFocusController::GetSuppressFocus(PRBool* aSuppressFocus)
-{
-  *aSuppressFocus = (mSuppressFocus > 0);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsFocusController::SetSuppressFocus(PRBool aSuppressFocus, const char* aReason)
-{
-  if(aSuppressFocus) {
-    ++mSuppressFocus;
-    //#ifdef DEBUG_hyatt
-    //printf("[%p] SuppressFocus incremented to %d. The reason is %s.\n", this, mSuppressFocus, aReason);
-    //#endif
-  }
-  else if(mSuppressFocus > 0) {
-    --mSuppressFocus;
-    //#ifdef DEBUG_hyatt
-    //printf("[%p] SuppressFocus decremented to %d. The reason is %s.\n", this, mSuppressFocus, aReason);
-    //#endif
-  }
-  else 
-    // It's ok to unsuppress even if no suppression is active (bug 112294)
-    return NS_OK;
-
-  // we are unsuppressing after activating, so update focus-related commands
-  // we need this to update command, including the case where there is no element
-  // because nsPresShell::UnsuppressPainting may have just now unsuppressed
-  // focus on the currently focused window
-  if (!mSuppressFocus) {
-    // Always update commands if we have a current element
-    // and mNeedUpdateCommands is true (checked in nsFC::UpdateCommands)
-    UpdateCommands();
-  }
-  
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsFocusController::GetActive(PRBool* aActive)
-{
-  *aActive = mActive;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsFocusController::SetActive(PRBool aActive)
-{
-  mActive = aActive;
-
-  // We may be activated before we ever have a focused window set.
-  // This happens on window creation, where the FocusController
-  // is activated just prior to setting the focused window.
-  // (see nsEventStateManager::PreHandleEvent/NS_ACTIVATE)
-  // If this is the case, we need to queue a notification of the
-  // WindowWatcher until SetFocusedWindow is called.
-  if (mActive) {
-    if (mCurrentWindow)
-      UpdateWWActiveWindow();
-    else
-      mUpdateWindowWatcher = PR_TRUE;
-  } else
-    mUpdateWindowWatcher = PR_FALSE;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsFocusController::ResetElementFocus()
-{
-  mCurrentElement = mPreviousElement = nsnull;
-  return NS_OK;
-}
-
-void
-nsFocusController::UpdateWWActiveWindow()
-{
-  // Inform the window watcher of the new active window.
-  nsCOMPtr<nsIWindowWatcher> wwatch = do_GetService("@mozilla.org/embedcomp/window-watcher;1");
-  if (!wwatch) return;
-
-  // This gets the toplevel DOMWindow
-  nsCOMPtr<nsIDocShellTreeItem> docShellAsItem =
-    do_QueryInterface(mCurrentWindow->GetDocShell());
-  if (!docShellAsItem) return;
-
-  nsCOMPtr<nsIDocShellTreeItem> rootItem;
-  docShellAsItem->GetRootTreeItem(getter_AddRefs(rootItem));
-  NS_ASSERTION(rootItem, "Invalid docshell tree - no root!");
-
-  nsCOMPtr<nsIDOMWindow> domWin = do_GetInterface(rootItem);
-  wwatch->SetActiveWindow(domWin);
-}
-
-NS_IMETHODIMP
 nsFocusController::GetPopupNode(nsIDOMNode** aNode)
 {
 #ifdef DEBUG_dr
   printf("dr :: nsFocusController::GetPopupNode\n");
 #endif
 
   *aNode = mPopupNode;
   NS_IF_ADDREF(*aNode);
--- a/dom/base/nsFocusController.h
+++ b/dom/base/nsFocusController.h
@@ -50,81 +50,35 @@
 #include "nsCycleCollectionParticipant.h"
 
 class nsIDOMElement;
 class nsIDOMWindow;
 class nsPIDOMWindow;
 class nsIController;
 class nsIControllers;
 
-class nsFocusController : public nsIFocusController, 
-                          public nsIDOMFocusListener,
+class nsFocusController : public nsIFocusController,
                           public nsSupportsWeakReference
 {
 public:
   static NS_IMETHODIMP Create(nsIFocusController** aResult);
 
-protected:
-  nsFocusController(void);
-  virtual ~nsFocusController(void);
-
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
-  NS_IMETHOD GetFocusedElement(nsIDOMElement** aResult);
-  NS_IMETHOD SetFocusedElement(nsIDOMElement* aElement);
-
-  NS_IMETHOD GetFocusedWindow(nsIDOMWindowInternal** aResult);
-  NS_IMETHOD SetFocusedWindow(nsIDOMWindowInternal* aResult);
-
-  NS_IMETHOD GetSuppressFocus(PRBool* aSuppressFlag);
-  NS_IMETHOD SetSuppressFocus(PRBool aSuppressFlag, const char* aReason);
-
-  NS_IMETHOD GetSuppressFocusScroll(PRBool* aSuppressFlag);
-  NS_IMETHOD SetSuppressFocusScroll(PRBool aSuppressFlag);
-  
-  NS_IMETHOD GetActive(PRBool* aActive);
-  NS_IMETHOD SetActive(PRBool aActive);
-
   NS_IMETHOD GetPopupNode(nsIDOMNode** aNode);
   NS_IMETHOD SetPopupNode(nsIDOMNode* aNode);
 
   NS_IMETHOD GetControllerForCommand(const char *aCommand, nsIController** aResult);
   NS_IMETHOD GetControllers(nsIControllers** aResult);
 
-  NS_IMETHOD MoveFocus(PRBool aForward, nsIDOMElement* aElt);
-  NS_IMETHOD RewindFocusState();
-
-  NS_IMETHOD ResetElementFocus();
-
-  // nsIDOMFocusListener
-  NS_IMETHOD Focus(nsIDOMEvent* aEvent);
-  NS_IMETHOD Blur(nsIDOMEvent* aEvent);
-
-  // nsIDOMEventListener
-  NS_IMETHOD HandleEvent(nsIDOMEvent* anEvent) { return NS_OK; }
-
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFocusController,
                                            nsIFocusController)
 
-protected:
-  void UpdateCommands();
-  void UpdateWWActiveWindow();
-
 public: