fixes bug 189039 "Allow type ahead find to position the cursor in text boxes" patch by pkasting, r=masayuki, sr=darin

This commit is contained in:
darin%meer.net 2006-06-29 20:55:39 +00:00
Родитель ba1a7a58da
Коммит faa323e28f
6 изменённых файлов: 318 добавлений и 139 удалений

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

@ -6,6 +6,7 @@
<hbox id="find-field-container" class="find-fast">
<textbox id="find-field" oninput="gFindBar.find(this.value);"
onkeypress="gFindBar.onFindBarKeyPress(event);"
onfocus="gFindBar.onFindBarFocus();"
onblur="gFindBar.onFindBarBlur();"
oncompositionstart="gFindBar.onFindBarCompositionStart(event);"
oncompositionend="gFindBar.onFindBarCompositionEnd(event);"/>

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

@ -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);

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

@ -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
/*************************************************************************/
};
/*****************************************************************************/

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

@ -52,6 +52,7 @@ PACKAGE_FILE = typeaheadfind.pkg
REQUIRES = content \
docshell \
dom \
editor \
find \
gfx \
layout \

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

@ -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<nsISelectionController> 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<nsISelectionController> selectionController =
do_QueryReferent(mSelectionController);
if (!selectionController) {
return NS_OK;
}
nsCOMPtr<nsISelection> 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<nsISelection> selection;
nsCOMPtr<nsISelectionController> selectionController;
nsCOMPtr<nsIPresShell> startingPresShell (GetPresShell());
if (!startingPresShell) {
nsCOMPtr<nsIDocShell> 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<nsISelection> selection;
nsCOMPtr<nsISelectionController> 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<nsISupports> startingContainer = presContext->GetContainer();
nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(startingContainer));
@ -346,7 +392,8 @@ nsTypeAheadFind::FindItNow(nsIPresShell *aPresShell,
// ------------ Get ranges ready ----------------
nsCOMPtr<nsIDOMRange> returnRange;
nsCOMPtr<nsIPresShell> 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<nsIDOMNode> node;
returnRange->GetStartContainer(getter_AddRefs(node));
while (node) {
nsCOMPtr<nsIDOMNSEditableElement> editable = do_QueryInterface(node);
if (editable) {
// Inside an editable element. Get the correct selection
// controller and selection.
nsCOMPtr<nsIEditor> 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<nsIContent> 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<nsIDocument> 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<nsIDocument> 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;
}
@ -493,6 +614,7 @@ nsTypeAheadFind::FindItNow(nsIPresShell *aPresShell,
if (continueLoop) {
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,
nsISelectionController *aSelectionController,
PRBool aIsRepeatingSameChar,
PRBool aIsFirstVisiblePreferred,
PRBool aCanUseDocSelection,
@ -621,8 +738,8 @@ nsTypeAheadFind::GetSearchContainers(nsISupports *aContainer,
nsCOMPtr<nsIPresShell> selectionPresShell (GetPresShell());
if (aCanUseDocSelection && selectionPresShell && selectionPresShell == presShell) {
nsCOMPtr<nsISelection> selection;
nsCOMPtr<nsISelectionController> 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<nsISelection> selection;
nsCOMPtr<nsISelectionController> selectionController;
nsCOMPtr<nsIPresShell> presShell (GetPresShell());
if (!presShell) {
nsCOMPtr<nsIDocShell> 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<nsISelection> selection;
nsCOMPtr<nsISelectionController> 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)

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

@ -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);
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<nsIDOMElement> mFoundLink;
nsCOMPtr<nsIDOMElement> mFoundLink; // Most recent elem found, if a link
nsCOMPtr<nsIDOMElement> mFoundEditable; // Most recent elem found, if editable
nsCOMPtr<nsIDOMWindow> mCurrentWindow;
PRPackedBool mLiteralTextSearchOnly;
PRPackedBool mDontTryExactMatch;
@ -152,7 +154,9 @@ protected:
nsCOMPtr<nsIFind> mFind;
nsCOMPtr<nsIWebBrowserFind> 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
};