Bug 1958322 - Plumb pip mode to Gecko. r=padenot,hiro,geckoview-reviewers,webidl,saschanaz,smaug,calu

Differential Revision: https://phabricator.services.mozilla.com/D244794
This commit is contained in:
Emilio Cobos Álvarez
2025-04-09 18:04:42 +00:00
parent ea16ef69b1
commit 79aa0d7606
14 changed files with 97 additions and 11 deletions

View File

@@ -19626,6 +19626,11 @@ bool Document::HasStorageAccessPermissionGrantedByAllowList() {
nsILoadInfo::StoragePermissionAllowListed;
}
bool Document::InAndroidPipMode() const {
auto* bc = BrowserChild::GetFrom(GetDocShell());
return bc && bc->InAndroidPipMode();
}
nsIPrincipal* Document::EffectiveStoragePrincipal() const {
if (!StaticPrefs::
privacy_partition_always_partition_third_party_non_cookie_storage()) {

View File

@@ -2192,6 +2192,10 @@ class Document : public nsINode,
* Returns true if this document was created from a nsXULPrototypeDocument.
*/
bool LoadedFromPrototype() const { return mPrototypeDocument; }
/* Returns true if we're currently in Android's PiP mode. */
bool InAndroidPipMode() const;
/**
* Returns the prototype the document was created from, or null if it was not
* created from a prototype.

View File

@@ -285,6 +285,7 @@ BrowserChild::BrowserChild(ContentChild* aManager, const TabId& aTabId,
mTriedBrowserInit(false),
mHasValidInnerSize(false),
mDestroyed(false),
mInAndroidPipMode(false),
mIsTopLevel(aIsTopLevel),
mIsTransparent(false),
mIPCOpen(false),
@@ -1257,6 +1258,21 @@ mozilla::ipc::IPCResult BrowserChild::RecvKeyboardHeightChanged(
return IPC_OK();
}
mozilla::ipc::IPCResult BrowserChild::RecvAndroidPipModeChanged(bool aPipMode) {
if (mInAndroidPipMode == aPipMode) {
return IPC_OK();
}
mInAndroidPipMode = aPipMode;
if (RefPtr<Document> document = GetTopLevelDocument()) {
nsContentUtils::DispatchEventOnlyToChrome(
document, document,
aPipMode ? u"MozAndroidPipModeEntered"_ns
: u"MozAndroidPipModeExited"_ns,
CanBubble::eYes, Cancelable::eNo, /* DefaultAction */ nullptr);
}
return IPC_OK();
}
mozilla::ipc::IPCResult BrowserChild::RecvSuppressDisplayport(
const bool& aEnabled) {
if (RefPtr<PresShell> presShell = GetTopLevelPresShell()) {

View File

@@ -85,12 +85,8 @@ class SessionStoreChild;
class RequestData;
class WebProgressData;
#define DOM_BROWSERCHILD_IID \
{ \
0x58a5775d, 0xba05, 0x45bf, { \
0xbd, 0xb8, 0xd7, 0x61, 0xf9, 0x01, 0x01, 0x31 \
} \
}
#define DOM_BROWSERCHILD_IID \
{0x58a5775d, 0xba05, 0x45bf, {0xbd, 0xb8, 0xd7, 0x61, 0xf9, 0x01, 0x01, 0x31}}
class BrowserChildMessageManager : public ContentFrameMessageManager,
public nsIMessageSender,
@@ -287,6 +283,8 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
mozilla::ipc::IPCResult RecvKeyboardHeightChanged(
const mozilla::ScreenIntCoord& aHeight);
mozilla::ipc::IPCResult RecvAndroidPipModeChanged(bool aPipMode);
mozilla::ipc::IPCResult RecvActivate(uint64_t aActionId);
mozilla::ipc::IPCResult RecvDeactivate(uint64_t aActionId);
@@ -563,6 +561,8 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
};
mozilla::ScreenIntCoord GetKeyboardHeight() const { return mKeyboardHeight; }
bool InAndroidPipMode() const { return mInAndroidPipMode; }
bool IPCOpen() const { return mIPCOpen; }
const mozilla::layers::CompositorOptions& GetCompositorOptions() const;
@@ -848,6 +848,8 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
bool mTriedBrowserInit : 1;
bool mHasValidInnerSize : 1;
bool mDestroyed : 1;
// Whether we're in Android's PiP mode.
bool mInAndroidPipMode : 1;
// Whether or not this browser is the child part of the top level PBrowser
// actor in a remote browser.

View File

@@ -1189,7 +1189,7 @@ void BrowserParent::SizeModeChanged(const nsSizeMode& aSizeMode) {
}
}
#if defined(MOZ_WIDGET_ANDROID)
#ifdef MOZ_WIDGET_ANDROID
void BrowserParent::DynamicToolbarMaxHeightChanged(ScreenIntCoord aHeight) {
if (!mIsDestroyed) {
Unused << SendDynamicToolbarMaxHeightChanged(aHeight);
@@ -1207,6 +1207,12 @@ void BrowserParent::KeyboardHeightChanged(ScreenIntCoord aHeight) {
Unused << SendKeyboardHeightChanged(aHeight);
}
}
void BrowserParent::AndroidPipModeChanged(bool aPipMode) {
if (!mIsDestroyed) {
Unused << SendAndroidPipModeChanged(aPipMode);
}
}
#endif
void BrowserParent::HandleAccessKey(const WidgetKeyboardEvent& aEvent,

View File

@@ -486,10 +486,11 @@ class BrowserParent final : public PBrowserParent,
void HandleAccessKey(const WidgetKeyboardEvent& aEvent,
nsTArray<uint32_t>& aCharCodes);
#if defined(MOZ_WIDGET_ANDROID)
#ifdef MOZ_WIDGET_ANDROID
void DynamicToolbarMaxHeightChanged(ScreenIntCoord aHeight);
void DynamicToolbarOffsetChanged(ScreenIntCoord aOffset);
void KeyboardHeightChanged(ScreenIntCoord aHeight);
void AndroidPipModeChanged(bool);
#endif
void Activate(uint64_t aActionId);

View File

@@ -703,6 +703,8 @@ child:
async KeyboardHeightChanged(ScreenIntCoord height);
async AndroidPipModeChanged(bool aPipMode);
/**
* StopIMEStateManagement() is called when the process loses focus and
* should stop managing IME state.

View File

@@ -385,6 +385,12 @@ partial interface Document {
[ChromeOnly]
readonly attribute boolean loadedFromPrototype;
// Whether we're in android's Picture-in-Picture mode.
// Top level document only (for now, if we want to deal with iframes, please
// also fix bug 1959448 while at it).
[ChromeOnly]
readonly attribute boolean inAndroidPipMode;
// The principal to use for the storage area of this document
[ChromeOnly]
readonly attribute Principal effectiveStoragePrincipal;

View File

@@ -410,6 +410,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 onPipModeChanged(boolean enabled);
@WrapForJNI(calledFrom = "ui", dispatchTo = "gecko")
public native void onKeyboardHeightChanged(int height);

View File

@@ -836,7 +836,7 @@ bool nsView::WindowResized(nsIWidget* aWidget, int32_t aWidth,
return false;
}
#if defined(MOZ_WIDGET_ANDROID)
#ifdef MOZ_WIDGET_ANDROID
void nsView::DynamicToolbarMaxHeightChanged(ScreenIntCoord aHeight) {
MOZ_ASSERT(XRE_IsParentProcess(),
"Should be only called for the browser parent process");
@@ -883,6 +883,18 @@ void nsView::KeyboardHeightChanged(ScreenIntCoord aHeight) {
return CallState::Stop;
});
}
void nsView::AndroidPipModeChanged(bool aPipMode) {
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(
[aPipMode](dom::BrowserParent* aBrowserParent) -> CallState {
aBrowserParent->AndroidPipModeChanged(aPipMode);
return CallState::Continue;
});
}
#endif
bool nsView::RequestWindowClose(nsIWidget* aWidget) {

View File

@@ -390,10 +390,11 @@ class nsView final : public nsIWidgetListener {
ByMoveToRect) override;
bool WindowResized(nsIWidget* aWidget, int32_t aWidth,
int32_t aHeight) override;
#if defined(MOZ_WIDGET_ANDROID)
#ifdef MOZ_WIDGET_ANDROID
void DynamicToolbarMaxHeightChanged(mozilla::ScreenIntCoord aHeight) override;
void DynamicToolbarOffsetChanged(mozilla::ScreenIntCoord aOffset) override;
void KeyboardHeightChanged(mozilla::ScreenIntCoord aHeight) override;
void AndroidPipModeChanged(bool) override;
#endif
bool RequestWindowClose(nsIWidget* aWidget) override;
MOZ_CAN_RUN_SCRIPT_BOUNDARY

View File

@@ -1382,6 +1382,21 @@ class LayerViewSupport final
gkWindow->UpdateDynamicToolbarMaxHeight(ScreenIntCoord(aHeight));
}
void OnPipModeChanged(bool aPipMode) {
MOZ_ASSERT(NS_IsMainThread());
auto win(mWindow.Access());
if (!win) {
return; // Already shut down.
}
nsWindow* gkWindow = win->GetNsWindow();
if (!gkWindow) {
return;
}
gkWindow->PipModeChanged(aPipMode);
}
void OnKeyboardHeightChanged(int32_t aHeight) {
MOZ_ASSERT(NS_IsMainThread());
auto win(mWindow.Access());
@@ -3302,6 +3317,16 @@ void nsWindow::UpdateDynamicToolbarOffset(ScreenIntCoord aOffset) {
}
}
void nsWindow::PipModeChanged(bool aPipMode) {
if (mWidgetListener) {
mWidgetListener->AndroidPipModeChanged(aPipMode);
}
if (mAttachedWidgetListener) {
mAttachedWidgetListener->AndroidPipModeChanged(aPipMode);
}
}
void nsWindow::KeyboardHeightChanged(ScreenIntCoord aHeight) {
if (mWidgetListener) {
mWidgetListener->KeyboardHeightChanged(aHeight);

View File

@@ -257,6 +257,8 @@ class nsWindow final : public nsBaseWidget {
void KeyboardHeightChanged(mozilla::ScreenIntCoord aHeight);
void PipModeChanged(bool aPipMode);
mozilla::jni::NativeWeakPtr<mozilla::widget::NPZCSupport>
GetNPZCSupportWeakPtr();

View File

@@ -81,12 +81,13 @@ class nsIWidgetListener {
*/
virtual void SizeModeChanged(nsSizeMode aSizeMode) {}
#if defined(MOZ_WIDGET_ANDROID)
#ifdef 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) {}
virtual void AndroidPipModeChanged(bool) {}
#endif
/** Called when the macOS titlebar is shown while in fullscreen. */