зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1636998 - Make ::-moz-focus-outer a no-op, and remove it on Nightly. r=jwatt
See https://bugzilla.mozilla.org/show_bug.cgi?id=932410#c2 for the context for which this pseudo-element was added. In the previous patch, I had to special-case range appearance because of this pseudo-class, but that patch makes this pseudo-class completely redundant, as now all form controls, themed and unthemed, display outlines, unless the native theme displays a focus indicator on its own. Remove the special case, and make ranges use outlines like everything else rather than this bespoke pseudo-element. Differential Revision: https://phabricator.services.mozilla.com/D74734
This commit is contained in:
Родитель
5a8027aef4
Коммит
36b46408b8
|
@ -417,10 +417,6 @@
|
|||
outline: none;
|
||||
}
|
||||
|
||||
.font-value-slider::-moz-focus-outer {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.font-value-slider::-moz-range-thumb {
|
||||
background-color: var(--slider-thumb-color);
|
||||
border: 0;
|
||||
|
|
|
@ -10685,7 +10685,6 @@ exports.PSEUDO_ELEMENTS = [
|
|||
":first-line",
|
||||
":selection",
|
||||
":-moz-focus-inner",
|
||||
":-moz-focus-outer",
|
||||
":-moz-progress-bar",
|
||||
":-moz-range-track",
|
||||
":-moz-range-progress",
|
||||
|
|
|
@ -72,11 +72,6 @@ void nsRangeFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
|
|||
aContent->AddEventListener(NS_LITERAL_STRING("touchstart"),
|
||||
mDummyTouchListener, false);
|
||||
|
||||
ServoStyleSet* styleSet = PresContext()->StyleSet();
|
||||
|
||||
mOuterFocusStyle = styleSet->ProbePseudoElementStyle(
|
||||
*aContent->AsElement(), PseudoStyleType::mozFocusOuter, Style());
|
||||
|
||||
return nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
|
||||
}
|
||||
|
||||
|
@ -148,78 +143,6 @@ void nsRangeFrame::AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
|
|||
}
|
||||
}
|
||||
|
||||
class nsDisplayRangeFocusRing final : public nsPaintedDisplayItem {
|
||||
public:
|
||||
nsDisplayRangeFocusRing(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
|
||||
: nsPaintedDisplayItem(aBuilder, aFrame) {
|
||||
MOZ_COUNT_CTOR(nsDisplayRangeFocusRing);
|
||||
}
|
||||
MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayRangeFocusRing)
|
||||
|
||||
nsDisplayItemGeometry* AllocateGeometry(
|
||||
nsDisplayListBuilder* aBuilder) override;
|
||||
void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayItemGeometry* aGeometry,
|
||||
nsRegion* aInvalidRegion) const override;
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap) const override;
|
||||
virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
|
||||
NS_DISPLAY_DECL_NAME("RangeFocusRing", TYPE_RANGE_FOCUS_RING)
|
||||
};
|
||||
|
||||
nsDisplayItemGeometry* nsDisplayRangeFocusRing::AllocateGeometry(
|
||||
nsDisplayListBuilder* aBuilder) {
|
||||
return new nsDisplayItemGenericImageGeometry(this, aBuilder);
|
||||
}
|
||||
|
||||
void nsDisplayRangeFocusRing::ComputeInvalidationRegion(
|
||||
nsDisplayListBuilder* aBuilder, const nsDisplayItemGeometry* aGeometry,
|
||||
nsRegion* aInvalidRegion) const {
|
||||
auto geometry =
|
||||
static_cast<const nsDisplayItemGenericImageGeometry*>(aGeometry);
|
||||
|
||||
if (aBuilder->ShouldSyncDecodeImages() &&
|
||||
geometry->ShouldInvalidateToSyncDecodeImages()) {
|
||||
bool snap;
|
||||
aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
|
||||
}
|
||||
|
||||
nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
|
||||
}
|
||||
|
||||
nsRect nsDisplayRangeFocusRing::GetBounds(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap) const {
|
||||
*aSnap = false;
|
||||
nsRect rect(ToReferenceFrame(), Frame()->GetSize());
|
||||
|
||||
// We want to paint as if specifying a border for ::-moz-focus-outer
|
||||
// specifies an outline for our frame, so inflate by the border widths:
|
||||
ComputedStyle* computedStyle =
|
||||
static_cast<nsRangeFrame*>(mFrame)->mOuterFocusStyle;
|
||||
MOZ_ASSERT(computedStyle, "We only exist if mOuterFocusStyle is non-null");
|
||||
rect.Inflate(computedStyle->StyleBorder()->GetComputedBorder());
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
void nsDisplayRangeFocusRing::Paint(nsDisplayListBuilder* aBuilder,
|
||||
gfxContext* aCtx) {
|
||||
bool unused;
|
||||
ComputedStyle* computedStyle =
|
||||
static_cast<nsRangeFrame*>(mFrame)->mOuterFocusStyle;
|
||||
MOZ_ASSERT(computedStyle, "We only exist if mOuterFocusStyle is non-null");
|
||||
|
||||
PaintBorderFlags flags = aBuilder->ShouldSyncDecodeImages()
|
||||
? PaintBorderFlags::SyncDecodeImages
|
||||
: PaintBorderFlags();
|
||||
|
||||
ImgDrawResult result = nsCSSRendering::PaintBorder(
|
||||
mFrame->PresContext(), *aCtx, mFrame, GetPaintRect(),
|
||||
GetBounds(aBuilder, &unused), computedStyle, flags);
|
||||
|
||||
nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
|
||||
}
|
||||
|
||||
void nsRangeFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayListSet& aLists) {
|
||||
const nsStyleDisplay* disp = StyleDisplay();
|
||||
|
@ -240,36 +163,6 @@ void nsRangeFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
} else {
|
||||
BuildDisplayListForInline(aBuilder, aLists);
|
||||
}
|
||||
|
||||
// Draw a focus outline if appropriate:
|
||||
|
||||
if (!aBuilder->IsForPainting() || !IsVisibleForPainting()) {
|
||||
// we don't want the focus ring item for hit-testing or if the item isn't
|
||||
// in the area being [re]painted
|
||||
return;
|
||||
}
|
||||
|
||||
EventStates eventStates = mContent->AsElement()->State();
|
||||
if (eventStates.HasState(NS_EVENT_STATE_DISABLED) ||
|
||||
!eventStates.HasState(NS_EVENT_STATE_FOCUSRING)) {
|
||||
return; // can't have focus or doesn't match :-moz-focusring
|
||||
}
|
||||
|
||||
if (!mOuterFocusStyle || !mOuterFocusStyle->StyleBorder()->HasBorder()) {
|
||||
// no ::-moz-focus-outer specified border (how style specifies a focus ring
|
||||
// for range)
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME(emilio): This is using ThemeWantsButtonInnerFocusRing even though
|
||||
// it's painting the ::-moz-focus-outer pseudo-class... But why is
|
||||
// ::-moz-focus-outer useful, instead of outline?
|
||||
if (IsThemed(disp) && !PresContext()->Theme()->ThemeWantsButtonInnerFocusRing(
|
||||
disp->mAppearance)) {
|
||||
return; // the native theme displays its own visual indication of focus
|
||||
}
|
||||
|
||||
aLists.Content()->AppendNewToTop<nsDisplayRangeFocusRing>(aBuilder, this);
|
||||
}
|
||||
|
||||
void nsRangeFrame::Reflow(nsPresContext* aPresContext,
|
||||
|
@ -821,22 +714,3 @@ bool nsRangeFrame::ShouldUseNativeStyle() const {
|
|||
!PresContext()->HasAuthorSpecifiedRules(
|
||||
thumbFrame, STYLES_DISABLING_NATIVE_THEMING);
|
||||
}
|
||||
|
||||
ComputedStyle* nsRangeFrame::GetAdditionalComputedStyle(int32_t aIndex) const {
|
||||
// We only implement this so that SetAdditionalComputedStyle will be
|
||||
// called if style changes that would change the -moz-focus-outer
|
||||
// pseudo-element have occurred.
|
||||
if (aIndex != 0) {
|
||||
return nullptr;
|
||||
}
|
||||
return mOuterFocusStyle;
|
||||
}
|
||||
|
||||
void nsRangeFrame::SetAdditionalComputedStyle(int32_t aIndex,
|
||||
ComputedStyle* aComputedStyle) {
|
||||
MOZ_ASSERT(aIndex == 0,
|
||||
"GetAdditionalComputedStyle is handling other indexes?");
|
||||
|
||||
// The -moz-focus-outer pseudo-element's style has changed.
|
||||
mOuterFocusStyle = aComputedStyle;
|
||||
}
|
||||
|
|
|
@ -88,10 +88,6 @@ class nsRangeFrame final : public nsContainerFrame,
|
|||
aFlags & ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
|
||||
}
|
||||
|
||||
ComputedStyle* GetAdditionalComputedStyle(int32_t aIndex) const override;
|
||||
void SetAdditionalComputedStyle(int32_t aIndex,
|
||||
ComputedStyle* aComputedStyle) override;
|
||||
|
||||
/**
|
||||
* Returns true if the slider's thumb moves horizontally, or else false if it
|
||||
* moves vertically.
|
||||
|
@ -180,11 +176,6 @@ class nsRangeFrame final : public nsContainerFrame,
|
|||
*/
|
||||
nsCOMPtr<Element> mThumbDiv;
|
||||
|
||||
/**
|
||||
* Cached ComputedStyle for -moz-focus-outer CSS pseudo-element style.
|
||||
*/
|
||||
RefPtr<ComputedStyle> mOuterFocusStyle;
|
||||
|
||||
class DummyTouchListener final : public nsIDOMEventListener {
|
||||
private:
|
||||
~DummyTouchListener() = default;
|
||||
|
|
|
@ -2623,12 +2623,8 @@ void nsFrame::DisplayOutlineUnconditional(nsDisplayListBuilder* aBuilder,
|
|||
// focus indicators.
|
||||
if (outline.mOutlineStyle.IsAuto()) {
|
||||
auto* disp = StyleDisplay();
|
||||
// FIXME(emilio): The range special-case is needed because <input
|
||||
// type=range> displays its own outline with ::-moz-focus-outer, and this
|
||||
// would show two outlines instead of one.
|
||||
if (IsThemed(disp) &&
|
||||
(PresContext()->Theme()->ThemeDrawsFocusForWidget(disp->mAppearance) ||
|
||||
disp->mAppearance != StyleAppearance::Range)) {
|
||||
PresContext()->Theme()->ThemeDrawsFocusForWidget(disp->mAppearance)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "mozilla/CSSEnabledState.h"
|
||||
#include "mozilla/Compiler.h"
|
||||
#include "mozilla/PseudoStyleType.h"
|
||||
#include "mozilla/StaticPrefs_layout.h"
|
||||
|
||||
// Is this pseudo-element a CSS2 pseudo-element that can be specified
|
||||
// with the single colon syntax (in addition to the double-colon syntax,
|
||||
|
@ -120,6 +121,9 @@ class nsCSSPseudoElements {
|
|||
static bool IsEnabled(Type aType, EnabledState aEnabledState) {
|
||||
if (!PseudoElementHasAnyFlag(
|
||||
aType, CSS_PSEUDO_ELEMENT_ENABLED_IN_UA_SHEETS_AND_CHROME)) {
|
||||
if (aType == Type::mozFocusOuter) {
|
||||
return mozilla::StaticPrefs::layout_css_moz_focus_outer_enabled();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -873,16 +873,6 @@ input[type=range] {
|
|||
user-select: none !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ideally we'd also require :-moz-focusring here, but that doesn't currently
|
||||
* work. Instead we only use the -moz-focus-outer border style if
|
||||
* NS_EVENT_STATE_FOCUSRING is set (the check is in
|
||||
* nsRangeFrame::BuildDisplayList).
|
||||
*/
|
||||
input[type=range]::-moz-focus-outer {
|
||||
border: 1px dotted black;
|
||||
}
|
||||
|
||||
/**
|
||||
* Layout handles positioning of this pseudo-element specially (so that content
|
||||
* authors can concentrate on styling the thumb without worrying about the
|
||||
|
|
|
@ -5714,6 +5714,13 @@
|
|||
mirror: always
|
||||
rust: true
|
||||
|
||||
# Whether the ::-moz-focus-outer pseudo-class is parsed.
|
||||
- name: layout.css.moz-focus-outer.enabled
|
||||
type: RelaxedAtomicBool
|
||||
value: @IS_NOT_NIGHTLY_BUILD@
|
||||
mirror: always
|
||||
rust: true
|
||||
|
||||
# Pref to control whether @-moz-document url-prefix() is parsed in content
|
||||
# pages. Only effective when layout.css.moz-document.content.enabled is false.
|
||||
- name: layout.css.moz-document.url-prefix-hack.enabled
|
||||
|
|
|
@ -159,7 +159,13 @@ impl PseudoElement {
|
|||
|
||||
/// Whether this pseudo-element is enabled for all content.
|
||||
pub fn enabled_in_content(&self) -> bool {
|
||||
(self.flags() & structs::CSS_PSEUDO_ELEMENT_ENABLED_IN_UA_SHEETS_AND_CHROME) == 0
|
||||
if (self.flags() & structs::CSS_PSEUDO_ELEMENT_ENABLED_IN_UA_SHEETS_AND_CHROME) != 0 {
|
||||
return false;
|
||||
}
|
||||
match *self {
|
||||
PseudoElement::MozFocusOuter => static_prefs::pref!("layout.css.moz-focus-outer.enabled"),
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether this pseudo is enabled explicitly in UA sheets.
|
||||
|
|
|
@ -224,9 +224,9 @@
|
|||
filter: drop-shadow(0px 0px 2px rgba(0,0,0,0.65));
|
||||
}
|
||||
|
||||
.volumeControl::-moz-focus-outer,
|
||||
.scrubber::-moz-focus-outer {
|
||||
border: 0;
|
||||
.volumeControl,
|
||||
.scrubber {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.progressBackgroundBar {
|
||||
|
|
|
@ -911,6 +911,7 @@ bool nsNativeBasicTheme::WidgetIsContainer(StyleAppearance aAppearance) {
|
|||
|
||||
bool nsNativeBasicTheme::ThemeDrawsFocusForWidget(StyleAppearance aAppearance) {
|
||||
switch (aAppearance) {
|
||||
case StyleAppearance::Range:
|
||||
// TODO(emilio): Checkbox / Radio don't have focus indicators when checked.
|
||||
// If they did, we could just return true here unconditionally.
|
||||
case StyleAppearance::Checkbox:
|
||||
|
|
Загрузка…
Ссылка в новой задаче