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
nsDeviceContext::SetDPI()
nsDeviceContext::SetDPI(double* aScale)
{
float dpi = -1.0f;
@ -280,9 +280,21 @@ nsDeviceContext::SetDPI()
dpi = 96.0f;
}
CSSToLayoutDeviceScale scale = mWidget ? mWidget->GetDefaultScale()
: CSSToLayoutDeviceScale(1.0);
double devPixelsPerCSSPixel = scale.scale;
double devPixelsPerCSSPixel;
if (aScale && *aScale > 0.0) {
// 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 =
std::max(1, NS_lround(AppUnitsPerCSSPixel() / devPixelsPerCSSPixel));
@ -632,11 +644,12 @@ nsDeviceContext::CalcPrintingSize()
return (mWidth > 0 && mHeight > 0);
}
bool nsDeviceContext::CheckDPIChange() {
bool nsDeviceContext::CheckDPIChange(double* aScale)
{
int32_t oldDevPixels = mAppUnitsPerDevPixelAtUnitFullZoom;
int32_t oldInches = mAppUnitsPerPhysicalInch;
SetDPI();
SetDPI(aScale);
return oldDevPixels != mAppUnitsPerDevPixelAtUnitFullZoom ||
oldInches != mAppUnitsPerPhysicalInch;

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

@ -219,12 +219,18 @@ public:
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
* AppUnitsPerDevPixel() or AppUnitsPerPhysicalInch()
* changed)
*/
bool CheckDPIChange();
bool CheckDPIChange(double* aScale = nullptr);
/**
* 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():
~nsDeviceContext();
void SetDPI();
void SetDPI(double* aScale = nullptr);
void ComputeClientRectUsingScreen(nsRect *outRect);
void ComputeFullAreaUsingScreen(nsRect *outRect);
void FindScreen(nsIScreen **outScreen);

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

@ -1693,7 +1693,7 @@ nsPresContext::UIResolutionChangedSync()
{
if (!mPendingUIResolutionChanged) {
mPendingUIResolutionChanged = true;
UIResolutionChangedInternal();
UIResolutionChangedInternalScale(0.0);
}
}
@ -1705,7 +1705,12 @@ nsPresContext::UIResolutionChangedSubdocumentCallback(nsIDocument* aDocument,
if (shell) {
nsPresContext* pc = shell->GetPresContext();
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;
@ -1730,10 +1735,16 @@ NotifyChildrenUIResolutionChanged(nsPIDOMWindowOuter* aWindow)
void
nsPresContext::UIResolutionChangedInternal()
{
UIResolutionChangedInternalScale(0.0);
}
void
nsPresContext::UIResolutionChangedInternalScale(double aScale)
{
mPendingUIResolutionChanged = false;
mDeviceContext->CheckDPIChange();
mDeviceContext->CheckDPIChange(&aScale);
if (mCurAppUnitsPerDevPixel != AppUnitsPerDevPixel()) {
AppUnitsPerDevPixelChanged();
}
@ -1744,7 +1755,7 @@ nsPresContext::UIResolutionChangedInternal()
}
mDocument->EnumerateSubDocuments(UIResolutionChangedSubdocumentCallback,
nullptr);
&aScale);
}
void

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

@ -1102,8 +1102,17 @@ protected:
friend class nsRunnableMethod<nsPresContext>;
void ThemeChangedInternal();
void SysColorChangedInternal();
// update device context's resolution from the widget
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
UIResolutionChangedSubdocumentCallback(nsIDocument* aDocument, void* aData);