зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
ba1a7a58da
Коммит
faa323e28f
|
@ -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
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче