1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137

ash / wm / gestures / back_gesture / back_gesture_event_handler.h [blame]

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef ASH_WM_GESTURES_BACK_GESTURE_BACK_GESTURE_EVENT_HANDLER_H_
#define ASH_WM_GESTURES_BACK_GESTURE_BACK_GESTURE_EVENT_HANDLER_H_

#include "ash/wm/gestures/back_gesture/back_gesture_metrics.h"
#include "base/containers/flat_set.h"
#include "ui/display/display_observer.h"
#include "ui/events/event_handler.h"
#include "ui/events/gestures/gesture_provider_aura.h"

namespace ash {

class BackGestureAffordance;
class BackGestureContextualNudgeControllerImpl;

class BackGestureEventHandler : public display::DisplayObserver,
                                public ui::EventHandler,
                                public ui::GestureConsumer,
                                public ui::GestureProviderAuraClient {
 public:
  // The threshold of the fling velocity while fling from left edge to go
  // previous page.
  static constexpr int kFlingVelocityForGoingBack = 1000;

  // How many dips are reserved for gesture events to start swiping to previous
  // page from the left edge of the screen in tablet mode.
  static constexpr int kStartGoingBackLeftEdgeInset = 16;

  BackGestureEventHandler();
  BackGestureEventHandler(const BackGestureEventHandler&) = delete;
  BackGestureEventHandler& operator=(const BackGestureEventHandler&) = delete;
  ~BackGestureEventHandler() override;

  // display::DisplayObserver:
  void OnDisplayMetricsChanged(const display::Display& display,
                               uint32_t metrics) override;

  // ui::EventHandler:
  void OnGestureEvent(ui::GestureEvent* event) override;
  void OnTouchEvent(ui::TouchEvent* event) override;

  // ui::GestureConsumer:
  const std::string& GetName() const override;

  // ui::GestureProviderAuraClient:
  void OnGestureEvent(GestureConsumer* consumer,
                      ui::GestureEvent* event) override;

  BackGestureContextualNudgeControllerImpl* nudge_controller_for_testing() {
    return nudge_controller_.get();
  }

 private:
  // Returns true if |event| was handled as a go-back gesture. |event| is
  // generated by |gesture_provider_| from touch event, |screen_location| is
  // location of the event in screen coordinates.
  bool MaybeHandleBackGesture(ui::GestureEvent* event,
                              const gfx::Point& screen_location);

  // True if we can start swiping from left edge of the display or splitview
  // divider to go back.
  bool CanStartGoingBack(const gfx::Point& screen_location);

  void SendBackEvent(const gfx::Point& screen_location);

  // Returns true if we should wait for touch press ack to decide whether to
  // show back gesture. If true, BackGestureEventHandler should not handle touch
  // press event in OnTouchEvent() but should wait after touch ack has been
  // received.
  bool ShouldWaitForTouchPressAck(const gfx::Point& screen_location);

  // True if swiping from left edge to go to previous page is in progress.
  bool going_back_started_ = false;

  // Tracks the x-axis and y-axis drag amount through touch events. Used for
  // back gesture affordance in tablet mode. The gesture movement of back
  // gesture can't be recognized by GestureRecognizer, which leads to wrong
  // gesture locations of back gesture. See crbug.com/1015464 for the details.
  int x_drag_amount_ = 0;
  int y_drag_amount_ = 0;

  // True if back gesture dragging on the negative direction of x-axis.
  bool during_reverse_dragging_ = false;

  // Position of last touch event. Used to calculate |y_drag_amount_|. Note,
  // only touch events from |first_touch_id_| will be recorded.
  gfx::Point last_touch_point_;
  ui::PointerId first_touch_id_ = ui::kPointerIdUnknown;

  // Maintains the ids list of the touch events that are not generated from
  // |first_touch_id_| when back gesture is performed. We need this so that we
  // can ignore gesture events that are not generated from the first finger.
  base::flat_set<uint32_t> other_touch_event_ids_list_;

  // Used to show the affordance while swiping from left edge to go to the
  // previous page.
  std::unique_ptr<BackGestureAffordance> back_gesture_affordance_;

  // Used to decide when to show/hide the back gesture contextual nudge.
  std::unique_ptr<BackGestureContextualNudgeControllerImpl> nudge_controller_;

  // True if back gesture dragged from splitview divider.
  bool dragged_from_splitview_divider_ = false;

  // Start location of the back gesture in screen coordinate. Used by
  // ActivateUnderneathWindowInSplitViewMode() to determine the snapped window
  // that should be activated for going back.
  gfx::Point back_start_location_;

  // A GestureProvider that is created for back gesture. Used to handle tap down
  // and the possibly following gesture scroll sequence for back gesture in
  // OnTouchEvent session. This is done to avoid tap down event be used by the
  // window that is underneath to do other things (e.g, highlight a menu item)
  // instead of going back.
  ui::GestureProviderAura gesture_provider_{this, this};

  // Register for DisplayObserver callbacks.
  display::ScopedDisplayObserver display_observer_{this};

  // False if BackGestureEventHandler should not handle touch events directly in
  // OnTouchEvent(), but should wait after touch ack is received. This is needed
  // as the window's touch action (if exist) will only be set after it sees the
  // touch start event and we'll need the touch action information to decide
  // whether back gesture should be shown.
  bool should_wait_for_touch_ack_ = false;

  // Start scenario type of the back gesture, used for related metrics.
  BackGestureStartScenarioType back_gesture_start_scenario_type_ =
      BackGestureStartScenarioType::kMaxValue;
};

}  // namespace ash

#endif  // ASH_WM_GESTURES_BACK_GESTURE_BACK_GESTURE_EVENT_HANDLER_H_