Bug 536625, use menupopup's move instead of widget's, r=roc

This commit is contained in:
Neil Deakin 2010-02-01 10:11:08 -05:00
parent 38e1e5bdc9
commit d3f3733d62
9 changed files with 182 additions and 12 deletions

View File

@ -762,7 +762,7 @@ nsMenuFrame::DoLayout(nsBoxLayoutState& aState)
// the popup. The flag that the popup checks in the HasOpenChanged
// method will get cleared in AdjustView which is called below.
if (IsOpen() && (sizeChanged || mPopupFrame->HasOpenChanged()))
mPopupFrame->SetPopupPosition(this);
mPopupFrame->SetPopupPosition(this, PR_FALSE);
// is the new size too small? Make sure we handle scrollbars correctly
nsIBox* child = mPopupFrame->GetChildBox();

View File

@ -905,7 +905,7 @@ nsMenuPopupFrame::FlipOrResize(nscoord& aScreenPoint, nscoord aSize,
}
nsresult
nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame)
nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame, PRBool aIsMove)
{
if (!mShouldAutoPosition)
return NS_OK;
@ -1045,6 +1045,12 @@ nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame)
vFlip = PR_TRUE;
}
// if a panel is being moved, don't flip it. But always do this for content
// shells, so that the popup doesn't extend outside the containing frame.
if (aIsMove && mPopupType == ePopupTypePanel && !mInContentShell) {
hFlip = vFlip = PR_FALSE;
}
nsRect screenRect = GetConstraintRect(anchorRect.TopLeft(), rootScreenRect);
// ensure that anchorRect is on screen
@ -1583,7 +1589,7 @@ nsMenuPopupFrame::MoveTo(PRInt32 aLeft, PRInt32 aTop, PRBool aUpdateAttrs)
mScreenXPos = aLeft;
mScreenYPos = aTop;
SetPopupPosition(nsnull);
SetPopupPosition(nsnull, PR_TRUE);
nsCOMPtr<nsIContent> popup = mContent;
if (aUpdateAttrs && (popup->HasAttr(kNameSpaceID_None, nsGkAtoms::left) ||

View File

@ -205,8 +205,9 @@ public:
// set the position of the popup either relative to the anchor aAnchorFrame
// (or the frame for mAnchorContent if aAnchorFrame is null) or at a specific
// point if a screen position (mScreenXPos and mScreenYPos) are set. The popup
// will be adjusted so that it is on screen.
nsresult SetPopupPosition(nsIFrame* aAnchorFrame);
// will be adjusted so that it is on screen. If aIsMove is true, then the popup
// is being moved, and should not be flipped.
nsresult SetPopupPosition(nsIFrame* aAnchorFrame, PRBool aIsMove);
PRBool HasGeneratedChildren() { return mGeneratedChildren; }
void SetGeneratedChildren() { mGeneratedChildren = PR_TRUE; }

View File

@ -183,7 +183,7 @@ nsPopupSetFrame::DoLayout(nsBoxLayoutState& aState)
prefSize = BoundsCheck(minSize, prefSize, maxSize);
popupChild->SetPreferredBounds(aState, nsRect(0,0,prefSize.width, prefSize.height));
popupChild->SetPopupPosition(nsnull);
popupChild->SetPopupPosition(nsnull, PR_FALSE);
// is the new size too small? Make sure we handle scrollbars correctly
nsIBox* child = popupChild->GetChildBox();
@ -218,7 +218,7 @@ nsPopupSetFrame::DoLayout(nsBoxLayoutState& aState)
// the size after layout was larger than the preferred size,
// so set the preferred size accordingly
popupChild->SetPreferredSize(popupChild->GetSize());
popupChild->SetPopupPosition(nsnull);
popupChild->SetPopupPosition(nsnull, PR_FALSE);
}
popupChild->AdjustView();
}

View File

@ -156,15 +156,15 @@ nsTitleBarFrame::HandleEvent(nsPresContext* aPresContext,
while (parent && parent->GetType() != nsGkAtoms::menuPopupFrame)
parent = parent->GetParent();
// if the titlebar is in a popup, move the popup's widget, otherwise
// if the titlebar is in a popup, move the popup frame, otherwise
// move the widget associated with the window
if (parent) {
nsMenuPopupFrame* menuPopupFrame = static_cast<nsMenuPopupFrame*>(parent);
nsCOMPtr<nsIWidget> widget;
(static_cast<nsMenuPopupFrame*>(parent))->
GetWidget(getter_AddRefs(widget));
menuPopupFrame->GetWidget(getter_AddRefs(widget));
nsIntRect bounds;
widget->GetScreenBounds(bounds);
widget->Move(bounds.x + nsMoveBy.x, bounds.y + nsMoveBy.y);
menuPopupFrame->MoveTo(bounds.x + nsMoveBy.x, bounds.y + nsMoveBy.y, PR_FALSE);
}
else {
nsIPresShell* presShell = aPresContext->PresShell();

View File

@ -269,7 +269,7 @@ nsXULPopupManager::AdjustPopupsOnWindowChange()
while (item) {
// if the auto positioning has been disabled, don't move the popup
if (item->Frame()->GetAutoPosition())
item->Frame()->SetPopupPosition(nsnull);
item->Frame()->SetPopupPosition(nsnull, PR_TRUE);
item = item->GetParent();
}
}

View File

@ -95,6 +95,8 @@ _TEST_FILES = findbar_window.xul \
dialog_dialogfocus.xul \
test_screenPersistence.xul \
window_screenPosSize.xul \
test_titlebar.xul \
window_titlebar.xul \
$(NULL)
# test_panel_focus.xul won't work if the Full Keyboard Access preference is set to

View File

@ -0,0 +1,37 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<!--
XUL Widget Test for the titlebar element and window dragging
-->
<window title="Titlebar" width="200" height="200"
onload="setTimeout(test_titlebar, 0);"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"/>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
SimpleTest.waitForExplicitFinish();
function test_titlebar()
{
window.open("window_titlebar.xul", "_blank", "chrome,left=200,top=200");
}
function done(testWindow)
{
testWindow.close();
SimpleTest.finish();
}
]]>
</script>
</window>

View File

@ -0,0 +1,124 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<!--
XUL Widget Test for the titlebar element and window dragging
-->
<window title="Titlebar" width="200" height="200"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
<titlebar id="titlebar">
<label id="label" value="Titlebar"/>
</titlebar>
<panel id="panel" onpopupshown="popupshown()" onpopuphidden="popuphidden()">
<titlebar>
<label id="panellabel" value="Titlebar"/>
</titlebar>
</panel>
<button id="button" label="OK"/>
<statusbar id="statusbar">
<statusbarpanel>
<label id="statuslabel" value="Status"/>
<label id="statuslabelnodrag" value="No Drag" onmousedown="event.preventDefault()"/>
</statusbarpanel>
</statusbar>
<script>
<![CDATA[
var SimpleTest = window.opener.wrappedJSObject.SimpleTest;
SimpleTest.waitForFocus(test_titlebar, window);
function test_titlebar()
{
var titlebar = document.getElementById("titlebar");
var label = document.getElementById("label");
var oldx, oldy;
// on Mac, the window can also be moved with the statusbar
if (navigator.platform.indexOf("Mac") >= 0) {
var statuslabel = document.getElementById("statuslabel");
var statuslabelnodrag = document.getElementById("statuslabelnodrag");
oldx = window.screenX;
oldy = window.screenY;
synthesizeMouse(statuslabel, 2, 2, { type: "mousedown" });
synthesizeMouse(statuslabel, 22, 22, { type: "mousemove" });
SimpleTest.is(window.screenX, oldx + 20, "move window with statusbar horizontal");
SimpleTest.is(window.screenY, oldy + 20, "move window with statusbar vertical");
synthesizeMouse(statuslabel, 22, 22, { type: "mouseup" });
// event was cancelled so the drag should not have occurred
synthesizeMouse(statuslabelnodrag, 2, 2, { type: "mousedown" });
synthesizeMouse(statuslabelnodrag, 22, 22, { type: "mousemove" });
SimpleTest.is(window.screenX, oldx + 20, "move window with statusbar cancelled mousedown horizontal");
SimpleTest.is(window.screenY, oldy + 20, "move window with statusbar cancelled mousedown vertical");
synthesizeMouse(statuslabelnodrag, 22, 22, { type: "mouseup" });
}
oldx = window.screenX;
oldy = window.screenY;
var target;
var mousedownListener = function (event) target = event.originalTarget;
window.addEventListener("mousedown", mousedownListener, false);
synthesizeMouse(label, 2, 2, { type: "mousedown" });
SimpleTest.is(target, titlebar, "movedown on titlebar");
synthesizeMouse(label, 22, 22, { type: "mousemove" });
SimpleTest.is(window.screenX, oldx + 20, "move window horizontal");
SimpleTest.is(window.screenY, oldy + 20, "move window vertical");
synthesizeMouse(label, 22, 22, { type: "mouseup" });
// with allowEvents set to true, the mouse should target the label instead
// and not move the window
titlebar.allowEvents = true;
synthesizeMouse(label, 2, 2, { type: "mousedown" });
SimpleTest.is(target, label, "movedown on titlebar with allowevents");
synthesizeMouse(label, 22, 22, { type: "mousemove" });
SimpleTest.is(window.screenX, oldx + 20, "mouse on label move window horizontal");
SimpleTest.is(window.screenY, oldy + 20, "mouse on label move window vertical");
synthesizeMouse(label, 22, 22, { type: "mouseup" });
window.removeEventListener("mousedown", mousedownListener, false);
document.getElementById("panel").openPopupAtScreen(window.screenX + 50, window.screenY + 60, false);
}
function popupshown()
{
var panellabel = document.getElementById("panellabel");
var panel = document.getElementById("panel");
var oldrect = panel.getBoundingClientRect();
synthesizeMouse(panellabel, 2, 2, { type: "mousedown" });
synthesizeMouse(panellabel, 22, 22, { type: "mousemove" });
var newrect = panel.getBoundingClientRect();
SimpleTest.is(newrect.left, oldrect.left + 20, "move popup horizontal");
SimpleTest.is(newrect.top, oldrect.top + 20, "move popup vertical");
synthesizeMouse(panellabel, 22, 22, { type: "mouseup" });
synthesizeMouse(document.getElementById("button"), 5, 5, { type: "mousemove" });
SimpleTest.is(newrect.left, oldrect.left + 20, "popup horizontal after mouse on button");
SimpleTest.is(newrect.top, oldrect.top + 20, "popup vertical after mouse on button");
panel.hidePopup();
}
function popuphidden()
{
window.opener.wrappedJSObject.done(window);
}
]]>
</script>
</window>