Bug Summary

File:root/firefox-clang/dom/events/EventStateManager.cpp
Warning:line 5437, column 22
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name EventStateManager.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/events -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/events -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/dom/events -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/events -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/third_party/abseil-cpp -I /root/firefox-clang/docshell/base -I /root/firefox-clang/dom/base -I /root/firefox-clang/dom/html -I /root/firefox-clang/dom/storage -I /root/firefox-clang/dom/xml -I /root/firefox-clang/dom/xul -I /root/firefox-clang/js/xpconnect/wrappers -I /root/firefox-clang/layout/forms -I /root/firefox-clang/layout/generic -I /root/firefox-clang/layout/xul -I /root/firefox-clang/layout/xul/tree -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-11-12-001017-1011516-1 -x c++ /root/firefox-clang/dom/events/EventStateManager.cpp
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5#include "EventStateManager.h"
6
7#include "ContentEventHandler.h"
8#include "IMEContentObserver.h"
9#include "RemoteDragStartData.h"
10#include "Units.h"
11#include "WheelHandlingHelper.h"
12#include "imgIContainer.h"
13#include "mozilla/AppShutdown.h"
14#include "mozilla/AsyncEventDispatcher.h"
15#include "mozilla/Attributes.h"
16#include "mozilla/ConnectedAncestorTracker.h"
17#include "mozilla/EditorBase.h"
18#include "mozilla/EventDispatcher.h"
19#include "mozilla/EventForwards.h"
20#include "mozilla/FocusModel.h"
21#include "mozilla/HTMLEditor.h"
22#include "mozilla/Hal.h"
23#include "mozilla/IMEStateManager.h"
24#include "mozilla/Likely.h"
25#include "mozilla/Logging.h"
26#include "mozilla/LookAndFeel.h"
27#include "mozilla/MathAlgorithms.h"
28#include "mozilla/MiscEvents.h"
29#include "mozilla/MouseEvents.h"
30#include "mozilla/PointerLockManager.h"
31#include "mozilla/Preferences.h"
32#include "mozilla/PresShell.h"
33#include "mozilla/ProfilerLabels.h"
34#include "mozilla/ScopeExit.h"
35#include "mozilla/ScrollContainerFrame.h"
36#include "mozilla/ScrollTypes.h"
37#include "mozilla/Services.h"
38#include "mozilla/StaticPrefs_accessibility.h"
39#include "mozilla/StaticPrefs_browser.h"
40#include "mozilla/StaticPrefs_dom.h"
41#include "mozilla/StaticPrefs_layout.h"
42#include "mozilla/StaticPrefs_mousewheel.h"
43#include "mozilla/StaticPrefs_ui.h"
44#include "mozilla/StaticPrefs_zoom.h"
45#include "mozilla/TextComposition.h"
46#include "mozilla/TextControlElement.h"
47#include "mozilla/TextEditor.h"
48#include "mozilla/TextEvents.h"
49#include "mozilla/TouchEvents.h"
50#include "mozilla/UniquePtr.h"
51#include "mozilla/dom/AncestorIterator.h"
52#include "mozilla/dom/BrowserBridgeChild.h"
53#include "mozilla/dom/BrowserChild.h"
54#include "mozilla/dom/BrowsingContext.h"
55#include "mozilla/dom/CanonicalBrowsingContext.h"
56#include "mozilla/dom/ContentChild.h"
57#include "mozilla/dom/ContentParent.h"
58#include "mozilla/dom/DOMIntersectionObserver.h"
59#include "mozilla/dom/DataTransfer.h"
60#include "mozilla/dom/Document.h"
61#include "mozilla/dom/DragEvent.h"
62#include "mozilla/dom/EditContext.h"
63#include "mozilla/dom/ElementInlines.h"
64#include "mozilla/dom/Event.h"
65#include "mozilla/dom/FrameLoaderBinding.h"
66#include "mozilla/dom/HTMLDialogElement.h"
67#include "mozilla/dom/HTMLInputElement.h"
68#include "mozilla/dom/HTMLLabelElement.h"
69#include "mozilla/dom/MouseEventBinding.h"
70#include "mozilla/dom/PerformanceMainThread.h"
71#include "mozilla/dom/PointerEventHandler.h"
72#include "mozilla/dom/PopoverData.h"
73#include "mozilla/dom/Record.h"
74#include "mozilla/dom/Selection.h"
75#include "mozilla/dom/SpeculationRules.h"
76#include "mozilla/dom/UIEvent.h"
77#include "mozilla/dom/UIEventBinding.h"
78#include "mozilla/dom/UserActivation.h"
79#include "mozilla/dom/WheelEventBinding.h"
80#include "mozilla/glean/ProcesstoolsMetrics.h"
81#include "nsCOMPtr.h"
82#include "nsComboboxControlFrame.h"
83#include "nsCommandParams.h"
84#include "nsComputedDOMStyle.h"
85#include "nsContentAreaDragDrop.h"
86#include "nsContentUtils.h"
87#include "nsCopySupport.h"
88#include "nsFocusManager.h"
89#include "nsFontMetrics.h"
90#include "nsFrameLoaderOwner.h"
91#include "nsFrameManager.h"
92#include "nsFrameSelection.h"
93#include "nsGenericHTMLElement.h"
94#include "nsGkAtoms.h"
95#include "nsIBaseWindow.h"
96#include "nsIBrowserChild.h"
97#include "nsIClipboard.h"
98#include "nsIContent.h"
99#include "nsIContentInlines.h"
100#include "nsIController.h"
101#include "nsICookieJarSettings.h"
102#include "nsIDOMXULControlElement.h"
103#include "nsIDocShell.h"
104#include "nsIDocumentViewer.h"
105#include "nsIDragService.h"
106#include "nsIDragSession.h"
107#include "nsIFormControl.h"
108#include "nsIFrame.h"
109#include "nsIInterfaceRequestorUtils.h"
110#include "nsIObserverService.h"
111#include "nsIProperties.h"
112#include "nsISupportsPrimitives.h"
113#include "nsITimer.h"
114#include "nsIWeakReferenceUtils.h"
115#include "nsIWebNavigation.h"
116#include "nsIWidget.h"
117#include "nsLayoutUtils.h"
118#include "nsLiteralString.h"
119#include "nsMenuPopupFrame.h"
120#include "nsNameSpaceManager.h"
121#include "nsPIDOMWindow.h"
122#include "nsPIWindowRoot.h"
123#include "nsPresContext.h"
124#include "nsRefreshObservers.h"
125#include "nsServiceManagerUtils.h"
126#include "nsSubDocumentFrame.h"
127#include "nsTArray.h"
128#include "nsTreeBodyFrame.h"
129#include "nsUnicharUtils.h"
130
131#ifdef XP_MACOSX
132# import <ApplicationServices/ApplicationServices.h>
133#endif
134
135namespace mozilla {
136
137using namespace dom;
138
139// Log the mouse cursor updates. That should be updated only by the events for
140// the last pointer which is actually handled as a user input. I.e., should not
141// be updated by synthesized mouse/pointer move events which are not for the
142// last pointer.
143// - MouseCursorUpdate:3 logs only when EventStateManager and BrowserParent
144// updated the cursor.
145// - MouseCursorUpdate:4 logs any results when BrowserParent handles that.
146// - MouseCursorUpdate:5 logs when UpdateCursor() stopped updating the cursor.
147//
148// NOTE: This can work only on debug builds for avoiding to the damage to the
149// performance.
150LazyLogModule gMouseCursorUpdates("MouseCursorUpdates");
151
152static const LayoutDeviceIntPoint kInvalidRefPoint =
153 LayoutDeviceIntPoint(-1, -1);
154
155static uint32_t gMouseOrKeyboardEventCounter = 0;
156// Like gMouseOrKeyboardEventCounter, but excludes synthesized mouse/pointer
157// events (e.g. synthesized pointer moves dispatched when content shifts under a
158// stationary cursor). Drives the "non-synthesized" active-tick notifications so
159// telemetry can record a corrected active tick alongside the legacy one.
160static uint32_t gNonSynthesizedMouseOrKeyboardEventCounter = 0;
161static nsITimer* gUserInteractionTimer = nullptr;
162static nsITimerCallback* gUserInteractionTimerCallback = nullptr;
163
164static const int32_t kCursorLoadingTimeout = 1000; // ms
165constinit static AutoWeakFrame gLastCursorSourceFrame;
166static TimeStamp gLastCursorUpdateTime;
167static TimeStamp gTypingStartTime;
168static TimeStamp gTypingEndTime;
169static int32_t gTypingInteractionKeyPresses = 0;
170constinit static dom::InteractionData gTypingInteraction = {};
171
172static inline int32_t RoundDown(double aDouble) {
173 return (aDouble > 0) ? static_cast<int32_t>(floor(aDouble))
174 : static_cast<int32_t>(ceil(aDouble));
175}
176
177static bool IsSelectingLink(nsIFrame* aTargetFrame) {
178 if (!aTargetFrame) {
179 return false;
180 }
181 const nsFrameSelection* frameSel = aTargetFrame->GetConstFrameSelection();
182 if (!frameSel || !frameSel->GetDragState()) {
183 return false;
184 }
185
186 if (!nsContentUtils::GetClosestLinkInFlatTree(aTargetFrame->GetContent())) {
187 return false;
188 }
189 return true;
190}
191
192static UniquePtr<WidgetMouseEvent> CreateMouseOrPointerWidgetEvent(
193 const WidgetMouseEvent* aMouseEvent, EventMessage aMessage,
194 EventTarget* aRelatedTarget);
195
196/**
197 * Returns the common ancestor for mouseup purpose, given the
198 * current mouseup target and the previous mousedown target.
199 */
200static nsINode* GetCommonAncestorForMouseUp(
201 nsINode* aCurrentMouseUpTarget, nsINode* aLastMouseDownTarget,
202 const Maybe<FormControlType>& aLastMouseDownInputControlType) {
203 if (!aCurrentMouseUpTarget || !aLastMouseDownTarget) {
204 return nullptr;
205 }
206
207 if (aCurrentMouseUpTarget == aLastMouseDownTarget) {
208 return aCurrentMouseUpTarget;
209 }
210
211 // Build the chain of parents
212 AutoTArray<nsINode*, 30> parents1;
213 do {
214 parents1.AppendElement(aCurrentMouseUpTarget);
215 aCurrentMouseUpTarget = aCurrentMouseUpTarget->GetFlattenedTreeParentNode();
216 } while (aCurrentMouseUpTarget);
217
218 AutoTArray<nsINode*, 30> parents2;
219 do {
220 parents2.AppendElement(aLastMouseDownTarget);
221 if (aLastMouseDownTarget == parents1.LastElement()) {
222 break;
223 }
224 aLastMouseDownTarget = aLastMouseDownTarget->GetFlattenedTreeParentNode();
225 } while (aLastMouseDownTarget);
226
227 // Find where the parent chain differs
228 uint32_t pos1 = parents1.Length();
229 uint32_t pos2 = parents2.Length();
230 nsINode* parent = nullptr;
231 for (uint32_t len = std::min(pos1, pos2); len > 0; --len) {
232 nsINode* child1 = parents1.ElementAt(--pos1);
233 nsINode* child2 = parents2.ElementAt(--pos2);
234 if (child1 != child2) {
235 break;
236 }
237
238 // If the input control type is different between mouseup and mousedown,
239 // this is not a valid click.
240 if (HTMLInputElement* input = HTMLInputElement::FromNodeOrNull(child1)) {
241 if (aLastMouseDownInputControlType.isSome() &&
242 aLastMouseDownInputControlType.ref() != input->ControlType()) {
243 break;
244 }
245 }
246 parent = child1;
247 }
248
249 return parent;
250}
251
252static bool HasNativeKeyBindings(nsIContent* aContent,
253 WidgetKeyboardEvent* aEvent) {
254 MOZ_ASSERT(aEvent->mMessage == eKeyPress)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->mMessage == eKeyPress)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aEvent->mMessage == eKeyPress
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aEvent->mMessage == eKeyPress", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 254); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == eKeyPress"
")"); do { MOZ_CrashSequence(__null, 254); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
255
256 if (!aContent) {
257 return false;
258 }
259
260 const RefPtr<dom::Element> targetElement = aContent->AsElement();
261 if (!targetElement) {
262 return false;
263 }
264
265 const auto type = [&]() -> Maybe<NativeKeyBindingsType> {
266 if (BrowserParent::GetFrom(targetElement)) {
267 const nsCOMPtr<nsIWidget> widget = aEvent->mWidget;
268 if (MOZ_UNLIKELY(!widget)(__builtin_expect(!!(!widget), 0))) {
269 return Nothing();
270 }
271 widget::InputContext context = widget->GetInputContext();
272 return context.mIMEState.IsEditable()
273 ? Some(context.GetNativeKeyBindingsType())
274 : Nothing();
275 }
276
277 const auto* const textControlElement =
278 TextControlElement::FromNode(targetElement);
279 if (textControlElement &&
280 textControlElement->IsSingleLineTextControlOrTextArea() &&
281 !textControlElement->IsInDesignMode()) {
282 return textControlElement->IsTextArea()
283 ? Some(NativeKeyBindingsType::MultiLineEditor)
284 : Some(NativeKeyBindingsType::SingleLineEditor);
285 }
286 return targetElement->IsEditable()
287 ? Some(NativeKeyBindingsType::RichTextEditor)
288 : Nothing();
289 }();
290 if (type.isNothing()) {
291 return false;
292 }
293
294 const nsTArray<CommandInt>& commands =
295 aEvent->EditCommandsConstRef(type.value());
296 return !commands.IsEmpty();
297}
298
299LazyLogModule sMouseBoundaryLog("MouseBoundaryEvents");
300LazyLogModule sPointerBoundaryLog("PointerBoundaryEvents");
301
302/******************************************************************/
303/* mozilla::UITimerCallback */
304/******************************************************************/
305
306class UITimerCallback final : public nsITimerCallback, public nsINamed {
307 public:
308 UITimerCallback() : mPreviousCount(0), mPreviousNonSynthesizedCount(0) {}
309 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
310 NS_DECL_NSITIMERCALLBACKvirtual nsresult Notify(nsITimer *timer) override; inline void
_ensure_GetName_exists(void) { static_assert(std::is_convertible_v
<decltype(this), nsINamed*>, "nsITimerCallback implementations must also implement nsINamed"
); }
311 NS_DECL_NSINAMEDvirtual nsresult GetName(nsACString& aName) override;
312 private:
313 ~UITimerCallback() = default;
314 uint32_t mPreviousCount;
315 uint32_t mPreviousNonSynthesizedCount;
316};
317
318NS_IMPL_ISUPPORTS(UITimerCallback, nsITimerCallback, nsINamed)MozExternalRefCountType UITimerCallback::AddRef(void) { static_assert
(!std::is_destructible_v<UITimerCallback>, "Reference-counted class "
"UITimerCallback" " should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 318); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 318
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("UITimerCallback" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("UITimerCallback" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"UITimerCallback\" != nullptr" " (" "Must specify a name" ")"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 318
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"UITimerCallback\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 318); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("UITimerCallback" " not thread-safe"); nsrefcnt count = ++mRefCnt
; NS_LogAddRef((this), (count), ("UITimerCallback"), (uint32_t
)(sizeof(*this))); return count; } MozExternalRefCountType UITimerCallback
::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 318); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 318
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("UITimerCallback" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("UITimerCallback" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"UITimerCallback\" != nullptr" " (" "Must specify a name" ")"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 318
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"UITimerCallback\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 318); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("UITimerCallback" " not thread-safe"); const char* const nametmp
= "UITimerCallback"; nsrefcnt count = --mRefCnt; NS_LogRelease
((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete
(this); return 0; } return count; } nsresult UITimerCallback
::QueryInterface(const nsIID& aIID, void** aInstancePtr) {
do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "QueryInterface requires a non-NULL destination!", "aInstancePtr"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 318
); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(2 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<UITimerCallback, nsITimerCallback>, int32_t
( reinterpret_cast<char*>(static_cast<nsITimerCallback
*>((UITimerCallback*)0x1000)) - reinterpret_cast<char*>
((UITimerCallback*)0x1000))}, {&mozilla::detail::kImplementedIID
<UITimerCallback, nsINamed>, int32_t( reinterpret_cast<
char*>(static_cast<nsINamed*>((UITimerCallback*)0x1000
)) - reinterpret_cast<char*>((UITimerCallback*)0x1000))
}, {&mozilla::detail::kImplementedIID<UITimerCallback,
nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsITimerCallback*>((UITimerCallback
*)0x1000))) - reinterpret_cast<char*>((UITimerCallback*
)0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table)
> 1, "need at least 1 interface"); rv = NS_TableDrivenQI(
static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
319
320// If aTimer is nullptr, this method always sends "user-interaction-inactive"
321// notification.
322NS_IMETHODIMPnsresult
323UITimerCallback::Notify(nsITimer* aTimer) {
324 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
325 // ObserverService shutdown happens after XPCOMShutdownThreads.
326 if (!obs || AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMShutdownThreads)) {
327 return NS_ERROR_FAILURE;
328 }
329 if ((gMouseOrKeyboardEventCounter == mPreviousCount) || !aTimer) {
330 gMouseOrKeyboardEventCounter = 0;
331 gNonSynthesizedMouseOrKeyboardEventCounter = 0;
332 obs->NotifyObservers(nullptr, "user-interaction-inactive", nullptr);
333 obs->NotifyObservers(nullptr, "user-interaction-inactive-non-synthesized",
334 nullptr);
335 if (gUserInteractionTimer) {
336 gUserInteractionTimer->Cancel();
337 NS_RELEASE(gUserInteractionTimer)do { (gUserInteractionTimer)->Release(); (gUserInteractionTimer
) = 0; } while (0)
;
338 }
339 } else {
340 obs->NotifyObservers(nullptr, "user-interaction-active", nullptr);
341 // The corrected active tick only stays active while non-synthesized events
342 // keep arriving, even if synthesized events alone kept the legacy tick
343 // active during this interval.
344 if (gNonSynthesizedMouseOrKeyboardEventCounter ==
345 mPreviousNonSynthesizedCount) {
346 obs->NotifyObservers(nullptr, "user-interaction-inactive-non-synthesized",
347 nullptr);
348 } else {
349 obs->NotifyObservers(nullptr, "user-interaction-active-non-synthesized",
350 nullptr);
351 }
352 EventStateManager::UpdateUserActivityTimer();
353
354 if (XRE_IsParentProcess()) {
355 hal::BatteryInformation batteryInfo;
356 hal::GetCurrentBatteryInformation(&batteryInfo);
357 glean::power_battery::percentage_when_user_active.AccumulateSingleSample(
358 uint64_t(batteryInfo.level() * 100));
359 }
360 }
361 mPreviousCount = gMouseOrKeyboardEventCounter;
362 mPreviousNonSynthesizedCount = gNonSynthesizedMouseOrKeyboardEventCounter;
363 return NS_OK;
364}
365
366NS_IMETHODIMPnsresult
367UITimerCallback::GetName(nsACString& aName) {
368 aName.AssignLiteral("UITimerCallback_timer");
369 return NS_OK;
370}
371
372/******************************************************************/
373/* mozilla::OverOutElementsWrapper */
374/******************************************************************/
375
376NS_IMPL_CYCLE_COLLECTION(OverOutElementsWrapper, mDeepestEnterEventTarget,OverOutElementsWrapper::cycleCollection OverOutElementsWrapper
::_cycleCollectorGlobal; void OverOutElementsWrapper::cycleCollection
::Unlink(void* p) { OverOutElementsWrapper* tmp = DowncastCCParticipant
<OverOutElementsWrapper>(p); ImplCycleCollectionUnlink(
tmp->mDeepestEnterEventTarget); ImplCycleCollectionUnlink(
tmp->mDispatchingOverEventTarget); ImplCycleCollectionUnlink
(tmp->mDispatchingOutOrDeepestLeaveEventTarget); (void)tmp
; } nsresult OverOutElementsWrapper::cycleCollection::TraverseNative
( void* p, nsCycleCollectionTraversalCallback& cb) { OverOutElementsWrapper
* tmp = DowncastCCParticipant<OverOutElementsWrapper>(p
); cb.DescribeRefCountedNode(tmp->mRefCnt.get(), "OverOutElementsWrapper"
); ImplCycleCollectionTraverse(cb, tmp->mDeepestEnterEventTarget
, "mDeepestEnterEventTarget", 0); ImplCycleCollectionTraverse
(cb, tmp->mDispatchingOverEventTarget, "mDispatchingOverEventTarget"
, 0); ImplCycleCollectionTraverse(cb, tmp->mDispatchingOutOrDeepestLeaveEventTarget
, "mDispatchingOutOrDeepestLeaveEventTarget", 0); (void)tmp; return
NS_OK; }
377 mDispatchingOverEventTarget,OverOutElementsWrapper::cycleCollection OverOutElementsWrapper
::_cycleCollectorGlobal; void OverOutElementsWrapper::cycleCollection
::Unlink(void* p) { OverOutElementsWrapper* tmp = DowncastCCParticipant
<OverOutElementsWrapper>(p); ImplCycleCollectionUnlink(
tmp->mDeepestEnterEventTarget); ImplCycleCollectionUnlink(
tmp->mDispatchingOverEventTarget); ImplCycleCollectionUnlink
(tmp->mDispatchingOutOrDeepestLeaveEventTarget); (void)tmp
; } nsresult OverOutElementsWrapper::cycleCollection::TraverseNative
( void* p, nsCycleCollectionTraversalCallback& cb) { OverOutElementsWrapper
* tmp = DowncastCCParticipant<OverOutElementsWrapper>(p
); cb.DescribeRefCountedNode(tmp->mRefCnt.get(), "OverOutElementsWrapper"
); ImplCycleCollectionTraverse(cb, tmp->mDeepestEnterEventTarget
, "mDeepestEnterEventTarget", 0); ImplCycleCollectionTraverse
(cb, tmp->mDispatchingOverEventTarget, "mDispatchingOverEventTarget"
, 0); ImplCycleCollectionTraverse(cb, tmp->mDispatchingOutOrDeepestLeaveEventTarget
, "mDispatchingOutOrDeepestLeaveEventTarget", 0); (void)tmp; return
NS_OK; }
378 mDispatchingOutOrDeepestLeaveEventTarget)OverOutElementsWrapper::cycleCollection OverOutElementsWrapper
::_cycleCollectorGlobal; void OverOutElementsWrapper::cycleCollection
::Unlink(void* p) { OverOutElementsWrapper* tmp = DowncastCCParticipant
<OverOutElementsWrapper>(p); ImplCycleCollectionUnlink(
tmp->mDeepestEnterEventTarget); ImplCycleCollectionUnlink(
tmp->mDispatchingOverEventTarget); ImplCycleCollectionUnlink
(tmp->mDispatchingOutOrDeepestLeaveEventTarget); (void)tmp
; } nsresult OverOutElementsWrapper::cycleCollection::TraverseNative
( void* p, nsCycleCollectionTraversalCallback& cb) { OverOutElementsWrapper
* tmp = DowncastCCParticipant<OverOutElementsWrapper>(p
); cb.DescribeRefCountedNode(tmp->mRefCnt.get(), "OverOutElementsWrapper"
); ImplCycleCollectionTraverse(cb, tmp->mDeepestEnterEventTarget
, "mDeepestEnterEventTarget", 0); ImplCycleCollectionTraverse
(cb, tmp->mDispatchingOverEventTarget, "mDispatchingOverEventTarget"
, 0); ImplCycleCollectionTraverse(cb, tmp->mDispatchingOutOrDeepestLeaveEventTarget
, "mDispatchingOutOrDeepestLeaveEventTarget", 0); (void)tmp; return
NS_OK; }
379NS_IMPL_CYCLE_COLLECTING_ADDREF(OverOutElementsWrapper)MozExternalRefCountType OverOutElementsWrapper::AddRef(void) {
static_assert(!std::is_destructible_v<OverOutElementsWrapper
>, "Reference-counted class " "OverOutElementsWrapper" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 379); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 379
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); _mOwningThread.AssertOwnership("OverOutElementsWrapper"
" not thread-safe"); nsISupports* base = OverOutElementsWrapper
::cycleCollection::Upcast(this); nsrefcnt count = mRefCnt.incr
(base); NS_LogAddRef((this), (count), ("OverOutElementsWrapper"
), (uint32_t)(sizeof(*this))); return count; }
380NS_IMPL_CYCLE_COLLECTING_RELEASE(OverOutElementsWrapper)MozExternalRefCountType OverOutElementsWrapper::Release(void)
{ do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 380
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); _mOwningThread.AssertOwnership("OverOutElementsWrapper"
" not thread-safe"); nsISupports* base = OverOutElementsWrapper
::cycleCollection::Upcast(this); nsrefcnt count = mRefCnt.decr
(base); if (count == 0) { NS_CycleCollectableHasRefCntZero();
} NS_LogRelease((this), (count), ("OverOutElementsWrapper"))
; return count; } void OverOutElementsWrapper::DeleteCycleCollectable
(void) { delete (this); }
381
382NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(OverOutElementsWrapper)nsresult OverOutElementsWrapper::QueryInterface(const nsIID&
aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 382); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
; if (TopThreeWordsEquals( aIID, (nsXPCOMCycleCollectionParticipant
::kIID), (nsCycleCollectionISupports::kIID)) && (LowWordEquals
(aIID, (nsXPCOMCycleCollectionParticipant::kIID)) || LowWordEquals
(aIID, (nsCycleCollectionISupports::kIID)))) { if (LowWordEquals
(aIID, (nsXPCOMCycleCollectionParticipant::kIID))) { *aInstancePtr
= OverOutElementsWrapper::cycleCollection::GetParticipant();
return NS_OK; } if (LowWordEquals(aIID, (nsCycleCollectionISupports
::kIID))) { *aInstancePtr = OverOutElementsWrapper::cycleCollection
::Upcast(this); return NS_OK; } foundInterface = nullptr; } else
383 NS_INTERFACE_MAP_ENTRY(nsISupports)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(this); else
384NS_INTERFACE_MAP_ENDfoundInterface = 0; nsresult status; if (!foundInterface) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(!aIID.Equals((nsISupports::kIID)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aIID.Equals((nsISupports::kIID
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aIID.Equals((nsISupports::kIID))", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 384); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::kIID))"
")"); do { MOZ_CrashSequence(__null, 384); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
385
386already_AddRefed<nsIWidget> OverOutElementsWrapper::GetLastOverWidget() const {
387 nsCOMPtr<nsIWidget> widget = do_QueryReferent(mLastOverWidget);
388 return widget.forget();
389}
390
391void OverOutElementsWrapper::ContentRemoved(nsIContent& aContent) {
392 if (!mDeepestEnterEventTarget) {
393 return;
394 }
395
396 if (!nsContentUtils::ContentIsFlattenedTreeDescendantOf(
397 mDeepestEnterEventTarget, &aContent)) {
398 return;
399 }
400
401 LogModule* const logModule = mType == BoundaryEventType::Mouse
402 ? sMouseBoundaryLog
403 : sPointerBoundaryLog;
404
405 if (mDispatchingOverEventTarget &&
406 (mDeepestEnterEventTarget == mDispatchingOverEventTarget ||
407 nsContentUtils::ContentIsFlattenedTreeDescendantOf(
408 mDispatchingOverEventTarget, &aContent))) {
409 if (mDispatchingOverEventTarget ==
410 mDispatchingOutOrDeepestLeaveEventTarget) {
411 MOZ_LOG(logModule, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The dispatching \"%s\" event target (%p) is removed"
, LastOverEventTargetIsOutEventTarget() ? "out" : "leave", mDispatchingOutOrDeepestLeaveEventTarget
.get()); } } while (0)
412 ("The dispatching \"%s\" event target (%p) is removed",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The dispatching \"%s\" event target (%p) is removed"
, LastOverEventTargetIsOutEventTarget() ? "out" : "leave", mDispatchingOutOrDeepestLeaveEventTarget
.get()); } } while (0)
413 LastOverEventTargetIsOutEventTarget() ? "out" : "leave",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The dispatching \"%s\" event target (%p) is removed"
, LastOverEventTargetIsOutEventTarget() ? "out" : "leave", mDispatchingOutOrDeepestLeaveEventTarget
.get()); } } while (0)
414 mDispatchingOutOrDeepestLeaveEventTarget.get()))do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The dispatching \"%s\" event target (%p) is removed"
, LastOverEventTargetIsOutEventTarget() ? "out" : "leave", mDispatchingOutOrDeepestLeaveEventTarget
.get()); } } while (0)
;
415 mDispatchingOutOrDeepestLeaveEventTarget = nullptr;
416 }
417 MOZ_LOG(logModule, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The dispatching \"over\" event target (%p) is removed"
, mDispatchingOverEventTarget.get()); } } while (0)
418 ("The dispatching \"over\" event target (%p) is removed",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The dispatching \"over\" event target (%p) is removed"
, mDispatchingOverEventTarget.get()); } } while (0)
419 mDispatchingOverEventTarget.get()))do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The dispatching \"over\" event target (%p) is removed"
, mDispatchingOverEventTarget.get()); } } while (0)
;
420 mDispatchingOverEventTarget = nullptr;
421 }
422 if (mDispatchingOutOrDeepestLeaveEventTarget &&
423 (mDeepestEnterEventTarget == mDispatchingOutOrDeepestLeaveEventTarget ||
424 nsContentUtils::ContentIsFlattenedTreeDescendantOf(
425 mDispatchingOutOrDeepestLeaveEventTarget, &aContent))) {
426 MOZ_LOG(logModule, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The dispatching \"%s\" event target (%p) is removed"
, LastOverEventTargetIsOutEventTarget() ? "out" : "leave", mDispatchingOutOrDeepestLeaveEventTarget
.get()); } } while (0)
427 ("The dispatching \"%s\" event target (%p) is removed",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The dispatching \"%s\" event target (%p) is removed"
, LastOverEventTargetIsOutEventTarget() ? "out" : "leave", mDispatchingOutOrDeepestLeaveEventTarget
.get()); } } while (0)
428 LastOverEventTargetIsOutEventTarget() ? "out" : "leave",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The dispatching \"%s\" event target (%p) is removed"
, LastOverEventTargetIsOutEventTarget() ? "out" : "leave", mDispatchingOutOrDeepestLeaveEventTarget
.get()); } } while (0)
429 mDispatchingOutOrDeepestLeaveEventTarget.get()))do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The dispatching \"%s\" event target (%p) is removed"
, LastOverEventTargetIsOutEventTarget() ? "out" : "leave", mDispatchingOutOrDeepestLeaveEventTarget
.get()); } } while (0)
;
430 mDispatchingOutOrDeepestLeaveEventTarget = nullptr;
431 }
432 MOZ_LOG(logModule, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The last \"%s\" event target (%p) is removed and now the last "
"deepest enter target becomes %s(%p)", LastOverEventTargetIsOutEventTarget
() ? "over" : "enter", mDeepestEnterEventTarget.get(), aContent
.GetFlattenedTreeParent() ? ToString(*aContent.GetFlattenedTreeParent
()).c_str() : "nullptr", aContent.GetFlattenedTreeParent()); }
} while (0)
433 ("The last \"%s\" event target (%p) is removed and now the last "do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The last \"%s\" event target (%p) is removed and now the last "
"deepest enter target becomes %s(%p)", LastOverEventTargetIsOutEventTarget
() ? "over" : "enter", mDeepestEnterEventTarget.get(), aContent
.GetFlattenedTreeParent() ? ToString(*aContent.GetFlattenedTreeParent
()).c_str() : "nullptr", aContent.GetFlattenedTreeParent()); }
} while (0)
434 "deepest enter target becomes %s(%p)",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The last \"%s\" event target (%p) is removed and now the last "
"deepest enter target becomes %s(%p)", LastOverEventTargetIsOutEventTarget
() ? "over" : "enter", mDeepestEnterEventTarget.get(), aContent
.GetFlattenedTreeParent() ? ToString(*aContent.GetFlattenedTreeParent
()).c_str() : "nullptr", aContent.GetFlattenedTreeParent()); }
} while (0)
435 LastOverEventTargetIsOutEventTarget() ? "over" : "enter",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The last \"%s\" event target (%p) is removed and now the last "
"deepest enter target becomes %s(%p)", LastOverEventTargetIsOutEventTarget
() ? "over" : "enter", mDeepestEnterEventTarget.get(), aContent
.GetFlattenedTreeParent() ? ToString(*aContent.GetFlattenedTreeParent
()).c_str() : "nullptr", aContent.GetFlattenedTreeParent()); }
} while (0)
436 mDeepestEnterEventTarget.get(),do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The last \"%s\" event target (%p) is removed and now the last "
"deepest enter target becomes %s(%p)", LastOverEventTargetIsOutEventTarget
() ? "over" : "enter", mDeepestEnterEventTarget.get(), aContent
.GetFlattenedTreeParent() ? ToString(*aContent.GetFlattenedTreeParent
()).c_str() : "nullptr", aContent.GetFlattenedTreeParent()); }
} while (0)
437 aContent.GetFlattenedTreeParent()do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The last \"%s\" event target (%p) is removed and now the last "
"deepest enter target becomes %s(%p)", LastOverEventTargetIsOutEventTarget
() ? "over" : "enter", mDeepestEnterEventTarget.get(), aContent
.GetFlattenedTreeParent() ? ToString(*aContent.GetFlattenedTreeParent
()).c_str() : "nullptr", aContent.GetFlattenedTreeParent()); }
} while (0)
438 ? ToString(*aContent.GetFlattenedTreeParent()).c_str()do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The last \"%s\" event target (%p) is removed and now the last "
"deepest enter target becomes %s(%p)", LastOverEventTargetIsOutEventTarget
() ? "over" : "enter", mDeepestEnterEventTarget.get(), aContent
.GetFlattenedTreeParent() ? ToString(*aContent.GetFlattenedTreeParent
()).c_str() : "nullptr", aContent.GetFlattenedTreeParent()); }
} while (0)
439 : "nullptr",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The last \"%s\" event target (%p) is removed and now the last "
"deepest enter target becomes %s(%p)", LastOverEventTargetIsOutEventTarget
() ? "over" : "enter", mDeepestEnterEventTarget.get(), aContent
.GetFlattenedTreeParent() ? ToString(*aContent.GetFlattenedTreeParent
()).c_str() : "nullptr", aContent.GetFlattenedTreeParent()); }
} while (0)
440 aContent.GetFlattenedTreeParent()))do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The last \"%s\" event target (%p) is removed and now the last "
"deepest enter target becomes %s(%p)", LastOverEventTargetIsOutEventTarget
() ? "over" : "enter", mDeepestEnterEventTarget.get(), aContent
.GetFlattenedTreeParent() ? ToString(*aContent.GetFlattenedTreeParent
()).c_str() : "nullptr", aContent.GetFlattenedTreeParent()); }
} while (0)
;
441 UpdateDeepestEnterEventTarget(aContent.GetFlattenedTreeParent());
442}
443
444void OverOutElementsWrapper::TryToRestorePendingRemovedOverTarget(
445 const WidgetEvent* aEvent) {
446 if (!MaybeHasPendingRemovingOverEventTarget()) {
447 return;
448 }
449
450 LogModule* const logModule = mType == BoundaryEventType::Mouse
451 ? sMouseBoundaryLog
452 : sPointerBoundaryLog;
453
454 // If we receive a mouse event immediately, let's try to restore the last
455 // "over" event target as the following "out" event target. We assume that a
456 // synthesized mousemove or another mouse event is being dispatched at latest
457 // the next animation frame from the removal. However, synthesized mouse move
458 // which is enqueued by ContentRemoved() may not sent to this instance because
459 // the target is considered with the latest layout, so the document of this
460 // instance may be moved somewhere before the next animation frame.
461 // Therefore, we should not restore the last "over" target if we receive an
462 // unexpected event like a keyboard event, a wheel event, etc.
463 if (aEvent->AsMouseEvent()) {
464 // Restore the original "over" event target should be allowed only when it's
465 // reconnected under the last deepest "enter" event target because we need
466 // to dispatch "leave" events later at least on the ancestors which have
467 // never been removed from the tree.
468 // XXX If new ancestor is inserted between mDeepestEnterEventTarget and
469 // mPendingToRemoveLastOverEventTarget, we will dispatch "leave" event even
470 // though we have not dispatched "enter" event on the element. For fixing
471 // this, we need to store the full path of the last "out" event target when
472 // it's removed from the tree. I guess we can be relax for this issue
473 // because this hack is required for web apps which reconnect the target
474 // to the same position immediately.
475 // XXX Should be IsInclusiveFlatTreeDescendantOf()? However, it may
476 // be reconnected into a subtree which is different from where the
477 // last over element was.
478 nsCOMPtr<nsIContent> pendingRemovingOverEventTarget =
479 GetPendingRemovingOverEventTarget();
480 if (pendingRemovingOverEventTarget &&
481 pendingRemovingOverEventTarget->IsInclusiveDescendantOf(
482 mDeepestEnterEventTarget)) {
483 // StoreOverEventTargetAndDeepestEnterEventTarget() always resets
484 // mLastOverWidget. When we restore the pending removing "over" event
485 // target, we need to keep storing the original "over" widget too.
486 nsCOMPtr<nsIWeakReference> widget = std::move(mLastOverWidget);
487 StoreOverEventTargetAndDeepestEnterEventTarget(
488 pendingRemovingOverEventTarget);
489 mLastOverWidget = std::move(widget);
490 MOZ_LOG(logModule, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The \"over\" event target (%p) is restored"
, mDeepestEnterEventTarget.get()); } } while (0)
491 ("The \"over\" event target (%p) is restored",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The \"over\" event target (%p) is restored"
, mDeepestEnterEventTarget.get()); } } while (0)
492 mDeepestEnterEventTarget.get()))do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The \"over\" event target (%p) is restored"
, mDeepestEnterEventTarget.get()); } } while (0)
;
493 return;
494 }
495 MOZ_LOG(logModule, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Forgetting the last \"over\" event target (%p) because it is not "
"reconnected under the deepest enter event target (%p)", mPendingRemovingOverEventTarget
.get(), mDeepestEnterEventTarget.get()); } } while (0)
496 ("Forgetting the last \"over\" event target (%p) because it is not "do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Forgetting the last \"over\" event target (%p) because it is not "
"reconnected under the deepest enter event target (%p)", mPendingRemovingOverEventTarget
.get(), mDeepestEnterEventTarget.get()); } } while (0)
497 "reconnected under the deepest enter event target (%p)",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Forgetting the last \"over\" event target (%p) because it is not "
"reconnected under the deepest enter event target (%p)", mPendingRemovingOverEventTarget
.get(), mDeepestEnterEventTarget.get()); } } while (0)
498 mPendingRemovingOverEventTarget.get(),do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Forgetting the last \"over\" event target (%p) because it is not "
"reconnected under the deepest enter event target (%p)", mPendingRemovingOverEventTarget
.get(), mDeepestEnterEventTarget.get()); } } while (0)
499 mDeepestEnterEventTarget.get()))do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Forgetting the last \"over\" event target (%p) because it is not "
"reconnected under the deepest enter event target (%p)", mPendingRemovingOverEventTarget
.get(), mDeepestEnterEventTarget.get()); } } while (0)
;
500 } else {
501 MOZ_LOG(logModule, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Forgetting the last \"over\" event target (%p) because an "
"unexpected event (%s) is being dispatched, that means that "
"EventStateManager didn't receive a synthesized mousemove which "
"should be dispatched at next animation frame from the removal"
, mPendingRemovingOverEventTarget.get(), ToChar(aEvent->mMessage
)); } } while (0)
502 ("Forgetting the last \"over\" event target (%p) because an "do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Forgetting the last \"over\" event target (%p) because an "
"unexpected event (%s) is being dispatched, that means that "
"EventStateManager didn't receive a synthesized mousemove which "
"should be dispatched at next animation frame from the removal"
, mPendingRemovingOverEventTarget.get(), ToChar(aEvent->mMessage
)); } } while (0)
503 "unexpected event (%s) is being dispatched, that means that "do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Forgetting the last \"over\" event target (%p) because an "
"unexpected event (%s) is being dispatched, that means that "
"EventStateManager didn't receive a synthesized mousemove which "
"should be dispatched at next animation frame from the removal"
, mPendingRemovingOverEventTarget.get(), ToChar(aEvent->mMessage
)); } } while (0)
504 "EventStateManager didn't receive a synthesized mousemove which "do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Forgetting the last \"over\" event target (%p) because an "
"unexpected event (%s) is being dispatched, that means that "
"EventStateManager didn't receive a synthesized mousemove which "
"should be dispatched at next animation frame from the removal"
, mPendingRemovingOverEventTarget.get(), ToChar(aEvent->mMessage
)); } } while (0)
505 "should be dispatched at next animation frame from the removal",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Forgetting the last \"over\" event target (%p) because an "
"unexpected event (%s) is being dispatched, that means that "
"EventStateManager didn't receive a synthesized mousemove which "
"should be dispatched at next animation frame from the removal"
, mPendingRemovingOverEventTarget.get(), ToChar(aEvent->mMessage
)); } } while (0)
506 mPendingRemovingOverEventTarget.get(), ToChar(aEvent->mMessage)))do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Forgetting the last \"over\" event target (%p) because an "
"unexpected event (%s) is being dispatched, that means that "
"EventStateManager didn't receive a synthesized mousemove which "
"should be dispatched at next animation frame from the removal"
, mPendingRemovingOverEventTarget.get(), ToChar(aEvent->mMessage
)); } } while (0)
;
507 }
508
509 // Now, we should not restore mPendingRemovingOverEventTarget to
510 // mDeepestEnterEventTarget anymore since mPendingRemovingOverEventTarget was
511 // moved outside the subtree of mDeepestEnterEventTarget.
512 mPendingRemovingOverEventTarget = nullptr;
513}
514
515void OverOutElementsWrapper::WillDispatchOverAndEnterEvent(
516 nsIContent* aOverEventTarget) {
517 StoreOverEventTargetAndDeepestEnterEventTarget(aOverEventTarget);
518 // Store the first "over" event target we fire and don't refire "over" event
519 // to that element while the first "over" event is still ongoing.
520 mDispatchingOverEventTarget = aOverEventTarget;
521}
522
523void OverOutElementsWrapper::DidDispatchOverAndEnterEvent(
524 nsIContent* aOriginalOverTargetInComposedDoc,
525 nsIWidget* aOverEventTargetWidget) {
526 mDispatchingOverEventTarget = nullptr;
527 mLastOverWidget = do_GetWeakReference(aOverEventTargetWidget);
528
529 // Pointer Events define that once the `pointerover` event target is removed
530 // from the tree, `pointerout` should not be fired on that and the closest
531 // connected ancestor at the target removal should be kept as the deepest
532 // `pointerleave` target. Therefore, we don't need the special handling for
533 // `pointerout` event target if the last `pointerover` target is temporarily
534 // removed from the tree.
535 if (mType == OverOutElementsWrapper::BoundaryEventType::Pointer) {
536 return;
537 }
538
539 // Assume that the caller checks whether aOriginalOverTarget is in the
540 // original document. If we don't enable the strict mouse/pointer event
541 // boundary event dispatching by the pref (see below),
542 // mDeepestEnterEventTarget is set to nullptr when the last "over" target is
543 // removed. Therefore, we cannot check whether aOriginalOverTarget is in the
544 // original document here.
545 if (!aOriginalOverTargetInComposedDoc) {
546 return;
547 }
548 MOZ_ASSERT_IF(mDeepestEnterEventTarget,do { if (mDeepestEnterEventTarget) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(mDeepestEnterEventTarget
->GetComposedDoc() == aOriginalOverTargetInComposedDoc->
GetComposedDoc())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDeepestEnterEventTarget->
GetComposedDoc() == aOriginalOverTargetInComposedDoc->GetComposedDoc
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mDeepestEnterEventTarget->GetComposedDoc() == aOriginalOverTargetInComposedDoc->GetComposedDoc()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 550
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDeepestEnterEventTarget->GetComposedDoc() == aOriginalOverTargetInComposedDoc->GetComposedDoc()"
")"); do { MOZ_CrashSequence(__null, 550); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
549 mDeepestEnterEventTarget->GetComposedDoc() ==do { if (mDeepestEnterEventTarget) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(mDeepestEnterEventTarget
->GetComposedDoc() == aOriginalOverTargetInComposedDoc->
GetComposedDoc())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDeepestEnterEventTarget->
GetComposedDoc() == aOriginalOverTargetInComposedDoc->GetComposedDoc
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mDeepestEnterEventTarget->GetComposedDoc() == aOriginalOverTargetInComposedDoc->GetComposedDoc()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 550
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDeepestEnterEventTarget->GetComposedDoc() == aOriginalOverTargetInComposedDoc->GetComposedDoc()"
")"); do { MOZ_CrashSequence(__null, 550); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
550 aOriginalOverTargetInComposedDoc->GetComposedDoc())do { if (mDeepestEnterEventTarget) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(mDeepestEnterEventTarget
->GetComposedDoc() == aOriginalOverTargetInComposedDoc->
GetComposedDoc())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDeepestEnterEventTarget->
GetComposedDoc() == aOriginalOverTargetInComposedDoc->GetComposedDoc
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mDeepestEnterEventTarget->GetComposedDoc() == aOriginalOverTargetInComposedDoc->GetComposedDoc()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 550
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDeepestEnterEventTarget->GetComposedDoc() == aOriginalOverTargetInComposedDoc->GetComposedDoc()"
")"); do { MOZ_CrashSequence(__null, 550); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
551 // If the "mouseover" event target is removed temporarily while we're
552 // dispatching "mouseover" and "mouseenter" events and the target gets back
553 // under the deepest enter event target, we should restore the "mouseover"
554 // target.
555 if (!LastOverEventTargetIsOutEventTarget() && mDeepestEnterEventTarget &&
556 nsContentUtils::ContentIsFlattenedTreeDescendantOf(
557 aOriginalOverTargetInComposedDoc, mDeepestEnterEventTarget)) {
558 StoreOverEventTargetAndDeepestEnterEventTarget(
559 aOriginalOverTargetInComposedDoc);
560 LogModule* const logModule = mType == BoundaryEventType::Mouse
561 ? sMouseBoundaryLog
562 : sPointerBoundaryLog;
563 MOZ_LOG(logModule, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The \"over\" event target (%p) is restored"
, mDeepestEnterEventTarget.get()); } } while (0)
564 ("The \"over\" event target (%p) is restored",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The \"over\" event target (%p) is restored"
, mDeepestEnterEventTarget.get()); } } while (0)
565 mDeepestEnterEventTarget.get()))do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "The \"over\" event target (%p) is restored"
, mDeepestEnterEventTarget.get()); } } while (0)
;
566 }
567}
568
569void OverOutElementsWrapper::StoreOverEventTargetAndDeepestEnterEventTarget(
570 nsIContent* aOverEventTargetAndDeepestEnterEventTarget) {
571 mDeepestEnterEventTarget = aOverEventTargetAndDeepestEnterEventTarget;
572 mPendingRemovingOverEventTarget = nullptr;
573 mDeepestEnterEventTargetIsOverEventTarget = !!mDeepestEnterEventTarget;
574 mLastOverWidget = nullptr; // Set it after dispatching the "over" event.
575}
576
577void OverOutElementsWrapper::UpdateDeepestEnterEventTarget(
578 nsIContent* aDeepestEnterEventTarget) {
579 if (MOZ_UNLIKELY(mDeepestEnterEventTarget == aDeepestEnterEventTarget)(__builtin_expect(!!(mDeepestEnterEventTarget == aDeepestEnterEventTarget
), 0))
) {
580 return;
581 }
582
583 if (!aDeepestEnterEventTarget) {
584 // If the root element is removed, we don't need to dispatch "leave"
585 // events on any elements. Therefore, we can forget everything.
586 StoreOverEventTargetAndDeepestEnterEventTarget(nullptr);
587 return;
588 }
589
590 if (LastOverEventTargetIsOutEventTarget()) {
591 MOZ_ASSERT(mDeepestEnterEventTarget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDeepestEnterEventTarget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDeepestEnterEventTarget))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("mDeepestEnterEventTarget"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 591
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDeepestEnterEventTarget"
")"); do { MOZ_CrashSequence(__null, 591); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
592 if (mType == BoundaryEventType::Pointer) {
593 // The spec of Pointer Events defines that once the `pointerover` event
594 // target is removed from the tree, `pointerout` should not be fired on
595 // that and the closest connected ancestor at the target removal should be
596 // kept as the deepest `pointerleave` target. All browsers considers the
597 // last `pointerover` event target is removed immediately when it occurs.
598 // Therefore, we don't need the special handling which we do for the
599 // `mouseout` event target below for considering whether we'll dispatch
600 // `pointerout` on the last `pointerover` target.
601 mPendingRemovingOverEventTarget = nullptr;
602 } else if (
603 !StaticPrefs::
604 dom_event_mouse_boundary_restore_last_over_target_from_temporary_removal()) {
605 // The spec of UI Events do not define that browsers should keep storing
606 // the last `mouseover` target when it's removed temporarily and
607 // reconnected immediately. We've decided to follow Chrome's behavior for
608 // now. However, there is a pref to bring back the old behavior if
609 // needed.
610 mPendingRemovingOverEventTarget = nullptr;
611 } else {
612 // However, Safari and old Chrome restore the last `mouseover` target when
613 // it's temporarily removed and reconnected immediately. Therefore, we
614 // should follow them by default. However, we should keep the old
615 // behavior for making it easier to backout the new behavior with
616 // disabling the pref.
617 MOZ_ASSERT(!mPendingRemovingOverEventTarget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mPendingRemovingOverEventTarget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mPendingRemovingOverEventTarget
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mPendingRemovingOverEventTarget", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 617); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPendingRemovingOverEventTarget"
")"); do { MOZ_CrashSequence(__null, 617); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
618 MOZ_ASSERT(mDeepestEnterEventTarget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDeepestEnterEventTarget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDeepestEnterEventTarget))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("mDeepestEnterEventTarget"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 618
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDeepestEnterEventTarget"
")"); do { MOZ_CrashSequence(__null, 618); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
619 mPendingRemovingOverEventTarget =
620 do_GetWeakReference(mDeepestEnterEventTarget);
621 }
622 } else {
623 MOZ_ASSERT(!mDeepestEnterEventTargetIsOverEventTarget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mDeepestEnterEventTargetIsOverEventTarget)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!mDeepestEnterEventTargetIsOverEventTarget))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!mDeepestEnterEventTargetIsOverEventTarget"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 623
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDeepestEnterEventTargetIsOverEventTarget"
")"); do { MOZ_CrashSequence(__null, 623); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
624 // If mDeepestEnterEventTarget is not the last "over" event target, we've
625 // already done the complicated state managing above. Therefore, we only
626 // need to update mDeepestEnterEventTarget in this case.
627 }
628 mDeepestEnterEventTarget = aDeepestEnterEventTarget;
629 mDeepestEnterEventTargetIsOverEventTarget = false;
630 // Do not update mLastOverWidget here because it's required to ignore some
631 // following pointer events which are fired on widget under different top
632 // level widget.
633}
634
635/******************************************************************/
636/* mozilla::EventStateManager */
637/******************************************************************/
638
639static uint32_t sESMInstanceCount = 0;
640
641bool EventStateManager::sNormalLMouseEventInProcess = false;
642int16_t EventStateManager::sCurrentMouseBtn = MouseButton::eNotPressed;
643EventStateManager* EventStateManager::sActiveESM = nullptr;
644EventStateManager* EventStateManager::sCursorSettingManager = nullptr;
645constinit AutoWeakFrame EventStateManager::sLastDragOverFrame{};
646LayoutDeviceIntPoint EventStateManager::sPreLockScreenPoint = kInvalidRefPoint;
647Maybe<CSSIntPoint> EventStateManager::sLastRealScreenPoint;
648bool EventStateManager::sRestorePointerAfterUnlock = false;
649LayoutDeviceIntPoint EventStateManager::sLastRefPoint = kInvalidRefPoint;
650LayoutDeviceIntPoint EventStateManager::sLastRefPointOfRawUpdate =
651 kInvalidRefPoint;
652CSSIntPoint EventStateManager::sLastScreenPoint = CSSIntPoint(0, 0);
653LayoutDeviceIntPoint EventStateManager::sSynthCenteringPoint = kInvalidRefPoint;
654CSSIntPoint EventStateManager::sLastClientPoint = CSSIntPoint(0, 0);
655constinit nsCOMPtr<nsIContent> EventStateManager::sDragOverContent;
656
657EventStateManager::WheelPrefs* EventStateManager::WheelPrefs::sInstance =
658 nullptr;
659EventStateManager::DeltaAccumulator*
660 EventStateManager::DeltaAccumulator::sInstance = nullptr;
661
662constexpr const StyleCursorKind kInvalidCursorKind =
663 static_cast<StyleCursorKind>(255);
664
665EventStateManager::EventStateManager()
666 : mLockCursor(kInvalidCursorKind),
667 mCurrentTarget(nullptr),
668 // init d&d gesture state machine variables
669 mGestureDownPoint(0, 0),
670 mGestureModifiers(0),
671 mGestureDownButtons(0),
672 mGestureDownButton(0),
673 mPresContext(nullptr),
674 mShouldAlwaysUseLineDeltas(false),
675 mShouldAlwaysUseLineDeltasInitialized(false),
676 mInTouchDrag(false),
677 m_haveShutdown(false) {
678 if (sESMInstanceCount == 0) {
679 gUserInteractionTimerCallback = new UITimerCallback();
680 if (gUserInteractionTimerCallback) NS_ADDREF(gUserInteractionTimerCallback)(gUserInteractionTimerCallback)->AddRef();
681 UpdateUserActivityTimer();
682 }
683 ++sESMInstanceCount;
684}
685
686// static
687LazyLogModule& EventStateManager::MouseCursorUpdateLogRef() {
688 return gMouseCursorUpdates;
689}
690
691nsresult EventStateManager::UpdateUserActivityTimer() {
692 if (!gUserInteractionTimerCallback) return NS_OK;
693
694 if (!gUserInteractionTimer) {
695 gUserInteractionTimer = NS_NewTimer().take();
696 }
697
698 if (gUserInteractionTimer) {
699 gUserInteractionTimer->InitWithCallback(
700 gUserInteractionTimerCallback,
701 StaticPrefs::dom_events_user_interaction_interval(),
702 nsITimer::TYPE_ONE_SHOT);
703 }
704 return NS_OK;
705}
706
707void EventStateManager::Init() {
708 nsCOMPtr<nsIObserverService> observerService =
709 mozilla::services::GetObserverService();
710 if (observerService) {
711 observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown", true);
712 }
713}
714
715bool EventStateManager::ShouldAlwaysUseLineDeltas() {
716 if (MOZ_UNLIKELY(!mShouldAlwaysUseLineDeltasInitialized)(__builtin_expect(!!(!mShouldAlwaysUseLineDeltasInitialized),
0))
) {
717 mShouldAlwaysUseLineDeltasInitialized = true;
718 mShouldAlwaysUseLineDeltas =
719 !StaticPrefs::dom_event_wheel_deltaMode_lines_disabled();
720 if (!mShouldAlwaysUseLineDeltas && mDocument) {
721 if (nsIPrincipal* principal =
722 mDocument->GetPrincipalForPrefBasedHacks()) {
723 mShouldAlwaysUseLineDeltas = principal->IsURIInPrefList(
724 "dom.event.wheel-deltaMode-lines.always-enabled");
725 }
726 }
727 }
728 return mShouldAlwaysUseLineDeltas;
729}
730
731EventStateManager::~EventStateManager() {
732 ReleaseCurrentIMEContentObserver();
733
734 if (sActiveESM == this) {
735 sActiveESM = nullptr;
736 }
737
738 if (StaticPrefs::ui_click_hold_context_menus()) {
739 KillClickHoldTimer();
740 }
741
742 if (sCursorSettingManager == this) {
743 sCursorSettingManager = nullptr;
744 }
745
746 --sESMInstanceCount;
747 if (sESMInstanceCount == 0) {
748 WheelTransaction::Shutdown();
749 if (gUserInteractionTimerCallback) {
750 gUserInteractionTimerCallback->Notify(nullptr);
751 NS_RELEASE(gUserInteractionTimerCallback)do { (gUserInteractionTimerCallback)->Release(); (gUserInteractionTimerCallback
) = 0; } while (0)
;
752 }
753 if (gUserInteractionTimer) {
754 gUserInteractionTimer->Cancel();
755 NS_RELEASE(gUserInteractionTimer)do { (gUserInteractionTimer)->Release(); (gUserInteractionTimer
) = 0; } while (0)
;
756 }
757 WheelPrefs::Shutdown();
758 DeltaAccumulator::Shutdown();
759 }
760
761 if (sDragOverContent && sDragOverContent->OwnerDoc() == mDocument) {
762 sDragOverContent = nullptr;
763 }
764
765 if (!m_haveShutdown) {
766 Shutdown();
767
768 // Don't remove from Observer service in Shutdown because Shutdown also
769 // gets called from xpcom shutdown observer. And we don't want to remove
770 // from the service in that case.
771
772 nsCOMPtr<nsIObserverService> observerService =
773 mozilla::services::GetObserverService();
774 if (observerService) {
775 observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown");
776 }
777 }
778}
779
780void EventStateManager::Shutdown() { m_haveShutdown = true; }
781
782NS_IMETHODIMPnsresult
783EventStateManager::Observe(nsISupports* aSubject, const char* aTopic,
784 const char16_t* someData) {
785 if (!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown")) {
786 Shutdown();
787 }
788
789 return NS_OK;
790}
791
792NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EventStateManager)nsresult EventStateManager::QueryInterface(const nsIID& aIID
, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 792); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
; if (TopThreeWordsEquals( aIID, (nsXPCOMCycleCollectionParticipant
::kIID), (nsCycleCollectionISupports::kIID)) && (LowWordEquals
(aIID, (nsXPCOMCycleCollectionParticipant::kIID)) || LowWordEquals
(aIID, (nsCycleCollectionISupports::kIID)))) { if (LowWordEquals
(aIID, (nsXPCOMCycleCollectionParticipant::kIID))) { *aInstancePtr
= EventStateManager::cycleCollection::GetParticipant(); return
NS_OK; } if (LowWordEquals(aIID, (nsCycleCollectionISupports
::kIID))) { *aInstancePtr = EventStateManager::cycleCollection
::Upcast(this); return NS_OK; } foundInterface = nullptr; } else
793 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(static_cast<nsIObserver*>(this)); else
794 NS_INTERFACE_MAP_ENTRY(nsIObserver)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIObserver>)) foundInterface = static_cast
<nsIObserver*>(this); else
795 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsWeakReference>)) foundInterface
= static_cast<nsISupportsWeakReference*>(this); else
796NS_INTERFACE_MAP_ENDfoundInterface = 0; nsresult status; if (!foundInterface) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(!aIID.Equals((nsISupports::kIID)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aIID.Equals((nsISupports::kIID
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aIID.Equals((nsISupports::kIID))", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 796); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::kIID))"
")"); do { MOZ_CrashSequence(__null, 796); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
797
798NS_IMPL_CYCLE_COLLECTING_ADDREF(EventStateManager)MozExternalRefCountType EventStateManager::AddRef(void) { static_assert
(!std::is_destructible_v<EventStateManager>, "Reference-counted class "
"EventStateManager" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 798); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 798
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); _mOwningThread.AssertOwnership("EventStateManager" " not thread-safe"
); nsISupports* base = EventStateManager::cycleCollection::Upcast
(this); nsrefcnt count = mRefCnt.incr(base); NS_LogAddRef((this
), (count), ("EventStateManager"), (uint32_t)(sizeof(*this)))
; return count; }
799NS_IMPL_CYCLE_COLLECTING_RELEASE(EventStateManager)MozExternalRefCountType EventStateManager::Release(void) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 799); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 799
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); _mOwningThread.AssertOwnership("EventStateManager" " not thread-safe"
); nsISupports* base = EventStateManager::cycleCollection::Upcast
(this); nsrefcnt count = mRefCnt.decr(base); if (count == 0) {
NS_CycleCollectableHasRefCntZero(); } NS_LogRelease((this), (
count), ("EventStateManager")); return count; } void EventStateManager
::DeleteCycleCollectable(void) { delete (this); }
800
801NS_IMPL_CYCLE_COLLECTION_WEAK(EventStateManager::cycleCollection EventStateManager::_cycleCollectorGlobal
; void EventStateManager::cycleCollection::Unlink(void* p) { EventStateManager
* tmp = DowncastCCParticipant<EventStateManager>(p); ImplCycleCollectionUnlink
(tmp->mCurrentTargetContent); ImplCycleCollectionUnlink(tmp
->mGestureDownContent); ImplCycleCollectionUnlink(tmp->
mGestureDownFrameOwner); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mActiveContent
); ImplCycleCollectionUnlink(tmp->mHoverContent); ImplCycleCollectionUnlink
(tmp->mURLTargetContent); ImplCycleCollectionUnlink(tmp->
mPopoverPointerDownTarget); ImplCycleCollectionUnlink(tmp->
mMouseEnterLeaveHelper); ImplCycleCollectionUnlink(tmp->mPointersEnterLeaveHelper
); ImplCycleCollectionUnlink(tmp->mDocument); ImplCycleCollectionUnlink
(tmp->mIMEContentObserver); ImplCycleCollectionUnlink(tmp->
mAccessKeys); ImplCycleCollectionUnlink(tmp->mPendingLeaveLinkElement
); tmp->ClearWeakReferences(); (void)tmp; } nsresult EventStateManager
::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { EventStateManager* tmp = DowncastCCParticipant<
EventStateManager>(p); cb.DescribeRefCountedNode(tmp->mRefCnt
.get(), "EventStateManager"); ImplCycleCollectionTraverse(cb,
tmp->mCurrentTargetContent, "mCurrentTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownContent, "mGestureDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownFrameOwner, "mGestureDownFrameOwner"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent, "mLastPrimaryButtonPressInfo.mConnectedDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mDownContent, "mLastPrimaryButtonPressInfo.mDownContent", 0)
; ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mUpContent, "mLastPrimaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mConnectedDownContent
, "mLastMiddleButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mDownContent, "mLastMiddleButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastMiddleButtonPressInfo
.mUpContent, "mLastMiddleButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mConnectedDownContent
, "mLastSecondaryButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mDownContent, "mLastSecondaryButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastSecondaryButtonPressInfo
.mUpContent, "mLastSecondaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mActiveContent, "mActiveContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mHoverContent, "mHoverContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mURLTargetContent, "mURLTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mPopoverPointerDownTarget, "mPopoverPointerDownTarget"
, 0); ImplCycleCollectionTraverse(cb, tmp->mMouseEnterLeaveHelper
, "mMouseEnterLeaveHelper", 0); ImplCycleCollectionTraverse(cb
, tmp->mPointersEnterLeaveHelper, "mPointersEnterLeaveHelper"
, 0); ImplCycleCollectionTraverse(cb, tmp->mDocument, "mDocument"
, 0); ImplCycleCollectionTraverse(cb, tmp->mIMEContentObserver
, "mIMEContentObserver", 0); ImplCycleCollectionTraverse(cb, tmp
->mAccessKeys, "mAccessKeys", 0); ImplCycleCollectionTraverse
(cb, tmp->mPendingLeaveLinkElement, "mPendingLeaveLinkElement"
, 0); (void)tmp; return NS_OK; }
802 EventStateManager, mCurrentTargetContent, mGestureDownContent,EventStateManager::cycleCollection EventStateManager::_cycleCollectorGlobal
; void EventStateManager::cycleCollection::Unlink(void* p) { EventStateManager
* tmp = DowncastCCParticipant<EventStateManager>(p); ImplCycleCollectionUnlink
(tmp->mCurrentTargetContent); ImplCycleCollectionUnlink(tmp
->mGestureDownContent); ImplCycleCollectionUnlink(tmp->
mGestureDownFrameOwner); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mActiveContent
); ImplCycleCollectionUnlink(tmp->mHoverContent); ImplCycleCollectionUnlink
(tmp->mURLTargetContent); ImplCycleCollectionUnlink(tmp->
mPopoverPointerDownTarget); ImplCycleCollectionUnlink(tmp->
mMouseEnterLeaveHelper); ImplCycleCollectionUnlink(tmp->mPointersEnterLeaveHelper
); ImplCycleCollectionUnlink(tmp->mDocument); ImplCycleCollectionUnlink
(tmp->mIMEContentObserver); ImplCycleCollectionUnlink(tmp->
mAccessKeys); ImplCycleCollectionUnlink(tmp->mPendingLeaveLinkElement
); tmp->ClearWeakReferences(); (void)tmp; } nsresult EventStateManager
::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { EventStateManager* tmp = DowncastCCParticipant<
EventStateManager>(p); cb.DescribeRefCountedNode(tmp->mRefCnt
.get(), "EventStateManager"); ImplCycleCollectionTraverse(cb,
tmp->mCurrentTargetContent, "mCurrentTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownContent, "mGestureDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownFrameOwner, "mGestureDownFrameOwner"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent, "mLastPrimaryButtonPressInfo.mConnectedDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mDownContent, "mLastPrimaryButtonPressInfo.mDownContent", 0)
; ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mUpContent, "mLastPrimaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mConnectedDownContent
, "mLastMiddleButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mDownContent, "mLastMiddleButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastMiddleButtonPressInfo
.mUpContent, "mLastMiddleButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mConnectedDownContent
, "mLastSecondaryButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mDownContent, "mLastSecondaryButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastSecondaryButtonPressInfo
.mUpContent, "mLastSecondaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mActiveContent, "mActiveContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mHoverContent, "mHoverContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mURLTargetContent, "mURLTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mPopoverPointerDownTarget, "mPopoverPointerDownTarget"
, 0); ImplCycleCollectionTraverse(cb, tmp->mMouseEnterLeaveHelper
, "mMouseEnterLeaveHelper", 0); ImplCycleCollectionTraverse(cb
, tmp->mPointersEnterLeaveHelper, "mPointersEnterLeaveHelper"
, 0); ImplCycleCollectionTraverse(cb, tmp->mDocument, "mDocument"
, 0); ImplCycleCollectionTraverse(cb, tmp->mIMEContentObserver
, "mIMEContentObserver", 0); ImplCycleCollectionTraverse(cb, tmp
->mAccessKeys, "mAccessKeys", 0); ImplCycleCollectionTraverse
(cb, tmp->mPendingLeaveLinkElement, "mPendingLeaveLinkElement"
, 0); (void)tmp; return NS_OK; }
803 mGestureDownFrameOwner, mLastPrimaryButtonPressInfo.mConnectedDownContent,EventStateManager::cycleCollection EventStateManager::_cycleCollectorGlobal
; void EventStateManager::cycleCollection::Unlink(void* p) { EventStateManager
* tmp = DowncastCCParticipant<EventStateManager>(p); ImplCycleCollectionUnlink
(tmp->mCurrentTargetContent); ImplCycleCollectionUnlink(tmp
->mGestureDownContent); ImplCycleCollectionUnlink(tmp->
mGestureDownFrameOwner); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mActiveContent
); ImplCycleCollectionUnlink(tmp->mHoverContent); ImplCycleCollectionUnlink
(tmp->mURLTargetContent); ImplCycleCollectionUnlink(tmp->
mPopoverPointerDownTarget); ImplCycleCollectionUnlink(tmp->
mMouseEnterLeaveHelper); ImplCycleCollectionUnlink(tmp->mPointersEnterLeaveHelper
); ImplCycleCollectionUnlink(tmp->mDocument); ImplCycleCollectionUnlink
(tmp->mIMEContentObserver); ImplCycleCollectionUnlink(tmp->
mAccessKeys); ImplCycleCollectionUnlink(tmp->mPendingLeaveLinkElement
); tmp->ClearWeakReferences(); (void)tmp; } nsresult EventStateManager
::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { EventStateManager* tmp = DowncastCCParticipant<
EventStateManager>(p); cb.DescribeRefCountedNode(tmp->mRefCnt
.get(), "EventStateManager"); ImplCycleCollectionTraverse(cb,
tmp->mCurrentTargetContent, "mCurrentTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownContent, "mGestureDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownFrameOwner, "mGestureDownFrameOwner"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent, "mLastPrimaryButtonPressInfo.mConnectedDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mDownContent, "mLastPrimaryButtonPressInfo.mDownContent", 0)
; ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mUpContent, "mLastPrimaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mConnectedDownContent
, "mLastMiddleButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mDownContent, "mLastMiddleButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastMiddleButtonPressInfo
.mUpContent, "mLastMiddleButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mConnectedDownContent
, "mLastSecondaryButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mDownContent, "mLastSecondaryButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastSecondaryButtonPressInfo
.mUpContent, "mLastSecondaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mActiveContent, "mActiveContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mHoverContent, "mHoverContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mURLTargetContent, "mURLTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mPopoverPointerDownTarget, "mPopoverPointerDownTarget"
, 0); ImplCycleCollectionTraverse(cb, tmp->mMouseEnterLeaveHelper
, "mMouseEnterLeaveHelper", 0); ImplCycleCollectionTraverse(cb
, tmp->mPointersEnterLeaveHelper, "mPointersEnterLeaveHelper"
, 0); ImplCycleCollectionTraverse(cb, tmp->mDocument, "mDocument"
, 0); ImplCycleCollectionTraverse(cb, tmp->mIMEContentObserver
, "mIMEContentObserver", 0); ImplCycleCollectionTraverse(cb, tmp
->mAccessKeys, "mAccessKeys", 0); ImplCycleCollectionTraverse
(cb, tmp->mPendingLeaveLinkElement, "mPendingLeaveLinkElement"
, 0); (void)tmp; return NS_OK; }
804 mLastPrimaryButtonPressInfo.mDownContent,EventStateManager::cycleCollection EventStateManager::_cycleCollectorGlobal
; void EventStateManager::cycleCollection::Unlink(void* p) { EventStateManager
* tmp = DowncastCCParticipant<EventStateManager>(p); ImplCycleCollectionUnlink
(tmp->mCurrentTargetContent); ImplCycleCollectionUnlink(tmp
->mGestureDownContent); ImplCycleCollectionUnlink(tmp->
mGestureDownFrameOwner); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mActiveContent
); ImplCycleCollectionUnlink(tmp->mHoverContent); ImplCycleCollectionUnlink
(tmp->mURLTargetContent); ImplCycleCollectionUnlink(tmp->
mPopoverPointerDownTarget); ImplCycleCollectionUnlink(tmp->
mMouseEnterLeaveHelper); ImplCycleCollectionUnlink(tmp->mPointersEnterLeaveHelper
); ImplCycleCollectionUnlink(tmp->mDocument); ImplCycleCollectionUnlink
(tmp->mIMEContentObserver); ImplCycleCollectionUnlink(tmp->
mAccessKeys); ImplCycleCollectionUnlink(tmp->mPendingLeaveLinkElement
); tmp->ClearWeakReferences(); (void)tmp; } nsresult EventStateManager
::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { EventStateManager* tmp = DowncastCCParticipant<
EventStateManager>(p); cb.DescribeRefCountedNode(tmp->mRefCnt
.get(), "EventStateManager"); ImplCycleCollectionTraverse(cb,
tmp->mCurrentTargetContent, "mCurrentTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownContent, "mGestureDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownFrameOwner, "mGestureDownFrameOwner"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent, "mLastPrimaryButtonPressInfo.mConnectedDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mDownContent, "mLastPrimaryButtonPressInfo.mDownContent", 0)
; ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mUpContent, "mLastPrimaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mConnectedDownContent
, "mLastMiddleButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mDownContent, "mLastMiddleButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastMiddleButtonPressInfo
.mUpContent, "mLastMiddleButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mConnectedDownContent
, "mLastSecondaryButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mDownContent, "mLastSecondaryButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastSecondaryButtonPressInfo
.mUpContent, "mLastSecondaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mActiveContent, "mActiveContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mHoverContent, "mHoverContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mURLTargetContent, "mURLTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mPopoverPointerDownTarget, "mPopoverPointerDownTarget"
, 0); ImplCycleCollectionTraverse(cb, tmp->mMouseEnterLeaveHelper
, "mMouseEnterLeaveHelper", 0); ImplCycleCollectionTraverse(cb
, tmp->mPointersEnterLeaveHelper, "mPointersEnterLeaveHelper"
, 0); ImplCycleCollectionTraverse(cb, tmp->mDocument, "mDocument"
, 0); ImplCycleCollectionTraverse(cb, tmp->mIMEContentObserver
, "mIMEContentObserver", 0); ImplCycleCollectionTraverse(cb, tmp
->mAccessKeys, "mAccessKeys", 0); ImplCycleCollectionTraverse
(cb, tmp->mPendingLeaveLinkElement, "mPendingLeaveLinkElement"
, 0); (void)tmp; return NS_OK; }
805 mLastPrimaryButtonPressInfo.mUpContent,EventStateManager::cycleCollection EventStateManager::_cycleCollectorGlobal
; void EventStateManager::cycleCollection::Unlink(void* p) { EventStateManager
* tmp = DowncastCCParticipant<EventStateManager>(p); ImplCycleCollectionUnlink
(tmp->mCurrentTargetContent); ImplCycleCollectionUnlink(tmp
->mGestureDownContent); ImplCycleCollectionUnlink(tmp->
mGestureDownFrameOwner); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mActiveContent
); ImplCycleCollectionUnlink(tmp->mHoverContent); ImplCycleCollectionUnlink
(tmp->mURLTargetContent); ImplCycleCollectionUnlink(tmp->
mPopoverPointerDownTarget); ImplCycleCollectionUnlink(tmp->
mMouseEnterLeaveHelper); ImplCycleCollectionUnlink(tmp->mPointersEnterLeaveHelper
); ImplCycleCollectionUnlink(tmp->mDocument); ImplCycleCollectionUnlink
(tmp->mIMEContentObserver); ImplCycleCollectionUnlink(tmp->
mAccessKeys); ImplCycleCollectionUnlink(tmp->mPendingLeaveLinkElement
); tmp->ClearWeakReferences(); (void)tmp; } nsresult EventStateManager
::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { EventStateManager* tmp = DowncastCCParticipant<
EventStateManager>(p); cb.DescribeRefCountedNode(tmp->mRefCnt
.get(), "EventStateManager"); ImplCycleCollectionTraverse(cb,
tmp->mCurrentTargetContent, "mCurrentTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownContent, "mGestureDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownFrameOwner, "mGestureDownFrameOwner"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent, "mLastPrimaryButtonPressInfo.mConnectedDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mDownContent, "mLastPrimaryButtonPressInfo.mDownContent", 0)
; ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mUpContent, "mLastPrimaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mConnectedDownContent
, "mLastMiddleButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mDownContent, "mLastMiddleButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastMiddleButtonPressInfo
.mUpContent, "mLastMiddleButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mConnectedDownContent
, "mLastSecondaryButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mDownContent, "mLastSecondaryButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastSecondaryButtonPressInfo
.mUpContent, "mLastSecondaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mActiveContent, "mActiveContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mHoverContent, "mHoverContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mURLTargetContent, "mURLTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mPopoverPointerDownTarget, "mPopoverPointerDownTarget"
, 0); ImplCycleCollectionTraverse(cb, tmp->mMouseEnterLeaveHelper
, "mMouseEnterLeaveHelper", 0); ImplCycleCollectionTraverse(cb
, tmp->mPointersEnterLeaveHelper, "mPointersEnterLeaveHelper"
, 0); ImplCycleCollectionTraverse(cb, tmp->mDocument, "mDocument"
, 0); ImplCycleCollectionTraverse(cb, tmp->mIMEContentObserver
, "mIMEContentObserver", 0); ImplCycleCollectionTraverse(cb, tmp
->mAccessKeys, "mAccessKeys", 0); ImplCycleCollectionTraverse
(cb, tmp->mPendingLeaveLinkElement, "mPendingLeaveLinkElement"
, 0); (void)tmp; return NS_OK; }
806 mLastMiddleButtonPressInfo.mConnectedDownContent,EventStateManager::cycleCollection EventStateManager::_cycleCollectorGlobal
; void EventStateManager::cycleCollection::Unlink(void* p) { EventStateManager
* tmp = DowncastCCParticipant<EventStateManager>(p); ImplCycleCollectionUnlink
(tmp->mCurrentTargetContent); ImplCycleCollectionUnlink(tmp
->mGestureDownContent); ImplCycleCollectionUnlink(tmp->
mGestureDownFrameOwner); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mActiveContent
); ImplCycleCollectionUnlink(tmp->mHoverContent); ImplCycleCollectionUnlink
(tmp->mURLTargetContent); ImplCycleCollectionUnlink(tmp->
mPopoverPointerDownTarget); ImplCycleCollectionUnlink(tmp->
mMouseEnterLeaveHelper); ImplCycleCollectionUnlink(tmp->mPointersEnterLeaveHelper
); ImplCycleCollectionUnlink(tmp->mDocument); ImplCycleCollectionUnlink
(tmp->mIMEContentObserver); ImplCycleCollectionUnlink(tmp->
mAccessKeys); ImplCycleCollectionUnlink(tmp->mPendingLeaveLinkElement
); tmp->ClearWeakReferences(); (void)tmp; } nsresult EventStateManager
::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { EventStateManager* tmp = DowncastCCParticipant<
EventStateManager>(p); cb.DescribeRefCountedNode(tmp->mRefCnt
.get(), "EventStateManager"); ImplCycleCollectionTraverse(cb,
tmp->mCurrentTargetContent, "mCurrentTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownContent, "mGestureDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownFrameOwner, "mGestureDownFrameOwner"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent, "mLastPrimaryButtonPressInfo.mConnectedDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mDownContent, "mLastPrimaryButtonPressInfo.mDownContent", 0)
; ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mUpContent, "mLastPrimaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mConnectedDownContent
, "mLastMiddleButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mDownContent, "mLastMiddleButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastMiddleButtonPressInfo
.mUpContent, "mLastMiddleButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mConnectedDownContent
, "mLastSecondaryButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mDownContent, "mLastSecondaryButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastSecondaryButtonPressInfo
.mUpContent, "mLastSecondaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mActiveContent, "mActiveContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mHoverContent, "mHoverContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mURLTargetContent, "mURLTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mPopoverPointerDownTarget, "mPopoverPointerDownTarget"
, 0); ImplCycleCollectionTraverse(cb, tmp->mMouseEnterLeaveHelper
, "mMouseEnterLeaveHelper", 0); ImplCycleCollectionTraverse(cb
, tmp->mPointersEnterLeaveHelper, "mPointersEnterLeaveHelper"
, 0); ImplCycleCollectionTraverse(cb, tmp->mDocument, "mDocument"
, 0); ImplCycleCollectionTraverse(cb, tmp->mIMEContentObserver
, "mIMEContentObserver", 0); ImplCycleCollectionTraverse(cb, tmp
->mAccessKeys, "mAccessKeys", 0); ImplCycleCollectionTraverse
(cb, tmp->mPendingLeaveLinkElement, "mPendingLeaveLinkElement"
, 0); (void)tmp; return NS_OK; }
807 mLastMiddleButtonPressInfo.mDownContent,EventStateManager::cycleCollection EventStateManager::_cycleCollectorGlobal
; void EventStateManager::cycleCollection::Unlink(void* p) { EventStateManager
* tmp = DowncastCCParticipant<EventStateManager>(p); ImplCycleCollectionUnlink
(tmp->mCurrentTargetContent); ImplCycleCollectionUnlink(tmp
->mGestureDownContent); ImplCycleCollectionUnlink(tmp->
mGestureDownFrameOwner); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mActiveContent
); ImplCycleCollectionUnlink(tmp->mHoverContent); ImplCycleCollectionUnlink
(tmp->mURLTargetContent); ImplCycleCollectionUnlink(tmp->
mPopoverPointerDownTarget); ImplCycleCollectionUnlink(tmp->
mMouseEnterLeaveHelper); ImplCycleCollectionUnlink(tmp->mPointersEnterLeaveHelper
); ImplCycleCollectionUnlink(tmp->mDocument); ImplCycleCollectionUnlink
(tmp->mIMEContentObserver); ImplCycleCollectionUnlink(tmp->
mAccessKeys); ImplCycleCollectionUnlink(tmp->mPendingLeaveLinkElement
); tmp->ClearWeakReferences(); (void)tmp; } nsresult EventStateManager
::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { EventStateManager* tmp = DowncastCCParticipant<
EventStateManager>(p); cb.DescribeRefCountedNode(tmp->mRefCnt
.get(), "EventStateManager"); ImplCycleCollectionTraverse(cb,
tmp->mCurrentTargetContent, "mCurrentTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownContent, "mGestureDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownFrameOwner, "mGestureDownFrameOwner"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent, "mLastPrimaryButtonPressInfo.mConnectedDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mDownContent, "mLastPrimaryButtonPressInfo.mDownContent", 0)
; ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mUpContent, "mLastPrimaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mConnectedDownContent
, "mLastMiddleButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mDownContent, "mLastMiddleButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastMiddleButtonPressInfo
.mUpContent, "mLastMiddleButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mConnectedDownContent
, "mLastSecondaryButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mDownContent, "mLastSecondaryButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastSecondaryButtonPressInfo
.mUpContent, "mLastSecondaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mActiveContent, "mActiveContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mHoverContent, "mHoverContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mURLTargetContent, "mURLTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mPopoverPointerDownTarget, "mPopoverPointerDownTarget"
, 0); ImplCycleCollectionTraverse(cb, tmp->mMouseEnterLeaveHelper
, "mMouseEnterLeaveHelper", 0); ImplCycleCollectionTraverse(cb
, tmp->mPointersEnterLeaveHelper, "mPointersEnterLeaveHelper"
, 0); ImplCycleCollectionTraverse(cb, tmp->mDocument, "mDocument"
, 0); ImplCycleCollectionTraverse(cb, tmp->mIMEContentObserver
, "mIMEContentObserver", 0); ImplCycleCollectionTraverse(cb, tmp
->mAccessKeys, "mAccessKeys", 0); ImplCycleCollectionTraverse
(cb, tmp->mPendingLeaveLinkElement, "mPendingLeaveLinkElement"
, 0); (void)tmp; return NS_OK; }
808 mLastMiddleButtonPressInfo.mUpContent,EventStateManager::cycleCollection EventStateManager::_cycleCollectorGlobal
; void EventStateManager::cycleCollection::Unlink(void* p) { EventStateManager
* tmp = DowncastCCParticipant<EventStateManager>(p); ImplCycleCollectionUnlink
(tmp->mCurrentTargetContent); ImplCycleCollectionUnlink(tmp
->mGestureDownContent); ImplCycleCollectionUnlink(tmp->
mGestureDownFrameOwner); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mActiveContent
); ImplCycleCollectionUnlink(tmp->mHoverContent); ImplCycleCollectionUnlink
(tmp->mURLTargetContent); ImplCycleCollectionUnlink(tmp->
mPopoverPointerDownTarget); ImplCycleCollectionUnlink(tmp->
mMouseEnterLeaveHelper); ImplCycleCollectionUnlink(tmp->mPointersEnterLeaveHelper
); ImplCycleCollectionUnlink(tmp->mDocument); ImplCycleCollectionUnlink
(tmp->mIMEContentObserver); ImplCycleCollectionUnlink(tmp->
mAccessKeys); ImplCycleCollectionUnlink(tmp->mPendingLeaveLinkElement
); tmp->ClearWeakReferences(); (void)tmp; } nsresult EventStateManager
::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { EventStateManager* tmp = DowncastCCParticipant<
EventStateManager>(p); cb.DescribeRefCountedNode(tmp->mRefCnt
.get(), "EventStateManager"); ImplCycleCollectionTraverse(cb,
tmp->mCurrentTargetContent, "mCurrentTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownContent, "mGestureDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownFrameOwner, "mGestureDownFrameOwner"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent, "mLastPrimaryButtonPressInfo.mConnectedDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mDownContent, "mLastPrimaryButtonPressInfo.mDownContent", 0)
; ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mUpContent, "mLastPrimaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mConnectedDownContent
, "mLastMiddleButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mDownContent, "mLastMiddleButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastMiddleButtonPressInfo
.mUpContent, "mLastMiddleButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mConnectedDownContent
, "mLastSecondaryButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mDownContent, "mLastSecondaryButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastSecondaryButtonPressInfo
.mUpContent, "mLastSecondaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mActiveContent, "mActiveContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mHoverContent, "mHoverContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mURLTargetContent, "mURLTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mPopoverPointerDownTarget, "mPopoverPointerDownTarget"
, 0); ImplCycleCollectionTraverse(cb, tmp->mMouseEnterLeaveHelper
, "mMouseEnterLeaveHelper", 0); ImplCycleCollectionTraverse(cb
, tmp->mPointersEnterLeaveHelper, "mPointersEnterLeaveHelper"
, 0); ImplCycleCollectionTraverse(cb, tmp->mDocument, "mDocument"
, 0); ImplCycleCollectionTraverse(cb, tmp->mIMEContentObserver
, "mIMEContentObserver", 0); ImplCycleCollectionTraverse(cb, tmp
->mAccessKeys, "mAccessKeys", 0); ImplCycleCollectionTraverse
(cb, tmp->mPendingLeaveLinkElement, "mPendingLeaveLinkElement"
, 0); (void)tmp; return NS_OK; }
809 mLastSecondaryButtonPressInfo.mConnectedDownContent,EventStateManager::cycleCollection EventStateManager::_cycleCollectorGlobal
; void EventStateManager::cycleCollection::Unlink(void* p) { EventStateManager
* tmp = DowncastCCParticipant<EventStateManager>(p); ImplCycleCollectionUnlink
(tmp->mCurrentTargetContent); ImplCycleCollectionUnlink(tmp
->mGestureDownContent); ImplCycleCollectionUnlink(tmp->
mGestureDownFrameOwner); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mActiveContent
); ImplCycleCollectionUnlink(tmp->mHoverContent); ImplCycleCollectionUnlink
(tmp->mURLTargetContent); ImplCycleCollectionUnlink(tmp->
mPopoverPointerDownTarget); ImplCycleCollectionUnlink(tmp->
mMouseEnterLeaveHelper); ImplCycleCollectionUnlink(tmp->mPointersEnterLeaveHelper
); ImplCycleCollectionUnlink(tmp->mDocument); ImplCycleCollectionUnlink
(tmp->mIMEContentObserver); ImplCycleCollectionUnlink(tmp->
mAccessKeys); ImplCycleCollectionUnlink(tmp->mPendingLeaveLinkElement
); tmp->ClearWeakReferences(); (void)tmp; } nsresult EventStateManager
::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { EventStateManager* tmp = DowncastCCParticipant<
EventStateManager>(p); cb.DescribeRefCountedNode(tmp->mRefCnt
.get(), "EventStateManager"); ImplCycleCollectionTraverse(cb,
tmp->mCurrentTargetContent, "mCurrentTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownContent, "mGestureDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownFrameOwner, "mGestureDownFrameOwner"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent, "mLastPrimaryButtonPressInfo.mConnectedDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mDownContent, "mLastPrimaryButtonPressInfo.mDownContent", 0)
; ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mUpContent, "mLastPrimaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mConnectedDownContent
, "mLastMiddleButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mDownContent, "mLastMiddleButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastMiddleButtonPressInfo
.mUpContent, "mLastMiddleButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mConnectedDownContent
, "mLastSecondaryButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mDownContent, "mLastSecondaryButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastSecondaryButtonPressInfo
.mUpContent, "mLastSecondaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mActiveContent, "mActiveContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mHoverContent, "mHoverContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mURLTargetContent, "mURLTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mPopoverPointerDownTarget, "mPopoverPointerDownTarget"
, 0); ImplCycleCollectionTraverse(cb, tmp->mMouseEnterLeaveHelper
, "mMouseEnterLeaveHelper", 0); ImplCycleCollectionTraverse(cb
, tmp->mPointersEnterLeaveHelper, "mPointersEnterLeaveHelper"
, 0); ImplCycleCollectionTraverse(cb, tmp->mDocument, "mDocument"
, 0); ImplCycleCollectionTraverse(cb, tmp->mIMEContentObserver
, "mIMEContentObserver", 0); ImplCycleCollectionTraverse(cb, tmp
->mAccessKeys, "mAccessKeys", 0); ImplCycleCollectionTraverse
(cb, tmp->mPendingLeaveLinkElement, "mPendingLeaveLinkElement"
, 0); (void)tmp; return NS_OK; }
810 mLastSecondaryButtonPressInfo.mDownContent,EventStateManager::cycleCollection EventStateManager::_cycleCollectorGlobal
; void EventStateManager::cycleCollection::Unlink(void* p) { EventStateManager
* tmp = DowncastCCParticipant<EventStateManager>(p); ImplCycleCollectionUnlink
(tmp->mCurrentTargetContent); ImplCycleCollectionUnlink(tmp
->mGestureDownContent); ImplCycleCollectionUnlink(tmp->
mGestureDownFrameOwner); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mActiveContent
); ImplCycleCollectionUnlink(tmp->mHoverContent); ImplCycleCollectionUnlink
(tmp->mURLTargetContent); ImplCycleCollectionUnlink(tmp->
mPopoverPointerDownTarget); ImplCycleCollectionUnlink(tmp->
mMouseEnterLeaveHelper); ImplCycleCollectionUnlink(tmp->mPointersEnterLeaveHelper
); ImplCycleCollectionUnlink(tmp->mDocument); ImplCycleCollectionUnlink
(tmp->mIMEContentObserver); ImplCycleCollectionUnlink(tmp->
mAccessKeys); ImplCycleCollectionUnlink(tmp->mPendingLeaveLinkElement
); tmp->ClearWeakReferences(); (void)tmp; } nsresult EventStateManager
::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { EventStateManager* tmp = DowncastCCParticipant<
EventStateManager>(p); cb.DescribeRefCountedNode(tmp->mRefCnt
.get(), "EventStateManager"); ImplCycleCollectionTraverse(cb,
tmp->mCurrentTargetContent, "mCurrentTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownContent, "mGestureDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownFrameOwner, "mGestureDownFrameOwner"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent, "mLastPrimaryButtonPressInfo.mConnectedDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mDownContent, "mLastPrimaryButtonPressInfo.mDownContent", 0)
; ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mUpContent, "mLastPrimaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mConnectedDownContent
, "mLastMiddleButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mDownContent, "mLastMiddleButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastMiddleButtonPressInfo
.mUpContent, "mLastMiddleButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mConnectedDownContent
, "mLastSecondaryButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mDownContent, "mLastSecondaryButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastSecondaryButtonPressInfo
.mUpContent, "mLastSecondaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mActiveContent, "mActiveContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mHoverContent, "mHoverContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mURLTargetContent, "mURLTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mPopoverPointerDownTarget, "mPopoverPointerDownTarget"
, 0); ImplCycleCollectionTraverse(cb, tmp->mMouseEnterLeaveHelper
, "mMouseEnterLeaveHelper", 0); ImplCycleCollectionTraverse(cb
, tmp->mPointersEnterLeaveHelper, "mPointersEnterLeaveHelper"
, 0); ImplCycleCollectionTraverse(cb, tmp->mDocument, "mDocument"
, 0); ImplCycleCollectionTraverse(cb, tmp->mIMEContentObserver
, "mIMEContentObserver", 0); ImplCycleCollectionTraverse(cb, tmp
->mAccessKeys, "mAccessKeys", 0); ImplCycleCollectionTraverse
(cb, tmp->mPendingLeaveLinkElement, "mPendingLeaveLinkElement"
, 0); (void)tmp; return NS_OK; }
811 mLastSecondaryButtonPressInfo.mUpContent, mActiveContent, mHoverContent,EventStateManager::cycleCollection EventStateManager::_cycleCollectorGlobal
; void EventStateManager::cycleCollection::Unlink(void* p) { EventStateManager
* tmp = DowncastCCParticipant<EventStateManager>(p); ImplCycleCollectionUnlink
(tmp->mCurrentTargetContent); ImplCycleCollectionUnlink(tmp
->mGestureDownContent); ImplCycleCollectionUnlink(tmp->
mGestureDownFrameOwner); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mActiveContent
); ImplCycleCollectionUnlink(tmp->mHoverContent); ImplCycleCollectionUnlink
(tmp->mURLTargetContent); ImplCycleCollectionUnlink(tmp->
mPopoverPointerDownTarget); ImplCycleCollectionUnlink(tmp->
mMouseEnterLeaveHelper); ImplCycleCollectionUnlink(tmp->mPointersEnterLeaveHelper
); ImplCycleCollectionUnlink(tmp->mDocument); ImplCycleCollectionUnlink
(tmp->mIMEContentObserver); ImplCycleCollectionUnlink(tmp->
mAccessKeys); ImplCycleCollectionUnlink(tmp->mPendingLeaveLinkElement
); tmp->ClearWeakReferences(); (void)tmp; } nsresult EventStateManager
::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { EventStateManager* tmp = DowncastCCParticipant<
EventStateManager>(p); cb.DescribeRefCountedNode(tmp->mRefCnt
.get(), "EventStateManager"); ImplCycleCollectionTraverse(cb,
tmp->mCurrentTargetContent, "mCurrentTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownContent, "mGestureDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownFrameOwner, "mGestureDownFrameOwner"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent, "mLastPrimaryButtonPressInfo.mConnectedDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mDownContent, "mLastPrimaryButtonPressInfo.mDownContent", 0)
; ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mUpContent, "mLastPrimaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mConnectedDownContent
, "mLastMiddleButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mDownContent, "mLastMiddleButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastMiddleButtonPressInfo
.mUpContent, "mLastMiddleButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mConnectedDownContent
, "mLastSecondaryButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mDownContent, "mLastSecondaryButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastSecondaryButtonPressInfo
.mUpContent, "mLastSecondaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mActiveContent, "mActiveContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mHoverContent, "mHoverContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mURLTargetContent, "mURLTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mPopoverPointerDownTarget, "mPopoverPointerDownTarget"
, 0); ImplCycleCollectionTraverse(cb, tmp->mMouseEnterLeaveHelper
, "mMouseEnterLeaveHelper", 0); ImplCycleCollectionTraverse(cb
, tmp->mPointersEnterLeaveHelper, "mPointersEnterLeaveHelper"
, 0); ImplCycleCollectionTraverse(cb, tmp->mDocument, "mDocument"
, 0); ImplCycleCollectionTraverse(cb, tmp->mIMEContentObserver
, "mIMEContentObserver", 0); ImplCycleCollectionTraverse(cb, tmp
->mAccessKeys, "mAccessKeys", 0); ImplCycleCollectionTraverse
(cb, tmp->mPendingLeaveLinkElement, "mPendingLeaveLinkElement"
, 0); (void)tmp; return NS_OK; }
812 mURLTargetContent, mPopoverPointerDownTarget, mMouseEnterLeaveHelper,EventStateManager::cycleCollection EventStateManager::_cycleCollectorGlobal
; void EventStateManager::cycleCollection::Unlink(void* p) { EventStateManager
* tmp = DowncastCCParticipant<EventStateManager>(p); ImplCycleCollectionUnlink
(tmp->mCurrentTargetContent); ImplCycleCollectionUnlink(tmp
->mGestureDownContent); ImplCycleCollectionUnlink(tmp->
mGestureDownFrameOwner); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mActiveContent
); ImplCycleCollectionUnlink(tmp->mHoverContent); ImplCycleCollectionUnlink
(tmp->mURLTargetContent); ImplCycleCollectionUnlink(tmp->
mPopoverPointerDownTarget); ImplCycleCollectionUnlink(tmp->
mMouseEnterLeaveHelper); ImplCycleCollectionUnlink(tmp->mPointersEnterLeaveHelper
); ImplCycleCollectionUnlink(tmp->mDocument); ImplCycleCollectionUnlink
(tmp->mIMEContentObserver); ImplCycleCollectionUnlink(tmp->
mAccessKeys); ImplCycleCollectionUnlink(tmp->mPendingLeaveLinkElement
); tmp->ClearWeakReferences(); (void)tmp; } nsresult EventStateManager
::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { EventStateManager* tmp = DowncastCCParticipant<
EventStateManager>(p); cb.DescribeRefCountedNode(tmp->mRefCnt
.get(), "EventStateManager"); ImplCycleCollectionTraverse(cb,
tmp->mCurrentTargetContent, "mCurrentTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownContent, "mGestureDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownFrameOwner, "mGestureDownFrameOwner"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent, "mLastPrimaryButtonPressInfo.mConnectedDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mDownContent, "mLastPrimaryButtonPressInfo.mDownContent", 0)
; ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mUpContent, "mLastPrimaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mConnectedDownContent
, "mLastMiddleButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mDownContent, "mLastMiddleButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastMiddleButtonPressInfo
.mUpContent, "mLastMiddleButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mConnectedDownContent
, "mLastSecondaryButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mDownContent, "mLastSecondaryButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastSecondaryButtonPressInfo
.mUpContent, "mLastSecondaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mActiveContent, "mActiveContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mHoverContent, "mHoverContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mURLTargetContent, "mURLTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mPopoverPointerDownTarget, "mPopoverPointerDownTarget"
, 0); ImplCycleCollectionTraverse(cb, tmp->mMouseEnterLeaveHelper
, "mMouseEnterLeaveHelper", 0); ImplCycleCollectionTraverse(cb
, tmp->mPointersEnterLeaveHelper, "mPointersEnterLeaveHelper"
, 0); ImplCycleCollectionTraverse(cb, tmp->mDocument, "mDocument"
, 0); ImplCycleCollectionTraverse(cb, tmp->mIMEContentObserver
, "mIMEContentObserver", 0); ImplCycleCollectionTraverse(cb, tmp
->mAccessKeys, "mAccessKeys", 0); ImplCycleCollectionTraverse
(cb, tmp->mPendingLeaveLinkElement, "mPendingLeaveLinkElement"
, 0); (void)tmp; return NS_OK; }
813 mPointersEnterLeaveHelper, mDocument, mIMEContentObserver, mAccessKeys,EventStateManager::cycleCollection EventStateManager::_cycleCollectorGlobal
; void EventStateManager::cycleCollection::Unlink(void* p) { EventStateManager
* tmp = DowncastCCParticipant<EventStateManager>(p); ImplCycleCollectionUnlink
(tmp->mCurrentTargetContent); ImplCycleCollectionUnlink(tmp
->mGestureDownContent); ImplCycleCollectionUnlink(tmp->
mGestureDownFrameOwner); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mActiveContent
); ImplCycleCollectionUnlink(tmp->mHoverContent); ImplCycleCollectionUnlink
(tmp->mURLTargetContent); ImplCycleCollectionUnlink(tmp->
mPopoverPointerDownTarget); ImplCycleCollectionUnlink(tmp->
mMouseEnterLeaveHelper); ImplCycleCollectionUnlink(tmp->mPointersEnterLeaveHelper
); ImplCycleCollectionUnlink(tmp->mDocument); ImplCycleCollectionUnlink
(tmp->mIMEContentObserver); ImplCycleCollectionUnlink(tmp->
mAccessKeys); ImplCycleCollectionUnlink(tmp->mPendingLeaveLinkElement
); tmp->ClearWeakReferences(); (void)tmp; } nsresult EventStateManager
::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { EventStateManager* tmp = DowncastCCParticipant<
EventStateManager>(p); cb.DescribeRefCountedNode(tmp->mRefCnt
.get(), "EventStateManager"); ImplCycleCollectionTraverse(cb,
tmp->mCurrentTargetContent, "mCurrentTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownContent, "mGestureDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownFrameOwner, "mGestureDownFrameOwner"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent, "mLastPrimaryButtonPressInfo.mConnectedDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mDownContent, "mLastPrimaryButtonPressInfo.mDownContent", 0)
; ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mUpContent, "mLastPrimaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mConnectedDownContent
, "mLastMiddleButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mDownContent, "mLastMiddleButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastMiddleButtonPressInfo
.mUpContent, "mLastMiddleButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mConnectedDownContent
, "mLastSecondaryButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mDownContent, "mLastSecondaryButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastSecondaryButtonPressInfo
.mUpContent, "mLastSecondaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mActiveContent, "mActiveContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mHoverContent, "mHoverContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mURLTargetContent, "mURLTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mPopoverPointerDownTarget, "mPopoverPointerDownTarget"
, 0); ImplCycleCollectionTraverse(cb, tmp->mMouseEnterLeaveHelper
, "mMouseEnterLeaveHelper", 0); ImplCycleCollectionTraverse(cb
, tmp->mPointersEnterLeaveHelper, "mPointersEnterLeaveHelper"
, 0); ImplCycleCollectionTraverse(cb, tmp->mDocument, "mDocument"
, 0); ImplCycleCollectionTraverse(cb, tmp->mIMEContentObserver
, "mIMEContentObserver", 0); ImplCycleCollectionTraverse(cb, tmp
->mAccessKeys, "mAccessKeys", 0); ImplCycleCollectionTraverse
(cb, tmp->mPendingLeaveLinkElement, "mPendingLeaveLinkElement"
, 0); (void)tmp; return NS_OK; }
814 mPendingLeaveLinkElement)EventStateManager::cycleCollection EventStateManager::_cycleCollectorGlobal
; void EventStateManager::cycleCollection::Unlink(void* p) { EventStateManager
* tmp = DowncastCCParticipant<EventStateManager>(p); ImplCycleCollectionUnlink
(tmp->mCurrentTargetContent); ImplCycleCollectionUnlink(tmp
->mGestureDownContent); ImplCycleCollectionUnlink(tmp->
mGestureDownFrameOwner); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastPrimaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastMiddleButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mConnectedDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mDownContent); ImplCycleCollectionUnlink(tmp->mLastSecondaryButtonPressInfo
.mUpContent); ImplCycleCollectionUnlink(tmp->mActiveContent
); ImplCycleCollectionUnlink(tmp->mHoverContent); ImplCycleCollectionUnlink
(tmp->mURLTargetContent); ImplCycleCollectionUnlink(tmp->
mPopoverPointerDownTarget); ImplCycleCollectionUnlink(tmp->
mMouseEnterLeaveHelper); ImplCycleCollectionUnlink(tmp->mPointersEnterLeaveHelper
); ImplCycleCollectionUnlink(tmp->mDocument); ImplCycleCollectionUnlink
(tmp->mIMEContentObserver); ImplCycleCollectionUnlink(tmp->
mAccessKeys); ImplCycleCollectionUnlink(tmp->mPendingLeaveLinkElement
); tmp->ClearWeakReferences(); (void)tmp; } nsresult EventStateManager
::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { EventStateManager* tmp = DowncastCCParticipant<
EventStateManager>(p); cb.DescribeRefCountedNode(tmp->mRefCnt
.get(), "EventStateManager"); ImplCycleCollectionTraverse(cb,
tmp->mCurrentTargetContent, "mCurrentTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownContent, "mGestureDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mGestureDownFrameOwner, "mGestureDownFrameOwner"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mConnectedDownContent, "mLastPrimaryButtonPressInfo.mConnectedDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mDownContent, "mLastPrimaryButtonPressInfo.mDownContent", 0)
; ImplCycleCollectionTraverse(cb, tmp->mLastPrimaryButtonPressInfo
.mUpContent, "mLastPrimaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mConnectedDownContent
, "mLastMiddleButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastMiddleButtonPressInfo.mDownContent, "mLastMiddleButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastMiddleButtonPressInfo
.mUpContent, "mLastMiddleButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mConnectedDownContent
, "mLastSecondaryButtonPressInfo.mConnectedDownContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mLastSecondaryButtonPressInfo.mDownContent, "mLastSecondaryButtonPressInfo.mDownContent"
, 0); ImplCycleCollectionTraverse(cb, tmp->mLastSecondaryButtonPressInfo
.mUpContent, "mLastSecondaryButtonPressInfo.mUpContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mActiveContent, "mActiveContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mHoverContent, "mHoverContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mURLTargetContent, "mURLTargetContent", 0); ImplCycleCollectionTraverse
(cb, tmp->mPopoverPointerDownTarget, "mPopoverPointerDownTarget"
, 0); ImplCycleCollectionTraverse(cb, tmp->mMouseEnterLeaveHelper
, "mMouseEnterLeaveHelper", 0); ImplCycleCollectionTraverse(cb
, tmp->mPointersEnterLeaveHelper, "mPointersEnterLeaveHelper"
, 0); ImplCycleCollectionTraverse(cb, tmp->mDocument, "mDocument"
, 0); ImplCycleCollectionTraverse(cb, tmp->mIMEContentObserver
, "mIMEContentObserver", 0); ImplCycleCollectionTraverse(cb, tmp
->mAccessKeys, "mAccessKeys", 0); ImplCycleCollectionTraverse
(cb, tmp->mPendingLeaveLinkElement, "mPendingLeaveLinkElement"
, 0); (void)tmp; return NS_OK; }
815
816void EventStateManager::ReleaseCurrentIMEContentObserver() {
817 if (mIMEContentObserver) {
818 mIMEContentObserver->DisconnectFromEventStateManager();
819 }
820 mIMEContentObserver = nullptr;
821}
822
823void EventStateManager::OnStartToObserveContent(
824 IMEContentObserver* aIMEContentObserver) {
825 if (mIMEContentObserver == aIMEContentObserver) {
826 return;
827 }
828 ReleaseCurrentIMEContentObserver();
829 mIMEContentObserver = aIMEContentObserver;
830}
831
832void EventStateManager::OnStopObservingContent(
833 IMEContentObserver* aIMEContentObserver) {
834 aIMEContentObserver->DisconnectFromEventStateManager();
835 NS_ENSURE_TRUE_VOID(mIMEContentObserver == aIMEContentObserver)do { if ((__builtin_expect(!!(!(mIMEContentObserver == aIMEContentObserver
)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mIMEContentObserver == aIMEContentObserver"
") failed", nullptr, "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 835); return; } } while (false)
;
836 mIMEContentObserver = nullptr;
837}
838
839void EventStateManager::TryToFlushPendingNotificationsToIME() {
840 if (mIMEContentObserver) {
841 mIMEContentObserver->TryToFlushPendingNotifications(true);
842 }
843}
844
845static bool IsMessageMouseUserActivity(EventMessage aMessage) {
846 return aMessage == eMouseMove || aMessage == eMouseUp ||
847 aMessage == eMouseDown || aMessage == ePointerAuxClick ||
848 aMessage == eMouseDoubleClick || aMessage == ePointerClick ||
849 aMessage == eMouseActivate || aMessage == eMouseLongTap;
850}
851
852static bool IsMessageGamepadUserActivity(EventMessage aMessage) {
853 return aMessage == eGamepadButtonDown || aMessage == eGamepadButtonUp ||
854 aMessage == eGamepadAxisMove;
855}
856
857// static
858bool EventStateManager::IsKeyboardEventUserActivity(WidgetEvent* aEvent) {
859 // We ignore things that shouldn't cause popups, but also things that look
860 // like shortcut presses. In some obscure cases these may actually be
861 // website input, but any meaningful website will have other input anyway,
862 // and we can't very well tell whether shortcut input was supposed to be
863 // directed at chrome or the document.
864
865 WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
866 // Access keys should be treated as page interaction.
867 if (keyEvent->ModifiersMatchWithAccessKey(AccessKeyType::eContent)) {
868 return true;
869 }
870 if (!keyEvent->CanTreatAsUserInput() || keyEvent->IsControl() ||
871 keyEvent->IsMeta() || keyEvent->IsAlt()) {
872 return false;
873 }
874 // Deal with function keys:
875 switch (keyEvent->mKeyNameIndex) {
876 case KEY_NAME_INDEX_F1:
877 case KEY_NAME_INDEX_F2:
878 case KEY_NAME_INDEX_F3:
879 case KEY_NAME_INDEX_F4:
880 case KEY_NAME_INDEX_F5:
881 case KEY_NAME_INDEX_F6:
882 case KEY_NAME_INDEX_F7:
883 case KEY_NAME_INDEX_F8:
884 case KEY_NAME_INDEX_F9:
885 case KEY_NAME_INDEX_F10:
886 case KEY_NAME_INDEX_F11:
887 case KEY_NAME_INDEX_F12:
888 case KEY_NAME_INDEX_F13:
889 case KEY_NAME_INDEX_F14:
890 case KEY_NAME_INDEX_F15:
891 case KEY_NAME_INDEX_F16:
892 case KEY_NAME_INDEX_F17:
893 case KEY_NAME_INDEX_F18:
894 case KEY_NAME_INDEX_F19:
895 case KEY_NAME_INDEX_F20:
896 case KEY_NAME_INDEX_F21:
897 case KEY_NAME_INDEX_F22:
898 case KEY_NAME_INDEX_F23:
899 case KEY_NAME_INDEX_F24:
900 return false;
901 default:
902 return true;
903 }
904}
905
906static void OnTypingInteractionEnded() {
907 // We don't consider a single keystroke to be typing.
908 if (gTypingInteractionKeyPresses > 1) {
909 gTypingInteraction.mInteractionCount += gTypingInteractionKeyPresses;
910 gTypingInteraction.mInteractionTimeInMilliseconds += static_cast<uint32_t>(
911 std::ceil((gTypingEndTime - gTypingStartTime).ToMilliseconds()));
912 }
913
914 gTypingInteractionKeyPresses = 0;
915 gTypingStartTime = TimeStamp();
916 gTypingEndTime = TimeStamp();
917}
918
919static void HandleKeyUpInteraction(WidgetKeyboardEvent* aKeyEvent) {
920 if (EventStateManager::IsKeyboardEventUserActivity(aKeyEvent)) {
921 TimeStamp now = TimeStamp::Now();
922 if (gTypingEndTime.IsNull()) {
923 gTypingEndTime = now;
924 }
925 TimeDuration delay = now - gTypingEndTime;
926 // Has it been too long since the last keystroke to be considered typing?
927 if (gTypingInteractionKeyPresses > 0 &&
928 delay >
929 TimeDuration::FromMilliseconds(
930 StaticPrefs::browser_places_interactions_typing_timeout_ms())) {
931 OnTypingInteractionEnded();
932 }
933 gTypingInteractionKeyPresses++;
934 if (gTypingStartTime.IsNull()) {
935 gTypingStartTime = now;
936 }
937 gTypingEndTime = now;
938 }
939}
940
941static bool NeedsActiveContentChange(const WidgetMouseEvent* aMouseEvent) {
942 // If the mouse event is a synthesized mouse event due to a touch, do
943 // not set/clear the activation state. Element activation is handled by APZ.
944 return !aMouseEvent ||
945 aMouseEvent->mInputSource != MouseEvent_Binding::MOZ_SOURCE_TOUCH;
946}
947
948nsresult EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
949 WidgetEvent* aEvent,
950 nsIFrame* aTargetFrame,
951 nsIContent* aTargetContent,
952 nsEventStatus* aStatus,
953 nsIContent* aOverrideClickTarget) {
954 AUTO_PROFILER_LABEL("EventStateManager::PreHandleEvent", DOM)mozilla::AutoProfilerLabel raiiObject954( "EventStateManager::PreHandleEvent"
, nullptr, JS::ProfilingCategoryPair::DOM)
;
955 NS_ENSURE_ARG_POINTER(aStatus)do { if ((__builtin_expect(!!(!(aStatus)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aStatus" ") failed", nullptr
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 955
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
956 NS_ENSURE_ARG(aPresContext)do { if ((__builtin_expect(!!(!(aPresContext)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPresContext" ") failed"
, nullptr, "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 956); return NS_ERROR_INVALID_ARG; } } while (false)
;
957 if (!aEvent) {
958 NS_ERROR("aEvent is null. This should never happen.")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "aEvent is null. This should never happen."
, "Error", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 958); MOZ_PretendNoReturn(); } while (0)
;
959 return NS_ERROR_NULL_POINTER;
960 }
961
962 NS_WARNING_ASSERTION(do { if (!(!aTargetFrame || !aTargetFrame->GetContent() ||
aTargetFrame->GetContent() == aTargetContent || aTargetFrame
->GetContent()->GetFlattenedTreeParent() == aTargetContent
|| aTargetFrame->IsGeneratedContentFrame())) { NS_DebugBreak
(NS_DEBUG_WARNING, "aTargetFrame should be related with aTargetContent"
, "!aTargetFrame || !aTargetFrame->GetContent() || aTargetFrame->GetContent() == aTargetContent || aTargetFrame->GetContent()->GetFlattenedTreeParent() == aTargetContent || aTargetFrame->IsGeneratedContentFrame()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 968
); } } while (false)
963 !aTargetFrame || !aTargetFrame->GetContent() ||do { if (!(!aTargetFrame || !aTargetFrame->GetContent() ||
aTargetFrame->GetContent() == aTargetContent || aTargetFrame
->GetContent()->GetFlattenedTreeParent() == aTargetContent
|| aTargetFrame->IsGeneratedContentFrame())) { NS_DebugBreak
(NS_DEBUG_WARNING, "aTargetFrame should be related with aTargetContent"
, "!aTargetFrame || !aTargetFrame->GetContent() || aTargetFrame->GetContent() == aTargetContent || aTargetFrame->GetContent()->GetFlattenedTreeParent() == aTargetContent || aTargetFrame->IsGeneratedContentFrame()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 968
); } } while (false)
964 aTargetFrame->GetContent() == aTargetContent ||do { if (!(!aTargetFrame || !aTargetFrame->GetContent() ||
aTargetFrame->GetContent() == aTargetContent || aTargetFrame
->GetContent()->GetFlattenedTreeParent() == aTargetContent
|| aTargetFrame->IsGeneratedContentFrame())) { NS_DebugBreak
(NS_DEBUG_WARNING, "aTargetFrame should be related with aTargetContent"
, "!aTargetFrame || !aTargetFrame->GetContent() || aTargetFrame->GetContent() == aTargetContent || aTargetFrame->GetContent()->GetFlattenedTreeParent() == aTargetContent || aTargetFrame->IsGeneratedContentFrame()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 968
); } } while (false)
965 aTargetFrame->GetContent()->GetFlattenedTreeParent() ==do { if (!(!aTargetFrame || !aTargetFrame->GetContent() ||
aTargetFrame->GetContent() == aTargetContent || aTargetFrame
->GetContent()->GetFlattenedTreeParent() == aTargetContent
|| aTargetFrame->IsGeneratedContentFrame())) { NS_DebugBreak
(NS_DEBUG_WARNING, "aTargetFrame should be related with aTargetContent"
, "!aTargetFrame || !aTargetFrame->GetContent() || aTargetFrame->GetContent() == aTargetContent || aTargetFrame->GetContent()->GetFlattenedTreeParent() == aTargetContent || aTargetFrame->IsGeneratedContentFrame()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 968
); } } while (false)
966 aTargetContent ||do { if (!(!aTargetFrame || !aTargetFrame->GetContent() ||
aTargetFrame->GetContent() == aTargetContent || aTargetFrame
->GetContent()->GetFlattenedTreeParent() == aTargetContent
|| aTargetFrame->IsGeneratedContentFrame())) { NS_DebugBreak
(NS_DEBUG_WARNING, "aTargetFrame should be related with aTargetContent"
, "!aTargetFrame || !aTargetFrame->GetContent() || aTargetFrame->GetContent() == aTargetContent || aTargetFrame->GetContent()->GetFlattenedTreeParent() == aTargetContent || aTargetFrame->IsGeneratedContentFrame()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 968
); } } while (false)
967 aTargetFrame->IsGeneratedContentFrame(),do { if (!(!aTargetFrame || !aTargetFrame->GetContent() ||
aTargetFrame->GetContent() == aTargetContent || aTargetFrame
->GetContent()->GetFlattenedTreeParent() == aTargetContent
|| aTargetFrame->IsGeneratedContentFrame())) { NS_DebugBreak
(NS_DEBUG_WARNING, "aTargetFrame should be related with aTargetContent"
, "!aTargetFrame || !aTargetFrame->GetContent() || aTargetFrame->GetContent() == aTargetContent || aTargetFrame->GetContent()->GetFlattenedTreeParent() == aTargetContent || aTargetFrame->IsGeneratedContentFrame()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 968
); } } while (false)
968 "aTargetFrame should be related with aTargetContent")do { if (!(!aTargetFrame || !aTargetFrame->GetContent() ||
aTargetFrame->GetContent() == aTargetContent || aTargetFrame
->GetContent()->GetFlattenedTreeParent() == aTargetContent
|| aTargetFrame->IsGeneratedContentFrame())) { NS_DebugBreak
(NS_DEBUG_WARNING, "aTargetFrame should be related with aTargetContent"
, "!aTargetFrame || !aTargetFrame->GetContent() || aTargetFrame->GetContent() == aTargetContent || aTargetFrame->GetContent()->GetFlattenedTreeParent() == aTargetContent || aTargetFrame->IsGeneratedContentFrame()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 968
); } } while (false)
;
969#if DEBUG1
970 if (aTargetFrame && aTargetFrame->IsGeneratedContentFrame()) {
971 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTargetContent == aTargetFrame->GetExplicitEventTargetContent
(aEvent))>::isValid, "invalid assertion condition"); if ((
__builtin_expect(!!(!(!!(aTargetContent == aTargetFrame->GetExplicitEventTargetContent
(aEvent)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aTargetContent == aTargetFrame->GetExplicitEventTargetContent(aEvent)"
" (" "Unexpected target for generated content frame!" ")", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTargetContent == aTargetFrame->GetExplicitEventTargetContent(aEvent)"
") (" "Unexpected target for generated content frame!" ")");
do { MOZ_CrashSequence(__null, 973); __attribute__((nomerge)
) ::abort(); } while (false); } } while (false)
972 aTargetContent == aTargetFrame->GetExplicitEventTargetContent(aEvent),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTargetContent == aTargetFrame->GetExplicitEventTargetContent
(aEvent))>::isValid, "invalid assertion condition"); if ((
__builtin_expect(!!(!(!!(aTargetContent == aTargetFrame->GetExplicitEventTargetContent
(aEvent)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aTargetContent == aTargetFrame->GetExplicitEventTargetContent(aEvent)"
" (" "Unexpected target for generated content frame!" ")", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTargetContent == aTargetFrame->GetExplicitEventTargetContent(aEvent)"
") (" "Unexpected target for generated content frame!" ")");
do { MOZ_CrashSequence(__null, 973); __attribute__((nomerge)
) ::abort(); } while (false); } } while (false)
973 "Unexpected target for generated content frame!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTargetContent == aTargetFrame->GetExplicitEventTargetContent
(aEvent))>::isValid, "invalid assertion condition"); if ((
__builtin_expect(!!(!(!!(aTargetContent == aTargetFrame->GetExplicitEventTargetContent
(aEvent)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aTargetContent == aTargetFrame->GetExplicitEventTargetContent(aEvent)"
" (" "Unexpected target for generated content frame!" ")", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTargetContent == aTargetFrame->GetExplicitEventTargetContent(aEvent)"
") (" "Unexpected target for generated content frame!" ")");
do { MOZ_CrashSequence(__null, 973); __attribute__((nomerge)
) ::abort(); } while (false); } } while (false)
;
974 }
975#endif
976
977 mCurrentTarget = aTargetFrame;
978 mCurrentTargetContent = nullptr;
979
980 // Do not take account eMouseEnterIntoWidget/ExitFromWidget so that loading
981 // a page when user is not active doesn't change the state to active.
982 WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
983 if (aEvent->IsTrusted() &&
984 ((mouseEvent && mouseEvent->IsReal() &&
985 IsMessageMouseUserActivity(mouseEvent->mMessage)) ||
986 aEvent->mClass == eWheelEventClass ||
987 aEvent->mClass == ePointerEventClass ||
988 aEvent->mClass == eTouchEventClass ||
989 aEvent->mClass == eKeyboardEventClass ||
990 (aEvent->mClass == eDragEventClass && aEvent->mMessage == eDrop) ||
991 IsMessageGamepadUserActivity(aEvent->mMessage))) {
992 if (gMouseOrKeyboardEventCounter == 0) {
993 nsCOMPtr<nsIObserverService> obs =
994 mozilla::services::GetObserverService();
995 if (obs) {
996 obs->NotifyObservers(nullptr, "user-interaction-active", nullptr);
997 UpdateUserActivityTimer();
998 }
999 }
1000 ++gMouseOrKeyboardEventCounter;
1001
1002 // Synthesized mouse/pointer events (e.g. a synthesized pointer move when
1003 // content moves under a stationary cursor) are not real user activity, so
1004 // they are excluded from the corrected active tick.
1005 if (!mouseEvent || mouseEvent->IsReal()) {
1006 if (gNonSynthesizedMouseOrKeyboardEventCounter == 0) {
1007 nsCOMPtr<nsIObserverService> obs =
1008 mozilla::services::GetObserverService();
1009 if (obs) {
1010 obs->NotifyObservers(
1011 nullptr, "user-interaction-active-non-synthesized", nullptr);
1012 }
1013 }
1014 ++gNonSynthesizedMouseOrKeyboardEventCounter;
1015 }
1016
1017 nsCOMPtr<nsINode> node = aTargetContent;
1018 if (node &&
1019 ((aEvent->mMessage == eKeyUp && IsKeyboardEventUserActivity(aEvent)) ||
1020 aEvent->mMessage == eMouseUp || aEvent->mMessage == eWheel ||
1021 aEvent->mMessage == eTouchEnd || aEvent->mMessage == ePointerUp ||
1022 aEvent->mMessage == eDrop)) {
1023 Document* doc = node->OwnerDoc();
1024 while (doc) {
1025 doc->SetUserHasInteracted();
1026 doc = nsContentUtils::IsChildOfSameType(doc)
1027 ? doc->GetInProcessParentDocument()
1028 : nullptr;
1029 }
1030 }
1031 }
1032
1033 WheelTransaction::OnEvent(aEvent);
1034
1035 // Focus events don't necessarily need a frame.
1036 if (!mCurrentTarget && !aTargetContent) {
1037 NS_ERROR("mCurrentTarget and aTargetContent are null")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "mCurrentTarget and aTargetContent are null"
, "Error", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 1037); MOZ_PretendNoReturn(); } while (0)
;
1038 return NS_ERROR_NULL_POINTER;
1039 }
1040#ifdef DEBUG1
1041 if (aEvent->HasDragEventMessage() && PointerLockManager::IsLocked()) {
1042 NS_ASSERTION(PointerLockManager::IsLocked(),do { if (!(PointerLockManager::IsLocked())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Pointer is locked. Drag events should be suppressed when "
"the pointer is locked.", "PointerLockManager::IsLocked()", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 1044); MOZ_PretendNoReturn(); } } while (0)
1043 "Pointer is locked. Drag events should be suppressed when "do { if (!(PointerLockManager::IsLocked())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Pointer is locked. Drag events should be suppressed when "
"the pointer is locked.", "PointerLockManager::IsLocked()", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 1044); MOZ_PretendNoReturn(); } } while (0)
1044 "the pointer is locked.")do { if (!(PointerLockManager::IsLocked())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Pointer is locked. Drag events should be suppressed when "
"the pointer is locked.", "PointerLockManager::IsLocked()", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 1044); MOZ_PretendNoReturn(); } } while (0)
;
1045 }
1046#endif
1047 // Store last known screenPoint and clientPoint so pointer lock
1048 // can use these values as constants.
1049 const bool shouldStoreLastKnownPoints = [&]() {
1050 if (!aEvent->IsTrusted()) {
1051 return false;
1052 }
1053 if (PointerLockManager::IsLocked()) {
1054 return false;
1055 }
1056 if (mouseEvent) {
1057 if (!mouseEvent->IsReal()) {
1058 return false;
1059 }
1060 // An event with a movement delta was either generated while the native
1061 // pointer was locked, or is the synthesized repositioning mousemove. In
1062 // either case, we should not update the last known position.
1063 // We need this check because the initial synthesized mousemove might
1064 // arrive in the content process before the pointer lock request is
1065 // resolved.
1066 if (mouseEvent->mMovement) {
1067 return false;
1068 }
1069 return true;
1070 }
1071 return aEvent->mClass == eWheelEventClass;
1072 }();
1073
1074 if (shouldStoreLastKnownPoints) {
1075 // XXX Probably doesn't matter much, but storing these in CSS pixels instead
1076 // of device pixels means behavior can be a bit odd if you zoom while
1077 // pointer-locked.
1078 sLastScreenPoint = RoundedToInt(
1079 Event::GetScreenCoords(aPresContext, aEvent, aEvent->mRefPoint)
1080 .extract());
1081 sLastClientPoint = RoundedToInt(Event::GetClientCoords(
1082 aPresContext, aEvent, aEvent->mRefPoint, CSSDoublePoint{0, 0}));
1083 if (!aEvent->mFlags.mIsSynthesizedForTests) {
1084 sLastRealScreenPoint = Some(sLastScreenPoint);
1085 }
1086 }
1087
1088 *aStatus = nsEventStatus_eIgnore;
1089
1090 if (aEvent->mClass == eQueryContentEventClass) {
1091 HandleQueryContentEvent(aEvent->AsQueryContentEvent());
1092 return NS_OK;
1093 }
1094
1095 WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent();
1096 if (touchEvent && mInTouchDrag) {
1097 if (touchEvent->mMessage == eTouchMove) {
1098 GenerateDragGesture(aPresContext, *touchEvent);
1099 } else {
1100 MOZ_ASSERT(touchEvent->mMessage != eTouchRawUpdate)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(touchEvent->mMessage != eTouchRawUpdate)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(touchEvent->mMessage != eTouchRawUpdate))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("touchEvent->mMessage != eTouchRawUpdate"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 1100
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "touchEvent->mMessage != eTouchRawUpdate"
")"); do { MOZ_CrashSequence(__null, 1100); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1101 mInTouchDrag = false;
1102 StopTrackingDragGesture(true);
1103 }
1104 }
1105
1106 if (mMouseEnterLeaveHelper && aEvent->IsTrusted()) {
1107 // When the last `mouseover` event target is removed from the document,
1108 // we makes mMouseEnterLeaveHelper update the last deepest `mouseenter`
1109 // event target to the removed node parent and mark it as not the following
1110 // `mouseout` event target. However, the other browsers may dispatch
1111 // `mouseout` on it if it's restored "immediately". Therefore, we use
1112 // the next animation frame as the deadline. ContentRemoved() enqueues a
1113 // synthesized `mousemove` to dispatch mouse boundary events under the
1114 // mouse cursor soon and the synthesized event (or eMouseExitFromWidget if
1115 // our window is moved) will reach here at latest the next animation frame.
1116 // Therefore, we can use the event as the deadline. If the removed last
1117 // `mouseover` target is reconnected before a synthesized mouse event or
1118 // a real mouse event, let's restore it as the following `mouseout` event
1119 // target. Otherwise, e.g., a keyboard event, let's forget it.
1120 mMouseEnterLeaveHelper->TryToRestorePendingRemovedOverTarget(aEvent);
1121 }
1122
1123 static constexpr auto const allowSynthesisForTests = []() -> bool {
1124 nsCOMPtr<nsIDragService> dragService =
1125 do_GetService("@mozilla.org/widget/dragservice;1");
1126 return dragService &&
1127 !dragService->GetNeverAllowSessionIsSynthesizedForTests();
1128 };
1129
1130 switch (aEvent->mMessage) {
1131 case eContextMenu:
1132 if (PointerLockManager::IsLocked()) {
1133 return NS_ERROR_DOM_INVALID_STATE_ERR;
1134 }
1135 break;
1136 case eMouseTouchDrag:
1137 mInTouchDrag = true;
1138 BeginTrackingDragGesture(aPresContext, *mouseEvent, aTargetFrame);
1139 break;
1140 case eMouseDown: {
1141 switch (mouseEvent->mButton) {
1142 case MouseButton::ePrimary:
1143 BeginTrackingDragGesture(aPresContext, *mouseEvent, aTargetFrame);
1144 mLastPrimaryButtonPressInfo.mClickCount = mouseEvent->mClickCount;
1145 PrepareForFollowingClickEvent(*mouseEvent);
1146 sNormalLMouseEventInProcess = true;
1147 break;
1148 case MouseButton::eMiddle:
1149 mLastMiddleButtonPressInfo.mClickCount = mouseEvent->mClickCount;
1150 PrepareForFollowingClickEvent(*mouseEvent);
1151 break;
1152 case MouseButton::eSecondary:
1153 mLastSecondaryButtonPressInfo.mClickCount = mouseEvent->mClickCount;
1154 PrepareForFollowingClickEvent(*mouseEvent);
1155 break;
1156 case MouseButton::eX1:
1157 case MouseButton::eX2:
1158 // XXX FIXME: We won't dispatch `auxclick` for 4th nor 5th button.
1159 break;
1160 default:
1161 break;
1162 }
1163 break;
1164 }
1165 case eMouseUp: {
1166 switch (mouseEvent->mButton) {
1167 case MouseButton::ePrimary:
1168 if (StaticPrefs::ui_click_hold_context_menus()) {
1169 KillClickHoldTimer();
1170 }
1171 mInTouchDrag = false;
1172 StopTrackingDragGesture(true);
1173 sNormalLMouseEventInProcess = false;
1174 // then fall through...
1175 [[fallthrough]];
1176 case MouseButton::eSecondary:
1177 case MouseButton::eMiddle: {
1178 RefPtr<EventStateManager> esm =
1179 ESMFromContentOrThis(aOverrideClickTarget);
1180 esm->PrepareForFollowingClickEvent(*mouseEvent, aOverrideClickTarget);
1181 break;
1182 }
1183 case MouseButton::eX1:
1184 case MouseButton::eX2:
1185 // XXX FIXME: We won't dispatch `auxclick` for 4th nor 5th button.
1186 break;
1187 default:
1188 break;
1189 }
1190 break;
1191 }
1192 case eMouseEnterIntoWidget:
1193 PointerEventHandler::UpdatePointerActiveState(mouseEvent, aTargetContent);
1194 // In some cases on e10s eMouseEnterIntoWidget
1195 // event was sent twice into child process of content.
1196 // (From specific widget code (sending is not permanent) and
1197 // from ESM::DispatchMouseOrPointerBoundaryEvent (sending is permanent)).
1198 // IsCrossProcessForwardingStopped() helps to suppress sending accidental
1199 // event from widget code.
1200 aEvent->StopCrossProcessForwarding();
1201 break;
1202 case eMouseExitFromWidget:
1203 // If this is a remote frame, we receive eMouseExitFromWidget from the
1204 // parent the mouse exits our content. Since the parent may update the
1205 // cursor while the mouse is outside our frame, and since PuppetWidget
1206 // caches the current cursor internally, re-entering our content (say from
1207 // over a window edge) wont update the cursor if the cached value and the
1208 // current cursor match. So when the mouse exits a remote frame, clear the
1209 // cached widget cursor so a proper update will occur when the mouse
1210 // re-enters.
1211 if (XRE_IsContentProcess()) {
1212 ClearCachedWidgetCursor(mCurrentTarget);
1213 }
1214
1215 // IsCrossProcessForwardingStopped() helps to suppress double event
1216 // sending into process of content. For more information see comment
1217 // above, at eMouseEnterIntoWidget case.
1218 aEvent->StopCrossProcessForwarding();
1219
1220 // If the event is not a top-level window or puppet widget exit, then it's
1221 // not really an exit --- we may have traversed widget boundaries but
1222 // we're still in our toplevel window or puppet widget.
1223 if (mouseEvent->mExitFrom.value() !=
1224 WidgetMouseEvent::ePlatformTopLevel &&
1225 mouseEvent->mExitFrom.value() != WidgetMouseEvent::ePuppet) {
1226 // Treat it as a synthetic move so we don't generate spurious
1227 // "exit" or "move" events. Any necessary "out" or "over" events
1228 // will be generated by GenerateMouseEnterExit
1229 mouseEvent->mMessage = eMouseMove;
1230 mouseEvent->mReason = WidgetMouseEvent::eSynthesized;
1231 // We need to generate pointer boundary events here because there is no
1232 // preceding pointer event dispatched for the eMouseExitFromWidget
1233 // event.
1234 GeneratePointerEnterExit(ePointerMove, mouseEvent);
1235 // then fall through...
1236 } else {
1237 MOZ_ASSERT_IF(XRE_IsParentProcess(),do { if (XRE_IsParentProcess()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(mouseEvent->mExitFrom
.value() == WidgetMouseEvent::ePlatformTopLevel)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mouseEvent->mExitFrom.value() == WidgetMouseEvent::ePlatformTopLevel
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mouseEvent->mExitFrom.value() == WidgetMouseEvent::ePlatformTopLevel"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 1239
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mouseEvent->mExitFrom.value() == WidgetMouseEvent::ePlatformTopLevel"
")"); do { MOZ_CrashSequence(__null, 1239); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1238 mouseEvent->mExitFrom.value() ==do { if (XRE_IsParentProcess()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(mouseEvent->mExitFrom
.value() == WidgetMouseEvent::ePlatformTopLevel)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mouseEvent->mExitFrom.value() == WidgetMouseEvent::ePlatformTopLevel
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mouseEvent->mExitFrom.value() == WidgetMouseEvent::ePlatformTopLevel"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 1239
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mouseEvent->mExitFrom.value() == WidgetMouseEvent::ePlatformTopLevel"
")"); do { MOZ_CrashSequence(__null, 1239); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1239 WidgetMouseEvent::ePlatformTopLevel)do { if (XRE_IsParentProcess()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(mouseEvent->mExitFrom
.value() == WidgetMouseEvent::ePlatformTopLevel)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mouseEvent->mExitFrom.value() == WidgetMouseEvent::ePlatformTopLevel
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mouseEvent->mExitFrom.value() == WidgetMouseEvent::ePlatformTopLevel"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 1239
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mouseEvent->mExitFrom.value() == WidgetMouseEvent::ePlatformTopLevel"
")"); do { MOZ_CrashSequence(__null, 1239); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1240 MOZ_ASSERT_IF(XRE_IsContentProcess(), mouseEvent->mExitFrom.value() ==do { if (XRE_IsContentProcess()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(mouseEvent->mExitFrom
.value() == WidgetMouseEvent::ePuppet)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mouseEvent->mExitFrom.value
() == WidgetMouseEvent::ePuppet))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("mouseEvent->mExitFrom.value() == WidgetMouseEvent::ePuppet"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 1241
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mouseEvent->mExitFrom.value() == WidgetMouseEvent::ePuppet"
")"); do { MOZ_CrashSequence(__null, 1241); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1241 WidgetMouseEvent::ePuppet)do { if (XRE_IsContentProcess()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(mouseEvent->mExitFrom
.value() == WidgetMouseEvent::ePuppet)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mouseEvent->mExitFrom.value
() == WidgetMouseEvent::ePuppet))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("mouseEvent->mExitFrom.value() == WidgetMouseEvent::ePuppet"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 1241
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mouseEvent->mExitFrom.value() == WidgetMouseEvent::ePuppet"
")"); do { MOZ_CrashSequence(__null, 1241); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1242 // We should synthetize corresponding pointer events
1243 GeneratePointerEnterExit(ePointerLeave, mouseEvent);
1244 GenerateMouseEnterExit(mouseEvent);
1245 // Remove the pointer from the active pointerId table.
1246 PointerEventHandler::UpdatePointerActiveState(mouseEvent);
1247 // This is really an exit and should stop here
1248 aEvent->mMessage = eVoidEvent;
1249 break;
1250 }
1251 [[fallthrough]];
1252 case ePointerDown:
1253 if (aEvent->mMessage == ePointerDown) {
1254 PointerEventHandler::UpdatePointerActiveState(mouseEvent,
1255 aTargetContent);
1256 PointerEventHandler::ImplicitlyCapturePointer(aTargetFrame, *aEvent);
1257 // https://html.spec.whatwg.org/multipage/interaction.html#activation-triggering-input-event
1258 if (mouseEvent->mInputSource == MouseEvent_Binding::MOZ_SOURCE_MOUSE) {
1259 NotifyTargetUserActivation(aEvent, aTargetContent);
1260 }
1261
1262 LightDismissOpenPopovers(aEvent, aTargetContent);
1263 LightDismissOpenDialogs(aEvent, aTargetContent);
1264 }
1265 [[fallthrough]];
1266 case eMouseMove:
1267 case ePointerMove:
1268 case ePointerRawUpdate: {
1269 if (aEvent->mMessage == ePointerMove) {
1270 PointerEventHandler::UpdatePointerActiveState(mouseEvent,
1271 aTargetContent);
1272 }
1273 if (!mInTouchDrag &&
1274 PointerEventHandler::IsDragAndDropEnabled(*mouseEvent)) {
1275 GenerateDragGesture(aPresContext, *mouseEvent);
1276 }
1277 // on the Mac, GenerateDragGesture() may not return until the drag
1278 // has completed and so |aTargetFrame| may have been deleted (moving
1279 // a bookmark, for example). If this is the case, however, we know
1280 // that ClearFrameRefs() has been called and it cleared out
1281 // |mCurrentTarget|. As a result, we should pass |mCurrentTarget|
1282 // into UpdateCursor().
1283 UpdateCursor(aPresContext, mouseEvent, mCurrentTarget, aStatus);
1284
1285 UpdateLastRefPointOfMouseEvent(mouseEvent);
1286 ResetPointerToWindowCenterWhilePointerLocked(mouseEvent);
1287 UpdateLastPointerPosition(mouseEvent);
1288
1289 GenerateMouseEnterExit(mouseEvent);
1290 // Flush pending layout changes, so that later mouse move events
1291 // will go to the right nodes.
1292 FlushLayout(aPresContext);
1293
1294 if (aEvent->mMessage == ePointerDown &&
1295 NeedsActiveContentChange(mouseEvent)) {
1296 nsCOMPtr<nsIContent> activeContent =
1297 mCurrentTarget ? mCurrentTarget->GetContent() : nullptr;
1298 if (activeContent && !activeContent->IsElement()) {
1299 if (nsIContent* parent = activeContent->GetFlattenedTreeParent()) {
1300 activeContent = parent;
1301 }
1302 }
1303 SetActiveManager(this, activeContent);
1304 }
1305 break;
1306 }
1307 case ePointerUp:
1308 LightDismissOpenPopovers(aEvent, aTargetContent);
1309 LightDismissOpenDialogs(aEvent, aTargetContent);
1310 GenerateMouseEnterExit(mouseEvent);
1311 if (mouseEvent->mInputSource != MouseEvent_Binding::MOZ_SOURCE_MOUSE) {
1312 NotifyTargetUserActivation(aEvent, aTargetContent);
1313 }
1314 if (NeedsActiveContentChange(mouseEvent)) {
1315 ClearGlobalActiveContent(this);
1316 }
1317 break;
1318 case ePointerGotCapture:
1319 GenerateMouseEnterExit(mouseEvent);
1320 break;
1321 case eDragStart:
1322 if (StaticPrefs::ui_click_hold_context_menus()) {
1323 // an external drag gesture event came in, not generated internally
1324 // by Gecko. Make sure we get rid of the click-hold timer.
1325 KillClickHoldTimer();
1326 }
1327 break;
1328 case eDragOver: {
1329 WidgetDragEvent* dragEvent = aEvent->AsDragEvent();
1330 MOZ_ASSERT(dragEvent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(dragEvent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(dragEvent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("dragEvent", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 1330); AnnotateMozCrashReason("MOZ_ASSERT" "(" "dragEvent" ")"
); do { MOZ_CrashSequence(__null, 1330); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1331 if (dragEvent->mFlags.mIsSynthesizedForTests &&
1332 allowSynthesisForTests()) {
1333 dragEvent->InitDropEffectForTests();
1334 }
1335 // Send the enter/exit events before eDrop.
1336 GenerateDragDropEnterExit(aPresContext, *dragEvent);
1337 break;
1338 }
1339 case eDrop: {
1340 if (aEvent->mFlags.mIsSynthesizedForTests && allowSynthesisForTests()) {
1341 MOZ_ASSERT(aEvent->AsDragEvent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->AsDragEvent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aEvent->AsDragEvent()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("aEvent->AsDragEvent()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 1341
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->AsDragEvent()"
")"); do { MOZ_CrashSequence(__null, 1341); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1342 aEvent->AsDragEvent()->InitDropEffectForTests();
1343 }
1344 break;
1345 }
1346 case eKeyPress: {
1347 WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
1348 if ((keyEvent->ModifiersMatchWithAccessKey(AccessKeyType::eChrome) ||
1349 keyEvent->ModifiersMatchWithAccessKey(AccessKeyType::eContent)) &&
1350 // If the key binding of this event is a native key binding, we
1351 // prioritize it.
1352 !HasNativeKeyBindings(aTargetContent, keyEvent)) {
1353 // If the eKeyPress event will be sent to a remote process, this
1354 // process needs to wait reply from the remote process for checking if
1355 // preceding eKeyDown event is consumed. If preceding eKeyDown event
1356 // is consumed in the remote process, BrowserChild won't send the event
1357 // back to this process. So, only when this process receives a reply
1358 // eKeyPress event in BrowserParent, we should handle accesskey in this
1359 // process.
1360 if (IsTopLevelRemoteTarget(GetFocusedElement())) {
1361 // However, if there is no accesskey target for the key combination,
1362 // we don't need to wait reply from the remote process. Otherwise,
1363 // Mark the event as waiting reply from remote process and stop
1364 // propagation in this process.
1365 if (CheckIfEventMatchesAccessKey(keyEvent, aPresContext)) {
1366 keyEvent->StopPropagation();
1367 keyEvent->MarkAsWaitingReplyFromRemoteProcess();
1368 }
1369 }
1370 // If the event target is in this process, we can handle accesskey now
1371 // since if preceding eKeyDown event was consumed, eKeyPress event
1372 // won't be dispatched by widget. So, coming eKeyPress event means
1373 // that the preceding eKeyDown event wasn't consumed in this case.
1374 else {
1375 AutoTArray<uint32_t, 10> accessCharCodes;
1376 keyEvent->GetAccessKeyCandidates(accessCharCodes);
1377
1378 if (HandleAccessKey(keyEvent, aPresContext, accessCharCodes)) {
1379 *aStatus = nsEventStatus_eConsumeNoDefault;
1380 }
1381 }
1382 }
1383 }
1384 // then fall through...
1385 [[fallthrough]];
1386 case eKeyDown:
1387 if (aEvent->mMessage == eKeyDown) {
1388 NotifyTargetUserActivation(aEvent, aTargetContent);
1389 }
1390 [[fallthrough]];
1391 case eKeyUp: {
1392 Element* element = GetFocusedElement();
1393 if (element) {
1394 mCurrentTargetContent = element;
1395 }
1396
1397 // NOTE: Don't refer TextComposition::IsComposing() since UI Events
1398 // defines that KeyboardEvent.isComposing is true when it's
1399 // dispatched after compositionstart and compositionend.
1400 // TextComposition::IsComposing() is false even before
1401 // compositionend if there is no composing string.
1402 // And also don't expose other document's composition state.
1403 // A native IME context is typically shared by multiple documents.
1404 // So, don't use GetTextCompositionFor(nsIWidget*) here.
1405 RefPtr<TextComposition> composition =
1406 IMEStateManager::GetTextCompositionFor(aPresContext);
1407 aEvent->AsKeyboardEvent()->mIsComposing = !!composition;
1408
1409 // Widget may need to perform default action for specific keyboard
1410 // event if it's not consumed. In this case, widget has already marked
1411 // the event as "waiting reply from remote process". However, we need
1412 // to reset it if the target (focused content) isn't in a remote process
1413 // because PresShell needs to check if it's marked as so before
1414 // dispatching events into the DOM tree.
1415 if (aEvent->IsWaitingReplyFromRemoteProcess() &&
1416 !aEvent->PropagationStopped() && !IsTopLevelRemoteTarget(element)) {
1417 aEvent->ResetWaitingReplyFromRemoteProcessState();
1418 }
1419 } break;
1420 case eWheel:
1421 case eWheelOperationStart:
1422 case eWheelOperationEnd: {
1423 NS_ASSERTION(aEvent->IsTrusted(),do { if (!(aEvent->IsTrusted())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Untrusted wheel event shouldn't be here", "aEvent->IsTrusted()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 1424
); MOZ_PretendNoReturn(); } } while (0)
1424 "Untrusted wheel event shouldn't be here")do { if (!(aEvent->IsTrusted())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Untrusted wheel event shouldn't be here", "aEvent->IsTrusted()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 1424
); MOZ_PretendNoReturn(); } } while (0)
;
1425 using DeltaModeCheckingState = WidgetWheelEvent::DeltaModeCheckingState;
1426
1427 if (Element* element = GetFocusedElement()) {
1428 mCurrentTargetContent = element;
1429 }
1430
1431 if (aEvent->mMessage != eWheel) {
1432 break;
1433 }
1434
1435 WidgetWheelEvent* wheelEvent = aEvent->AsWheelEvent();
1436 WheelPrefs::GetInstance()->ApplyUserPrefsToDelta(wheelEvent);
1437
1438 // If we won't dispatch a DOM event for this event, nothing to do anymore.
1439 if (!wheelEvent->IsAllowedToDispatchDOMEvent()) {
1440 break;
1441 }
1442
1443 if (StaticPrefs::dom_event_wheel_deltaMode_lines_always_disabled()) {
1444 wheelEvent->mDeltaModeCheckingState = DeltaModeCheckingState::Unchecked;
1445 } else if (ShouldAlwaysUseLineDeltas()) {
1446 wheelEvent->mDeltaModeCheckingState = DeltaModeCheckingState::Checked;
1447 } else {
1448 wheelEvent->mDeltaModeCheckingState = DeltaModeCheckingState::Unknown;
1449 }
1450
1451 // Init lineOrPageDelta values for line scroll events for some devices
1452 // on some platforms which might dispatch wheel events which don't
1453 // have lineOrPageDelta values. And also, if delta values are
1454 // customized by prefs, this recomputes them.
1455 DeltaAccumulator::GetInstance()->InitLineOrPageDelta(aTargetFrame, this,
1456 wheelEvent);
1457 } break;
1458 case eSetSelection: {
1459 const RefPtr<Element> focusedElement = GetFocusedElement();
1460 IMEStateManager::HandleSelectionEvent(aPresContext, focusedElement,
1461 aEvent->AsSelectionEvent());
1462 break;
1463 }
1464 case eContentCommandCut:
1465 case eContentCommandCopy:
1466 case eContentCommandPaste:
1467 case eContentCommandDelete:
1468 case eContentCommandUndo:
1469 case eContentCommandRedo:
1470 case eContentCommandPasteTransferable:
1471 case eContentCommandLookUpDictionary:
1472 DoContentCommandEvent(aEvent->AsContentCommandEvent());
1473 break;
1474 case eContentCommandInsertText:
1475 DoContentCommandInsertTextEvent(aEvent->AsContentCommandEvent());
1476 break;
1477 case eContentCommandReplaceText:
1478 DoContentCommandReplaceTextEvent(aEvent->AsContentCommandEvent());
1479 break;
1480 case eContentCommandScroll:
1481 DoContentCommandScrollEvent(aEvent->AsContentCommandEvent());
1482 break;
1483 case eCompositionStart:
1484 if (aEvent->IsTrusted()) {
1485 // If the event is trusted event, set the selected text to data of
1486 // composition event.
1487 WidgetCompositionEvent* compositionEvent = aEvent->AsCompositionEvent();
1488 WidgetQueryContentEvent querySelectedTextEvent(
1489 true, eQuerySelectedText, compositionEvent->mWidget);
1490 HandleQueryContentEvent(&querySelectedTextEvent);
1491 if (querySelectedTextEvent.FoundSelection()) {
1492 compositionEvent->mData = querySelectedTextEvent.mReply->DataRef();
1493 }
1494 NS_ASSERTION(querySelectedTextEvent.Succeeded(),do { if (!(querySelectedTextEvent.Succeeded())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Failed to get selected text", "querySelectedTextEvent.Succeeded()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 1495
); MOZ_PretendNoReturn(); } } while (0)
1495 "Failed to get selected text")do { if (!(querySelectedTextEvent.Succeeded())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Failed to get selected text", "querySelectedTextEvent.Succeeded()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 1495
); MOZ_PretendNoReturn(); } } while (0)
;
1496 }
1497 break;
1498 case eTouchStart:
1499 SetGestureDownPoint(*aEvent->AsTouchEvent());
1500 break;
1501 default:
1502 break;
1503 }
1504 return NS_OK;
1505}
1506
1507// Returns true if this event is likely an user activation for a link or
1508// a link-like button, where modifier keys are likely be used for controlling
1509// where the link is opened.
1510//
1511// The modifiers associated with the user activation is used for controlling
1512// where the `window.open` is opened into.
1513static bool CanReflectModifiersToUserActivation(WidgetInputEvent* aEvent) {
1514 MOZ_ASSERT(aEvent->mMessage == eKeyDown || aEvent->mMessage == ePointerDown ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->mMessage == eKeyDown || aEvent->mMessage
== ePointerDown || aEvent->mMessage == ePointerUp)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aEvent->mMessage == eKeyDown || aEvent->mMessage == ePointerDown
|| aEvent->mMessage == ePointerUp))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aEvent->mMessage == eKeyDown || aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 1515
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == eKeyDown || aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
")"); do { MOZ_CrashSequence(__null, 1515); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1515 aEvent->mMessage == ePointerUp)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->mMessage == eKeyDown || aEvent->mMessage
== ePointerDown || aEvent->mMessage == ePointerUp)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aEvent->mMessage == eKeyDown || aEvent->mMessage == ePointerDown
|| aEvent->mMessage == ePointerUp))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aEvent->mMessage == eKeyDown || aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 1515
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == eKeyDown || aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
")"); do { MOZ_CrashSequence(__null, 1515); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1516
1517 WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
1518 if (keyEvent) {
1519 return keyEvent->CanReflectModifiersToUserActivation();
1520 }
1521
1522 return true;
1523}
1524
1525void EventStateManager::NotifyTargetUserActivation(WidgetEvent* aEvent,
1526 nsIContent* aTargetContent) {
1527 if (!aEvent->IsTrusted()) {
1528 return;
1529 }
1530
1531 WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
1532 if (mouseEvent && !mouseEvent->IsReal()) {
1533 return;
1534 }
1535
1536 nsCOMPtr<nsINode> node = aTargetContent;
1537 if (!node) {
1538 return;
1539 }
1540
1541 Document* doc = node->OwnerDoc();
1542 if (!doc) {
1543 return;
1544 }
1545
1546 // Don't gesture activate for key events for keys which are likely
1547 // to be interaction with the browser, OS.
1548 WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
1549 if (keyEvent && !keyEvent->CanUserGestureActivateTarget()) {
1550 return;
1551 }
1552
1553 // Do not treat the click on scrollbar as a user interaction with the web
1554 // content.
1555 if (StaticPrefs::dom_user_activation_ignore_scrollbars() &&
1556 (aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp) &&
1557 aTargetContent->IsInNativeAnonymousSubtree()) {
1558 nsIContent* current = aTargetContent;
1559 do {
1560 nsIContent* root = current->GetClosestNativeAnonymousSubtreeRoot();
1561 if (!root) {
1562 break;
1563 }
1564 if (root->IsXULElement(nsGkAtoms::scrollbar)) {
1565 return;
1566 }
1567 current = root->GetParent();
1568 } while (current);
1569 }
1570
1571 MOZ_ASSERT(aEvent->mMessage == eKeyDown || aEvent->mMessage == ePointerDown ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->mMessage == eKeyDown || aEvent->mMessage
== ePointerDown || aEvent->mMessage == ePointerUp)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aEvent->mMessage == eKeyDown || aEvent->mMessage == ePointerDown
|| aEvent->mMessage == ePointerUp))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aEvent->mMessage == eKeyDown || aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 1572
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == eKeyDown || aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
")"); do { MOZ_CrashSequence(__null, 1572); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1572 aEvent->mMessage == ePointerUp)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->mMessage == eKeyDown || aEvent->mMessage
== ePointerDown || aEvent->mMessage == ePointerUp)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aEvent->mMessage == eKeyDown || aEvent->mMessage == ePointerDown
|| aEvent->mMessage == ePointerUp))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aEvent->mMessage == eKeyDown || aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 1572
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == eKeyDown || aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
")"); do { MOZ_CrashSequence(__null, 1572); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1573
1574 UserActivation::Modifiers modifiers;
1575 if (WidgetInputEvent* inputEvent = aEvent->AsInputEvent()) {
1576 if (CanReflectModifiersToUserActivation(inputEvent)) {
1577 if (inputEvent->IsShift()) {
1578 modifiers.SetShift();
1579 }
1580 if (inputEvent->IsMeta()) {
1581 modifiers.SetMeta();
1582 }
1583 if (inputEvent->IsControl()) {
1584 modifiers.SetControl();
1585 }
1586 if (inputEvent->IsAlt()) {
1587 modifiers.SetAlt();
1588 }
1589
1590 WidgetMouseEvent* mouseEvent = inputEvent->AsMouseEvent();
1591 if (mouseEvent) {
1592 if (mouseEvent->mButton == MouseButton::eMiddle) {
1593 modifiers.SetMiddleMouse();
1594 }
1595 }
1596 }
1597 }
1598 doc->NotifyUserGestureActivation(modifiers);
1599}
1600
1601// https://html.spec.whatwg.org/multipage/popover.html#popover-light-dismiss
1602void EventStateManager::LightDismissOpenPopovers(WidgetEvent* aEvent,
1603 nsIContent* aTargetContent) {
1604 MOZ_ASSERT(aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->mMessage == ePointerDown || aEvent->mMessage
== ePointerUp)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(aEvent->mMessage == ePointerDown
|| aEvent->mMessage == ePointerUp))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
" (" "Light dismiss must be called for pointer up/down only"
")", "/root/firefox-clang/dom/events/EventStateManager.cpp",
1605); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
") (" "Light dismiss must be called for pointer up/down only"
")"); do { MOZ_CrashSequence(__null, 1605); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1605 "Light dismiss must be called for pointer up/down only")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->mMessage == ePointerDown || aEvent->mMessage
== ePointerUp)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(aEvent->mMessage == ePointerDown
|| aEvent->mMessage == ePointerUp))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
" (" "Light dismiss must be called for pointer up/down only"
")", "/root/firefox-clang/dom/events/EventStateManager.cpp",
1605); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
") (" "Light dismiss must be called for pointer up/down only"
")"); do { MOZ_CrashSequence(__null, 1605); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1606
1607 // 1. Assert: event's isTrusted attribute is true.
1608 if (!aEvent->IsTrusted() || !aTargetContent) {
1609 return;
1610 }
1611
1612 // 2. Let target be event's target.
1613
1614 // 3. Let document be target's node document.
1615 RefPtr<Document> targetDoc(aTargetContent->OwnerDoc());
1616
1617 // 4. If the result of running topmost auto or hint popover given document is
1618 // null, then return.
1619 RefPtr<Element> topmostPopover =
1620 targetDoc->GetTopmostPopoverOf(PopoverAttributeState::Hint);
1621 if (!topmostPopover) {
1622 topmostPopover =
1623 targetDoc->GetTopmostPopoverOf(PopoverAttributeState::Auto);
1624 }
1625 if (!topmostPopover) {
1626 return;
1627 }
1628
1629 // 5. If event's type is "pointerdown": set document's popover pointerdown
1630 // target to the result of running topmost clicked popover given target.
1631 if (aEvent->mMessage == ePointerDown) {
1632 mPopoverPointerDownTarget = aTargetContent->GetTopmostClickedPopover();
1633 return;
1634 }
1635 // 6. If event's type is "pointerup":
1636
1637 // 6.1. Let ancestor be the result of running topmost clicked popover given
1638 // target.
1639 RefPtr<Element> ancestor = aTargetContent->GetTopmostClickedPopover();
1640
1641 // 6.2. Let sameTarget be true if ancestor is document's popover pointerdown
1642 // target.
1643 bool sameTarget =
1644 mPopoverPointerDownTarget == static_cast<nsINode*>(ancestor.get());
1645
1646 // 6.3. Set document's popover pointerdown target to null.
1647 mPopoverPointerDownTarget = nullptr;
1648
1649 // 6.4. If sameTarget is false, then return.
1650 if (!sameTarget) {
1651 return;
1652 }
1653
1654 // 6.5. Run hide popovers until given document, ancestor, false, and true.
1655 targetDoc->HidePopoversUntil(ancestor, false, true);
1656}
1657
1658// https://html.spec.whatwg.org/multipage/interactive-elements.html#run-light-dismiss-activities
1659// https://html.spec.whatwg.org/multipage/interactive-elements.html#light-dismiss-open-dialogs
1660void EventStateManager::LightDismissOpenDialogs(WidgetEvent* aEvent,
1661 nsIContent* aTargetContent) {
1662 // 1. Assert: event's isTrusted attribute is true.
1663 // 2. Let document be event's target's node document.
1664 // (Skipped - not applicable)
1665
1666 if (!StaticPrefs::dom_dialog_light_dismiss_enabled()) {
1667 return;
1668 }
1669
1670 MOZ_ASSERT(aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->mMessage == ePointerDown || aEvent->mMessage
== ePointerUp)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(aEvent->mMessage == ePointerDown
|| aEvent->mMessage == ePointerUp))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
" (" "Light dismiss must be called for pointer up/down only"
")", "/root/firefox-clang/dom/events/EventStateManager.cpp",
1671); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
") (" "Light dismiss must be called for pointer up/down only"
")"); do { MOZ_CrashSequence(__null, 1671); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1671 "Light dismiss must be called for pointer up/down only")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->mMessage == ePointerDown || aEvent->mMessage
== ePointerUp)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(aEvent->mMessage == ePointerDown
|| aEvent->mMessage == ePointerUp))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
" (" "Light dismiss must be called for pointer up/down only"
")", "/root/firefox-clang/dom/events/EventStateManager.cpp",
1671); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == ePointerDown || aEvent->mMessage == ePointerUp"
") (" "Light dismiss must be called for pointer up/down only"
")"); do { MOZ_CrashSequence(__null, 1671); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1672
1673 if (aEvent->mFlags.mDefaultPrevented || !aEvent->IsTrusted() ||
1674 !aTargetContent) {
1675 return;
1676 }
1677
1678 auto* doc = aTargetContent->OwnerDoc();
1679
1680 // 3. If document's open dialogs list is empty, then return.
1681 if (!doc->HasOpenDialogs()) {
1682 return;
1683 }
1684
1685 // 4. Let ancestor be the result of running nearest clicked dialog given
1686 // event.
1687 RefPtr<HTMLDialogElement> ancestor =
1688 aTargetContent->NearestClickedDialog(aEvent);
1689
1690 // 5. If event's type is "pointerdown", then set document's dialog pointerdown
1691 // target to ancestor.
1692 if (aEvent->mMessage == ePointerDown) {
1693 // XXX: "document's dialog pointerdown target" can be null, but
1694 // `SetLastDialogPointerdownTarget` takes `&` to avoid incidental nullptrs,
1695 // meaning we need to nullcheck `ancestor` & call
1696 // `ClearLastDialogPointerdownTarget` instead.
1697 if (!ancestor) {
1698 doc->ClearLastDialogPointerdownTarget();
1699 } else {
1700 doc->SetLastDialogPointerdownTarget(*ancestor);
1701 }
1702 return;
1703 }
1704
1705 MOZ_ASSERT(aEvent->mMessage == ePointerUp)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->mMessage == ePointerUp)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aEvent->mMessage == ePointerUp
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aEvent->mMessage == ePointerUp", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 1705); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == ePointerUp"
")"); do { MOZ_CrashSequence(__null, 1705); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1706
1707 // 6.1 Let sameTarget be true if ancestor is document's dialog pointerdown
1708 // target.
1709 RefPtr<HTMLDialogElement> lastDialog = doc->GetLastDialogPointerdownTarget();
1710 bool sameTarget = ancestor == lastDialog;
1711
1712 // 6.2 Set document's dialog pointerdown target to null.
1713 doc->ClearLastDialogPointerdownTarget();
1714
1715 // 6.3 If sameTarget is false, then return.
1716 if (!sameTarget) {
1717 return;
1718 }
1719
1720 // 6.4 Let topmostDialog be the last element of document's open dialogs list.
1721 RefPtr<HTMLDialogElement> topmostDialog = doc->GetTopMostOpenDialog();
1722
1723 // 6.5 If ancestor is topmostDialog, then return.
1724 if (ancestor == topmostDialog) {
1725 return;
1726 }
1727
1728 // 6.6 If topmostDialog's computed closed-by state is not Any, then return.
1729 if (!topmostDialog ||
1730 topmostDialog->GetClosedBy() != HTMLDialogElement::ClosedBy::Any) {
1731 return;
1732 }
1733
1734 // 7. Assert: topmostDialog's close watcher is not null.
1735
1736 // 8. Request to close topmostDialog's close watcher with false.
1737 const mozilla::dom::Optional<nsAString> returnValue;
1738 topmostDialog->RequestClose(returnValue);
1739}
1740
1741already_AddRefed<EventStateManager> EventStateManager::ESMFromContentOrThis(
1742 nsIContent* aContent) {
1743 if (aContent) {
1744 PresShell* presShell = aContent->OwnerDoc()->GetPresShell();
1745 if (presShell) {
1746 nsPresContext* prescontext = presShell->GetPresContext();
1747 if (prescontext) {
1748 RefPtr<EventStateManager> esm = prescontext->EventStateManager();
1749 if (esm) {
1750 return esm.forget();
1751 }
1752 }
1753 }
1754 }
1755
1756 RefPtr<EventStateManager> esm = this;
1757 return esm.forget();
1758}
1759
1760auto EventStateManager::GetLastMouseButtonPressInfo(int16_t aButton) const
1761 -> const LastMouseButtonPressInfo& {
1762 switch (aButton) {
1763 case MouseButton::ePrimary:
1764 return mLastPrimaryButtonPressInfo;
1765 case MouseButton::eMiddle:
1766 return mLastMiddleButtonPressInfo;
1767 case MouseButton::eSecondary:
1768 return mLastSecondaryButtonPressInfo;
1769 default:
1770 MOZ_ASSERT_UNREACHABLE("This button shouldn't use this method")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"This button shouldn't use this method" ")", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 1770); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "This button shouldn't use this method"
")"); do { MOZ_CrashSequence(__null, 1770); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1771 return mLastPrimaryButtonPressInfo;
1772 }
1773}
1774
1775void EventStateManager::HandleQueryContentEvent(
1776 WidgetQueryContentEvent* aEvent) {
1777 switch (aEvent->mMessage) {
1778 case eQuerySelectedText:
1779 case eQueryTextContent:
1780 case eQueryCaretRect:
1781 case eQueryTextRect:
1782 case eQueryEditorRect:
1783 if (!IsTargetCrossProcess(aEvent)) {
1784 break;
1785 }
1786 // Will not be handled locally, remote the event
1787 GetCrossProcessTarget()->HandleQueryContentEvent(*aEvent);
1788 return;
1789 // Following events have not been supported in e10s mode yet.
1790 case eQueryContentState:
1791 case eQuerySelectionAsTransferable:
1792 case eQueryCharacterAtPoint:
1793 case eQueryDOMWidgetHittest:
1794 case eQueryTextRectArray:
1795 case eQueryDropTargetHittest:
1796 break;
1797 default:
1798 return;
1799 }
1800
1801 // If there is an IMEContentObserver, we need to handle QueryContentEvent
1802 // with it.
1803 // eQueryDropTargetHittest is not really an IME event, though
1804 if (mIMEContentObserver && aEvent->mMessage != eQueryDropTargetHittest) {
1805 RefPtr<IMEContentObserver> contentObserver = mIMEContentObserver;
1806 contentObserver->HandleQueryContentEvent(aEvent);
1807 return;
1808 }
1809
1810 ContentEventHandler handler(mPresContext);
1811 handler.HandleQueryContentEvent(aEvent);
1812}
1813
1814static AccessKeyType GetAccessKeyTypeFor(nsISupports* aDocShell) {
1815 nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(aDocShell));
1816 if (!treeItem) {
1817 return AccessKeyType::eNone;
1818 }
1819
1820 switch (treeItem->ItemType()) {
1821 case nsIDocShellTreeItem::typeChrome:
1822 return AccessKeyType::eChrome;
1823 case nsIDocShellTreeItem::typeContent:
1824 return AccessKeyType::eContent;
1825 default:
1826 return AccessKeyType::eNone;
1827 }
1828}
1829
1830static bool IsAccessKeyTarget(Element* aElement, nsAString& aKey) {
1831 // Use GetAttr because we want Unicode case=insensitive matching
1832 // XXXbz shouldn't this be case-sensitive, per spec?
1833 nsString contentKey;
1834 if (!aElement || !aElement->GetAttr(nsGkAtoms::accesskey, contentKey) ||
1835 !contentKey.Equals(aKey, nsCaseInsensitiveStringComparator)) {
1836 return false;
1837 }
1838
1839 if (!aElement->IsXULElement() &&
1840 !nsContentUtils::IsChromeDoc(aElement->OwnerDoc())) {
1841 return true;
1842 }
1843
1844 // For XUL and chrome docs we do visibility checks.
1845 nsIFrame* frame = aElement->GetPrimaryFrame();
1846 if (!frame) {
1847 return false;
1848 }
1849
1850 if (frame->IsFocusable()) {
1851 return true;
1852 }
1853
1854 if (!frame->IsVisibleConsideringAncestors()) {
1855 return false;
1856 }
1857
1858 // XUL controls can be activated.
1859 nsCOMPtr<nsIDOMXULControlElement> control = aElement->AsXULControl();
1860 if (control) {
1861 return true;
1862 }
1863
1864 // label elements are never focusable, so we need to check for them
1865 // explicitly before giving up.
1866 if (aElement->IsXULElement(nsGkAtoms::label) ||
1867 aElement->IsHTMLElement(nsGkAtoms::label)) {
1868 return true;
1869 }
1870
1871 return false;
1872}
1873
1874bool EventStateManager::CheckIfEventMatchesAccessKey(
1875 WidgetKeyboardEvent* aEvent, nsPresContext* aPresContext) {
1876 AutoTArray<uint32_t, 10> accessCharCodes;
1877 aEvent->GetAccessKeyCandidates(accessCharCodes);
1878 return WalkESMTreeToHandleAccessKey(aEvent, aPresContext, accessCharCodes,
1879 nullptr, eAccessKeyProcessingNormal,
1880 false);
1881}
1882
1883bool EventStateManager::LookForAccessKeyAndExecute(
1884 nsTArray<uint32_t>& aAccessCharCodes, bool aIsTrustedEvent, bool aIsRepeat,
1885 bool aExecute) {
1886 int32_t count, start = -1;
1887 if (Element* focusedElement = GetFocusedElement()) {
1888 start = mAccessKeys.IndexOf(focusedElement);
1889 if (start == -1 && focusedElement->IsInNativeAnonymousSubtree()) {
1890 start = mAccessKeys.IndexOf(Element::FromNodeOrNull(
1891 focusedElement->GetClosestNativeAnonymousSubtreeRootParentOrHost()));
1892 }
1893 }
1894 RefPtr<Element> element;
1895 int32_t length = mAccessKeys.Count();
1896 for (uint32_t i = 0; i < aAccessCharCodes.Length(); ++i) {
1897 uint32_t ch = aAccessCharCodes[i];
1898 nsAutoString accessKey;
1899 AppendUCS4ToUTF16(ch, accessKey);
1900 for (count = 1; count <= length; ++count) {
1901 // mAccessKeys always stores Element instances.
1902 MOZ_DIAGNOSTIC_ASSERT(length == mAccessKeys.Count())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(length == mAccessKeys.Count())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(length == mAccessKeys.Count(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("length == mAccessKeys.Count()", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 1902); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "length == mAccessKeys.Count()"
")"); do { MOZ_CrashSequence(__null, 1902); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1903 element = mAccessKeys[(start + count) % length];
1904 if (IsAccessKeyTarget(element, accessKey)) {
1905 if (!aExecute) {
1906 return true;
1907 }
1908 Document* doc = element->OwnerDoc();
1909 const bool shouldActivate = [&] {
1910 if (!StaticPrefs::accessibility_accesskeycausesactivation()) {
1911 return false;
1912 }
1913 if (aIsRepeat && nsContentUtils::IsChromeDoc(doc)) {
1914 return false;
1915 }
1916
1917 // XXXedgar, Bug 1700646, maybe we could use other data structure to
1918 // make searching target with same accesskey easier, and current setup
1919 // could not ensure we cycle the target with tree order.
1920 int32_t j = 0;
1921 while (++j < length) {
1922 Element* el = mAccessKeys[(start + count + j) % length];
1923 if (IsAccessKeyTarget(el, accessKey)) {
1924 return false;
1925 }
1926 }
1927 return true;
1928 }();
1929
1930 // TODO(bug 1641171): This shouldn't be needed if we considered the
1931 // accesskey combination properly.
1932 if (aIsTrustedEvent) {
1933 doc->NotifyUserGestureActivation();
1934 }
1935
1936 auto result =
1937 element->PerformAccesskey(shouldActivate, aIsTrustedEvent);
1938 if (result.isOk()) {
1939 if (result.unwrap() && aIsTrustedEvent) {
1940 // If this is a child process, inform the parent that we want the
1941 // focus, but pass false since we don't want to change the window
1942 // order.
1943 nsIDocShell* docShell = mPresContext->GetDocShell();
1944 nsCOMPtr<nsIBrowserChild> child =
1945 docShell ? docShell->GetBrowserChild() : nullptr;
1946 if (child) {
1947 child->SendRequestFocus(false, CallerType::System);
1948 }
1949 }
1950 return true;
1951 }
1952 }
1953 }
1954 }
1955 return false;
1956}
1957
1958// static
1959void EventStateManager::GetAccessKeyLabelPrefix(Element* aElement,
1960 nsAString& aPrefix) {
1961 aPrefix.Truncate();
1962 nsAutoString separator, modifierText;
1963 nsContentUtils::GetModifierSeparatorText(separator);
1964
1965 AccessKeyType accessKeyType =
1966 GetAccessKeyTypeFor(aElement->OwnerDoc()->GetDocShell());
1967 if (accessKeyType == AccessKeyType::eNone) {
1968 return;
1969 }
1970 Modifiers modifiers = WidgetKeyboardEvent::AccessKeyModifiers(accessKeyType);
1971 if (modifiers == MODIFIER_NONE) {
1972 return;
1973 }
1974
1975 if (modifiers & MODIFIER_CONTROL) {
1976 nsContentUtils::GetControlText(modifierText);
1977 aPrefix.Append(modifierText + separator);
1978 }
1979 if (modifiers & MODIFIER_META) {
1980 nsContentUtils::GetCommandOrWinText(modifierText);
1981 aPrefix.Append(modifierText + separator);
1982 }
1983 if (modifiers & MODIFIER_ALT) {
1984 nsContentUtils::GetAltText(modifierText);
1985 aPrefix.Append(modifierText + separator);
1986 }
1987 if (modifiers & MODIFIER_SHIFT) {
1988 nsContentUtils::GetShiftText(modifierText);
1989 aPrefix.Append(modifierText + separator);
1990 }
1991}
1992
1993struct MOZ_STACK_CLASS AccessKeyInfo {
1994 WidgetKeyboardEvent* event;
1995 nsTArray<uint32_t>& charCodes;
1996
1997 AccessKeyInfo(WidgetKeyboardEvent* aEvent, nsTArray<uint32_t>& aCharCodes)
1998 : event(aEvent), charCodes(aCharCodes) {}
1999};
2000
2001bool EventStateManager::WalkESMTreeToHandleAccessKey(
2002 WidgetKeyboardEvent* aEvent, nsPresContext* aPresContext,
2003 nsTArray<uint32_t>& aAccessCharCodes, nsIDocShellTreeItem* aBubbledFrom,
2004 ProcessingAccessKeyState aAccessKeyState, bool aExecute) {
2005 EnsureDocument(mPresContext);
2006 nsCOMPtr<nsIDocShell> docShell = aPresContext->GetDocShell();
2007 if (NS_WARN_IF(!docShell)NS_warn_if_impl(!docShell, "!docShell", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 2007)
|| NS_WARN_IF(!mDocument)NS_warn_if_impl(!mDocument, "!mDocument", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 2007)
) {
2008 return false;
2009 }
2010 AccessKeyType accessKeyType = GetAccessKeyTypeFor(docShell);
2011 if (accessKeyType == AccessKeyType::eNone) {
2012 return false;
2013 }
2014 // Alt or other accesskey modifier is down, we may need to do an accesskey.
2015 if (mAccessKeys.Count() > 0 &&
2016 aEvent->ModifiersMatchWithAccessKey(accessKeyType)) {
2017 // Someone registered an accesskey. Find and activate it.
2018 if (LookForAccessKeyAndExecute(aAccessCharCodes, aEvent->IsTrusted(),
2019 aEvent->mIsRepeat, aExecute)) {
2020 return true;
2021 }
2022 }
2023
2024 int32_t childCount;
2025 docShell->GetInProcessChildCount(&childCount);
2026 for (int32_t counter = 0; counter < childCount; counter++) {
2027 // Not processing the child which bubbles up the handling
2028 nsCOMPtr<nsIDocShellTreeItem> subShellItem;
2029 docShell->GetInProcessChildAt(counter, getter_AddRefs(subShellItem));
2030 if (aAccessKeyState == eAccessKeyProcessingUp &&
2031 subShellItem == aBubbledFrom) {
2032 continue;
2033 }
2034
2035 nsCOMPtr<nsIDocShell> subDS = do_QueryInterface(subShellItem);
2036 if (subDS && IsShellVisible(subDS)) {
2037 // Guarantee subPresShell lifetime while we're handling access key
2038 // since somebody may assume that it won't be deleted before the
2039 // corresponding nsPresContext and EventStateManager.
2040 RefPtr<PresShell> subPresShell = subDS->GetPresShell();
2041
2042 // Docshells need not have a presshell (eg. display:none
2043 // iframes, docshells in transition between documents, etc).
2044 if (!subPresShell) {
2045 // Oh, well. Just move on to the next child
2046 continue;
2047 }
2048
2049 RefPtr<nsPresContext> subPresContext = subPresShell->GetPresContext();
2050
2051 RefPtr<EventStateManager> esm =
2052 static_cast<EventStateManager*>(subPresContext->EventStateManager());
2053
2054 if (esm && esm->WalkESMTreeToHandleAccessKey(
2055 aEvent, subPresContext, aAccessCharCodes, nullptr,
2056 eAccessKeyProcessingDown, aExecute)) {
2057 return true;
2058 }
2059 }
2060 } // if end . checking all sub docshell ends here.
2061
2062 // bubble up the process to the parent docshell if necessary
2063 if (eAccessKeyProcessingDown != aAccessKeyState) {
2064 nsCOMPtr<nsIDocShellTreeItem> parentShellItem;
2065 docShell->GetInProcessParent(getter_AddRefs(parentShellItem));
2066 nsCOMPtr<nsIDocShell> parentDS = do_QueryInterface(parentShellItem);
2067 if (parentDS) {
2068 // Guarantee parentPresShell lifetime while we're handling access key
2069 // since somebody may assume that it won't be deleted before the
2070 // corresponding nsPresContext and EventStateManager.
2071 RefPtr<PresShell> parentPresShell = parentDS->GetPresShell();
2072 NS_ASSERTION(parentPresShell,do { if (!(parentPresShell)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Our PresShell exists but the parent's does not?", "parentPresShell"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2073
); MOZ_PretendNoReturn(); } } while (0)
2073 "Our PresShell exists but the parent's does not?")do { if (!(parentPresShell)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Our PresShell exists but the parent's does not?", "parentPresShell"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2073
); MOZ_PretendNoReturn(); } } while (0)
;
2074
2075 RefPtr<nsPresContext> parentPresContext =
2076 parentPresShell->GetPresContext();
2077 NS_ASSERTION(parentPresContext, "PresShell without PresContext")do { if (!(parentPresContext)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "PresShell without PresContext", "parentPresContext", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 2077); MOZ_PretendNoReturn(); } } while (0)
;
2078
2079 RefPtr<EventStateManager> esm = static_cast<EventStateManager*>(
2080 parentPresContext->EventStateManager());
2081 if (esm && esm->WalkESMTreeToHandleAccessKey(
2082 aEvent, parentPresContext, aAccessCharCodes, docShell,
2083 eAccessKeyProcessingDown, aExecute)) {
2084 return true;
2085 }
2086 }
2087 } // if end. bubble up process
2088
2089 // If the content access key modifier is pressed, try remote children
2090 if (aExecute &&
2091 aEvent->ModifiersMatchWithAccessKey(AccessKeyType::eContent) &&
2092 mDocument && mDocument->GetWindow()) {
2093 // If the focus is currently on a node with a BrowserParent, the key event
2094 // should've gotten forwarded to the child process and HandleAccessKey
2095 // called from there.
2096 if (BrowserParent::GetFrom(GetFocusedElement())) {
2097 // If access key may be only in remote contents, this method won't handle
2098 // access key synchronously. In this case, only reply event should reach
2099 // here.
2100 MOZ_ASSERT(aEvent->IsHandledInRemoteProcess() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->IsHandledInRemoteProcess() || !aEvent->
IsWaitingReplyFromRemoteProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aEvent->IsHandledInRemoteProcess
() || !aEvent->IsWaitingReplyFromRemoteProcess()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aEvent->IsHandledInRemoteProcess() || !aEvent->IsWaitingReplyFromRemoteProcess()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2101
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->IsHandledInRemoteProcess() || !aEvent->IsWaitingReplyFromRemoteProcess()"
")"); do { MOZ_CrashSequence(__null, 2101); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2101 !aEvent->IsWaitingReplyFromRemoteProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->IsHandledInRemoteProcess() || !aEvent->
IsWaitingReplyFromRemoteProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aEvent->IsHandledInRemoteProcess
() || !aEvent->IsWaitingReplyFromRemoteProcess()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aEvent->IsHandledInRemoteProcess() || !aEvent->IsWaitingReplyFromRemoteProcess()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2101
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->IsHandledInRemoteProcess() || !aEvent->IsWaitingReplyFromRemoteProcess()"
")"); do { MOZ_CrashSequence(__null, 2101); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2102 }
2103 // If focus is somewhere else, then we need to check the remote children.
2104 // However, if the event has already been handled in a remote process,
2105 // then, focus is moved from the remote process after posting the event.
2106 // In such case, we shouldn't retry to handle access keys in remote
2107 // processes.
2108 else if (!aEvent->IsHandledInRemoteProcess()) {
2109 AccessKeyInfo accessKeyInfo(aEvent, aAccessCharCodes);
2110 nsContentUtils::CallOnAllRemoteChildren(
2111 mDocument->GetWindow(),
2112 [&accessKeyInfo](BrowserParent* aBrowserParent) -> CallState {
2113 // Only forward accesskeys for the active tab.
2114 if (aBrowserParent->GetDocShellIsActive()) {
2115 // Even if there is no target for the accesskey in this process,
2116 // the event may match with a content accesskey. If so, the
2117 // keyboard event should be handled with reply event for
2118 // preventing double action. (e.g., Alt+Shift+F on Windows may
2119 // focus a content in remote and open "File" menu.)
2120 accessKeyInfo.event->StopPropagation();
2121 accessKeyInfo.event->MarkAsWaitingReplyFromRemoteProcess();
2122 aBrowserParent->HandleAccessKey(*accessKeyInfo.event,
2123 accessKeyInfo.charCodes);
2124 return CallState::Stop;
2125 }
2126
2127 return CallState::Continue;
2128 });
2129 }
2130 }
2131
2132 return false;
2133} // end of HandleAccessKey
2134
2135static BrowserParent* GetBrowserParentAncestor(BrowserParent* aBrowserParent) {
2136 MOZ_ASSERT(aBrowserParent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aBrowserParent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aBrowserParent))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aBrowserParent"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2136
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowserParent" ")"
); do { MOZ_CrashSequence(__null, 2136); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2137
2138 BrowserBridgeParent* bbp = aBrowserParent->GetBrowserBridgeParent();
2139 if (!bbp) {
2140 return nullptr;
2141 }
2142
2143 return bbp->Manager();
2144}
2145
2146static void DispatchCrossProcessMouseExitEvents(WidgetMouseEvent* aMouseEvent,
2147 BrowserParent* aRemoteTarget,
2148 BrowserParent* aStopAncestor,
2149 bool aIsReallyExit) {
2150 MOZ_ASSERT(aMouseEvent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMouseEvent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMouseEvent))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aMouseEvent", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 2150); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseEvent"
")"); do { MOZ_CrashSequence(__null, 2150); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2151 MOZ_ASSERT(aRemoteTarget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRemoteTarget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRemoteTarget))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aRemoteTarget",
"/root/firefox-clang/dom/events/EventStateManager.cpp", 2151
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRemoteTarget" ")"
); do { MOZ_CrashSequence(__null, 2151); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2152 MOZ_ASSERT(aRemoteTarget != aStopAncestor)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRemoteTarget != aStopAncestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRemoteTarget != aStopAncestor
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aRemoteTarget != aStopAncestor", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 2152); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRemoteTarget != aStopAncestor"
")"); do { MOZ_CrashSequence(__null, 2152); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2153 MOZ_ASSERT_IF(aStopAncestor, nsContentUtils::GetCommonBrowserParentAncestor(do { if (aStopAncestor) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(nsContentUtils::GetCommonBrowserParentAncestor
( aRemoteTarget, aStopAncestor))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(nsContentUtils::GetCommonBrowserParentAncestor
( aRemoteTarget, aStopAncestor)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("nsContentUtils::GetCommonBrowserParentAncestor( aRemoteTarget, aStopAncestor)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2154
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nsContentUtils::GetCommonBrowserParentAncestor( aRemoteTarget, aStopAncestor)"
")"); do { MOZ_CrashSequence(__null, 2154); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2154 aRemoteTarget, aStopAncestor))do { if (aStopAncestor) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(nsContentUtils::GetCommonBrowserParentAncestor
( aRemoteTarget, aStopAncestor))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(nsContentUtils::GetCommonBrowserParentAncestor
( aRemoteTarget, aStopAncestor)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("nsContentUtils::GetCommonBrowserParentAncestor( aRemoteTarget, aStopAncestor)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2154
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nsContentUtils::GetCommonBrowserParentAncestor( aRemoteTarget, aStopAncestor)"
")"); do { MOZ_CrashSequence(__null, 2154); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2155
2156 while (aRemoteTarget != aStopAncestor) {
2157 UniquePtr<WidgetMouseEvent> mouseExitEvent =
2158 CreateMouseOrPointerWidgetEvent(aMouseEvent, eMouseExitFromWidget,
2159 aMouseEvent->mRelatedTarget);
2160 mouseExitEvent->mExitFrom =
2161 Some(aIsReallyExit ? WidgetMouseEvent::ePuppet
2162 : WidgetMouseEvent::ePuppetParentToPuppetChild);
2163
2164 auto ContentReactsToPointerEvents = [](BrowserParent* aRemoteTarget) {
2165 if (Element* owner = aRemoteTarget->GetOwnerElement()) {
2166 if (nsSubDocumentFrame* subDocFrame =
2167 do_QueryFrame(owner->GetPrimaryFrame())) {
2168 return subDocFrame->ContentReactsToPointerEvents();
2169 }
2170 }
2171 return true;
2172 };
2173
2174 if (ContentReactsToPointerEvents(aRemoteTarget)) {
2175 aRemoteTarget->SendRealMouseEvent(*mouseExitEvent);
2176 }
2177
2178 aRemoteTarget = GetBrowserParentAncestor(aRemoteTarget);
2179 }
2180}
2181
2182void EventStateManager::DispatchCrossProcessEvent(WidgetEvent* aEvent,
2183 BrowserParent* aRemoteTarget,
2184 nsEventStatus* aStatus) {
2185 MOZ_ASSERT(aEvent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aEvent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aEvent", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 2185); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent" ")"
); do { MOZ_CrashSequence(__null, 2185); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2186 MOZ_ASSERT(aRemoteTarget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRemoteTarget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRemoteTarget))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aRemoteTarget",
"/root/firefox-clang/dom/events/EventStateManager.cpp", 2186
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRemoteTarget" ")"
); do { MOZ_CrashSequence(__null, 2186); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2187 MOZ_ASSERT(aStatus)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStatus)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aStatus))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aStatus", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 2187); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStatus" ")"
); do { MOZ_CrashSequence(__null, 2187); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2188
2189 RefPtr<BrowserParent> remote = aRemoteTarget;
2190
2191 WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
2192 bool isContextMenuKey = mouseEvent && mouseEvent->IsContextMenuKeyEvent();
2193 if (aEvent->mClass == eKeyboardEventClass || isContextMenuKey) {
2194 // APZ attaches a LayersId to hit-testable events, for keyboard events,
2195 // we use focus.
2196 BrowserParent* preciseRemote = BrowserParent::GetFocused();
2197 if (preciseRemote) {
2198 remote = preciseRemote;
2199 }
2200 // else there is a race between layout and focus tracking,
2201 // so fall back to delivering the event to the topmost child process.
2202 } else if (aEvent->mLayersId.IsValid()) {
2203 RefPtr<BrowserParent> preciseRemote =
2204 BrowserParent::GetBrowserParentFromLayersId(aEvent->mLayersId);
2205 if (preciseRemote) {
2206 remote = preciseRemote.forget();
2207 }
2208 // else there is a race between APZ and the LayersId to BrowserParent
2209 // mapping, so fall back to delivering the event to the topmost child
2210 // process.
2211 }
2212
2213 MOZ_ASSERT(aEvent->mMessage != ePointerClick)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->mMessage != ePointerClick)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aEvent->mMessage != ePointerClick
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aEvent->mMessage != ePointerClick", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 2213); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage != ePointerClick"
")"); do { MOZ_CrashSequence(__null, 2213); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2214 MOZ_ASSERT(aEvent->mMessage != ePointerAuxClick)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->mMessage != ePointerAuxClick)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aEvent->mMessage != ePointerAuxClick))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aEvent->mMessage != ePointerAuxClick"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2214
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage != ePointerAuxClick"
")"); do { MOZ_CrashSequence(__null, 2214); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2215
2216 // SendReal* will transform the coordinate to the child process coordinate
2217 // space. So restore the coordinate after the event has been dispatched to the
2218 // child process to avoid using the transformed coordinate afterward.
2219 AutoRestore<LayoutDeviceIntPoint> restore(aEvent->mRefPoint);
2220 switch (aEvent->mClass) {
2221 case ePointerEventClass:
2222 MOZ_ASSERT(aEvent->mMessage == eContextMenu)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->mMessage == eContextMenu)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aEvent->mMessage == eContextMenu
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aEvent->mMessage == eContextMenu", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 2222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == eContextMenu"
")"); do { MOZ_CrashSequence(__null, 2222); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2223 [[fallthrough]];
2224 case eMouseEventClass: {
2225 BrowserParent* oldRemote = BrowserParent::GetLastMouseRemoteTarget();
2226
2227 // If this is a eMouseExitFromWidget event, need to redirect the event to
2228 // the last remote and and notify all its ancestors about the exit, if
2229 // any.
2230 if (mouseEvent->mMessage == eMouseExitFromWidget) {
2231 MOZ_ASSERT(mouseEvent->mExitFrom.value() == WidgetMouseEvent::ePuppet)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mouseEvent->mExitFrom.value() == WidgetMouseEvent
::ePuppet)>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(mouseEvent->mExitFrom.value() ==
WidgetMouseEvent::ePuppet))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mouseEvent->mExitFrom.value() == WidgetMouseEvent::ePuppet"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2231
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mouseEvent->mExitFrom.value() == WidgetMouseEvent::ePuppet"
")"); do { MOZ_CrashSequence(__null, 2231); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2232 MOZ_ASSERT(mouseEvent->mReason == WidgetMouseEvent::eReal)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mouseEvent->mReason == WidgetMouseEvent::eReal)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mouseEvent->mReason == WidgetMouseEvent::eReal)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("mouseEvent->mReason == WidgetMouseEvent::eReal"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2232
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mouseEvent->mReason == WidgetMouseEvent::eReal"
")"); do { MOZ_CrashSequence(__null, 2232); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2233 MOZ_ASSERT(!mouseEvent->mLayersId.IsValid())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mouseEvent->mLayersId.IsValid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mouseEvent->mLayersId.IsValid
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mouseEvent->mLayersId.IsValid()", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 2233); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mouseEvent->mLayersId.IsValid()"
")"); do { MOZ_CrashSequence(__null, 2233); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2234 MOZ_ASSERT(remote->GetBrowserHost())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(remote->GetBrowserHost())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(remote->GetBrowserHost())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("remote->GetBrowserHost()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2234
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "remote->GetBrowserHost()"
")"); do { MOZ_CrashSequence(__null, 2234); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2235
2236 if (oldRemote && oldRemote != remote) {
2237 (void)NS_WARN_IF(nsContentUtils::GetCommonBrowserParentAncestor(NS_warn_if_impl(nsContentUtils::GetCommonBrowserParentAncestor
( remote, oldRemote) != remote, "nsContentUtils::GetCommonBrowserParentAncestor( remote, oldRemote) != remote"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2238
)
2238 remote, oldRemote) != remote)NS_warn_if_impl(nsContentUtils::GetCommonBrowserParentAncestor
( remote, oldRemote) != remote, "nsContentUtils::GetCommonBrowserParentAncestor( remote, oldRemote) != remote"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2238
)
;
2239 remote = oldRemote;
2240 }
2241
2242 DispatchCrossProcessMouseExitEvents(mouseEvent, remote, nullptr, true);
2243 return;
2244 }
2245
2246 if (BrowserParent* pointerLockedRemote =
2247 PointerLockManager::GetLockedRemoteTarget()) {
2248 remote = pointerLockedRemote;
2249 } else if (BrowserParent* pointerCapturedRemote =
2250 PointerEventHandler::GetPointerCapturingRemoteTarget(
2251 mouseEvent->pointerId)) {
2252 remote = pointerCapturedRemote;
2253 } else if (BrowserParent* capturingRemote =
2254 PresShell::GetCapturingRemoteTarget()) {
2255 remote = capturingRemote;
2256 }
2257
2258 // If a mouse is over a remote target A, and then moves to
2259 // remote target B, we'd deliver the event directly to remote target B
2260 // after the moving, A would never get notified that the mouse left.
2261 // So we generate a exit event to notify A after the move.
2262 // XXXedgar, if the synthesized mouse events could deliver to the correct
2263 // process directly (see
2264 // https://bugzilla.mozilla.org/show_bug.cgi?id=1549355), we probably
2265 // don't need to check mReason then.
2266 if (mouseEvent->mReason == WidgetMouseEvent::eReal &&
2267 remote != oldRemote) {
2268 MOZ_ASSERT(mouseEvent->mMessage != eMouseExitFromWidget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mouseEvent->mMessage != eMouseExitFromWidget)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mouseEvent->mMessage != eMouseExitFromWidget))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("mouseEvent->mMessage != eMouseExitFromWidget"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2268
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mouseEvent->mMessage != eMouseExitFromWidget"
")"); do { MOZ_CrashSequence(__null, 2268); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2269 if (oldRemote) {
2270 BrowserParent* commonAncestor =
2271 nsContentUtils::GetCommonBrowserParentAncestor(remote, oldRemote);
2272 if (commonAncestor == oldRemote) {
2273 // Mouse moves to the inner OOP frame, it is not a really exit.
2274 DispatchCrossProcessMouseExitEvents(
2275 mouseEvent, GetBrowserParentAncestor(remote),
2276 GetBrowserParentAncestor(commonAncestor), false);
2277 } else if (commonAncestor == remote) {
2278 // Mouse moves to the outer OOP frame, it is a really exit.
2279 DispatchCrossProcessMouseExitEvents(mouseEvent, oldRemote,
2280 commonAncestor, true);
2281 } else {
2282 // Mouse moves to OOP frame in other subtree, it is a really exit,
2283 // need to notify all its ancestors before common ancestor about the
2284 // exit.
2285 DispatchCrossProcessMouseExitEvents(mouseEvent, oldRemote,
2286 commonAncestor, true);
2287 if (commonAncestor) {
2288 UniquePtr<WidgetMouseEvent> mouseExitEvent =
2289 CreateMouseOrPointerWidgetEvent(mouseEvent,
2290 eMouseExitFromWidget,
2291 mouseEvent->mRelatedTarget);
2292 mouseExitEvent->mExitFrom =
2293 Some(WidgetMouseEvent::ePuppetParentToPuppetChild);
2294 commonAncestor->SendRealMouseEvent(*mouseExitEvent);
2295 }
2296 }
2297 }
2298
2299 if (mouseEvent->mMessage != eMouseExitFromWidget &&
2300 mouseEvent->mMessage != eMouseEnterIntoWidget) {
2301 // This is to make cursor would be updated correctly.
2302 remote->MouseEnterIntoWidget();
2303 }
2304 }
2305
2306 remote->SendRealMouseEvent(*mouseEvent);
2307 return;
2308 }
2309 case eKeyboardEventClass: {
2310 auto* keyboardEvent = aEvent->AsKeyboardEvent();
2311 if (aEvent->mMessage == eKeyUp) {
2312 HandleKeyUpInteraction(keyboardEvent);
2313 }
2314 remote->SendRealKeyEvent(*keyboardEvent);
2315 return;
2316 }
2317 case eWheelEventClass: {
2318 if (BrowserParent* pointerLockedRemote =
2319 PointerLockManager::GetLockedRemoteTarget()) {
2320 remote = pointerLockedRemote;
2321 }
2322 remote->SendMouseWheelEvent(*aEvent->AsWheelEvent());
2323 return;
2324 }
2325 case eTouchEventClass: {
2326 // Let the child process synthesize a mouse event if needed, and
2327 // ensure we don't synthesize one in this process.
2328 *aStatus = nsEventStatus_eConsumeNoDefault;
2329 remote->SendRealTouchEvent(*aEvent->AsTouchEvent());
2330 return;
2331 }
2332 case eDragEventClass: {
2333 RefPtr<BrowserParent> browserParent = remote;
2334 browserParent->MaybeInvokeDragSession(aEvent->mMessage);
2335
2336 RefPtr<nsIWidget> widget = browserParent->GetTopLevelWidget();
2337 nsCOMPtr<nsIDragSession> dragSession =
2338 nsContentUtils::GetDragSession(widget);
2339 uint32_t dropEffect = nsIDragService::DRAGDROP_ACTION_NONE;
2340 uint32_t action = nsIDragService::DRAGDROP_ACTION_NONE;
2341 nsCOMPtr<nsIPrincipal> principal;
2342 nsCOMPtr<nsIPolicyContainer> policyContainer;
2343
2344 if (dragSession) {
2345 dragSession->DragEventDispatchedToChildProcess();
2346 dragSession->GetDragAction(&action);
2347 dragSession->GetTriggeringPrincipal(getter_AddRefs(principal));
2348 dragSession->GetPolicyContainer(getter_AddRefs(policyContainer));
2349 RefPtr<DataTransfer> initialDataTransfer =
2350 dragSession->GetDataTransfer();
2351 if (initialDataTransfer) {
2352 dropEffect = initialDataTransfer->DropEffectInt();
2353 }
2354 }
2355
2356 browserParent->SendRealDragEvent(*aEvent->AsDragEvent(), action,
2357 dropEffect, principal, policyContainer);
2358 return;
2359 }
2360 default: {
2361 MOZ_CRASH("Attempt to send non-whitelisted event?")do { do { } while (false); MOZ_ReportCrash("" "Attempt to send non-whitelisted event?"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2361
); AnnotateMozCrashReason("MOZ_CRASH(" "Attempt to send non-whitelisted event?"
")"); do { MOZ_CrashSequence(__null, 2361); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2362 }
2363 }
2364}
2365
2366bool EventStateManager::IsRemoteTarget(nsIContent* target) {
2367 return BrowserParent::GetFrom(target) || BrowserBridgeChild::GetFrom(target);
2368}
2369
2370bool EventStateManager::IsTopLevelRemoteTarget(nsIContent* target) {
2371 return !!BrowserParent::GetFrom(target);
2372}
2373
2374bool EventStateManager::HandleCrossProcessEvent(WidgetEvent* aEvent,
2375 nsEventStatus* aStatus) {
2376 if (!aEvent->CanBeSentToRemoteProcess()) {
2377 return false;
2378 }
2379
2380 MOZ_ASSERT(!aEvent->HasBeenPostedToRemoteProcess(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aEvent->HasBeenPostedToRemoteProcess())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aEvent->HasBeenPostedToRemoteProcess()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!aEvent->HasBeenPostedToRemoteProcess()"
" (" "Why do we need to post same event to remote processes again?"
")", "/root/firefox-clang/dom/events/EventStateManager.cpp",
2381); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEvent->HasBeenPostedToRemoteProcess()"
") (" "Why do we need to post same event to remote processes again?"
")"); do { MOZ_CrashSequence(__null, 2381); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2381 "Why do we need to post same event to remote processes again?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aEvent->HasBeenPostedToRemoteProcess())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aEvent->HasBeenPostedToRemoteProcess()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!aEvent->HasBeenPostedToRemoteProcess()"
" (" "Why do we need to post same event to remote processes again?"
")", "/root/firefox-clang/dom/events/EventStateManager.cpp",
2381); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEvent->HasBeenPostedToRemoteProcess()"
") (" "Why do we need to post same event to remote processes again?"
")"); do { MOZ_CrashSequence(__null, 2381); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2382
2383 // Collect the remote event targets we're going to forward this
2384 // event to.
2385 //
2386 // NB: the elements of |remoteTargets| must be unique, for correctness.
2387 AutoTArray<RefPtr<BrowserParent>, 1> remoteTargets;
2388 if (aEvent->mClass != eTouchEventClass || aEvent->mMessage == eTouchStart) {
2389 // If this event only has one target, and it's remote, add it to
2390 // the array.
2391 nsIFrame* frame = aEvent->mMessage == eDragExit
2392 ? sLastDragOverFrame.GetFrame()
2393 : GetEventTarget();
2394 nsIContent* target = frame ? frame->GetContent() : nullptr;
2395 if (BrowserParent* remoteTarget = BrowserParent::GetFrom(target)) {
2396 remoteTargets.AppendElement(remoteTarget);
2397 }
2398 } else {
2399 // This is a touch event with possibly multiple touch points.
2400 // Each touch point may have its own target. So iterate through
2401 // all of them and collect the unique set of targets for event
2402 // forwarding.
2403 //
2404 // This loop is similar to the one used in
2405 // PresShell::DispatchTouchEvent().
2406 const WidgetTouchEvent::TouchArray& touches =
2407 aEvent->AsTouchEvent()->mTouches;
2408 for (uint32_t i = 0; i < touches.Length(); ++i) {
2409 Touch* touch = touches[i];
2410 // NB: the |mChanged| check is an optimization, subprocesses can
2411 // compute this for themselves. If the touch hasn't changed, we
2412 // may be able to avoid forwarding the event entirely (which is
2413 // not free).
2414 if (!touch || !touch->mChanged) {
2415 continue;
2416 }
2417 nsCOMPtr<EventTarget> targetPtr = touch->mTarget;
2418 if (!targetPtr) {
2419 continue;
2420 }
2421 nsCOMPtr<nsIContent> target = do_QueryInterface(targetPtr);
2422 BrowserParent* remoteTarget = BrowserParent::GetFrom(target);
2423 if (remoteTarget && !remoteTargets.Contains(remoteTarget)) {
2424 remoteTargets.AppendElement(remoteTarget);
2425 }
2426 }
2427 }
2428
2429 if (remoteTargets.Length() == 0) {
2430 return false;
2431 }
2432
2433 // Dispatch the event to the remote target.
2434 for (uint32_t i = 0; i < remoteTargets.Length(); ++i) {
2435 DispatchCrossProcessEvent(aEvent, remoteTargets[i], aStatus);
2436 }
2437 return aEvent->HasBeenPostedToRemoteProcess();
2438}
2439
2440//
2441// CreateClickHoldTimer
2442//
2443// Fire off a timer for determining if the user wants click-hold. This timer
2444// is a one-shot that will be cancelled when the user moves enough to fire
2445// a drag.
2446//
2447void EventStateManager::CreateClickHoldTimer(nsPresContext* inPresContext,
2448 nsIFrame* inDownFrame,
2449 WidgetGUIEvent* inMouseDownEvent) {
2450 if (!inMouseDownEvent->IsTrusted() ||
2451 IsTopLevelRemoteTarget(mGestureDownContent) ||
2452 PointerLockManager::IsLocked()) {
2453 return;
2454 }
2455
2456 // just to be anal (er, safe)
2457 if (mClickHoldTimer) {
2458 mClickHoldTimer->Cancel();
2459 mClickHoldTimer = nullptr;
2460 }
2461
2462 // if content clicked on has a popup, don't even start the timer
2463 // since we'll end up conflicting and both will show.
2464 if (mGestureDownContent &&
2465 nsContentUtils::HasNonEmptyAttr(mGestureDownContent, kNameSpaceID_None,
2466 nsGkAtoms::popup)) {
2467 return;
2468 }
2469
2470 int32_t clickHoldDelay = StaticPrefs::ui_click_hold_context_menus_delay();
2471 NS_NewTimerWithFuncCallback(
2472 getter_AddRefs(mClickHoldTimer), sClickHoldCallback, this, clickHoldDelay,
2473 nsITimer::TYPE_ONE_SHOT, "EventStateManager::CreateClickHoldTimer"_ns);
2474} // CreateClickHoldTimer
2475
2476//
2477// KillClickHoldTimer
2478//
2479// Stop the timer that would show the context menu dead in its tracks
2480//
2481void EventStateManager::KillClickHoldTimer() {
2482 if (mClickHoldTimer) {
2483 mClickHoldTimer->Cancel();
2484 mClickHoldTimer = nullptr;
2485 }
2486}
2487
2488//
2489// sClickHoldCallback
2490//
2491// This fires after the mouse has been down for a certain length of time.
2492//
2493void EventStateManager::sClickHoldCallback(nsITimer* aTimer, void* aESM) {
2494 RefPtr<EventStateManager> self = static_cast<EventStateManager*>(aESM);
2495 if (self) {
2496 self->FireContextClick();
2497 }
2498
2499 // NOTE: |aTimer| and |self->mAutoHideTimer| are invalid after calling
2500 // ClosePopup();
2501
2502} // sAutoHideCallback
2503
2504//
2505// FireContextClick
2506//
2507// If we're this far, our timer has fired, which means the mouse has been down
2508// for a certain period of time and has not moved enough to generate a
2509// dragGesture. We can be certain the user wants a context-click at this stage,
2510// so generate a dom event and fire it in.
2511//
2512// After the event fires, check if PreventDefault() has been set on the event
2513// which means that someone either ate the event or put up a context menu. This
2514// is our cue to stop tracking the drag gesture. If we always did this,
2515// draggable items w/out a context menu wouldn't be draggable after a certain
2516// length of time, which is _not_ what we want.
2517//
2518void EventStateManager::FireContextClick() {
2519 if (!mGestureDownContent || !mPresContext || PointerLockManager::IsLocked()) {
2520 return;
2521 }
2522
2523#ifdef XP_MACOSX
2524 // Hack to ensure that we don't show a context menu when the user
2525 // let go of the mouse after a long cpu-hogging operation prevented
2526 // us from handling any OS events. See bug 117589.
2527 if (!CGEventSourceButtonState(kCGEventSourceStateCombinedSessionState,
2528 kCGMouseButtonLeft))
2529 return;
2530#endif
2531
2532 nsEventStatus status = nsEventStatus_eIgnore;
2533
2534 // Dispatch to the DOM. We have to fake out the ESM and tell it that the
2535 // current target frame is actually where the mouseDown occurred, otherwise it
2536 // will use the frame the mouse is currently over which may or may not be
2537 // the same. (Note: saari and I have decided that we don't have to reset
2538 // |mCurrentTarget| when we're through because no one else is doing anything
2539 // more with this event and it will get reset on the very next event to the
2540 // correct frame).
2541 mCurrentTarget =
2542 mPresContext->GetPrimaryOrAreaImageFrameFor(mGestureDownContent);
2543 // make sure the widget sticks around
2544 nsCOMPtr<nsIWidget> targetWidget;
2545 if (mCurrentTarget && (targetWidget = mCurrentTarget->GetNearestWidget())) {
2546 NS_ASSERTION(do { if (!(mPresContext == mCurrentTarget->PresContext()))
{ NS_DebugBreak(NS_DEBUG_ASSERTION, "a prescontext returned a primary frame that didn't belong to it?"
, "mPresContext == mCurrentTarget->PresContext()", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 2548); MOZ_PretendNoReturn(); } } while (0)
2547 mPresContext == mCurrentTarget->PresContext(),do { if (!(mPresContext == mCurrentTarget->PresContext()))
{ NS_DebugBreak(NS_DEBUG_ASSERTION, "a prescontext returned a primary frame that didn't belong to it?"
, "mPresContext == mCurrentTarget->PresContext()", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 2548); MOZ_PretendNoReturn(); } } while (0)
2548 "a prescontext returned a primary frame that didn't belong to it?")do { if (!(mPresContext == mCurrentTarget->PresContext()))
{ NS_DebugBreak(NS_DEBUG_ASSERTION, "a prescontext returned a primary frame that didn't belong to it?"
, "mPresContext == mCurrentTarget->PresContext()", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 2548); MOZ_PretendNoReturn(); } } while (0)
;
2549
2550 // before dispatching, check that we're not on something that
2551 // doesn't get a context menu
2552 bool allowedToDispatch = true;
2553
2554 if (mGestureDownContent->IsAnyOfXULElements(nsGkAtoms::scrollbar,
2555 nsGkAtoms::scrollbarbutton,
2556 nsGkAtoms::button)) {
2557 allowedToDispatch = false;
2558 } else if (mGestureDownContent->IsXULElement(nsGkAtoms::toolbarbutton)) {
2559 // a <toolbarbutton> that has the container attribute set
2560 // will already have its own dropdown.
2561 if (nsContentUtils::HasNonEmptyAttr(
2562 mGestureDownContent, kNameSpaceID_None, nsGkAtoms::container)) {
2563 allowedToDispatch = false;
2564 } else {
2565 // If the toolbar button has an open menu, don't attempt to open
2566 // a second menu
2567 if (mGestureDownContent->IsElement() &&
2568 mGestureDownContent->AsElement()->AttrValueIs(
2569 kNameSpaceID_None, nsGkAtoms::open, nsGkAtoms::_true,
2570 eCaseMatters)) {
2571 allowedToDispatch = false;
2572 }
2573 }
2574 } else if (mGestureDownContent->IsHTMLElement()) {
2575 if (const auto* formCtrl =
2576 nsIFormControl::FromNode(mGestureDownContent)) {
2577 allowedToDispatch =
2578 formCtrl->IsTextControl(/*aExcludePassword*/ false) ||
2579 formCtrl->ControlType() == FormControlType::InputFile;
2580 } else if (mGestureDownContent->IsAnyOfHTMLElements(
2581 nsGkAtoms::embed, nsGkAtoms::object, nsGkAtoms::label)) {
2582 allowedToDispatch = false;
2583 }
2584 }
2585
2586 if (allowedToDispatch) {
2587 // init the event while mCurrentTarget is still good
2588 WidgetPointerEvent event(true, eContextMenu, targetWidget);
2589 event.mClickCount = 1;
2590 FillInEventFromGestureDown(&event);
2591
2592 // we need to forget the clicking content and click count for the
2593 // following eMouseUp event when click-holding context menus
2594 GetLastMouseButtonPressInfo(event.mButton).Clear();
2595
2596 // stop selection tracking, we're in control now
2597 if (mCurrentTarget) {
2598 RefPtr<nsFrameSelection> frameSel = mCurrentTarget->GetFrameSelection();
2599
2600 if (frameSel && frameSel->GetDragState()) {
2601 // note that this can cause selection changed events to fire if we're
2602 // in a text field, which will null out mCurrentTarget
2603 frameSel->SetDragState(false);
2604 }
2605 }
2606
2607 AutoHandlingUserInputStatePusher userInpStatePusher(true, &event);
2608
2609 // dispatch to DOM
2610 RefPtr<nsPresContext> presContext = mPresContext;
2611
2612 // The contextmenu event handled by PresShell will apply to elements (not
2613 // all nodes) correctly and will be dispatched to EventStateManager for
2614 // further handling preventing click event and stopping tracking drag
2615 // gesture.
2616 if (RefPtr<PresShell> presShell = presContext->GetPresShell()) {
2617 presShell->HandleEvent(mCurrentTarget, &event, false, &status);
2618 }
2619
2620 // We don't need to dispatch to frame handling because no frames
2621 // watch eContextMenu except for nsMenuFrame and that's only for
2622 // dismissal. That's just as well since we don't really know
2623 // which frame to send it to.
2624 }
2625 }
2626
2627 // stop tracking a drag whatever the event has been handled or not.
2628 StopTrackingDragGesture(true);
2629
2630 KillClickHoldTimer();
2631
2632} // FireContextClick
2633
2634//
2635// BeginTrackingDragGesture
2636//
2637// Record that the mouse has gone down and that we should move to TRACKING state
2638// of d&d gesture tracker.
2639//
2640// We also use this to track click-hold context menus. When the mouse goes down,
2641// fire off a short timer. If the timer goes off and we have yet to fire the
2642// drag gesture (ie, the mouse hasn't moved a certain distance), then we can
2643// assume the user wants a click-hold, so fire a context-click event. We only
2644// want to cancel the drag gesture if the context-click event is handled.
2645//
2646void EventStateManager::BeginTrackingDragGesture(
2647 nsPresContext* aPresContext, WidgetMouseEvent& aMouseDownOrTouchDragEvent,
2648 nsIFrame* aMouseDownOrTouchDragFrame) {
2649 MOZ_ASSERT(aMouseDownOrTouchDragEvent.mMessage == eMouseDown ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMouseDownOrTouchDragEvent.mMessage == eMouseDown ||
aMouseDownOrTouchDragEvent.mMessage == eMouseTouchDrag)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aMouseDownOrTouchDragEvent.mMessage == eMouseDown ||
aMouseDownOrTouchDragEvent.mMessage == eMouseTouchDrag))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aMouseDownOrTouchDragEvent.mMessage == eMouseDown || aMouseDownOrTouchDragEvent.mMessage == eMouseTouchDrag"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2650
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseDownOrTouchDragEvent.mMessage == eMouseDown || aMouseDownOrTouchDragEvent.mMessage == eMouseTouchDrag"
")"); do { MOZ_CrashSequence(__null, 2650); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2650 aMouseDownOrTouchDragEvent.mMessage == eMouseTouchDrag)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMouseDownOrTouchDragEvent.mMessage == eMouseDown ||
aMouseDownOrTouchDragEvent.mMessage == eMouseTouchDrag)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aMouseDownOrTouchDragEvent.mMessage == eMouseDown ||
aMouseDownOrTouchDragEvent.mMessage == eMouseTouchDrag))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aMouseDownOrTouchDragEvent.mMessage == eMouseDown || aMouseDownOrTouchDragEvent.mMessage == eMouseTouchDrag"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2650
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseDownOrTouchDragEvent.mMessage == eMouseDown || aMouseDownOrTouchDragEvent.mMessage == eMouseTouchDrag"
")"); do { MOZ_CrashSequence(__null, 2650); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2651 if (!aMouseDownOrTouchDragEvent.mWidget) [[unlikely]] {
2652 return;
2653 }
2654
2655 // Note that |inDownEvent| could be either a mouse down event or a
2656 // synthesized mouse move event.
2657 SetGestureDownPoint(aMouseDownOrTouchDragEvent);
2658
2659 if (aMouseDownOrTouchDragFrame) {
2660 // We need to store the explicit target of the drag gesture start content,
2661 // i.e., it may be a `Text` even though the event target should be its
2662 // flattened tree parent element because we want to maintain `Selection`
2663 // with the `Text`. E.g., we want to allow to extending selection in a
2664 // draggable editing host, check whether the `Text` is selectable or not
2665 // like in a `Text` of a <button>.
2666 mGestureDownContent =
2667 aMouseDownOrTouchDragFrame->GetExplicitEventTargetContent(
2668 aMouseDownOrTouchDragEvent);
2669 mGestureDownFrameOwner = aMouseDownOrTouchDragFrame->GetContent();
2670 if (!mGestureDownFrameOwner) {
2671 mGestureDownFrameOwner = mGestureDownContent;
2672 }
2673 mGestureDownTopLevelRemoteTarget =
2674 BrowserParent::GetFrom(mGestureDownContent);
2675 }
2676 mGestureModifiers = aMouseDownOrTouchDragEvent.mModifiers;
2677 mGestureDownButtons = aMouseDownOrTouchDragEvent.mButtons;
2678 mGestureDownButton = aMouseDownOrTouchDragEvent.mButton;
2679
2680 if (aMouseDownOrTouchDragEvent.mMessage != eMouseTouchDrag &&
2681 StaticPrefs::ui_click_hold_context_menus()) {
2682 // fire off a timer to track click-hold
2683 CreateClickHoldTimer(aPresContext, aMouseDownOrTouchDragFrame,
2684 &aMouseDownOrTouchDragEvent);
2685 }
2686}
2687
2688void EventStateManager::SetGestureDownPoint(const WidgetGUIEvent& aEvent) {
2689 mGestureDownPoint =
2690 GetEventRefPoint(aEvent) + aEvent.mWidget->WidgetToScreenOffset();
2691}
2692
2693LayoutDeviceIntPoint EventStateManager::GetEventRefPoint(
2694 const WidgetEvent& aEvent) const {
2695 const auto* touchEvent = aEvent.AsTouchEvent();
2696 return (touchEvent && !touchEvent->mTouches.IsEmpty())
2697 ? aEvent.AsTouchEvent()->mTouches[0]->mRefPoint
2698 : aEvent.mRefPoint;
2699}
2700
2701void EventStateManager::BeginTrackingRemoteDragGesture(
2702 nsIContent* aContent, RemoteDragStartData* aDragStartData) {
2703 UpdateGestureContent(aContent);
2704 mGestureDownDragStartData = aDragStartData;
2705}
2706
2707//
2708// StopTrackingDragGesture
2709//
2710// Record that the mouse has gone back up so that we should leave the TRACKING
2711// state of d&d gesture tracker and return to the START state.
2712//
2713void EventStateManager::StopTrackingDragGesture(bool aClearInChildProcesses) {
2714 mGestureDownContent = nullptr;
2715 mGestureDownFrameOwner = nullptr;
2716 mGestureDownDragStartData = nullptr;
2717
2718 // If a content process starts a drag but the mouse is released before the
2719 // parent starts the actual drag, the content process will think a drag is
2720 // still happening. Inform any child processes with active drags that the drag
2721 // should be stopped.
2722 if (!aClearInChildProcesses || !XRE_IsParentProcess()) {
2723 return;
2724 }
2725
2726 mGestureDownTopLevelRemoteTarget = nullptr;
2727
2728 // Only notify if there is NOT a drag session active in the parent.
2729 RefPtr<nsIDragSession> dragSession =
2730 nsContentUtils::GetDragSession(mPresContext);
2731 if (dragSession) {
2732 return;
2733 }
2734 nsCOMPtr<nsIDragService> dragService =
2735 do_GetService("@mozilla.org/widget/dragservice;1");
2736 if (!dragService) {
2737 return;
2738 }
2739 dragService->RemoveAllBrowsers();
2740}
2741
2742void EventStateManager::FillInEventFromGestureDown(WidgetMouseEvent* aEvent) {
2743 NS_ASSERTION(aEvent->mWidget == mCurrentTarget->GetNearestWidget(),do { if (!(aEvent->mWidget == mCurrentTarget->GetNearestWidget
())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Incorrect widget in event"
, "aEvent->mWidget == mCurrentTarget->GetNearestWidget()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2744
); MOZ_PretendNoReturn(); } } while (0)
2744 "Incorrect widget in event")do { if (!(aEvent->mWidget == mCurrentTarget->GetNearestWidget
())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Incorrect widget in event"
, "aEvent->mWidget == mCurrentTarget->GetNearestWidget()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2744
); MOZ_PretendNoReturn(); } } while (0)
;
2745
2746 // Set the coordinates in the new event to the coordinates of
2747 // the old event, adjusted for the fact that the widget might be
2748 // different
2749 aEvent->mRefPoint =
2750 mGestureDownPoint - aEvent->mWidget->WidgetToScreenOffset();
2751 aEvent->mModifiers = mGestureModifiers;
2752 aEvent->mButtons = mGestureDownButtons;
2753 if (aEvent->mMessage == eContextMenu) {
2754 aEvent->mButton = mGestureDownButton;
2755 }
2756}
2757
2758void EventStateManager::MaybeDispatchPointerCancel(
2759 const WidgetInputEvent& aSourceEvent, nsIContent& aTargetContent) {
2760 // Dispatching ePointerCancel clears out mCurrentTarget, which may be used in
2761 // the caller GenerateDragGesture. We have to restore mCurrentTarget.
2762 AutoWeakFrame targetFrame = mCurrentTarget;
2763 const auto restoreCurrentTarget =
2764 MakeScopeExit([&]() { mCurrentTarget = targetFrame; });
2765
2766 const RefPtr<Element> targetElement =
2767 aTargetContent.GetAsElementOrParentElement();
2768 // XXX If there is no proper event target, should we retarget ePointerCancel
2769 // somewhere else?
2770 if (NS_WARN_IF(!targetElement)NS_warn_if_impl(!targetElement, "!targetElement", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 2770)
) {
2771 return;
2772 }
2773
2774 if (const WidgetMouseEvent* const mouseEvent = aSourceEvent.AsMouseEvent()) {
2775 PointerEventHandler::DispatchPointerEventWithTarget(
2776 ePointerCancel, *mouseEvent, AutoWeakFrame{}, targetElement);
2777 } else if (const WidgetTouchEvent* const touchEvent =
2778 aSourceEvent.AsTouchEvent()) {
2779 PointerEventHandler::DispatchPointerEventWithTarget(
2780 ePointerCancel, *touchEvent, 0, AutoWeakFrame{}, targetElement);
2781 } else {
2782 MOZ_ASSERT_UNREACHABLE(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"MaybeDispatchPointerCancel() should be called with a mouse event or a "
"touch event" ")", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 2784); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "MaybeDispatchPointerCancel() should be called with a mouse event or a "
"touch event" ")"); do { MOZ_CrashSequence(__null, 2784); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
2783 "MaybeDispatchPointerCancel() should be called with a mouse event or a "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"MaybeDispatchPointerCancel() should be called with a mouse event or a "
"touch event" ")", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 2784); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "MaybeDispatchPointerCancel() should be called with a mouse event or a "
"touch event" ")"); do { MOZ_CrashSequence(__null, 2784); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
2784 "touch event")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"MaybeDispatchPointerCancel() should be called with a mouse event or a "
"touch event" ")", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 2784); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "MaybeDispatchPointerCancel() should be called with a mouse event or a "
"touch event" ")"); do { MOZ_CrashSequence(__null, 2784); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
2785 }
2786}
2787
2788bool EventStateManager::IsEventOutsideDragThreshold(
2789 const WidgetInputEvent& aEvent) const {
2790 static int32_t sPixelThresholdX = 0;
2791 static int32_t sPixelThresholdY = 0;
2792
2793 if (!sPixelThresholdX) {
2794 sPixelThresholdX =
2795 LookAndFeel::GetInt(LookAndFeel::IntID::DragThresholdX, 0);
2796 sPixelThresholdY =
2797 LookAndFeel::GetInt(LookAndFeel::IntID::DragThresholdY, 0);
2798 if (sPixelThresholdX <= 0) {
2799 sPixelThresholdX = 5;
2800 }
2801 if (sPixelThresholdY <= 0) {
2802 sPixelThresholdY = 5;
2803 }
2804 }
2805
2806 LayoutDeviceIntPoint pt =
2807 aEvent.mWidget->WidgetToScreenOffset() + GetEventRefPoint(aEvent);
2808 LayoutDeviceIntPoint distance = pt - mGestureDownPoint;
2809 return Abs(distance.x) > sPixelThresholdX ||
2810 Abs(distance.y) > sPixelThresholdY;
2811}
2812
2813//
2814// GenerateDragGesture
2815//
2816// If we're in the TRACKING state of the d&d gesture tracker, check the current
2817// position of the mouse in relation to the old one. If we've moved a sufficient
2818// amount from the mouse down, then fire off a drag gesture event.
2819void EventStateManager::GenerateDragGesture(
2820 nsPresContext* aPresContext,
2821 WidgetInputEvent& aMouseOrTouchOrPointerEvent) {
2822 NS_ASSERTION(aPresContext, "This shouldn't happen.")do { if (!(aPresContext)) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"This shouldn't happen.", "aPresContext", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 2822); MOZ_PretendNoReturn(); } } while (0)
;
2823 MOZ_ASSERT_IF(aMouseOrTouchOrPointerEvent.AsMouseEvent(),do { if (aMouseOrTouchOrPointerEvent.AsMouseEvent()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aMouseOrTouchOrPointerEvent
.AsMouseEvent()->IsReal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMouseOrTouchOrPointerEvent.
AsMouseEvent()->IsReal()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aMouseOrTouchOrPointerEvent.AsMouseEvent()->IsReal()", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 2824); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseOrTouchOrPointerEvent.AsMouseEvent()->IsReal()"
")"); do { MOZ_CrashSequence(__null, 2824); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2824 aMouseOrTouchOrPointerEvent.AsMouseEvent()->IsReal())do { if (aMouseOrTouchOrPointerEvent.AsMouseEvent()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aMouseOrTouchOrPointerEvent
.AsMouseEvent()->IsReal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMouseOrTouchOrPointerEvent.
AsMouseEvent()->IsReal()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aMouseOrTouchOrPointerEvent.AsMouseEvent()->IsReal()", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 2824); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseOrTouchOrPointerEvent.AsMouseEvent()->IsReal()"
")"); do { MOZ_CrashSequence(__null, 2824); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2825 MOZ_ASSERT(aMouseOrTouchOrPointerEvent.mMessage == eTouchMove ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMouseOrTouchOrPointerEvent.mMessage == eTouchMove ||
aMouseOrTouchOrPointerEvent.mMessage == eMouseMove || aMouseOrTouchOrPointerEvent
.mMessage == ePointerMove || aMouseOrTouchOrPointerEvent.mMessage
== ePointerDown)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMouseOrTouchOrPointerEvent.
mMessage == eTouchMove || aMouseOrTouchOrPointerEvent.mMessage
== eMouseMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerMove
|| aMouseOrTouchOrPointerEvent.mMessage == ePointerDown))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aMouseOrTouchOrPointerEvent.mMessage == eTouchMove || aMouseOrTouchOrPointerEvent.mMessage == eMouseMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerDown"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2828
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseOrTouchOrPointerEvent.mMessage == eTouchMove || aMouseOrTouchOrPointerEvent.mMessage == eMouseMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerDown"
")"); do { MOZ_CrashSequence(__null, 2828); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2826 aMouseOrTouchOrPointerEvent.mMessage == eMouseMove ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMouseOrTouchOrPointerEvent.mMessage == eTouchMove ||
aMouseOrTouchOrPointerEvent.mMessage == eMouseMove || aMouseOrTouchOrPointerEvent
.mMessage == ePointerMove || aMouseOrTouchOrPointerEvent.mMessage
== ePointerDown)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMouseOrTouchOrPointerEvent.
mMessage == eTouchMove || aMouseOrTouchOrPointerEvent.mMessage
== eMouseMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerMove
|| aMouseOrTouchOrPointerEvent.mMessage == ePointerDown))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aMouseOrTouchOrPointerEvent.mMessage == eTouchMove || aMouseOrTouchOrPointerEvent.mMessage == eMouseMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerDown"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2828
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseOrTouchOrPointerEvent.mMessage == eTouchMove || aMouseOrTouchOrPointerEvent.mMessage == eMouseMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerDown"
")"); do { MOZ_CrashSequence(__null, 2828); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2827 aMouseOrTouchOrPointerEvent.mMessage == ePointerMove ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMouseOrTouchOrPointerEvent.mMessage == eTouchMove ||
aMouseOrTouchOrPointerEvent.mMessage == eMouseMove || aMouseOrTouchOrPointerEvent
.mMessage == ePointerMove || aMouseOrTouchOrPointerEvent.mMessage
== ePointerDown)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMouseOrTouchOrPointerEvent.
mMessage == eTouchMove || aMouseOrTouchOrPointerEvent.mMessage
== eMouseMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerMove
|| aMouseOrTouchOrPointerEvent.mMessage == ePointerDown))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aMouseOrTouchOrPointerEvent.mMessage == eTouchMove || aMouseOrTouchOrPointerEvent.mMessage == eMouseMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerDown"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2828
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseOrTouchOrPointerEvent.mMessage == eTouchMove || aMouseOrTouchOrPointerEvent.mMessage == eMouseMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerDown"
")"); do { MOZ_CrashSequence(__null, 2828); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2828 aMouseOrTouchOrPointerEvent.mMessage == ePointerDown)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMouseOrTouchOrPointerEvent.mMessage == eTouchMove ||
aMouseOrTouchOrPointerEvent.mMessage == eMouseMove || aMouseOrTouchOrPointerEvent
.mMessage == ePointerMove || aMouseOrTouchOrPointerEvent.mMessage
== ePointerDown)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMouseOrTouchOrPointerEvent.
mMessage == eTouchMove || aMouseOrTouchOrPointerEvent.mMessage
== eMouseMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerMove
|| aMouseOrTouchOrPointerEvent.mMessage == ePointerDown))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aMouseOrTouchOrPointerEvent.mMessage == eTouchMove || aMouseOrTouchOrPointerEvent.mMessage == eMouseMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerDown"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 2828
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseOrTouchOrPointerEvent.mMessage == eTouchMove || aMouseOrTouchOrPointerEvent.mMessage == eMouseMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerMove || aMouseOrTouchOrPointerEvent.mMessage == ePointerDown"
")"); do { MOZ_CrashSequence(__null, 2828); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2829 if (!IsTrackingDragGesture()) {
2830 return;
2831 }
2832
2833 AutoWeakFrame targetFrameBefore = mCurrentTarget;
2834 auto autoRestore = MakeScopeExit([&] { mCurrentTarget = targetFrameBefore; });
2835
2836 mCurrentTarget = nullptr;
2837 // Try to find a suitable frame by looping through the ancestors chain.
2838 for (auto* content :
2839 mGestureDownFrameOwner->InclusiveFlatTreeAncestorsOfType<nsIContent>()) {
2840 if (nsIFrame* target = nsLayoutUtils::GetPrimaryOrAreaImageFrame(content)) {
2841 mCurrentTarget = target;
2842
2843 if (content != mGestureDownFrameOwner) {
2844 UpdateGestureContent(content);
2845 }
2846 break;
2847 }
2848 }
2849
2850 if (!mCurrentTarget || !mCurrentTarget->GetNearestWidget()) {
2851 StopTrackingDragGesture(true);
2852 return;
2853 }
2854
2855 // Check if selection is tracking drag gestures, if so
2856 // don't interfere!
2857 if (mCurrentTarget) {
2858 RefPtr<nsFrameSelection> frameSel = mCurrentTarget->GetFrameSelection();
2859 if (frameSel && frameSel->GetDragState()) {
2860 StopTrackingDragGesture(true);
2861 return;
2862 }
2863 }
2864
2865 // If non-native code is capturing the mouse don't start a drag.
2866 if (PresShell::IsMouseCapturePreventingDrag()) {
2867 StopTrackingDragGesture(true);
2868 return;
2869 }
2870
2871 if (!IsEventOutsideDragThreshold(aMouseOrTouchOrPointerEvent)) {
2872 // To keep the old behavior, flush layout even if we don't start dnd.
2873 FlushLayout(aPresContext);
2874 return;
2875 }
2876
2877 if (StaticPrefs::ui_click_hold_context_menus()) {
2878 // stop the click-hold before we fire off the drag gesture, in case
2879 // it takes a long time
2880 KillClickHoldTimer();
2881 }
2882
2883 nsCOMPtr<nsIDocShell> docshell = aPresContext->GetDocShell();
2884 if (!docshell) {
2885 return;
2886 }
2887
2888 nsCOMPtr<nsPIDOMWindowOuter> window = docshell->GetWindow();
2889 if (!window) return;
2890
2891 RefPtr<DataTransfer> dataTransfer =
2892 new DataTransfer(window, eDragStart, /* aIsExternal */ false,
2893 /* aClipboardType */ Nothing());
2894 auto protectDataTransfer = MakeScopeExit([&] {
2895 if (dataTransfer) {
2896 dataTransfer->Disconnect();
2897 }
2898 });
2899
2900 RefPtr<Selection> selection;
2901 RefPtr<RemoteDragStartData> remoteDragStartData;
2902 nsCOMPtr<nsIPrincipal> principal;
2903 nsCOMPtr<nsIPolicyContainer> policyContainer;
2904 nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
2905 nsCOMPtr<nsIContent> targetContent;
2906 bool allowEmptyDataTransfer = false;
2907 if (const nsCOMPtr<nsIContent> eventContent =
2908 mCurrentTarget->GetExplicitEventTargetContent(
2909 aMouseOrTouchOrPointerEvent)) {
2910 // If the content is a text node in a password field, we shouldn't
2911 // allow to drag its raw text. Note that we've supported drag from
2912 // password fields but dragging data was masked text. So, it doesn't
2913 // make sense anyway.
2914 if (eventContent->IsText() && eventContent->HasFlag(NS_MAYBE_MASKED)) {
2915 // However, it makes sense to allow to drag selected password text
2916 // when copying selected password is allowed because users may want
2917 // to use drag and drop rather than copy and paste when web apps
2918 // request to input password twice for conforming new password but
2919 // they used password generator.
2920 const TextEditor* const textEditor =
2921 nsContentUtils::GetExtantTextEditorFromAnonymousNode(eventContent);
2922 if (!textEditor || !textEditor->IsCopyToClipboardAllowed()) {
2923 StopTrackingDragGesture(true);
2924 return;
2925 }
2926 }
2927 DetermineDragTargetAndDefaultData(
2928 window, eventContent, dataTransfer, &allowEmptyDataTransfer,
2929 getter_AddRefs(selection), getter_AddRefs(remoteDragStartData),
2930 getter_AddRefs(targetContent), getter_AddRefs(principal),
2931 getter_AddRefs(policyContainer), getter_AddRefs(cookieJarSettings));
2932 }
2933
2934 // Stop tracking the drag gesture now. This should stop us from
2935 // reentering GenerateDragGesture inside DOM event processing.
2936 // Pass false to avoid clearing the child process state since a real
2937 // drag should be starting.
2938 StopTrackingDragGesture(false);
2939
2940 if (MOZ_UNLIKELY(!targetContent)(__builtin_expect(!!(!targetContent), 0))) {
2941 return;
2942 }
2943
2944 // Use our targetContent, now that we've determined it, as the
2945 // parent object of the DataTransfer.
2946 nsCOMPtr<nsIContent> parentContent =
2947 targetContent->FindFirstNonChromeOnlyAccessContent();
2948 dataTransfer->SetParentObject(parentContent);
2949
2950 sLastDragOverFrame = nullptr;
2951 nsCOMPtr<nsIWidget> widget = mCurrentTarget->GetNearestWidget();
2952
2953 // get the widget from the target frame
2954 WidgetDragEvent startEvent(aMouseOrTouchOrPointerEvent.IsTrusted(),
2955 eDragStart, widget);
2956 startEvent.mFlags.mIsSynthesizedForTests =
2957 aMouseOrTouchOrPointerEvent.mFlags.mIsSynthesizedForTests;
2958 startEvent.mFlags.mIsAsyncSynthesizedForTests =
2959 aMouseOrTouchOrPointerEvent.mFlags.mIsAsyncSynthesizedForTests;
2960 FillInEventFromGestureDown(&startEvent);
2961
2962 startEvent.mDataTransfer = dataTransfer;
2963 switch (aMouseOrTouchOrPointerEvent.mClass) {
2964 case eMouseEventClass:
2965 case ePointerEventClass:
2966 startEvent.mInputSource =
2967 static_cast<const WidgetMouseEvent&>(aMouseOrTouchOrPointerEvent)
2968 .mInputSource;
2969 break;
2970 case eTouchEventClass:
2971 startEvent.mInputSource = MouseEvent_Binding::MOZ_SOURCE_TOUCH;
2972 break;
2973 default:
2974 MOZ_ASSERT(false)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 2974); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ")")
; do { MOZ_CrashSequence(__null, 2974); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2975 }
2976
2977 // Dispatch to the DOM. By setting mCurrentTarget we are faking
2978 // out the ESM and telling it that the current target frame is
2979 // actually where the mouseDown occurred, otherwise it will use
2980 // the frame the mouse is currently over which may or may not be
2981 // the same.
2982
2983 // Hold onto old target content through the event and reset after.
2984 nsCOMPtr<nsIContent> targetBeforeEvent = mCurrentTargetContent;
2985
2986 {
2987 AutoConnectedAncestorTracker trackTargetContent(*targetContent);
2988 // Set the current target to the content for the mouse down
2989 mCurrentTargetContent = targetContent;
2990
2991 // Dispatch the dragstart event to the DOM.
2992 nsEventStatus status = nsEventStatus_eIgnore;
2993 EventDispatcher::Dispatch(targetContent, aPresContext, &startEvent, nullptr,
2994 &status);
2995
2996 WidgetDragEvent* event = &startEvent;
2997
2998 // Emit observer event to allow addons to modify the DataTransfer
2999 // object.
3000 if (nsCOMPtr<nsIObserverService> observerService =
3001 mozilla::services::GetObserverService()) {
3002 observerService->NotifyObservers(dataTransfer,
3003 "on-datatransfer-available", nullptr);
3004 }
3005
3006 if (status != nsEventStatus_eConsumeNoDefault) {
3007 bool dragStarted = DoDefaultDragStart(
3008 aPresContext, event, dataTransfer, allowEmptyDataTransfer,
3009 targetContent, selection, remoteDragStartData, principal,
3010 policyContainer, cookieJarSettings);
3011 if (dragStarted) {
3012 sActiveESM = nullptr;
3013 aMouseOrTouchOrPointerEvent.StopPropagation();
3014 // XXX If all elements were removed from the document, we may need to
3015 // dispatch ePointerCancel on the Document node.
3016 if ((targetContent = trackTargetContent.GetConnectedContent())) {
3017 MaybeDispatchPointerCancel(aMouseOrTouchOrPointerEvent,
3018 *targetContent);
3019 }
3020 }
3021 }
3022 }
3023
3024 // Reset mCurretTargetContent to what it was
3025 mCurrentTargetContent = std::move(targetBeforeEvent);
3026
3027 // Now flush all pending notifications, for better responsiveness
3028 // while dragging.
3029 FlushLayout(aPresContext);
3030} // GenerateDragGesture
3031
3032void EventStateManager::DetermineDragTargetAndDefaultData(
3033 nsPIDOMWindowOuter* aWindow, nsIContent* aSelectionTarget,
3034 DataTransfer* aDataTransfer, bool* aAllowEmptyDataTransfer,
3035 Selection** aSelection, RemoteDragStartData** aRemoteDragStartData,
3036 nsIContent** aTargetNode, nsIPrincipal** aPrincipal,
3037 nsIPolicyContainer** aPolicyContainer,
3038 nsICookieJarSettings** aCookieJarSettings) {
3039 *aTargetNode = nullptr;
3040 *aAllowEmptyDataTransfer = false;
3041 nsCOMPtr<nsIContent> dragDataNode;
3042
3043 nsIContent* editingElement = aSelectionTarget->IsEditable()
3044 ? aSelectionTarget->GetEditingHost()
3045 : nullptr;
3046 nsCOMPtr<nsIPrincipal> principal;
3047 bool fromChildProcess = false;
3048
3049 // In chrome, only allow dragging inside editable areas.
3050 bool isChromeContext = !aWindow->GetBrowsingContext()->IsContent();
3051 if (isChromeContext && !editingElement) {
3052 if (mGestureDownDragStartData) {
3053 // A child process started a drag so use any data it assigned for the dnd
3054 // session.
3055 mGestureDownDragStartData->AddInitialDnDDataTo(
3056 aDataTransfer, getter_AddRefs(principal), aPolicyContainer,
3057 aCookieJarSettings);
3058 fromChildProcess = true;
3059 mGestureDownDragStartData.forget(aRemoteDragStartData);
3060 *aAllowEmptyDataTransfer = true;
3061 }
3062 } else {
3063 mGestureDownDragStartData = nullptr;
3064
3065 // GetDragData determines if a selection, link or image in the content
3066 // should be dragged, and places the data associated with the drag in the
3067 // data transfer.
3068 // mGestureDownContent is the node where the mousedown event for the drag
3069 // occurred, and aSelectionTarget is the node to use when a selection is
3070 // used
3071 bool canDrag;
3072 bool wasAlt = (mGestureModifiers & MODIFIER_ALT) != 0;
3073 nsresult rv = nsContentAreaDragDrop::GetDragData(
3074 aWindow, mGestureDownContent, aSelectionTarget, wasAlt, aDataTransfer,
3075 &canDrag, aSelection, getter_AddRefs(dragDataNode), aPolicyContainer,
3076 aCookieJarSettings);
3077 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !canDrag) {
3078 return;
3079 }
3080 }
3081
3082 // if GetDragData returned a node, use that as the node being dragged.
3083 // Otherwise, if a selection is being dragged, use the node within the
3084 // selection that was dragged. Otherwise, just use the mousedown target.
3085 nsIContent* dragContent = mGestureDownContent;
3086 if (dragDataNode)
3087 dragContent = dragDataNode;
3088 else if (*aSelection)
3089 dragContent = aSelectionTarget;
3090
3091 nsIContent* originalDragContent = dragContent;
3092
3093 // If a selection isn't being dragged, look for an ancestor with the
3094 // draggable property set. If one is found, use that as the target of the
3095 // drag instead of the node that was clicked on. If a draggable node wasn't
3096 // found, just use the clicked node.
3097 if (!*aSelection) {
3098 while (dragContent) {
3099 if (auto htmlElement = nsGenericHTMLElement::FromNode(dragContent)) {
3100 if (htmlElement->Draggable()) {
3101 // We let draggable elements to trigger dnd even if there is no data
3102 // in the DataTransfer.
3103 *aAllowEmptyDataTransfer = true;
3104 break;
3105 }
3106 } else {
3107 if (dragContent->IsXULElement()) {
3108 // All XUL elements are draggable, so if a XUL element is
3109 // encountered, stop looking for draggable nodes and just use the
3110 // original clicked node instead.
3111 // XXXndeakin
3112 // In the future, we will want to improve this so that XUL has a
3113 // better way to specify whether something is draggable than just
3114 // on/off.
3115 dragContent = mGestureDownContent;
3116 break;
3117 }
3118 // otherwise, it's not an HTML or XUL element, so just keep looking
3119 }
3120 dragContent = dragContent->GetFlattenedTreeParent();
3121 }
3122 }
3123
3124 // if no node in the hierarchy was found to drag, but the GetDragData method
3125 // returned a node, use that returned node. Otherwise, nothing is draggable.
3126 if (!dragContent && dragDataNode) dragContent = dragDataNode;
3127
3128 if (dragContent) {
3129 // if an ancestor node was used instead, clear the drag data
3130 // XXXndeakin rework this a bit. Find a way to just not call GetDragData if
3131 // we don't need to.
3132 if (dragContent != originalDragContent) aDataTransfer->ClearAll();
3133 *aTargetNode = dragContent;
3134 NS_ADDREF(*aTargetNode)(*aTargetNode)->AddRef();
3135 if (!fromChildProcess) {
3136 principal = dragContent->NodePrincipal();
3137 }
3138 principal.forget(aPrincipal);
3139 }
3140}
3141
3142bool EventStateManager::DoDefaultDragStart(
3143 nsPresContext* aPresContext, WidgetDragEvent* aDragEvent,
3144 DataTransfer* aDataTransfer, bool aAllowEmptyDataTransfer,
3145 nsIContent* aDragTarget, Selection* aSelection,
3146 RemoteDragStartData* aDragStartData, nsIPrincipal* aPrincipal,
3147 nsIPolicyContainer* aPolicyContainer,
3148 nsICookieJarSettings* aCookieJarSettings) {
3149 nsCOMPtr<nsIDragService> dragService =
3150 do_GetService("@mozilla.org/widget/dragservice;1");
3151 if (!dragService) return false;
3152
3153 // Default handling for the dragstart event.
3154 //
3155 // First, check if a drag session already exists. This means that the drag
3156 // service was called directly within a draggesture handler. In this case,
3157 // don't do anything more, as it is assumed that the handler is managing
3158 // drag and drop manually. Make sure to return true to indicate that a drag
3159 // began. However, if we're handling drag session for synthesized events,
3160 // we need to initialize some information of the session. Therefore, we
3161 // need to keep going for synthesized case.
3162 if (MOZ_UNLIKELY(!mPresContext)(__builtin_expect(!!(!mPresContext), 0))) {
3163 return true;
3164 }
3165 nsCOMPtr<nsIDragSession> dragSession =
3166 dragService->GetCurrentSession(mPresContext->GetRootWidget());
3167 if (dragSession && !dragSession->IsSynthesizedForTests()) {
3168 return true;
3169 }
3170
3171 // No drag session is currently active, so check if a handler added
3172 // any items to be dragged. If not, there isn't anything to drag.
3173 uint32_t count = 0;
3174 if (aDataTransfer) {
3175 count = aDataTransfer->MozItemCount();
3176 }
3177 if (!aAllowEmptyDataTransfer && !count) {
3178 return false;
3179 }
3180
3181 // Get the target being dragged, which may not be the same as the
3182 // target of the mouse event. If one wasn't set in the
3183 // aDataTransfer during the event handler, just use the original
3184 // target instead.
3185 nsCOMPtr<nsIContent> dragTarget = aDataTransfer->GetDragTarget();
3186 if (!dragTarget) {
3187 dragTarget = aDragTarget;
3188 if (!dragTarget) {
3189 return false;
3190 }
3191 }
3192
3193 // check which drag effect should initially be used. If the effect was not
3194 // set, just use all actions, otherwise Windows won't allow a drop.
3195 uint32_t action = aDataTransfer->EffectAllowedInt();
3196 if (action == nsIDragService::DRAGDROP_ACTION_UNINITIALIZED) {
3197 action = nsIDragService::DRAGDROP_ACTION_COPY |
3198 nsIDragService::DRAGDROP_ACTION_MOVE |
3199 nsIDragService::DRAGDROP_ACTION_LINK;
3200 }
3201
3202 // get any custom drag image that was set
3203 int32_t imageX, imageY;
3204 RefPtr<Element> dragImage = aDataTransfer->GetDragImage(&imageX, &imageY);
3205
3206 nsCOMPtr<nsIArray> transArray = aDataTransfer->GetTransferables(dragTarget);
3207 if (!transArray) {
3208 return false;
3209 }
3210
3211 RefPtr<DataTransfer> dataTransfer;
3212 if (!dragSession) {
3213 // After this function returns, the DataTransfer will be cleared so it
3214 // appears empty to content. We need to pass a DataTransfer into the Drag
3215 // Session, so we need to make a copy.
3216 aDataTransfer->Clone(aDragTarget, eDrop, aDataTransfer->MozUserCancelled(),
3217 false, getter_AddRefs(dataTransfer));
3218
3219 // Copy over the drop effect, as Clone doesn't copy it for us.
3220 dataTransfer->SetDropEffectInt(aDataTransfer->DropEffectInt());
3221 } else {
3222 MOZ_ASSERT(dragSession->IsSynthesizedForTests())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(dragSession->IsSynthesizedForTests())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(dragSession->IsSynthesizedForTests()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("dragSession->IsSynthesizedForTests()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 3222
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "dragSession->IsSynthesizedForTests()"
")"); do { MOZ_CrashSequence(__null, 3222); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3223 MOZ_ASSERT(aDragEvent->mFlags.mIsSynthesizedForTests)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDragEvent->mFlags.mIsSynthesizedForTests)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aDragEvent->mFlags.mIsSynthesizedForTests))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aDragEvent->mFlags.mIsSynthesizedForTests"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 3223
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDragEvent->mFlags.mIsSynthesizedForTests"
")"); do { MOZ_CrashSequence(__null, 3223); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3224 // If we're initializing synthesized drag session, we should use given
3225 // DataTransfer as is because it'll be used with following drag events
3226 // in any tests, therefore it should be set to nsIDragSession.dataTransfer
3227 // because it and DragEvent.dataTransfer should be same instance.
3228 dataTransfer = aDataTransfer;
3229 }
3230
3231 // XXXndeakin don't really want to create a new drag DOM event
3232 // here, but we need something to pass to the InvokeDragSession
3233 // methods.
3234 RefPtr<DragEvent> event =
3235 NS_NewDOMDragEvent(dragTarget, aPresContext, aDragEvent);
3236
3237 // Use InvokeDragSessionWithSelection if a selection is being dragged,
3238 // such that the image can be generated from the selected text. However,
3239 // use InvokeDragSessionWithImage if a custom image was set or something
3240 // other than a selection is being dragged.
3241 if (!dragImage && aSelection) {
3242 dragService->InvokeDragSessionWithSelection(
3243 aSelection, aPrincipal, aPolicyContainer, aCookieJarSettings,
3244 transArray, action, event, dataTransfer, dragTarget);
3245 } else if (aDragStartData) {
3246 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 3246
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 3246); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3247 dragService->InvokeDragSessionWithRemoteImage(
3248 dragTarget, aPrincipal, aPolicyContainer, aCookieJarSettings,
3249 transArray, action, aDragStartData, event, dataTransfer);
3250 } else {
3251 dragService->InvokeDragSessionWithImage(
3252 dragTarget, aPrincipal, aPolicyContainer, aCookieJarSettings,
3253 transArray, action, dragImage, imageX, imageY, event, dataTransfer);
3254 }
3255
3256 return true;
3257}
3258
3259void EventStateManager::ChangeZoom(bool aIncrease) {
3260 // Send the zoom change to the top level browser so it will be handled by the
3261 // front end in the same way as other zoom actions.
3262 nsIDocShell* docShell = mDocument->GetDocShell();
3263 if (!docShell) {
3264 return;
3265 }
3266
3267 BrowsingContext* bc = docShell->GetBrowsingContext();
3268 if (!bc) {
3269 return;
3270 }
3271
3272 if (XRE_IsParentProcess()) {
3273 bc->Canonical()->DispatchWheelZoomChange(aIncrease);
3274 } else if (BrowserChild* child = BrowserChild::GetFrom(docShell)) {
3275 child->SendWheelZoomChange(aIncrease);
3276 }
3277}
3278
3279void EventStateManager::DoScrollHistory(int32_t direction) {
3280 nsCOMPtr<nsISupports> pcContainer(mPresContext->GetContainerWeak());
3281 if (pcContainer) {
3282 nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(pcContainer));
3283 if (webNav) {
3284 // positive direction to go back one step, nonpositive to go forward
3285 // This is doing user-initiated history traversal, hence we want
3286 // to require that history entries we navigate to have user interaction.
3287 if (direction > 0)
3288 webNav->GoBack(StaticPrefs::browser_navigation_requireUserInteraction(),
3289 true);
3290 else
3291 webNav->GoForward(
3292 StaticPrefs::browser_navigation_requireUserInteraction(), true);
3293 }
3294 }
3295}
3296
3297void EventStateManager::DoScrollZoom(nsIFrame* aTargetFrame,
3298 int32_t adjustment) {
3299 // Exclude content in chrome docshells.
3300 nsIContent* content = aTargetFrame->GetContent();
3301 if (content && !nsContentUtils::IsInChromeDocshell(content->OwnerDoc())) {
3302 // Positive adjustment to decrease zoom, negative to increase
3303 const bool increase = adjustment <= 0;
3304 EnsureDocument(mPresContext);
3305 ChangeZoom(increase);
3306 }
3307}
3308
3309static nsIFrame* GetParentFrameToScroll(nsIFrame* aFrame) {
3310 if (!aFrame) return nullptr;
3311
3312 if (aFrame->StyleDisplay()->mPosition == StylePositionProperty::Fixed &&
3313 nsLayoutUtils::IsReallyFixedPos(aFrame)) {
3314 return aFrame->PresShell()->GetRootScrollContainerFrame();
3315 }
3316 return aFrame->GetParent();
3317}
3318
3319void EventStateManager::DispatchLegacyMouseScrollEvents(
3320 nsIFrame* aTargetFrame, WidgetWheelEvent* aEvent, nsEventStatus* aStatus) {
3321 MOZ_ASSERT(aEvent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aEvent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aEvent", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 3321); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent" ")"
); do { MOZ_CrashSequence(__null, 3321); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3322 MOZ_ASSERT(aStatus)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStatus)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aStatus))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aStatus", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 3322); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStatus" ")"
); do { MOZ_CrashSequence(__null, 3322); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3323
3324 if (!aTargetFrame || *aStatus == nsEventStatus_eConsumeNoDefault) {
3325 return;
3326 }
3327
3328 // Ignore mouse wheel transaction for computing legacy mouse wheel
3329 // events' delta value.
3330 // DOM event's delta vales are computed from CSS pixels.
3331 auto scrollAmountInCSSPixels =
3332 CSSIntSize::FromAppUnitsRounded(aEvent->mScrollAmount);
3333
3334 // XXX We don't deal with fractional amount in legacy event, though the
3335 // default action handler (DoScrollText()) deals with it.
3336 // If we implemented such strict computation, we would need additional
3337 // accumulated delta values. It would made the code more complicated.
3338 // And also it would computes different delta values from older version.
3339 // It doesn't make sense to implement such code for legacy events and
3340 // rare cases.
3341 int32_t scrollDeltaX, scrollDeltaY, pixelDeltaX, pixelDeltaY;
3342 switch (aEvent->mDeltaMode) {
3343 case WheelEvent_Binding::DOM_DELTA_PAGE:
3344 scrollDeltaX = !aEvent->mLineOrPageDeltaX
3345 ? 0
3346 : (aEvent->mLineOrPageDeltaX > 0
3347 ? UIEvent_Binding::SCROLL_PAGE_DOWN
3348 : UIEvent_Binding::SCROLL_PAGE_UP);
3349 scrollDeltaY = !aEvent->mLineOrPageDeltaY
3350 ? 0
3351 : (aEvent->mLineOrPageDeltaY > 0
3352 ? UIEvent_Binding::SCROLL_PAGE_DOWN
3353 : UIEvent_Binding::SCROLL_PAGE_UP);
3354 pixelDeltaX = RoundDown(aEvent->mDeltaX * scrollAmountInCSSPixels.width);
3355 pixelDeltaY = RoundDown(aEvent->mDeltaY * scrollAmountInCSSPixels.height);
3356 break;
3357
3358 case WheelEvent_Binding::DOM_DELTA_LINE:
3359 scrollDeltaX = aEvent->mLineOrPageDeltaX;
3360 scrollDeltaY = aEvent->mLineOrPageDeltaY;
3361 pixelDeltaX = RoundDown(aEvent->mDeltaX * scrollAmountInCSSPixels.width);
3362 pixelDeltaY = RoundDown(aEvent->mDeltaY * scrollAmountInCSSPixels.height);
3363 break;
3364
3365 case WheelEvent_Binding::DOM_DELTA_PIXEL:
3366 scrollDeltaX = aEvent->mLineOrPageDeltaX;
3367 scrollDeltaY = aEvent->mLineOrPageDeltaY;
3368 pixelDeltaX = RoundDown(aEvent->mDeltaX);
3369 pixelDeltaY = RoundDown(aEvent->mDeltaY);
3370 break;
3371
3372 default:
3373 MOZ_CRASH("Invalid deltaMode value comes")do { do { } while (false); MOZ_ReportCrash("" "Invalid deltaMode value comes"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 3373
); AnnotateMozCrashReason("MOZ_CRASH(" "Invalid deltaMode value comes"
")"); do { MOZ_CrashSequence(__null, 3373); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
3374 }
3375
3376 // Send the legacy events in following order:
3377 // 1. Vertical scroll
3378 // 2. Vertical pixel scroll (even if #1 isn't consumed)
3379 // 3. Horizontal scroll (even if #1 and/or #2 are consumed)
3380 // 4. Horizontal pixel scroll (even if #3 isn't consumed)
3381
3382 AutoWeakFrame targetFrame(aTargetFrame);
3383
3384 MOZ_ASSERT(*aStatus != nsEventStatus_eConsumeNoDefault &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(*aStatus != nsEventStatus_eConsumeNoDefault &&
!aEvent->DefaultPrevented())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*aStatus != nsEventStatus_eConsumeNoDefault
&& !aEvent->DefaultPrevented()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("*aStatus != nsEventStatus_eConsumeNoDefault && !aEvent->DefaultPrevented()"
" (" "If you make legacy events dispatched for default prevented wheel "
"event, you need to initialize stateX and stateY" ")", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 3387); AnnotateMozCrashReason("MOZ_ASSERT" "(" "*aStatus != nsEventStatus_eConsumeNoDefault && !aEvent->DefaultPrevented()"
") (" "If you make legacy events dispatched for default prevented wheel "
"event, you need to initialize stateX and stateY" ")"); do {
MOZ_CrashSequence(__null, 3387); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
3385 !aEvent->DefaultPrevented(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(*aStatus != nsEventStatus_eConsumeNoDefault &&
!aEvent->DefaultPrevented())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*aStatus != nsEventStatus_eConsumeNoDefault
&& !aEvent->DefaultPrevented()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("*aStatus != nsEventStatus_eConsumeNoDefault && !aEvent->DefaultPrevented()"
" (" "If you make legacy events dispatched for default prevented wheel "
"event, you need to initialize stateX and stateY" ")", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 3387); AnnotateMozCrashReason("MOZ_ASSERT" "(" "*aStatus != nsEventStatus_eConsumeNoDefault && !aEvent->DefaultPrevented()"
") (" "If you make legacy events dispatched for default prevented wheel "
"event, you need to initialize stateX and stateY" ")"); do {
MOZ_CrashSequence(__null, 3387); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
3386 "If you make legacy events dispatched for default prevented wheel "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(*aStatus != nsEventStatus_eConsumeNoDefault &&
!aEvent->DefaultPrevented())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*aStatus != nsEventStatus_eConsumeNoDefault
&& !aEvent->DefaultPrevented()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("*aStatus != nsEventStatus_eConsumeNoDefault && !aEvent->DefaultPrevented()"
" (" "If you make legacy events dispatched for default prevented wheel "
"event, you need to initialize stateX and stateY" ")", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 3387); AnnotateMozCrashReason("MOZ_ASSERT" "(" "*aStatus != nsEventStatus_eConsumeNoDefault && !aEvent->DefaultPrevented()"
") (" "If you make legacy events dispatched for default prevented wheel "
"event, you need to initialize stateX and stateY" ")"); do {
MOZ_CrashSequence(__null, 3387); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
3387 "event, you need to initialize stateX and stateY")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(*aStatus != nsEventStatus_eConsumeNoDefault &&
!aEvent->DefaultPrevented())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*aStatus != nsEventStatus_eConsumeNoDefault
&& !aEvent->DefaultPrevented()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("*aStatus != nsEventStatus_eConsumeNoDefault && !aEvent->DefaultPrevented()"
" (" "If you make legacy events dispatched for default prevented wheel "
"event, you need to initialize stateX and stateY" ")", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 3387); AnnotateMozCrashReason("MOZ_ASSERT" "(" "*aStatus != nsEventStatus_eConsumeNoDefault && !aEvent->DefaultPrevented()"
") (" "If you make legacy events dispatched for default prevented wheel "
"event, you need to initialize stateX and stateY" ")"); do {
MOZ_CrashSequence(__null, 3387); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
3388 EventState stateX, stateY;
3389 if (scrollDeltaY) {
3390 SendLineScrollEvent(aTargetFrame, aEvent, stateY, scrollDeltaY,
3391 DELTA_DIRECTION_Y);
3392 if (!targetFrame.IsAlive()) {
3393 *aStatus = nsEventStatus_eConsumeNoDefault;
3394 return;
3395 }
3396 }
3397
3398 if (pixelDeltaY) {
3399 SendPixelScrollEvent(aTargetFrame, aEvent, stateY, pixelDeltaY,
3400 DELTA_DIRECTION_Y);
3401 if (!targetFrame.IsAlive()) {
3402 *aStatus = nsEventStatus_eConsumeNoDefault;
3403 return;
3404 }
3405 }
3406
3407 if (scrollDeltaX) {
3408 SendLineScrollEvent(aTargetFrame, aEvent, stateX, scrollDeltaX,
3409 DELTA_DIRECTION_X);
3410 if (!targetFrame.IsAlive()) {
3411 *aStatus = nsEventStatus_eConsumeNoDefault;
3412 return;
3413 }
3414 }
3415
3416 if (pixelDeltaX) {
3417 SendPixelScrollEvent(aTargetFrame, aEvent, stateX, pixelDeltaX,
3418 DELTA_DIRECTION_X);
3419 if (!targetFrame.IsAlive()) {
3420 *aStatus = nsEventStatus_eConsumeNoDefault;
3421 return;
3422 }
3423 }
3424
3425 if (stateY.mDefaultPrevented) {
3426 *aStatus = nsEventStatus_eConsumeNoDefault;
3427 aEvent->PreventDefault(!stateY.mDefaultPreventedByContent);
3428 }
3429
3430 if (stateX.mDefaultPrevented) {
3431 *aStatus = nsEventStatus_eConsumeNoDefault;
3432 aEvent->PreventDefault(!stateX.mDefaultPreventedByContent);
3433 }
3434}
3435
3436void EventStateManager::SendLineScrollEvent(nsIFrame* aTargetFrame,
3437 WidgetWheelEvent* aEvent,
3438 EventState& aState, int32_t aDelta,
3439 DeltaDirection aDeltaDirection) {
3440 nsCOMPtr<nsIContent> targetContent = aTargetFrame->GetContent();
3441 if (!targetContent) {
3442 targetContent = GetFocusedElement();
3443 if (!targetContent) {
3444 return;
3445 }
3446 }
3447
3448 while (targetContent->IsText()) {
3449 targetContent = targetContent->GetFlattenedTreeParent();
3450 }
3451
3452 WidgetMouseScrollEvent event(aEvent->IsTrusted(),
3453 eLegacyMouseLineOrPageScroll, aEvent->mWidget);
3454 event.mFlags.mDefaultPrevented = aState.mDefaultPrevented;
3455 event.mFlags.mDefaultPreventedByContent = aState.mDefaultPreventedByContent;
3456 event.mRefPoint = aEvent->mRefPoint;
3457 event.mTimeStamp = aEvent->mTimeStamp;
3458 event.mModifiers = aEvent->mModifiers;
3459 event.mButtons = aEvent->mButtons;
3460 event.mIsHorizontal = (aDeltaDirection == DELTA_DIRECTION_X);
3461 event.mDelta = aDelta;
3462 event.mInputSource = aEvent->mInputSource;
3463
3464 RefPtr<nsPresContext> presContext = aTargetFrame->PresContext();
3465 nsEventStatus status = nsEventStatus_eIgnore;
3466 EventDispatcher::Dispatch(targetContent, presContext, &event, nullptr,
3467 &status);
3468 aState.mDefaultPrevented =
3469 event.DefaultPrevented() || status == nsEventStatus_eConsumeNoDefault;
3470 aState.mDefaultPreventedByContent = event.DefaultPreventedByContent();
3471}
3472
3473void EventStateManager::SendPixelScrollEvent(nsIFrame* aTargetFrame,
3474 WidgetWheelEvent* aEvent,
3475 EventState& aState,
3476 int32_t aPixelDelta,
3477 DeltaDirection aDeltaDirection) {
3478 nsCOMPtr<nsIContent> targetContent = aTargetFrame->GetContent();
3479 if (!targetContent) {
3480 targetContent = GetFocusedElement();
3481 if (!targetContent) {
3482 return;
3483 }
3484 }
3485
3486 while (targetContent->IsText()) {
3487 targetContent = targetContent->GetFlattenedTreeParent();
3488 }
3489
3490 WidgetMouseScrollEvent event(aEvent->IsTrusted(), eLegacyMousePixelScroll,
3491 aEvent->mWidget);
3492 event.mFlags.mDefaultPrevented = aState.mDefaultPrevented;
3493 event.mFlags.mDefaultPreventedByContent = aState.mDefaultPreventedByContent;
3494 event.mRefPoint = aEvent->mRefPoint;
3495 event.mTimeStamp = aEvent->mTimeStamp;
3496 event.mModifiers = aEvent->mModifiers;
3497 event.mButtons = aEvent->mButtons;
3498 event.mIsHorizontal = (aDeltaDirection == DELTA_DIRECTION_X);
3499 event.mDelta = aPixelDelta;
3500 event.mInputSource = aEvent->mInputSource;
3501
3502 RefPtr<nsPresContext> presContext = aTargetFrame->PresContext();
3503 nsEventStatus status = nsEventStatus_eIgnore;
3504 EventDispatcher::Dispatch(targetContent, presContext, &event, nullptr,
3505 &status);
3506 aState.mDefaultPrevented =
3507 event.DefaultPrevented() || status == nsEventStatus_eConsumeNoDefault;
3508 aState.mDefaultPreventedByContent = event.DefaultPreventedByContent();
3509}
3510
3511ScrollContainerFrame*
3512EventStateManager::ComputeScrollTargetAndMayAdjustWheelEvent(
3513 nsIFrame* aTargetFrame, WidgetWheelEvent* aEvent,
3514 ComputeScrollTargetOptions aOptions) {
3515 return ComputeScrollTargetAndMayAdjustWheelEvent(
3516 aTargetFrame, aEvent->mDeltaX, aEvent->mDeltaY, aEvent, aOptions);
3517}
3518
3519// Overload ComputeScrollTargetAndMayAdjustWheelEvent method to allow passing
3520// "test" dx and dy when looking for which scrollbarmediators to activate when
3521// two finger down on trackpad and before any actual motion
3522ScrollContainerFrame*
3523EventStateManager::ComputeScrollTargetAndMayAdjustWheelEvent(
3524 nsIFrame* aTargetFrame, double aDirectionX, double aDirectionY,
3525 WidgetWheelEvent* aEvent, ComputeScrollTargetOptions aOptions) {
3526 bool isAutoDir = false;
3527 bool honoursRoot = false;
3528 if (MAY_BE_ADJUSTED_BY_AUTO_DIR & aOptions) {
3529 // If the scroll is respected as auto-dir, aDirection* should always be
3530 // equivalent to the event's delta vlaues(Currently, there are only one case
3531 // where aDirection*s have different values from the widget wheel event's
3532 // original delta values and the only case isn't auto-dir, see
3533 // ScrollbarsForWheel::TemporarilyActivateAllPossibleScrollTargets).
3534 MOZ_ASSERT(aDirectionX == aEvent->mDeltaX &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDirectionX == aEvent->mDeltaX && aDirectionY
== aEvent->mDeltaY)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDirectionX == aEvent->mDeltaX
&& aDirectionY == aEvent->mDeltaY))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aDirectionX == aEvent->mDeltaX && aDirectionY == aEvent->mDeltaY"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 3535
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDirectionX == aEvent->mDeltaX && aDirectionY == aEvent->mDeltaY"
")"); do { MOZ_CrashSequence(__null, 3535); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3535 aDirectionY == aEvent->mDeltaY)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDirectionX == aEvent->mDeltaX && aDirectionY
== aEvent->mDeltaY)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDirectionX == aEvent->mDeltaX
&& aDirectionY == aEvent->mDeltaY))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aDirectionX == aEvent->mDeltaX && aDirectionY == aEvent->mDeltaY"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 3535
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDirectionX == aEvent->mDeltaX && aDirectionY == aEvent->mDeltaY"
")"); do { MOZ_CrashSequence(__null, 3535); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3536
3537 WheelDeltaAdjustmentStrategy strategy =
3538 GetWheelDeltaAdjustmentStrategy(*aEvent);
3539 switch (strategy) {
3540 case WheelDeltaAdjustmentStrategy::eAutoDir:
3541 isAutoDir = true;
3542 honoursRoot = false;
3543 break;
3544 case WheelDeltaAdjustmentStrategy::eAutoDirWithRootHonour:
3545 isAutoDir = true;
3546 honoursRoot = true;
3547 break;
3548 default:
3549 break;
3550 }
3551 }
3552
3553 if (aOptions & PREFER_MOUSE_WHEEL_TRANSACTION) {
3554 // If the user recently scrolled with the mousewheel, then they probably
3555 // want to scroll the same view as before instead of the view under the
3556 // cursor. WheelTransaction tracks the frame currently being
3557 // scrolled with the mousewheel. We consider the transaction ended when the
3558 // mouse moves more than "mousewheel.transaction.ignoremovedelay"
3559 // milliseconds after the last scroll operation, or any time the mouse moves
3560 // out of the frame, or when more than "mousewheel.transaction.timeout"
3561 // milliseconds have passed after the last operation, even if the mouse
3562 // hasn't moved.
3563 nsIFrame* lastScrollFrame = WheelTransaction::GetScrollTargetFrame();
3564 if (lastScrollFrame) {
3565 ScrollContainerFrame* scrollContainerFrame =
3566 lastScrollFrame->GetScrollTargetFrame();
3567 if (scrollContainerFrame) {
3568 if (isAutoDir) {
3569 ESMAutoDirWheelDeltaAdjuster adjuster(*aEvent, *lastScrollFrame,
3570 honoursRoot);
3571 // Note that calling this function will not always cause the delta to
3572 // be adjusted, it only adjusts the delta when it should, because
3573 // Adjust() internally calls ShouldBeAdjusted() before making
3574 // adjustment.
3575 adjuster.Adjust();
3576 }
3577 return scrollContainerFrame;
3578 }
3579 }
3580 }
3581
3582 // If the event doesn't cause scroll actually, we cannot find scroll target
3583 // because we check if the event can cause scroll actually on each found
3584 // scrollable frame.
3585 if (!aDirectionX && !aDirectionY) {
3586 return nullptr;
3587 }
3588
3589 bool checkIfScrollableX;
3590 bool checkIfScrollableY;
3591 if (isAutoDir) {
3592 // Always check the frame's scrollability in both the two directions for an
3593 // auto-dir scroll. That is, for an auto-dir scroll,
3594 // PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS and
3595 // PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS should be ignored.
3596 checkIfScrollableX = true;
3597 checkIfScrollableY = true;
3598 } else {
3599 checkIfScrollableX =
3600 aDirectionX &&
3601 (aOptions & PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS);
3602 checkIfScrollableY =
3603 aDirectionY &&
3604 (aOptions & PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS);
3605 }
3606
3607 nsIFrame* scrollFrame = !(aOptions & START_FROM_PARENT)
3608 ? aTargetFrame
3609 : GetParentFrameToScroll(aTargetFrame);
3610 for (; scrollFrame; scrollFrame = GetParentFrameToScroll(scrollFrame)) {
3611 // Check whether the frame wants to provide us with a scrollable view.
3612 ScrollContainerFrame* scrollContainerFrame =
3613 scrollFrame->GetScrollTargetFrame();
3614 if (!scrollContainerFrame) {
3615 nsMenuPopupFrame* menuPopupFrame = do_QueryFrame(scrollFrame);
3616 if (menuPopupFrame) {
3617 return nullptr;
3618 }
3619 continue;
3620 }
3621
3622 if (!checkIfScrollableX && !checkIfScrollableY) {
3623 return scrollContainerFrame;
3624 }
3625
3626 // If the frame disregards the direction the user is trying to scroll, then
3627 // it should just bubbles the scroll event up to its parental scroll frame
3628
3629 Maybe<layers::ScrollDirection> disregardedDirection =
3630 WheelHandlingUtils::GetDisregardedWheelScrollDirection(scrollFrame);
3631 if (disregardedDirection) {
3632 switch (disregardedDirection.ref()) {
3633 case layers::ScrollDirection::eHorizontal:
3634 if (checkIfScrollableX) {
3635 continue;
3636 }
3637 break;
3638 case layers::ScrollDirection::eVertical:
3639 if (checkIfScrollableY) {
3640 continue;
3641 }
3642 break;
3643 }
3644 }
3645
3646 layers::ScrollDirections directions =
3647 scrollContainerFrame
3648 ->GetAvailableScrollingDirectionsForUserInputEvents();
3649 if ((!(directions.contains(layers::ScrollDirection::eVertical)) &&
3650 !(directions.contains(layers::ScrollDirection::eHorizontal))) ||
3651 (checkIfScrollableY && !checkIfScrollableX &&
3652 !(directions.contains(layers::ScrollDirection::eVertical))) ||
3653 (checkIfScrollableX && !checkIfScrollableY &&
3654 !(directions.contains(layers::ScrollDirection::eHorizontal)))) {
3655 continue;
3656 }
3657
3658 // Computes whether the currently checked frame is scrollable by this wheel
3659 // event.
3660 bool canScroll = false;
3661 if (isAutoDir) {
3662 ESMAutoDirWheelDeltaAdjuster adjuster(*aEvent, *scrollFrame, honoursRoot);
3663 if (adjuster.ShouldBeAdjusted()) {
3664 adjuster.Adjust();
3665 canScroll = true;
3666 } else if (WheelHandlingUtils::CanScrollOn(scrollContainerFrame,
3667 aDirectionX, aDirectionY)) {
3668 canScroll = true;
3669 }
3670 } else if (WheelHandlingUtils::CanScrollOn(scrollContainerFrame,
3671 aDirectionX, aDirectionY)) {
3672 canScroll = true;
3673 }
3674
3675 if (canScroll) {
3676 return scrollContainerFrame;
3677 }
3678
3679 // Where we are at is the block ending in a for loop.
3680 // The current frame has been checked to be unscrollable by this wheel
3681 // event, continue the loop to check its parent, if any.
3682 }
3683
3684 nsIFrame* newFrame = nsLayoutUtils::GetCrossDocParentFrameInProcess(
3685 aTargetFrame->PresShell()->GetRootFrame());
3686 aOptions =
3687 static_cast<ComputeScrollTargetOptions>(aOptions & ~START_FROM_PARENT);
3688 if (!newFrame) {
3689 return nullptr;
3690 }
3691 return ComputeScrollTargetAndMayAdjustWheelEvent(newFrame, aEvent, aOptions);
3692}
3693
3694nsSize EventStateManager::GetScrollAmount(
3695 nsPresContext* aPresContext, WidgetWheelEvent* aEvent,
3696 ScrollContainerFrame* aScrollContainerFrame) {
3697 MOZ_ASSERT(aPresContext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPresContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPresContext))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aPresContext", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 3697); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresContext"
")"); do { MOZ_CrashSequence(__null, 3697); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3698 MOZ_ASSERT(aEvent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aEvent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aEvent", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 3698); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent" ")"
); do { MOZ_CrashSequence(__null, 3698); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3699
3700 const bool isPage = aEvent->mDeltaMode == WheelEvent_Binding::DOM_DELTA_PAGE;
3701 if (!aScrollContainerFrame) {
3702 // If there is no scrollable frame, we should use root, see below.
3703 aScrollContainerFrame =
3704 aPresContext->PresShell()->GetRootScrollContainerFrame();
3705 }
3706
3707 if (aScrollContainerFrame) {
3708 return isPage ? aScrollContainerFrame->GetPageScrollAmount()
3709 : aScrollContainerFrame->GetLineScrollAmount();
3710 }
3711
3712 // If there is no scrollable frame and page scrolling, use viewport size.
3713 if (isPage) {
3714 return aPresContext->GetVisibleArea().Size();
3715 }
3716
3717 // Otherwise use root frame's font metrics.
3718 //
3719 // FIXME(emilio): Should this use the root element's style frame? The root
3720 // frame will always have the initial font. Then again it should never matter
3721 // for content, we should always have a root scrollable frame in html
3722 // documents.
3723 nsIFrame* rootFrame = aPresContext->PresShell()->GetRootFrame();
3724 if (!rootFrame) {
3725 return nsSize(0, 0);
3726 }
3727 RefPtr<nsFontMetrics> fm =
3728 nsLayoutUtils::GetInflatedFontMetricsForFrame(rootFrame);
3729 NS_ENSURE_TRUE(fm, nsSize(0, 0))do { if ((__builtin_expect(!!(!(fm)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "fm" ") failed", nullptr, "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 3729); return nsSize(0, 0); } } while (false)
;
3730 return nsSize(fm->AveCharWidth(), fm->MaxHeight());
3731}
3732
3733void EventStateManager::DoScrollText(
3734 ScrollContainerFrame* aScrollContainerFrame, WidgetWheelEvent* aEvent) {
3735 MOZ_ASSERT(aScrollContainerFrame)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aScrollContainerFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aScrollContainerFrame))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("aScrollContainerFrame"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 3735
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aScrollContainerFrame"
")"); do { MOZ_CrashSequence(__null, 3735); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3736 MOZ_ASSERT(aEvent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aEvent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aEvent", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 3736); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent" ")"
); do { MOZ_CrashSequence(__null, 3736); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3737
3738 AutoWeakFrame scrollFrameWeak(aScrollContainerFrame);
3739 AutoWeakFrame eventFrameWeak(mCurrentTarget);
3740 if (!WheelTransaction::WillHandleDefaultAction(aEvent, scrollFrameWeak,
3741 eventFrameWeak)) {
3742 return;
3743 }
3744
3745 // Default action's actual scroll amount should be computed from device
3746 // pixels.
3747 nsPresContext* pc = aScrollContainerFrame->PresContext();
3748 nsSize scrollAmount = GetScrollAmount(pc, aEvent, aScrollContainerFrame);
3749 nsIntSize scrollAmountInDevPixels(
3750 pc->AppUnitsToDevPixels(scrollAmount.width),
3751 pc->AppUnitsToDevPixels(scrollAmount.height));
3752 nsIntPoint actualDevPixelScrollAmount =
3753 DeltaAccumulator::GetInstance()->ComputeScrollAmountForDefaultAction(
3754 aEvent, scrollAmountInDevPixels);
3755
3756 // Don't scroll around the axis whose overflow style is hidden.
3757 ScrollStyles overflowStyle = aScrollContainerFrame->GetScrollStyles();
3758 if (overflowStyle.mHorizontal == StyleOverflow::Hidden) {
3759 actualDevPixelScrollAmount.x = 0;
3760 }
3761 if (overflowStyle.mVertical == StyleOverflow::Hidden) {
3762 actualDevPixelScrollAmount.y = 0;
3763 }
3764
3765 ScrollSnapFlags snapFlags = ScrollSnapFlags::IntendedDirection;
3766 mozilla::ScrollOrigin origin = mozilla::ScrollOrigin::NotSpecified;
3767 switch (aEvent->mDeltaMode) {
3768 case WheelEvent_Binding::DOM_DELTA_LINE:
3769 origin = mozilla::ScrollOrigin::MouseWheel;
3770 break;
3771 case WheelEvent_Binding::DOM_DELTA_PAGE:
3772 origin = mozilla::ScrollOrigin::Pages;
3773 snapFlags |= ScrollSnapFlags::IntendedEndPosition;
3774 break;
3775 case WheelEvent_Binding::DOM_DELTA_PIXEL:
3776 origin = mozilla::ScrollOrigin::Pixels;
3777 break;
3778 default:
3779 MOZ_CRASH("Invalid deltaMode value comes")do { do { } while (false); MOZ_ReportCrash("" "Invalid deltaMode value comes"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 3779
); AnnotateMozCrashReason("MOZ_CRASH(" "Invalid deltaMode value comes"
")"); do { MOZ_CrashSequence(__null, 3779); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
3780 }
3781
3782 // We shouldn't scroll more one page at once except when over one page scroll
3783 // is allowed for the event.
3784 nsSize pageSize = aScrollContainerFrame->GetPageScrollAmount();
3785 nsIntSize devPixelPageSize(pc->AppUnitsToDevPixels(pageSize.width),
3786 pc->AppUnitsToDevPixels(pageSize.height));
3787 if (!WheelPrefs::GetInstance()->IsOverOnePageScrollAllowedX(aEvent) &&
3788 Abs(actualDevPixelScrollAmount.x.value) >
3789 (unsigned)std::max(devPixelPageSize.width, 0)) {
3790 actualDevPixelScrollAmount.x = (actualDevPixelScrollAmount.x >= 0)
3791 ? devPixelPageSize.width
3792 : -devPixelPageSize.width;
3793 }
3794
3795 if (!WheelPrefs::GetInstance()->IsOverOnePageScrollAllowedY(aEvent) &&
3796 Abs(actualDevPixelScrollAmount.y.value) >
3797 (unsigned)std::max(devPixelPageSize.height, 0)) {
3798 actualDevPixelScrollAmount.y = (actualDevPixelScrollAmount.y >= 0)
3799 ? devPixelPageSize.height
3800 : -devPixelPageSize.height;
3801 }
3802
3803 bool isDeltaModePixel =
3804 (aEvent->mDeltaMode == WheelEvent_Binding::DOM_DELTA_PIXEL);
3805
3806 ScrollMode mode;
3807 switch (aEvent->mScrollType) {
3808 case WidgetWheelEvent::SCROLL_DEFAULT:
3809 if (isDeltaModePixel) {
3810 mode = ScrollMode::Normal;
3811 } else {
3812 mode = ScrollMode::Smooth;
3813 }
3814 break;
3815 case WidgetWheelEvent::SCROLL_SYNCHRONOUSLY:
3816 mode = ScrollMode::Instant;
3817 break;
3818 case WidgetWheelEvent::SCROLL_ASYNCHRONOUSLY:
3819 mode = ScrollMode::Normal;
3820 break;
3821 case WidgetWheelEvent::SCROLL_SMOOTHLY:
3822 mode = ScrollMode::Smooth;
3823 break;
3824 default:
3825 MOZ_CRASH("Invalid mScrollType value comes")do { do { } while (false); MOZ_ReportCrash("" "Invalid mScrollType value comes"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 3825
); AnnotateMozCrashReason("MOZ_CRASH(" "Invalid mScrollType value comes"
")"); do { MOZ_CrashSequence(__null, 3825); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
3826 }
3827
3828 ScrollContainerFrame::ScrollMomentum momentum =
3829 aEvent->mIsMomentum ? ScrollContainerFrame::SYNTHESIZED_MOMENTUM_EVENT
3830 : ScrollContainerFrame::NOT_MOMENTUM;
3831
3832 nsIntPoint overflow;
3833 aScrollContainerFrame->ScrollBy(actualDevPixelScrollAmount,
3834 ScrollUnit::DEVICE_PIXELS, mode, &overflow,
3835 origin, momentum, snapFlags);
3836
3837 if (!scrollFrameWeak.IsAlive()) {
3838 // If the scroll causes changing the layout, we can think that the event
3839 // has been completely consumed by the content. Then, users probably don't
3840 // want additional action.
3841 aEvent->mOverflowDeltaX = aEvent->mOverflowDeltaY = 0;
3842 } else if (isDeltaModePixel) {
3843 aEvent->mOverflowDeltaX = overflow.x;
3844 aEvent->mOverflowDeltaY = overflow.y;
3845 } else {
3846 aEvent->mOverflowDeltaX =
3847 static_cast<double>(overflow.x) / scrollAmountInDevPixels.width;
3848 aEvent->mOverflowDeltaY =
3849 static_cast<double>(overflow.y) / scrollAmountInDevPixels.height;
3850 }
3851
3852 // If CSS overflow properties caused not to scroll, the overflowDelta* values
3853 // should be same as delta* values since they may be used as gesture event by
3854 // widget. However, if there is another scrollable element in the ancestor
3855 // along the axis, probably users don't want the operation to cause
3856 // additional action such as moving history. In such case, overflowDelta
3857 // values should stay zero.
3858 if (scrollFrameWeak.IsAlive()) {
3859 if (aEvent->mDeltaX && overflowStyle.mHorizontal == StyleOverflow::Hidden &&
3860 !ComputeScrollTargetAndMayAdjustWheelEvent(
3861 aScrollContainerFrame, aEvent,
3862 COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS_WITH_AUTO_DIR)) {
3863 aEvent->mOverflowDeltaX = aEvent->mDeltaX;
3864 }
3865 if (aEvent->mDeltaY && overflowStyle.mVertical == StyleOverflow::Hidden &&
3866 !ComputeScrollTargetAndMayAdjustWheelEvent(
3867 aScrollContainerFrame, aEvent,
3868 COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS_WITH_AUTO_DIR)) {
3869 aEvent->mOverflowDeltaY = aEvent->mDeltaY;
3870 }
3871 }
3872
3873 NS_ASSERTION(do { if (!(aEvent->mOverflowDeltaX == 0 || (aEvent->mOverflowDeltaX
> 0) == (aEvent->mDeltaX > 0))) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "The sign of mOverflowDeltaX is different from the scroll direction"
, "aEvent->mOverflowDeltaX == 0 || (aEvent->mOverflowDeltaX > 0) == (aEvent->mDeltaX > 0)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 3876
); MOZ_PretendNoReturn(); } } while (0)
3874 aEvent->mOverflowDeltaX == 0 ||do { if (!(aEvent->mOverflowDeltaX == 0 || (aEvent->mOverflowDeltaX
> 0) == (aEvent->mDeltaX > 0))) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "The sign of mOverflowDeltaX is different from the scroll direction"
, "aEvent->mOverflowDeltaX == 0 || (aEvent->mOverflowDeltaX > 0) == (aEvent->mDeltaX > 0)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 3876
); MOZ_PretendNoReturn(); } } while (0)
3875 (aEvent->mOverflowDeltaX > 0) == (aEvent->mDeltaX > 0),do { if (!(aEvent->mOverflowDeltaX == 0 || (aEvent->mOverflowDeltaX
> 0) == (aEvent->mDeltaX > 0))) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "The sign of mOverflowDeltaX is different from the scroll direction"
, "aEvent->mOverflowDeltaX == 0 || (aEvent->mOverflowDeltaX > 0) == (aEvent->mDeltaX > 0)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 3876
); MOZ_PretendNoReturn(); } } while (0)
3876 "The sign of mOverflowDeltaX is different from the scroll direction")do { if (!(aEvent->mOverflowDeltaX == 0 || (aEvent->mOverflowDeltaX
> 0) == (aEvent->mDeltaX > 0))) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "The sign of mOverflowDeltaX is different from the scroll direction"
, "aEvent->mOverflowDeltaX == 0 || (aEvent->mOverflowDeltaX > 0) == (aEvent->mDeltaX > 0)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 3876
); MOZ_PretendNoReturn(); } } while (0)
;
3877 NS_ASSERTION(do { if (!(aEvent->mOverflowDeltaY == 0 || (aEvent->mOverflowDeltaY
> 0) == (aEvent->mDeltaY > 0))) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "The sign of mOverflowDeltaY is different from the scroll direction"
, "aEvent->mOverflowDeltaY == 0 || (aEvent->mOverflowDeltaY > 0) == (aEvent->mDeltaY > 0)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 3880
); MOZ_PretendNoReturn(); } } while (0)
3878 aEvent->mOverflowDeltaY == 0 ||do { if (!(aEvent->mOverflowDeltaY == 0 || (aEvent->mOverflowDeltaY
> 0) == (aEvent->mDeltaY > 0))) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "The sign of mOverflowDeltaY is different from the scroll direction"
, "aEvent->mOverflowDeltaY == 0 || (aEvent->mOverflowDeltaY > 0) == (aEvent->mDeltaY > 0)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 3880
); MOZ_PretendNoReturn(); } } while (0)
3879 (aEvent->mOverflowDeltaY > 0) == (aEvent->mDeltaY > 0),do { if (!(aEvent->mOverflowDeltaY == 0 || (aEvent->mOverflowDeltaY
> 0) == (aEvent->mDeltaY > 0))) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "The sign of mOverflowDeltaY is different from the scroll direction"
, "aEvent->mOverflowDeltaY == 0 || (aEvent->mOverflowDeltaY > 0) == (aEvent->mDeltaY > 0)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 3880
); MOZ_PretendNoReturn(); } } while (0)
3880 "The sign of mOverflowDeltaY is different from the scroll direction")do { if (!(aEvent->mOverflowDeltaY == 0 || (aEvent->mOverflowDeltaY
> 0) == (aEvent->mDeltaY > 0))) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "The sign of mOverflowDeltaY is different from the scroll direction"
, "aEvent->mOverflowDeltaY == 0 || (aEvent->mOverflowDeltaY > 0) == (aEvent->mDeltaY > 0)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 3880
); MOZ_PretendNoReturn(); } } while (0)
;
3881
3882 WheelPrefs::GetInstance()->CancelApplyingUserPrefsFromOverflowDelta(aEvent);
3883}
3884
3885void EventStateManager::DecideGestureEvent(WidgetGestureNotifyEvent* aEvent,
3886 nsIFrame* targetFrame) {
3887 NS_ASSERTION(aEvent->mMessage == eGestureNotify,do { if (!(aEvent->mMessage == eGestureNotify)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "DecideGestureEvent called with a non-gesture event"
, "aEvent->mMessage == eGestureNotify", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 3888); MOZ_PretendNoReturn(); } } while (0)
3888 "DecideGestureEvent called with a non-gesture event")do { if (!(aEvent->mMessage == eGestureNotify)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "DecideGestureEvent called with a non-gesture event"
, "aEvent->mMessage == eGestureNotify", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 3888); MOZ_PretendNoReturn(); } } while (0)
;
3889
3890 /* Check the ancestor tree to decide if any frame is willing* to receive
3891 * a MozPixelScroll event. If that's the case, the current touch gesture
3892 * will be used as a pan gesture; otherwise it will be a regular
3893 * mousedown/mousemove/click event.
3894 *
3895 * *willing: determine if it makes sense to pan the element using scroll
3896 * events:
3897 * - For web content: if there are any visible scrollbars on the touch point
3898 * - For XUL: if it's an scrollable element that can currently scroll in some
3899 * direction.
3900 *
3901 * Note: we'll have to one-off various cases to ensure a good usable behavior
3902 */
3903 WidgetGestureNotifyEvent::PanDirection panDirection =
3904 WidgetGestureNotifyEvent::ePanNone;
3905 bool displayPanFeedback = false;
3906 for (nsIFrame* current = targetFrame; current;
3907 current = nsLayoutUtils::GetCrossDocParentFrame(current)) {
3908 // e10s - mark remote content as pannable. This is a work around since
3909 // we don't have access to remote frame scroll info here. Apz data may
3910 // assist is solving this.
3911 if (current && IsTopLevelRemoteTarget(current->GetContent())) {
3912 panDirection = WidgetGestureNotifyEvent::ePanBoth;
3913 // We don't know when we reach bounds, so just disable feedback for now.
3914 displayPanFeedback = false;
3915 break;
3916 }
3917
3918 LayoutFrameType currentFrameType = current->Type();
3919
3920 // Scrollbars should always be draggable
3921 if (currentFrameType == LayoutFrameType::Scrollbar) {
3922 panDirection = WidgetGestureNotifyEvent::ePanNone;
3923 break;
3924 }
3925
3926 // Special check for trees
3927 if (nsTreeBodyFrame* treeFrame = do_QueryFrame(current)) {
3928 if (treeFrame->GetVerticalOverflow()) {
3929 panDirection = WidgetGestureNotifyEvent::ePanVertical;
3930 }
3931 break;
3932 }
3933
3934 if (ScrollContainerFrame* scrollContainerFrame = do_QueryFrame(current)) {
3935 layers::ScrollDirections scrollbarVisibility =
3936 scrollContainerFrame->GetScrollbarVisibility();
3937
3938 // Check if we have visible scrollbars
3939 if (scrollbarVisibility.contains(layers::ScrollDirection::eVertical)) {
3940 panDirection = WidgetGestureNotifyEvent::ePanVertical;
3941 displayPanFeedback = true;
3942 break;
3943 }
3944
3945 if (scrollbarVisibility.contains(layers::ScrollDirection::eHorizontal)) {
3946 panDirection = WidgetGestureNotifyEvent::ePanHorizontal;
3947 displayPanFeedback = true;
3948 }
3949 }
3950 } // ancestor chain
3951 aEvent->mDisplayPanFeedback = displayPanFeedback;
3952 aEvent->mPanDirection = panDirection;
3953}
3954
3955#ifdef XP_MACOSX
3956static nsINode* GetCrossDocParentNode(nsINode* aChild) {
3957 MOZ_ASSERT(aChild, "The child is null!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChild)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aChild))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aChild" " (" "The child is null!"
")", "/root/firefox-clang/dom/events/EventStateManager.cpp",
3957); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild" ") ("
"The child is null!" ")"); do { MOZ_CrashSequence(__null, 3957
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
3958 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 3958
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 3958); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3959
3960 nsINode* parent = aChild->GetParentNode();
3961 if (parent && parent->IsContent() && aChild->IsContent()) {
3962 parent = aChild->AsContent()->GetFlattenedTreeParent();
3963 }
3964
3965 if (parent || !aChild->IsDocument()) {
3966 return parent;
3967 }
3968
3969 return aChild->AsDocument()->GetEmbedderElement();
3970}
3971
3972static bool NodeAllowsClickThrough(nsINode* aNode) {
3973 while (aNode) {
3974 if (aNode->IsAnyOfXULElements(nsGkAtoms::browser, nsGkAtoms::tree)) {
3975 return false;
3976 }
3977 if (aNode->IsAnyOfXULElements(nsGkAtoms::scrollbar, nsGkAtoms::resizer)) {
3978 return true;
3979 }
3980 aNode = GetCrossDocParentNode(aNode);
3981 }
3982 return true;
3983}
3984#endif
3985
3986void EventStateManager::PostHandleKeyboardEvent(
3987 WidgetKeyboardEvent* aKeyboardEvent, nsIFrame* aTargetFrame,
3988 nsEventStatus& aStatus) {
3989 if (aStatus == nsEventStatus_eConsumeNoDefault) {
3990 return;
3991 }
3992
3993 RefPtr<nsPresContext> presContext = mPresContext;
3994
3995 if (!aKeyboardEvent->HasBeenPostedToRemoteProcess()) {
3996 if (aKeyboardEvent->IsWaitingReplyFromRemoteProcess()) {
3997 RefPtr<BrowserParent> remote =
3998 aTargetFrame ? BrowserParent::GetFrom(aTargetFrame->GetContent())
3999 : nullptr;
4000 if (remote) {
4001 // remote is null-checked above in order to let pre-existing event
4002 // targeting code's chrome vs. content decision override in case of
4003 // disagreement in order not to disrupt non-Fission e10s mode in case
4004 // there are still bugs in the Fission-mode code. That is, if remote
4005 // is nullptr, the pre-existing event targeting code has deemed this
4006 // event to belong to chrome rather than content.
4007 BrowserParent* preciseRemote = BrowserParent::GetFocused();
4008 if (preciseRemote) {
4009 remote = preciseRemote;
4010 }
4011 // else there was a race between layout and focus tracking
4012 }
4013 if (remote && !remote->IsReadyToHandleInputEvents()) {
4014 // We need to dispatch the event to the browser element again if we were
4015 // waiting for the key reply but the event wasn't sent to the content
4016 // process due to the remote browser wasn't ready.
4017 WidgetKeyboardEvent keyEvent(*aKeyboardEvent);
4018 aKeyboardEvent->MarkAsHandledInRemoteProcess();
4019 RefPtr<Element> ownerElement = remote->GetOwnerElement();
4020 EventDispatcher::Dispatch(ownerElement, presContext, &keyEvent);
4021 if (keyEvent.DefaultPrevented()) {
4022 aKeyboardEvent->PreventDefault(!keyEvent.DefaultPreventedByContent());
4023 aStatus = nsEventStatus_eConsumeNoDefault;
4024 return;
4025 }
4026 }
4027 }
4028 // The widget expects a reply for every keyboard event. If the event wasn't
4029 // dispatched to a content process (non-e10s or no content process
4030 // running), we need to short-circuit here. Otherwise, we need to wait for
4031 // the content process to handle the event.
4032 if (aKeyboardEvent->mWidget) {
4033 aKeyboardEvent->mWidget->PostHandleKeyEvent(aKeyboardEvent);
4034 }
4035 if (aKeyboardEvent->DefaultPrevented()) {
4036 aStatus = nsEventStatus_eConsumeNoDefault;
4037 return;
4038 }
4039 }
4040
4041 // XXX Currently, our automated tests don't support mKeyNameIndex.
4042 // Therefore, we still need to handle this with keyCode.
4043 switch (aKeyboardEvent->mKeyCode) {
4044 case NS_VK_TAB:
4045 case NS_VK_F6:
4046 // This is to prevent keyboard scrolling while alt modifier in use.
4047 if (!aKeyboardEvent->IsAlt()) {
4048 aStatus = nsEventStatus_eConsumeNoDefault;
4049
4050 // Handling the tab event after it was sent to content is bad,
4051 // because to the FocusManager the remote-browser looks like one
4052 // element, so we would just move the focus to the next element
4053 // in chrome, instead of handling it in content.
4054 if (aKeyboardEvent->HasBeenPostedToRemoteProcess()) {
4055 break;
4056 }
4057
4058 EnsureDocument(presContext);
4059 nsFocusManager* fm = nsFocusManager::GetFocusManager();
4060 if (fm && mDocument) {
4061 // Shift focus forward or back depending on shift key
4062 bool isDocMove = aKeyboardEvent->IsControl() ||
4063 aKeyboardEvent->mKeyCode == NS_VK_F6;
4064 uint32_t dir =
4065 aKeyboardEvent->IsShift()
4066 ? (isDocMove ? static_cast<uint32_t>(
4067 nsIFocusManager::MOVEFOCUS_BACKWARDDOC)
4068 : static_cast<uint32_t>(
4069 nsIFocusManager::MOVEFOCUS_BACKWARD))
4070 : (isDocMove ? static_cast<uint32_t>(
4071 nsIFocusManager::MOVEFOCUS_FORWARDDOC)
4072 : static_cast<uint32_t>(
4073 nsIFocusManager::MOVEFOCUS_FORWARD));
4074 RefPtr<Element> result;
4075 fm->MoveFocus(mDocument->GetWindow(), nullptr, dir,
4076 nsIFocusManager::FLAG_BYKEY, getter_AddRefs(result));
4077 }
4078 }
4079 return;
4080 case 0:
4081 // We handle keys with no specific keycode value below.
4082 break;
4083 default:
4084 return;
4085 }
4086
4087 switch (aKeyboardEvent->mKeyNameIndex) {
4088 case KEY_NAME_INDEX_ZoomIn:
4089 case KEY_NAME_INDEX_ZoomOut:
4090 ChangeZoom(aKeyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_ZoomIn);
4091 aStatus = nsEventStatus_eConsumeNoDefault;
4092 break;
4093 default:
4094 break;
4095 }
4096}
4097
4098nsresult EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
4099 WidgetEvent* aEvent,
4100 nsIFrame* aTargetFrame,
4101 nsEventStatus* aStatus,
4102 nsIContent* aOverrideClickTarget) {
4103 AUTO_PROFILER_LABEL("EventStateManager::PostHandleEvent", DOM)mozilla::AutoProfilerLabel raiiObject4103( "EventStateManager::PostHandleEvent"
, nullptr, JS::ProfilingCategoryPair::DOM)
;
4104 NS_ENSURE_ARG(aPresContext)do { if ((__builtin_expect(!!(!(aPresContext)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPresContext" ") failed"
, nullptr, "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 4104); return NS_ERROR_INVALID_ARG; } } while (false)
;
1
Assuming 'aPresContext' is non-null
2
Taking false branch
3
Loop condition is false. Exiting loop
4105 NS_ENSURE_ARG_POINTER(aStatus)do { if ((__builtin_expect(!!(!(aStatus)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aStatus" ") failed", nullptr
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 4105
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4
Assuming 'aStatus' is non-null
5
Taking false branch
6
Loop condition is false. Exiting loop
4106
4107 mCurrentTarget = aTargetFrame;
4108 mCurrentTargetContent = nullptr;
4109
4110 HandleCrossProcessEvent(aEvent, aStatus);
4111 // NOTE: the above call may have destroyed aTargetFrame, please use
4112 // mCurrentTarget henceforth. This is to avoid using it accidentally:
4113 aTargetFrame = nullptr;
4114
4115 // Most of the events we handle below require a frame.
4116 // Add special cases here.
4117 if (!mCurrentTarget && aEvent->mMessage != eMouseUp &&
7
Assuming the condition is false
4118 aEvent->mMessage != eMouseDown && aEvent->mMessage != eDragEnter &&
4119 aEvent->mMessage != eDragOver && aEvent->mMessage != ePointerUp &&
4120 aEvent->mMessage != ePointerCancel) {
4121 return NS_OK;
4122 }
4123
4124 // Keep the prescontext alive, we might need it after event dispatch
4125 RefPtr<nsPresContext> presContext = aPresContext;
4126 nsresult ret = NS_OK;
4127
4128 switch (aEvent->mMessage) {
8
Control jumps to 'case ePointerUp:' at line 4322
4129 case eMouseDown: {
4130 WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
4131 if (mouseEvent->mButton == MouseButton::ePrimary &&
4132 !sNormalLMouseEventInProcess) {
4133 // We got a mouseup event while a mousedown event was being processed.
4134 // Make sure that the capturing content is cleared.
4135 PresShell::ReleaseCapturingContent();
4136 break;
4137 }
4138
4139 // For remote content, capture the event in the parent process at the
4140 // <xul:browser remote> element. This will ensure that subsequent
4141 // mousemove/mouseup events will continue to be dispatched to this element
4142 // and therefore forwarded to the child.
4143 if (aEvent->HasBeenPostedToRemoteProcess() &&
4144 !PresShell::GetCapturingContent()) {
4145 if (nsIContent* content =
4146 mCurrentTarget ? mCurrentTarget->GetContent() : nullptr) {
4147 PresShell::SetCapturingContent(content, CaptureFlags::None, aEvent);
4148 } else {
4149 PresShell::ReleaseCapturingContent();
4150 }
4151 }
4152
4153 // If MouseEvent::PreventClickEvent() was called by chrome script,
4154 // we need to forget the clicking content and click count for the
4155 // following eMouseUp event.
4156 if (mouseEvent->mClickEventPrevented) {
4157 switch (mouseEvent->mButton) {
4158 case MouseButton::ePrimary:
4159 case MouseButton::eSecondary:
4160 case MouseButton::eMiddle: {
4161 GetLastMouseButtonPressInfo(mouseEvent->mButton).Clear();
4162 break;
4163 }
4164
4165 default:
4166 break;
4167 }
4168 }
4169
4170 nsCOMPtr<nsIContent> activeContent;
4171 // When content calls PreventDefault on pointerdown, we also call
4172 // PreventDefault on the subsequent mouse events to suppress default
4173 // behaviors. Normally, aStatus should be nsEventStatus_eConsumeNoDefault
4174 // when the event is DefaultPrevented but it's reset to
4175 // nsEventStatus_eIgnore in EventStateManager::PreHandleEvent. So we also
4176 // check if the event is DefaultPrevented.
4177 if (nsEventStatus_eConsumeNoDefault != *aStatus &&
4178 !aEvent->DefaultPrevented()) {
4179 RefPtr<Element> newFocus;
4180 bool suppressBlur = false;
4181 if (mCurrentTarget) {
4182 newFocus = Element::FromNodeOrNull(
4183 mCurrentTarget->GetEventTargetContent(aEvent));
4184 activeContent = mCurrentTarget->GetContent();
4185
4186 // In some cases, we do not want to even blur the current focused
4187 // element. Those cases are:
4188 // 1. -moz-user-focus CSS property is set to 'ignore';
4189 // 2. XUL control element has the disabled property set to 'true'.
4190 //
4191 // We can't use nsIFrame::IsFocusable() because we want to blur when
4192 // we click on a visibility: none element.
4193 // We can't use nsIContent::IsFocusable() because we want to blur when
4194 // we click on a non-focusable element like a <div>.
4195 // We have to use |aEvent->mTarget| to not make sure we do not check
4196 // an anonymous node of the targeted element.
4197 suppressBlur =
4198 mCurrentTarget->StyleUI()->UserFocus() == StyleUserFocus::Ignore;
4199
4200 if (!suppressBlur) {
4201 if (Element* element =
4202 Element::FromEventTargetOrNull(aEvent->mTarget)) {
4203 if (nsCOMPtr<nsIDOMXULControlElement> xulControl =
4204 element->AsXULControl()) {
4205 bool disabled = false;
4206 xulControl->GetDisabled(&disabled);
4207 suppressBlur = disabled;
4208 }
4209 }
4210 }
4211 }
4212
4213 // When a root content which isn't editable but has an editable HTML
4214 // <body> element is clicked, we should redirect the focus to the
4215 // the <body> element. E.g., when an user click bottom of the editor
4216 // where is outside of the <body> element, the <body> should be focused
4217 // and the user can edit immediately after that.
4218 //
4219 // NOTE: The newFocus isn't editable that also means it's not in
4220 // designMode. In designMode, all contents are not focusable.
4221 if (newFocus && !newFocus->IsEditable()) {
4222 Document* doc = newFocus->GetComposedDoc();
4223 if (doc && newFocus == doc->GetRootElement()) {
4224 Element* bodyElement =
4225 nsLayoutUtils::GetEditableRootContentByContentEditable(doc);
4226 if (bodyElement && bodyElement->GetPrimaryFrame()) {
4227 newFocus = bodyElement;
4228 }
4229 }
4230 }
4231
4232 // When the mouse is pressed, the default action is to focus the
4233 // target. Look for the nearest enclosing focusable frame.
4234 //
4235 // TODO: Probably this should be moved to Element::PostHandleEvent.
4236 for (; newFocus; newFocus = newFocus->GetFlattenedTreeParentElement()) {
4237 nsIFrame* frame = nsLayoutUtils::GetPrimaryOrAreaImageFrame(newFocus);
4238 if (!frame) {
4239 continue;
4240 }
4241
4242 // If the mousedown happened inside a popup, don't try to set focus on
4243 // one of its containing elements
4244 if (frame->IsMenuPopupFrame()) {
4245 newFocus = nullptr;
4246 break;
4247 }
4248
4249 auto flags = IsFocusableFlags::WithMouse;
4250 if (frame->IsFocusable(flags)) {
4251 break;
4252 }
4253
4254 if (ShadowRoot* root = newFocus->GetShadowRoot()) {
4255 if (root->DelegatesFocus()) {
4256 if (Element* firstFocusable = root->GetFocusDelegate(flags)) {
4257 newFocus = firstFocusable;
4258 break;
4259 }
4260 }
4261 }
4262 }
4263
4264 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
4265 // if something was found to focus, focus it. Otherwise, if the
4266 // element that was clicked doesn't have -moz-user-focus: ignore,
4267 // clear the existing focus. For -moz-user-focus: ignore, the focus
4268 // is just left as is.
4269 // Another effect of mouse clicking, handled in Selection, is that
4270 // it should update the caret position to where the mouse was
4271 // clicked. Because the focus is cleared when clicking on a
4272 // non-focusable node, the next press of the tab key will cause
4273 // focus to be shifted from the caret position instead of the root.
4274 if (newFocus) {
4275 // use the mouse flag and the noscroll flag so that the content
4276 // doesn't unexpectedly scroll when clicking an element that is
4277 // only half visible
4278 uint32_t flags =
4279 nsIFocusManager::FLAG_BYMOUSE | nsIFocusManager::FLAG_NOSCROLL;
4280 // If this was a touch-generated event, pass that information:
4281 if (mouseEvent->mInputSource ==
4282 MouseEvent_Binding::MOZ_SOURCE_TOUCH) {
4283 flags |= nsIFocusManager::FLAG_BYTOUCH;
4284 }
4285 fm->SetFocus(newFocus, flags);
4286 } else if (!suppressBlur) {
4287 // clear the focus within the frame and then set it as the
4288 // focused frame
4289 EnsureDocument(mPresContext);
4290 if (mDocument) {
4291 nsCOMPtr<nsPIDOMWindowOuter> outerWindow = mDocument->GetWindow();
4292#ifdef XP_MACOSX
4293 if (!activeContent || !activeContent->IsXULElement())
4294#endif
4295 fm->ClearFocus(outerWindow);
4296 // Prevent switch frame if we're already not in the foreground tab
4297 // and we're in a content process.
4298 // TODO: If we were inactive frame in this tab, and now in
4299 // background tab, we shouldn't make the tab foreground, but
4300 // we should set focus to clicked document in the background
4301 // tab. However, nsFocusManager does not have proper method
4302 // for doing this. Therefore, we should skip setting focus
4303 // to clicked document for now.
4304 if (XRE_IsParentProcess() || IsInActiveTab(mDocument)) {
4305 fm->SetFocusedWindow(outerWindow);
4306 }
4307 }
4308 }
4309 }
4310
4311 // The rest is left button-specific.
4312 if (mouseEvent->mButton != MouseButton::ePrimary) {
4313 break;
4314 }
4315 } else {
4316 // if we're here, the event handler returned false, so stop
4317 // any of our own processing of a drag. Workaround for bug 43258.
4318 StopTrackingDragGesture(true);
4319 }
4320 } break;
4321 case ePointerCancel:
4322 case ePointerUp: {
4323 WidgetPointerEvent* pointerEvent = aEvent->AsPointerEvent();
4324 MOZ_ASSERT(pointerEvent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pointerEvent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pointerEvent))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("pointerEvent", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 4324); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pointerEvent"
")"); do { MOZ_CrashSequence(__null, 4324); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9
Assuming 'pointerEvent' is non-null
10
Taking false branch
11
Loop condition is false. Exiting loop
4325 // Implicitly releasing capture for given pointer. ePointerLostCapture
4326 // should be send after ePointerUp or ePointerCancel.
4327 PointerEventHandler::ImplicitlyReleasePointerCapture(pointerEvent);
4328 PointerEventHandler::UpdatePointerActiveState(pointerEvent);
4329
4330 if (
14
Taking true branch
4331 // After pointercancel, pointer becomes invalid so we can remove
4332 // relevant helper from table.
4333 pointerEvent->mMessage == ePointerCancel ||
12
Assuming field 'mMessage' is not equal to ePointerCancel
4334 // pointerup for non-hoverable pointer needs to dispatch pointerout
4335 // and pointerleave events because the pointer is valid only while the
4336 // pointer is "down".
4337 !pointerEvent->InputSourceSupportsHover()) {
13
Assuming the condition is true
4338 GenerateMouseEnterExit(pointerEvent);
15
Calling 'EventStateManager::GenerateMouseEnterExit'
4339 mPointersEnterLeaveHelper.Remove(pointerEvent->pointerId);
4340 }
4341
4342 break;
4343 }
4344 case eMouseUp: {
4345 // We can unconditionally stop capturing because
4346 // we should never be capturing when the mouse button is up
4347 PresShell::ReleaseCapturingContent();
4348
4349 WidgetMouseEvent* mouseUpEvent = aEvent->AsMouseEvent();
4350 if (NeedsActiveContentChange(mouseUpEvent)) {
4351 ClearGlobalActiveContent(this);
4352 }
4353 if (mouseUpEvent) {
4354 if (EventCausesClickEvents(*mouseUpEvent)) {
4355 // Make sure to dispatch the click even if there is no frame for
4356 // the current target element. This is required for Web compatibility.
4357 RefPtr<EventStateManager> esm =
4358 ESMFromContentOrThis(aOverrideClickTarget);
4359 ret = esm->PostHandleMouseUp(mouseUpEvent, aStatus,
4360 aOverrideClickTarget);
4361 }
4362 switch (mouseUpEvent->mButton) {
4363 case MouseButton::ePrimary:
4364 case MouseButton::eSecondary:
4365 case MouseButton::eMiddle:
4366 GetLastMouseButtonPressInfo(mouseUpEvent->mButton).Clear();
4367 break;
4368 default:
4369 break;
4370 }
4371 }
4372
4373 // After dispatching click events for this eMouseUp, nobody needs to refer
4374 // to the preceding ePointerUp event target anymore because it was
4375 // required by the click event dispatcher to consider the target.
4376 // Therefore, PointerEventHandler should forget the target now.
4377 PointerEventHandler::ReleasePointerCapturingElementAtLastPointerUp();
4378
4379 if (PresShell* presShell = presContext->GetPresShell()) {
4380 RefPtr<nsFrameSelection> frameSelection = presShell->FrameSelection();
4381 frameSelection->SetDragState(false);
4382 }
4383 } break;
4384 case eContextMenu: {
4385 // If the context menu event was not prevented, a context menu is about
4386 // to be shown. Record a fallback time now so that pending event timing
4387 // entries (pointerdown, mousedown, etc.) are not inflated by the time
4388 // the user spends interacting with the menu.
4389 // https://github.com/w3c/event-timing/issues/154
4390 if (!aEvent->DefaultPrevented() && aEvent->IsTrusted()) {
4391 if (auto* perf = aPresContext->GetPerformanceMainThread()) {
4392 perf->RecordModalFallbackTime();
4393 }
4394 }
4395 break;
4396 }
4397 case eWheelOperationEnd: {
4398 MOZ_ASSERT(aEvent->IsTrusted())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->IsTrusted())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aEvent->IsTrusted()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aEvent->IsTrusted()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 4398
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->IsTrusted()"
")"); do { MOZ_CrashSequence(__null, 4398); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4399 ScrollbarsForWheel::MayInactivate();
4400 WidgetWheelEvent* wheelEvent = aEvent->AsWheelEvent();
4401 ScrollContainerFrame* scrollTarget =
4402 ComputeScrollTargetAndMayAdjustWheelEvent(
4403 mCurrentTarget, wheelEvent,
4404 COMPUTE_DEFAULT_ACTION_TARGET_WITH_AUTO_DIR);
4405 // If the wheel event was handled by APZ, APZ will perform the scroll
4406 // snap.
4407 if (scrollTarget && !WheelTransaction::HandledByApz()) {
4408 scrollTarget->ScrollSnap();
4409 }
4410 } break;
4411 case eWheel:
4412 case eWheelOperationStart: {
4413 MOZ_ASSERT(aEvent->IsTrusted())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->IsTrusted())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aEvent->IsTrusted()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aEvent->IsTrusted()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 4413
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->IsTrusted()"
")"); do { MOZ_CrashSequence(__null, 4413); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4414
4415 if (*aStatus == nsEventStatus_eConsumeNoDefault) {
4416 ScrollbarsForWheel::Inactivate();
4417 break;
4418 }
4419
4420 WidgetWheelEvent* wheelEvent = aEvent->AsWheelEvent();
4421 MOZ_ASSERT(wheelEvent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(wheelEvent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(wheelEvent))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("wheelEvent", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 4421); AnnotateMozCrashReason("MOZ_ASSERT" "(" "wheelEvent"
")"); do { MOZ_CrashSequence(__null, 4421); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4422
4423 // When APZ is enabled, the actual scroll animation might be handled by
4424 // the compositor.
4425 WheelPrefs::Action action =
4426 wheelEvent->mFlags.mHandledByAPZ
4427 ? WheelPrefs::ACTION_NONE
4428 : WheelPrefs::GetInstance()->ComputeActionFor(wheelEvent);
4429
4430 WheelDeltaAdjustmentStrategy strategy =
4431 GetWheelDeltaAdjustmentStrategy(*wheelEvent);
4432 // Adjust the delta values of the wheel event if the current default
4433 // action is to horizontalize scrolling. I.e., deltaY values are set to
4434 // deltaX and deltaY and deltaZ values are set to 0.
4435 // If horizontalized, the delta values will be restored and its overflow
4436 // deltaX will become 0 when the WheelDeltaHorizontalizer instance is
4437 // being destroyed.
4438 WheelDeltaHorizontalizer horizontalizer(*wheelEvent);
4439 if (WheelDeltaAdjustmentStrategy::eHorizontalize == strategy) {
4440 horizontalizer.Horizontalize();
4441 }
4442
4443 // Since ComputeScrollTargetAndMayAdjustWheelEvent() may adjust the delta
4444 // if the event is auto-dir. So we use |ESMAutoDirWheelDeltaRestorer|
4445 // here.
4446 // An instance of |ESMAutoDirWheelDeltaRestorer| is used to monitor
4447 // auto-dir adjustment which may happen during its lifetime. If the delta
4448 // values is adjusted during its lifetime, the instance will restore the
4449 // adjusted delta when it's being destrcuted.
4450 ESMAutoDirWheelDeltaRestorer restorer(*wheelEvent);
4451 ScrollContainerFrame* scrollTarget =
4452 ComputeScrollTargetAndMayAdjustWheelEvent(
4453 mCurrentTarget, wheelEvent,
4454 COMPUTE_DEFAULT_ACTION_TARGET_WITH_AUTO_DIR);
4455
4456 switch (action) {
4457 case WheelPrefs::ACTION_SCROLL:
4458 case WheelPrefs::ACTION_HORIZONTALIZED_SCROLL: {
4459 // For scrolling of default action, we should honor the mouse wheel
4460 // transaction.
4461
4462 ScrollbarsForWheel::PrepareToScrollText(this, mCurrentTarget,
4463 wheelEvent);
4464
4465 if (aEvent->mMessage != eWheel ||
4466 (!wheelEvent->mDeltaX && !wheelEvent->mDeltaY)) {
4467 break;
4468 }
4469
4470 ScrollbarsForWheel::SetActiveScrollTarget(scrollTarget);
4471
4472 ScrollContainerFrame* rootScrollContainerFrame =
4473 !mCurrentTarget
4474 ? nullptr
4475 : mCurrentTarget->PresShell()->GetRootScrollContainerFrame();
4476 if (!scrollTarget || scrollTarget == rootScrollContainerFrame) {
4477 wheelEvent->mViewPortIsOverscrolled = true;
4478 }
4479 wheelEvent->mOverflowDeltaX = wheelEvent->mDeltaX;
4480 wheelEvent->mOverflowDeltaY = wheelEvent->mDeltaY;
4481 WheelPrefs::GetInstance()->CancelApplyingUserPrefsFromOverflowDelta(
4482 wheelEvent);
4483 if (scrollTarget) {
4484 DoScrollText(scrollTarget, wheelEvent);
4485 } else {
4486 WheelTransaction::EndTransaction();
4487 ScrollbarsForWheel::Inactivate();
4488 }
4489 break;
4490 }
4491 case WheelPrefs::ACTION_HISTORY: {
4492 // If this event doesn't cause eLegacyMouseLineOrPageScroll event or
4493 // the direction is oblique, don't perform history back/forward.
4494 int32_t intDelta = wheelEvent->GetPreferredIntDelta();
4495 if (!intDelta) {
4496 break;
4497 }
4498 DoScrollHistory(intDelta);
4499 break;
4500 }
4501 case WheelPrefs::ACTION_ZOOM: {
4502 // If this event doesn't cause eLegacyMouseLineOrPageScroll event or
4503 // the direction is oblique, don't perform zoom in/out.
4504 int32_t intDelta = wheelEvent->GetPreferredIntDelta();
4505 if (!intDelta) {
4506 break;
4507 }
4508 DoScrollZoom(mCurrentTarget, intDelta);
4509 break;
4510 }
4511 case WheelPrefs::ACTION_NONE:
4512 default:
4513 bool allDeltaOverflown = false;
4514 if (wheelEvent->mDeltaX != 0.0 || wheelEvent->mDeltaY != 0.0) {
4515 if (scrollTarget) {
4516 WheelTransaction::WillHandleDefaultAction(
4517 wheelEvent, scrollTarget, mCurrentTarget);
4518 } else {
4519 WheelTransaction::EndTransaction();
4520 }
4521 }
4522 if (wheelEvent->mFlags.mHandledByAPZ) {
4523 if (wheelEvent->mCanTriggerSwipe) {
4524 // For events that can trigger swipes, APZ needs to know whether
4525 // scrolling is possible in the requested direction. It does this
4526 // by looking at the scroll overflow values on mCanTriggerSwipe
4527 // events after they have been processed. When determining if
4528 // a swipe should occur, we should not prefer the current wheel
4529 // transaction.
4530 nsIFrame* lastScrollFrame =
4531 WheelTransaction::GetScrollTargetFrame();
4532 bool wheelTransactionHandlesInput = false;
4533 if (lastScrollFrame) {
4534 ScrollContainerFrame* scrollContainerFrame =
4535 lastScrollFrame->GetScrollTargetFrame();
4536 if (scrollContainerFrame->IsRootScrollFrameOfDocument()) {
4537 // If the current wheel transaction target is the root scroll
4538 // frame and is not scrollable on the x-axis, all delta is
4539 // overflown and swipe-to-nav may occur.
4540 wheelTransactionHandlesInput = true;
4541 allDeltaOverflown = !WheelHandlingUtils::CanScrollOn(
4542 scrollContainerFrame, wheelEvent->mDeltaX, 0.0);
4543 } else if (WheelHandlingUtils::CanScrollOn(
4544 scrollContainerFrame, wheelEvent->mDeltaX,
4545 wheelEvent->mDeltaY)) {
4546 // If the current wheel transaction target is not the root
4547 // scroll frame, ensure that swipe to nav does not occur if
4548 // the scroll frame is scrollable on the x or y axis. If the
4549 // scroll frame cannot scroll, all delta _may_ be overflown.
4550 wheelTransactionHandlesInput = true;
4551 allDeltaOverflown = false;
4552 }
4553 }
4554 if (!wheelTransactionHandlesInput) {
4555 allDeltaOverflown = !ComputeScrollTarget(
4556 mCurrentTarget, wheelEvent,
4557 COMPUTE_DEFAULT_ACTION_TARGET_WITHOUT_WHEEL_TRANSACTION);
4558 }
4559 }
4560 } else {
4561 // The event was processed neither by APZ nor by us, so all of the
4562 // delta values must be overflown delta values.
4563 allDeltaOverflown = true;
4564 }
4565
4566 if (!allDeltaOverflown) {
4567 break;
4568 }
4569 wheelEvent->mOverflowDeltaX = wheelEvent->mDeltaX;
4570 wheelEvent->mOverflowDeltaY = wheelEvent->mDeltaY;
4571 WheelPrefs::GetInstance()->CancelApplyingUserPrefsFromOverflowDelta(
4572 wheelEvent);
4573 wheelEvent->mViewPortIsOverscrolled = true;
4574 break;
4575 }
4576 *aStatus = nsEventStatus_eConsumeNoDefault;
4577 } break;
4578
4579 case eGestureNotify: {
4580 if (nsEventStatus_eConsumeNoDefault != *aStatus) {
4581 DecideGestureEvent(aEvent->AsGestureNotifyEvent(), mCurrentTarget);
4582 }
4583 } break;
4584
4585 case eDragEnter:
4586 case eDragOver: {
4587 NS_ASSERTION(aEvent->mClass == eDragEventClass, "Expected a drag event")do { if (!(aEvent->mClass == eDragEventClass)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Expected a drag event", "aEvent->mClass == eDragEventClass"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 4587
); MOZ_PretendNoReturn(); } } while (0)
;
4588
4589 // Check if the drag is occurring inside a scrollable area. If so, scroll
4590 // the area when the mouse is near the edges.
4591 if (mCurrentTarget && aEvent->mMessage == eDragOver) {
4592 nsIFrame* checkFrame = mCurrentTarget;
4593 while (checkFrame) {
4594 ScrollContainerFrame* scrollFrame = do_QueryFrame(checkFrame);
4595 // Break out so only the innermost scrollframe is scrolled.
4596 if (scrollFrame && scrollFrame->DragScroll(aEvent)) {
4597 break;
4598 }
4599 checkFrame = checkFrame->GetParent();
4600 }
4601 }
4602
4603 nsCOMPtr<nsIDragSession> dragSession =
4604 nsContentUtils::GetDragSession(mPresContext);
4605 if (!dragSession) break;
4606
4607 // Reset the flag.
4608 dragSession->SetOnlyChromeDrop(false);
4609 if (mPresContext) {
4610 EnsureDocument(mPresContext);
4611 }
4612 bool isChromeDoc = nsContentUtils::IsChromeDoc(mDocument);
4613
4614 // the initial dataTransfer is the one from the dragstart event that
4615 // was set on the dragSession when the drag began.
4616 RefPtr<DataTransfer> dataTransfer;
4617 RefPtr<DataTransfer> initialDataTransfer = dragSession->GetDataTransfer();
4618
4619 WidgetDragEvent* dragEvent = aEvent->AsDragEvent();
4620
4621 // collect any changes to moz cursor settings stored in the event's
4622 // data transfer.
4623 UpdateDragDataTransfer(dragEvent);
4624
4625 // cancelling a dragenter or dragover event means that a drop should be
4626 // allowed, so update the dropEffect and the canDrop state to indicate
4627 // that a drag is allowed. If the event isn't cancelled, a drop won't be
4628 // allowed. Essentially, to allow a drop somewhere, specify the effects
4629 // using the effectAllowed and dropEffect properties in a dragenter or
4630 // dragover event and cancel the event. To not allow a drop somewhere,
4631 // don't cancel the event or set the effectAllowed or dropEffect to
4632 // "none". This way, if the event is just ignored, no drop will be
4633 // allowed.
4634 uint32_t dropEffect = nsIDragService::DRAGDROP_ACTION_NONE;
4635 uint32_t action = nsIDragService::DRAGDROP_ACTION_NONE;
4636 if (nsEventStatus_eConsumeNoDefault == *aStatus) {
4637 // If the event has initialized its mDataTransfer, use it.
4638 // Or the event has not been initialized its mDataTransfer, but
4639 // it's set before dispatch because of synthesized, but without
4640 // testing session (e.g., emulating drag from another app), use it
4641 // coming from outside.
4642 // XXX Perhaps, for the latter case, we need new API because we don't
4643 // have a chance to initialize allowed effects of the session.
4644 if (dragEvent->mDataTransfer) {
4645 // get the dataTransfer and the dropEffect that was set on it
4646 dataTransfer = dragEvent->mDataTransfer;
4647 dropEffect = dataTransfer->DropEffectInt();
4648 } else {
4649 // if dragEvent->mDataTransfer is null, it means that no attempt was
4650 // made to access the dataTransfer during the event, yet the event
4651 // was cancelled. Instead, use the initial data transfer available
4652 // from the drag session. The drop effect would not have been
4653 // initialized (which is done in DragEvent::GetDataTransfer),
4654 // so set it from the drag action. We'll still want to filter it
4655 // based on the effectAllowed below.
4656 dataTransfer = initialDataTransfer;
4657
4658 dragSession->GetDragAction(&action);
4659
4660 // filter the drop effect based on the action. Use UNINITIALIZED as
4661 // any effect is allowed.
4662 dropEffect = nsContentUtils::FilterDropEffect(
4663 action, nsIDragService::DRAGDROP_ACTION_UNINITIALIZED);
4664 }
4665
4666 // At this point, if the dataTransfer is null, it means that the
4667 // drag was originally started by directly calling the drag service.
4668 // Just assume that all effects are allowed.
4669 uint32_t effectAllowed = nsIDragService::DRAGDROP_ACTION_UNINITIALIZED;
4670 if (dataTransfer) {
4671 effectAllowed = dataTransfer->EffectAllowedInt();
4672 }
4673
4674 // set the drag action based on the drop effect and effect allowed.
4675 // The drop effect field on the drag transfer object specifies the
4676 // desired current drop effect. However, it cannot be used if the
4677 // effectAllowed state doesn't include that type of action. If the
4678 // dropEffect is "none", then the action will be 'none' so a drop will
4679 // not be allowed.
4680 if (effectAllowed == nsIDragService::DRAGDROP_ACTION_UNINITIALIZED ||
4681 dropEffect & effectAllowed)
4682 action = dropEffect;
4683
4684 if (action == nsIDragService::DRAGDROP_ACTION_NONE)
4685 dropEffect = nsIDragService::DRAGDROP_ACTION_NONE;
4686
4687 // inform the drag session that a drop is allowed on this node.
4688 dragSession->SetDragAction(action);
4689 dragSession->SetCanDrop(action != nsIDragService::DRAGDROP_ACTION_NONE);
4690
4691 // For now, do this only for dragover.
4692 // XXXsmaug dragenter needs some more work.
4693 if (aEvent->mMessage == eDragOver && !isChromeDoc) {
4694 // Someone has called preventDefault(), check whether is was on
4695 // content or chrome.
4696 dragSession->SetOnlyChromeDrop(
4697 !dragEvent->mDefaultPreventedOnContent);
4698 }
4699 } else if (aEvent->mMessage == eDragOver && !isChromeDoc) {
4700 // No one called preventDefault(), so handle drop only in chrome.
4701 dragSession->SetOnlyChromeDrop(true);
4702 }
4703 if (auto* bc = BrowserChild::GetFrom(presContext->GetDocShell())) {
4704 bc->SendUpdateDropEffect(action, dropEffect);
4705 }
4706 if (aEvent->HasBeenPostedToRemoteProcess()) {
4707 dragSession->SetCanDrop(true);
4708 } else if (initialDataTransfer) {
4709 // Now set the drop effect in the initial dataTransfer. This ensures
4710 // that we can get the desired drop effect in the drop event. For events
4711 // dispatched to content, the content process will take care of setting
4712 // this.
4713 initialDataTransfer->SetDropEffectInt(dropEffect);
4714 }
4715 } break;
4716
4717 case eDrop: {
4718 if (aEvent->mFlags.mIsSynthesizedForTests) {
4719 nsCOMPtr<nsIDragService> dragService =
4720 do_GetService("@mozilla.org/widget/dragservice;1");
4721 nsCOMPtr<nsIDragSession> dragSession =
4722 nsContentUtils::GetDragSession(mPresContext);
4723 if (dragSession && dragService &&
4724 !dragService->GetNeverAllowSessionIsSynthesizedForTests()) {
4725 MOZ_ASSERT(dragSession->IsSynthesizedForTests())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(dragSession->IsSynthesizedForTests())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(dragSession->IsSynthesizedForTests()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("dragSession->IsSynthesizedForTests()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 4725
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "dragSession->IsSynthesizedForTests()"
")"); do { MOZ_CrashSequence(__null, 4725); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4726 RefPtr<WindowContext> sourceWC;
4727 DebugOnly<nsresult> rvIgnored =
4728 dragSession->GetSourceWindowContext(getter_AddRefs(sourceWC));
4729 NS_WARNING_ASSERTION(do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored
)), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "nsIDragSession::GetSourceDocument() failed, but ignored"
, "NS_SUCCEEDED(rvIgnored)", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 4731); } } while (false)
4730 NS_SUCCEEDED(rvIgnored),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored
)), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "nsIDragSession::GetSourceDocument() failed, but ignored"
, "NS_SUCCEEDED(rvIgnored)", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 4731); } } while (false)
4731 "nsIDragSession::GetSourceDocument() failed, but ignored")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored
)), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "nsIDragSession::GetSourceDocument() failed, but ignored"
, "NS_SUCCEEDED(rvIgnored)", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 4731); } } while (false)
;
4732 // If the drag source hasn't been initialized, i.e., dragstart was
4733 // consumed by the test, the test needs to dispatch "dragend" event
4734 // instead of the drag session. Therefore, it does not make sense
4735 // to set drag end point in such case (you hit assersion if you do
4736 // it).
4737 if (sourceWC) {
4738 const CSSIntPoint dropPointInScreen = RoundedToInt(
4739 Event::GetScreenCoords(aPresContext, aEvent, aEvent->mRefPoint)
4740 .extract());
4741 dragSession->SetDragEndPointForTests(dropPointInScreen.x,
4742 dropPointInScreen.y);
4743 }
4744 }
4745 }
4746 sLastDragOverFrame = nullptr;
4747 ClearGlobalActiveContent(this);
4748 break;
4749 }
4750 case eDragExit: {
4751 // make sure to fire the enter and exit_synth events after the
4752 // eDragExit event, otherwise we'll clean up too early
4753 GenerateDragDropEnterExit(presContext, *aEvent->AsDragEvent());
4754 if (auto* bc = BrowserChild::GetFrom(presContext->GetDocShell())) {
4755 // SendUpdateDropEffect to prevent nsIDragService from waiting for
4756 // response of forwarded dragexit event.
4757 bc->SendUpdateDropEffect(nsIDragService::DRAGDROP_ACTION_NONE,
4758 nsIDragService::DRAGDROP_ACTION_NONE);
4759 }
4760 break;
4761 }
4762 case eKeyUp:
4763 // If space key is released, we need to inactivate the element which was
4764 // activated by preceding space key down.
4765 // XXX Currently, we don't store the reason of activation. Therefore,
4766 // this may cancel what is activated by a mousedown, but it must not
4767 // cause actual problem in web apps in the wild since it must be
4768 // rare case that users release space key during a mouse click/drag.
4769 if (aEvent->AsKeyboardEvent()->ShouldWorkAsSpaceKey()) {
4770 ClearGlobalActiveContent(this);
4771 }
4772 break;
4773
4774 case eKeyPress: {
4775 WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
4776 PostHandleKeyboardEvent(keyEvent, mCurrentTarget, *aStatus);
4777 } break;
4778
4779 case eMouseEnterIntoWidget:
4780 if (mCurrentTarget) {
4781 nsCOMPtr<nsIContent> targetContent =
4782 mCurrentTarget->GetEventTargetContent(aEvent);
4783 SetContentState(targetContent, ElementState::HOVER);
4784 }
4785 break;
4786
4787 case eMouseExitFromWidget:
4788 MOZ_ASSERT_UNREACHABLE(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Should've already been handled in PreHandleEvent()" ")", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 4789); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Should've already been handled in PreHandleEvent()"
")"); do { MOZ_CrashSequence(__null, 4789); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4789 "Should've already been handled in PreHandleEvent()")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Should've already been handled in PreHandleEvent()" ")", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 4789); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Should've already been handled in PreHandleEvent()"
")"); do { MOZ_CrashSequence(__null, 4789); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4790 break;
4791
4792#ifdef XP_MACOSX
4793 case eMouseActivate:
4794 if (mCurrentTarget) {
4795 nsCOMPtr<nsIContent> targetContent =
4796 mCurrentTarget->GetExplicitEventTargetContent(aEvent);
4797 if (!NodeAllowsClickThrough(targetContent)) {
4798 *aStatus = nsEventStatus_eConsumeNoDefault;
4799 }
4800 }
4801 break;
4802#endif
4803
4804 default:
4805 break;
4806 }
4807
4808 // Reset target frame to null to avoid mistargeting after reentrant event
4809 mCurrentTarget = nullptr;
4810 mCurrentTargetContent = nullptr;
4811
4812 return ret;
4813}
4814
4815BrowserParent* EventStateManager::GetCrossProcessTarget() {
4816 return IMEStateManager::GetActiveBrowserParent();
4817}
4818
4819bool EventStateManager::IsTargetCrossProcess(WidgetGUIEvent* aEvent) {
4820 // Check to see if there is a focused, editable content in chrome,
4821 // in that case, do not forward IME events to content
4822 Element* focusedElement = GetFocusedElement();
4823 if (focusedElement && focusedElement->IsEditable()) {
4824 return false;
4825 }
4826 return IMEStateManager::GetActiveBrowserParent() != nullptr;
4827}
4828
4829void EventStateManager::NotifyDestroyPresContext(nsPresContext* aPresContext) {
4830 RefPtr<nsPresContext> presContext = aPresContext;
4831 if (presContext) {
4832 IMEStateManager::OnDestroyPresContext(*presContext);
4833 }
4834
4835 // Bug 70855: Presentation is going away, possibly for a reframe.
4836 // Reset the hover state so that if we're recreating the presentation,
4837 // we won't have the old hover state still set in the new presentation,
4838 // as if the new presentation is resized, a new element may be hovered.
4839 ResetHoverState();
4840
4841 mMouseEnterLeaveHelper = nullptr;
4842 mPointersEnterLeaveHelper.Clear();
4843 PointerEventHandler::NotifyDestroyPresContext(presContext);
4844}
4845
4846void EventStateManager::ResetHoverState() {
4847 if (mHoverContent) {
4848 SetContentState(nullptr, ElementState::HOVER);
4849 }
4850}
4851
4852void EventStateManager::SetPresContext(nsPresContext* aPresContext) {
4853 mPresContext = aPresContext;
4854}
4855
4856void EventStateManager::ClearFrameRefs(nsIFrame* aFrame) {
4857 if (!aFrame) {
4858 return;
4859 }
4860
4861 if (aFrame == mCurrentTarget) {
4862 mCurrentTargetContent = aFrame->GetContent();
4863 }
4864
4865 // If the element currently shown in the status bar has lost its
4866 // frame, clear the status bar.
4867 if (aFrame == mLinkOverFrame.GetFrame()) {
4868 nsIContent* content = aFrame->GetContent();
4869 if (content && content->IsElement()) {
4870 nsPresContext* rootPc = mPresContext->GetRootPresContext();
4871 if (rootPc) {
4872 mPendingLeaveLinkElement = content->AsElement();
4873 RefPtr<ManagedPostRefreshObserver> observer =
4874 new ManagedPostRefreshObserver(
4875 rootPc,
4876 [esm = RefPtr<EventStateManager>(this)](bool aWasCanceled)
4877 -> ManagedPostRefreshObserver::Unregister {
4878 esm->MaybeLeavePendingLink(aWasCanceled);
4879 return ManagedPostRefreshObserver::Unregister::Yes;
4880 });
4881 rootPc->RegisterManagedPostRefreshObserver(observer);
4882 }
4883 }
4884 }
4885}
4886
4887void EventStateManager::MaybeLeavePendingLink(bool aWasCanceled) {
4888 RefPtr<dom::Element> element = std::move(mPendingLeaveLinkElement);
4889 if (aWasCanceled || !element || element->GetPrimaryFrame() ||
4890 mLinkOverFrame.GetFrame()) {
4891 return;
4892 }
4893 element->LeaveLink(mPresContext);
4894}
4895
4896struct CursorImage {
4897 gfx::IntPoint mHotspot;
4898 nsCOMPtr<imgIContainer> mContainer;
4899 ImageResolution mResolution;
4900 bool mEarlierCursorLoading = false;
4901};
4902
4903// Given the event that we're processing, and the computed cursor and hotspot,
4904// determine whether the custom CSS cursor should be blocked (that is, not
4905// honored).
4906//
4907// We will not honor it all of the following are true:
4908//
4909// * the size of the custom cursor is bigger than layout.cursor.block.max-size.
4910// * the bounds of the cursor would end up outside of the viewport of the
4911// top-level content document.
4912//
4913// This is done in order to prevent hijacking the cursor, see bug 1445844 and
4914// co.
4915static bool ShouldBlockCustomCursor(nsPresContext* aPresContext,
4916 WidgetEvent* aEvent,
4917 const CursorImage& aCursor) {
4918 int32_t width = 0;
4919 int32_t height = 0;
4920 aCursor.mContainer->GetWidth(&width);
4921 aCursor.mContainer->GetHeight(&height);
4922 aCursor.mResolution.ApplyTo(width, height);
4923
4924 int32_t maxSize = StaticPrefs::layout_cursor_block_max_size();
4925
4926 if (width <= maxSize && height <= maxSize) {
4927 return false;
4928 }
4929
4930 auto input = DOMIntersectionObserver::ComputeInput(*aPresContext->Document(),
4931 nullptr, nullptr, nullptr);
4932
4933 if (!input.mRootFrame) {
4934 return false;
4935 }
4936
4937 nsPoint point = nsLayoutUtils::GetEventCoordinatesRelativeTo(
4938 aEvent, RelativeTo{input.mRootFrame});
4939
4940 // The cursor size won't be affected by our full zoom in the parent process,
4941 // so undo that before checking the rect.
4942 float zoom = aPresContext->GetFullZoom();
4943
4944 // Also adjust for accessibility cursor scaling factor.
4945 zoom /= LookAndFeel::GetFloat(LookAndFeel::FloatID::CursorScale, 1.0f);
4946
4947 nsSize size(CSSPixel::ToAppUnits(width / zoom),
4948 CSSPixel::ToAppUnits(height / zoom));
4949 nsPoint hotspot(
4950 CSSPixel::ToAppUnits(ViewAs<CSSPixel>(aCursor.mHotspot.x / zoom)),
4951 CSSPixel::ToAppUnits(ViewAs<CSSPixel>(aCursor.mHotspot.y / zoom)));
4952
4953 const nsRect cursorRect(point - hotspot, size);
4954 auto output = DOMIntersectionObserver::Intersect(input, cursorRect);
4955 return !output.mIntersectionRect ||
4956 !(*output.mIntersectionRect == cursorRect);
4957}
4958
4959static gfx::IntPoint ComputeHotspot(imgIContainer* aContainer,
4960 const Maybe<gfx::Point>& aHotspot) {
4961 MOZ_ASSERT(aContainer)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aContainer)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aContainer))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aContainer", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 4961); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContainer"
")"); do { MOZ_CrashSequence(__null, 4961); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4962
4963 // css3-ui says to use the CSS-specified hotspot if present,
4964 // otherwise use the intrinsic hotspot, otherwise use the top left
4965 // corner.
4966 if (aHotspot) {
4967 int32_t imgWidth, imgHeight;
4968 aContainer->GetWidth(&imgWidth);
4969 aContainer->GetHeight(&imgHeight);
4970 auto hotspot = gfx::IntPoint::Round(*aHotspot);
4971 return {std::max(std::min(hotspot.x.value, imgWidth - 1), 0),
4972 std::max(std::min(hotspot.y.value, imgHeight - 1), 0)};
4973 }
4974
4975 gfx::IntPoint hotspot;
4976 aContainer->GetHotspotX(&hotspot.x.value);
4977 aContainer->GetHotspotY(&hotspot.y.value);
4978 return hotspot;
4979}
4980
4981static CursorImage ComputeCustomCursor(nsPresContext* aPresContext,
4982 WidgetEvent* aEvent,
4983 const nsIFrame& aFrame,
4984 const nsIFrame::Cursor& aCursor) {
4985 if (aCursor.mAllowCustomCursor == nsIFrame::AllowCustomCursorImage::No) {
4986 return {};
4987 }
4988 const ComputedStyle& style =
4989 aCursor.mStyle ? *aCursor.mStyle : *aFrame.Style();
4990
4991 // If we are falling back because any cursor before us is loading, let the
4992 // consumer know.
4993 bool loading = false;
4994 for (const auto& image : style.StyleUI()->Cursor().images.AsSpan()) {
4995 MOZ_ASSERT(image.image.IsImageRequestType(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(image.image.IsImageRequestType())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(image.image.IsImageRequestType
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("image.image.IsImageRequestType()" " (" "Cursor image should only parse url() types"
")", "/root/firefox-clang/dom/events/EventStateManager.cpp",
4996); AnnotateMozCrashReason("MOZ_ASSERT" "(" "image.image.IsImageRequestType()"
") (" "Cursor image should only parse url() types" ")"); do {
MOZ_CrashSequence(__null, 4996); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
4996 "Cursor image should only parse url() types")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(image.image.IsImageRequestType())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(image.image.IsImageRequestType
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("image.image.IsImageRequestType()" " (" "Cursor image should only parse url() types"
")", "/root/firefox-clang/dom/events/EventStateManager.cpp",
4996); AnnotateMozCrashReason("MOZ_ASSERT" "(" "image.image.IsImageRequestType()"
") (" "Cursor image should only parse url() types" ")"); do {
MOZ_CrashSequence(__null, 4996); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4997 uint32_t status;
4998 imgRequestProxy* req = image.image.GetImageRequest();
4999 if (!req || NS_FAILED(req->GetImageStatus(&status))((bool)(__builtin_expect(!!(NS_FAILED_impl(req->GetImageStatus
(&status))), 0)))
) {
5000 continue;
5001 }
5002 if (!(status & imgIRequest::STATUS_LOAD_COMPLETE)) {
5003 loading = true;
5004 continue;
5005 }
5006 if (status & imgIRequest::STATUS_ERROR) {
5007 continue;
5008 }
5009 nsCOMPtr<imgIContainer> container;
5010 req->GetImage(getter_AddRefs(container));
5011 if (!container) {
5012 continue;
5013 }
5014 StyleImageOrientation orientation =
5015 aFrame.StyleVisibility()->UsedImageOrientation(req);
5016 container = nsLayoutUtils::OrientImage(container, orientation);
5017 Maybe<gfx::Point> specifiedHotspot =
5018 image.has_hotspot ? Some(gfx::Point{image.hotspot_x, image.hotspot_y})
5019 : Nothing();
5020 gfx::IntPoint hotspot = ComputeHotspot(container, specifiedHotspot);
5021 CursorImage result{hotspot, std::move(container),
5022 image.image.GetResolution(&style), loading};
5023 if (ShouldBlockCustomCursor(aPresContext, aEvent, result)) {
5024 continue;
5025 }
5026 // This is the one we want!
5027 return result;
5028 }
5029 return {{}, nullptr, {}, loading};
5030}
5031
5032void EventStateManager::UpdateCursor(nsPresContext* aPresContext,
5033 WidgetMouseEvent* aEvent,
5034 nsIFrame* aTargetFrame,
5035 nsEventStatus* aStatus) {
5036 if (!PointerEventHandler::IsLastPointerId(aEvent->pointerId)) {
5037 MOZ_LOG_DEBUG_ONLY(do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Stopped updating cursor for the pointer "
"because of %s, ESM: %p, in-process root PresShell: %p", aEvent
->pointerId, InputSourceToString(aEvent->mInputSource).
get(), ToChar(aEvent->mMessage), aEvent->IsReal() ? "Real"
: "Synthesized", !PointerEventHandler::GetLastPointerId() ? "no last pointerId"
: nsPrintfCString("different from last pointerId (%u)", *PointerEventHandler
::GetLastPointerId()) .get(), this, GetRootPresShell()); } } while
(0)
5038 gMouseCursorUpdates, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Stopped updating cursor for the pointer "
"because of %s, ESM: %p, in-process root PresShell: %p", aEvent
->pointerId, InputSourceToString(aEvent->mInputSource).
get(), ToChar(aEvent->mMessage), aEvent->IsReal() ? "Real"
: "Synthesized", !PointerEventHandler::GetLastPointerId() ? "no last pointerId"
: nsPrintfCString("different from last pointerId (%u)", *PointerEventHandler
::GetLastPointerId()) .get(), this, GetRootPresShell()); } } while
(0)
5039 ("EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Stopped updating cursor for the pointer "
"because of %s, ESM: %p, in-process root PresShell: %p", aEvent
->pointerId, InputSourceToString(aEvent->mInputSource).
get(), ToChar(aEvent->mMessage), aEvent->IsReal() ? "Real"
: "Synthesized", !PointerEventHandler::GetLastPointerId() ? "no last pointerId"
: nsPrintfCString("different from last pointerId (%u)", *PointerEventHandler
::GetLastPointerId()) .get(), this, GetRootPresShell()); } } while
(0)
5040 "message=%s, reason=%s}): Stopped updating cursor for the pointer "do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Stopped updating cursor for the pointer "
"because of %s, ESM: %p, in-process root PresShell: %p", aEvent
->pointerId, InputSourceToString(aEvent->mInputSource).
get(), ToChar(aEvent->mMessage), aEvent->IsReal() ? "Real"
: "Synthesized", !PointerEventHandler::GetLastPointerId() ? "no last pointerId"
: nsPrintfCString("different from last pointerId (%u)", *PointerEventHandler
::GetLastPointerId()) .get(), this, GetRootPresShell()); } } while
(0)
5041 "because of %s, ESM: %p, in-process root PresShell: %p",do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Stopped updating cursor for the pointer "
"because of %s, ESM: %p, in-process root PresShell: %p", aEvent
->pointerId, InputSourceToString(aEvent->mInputSource).
get(), ToChar(aEvent->mMessage), aEvent->IsReal() ? "Real"
: "Synthesized", !PointerEventHandler::GetLastPointerId() ? "no last pointerId"
: nsPrintfCString("different from last pointerId (%u)", *PointerEventHandler
::GetLastPointerId()) .get(), this, GetRootPresShell()); } } while
(0)
5042 aEvent->pointerId, InputSourceToString(aEvent->mInputSource).get(),do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Stopped updating cursor for the pointer "
"because of %s, ESM: %p, in-process root PresShell: %p", aEvent
->pointerId, InputSourceToString(aEvent->mInputSource).
get(), ToChar(aEvent->mMessage), aEvent->IsReal() ? "Real"
: "Synthesized", !PointerEventHandler::GetLastPointerId() ? "no last pointerId"
: nsPrintfCString("different from last pointerId (%u)", *PointerEventHandler
::GetLastPointerId()) .get(), this, GetRootPresShell()); } } while
(0)
5043 ToChar(aEvent->mMessage), aEvent->IsReal() ? "Real" : "Synthesized",do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Stopped updating cursor for the pointer "
"because of %s, ESM: %p, in-process root PresShell: %p", aEvent
->pointerId, InputSourceToString(aEvent->mInputSource).
get(), ToChar(aEvent->mMessage), aEvent->IsReal() ? "Real"
: "Synthesized", !PointerEventHandler::GetLastPointerId() ? "no last pointerId"
: nsPrintfCString("different from last pointerId (%u)", *PointerEventHandler
::GetLastPointerId()) .get(), this, GetRootPresShell()); } } while
(0)
5044 !PointerEventHandler::GetLastPointerId()do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Stopped updating cursor for the pointer "
"because of %s, ESM: %p, in-process root PresShell: %p", aEvent
->pointerId, InputSourceToString(aEvent->mInputSource).
get(), ToChar(aEvent->mMessage), aEvent->IsReal() ? "Real"
: "Synthesized", !PointerEventHandler::GetLastPointerId() ? "no last pointerId"
: nsPrintfCString("different from last pointerId (%u)", *PointerEventHandler
::GetLastPointerId()) .get(), this, GetRootPresShell()); } } while
(0)
5045 ? "no last pointerId"do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Stopped updating cursor for the pointer "
"because of %s, ESM: %p, in-process root PresShell: %p", aEvent
->pointerId, InputSourceToString(aEvent->mInputSource).
get(), ToChar(aEvent->mMessage), aEvent->IsReal() ? "Real"
: "Synthesized", !PointerEventHandler::GetLastPointerId() ? "no last pointerId"
: nsPrintfCString("different from last pointerId (%u)", *PointerEventHandler
::GetLastPointerId()) .get(), this, GetRootPresShell()); } } while
(0)
5046 : nsPrintfCString("different from last pointerId (%u)",do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Stopped updating cursor for the pointer "
"because of %s, ESM: %p, in-process root PresShell: %p", aEvent
->pointerId, InputSourceToString(aEvent->mInputSource).
get(), ToChar(aEvent->mMessage), aEvent->IsReal() ? "Real"
: "Synthesized", !PointerEventHandler::GetLastPointerId() ? "no last pointerId"
: nsPrintfCString("different from last pointerId (%u)", *PointerEventHandler
::GetLastPointerId()) .get(), this, GetRootPresShell()); } } while
(0)
5047 *PointerEventHandler::GetLastPointerId())do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Stopped updating cursor for the pointer "
"because of %s, ESM: %p, in-process root PresShell: %p", aEvent
->pointerId, InputSourceToString(aEvent->mInputSource).
get(), ToChar(aEvent->mMessage), aEvent->IsReal() ? "Real"
: "Synthesized", !PointerEventHandler::GetLastPointerId() ? "no last pointerId"
: nsPrintfCString("different from last pointerId (%u)", *PointerEventHandler
::GetLastPointerId()) .get(), this, GetRootPresShell()); } } while
(0)
5048 .get(),do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Stopped updating cursor for the pointer "
"because of %s, ESM: %p, in-process root PresShell: %p", aEvent
->pointerId, InputSourceToString(aEvent->mInputSource).
get(), ToChar(aEvent->mMessage), aEvent->IsReal() ? "Real"
: "Synthesized", !PointerEventHandler::GetLastPointerId() ? "no last pointerId"
: nsPrintfCString("different from last pointerId (%u)", *PointerEventHandler
::GetLastPointerId()) .get(), this, GetRootPresShell()); } } while
(0)
5049 this, GetRootPresShell()))do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Stopped updating cursor for the pointer "
"because of %s, ESM: %p, in-process root PresShell: %p", aEvent
->pointerId, InputSourceToString(aEvent->mInputSource).
get(), ToChar(aEvent->mMessage), aEvent->IsReal() ? "Real"
: "Synthesized", !PointerEventHandler::GetLastPointerId() ? "no last pointerId"
: nsPrintfCString("different from last pointerId (%u)", *PointerEventHandler
::GetLastPointerId()) .get(), this, GetRootPresShell()); } } while
(0)
;
5050 return;
5051 }
5052
5053 // XXX This is still not entirely correct, e.g. when mouse hover over the
5054 // broder of a cross-origin iframe, we should show the cursor specified on the
5055 // iframe (see bug 1943530).
5056 if (nsSubDocumentFrame* f = do_QueryFrame(aTargetFrame)) {
5057 if (auto* fl = f->FrameLoader();
5058 fl && fl->IsRemoteFrame() && f->ContentReactsToPointerEvents()) {
5059 // The sub-frame will update the cursor if needed.
5060 MOZ_LOG_DEBUG_ONLY(do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Stopped updating cursor for the pointer "
"because of over a remote frame, ESM: %p, in-process root " "PresShell: %p"
, aEvent->pointerId, InputSourceToString(aEvent->mInputSource
).get(), ToChar(aEvent->mMessage), RealOrSynthesized(aEvent
->IsReal()), this, GetRootPresShell()); } } while (0)
5061 gMouseCursorUpdates, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Stopped updating cursor for the pointer "
"because of over a remote frame, ESM: %p, in-process root " "PresShell: %p"
, aEvent->pointerId, InputSourceToString(aEvent->mInputSource
).get(), ToChar(aEvent->mMessage), RealOrSynthesized(aEvent
->IsReal()), this, GetRootPresShell()); } } while (0)
5062 ("EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Stopped updating cursor for the pointer "
"because of over a remote frame, ESM: %p, in-process root " "PresShell: %p"
, aEvent->pointerId, InputSourceToString(aEvent->mInputSource
).get(), ToChar(aEvent->mMessage), RealOrSynthesized(aEvent
->IsReal()), this, GetRootPresShell()); } } while (0)
5063 "message=%s, reason=%s}): Stopped updating cursor for the pointer "do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Stopped updating cursor for the pointer "
"because of over a remote frame, ESM: %p, in-process root " "PresShell: %p"
, aEvent->pointerId, InputSourceToString(aEvent->mInputSource
).get(), ToChar(aEvent->mMessage), RealOrSynthesized(aEvent
->IsReal()), this, GetRootPresShell()); } } while (0)
5064 "because of over a remote frame, ESM: %p, in-process root "do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Stopped updating cursor for the pointer "
"because of over a remote frame, ESM: %p, in-process root " "PresShell: %p"
, aEvent->pointerId, InputSourceToString(aEvent->mInputSource
).get(), ToChar(aEvent->mMessage), RealOrSynthesized(aEvent
->IsReal()), this, GetRootPresShell()); } } while (0)
5065 "PresShell: %p",do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Stopped updating cursor for the pointer "
"because of over a remote frame, ESM: %p, in-process root " "PresShell: %p"
, aEvent->pointerId, InputSourceToString(aEvent->mInputSource
).get(), ToChar(aEvent->mMessage), RealOrSynthesized(aEvent
->IsReal()), this, GetRootPresShell()); } } while (0)
5066 aEvent->pointerId, InputSourceToString(aEvent->mInputSource).get(),do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Stopped updating cursor for the pointer "
"because of over a remote frame, ESM: %p, in-process root " "PresShell: %p"
, aEvent->pointerId, InputSourceToString(aEvent->mInputSource
).get(), ToChar(aEvent->mMessage), RealOrSynthesized(aEvent
->IsReal()), this, GetRootPresShell()); } } while (0)
5067 ToChar(aEvent->mMessage), RealOrSynthesized(aEvent->IsReal()), this,do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Stopped updating cursor for the pointer "
"because of over a remote frame, ESM: %p, in-process root " "PresShell: %p"
, aEvent->pointerId, InputSourceToString(aEvent->mInputSource
).get(), ToChar(aEvent->mMessage), RealOrSynthesized(aEvent
->IsReal()), this, GetRootPresShell()); } } while (0)
5068 GetRootPresShell()))do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Stopped updating cursor for the pointer "
"because of over a remote frame, ESM: %p, in-process root " "PresShell: %p"
, aEvent->pointerId, InputSourceToString(aEvent->mInputSource
).get(), ToChar(aEvent->mMessage), RealOrSynthesized(aEvent
->IsReal()), this, GetRootPresShell()); } } while (0)
;
5069 return;
5070 }
5071 }
5072
5073 auto cursor = StyleCursorKind::Default;
5074 nsCOMPtr<imgIContainer> container;
5075 ImageResolution resolution;
5076 Maybe<gfx::IntPoint> hotspot;
5077
5078 if (mHidingCursorWhileTyping && aEvent->IsReal()) {
5079 // Any non-synthetic mouse event makes us show the cursor again.
5080 mHidingCursorWhileTyping = false;
5081 }
5082
5083 if (mHidingCursorWhileTyping) {
5084 cursor = StyleCursorKind::None;
5085 } else if (mLockCursor != kInvalidCursorKind) {
5086 // If cursor is locked just use the locked one
5087 cursor = mLockCursor;
5088 } else if (aTargetFrame) {
5089 // If not locked, look for correct cursor
5090 nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(
5091 aEvent, RelativeTo{aTargetFrame});
5092 const nsIFrame::Cursor framecursor = aTargetFrame->GetCursor(pt);
5093 const CursorImage customCursor =
5094 ComputeCustomCursor(aPresContext, aEvent, *aTargetFrame, framecursor);
5095
5096 // If the current cursor is from the same frame, and it is now
5097 // loading some new image for the cursor, we should wait for a
5098 // while rather than taking its fallback cursor directly.
5099 if (customCursor.mEarlierCursorLoading &&
5100 gLastCursorSourceFrame == aTargetFrame &&
5101 TimeStamp::NowLoRes() - gLastCursorUpdateTime <
5102 TimeDuration::FromMilliseconds(kCursorLoadingTimeout)) {
5103 return;
5104 }
5105 cursor = framecursor.mCursor;
5106 container = std::move(customCursor.mContainer);
5107 resolution = customCursor.mResolution;
5108 hotspot = Some(customCursor.mHotspot);
5109 }
5110
5111 if (aTargetFrame) {
5112 if (cursor == StyleCursorKind::Pointer && IsSelectingLink(aTargetFrame)) {
5113 cursor = aTargetFrame->GetWritingMode().IsVertical()
5114 ? StyleCursorKind::VerticalText
5115 : StyleCursorKind::Text;
5116 }
5117 SetCursor(cursor, container, resolution, hotspot,
5118 aTargetFrame->GetNearestWidget(), false);
5119 gLastCursorSourceFrame = aTargetFrame;
5120 gLastCursorUpdateTime = TimeStamp::NowLoRes();
5121 MOZ_LOG_DEBUG_ONLY(do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Updated the cursor to %u, ESM: %p, "
"in-process root PresShell: %p", aEvent->pointerId, InputSourceToString
(aEvent->mInputSource).get(), ToChar(aEvent->mMessage),
aEvent->IsReal() ? "Real" : "Synthesized", static_cast<
uint32_t>(cursor), this, GetRootPresShell()); } } while (0
)
5122 gMouseCursorUpdates, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Updated the cursor to %u, ESM: %p, "
"in-process root PresShell: %p", aEvent->pointerId, InputSourceToString
(aEvent->mInputSource).get(), ToChar(aEvent->mMessage),
aEvent->IsReal() ? "Real" : "Synthesized", static_cast<
uint32_t>(cursor), this, GetRootPresShell()); } } while (0
)
5123 ("EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Updated the cursor to %u, ESM: %p, "
"in-process root PresShell: %p", aEvent->pointerId, InputSourceToString
(aEvent->mInputSource).get(), ToChar(aEvent->mMessage),
aEvent->IsReal() ? "Real" : "Synthesized", static_cast<
uint32_t>(cursor), this, GetRootPresShell()); } } while (0
)
5124 "message=%s, reason=%s}): Updated the cursor to %u, ESM: %p, "do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Updated the cursor to %u, ESM: %p, "
"in-process root PresShell: %p", aEvent->pointerId, InputSourceToString
(aEvent->mInputSource).get(), ToChar(aEvent->mMessage),
aEvent->IsReal() ? "Real" : "Synthesized", static_cast<
uint32_t>(cursor), this, GetRootPresShell()); } } while (0
)
5125 "in-process root PresShell: %p",do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Updated the cursor to %u, ESM: %p, "
"in-process root PresShell: %p", aEvent->pointerId, InputSourceToString
(aEvent->mInputSource).get(), ToChar(aEvent->mMessage),
aEvent->IsReal() ? "Real" : "Synthesized", static_cast<
uint32_t>(cursor), this, GetRootPresShell()); } } while (0
)
5126 aEvent->pointerId, InputSourceToString(aEvent->mInputSource).get(),do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Updated the cursor to %u, ESM: %p, "
"in-process root PresShell: %p", aEvent->pointerId, InputSourceToString
(aEvent->mInputSource).get(), ToChar(aEvent->mMessage),
aEvent->IsReal() ? "Real" : "Synthesized", static_cast<
uint32_t>(cursor), this, GetRootPresShell()); } } while (0
)
5127 ToChar(aEvent->mMessage), aEvent->IsReal() ? "Real" : "Synthesized",do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Updated the cursor to %u, ESM: %p, "
"in-process root PresShell: %p", aEvent->pointerId, InputSourceToString
(aEvent->mInputSource).get(), ToChar(aEvent->mMessage),
aEvent->IsReal() ? "Real" : "Synthesized", static_cast<
uint32_t>(cursor), this, GetRootPresShell()); } } while (0
)
5128 static_cast<uint32_t>(cursor), this, GetRootPresShell()))do { const ::mozilla::LogModule* moz_real_module = gMouseCursorUpdates
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "EventStateManager::UpdateCursor(aEvent=${pointerId=%u, source=%s, "
"message=%s, reason=%s}): Updated the cursor to %u, ESM: %p, "
"in-process root PresShell: %p", aEvent->pointerId, InputSourceToString
(aEvent->mInputSource).get(), ToChar(aEvent->mMessage),
aEvent->IsReal() ? "Real" : "Synthesized", static_cast<
uint32_t>(cursor), this, GetRootPresShell()); } } while (0
)
;
5129 }
5130
5131 if (mLockCursor != kInvalidCursorKind || StyleCursorKind::Auto != cursor) {
5132 *aStatus = nsEventStatus_eConsumeDoDefault;
5133 }
5134}
5135
5136void EventStateManager::ClearCachedWidgetCursor(nsIFrame* aTargetFrame) {
5137 if (!aTargetFrame) {
5138 return;
5139 }
5140 nsIWidget* aWidget = aTargetFrame->GetNearestWidget();
5141 if (!aWidget) {
5142 return;
5143 }
5144 aWidget->ClearCachedCursor();
5145}
5146
5147void EventStateManager::StartHidingCursorWhileTyping(nsIWidget* aWidget) {
5148 if (mHidingCursorWhileTyping || sCursorSettingManager != this) {
5149 return;
5150 }
5151 mHidingCursorWhileTyping = true;
5152 SetCursor(StyleCursorKind::None, nullptr, {}, {}, aWidget, false);
5153}
5154
5155nsresult EventStateManager::SetCursor(StyleCursorKind aCursor,
5156 imgIContainer* aContainer,
5157 const ImageResolution& aResolution,
5158 const Maybe<gfx::IntPoint>& aHotspot,
5159 nsIWidget* aWidget, bool aLockCursor) {
5160 EnsureDocument(mPresContext);
5161 NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocument" ") failed", nullptr
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 5161
); return NS_ERROR_FAILURE; } } while (false)
;
5162 sCursorSettingManager = this;
5163
5164 NS_ENSURE_TRUE(aWidget, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(aWidget)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aWidget" ") failed", nullptr
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 5164
); return NS_ERROR_FAILURE; } } while (false)
;
5165 if (aLockCursor) {
5166 if (StyleCursorKind::Auto != aCursor) {
5167 mLockCursor = aCursor;
5168 } else {
5169 // If cursor style is set to auto we unlock the cursor again.
5170 mLockCursor = kInvalidCursorKind;
5171 }
5172 }
5173 nsCursor c;
5174 switch (aCursor) {
5175 case StyleCursorKind::Auto:
5176 case StyleCursorKind::Default:
5177 c = eCursor_standard;
5178 break;
5179 case StyleCursorKind::Pointer:
5180 c = eCursor_hyperlink;
5181 break;
5182 case StyleCursorKind::Crosshair:
5183 c = eCursor_crosshair;
5184 break;
5185 case StyleCursorKind::Move:
5186 c = eCursor_move;
5187 break;
5188 case StyleCursorKind::Text:
5189 c = eCursor_select;
5190 break;
5191 case StyleCursorKind::Wait:
5192 c = eCursor_wait;
5193 break;
5194 case StyleCursorKind::Help:
5195 c = eCursor_help;
5196 break;
5197 case StyleCursorKind::NResize:
5198 c = eCursor_n_resize;
5199 break;
5200 case StyleCursorKind::SResize:
5201 c = eCursor_s_resize;
5202 break;
5203 case StyleCursorKind::WResize:
5204 c = eCursor_w_resize;
5205 break;
5206 case StyleCursorKind::EResize:
5207 c = eCursor_e_resize;
5208 break;
5209 case StyleCursorKind::NwResize:
5210 c = eCursor_nw_resize;
5211 break;
5212 case StyleCursorKind::SeResize:
5213 c = eCursor_se_resize;
5214 break;
5215 case StyleCursorKind::NeResize:
5216 c = eCursor_ne_resize;
5217 break;
5218 case StyleCursorKind::SwResize:
5219 c = eCursor_sw_resize;
5220 break;
5221 case StyleCursorKind::Copy: // CSS3
5222 c = eCursor_copy;
5223 break;
5224 case StyleCursorKind::Alias:
5225 c = eCursor_alias;
5226 break;
5227 case StyleCursorKind::ContextMenu:
5228 c = eCursor_context_menu;
5229 break;
5230 case StyleCursorKind::Cell:
5231 c = eCursor_cell;
5232 break;
5233 case StyleCursorKind::Grab:
5234 c = eCursor_grab;
5235 break;
5236 case StyleCursorKind::Grabbing:
5237 c = eCursor_grabbing;
5238 break;
5239 case StyleCursorKind::Progress:
5240 c = eCursor_spinning;
5241 break;
5242 case StyleCursorKind::ZoomIn:
5243 c = eCursor_zoom_in;
5244 break;
5245 case StyleCursorKind::ZoomOut:
5246 c = eCursor_zoom_out;
5247 break;
5248 case StyleCursorKind::NotAllowed:
5249 c = eCursor_not_allowed;
5250 break;
5251 case StyleCursorKind::ColResize:
5252 c = eCursor_col_resize;
5253 break;
5254 case StyleCursorKind::RowResize:
5255 c = eCursor_row_resize;
5256 break;
5257 case StyleCursorKind::NoDrop:
5258 c = eCursor_no_drop;
5259 break;
5260 case StyleCursorKind::VerticalText:
5261 c = eCursor_vertical_text;
5262 break;
5263 case StyleCursorKind::AllScroll:
5264 c = eCursor_all_scroll;
5265 break;
5266 case StyleCursorKind::NeswResize:
5267 c = eCursor_nesw_resize;
5268 break;
5269 case StyleCursorKind::NwseResize:
5270 c = eCursor_nwse_resize;
5271 break;
5272 case StyleCursorKind::NsResize:
5273 c = eCursor_ns_resize;
5274 break;
5275 case StyleCursorKind::EwResize:
5276 c = eCursor_ew_resize;
5277 break;
5278 case StyleCursorKind::None:
5279 c = eCursor_none;
5280 break;
5281 default:
5282 MOZ_ASSERT_UNREACHABLE("Unknown cursor kind")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Unknown cursor kind" ")", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 5282); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unknown cursor kind" ")"); do { MOZ_CrashSequence
(__null, 5282); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5283 c = eCursor_standard;
5284 break;
5285 }
5286
5287 uint32_t x = aHotspot ? aHotspot->x.value : 0;
5288 uint32_t y = aHotspot ? aHotspot->y.value : 0;
5289 aWidget->SetCursor(nsIWidget::Cursor{c, aContainer, x, y, aResolution});
5290 return NS_OK;
5291}
5292
5293bool EventStateManager::CursorSettingManagerHasLockedCursor() {
5294 return sCursorSettingManager &&
5295 sCursorSettingManager->mLockCursor != kInvalidCursorKind;
5296}
5297
5298class MOZ_STACK_CLASS ESMEventCB : public EventDispatchingCallback {
5299 public:
5300 explicit ESMEventCB(nsIContent* aTarget) : mTarget(aTarget) {}
5301
5302 MOZ_CAN_RUN_SCRIPT
5303 void HandleEvent(EventChainPostVisitor& aVisitor) override {
5304 if (aVisitor.mPresContext) {
5305 nsIFrame* frame =
5306 aVisitor.mPresContext->GetPrimaryOrAreaImageFrameFor(mTarget);
5307 if (frame) {
5308 frame->HandleEvent(aVisitor.mPresContext, aVisitor.mEvent->AsGUIEvent(),
5309 &aVisitor.mEventStatus);
5310 }
5311 }
5312 }
5313
5314 nsCOMPtr<nsIContent> mTarget;
5315};
5316
5317static UniquePtr<WidgetMouseEvent> CreateMouseOrPointerWidgetEvent(
5318 const WidgetMouseEvent* aMouseEvent, EventMessage aMessage,
5319 EventTarget* aRelatedTarget) {
5320 // This method does not support creating a mouse/pointer button change event
5321 // because of no data about the changing state.
5322 MOZ_ASSERT(aMessage != eMouseDown)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMessage != eMouseDown)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMessage != eMouseDown))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aMessage != eMouseDown"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 5322
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage != eMouseDown"
")"); do { MOZ_CrashSequence(__null, 5322); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5323 MOZ_ASSERT(aMessage != eMouseUp)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMessage != eMouseUp)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMessage != eMouseUp))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("aMessage != eMouseUp"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 5323
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage != eMouseUp"
")"); do { MOZ_CrashSequence(__null, 5323); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5324 MOZ_ASSERT(aMessage != ePointerDown)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMessage != ePointerDown)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMessage != ePointerDown))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("aMessage != ePointerDown"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 5324
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage != ePointerDown"
")"); do { MOZ_CrashSequence(__null, 5324); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5325 MOZ_ASSERT(aMessage != ePointerUp)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMessage != ePointerUp)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMessage != ePointerUp))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aMessage != ePointerUp"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 5325
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage != ePointerUp"
")"); do { MOZ_CrashSequence(__null, 5325); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5326 // This method is currently designed to create the following events.
5327 MOZ_ASSERT(aMessage == eMouseOver || aMessage == eMouseEnter ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMessage == eMouseOver || aMessage == eMouseEnter ||
aMessage == eMouseOut || aMessage == eMouseLeave || aMessage
== ePointerOver || aMessage == ePointerEnter || aMessage == ePointerOut
|| aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget
|| aMessage == eMouseExitFromWidget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMessage == eMouseOver || aMessage
== eMouseEnter || aMessage == eMouseOut || aMessage == eMouseLeave
|| aMessage == ePointerOver || aMessage == ePointerEnter || aMessage
== ePointerOut || aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget
|| aMessage == eMouseExitFromWidget))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("aMessage == eMouseOver || aMessage == eMouseEnter || aMessage == eMouseOut || aMessage == eMouseLeave || aMessage == ePointerOver || aMessage == ePointerEnter || aMessage == ePointerOut || aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget || aMessage == eMouseExitFromWidget"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 5332
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage == eMouseOver || aMessage == eMouseEnter || aMessage == eMouseOut || aMessage == eMouseLeave || aMessage == ePointerOver || aMessage == ePointerEnter || aMessage == ePointerOut || aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget || aMessage == eMouseExitFromWidget"
")"); do { MOZ_CrashSequence(__null, 5332); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5328 aMessage == eMouseOut || aMessage == eMouseLeave ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMessage == eMouseOver || aMessage == eMouseEnter ||
aMessage == eMouseOut || aMessage == eMouseLeave || aMessage
== ePointerOver || aMessage == ePointerEnter || aMessage == ePointerOut
|| aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget
|| aMessage == eMouseExitFromWidget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMessage == eMouseOver || aMessage
== eMouseEnter || aMessage == eMouseOut || aMessage == eMouseLeave
|| aMessage == ePointerOver || aMessage == ePointerEnter || aMessage
== ePointerOut || aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget
|| aMessage == eMouseExitFromWidget))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("aMessage == eMouseOver || aMessage == eMouseEnter || aMessage == eMouseOut || aMessage == eMouseLeave || aMessage == ePointerOver || aMessage == ePointerEnter || aMessage == ePointerOut || aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget || aMessage == eMouseExitFromWidget"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 5332
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage == eMouseOver || aMessage == eMouseEnter || aMessage == eMouseOut || aMessage == eMouseLeave || aMessage == ePointerOver || aMessage == ePointerEnter || aMessage == ePointerOut || aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget || aMessage == eMouseExitFromWidget"
")"); do { MOZ_CrashSequence(__null, 5332); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5329 aMessage == ePointerOver || aMessage == ePointerEnter ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMessage == eMouseOver || aMessage == eMouseEnter ||
aMessage == eMouseOut || aMessage == eMouseLeave || aMessage
== ePointerOver || aMessage == ePointerEnter || aMessage == ePointerOut
|| aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget
|| aMessage == eMouseExitFromWidget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMessage == eMouseOver || aMessage
== eMouseEnter || aMessage == eMouseOut || aMessage == eMouseLeave
|| aMessage == ePointerOver || aMessage == ePointerEnter || aMessage
== ePointerOut || aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget
|| aMessage == eMouseExitFromWidget))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("aMessage == eMouseOver || aMessage == eMouseEnter || aMessage == eMouseOut || aMessage == eMouseLeave || aMessage == ePointerOver || aMessage == ePointerEnter || aMessage == ePointerOut || aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget || aMessage == eMouseExitFromWidget"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 5332
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage == eMouseOver || aMessage == eMouseEnter || aMessage == eMouseOut || aMessage == eMouseLeave || aMessage == ePointerOver || aMessage == ePointerEnter || aMessage == ePointerOut || aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget || aMessage == eMouseExitFromWidget"
")"); do { MOZ_CrashSequence(__null, 5332); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5330 aMessage == ePointerOut || aMessage == ePointerLeave ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMessage == eMouseOver || aMessage == eMouseEnter ||
aMessage == eMouseOut || aMessage == eMouseLeave || aMessage
== ePointerOver || aMessage == ePointerEnter || aMessage == ePointerOut
|| aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget
|| aMessage == eMouseExitFromWidget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMessage == eMouseOver || aMessage
== eMouseEnter || aMessage == eMouseOut || aMessage == eMouseLeave
|| aMessage == ePointerOver || aMessage == ePointerEnter || aMessage
== ePointerOut || aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget
|| aMessage == eMouseExitFromWidget))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("aMessage == eMouseOver || aMessage == eMouseEnter || aMessage == eMouseOut || aMessage == eMouseLeave || aMessage == ePointerOver || aMessage == ePointerEnter || aMessage == ePointerOut || aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget || aMessage == eMouseExitFromWidget"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 5332
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage == eMouseOver || aMessage == eMouseEnter || aMessage == eMouseOut || aMessage == eMouseLeave || aMessage == ePointerOver || aMessage == ePointerEnter || aMessage == ePointerOut || aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget || aMessage == eMouseExitFromWidget"
")"); do { MOZ_CrashSequence(__null, 5332); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5331 aMessage == eMouseEnterIntoWidget ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMessage == eMouseOver || aMessage == eMouseEnter ||
aMessage == eMouseOut || aMessage == eMouseLeave || aMessage
== ePointerOver || aMessage == ePointerEnter || aMessage == ePointerOut
|| aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget
|| aMessage == eMouseExitFromWidget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMessage == eMouseOver || aMessage
== eMouseEnter || aMessage == eMouseOut || aMessage == eMouseLeave
|| aMessage == ePointerOver || aMessage == ePointerEnter || aMessage
== ePointerOut || aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget
|| aMessage == eMouseExitFromWidget))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("aMessage == eMouseOver || aMessage == eMouseEnter || aMessage == eMouseOut || aMessage == eMouseLeave || aMessage == ePointerOver || aMessage == ePointerEnter || aMessage == ePointerOut || aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget || aMessage == eMouseExitFromWidget"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 5332
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage == eMouseOver || aMessage == eMouseEnter || aMessage == eMouseOut || aMessage == eMouseLeave || aMessage == ePointerOver || aMessage == ePointerEnter || aMessage == ePointerOut || aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget || aMessage == eMouseExitFromWidget"
")"); do { MOZ_CrashSequence(__null, 5332); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5332 aMessage == eMouseExitFromWidget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMessage == eMouseOver || aMessage == eMouseEnter ||
aMessage == eMouseOut || aMessage == eMouseLeave || aMessage
== ePointerOver || aMessage == ePointerEnter || aMessage == ePointerOut
|| aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget
|| aMessage == eMouseExitFromWidget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMessage == eMouseOver || aMessage
== eMouseEnter || aMessage == eMouseOut || aMessage == eMouseLeave
|| aMessage == ePointerOver || aMessage == ePointerEnter || aMessage
== ePointerOut || aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget
|| aMessage == eMouseExitFromWidget))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("aMessage == eMouseOver || aMessage == eMouseEnter || aMessage == eMouseOut || aMessage == eMouseLeave || aMessage == ePointerOver || aMessage == ePointerEnter || aMessage == ePointerOut || aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget || aMessage == eMouseExitFromWidget"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 5332
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage == eMouseOver || aMessage == eMouseEnter || aMessage == eMouseOut || aMessage == eMouseLeave || aMessage == ePointerOver || aMessage == ePointerEnter || aMessage == ePointerOut || aMessage == ePointerLeave || aMessage == eMouseEnterIntoWidget || aMessage == eMouseExitFromWidget"
")"); do { MOZ_CrashSequence(__null, 5332); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5333
5334 UniquePtr<WidgetMouseEvent> newEvent;
5335 if (IsPointerEventMessage(aMessage)) {
5336 AUTO_PROFILER_LABEL("CreateMouseOrPointerWidgetEvent", OTHER)mozilla::AutoProfilerLabel raiiObject5336( "CreateMouseOrPointerWidgetEvent"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
5337
5338 newEvent = std::make_unique<WidgetPointerEvent>(
5339 aMouseEvent->IsTrusted(), aMessage, aMouseEvent->mWidget);
5340 if (const WidgetPointerEvent* const sourcePointerEvent =
5341 aMouseEvent->AsPointerEvent()) {
5342 WidgetPointerEvent* const newPointerEvent =
5343 static_cast<WidgetPointerEvent*>(newEvent.get());
5344 newPointerEvent->mIsPrimary = sourcePointerEvent->mIsPrimary;
5345 newPointerEvent->mWidth = sourcePointerEvent->mWidth;
5346 newPointerEvent->mHeight = sourcePointerEvent->mHeight;
5347 // Not assigning mFromTouchEvent
5348 }
5349 } else {
5350 newEvent = std::make_unique<WidgetMouseEvent>(
5351 aMouseEvent->IsTrusted(), aMessage, aMouseEvent->mWidget,
5352 WidgetMouseEvent::eReal);
5353 }
5354
5355 // Inherit whether the event is synthesized by the test API or not.
5356 // Then, when the event is synthesized by a test API and handled in a remote
5357 // process, it won't be ignored. See PresShell::HandleEvent().
5358 newEvent->mFlags.mIsSynthesizedForTests =
5359 aMouseEvent->mFlags.mIsSynthesizedForTests;
5360
5361 newEvent->mRelatedTarget = aRelatedTarget;
5362 newEvent->mRefPoint = aMouseEvent->mRefPoint;
5363 newEvent->mModifiers = aMouseEvent->mModifiers;
5364 newEvent->mInputSource = aMouseEvent->mInputSource;
5365 newEvent->pointerId = aMouseEvent->pointerId;
5366 newEvent->mMovement = aMouseEvent->mMovement;
5367 // NOTE: If you need to change this if-expression, you need to update
5368 // WidgetMouseEventBase::ComputeMouseButtonPressure() too.
5369 if (!aMouseEvent->mFlags.mDispatchedAtLeastOnce &&
5370 aMouseEvent->InputSourceSupportsHover()) {
5371 // If we synthesize a pointer event or a mouse event from another event
5372 // which changes a button state whose input soucre supports hover state and
5373 // the source event has not been dispatched yet, we should set to the button
5374 // state of the synthesizing event to previous one.
5375 // Note that we don't need to do this if the input source does not support
5376 // hover state because a WPT check the behavior (see below) and the other
5377 // browsers pass the test even though this is inconsistent behavior.
5378 newEvent->mButton = newEvent->mClass == ePointerEventClass
5379 ? MouseButton::eNotPressed
5380 : MouseButton::ePrimary;
5381 // If the source event has not been dispatched into the DOM yet, we
5382 // need to remove the flag which is being pressed. Similarly, if the source
5383 // event has not been dispatched into the DOM yet, we need to add the flag
5384 // which is being released.
5385 newEvent->mButtons = aMouseEvent->ComputeButtonsBeforeDispatch();
5386 // Adjust pressure if it does not matches with mButtons.
5387 // FIXME: We may use wrong pressure value if the source event has not been
5388 // dispatched into the DOM yet. However, fixing this requires to store the
5389 // last pressure value somewhere (bug 1953669).
5390 newEvent->mPressure = newEvent->ComputeMouseButtonPressure();
5391 } else {
5392 // If the event has already been dispatched into the tree, web apps has
5393 // already handled the button state change, so the button state of the
5394 // source event has already synced.
5395 // If the input source does not have hover state, we don't need to modify
5396 // the state because the other browsers behave so and tested by
5397 // pointerevent_attributes_nohover_pointers.html even though this is
5398 // different expectation from
5399 // pointerevent_attributes_hoverable_pointers.html, but the other browsers
5400 // pass both of them.
5401 newEvent->mButton = aMouseEvent->mButton;
5402 newEvent->mButtons = aMouseEvent->mButtons;
5403 newEvent->mPressure = aMouseEvent->mPressure;
5404 }
5405 return newEvent;
5406}
5407
5408already_AddRefed<nsIWidget>
5409EventStateManager::DispatchMouseOrPointerBoundaryEvent(
5410 WidgetMouseEvent* aMouseEvent, EventMessage aMessage,
5411 nsIContent* aTargetContent, nsIContent* aRelatedContent) {
5412 MOZ_ASSERT(aMessage == eMouseEnter || aMessage == ePointerEnter ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMessage == eMouseEnter || aMessage == ePointerEnter
|| aMessage == eMouseLeave || aMessage == ePointerLeave || aMessage
== eMouseOver || aMessage == ePointerOver || aMessage == eMouseOut
|| aMessage == ePointerOut)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMessage == eMouseEnter || aMessage
== ePointerEnter || aMessage == eMouseLeave || aMessage == ePointerLeave
|| aMessage == eMouseOver || aMessage == ePointerOver || aMessage
== eMouseOut || aMessage == ePointerOut))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aMessage == eMouseEnter || aMessage == ePointerEnter || aMessage == eMouseLeave || aMessage == ePointerLeave || aMessage == eMouseOver || aMessage == ePointerOver || aMessage == eMouseOut || aMessage == ePointerOut"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 5415
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage == eMouseEnter || aMessage == ePointerEnter || aMessage == eMouseLeave || aMessage == ePointerLeave || aMessage == eMouseOver || aMessage == ePointerOver || aMessage == eMouseOut || aMessage == ePointerOut"
")"); do { MOZ_CrashSequence(__null, 5415); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
59
Taking false branch
5413 aMessage == eMouseLeave || aMessage == ePointerLeave ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMessage == eMouseEnter || aMessage == ePointerEnter
|| aMessage == eMouseLeave || aMessage == ePointerLeave || aMessage
== eMouseOver || aMessage == ePointerOver || aMessage == eMouseOut
|| aMessage == ePointerOut)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMessage == eMouseEnter || aMessage
== ePointerEnter || aMessage == eMouseLeave || aMessage == ePointerLeave
|| aMessage == eMouseOver || aMessage == ePointerOver || aMessage
== eMouseOut || aMessage == ePointerOut))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aMessage == eMouseEnter || aMessage == ePointerEnter || aMessage == eMouseLeave || aMessage == ePointerLeave || aMessage == eMouseOver || aMessage == ePointerOver || aMessage == eMouseOut || aMessage == ePointerOut"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 5415
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage == eMouseEnter || aMessage == ePointerEnter || aMessage == eMouseLeave || aMessage == ePointerLeave || aMessage == eMouseOver || aMessage == ePointerOver || aMessage == eMouseOut || aMessage == ePointerOut"
")"); do { MOZ_CrashSequence(__null, 5415); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5414 aMessage == eMouseOver || aMessage == ePointerOver ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMessage == eMouseEnter || aMessage == ePointerEnter
|| aMessage == eMouseLeave || aMessage == ePointerLeave || aMessage
== eMouseOver || aMessage == ePointerOver || aMessage == eMouseOut
|| aMessage == ePointerOut)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMessage == eMouseEnter || aMessage
== ePointerEnter || aMessage == eMouseLeave || aMessage == ePointerLeave
|| aMessage == eMouseOver || aMessage == ePointerOver || aMessage
== eMouseOut || aMessage == ePointerOut))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aMessage == eMouseEnter || aMessage == ePointerEnter || aMessage == eMouseLeave || aMessage == ePointerLeave || aMessage == eMouseOver || aMessage == ePointerOver || aMessage == eMouseOut || aMessage == ePointerOut"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 5415
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage == eMouseEnter || aMessage == ePointerEnter || aMessage == eMouseLeave || aMessage == ePointerLeave || aMessage == eMouseOver || aMessage == ePointerOver || aMessage == eMouseOut || aMessage == ePointerOut"
")"); do { MOZ_CrashSequence(__null, 5415); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5415 aMessage == eMouseOut || aMessage == ePointerOut)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMessage == eMouseEnter || aMessage == ePointerEnter
|| aMessage == eMouseLeave || aMessage == ePointerLeave || aMessage
== eMouseOver || aMessage == ePointerOver || aMessage == eMouseOut
|| aMessage == ePointerOut)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMessage == eMouseEnter || aMessage
== ePointerEnter || aMessage == eMouseLeave || aMessage == ePointerLeave
|| aMessage == eMouseOver || aMessage == ePointerOver || aMessage
== eMouseOut || aMessage == ePointerOut))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aMessage == eMouseEnter || aMessage == ePointerEnter || aMessage == eMouseLeave || aMessage == ePointerLeave || aMessage == eMouseOver || aMessage == ePointerOver || aMessage == eMouseOut || aMessage == ePointerOut"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 5415
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage == eMouseEnter || aMessage == ePointerEnter || aMessage == eMouseLeave || aMessage == ePointerLeave || aMessage == eMouseOver || aMessage == ePointerOver || aMessage == eMouseOut || aMessage == ePointerOut"
")"); do { MOZ_CrashSequence(__null, 5415); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5416
5417 // https://w3c.github.io/pointerlock/#dom-element-requestpointerlock
5418 // "[Once in the locked state...E]vents that require the concept
5419 // of a mouse cursor must not be dispatched (for example: mouseover,
5420 // mouseout...).
5421 // XXXedgar should we also block pointer events?
5422 if (PointerLockManager::IsLocked() &&
60
Loop condition is false. Exiting loop
61
Assuming the condition is true
62
Taking true branch
5423 (aMessage
61.1
'aMessage' is not equal to eMouseLeave
== eMouseLeave || aMessage
61.2
'aMessage' is not equal to eMouseEnter
== eMouseEnter ||
5424 aMessage
61.3
'aMessage' is not equal to eMouseOver
== eMouseOver || aMessage
61.4
'aMessage' is equal to eMouseOut
== eMouseOut)) {
5425 mCurrentTargetContent = nullptr;
5426 nsCOMPtr<Element> pointerLockedElement =
5427 PointerLockManager::GetLockedElement();
5428 if (!pointerLockedElement) {
63
Taking false branch
5429 NS_WARNING("Should have pointer locked element, but didn't.")NS_DebugBreak(NS_DEBUG_WARNING, "Should have pointer locked element, but didn't."
, nullptr, "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 5429)
;
5430 return nullptr;
5431 }
5432 nsIFrame* const pointerLockedFrame =
64
'pointerLockedFrame' initialized here
5433 mPresContext->GetPrimaryOrAreaImageFrameFor(pointerLockedElement);
5434 if (NS_WARN_IF(!pointerLockedFrame)NS_warn_if_impl(!pointerLockedFrame, "!pointerLockedFrame", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 5434)
) {
65
Assuming 'pointerLockedFrame' is null
66
Assuming the condition is false
67
Taking false branch
5435 return nullptr;
5436 }
5437 return do_AddRef(pointerLockedFrame->GetNearestWidget());
68
Called C++ object pointer is null
5438 }
5439
5440 mCurrentTargetContent = nullptr;
5441
5442 if (!aTargetContent) {
5443 return nullptr;
5444 }
5445
5446 // Store the widget before dispatching the event because some event listeners
5447 // of the dispatching event may cause reframe the target or remove the target
5448 // from the tree.
5449 nsCOMPtr<nsIWidget> targetWidget;
5450 if (nsIFrame* const targetFrame =
5451 mPresContext->GetPrimaryOrAreaImageFrameFor(aTargetContent)) {
5452 targetWidget = targetFrame->GetNearestWidget();
5453 }
5454
5455 nsCOMPtr<nsIContent> targetContent = aTargetContent;
5456 nsCOMPtr<nsIContent> relatedContent = aRelatedContent;
5457
5458 UniquePtr<WidgetMouseEvent> dispatchEvent =
5459 CreateMouseOrPointerWidgetEvent(aMouseEvent, aMessage, relatedContent);
5460
5461 AutoWeakFrame previousTarget = mCurrentTarget;
5462 mCurrentTargetContent = targetContent;
5463
5464 nsEventStatus status = nsEventStatus_eIgnore;
5465 ESMEventCB callback(targetContent);
5466 RefPtr<nsPresContext> presContext = mPresContext;
5467 EventDispatcher::Dispatch(targetContent, presContext, dispatchEvent.get(),
5468 nullptr, &status, &callback);
5469
5470 if (mPresContext) {
5471 // If we are entering/leaving remote content, dispatch a mouse enter/exit
5472 // event to the remote frame.
5473 if (IsTopLevelRemoteTarget(targetContent)) {
5474 if (aMessage == eMouseOut) {
5475 // For remote content, send a puppet widget mouse exit event.
5476 UniquePtr<WidgetMouseEvent> remoteEvent =
5477 CreateMouseOrPointerWidgetEvent(aMouseEvent, eMouseExitFromWidget,
5478 relatedContent);
5479 remoteEvent->mExitFrom = Some(WidgetMouseEvent::ePuppet);
5480
5481 // mCurrentTarget is set to the new target, so we must reset it to the
5482 // old target and then dispatch a cross-process event. (mCurrentTarget
5483 // will be set back below.) HandleCrossProcessEvent will query for the
5484 // proper target via GetEventTarget which will return mCurrentTarget.
5485 mCurrentTarget =
5486 mPresContext->GetPrimaryOrAreaImageFrameFor(targetContent);
5487 HandleCrossProcessEvent(remoteEvent.get(), &status);
5488 } else if (aMessage == eMouseOver) {
5489 UniquePtr<WidgetMouseEvent> remoteEvent =
5490 CreateMouseOrPointerWidgetEvent(aMouseEvent, eMouseEnterIntoWidget,
5491 relatedContent);
5492 HandleCrossProcessEvent(remoteEvent.get(), &status);
5493 }
5494 }
5495 }
5496
5497 mCurrentTargetContent = nullptr;
5498 mCurrentTarget = previousTarget;
5499
5500 return targetWidget.forget();
5501}
5502
5503static nsIContent* FindCommonAncestor(nsIContent* aNode1, nsIContent* aNode2) {
5504 if (!aNode1 || !aNode2) {
5505 return nullptr;
5506 }
5507 return nsContentUtils::GetCommonFlattenedTreeAncestor(aNode1, aNode2);
5508}
5509
5510class EnterLeaveDispatcher {
5511 public:
5512 EnterLeaveDispatcher(EventStateManager* aESM, nsIContent* aTarget,
5513 nsIContent* aRelatedTarget,
5514 WidgetMouseEvent* aMouseEvent,
5515 EventMessage aEventMessage)
5516 : mESM(aESM), mMouseEvent(aMouseEvent), mEventMessage(aEventMessage) {
5517 nsPIDOMWindowInner* win =
5518 aTarget ? aTarget->OwnerDoc()->GetInnerWindow() : nullptr;
5519 if (aMouseEvent->AsPointerEvent()
5520 ? win && win->HasPointerEnterLeaveEventListeners()
5521 : win && win->HasMouseEnterLeaveEventListeners()) {
5522 mRelatedTarget =
5523 aRelatedTarget ? aRelatedTarget->FindFirstNonChromeOnlyAccessContent()
5524 : nullptr;
5525 nsINode* commonParent = FindCommonAncestor(aTarget, aRelatedTarget);
5526 nsIContent* current = aTarget;
5527 // Note, it is ok if commonParent is null!
5528 while (current && current != commonParent) {
5529 if (!current->ChromeOnlyAccess()) {
5530 mTargets.AppendObject(current);
5531 }
5532 // mouseenter/leave is fired only on elements.
5533 current = current->GetFlattenedTreeParent();
5534 }
5535 }
5536 }
5537
5538 // TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230)
5539 MOZ_CAN_RUN_SCRIPT_BOUNDARY void Dispatch() {
5540 if (mEventMessage == eMouseEnter || mEventMessage == ePointerEnter) {
5541 for (int32_t i = mTargets.Count() - 1; i >= 0; --i) {
5542 nsCOMPtr<nsIWidget> widget = mESM->DispatchMouseOrPointerBoundaryEvent(
5543 mMouseEvent, mEventMessage, MOZ_KnownLive(mTargets[i])(mTargets[i]),
5544 mRelatedTarget);
5545 }
5546 } else {
5547 for (int32_t i = 0; i < mTargets.Count(); ++i) {
5548 nsCOMPtr<nsIWidget> widget = mESM->DispatchMouseOrPointerBoundaryEvent(
5549 mMouseEvent, mEventMessage, MOZ_KnownLive(mTargets[i])(mTargets[i]),
5550 mRelatedTarget);
5551 }
5552 }
5553 }
5554
5555 // Nothing overwrites anything after constructor. Please remove MOZ_KnownLive
5556 // and MOZ_KNOWN_LIVE if anything marked as such becomes mutable.
5557 const RefPtr<EventStateManager> mESM;
5558 nsCOMArray<nsIContent> mTargets;
5559 MOZ_KNOWN_LIVE nsCOMPtr<nsIContent> mRelatedTarget;
5560 WidgetMouseEvent* mMouseEvent;
5561 EventMessage mEventMessage;
5562};
5563
5564void EventStateManager::NotifyMouseOut(WidgetMouseEvent* aMouseEvent,
5565 nsIContent* aMovingInto) {
5566 const bool isPointer = aMouseEvent->mClass == ePointerEventClass;
20
Assuming field 'mClass' is not equal to ePointerEventClass
39
Assuming field 'mClass' is not equal to ePointerEventClass
5567 LogModule* const logModule =
5568 isPointer
20.1
'isPointer' is false
39.1
'isPointer' is false
? sPointerBoundaryLog : sMouseBoundaryLog;
21
'?' condition is false
40
'?' condition is false
5569
5570 RefPtr<OverOutElementsWrapper> wrapper = GetWrapperByEventID(aMouseEvent);
5571
5572 // If there is no deepest "leave" event target, that means the last "over"
5573 // target has already been removed from the tree. Therefore, checking only
5574 // the "leave" event target is enough.
5575 if (!wrapper || !wrapper->GetDeepestLeaveEventTarget()) {
22
Assuming the condition is false
23
Taking false branch
41
Assuming the condition is false
42
Taking false branch
5576 return;
5577 }
5578 // Before firing "out" and/or "leave" events, check for recursion
5579 if (wrapper->IsDispatchingOutEventOnLastOverEventTarget()) {
24
Taking false branch
43
Taking false branch
5580 return;
5581 }
5582
5583 MOZ_LOG(logModule, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "NotifyMouseOut: the source event is %s (IsReal()=%s)"
, ToChar(aMouseEvent->mMessage), aMouseEvent->IsReal() ?
"true" : "false"); } } while (0)
25
Assuming the condition is false
26
Taking true branch
27
'?' condition is false
28
Loop condition is false. Exiting loop
44
Assuming the condition is false
45
Taking true branch
46
'?' condition is false
47
Loop condition is false. Exiting loop
5584 ("NotifyMouseOut: the source event is %s (IsReal()=%s)",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "NotifyMouseOut: the source event is %s (IsReal()=%s)"
, ToChar(aMouseEvent->mMessage), aMouseEvent->IsReal() ?
"true" : "false"); } } while (0)
5585 ToChar(aMouseEvent->mMessage),do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "NotifyMouseOut: the source event is %s (IsReal()=%s)"
, ToChar(aMouseEvent->mMessage), aMouseEvent->IsReal() ?
"true" : "false"); } } while (0)
5586 aMouseEvent->IsReal() ? "true" : "false"))do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "NotifyMouseOut: the source event is %s (IsReal()=%s)"
, ToChar(aMouseEvent->mMessage), aMouseEvent->IsReal() ?
"true" : "false"); } } while (0)
;
5587
5588 // XXX If a content node is a container of remove content, it should be
5589 // replaced with them and its children should not be visible. Therefore,
5590 // if the deepest "enter" target is not the last "over" target, i.e., the
5591 // last "over" target has been removed from the DOM tree, it means that the
5592 // child/descendant was not replaced by remote content. So,
5593 // wrapper->GetOutEventTaget() may be enough here.
5594 if (RefPtr<nsFrameLoaderOwner> flo =
29
Taking true branch
48
Taking false branch
5595 do_QueryObject(wrapper->GetDeepestLeaveEventTarget())) {
5596 if (BrowsingContext* bc = flo->GetExtantBrowsingContext()) {
30
Assuming 'bc' is non-null
31
Taking true branch
5597 if (nsIDocShell* docshell = bc->GetDocShell()) {
32
Assuming 'docshell' is non-null
33
Taking true branch
5598 if (RefPtr<nsPresContext> presContext = docshell->GetPresContext()) {
34
Taking true branch
5599 EventStateManager* kidESM = presContext->EventStateManager();
5600 // Not moving into any element in this subdocument
5601 MOZ_LOG(logModule, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Notifying child EventStateManager (%p) of \"out\" "
"event...", kidESM); } } while (0)
35
Assuming the condition is false
36
Taking true branch
37
Loop condition is false. Exiting loop
5602 ("Notifying child EventStateManager (%p) of \"out\" "do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Notifying child EventStateManager (%p) of \"out\" "
"event...", kidESM); } } while (0)
5603 "event...",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Notifying child EventStateManager (%p) of \"out\" "
"event...", kidESM); } } while (0)
5604 kidESM))do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Notifying child EventStateManager (%p) of \"out\" "
"event...", kidESM); } } while (0)
;
5605 kidESM->NotifyMouseOut(aMouseEvent, nullptr);
38
Calling 'EventStateManager::NotifyMouseOut'
5606 }
5607 }
5608 }
5609 }
5610 // That could have caused DOM events which could wreak havoc. Reverify
5611 // things and be careful.
5612 if (!wrapper->GetDeepestLeaveEventTarget()) {
49
Taking false branch
5613 return;
5614 }
5615
5616 wrapper->WillDispatchOutAndOrLeaveEvent();
5617
5618 // Don't touch hover state if aMovingInto is non-null. Caller will update
5619 // hover state itself, and we have optimizations for hover switching between
5620 // two nearby elements both deep in the DOM tree that would be defeated by
5621 // switching the hover state to null here.
5622 if (!aMovingInto
49.1
'aMovingInto' is null
&& (!isPointer
49.2
'isPointer' is false
|| aMouseEvent->InputSourceSupportsHover())) {
5623 // Unset :hover
5624 SetContentState(nullptr, ElementState::HOVER);
5625 }
5626
5627 EnterLeaveDispatcher leaveDispatcher(
5628 this, wrapper->GetDeepestLeaveEventTarget(), aMovingInto, aMouseEvent,
5629 isPointer
49.3
'isPointer' is false
? ePointerLeave : eMouseLeave);
50
'?' condition is false
5630
5631 // "out" events hould be fired only when the deepest "leave" event target
5632 // is the last "over" event target.
5633 if (nsCOMPtr<nsIContent> outEventTarget = wrapper->GetOutEventTarget()) {
51
Taking true branch
5634 MOZ_LOG(logModule, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s event to %s (%p)", isPointer
? "ePointerOut" : "eMouseOut", outEventTarget ? ToString(*outEventTarget
).c_str() : "nullptr", outEventTarget.get()); } } while (0)
52
Assuming the condition is false
53
Taking true branch
54
'?' condition is false
55
'?' condition is true
56
Loop condition is false. Exiting loop
5635 ("Dispatching %s event to %s (%p)",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s event to %s (%p)", isPointer
? "ePointerOut" : "eMouseOut", outEventTarget ? ToString(*outEventTarget
).c_str() : "nullptr", outEventTarget.get()); } } while (0)
5636 isPointer ? "ePointerOut" : "eMouseOut",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s event to %s (%p)", isPointer
? "ePointerOut" : "eMouseOut", outEventTarget ? ToString(*outEventTarget
).c_str() : "nullptr", outEventTarget.get()); } } while (0)
5637 outEventTarget ? ToString(*outEventTarget).c_str() : "nullptr",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s event to %s (%p)", isPointer
? "ePointerOut" : "eMouseOut", outEventTarget ? ToString(*outEventTarget
).c_str() : "nullptr", outEventTarget.get()); } } while (0)
5638 outEventTarget.get()))do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s event to %s (%p)", isPointer
? "ePointerOut" : "eMouseOut", outEventTarget ? ToString(*outEventTarget
).c_str() : "nullptr", outEventTarget.get()); } } while (0)
;
5639 nsCOMPtr<nsIWidget> widget = DispatchMouseOrPointerBoundaryEvent(
58
Calling 'EventStateManager::DispatchMouseOrPointerBoundaryEvent'
5640 aMouseEvent, isPointer
56.1
'isPointer' is false
? ePointerOut : eMouseOut, outEventTarget,
57
'?' condition is false
5641 aMovingInto);
5642 }
5643
5644 MOZ_LOG(logModule, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s event to %s (%p) and its ancestors"
, isPointer ? "ePointerLeave" : "eMouseLeave", wrapper->GetDeepestLeaveEventTarget
() ? ToString(*wrapper->GetDeepestLeaveEventTarget()).c_str
() : "nullptr", wrapper->GetDeepestLeaveEventTarget()); } }
while (0)
5645 ("Dispatching %s event to %s (%p) and its ancestors",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s event to %s (%p) and its ancestors"
, isPointer ? "ePointerLeave" : "eMouseLeave", wrapper->GetDeepestLeaveEventTarget
() ? ToString(*wrapper->GetDeepestLeaveEventTarget()).c_str
() : "nullptr", wrapper->GetDeepestLeaveEventTarget()); } }
while (0)
5646 isPointer ? "ePointerLeave" : "eMouseLeave",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s event to %s (%p) and its ancestors"
, isPointer ? "ePointerLeave" : "eMouseLeave", wrapper->GetDeepestLeaveEventTarget
() ? ToString(*wrapper->GetDeepestLeaveEventTarget()).c_str
() : "nullptr", wrapper->GetDeepestLeaveEventTarget()); } }
while (0)
5647 wrapper->GetDeepestLeaveEventTarget()do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s event to %s (%p) and its ancestors"
, isPointer ? "ePointerLeave" : "eMouseLeave", wrapper->GetDeepestLeaveEventTarget
() ? ToString(*wrapper->GetDeepestLeaveEventTarget()).c_str
() : "nullptr", wrapper->GetDeepestLeaveEventTarget()); } }
while (0)
5648 ? ToString(*wrapper->GetDeepestLeaveEventTarget()).c_str()do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s event to %s (%p) and its ancestors"
, isPointer ? "ePointerLeave" : "eMouseLeave", wrapper->GetDeepestLeaveEventTarget
() ? ToString(*wrapper->GetDeepestLeaveEventTarget()).c_str
() : "nullptr", wrapper->GetDeepestLeaveEventTarget()); } }
while (0)
5649 : "nullptr",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s event to %s (%p) and its ancestors"
, isPointer ? "ePointerLeave" : "eMouseLeave", wrapper->GetDeepestLeaveEventTarget
() ? ToString(*wrapper->GetDeepestLeaveEventTarget()).c_str
() : "nullptr", wrapper->GetDeepestLeaveEventTarget()); } }
while (0)
5650 wrapper->GetDeepestLeaveEventTarget()))do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s event to %s (%p) and its ancestors"
, isPointer ? "ePointerLeave" : "eMouseLeave", wrapper->GetDeepestLeaveEventTarget
() ? ToString(*wrapper->GetDeepestLeaveEventTarget()).c_str
() : "nullptr", wrapper->GetDeepestLeaveEventTarget()); } }
while (0)
;
5651 leaveDispatcher.Dispatch();
5652
5653 MOZ_LOG(logModule, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatched \"out\" and/or \"leave\" events"
); } } while (0)
5654 ("Dispatched \"out\" and/or \"leave\" events"))do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatched \"out\" and/or \"leave\" events"
); } } while (0)
;
5655 wrapper->DidDispatchOutAndOrLeaveEvent();
5656}
5657
5658void EventStateManager::RecomputeMouseEnterStateForRemoteFrame(
5659 Element& aElement) {
5660 if (!mMouseEnterLeaveHelper ||
5661 mMouseEnterLeaveHelper->GetDeepestLeaveEventTarget() != &aElement) {
5662 return;
5663 }
5664
5665 if (BrowserParent* remote = BrowserParent::GetFrom(&aElement)) {
5666 remote->MouseEnterIntoWidget();
5667 }
5668}
5669
5670void EventStateManager::NotifyMouseOver(WidgetMouseEvent* aMouseEvent,
5671 nsIContent* aContent) {
5672 NS_ASSERTION(aContent, "Mouse must be over something")do { if (!(aContent)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Mouse must be over something"
, "aContent", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 5672); MOZ_PretendNoReturn(); } } while (0)
;
5673
5674 const bool isPointer = aMouseEvent->mClass == ePointerEventClass;
5675 LogModule* const logModule =
5676 isPointer ? sPointerBoundaryLog : sMouseBoundaryLog;
5677
5678 RefPtr<OverOutElementsWrapper> wrapper = GetWrapperByEventID(aMouseEvent);
5679
5680 // If we have next "out" event target and it's the new "over" target, we don't
5681 // need to dispatch "out" nor "enter" event.
5682 if (!wrapper || aContent == wrapper->GetOutEventTarget()) {
5683 return;
5684 }
5685
5686 // Before firing "over" and "enter" events, check for recursion
5687 if (wrapper->IsDispatchingOverEventOn(aContent)) {
5688 return;
5689 }
5690
5691 MOZ_LOG(logModule, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "NotifyMouseOver: the source event is %s (IsReal()=%s)"
, ToChar(aMouseEvent->mMessage), aMouseEvent->IsReal() ?
"true" : "false"); } } while (0)
5692 ("NotifyMouseOver: the source event is %s (IsReal()=%s)",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "NotifyMouseOver: the source event is %s (IsReal()=%s)"
, ToChar(aMouseEvent->mMessage), aMouseEvent->IsReal() ?
"true" : "false"); } } while (0)
5693 ToChar(aMouseEvent->mMessage),do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "NotifyMouseOver: the source event is %s (IsReal()=%s)"
, ToChar(aMouseEvent->mMessage), aMouseEvent->IsReal() ?
"true" : "false"); } } while (0)
5694 aMouseEvent->IsReal() ? "true" : "false"))do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "NotifyMouseOver: the source event is %s (IsReal()=%s)"
, ToChar(aMouseEvent->mMessage), aMouseEvent->IsReal() ?
"true" : "false"); } } while (0)
;
5695
5696 // Check to see if we're a subdocument and if so update the parent
5697 // document's ESM state to indicate that the mouse is over the
5698 // content associated with our subdocument.
5699 EnsureDocument(mPresContext);
5700 if (Document* parentDoc = mDocument->GetInProcessParentDocument()) {
5701 if (nsCOMPtr<nsIContent> docContent = mDocument->GetEmbedderElement()) {
5702 if (PresShell* parentPresShell = parentDoc->GetPresShell()) {
5703 RefPtr<EventStateManager> parentESM =
5704 parentPresShell->GetPresContext()->EventStateManager();
5705 MOZ_LOG(logModule, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Notifying parent EventStateManager (%p) of \"over\" "
"event...", parentESM.get()); } } while (0)
5706 ("Notifying parent EventStateManager (%p) of \"over\" "do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Notifying parent EventStateManager (%p) of \"over\" "
"event...", parentESM.get()); } } while (0)
5707 "event...",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Notifying parent EventStateManager (%p) of \"over\" "
"event...", parentESM.get()); } } while (0)
5708 parentESM.get()))do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Notifying parent EventStateManager (%p) of \"over\" "
"event...", parentESM.get()); } } while (0)
;
5709 parentESM->NotifyMouseOver(aMouseEvent, docContent);
5710 }
5711 }
5712 }
5713 // Firing the DOM event in the parent document could cause all kinds
5714 // of havoc. Reverify and take care.
5715 if (aContent == wrapper->GetOutEventTarget()) {
5716 return;
5717 }
5718
5719 // Remember the deepest leave event target as the related content for the
5720 // DispatchMouseOrPointerBoundaryEvent() call below, since NotifyMouseOut()
5721 // resets it, bug 298477.
5722 nsCOMPtr<nsIContent> deepestLeaveEventTarget =
5723 wrapper->GetDeepestLeaveEventTarget();
5724
5725 EnterLeaveDispatcher enterDispatcher(this, aContent, deepestLeaveEventTarget,
5726 aMouseEvent,
5727 isPointer ? ePointerEnter : eMouseEnter);
5728
5729 if (!isPointer || aMouseEvent->InputSourceSupportsHover()) {
5730 SetContentState(aContent, ElementState::HOVER);
5731 }
5732
5733 NotifyMouseOut(aMouseEvent, aContent);
5734
5735 wrapper->WillDispatchOverAndEnterEvent(aContent);
5736
5737 // Fire mouseover
5738 // XXX If aContent has already been removed from the DOM tree, what should we
5739 // do? At least, dispatching `mouseover` on it is odd.
5740 MOZ_LOG(logModule, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s event to %s (%p)", isPointer
? "ePointerOver" : "eMouseOver", aContent ? ToString(*aContent
).c_str() : "nullptr", aContent); } } while (0)
5741 ("Dispatching %s event to %s (%p)",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s event to %s (%p)", isPointer
? "ePointerOver" : "eMouseOver", aContent ? ToString(*aContent
).c_str() : "nullptr", aContent); } } while (0)
5742 isPointer ? "ePointerOver" : "eMouseOver",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s event to %s (%p)", isPointer
? "ePointerOver" : "eMouseOver", aContent ? ToString(*aContent
).c_str() : "nullptr", aContent); } } while (0)
5743 aContent ? ToString(*aContent).c_str() : "nullptr", aContent))do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s event to %s (%p)", isPointer
? "ePointerOver" : "eMouseOver", aContent ? ToString(*aContent
).c_str() : "nullptr", aContent); } } while (0)
;
5744 nsCOMPtr<nsIWidget> targetWidget = DispatchMouseOrPointerBoundaryEvent(
5745 aMouseEvent, isPointer ? ePointerOver : eMouseOver, aContent,
5746 deepestLeaveEventTarget);
5747
5748 MOZ_LOG(logModule, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s event to %s (%p) and its ancestors"
, isPointer ? "ePointerEnter" : "eMouseEnter", aContent ? ToString
(*aContent).c_str() : "nullptr", aContent); } } while (0)
5749 ("Dispatching %s event to %s (%p) and its ancestors",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s event to %s (%p) and its ancestors"
, isPointer ? "ePointerEnter" : "eMouseEnter", aContent ? ToString
(*aContent).c_str() : "nullptr", aContent); } } while (0)
5750 isPointer ? "ePointerEnter" : "eMouseEnter",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s event to %s (%p) and its ancestors"
, isPointer ? "ePointerEnter" : "eMouseEnter", aContent ? ToString
(*aContent).c_str() : "nullptr", aContent); } } while (0)
5751 aContent ? ToString(*aContent).c_str() : "nullptr", aContent))do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s event to %s (%p) and its ancestors"
, isPointer ? "ePointerEnter" : "eMouseEnter", aContent ? ToString
(*aContent).c_str() : "nullptr", aContent); } } while (0)
;
5752 enterDispatcher.Dispatch();
5753
5754 MOZ_LOG(logModule, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatched \"over\" and \"enter\" events (the original \"over\" "
"event target was in the document %p, and now in %p)", aContent
->GetComposedDoc(), mDocument.get()); } } while (0)
5755 ("Dispatched \"over\" and \"enter\" events (the original \"over\" "do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatched \"over\" and \"enter\" events (the original \"over\" "
"event target was in the document %p, and now in %p)", aContent
->GetComposedDoc(), mDocument.get()); } } while (0)
5756 "event target was in the document %p, and now in %p)",do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatched \"over\" and \"enter\" events (the original \"over\" "
"event target was in the document %p, and now in %p)", aContent
->GetComposedDoc(), mDocument.get()); } } while (0)
5757 aContent->GetComposedDoc(), mDocument.get()))do { const ::mozilla::LogModule* moz_real_module = logModule;
if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatched \"over\" and \"enter\" events (the original \"over\" "
"event target was in the document %p, and now in %p)", aContent
->GetComposedDoc(), mDocument.get()); } } while (0)
;
5758 wrapper->DidDispatchOverAndEnterEvent(
5759 aContent->GetComposedDoc() == mDocument ? aContent : nullptr,
5760 targetWidget);
5761}
5762
5763// Returns the size and also the center point of the window's client area. The
5764// center point is in widget coordinates, i.e. relative to the widget's top-left
5765// corner, not in screen coordinates, the same units that UIEvent:: refpoint is
5766// in. It may not be the exact center of the window if the platform requires
5767// rounding the coordinate.
5768static std::pair<LayoutDeviceIntSize, LayoutDeviceIntPoint>
5769GetWindowClientSizeAndCenterPoint(nsIWidget* aWidget) {
5770 MOZ_ASSERT(aWidget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aWidget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aWidget))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aWidget", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 5770); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWidget" ")"
); do { MOZ_CrashSequence(__null, 5770); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5771
5772 LayoutDeviceIntSize size = aWidget->GetClientSize();
5773 LayoutDeviceIntPoint point(size.width / 2, size.height / 2);
5774 int32_t round = aWidget->RoundsWidgetCoordinatesTo();
5775 point.x = point.x / round * round;
5776 point.y = point.y / round * round;
5777 return std::pair{size, point};
5778}
5779
5780void EventStateManager::GeneratePointerEnterExit(EventMessage aMessage,
5781 WidgetMouseEvent* aEvent) {
5782 WidgetPointerEvent pointerEvent =
5783 WidgetPointerEvent::MakeCopyFromMouseEvent(*aEvent);
5784 pointerEvent.mMessage = aMessage;
5785 GenerateMouseEnterExit(&pointerEvent);
5786}
5787
5788/* static */
5789void EventStateManager::UpdateLastRefPointOfMouseEvent(
5790 WidgetMouseEvent* aMouseEvent) {
5791 if (aMouseEvent->mMessage != ePointerRawUpdate &&
5792 aMouseEvent->mMessage != eMouseMove &&
5793 aMouseEvent->mMessage != ePointerMove) {
5794 return;
5795 }
5796
5797 const LayoutDeviceIntPoint& lastRefPoint =
5798 aMouseEvent->mMessage == ePointerRawUpdate ? sLastRefPointOfRawUpdate
5799 : sLastRefPoint;
5800
5801 // Mouse movement is reported on the MouseEvent.movement{X,Y} fields.
5802 // Movement is calculated in UIEvent::GetMovementPoint() as:
5803 // previous_mousemove_mRefPoint - current_mousemove_mRefPoint.
5804 if (lastRefPoint == kInvalidRefPoint) {
5805 // We don't have a valid previous mousemove mRefPoint. This is either
5806 // the first move we've encountered, or the mouse has just re-entered
5807 // the application window. We should report (0,0) movement for this
5808 // case, so make the current and previous mRefPoints the same.
5809 aMouseEvent->mLastRefPoint = aMouseEvent->mRefPoint;
5810 } else {
5811 aMouseEvent->mLastRefPoint = lastRefPoint;
5812 }
5813
5814 if (auto coalescedEvents = aMouseEvent->mCoalescedWidgetEvents) {
5815 // Fix up mLastRefPoints of coalesced events, so that each one's
5816 // movementX/Y is relative to the last.
5817 WidgetPointerEvent* prev = nullptr;
5818 for (WidgetPointerEvent& coalesced : coalescedEvents->mEvents) {
5819 coalesced.mLastRefPoint =
5820 prev ? prev->mRefPoint : aMouseEvent->mLastRefPoint;
5821 prev = &coalesced;
5822 }
5823 }
5824}
5825
5826/* static */
5827void EventStateManager::RequestLockPointer(nsIWidget* aWidget,
5828 nsPresContext* aPresContext,
5829 bool aUnadjustedMovement) {
5830 MOZ_ASSERT(aWidget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aWidget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aWidget))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aWidget", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 5830); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWidget" ")"
); do { MOZ_CrashSequence(__null, 5830); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5831 MOZ_ASSERT(aPresContext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPresContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPresContext))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aPresContext", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 5831); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresContext"
")"); do { MOZ_CrashSequence(__null, 5831); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5832
5833 if (!PointerLockManager::ShouldResetPointer()) {
5834 return;
5835 }
5836
5837 // Resetting pointer should only happen in the parent process.
5838 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 5838
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 5838); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5839 MOZ_ASSERT(sPreLockScreenPoint == kInvalidRefPoint)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sPreLockScreenPoint == kInvalidRefPoint)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(sPreLockScreenPoint == kInvalidRefPoint))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("sPreLockScreenPoint == kInvalidRefPoint"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 5839
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sPreLockScreenPoint == kInvalidRefPoint"
")"); do { MOZ_CrashSequence(__null, 5839); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5840 MOZ_ASSERT(sSynthCenteringPoint == kInvalidRefPoint)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sSynthCenteringPoint == kInvalidRefPoint)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(sSynthCenteringPoint == kInvalidRefPoint))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("sSynthCenteringPoint == kInvalidRefPoint"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 5840
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sSynthCenteringPoint == kInvalidRefPoint"
")"); do { MOZ_CrashSequence(__null, 5840); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5841
5842 // Activate native pointer lock on platforms where it is required.
5843 aWidget->LockNativePointer(aUnadjustedMovement
5844 ? nsIWidget::NativePointerLockMode::Unadjusted
5845 : nsIWidget::NativePointerLockMode::Regular);
5846
5847 // Store the last known ref point so we can reposition the pointer after
5848 // unlock. Don't reposition it if we've only seen synthesized events.
5849 sRestorePointerAfterUnlock = sLastRealScreenPoint.isSome();
5850 sPreLockScreenPoint = LayoutDeviceIntPoint::Round(
5851 sLastRealScreenPoint.valueOr(sLastScreenPoint) *
5852 aPresContext->CSSToDevPixelScale());
5853
5854 // Fire a synthetic mouse move to ensure event state is updated. We first
5855 // set the mouse to the center of the window, so that the mouse event
5856 // doesn't report any movement.
5857 sLastRefPoint = sLastRefPointOfRawUpdate =
5858 GetWindowClientSizeAndCenterPoint(aWidget).second;
5859 sSynthCenteringPoint = sLastRefPoint;
5860
5861 aWidget->SynthesizeNativeMouseMove(
5862 sLastRefPoint + aWidget->WidgetToScreenOffset(), nullptr);
5863}
5864
5865/* static */
5866void EventStateManager::ResetPointerToWindowCenterWhilePointerLocked(
5867 WidgetMouseEvent* aMouseEvent) {
5868 MOZ_ASSERT(aMouseEvent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMouseEvent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMouseEvent))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aMouseEvent", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 5868); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseEvent"
")"); do { MOZ_CrashSequence(__null, 5868); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5869
5870 if (!PointerLockManager::ShouldResetPointer()) {
5871 return;
5872 }
5873
5874 // Pointer repositioning should be triggered from the parent process.
5875 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 5875
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 5875); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5876
5877 if ((aMouseEvent->mMessage != ePointerRawUpdate &&
5878 aMouseEvent->mMessage != eMouseMove &&
5879 aMouseEvent->mMessage != ePointerMove) ||
5880 !aMouseEvent->mWidget || !aMouseEvent->IsReal()) {
5881 return;
5882 }
5883
5884 // We generate pointermove from mousemove event, so only synthesize native
5885 // mouse move and update sSynthCenteringPoint by mousemove event.
5886 const bool updateSynthCenteringPoint = aMouseEvent->mMessage == eMouseMove;
5887 const auto recenteringPoint = [&]() -> Maybe<LayoutDeviceIntPoint> {
5888 if (!updateSynthCenteringPoint) {
5889 return Nothing();
5890 }
5891
5892 auto [size, center] =
5893 GetWindowClientSizeAndCenterPoint(aMouseEvent->mWidget);
5894
5895 // The pointer cannot be move outside the browser window boundary, as each
5896 // platform now use a native API to "lock" the pointer Therefore, we do not
5897 // need to reposition it to the center on every mousemove event. However, we
5898 // still need to recenter it once it moves too close to the boundary;
5899 // otherwise, the pointer may become stuck at the boundary and no longer be
5900 // able to move in certain directions. The boundary buffer is currently
5901 // 25% of the window size.
5902 LayoutDeviceIntRect rect(size.Width() / 4, size.Height() / 4,
5903 size.Width() / 2, size.Height() / 2);
5904 if (!rect.Contains(aMouseEvent->mRefPoint)) {
5905 return Some(center);
5906 }
5907 return Nothing();
5908 }();
5909
5910 // The pointer is locked. If the pointer is not located at the center of
5911 // the window, dispatch a synthetic mousemove to return the pointer there.
5912 // Doing this between "real" pointer moves gives the impression that the
5913 // (locked) pointer can continue moving and won't stop at the screen
5914 // boundary. We cancel the synthetic event so that we don't end up
5915 // dispatching the centering move event to content.
5916 if (recenteringPoint) {
5917 // Mouse move doesn't finish at the center of the window. Dispatch a
5918 // synthetic native mouse event to move the pointer back to the center
5919 // of the window, to faciliate more movement. But first, record that
5920 // we've dispatched a synthetic mouse movement, so we can cancel it
5921 // in the other branch here.
5922 sSynthCenteringPoint = *recenteringPoint;
5923
5924 // XXX Once we fix XXX comments in SetPointerLock about this API, we could
5925 // restrict that this API works only in the automation mode or in the
5926 // pointer locked situation.
5927 aMouseEvent->mWidget->SynthesizeNativeMouseMove(
5928 sSynthCenteringPoint + aMouseEvent->mWidget->WidgetToScreenOffset(),
5929 nullptr);
5930 return;
5931 }
5932
5933 // The synthesized re-centering event might be coalesced with subsequent
5934 // events at the OS level, so the event's ref point might not exactly match
5935 // sSynthCenteringPoint here.
5936 if (sSynthCenteringPoint != kInvalidRefPoint) {
5937 // If the synthesized re-centering even is coalesced, we need to report the
5938 // corresponding movement if the OS does not provide movement data. The
5939 // synthesized re-centering event is also very important for content process
5940 // to update its last ref point, so it should not be compressed or
5941 // coalesced, setting movement data can also prevent it from being
5942 // compressed or coalesced.
5943 if (!aMouseEvent->mMovement) {
5944 aMouseEvent->mMovement.emplace(aMouseEvent->mRefPoint -
5945 sSynthCenteringPoint);
5946 }
5947
5948 // This is the "synthetic native" event we dispatched to re-center the
5949 // pointer. We don't expose it to content. We also want to propagate this
5950 // state to the content process, so we do not use `StopPropagation()`, since
5951 // that state is reset for each event group.
5952 if (*aMouseEvent->mMovement == LayoutDeviceIntPoint(0, 0)) {
5953 aMouseEvent->mFlags.mOnlySystemGroupDispatch = true;
5954 }
5955
5956 // Clear sSynthCenteringPoint so subsequent events are handled normally.
5957 if (updateSynthCenteringPoint) {
5958 sSynthCenteringPoint = kInvalidRefPoint;
5959 }
5960 }
5961}
5962
5963/* static */
5964void EventStateManager::ReleaseLockedPointer(nsIWidget* aWidget) {
5965 if (sPreLockScreenPoint == kInvalidRefPoint) {
5966 MOZ_ASSERT(sSynthCenteringPoint == kInvalidRefPoint)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sSynthCenteringPoint == kInvalidRefPoint)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(sSynthCenteringPoint == kInvalidRefPoint))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("sSynthCenteringPoint == kInvalidRefPoint"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 5966
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sSynthCenteringPoint == kInvalidRefPoint"
")"); do { MOZ_CrashSequence(__null, 5966); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5967 return;
5968 }
5969
5970 // Resetting pointer should only happen in the parent process.
5971 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 5971
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 5971); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5972
5973 // Reset sSynthCenteringPoint to invalid so that next time we start
5974 // locking pointer, it has its initial value.
5975 sSynthCenteringPoint = kInvalidRefPoint;
5976
5977 LayoutDeviceIntPoint preLockScreenPoint = sPreLockScreenPoint;
5978 sPreLockScreenPoint = kInvalidRefPoint;
5979 const bool restorePointer = sRestorePointerAfterUnlock;
5980 sRestorePointerAfterUnlock = false;
5981
5982 if (aWidget) {
5983 // Deactivate native pointer lock on platforms where it is required
5984 aWidget->UnlockNativePointer();
5985
5986 if (!restorePointer) {
5987 return;
5988 }
5989
5990 // Unlocking, so return pointer to the original position by firing a
5991 // synthetic mouse event. We first reset sLastRefPoint and
5992 // sLastRefPointOfRawUpdate to its pre-pointerlock position, so that the
5993 // synthetic mouse event reports no movement.
5994 sLastRefPoint = sLastRefPointOfRawUpdate =
5995 preLockScreenPoint - aWidget->WidgetToScreenOffset();
5996
5997 aWidget->SynthesizeNativeMouseMove(preLockScreenPoint, nullptr);
5998 }
5999}
6000
6001/* static */
6002void EventStateManager::UpdateLastPointerPosition(
6003 WidgetMouseEvent* aMouseEvent) {
6004 if (aMouseEvent->IsSynthesized()) {
6005 return;
6006 }
6007 if (aMouseEvent->mMessage == eMouseMove) {
6008 sLastRefPoint = aMouseEvent->mRefPoint;
6009 } else if (aMouseEvent->mMessage == ePointerRawUpdate ||
6010 // FYI: ePointerRawUpdate is handled only when there are some
6011 // `pointerrawupdate` event listeners. Therefore, we need to
6012 // update the last ref point for ePointerRawUpdate when we dispatch
6013 // ePointerMove too since the first `pointerrawupdate` event
6014 // listener may be added after the ePointerMove.
6015 aMouseEvent->mMessage == ePointerMove) {
6016 // XXX Shouldn't we store last refpoint of PointerEvent per pointerId?
6017 sLastRefPointOfRawUpdate = aMouseEvent->mRefPoint;
6018 }
6019}
6020
6021void EventStateManager::GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent) {
6022 EnsureDocument(mPresContext);
6023 if (!mDocument) return;
16
Taking false branch
6024
6025 // Hold onto old target content through the event and reset after.
6026 nsCOMPtr<nsIContent> targetBeforeEvent = mCurrentTargetContent;
6027
6028 switch (aMouseEvent->mMessage) {
17
Control jumps to 'case eMouseExitFromWidget:' at line 6085
6029 case eMouseMove:
6030 case ePointerMove:
6031 case ePointerRawUpdate:
6032 case ePointerDown:
6033 case ePointerGotCapture: {
6034 // Get the target content target (mousemove target == mouseover target)
6035 nsCOMPtr<nsIContent> targetElement =
6036 GetExplicitEventTargetContent(aMouseEvent);
6037 if (!targetElement) {
6038 // We're always over the document root, even if we're only
6039 // over dead space in a page (whose frame is not associated with
6040 // any content) or in print preview dead space
6041 targetElement = mDocument->GetRootElement();
6042 }
6043 if (targetElement) {
6044 NotifyMouseOver(aMouseEvent, targetElement);
6045 }
6046 break;
6047 }
6048 case ePointerUp: {
6049 if (aMouseEvent->mFlags.mDispatchedAtLeastOnce) {
6050 // If we've already dispatched the pointerup event caused by
6051 // non-hoverable input device like touch, we need to synthesize
6052 // pointerout and pointerleave events because the poiner is valid only
6053 // while it's "down".
6054 if (!aMouseEvent->InputSourceSupportsHover()) {
6055 NotifyMouseOut(aMouseEvent, nullptr);
6056 }
6057 break;
6058 }
6059
6060 // If we're going to dispatch the pointerup event and the element under
6061 // the pointer is changed from the previous pointer event dispatching, we
6062 // need to dispatch pointer boundary events. If the pointing device is
6063 // hoverable, we always need to do it. Otherwise, an element captures the
6064 // pointer by default. If so, we don't need the boundary events, but if
6065 // the capture has already been released, e.g., by the capturing element
6066 // is removed, we need to dispatch the pointer boundary event the same
6067 // way as with hoverable pointer.
6068 if (aMouseEvent->InputSourceSupportsHover() ||
6069 !PointerEventHandler::GetPointerCapturingElement(
6070 aMouseEvent->pointerId)) {
6071 nsCOMPtr<nsIContent> targetElement =
6072 GetExplicitEventTargetContent(aMouseEvent);
6073 if (!targetElement) {
6074 targetElement = mDocument->GetRootElement();
6075 }
6076 if (targetElement) {
6077 NotifyMouseOver(aMouseEvent, targetElement);
6078 }
6079 break;
6080 }
6081 break;
6082 }
6083 case ePointerLeave:
6084 case ePointerCancel:
6085 case eMouseExitFromWidget: {
6086 // This is actually the window mouse exit or pointer leave event. We're
6087 // not moving into any new element.
6088
6089 RefPtr<OverOutElementsWrapper> helper = GetWrapperByEventID(aMouseEvent);
6090 if (helper) {
18
Taking false branch
6091 nsCOMPtr<nsIWidget> lastOverWidget = helper->GetLastOverWidget();
6092 if (lastOverWidget &&
6093 nsContentUtils::GetTopLevelWidget(aMouseEvent->mWidget) !=
6094 nsContentUtils::GetTopLevelWidget(lastOverWidget)) {
6095 // the Mouse/PointerOut event widget doesn't have same top widget with
6096 // the last over event target, it's a spurious event for the frame for
6097 // the target.
6098 break;
6099 }
6100 }
6101
6102 // Reset sLastRefPoint and sLastRefPointOfRawUpdate, so that we'll know
6103 // not to report any movement the next time we re-enter the window.
6104 sLastRefPoint = sLastRefPointOfRawUpdate = kInvalidRefPoint;
6105
6106 NotifyMouseOut(aMouseEvent, nullptr);
19
Calling 'EventStateManager::NotifyMouseOut'
6107 break;
6108 }
6109 default:
6110 break;
6111 }
6112
6113 // reset mCurretTargetContent to what it was
6114 mCurrentTargetContent = std::move(targetBeforeEvent);
6115}
6116
6117OverOutElementsWrapper* EventStateManager::GetWrapperByEventID(
6118 WidgetMouseEvent* aMouseEvent) {
6119 MOZ_ASSERT(aMouseEvent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMouseEvent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMouseEvent))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aMouseEvent", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6119); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseEvent"
")"); do { MOZ_CrashSequence(__null, 6119); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6120 WidgetPointerEvent* pointer = aMouseEvent->AsPointerEvent();
6121 if (!pointer) {
6122 if (!mMouseEnterLeaveHelper) {
6123 mMouseEnterLeaveHelper = new OverOutElementsWrapper(
6124 OverOutElementsWrapper::BoundaryEventType::Mouse);
6125 }
6126 return mMouseEnterLeaveHelper;
6127 }
6128 return mPointersEnterLeaveHelper.GetOrInsertNew(
6129 pointer->pointerId, OverOutElementsWrapper::BoundaryEventType::Pointer);
6130}
6131
6132/* static */
6133void EventStateManager::SetPointerLock(nsIWidget* aWidget,
6134 nsPresContext* aPresContext,
6135 bool aUnadjustedMovement) {
6136 // Reset mouse wheel transaction
6137 WheelTransaction::EndTransaction();
6138
6139 // Deal with DnD events
6140 nsCOMPtr<nsIDragService> dragService =
6141 do_GetService("@mozilla.org/widget/dragservice;1");
6142
6143 if (PointerLockManager::IsLocked()) {
6144 MOZ_ASSERT(aWidget, "Locking pointer requires a widget")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aWidget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aWidget))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aWidget" " (" "Locking pointer requires a widget"
")", "/root/firefox-clang/dom/events/EventStateManager.cpp",
6144); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWidget" ") ("
"Locking pointer requires a widget" ")"); do { MOZ_CrashSequence
(__null, 6144); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6145 MOZ_ASSERT(aPresContext, "Locking pointer requires a presContext")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPresContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPresContext))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aPresContext" " ("
"Locking pointer requires a presContext" ")", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6145); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresContext"
") (" "Locking pointer requires a presContext" ")"); do { MOZ_CrashSequence
(__null, 6145); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6146
6147 // Release all pointer capture when a pointer lock is successfully applied
6148 // on an element.
6149 PointerEventHandler::ReleaseAllPointerCapture();
6150
6151 // Suppress DnD
6152 if (dragService) {
6153 dragService->Suppress();
6154 }
6155
6156 RequestLockPointer(aWidget, aPresContext, aUnadjustedMovement);
6157 } else {
6158 ReleaseLockedPointer(aWidget);
6159
6160 // Unsuppress DnD
6161 if (dragService) {
6162 dragService->Unsuppress();
6163 }
6164 }
6165}
6166
6167void EventStateManager::GenerateDragDropEnterExit(nsPresContext* aPresContext,
6168 WidgetDragEvent& aDragEvent) {
6169 // Hold onto old target content through the event and reset after.
6170 nsCOMPtr<nsIContent> targetBeforeEvent = mCurrentTargetContent;
6171
6172 switch (aDragEvent.mMessage) {
6173 case eDragOver: {
6174 // when dragging from one frame to another, events are fired in the
6175 // order: dragexit, dragenter, dragleave
6176 if (sLastDragOverFrame != mCurrentTarget) {
6177 // We'll need the content, too, to check if it changed separately from
6178 // the frames.
6179 nsCOMPtr<nsIContent> lastContent;
6180 MOZ_ASSERT(IsForbiddenDispatchingToNonElementContent(eDragExit) ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsForbiddenDispatchingToNonElementContent(eDragExit)
== IsForbiddenDispatchingToNonElementContent(eDragOver))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsForbiddenDispatchingToNonElementContent(eDragExit)
== IsForbiddenDispatchingToNonElementContent(eDragOver)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("IsForbiddenDispatchingToNonElementContent(eDragExit) == IsForbiddenDispatchingToNonElementContent(eDragOver)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6181
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsForbiddenDispatchingToNonElementContent(eDragExit) == IsForbiddenDispatchingToNonElementContent(eDragOver)"
")"); do { MOZ_CrashSequence(__null, 6181); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6181 IsForbiddenDispatchingToNonElementContent(eDragOver))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsForbiddenDispatchingToNonElementContent(eDragExit)
== IsForbiddenDispatchingToNonElementContent(eDragOver))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsForbiddenDispatchingToNonElementContent(eDragExit)
== IsForbiddenDispatchingToNonElementContent(eDragOver)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("IsForbiddenDispatchingToNonElementContent(eDragExit) == IsForbiddenDispatchingToNonElementContent(eDragOver)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6181
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsForbiddenDispatchingToNonElementContent(eDragExit) == IsForbiddenDispatchingToNonElementContent(eDragOver)"
")"); do { MOZ_CrashSequence(__null, 6181); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6182 MOZ_ASSERT(IsForbiddenDispatchingToNonElementContent(eDragEnter) ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsForbiddenDispatchingToNonElementContent(eDragEnter
) == IsForbiddenDispatchingToNonElementContent(eDragOver))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsForbiddenDispatchingToNonElementContent(eDragEnter
) == IsForbiddenDispatchingToNonElementContent(eDragOver)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("IsForbiddenDispatchingToNonElementContent(eDragEnter) == IsForbiddenDispatchingToNonElementContent(eDragOver)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6183
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsForbiddenDispatchingToNonElementContent(eDragEnter) == IsForbiddenDispatchingToNonElementContent(eDragOver)"
")"); do { MOZ_CrashSequence(__null, 6183); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6183 IsForbiddenDispatchingToNonElementContent(eDragOver))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsForbiddenDispatchingToNonElementContent(eDragEnter
) == IsForbiddenDispatchingToNonElementContent(eDragOver))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsForbiddenDispatchingToNonElementContent(eDragEnter
) == IsForbiddenDispatchingToNonElementContent(eDragOver)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("IsForbiddenDispatchingToNonElementContent(eDragEnter) == IsForbiddenDispatchingToNonElementContent(eDragOver)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6183
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsForbiddenDispatchingToNonElementContent(eDragEnter) == IsForbiddenDispatchingToNonElementContent(eDragOver)"
")"); do { MOZ_CrashSequence(__null, 6183); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6184 MOZ_ASSERT(IsForbiddenDispatchingToNonElementContent(eDragLeave) ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsForbiddenDispatchingToNonElementContent(eDragLeave
) == IsForbiddenDispatchingToNonElementContent(eDragOver))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsForbiddenDispatchingToNonElementContent(eDragLeave
) == IsForbiddenDispatchingToNonElementContent(eDragOver)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("IsForbiddenDispatchingToNonElementContent(eDragLeave) == IsForbiddenDispatchingToNonElementContent(eDragOver)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6185
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsForbiddenDispatchingToNonElementContent(eDragLeave) == IsForbiddenDispatchingToNonElementContent(eDragOver)"
")"); do { MOZ_CrashSequence(__null, 6185); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6185 IsForbiddenDispatchingToNonElementContent(eDragOver))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsForbiddenDispatchingToNonElementContent(eDragLeave
) == IsForbiddenDispatchingToNonElementContent(eDragOver))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsForbiddenDispatchingToNonElementContent(eDragLeave
) == IsForbiddenDispatchingToNonElementContent(eDragOver)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("IsForbiddenDispatchingToNonElementContent(eDragLeave) == IsForbiddenDispatchingToNonElementContent(eDragOver)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6185
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsForbiddenDispatchingToNonElementContent(eDragLeave) == IsForbiddenDispatchingToNonElementContent(eDragOver)"
")"); do { MOZ_CrashSequence(__null, 6185); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6186 nsCOMPtr<nsIContent> targetContent =
6187 mCurrentTarget->GetEventTargetContent(aDragEvent);
6188 if (sLastDragOverFrame) {
6189 // The frame has changed but the content may not have. Check before
6190 // dispatching to content
6191 lastContent = sLastDragOverFrame->GetEventTargetContent(aDragEvent);
6192 RefPtr<nsPresContext> presContext = sLastDragOverFrame->PresContext();
6193 FireDragEnterOrExit(presContext, aDragEvent, eDragExit, targetContent,
6194 lastContent, sLastDragOverFrame);
6195 nsIContent* target = sLastDragOverFrame
6196 ? sLastDragOverFrame.GetFrame()->GetContent()
6197 : nullptr;
6198 // XXXedgar, look like we need to consider fission OOP iframe, too.
6199 if (IsTopLevelRemoteTarget(target)) {
6200 // Dragging something and moving from web content to chrome only
6201 // fires dragexit and dragleave to xul:browser. We have to forward
6202 // dragexit to sLastDragOverFrame when its content is a remote
6203 // target. We don't forward dragleave since it's generated from
6204 // dragexit.
6205 WidgetDragEvent remoteEvent(aDragEvent.IsTrusted(), eDragExit,
6206 aDragEvent.mWidget);
6207 remoteEvent.AssignDragEventData(aDragEvent, true);
6208 remoteEvent.mFlags.mIsSynthesizedForTests =
6209 aDragEvent.mFlags.mIsSynthesizedForTests;
6210 nsEventStatus remoteStatus = nsEventStatus_eIgnore;
6211 HandleCrossProcessEvent(&remoteEvent, &remoteStatus);
6212 }
6213 }
6214
6215 AutoWeakFrame currentTraget = mCurrentTarget;
6216 FireDragEnterOrExit(aPresContext, aDragEvent, eDragEnter, lastContent,
6217 targetContent, currentTraget);
6218
6219 if (sLastDragOverFrame) {
6220 RefPtr<nsPresContext> presContext = sLastDragOverFrame->PresContext();
6221 FireDragEnterOrExit(presContext, aDragEvent, eDragLeave,
6222 targetContent, lastContent, sLastDragOverFrame);
6223 }
6224
6225 sLastDragOverFrame = mCurrentTarget;
6226 }
6227 } break;
6228
6229 case eDragExit: {
6230 // This is actually the window mouse exit event.
6231 if (sLastDragOverFrame) {
6232 nsCOMPtr<nsIContent> lastContent =
6233 sLastDragOverFrame->GetEventTargetContent(aDragEvent);
6234 RefPtr<nsPresContext> lastDragOverFramePresContext =
6235 sLastDragOverFrame->PresContext();
6236 FireDragEnterOrExit(lastDragOverFramePresContext, aDragEvent, eDragExit,
6237 nullptr, lastContent, sLastDragOverFrame);
6238 FireDragEnterOrExit(lastDragOverFramePresContext, aDragEvent,
6239 eDragLeave, nullptr, lastContent,
6240 sLastDragOverFrame);
6241
6242 sLastDragOverFrame = nullptr;
6243 }
6244 } break;
6245
6246 default:
6247 break;
6248 }
6249
6250 // reset mCurretTargetContent to what it was
6251 mCurrentTargetContent = std::move(targetBeforeEvent);
6252
6253 // Now flush all pending notifications, for better responsiveness.
6254 FlushLayout(aPresContext);
6255}
6256
6257void EventStateManager::FireDragEnterOrExit(nsPresContext* aPresContext,
6258 const WidgetDragEvent& aDragEvent,
6259 EventMessage aMessage,
6260 nsIContent* aRelatedTarget,
6261 nsIContent* aTargetContent,
6262 AutoWeakFrame& aTargetFrame) {
6263 MOZ_ASSERT(aMessage == eDragLeave || aMessage == eDragExit ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMessage == eDragLeave || aMessage == eDragExit || aMessage
== eDragEnter)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(aMessage == eDragLeave || aMessage
== eDragExit || aMessage == eDragEnter))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aMessage == eDragLeave || aMessage == eDragExit || aMessage == eDragEnter"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6264
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage == eDragLeave || aMessage == eDragExit || aMessage == eDragEnter"
")"); do { MOZ_CrashSequence(__null, 6264); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6264 aMessage == eDragEnter)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMessage == eDragLeave || aMessage == eDragExit || aMessage
== eDragEnter)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(aMessage == eDragLeave || aMessage
== eDragExit || aMessage == eDragEnter))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aMessage == eDragLeave || aMessage == eDragExit || aMessage == eDragEnter"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6264
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMessage == eDragLeave || aMessage == eDragExit || aMessage == eDragEnter"
")"); do { MOZ_CrashSequence(__null, 6264); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6265 nsEventStatus status = nsEventStatus_eIgnore;
6266 WidgetDragEvent event(aDragEvent.IsTrusted(), aMessage, aDragEvent.mWidget);
6267 event.AssignDragEventData(aDragEvent, false);
6268 event.mFlags.mIsSynthesizedForTests =
6269 aDragEvent.mFlags.mIsSynthesizedForTests;
6270 event.mRelatedTarget = aRelatedTarget;
6271 if (aMessage == eDragExit && !StaticPrefs::dom_event_dragexit_enabled()) {
6272 event.mFlags.mOnlyChromeDispatch = true;
6273 }
6274
6275 mCurrentTargetContent = aTargetContent;
6276
6277 if (aTargetContent != aRelatedTarget) {
6278 // XXX This event should still go somewhere!!
6279 if (aTargetContent) {
6280 EventDispatcher::Dispatch(aTargetContent, aPresContext, &event, nullptr,
6281 &status);
6282 }
6283
6284 // adjust the drag hover if the dragenter event was cancelled or this is a
6285 // drag exit
6286 if (status == nsEventStatus_eConsumeNoDefault || aMessage == eDragExit) {
6287 SetContentState((aMessage == eDragEnter) ? aTargetContent : nullptr,
6288 ElementState::DRAGOVER);
6289 }
6290
6291 // collect any changes to moz cursor settings stored in the event's
6292 // data transfer.
6293 UpdateDragDataTransfer(&event);
6294 }
6295
6296 // Finally dispatch the event to the frame
6297 if (aTargetFrame) {
6298 aTargetFrame->HandleEvent(aPresContext, &event, &status);
6299 }
6300}
6301
6302void EventStateManager::UpdateDragDataTransfer(WidgetDragEvent* dragEvent) {
6303 NS_ASSERTION(dragEvent, "drag event is null in UpdateDragDataTransfer!")do { if (!(dragEvent)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "drag event is null in UpdateDragDataTransfer!"
, "dragEvent", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6303); MOZ_PretendNoReturn(); } } while (0)
;
6304 if (!dragEvent->mDataTransfer) {
6305 return;
6306 }
6307
6308 nsCOMPtr<nsIDragSession> dragSession =
6309 nsContentUtils::GetDragSession(mPresContext);
6310
6311 if (dragSession) {
6312 // the initial dataTransfer is the one from the dragstart event that
6313 // was set on the dragSession when the drag began.
6314 RefPtr<DataTransfer> initialDataTransfer = dragSession->GetDataTransfer();
6315 if (initialDataTransfer) {
6316 // retrieve the current moz cursor setting and save it.
6317 nsAutoString mozCursor;
6318 dragEvent->mDataTransfer->GetMozCursor(mozCursor);
6319 initialDataTransfer->SetMozCursor(mozCursor);
6320 }
6321 }
6322}
6323
6324void EventStateManager::PrepareForFollowingClickEvent(
6325 WidgetMouseEvent& aEvent, nsIContent* aOverrideClickTarget) {
6326 const nsCOMPtr<nsIContent> mouseContent =
6327 aOverrideClickTarget
6328 ? aOverrideClickTarget->GetInclusiveFlattenedTreeAncestorElement()
6329 : (mCurrentTarget ? mCurrentTarget->GetEventTargetContent(aEvent)
6330 : nullptr);
6331 LastMouseButtonPressInfo& lastButtonPressInfo =
6332 GetLastMouseButtonPressInfo(aEvent.mButton);
6333 if (aEvent.mMessage == eMouseDown) {
6334 lastButtonPressInfo.mConnectedDownContent =
6335 lastButtonPressInfo.mDownContent =
6336 !aEvent.mClickEventPrevented ? mouseContent : nullptr;
6337 lastButtonPressInfo.mUpContent = nullptr;
6338
6339 if (lastButtonPressInfo.mDownContent) {
6340 if (HTMLInputElement* input = HTMLInputElement::FromNodeOrNull(
6341 lastButtonPressInfo.mDownContent)) {
6342 lastButtonPressInfo.mDownInputControlType = Some(input->ControlType());
6343 } else if (lastButtonPressInfo.mDownContent
6344 ->IsInNativeAnonymousSubtree()) {
6345 if (HTMLInputElement* input = HTMLInputElement::FromNodeOrNull(
6346 lastButtonPressInfo.mDownContent->GetFlattenedTreeParent())) {
6347 lastButtonPressInfo.mDownInputControlType =
6348 Some(input->ControlType());
6349 }
6350 }
6351 }
6352 } else {
6353 MOZ_ASSERT(aEvent.mMessage == eMouseUp)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent.mMessage == eMouseUp)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aEvent.mMessage == eMouseUp)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aEvent.mMessage == eMouseUp"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6353
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent.mMessage == eMouseUp"
")"); do { MOZ_CrashSequence(__null, 6353); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6354 lastButtonPressInfo.mUpContent = mouseContent;
6355 aEvent.mClickTarget = [&]() -> EventTarget* {
6356 if (aEvent.mClickEventPrevented ||
6357 !lastButtonPressInfo.mConnectedDownContent) {
6358 return nullptr;
6359 }
6360 // If an element was capturing the pointer at dispatching ePointerUp, we
6361 // should dispatch click/auxclick/contextmenu event on it to conform to
6362 // Pointer Events. https://w3c.github.io/pointerevents/#event-dispatch
6363 if (PointerEventHandler::ShouldDispatchClickEventOnCapturingElement(
6364 &aEvent)) {
6365 const RefPtr<Element> capturingElementAtLastPointerUp =
6366 PointerEventHandler::GetPointerCapturingElementAtLastPointerUp();
6367 if (capturingElementAtLastPointerUp &&
6368 capturingElementAtLastPointerUp->GetPresContext(
6369 Element::PresContextFor::eForComposedDoc) == mPresContext) {
6370 return capturingElementAtLastPointerUp;
6371 }
6372 }
6373 return GetCommonAncestorForMouseUp(
6374 mouseContent, lastButtonPressInfo.mConnectedDownContent,
6375 lastButtonPressInfo.mDownInputControlType);
6376 }();
6377 if (aEvent.mClickTarget) {
6378 aEvent.mClickCount = lastButtonPressInfo.mClickCount;
6379 } else {
6380 aEvent.mClickCount = 0;
6381 }
6382 // We'll clear lastButtonPressInfo in PostHandleEvent().
6383 }
6384}
6385
6386// static
6387bool EventStateManager::EventCausesClickEvents(
6388 const WidgetMouseEvent& aMouseEvent) {
6389 if (NS_WARN_IF(aMouseEvent.mMessage != eMouseUp)NS_warn_if_impl(aMouseEvent.mMessage != eMouseUp, "aMouseEvent.mMessage != eMouseUp"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6389
)
) {
6390 return false;
6391 }
6392 // If the mouseup event is synthesized event, we don't need to dispatch
6393 // click events.
6394 if (!aMouseEvent.IsReal()) {
6395 return false;
6396 }
6397 // If mouse is still over same element, clickcount will be > 1.
6398 // If it has moved it will be zero, so no click.
6399 if (!aMouseEvent.mClickCount || !aMouseEvent.mClickTarget) {
6400 return false;
6401 }
6402 // If click event was explicitly prevented, we shouldn't dispatch it.
6403 if (aMouseEvent.mClickEventPrevented) {
6404 return false;
6405 }
6406 // Check that the window isn't disabled before firing a click
6407 // (see bug 366544).
6408 return !(aMouseEvent.mWidget && !aMouseEvent.mWidget->IsEnabled());
6409}
6410
6411nsresult EventStateManager::InitAndDispatchClickEvent(
6412 WidgetMouseEvent* aMouseUpEvent, nsEventStatus* aStatus,
6413 EventMessage aMessage, PresShell* aPresShell, nsIContent* aMouseUpContent,
6414 AutoWeakFrame aCurrentTarget, bool aNoContentDispatch,
6415 nsIContent* aOverrideClickTarget) {
6416 MOZ_ASSERT(aMouseUpEvent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMouseUpEvent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMouseUpEvent))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aMouseUpEvent",
"/root/firefox-clang/dom/events/EventStateManager.cpp", 6416
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseUpEvent" ")"
); do { MOZ_CrashSequence(__null, 6416); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6417 MOZ_ASSERT(EventCausesClickEvents(*aMouseUpEvent))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(EventCausesClickEvents(*aMouseUpEvent))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(EventCausesClickEvents(*aMouseUpEvent)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("EventCausesClickEvents(*aMouseUpEvent)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6417
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "EventCausesClickEvents(*aMouseUpEvent)"
")"); do { MOZ_CrashSequence(__null, 6417); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6418 MOZ_ASSERT(aMouseUpContent || aCurrentTarget || aOverrideClickTarget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMouseUpContent || aCurrentTarget || aOverrideClickTarget
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aMouseUpContent || aCurrentTarget || aOverrideClickTarget
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aMouseUpContent || aCurrentTarget || aOverrideClickTarget", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6418); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseUpContent || aCurrentTarget || aOverrideClickTarget"
")"); do { MOZ_CrashSequence(__null, 6418); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6419
6420 Maybe<WidgetPointerEvent> pointerEvent;
6421 Maybe<WidgetMouseEvent> mouseEvent;
6422 if (IsPointerEventMessage(aMessage)) {
6423 pointerEvent.emplace(aMouseUpEvent->IsTrusted(), aMessage,
6424 aMouseUpEvent->mWidget);
6425 } else {
6426 mouseEvent.emplace(aMouseUpEvent->IsTrusted(), aMessage,
6427 aMouseUpEvent->mWidget, WidgetMouseEvent::eReal);
6428 }
6429
6430 WidgetMouseEvent& mouseOrPointerEvent =
6431 pointerEvent.isSome() ? pointerEvent.ref() : mouseEvent.ref();
6432
6433 mouseOrPointerEvent.mRefPoint = aMouseUpEvent->mRefPoint;
6434 mouseOrPointerEvent.mClickCount = aMouseUpEvent->mClickCount;
6435 mouseOrPointerEvent.mModifiers = aMouseUpEvent->mModifiers;
6436 mouseOrPointerEvent.mButtons = aMouseUpEvent->mButtons;
6437 mouseOrPointerEvent.mTimeStamp = aMouseUpEvent->mTimeStamp;
6438 mouseOrPointerEvent.mFlags.mOnlyChromeDispatch = aNoContentDispatch;
6439 mouseOrPointerEvent.mFlags.mNoContentDispatch = aNoContentDispatch;
6440 mouseOrPointerEvent.mButton = aMouseUpEvent->mButton;
6441 mouseOrPointerEvent.pointerId = aMouseUpEvent->pointerId;
6442 mouseOrPointerEvent.mInputSource = aMouseUpEvent->mInputSource;
6443 nsIContent* target = aMouseUpContent;
6444 nsIFrame* targetFrame = aCurrentTarget;
6445 if (aOverrideClickTarget) {
6446 target = aOverrideClickTarget;
6447 targetFrame =
6448 nsLayoutUtils::GetPrimaryOrAreaImageFrame(aOverrideClickTarget);
6449 }
6450
6451 if (!target->IsInComposedDoc()) {
6452 return NS_OK;
6453 }
6454
6455 // Use local event status for each click event dispatching since it'll be
6456 // cleared by EventStateManager::PreHandleEvent(). Therefore, dispatching
6457 // an event means that previous event status will be ignored.
6458 nsEventStatus status = nsEventStatus_eIgnore;
6459 nsresult rv = aPresShell->HandleEventWithTarget(
6460 &mouseOrPointerEvent, targetFrame, MOZ_KnownLive(target)(target), &status);
6461
6462 // Copy mMultipleActionsPrevented flag from a click event to the mouseup
6463 // event only when it's set to true. It may be set to true if an editor has
6464 // already handled it. This is important to avoid two or more default
6465 // actions handled here.
6466 aMouseUpEvent->mFlags.mMultipleActionsPrevented |=
6467 mouseOrPointerEvent.mFlags.mMultipleActionsPrevented;
6468 // If current status is nsEventStatus_eConsumeNoDefault, we don't need to
6469 // overwrite it.
6470 if (*aStatus == nsEventStatus_eConsumeNoDefault) {
6471 return rv;
6472 }
6473 // If new status is nsEventStatus_eConsumeNoDefault or
6474 // nsEventStatus_eConsumeDoDefault, use it.
6475 if (status == nsEventStatus_eConsumeNoDefault ||
6476 status == nsEventStatus_eConsumeDoDefault) {
6477 *aStatus = status;
6478 return rv;
6479 }
6480 // Otherwise, keep the original status.
6481 return rv;
6482}
6483
6484nsresult EventStateManager::PostHandleMouseUp(
6485 WidgetMouseEvent* aMouseUpEvent, nsEventStatus* aStatus,
6486 nsIContent* aOverrideClickTarget) {
6487 MOZ_ASSERT(aMouseUpEvent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMouseUpEvent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMouseUpEvent))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aMouseUpEvent",
"/root/firefox-clang/dom/events/EventStateManager.cpp", 6487
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseUpEvent" ")"
); do { MOZ_CrashSequence(__null, 6487); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6488 MOZ_ASSERT(EventCausesClickEvents(*aMouseUpEvent))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(EventCausesClickEvents(*aMouseUpEvent))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(EventCausesClickEvents(*aMouseUpEvent)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("EventCausesClickEvents(*aMouseUpEvent)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6488
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "EventCausesClickEvents(*aMouseUpEvent)"
")"); do { MOZ_CrashSequence(__null, 6488); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6489 MOZ_ASSERT(aStatus)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStatus)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aStatus))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aStatus", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6489); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStatus" ")"
); do { MOZ_CrashSequence(__null, 6489); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6490
6491 RefPtr<PresShell> presShell = mPresContext->GetPresShell();
6492 if (!presShell) {
6493 return NS_OK;
6494 }
6495
6496 nsCOMPtr<nsIContent> clickTarget =
6497 nsIContent::FromEventTargetOrNull(aMouseUpEvent->mClickTarget);
6498 NS_ENSURE_STATE(clickTarget)do { if ((__builtin_expect(!!(!(clickTarget)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "clickTarget" ") failed"
, nullptr, "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6498); return NS_ERROR_UNEXPECTED; } } while (false)
;
6499
6500 // Fire click events if the event target is still available.
6501 // Note that do not include the eMouseUp event's status since we ignore it
6502 // for compatibility with the other browsers.
6503 nsEventStatus status = nsEventStatus_eIgnore;
6504 nsresult rv = DispatchClickEvents(presShell, aMouseUpEvent, &status,
6505 clickTarget, aOverrideClickTarget);
6506 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6506)
) {
6507 return rv;
6508 }
6509
6510 // Do not do anything if preceding click events are consumed.
6511 // Note that Chromium dispatches "paste" event and actually pates clipboard
6512 // text into focused editor even if the preceding click events are consumed.
6513 // However, this is different from our traditional behavior and does not
6514 // conform to DOM events. If we need to keep compatibility with Chromium,
6515 // we should change it later.
6516 if (status == nsEventStatus_eConsumeNoDefault) {
6517 *aStatus = nsEventStatus_eConsumeNoDefault;
6518 return NS_OK;
6519 }
6520
6521 // Handle middle click paste if it's enabled and the mouse button is middle.
6522 if (aMouseUpEvent->mButton != MouseButton::eMiddle ||
6523 !WidgetMouseEvent::IsMiddleClickPasteEnabled()) {
6524 return NS_OK;
6525 }
6526 DebugOnly<nsresult> rvIgnored =
6527 HandleMiddleClickPaste(presShell, aMouseUpEvent, &status, nullptr);
6528 NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored
)), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "Failed to paste for a middle click"
, "NS_SUCCEEDED(rvIgnored)", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6529); } } while (false)
6529 "Failed to paste for a middle click")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored
)), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "Failed to paste for a middle click"
, "NS_SUCCEEDED(rvIgnored)", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6529); } } while (false)
;
6530
6531 // If new status is nsEventStatus_eConsumeNoDefault or
6532 // nsEventStatus_eConsumeDoDefault, use it.
6533 if (*aStatus != nsEventStatus_eConsumeNoDefault &&
6534 (status == nsEventStatus_eConsumeNoDefault ||
6535 status == nsEventStatus_eConsumeDoDefault)) {
6536 *aStatus = status;
6537 }
6538
6539 // Don't return error even if middle mouse paste fails since we haven't
6540 // handled it here.
6541 return NS_OK;
6542}
6543
6544nsresult EventStateManager::DispatchClickEvents(
6545 PresShell* aPresShell, WidgetMouseEvent* aMouseUpEvent,
6546 nsEventStatus* aStatus, nsIContent* aClickTarget,
6547 nsIContent* aOverrideClickTarget) {
6548 MOZ_ASSERT(aPresShell)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPresShell)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPresShell))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aPresShell", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6548); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresShell"
")"); do { MOZ_CrashSequence(__null, 6548); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6549 MOZ_ASSERT(aMouseUpEvent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMouseUpEvent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMouseUpEvent))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aMouseUpEvent",
"/root/firefox-clang/dom/events/EventStateManager.cpp", 6549
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseUpEvent" ")"
); do { MOZ_CrashSequence(__null, 6549); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6550 MOZ_ASSERT(EventCausesClickEvents(*aMouseUpEvent))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(EventCausesClickEvents(*aMouseUpEvent))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(EventCausesClickEvents(*aMouseUpEvent)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("EventCausesClickEvents(*aMouseUpEvent)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6550
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "EventCausesClickEvents(*aMouseUpEvent)"
")"); do { MOZ_CrashSequence(__null, 6550); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6551 MOZ_ASSERT(aStatus)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStatus)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aStatus))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aStatus", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6551); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStatus" ")"
); do { MOZ_CrashSequence(__null, 6551); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6552 MOZ_ASSERT(aClickTarget || aOverrideClickTarget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aClickTarget || aOverrideClickTarget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aClickTarget || aOverrideClickTarget
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aClickTarget || aOverrideClickTarget", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6552); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aClickTarget || aOverrideClickTarget"
")"); do { MOZ_CrashSequence(__null, 6552); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6553
6554 bool notDispatchToContents =
6555 (aMouseUpEvent->mButton == MouseButton::eMiddle ||
6556 aMouseUpEvent->mButton == MouseButton::eSecondary);
6557
6558 bool fireAuxClick = notDispatchToContents;
6559
6560 AutoWeakFrame currentTarget =
6561 nsLayoutUtils::GetPrimaryOrAreaImageFrame(aClickTarget);
6562 nsresult rv = InitAndDispatchClickEvent(
6563 aMouseUpEvent, aStatus, ePointerClick, aPresShell, aClickTarget,
6564 currentTarget, notDispatchToContents, aOverrideClickTarget);
6565 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6565)
) {
6566 return rv;
6567 }
6568
6569 // Fire auxclick event if necessary.
6570 if (fireAuxClick && *aStatus != nsEventStatus_eConsumeNoDefault &&
6571 aClickTarget && aClickTarget->IsInComposedDoc()) {
6572 rv = InitAndDispatchClickEvent(aMouseUpEvent, aStatus, ePointerAuxClick,
6573 aPresShell, aClickTarget, currentTarget,
6574 false, aOverrideClickTarget);
6575 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))))) { NS_DebugBreak(NS_DEBUG_WARNING, "Failed to dispatch ePointerAuxClick"
, "NS_SUCCEEDED(rv)", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6576); } } while (false)
6576 "Failed to dispatch ePointerAuxClick")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))))) { NS_DebugBreak(NS_DEBUG_WARNING, "Failed to dispatch ePointerAuxClick"
, "NS_SUCCEEDED(rv)", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6576); } } while (false)
;
6577 }
6578
6579 // Fire double click event if click count is 2.
6580 if (aMouseUpEvent->mClickCount == 2 && !fireAuxClick && aClickTarget &&
6581 aClickTarget->IsInComposedDoc()) {
6582 rv = InitAndDispatchClickEvent(aMouseUpEvent, aStatus, eMouseDoubleClick,
6583 aPresShell, aClickTarget, currentTarget,
6584 notDispatchToContents, aOverrideClickTarget);
6585 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6585)
) {
6586 return rv;
6587 }
6588 }
6589
6590 return rv;
6591}
6592
6593nsresult EventStateManager::HandleMiddleClickPaste(
6594 PresShell* aPresShell, WidgetMouseEvent* aMouseOrPointerEvent,
6595 nsEventStatus* aStatus, EditorBase* aEditorBase) {
6596 MOZ_ASSERT(aPresShell)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPresShell)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPresShell))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aPresShell", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6596); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresShell"
")"); do { MOZ_CrashSequence(__null, 6596); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6597 MOZ_ASSERT(aMouseOrPointerEvent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMouseOrPointerEvent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMouseOrPointerEvent))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("aMouseOrPointerEvent"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6597
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseOrPointerEvent"
")"); do { MOZ_CrashSequence(__null, 6597); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6598 MOZ_ASSERT((aMouseOrPointerEvent->mMessage == ePointerAuxClick &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype((aMouseOrPointerEvent->mMessage == ePointerAuxClick
&& aMouseOrPointerEvent->mButton == MouseButton::
eMiddle) || EventCausesClickEvents(*aMouseOrPointerEvent))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!((aMouseOrPointerEvent->mMessage == ePointerAuxClick
&& aMouseOrPointerEvent->mButton == MouseButton::
eMiddle) || EventCausesClickEvents(*aMouseOrPointerEvent)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("(aMouseOrPointerEvent->mMessage == ePointerAuxClick && aMouseOrPointerEvent->mButton == MouseButton::eMiddle) || EventCausesClickEvents(*aMouseOrPointerEvent)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6600
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aMouseOrPointerEvent->mMessage == ePointerAuxClick && aMouseOrPointerEvent->mButton == MouseButton::eMiddle) || EventCausesClickEvents(*aMouseOrPointerEvent)"
")"); do { MOZ_CrashSequence(__null, 6600); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6599 aMouseOrPointerEvent->mButton == MouseButton::eMiddle) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype((aMouseOrPointerEvent->mMessage == ePointerAuxClick
&& aMouseOrPointerEvent->mButton == MouseButton::
eMiddle) || EventCausesClickEvents(*aMouseOrPointerEvent))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!((aMouseOrPointerEvent->mMessage == ePointerAuxClick
&& aMouseOrPointerEvent->mButton == MouseButton::
eMiddle) || EventCausesClickEvents(*aMouseOrPointerEvent)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("(aMouseOrPointerEvent->mMessage == ePointerAuxClick && aMouseOrPointerEvent->mButton == MouseButton::eMiddle) || EventCausesClickEvents(*aMouseOrPointerEvent)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6600
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aMouseOrPointerEvent->mMessage == ePointerAuxClick && aMouseOrPointerEvent->mButton == MouseButton::eMiddle) || EventCausesClickEvents(*aMouseOrPointerEvent)"
")"); do { MOZ_CrashSequence(__null, 6600); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6600 EventCausesClickEvents(*aMouseOrPointerEvent))do { static_assert( mozilla::detail::AssertionConditionType<
decltype((aMouseOrPointerEvent->mMessage == ePointerAuxClick
&& aMouseOrPointerEvent->mButton == MouseButton::
eMiddle) || EventCausesClickEvents(*aMouseOrPointerEvent))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!((aMouseOrPointerEvent->mMessage == ePointerAuxClick
&& aMouseOrPointerEvent->mButton == MouseButton::
eMiddle) || EventCausesClickEvents(*aMouseOrPointerEvent)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("(aMouseOrPointerEvent->mMessage == ePointerAuxClick && aMouseOrPointerEvent->mButton == MouseButton::eMiddle) || EventCausesClickEvents(*aMouseOrPointerEvent)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6600
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aMouseOrPointerEvent->mMessage == ePointerAuxClick && aMouseOrPointerEvent->mButton == MouseButton::eMiddle) || EventCausesClickEvents(*aMouseOrPointerEvent)"
")"); do { MOZ_CrashSequence(__null, 6600); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6601 MOZ_ASSERT(aStatus)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStatus)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aStatus))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aStatus", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6601); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStatus" ")"
); do { MOZ_CrashSequence(__null, 6601); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6602 MOZ_ASSERT(*aStatus != nsEventStatus_eConsumeNoDefault)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(*aStatus != nsEventStatus_eConsumeNoDefault)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(*aStatus != nsEventStatus_eConsumeNoDefault))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("*aStatus != nsEventStatus_eConsumeNoDefault"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6602
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "*aStatus != nsEventStatus_eConsumeNoDefault"
")"); do { MOZ_CrashSequence(__null, 6602); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6603
6604 // Even if we're called twice or more for a mouse operation, we should
6605 // handle only once. Although mMultipleActionsPrevented may be set to
6606 // true by different event handler in the future, we can use it for now.
6607 if (aMouseOrPointerEvent->mFlags.mMultipleActionsPrevented) {
6608 return NS_OK;
6609 }
6610 aMouseOrPointerEvent->mFlags.mMultipleActionsPrevented = true;
6611
6612 RefPtr<Selection> selection;
6613 if (aEditorBase) {
6614 selection = aEditorBase->GetSelection();
6615 if (NS_WARN_IF(!selection)NS_warn_if_impl(!selection, "!selection", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6615)
) {
6616 return NS_ERROR_FAILURE;
6617 }
6618 } else {
6619 Document* document = aPresShell->GetDocument();
6620 if (NS_WARN_IF(!document)NS_warn_if_impl(!document, "!document", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6620)
) {
6621 return NS_ERROR_FAILURE;
6622 }
6623 selection = nsCopySupport::GetSelectionForCopy(document);
6624 if (NS_WARN_IF(!selection)NS_warn_if_impl(!selection, "!selection", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6624)
) {
6625 return NS_ERROR_FAILURE;
6626 }
6627
6628 const dom::Range* range = selection->GetRangeAt(0);
6629 if (range) {
6630 nsINode* target = range->GetStartContainer();
6631 if (target && target->OwnerDoc()->IsInChromeDocShell()) {
6632 // In Chrome document, limit middle-click pasting to only the editor
6633 // because it looks odd if pasting works in the focused editor when you
6634 // middle-click toolbar or something which are far from the editor.
6635 // However, as DevTools especially Web Console module assumes that paste
6636 // event will be fired when middle-click even on not editor, don't limit
6637 // it.
6638 return NS_OK;
6639 }
6640 }
6641 }
6642
6643 // Don't modify selection here because we've already set caret to the point
6644 // at "mousedown" event.
6645
6646 nsIClipboard::ClipboardType clipboardType = nsIClipboard::kGlobalClipboard;
6647 nsCOMPtr<nsIClipboard> clipboardService =
6648 do_GetService("@mozilla.org/widget/clipboard;1");
6649 if (clipboardService && clipboardService->IsClipboardTypeSupported(
6650 nsIClipboard::kSelectionClipboard)) {
6651 clipboardType = nsIClipboard::kSelectionClipboard;
6652 }
6653
6654 RefPtr<DataTransfer> dataTransfer;
6655 if (aEditorBase) {
6656 // Create the same DataTransfer object here so we can share it between
6657 // the clipboard event and the call to HandlePaste below. This prevents
6658 // race conditions with Content Analysis on like we see in bug 1918027.
6659 dataTransfer =
6660 aEditorBase->CreateDataTransferForPaste(ePaste, clipboardType);
6661 }
6662 const auto clearDataTransfer = MakeScopeExit([&] {
6663 if (dataTransfer) {
6664 dataTransfer->ClearForPaste();
6665 }
6666 });
6667
6668 // Fire ePaste event by ourselves since we need to dispatch "paste" event
6669 // even if the middle click event was consumed for compatibility with
6670 // Chromium.
6671 if (!nsCopySupport::FireClipboardEvent(ePaste, Some(clipboardType),
6672 aPresShell, selection, dataTransfer)) {
6673 *aStatus = nsEventStatus_eConsumeNoDefault;
6674 return NS_OK;
6675 }
6676
6677 // Although we've fired "paste" event, there is no editor to accept the
6678 // clipboard content.
6679 if (!aEditorBase) {
6680 return NS_OK;
6681 }
6682
6683 // Check if the editor is still the good target to paste.
6684 if (aEditorBase->Destroyed() || aEditorBase->IsReadonly()) {
6685 // XXX Should we consume the event when the editor is readonly and/or
6686 // disabled?
6687 return NS_OK;
6688 }
6689
6690 // The selection may have been modified during reflow. Therefore, we
6691 // should adjust event target to pass IsAcceptableInputEvent().
6692 const dom::Range* range = selection->GetRangeAt(0);
6693 if (!range) {
6694 return NS_OK;
6695 }
6696 {
6697 Maybe<WidgetPointerEvent> pointerEvent;
6698 Maybe<WidgetMouseEvent> mouseEvent;
6699 if (aMouseOrPointerEvent->mClass == ePointerEventClass) {
6700 MOZ_ASSERT(aMouseOrPointerEvent->AsPointerEvent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMouseOrPointerEvent->AsPointerEvent())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aMouseOrPointerEvent->AsPointerEvent()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aMouseOrPointerEvent->AsPointerEvent()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6700
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMouseOrPointerEvent->AsPointerEvent()"
")"); do { MOZ_CrashSequence(__null, 6700); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6701 pointerEvent.emplace(
6702 WidgetPointerEvent::MakeCopyFromMouseEvent(*aMouseOrPointerEvent));
6703 } else {
6704 MOZ_ASSERT(!aMouseOrPointerEvent->AsPointerEvent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aMouseOrPointerEvent->AsPointerEvent())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aMouseOrPointerEvent->AsPointerEvent()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!aMouseOrPointerEvent->AsPointerEvent()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6704
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aMouseOrPointerEvent->AsPointerEvent()"
")"); do { MOZ_CrashSequence(__null, 6704); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6705 MOZ_ASSERT(!aMouseOrPointerEvent->AsDragEvent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aMouseOrPointerEvent->AsDragEvent())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aMouseOrPointerEvent->AsDragEvent()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!aMouseOrPointerEvent->AsDragEvent()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6705
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aMouseOrPointerEvent->AsDragEvent()"
")"); do { MOZ_CrashSequence(__null, 6705); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6706 mouseEvent.emplace(*aMouseOrPointerEvent);
6707 }
6708 WidgetMouseEvent& eventCopyRef =
6709 pointerEvent.isSome() ? pointerEvent.ref() : mouseEvent.ref();
6710 eventCopyRef.mOriginalTarget = range->GetStartContainer();
6711 if (NS_WARN_IF(!eventCopyRef.mOriginalTarget)NS_warn_if_impl(!eventCopyRef.mOriginalTarget, "!eventCopyRef.mOriginalTarget"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6711
)
||
6712 !aEditorBase->IsAcceptableInputEvent(&eventCopyRef)) {
6713 return NS_OK;
6714 }
6715 }
6716
6717 // If Control key is pressed, we should paste clipboard content as
6718 // quotation. Otherwise, paste it as is.
6719 if (aMouseOrPointerEvent->IsControl()) {
6720 DebugOnly<nsresult> rv = aEditorBase->PasteAsQuotationAsAction(
6721 clipboardType, EditorBase::DispatchPasteEvent::No, dataTransfer);
6722 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to paste as quotation")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))))) { NS_DebugBreak(NS_DEBUG_WARNING, "Failed to paste as quotation"
, "NS_SUCCEEDED(rv)", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6722); } } while (false)
;
6723 } else {
6724 DebugOnly<nsresult> rv = aEditorBase->PasteAsAction(
6725 clipboardType, EditorBase::DispatchPasteEvent::No, dataTransfer);
6726 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to paste")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))))) { NS_DebugBreak(NS_DEBUG_WARNING, "Failed to paste", "NS_SUCCEEDED(rv)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6726
); } } while (false)
;
6727 }
6728 *aStatus = nsEventStatus_eConsumeNoDefault;
6729
6730 return NS_OK;
6731}
6732
6733void EventStateManager::ConsumeInteractionData(
6734 Record<nsString, dom::InteractionData>& aInteractions) {
6735 OnTypingInteractionEnded();
6736
6737 aInteractions.Entries().Clear();
6738 auto newEntry = aInteractions.Entries().AppendElement();
6739 newEntry->mKey = u"Typing"_ns;
6740 newEntry->mValue = gTypingInteraction;
6741 gTypingInteraction = {};
6742}
6743
6744nsIFrame* EventStateManager::GetEventTarget() {
6745 PresShell* presShell;
6746 if (mCurrentTarget || !mPresContext ||
6747 !(presShell = mPresContext->GetPresShell())) {
6748 return mCurrentTarget;
6749 }
6750
6751 if (mCurrentTargetContent) {
6752 mCurrentTarget =
6753 mPresContext->GetPrimaryOrAreaImageFrameFor(mCurrentTargetContent);
6754 if (mCurrentTarget) {
6755 return mCurrentTarget;
6756 }
6757 }
6758
6759 nsIFrame* frame = presShell->GetCurrentEventFrame();
6760 return (mCurrentTarget = frame);
6761}
6762
6763nsIContent* EventStateManager::GetExplicitEventTargetContent(
6764 const WidgetEvent* aEvent /* = nullptr */) {
6765 if (aEvent && (aEvent->mMessage == eFocus || aEvent->mMessage == eBlur)) {
6766 return GetFocusedElement();
6767 }
6768
6769 if (mCurrentTargetContent) {
6770 return mCurrentTargetContent;
6771 }
6772
6773 if (PresShell* presShell = mPresContext->GetPresShell()) {
6774 if (nsIContent* content =
6775 presShell->GetExplicitEventTargetContent(aEvent)) {
6776 return content;
6777 }
6778 }
6779
6780 // Some events here may set mCurrentTarget but not set the corresponding
6781 // event target in the PresShell.
6782 return mCurrentTarget ? mCurrentTarget->GetExplicitEventTargetContent(aEvent)
6783 : nullptr;
6784}
6785
6786nsIContent* EventStateManager::GetEventTargetContent(
6787 const WidgetEvent* aEvent /* = nullptr */) {
6788 return nsContentUtils::GetEventTargetContent(
6789 GetExplicitEventTargetContent(aEvent), aEvent);
6790}
6791
6792static Element* GetLabelTarget(nsIContent* aPossibleLabel) {
6793 mozilla::dom::HTMLLabelElement* label =
6794 mozilla::dom::HTMLLabelElement::FromNode(aPossibleLabel);
6795 if (!label) return nullptr;
6796
6797 return label->GetLabeledElementInternal();
6798}
6799
6800/* static */
6801inline void EventStateManager::DoStateChange(Element* aElement,
6802 ElementState aState,
6803 bool aAddState) {
6804 if (aAddState) {
6805 aElement->AddStates(aState);
6806 } else {
6807 aElement->RemoveStates(aState);
6808 }
6809}
6810
6811/* static */
6812inline void EventStateManager::DoStateChange(nsIContent* aContent,
6813 ElementState aState,
6814 bool aStateAdded) {
6815 if (aContent->IsElement()) {
6816 DoStateChange(aContent->AsElement(), aState, aStateAdded);
6817 }
6818}
6819
6820/* static */
6821void EventStateManager::UpdateAncestorState(nsIContent* aStartNode,
6822 nsIContent* aStopBefore,
6823 ElementState aState,
6824 bool aAddState) {
6825 for (; aStartNode && aStartNode != aStopBefore;
6826 aStartNode = aStartNode->GetFlattenedTreeParent()) {
6827 // We might be starting with a non-element (e.g. a text node) and
6828 // if someone is doing something weird might be ending with a
6829 // non-element too (e.g. a document fragment)
6830 if (!aStartNode->IsElement()) {
6831 continue;
6832 }
6833 Element* element = aStartNode->AsElement();
6834 DoStateChange(element, aState, aAddState);
6835 Element* labelTarget = GetLabelTarget(element);
6836 if (labelTarget) {
6837 DoStateChange(labelTarget, aState, aAddState);
6838 }
6839 }
6840
6841 if (aAddState) {
6842 // We might be in a situation where a node was in hover both
6843 // because it was hovered and because the label for it was
6844 // hovered, and while we stopped hovering the node the label is
6845 // still hovered. Or we might have had two nested labels for the
6846 // same node, and while one is no longer hovered the other still
6847 // is. In that situation, the label that's still hovered will be
6848 // aStopBefore or some ancestor of it, and the call we just made
6849 // to UpdateAncestorState with aAddState = false would have
6850 // removed the hover state from the node. But the node should
6851 // still be in hover state. To handle this situation we need to
6852 // keep walking up the tree and any time we find a label mark its
6853 // corresponding node as still in our state.
6854 for (; aStartNode; aStartNode = aStartNode->GetFlattenedTreeParent()) {
6855 if (!aStartNode->IsElement()) {
6856 continue;
6857 }
6858
6859 Element* labelTarget = GetLabelTarget(aStartNode->AsElement());
6860 if (labelTarget && !labelTarget->State().HasState(aState)) {
6861 DoStateChange(labelTarget, aState, true);
6862 }
6863 }
6864 }
6865}
6866
6867// static
6868bool CanContentHaveActiveState(nsIContent& aContent) {
6869 // Editable content can never become active since their default actions
6870 // are disabled. Watch out for editable content in native anonymous
6871 // subtrees though, as they belong to text controls.
6872 return !aContent.IsEditable() || aContent.IsInNativeAnonymousSubtree();
6873}
6874
6875bool EventStateManager::SetContentState(nsIContent* aContent,
6876 ElementState aState) {
6877 MOZ_ASSERT(ManagesState(aState), "Unexpected state")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ManagesState(aState))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(ManagesState(aState)))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("ManagesState(aState)"
" (" "Unexpected state" ")", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6877); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ManagesState(aState)"
") (" "Unexpected state" ")"); do { MOZ_CrashSequence(__null
, 6877); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
6878
6879 nsCOMPtr<nsIContent> notifyContent1;
6880 nsCOMPtr<nsIContent> notifyContent2;
6881 bool updateAncestors;
6882
6883 if (aState == ElementState::HOVER || aState == ElementState::ACTIVE) {
6884 // Hover and active are hierarchical
6885 updateAncestors = true;
6886
6887 if (aState == ElementState::ACTIVE) {
6888 if (aContent && !CanContentHaveActiveState(*aContent)) {
6889 aContent = nullptr;
6890 }
6891 if (aContent != mActiveContent) {
6892 notifyContent1 = aContent;
6893 notifyContent2 = mActiveContent;
6894 mActiveContent = aContent;
6895 }
6896 } else {
6897 NS_ASSERTION(aState == ElementState::HOVER, "How did that happen?")do { if (!(aState == ElementState::HOVER)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "How did that happen?", "aState == ElementState::HOVER", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 6897); MOZ_PretendNoReturn(); } } while (0)
;
6898 nsIContent* newHover;
6899
6900 if (mPresContext->IsDynamic()) {
6901 newHover = aContent;
6902 } else {
6903 NS_ASSERTION(!aContent || aContent->GetComposedDoc() ==do { if (!(!aContent || aContent->GetComposedDoc() == mPresContext
->PresShell()->GetDocument())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Unexpected document", "!aContent || aContent->GetComposedDoc() == mPresContext->PresShell()->GetDocument()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6905
); MOZ_PretendNoReturn(); } } while (0)
6904 mPresContext->PresShell()->GetDocument(),do { if (!(!aContent || aContent->GetComposedDoc() == mPresContext
->PresShell()->GetDocument())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Unexpected document", "!aContent || aContent->GetComposedDoc() == mPresContext->PresShell()->GetDocument()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6905
); MOZ_PretendNoReturn(); } } while (0)
6905 "Unexpected document")do { if (!(!aContent || aContent->GetComposedDoc() == mPresContext
->PresShell()->GetDocument())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Unexpected document", "!aContent || aContent->GetComposedDoc() == mPresContext->PresShell()->GetDocument()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 6905
); MOZ_PretendNoReturn(); } } while (0)
;
6906 nsIFrame* frame =
6907 aContent ? nsLayoutUtils::GetPrimaryOrAreaImageFrame(aContent)
6908 : nullptr;
6909 if (frame && nsLayoutUtils::IsViewportScrollbarFrame(frame)) {
6910 // The scrollbars of viewport should not ignore the hover state.
6911 // Because they are *not* the content of the web page.
6912 newHover = aContent;
6913 } else {
6914 // All contents of the web page should ignore the hover state.
6915 newHover = nullptr;
6916 }
6917 }
6918
6919 if (newHover != mHoverContent) {
6920 notifyContent1 = newHover;
6921 notifyContent2 = mHoverContent;
6922 NotifySpeculationRulesOfHover(newHover);
6923 mHoverContent = newHover;
6924 }
6925 }
6926 } else {
6927 updateAncestors = false;
6928 if (aState == ElementState::DRAGOVER) {
6929 if (aContent != sDragOverContent) {
6930 notifyContent1 = aContent;
6931 notifyContent2 = sDragOverContent;
6932 sDragOverContent = aContent;
6933 }
6934 } else if (aState == ElementState::URLTARGET) {
6935 if (aContent != mURLTargetContent) {
6936 notifyContent1 = aContent;
6937 notifyContent2 = mURLTargetContent;
6938 mURLTargetContent = aContent;
6939 }
6940 }
6941 }
6942
6943 // We need to keep track of which of notifyContent1 and notifyContent2 is
6944 // getting the state set and which is getting it unset. If both are
6945 // non-null, then notifyContent1 is having the state set and notifyContent2
6946 // is having it unset. But if one of them is null, we need to keep track of
6947 // the right thing for notifyContent1 explicitly.
6948 bool content1StateSet = true;
6949 if (!notifyContent1) {
6950 // This is ok because FindCommonAncestor wouldn't find anything
6951 // anyway if notifyContent1 is null.
6952 notifyContent1 = notifyContent2;
6953 notifyContent2 = nullptr;
6954 content1StateSet = false;
6955 }
6956
6957 if (notifyContent1 && mPresContext) {
6958 EnsureDocument(mPresContext);
6959 if (mDocument) {
6960 nsAutoScriptBlocker scriptBlocker;
6961
6962 if (updateAncestors) {
6963 nsCOMPtr<nsIContent> commonAncestor =
6964 FindCommonAncestor(notifyContent1, notifyContent2);
6965 if (notifyContent2) {
6966 // It's very important to first notify the state removal and
6967 // then the state addition, because due to labels it's
6968 // possible that we're removing state from some element but
6969 // then adding it again (say because mHoverContent changed
6970 // from a control to its label).
6971 UpdateAncestorState(notifyContent2, commonAncestor, aState, false);
6972 }
6973 UpdateAncestorState(notifyContent1, commonAncestor, aState,
6974 content1StateSet);
6975 } else {
6976 if (notifyContent2) {
6977 DoStateChange(notifyContent2, aState, false);
6978 }
6979 DoStateChange(notifyContent1, aState, content1StateSet);
6980 }
6981 }
6982 }
6983
6984 return true;
6985}
6986
6987// Hovering a link is a signal of user interest that can enact a speculation
6988// rules prefetch candidate. This is notified on hover chain changes rather than
6989// from mouseover/mouseout so that moving the cursor between the children of a
6990// link doesn't read as leaving and re-entering the link itself.
6991void EventStateManager::NotifySpeculationRulesOfHover(nsIContent* aNewHover) {
6992 nsIContent* content = aNewHover ? aNewHover : mHoverContent.get();
6993 if (!content) {
6994 return;
6995 }
6996 if (auto* speculationRules = content->OwnerDoc()->GetSpeculationRules()) {
6997 speculationRules->HoverContentChanged(aNewHover);
6998 }
6999}
7000
7001void EventStateManager::RemoveNodeFromChainIfNeeded(ElementState aState,
7002 nsIContent* aContentRemoved,
7003 bool aNotify) {
7004 MOZ_ASSERT(aState == ElementState::HOVER || aState == ElementState::ACTIVE)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aState == ElementState::HOVER || aState == ElementState
::ACTIVE)>::isValid, "invalid assertion condition"); if ((
__builtin_expect(!!(!(!!(aState == ElementState::HOVER || aState
== ElementState::ACTIVE))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aState == ElementState::HOVER || aState == ElementState::ACTIVE"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 7004
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aState == ElementState::HOVER || aState == ElementState::ACTIVE"
")"); do { MOZ_CrashSequence(__null, 7004); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7005 if (!aContentRemoved->IsElement() ||
7006 !aContentRemoved->AsElement()->State().HasState(aState)) {
7007 return;
7008 }
7009
7010 nsCOMPtr<nsIContent>& leaf =
7011 aState == ElementState::HOVER ? mHoverContent : mActiveContent;
7012
7013 MOZ_ASSERT(leaf)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(leaf)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(leaf))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("leaf", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7013); AnnotateMozCrashReason("MOZ_ASSERT" "(" "leaf" ")");
do { MOZ_CrashSequence(__null, 7013); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7014 // These two NS_ASSERTIONS below can fail for Shadow DOM sometimes, and it's
7015 // not clear how to best handle it, see
7016 // https://github.com/whatwg/html/issues/4795 and bug 1551621.
7017 NS_ASSERTION(do { if (!(nsContentUtils::ContentIsFlattenedTreeDescendantOf
(leaf, aContentRemoved))) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"Flat tree and active / hover chain got out of sync", "nsContentUtils::ContentIsFlattenedTreeDescendantOf(leaf, aContentRemoved)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 7019
); MOZ_PretendNoReturn(); } } while (0)
7018 nsContentUtils::ContentIsFlattenedTreeDescendantOf(leaf, aContentRemoved),do { if (!(nsContentUtils::ContentIsFlattenedTreeDescendantOf
(leaf, aContentRemoved))) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"Flat tree and active / hover chain got out of sync", "nsContentUtils::ContentIsFlattenedTreeDescendantOf(leaf, aContentRemoved)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 7019
); MOZ_PretendNoReturn(); } } while (0)
7019 "Flat tree and active / hover chain got out of sync")do { if (!(nsContentUtils::ContentIsFlattenedTreeDescendantOf
(leaf, aContentRemoved))) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"Flat tree and active / hover chain got out of sync", "nsContentUtils::ContentIsFlattenedTreeDescendantOf(leaf, aContentRemoved)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 7019
); MOZ_PretendNoReturn(); } } while (0)
;
7020
7021 nsIContent* newLeaf = aContentRemoved->GetFlattenedTreeParent();
7022 MOZ_ASSERT(!newLeaf || newLeaf->IsElement())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!newLeaf || newLeaf->IsElement())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!newLeaf || newLeaf->IsElement
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!newLeaf || newLeaf->IsElement()", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7022); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!newLeaf || newLeaf->IsElement()"
")"); do { MOZ_CrashSequence(__null, 7022); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7023 NS_ASSERTION(!newLeaf || newLeaf->AsElement()->State().HasState(aState),do { if (!(!newLeaf || newLeaf->AsElement()->State().HasState
(aState))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "State got out of sync because of shadow DOM"
, "!newLeaf || newLeaf->AsElement()->State().HasState(aState)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 7024
); MOZ_PretendNoReturn(); } } while (0)
7024 "State got out of sync because of shadow DOM")do { if (!(!newLeaf || newLeaf->AsElement()->State().HasState
(aState))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "State got out of sync because of shadow DOM"
, "!newLeaf || newLeaf->AsElement()->State().HasState(aState)"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 7024
); MOZ_PretendNoReturn(); } } while (0)
;
7025 if (aNotify) {
7026 SetContentState(newLeaf, aState);
7027 } else {
7028 // We don't update the removed content's state here, since removing NAC
7029 // happens from layout and we don't really want to notify at that point or
7030 // what not.
7031 //
7032 // Also, NAC is not observable and NAC being removed will go away soon.
7033 leaf = newLeaf;
7034 }
7035 MOZ_ASSERT(leaf == newLeaf || (aState == ElementState::ACTIVE && !leaf &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(leaf == newLeaf || (aState == ElementState::ACTIVE &&
!leaf && !CanContentHaveActiveState(*newLeaf)))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(leaf == newLeaf || (aState == ElementState::ACTIVE &&
!leaf && !CanContentHaveActiveState(*newLeaf))))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("leaf == newLeaf || (aState == ElementState::ACTIVE && !leaf && !CanContentHaveActiveState(*newLeaf))"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 7036
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "leaf == newLeaf || (aState == ElementState::ACTIVE && !leaf && !CanContentHaveActiveState(*newLeaf))"
")"); do { MOZ_CrashSequence(__null, 7036); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7036 !CanContentHaveActiveState(*newLeaf)))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(leaf == newLeaf || (aState == ElementState::ACTIVE &&
!leaf && !CanContentHaveActiveState(*newLeaf)))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(leaf == newLeaf || (aState == ElementState::ACTIVE &&
!leaf && !CanContentHaveActiveState(*newLeaf))))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("leaf == newLeaf || (aState == ElementState::ACTIVE && !leaf && !CanContentHaveActiveState(*newLeaf))"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 7036
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "leaf == newLeaf || (aState == ElementState::ACTIVE && !leaf && !CanContentHaveActiveState(*newLeaf))"
")"); do { MOZ_CrashSequence(__null, 7036); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7037}
7038
7039void EventStateManager::NativeAnonymousContentRemoved(nsIContent* aContent) {
7040 MOZ_ASSERT(aContent->IsRootOfNativeAnonymousSubtree())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aContent->IsRootOfNativeAnonymousSubtree())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aContent->IsRootOfNativeAnonymousSubtree()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("aContent->IsRootOfNativeAnonymousSubtree()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 7040
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsRootOfNativeAnonymousSubtree()"
")"); do { MOZ_CrashSequence(__null, 7040); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7041 RemoveNodeFromChainIfNeeded(ElementState::HOVER, aContent, false);
7042 RemoveNodeFromChainIfNeeded(ElementState::ACTIVE, aContent, false);
7043
7044 nsCOMPtr<nsIContent>& lastLeftMouseDownContent =
7045 mLastPrimaryButtonPressInfo.mConnectedDownContent;
7046 if (lastLeftMouseDownContent &&
7047 nsContentUtils::ContentIsFlattenedTreeDescendantOf(
7048 lastLeftMouseDownContent, aContent)) {
7049 lastLeftMouseDownContent = aContent->GetFlattenedTreeParent();
7050 }
7051
7052 nsCOMPtr<nsIContent>& lastMiddleMouseDownContent =
7053 mLastMiddleButtonPressInfo.mConnectedDownContent;
7054 if (lastMiddleMouseDownContent &&
7055 nsContentUtils::ContentIsFlattenedTreeDescendantOf(
7056 lastMiddleMouseDownContent, aContent)) {
7057 lastMiddleMouseDownContent = aContent->GetFlattenedTreeParent();
7058 }
7059
7060 nsCOMPtr<nsIContent>& lastRightMouseDownContent =
7061 mLastSecondaryButtonPressInfo.mConnectedDownContent;
7062 if (lastRightMouseDownContent &&
7063 nsContentUtils::ContentIsFlattenedTreeDescendantOf(
7064 lastRightMouseDownContent, aContent)) {
7065 lastRightMouseDownContent = aContent->GetFlattenedTreeParent();
7066 }
7067}
7068
7069void EventStateManager::ContentInserted(nsIContent* aChild,
7070 const ContentInsertInfo& aInfo) {
7071 if (nsFocusManager* fm = nsFocusManager::GetFocusManager()) {
7072 fm->ContentInserted(aChild, aInfo);
7073 }
7074}
7075void EventStateManager::ContentAppended(nsIContent* aFirstNewContent,
7076 const ContentAppendInfo& aInfo) {
7077 if (nsFocusManager* fm = nsFocusManager::GetFocusManager()) {
7078 fm->ContentAppended(aFirstNewContent, aInfo);
7079 }
7080}
7081
7082void EventStateManager::ContentRemoved(Document* aDocument,
7083 nsIContent* aContent,
7084 const ContentRemoveInfo& aInfo) {
7085 /*
7086 * Anchor and area elements when focused or hovered might make the UI to show
7087 * the current link. We want to make sure that the UI gets informed when they
7088 * are actually removed from the DOM.
7089 */
7090 if (aContent->IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area) &&
7091 (aContent->AsElement()->State().HasAtLeastOneOfStates(
7092 ElementState::FOCUS | ElementState::HOVER))) {
7093 Element* element = aContent->AsElement();
7094 element->LeaveLink(element->GetPresContext(Element::eForComposedDoc));
7095 }
7096
7097 if (aContent->IsElement()) {
7098 if (RefPtr<nsPresContext> presContext = mPresContext) {
7099 IMEStateManager::OnRemoveContent(*presContext,
7100 MOZ_KnownLive(*aContent->AsElement())(*aContent->AsElement()));
7101 }
7102 WheelTransaction::OnRemoveElement(aContent);
7103 }
7104
7105 // inform the focus manager that the content is being removed. If this
7106 // content is focused, the focus will be removed without firing events.
7107 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
7108 fm->ContentRemoved(aDocument, aContent, aInfo);
7109 }
7110
7111 RemoveNodeFromChainIfNeeded(ElementState::HOVER, aContent, true);
7112 RemoveNodeFromChainIfNeeded(ElementState::ACTIVE, aContent, true);
7113
7114 if (sDragOverContent &&
7115 sDragOverContent->OwnerDoc() == aContent->OwnerDoc() &&
7116 nsContentUtils::ContentIsFlattenedTreeDescendantOf(sDragOverContent,
7117 aContent)) {
7118 sDragOverContent = nullptr;
7119 }
7120
7121 if (!aInfo.mNewParent) {
7122 PointerEventHandler::ReleaseIfCaptureByDescendant(aContent);
7123 }
7124
7125 if (mMouseEnterLeaveHelper) {
7126 const bool hadMouseOutTarget =
7127 mMouseEnterLeaveHelper->GetOutEventTarget() != nullptr;
7128 mMouseEnterLeaveHelper->ContentRemoved(*aContent);
7129 if (hadMouseOutTarget && !mMouseEnterLeaveHelper->GetOutEventTarget()) {
7130 if (PresShell* const presShell =
7131 mPresContext ? mPresContext->GetPresShell() : nullptr) {
7132 // If we lose the mouseout target, we need to dispatch mouseover on an
7133 // ancestor. For ensuring the chance to do it before next user input,
7134 // we need a synthetic mouse move.
7135 const bool requiresToSynthesizeMouseMove = [&]() {
7136 // If the last mouse event is caused by a pointing device which does
7137 // not support hover state and it's inactive, we don't need to
7138 // synthesize mouse move.
7139 const PointerInfo* const lastMouseInfo =
7140 PointerEventHandler::GetLastMouseInfo();
7141 return lastMouseInfo && (lastMouseInfo->InputSourceSupportsHover() ||
7142 lastMouseInfo->mIsActive);
7143 }();
7144 if (requiresToSynthesizeMouseMove) {
7145 presShell->SynthesizeMouseMove(false);
7146 }
7147 }
7148 }
7149 }
7150 for (const auto& entry : mPointersEnterLeaveHelper) {
7151 if (entry.GetData()) {
7152 entry.GetData()->ContentRemoved(*aContent);
7153 }
7154 }
7155
7156 NotifyContentWillBeRemovedForGesture(*aContent);
7157}
7158
7159bool EventStateManager::EventStatusOK(WidgetGUIEvent* aEvent) {
7160 return !(aEvent->mMessage == eMouseDown &&
7161 aEvent->AsMouseEvent()->mButton == MouseButton::ePrimary &&
7162 !sNormalLMouseEventInProcess);
7163}
7164
7165//-------------------------------------------
7166// Access Key Registration
7167//-------------------------------------------
7168void EventStateManager::RegisterAccessKey(Element* aElement, uint32_t aKey) {
7169 if (aElement && !mAccessKeys.Contains(aElement)) {
7170 mAccessKeys.AppendObject(aElement);
7171 }
7172}
7173
7174void EventStateManager::UnregisterAccessKey(Element* aElement, uint32_t aKey) {
7175 if (aElement) {
7176 mAccessKeys.RemoveObject(aElement);
7177 }
7178}
7179
7180uint32_t EventStateManager::GetRegisteredAccessKey(Element* aElement) {
7181 MOZ_ASSERT(aElement)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElement)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aElement))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aElement", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7181); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { MOZ_CrashSequence(__null, 7181); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7182
7183 if (!mAccessKeys.Contains(aElement)) {
7184 return 0;
7185 }
7186
7187 nsAutoString accessKey;
7188 aElement->GetAttr(nsGkAtoms::accesskey, accessKey);
7189 return accessKey.First();
7190}
7191
7192PresShell* EventStateManager::GetRootPresShell() const {
7193 PresShell* const presShell = GetPresShell();
7194 return presShell ? presShell->GetRootPresShell() : nullptr;
7195}
7196
7197void EventStateManager::EnsureDocument(nsPresContext* aPresContext) {
7198 if (!mDocument) mDocument = aPresContext->Document();
7199}
7200
7201void EventStateManager::FlushLayout(nsPresContext* aPresContext) {
7202 MOZ_ASSERT(aPresContext, "nullptr ptr")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPresContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPresContext))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aPresContext" " ("
"nullptr ptr" ")", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7202); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresContext"
") (" "nullptr ptr" ")"); do { MOZ_CrashSequence(__null, 7202
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
7203 if (RefPtr<PresShell> presShell = aPresContext->GetPresShell()) {
7204 presShell->FlushPendingNotifications(FlushType::InterruptibleLayout);
7205 }
7206}
7207
7208Element* EventStateManager::GetFocusedElement() {
7209 nsFocusManager* fm = nsFocusManager::GetFocusManager();
7210 EnsureDocument(mPresContext);
7211 if (!fm || !mDocument) {
7212 return nullptr;
7213 }
7214
7215 nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
7216 return nsFocusManager::GetFocusedDescendant(
7217 mDocument->GetWindow(), nsFocusManager::eOnlyCurrentWindow,
7218 getter_AddRefs(focusedWindow));
7219}
7220
7221//-------------------------------------------------------
7222// Return true if the docshell is visible
7223
7224bool EventStateManager::IsShellVisible(nsIDocShell* aShell) {
7225 NS_ASSERTION(aShell, "docshell is null")do { if (!(aShell)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "docshell is null"
, "aShell", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7225); MOZ_PretendNoReturn(); } } while (0)
;
7226
7227 nsCOMPtr<nsIBaseWindow> basewin = do_QueryInterface(aShell);
7228 if (!basewin) return true;
7229
7230 bool isVisible = true;
7231 basewin->GetVisibility(&isVisible);
7232
7233 // We should be doing some additional checks here so that
7234 // we don't tab into hidden tabs of tabbrowser. -bryner
7235
7236 return isVisible;
7237}
7238
7239nsresult EventStateManager::DoContentCommandEvent(
7240 WidgetContentCommandEvent* aEvent) {
7241 MOZ_DIAGNOSTIC_ASSERT(aEvent->DispatchedByValidDispatcher())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->DispatchedByValidDispatcher())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aEvent->DispatchedByValidDispatcher()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aEvent->DispatchedByValidDispatcher()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 7241
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aEvent->DispatchedByValidDispatcher()"
")"); do { MOZ_CrashSequence(__null, 7241); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7242
7243 EnsureDocument(mPresContext);
7244 NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocument" ") failed", nullptr
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 7244
); return NS_ERROR_FAILURE; } } while (false)
;
7245 nsCOMPtr<nsPIDOMWindowOuter> window(mDocument->GetWindow());
7246 NS_ENSURE_TRUE(window, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(window)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "window" ") failed", nullptr
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 7246
); return NS_ERROR_FAILURE; } } while (false)
;
7247
7248 nsCOMPtr<nsPIWindowRoot> root = window->GetTopWindowRoot();
7249 NS_ENSURE_TRUE(root, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(root)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "root" ") failed", nullptr
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 7249
); return NS_ERROR_FAILURE; } } while (false)
;
7250 const char* cmd;
7251 bool maybeNeedToHandleInRemote = false;
7252 switch (aEvent->mMessage) {
7253 case eContentCommandCut:
7254 cmd = "cmd_cut";
7255 maybeNeedToHandleInRemote = true;
7256 break;
7257 case eContentCommandCopy:
7258 cmd = "cmd_copy";
7259 maybeNeedToHandleInRemote = true;
7260 break;
7261 case eContentCommandPaste:
7262 cmd = "cmd_paste";
7263 maybeNeedToHandleInRemote = true;
7264 break;
7265 case eContentCommandDelete:
7266 cmd = "cmd_delete";
7267 maybeNeedToHandleInRemote = true;
7268 break;
7269 case eContentCommandUndo:
7270 cmd = "cmd_undo";
7271 maybeNeedToHandleInRemote = true;
7272 break;
7273 case eContentCommandRedo:
7274 cmd = "cmd_redo";
7275 maybeNeedToHandleInRemote = true;
7276 break;
7277 case eContentCommandPasteTransferable:
7278 cmd = "cmd_pasteTransferable";
7279 break;
7280 case eContentCommandLookUpDictionary:
7281 cmd = "cmd_lookUpDictionary";
7282 break;
7283 default:
7284 return NS_ERROR_NOT_IMPLEMENTED;
7285 }
7286 if (XRE_IsParentProcess() && maybeNeedToHandleInRemote) {
7287 if (BrowserParent* remote = BrowserParent::GetFocused()) {
7288 if (!aEvent->ShouldCheckEnabledOnly()) {
7289 remote->SendSimpleContentCommandEvent(*aEvent);
7290 }
7291 // XXX The command may be disabled in the parent process. Perhaps, we
7292 // should set actual enabled state in the parent process here and there
7293 // should be another bool flag which indicates whether the content is sent
7294 // to a remote process.
7295 aEvent->mIsEnabled = true;
7296 aEvent->mSucceeded = true;
7297 return NS_OK;
7298 }
7299 }
7300 // If user tries to do something, user must try to do it in visible window.
7301 // So, let's retrieve controller of visible window.
7302 nsCOMPtr<nsIController> controller;
7303 nsresult rv =
7304 root->GetControllerForCommand(cmd, true, getter_AddRefs(controller));
7305 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7305); return rv; } } while (false)
;
7306 if (!controller) {
7307 // When GetControllerForCommand succeeded but there is no controller, the
7308 // command isn't supported.
7309 aEvent->mIsEnabled = false;
7310 } else {
7311 bool canDoIt;
7312 rv = controller->IsCommandEnabled(cmd, &canDoIt);
7313 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7313); return rv; } } while (false)
;
7314 aEvent->mIsEnabled = canDoIt;
7315 if (canDoIt && !aEvent->ShouldCheckEnabledOnly()) {
7316 switch (aEvent->mMessage) {
7317 case eContentCommandPasteTransferable: {
7318 BrowserParent* remote = BrowserParent::GetFocused();
7319 if (remote) {
7320 IPCTransferable ipcTransferable;
7321 nsContentUtils::TransferableToIPCTransferable(
7322 aEvent->mTransferable, &ipcTransferable, false,
7323 remote->Manager());
7324 remote->SendPasteTransferable(std::move(ipcTransferable));
7325 rv = NS_OK;
7326 } else {
7327 nsCOMPtr<nsICommandController> commandController =
7328 do_QueryInterface(controller);
7329 NS_ENSURE_STATE(commandController)do { if ((__builtin_expect(!!(!(commandController)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "commandController" ") failed"
, nullptr, "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7329); return NS_ERROR_UNEXPECTED; } } while (false)
;
7330
7331 RefPtr<nsCommandParams> params = new nsCommandParams();
7332 rv = params->SetISupports("transferable", aEvent->mTransferable);
7333 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7333)
) {
7334 return rv;
7335 }
7336 rv = commandController->DoCommandWithParams(cmd, params);
7337 }
7338 break;
7339 }
7340
7341 case eContentCommandLookUpDictionary: {
7342 nsCOMPtr<nsICommandController> commandController =
7343 do_QueryInterface(controller);
7344 if (NS_WARN_IF(!commandController)NS_warn_if_impl(!commandController, "!commandController", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7344)
) {
7345 return NS_ERROR_FAILURE;
7346 }
7347
7348 RefPtr<nsCommandParams> params = new nsCommandParams();
7349 rv = params->SetInt("x", aEvent->mRefPoint.x);
7350 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7350)
) {
7351 return rv;
7352 }
7353
7354 rv = params->SetInt("y", aEvent->mRefPoint.y);
7355 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7355)
) {
7356 return rv;
7357 }
7358
7359 rv = commandController->DoCommandWithParams(cmd, params);
7360 break;
7361 }
7362
7363 default:
7364 rv = controller->DoCommand(cmd);
7365 break;
7366 }
7367 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7367); return rv; } } while (false)
;
7368 }
7369 }
7370 aEvent->mSucceeded = true;
7371 return NS_OK;
7372}
7373
7374nsresult EventStateManager::DoContentCommandInsertTextEvent(
7375 WidgetContentCommandEvent* aEvent) {
7376 MOZ_ASSERT(aEvent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aEvent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aEvent", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7376); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent" ")"
); do { MOZ_CrashSequence(__null, 7376); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7377 MOZ_ASSERT(aEvent->mMessage == eContentCommandInsertText)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->mMessage == eContentCommandInsertText)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aEvent->mMessage == eContentCommandInsertText))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("aEvent->mMessage == eContentCommandInsertText"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 7377
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == eContentCommandInsertText"
")"); do { MOZ_CrashSequence(__null, 7377); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7378 MOZ_DIAGNOSTIC_ASSERT(aEvent->DispatchedByValidDispatcher())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->DispatchedByValidDispatcher())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aEvent->DispatchedByValidDispatcher()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aEvent->DispatchedByValidDispatcher()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 7378
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aEvent->DispatchedByValidDispatcher()"
")"); do { MOZ_CrashSequence(__null, 7378); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7379 MOZ_DIAGNOSTIC_ASSERT(aEvent->mString.isSome())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->mString.isSome())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aEvent->mString.isSome())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aEvent->mString.isSome()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 7379
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aEvent->mString.isSome()"
")"); do { MOZ_CrashSequence(__null, 7379); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7380 MOZ_DIAGNOSTIC_ASSERT(!aEvent->mString.ref().IsEmpty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aEvent->mString.ref().IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aEvent->mString.ref().IsEmpty
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aEvent->mString.ref().IsEmpty()", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7380); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!aEvent->mString.ref().IsEmpty()"
")"); do { MOZ_CrashSequence(__null, 7380); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7381
7382 aEvent->mIsEnabled = false;
7383 aEvent->mSucceeded = false;
7384
7385 NS_ENSURE_TRUE(mPresContext, NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(mPresContext)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mPresContext" ") failed"
, nullptr, "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7385); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
7386
7387 if (XRE_IsParentProcess()) {
7388 // Handle it in focused content process if there is.
7389 if (BrowserParent* remote = BrowserParent::GetFocused()) {
7390 if (!aEvent->ShouldCheckEnabledOnly()) {
7391 remote->SendInsertText(*aEvent);
7392 }
7393 // XXX The remote process may be not editable right now. Therefore, this
7394 // may be different from actual state in the remote process.
7395 aEvent->mIsEnabled = true;
7396 aEvent->mSucceeded = true;
7397 return NS_OK;
7398 }
7399 }
7400
7401 // If there is no active editor in this process, we should treat the command
7402 // is disabled.
7403 RefPtr<EditorBase> activeEditor =
7404 nsContentUtils::GetActiveEditor(mPresContext);
7405 if (!activeEditor) {
7406 aEvent->mSucceeded = true;
7407 return NS_OK;
7408 }
7409
7410 if (aEvent->ShouldCheckEnabledOnly()) {
7411 aEvent->mIsEnabled = !activeEditor->IsReadonly();
7412 aEvent->mSucceeded = true;
7413 return NS_OK;
7414 }
7415
7416 nsresult rv = activeEditor->InsertTextAsAction(aEvent->mString.ref());
7417 aEvent->mIsEnabled = rv != NS_SUCCESS_DOM_NO_OPERATION;
7418 aEvent->mSucceeded = NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)));
7419 return NS_OK;
7420}
7421
7422nsresult EventStateManager::DoContentCommandReplaceTextEvent(
7423 WidgetContentCommandEvent* aEvent) {
7424 MOZ_ASSERT(aEvent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aEvent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aEvent", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7424); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent" ")"
); do { MOZ_CrashSequence(__null, 7424); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7425 MOZ_ASSERT(aEvent->mMessage == eContentCommandReplaceText)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->mMessage == eContentCommandReplaceText)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aEvent->mMessage == eContentCommandReplaceText)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("aEvent->mMessage == eContentCommandReplaceText"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 7425
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent->mMessage == eContentCommandReplaceText"
")"); do { MOZ_CrashSequence(__null, 7425); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7426 MOZ_DIAGNOSTIC_ASSERT(aEvent->DispatchedByValidDispatcher())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->DispatchedByValidDispatcher())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aEvent->DispatchedByValidDispatcher()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aEvent->DispatchedByValidDispatcher()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 7426
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aEvent->DispatchedByValidDispatcher()"
")"); do { MOZ_CrashSequence(__null, 7426); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7427 MOZ_DIAGNOSTIC_ASSERT(aEvent->mString.isSome())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent->mString.isSome())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aEvent->mString.isSome())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aEvent->mString.isSome()"
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 7427
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aEvent->mString.isSome()"
")"); do { MOZ_CrashSequence(__null, 7427); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7428 MOZ_DIAGNOSTIC_ASSERT(!aEvent->mString.ref().IsEmpty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aEvent->mString.ref().IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aEvent->mString.ref().IsEmpty
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aEvent->mString.ref().IsEmpty()", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7428); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!aEvent->mString.ref().IsEmpty()"
")"); do { MOZ_CrashSequence(__null, 7428); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7429
7430 aEvent->mIsEnabled = false;
7431 aEvent->mSucceeded = false;
7432
7433 NS_ENSURE_TRUE(mPresContext, NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(mPresContext)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mPresContext" ") failed"
, nullptr, "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7433); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
7434
7435 if (XRE_IsParentProcess()) {
7436 // Handle it in focused content process if there is.
7437 if (BrowserParent* remote = BrowserParent::GetFocused()) {
7438 if (!aEvent->ShouldCheckEnabledOnly()) {
7439 (void)remote->SendReplaceText(*aEvent);
7440 }
7441 // XXX The remote process may be not editable right now. Therefore, this
7442 // may be different from actual state in the remote process.
7443 aEvent->mIsEnabled = true;
7444 aEvent->mSucceeded = true;
7445 return NS_OK;
7446 }
7447 }
7448
7449 // If there is no active editor in this process, we should treat the command
7450 // is disabled.
7451 RefPtr<EditorBase> activeEditor =
7452 nsContentUtils::GetActiveEditor(mPresContext);
7453 if (NS_WARN_IF(!activeEditor)NS_warn_if_impl(!activeEditor, "!activeEditor", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7453)
) {
7454 aEvent->mSucceeded = true;
7455 return NS_OK;
7456 }
7457
7458 RefPtr<TextComposition> composition =
7459 IMEStateManager::GetTextCompositionFor(mPresContext);
7460 if (NS_WARN_IF(composition)NS_warn_if_impl(composition, "composition", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7460)
) {
7461 // We don't support replace text action during composition.
7462 aEvent->mSucceeded = true;
7463 return NS_OK;
7464 }
7465
7466 // Don't try to compute range in DOM from text offsets for EditContext,
7467 // since it will often be incorrect.
7468 if (RefPtr editContext = activeEditor->ComputeEditContext()) {
7469 editContext->DoContentCommandReplaceText(*aEvent);
7470 return NS_OK;
7471 }
7472
7473 ContentEventHandler handler(mPresContext);
7474 RefPtr<dom::Range> range = handler.GetRangeFromFlatTextOffset(
7475 aEvent, aEvent->mSelection.mOffset,
7476 aEvent->mSelection.mReplaceSrcString.Length());
7477 if (NS_WARN_IF(!range)NS_warn_if_impl(!range, "!range", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7477)
) {
7478 aEvent->mSucceeded = false;
7479 return NS_OK;
7480 }
7481
7482 // If original replacement text isn't matched with selection text, throws
7483 // error.
7484 nsAutoString targetStr;
7485 nsresult rv = handler.GenerateFlatTextContent(range, targetStr);
7486 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7486)
) {
7487 aEvent->mSucceeded = false;
7488 return NS_OK;
7489 }
7490 if (!aEvent->mSelection.mReplaceSrcString.Equals(targetStr)) {
7491 aEvent->mSucceeded = false;
7492 return NS_OK;
7493 }
7494
7495 if (aEvent->ShouldCheckEnabledOnly()) {
7496 aEvent->mIsEnabled = !activeEditor->IsReadonly();
7497 aEvent->mSucceeded = true;
7498 return NS_OK;
7499 }
7500
7501 rv = activeEditor->ReplaceTextAsAction(
7502 aEvent->mString.ref(), range,
7503 TextEditor::AllowBeforeInputEventCancelable::Yes,
7504 aEvent->mSelection.mPreventSetSelection);
7505 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7505)
) {
7506 aEvent->mSucceeded = false;
7507 return NS_OK;
7508 }
7509
7510 aEvent->mIsEnabled = rv != NS_SUCCESS_DOM_NO_OPERATION;
7511 aEvent->mSucceeded = true;
7512 return NS_OK;
7513}
7514
7515nsresult EventStateManager::DoContentCommandScrollEvent(
7516 WidgetContentCommandEvent* aEvent) {
7517 NS_ENSURE_TRUE(mPresContext, NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(mPresContext)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mPresContext" ") failed"
, nullptr, "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7517); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
7518 PresShell* presShell = mPresContext->GetPresShell();
7519 NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(presShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presShell" ") failed", nullptr
, "/root/firefox-clang/dom/events/EventStateManager.cpp", 7519
); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
7520 NS_ENSURE_TRUE(aEvent->mScroll.mAmount != 0, NS_ERROR_INVALID_ARG)do { if ((__builtin_expect(!!(!(aEvent->mScroll.mAmount !=
0)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"aEvent->mScroll.mAmount != 0" ") failed", nullptr, "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7520); return NS_ERROR_INVALID_ARG; } } while (false)
;
7521
7522 ScrollUnit scrollUnit;
7523 switch (aEvent->mScroll.mUnit) {
7524 case WidgetContentCommandEvent::eCmdScrollUnit_Line:
7525 scrollUnit = ScrollUnit::LINES;
7526 break;
7527 case WidgetContentCommandEvent::eCmdScrollUnit_Page:
7528 scrollUnit = ScrollUnit::PAGES;
7529 break;
7530 case WidgetContentCommandEvent::eCmdScrollUnit_Whole:
7531 scrollUnit = ScrollUnit::WHOLE;
7532 break;
7533 default:
7534 return NS_ERROR_INVALID_ARG;
7535 }
7536
7537 aEvent->mSucceeded = true;
7538
7539 ScrollContainerFrame* sf =
7540 presShell->GetScrollContainerFrameToScroll(layers::EitherScrollDirection);
7541 aEvent->mIsEnabled =
7542 sf ? (aEvent->mScroll.mIsHorizontal ? WheelHandlingUtils::CanScrollOn(
7543 sf, aEvent->mScroll.mAmount, 0)
7544 : WheelHandlingUtils::CanScrollOn(
7545 sf, 0, aEvent->mScroll.mAmount))
7546 : false;
7547
7548 if (!aEvent->mIsEnabled || aEvent->ShouldCheckEnabledOnly()) {
7549 return NS_OK;
7550 }
7551
7552 nsIntPoint pt(0, 0);
7553 if (aEvent->mScroll.mIsHorizontal) {
7554 pt.x = aEvent->mScroll.mAmount;
7555 } else {
7556 pt.y = aEvent->mScroll.mAmount;
7557 }
7558
7559 // The caller may want synchronous scrolling.
7560 sf->ScrollBy(pt, scrollUnit, ScrollMode::Instant);
7561 return NS_OK;
7562}
7563
7564void EventStateManager::SetActiveManager(EventStateManager* aNewESM,
7565 nsIContent* aContent) {
7566 if (sActiveESM && aNewESM != sActiveESM) {
7567 sActiveESM->SetContentState(nullptr, ElementState::ACTIVE);
7568 }
7569 sActiveESM = aNewESM;
7570 if (sActiveESM && aContent) {
7571 sActiveESM->SetContentState(aContent, ElementState::ACTIVE);
7572 }
7573}
7574
7575void EventStateManager::ClearGlobalActiveContent(EventStateManager* aClearer) {
7576 if (aClearer) {
7577 aClearer->SetContentState(nullptr, ElementState::ACTIVE);
7578 if (sDragOverContent) {
7579 aClearer->SetContentState(nullptr, ElementState::DRAGOVER);
7580 }
7581 }
7582 if (sActiveESM && aClearer != sActiveESM) {
7583 sActiveESM->SetContentState(nullptr, ElementState::ACTIVE);
7584 }
7585 sActiveESM = nullptr;
7586}
7587
7588/******************************************************************/
7589/* mozilla::EventStateManager::DeltaAccumulator */
7590/******************************************************************/
7591
7592void EventStateManager::DeltaAccumulator::InitLineOrPageDelta(
7593 nsIFrame* aTargetFrame, EventStateManager* aESM, WidgetWheelEvent* aEvent) {
7594 MOZ_ASSERT(aESM)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aESM)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aESM))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aESM", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7594); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aESM" ")");
do { MOZ_CrashSequence(__null, 7594); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7595 MOZ_ASSERT(aEvent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aEvent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aEvent", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7595); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent" ")"
); do { MOZ_CrashSequence(__null, 7595); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7596
7597 // Reset if the previous wheel event is too old.
7598 if (!mLastTime.IsNull()) {
7599 TimeDuration duration = TimeStamp::Now() - mLastTime;
7600 if (duration.ToMilliseconds() >
7601 StaticPrefs::mousewheel_transaction_timeout()) {
7602 Reset();
7603 }
7604 }
7605 // If we have accumulated delta, we may need to reset it.
7606 if (IsInTransaction()) {
7607 // If wheel event type is changed, reset the values.
7608 if (mHandlingDeltaMode != aEvent->mDeltaMode ||
7609 mIsNoLineOrPageDeltaDevice != aEvent->mIsNoLineOrPageDelta) {
7610 Reset();
7611 } else {
7612 // If the delta direction is changed, we should reset only the
7613 // accumulated values.
7614 if (mX && aEvent->mDeltaX && ((aEvent->mDeltaX > 0.0) != (mX > 0.0))) {
7615 mX = mPendingScrollAmountX = 0.0;
7616 }
7617 if (mY && aEvent->mDeltaY && ((aEvent->mDeltaY > 0.0) != (mY > 0.0))) {
7618 mY = mPendingScrollAmountY = 0.0;
7619 }
7620 }
7621 }
7622
7623 mHandlingDeltaMode = aEvent->mDeltaMode;
7624 mIsNoLineOrPageDeltaDevice = aEvent->mIsNoLineOrPageDelta;
7625
7626 {
7627 ScrollContainerFrame* scrollTarget = aESM->ComputeScrollTarget(
7628 aTargetFrame, aEvent, COMPUTE_DEFAULT_ACTION_TARGET);
7629 nsPresContext* pc = scrollTarget ? scrollTarget->PresContext()
7630 : aTargetFrame->PresContext();
7631 aEvent->mScrollAmount = aESM->GetScrollAmount(pc, aEvent, scrollTarget);
7632 }
7633
7634 // If it's handling neither a device that does not provide line or page deltas
7635 // nor delta values multiplied by prefs, we must not modify lineOrPageDelta
7636 // values.
7637 // TODO(emilio): Does this care about overridden scroll speed?
7638 if (!mIsNoLineOrPageDeltaDevice &&
7639 !EventStateManager::WheelPrefs::GetInstance()
7640 ->NeedToComputeLineOrPageDelta(aEvent)) {
7641 // Set the delta values to mX and mY. They would be used when above block
7642 // resets mX/mY/mPendingScrollAmountX/mPendingScrollAmountY if the direction
7643 // is changed.
7644 // NOTE: We shouldn't accumulate the delta values, it might could cause
7645 // overflow even though it's not a realistic situation.
7646 if (aEvent->mDeltaX) {
7647 mX = aEvent->mDeltaX;
7648 }
7649 if (aEvent->mDeltaY) {
7650 mY = aEvent->mDeltaY;
7651 }
7652 mLastTime = TimeStamp::Now();
7653 return;
7654 }
7655
7656 mX += aEvent->mDeltaX;
7657 mY += aEvent->mDeltaY;
7658
7659 if (mHandlingDeltaMode == WheelEvent_Binding::DOM_DELTA_PIXEL) {
7660 // Records pixel delta values and init mLineOrPageDeltaX and
7661 // mLineOrPageDeltaY for wheel events which are caused by pixel only
7662 // devices. Ignore mouse wheel transaction for computing this. The
7663 // lineOrPageDelta values will be used by dispatching legacy
7664 // eMouseScrollEventClass (DOMMouseScroll) but not be used for scrolling
7665 // of default action. The transaction should be used only for the default
7666 // action.
7667 auto scrollAmountInCSSPixels =
7668 CSSIntSize::FromAppUnitsRounded(aEvent->mScrollAmount);
7669
7670 aEvent->mLineOrPageDeltaX = RoundDown(mX) / scrollAmountInCSSPixels.width;
7671 aEvent->mLineOrPageDeltaY = RoundDown(mY) / scrollAmountInCSSPixels.height;
7672
7673 mX -= aEvent->mLineOrPageDeltaX * scrollAmountInCSSPixels.width;
7674 mY -= aEvent->mLineOrPageDeltaY * scrollAmountInCSSPixels.height;
7675 } else {
7676 aEvent->mLineOrPageDeltaX = RoundDown(mX);
7677 aEvent->mLineOrPageDeltaY = RoundDown(mY);
7678 mX -= aEvent->mLineOrPageDeltaX;
7679 mY -= aEvent->mLineOrPageDeltaY;
7680 }
7681
7682 mLastTime = TimeStamp::Now();
7683}
7684
7685void EventStateManager::DeltaAccumulator::Reset() {
7686 mX = mY = 0.0;
7687 mPendingScrollAmountX = mPendingScrollAmountY = 0.0;
7688 mHandlingDeltaMode = UINT32_MAX(4294967295U);
7689 mIsNoLineOrPageDeltaDevice = false;
7690}
7691
7692nsIntPoint
7693EventStateManager::DeltaAccumulator::ComputeScrollAmountForDefaultAction(
7694 WidgetWheelEvent* aEvent, const nsIntSize& aScrollAmountInDevPixels) {
7695 MOZ_ASSERT(aEvent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aEvent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aEvent", "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7695); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent" ")"
); do { MOZ_CrashSequence(__null, 7695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7696
7697 DeltaValues acceleratedDelta = WheelTransaction::AccelerateWheelDelta(aEvent);
7698
7699 nsIntPoint result(0, 0);
7700 if (aEvent->mDeltaMode == WheelEvent_Binding::DOM_DELTA_PIXEL) {
7701 mPendingScrollAmountX += acceleratedDelta.deltaX;
7702 mPendingScrollAmountY += acceleratedDelta.deltaY;
7703 } else {
7704 mPendingScrollAmountX +=
7705 aScrollAmountInDevPixels.width * acceleratedDelta.deltaX;
7706 mPendingScrollAmountY +=
7707 aScrollAmountInDevPixels.height * acceleratedDelta.deltaY;
7708 }
7709 result.x = RoundDown(mPendingScrollAmountX);
7710 result.y = RoundDown(mPendingScrollAmountY);
7711 mPendingScrollAmountX -= result.x;
7712 mPendingScrollAmountY -= result.y;
7713
7714 return result;
7715}
7716
7717/******************************************************************/
7718/* mozilla::EventStateManager::WheelPrefs */
7719/******************************************************************/
7720
7721// static
7722EventStateManager::WheelPrefs* EventStateManager::WheelPrefs::GetInstance() {
7723 if (!sInstance) {
7724 sInstance = new WheelPrefs();
7725 }
7726 return sInstance;
7727}
7728
7729// static
7730void EventStateManager::WheelPrefs::Shutdown() {
7731 delete sInstance;
7732 sInstance = nullptr;
7733}
7734
7735// static
7736void EventStateManager::WheelPrefs::OnPrefChanged(const char* aPrefName,
7737 void* aClosure) {
7738 // forget all prefs, it's not problem for performance.
7739 sInstance->Reset();
7740 DeltaAccumulator::GetInstance()->Reset();
7741}
7742
7743EventStateManager::WheelPrefs::WheelPrefs() {
7744 Reset();
7745 Preferences::RegisterPrefixCallback(OnPrefChanged, "mousewheel.");
7746}
7747
7748EventStateManager::WheelPrefs::~WheelPrefs() {
7749 Preferences::UnregisterPrefixCallback(OnPrefChanged, "mousewheel.");
7750}
7751
7752void EventStateManager::WheelPrefs::Reset() { memset(mInit, 0, sizeof(mInit)); }
7753
7754EventStateManager::WheelPrefs::Index EventStateManager::WheelPrefs::GetIndexFor(
7755 const WidgetWheelEvent* aEvent) {
7756 if (!aEvent) {
7757 return INDEX_DEFAULT;
7758 }
7759
7760 Modifiers modifiers = (aEvent->mModifiers & (MODIFIER_ALT | MODIFIER_CONTROL |
7761 MODIFIER_META | MODIFIER_SHIFT));
7762
7763 switch (modifiers) {
7764 case MODIFIER_ALT:
7765 return INDEX_ALT;
7766 case MODIFIER_CONTROL:
7767 return INDEX_CONTROL;
7768 case MODIFIER_META:
7769 return INDEX_META;
7770 case MODIFIER_SHIFT:
7771 return INDEX_SHIFT;
7772 default:
7773 // If two or more modifier keys are pressed, we should use default
7774 // settings.
7775 return INDEX_DEFAULT;
7776 }
7777}
7778
7779void EventStateManager::WheelPrefs::GetBasePrefName(
7780 EventStateManager::WheelPrefs::Index aIndex, nsACString& aBasePrefName) {
7781 aBasePrefName.AssignLiteral("mousewheel.");
7782 switch (aIndex) {
7783 case INDEX_ALT:
7784 aBasePrefName.AppendLiteral("with_alt.");
7785 break;
7786 case INDEX_CONTROL:
7787 aBasePrefName.AppendLiteral("with_control.");
7788 break;
7789 case INDEX_META:
7790 aBasePrefName.AppendLiteral("with_meta.");
7791 break;
7792 case INDEX_SHIFT:
7793 aBasePrefName.AppendLiteral("with_shift.");
7794 break;
7795 case INDEX_DEFAULT:
7796 default:
7797 aBasePrefName.AppendLiteral("default.");
7798 break;
7799 }
7800}
7801
7802void EventStateManager::WheelPrefs::Init(
7803 EventStateManager::WheelPrefs::Index aIndex) {
7804 if (mInit[aIndex]) {
7805 return;
7806 }
7807 mInit[aIndex] = true;
7808
7809 nsAutoCString basePrefName;
7810 GetBasePrefName(aIndex, basePrefName);
7811
7812 nsAutoCString prefNameX(basePrefName);
7813 prefNameX.AppendLiteral("delta_multiplier_x");
7814 mMultiplierX[aIndex] =
7815 static_cast<double>(Preferences::GetInt(prefNameX.get(), 100)) / 100;
7816
7817 nsAutoCString prefNameY(basePrefName);
7818 prefNameY.AppendLiteral("delta_multiplier_y");
7819 mMultiplierY[aIndex] =
7820 static_cast<double>(Preferences::GetInt(prefNameY.get(), 100)) / 100;
7821
7822 nsAutoCString prefNameZ(basePrefName);
7823 prefNameZ.AppendLiteral("delta_multiplier_z");
7824 mMultiplierZ[aIndex] =
7825 static_cast<double>(Preferences::GetInt(prefNameZ.get(), 100)) / 100;
7826
7827 nsAutoCString prefNameAction(basePrefName);
7828 prefNameAction.AppendLiteral("action");
7829 int32_t action = Preferences::GetInt(prefNameAction.get(), ACTION_SCROLL);
7830 if (action < int32_t(ACTION_NONE) || action > int32_t(ACTION_LAST)) {
7831 NS_WARNING("Unsupported action pref value, replaced with 'Scroll'.")NS_DebugBreak(NS_DEBUG_WARNING, "Unsupported action pref value, replaced with 'Scroll'."
, nullptr, "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7831)
;
7832 action = ACTION_SCROLL;
7833 }
7834 mActions[aIndex] = static_cast<Action>(action);
7835
7836 // Compute action values overridden by .override_x pref.
7837 // At present, override is possible only for the x-direction
7838 // because this pref is introduced mainly for tilt wheels.
7839 // Note that ACTION_HORIZONTALIZED_SCROLL isn't a valid value for this pref
7840 // because it affects only to deltaY.
7841 prefNameAction.AppendLiteral(".override_x");
7842 int32_t actionOverrideX = Preferences::GetInt(prefNameAction.get(), -1);
7843 if (actionOverrideX < -1 || actionOverrideX > int32_t(ACTION_LAST) ||
7844 actionOverrideX == ACTION_HORIZONTALIZED_SCROLL) {
7845 NS_WARNING("Unsupported action override pref value, didn't override.")NS_DebugBreak(NS_DEBUG_WARNING, "Unsupported action override pref value, didn't override."
, nullptr, "/root/firefox-clang/dom/events/EventStateManager.cpp"
, 7845)
;
7846 actionOverrideX = -1;
7847 }
7848 mOverriddenActionsX[aIndex] = (actionOverrideX == -1)
7849 ? static_cast<Action>(action)
7850 : static_cast<Action>(actionOverrideX);
7851}
7852
7853void EventStateManager::WheelPrefs::GetMultiplierForDeltaXAndY(
7854 const WidgetWheelEvent* aEvent, Index aIndex, double* aMultiplierForDeltaX,
7855 double* aMultiplierForDeltaY) {
7856 *aMultiplierForDeltaX = mMultiplierX[aIndex];
7857 *aMultiplierForDeltaY = mMultiplierY[aIndex];
7858 // If the event has been horizontalized(I.e. treated as a horizontal wheel
7859 // scroll for a vertical wheel scroll), then we should swap mMultiplierX and
7860 // mMultiplierY. By doing this, multipliers will still apply to the delta
7861 // values they origianlly corresponded to.
7862 if (aEvent->mDeltaValuesHorizontalizedForDefaultHandler &&
7863 ComputeActionFor(aEvent) == ACTION_HORIZONTALIZED_SCROLL) {
7864 std::swap(*aMultiplierForDeltaX, *aMultiplierForDeltaY);
7865 }
7866}
7867
7868void EventStateManager::WheelPrefs::ApplyUserPrefsToDelta(
7869 WidgetWheelEvent* aEvent) {
7870 if (aEvent->mCustomizedByUserPrefs) {
7871 return;
7872 }
7873
7874 Index index = GetIndexFor(aEvent);
7875 Init(index);
7876
7877 double multiplierForDeltaX = 1.0, multiplierForDeltaY = 1.0;
7878 GetMultiplierForDeltaXAndY(aEvent, index, &multiplierForDeltaX,
7879 &multiplierForDeltaY);
7880 aEvent->mDeltaX *= multiplierForDeltaX;
7881 aEvent->mDeltaY *= multiplierForDeltaY;
7882 aEvent->mDeltaZ *= mMultiplierZ[index];
7883
7884 // If the multiplier is 1.0 or -1.0, i.e., it doesn't change the absolute
7885 // value, we should use lineOrPageDelta values which were set by widget.
7886 // Otherwise, we need to compute them from accumulated delta values.
7887 if (!NeedToComputeLineOrPageDelta(aEvent)) {
7888 aEvent->mLineOrPageDeltaX *= static_cast<int32_t>(multiplierForDeltaX);
7889 aEvent->mLineOrPageDeltaY *= static_cast<int32_t>(multiplierForDeltaY);
7890 } else {
7891 aEvent->mLineOrPageDeltaX = 0;
7892 aEvent->mLineOrPageDeltaY = 0;
7893 }
7894
7895 aEvent->mCustomizedByUserPrefs =
7896 ((mMultiplierX[index] != 1.0) || (mMultiplierY[index] != 1.0) ||
7897 (mMultiplierZ[index] != 1.0));
7898}
7899
7900void EventStateManager::WheelPrefs::CancelApplyingUserPrefsFromOverflowDelta(
7901 WidgetWheelEvent* aEvent) {
7902 Index index = GetIndexFor(aEvent);
7903 Init(index);
7904
7905 // XXX If the multiplier pref value is negative, the scroll direction was
7906 // changed and caused to scroll different direction. In such case,
7907 // this method reverts the sign of overflowDelta. Does it make widget
7908 // happy? Although, widget can know the pref applied delta values by
7909 // referrencing the deltaX and deltaY of the event.
7910
7911 double multiplierForDeltaX = 1.0, multiplierForDeltaY = 1.0;
7912 GetMultiplierForDeltaXAndY(aEvent, index, &multiplierForDeltaX,
7913 &multiplierForDeltaY);
7914 if (multiplierForDeltaX) {
7915 aEvent->mOverflowDeltaX /= multiplierForDeltaX;
7916 }
7917 if (multiplierForDeltaY) {
7918 aEvent->mOverflowDeltaY /= multiplierForDeltaY;
7919 }
7920}
7921
7922EventStateManager::WheelPrefs::Action
7923EventStateManager::WheelPrefs::ComputeActionFor(
7924 const WidgetWheelEvent* aEvent) {
7925 Index index = GetIndexFor(aEvent);
7926 Init(index);
7927
7928 bool deltaXPreferred = (Abs(aEvent->mDeltaX) > Abs(aEvent->mDeltaY) &&
7929 Abs(aEvent->mDeltaX) > Abs(aEvent->mDeltaZ));
7930 Action* actions = deltaXPreferred ? mOverriddenActionsX : mActions;
7931 if (actions[index] == ACTION_NONE || actions[index] == ACTION_SCROLL ||
7932 actions[index] == ACTION_HORIZONTALIZED_SCROLL) {
7933 return actions[index];
7934 }
7935
7936 // Momentum events shouldn't run special actions.
7937 if (aEvent->mIsMomentum) {
7938 // Use the default action. Note that user might kill the wheel scrolling.
7939 Init(INDEX_DEFAULT);
7940 if (actions[INDEX_DEFAULT] == ACTION_SCROLL ||
7941 actions[INDEX_DEFAULT] == ACTION_HORIZONTALIZED_SCROLL) {
7942 return actions[INDEX_DEFAULT];
7943 }
7944 return ACTION_NONE;
7945 }
7946
7947 return actions[index];
7948}
7949
7950bool EventStateManager::WheelPrefs::NeedToComputeLineOrPageDelta(
7951 const WidgetWheelEvent* aEvent) {
7952 Index index = GetIndexFor(aEvent);
7953 Init(index);
7954
7955 return (mMultiplierX[index] != 1.0 && mMultiplierX[index] != -1.0) ||
7956 (mMultiplierY[index] != 1.0 && mMultiplierY[index] != -1.0);
7957}
7958
7959void EventStateManager::WheelPrefs::GetUserPrefsForEvent(
7960 const WidgetWheelEvent* aEvent, double* aOutMultiplierX,
7961 double* aOutMultiplierY) {
7962 Index index = GetIndexFor(aEvent);
7963 Init(index);
7964
7965 double multiplierForDeltaX = 1.0, multiplierForDeltaY = 1.0;
7966 GetMultiplierForDeltaXAndY(aEvent, index, &multiplierForDeltaX,
7967 &multiplierForDeltaY);
7968 *aOutMultiplierX = multiplierForDeltaX;
7969 *aOutMultiplierY = multiplierForDeltaY;
7970}
7971
7972// static
7973Maybe<layers::APZWheelAction> EventStateManager::APZWheelActionFor(
7974 const WidgetWheelEvent* aEvent) {
7975 if (aEvent->mMessage != eWheel) {
7976 return Nothing();
7977 }
7978 WheelPrefs::Action action =
7979 WheelPrefs::GetInstance()->ComputeActionFor(aEvent);
7980 switch (action) {
7981 case WheelPrefs::ACTION_SCROLL:
7982 case WheelPrefs::ACTION_HORIZONTALIZED_SCROLL:
7983 return Some(layers::APZWheelAction::Scroll);
7984 case WheelPrefs::ACTION_PINCH_ZOOM:
7985 return Some(layers::APZWheelAction::PinchZoom);
7986 default:
7987 return Nothing();
7988 }
7989}
7990
7991// static
7992WheelDeltaAdjustmentStrategy EventStateManager::GetWheelDeltaAdjustmentStrategy(
7993 const WidgetWheelEvent& aEvent) {
7994 if (aEvent.mMessage != eWheel) {
7995 return WheelDeltaAdjustmentStrategy::eNone;
7996 }
7997 switch (WheelPrefs::GetInstance()->ComputeActionFor(&aEvent)) {
7998 case WheelPrefs::ACTION_SCROLL:
7999 if (StaticPrefs::mousewheel_autodir_enabled() && 0 == aEvent.mDeltaZ) {
8000 if (StaticPrefs::mousewheel_autodir_honourroot()) {
8001 return WheelDeltaAdjustmentStrategy::eAutoDirWithRootHonour;
8002 }
8003 return WheelDeltaAdjustmentStrategy::eAutoDir;
8004 }
8005 return WheelDeltaAdjustmentStrategy::eNone;
8006 case WheelPrefs::ACTION_HORIZONTALIZED_SCROLL:
8007 return WheelDeltaAdjustmentStrategy::eHorizontalize;
8008 default:
8009 break;
8010 }
8011 return WheelDeltaAdjustmentStrategy::eNone;
8012}
8013
8014void EventStateManager::GetUserPrefsForWheelEvent(
8015 const WidgetWheelEvent* aEvent, double* aOutMultiplierX,
8016 double* aOutMultiplierY) {
8017 WheelPrefs::GetInstance()->GetUserPrefsForEvent(aEvent, aOutMultiplierX,
8018 aOutMultiplierY);
8019}
8020
8021bool EventStateManager::WheelPrefs::IsOverOnePageScrollAllowedX(
8022 const WidgetWheelEvent* aEvent) {
8023 if (StaticPrefs::mousewheel_allow_scrolling_more_than_one_page()) {
8024 return true;
8025 }
8026
8027 Index index = GetIndexFor(aEvent);
8028 Init(index);
8029 return Abs(mMultiplierX[index]) >=
8030 MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL;
8031}
8032
8033bool EventStateManager::WheelPrefs::IsOverOnePageScrollAllowedY(
8034 const WidgetWheelEvent* aEvent) {
8035 if (StaticPrefs::mousewheel_allow_scrolling_more_than_one_page()) {
8036 return true;
8037 }
8038
8039 Index index = GetIndexFor(aEvent);
8040 Init(index);
8041 return Abs(mMultiplierY[index]) >=
8042 MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL;
8043}
8044
8045void EventStateManager::UpdateGestureContent(nsIContent* aContent) {
8046 mGestureDownContent = aContent;
8047 mGestureDownFrameOwner = aContent;
8048 mGestureDownTopLevelRemoteTarget = BrowserParent::GetFrom(aContent);
8049}
8050
8051void EventStateManager::NotifyContentWillBeRemovedForGesture(
8052 nsIContent& aContent) {
8053 if (!mGestureDownContent) {
8054 return;
8055 }
8056
8057 if (!nsContentUtils::ContentIsFlattenedTreeDescendantOf(mGestureDownContent,
8058 &aContent)) {
8059 return;
8060 }
8061
8062 UpdateGestureContent(aContent.GetFlattenedTreeParent());
8063}
8064
8065} // namespace mozilla