ElementStateManager.h (4568B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_layers_ElementStateManager_h 8 #define mozilla_layers_ElementStateManager_h 9 10 #include "nsCOMPtr.h" 11 #include "nsISupportsImpl.h" 12 #include "mozilla/EnumSet.h" 13 14 namespace mozilla { 15 16 class CancelableRunnable; 17 18 namespace dom { 19 class Element; 20 class EventTarget; 21 } // namespace dom 22 23 namespace layers { 24 25 class DelayedClearElementActivation; 26 27 namespace apz { 28 enum class SingleTapState : uint8_t; 29 } // namespace apz 30 31 /** 32 * Manages setting and clearing the ':active' or `:hover` CSS pseudostate in the 33 * presence of touch input. 34 */ 35 class ElementStateManager final { 36 ~ElementStateManager(); 37 38 public: 39 NS_INLINE_DECL_REFCOUNTING(ElementStateManager) 40 41 ElementStateManager(); 42 43 enum class PreventDefault : bool { No, Yes }; 44 /** 45 * Specify the target of a touch. Typically this should be called right 46 * after HandleTouchStart(), but in cases where the APZ needs to wait for 47 * a content response the HandleTouchStart() may be delayed, in which case 48 * this function can be called first. 49 * |aTarget| may be nullptr. 50 */ 51 void SetTargetElement(dom::EventTarget* aTarget, 52 PreventDefault aTouchStartPreventDefault); 53 /** 54 * Handle a touch-start state notification from APZ. This notification 55 * may be delayed until after touch listeners have responded to the APZ. 56 * @param aCanBePanOrZoom whether the touch can be a pan or double-tap-to-zoom 57 */ 58 void HandleTouchStart(bool aCanBePanOrZoom); 59 60 /** 61 * Handle an eStartPanning state notification from APZ. 62 */ 63 void HandleStartPanning(); 64 65 /** 66 * Clear the active element. 67 */ 68 void ClearActivation(); 69 /** 70 * Handle a touch-end or touch-cancel event. 71 * @param aWasClick whether the touch was a click 72 */ 73 bool HandleTouchEndEvent(apz::SingleTapState aState); 74 /** 75 * Handle a touch-end state notification from APZ. This notification may be 76 * delayed until after touch listeners have responded to the APZ. 77 */ 78 bool HandleTouchEnd(apz::SingleTapState aState); 79 /** 80 * Possibly clear active element sate in response to a single tap. 81 */ 82 void ProcessSingleTap(); 83 /** 84 * Cleanup on window destroy. 85 */ 86 void Destroy(); 87 88 private: 89 /** 90 * The target of the first touch point in the current touch block. 91 */ 92 RefPtr<dom::Element> mTarget; 93 /** 94 * Whether the current touch block can be a pan or double-tap-to-zoom. Set in 95 * HandleTouchStart(). 96 */ 97 bool mCanBePanOrZoom; 98 /** 99 * Whether mCanBePanOrZoom has been set for the current touch block. 100 * We need to keep track of this to allow HandleTouchStart() and 101 * SetTargetElement() to be called in either order. 102 */ 103 bool mCanBePanOrZoomSet; 104 105 bool mSingleTapBeforeActivation; 106 107 enum class TouchEndState : uint8_t { 108 GotTouchEndNotification, 109 GotTouchEndEvent, 110 }; 111 using TouchEndStates = EnumSet<TouchEndState>; 112 113 /** 114 * A flag tracks whether `APZStateChange::eEndTouch` notification has arrived 115 * and whether `eTouchEnd` event has arrived. 116 */ 117 TouchEndStates mTouchEndState; 118 119 /** 120 * A tri-state variable to represent the single tap state when both of 121 * `APZStateChange::eEndTouch` notification and `eTouchEnd` event arrived. 122 */ 123 apz::SingleTapState mSingleTapState; 124 125 /** 126 * A task for calling SetActive() after a timeout. 127 */ 128 RefPtr<CancelableRunnable> mSetActiveTask; 129 130 /** 131 * A task for calling SetHover() after a timeout. 132 */ 133 RefPtr<CancelableRunnable> mSetHoverTask; 134 135 // Store the pending single tap event element activation clearing 136 // task. 137 RefPtr<DelayedClearElementActivation> mDelayedClearElementActivation; 138 139 // Helpers 140 void TriggerElementActivation(); 141 void SetActive(dom::Element* aTarget); 142 void SetHover(dom::Element* aTarget); 143 void ResetActive(); 144 void ResetTouchBlockState(); 145 void ScheduleSetActiveTask(); 146 void SetActiveTask(const nsCOMPtr<dom::Element>& aTarget); 147 void CancelActiveTask(); 148 void ScheduleSetHoverTask(); 149 void SetHoverTask(const nsCOMPtr<dom::Element>& aTarget); 150 void CancelHoverTask(); 151 // Returns true if the function changed the active element state. 152 bool MaybeChangeActiveState(apz::SingleTapState aState); 153 }; 154 155 } // namespace layers 156 } // namespace mozilla 157 158 #endif /* mozilla_layers_ElementStateManager_h */