diff --git a/mozilla/content/events/public/nsIEventStateManager.h b/mozilla/content/events/public/nsIEventStateManager.h index 2f43b409ad0..f4ee9e765a8 100644 --- a/mozilla/content/events/public/nsIEventStateManager.h +++ b/mozilla/content/events/public/nsIEventStateManager.h @@ -49,7 +49,6 @@ class nsIDOMEvent; class nsIFrame; class nsIView; class nsIWidget; -class nsIDocument; /* * Event listener manager interface. @@ -91,19 +90,10 @@ public: NS_IMETHOD GetFocusedContent(nsIContent **aContent) = 0; NS_IMETHOD SetFocusedContent(nsIContent* aContent) = 0; - virtual PRBool ChangeFocus(nsIContent* aFocus, nsIFrame* aFocusFrame, PRBool aSetFocus) = 0; NS_IMETHOD GetNextTabbableContent(nsIContent* aRootContent, nsIFrame* aFrame, PRBool forward, nsIContent** aResult) = 0; - NS_IMETHOD GetNextTabbableIndexContent(nsIContent* aRootContent, - PRBool forward, - PRBool aStartOver, - nsIContent** aResult) = 0; - - NS_IMETHOD HasPositiveTabIndex(nsIContent* aContent, - PRBool* aResult) = 0; - - // This is an experiement and may be temporary + // This is an experiment and may be temporary NS_IMETHOD ConsumeFocusEvents(PRBool aDoConsume) = 0; // Access Key Registration @@ -116,11 +106,7 @@ public: NS_IMETHOD DispatchNewEvent(nsISupports* aTarget, nsIDOMEvent* aEvent, PRBool* aPreventDefault) = 0; // Method for moving the focus forward/back. - NS_IMETHOD MoveFocus(PRBool aDirection, nsIContent* aRoot)=0; - - //-- Special Enums needed for DocShell Identification - enum eDocType {eChrome = 0, eGenericContent, eFrameSet, eFrame, eIFrame}; - NS_IMETHOD FigureOutKindOfDoc(nsIDocument* aDoc, eDocType* aDocType) = 0; + NS_IMETHOD ShiftFocus(PRBool aDirection, nsIContent* aStart)=0; }; diff --git a/mozilla/content/events/src/nsEventStateManager.cpp b/mozilla/content/events/src/nsEventStateManager.cpp index 2c5a924649c..d02e43af018 100644 --- a/mozilla/content/events/src/nsEventStateManager.cpp +++ b/mozilla/content/events/src/nsEventStateManager.cpp @@ -37,7 +37,6 @@ * ***** END LICENSE BLOCK ***** */ #include "nsCOMPtr.h" -#include "nsIEventStateManager.h" #include "nsEventStateManager.h" #include "nsIContent.h" #include "nsIDocument.h" @@ -74,6 +73,7 @@ #include "nsIEnumerator.h" #include "nsFrameTraversal.h" #include "nsIDocShellTreeItem.h" +#include "nsIDocShellTreeNode.h" #include "nsIWebNavigation.h" #include "nsIContentViewer.h" @@ -101,16 +101,9 @@ #include "nsIFrameTraversal.h" #include "nsLayoutCID.h" -#include "nsHTMLAtoms.h" -#include "nsXULAtoms.h" -#include "nsIDOMHTMLFormElement.h" -#include "nsIDOMHTMLFrameSetElement.h" -#include "nsIDOMHTMLFrameElement.h" -#include "nsIDOMHTMLIFrameElement.h" -#include "nsIDocShellTreeItem.h" -#include "nsIDocShellTreeNode.h" +#include "nsIInterfaceRequestorUtils.h" -#ifdef DEBUG_rods +#if defined(DEBUG_rods) || defined(DEBUG_bryner) //#define DEBUG_DOCSHELL_FOCUS #endif @@ -742,7 +735,7 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext, //Its hard to say what HTML4 wants us to do in all cases. So for now we'll settle for //A) Set focus - ChangeFocus(content, nsnull, PR_TRUE); + ChangeFocus(content); nsresult rv = getPrefService(); PRBool activate = PR_TRUE; @@ -1457,9 +1450,8 @@ nsEventStateManager::GetParentScrollingView(nsMouseScrollEvent *aEvent, /* now find the content node in our parent docshell's document that corresponds to our docshell */ - nsCOMPtr frameContent = getter_AddRefs(FindContentForDocShell(pPresShell, - rootContent, - ourDS)); + nsCOMPtr frameContent; + pPresShell->FindContentForShell(ourDS, getter_AddRefs(frameContent)); if (!frameContent) return NS_ERROR_FAILURE; /* @@ -1539,7 +1531,7 @@ nsEventStateManager::PostHandleEvent(nsIPresContext* aPresContext, } if (newFocus && currFrame) - ChangeFocus(newFocus, currFrame, PR_TRUE); + ChangeFocus(newFocus); else if (!suppressBlur) { SetContentState(nsnull, NS_EVENT_STATE_FOCUS); } @@ -2530,7 +2522,7 @@ nsEventStateManager::CheckForAndDispatchClick(nsIPresContext* aPresContext, } PRBool -nsEventStateManager::ChangeFocus(nsIContent* aFocusContent, nsIFrame* aTargetFrame, PRBool aSetFocus) +nsEventStateManager::ChangeFocus(nsIContent* aFocusContent) { aFocusContent->SetFocus(mPresContext); MoveCaretToFocus(); @@ -2538,13 +2530,6 @@ nsEventStateManager::ChangeFocus(nsIContent* aFocusContent, nsIFrame* aTargetFra return PR_FALSE; } -NS_IMETHODIMP -nsEventStateManager::MoveFocus(PRBool aDirection, nsIContent* aRoot) -{ - ShiftFocus(aDirection, aRoot); - return NS_OK; -} - //--------------------------------------------------------- // Debug Helpers #ifdef DEBUG_DOCSHELL_FOCUS @@ -2593,256 +2578,210 @@ PrintDocTree(nsIDocShellTreeNode * aParentNode, int aLevel) } } } - -static void -PrintDocTree(nsIDocShellTreeNode * aParentNode) -{ - NS_ASSERTION(aParentNode, "Pointer is null!"); - - nsCOMPtr item(do_QueryInterface(aParentNode)); - nsCOMPtr parentItem; - item->GetParent(getter_AddRefs(parentItem)); - while (parentItem) { - nsCOMPtrtmp; - parentItem->GetParent(getter_AddRefs(tmp)); - if (!tmp) { - break; - } - parentItem = tmp; - } - - if (!parentItem) { - parentItem = do_QueryInterface(aParentNode); - } - - if (parentItem) { - nsCOMPtr parentAsNode(do_QueryInterface(parentItem)); - PrintDocTree(parentAsNode, 0); - } -} #endif // end debug helpers -void -nsEventStateManager::ShiftFocus(PRBool forward, nsIContent* aRoot) +NS_IMETHODIMP +nsEventStateManager::ShiftFocus(PRBool forward, nsIContent* aStart) { - nsCOMPtr docShell; - if (mPresContext) { - nsCOMPtr pcContainer; - mPresContext->GetContainer(getter_AddRefs(pcContainer)); - if (pcContainer) - docShell = do_QueryInterface(pcContainer); - } - #ifdef DEBUG_DOCSHELL_FOCUS - printf("ShiftFocus DocShell %p Doc: %p\n", docshell.get(), mDocument); + printf("[%p] ShiftFocus: forward=%d, aStart=%p, mCurrentFocus=%p\n", + this, forward, aStart, mCurrentFocus); #endif - - // Indicates whether the document itself (i.e. no content) has focus - PRBool docHasFocus = PR_FALSE; - - if (nsnull == mPresContext) { - return; - } - + NS_ASSERTION(mPresContext, "no pres context"); EnsureDocument(mPresContext); - if (nsnull == mDocument) { - return; - } - - // Figure out what type of document we are - eDocType docType; - FigureOutKindOfDoc(mDocument, &docType); -#ifdef DEBUG_DOCSHELL_FOCUS - printf("Doc Type is [%s]\n", gDocTypeNames[docType]); -#endif - - if (aRoot) { - NS_IF_RELEASE(mCurrentFocus); - mCurrentFocus = aRoot; - NS_ADDREF(mCurrentFocus); - //mCurrentTabIndex = forward ? 1 : 0; - // for frames this needs to be set to 0 - // otherwise it doesn't look for the next content correctly - //if (docType == eFrame) { - mCurrentTabIndex = 0; - //} - } - else if (nsnull == mCurrentFocus) { - mDocument->GetRootContent(&mCurrentFocus); - if (nsnull == mCurrentFocus) { - return; - } - mCurrentTabIndex = forward ? 1 : 0; - docHasFocus = PR_TRUE; - } - - nsIFrame* primaryFrame = nsnull; - nsCOMPtr shell; - if (mPresContext) { - nsresult rv = mPresContext->GetShell(getter_AddRefs(shell)); - if (NS_SUCCEEDED(rv) && shell){ - if (mBrowseWithCaret) { - nsCOMPtr caretFocus; - PRUint32 caretOffset; - GetCaretLocation(getter_AddRefs(caretFocus), &primaryFrame, &caretOffset); - } - else { - shell->GetPrimaryFrameFor(mCurrentFocus, &primaryFrame); - if (docHasFocus) { - // so if we are going backwards then find the last piece of content - // and and look backwards for the last focusable content - if (!forward) { - nsCOMPtr lastContent = getter_AddRefs(GetLastContent(docShell)); - nsCOMPtr iframe(do_QueryInterface(lastContent)); - if (iframe) { - if (FocusWithinHTMLIFrameDoc(lastContent, forward)) { - return; - } - } - shell->GetPrimaryFrameFor(lastContent, &primaryFrame); - } - } - } - } - } - - PRBool doFocusAvailDocShells = PR_FALSE; - nsCOMPtr next; - PRBool hadDocFocus = docHasFocus; + NS_ASSERTION(mDocument, "no document"); nsCOMPtr rootContent; mDocument->GetRootContent(getter_AddRefs(rootContent)); - // Check here to see if the HTMLFrame wants to do anything special - // with the focus. i.e. like focusing a docshell child, or if it - // is the last frame in the frameset, it will pass it on to the Chrome - if (docType == eFrame && aRoot == nsnull) { - if (FocusWithinHTMLFrameDoc(aRoot, shell, forward, doFocusAvailDocShells)) { - return; - } else if (docHasFocus) { - // If we are starting at the top of the document - // first check to see if there is a tabbable index to go to - // - // GetNextTabbableIndexContent may change the value mCurrentTabIndex - // so we remember it here and reset it back if it didn't find anything - PRInt32 currentTabIndex = mCurrentTabIndex; - GetNextTabbableIndexContent(rootContent, forward, PR_TRUE, getter_AddRefs(next)); - if (!next) { - mCurrentTabIndex = currentTabIndex; - } + nsCOMPtr pcContainer; + mPresContext->GetContainer(getter_AddRefs(pcContainer)); + NS_ASSERTION(pcContainer, "no container for presContext"); + + nsCOMPtr docShell = do_QueryInterface(pcContainer); + PRBool docHasFocus = PR_FALSE; - // frames are document first, then content - // so this allows us to call GetNextTabbableContent below - docHasFocus = PR_FALSE; + // allowWrapAround specifies whether shift+tab (when focus is null) + // will start at the end of the document (such as when we're coming + // from an unfocused state), or pop out to the parent document + // (such as when we have "canvas focus") + PRBool allowWrapAround = PR_FALSE; + + if (aStart) { + NS_IF_RELEASE(mCurrentFocus); + mCurrentFocus = aStart; + NS_ADDREF(mCurrentFocus); + + nsAutoString tabIndexStr; + mCurrentFocus->GetAttr(kNameSpaceID_None, nsHTMLAtoms::tabindex, tabIndexStr); + if (!tabIndexStr.IsEmpty()) { + PRInt32 ec, tabIndexVal = tabIndexStr.ToInteger(&ec); + if (NS_SUCCEEDED(ec)) + mCurrentTabIndex = tabIndexVal; + } + } else if (!mCurrentFocus && !mBrowseWithCaret) { + // 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); + if (forward) { + mCurrentFocus = rootContent; + NS_IF_ADDREF(mCurrentFocus); + mCurrentTabIndex = 1; + } else if (!docHasFocus) { + // Only wrap around from the end if we're coming from an + // unfocused state. By not setting curFocusFrame, we will + // cause GetNextTabbableContent to start over at the beginning/end. + + allowWrapAround = PR_TRUE; + mCurrentTabIndex = 0; } } + nsCOMPtr presShell; + mPresContext->GetShell(getter_AddRefs(presShell)); - PRBool docFocusFirst = PR_FALSE; - if (docShell) - docShell->GetFocusDocBeforeContent(&docFocusFirst); + nsIFrame* curFocusFrame = nsnull; - //Get the next tab item. This takes tabIndex into account - if ((docFocusFirst || !docHasFocus) && !next) - GetNextTabbableContent(rootContent, primaryFrame, forward, getter_AddRefs(next)); - - //Either no tabbable items or the end of the document - if (!next) { + if (mBrowseWithCaret) { + nsCOMPtr caretContent; + PRUint32 caretOffset; + GetCaretLocation(getter_AddRefs(caretContent), &curFocusFrame, &caretOffset); + } else if (!allowWrapAround && mCurrentFocus) + presShell->GetPrimaryFrameFor(mCurrentFocus, &curFocusFrame); - // If we've reached the end of the content in this document, we - // focus the document itself before leaving. + nsCOMPtr nextFocus; + if (forward || !docHasFocus) + GetNextTabbableContent(rootContent, curFocusFrame, forward, + getter_AddRefs(nextFocus)); - // Only do this if we're not in document-before-content focus mode + if (nextFocus) { - if (docType == eChrome) { - // if we're a chrome document, act as if the doc has already been - // focused, so we will go back to the beginning. - docHasFocus = PR_TRUE; - } else if (!docHasFocus && !doFocusAvailDocShells && !docFocusFirst) { - PRBool focusDoc = PR_TRUE; + // 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 docShell; - nsCOMPtr parentDS; - if (NS_SUCCEEDED(GetDocShellsFromDoc(mDocument, getter_AddRefs(docShell), getter_AddRefs(parentDS)))) { - if (docType == eFrame) { - if (FocusAfterHTMLFrameDoc(docShell, parentDS, forward)) { - return; - } - } else if (docType == eIFrame) { - if (FocusAfterHTMLIFrameDoc(docShell, parentDS, forward, focusDoc)) { - return; - } - } + nsCOMPtr shellObject; + presShell->GetSubShellFor(nextFocus, getter_AddRefs(shellObject)); + if (shellObject) { + nsCOMPtr subShell = do_QueryInterface(shellObject); + if (subShell) { + SetContentState(nsnull, NS_EVENT_STATE_FOCUS); + + nsIFrame* nextFocusFrame = nsnull; + presShell->GetPrimaryFrameFor(nextFocus, &nextFocusFrame); + presShell->ScrollFrameIntoView(nextFocusFrame, NS_PRESSHELL_SCROLL_ANYWHERE, + NS_PRESSHELL_SCROLL_ANYWHERE); + TabIntoDocument(subShell, forward); } - - // IFrame may or may not want the current document focused - if (focusDoc) { - nsCOMPtr sgo; - mDocument->GetScriptGlobalObject(getter_AddRefs(sgo)); - nsCOMPtr domwin(do_QueryInterface(sgo)); - if (domwin) { - SetContentState(nsnull, NS_EVENT_STATE_FOCUS); - if (NS_SUCCEEDED(domwin->Focus())) - return; - } - } - } - - PRBool focusTaken = PR_FALSE; - SetContentState(nsnull, NS_EVENT_STATE_FOCUS); - - //Offer focus upwards to allow shifting focus to UI controls - nsCOMPtr container; - mPresContext->GetContainer(getter_AddRefs(container)); - nsCOMPtr docShellAsWin(do_QueryInterface(container)); - if (docShellAsWin) { - docShellAsWin->FocusAvailable(docShellAsWin, forward, &focusTaken); + } else { + // there is no subshell, so just focus nextFocus #ifdef DEBUG_DOCSHELL_FOCUS - nsCOMPtr node = do_QueryInterface(container); - PrintDocTree(node); + printf("focusing next focusable content: %p\n", nextFocus.get()); #endif - } + SetContentState(nsnull, NS_EVENT_STATE_FOCUS); + presShell->GetPrimaryFrameFor(nextFocus, &mCurrentTarget); + ChangeFocus(nextFocus); - //No one took focus and we're not already at the top of the doc - //so calling ShiftFocus will start at the top of the doc again. - if (!focusTaken && !docHasFocus) { - ShiftFocus(forward); + NS_IF_RELEASE(mCurrentFocus); + mCurrentFocus = nextFocus; + NS_ADDREF(mCurrentFocus); + + if (docHasFocus) + docShell->SetCanvasHasFocus(PR_FALSE); + else + docShell->SetHasFocus(PR_TRUE); + } + } else { + + // If we're going backwards past the first content, + // focus the document. + + PRBool focusDocument; + PRInt32 itemType; + nsCOMPtr shellItem = do_QueryInterface(docShell); + shellItem->GetItemType(&itemType); + if (itemType == nsIDocShellTreeItem::typeChrome) + focusDocument = PR_FALSE; + else { + // Check for a frameset document + focusDocument = !(IsFrameSetDoc(docShell)); } - return; - } else { - // The "next" piece of content to be focused is an IFrame, - // so we need to "walk" into the new HTMLIFrame docShell - nsCOMPtr iframe(do_QueryInterface(next)); - if (iframe) { - if (FocusWithinHTMLIFrameDoc(next, forward)) { - return; + if (!forward && !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); + } 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. + + nsCOMPtr treeItem = do_QueryInterface(pcContainer); + nsCOMPtr treeParent; + treeItem->GetParent(getter_AddRefs(treeParent)); + if (treeParent) { + nsCOMPtr parentDS = do_QueryInterface(treeParent); + if (parentDS) { + nsCOMPtr parentShell; + parentDS->GetPresShell(getter_AddRefs(parentShell)); + + nsCOMPtr shellContent; + parentShell->FindContentForShell(docShell, getter_AddRefs(shellContent)); + + nsCOMPtr parentPC; + parentShell->GetPresContext(getter_AddRefs(parentPC)); + + nsCOMPtr parentESM; + parentPC->GetEventStateManager(getter_AddRefs(parentESM)); + + SetContentState(nsnull, NS_EVENT_STATE_FOCUS); + +#ifdef DEBUG_DOCSHELL_FOCUS + printf("popping out focus to parent docshell\n"); +#endif + + parentESM->ShiftFocus(forward, shellContent); + } + } else { + PRBool tookFocus = PR_FALSE; + nsCOMPtr subShell = do_QueryInterface(pcContainer); + if (subShell) + subShell->TabToTreeOwner(forward, &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. + +#ifdef DEBUG_DOCSHELL_FOCUS + printf("wrapping around within this document\n"); +#endif + + NS_IF_RELEASE(mCurrentFocus); + docShell->SetHasFocus(PR_FALSE); + ShiftFocus(forward); + } } } } -#ifdef DEBUG_DOCSHELL_FOCUS - printf("Shift Focus to Content: %p\n", next.get()); -#endif - - // Now we need to get the content node's frame and reset - // the mCurrentTarget target. Otherwise the focus - // code will be slightly out of sync (with regards to - // focusing widgets within the current target) - if (shell) - shell->GetPrimaryFrameFor(next, &mCurrentTarget); - - ChangeFocus(next, mCurrentTarget, PR_TRUE); - - NS_IF_RELEASE(mCurrentFocus); - mCurrentFocus = next; - NS_IF_ADDREF(mCurrentFocus); - - if (docShell) - docShell->SetCanvasHasFocus(PR_FALSE); - - if (hadDocFocus) - ForceUpdate(docShell); + return NS_OK; } NS_IMETHODIMP @@ -3027,7 +2966,7 @@ nsEventStateManager::GetNextTabbableContent(nsIContent* aRootContent, nsIFrame* map->ChildAt(index, *getter_AddRefs(childArea)); if (childArea.get() == mCurrentFocus) { nsAutoString tabIndexStr; - childArea->GetAttr(kNameSpaceID_HTML, nsHTMLAtoms::tabindex, tabIndexStr); + childArea->GetAttr(kNameSpaceID_None, nsHTMLAtoms::tabindex, tabIndexStr); PRInt32 val = 0; if (!tabIndexStr.IsEmpty()) { PRInt32 ec, tabIndexVal = tabIndexStr.ToInteger(&ec); @@ -3052,7 +2991,7 @@ nsEventStateManager::GetNextTabbableContent(nsIContent* aRootContent, nsIFrame* //Got the map area, check its tabindex. nsAutoString tabIndexStr; - childArea->GetAttr(kNameSpaceID_HTML, nsHTMLAtoms::tabindex, tabIndexStr); + childArea->GetAttr(kNameSpaceID_None, nsHTMLAtoms::tabindex, tabIndexStr); PRInt32 val = 0; if (!tabIndexStr.IsEmpty()) { PRInt32 ec, tabIndexVal = tabIndexStr.ToInteger(&ec); @@ -3079,10 +3018,10 @@ nsEventStateManager::GetNextTabbableContent(nsIContent* aRootContent, nsIFrame* disabled = PR_FALSE; } else if (nsHTMLAtoms::iframe==tag.get()) { - nsCOMPtr iframe(do_QueryInterface(child)); - if (iframe) { - disabled = PR_FALSE; - } + disabled = PR_FALSE; + } + else if (nsHTMLAtoms::frame==tag.get()) { + disabled = PR_FALSE; } } else { @@ -3145,7 +3084,7 @@ nsEventStateManager::GetNextTabIndex(nsIContent* aParent, PRBool forward) } nsAutoString tabIndexStr; - child->GetAttr(kNameSpaceID_HTML, nsHTMLAtoms::tabindex, tabIndexStr); + child->GetAttr(kNameSpaceID_None, nsHTMLAtoms::tabindex, tabIndexStr); PRInt32 ec, val = tabIndexStr.ToInteger(&ec); if (NS_OK == ec && val > mCurrentTabIndex && val != tabIndex) { tabIndex = (tabIndex == 0 || val < tabIndex) ? val : tabIndex; @@ -3163,7 +3102,7 @@ nsEventStateManager::GetNextTabIndex(nsIContent* aParent, PRBool forward) } nsAutoString tabIndexStr; - child->GetAttr(kNameSpaceID_HTML, nsHTMLAtoms::tabindex, tabIndexStr); + child->GetAttr(kNameSpaceID_None, nsHTMLAtoms::tabindex, tabIndexStr); PRInt32 ec, val = tabIndexStr.ToInteger(&ec); if (NS_OK == ec) { if ((mCurrentTabIndex==0 && val > tabIndex) || @@ -3176,29 +3115,6 @@ nsEventStateManager::GetNextTabIndex(nsIContent* aParent, PRBool forward) return tabIndex; } -NS_IMETHODIMP -nsEventStateManager::GetNextTabbableIndexContent(nsIContent* aRootContent, - PRBool forward, - PRBool aStartOver, - nsIContent** aResult) -{ - if (forward) { - if (aStartOver) { - mCurrentTabIndex = 0; - } - mCurrentTabIndex = GetNextTabIndex(aRootContent, forward); - if (mCurrentTabIndex > 0) { - return GetNextTabbableContent(aRootContent, nsnull, forward, aResult); - } - } else { - nsCOMPtr lastContent = getter_AddRefs(GetLastContent(aRootContent)); - if (lastContent) { - MoveFocus(PR_FALSE, lastContent); - } - } - return NS_ERROR_FAILURE; -} - NS_IMETHODIMP nsEventStateManager::GetEventTarget(nsIFrame **aFrame) { @@ -3224,38 +3140,6 @@ nsEventStateManager::GetEventTarget(nsIFrame **aFrame) return NS_OK; } -NS_IMETHODIMP -nsEventStateManager::HasPositiveTabIndex(nsIContent* aContent, - PRBool* aResult) -{ - NS_ENSURE_ARG_POINTER(aContent); - NS_ENSURE_ARG_POINTER(aResult); - *aResult = PR_FALSE; - - nsAutoString tabIndexStr; - aContent->GetAttr(kNameSpaceID_HTML, nsHTMLAtoms::tabindex, tabIndexStr); - if (!tabIndexStr.IsEmpty()) { - PRInt32 ec, tabIndexVal = tabIndexStr.ToInteger(&ec); - if (NS_SUCCEEDED(ec)) { - if (tabIndexVal > 0) { - *aResult = PR_TRUE; - return NS_OK; - } - } - } - - PRInt32 count; - aContent->ChildCount(count); - for (PRInt32 i=0;iChildAt(i, child); - if (NS_SUCCEEDED(HasPositiveTabIndex(child, aResult))) { - return NS_OK; - } - } - return NS_ERROR_FAILURE; -} - NS_IMETHODIMP nsEventStateManager::GetEventTargetContent(nsEvent* aEvent, nsIContent** aContent) { @@ -3757,7 +3641,7 @@ nsEventStateManager::SendFocusBlur(nsIPresContext* aPresContext, nsIContent *aCo } nsAutoString tabIndex; - aContent->GetAttr(kNameSpaceID_HTML, nsHTMLAtoms::tabindex, tabIndex); + aContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::tabindex, tabIndex); PRInt32 ec, val = tabIndex.ToInteger(&ec); if (NS_OK == ec) { mCurrentTabIndex = val; @@ -4117,7 +4001,7 @@ nsresult nsEventStateManager::MoveFocusToCaret() // Add more focusable tags here later if necessary ... if (nsHTMLAtoms::a == tag.get()) { // We are on a link, so change focus to it. - ChangeFocus(caretContent, caretFrame, PR_TRUE); + ChangeFocus(caretContent); break; } // Get the parent @@ -4215,674 +4099,293 @@ nsresult nsEventStateManager::EnsureCaretVisible(nsIPresShell* aPresShell, nsICo //---------------------------------------- // Returns PR_TRUE if this doc contains a frameset -PRBool -nsEventStateManager::IsFrameSetDoc(nsIContent* aContent) +PRBool +nsEventStateManager::IsFrameSetDoc(nsIDocShell* aDocShell) { - NS_ASSERTION(aContent, "Pointer is null!"); - - if (!aContent) { - return PR_FALSE; - } - - nsCOMPtr frameSet = do_QueryInterface(aContent); - if (frameSet) { - return PR_TRUE; - } - - PRInt32 count; - aContent->ChildCount(count); - for (PRInt32 i=0;iChildAt(i, child); - if (IsFrameSetDoc(child)) { - return PR_TRUE; - } - } - return PR_FALSE; -} - -//---------------------------------------- -// This method finds the content node in the parent document -// corresponds to the docshell -nsIContent* -nsEventStateManager::FindContentForDocShell(nsIPresShell* aPresShell, - nsIContent* aContent, - nsIDocShell* aDocShell) -{ - NS_ASSERTION(aPresShell, "Pointer is null!"); - NS_ASSERTION(aDocShell, "Pointer is null!"); - NS_ASSERTION(aContent, "Pointer is null!"); - - nsCOMPtr supps; - aPresShell->GetSubShellFor(aContent, getter_AddRefs(supps)); - if (supps) { - nsCOMPtr docShell(do_QueryInterface(supps)); - if (docShell.get() == aDocShell) { - NS_ADDREF(aContent); - return aContent; - } - } - - // walk children content - PRInt32 count; - aContent->ChildCount(count); - for (PRInt32 i=0;i child; - aContent->ChildAt(i, *getter_AddRefs(child)); - nsIContent* foundContent = FindContentForDocShell(aPresShell, child, aDocShell); - if (foundContent != nsnull) { - return foundContent; - } - } - return nsnull; -} - -//---------------------------------------- -// This method checks to see if the Content node -// (that is a HTMLFrame, is the last one -PRBool -nsEventStateManager::IsLastFrameInFrameSet(nsIContent* aLastFrameContent) -{ - NS_ASSERTION(aLastFrameContent, "Pointer is null!"); - - nsCOMPtr parent; - aLastFrameContent->GetParent(*getter_AddRefs(parent)); - NS_ASSERTION(parent, "parent is null!"); - - PRInt32 count; - parent->ChildCount(count); - for (PRInt32 i=0;i child; - parent->ChildAt(i, *getter_AddRefs(child)); - if (child.get() == aLastFrameContent && i == count-1) { - return PR_TRUE; - } - } - return PR_FALSE; -} - - -//---------------------------------------- -// Identifies the type of document it is -NS_IMETHODIMP -nsEventStateManager::FigureOutKindOfDoc(nsIDocument* aDoc, eDocType* aDocType) -{ - NS_ENSURE_ARG_POINTER(aDoc); - NS_ENSURE_ARG_POINTER(aDocType); - - *aDocType = eChrome; - - nsCOMPtr presShell; - aDoc->GetShellAt(0, getter_AddRefs(presShell)); - if (!presShell) return NS_ERROR_FAILURE; - nsCOMPtr presContext; - presShell->GetPresContext(getter_AddRefs(presContext)); - if (!presContext) return NS_ERROR_FAILURE; - nsCOMPtr pcContainer; - presContext->GetContainer(getter_AddRefs(pcContainer)); - if (!pcContainer) return NS_ERROR_FAILURE; - nsCOMPtr docShell(do_QueryInterface(pcContainer)); - -#ifdef DEBUG_DOCSHELL_FOCUS - printf("FigureOutKindOfDoc DocShell %p Doc: %p\n", docShell.get(), aDoc); -#endif - - // Make sure this document is "content" and not "chrome" - nsCOMPtr treeItem(do_QueryInterface(docShell)); - if (!treeItem) return NS_ERROR_FAILURE; - - PRInt32 type; - treeItem->GetItemType(&type); - if (type != nsIDocShellTreeItem::typeContent) { - return NS_OK; - } - *aDocType = eGenericContent; - - // See if we are a frame set - nsCOMPtr rootContent; - aDoc->GetRootContent(getter_AddRefs(rootContent)); - if (IsFrameSetDoc(rootContent)) { - *aDocType = eFrameSet; - return NS_OK; - } - - // So we know we the docShell is content and it isn't - // a FrameSet, so let's get the parent's doc to see if we - // are a FrameSet-Frame or an IFrame - - // Get Parent Doc - nsCOMPtr treeItemParent; - treeItem->GetParent(getter_AddRefs(treeItemParent)); - if (!treeItemParent) return NS_ERROR_FAILURE; - - nsCOMPtr parentDS = do_QueryInterface(treeItemParent); - if (!parentDS) return NS_ERROR_FAILURE; - - nsCOMPtr parentPresShell; - parentDS->GetPresShell(getter_AddRefs(parentPresShell)); - if (!parentPresShell) return NS_ERROR_FAILURE; - - nsCOMPtr parentDoc; - parentPresShell->GetDocument(getter_AddRefs(parentDoc)); - if (!parentDoc) return NS_ERROR_FAILURE; - - parentDoc->GetRootContent(getter_AddRefs(rootContent)); - - nsCOMPtr content = getter_AddRefs(FindContentForDocShell(parentPresShell, rootContent, docShell)); - - // Is it a FrameSet Frame? - nsCOMPtr frameSetFrame = do_QueryInterface(content); - if (frameSetFrame) { - *aDocType = eFrame; - return NS_OK; - } - - // Is it an IFrame/ - nsCOMPtr iframe = do_QueryInterface(content); - if (iframe) { - *aDocType = eIFrame; - return NS_OK; - } - // Generic Content gets here - return NS_OK; -} - -//------------------------------------------------------- -// This method gets the DocShells for the document and -// its parent -nsresult -nsEventStateManager::GetDocShellsFromDoc(nsIDocument* aDocument, - nsIDocShell** aDocShell, - nsIDocShell** aParentDS) -{ - NS_ASSERTION(aDocument, "Pointer is null!"); - NS_ASSERTION(aDocShell, "Pointer is null!"); - NS_ASSERTION(aParentDS, "Pointer is null!"); - - nsCOMPtr presShell; - aDocument->GetShellAt(0, getter_AddRefs(presShell)); - if (!presShell) return NS_ERROR_FAILURE; - - nsCOMPtr presContext; - presShell->GetPresContext(getter_AddRefs(presContext)); - if (!presContext) return NS_ERROR_FAILURE; - - nsCOMPtr pcContainer; - presContext->GetContainer(getter_AddRefs(pcContainer)); - if (!pcContainer) return NS_ERROR_FAILURE; - - nsCOMPtr docshell(do_QueryInterface(pcContainer)); - if (!docshell) return NS_ERROR_FAILURE; - - *aDocShell = docshell.get(); - NS_ADDREF(*aDocShell); - nsCOMPtr treeItem(do_QueryInterface(docshell)); - if (!treeItem) return NS_ERROR_FAILURE; - - nsCOMPtr treeItemParent; - treeItem->GetParent(getter_AddRefs(treeItemParent)); - if (!treeItemParent) return NS_ERROR_FAILURE; - - nsCOMPtr parentDS(do_QueryInterface(treeItemParent)); - if (!parentDS) return NS_ERROR_FAILURE; - - *aParentDS = parentDS.get(); - NS_ADDREF(*aParentDS); - return NS_OK; -} - -//------------------------------------------------------- -// This method refreshes a docshell -void -nsEventStateManager::ForceUpdate(nsIDocShell* aDocShell) -{ - NS_ASSERTION(aDocShell, "Pointer is null!"); + 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 presShell; aDocShell->GetPresShell(getter_AddRefs(presShell)); - if (!presShell) return; - - nsCOMPtr presContext; - aDocShell->GetPresContext(getter_AddRefs(presContext)); - if (!presContext) return; - - nsCOMPtr vm; - presShell->GetViewManager(getter_AddRefs(vm)); - if (!vm) return; - - vm->UpdateAllViews(NS_VMREFRESH_NO_SYNC); - -#ifdef DEBUG_DOCSHELL_FOCUS - printf("ForceUpdate - DS: %p ********************************************\n", aDocShell); -#endif -} - -//------------------------------------------------------- -// This method will find the next DocShell within Parent -nsIDocShell* -nsEventStateManager::GetNextDocShell(nsIDocShell* aParentDS, nsIDocShell* aCurrentDS, PRBool aForward) -{ - NS_ASSERTION(aParentDS, "Pointer is null!"); - NS_ASSERTION(aCurrentDS, "Pointer is null!"); - - nsCOMPtr parentTreeNode(do_QueryInterface(aParentDS)); - if (!parentTreeNode) return nsnull; - - PRInt32 count; - parentTreeNode->GetChildCount(&count); - for (PRInt32 i=0;i child; - parentTreeNode->GetChildAt(i, getter_AddRefs(child)); - nsCOMPtr ds = do_QueryInterface(child); - if (ds.get() == aCurrentDS) { - i += aForward?1:-1; - if (i > -1 && i < count) { - parentTreeNode->GetChildAt(i, getter_AddRefs(child)); - ds = do_QueryInterface(child); - nsIDocShell* fndDocShell = ds.get(); - NS_ADDREF(fndDocShell); - return fndDocShell; - } - return nsnull; - } - } - return nsnull; -} - -//------------------------------------------------------- -// This method will find a DocShell that corresponds to -// a content node in a parent document -nsIDocShell* -nsEventStateManager::GetDocShellFromContent(nsIDocShell* aParentDocShell, nsIContent* aContent) -{ - NS_ASSERTION(aParentDocShell, "Pointer is null!"); - NS_ASSERTION(aContent, "Pointer is null!"); - - nsCOMPtr parentPresShell; - aParentDocShell->GetPresShell(getter_AddRefs(parentPresShell)); - nsCOMPtr supports; - parentPresShell->GetSubShellFor(aContent, getter_AddRefs(supports)); - nsCOMPtr docShell = do_QueryInterface(supports); - if (docShell) { - nsIDocShell* ds = docShell.get(); - NS_ADDREF(ds); - return ds; - } - return nsnull; -} - -//------------------------------------------------------- -// This method will get the very last content object -// when given aRootContent node -nsIContent* -nsEventStateManager::GetLastContent(nsIContent* aRootContent) -{ - if (aRootContent == nsnull) { - return nsnull; - } - - PRInt32 count; - aRootContent->ChildCount(count); - nsCOMPtr child; - aRootContent->ChildAt(count-1, *getter_AddRefs(child)); - nsIContent* last = GetLastContent(child); - return last; -} - - -//------------------------------------------------------- -// This method will get the very last content object in -// in a DocShell -nsIContent* -nsEventStateManager::GetLastContent(nsIDocShell* aDocShell) -{ - NS_ASSERTION(aDocShell, "Pointer is null!"); - - nsCOMPtr presShell; - aDocShell->GetPresShell(getter_AddRefs(presShell)); - if (!presShell) return nsnull; - - nsCOMPtr doc; - presShell->GetDocument(getter_AddRefs(doc)); - if (!doc) return nsnull; - - nsCOMPtr rootContent; - doc->GetRootContent(getter_AddRefs(rootContent)); - if (!rootContent) return nsnull; - - nsIContent* last = nsnull; - nsCOMPtr parent = rootContent; - PRInt32 count; - parent->ChildCount(count); - while (count > 0) { - nsCOMPtr child; - parent->ChildAt(count-1, *getter_AddRefs(child)); - child->ChildCount(count); - parent = child; - last = child.get(); - } - NS_IF_ADDREF(last); - return last; -} - -//------------------------------------------------------- -// This method will get the "next" Frame in a FrameSet (forward or backwards) -// and if one doesn't exist, then focus the next docshell AFTER -// the FrameSet -PRBool -nsEventStateManager::FocusAfterHTMLFrameDoc(nsIDocShell* aDocShell, - nsIDocShell* aParentDocShell, - PRBool aForward) -{ - // neither of should ever be null, but just in case - if (aDocShell == nsnull || aParentDocShell == nsnull) { - return PR_FALSE; - } - - // Try to get the next DocShell - nsCOMPtr nextDocShell = getter_AddRefs(GetNextDocShell(aParentDocShell, aDocShell, aForward)); - if (nextDocShell) { - // unset focus in current doc - SetContentState(nsnull, NS_EVENT_STATE_FOCUS); - - nsCOMPtr baseWin(do_QueryInterface(nextDocShell)); - if (NS_SUCCEEDED(baseWin->SetFocus())) { -#ifdef DEBUG_DOCSHELL_FOCUS - printf("Focused DS: %p ********************************************\n", nextDocShell.get()); -#endif - return PR_TRUE; - } - } else { - // ok, since the we are a HTMLFrame and parent is a FrameSet - // then we will get the parent of the FrameSet and try to - // find the next aDocShell - nsCOMPtr oldDocShell = aDocShell; - - // unset focus in current doc - SetContentState(nsnull, NS_EVENT_STATE_FOCUS); - - nsCOMPtr parentItem(do_QueryInterface(aParentDocShell)); - if (!parentItem) return PR_FALSE; - - nsCOMPtr ds = aDocShell; - nsCOMPtr pDS = aParentDocShell; - nsCOMPtr parentParentItem; - parentItem->GetParent(getter_AddRefs(parentParentItem)); - if (parentParentItem) { - ds = aParentDocShell; - pDS = do_QueryInterface(parentParentItem); - } - PRBool focusTaken; - // it was the last one in the Frame - //Offer focus upwards to allow shifting focus to UI controls - nsCOMPtr docShellAsWin(do_QueryInterface(ds)); - nsCOMPtr parentDocShellAsWin(do_QueryInterface(pDS)); - if (docShellAsWin && parentDocShellAsWin) { - parentDocShellAsWin->FocusAvailable(docShellAsWin, aForward, &focusTaken); - if (focusTaken) { - return PR_TRUE; - } - } - } - return PR_FALSE; -} - -//------------------------------------------------------- -// This methods finds the content object in the parent document that -// corresponds to the aDocShell. -// Then the parent doc is asked to find the next "focusable" item -// AFTER this IFrame. -PRBool -nsEventStateManager::FocusAfterHTMLIFrameDoc(nsIDocShell* aDocShell, - nsIDocShell* aParentDocShell, - PRBool aForward, - PRBool& aFocusDoc) -{ - NS_ASSERTION(aDocShell, "Pointer is null!"); - NS_ASSERTION(aParentDocShell, "Pointer is null!"); - - // Make sure this IFrame is inside a Content Doc - nsCOMPtr parentItem(do_QueryInterface(aParentDocShell)); - if (!parentItem) return PR_FALSE; - - PRInt32 type; - parentItem->GetItemType(&type); - if (type == nsIDocShellTreeItem::typeContent) { - - // remove focus from any items in doc - SetContentState(nsnull, NS_EVENT_STATE_FOCUS); - - // Go find the root content object for the parent document - // so we can find the content that corresponds to this docshell - nsCOMPtr parentPresShell; - aParentDocShell->GetPresShell(getter_AddRefs(parentPresShell)); - if (!parentPresShell) return PR_FALSE; - - nsCOMPtr parentDoc; - parentPresShell->GetDocument(getter_AddRefs(parentDoc)); - if (!parentDoc) return PR_FALSE; - - nsCOMPtr parentPresContext; - aParentDocShell->GetPresContext(getter_AddRefs(parentPresContext)); - if (!parentPresContext) return PR_FALSE; - - nsCOMPtr rootContent; - parentDoc->GetRootContent(getter_AddRefs(rootContent)); - if (!rootContent) return PR_FALSE; - - // Now that we have the Root Content for the Parent Doc - // we can look for the the content object that corresponds to this DocShell - nsCOMPtr focusedContent = getter_AddRefs(FindContentForDocShell(parentPresShell, rootContent, aDocShell)); - -#ifdef DEBUG_DOCSHELL_FOCUS - printf("For Child DocShell %p shifting focus to content %p in parent DocShell %p\n", - aDocShell, focusedContent.get(), aParentDocShell); -#endif - - nsCOMPtr esm; - parentPresContext->GetEventStateManager(getter_AddRefs(esm)); - if (!esm) return PR_FALSE; - -#ifdef DEBUG_DOCSHELL_FOCUS - printf("PDS: %p Pres %p EM %p Doc %p\n", aParentDocShell, - parentPresShell.get(), esm.get(), parentDoc.get()); -#endif - - // So we use that Content node in the Parent Doc - // to focus the very next object - if (focusedContent) { - esm->MoveFocus(aForward, focusedContent); - } - nsCOMPtr newFocusedContent; - esm->GetFocusedContent(getter_AddRefs(newFocusedContent)); - - /*nsCOMPtr next; - nsIFrame* primaryFrame = nsnull; - parentPresShell->GetPrimaryFrameFor(focusedContent, &primaryFrame); - if (primaryFrame) { - esm->GetNextTabbableContent(rootContent, primaryFrame, aForward, getter_AddRefs(next)); - }*/ - - if (newFocusedContent) { - // Now, give focus to the DOM Window - nsCOMPtr sgo; - parentDoc->GetScriptGlobalObject(getter_AddRefs(sgo)); - if (!sgo) return PR_FALSE; - - nsCOMPtr domwin(do_QueryInterface(sgo)); - if (domwin && NS_SUCCEEDED(domwin->Focus())) { - aParentDocShell->SetCanvasHasFocus(PR_FALSE); - return PR_TRUE; - } - } else { - return PR_TRUE; - } - - // tell the outside NOT to focus the document - // because it found something to focus - aFocusDoc = PR_FALSE; - } - return PR_FALSE; -} - -//------------------------------------------------------------------ -// This method is checking for two things: -// -// 1) To see if the currently focused content has a docshell -// and if it does we focus it -// -// 2) Check to see if this frame is the last frame in the frameset -// and if it is then we want the parent to focus the next piece of -// content, which means it should move on to the Chrome -PRBool -nsEventStateManager::FocusWithinHTMLFrameDoc(nsIContent* aRootContent, - nsIPresShell* aPresShell, - PRBool aForward, - PRBool& aDoFocusAvailDocShells) -{ - NS_ASSERTION(aPresShell, "Pointer is null!"); - - if (mCurrentFocus == nsnull) return PR_FALSE; - - if (aRootContent == nsnull) { - if (aPresShell) { - // See if the currently focused item has a DocShell (like an IFrame) - // and then give it focus - nsCOMPtr supports; - aPresShell->GetSubShellFor(mCurrentFocus, getter_AddRefs(supports)); - nsCOMPtr docShell = do_QueryInterface(supports); - if (docShell) { - nsCOMPtr baseWin(do_QueryInterface(docShell)); - if (NS_SUCCEEDED(baseWin->SetFocus())) { -#ifdef DEBUG_DOCSHELL_FOCUS - printf("Focused DS: %p ********************************************\n", docShell.get()); -#endif - return PR_TRUE; - } - } - } - } else { - // Ok, the root content has been set so we need to go find the content - // in the parent's doc that represents this DocShell - nsCOMPtr docShell; - nsCOMPtr parentDS; - - if (NS_SUCCEEDED(GetDocShellsFromDoc(mDocument, getter_AddRefs(docShell), getter_AddRefs(parentDS)))) { - nsCOMPtr parentPresShell; - parentDS->GetPresShell(getter_AddRefs(parentPresShell)); - if (!parentPresShell) return PR_FALSE; - - nsCOMPtr parentDoc; - parentPresShell->GetDocument(getter_AddRefs(parentDoc)); - if (!parentDoc) return PR_FALSE; - + if (presShell) { + nsCOMPtr doc; + presShell->GetDocument(getter_AddRefs(doc)); + nsCOMPtr htmlDoc = do_QueryInterface(doc); + if (htmlDoc) { nsCOMPtr rootContent; - parentDoc->GetRootContent(getter_AddRefs(rootContent)); - if (!rootContent) return PR_FALSE; - - // Look up the content - nsCOMPtr focusedContent = getter_AddRefs(FindContentForDocShell(parentPresShell, rootContent, docShell)); - - // Now check to see if the focused piece of content that represents - // the current DocShell is the last frame in the frameset - if (focusedContent && IsLastFrameInFrameSet(focusedContent)) { - aDoFocusAvailDocShells = PR_TRUE; - - PRBool focusTaken = PR_FALSE; - SetContentState(nsnull, NS_EVENT_STATE_FOCUS); - - // Now let the parent doc find the next focusable DocShell - // and in this case the focus will move on out of the frameset - nsCOMPtr docShellAsWin(do_QueryInterface(docShell)); - nsCOMPtr parentDocShellAsWin(do_QueryInterface(parentDS)); - if (docShellAsWin) { - parentDocShellAsWin->FocusAvailable(docShellAsWin, aForward, &focusTaken); - if (focusTaken) { - return PR_TRUE; + doc->GetRootContent(getter_AddRefs(rootContent)); + if (rootContent) { + PRInt32 childCount; + rootContent->ChildCount(childCount); + for (PRInt32 i = 0; i < childCount; ++i) { + nsCOMPtr childContent; + rootContent->ChildAt(i, *getter_AddRefs(childContent)); + nsCOMPtr childTag; + childContent->GetTag(*getter_AddRefs(childTag)); + if (childTag == nsHTMLAtoms::frameset) { + isFrameSet = PR_TRUE; + break; } } } } } - return PR_FALSE; + + return isFrameSet; } -//------------------------------------------------------------------ -// This method finds the +//---------------------------------------- +// Returns PR_TRUE if this doc is an IFRAME + PRBool -nsEventStateManager::FocusWithinHTMLIFrameDoc(nsIContent* aNextContent, PRBool aForward) +nsEventStateManager::IsIFrameDoc(nsIDocShell* aDocShell) { - NS_ASSERTION(aNextContent, "Pointer is null!"); + NS_ASSERTION(aDocShell, "docshell is null"); + nsCOMPtr treeItem = do_QueryInterface(aDocShell); + nsCOMPtr parentItem; + treeItem->GetParent(getter_AddRefs(parentItem)); + if (!parentItem) + return PR_FALSE; + + nsCOMPtr parentDS = do_QueryInterface(parentItem); + nsCOMPtr parentShell; + parentDS->GetPresShell(getter_AddRefs(parentShell)); + NS_ASSERTION(parentShell, "presshell is null"); + + nsCOMPtr docContent; + parentShell->FindContentForShell(aDocShell, getter_AddRefs(docContent)); + if (!docContent) + return PR_FALSE; + + nsCOMPtr tag; + docContent->GetTag(*getter_AddRefs(tag)); + return (tag == nsHTMLAtoms::iframe); +} - // Begin by finding the DocShell for this document - // and the DocShell for the IFrame content - nsCOMPtr container; - mPresContext->GetContainer(getter_AddRefs(container)); - nsCOMPtr docShell = do_QueryInterface(container); - if (!docShell) return PR_FALSE; +//------------------------------------------------------- +// Return PR_TRUE if the docshell is visible - // Here we find the DocShell that correpsonds to the IFrame - nsCOMPtr newDocShell = getter_AddRefs(GetDocShellFromContent(docShell, aNextContent)); - if (newDocShell) { - nsCOMPtr newDocShellAsWin(do_QueryInterface(newDocShell)); - if (newDocShellAsWin) { - // Clear focus in current document - SetContentState(nsnull, NS_EVENT_STATE_FOCUS); +PRBool +nsEventStateManager::IsShellVisible(nsIDocShell* aShell) +{ + NS_ASSERTION(aShell, "docshell is null"); - // set focus in IFrame - if (NS_SUCCEEDED(newDocShellAsWin->SetFocus())) { - // Now if we are reversing through the document then - // we need to find the last piece of content in the IFrame document - if (!aForward) { - nsCOMPtr presContext; - newDocShell->GetPresContext(getter_AddRefs(presContext)); - if (!presContext) return PR_FALSE; + nsCOMPtr basewin = do_QueryInterface(aShell); + if (!basewin) + return PR_TRUE; + + PRBool isVisible = PR_TRUE; + basewin->GetVisibility(&isVisible); - nsCOMPtr esm; - presContext->GetEventStateManager(getter_AddRefs(esm)); - if (!esm) return PR_FALSE; + // We should be doing some additional checks here so that + // we don't tab into hidden tabs of tabbrowser. -bryner - nsCOMPtr lastContent = getter_AddRefs(GetLastContent(newDocShell)); - if (lastContent) { - esm->MoveFocus(PR_FALSE, lastContent); - } - } - return PR_TRUE; + 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 domwin = do_GetInterface(aDocShell); + if (domwin) + domwin->Focus(); + + PRInt32 itemType; + nsCOMPtr treeItem = do_QueryInterface(aDocShell); + treeItem->GetItemType(&itemType); + + PRBool focusDocument; + 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); + + nsCOMPtr pc; + aDocShell->GetPresContext(getter_AddRefs(pc)); + if (pc) { + nsCOMPtr docESM; + pc->GetEventStateManager(getter_AddRefs(docESM)); + if (docESM) { + // 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); } } } - return PR_FALSE; +} + +void +nsEventStateManager::GetLastChildDocShell(nsIDocShellTreeItem* aItem, + nsIDocShellTreeItem** aResult) +{ + NS_ASSERTION(aItem, "null docshell"); + NS_ASSERTION(aResult, "null out pointer"); + + nsCOMPtr curItem = do_QueryInterface(aItem); + while (1) { + nsCOMPtr 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"); + + aNode->GetChildAt(0, aResult); + if (*aResult) + return; + + nsCOMPtr curNode = aNode; + while (curNode) { + nsCOMPtr curItem = do_QueryInterface(curNode); + nsCOMPtr parentItem; + curItem->GetParent(getter_AddRefs(parentItem)); + if (!parentItem) { + *aResult = nsnull; + return; + } + + PRInt32 childOffset = 0; + curItem->GetChildOffset(&childOffset); + nsCOMPtr parentNode = do_QueryInterface(parentItem); + parentNode->GetChildAt(childOffset+1, aResult); + if (*aResult) + return; + + curNode = do_QueryInterface(parentItem); + } +} + +void +nsEventStateManager::GetPrevDocShell(nsIDocShellTreeNode* aNode, + nsIDocShellTreeItem** aResult) +{ + NS_ASSERTION(aNode, "null docshell"); + NS_ASSERTION(aResult, "null out pointer"); + + nsCOMPtr curNode = aNode; + nsCOMPtr curItem = do_QueryInterface(curNode); + nsCOMPtr parentItem; + + curItem->GetParent(getter_AddRefs(parentItem)); + if (!parentItem) { + *aResult = nsnull; + return; + } + + PRInt32 childOffset = 0; + curItem->GetChildOffset(&childOffset); + if (childOffset) { + nsCOMPtr parentNode = do_QueryInterface(parentItem); + parentNode->GetChildAt(childOffset - 1, getter_AddRefs(curItem)); + + // get the last child recursively of this node + while (1) { + PRInt32 childCount = 0; + curNode = do_QueryInterface(curItem); + 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 inclide any content inside the doc +// this does not include any content inside the doc // or IFrames void -nsEventStateManager::ShiftFocusByDoc(PRBool aForward, nsIContent* aRoot) +nsEventStateManager::ShiftFocusByDoc(PRBool aForward) { - // Figure out what type of document we are - eDocType docType; - FigureOutKindOfDoc(mDocument, &docType); + // 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"); -#ifdef DEBUG_DOCSHELL_FOCUS - printf("Doc Type is [%s]\n", gDocTypeNames[docType]); -#endif + nsCOMPtr pcContainer; + mPresContext->GetContainer(getter_AddRefs(pcContainer)); + nsCOMPtr curNode = do_QueryInterface(pcContainer); + + // perform a depth first search (preorder) of the docshell tree + // looking for an HTML Frame or a chrome document + + nsCOMPtr nextItem; + nsCOMPtr nextShell; + do { + if (aForward) { + GetNextDocShell(curNode, getter_AddRefs(nextItem)); + if (!nextItem) { + nsCOMPtr 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 curItem = do_QueryInterface(pcContainer); + // wrap around to the end, which is the last node in the tree + nsCOMPtr rootItem; + curItem->GetRootTreeItem(getter_AddRefs(rootItem)); + GetLastChildDocShell(rootItem, getter_AddRefs(nextItem)); + } + } - if (docType == eChrome) { - ShiftFocus(aForward, aRoot); - return; + 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); } - - if (docType == eFrame) { - nsCOMPtr docShell; - nsCOMPtr parentDS; - if (NS_SUCCEEDED(GetDocShellsFromDoc(mDocument, getter_AddRefs(docShell), getter_AddRefs(parentDS)))) { - // Try to focus the Next Frame in the FrameSet - // if there is none then focus the next Chrome Doc - FocusAfterHTMLFrameDoc(docShell, parentDS, aForward); - } - } - } diff --git a/mozilla/content/events/src/nsEventStateManager.h b/mozilla/content/events/src/nsEventStateManager.h index 1e165a9c297..f0fc0624620 100644 --- a/mozilla/content/events/src/nsEventStateManager.h +++ b/mozilla/content/events/src/nsEventStateManager.h @@ -54,6 +54,8 @@ class nsIPresShell; class nsITreeFrame; class nsIFrameSelection; class nsIDocShell; +class nsIDocShellTreeNode; +class nsIDocShellTreeItem; // mac uses click-hold context menus, a holdover from 4.x #ifdef XP_MAC @@ -128,9 +130,7 @@ public: //Method for centralized distribution of new DOM events NS_IMETHOD DispatchNewEvent(nsISupports* aTarget, nsIDOMEvent* aEvent, PRBool *aPreventDefault); - NS_IMETHOD MoveFocus(PRBool aDirection, nsIContent* aRoot); - - NS_IMETHOD FigureOutKindOfDoc(nsIDocument* aDoc, eDocType* aDocType); + NS_IMETHOD ShiftFocus(PRBool forward, nsIContent* aStart=nsnull); protected: void UpdateCursor(nsIPresContext* aPresContext, nsEvent* aEvent, nsIFrame* aTargetFrame, nsEventStatus* aStatus); @@ -138,15 +138,8 @@ protected: void GenerateDragDropEnterExit(nsIPresContext* aPresContext, nsGUIEvent* aEvent); NS_IMETHOD SetClickCount(nsIPresContext* aPresContext, nsMouseEvent *aEvent, nsEventStatus* aStatus); NS_IMETHOD CheckForAndDispatchClick(nsIPresContext* aPresContext, nsMouseEvent *aEvent, nsEventStatus* aStatus); - PRBool ChangeFocus(nsIContent* aFocus, nsIFrame* aFocusFrame, PRBool aSetFocus); - void ShiftFocus(PRBool forward, nsIContent* aRoot=nsnull); + PRBool ChangeFocus(nsIContent* aFocus); NS_IMETHOD GetNextTabbableContent(nsIContent* aRootContent, nsIFrame* aFrame, PRBool forward, nsIContent** aResult); - NS_IMETHOD GetNextTabbableIndexContent(nsIContent* aRootContent, - PRBool forward, - PRBool aStartOver, - nsIContent** aResult); - NS_IMETHOD HasPositiveTabIndex(nsIContent* aContent, - PRBool* aResult); PRInt32 GetNextTabIndex(nsIContent* aParent, PRBool foward); NS_IMETHOD SendFocusBlur(nsIPresContext* aPresContext, nsIContent *aContent); @@ -159,21 +152,17 @@ protected: // DocShell Focus Traversal Methods //--------------------------------------------- - void ShiftFocusByDoc(PRBool forward, nsIContent* aRoot=nsnull); - PRBool FocusAfterHTMLFrameDoc(nsIDocShell* aDocShell, nsIDocShell* aParentDocShell, PRBool aForward); - PRBool FocusAfterHTMLIFrameDoc(nsIDocShell* aDocShell, nsIDocShell* aParentDocShell, PRBool aForward, PRBool& aFocusDoc); - PRBool FocusWithinHTMLFrameDoc(nsIContent* aRootContent, nsIPresShell* aPresShell, PRBool aForward, PRBool& aDoFocusAvailDocShells); - PRBool FocusWithinHTMLIFrameDoc(nsIContent* aNextContent, PRBool aForward); - nsIContent* GetLastContent(nsIDocShell* aDocShell); - nsIContent* GetLastContent(nsIContent* aRootContent); - nsIDocShell* GetDocShellFromContent(nsIDocShell* aParentDocShell, nsIContent* aContent); - nsIDocShell* GetNextDocShell(nsIDocShell* aParentDS, nsIDocShell* aCurrentDS, PRBool aForward); - void ForceUpdate(nsIDocShell* aDocShell); - nsresult GetDocShellsFromDoc(nsIDocument* aDocument, nsIDocShell** aDocShell, nsIDocShell** aParentDS); - PRBool IsLastFrameInFrameSet(nsIContent* aLastFrameContent); - nsIContent* FindContentForDocShell(nsIPresShell* aPresShell, nsIContent* aContent, nsIDocShell* aDocShell); - PRBool IsFrameSetDoc(nsIContent* aContent); - + void TabIntoDocument(nsIDocShell* aDocShell, PRBool aForward); + void ShiftFocusByDoc(PRBool forward); + PRBool IsFrameSetDoc(nsIDocShell* aDocShell); + PRBool IsIFrameDoc(nsIDocShell* aDocShell); + 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 scrolling nsIScrollableView* GetNearestScrollingView(nsIView* aView); @@ -255,7 +244,7 @@ protected: static PRUint32 mInstanceCount; - // For mousewheel preferences handling + // For preferences handling nsCOMPtr mPrefService; PRBool m_haveShutdown; diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp index f6030f8a823..89a592a4c70 100644 --- a/mozilla/docshell/base/nsDocShell.cpp +++ b/mozilla/docshell/base/nsDocShell.cpp @@ -123,7 +123,7 @@ static NS_DEFINE_CID(kPluginManagerCID, NS_PLUGINMANAGER_CID); static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID); -#ifdef DEBUG_rods +#if defined(DEBUG_rods) || defined(DEBUG_bryner) //#define DEBUG_DOCSHELL_FOCUS #endif // @@ -1265,22 +1265,6 @@ NS_IMETHODIMP nsDocShell::SetAllowImages(PRBool aAllowImages) return NS_OK; } -NS_IMETHODIMP -nsDocShell::GetFocusDocBeforeContent(PRBool* aDocFirst) -{ - NS_ENSURE_ARG_POINTER(aDocFirst); - - *aDocFirst = mFocusDocFirst; - return NS_OK; -} - -NS_IMETHODIMP -nsDocShell::SetFocusDocBeforeContent(PRBool aDocFirst) -{ - mFocusDocFirst = aDocFirst; - return NS_OK; -} - NS_IMETHODIMP nsDocShell::GetDocShellEnumerator(PRInt32 aItemType, PRInt32 aDirection, nsISimpleEnumerator **outEnum) { @@ -1409,6 +1393,25 @@ nsDocShell::GetBusyFlags(PRUint32 * aBusyFlags) return NS_OK; } +NS_IMETHODIMP +nsDocShell::TabToTreeOwner(PRBool aForward, PRBool* aTookFocus) +{ + NS_ENSURE_ARG_POINTER(aTookFocus); + + nsCOMPtr chromeFocus = do_GetInterface(mTreeOwner); + if (chromeFocus) { + *aTookFocus = PR_TRUE; + if (aForward) + chromeFocus->FocusNextElement(); + else + chromeFocus->FocusPrevElement(); + } else + *aTookFocus = PR_FALSE; + + return NS_OK; +} + + //***************************************************************************** // nsDocShell::nsIDocShellTreeItem //***************************************************************************** @@ -2692,7 +2695,7 @@ nsDocShell::GetVisibility(PRBool * aVisibility) // convert the view's visibility attribute to a bool nsViewVisibility vis; - NS_ENSURE_TRUE(rootView->GetVisibility(vis), NS_ERROR_FAILURE); + NS_ENSURE_SUCCESS(rootView->GetVisibility(vis), NS_ERROR_FAILURE); *aVisibility = nsViewVisibility_kHide == vis ? PR_FALSE : PR_TRUE; return NS_OK; @@ -2720,28 +2723,6 @@ nsDocShell::GetMainWidget(nsIWidget ** aMainWidget) return GetParentWidget(aMainWidget); } -void -nsDocShell::ForceUpdate(nsIDocShell* aDocShell) -{ - NS_ASSERTION(aDocShell, "DocShell is null!"); - - nsCOMPtr presShell; - aDocShell->GetPresShell(getter_AddRefs(presShell)); - - // we might not have a presshell yet - if (!presShell) - return; - - nsCOMPtr vm; - presShell->GetViewManager(getter_AddRefs(vm)); - if (vm) { - vm->UpdateAllViews(NS_VMREFRESH_NO_SYNC); -#ifdef DEBUG_DOCSHELL_FOCUS - printf("nsDocShell::ForceUpdate - DS: %p **********\n", aDocShell); -#endif - } -} - NS_IMETHODIMP nsDocShell::SetFocus() { @@ -2749,353 +2730,14 @@ nsDocShell::SetFocus() printf("nsDocShell::SetFocus %p\n", (nsIDocShell*)this); #endif - nsCOMPtr presShell; - GetPresShell(getter_AddRefs(presShell)); - if (!presShell) - return NS_ERROR_FAILURE; - - /* Check to make sure the root frame for this document - is not collapsed. */ - nsIFrame* rootFrame; - presShell->GetRootFrame(&rootFrame); - if (rootFrame) { - nsRect frameRect; - rootFrame->GetRect(frameRect); - if (frameRect.IsEmpty()) { -#ifdef DEBUG_bryner - printf("SetFocus: empty frame rect, not accepting focus\n"); -#endif - return NS_ERROR_FAILURE; - } - } - - nsCOMPtr document; - presShell->GetDocument(getter_AddRefs(document)); - - // Figure out what type of document this is - // if parent doc is content then set focus to document itself - // and set the "special" flag so it knows we are at the beginning - // of the document - PRBool doFocusDoc = PR_FALSE; - nsIDocShellTreeItem* treeItem = NS_STATIC_CAST(nsIDocShellTreeItem *, this); - nsCOMPtr parentItem; - treeItem->GetParent(getter_AddRefs(parentItem)); - if (parentItem) { - PRInt32 type; - parentItem->GetItemType(&type); - doFocusDoc = type == nsIDocShellTreeItem::typeContent; - } - - if (mFocusDocFirst) - doFocusDoc = PR_TRUE; - // Tell itself (and the DocShellFocusController) who has focus // this way focus gets removed from the currently focused DocShell + SetHasFocus(PR_TRUE); - nsCOMPtr focusContent; - - nsCOMPtr esm; - - nsCOMPtr presContext; - GetPresContext(getter_AddRefs(presContext)); - if (presContext) { - presContext->GetEventStateManager(getter_AddRefs(esm)); - nsCOMPtr rootContent; - document->GetRootContent(getter_AddRefs(rootContent)); - if (esm && rootContent) { - // Either focus the document or the "first" piece of content - if (doFocusDoc) { - esm->SetContentState(nsnull, NS_EVENT_STATE_FOCUS); - } else { - nsCOMPtr content; - esm->GetNextTabbableIndexContent(rootContent, PR_TRUE, PR_TRUE, getter_AddRefs(content)); - if (!content) { - esm->GetNextTabbableContent(rootContent, nsnull, PR_TRUE, - getter_AddRefs(focusContent)); - } else { - focusContent = content; - } - } - } - } - - if (focusContent) { - nsIFrame *focusFrame = nsnull; - presShell->GetPrimaryFrameFor(focusContent, &focusFrame); - esm->ChangeFocus(focusContent, focusFrame, PR_TRUE); - SetCanvasHasFocus(PR_FALSE); - } else { - nsCOMPtr sgo; - document->GetScriptGlobalObject(getter_AddRefs(sgo)); - if (sgo) { - nsCOMPtr domwin(do_QueryInterface(sgo)); - if (domwin) - domwin->Focus(); - } - } - return NS_OK; } -//------------------------------------------------- -// Finds the very next DocShell after the arg aNode -nsresult -nsDocShell::FindNextChildDoc(nsIDocShellTreeNode* aNode, PRBool aForward, nsIDocShell** aDocShell) -{ - NS_ENSURE_ARG_POINTER(aNode); - *aDocShell = nsnull; - - PRInt32 count; - aNode->GetChildCount(&count); - if (count > 0) { - nsCOMPtr child; - aNode->GetChildAt(aForward?0:count-1, getter_AddRefs(child)); - NS_ASSERTION(child, "Child can't be null!"); - nsCOMPtrds = do_QueryInterface(child); - *aDocShell = ds.get(); - NS_ADDREF(*aDocShell); - return NS_OK; - } - - return NS_ERROR_FAILURE; -} - -//------------------------------------------------- -// Finds the very next DocShell after the arg aNode -PRBool -nsDocShell::FocusNextChild(nsIBaseWindow * aCurrentFocus, PRBool aForward) -{ - // Make sure the current focused item is content - // and if so find the next content DS and give it focus - nsCOMPtr treeItem(do_QueryInterface(aCurrentFocus)); - if (treeItem) { - PRInt32 type; - treeItem->GetItemType(&type); - if (type == nsIDocShellTreeItem::typeContent) { - nsCOMPtr docShell(do_QueryInterface(aCurrentFocus)); - if (!docShell) return PR_FALSE; - - nsCOMPtr treeNode(do_QueryInterface(aCurrentFocus)); - if (!treeNode) return PR_FALSE; - PRInt32 childCount; - treeNode->GetChildCount(&childCount); - - nsCOMPtr presContext; - docShell->GetPresContext(getter_AddRefs(presContext)); - if (!presContext) return PR_FALSE; - - nsCOMPtr esm; - presContext->GetEventStateManager(getter_AddRefs(esm)); - if (!esm) return PR_FALSE; - - nsCOMPtr presShell; - docShell->GetPresShell(getter_AddRefs(presShell)); - if (!presShell) return PR_FALSE; - - nsCOMPtr document; - presShell->GetDocument(getter_AddRefs(document)); - if (!document) return PR_FALSE; - - nsIEventStateManager::eDocType docType; - if (NS_FAILED(esm->FigureOutKindOfDoc(document, &docType))) return PR_FALSE; - - nsCOMPtr rootContent; - document->GetRootContent(getter_AddRefs(rootContent)); - if (!rootContent) return PR_FALSE; - - PRBool hasTabIndexes; - esm->HasPositiveTabIndex(rootContent, &hasTabIndexes); // ignoring return code - - nsIDocShell* thisDS = NS_STATIC_CAST(nsIDocShell *, this); - // leave printf for debugging - //printf("DS: %p TBI: %s chld: %s DSE: %s\n", docShell.get(), hasTabIndexes?"Y":"N", childCount > 0?"Y":"N", docShell.get() != thisDS?"Y":"N"); - if (docType == nsIEventStateManager::eFrameSet || - (docShell.get() != thisDS && !hasTabIndexes && childCount > 0)) { - nsCOMPtr childDS; - if (NS_SUCCEEDED(FindNextChildDoc(treeNode, aForward, getter_AddRefs(childDS)))) { - nsCOMPtr baseWin(do_QueryInterface(childDS)); - if (NS_SUCCEEDED(baseWin->SetFocus())) { - MakeSureOfSetFocus(baseWin); - return PR_TRUE; - } - } - } else if (docShell.get() != thisDS) { - nsCOMPtr baseWin(do_QueryInterface(docShell)); - if (NS_SUCCEEDED(baseWin->SetFocus())) { - MakeSureOfSetFocus(baseWin); - return PR_TRUE; - } - } - } - } - return PR_FALSE; -} - -//------------------------------------------------------------ -// This is just in case we run into a window that -// isn't implemented nsDocShell, because if it is implemented -// by this class then all this will have already been done. -void -nsDocShell::MakeSureOfSetFocus(nsIBaseWindow * aCurrentFocus, nsIDocShell* aDocShell) -{ - nsCOMPtr docShell = do_QueryInterface(aCurrentFocus); - if (!docShell) { - if (aDocShell != nsnull) { - docShell = aDocShell; - } else { - return; - } - } - - PRBool hasFocus; - docShell->GetHasFocus(&hasFocus); - - // leave printf for debugging purposes - //printf(">>>>>>>>>> nsDocShell::SetHasFocus: %p %s\n", docShell.get(), hasFocus?"Yes":"No"); - - if (!hasFocus) { - docShell->SetHasFocus(PR_TRUE); - - nsDocShellFocusController* dsfc = nsDocShellFocusController::GetInstance(); - if (dsfc) { - dsfc->Focus(docShell); - } - ForceUpdate(docShell);// Force Paint Here - } -} - -NS_IMETHODIMP -nsDocShell::FocusAvailable(nsIBaseWindow * aCurrentFocus, - PRBool aForward, PRBool * aTookFocus) -{ - NS_ENSURE_ARG_POINTER(aTookFocus); - - nsresult ret; - - // Are we embedded? - - nsCOMPtr - chromeFocus(do_GetInterface(mTreeOwner, &ret)); - if (chromeFocus) { -#ifdef DEBUG_dr - printf("dr :: nsDocShell::FocusAvailable, embedded\n"); -#endif - if (aForward) - ret = chromeFocus->FocusNextElement(); - else - ret = chromeFocus->FocusPrevElement(); - - if (NS_SUCCEEDED(ret)) { - // For DocShell's not implemented by this class - nsCOMPtr docShell(do_QueryInterface(chromeFocus)); - MakeSureOfSetFocus(nsnull, docShell); - *aTookFocus = PR_TRUE; - return ret; - } else { - // If the embeddor does not implement FocusNext/PrevElement, - // or some other error occurred, just focus ourselves again. - SetFocus(); - return NS_OK; - } - } - -#ifdef DEBUG_DOCSHELL_FOCUS - nsIDocShellTreeNode* node = NS_STATIC_CAST(nsIDocShellTreeNode *, this); - if (node) { - PrintDocTree(node); - } -#endif - - // Otherwise, first person we should call is the parent, or the - // docshell tree owner. - nsCOMPtr nextCallWin(do_QueryInterface(mParent)); - if (!nextCallWin) - nextCallWin = do_QueryInterface(mTreeOwner); - - //If the current focus is us, offer it to the next owner. - if (aCurrentFocus == NS_STATIC_CAST(nsIBaseWindow *, this)) { - if (nextCallWin) { - - // Make sure the current focused item is content - // and if so find the next content DS and give it focus - if (FocusNextChild(aCurrentFocus, aForward)) { - *aTookFocus = PR_TRUE; - return NS_OK; - } - - ret = nextCallWin->FocusAvailable(aCurrentFocus, - aForward, aTookFocus); - if (NS_SUCCEEDED(ret) && *aTookFocus) - return NS_OK; - } - - if (!mChildren.Count()) { - //If we don't have children and our parent didn't want - //the focus then we should just take focus again. - SetFocus(); - return NS_OK; - } - } - - - //Otherwise, check the children and offer it to the next sibling. - PRInt32 i; - PRInt32 n = mChildren.Count(); - for (i = 0; i < n; i++) { - nsCOMPtr - child(do_QueryInterface((nsISupports *) mChildren.ElementAt(i))); - //If we have focus we offer it to our first child. - if (aCurrentFocus == NS_STATIC_CAST(nsIBaseWindow *, this)) { - // Make sure the current focused item is content - // and if so find the next content DS and give it focus - if (FocusNextChild(child, aForward)) { - *aTookFocus = PR_TRUE; - return NS_OK; - } - - if (NS_SUCCEEDED(child->SetFocus())) { - *aTookFocus = PR_TRUE; - // For DocShell's not implemented by this class - MakeSureOfSetFocus(child); - return NS_OK; - } - } - //If we don't have focus, find the child that does then - //offer focus to the next one. - else if (child.get() == aCurrentFocus) { - while (++i < n) { - child = - do_QueryInterface((nsISupports *) mChildren.ElementAt(i)); - if (NS_SUCCEEDED(child->SetFocus())) { - *aTookFocus = PR_TRUE; - // For DocShell's not implemented by this class - MakeSureOfSetFocus(child); - return NS_OK; - } - } - break; - } - } - - //Reached the end of our child list. If we aren't currently focused, try - // to accept focus. - - if ((aCurrentFocus != NS_STATIC_CAST(nsIBaseWindow *, this)) && - NS_SUCCEEDED(SetFocus())) { - *aTookFocus = PR_TRUE; - return NS_OK; - } - - // Call again to offer focus upwards and to start at the beginning of our - // child list if no one above us wants focus. - if (NS_STATIC_CAST(nsIBaseWindow*, this) != aCurrentFocus) - return FocusAvailable(this, aForward, aTookFocus); - - *aTookFocus = PR_FALSE; - return NS_OK; -} - NS_IMETHODIMP nsDocShell::GetTitle(PRUnichar ** aTitle) { @@ -6064,16 +5706,9 @@ nsDocShell::GetHasFocus(PRBool *aHasFocus) NS_IMETHODIMP nsDocShell::SetHasFocus(PRBool aHasFocus) { - if (mParent != nsnull) { - PRInt32 type; - mParent->GetItemType(&type); - if (type != nsIDocShellTreeItem::typeContent) { - return NS_OK; - } - } - - // leave printf for debgging purposes - //printf(">>>>>>>>>> nsDocShell::SetHasFocus: %p %s\n", this, aHasFocus?"Yes":"No"); +#ifdef DEBUG_DOCSHELL_FOCUS + printf(">>>>>>>>>> nsDocShell::SetHasFocus: %p %s\n", this, aHasFocus?"Yes":"No"); +#endif mHasFocus = aHasFocus; @@ -6082,10 +5717,14 @@ nsDocShell::SetHasFocus(PRBool aHasFocus) dsfc->Focus(this); } - SetCanvasHasFocus(aHasFocus); + 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); + } - // Force Paint Here - ForceUpdate(this); return NS_OK; } @@ -6114,6 +5753,17 @@ nsDocShell::SetCanvasHasFocus(PRBool aCanvasHasFocus) nsICanvasFrame* canvasFrame; if (NS_SUCCEEDED(frame->QueryInterface(NS_GET_IID(nsICanvasFrame), (void**)&canvasFrame))) { canvasFrame->SetHasFocus(aCanvasHasFocus); + + nsCOMPtr presContext; + GetPresContext(getter_AddRefs(presContext)); + + nsIView* canvasView = nsnull; + frame->GetView(presContext, &canvasView); + + nsCOMPtr viewManager; + canvasView->GetViewManager(*getter_AddRefs(viewManager)); + viewManager->UpdateView(canvasView, NS_VMREFRESH_NO_SYNC); + return NS_OK; } } diff --git a/mozilla/docshell/base/nsDocShell.h b/mozilla/docshell/base/nsDocShell.h index 04100f73237..c80f69e1456 100644 --- a/mozilla/docshell/base/nsDocShell.h +++ b/mozilla/docshell/base/nsDocShell.h @@ -278,12 +278,6 @@ protected: PRBool IsFrame(); - // DocShell Focus helpers - void ForceUpdate(nsIDocShell* aDocShell); - nsresult FindNextChildDoc(nsIDocShellTreeNode* aNode, PRBool aForward, nsIDocShell** aDocShell); - PRBool FocusNextChild(nsIBaseWindow * aCurrentFocus, PRBool aForward); - void MakeSureOfSetFocus(nsIBaseWindow * aCurrentFocus, nsIDocShell* aDocShell = nsnull); - // // Helper method that is called when a new document (including any // sub-documents - ie. frames) has been completely loaded. diff --git a/mozilla/docshell/base/nsIDocShell.idl b/mozilla/docshell/base/nsIDocShell.idl index b2fb013cd76..3871fe4fcc7 100644 --- a/mozilla/docshell/base/nsIDocShell.idl +++ b/mozilla/docshell/base/nsIDocShell.idl @@ -198,13 +198,6 @@ interface nsIDocShell : nsISupports */ attribute boolean allowSubframes; - /** - * Attribute stating whether the document itself should come before - * its focusable content in tab traversal (the default is for the document - * to be focused last). - */ - attribute boolean focusDocBeforeContent; - /** * Attribute stating whether or not images should be loaded. */ @@ -263,6 +256,13 @@ interface nsIDocShell : nsISupports */ 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 */ diff --git a/mozilla/dom/src/base/nsFocusController.cpp b/mozilla/dom/src/base/nsFocusController.cpp index 147b8a25f72..99f5b22710e 100644 --- a/mozilla/dom/src/base/nsFocusController.cpp +++ b/mozilla/dom/src/base/nsFocusController.cpp @@ -39,6 +39,8 @@ #include "prlog.h" #include "nsIDOMEventTarget.h" #include "nsIEventStateManager.h" +#include "nsIDocShell.h" +#include "nsIBaseWindow.h" #ifdef INCLUDE_XUL #include "nsIDOMXULDocument.h" @@ -111,6 +113,16 @@ nsFocusController::SetFocusedElement(nsIDOMElement* aElement) NS_IMETHODIMP nsFocusController::SetFocusedWindow(nsIDOMWindowInternal* aWindow) { + if (aWindow && (mCurrentWindow != aWindow)) { + nsCOMPtr sgo = do_QueryInterface(aWindow); + if (sgo) { + nsCOMPtr docShell; + sgo->GetDocShell(getter_AddRefs(docShell)); + nsCOMPtr basewin = do_QueryInterface(docShell); + if (basewin) + basewin->SetFocus(); + } + } mCurrentWindow = aWindow; return NS_OK; } @@ -217,7 +229,7 @@ nsFocusController::MoveFocus(PRBool aForward, nsIDOMElement* aElt) presContext->GetEventStateManager(getter_AddRefs(esm)); if (esm) // Make this ESM shift the focus per our instructions. - esm->MoveFocus(aForward, content); + esm->ShiftFocus(aForward, content); return NS_OK; } diff --git a/mozilla/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp b/mozilla/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp index 608bf8f1b5b..951fa239bdf 100644 --- a/mozilla/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp +++ b/mozilla/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp @@ -626,13 +626,6 @@ NS_IMETHODIMP nsDocShellTreeOwner::SetFocus() return NS_ERROR_NULL_POINTER; } -NS_IMETHODIMP nsDocShellTreeOwner::FocusAvailable(nsIBaseWindow* aCurrentFocus, - PRBool aForward, - PRBool* aTookFocus) -{ - return NS_ERROR_NULL_POINTER; -} - NS_IMETHODIMP nsDocShellTreeOwner::GetTitle(PRUnichar** aTitle) { if (mOwnerWin) diff --git a/mozilla/embedding/browser/webBrowser/nsIWebBrowserSetup.idl b/mozilla/embedding/browser/webBrowser/nsIWebBrowserSetup.idl index 730d768fc81..f1e5d233eb5 100644 --- a/mozilla/embedding/browser/webBrowser/nsIWebBrowserSetup.idl +++ b/mozilla/embedding/browser/webBrowser/nsIWebBrowserSetup.idl @@ -80,6 +80,8 @@ interface nsIWebBrowserSetup : nsISupports * Enables/disables whether the document as a whole gets focus before * traversing the document's content, or after traversing its content. * + * NOTE: this property is obsolete and now has no effect + * * @see setProperty */ const unsigned long SETUP_FOCUS_DOC_BEFORE_CONTENT = 6; diff --git a/mozilla/embedding/browser/webBrowser/nsWebBrowser.cpp b/mozilla/embedding/browser/webBrowser/nsWebBrowser.cpp index b178aa721d9..5b66d001121 100644 --- a/mozilla/embedding/browser/webBrowser/nsWebBrowser.cpp +++ b/mozilla/embedding/browser/webBrowser/nsWebBrowser.cpp @@ -702,9 +702,7 @@ NS_IMETHODIMP nsWebBrowser::SetProperty(PRUint32 aId, PRUint32 aValue) break; case nsIWebBrowserSetup::SETUP_FOCUS_DOC_BEFORE_CONTENT: { - NS_ENSURE_STATE(mDocShell); - NS_ENSURE_TRUE((aValue == PR_TRUE || aValue == PR_FALSE), NS_ERROR_INVALID_ARG); - mDocShell->SetFocusDocBeforeContent(aValue); + // obsolete } break; default: @@ -1295,38 +1293,6 @@ NS_IMETHODIMP nsWebBrowser::SetFocus() return NS_OK; } -NS_IMETHODIMP nsWebBrowser::FocusAvailable(nsIBaseWindow* aCurrentFocus, - PRBool aForward, - PRBool* aTookFocus) -{ - NS_ENSURE_ARG_POINTER(aTookFocus); - - // Next person we should call is first the parent otherwise the - // docshell tree owner. - nsCOMPtr nextCallWin(do_QueryInterface(mParent)); - if(!nextCallWin) - nextCallWin = do_QueryInterface(nsnull /*mTreeOwner*/); - - //If the current focus is us, offer it to the next owner. - if(aCurrentFocus == NS_STATIC_CAST(nsIBaseWindow*, this)) - { - if(nextCallWin) - return nextCallWin->FocusAvailable(aCurrentFocus, - aForward, aTookFocus); - return NS_OK; - } - - //Otherwise, check the chilren and offer it to the next sibling. - if((mDocShellAsWin.get() != aCurrentFocus) && - NS_SUCCEEDED(mDocShellAsWin->SetFocus())) - { - *aTookFocus = PR_TRUE; - return NS_OK; - } - - return NS_OK; -} - NS_IMETHODIMP nsWebBrowser::GetTitle(PRUnichar** aTitle) { NS_ENSURE_ARG_POINTER(aTitle); diff --git a/mozilla/layout/base/nsIPresShell.h b/mozilla/layout/base/nsIPresShell.h index a35b36d585c..c2eefdff9fc 100644 --- a/mozilla/layout/base/nsIPresShell.h +++ b/mozilla/layout/base/nsIPresShell.h @@ -270,6 +270,14 @@ public: NS_IMETHOD SetSubShellFor(nsIContent* aContent, nsISupports* aSubShell) = 0; + /** + * Find the content in the map that has aSubShell set + * as its subshell. If there is more than one mapping for + * aSubShell, the result is undefined. + */ + NS_IMETHOD FindContentForShell(nsISupports* aSubShell, + nsIContent** aContent) const = 0; + /** * Gets the placeholder frame associated with the specified frame. This is * a helper frame that forwards the request to the frame manager. diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index ea5dd762afd..fd2c53a3811 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -791,6 +791,29 @@ DummyLayoutRequest::Cancel(nsresult status) return rv; } +// ---------------------------------------------------------------------------- +// A generic nsDSTNodeFunctor to look for a specific value in the map + +class nsSearchEnumerator : public nsDSTNodeFunctor +{ +public: + nsSearchEnumerator(void* aTargetValue) + : mTargetValue(aTargetValue) { + mResultKey = nsnull; + } + + void operator() (void* aKey, void* aValue) { + if (aValue == mTargetValue) + mResultKey = aKey; + } + + void* GetResult() { return mResultKey; } + +private: + void* mResultKey; + void* mTargetValue; +}; + // ---------------------------------------------------------------------------- class PresShell : public nsIPresShell, public nsIViewObserver, @@ -856,6 +879,8 @@ public: nsISupports** aResult) const; NS_IMETHOD SetSubShellFor(nsIContent* aContent, nsISupports* aSubShell); + NS_IMETHOD FindContentForShell(nsISupports* aSubShell, + nsIContent** aContent) const; NS_IMETHOD GetPlaceholderFrameFor(nsIFrame* aFrame, nsIFrame** aPlaceholderFrame) const; NS_IMETHOD AppendReflowCommand(nsIReflowCommand* aReflowCommand); @@ -5334,6 +5359,24 @@ PresShell::SetSubShellFor(nsIContent* aContent, return NS_OK; } +NS_IMETHODIMP +PresShell::FindContentForShell(nsISupports* aSubShell, + nsIContent** aContent) const +{ + NS_ENSURE_ARG_POINTER(aSubShell); + NS_ENSURE_ARG_POINTER(aContent); + *aContent = nsnull; + + if (!mSubShellMap) + return NS_OK; + + nsSearchEnumerator enumerator(NS_STATIC_CAST(void*, aSubShell)); + mSubShellMap->Enumerate(enumerator); + *aContent = NS_STATIC_CAST(nsIContent*, enumerator.GetResult()); + NS_IF_ADDREF(*aContent); + + return NS_OK; +} NS_IMETHODIMP PresShell::GetPlaceholderFrameFor(nsIFrame* aFrame, diff --git a/mozilla/layout/base/public/nsIPresShell.h b/mozilla/layout/base/public/nsIPresShell.h index a35b36d585c..c2eefdff9fc 100644 --- a/mozilla/layout/base/public/nsIPresShell.h +++ b/mozilla/layout/base/public/nsIPresShell.h @@ -270,6 +270,14 @@ public: NS_IMETHOD SetSubShellFor(nsIContent* aContent, nsISupports* aSubShell) = 0; + /** + * Find the content in the map that has aSubShell set + * as its subshell. If there is more than one mapping for + * aSubShell, the result is undefined. + */ + NS_IMETHOD FindContentForShell(nsISupports* aSubShell, + nsIContent** aContent) const = 0; + /** * Gets the placeholder frame associated with the specified frame. This is * a helper frame that forwards the request to the frame manager. diff --git a/mozilla/layout/generic/nsHTMLFrame.cpp b/mozilla/layout/generic/nsHTMLFrame.cpp index 8594d1e2ff1..01a7352bb1a 100644 --- a/mozilla/layout/generic/nsHTMLFrame.cpp +++ b/mozilla/layout/generic/nsHTMLFrame.cpp @@ -166,7 +166,6 @@ public: protected: virtual PRIntn GetSkipSides() const; - void DrawDottedRect(nsIRenderingContext& aRenderingContext, nsRect& aRect); // Data members PRPackedBool mDoPaintFocus; @@ -381,26 +380,6 @@ CanvasFrame::RemoveFrame(nsIPresContext* aPresContext, return rv; } -void -CanvasFrame::DrawDottedRect(nsIRenderingContext& aRenderingContext, nsRect& aRect) -{ -#ifdef DEBUG_CANVAS_FOCUS - printf("** DrawDottedRect: %d,%d,%d,%d\n",aRect.x, aRect.y, aRect.width, aRect.height); -#endif - - aRenderingContext.DrawLine(aRect.x, aRect.y, - aRect.x+aRect.width, aRect.y); - aRenderingContext.DrawLine(aRect.x+aRect.width, aRect.y, - aRect.x+aRect.width, aRect.y+aRect.height); - aRenderingContext.DrawLine(aRect.x+aRect.width, aRect.y+aRect.height, - aRect.x, aRect.y+aRect.height); - aRenderingContext.DrawLine(aRect.x, aRect.y+aRect.height, - aRect.x, aRect.y); - aRenderingContext.DrawLine(aRect.x, aRect.y+aRect.height, - aRect.x, aRect.y); -} - - NS_IMETHODIMP CanvasFrame::Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -438,7 +417,6 @@ CanvasFrame::Paint(nsIPresContext* aPresContext, #endif if (mDoPaintFocus) { - aRenderingContext.PushState(); PRBool clipEmpty; nsRect focusRect; GetRect(focusRect); @@ -469,29 +447,37 @@ CanvasFrame::Paint(nsIPresContext* aPresContext, scrollableView->GetClipView(&clippedView); nsRect vcr; clippedView->GetBounds(vcr); + focusRect.width = vcr.width; focusRect.height = vcr.height; nscoord x,y; scrollableView->GetScrollPosition(x, y); focusRect.x += x; focusRect.y += y; } - aRenderingContext.SetLineStyle(nsLineStyle_kDotted); - aRenderingContext.SetColor(NS_RGB(0,0,0)); + nsStyleOutline outlineStyle(aPresContext); + outlineStyle.SetOutlineStyle(NS_STYLE_BORDER_STYLE_DOTTED); + outlineStyle.SetOutlineInvert(); + float p2t; aPresContext->GetPixelsToTwips(&p2t); + // XXX the CSS border for links is specified as 2px, but it + // is only drawn as 1px. Match this here. nscoord onePixel = NSIntPixelsToTwips(1, p2t); - focusRect.width -= onePixel; - focusRect.height -= onePixel; + nsRect borderInside(focusRect.x + onePixel, + focusRect.y + onePixel, + focusRect.width - 2 * onePixel, + focusRect.height - 2 * onePixel); - DrawDottedRect(aRenderingContext, focusRect); - - focusRect.Deflate(onePixel, onePixel); - DrawDottedRect(aRenderingContext, focusRect); + nsCSSRendering::DrawDashedSides(0, aRenderingContext, + focusRect, nsnull, + nsnull, &outlineStyle, + PR_TRUE, focusRect, + borderInside, 0, + nsnull); } } - aRenderingContext.PopState(clipEmpty); } } return rv; diff --git a/mozilla/layout/html/base/src/nsHTMLFrame.cpp b/mozilla/layout/html/base/src/nsHTMLFrame.cpp index 8594d1e2ff1..01a7352bb1a 100644 --- a/mozilla/layout/html/base/src/nsHTMLFrame.cpp +++ b/mozilla/layout/html/base/src/nsHTMLFrame.cpp @@ -166,7 +166,6 @@ public: protected: virtual PRIntn GetSkipSides() const; - void DrawDottedRect(nsIRenderingContext& aRenderingContext, nsRect& aRect); // Data members PRPackedBool mDoPaintFocus; @@ -381,26 +380,6 @@ CanvasFrame::RemoveFrame(nsIPresContext* aPresContext, return rv; } -void -CanvasFrame::DrawDottedRect(nsIRenderingContext& aRenderingContext, nsRect& aRect) -{ -#ifdef DEBUG_CANVAS_FOCUS - printf("** DrawDottedRect: %d,%d,%d,%d\n",aRect.x, aRect.y, aRect.width, aRect.height); -#endif - - aRenderingContext.DrawLine(aRect.x, aRect.y, - aRect.x+aRect.width, aRect.y); - aRenderingContext.DrawLine(aRect.x+aRect.width, aRect.y, - aRect.x+aRect.width, aRect.y+aRect.height); - aRenderingContext.DrawLine(aRect.x+aRect.width, aRect.y+aRect.height, - aRect.x, aRect.y+aRect.height); - aRenderingContext.DrawLine(aRect.x, aRect.y+aRect.height, - aRect.x, aRect.y); - aRenderingContext.DrawLine(aRect.x, aRect.y+aRect.height, - aRect.x, aRect.y); -} - - NS_IMETHODIMP CanvasFrame::Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -438,7 +417,6 @@ CanvasFrame::Paint(nsIPresContext* aPresContext, #endif if (mDoPaintFocus) { - aRenderingContext.PushState(); PRBool clipEmpty; nsRect focusRect; GetRect(focusRect); @@ -469,29 +447,37 @@ CanvasFrame::Paint(nsIPresContext* aPresContext, scrollableView->GetClipView(&clippedView); nsRect vcr; clippedView->GetBounds(vcr); + focusRect.width = vcr.width; focusRect.height = vcr.height; nscoord x,y; scrollableView->GetScrollPosition(x, y); focusRect.x += x; focusRect.y += y; } - aRenderingContext.SetLineStyle(nsLineStyle_kDotted); - aRenderingContext.SetColor(NS_RGB(0,0,0)); + nsStyleOutline outlineStyle(aPresContext); + outlineStyle.SetOutlineStyle(NS_STYLE_BORDER_STYLE_DOTTED); + outlineStyle.SetOutlineInvert(); + float p2t; aPresContext->GetPixelsToTwips(&p2t); + // XXX the CSS border for links is specified as 2px, but it + // is only drawn as 1px. Match this here. nscoord onePixel = NSIntPixelsToTwips(1, p2t); - focusRect.width -= onePixel; - focusRect.height -= onePixel; + nsRect borderInside(focusRect.x + onePixel, + focusRect.y + onePixel, + focusRect.width - 2 * onePixel, + focusRect.height - 2 * onePixel); - DrawDottedRect(aRenderingContext, focusRect); - - focusRect.Deflate(onePixel, onePixel); - DrawDottedRect(aRenderingContext, focusRect); + nsCSSRendering::DrawDashedSides(0, aRenderingContext, + focusRect, nsnull, + nsnull, &outlineStyle, + PR_TRUE, focusRect, + borderInside, 0, + nsnull); } } - aRenderingContext.PopState(clipEmpty); } } return rv; diff --git a/mozilla/layout/html/base/src/nsPresShell.cpp b/mozilla/layout/html/base/src/nsPresShell.cpp index ea5dd762afd..fd2c53a3811 100644 --- a/mozilla/layout/html/base/src/nsPresShell.cpp +++ b/mozilla/layout/html/base/src/nsPresShell.cpp @@ -791,6 +791,29 @@ DummyLayoutRequest::Cancel(nsresult status) return rv; } +// ---------------------------------------------------------------------------- +// A generic nsDSTNodeFunctor to look for a specific value in the map + +class nsSearchEnumerator : public nsDSTNodeFunctor +{ +public: + nsSearchEnumerator(void* aTargetValue) + : mTargetValue(aTargetValue) { + mResultKey = nsnull; + } + + void operator() (void* aKey, void* aValue) { + if (aValue == mTargetValue) + mResultKey = aKey; + } + + void* GetResult() { return mResultKey; } + +private: + void* mResultKey; + void* mTargetValue; +}; + // ---------------------------------------------------------------------------- class PresShell : public nsIPresShell, public nsIViewObserver, @@ -856,6 +879,8 @@ public: nsISupports** aResult) const; NS_IMETHOD SetSubShellFor(nsIContent* aContent, nsISupports* aSubShell); + NS_IMETHOD FindContentForShell(nsISupports* aSubShell, + nsIContent** aContent) const; NS_IMETHOD GetPlaceholderFrameFor(nsIFrame* aFrame, nsIFrame** aPlaceholderFrame) const; NS_IMETHOD AppendReflowCommand(nsIReflowCommand* aReflowCommand); @@ -5334,6 +5359,24 @@ PresShell::SetSubShellFor(nsIContent* aContent, return NS_OK; } +NS_IMETHODIMP +PresShell::FindContentForShell(nsISupports* aSubShell, + nsIContent** aContent) const +{ + NS_ENSURE_ARG_POINTER(aSubShell); + NS_ENSURE_ARG_POINTER(aContent); + *aContent = nsnull; + + if (!mSubShellMap) + return NS_OK; + + nsSearchEnumerator enumerator(NS_STATIC_CAST(void*, aSubShell)); + mSubShellMap->Enumerate(enumerator); + *aContent = NS_STATIC_CAST(nsIContent*, enumerator.GetResult()); + NS_IF_ADDREF(*aContent); + + return NS_OK; +} NS_IMETHODIMP PresShell::GetPlaceholderFrameFor(nsIFrame* aFrame, diff --git a/mozilla/layout/html/document/src/html.css b/mozilla/layout/html/document/src/html.css index f82b21961d3..73e8c070f2d 100644 --- a/mozilla/layout/html/document/src/html.css +++ b/mozilla/layout/html/document/src/html.css @@ -400,6 +400,7 @@ frameset { frame { background-color: transparent ! important; /* (b=49779) */ + -moz-user-focus: normal; } iframe { diff --git a/mozilla/layout/style/html.css b/mozilla/layout/style/html.css index f82b21961d3..73e8c070f2d 100644 --- a/mozilla/layout/style/html.css +++ b/mozilla/layout/style/html.css @@ -400,6 +400,7 @@ frameset { frame { background-color: transparent ! important; /* (b=49779) */ + -moz-user-focus: normal; } iframe { diff --git a/mozilla/webshell/tests/viewer/nsBrowserWindow.cpp b/mozilla/webshell/tests/viewer/nsBrowserWindow.cpp index cd445e5a831..67e86921ebf 100644 --- a/mozilla/webshell/tests/viewer/nsBrowserWindow.cpp +++ b/mozilla/webshell/tests/viewer/nsBrowserWindow.cpp @@ -401,15 +401,6 @@ NS_IMETHODIMP nsBrowserWindow::SetFocus() return NS_OK; } -NS_IMETHODIMP nsBrowserWindow::FocusAvailable(nsIBaseWindow* aCurrentFocus, - PRBool aForward, - PRBool* aTookFocus) -{ - //XXX First Check In - NS_ASSERTION(PR_FALSE, "Not Yet Implemented"); - return NS_OK; -} - NS_IMETHODIMP nsBrowserWindow::GetTitle(PRUnichar** aTitle) { NS_ENSURE_ARG_POINTER(aTitle); @@ -2091,12 +2082,6 @@ nsBrowserWindow::FindWebShellWithName(const PRUnichar* aName, nsIWebShell*& aRes return NS_OK; } -NS_IMETHODIMP -nsBrowserWindow::FocusAvailable(nsIWebShell* aFocusedWebShell, PRBool& aFocusTaken) -{ - return NS_OK; -} - //---------------------------------------- diff --git a/mozilla/webshell/tests/viewer/nsBrowserWindow.h b/mozilla/webshell/tests/viewer/nsBrowserWindow.h index 348d0d7ea55..8f2726e2f24 100644 --- a/mozilla/webshell/tests/viewer/nsBrowserWindow.h +++ b/mozilla/webshell/tests/viewer/nsBrowserWindow.h @@ -139,7 +139,6 @@ public: nsIWebShell *&aNewWebShell); NS_IMETHOD ContentShellAdded(nsIWebShell* aChildShell, nsIContent* frameNode); NS_IMETHOD FindWebShellWithName(const PRUnichar* aName, nsIWebShell*& aResult); - NS_IMETHOD FocusAvailable(nsIWebShell* aFocusedWebShell, PRBool& aFocusTaken); // nsBrowserWindow void SetWebCrawler(nsWebCrawler* aWebCrawler); diff --git a/mozilla/widget/public/nsIBaseWindow.idl b/mozilla/widget/public/nsIBaseWindow.idl index d4a04b94a89..26da3d0e22c 100644 --- a/mozilla/widget/public/nsIBaseWindow.idl +++ b/mozilla/widget/public/nsIBaseWindow.idl @@ -186,21 +186,6 @@ interface nsIBaseWindow : nsISupports */ void setFocus(); - /* This is called when focus is available for the taking because of - tabbing through an object. In any case this is called on an object to - allow it to take focus if it desires. If the aCurrentFocus object is - the object being called, then the object being called should offer focus to - it's parent. If the aCurrentFocus is a child of the object being called, - the object being called should set the focus to the next sibling to the - aCurrentFocus object. Otherwise it should take focus for itself. If the - object being called can not take focus for itself it should offer focus to - it's parent. Note an object should not take focus for itself by giving it - to a child. In most cases this function is being called because the child - is trying to give up focus. */ - void focusAvailable(in nsIBaseWindow aCurrentFocus, - in boolean aForward, - out boolean aTookFocus); - /* Title of the window. */ diff --git a/mozilla/widget/src/windows/nsWindow.cpp b/mozilla/widget/src/windows/nsWindow.cpp index 23337c9d711..fb3ef4d5231 100644 --- a/mozilla/widget/src/windows/nsWindow.cpp +++ b/mozilla/widget/src/windows/nsWindow.cpp @@ -2463,6 +2463,9 @@ BOOL nsWindow::OnKeyDown( UINT aVirtualKeyCode, UINT aScanCode) { DispatchKeyEvent(NS_KEY_PRESS, 0, aVirtualKeyCode); } + else if (mIsControlDown && aVirtualKeyCode == NS_VK_TAB) { + DispatchKeyEvent(NS_KEY_PRESS, 0, NS_VK_TAB); + } else if (mIsControlDown && aVirtualKeyCode == NS_VK_SUBTRACT) { DispatchKeyEvent(NS_KEY_PRESS, aVirtualKeyCode-64, 0); } diff --git a/mozilla/xpfe/appshell/src/nsChromeTreeOwner.cpp b/mozilla/xpfe/appshell/src/nsChromeTreeOwner.cpp index 8e4576d8a78..3b7e030ab6a 100644 --- a/mozilla/xpfe/appshell/src/nsChromeTreeOwner.cpp +++ b/mozilla/xpfe/appshell/src/nsChromeTreeOwner.cpp @@ -311,13 +311,6 @@ NS_IMETHODIMP nsChromeTreeOwner::SetFocus() return mXULWindow->SetFocus(); } -NS_IMETHODIMP nsChromeTreeOwner::FocusAvailable(nsIBaseWindow* aCurrentFocus, - PRBool aForward, - PRBool* aTookFocus) -{ - return mXULWindow->FocusAvailable(aCurrentFocus, aForward, aTookFocus); -} - NS_IMETHODIMP nsChromeTreeOwner::GetTitle(PRUnichar** aTitle) { return mXULWindow->GetTitle(aTitle); diff --git a/mozilla/xpfe/appshell/src/nsContentTreeOwner.cpp b/mozilla/xpfe/appshell/src/nsContentTreeOwner.cpp index 2db3de9e23f..b07a5ad22af 100644 --- a/mozilla/xpfe/appshell/src/nsContentTreeOwner.cpp +++ b/mozilla/xpfe/appshell/src/nsContentTreeOwner.cpp @@ -533,13 +533,6 @@ NS_IMETHODIMP nsContentTreeOwner::SetFocus() return mXULWindow->SetFocus(); } -NS_IMETHODIMP nsContentTreeOwner::FocusAvailable(nsIBaseWindow* aCurrentFocus, - PRBool aForward, - PRBool* aTookFocus) -{ - return mXULWindow->FocusAvailable(aCurrentFocus, aForward, aTookFocus); -} - NS_IMETHODIMP nsContentTreeOwner::GetTitle(PRUnichar** aTitle) { NS_ENSURE_ARG_POINTER(aTitle); diff --git a/mozilla/xpfe/appshell/src/nsXULWindow.cpp b/mozilla/xpfe/appshell/src/nsXULWindow.cpp index f742e685edf..363caea7c8c 100644 --- a/mozilla/xpfe/appshell/src/nsXULWindow.cpp +++ b/mozilla/xpfe/appshell/src/nsXULWindow.cpp @@ -618,13 +618,6 @@ NS_IMETHODIMP nsXULWindow::SetFocus() return NS_OK; } -NS_IMETHODIMP nsXULWindow::FocusAvailable(nsIBaseWindow* aCurrentFocus, - PRBool aForward, - PRBool* aTookFocus) -{ - return NS_OK; -} - NS_IMETHODIMP nsXULWindow::GetTitle(PRUnichar** aTitle) { NS_ENSURE_ARG_POINTER(aTitle); diff --git a/mozilla/xpfe/global/resources/content/bindings/tabbox.xml b/mozilla/xpfe/global/resources/content/bindings/tabbox.xml index 2b9d2e6c231..63af45029d4 100644 --- a/mozilla/xpfe/global/resources/content/bindings/tabbox.xml +++ b/mozilla/xpfe/global/resources/content/bindings/tabbox.xml @@ -15,6 +15,19 @@ + + + + + + + + + @@ -196,10 +213,20 @@ diff --git a/mozilla/xpfe/global/resources/content/bindings/tabbrowser.xml b/mozilla/xpfe/global/resources/content/bindings/tabbrowser.xml index 07cc57232f5..7f2a1acd673 100644 --- a/mozilla/xpfe/global/resources/content/bindings/tabbrowser.xml +++ b/mozilla/xpfe/global/resources/content/bindings/tabbrowser.xml @@ -681,6 +681,7 @@ this.mCurrentBrowser = this.mPanelContainer.firstChild; this.mCurrentTab = this.mTabContainer.firstChild; + this.mTabBox.setAttribute("handleCtrlTab", "false"); diff --git a/mozilla/xpfe/global/resources/content/xul.css b/mozilla/xpfe/global/resources/content/xul.css index f78661054b9..9fdaba8241a 100644 --- a/mozilla/xpfe/global/resources/content/xul.css +++ b/mozilla/xpfe/global/resources/content/xul.css @@ -45,7 +45,10 @@ bindings, binding, content, member, triple { checkbox, colorpicker[type="button"], menulist, -outliner { +outliner, +browser, +editor, +iframe { -moz-user-focus: normal; }