From efd8c4f4fb92ef255625fdd3b29f36e446d483ab Mon Sep 17 00:00:00 2001 From: Tanushree Podder Date: Mon, 20 Aug 2018 16:28:42 -0400 Subject: [PATCH] Bug 1357785 - Expose the Visual Viewport API to web content. r=botond, r=nika --HG-- extra : amend_source : 8e5fe3e3195dd82aef19a4c79df31e2048024c99 --- dom/base/VisualViewport.cpp | 140 ++++++++++++++++++ dom/base/VisualViewport.h | 48 ++++++ dom/base/moz.build | 2 + dom/base/nsGlobalWindowInner.cpp | 10 ++ dom/base/nsGlobalWindowInner.h | 4 + dom/bindings/Bindings.conf | 4 + .../mochitest/general/test_interfaces.js | 2 + dom/webidl/VisualViewport.webidl | 21 +++ dom/webidl/Window.webidl | 7 + dom/webidl/moz.build | 1 + gfx/thebes/gfxPrefs.h | 1 + modules/libpref/init/all.js | 3 + 12 files changed, 243 insertions(+) create mode 100644 dom/base/VisualViewport.cpp create mode 100644 dom/base/VisualViewport.h create mode 100644 dom/webidl/VisualViewport.webidl diff --git a/dom/base/VisualViewport.cpp b/dom/base/VisualViewport.cpp new file mode 100644 index 000000000000..1dbbba54a635 --- /dev/null +++ b/dom/base/VisualViewport.cpp @@ -0,0 +1,140 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "VisualViewport.h" +#include "nsIScrollableFrame.h" +#include "nsIDocShell.h" + +using namespace mozilla; +using namespace mozilla::dom; + +VisualViewport::VisualViewport(nsPIDOMWindowInner* aWindow) + : DOMEventTargetHelper(aWindow) +{ +} + +VisualViewport::~VisualViewport() +{ +} + +/* virtual */ +JSObject* +VisualViewport::WrapObject(JSContext* aCx, JS::Handle aGivenProto) +{ + return VisualViewport_Binding::Wrap(aCx, this, aGivenProto); +} + +CSSSize +VisualViewport::VisualViewportSize() const +{ + CSSSize size = CSSSize(0,0); + + nsIPresShell* presShell = GetPresShell(); + if (presShell) { + if (presShell->IsVisualViewportSizeSet()) { + size = CSSRect::FromAppUnits( + presShell->GetVisualViewportSize()); + } else { + nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable(); + if (sf) { + size = CSSRect::FromAppUnits(sf->GetScrollPortRect().Size()); + } + } + } + return size; +} + +double +VisualViewport::Width() const +{ + CSSSize size = VisualViewportSize(); + return size.width; +} + +double +VisualViewport::Height() const +{ + CSSSize size = VisualViewportSize(); + return size.height; +} + +double +VisualViewport::Scale() const +{ + double scale = 1; + nsIPresShell* presShell = GetPresShell(); + if (presShell) { + scale = presShell->GetResolution(); + } + return scale; +} + +CSSPoint +VisualViewport::VisualViewportOffset() const +{ + CSSPoint offset = CSSPoint(0,0); + + nsIPresShell* presShell = GetPresShell(); + if (presShell) { + offset = CSSPoint::FromAppUnits(presShell->GetVisualViewportOffset()); + } + return offset; +} + +CSSPoint +VisualViewport::LayoutViewportOffset() const +{ + CSSPoint offset = CSSPoint(0,0); + + nsIPresShell* presShell = GetPresShell(); + if (presShell) { + nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable(); + if (sf) { + offset = CSSPoint::FromAppUnits(sf->GetScrollPosition()); + } + } + return offset; +} + +double +VisualViewport::PageLeft() const +{ + return VisualViewportOffset().X(); +} + +double +VisualViewport::PageTop() const +{ + return VisualViewportOffset().Y(); +} + +double +VisualViewport::OffsetLeft() const +{ + return PageLeft() - LayoutViewportOffset().X(); +} + +double +VisualViewport::OffsetTop() const +{ + return PageTop() - LayoutViewportOffset().Y(); +} + +nsIPresShell* +VisualViewport::GetPresShell() const +{ + nsCOMPtr window = GetOwner(); + if (!window) { + return nullptr; + } + + nsIDocShell* docShell = window->GetDocShell(); + if (!docShell) { + return nullptr; + } + + return docShell->GetPresShell(); +} diff --git a/dom/base/VisualViewport.h b/dom/base/VisualViewport.h new file mode 100644 index 000000000000..0a577a93e62a --- /dev/null +++ b/dom/base/VisualViewport.h @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +#ifndef mozilla_dom_VisualViewport_h +#define mozilla_dom_VisualViewport_h + +#include "mozilla/DOMEventTargetHelper.h" +#include "mozilla/dom/VisualViewportBinding.h" +#include "Units.h" +#include "nsIPresShell.h" + +namespace mozilla { +namespace dom { + +/* Visual Viewport API spec: https://wicg.github.io/visual-viewport/#the-visualviewport-interface */ +class VisualViewport final: public mozilla::DOMEventTargetHelper +{ + +public: + explicit VisualViewport(nsPIDOMWindowInner* aWindow); + + double OffsetLeft() const; + double OffsetTop() const; + double PageLeft() const; + double PageTop() const; + double Width() const; + double Height() const; + double Scale() const; + + virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; + +private: + virtual ~VisualViewport(); + + CSSSize VisualViewportSize() const; + CSSPoint VisualViewportOffset() const; + CSSPoint LayoutViewportOffset() const; + nsIPresShell* GetPresShell() const; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_VisualViewport_h diff --git a/dom/base/moz.build b/dom/base/moz.build index 1c6e23cd5b88..776b07831cb2 100644 --- a/dom/base/moz.build +++ b/dom/base/moz.build @@ -227,6 +227,7 @@ EXPORTS.mozilla.dom += [ 'TimeoutManager.h', 'TreeIterator.h', 'TreeWalker.h', + 'VisualViewport.h', 'WebKitCSSMatrix.h', 'WindowOrientationObserver.h', ] @@ -383,6 +384,7 @@ UNIFIED_SOURCES += [ 'TimeoutHandler.cpp', 'TimeoutManager.cpp', 'TreeWalker.cpp', + 'VisualViewport.cpp', 'WebKitCSSMatrix.cpp', 'WindowDestroyedEvent.cpp', 'WindowNamedPropertiesHandler.cpp', diff --git a/dom/base/nsGlobalWindowInner.cpp b/dom/base/nsGlobalWindowInner.cpp index e060835f24e3..5bc2020b423a 100644 --- a/dom/base/nsGlobalWindowInner.cpp +++ b/dom/base/nsGlobalWindowInner.cpp @@ -33,6 +33,7 @@ #include "mozilla/dom/Timeout.h" #include "mozilla/dom/TimeoutHandler.h" #include "mozilla/dom/TimeoutManager.h" +#include "mozilla/dom/VisualViewport.h" #include "mozilla/IntegerPrintfMacros.h" #if defined(MOZ_WIDGET_ANDROID) #include "mozilla/dom/WindowOrientationObserver.h" @@ -2217,6 +2218,15 @@ nsPIDOMWindowInner::Navigator() return mNavigator; } +VisualViewport* nsGlobalWindowInner::VisualViewport() +{ + if (!mVisualViewport) { + mVisualViewport = new mozilla::dom::VisualViewport(this); + } + + return mVisualViewport; +} + nsScreen* nsGlobalWindowInner::GetScreen(ErrorResult& aError) { diff --git a/dom/base/nsGlobalWindowInner.h b/dom/base/nsGlobalWindowInner.h index 935a84e60cca..5e599de2093e 100644 --- a/dom/base/nsGlobalWindowInner.h +++ b/dom/base/nsGlobalWindowInner.h @@ -126,6 +126,7 @@ class SpeechSynthesis; class TabGroup; class Timeout; class U2F; +class VisualViewport; class VRDisplay; enum class VRDisplayEventReason : uint8_t; class VREventObserver; @@ -764,6 +765,7 @@ public: already_AddRefed GetComputedStyle(mozilla::dom::Element& aElt, const nsAString& aPseudoElt, mozilla::ErrorResult& aError) override; + mozilla::dom::VisualViewport* VisualViewport(); already_AddRefed MatchMedia( const nsAString& aQuery, mozilla::dom::CallerType aCallerType, @@ -1393,6 +1395,8 @@ protected: RefPtr mHistory; RefPtr mCustomElements; + RefPtr mVisualViewport; + nsCOMPtr mDocumentPrincipal; // mTabChild is only ever populated in the content process. nsCOMPtr mTabChild; diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index d63090671716..b21abfdbdc7e 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -1064,6 +1064,10 @@ DOMInterfaces = { 'wrapperCache': False, }, +'VisualViewport': { + 'nativeType': 'mozilla::dom::VisualViewport', +}, + 'VTTCue': { 'nativeType': 'mozilla::dom::TextTrackCue' }, diff --git a/dom/tests/mochitest/general/test_interfaces.js b/dom/tests/mochitest/general/test_interfaces.js index a9450f237588..d1c5b7a21f3a 100644 --- a/dom/tests/mochitest/general/test_interfaces.js +++ b/dom/tests/mochitest/general/test_interfaces.js @@ -1161,6 +1161,8 @@ var interfaceNamesInGlobalScope = {name: "VideoPlaybackQuality", insecureContext: true}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "VideoStreamTrack", insecureContext: true}, +// IMPORTANT: Do not change this list without review from a DOM peer! + {name: "VisualViewport", insecureContext: true}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "VRDisplay", insecureContext: true, releaseNonWindows: false}, // IMPORTANT: Do not change this list without review from a DOM peer! diff --git a/dom/webidl/VisualViewport.webidl b/dom/webidl/VisualViewport.webidl new file mode 100644 index 000000000000..25c25cd1897c --- /dev/null +++ b/dom/webidl/VisualViewport.webidl @@ -0,0 +1,21 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * The origin of this IDL file is: + * https://wicg.github.io/visual-viewport/#the-visualviewport-interface + */ + +interface VisualViewport : EventTarget { + readonly attribute double offsetLeft; + readonly attribute double offsetTop; + + readonly attribute double pageLeft; + readonly attribute double pageTop; + + readonly attribute double width; + readonly attribute double height; + + readonly attribute double scale; +}; diff --git a/dom/webidl/Window.webidl b/dom/webidl/Window.webidl index b30314ba9894..6ca2c8e2ab28 100644 --- a/dom/webidl/Window.webidl +++ b/dom/webidl/Window.webidl @@ -16,6 +16,7 @@ * https://w3c.github.io/webappsec-secure-contexts/#monkey-patching-global-object * https://w3c.github.io/requestidlecallback/ * https://drafts.css-houdini.org/css-paint-api-1/#dom-window-paintworklet + * https://wicg.github.io/visual-viewport/#the-visualviewport-interface */ interface IID; @@ -565,3 +566,9 @@ partial interface Window { }; Window implements WebGPUProvider; + +partial interface Window { + [SameObject, Pref="dom.visualviewport.enabled", Replaceable] + readonly attribute VisualViewport visualViewport; + +}; diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index 1ebbc5c4dcb5..17b947136dbd 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -918,6 +918,7 @@ WEBIDL_FILES = [ 'VideoStreamTrack.webidl', 'VideoTrack.webidl', 'VideoTrackList.webidl', + 'VisualViewport.webidl', 'VRDisplay.webidl', 'VRDisplayEvent.webidl', 'VRServiceTest.webidl', diff --git a/gfx/thebes/gfxPrefs.h b/gfx/thebes/gfxPrefs.h index 002214d58ce6..418860eb25fe 100644 --- a/gfx/thebes/gfxPrefs.h +++ b/gfx/thebes/gfxPrefs.h @@ -372,6 +372,7 @@ private: DECL_GFX_PREF(Live, "dom.ipc.plugins.asyncdrawing.enabled", PluginAsyncDrawingEnabled, bool, false); DECL_GFX_PREF(Live, "dom.meta-viewport.enabled", MetaViewportEnabled, bool, false); + DECL_GFX_PREF(Live, "dom.visualviewport.enabled", VisualViewportEnabled, bool, false); DECL_GFX_PREF(Once, "dom.vr.enabled", VREnabled, bool, false); DECL_GFX_PREF(Live, "dom.vr.autoactivate.enabled", VRAutoActivateEnabled, bool, false); DECL_GFX_PREF(Live, "dom.vr.controller_trigger_threshold", VRControllerTriggerThreshold, float, 0.1f); diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 65e7c600c601..1bb5deed4df1 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -5639,6 +5639,9 @@ pref("intl.allow-insecure-text-input", false); // Enable meta-viewport support in remote APZ-enabled frames. pref("dom.meta-viewport.enabled", false); +// Disable Visual Viewport API +pref("dom.visualviewport.enabled", false); + // Search service settings pref("browser.search.log", false); pref("browser.search.update", true);