summaryrefslogtreecommitdiffstats
path: root/gfx/layers/apz/public/IAPZCTreeManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/layers/apz/public/IAPZCTreeManager.cpp')
-rw-r--r--gfx/layers/apz/public/IAPZCTreeManager.cpp164
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