Bug 1285474: stylo: Partially implement some restyling APIs to take rid of some gecko-only code paths. draft
authorEmilio Cobos Álvarez <ecoal95@gmail.com>
Fri, 08 Jul 2016 00:08:46 -0700
changeset 385690 0fd459f1038e6d7009ac3933d0f033d2c1f419c2
parent 385689 c6686b25b19d9eb2403a7da0175a98f1f2f2e698
child 385752 342d21b89dc137a2998925621a63ef1373539601
push id22581
push userbmo:ealvarez@mozilla.com
push dateSat, 09 Jul 2016 03:09:37 +0000
bugs1285474
milestone50.0a1
Bug 1285474: stylo: Partially implement some restyling APIs to take rid of some gecko-only code paths. MozReview-Commit-ID: Jf59l1asuZ6
layout/base/RestyleManager.h
layout/base/RestyleManagerHandle.h
layout/base/RestyleManagerHandleInlines.h
layout/base/ServoRestyleManager.cpp
layout/base/ServoRestyleManager.h
layout/base/nsPresShell.cpp
layout/base/nsRefreshDriver.cpp
--- a/layout/base/RestyleManager.h
+++ b/layout/base/RestyleManager.h
@@ -119,16 +119,20 @@ public:
 
   // Whether rule matching should skip styles associated with animation
   bool SkipAnimationRules() const { return mSkipAnimationRules; }
 
   void SetSkipAnimationRules(bool aSkipAnimationRules) {
     mSkipAnimationRules = aSkipAnimationRules;
   }
 
+  void SetObservingRefreshDriver(bool aObserving) {
+      mObservingRefreshDriver = aObserving;
+  }
+
   /**
    * Reparent the style contexts of this frame subtree.  The parent frame of
    * aFrame must be changed to the new parent before this function is called;
    * the new parent style context will be automatically computed based on the
    * new position in the frame tree.
    *
    * @param aFrame the root of the subtree to reparent.  Must not be null.
    */
--- a/layout/base/RestyleManagerHandle.h
+++ b/layout/base/RestyleManagerHandle.h
@@ -130,16 +130,18 @@ public:
     inline void AttributeChanged(dom::Element* aElement,
                                  int32_t aNameSpaceID,
                                  nsIAtom* aAttribute,
                                  int32_t aModType,
                                  const nsAttrValue* aOldValue);
     inline nsresult ReparentStyleContext(nsIFrame* aFrame);
     inline bool HasPendingRestyles();
     inline uint64_t GetRestyleGeneration() const;
+    inline uint32_t GetHoverGeneration() const;
+    inline void SetObservingRefreshDriver(bool aObserving);
 
   private:
     // Stores a pointer to an RestyleManager or a ServoRestyleManager.  The least
     // significant bit is 0 for the former, 1 for the latter.  This is
     // valid as the least significant bit will never be used for a pointer
     // value on platforms we care about.
     uintptr_t mValue;
   };
--- a/layout/base/RestyleManagerHandleInlines.h
+++ b/layout/base/RestyleManagerHandleInlines.h
@@ -138,14 +138,27 @@ RestyleManagerHandle::Ptr::HasPendingRes
 }
 
 uint64_t
 RestyleManagerHandle::Ptr::GetRestyleGeneration() const
 {
   FORWARD(GetRestyleGeneration, ());
 }
 
+uint32_t
+RestyleManagerHandle::Ptr::GetHoverGeneration() const
+{
+  FORWARD(GetHoverGeneration, ());
+}
+
+void
+RestyleManagerHandle::Ptr::SetObservingRefreshDriver(bool aObserving)
+{
+  FORWARD(SetObservingRefreshDriver, (aObserving));
+}
+
+
 } // namespace mozilla
 
 #undef FORWARD
 #undef FORWARD_CONCRETE
 
 #endif // mozilla_RestyleManagerHandleInlines_h
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -1,37 +1,60 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ServoRestyleManager.h"
+#include "mozilla/ServoStyleSet.h"
 
 using namespace mozilla::dom;
 
 namespace mozilla {
 
-ServoRestyleManager::ServoRestyleManager()
-  : mRestyleGeneration(1)
+ServoRestyleManager::ServoRestyleManager(nsPresContext* aPresContext)
+  : mRestyleGeneration(1),
+    mHoverGeneration(0),
+    mPresContext(aPresContext),
+    mObservingRefreshDriver(false)
 {
 }
 
 void
 ServoRestyleManager::Disconnect()
 {
   NS_ERROR("stylo: ServoRestyleManager::Disconnect not implemented");
 }
 
 void
 ServoRestyleManager::PostRestyleEvent(Element* aElement,
                                       nsRestyleHint aRestyleHint,
                                       nsChangeHint aMinChangeHint)
 {
-  NS_ERROR("stylo: ServoRestyleManager::PostRestyleEvent not implemented");
+  if (MOZ_UNLIKELY(!mPresContext) ||
+      MOZ_UNLIKELY(mPresContext->PresShell()->IsDestroying())) {
+    return;
+  }
+
+  nsIPresShell* presShell = mPresContext->PresShell();
+  if (!mObservingRefreshDriver) {
+    mObservingRefreshDriver = mPresContext->RefreshDriver()->
+      AddStyleFlushObserver(presShell);
+  }
+
+  aElement->SetIsDirtyForServo();
+  nsINode* cur = aElement;
+  while ((cur = cur->GetParentNode())) {
+    if (cur->HasDirtyDescendantsForServo())
+      break;
+    cur->SetHasDirtyDescendantsForServo();
+  }
+
+  presShell->GetDocument()->SetNeedStyleFlush();
 }
 
 void
 ServoRestyleManager::PostRestyleEventForLazyConstruction()
 {
   NS_ERROR("stylo: ServoRestyleManager::PostRestyleEventForLazyConstruction not implemented");
 }
 
@@ -77,17 +100,33 @@ ServoRestyleManager::RestyleForRemove(El
 {
   NS_ERROR("stylo: ServoRestyleManager::RestyleForRemove not implemented");
 }
 
 nsresult
 ServoRestyleManager::ContentStateChanged(nsIContent* aContent,
                                          EventStates aStateMask)
 {
-  NS_ERROR("stylo: ServoRestyleManager::ContentStateChanged not implemented");
+  if (!aContent->IsElement()) {
+    return NS_OK;
+  }
+
+  Element* aElement = aContent->AsElement();
+  nsIFrame* primaryFrame = aElement->GetPrimaryFrame();
+  if (primaryFrame) {
+    primaryFrame->ContentStatesChanged(aStateMask);
+  }
+
+  if (aStateMask.HasState(NS_EVENT_STATE_HOVER)) {
+    ++mHoverGeneration;
+  }
+
+  // TODO(emilio): There's a bunch more logic in the normal RestyleManager that
+  // we need to implement.
+  NS_ERROR("stylo: ServoRestyleManager::ContentStateChanged not completely implemented");
   return NS_OK;
 }
 
 void
 ServoRestyleManager::AttributeWillChange(Element* aElement,
                                          int32_t aNameSpaceID,
                                          nsIAtom* aAttribute,
                                          int32_t aModType,
--- a/layout/base/ServoRestyleManager.h
+++ b/layout/base/ServoRestyleManager.h
@@ -5,16 +5,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_ServoRestyleManager_h
 #define mozilla_ServoRestyleManager_h
 
 #include "mozilla/EventStates.h"
 #include "nsChangeHint.h"
 #include "nsISupportsImpl.h"
+#include "nsPresContext.h"
+#include "nsINode.h"
 
 namespace mozilla {
 namespace dom {
 class Element;
 } // namespace dom
 } // namespace mozilla
 class nsAttrValue;
 class nsIAtom;
@@ -26,17 +28,17 @@ namespace mozilla {
 /**
  * Restyle manager for a Servo-backed style system.
  */
 class ServoRestyleManager
 {
 public:
   NS_INLINE_DECL_REFCOUNTING(ServoRestyleManager)
 
-  ServoRestyleManager();
+  explicit ServoRestyleManager(nsPresContext* aPresContext);
 
   void Disconnect();
   void PostRestyleEvent(dom::Element* aElement,
                         nsRestyleHint aRestyleHint,
                         nsChangeHint aMinChangeHint);
   void PostRestyleEventForLazyConstruction();
   void RebuildAllStyleData(nsChangeHint aExtraHint,
                            nsRestyleHint aRestyleHint);
@@ -60,18 +62,35 @@ public:
   void AttributeChanged(dom::Element* aElement,
                         int32_t aNameSpaceID,
                         nsIAtom* aAttribute,
                         int32_t aModType,
                         const nsAttrValue* aOldValue);
   nsresult ReparentStyleContext(nsIFrame* aFrame);
   bool HasPendingRestyles();
   uint64_t GetRestyleGeneration() const;
+  uint32_t GetHoverGeneration() const { return mHoverGeneration; }
+  void SetObservingRefreshDriver(bool aObserving) {
+      mObservingRefreshDriver = aObserving;
+  }
+
 
 protected:
   ~ServoRestyleManager() {}
 
   uint64_t mRestyleGeneration;
+  uint32_t mHoverGeneration;
+  nsPresContext* mPresContext; // weak
+  bool mObservingRefreshDriver;
+
+private:
+  nsPresContext* PresContext() const { return mPresContext; }
+  nsCSSFrameConstructor* FrameConstructor() const {
+    return mPresContext->FrameConstructor();
+  }
+  inline ServoStyleSet* StyleSet() const {
+    return PresContext()->StyleSet()->AsServo();
+  }
 };
 
 } // namespace mozilla
 
 #endif // mozilla_ServoRestyleManager_h
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -3677,33 +3677,28 @@ FlushLayoutRecursive(nsIDocument* aDocum
   return true;
 }
 
 void
 PresShell::DispatchSynthMouseMove(WidgetGUIEvent* aEvent,
                                   bool aFlushOnHoverChange)
 {
   RestyleManagerHandle restyleManager = mPresContext->RestyleManager();
-  if (restyleManager->IsServo()) {
-    NS_ERROR("stylo: cannot dispatch synthetic mouse moves when using a "
-             "ServoRestyleManager yet");
-    return;
-  }
   uint32_t hoverGenerationBefore =
-    restyleManager->AsGecko()->GetHoverGeneration();
+    restyleManager->GetHoverGeneration();
   nsEventStatus status;
   nsView* targetView = nsView::GetViewFor(aEvent->mWidget);
   if (!targetView)
     return;
   targetView->GetViewManager()->DispatchEvent(aEvent, targetView, &status);
   if (MOZ_UNLIKELY(mIsDestroying)) {
     return;
   }
   if (aFlushOnHoverChange &&
-      hoverGenerationBefore != restyleManager->AsGecko()->GetHoverGeneration()) {
+      hoverGenerationBefore != restyleManager->GetHoverGeneration()) {
     // Flush so that the resulting reflow happens now so that our caller
     // can suppress any synthesized mouse moves caused by that reflow.
     // This code only ever runs for the root document, but :hover changes
     // can happen in descendant documents too, so make sure we flush
     // all of them.
     FlushLayoutRecursive(mDocument);
   }
 }
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -1741,20 +1741,17 @@ nsRefreshDriver::Tick(int64_t aNowEpoch,
             profiler_tracing("Paint", "Styles", mStyleCause, TRACING_INTERVAL_START);
             mStyleCause = nullptr;
           }
 
           NS_ADDREF(shell);
           mStyleFlushObservers.RemoveElement(shell);
           RestyleManagerHandle restyleManager =
             shell->GetPresContext()->RestyleManager();
-          // XXX stylo: ServoRestyleManager does not observer the refresh driver yet.
-          if (restyleManager->IsGecko()) {
-            restyleManager->AsGecko()->mObservingRefreshDriver = false;
-          }
+          restyleManager->SetObservingRefreshDriver(false);
           shell->FlushPendingNotifications(ChangesToFlush(Flush_Style, false));
           // Inform the FontFaceSet that we ticked, so that it can resolve its
           // ready promise if it needs to (though it might still be waiting on
           // a layout flush).
           nsPresContext* presContext = shell->GetPresContext();
           if (presContext) {
             presContext->NotifyFontFaceSetOnRefresh();
           }