OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "ui/events/gesture_detection/gesture_provider.h" | 5 #include "ui/events/gesture_detection/gesture_provider.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 | 8 |
9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
69 GestureEventDetails tap_details(type, 1, 0); | 69 GestureEventDetails tap_details(type, 1, 0); |
70 tap_details.set_bounding_box( | 70 tap_details.set_bounding_box( |
71 gfx::RectF(event.GetTouchMajor(), event.GetTouchMajor())); | 71 gfx::RectF(event.GetTouchMajor(), event.GetTouchMajor())); |
72 return tap_details; | 72 return tap_details; |
73 } | 73 } |
74 | 74 |
75 } // namespace | 75 } // namespace |
76 | 76 |
77 // GestureProvider:::Config | 77 // GestureProvider:::Config |
78 | 78 |
79 GestureProvider::Config::Config() : disable_click_delay(false) {} | 79 GestureProvider::Config::Config() |
80 : disable_click_delay(false), gesture_begin_end_types_enabled(false) {} | |
80 | 81 |
81 GestureProvider::Config::~Config() {} | 82 GestureProvider::Config::~Config() {} |
82 | 83 |
83 // GestureProvider::ScaleGestureListener | 84 // GestureProvider::ScaleGestureListener |
84 | 85 |
85 class GestureProvider::ScaleGestureListenerImpl | 86 class GestureProvider::ScaleGestureListenerImpl |
86 : public ScaleGestureDetector::ScaleGestureListener { | 87 : public ScaleGestureDetector::ScaleGestureListener { |
87 public: | 88 public: |
88 ScaleGestureListenerImpl(const ScaleGestureDetector::Config& config, | 89 ScaleGestureListenerImpl(const ScaleGestureDetector::Config& config, |
89 GestureProvider* provider) | 90 GestureProvider* provider) |
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
597 }; | 598 }; |
598 | 599 |
599 // GestureProvider | 600 // GestureProvider |
600 | 601 |
601 GestureProvider::GestureProvider(const Config& config, | 602 GestureProvider::GestureProvider(const Config& config, |
602 GestureProviderClient* client) | 603 GestureProviderClient* client) |
603 : client_(client), | 604 : client_(client), |
604 needs_show_press_event_(false), | 605 needs_show_press_event_(false), |
605 needs_tap_ending_event_(false), | 606 needs_tap_ending_event_(false), |
606 touch_scroll_in_progress_(false), | 607 touch_scroll_in_progress_(false), |
607 pinch_in_progress_(false) { | 608 pinch_in_progress_(false), |
609 gesture_begin_end_types_enabled_(false) { | |
jdduke (slow)
2014/04/03 22:03:28
gesture_begin_end_types_enabled_(config.gesture_be
tdresser
2014/04/04 16:39:31
Done.
| |
608 DCHECK(client); | 610 DCHECK(client); |
609 InitGestureDetectors(config); | 611 InitGestureDetectors(config); |
610 } | 612 } |
611 | 613 |
612 GestureProvider::~GestureProvider() {} | 614 GestureProvider::~GestureProvider() {} |
613 | 615 |
614 bool GestureProvider::OnTouchEvent(const MotionEvent& event) { | 616 bool GestureProvider::OnTouchEvent(const MotionEvent& event) { |
615 TRACE_EVENT1("input", "GestureProvider::OnTouchEvent", | 617 TRACE_EVENT1("input", "GestureProvider::OnTouchEvent", |
616 "action", GetMotionEventActionName(event.GetAction())); | 618 "action", GetMotionEventActionName(event.GetAction())); |
617 if (!CanHandle(event)) | 619 if (!CanHandle(event)) |
618 return false; | 620 return false; |
619 | 621 |
620 const bool was_touch_scrolling_ = touch_scroll_in_progress_; | 622 OnTouchEventHandlingBegin(event); |
623 | |
624 const bool was_touch_scrolling = touch_scroll_in_progress_; | |
621 const bool in_scale_gesture = | 625 const bool in_scale_gesture = |
622 scale_gesture_listener_->IsScaleGestureDetectionInProgress(); | 626 scale_gesture_listener_->IsScaleGestureDetectionInProgress(); |
623 | 627 |
624 if (event.GetAction() == MotionEvent::ACTION_DOWN) { | |
625 current_down_event_ = event.Clone(); | |
626 touch_scroll_in_progress_ = false; | |
627 needs_show_press_event_ = true; | |
628 current_longpress_time_ = base::TimeTicks(); | |
629 SendTapCancelIfNecessary(event); | |
630 } | |
631 | 628 |
632 bool handled = gesture_listener_->OnTouchEvent(event, in_scale_gesture); | 629 bool handled = gesture_listener_->OnTouchEvent(event, in_scale_gesture); |
jdduke (slow)
2014/04/03 22:03:28
I guess we'll no longer need the |handled| variabl
tdresser
2014/04/04 16:39:31
Done.
| |
633 handled |= scale_gesture_listener_->OnTouchEvent(event); | 630 handled |= scale_gesture_listener_->OnTouchEvent(event); |
634 | 631 |
635 if (event.GetAction() == MotionEvent::ACTION_UP || | 632 OnTouchEventHandlingEnd(event, handled, was_touch_scrolling); |
636 event.GetAction() == MotionEvent::ACTION_CANCEL) { | |
637 // "Last finger raised" could be an end to movement, but it should | |
638 // only terminate scrolling if the event did not cause a fling. | |
639 if (was_touch_scrolling_ && !handled) | |
640 EndTouchScrollIfNecessary(event.GetEventTime(), true); | |
641 | |
642 // We shouldn't necessarily cancel a tap on ACTION_UP, as the double-tap | |
643 // timeout may yet trigger a SINGLE_TAP. | |
644 if (event.GetAction() == MotionEvent::ACTION_CANCEL) | |
645 SendTapCancelIfNecessary(event); | |
646 | |
647 current_down_event_.reset(); | |
648 } | |
649 | 633 |
650 return true; | 634 return true; |
651 } | 635 } |
652 | 636 |
653 void GestureProvider::ResetGestureDetectors() { | 637 void GestureProvider::ResetGestureDetectors() { |
654 if (!current_down_event_) | 638 if (!current_down_event_) |
655 return; | 639 return; |
656 scoped_ptr<MotionEvent> cancel_event = current_down_event_->Cancel(); | 640 scoped_ptr<MotionEvent> cancel_event = current_down_event_->Cancel(); |
657 gesture_listener_->OnTouchEvent(*cancel_event, false); | 641 gesture_listener_->OnTouchEvent(*cancel_event, false); |
658 scale_gesture_listener_->OnTouchEvent(*cancel_event); | 642 scale_gesture_listener_->OnTouchEvent(*cancel_event); |
659 } | 643 } |
660 | 644 |
661 void GestureProvider::SetMultiTouchSupportEnabled(bool enabled) { | 645 void GestureProvider::SetMultiTouchSupportEnabled(bool enabled) { |
662 scale_gesture_listener_->set_ignore_detector_events(!enabled); | 646 scale_gesture_listener_->set_ignore_detector_events(!enabled); |
663 } | 647 } |
664 | 648 |
665 void GestureProvider::SetDoubleTapSupportForPlatformEnabled(bool enabled) { | 649 void GestureProvider::SetDoubleTapSupportForPlatformEnabled(bool enabled) { |
666 gesture_listener_->SetDoubleTapSupportForPlatformEnabled(enabled); | 650 gesture_listener_->SetDoubleTapSupportForPlatformEnabled(enabled); |
667 } | 651 } |
668 | 652 |
669 void GestureProvider::SetDoubleTapSupportForPageEnabled(bool enabled) { | 653 void GestureProvider::SetDoubleTapSupportForPageEnabled(bool enabled) { |
670 gesture_listener_->SetDoubleTapSupportForPageEnabled(enabled); | 654 gesture_listener_->SetDoubleTapSupportForPageEnabled(enabled); |
671 } | 655 } |
672 | 656 |
657 void GestureProvider::SetBeginEndTypesEnabled(bool enabled) { | |
658 gesture_begin_end_types_enabled_ = enabled; | |
659 } | |
660 | |
673 bool GestureProvider::IsScrollInProgress() const { | 661 bool GestureProvider::IsScrollInProgress() const { |
674 // TODO(wangxianzhu): Also return true when fling is active once the UI knows | 662 // TODO(wangxianzhu): Also return true when fling is active once the UI knows |
675 // exactly when the fling ends. | 663 // exactly when the fling ends. |
676 return touch_scroll_in_progress_; | 664 return touch_scroll_in_progress_; |
677 } | 665 } |
678 | 666 |
679 bool GestureProvider::IsPinchInProgress() const { return pinch_in_progress_; } | 667 bool GestureProvider::IsPinchInProgress() const { return pinch_in_progress_; } |
680 | 668 |
681 bool GestureProvider::IsDoubleTapInProgress() const { | 669 bool GestureProvider::IsDoubleTapInProgress() const { |
682 return gesture_listener_->IsDoubleTapInProgress(); | 670 return gesture_listener_->IsDoubleTapInProgress(); |
683 } | 671 } |
684 | 672 |
685 bool GestureProvider::IsClickDelayDisabled() const { | 673 bool GestureProvider::IsClickDelayDisabled() const { |
686 return gesture_listener_->IsClickDelayDisabled(); | 674 return gesture_listener_->IsClickDelayDisabled(); |
687 } | 675 } |
688 | 676 |
689 void GestureProvider::InitGestureDetectors(const Config& config) { | 677 void GestureProvider::InitGestureDetectors(const Config& config) { |
690 TRACE_EVENT0("input", "GestureProvider::InitGestureDetectors"); | 678 TRACE_EVENT0("input", "GestureProvider::InitGestureDetectors"); |
691 gesture_listener_.reset( | 679 gesture_listener_.reset( |
692 new GestureListenerImpl(config.gesture_detector_config, | 680 new GestureListenerImpl(config.gesture_detector_config, |
693 config.snap_scroll_controller_config, | 681 config.snap_scroll_controller_config, |
694 config.disable_click_delay, | 682 config.disable_click_delay, |
695 this)); | 683 this)); |
696 | 684 |
697 scale_gesture_listener_.reset( | 685 scale_gesture_listener_.reset( |
698 new ScaleGestureListenerImpl(config.scale_gesture_detector_config, this)); | 686 new ScaleGestureListenerImpl(config.scale_gesture_detector_config, this)); |
687 gesture_begin_end_types_enabled_ = config.gesture_begin_end_types_enabled; | |
699 } | 688 } |
700 | 689 |
701 bool GestureProvider::CanHandle(const MotionEvent& event) const { | 690 bool GestureProvider::CanHandle(const MotionEvent& event) const { |
702 return event.GetAction() == MotionEvent::ACTION_DOWN || current_down_event_; | 691 return event.GetAction() == MotionEvent::ACTION_DOWN || current_down_event_; |
703 } | 692 } |
704 | 693 |
705 void GestureProvider::Fling(base::TimeTicks time, | 694 void GestureProvider::Fling(base::TimeTicks time, |
706 float x, | 695 float x, |
707 float y, | 696 float y, |
708 float velocity_x, | 697 float velocity_x, |
(...skipping 18 matching lines...) Expand all Loading... | |
727 ET_SCROLL_FLING_START, velocity_x, velocity_y); | 716 ET_SCROLL_FLING_START, velocity_x, velocity_y); |
728 Send(CreateGesture(ET_SCROLL_FLING_START, time, x, y, fling_details)); | 717 Send(CreateGesture(ET_SCROLL_FLING_START, time, x, y, fling_details)); |
729 } | 718 } |
730 | 719 |
731 void GestureProvider::Send(const GestureEventData& gesture) { | 720 void GestureProvider::Send(const GestureEventData& gesture) { |
732 DCHECK(!gesture.time.is_null()); | 721 DCHECK(!gesture.time.is_null()); |
733 // The only valid events that should be sent without an active touch sequence | 722 // The only valid events that should be sent without an active touch sequence |
734 // are SHOW_PRESS and TAP, potentially triggered by the double-tap | 723 // are SHOW_PRESS and TAP, potentially triggered by the double-tap |
735 // delay timing out. | 724 // delay timing out. |
736 DCHECK(current_down_event_ || gesture.type == ET_GESTURE_TAP || | 725 DCHECK(current_down_event_ || gesture.type == ET_GESTURE_TAP || |
737 gesture.type == ET_GESTURE_SHOW_PRESS); | 726 gesture.type == ET_GESTURE_SHOW_PRESS || |
727 gesture.type == ET_GESTURE_BEGIN || gesture.type == ET_GESTURE_END); | |
jdduke (slow)
2014/04/03 22:03:28
If we send GESTURE_END before resetting the down e
tdresser
2014/04/04 16:39:31
Done.
| |
738 | 728 |
739 switch (gesture.type) { | 729 switch (gesture.type) { |
740 case ET_GESTURE_TAP_DOWN: | 730 case ET_GESTURE_TAP_DOWN: |
741 needs_tap_ending_event_ = true; | 731 needs_tap_ending_event_ = true; |
742 break; | 732 break; |
743 case ET_GESTURE_TAP_UNCONFIRMED: | 733 case ET_GESTURE_TAP_UNCONFIRMED: |
744 needs_show_press_event_ = false; | 734 needs_show_press_event_ = false; |
745 break; | 735 break; |
746 case ET_GESTURE_TAP: | 736 case ET_GESTURE_TAP: |
747 if (needs_show_press_event_) | 737 if (needs_show_press_event_) |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
811 | 801 |
812 void GestureProvider::EndTouchScrollIfNecessary(base::TimeTicks time, | 802 void GestureProvider::EndTouchScrollIfNecessary(base::TimeTicks time, |
813 bool send_scroll_end_event) { | 803 bool send_scroll_end_event) { |
814 if (!touch_scroll_in_progress_) | 804 if (!touch_scroll_in_progress_) |
815 return; | 805 return; |
816 touch_scroll_in_progress_ = false; | 806 touch_scroll_in_progress_ = false; |
817 if (send_scroll_end_event) | 807 if (send_scroll_end_event) |
818 Send(CreateGesture(ET_GESTURE_SCROLL_END, time, 0, 0)); | 808 Send(CreateGesture(ET_GESTURE_SCROLL_END, time, 0, 0)); |
819 } | 809 } |
820 | 810 |
811 void GestureProvider::OnTouchEventHandlingBegin(const MotionEvent& event) { | |
812 switch (event.GetAction()) { | |
813 case MotionEvent::ACTION_DOWN: | |
814 current_down_event_ = event.Clone(); | |
815 touch_scroll_in_progress_ = false; | |
816 needs_show_press_event_ = true; | |
jdduke (slow)
2014/04/03 22:03:28
Hmm, this show press assignment looks funky (prett
tdresser
2014/04/04 16:39:31
Done.
| |
817 current_longpress_time_ = base::TimeTicks(); | |
818 SendTapCancelIfNecessary(event); | |
819 if (gesture_begin_end_types_enabled_) | |
820 Send(CreateGesture(ET_GESTURE_BEGIN, event)); | |
821 break; | |
822 case MotionEvent::ACTION_POINTER_DOWN: | |
823 if (gesture_begin_end_types_enabled_) | |
824 Send(CreateGesture(ET_GESTURE_BEGIN, event)); | |
825 break; | |
826 case MotionEvent::ACTION_POINTER_UP: | |
827 case MotionEvent::ACTION_UP: | |
828 case MotionEvent::ACTION_CANCEL: | |
829 case MotionEvent::ACTION_MOVE: | |
830 break; | |
831 } | |
832 } | |
833 | |
834 void GestureProvider::OnTouchEventHandlingEnd( | |
835 const MotionEvent& event, bool handled, bool was_touch_scrolling) { | |
836 switch (event.GetAction()) { | |
837 case MotionEvent::ACTION_UP: | |
838 case MotionEvent::ACTION_CANCEL: | |
839 // "Last finger raised" could be an end to movement, but it should | |
840 // only terminate scrolling if the event did not cause a fling. | |
841 if (was_touch_scrolling && !handled) | |
842 EndTouchScrollIfNecessary(event.GetEventTime(), true); | |
jdduke (slow)
2014/04/03 22:03:28
This will probably fail during rebase after https:
tdresser
2014/04/04 16:39:31
Done.
| |
843 | |
844 // We shouldn't necessarily cancel a tap on ACTION_UP, as the double-tap | |
845 // timeout may yet trigger a SINGLE_TAP. | |
846 if (event.GetAction() == MotionEvent::ACTION_CANCEL) | |
847 SendTapCancelIfNecessary(event); | |
848 | |
849 current_down_event_.reset(); | |
850 if (gesture_begin_end_types_enabled_) | |
jdduke (slow)
2014/04/03 22:03:28
This should come before resetting the down event (
tdresser
2014/04/04 16:39:31
Done.
| |
851 Send(CreateGesture(ET_GESTURE_END, event)); | |
852 break; | |
853 case MotionEvent::ACTION_POINTER_UP: | |
854 if (gesture_begin_end_types_enabled_) | |
855 Send(CreateGesture(ET_GESTURE_END, event)); | |
856 break; | |
857 case MotionEvent::ACTION_DOWN: | |
858 case MotionEvent::ACTION_POINTER_DOWN: | |
859 case MotionEvent::ACTION_MOVE: | |
860 break; | |
861 } | |
862 } | |
863 | |
821 } // namespace ui | 864 } // namespace ui |
OLD | NEW |