summaryrefslogtreecommitdiffstats
path: root/gfx/layers/apz/src/APZInputBridge.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /gfx/layers/apz/src/APZInputBridge.cpp
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'gfx/layers/apz/src/APZInputBridge.cpp')
-rw-r--r--gfx/layers/apz/src/APZInputBridge.cpp215
1 files changed, 215 insertions, 0 deletions
diff --git a/gfx/layers/apz/src/APZInputBridge.cpp b/gfx/layers/apz/src/APZInputBridge.cpp
new file mode 100644
index 0000000000..3472c497b5
--- /dev/null
+++ b/gfx/layers/apz/src/APZInputBridge.cpp
@@ -0,0 +1,215 @@
+/* -*- 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 "mozilla/layers/APZInputBridge.h"
+
+#include "InputData.h" // for MouseInput, etc
+#include "InputBlockState.h" // for InputBlockState
+#include "mozilla/dom/WheelEventBinding.h" // for WheelEvent constants
+#include "mozilla/EventStateManager.h" // for EventStateManager
+#include "mozilla/layers/APZThreadUtils.h" // for AssertOnControllerThread, etc
+#include "mozilla/MouseEvents.h" // for WidgetMouseEvent
+#include "mozilla/StaticPrefs_apz.h"
+#include "mozilla/StaticPrefs_general.h"
+#include "mozilla/StaticPrefs_test.h"
+#include "mozilla/TextEvents.h" // for WidgetKeyboardEvent
+#include "mozilla/TouchEvents.h" // for WidgetTouchEvent
+#include "mozilla/WheelHandlingHelper.h" // for WheelDeltaHorizontalizer,
+ // WheelDeltaAdjustmentStrategy
+
+namespace mozilla {
+namespace layers {
+
+APZEventResult::APZEventResult()
+ : mStatus(nsEventStatus_eIgnore),
+ mInputBlockId(InputBlockState::NO_BLOCK_ID) {}
+
+static bool WillHandleMouseEvent(const WidgetMouseEventBase& aEvent) {
+ return aEvent.mMessage == eMouseMove || aEvent.mMessage == eMouseDown ||
+ aEvent.mMessage == eMouseUp || aEvent.mMessage == eDragEnd ||
+ (StaticPrefs::test_events_async_enabled() &&
+ aEvent.mMessage == eMouseHitTest);
+}
+
+/* static */
+Maybe<APZWheelAction> APZInputBridge::ActionForWheelEvent(
+ WidgetWheelEvent* aEvent) {
+ if (!(aEvent->mDeltaMode == dom::WheelEvent_Binding::DOM_DELTA_LINE ||
+ aEvent->mDeltaMode == dom::WheelEvent_Binding::DOM_DELTA_PIXEL ||
+ aEvent->mDeltaMode == dom::WheelEvent_Binding::DOM_DELTA_PAGE)) {
+ return Nothing();
+ }
+ return EventStateManager::APZWheelActionFor(aEvent);
+}
+
+APZEventResult APZInputBridge::ReceiveInputEvent(WidgetInputEvent& aEvent) {
+ APZThreadUtils::AssertOnControllerThread();
+
+ APZEventResult result;
+
+ 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);
+
+ result = ReceiveInputEvent(input);
+
+ mouseEvent.mRefPoint.x = input.mOrigin.x;
+ mouseEvent.mRefPoint.y = input.mOrigin.y;
+ mouseEvent.mFlags.mHandledByAPZ = input.mHandledByAPZ;
+ mouseEvent.mFocusSequenceNumber = input.mFocusSequenceNumber;
+ aEvent.mLayersId = input.mLayersId;
+ return result;
+ }
+
+ ProcessUnhandledEvent(&mouseEvent.mRefPoint, &result.mTargetGuid,
+ &aEvent.mFocusSequenceNumber, &aEvent.mLayersId);
+ return result;
+ }
+ case eTouchEventClass: {
+ WidgetTouchEvent& touchEvent = *aEvent.AsTouchEvent();
+ MultiTouchInput touchInput(touchEvent);
+ result = ReceiveInputEvent(touchInput);
+ // 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;
+ touchEvent.mFocusSequenceNumber = touchInput.mFocusSequenceNumber;
+ aEvent.mLayersId = touchInput.mLayersId;
+ return result;
+ }
+ case eWheelEventClass: {
+ WidgetWheelEvent& wheelEvent = *aEvent.AsWheelEvent();
+
+ if (Maybe<APZWheelAction> action = ActionForWheelEvent(&wheelEvent)) {
+ ScrollWheelInput::ScrollMode scrollMode =
+ ScrollWheelInput::SCROLLMODE_INSTANT;
+ if (StaticPrefs::general_smoothScroll() &&
+ ((wheelEvent.mDeltaMode ==
+ dom::WheelEvent_Binding::DOM_DELTA_LINE &&
+ StaticPrefs::general_smoothScroll_mouseWheel()) ||
+ (wheelEvent.mDeltaMode ==
+ dom::WheelEvent_Binding::DOM_DELTA_PAGE &&
+ StaticPrefs::general_smoothScroll_pages()))) {
+ scrollMode = ScrollWheelInput::SCROLLMODE_SMOOTH;
+ }
+
+ WheelDeltaAdjustmentStrategy strategy =
+ EventStateManager::GetWheelDeltaAdjustmentStrategy(wheelEvent);
+ // Adjust the delta values of the wheel event if the current default
+ // action is to horizontalize scrolling. I.e., deltaY values are set to
+ // deltaX and deltaY and deltaZ values are set to 0.
+ // If horizontalized, the delta values will be restored and its overflow
+ // deltaX will become 0 when the WheelDeltaHorizontalizer instance is
+ // being destroyed.
+ WheelDeltaHorizontalizer horizontalizer(wheelEvent);
+ if (WheelDeltaAdjustmentStrategy::eHorizontalize == strategy) {
+ horizontalizer.Horizontalize();
+ }
+
+ // If the wheel event becomes no-op event, don't handle it as scroll.
+ if (wheelEvent.mDeltaX || wheelEvent.mDeltaY) {
+ 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, strategy);
+ input.mAPZAction = action.value();
+
+ // 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);
+
+ result = ReceiveInputEvent(input);
+ wheelEvent.mRefPoint.x = input.mOrigin.x;
+ wheelEvent.mRefPoint.y = input.mOrigin.y;
+ wheelEvent.mFlags.mHandledByAPZ = input.mHandledByAPZ;
+ wheelEvent.mFocusSequenceNumber = input.mFocusSequenceNumber;
+ aEvent.mLayersId = input.mLayersId;
+
+ return result;
+ }
+ }
+
+ UpdateWheelTransaction(aEvent.mRefPoint, aEvent.mMessage);
+ ProcessUnhandledEvent(&aEvent.mRefPoint, &result.mTargetGuid,
+ &aEvent.mFocusSequenceNumber, &aEvent.mLayersId);
+ result.mStatus = nsEventStatus_eIgnore;
+ return result;
+ }
+ case eKeyboardEventClass: {
+ WidgetKeyboardEvent& keyboardEvent = *aEvent.AsKeyboardEvent();
+
+ KeyboardInput input(keyboardEvent);
+
+ result = ReceiveInputEvent(input);
+
+ keyboardEvent.mFlags.mHandledByAPZ = input.mHandledByAPZ;
+ keyboardEvent.mFocusSequenceNumber = input.mFocusSequenceNumber;
+ return result;
+ }
+ default: {
+ UpdateWheelTransaction(aEvent.mRefPoint, aEvent.mMessage);
+ ProcessUnhandledEvent(&aEvent.mRefPoint, &result.mTargetGuid,
+ &aEvent.mFocusSequenceNumber, &aEvent.mLayersId);
+ return result;
+ }
+ }
+
+ MOZ_ASSERT_UNREACHABLE("Invalid WidgetInputEvent type.");
+ result.mStatus = nsEventStatus_eConsumeNoDefault;
+ return result;
+}
+
+std::ostream& operator<<(std::ostream& aOut,
+ const APZHandledResult& aHandledResult) {
+ switch (aHandledResult) {
+ case APZHandledResult::Unhandled:
+ aOut << "unhandled";
+ break;
+ case APZHandledResult::HandledByRoot: {
+ aOut << "handled-by-root";
+ break;
+ }
+ case APZHandledResult::HandledByContent: {
+ aOut << "handled-by-content";
+ break;
+ }
+ case APZHandledResult::Invalid: {
+ aOut << "INVALID";
+ break;
+ }
+ }
+ return aOut;
+}
+
+} // namespace layers
+} // namespace mozilla