зеркало из https://github.com/mozilla/gecko-dev.git
Bug 851641. Make nsView::DoResetWidgetBounds safe against any kind of painting or flushing happening during it. r=mats
This commit is contained in:
Родитель
ca6f57edb1
Коммит
923eed369f
|
@ -237,21 +237,40 @@ void nsView::DoResetWidgetBounds(bool aMoveOnly,
|
||||||
|
|
||||||
NS_PRECONDITION(mWindow, "Why was this called??");
|
NS_PRECONDITION(mWindow, "Why was this called??");
|
||||||
|
|
||||||
bool curVisibility = mWindow->IsVisible();
|
// Hold this ref to make sure it stays alive.
|
||||||
bool newVisibility = IsEffectivelyVisible();
|
nsCOMPtr<nsIWidget> widget = mWindow;
|
||||||
if (curVisibility && !newVisibility) {
|
|
||||||
mWindow->Show(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsIntRect curBounds;
|
// Stash a copy of these and use them so we can handle this being deleted (say
|
||||||
mWindow->GetClientBounds(curBounds);
|
// from sync painting/flushing from Show/Move/Resize on the widget).
|
||||||
|
nsRect dimBounds = mDimBounds;
|
||||||
|
nsViewVisibility vis = mVis;
|
||||||
|
nsIntRect newBounds;
|
||||||
|
nsRefPtr<nsDeviceContext> dx;
|
||||||
|
mViewManager->GetDeviceContext(*getter_AddRefs(dx));
|
||||||
|
|
||||||
nsWindowType type;
|
nsWindowType type;
|
||||||
mWindow->GetWindowType(type);
|
widget->GetWindowType(type);
|
||||||
|
|
||||||
|
nsIntRect curBounds;
|
||||||
|
widget->GetClientBounds(curBounds);
|
||||||
|
|
||||||
if (type == eWindowType_popup &&
|
if (type == eWindowType_popup &&
|
||||||
((curBounds.IsEmpty() && mDimBounds.IsEmpty()) ||
|
((curBounds.IsEmpty() && dimBounds.IsEmpty()) ||
|
||||||
mVis == nsViewVisibility_kHide)) {
|
vis == nsViewVisibility_kHide)) {
|
||||||
|
// We're going to hit the early exit below, avoid calling CalcWidgetBounds.
|
||||||
|
} else {
|
||||||
|
newBounds = CalcWidgetBounds(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool curVisibility = widget->IsVisible();
|
||||||
|
bool newVisibility = IsEffectivelyVisible();
|
||||||
|
if (curVisibility && !newVisibility) {
|
||||||
|
widget->Show(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == eWindowType_popup &&
|
||||||
|
((curBounds.IsEmpty() && dimBounds.IsEmpty()) ||
|
||||||
|
vis == nsViewVisibility_kHide)) {
|
||||||
// Don't manipulate empty or hidden popup widgets. For example there's no
|
// Don't manipulate empty or hidden popup widgets. For example there's no
|
||||||
// point moving hidden comboboxes around, or doing X server roundtrips
|
// point moving hidden comboboxes around, or doing X server roundtrips
|
||||||
// to compute their true screen position. This could mean that WidgetToScreen
|
// to compute their true screen position. This could mean that WidgetToScreen
|
||||||
|
@ -260,8 +279,6 @@ void nsView::DoResetWidgetBounds(bool aMoveOnly,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIntRect newBounds = CalcWidgetBounds(type);
|
|
||||||
|
|
||||||
bool changedPos = curBounds.TopLeft() != newBounds.TopLeft();
|
bool changedPos = curBounds.TopLeft() != newBounds.TopLeft();
|
||||||
bool changedSize = curBounds.Size() != newBounds.Size();
|
bool changedSize = curBounds.Size() != newBounds.Size();
|
||||||
|
|
||||||
|
@ -271,12 +288,10 @@ void nsView::DoResetWidgetBounds(bool aMoveOnly,
|
||||||
// because of the potential for device-pixel coordinate spaces for mixed
|
// because of the potential for device-pixel coordinate spaces for mixed
|
||||||
// hidpi/lodpi screens to overlap each other and result in bad placement
|
// hidpi/lodpi screens to overlap each other and result in bad placement
|
||||||
// (bug 814434).
|
// (bug 814434).
|
||||||
nsRefPtr<nsDeviceContext> dx;
|
|
||||||
mViewManager->GetDeviceContext(*getter_AddRefs(dx));
|
|
||||||
double invScale;
|
double invScale;
|
||||||
|
|
||||||
// Bug 861270: for correct widget manipulation at arbitrary scale factors,
|
// Bug 861270: for correct widget manipulation at arbitrary scale factors,
|
||||||
// prefer to base scaling on mWindow->GetDefaultScale(). But only do this if
|
// prefer to base scaling on widget->GetDefaultScale(). But only do this if
|
||||||
// it matches the view manager's device context scale after allowing for the
|
// it matches the view manager's device context scale after allowing for the
|
||||||
// quantization to app units, because of OS X multiscreen issues (where the
|
// quantization to app units, because of OS X multiscreen issues (where the
|
||||||
// only two scales are 1.0 or 2.0, and so the quantization doesn't actually
|
// only two scales are 1.0 or 2.0, and so the quantization doesn't actually
|
||||||
|
@ -285,7 +300,7 @@ void nsView::DoResetWidgetBounds(bool aMoveOnly,
|
||||||
// unscaledAppUnitsPerDevPixel value. On platforms where the device-pixel
|
// unscaledAppUnitsPerDevPixel value. On platforms where the device-pixel
|
||||||
// scale is uniform across all displays (currently all except OS X), we'll
|
// scale is uniform across all displays (currently all except OS X), we'll
|
||||||
// always use the precise value from mWindow->GetDefaultScale here.
|
// always use the precise value from mWindow->GetDefaultScale here.
|
||||||
double scale = mWindow->GetDefaultScale();
|
double scale = widget->GetDefaultScale();
|
||||||
if (NSToIntRound(60.0 / scale) == dx->UnscaledAppUnitsPerDevPixel()) {
|
if (NSToIntRound(60.0 / scale) == dx->UnscaledAppUnitsPerDevPixel()) {
|
||||||
invScale = 1.0 / scale;
|
invScale = 1.0 / scale;
|
||||||
} else {
|
} else {
|
||||||
|
@ -294,25 +309,25 @@ void nsView::DoResetWidgetBounds(bool aMoveOnly,
|
||||||
|
|
||||||
if (changedPos) {
|
if (changedPos) {
|
||||||
if (changedSize && !aMoveOnly) {
|
if (changedSize && !aMoveOnly) {
|
||||||
mWindow->ResizeClient(newBounds.x * invScale,
|
widget->ResizeClient(newBounds.x * invScale,
|
||||||
newBounds.y * invScale,
|
newBounds.y * invScale,
|
||||||
newBounds.width * invScale,
|
newBounds.width * invScale,
|
||||||
newBounds.height * invScale,
|
newBounds.height * invScale,
|
||||||
aInvalidateChangedSize);
|
aInvalidateChangedSize);
|
||||||
} else {
|
} else {
|
||||||
mWindow->MoveClient(newBounds.x * invScale,
|
widget->MoveClient(newBounds.x * invScale,
|
||||||
newBounds.y * invScale);
|
newBounds.y * invScale);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (changedSize && !aMoveOnly) {
|
if (changedSize && !aMoveOnly) {
|
||||||
mWindow->ResizeClient(newBounds.width * invScale,
|
widget->ResizeClient(newBounds.width * invScale,
|
||||||
newBounds.height * invScale,
|
newBounds.height * invScale,
|
||||||
aInvalidateChangedSize);
|
aInvalidateChangedSize);
|
||||||
} // else do nothing!
|
} // else do nothing!
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!curVisibility && newVisibility) {
|
if (!curVisibility && newVisibility) {
|
||||||
mWindow->Show(true);
|
widget->Show(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче