diff options
Diffstat (limited to 'gfx/layers/apz/public/IAPZCTreeManager.cpp')
-rw-r--r-- | gfx/layers/apz/public/IAPZCTreeManager.cpp | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/gfx/layers/apz/public/IAPZCTreeManager.cpp b/gfx/layers/apz/public/IAPZCTreeManager.cpp new file mode 100644 index 000000000..372257ae4 --- /dev/null +++ b/gfx/layers/apz/public/IAPZCTreeManager.cpp @@ -0,0 +1,164 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=99: */ +/* 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 "mozilla/layers/IAPZCTreeManager.h" + +#include "gfxPrefs.h" // for gfxPrefs +#include "InputData.h" // for InputData, etc +#include "mozilla/EventStateManager.h" // for WheelPrefs +#include "mozilla/layers/APZThreadUtils.h" // for AssertOnCompositorThread, etc +#include "mozilla/MouseEvents.h" // for WidgetMouseEvent +#include "mozilla/TouchEvents.h" // for WidgetTouchEvent + +namespace mozilla { +namespace layers { + +static bool +WillHandleMouseEvent(const WidgetMouseEventBase& aEvent) +{ + return aEvent.mMessage == eMouseMove || + aEvent.mMessage == eMouseDown || + aEvent.mMessage == eMouseUp || + aEvent.mMessage == eDragEnd; +} + +// Returns whether or not a wheel event action will be (or was) performed by +// APZ. If this returns true, the event must not perform a synchronous +// scroll. +// +// Even if this returns false, all wheel events in APZ-aware widgets must +// be sent through APZ so they are transformed correctly for TabParent. +static bool +WillHandleWheelEvent(WidgetWheelEvent* aEvent) +{ + return EventStateManager::WheelEventIsScrollAction(aEvent) && + (aEvent->mDeltaMode == nsIDOMWheelEvent::DOM_DELTA_LINE || + aEvent->mDeltaMode == nsIDOMWheelEvent::DOM_DELTA_PIXEL || + aEvent->mDeltaMode == nsIDOMWheelEvent::DOM_DELTA_PAGE); +} + +nsEventStatus +IAPZCTreeManager::ReceiveInputEvent( + WidgetInputEvent& aEvent, + ScrollableLayerGuid* aOutTargetGuid, + uint64_t* aOutInputBlockId) +{ + APZThreadUtils::AssertOnControllerThread(); + + // Initialize aOutInputBlockId to a sane value, and then later we overwrite + // it if the input event goes into a block. + if (aOutInputBlockId) { + *aOutInputBlockId = 0; + } + + switch (aEvent.mClass) { + case eMouseEventClass: + case eDragEventClass: { + + WidgetMouseEvent& mouseEvent = *aEvent.AsMouseEvent(); + + // Note, we call this before having transformed the reference point. + if (mouseEvent.IsReal()) { + UpdateWheelTransaction(mouseEvent.mRefPoint, mouseEvent.mMessage); + } + + if (WillHandleMouseEvent(mouseEvent)) { + + MouseInput input(mouseEvent); + input.mOrigin = ScreenPoint(mouseEvent.mRefPoint.x, mouseEvent.mRefPoint.y); + + nsEventStatus status = ReceiveInputEvent(input, aOutTargetGuid, aOutInputBlockId); + + mouseEvent.mRefPoint.x = input.mOrigin.x; + mouseEvent.mRefPoint.y = input.mOrigin.y; + mouseEvent.mFlags.mHandledByAPZ = input.mHandledByAPZ; + return status; + + } + + TransformEventRefPoint(&mouseEvent.mRefPoint, aOutTargetGuid); + return nsEventStatus_eIgnore; + } + case eTouchEventClass: { + + WidgetTouchEvent& touchEvent = *aEvent.AsTouchEvent(); + MultiTouchInput touchInput(touchEvent); + nsEventStatus result = ReceiveInputEvent(touchInput, aOutTargetGuid, aOutInputBlockId); + // touchInput was modified in-place to possibly remove some + // touch points (if we are overscrolled), and the coordinates were + // modified using the APZ untransform. We need to copy these changes + // back into the WidgetInputEvent. + touchEvent.mTouches.Clear(); + touchEvent.mTouches.SetCapacity(touchInput.mTouches.Length()); + for (size_t i = 0; i < touchInput.mTouches.Length(); i++) { + *touchEvent.mTouches.AppendElement() = + touchInput.mTouches[i].ToNewDOMTouch(); + } + touchEvent.mFlags.mHandledByAPZ = touchInput.mHandledByAPZ; + return result; + + } + case eWheelEventClass: { + WidgetWheelEvent& wheelEvent = *aEvent.AsWheelEvent(); + + if (WillHandleWheelEvent(&wheelEvent)) { + + ScrollWheelInput::ScrollMode scrollMode = ScrollWheelInput::SCROLLMODE_INSTANT; + if (gfxPrefs::SmoothScrollEnabled() && + ((wheelEvent.mDeltaMode == nsIDOMWheelEvent::DOM_DELTA_LINE && + gfxPrefs::WheelSmoothScrollEnabled()) || + (wheelEvent.mDeltaMode == nsIDOMWheelEvent::DOM_DELTA_PAGE && + gfxPrefs::PageSmoothScrollEnabled()))) + { + scrollMode = ScrollWheelInput::SCROLLMODE_SMOOTH; + } + + ScreenPoint origin(wheelEvent.mRefPoint.x, wheelEvent.mRefPoint.y); + ScrollWheelInput input(wheelEvent.mTime, wheelEvent.mTimeStamp, 0, + scrollMode, + ScrollWheelInput::DeltaTypeForDeltaMode( + wheelEvent.mDeltaMode), + origin, + wheelEvent.mDeltaX, wheelEvent.mDeltaY, + wheelEvent.mAllowToOverrideSystemScrollSpeed); + + // We add the user multiplier as a separate field, rather than premultiplying + // it, because if the input is converted back to a WidgetWheelEvent, then + // EventStateManager would apply the delta a second time. We could in theory + // work around this by asking ESM to customize the event much sooner, and + // then save the "mCustomizedByUserPrefs" bit on ScrollWheelInput - but for + // now, this seems easier. + EventStateManager::GetUserPrefsForWheelEvent(&wheelEvent, + &input.mUserDeltaMultiplierX, + &input.mUserDeltaMultiplierY); + + nsEventStatus status = ReceiveInputEvent(input, aOutTargetGuid, aOutInputBlockId); + wheelEvent.mRefPoint.x = input.mOrigin.x; + wheelEvent.mRefPoint.y = input.mOrigin.y; + wheelEvent.mFlags.mHandledByAPZ = input.mHandledByAPZ; + return status; + } + + UpdateWheelTransaction(aEvent.mRefPoint, aEvent.mMessage); + TransformEventRefPoint(&aEvent.mRefPoint, aOutTargetGuid); + return nsEventStatus_eIgnore; + + } + default: { + + UpdateWheelTransaction(aEvent.mRefPoint, aEvent.mMessage); + TransformEventRefPoint(&aEvent.mRefPoint, aOutTargetGuid); + return nsEventStatus_eIgnore; + + } + } + + MOZ_ASSERT_UNREACHABLE("Invalid WidgetInputEvent type."); + return nsEventStatus_eConsumeNoDefault; +} + +} // namespace layers +} // namespace mozilla |