зеркало из https://github.com/mozilla/gecko-dev.git
Bug 675865 backout new dragginf for selection handling code from Mozilla8 r=smaug (backed out patches are: bug 552707, bug 644621, bug 670058, bug 670508, bug 671319)
This commit is contained in:
Родитель
bc87676167
Коммит
bfc72b90bf
|
@ -6198,14 +6198,6 @@ PresShell::Paint(nsIView* aViewToPaint,
|
|||
void
|
||||
nsIPresShell::SetCapturingContent(nsIContent* aContent, PRUint8 aFlags)
|
||||
{
|
||||
// If SetCapturingContent() is called during dragging mouse for selection,
|
||||
// we should abort current transaction.
|
||||
nsRefPtr<nsFrameSelection> fs =
|
||||
nsFrameSelection::GetMouseDownFrameSelection();
|
||||
if (fs) {
|
||||
fs->AbortDragForSelection();
|
||||
}
|
||||
|
||||
NS_IF_RELEASE(gCaptureInfo.mContent);
|
||||
|
||||
// only set capturing content if allowed or the CAPTURE_IGNOREALLOWED flag
|
||||
|
|
|
@ -933,6 +933,18 @@ 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)
|
||||
{
|
||||
|
@ -2039,147 +2051,6 @@ 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
|
||||
*/
|
||||
|
@ -2189,8 +2060,6 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
|
|||
nsEventStatus* aEventStatus)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aEventStatus);
|
||||
NS_ASSERTION(aPresContext == PresContext(),
|
||||
"HandlePress called with different presContext");
|
||||
if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -2228,52 +2097,49 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
|
|||
}
|
||||
}
|
||||
|
||||
nsFrameSelection* fs = GetFrameSelectionForSelectingByMouse();
|
||||
if (!fs) {
|
||||
return NS_OK; // maybe, select: none
|
||||
}
|
||||
// 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;
|
||||
|
||||
// If the mouse is dragged outside the selection root's scrollable area
|
||||
// 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 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 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;
|
||||
// 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();
|
||||
}
|
||||
} else {
|
||||
nsIContent* contentToCaptureForSelection =
|
||||
GetContentToCaptureForSelection(selectionRootOfThisFrame);
|
||||
nsIPresShell::SetCapturingContent(contentToCaptureForSelection,
|
||||
CAPTURE_IGNOREALLOWED);
|
||||
}
|
||||
|
||||
if (fs->GetDisplaySelection() == nsISelectionController::SELECTION_OFF) {
|
||||
// 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 (!frameselection || frameselection->GetDisplaySelection() == nsISelectionController::SELECTION_OFF)
|
||||
return NS_OK;//nothing to do we cannot affect selection from here
|
||||
}
|
||||
|
||||
nsMouseEvent *me = (nsMouseEvent *)aEvent;
|
||||
|
||||
|
@ -2285,12 +2151,13 @@ 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.
|
||||
fs->SetMouseDownState(PR_TRUE);
|
||||
fs->SetMouseDoubleDown(PR_TRUE);
|
||||
fc->SetMouseDownState(PR_TRUE);
|
||||
fc->SetMouseDoubleDown(PR_TRUE);
|
||||
return HandleMultiplePress(aPresContext, aEvent, aEventStatus, control);
|
||||
}
|
||||
|
||||
|
@ -2304,33 +2171,14 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
|
|||
nsCOMPtr<nsIContent>parentContent;
|
||||
PRInt32 contentOffset;
|
||||
PRInt32 target;
|
||||
rv = GetDataForTableSelection(fs, shell, me, getter_AddRefs(parentContent),
|
||||
&contentOffset, &target);
|
||||
rv = GetDataForTableSelection(frameselection, shell, me, getter_AddRefs(parentContent), &contentOffset, &target);
|
||||
if (NS_SUCCEEDED(rv) && parentContent)
|
||||
{
|
||||
// In table selection mode, a nearest scrollable frame should capture the
|
||||
// mouse events.
|
||||
if (captureMouse) {
|
||||
// NOTE: we must have set a content to capture already. The content is
|
||||
// selection root of this frame. Therefore, when there is no scrollable
|
||||
// frame, we don't need to reset the capturing content.
|
||||
NS_ASSERTION(nsIPresShell::GetCapturingContent() != nsnull,
|
||||
"Someone must have captured mouse event already");
|
||||
nsIScrollableFrame* scrollableFrame =
|
||||
FindNearestScrollableFrameForSelection(this);
|
||||
if (scrollableFrame) {
|
||||
nsIFrame* frame = do_QueryFrame(scrollableFrame);
|
||||
nsIContent* contentToCaptureForTableSelection =
|
||||
GetContentToCaptureForSelection(frame->GetContent());
|
||||
nsIPresShell::SetCapturingContent(contentToCaptureForTableSelection,
|
||||
CAPTURE_IGNOREALLOWED);
|
||||
}
|
||||
}
|
||||
fs->SetMouseDownState(PR_TRUE);
|
||||
return fs->HandleTableSelection(parentContent, contentOffset, target, me);
|
||||
fc->SetMouseDownState(PR_TRUE);
|
||||
return fc->HandleTableSelection(parentContent, contentOffset, target, me);
|
||||
}
|
||||
|
||||
fs->SetDelayedCaretData(0);
|
||||
fc->SetDelayedCaretData(0);
|
||||
|
||||
// Check if any part of this frame is selected, and if the
|
||||
// user clicked inside the selected region. If so, we delay
|
||||
|
@ -2343,8 +2191,8 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
|
|||
if (isSelected)
|
||||
{
|
||||
PRBool inSelection = PR_FALSE;
|
||||
details =
|
||||
fs->LookUpSelection(offsets.content, 0, offsets.EndOffset(), PR_FALSE);
|
||||
details = frameselection->LookUpSelection(offsets.content, 0,
|
||||
offsets.EndOffset(), PR_FALSE);
|
||||
|
||||
//
|
||||
// If there are any details, check to see if the user clicked
|
||||
|
@ -2376,17 +2224,17 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
|
|||
}
|
||||
|
||||
if (inSelection) {
|
||||
fs->SetMouseDownState(PR_FALSE);
|
||||
fs->SetDelayedCaretData(me);
|
||||
fc->SetMouseDownState(PR_FALSE);
|
||||
fc->SetDelayedCaretData(me);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
fs->SetMouseDownState(PR_TRUE);
|
||||
fc->SetMouseDownState(PR_TRUE);
|
||||
|
||||
// Do not touch any nsFrame members after this point without adding
|
||||
// weakFrame checks.
|
||||
rv = fs->HandleClick(offsets.content, offsets.StartOffset(),
|
||||
rv = fc->HandleClick(offsets.content, offsets.StartOffset(),
|
||||
offsets.EndOffset(), me->isShift, control,
|
||||
offsets.associateWithNext);
|
||||
|
||||
|
@ -2394,7 +2242,7 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
|
|||
return rv;
|
||||
|
||||
if (offsets.offset != offsets.secondaryOffset)
|
||||
fs->MaintainSelection();
|
||||
fc->MaintainSelection();
|
||||
|
||||
if (isEditor && !me->isShift &&
|
||||
(offsets.EndOffset() - offsets.StartOffset()) == 1)
|
||||
|
@ -2404,7 +2252,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?
|
||||
fs->SetMouseDownState(PR_FALSE);
|
||||
fc->SetMouseDownState(PR_FALSE);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -2556,67 +2404,46 @@ 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)
|
||||
{
|
||||
nsFrame* target;
|
||||
nsRefPtr<nsFrameSelection> fs =
|
||||
FindDraggingFrameSelection(aPresContext->PresShell(), &target);
|
||||
if (!fs || !target || IsSelectionOff()) {
|
||||
return NS_OK; // not selecting now
|
||||
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;
|
||||
}
|
||||
nsIPresShell *presShell = aPresContext->PresShell();
|
||||
|
||||
NS_ASSERTION(target->PresContext()->PresShell() == fs->GetShell(),
|
||||
"A different presShell received mouse move event during drag");
|
||||
nsRefPtr<nsFrameSelection> frameselection = GetFrameSelection();
|
||||
PRBool mouseDown = frameselection->GetMouseDownState();
|
||||
if (!mouseDown)
|
||||
return NS_OK;
|
||||
|
||||
// Stop auto scrolling, first.
|
||||
fs->StopAutoScrollTimer();
|
||||
|
||||
return target->ExpandSelectionByMouseMove(fs, fs->GetShell(),
|
||||
static_cast<nsMouseEvent*>(aEvent),
|
||||
aEventStatus);
|
||||
}
|
||||
|
||||
static const char kPrefName_EdgeWidth[] =
|
||||
"layout.selection.drag.autoscroll.edge_width";
|
||||
static const char kPrefName_EdgeScrollAmount[] =
|
||||
"layout.selection.drag.autoscroll.edge_scroll_amount";
|
||||
|
||||
nsresult
|
||||
nsFrame::ExpandSelectionByMouseMove(nsFrameSelection* aFrameSelection,
|
||||
nsIPresShell* aPresShell,
|
||||
nsMouseEvent* aEvent,
|
||||
nsEventStatus* aEventStatus)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
nsFrameSelection* draggingFrameSelection =
|
||||
nsFrameSelection::GetMouseDownFrameSelection();
|
||||
nsFrameSelection* selectionFrameForSelectingByMouse =
|
||||
GetFrameSelectionForSelectingByMouse();
|
||||
NS_ASSERTION(draggingFrameSelection,
|
||||
"dragging FrameSelection must not be NULL");
|
||||
NS_ASSERTION(draggingFrameSelection == selectionFrameForSelectingByMouse,
|
||||
"aFrameSelection must be handling current drag for selection");
|
||||
#endif
|
||||
frameselection->StopAutoScrollTimer();
|
||||
|
||||
// Check if we are dragging in a table cell
|
||||
nsCOMPtr<nsIContent> parentContent;
|
||||
PRInt32 contentOffset;
|
||||
PRInt32 target;
|
||||
nsresult rv = GetDataForTableSelection(aFrameSelection, aPresShell,
|
||||
aEvent, getter_AddRefs(parentContent),
|
||||
&contentOffset, &target);
|
||||
PRBool handleTableSelection = NS_SUCCEEDED(rv) && parentContent;
|
||||
nsMouseEvent *me = (nsMouseEvent *)aEvent;
|
||||
nsresult result;
|
||||
result = GetDataForTableSelection(frameselection, presShell, me,
|
||||
getter_AddRefs(parentContent),
|
||||
&contentOffset, &target);
|
||||
|
||||
nsWeakFrame weakThis = this;
|
||||
if (handleTableSelection) {
|
||||
aFrameSelection->HandleTableSelection(parentContent, contentOffset,
|
||||
target, aEvent);
|
||||
if (NS_SUCCEEDED(result) && parentContent) {
|
||||
frameselection->HandleTableSelection(parentContent, contentOffset, target, me);
|
||||
} else {
|
||||
nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
|
||||
aFrameSelection->HandleDrag(this, pt);
|
||||
frameselection->HandleDrag(this, pt);
|
||||
}
|
||||
|
||||
// The frameselection object notifies selection listeners synchronously above
|
||||
|
@ -2625,332 +2452,175 @@ nsFrame::ExpandSelectionByMouseMove(nsFrameSelection* aFrameSelection,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIContent* capturingContent = nsIPresShell::GetCapturingContent();
|
||||
if (!capturingContent) {
|
||||
return NS_OK; // The capture was canceled.
|
||||
}
|
||||
nsIContent* selectionRoot =
|
||||
GetSelectionRootContentForCapturingContent(aPresShell, capturingContent);
|
||||
|
||||
nsIScrollableFrame* scrollableFrame =
|
||||
FindNearestScrollableFrameForSelection(this, selectionRoot);
|
||||
// If a non-scrollable content captures by script and there is no scrollable
|
||||
// frame between the selection root and this, we don't need to do anymore.
|
||||
if (!scrollableFrame) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
const PRUint32 kAutoScrollTimerDelay = 30;
|
||||
|
||||
if (!handleTableSelection) {
|
||||
nsIScrollableFrame* selectionRootScrollableFrame =
|
||||
FindNearestScrollableFrameForSelection(selectionRoot->GetPrimaryFrame(),
|
||||
selectionRoot);
|
||||
while (scrollableFrame) {
|
||||
nsPoint scrollTo;
|
||||
if (IsOnScrollableFrameEdge(scrollableFrame, aEvent, scrollTo)) {
|
||||
aFrameSelection->StartAutoScrollTimer(
|
||||
scrollableFrame->GetScrolledFrame(), scrollTo, kAutoScrollTimerDelay);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIFrame* frame = do_QueryFrame(scrollableFrame);
|
||||
scrollableFrame =
|
||||
FindNearestScrollableFrameForSelection(frame->GetParent(),
|
||||
selectionRoot);
|
||||
// get the nearest scrollframe
|
||||
nsIFrame* checkFrame = this;
|
||||
nsIScrollableFrame *scrollFrame = nsnull;
|
||||
while (checkFrame) {
|
||||
scrollFrame = do_QueryFrame(checkFrame);
|
||||
if (scrollFrame) {
|
||||
break;
|
||||
}
|
||||
scrollableFrame = selectionRootScrollableFrame;
|
||||
checkFrame = checkFrame->GetParent();
|
||||
}
|
||||
|
||||
if (!scrollableFrame) {
|
||||
return NS_OK;
|
||||
if (scrollFrame) {
|
||||
nsIFrame* capturingFrame = scrollFrame->GetScrolledFrame();
|
||||
if (capturingFrame) {
|
||||
nsPoint pt =
|
||||
nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, capturingFrame);
|
||||
frameselection->StartAutoScrollTimer(capturingFrame, pt, 30);
|
||||
}
|
||||
}
|
||||
|
||||
nsIFrame* scrolledFrame = scrollableFrame->GetScrolledFrame();
|
||||
NS_ASSERTION(scrolledFrame,
|
||||
"The found scrollable frame doesn't have scrolled frame");
|
||||
nsPoint scrollTo =
|
||||
nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, scrolledFrame);
|
||||
|
||||
// We should set minimum scroll speed same as the on-edge scrolling speed.
|
||||
// E.g., while mouse cursor is on the edge, scrolling speed is always same.
|
||||
nsPoint currentScrollPos = scrollableFrame->GetScrollPosition();
|
||||
nsRect visibleRectOfScrolledFrame = scrollableFrame->GetScrollPortRect();
|
||||
visibleRectOfScrolledFrame.MoveTo(currentScrollPos);
|
||||
if (visibleRectOfScrolledFrame.Contains(scrollTo)) {
|
||||
return NS_OK; // scroll wouldn't happen actually
|
||||
}
|
||||
PRInt32 minAmountPixel =
|
||||
NS_MAX(Preferences::GetInt(kPrefName_EdgeScrollAmount), 1);
|
||||
nscoord minAmountApp = PresContext()->DevPixelsToAppUnits(minAmountPixel);
|
||||
if (visibleRectOfScrolledFrame.x > scrollTo.x) {
|
||||
scrollTo.x =
|
||||
NS_MIN(visibleRectOfScrolledFrame.x - minAmountApp, scrollTo.x);
|
||||
} else if (visibleRectOfScrolledFrame.XMost() < scrollTo.x) {
|
||||
scrollTo.x =
|
||||
NS_MAX(visibleRectOfScrolledFrame.XMost() + minAmountApp, scrollTo.x);
|
||||
}
|
||||
if (visibleRectOfScrolledFrame.y > scrollTo.y) {
|
||||
scrollTo.y =
|
||||
NS_MIN(visibleRectOfScrolledFrame.y - minAmountApp, scrollTo.y);
|
||||
} else if (visibleRectOfScrolledFrame.YMost() < scrollTo.y) {
|
||||
scrollTo.y =
|
||||
NS_MAX(visibleRectOfScrolledFrame.YMost() + minAmountApp, scrollTo.y);
|
||||
}
|
||||
|
||||
aFrameSelection->StartAutoScrollTimer(scrolledFrame, scrollTo,
|
||||
kAutoScrollTimerDelay);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsFrame*
|
||||
nsFrame::FindSelectableAncestor(nsIFrame* aFrame,
|
||||
nsFrameSelection* aFrameSelection)
|
||||
/**
|
||||
* 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 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;
|
||||
if (!aFrameSelection) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (nsEventStatus_eConsumeNoDefault != *aEventStatus) {
|
||||
if (!aHandleTableSel) {
|
||||
nsMouseEvent *me = aFrameSelection->GetDelayedCaretData();
|
||||
if (!aOffsets.content || !me) {
|
||||
return 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);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
nsRect scrollableFrameRect(scrollableFrame->GetRect());
|
||||
scrollableFrameRect.MoveTo(0, 0);
|
||||
if (!scrollableFrameRect.Contains(ptInScrollableFrame)) {
|
||||
return PR_FALSE; // cursor is outside of the frame.
|
||||
}
|
||||
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.
|
||||
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.
|
||||
PRInt32 scrollAmountPixel =
|
||||
NS_MAX(Preferences::GetInt(kPrefName_EdgeScrollAmount), 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;
|
||||
}
|
||||
aFrameSelection->SetDelayedCaretData(0);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// NOTE: You don't need to release mouse capture here. It'll be done
|
||||
// in PresShell automatically. If you need to do it here, you must
|
||||
// do it after nsFrame::EndSelectionChangeByMouse() because we need
|
||||
// to call nsFrameSelection::SetMouseDownState(PR_FALSE) first.
|
||||
// If we release mouse event capture first, it doesn't cause
|
||||
// MOUSEUP_REASON selection change event.
|
||||
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;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> parentContent;
|
||||
PRInt32 contentOffsetForTableSel = 0;
|
||||
PRInt32 targetForTableSel = 0;
|
||||
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);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsFrame::IsSelectionOff()
|
||||
NS_IMETHODIMP nsFrame::HandleRelease(nsPresContext* aPresContext,
|
||||
nsGUIEvent* aEvent,
|
||||
nsEventStatus* aEventStatus)
|
||||
{
|
||||
nsRefPtr<nsFrameSelection> fs = GetFrameSelection();
|
||||
NS_ENSURE_TRUE(fs, PR_TRUE);
|
||||
return (fs->GetDisplaySelection() == nsISelectionController::SELECTION_OFF);
|
||||
nsIFrame* activeFrame = GetActiveSelectionFrame(aPresContext, this);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
struct NS_STACK_CLASS FrameContentRange {
|
||||
|
|
|
@ -599,53 +599,6 @@ 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,20 +369,6 @@ public:
|
|||
*/
|
||||
PRBool GetMouseDownState() const { return mMouseDownState; }
|
||||
|
||||
/**
|
||||
* GetMouseDownedFrameSelection returns an instance which is handling
|
||||
* mouse dragging.
|
||||
*/
|
||||
static nsFrameSelection* GetMouseDownFrameSelection()
|
||||
{
|
||||
return sDraggingFrameSelection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call AbortDragForSelection() when we abort handling the drag as selecting.
|
||||
*/
|
||||
void AbortDragForSelection();
|
||||
|
||||
/**
|
||||
if we are in table cell selection mode. aka ctrl click in table cell
|
||||
*/
|
||||
|
@ -612,7 +598,6 @@ public:
|
|||
|
||||
|
||||
nsFrameSelection();
|
||||
virtual ~nsFrameSelection();
|
||||
|
||||
void StartBatchChanges();
|
||||
void EndBatchChanges();
|
||||
|
@ -621,11 +606,7 @@ public:
|
|||
|
||||
nsIPresShell *GetShell()const { return mShell; }
|
||||
|
||||
void DisconnectFromPresShell()
|
||||
{
|
||||
AbortDragForSelection();
|
||||
mShell = nsnull;
|
||||
}
|
||||
void DisconnectFromPresShell() { StopAutoScrollTimer(); mShell = nsnull; }
|
||||
private:
|
||||
nsresult TakeFocus(nsIContent *aNewFocus,
|
||||
PRUint32 aContentOffset,
|
||||
|
@ -715,8 +696,6 @@ 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;
|
||||
|
|
|
@ -141,7 +141,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
|
||||
|
@ -426,8 +426,7 @@ public:
|
|||
}
|
||||
|
||||
// aPoint is relative to aPresContext's root frame
|
||||
nsresult Start(nsPresContext *aPresContext, nsIContent *aContent,
|
||||
nsPoint &aPoint)
|
||||
nsresult Start(nsPresContext *aPresContext, nsPoint &aPoint)
|
||||
{
|
||||
mPoint = aPoint;
|
||||
|
||||
|
@ -435,7 +434,7 @@ public:
|
|||
// stopped by the selection if the prescontext is destroyed.
|
||||
mPresContext = aPresContext;
|
||||
|
||||
mContent = aContent;
|
||||
mContent = nsIPresShell::GetCapturingContent();
|
||||
|
||||
if (!mTimer)
|
||||
{
|
||||
|
@ -749,13 +748,6 @@ 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)
|
||||
|
@ -925,10 +917,41 @@ nsFrameSelection::ConstrainFrameAndPointToAnchorSubtree(nsIFrame *aFrame,
|
|||
|
||||
if (anchorRoot == contentRoot)
|
||||
{
|
||||
// The anchor and aFrame's root are the same. There
|
||||
// is no need to constrain, simply return aFrame.
|
||||
*aRetFrame = aFrame;
|
||||
return NS_OK;
|
||||
// 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.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1921,40 +1944,16 @@ nsFrameSelection::SetMouseDownState(PRBool aState)
|
|||
if (mMouseDownState == aState)
|
||||
return;
|
||||
|
||||
NS_ASSERTION((aState && !sDraggingFrameSelection) ||
|
||||
(!aState && sDraggingFrameSelection),
|
||||
"Unexpected state happened");
|
||||
|
||||
mMouseDownState = aState;
|
||||
|
||||
if (mMouseDownState) {
|
||||
if (sDraggingFrameSelection) {
|
||||
sDraggingFrameSelection->AbortDragForSelection();
|
||||
}
|
||||
sDraggingFrameSelection = this;
|
||||
} else {
|
||||
if (sDraggingFrameSelection == this) {
|
||||
sDraggingFrameSelection = nsnull;
|
||||
}
|
||||
|
||||
if (!mMouseDownState)
|
||||
{
|
||||
mDragSelectingCells = PR_FALSE;
|
||||
PostReason(nsISelectionListener::MOUSEUP_REASON);
|
||||
NotifySelectionListeners(nsISelectionController::SELECTION_NORMAL); //notify that reason is mouse up please.
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameSelection::AbortDragForSelection()
|
||||
{
|
||||
if (sDraggingFrameSelection == this) {
|
||||
sDraggingFrameSelection = nsnull;
|
||||
mMouseDownState = PR_FALSE;
|
||||
mDragSelectingCells = PR_FALSE;
|
||||
PostReason(nsISelectionListener::NO_REASON);
|
||||
NotifySelectionListeners(nsISelectionController::SELECTION_NORMAL);
|
||||
}
|
||||
StopAutoScrollTimer();
|
||||
}
|
||||
|
||||
nsISelection*
|
||||
nsFrameSelection::GetSelection(SelectionType aType) const
|
||||
{
|
||||
|
@ -4718,8 +4717,7 @@ nsTypedSelection::DoAutoScroll(nsIFrame *aFrame, nsPoint& aPoint)
|
|||
{
|
||||
nsPoint presContextPoint = globalPoint -
|
||||
presContext->PresShell()->FrameManager()->GetRootFrame()->GetOffsetToCrossDoc(rootmostFrame);
|
||||
mAutoScrollTimer->Start(presContext, aFrame->GetContent(),
|
||||
presContextPoint);
|
||||
mAutoScrollTimer->Start(presContext, presContextPoint);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -135,12 +135,6 @@ _CHROME_FILES = \
|
|||
test_backspace_delete.xul \
|
||||
test_bug514732-2.xul \
|
||||
file_bug514732_window.xul \
|
||||
test_selection_scrolling.html \
|
||||
window_selection_scrolling.html \
|
||||
test_bug670058.html \
|
||||
test_bug670508.html \
|
||||
test_bug671319.html \
|
||||
test_bug673315-1.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
<!DOCTYPE>
|
||||
<html>
|
||||
<head>
|
||||
<title>test for bug 670058</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>
|
||||
<script type="text/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<textarea id="textarea" style="width: 200px; height: 100px;"></textarea>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var textarea = document.getElementById('textarea');
|
||||
|
||||
var x = 50;
|
||||
var y = 50;
|
||||
|
||||
var timer = 0;
|
||||
|
||||
function doTest() {
|
||||
synthesizeMouse(textarea, x, y, { type: "mousedown" });
|
||||
|
||||
timer = setInterval(function()
|
||||
{
|
||||
if (textarea.style.display == 'block') {
|
||||
synthesizeMouse(textarea, x++, y++, { type: "mousemove" });
|
||||
textarea.style.display = '';
|
||||
} else {
|
||||
textarea.style.display = 'block';
|
||||
synthesizeMouse(textarea, x++, y++, { type: "mousemove" });
|
||||
}
|
||||
if (x == 70) {
|
||||
ok(true, "not crashed");
|
||||
clearInterval(timer);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}, 200);
|
||||
}
|
||||
|
||||
SimpleTest.waitForFocus(doTest, window);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1,37 +0,0 @@
|
|||
<!DOCTYPE>
|
||||
<html>
|
||||
<head>
|
||||
<title>test for bug 670508</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>
|
||||
<script type="text/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td id="td" contenteditable="true">
|
||||
here is an editable table cell
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function doTest() {
|
||||
synthesizeMouse(document.getElementById('td'), 5, 5, { ctrlKey: true });
|
||||
ok(true, "not crashed");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForFocus(doTest, window);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1,55 +0,0 @@
|
|||
<!DOCTYPE>
|
||||
<html>
|
||||
<head>
|
||||
<title>test for bug 671319</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>
|
||||
<script type="text/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<iframe id="iframe1"
|
||||
src="data:text/html,<input id='childInput' style='width: 100px; height: 20px;'>"
|
||||
style="margin: 10px; width: 150px; height: 40px;"></iframe><br>
|
||||
<iframe id="iframe2"
|
||||
src="data:text/html,<input id='childInput' style='width: 100px; height: 20px;'>"
|
||||
style="margin: 10px; width: 150px; height: 40px;"></iframe>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function doTest() {
|
||||
var iframe1 = document.getElementById("iframe1");
|
||||
var childInput1 = iframe1.contentDocument.getElementById("childInput");
|
||||
var childWindow1 = iframe1.contentWindow;
|
||||
|
||||
var iframe2 = document.getElementById("iframe2");
|
||||
var childInput2 = iframe2.contentDocument.getElementById("childInput");
|
||||
childInput2.onmousedown = function (aEvent) {
|
||||
aEvent.preventDefault();
|
||||
};
|
||||
childInput2.onmousemove = function (aEvent) {
|
||||
childInput2.setCapture();
|
||||
};
|
||||
var childWindow2 = iframe2.contentWindow;
|
||||
|
||||
synthesizeMouse(childInput1, 10, 10, { type: "mousedown", button: 0 }, childWindow1);
|
||||
iframe1.contentDocument.releaseCapture();
|
||||
synthesizeMouse(childInput2, 10, 10, { type: "mousedown", button: 0 }, childWindow2);
|
||||
synthesizeMouse(childInput2, 20, 10, { type: "mousemove" }, childWindow2);
|
||||
|
||||
ok(true, "not crashed");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForFocus(doTest, window);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1,64 +0,0 @@
|
|||
<!DOCTYPE>
|
||||
<html>
|
||||
<head>
|
||||
<title>test for bug 673315 part.1</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>
|
||||
<script type="text/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="p">aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</p>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var gSelectionListener = {
|
||||
reason: 0,
|
||||
reset: function () { this.reason = 0; },
|
||||
notifySelectionChanged: function (doc, sel, reason)
|
||||
{
|
||||
this.reason |= reason;
|
||||
}
|
||||
}
|
||||
|
||||
function doTest() {
|
||||
var p = document.getElementById("p");
|
||||
|
||||
const nsISelectionPrivate = Components.interfaces.nsISelectionPrivate;
|
||||
const nsISelectionListener = Components.interfaces.nsISelectionListener;
|
||||
var selPrivate =
|
||||
window.getSelection().QueryInterface(nsISelectionPrivate);
|
||||
selPrivate.addSelectionListener(gSelectionListener);
|
||||
|
||||
gSelectionListener.reset();
|
||||
synthesizeMouse(p, 10, 10, { type: "mousedown", button: 0 });
|
||||
is(gSelectionListener.reason,
|
||||
nsISelectionListener.DRAG_REASON | nsISelectionListener.MOUSEDOWN_REASON,
|
||||
"the reason isn't drag and mosuedown after mousedown event");
|
||||
gSelectionListener.reset();
|
||||
synthesizeMouse(p, 10, 50, { type: "mousemove" });
|
||||
is(gSelectionListener.reason,
|
||||
nsISelectionListener.DRAG_REASON | nsISelectionListener.MOUSEDOWN_REASON,
|
||||
"the reason isn't drag and mosuedown after mousemove event");
|
||||
gSelectionListener.reset();
|
||||
synthesizeMouse(p, 10, 50, { type: "mouseup", button: 0 });
|
||||
is(gSelectionListener.reason,
|
||||
nsISelectionListener.MOUSEUP_REASON,
|
||||
"the reason isn't mosueup after mouseup event");
|
||||
|
||||
selPrivate.addSelectionListener(gSelectionListener);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForFocus(doTest, window);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -184,21 +184,28 @@ 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, kFalse, kFalse,
|
||||
check(kTrue | kToDo, 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, kTrue, kFalse,
|
||||
check(kTrue | todoFlag, kTrue | todoFlag, 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, kTrue, kTrue,
|
||||
check(kTrue | todoFlag, kTrue | todoFlag, kTrue | todoFlag,
|
||||
kFalse, kFalse, kFalse, kFalse, kFalse, kFalse,
|
||||
"div1-textarea, all boxes are overflow: " + kOverflows[i] + ";");
|
||||
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
<!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=100,left=100,width=500,height=500,scrollbars=yes");
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -169,7 +169,7 @@ nsAutoRepeatBoxFrame::HandleRelease(nsPresContext* aPresContext,
|
|||
if (!IsActivatedOnHover()) {
|
||||
StopRepeat();
|
||||
}
|
||||
return nsButtonBoxFrame::HandleRelease(aPresContext, aEvent, aEventStatus);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -82,10 +82,11 @@ nsScrollbarButtonFrame::HandleEvent(nsPresContext* aPresContext,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aEvent->message == NS_MOUSE_EXIT_SYNTH) {
|
||||
Deactivate();
|
||||
}
|
||||
|
||||
// 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 we didn't handle the press ourselves, pass it on to the superclass
|
||||
if (!HandleButtonPress(aPresContext, aEvent, aEventStatus))
|
||||
return nsButtonBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
|
||||
|
@ -190,15 +191,10 @@ nsScrollbarButtonFrame::HandleRelease(nsPresContext* aPresContext,
|
|||
nsGUIEvent* aEvent,
|
||||
nsEventStatus* aEventStatus)
|
||||
{
|
||||
Deactivate();
|
||||
return nsButtonBoxFrame::HandleRelease(aPresContext, aEvent, aEventStatus);
|
||||
}
|
||||
|
||||
void
|
||||
nsScrollbarButtonFrame::Deactivate()
|
||||
{
|
||||
// we're not active anymore
|
||||
mContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::active, PR_TRUE);
|
||||
StopRepeat();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsScrollbarButtonFrame::Notify()
|
||||
|
|
|
@ -81,6 +81,10 @@ 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);
|
||||
|
@ -101,8 +105,6 @@ protected:
|
|||
}
|
||||
|
||||
PRInt32 mIncrement;
|
||||
|
||||
void Deactivate();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -154,6 +154,22 @@ 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)
|
||||
{
|
||||
|
|
|
@ -79,6 +79,14 @@ 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);
|
||||
|
|
|
@ -587,19 +587,8 @@ nsSliderFrame::HandleEvent(nsPresContext* aPresContext,
|
|||
// if (aEvent->message == NS_MOUSE_EXIT_SYNTH || aEvent->message == NS_MOUSE_RIGHT_BUTTON_UP || aEvent->message == NS_MOUSE_LEFT_BUTTON_UP)
|
||||
// HandleRelease(aPresContext, aEvent, aEventStatus);
|
||||
|
||||
if (aEvent->message == NS_MOUSE_EXIT_SYNTH && mChange) {
|
||||
// XXX This is wrong behavior. We shouldn't stop handling dragging by
|
||||
// mouseexit event.
|
||||
// On Windows, can continue to change the value when mouse cursor is
|
||||
// moved back to the slider button.
|
||||
// On Linux (GTK), even if the mouse cursor existed from slider button,
|
||||
// kept to change the value. (confirmed on Ubuntu 10.10)
|
||||
// On Mac, like Windows, when mouse cursor is moved back to the button,
|
||||
// restart to change the value. However, Mac's slider can use the other
|
||||
// direction button too.
|
||||
HandleRelease(aPresContext, aEvent, aEventStatus);
|
||||
nsIPresShell::SetCapturingContent(nsnull, 0);
|
||||
}
|
||||
if (aEvent->message == NS_MOUSE_EXIT_SYNTH && mChange)
|
||||
HandleRelease(aPresContext, aEvent, aEventStatus);
|
||||
|
||||
return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
|
||||
}
|
||||
|
@ -1055,7 +1044,7 @@ nsSliderFrame::HandleRelease(nsPresContext* aPresContext,
|
|||
{
|
||||
StopRepeat();
|
||||
|
||||
return nsBoxFrame::HandleRelease(aPresContext, aEvent, aEventStatus);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -148,6 +148,10 @@ 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);
|
||||
|
|
|
@ -380,6 +380,22 @@ 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,6 +86,14 @@ 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);
|
||||
|
|
|
@ -1353,20 +1353,6 @@ 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
|
||||
// scrollable frame which is a selection root or its descendant, the frame will
|
||||
// be scrolled.
|
||||
// |.edge_width| defines the edge width by device pixels.
|
||||
// |.edge_scroll_amount| defines the scrolling speed by device pixels.
|
||||
// The auto scroll implementation uses this value for scrolling-to computation.
|
||||
// When the mouse cursor is on the edge, it tries to scroll the frame to
|
||||
// this pixels away from the edge.
|
||||
// I.e., larger value makes faster scroll.
|
||||
// And also this value is used for the minimum scrolling speed when mouse cursor
|
||||
// is outside of the selection root element.
|
||||
pref("layout.selection.drag.autoscroll.edge_width", 32);
|
||||
pref("layout.selection.drag.autoscroll.edge_scroll_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,13 +220,6 @@ 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);
|
||||
}
|
||||
|
@ -289,14 +282,8 @@ function synthesizeMouseScroll(aTarget, aOffsetX, aOffsetY, aEvent, aWindow)
|
|||
|
||||
var rect = aTarget.getBoundingClientRect();
|
||||
|
||||
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 left = rect.left;
|
||||
var top = rect.top;
|
||||
|
||||
var type = aEvent.type || "DOMMouseScroll";
|
||||
var axis = aEvent.axis || "vertical";
|
||||
|
@ -307,7 +294,7 @@ function synthesizeMouseScroll(aTarget, aOffsetX, aOffsetY, aEvent, aWindow)
|
|||
if (aEvent.isMomentum) {
|
||||
scrollFlags |= kIsMomentum;
|
||||
}
|
||||
utils.sendMouseScrollEvent(type, left, top, button,
|
||||
utils.sendMouseScrollEvent(type, left + aOffsetX, top + aOffsetY, button,
|
||||
scrollFlags, aEvent.delta, modifiers);
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче