Bug 1249279 - Let subdocuments' presContexts inherit the DPI setting of their parent, instead of retrieving it from their widget, to avoid using stale values from a currently-hidden widget on a screen with a different DPI. r=bz

This commit is contained in:
Jonathan Kew 2016-04-07 10:01:30 +01:00
Родитель ab4cb0d9ab
Коммит 0d6a32ee9b
4 изменённых файлов: 52 добавлений и 13 удалений

Просмотреть файл

@ -251,7 +251,7 @@ nsDeviceContext::IsPrinterSurface()
} }
void void
nsDeviceContext::SetDPI() nsDeviceContext::SetDPI(double* aScale)
{ {
float dpi = -1.0f; float dpi = -1.0f;
@ -280,9 +280,21 @@ nsDeviceContext::SetDPI()
dpi = 96.0f; dpi = 96.0f;
} }
CSSToLayoutDeviceScale scale = mWidget ? mWidget->GetDefaultScale() double devPixelsPerCSSPixel;
: CSSToLayoutDeviceScale(1.0); if (aScale && *aScale > 0.0) {
double devPixelsPerCSSPixel = scale.scale; // if caller provided a scale, we just use it
devPixelsPerCSSPixel = *aScale;
} else {
// otherwise get from the widget, and return it in aScale for
// the caller to pass to child contexts if needed
CSSToLayoutDeviceScale scale =
mWidget ? mWidget->GetDefaultScale()
: CSSToLayoutDeviceScale(1.0);
devPixelsPerCSSPixel = scale.scale;
if (aScale) {
*aScale = devPixelsPerCSSPixel;
}
}
mAppUnitsPerDevPixelAtUnitFullZoom = mAppUnitsPerDevPixelAtUnitFullZoom =
std::max(1, NS_lround(AppUnitsPerCSSPixel() / devPixelsPerCSSPixel)); std::max(1, NS_lround(AppUnitsPerCSSPixel() / devPixelsPerCSSPixel));
@ -632,11 +644,12 @@ nsDeviceContext::CalcPrintingSize()
return (mWidth > 0 && mHeight > 0); return (mWidth > 0 && mHeight > 0);
} }
bool nsDeviceContext::CheckDPIChange() { bool nsDeviceContext::CheckDPIChange(double* aScale)
{
int32_t oldDevPixels = mAppUnitsPerDevPixelAtUnitFullZoom; int32_t oldDevPixels = mAppUnitsPerDevPixelAtUnitFullZoom;
int32_t oldInches = mAppUnitsPerPhysicalInch; int32_t oldInches = mAppUnitsPerPhysicalInch;
SetDPI(); SetDPI(aScale);
return oldDevPixels != mAppUnitsPerDevPixelAtUnitFullZoom || return oldDevPixels != mAppUnitsPerDevPixelAtUnitFullZoom ||
oldInches != mAppUnitsPerPhysicalInch; oldInches != mAppUnitsPerPhysicalInch;

Просмотреть файл

@ -219,12 +219,18 @@ public:
nsresult EndPage(); nsresult EndPage();
/** /**
* Check to see if the DPI has changed * Check to see if the DPI has changed, or impose a new DPI scale value.
* @param aScale - If non-null, the default (unzoomed) CSS to device pixel
* scale factor will be returned here; and if it is > 0.0
* on input, the given value will be used instead of
* getting it from the widget (if any). This is used to
* allow subdocument contexts to inherit the resolution
* setting of their parent.
* @return whether there was actually a change in the DPI (whether * @return whether there was actually a change in the DPI (whether
* AppUnitsPerDevPixel() or AppUnitsPerPhysicalInch() * AppUnitsPerDevPixel() or AppUnitsPerPhysicalInch()
* changed) * changed)
*/ */
bool CheckDPIChange(); bool CheckDPIChange(double* aScale = nullptr);
/** /**
* Set the full zoom factor: all lengths are multiplied by this factor * Set the full zoom factor: all lengths are multiplied by this factor
@ -249,7 +255,7 @@ private:
// Private destructor, to discourage deletion outside of Release(): // Private destructor, to discourage deletion outside of Release():
~nsDeviceContext(); ~nsDeviceContext();
void SetDPI(); void SetDPI(double* aScale = nullptr);
void ComputeClientRectUsingScreen(nsRect *outRect); void ComputeClientRectUsingScreen(nsRect *outRect);
void ComputeFullAreaUsingScreen(nsRect *outRect); void ComputeFullAreaUsingScreen(nsRect *outRect);
void FindScreen(nsIScreen **outScreen); void FindScreen(nsIScreen **outScreen);

Просмотреть файл

@ -1693,7 +1693,7 @@ nsPresContext::UIResolutionChangedSync()
{ {
if (!mPendingUIResolutionChanged) { if (!mPendingUIResolutionChanged) {
mPendingUIResolutionChanged = true; mPendingUIResolutionChanged = true;
UIResolutionChangedInternal(); UIResolutionChangedInternalScale(0.0);
} }
} }
@ -1705,7 +1705,12 @@ nsPresContext::UIResolutionChangedSubdocumentCallback(nsIDocument* aDocument,
if (shell) { if (shell) {
nsPresContext* pc = shell->GetPresContext(); nsPresContext* pc = shell->GetPresContext();
if (pc) { if (pc) {
pc->UIResolutionChangedInternal(); // For subdocuments, we want to apply the parent's scale, because there
// are cases where the subdoc's device context is connected to a widget
// that has an out-of-date resolution (it's on a different screen, but
// currently hidden, and will not be updated until shown): bug 1249279.
double scale = *static_cast<double*>(aData);
pc->UIResolutionChangedInternalScale(scale);
} }
} }
return true; return true;
@ -1730,10 +1735,16 @@ NotifyChildrenUIResolutionChanged(nsPIDOMWindowOuter* aWindow)
void void
nsPresContext::UIResolutionChangedInternal() nsPresContext::UIResolutionChangedInternal()
{
UIResolutionChangedInternalScale(0.0);
}
void
nsPresContext::UIResolutionChangedInternalScale(double aScale)
{ {
mPendingUIResolutionChanged = false; mPendingUIResolutionChanged = false;
mDeviceContext->CheckDPIChange(); mDeviceContext->CheckDPIChange(&aScale);
if (mCurAppUnitsPerDevPixel != AppUnitsPerDevPixel()) { if (mCurAppUnitsPerDevPixel != AppUnitsPerDevPixel()) {
AppUnitsPerDevPixelChanged(); AppUnitsPerDevPixelChanged();
} }
@ -1744,7 +1755,7 @@ nsPresContext::UIResolutionChangedInternal()
} }
mDocument->EnumerateSubDocuments(UIResolutionChangedSubdocumentCallback, mDocument->EnumerateSubDocuments(UIResolutionChangedSubdocumentCallback,
nullptr); &aScale);
} }
void void

Просмотреть файл

@ -1102,8 +1102,17 @@ protected:
friend class nsRunnableMethod<nsPresContext>; friend class nsRunnableMethod<nsPresContext>;
void ThemeChangedInternal(); void ThemeChangedInternal();
void SysColorChangedInternal(); void SysColorChangedInternal();
// update device context's resolution from the widget
void UIResolutionChangedInternal(); void UIResolutionChangedInternal();
// if aScale > 0.0, use it as resolution scale factor to the device context
// (otherwise get it from the widget)
void UIResolutionChangedInternalScale(double aScale);
// aData here is a pointer to a double that holds the CSS to device-pixel
// scale factor from the parent, which will be applied to the subdocument's
// device context instead of retrieving a scale from the widget.
static bool static bool
UIResolutionChangedSubdocumentCallback(nsIDocument* aDocument, void* aData); UIResolutionChangedSubdocumentCallback(nsIDocument* aDocument, void* aData);