Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=99: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "mozilla/layers/IAPZCTreeManager.h"
8 :
9 : #include "gfxPrefs.h" // for gfxPrefs
10 : #include "InputData.h" // for InputData, etc
11 : #include "mozilla/EventStateManager.h" // for WheelPrefs
12 : #include "mozilla/layers/APZThreadUtils.h" // for AssertOnCompositorThread, etc
13 : #include "mozilla/MouseEvents.h" // for WidgetMouseEvent
14 : #include "mozilla/TextEvents.h" // for WidgetKeyboardEvent
15 : #include "mozilla/TouchEvents.h" // for WidgetTouchEvent
16 :
17 : namespace mozilla {
18 : namespace layers {
19 :
20 : static bool
21 6 : WillHandleMouseEvent(const WidgetMouseEventBase& aEvent)
22 : {
23 8 : return aEvent.mMessage == eMouseMove ||
24 4 : aEvent.mMessage == eMouseDown ||
25 10 : aEvent.mMessage == eMouseUp ||
26 8 : aEvent.mMessage == eDragEnd;
27 : }
28 :
29 : /* static */ bool
30 0 : IAPZCTreeManager::WillHandleWheelEvent(WidgetWheelEvent* aEvent)
31 : {
32 0 : return EventStateManager::WheelEventIsScrollAction(aEvent) &&
33 0 : (aEvent->mDeltaMode == nsIDOMWheelEvent::DOM_DELTA_LINE ||
34 0 : aEvent->mDeltaMode == nsIDOMWheelEvent::DOM_DELTA_PIXEL ||
35 0 : aEvent->mDeltaMode == nsIDOMWheelEvent::DOM_DELTA_PAGE);
36 : }
37 :
38 : nsEventStatus
39 6 : IAPZCTreeManager::ReceiveInputEvent(
40 : WidgetInputEvent& aEvent,
41 : ScrollableLayerGuid* aOutTargetGuid,
42 : uint64_t* aOutInputBlockId)
43 : {
44 6 : APZThreadUtils::AssertOnControllerThread();
45 :
46 : // Initialize aOutInputBlockId to a sane value, and then later we overwrite
47 : // it if the input event goes into a block.
48 6 : if (aOutInputBlockId) {
49 6 : *aOutInputBlockId = 0;
50 : }
51 :
52 6 : switch (aEvent.mClass) {
53 : case eMouseEventClass:
54 : case eDragEventClass: {
55 :
56 6 : WidgetMouseEvent& mouseEvent = *aEvent.AsMouseEvent();
57 :
58 : // Note, we call this before having transformed the reference point.
59 6 : if (mouseEvent.IsReal()) {
60 6 : UpdateWheelTransaction(mouseEvent.mRefPoint, mouseEvent.mMessage);
61 : }
62 :
63 6 : if (WillHandleMouseEvent(mouseEvent)) {
64 :
65 8 : MouseInput input(mouseEvent);
66 4 : input.mOrigin = ScreenPoint(mouseEvent.mRefPoint.x, mouseEvent.mRefPoint.y);
67 :
68 4 : nsEventStatus status = ReceiveInputEvent(input, aOutTargetGuid, aOutInputBlockId);
69 :
70 4 : mouseEvent.mRefPoint.x = input.mOrigin.x;
71 4 : mouseEvent.mRefPoint.y = input.mOrigin.y;
72 4 : mouseEvent.mFlags.mHandledByAPZ = input.mHandledByAPZ;
73 4 : mouseEvent.mFocusSequenceNumber = input.mFocusSequenceNumber;
74 4 : return status;
75 :
76 : }
77 :
78 2 : ProcessUnhandledEvent(&mouseEvent.mRefPoint, aOutTargetGuid, &aEvent.mFocusSequenceNumber);
79 2 : return nsEventStatus_eIgnore;
80 : }
81 : case eTouchEventClass: {
82 :
83 0 : WidgetTouchEvent& touchEvent = *aEvent.AsTouchEvent();
84 0 : MultiTouchInput touchInput(touchEvent);
85 0 : nsEventStatus result = ReceiveInputEvent(touchInput, aOutTargetGuid, aOutInputBlockId);
86 : // touchInput was modified in-place to possibly remove some
87 : // touch points (if we are overscrolled), and the coordinates were
88 : // modified using the APZ untransform. We need to copy these changes
89 : // back into the WidgetInputEvent.
90 0 : touchEvent.mTouches.Clear();
91 0 : touchEvent.mTouches.SetCapacity(touchInput.mTouches.Length());
92 0 : for (size_t i = 0; i < touchInput.mTouches.Length(); i++) {
93 : *touchEvent.mTouches.AppendElement() =
94 0 : touchInput.mTouches[i].ToNewDOMTouch();
95 : }
96 0 : touchEvent.mFlags.mHandledByAPZ = touchInput.mHandledByAPZ;
97 0 : touchEvent.mFocusSequenceNumber = touchInput.mFocusSequenceNumber;
98 0 : return result;
99 :
100 : }
101 : case eWheelEventClass: {
102 0 : WidgetWheelEvent& wheelEvent = *aEvent.AsWheelEvent();
103 :
104 0 : if (WillHandleWheelEvent(&wheelEvent)) {
105 :
106 0 : ScrollWheelInput::ScrollMode scrollMode = ScrollWheelInput::SCROLLMODE_INSTANT;
107 0 : if (gfxPrefs::SmoothScrollEnabled() &&
108 0 : ((wheelEvent.mDeltaMode == nsIDOMWheelEvent::DOM_DELTA_LINE &&
109 0 : gfxPrefs::WheelSmoothScrollEnabled()) ||
110 0 : (wheelEvent.mDeltaMode == nsIDOMWheelEvent::DOM_DELTA_PAGE &&
111 0 : gfxPrefs::PageSmoothScrollEnabled())))
112 : {
113 0 : scrollMode = ScrollWheelInput::SCROLLMODE_SMOOTH;
114 : }
115 :
116 0 : ScreenPoint origin(wheelEvent.mRefPoint.x, wheelEvent.mRefPoint.y);
117 0 : ScrollWheelInput input(wheelEvent.mTime, wheelEvent.mTimeStamp, 0,
118 : scrollMode,
119 : ScrollWheelInput::DeltaTypeForDeltaMode(
120 : wheelEvent.mDeltaMode),
121 : origin,
122 : wheelEvent.mDeltaX, wheelEvent.mDeltaY,
123 0 : wheelEvent.mAllowToOverrideSystemScrollSpeed);
124 :
125 : // We add the user multiplier as a separate field, rather than premultiplying
126 : // it, because if the input is converted back to a WidgetWheelEvent, then
127 : // EventStateManager would apply the delta a second time. We could in theory
128 : // work around this by asking ESM to customize the event much sooner, and
129 : // then save the "mCustomizedByUserPrefs" bit on ScrollWheelInput - but for
130 : // now, this seems easier.
131 : EventStateManager::GetUserPrefsForWheelEvent(&wheelEvent,
132 : &input.mUserDeltaMultiplierX,
133 0 : &input.mUserDeltaMultiplierY);
134 :
135 0 : nsEventStatus status = ReceiveInputEvent(input, aOutTargetGuid, aOutInputBlockId);
136 0 : wheelEvent.mRefPoint.x = input.mOrigin.x;
137 0 : wheelEvent.mRefPoint.y = input.mOrigin.y;
138 0 : wheelEvent.mFlags.mHandledByAPZ = input.mHandledByAPZ;
139 0 : wheelEvent.mFocusSequenceNumber = input.mFocusSequenceNumber;
140 0 : return status;
141 : }
142 :
143 0 : UpdateWheelTransaction(aEvent.mRefPoint, aEvent.mMessage);
144 0 : ProcessUnhandledEvent(&aEvent.mRefPoint, aOutTargetGuid, &aEvent.mFocusSequenceNumber);
145 0 : return nsEventStatus_eIgnore;
146 :
147 : }
148 : case eKeyboardEventClass: {
149 0 : WidgetKeyboardEvent& keyboardEvent = *aEvent.AsKeyboardEvent();
150 :
151 0 : KeyboardInput input(keyboardEvent);
152 :
153 0 : nsEventStatus status = ReceiveInputEvent(input, aOutTargetGuid, aOutInputBlockId);
154 :
155 0 : keyboardEvent.mFlags.mHandledByAPZ = input.mHandledByAPZ;
156 0 : keyboardEvent.mFocusSequenceNumber = input.mFocusSequenceNumber;
157 0 : return status;
158 : }
159 : default: {
160 :
161 0 : UpdateWheelTransaction(aEvent.mRefPoint, aEvent.mMessage);
162 0 : ProcessUnhandledEvent(&aEvent.mRefPoint, aOutTargetGuid, &aEvent.mFocusSequenceNumber);
163 0 : return nsEventStatus_eIgnore;
164 :
165 : }
166 : }
167 :
168 : MOZ_ASSERT_UNREACHABLE("Invalid WidgetInputEvent type.");
169 : return nsEventStatus_eConsumeNoDefault;
170 : }
171 :
172 : } // namespace layers
173 : } // namespace mozilla
|