forked from mirrors/gecko-dev
Bug 1574307 - Part 4. Notify GV of viewport-fit. r=geckoview-reviewers,snorp
`viewport-fit` is hint that browser application can use cutout area. So we should expose it to GeckoView application to set `layoutInDisplayCutoutMode`. When meta element is found or changed, `ContentDelegate.onMetaviewportFitChange` is called. Even if nothing, it will be called after DOMContentLoaded is fired. Depends on D57398 Differential Revision: https://phabricator.services.mozilla.com/D55610 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
7b3ef75994
commit
452a87b7b0
6 changed files with 83 additions and 2 deletions
|
|
@ -39,6 +39,8 @@ class GeckoViewContentChild extends GeckoViewChildModule {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.timeoutsSuspended = false;
|
this.timeoutsSuspended = false;
|
||||||
|
this.lastViewportFit = "";
|
||||||
|
this.triggerViewportFitChange = null;
|
||||||
|
|
||||||
this.messageManager.addMessageListener(
|
this.messageManager.addMessageListener(
|
||||||
"GeckoView:DOMFullscreenEntered",
|
"GeckoView:DOMFullscreenEntered",
|
||||||
|
|
@ -80,6 +82,7 @@ class GeckoViewContentChild extends GeckoViewChildModule {
|
||||||
addEventListener("contextmenu", this, { capture: true });
|
addEventListener("contextmenu", this, { capture: true });
|
||||||
addEventListener("DOMContentLoaded", this, false);
|
addEventListener("DOMContentLoaded", this, false);
|
||||||
addEventListener("MozFirstContentfulPaint", this, false);
|
addEventListener("MozFirstContentfulPaint", this, false);
|
||||||
|
addEventListener("DOMMetaViewportFitChanged", this, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
onDisable() {
|
onDisable() {
|
||||||
|
|
@ -94,6 +97,7 @@ class GeckoViewContentChild extends GeckoViewChildModule {
|
||||||
removeEventListener("contextmenu", this, { capture: true });
|
removeEventListener("contextmenu", this, { capture: true });
|
||||||
removeEventListener("DOMContentLoaded", this);
|
removeEventListener("DOMContentLoaded", this);
|
||||||
removeEventListener("MozFirstContentfulPaint", this);
|
removeEventListener("MozFirstContentfulPaint", this);
|
||||||
|
removeEventListener("DOMMetaViewportFitChanged", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
toPixels(aLength, aType) {
|
toPixels(aLength, aType) {
|
||||||
|
|
@ -124,6 +128,24 @@ class GeckoViewContentChild extends GeckoViewChildModule {
|
||||||
return content.windowUtils.SCROLL_MODE_SMOOTH;
|
return content.windowUtils.SCROLL_MODE_SMOOTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notifyParentOfViewportFit() {
|
||||||
|
if (this.triggerViewportFitChange) {
|
||||||
|
content.cancelIdleCallback(this.triggerViewportFitChange);
|
||||||
|
}
|
||||||
|
this.triggerViewportFitChange = content.requestIdleCallback(() => {
|
||||||
|
this.triggerViewportFitChange = null;
|
||||||
|
let viewportFit = content.windowUtils.getViewportFitInfo();
|
||||||
|
if (this.lastViewportFit === viewportFit) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.lastViewportFit = viewportFit;
|
||||||
|
this.eventDispatcher.sendRequest({
|
||||||
|
type: "GeckoView:DOMMetaViewportFit",
|
||||||
|
viewportfit: viewportFit,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
receiveMessage(aMsg) {
|
receiveMessage(aMsg) {
|
||||||
debug`receiveMessage: ${aMsg.name}`;
|
debug`receiveMessage: ${aMsg.name}`;
|
||||||
|
|
||||||
|
|
@ -271,6 +293,11 @@ class GeckoViewContentChild extends GeckoViewChildModule {
|
||||||
content.windowUtils.resumeTimeouts();
|
content.windowUtils.resumeTimeouts();
|
||||||
this.timeoutsSuspended = false;
|
this.timeoutsSuspended = false;
|
||||||
}
|
}
|
||||||
|
if (aMsg.data.active) {
|
||||||
|
// Send current viewport-fit to parent.
|
||||||
|
this.lastViewportFit = "";
|
||||||
|
this.notifyParentOfViewportFit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (content && aMsg.data.suspendMedia) {
|
if (content && aMsg.data.suspendMedia) {
|
||||||
content.windowUtils.mediaSuspend = aMsg.data.active
|
content.windowUtils.mediaSuspend = aMsg.data.active
|
||||||
|
|
@ -380,6 +407,11 @@ class GeckoViewContentChild extends GeckoViewChildModule {
|
||||||
case "MozDOMFullscreen:Exit":
|
case "MozDOMFullscreen:Exit":
|
||||||
sendAsyncMessage("GeckoView:DOMFullscreenExit");
|
sendAsyncMessage("GeckoView:DOMFullscreenExit");
|
||||||
break;
|
break;
|
||||||
|
case "DOMMetaViewportFitChanged":
|
||||||
|
if (aEvent.originalTarget.ownerGlobal == content) {
|
||||||
|
this.notifyParentOfViewportFit();
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "DOMTitleChanged":
|
case "DOMTitleChanged":
|
||||||
this.eventDispatcher.sendRequest({
|
this.eventDispatcher.sendRequest({
|
||||||
type: "GeckoView:DOMTitleChanged",
|
type: "GeckoView:DOMTitleChanged",
|
||||||
|
|
@ -408,6 +440,11 @@ class GeckoViewContentChild extends GeckoViewChildModule {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "DOMContentLoaded": {
|
case "DOMContentLoaded": {
|
||||||
|
if (aEvent.originalTarget.ownerGlobal == content) {
|
||||||
|
// If loaded content doesn't have viewport-fit, parent still
|
||||||
|
// uses old value of previous content.
|
||||||
|
this.notifyParentOfViewportFit();
|
||||||
|
}
|
||||||
content.requestIdleCallback(async () => {
|
content.requestIdleCallback(async () => {
|
||||||
const manifest = await ManifestObtainer.contentObtainManifest(
|
const manifest = await ManifestObtainer.contentObtainManifest(
|
||||||
content
|
content
|
||||||
|
|
|
||||||
|
|
@ -687,6 +687,7 @@ package org.mozilla.geckoview {
|
||||||
method @UiThread default public void onFocusRequest(@NonNull GeckoSession);
|
method @UiThread default public void onFocusRequest(@NonNull GeckoSession);
|
||||||
method @UiThread default public void onFullScreen(@NonNull GeckoSession, boolean);
|
method @UiThread default public void onFullScreen(@NonNull GeckoSession, boolean);
|
||||||
method @UiThread default public void onKill(@NonNull GeckoSession);
|
method @UiThread default public void onKill(@NonNull GeckoSession);
|
||||||
|
method @UiThread default public void onMetaViewportFitChange(@NonNull GeckoSession, @NonNull String);
|
||||||
method @UiThread @Nullable default public GeckoResult<SlowScriptResponse> onSlowScript(@NonNull GeckoSession, @NonNull String);
|
method @UiThread @Nullable default public GeckoResult<SlowScriptResponse> onSlowScript(@NonNull GeckoSession, @NonNull String);
|
||||||
method @UiThread default public void onTitleChange(@NonNull GeckoSession, @Nullable String);
|
method @UiThread default public void onTitleChange(@NonNull GeckoSession, @Nullable String);
|
||||||
method @UiThread default public void onWebAppManifest(@NonNull GeckoSession, @NonNull JSONObject);
|
method @UiThread default public void onWebAppManifest(@NonNull GeckoSession, @NonNull JSONObject);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
#wide {
|
#wide {
|
||||||
background-color: rgb(200, 0, 0);
|
background-color: rgb(200, 0, 0);
|
||||||
|
|
|
||||||
|
|
@ -327,6 +327,33 @@ class ContentDelegateTest : BaseSessionTest() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test fun viewportFit() {
|
||||||
|
mainSession.loadTestPath(VIEWPORT_PATH)
|
||||||
|
mainSession.waitUntilCalled(object : Callbacks.All {
|
||||||
|
@AssertCalled(count = 1)
|
||||||
|
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
||||||
|
assertThat("Page load should succeed", success, equalTo(true))
|
||||||
|
}
|
||||||
|
|
||||||
|
@AssertCalled(count = 1)
|
||||||
|
override fun onMetaViewportFitChange(session: GeckoSession, viewportFit: String) {
|
||||||
|
assertThat("viewport-fit should match", viewportFit, equalTo("cover"))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
mainSession.loadTestPath(HELLO_HTML_PATH)
|
||||||
|
mainSession.waitUntilCalled(object : Callbacks.All {
|
||||||
|
@AssertCalled(count = 1)
|
||||||
|
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
||||||
|
assertThat("Page load should succeed", success, equalTo(true))
|
||||||
|
}
|
||||||
|
|
||||||
|
@AssertCalled(count = 1)
|
||||||
|
override fun onMetaViewportFitChange(session: GeckoSession, viewportFit: String) {
|
||||||
|
assertThat("viewport-fit should match", viewportFit, equalTo("auto"))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preferences to induce wanted behaviour.
|
* Preferences to induce wanted behaviour.
|
||||||
|
|
|
||||||
|
|
@ -423,6 +423,7 @@ public class GeckoSession implements Parcelable {
|
||||||
"GeckoView:ContentCrash",
|
"GeckoView:ContentCrash",
|
||||||
"GeckoView:ContentKill",
|
"GeckoView:ContentKill",
|
||||||
"GeckoView:ContextMenu",
|
"GeckoView:ContextMenu",
|
||||||
|
"GeckoView:DOMMetaViewportFit",
|
||||||
"GeckoView:DOMTitleChanged",
|
"GeckoView:DOMTitleChanged",
|
||||||
"GeckoView:DOMWindowClose",
|
"GeckoView:DOMWindowClose",
|
||||||
"GeckoView:ExternalResponse",
|
"GeckoView:ExternalResponse",
|
||||||
|
|
@ -459,6 +460,9 @@ public class GeckoSession implements Parcelable {
|
||||||
message.getInt("screenY"),
|
message.getInt("screenY"),
|
||||||
elem);
|
elem);
|
||||||
|
|
||||||
|
} else if ("GeckoView:DOMMetaViewportFit".equals(event)) {
|
||||||
|
delegate.onMetaViewportFitChange(GeckoSession.this,
|
||||||
|
message.getString("viewportfit"));
|
||||||
} else if ("GeckoView:DOMTitleChanged".equals(event)) {
|
} else if ("GeckoView:DOMTitleChanged".equals(event)) {
|
||||||
delegate.onTitleChange(GeckoSession.this,
|
delegate.onTitleChange(GeckoSession.this,
|
||||||
message.getString("title"));
|
message.getString("title"));
|
||||||
|
|
@ -3014,6 +3018,16 @@ public class GeckoSession implements Parcelable {
|
||||||
@UiThread
|
@UiThread
|
||||||
default void onFullScreen(@NonNull GeckoSession session, boolean fullScreen) {}
|
default void onFullScreen(@NonNull GeckoSession session, boolean fullScreen) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A viewport-fit was discovered in the content or updated after the content.
|
||||||
|
*
|
||||||
|
* @param session The GeckoSession that initiated the callback.
|
||||||
|
* @param viewportFit The value of viewport-fit of meta element in content.
|
||||||
|
* @see <a href="https://drafts.csswg.org/css-round-display/#viewport-fit-descriptor">4.1. The viewport-fit descriptor</a>
|
||||||
|
*/
|
||||||
|
@UiThread
|
||||||
|
default void onMetaViewportFitChange(@NonNull GeckoSession session, @NonNull String viewportFit) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Element details for onContextMenu callbacks.
|
* Element details for onContextMenu callbacks.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ exclude: true
|
||||||
exceptions and to add better support for removing exceptions. This deprecates [`ExceptionList`][74.8]
|
exceptions and to add better support for removing exceptions. This deprecates [`ExceptionList`][74.8]
|
||||||
and [`restoreExceptionList`][74.9] with the intent to remove them in 76.
|
and [`restoreExceptionList`][74.9] with the intent to remove them in 76.
|
||||||
([bug 1587552]({{bugzilla}}1587552))
|
([bug 1587552]({{bugzilla}}1587552))
|
||||||
|
- Added [`GeckoSession.ContentDelegate.onMetaViewportFitChange`][74.10]. This exposes `viewport-fit` value that is CSS Round Display Level 1. ([bug 1574307]({{bugzilla}}1574307))
|
||||||
|
|
||||||
[74.1]: {{javadoc_uri}}/WebExtensionController.html#enable-org.mozilla.geckoview.WebExtension-int-
|
[74.1]: {{javadoc_uri}}/WebExtensionController.html#enable-org.mozilla.geckoview.WebExtension-int-
|
||||||
[74.2]: {{javadoc_uri}}/WebExtensionController.html#disable-org.mozilla.geckoview.WebExtension-int-
|
[74.2]: {{javadoc_uri}}/WebExtensionController.html#disable-org.mozilla.geckoview.WebExtension-int-
|
||||||
|
|
@ -43,6 +44,7 @@ exclude: true
|
||||||
[74.7]: {{javadoc_uri}}/ContentBlockingController.html
|
[74.7]: {{javadoc_uri}}/ContentBlockingController.html
|
||||||
[74.8]: {{javadoc_uri}}/ContentBlockingController.ExceptionList.html
|
[74.8]: {{javadoc_uri}}/ContentBlockingController.ExceptionList.html
|
||||||
[74.9]: {{javadoc_uri}}/ContentBlockingController.html#restoreExceptionList-org.mozilla.geckoview.ContentBlockingController.ExceptionList-
|
[74.9]: {{javadoc_uri}}/ContentBlockingController.html#restoreExceptionList-org.mozilla.geckoview.ContentBlockingController.ExceptionList-
|
||||||
|
[74.10]: {{javadoc_uri}}/GeckoSession.ContentDelegate.html#onMetaViewportFitChange-org.mozilla.geckoview.GeckoSession-java.lang.String-
|
||||||
|
|
||||||
## v73
|
## v73
|
||||||
- Added [`WebExtensionController.install`][73.1] and [`uninstall`][73.2] to
|
- Added [`WebExtensionController.install`][73.1] and [`uninstall`][73.2] to
|
||||||
|
|
@ -553,4 +555,4 @@ exclude: true
|
||||||
[65.24]: {{javadoc_uri}}/CrashReporter.html#sendCrashReport-android.content.Context-android.os.Bundle-java.lang.String-
|
[65.24]: {{javadoc_uri}}/CrashReporter.html#sendCrashReport-android.content.Context-android.os.Bundle-java.lang.String-
|
||||||
[65.25]: {{javadoc_uri}}/GeckoResult.html
|
[65.25]: {{javadoc_uri}}/GeckoResult.html
|
||||||
|
|
||||||
[api-version]: e89f3bb79d0c5cc936812de4c2d8f4d30923afb9
|
[api-version]: 5342560e4c467a1f3d363748ebb20a077d2e8385
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue