From f4b3e0c923b40fbc01320f307b5f015fc8f89b62 Mon Sep 17 00:00:00 2001 From: Botond Ballo Date: Mon, 12 Aug 2013 16:31:49 -0400 Subject: [PATCH] Bug 898580 - Metro mechanism for content to inform APZC about scroll events. Handles multi-APZC. r=bbondy, r=kats --- browser/metro/base/content/apzc.js | 15 ++++++- .../metro/base/content/bindings/browser.js | 40 ++++++++++++----- .../metro/base/content/bindings/browser.xml | 4 +- widget/windows/winrt/MetroWidget.cpp | 43 +++++++++++++++++++ widget/windows/winrt/MetroWidget.h | 10 +++-- 5 files changed, 96 insertions(+), 16 deletions(-) diff --git a/browser/metro/base/content/apzc.js b/browser/metro/base/content/apzc.js index 9729ca299b98..0509c2950ce3 100644 --- a/browser/metro/base/content/apzc.js +++ b/browser/metro/base/content/apzc.js @@ -46,11 +46,13 @@ var APZCObserver = { case 'TabOpen': { let browser = aEvent.originalTarget.linkedBrowser; browser.addEventListener("pageshow", this, true); + browser.messageManager.addMessageListener("scroll", this); break; } case 'TabClose': { let browser = aEvent.originalTarget.linkedBrowser; - browser.removeEventListener("pageshow", this); + browser.removeEventListener("pageshow", this, true); + browser.messageManager.removeMessageListener("scroll", this); break; } } @@ -113,5 +115,16 @@ var APZCObserver = { } else if (aTopic == "apzc-handle-pan-end") { Util.dumpLn("APZC pan-end"); } + }, + + receiveMessage: function(aMessage) { + let json = aMessage.json; + switch (aMessage.name) { + case "scroll": { + let data = json.viewId + " " + json.presShellId + " (" + json.scrollOffset.x + ", " + json.scrollOffset.y + ")"; + Services.obs.notifyObservers(null, "scroll-offset-changed", data); + break; + } + } } }; diff --git a/browser/metro/base/content/bindings/browser.js b/browser/metro/base/content/bindings/browser.js index 8dbff2d248f8..39045349c2f7 100644 --- a/browser/metro/base/content/bindings/browser.js +++ b/browser/metro/base/content/bindings/browser.js @@ -652,11 +652,7 @@ let ContentScroll = { break; case "scroll": { - let doc = aEvent.target; - if (doc != content.document) - break; - - this.sendScroll(); + this.sendScroll(aEvent.target); break; } @@ -683,13 +679,35 @@ let ContentScroll = { } }, - sendScroll: function sendScroll() { - let scrollOffset = this.getScrollOffset(content); - if (this._scrollOffset.x == scrollOffset.x && this._scrollOffset.y == scrollOffset.y) - return; + sendScroll: function sendScroll(target) { + let isRoot = false; + if (target instanceof Ci.nsIDOMDocument) { + var window = target.defaultView; + var scrollOffset = this.getScrollOffset(window); + var element = target.documentElement; - this._scrollOffset = scrollOffset; - sendAsyncMessage("scroll", scrollOffset); + if (target == content.document) { + if (this._scrollOffset.x == scrollOffset.x && this._scrollOffset.y == scrollOffset.y) { + return; + } + this._scrollOffset = scrollOffset; + isRoot = true; + } + } else { + var window = target.currentDoc.defaultView; + var scrollOffset = this.getScrollOffsetForElement(target); + var element = target; + } + + let utils = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); + let presShellId = {}; + utils.getPresShellId(presShellId); + let viewId = utils.getViewId(element); + + sendAsyncMessage("scroll", { presShellId: presShellId.value, + viewId: viewId, + scrollOffset: scrollOffset, + isRoot: isRoot }); } }; diff --git a/browser/metro/base/content/bindings/browser.xml b/browser/metro/base/content/bindings/browser.xml index f7340589a75e..67db5babe3e1 100644 --- a/browser/metro/base/content/bindings/browser.xml +++ b/browser/metro/base/content/bindings/browser.xml @@ -859,9 +859,11 @@ switch (aMessage.name) { case "scroll": + if (!json.isRoot) + return; if (!self.scrollSync) return; - this.doScroll(json.x, json.y, 0); + this.doScroll(json.scrollOffset.x, json.scrollOffset.y, 0); break; } }, diff --git a/widget/windows/winrt/MetroWidget.cpp b/widget/windows/winrt/MetroWidget.cpp index 854430232f01..5d49fb94ff56 100644 --- a/widget/windows/winrt/MetroWidget.cpp +++ b/widget/windows/winrt/MetroWidget.cpp @@ -163,6 +163,7 @@ MetroWidget::MetroWidget() : mWnd(NULL), mMetroWndProc(NULL), mTempBasicLayerInUse(false), + mRootLayerTreeId(), nsWindowBase() { // Global initialization @@ -271,6 +272,14 @@ MetroWidget::Destroy() nsCOMPtr kungFuDeathGrip(this); + if (ShouldUseAPZC()) { + nsresult rv; + nsCOMPtr observerService = do_GetService("@mozilla.org/observer-service;1", &rv); + if (NS_SUCCEEDED(rv)) { + observerService->RemoveObserver(this, "scroll-offset-changed"); + } + } + RemoveSubclass(); NotifyWindowDestroyed(); @@ -829,6 +838,13 @@ CompositorParent* MetroWidget::NewCompositorParent(int aSurfaceWidth, int aSurfa if (ShouldUseAPZC()) { CompositorParent::SetControllerForLayerTree(compositor->RootLayerTreeId(), this); MetroWidget::sAPZC = CompositorParent::GetAPZCTreeManager(compositor->RootLayerTreeId()); + mRootLayerTreeId = compositor->RootLayerTreeId(); + + nsresult rv; + nsCOMPtr observerService = do_GetService("@mozilla.org/observer-service;1", &rv); + if (NS_SUCCEEDED(rv)) { + observerService->AddObserver(this, "scroll-offset-changed", false); + } } return compositor; @@ -1446,3 +1462,30 @@ MetroWidget::HandlePanEnd() LogFunction(); MetroUtils::FireObserver("apzc-handle-pan-end", L""); } + +NS_IMETHODIMP +MetroWidget::Observe(nsISupports *subject, const char *topic, const PRUnichar *data) +{ + NS_ENSURE_ARG_POINTER(topic); + if (!strcmp(topic, "scroll-offset-changed")) { + uint64_t scrollId; + int32_t presShellId; + CSSIntPoint scrollOffset; + int matched = sscanf(NS_LossyConvertUTF16toASCII(data).get(), + "%llu %d (%d, %d)", + &scrollId, + &presShellId, + &scrollOffset.x, + &scrollOffset.y); + if (matched != 4) { + NS_WARNING("Malformed scroll-offset-changed message"); + return NS_ERROR_UNEXPECTED; + } + if (MetroWidget::sAPZC) { + MetroWidget::sAPZC->UpdateScrollOffset( + ScrollableLayerGuid(mRootLayerTreeId, presShellId, scrollId), + scrollOffset); + } + } + return NS_OK; +} \ No newline at end of file diff --git a/widget/windows/winrt/MetroWidget.h b/widget/windows/winrt/MetroWidget.h index 0a049bd604da..5d9aef8c6cdb 100644 --- a/widget/windows/winrt/MetroWidget.h +++ b/widget/windows/winrt/MetroWidget.h @@ -46,7 +46,8 @@ class FrameworkView; } } } class MetroWidget : public nsWindowBase, - public mozilla::layers::GeckoContentController + public mozilla::layers::GeckoContentController, + public nsIObserver { typedef mozilla::widget::WindowHook WindowHook; typedef mozilla::widget::TaskbarWindowPreview TaskbarWindowPreview; @@ -55,6 +56,7 @@ class MetroWidget : public nsWindowBase, typedef ABI::Windows::UI::Core::IKeyEventArgs IKeyEventArgs; typedef ABI::Windows::UI::Core::ICharacterReceivedEventArgs ICharacterReceivedEventArgs; typedef mozilla::widget::winrt::FrameworkView FrameworkView; + typedef mozilla::layers::FrameMetrics FrameMetrics; static LRESULT CALLBACK StaticWindowProcedure(HWND aWnd, UINT aMsg, WPARAM aWParan, LPARAM aLParam); @@ -65,6 +67,7 @@ public: virtual ~MetroWidget(); NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIOBSERVER static HWND GetICoreWindowHWND() { return sICoreHwnd; } @@ -194,11 +197,11 @@ public: void RequestContentRepaintImplMainThread(); // GeckoContentController interface impl - virtual void RequestContentRepaint(const mozilla::layers::FrameMetrics& aFrameMetrics); + virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics); virtual void HandleDoubleTap(const mozilla::CSSIntPoint& aPoint); virtual void HandleSingleTap(const mozilla::CSSIntPoint& aPoint); virtual void HandleLongTap(const mozilla::CSSIntPoint& aPoint); - virtual void SendAsyncScrollDOMEvent(mozilla::layers::FrameMetrics::ViewID aScrollId, const mozilla::CSSRect &aContentRect, const mozilla::CSSSize &aScrollableSize); + virtual void SendAsyncScrollDOMEvent(FrameMetrics::ViewID aScrollId, const mozilla::CSSRect &aContentRect, const mozilla::CSSSize &aScrollableSize); virtual void PostDelayedTask(Task* aTask, int aDelayMs); virtual void HandlePanBegin(); virtual void HandlePanEnd(); @@ -243,6 +246,7 @@ protected: bool mTempBasicLayerInUse; Microsoft::WRL::ComPtr mMetroInput; mozilla::layers::FrameMetrics mFrameMetrics; + uint64_t mRootLayerTreeId; public: static nsRefPtr sAPZC;