UserActivation.h (6585B)
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_dom_UserActivation_h 8 #define mozilla_dom_UserActivation_h 9 10 #include "mozilla/Assertions.h" 11 #include "mozilla/EventForwards.h" 12 #include "mozilla/TimeStamp.h" 13 #include "nsCycleCollectionParticipant.h" 14 #include "nsPIDOMWindow.h" 15 #include "nsWrapperCache.h" 16 17 namespace IPC { 18 template <class P> 19 struct ParamTraits; 20 } // namespace IPC 21 22 namespace mozilla::dom { 23 24 /** 25 * Most of this class is for the old user activation model. The new model 26 * defined in the spec [1] is implemented by `dom::WindowContext` (see 27 * `WindowContext::GetUserActivationState` etc.) since the state defined in the 28 * spec is associated with the `window` object. 29 * 30 * [1]: 31 * https://html.spec.whatwg.org/multipage/interaction.html#user-activation-data-model 32 */ 33 class UserActivation final : public nsISupports, public nsWrapperCache { 34 public: 35 // WebIDL UserActivation 36 37 NS_DECL_CYCLE_COLLECTING_ISUPPORTS_FINAL 38 NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(UserActivation) 39 40 explicit UserActivation(nsPIDOMWindowInner* aWindow); 41 42 nsPIDOMWindowInner* GetParentObject() const { return mWindow; } 43 JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) final; 44 45 bool HasBeenActive() const; 46 bool IsActive() const; 47 48 // End of WebIDL UserActivation 49 50 enum class State : uint8_t { 51 // Not activated. 52 None, 53 // It is considered as has-been-activated, but not transient-activated given 54 // that it is being consumed. 55 HasBeenActivated, 56 // It is considered as has-been-activated, and also transient-activated if 57 // haven't timed out. 58 FullActivated, 59 EndGuard_ 60 }; 61 62 class StateAndModifiers; 63 64 // Modifier keys held while the user activation. 65 class Modifiers { 66 public: 67 static constexpr uint8_t Shift = 0x10; 68 static constexpr uint8_t Meta = 0x20; 69 static constexpr uint8_t Control = 0x40; 70 static constexpr uint8_t Alt = 0x80; 71 static constexpr uint8_t MiddleMouse = 0x08; 72 73 static constexpr uint8_t Mask = 0xF8; 74 75 static_assert((uint8_t(State::EndGuard_) & ~Mask) == 76 uint8_t(State::EndGuard_)); 77 78 constexpr Modifiers() = default; 79 explicit constexpr Modifiers(uint8_t aModifiers) : mModifiers(aModifiers) {} 80 81 static constexpr Modifiers None() { return Modifiers(0); } 82 83 void SetShift() { mModifiers |= Shift; } 84 void SetMeta() { mModifiers |= Meta; } 85 void SetControl() { mModifiers |= Control; } 86 void SetAlt() { mModifiers |= Alt; } 87 void SetMiddleMouse() { mModifiers |= MiddleMouse; } 88 89 bool IsShift() const { return mModifiers & Shift; } 90 bool IsMeta() const { return mModifiers & Meta; } 91 bool IsControl() const { return mModifiers & Control; } 92 bool IsAlt() const { return mModifiers & Alt; } 93 bool IsMiddleMouse() const { return mModifiers & MiddleMouse; } 94 95 private: 96 uint8_t mModifiers = 0; 97 98 friend class StateAndModifiers; 99 template <class P> 100 friend struct IPC::ParamTraits; 101 }; 102 103 // State and Modifiers encoded into single data, for WindowContext field. 104 class StateAndModifiers { 105 public: 106 using DataT = uint8_t; 107 108 constexpr StateAndModifiers() = default; 109 explicit constexpr StateAndModifiers(DataT aStateAndModifiers) 110 : mStateAndModifiers(aStateAndModifiers) {} 111 112 DataT GetRawData() const { return mStateAndModifiers; } 113 114 State GetState() const { return State(RawState()); } 115 void SetState(State aState) { 116 MOZ_ASSERT((uint8_t(aState) & Modifiers::Mask) == 0); 117 mStateAndModifiers = uint8_t(aState) | RawModifiers(); 118 } 119 120 Modifiers GetModifiers() const { return Modifiers(RawModifiers()); } 121 void SetModifiers(Modifiers aModifiers) { 122 mStateAndModifiers = RawState() | aModifiers.mModifiers; 123 } 124 125 private: 126 uint8_t RawState() const { return mStateAndModifiers & ~Modifiers::Mask; } 127 128 uint8_t RawModifiers() const { 129 return mStateAndModifiers & Modifiers::Mask; 130 } 131 132 uint8_t mStateAndModifiers = 0; 133 }; 134 135 /** 136 * Returns true if the current code is being executed as a result of 137 * user input or keyboard input. The former includes anything that is 138 * initiated by user, with the exception of page load events or mouse 139 * over events. And the latter returns true when one of the user inputs 140 * is an input from keyboard. If these methods are called from asynchronously 141 * executed code, such as during layout reflows, it will return false. 142 */ 143 static bool IsHandlingUserInput(); 144 static bool IsHandlingKeyboardInput(); 145 146 /** 147 * Returns true if the event is considered as user interaction event. I.e., 148 * enough obvious input to allow to open popup, etc. Otherwise, returns false. 149 */ 150 static bool IsUserInteractionEvent(const WidgetEvent* aEvent); 151 152 /** 153 * StartHandlingUserInput() is called when we start to handle a user input. 154 * StopHandlingUserInput() is called when we finish handling a user input. 155 * If the caller knows which input event caused that, it should set 156 * aMessage to the event message. Otherwise, set eVoidEvent. 157 * Note that StopHandlingUserInput() caller should call it with exactly same 158 * event message as its corresponding StartHandlingUserInput() call because 159 * these methods may count the number of specific event message. 160 */ 161 static void StartHandlingUserInput(EventMessage aMessage); 162 static void StopHandlingUserInput(EventMessage aMessage); 163 164 static TimeStamp GetHandlingInputStart(); 165 166 /** 167 * Get the timestamp at which the latest user input was handled. 168 * 169 * Guaranteed to be monotonic. Until the first user input, return 170 * the epoch. 171 */ 172 static TimeStamp LatestUserInputStart(); 173 174 private: 175 ~UserActivation() = default; 176 177 nsCOMPtr<nsPIDOMWindowInner> mWindow; 178 }; 179 180 /** 181 * This class is used while processing real user input. During this time, popups 182 * are allowed. For mousedown events, mouse capturing is also permitted. 183 */ 184 class MOZ_RAII AutoHandlingUserInputStatePusher final { 185 public: 186 explicit AutoHandlingUserInputStatePusher(bool aIsHandlingUserInput, 187 WidgetEvent* aEvent = nullptr); 188 ~AutoHandlingUserInputStatePusher(); 189 190 protected: 191 EventMessage mMessage; 192 bool mIsHandlingUserInput; 193 }; 194 195 } // namespace mozilla::dom 196 197 #endif // mozilla_dom_UserActivation_h