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
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170

ash / display / touch_calibrator_controller.h [blame]

// Copyright 2016 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_DISPLAY_TOUCH_CALIBRATOR_CONTROLLER_H_
#define ASH_DISPLAY_TOUCH_CALIBRATOR_CONTROLLER_H_

#include <map>

#include "ash/ash_export.h"
#include "base/gtest_prod_util.h"
#include "base/time/time.h"
#include "ui/display/display.h"
#include "ui/display/display_layout.h"
#include "ui/display/manager/display_manager_observer.h"
#include "ui/display/manager/managed_display_info.h"
#include "ui/display/manager/touch_device_manager.h"
#include "ui/events/devices/touchscreen_device.h"
#include "ui/events/event_handler.h"
#include "ui/gfx/geometry/transform.h"
#include "ui/views/widget/unique_widget_ptr.h"

namespace ui {
class KeyEvent;
class TouchEvent;
}  // namespace ui

namespace ash {

class TouchCalibratorView;

// TouchCalibratorController is responsible for managing the touch calibration
// process. In case of native touch calibration it is also responsible for
// collecting the touch calibration associated data from the user. It
// instantiates TouchCalibratorView classes to present the native UX interface
// the user can interact with for calibration.
// This controller ensures that only one instance of calibration is running at
// any given time.
class ASH_EXPORT TouchCalibratorController
    : public ui::EventHandler,
      public display::DisplayManagerObserver {
 public:
  using CalibrationPointPairQuad =
      display::TouchCalibrationData::CalibrationPointPairQuad;
  using TouchCalibrationCallback = base::OnceCallback<void(bool)>;

  static const base::TimeDelta kTouchIntervalThreshold;

  TouchCalibratorController();

  TouchCalibratorController(const TouchCalibratorController&) = delete;
  TouchCalibratorController& operator=(const TouchCalibratorController&) =
      delete;

  ~TouchCalibratorController() override;

  // ui::EventHandler
  void OnKeyEvent(ui::KeyEvent* event) override;
  void OnTouchEvent(ui::TouchEvent* event) override;

  // display::DisplayManagerObserver
  void OnDidApplyDisplayChanges() override;

  // Starts the calibration process for the given |target_display|.
  // |opt_callback| is an optional callback that if provided is executed
  // with the success or failure of the calibration as a boolean argument.
  void StartCalibration(const display::Display& target_display,
                        bool is_custom_calibration,
                        TouchCalibrationCallback opt_callback);

  // Maps all monitors to their matching touchscreen device. Provided callback
  // will be called once all displays have been mapped.
  void StartNativeTouchscreenMappingExperience(
      TouchCalibrationCallback opt_callback);

  // Stops any ongoing calibration process. This is a hard stop which does not
  // save any calibration data. Call CompleteCalibration() if you wish to save
  // calibration data.
  void StopCalibrationAndResetParams();

  // Completes the touch calibration by storing the calibration data for the
  // display.
  void CompleteCalibration(const CalibrationPointPairQuad& pairs,
                           const gfx::Size& display_size);

  // Returns true if any type of touch calibration is active.
  bool IsCalibrating() const;

 private:
  friend class TouchCalibratorControllerTest;
  FRIEND_TEST_ALL_PREFIXES(TouchCalibratorControllerTest, TouchThreshold);
  FRIEND_TEST_ALL_PREFIXES(TouchCalibratorControllerTest, CustomCalibration);
  FRIEND_TEST_ALL_PREFIXES(TouchCalibratorControllerTest,
                           CustomCalibrationInvalidTouchId);
  FRIEND_TEST_ALL_PREFIXES(TouchCalibratorControllerTest,
                           InternalTouchDeviceIsRejected);
  FRIEND_TEST_ALL_PREFIXES(TouchCalibratorControllerTest,
                           Mapping_TwoExternalDisplays_FullFlow);
  FRIEND_TEST_ALL_PREFIXES(TouchCalibratorControllerTest,
                           Mapping_TwoExternalDisplays_SkipFirst);

  enum class CalibrationState {
    // Indicates that the touch calibration is currently active with the built
    // in native UX.
    kNativeCalibration = 0,

    // Indicates that the touch calibration is currently active with the built
    // in native UX for all displays.
    kNativeCalibrationTouchscreenMapping,

    // Indicates that the touch calibration is currently active with a custom
    // UX via the extensions API.
    kCustomCalibration,

    // Indicates that touch calibration is currently inactive.
    kInactive
  };

  // Iterates over to run the calibration experience on the next display.
  // Used when running the touchscreen mapping experience.
  void CalibrateNextDisplay();

  CalibrationState state_ = CalibrationState::kInactive;

  // A map for TouchCalibrator view with the key as display id of the display
  // it is present in.
  std::map<int64_t, views::UniqueWidgetPtr> touch_calibrator_widgets_;

  // The display which is being calibrated by the touch calibrator controller.
  // This is valid only if |is_calibrating| is set to true.
  display::Display target_display_;

  // During calibration this stores the timestamp when the previous touch event
  // was received.
  base::Time last_touch_timestamp_;

  // This is populated during calibration, based on the source id of the device
  // the events are originating from.
  int touch_device_id_ = ui::InputDevice::kInvalidId;

  // A set of ids that belong to touch devices associated with the internal
  // display and are of type |ui::InputDeviceType::INPUT_DEVICE_INTERNAL|. This
  // is only valid when |state_| is not |kInactive|.
  std::set<int> internal_touch_device_ids_;

  // An array of Calibration point pairs. This stores all the 4 display and
  // touch input point pairs that will be used for calibration.
  CalibrationPointPairQuad touch_point_quad_;

  // A callback to be called when touch calibration completes when started via
  // `StartCalibration`.
  TouchCalibrationCallback opt_callback_;
  // A callback to be called when the native touch mapping experience has
  // completed. This is started via `StartNativeTouchscreenMappingExperience`.
  TouchCalibrationCallback opt_callback_all_displays_;

  // The list of displays were already mapped to touchscreen devices in the
  // current instantiation of the touchscreen mapping experience.
  base::flat_set<int64_t> already_mapped_display_ids_;

  // The touch device under calibration may be re-associated to another display
  // during calibration. In such a case, the events originating from the touch
  // device are tranformed based on parameters of the previous display it was
  // linked to. We need to undo these transformations before recording the event
  // locations.
  gfx::Transform event_transformer_;
};

}  // namespace ash
#endif  // ASH_DISPLAY_TOUCH_CALIBRATOR_CONTROLLER_H_