From 40b88fe3edbb4c3e98e18780f725783f630b5f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 9 Jun 2022 23:02:11 +0000 Subject: [PATCH] Bug 1773342 - Treat text scale factor as an additional zoom factor, on both GTK and Windows. r=stransky,handyman GTK already did this, sorta, in a platform-specific way: by hacking in the scale factor in the CSS screen code. I think this is cleaner, since we have a centralized place to compute the full zoom in nsPresContext, and that code path is fairly well tested. This also would make it trivial to make this text zoom rather than full zoom in the future, if we wanted (which is probably _technically_ more correct, even though less pretty less pretty). This also allows us to remove some hacks where we were undoing the text scale factor on Linux (since stuff like scrollbars already ignore full zoom). Depends on D148675 Differential Revision: https://phabricator.services.mozilla.com/D148676 --- dom/base/nsDOMWindowUtils.cpp | 24 +++++++++++++++++------- layout/base/nsPresContext.cpp | 13 ++++++++++++- widget/LookAndFeel.h | 4 ++++ widget/ScrollbarDrawingGTK.cpp | 12 ------------ widget/gtk/ScreenHelperGTK.cpp | 6 ++---- widget/gtk/nsNativeThemeGTK.cpp | 12 +----------- widget/gtk/nsWindow.cpp | 4 +--- widget/windows/nsLookAndFeel.cpp | 3 ++- 8 files changed, 39 insertions(+), 39 deletions(-) diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index b1e7116444dc..97529b6a5543 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -1865,15 +1865,25 @@ nsDOMWindowUtils::ToScreenRectInCSSUnits(float aX, float aY, float aWidth, nsPresContext* presContext = GetPresContext(); MOZ_ASSERT(presContext); - nsRect appUnitsRect = LayoutDeviceRect::ToAppUnits( - ViewAs( - rect, PixelCastJustification::ScreenIsParentLayerForRoot), - presContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom()); - CSSRect cssUnitsRect = CSSRect::FromAppUnits(appUnitsRect); + auto devRect = ViewAs( + rect, PixelCastJustification::ScreenIsParentLayerForRoot); + // We want to return the screen rect in CSS units of the browser chrome. The + // browser chrome doesn't have any built-in zoom, except for the text scale + // factor. + // + // TODO(emilio): It'd be cleaner to convert callers to use plain toScreenRect, + // and perform the screen -> CSS rect in the parent process instead, probably. + LayoutDeviceToCSSScale scale = [&] { + float auPerDev = + presContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom(); + auPerDev /= LookAndFeel::GetTextScaleFactor(); + return LayoutDeviceToCSSScale(auPerDev / AppUnitsPerCSSPixel()); + }(); + + CSSRect cssRect = devRect * scale; RefPtr outRect = new DOMRect(mWindow); - outRect->SetRect(cssUnitsRect.x, cssUnitsRect.y, cssUnitsRect.width, - cssUnitsRect.height); + outRect->SetRect(cssRect.x, cssRect.y, cssRect.width, cssRect.height); outRect.forget(aResult); return NS_OK; } diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index e982a7d0b9f9..170c3ae9ebca 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -929,7 +929,15 @@ void nsPresContext::RecomputeBrowsingContextDependentData() { // matter... Medium also doesn't affect those. return; } - SetFullZoom(browsingContext->FullZoom()); + // NOTE(emilio): We use the OS "text scale factor" as an extra source for full + // zoom, rather than text zoom (which would seem the obvious choice at first). + // is for a variety of reasons: + // * It generally creates more visually consistent results. + // * It has always been the effective behavior on GTK. + // * It matches other browsers as well. + float effectiveFullZoom = + browsingContext->FullZoom() * LookAndFeel::GetTextScaleFactor(); + SetFullZoom(effectiveFullZoom); SetTextZoom(browsingContext->TextZoom()); SetOverrideDPPX(browsingContext->OverrideDPPX()); @@ -1581,6 +1589,9 @@ void nsPresContext::ThemeChangedInternal() { LookAndFeel::HandleGlobalThemeChange(); + // Full zoom might have changed as a result of the text scale factor. + RecomputeBrowsingContextDependentData(); + // Changes to system metrics and other look and feel values can change media // queries on them. // diff --git a/widget/LookAndFeel.h b/widget/LookAndFeel.h index 955c7875160c..2cc2f03b8dab 100644 --- a/widget/LookAndFeel.h +++ b/widget/LookAndFeel.h @@ -445,6 +445,10 @@ class LookAndFeel { return GetColor(aId, aFrame).valueOr(aDefault); } + static float GetTextScaleFactor() { + return GetFloat(FloatID::TextScaleFactor, 1.0f); + } + /** * GetInt() and GetFloat() return a int or float value for aID. The result * might be distance, time, some flags or a int value which has particular diff --git a/widget/ScrollbarDrawingGTK.cpp b/widget/ScrollbarDrawingGTK.cpp index 6877ed0c3b33..15556cad35d7 100644 --- a/widget/ScrollbarDrawingGTK.cpp +++ b/widget/ScrollbarDrawingGTK.cpp @@ -131,16 +131,4 @@ void ScrollbarDrawingGTK::RecomputeScrollbarParams() { defaultSize = overrideSize; } mHorizontalScrollbarHeight = mVerticalScrollbarWidth = defaultSize; - - // On GTK, widgets don't account for text scale factor, but that's included - // in the usual DPI computations, so we undo that here, just like - // GetMonitorScaleFactor does it in nsNativeThemeGTK. - float scale = - LookAndFeel::GetFloat(LookAndFeel::FloatID::TextScaleFactor, 1.0f); - if (scale != 1.0f) { - mVerticalScrollbarWidth = - uint32_t(round(float(mVerticalScrollbarWidth) / scale)); - mHorizontalScrollbarHeight = - uint32_t(round(float(mHorizontalScrollbarHeight) / scale)); - } } diff --git a/widget/gtk/ScreenHelperGTK.cpp b/widget/gtk/ScreenHelperGTK.cpp index 2011face0c93..2989cbf3d76a 100644 --- a/widget/gtk/ScreenHelperGTK.cpp +++ b/widget/gtk/ScreenHelperGTK.cpp @@ -204,8 +204,7 @@ static already_AddRefed MakeScreenGtk(GdkScreen* aScreen, } #endif - CSSToLayoutDeviceScale defaultCssScale(gdkScaleFactor * - gfxPlatformGtk::GetFontScaleFactor()); + CSSToLayoutDeviceScale defaultCssScale(gdkScaleFactor); float dpi = 96.0f; gint heightMM = gdk_screen_get_monitor_height_mm(aScreen, aMonitorNum); @@ -371,8 +370,7 @@ already_AddRefed ScreenGetterWayland::MakeScreenWayland(gint aMonitor) { // Use per-monitor scaling factor in gtk/wayland, or 1.0 otherwise. DesktopToLayoutDeviceScale contentsScale(monitor->scale); - CSSToLayoutDeviceScale defaultCssScale(monitor->scale * - gfxPlatformGtk::GetFontScaleFactor()); + CSSToLayoutDeviceScale defaultCssScale(monitor->scale); float dpi = 96.0f; gint heightMM = monitor->height_mm; diff --git a/widget/gtk/nsNativeThemeGTK.cpp b/widget/gtk/nsNativeThemeGTK.cpp index 0a27e92e11c2..98d65481fe53 100644 --- a/widget/gtk/nsNativeThemeGTK.cpp +++ b/widget/gtk/nsNativeThemeGTK.cpp @@ -66,17 +66,7 @@ static inline gint GetMonitorScaleFactor(nsPresContext* aPresContext) { double scale = StaticPrefs::layout_css_devPixelsPerPx(); if (scale <= 0) { if (nsCOMPtr rootWidget = aPresContext->GetRootWidget()) { - // We need to use GetDefaultScale() despite it returns monitor scale - // factor multiplied by font scale factor because it is the only scale - // updated in nsPuppetWidget. - // Since we don't want to apply font scale factor for UI elements - // (because GTK does not do so) we need to remove that from returned - // value. The computed monitor scale factor needs to be rounded before - // casting to integer to avoid rounding errors which would lead to - // returning 0. - int monitorScale = int( - round(rootWidget->GetDefaultScale().scale / - LookAndFeel::GetFloat(LookAndFeel::FloatID::TextScaleFactor))); + int monitorScale = int(round(rootWidget->GetDefaultScale().scale)); // Monitor scale can be negative if it has not been initialized in the // puppet widget yet. We also make sure that we return positive value. if (monitorScale < 1) { diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp index 025c37f39aa7..c0300eb50283 100644 --- a/widget/gtk/nsWindow.cpp +++ b/widget/gtk/nsWindow.cpp @@ -646,9 +646,7 @@ float nsWindow::GetDPI() { return dpi; } -double nsWindow::GetDefaultScaleInternal() { - return FractionalScaleFactor() * gfxPlatformGtk::GetFontScaleFactor(); -} +double nsWindow::GetDefaultScaleInternal() { return FractionalScaleFactor(); } DesktopToLayoutDeviceScale nsWindow::GetDesktopToDeviceScale() { #ifdef MOZ_WAYLAND diff --git a/widget/windows/nsLookAndFeel.cpp b/widget/windows/nsLookAndFeel.cpp index f9db6770712d..7c3e19a12de7 100644 --- a/widget/windows/nsLookAndFeel.cpp +++ b/widget/windows/nsLookAndFeel.cpp @@ -576,7 +576,8 @@ LookAndFeelFont nsLookAndFeel::GetLookAndFeelFontInternal( result.haveFont() = false; // Get scaling factor from physical to logical pixels - double pixelScale = 1.0 / WinUtils::SystemScaleFactor(); + double pixelScale = + 1.0 / WinUtils::SystemScaleFactor() / LookAndFeel::GetTextScaleFactor(); // The lfHeight is in pixels, and it needs to be adjusted for the // device it will be displayed on.