From e2f100731e6f01f427c66a85890edf7c912bec8a Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 18 Dec 2014 15:25:03 -0800 Subject: [PATCH] Handle in-process APZ events correctly on Windows. (bug 1111873 part 2, r=kats) --HG-- extra : rebase_source : 8ca5156392705e3a1806fc6a15154dbaa380f438 --- dom/ipc/TabParent.cpp | 5 +++++ gfx/layers/apz/src/APZCTreeManager.cpp | 7 +++++++ gfx/layers/apz/src/APZCTreeManager.h | 6 ++++++ gfx/layers/apz/util/InputAPZContext.cpp | 16 ++++++++++++++++ gfx/layers/apz/util/InputAPZContext.h | 5 +++++ widget/nsBaseWidget.cpp | 23 +++++++++++++++++++++++ widget/nsBaseWidget.h | 8 ++++++++ widget/windows/nsWindow.cpp | 18 +++++++++--------- 8 files changed, 79 insertions(+), 9 deletions(-) diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index b19c97d3b5e8..f6f02f443f4e 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -2150,6 +2150,11 @@ TabParent::MaybeForwardEventToRenderFrame(WidgetInputEvent& aEvent, if (aOutInputBlockId) { *aOutInputBlockId = InputAPZContext::GetInputBlockId(); } + + // Let the widget know that the event will be sent to the child process, + // which will (hopefully) send a confirmation notice back to APZ. + InputAPZContext::SetRoutedToChildProcess(); + return nsEventStatus_eIgnore; } diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index 76dfc857a5df..e1e3c60472dc 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -1013,6 +1013,13 @@ APZCTreeManager::SetTargetAPZC(uint64_t aInputBlockId, mInputQueue->SetConfirmedTargetApzc(aInputBlockId, target); } +void +APZCTreeManager::SetTargetAPZC(uint64_t aInputBlockId, const ScrollableLayerGuid& aTarget) +{ + nsRefPtr target = GetTargetAPZC(aTarget); + mInputQueue->SetConfirmedTargetApzc(aInputBlockId, target); +} + void APZCTreeManager::UpdateZoomConstraints(const ScrollableLayerGuid& aGuid, const ZoomConstraints& aConstraints) diff --git a/gfx/layers/apz/src/APZCTreeManager.h b/gfx/layers/apz/src/APZCTreeManager.h index a010fea61839..63b6e0dd44bd 100644 --- a/gfx/layers/apz/src/APZCTreeManager.h +++ b/gfx/layers/apz/src/APZCTreeManager.h @@ -228,6 +228,12 @@ public: void SetTargetAPZC(uint64_t aInputBlockId, const nsTArray& aTargets); + /** + * Helper function for SetTargetAPZC when used with single-target events, + * such as mouse wheel events. + */ + void SetTargetAPZC(uint64_t aInputBlockId, const ScrollableLayerGuid& aTarget); + /** * Updates any zoom constraints contained in the tag. */ diff --git a/gfx/layers/apz/util/InputAPZContext.cpp b/gfx/layers/apz/util/InputAPZContext.cpp index 0aa48e7bd7df..68aa6a46f73d 100644 --- a/gfx/layers/apz/util/InputAPZContext.cpp +++ b/gfx/layers/apz/util/InputAPZContext.cpp @@ -10,6 +10,7 @@ namespace layers { ScrollableLayerGuid InputAPZContext::sGuid; uint64_t InputAPZContext::sBlockId = 0; +bool InputAPZContext::sRoutedToChildProcess = false; /*static*/ ScrollableLayerGuid InputAPZContext::GetTargetLayerGuid() @@ -23,19 +24,34 @@ InputAPZContext::GetInputBlockId() return sBlockId; } +/*static*/ void +InputAPZContext::SetRoutedToChildProcess() +{ + sRoutedToChildProcess = true; +} + InputAPZContext::InputAPZContext(const ScrollableLayerGuid& aGuid, const uint64_t& aBlockId) : mOldGuid(sGuid) , mOldBlockId(sBlockId) + , mOldRoutedToChildProcess(sRoutedToChildProcess) { sGuid = aGuid; sBlockId = aBlockId; + sRoutedToChildProcess = false; } InputAPZContext::~InputAPZContext() { sGuid = mOldGuid; sBlockId = mOldBlockId; + sRoutedToChildProcess = mOldRoutedToChildProcess; +} + +bool +InputAPZContext::WasRoutedToChildProcess() +{ + return sRoutedToChildProcess; } } diff --git a/gfx/layers/apz/util/InputAPZContext.h b/gfx/layers/apz/util/InputAPZContext.h index 4f210ac58db8..869066887a78 100644 --- a/gfx/layers/apz/util/InputAPZContext.h +++ b/gfx/layers/apz/util/InputAPZContext.h @@ -20,18 +20,23 @@ class MOZ_STACK_CLASS InputAPZContext private: static ScrollableLayerGuid sGuid; static uint64_t sBlockId; + static bool sRoutedToChildProcess; public: static ScrollableLayerGuid GetTargetLayerGuid(); static uint64_t GetInputBlockId(); + static void SetRoutedToChildProcess(); InputAPZContext(const ScrollableLayerGuid& aGuid, const uint64_t& aBlockId); ~InputAPZContext(); + bool WasRoutedToChildProcess(); + private: ScrollableLayerGuid mOldGuid; uint64_t mOldBlockId; + bool mOldRoutedToChildProcess; }; } diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index 0623e91f075e..ae5c60f7a3ff 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -46,6 +46,8 @@ #include "mozilla/VsyncDispatcher.h" #include "mozilla/layers/APZCTreeManager.h" #include "mozilla/layers/ChromeProcessController.h" +#include "mozilla/layers/InputAPZContext.h" +#include "mozilla/dom/TabParent.h" #ifdef ACCESSIBILITY #include "nsAccessibilityService.h" @@ -940,6 +942,27 @@ void nsBaseWidget::ConfigureAPZCTreeManager() } } +nsEventStatus +nsBaseWidget::DispatchEventForAPZ(WidgetGUIEvent* aEvent, + const ScrollableLayerGuid& aGuid, + uint64_t aInputBlockId) +{ + InputAPZContext context(aGuid, aInputBlockId); + + nsEventStatus status; + DispatchEvent(aEvent, status); + + if (mAPZC && !context.WasRoutedToChildProcess()) { + // APZ did not find a dispatch-to-content region in the child process, + // and EventStateManager did not route the event into the child process. + // It's safe to communicate to APZ that the event has been processed. + mAPZC->SetTargetAPZC(aInputBlockId, aGuid); + mAPZC->ContentReceivedInputBlock(aInputBlockId, aEvent->mFlags.mDefaultPrevented); + } + + return status; +} + void nsBaseWidget::GetPreferredCompositorBackends(nsTArray& aHints) { diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h index 15bf254732c9..1e3c6789f8d5 100644 --- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -36,6 +36,7 @@ class CompositorChild; class CompositorParent; class APZCTreeManager; class GeckoContentController; +struct ScrollableLayerGuid; } class VsyncDispatcher; @@ -88,6 +89,7 @@ protected: typedef mozilla::layers::CompositorParent CompositorParent; typedef mozilla::layers::APZCTreeManager APZCTreeManager; typedef mozilla::layers::GeckoContentController GeckoContentController; + typedef mozilla::layers::ScrollableLayerGuid ScrollableLayerGuid; typedef mozilla::ScreenRotation ScreenRotation; virtual ~nsBaseWidget(); @@ -311,6 +313,12 @@ protected: virtual void ConfigureAPZCTreeManager(); virtual already_AddRefed CreateRootContentController(); + // Dispatch an event that has been routed through APZ directly from the + // widget. + nsEventStatus DispatchEventForAPZ(mozilla::WidgetGUIEvent* aEvent, + const ScrollableLayerGuid& aGuid, + uint64_t aInputBlockId); + const nsIntRegion RegionFromArray(const nsTArray& aRects); void ArrayFromRegion(const nsIntRegion& aRegion, nsTArray& aRects); diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index 1d56e9533f77..bafa64f5c600 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -3742,20 +3742,20 @@ bool nsWindow::DispatchKeyboardEvent(WidgetGUIEvent* event) bool nsWindow::DispatchScrollEvent(WidgetGUIEvent* aEvent) { - uint64_t inputBlockId = 0; - ScrollableLayerGuid guid; + nsEventStatus status; if (mAPZC && aEvent->mClass == eWheelEventClass) { - nsEventStatus status = mAPZC->ReceiveInputEvent(*aEvent->AsWheelEvent(), &guid, &inputBlockId); - if (status == nsEventStatus_eConsumeNoDefault) { + uint64_t inputBlockId = 0; + ScrollableLayerGuid guid; + + nsEventStatus result = mAPZC->ReceiveInputEvent(*aEvent->AsWheelEvent(), &guid, &inputBlockId); + if (result == nsEventStatus_eConsumeNoDefault) { return true; } + status = DispatchEventForAPZ(aEvent, guid, inputBlockId); + } else { + DispatchEvent(aEvent, status); } - - InputAPZContext context(guid, inputBlockId); - - nsEventStatus status; - DispatchEvent(aEvent, status); return ConvertStatus(status); }