зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
4686066b93
Коммит
02f36526f8
|
@ -933,18 +933,6 @@ nsFrame::GetChildList(nsIAtom* aListName) const
|
||||||
return nsFrameList::EmptyList();
|
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
|
PRInt16
|
||||||
nsFrame::DisplaySelection(nsPresContext* aPresContext, PRBool isOkToTurnOn)
|
nsFrame::DisplaySelection(nsPresContext* aPresContext, PRBool isOkToTurnOn)
|
||||||
{
|
{
|
||||||
|
@ -2048,6 +2036,147 @@ nsFrame::IsSelectable(PRBool* aSelectable, PRUint8* aSelectStyle) const
|
||||||
return NS_OK;
|
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
|
* Handles the Mouse Press Event for the frame
|
||||||
*/
|
*/
|
||||||
|
@ -2094,49 +2223,52 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check whether style allows selection
|
nsFrameSelection* fs = GetFrameSelectionForSelectingByMouse();
|
||||||
// if not, don't tell selection the mouse event even occurred.
|
if (!fs) {
|
||||||
PRBool selectable;
|
return NS_OK; // maybe, select: none
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX This is screwy; it really should use the selection frame, not the
|
// If the mouse is dragged outside the selection root's scrollable area
|
||||||
// event frame
|
// while making a selection, the area will be scrolled. To do this, capture
|
||||||
const nsFrameSelection* frameselection = nsnull;
|
// the mouse on the selection root frame. However, in table selection mode,
|
||||||
if (useFrameSelection)
|
// a nearest scrollable frame should be captured the mouse because each
|
||||||
frameselection = GetConstFrameSelection();
|
// scrollable frame except the nearest one doesn't need to scroll during
|
||||||
else
|
// selection.
|
||||||
frameselection = shell->ConstFrameSelection();
|
|
||||||
|
|
||||||
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
|
return NS_OK;//nothing to do we cannot affect selection from here
|
||||||
|
}
|
||||||
|
|
||||||
nsMouseEvent *me = (nsMouseEvent *)aEvent;
|
nsMouseEvent *me = (nsMouseEvent *)aEvent;
|
||||||
|
|
||||||
|
@ -2148,13 +2280,12 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
|
||||||
PRBool control = me->isControl;
|
PRBool control = me->isControl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nsRefPtr<nsFrameSelection> fc = const_cast<nsFrameSelection*>(frameselection);
|
|
||||||
if (me->clickCount >1 )
|
if (me->clickCount >1 )
|
||||||
{
|
{
|
||||||
// These methods aren't const but can't actually delete anything,
|
// These methods aren't const but can't actually delete anything,
|
||||||
// so no need for nsWeakFrame.
|
// so no need for nsWeakFrame.
|
||||||
fc->SetMouseDownState(PR_TRUE);
|
fs->SetMouseDownState(PR_TRUE);
|
||||||
fc->SetMouseDoubleDown(PR_TRUE);
|
fs->SetMouseDoubleDown(PR_TRUE);
|
||||||
return HandleMultiplePress(aPresContext, aEvent, aEventStatus, control);
|
return HandleMultiplePress(aPresContext, aEvent, aEventStatus, control);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2168,14 +2299,24 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
|
||||||
nsCOMPtr<nsIContent>parentContent;
|
nsCOMPtr<nsIContent>parentContent;
|
||||||
PRInt32 contentOffset;
|
PRInt32 contentOffset;
|
||||||
PRInt32 target;
|
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)
|
if (NS_SUCCEEDED(rv) && parentContent)
|
||||||
{
|
{
|
||||||
fc->SetMouseDownState(PR_TRUE);
|
// In table selection mode, a nearest scrollable frame should capture the
|
||||||
return fc->HandleTableSelection(parentContent, contentOffset, target, me);
|
// 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
|
// Check if any part of this frame is selected, and if the
|
||||||
// user clicked inside the selected region. If so, we delay
|
// user clicked inside the selected region. If so, we delay
|
||||||
|
@ -2188,8 +2329,8 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
|
||||||
if (isSelected)
|
if (isSelected)
|
||||||
{
|
{
|
||||||
PRBool inSelection = PR_FALSE;
|
PRBool inSelection = PR_FALSE;
|
||||||
details = frameselection->LookUpSelection(offsets.content, 0,
|
details =
|
||||||
offsets.EndOffset(), PR_FALSE);
|
fs->LookUpSelection(offsets.content, 0, offsets.EndOffset(), PR_FALSE);
|
||||||
|
|
||||||
//
|
//
|
||||||
// If there are any details, check to see if the user clicked
|
// If there are any details, check to see if the user clicked
|
||||||
|
@ -2221,17 +2362,17 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inSelection) {
|
if (inSelection) {
|
||||||
fc->SetMouseDownState(PR_FALSE);
|
fs->SetMouseDownState(PR_FALSE);
|
||||||
fc->SetDelayedCaretData(me);
|
fs->SetDelayedCaretData(me);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fc->SetMouseDownState(PR_TRUE);
|
fs->SetMouseDownState(PR_TRUE);
|
||||||
|
|
||||||
// Do not touch any nsFrame members after this point without adding
|
// Do not touch any nsFrame members after this point without adding
|
||||||
// weakFrame checks.
|
// weakFrame checks.
|
||||||
rv = fc->HandleClick(offsets.content, offsets.StartOffset(),
|
rv = fs->HandleClick(offsets.content, offsets.StartOffset(),
|
||||||
offsets.EndOffset(), me->isShift, control,
|
offsets.EndOffset(), me->isShift, control,
|
||||||
offsets.associateWithNext);
|
offsets.associateWithNext);
|
||||||
|
|
||||||
|
@ -2239,7 +2380,7 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
if (offsets.offset != offsets.secondaryOffset)
|
if (offsets.offset != offsets.secondaryOffset)
|
||||||
fc->MaintainSelection();
|
fs->MaintainSelection();
|
||||||
|
|
||||||
if (isEditor && !me->isShift &&
|
if (isEditor && !me->isShift &&
|
||||||
(offsets.EndOffset() - offsets.StartOffset()) == 1)
|
(offsets.EndOffset() - offsets.StartOffset()) == 1)
|
||||||
|
@ -2249,7 +2390,7 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
|
||||||
// -moz-user-select: all or a non-text node without children).
|
// -moz-user-select: all or a non-text node without children).
|
||||||
// Therefore, disable selection extension during mouse moves.
|
// Therefore, disable selection extension during mouse moves.
|
||||||
// XXX This is a bit hacky; shouldn't editor be able to deal with this?
|
// 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;
|
return rv;
|
||||||
|
@ -2401,46 +2542,56 @@ nsFrame::PeekBackwardAndForward(nsSelectionAmount aAmountBack,
|
||||||
return frameSelection->MaintainSelection(aAmountBack);
|
return frameSelection->MaintainSelection(aAmountBack);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP nsFrame::HandleDrag(nsPresContext* aPresContext,
|
NS_IMETHODIMP
|
||||||
nsGUIEvent* aEvent,
|
nsFrame::HandleDrag(nsPresContext* aPresContext,
|
||||||
nsEventStatus* aEventStatus)
|
nsGUIEvent* aEvent,
|
||||||
|
nsEventStatus* aEventStatus)
|
||||||
{
|
{
|
||||||
PRBool selectable;
|
nsFrame* target;
|
||||||
PRUint8 selectStyle;
|
nsRefPtr<nsFrameSelection> fs =
|
||||||
IsSelectable(&selectable, &selectStyle);
|
FindDraggingFrameSelection(aPresContext->PresShell(), &target);
|
||||||
// XXX Do we really need to exclude non-selectable content here?
|
if (!fs || !target || IsSelectionOff()) {
|
||||||
// GetContentOffsetsFromPoint can handle it just fine, although some
|
return NS_OK; // not selecting now
|
||||||
// other stuff might not like it.
|
|
||||||
if (!selectable)
|
|
||||||
return NS_OK;
|
|
||||||
if (DisplaySelection(aPresContext) == nsISelectionController::SELECTION_OFF) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
nsIPresShell *presShell = aPresContext->PresShell();
|
|
||||||
|
|
||||||
nsRefPtr<nsFrameSelection> frameselection = GetFrameSelection();
|
// Stop auto scrolling, first.
|
||||||
PRBool mouseDown = frameselection->GetMouseDownState();
|
fs->StopAutoScrollTimer();
|
||||||
if (!mouseDown)
|
|
||||||
return NS_OK;
|
|
||||||
|
|
||||||
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
|
// Check if we are dragging in a table cell
|
||||||
nsCOMPtr<nsIContent> parentContent;
|
nsCOMPtr<nsIContent> parentContent;
|
||||||
PRInt32 contentOffset;
|
PRInt32 contentOffset;
|
||||||
PRInt32 target;
|
PRInt32 target;
|
||||||
nsMouseEvent *me = (nsMouseEvent *)aEvent;
|
nsresult rv = GetDataForTableSelection(aFrameSelection, aPresShell,
|
||||||
nsresult result;
|
aEvent, getter_AddRefs(parentContent),
|
||||||
result = GetDataForTableSelection(frameselection, presShell, me,
|
&contentOffset, &target);
|
||||||
getter_AddRefs(parentContent),
|
PRBool handleTableSelection = NS_SUCCEEDED(rv) && parentContent;
|
||||||
&contentOffset, &target);
|
|
||||||
|
|
||||||
nsWeakFrame weakThis = this;
|
nsWeakFrame weakThis = this;
|
||||||
if (NS_SUCCEEDED(result) && parentContent) {
|
if (handleTableSelection) {
|
||||||
frameselection->HandleTableSelection(parentContent, contentOffset, target, me);
|
aFrameSelection->HandleTableSelection(parentContent, contentOffset,
|
||||||
|
target, aEvent);
|
||||||
} else {
|
} else {
|
||||||
nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
|
nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
|
||||||
frameselection->HandleDrag(this, pt);
|
aFrameSelection->HandleDrag(this, pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The frameselection object notifies selection listeners synchronously above
|
// The frameselection object notifies selection listeners synchronously above
|
||||||
|
@ -2449,175 +2600,312 @@ NS_IMETHODIMP nsFrame::HandleDrag(nsPresContext* aPresContext,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the nearest scrollframe
|
nsIContent* capturingContent = nsIPresShell::GetCapturingContent();
|
||||||
nsIFrame* checkFrame = this;
|
if (!capturingContent) {
|
||||||
nsIScrollableFrame *scrollFrame = nsnull;
|
return NS_OK; // The capture was canceled.
|
||||||
while (checkFrame) {
|
|
||||||
scrollFrame = do_QueryFrame(checkFrame);
|
|
||||||
if (scrollFrame) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
checkFrame = checkFrame->GetParent();
|
|
||||||
}
|
}
|
||||||
|
nsIContent* selectionRoot =
|
||||||
|
GetSelectionRootContentForCapturingContent(aPresShell, capturingContent);
|
||||||
|
|
||||||
if (scrollFrame) {
|
nsIScrollableFrame* scrollableFrame =
|
||||||
nsIFrame* capturingFrame = scrollFrame->GetScrolledFrame();
|
FindNearestScrollableFrameForSelection(this, selectionRoot);
|
||||||
if (capturingFrame) {
|
// If a non-scrollable content captures by script, we may not be able to find
|
||||||
nsPoint pt =
|
// any scrollable frame.
|
||||||
nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, capturingFrame);
|
if (!scrollableFrame) {
|
||||||
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) {
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult rv = NS_OK;
|
const PRUint32 kAutoScrollTimerDelay = 30;
|
||||||
|
|
||||||
if (nsEventStatus_eConsumeNoDefault != *aEventStatus) {
|
if (!handleTableSelection) {
|
||||||
if (!aHandleTableSel) {
|
nsIScrollableFrame* selectionRootScrollableFrame =
|
||||||
nsMouseEvent *me = aFrameSelection->GetDelayedCaretData();
|
FindNearestScrollableFrameForSelection(selectionRoot->GetPrimaryFrame());
|
||||||
if (!aOffsets.content || !me) {
|
NS_ENSURE_TRUE(selectionRootScrollableFrame, NS_OK);
|
||||||
return NS_ERROR_FAILURE;
|
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.
|
nsPoint scrollTo;
|
||||||
// We didn't do it there to give the user an opportunity to drag
|
if (IsOnScrollableFrameEdge(scrollableFrame, aEvent, scrollTo)) {
|
||||||
// the text, but since they didn't drag, we want to place the
|
aFrameSelection->StartAutoScrollTimer(
|
||||||
// caret.
|
scrollableFrame->GetScrolledFrame(), scrollTo, kAutoScrollTimerDelay);
|
||||||
// However, we'll use the mouse position from the release, since:
|
return NS_OK;
|
||||||
// * 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);
|
|
||||||
|
|
||||||
rv = aFrameSelection->HandleClick(aOffsets.content,
|
nsIFrame* frame = do_QueryFrame(scrollableFrame);
|
||||||
aOffsets.StartOffset(),
|
scrollableFrame =
|
||||||
aOffsets.EndOffset(),
|
FindNearestScrollableFrameForSelection(frame->GetParent(),
|
||||||
me->isShift, PR_FALSE,
|
selectionRoot);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
aFrameSelection->SetDelayedCaretData(0);
|
scrollableFrame = selectionRootScrollableFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
aFrameSelection->SetMouseDownState(PR_FALSE);
|
if (!scrollableFrame) {
|
||||||
aFrameSelection->StopAutoScrollTimer();
|
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;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP nsFrame::HandleRelease(nsPresContext* aPresContext,
|
nsFrame*
|
||||||
nsGUIEvent* aEvent,
|
nsFrame::FindSelectableAncestor(nsIFrame* aFrame,
|
||||||
nsEventStatus* aEventStatus)
|
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();
|
nsCOMPtr<nsIContent> captureContent = nsIPresShell::GetCapturingContent();
|
||||||
|
|
||||||
// We can unconditionally stop capturing because
|
// We can unconditionally stop capturing because
|
||||||
// we should never be capturing when the mouse button is up
|
// we should never be capturing when the mouse button is up
|
||||||
nsIPresShell::SetCapturingContent(nsnull, 0);
|
nsIPresShell::SetCapturingContent(nsnull, 0);
|
||||||
|
|
||||||
PRBool selectionOff =
|
nsFrame* targetFrame;
|
||||||
(DisplaySelection(aPresContext) == nsISelectionController::SELECTION_OFF);
|
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;
|
nsCOMPtr<nsIContent> parentContent;
|
||||||
PRInt32 contentOffsetForTableSel = 0;
|
PRInt32 contentOffsetForTableSel = 0;
|
||||||
PRInt32 targetForTableSel = 0;
|
PRInt32 targetForTableSel = 0;
|
||||||
PRBool handleTableSelection = PR_TRUE;
|
GetDataForTableSelection(aFrameSelection, PresContext()->PresShell(),
|
||||||
|
aMouseEvent, getter_AddRefs(parentContent),
|
||||||
if (!selectionOff) {
|
&contentOffsetForTableSel, &targetForTableSel);
|
||||||
frameselection = GetFrameSelection();
|
if (parentContent) {
|
||||||
if (nsEventStatus_eConsumeNoDefault != *aEventStatus && frameselection) {
|
// XXX Do not call any methods of the current object after this point!!!
|
||||||
// Check if the frameselection recorded the mouse going down.
|
// The object is perhaps dead!
|
||||||
// If not, the user must have clicked in a part of the selection.
|
rv = aFrameSelection->HandleTableSelection(parentContent,
|
||||||
// Place the caret before continuing!
|
contentOffsetForTableSel,
|
||||||
|
targetForTableSel,
|
||||||
PRBool mouseDown = frameselection->GetMouseDownState();
|
aMouseEvent);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
aFrameSelection->SetDelayedCaretData(nsnull);
|
||||||
|
|
||||||
// We might be capturing in some other document and the event just happened to
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
// trickle down here. Make sure that document's frame selection is notified.
|
return NS_OK;
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Also check the selection of the capturing content which might be in a
|
PRBool
|
||||||
// different document.
|
nsFrame::IsSelectionOff()
|
||||||
if (!frameSelection && captureContent) {
|
{
|
||||||
nsIDocument* doc = captureContent->GetCurrentDoc();
|
nsRefPtr<nsFrameSelection> fs = GetFrameSelection();
|
||||||
if (doc) {
|
NS_ENSURE_TRUE(fs, PR_TRUE);
|
||||||
nsIPresShell* capturingShell = doc->GetShell();
|
return (fs->GetDisplaySelection() == nsISelectionController::SELECTION_OFF);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NS_STACK_CLASS FrameContentRange {
|
struct NS_STACK_CLASS FrameContentRange {
|
||||||
|
|
|
@ -599,6 +599,53 @@ protected:
|
||||||
nsIContent **aParentContent, PRInt32 *aContentOffset,
|
nsIContent **aParentContent, PRInt32 *aContentOffset,
|
||||||
PRInt32 *aTarget);
|
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
|
// Fills aCursor with the appropriate information from ui
|
||||||
static void FillCursorInformationFromStyle(const nsStyleUserInterface* ui,
|
static void FillCursorInformationFromStyle(const nsStyleUserInterface* ui,
|
||||||
nsIFrame::Cursor& aCursor);
|
nsIFrame::Cursor& aCursor);
|
||||||
|
|
|
@ -369,6 +369,15 @@ public:
|
||||||
*/
|
*/
|
||||||
PRBool GetMouseDownState() const { return mMouseDownState; }
|
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
|
if we are in table cell selection mode. aka ctrl click in table cell
|
||||||
*/
|
*/
|
||||||
|
@ -598,6 +607,7 @@ public:
|
||||||
|
|
||||||
|
|
||||||
nsFrameSelection();
|
nsFrameSelection();
|
||||||
|
virtual ~nsFrameSelection();
|
||||||
|
|
||||||
void StartBatchChanges();
|
void StartBatchChanges();
|
||||||
void EndBatchChanges();
|
void EndBatchChanges();
|
||||||
|
@ -696,6 +706,8 @@ private:
|
||||||
nsresult CreateAndAddRange(nsINode *aParentNode, PRInt32 aOffset);
|
nsresult CreateAndAddRange(nsINode *aParentNode, PRInt32 aOffset);
|
||||||
nsresult ClearNormalSelection();
|
nsresult ClearNormalSelection();
|
||||||
|
|
||||||
|
static nsFrameSelection* sDraggingFrameSelection;
|
||||||
|
|
||||||
nsCOMPtr<nsINode> mCellParent; //used to snap to table selection
|
nsCOMPtr<nsINode> mCellParent; //used to snap to table selection
|
||||||
nsCOMPtr<nsIContent> mStartSelectedCell;
|
nsCOMPtr<nsIContent> mStartSelectedCell;
|
||||||
nsCOMPtr<nsIContent> mEndSelectedCell;
|
nsCOMPtr<nsIContent> mEndSelectedCell;
|
||||||
|
|
|
@ -140,7 +140,7 @@ static void printRange(nsIRange *aDomRange);
|
||||||
#define DEBUG_OUT_RANGE(x)
|
#define DEBUG_OUT_RANGE(x)
|
||||||
#endif //MOZ_DEBUG
|
#endif //MOZ_DEBUG
|
||||||
|
|
||||||
|
nsFrameSelection* nsFrameSelection::sDraggingFrameSelection = nsnull;
|
||||||
|
|
||||||
//#define DEBUG_SELECTION // uncomment for printf describing every collapse and extend.
|
//#define DEBUG_SELECTION // uncomment for printf describing every collapse and extend.
|
||||||
//#define DEBUG_NAVIGATION
|
//#define DEBUG_NAVIGATION
|
||||||
|
@ -425,7 +425,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// aPoint is relative to aPresContext's root frame
|
// aPoint is relative to aPresContext's root frame
|
||||||
nsresult Start(nsPresContext *aPresContext, nsPoint &aPoint)
|
nsresult Start(nsPresContext *aPresContext, nsIContent *aContent,
|
||||||
|
nsPoint &aPoint)
|
||||||
{
|
{
|
||||||
mPoint = aPoint;
|
mPoint = aPoint;
|
||||||
|
|
||||||
|
@ -433,7 +434,7 @@ public:
|
||||||
// stopped by the selection if the prescontext is destroyed.
|
// stopped by the selection if the prescontext is destroyed.
|
||||||
mPresContext = aPresContext;
|
mPresContext = aPresContext;
|
||||||
|
|
||||||
mContent = nsIPresShell::GetCapturingContent();
|
mContent = aContent;
|
||||||
|
|
||||||
if (!mTimer)
|
if (!mTimer)
|
||||||
{
|
{
|
||||||
|
@ -747,6 +748,13 @@ nsFrameSelection::nsFrameSelection()
|
||||||
mSelectionChangeReason = nsISelectionListener::NO_REASON;
|
mSelectionChangeReason = nsISelectionListener::NO_REASON;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsFrameSelection::~nsFrameSelection()
|
||||||
|
{
|
||||||
|
if (this == sDraggingFrameSelection) {
|
||||||
|
sDraggingFrameSelection = nsnull;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsFrameSelection)
|
NS_IMPL_CYCLE_COLLECTION_CLASS(nsFrameSelection)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFrameSelection)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFrameSelection)
|
||||||
|
@ -916,41 +924,10 @@ nsFrameSelection::ConstrainFrameAndPointToAnchorSubtree(nsIFrame *aFrame,
|
||||||
|
|
||||||
if (anchorRoot == contentRoot)
|
if (anchorRoot == contentRoot)
|
||||||
{
|
{
|
||||||
// If the aFrame's content isn't the capturing content, it should be
|
// The anchor and aFrame's root are the same. There
|
||||||
// a descendant. At this time, we can return simply.
|
// is no need to constrain, simply return aFrame.
|
||||||
nsIContent* capturedContent = nsIPresShell::GetCapturingContent();
|
*aRetFrame = aFrame;
|
||||||
if (capturedContent != content)
|
return NS_OK;
|
||||||
{
|
|
||||||
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.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1943,10 +1920,16 @@ nsFrameSelection::SetMouseDownState(PRBool aState)
|
||||||
if (mMouseDownState == aState)
|
if (mMouseDownState == aState)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
NS_ASSERTION((aState && !sDraggingFrameSelection) ||
|
||||||
|
(!aState && sDraggingFrameSelection),
|
||||||
|
"Unexpected state happened");
|
||||||
|
|
||||||
mMouseDownState = aState;
|
mMouseDownState = aState;
|
||||||
|
|
||||||
if (!mMouseDownState)
|
if (mMouseDownState) {
|
||||||
{
|
sDraggingFrameSelection = this;
|
||||||
|
} else {
|
||||||
|
sDraggingFrameSelection = nsnull;
|
||||||
mDragSelectingCells = PR_FALSE;
|
mDragSelectingCells = PR_FALSE;
|
||||||
PostReason(nsISelectionListener::MOUSEUP_REASON);
|
PostReason(nsISelectionListener::MOUSEUP_REASON);
|
||||||
NotifySelectionListeners(nsISelectionController::SELECTION_NORMAL); //notify that reason is mouse up please.
|
NotifySelectionListeners(nsISelectionController::SELECTION_NORMAL); //notify that reason is mouse up please.
|
||||||
|
@ -4716,7 +4699,8 @@ nsTypedSelection::DoAutoScroll(nsIFrame *aFrame, nsPoint& aPoint)
|
||||||
{
|
{
|
||||||
nsPoint presContextPoint = globalPoint -
|
nsPoint presContextPoint = globalPoint -
|
||||||
presContext->PresShell()->FrameManager()->GetRootFrame()->GetOffsetToCrossDoc(rootmostFrame);
|
presContext->PresShell()->FrameManager()->GetRootFrame()->GetOffsetToCrossDoc(rootmostFrame);
|
||||||
mAutoScrollTimer->Start(presContext, presContextPoint);
|
mAutoScrollTimer->Start(presContext, aFrame->GetContent(),
|
||||||
|
presContextPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
|
@ -135,6 +135,8 @@ _CHROME_FILES = \
|
||||||
test_backspace_delete.xul \
|
test_backspace_delete.xul \
|
||||||
test_bug514732-2.xul \
|
test_bug514732-2.xul \
|
||||||
file_bug514732_window.xul \
|
file_bug514732_window.xul \
|
||||||
|
test_selection_scrolling.html \
|
||||||
|
window_selection_scrolling.html \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
libs:: $(_TEST_FILES)
|
libs:: $(_TEST_FILES)
|
||||||
|
|
|
@ -184,28 +184,21 @@ function test()
|
||||||
// selection starting at div1
|
// selection starting at div1
|
||||||
synthesizeMouse(div1, 30, 5, { type: "mousedown" });
|
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
|
// to iframe
|
||||||
synthesizeMouse(iframe, 30, 5, { type: "mousemove" });
|
synthesizeMouse(iframe, 30, 5, { type: "mousemove" });
|
||||||
check(kTrue | kToDo, kFalse, kFalse,
|
check(kTrue, kFalse, kFalse,
|
||||||
kFalse, kFalse, kFalse, kFalse, kFalse, kFalse,
|
kFalse, kFalse, kFalse, kFalse, kFalse, kFalse,
|
||||||
"div1-iframe, all boxes are overflow: " + kOverflows[i] + ";");
|
"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
|
// to input
|
||||||
synthesizeMouse(input, 30, 5, { type: "mousemove" });
|
synthesizeMouse(input, 30, 5, { type: "mousemove" });
|
||||||
check(kTrue | todoFlag, kTrue | todoFlag, kFalse,
|
check(kTrue, kTrue, kFalse,
|
||||||
kFalse, kFalse, kFalse, kFalse, kFalse, kFalse,
|
kFalse, kFalse, kFalse, kFalse, kFalse, kFalse,
|
||||||
"div1-input, all boxes are overflow: " + kOverflows[i] + ";");
|
"div1-input, all boxes are overflow: " + kOverflows[i] + ";");
|
||||||
|
|
||||||
// to textarea
|
// to textarea
|
||||||
synthesizeMouse(textarea, 30, 5, { type: "mousemove" });
|
synthesizeMouse(textarea, 30, 5, { type: "mousemove" });
|
||||||
check(kTrue | todoFlag, kTrue | todoFlag, kTrue | todoFlag,
|
check(kTrue, kTrue, kTrue,
|
||||||
kFalse, kFalse, kFalse, kFalse, kFalse, kFalse,
|
kFalse, kFalse, kFalse, kFalse, kFalse, kFalse,
|
||||||
"div1-textarea, all boxes are overflow: " + kOverflows[i] + ";");
|
"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()) {
|
if (!IsActivatedOnHover()) {
|
||||||
StopRepeat();
|
StopRepeat();
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return nsButtonBoxFrame::HandleRelease(aPresContext, aEvent, aEventStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
|
|
@ -82,11 +82,10 @@ nsScrollbarButtonFrame::HandleEvent(nsPresContext* aPresContext,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX hack until handle release is actually called in nsframe.
|
if (aEvent->message == NS_MOUSE_EXIT_SYNTH) {
|
||||||
if (aEvent->message == NS_MOUSE_EXIT_SYNTH ||
|
Deactivate();
|
||||||
aEvent->message == NS_MOUSE_BUTTON_UP)
|
}
|
||||||
HandleRelease(aPresContext, aEvent, aEventStatus);
|
|
||||||
|
|
||||||
// if we didn't handle the press ourselves, pass it on to the superclass
|
// if we didn't handle the press ourselves, pass it on to the superclass
|
||||||
if (!HandleButtonPress(aPresContext, aEvent, aEventStatus))
|
if (!HandleButtonPress(aPresContext, aEvent, aEventStatus))
|
||||||
return nsButtonBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
|
return nsButtonBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
|
||||||
|
@ -191,10 +190,15 @@ nsScrollbarButtonFrame::HandleRelease(nsPresContext* aPresContext,
|
||||||
nsGUIEvent* aEvent,
|
nsGUIEvent* aEvent,
|
||||||
nsEventStatus* aEventStatus)
|
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);
|
mContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::active, PR_TRUE);
|
||||||
StopRepeat();
|
StopRepeat();
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsScrollbarButtonFrame::Notify()
|
void nsScrollbarButtonFrame::Notify()
|
||||||
|
|
|
@ -81,10 +81,6 @@ public:
|
||||||
nsEventStatus* aEventStatus,
|
nsEventStatus* aEventStatus,
|
||||||
PRBool aControlHeld) { return NS_OK; }
|
PRBool aControlHeld) { return NS_OK; }
|
||||||
|
|
||||||
NS_IMETHOD HandleDrag(nsPresContext* aPresContext,
|
|
||||||
nsGUIEvent * aEvent,
|
|
||||||
nsEventStatus* aEventStatus) { return NS_OK; }
|
|
||||||
|
|
||||||
NS_IMETHOD HandleRelease(nsPresContext* aPresContext,
|
NS_IMETHOD HandleRelease(nsPresContext* aPresContext,
|
||||||
nsGUIEvent * aEvent,
|
nsGUIEvent * aEvent,
|
||||||
nsEventStatus* aEventStatus);
|
nsEventStatus* aEventStatus);
|
||||||
|
@ -105,6 +101,8 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
PRInt32 mIncrement;
|
PRInt32 mIncrement;
|
||||||
|
|
||||||
|
void Deactivate();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -158,22 +158,6 @@ nsScrollbarFrame::HandleMultiplePress(nsPresContext* aPresContext,
|
||||||
return NS_OK;
|
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
|
void
|
||||||
nsScrollbarFrame::SetScrollbarMediatorContent(nsIContent* aMediator)
|
nsScrollbarFrame::SetScrollbarMediatorContent(nsIContent* aMediator)
|
||||||
{
|
{
|
||||||
|
|
|
@ -78,14 +78,6 @@ public:
|
||||||
nsEventStatus* aEventStatus,
|
nsEventStatus* aEventStatus,
|
||||||
PRBool aControlHeld);
|
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,
|
NS_IMETHOD Init(nsIContent* aContent,
|
||||||
nsIFrame* aParent,
|
nsIFrame* aParent,
|
||||||
nsIFrame* aPrevInFlow);
|
nsIFrame* aPrevInFlow);
|
||||||
|
|
|
@ -1044,7 +1044,7 @@ nsSliderFrame::HandleRelease(nsPresContext* aPresContext,
|
||||||
{
|
{
|
||||||
StopRepeat();
|
StopRepeat();
|
||||||
|
|
||||||
return NS_OK;
|
return nsBoxFrame::HandleRelease(aPresContext, aEvent, aEventStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -148,10 +148,6 @@ public:
|
||||||
nsEventStatus* aEventStatus,
|
nsEventStatus* aEventStatus,
|
||||||
PRBool aControlHeld) { return NS_OK; }
|
PRBool aControlHeld) { return NS_OK; }
|
||||||
|
|
||||||
NS_IMETHOD HandleDrag(nsPresContext* aPresContext,
|
|
||||||
nsGUIEvent * aEvent,
|
|
||||||
nsEventStatus* aEventStatus) { return NS_OK; }
|
|
||||||
|
|
||||||
NS_IMETHOD HandleRelease(nsPresContext* aPresContext,
|
NS_IMETHOD HandleRelease(nsPresContext* aPresContext,
|
||||||
nsGUIEvent * aEvent,
|
nsGUIEvent * aEvent,
|
||||||
nsEventStatus* aEventStatus);
|
nsEventStatus* aEventStatus);
|
||||||
|
|
|
@ -379,22 +379,6 @@ nsSplitterFrame::HandleMultiplePress(nsPresContext* aPresContext,
|
||||||
return NS_OK;
|
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
|
NS_IMETHODIMP
|
||||||
nsSplitterFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
nsSplitterFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||||
const nsRect& aDirtyRect,
|
const nsRect& aDirtyRect,
|
||||||
|
|
|
@ -86,14 +86,6 @@ public:
|
||||||
nsEventStatus* aEventStatus,
|
nsEventStatus* aEventStatus,
|
||||||
PRBool aControlHeld);
|
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,
|
NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
|
||||||
nsGUIEvent* aEvent,
|
nsGUIEvent* aEvent,
|
||||||
nsEventStatus* aEventStatus);
|
nsEventStatus* aEventStatus);
|
||||||
|
|
|
@ -1293,6 +1293,17 @@ pref("layout.word_select.stop_at_punctuation", true);
|
||||||
// deletes the selection (Unix default)
|
// deletes the selection (Unix default)
|
||||||
pref("layout.selection.caret_style", 0);
|
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
|
// pref to control whether or not to replace backslashes with Yen signs
|
||||||
// in documents encoded in one of Japanese legacy encodings (EUC-JP,
|
// in documents encoded in one of Japanese legacy encodings (EUC-JP,
|
||||||
// Shift_JIS, ISO-2022-JP)
|
// Shift_JIS, ISO-2022-JP)
|
||||||
|
|
|
@ -220,6 +220,13 @@ function synthesizeMouse(aTarget, aOffsetX, aOffsetY, aEvent, aWindow)
|
||||||
var left = rect.left + aOffsetX;
|
var left = rect.left + aOffsetX;
|
||||||
var top = rect.top + aOffsetY;
|
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) {
|
if (aEvent.type) {
|
||||||
utils.sendMouseEvent(aEvent.type, left, top, button, clickCount, modifiers);
|
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 rect = aTarget.getBoundingClientRect();
|
||||||
|
|
||||||
var left = rect.left;
|
var left = rect.left + aOffsetX;
|
||||||
var top = rect.top;
|
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 type = aEvent.type || "DOMMouseScroll";
|
||||||
var axis = aEvent.axis || "vertical";
|
var axis = aEvent.axis || "vertical";
|
||||||
|
@ -294,7 +307,7 @@ function synthesizeMouseScroll(aTarget, aOffsetX, aOffsetY, aEvent, aWindow)
|
||||||
if (aEvent.isMomentum) {
|
if (aEvent.isMomentum) {
|
||||||
scrollFlags |= kIsMomentum;
|
scrollFlags |= kIsMomentum;
|
||||||
}
|
}
|
||||||
utils.sendMouseScrollEvent(type, left + aOffsetX, top + aOffsetY, button,
|
utils.sendMouseScrollEvent(type, left, top, button,
|
||||||
scrollFlags, aEvent.delta, modifiers);
|
scrollFlags, aEvent.delta, modifiers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче