зеркало из https://github.com/mozilla/gecko-dev.git
Bug 516615, when capturing, check if the target frame's content is a descendant of the capturing content, rather than using the frame tree, r=roc,sr=smaug
This commit is contained in:
Родитель
03f6ef64f9
Коммит
9dcaa2e4e5
|
@ -6000,6 +6000,9 @@ PresShell::HandleEvent(nsIView *aView,
|
|||
}
|
||||
#endif
|
||||
|
||||
nsIContent* capturingContent =
|
||||
NS_IS_MOUSE_EVENT(aEvent) ? GetCapturingContent() : nsnull;
|
||||
|
||||
nsCOMPtr<nsIDocument> retargetEventDoc;
|
||||
// key and IME events must be targeted at the presshell for the focused frame
|
||||
if (!sDontRetargetEvents) {
|
||||
|
@ -6020,10 +6023,10 @@ PresShell::HandleEvent(nsIView *aView,
|
|||
retargetEventDoc = do_QueryInterface(piWindow->GetExtantDocument());
|
||||
if (!retargetEventDoc)
|
||||
return NS_OK;
|
||||
} else if (NS_IS_MOUSE_EVENT(aEvent) && GetCapturingContent()) {
|
||||
} else if (capturingContent) {
|
||||
// if the mouse is being captured then retarget the mouse event at the
|
||||
// document that is being captured.
|
||||
retargetEventDoc = gCaptureInfo.mContent->GetCurrentDoc();
|
||||
retargetEventDoc = capturingContent->GetCurrentDoc();
|
||||
}
|
||||
|
||||
if (retargetEventDoc) {
|
||||
|
@ -6093,43 +6096,7 @@ PresShell::HandleEvent(nsIView *aView,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool getDescendantPoint = PR_TRUE;
|
||||
nsIFrame* frame = static_cast<nsIFrame*>(aView->GetClientData());
|
||||
|
||||
if (NS_IS_MOUSE_EVENT(aEvent) && GetCapturingContent()) {
|
||||
// if a node is capturing the mouse, get the frame for the capturing
|
||||
// content and use that instead. However, if the content has no parent,
|
||||
// such as the root frame, get the parent canvas frame instead. This
|
||||
// ensures that positioned frames are included when hit-testing. Note
|
||||
// that a check was already done above to ensure that capturingContent
|
||||
// is in this presshell.
|
||||
nsIContent* capturingContent = gCaptureInfo.mContent;
|
||||
frame = GetPrimaryFrameFor(capturingContent);
|
||||
if (frame) {
|
||||
getDescendantPoint = !gCaptureInfo.mRetargetToElement;
|
||||
if (!capturingContent->GetParent()) {
|
||||
frame = frame->GetParent();
|
||||
}
|
||||
else {
|
||||
// special case for <select> as it needs to capture on the dropdown list.
|
||||
if (capturingContent->Tag() == nsGkAtoms::select &&
|
||||
capturingContent->IsNodeOfType(nsINode::eHTML)) {
|
||||
nsIFrame* childframe = frame->GetChildList(nsGkAtoms::selectPopupList).FirstChild();
|
||||
if (childframe) {
|
||||
frame = childframe;
|
||||
}
|
||||
}
|
||||
|
||||
// if the frame is a scrolling frame, get the inner scrolled frame instead.
|
||||
nsIScrollableFrame* scrollFrame = do_QueryFrame(frame);
|
||||
if (scrollFrame) {
|
||||
frame = scrollFrame->GetScrolledFrame();
|
||||
}
|
||||
}
|
||||
aView = frame->GetClosestView();
|
||||
}
|
||||
}
|
||||
|
||||
PRBool dispatchUsingCoordinates = NS_IsEventUsingCoordinates(aEvent);
|
||||
|
||||
// if this event has no frame, we need to retarget it at a parent
|
||||
|
@ -6182,8 +6149,28 @@ PresShell::HandleEvent(nsIView *aView,
|
|||
#endif
|
||||
}
|
||||
|
||||
PRBool captureRetarget = PR_FALSE;
|
||||
if (capturingContent) {
|
||||
captureRetarget = gCaptureInfo.mRetargetToElement;
|
||||
// special case for <select> as it needs to capture on the dropdown list,
|
||||
// so get the frame for the dropdown list instead.
|
||||
if (!captureRetarget && capturingContent->Tag() == nsGkAtoms::select &&
|
||||
capturingContent->IsNodeOfType(nsINode::eHTML)) {
|
||||
nsIFrame* selectFrame = GetPrimaryFrameFor(capturingContent);
|
||||
if (selectFrame) {
|
||||
nsIFrame* childframe = selectFrame->GetChildList(nsGkAtoms::selectPopupList).FirstChild();
|
||||
if (childframe) {
|
||||
frame = childframe;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the frame at the event point. However, don't do this if we're
|
||||
// capturing and retargeting the event because the captured frame will
|
||||
// be used instead below.
|
||||
nsIFrame* targetFrame = nsnull;
|
||||
if (getDescendantPoint) {
|
||||
if (!captureRetarget) {
|
||||
nsPoint eventPoint
|
||||
= nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, frame);
|
||||
{
|
||||
|
@ -6197,6 +6184,24 @@ PresShell::HandleEvent(nsIView *aView,
|
|||
}
|
||||
}
|
||||
|
||||
// if a node is capturing the mouse, check if the event needs to be
|
||||
// retargeted at the capturing content instead. This will be the case when
|
||||
// capture retargeting is being used, no frame was found or the frame's
|
||||
// content is not a descendant of the capturing content.
|
||||
if (capturingContent &&
|
||||
(gCaptureInfo.mRetargetToElement ||
|
||||
!targetFrame || !targetFrame->GetContent() ||
|
||||
!nsContentUtils::ContentIsCrossDocDescendantOf(targetFrame->GetContent(),
|
||||
capturingContent))) {
|
||||
// A check was already done above to ensure that capturingContent is
|
||||
// in this presshell, so GetPrimaryFrameFor can just be called directly.
|
||||
nsIFrame* capturingFrame = GetPrimaryFrameFor(capturingContent);
|
||||
if (capturingFrame) {
|
||||
targetFrame = capturingFrame;
|
||||
aView = targetFrame->GetClosestView();
|
||||
}
|
||||
}
|
||||
|
||||
if (targetFrame) {
|
||||
PresShell* shell =
|
||||
static_cast<PresShell*>(targetFrame->PresContext()->PresShell());
|
||||
|
|
|
@ -1458,6 +1458,13 @@ void
|
|||
nsHTMLFramesetFrame::MouseDrag(nsPresContext* aPresContext,
|
||||
nsGUIEvent* aEvent)
|
||||
{
|
||||
// if the capture ended, reset the drag state
|
||||
if (nsIPresShell::GetCapturingContent() != GetContent()) {
|
||||
mDragger = nsnull;
|
||||
gDragInProgress = PR_FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
PRInt32 change; // measured positive from left-to-right or top-to-bottom
|
||||
nsWeakFrame weakFrame(this);
|
||||
if (mDragger->mVertical) {
|
||||
|
|
|
@ -124,9 +124,27 @@ function runTests()
|
|||
runCaptureTest(custom5);
|
||||
captureRetargetMode = false;
|
||||
|
||||
var custom6 = document.getElementById("custom6");
|
||||
synthesizeMouse(custom6, 2, 2, { type: "mousedown" });
|
||||
synthesizeMouseExpectEvent($("leftbox"), 2, 2, { type: "mousemove" },
|
||||
$("leftbox"), "mousemove", "setCapture only works on elements in documents");
|
||||
synthesizeMouse(custom6, 2, 2, { type: "mouseup" });
|
||||
|
||||
var b = frames[0].document.getElementById("b");
|
||||
runCaptureTest(b, selectionCallback);
|
||||
|
||||
frames[0].getSelection().collapseToStart();
|
||||
|
||||
var body = frames[0].document.body;
|
||||
var fixed = frames[0].document.getElementById("fixed");
|
||||
function captureOnBody() { body.setCapture() }
|
||||
body.addEventListener("mousedown", captureOnBody, true);
|
||||
synthesizeMouse(body, 8, 8, { type: "mousedown" }, frames[0]);
|
||||
body.removeEventListener("mousedown", captureOnBody, true);
|
||||
synthesizeMouseExpectEvent(fixed, 2, 2, { type: "mousemove" },
|
||||
fixed, "mousemove", "setCapture on body retargets to root node", frames[0]);
|
||||
synthesizeMouse(body, 8, 8, { type: "mouseup" }, frames[0]);
|
||||
|
||||
previousWidth = frames[1].frames[0].document.documentElement.clientWidth;
|
||||
originalWidth = previousWidth;
|
||||
runCaptureTest(frames[1].document.documentElement.lastChild, framesetCallback);
|
||||
|
@ -220,16 +238,18 @@ SimpleTest.waitForFocus(runTests);
|
|||
<spacer id="custom5spacer" width="5"/>
|
||||
<hbox id="custom5inner" width="35" height="35"/>
|
||||
</hbox>
|
||||
<vbox id="custom6" width="10" height="10"
|
||||
onmousedown="document.createElement('hbox').setCapture();"/>
|
||||
|
||||
<hbox>
|
||||
<iframe width="100" height="100"
|
||||
src="data:text/html,%3Cbody style%3D'font-size%3A 40pt%3B'%3E.%3Cb id%3D'b'%3EThis%3C/b%3E is some text%3C/body%3E"/>
|
||||
src="data:text/html,%3Cbody style%3D'font-size%3A 40pt%3B'%3E.%3Cb id%3D'b'%3EThis%3C/b%3E is some text%3Cdiv id='fixed' style='position: fixed; left: 55px; top: 5px; width: 10px; height: 10px'%3E.%3C/div%3E%3C/body%3E"/>
|
||||
|
||||
<iframe width="100" height="100"
|
||||
src="data:text/html,%3Cframeset cols='50%, 50%'%3E%3Cframe src='about:blank'%3E%3Cframe src='about:blank'%3E%3C/frameset%3E"/>
|
||||
</hbox>
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<body id="body" xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p id="display"/><div id="content" style="display: none"/><pre id="test"/>
|
||||
</body>
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче