зеркало из https://github.com/mozilla/pjs.git
Bug 387659, popup coordinates are not set within popupshowing event,r=eli,sr=bz
This commit is contained in:
Родитель
5a29248630
Коммит
6112095836
|
@ -46,6 +46,7 @@
|
||||||
#include "nsIRollupListener.h"
|
#include "nsIRollupListener.h"
|
||||||
#include "nsIMenuRollup.h"
|
#include "nsIMenuRollup.h"
|
||||||
#include "nsIDOMKeyListener.h"
|
#include "nsIDOMKeyListener.h"
|
||||||
|
#include "nsPoint.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
#include "nsITimer.h"
|
#include "nsITimer.h"
|
||||||
|
@ -359,8 +360,9 @@ public:
|
||||||
// This is used by the implementation of nsIDOMXULDocument::GetPopupRangeParent
|
// This is used by the implementation of nsIDOMXULDocument::GetPopupRangeParent
|
||||||
// and nsIDOMXULDocument::GetPopupRangeOffset.
|
// and nsIDOMXULDocument::GetPopupRangeOffset.
|
||||||
void GetMouseLocation(nsIDOMNode** aNode, PRInt32* aOffset);
|
void GetMouseLocation(nsIDOMNode** aNode, PRInt32* aOffset);
|
||||||
// set the mouse event that was used to activate the next popup to be opened.
|
// set the mouse event that was used to activate the next popup, specified by
|
||||||
void SetMouseLocation(nsIDOMEvent* aEvent);
|
// aPopup, to be opened.
|
||||||
|
void SetMouseLocation(nsIDOMEvent* aEvent, nsIContent* aPopup);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a <menu> given its content node. If aSelectFirstItem is
|
* Open a <menu> given its content node. If aSelectFirstItem is
|
||||||
|
@ -626,6 +628,7 @@ protected:
|
||||||
// range parent and offset set in SetMouseLocation
|
// range parent and offset set in SetMouseLocation
|
||||||
nsCOMPtr<nsIDOMNode> mRangeParent;
|
nsCOMPtr<nsIDOMNode> mRangeParent;
|
||||||
PRInt32 mRangeOffset;
|
PRInt32 mRangeOffset;
|
||||||
|
nsPoint mCachedMousePoint;
|
||||||
|
|
||||||
// set to the currently active menu bar, if any
|
// set to the currently active menu bar, if any
|
||||||
nsMenuBarFrame* mActiveMenuBar;
|
nsMenuBarFrame* mActiveMenuBar;
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#include "nsIDOMDocument.h"
|
#include "nsIDOMDocument.h"
|
||||||
#include "nsIDOMNSEvent.h"
|
#include "nsIDOMNSEvent.h"
|
||||||
#include "nsIDOMNSUIEvent.h"
|
#include "nsIDOMNSUIEvent.h"
|
||||||
|
#include "nsIPrivateDOMEvent.h"
|
||||||
#include "nsEventDispatcher.h"
|
#include "nsEventDispatcher.h"
|
||||||
#include "nsCSSFrameConstructor.h"
|
#include "nsCSSFrameConstructor.h"
|
||||||
#include "nsLayoutUtils.h"
|
#include "nsLayoutUtils.h"
|
||||||
|
@ -236,13 +237,40 @@ nsXULPopupManager::GetMouseLocation(nsIDOMNode** aNode, PRInt32* aOffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsXULPopupManager::SetMouseLocation(nsIDOMEvent* aEvent)
|
nsXULPopupManager::SetMouseLocation(nsIDOMEvent* aEvent, nsIContent* aPopup)
|
||||||
{
|
{
|
||||||
|
mCachedMousePoint = nsPoint(0, 0);
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMNSUIEvent> uiEvent = do_QueryInterface(aEvent);
|
nsCOMPtr<nsIDOMNSUIEvent> uiEvent = do_QueryInterface(aEvent);
|
||||||
NS_ASSERTION(uiEvent, "Expected an nsIDOMNSUIEvent");
|
NS_ASSERTION(!aEvent || uiEvent, "Expected an nsIDOMNSUIEvent");
|
||||||
if (uiEvent) {
|
if (uiEvent) {
|
||||||
uiEvent->GetRangeParent(getter_AddRefs(mRangeParent));
|
uiEvent->GetRangeParent(getter_AddRefs(mRangeParent));
|
||||||
uiEvent->GetRangeOffset(&mRangeOffset);
|
uiEvent->GetRangeOffset(&mRangeOffset);
|
||||||
|
|
||||||
|
// get the event coordinates relative to the root frame of the document
|
||||||
|
// containing the popup.
|
||||||
|
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aEvent));
|
||||||
|
if (privateEvent) {
|
||||||
|
NS_ASSERTION(aPopup, "Expected a popup node");
|
||||||
|
nsEvent* event;
|
||||||
|
nsresult rv = privateEvent->GetInternalNSEvent(&event);
|
||||||
|
if (NS_SUCCEEDED(rv) && event) {
|
||||||
|
nsIDocument* doc = aPopup->GetCurrentDoc();
|
||||||
|
if (doc) {
|
||||||
|
nsIPresShell* presShell = doc->GetPrimaryShell();
|
||||||
|
if (presShell) {
|
||||||
|
nsPresContext* presContext = presShell->GetPresContext();
|
||||||
|
nsIFrame* rootFrame = presShell->GetRootFrame();
|
||||||
|
if (rootFrame && presContext) {
|
||||||
|
nsPoint pnt =
|
||||||
|
nsLayoutUtils::GetEventCoordinatesRelativeTo(event, rootFrame);
|
||||||
|
mCachedMousePoint = nsPoint(presContext->AppUnitsToDevPixels(pnt.x),
|
||||||
|
presContext->AppUnitsToDevPixels(pnt.y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mRangeParent = nsnull;
|
mRangeParent = nsnull;
|
||||||
|
@ -293,6 +321,7 @@ nsXULPopupManager::ShowMenu(nsIContent *aMenu,
|
||||||
popupFrame->InitializePopup(aMenu, position, 0, 0, PR_TRUE);
|
popupFrame->InitializePopup(aMenu, position, 0, 0, PR_TRUE);
|
||||||
|
|
||||||
if (aAsynchronous) {
|
if (aAsynchronous) {
|
||||||
|
SetMouseLocation(nsnull, nsnull);
|
||||||
nsCOMPtr<nsIRunnable> event =
|
nsCOMPtr<nsIRunnable> event =
|
||||||
new nsXULPopupShowingEvent(popupFrame->GetContent(), aMenu,
|
new nsXULPopupShowingEvent(popupFrame->GetContent(), aMenu,
|
||||||
parentIsContextMenu, aSelectFirstItem);
|
parentIsContextMenu, aSelectFirstItem);
|
||||||
|
@ -539,7 +568,7 @@ nsXULPopupManager::HidePopupCallback(nsIContent* aPopup,
|
||||||
|
|
||||||
// send the popuphidden event synchronously. This event has no default behaviour.
|
// send the popuphidden event synchronously. This event has no default behaviour.
|
||||||
nsEventStatus status = nsEventStatus_eIgnore;
|
nsEventStatus status = nsEventStatus_eIgnore;
|
||||||
nsEvent event(PR_TRUE, NS_XUL_POPUP_HIDDEN);
|
nsMouseEvent event(PR_TRUE, NS_XUL_POPUP_HIDDEN, nsnull, nsMouseEvent::eReal);
|
||||||
nsEventDispatcher::Dispatch(aPopup, aPopupFrame->PresContext(),
|
nsEventDispatcher::Dispatch(aPopup, aPopupFrame->PresContext(),
|
||||||
&event, nsnull, &status);
|
&event, nsnull, &status);
|
||||||
|
|
||||||
|
@ -678,8 +707,13 @@ nsXULPopupManager::FirePopupShowingEvent(nsIContent* aPopup,
|
||||||
// is where those details would be retrieved. This removes the need for
|
// is where those details would be retrieved. This removes the need for
|
||||||
// all the globals people keep adding to nsIDOMXULDocument.
|
// all the globals people keep adding to nsIDOMXULDocument.
|
||||||
nsEventStatus status = nsEventStatus_eIgnore;
|
nsEventStatus status = nsEventStatus_eIgnore;
|
||||||
nsEvent event(PR_TRUE, NS_XUL_POPUP_SHOWING);
|
nsMouseEvent event(PR_TRUE, NS_XUL_POPUP_SHOWING, nsnull, nsMouseEvent::eReal);
|
||||||
|
nsPoint pnt;
|
||||||
|
event.widget = presShell->GetRootFrame()->
|
||||||
|
GetClosestView()->GetNearestWidget(&pnt);
|
||||||
|
event.refPoint = mCachedMousePoint;
|
||||||
nsEventDispatcher::Dispatch(aPopup, aPresContext, &event, nsnull, &status);
|
nsEventDispatcher::Dispatch(aPopup, aPresContext, &event, nsnull, &status);
|
||||||
|
mCachedMousePoint = nsPoint(0, 0);
|
||||||
|
|
||||||
// it is common to append content to the menu during the popupshowing event.
|
// it is common to append content to the menu during the popupshowing event.
|
||||||
// Flush the notifications so that the frames are up to date before showing
|
// Flush the notifications so that the frames are up to date before showing
|
||||||
|
@ -712,7 +746,7 @@ nsXULPopupManager::FirePopupHidingEvent(nsIContent* aPopup,
|
||||||
nsCOMPtr<nsIPresShell> presShell = aPresContext->PresShell();
|
nsCOMPtr<nsIPresShell> presShell = aPresContext->PresShell();
|
||||||
|
|
||||||
nsEventStatus status = nsEventStatus_eIgnore;
|
nsEventStatus status = nsEventStatus_eIgnore;
|
||||||
nsEvent event(PR_TRUE, NS_XUL_POPUP_HIDING);
|
nsMouseEvent event(PR_TRUE, NS_XUL_POPUP_HIDING, nsnull, nsMouseEvent::eReal);
|
||||||
nsEventDispatcher::Dispatch(aPopup, aPresContext, &event, nsnull, &status);
|
nsEventDispatcher::Dispatch(aPopup, aPresContext, &event, nsnull, &status);
|
||||||
|
|
||||||
// get frame again in case it went away
|
// get frame again in case it went away
|
||||||
|
|
|
@ -48,6 +48,7 @@ _TEST_FILES = test_bug360220.xul \
|
||||||
test_bug359754.xul \
|
test_bug359754.xul \
|
||||||
test_bug365773.xul \
|
test_bug365773.xul \
|
||||||
test_colorpicker_popup.xul \
|
test_colorpicker_popup.xul \
|
||||||
|
test_popup_coords.xul \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
libs:: $(_TEST_FILES)
|
libs:: $(_TEST_FILES)
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||||
|
<?xml-stylesheet href="/tests/SimpleTest/test.css" type="text/css"?>
|
||||||
|
|
||||||
|
<window title="Popup Coordinate Tests"
|
||||||
|
onload="setTimeout(openThePopup, 0, 'outer');"
|
||||||
|
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||||
|
|
||||||
|
<title>Popup Tests</title>
|
||||||
|
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||||
|
|
||||||
|
<deck style="margin-top: 5px; padding-top: 5px;">
|
||||||
|
<label id="outer" popup="outerpopup" value="Popup"/>
|
||||||
|
</deck>
|
||||||
|
|
||||||
|
<panel id="outerpopup"
|
||||||
|
onpopupshowing="popupShowingEventOccured(event);"
|
||||||
|
onpopupshown="eventOccured(event); openThePopup('inner')"
|
||||||
|
onpopuphiding="eventOccured(event);"
|
||||||
|
onpopuphidden="eventOccured(event); SimpleTest.finish();">
|
||||||
|
<button id="item1" label="First"/>
|
||||||
|
<label id="inner" value="Second" popup="innerpopup"/>
|
||||||
|
<button id="item2" label="Third"/>
|
||||||
|
</panel>
|
||||||
|
|
||||||
|
<menupopup id="innerpopup"
|
||||||
|
onpopupshowing="popupShowingEventOccured(event);"
|
||||||
|
onpopupshown="eventOccured(event); event.target.hidePopup();"
|
||||||
|
onpopuphiding="eventOccured(event);"
|
||||||
|
onpopuphidden="eventOccured(event); document.getElementById('outerpopup').hidePopup();">
|
||||||
|
<menuitem id="inner1" label="Inner First"/>
|
||||||
|
<menuitem id="inner2" label="Inner Second"/>
|
||||||
|
</menupopup>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
function openThePopup(id)
|
||||||
|
{
|
||||||
|
if (id == "inner")
|
||||||
|
document.getElementById("item1").focus();
|
||||||
|
|
||||||
|
var trigger = document.getElementById(id);
|
||||||
|
synthesizeMouse(trigger, 4, 5, { });
|
||||||
|
}
|
||||||
|
|
||||||
|
function eventOccured(event)
|
||||||
|
{
|
||||||
|
var testname = event.type + " on " + event.target.id + " ";
|
||||||
|
ok(event instanceof MouseEvent, testname + "is a mouse event");
|
||||||
|
is(event.clientX, 0, testname + "clientX");
|
||||||
|
is(event.clientY, 0, testname + "clientY");
|
||||||
|
is(event.rangeParent, null, testname + "rangeParent");
|
||||||
|
is(event.rangeOffset, 0, testname + "rangeOffset");
|
||||||
|
}
|
||||||
|
|
||||||
|
function popupShowingEventOccured(event)
|
||||||
|
{
|
||||||
|
// the popupshowing event should have the event coordinates and
|
||||||
|
// range position filled in.
|
||||||
|
var testname = "popupshowing on " + event.target.id + " ";
|
||||||
|
ok(event instanceof MouseEvent, testname + "is a mouse event");
|
||||||
|
|
||||||
|
var trigger = document.getElementById(event.target.id == "outerpopup" ? "outer" : "inner");
|
||||||
|
var rect = trigger.getBoundingClientRect();
|
||||||
|
is(event.clientX, Math.round(rect.left) + 4, testname + "clientX");
|
||||||
|
is(event.clientY, Math.round(rect.top) + 5, testname + "clientY");
|
||||||
|
// rangeOffset should be just after the trigger element. As rangeOffset
|
||||||
|
// considers the zeroth position to be before the first element, the value
|
||||||
|
// should be one higher than its index within its parent.
|
||||||
|
is(event.rangeParent, trigger.parentNode, testname + "rangeParent");
|
||||||
|
is(event.rangeOffset, Array.indexOf(trigger.parentNode.childNodes, trigger) + 1, testname + "rangeOffset");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<p id="display">
|
||||||
|
</p>
|
||||||
|
<div id="content" style="display: none">
|
||||||
|
</div>
|
||||||
|
<pre id="test">
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</window>
|
Загрузка…
Ссылка в новой задаче