| OLD | NEW | 
|---|
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "core/input/MouseWheelEventManager.h" | 5 #include "core/input/MouseWheelEventManager.h" | 
| 6 | 6 | 
| 7 #include "core/dom/Document.h" | 7 #include "core/dom/Document.h" | 
| 8 #include "core/events/WheelEvent.h" | 8 #include "core/events/WheelEvent.h" | 
| 9 #include "core/frame/LocalFrameView.h" | 9 #include "core/frame/LocalFrameView.h" | 
| 10 #include "core/input/EventHandler.h" | 10 #include "core/input/EventHandler.h" | 
| 11 #include "core/input/EventHandlingUtil.h" | 11 #include "core/input/EventHandlingUtil.h" | 
| 12 #include "core/input/ScrollManager.h" | 12 #include "core/input/ScrollManager.h" | 
| 13 #include "core/layout/HitTestRequest.h" | 13 #include "core/layout/HitTestRequest.h" | 
| 14 #include "core/layout/HitTestResult.h" | 14 #include "core/layout/HitTestResult.h" | 
| 15 #include "core/layout/api/LayoutViewItem.h" | 15 #include "core/layout/api/LayoutViewItem.h" | 
| 16 #include "public/platform/WebMouseWheelEvent.h" | 16 #include "public/platform/WebMouseWheelEvent.h" | 
| 17 | 17 | 
| 18 namespace blink { | 18 namespace blink { | 
| 19 MouseWheelEventManager::MouseWheelEventManager(LocalFrame& frame, | 19 MouseWheelEventManager::MouseWheelEventManager(LocalFrame& frame, | 
| 20                                                ScrollManager& scroll_manager) | 20                                                ScrollManager& scroll_manager) | 
| 21     : frame_(frame), scroll_manager_(scroll_manager) {} | 21     : frame_(frame), wheel_target_(nullptr), scroll_manager_(scroll_manager) {} | 
| 22 | 22 | 
| 23 DEFINE_TRACE(MouseWheelEventManager) { | 23 DEFINE_TRACE(MouseWheelEventManager) { | 
| 24   visitor->Trace(frame_); | 24   visitor->Trace(frame_); | 
|  | 25   visitor->Trace(wheel_target_); | 
| 25   visitor->Trace(scroll_manager_); | 26   visitor->Trace(scroll_manager_); | 
| 26 } | 27 } | 
| 27 | 28 | 
|  | 29 void MouseWheelEventManager::Clear() { | 
|  | 30   wheel_target_ = nullptr; | 
|  | 31 } | 
|  | 32 | 
| 28 WebInputEventResult MouseWheelEventManager::HandleWheelEvent( | 33 WebInputEventResult MouseWheelEventManager::HandleWheelEvent( | 
| 29     const WebMouseWheelEvent& event) { | 34     const WebMouseWheelEvent& event) { | 
| 30 #if OS(MACOSX) | 35   bool wheel_scroll_latching = | 
| 31   // Filter Mac OS specific phases, usually with a zero-delta. | 36       RuntimeEnabledFeatures::TouchpadAndWheelScrollLatchingEnabled(); | 
| 32   // https://crbug.com/553732 | 37 | 
| 33   // TODO(chongz): EventSender sends events with |  | 
| 34   // |WebMouseWheelEvent::PhaseNone|, |  | 
| 35   // but it shouldn't. |  | 
| 36   const int kWheelEventPhaseNoEventMask = WebMouseWheelEvent::kPhaseEnded | |  | 
| 37                                           WebMouseWheelEvent::kPhaseCancelled | |  | 
| 38                                           WebMouseWheelEvent::kPhaseMayBegin; |  | 
| 39   if ((event.phase & kWheelEventPhaseNoEventMask) || |  | 
| 40       (event.momentum_phase & kWheelEventPhaseNoEventMask)) |  | 
| 41     return WebInputEventResult::kNotHandled; |  | 
| 42 #endif |  | 
| 43   Document* doc = frame_->GetDocument(); | 38   Document* doc = frame_->GetDocument(); | 
| 44 | 39   if (!doc || doc->GetLayoutViewItem().IsNull()) | 
| 45   if (doc->GetLayoutViewItem().IsNull()) |  | 
| 46     return WebInputEventResult::kNotHandled; | 40     return WebInputEventResult::kNotHandled; | 
| 47 | 41 | 
| 48   LocalFrameView* view = frame_->View(); | 42   LocalFrameView* view = frame_->View(); | 
| 49   if (!view) | 43   if (!view) | 
| 50     return WebInputEventResult::kNotHandled; | 44     return WebInputEventResult::kNotHandled; | 
| 51 | 45 | 
| 52   LayoutPoint v_point = | 46   if (wheel_scroll_latching) { | 
| 53       view->RootFrameToContents(FlooredIntPoint(event.PositionInRootFrame())); | 47     const int kWheelEventPhaseEndedEventMask = | 
|  | 48         WebMouseWheelEvent::kPhaseEnded | WebMouseWheelEvent::kPhaseCancelled; | 
|  | 49     const int kWheelEventPhaseNoEventMask = | 
|  | 50         kWheelEventPhaseEndedEventMask | WebMouseWheelEvent::kPhaseMayBegin; | 
| 54 | 51 | 
| 55   HitTestRequest request(HitTestRequest::kReadOnly); | 52     if ((event.phase & kWheelEventPhaseEndedEventMask) || | 
| 56   HitTestResult result(request, v_point); | 53         (event.momentum_phase & kWheelEventPhaseEndedEventMask)) { | 
| 57   doc->GetLayoutViewItem().HitTest(result); | 54       wheel_target_ = nullptr; | 
|  | 55     } | 
| 58 | 56 | 
| 59   Node* node = result.InnerNode(); | 57     if ((event.phase & kWheelEventPhaseNoEventMask) || | 
| 60   // Wheel events should not dispatch to text nodes. | 58         (event.momentum_phase & kWheelEventPhaseNoEventMask)) { | 
| 61   if (node && node->IsTextNode()) | 59       // Filter wheel events with zero deltas and reset the wheel_target_ node. | 
| 62     node = FlatTreeTraversal::Parent(*node); | 60       DCHECK(!event.delta_x && !event.delta_y); | 
|  | 61       return WebInputEventResult::kNotHandled; | 
|  | 62     } | 
| 63 | 63 | 
| 64   // If we're over the frame scrollbar, scroll the document. | 64     if (event.phase == WebMouseWheelEvent::kPhaseBegan) { | 
| 65   if (!node && result.GetScrollbar()) | 65       // Find and save the wheel_target_, this target will be used for the rest | 
| 66     node = doc->documentElement(); | 66       // of the current scrolling sequence. | 
|  | 67       DCHECK(!wheel_target_); | 
|  | 68       wheel_target_ = FindTargetNode(event, doc, view); | 
|  | 69     } | 
|  | 70   } else {  // !wheel_scroll_latching, wheel_target_ will be updated for each | 
|  | 71             // wheel event. | 
|  | 72 #if OS(MACOSX) | 
|  | 73     // Filter Mac OS specific phases, usually with a zero-delta. | 
|  | 74     // https://crbug.com/553732 | 
|  | 75     // TODO(chongz): EventSender sends events with | 
|  | 76     // |WebMouseWheelEvent::PhaseNone|, | 
|  | 77     // but it shouldn't. | 
|  | 78     const int kWheelEventPhaseNoEventMask = | 
|  | 79         WebMouseWheelEvent::kPhaseEnded | WebMouseWheelEvent::kPhaseCancelled | | 
|  | 80         WebMouseWheelEvent::kPhaseMayBegin; | 
|  | 81     if ((event.phase & kWheelEventPhaseNoEventMask) || | 
|  | 82         (event.momentum_phase & kWheelEventPhaseNoEventMask)) | 
|  | 83       return WebInputEventResult::kNotHandled; | 
|  | 84 #endif | 
| 67 | 85 | 
| 68   LocalFrame* subframe = EventHandlingUtil::SubframeForTargetNode(node); | 86     wheel_target_ = FindTargetNode(event, doc, view); | 
|  | 87   } | 
|  | 88 | 
|  | 89   LocalFrame* subframe = | 
|  | 90       EventHandlingUtil::SubframeForTargetNode(wheel_target_.Get()); | 
| 69   if (subframe) { | 91   if (subframe) { | 
| 70     WebInputEventResult result = | 92     WebInputEventResult result = | 
| 71         subframe->GetEventHandler().HandleWheelEvent(event); | 93         subframe->GetEventHandler().HandleWheelEvent(event); | 
| 72     if (result != WebInputEventResult::kNotHandled) | 94     if (result != WebInputEventResult::kNotHandled) | 
| 73       scroll_manager_->SetFrameWasScrolledByUser(); | 95       scroll_manager_->SetFrameWasScrolledByUser(); | 
| 74     return result; | 96     return result; | 
| 75   } | 97   } | 
| 76 | 98 | 
| 77   if (node) { | 99   if (wheel_target_) { | 
| 78     WheelEvent* dom_event = | 100     WheelEvent* dom_event = | 
| 79         WheelEvent::Create(event, node->GetDocument().domWindow()); | 101         WheelEvent::Create(event, wheel_target_->GetDocument().domWindow()); | 
| 80     DispatchEventResult dom_event_result = node->DispatchEvent(dom_event); | 102     DispatchEventResult dom_event_result = | 
|  | 103         wheel_target_->DispatchEvent(dom_event); | 
| 81     if (dom_event_result != DispatchEventResult::kNotCanceled) | 104     if (dom_event_result != DispatchEventResult::kNotCanceled) | 
| 82       return EventHandlingUtil::ToWebInputEventResult(dom_event_result); | 105       return EventHandlingUtil::ToWebInputEventResult(dom_event_result); | 
| 83   } | 106   } | 
| 84 | 107 | 
| 85   return WebInputEventResult::kNotHandled; | 108   return WebInputEventResult::kNotHandled; | 
| 86 } | 109 } | 
| 87 | 110 | 
|  | 111 Node* MouseWheelEventManager::FindTargetNode(const WebMouseWheelEvent& event, | 
|  | 112                                              const Document* doc, | 
|  | 113                                              const LocalFrameView* view) { | 
|  | 114   DCHECK(doc && !doc->GetLayoutViewItem().IsNull() && view); | 
|  | 115   LayoutPoint v_point = | 
|  | 116       view->RootFrameToContents(FlooredIntPoint(event.PositionInRootFrame())); | 
|  | 117 | 
|  | 118   HitTestRequest request(HitTestRequest::kReadOnly); | 
|  | 119   HitTestResult result(request, v_point); | 
|  | 120   doc->GetLayoutViewItem().HitTest(result); | 
|  | 121 | 
|  | 122   Node* node = result.InnerNode(); | 
|  | 123   // Wheel events should not dispatch to text nodes. | 
|  | 124   if (node && node->IsTextNode()) | 
|  | 125     node = FlatTreeTraversal::Parent(*node); | 
|  | 126 | 
|  | 127   // If we're over the frame scrollbar, scroll the document. | 
|  | 128   if (!node && result.GetScrollbar()) | 
|  | 129     node = doc->documentElement(); | 
|  | 130 | 
|  | 131   return node; | 
|  | 132 } | 
|  | 133 | 
| 88 }  // namespace blink | 134 }  // namespace blink | 
| OLD | NEW | 
|---|