Bug 1831649 - Propagate the software keyboard height change into nsPresContext. r=botond,geckoview-reviewers,m_kato

Differential Revision: https://phabricator.services.mozilla.com/D204166
This commit is contained in:
Hiroyuki Ikezoe 2024-08-06 07:46:21 +00:00
parent aecb670460
commit b94489a2ea
14 changed files with 146 additions and 55 deletions

View File

@ -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> 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> presShell = GetTopLevelPresShell()) {

View File

@ -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;

View File

@ -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,

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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(

View File

@ -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<CallState(dom::BrowserParent*)>& 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);
}

View File

@ -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<mozilla::CallState(mozilla::dom::BrowserParent*)>&
aCallback);
nsViewManager* mViewManager;
nsView* mParent;
nsCOMPtr<nsIWidget> mWindow;

View File

@ -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) {

View File

@ -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<mozilla::widget::NPZCSupport>
GetNPZCSupportWeakPtr();

View File

@ -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(

View File

@ -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
/**