OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/EventHandler.h" | 5 #include "core/input/EventHandler.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include "core/dom/Document.h" | 8 #include "core/dom/Document.h" |
9 #include "core/dom/Range.h" | 9 #include "core/dom/Range.h" |
10 #include "core/editing/Editor.h" | 10 #include "core/editing/Editor.h" |
11 #include "core/editing/FrameSelection.h" | 11 #include "core/editing/FrameSelection.h" |
12 #include "core/frame/FrameView.h" | 12 #include "core/frame/FrameView.h" |
13 #include "core/frame/LocalFrame.h" | 13 #include "core/frame/LocalFrame.h" |
14 #include "core/frame/Settings.h" | 14 #include "core/frame/Settings.h" |
15 #include "core/layout/LayoutBox.h" | |
15 #include "core/loader/EmptyClients.h" | 16 #include "core/loader/EmptyClients.h" |
16 #include "core/page/AutoscrollController.h" | 17 #include "core/page/AutoscrollController.h" |
17 #include "core/page/Page.h" | 18 #include "core/page/Page.h" |
19 #include "core/paint/PaintLayerScrollableArea.h" | |
18 #include "core/testing/DummyPageHolder.h" | 20 #include "core/testing/DummyPageHolder.h" |
21 #include "platform/scroll/MainThreadScrollingReason.h" | |
22 #include "platform/testing/HistogramTester.h" | |
19 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
20 | 24 |
25 #define EXPECT_WHEEL_BUCKET(reason, count) \ | |
26 histogram_tester.ExpectBucketCount( \ | |
27 "Renderer4.MainThreadWheelScrollReason", \ | |
28 GetBucketIndex(MainThreadScrollingReason::reason), count); | |
29 | |
30 #define EXPECT_TOUCH_BUCKET(reason, count) \ | |
31 histogram_tester.ExpectBucketCount( \ | |
32 "Renderer4.MainThreadGestureScrollReason", \ | |
33 GetBucketIndex(MainThreadScrollingReason::reason), count); | |
34 | |
35 #define EXPECT_WHEEL_TOTAL(count) \ | |
36 histogram_tester.ExpectTotalCount("Renderer4.MainThreadWheelScrollReason", \ | |
37 count); | |
38 | |
39 #define EXPECT_TOUCH_TOTAL(count) \ | |
40 histogram_tester.ExpectTotalCount("Renderer4.MainThreadGestureScrollReason", \ | |
41 count); | |
42 | |
21 namespace blink { | 43 namespace blink { |
22 | 44 |
23 class EventHandlerTest : public ::testing::Test { | 45 class EventHandlerTest : public ::testing::Test { |
24 protected: | 46 protected: |
25 void SetUp() override; | 47 void SetUp() override; |
26 | 48 |
27 Page& GetPage() const { return dummy_page_holder_->GetPage(); } | 49 Page& GetPage() const { return dummy_page_holder_->GetPage(); } |
28 Document& GetDocument() const { return dummy_page_holder_->GetDocument(); } | 50 Document& GetDocument() const { return dummy_page_holder_->GetDocument(); } |
29 FrameSelection& Selection() const { | 51 FrameSelection& Selection() const { |
30 return GetDocument().GetFrame()->Selection(); | 52 return GetDocument().GetFrame()->Selection(); |
31 } | 53 } |
32 | 54 |
33 void SetHtmlInnerHTML(const char* html_content); | 55 void SetHtmlInnerHTML(const char* html_content); |
34 | 56 |
35 protected: | 57 protected: |
36 std::unique_ptr<DummyPageHolder> dummy_page_holder_; | 58 std::unique_ptr<DummyPageHolder> dummy_page_holder_; |
37 }; | 59 }; |
38 | 60 |
61 class NonCompositedMainThreadScrollingReasonRecordTest | |
62 : public EventHandlerTest { | |
63 protected: | |
64 class ScrollBeginEventBuilder : public WebGestureEvent { | |
65 public: | |
66 ScrollBeginEventBuilder(IntPoint position, | |
67 FloatPoint delta, | |
68 WebGestureDevice device) | |
69 : WebGestureEvent() { | |
70 type_ = WebInputEvent::kGestureScrollBegin; | |
71 x = global_x = position.X(); | |
72 y = global_y = position.Y(); | |
73 data.scroll_begin.delta_y_hint = delta.Y(); | |
74 source_device = device; | |
75 frame_scale_ = 1; | |
76 } | |
77 }; | |
78 | |
79 class ScrollUpdateEventBuilder : public WebGestureEvent { | |
80 public: | |
81 ScrollUpdateEventBuilder() : WebGestureEvent() { | |
82 type_ = WebInputEvent::kGestureScrollUpdate; | |
83 data.scroll_update.delta_x = 0.0f; | |
84 data.scroll_update.delta_y = 1.0f; | |
85 data.scroll_update.velocity_x = 0; | |
86 data.scroll_update.velocity_y = 1; | |
87 frame_scale_ = 1; | |
88 } | |
89 }; | |
90 | |
91 class ScrollEndEventBuilder : public WebGestureEvent { | |
92 public: | |
93 ScrollEndEventBuilder() : WebGestureEvent() { | |
94 type_ = WebInputEvent::kGestureScrollEnd; | |
95 frame_scale_ = 1; | |
96 } | |
97 }; | |
98 | |
99 int GetBucketIndex(uint32_t reason); | |
100 void Scroll(const Element*, | |
101 const WebGestureDevice = kWebGestureDeviceTouchpad); | |
bokan
2017/04/11 17:30:52
No default param. It should be clear at the call s
yigu
2017/04/11 21:28:10
Done.
| |
102 }; | |
103 | |
39 class TapEventBuilder : public WebGestureEvent { | 104 class TapEventBuilder : public WebGestureEvent { |
40 public: | 105 public: |
41 TapEventBuilder(IntPoint position, int tap_count) | 106 TapEventBuilder(IntPoint position, int tap_count) |
42 : WebGestureEvent(WebInputEvent::kGestureTap, | 107 : WebGestureEvent(WebInputEvent::kGestureTap, |
43 WebInputEvent::kNoModifiers, | 108 WebInputEvent::kNoModifiers, |
44 TimeTicks::Now().InSeconds()) { | 109 TimeTicks::Now().InSeconds()) { |
45 x = global_x = position.X(); | 110 x = global_x = position.X(); |
46 y = global_y = position.Y(); | 111 y = global_y = position.Y(); |
47 source_device = kWebGestureDeviceTouchscreen; | 112 source_device = kWebGestureDeviceTouchscreen; |
48 data.tap.tap_count = tap_count; | 113 data.tap.tap_count = tap_count; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
83 | 148 |
84 void EventHandlerTest::SetUp() { | 149 void EventHandlerTest::SetUp() { |
85 dummy_page_holder_ = DummyPageHolder::Create(IntSize(300, 400)); | 150 dummy_page_holder_ = DummyPageHolder::Create(IntSize(300, 400)); |
86 } | 151 } |
87 | 152 |
88 void EventHandlerTest::SetHtmlInnerHTML(const char* html_content) { | 153 void EventHandlerTest::SetHtmlInnerHTML(const char* html_content) { |
89 GetDocument().documentElement()->setInnerHTML(String::FromUTF8(html_content)); | 154 GetDocument().documentElement()->setInnerHTML(String::FromUTF8(html_content)); |
90 GetDocument().View()->UpdateAllLifecyclePhases(); | 155 GetDocument().View()->UpdateAllLifecyclePhases(); |
91 } | 156 } |
92 | 157 |
158 int NonCompositedMainThreadScrollingReasonRecordTest::GetBucketIndex( | |
159 uint32_t reason) { | |
160 int index = 1; | |
161 while (!(reason & 1)) { | |
162 reason >>= 1; | |
163 ++index; | |
164 } | |
165 DCHECK_EQ(reason, 1u); | |
166 return index; | |
167 } | |
168 | |
169 void NonCompositedMainThreadScrollingReasonRecordTest::Scroll( | |
170 const Element* element, | |
171 const WebGestureDevice device) { | |
172 DCHECK(element); | |
173 DCHECK(element->GetLayoutBox()); | |
174 LayoutBox* box = element->GetLayoutBox(); | |
175 ScrollBeginEventBuilder scroll_begin( | |
176 IntPoint(box->Location().X().ToInt() + box->size().Width().ToInt() / 2, | |
bokan
2017/04/11 17:30:52
Location() is relative to its container, which is
yigu
2017/04/11 21:28:10
Done.
| |
177 box->Location().Y().ToInt() + box->size().Height().ToInt() / 2), | |
178 FloatPoint(0.f, 1.f), device); | |
179 ScrollUpdateEventBuilder scroll_update; | |
180 ScrollEndEventBuilder scroll_end; | |
181 GetDocument().GetFrame()->GetEventHandler().HandleGestureEvent(scroll_begin); | |
182 GetDocument().GetFrame()->GetEventHandler().HandleGestureEvent(scroll_update); | |
183 GetDocument().GetFrame()->GetEventHandler().HandleGestureEvent(scroll_end); | |
184 } | |
185 | |
93 TEST_F(EventHandlerTest, dragSelectionAfterScroll) { | 186 TEST_F(EventHandlerTest, dragSelectionAfterScroll) { |
94 SetHtmlInnerHTML( | 187 SetHtmlInnerHTML( |
95 "<style> body { margin: 0px; } .upper { width: 300px; height: 400px; }" | 188 "<style> body { margin: 0px; } .upper { width: 300px; height: 400px; }" |
96 ".lower { margin: 0px; width: 300px; height: 400px; } .line { display: " | 189 ".lower { margin: 0px; width: 300px; height: 400px; } .line { display: " |
97 "block; width: 300px; height: 30px; } </style>" | 190 "block; width: 300px; height: 30px; } </style>" |
98 "<div class='upper'></div>" | 191 "<div class='upper'></div>" |
99 "<div class='lower'>" | 192 "<div class='lower'>" |
100 "<span class='line'>Line 1</span><span class='line'>Line 2</span><span " | 193 "<span class='line'>Line 1</span><span class='line'>Line 2</span><span " |
101 "class='line'>Line 3</span><span class='line'>Line 4</span><span " | 194 "class='line'>Line 3</span><span class='line'>Line 4</span><span " |
102 "class='line'>Line 5</span>" | 195 "class='line'>Line 5</span>" |
(...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
541 WebInputEvent::kMouseLeave, WebFloatPoint(0, 0), WebFloatPoint(0, 0), | 634 WebInputEvent::kMouseLeave, WebFloatPoint(0, 0), WebFloatPoint(0, 0), |
542 WebPointerProperties::Button::kNoButton, 0, WebInputEvent::kNoModifiers, | 635 WebPointerProperties::Button::kNoButton, 0, WebInputEvent::kNoModifiers, |
543 TimeTicks::Now().InSeconds()); | 636 TimeTicks::Now().InSeconds()); |
544 mouse_leave_event.SetFrameScale(1); | 637 mouse_leave_event.SetFrameScale(1); |
545 GetDocument().GetFrame()->GetEventHandler().HandleMouseLeaveEvent( | 638 GetDocument().GetFrame()->GetEventHandler().HandleMouseLeaveEvent( |
546 mouse_leave_event); | 639 mouse_leave_event); |
547 | 640 |
548 EXPECT_EQ(WTF::String(), LastToolTip()); | 641 EXPECT_EQ(WTF::String(), LastToolTip()); |
549 } | 642 } |
550 | 643 |
644 TEST_F(NonCompositedMainThreadScrollingReasonRecordTest, | |
645 TouchAndWheelGeneralTest) { | |
646 SetHtmlInnerHTML( | |
647 "<style>" | |
648 " .box { overflow:scroll; width: 100px; height: 100px; }" | |
649 " .translucent { opacity: 0.5; }" | |
650 " .spacer { height: 1000px; }" | |
651 "</style>" | |
652 "<div id='box' class='translucent box'>" | |
653 " <div class='spacer'></div>" | |
654 "</div>"); | |
655 | |
656 GetDocument().View()->UpdateAllLifecyclePhases(); | |
657 | |
658 Element* box = GetDocument().getElementById("box"); | |
659 HistogramTester histogram_tester; | |
660 | |
661 // Test touch scroll. | |
662 Scroll(box, kWebGestureDeviceTouchscreen); | |
663 EXPECT_TOUCH_BUCKET(kHasOpacityAndLCDText, 1); | |
664 EXPECT_TOUCH_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 1); | |
665 | |
666 Scroll(box, kWebGestureDeviceTouchscreen); | |
667 EXPECT_TOUCH_BUCKET(kHasOpacityAndLCDText, 2); | |
668 EXPECT_TOUCH_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 2); | |
669 EXPECT_TOUCH_TOTAL(4); | |
670 | |
671 // Test wheel scroll. | |
672 Scroll(box); | |
673 EXPECT_WHEEL_BUCKET(kHasOpacityAndLCDText, 1); | |
674 EXPECT_WHEEL_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 1); | |
675 EXPECT_WHEEL_TOTAL(2); | |
676 } | |
677 | |
678 TEST_F(NonCompositedMainThreadScrollingReasonRecordTest, | |
679 CompositedScrollableAreaTest) { | |
680 SetHtmlInnerHTML( | |
681 "<style>" | |
682 " .box { overflow:scroll; width: 100px; height: 100px; }" | |
683 " .translucent { opacity: 0.5; }" | |
684 " .composited { will-change: transform; }" | |
685 " .spacer { height: 1000px; }" | |
686 "</style>" | |
687 "<div id='box' class='translucent box'>" | |
688 " <div class='spacer'></div>" | |
689 "</div>"); | |
690 | |
691 GetPage().GetSettings().SetAcceleratedCompositingEnabled(true); | |
692 GetDocument().View()->SetParentVisible(true); | |
693 GetDocument().View()->SetSelfVisible(true); | |
694 GetDocument().View()->UpdateAllLifecyclePhases(); | |
695 | |
696 Element* box = GetDocument().getElementById("box"); | |
697 HistogramTester histogram_tester; | |
698 | |
699 Scroll(box); | |
700 EXPECT_WHEEL_BUCKET(kHasOpacityAndLCDText, 1); | |
701 EXPECT_WHEEL_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 1); | |
702 EXPECT_WHEEL_TOTAL(2); | |
703 | |
704 box->setAttribute("class", "composited translucent box"); | |
705 GetDocument().View()->UpdateAllLifecyclePhases(); | |
706 Scroll(box); | |
707 EXPECT_FALSE(ToLayoutBox(box->GetLayoutObject()) | |
708 ->GetScrollableArea() | |
709 ->GetNonCompositedMainThreadScrollingReasons()); | |
710 EXPECT_WHEEL_BUCKET(kHasOpacityAndLCDText, 1); | |
711 EXPECT_WHEEL_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 1); | |
712 EXPECT_WHEEL_TOTAL(2); | |
713 } | |
714 | |
715 TEST_F(NonCompositedMainThreadScrollingReasonRecordTest, | |
716 NotScrollableAreaTest) { | |
717 SetHtmlInnerHTML( | |
718 "<style>.box { overflow:scroll; width: 100px; height: 100px; }" | |
719 " .translucent { opacity: 0.5; }" | |
720 " .hidden { overflow: hidden; }" | |
721 " .spacer { height: 1000px; }" | |
722 "</style>" | |
723 "<div id='box' class='translucent box'>" | |
724 " <div class='spacer'></div>" | |
725 "</div>"); | |
726 | |
727 GetDocument().View()->UpdateAllLifecyclePhases(); | |
728 | |
729 Element* box = GetDocument().getElementById("box"); | |
730 HistogramTester histogram_tester; | |
731 | |
732 Scroll(box); | |
733 EXPECT_WHEEL_BUCKET(kHasOpacityAndLCDText, 1); | |
734 EXPECT_WHEEL_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 1); | |
735 EXPECT_WHEEL_TOTAL(2); | |
736 | |
737 box->setAttribute("class", "hidden translucent box"); | |
738 GetDocument().View()->UpdateAllLifecyclePhases(); | |
739 Scroll(box); | |
740 EXPECT_WHEEL_BUCKET(kHasOpacityAndLCDText, 1); | |
741 EXPECT_WHEEL_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 1); | |
742 EXPECT_WHEEL_TOTAL(2); | |
743 } | |
744 | |
745 TEST_F(NonCompositedMainThreadScrollingReasonRecordTest, NestedScrollersTest) { | |
746 SetHtmlInnerHTML( | |
747 "<style>" | |
748 " .container { overflow:scroll; width: 200px; height: 200px; }" | |
749 " .box { overflow:scroll; width: 100px; height: 100px; }" | |
750 " .translucent { opacity: 0.5; }" | |
751 " .transform { transform: scale(0.8); }" | |
752 " .with-border-radius { border: 5px solid; border-radius: 5px; }" | |
753 " .spacer { height: 1000px; }" | |
754 " .composited { will-change: transform; }" | |
755 "</style>" | |
756 "<div id='container' class='container with-border-radius'>" | |
757 " <div class='translucent box'>" | |
758 " <div id='inner' class='composited transform box'>" | |
759 " <div class='spacer'></div>" | |
760 " </div>" | |
761 " </div>" | |
762 " <div class='spacer'></div>" | |
763 "</div>"); | |
764 | |
765 GetPage().GetSettings().SetAcceleratedCompositingEnabled(true); | |
766 GetDocument().View()->SetParentVisible(true); | |
767 GetDocument().View()->SetSelfVisible(true); | |
768 GetDocument().View()->UpdateAllLifecyclePhases(); | |
769 | |
770 Element* box = GetDocument().getElementById("inner"); | |
771 HistogramTester histogram_tester; | |
772 | |
773 Scroll(box); | |
774 // Scrolling the inner box will gather reasons from the scrolling chain. The | |
775 // inner box itself has no reason because it's composited. Other scrollable | |
776 // areas from the chain have corresponding reasons. | |
777 EXPECT_WHEEL_BUCKET(kHasOpacityAndLCDText, 1); | |
778 EXPECT_WHEEL_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 1); | |
779 EXPECT_WHEEL_BUCKET(kHasBorderRadius, 1); | |
780 EXPECT_WHEEL_BUCKET(kHasTransformAndLCDText, 0); | |
781 EXPECT_WHEEL_TOTAL(3); | |
782 } | |
783 | |
551 } // namespace blink | 784 } // namespace blink |
OLD | NEW |