зеркало из https://github.com/mozilla/gecko-dev.git
Bug 545268. Decide whether to suppress a mouse event by looking at the suppression state of the document where the event is going to be delivered. r=smaug
This commit is contained in:
Родитель
aeff873bb5
Коммит
bf5b70fa35
|
@ -83,6 +83,7 @@ _TEST_FILES = \
|
||||||
test_bug508479.html \
|
test_bug508479.html \
|
||||||
test_bug517851.html \
|
test_bug517851.html \
|
||||||
test_bug534833.html \
|
test_bug534833.html \
|
||||||
|
test_bug545268.html \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
_CHROME_FILES = \
|
_CHROME_FILES = \
|
||||||
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=545268
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<title>Test for Bug 545268</title>
|
||||||
|
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=545268">Mozilla Bug 545268</a>
|
||||||
|
<p id="display">
|
||||||
|
</p>
|
||||||
|
<div id="content" style="display: none">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
/** Test for Bug 545268
|
||||||
|
Like the test for bug 493251, but we test that suppressing events in
|
||||||
|
a parent window stops the events from reaching the child window. */
|
||||||
|
|
||||||
|
var win;
|
||||||
|
var subwin;
|
||||||
|
|
||||||
|
var mouseDown = 0;
|
||||||
|
var mouseUp = 0;
|
||||||
|
var mouseClick = 0;
|
||||||
|
|
||||||
|
var keyDown = 0;
|
||||||
|
var keyPress = 0;
|
||||||
|
var keyUp = 0;
|
||||||
|
|
||||||
|
function dispatchKeyEvent(type) {
|
||||||
|
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||||
|
var utils = subwin.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||||
|
getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||||
|
utils.sendKeyEvent(type,
|
||||||
|
Components.interfaces.nsIDOMKeyEvent.DOM_VK_A,
|
||||||
|
0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function doTest() {
|
||||||
|
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||||
|
var utils = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||||
|
getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||||
|
var f = win.document.getElementById("f");
|
||||||
|
subwin = f.contentWindow;
|
||||||
|
subwin.document.getElementsByTagName("input")[0].focus();
|
||||||
|
subwin.addEventListener("keydown", function(e) { ++keyDown; }, true);
|
||||||
|
subwin.addEventListener("keypress", function(e) { ++keyPress; }, true);
|
||||||
|
subwin.addEventListener("keyup", function(e) { ++keyUp; }, true);
|
||||||
|
subwin.addEventListener("mousedown", function(e) { ++mouseDown; }, true);
|
||||||
|
subwin.addEventListener("mouseup", function(e) { ++mouseUp; }, true);
|
||||||
|
subwin.addEventListener("click", function(e) { ++mouseClick; }, true);
|
||||||
|
|
||||||
|
dispatchKeyEvent("keydown");
|
||||||
|
dispatchKeyEvent("keypress");
|
||||||
|
dispatchKeyEvent("keyup");
|
||||||
|
is(keyDown, 1, "Wrong number events (1)");
|
||||||
|
is(keyPress, 1, "Wrong number events (2)");
|
||||||
|
is(keyUp, 1, "Wrong number events (3)");
|
||||||
|
|
||||||
|
// Test that suppressing events on the parent window prevents key
|
||||||
|
// events in the subdocument window
|
||||||
|
utils.suppressEventHandling(true);
|
||||||
|
dispatchKeyEvent("keydown");
|
||||||
|
dispatchKeyEvent("keypress");
|
||||||
|
dispatchKeyEvent("keyup");
|
||||||
|
is(keyDown, 1, "Wrong number events (4)");
|
||||||
|
is(keyPress, 1, "Wrong number events (5)");
|
||||||
|
is(keyUp, 1, "Wrong number events (6)");
|
||||||
|
utils.suppressEventHandling(false);
|
||||||
|
is(keyDown, 1, "Wrong number events (7)");
|
||||||
|
is(keyPress, 1, "Wrong number events (8)");
|
||||||
|
is(keyUp, 1, "Wrong number events (9)");
|
||||||
|
|
||||||
|
setTimeout(continueTest1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function continueTest1() {
|
||||||
|
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||||
|
var utils = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||||
|
getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||||
|
dispatchKeyEvent("keydown");
|
||||||
|
utils.suppressEventHandling(true);
|
||||||
|
dispatchKeyEvent("keypress");
|
||||||
|
dispatchKeyEvent("keyup");
|
||||||
|
is(keyDown, 2, "Wrong number events (10)");
|
||||||
|
is(keyPress, 1, "Wrong number events (11)");
|
||||||
|
is(keyUp, 1, "Wrong number events (12)");
|
||||||
|
utils.suppressEventHandling(false);
|
||||||
|
setTimeout(continueTest2, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function continueTest2() {
|
||||||
|
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||||
|
var utils = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||||
|
getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||||
|
is(keyDown, 2, "Wrong number events (13)");
|
||||||
|
is(keyPress, 2, "Wrong number events (14)");
|
||||||
|
is(keyUp, 2, "Wrong number events (15)");
|
||||||
|
|
||||||
|
utils.sendMouseEvent("mousedown", 5, 5, 0, 1, 0);
|
||||||
|
utils.sendMouseEvent("mouseup", 5, 5, 0, 1, 0);
|
||||||
|
is(mouseDown, 1, "Wrong number events (16)");
|
||||||
|
is(mouseUp, 1, "Wrong number events (17)");
|
||||||
|
is(mouseClick, 1, "Wrong number events (18)");
|
||||||
|
|
||||||
|
utils.suppressEventHandling(true);
|
||||||
|
utils.sendMouseEvent("mousedown", 5, 5, 0, 1, 0);
|
||||||
|
utils.sendMouseEvent("mouseup", 5, 5, 0, 1, 0);
|
||||||
|
utils.suppressEventHandling(false);
|
||||||
|
is(mouseDown, 1, "Wrong number events (19)");
|
||||||
|
is(mouseUp, 1, "Wrong number events (20)");
|
||||||
|
is(mouseClick, 1, "Wrong number events (21)");
|
||||||
|
|
||||||
|
setTimeout(continueTest3, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function continueTest3() {
|
||||||
|
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||||
|
var utils = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||||
|
getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||||
|
utils.sendMouseEvent("mousedown", 5, 5, 0, 1, 0);
|
||||||
|
utils.suppressEventHandling(true);
|
||||||
|
utils.sendMouseEvent("mouseup", 5, 5, 0, 1, 0);
|
||||||
|
utils.suppressEventHandling(false);
|
||||||
|
setTimeout(continueTest4, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function continueTest4() {
|
||||||
|
is(mouseDown, 2, "Wrong number events (19)");
|
||||||
|
is(mouseUp, 2, "Wrong number events (20)");
|
||||||
|
is(mouseClick, 2, "Wrong number events (21)");
|
||||||
|
win.close();
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
win = window.open("data:text/html,<iframe id='f' style='position:absolute; border:none; width:100%; height:100%; left:0; top:0' src='data:text/html,<input>'>", "" , "");
|
||||||
|
win.onload = doTest;
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -6097,23 +6097,16 @@ PresShell::HandleEvent(nsIView *aView,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mDocument && mDocument->EventHandlingSuppressed()) {
|
if (aEvent->eventStructType == NS_KEY_EVENT &&
|
||||||
nsDelayedEvent* event = nsnull;
|
mDocument && mDocument->EventHandlingSuppressed()) {
|
||||||
if (aEvent->eventStructType == NS_KEY_EVENT) {
|
if (aEvent->message == NS_KEY_DOWN) {
|
||||||
if (aEvent->message == NS_KEY_DOWN) {
|
mNoDelayedKeyEvents = PR_TRUE;
|
||||||
mNoDelayedKeyEvents = PR_TRUE;
|
} else if (!mNoDelayedKeyEvents) {
|
||||||
} else if (!mNoDelayedKeyEvents) {
|
nsDelayedEvent* event =
|
||||||
event = new nsDelayedKeyEvent(static_cast<nsKeyEvent*>(aEvent));
|
new nsDelayedKeyEvent(static_cast<nsKeyEvent*>(aEvent));
|
||||||
|
if (event && !mDelayedEvents.AppendElement(event)) {
|
||||||
|
delete event;
|
||||||
}
|
}
|
||||||
} else if (aEvent->eventStructType == NS_MOUSE_EVENT) {
|
|
||||||
if (aEvent->message == NS_MOUSE_BUTTON_DOWN) {
|
|
||||||
mNoDelayedMouseEvents = PR_TRUE;
|
|
||||||
} else if (!mNoDelayedMouseEvents && aEvent->message == NS_MOUSE_BUTTON_UP) {
|
|
||||||
event = new nsDelayedMouseEvent(static_cast<nsMouseEvent*>(aEvent));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (event && !mDelayedEvents.AppendElement(event)) {
|
|
||||||
delete event;
|
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -6159,7 +6152,7 @@ PresShell::HandleEvent(nsIView *aView,
|
||||||
nsTArray<nsIFrame*> popups = pm->GetVisiblePopups();
|
nsTArray<nsIFrame*> popups = pm->GetVisiblePopups();
|
||||||
PRUint32 i;
|
PRUint32 i;
|
||||||
// Search from top to bottom
|
// Search from top to bottom
|
||||||
nsIDocument* doc = frame->PresContext()->GetPresShell()->GetDocument();
|
nsIDocument* doc = framePresContext->GetPresShell()->GetDocument();
|
||||||
for (i = 0; i < popups.Length(); i++) {
|
for (i = 0; i < popups.Length(); i++) {
|
||||||
nsIFrame* popup = popups[i];
|
nsIFrame* popup = popups[i];
|
||||||
if (popup->GetOverflowRect().Contains(
|
if (popup->GetOverflowRect().Contains(
|
||||||
|
@ -6221,7 +6214,6 @@ PresShell::HandleEvent(nsIView *aView,
|
||||||
// Get the frame at the event point. However, don't do this if we're
|
// 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
|
// capturing and retargeting the event because the captured frame will
|
||||||
// be used instead below.
|
// be used instead below.
|
||||||
nsIFrame* targetFrame = nsnull;
|
|
||||||
if (!captureRetarget) {
|
if (!captureRetarget) {
|
||||||
nsPoint eventPoint
|
nsPoint eventPoint
|
||||||
= nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, frame);
|
= nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, frame);
|
||||||
|
@ -6230,8 +6222,11 @@ PresShell::HandleEvent(nsIView *aView,
|
||||||
if (aEvent->eventStructType == NS_MOUSE_EVENT) {
|
if (aEvent->eventStructType == NS_MOUSE_EVENT) {
|
||||||
ignoreRootScrollFrame = static_cast<nsMouseEvent*>(aEvent)->ignoreRootScrollFrame;
|
ignoreRootScrollFrame = static_cast<nsMouseEvent*>(aEvent)->ignoreRootScrollFrame;
|
||||||
}
|
}
|
||||||
targetFrame = nsLayoutUtils::GetFrameForPoint(frame, eventPoint,
|
nsIFrame* target = nsLayoutUtils::GetFrameForPoint(frame, eventPoint,
|
||||||
PR_FALSE, ignoreRootScrollFrame);
|
PR_FALSE, ignoreRootScrollFrame);
|
||||||
|
if (target) {
|
||||||
|
frame = target;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6240,9 +6235,8 @@ PresShell::HandleEvent(nsIView *aView,
|
||||||
// capture retargeting is being used, no frame was found or the frame's
|
// capture retargeting is being used, no frame was found or the frame's
|
||||||
// content is not a descendant of the capturing content.
|
// content is not a descendant of the capturing content.
|
||||||
if (capturingContent &&
|
if (capturingContent &&
|
||||||
(gCaptureInfo.mRetargetToElement ||
|
(gCaptureInfo.mRetargetToElement || !frame->GetContent() ||
|
||||||
!targetFrame || !targetFrame->GetContent() ||
|
!nsContentUtils::ContentIsCrossDocDescendantOf(frame->GetContent(),
|
||||||
!nsContentUtils::ContentIsCrossDocDescendantOf(targetFrame->GetContent(),
|
|
||||||
capturingContent))) {
|
capturingContent))) {
|
||||||
// A check was already done above to ensure that capturingContent is
|
// A check was already done above to ensure that capturingContent is
|
||||||
// in this presshell.
|
// in this presshell.
|
||||||
|
@ -6250,33 +6244,45 @@ PresShell::HandleEvent(nsIView *aView,
|
||||||
"Unexpected document");
|
"Unexpected document");
|
||||||
nsIFrame* capturingFrame = capturingContent->GetPrimaryFrame();
|
nsIFrame* capturingFrame = capturingContent->GetPrimaryFrame();
|
||||||
if (capturingFrame) {
|
if (capturingFrame) {
|
||||||
targetFrame = capturingFrame;
|
frame = capturingFrame;
|
||||||
aView = targetFrame->GetClosestView();
|
aView = frame->GetClosestView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetFrame) {
|
// Suppress mouse event if it's being targeted at an element inside
|
||||||
PresShell* shell =
|
// a document which needs events suppressed
|
||||||
static_cast<PresShell*>(targetFrame->PresContext()->PresShell());
|
if (aEvent->eventStructType == NS_MOUSE_EVENT &&
|
||||||
if (shell != this) {
|
frame->PresContext()->Document()->EventHandlingSuppressed()) {
|
||||||
// Handle the event in the correct shell.
|
if (aEvent->message == NS_MOUSE_BUTTON_DOWN) {
|
||||||
// Prevent deletion until we're done with event handling (bug 336582).
|
mNoDelayedMouseEvents = PR_TRUE;
|
||||||
nsCOMPtr<nsIPresShell> kungFuDeathGrip(shell);
|
} else if (!mNoDelayedMouseEvents && aEvent->message == NS_MOUSE_BUTTON_UP) {
|
||||||
nsIView* subshellRootView;
|
nsDelayedEvent* event =
|
||||||
shell->GetViewManager()->GetRootView(subshellRootView);
|
new nsDelayedMouseEvent(static_cast<nsMouseEvent*>(aEvent));
|
||||||
// We pass the subshell's root view as the view to start from. This is
|
if (!mDelayedEvents.AppendElement(event)) {
|
||||||
// the only correct alternative; if the event was captured then it
|
delete event;
|
||||||
// must have been captured by us or some ancestor shell and we
|
}
|
||||||
// now ask the subshell to dispatch it normally.
|
|
||||||
return shell->HandlePositionedEvent(subshellRootView, targetFrame,
|
|
||||||
aEvent, aEventStatus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!targetFrame) {
|
PresShell* shell =
|
||||||
targetFrame = frame;
|
static_cast<PresShell*>(frame->PresContext()->PresShell());
|
||||||
|
if (shell != this) {
|
||||||
|
// Handle the event in the correct shell.
|
||||||
|
// Prevent deletion until we're done with event handling (bug 336582).
|
||||||
|
nsCOMPtr<nsIPresShell> kungFuDeathGrip(shell);
|
||||||
|
nsIView* subshellRootView;
|
||||||
|
shell->GetViewManager()->GetRootView(subshellRootView);
|
||||||
|
// We pass the subshell's root view as the view to start from. This is
|
||||||
|
// the only correct alternative; if the event was captured then it
|
||||||
|
// must have been captured by us or some ancestor shell and we
|
||||||
|
// now ask the subshell to dispatch it normally.
|
||||||
|
return shell->HandlePositionedEvent(subshellRootView, frame,
|
||||||
|
aEvent, aEventStatus);
|
||||||
}
|
}
|
||||||
return HandlePositionedEvent(aView, targetFrame, aEvent, aEventStatus);
|
|
||||||
|
return HandlePositionedEvent(aView, frame, aEvent, aEventStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче