зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1645954 - Ensure we update both the content viewer and widget sizes before doing a reflow. r=tnikkel
The existing comment in BrowserChild::RecvUpdateDimensions may have been accurate at some point in the past, but I'm seeing cases where setting the content viewer size itself triggers a reflow. Since the widget size hasn't been updated yet, the reflow uses some stale values and produces incorrect outcomes. This patch ensures both the content viewer and widget get their sizes updated first, and only then do we do the reflow. Differential Revision: https://phabricator.services.mozilla.com/D79885
This commit is contained in:
Родитель
8349c27e4a
Коммит
e28e2f103c
|
@ -32,6 +32,7 @@
|
||||||
#include "ipc/nsGUIEventIPC.h"
|
#include "ipc/nsGUIEventIPC.h"
|
||||||
#include "js/JSON.h"
|
#include "js/JSON.h"
|
||||||
#include "mozilla/AsyncEventDispatcher.h"
|
#include "mozilla/AsyncEventDispatcher.h"
|
||||||
|
#include "mozilla/AutoResizeReflowSquasher.h"
|
||||||
#include "mozilla/ClearOnShutdown.h"
|
#include "mozilla/ClearOnShutdown.h"
|
||||||
#include "mozilla/EventForwards.h"
|
#include "mozilla/EventForwards.h"
|
||||||
#include "mozilla/EventListenerManager.h"
|
#include "mozilla/EventListenerManager.h"
|
||||||
|
@ -1166,9 +1167,25 @@ mozilla::ipc::IPCResult BrowserChild::RecvUpdateDimensions(
|
||||||
ScreenIntSize screenSize = GetInnerSize();
|
ScreenIntSize screenSize = GetInnerSize();
|
||||||
ScreenIntRect screenRect = GetOuterRect();
|
ScreenIntRect screenRect = GetOuterRect();
|
||||||
|
|
||||||
// Set the size on the document viewer before we update the widget and
|
{
|
||||||
// trigger a reflow. Otherwise the MobileViewportManager reads the stale
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
// size from the content viewer when it computes a new CSS viewport.
|
// For some reason on geckoview-junit tests we get multiple reflows on the
|
||||||
|
// top-level presShell, but with different sizes. This seems kinda wrong,
|
||||||
|
// but for now let's just leave it as-is and not squash them, since handling
|
||||||
|
// the multiple reflows in order might be important. Filed bug 1646261 to
|
||||||
|
// investigate this more closely.
|
||||||
|
#else
|
||||||
|
AutoResizeReflowSquasher squasher(GetTopLevelPresShell());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Make sure to set the size on the document viewer and the widget before
|
||||||
|
// triggering a reflow. We do this by capturing the reflows and making
|
||||||
|
// that happen at the end of this scoped block, using the squasher.
|
||||||
|
// The MobileViewportManager needs the content viewer size to be updated
|
||||||
|
// before the reflow, otherwise it gets a stale size when it computes
|
||||||
|
// a new CSS viewport. Similarly, the widget size needs to be updated before
|
||||||
|
// the root scrollframe figures out which scrollbars are needed because
|
||||||
|
// it might read the composition size from the widget.
|
||||||
nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(WebNavigation());
|
nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(WebNavigation());
|
||||||
baseWin->SetPositionAndSize(0, 0, screenSize.width, screenSize.height,
|
baseWin->SetPositionAndSize(0, 0, screenSize.width, screenSize.height,
|
||||||
nsIBaseWindow::eRepaint);
|
nsIBaseWindow::eRepaint);
|
||||||
|
@ -1176,6 +1193,7 @@ mozilla::ipc::IPCResult BrowserChild::RecvUpdateDimensions(
|
||||||
mPuppetWidget->Resize(screenRect.x + mClientOffset.x + mChromeOffset.x,
|
mPuppetWidget->Resize(screenRect.x + mClientOffset.x + mChromeOffset.x,
|
||||||
screenRect.y + mClientOffset.y + mChromeOffset.y,
|
screenRect.y + mClientOffset.y + mChromeOffset.y,
|
||||||
screenSize.width, screenSize.height, true);
|
screenSize.width, screenSize.height, true);
|
||||||
|
}
|
||||||
|
|
||||||
RecvSafeAreaInsetsChanged(mPuppetWidget->GetSafeAreaInsets());
|
RecvSafeAreaInsetsChanged(mPuppetWidget->GetSafeAreaInsets());
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "AutoResizeReflowSquasher.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
StaticRefPtr<PresShell> AutoResizeReflowSquasher::sPresShell;
|
||||||
|
bool AutoResizeReflowSquasher::sHasCapture = false;
|
||||||
|
nscoord AutoResizeReflowSquasher::sWidth = 0;
|
||||||
|
nscoord AutoResizeReflowSquasher::sHeight = 0;
|
||||||
|
ResizeReflowOptions AutoResizeReflowSquasher::sOptions =
|
||||||
|
ResizeReflowOptions::NoOption;
|
||||||
|
|
||||||
|
AutoResizeReflowSquasher::AutoResizeReflowSquasher(PresShell* aShell) {
|
||||||
|
// Don't allow nested AutoResizeReflowSquashers. Note that aShell may
|
||||||
|
// be null, in which case this AutoResizeReflowSquasher should behave as
|
||||||
|
// though it was never created. In this scenario nested instances are
|
||||||
|
// allowed.
|
||||||
|
MOZ_ASSERT(!sPresShell);
|
||||||
|
sPresShell = aShell;
|
||||||
|
MOZ_ASSERT(!sHasCapture);
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoResizeReflowSquasher::~AutoResizeReflowSquasher() {
|
||||||
|
RefPtr<PresShell> presShell = sPresShell;
|
||||||
|
sPresShell = nullptr;
|
||||||
|
if (sHasCapture) {
|
||||||
|
presShell->ResizeReflow(sWidth, sHeight, sOptions);
|
||||||
|
sHasCapture = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AutoResizeReflowSquasher::CaptureResizeReflow(
|
||||||
|
PresShell* aShell, nscoord aWidth, nscoord aHeight,
|
||||||
|
ResizeReflowOptions aOptions) {
|
||||||
|
if (!sPresShell) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (sPresShell.get() != aShell) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!sHasCapture) {
|
||||||
|
sHasCapture = true;
|
||||||
|
sWidth = aWidth;
|
||||||
|
sHeight = aHeight;
|
||||||
|
sOptions = aOptions;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(sWidth == aWidth);
|
||||||
|
MOZ_ASSERT(sHeight == aHeight);
|
||||||
|
MOZ_ASSERT(sOptions == aOptions);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mozilla
|
|
@ -0,0 +1,40 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_AutoResizeReflowSquasher_h_
|
||||||
|
#define mozilla_AutoResizeReflowSquasher_h_
|
||||||
|
|
||||||
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "mozilla/PresShellForwards.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
// Put one of these on the stack to "capture" any calls to aShell->ResizeReflow
|
||||||
|
// and have them execute when this class is destroyed.
|
||||||
|
// This effectively "squashes" together multiple calls to ResizeReflow and
|
||||||
|
// combines them into one call at the end of the scope that contains this
|
||||||
|
// RAII class. Note that only calls to ResizeReflow on a particular shell are
|
||||||
|
// captured, and they must all have the same arguments, otherwise an assertion
|
||||||
|
// will be thrown.
|
||||||
|
class MOZ_RAII AutoResizeReflowSquasher {
|
||||||
|
public:
|
||||||
|
explicit AutoResizeReflowSquasher(PresShell* aShell);
|
||||||
|
MOZ_CAN_RUN_SCRIPT ~AutoResizeReflowSquasher();
|
||||||
|
static bool CaptureResizeReflow(PresShell* aShell, nscoord aWidth,
|
||||||
|
nscoord aHeight,
|
||||||
|
ResizeReflowOptions aOptions);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static StaticRefPtr<PresShell> sPresShell;
|
||||||
|
static bool sHasCapture;
|
||||||
|
static nscoord sWidth;
|
||||||
|
static nscoord sHeight;
|
||||||
|
static ResizeReflowOptions sOptions;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_AutoResizeReflowSquasher_h_
|
|
@ -12,6 +12,7 @@
|
||||||
#include "mozilla/dom/FontFaceSet.h"
|
#include "mozilla/dom/FontFaceSet.h"
|
||||||
#include "mozilla/ArrayUtils.h"
|
#include "mozilla/ArrayUtils.h"
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "mozilla/AutoResizeReflowSquasher.h"
|
||||||
#include "mozilla/AutoRestore.h"
|
#include "mozilla/AutoRestore.h"
|
||||||
#include "mozilla/ContentIterator.h"
|
#include "mozilla/ContentIterator.h"
|
||||||
#include "mozilla/EventDispatcher.h"
|
#include "mozilla/EventDispatcher.h"
|
||||||
|
@ -1939,6 +1940,11 @@ void PresShell::sPaintSuppressionCallback(nsITimer* aTimer, void* aPresShell) {
|
||||||
|
|
||||||
nsresult PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight,
|
nsresult PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight,
|
||||||
ResizeReflowOptions aOptions) {
|
ResizeReflowOptions aOptions) {
|
||||||
|
if (AutoResizeReflowSquasher::CaptureResizeReflow(this, aWidth, aHeight,
|
||||||
|
aOptions)) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (mZoomConstraintsClient) {
|
if (mZoomConstraintsClient) {
|
||||||
// If we have a ZoomConstraintsClient and the available screen area
|
// If we have a ZoomConstraintsClient and the available screen area
|
||||||
// changed, then we might need to disable double-tap-to-zoom, so notify
|
// changed, then we might need to disable double-tap-to-zoom, so notify
|
||||||
|
|
|
@ -72,6 +72,7 @@ EXPORTS += [
|
||||||
EXPORTS.mozilla += [
|
EXPORTS.mozilla += [
|
||||||
'AccessibleCaretEventHub.h',
|
'AccessibleCaretEventHub.h',
|
||||||
'ArenaObjectID.h',
|
'ArenaObjectID.h',
|
||||||
|
'AutoResizeReflowSquasher.h',
|
||||||
'GeckoMVMContext.h',
|
'GeckoMVMContext.h',
|
||||||
'GeometryUtils.h',
|
'GeometryUtils.h',
|
||||||
'MediaEmulationData.h',
|
'MediaEmulationData.h',
|
||||||
|
@ -99,6 +100,7 @@ UNIFIED_SOURCES += [
|
||||||
'AccessibleCaret.cpp',
|
'AccessibleCaret.cpp',
|
||||||
'AccessibleCaretEventHub.cpp',
|
'AccessibleCaretEventHub.cpp',
|
||||||
'AccessibleCaretManager.cpp',
|
'AccessibleCaretManager.cpp',
|
||||||
|
'AutoResizeReflowSquasher.cpp',
|
||||||
'GeckoMVMContext.cpp',
|
'GeckoMVMContext.cpp',
|
||||||
'GeometryUtils.cpp',
|
'GeometryUtils.cpp',
|
||||||
'LayoutLogging.cpp',
|
'LayoutLogging.cpp',
|
||||||
|
|
Загрузка…
Ссылка в новой задаче