Bug 1238137 - Telemetry pings for main thread scrolling to bring the caret into view after moving it in response to keyboard input. r=ehsan
--- a/dom/base/nsISelectionController.idl
+++ b/dom/base/nsISelectionController.idl
@@ -61,31 +61,35 @@ interface nsISelectionController : nsISe
* @param _return will hold the return value
*/
nsISelection getSelection(in short type);
const short SCROLL_SYNCHRONOUS = 1<<1;
const short SCROLL_FIRST_ANCESTOR_ONLY = 1<<2;
const short SCROLL_CENTER_VERTICALLY = 1<<4;
const short SCROLL_OVERFLOW_HIDDEN = 1<<5;
+ const short SCROLL_FOR_CARET_MOVE = 1<<6;
/**
* ScrollSelectionIntoView scrolls a region of the selection,
* so that it is visible in the scrolled view.
*
* @param aType the selection to scroll into view. //SelectionType
* @param aRegion the region inside the selection to scroll into view. //SelectionRegion
* @param aFlags the scroll flags. Valid bits include:
* SCROLL_SYNCHRONOUS: when set, scrolls the selection into view
* before returning. If not set, posts a request which is processed
* at some point after the method returns.
* SCROLL_FIRST_ANCESTOR_ONLY: if set, only the first ancestor will be scrolled
* into view.
* SCROLL_OVERFLOW_HIDDEN: if set, scrolls even if the overflow is specified
* as hidden.
+ * SCROLL_FOR_CARET_MOVE: set to indicate whether scrolling is in response
+ * to the caret being moved. Does not affect behavior (used for telemetry
+ * purposes only).
*
* Note that if isSynchronous is true, then this might flush the pending
* reflow. It's dangerous for some objects. See bug 418470 comment 12.
*/
void scrollSelectionIntoView(in short type, in short region, in short flags);
/**
* RepaintSelection repaints the selection specified by aType.
@@ -101,17 +105,17 @@ interface nsISelectionController : nsISe
* @param aEnable PR_TRUE to enable caret. PR_FALSE to disable.
* @return always NS_OK
*/
void setCaretEnabled(in boolean enabled);
/**
* Set the caret readonly or not. An readonly caret will
- * draw but not blink when made visible.
+ * draw but not blink when made visible.
* @param aReadOnly PR_TRUE to enable caret. PR_FALSE to disable.
* @return always NS_OK
*/
void setCaretReadOnly(in boolean readOnly);
/**
* Gets the current state of the caret.
* @param aEnabled [OUT] set to the current caret state, as set by SetCaretEnabled
@@ -121,40 +125,40 @@ interface nsISelectionController : nsISe
boolean getCaretEnabled();
/**
* This is true if the caret is enabled, visible, and currently blinking.
* This is still true when the caret is enabled, visible, but in its "off"
* blink cycle.
*/
readonly attribute boolean caretVisible;
-
+
/**
* Show the caret even in selections. By default the caret is hidden unless the
* selection is collapsed. Use this function to show the caret even in selections.
* @param aVisibility PR_TRUE to show the caret in selections. PR_FALSE to hide.
* @return always NS_OK
*/
void setCaretVisibilityDuringSelection(in boolean visibility);
/** CharacterMove will move the selection one character forward/backward in the document.
* this will also have the effect of collapsing the selection if the aExtend = PR_FALSE
- * the "point" of selection that is extended is considered the "focus" point.
+ * the "point" of selection that is extended is considered the "focus" point.
* or the last point adjusted by the selection.
* @param aForward forward or backward if PR_FALSE
* @param aExtend should it collapse the selection of extend it?
*/
void characterMove(in boolean forward, in boolean extend);
/** PhysicalMove will move the selection one "unit" in a given direction
* within the document.
* this will also have the effect of collapsing the selection if the aExtend = PR_FALSE
- * the "point" of selection that is extended is considered the "focus" point.
+ * the "point" of selection that is extended is considered the "focus" point.
* or the last point adjusted by the selection.
- * @param aDirection
+ * @param aDirection
* @param aAmount character/line; word/lineBoundary
* @param aExtend should it collapse the selection of extend it?
*/
void physicalMove(in short direction, in short amount, in boolean extend);
/**
* nsFrameSelection::PhysicalMove depends on the ordering of these values;
* do not change without checking there!
@@ -176,66 +180,66 @@ interface nsISelectionController : nsISe
* backward in the document.
* this method is used internally for handling backspace key only when we're
* after UTF-16 surrogates.
*/
[noscript] void characterExtendForBackspace();
/** WordMove will move the selection one word forward/backward in the document.
* this will also have the effect of collapsing the selection if the aExtend = PR_FALSE
- * the "point" of selection that is extended is considered the "focus" point.
+ * the "point" of selection that is extended is considered the "focus" point.
* or the last point adjusted by the selection.
* @param aForward forward or backward if PR_FALSE
* @param aExtend should it collapse the selection of extend it?
*/
void wordMove(in boolean forward, in boolean extend);
/** wordExtendForDelete will extend the selection one word forward/backward in the document.
* this method is used internally for handling ctrl[option]-backspace and ctrl[option]-del.
* @param aForward forward or backward if PR_FALSE
*/
[noscript] void wordExtendForDelete(in boolean forward);
/** LineMove will move the selection one line forward/backward in the document.
* this will also have the effect of collapsing the selection if the aExtend = PR_FALSE
- * the "point" of selection that is extended is considered the "focus" point.
+ * the "point" of selection that is extended is considered the "focus" point.
* or the last point adjusted by the selection.
* @param aForward forward or backward if PR_FALSE
* @param aExtend should it collapse the selection of extend it?
*/
void lineMove(in boolean forward, in boolean extend);
/** IntraLineMove will move the selection to the front of the line or end of the line
* in the document.
* this will also have the effect of collapsing the selection if the aExtend = PR_FALSE
- * the "point" of selection that is extended is considered the "focus" point.
+ * the "point" of selection that is extended is considered the "focus" point.
* or the last point adjusted by the selection.
* @param aForward forward or backward if PR_FALSE
* @param aExtend should it collapse the selection of extend it?
*/
void intraLineMove(in boolean forward, in boolean extend);
/** PageMove will move the selection one page forward/backward in the document.
* this will also have the effect of collapsing the selection if the aExtend = PR_FALSE
- * the "point" of selection that is extended is considered the "focus" point.
+ * the "point" of selection that is extended is considered the "focus" point.
* or the last point adjusted by the selection.
* @param aForward forward or backward if PR_FALSE
* @param aExtend should it collapse the selection of extend it?
*/
void pageMove(in boolean forward, in boolean extend);
/** CompleteScroll will move page view to the top or bottom of the document
* @param aForward forward or backward if PR_FALSE
*/
void completeScroll(in boolean forward);
/** CompleteMove will move page view to the top or bottom of the document
* this will also have the effect of collapsing the selection if the aExtend = PR_FALSE
- * the "point" of selection that is extended is considered the "focus" point.
+ * the "point" of selection that is extended is considered the "focus" point.
* or the last point adjusted by the selection.
* @param aForward forward or backward if PR_FALSE
* @param aExtend should it collapse the selection of extend it?
*/
void completeMove(in boolean forward, in boolean extend);
/** ScrollPage will scroll the page without affecting the selection.
@@ -252,17 +256,17 @@ interface nsISelectionController : nsISe
* @param aRight if true will scroll right. if not will scroll left.
*/
void scrollCharacter(in boolean right);
/** SelectAll will select the whole page
*/
void selectAll();
- /** CheckVisibility will return true if textnode and offsets are actually rendered
+ /** CheckVisibility will return true if textnode and offsets are actually rendered
* in the current precontext.
* @param aNode textNode to test
* @param aStartOffset offset in dom to first char of textnode to test
* @param aEndOffset offset in dom to last char of textnode to test
* @param aReturnBool boolean returned TRUE if visible FALSE if not
*/
boolean checkVisibility(in nsIDOMNode node, in short startOffset, in short endOffset);
[noscript,nostdcall] boolean checkVisibilityContent(in nsIContent node, in short startOffset, in short endOffset);
--- a/dom/html/nsTextEditorState.cpp
+++ b/dom/html/nsTextEditorState.cpp
@@ -534,18 +534,20 @@ nsTextInputSelectionImpl::PageMove(bool
// expected behavior for PageMove is to scroll AND move the caret
// and to remain relative position of the caret in view. see Bug 4302.
if (mScrollFrame)
{
mFrameSelection->CommonPageMove(aForward, aExtend, mScrollFrame);
}
// After ScrollSelectionIntoView(), the pending notifications might be
// flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
- return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION,
- nsISelectionController::SCROLL_SYNCHRONOUS);
+ return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
+ nsISelectionController::SELECTION_FOCUS_REGION,
+ nsISelectionController::SCROLL_SYNCHRONOUS |
+ nsISelectionController::SCROLL_FOR_CARET_MOVE);
}
NS_IMETHODIMP
nsTextInputSelectionImpl::CompleteScroll(bool aForward)
{
if (!mScrollFrame)
return NS_ERROR_NOT_INITIALIZED;
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -2102,17 +2102,18 @@ PresShell::PageMove(bool aForward, bool
if (!scrollableFrame)
return NS_OK;
mSelection->CommonPageMove(aForward, aExtend, scrollableFrame);
// After ScrollSelectionIntoView(), the pending notifications might be
// flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
nsISelectionController::SELECTION_FOCUS_REGION,
- nsISelectionController::SCROLL_SYNCHRONOUS);
+ nsISelectionController::SCROLL_SYNCHRONOUS |
+ nsISelectionController::SCROLL_FOR_CARET_MOVE);
}
NS_IMETHODIMP
PresShell::ScrollPage(bool aForward)
{
nsIScrollableFrame* scrollFrame =
@@ -2208,17 +2209,18 @@ PresShell::CompleteMove(bool aForward, b
// HandleClick resets ancestorLimiter, so set it again.
mSelection->SetAncestorLimiter(limiter);
}
// After ScrollSelectionIntoView(), the pending notifications might be
// flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
nsISelectionController::SELECTION_FOCUS_REGION,
- nsISelectionController::SCROLL_SYNCHRONOUS);
+ nsISelectionController::SCROLL_SYNCHRONOUS |
+ nsISelectionController::SCROLL_FOR_CARET_MOVE);
}
NS_IMETHODIMP
PresShell::SelectAll()
{
return mSelection->SelectAll();
}
--- a/layout/generic/Selection.h
+++ b/layout/generic/Selection.h
@@ -88,17 +88,18 @@ public:
SelectionRegion aRegion,
int32_t aFlags,
nsIPresShell::ScrollAxis aVertical,
nsIPresShell::ScrollAxis aHorizontal);
enum {
SCROLL_SYNCHRONOUS = 1<<1,
SCROLL_FIRST_ANCESTOR_ONLY = 1<<2,
SCROLL_DO_FLUSH = 1<<3,
- SCROLL_OVERFLOW_HIDDEN = 1<<5
+ SCROLL_OVERFLOW_HIDDEN = 1<<5,
+ SCROLL_FOR_CARET_MOVE = 1<<6
};
// aDoFlush only matters if aIsSynchronous is true. If not, we'll just flush
// when the scroll event fires so we make sure to scroll to the right place.
nsresult ScrollIntoView(SelectionRegion aRegion,
nsIPresShell::ScrollAxis aVertical =
nsIPresShell::ScrollAxis(),
nsIPresShell::ScrollAxis aHorizontal =
nsIPresShell::ScrollAxis(),
--- a/layout/generic/nsFrameSelection.h
+++ b/layout/generic/nsFrameSelection.h
@@ -356,16 +356,17 @@ public:
* @param aType the selection to scroll into view.
* @param aRegion the region inside the selection to scroll into view.
* @param aFlags the scroll flags. Valid bits include:
* SCROLL_SYNCHRONOUS: when set, scrolls the selection into view
* before returning. If not set, posts a request which is processed
* at some point after the method returns.
* SCROLL_FIRST_ANCESTOR_ONLY: if set, only the first ancestor will be scrolled
* into view.
+ *
*/
/*unsafe*/
nsresult ScrollSelectionIntoView(SelectionType aType,
SelectionRegion aRegion,
int16_t aFlags) const;
/** RepaintSelection repaints the selected frames that are inside the selection
* specified by aSelectionType.
--- a/layout/generic/nsSelection.cpp
+++ b/layout/generic/nsSelection.cpp
@@ -872,17 +872,17 @@ nsFrameSelection::MoveCaret(nsDirection
bool isCollapsed;
nsPoint desiredPos(0, 0); //we must keep this around and revalidate it when its just UP/DOWN
int8_t index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
RefPtr<Selection> sel = mDomSelections[index];
if (!sel)
return NS_ERROR_NULL_POINTER;
- int32_t scrollFlags = 0;
+ int32_t scrollFlags = Selection::SCROLL_FOR_CARET_MOVE;
nsINode* focusNode = sel->GetFocusNode();
if (focusNode &&
(focusNode->IsEditable() ||
(focusNode->IsElement() &&
focusNode->AsElement()->State().
HasState(NS_EVENT_STATE_MOZ_READWRITE)))) {
// If caret moves in editor, it should cause scrolling even if it's in
// overflow: hidden;.
@@ -1835,16 +1835,19 @@ nsFrameSelection::ScrollSelectionIntoVie
}
if (aFlags & nsISelectionController::SCROLL_OVERFLOW_HIDDEN) {
flags |= Selection::SCROLL_OVERFLOW_HIDDEN;
}
if (aFlags & nsISelectionController::SCROLL_CENTER_VERTICALLY) {
verticalScroll = nsIPresShell::ScrollAxis(
nsIPresShell::SCROLL_CENTER, nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE);
}
+ if (aFlags & nsISelectionController::SCROLL_FOR_CARET_MOVE) {
+ flags |= Selection::SCROLL_FOR_CARET_MOVE;
+ }
// After ScrollSelectionIntoView(), the pending notifications might be
// flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
return mDomSelections[index]->ScrollIntoView(aRegion,
verticalScroll,
nsIPresShell::ScrollAxis(),
flags);
}
@@ -5877,16 +5880,21 @@ Selection::ScrollIntoView(SelectionRegio
uint32_t flags = 0;
if (aFlags & Selection::SCROLL_FIRST_ANCESTOR_ONLY) {
flags |= nsIPresShell::SCROLL_FIRST_ANCESTOR_ONLY;
}
if (aFlags & Selection::SCROLL_OVERFLOW_HIDDEN) {
flags |= nsIPresShell::SCROLL_OVERFLOW_HIDDEN;
}
+ if (aFlags & Selection::SCROLL_FOR_CARET_MOVE) {
+ mozilla::Telemetry::Accumulate(mozilla::Telemetry::SCROLL_INPUT_METHODS,
+ (uint32_t) ScrollInputMethod::MainThreadScrollCaretIntoView);
+ }
+
presShell->ScrollFrameRectIntoView(frame, rect, aVertical, aHorizontal,
flags);
return NS_OK;
}
NS_IMETHODIMP
Selection::AddSelectionListener(nsISelectionListener* aNewListener)
{