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:
Robert O'Callahan 2010-03-05 13:10:32 +13:00
Родитель aeff873bb5
Коммит bf5b70fa35
3 изменённых файлов: 202 добавлений и 44 удалений

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

@ -83,6 +83,7 @@ _TEST_FILES = \
test_bug508479.html \
test_bug517851.html \
test_bug534833.html \
test_bug545268.html \
$(NULL)
_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,&lt;input&gt;'>", "" , "");
win.onload = doTest;
</script>
</pre>
</body>
</html>

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

@ -6097,23 +6097,16 @@ PresShell::HandleEvent(nsIView *aView,
return NS_OK;
}
if (mDocument && mDocument->EventHandlingSuppressed()) {
nsDelayedEvent* event = nsnull;
if (aEvent->eventStructType == NS_KEY_EVENT) {
if (aEvent->message == NS_KEY_DOWN) {
mNoDelayedKeyEvents = PR_TRUE;
} else if (!mNoDelayedKeyEvents) {
event = new nsDelayedKeyEvent(static_cast<nsKeyEvent*>(aEvent));
if (aEvent->eventStructType == NS_KEY_EVENT &&
mDocument && mDocument->EventHandlingSuppressed()) {
if (aEvent->message == NS_KEY_DOWN) {
mNoDelayedKeyEvents = PR_TRUE;
} else if (!mNoDelayedKeyEvents) {
nsDelayedEvent* event =
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;
}
@ -6159,7 +6152,7 @@ PresShell::HandleEvent(nsIView *aView,
nsTArray<nsIFrame*> popups = pm->GetVisiblePopups();
PRUint32 i;
// Search from top to bottom
nsIDocument* doc = frame->PresContext()->GetPresShell()->GetDocument();
nsIDocument* doc = framePresContext->GetPresShell()->GetDocument();
for (i = 0; i < popups.Length(); i++) {
nsIFrame* popup = popups[i];
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
// capturing and retargeting the event because the captured frame will
// be used instead below.
nsIFrame* targetFrame = nsnull;
if (!captureRetarget) {
nsPoint eventPoint
= nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, frame);
@ -6230,8 +6222,11 @@ PresShell::HandleEvent(nsIView *aView,
if (aEvent->eventStructType == NS_MOUSE_EVENT) {
ignoreRootScrollFrame = static_cast<nsMouseEvent*>(aEvent)->ignoreRootScrollFrame;
}
targetFrame = nsLayoutUtils::GetFrameForPoint(frame, eventPoint,
PR_FALSE, ignoreRootScrollFrame);
nsIFrame* target = nsLayoutUtils::GetFrameForPoint(frame, eventPoint,
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
// content is not a descendant of the capturing content.
if (capturingContent &&
(gCaptureInfo.mRetargetToElement ||
!targetFrame || !targetFrame->GetContent() ||
!nsContentUtils::ContentIsCrossDocDescendantOf(targetFrame->GetContent(),
(gCaptureInfo.mRetargetToElement || !frame->GetContent() ||
!nsContentUtils::ContentIsCrossDocDescendantOf(frame->GetContent(),
capturingContent))) {
// A check was already done above to ensure that capturingContent is
// in this presshell.
@ -6250,33 +6244,45 @@ PresShell::HandleEvent(nsIView *aView,
"Unexpected document");
nsIFrame* capturingFrame = capturingContent->GetPrimaryFrame();
if (capturingFrame) {
targetFrame = capturingFrame;
aView = targetFrame->GetClosestView();
frame = capturingFrame;
aView = frame->GetClosestView();
}
}
if (targetFrame) {
PresShell* shell =
static_cast<PresShell*>(targetFrame->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, targetFrame,
aEvent, aEventStatus);
// Suppress mouse event if it's being targeted at an element inside
// a document which needs events suppressed
if (aEvent->eventStructType == NS_MOUSE_EVENT &&
frame->PresContext()->Document()->EventHandlingSuppressed()) {
if (aEvent->message == NS_MOUSE_BUTTON_DOWN) {
mNoDelayedMouseEvents = PR_TRUE;
} else if (!mNoDelayedMouseEvents && aEvent->message == NS_MOUSE_BUTTON_UP) {
nsDelayedEvent* event =
new nsDelayedMouseEvent(static_cast<nsMouseEvent*>(aEvent));
if (!mDelayedEvents.AppendElement(event)) {
delete event;
}
}
return NS_OK;
}
if (!targetFrame) {
targetFrame = frame;
PresShell* shell =
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;