summaryrefslogtreecommitdiffstats
path: root/gfx/layers/apz/util/ActiveElementManager.h
blob: 1f2e1e4aad9a9f184e501b1d13b684f54be8bf54 (plain)
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
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_layers_ActiveElementManager_h
#define mozilla_layers_ActiveElementManager_h

#include "nsCOMPtr.h"
#include "nsISupportsImpl.h"
#include "mozilla/EnumSet.h"

namespace mozilla {

class CancelableRunnable;

namespace dom {
class Element;
class EventTarget;
}  // namespace dom

namespace layers {

class DelayedClearElementActivation;

namespace apz {
enum class SingleTapState : uint8_t;
}  // namespace apz

/**
 * Manages setting and clearing the ':active' CSS pseudostate in the presence
 * of touch input.
 */
class ActiveElementManager final {
  ~ActiveElementManager();

 public:
  NS_INLINE_DECL_REFCOUNTING(ActiveElementManager)

  ActiveElementManager();

  /**
   * Specify the target of a touch. Typically this should be called right
   * after HandleTouchStart(), but in cases where the APZ needs to wait for
   * a content response the HandleTouchStart() may be delayed, in which case
   * this function can be called first.
   * |aTarget| may be nullptr.
   */
  void SetTargetElement(dom::EventTarget* aTarget);
  /**
   * Handle a touch-start state notification from APZ. This notification
   * may be delayed until after touch listeners have responded to the APZ.
   * @param aCanBePanOrZoom whether the touch can be a pan or double-tap-to-zoom
   */
  void HandleTouchStart(bool aCanBePanOrZoom);
  /**
   * Clear the active element.
   */
  void ClearActivation();
  /**
   * Handle a touch-end or touch-cancel event.
   * @param aWasClick whether the touch was a click
   */
  bool HandleTouchEndEvent(apz::SingleTapState aState);
  /**
   * Handle a touch-end state notification from APZ. This notification may be
   * delayed until after touch listeners have responded to the APZ.
   */
  bool HandleTouchEnd(apz::SingleTapState aState);
  /**
   * Possibly clear active element sate in response to a single tap.
   */
  void ProcessSingleTap();
  /**
   * Cleanup on window destroy.
   */
  void Destroy();

 private:
  /**
   * The target of the first touch point in the current touch block.
   */
  RefPtr<dom::Element> mTarget;
  /**
   * Whether the current touch block can be a pan or double-tap-to-zoom. Set in
   * HandleTouchStart().
   */
  bool mCanBePanOrZoom;
  /**
   * Whether mCanBePanOrZoom has been set for the current touch block.
   * We need to keep track of this to allow HandleTouchStart() and
   * SetTargetElement() to be called in either order.
   */
  bool mCanBePanOrZoomSet;

  bool mSingleTapBeforeActivation;

  enum class TouchEndState : uint8_t {
    GotTouchEndNotification,
    GotTouchEndEvent,
  };
  using TouchEndStates = EnumSet<TouchEndState>;

  /**
   * A flag tracks whether `APZStateChange::eEndTouch` notification has arrived
   * and whether `eTouchEnd` event has arrived.
   */
  TouchEndStates mTouchEndState;

  /**
   * A tri-state variable to represent the single tap state when both of
   * `APZStateChange::eEndTouch` notification and `eTouchEnd` event arrived.
   */
  apz::SingleTapState mSingleTapState;

  /**
   * A task for calling SetActive() after a timeout.
   */
  RefPtr<CancelableRunnable> mSetActiveTask;

  // Store the pending single tap event element activation clearing
  // task.
  RefPtr<DelayedClearElementActivation> mDelayedClearElementActivation;

  // Helpers
  void TriggerElementActivation();
  void SetActive(dom::Element* aTarget);
  void ResetActive();
  void ResetTouchBlockState();
  void SetActiveTask(const nsCOMPtr<dom::Element>& aTarget);
  void CancelTask();
  // Returns true if the function changed the active element state.
  bool MaybeChangeActiveState(apz::SingleTapState aState);
};

}  // namespace layers
}  // namespace mozilla

#endif /* mozilla_layers_ActiveElementManager_h */