bug 108791 - infinite recursion crash when tabbing if there is no focusable content. r=saari, sr=sfraser.

This commit is contained in:
bryner%netscape.com 2002-02-01 05:14:44 +00:00
Родитель 6f66239aa4
Коммит 1ebc6d2820
2 изменённых файлов: 35 добавлений и 13 удалений

Просмотреть файл

@ -2553,11 +2553,24 @@ PrintDocTree(nsIDocShellTreeNode * aParentNode, int aLevel)
#endif // end debug helpers
NS_IMETHODIMP
nsEventStateManager::ShiftFocus(PRBool forward, nsIContent* aStart)
nsEventStateManager::ShiftFocus(PRBool aForward, nsIContent* aStart)
{
// 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] ShiftFocus: forward=%d, aStart=%p, mCurrentFocus=%p\n",
this, forward, aStart, mCurrentFocus);
printf("[%p] ShiftFocus: aForward=%d, aStart=%p, mCurrentFocus=%p\n",
this, aForward, aStart, mCurrentFocus);
#endif
NS_ASSERTION(mPresContext, "no pres context");
EnsureDocument(mPresContext);
@ -2600,7 +2613,7 @@ nsEventStateManager::ShiftFocus(PRBool forward, nsIContent* aStart)
// So, use the docshell focus state to disambiguate.
docShell->GetHasFocus(&docHasFocus);
if (forward) {
if (aForward) {
mCurrentFocus = rootContent;
NS_IF_ADDREF(mCurrentFocus);
mCurrentTabIndex = 1;
@ -2627,8 +2640,8 @@ nsEventStateManager::ShiftFocus(PRBool forward, nsIContent* aStart)
presShell->GetPrimaryFrameFor(mCurrentFocus, &curFocusFrame);
nsCOMPtr<nsIContent> nextFocus;
if (forward || !docHasFocus)
GetNextTabbableContent(rootContent, curFocusFrame, forward,
if (aForward || !docHasFocus)
GetNextTabbableContent(rootContent, curFocusFrame, aForward,
getter_AddRefs(nextFocus));
if (nextFocus) {
@ -2648,7 +2661,7 @@ nsEventStateManager::ShiftFocus(PRBool forward, nsIContent* aStart)
presShell->GetPrimaryFrameFor(nextFocus, &nextFocusFrame);
presShell->ScrollFrameIntoView(nextFocusFrame, NS_PRESSHELL_SCROLL_ANYWHERE,
NS_PRESSHELL_SCROLL_ANYWHERE);
TabIntoDocument(subShell, forward);
TabIntoDocument(subShell, aForward);
}
} else {
// there is no subshell, so just focus nextFocus
@ -2683,7 +2696,7 @@ nsEventStateManager::ShiftFocus(PRBool forward, nsIContent* aStart)
focusDocument = !(IsFrameSetDoc(docShell));
}
if (!forward && !docHasFocus && focusDocument) {
if (!aForward && !docHasFocus && focusDocument) {
#ifdef DEBUG_DOCSHELL_FOCUS
printf("Focusing document\n");
#endif
@ -2696,6 +2709,11 @@ nsEventStateManager::ShiftFocus(PRBool forward, nsIContent* aStart)
// 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;
mTabbedThroughDocument = PR_TRUE;
nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(pcContainer);
nsCOMPtr<nsIDocShellTreeItem> treeParent;
treeItem->GetParent(getter_AddRefs(treeParent));
@ -2720,13 +2738,13 @@ nsEventStateManager::ShiftFocus(PRBool forward, nsIContent* aStart)
printf("popping out focus to parent docshell\n");
#endif
parentESM->ShiftFocus(forward, shellContent);
parentESM->ShiftFocus(aForward, shellContent);
}
} else {
PRBool tookFocus = PR_FALSE;
nsCOMPtr<nsIDocShell> subShell = do_QueryInterface(pcContainer);
if (subShell)
subShell->TabToTreeOwner(forward, &tookFocus);
subShell->TabToTreeOwner(aForward, &tookFocus);
#ifdef DEBUG_DOCSHEL_FOCUS
printf("offered focus to tree owner, tookFocus=%d\n",
@ -2746,7 +2764,7 @@ nsEventStateManager::ShiftFocus(PRBool forward, nsIContent* aStart)
NS_IF_RELEASE(mCurrentFocus);
docShell->SetHasFocus(PR_FALSE);
ShiftFocus(forward);
ShiftFocusInternal(aForward);
}
}
}

Просмотреть файл

@ -130,7 +130,7 @@ public:
//Method for centralized distribution of new DOM events
NS_IMETHOD DispatchNewEvent(nsISupports* aTarget, nsIDOMEvent* aEvent, PRBool *aPreventDefault);
NS_IMETHOD ShiftFocus(PRBool forward, nsIContent* aStart=nsnull);
NS_IMETHOD ShiftFocus(PRBool aForward, nsIContent* aStart=nsnull);
protected:
void UpdateCursor(nsIPresContext* aPresContext, nsEvent* aEvent, nsIFrame* aTargetFrame, nsEventStatus* aStatus);
@ -152,6 +152,7 @@ protected:
// 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);
@ -253,7 +254,10 @@ protected:
// So we don't have to keep checking accessibility.browsewithcaret pref
PRBool mBrowseWithCaret;
// Recursion guard for tabbing
PRBool mTabbedThroughDocument;
#ifdef CLICK_HOLD_CONTEXT_MENUS
enum { kClickHoldDelay = 500 } ; // 500ms == 1/2 second