mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 02:14:43 +00:00
Bug 1812868 - Expose scrollbar-inline-size as a CSS variable to chrome code. r=mstange
For that we need to: * Make GetDPIRatioForScrollbarPart thread-safe: This was using the widget for bug 1727289, but just looking at the print preview scale is enough to fix that. * Make nsPresContext::UseOverlayScrollbars() thread-safe: We store the RDM pane stuff in the pres context. The rest is pretty straight-forward. Differential Revision: https://phabricator.services.mozilla.com/D168148
This commit is contained in:
parent
42ef1bc602
commit
ad4bd6a3ba
@ -2757,21 +2757,7 @@ void BrowsingContext::DidSet(FieldIndex<IDX_InRDMPane>, bool aOldValue) {
|
||||
if (GetInRDMPane() == aOldValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
PreOrderWalk([&](BrowsingContext* aContext) {
|
||||
if (nsIDocShell* shell = aContext->GetDocShell()) {
|
||||
if (nsPresContext* pc = shell->GetPresContext()) {
|
||||
pc->RecomputeTheme();
|
||||
|
||||
// This is a bit of a lie, but this affects the overlay-scrollbars
|
||||
// media query and it's the code-path that gets taken for regular system
|
||||
// metrics changes via ThemeChanged().
|
||||
pc->MediaFeatureValuesChanged(
|
||||
{MediaFeatureChangeReason::SystemMetricsChange},
|
||||
MediaFeatureChangePropagation::JustThisDocument);
|
||||
}
|
||||
}
|
||||
});
|
||||
PresContextAffectingFieldChanged();
|
||||
}
|
||||
|
||||
bool BrowsingContext::CanSet(FieldIndex<IDX_PageAwakeRequestCount>,
|
||||
|
@ -278,6 +278,7 @@ nsPresContext::nsPresContext(dom::Document* aDocument, nsPresContextType aType)
|
||||
mFontFeatureValuesDirty(true),
|
||||
mFontPaletteValuesDirty(true),
|
||||
mIsVisual(false),
|
||||
mInRDMPane(false),
|
||||
mHasWarnedAboutTooLargeDashedOrDottedRadius(false),
|
||||
mQuirkSheetAdded(false),
|
||||
mHadNonBlankPaint(false),
|
||||
@ -858,6 +859,8 @@ void nsPresContext::AttachPresShell(mozilla::PresShell* aPresShell) {
|
||||
// have a presshell, and hence a document.
|
||||
GetUserPreferences();
|
||||
|
||||
EnsureTheme();
|
||||
|
||||
nsIURI* docURI = doc->GetDocumentURI();
|
||||
|
||||
if (IsDynamic() && docURI) {
|
||||
@ -933,6 +936,8 @@ void nsPresContext::RecomputeBrowsingContextDependentData() {
|
||||
return browsingContext->GetEmbedderColorSchemes().mPreferred;
|
||||
}());
|
||||
|
||||
SetInRDMPane(top->GetInRDMPane());
|
||||
|
||||
if (doc == mDocument) {
|
||||
// Medium doesn't apply to resource documents, etc.
|
||||
RefPtr<nsAtom> mediumToEmulate;
|
||||
@ -1286,6 +1291,14 @@ void nsPresContext::UpdateEffectiveTextZoom() {
|
||||
MediaFeatureChangePropagation::JustThisDocument);
|
||||
}
|
||||
|
||||
void nsPresContext::SetInRDMPane(bool aInRDMPane) {
|
||||
if (mInRDMPane == aInRDMPane) {
|
||||
return;
|
||||
}
|
||||
mInRDMPane = aInRDMPane;
|
||||
RecomputeTheme();
|
||||
}
|
||||
|
||||
float nsPresContext::GetDeviceFullZoom() {
|
||||
return mDeviceContext->GetFullZoom();
|
||||
}
|
||||
@ -1629,8 +1642,7 @@ void nsPresContext::RecordInteractionTime(InteractionType aType,
|
||||
nsITheme* nsPresContext::EnsureTheme() {
|
||||
MOZ_ASSERT(!mTheme);
|
||||
if (Document()->ShouldAvoidNativeTheme()) {
|
||||
BrowsingContext* bc = Document()->GetBrowsingContext();
|
||||
if (bc && bc->Top()->InRDMPane()) {
|
||||
if (mInRDMPane) {
|
||||
mTheme = do_GetRDMThemeDoNotUseDirectly();
|
||||
} else {
|
||||
mTheme = do_GetBasicNativeThemeDoNotUseDirectly();
|
||||
@ -1651,17 +1663,21 @@ void nsPresContext::RecomputeTheme() {
|
||||
if (oldTheme == mTheme) {
|
||||
return;
|
||||
}
|
||||
// Theme only affects layout information, not style, so we just need to
|
||||
// reframe (as it affects whether we create scrollbar buttons for example).
|
||||
RebuildAllStyleData(nsChangeHint_ReconstructFrame, RestyleHint{0});
|
||||
// Theme affects layout information (as it affects whether we create
|
||||
// scrollbar buttons for example) and also style (affects the
|
||||
// scrollbar-inline-size env var).
|
||||
RebuildAllStyleData(nsChangeHint_ReconstructFrame,
|
||||
RestyleHint::RecascadeSubtree());
|
||||
// This is a bit of a lie, but this affects the overlay-scrollbars
|
||||
// media query and it's the code-path that gets taken for regular system
|
||||
// metrics changes via ThemeChanged().
|
||||
MediaFeatureValuesChanged({MediaFeatureChangeReason::SystemMetricsChange},
|
||||
MediaFeatureChangePropagation::JustThisDocument);
|
||||
}
|
||||
|
||||
bool nsPresContext::UseOverlayScrollbars() const {
|
||||
if (LookAndFeel::GetInt(LookAndFeel::IntID::UseOverlayScrollbars)) {
|
||||
return true;
|
||||
}
|
||||
BrowsingContext* bc = Document()->GetBrowsingContext();
|
||||
return bc && bc->Top()->InRDMPane();
|
||||
return LookAndFeel::GetInt(LookAndFeel::IntID::UseOverlayScrollbars) ||
|
||||
mInRDMPane;
|
||||
}
|
||||
|
||||
void nsPresContext::ThemeChanged(widget::ThemeChangeKind aKind) {
|
||||
|
@ -502,7 +502,9 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
|
||||
*
|
||||
* XXX Temporary: see http://wiki.mozilla.org/Gecko:PrintPreview
|
||||
*/
|
||||
float GetPrintPreviewScaleForSequenceFrame() { return mPPScale; }
|
||||
float GetPrintPreviewScaleForSequenceFrameOrScrollbars() const {
|
||||
return mPPScale;
|
||||
}
|
||||
void SetPrintPreviewScale(float aScale) { mPPScale = aScale; }
|
||||
|
||||
nsDeviceContext* DeviceContext() const { return mDeviceContext; }
|
||||
@ -573,6 +575,7 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
|
||||
}
|
||||
void SetFullZoom(float aZoom);
|
||||
void SetOverrideDPPX(float);
|
||||
void SetInRDMPane(bool aInRDMPane);
|
||||
|
||||
public:
|
||||
float GetFullZoom() { return mFullZoom; }
|
||||
@ -824,17 +827,9 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
|
||||
*/
|
||||
uint32_t GetBidi() const;
|
||||
|
||||
/*
|
||||
* Obtain a native theme for rendering our widgets (both form controls and
|
||||
* html)
|
||||
*
|
||||
* Guaranteed to return non-null.
|
||||
*/
|
||||
nsITheme* Theme() MOZ_NONNULL_RETURN {
|
||||
if (MOZ_LIKELY(mTheme)) {
|
||||
return mTheme;
|
||||
}
|
||||
return EnsureTheme();
|
||||
nsITheme* Theme() const MOZ_NONNULL_RETURN {
|
||||
MOZ_ASSERT(mTheme);
|
||||
return mTheme;
|
||||
}
|
||||
|
||||
void RecomputeTheme();
|
||||
@ -907,6 +902,8 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
|
||||
return mType == eContext_Print || mType == eContext_PrintPreview;
|
||||
}
|
||||
|
||||
bool IsPrintPreview() const { return mType == eContext_PrintPreview; }
|
||||
|
||||
// Is this presentation in a chrome docshell?
|
||||
bool IsChrome() const;
|
||||
|
||||
@ -1352,6 +1349,9 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
|
||||
|
||||
unsigned mIsVisual : 1;
|
||||
|
||||
// Are we in the RDM pane?
|
||||
unsigned mInRDMPane : 1;
|
||||
|
||||
unsigned mHasWarnedAboutTooLargeDashedOrDottedRadius : 1;
|
||||
|
||||
// Have we added quirk.css to the style set?
|
||||
|
@ -146,7 +146,7 @@ NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
|
||||
|
||||
float nsPageSequenceFrame::GetPrintPreviewScale() const {
|
||||
nsPresContext* pc = PresContext();
|
||||
float scale = pc->GetPrintPreviewScaleForSequenceFrame();
|
||||
float scale = pc->GetPrintPreviewScaleForSequenceFrameOrScrollbars();
|
||||
|
||||
WritingMode wm = GetWritingMode();
|
||||
if (pc->IsScreen() && MOZ_LIKELY(mScrollportSize.ISize(wm) > 0 &&
|
||||
|
@ -305,6 +305,16 @@ bool Gecko_AnimationNameMayBeReferencedFromStyle(
|
||||
return aPresContext->AnimationManager()->AnimationMayBeReferenced(aName);
|
||||
}
|
||||
|
||||
float Gecko_GetScrollbarInlineSize(const nsPresContext* aPc) {
|
||||
MOZ_ASSERT(aPc);
|
||||
AutoWriteLock guard(*sServoFFILock); // We read some look&feel values.
|
||||
auto overlay = aPc->UseOverlayScrollbars() ? nsITheme::Overlay::Yes
|
||||
: nsITheme::Overlay::No;
|
||||
LayoutDeviceIntCoord size =
|
||||
aPc->Theme()->GetScrollbarSize(aPc, StyleScrollbarWidth::Auto, overlay);
|
||||
return aPc->DevPixelsToFloatCSSPixels(size);
|
||||
}
|
||||
|
||||
PseudoStyleType Gecko_GetImplementedPseudo(const Element* aElement) {
|
||||
return aElement->GetPseudoElementType();
|
||||
}
|
||||
|
@ -350,6 +350,8 @@ void Gecko_NoteAnimationOnlyDirtyElement(const mozilla::dom::Element*);
|
||||
bool Gecko_AnimationNameMayBeReferencedFromStyle(const nsPresContext*,
|
||||
nsAtom* name);
|
||||
|
||||
float Gecko_GetScrollbarInlineSize(const nsPresContext*);
|
||||
|
||||
// Incremental restyle.
|
||||
mozilla::PseudoStyleType Gecko_GetImplementedPseudo(
|
||||
const mozilla::dom::Element*);
|
||||
|
@ -22,6 +22,7 @@ tags = fullscreen
|
||||
[test_display_mode_reflow.html]
|
||||
support-files = display_mode_reflow.html
|
||||
tags = fullscreen
|
||||
[test_scrollbar_inline_size.html]
|
||||
[test_hover.html]
|
||||
skip-if = true # bug 1346353
|
||||
[test_moz_document_rules.html]
|
||||
|
35
layout/style/test/chrome/test_scrollbar_inline_size.html
Normal file
35
layout/style/test/chrome/test_scrollbar_inline_size.html
Normal file
@ -0,0 +1,35 @@
|
||||
<!DOCTYPE HTML>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for env(scrollbar-inline-size)</title>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" href="chrome://global/skin"/>
|
||||
<link rel="stylesheet" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
<div id="scroller" style="width: 100px; height: 100px; overflow: scroll"></div>
|
||||
<div id="ref" style="width: env(scrollbar-inline-size, 1000px)"></div>
|
||||
<script>
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
async function runTest() {
|
||||
// We need to disable overlay scrollbars to measure the real scrollbar
|
||||
// size.
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["ui.useOverlayScrollbars", 0]],
|
||||
});
|
||||
runOnce();
|
||||
|
||||
info("with full zoom");
|
||||
SpecialPowers.setFullZoom(window, 2.0);
|
||||
|
||||
runOnce();
|
||||
}
|
||||
|
||||
function runOnce() {
|
||||
let scroller = document.getElementById("scroller");
|
||||
let ref = document.getElementById("ref");
|
||||
let scrollbarSize = scroller.getBoundingClientRect().width - scroller.clientWidth;
|
||||
ok(scrollbarSize > 0, "Should have a scrollbar");
|
||||
is(ref.getBoundingClientRect().width, scrollbarSize, "env() should match the scrollbar size");
|
||||
}
|
||||
|
||||
runTest().then(SimpleTest.finish);
|
||||
</script>
|
@ -10,6 +10,7 @@ const NON_CONTENT_ACCESSIBLE_ENV_VARS = [
|
||||
"-moz-gtk-csd-maximize-button-position",
|
||||
"-moz-gtk-csd-close-button-position",
|
||||
"-moz-content-preferred-color-scheme",
|
||||
"scrollbar-inline-size",
|
||||
];
|
||||
|
||||
const div = document.querySelector("div");
|
||||
|
@ -78,6 +78,10 @@ fn get_content_preferred_color_scheme(device: &Device) -> VariableValue {
|
||||
})
|
||||
}
|
||||
|
||||
fn get_scrollbar_inline_size(device: &Device) -> VariableValue {
|
||||
VariableValue::pixels(device.scrollbar_inline_size().px())
|
||||
}
|
||||
|
||||
static ENVIRONMENT_VARIABLES: [EnvironmentVariable; 4] = [
|
||||
make_variable!(atom!("safe-area-inset-top"), get_safearea_inset_top),
|
||||
make_variable!(atom!("safe-area-inset-bottom"), get_safearea_inset_bottom),
|
||||
@ -104,7 +108,7 @@ macro_rules! lnf_int_variable {
|
||||
}};
|
||||
}
|
||||
|
||||
static CHROME_ENVIRONMENT_VARIABLES: [EnvironmentVariable; 6] = [
|
||||
static CHROME_ENVIRONMENT_VARIABLES: [EnvironmentVariable; 7] = [
|
||||
lnf_int_variable!(
|
||||
atom!("-moz-gtk-csd-titlebar-radius"),
|
||||
TitlebarRadius,
|
||||
@ -130,6 +134,10 @@ static CHROME_ENVIRONMENT_VARIABLES: [EnvironmentVariable; 6] = [
|
||||
atom!("-moz-content-preferred-color-scheme"),
|
||||
get_content_preferred_color_scheme
|
||||
),
|
||||
make_variable!(
|
||||
atom!("scrollbar-inline-size"),
|
||||
get_scrollbar_inline_size
|
||||
),
|
||||
];
|
||||
|
||||
impl CssEnvironment {
|
||||
|
@ -199,6 +199,18 @@ impl Device {
|
||||
unsafe { bindings::Gecko_GetBaseSize(self.document(), language.as_ptr(), generic) }
|
||||
}
|
||||
|
||||
/// Gets the size of the scrollbar in CSS pixels.
|
||||
pub fn scrollbar_inline_size(&self) -> Length {
|
||||
let pc = match self.pres_context() {
|
||||
Some(pc) => pc,
|
||||
// XXX: we could have a more reasonable default perhaps.
|
||||
None => return Length::new(0.0),
|
||||
};
|
||||
Length::new(unsafe {
|
||||
bindings::Gecko_GetScrollbarInlineSize(pc)
|
||||
})
|
||||
}
|
||||
|
||||
/// Queries font metrics
|
||||
pub fn query_font_metrics(
|
||||
&self,
|
||||
@ -541,8 +553,11 @@ impl Device {
|
||||
}
|
||||
|
||||
/// Return whether the document is a chrome document.
|
||||
///
|
||||
/// This check is consistent with how we enable chrome rules for chrome:// and resource://
|
||||
/// stylesheets (and thus chrome:// documents).
|
||||
#[inline]
|
||||
pub fn is_chrome_document(&self) -> bool {
|
||||
self.pref_sheet_prefs().mIsChrome
|
||||
self.document().mDocURISchemeIsChrome()
|
||||
}
|
||||
}
|
||||
|
@ -24,16 +24,12 @@ using mozilla::RelativeLuminanceUtils;
|
||||
/* static */
|
||||
auto ScrollbarDrawing::GetDPIRatioForScrollbarPart(const nsPresContext* aPc)
|
||||
-> DPIRatio {
|
||||
auto ratio = [&] {
|
||||
if (auto* rootPc = aPc->GetRootPresContext()) {
|
||||
if (nsCOMPtr<nsIWidget> widget = rootPc->GetRootWidget()) {
|
||||
return widget->GetDefaultScale();
|
||||
}
|
||||
}
|
||||
return DPIRatio(
|
||||
float(AppUnitsPerCSSPixel()) /
|
||||
float(aPc->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom()));
|
||||
}();
|
||||
DPIRatio ratio(
|
||||
float(AppUnitsPerCSSPixel()) /
|
||||
float(aPc->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom()));
|
||||
if (aPc->IsPrintPreview()) {
|
||||
ratio.scale *= aPc->GetPrintPreviewScaleForSequenceFrameOrScrollbars();
|
||||
}
|
||||
if (mKind == Kind::Cocoa) {
|
||||
return DPIRatio(ratio.scale >= 2.0f ? 2.0f : 1.0f);
|
||||
}
|
||||
|
@ -1117,6 +1117,7 @@ STATIC_ATOMS = [
|
||||
Atom("scrollbarbutton", "scrollbarbutton"),
|
||||
Atom("scrollbarDownBottom", "scrollbar-down-bottom"),
|
||||
Atom("scrollbarDownTop", "scrollbar-down-top"),
|
||||
Atom("scrollbarInlineSize", "scrollbar-inline-size"),
|
||||
Atom("scrollbarUpBottom", "scrollbar-up-bottom"),
|
||||
Atom("scrollbarUpTop", "scrollbar-up-top"),
|
||||
Atom("scrollbox", "scrollbox"),
|
||||
|
Loading…
Reference in New Issue
Block a user