diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /gfx/layers/apz/src/APZInputBridge.cpp | |
parent | Initial commit. (diff) | |
download | firefox-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.cpp | 215 |
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 |