diff --git a/mozilla/layout/base/nsIPresShell.h b/mozilla/layout/base/nsIPresShell.h index 23a036aeeec..8752c0344ac 100644 --- a/mozilla/layout/base/nsIPresShell.h +++ b/mozilla/layout/base/nsIPresShell.h @@ -386,6 +386,13 @@ public: nsIContent* aContent, nsEventStatus* aStatus) = 0; + /** + * Dispatch event to content only (NOT full processing) + */ + NS_IMETHOD HandleDOMEventWithTarget(nsIContent* aTargetContent, + nsEvent* aEvent, + nsEventStatus* aStatus) = 0; + /** * Gets the current target event frame from the PresShell */ diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index 98dbaea88bc..7e3a2e3f113 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -696,6 +696,9 @@ public: nsGUIEvent* aEvent, nsEventStatus* aEventStatus, PRBool& aHandled); + NS_IMETHOD HandleDOMEventWithTarget(nsIContent* aTargetContent, + nsEvent* aEvent, + nsEventStatus* aStatus); NS_IMETHOD Scrolled(nsIView *aView); NS_IMETHOD ResizeReflow(nsIView *aView, nscoord aWidth, nscoord aHeight); @@ -3927,6 +3930,32 @@ PresShell::HandleEventInternal(nsEvent* aEvent, nsIView *aView, nsEventStatus* a return rv; } +// Dispatch event to content only (NOT full processing) +// See also HandleEventWithTarget which does full event processing. +NS_IMETHODIMP +PresShell::HandleDOMEventWithTarget(nsIContent* aTargetContent, nsEvent* aEvent, nsEventStatus* aStatus) +{ + nsresult ret; + + PushCurrentEventInfo(nsnull, aTargetContent); + + // Bug 41013: Check if the event should be dispatched to content. + // It's possible that we are in the middle of destroying the window + // and the js context is out of date. This check detects the case + // that caused a crash in bug 41013, but there may be a better way + // to handle this situation! + nsCOMPtr container; + ret = mPresContext->GetContainer(getter_AddRefs(container)); + if (NS_SUCCEEDED(ret) && container) { + + // Dispatch event to content + ret = aTargetContent->HandleDOMEvent(mPresContext, aEvent, nsnull, NS_EVENT_FLAG_INIT, aStatus); + } + + PopCurrentEventInfo(); + return NS_OK; +} + NS_IMETHODIMP PresShell::Scrolled(nsIView *aView) { diff --git a/mozilla/layout/base/public/nsIPresShell.h b/mozilla/layout/base/public/nsIPresShell.h index 23a036aeeec..8752c0344ac 100644 --- a/mozilla/layout/base/public/nsIPresShell.h +++ b/mozilla/layout/base/public/nsIPresShell.h @@ -386,6 +386,13 @@ public: nsIContent* aContent, nsEventStatus* aStatus) = 0; + /** + * Dispatch event to content only (NOT full processing) + */ + NS_IMETHOD HandleDOMEventWithTarget(nsIContent* aTargetContent, + nsEvent* aEvent, + nsEventStatus* aStatus) = 0; + /** * Gets the current target event frame from the PresShell */ diff --git a/mozilla/layout/forms/nsImageControlFrame.cpp b/mozilla/layout/forms/nsImageControlFrame.cpp index 189f2c95709..c114d2ba138 100644 --- a/mozilla/layout/forms/nsImageControlFrame.cpp +++ b/mozilla/layout/forms/nsImageControlFrame.cpp @@ -375,6 +375,8 @@ nsImageControlFrame::GetName(nsString* aResult) PRBool nsImageControlFrame::IsSuccessful(nsIFormControlFrame* aSubmitter) { + // Image control will only add it's value if it is clicked on. + // XXX Is this right? return (this == (aSubmitter)); } @@ -456,7 +458,11 @@ nsImageControlFrame::MouseClicked(nsIPresContext* aPresContext) event.eventStructType = NS_EVENT; event.message = NS_FORM_SUBMIT; if (nsnull != formContent) { - formContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); + nsCOMPtr shell; + nsresult result = aPresContext->GetShell(getter_AddRefs(shell)); + if (NS_SUCCEEDED(result) && shell) { + shell->HandleDOMEventWithTarget(formContent, &event, &status); + } NS_RELEASE(formContent); } if (nsEventStatus_eConsumeNoDefault != status) { diff --git a/mozilla/layout/html/base/src/nsPresShell.cpp b/mozilla/layout/html/base/src/nsPresShell.cpp index 98dbaea88bc..7e3a2e3f113 100644 --- a/mozilla/layout/html/base/src/nsPresShell.cpp +++ b/mozilla/layout/html/base/src/nsPresShell.cpp @@ -696,6 +696,9 @@ public: nsGUIEvent* aEvent, nsEventStatus* aEventStatus, PRBool& aHandled); + NS_IMETHOD HandleDOMEventWithTarget(nsIContent* aTargetContent, + nsEvent* aEvent, + nsEventStatus* aStatus); NS_IMETHOD Scrolled(nsIView *aView); NS_IMETHOD ResizeReflow(nsIView *aView, nscoord aWidth, nscoord aHeight); @@ -3927,6 +3930,32 @@ PresShell::HandleEventInternal(nsEvent* aEvent, nsIView *aView, nsEventStatus* a return rv; } +// Dispatch event to content only (NOT full processing) +// See also HandleEventWithTarget which does full event processing. +NS_IMETHODIMP +PresShell::HandleDOMEventWithTarget(nsIContent* aTargetContent, nsEvent* aEvent, nsEventStatus* aStatus) +{ + nsresult ret; + + PushCurrentEventInfo(nsnull, aTargetContent); + + // Bug 41013: Check if the event should be dispatched to content. + // It's possible that we are in the middle of destroying the window + // and the js context is out of date. This check detects the case + // that caused a crash in bug 41013, but there may be a better way + // to handle this situation! + nsCOMPtr container; + ret = mPresContext->GetContainer(getter_AddRefs(container)); + if (NS_SUCCEEDED(ret) && container) { + + // Dispatch event to content + ret = aTargetContent->HandleDOMEvent(mPresContext, aEvent, nsnull, NS_EVENT_FLAG_INIT, aStatus); + } + + PopCurrentEventInfo(); + return NS_OK; +} + NS_IMETHODIMP PresShell::Scrolled(nsIView *aView) { diff --git a/mozilla/layout/html/forms/src/nsImageControlFrame.cpp b/mozilla/layout/html/forms/src/nsImageControlFrame.cpp index 189f2c95709..c114d2ba138 100644 --- a/mozilla/layout/html/forms/src/nsImageControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsImageControlFrame.cpp @@ -375,6 +375,8 @@ nsImageControlFrame::GetName(nsString* aResult) PRBool nsImageControlFrame::IsSuccessful(nsIFormControlFrame* aSubmitter) { + // Image control will only add it's value if it is clicked on. + // XXX Is this right? return (this == (aSubmitter)); } @@ -456,7 +458,11 @@ nsImageControlFrame::MouseClicked(nsIPresContext* aPresContext) event.eventStructType = NS_EVENT; event.message = NS_FORM_SUBMIT; if (nsnull != formContent) { - formContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); + nsCOMPtr shell; + nsresult result = aPresContext->GetShell(getter_AddRefs(shell)); + if (NS_SUCCEEDED(result) && shell) { + shell->HandleDOMEventWithTarget(formContent, &event, &status); + } NS_RELEASE(formContent); } if (nsEventStatus_eConsumeNoDefault != status) { diff --git a/mozilla/layout/xul/base/src/nsButtonBoxFrame.cpp b/mozilla/layout/xul/base/src/nsButtonBoxFrame.cpp index 1e01132beaa..48c5b70a6d1 100644 --- a/mozilla/layout/xul/base/src/nsButtonBoxFrame.cpp +++ b/mozilla/layout/xul/base/src/nsButtonBoxFrame.cpp @@ -29,6 +29,8 @@ #include "nsIDOMNodeList.h" #include "nsHTMLAtoms.h" #include "nsINameSpaceManager.h" +#include "nsIPresContext.h" +#include "nsIPresShell.h" // // NS_NewXULButtonFrame @@ -99,6 +101,8 @@ nsButtonBoxFrame::HandleEvent(nsIPresContext* aPresContext, void nsButtonBoxFrame::MouseClicked (nsIPresContext* aPresContext) { + nsresult rv = NS_OK; + // Execute the oncommand event handler. nsEventStatus status = nsEventStatus_eIgnore; nsMouseEvent event; @@ -110,5 +114,11 @@ nsButtonBoxFrame::MouseClicked (nsIPresContext* aPresContext) event.isMeta = PR_FALSE; event.clickCount = 0; event.widget = nsnull; - mContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); + + // Have the content handle the event, propagating it according to normal DOM rules. + nsCOMPtr shell; + rv = aPresContext->GetShell(getter_AddRefs(shell)); + if (NS_SUCCEEDED(rv) && shell) { + shell->HandleDOMEventWithTarget(mContent, &event, &status); + } } diff --git a/mozilla/layout/xul/base/src/nsMenuFrame.cpp b/mozilla/layout/xul/base/src/nsMenuFrame.cpp index f66b17187c1..9ce476c8cd7 100644 --- a/mozilla/layout/xul/base/src/nsMenuFrame.cpp +++ b/mozilla/layout/xul/base/src/nsMenuFrame.cpp @@ -1417,7 +1417,11 @@ nsMenuFrame::Execute() event.isMeta = PR_FALSE; event.clickCount = 0; event.widget = nsnull; - mContent->HandleDOMEvent(mPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); + nsCOMPtr shell; + nsresult result = mPresContext->GetShell(getter_AddRefs(shell)); + if (NS_SUCCEEDED(result) && shell) { + shell->HandleDOMEventWithTarget(mContent, &event, &status); + } // XXX HACK. Just gracefully exit if the node has been removed, e.g., window.close() // was executed. @@ -1452,9 +1456,16 @@ nsMenuFrame::OnCreate() GetMenuChildrenElement(getter_AddRefs(child)); nsresult rv; - if (child) - rv = child->HandleDOMEvent(mPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); - else rv = mContent->HandleDOMEvent(mPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); + nsCOMPtr shell; + rv = mPresContext->GetShell(getter_AddRefs(shell)); + if (NS_SUCCEEDED(rv) && shell) { + if (child) { + rv = shell->HandleDOMEventWithTarget(child, &event, &status); + } + else { + rv = shell->HandleDOMEventWithTarget(mContent, &event, &status); + } + } if ( NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault ) return PR_FALSE; @@ -1479,9 +1490,16 @@ nsMenuFrame::OnDestroy() GetMenuChildrenElement(getter_AddRefs(child)); nsresult rv; - if (child) - rv = child->HandleDOMEvent(mPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); - else rv = mContent->HandleDOMEvent(mPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); + nsCOMPtr shell; + rv = mPresContext->GetShell(getter_AddRefs(shell)); + if (NS_SUCCEEDED(rv) && shell) { + if (child) { + rv = shell->HandleDOMEventWithTarget(child, &event, &status); + } + else { + rv = shell->HandleDOMEventWithTarget(mContent, &event, &status); + } + } if ( NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault ) return PR_FALSE; diff --git a/mozilla/layout/xul/base/src/nsPopupSetFrame.cpp b/mozilla/layout/xul/base/src/nsPopupSetFrame.cpp index b4fac53e171..60ffee5e10c 100644 --- a/mozilla/layout/xul/base/src/nsPopupSetFrame.cpp +++ b/mozilla/layout/xul/base/src/nsPopupSetFrame.cpp @@ -608,7 +608,11 @@ nsPopupSetFrame::OnCreate(nsIContent* aPopupContent) event.widget = nsnull; if (aPopupContent) { - nsresult rv = aPopupContent->HandleDOMEvent(mPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); + nsCOMPtr shell; + nsresult rv = mPresContext->GetShell(getter_AddRefs(shell)); + if (NS_SUCCEEDED(rv) && shell) { + rv = shell->HandleDOMEventWithTarget(aPopupContent, &event, &status); + } if ( NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault ) return PR_FALSE; } @@ -634,7 +638,11 @@ nsPopupSetFrame::OnDestroy() GetActiveChildElement(getter_AddRefs(content)); if (content) { - nsresult rv = content->HandleDOMEvent(mPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); + nsCOMPtr shell; + nsresult rv = mPresContext->GetShell(getter_AddRefs(shell)); + if (NS_SUCCEEDED(rv) && shell) { + rv = shell->HandleDOMEventWithTarget(content, &event, &status); + } if ( NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault ) return PR_FALSE; } diff --git a/mozilla/layout/xul/base/src/nsTitledButtonFrame.cpp b/mozilla/layout/xul/base/src/nsTitledButtonFrame.cpp index 506e3221292..0e18bc77563 100644 --- a/mozilla/layout/xul/base/src/nsTitledButtonFrame.cpp +++ b/mozilla/layout/xul/base/src/nsTitledButtonFrame.cpp @@ -1271,7 +1271,11 @@ nsTitledButtonFrame::MouseClicked (nsIPresContext* aPresContext) event.isMeta = PR_FALSE; event.clickCount = 0; event.widget = nsnull; - mContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); + nsCOMPtr shell; + nsresult rv = aPresContext->GetShell(getter_AddRefs(shell)); + if (NS_SUCCEEDED(rv) && shell) { + shell->HandleDOMEventWithTarget(mContent, &event, &status); + } } //