diff --git a/dom/ipc/BrowserChild.cpp b/dom/ipc/BrowserChild.cpp index 4069f7bae76c..fcf7239df341 100644 --- a/dom/ipc/BrowserChild.cpp +++ b/dom/ipc/BrowserChild.cpp @@ -278,6 +278,7 @@ BrowserChild::BrowserChild(ContentChild* aManager, const TabId& aTabId, mLayersId{0}, mEffectsInfo{EffectsInfo::FullyHidden()}, mDynamicToolbarMaxHeight(0), + mKeyboardHeight(0), mUniqueId(aTabId), mDidFakeShow(false), mTriedBrowserInit(false), @@ -1237,6 +1238,23 @@ mozilla::ipc::IPCResult BrowserChild::RecvDynamicToolbarOffsetChanged( return IPC_OK(); } +mozilla::ipc::IPCResult BrowserChild::RecvKeyboardHeightChanged( + const ScreenIntCoord& aHeight) { +#if defined(MOZ_WIDGET_ANDROID) + mKeyboardHeight = aHeight; + + RefPtr document = GetTopLevelDocument(); + if (!document) { + return IPC_OK(); + } + + if (nsPresContext* presContext = document->GetPresContext()) { + presContext->UpdateKeyboardHeight(aHeight); + } +#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 4f9f144f5c8e..88dffe219f55 100644 --- a/dom/ipc/BrowserChild.h +++ b/dom/ipc/BrowserChild.h @@ -284,6 +284,9 @@ class BrowserChild final : public nsMessageManagerScriptExecutor, mozilla::ipc::IPCResult RecvDynamicToolbarOffsetChanged( const mozilla::ScreenIntCoord& aOffset); + mozilla::ipc::IPCResult RecvKeyboardHeightChanged( + const mozilla::ScreenIntCoord& aHeight); + mozilla::ipc::IPCResult RecvActivate(uint64_t aActionId); mozilla::ipc::IPCResult RecvDeactivate(uint64_t aActionId); @@ -552,6 +555,7 @@ class BrowserChild final : public nsMessageManagerScriptExecutor, ScreenIntCoord GetDynamicToolbarMaxHeight() const { return mDynamicToolbarMaxHeight; }; + mozilla::ScreenIntCoord GetKeyboardHeight() const { return mKeyboardHeight; } bool IPCOpen() const { return mIPCOpen; } @@ -813,6 +817,8 @@ class BrowserChild final : public nsMessageManagerScriptExecutor, // NOTE: This value is valuable only for the top level browser. LayoutDeviceIntPoint mChromeOffset; ScreenIntCoord mDynamicToolbarMaxHeight; + // The software keyboard height. + ScreenIntCoord mKeyboardHeight; TabId mUniqueId; bool mDidFakeShow : 1; diff --git a/dom/ipc/BrowserParent.cpp b/dom/ipc/BrowserParent.cpp index 2a871ddc7181..015f021ef597 100644 --- a/dom/ipc/BrowserParent.cpp +++ b/dom/ipc/BrowserParent.cpp @@ -1213,6 +1213,12 @@ void BrowserParent::DynamicToolbarOffsetChanged(ScreenIntCoord aOffset) { Unused << SendDynamicToolbarOffsetChanged(aOffset); } } + +void BrowserParent::KeyboardHeightChanged(ScreenIntCoord aHeight) { + if (!mIsDestroyed) { + Unused << SendKeyboardHeightChanged(aHeight); + } +} #endif void BrowserParent::HandleAccessKey(const WidgetKeyboardEvent& aEvent, diff --git a/dom/ipc/BrowserParent.h b/dom/ipc/BrowserParent.h index 6bd8178d5309..38f24d5767a7 100644 --- a/dom/ipc/BrowserParent.h +++ b/dom/ipc/BrowserParent.h @@ -487,6 +487,7 @@ class BrowserParent final : public PBrowserParent, #if defined(MOZ_WIDGET_ANDROID) void DynamicToolbarMaxHeightChanged(ScreenIntCoord aHeight); void DynamicToolbarOffsetChanged(ScreenIntCoord aOffset); + void KeyboardHeightChanged(ScreenIntCoord aHeight); #endif void Activate(uint64_t aActionId); diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index 92519762c0b0..9b62de7a9b87 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -697,7 +697,9 @@ child: async DynamicToolbarMaxHeightChanged(ScreenIntCoord height); - async DynamicToolbarOffsetChanged(ScreenIntCoord height); + async DynamicToolbarOffsetChanged(ScreenIntCoord offset); + + async KeyboardHeightChanged(ScreenIntCoord height); /** * StopIMEStateManagement() is called when the process loses focus and diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index 4caefe16c48a..faa2c6f10552 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -246,6 +246,7 @@ nsPresContext::nsPresContext(dom::Document* aDocument, nsPresContextType aType) mCurAppUnitsPerDevPixel(0), mDynamicToolbarMaxHeight(0), mDynamicToolbarHeight(0), + mKeyboardHeight(0), mPageSize(-1, -1), mPageScale(0.0), mPPScale(1.0f), @@ -716,13 +717,15 @@ nsresult nsPresContext::Init(nsDeviceContext* aDeviceContext) { mEventManager->SetPresContext(this); #if defined(MOZ_WIDGET_ANDROID) - if (IsRootContentDocumentCrossProcess() && - MOZ_LIKELY( - !Preferences::HasUserValue("layout.dynamic-toolbar-max-height"))) { - if (BrowserChild* browserChild = - BrowserChild::GetFrom(mDocument->GetDocShell())) { - mDynamicToolbarMaxHeight = browserChild->GetDynamicToolbarMaxHeight(); - mDynamicToolbarHeight = mDynamicToolbarMaxHeight; + if (IsRootContentDocumentCrossProcess()) { + if (BrowserChild* browserChild = BrowserChild::GetFrom(GetDocShell())) { + mKeyboardHeight = browserChild->GetKeyboardHeight(); + + if (MOZ_LIKELY(!Preferences::HasUserValue( + "layout.dynamic-toolbar-max-height"))) { + mDynamicToolbarMaxHeight = browserChild->GetDynamicToolbarMaxHeight(); + mDynamicToolbarHeight = mDynamicToolbarMaxHeight; + } } } #endif @@ -3041,6 +3044,11 @@ void nsPresContext::UpdateDynamicToolbarOffset(ScreenIntCoord aOffset) { ServoStyleSet::OnlyDynamic::Yes); } +void nsPresContext::UpdateKeyboardHeight(ScreenIntCoord aHeight) { + MOZ_ASSERT(IsRootContentDocumentCrossProcess()); + mKeyboardHeight = aHeight; +} + DynamicToolbarState nsPresContext::GetDynamicToolbarState() const { if (!HasDynamicToolbar()) { return DynamicToolbarState::None; diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h index e02e901fdb63..b04092dab7bb 100644 --- a/layout/base/nsPresContext.h +++ b/layout/base/nsPresContext.h @@ -435,6 +435,8 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr { return mDynamicToolbarHeight; } + void UpdateKeyboardHeight(mozilla::ScreenIntCoord aHeight); + /** * Returns the maximum height of the dynamic toolbar if the toolbar state is * `DynamicToolbarState::Collapsed`, otherwise returns zero. @@ -1226,6 +1228,8 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr { // The maximum height of the dynamic toolbar on mobile. mozilla::ScreenIntCoord mDynamicToolbarMaxHeight; mozilla::ScreenIntCoord mDynamicToolbarHeight; + // The software keyboard height. + mozilla::ScreenIntCoord mKeyboardHeight; // Safe area insets support mozilla::ScreenIntMargin mSafeAreaInsets; nsSize mPageSize; 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 ef1a45a79459..3f431d63457f 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 @@ -411,6 +411,9 @@ public class GeckoSession { @WrapForJNI(calledFrom = "ui", dispatchTo = "gecko") public native void onSafeAreaInsetsChanged(int top, int right, int bottom, int left); + @WrapForJNI(calledFrom = "ui", dispatchTo = "gecko") + public native void onKeyboardHeightChanged(int height); + @WrapForJNI(calledFrom = "ui") public void setPointerIcon( final int defaultCursor, final Bitmap customCursor, final float x, final float y) { @@ -2639,6 +2642,10 @@ public class GeckoSession { } else { // Delete any pending memory pressure events since we're active again. ThreadUtils.removeUiThreadCallbacks(mNotifyMemoryPressure); + + if (mAttachedCompositor) { + mCompositor.onKeyboardHeightChanged(mKeyboardHeight); + } } ThreadUtils.runOnUiThread(() -> getAutofillSupport().onActiveChanged(active)); @@ -7905,6 +7912,10 @@ public class GeckoSession { } mKeyboardHeight = height; + + if (mAttachedCompositor) { + mCompositor.onKeyboardHeightChanged(mKeyboardHeight); + } } /* package */ void setPointerIcon( diff --git a/view/nsView.cpp b/view/nsView.cpp index c1c1e12f09ec..b1c108aface6 100644 --- a/view/nsView.cpp +++ b/view/nsView.cpp @@ -921,23 +921,8 @@ void nsView::DynamicToolbarMaxHeightChanged(ScreenIntCoord aHeight) { 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, [&aHeight](dom::BrowserParent* aBrowserParent) -> CallState { + CallOnAllRemoteChildren( + [aHeight](dom::BrowserParent* aBrowserParent) -> CallState { aBrowserParent->DynamicToolbarMaxHeightChanged(aHeight); return CallState::Continue; }); @@ -948,24 +933,8 @@ void nsView::DynamicToolbarOffsetChanged(ScreenIntCoord aOffset) { "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, [&aOffset](dom::BrowserParent* aBrowserParent) -> CallState { + CallOnAllRemoteChildren( + [aOffset](dom::BrowserParent* aBrowserParent) -> CallState { // Skip background tabs. if (!aBrowserParent->GetDocShellIsActive()) { return CallState::Continue; @@ -975,6 +944,23 @@ void nsView::DynamicToolbarOffsetChanged(ScreenIntCoord aOffset) { return CallState::Stop; }); } + +void nsView::KeyboardHeightChanged(ScreenIntCoord aHeight) { + 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"); + CallOnAllRemoteChildren( + [aHeight](dom::BrowserParent* aBrowserParent) -> CallState { + // Skip background tabs. + if (!aBrowserParent->GetDocShellIsActive()) { + return CallState::Continue; + } + + aBrowserParent->KeyboardHeightChanged(aHeight); + return CallState::Stop; + }); +} #endif bool nsView::RequestWindowClose(nsIWidget* aWidget) { @@ -1092,6 +1078,24 @@ void nsView::SafeAreaInsetsChanged(const ScreenIntMargin& aSafeAreaInsets) { // https://github.com/w3c/csswg-drafts/issues/4670 // Actually we don't set this value on sub document. This behaviour is // same as Blink. + CallOnAllRemoteChildren([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(); +} + +void nsView::CallOnAllRemoteChildren( + const std::function& aCallback) { + PresShell* presShell = mViewManager->GetPresShell(); + if (!presShell) { + return; + } dom::Document* document = presShell->GetDocument(); if (!document) { @@ -1103,16 +1107,5 @@ void nsView::SafeAreaInsetsChanged(const ScreenIntMargin& aSafeAreaInsets) { 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(); + nsContentUtils::CallOnAllRemoteChildren(window, aCallback); } diff --git a/view/nsView.h b/view/nsView.h index af87038b1705..158993614e6e 100644 --- a/view/nsView.h +++ b/view/nsView.h @@ -15,6 +15,7 @@ #include "nsIWidgetListener.h" #include "Units.h" #include "mozilla/Attributes.h" +#include "mozilla/CallState.h" #include "mozilla/EventForwards.h" #include "mozilla/UniquePtr.h" @@ -24,6 +25,9 @@ class nsIFrame; namespace mozilla { class PresShell; +namespace dom { +class BrowserParent; +} // namespace dom namespace widget { struct InitData; enum class TransparencyMode : uint8_t; @@ -429,6 +433,7 @@ class nsView final : public nsIWidgetListener { mozilla::ScreenIntCoord aHeight) override; virtual void DynamicToolbarOffsetChanged( mozilla::ScreenIntCoord aOffset) override; + virtual void KeyboardHeightChanged(mozilla::ScreenIntCoord aHeight) override; #endif virtual bool RequestWindowClose(nsIWidget* aWidget) override; MOZ_CAN_RUN_SCRIPT_BOUNDARY @@ -514,6 +519,10 @@ class nsView final : public nsIWidgetListener { // Update the cached RootViewManager for all view manager descendents. void InvalidateHierarchy(); + void CallOnAllRemoteChildren( + const std::function& + aCallback); + nsViewManager* mViewManager; nsView* mParent; nsCOMPtr mWindow; diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp index fceb57587f63..381549e4c567 100644 --- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -1315,6 +1315,21 @@ class LayerViewSupport final gkWindow->UpdateDynamicToolbarMaxHeight(ScreenIntCoord(aHeight)); } + void OnKeyboardHeightChanged(int32_t aHeight) { + MOZ_ASSERT(NS_IsMainThread()); + auto win(mWindow.Access()); + if (!win) { + return; // Already shut down. + } + + nsWindow* gkWindow = win->GetNsWindow(); + if (!gkWindow) { + return; + } + + gkWindow->KeyboardHeightChanged(ScreenIntCoord(aHeight)); + } + void SyncPauseCompositor() { MOZ_ASSERT(AndroidBridge::IsJavaUiThread()); @@ -3259,6 +3274,16 @@ void nsWindow::UpdateDynamicToolbarOffset(ScreenIntCoord aOffset) { } } +void nsWindow::KeyboardHeightChanged(ScreenIntCoord aHeight) { + if (mWidgetListener) { + mWidgetListener->KeyboardHeightChanged(aHeight); + } + + if (mAttachedWidgetListener) { + mAttachedWidgetListener->KeyboardHeightChanged(aHeight); + } +} + ScreenIntMargin nsWindow::GetSafeAreaInsets() const { return mSafeAreaInsets; } void nsWindow::UpdateSafeAreaInsets(const ScreenIntMargin& aSafeAreaInsets) { diff --git a/widget/android/nsWindow.h b/widget/android/nsWindow.h index 94e199001af7..bbf57c403005 100644 --- a/widget/android/nsWindow.h +++ b/widget/android/nsWindow.h @@ -245,6 +245,8 @@ class nsWindow final : public nsBaseWidget { mozilla::ScreenIntMargin GetSafeAreaInsets() const override; void UpdateSafeAreaInsets(const mozilla::ScreenIntMargin& aSafeAreaInsets); + void KeyboardHeightChanged(mozilla::ScreenIntCoord aHeight); + mozilla::jni::NativeWeakPtr GetNPZCSupportWeakPtr(); diff --git a/widget/nsIWidgetListener.cpp b/widget/nsIWidgetListener.cpp index a554a6363660..b0e2c438e5ee 100644 --- a/widget/nsIWidgetListener.cpp +++ b/widget/nsIWidgetListener.cpp @@ -40,6 +40,7 @@ void nsIWidgetListener::SafeAreaInsetsChanged(const mozilla::ScreenIntMargin&) { void nsIWidgetListener::DynamicToolbarMaxHeightChanged(ScreenIntCoord aHeight) { } void nsIWidgetListener::DynamicToolbarOffsetChanged(ScreenIntCoord aOffset) {} +void nsIWidgetListener::KeyboardHeightChanged(ScreenIntCoord aHeight) {} #endif void nsIWidgetListener::MacFullscreenMenubarOverlapChanged( diff --git a/widget/nsIWidgetListener.h b/widget/nsIWidgetListener.h index 55a6987b0b52..d0d2e334704a 100644 --- a/widget/nsIWidgetListener.h +++ b/widget/nsIWidgetListener.h @@ -84,6 +84,11 @@ class nsIWidgetListener { #if defined(MOZ_WIDGET_ANDROID) virtual void DynamicToolbarMaxHeightChanged(mozilla::ScreenIntCoord aHeight); virtual void DynamicToolbarOffsetChanged(mozilla::ScreenIntCoord aOffset); + + /** + * Called when the software keyboard appears/disappears. + */ + virtual void KeyboardHeightChanged(mozilla::ScreenIntCoord aHeight); #endif /**