Bug 599938. Show select drop downs in the correct location if they are being translated by CSS transforms. r=roc

This commit is contained in:
Timothy Nikkel 2011-09-18 13:16:47 -05:00
Родитель a724f86af6
Коммит f7f6b0b885
2 изменённых файлов: 50 добавлений и 2 удалений

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

@ -544,6 +544,43 @@ nsComboboxControlFrame::ReflowDropdown(nsPresContext* aPresContext,
return rv;
}
nsPoint
nsComboboxControlFrame::GetCSSTransformTranslate()
{
nsIFrame* frame = this;
PRBool is3DTransform = PR_FALSE;
gfxMatrix transform;
while (frame) {
nsIFrame* parent = nsnull;
gfx3DMatrix ctm = frame->GetTransformMatrix(&parent);
gfxMatrix matrix;
if (ctm.Is2D(&matrix)) {
transform = transform * matrix;
} else {
is3DTransform = PR_TRUE;
break;
}
frame = parent;
}
nsPoint translation;
if (!is3DTransform && !transform.HasNonTranslation()) {
nsPresContext* pc = PresContext();
gfxPoint pixelTranslation = transform.GetTranslation();
PRInt32 apd = pc->AppUnitsPerDevPixel();
translation.x = NSFloatPixelsToAppUnits(float(pixelTranslation.x), apd);
translation.y = NSFloatPixelsToAppUnits(float(pixelTranslation.y), apd);
// To get the translation introduced only by transforms we subtract the
// regular non-transform translation.
nsRootPresContext* rootPC = pc->GetRootPresContext();
if (rootPC) {
translation -= GetOffsetToCrossDoc(rootPC->PresShell()->GetRootFrame());
} else {
translation.x = translation.y = 0;
}
}
return translation;
}
void
nsComboboxControlFrame::AbsolutelyPositionDropDown()
{
@ -558,6 +595,11 @@ nsComboboxControlFrame::AbsolutelyPositionDropDown()
// The approach, taken here is to get use the absolute position of the display frame and use it's location
// to determine if the dropdown will go offscreen.
// Normal frame geometry (eg GetOffsetTo, mRect) doesn't include transforms.
// In the special case that our transform is only a 2D translation we
// introduce this hack so that the dropdown will show up in the right place.
nsPoint translation = GetCSSTransformTranslation();
// Use the height calculated for the area frame so it includes both
// the display and button heights.
nscoord dropdownYOffset = GetRect().height;
@ -566,7 +608,7 @@ nsComboboxControlFrame::AbsolutelyPositionDropDown()
nsRect screen = nsFormControlFrame::GetUsableScreenRect(PresContext());
// Check to see if the drop-down list will go offscreen
if (GetScreenRectInAppUnits().YMost() + dropdownSize.height > screen.YMost()) {
if ((GetScreenRectInAppUnits() + translation).YMost() + dropdownSize.height > screen.YMost()) {
// move the dropdown list up
dropdownYOffset = - (dropdownSize.height);
}
@ -581,7 +623,7 @@ nsComboboxControlFrame::AbsolutelyPositionDropDown()
}
dropdownPosition.y = dropdownYOffset;
mDropdownFrame->SetPosition(dropdownPosition);
mDropdownFrame->SetPosition(dropdownPosition + translation);
}
//----------------------------------------------------------

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

@ -254,6 +254,12 @@ protected:
void HandleRedisplayTextEvent();
void ActuallyDisplayText(PRBool aNotify);
private:
// If our total transform to the root frame of the root document is only a 2d
// translation then return that translation, otherwise returns (0,0).
nsPoint GetCSSTransformTranslation();
protected:
nsFrameList mPopupFrames; // additional named child list
nsCOMPtr<nsIContent> mDisplayContent; // Anonymous content used to display the current selection
nsCOMPtr<nsIContent> mButtonContent; // Anonymous content for the button