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/loader/EmptyClients.h" | 15 #include "core/loader/EmptyClients.h" |
16 #include "core/page/AutoscrollController.h" | 16 #include "core/page/AutoscrollController.h" |
17 #include "core/page/Page.h" | 17 #include "core/page/Page.h" |
18 #include "core/testing/DummyPageHolder.h" | 18 #include "core/testing/DummyPageHolder.h" |
19 #include "platform/scroll/MainThreadScrollingReason.h" | |
20 #include "platform/testing/HistogramTester.h" | |
19 #include "testing/gtest/include/gtest/gtest.h" | 21 #include "testing/gtest/include/gtest/gtest.h" |
20 | 22 |
21 namespace blink { | 23 namespace blink { |
22 | 24 |
23 class EventHandlerTest : public ::testing::Test { | 25 class EventHandlerTest : public ::testing::Test { |
24 protected: | 26 protected: |
25 void SetUp() override; | 27 void SetUp() override; |
26 | 28 |
27 Page& page() const { return m_dummyPageHolder->page(); } | 29 Page& page() const { return m_dummyPageHolder->page(); } |
28 Document& document() const { return m_dummyPageHolder->document(); } | 30 Document& document() const { return m_dummyPageHolder->document(); } |
29 FrameSelection& selection() const { return document().frame()->selection(); } | 31 FrameSelection& selection() const { return document().frame()->selection(); } |
30 | 32 |
31 void setHtmlInnerHTML(const char* htmlContent); | 33 void setHtmlInnerHTML(const char* htmlContent); |
34 int getBucketIndex(uint32_t reason); | |
32 | 35 |
33 protected: | 36 protected: |
34 std::unique_ptr<DummyPageHolder> m_dummyPageHolder; | 37 std::unique_ptr<DummyPageHolder> m_dummyPageHolder; |
35 }; | 38 }; |
36 | 39 |
37 class TapEventBuilder : public WebGestureEvent { | 40 class TapEventBuilder : public WebGestureEvent { |
38 public: | 41 public: |
39 TapEventBuilder(IntPoint position, int tapCount) | 42 TapEventBuilder(IntPoint position, int tapCount) |
40 : WebGestureEvent(WebInputEvent::GestureTap, | 43 : WebGestureEvent(WebInputEvent::GestureTap, |
41 WebInputEvent::NoModifiers, | 44 WebInputEvent::NoModifiers, |
(...skipping 30 matching lines...) Expand all Loading... | |
72 WebInputEvent::NoModifiers, | 75 WebInputEvent::NoModifiers, |
73 TimeTicks::Now().InSeconds()) { | 76 TimeTicks::Now().InSeconds()) { |
74 clickCount = clickCountParam; | 77 clickCount = clickCountParam; |
75 button = buttonParam; | 78 button = buttonParam; |
76 setPositionInWidget(positionParam.x(), positionParam.y()); | 79 setPositionInWidget(positionParam.x(), positionParam.y()); |
77 setPositionInScreen(positionParam.x(), positionParam.y()); | 80 setPositionInScreen(positionParam.x(), positionParam.y()); |
78 m_frameScale = 1; | 81 m_frameScale = 1; |
79 } | 82 } |
80 }; | 83 }; |
81 | 84 |
85 class ScrollBeginEventBuilder : public WebGestureEvent { | |
86 public: | |
87 ScrollBeginEventBuilder(IntPoint position, | |
88 FloatPoint delta, | |
89 WebGestureDevice device) | |
90 : WebGestureEvent() { | |
91 m_type = WebInputEvent::GestureScrollBegin; | |
92 x = globalX = position.x(); | |
93 y = globalY = position.y(); | |
94 data.scrollBegin.deltaYHint = delta.y(); | |
95 sourceDevice = device; | |
96 m_frameScale = 1; | |
97 } | |
98 }; | |
99 | |
100 class ScrollEndEventBuilder : public WebGestureEvent { | |
101 public: | |
102 ScrollEndEventBuilder() : WebGestureEvent() { | |
103 m_type = WebInputEvent::GestureScrollEnd; | |
104 m_frameScale = 1; | |
105 } | |
106 }; | |
107 | |
82 void EventHandlerTest::SetUp() { | 108 void EventHandlerTest::SetUp() { |
83 m_dummyPageHolder = DummyPageHolder::create(IntSize(300, 400)); | 109 m_dummyPageHolder = DummyPageHolder::create(IntSize(300, 400)); |
84 } | 110 } |
85 | 111 |
86 void EventHandlerTest::setHtmlInnerHTML(const char* htmlContent) { | 112 void EventHandlerTest::setHtmlInnerHTML(const char* htmlContent) { |
87 document().documentElement()->setInnerHTML(String::fromUTF8(htmlContent)); | 113 document().documentElement()->setInnerHTML(String::fromUTF8(htmlContent)); |
88 document().view()->updateAllLifecyclePhases(); | 114 document().view()->updateAllLifecyclePhases(); |
89 } | 115 } |
90 | 116 |
117 int EventHandlerTest::getBucketIndex(uint32_t reason) { | |
118 if (reason & (reason - 1)) | |
bokan
2017/04/07 21:05:57
I had to google what this does. A clearer way to e
yigu
2017/04/10 20:39:04
Done.
| |
119 return -1; | |
120 int index = 0; | |
121 while (reason > 0) { | |
122 reason >>= 1; | |
123 ++index; | |
124 } | |
125 return index; | |
126 } | |
127 | |
91 TEST_F(EventHandlerTest, dragSelectionAfterScroll) { | 128 TEST_F(EventHandlerTest, dragSelectionAfterScroll) { |
92 setHtmlInnerHTML( | 129 setHtmlInnerHTML( |
93 "<style> body { margin: 0px; } .upper { width: 300px; height: 400px; }" | 130 "<style> body { margin: 0px; } .upper { width: 300px; height: 400px; }" |
94 ".lower { margin: 0px; width: 300px; height: 400px; } .line { display: " | 131 ".lower { margin: 0px; width: 300px; height: 400px; } .line { display: " |
95 "block; width: 300px; height: 30px; } </style>" | 132 "block; width: 300px; height: 30px; } </style>" |
96 "<div class='upper'></div>" | 133 "<div class='upper'></div>" |
97 "<div class='lower'>" | 134 "<div class='lower'>" |
98 "<span class='line'>Line 1</span><span class='line'>Line 2</span><span " | 135 "<span class='line'>Line 1</span><span class='line'>Line 2</span><span " |
99 "class='line'>Line 3</span><span class='line'>Line 4</span><span " | 136 "class='line'>Line 3</span><span class='line'>Line 4</span><span " |
100 "class='line'>Line 5</span>" | 137 "class='line'>Line 5</span>" |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
454 WebInputEvent::MouseUp, WebFloatPoint(100, 50), WebFloatPoint(200, 250), | 491 WebInputEvent::MouseUp, WebFloatPoint(100, 50), WebFloatPoint(200, 250), |
455 WebPointerProperties::Button::Left, 1, WebInputEvent::NoModifiers, | 492 WebPointerProperties::Button::Left, 1, WebInputEvent::NoModifiers, |
456 TimeTicks::Now().InSeconds()); | 493 TimeTicks::Now().InSeconds()); |
457 mouseUpEvent.setFrameScale(1); | 494 mouseUpEvent.setFrameScale(1); |
458 document().frame()->eventHandler().dragSourceEndedAt(mouseUpEvent, | 495 document().frame()->eventHandler().dragSourceEndedAt(mouseUpEvent, |
459 DragOperationNone); | 496 DragOperationNone); |
460 | 497 |
461 // This test passes if it doesn't crash. | 498 // This test passes if it doesn't crash. |
462 } | 499 } |
463 | 500 |
501 TEST_F(EventHandlerTest, NonCompositedMainThreadScrollingReasonTest) { | |
502 setHtmlInnerHTML( | |
503 "<style>" | |
504 " .box { overflow:scroll; width: 100px; height: 100px; }" | |
505 " .translucent { opacity: 0.5; }" | |
506 " .spacer { height: 1000px; }" | |
507 "</style>" | |
508 "<div id='box' class='translucent box'>" | |
509 " <div class='spacer'></div>" | |
510 "</div>"); | |
511 | |
512 document().view()->updateAllLifecyclePhases(); | |
513 | |
514 HistogramTester histogramTester; | |
515 | |
516 // Test touch scroll. | |
517 ScrollBeginEventBuilder touchScrollBegin( | |
518 IntPoint(50, 50), FloatPoint(0.f, 1.f), WebGestureDeviceTouchscreen); | |
519 ScrollEndEventBuilder touchScrollEnd; | |
520 document().frame()->eventHandler().handleGestureEvent(touchScrollBegin); | |
521 document().frame()->eventHandler().handleGestureEvent(touchScrollEnd); | |
522 histogramTester.expectBucketCount( | |
523 "Renderer4.MainThreadGestureScrollReason", | |
524 getBucketIndex(MainThreadScrollingReason::kHasOpacityAndLCDText), 1); | |
525 | |
526 document().frame()->eventHandler().handleGestureEvent(touchScrollBegin); | |
527 document().frame()->eventHandler().handleGestureEvent(touchScrollEnd); | |
bokan
2017/04/07 21:05:56
I'd throw two GestureScrollUpdates between this, j
yigu
2017/04/10 20:39:05
Done.
| |
528 histogramTester.expectBucketCount( | |
529 "Renderer4.MainThreadGestureScrollReason", | |
530 getBucketIndex(MainThreadScrollingReason::kHasOpacityAndLCDText), 2); | |
531 | |
532 // Test wheel scroll. | |
533 ScrollBeginEventBuilder wheelScrollBegin( | |
534 IntPoint(50, 50), FloatPoint(0.f, 1.f), WebGestureDeviceTouchpad); | |
535 ScrollEndEventBuilder wheelScrollEnd; | |
536 document().frame()->eventHandler().handleGestureEvent(wheelScrollBegin); | |
537 document().frame()->eventHandler().handleGestureEvent(wheelScrollEnd); | |
538 histogramTester.expectBucketCount( | |
539 "Renderer4.MainThreadWheelScrollReason", | |
bokan
2017/04/07 21:05:57
You can improve readability of your expectations w
yigu
2017/04/10 20:39:05
It looks MUCH better with this improvement. Thanks
| |
540 getBucketIndex(MainThreadScrollingReason::kHasOpacityAndLCDText), 1); | |
541 histogramTester.expectBucketCount( | |
542 "Renderer4.MainThreadWheelScrollReason", | |
543 getBucketIndex( | |
544 MainThreadScrollingReason::kBackgroundNotOpaqueInRectAndLCDText), | |
bokan
2017/04/07 21:05:57
Why do we get this reason for touch but not wheel?
yigu
2017/04/10 20:39:05
Done.
| |
545 1); | |
546 histogramTester.expectTotalCount("Renderer4.MainThreadWheelScrollReason", 2); | |
547 } | |
548 | |
549 TEST_F(EventHandlerTest, | |
550 NonCompositedMainThreadScrollingReasonWithCompositedScrollableAreaTest) { | |
551 setHtmlInnerHTML( | |
552 "<style>" | |
553 " .box { overflow:scroll; width: 100px; height: 100px; }" | |
554 " .translucent { opacity: 0.5; }" | |
555 " .composited { will-change: transform; }" | |
556 " .spacer { height: 1000px; }" | |
557 "</style>" | |
558 "<div id='box' class='translucent box'>" | |
559 " <div class='spacer'></div>" | |
560 "</div>"); | |
561 | |
562 page().settings().setAcceleratedCompositingEnabled(true); | |
563 document().view()->setParentVisible(true); | |
bokan
2017/04/07 21:05:57
Why is setParentVisible and setSelfVisible needed?
yigu
2017/04/10 20:39:05
We have to use these to make sure the test box get
| |
564 document().view()->setSelfVisible(true); | |
565 document().view()->updateAllLifecyclePhases(); | |
566 | |
567 HistogramTester histogramTester; | |
568 | |
569 ScrollBeginEventBuilder wheelScrollBegin( | |
570 IntPoint(50, 50), FloatPoint(0.f, 1.f), WebGestureDeviceTouchpad); | |
571 ScrollEndEventBuilder wheelScrollEnd; | |
572 document().frame()->eventHandler().handleGestureEvent(wheelScrollBegin); | |
573 document().frame()->eventHandler().handleGestureEvent(wheelScrollEnd); | |
bokan
2017/04/07 21:05:57
Another way to make this more readable is to wrap
yigu
2017/04/10 20:39:05
Done.
| |
574 histogramTester.expectBucketCount( | |
575 "Renderer4.MainThreadWheelScrollReason", | |
576 getBucketIndex(MainThreadScrollingReason::kHasOpacityAndLCDText), 1); | |
577 | |
578 Element* box = document().getElementById("box"); | |
579 box->setAttribute("class", "composited translucent box"); | |
580 document().view()->updateAllLifecyclePhases(); | |
581 document().frame()->eventHandler().handleGestureEvent(wheelScrollBegin); | |
582 document().frame()->eventHandler().handleGestureEvent(wheelScrollEnd); | |
bokan
2017/04/07 21:05:57
Lets also EXPECT box's PLSA::getNonCompositedMainT
yigu
2017/04/10 20:39:04
Done.
| |
583 histogramTester.expectBucketCount( | |
584 "Renderer4.MainThreadWheelScrollReason", | |
585 getBucketIndex(MainThreadScrollingReason::kHasOpacityAndLCDText), 1); | |
bokan
2017/04/07 21:05:57
It'd be safer to check that the total count didn't
yigu
2017/04/10 20:39:04
Done.
| |
586 } | |
587 | |
588 TEST_F(EventHandlerTest, | |
589 NonCompositedMainThreadScrollingReasonWithNotScrollableAreaTest) { | |
590 setHtmlInnerHTML( | |
591 "<style>.box { overflow:scroll; width: 100px; height: 100px; }" | |
592 " .translucent { opacity: 0.5; }" | |
593 " .hidden { overflow: hidden; }" | |
594 " .spacer { height: 1000px; }" | |
595 "</style>" | |
596 "<div id='box' class='translucent box'>" | |
597 " <div class='spacer'></div>" | |
598 "</div>"); | |
599 | |
600 document().view()->updateAllLifecyclePhases(); | |
601 | |
602 HistogramTester histogramTester; | |
603 | |
604 ScrollBeginEventBuilder wheelScrollBegin( | |
605 IntPoint(50, 50), FloatPoint(0.f, 1.f), WebGestureDeviceTouchpad); | |
606 ScrollEndEventBuilder wheelScrollEnd; | |
607 document().frame()->eventHandler().handleGestureEvent(wheelScrollBegin); | |
608 document().frame()->eventHandler().handleGestureEvent(wheelScrollEnd); | |
609 histogramTester.expectBucketCount( | |
610 "Renderer4.MainThreadWheelScrollReason", | |
611 getBucketIndex(MainThreadScrollingReason::kHasOpacityAndLCDText), 1); | |
612 | |
613 Element* box = document().getElementById("box"); | |
614 box->setAttribute("class", "hidden translucent box"); | |
615 document().view()->updateAllLifecyclePhases(); | |
616 document().frame()->eventHandler().handleGestureEvent(wheelScrollBegin); | |
617 document().frame()->eventHandler().handleGestureEvent(wheelScrollEnd); | |
618 histogramTester.expectBucketCount( | |
bokan
2017/04/07 21:05:57
Check total count.
yigu
2017/04/10 20:39:05
Done.
| |
619 "Renderer4.MainThreadWheelScrollReason", | |
620 getBucketIndex(MainThreadScrollingReason::kHasOpacityAndLCDText), 1); | |
621 } | |
622 | |
623 TEST_F(EventHandlerTest, | |
624 NonCompositedMainThreadScrollingReasonWithNestedScrollersTest) { | |
625 setHtmlInnerHTML( | |
626 "<style>" | |
627 " .container { overflow:scroll; width: 200px; height: 200px; }" | |
628 " .box { overflow:scroll; width: 100px; height: 100px; }" | |
629 " .translucent { opacity: 0.5; }" | |
630 " .transform { transform: scale(0.8); }" | |
631 " .with-border-radius { border: 5px solid; border-radius: 5px; }" | |
632 " .spacer { height: 1000px; }" | |
633 " .composited { will-change: transform; }" | |
634 "</style>" | |
635 "<div id='container' class='container with-border-radius'>" | |
636 " <div class='translucent box'>" | |
637 " <div class='composited transform box'>" | |
638 " <div class='spacer'></div>" | |
639 " </div>" | |
640 " </div>" | |
641 " <div class='spacer'></div>" | |
642 "</div>"); | |
643 | |
644 page().settings().setAcceleratedCompositingEnabled(true); | |
645 document().view()->setParentVisible(true); | |
646 document().view()->setSelfVisible(true); | |
647 document().view()->updateAllLifecyclePhases(); | |
648 | |
649 HistogramTester histogramTester; | |
650 | |
651 ScrollBeginEventBuilder wheelScrollBegin( | |
652 IntPoint(50, 50), FloatPoint(0.f, 1.f), WebGestureDeviceTouchpad); | |
653 ScrollEndEventBuilder wheelScrollEnd; | |
654 document().frame()->eventHandler().handleGestureEvent(wheelScrollBegin); | |
655 document().frame()->eventHandler().handleGestureEvent(wheelScrollEnd); | |
656 histogramTester.expectBucketCount( | |
bokan
2017/04/07 21:05:57
This test is a little more complex, some comments
yigu
2017/04/10 20:39:05
Done.
| |
657 "Renderer4.MainThreadWheelScrollReason", | |
658 getBucketIndex(MainThreadScrollingReason::kHasOpacityAndLCDText), 1); | |
bokan
2017/04/07 21:05:57
This one comes from "translucent box" right? Isn't
yigu
2017/04/10 20:39:05
It's actually scrollable (see jsbin.com/muluhes).
| |
659 histogramTester.expectBucketCount( | |
660 "Renderer4.MainThreadWheelScrollReason", | |
661 getBucketIndex( | |
662 MainThreadScrollingReason::kBackgroundNotOpaqueInRectAndLCDText), | |
bokan
2017/04/07 21:05:57
This one comes from all of them, right?
yigu
2017/04/10 20:39:05
In this case yes. Usually we set this reason whene
| |
663 1); | |
664 histogramTester.expectBucketCount( | |
665 "Renderer4.MainThreadWheelScrollReason", | |
666 getBucketIndex(MainThreadScrollingReason::kHasBorderRadius), 1); | |
667 histogramTester.expectBucketCount( | |
668 "Renderer4.MainThreadWheelScrollReason", | |
669 getBucketIndex(MainThreadScrollingReason::kHasTransformAndLCDText), 0); | |
670 histogramTester.expectTotalCount("Renderer4.MainThreadWheelScrollReason", 3); | |
671 } | |
672 | |
464 class TooltipCapturingChromeClient : public EmptyChromeClient { | 673 class TooltipCapturingChromeClient : public EmptyChromeClient { |
465 public: | 674 public: |
466 TooltipCapturingChromeClient() {} | 675 TooltipCapturingChromeClient() {} |
467 | 676 |
468 void setToolTip(LocalFrame&, const String& str, TextDirection) override { | 677 void setToolTip(LocalFrame&, const String& str, TextDirection) override { |
469 m_lastToolTip = str; | 678 m_lastToolTip = str; |
470 } | 679 } |
471 | 680 |
472 String& lastToolTip() { return m_lastToolTip; } | 681 String& lastToolTip() { return m_lastToolTip; } |
473 | 682 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
514 WebInputEvent::MouseLeave, WebFloatPoint(0, 0), WebFloatPoint(0, 0), | 723 WebInputEvent::MouseLeave, WebFloatPoint(0, 0), WebFloatPoint(0, 0), |
515 WebPointerProperties::Button::NoButton, 0, WebInputEvent::NoModifiers, | 724 WebPointerProperties::Button::NoButton, 0, WebInputEvent::NoModifiers, |
516 TimeTicks::Now().InSeconds()); | 725 TimeTicks::Now().InSeconds()); |
517 mouseLeaveEvent.setFrameScale(1); | 726 mouseLeaveEvent.setFrameScale(1); |
518 document().frame()->eventHandler().handleMouseLeaveEvent(mouseLeaveEvent); | 727 document().frame()->eventHandler().handleMouseLeaveEvent(mouseLeaveEvent); |
519 | 728 |
520 EXPECT_EQ(WTF::String(), lastToolTip()); | 729 EXPECT_EQ(WTF::String(), lastToolTip()); |
521 } | 730 } |
522 | 731 |
523 } // namespace blink | 732 } // namespace blink |
OLD | NEW |