diff --git a/dom/ipc/BrowserChild.cpp b/dom/ipc/BrowserChild.cpp index bc68ba771941..2b2362181264 100644 --- a/dom/ipc/BrowserChild.cpp +++ b/dom/ipc/BrowserChild.cpp @@ -1349,6 +1349,21 @@ mozilla::ipc::IPCResult BrowserChild::RecvDynamicToolbarMaxHeightChanged( return IPC_OK(); } +mozilla::ipc::IPCResult BrowserChild::RecvDynamicToolbarOffsetChanged( + const ScreenIntCoord& aOffset) { +#if defined(MOZ_WIDGET_ANDROID) + RefPtr document = GetTopLevelDocument(); + if (!document) { + return IPC_OK(); + } + + if (nsPresContext* presContext = document->GetPresContext()) { + presContext->UpdateDynamicToolbarOffset(aOffset); + } +#endif + return IPC_OK(); +} + mozilla::ipc::IPCResult BrowserChild::RecvSuppressDisplayport( const bool& aEnabled) { if (RefPtr presShell = GetTopLevelPresShell()) { diff --git a/dom/ipc/BrowserChild.h b/dom/ipc/BrowserChild.h index b684c3c4e27f..2476783ffcca 100644 --- a/dom/ipc/BrowserChild.h +++ b/dom/ipc/BrowserChild.h @@ -293,6 +293,9 @@ class BrowserChild final : public nsMessageManagerScriptExecutor, mozilla::ipc::IPCResult RecvDynamicToolbarMaxHeightChanged( const mozilla::ScreenIntCoord& aHeight); + mozilla::ipc::IPCResult RecvDynamicToolbarOffsetChanged( + const mozilla::ScreenIntCoord& aOffset); + mozilla::ipc::IPCResult RecvActivate(); mozilla::ipc::IPCResult RecvDeactivate(); diff --git a/dom/ipc/BrowserParent.cpp b/dom/ipc/BrowserParent.cpp index 875ee12bd84e..31cbe74fce4f 100644 --- a/dom/ipc/BrowserParent.cpp +++ b/dom/ipc/BrowserParent.cpp @@ -1097,6 +1097,12 @@ void BrowserParent::DynamicToolbarMaxHeightChanged(ScreenIntCoord aHeight) { Unused << SendDynamicToolbarMaxHeightChanged(aHeight); } } + +void BrowserParent::DynamicToolbarOffsetChanged(ScreenIntCoord aOffset) { + if (!mIsDestroyed) { + Unused << SendDynamicToolbarOffsetChanged(aOffset); + } +} #endif void BrowserParent::HandleAccessKey(const WidgetKeyboardEvent& aEvent, diff --git a/dom/ipc/BrowserParent.h b/dom/ipc/BrowserParent.h index 5d3abeeb26da..d88882f6ba71 100644 --- a/dom/ipc/BrowserParent.h +++ b/dom/ipc/BrowserParent.h @@ -535,6 +535,7 @@ class BrowserParent final : public PBrowserParent, #if defined(MOZ_WIDGET_ANDROID) void DynamicToolbarMaxHeightChanged(ScreenIntCoord aHeight); + void DynamicToolbarOffsetChanged(ScreenIntCoord aOffset); #endif void Activate(); diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index 4f2302671e00..6fed5b6b6463 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -753,6 +753,8 @@ child: async DynamicToolbarMaxHeightChanged(ScreenIntCoord height); + async DynamicToolbarOffsetChanged(ScreenIntCoord height); + async ParentActivated(bool aActivated); async SetKeyboardIndicators(UIStateChangeType showFocusRings); diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp index 3a946f72a6bb..7da0f946c49f 100644 --- a/layout/base/PresShell.cpp +++ b/layout/base/PresShell.cpp @@ -10418,6 +10418,10 @@ static void SetPluginIsActive(nsISupports* aSupports, void* aClosure) { nsresult PresShell::SetIsActive(bool aIsActive) { MOZ_ASSERT(mDocument, "should only be called with a document"); +#if defined(MOZ_WIDGET_ANDROID) + const bool changed = mIsActive != aIsActive; +#endif + mIsActive = aIsActive; nsPresContext* presContext = GetPresContext(); @@ -10439,6 +10443,17 @@ nsresult PresShell::SetIsActive(bool aIsActive) { } } #endif // #ifdef ACCESSIBILITY + +#if defined(MOZ_WIDGET_ANDROID) + if (changed && !aIsActive && presContext && + presContext->IsRootContentDocumentCrossProcess()) { + if (BrowserChild* browserChild = BrowserChild::GetFrom(this)) { + // Reset the dynamic toolbar offset state. + presContext->UpdateDynamicToolbarOffset(0); + } + } +#endif + return rv; } diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index 42add327123f..38dd3b4cc1c7 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -2535,6 +2535,19 @@ void nsPresContext::AdjustSizeForViewportUnits() { NSIntPixelsToAppUnits(mDynamicToolbarMaxHeight, mCurAppUnitsPerDevPixel); } +void nsPresContext::UpdateDynamicToolbarOffset(ScreenIntCoord aOffset) { + MOZ_ASSERT(IsRootContentDocumentCrossProcess()); + if (!mPresShell) { + return; + } + + if (!HasDynamicToolbar()) { + return; + } + + MOZ_ASSERT(-mDynamicToolbarMaxHeight <= aOffset && aOffset <= 0); +} + #ifdef DEBUG void nsPresContext::ValidatePresShellAndDocumentReleation() const { diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h index 336e2e20e76b..2cb89113484e 100644 --- a/layout/base/nsPresContext.h +++ b/layout/base/nsPresContext.h @@ -392,6 +392,11 @@ class nsPresContext : public nsISupports, return mDynamicToolbarMaxHeight > 0; } + /* + * |aOffset| must be offset from the bottom edge of the ICB and it's negative. + */ + void UpdateDynamicToolbarOffset(mozilla::ScreenIntCoord aOffset); + /** * Return true if this presentation context is a paginated * context. diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java index 3ca86b151b80..6bca608ea04d 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java @@ -222,7 +222,7 @@ public class GeckoSession implements Parcelable { @WrapForJNI(calledFrom = "ui", dispatchTo = "current") public native void setMaxToolbarHeight(int height); - @WrapForJNI(calledFrom = "ui", dispatchTo = "current") + @WrapForJNI(calledFrom = "ui", dispatchTo = "gecko") public native void setFixedBottomOffset(int offset); @WrapForJNI(calledFrom = "ui", dispatchTo = "current") diff --git a/view/nsView.cpp b/view/nsView.cpp index 488c97e3c0ab..29fb909e5679 100644 --- a/view/nsView.cpp +++ b/view/nsView.cpp @@ -999,6 +999,43 @@ void nsView::DynamicToolbarMaxHeightChanged(ScreenIntCoord aHeight) { nsContentUtils::CallOnAllRemoteChildren( window, NotifyDynamicToolbarMaxHeightChanged, &aHeight); } + +static bool NotifyDynamicToolbarOffsetChanged( + dom::BrowserParent* aBrowserParent, void* aArg) { + // Skip background tabs. + if (!aBrowserParent->GetDocShellIsActive()) { + return false; + } + + ScreenIntCoord* offset = static_cast(aArg); + aBrowserParent->DynamicToolbarOffsetChanged(*offset); + return true; +} + +void nsView::DynamicToolbarOffsetChanged(ScreenIntCoord aOffset) { + MOZ_ASSERT(XRE_IsParentProcess(), + "Should be only called for the browser parent process"); + MOZ_ASSERT(this == mViewManager->GetRootView(), + "Should be called for the root view"); + + PresShell* presShell = mViewManager->GetPresShell(); + if (!presShell) { + return; + } + + dom::Document* document = presShell->GetDocument(); + if (!document) { + return; + } + + nsPIDOMWindowOuter* window = document->GetWindow(); + if (!window) { + return; + } + + nsContentUtils::CallOnAllRemoteChildren( + window, NotifyDynamicToolbarOffsetChanged, &aOffset); +} #endif bool nsView::RequestWindowClose(nsIWidget* aWidget) { diff --git a/view/nsView.h b/view/nsView.h index 04d369d22c6c..7350cf66a278 100644 --- a/view/nsView.h +++ b/view/nsView.h @@ -452,6 +452,8 @@ class nsView final : public nsIWidgetListener { #if defined(MOZ_WIDGET_ANDROID) virtual void DynamicToolbarMaxHeightChanged( mozilla::ScreenIntCoord aHeight) override; + virtual void DynamicToolbarOffsetChanged( + mozilla::ScreenIntCoord aOffset) override; #endif virtual bool RequestWindowClose(nsIWidget* aWidget) override; MOZ_CAN_RUN_SCRIPT_BOUNDARY diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp index ef89728b21ae..39b85fbad840 100644 --- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -1090,11 +1090,18 @@ class nsWindow::LayerViewSupport final } void SetFixedBottomOffset(int32_t aOffset) { - MOZ_ASSERT(AndroidBridge::IsJavaUiThread()); + if (mWindow) { + mWindow->UpdateDynamicToolbarOffset(ScreenIntCoord(aOffset)); + } - if (RefPtr child = - GetUiCompositorControllerChild()) { - child->SetFixedBottomOffset(aOffset); + if (RefPtr uiThread = GetAndroidUiThread()) { + uiThread->Dispatch(NS_NewRunnableFunction( + "LayerViewSupport::SetFixedBottomOffset", [this, offset = aOffset] { + if (RefPtr child = + GetUiCompositorControllerChild()) { + child->SetFixedBottomOffset(offset); + } + })); } } @@ -2326,6 +2333,16 @@ void nsWindow::UpdateDynamicToolbarMaxHeight(ScreenIntCoord aHeight) { } } +void nsWindow::UpdateDynamicToolbarOffset(ScreenIntCoord aOffset) { + if (mWidgetListener) { + mWidgetListener->DynamicToolbarOffsetChanged(aOffset); + } + + if (mAttachedWidgetListener) { + mAttachedWidgetListener->DynamicToolbarOffsetChanged(aOffset); + } +} + nsresult nsWindow::SetPrefersReducedMotionOverrideForTest(bool aValue) { nsXPLookAndFeel::GetInstance()->SetPrefersReducedMotionOverrideForTest( aValue); diff --git a/widget/android/nsWindow.h b/widget/android/nsWindow.h index 7821b50832e7..ad995c0ebefb 100644 --- a/widget/android/nsWindow.h +++ b/widget/android/nsWindow.h @@ -330,6 +330,8 @@ class nsWindow final : public nsBaseWidget { nsresult SetPrefersReducedMotionOverrideForTest(bool aValue) override; nsresult ResetPrefersReducedMotionOverrideForTest() override; + void UpdateDynamicToolbarOffset(mozilla::ScreenIntCoord aOffset); + protected: void BringToFront(); nsWindow* FindTopLevel(); diff --git a/widget/nsIWidgetListener.cpp b/widget/nsIWidgetListener.cpp index 5c2aede0fe5e..e4a063d681c6 100644 --- a/widget/nsIWidgetListener.cpp +++ b/widget/nsIWidgetListener.cpp @@ -38,6 +38,7 @@ void nsIWidgetListener::UIResolutionChanged() {} #if defined(MOZ_WIDGET_ANDROID) void nsIWidgetListener::DynamicToolbarMaxHeightChanged(ScreenIntCoord aHeight) { } +void nsIWidgetListener::DynamicToolbarOffsetChanged(ScreenIntCoord aOffset) {} #endif void nsIWidgetListener::FullscreenWillChange(bool aInFullscreen) {} diff --git a/widget/nsIWidgetListener.h b/widget/nsIWidgetListener.h index 70e1d665fe33..94b865141f6a 100644 --- a/widget/nsIWidgetListener.h +++ b/widget/nsIWidgetListener.h @@ -87,6 +87,7 @@ class nsIWidgetListener { #if defined(MOZ_WIDGET_ANDROID) virtual void DynamicToolbarMaxHeightChanged(mozilla::ScreenIntCoord aHeight); + virtual void DynamicToolbarOffsetChanged(mozilla::ScreenIntCoord aOffset); #endif /**