Bug 552707 While we're expanding selection by dragging, the selection root element should capture mouse events and all scrollable elements should be scrollable r=roc+smaug, ui=faaborg

This commit is contained in:
Masayuki Nakano 2011-07-06 11:16:18 +09:00
Родитель 4686066b93
Коммит 02f36526f8
19 изменённых файлов: 2158 добавлений и 351 удалений

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

@ -933,18 +933,6 @@ nsFrame::GetChildList(nsIAtom* aListName) const
return nsFrameList::EmptyList();
}
static nsIFrame*
GetActiveSelectionFrame(nsPresContext* aPresContext, nsIFrame* aFrame)
{
nsIContent* capturingContent = nsIPresShell::GetCapturingContent();
if (capturingContent) {
nsIFrame* activeFrame = aPresContext->GetPrimaryFrameFor(capturingContent);
return activeFrame ? activeFrame : aFrame;
}
return aFrame;
}
PRInt16
nsFrame::DisplaySelection(nsPresContext* aPresContext, PRBool isOkToTurnOn)
{
@ -2048,6 +2036,147 @@ nsFrame::IsSelectable(PRBool* aSelectable, PRUint8* aSelectStyle) const
return NS_OK;
}
nsFrameSelection*
nsFrame::GetFrameSelectionForSelectingByMouse()
{
PRBool selectable;
PRUint8 selectStyle;
nsresult rv = IsSelectable(&selectable, &selectStyle);
NS_ENSURE_SUCCESS(rv, nsnull);
if (!selectable) {
return nsnull;
}
// When implementing NS_STYLE_USER_SELECT_ELEMENT,
// NS_STYLE_USER_SELECT_ELEMENTS and NS_STYLE_USER_SELECT_TOGGLE, need to
// change this logic
PRBool useFrameSelection = (selectStyle == NS_STYLE_USER_SELECT_TEXT);
// XXX This is screwy; it really should use the selection frame, not the
// event frame
const nsFrameSelection* frameselection =
(selectStyle == NS_STYLE_USER_SELECT_TEXT) ? GetConstFrameSelection() :
PresContext()->PresShell()->ConstFrameSelection();
return const_cast<nsFrameSelection*>(frameselection);
}
/**
* GetContentToCaptureForSelection() returns a content which should capture
* mouse events for aSelectionRoot. E.g., the result is <input type="text">
* if the aSelectionRoot is anonymous div element in the editor.
*/
static nsIContent*
GetContentToCaptureForSelection(nsIContent* aSelectionRoot)
{
return aSelectionRoot->FindFirstNonNativeAnonymous();
}
/**
* GetSelectionRootContentForCapturingContent() returns a selection root
* content for the capturing content. E.g., the result is anonymous div
* element if aCapturingContent is a <input type="text">.
*/
static nsIContent*
GetSelectionRootContentForCapturingContent(nsIPresShell* aPresShell,
nsIContent* aCapturingContent)
{
if (!aCapturingContent->HasIndependentSelection()) {
return aCapturingContent;
}
return aCapturingContent->GetSelectionRootContent(aPresShell);
}
/**
* FindNearestScrollableFrameForSelection() returns the nearest ancestor
* scrollable frame when user is dragging on aFrame.
*
* @param aFrame A frame which the user is dragging on.
* @param aSelectionRoot When this is not NULL, the result is guaranteed that
* the result belongs to the same selection root.
* For example, when aFrame is in <input type="text">
* but user is selecting outside of the <input>:
* * If aSelectionRoot is NULL, this returns the
* selection root frame of the <input>.
* * Otherwise, e.g., aSelectionRoot is the root
* element of the document, the result is the
* nearest ancestor scrollable element of the
* <input> element.
*
* @return The nearest ancestor scrollable frame for aFrame.
* If it was not found, returns NULL.
*/
static nsIScrollableFrame*
FindNearestScrollableFrameForSelection(nsIFrame* aFrame,
nsIContent* aSelectionRoot = nsnull)
{
#ifdef DEBUG
nsFrameSelection* draggingFrameSelection =
nsFrameSelection::GetMouseDownFrameSelection();
NS_ASSERTION(!draggingFrameSelection ||
draggingFrameSelection == aFrame->GetConstFrameSelection(),
"aFrame must be in dragging nsFrameSelection");
#endif
PRBool foundCapturingContent = PR_FALSE;
nsIContent* capturingContent = nsIPresShell::GetCapturingContent();
// If the specified selection root content is capturing content,
// that might be different from the computed selection root. Then, we should
// replace aSelectionRoot with its computed selection root.
if (aSelectionRoot && aSelectionRoot == capturingContent) {
nsIFrame* selectionRootFrame = aSelectionRoot->GetPrimaryFrame();
NS_ENSURE_TRUE(selectionRootFrame, nsnull);
nsIPresShell* ps = selectionRootFrame->PresContext()->PresShell();
aSelectionRoot = aSelectionRoot->GetSelectionRootContent(ps);
}
nsIScrollableFrame* lastScrollableFrame = nsnull;
for (nsIFrame* frame = aFrame; frame; frame = frame->GetParent()) {
do {
nsIScrollableFrame* scrollableFrame = do_QueryFrame(frame);
if (!scrollableFrame || !scrollableFrame->GetScrolledFrame()) {
break; // non-scrollable frame.
}
if (aSelectionRoot) {
// If aSelectionRoot isn't null, find a scrollable frame whose
// selection root is the same as aSelectionRoot.
nsIContent* content = frame->GetContent();
if (!content) {
break;
}
nsIPresShell* ps = frame->PresContext()->PresShell();
if (content->GetSelectionRootContent(ps) != aSelectionRoot) {
break;
}
}
lastScrollableFrame = scrollableFrame;
// If the scrollable frame has independent selection, we should return it
// even if it's not actually scrollable.
if (frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION) {
return scrollableFrame;
}
nsRect range = scrollableFrame->GetScrollRange();
if (range.width == 0 && range.height == 0) {
// The scrollable frame cannot scroll actually. We should look for
// another scrollable frame which can scrollable, however, if there is
// no such frame, we should return top most scrollable frame.
break;
}
return scrollableFrame;
} while (0);
if (frame->GetContent() == capturingContent) {
foundCapturingContent = PR_TRUE;
} else if (foundCapturingContent) {
break; // There is no scrollable frame in the capturing content
}
}
return lastScrollableFrame;
}
/**
* Handles the Mouse Press Event for the frame
*/
@ -2094,49 +2223,52 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
}
}
// check whether style allows selection
// if not, don't tell selection the mouse event even occurred.
PRBool selectable;
PRUint8 selectStyle;
rv = IsSelectable(&selectable, &selectStyle);
if (NS_FAILED(rv)) return rv;
// check for select: none
if (!selectable)
return NS_OK;
// When implementing NS_STYLE_USER_SELECT_ELEMENT, NS_STYLE_USER_SELECT_ELEMENTS and
// NS_STYLE_USER_SELECT_TOGGLE, need to change this logic
PRBool useFrameSelection = (selectStyle == NS_STYLE_USER_SELECT_TEXT);
// If the mouse is dragged outside the nearest enclosing scrollable area
// while making a selection, the area will be scrolled. To do this, capture
// the mouse on the nearest scrollable frame. If there isn't a scrollable
// frame, or something else is already capturing the mouse, there's no
// reason to capture.
if (!nsIPresShell::GetCapturingContent()) {
nsIFrame* checkFrame = this;
nsIScrollableFrame *scrollFrame = nsnull;
while (checkFrame) {
scrollFrame = do_QueryFrame(checkFrame);
if (scrollFrame) {
nsIPresShell::SetCapturingContent(checkFrame->GetContent(), CAPTURE_IGNOREALLOWED);
break;
}
checkFrame = checkFrame->GetParent();
}
nsFrameSelection* fs = GetFrameSelectionForSelectingByMouse();
if (!fs) {
return NS_OK; // maybe, select: none
}
// XXX This is screwy; it really should use the selection frame, not the
// event frame
const nsFrameSelection* frameselection = nsnull;
if (useFrameSelection)
frameselection = GetConstFrameSelection();
else
frameselection = shell->ConstFrameSelection();
// If the mouse is dragged outside the selection root's scrollable area
// while making a selection, the area will be scrolled. To do this, capture
// the mouse on the selection root frame. However, in table selection mode,
// a nearest scrollable frame should be captured the mouse because each
// scrollable frame except the nearest one doesn't need to scroll during
// selection.
if (!frameselection || frameselection->GetDisplaySelection() == nsISelectionController::SELECTION_OFF)
// If something else is already capturing the mouse, the current selection
// root must be the capturing content. However, it might be outside of the
// this frame's selection root content. Then, we should do nothing.
nsIContent* capturingContent = nsIPresShell::GetCapturingContent();
PRBool captureMouse = !capturingContent;
NS_ASSERTION(mContent, "mContent must not be null");
nsIContent* selectionRootOfThisFrame =
mContent->GetSelectionRootContent(shell);
NS_ASSERTION(selectionRootOfThisFrame,
"mContent must have a selection root content");
if (capturingContent) {
nsIFrame* capturingFrame = capturingContent->GetPrimaryFrame();
NS_ENSURE_TRUE(capturingFrame, NS_OK);
nsIPresShell* capturedPresShell =
capturingFrame->PresContext()->PresShell();
NS_ASSERTION(capturedPresShell,
"The captured content must have a presShell");
nsIContent* selectionRootOfCapturedContent =
capturingContent->GetSelectionRootContent(capturedPresShell);
NS_ASSERTION(selectionRootOfCapturedContent,
"The captured content must have a selection root content");
if (selectionRootOfThisFrame != selectionRootOfCapturedContent) {
return NS_OK;
}
} else {
nsIContent* contentToCaptureForSelection =
GetContentToCaptureForSelection(selectionRootOfThisFrame);
nsIPresShell::SetCapturingContent(contentToCaptureForSelection,
CAPTURE_IGNOREALLOWED);
}
if (fs->GetDisplaySelection() == nsISelectionController::SELECTION_OFF) {
return NS_OK;//nothing to do we cannot affect selection from here
}
nsMouseEvent *me = (nsMouseEvent *)aEvent;
@ -2148,13 +2280,12 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
PRBool control = me->isControl;
#endif
nsRefPtr<nsFrameSelection> fc = const_cast<nsFrameSelection*>(frameselection);
if (me->clickCount >1 )
{
// These methods aren't const but can't actually delete anything,
// so no need for nsWeakFrame.
fc->SetMouseDownState(PR_TRUE);
fc->SetMouseDoubleDown(PR_TRUE);
fs->SetMouseDownState(PR_TRUE);
fs->SetMouseDoubleDown(PR_TRUE);
return HandleMultiplePress(aPresContext, aEvent, aEventStatus, control);
}
@ -2168,14 +2299,24 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
nsCOMPtr<nsIContent>parentContent;
PRInt32 contentOffset;
PRInt32 target;
rv = GetDataForTableSelection(frameselection, shell, me, getter_AddRefs(parentContent), &contentOffset, &target);
rv = GetDataForTableSelection(fs, shell, me, getter_AddRefs(parentContent),
&contentOffset, &target);
if (NS_SUCCEEDED(rv) && parentContent)
{
fc->SetMouseDownState(PR_TRUE);
return fc->HandleTableSelection(parentContent, contentOffset, target, me);
// In table selection mode, a nearest scrollable frame should capture the
// mouse events.
if (captureMouse) {
nsIScrollableFrame* scrollableFrame =
FindNearestScrollableFrameForSelection(this);
nsIFrame* frame = do_QueryFrame(scrollableFrame);
nsIPresShell::SetCapturingContent(frame->GetContent(),
CAPTURE_IGNOREALLOWED);
}
fs->SetMouseDownState(PR_TRUE);
return fs->HandleTableSelection(parentContent, contentOffset, target, me);
}
fc->SetDelayedCaretData(0);
fs->SetDelayedCaretData(0);
// Check if any part of this frame is selected, and if the
// user clicked inside the selected region. If so, we delay
@ -2188,8 +2329,8 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
if (isSelected)
{
PRBool inSelection = PR_FALSE;
details = frameselection->LookUpSelection(offsets.content, 0,
offsets.EndOffset(), PR_FALSE);
details =
fs->LookUpSelection(offsets.content, 0, offsets.EndOffset(), PR_FALSE);
//
// If there are any details, check to see if the user clicked
@ -2221,17 +2362,17 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
}
if (inSelection) {
fc->SetMouseDownState(PR_FALSE);
fc->SetDelayedCaretData(me);
fs->SetMouseDownState(PR_FALSE);
fs->SetDelayedCaretData(me);
return NS_OK;
}
}
fc->SetMouseDownState(PR_TRUE);
fs->SetMouseDownState(PR_TRUE);
// Do not touch any nsFrame members after this point without adding
// weakFrame checks.
rv = fc->HandleClick(offsets.content, offsets.StartOffset(),
rv = fs->HandleClick(offsets.content, offsets.StartOffset(),
offsets.EndOffset(), me->isShift, control,
offsets.associateWithNext);
@ -2239,7 +2380,7 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
return rv;
if (offsets.offset != offsets.secondaryOffset)
fc->MaintainSelection();
fs->MaintainSelection();
if (isEditor && !me->isShift &&
(offsets.EndOffset() - offsets.StartOffset()) == 1)
@ -2249,7 +2390,7 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
// -moz-user-select: all or a non-text node without children).
// Therefore, disable selection extension during mouse moves.
// XXX This is a bit hacky; shouldn't editor be able to deal with this?
fc->SetMouseDownState(PR_FALSE);
fs->SetMouseDownState(PR_FALSE);
}
return rv;
@ -2401,46 +2542,56 @@ nsFrame::PeekBackwardAndForward(nsSelectionAmount aAmountBack,
return frameSelection->MaintainSelection(aAmountBack);
}
NS_IMETHODIMP nsFrame::HandleDrag(nsPresContext* aPresContext,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus)
NS_IMETHODIMP
nsFrame::HandleDrag(nsPresContext* aPresContext,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus)
{
PRBool selectable;
PRUint8 selectStyle;
IsSelectable(&selectable, &selectStyle);
// XXX Do we really need to exclude non-selectable content here?
// GetContentOffsetsFromPoint can handle it just fine, although some
// other stuff might not like it.
if (!selectable)
return NS_OK;
if (DisplaySelection(aPresContext) == nsISelectionController::SELECTION_OFF) {
return NS_OK;
nsFrame* target;
nsRefPtr<nsFrameSelection> fs =
FindDraggingFrameSelection(aPresContext->PresShell(), &target);
if (!fs || !target || IsSelectionOff()) {
return NS_OK; // not selecting now
}
nsIPresShell *presShell = aPresContext->PresShell();
nsRefPtr<nsFrameSelection> frameselection = GetFrameSelection();
PRBool mouseDown = frameselection->GetMouseDownState();
if (!mouseDown)
return NS_OK;
// Stop auto scrolling, first.
fs->StopAutoScrollTimer();
frameselection->StopAutoScrollTimer();
return target->ExpandSelectionByMouseMove(fs, fs->GetShell(),
static_cast<nsMouseEvent*>(aEvent),
aEventStatus);
}
nsresult
nsFrame::ExpandSelectionByMouseMove(nsFrameSelection* aFrameSelection,
nsIPresShell* aPresShell,
nsMouseEvent* aEvent,
nsEventStatus* aEventStatus)
{
#ifdef DEBUG
nsFrameSelection* draggingFrameSelection =
nsFrameSelection::GetMouseDownFrameSelection();
NS_ASSERTION(draggingFrameSelection &&
draggingFrameSelection == GetConstFrameSelection(),
"aFrameSelection must be handling current drag for selection");
#endif
// Check if we are dragging in a table cell
nsCOMPtr<nsIContent> parentContent;
PRInt32 contentOffset;
PRInt32 target;
nsMouseEvent *me = (nsMouseEvent *)aEvent;
nsresult result;
result = GetDataForTableSelection(frameselection, presShell, me,
getter_AddRefs(parentContent),
&contentOffset, &target);
nsresult rv = GetDataForTableSelection(aFrameSelection, aPresShell,
aEvent, getter_AddRefs(parentContent),
&contentOffset, &target);
PRBool handleTableSelection = NS_SUCCEEDED(rv) && parentContent;
nsWeakFrame weakThis = this;
if (NS_SUCCEEDED(result) && parentContent) {
frameselection->HandleTableSelection(parentContent, contentOffset, target, me);
if (handleTableSelection) {
aFrameSelection->HandleTableSelection(parentContent, contentOffset,
target, aEvent);
} else {
nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
frameselection->HandleDrag(this, pt);
aFrameSelection->HandleDrag(this, pt);
}
// The frameselection object notifies selection listeners synchronously above
@ -2449,175 +2600,312 @@ NS_IMETHODIMP nsFrame::HandleDrag(nsPresContext* aPresContext,
return NS_OK;
}
// get the nearest scrollframe
nsIFrame* checkFrame = this;
nsIScrollableFrame *scrollFrame = nsnull;
while (checkFrame) {
scrollFrame = do_QueryFrame(checkFrame);
if (scrollFrame) {
break;
}
checkFrame = checkFrame->GetParent();
nsIContent* capturingContent = nsIPresShell::GetCapturingContent();
if (!capturingContent) {
return NS_OK; // The capture was canceled.
}
nsIContent* selectionRoot =
GetSelectionRootContentForCapturingContent(aPresShell, capturingContent);
if (scrollFrame) {
nsIFrame* capturingFrame = scrollFrame->GetScrolledFrame();
if (capturingFrame) {
nsPoint pt =
nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, capturingFrame);
frameselection->StartAutoScrollTimer(capturingFrame, pt, 30);
}
}
return NS_OK;
}
/**
* This static method handles part of the nsFrame::HandleRelease in a way
* which doesn't rely on the nsFrame object to stay alive.
*/
static nsresult
HandleFrameSelection(nsFrameSelection* aFrameSelection,
nsIFrame::ContentOffsets& aOffsets,
PRBool aHandleTableSel,
PRInt32 aContentOffsetForTableSel,
PRInt32 aTargetForTableSel,
nsIContent* aParentContentForTableSel,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus)
{
if (!aFrameSelection) {
nsIScrollableFrame* scrollableFrame =
FindNearestScrollableFrameForSelection(this, selectionRoot);
// If a non-scrollable content captures by script, we may not be able to find
// any scrollable frame.
if (!scrollableFrame) {
return NS_OK;
}
nsresult rv = NS_OK;
const PRUint32 kAutoScrollTimerDelay = 30;
if (nsEventStatus_eConsumeNoDefault != *aEventStatus) {
if (!aHandleTableSel) {
nsMouseEvent *me = aFrameSelection->GetDelayedCaretData();
if (!aOffsets.content || !me) {
return NS_ERROR_FAILURE;
if (!handleTableSelection) {
nsIScrollableFrame* selectionRootScrollableFrame =
FindNearestScrollableFrameForSelection(selectionRoot->GetPrimaryFrame());
NS_ENSURE_TRUE(selectionRootScrollableFrame, NS_OK);
while (scrollableFrame) {
// We don't need to scroll the selection root frame when the mouse cursor
// is on its edge because selection root frame will be scrolled when the
// mouse cursor is outside of the frame. And user may want slower scroll
// than the "on edge" scroll speed.
if (selectionRootScrollableFrame == scrollableFrame) {
break;
}
// We are doing this to simulate what we would have done on HandlePress.
// We didn't do it there to give the user an opportunity to drag
// the text, but since they didn't drag, we want to place the
// caret.
// However, we'll use the mouse position from the release, since:
// * it's easier
// * that's the normal click position to use (although really, in
// the normal case, small movements that don't count as a drag
// can do selection)
aFrameSelection->SetMouseDownState(PR_TRUE);
nsPoint scrollTo;
if (IsOnScrollableFrameEdge(scrollableFrame, aEvent, scrollTo)) {
aFrameSelection->StartAutoScrollTimer(
scrollableFrame->GetScrolledFrame(), scrollTo, kAutoScrollTimerDelay);
return NS_OK;
}
rv = aFrameSelection->HandleClick(aOffsets.content,
aOffsets.StartOffset(),
aOffsets.EndOffset(),
me->isShift, PR_FALSE,
aOffsets.associateWithNext);
if (NS_FAILED(rv)) {
return rv;
}
} else if (aParentContentForTableSel) {
aFrameSelection->SetMouseDownState(PR_FALSE);
rv = aFrameSelection->HandleTableSelection(aParentContentForTableSel,
aContentOffsetForTableSel,
aTargetForTableSel,
(nsMouseEvent *)aEvent);
if (NS_FAILED(rv)) {
return rv;
}
nsIFrame* frame = do_QueryFrame(scrollableFrame);
scrollableFrame =
FindNearestScrollableFrameForSelection(frame->GetParent(),
selectionRoot);
}
aFrameSelection->SetDelayedCaretData(0);
scrollableFrame = selectionRootScrollableFrame;
}
aFrameSelection->SetMouseDownState(PR_FALSE);
aFrameSelection->StopAutoScrollTimer();
if (!scrollableFrame) {
return NS_OK;
}
nsIFrame* scrolledFrame = scrollableFrame->GetScrolledFrame();
NS_ASSERTION(scrolledFrame,
"The found scrollable frame doesn't have scrolled frame");
nsPoint scrollTo =
nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, scrolledFrame);
aFrameSelection->StartAutoScrollTimer(scrolledFrame, scrollTo,
kAutoScrollTimerDelay);
return NS_OK;
}
NS_IMETHODIMP nsFrame::HandleRelease(nsPresContext* aPresContext,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus)
nsFrame*
nsFrame::FindSelectableAncestor(nsIFrame* aFrame,
nsFrameSelection* aFrameSelection)
{
nsIFrame* activeFrame = GetActiveSelectionFrame(aPresContext, this);
// If we're not selecting by mouse dragging, our ancestor must be selecting,
// so, we should handle it on the first selectable ancestor frame of the
// selecting document.
for (nsIFrame* frame = aFrame; frame;
frame = nsLayoutUtils::GetCrossDocParentFrame(frame)) {
PRBool selectable = PR_FALSE;
if (frame->GetConstFrameSelection() == aFrameSelection &&
NS_SUCCEEDED(frame->IsSelectable(&selectable, nsnull)) &&
selectable) {
nsFrame* result = do_QueryFrame(frame);
if (result) {
return result;
}
}
}
return nsnull;
}
nsFrameSelection*
nsFrame::FindDraggingFrameSelection(nsIPresShell* aPresShell,
nsFrame** aEventTarget)
{
*aEventTarget = nsnull;
nsFrameSelection* fs = nsFrameSelection::GetMouseDownFrameSelection();
if (!fs) {
return nsnull; // not dragging now
}
NS_ASSERTION(fs->GetMouseDownState(),
"Wrong nsFrameSelection was returned by GetMouseDownFrameSelection()");
nsIFrame* selectingFrame = this;
// If this frame is for capturing content and it has independent selection,
// the actual selection root element might be its child or descendant which
// is a native anonymous element.
if (mContent == nsIPresShell::GetCapturingContent()) {
nsIContent* selectionRoot =
GetSelectionRootContentForCapturingContent(aPresShell, mContent);
if (selectionRoot) {
nsIFrame* frame = selectionRoot->GetPrimaryFrame();
if (frame) {
selectingFrame = frame;
}
}
}
*aEventTarget = FindSelectableAncestor(selectingFrame, fs);
if (!*aEventTarget) {
*aEventTarget = this;
}
return fs;
}
PRBool
nsFrame::IsOnScrollableFrameEdge(nsIScrollableFrame* aScrollableFrame,
nsGUIEvent* aEvent,
nsPoint &aScrollIntoView)
{
nsIFrame* scrollableFrame = do_QueryFrame(aScrollableFrame);
nsPoint ptInScrollableFrame =
nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, scrollableFrame);
nsPoint scrollPosition = aScrollableFrame->GetScrollPosition();
nsRect scrollRange = aScrollableFrame->GetScrollRange();
nsRect scrollPort = aScrollableFrame->GetScrollPortRect();
nsIFrame* scrolledFrame = aScrollableFrame->GetScrolledFrame();
NS_ENSURE_TRUE(scrolledFrame, PR_FALSE);
aScrollIntoView =
nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, scrolledFrame);
// The edge width (or height) is defined by pref, however, if the value
// is too thick for the frame, we should use 1/4 width (or height) of
// the frame.
static const char kPrefName_EdgeWidth[] =
"layout.selection.drag.autoscroll.inner_frame.edge_width";
nsPresContext* pc = PresContext();
PRInt32 edgePixel = Preferences::GetInt(kPrefName_EdgeWidth);
nscoord edgeApp = pc->DevPixelsToAppUnits(edgePixel);
nscoord onePixel = pc->DevPixelsToAppUnits(1);
nscoord edgeH = NS_MAX(onePixel, NS_MIN(edgeApp, scrollPort.width / 4));
nscoord edgeV = NS_MAX(onePixel, NS_MIN(edgeApp, scrollPort.height / 4));
// The scrolling mouse is defined by pref, however, if the amount is
// too big for the frame, we should use 1/2 width (or height) of the
// frame.
static const char kPrefName_ScrollAmount[] =
"layout.selection.drag.autoscroll.inner_frame.amount";
PRInt32 scrollAmountPixel =
NS_MAX(Preferences::GetInt(kPrefName_ScrollAmount), 1);
nscoord scrollAmountApp = pc->DevPixelsToAppUnits(scrollAmountPixel);
nscoord scrollAmountH =
NS_MAX(onePixel, NS_MIN(scrollAmountApp, scrollPort.width / 2));
nscoord scrollAmountV =
NS_MAX(onePixel, NS_MIN(scrollAmountApp, scrollPort.height / 2));
PRBool isOnEdge = PR_FALSE;
if (ptInScrollableFrame.x < scrollPort.x + edgeH) {
if (scrollRange.x < scrollPosition.x) {
// Scroll to left.
aScrollIntoView.x = scrollPosition.x - scrollAmountH;
isOnEdge = PR_TRUE;
}
} else if (ptInScrollableFrame.x > scrollPort.x + scrollPort.width - edgeH) {
if (scrollRange.width > scrollPosition.x) {
// Scroll to right.
aScrollIntoView.x = scrollPosition.x + scrollPort.width + scrollAmountH;
isOnEdge = PR_TRUE;
}
}
if (ptInScrollableFrame.y < scrollPort.y + edgeV) {
if (scrollRange.y < scrollPosition.y) {
// Scroll to top.
aScrollIntoView.y = scrollPosition.y - scrollAmountV;
isOnEdge = PR_TRUE;
}
} else if (ptInScrollableFrame.y > scrollPort.y + scrollPort.height - edgeV) {
if (scrollRange.height > scrollPosition.y) {
// Scroll to bottom.
aScrollIntoView.y = scrollPosition.y + scrollPort.height + scrollAmountV;
isOnEdge = PR_TRUE;
}
}
return isOnEdge;
}
NS_IMETHODIMP
nsFrame::HandleRelease(nsPresContext* aPresContext,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus)
{
nsCOMPtr<nsIContent> captureContent = nsIPresShell::GetCapturingContent();
// We can unconditionally stop capturing because
// we should never be capturing when the mouse button is up
nsIPresShell::SetCapturingContent(nsnull, 0);
PRBool selectionOff =
(DisplaySelection(aPresContext) == nsISelectionController::SELECTION_OFF);
nsFrame* targetFrame;
nsRefPtr<nsFrameSelection> fs =
FindDraggingFrameSelection(aPresContext->PresShell(), &targetFrame);
if (!fs) {
// If mouse button was pressed on selected text and released without
// mousemove event, there is no dragging frame selection. At that time,
// we need to clean up the pressed state with the frame selection for this
// frame.
fs = GetFrameSelectionForSelectingByMouse();
if (!fs) {
return NS_OK; // maybe, select: none
}
targetFrame = FindSelectableAncestor(this, fs);
if (!targetFrame) {
// XXX At this time, can we just return?
targetFrame = this;
}
}
NS_ASSERTION(targetFrame, "targetFrame must be non-null");
nsMouseEvent* mouseEvent = static_cast<nsMouseEvent*>(aEvent);
return targetFrame->EndSelectionChangeByMouse(fs, mouseEvent, aEventStatus);
}
nsresult
nsFrame::EndSelectionChangeByMouse(nsFrameSelection* aFrameSelection,
nsMouseEvent* aMouseEvent,
nsEventStatus* aEventStatus)
{
PRBool wasMouseDown = aFrameSelection->GetMouseDownState();
// First, stop expanding selection if necessary
aFrameSelection->SetMouseDownState(PR_FALSE);
aFrameSelection->StopAutoScrollTimer();
if (IsSelectionOff() || nsEventStatus_eConsumeNoDefault == *aEventStatus) {
return NS_OK;
}
// Check if the frameselection recorded the mouse going down.
// If not, the user must have clicked in a part of the selection.
// Place the caret before continuing!
nsresult rv = NS_OK;
nsMouseEvent* delayedEvent = aFrameSelection->GetDelayedCaretData();
if (!wasMouseDown && delayedEvent && delayedEvent->clickCount < 2) {
nsPoint pt =
nsLayoutUtils::GetEventCoordinatesRelativeTo(aMouseEvent, this);
ContentOffsets offsets = GetContentOffsetsFromPoint(pt);
NS_ENSURE_TRUE(offsets.content, NS_ERROR_FAILURE);
// We are doing this to simulate what we would have done on HandlePress.
// We didn't do it there to give the user an opportunity to drag
// the text, but since they didn't drag, we want to place the
// caret.
// However, we'll use the mouse position from the release, since:
// * it's easier
// * that's the normal click position to use (although really, in
// the normal case, small movements that don't count as a drag
// can do selection)
aFrameSelection->SetMouseDownState(PR_TRUE);
// XXX Do not call any methods of the current object after this point!!!
// The object is perhaps dead!
rv = aFrameSelection->HandleClick(offsets.content,
offsets.StartOffset(),
offsets.EndOffset(),
delayedEvent->isShift,
PR_FALSE,
offsets.associateWithNext);
aFrameSelection->SetMouseDownState(PR_FALSE);
aFrameSelection->SetDelayedCaretData(0);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsRefPtr<nsFrameSelection> frameselection;
ContentOffsets offsets;
nsCOMPtr<nsIContent> parentContent;
PRInt32 contentOffsetForTableSel = 0;
PRInt32 targetForTableSel = 0;
PRBool handleTableSelection = PR_TRUE;
if (!selectionOff) {
frameselection = GetFrameSelection();
if (nsEventStatus_eConsumeNoDefault != *aEventStatus && frameselection) {
// Check if the frameselection recorded the mouse going down.
// If not, the user must have clicked in a part of the selection.
// Place the caret before continuing!
PRBool mouseDown = frameselection->GetMouseDownState();
nsMouseEvent *me = frameselection->GetDelayedCaretData();
if (!mouseDown && me && me->clickCount < 2) {
nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
offsets = GetContentOffsetsFromPoint(pt);
handleTableSelection = PR_FALSE;
} else {
GetDataForTableSelection(frameselection, PresContext()->PresShell(),
(nsMouseEvent *)aEvent,
getter_AddRefs(parentContent),
&contentOffsetForTableSel,
&targetForTableSel);
}
}
GetDataForTableSelection(aFrameSelection, PresContext()->PresShell(),
aMouseEvent, getter_AddRefs(parentContent),
&contentOffsetForTableSel, &targetForTableSel);
if (parentContent) {
// XXX Do not call any methods of the current object after this point!!!
// The object is perhaps dead!
rv = aFrameSelection->HandleTableSelection(parentContent,
contentOffsetForTableSel,
targetForTableSel,
aMouseEvent);
}
aFrameSelection->SetDelayedCaretData(nsnull);
// We might be capturing in some other document and the event just happened to
// trickle down here. Make sure that document's frame selection is notified.
// Note, this may cause the current nsFrame object to be deleted, bug 336592.
nsRefPtr<nsFrameSelection> frameSelection;
if (activeFrame != this &&
static_cast<nsFrame*>(activeFrame)->DisplaySelection(activeFrame->PresContext())
!= nsISelectionController::SELECTION_OFF) {
frameSelection = activeFrame->GetFrameSelection();
}
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
// Also check the selection of the capturing content which might be in a
// different document.
if (!frameSelection && captureContent) {
nsIDocument* doc = captureContent->GetCurrentDoc();
if (doc) {
nsIPresShell* capturingShell = doc->GetShell();
if (capturingShell && capturingShell != PresContext()->GetPresShell()) {
frameSelection = capturingShell->FrameSelection();
}
}
}
if (frameSelection) {
frameSelection->SetMouseDownState(PR_FALSE);
frameSelection->StopAutoScrollTimer();
}
// Do not call any methods of the current object after this point!!!
// The object is perhaps dead!
return selectionOff
? NS_OK
: HandleFrameSelection(frameselection, offsets, handleTableSelection,
contentOffsetForTableSel, targetForTableSel,
parentContent, aEvent, aEventStatus);
PRBool
nsFrame::IsSelectionOff()
{
nsRefPtr<nsFrameSelection> fs = GetFrameSelection();
NS_ENSURE_TRUE(fs, PR_TRUE);
return (fs->GetDisplaySelection() == nsISelectionController::SELECTION_OFF);
}
struct NS_STACK_CLASS FrameContentRange {

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

@ -599,6 +599,53 @@ protected:
nsIContent **aParentContent, PRInt32 *aContentOffset,
PRInt32 *aTarget);
// Returns nsFrameSelection which is handling drag for selection.
// If it's not dragging for selection, this returns NULL. Otherwise,
// this returns the handling nsFrameSelection and a frame which is ancestor
// and should handle mouse events for selection.
nsFrameSelection* FindDraggingFrameSelection(nsIPresShell* aPresShell,
nsFrame** aEventTarget);
// ExpandSelectionByMouseMove() will expand selection by aEvent.
// This should be called ONLY when the frame is mouse event target which is
// found by FindDraggingFrameSelection(). And aFrameSelection must be the
// drag handling nsFrameSelection.
nsresult ExpandSelectionByMouseMove(nsFrameSelection* aFrameSelection,
nsIPresShell* aPresShell,
nsMouseEvent* aEvent,
nsEventStatus* aEventStatus);
// EndSelectionChangeByMouse() will stop the drag for selection if during
// that. And also cancel the selection if it's clicked on the selection
// range.
// This can be called on every frame. However, if an nsFrameSelection is
// handling drag for selection, this is called on the mouse event target
// frame which is computed by FindDraggingFrameSelection().
// Otherwise, nearest ancestor selectable frame's should be called.
nsresult EndSelectionChangeByMouse(nsFrameSelection* aFrameSelection,
nsMouseEvent* aMouseEvent,
nsEventStatus* aEventStatus);
// IsOnScrollableFrameEdge() checks whether the aEvent is fired on the
// edge of aScrollableFrame and it can be scrolled to the direction of the
// edge. If aEvent is fired on the edge and scrollable, this returns TRUE.
// Otherwise, FALSE. When this returns TRUE, this computes aScrollIntoView.
PRBool IsOnScrollableFrameEdge(nsIScrollableFrame* aScrollableFrame,
nsGUIEvent* aEvent,
nsPoint &aScrollIntoView);
// FindSelectableAncestor() returns a frame which is the nearest selectable
// ancestor of aFrame.
static nsFrame* FindSelectableAncestor(nsIFrame* aFrame,
nsFrameSelection* aFrameSelection);
// Returns nsFrameSelection for selecting by mouse in the frame.
nsFrameSelection* GetFrameSelectionForSelectingByMouse();
// If selection is off, returns TRUE. Otherwise, FALSE.
// This method always uses the frame's nsFrameSelection.
PRBool IsSelectionOff();
// Fills aCursor with the appropriate information from ui
static void FillCursorInformationFromStyle(const nsStyleUserInterface* ui,
nsIFrame::Cursor& aCursor);

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

@ -369,6 +369,15 @@ public:
*/
PRBool GetMouseDownState() const { return mMouseDownState; }
/**
* GetMouseDownedFrameSelection returns an instance which is handling
* mouse dragging.
*/
static nsFrameSelection* GetMouseDownFrameSelection()
{
return sDraggingFrameSelection;
}
/**
if we are in table cell selection mode. aka ctrl click in table cell
*/
@ -598,6 +607,7 @@ public:
nsFrameSelection();
virtual ~nsFrameSelection();
void StartBatchChanges();
void EndBatchChanges();
@ -696,6 +706,8 @@ private:
nsresult CreateAndAddRange(nsINode *aParentNode, PRInt32 aOffset);
nsresult ClearNormalSelection();
static nsFrameSelection* sDraggingFrameSelection;
nsCOMPtr<nsINode> mCellParent; //used to snap to table selection
nsCOMPtr<nsIContent> mStartSelectedCell;
nsCOMPtr<nsIContent> mEndSelectedCell;

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

@ -140,7 +140,7 @@ static void printRange(nsIRange *aDomRange);
#define DEBUG_OUT_RANGE(x)
#endif //MOZ_DEBUG
nsFrameSelection* nsFrameSelection::sDraggingFrameSelection = nsnull;
//#define DEBUG_SELECTION // uncomment for printf describing every collapse and extend.
//#define DEBUG_NAVIGATION
@ -425,7 +425,8 @@ public:
}
// aPoint is relative to aPresContext's root frame
nsresult Start(nsPresContext *aPresContext, nsPoint &aPoint)
nsresult Start(nsPresContext *aPresContext, nsIContent *aContent,
nsPoint &aPoint)
{
mPoint = aPoint;
@ -433,7 +434,7 @@ public:
// stopped by the selection if the prescontext is destroyed.
mPresContext = aPresContext;
mContent = nsIPresShell::GetCapturingContent();
mContent = aContent;
if (!mTimer)
{
@ -747,6 +748,13 @@ nsFrameSelection::nsFrameSelection()
mSelectionChangeReason = nsISelectionListener::NO_REASON;
}
nsFrameSelection::~nsFrameSelection()
{
if (this == sDraggingFrameSelection) {
sDraggingFrameSelection = nsnull;
}
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsFrameSelection)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFrameSelection)
@ -916,41 +924,10 @@ nsFrameSelection::ConstrainFrameAndPointToAnchorSubtree(nsIFrame *aFrame,
if (anchorRoot == contentRoot)
{
// If the aFrame's content isn't the capturing content, it should be
// a descendant. At this time, we can return simply.
nsIContent* capturedContent = nsIPresShell::GetCapturingContent();
if (capturedContent != content)
{
return NS_OK;
}
// Find the frame under the mouse cursor with the root frame.
// At this time, don't use the anchor's frame because it may not have
// fixed positioned frames.
nsIFrame* rootFrame = mShell->FrameManager()->GetRootFrame();
nsPoint ptInRoot = aPoint + aFrame->GetOffsetTo(rootFrame);
nsIFrame* cursorFrame =
nsLayoutUtils::GetFrameForPoint(rootFrame, ptInRoot);
// If the mouse cursor in on a frame which is descendant of same
// selection root, we can expand the selection to the frame.
if (cursorFrame && cursorFrame->PresContext()->PresShell() == mShell)
{
nsIContent* cursorContent = cursorFrame->GetContent();
NS_ENSURE_TRUE(cursorContent, NS_ERROR_FAILURE);
nsIContent* cursorContentRoot =
cursorContent->GetSelectionRootContent(mShell);
NS_ENSURE_TRUE(cursorContentRoot, NS_ERROR_UNEXPECTED);
if (cursorContentRoot == anchorRoot)
{
*aRetFrame = cursorFrame;
aRetPoint = aPoint + aFrame->GetOffsetTo(cursorFrame);
return NS_OK;
}
}
// Otherwise, e.g., the cursor isn't on any frames (e.g., the mouse
// cursor is out of the window), we should use the frame of the anchor
// root.
// The anchor and aFrame's root are the same. There
// is no need to constrain, simply return aFrame.
*aRetFrame = aFrame;
return NS_OK;
}
}
@ -1943,10 +1920,16 @@ nsFrameSelection::SetMouseDownState(PRBool aState)
if (mMouseDownState == aState)
return;
NS_ASSERTION((aState && !sDraggingFrameSelection) ||
(!aState && sDraggingFrameSelection),
"Unexpected state happened");
mMouseDownState = aState;
if (!mMouseDownState)
{
if (mMouseDownState) {
sDraggingFrameSelection = this;
} else {
sDraggingFrameSelection = nsnull;
mDragSelectingCells = PR_FALSE;
PostReason(nsISelectionListener::MOUSEUP_REASON);
NotifySelectionListeners(nsISelectionController::SELECTION_NORMAL); //notify that reason is mouse up please.
@ -4716,7 +4699,8 @@ nsTypedSelection::DoAutoScroll(nsIFrame *aFrame, nsPoint& aPoint)
{
nsPoint presContextPoint = globalPoint -
presContext->PresShell()->FrameManager()->GetRootFrame()->GetOffsetToCrossDoc(rootmostFrame);
mAutoScrollTimer->Start(presContext, presContextPoint);
mAutoScrollTimer->Start(presContext, aFrame->GetContent(),
presContextPoint);
}
return NS_OK;

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

@ -135,6 +135,8 @@ _CHROME_FILES = \
test_backspace_delete.xul \
test_bug514732-2.xul \
file_bug514732_window.xul \
test_selection_scrolling.html \
window_selection_scrolling.html \
$(NULL)
libs:: $(_TEST_FILES)

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

@ -184,28 +184,21 @@ function test()
// selection starting at div1
synthesizeMouse(div1, 30, 5, { type: "mousedown" });
// XXX if we move the mouse cursor to another document, the
// nsFrameSelection::HandleDrag method is called on the another document's.
// to iframe
synthesizeMouse(iframe, 30, 5, { type: "mousemove" });
check(kTrue | kToDo, kFalse, kFalse,
check(kTrue, kFalse, kFalse,
kFalse, kFalse, kFalse, kFalse, kFalse, kFalse,
"div1-iframe, all boxes are overflow: " + kOverflows[i] + ";");
// XXX if the overflow is visible, synthesizeMouse with the input element
// or textarea element doesn't work fine.
var isVisibleTesting = kOverflows[i] == "visible";
var todoFlag = isVisibleTesting ? kToDo : 0;
// to input
synthesizeMouse(input, 30, 5, { type: "mousemove" });
check(kTrue | todoFlag, kTrue | todoFlag, kFalse,
check(kTrue, kTrue, kFalse,
kFalse, kFalse, kFalse, kFalse, kFalse, kFalse,
"div1-input, all boxes are overflow: " + kOverflows[i] + ";");
// to textarea
synthesizeMouse(textarea, 30, 5, { type: "mousemove" });
check(kTrue | todoFlag, kTrue | todoFlag, kTrue | todoFlag,
check(kTrue, kTrue, kTrue,
kFalse, kFalse, kFalse, kFalse, kFalse, kFalse,
"div1-textarea, all boxes are overflow: " + kOverflows[i] + ";");

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

@ -0,0 +1,22 @@
<!DOCTYPE>
<html>
<head>
<title>selection scrolling test</title>
<script type="text/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="text/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
window.open("window_selection_scrolling.html", "_blank",
"top=200,left=200,width=300,height=300,scrollbars=yes");
</script>
</pre>
</body>
</html>

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -169,7 +169,7 @@ nsAutoRepeatBoxFrame::HandleRelease(nsPresContext* aPresContext,
if (!IsActivatedOnHover()) {
StopRepeat();
}
return NS_OK;
return nsButtonBoxFrame::HandleRelease(aPresContext, aEvent, aEventStatus);
}
NS_IMETHODIMP

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

@ -82,11 +82,10 @@ nsScrollbarButtonFrame::HandleEvent(nsPresContext* aPresContext,
return NS_OK;
}
// XXX hack until handle release is actually called in nsframe.
if (aEvent->message == NS_MOUSE_EXIT_SYNTH ||
aEvent->message == NS_MOUSE_BUTTON_UP)
HandleRelease(aPresContext, aEvent, aEventStatus);
if (aEvent->message == NS_MOUSE_EXIT_SYNTH) {
Deactivate();
}
// if we didn't handle the press ourselves, pass it on to the superclass
if (!HandleButtonPress(aPresContext, aEvent, aEventStatus))
return nsButtonBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
@ -191,10 +190,15 @@ nsScrollbarButtonFrame::HandleRelease(nsPresContext* aPresContext,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus)
{
// we're not active anymore
Deactivate();
return nsButtonBoxFrame::HandleRelease(aPresContext, aEvent, aEventStatus);
}
void
nsScrollbarButtonFrame::Deactivate()
{
mContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::active, PR_TRUE);
StopRepeat();
return NS_OK;
}
void nsScrollbarButtonFrame::Notify()

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

@ -81,10 +81,6 @@ public:
nsEventStatus* aEventStatus,
PRBool aControlHeld) { return NS_OK; }
NS_IMETHOD HandleDrag(nsPresContext* aPresContext,
nsGUIEvent * aEvent,
nsEventStatus* aEventStatus) { return NS_OK; }
NS_IMETHOD HandleRelease(nsPresContext* aPresContext,
nsGUIEvent * aEvent,
nsEventStatus* aEventStatus);
@ -105,6 +101,8 @@ protected:
}
PRInt32 mIncrement;
void Deactivate();
};
#endif

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

@ -158,22 +158,6 @@ nsScrollbarFrame::HandleMultiplePress(nsPresContext* aPresContext,
return NS_OK;
}
NS_IMETHODIMP
nsScrollbarFrame::HandleDrag(nsPresContext* aPresContext,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus)
{
return NS_OK;
}
NS_IMETHODIMP
nsScrollbarFrame::HandleRelease(nsPresContext* aPresContext,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus)
{
return NS_OK;
}
void
nsScrollbarFrame::SetScrollbarMediatorContent(nsIContent* aMediator)
{

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

@ -78,14 +78,6 @@ public:
nsEventStatus* aEventStatus,
PRBool aControlHeld);
NS_IMETHOD HandleDrag(nsPresContext* aPresContext,
nsGUIEvent * aEvent,
nsEventStatus* aEventStatus);
NS_IMETHOD HandleRelease(nsPresContext* aPresContext,
nsGUIEvent * aEvent,
nsEventStatus* aEventStatus);
NS_IMETHOD Init(nsIContent* aContent,
nsIFrame* aParent,
nsIFrame* aPrevInFlow);

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

@ -1044,7 +1044,7 @@ nsSliderFrame::HandleRelease(nsPresContext* aPresContext,
{
StopRepeat();
return NS_OK;
return nsBoxFrame::HandleRelease(aPresContext, aEvent, aEventStatus);
}
void

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

@ -148,10 +148,6 @@ public:
nsEventStatus* aEventStatus,
PRBool aControlHeld) { return NS_OK; }
NS_IMETHOD HandleDrag(nsPresContext* aPresContext,
nsGUIEvent * aEvent,
nsEventStatus* aEventStatus) { return NS_OK; }
NS_IMETHOD HandleRelease(nsPresContext* aPresContext,
nsGUIEvent * aEvent,
nsEventStatus* aEventStatus);

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

@ -379,22 +379,6 @@ nsSplitterFrame::HandleMultiplePress(nsPresContext* aPresContext,
return NS_OK;
}
NS_IMETHODIMP
nsSplitterFrame::HandleDrag(nsPresContext* aPresContext,
nsGUIEvent * aEvent,
nsEventStatus* aEventStatus)
{
return NS_OK;
}
NS_IMETHODIMP
nsSplitterFrame::HandleRelease(nsPresContext* aPresContext,
nsGUIEvent * aEvent,
nsEventStatus* aEventStatus)
{
return NS_OK;
}
NS_IMETHODIMP
nsSplitterFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,

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

@ -86,14 +86,6 @@ public:
nsEventStatus* aEventStatus,
PRBool aControlHeld);
NS_IMETHOD HandleDrag(nsPresContext* aPresContext,
nsGUIEvent * aEvent,
nsEventStatus* aEventStatus);
NS_IMETHOD HandleRelease(nsPresContext* aPresContext,
nsGUIEvent * aEvent,
nsEventStatus* aEventStatus);
NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus);

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

@ -1293,6 +1293,17 @@ pref("layout.word_select.stop_at_punctuation", true);
// deletes the selection (Unix default)
pref("layout.selection.caret_style", 0);
// Prefs for auto scrolling by mouse drag. When the mouse cursor is on edge of
// inner scrollable frame than the selection root, the frame will be scrolled.
// |.edge_width| defines the edge width by CSS pixels.
// |.amout| defines the scrolling speed by CSS pixels. The auto scroll method
// uses scroll to a point function. When the mouse cursor is on the edge, it
// tries to scroll the frame to the point which is away from the edge. The
// value means how far the point is from edge in CSS pixels.
// I.e., larger value makes faster scroll.
pref("layout.selection.drag.autoscroll.inner_frame.edge_width", 32);
pref("layout.selection.drag.autoscroll.inner_frame.amount", 8);
// pref to control whether or not to replace backslashes with Yen signs
// in documents encoded in one of Japanese legacy encodings (EUC-JP,
// Shift_JIS, ISO-2022-JP)

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

@ -220,6 +220,13 @@ function synthesizeMouse(aTarget, aOffsetX, aOffsetY, aEvent, aWindow)
var left = rect.left + aOffsetX;
var top = rect.top + aOffsetY;
// body's bounding client rect depends its scroll position.
var body = aTarget.ownerDocument.body;
if (body == aTarget) {
left += aTarget.scrollLeft;
top += aTarget.scrollTop;
}
if (aEvent.type) {
utils.sendMouseEvent(aEvent.type, left, top, button, clickCount, modifiers);
}
@ -282,8 +289,14 @@ function synthesizeMouseScroll(aTarget, aOffsetX, aOffsetY, aEvent, aWindow)
var rect = aTarget.getBoundingClientRect();
var left = rect.left;
var top = rect.top;
var left = rect.left + aOffsetX;
var top = rect.top + aOffsetY;
// body's bounding client rect depends its scroll position.
if (aTarget.ownerDocument.body == aTarget) {
left += aTarget.scrollLeft;
top += aTarget.scrollTop;
}
var type = aEvent.type || "DOMMouseScroll";
var axis = aEvent.axis || "vertical";
@ -294,7 +307,7 @@ function synthesizeMouseScroll(aTarget, aOffsetX, aOffsetY, aEvent, aWindow)
if (aEvent.isMomentum) {
scrollFlags |= kIsMomentum;
}
utils.sendMouseScrollEvent(type, left + aOffsetX, top + aOffsetY, button,
utils.sendMouseScrollEvent(type, left, top, button,
scrollFlags, aEvent.delta, modifiers);
}
}