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
|
/* -*- 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/. */
#include "mozilla/dom/UserActivation.h"
#include "mozilla/TextEvents.h"
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/UserActivationBinding.h"
#include "mozilla/dom/WindowGlobalChild.h"
namespace mozilla::dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(UserActivation, mWindow)
NS_IMPL_CYCLE_COLLECTING_ADDREF(UserActivation)
NS_IMPL_CYCLE_COLLECTING_RELEASE(UserActivation)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(UserActivation)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
UserActivation::UserActivation(nsPIDOMWindowInner* aWindow)
: mWindow(aWindow) {}
JSObject* UserActivation::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
return UserActivation_Binding::Wrap(aCx, this, aGivenProto);
};
// https://html.spec.whatwg.org/multipage/interaction.html#dom-useractivation-hasbeenactive
bool UserActivation::HasBeenActive() const {
// The hasBeenActive getter steps are to return true if this's relevant global
// object has sticky activation, and false otherwise.
WindowContext* wc = mWindow->GetWindowContext();
return wc && wc->HasBeenUserGestureActivated();
}
// https://html.spec.whatwg.org/multipage/interaction.html#dom-useractivation-isactive
bool UserActivation::IsActive() const {
// The isActive getter steps are to return true if this's relevant global
// object has transient activation, and false otherwise.
WindowContext* wc = mWindow->GetWindowContext();
return wc && wc->HasValidTransientUserGestureActivation();
}
namespace {
// The current depth of user and keyboard inputs. sUserInputEventDepth
// is the number of any user input events, page load events and mouse over
// events. sUserKeyboardEventDepth is the number of keyboard input events.
// Incremented whenever we start handling a user input, decremented when we
// have finished handling a user input. This depth is *not* reset in case
// of nested event loops.
static int32_t sUserInputEventDepth = 0;
static int32_t sUserKeyboardEventDepth = 0;
// Time at which we began handling user input. Reset to the epoch
// once we have finished handling user input.
static TimeStamp sHandlingInputStart;
// Time at which we began handling the latest user input. Not reset
// at the end of the input.
static TimeStamp sLatestUserInputStart;
} // namespace
/* static */
bool UserActivation::IsHandlingUserInput() { return sUserInputEventDepth > 0; }
/* static */
bool UserActivation::IsHandlingKeyboardInput() {
return sUserKeyboardEventDepth > 0;
}
/* static */
bool UserActivation::IsUserInteractionEvent(const WidgetEvent* aEvent) {
if (!aEvent->IsTrusted()) {
return false;
}
switch (aEvent->mMessage) {
// eKeyboardEventClass
case eKeyPress:
case eKeyDown:
case eKeyUp:
// Not all keyboard events are treated as user input, so that popups
// can't be opened, fullscreen mode can't be started, etc at
// unexpected time.
return aEvent->AsKeyboardEvent()->CanTreatAsUserInput();
// eBasicEventClass
// eMouseEventClass
case eMouseDown:
case eMouseUp:
// ePointerEventClass
case ePointerClick:
case ePointerDown:
case ePointerUp:
// eTouchEventClass
case eTouchStart:
case eTouchEnd:
return true;
default:
return false;
}
}
/* static */
void UserActivation::StartHandlingUserInput(EventMessage aMessage) {
++sUserInputEventDepth;
if (sUserInputEventDepth == 1) {
sLatestUserInputStart = sHandlingInputStart = TimeStamp::Now();
}
if (WidgetEvent::IsKeyEventMessage(aMessage)) {
++sUserKeyboardEventDepth;
}
}
/* static */
void UserActivation::StopHandlingUserInput(EventMessage aMessage) {
--sUserInputEventDepth;
if (sUserInputEventDepth == 0) {
sHandlingInputStart = TimeStamp();
}
if (WidgetEvent::IsKeyEventMessage(aMessage)) {
--sUserKeyboardEventDepth;
}
}
/* static */
TimeStamp UserActivation::GetHandlingInputStart() {
return sHandlingInputStart;
}
/* static */
TimeStamp UserActivation::LatestUserInputStart() {
return sLatestUserInputStart;
}
//-----------------------------------------------------------------------------
// mozilla::dom::AutoHandlingUserInputStatePusher
//-----------------------------------------------------------------------------
AutoHandlingUserInputStatePusher::AutoHandlingUserInputStatePusher(
bool aIsHandlingUserInput, WidgetEvent* aEvent)
: mMessage(aEvent ? aEvent->mMessage : eVoidEvent),
mIsHandlingUserInput(aIsHandlingUserInput) {
if (!aIsHandlingUserInput) {
return;
}
UserActivation::StartHandlingUserInput(mMessage);
}
AutoHandlingUserInputStatePusher::~AutoHandlingUserInputStatePusher() {
if (!mIsHandlingUserInput) {
return;
}
UserActivation::StopHandlingUserInput(mMessage);
}
} // namespace mozilla::dom
|