Bug 1428701 - (Part 1) Build the dropdown frame as the top layer frame in the viewport frame draft
authorKuoE0 <kuoe0.tw@gmail.com>
Mon, 08 Jan 2018 17:20:33 +0800
changeset 720311 b1e061da56935d9b223c75484e8bbdbd35be9955
parent 718895 fe9e3ef4debf4fdcdaaeb6b278c778b83cef64a6
child 720312 c4ec255ad8da49f08ec65b93a6690913b154feaf
push id95503
push userbmo:kuoe0@mozilla.com
push dateMon, 15 Jan 2018 07:53:49 +0000
bugs1428701
milestone59.0a1
Bug 1428701 - (Part 1) Build the dropdown frame as the top layer frame in the viewport frame When a dropdown frame is toggled to drop down, we set it to its parent, the canvas frame. If it's toggled to roll up, we clear the dropdown frame in the canvas frame. Then we build the display lists of the dropdown frame that should be dropped down after building the other top layer contents to make sure that the dropdown frame would be on the top of all contents. MozReview-Commit-ID: AouhRY1ma13
layout/generic/ViewportFrame.cpp
layout/generic/nsCanvasFrame.cpp
layout/generic/nsCanvasFrame.h
--- a/layout/generic/ViewportFrame.cpp
+++ b/layout/generic/ViewportFrame.cpp
@@ -177,16 +177,21 @@ ViewportFrame::BuildDisplayListForTopLay
         BuildDisplayListForTopLayerFrame(aBuilder, backdropFrame, aList);
       }
       BuildDisplayListForTopLayerFrame(aBuilder, frame, aList);
     }
   }
 
   nsIPresShell* shell = PresShell();
   if (nsCanvasFrame* canvasFrame = shell->GetCanvasFrame()) {
+    // Build display items for the dropped-down menu
+    if (nsIFrame* dropdownFrame = canvasFrame->GetDropdownFrame()) {
+      BuildDisplayListForTopLayerFrame(aBuilder, dropdownFrame, aList);
+    }
+
     if (Element* container = canvasFrame->GetCustomContentContainer()) {
       if (nsIFrame* frame = container->GetPrimaryFrame()) {
         BuildDisplayListForTopLayerFrame(aBuilder, frame, aList);
       }
     }
   }
 }
 
--- a/layout/generic/nsCanvasFrame.cpp
+++ b/layout/generic/nsCanvasFrame.cpp
@@ -251,16 +251,25 @@ nsRect nsCanvasFrame::CanvasArea() const
   if (scrollableFrame) {
     nsRect portRect = scrollableFrame->GetScrollPortRect();
     result.UnionRect(result, nsRect(nsPoint(0, 0), portRect.Size()));
   }
   return result;
 }
 
 void
+nsCanvasFrame::SetDropdownFrame(nsIFrame* aDropdownFrame) {
+  if (aDropdownFrame) {
+    MOZ_ASSERT(aDropdownFrame->IsListControlFrame(),
+               "Only nsListControlFrame can be dropped down.");
+  }
+  mDropdownFrame = aDropdownFrame;
+}
+
+void
 nsDisplayCanvasBackgroundColor::Paint(nsDisplayListBuilder* aBuilder,
                                       gfxContext* aCtx)
 {
   nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
   nsPoint offset = ToReferenceFrame();
   nsRect bgClipRect = frame->CanvasArea() + offset;
   if (NS_GET_A(mColor) > 0) {
     DrawTarget* drawTarget = aCtx->GetDrawTarget();
--- a/layout/generic/nsCanvasFrame.h
+++ b/layout/generic/nsCanvasFrame.h
@@ -33,16 +33,17 @@ class nsCanvasFrame final : public nsCon
                             public nsIScrollPositionListener,
                             public nsIAnonymousContentCreator
 {
 public:
   explicit nsCanvasFrame(nsStyleContext* aContext)
     : nsContainerFrame(aContext, kClassID)
     , mDoPaintFocus(false)
     , mAddedScrollPositionListener(false)
+    , mDropdownFrame(nullptr)
   {}
 
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS(nsCanvasFrame)
 
 
   virtual void DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData) override;
 
@@ -108,26 +109,33 @@ public:
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
   virtual nsresult GetContentForEvent(mozilla::WidgetEvent* aEvent,
                                       nsIContent** aContent) override;
 
   nsRect CanvasArea() const;
 
+  // The frame should be dropped down
+  nsIFrame* GetDropdownFrame() const { return mDropdownFrame; }
+  void SetDropdownFrame(nsIFrame* aDropDownFrame);
+
 protected:
   // Utility function to propagate the WritingMode from our first child to
   // 'this' and all its ancestors.
   void MaybePropagateRootElementWritingMode();
 
   // Data members
   bool                      mDoPaintFocus;
   bool                      mAddedScrollPositionListener;
 
   nsCOMPtr<mozilla::dom::Element> mCustomContentContainer;
+
+private:
+  nsIFrame* mDropdownFrame;
 };
 
 /**
  * Override nsDisplayBackground methods so that we pass aBGClipRect to
  * PaintBackground, covering the whole overflow area.
  * We can also paint an "extra background color" behind the normal
  * background.
  */