diff --git a/toolkit/components/typeaheadfind/content/findBar.inc b/toolkit/components/typeaheadfind/content/findBar.inc index 60a89447abe2..a45bbf8e4ba1 100755 --- a/toolkit/components/typeaheadfind/content/findBar.inc +++ b/toolkit/components/typeaheadfind/content/findBar.inc @@ -6,6 +6,7 @@ diff --git a/toolkit/components/typeaheadfind/content/findBar.js b/toolkit/components/typeaheadfind/content/findBar.js index 44726f556465..4af88c3b6567 100755 --- a/toolkit/components/typeaheadfind/content/findBar.js +++ b/toolkit/components/typeaheadfind/content/findBar.js @@ -58,10 +58,14 @@ const CHAR_CODE_APOSTROPHE = "'".charCodeAt(0); */ var gFindBar = { + SELECTION_CONTROLLER: Components.interfaces.nsISelectionController, + mFindEnabled: true, mFindMode: FIND_NORMAL, mFoundLink: null, + mFoundEditable: null, mCurrentWindow: null, + mHasFocus: false, mTmpOutline: null, mTmpOutlineOffset: "0", mDrawOutline: false, @@ -144,9 +148,6 @@ var gFindBar = { this.mTypeAheadCaseSensitive = prefService.getIntPref("accessibility.typeaheadfind.casesensitive"); - var fastFind = getBrowser().fastFind; - fastFind.focusLinks = true; - var findField = document.getElementById("find-field"); findField.addEventListener("dragdrop", findBar_OnDrop, true); @@ -368,41 +369,6 @@ var gFindBar = { return node; }, - getSelectionControllerForFindToolbar: function (ds) - { - try { - var display = - ds.QueryInterface(Components.interfaces.nsIInterfaceRequestor) - .getInterface(Components.interfaces.nsISelectionDisplay); - } - catch (e) { return null; } - return display.QueryInterface(Components.interfaces.nsISelectionController); - }, - - changeSelectionColor: function (aAttention) - { - try { - var ds = getBrowser().docShell; - } catch(e) { - // If we throw here, the browser we were in is already destroyed. - // See bug 273200. - return; - } - var dsEnum = ds.getDocShellEnumerator( - Components.interfaces.nsIDocShellTreeItem.typeContent, - Components.interfaces.nsIDocShell.ENUMERATE_FORWARDS); - while (dsEnum.hasMoreElements()) { - ds = dsEnum.getNext().QueryInterface(Components.interfaces.nsIDocShell); - var controller = this.getSelectionControllerForFindToolbar(ds); - if (!controller) - continue; - const selCon = Components.interfaces.nsISelectionController; - controller.setDisplaySelection(aAttention ? - selCon.SELECTION_ATTENTION : - selCon.SELECTION_ON); - } - }, - setCaseSensitiveStr: function (val) { var findToolbar = document.getElementById("FindToolbar"); @@ -557,7 +523,11 @@ var gFindBar = { try { if (this.mFoundLink) this.mFoundLink.focus(); - else if (this.mCurrentWindow) + else if (this.mFoundEditable) { + this.mFoundEditable.focus(); + var fastFind = getBrowser().fastFind; + fastFind.collapseSelection(); + } else if (this.mCurrentWindow) this.mCurrentWindow.focus(); else return false; @@ -566,9 +536,6 @@ var gFindBar = { return false; } - // NOTE: In this time, gFoundLink and gCurrentWindow are set null. - // Because find toolbar lost focus. - if (aKeypressEvent) aKeypressEvent.preventDefault(); @@ -596,6 +563,8 @@ var gFindBar = { try { if (this.mFoundLink) this.mFoundLink.focus(); + else if (this.mFoundEditable) + this.mFoundEditable.focus(); else if (this.mCurrentWindow) this.mCurrentWindow.focus(); else @@ -613,8 +582,10 @@ var gFindBar = { } findToolbar.hidden = true; - this.changeSelectionColor(false); + var fastFind = getBrowser().fastFind; + fastFind.setSelectionModeAndRepaint(this.SELECTION_CONTROLLER.SELECTION_ON); this.setFoundLink(null); + this.mFoundEditable = null; this.mCurrentWindow = null; if (this.mQuickFindTimeout) { clearTimeout(this.mQuickFindTimeout); @@ -670,11 +641,23 @@ var gFindBar = { return (str != str.toLowerCase() && str != str.toUpperCase()); }, + onFindBarFocus: function () + { + this.mHasFocus = true; + }, + onFindBarBlur: function () { - this.changeSelectionColor(false); + var fastFind = getBrowser().fastFind; + if (this.mFoundEditable) { + fastFind.collapseSelection(); + } else { + fastFind.setSelectionModeAndRepaint(this.SELECTION_CONTROLLER.SELECTION_ON); + } this.setFoundLink(null); + this.mFoundEditable = null; this.mCurrentWindow = null; + this.mHasFocus = false; }, onBrowserMouseUp: function (evt) @@ -844,9 +827,11 @@ var gFindBar = { var val = document.getElementById("find-field").value; if (res == Components.interfaces.nsITypeAheadFind.FIND_NOTFOUND || !val) { this.setFoundLink(null); + this.mFoundEditable = null; this.mCurrentWindow = null; } else { this.setFoundLink(getBrowser().fastFind.foundLink); + this.mFoundEditable = getBrowser().fastFind.foundEditable; this.mCurrentWindow = getBrowser().fastFind.currentWindow; } }, @@ -865,8 +850,7 @@ var gFindBar = { var fastFind = getBrowser().fastFind; fastFind.caseSensitive = this.shouldBeCaseSensitive(val); this.setCaseSensitiveStr(val); - var res = fastFind.find(val, this.mFindMode == FIND_LINKS); - this.changeSelectionColor(true); + var res = fastFind.find(val, this.mFindMode == FIND_LINKS, this.mHasFocus); this.updateFoundLink(res); this.updateStatus(res, true); @@ -982,8 +966,7 @@ var gFindBar = { findNext: function () { var fastFind = getBrowser().fastFind; - var res = fastFind.findNext(); - this.changeSelectionColor(true); + var res = fastFind.findNext(this.mHasFocus); this.updateFoundLink(res); this.updateStatus(res, true); @@ -996,8 +979,7 @@ var gFindBar = { findPrevious: function () { var fastFind = getBrowser().fastFind; - var res = fastFind.findPrevious(); - this.changeSelectionColor(true); + var res = fastFind.findPrevious(this.mHasFocus); this.updateFoundLink(res); this.updateStatus(res, false); diff --git a/toolkit/components/typeaheadfind/public/nsITypeAheadFind.idl b/toolkit/components/typeaheadfind/public/nsITypeAheadFind.idl index 046219db0318..f6eedfc225c2 100755 --- a/toolkit/components/typeaheadfind/public/nsITypeAheadFind.idl +++ b/toolkit/components/typeaheadfind/public/nsITypeAheadFind.idl @@ -37,31 +37,88 @@ * * ***** END LICENSE BLOCK ***** */ -#include "nsISupports.idl" -#include "domstubs.idl" -#include "nsISupportsPrimitives.idl" + +/********************************* #includes *********************************/ + +#include "domstubs.idl" // nsIDOMElement, nsIDOMWindow +#include "nsISupports.idl" // nsISupports + + +/******************************** Declarations *******************************/ interface nsIDocShell; -[scriptable, uuid(376da416-e6b3-4bac-98f3-6aa408742751)] + +/****************************** nsTypeAheadFind ******************************/ + +[scriptable, uuid(c67aa119-fe47-4d1a-9a9b-485728f9adbe)] interface nsITypeAheadFind : nsISupports { + /****************************** Initializer ******************************/ + + /* Necessary initialization that can't happen in the constructor, either + * because function calls here may fail, or because the docShell is + * required. */ void init(in nsIDocShell aDocShell); - const unsigned short FIND_FOUND = 0; - const unsigned short FIND_NOTFOUND = 1; - const unsigned short FIND_WRAPPED = 2; - unsigned short find(in AString aSearchString, in boolean aLinksOnly); - unsigned short findNext(); - unsigned short findPrevious(); + /***************************** Core functions ****************************/ + /* Find aSearchString in page. If aLinksOnly is true, only search the page's + * hyperlinks for the string. aHasFocus will be true if the "Find" textfield + * has focus. */ + unsigned short find(in AString aSearchString, in boolean aLinksOnly, in boolean aHasFocus); + + /* Find next match in the page. */ + unsigned short findNext(in boolean aHasFocus); + + /* Find previous match in the page. */ + unsigned short findPrevious(in boolean aHasFocus); + + + /**************************** Helper functions ***************************/ + + /* Change searched docShell. This happens when e.g. we use the same + * nsITypeAheadFind object to search different tabs. */ void setDocShell(in nsIDocShell aDocShell); + /* Change the look of the the "found match" selection to aToggle, and repaint + * the selection. */ + void setSelectionModeAndRepaint(in short toggle); + + /* Collapse the "found match" selection to its start. Because not all + * matches are owned by the same selection controller, this doesn't + * necessarily happen automatically. */ + void collapseSelection(); + + + /******************************* Attributes ******************************/ + readonly attribute AString searchString; - attribute boolean focusLinks; - attribute boolean caseSensitive; + // Most recent search string + attribute boolean caseSensitive; // Searches are case sensitive readonly attribute nsIDOMElement foundLink; + // Most recent elem found, if a link + readonly attribute nsIDOMElement foundEditable; + // Most recent elem found, if editable readonly attribute nsIDOMWindow currentWindow; + // Window of most recent match + + + /******************************* Constants *******************************/ + + /* Find return codes */ + const unsigned short FIND_FOUND = 0; + // Successful find + const unsigned short FIND_NOTFOUND = 1; + // Unsuccessful find + const unsigned short FIND_WRAPPED = 2; + // Successful find, but wrapped around + + + /*************************************************************************/ + }; + +/*****************************************************************************/ diff --git a/toolkit/components/typeaheadfind/src/Makefile.in b/toolkit/components/typeaheadfind/src/Makefile.in index 6362abfbc55c..9bead7eb5c04 100755 --- a/toolkit/components/typeaheadfind/src/Makefile.in +++ b/toolkit/components/typeaheadfind/src/Makefile.in @@ -52,6 +52,7 @@ PACKAGE_FILE = typeaheadfind.pkg REQUIRES = content \ docshell \ dom \ + editor \ find \ gfx \ layout \ diff --git a/toolkit/components/typeaheadfind/src/nsTypeAheadFind.cpp b/toolkit/components/typeaheadfind/src/nsTypeAheadFind.cpp index 58404c08bd6c..c85224ee7db3 100755 --- a/toolkit/components/typeaheadfind/src/nsTypeAheadFind.cpp +++ b/toolkit/components/typeaheadfind/src/nsTypeAheadFind.cpp @@ -69,6 +69,7 @@ #include "nsIDOMNSHTMLDocument.h" #include "nsIDOMHTMLElement.h" #include "nsIEventStateManager.h" +#include "nsIFocusController.h" #include "nsIViewManager.h" #include "nsIScrollableView.h" #include "nsIDocument.h" @@ -77,6 +78,9 @@ #include "nsILink.h" #include "nsITextContent.h" #include "nsTextFragment.h" +#include "nsIDOMNSEditableElement.h" +#include "nsIDOMNSHTMLElement.h" +#include "nsIEditor.h" #include "nsICaret.h" #include "nsIDocShellTreeItem.h" @@ -94,7 +98,6 @@ #include "nsTypeAheadFind.h" -// XXX Finding in textboxes (show cursor?), add if (mDocShell) and if (mPresShell) checks NS_INTERFACE_MAP_BEGIN(nsTypeAheadFind) NS_INTERFACE_MAP_ENTRY(nsITypeAheadFind) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITypeAheadFind) @@ -113,10 +116,9 @@ static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID); nsTypeAheadFind::nsTypeAheadFind(): mLinksOnlyPref(PR_FALSE), mStartLinksOnlyPref(PR_FALSE), mLinksOnly(PR_FALSE), mCaretBrowsingOn(PR_FALSE), - mFocusLinks(PR_FALSE), mLiteralTextSearchOnly(PR_FALSE), - mDontTryExactMatch(PR_FALSE), mAllTheSameChar(PR_TRUE), - mRepeatingMode(eRepeatingNone), mLastFindLength(0), - mIsSoundInitialized(PR_FALSE) + mLiteralTextSearchOnly(PR_FALSE), mDontTryExactMatch(PR_FALSE), + mAllTheSameChar(PR_TRUE), mRepeatingMode(eRepeatingNone), + mLastFindLength(0), mIsSoundInitialized(PR_FALSE) { } @@ -216,8 +218,43 @@ nsTypeAheadFind::SetDocShell(nsIDocShell* aDocShell) mSearchRange = do_CreateInstance(kRangeCID); mFoundLink = nsnull; + mFoundEditable = nsnull; mCurrentWindow = nsnull; + mSelectionController = nsnull; + + return NS_OK; +} + +NS_IMETHODIMP +nsTypeAheadFind::SetSelectionModeAndRepaint(PRInt16 aToggle) +{ + nsCOMPtr selectionController = + do_QueryReferent(mSelectionController); + if (!selectionController) { + return NS_OK; + } + + selectionController->SetDisplaySelection(aToggle); + selectionController->RepaintSelection(nsISelectionController::SELECTION_NORMAL); + + return NS_OK; +} + +NS_IMETHODIMP +nsTypeAheadFind::CollapseSelection() +{ + nsCOMPtr selectionController = + do_QueryReferent(mSelectionController); + if (!selectionController) { + return NS_OK; + } + + nsCOMPtr selection; + selectionController->GetSelection(nsISelectionController::SELECTION_NORMAL, + getter_AddRefs(selection)); + selection->CollapseToStart(); + return NS_OK; } @@ -273,13 +310,13 @@ nsTypeAheadFind::PlayNotFoundSound() nsresult nsTypeAheadFind::FindItNow(nsIPresShell *aPresShell, PRBool aIsRepeatingSameChar, PRBool aIsLinksOnly, - PRBool aIsFirstVisiblePreferred, PRBool aFindNext, PRUint16* aResult) + PRBool aIsFirstVisiblePreferred, PRBool aFindNext, + PRBool aHasFocus, PRUint16* aResult) { *aResult = FIND_NOTFOUND; mFoundLink = nsnull; + mFoundEditable = nsnull; mCurrentWindow = nsnull; - nsCOMPtr selection; - nsCOMPtr selectionController; nsCOMPtr startingPresShell (GetPresShell()); if (!startingPresShell) { nsCOMPtr ds = do_QueryReferent(mDocShell); @@ -303,8 +340,17 @@ nsTypeAheadFind::FindItNow(nsIPresShell *aPresShell, if (!presContext) return NS_ERROR_FAILURE; - GetSelection(presShell, getter_AddRefs(selectionController), - getter_AddRefs(selection)); // cache for reuse + nsCOMPtr selection; + nsCOMPtr selectionController = + do_QueryReferent(mSelectionController); + if (!selectionController) { + GetSelection(presShell, getter_AddRefs(selectionController), + getter_AddRefs(selection)); // cache for reuse + mSelectionController = do_GetWeakReference(selectionController); + } else { + selectionController->GetSelection( + nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection)); + } nsCOMPtr startingContainer = presContext->GetContainer(); nsCOMPtr treeItem(do_QueryInterface(startingContainer)); @@ -346,7 +392,8 @@ nsTypeAheadFind::FindItNow(nsIPresShell *aPresShell, // ------------ Get ranges ready ---------------- nsCOMPtr returnRange; nsCOMPtr focusedPS; - if (NS_FAILED(GetSearchContainers(currentContainer, aIsRepeatingSameChar, + if (NS_FAILED(GetSearchContainers(currentContainer, selectionController, + aIsRepeatingSameChar, aIsFirstVisiblePreferred, !aIsFirstVisiblePreferred || mStartFindRange, getter_AddRefs(presShell), @@ -387,9 +434,11 @@ nsTypeAheadFind::FindItNow(nsIPresShell *aPresShell, &isStartingLink); } + PRBool usesIndependentSelection; if (!IsRangeVisible(presShell, presContext, returnRange, aIsFirstVisiblePreferred, PR_FALSE, - getter_AddRefs(mStartPointRange)) || + getter_AddRefs(mStartPointRange), + &usesIndependentSelection) || (aIsRepeatingSameChar && !isStartingLink) || (aIsLinksOnly && !isInsideLink) || (mStartLinksOnlyPref && aIsLinksOnly && !isStartingLink)) { @@ -404,31 +453,90 @@ nsTypeAheadFind::FindItNow(nsIPresShell *aPresShell, } // ------ Success! ------- + // Hide old selection (new one may be on a different controller) + if (selection) { + selection->CollapseToStart(); + SetSelectionModeAndRepaint(nsISelectionController::SELECTION_ON); + } + // Make sure new document is selected if (presShell != startingPresShell) { // We are in a new document (because of frames/iframes) - if (selection) - selection->CollapseToStart(); // Hide old doc's selection - - // Get selection controller and selection for new frame/iframe - GetSelection(presShell, getter_AddRefs(selectionController), - getter_AddRefs(selection)); - mPresShell = do_GetWeakReference(presShell); } + if (usesIndependentSelection) { + // We may be inside an editable element, and therefore the selection + // may be controlled by a different selection controller. Walk up the + // chain of parent nodes to see if we find one. + nsCOMPtr node; + returnRange->GetStartContainer(getter_AddRefs(node)); + while (node) { + nsCOMPtr editable = do_QueryInterface(node); + if (editable) { + // Inside an editable element. Get the correct selection + // controller and selection. + nsCOMPtr editor; + editable->GetEditor(getter_AddRefs(editor)); + NS_ASSERTION(editor, "Editable element has no editor!"); + if (!editor) { + break; + } + editor->GetSelectionController( + getter_AddRefs(selectionController)); + if (selectionController) { + selectionController->GetSelection( + nsISelectionController::SELECTION_NORMAL, + getter_AddRefs(selection)); + } + mFoundEditable = do_QueryInterface(node); + + // Check if find field is focused, if so do nothing + if (aHasFocus) { + break; + } + + // Otherwise move focus/caret to editable element + nsCOMPtr content = do_QueryInterface(mFoundEditable); + if (content) { + content->SetFocus(presContext); + presContext->EventStateManager()->MoveCaretToFocus(); + } + break; + } + nsIDOMNode* tmp = node; + tmp->GetParentNode(getter_AddRefs(node)); + } + + // If we reach here without setting mFoundEditable, then something + // besides editable elements can cause us to have an independent + // selection controller. I don't know whether this is possible. + // Currently, we simply fall back to grabbing the document's selection + // controller in this case. Perhaps we should reject this find match + // and search again. + NS_ASSERTION(mFoundEditable, "Independent selection controller on " + "non-editable element!"); + } + + if (!mFoundEditable) { + // Not using a separate selection controller, so just get the + // document's controller and selection. + GetSelection(presShell, getter_AddRefs(selectionController), + getter_AddRefs(selection)); + } + mSelectionController = do_GetWeakReference(selectionController); + // Select the found text if (selection) { selection->RemoveAllRanges(); selection->AddRange(returnRange); } - if (selectionController) - selectionController->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, - nsISelectionController::SELECTION_FOCUS_REGION, PR_TRUE); - currentDocShell->SetHasFocus(PR_TRUE); + if (!mFoundEditable) { + currentDocShell->SetHasFocus(PR_TRUE); // What does this do? - if (mFocusLinks) { + // Keep track of whether we've found a link, so we can focus it, jump + // to its target, etc. nsIEventStateManager *esm = presContext->EventStateManager(); PRBool isSelectionWithFocus; esm->MoveFocusToCaret(PR_TRUE, &isSelectionWithFocus); @@ -439,16 +547,29 @@ nsTypeAheadFind::FindItNow(nsIPresShell *aPresShell, lastFocusedElement(do_QueryInterface(lastFocusedContent)); mFoundLink = lastFocusedElement; } - nsCOMPtr doc = - do_QueryInterface(presShell->GetDocument()); - NS_ASSERTION(doc, "Wow, presShell doesn't have document!"); - mCurrentWindow = doc->GetWindow(); } - if (hasWrapped) + // Change selection color to ATTENTION and scroll to it. Careful: we + // must wait until after we goof with focus above before changing to + // ATTENTION, or when we MoveFocusToCaret() and the selection is not on a + // link, we'll blur, which will lose the ATTENTION. + if (selectionController) { + SetSelectionModeAndRepaint(nsISelectionController::SELECTION_ATTENTION); + selectionController->ScrollSelectionIntoView( + nsISelectionController::SELECTION_NORMAL, + nsISelectionController::SELECTION_FOCUS_REGION, PR_TRUE); + } + + nsCOMPtr doc = + do_QueryInterface(presShell->GetDocument()); + NS_ASSERTION(doc, "Wow, presShell doesn't have document!"); + mCurrentWindow = doc->GetWindow(); + + if (hasWrapped) { *aResult = FIND_WRAPPED; - else + } else { *aResult = FIND_FOUND; + } return NS_OK; } @@ -492,7 +613,8 @@ nsTypeAheadFind::FindItNow(nsIPresShell *aPresShell, } if (continueLoop) { - if (NS_FAILED(GetSearchContainers(currentContainer, + if (NS_FAILED(GetSearchContainers(currentContainer, + selectionController, aIsRepeatingSameChar, aIsFirstVisiblePreferred, PR_FALSE, getter_AddRefs(presShell), @@ -535,6 +657,15 @@ nsTypeAheadFind::GetFoundLink(nsIDOMElement** aFoundLink) return NS_OK; } +NS_IMETHODIMP +nsTypeAheadFind::GetFoundEditable(nsIDOMElement** aFoundEditable) +{ + NS_ENSURE_ARG_POINTER(aFoundEditable); + *aFoundEditable = mFoundEditable; + NS_IF_ADDREF(*aFoundEditable); + return NS_OK; +} + NS_IMETHODIMP nsTypeAheadFind::GetCurrentWindow(nsIDOMWindow** aCurrentWindow) { @@ -544,23 +675,9 @@ nsTypeAheadFind::GetCurrentWindow(nsIDOMWindow** aCurrentWindow) return NS_OK; } -NS_IMETHODIMP -nsTypeAheadFind::GetFocusLinks(PRBool* aFocusLinks) -{ - NS_ENSURE_ARG(aFocusLinks); - *aFocusLinks = mFocusLinks; - return NS_OK; -} - -NS_IMETHODIMP -nsTypeAheadFind::SetFocusLinks(PRBool aFocusLinks) -{ - mFocusLinks = aFocusLinks; - return NS_OK; -} - nsresult -nsTypeAheadFind::GetSearchContainers(nsISupports *aContainer, +nsTypeAheadFind::GetSearchContainers(nsISupports *aContainer, + nsISelectionController *aSelectionController, PRBool aIsRepeatingSameChar, PRBool aIsFirstVisiblePreferred, PRBool aCanUseDocSelection, @@ -621,8 +738,8 @@ nsTypeAheadFind::GetSearchContainers(nsISupports *aContainer, nsCOMPtr selectionPresShell (GetPresShell()); if (aCanUseDocSelection && selectionPresShell && selectionPresShell == presShell) { nsCOMPtr selection; - nsCOMPtr selectionController; - GetSelection(presShell, getter_AddRefs(selectionController), getter_AddRefs(selection)); + aSelectionController->GetSelection( + nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection)); if (selection) selection->GetRangeAt(0, getter_AddRefs(currentSelectionRange)); } @@ -633,7 +750,7 @@ nsTypeAheadFind::GetSearchContainers(nsISupports *aContainer, // IsRangeVisible. It returns the first visible range after searchRange IsRangeVisible(presShell, presContext, mSearchRange, aIsFirstVisiblePreferred, PR_TRUE, - getter_AddRefs(mStartPointRange)); + getter_AddRefs(mStartPointRange), nsnull); } else { PRInt32 startOffset; @@ -773,19 +890,20 @@ nsTypeAheadFind::RangeStartsInsideLink(nsIDOMRange *aRange, } NS_IMETHODIMP -nsTypeAheadFind::FindPrevious(PRUint16* aResult) +nsTypeAheadFind::FindPrevious(PRBool aHasFocus, PRUint16* aResult) { - return FindInternal(true, aResult); + return FindInternal(PR_TRUE, aHasFocus, aResult); } NS_IMETHODIMP -nsTypeAheadFind::FindNext(PRUint16* aResult) +nsTypeAheadFind::FindNext(PRBool aHasFocus, PRUint16* aResult) { - return FindInternal(false, aResult); + return FindInternal(PR_FALSE, aHasFocus, aResult); } nsresult -nsTypeAheadFind::FindInternal(PRBool aFindBackwards, PRUint16* aResult) +nsTypeAheadFind::FindInternal(PRBool aFindBackwards, PRBool aHasFocus, + PRUint16* aResult) { *aResult = FIND_NOTFOUND; @@ -804,7 +922,8 @@ nsTypeAheadFind::FindInternal(PRBool aFindBackwards, PRUint16* aResult) } mLiteralTextSearchOnly = PR_TRUE; - if (NS_FAILED(FindItNow(nsnull, repeatingSameChar, mLinksOnly, PR_FALSE, !aFindBackwards, aResult))) + if (NS_FAILED(FindItNow(nsnull, repeatingSameChar, mLinksOnly, PR_FALSE, + !aFindBackwards, aHasFocus, aResult))) mRepeatingMode = eRepeatingNone; return NS_OK; @@ -824,16 +943,17 @@ nsTypeAheadFind::Cancel() mStartFindRange = nsnull; mAllTheSameChar = PR_TRUE; // Until at least 2 different chars are typed + mSelectionController = nsnull; + return NS_OK; } NS_IMETHODIMP -nsTypeAheadFind::Find(const nsAString& aSearchString, PRBool aLinksOnly, PRUint16* aResult) +nsTypeAheadFind::Find(const nsAString& aSearchString, PRBool aLinksOnly, + PRBool aHasFocus, PRUint16* aResult) { *aResult = FIND_NOTFOUND; - nsCOMPtr selection; - nsCOMPtr selectionController; nsCOMPtr presShell (GetPresShell()); if (!presShell) { nsCOMPtr ds (do_QueryReferent(mDocShell)); @@ -842,8 +962,17 @@ nsTypeAheadFind::Find(const nsAString& aSearchString, PRBool aLinksOnly, PRUint1 ds->GetPresShell(getter_AddRefs(presShell)); mPresShell = do_GetWeakReference(presShell); } - GetSelection(presShell, getter_AddRefs(selectionController), - getter_AddRefs(selection)); // cache for reuse + nsCOMPtr selection; + nsCOMPtr selectionController = + do_QueryReferent(mSelectionController); + if (!selectionController) { + GetSelection(presShell, getter_AddRefs(selectionController), + getter_AddRefs(selection)); // cache for reuse + mSelectionController = do_GetWeakReference(selectionController); + } else { + selectionController->GetSelection( + nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection)); + } if (selection) selection->CollapseToStart(); @@ -953,7 +1082,8 @@ nsTypeAheadFind::Find(const nsAString& aSearchString, PRBool aLinksOnly, PRUint1 // Regular find, not repeated char find // Prefer to find exact match - rv = FindItNow(nsnull, PR_FALSE, mLinksOnly, isFirstVisiblePreferred, PR_FALSE, aResult); + rv = FindItNow(nsnull, PR_FALSE, mLinksOnly, isFirstVisiblePreferred, + PR_FALSE, aHasFocus, aResult); } #ifndef NO_LINK_CYCLE_ON_SAME_CHAR @@ -961,7 +1091,8 @@ nsTypeAheadFind::Find(const nsAString& aSearchString, PRBool aLinksOnly, PRUint1 mTypeAheadBuffer.Length() > 1) { mRepeatingMode = eRepeatingChar; mDontTryExactMatch = PR_TRUE; // Repeated character find mode - rv = FindItNow(nsnull, PR_TRUE, PR_TRUE, isFirstVisiblePreferred, PR_FALSE, aResult); + rv = FindItNow(nsnull, PR_TRUE, PR_TRUE, isFirstVisiblePreferred, PR_FALSE, + aHasFocus, aResult); } #endif @@ -1021,7 +1152,8 @@ nsTypeAheadFind::IsRangeVisible(nsIPresShell *aPresShell, nsPresContext *aPresContext, nsIDOMRange *aRange, PRBool aMustBeInViewPort, PRBool aGetTopVisibleLeaf, - nsIDOMRange **aFirstVisibleRange) + nsIDOMRange **aFirstVisibleRange, + PRBool *aUsesIndependentSelection) { NS_ENSURE_ARG_POINTER(aPresShell); NS_ENSURE_ARG_POINTER(aPresContext); @@ -1047,10 +1179,12 @@ nsTypeAheadFind::IsRangeVisible(nsIPresShell *aPresShell, if (!frame->GetStyleVisibility()->IsVisible()) return PR_FALSE; - // Detect if we are _inside_ a text control. - // bug 189039 - FAYT doesn't want to find inside text boxes - if (NS_FRAME_INDEPENDENT_SELECTION & frame->GetStateBits()) - return PR_FALSE; + // Detect if we are _inside_ a text control, or something else with its own + // selection controller. + if (aUsesIndependentSelection) { + *aUsesIndependentSelection = + (frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION); + } // ---- We have a frame ---- if (!aMustBeInViewPort) diff --git a/toolkit/components/typeaheadfind/src/nsTypeAheadFind.h b/toolkit/components/typeaheadfind/src/nsTypeAheadFind.h index 736fecaed179..b2c25ac1f1f9 100755 --- a/toolkit/components/typeaheadfind/src/nsTypeAheadFind.h +++ b/toolkit/components/typeaheadfind/src/nsTypeAheadFind.h @@ -85,7 +85,7 @@ protected: void SaveFind(); void PlayNotFoundSound(); - nsresult FindInternal(PRBool aFindBackwards, PRUint16* aResult); + nsresult FindInternal(PRBool aFindBackwards, PRBool aHasFocus, PRUint16* aResult); nsresult GetWebBrowserFind(nsIDocShell *aDocShell, nsIWebBrowserFind **aWebBrowserFind); @@ -95,12 +95,14 @@ protected: void GetSelection(nsIPresShell *aPresShell, nsISelectionController **aSelCon, nsISelection **aDomSel); PRBool IsRangeVisible(nsIPresShell *aPresShell, nsPresContext *aPresContext, - nsIDOMRange *aRange, PRBool aMustBeVisible, - PRBool aGetTopVisibleLeaf, - nsIDOMRange **aNewRange); + nsIDOMRange *aRange, PRBool aMustBeVisible, + PRBool aGetTopVisibleLeaf, nsIDOMRange **aNewRange, + PRBool *aUsesIndependentSelection); nsresult FindItNow(nsIPresShell *aPresShell, PRBool aIsRepeatingSameChar, - PRBool aIsLinksOnly, PRBool aIsFirstVisiblePreferred, PRBool aFindNext, PRUint16* aResult); - nsresult GetSearchContainers(nsISupports *aContainer, + PRBool aIsLinksOnly, PRBool aIsFirstVisiblePreferred, + PRBool aFindNext, PRBool aHasFocus, PRUint16* aResult); + nsresult GetSearchContainers(nsISupports *aContainer, + nsISelectionController *aSelectionController, PRBool aIsRepeatingSameChar, PRBool aIsFirstVisiblePreferred, PRBool aCanUseDocSelection, @@ -124,8 +126,8 @@ protected: PRBool mStartLinksOnlyPref; PRPackedBool mLinksOnly; PRBool mCaretBrowsingOn; - PRBool mFocusLinks; - nsCOMPtr mFoundLink; + nsCOMPtr mFoundLink; // Most recent elem found, if a link + nsCOMPtr mFoundEditable; // Most recent elem found, if editable nsCOMPtr mCurrentWindow; PRPackedBool mLiteralTextSearchOnly; PRPackedBool mDontTryExactMatch; @@ -152,7 +154,9 @@ protected: nsCOMPtr mFind; nsCOMPtr mWebBrowserFind; - // The focused content window that we're listening to + // The focused content window that we're listening to and its cached objects nsWeakPtr mDocShell; nsWeakPtr mPresShell; + nsWeakPtr mSelectionController; + // Most recent match's controller };