зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1503656 - Part 7. Notify of safe area insets changed. r=smaug
Since safe area insets uses on content, we need send it from chrome process to content process. SafeAreaInsetsChanged will be called per window position/size change (Next patch is Android implementation for it), we have to calculate safe area insets on widget/window per change. Current implementation is that this value is top level document only like Blink since https://github.com/w3c/csswg-drafts/issues/4670 isn't resolved yet. Differential Revision: https://phabricator.services.mozilla.com/D55084 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
e3d1ff0f27
Коммит
6279258383
|
@ -10377,3 +10377,52 @@ bool nsContentUtils::IsURIInList(nsIURI* aURI, const nsCString& aBlackList) {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */
|
||||
ScreenIntMargin nsContentUtils::GetWindowSafeAreaInsets(
|
||||
nsIScreen* aScreen, const ScreenIntMargin& aSafeAreaInsets,
|
||||
const LayoutDeviceIntRect& aWindowRect) {
|
||||
// This calculates safe area insets of window from screen rectangle, window
|
||||
// rectangle and safe area insets of screen.
|
||||
//
|
||||
// +----------------------------------------+ <-- screen
|
||||
// | +-------------------------------+ <------- window
|
||||
// | | window's safe area inset top) | |
|
||||
// +--+-------------------------------+--+ |
|
||||
// | | | |<------ safe area rectangle of
|
||||
// | | | | | screen
|
||||
// +--+-------------------------------+--+ |
|
||||
// | |window's safe area inset bottom| |
|
||||
// | +-------------------------------+ |
|
||||
// +----------------------------------------+
|
||||
//
|
||||
ScreenIntMargin windowSafeAreaInsets;
|
||||
|
||||
int32_t screenLeft, screenTop, screenWidth, screenHeight;
|
||||
nsresult rv =
|
||||
aScreen->GetRect(&screenLeft, &screenTop, &screenWidth, &screenHeight);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return windowSafeAreaInsets;
|
||||
}
|
||||
|
||||
// Screen's rect of safe area
|
||||
LayoutDeviceIntRect safeAreaRect(
|
||||
screenLeft + aSafeAreaInsets.left, screenTop + aSafeAreaInsets.top,
|
||||
screenWidth - aSafeAreaInsets.right - aSafeAreaInsets.left,
|
||||
screenHeight - aSafeAreaInsets.bottom - aSafeAreaInsets.top);
|
||||
// window's rect of safe area
|
||||
safeAreaRect = safeAreaRect.Intersect(aWindowRect);
|
||||
|
||||
windowSafeAreaInsets.top = std::max(safeAreaRect.y - aWindowRect.y, 0);
|
||||
windowSafeAreaInsets.left = std::max(safeAreaRect.x - aWindowRect.x, 0);
|
||||
windowSafeAreaInsets.right =
|
||||
std::max((aWindowRect.x + aWindowRect.width) -
|
||||
(safeAreaRect.x + safeAreaRect.width),
|
||||
0);
|
||||
windowSafeAreaInsets.bottom =
|
||||
std::max(aWindowRect.y + aWindowRect.height -
|
||||
(safeAreaRect.y + safeAreaRect.height),
|
||||
0);
|
||||
|
||||
return windowSafeAreaInsets;
|
||||
}
|
||||
|
|
|
@ -3224,6 +3224,14 @@ class nsContentUtils {
|
|||
|
||||
static nsGlobalWindowInner* CallerInnerWindow();
|
||||
|
||||
/*
|
||||
* Return safe area insets of window that defines as
|
||||
* https://drafts.csswg.org/css-env-1/#safe-area-insets.
|
||||
*/
|
||||
static mozilla::ScreenIntMargin GetWindowSafeAreaInsets(
|
||||
nsIScreen* aScreen, const mozilla::ScreenIntMargin& aSafeareaInsets,
|
||||
const mozilla::LayoutDeviceIntRect& aWindowRect);
|
||||
|
||||
private:
|
||||
static bool InitializeEventTable();
|
||||
|
||||
|
|
|
@ -1264,6 +1264,8 @@ mozilla::ipc::IPCResult BrowserChild::RecvUpdateDimensions(
|
|||
dispatcher->PostDOMEvent();
|
||||
}
|
||||
|
||||
RecvSafeAreaInsetsChanged(mPuppetWidget->GetSafeAreaInsets());
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
@ -3255,6 +3257,44 @@ mozilla::ipc::IPCResult BrowserChild::RecvThemeChanged(
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult BrowserChild::RecvSafeAreaInsetsChanged(
|
||||
const mozilla::ScreenIntMargin& aSafeAreaInsets) {
|
||||
mPuppetWidget->UpdateSafeAreaInsets(aSafeAreaInsets);
|
||||
|
||||
nsCOMPtr<nsIScreenManager> screenMgr =
|
||||
do_GetService("@mozilla.org/gfx/screenmanager;1");
|
||||
ScreenIntMargin currentSafeAreaInsets;
|
||||
if (screenMgr) {
|
||||
// aSafeAreaInsets is for current screen. But we have to calculate
|
||||
// safe insets for content window.
|
||||
int32_t x, y, cx, cy;
|
||||
GetDimensions(0, &x, &y, &cx, &cy);
|
||||
nsCOMPtr<nsIScreen> screen;
|
||||
screenMgr->ScreenForRect(x, y, cx, cy, getter_AddRefs(screen));
|
||||
|
||||
if (screen) {
|
||||
LayoutDeviceIntRect windowRect(x + mClientOffset.x + mChromeOffset.x,
|
||||
y + mClientOffset.y + mChromeOffset.y, cx,
|
||||
cy);
|
||||
currentSafeAreaInsets = nsContentUtils::GetWindowSafeAreaInsets(
|
||||
screen, aSafeAreaInsets, windowRect);
|
||||
}
|
||||
}
|
||||
|
||||
if (nsCOMPtr<Document> document = GetTopLevelDocument()) {
|
||||
nsPresContext* presContext = document->GetPresContext();
|
||||
if (presContext) {
|
||||
presContext->SetSafeAreaInsets(currentSafeAreaInsets);
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/w3c/csswg-drafts/issues/4670
|
||||
// Actually we don't set this value on sub document. This behaviour is
|
||||
// same as Blink that safe area insets isn't set on sub document.
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult BrowserChild::RecvAwaitLargeAlloc() {
|
||||
mAwaitingLA = true;
|
||||
return IPC_OK();
|
||||
|
|
|
@ -406,6 +406,9 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
|
|||
mozilla::ipc::IPCResult RecvSwappedWithOtherRemoteLoader(
|
||||
const IPCTabContext& aContext);
|
||||
|
||||
mozilla::ipc::IPCResult RecvSafeAreaInsetsChanged(
|
||||
const mozilla::ScreenIntMargin& aSafeAreaInsets);
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
PDocAccessibleChild* AllocPDocAccessibleChild(PDocAccessibleChild*,
|
||||
const uint64_t&,
|
||||
|
|
|
@ -935,9 +935,15 @@ void BrowserParent::InitRendering() {
|
|||
Unused << SendInitRendering(textureFactoryIdentifier, layersId,
|
||||
mRemoteLayerTreeOwner.GetCompositorOptions(),
|
||||
mRemoteLayerTreeOwner.IsLayersConnected());
|
||||
|
||||
RefPtr<nsIWidget> widget = GetTopLevelWidget();
|
||||
if (widget) {
|
||||
ScreenIntMargin safeAreaInsets = widget->GetSafeAreaInsets();
|
||||
Unused << SendSafeAreaInsetsChanged(safeAreaInsets);
|
||||
}
|
||||
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
if (XRE_IsParentProcess()) {
|
||||
RefPtr<nsIWidget> widget = GetTopLevelWidget();
|
||||
MOZ_ASSERT(widget);
|
||||
|
||||
Unused << SendDynamicToolbarMaxHeightChanged(
|
||||
|
|
|
@ -41,6 +41,7 @@ using mozilla::gfx::SurfaceFormat from "mozilla/gfx/Types.h";
|
|||
using mozilla::LayoutDeviceIntPoint from "Units.h";
|
||||
using mozilla::LayoutDevicePoint from "Units.h";
|
||||
using mozilla::ScreenIntCoord from "Units.h";
|
||||
using mozilla::ScreenIntMargin from "Units.h";
|
||||
using mozilla::ScreenIntPoint from "Units.h";
|
||||
using ScreenRect from "Units.h";
|
||||
using struct mozilla::layers::ScrollableLayerGuid from "mozilla/layers/ScrollableLayerGuid.h";
|
||||
|
@ -935,6 +936,12 @@ child:
|
|||
*/
|
||||
async ThemeChanged(LookAndFeelInt[] lookAndFeelIntCache);
|
||||
|
||||
/**
|
||||
* Tell the child that the safe area of widget has changed.
|
||||
*
|
||||
*/
|
||||
async SafeAreaInsetsChanged(ScreenIntMargin aSafeAreaInsets);
|
||||
|
||||
/**
|
||||
* Tell the browser that its frame loader has been swapped
|
||||
* with another.
|
||||
|
|
|
@ -609,6 +609,26 @@ struct ParamTraits<mozilla::gfx::MarginTyped<T>> {
|
|||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct ParamTraits<mozilla::gfx::IntMarginTyped<T>> {
|
||||
typedef mozilla::gfx::IntMarginTyped<T> paramType;
|
||||
|
||||
static void Write(Message* msg, const paramType& param) {
|
||||
WriteParam(msg, param.top);
|
||||
WriteParam(msg, param.right);
|
||||
WriteParam(msg, param.bottom);
|
||||
WriteParam(msg, param.left);
|
||||
}
|
||||
|
||||
static bool Read(const Message* msg, PickleIterator* iter,
|
||||
paramType* result) {
|
||||
return (ReadParam(msg, iter, &result->top) &&
|
||||
ReadParam(msg, iter, &result->right) &&
|
||||
ReadParam(msg, iter, &result->bottom) &&
|
||||
ReadParam(msg, iter, &result->left));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<nsRect> {
|
||||
typedef nsRect paramType;
|
||||
|
|
|
@ -811,6 +811,19 @@ nsresult nsDocumentViewer::InitPresentationStuff(bool aDoInitialReflow) {
|
|||
mPresContext->SetOverrideDPPX(mOverrideDPPX);
|
||||
}
|
||||
|
||||
if (mWindow && mDocument->IsTopLevelContentDocument()) {
|
||||
// Set initial safe area insets
|
||||
ScreenIntMargin windowSafeAreaInsets;
|
||||
LayoutDeviceIntRect windowRect = mWindow->GetScreenBounds();
|
||||
nsCOMPtr<nsIScreen> screen = mWindow->GetWidgetScreen();
|
||||
if (screen) {
|
||||
windowSafeAreaInsets = nsContentUtils::GetWindowSafeAreaInsets(
|
||||
screen, mWindow->GetSafeAreaInsets(), windowRect);
|
||||
}
|
||||
|
||||
mPresContext->SetSafeAreaInsets(windowSafeAreaInsets);
|
||||
}
|
||||
|
||||
if (aDoInitialReflow) {
|
||||
RefPtr<PresShell> presShell = mPresShell;
|
||||
// Initial reflow
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "nsIFrame.h"
|
||||
#include "nsPresArena.h"
|
||||
#include "nsXULPopupManager.h"
|
||||
#include "nsIScreen.h"
|
||||
#include "nsIWidgetListener.h"
|
||||
#include "nsContentUtils.h" // for nsAutoScriptBlocker
|
||||
#include "nsDocShell.h"
|
||||
|
@ -1137,6 +1138,49 @@ nsEventStatus nsView::HandleEvent(WidgetGUIEvent* aEvent,
|
|||
return result;
|
||||
}
|
||||
|
||||
void nsView::SafeAreaInsetsChanged(const ScreenIntMargin& aSafeAreaInsets) {
|
||||
if (!IsRoot()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PresShell* presShell = mViewManager->GetPresShell();
|
||||
if (!presShell) {
|
||||
return;
|
||||
}
|
||||
|
||||
ScreenIntMargin windowSafeAreaInsets;
|
||||
LayoutDeviceIntRect windowRect = mWindow->GetScreenBounds();
|
||||
nsCOMPtr<nsIScreen> screen = mWindow->GetWidgetScreen();
|
||||
if (screen) {
|
||||
windowSafeAreaInsets = nsContentUtils::GetWindowSafeAreaInsets(
|
||||
screen, aSafeAreaInsets, windowRect);
|
||||
}
|
||||
|
||||
presShell->GetPresContext()->SetSafeAreaInsets(windowSafeAreaInsets);
|
||||
|
||||
// https://github.com/w3c/csswg-drafts/issues/4670
|
||||
// Actually we don't set this value on sub document. This behaviour is
|
||||
// same as Blink.
|
||||
|
||||
dom::Document* document = presShell->GetDocument();
|
||||
if (!document) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsPIDOMWindowOuter* window = document->GetWindow();
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsContentUtils::CallOnAllRemoteChildren(
|
||||
window,
|
||||
[windowSafeAreaInsets](dom::BrowserParent* aBrowserParent) -> CallState {
|
||||
Unused << aBrowserParent->SendSafeAreaInsetsChanged(
|
||||
windowSafeAreaInsets);
|
||||
return CallState::Continue;
|
||||
});
|
||||
}
|
||||
|
||||
bool nsView::IsPrimaryFramePaintSuppressed() {
|
||||
return StaticPrefs::layout_show_previous_page() && mFrame &&
|
||||
mFrame->PresShell()->IsPaintingSuppressed();
|
||||
|
|
|
@ -472,6 +472,7 @@ class nsView final : public nsIWidgetListener {
|
|||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||
virtual nsEventStatus HandleEvent(mozilla::WidgetGUIEvent* aEvent,
|
||||
bool aUseAttachedEvents) override;
|
||||
virtual void SafeAreaInsetsChanged(const mozilla::ScreenIntMargin&) override;
|
||||
|
||||
virtual ~nsView();
|
||||
|
||||
|
|
|
@ -1259,6 +1259,15 @@ PuppetScreenManager::ScreenForRect(int32_t inLeft, int32_t inTop,
|
|||
return GetPrimaryScreen(outScreen);
|
||||
}
|
||||
|
||||
ScreenIntMargin PuppetWidget::GetSafeAreaInsets() const {
|
||||
return mSafeAreaInsets;
|
||||
}
|
||||
|
||||
void PuppetWidget::UpdateSafeAreaInsets(
|
||||
const ScreenIntMargin& aSafeAreaInsets) {
|
||||
mSafeAreaInsets = aSafeAreaInsets;
|
||||
}
|
||||
|
||||
nsIWidgetListener* PuppetWidget::GetCurrentWidgetListener() {
|
||||
if (!mPreviouslyAttachedWidgetListener || !mAttachedWidgetListener) {
|
||||
return mAttachedWidgetListener;
|
||||
|
|
|
@ -232,6 +232,10 @@ class PuppetWidget : public nsBaseWidget,
|
|||
|
||||
nsIntSize GetScreenDimensions();
|
||||
|
||||
// safe area insets support
|
||||
virtual ScreenIntMargin GetSafeAreaInsets() const override;
|
||||
void UpdateSafeAreaInsets(const ScreenIntMargin& aSafeAreaInsets);
|
||||
|
||||
// Get the offset to the chrome of the window that this tab belongs to.
|
||||
//
|
||||
// NOTE: In OOP iframes this value is zero. You should use
|
||||
|
@ -399,6 +403,8 @@ class PuppetWidget : public nsBaseWidget,
|
|||
nsCOMPtr<imgIContainer> mCustomCursor;
|
||||
uint32_t mCursorHotspotX, mCursorHotspotY;
|
||||
|
||||
ScreenIntMargin mSafeAreaInsets;
|
||||
|
||||
nsCOMArray<nsIKeyEventInPluginCallback> mKeyEventInPluginCallbacks;
|
||||
|
||||
RefPtr<TextEventDispatcherListener> mNativeTextEventDispatcherListener;
|
||||
|
|
|
@ -33,6 +33,9 @@ bool nsIWidgetListener::WindowResized(nsIWidget* aWidget, int32_t aWidth,
|
|||
|
||||
void nsIWidgetListener::SizeModeChanged(nsSizeMode aSizeMode) {}
|
||||
|
||||
void nsIWidgetListener::SafeAreaInsetsChanged(const mozilla::ScreenIntMargin&) {
|
||||
}
|
||||
|
||||
void nsIWidgetListener::UIResolutionChanged() {}
|
||||
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
|
|
|
@ -185,6 +185,12 @@ class nsIWidgetListener {
|
|||
*/
|
||||
virtual nsEventStatus HandleEvent(mozilla::WidgetGUIEvent* aEvent,
|
||||
bool aUseAttachedEvents);
|
||||
|
||||
/**
|
||||
* Called when safe area insets are changed.
|
||||
*/
|
||||
virtual void SafeAreaInsetsChanged(
|
||||
const mozilla::ScreenIntMargin& aSafeAreaInsets);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче