diff --git a/dom/public/idl/base/nsIDOMWindowUtils.idl b/dom/public/idl/base/nsIDOMWindowUtils.idl index 0b0db5f1b67..18792cd4895 100644 --- a/dom/public/idl/base/nsIDOMWindowUtils.idl +++ b/dom/public/idl/base/nsIDOMWindowUtils.idl @@ -45,7 +45,9 @@ * getInterface on a DOMWindow. */ -[scriptable, uuid(76cdfff8-6f13-43e8-9ed4-36066cd83742)] +interface nsIDOMElement; + +[scriptable, uuid(1F313394-73AB-41BF-8307-9FC5DA8A481E)] interface nsIDOMWindowUtils : nsISupports { /** @@ -126,4 +128,13 @@ interface nsIDOMWindowUtils : nsISupports { in long aKeyCode, in long aCharCode, in long aModifiers); + + /** + * Focus the element aElement. The element should be in the same document + * that the window is displaying. Pass null to blur the element, if any, + * that currently has focus, and focus the document. + * + * @param aElement the element to focus + */ + void focus(in nsIDOMElement aElement); }; diff --git a/dom/src/base/nsDOMWindowUtils.cpp b/dom/src/base/nsDOMWindowUtils.cpp index 560342bab9e..8330bbd6663 100644 --- a/dom/src/base/nsDOMWindowUtils.cpp +++ b/dom/src/base/nsDOMWindowUtils.cpp @@ -45,6 +45,7 @@ #include "nsGlobalWindow.h" #include "nsIDocument.h" #include "nsIFocusController.h" +#include "nsIEventStateManager.h" #include "nsContentUtils.h" @@ -270,3 +271,32 @@ nsDOMWindowUtils::GetWidget() return nsnull; } + +NS_IMETHODIMP +nsDOMWindowUtils::Focus(nsIDOMElement* aElement) +{ + if (mWindow) { + nsCOMPtr content = do_QueryInterface(aElement); + if (content) { + nsCOMPtr doc(do_QueryInterface(mWindow->GetExtantDocument())); + if (!doc || content->GetCurrentDoc() != doc) + return NS_ERROR_FAILURE; + } + + nsIDocShell *docShell = mWindow->GetDocShell(); + if (docShell) { + nsCOMPtr presShell; + docShell->GetPresShell(getter_AddRefs(presShell)); + if (presShell) { + nsPresContext *pc = presShell->GetPresContext(); + if (pc) { + pc->EventStateManager()->ChangeFocusWith(content, + nsIEventStateManager::eEventFocusedByApplication); + } + } + } + } + + return NS_OK; +} + diff --git a/toolkit/content/widgets/tabbrowser.xml b/toolkit/content/widgets/tabbrowser.xml index 4117f1f3113..77b49126533 100644 --- a/toolkit/content/widgets/tabbrowser.xml +++ b/toolkit/content/widgets/tabbrowser.xml @@ -695,7 +695,15 @@ // 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 - this.mCurrentBrowser.focusedElement.blur(); + 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"); } @@ -801,7 +809,16 @@ .getService(Components.interfaces.nsIWindowWatcher); if (ww.activeWindow == window) { cmdDispatcher.suppressFocusScroll = true; - whatToFocus.focus(); + 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 {