Skip to content

Commit

Permalink
Bug 1503656 - Part 7. Notify of safe area insets changed. r=smaug
Browse files Browse the repository at this point in the history
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 w3c/csswg-drafts#4670 isn't resolved yet.

Differential Revision: https://phabricator.services.mozilla.com/D55084

--HG--
extra : moz-landing-system : lando
  • Loading branch information
makotokato committed Mar 4, 2020
1 parent e3d1ff0 commit 6279258
Show file tree
Hide file tree
Showing 14 changed files with 216 additions and 1 deletion.
49 changes: 49 additions & 0 deletions dom/base/nsContentUtils.cpp
Expand Up @@ -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;
}
8 changes: 8 additions & 0 deletions dom/base/nsContentUtils.h
Expand Up @@ -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();

Expand Down
40 changes: 40 additions & 0 deletions dom/ipc/BrowserChild.cpp
Expand Up @@ -1264,6 +1264,8 @@ mozilla::ipc::IPCResult BrowserChild::RecvUpdateDimensions(
dispatcher->PostDOMEvent();
}

RecvSafeAreaInsetsChanged(mPuppetWidget->GetSafeAreaInsets());

return IPC_OK();
}

Expand Down Expand Up @@ -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();
Expand Down
3 changes: 3 additions & 0 deletions dom/ipc/BrowserChild.h
Expand Up @@ -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&,
Expand Down
8 changes: 7 additions & 1 deletion dom/ipc/BrowserParent.cpp
Expand Up @@ -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(
Expand Down
7 changes: 7 additions & 0 deletions dom/ipc/PBrowser.ipdl
Expand Up @@ -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";
Expand Down Expand Up @@ -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.
Expand Down
20 changes: 20 additions & 0 deletions gfx/ipc/GfxMessageUtils.h
Expand Up @@ -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;
Expand Down
13 changes: 13 additions & 0 deletions layout/base/nsDocumentViewer.cpp
Expand Up @@ -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
Expand Down
44 changes: 44 additions & 0 deletions view/nsView.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -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();
Expand Down
1 change: 1 addition & 0 deletions view/nsView.h
Expand Up @@ -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();

Expand Down
9 changes: 9 additions & 0 deletions widget/PuppetWidget.cpp
Expand Up @@ -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;
Expand Down
6 changes: 6 additions & 0 deletions widget/PuppetWidget.h
Expand Up @@ -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
Expand Down Expand Up @@ -399,6 +403,8 @@ class PuppetWidget : public nsBaseWidget,
nsCOMPtr<imgIContainer> mCustomCursor;
uint32_t mCursorHotspotX, mCursorHotspotY;

ScreenIntMargin mSafeAreaInsets;

nsCOMArray<nsIKeyEventInPluginCallback> mKeyEventInPluginCallbacks;

RefPtr<TextEventDispatcherListener> mNativeTextEventDispatcherListener;
Expand Down
3 changes: 3 additions & 0 deletions widget/nsIWidgetListener.cpp
Expand Up @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions widget/nsIWidgetListener.h
Expand Up @@ -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

0 comments on commit 6279258

Please sign in to comment.