--- 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:
static nsPIDOMWindow *GetWindowFromDocument(nsIDOMDocument* aElement);
// Members
protected:
- nsCOMPtr<nsIDOMElement> mCurrentElement; // [OWNER]
- nsCOMPtr<nsIDOMElement> mPreviousElement; // [OWNER]
- nsCOMPtr<nsPIDOMWindow> mCurrentWindow; // [OWNER]
- nsCOMPtr<nsPIDOMWindow> mPreviousWindow; // [OWNER]
nsCOMPtr<nsIDOMNode> mPopupNode; // [OWNER]
-
- PRUint32 mSuppressFocus;
- PRPackedBool mSuppressFocusScroll;
- PRPackedBool mActive;
- PRPackedBool mUpdateWindowWatcher;
- PRPackedBool mNeedUpdateCommands;
};
#endif // nsFocusContro