Bug 1285474: stylo: Partially implement some restyling APIs to take rid of some gecko-only code paths.
MozReview-Commit-ID: Jf59l1asuZ6
--- 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();
}