Bug 1291457 - Call nsIWidget::SetIsArrowPanel for panels with type="arrow", and supply the computed value of the transform-origin CSS property as the panel's arrow tip location.
This does not work for the bookmarks popup because that popup is not type="arrow" and reimplements a bunch of arrowpanel stuff itself.
MozReview-Commit-ID: 2IG8YOPcNV7
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -5531,24 +5531,33 @@ nsDisplayTransform::nsDisplayTransform(n
* called off the main thread.
*/
/* static */ Point3D
nsDisplayTransform::GetDeltaToTransformOrigin(const nsIFrame* aFrame,
float aAppUnitsPerPixel,
const nsRect* aBoundsOverride)
{
NS_PRECONDITION(aFrame, "Can't get delta for a null frame!");
- NS_PRECONDITION(aFrame->IsTransformed() ||
- aFrame->BackfaceIsHidden() ||
- aFrame->Combines3DTransformWithAncestors(),
- "Shouldn't get a delta for an untransformed frame!");
-
- if (!aFrame->IsTransformed()) {
- return Point3D();
- }
+
+ // Disable this stuff because nsMenuPopupFrame::LayoutPopup wants to know the
+ // value of transform-origin for a frame that is not transformed.
+ // Disabling these checks is not right. What we should do instead is create
+ // a wrapper function that has these checks and is called in the existing
+ // places where this function used to be called, and then the inner function
+ // (without the checks) should be the one that is only called by
+ // nsMenuPopupFrame::LayoutPopup (and by the new wrapper function).
+
+ // NS_PRECONDITION(aFrame->IsTransformed() ||
+ // aFrame->BackfaceIsHidden() ||
+ // aFrame->Combines3DTransformWithAncestors(),
+ // "Shouldn't get a delta for an untransformed frame!");
+
+ // if (!aFrame->IsTransformed()) {
+ // return Point3D();
+ // }
/* For both of the coordinates, if the value of transform is a
* percentage, it's relative to the size of the frame. Otherwise, if it's
* a distance, it's already computed for us!
*/
const nsStyleDisplay* display = aFrame->StyleDisplay();
// We don't use aBoundsOverride for SVG since we need to account for
// refBox.X/Y(). This happens to work because ReflowSVG sets the frame's
--- a/layout/xul/nsMenuPopupFrame.cpp
+++ b/layout/xul/nsMenuPopupFrame.cpp
@@ -502,35 +502,44 @@ nsMenuPopupFrame::LayoutPopup(nsBoxLayou
SetPopupPosition(aAnchor, false, aSizedToPopup);
needCallback = true;
}
}
}
nsPresContext* pc = PresContext();
nsView* view = GetView();
+ nsIWidget* widget = view->GetWidget();
- if (sizeChanged) {
+ if (sizeChanged && widget) {
// If the size of the popup changed, apply any size constraints.
- nsIWidget* widget = view->GetWidget();
- if (widget) {
- SetSizeConstraints(pc, widget, minSize, maxSize);
- }
+ SetSizeConstraints(pc, widget, minSize, maxSize);
}
if (isOpen) {
nsViewManager* viewManager = view->GetViewManager();
nsRect rect = GetRect();
rect.x = rect.y = 0;
viewManager->ResizeView(view, rect);
if (mPopupState == ePopupOpening) {
mPopupState = ePopupVisible;
}
+ if (widget) {
+ if (mPopupType == ePopupTypePanel &&
+ mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+ nsGkAtoms::arrow, eIgnoreCase)) {
+ mozilla::gfx::Point3D transformOrigin = nsDisplayTransform::GetDeltaToTransformOrigin(this, pc->AppUnitsPerDevPixel(), nullptr);
+ widget->SetIsArrowPanel(true, LayoutDeviceIntPoint((int32_t)transformOrigin.x, (int32_t)transformOrigin.y));
+ } else {
+ widget->SetIsArrowPanel(false, LayoutDeviceIntPoint());
+ }
+ }
+
viewManager->SetViewVisibility(view, nsViewVisibility_kShow);
nsContainerFrame::SyncFrameViewProperties(pc, this, nullptr, view, 0);
}
// finally, if the popup just opened, send a popupshown event
if (mIsOpenChanged) {
mIsOpenChanged = false;