Bug 493251 - Header/navigation links on PG.com take two clicks to load, r+sr=jst

This commit is contained in:
Olli Pettay 2009-05-18 12:17:45 +03:00
Родитель ec4430cfb4
Коммит 7821f28d58
3 изменённых файлов: 282 добавлений и 19 удалений

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

@ -69,6 +69,7 @@ _TEST_FILES = \
bug457672.html \
test_draggableprop.html \
test_dragstart.html \
test_bug493251.html \
$(NULL)
_CHROME_FILES = \

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

@ -0,0 +1,144 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=493251
-->
<head>
<title>Test for Bug 493251</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=493251">Mozilla Bug 493251</a>
<p id="display">
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 493251 **/
var win;
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 = win.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);
win.document.getElementsByTagName("input")[0].focus();
win.addEventListener("keydown", function(e) { ++keyDown; }, true);
win.addEventListener("keypress", function(e) { ++keyPress; }, true);
win.addEventListener("keyup", function(e) { ++keyUp; }, true);
win.addEventListener("mousedown", function(e) { ++mouseDown; }, true);
win.addEventListener("mouseup", function(e) { ++mouseUp; }, true);
win.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)");
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,<input>", "" , "");
win.onload = doTest;
</script>
</pre>
</body>
</html>

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

@ -1180,18 +1180,118 @@ protected:
PRIntn mContentScrollVPosition;
PRIntn mContentScrollHPosition;
struct nsBlurOrFocusTarget
class nsDelayedEvent
{
nsBlurOrFocusTarget(nsPIDOMEventTarget* aTarget, PRUint32 aEventType)
public:
virtual ~nsDelayedEvent() {};
virtual void Dispatch(PresShell* aShell) {}
// This is needed only by nsDelayedFocusBlur.
virtual PRBool Equals(nsPIDOMEventTarget* aTarget, PRUint32 aEventType)
{
return PR_FALSE;
}
};
class nsDelayedFocusBlur : public nsDelayedEvent
{
public:
nsDelayedFocusBlur(nsPIDOMEventTarget* aTarget, PRUint32 aEventType)
: mTarget(aTarget), mEventType(aEventType) {}
nsBlurOrFocusTarget(const nsBlurOrFocusTarget& aOther)
: mTarget(aOther.mTarget), mEventType(aOther.mEventType) {}
virtual void Dispatch(PresShell* aShell)
{
nsEvent event(PR_TRUE, mEventType);
event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
nsEventDispatcher::Dispatch(mTarget, aShell->GetPresContext(), &event);
}
virtual PRBool Equals(nsPIDOMEventTarget* aTarget, PRUint32 aEventType)
{
return aTarget == mTarget && aEventType == mEventType;
}
nsCOMPtr<nsPIDOMEventTarget> mTarget;
PRUint32 mEventType;
};
nsTArray<nsBlurOrFocusTarget> mDelayedBlurFocusTargets;
class nsDelayedInputEvent : public nsDelayedEvent
{
public:
virtual void Dispatch(PresShell* aShell)
{
if (mEvent && mEvent->widget) {
nsCOMPtr<nsIWidget> w = mEvent->widget;
nsEventStatus status;
w->DispatchEvent(mEvent, status);
}
}
protected:
void Init(nsInputEvent* aEvent)
{
mEvent->time = aEvent->time;
mEvent->refPoint = aEvent->refPoint;
mEvent->isShift = aEvent->isShift;
mEvent->isControl = aEvent->isControl;
mEvent->isAlt = aEvent->isAlt;
mEvent->isMeta = aEvent->isMeta;
}
nsDelayedInputEvent()
: nsDelayedEvent(), mEvent(nsnull) {}
nsInputEvent* mEvent;
};
class nsDelayedMouseEvent : public nsDelayedInputEvent
{
public:
nsDelayedMouseEvent(nsMouseEvent* aEvent) : nsDelayedInputEvent()
{
mEvent = new nsMouseEvent(NS_IS_TRUSTED_EVENT(aEvent),
aEvent->message,
aEvent->widget,
aEvent->reason,
aEvent->context);
if (mEvent) {
Init(aEvent);
static_cast<nsMouseEvent*>(mEvent)->clickCount = aEvent->clickCount;
}
}
virtual ~nsDelayedMouseEvent()
{
delete static_cast<nsMouseEvent*>(mEvent);
}
};
class nsDelayedKeyEvent : public nsDelayedInputEvent
{
public:
nsDelayedKeyEvent(nsKeyEvent* aEvent) : nsDelayedInputEvent()
{
mEvent = new nsKeyEvent(NS_IS_TRUSTED_EVENT(aEvent),
aEvent->message,
aEvent->widget);
if (mEvent) {
Init(aEvent);
static_cast<nsKeyEvent*>(mEvent)->keyCode = aEvent->keyCode;
static_cast<nsKeyEvent*>(mEvent)->charCode = aEvent->charCode;
static_cast<nsKeyEvent*>(mEvent)->alternativeCharCodes =
aEvent->alternativeCharCodes;
static_cast<nsKeyEvent*>(mEvent)->isChar = aEvent->isChar;
}
}
virtual ~nsDelayedKeyEvent()
{
delete static_cast<nsKeyEvent*>(mEvent);
}
};
PRPackedBool mNoDelayedMouseEvents;
PRPackedBool mNoDelayedKeyEvents;
nsTArray<nsAutoPtr<nsDelayedEvent> > mDelayedEvents;
nsCallbackEventRequest* mFirstCallbackEventRequest;
nsCallbackEventRequest* mLastCallbackEventRequest;
@ -5880,10 +5980,27 @@ PresShell::HandleEvent(nsIView *aView,
aEvent->message == NS_DEACTIVATE);
if (mDocument && mDocument->EventHandlingSuppressed()) {
if (!widgetHandlingEvent) {
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));
}
} 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;
}
} else if (widgetHandlingEvent) {
mDelayedBlurFocusTargets.Clear();
FireOrClearDelayedEvents(PR_FALSE);
}
nsIFrame* frame = static_cast<nsIFrame*>(aView->GetClientData());
@ -6731,22 +6848,21 @@ PresShell::Freeze()
void
PresShell::FireOrClearDelayedEvents(PRBool aFireEvents)
{
mNoDelayedMouseEvents = PR_FALSE;
mNoDelayedKeyEvents = PR_FALSE;
if (!aFireEvents) {
mDelayedBlurFocusTargets.Clear();
mDelayedEvents.Clear();
return;
}
if (!mIsDestroying && mDocument) {
nsCOMPtr<nsIDocument> doc = mDocument;
while (mDelayedBlurFocusTargets.Length() && !doc->EventHandlingSuppressed()) {
nsEvent event(PR_TRUE, mDelayedBlurFocusTargets[0].mEventType);
event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
nsEventDispatcher::Dispatch(mDelayedBlurFocusTargets[0].mTarget,
mPresContext, &event);
mDelayedBlurFocusTargets.RemoveElementAt(0);
while (mDelayedEvents.Length() && !doc->EventHandlingSuppressed()) {
mDelayedEvents[0]->Dispatch(this);
mDelayedEvents.RemoveElementAt(0);
}
if (!doc->EventHandlingSuppressed()) {
mDelayedBlurFocusTargets.Clear();
mDelayedEvents.Clear();
}
}
}
@ -6756,14 +6872,16 @@ PresShell::NeedsFocusOrBlurAfterSuppression(nsPIDOMEventTarget* aTarget,
PRUint32 aEventType)
{
if (mDocument && mDocument->EventHandlingSuppressed()) {
for (PRUint32 i = mDelayedBlurFocusTargets.Length(); i > 0; --i) {
if (mDelayedBlurFocusTargets[i - 1].mTarget == aTarget &&
mDelayedBlurFocusTargets[i - 1].mEventType == aEventType) {
mDelayedBlurFocusTargets.RemoveElementAt(i - 1);
for (PRUint32 i = mDelayedEvents.Length(); i > 0; --i) {
if (mDelayedEvents[i - 1]->Equals(aTarget, aEventType)) {
mDelayedEvents.RemoveElementAt(i - 1);
}
}
mDelayedBlurFocusTargets.AppendElement(nsBlurOrFocusTarget(aTarget, aEventType));
nsDelayedFocusBlur* delayed = new nsDelayedFocusBlur(aTarget, aEventType);
if (delayed && !mDelayedEvents.AppendElement(delayed)) {
delete delayed;
}
}
}